Servlet/JSP로 사용자 관리 시스템 구현하기 과정 - 5
JSP/Servlet과JSP로 사용자 관리 시스템 구현

Servlet/JSP로 사용자 관리 시스템 구현하기 과정 - 5

반응형

Servlet/JSP로 사용자 관리 시스템 구현하기 과정 

강의 링크 : https://www.slipp.net/wiki/pages/viewpage.action?pageId=25526852

이번 시간부터는 드디어 데이터베이스를 연결해보는 과정이 이루어집니다!

mysql을 이용해서 데이터를 저장시켜보도록 하겠습니다. 우선 mysql을 다운로드 받고 진행해보도록 합시다.

설치가 완료되면, cmd 창을 띄운 후 mysql에 접속해봅시다.



mysql -uroot -p


mysql의 root계정으로 들어가는 명령입니다. 만약 password를 지정했으면 입력하시고, 안했으면 그냥 enter치시면 접속이 될 겁니다.


이제 데이터베이스를 생성하기 위해 아래와 같이 입력해줍니다.


CREATE DATABASE '만들 데이터베이스 이름' DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;


잘 만들어졌는지 show databases;를 입력하면 확인할 수 있습니다.



전 cadi_dev로 생성했는데 잘 저장되어있는 걸 볼 수 있네요!


이제 우리가 사용할 데이터베이스에 접속해야겠죠?


use cadi_dev;


cadi_dev로 들어왔구요. 이 곳에서 테이블을 생성해주면 됩니다.


우리가 프로젝트에서 사용하는 users 테이블을 생성해줍시다. 만들어야할 변수는 총 4개이겠죠? (아이디, 비밀번호, 이름, 이메일)


CREATE TABLE USERS (

userId varchar(12) NOT NULL,

password varchar(12) NOT NULL,

name varchar(20) NOT NULL,

email varchar(50),


PRIMARY KEY (userId)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;


테이블이 잘 만들어졌는지, 상세내용을 보려면 아래와 같이 명령어를 입력해주면 됩니다.


desc users;




입력한 대로 잘 만들어진걸 확인할 수 있습니다!



실제로 적용시키기 전에, 유닛 테스트를 통해 잘 동작하는 지 알아보도록 하겠습니다.


userDAOtest.java로 유닛테스트 파일을 만들고, user패키지 내에서 UserDAO.java를 생성합니다.


DAO란? data access operation으로, 데이터를 접근하는 오퍼레이션을 뜻하는 명칭입니다. 앞으로 많이 나오는 말이니 익숙해집시다.



우선 UserDAO.java에서 mysql에 접속할 Connection 부분 코드입니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
public Connection getConnection() {
        String url = "jdbc:mysql://localhost:3306/cadi_dev";
        String id = "root";
        String pw = "";
        
        try{
            Class.forName("com.mysql.jdbc.Driver");
            return DriverManager.getConnection(url,id,pw);
        } catch (Exception e) {
            System.out.println(e.getMessage());
            return null;
        }
    }
cs


url은 자신에 맞는 데이터베이스 이름으로 변경해주시면 되구요. id와 pw도 자신에 맞게 바꿔주세요. 저는 root 계정이고 비밀번호가 없는 상태라 저렇게 했습니다.


이제 USERS 테이블에 데이터를 넣는 insert 메소드를 만들어야겠죠?


1
2
3
4
5
6
7
8
9
10
public void insert(User user) throws SQLException {
        String sql = "insert into USERS values(?,?,?,?)";
        PreparedStatement pstmt = getConnection().prepareStatement(sql); 
// 쿼리를 전달한 후, 정상적인 쿼리문인지 검증하는 단계
        pstmt.setString(1, user.getUserId());
        pstmt.setString(2, user.getPassword());
        pstmt.setString(3, user.getName());
        pstmt.setString(4, user.getEmail());
        
        pstmt.executeUpdate(); // 쿼리 실행
    }
cs


이제 유닛테스트에서 이를 실행할 코드를 만들어봅시다. 


1
public static User TEST_USER = new User("userId""password""name""abc@naver.com");
cs


기존에 test했던 UserTest에 존재하는 TEST_USER 데이터를 우리가 mysql로 생성한 users 데이터베이스에 입력해보도록 하겠습니다.




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
package net.slipp.user;
 
import static org.junit.Assert.*;
 
import java.sql.Connection;
 
import org.junit.Before;
import org.junit.Test;
 
public class userDAOTest {
 
    private UserDAO userDao;
    
    @Before
    public void setup(){
        userDao = new UserDAO();
    }
    
    @Test
    public void connection() {
        Connection con = userDao.getConnection();
        assertNotNull(con);
    }
    
    @Test
    public void insert() throws Exception {
        userDao.insert(UserTest.TEST_USER);
    }
 
}
cs

@Before은 테스트하기 전에 실행시켜주는 역할을 합니다. 아래 두 Test가 실행되기 전, UserDAO가 있어야하므로 setup 메소드를 만들어 실행해줍시다.

아래 insert 메소드를 통해 UserTest.TEST_USER를 추가하고 있습니다. 실행 후 에러가 없다면, 다시 cmd 창으로 돌아가서 잘 들어갔는지 확인해봅시다. 모든 정보를 확인하려면 select * 을 이용하면 됩니다.


TEST_USER의 데이터가 잘 들어갔네요!! 이제 테스트가 잘 완료되었습니다. 실제로 홈페이지 상에서 회원가입을 하면, 그 데이터가 USERS 테이블에 잘 저장할 수 있도록 만들어봅시다.



작성된 코드는 아래와 같습니다. 기존의 User 클래스에서 login 메소드안에서 userDAO 클래스를 활용해주면 됩니다.




userDAO.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
package net.slipp.user;
 
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.DriverManager;
 
public class UserDAO {
 
    public Connection getConnection() {
        String url = "jdbc:mysql://localhost:3306/cadi_dev";
        String id = "root";
        String pw = "";
        
        try{
            Class.forName("com.mysql.jdbc.Driver");
            return DriverManager.getConnection(url,id,pw);
        } catch (Exception e) {
            System.out.println(e.getMessage());
            return null;
        }
    }
 
    public void addUser(User user) throws SQLException {
        String sql = "insert into USERS values(?,?,?,?)";
        PreparedStatement pstmt = getConnection().prepareStatement(sql); 
// 쿼리를 전달한 후, 정상적인 쿼리문인지 검증하는 단계
        pstmt.setString(1, user.getUserId());
        pstmt.setString(2, user.getPassword());
        pstmt.setString(3, user.getName());
        pstmt.setString(4, user.getEmail());
        
        pstmt.executeUpdate(); // 쿼리 실행
    }
 
    public User findByUserId(String userId) throws SQLException {
        String sql = "select * from USERS where userId = ?";
        PreparedStatement pstmt = getConnection().prepareStatement(sql);
        pstmt.setString(1, userId);
        
        ResultSet rs = pstmt.executeQuery();
        
        if(!rs.next()){
            return null;
        }
        
        
        return new User(
                rs.getString("userId"),
                rs.getString("password"),
                rs.getString("name"),
                rs.getString("email"));
    }
 
}
 
cs



User.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
package net.slipp.user;
 
import java.sql.SQLException;
 
import net.slipp.db.Database;
 
public class User {
    private String userId;
    private String password;
    private String name;
    private String email;
    
    public User(String userId, String password, String name, String email) {
        super();
        this.userId = userId;
        this.password = password;
        this.name = name;
        this.email = email;
    }
    
    public String getUserId() {
        return userId;
    }
    
    public String getPassword() {
        return password;
    }
    
    public String getName() {
        return name;
    }
 
    public String getEmail() {
        return email;
    }
    public boolean matchPassword(String newPassword) {
        
        return this.password.equals(newPassword);
    }
    public static boolean login(String userId, String password) 
        throws UserNotFoundException, PasswordMismatchException {
        UserDAO userDAO = new UserDAO();
        User user = null;
        try {
            user = userDAO.findByUserId(userId);
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        if(user == null){
            throw new UserNotFoundException();
        }
        
        if(!user.matchPassword(password)){
            throw new PasswordMismatchException();
        }
        
        return true;
    }
    
    
 
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((email == null) ? 0 : email.hashCode());
        result = prime * result + ((name == null) ? 0 : name.hashCode());
        result = prime * result + ((password == null) ? 0 : password.hashCode());
        result = prime * result + ((userId == null) ? 0 : userId.hashCode());
        return result;
    }
 
    //alt+s를 통해 generate equals 메소드 실행해주기
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        User other = (User) obj;
        if (email == null) {
            if (other.email != null)
                return false;
        } else if (!email.equals(other.email))
            return false;
        if (name == null) {
            if (other.name != null)
                return false;
        } else if (!name.equals(other.name))
            return false;
        if (password == null) {
            if (other.password != null)
                return false;
        } else if (!password.equals(other.password))
            return false;
        if (userId == null) {
            if (other.userId != null)
                return false;
        } else if (!userId.equals(other.userId))
            return false;
        return true;
    }
 
    @Override
    public String toString() {
        return "User [userId=" + userId + ", password=" + password + 
                ", name=" + name + ", email=" + email + "]";
    }
 
 
}
 
cs




User.java에서


UserDAO userDAO = new UserDAO();
        User user = null;
        try {
            user = userDAO.findByUserId(userId);
        } catch (SQLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }


이 부분을 통해 회원가입 시 User클래스가 생성된 데이터를 이용해 findByUserId 메소드에 의해서 쿼리문이 데이터베이스에 저장될 수 있게 됩니다.


실제로 서버를 실행한 후, 회원가입을 한 뒤에 홈페이지에서 제대로 로그인하는 모습을 볼 수 있으며 mysql에서 select * from users;를 통해 입력된 사용자 데이터를 확인할 수 있습니다. 이제 우리는 서버를 재시작해도 이 데이터 정보로 로그인이 가능하게 됩니다.



(한글로 입력된 정보는 물음표로 나오게 되네요.. 아마 UTF8을 지원하고 있지 않아서 그런 것 같은데 이는 나중에 해결해봐야할 것 같습니다.)




이제 데이터베이스 내에 사용자 정보를 저장할 수 있습니다! 그렇다면, 서버가 켜 있는 동안 임시로 활용했던 database 클래스는 이제 사용하지 않아도 되겠죠? 


삭제하기 전에, 기존에 database.java 클래스를 활용해서 테스트를 진행했던 UserTest의 내용 중 database를 userDAO로 바꿔줍시다.


database.addUser(user);는 이제 사용하지 않을 것이므로, userDAO 클래스를 생성하고 여기에 다시 만든 addUser를 이용해 테스트할 것입니다.



User user = UserTest.TEST_USER;

UserDAO userDAO = new UserDAO();

userDAO.addUser(user);



수정된 UserTest 코드는 아래와 같습니다.


UserTest.java


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
package net.slipp.user;
 
import static org.junit.Assert.*;
 
import org.junit.Test;
 
import net.slipp.db.Database;
 
public class UserTest {
 
    public static User TEST_USER = new User("userId""password""name""abc@naver.com");
    
    @Test
    public void matchPassword() {
        assertTrue(TEST_USER.matchPassword("password"));
    }
    
    @Test
    public void notmatchPassword() {
        assertFalse(TEST_USER.matchPassword("password2"));
    }
    
    @Test
    public void login() throws Exception {
        User user = UserTest.TEST_USER;
        
        UserDAO userDAO = new UserDAO();
        userDAO.addUser(user);
        
        assertTrue(User.login(TEST_USER.getUserId(), TEST_USER.getPassword()));
    }
    
    @Test(expected=UserNotFoundException.class)
    public void loginWhenNotExistedUser() throws Exception {
        User.login("userId2", TEST_USER.getPassword());
    }
    
    @Test(expected=PasswordMismatchException.class)
    public void loginWhenPasswordMismatch() throws Exception {
        User user = UserTest.TEST_USER;
        UserDAO userDAO = new UserDAO();
        userDAO.addUser(user);
        User.login(TEST_USER.getUserId(), "password2");
    }
 
 
}
 
cs




이제 database 클래스가 사용되는 곳은 없어졌습니다. test에 만든 database 패키지와 실제 패키지를 모두 삭제합시다.


삭제하면 몇개의 파일에서 오류가 뜰 텐데요. 이는 우리가 database 클래스를 가져오기 위해 import문을 작성했기 때문입니다. 오류가 나는 파일마다 맨 위에서 우리가 삭제한 database 패키지와 관련된 import문을 삭제해주면 오류가 해결됩니다!



반응형