6주차 Unit 5.1 — 다양한 커넥션 획득 방식

Psj·2026년 5월 31일

F-lab

목록 보기
198/240

Unit 5.1 — 다양한 커넥션 획득 방식

F-LAB JAVA · 6주차 · Phase 5 · DataSource 인터페이스 (추상화의 진화)
🔌 Phase 5 시작 — 추상화로 가는 길


📌 학습 목표

이 Unit을 끝내면 다음을 답할 수 있어야 한다.

  • 커넥션 획득 방식이 다양한 이유는?
  • DriverManager 사용 방식은?
  • HikariCP 사용 방식은?
  • DBCP2 / Tomcat JDBC Pool 사용 방식은?
  • 사용법이 모두 다르다 는 문제는?
  • 커넥션 획득 방법 변경 시 코드 변경 범위는?
  • 5주차 ConnectionMaker 와 닮음 은?
  • 변경의 압력 이 코드에 전파되는 이유는?
  • 해결 방향 (추상화) 은?

🎯 핵심 한 문장

커넥션을 얻는 방법은 DriverManager·HikariCP·DBCP2·Tomcat JDBC Pool 등 다양한데 각자 API 사용법이 달라서 획득 방법이 바뀌면 애플리케이션 코드가 모두 바뀌어야 하며, 이는 5주차의 ConnectionMaker 인터페이스 도입과 똑같은 OCP 위반 문제다.
Connection 을 얻는 방법은 다양하다 — (1) DriverManager.getConnection() (매번 새로, 풀 X), (2) HikariCP (커넥션 풀), (3) DBCP2 (Apache 커넥션 풀), (4) Tomcat JDBC Pool (Tomcat 내장 풀).
문제는 각자 사용법이 다르다 는 것 — DriverManager.getConnection(url, ...)new HikariDataSource() + 설정 + getConnection() 은 코드가 전혀 다르다.
그래서 커넥션 획득 방법이 바뀌면 (예: DriverManager → HikariCP) 애플리케이션의 모든 DB 접근 코드 가 바뀌어야 한다.
이는 5주차의 ConnectionMaker 인터페이스 도입 직전과 똑같은 문제 — 구체에 강결합되어 변경 압력이 전파되는 OCP 위반 이며, 해결은 동일하다: 인터페이스로 추상화 (다음 Unit).

비유 — 가전마다 다른 충전기

다양한 커넥션 획득 = 가전마다 다른 충전기:

DriverManager:
  - 가전 A 전용 충전기
  - DriverManager.getConnection(url, ...)

HikariCP:
  - 가전 B 전용 충전기
  - new HikariDataSource(); .setJdbcUrl(); .getConnection();
  - 다른 모양

DBCP2:
  - 가전 C 전용 충전기

Tomcat JDBC Pool:
  - 가전 D 전용 충전기

문제:
  - 충전기 (커넥션 방식) 바꾸면
  - 가전 (애플리케이션) 의 모든 부품 (코드) 교체
  - 비효율

5주차 ConnectionMaker:
  - 표준 USB 정신
  - "어떤 충전기든 같은 포트"

해결 (다음 Unit):
  - DataSource (만능 어댑터)
  - 표준 인터페이스

→ 획득 방식 다양 + 사용법 제각각 → 변경 시 전체 영향 → 5주차 OCP 문제와 동일.


🧭 9개 섹션 로드맵

1. 다양한 획득 방식
2. DriverManager 사용
3. HikariCP 사용
4. DBCP2 / Tomcat 사용
5. 사용법이 모두 다름
6. 변경의 압력 전파
7. 5주차 ConnectionMaker와 닮음
8. OCP 위반
9. 면접 + 자기 점검

1️⃣ 다양한 획득 방식

1.1 4가지 방식

커넥션 획득 방식:

1. DriverManager
   - 매번 새 연결 (풀 X)
   - JDBC 기본

2. HikariCP
   - Spring Boot 기본
   - 가장 빠른 풀

3. DBCP2 (Apache)
   - 전통 풀

4. Tomcat JDBC Pool
   - Tomcat 내장 풀

1.2 각자 특성

각자 특성:

  DriverManager:
    - 풀 없음, 직접 연결
    - 학습/테스트용

  Pool 들 (HikariCP/DBCP2/Tomcat):
    - 미리 N개 (Phase 4)
    - 재사용
    - 운영 환경

1.3 선택 기준

선택 기준:

  - 운영 환경: 풀 사용
  - 단순/테스트: DriverManager
  - 성능: HikariCP
  - 레거시: DBCP2
  - Tomcat 통합: Tomcat JDBC Pool

1.4 ILIC 의 맥락

획득 방식 (ILIC)

ILIC 환경:
  - 운영: HikariCP (Spring Boot 기본)
  - 테스트: H2 + DriverManager 도 가능
  - 레거시 마이그레이션 시 DBCP2

  애플리케이션 코드:
    - 어떤 방식이든 결국 Connection 객체 필요
    - 하지만 획득 방법은 다름

  → 추상화 필요 (다음 Unit)

1.5 자기 점검 답변

커넥션 획득 방식이 다양한 이유는?

:
1. 4가지:

  • DriverManager/HikariCP/DBCP2/Tomcat
  1. 특성:

    • 풀 유무, 성능
  2. 선택:

    • 환경 따라
  3. 공통:

    • Connection 객체

2️⃣ DriverManager 사용

2.1 DriverManager

// DriverManager 사용
public Connection getConnection() throws SQLException {
    return DriverManager.getConnection(
        "jdbc:mysql://localhost:3306/ilic",
        "ilic_user",
        "password"
    );
}
// 매 호출마다 새 연결

2.2 특징

DriverManager 특징:

  - 풀 X (매번 새 연결)
  - 단순 (JDBC 표준)
  - 학습/테스트용
  - 운영 X (성능 ↓)

2.3 사용 패턴

// 사용 패턴
Connection c = DriverManager.getConnection(url, user, pwd);
try {
    // 사용
} finally {
    c.close();   // 진짜 close (TCP 종료)
}
// 다음 호출 또 새 연결

2.4 단점

DriverManager 단점:

  - 매번 연결 비용 (Unit 4.1)
  - 자원 관리 직접
  - 운영 부적합

→ 풀로 대체

2.5 ILIC 의 맥락

// DriverManager (ILIC 가 풀 없으면)
public class ShipmentDao {
    public Shipment get(Long id) throws Exception {
        // DriverManager — 매 요청마다 새 연결
        Connection c = DriverManager.getConnection(
            "jdbc:mysql://localhost:3306/ilic",
            "ilic_user",
            "password"
        );
        // ↑ TCP handshake + 인증 + 세션 (매번)
        try {
            // SQL 실행
        } finally {
            c.close();
            // ↑ TCP 종료 (매번)
        }
        return null;
    }
}
// → ILIC 의 431 API 마다 새 연결 → 성능 폭망
// → 실제는 풀 사용 (다음 섹션들)
class Shipment {}

2.6 자기 점검 답변

DriverManager 사용 방식은?

:
1. 사용:

  • DriverManager.getConnection(url, ...)
  1. 특징:

    • 풀 X, 매번 새 연결
  2. 단점:

    • 비용, 운영 부적합
  3. 용도:

    • 학습/테스트

3️⃣ HikariCP 사용

3.1 HikariCP 직접

// HikariCP 직접 사용 (Spring 없이)
HikariConfig config = new HikariConfig();
config.setJdbcUrl("jdbc:mysql://localhost:3306/ilic");
config.setUsername("ilic_user");
config.setPassword("password");
config.setMaximumPoolSize(20);

HikariDataSource ds = new HikariDataSource(config);

// 사용
Connection c = ds.getConnection();   // 풀에서 빌림
// 사용
c.close();   // 풀로 반환

3.2 vs DriverManager

HikariCP vs DriverManager:

DriverManager:
  - DriverManager.getConnection(url)
  - 매번 새 연결

HikariCP:
  - new HikariDataSource(config)
  - 풀에서 재사용

→ 코드가 다름!

3.3 풀 설정

풀 설정 (HikariCP):

  - maximumPoolSize
  - minimumIdle
  - connectionTimeout
  - idleTimeout

→ HikariConfig 객체

3.4 Spring Boot 자동

# Spring Boot 는 application.yml 만
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/ilic
    username: ilic_user
    password: password
    hikari:
      maximum-pool-size: 20
# Spring 이 HikariDataSource 자동 생성

3.5 ILIC 의 맥락

// HikariCP 직접 (ILIC 가 Spring 안 썼다면)
public class ShipmentDao {
    private final HikariDataSource dataSource;
    
    public ShipmentDao() {
        HikariConfig config = new HikariConfig();
        config.setJdbcUrl("jdbc:mysql://localhost:3306/ilic");
        config.setUsername("ilic_user");
        config.setPassword("password");
        config.setMaximumPoolSize(20);
        this.dataSource = new HikariDataSource(config);
    }
    
    public Shipment get(Long id) throws Exception {
        Connection c = dataSource.getConnection();   // 풀에서
        try {
            // SQL
        } finally {
            c.close();   // 풀로 반환
        }
        return null;
    }
}

// ILIC 는 Spring Boot (HikariCP 자동)
// → application.yml 만 설정
class HikariConfig {
    void setJdbcUrl(String s) {}
    void setUsername(String s) {}
    void setPassword(String s) {}
    void setMaximumPoolSize(int n) {}
}
class HikariDataSource {
    HikariDataSource(HikariConfig c) {}
    Connection getConnection() throws java.sql.SQLException { return null; }
}
class Shipment {}

3.6 자기 점검 답변

HikariCP 사용 방식은?

:
1. 사용:

  • new HikariDataSource(config)
  • getConnection()
  1. vs DriverManager:

    • 코드 다름
  2. 설정:

    • HikariConfig
  3. Spring:

    • 자동

4️⃣ DBCP2 / Tomcat 사용

4.1 DBCP2

// DBCP2 (Apache)
BasicDataSource ds = new BasicDataSource();
ds.setUrl("jdbc:mysql://localhost:3306/ilic");
ds.setUsername("ilic_user");
ds.setPassword("password");
ds.setMaxTotal(20);

// 사용
Connection c = ds.getConnection();

4.2 Tomcat JDBC Pool

// Tomcat JDBC Pool
org.apache.tomcat.jdbc.pool.DataSource ds 
    = new org.apache.tomcat.jdbc.pool.DataSource();
PoolProperties p = new PoolProperties();
p.setUrl("jdbc:mysql://localhost:3306/ilic");
p.setUsername("ilic_user");
p.setPassword("password");
p.setMaxActive(20);
ds.setPoolProperties(p);

// 사용
Connection c = ds.getConnection();

4.3 모두 다른 API

모두 다른 API:

  HikariCP:
    - HikariConfig + HikariDataSource
    - setMaximumPoolSize

  DBCP2:
    - BasicDataSource
    - setMaxTotal

  Tomcat:
    - DataSource + PoolProperties
    - setMaxActive

  → 같은 일, 다른 API

4.4 코드 변경 부담

코드 변경 부담:

  풀 교체 (HikariCP → DBCP2):
    - 설정 클래스 변경
    - 메서드 이름 변경
    - import 변경

→ 변경 광범위

4.5 ILIC 의 맥락

// 3가지 풀 비교 (ILIC, 같은 일 다른 API)

// HikariCP
HikariConfig hc = new HikariConfig();
hc.setJdbcUrl(url);
hc.setMaximumPoolSize(20);
HikariDataSource hikari = new HikariDataSource(hc);

// DBCP2
BasicDataSource dbcp = new BasicDataSource();
dbcp.setUrl(url);
dbcp.setMaxTotal(20);

// Tomcat JDBC Pool
org.apache.tomcat.jdbc.pool.DataSource tomcat 
    = new org.apache.tomcat.jdbc.pool.DataSource();
PoolProperties pp = new PoolProperties();
pp.setUrl(url);
pp.setMaxActive(20);
tomcat.setPoolProperties(pp);

// → 풀 바꾸면 코드 전부 다시 (애플리케이션 코드까지)
// → 5주차 OCP 위반
String url;
class HikariConfig { void setJdbcUrl(String s) {} void setMaximumPoolSize(int n) {} }
class HikariDataSource { HikariDataSource(HikariConfig c) {} }
class BasicDataSource { void setUrl(String s) {} void setMaxTotal(int n) {} }
class PoolProperties { void setUrl(String s) {} void setMaxActive(int n) {} }

4.6 자기 점검 답변

DBCP2 / Tomcat JDBC Pool 사용 방식은?

:
1. DBCP2:

  • BasicDataSource
  1. Tomcat:

    • DataSource + PoolProperties
  2. API:

    • 모두 다름
  3. 부담:

    • 변경 광범위

5️⃣ 사용법이 모두 다름

5.1 문제 요약

사용법이 모두 다름:

  DriverManager:
    DriverManager.getConnection(url, ...)

  HikariCP:
    new HikariConfig + new HikariDataSource

  DBCP2:
    new BasicDataSource

  Tomcat:
    new DataSource + PoolProperties

  → 코드 전부 달라

5.2 같은 목적

같은 목적, 다른 코드:

  목적: Connection 객체 획득

  방식: 모두 다름
    - 클래스
    - 설정
    - 메서드

→ 비효율

5.3 학습 부담

학습 부담:

  풀 라이브러리마다:
    - 새 API 학습
    - 다른 설정 방식
    - 다른 모니터링

→ 시간 낭비

5.4 코드 분산

코드 분산:

  애플리케이션 곳곳:
    - 풀 의존 코드 산재
    - 변경 시 모두 영향

→ 유지보수 ↓

5.5 ILIC 의 맥락

// 사용법 다름 (ILIC)

// ❌ 풀 의존 코드 (변경 광범위)
public class BadShipmentDao {
    private final HikariDataSource dataSource;   // HikariCP 직접
    
    public BadShipmentDao() {
        // HikariCP 전용 설정
        HikariConfig config = new HikariConfig();
        config.setJdbcUrl("...");
        this.dataSource = new HikariDataSource(config);
    }
    
    public Connection getConnection() throws Exception {
        return dataSource.getConnection();
    }
}

// HikariCP → DBCP2 변경 시:
// - HikariConfig → BasicDataSource
// - HikariDataSource → BasicDataSource
// - import 전부 변경
// - 모든 DAO 가 풀에 의존하면 → 모두 변경

// → 추상화 필요 (다음)
class HikariConfig { void setJdbcUrl(String s) {} }
class HikariDataSource {
    HikariDataSource(HikariConfig c) {}
    Connection getConnection() throws Exception { return null; }
}

5.6 자기 점검 답변

사용법이 모두 다르다는 문제는?

:
1. 사용법 다름:

  • 클래스/설정/메서드
  1. 같은 목적:

    • 다른 코드
  2. 학습 부담:

    • 풀마다
  3. 분산:

    • 코드 산재

6️⃣ 변경의 압력 전파

6.1 변경 압력

변경 압력:

  외부 변경 (풀 라이브러리):
    - 애플리케이션에 전파
    - 코드 변경 필요

→ 강결합 신호

6.2 전파 경로

전파 경로:

  HikariCP → DBCP2 변경:
    1. 설정 코드 변경
    2. 의존성 변경
    3. 사용 코드 변경 (getConnection 호출)
    4. 모니터링 코드 변경

→ 전 영역

6.3 5주차 OCP

5주차 OCP:

  "확장 열림, 변경 닫힘":
    - 풀 변경 = 변경 (위반)
    - 코드 전체 영향

→ OCP 위반

6.4 해결 원리

해결 원리 (5주차):

  인터페이스 추상화:
    - 풀에 의존 X
    - 인터페이스 의존
    - 풀은 외부 주입

→ DataSource (다음 Unit)

6.5 ILIC 의 맥락

// 변경 압력 전파 (ILIC, 추상화 없을 때)

// 100 개의 DAO 가 모두 HikariCP 직접 의존
public class ShipmentDao {
    private final HikariDataSource dataSource;   // 강결합!
}
public class BookingDao {
    private final HikariDataSource dataSource;   // 강결합!
}
// ... 100 개

// HikariCP → DBCP2 변경:
// → 100 개 DAO 전부 수정
// → 변경 압력 전파

// 5주차 정신:
// → 인터페이스 추상화 필요
// → DataSource (다음 Unit)
class HikariDataSource {}

6.6 자기 점검 답변

변경의 압력이 코드에 전파되는 이유는?

:
1. 변경 압력:

  • 외부 → 애플리케이션
  1. 전파 경로:

    • 설정/의존성/사용
  2. OCP:

    • 위반
  3. 해결:

    • 인터페이스

7️⃣ 5주차 ConnectionMaker와 닮음

7.1 5주차 복습

5주차 ConnectionMaker:

  처음:
    - UserDao 가 NConnectionMaker 직접
    - 구체에 강결합

  해결:
    - ConnectionMaker 인터페이스
    - 외부 주입

→ OCP 달성

7.2 같은 구조

같은 구조:

5주차 UserDao:
  - 구체 ConnectionMaker 의존 → 인터페이스 추상화

6주차 ShipmentDao:
  - 구체 풀 (HikariCP) 의존 → DataSource 추상화

→ 똑같은 패턴

7.3 매핑

5주차 ↔ 6주차 매핑:

5주차:
  - NConnectionMaker (구체)
  - ConnectionMaker (인터페이스)

6주차:
  - HikariDataSource (구체)
  - DataSource (인터페이스, 다음 Unit)

→ 같은 사상

7.4 자바 표준의 OCP

자바 표준에 녹은 OCP:

  자바 (javax.sql):
    - DataSource 인터페이스
    - JDBC 4.0+
    - 5주차 정신을 표준으로

→ OOP 원칙의 실제 사례

7.5 ILIC 의 맥락

// 5주차 ↔ 6주차 닮음 (ILIC)

// 5주차 (자체 추상화)
public interface ConnectionMaker {
    Connection makeConnection() throws Exception;
}

public class ShipmentDao5 {
    private final ConnectionMaker connectionMaker;   // 인터페이스
    public ShipmentDao5(ConnectionMaker cm) {
        this.connectionMaker = cm;
    }
}

// 6주차 (자바 표준 추상화 — DataSource)
public class ShipmentDao6 {
    private final DataSource dataSource;   // 자바 표준 인터페이스
    public ShipmentDao6(DataSource ds) {
        this.dataSource = ds;
    }
}

// → 5주차 ConnectionMaker = 6주차 DataSource
// → 같은 OCP/DIP 정신
// → 자바가 표준 인터페이스로 정착
interface DataSource {}

7.6 자기 점검 답변

5주차 ConnectionMaker 와 닮음은?

:
1. 5주차:

  • ConnectionMaker 인터페이스
  1. 6주차:

    • DataSource 인터페이스
  2. 같은 구조:

    • 구체 → 추상
  3. 자바 표준:

    • OCP 정신

8️⃣ OCP 위반

8.1 OCP 정의

OCP (개방-폐쇄 원칙):

  - 확장에 열림 (Open)
  - 변경에 닫힘 (Closed)

  새 기능: 추가
  기존 코드: 변경 X

8.2 현재 OCP 위반

현재 OCP 위반:

  풀 변경 (확장 가정):
    - HikariCP → DBCP2
    - 기존 코드 변경 (닫힘 위반)

→ OCP 위반

8.3 해결 = 추상화

해결 = 추상화:

  인터페이스 도입:
    - 새 풀 추가 (확장 ✅)
    - 기존 코드 그대로 (변경 X ✅)

→ OCP 준수

8.4 5주차 정신

5주차 정신:

  "변경에 닫히려면 추상화":
    - 인터페이스
    - 구체는 외부 주입
    - 코드는 인터페이스만

→ 다음 Unit (5.2)

8.5 ILIC 의 맥락

// OCP 위반 vs 준수 (ILIC)

// ❌ OCP 위반 (현재)
public class ShipmentDao {
    private final HikariDataSource dataSource;   // 구체!
    // HikariCP → DBCP2 변경 시 코드 수정 (변경에 열림 = OCP 위반)
}

// ✓ OCP 준수 (다음 Unit, DataSource)
public class ShipmentDaoGood {
    private final DataSource dataSource;   // 인터페이스!
    public ShipmentDaoGood(DataSource ds) {
        this.dataSource = ds;
    }
    // HikariCP → DBCP2 변경 시:
    // → 주입만 다르게 (코드 X)
    // → OCP 준수
}
class HikariDataSource {}
interface DataSource {}

8.6 자기 점검 답변

OCP 위반인 이유는?

:
1. OCP:

  • 확장 열림, 변경 닫힘
  1. 위반:

    • 풀 변경 → 코드 변경
  2. 해결:

    • 추상화
  3. 5주차:

    • 같은 정신

9️⃣ 면접 + 자기 점검

9.1 면접 단골 질문 매핑

Q핵심 답변
획득 방식 종류?DriverManager/HikariCP/DBCP2/Tomcat
DriverManager?풀 X, 매번
HikariCP?풀, 가장 빠름
사용법 다른가?모두 다름
변경 압력?코드 전파
5주차 닮음?ConnectionMaker
OCP 위반?풀 변경 → 코드
해결?인터페이스 (DataSource)
Spring?HikariCP 자동
강결합 신호?구체 의존

9.2 자기 점검 체크리스트

4가지 방식

  • 종류

DriverManager

  • 풀 X

HikariCP

  • 가장 빠름

DBCP2/Tomcat

  • API

사용법

  • 다름

변경 압력

  • 전파

5주차 닮음

  • ConnectionMaker

OCP

  • 위반

9.3 추가 심화 질문

Q1: c3p0?

답:

  • 오래된 풀
  • 한때 인기
  • 현재 HikariCP 에 밀림
  • 레거시

Q2: 풀 직접 vs 추상화?

답:

  • 직접: 강결합 (현재 Unit)
  • 추상화: 유연 (DataSource)
  • 거의 모든 케이스 추상화 권장
  • 변경 가능성

Q3: 외부 라이브러리 변경?

답:

  • 추상화 계층 있으면
  • 인터페이스 그대로
  • 어댑터 작성
  • 영향 최소

Q4: ConnectionFactory?

답:

  • 5주차 ConnectionMaker 유사
  • 일부 라이브러리 명명
  • Connection 생성 추상화
  • 팩토리 패턴

Q5: 추상화 비용?

답:

  • 학습 (간접 호출)
  • 약간의 성능
  • 보통 무시
  • 유연성 이득 > 비용

🎯 핵심 요약 — 3줄 정리

1. 획득 방식 다양

  • DriverManager (풀 X) / HikariCP / DBCP2 / Tomcat JDBC Pool
  • 각자 사용법 다름 (클래스/설정/메서드)

2. 변경 압력

  • 풀 변경 시 애플리케이션 코드 전부 영향
  • 5주차 ConnectionMaker 도입 직전과 동일 구조

3. OCP 위반과 해결

  • 구체 풀에 강결합 → OCP 위반
  • 해결: 인터페이스 추상화 (DataSource, 다음 Unit)

📚 다음으로...

Unit 5.2 — 추상화의 필요성

이번 Unit에서 다양한 획득 방식의 문제를 봤다면, 다음은 추상화 필요성 정리.

  • 변경 압력 차단
  • 인터페이스로 추상화
  • 5주차 정신
  • DataSource 도입 준비

Phase 5 진행 상황

🔌 Phase 5 — DataSource 인터페이스
  ✅ Unit 5.1 다양한 커넥션 획득 방식 ← 여기
  ⏭ Unit 5.2 추상화의 필요성
  ⏭ Unit 5.3 DataSource 인터페이스 ★깊이
  ⏭ Unit 5.4 DriverManagerDataSource

6주차 누적 진행

🧪 Part A (9 Unit) ✅
💾 Part B — DB 접근의 진화
  ✅ Phase 3 — JDBC (3)
  ✅ Phase 4 — Connection Pool (4)
  🔌 Phase 5 — DataSource (1/4)

총: 17/28 Unit

🔌 Phase 5 시작 — 추상화로 가는 길

profile
Software Developer

0개의 댓글