코딩짜는 일상

[현대이지웰 Java 풀스택 개발자 아카데미 6월] TIL 7주차 - JDBC를 이용한 JAVA의 데이터베이스 접근과 DTO, DAO를 도입하기 위한 구조도 본문

TIL

[현대이지웰 Java 풀스택 개발자 아카데미 6월] TIL 7주차 - JDBC를 이용한 JAVA의 데이터베이스 접근과 DTO, DAO를 도입하기 위한 구조도

Remily 2025. 8. 26. 23:47
반응형

📚 서론

이번주는 JDBC를 사용해 자바와 데이터베이스를 연결해 사용하는 방법에 대해 포스팅 해보겠습니다.

 

JDBC는 자바 표준 SQL 인터페이스로, 각 DBMS 밴더에서 제공하는 드라이버를 통해

쿼리를 컴파일(최적화)하기 때문에 실행속도가 빠릅니다.

 

자바에선 표준 인터페이스를 이용해 단순히 쿼리만 주면 되니까 사용이 간편하고 추후 DB를 바꾸는 것도 쉽습니다.

JAVA와 DB사이에서 통역사같은 JDBC

 

이러한 JDBC를 이용해 테이블에 새로운 행을 추가(INSERT)하는 예제를 만들어 보겠습니다.

 

 

 

 

 

🎷 사용자 DB 연결 클래스 만들기

DB에 연결하기위해선 Connection 인터페이스를 이용해 DB 연결 객체를 생성해야 합니다.

 

이것을 DB에 쿼리를 전달하기 위한 소통 창구라고 생각하시면 편합니다.

 

저기요~ 제 쿼리 좀 실행해 주시겠어요? 출처:giphy

 

하지만 이 연결 객체를 무작정 무한히 만들 순 없습니다.

 

DBMS는 생겨난 객체만큼 클라이언트가 있다고 인식하기 때문에

쿼리를 전달할 때마다 연결 객체를 생성하면 그만큼 허비되는 리소스가 커집니다.😥

 

 

그래서 DB 연결 객체를 하나만 만들어 다른 곳에서도 인수로 전달받아 사용할 것이고

그렇게되면 Main클래스가 가장 적당하겠지만 이것은 DB에 연결하는 계정 정보도 필요하기에

보안을 위해서 별도의 클래스를 만들어 보겠습니다.

 

import java.sql.Connection;
import java.sql.DriverManager;

public class DBConnect {
	public Connection getConnection() {
		Connection con = null;
		
		try {
			String url = "연결할 DB주소";
			String user = "연결할 계정";
			String pwd = "비밀번호";
			con = DriverManager.getConnection(url, user, pwd);
			
			if(con != null) {
				System.out.println("DB연결 성공");
			} else {
				System.out.println("DB연결 실패");
			}
		} catch(Exception e) {
			e.printStackTrace();
		}
		return con;
	}
}

 

먼저 Connection 인터페이스를 이용해 빈 연결 객체를 만들어주고

DriverMavager 클래스를 이용해 주소와 계정, 비밀번호를 전달하여 연결을 생성해 담아줍니다.

그 후 연결이 성공하면 생성된 DB 연결 객체를 반환해주는 DBConnect 클래스를 만들어 봤습니다.

 

이렇게 하면 Connection으로 만든 DB 연결 객체인 con을 반환받을 수 있으니까

Main 클래스는 이 클래스의 getConnection 메서드를 사용해 DB 연결 객체를 반환받을 수 있습니다!

 

import java.sql.Connection;

public class DBConnMain {
	public static void main(String[] args) {
    	Connection con = null;
        
        // 사용자 정의 클래스(DBConnect)객체 생성
        DBConnect dbCon = new DBConnect();
        // 만들어진 객체 dbCon으로 메서드 getConnection을 사용해
        // DB와의 연결을 생성하고 con변수에 담기
        con = dbCon.getConnection();
	}
}

 

 

 

 

 

🎺 기능 구현을 위한 구조도

보안을 위해 DB 연결정보가 담긴 연결 객체 생성 클래스를 따로 만들었고 그걸 Main에서 끌어 쓸 수 있게 되었습니다.

남은 건 이제 INSERT 쿼리를 DB에 전달하고 제대로 실행 되었는지 확인하는 것 뿐이죠!

 

 

그런데 이걸 Main 클래스에 전부 작성하려고 하니 한 가지 고민이 생깁니다.🤔

 

이번 포스팅에선 분량 관계상 INSERT만 다룰 것이지만 데이터베이스를 다루는 기본은 CRUD.

즉, 추가(INSERT), 읽기(SELECT), 수정(UPDATE), 삭제(DELETE)입니다.

 

추후 기능을 확장할 때 Main 클래스에 이 모든 걸 구현하려면 매우 복잡해지겠죠...?😥

 

 

이때 사용할 수 있는 것이 DAO(Data Access Object), DTO(Data Transfer Object) 입니다.

 

DAO에 DB와 직접 통신하는 모든 코드를 모아둠으로써

사용자에게 서비스를 제공하게 될 로직과 DB 접근 로직을 분리할 수 있고

 

DTO를 이용해 표준화된 데이터 구조체를 만들어 클래스 또는 메서드에 인수로 전달하면

릴레이션의 튜플처럼 획일화된 형태를 하고 있어서 데이터 관리가 용이합니다.

 

 

대략적인 구조를 그려보자면 아래와 같습니다.

DAO와 DTO를 추가한 구조도

 

이렇게 하면 Main에선 사용자의 요청에 따라 어떤 서비스가 필요한지 판단만 하고

DAO에 처리를 요청한 다음, 결과 데이터를 받으면 그것을 출력하기만 하면 됩니다.

 

 

그런데 추가(INSERT)를 하려면 사용자에게 값을 입력 받아야 하는데

DAO는 데이터베이스에 접근이 필요한 작업에 대해서만 기능을 구현하는 클래스 입니다.

 

그럼 따로 사용자 입력값을 받을 클래스를 추가해야겠죠?😎

사용자 입력값을 받을 클래스 추가

 

이렇게 클래스를 분리해서 사용자 입력값을 받고

그 입력값을 DTO로 전달해 표준화된 데이터 객체를 얻어서

DAO에 전달하면 DAO는 그것을 토대로 INSERT 쿼리를 DB에 전달합니다.🤗

 

 

그런데 여기서 또 고민이 생깁니다!?😫

 

현재는 테이블 하나에 대해서 CRUD 기능을 구현했지만

나중에 또 다른 테이블이 추가되면 어쩌죠?

완전히 동일하지만 테이블 이름과 컬럼만 다른 시스템을 복제해야 할까요?🤯

 

 

이때 사용할 수 있는 것이 인터페이스Interface다형성입니다.

 

인터페이스로 DAO에 어떤 메서드가 필수로 존재해야 하는지 강제하고

DAO는 인터페이스를 상속 받아 구체적인 기능을 구현하도록 한다면

 

새로 추가된 테이블에 맞춰 DAO와 DTO만 새로 구현해주고

Main에선 해당인터페이스 타입의 변수에 사용할테이블의 DAO로 객체를 생성해주면 됩니다!

인터페이스를 추가해 확장성을 높인 구조도

InterfaceDAO dao = new 테이블1DAO(); // 인터페이스타입 변수 생성 예시

 

이렇게 하면 테이블을 바꿔서 실행하고 싶을  때마다 객체를 생성할 DAO만 바꿔서 변수에 새로 넣어주면

Main클래스의 서비스를 제공하는 로직은 그대로 두고 테이블만 바꿔서 동일한 기능을 쓸 수 있는거죠!🥳🎉

 

지지난주 정리했던 다형성! 출처:unsplash

 

 

 

 

 

🔥 결론

중요한 계정 정보나 실제 DB에 적용할 쿼리에 대한 정보를 서비스로직에 노출하지 않기 위해

DAO와 DTO의 역활이 확실히 중요한 것 같습니다.

 

물론 그만큼 계층이 다양해져서 절차지향적으로만 코딩하던 저는 낯설기만 합니다.

그만큼 구조도를 많이 그려보고 다양하게 확장시켜봐야겠네요.

 

꾸준히 다양한 구조도를 그려봐야겠어요. 출처:giphy

반응형