멀티캠퍼스

[2026.05.19] - TIL 33일차 JDBC MVC Product CRUD 프로젝트 정리

buckwheat 2026. 5. 19. 23:57

 

 

 

목차
1 PRODUCT 테이블
2 JDBCTemplate
3 MVC 구조
4 Product VO
5 ProductView
6 ProductController
7 ProductService
8 ProductDao
9 전체 조회 기능
10 선택 조회 기능
11 추가 기능
12 수정 기능
13 삭제 기능

1 PRODUCT 테이블

1) PRODUCT 테이블의 역할

 

    (1) PRODUCT 테이블

    PRODUCT 테이블은 상품 정보를 저장하는 테이블이다.

    상품 ID, 상품명, 가격, 설명을 하나의 행으로 저장해서 상품 데이터를 관리한다.

 

    (2) 상품 관리용 테이블

    이 테이블은 Java JDBC 프로젝트에서 상품 전체 조회, 선택 조회, 추가, 수정, 삭제 기능을 연습하기 위해 사용된다.

    Java 코드에서 SQL을 실행하면 이 PRODUCT 테이블의 데이터가 조회되거나 변경된다.

 

2) PRODUCT 컬럼

 

    (1) P_ID

    P_ID는 상품을 구분하는 고유한 ID이다.

    PRIMARY KEY로 설정되어 있기 때문에 같은 상품 ID를 중복해서 저장할 수 없다.

 

    (2) P_NAME

    P_NAME은 상품명을 저장하는 컬럼이다.

    NOT NULL이 설정되어 있어 상품명은 반드시 입력되어야 한다.

 

    (3) PRICE

    PRICE는 상품 가격을 저장하는 컬럼이다.

    NOT NULL이 설정되어 있어 가격 정보는 반드시 입력되어야 한다.

 

    (4) DES

    DES는 상품 설명을 저장하는 컬럼이다.

    상품에 대한 추가 설명을 저장할 수 있으며, 값이 없어도 되는 선택 정보이다.

 

3) 초기 데이터

 

    (1) 삼성노트북

    LT-SS1이라는 상품 ID로 삼성노트북 정보를 저장한다.

    가격은 2000000이고 설명은 갤럭시북이다.

 

    (2) LG노트북

    LT-LG1이라는 상품 ID로 LG노트북 정보를 저장한다.

    가격은 2200000이고 설명은 그램이다.

 

    (3) 애플컴퓨터

    PC-AP2라는 상품 ID로 애플컴퓨터 정보를 저장한다.

    가격은 3000000이고 설명은 mac이다.


2 JDBCTemplate

1) JDBCTemplate의 개념

 

    (1) JDBCTemplate의 역할

    JDBCTemplate은 JDBC에서 반복되는 DB 연결, 자원 해제, commit, rollback 기능을 모아둔 공통 클래스이다.

    여러 DAO나 Service에서 같은 코드를 반복하지 않고 재사용하기 위해 만든다.

 

    (2) 사용하는 이유

    JDBC는 Connection 생성, Statement 종료, ResultSet 종료 같은 코드가 계속 반복된다.

    이 공통 코드를 JDBCTemplate으로 분리하면 코드가 짧아지고 관리하기 쉬워진다.

 

2) getConnection 메소드

 

    (1) DB 연결

    getConnection 메소드는 Oracle JDBC Driver를 등록하고 DB와 연결한 뒤 Connection 객체를 반환한다.

    JDBC에서 SQL을 실행하려면 가장 먼저 DB와 연결된 Connection 객체가 필요하다.

 

    (2) 접속 정보

    url, id, pw는 Oracle DB에 접속하기 위한 정보이다.

    url은 DB의 주소와 서비스명을 나타내고, id와 pw는 접속할 계정 정보를 의미한다.

 

    (3) 자동 커밋 해제

    con.setAutoCommit(false)는 자동 커밋을 끄는 설정이다.

    자동 커밋을 끄면 INSERT, UPDATE, DELETE 실행 후 직접 commit 또는 rollback을 선택할 수 있다.

 

3) close 메소드

 

    (1) close의 역할

    close 메소드는 사용이 끝난 JDBC 객체를 닫는 역할을 한다.

    Connection, Statement, ResultSet은 DB 자원을 사용하므로 작업이 끝나면 반드시 닫아야 한다.

 

    (2) 메소드 오버로딩

    JDBCTemplate에는 Connection, Statement, ResultSet을 각각 닫는 close 메소드가 있다.

    메소드 이름은 같지만 매개변수 타입이 달라서 전달된 객체에 맞는 close 메소드가 실행된다.

 

    (3) PreparedStatement close

    PreparedStatement는 Statement를 상속받는 객체이다.

    그래서 close(Statement stmt) 메소드로 PreparedStatement도 닫을 수 있다.

 

4) commit과 rollback

 

    (1) commit

    commit은 INSERT, UPDATE, DELETE 같은 변경 작업을 DB에 최종 저장하는 기능이다.

    작업이 성공했을 때 호출한다.

 

    (2) rollback

    rollback은 변경 작업을 취소하는 기능이다.

    작업이 실패했거나 반영하지 않아야 할 때 호출한다.

 

    (3) Service에서 처리하는 이유

    commit과 rollback은 DAO가 아니라 Service에서 처리하는 것이 일반적이다.

    Service가 하나의 기능 흐름을 관리하고, 그 결과에 따라 저장 또는 취소를 결정하기 때문이다.


3 MVC 구조

1) MVC의 개념

 

    (1) MVC의 역할

    MVC는 프로그램을 Model, View, Controller로 나누어 개발하는 구조이다.

    화면 처리, 요청 제어, 데이터 처리를 분리해서 코드 관리가 쉬워진다.

 

    (2) MVC를 사용하는 이유

    모든 기능을 한 클래스에 작성하면 코드가 복잡해지고 수정하기 어렵다.

    역할별로 클래스를 나누면 각 클래스가 맡은 일이 명확해져 유지보수가 편해진다.

 

2) View

 

    (1) View의 역할

    View는 사용자에게 메뉴를 보여주고 입력을 받는 역할을 한다.

    이 프로젝트에서는 ProductView가 View 역할을 한다.

 

    (2) 사용자 요청 시작점

    사용자는 ProductView의 메뉴에서 전체출력, 선택출력, 추가, 수정, 삭제 중 하나를 선택한다.

    선택된 기능은 Controller로 전달된다.

 

3) Controller

 

    (1) Controller의 역할

    Controller는 View의 요청을 받아 Service로 전달하는 중간 관리자 역할을 한다.

    View가 직접 Service나 DAO에 접근하지 않도록 흐름을 연결한다.

 

    (2) 요청 전달

    ProductController는 selectAll, selectOne, insert, update, delete 요청을 ProductService로 넘긴다.

    실제 DB 처리 로직은 Controller가 직접 하지 않는다.

 

4) Model

 

    (1) Model의 역할

    Model은 데이터와 비즈니스 로직을 담당한다.

    이 프로젝트에서는 ProductService, ProductDao, Product VO가 Model에 해당한다.

 

    (2) Service

    Service는 기능 흐름과 트랜잭션 처리를 담당한다.

    DAO를 호출하고 결과에 따라 commit 또는 rollback을 수행한다.

 

    (3) DAO

    DAO는 DB에 직접 접근하는 클래스이다.

    SQL문을 실행하고 DB 결과를 Java 객체로 변환한다.

 

    (4) VO

    VO는 DB의 한 행 데이터를 Java 객체로 표현하는 클래스이다.

    PRODUCT 테이블의 한 행이 Product 객체 하나로 표현된다.


4 Product VO

1) Product 클래스의 역할

 

    (1) Product VO

    Product 클래스는 상품 정보를 담는 VO 클래스이다.

    PRODUCT 테이블의 P_ID, P_NAME, PRICE, DES 컬럼 값을 Java 객체로 관리한다.

 

    (2) DB 데이터와 Java 객체 연결

    DB에서 조회한 상품 한 행은 Product 객체 하나로 만들어진다.

    이렇게 하면 DB 데이터를 Java 코드에서 객체 형태로 다룰 수 있다.

 

2) 필드

 

    (1) pid

    pid는 상품 ID를 저장하는 필드이다.

    PRODUCT 테이블의 P_ID 컬럼과 연결된다.

 

    (2) pname

    pname은 상품명을 저장하는 필드이다.

    PRODUCT 테이블의 P_NAME 컬럼과 연결된다.

 

    (3) price

    price는 상품 가격을 저장하는 필드이다.

    PRODUCT 테이블의 PRICE 컬럼과 연결된다.

 

    (4) des

    des는 상품 설명을 저장하는 필드이다.

    PRODUCT 테이블의 DES 컬럼과 연결된다.

 

3) 생성자

 

    (1) 기본 생성자

    기본 생성자는 값을 넣지 않고 Product 객체를 만들 때 사용한다.

    객체를 먼저 만든 뒤 setter로 값을 넣을 수 있다.

 

    (2) 매개변수 생성자

    매개변수 생성자는 상품 ID, 상품명, 가격, 설명을 한 번에 받아 객체를 생성한다.

    DB에서 조회한 결과를 Product 객체로 만들 때 유용하다.

 

4) getter와 setter

 

    (1) getter

    getter는 private 필드 값을 외부에서 읽을 수 있게 해주는 메소드이다.

    예를 들어 getPid는 상품 ID를 반환한다.

 

    (2) setter

    setter는 private 필드 값을 외부에서 변경할 수 있게 해주는 메소드이다.

    예를 들어 setPrice는 상품 가격을 변경한다.

 

5) toString

 

    (1) toString의 역할

    toString은 객체 정보를 문자열로 표현하는 메소드이다.

    Product 객체를 출력했을 때 상품 정보가 보기 좋게 출력되도록 한다.


5 ProductView

1) ProductView의 역할

 

    (1) 화면 담당 클래스

    ProductView는 사용자에게 메뉴를 보여주고 입력을 받는 클래스이다.

    콘솔 기반 프로그램에서 사용자와 직접 만나는 부분이다.

 

    (2) Controller 사용

    ProductView는 ProductController 객체를 가지고 있다.

    사용자가 메뉴를 선택하면 Controller의 메소드를 호출해서 기능을 실행한다.

 

2) menu 메소드

 

    (1) 메뉴 출력

    menu 메소드는 전체출력, 선택출력, 추가, 수정, 삭제, 종료 메뉴를 출력한다.

    사용자는 번호를 입력해서 원하는 기능을 선택한다.

 

    (2) while 반복문

    while문은 사용자가 6번 종료를 선택할 때까지 메뉴를 반복해서 보여준다.

    프로그램을 한 번 실행한 뒤 여러 기능을 계속 사용할 수 있게 한다.

 

    (3) switch문

    switch문은 입력받은 번호에 따라 실행할 기능을 나눈다.

    1번은 전체출력, 2번은 선택출력, 3번은 추가, 4번은 수정, 5번은 삭제, 6번은 종료를 담당한다.

 

3) inputId 메소드

 

    (1) 제품 ID 입력

    inputId 메소드는 사용자에게 제품 ID를 입력받아 문자열로 반환한다.

    선택 조회나 삭제처럼 특정 상품 ID가 필요한 기능에서 사용된다.

 

    (2) 메소드로 분리한 이유

    제품 ID를 입력받는 코드는 여러 기능에서 반복된다.

    이를 inputId 메소드로 분리하면 중복을 줄이고 코드를 더 깔끔하게 만들 수 있다.

 

4) insertProduct 메소드

 

    (1) 추가할 상품 정보 입력

    insertProduct 메소드는 상품 ID, 상품명, 가격, 설명을 사용자에게 입력받는다.

    입력받은 값으로 Product 객체를 만들어 반환한다.

 

    (2) Product 객체 반환

    View는 입력값을 하나씩 Controller에 보내지 않고 Product 객체 하나로 묶어서 전달한다.

    상품 데이터가 하나의 객체로 이동하기 때문에 코드 구조가 깔끔해진다.

 

5) updateProduct 메소드

 

    (1) 수정할 정보 입력

    updateProduct 메소드는 수정할 상품 ID와 변경할 가격을 입력받는다.

    이 프로젝트에서는 상품의 가격만 수정하는 구조이다.

 

    (2) 수정용 Product 객체

    입력받은 ID와 가격을 Product 객체에 저장해서 반환한다.

    DAO에서는 이 객체의 pid로 수정 대상을 찾고, price로 변경값을 설정한다.


6 ProductController

1) ProductController의 역할

 

    (1) 요청 전달

    ProductController는 View에서 전달받은 요청을 Service로 넘기는 역할을 한다.

    사용자의 요청과 실제 처리 로직 사이를 연결한다.

 

    (2) 직접 DB 접근하지 않음

    Controller는 SQL을 실행하지 않는다.

    DB 작업은 Service와 DAO가 담당하고, Controller는 흐름만 제어한다.

 

2) 주요 메소드

 

    (1) selectAll

    selectAll은 전체 상품 조회 요청을 Service로 전달한다.

    결과로 Product 객체들이 담긴 List를 반환한다.

 

    (2) selectOne

    selectOne은 상품 ID를 받아 해당 상품 하나를 조회한다.

    조회 결과가 있으면 Product 객체를 반환하고, 없으면 null을 반환할 수 있다.

 

    (3) insert

    insert는 추가할 Product 객체를 받아 Service로 전달한다.

    추가 성공 여부를 int 값으로 반환한다.

 

    (4) update

    update는 수정할 Product 객체를 받아 Service로 전달한다.

    수정된 행의 개수를 결과로 반환한다.

 

    (5) delete

    delete는 삭제할 상품 ID를 받아 Service로 전달한다.

    삭제된 행의 개수를 결과로 반환한다.


7 ProductService

1) ProductService의 역할

 

    (1) 비즈니스 로직 담당

    ProductService는 Controller와 DAO 사이에서 기능 흐름을 관리한다.

    DB 연결을 생성하고 DAO를 호출한 뒤 결과에 따라 트랜잭션을 처리한다.

 

    (2) DAO 사용

    ProductService는 ProductDao 객체를 가지고 있다.

    실제 SQL 실행은 DAO에게 맡긴다.

 

2) 조회 기능

 

    (1) 전체 조회

    selectAll은 Connection을 생성한 뒤 dao.selectAll을 호출한다.

    조회 기능은 데이터를 변경하지 않으므로 commit이나 rollback이 필요하지 않다.

 

    (2) 선택 조회

    selectOne은 상품 ID를 받아 dao.selectOne에 전달한다.

    조회 결과로 Product 객체를 반환한다.

 

3) 변경 기능

 

    (1) insert

    insert는 DAO를 통해 상품 데이터를 추가한다.

    결과가 0보다 크면 commit하고, 그렇지 않으면 rollback한다.

 

    (2) update

    update는 DAO를 통해 상품 가격을 수정한다.

    수정 성공 시 commit하고 실패 시 rollback한다.

 

    (3) delete

    delete는 DAO를 통해 상품 데이터를 삭제한다.

    삭제 성공 시 commit하고 실패 시 rollback한다.

 

4) Connection 관리

 

    (1) Service에서 Connection 생성

    Service는 JDBCTemplate.getConnection을 사용해 Connection을 만든다.

    같은 기능 안에서 사용하는 DB 작업을 하나의 트랜잭션으로 묶기 위해 Service에서 Connection을 관리한다.

 

    (2) Service에서 Connection 종료

    DAO 작업이 끝나면 Service에서 Connection을 닫는다.

    Connection은 전체 DB 작업 흐름의 기준이 되므로 Service에서 마지막에 정리한다.


8 ProductDao

1) ProductDao의 역할

 

    (1) DB 접근 담당

    ProductDao는 PRODUCT 테이블에 직접 접근하는 클래스이다.

    SQL문을 작성하고 PreparedStatement를 사용해 실행한다.

 

    (2) DAO를 사용하는 이유

    DB 처리 코드를 DAO에 모아두면 Service나 View가 SQL문을 알 필요가 없다.

    SQL 변경이 필요할 때 DAO만 수정하면 되므로 유지보수가 쉬워진다.

 

2) PreparedStatement 사용

 

    (1) SQL 준비

    DAO에서는 con.prepareStatement(sql)을 사용해 PreparedStatement 객체를 만든다.

    SQL문 안의 ? 자리에 필요한 값을 넣은 뒤 실행한다.

 

    (2) 값 바인딩

    setString, setInt를 사용해 ? 자리에 값을 넣는다.

    상품 ID는 문자열이므로 setString을 사용하고, 가격은 숫자이므로 setInt를 사용한다.

 

3) ResultSet 처리

 

    (1) 조회 결과 받기

    SELECT문 실행 결과는 ResultSet으로 반환된다.

    DAO는 ResultSet에서 컬럼 값을 꺼내 Product 객체로 변환한다.

 

    (2) Product 객체 생성

    rs.getString, rs.getInt를 사용해 DB 컬럼 값을 가져온다.

    가져온 값으로 Product 객체를 생성해 View까지 전달할 수 있는 Java 데이터로 바꾼다.

 

4) 자원 해제

 

    (1) ResultSet 닫기

    SELECT 작업에서 사용한 ResultSet은 finally에서 닫는다.

    조회 결과 객체도 DB 자원을 사용하기 때문에 반드시 정리해야 한다.

 

    (2) PreparedStatement 닫기

    SQL 실행에 사용한 PreparedStatement도 finally에서 닫는다.

    Connection은 Service가 관리하므로 DAO에서는 닫지 않는다.


9 전체 조회 기능

1) 전체 조회 흐름

 

    (1) View

    사용자가 메뉴에서 1번 전체출력을 선택한다.

    ProductView는 controller.selectAll을 호출한다.

 

    (2) Controller

    ProductController는 service.selectAll을 호출한다.

    View의 요청을 Service로 전달하는 역할을 한다.

 

    (3) Service

    ProductService는 Connection을 생성하고 dao.selectAll을 호출한다.

    조회가 끝나면 Connection을 닫고 결과 List를 반환한다.

 

    (4) DAO

    ProductDao는 SELECT * FROM PRODUCT SQL문을 실행한다.

    조회된 여러 행을 Product 객체로 만들어 List에 담아 반환한다.

 

2) List 사용

 

    (1) List의 역할

    전체 조회는 상품이 여러 개 나올 수 있기 때문에 List<Product>를 사용한다.

    Product 객체 여러 개를 하나의 목록으로 담아 View에 전달한다.

 

    (2) ArrayList

    DAO에서는 ArrayList를 생성해 조회된 Product 객체를 순서대로 추가한다.

    ResultSet에서 한 행을 읽을 때마다 Product 객체 하나가 List에 추가된다.

 

3) 결과 출력

 

    (1) 데이터가 있는 경우

    List의 size가 0이 아니면 등록된 상품이 있다는 뜻이다.

    for문을 사용해 Product 객체를 하나씩 출력한다.

 

    (2) 데이터가 없는 경우

    List의 size가 0이면 등록된 제품이 없는 상태이다.

    View에서 등록된 제품이 없다는 메시지를 출력한다.


10 선택 조회 기능

1) 선택 조회 흐름

 

    (1) View

    사용자가 메뉴에서 2번 선택출력을 선택한다.

    ProductView는 inputId로 제품 ID를 입력받고 controller.selectOne을 호출한다.

 

    (2) Controller

    ProductController는 입력받은 ID를 service.selectOne으로 전달한다.

    특정 상품 하나를 조회하는 요청을 넘긴다.

 

    (3) Service

    ProductService는 Connection을 생성하고 dao.selectOne을 호출한다.

    조회 결과를 받은 뒤 Connection을 닫고 Product 객체를 반환한다.

 

    (4) DAO

    ProductDao는 SELECT * FROM PRODUCT WHERE P_ID=? SQL문을 실행한다.

    입력받은 ID를 ? 자리에 넣어 해당 상품만 조회한다.

 

2) Product 반환

 

    (1) 조회 성공

    ResultSet에 데이터가 있으면 Product 객체를 생성한다.

    해당 상품의 ID, 이름, 가격, 설명을 객체에 담아 반환한다.

 

    (2) 조회 실패

    ResultSet에 데이터가 없으면 Product 객체를 만들지 않는다.

    결과가 null이면 View에서 조회한 제품이 없다는 메시지를 출력한다.


11 추가 기능

1) 추가 흐름

 

    (1) View

    사용자가 메뉴에서 3번 추가를 선택한다.

    ProductView는 insertProduct를 호출해 상품 ID, 상품명, 가격, 설명을 입력받는다.

 

    (2) Controller

    ProductController는 입력받은 Product 객체를 service.insert로 전달한다.

    상품 추가 요청을 Service로 넘긴다.

 

    (3) Service

    ProductService는 Connection을 생성하고 dao.insert를 호출한다.

    결과가 0보다 크면 commit하고, 실패하면 rollback한다.

 

    (4) DAO

    ProductDao는 INSERT INTO PRODUCT VALUES(?,?,?,?) SQL문을 실행한다.

    Product 객체의 필드 값을 ? 자리에 바인딩한 뒤 executeUpdate로 실행한다.

 

2) executeUpdate 결과

 

    (1) 성공

    executeUpdate 결과가 0보다 크면 추가된 행이 있다는 뜻이다.

    Service에서 commit을 실행하고 View에는 Insert 성공 메시지가 출력된다.

 

    (2) 실패

    결과가 0이면 추가된 행이 없다는 뜻이다.

    Service에서 rollback을 실행하고 View에는 Insert 실패 메시지가 출력된다.


12 수정 기능

1) 수정 흐름

 

    (1) View

    사용자가 메뉴에서 4번 수정을 선택한다.

    ProductView는 수정할 제품 ID와 변경할 가격을 입력받는다.

 

    (2) Controller

    ProductController는 수정할 정보가 담긴 Product 객체를 service.update로 전달한다.

    수정 요청을 Service로 넘긴다.

 

    (3) Service

    ProductService는 Connection을 생성하고 dao.update를 호출한다.

    수정 결과가 0보다 크면 commit하고, 실패하면 rollback한다.

 

    (4) DAO

    ProductDao는 UPDATE PRODUCT SET PRICE = ? WHERE P_ID = ? SQL문을 실행한다.

    첫 번째 ?에는 변경할 가격을 넣고, 두 번째 ?에는 수정할 상품 ID를 넣는다.

 

2) 수정 대상

 

    (1) P_ID 기준

    상품 수정은 P_ID를 기준으로 대상을 찾는다.

    P_ID는 PRIMARY KEY이므로 하나의 상품을 정확히 찾는 기준이 된다.

 

    (2) PRICE 변경

    이 프로젝트의 수정 기능은 상품 가격만 변경한다.

    상품명이나 설명은 수정하지 않고, 입력받은 가격으로 PRICE 컬럼만 바꾼다.


13 삭제 기능

1) 삭제 흐름

 

    (1) View

    사용자가 메뉴에서 5번 삭제를 선택한다.

    ProductView는 inputId로 삭제할 제품 ID를 입력받는다.

 

    (2) Controller

    ProductController는 삭제할 ID를 service.delete로 전달한다.

    삭제 요청을 Service로 넘긴다.

 

    (3) Service

    ProductService는 Connection을 생성하고 dao.delete를 호출한다.

    삭제 결과가 0보다 크면 commit하고, 실패하면 rollback한다.

 

    (4) DAO

    ProductDao는 DELETE FROM PRODUCT WHERE P_ID = ? SQL문을 실행한다.

    ? 자리에는 삭제할 상품 ID를 넣는다.

 

2) 삭제 결과 처리

 

    (1) 삭제 성공

    executeUpdate 결과가 0보다 크면 해당 ID의 상품이 삭제된 것이다.

    View에서 Delete 성공 메시지를 출력한다.

 

    (2) 삭제 실패

    결과가 0이면 해당 ID를 가진 상품이 없거나 삭제되지 않은 것이다.

    View에서 Delete 실패 메시지를 출력한다.

 

3) CRUD 전체 흐름

 

    (1) 전체출력

    PRODUCT 테이블의 모든 상품을 조회한다.

 

    (2) 선택출력

    P_ID를 기준으로 상품 하나를 조회한다.

 

    (3) 추가

    사용자가 입력한 상품 정보를 PRODUCT 테이블에 INSERT한다.

 

    (4) 수정

    P_ID를 기준으로 상품을 찾아 PRICE 값을 UPDATE한다.

 

    (5) 삭제

    P_ID 기준으로 상품을 찾아 DELETE한다.