[DB] JDBC 프로그래밍 - ScoulaTodo (0716)

왕감자·2024년 7월 17일

KB IT's Your Life

목록 보기
86/177

CLI 프레임워크를 사용하여 TODO APP만들기~!

Project name: ScoulaTodo

설정

settings.gradle

rootProject.name = 'ScoulaTodo'
include ':ScoulaCli'
project(':ScoulaCli').projectDir=new File('C:\\KB_ITs_Your_Life\\Scoula\\ScoulaLib\\scoulacli')

build.gradle

dependencies {
    implementation project(':ScoulaCli')
    
    implementation 'com.mysql:mysql-connector-j:8.3.0'
    compileOnly 'org.projectlombok:lombok:1.18.30'
    annotationProcessor 'org.projectlombok:lombok:1.18.30'

    testCompileOnly 'org.projectlombok:lombok:1.18.30'
    testAnnotationProcessor 'org.projectlombok:lombok:1.18.30'
    
    testImplementation platform('org.junit:junit-bom:5.10.0')
    testImplementation 'org.junit.jupiter:junit-jupiter'
}
  • Annotation Processing 활성화

  • IntelliJ DataSource 등록

  • 프로젝트 루트에 todo.sql 파일 추가


  • 기존 jbdc_ex 프로젝트에서 코드 가져오기 + application.properties
// UserVO.java
@Data
@NoArgsConstructor 
@AllArgsConstructor
@Builder // 기존 코드에서 Builder만 추가
public class UserVO {
    private String id;
    private String password;
    private String name;
    private String role;
}    

구현할 기능

  • 회원가입
  • 로그인
  • 로그아웃
  • 종료
  • 로그인 상태에 따라 보여주는 메뉴가 다름
    • 기존 createMenu() 대신 다른 방식으로 메뉴 운영
    • App클래스에 void setMenu(Menu menu) 메서드 추가
// App.java
public abstract class App {
    Menu menu;

    public App() {
    }
    
    // 메서드 추가 - 외부에서 메뉴가 들어오도록~
    public void setMenu(Menu menu) {
        this.menu = menu;
    }
 ...

메뉴 구성

  • annoymousMenu
    • 로그인하지 않은 상태 때 운영
  • userMenu
    • 로그인 한 상태 때 운영

TodoApp.java

public class TodoApp extends App {
    Menu userMenu; // 로그인 상태
    Menu anonymousMenu; // 로그아웃 상태

    @Override
    public void init() {
        anonymousMenu = new Menu();
        anonymousMenu.add(new MenuItem("로그인", this::login));
        anonymousMenu.add(new MenuItem("가입", this::join)); // 아직 구현x
        anonymousMenu.add(new MenuItem("종료", this::exit));

        userMenu = new Menu();
        userMenu.add(new MenuItem("로그아웃", this::logout));
        userMenu.add(new MenuItem("종료", this::exit));

        setMenu(anonymousMenu); // 시작은 annonymousMenu로
    }

    public void join() {
    }

    public void login() {
        setMenu(userMenu);
    }
    public void logout() {
        if(Input.confirm("로그아웃 할까요?")) {
            setMenu(anonymousMenu); // 메뉴 교체
        }
    }

    // exit 메소드 추가 - 교안에 없음
    public void exit() {
        System.exit(0); // 프로그램 종료
    }

    public static void main(String[] args) {
        final TodoApp app = new TodoApp();
        app.run();
    }
}

회원가입(join)

  • 사용자 ID, 비밀번호, 비밀번호2, 이름, 역할 입력 받아 DB에 등록
  • 예외 상황 (사용자 정의 예외 - 상속)
    • 사용자 ID 중복 ➔ UsernameDuplicateException 예외 발생
    • 비밀번호, 비밀번호2 불일치 ➔ PasswordMissmatchException 예외 발생

예외

UsernameDuplicationException.java

package org.scoula.todo.exception;

// 회원가입 -사용자 ID 중복
public class UsernameDuplicationException extends Exception{
    public UsernameDuplicationException() {
        super("이미 사용중인 사용자 ID 입니다");
    }
}

PasswordMissmatchException.java

 package org.scoula.todo.exception;

// 회원가입 - 비밀번호, 비밀번호2 불일치
public class PasswordMissmatchException extends Exception{
    public PasswordMissmatchException() {
        super("비밀번호가 맞지 않습니다");
    }
}

회원가입

AccountService.java

package org.scoula.todo.service;

// 회원가입
public class AccountService {
    UserDao dao = new UserDaoImpl();

    public void join() {
        try {
            UserVO user = getUser();
            dao.create(user); // 유저 정보 받으면 dao를 이용해 create~
        } catch (UsernameDuplicationException | PasswordMissmatchException e) {
            System.out.println(e.getMessage());
        } catch (Exception e) {
            throw new RuntimeException(e); //
        }
    }

    public boolean checkDuplication(String username) throws UsernameDuplicationException, SQLException {
        Optional<UserVO> result = dao.get(username); // username이 있으면 리턴, 없으면 Null
        if (result.isPresent()) { // 데이터가 있으면 ID 중복
            throw new UsernameDuplicationException();
        }
        return false;
    }

    public UserVO getUser() throws SQLException, UsernameDuplicationException, PasswordMissmatchException {
        String username = Input.getLine("사용자 ID: ");
        checkDuplication(username); // 중복 체크

        String password = Input.getLine("비밀번호: ");
        String password2 = Input.getLine("비밀번호 확인: ");
        if (!password.equals(password2)) {
            throw new PasswordMissmatchException();
        }

        String name = Input.getLine("이름: ");
        String role = Input.getLine("역할: ");

        return UserVO.builder()
                .id(username)
                .password(password)
                .name(name)
                .role(role)
                .build();
    }
}

TodoApp.java

public class TodoApp extends App {
    Menu userMenu; // 로그인 상태
    Menu anonymousMenu; // 로그아웃 상태
    AccountService accountService = new AccountService();

    @Override
    public void init() {
        anonymousMenu = new Menu();
        anonymousMenu.add(new MenuItem("로그인", this::login));
        anonymousMenu.add(new MenuItem("가입", accountService::join));
        anonymousMenu.add(new MenuItem("종료", this::exit));

        userMenu = new Menu();
        userMenu.add(new MenuItem("로그아웃", this::logout));
        userMenu.add(new MenuItem("종료", this::exit));

        setMenu(anonymousMenu); // 시작은 annonymousMenu로
    }

    public void join() {
    }

    public void login() {
        setMenu(userMenu);
    }
    public void logout() {
        if(Input.confirm("로그아웃 할까요?")) {
            setMenu(anonymousMenu); // 메뉴 교체
        }
    }

    // exit 메소드 추가 - 교안에 없음
    public void exit() {
        System.exit(0); // 프로그램 종료
    }

    public static void main(String[] args) {
        final TodoApp app = new TodoApp();
        app.run();
    }
}

로그인

  • UserVO 객체 참조 UserVo user; //로그인 사용자
  • 로그인 사용자(User)정보는 어플리케이션 전체에서 접근 할 수 있어야 함
    • Context 객체를 싱글톤으로 운영
    • User 정보는 Context 객체를 통해 접근 (Context 객체 안에 user 정보 저장)
  • 사용자 ID와 비밀번호를 입력받아 DB의 내용과 일치하는지 체크
  • 로그인 성공 시
    • 로그인 사용자 정보 user 설정
    • 메뉴를 userMenu로 교체
  • 예외
    • 사용자 ID가 DB에 없는 경우
    • 비밀번호가 DB의 비밀번호와 맞지 않는 경우
      ⇨ LoginFailException발생 (사용자 정의 예외)

Context.java

package org.scoula.todo.context;

@Getter
@Setter
public class Context {
    private UserVO user; // 로그인 사용자 정보, null이면 로그아웃 상태

    // 싱글톤 패턴
    private Context() {}
    
    private static Context context = new Context();
    
    public static Context getContext() {
        return context;
    }
}

LoginFailException.java

package org.scoula.todo.exception;

public class LoginFailException extends Exception{
    public LoginFailException() {
        super("사용자 ID 또는 비밀번호가 일치하지 않습니다");
    }
}

LoginService.java

package org.scoula.todo.service;

import java.sql.SQLException;

public class LoginService {
    UserDao dao = new UserDaoImpl();
    
    public void login() throws SQLException, LoginFailException {
        String username = Input.getLine("사용자 ID: ");
        String password = Input.getLine("비밀번호: ");

        UserVO user = dao.get(username).orElseThrow(LoginFailException::new); // 일치하는 id가 아니면 예외 발생
        
        if (user.getPassword().equals(password)) {
            Context ctx = Context.getContext();
            ctx.setUser(user);
        } else {
            throw new LoginFailException();
        }
    }
}

TodoApp.java

public class TodoApp extends App {
    Menu userMenu; // 로그인 상태
    Menu anonymousMenu; // 로그아웃 상태
    AccountService accountService = new AccountService();
    LoginService loginService = new LoginService();

    @Override
    public void init() {
        anonymousMenu = new Menu();
        anonymousMenu.add(new MenuItem("로그인", this::login));
        anonymousMenu.add(new MenuItem("가입", accountService::join));
        anonymousMenu.add(new MenuItem("종료", this::exit));

        userMenu = new Menu();
        userMenu.add(new MenuItem("로그아웃", this::logout));
        userMenu.add(new MenuItem("종료", this::exit));

        setMenu(anonymousMenu); // 시작은 annonymousMenu로
    }

    public void join() {
    }

    public void login() {
        try {
            loginService.login();
            setMenu(userMenu);
        } catch (SQLException e){
            throw new RuntimeException(e);
        } catch (LoginFailException e){
            System.out.println(e.getMessage());
        }
    }
    public void logout() {
        if(Input.confirm("로그아웃 할까요?")) {
            setMenu(anonymousMenu); // 메뉴 교체
        }
    }

    // exit 메소드 추가 - 교안에 없음
    public void exit() {
        System.exit(0); // 프로그램 종료
    }

    public static void main(String[] args) {
        final TodoApp app = new TodoApp();
        app.run();
    }
}

로그아웃

  • 로그인 사용자 정보를 null로 설정 (Context)
  • 메뉴를 anonymousMenu로 교체

TodoApp.java

public void logout() {
        if(Input.confirm("로그아웃 할까요?")) {
            Context.getContext().setUser(null);
            setMenu(anonymousMenu); // 메뉴 교체
        }
    }

[0717]

사용자별 Todo 관리

데이터베이스 Todo 테이블 준비

todo.sql

DROP TABLE IF EXISTS TODO;
CREATE TABLE TODO (
    ID INTEGER AUTO_INCREMENT NOT NULL PRIMARY KEY,
    TITLE VARCHAR(128) NOT NULL,
    DESCRIPTION VARCHAR(512) NULL,
    DONE BOOLEAN,
    USERID VARCHAR(12) NOT NULL,
    FOREIGN KEY (USERID) REFERENCES USERS(ID)
        ON UPDATE CASCADE
        ON DELETE CASCADE
);

INSERT INTO TODO(TITLE, DESCRIPTION, DONE, USERID)
VALUES ('야구장', '프로야구 경기 보기', FALSE, 'GUEST'),
       ('놀기', '열심히 놀기', FALSE, 'GUEST'),
       ('DB공부', 'JDBC 모듈평가 공부', FALSE, 'MEMBER'),
       ('코테', '알고리즘 공부', TRUE, 'GUEST');

구현할 기능

  • 로그인 상태
    • 목록
    • 검색
    • 상세
    • 추가
    • 수정
    • 삭제

0개의 댓글