자바

week 12: DB & JDBC

aerimi-code 2025. 11. 16. 16:38

 

모든 프로그램은 데이터로 실행된다. 오늘은 이 데이터와 데이터를 다루는 개념을 알아보겠다.

 

이 그림에서 사용자는 데이터를 조회, 수정, 추가, 삭제하는 주체이다. 사용자는 DBMS에게 데이터 언어(SQL)를 사용하여 데이터를 처리하도록 명령을 내린다. 데이터베이스 관리 시스템(DBMS)는 사용자의 요청을 받아 데이터베이스를 실제로 관리하고, 요청된 작업을 수행한다. 

 

 

1. DB&DBMS

 

 

데이터베이스와 DBMS

데이터베이스: 거대한 엑셀 파일
- 여러 응용 시스템의 통합된 정보들을 저장하여 운영할 수 있는 공용 데이터들의 집합

- 데이터의 저장, 검색, 갱신을 효율적으로 수행할 수 있도록 고도로 조직화하여 저장

 

 

 

DBMS: 이 파일을 관리하고 보관하는 시스템 (MySQL, Oracle 등)

- 데이터베이스를 관리하는 시스템이다.

종류: 

관계형 DBMS

- 키와 값들의 관계를 테이블로 표현한 데이터베이스 모델

 

객체 지향 데이터베이스

- 정보를 객체의 형태로 표현하는 데이터베이스 모델

 

NoSQL, NewSQL DBMS

- 비정형 데이터를 처리하는데 적합


관계형 DB기본 용어에 대해 알아보자

 

관계형 DB에서는 테이블 형태로 데이터를 구성한다.

 

 

  • 릴레이션 (Relation): 하나의 개체에 관한 데이터를 저장하는 2차원 테이블 구조.
  • 속성(Attribute)/열(Column): 릴레이션의 열로, 데이터의 특징(예: 고객이름, 나이)을 나타냅니다.
  • 투플(Tuple)/행(Row): 릴레이션의 행으로, 하나의 레코드(개별 데이터, 예: 한 명의 고객 정보)를 표현합니다.
  • 도메인(Domain): 하나의 속성이 가질 수 있는 모든 값의 범위 또는 데이터타입(예: CHAR(20), INT)입니다.

 

 

2. SQL과 JDBC는 자바와 DB를 잇는 두 핵심 기술

 

데이터베이스를 조작하는 언어인 SQL과, 자바에서 DB에 접속하기 위한 표준 규약인 JDBC를 이해해보자

 

 

SQL (Structured Query Language)

  • 관계형 DBMS에서 사용하는 쿼리용 언어(원하는 정보나 작업을 요청하는 명령문)
  • 데이터베이스 스키마 생성, 자료의 검색, 관리, 수정 등을 맡는다.

(다수의 데이터베이스 관련 프로그램들이 SQL을 표준으로 채택)

 

JDBC (Java DataBase Connectivity)

  • 자바 애플리케이션이 데이터베이스에 연결하고 SQL문을 실행할 수 있도록 제공되는 표준 API
  • 과거에는 DB마다 접속 방식이 달랐지만, 자바가 통일된 JDBC 인터페이스를 제공하고 각 DB 제조사가 이에 맞는 JDBC 드라이버를 제공함으로써, 개발자는 드라이버만 교체하면 다양한 DB와 통신할 수 있게 되었다.

 

3. 데이터 조작의 기본: CRUD (데이터를 다루는 4가지 기능)

모든 데이터 처리 시스템의 근간이 되는 네 가지 핵심 기능

 

기능 설명 SQL 명령어 REST API (HTTP Method)
Create 데이터 생성 (추가) (사용자 등록) INSERT POST 
Read 데이터 조회 (사용자 목록 보기) SELECT GET 
Update 데이터 수정 (비밀번호 변경) UPDATE PUT 또는 PATCH 
Delete 데이터 삭제 (사용자 탈퇴) DELETE DELETE 

 

CRUD API:

- 기능을 HTTP 기반의 API로 제공하는 것.

- 데이터 베이스에 있는 데이터를 다른 시스템에서도 쉽게 다를 수 있게 만드는 인터페이스!

 

- CURD 프로그래밍: 데이터 생성,조회,수정,삭제 등 전체 흐름을 다루는 프로그램을 만든다.

 


4. JDBC 프로그래밍 핵심 5단계 (Feat. 코드 예시)
자바에서 DB와 통신하기 위한 표준적인 절차 5단계를 살펴보자!

 

1. JDBC 드라이버 로드 (Load Driver)

프로젝트 생성 후 build path로 JDBC 드라이버의 JAR파일을  추가하면 드라이버가 등록된다. 

 

2. 데이터베이스 연결 (Get Connection)

DriverManager를 통해 DB 서버 URL, 계정, 비밀번호를 사용하여 DB와 연결하고, Connection 객체를 반환 받는다.

 

Connection conn = DriverManager.getConnection(url, user, password);

 

try (Connection conn = DriverManager.getConnection(url,user,password))

이때 이렇게 try-with문을 쓰면 해당 Connection 객체는 try블록 내에서만 유효하게 존재하게 되며, 블록을 벗어나는 즉시 자동으로 닫힌다.  (리소스 해제까지 보장)

 

3. SQL 문 실행

conn(Connection 객체) 로부터 SQL을 실행할 수 있는 Statement 또는 PrepareStatement 객체를 생성한다.

 

[TIP] PreparedStatement을 사용하는 것을 권장. SQL을 미리 컴파일 하여 성능이 좋고, ?를 이용한 바인딩으로 SQL 인젝션 공격 을 원천적으로 방어할 수 있음! (바인딩을 통해 들어가는 값들은 오직 순수한 데이터로만 취)

=> SQL 문을 미리 준비하고 데이터는 나중에 바인딩! 성능 보안 이점

 

String insertsql="INSERT INTO student (no, dept, stdID, name) VALUES(?,?,?,?)";
PreparedStatement pstmt = conn.prepareStatement(insertsql);

 

1. SQL 문 정의

user table에 id, name, age를 추가하는 예시이다. (새로운 학생 기록 삽입)

  • insertsql은 실행할 SQL명령을 담고 있는 문자열 변수이다.
  • INSERT INTO student () 는 student 테이블에 새로운 행(row)를 삽입하는 SQL 구문이다.
  • ? : 바인딩 변수이고, 실제 값이 들어갈 홀더이다.
  • <- PrepareStatement는 이 물음표 자리에 나중에 setString(), setInt()등의 메서드를 사용하여 실제 데이터를 채워 넣는다. 

2. PreparedStatement 객체 생성

conn은 DB와 연결을 담당한다.

  • conn.prepareStatement(insertsql)을 통해 Connection객체의 메서드를 호출하여 PreapredStatement객체를 생성하고 반환한다.
  • 이 메서드가 호출되는 시점에, 데이터베이스는 insertsql에 있는 SQL 문을 받아서 구문 분석(Parsing)하고 미리 컴파일하여 실행 준비를 마친다. (앞서 설명한 성능 향상 및 보안 강화의 핵심).

3. 값 binding하기 

pstmt.setInt(1, 3);
pstmt.setString(2, "컴퓨터공학과");
pstmt.setString(3, "2466028");
pstmt.setString(4, "서예림");
pstmt.executeUpdate();
System.out.println("학생정보삽입성공!");

 

적절한 값을 넣어준다. 앞에 숫자는 인덱스 이다.

 

앞 단계에서 pstmt객체에 값을 넣어줬다면, 실제로 데이터 변경이나 조회 작업을 요청하고 결과를 받아온다.

 

*executeUpdate(): INSERT, UPDATE, DELETE 등 데이터 변경 SQL에 사용하고, 영향 받은 행의 수를 반환한다.

*executeQuery(): SELECT등 데이터 조회 SQL에 사용한다. 결과는 ResultSet 객체로 반환한다. 

 

결과: student 테이블 행에 내 정보를 추가했다. 

 

4. 결과 처리(Result Set)

SELECT문을 사용하여 데이터를 조회한다면 ResultSet객체를 처리해야한다.

String sql = "SELECT id,name,age FROM user WHERE id=?";
preparedStatement pstmt= conn.prepareStatement(sql);
pstmt.setString(1,"user01"); //바인딩 (물음표에 실제 값 설정)

try(ResultSet rs=pstmt.executeQuery())//SELECT 실행 및 ResultSet 반환
{

	if(rs.next()){
		String name=rs.getString("name");//"name" 컬럼의 값을 String으로 가져옴
        String age=rs.getInt("age");
        System.out.println("이름 "+name+", 나이 "+age);
        
    }
}

SQL 정의: user 테이블에서 id, name, age컬럼을 조회하는 SELECT 문을 정의한다. WHERE id=? 는 조회 조건을 특정 ID로 제한한다. 

바인딩: (1,"user01")은 SQL의 첫 번째 물음표에 문자열 "user01"을 실제 값으로 채워 넣는다. 

=> 최종적으로 실행될 SQL:  SELECT id,name,age FROM user WHERE id='user01'  (하나의 행을 반)

  • 테이블: user 테이블에서
  • 조건: id 컬럼의 값 'user01'인 행(row, 레코드)을 찾고,
  • 조회: 그렇게 찾은 행에서 id, name, age 세 가지 컬럼의 을 가져옴

 

 

어떻게 값을 가져오는 것일까?

ResultSet객체가 현재 위치한 행에서 원하는 데이터를 추출한다. 

값이 있을 경우, 컬럼을 getString("name")으로 지정한 후, 해당 컬럼 데이터를 String타입으로 변환하여 반환한다

 

 

5. 자원 해제 (Close)

만약 try-with 문을 쓰지 않았다면 resource close를 해줘야한다. 

이때, 사용한 객체를 사용한 역순으로 닫아 시스템의 자원 누수를 막아준다. 

 

  • Connection, PreparedStatement, ResultSet (ResultSet부터 close)

=> 따라서 try-with-resources 사용을 권장한다. 

 

 


#실습: 공유 DB에 접속하여 학과/학번/이름 남기기

 

 

 

String url="jdbc:mysql://192.168.0.13:3306/java2_3";
	 String user="stdUser";
	 String password="wkvmtlf2";
	 
	 //trywith
	 try (Connection conn = DriverManager.getConnection(url,user,password)){
		System.out.println("DB연결 성공!");
		
		String selectsql="SELECT * FROM student";
		Statement stmt=conn.createStatement();
		ResultSet rs=stmt.executeQuery(selectsql);
		
		while(rs.next()) {
			int no = rs.getInt("no");
			String dept=rs.getString("dept");
			String sid = rs.getString("stdID");
			String name=rs.getString("name");
			
			System.out.printf(" No: %d 학과 %s 학번: %s 이름: %s\n",no,dept,sid,name);
		}
		 //insert
		 String insertsql="INSERT INTO student (no, dept, stdID, name) VALUES(?,?,?,?)";
		 PreparedStatement pstmt = conn.prepareStatement(insertsql);
		 
		 pstmt.setInt(1, 3);
		 pstmt.setString(2, "컴퓨터공학과");
		 pstmt.setString(3, "2466028");
		 pstmt.setString(4, "서예림");
		 pstmt.executeUpdate();
		 System.out.println("학생정보삽입성공!");
		 
	}

 

 

해당 실습을 통해 다른 컴퓨터의 DB에 접근하여 테이블을 다룰 수 있었다. 

 


5. JDBC 프로그래밍의 품질 향상: SOLID와 패턴 적용

JDBC를 활용한 DB 연결 코드는 기초 같지만, 어떻게 설계하느냐에 따라 프로젝트 품질이 급상승한다.

 

SOLID 원칙 Factory 패턴 적용

 

단일 책임 SRP에 따라 각 객체의 역할을 명확히 분리한 후, 주입을 통해 코드의 유연성과 확장성을 확보한다.

클래스다이어그램

 

역할 클래스 이름 설명
학생 DAO StudentDao DB와 직접 통신하며, JDBC 관련 로직(CRUD 메서드)을 구현30.
모델 (DTO) Student 학생 테이블의 데이터를 담는 객체로, Getter/Setter만 존재31.
DB 연결 관리 DatabaseConnector DB 연결 정보 관리 및 Connection 객체만 제공 (연결 로직 분리)32.
 
메인 흐름 관리 StudentTest 모든 클래스를 조립하고 실행하는 메인 함수 역할33.
 

 

StudentDao는 connector를 주입받아 sudentDao의 메서드로 데이터 베이스에 접근할 수 있다. 

 

 


6. 애플리케이션에서 DB & JDBC 활용을 위한 권장 구조 정리:

디에서 다룬 내용을 기반으로 각 구성 요소의 역할을 명확히 설명해야 합니다.

구성 요소 역할  스터디 내용
Model View Controller (MVC) 전체 구조의 틀. 사용자 인터페이스(View), 핵심 로직(Model), 그리고 이 둘을 연결하는 제어(Controller)를 분리하여, 기능별 수정이 쉽고 유지보수가 용이 이번 DB 연동 코드는 주로 Model 영역(데이터 처리 로직)에 해당하며, 이 부분을 어떻게 잘게 쪼갤지 정리
DTO (Data Transfer Object) / Model 데이터 운반체. DB 테이블의 행(Row) 정보 1개를 담아 DB와 프로그램 계층 사이를 안전하게 전달하는 객체 (예: Student 클래스) 오직 Getter, Setter만 가지고 데이터를 '담는' 역할만 하는 단일 책임 원칙(SRP)의 적용 예시
DAO (Data Access Object) 데이터 접근 전문가. 오직 JDBC 코드(DB 접속, SQL 실행, Connection/Statement 관리)만을 담당하며, CRUD(Create, Read, Update, Delete) 메서드를 구현 가장 핵심적인 JDBC 로직이 위치하며, DB와 직접적으로 통신하는 창구의 역할
Service (또는 Business Logic) 비즈니스 로직 담당. 여러 개의 DAO를 조합하거나, 특정 비즈니스 규칙(예: 학점을 계산하거나, 중복 회원 가입을 체크하는)을 처리하는 핵심 기능을 담당 DAO 위에 한 겹 더 추가하여, 재사용성과 비즈니스 독립성을 높이기 위한 구조(StudentDao를 StudentService가 사용하는 형태)

 

 

 

1. DAO (Data Access Object): 데이터 접근 전문가

DAO는  데이터베이스와 직접 소통하는 역할만을 전담하는 객체 (  단일 책임 원칙(SRP) )

정의 데이터(DB)에 접근하는 로직만을 모아놓은 객체. 테이블마다 하나의 DAO를 만들 수 있다. (예: StudentDao, ProductDao).
포함 로직 오직 JDBC 관련 코드만 포함.
DB 연결/해제 (Connection 관리)
SQL 명령어 준비/실행 (PreparedStatement 사용)
결과 처리 (ResultSet을 DTO로 변환)
CRUD (Create, Read, Update, Delete) 메서드 구현
장점 역할 분리: 핵심 비즈니스 로직이 DB 접근 상세 내용에 오염되지 않음!
유지보수 용이: DB나 JDBC 코드가 변경되어도, DAO 내부만 수정하면 다른 애플리케이션 코드는 건드릴 필요가 없습니다.
테스트 용이: DB 연결 없이도 DAO를 쉽게 테스트(Mocking)할 수 있는 기반이 됩니다.
실습내용  StudentDao를 만들어 학생(Student) 데이터의 CRUD 작업을 전담
이 과정에서 PreparedStatement를 사용하여 SQL Injection을 방지하는 보안성 확보

 

2. MVC (Model-View-Controller) 패턴: 구조적 설계의 기본

MVC 패턴은 애플리케이션의 세 가지 핵심 기능을 나누어 분리하고 관리하는 소프트웨어 디자인 패턴

 

DAO, DTO, Service 계층은 모두 MVC 패턴의 Model 영역

구성 요소 역할 (DB/JDBC) 비유
Model (모델) 데이터와 비즈니스 로직을 담당. DB와 소통하고 데이터를 처리하는 모든 로직이 이 영역에 해당합니다. 주방 (요리 레시피와 재료 처리)
View (뷰) 사용자에게 보여지는 부분. HTML, JSP, Swing UI 등 최종 화면 출력을 담당. 식당 홀 (손님에게 음식을 보여주는 곳)
Controller (컨트롤러) 사용자의 요청을 받아 모델과 뷰를 연결하고 제어. "사용자가 버튼을 눌렀다"는 요청을 받으면, 모델에게 데이터를 처리하도록 지시하고, 결과를 뷰에 전달합니다. 매니저 (손님의 주문을 받고 주방에 전달)

 

 

 

  • Service: 비즈니스 로직 (Model의 최상위 계층)
  • DAO: 데이터 처리 로직 (Model의 하위 계층, DB 담당)
  • DTO: 데이터 운반체 (Model의 구성 요소)

 


어려웠던 점:  데이터 베이스를 처음 다뤄봐서 용어들이 헷갈렸었는데, 스터디 하면서 정확하게 이해 되었다. 

특히, SQL 과  JDBC (통역사)의 역할을 정확히 구분함으로써, 자바 애플리케이션이 DB와 어떻게 소통하는지 그 구조적인 이해도를 높일 수 있었다. 

 

다음 실습에서 적용하고 싶은 점:

이번 스터디에서 DAO, DTO, Service 계층 분리를 통해 DB 로직을 Model 영역에 캡슐화하는 방법을 배웠다.

다음 실습에서는 이 캡슐화된 DB 로직을 기반으로, 실제로 사용자가 정보를 입력하는 과정(View/Controller)과 프로그램이 이 데이터를 처리하여 DB에 저장하는 과정(Model/DAO)을 통합해 보고 싶다.

'자바' 카테고리의 다른 글

week14: CRUD  (0) 2025.11.29
week10: 자바 네트워크  (0) 2025.11.09
week9.java GUI_Swing, Event 실습  (0) 2025.11.02
week5: 자바 SOLID원칙  (0) 2025.10.03
week4: 자바 Thread -2  (0) 2025.10.01