개인 프로젝트 주제
Swing을 이용하여 반려동물 용품 쇼핑몰 DB 접근 프로그램을 GUI로 구현하기
프로젝트 기간
시간이 날 때마다 비정기적으로 진행할 예정
깃허브 주소
https://github.com/seoyounglee0105/ShopDB_GUI_Project
개발 계획
1. 로그인 프레임
- 회원가입 버튼
- 비밀번호 찾기 버튼
2. 회원가입 프레임
- 아이디 중복 확인 기능
- 항목 형식 힌트 (글자 수 제한 등)
- member 테이블에 회원 정보를 INSERT하는 기능
- 필수 값 중 입력되지 않은 값이 있으면 회원가입 거부
3. 비밀번호 찾기 프레임
4. 마이페이지 프레임
- 정보 수정 버튼 (비밀번호를 다시 입력받아서 본인 확인)
- 주문 내역
- 쿠폰함
- 장바구니
5. 쇼핑몰 홈 프레임
- 로그아웃 버튼 → 로그인 프레임을 다시 띄움
- 마이페이지 버튼
- 카테고리별로 상품을 출력하는 기능
6. 상품 상세 페이지 프레임
- 장바구니에 넣는 기능
1일차
- 회원(Member) 테이블 생성
- 회원가입 기능 구현
- 로그인 기능 구현
회원 테이블 생성
CREATE TABLE member (
id VARCHAR(15) PRIMARY KEY, -- 아이디
password VARCHAR(20) NOT NULL, -- 비밀번호
member_grade VARCHAR(10) NOT NULL DEFAULT '브론즈', -- 회원 등급 (외래키)
name VARCHAR(10) NOT NULL, -- 이름
phone_number VARCHAR(13) NOT NULL, -- 전화번호
address VARCHAR(100) NOT NULL, -- 주소
FOREIGN KEY (member_grade) REFERENCES grade(name)
);
- 처음 가입한 회원들은 자동으로 '브론즈' 등급을 할당받음
회원 등급 테이블 생성 및 데이터 삽입
CREATE TABLE grade (
name VARCHAR(10) PRIMARY KEY
);
INSERT INTO grade
VALUES
('플래티넘'),
('골드'),
('실버'),
('브론즈');
DBHelper 클래스 설계
public class DBHelper {
private static final String DB_HOST = "localhost";
private static final String DB_PORT = "3306";
private static final String DB_DATABASE_NAME = "my_shopdb";
private static final String DB_CHARSET = "UTF-8";
private static final String DB_USER = "root";
private static final String DB_PASSWORD = "1234";
private Connection connection;
// 싱글톤 패턴 객체 만들기
// 1.
private static DBHelper dbHelper;
// 2. private 생성자
private DBHelper() {
}
// 3.
public static DBHelper getInstance() {
if (dbHelper == null) {
dbHelper = new DBHelper();
}
return dbHelper;
}
public Connection getConnection() {
if (connection == null) {
String urlFormat = "jdbc:mysql://%s:%s/%s?serverTimezone=Asia/Seoul&characterEncoding=%s";
String url = String.format(urlFormat, DB_HOST, DB_PORT, DB_DATABASE_NAME, DB_CHARSET);
// 동적 로딩 (리플렉션 기법)
try {
Class.forName("com.mysql.cj.jdbc.Driver");
connection = DriverManager.getConnection(url, DB_USER, DB_PASSWORD);
System.out.println("Connection Success");
} catch (Exception e) {
e.printStackTrace();
}
}
return connection;
} // end of getConnection
public void closeConnection() {
if (connection != null) {
try {
connection.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
}
}
MemberDTO 클래스 설계
public class MemberDTO {
// member 테이블의 컬럼 값을 받을 멤버 변수
private String id;
private String password;
private String member_grade;
private String name;
private String phone_number;
private String address;
// 생성자
public MemberDTO(String id, String password, String member_grade, String name,
String phone_number, String address, String email) {
this.id = id;
this.password = password;
this.member_grade = member_grade;
this.name = name;
this.phone_number = phone_number;
this.address = address;
}
// get, set 메서드
}
MemberDAO - 회원 가입 기능
// 회원 가입 기능
@Override
public int memberSignUp(String id, String password, String name, String phoneNumber, String address) {
result = 0; // 초기화
String sql = " INSERT INTO member(id, password, name, phone_number, address) "
+ " VALUES (?, ?, ?, ?, ?) ";
try {
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, id);
pstmt.setString(2, password);
pstmt.setString(3, name);
pstmt.setString(4, phoneNumber);
pstmt.setString(5, address);
result = pstmt.executeUpdate();
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
pstmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return result;
}
// 아이디 중복 확인 기능
@Override
public int memberIdCheck(String id) {
result = 0; // 초기화
String sql = " SELECT * FROM member WHERE id = ? ";
try {
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, id);
rs = pstmt.executeQuery();
// 행이 존재한다면 while문으로 들어감
while (rs.next()) {
result = 1; // 아이디 중복
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
rs.close();
pstmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return result;
}
MemberDAO - 로그인 기능
// 로그인 기능
@Override
public int memberLogin(String id, String password) {
result = 0; // 초기화
String sql = " SELECT * FROM member " + " WHERE id = ? AND password = ? ";
try {
pstmt = conn.prepareStatement(sql);
pstmt.setString(1, id);
pstmt.setString(2, password);
rs = pstmt.executeQuery();
// 행이 존재한다면 while문으로 들어감
while (rs.next()) {
result = 1;
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
try {
rs.close();
pstmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
return result;
}
LoginFrame (Main)
public class LoginFrame extends JFrame implements ActionListener {
private JPanel panel1;
private JLabel idLabel; // 아이디
private JTextField idTextField; // 아이디 입력창
private JLabel pwLabel; // 비밀번호
private JPasswordField pwPasswordField; // 비밀번호 입력창
private JButton loginButton; // 로그인 버튼
private JPanel panel2;
private JButton signUpButton; // 회원가입 버튼
private JButton pwFindButton; // 비밀번호 찾기 버튼
private Color backgroundColor;
private int isSuccess = 0;
public LoginFrame() {
initData();
setInitLayout();
addEventListener();
}
private void initData() {
setTitle("로그인");
setSize(400, 300);
panel1 = new JPanel();
idLabel = new JLabel(" 아이디");
idTextField = new JTextField(10);
pwLabel = new JLabel("비밀번호");
pwPasswordField = new JPasswordField(10);
loginButton = new JButton("로그인");
panel2 = new JPanel();
signUpButton = new JButton("회원 가입");
pwFindButton = new JButton("비밀번호 찾기");
}
private void setInitLayout() {
setLayout(null);
setResizable(false);
setLocationRelativeTo(null);
Color backgroundColor = new Color(200, 235, 226);
getContentPane().setBackground(backgroundColor);
// panel1
panel1.setSize(200, 55);
panel1.setLocation(40, 70);
panel1.setBackground(backgroundColor);
add(panel1);
panel1.add(idLabel);
panel1.add(idTextField);
panel1.add(pwLabel);
panel1.add(pwPasswordField);
loginButton.setSize(80, 40);
loginButton.setLocation(240, 77);
add(loginButton);
// panel2
panel2.setSize(400, 100);
panel2.setLocation(0, 180);
panel2.setBackground(backgroundColor);
add(panel2);
panel2.add(signUpButton);
panel2.add(pwFindButton);
setVisible(true);
}
private void addEventListener() {
signUpButton.addActionListener(this);
loginButton.addActionListener(this);
}
@Override
public void actionPerformed(ActionEvent e) {
JButton targetButton = (JButton) e.getSource();
if (targetButton == signUpButton) {
new SignUpFrame();
} else if (targetButton == loginButton) {
String id = idTextField.getText();
char[] pwChar = pwPasswordField.getPassword();
String pw = new String(pwChar);
MemberDAO memberDAO = new MemberDAO();
isSuccess = memberDAO.memberLogin(id, pw);
if (isSuccess == 1) {
System.out.println("로그인에 성공했습니다!");
// 확인을 누르면 로그인 프레임 종료
JOptionPane.showMessageDialog(null, "로그인 완료", "로그인 성공", JOptionPane.PLAIN_MESSAGE);
System.exit(0);
} else {
System.out.println("로그인에 실패했습니다.");
JOptionPane.showMessageDialog(null, "아이디나 비밀번호를 확인해주세요.", "로그인 실패", JOptionPane.PLAIN_MESSAGE);
}
}
}
public static void main(String[] args) {
new LoginFrame();
}
}
SignUpFrame
public class SignUpFrame extends JFrame implements ActionListener, MouseListener {
private JPanel parentPanel1;
private JPanel panel1;
private JLabel idLabel; // 아이디
private JTextField idTextField; // 아이디 입력창
private JButton idCheckButton; // 중복확인 버튼
private JPanel panel2;
private JLabel pwLabel; // 비밀번호
private JPasswordField pwPasswordField; // 비밀번호 입력창
private JPanel panel3;
private JLabel nameLabel; // 이름
private JTextField nameTextField; // 이름 입력창
private JPanel panel4;
private JLabel phoneLabel; // 전화번호
private JTextField phoneTextField; // 전화번호 입력창
private JPanel panel5;
private JLabel addrLabel; // 주소
private JTextField addrTextField; // 주소 입력창
private JPanel parentPanel2;
private JPanel panel6;
private JButton signUpButton; // 회원가입 버튼
private Color backgroundColor;
private JTextField[] textFields = new JTextField[4];
private int phoneNumberHintCount = 0;
public SignUpFrame() {
initData();
setInitLayout();
addEventListener();
}
private void initData() {
setTitle("회원가입");
setSize(400, 350);
parentPanel1 = new JPanel();
panel1 = new JPanel();
idLabel = new JLabel(" 아이디");
idTextField = new JTextField("", 10);
idCheckButton = new JButton("중복 확인");
panel2 = new JPanel();
pwLabel = new JLabel("비밀번호");
pwPasswordField = new JPasswordField(10);
panel3 = new JPanel();
nameLabel = new JLabel(" 이름");
nameTextField = new JTextField("", 10);
panel4 = new JPanel();
phoneLabel = new JLabel("전화번호");
phoneTextField = new JTextField("010-0000-0000", 10);
panel5 = new JPanel();
addrLabel = new JLabel(" 주소");
addrTextField = new JTextField("", 20);
parentPanel2 = new JPanel();
panel6 = new JPanel();
signUpButton = new JButton("회원가입");
textFields[0] = idTextField;
textFields[1] = nameTextField;
textFields[2] = phoneTextField;
textFields[3] = addrTextField;
}
private void setInitLayout() {
add(parentPanel1, BorderLayout.CENTER);
parentPanel1.setBackground(backgroundColor);
add(parentPanel2, BorderLayout.SOUTH);
parentPanel2.setBackground(backgroundColor);
parentPanel1.setLayout(new FlowLayout(FlowLayout.LEFT, 40, 18));
setResizable(false);
// 뜨는 위치 지정하는 법 알아보기
setLocationRelativeTo(null); // JFrame 가운데 배치
Color backgroundColor = new Color(200, 235, 226);
getContentPane().setBackground(backgroundColor);
parentPanel1.add(panel1);
panel1.add(idLabel, FlowLayout.LEFT);
panel1.add(idTextField);
panel1.add(idCheckButton);
panel1.setBackground(backgroundColor);
parentPanel1.add(panel2);
panel2.add(pwLabel);
panel2.add(pwPasswordField);
panel2.setBackground(backgroundColor);
parentPanel1.add(panel3);
panel3.add(nameLabel);
panel3.add(nameTextField);
panel3.setBackground(backgroundColor);
parentPanel1.add(panel4);
panel4.add(phoneLabel);
panel4.add(phoneTextField);
panel4.setBackground(backgroundColor);
parentPanel1.add(panel5);
panel5.add(addrLabel);
panel5.add(addrTextField);
panel5.setBackground(backgroundColor);
parentPanel2.add(panel6);
panel6.add(signUpButton);
panel6.setBackground(backgroundColor);
setVisible(true);
}
private void addEventListener() {
signUpButton.addActionListener(this);
idCheckButton.addActionListener(this);
phoneTextField.addMouseListener(this);
}
@Override
public void actionPerformed(ActionEvent e) {
JButton targetButton = (JButton) e.getSource();
int result = 0;
// 아이디 중복확인 버튼
if (targetButton == idCheckButton) {
// 방어적 코드 (입력되지 않은 값이 있다면 실행 X)
if (idTextField.getText().isEmpty()) {
System.out.println("값이 입력되지 않았습니다.");
return;
}
String id = textFields[0].getText();
MemberDAO memberDAO = new MemberDAO();
result = memberDAO.memberIdCheck(id);
// 아이디가 중복되었다면
if (result == 1) {
JOptionPane.showMessageDialog(null, "이미 존재하는 아이디입니다.", "", JOptionPane.PLAIN_MESSAGE);
} else {
JOptionPane.showMessageDialog(null, "사용 가능한 아이디입니다.", "", JOptionPane.PLAIN_MESSAGE);
}
// 회원가입 버튼
} else if (targetButton == signUpButton) {
// 방어적 코드 (입력되지 않은 값이 있다면 실행 X)
for (int i = 0; i < textFields.length; i++) {
if (textFields[i].getText().isEmpty()) {
System.out.println("모든 값을 입력해주세요.");
JOptionPane.showMessageDialog(null, "모든 값을 입력해주세요.", "회원가입 실패", JOptionPane.PLAIN_MESSAGE);
return;
}
}
if (new String(pwPasswordField.getPassword()).isEmpty()) {
System.out.println("모든 값을 입력해주세요.");
JOptionPane.showMessageDialog(null, "모든 값을 입력해주세요.", "회원가입 실패", JOptionPane.PLAIN_MESSAGE);
return;
}
String id = textFields[0].getText();
char[] pwChar = pwPasswordField.getPassword();
String pw = new String(pwChar);
String name = textFields[1].getText();
String phoneNumber = textFields[2].getText();
String address = textFields[3].getText();
MemberDAO memberDAO = new MemberDAO();
result = memberDAO.memberSignUp(id, pw, name, phoneNumber, address);
if (result == 1) {
System.out.println("회원가입에 성공했습니다!");
// 확인을 누르면 회원가입 프레임 종료
JOptionPane.showMessageDialog(null, "회원가입에 성공했습니다!", "회원가입 성공", JOptionPane.PLAIN_MESSAGE);
this.dispose();
} else {
JOptionPane.showMessageDialog(null, "중복되거나 입력되지 않은 값이 있는지 확인해주세요.", "회원가입 실패", JOptionPane.PLAIN_MESSAGE);
}
}
} // end of method
@Override
public void mouseClicked(MouseEvent e) {
}
@Override
public void mousePressed(MouseEvent e) {
JTextField targetTextField = (JTextField) e.getSource();
if (targetTextField == phoneTextField) {
phoneNumberHintCount++;
// 처음 눌렀을 때만 힌트가 없어지도록
if (phoneNumberHintCount == 1) {
targetTextField.setText("");
}
}
}
@Override
public void mouseReleased(MouseEvent e) {
}
@Override
public void mouseEntered(MouseEvent e) {
}
@Override
public void mouseExited(MouseEvent e) {
}
}
실행
개선할 것
1) member 테이블
- '생일'을 NULL 허용 컬럼으로 추가
→ 나중에 쿠폰함을 만들어서 CURDATE()로 오늘 생일이면 쿠폰을 주는 기능을 추가하고 싶음
- phone_number를 UNIQUE로 변경
2) SignUpFrame
- 아이디, 비밀번호도 전화번호처럼 힌트가 표시되도록 하기 (글자 수 제한)
→ 힌트인 상태로 회원가입되지 않도록 조건도 달아야 함
- 힌트는 버튼을 한 번 클릭하면 사라지도록 하려고 int 변수를 활용했는데,
그 대신에 Boolean 변수를 활용하는 게 좀 더 직관적일 것 같음
- 비밀번호 확인 기능 만들기
→ 회원 가입 버튼을 눌렀을 때 비밀번호 칸과 비밀번호 확인 칸의 값이 서로 다르면 경고 메시지
- 형식에 맞지 않는 값을 입력하면 회원가입이 되지 않도록 하기
3) LoginFrame
- Login 메서드의 반환 값을 DTO 객체로 해서, 쇼핑몰 홈 프레임의 매개변수로 넣기
'My Project > Pet Shopping Mall GUI Project' 카테고리의 다른 글
[개발 일지] 반려동물 용품 쇼핑몰 GUI 구현 프로젝트 6일차 (03/16) (0) | 2023.03.17 |
---|---|
[개발 일지] 반려동물 용품 쇼핑몰 GUI 구현 프로젝트 5일차 (03/15) (0) | 2023.03.16 |
[개발 일지] 반려동물 용품 쇼핑몰 GUI 구현 프로젝트 4일차 (03/14) (0) | 2023.03.14 |
[개발 일지] 반려동물 용품 쇼핑몰 GUI 구현 프로젝트 3일차 (03/13) (0) | 2023.03.13 |
[개발 일지] 반려동물 용품 쇼핑몰 GUI 구현 프로젝트 2일차 (03/12) (0) | 2023.03.13 |