본문 바로가기
Programming Languages/Java

Chapter 31. DB연동 회원 가입 프로그램

by 더 이프 2023. 1. 26.
728x90

목차

    1. DB연동 회원 가입 프로그램

    ■ Config

    • JDBC를 이용해 DB와 연동
    package usermanagement.config;
    
    import java.sql.*;
    import java.util.Properties;
    import java.util.Vector;
    
    /**
     * Manages a java.sql.Connection pool.
     *
     * @author  Anil Hemrajani
     */
    public class DBConnectionMgr {
    
        private Vector connections = new Vector(10);
        // JDBC 드라이버 로딩
        private String _driver = "com.mysql.cj.jdbc.Driver",
        // jdbc프로토콜을 사용하며 mysql데이터베이스를 사용
        // 127.0.0.1은 ip, 3306은 포트번호이며, 3306은 mysql의 기본 포트번호임
        // chatting은 사용할 데이터베이스명
        _url = "jdbc:mysql://127.0.0.1:3306/chatting", 
        // 사용할 유저id
        _user = "root",
        // 유저 비밀번호
        _password = "root";
        
        private boolean _traceOn = false;
        private boolean initialized = false;
        private int _openConnections = 50;
        private static DBConnectionMgr instance = null;
    
        private DBConnectionMgr() {
        }
    
        /** Use this method to set the maximum number of open connections before
         unused connections are closed.
         */
    
        public static DBConnectionMgr getInstance() {
            if (instance == null) {
                synchronized (DBConnectionMgr.class) {
                    if (instance == null) {
                        instance = new DBConnectionMgr();
                    }
                }
            }
    
            return instance;
        }
    
        public void setOpenConnectionCount(int count) {
            _openConnections = count;
        }
    
        public void setEnableTrace(boolean enable) {
            _traceOn = enable;
        }
    
        /** Returns a Vector of java.sql.Connection objects */
        public Vector getConnectionList() {
            return connections;
        }
    
        /** Opens specified "count" of connections and adds them to the existing pool */
        public synchronized void setInitOpenConnections(int count)
                throws SQLException {
            Connection c = null;
            ConnectionObject co = null;
    
            for (int i = 0; i < count; i++) {
                c = createConnection();
                co = new ConnectionObject(c, false);
    
                connections.addElement(co);
                trace("ConnectionPoolManager: Adding new DB connection to pool (" + connections.size() + ")");
            }
        }
    
        /** Returns a count of open connections */
        public int getConnectionCount() {
            return connections.size();
        }
    
        /** Returns an unused existing or new connection.  */
        public synchronized Connection getConnection()
                throws Exception {
            if (!initialized) {
                Class c = Class.forName(_driver);
                DriverManager.registerDriver((Driver) c.newInstance());
    
                initialized = true;
            }
    
            Connection c = null;
            ConnectionObject co = null;
            boolean badConnection = false;
    
            for (int i = 0; i < connections.size(); i++) {
                co = (ConnectionObject) connections.elementAt(i);
    
                // If connection is not in use, test to ensure it's still valid!
                if (!co.inUse) {
                    try {
                        badConnection = co.connection.isClosed();
                        if (!badConnection)
                            badConnection = (co.connection.getWarnings() != null);
                    } catch (Exception e) {
                        badConnection = true;
                        e.printStackTrace();
                    }
    
                    // Connection is bad, remove from pool
                    if (badConnection) {
                        connections.removeElementAt(i);
                        trace("ConnectionPoolManager: Remove disconnected DB connection #" + i);
                        continue;
                    }
    
                    c = co.connection;
                    co.inUse = true;
    
                    trace("ConnectionPoolManager: Using existing DB connection #" + (i + 1));
                    break;
                }
            }
    
            if (c == null) {
                c = createConnection();
                co = new ConnectionObject(c, true);
                connections.addElement(co);
    
                trace("ConnectionPoolManager: Creating new DB connection #" + connections.size());
            }
    
            return c;
        }
    
        /** Marks a flag in the ConnectionObject to indicate this connection is no longer in use */
        public synchronized void freeConnection(Connection c) {
            if (c == null)
                return;
    
            ConnectionObject co = null;
    
            for (int i = 0; i < connections.size(); i++) {
                co = (ConnectionObject) connections.elementAt(i);
                if (c == co.connection) {
                    co.inUse = false;
                    break;
                }
            }
    
            for (int i = 0; i < connections.size(); i++) {
                co = (ConnectionObject) connections.elementAt(i);
                if ((i + 1) > _openConnections && !co.inUse)
                    removeConnection(co.connection);
            }
        }
    
        public void freeConnection(Connection c, PreparedStatement p, ResultSet r) {
            try {
                if (r != null) r.close();
                if (p != null) p.close();
                freeConnection(c);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    
        public void freeConnection(Connection c, Statement s, ResultSet r) {
            try {
                if (r != null) r.close();
                if (s != null) s.close();
                freeConnection(c);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    
        public void freeConnection(Connection c, PreparedStatement p) {
            try {
                if (p != null) p.close();
                freeConnection(c);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    
        public void freeConnection(Connection c, Statement s) {
            try {
                if (s != null) s.close();
                freeConnection(c);
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    
        /** Marks a flag in the ConnectionObject to indicate this connection is no longer in use */
        public synchronized void removeConnection(Connection c) {
            if (c == null)
                return;
    
            ConnectionObject co = null;
            for (int i = 0; i < connections.size(); i++) {
                co = (ConnectionObject) connections.elementAt(i);
                if (c == co.connection) {
                    try {
                        c.close();
                        connections.removeElementAt(i);
                        trace("Removed " + c.toString());
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
    
                    break;
                }
            }
        }
    
        private Connection createConnection()
                throws SQLException {
            Connection con = null;
    
            try {
                if (_user == null)
                    _user = "";
                if (_password == null)
                    _password = "";
    
                Properties props = new Properties();
                props.put("user", _user);
                props.put("password", _password);
    
                con = DriverManager.getConnection(_url, props);
            } catch (Throwable t) {
                throw new SQLException(t.getMessage());
            }
    
            return con;
        }
    
        /** Closes all connections and clears out the connection pool */
        public void releaseFreeConnections() {
            trace("ConnectionPoolManager.releaseFreeConnections()");
    
            Connection c = null;
            ConnectionObject co = null;
    
            for (int i = 0; i < connections.size(); i++) {
                co = (ConnectionObject) connections.elementAt(i);
                if (!co.inUse)
                    removeConnection(co.connection);
            }
        }
    
        /** Closes all connections and clears out the connection pool */
        public void finalize() {
            trace("ConnectionPoolManager.finalize()");
    
            Connection c = null;
            ConnectionObject co = null;
    
            for (int i = 0; i < connections.size(); i++) {
                co = (ConnectionObject) connections.elementAt(i);
                try {
                    co.connection.close();
                } catch (Exception e) {
                    e.printStackTrace();
                }
    
                co = null;
            }
    
            connections.removeAllElements();
        }
    
        private void trace(String s) {
            if (_traceOn)
                System.err.println(s);
        }
    
    }
    
    class ConnectionObject {
        public java.sql.Connection connection = null;
        public boolean inUse = false;
    
        public ConnectionObject(Connection c, boolean useFlag) {
            connection = c;
            inUse = useFlag;
        }
    }

    Entity

    • DB의 Column들을 선언
    package usermanagement.entity;
    
    import java.util.List;
    
    import lombok.Builder;
    import lombok.Data;
    
    @Builder
    @Data
    public class User {
    	// 데이터베이스의 user_mst테이블의 column
    	private int userId;
    	private String username;
    	private String password;
    	private String name;
    	private String email;
    	// join 후 생기는 행에 여러개의 roleId가 있을 수 있음
    	private List<RoleDtl> roleDtls;
    }
    
    package usermanagement.entity;
    
    import lombok.Builder;
    import lombok.Data;
    
    @Builder
    @Data
    public class RoleDtl {
    	// role_dtl테이블의 column
    	private int roleDtlId;
    	private int roleId;
    	private int userId;
    	// role_mst테이블의 column중 roleId가 연결되어 있어서 선언해줌
    	private RoleMst roleMst;
    }
    
    package usermanagement.entity;
    
    import lombok.Builder;
    import lombok.Data;
    
    @Builder
    @Data
    public class RoleMst {
    	// role_mst테이블의 column
    	private int roleId;
    	private String roleName;
    }

    Repository

    • Insert를 통해 회원가입 시 데이터를 DB에 저장
    package usermanagement.repository;
    
    import java.sql.Connection;
    import java.sql.PreparedStatement;
    import java.sql.ResultSet;
    import java.sql.Statement;
    import java.util.ArrayList;
    import java.util.List;
    
    import j23_database.DBConnectionMgr;
    import usermanagement.entity.RoleDtl;
    import usermanagement.entity.RoleMst;
    import usermanagement.entity.User;
    
    /*
     * UserDao(Data access object)
     */
    public class UserRepository {
    	// 싱글톤 패턴으로 한 번 생성 시 UserRepository를 어디서든 사용 가능
    	private static UserRepository instance;
    
    	public static UserRepository getInstance() {
    		if (instance == null) {
    			instance = new UserRepository();
    		}
    		return instance;
    	}
    	// pool은 튜브 관리소와 같은 역할로 튜브가 없으면 튜브가 반환될 때까지 막음
    	private DBConnectionMgr pool;
    
    	private UserRepository() {
    		pool = DBConnectionMgr.getInstance();
    	}
        // return을 int로 함
    	public int saveUser(User user) {
    		int successCount = 0;
    
    		Connection con = null;
    		PreparedStatement pstmt = null;
    		ResultSet rs = null;
    
    		try {
    			// 데이터베이스와 연결
    			con = pool.getConnection();
    			// 쿼리문, ?에는 값을 넣을 수 있음
    			String sql = "insert into user_mst values(0, ?, ?, ?, ?)";
    			// prepareStatement는 쿼리문을 작성하고 자동생성되는 key값을 가져옴
    			pstmt = con.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
    			pstmt.setString(1, user.getUsername());
    			pstmt.setString(2, user.getPassword());
    			pstmt.setString(3, user.getName());
    			pstmt.setString(4, user.getEmail());
    
    			successCount = pstmt.executeUpdate();
    
    			// id를 활용할 경우 키값을 넣어줌
    			rs = pstmt.getGeneratedKeys();
    			if (rs.next()) {
    				user.setUserId(rs.getInt(1));
    			}
    
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			pool.freeConnection(con, pstmt, rs);
    		}
    
    		return successCount;
    	}
    	
    	public int saveRoleDtl(RoleDtl roleDtl) {
    		int successCount = 0;
    		
    		Connection con = null;
    		PreparedStatement pstmt = null;
    
    		try {
    			con = pool.getConnection();
    			String sql = "insert into role_dtl values(0, ?, ?)";
    			pstmt = con.prepareStatement(sql);
    			pstmt.setInt(1, roleDtl.getRoleId());
    			pstmt.setInt(2, roleDtl.getUserId());
    
    			successCount = pstmt.executeUpdate();
    
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			pool.freeConnection(con, pstmt);
    		}
    		
    		return successCount;
    	}
    	
    	public User findUserByUsername(String username) {
    		User user = null;
    		
    		Connection con = null;
    		PreparedStatement pstmt = null;
    		ResultSet rs = null;
    		
    		try {
    			con = pool.getConnection();
    			String sql = "select\r\n"
    					+ "	   um.user_id,\r\n"
    					+ "    um.username,\r\n"
    					+ "    um.password,\r\n"
    					+ "    um.name,\r\n"
    					+ "    um.email,\r\n"
    					+ "    rd.role_dtl_id,\r\n"
    					+ "    rd.role_id,\r\n"
    					+ "    rd.user_id,\r\n"
    					+ "    rm.role_id,\r\n"
    					+ "    rm.role_name\r\n"
    					+ "from\r\n"
    					+ "	   user_mst um\r\n"
    					+ "    left outer join role_dtl rd on(rd.user_id = um.user_id)\r\n"
    					+ "    left outer join role_mst rm on(rm.role_id = rd.role_id)\r\n"
    					+ "where\r\n"
    					+ "	   um.username = ?";
    			pstmt = con.prepareStatement(sql);
    			pstmt.setString(1, username);
    			
    			rs = pstmt.executeQuery();
    			
    			List<RoleDtl> roleDtls = new ArrayList<>();
    			
    			int i = 0;
    			
    			while(rs.next()) {
    				if(i == 0) {
    					user = User.builder()
    							.userId(rs.getInt(1))
    							.username(rs.getString(2))
    							.password(rs.getString(3))
    							.name(rs.getString(4))
    							.email(rs.getString(5))
    							.build();
    				}
    				RoleMst roleMst = RoleMst.builder()
    						.roleId(rs.getInt(9))
    						.roleName(rs.getString(10))
    						.build();
    				
    				RoleDtl roleDtl = RoleDtl.builder()
    						.roleDtlId(rs.getInt(6))
    						.roleId(rs.getInt(7))
    						.userId(rs.getInt(8))
    						.roleMst(roleMst)
    						.build();
    
    					roleDtls.add(roleDtl);
    				
    				i++;
    			}
    			
    			if(user != null) {
    			user.setRoleDtls(roleDtls);
    			}
    			
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			pool.freeConnection(con, pstmt, rs);
    		}
    		
    		return user;
    	}
    	
    	public User findUserByEmail(String email) {
    		User user = null;
    		
    		Connection con = null;
    		PreparedStatement pstmt = null;
    		ResultSet rs = null;
    		
    		try {
    			con = pool.getConnection();
    			String sql = "select\r\n"
    					+ "	   um.user_id,\r\n"
    					+ "    um.username,\r\n"
    					+ "    um.password,\r\n"
    					+ "    um.name,\r\n"
    					+ "    um.email,\r\n"
    					+ "    rd.role_dtl_id,\r\n"
    					+ "    rd.role_id,\r\n"
    					+ "    rd.user_id,\r\n"
    					+ "    rm.role_id,\r\n"
    					+ "    rm.role_name\r\n"
    					+ "from\r\n"
    					+ "	   user_mst um\r\n"
    					+ "    left outer join role_dtl rd on(rd.user_id = um.user_id)\r\n"
    					+ "    left outer join role_mst rm on(rm.role_id = rd.role_id)\r\n"
    					+ "where\r\n"
    					+ "	   um.email = ?";
    			pstmt = con.prepareStatement(sql);
    			pstmt.setString(1, email);
    			
    			rs = pstmt.executeQuery();
    			
    			List<RoleDtl> roleDtls = new ArrayList<>();
    			
    			int i = 0;
    			
    			while(rs.next()) {
    				if(i == 0) {
    					user = User.builder()
    							.userId(rs.getInt(1))
    							.username(rs.getString(2))
    							.password(rs.getString(3))
    							.name(rs.getString(4))
    							.email(rs.getString(5))
    							.build();
    				}
    				RoleMst roleMst = RoleMst.builder()
    						.roleId(rs.getInt(9))
    						.roleName(rs.getString(10))
    						.build();
    				
    				RoleDtl roleDtl = RoleDtl.builder()
    						.roleDtlId(rs.getInt(6))
    						.roleId(rs.getInt(7))
    						.userId(rs.getInt(8))
    						.roleMst(roleMst)
    						.build();
    				
    					roleDtls.add(roleDtl);
    				
    				i++;
    			}
    			
    			if(user != null) {
    			user.setRoleDtls(roleDtls);
    			}
    			
    		} catch (Exception e) {
    			e.printStackTrace();
    		} finally {
    			pool.freeConnection(con, pstmt, rs);
    		}
    		
    		return user;
    	}
    }

    Service

    package usermanagement.service;
    
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Map.Entry;
    
    import org.mindrot.jbcrypt.BCrypt;
    
    import com.google.gson.Gson;
    import com.google.gson.GsonBuilder;
    
    import usermanagement.entity.RoleDtl;
    import usermanagement.entity.User;
    import usermanagement.repository.UserRepository;
    
    public class UserService {
    
    	private UserRepository userRepository;
    	private Gson gson;
    
    	private static UserService instance;
    
    	public static UserService getInstance() {
    		if (instance == null) {
    			instance = new UserService();
    		}
    		return instance;
    	}
    
    	private UserService() {
    		userRepository = UserRepository.getInstance();
    		gson = new GsonBuilder().setPrettyPrinting().create();
    	}
    
    	public Map<String, String> register(String userJson) {
    		// reponse : 응답
    		Map<String, String> response = new HashMap<>();
    		// 반복 작업을 하기 위해서 Map형태로 변환
    		Map<String, String> userMap = gson.fromJson(userJson, Map.class);
    		for (Entry<String, String> userEntry : userMap.entrySet()) {
    			// isBlank는 스페이스를 공백으로 봄
    			if (userEntry.getValue().isBlank()) {
    				response.put("error", userEntry.getKey() + "은(는) 공백일 수 없습니다.");
    				return response;
    			}
    		}
    
    		User user = gson.fromJson(userJson, User.class);
    		System.out.println("서비스에 넘어옴! User 객체로 변환");
    		System.out.println(user);
    
    		if (duplicatedUsername(user.getUsername())) {
    			response.put("error", "이미 사용중인 사용자 이름입니다.");
    			return response;
    		}
    
    		if (duplicatedEmail(user.getEmail())) {
    			response.put("error", "이미 사용중인 이메일입니다.");
    			return response;
    		}
    
    		// password를 암호화한 것을 pw에 대입
    //		String pw = BCrypt.hashpw("1234", BCrypt.gensalt());
    //		System.out.println(pw);
    //		System.out.println(BCrypt.checkpw("1234", pw));
    
    		user.setPassword(BCrypt.hashpw(user.getPassword(), BCrypt.gensalt()));
    		System.out.println("암호화 후");
    		System.out.println(user);
    
    		userRepository.saveUser(user);
    		
    		RoleDtl roleDtl = RoleDtl.builder()
    				.roleId(3)
    				.userId(user.getUserId())
    				.build();
    		
    		userRepository.saveRoleDtl(roleDtl);
    
    		response.put("ok", "회원가입 성공.");
    
    		return response;
    	}
    
    	private boolean duplicatedUsername(String username) {
    		return userRepository.findUserByUsername(username) != null;
    	}
    
    	private boolean duplicatedEmail(String email) {
    		return userRepository.findUserByEmail(email) != null;
    	}
    
    	public Map<String, String> authorize(String loginUserJson) {
    		Map<String, String> loginUser = gson.fromJson(loginUserJson, Map.class);
    
    		Map<String, String> response = new HashMap<>();
    
    		for (Entry<String, String> entry : loginUser.entrySet()) {
    			if (entry.getValue().isBlank()) {
    				response.put("error", entry.getKey() + "은(는) 공백일 수 없습니다.");
    				return response;
    			}
    		}
    
    		String usernameAndEmail = loginUser.get("usernameAndEmail");
    
    		User user = userRepository.findUserByUsername(usernameAndEmail);
    		if (user == null) {
    			user = userRepository.findUserByEmail(usernameAndEmail);
    			if (user == null) {
    				response.put("error", "사용자 정보를 확인해주세요");
    			}
    		}
    
    		if (!BCrypt.checkpw(loginUser.get("password"), user.getPassword())) {
    			response.put("error", "사용자 정보를 확인해주세요");
    		}
    
    		response.put("ok", user.getName() + "님 환영합니다.");
    		return response;
    	}
    }

    Frame

    • Frame 실행 시 Login화면이 출력되며, Sign up을 클릭하면 Register 화면으로 전환
    • Register에서 회원가입 시 Username, Password, name, email의 정보가 DB에 저장됨
    package usermanagement.frame;
    
    import java.awt.CardLayout;
    import java.awt.Color;
    import java.awt.EventQueue;
    import java.awt.Font;
    import java.awt.event.MouseAdapter;
    import java.awt.event.MouseEvent;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Map;
    
    import javax.swing.JButton;
    import javax.swing.JFrame;
    import javax.swing.JLabel;
    import javax.swing.JOptionPane;
    import javax.swing.JPanel;
    import javax.swing.JPasswordField;
    import javax.swing.JTextField;
    import javax.swing.SwingConstants;
    
    import com.google.gson.JsonObject;
    
    import usermanagement.service.UserService;
    
    public class UserManagementFrame extends JFrame {
    
    	private List<JTextField> loginFields;
    	private List<JTextField> registerFields;
    
    	private CardLayout mainCard;
    	private JPanel mainPanel;
    	private JTextField usernameField;
    	private JPasswordField passwordField;
    	private JTextField registerUsernameField;
    	private JPasswordField registerPasswordField;
    	private JTextField registerNameField;
    	private JTextField registerEmailField;
    
    	public static void main(String[] args) {
    		EventQueue.invokeLater(new Runnable() {
    			public void run() {
    				try {
    					UserManagementFrame frame = new UserManagementFrame();
    					frame.setVisible(true);
    				} catch (Exception e) {
    					e.printStackTrace();
    				}
    			}
    		});
    	}
    
    	public UserManagementFrame() {
    		loginFields = new ArrayList<>();
    		registerFields = new ArrayList<>();
    
    		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    		setBounds(100, 100, 400, 500);
    		mainPanel = new JPanel();
    		mainPanel.setLocation(0, 0);
    		mainPanel.setBackground(new Color(255, 255, 255));
    		mainPanel.setBorder(null);
    
    		setContentPane(mainPanel);
    
    		mainCard = new CardLayout();
    		mainPanel.setLayout(mainCard);
    
    		JPanel loginPanel = new JPanel();
    		loginPanel.setBackground(new Color(255, 255, 255));
    
    		mainPanel.add(loginPanel, "loginPanel");
    		loginPanel.setLayout(null);
    
    		JLabel LogoText = new JLabel("UserManagement");
    		LogoText.setFont(new Font("Arial", Font.BOLD, 20));
    		LogoText.setHorizontalAlignment(SwingConstants.CENTER);
    		LogoText.setBounds(75, 50, 250, 50);
    		loginPanel.add(LogoText);
    
    		JLabel LoginText = new JLabel("Login");
    		LoginText.setFont(new Font("Arial", Font.PLAIN, 30));
    		LoginText.setHorizontalAlignment(SwingConstants.CENTER);
    		LoginText.setBounds(115, 100, 170, 50);
    		loginPanel.add(LoginText);
    
    		usernameField = new JTextField();
    		usernameField.setFont(new Font("Arial", Font.PLAIN, 12));
    		usernameField.setBounds(75, 220, 250, 30);
    		loginPanel.add(usernameField);
    		usernameField.setColumns(10);
    
    		passwordField = new JPasswordField();
    		passwordField.setFont(new Font("Arial", Font.PLAIN, 12));
    		passwordField.setBounds(75, 280, 250, 30);
    		loginPanel.add(passwordField);
    
    		JLabel usernameLable = new JLabel("Username or email");
    		usernameLable.setFont(new Font("Arial", Font.PLAIN, 12));
    		usernameLable.setBounds(75, 200, 120, 15);
    		loginPanel.add(usernameLable);
    
    		JLabel passwordLable = new JLabel("Password");
    		passwordLable.setFont(new Font("Arial", Font.PLAIN, 12));
    		passwordLable.setBounds(75, 260, 60, 15);
    		loginPanel.add(passwordLable);
    
    		JButton loginButton = new JButton("Login");
    
    		loginButton.addMouseListener(new MouseAdapter() {
                // 인터페이스는 모두 구현해야함
                // MouseAdapter내에 인터페이스를 모두 구현해놓음
                // 사용하고 싶은 메소드만 오버라이드하여 사용가능
    			@Override
    			public void mouseClicked(MouseEvent e) {
    				JsonObject loginUser = new JsonObject();
    				loginUser.addProperty("usernameAndEmail", usernameField.getText());
    				loginUser.addProperty("password", passwordField.getText());
    
    				UserService userService = UserService.getInstance();
    
    				Map<String, String> response = userService.authorize(loginUser.toString());
    
    				if (response.containsKey("error")) {
    					JOptionPane.showMessageDialog(null, response.get("error"), "error", JOptionPane.ERROR_MESSAGE);
    					return;
    				}
    				
    				JOptionPane.showMessageDialog(null, response.get("ok"), "ok", JOptionPane.INFORMATION_MESSAGE);
    				
    			}
    		});
    
    		loginButton.setBackground(new Color(192, 192, 192));
    		loginButton.setFont(new Font("Arial", Font.PLAIN, 18));
    		loginButton.setBounds(75, 320, 250, 30);
    		loginPanel.add(loginButton);
    
    		JLabel signupDescription = new JLabel("Don't have an account?");
    		signupDescription.setFont(new Font("Arial", Font.PLAIN, 12));
    		signupDescription.setBounds(75, 360, 130, 15);
    		loginPanel.add(signupDescription);
    
    		JLabel signupLink = new JLabel("Sign up");
    		signupLink.addMouseListener(new MouseAdapter() {
    			@Override
    			public void mouseClicked(MouseEvent e) {
    				// mainPanel에서 registerPanel 키 값을 가진 화면을 보여줌
    				mainCard.show(mainPanel, "registerPanel");
    				// loginFields를 공백으로 만듬
    				clearFields(loginFields);
    			}
    		});
    		signupLink.setForeground(new Color(0, 128, 255));
    		signupLink.setFont(new Font("Arial", Font.PLAIN, 12));
    		signupLink.setBounds(210, 360, 50, 15);
    		loginPanel.add(signupLink);
    
    		JLabel forgotPasswordLink = new JLabel("Forgot your password?");
    		forgotPasswordLink.setFont(new Font("Arial", Font.PLAIN, 12));
    		forgotPasswordLink.setForeground(new Color(0, 128, 255));
    		forgotPasswordLink.setBounds(75, 380, 130, 15);
    		loginPanel.add(forgotPasswordLink);
    
    		JPanel registerPanel = new JPanel();
    		registerPanel.setBackground(new Color(255, 255, 255));
    		mainPanel.add(registerPanel, "registerPanel");
    		registerPanel.setLayout(null);
    
    		JLabel signinLink = new JLabel("Sign in");
    		signinLink.setForeground(new Color(0, 128, 255));
    		signinLink.setFont(new Font("Arial", Font.PLAIN, 12));
    		signinLink.addMouseListener(new MouseAdapter() {
    			@Override
    			public void mouseClicked(MouseEvent e) {
    				// mainPanel에서 loginPanel 키 값을 가진 화면을 보여줌
    				mainCard.show(mainPanel, "loginPanel");
    				// registerFields를 공백으로 만듬
    				clearFields(registerFields);
    			}
    		});
    		signinLink.setHorizontalAlignment(SwingConstants.CENTER);
    		signinLink.setBounds(175, 440, 50, 15);
    		registerPanel.add(signinLink);
    
    		JLabel registerLogoText = new JLabel("UserManagement");
    		registerLogoText.setHorizontalAlignment(SwingConstants.CENTER);
    		registerLogoText.setFont(new Font("Arial", Font.BOLD, 20));
    		registerLogoText.setBounds(75, 50, 250, 50);
    		registerPanel.add(registerLogoText);
    
    		JLabel RegisterText = new JLabel("Register");
    		RegisterText.setHorizontalAlignment(SwingConstants.CENTER);
    		RegisterText.setFont(new Font("Arial", Font.PLAIN, 30));
    		RegisterText.setBounds(115, 100, 170, 50);
    		registerPanel.add(RegisterText);
    
    		registerUsernameField = new JTextField();
    		registerUsernameField.setFont(new Font("Arial", Font.PLAIN, 12));
    		registerUsernameField.setColumns(10);
    		registerUsernameField.setBounds(75, 170, 250, 30);
    		registerPanel.add(registerUsernameField);
    
    		registerPasswordField = new JPasswordField();
    		registerPasswordField.setFont(new Font("Arial", Font.PLAIN, 12));
    		registerPasswordField.setBounds(75, 230, 250, 30);
    		registerPanel.add(registerPasswordField);
    
    		JLabel registerusernameLable = new JLabel("Username");
    		registerusernameLable.setFont(new Font("Arial", Font.PLAIN, 12));
    		registerusernameLable.setBounds(75, 150, 120, 15);
    		registerPanel.add(registerusernameLable);
    
    		JLabel registerpasswordLable = new JLabel("Password");
    		registerpasswordLable.setFont(new Font("Arial", Font.PLAIN, 12));
    		registerpasswordLable.setBounds(75, 210, 60, 15);
    		registerPanel.add(registerpasswordLable);
    
    		registerNameField = new JTextField();
    		registerNameField.setFont(new Font("HY견고딕", Font.PLAIN, 12));
    		registerNameField.setColumns(10);
    		registerNameField.setBounds(75, 290, 250, 30);
    		registerPanel.add(registerNameField);
    
    		JLabel registernameLable = new JLabel("name");
    		registernameLable.setFont(new Font("Arial", Font.PLAIN, 12));
    		registernameLable.setBounds(75, 270, 120, 15);
    		registerPanel.add(registernameLable);
    
    		registerEmailField = new JTextField();
    		registerEmailField.setFont(new Font("Arial", Font.PLAIN, 12));
    		registerEmailField.setColumns(10);
    		registerEmailField.setBounds(75, 350, 250, 30);
    		registerPanel.add(registerEmailField);
    
    		JLabel registeremailLable = new JLabel("email");
    		registeremailLable.setFont(new Font("Arial", Font.PLAIN, 12));
    		registeremailLable.setBounds(75, 330, 120, 15);
    		registerPanel.add(registeremailLable);
    
    		JButton registerButton = new JButton("Register");
    		registerButton.addMouseListener(new MouseAdapter() {
    			@Override
    			public void mouseClicked(MouseEvent e) {
    				JsonObject userJson = new JsonObject();
    				userJson.addProperty("username", registerUsernameField.getText());
    				userJson.addProperty("password", registerPasswordField.getText());
    				userJson.addProperty("name", registerNameField.getText());
    				userJson.addProperty("email", registerEmailField.getText());
    
    				System.out.println(userJson.toString());
    
    				UserService userService = UserService.getInstance();
    
    				Map<String, String> response = userService.register(userJson.toString());
    
    				if (response.containsKey("error")) {
    					JOptionPane.showMessageDialog(null, response.get("error"), "error", JOptionPane.ERROR_MESSAGE);
    					return;
    				}
    				JOptionPane.showMessageDialog(null, response.get("ok"), "ok", JOptionPane.INFORMATION_MESSAGE);
    				mainCard.show(mainPanel, "loginPanel");
    				// registerFields를 공백으로 만듬
    				clearFields(registerFields);
    			}
    		});
    		registerButton.setFont(new Font("Arial", Font.PLAIN, 18));
    		registerButton.setBackground(Color.LIGHT_GRAY);
    		registerButton.setBounds(75, 400, 250, 30);
    		registerPanel.add(registerButton);
    
    		loginFields.add(usernameField);
    		loginFields.add(passwordField);
    
    		registerFields.add(registerUsernameField);
    		registerFields.add(registerPasswordField);
    		registerFields.add(registerNameField);
    		registerFields.add(registerEmailField);
    	}
    
    	private void clearFields(List<JTextField> textFields) {
    		for (JTextField field : textFields) {
    			// 공백이라도 있으면 setText("") 실행
    			if (field.getText().isEmpty()) {
    				continue;
    			}
    			field.setText("");
    		}
    	}
    }
    • 로그인 화면과 회원가입 화면