Coding History

2024. 07. 14. JDBC 리팩토링

BlackBirdIT 2024. 7. 14. 18:20

이제 기능이 많아졌으니 클래스를 나누어서 각 클래스에 맞게 기능을 나누어 주는 과정이 필요할 것 같다.

MemberController와 ArticleController를 만들어서 각 기능을 일단 나누어보자.

일단은 현재 코드 모양.

public class App {

    public void run() {
        System.out.println("==프로그램 시작==");
        Scanner sc = new Scanner(System.in);

        while (true) {
            System.out.print("명령어 > ");
            String cmd = sc.nextLine().trim();

            Connection conn = null;

            try {
                Class.forName("org.mariadb.jdbc.Driver");
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }

            String url = "jdbc:mariadb://127.0.0.1:3306/AM_JDBC_2024_07?useUnicode=true&characterEncoding=utf8&autoReconnect=true&serverTimezone=Asia/Seoul";

            try {
                conn = DriverManager.getConnection(url, "root", "1234");

                int actionResult = doAction(conn, sc, cmd);

                if (actionResult == -1) {
                    System.out.println("==프로그램 종료==");
                    sc.close();
                    break;
                }

            } catch (SQLException e) {
                System.out.println("에러 1 : " + e);
            } finally {
                try {
                    if (conn != null && !conn.isClosed()) {
                        conn.close();
                    }
                } catch (SQLException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    private int doAction(Connection conn, Scanner sc, String cmd) {

        if (cmd.equals("exit")) {
            return -1;
        }

        if (cmd.equals("member join")) {
            String loginId = null;
            String loginPw = null;
            String loginPwConfirm = null;
            String name = null;

            System.out.println("==회원가입==");
            while (true) {
                System.out.print("로그인 아이디 : ");
                loginId = sc.nextLine().trim();

                if (loginId.length() == 0 || loginId.contains(" ")) {
                    System.out.println("아이디 똑바로 써");
                    continue;
                }

                SecSql sql = new SecSql();

                sql.append("SELECT COUNT(*) > 0");
                sql.append("FROM `member`");
                sql.append("WHERE loginId = ?;", loginId);

                boolean isLoindIdDup = DBUtil.selectRowBooleanValue(conn, sql);

                if (isLoindIdDup) {
                    System.out.println(loginId + "는(은) 이미 사용중");
                    continue;
                }
                break;
            }
            while (true) {
                System.out.print("비밀번호 : ");
                loginPw = sc.nextLine().trim();

                if (loginPw.length() == 0 || loginPw.contains(" ")) {
                    System.out.println("비번 똑바로 입력해");
                    continue;
                }

                boolean loginPwCheck = true;

                while (true) {
                    System.out.print("비밀번호 확인 : ");
                    loginPwConfirm = sc.nextLine().trim();

                    if (loginPwConfirm.length() == 0 || loginPwConfirm.contains(" ")) {
                        System.out.println("비번 확인 똑바로 써");
                        continue;
                    }
                    if (loginPw.equals(loginPwConfirm) == false) {
                        System.out.println("일치하지 않아");
                        loginPwCheck = false;
                    }
                    break;
                }
                if (loginPwCheck) {
                    break;
                }
            }

            while (true) {
                System.out.print("이름 : ");
                name = sc.nextLine();

                if (name.length() == 0 || name.contains(" ")) {
                    System.out.println("이름 똑바로 써");
                    continue;
                }
                break;
            }


            SecSql sql = new SecSql();

            sql.append("INSERT INTO `member`");
            sql.append("SET regDate = NOW(),");
            sql.append("updateDate = NOW(),");
            sql.append("loginId = ?,", loginId);
            sql.append("loginPw= ?,", loginPw);
            sql.append("name = ?;", name);

            int id = DBUtil.insert(conn, sql);

            System.out.println(id + "번 회원이 생성되었습니다");

        } else if (cmd.equals("article list")) {
            System.out.println("==목록==");


            List<Article> articles = new ArrayList<>();

            SecSql sql = new SecSql();
            sql.append("SELECT *");
            sql.append("FROM article");
            sql.append("ORDER BY id DESC");

            List<Map<String, Object>> articleListMap = DBUtil.selectRows(conn, sql);

            for (Map<String, Object> articleMap : articleListMap) {
                articles.add(new Article(articleMap));
            }

            if (articles.size() == 0) {
                System.out.println("게시글이 없습니다");
                return 0;
            }

            System.out.println("  번호  /   제목  ");
            for (Article article : articles) {
                System.out.printf("  %d     /   %s   \n", article.getId(), article.getTitle());
            }
        } else if (cmd.startsWith("article delete")) {

            int id = 0;

            try {
                id = Integer.parseInt(cmd.split(" ")[2]);
            } catch (Exception e) {
                System.out.println("번호는 정수로 입력해");
                return 0;
            }

            SecSql sql = new SecSql();
            sql.append("SELECT COUNT(*) FROM article WHERE id = ?;", id);
            int deleteId = DBUtil.selectRowIntValue(conn, sql);

            if (deleteId == 0) {
                System.out.println(id + "번 게시물 없어.");
            } else {
                SecSql sql2 = new SecSql();
                sql2.append("DELETE FROM article WHERE id = ?;", id);
                DBUtil.delete(conn, sql2);
                System.out.println(id + "번 글이 삭제되었습니다.");
            }

        } else if (cmd.startsWith("article modify")) {

            int id = 0;

            try {
                id = Integer.parseInt(cmd.split(" ")[2]);
            } catch (Exception e) {
                System.out.println("번호는 정수로 입력해");
                return 0;
            }
            SecSql sql = new SecSql();
            sql.append("SELECT COUNT(*) FROM article WHERE id = ?;", id);
            int articleId = DBUtil.selectRowIntValue(conn, sql);

            if (articleId == 0) {
                System.out.println(id + "번 게시물 없어.");
            } else {
                System.out.println("==수정==");
                System.out.print("새 제목 : ");
                String title = sc.nextLine().trim();
                System.out.print("새 내용 : ");
                String body = sc.nextLine().trim();
                SecSql sql2 = new SecSql();
                sql2.append("UPDATE article");
                sql2.append("SET updateDate = NOW(),");
                if (!title.isEmpty()) {
                    sql2.append("title = ?,", title);
                }
                if (!body.isEmpty()) {
                    sql2.append("`body`= ?", body);
                }
                sql2.append("WHERE id = ?;", id);

                DBUtil.update(conn, sql2);
                System.out.println(id + "번 글이 수정되었습니다.");
            }
        } else if (cmd.startsWith("article detail")) {
            int id = 0;
            try {
                id = Integer.parseInt(cmd.split(" ")[2]);
            } catch (Exception e) {
                System.out.println("번호는 정수로 입력해");
                return 0;
            }
            SecSql sql = new SecSql();
            sql.append("SELECT COUNT(*) FROM article WHERE id = ?;", id);
            int articleId = DBUtil.selectRowIntValue(conn, sql);
            if (articleId == 0) {
                System.out.println(id + "번 게시물 없어.");
            } else {

                SecSql sql2 = new SecSql();
                sql2.append("SELECT * FROM article WHERE id = ?;", id);
                Map<String, Object> articleListMap = DBUtil.selectRow(conn, sql2);

//                if (articleListMap.isEmpty()) {
//                    System.out.println(id + "번 게시물 없어");
//                    return 0;
//                }

                Article article = new Article(articleListMap);

                System.out.println("번호 : " + article.getId());
                System.out.println("제목 : " + article.getTitle());
                System.out.println("내용 : " + article.getBody());
                System.out.println("작성시간 : " + article.getRegDate());
                System.out.println("수정시간 : " + article.getUpdateDate());
            }


        }
        return 0;
    }
}

현재는 App에 모든 기능을 거의 다 넣고 있는 중이다. 여기서 한번 적절히 나누어 보자.

private int doAction(Connection conn, Scanner sc, String cmd) {

        if (cmd.equals("exit")) {
            return -1;
        }

        MemberController memberController = new MemberController();
        ArticleController articleController = new ArticleController();
        if (cmd.equals("member join")) {
            memberController. doJoin();

        }

일단은 컨트롤러 선언을 해주고,

package org.koreait.controller;

import org.koreait.Util.DBUtil;
import org.koreait.Util.SecSql;
import org.koreait.service.MemberService;

import java.sql.Connection;
import java.util.Scanner;

public class MemberController {
    private Connection conn;
    private Scanner sc;

    private MemberService memberService;

    public MemberController(Scanner sc, Connection conn) {
        this.sc = sc;
        this.conn = conn;
        this.memberService = new MemberService;
    }

    public void doJoin() {
        String loginId = null;
        String loginPw = null;
        String loginPwConfirm = null;
        String name = null;

        System.out.println("==회원가입==");
        while (true) {
            System.out.print("로그인 아이디 : ");
            loginId = sc.nextLine().trim();

            if (loginId.length() == 0 || loginId.contains(" ")) {
                System.out.println("아이디 똑바로 써");
                continue;
            }

            SecSql sql = new SecSql();

            sql.append("SELECT COUNT(*) > 0");
            sql.append("FROM `member`");
            sql.append("WHERE loginId = ?;", loginId);

            boolean isLoindIdDup = DBUtil.selectRowBooleanValue(conn, sql);

            if (isLoindIdDup) {
                System.out.println(loginId + "는(은) 이미 사용중");
                continue;
            }
            break;
        }
        while (true) {
            System.out.print("비밀번호 : ");
            loginPw = sc.nextLine().trim();

            if (loginPw.length() == 0 || loginPw.contains(" ")) {
                System.out.println("비번 똑바로 입력해");
                continue;
            }

            boolean loginPwCheck = true;

            while (true) {
                System.out.print("비밀번호 확인 : ");
                loginPwConfirm = sc.nextLine().trim();

                if (loginPwConfirm.length() == 0 || loginPwConfirm.contains(" ")) {
                    System.out.println("비번 확인 똑바로 써");
                    continue;
                }
                if (loginPw.equals(loginPwConfirm) == false) {
                    System.out.println("일치하지 않아");
                    loginPwCheck = false;
                }
                break;
            }
            if (loginPwCheck) {
                break;
            }
        }

        while (true) {
            System.out.print("이름 : ");
            name = sc.nextLine();

            if (name.length() == 0 || name.contains(" ")) {
                System.out.println("이름 똑바로 써");
                continue;
            }
            break;
        }


        SecSql sql = new SecSql();

        sql.append("INSERT INTO `member`");
        sql.append("SET regDate = NOW(),");
        sql.append("updateDate = NOW(),");
        sql.append("loginId = ?,", loginId);
        sql.append("loginPw= ?,", loginPw);
        sql.append("name = ?;", name);

        int id = DBUtil.insert(conn, sql);

        System.out.println(id + "번 회원이 생성되었습니다");
    }
}

코드를 옮겨 주고 정상 작동이 되는지 확인해본다. 확인이 된다면 MemberService에 쿼리를 날리는 부분을 다시 나눠줘야 하기 때문에 MemberService까지 선언해준 모습이다.

시간을 들여서 같은 방식으로 Article도 모두 다 기능을 나누면 코드는 이렇게 된다.

  • App Class
    package org.koreait;
    

import org.koreait.controller.ArticleController;
import org.koreait.controller.MemberController;

import java.sql.;
import java.util.
;

public class App {

public void run() {
    System.out.println("==프로그램 시작==");
    Scanner sc = new Scanner(System.in);

    while (true) {
        System.out.print("명령어 > ");
        String cmd = sc.nextLine().trim();

        Connection conn = null;

        try {
            Class.forName("org.mariadb.jdbc.Driver");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }

        String url = "jdbc:mariadb://127.0.0.1:3306/AM_JDBC_2024_07?useUnicode=true&characterEncoding=utf8&autoReconnect=true&serverTimezone=Asia/Seoul";

        try {
            conn = DriverManager.getConnection(url, "root", "1234");

            int actionResult = action(conn, sc, cmd);

            if (actionResult == -1) {
                System.out.println("==프로그램 종료==");
                sc.close();
                break;
            }

        } catch (SQLException e) {
            System.out.println("에러 1 : " + e);
        } finally {
            try {
                if (conn != null && !conn.isClosed()) {
                    conn.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

private int action(Connection conn, Scanner sc, String cmd) {

    if (cmd.equals("exit")) {
        return -1;
    }

    MemberController memberController = new MemberController(sc, conn);
    ArticleController articleController = new ArticleController(sc, conn);

    if (cmd.equals("member join")) {
        memberController. doJoin();

    } else if (cmd.equals("article write")) {
        articleController.doWrite();

    } else if (cmd.equals("article list")) {
        articleController.showList();

    } else if (cmd.startsWith("article delete")) {
        articleController.doDelete(cmd);

    }
    else if (cmd.startsWith("article modify")) {
        articleController.doModify(cmd);

    } else if (cmd.startsWith("article detail")) {
        articleController.showDetail(cmd);

    }
    return 0;
}

}


- ArticleController Class
```java
package org.koreait.controller;

import org.koreait.Article.Article;
import org.koreait.Util.SecSql;
import org.koreait.service.ArticleServie;

import java.sql.Connection;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Scanner;

public class ArticleController {
    private Connection conn;
    private Scanner sc;

    public ArticleController(Scanner sc, Connection conn) {
        this.sc = sc;
        this.conn = conn;
    }

    public void doWrite() {
        System.out.println("==글쓰기==");
        System.out.print("제목 : ");
        String title = sc.nextLine();
        System.out.print("내용 : ");
        String body = sc.nextLine();

        int id = ArticleServie.doWrite(conn, title, body);

        System.out.println(id + "번 글이 생성되었습니다");
    }

    public void showList() {

        System.out.println("==목록==");

        List<Article> articles = new ArrayList<>();

        List<Map<String, Object>> articleListMap = ArticleServie.showList(conn);

        for (Map<String, Object> articleMap : articleListMap) {
            articles.add(new Article(articleMap));
        }

        if (articles.isEmpty()) {
            System.out.println("게시글이 없습니다");
            return;
        }

        System.out.println("  번호  /   제목  ");
        for (Article article : articles) {
            System.out.printf("  %d     /   %s   \n", article.getId(), article.getTitle());
        }
    }

    public void doDelete(String cmd) {
        int id = 0;

        try {
            id = Integer.parseInt(cmd.split(" ")[2]);
        } catch (Exception e) {
            System.out.println("번호는 정수로 입력해");
            return;
        }

        int deleteId = ArticleServie.isExistId(conn, id);

        if (deleteId == 0) {
            System.out.println(id + "번 게시물 없어.");
        } else {
            ArticleServie.doDelete(conn, id);

            System.out.println(id + "번 글이 삭제되었습니다.");
        }
    }

    public void doModify(String cmd) {
        int id = 0;

        try {
            id = Integer.parseInt(cmd.split(" ")[2]);
        } catch (Exception e) {
            System.out.println("번호는 정수로 입력해");
            return;
        }

        int articleId = ArticleServie.isExistId(conn, id);

        if (articleId == 0) {
            System.out.println(id + "번 게시물 없어.");
        } else {
            System.out.println("==수정==");
            System.out.print("새 제목 : ");
            String newTitle = sc.nextLine().trim();
            System.out.print("새 내용 : ");
            String newBody = sc.nextLine().trim();

            ArticleServie.doUpdate(conn, newTitle, newBody, id);

            System.out.println(id + "번 글이 수정되었습니다.");
        }
    }

    public void showDetail(String cmd) {
        int id = 0;
        try {
            id = Integer.parseInt(cmd.split(" ")[2]);
        } catch (Exception e) {
            System.out.println("번호는 정수로 입력해");
            return;
        }

        int articleId = ArticleServie.isExistId(conn, id);

        if (articleId == 0) {
            System.out.println(id + "번 게시물 없어.");
        } else {
            Map<String, Object> articleListMap = ArticleServie.showDetail(conn, id);

            Article article = new Article(articleListMap);

            System.out.println("번호 : " + article.getId());
            System.out.println("제목 : " + article.getTitle());
            System.out.println("내용 : " + article.getBody());
            System.out.println("작성시간 : " + article.getRegDate());
            System.out.println("수정시간 : " + article.getUpdateDate());
        }
    }
}
  • ArticleService Class
    package org.koreait.service;
    

import org.koreait.dao.ArticleDao;

import java.sql.Connection;
import java.util.List;
import java.util.Map;

public class ArticleServie {

private ArticleDao articleDao;

public ArticleServie() {
    this.articleDao = new ArticleDao();
}


public static int doWrite(Connection conn, String title, String body) {
    return ArticleDao.doWrite(conn, title, body);
}

public static List<Map<String, Object>> showList(Connection conn) {
    return ArticleDao.showList(conn);
}

public static int isExistId(Connection conn, int id) {
    return ArticleDao.isExistId(conn, id);
}

public static void doDelete(Connection conn, int id) {
    ArticleDao.doDelete(conn, id);
}

public static void doUpdate(Connection conn, String newTitle, String newBody, int id) {
    ArticleDao.doUpdate(conn, newTitle, newBody, id);
}

public static Map<String, Object> showDetail(Connection conn, int id) {
    return ArticleDao.showDetail(conn, id);
}

}


- ArticleDao Class
```java
package org.koreait.dao;

import org.koreait.Util.DBUtil;
import org.koreait.Util.SecSql;

import java.sql.Connection;
import java.util.List;
import java.util.Map;

public class ArticleDao {
    public static int doWrite(Connection conn, String title, String body) {
        SecSql sql = new SecSql();

        sql.append("INSERT INTO article");
        sql.append("SET regDate = NOW(),");
        sql.append("updateDate = NOW(),");
        sql.append("title = ?,", title);
        sql.append("`body`= ?;", body);

        return DBUtil.insert(conn, sql);
    }

    public static List<Map<String, Object>> showList(Connection conn) {
        SecSql sql = new SecSql();

        sql.append("SELECT *");
        sql.append("FROM article");
        sql.append("ORDER BY id DESC");

        return DBUtil.selectRows(conn, sql);
    }

    public static int isExistId(Connection conn, int id) {
        SecSql sql = new SecSql();
        sql.append("SELECT COUNT(*) FROM article WHERE id = ?;", id);

        return DBUtil.selectRowIntValue(conn, sql);
    }

    public static void doDelete(Connection conn, int id) {
        SecSql sql = new SecSql();
        sql.append("DELETE FROM article WHERE id = ?;", id);

        DBUtil.delete(conn, sql);
    }

    public static void doUpdate(Connection conn, String newTitle, String newBody, int id) {
        SecSql sql2 = new SecSql();
        sql2.append("UPDATE article");
        sql2.append("SET updateDate = NOW(),");
        if (!newTitle.isEmpty()) {
            sql2.append("title = ?,", newTitle);
        }
        if (!newBody.isEmpty()) {
            sql2.append("`body`= ?", newBody);
        }
        sql2.append("WHERE id = ?;", id);

        DBUtil.update(conn, sql2);
    }

    public static Map<String, Object> showDetail(Connection conn, int id) {
        SecSql sql = new SecSql();
        sql.append("SELECT * FROM article WHERE id = ?;", id);

        return DBUtil.selectRow(conn, sql);
    }
}

이렇게 다 나누었고 기능도 모두 정상 작동한다.

각자의 역할에 맞게끔 기능을 분리 시키고 해당 클래스에서는 해당 기능만 작동할 수 있도록 리팩토링 했다. 오늘의 공부는 여기까지.