6주차 Unit 5.2 — 추상화의 필요성

Psj·2026년 6월 1일

F-lab

목록 보기
199/239

Unit 5.2 — 추상화의 필요성

F-LAB JAVA · 6주차 · Phase 5 · DataSource 인터페이스 (추상화의 진화)


📌 학습 목표

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

  • 추상화의 필요성 은?
  • 변경 압력 차단 의 의미는?
  • 5주차 OCP 정신 의 적용은?
  • 애플리케이션이 인터페이스에만 의존 한다는 것은?
  • "커넥션 획득 방법 자체를 인터페이스로" 의 의미는?
  • 5주차 ConnectionMaker 와 6주차 DataSource 는 같은 사상?
  • 추상화의 효과 (유연성/테스트/교체) 는?
  • DIP (의존 역전) 적용은?
  • DataSource 도입 준비 는?

🎯 핵심 한 문장

추상화는 변경의 압력이 애플리케이션 코드까지 전파되지 않도록 차단하는 장치로, "커넥션을 얻는 방법" 자체를 인터페이스로 만들면 애플리케이션은 인터페이스에만 의존하고 구체 풀(HikariCP·DBCP2 등)은 외부에서 주입받게 되며, 이는 5주차 ConnectionMaker 와 정확히 같은 사상이다.
추상화가 필요한 이유는 — 풀 라이브러리 (HikariCP, DBCP2 등) 가 바뀔 때마다 애플리케이션의 DB 접근 코드가 모두 바뀌는 OCP 위반 문제 (Unit 5.1) 를 해결하기 위해서다.
5주차에서 본 OCP 정신과 동일한 해결책 — 인터페이스로 추상화 하여 변경의 압력을 인터페이스 경계에서 차단하면 애플리케이션은 인터페이스에만 의존하고 구체 구현이 바뀌어도 영향받지 않는다.
해결의 방향은 "커넥션을 얻는 방법" 자체를 인터페이스로 분리 하는 것 — 5주차의 ConnectionMaker 가 한 그 역할을 자바 표준으로 끌어올린 것이 DataSource (다음 Unit) 다.
5주차의 ConnectionMaker 와 6주차의 DataSource같은 사상의 다른 이름 으로, 5주차에 자체적으로 만든 추상화가 사실 자바 표준 라이브러리에 이미 존재했음을 깨닫는 지점이다.

비유 — 표준 USB 포트 도입

추상화 = 표준 USB 포트:

문제 (Unit 5.1):
  - 가전마다 다른 충전기 (HikariCP/DBCP2/...)
  - 가전(애플리케이션) 이 충전기 모양에 강결합
  - 충전기 바꾸면 가전도 바꿔야

추상화 (표준 USB):
  - 표준 포트 (인터페이스)
  - 가전은 포트만 알면 됨
  - 충전기는 외부에서

변경 압력 차단:
  - 새 충전기 나와도 (HikariCP → DBCP2)
  - 표준 USB 호환이면
  - 가전 그대로

5주차 ConnectionMaker = USB:
  - 자체 표준 정의
  
6주차 DataSource = 자바 표준 USB:
  - 업계 표준 (javax.sql)

DIP:
  - 가전 → 표준 USB → 충전기
  - 가전이 충전기 직접 의존 X

→ 추상화 = 변경 압력 차단 (인터페이스 경계), 5주차 ConnectionMaker = 6주차 DataSource.


🧭 9개 섹션 로드맵

1. 추상화의 필요성
2. 변경 압력 차단
3. 5주차 OCP 정신
4. 인터페이스 의존
5. "획득 방법 자체를 인터페이스로"
6. ConnectionMaker = DataSource
7. 추상화의 효과
8. DIP 적용
9. 면접 + 자기 점검

1️⃣ 추상화의 필요성

1.1 왜 필요한가

추상화 필요:

  Unit 5.1 문제:
    - 풀 변경 → 코드 변경
    - OCP 위반
    - 변경 광범위

  → 변경 압력 차단 필요

1.2 추상화의 본질

추상화의 본질:

  세부 사항 숨김:
    - "무엇" 만 노출
    - "어떻게" 는 숨김

  → 의존을 줄임

1.3 변경의 격리

변경의 격리:

  변경 가능한 부분:
    - 추상화 뒤로
    - 인터페이스 뒤로

  애플리케이션:
    - 인터페이스만 의존
    - 변경 모름

1.4 ILIC 의 맥락

추상화 필요 (ILIC)

ILIC 현재 (가정, 풀 직접 의존):
  - 102 테이블 DAO 가 HikariDataSource 직접
  - HikariCP → DBCP2 변경 시 102 개 수정

추상화 (DataSource):
  - DAO 는 DataSource (인터페이스) 의존
  - HikariCP/DBCP2 외부 주입
  - 풀 변경 시 주입만 다르게
  - DAO 코드 그대로

→ 추상화로 변경 격리

1.5 자기 점검 답변

추상화의 필요성은?

:
1. :

  • 변경 압력 차단
  1. 본질:

    • 세부 숨김
  2. 격리:

    • 변경을 추상화 뒤로
  3. 결과:

    • 의존 ↓

2️⃣ 변경 압력 차단

2.1 변경 압력

변경 압력:

  외부 변경:
    - 새 풀 라이브러리
    - 라이브러리 업그레이드
    - 요구사항 변경

  → 코드에 압력

2.2 차단 = 인터페이스

차단 = 인터페이스:

  인터페이스가 방벽:
    - 변경: 인터페이스 뒤
    - 애플리케이션: 인터페이스 앞
    - 차단

→ 변경이 못 넘어옴

2.3 시각화

변경 압력 차단:

  변경 ────→ |인터페이스| ┃ 애플리케이션
                ↑           ┃
                            ┃ ← 영향 X
              (방벽)

  - 변경은 인터페이스 뒤 구현
  - 인터페이스는 그대로
  - 애플리케이션 영향 X

2.4 변경 가능 영역

변경 가능 영역:

  추상화 뒤:
    - 자유롭게 바뀜
    - 새 구현 추가
    - 구현 교체

  추상화 앞 (애플리케이션):
    - 안정
    - 인터페이스만 알면 됨

2.5 ILIC 의 맥락

// 변경 압력 차단 (ILIC)

// 인터페이스 (방벽)
interface DataSource {
    Connection getConnection() throws Exception;
}

// 애플리케이션 (변경 압력 받지 않음)
public class ShipmentDao {
    private final DataSource dataSource;   // 인터페이스만
    
    public ShipmentDao(DataSource ds) {
        this.dataSource = ds;
    }
    // → 풀 라이브러리 변경 무관
}

// 구현 (변경 가능 영역)
class HikariDataSource implements DataSource {
    public Connection getConnection() { return null; }
}
class DbcpDataSource implements DataSource {
    public Connection getConnection() { return null; }
}
// HikariDataSource → DbcpDataSource 교체:
// → ShipmentDao 그대로
// → 주입만 다르게

2.6 자기 점검 답변

변경 압력 차단의 의미는?

:
1. 변경 압력:

  • 외부 변경 → 코드
  1. 차단:

    • 인터페이스 방벽
  2. 시각화:

    • 변경 못 넘어옴
  3. 영역:

    • 추상화 앞/뒤

3️⃣ 5주차 OCP 정신

3.1 OCP 정신

5주차 OCP:

  "확장 열림, 변경 닫힘"

  - 확장: 새 구현 추가 (열림)
  - 변경: 기존 코드 변경 X (닫힘)

→ 추상화로 달성

3.2 OCP 달성

OCP 달성:

  새 풀 추가 (확장 ✅):
    - 새 DataSource 구현
    - 애플리케이션 코드 변경 X (닫힘 ✅)

→ OCP 준수

3.3 5주차 패턴 재등장

5주차 패턴 재등장:

  - OCP
  - DIP
  - 전략 패턴
  - 인터페이스 추상화

→ 모두 적용

3.4 자바 표준의 OOP

자바 표준의 OOP:

  자바 라이브러리:
    - OCP 정신 구현
    - DataSource 가 그 예
    - 5주차 정신을 표준화

→ 좋은 라이브러리 = 좋은 OOP

3.5 ILIC 의 맥락

// 5주차 OCP 정신 (ILIC)

// 5주차 ConnectionMaker (OCP)
interface ConnectionMaker {
    Connection makeConnection() throws Exception;
}
// 새 구현 추가 (확장)
class NewConnectionMaker implements ConnectionMaker {
    public Connection makeConnection() { return null; }
}

// 6주차 DataSource (자바 표준, 같은 OCP)
interface DataSource {
    Connection getConnection() throws Exception;
}
// 새 풀 추가 (확장)
class CustomDataSource implements DataSource {
    public Connection getConnection() { return null; }
}

// 애플리케이션:
public class ShipmentDao {
    private final DataSource ds;
    public ShipmentDao(DataSource ds) { this.ds = ds; }
    // OCP 준수: 새 DataSource 와도 호환
}

// → 5주차 정신 = 6주차 자바 표준

3.6 자기 점검 답변

5주차 OCP 정신의 적용은?

:
1. OCP:

  • 확장/변경
  1. 달성:

    • 새 풀 확장, 코드 그대로
  2. 재등장:

    • 5주차 패턴
  3. 자바 표준:

    • OOP 구현

4️⃣ 인터페이스 의존

4.1 인터페이스 의존

애플리케이션 → 인터페이스:

  구체 풀 의존 X:
    - HikariCP/DBCP2 모름

  인터페이스만:
    - DataSource (다음 Unit)
    - getConnection() 만 안다

4.2 구체는 모름

구체는 모름:

  애플리케이션:
    - DataSource.getConnection()
    - 반환된 Connection 사용

  실제 구현:
    - HikariCP? DBCP2? 알 필요 X
    - 외부가 결정

4.3 외부에서 주입

외부에서 주입:

  애플리케이션:
    - 인터페이스만 의존
    - 구체는 외부 (DI)

  → 5주차 DI

4.4 코드의 단순함

코드의 단순함:

  애플리케이션 코드:
    - 인터페이스 메서드만
    - 짧고 명확
    - 풀 설정 X (외부)

4.5 ILIC 의 맥락

// 인터페이스 의존 (ILIC)
@Service
public class ShipmentService {
    private final ShipmentDao shipmentDao;
    
    public ShipmentService(ShipmentDao dao) {
        this.shipmentDao = dao;
    }
    // ShipmentService 는 ShipmentDao 만 알면 됨
    // ShipmentDao 가 어떤 풀 쓰는지 X
}

@Repository
public class ShipmentDao {
    private final DataSource dataSource;   // 인터페이스
    
    public ShipmentDao(DataSource ds) {
        this.dataSource = ds;
    }
    // ShipmentDao 는 DataSource 만 알면 됨
    // 구체 풀 X (Spring 이 주입)
    
    public Connection getConn() throws Exception {
        return dataSource.getConnection();   // 인터페이스 메서드
    }
}

// 구체 (외부, Spring Boot 자동)
// HikariDataSource 가 DataSource 구현
// → ShipmentDao 는 모름 (그저 DataSource)
interface DataSource {
    Connection getConnection() throws Exception;
}

4.6 자기 점검 답변

애플리케이션이 인터페이스에만 의존한다는 것은?

:
1. 인터페이스 의존:

  • 구체 모름
  1. 구체:

    • 외부 결정
  2. 주입:

    • DI
  3. 이점:

    • 단순, 안정

5️⃣ "획득 방법 자체를 인터페이스로"

5.1 핵심 통찰

핵심 통찰:

  "커넥션을 얻는 방법" 자체를
  인터페이스로 분리.

  - 행위 (얻기) 를 인터페이스
  - 구현 (어떻게 얻나) 는 자유

5.2 행위의 추상화

행위의 추상화:

  Connection 얻는 행위:
    - getConnection()
    - 단 하나의 메서드
    - 모든 풀 공통

→ 공통 행위 추출

5.3 다양한 구현

다양한 구현:

  같은 행위 (getConnection):
    - DriverManager 가 직접
    - HikariCP 가 풀에서
    - DBCP2 가 풀에서
    - Mock 이 가짜로 (테스트)

→ 인터페이스 → N 개 구현

5.4 자바 표준화

자바 표준화:

  javax.sql.DataSource:
    - 자바가 표준화
    - 모든 풀 구현
    - 다음 Unit 5.3 (★깊이)

5.5 ILIC 의 맥락

// "획득 방법 자체를 인터페이스로" (ILIC)

// 인터페이스 (획득 방법 추상화)
interface DataSource {
    Connection getConnection() throws Exception;
    // 단 하나의 핵심 메서드
    // "어떻게 얻든 상관없이, 얻어다오"
}

// 다양한 구현 (어떻게 얻는지 다름)

// 1. DriverManager 로 (풀 X)
class DriverManagerDataSource implements DataSource {
    private final String url;
    public DriverManagerDataSource(String url) { this.url = url; }
    public Connection getConnection() throws Exception {
        return DriverManager.getConnection(url);
    }
}

// 2. HikariCP 로 (풀)
// HikariDataSource implements DataSource (Hikari 제공)

// 3. Mock (테스트)
class MockDataSource implements DataSource {
    public Connection getConnection() {
        return null;   // 가짜
    }
}

// 애플리케이션: 어느 구현이든 OK
ShipmentDao dao = new ShipmentDao(/* 어떤 DataSource든 */);
class ShipmentDao { ShipmentDao(DataSource ds) {} }

5.6 자기 점검 답변

"커넥션 획득 방법 자체를 인터페이스로" 의 의미는?

:
1. 핵심 통찰:

  • 행위 자체를 추상화
  1. 행위:

    • getConnection() 하나
  2. 구현:

    • 다양 (어떻게)
  3. 자바 표준:

    • DataSource

6️⃣ ConnectionMaker = DataSource

6.1 같은 사상

ConnectionMaker = DataSource:

  같은 사상의 다른 이름:
    - 5주차 자체 정의
    - 6주차 자바 표준

→ 같은 추상화

6.2 매핑

5주차6주차 (자바 표준)
ConnectionMakerDataSource
makeConnection()getConnection()
NConnectionMakerHikariDataSource
DConnectionMakerDriverManagerDataSource

6.3 깨달음

깨달음:

  5주차에서:
    - 자체 ConnectionMaker 정의

  6주차에서:
    - 자바가 이미 DataSource 로
    - 우리 추상화가 표준 그 자체

→ "내가 만든 게 사실 표준이었다"

6.4 표준의 가치

표준의 가치:

  자바 표준 (DataSource):
    - 모든 풀이 구현
    - 호환성
    - 다른 라이브러리도 알아봄

  자체 추상화:
    - 한 프로젝트 안에서만

→ 표준 사용 권장

6.5 ILIC 의 맥락

// 5주차 ConnectionMaker = 6주차 DataSource (ILIC)

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

// 6주차 (자바 표준)
// import javax.sql.DataSource;
interface DataSource {
    Connection getConnection() throws Exception;
}

// 메서드 이름만 다름, 사상 동일

// ILIC:
// - 5주차 정신을 6주차에선 자바 표준으로
// - HikariCP / DriverManagerDataSource 등 모두 DataSource 구현
// - ShipmentDao 는 DataSource 만 의존

// → 자체 추상화 학습이 자바 표준 이해의 기반

6.6 자기 점검 답변

5주차 ConnectionMaker 와 6주차 DataSource 는 같은 사상?

:
1. 같은 사상:

  • 추상화 정신 동일
  1. 매핑:

    • ConnectionMaker = DataSource
  2. 깨달음:

    • 자체 = 자바 표준
  3. 권장:

    • 표준 사용

7️⃣ 추상화의 효과

7.1 효과 정리

추상화 효과:

1. 유연성 (풀 교체)
2. 테스트 (Mock)
3. 결합도 ↓
4. 확장성
5. 변경 격리

7.2 유연성

유연성:

  풀 교체:
    - 주입만 다르게
    - 코드 그대로

  환경별:
    - prod: HikariCP
    - test: H2 + DriverManagerDataSource

7.3 테스트

// 테스트 (Mock 주입)
@Test
void test() {
    DataSource mockDs = mock(DataSource.class);
    Connection mockConn = mock(Connection.class);
    when(mockDs.getConnection()).thenReturn(mockConn);
    
    ShipmentDao dao = new ShipmentDao(mockDs);
    // 실제 DB 없이 테스트
}
// 추상화 덕분에 Mock 주입 가능

7.4 환경별

환경별 구현:

  운영: HikariDataSource
  테스트: 인메모리 DB (H2)
  단위 테스트: Mock

  → 환경 따라 주입만 다르게

7.5 ILIC 의 맥락

// 추상화 효과 (ILIC)

// 1. 환경별 (Spring 프로파일)
@Configuration
@Profile("prod")
class ProdDataSourceConfig {
    @Bean DataSource dataSource() {
        // HikariCP (운영)
        return null;
    }
}

@Configuration
@Profile("test")
class TestDataSourceConfig {
    @Bean DataSource dataSource() {
        // H2 (테스트)
        return null;
    }
}

// 2. 단위 테스트
class ShipmentDaoTest {
    @Test
    void test() {
        DataSource mock = mock(DataSource.class);   // Mock
        ShipmentDao dao = new ShipmentDao(mock);
        // DB 없이 테스트
    }
}

// 3. 새 풀 도입 시
// - 새 DataSource 구현
// - 빈 등록만
// - 코드 변경 X
class ShipmentDao { ShipmentDao(DataSource ds) {} }

7.6 자기 점검 답변

추상화의 효과 (유연성/테스트/교체) 는?

:
1. 효과:

  • 유연/테스트/교체
  1. 유연성:

    • 주입만
  2. 테스트:

    • Mock
  3. 환경별:

    • 프로파일

8️⃣ DIP 적용

8.1 DIP

DIP (의존 역전 원칙):

  "고수준 모듈은 저수준 모듈에 의존 X
   둘 다 추상에 의존"

  → 추상화 가운데

8.2 적용

DIP 적용:

  고수준: 애플리케이션 (ShipmentDao)
  저수준: 구체 풀 (HikariDataSource)

  추상: DataSource (인터페이스)

  - ShipmentDao → DataSource ← HikariDataSource

8.3 의존 방향 역전

의존 방향 역전:

전 (DIP 위반):
  ShipmentDao → HikariDataSource
  (고수준 → 저수준)

후 (DIP 준수):
  ShipmentDao → DataSource ← HikariDataSource
  (둘 다 추상 의존)

8.4 5주차 DIP

5주차 DIP 복습:

  UserDao → ConnectionMaker ← NConnectionMaker

6주차 적용:
  ShipmentDao → DataSource ← HikariDataSource

→ 같은 DIP, 다른 인터페이스 이름

8.5 ILIC 의 맥락

// DIP 적용 (ILIC)

// 추상 (인터페이스, 가운데)
interface DataSource {
    Connection getConnection() throws Exception;
}

// 고수준 (애플리케이션) — 추상 의존
public class ShipmentDao {
    private final DataSource ds;   // 추상
    public ShipmentDao(DataSource ds) { this.ds = ds; }
}

// 저수준 (구체 풀) — 추상 구현
class HikariDataSource implements DataSource {
    public Connection getConnection() { return null; }
}
class DbcpDataSource implements DataSource {
    public Connection getConnection() { return null; }
}

// 의존 방향:
// ShipmentDao → DataSource ← HikariDataSource
// 둘 다 추상을 가리킴 (DIP)

// 의존 역전: 풀이 애플리케이션을 안 알아도 OK
// 풀이 인터페이스에 맞춤 (역전)

8.6 자기 점검 답변

DIP (의존 역전) 적용은?

:
1. DIP:

  • 둘 다 추상 의존
  1. 적용:

    • 애플리케이션/풀 → DataSource
  2. 역전:

    • 의존 방향
  3. 5주차:

    • 같은 원리

9️⃣ 면접 + 자기 점검

9.1 면접 단골 질문 매핑

Q핵심 답변
추상화 필요?변경 압력 차단
변경 압력 차단?인터페이스 방벽
5주차 정신?OCP, DIP
인터페이스 의존?구체 모름
획득 방법 추상화?getConnection 하나
ConnectionMaker=DataSource?같은 사상
효과?유연/테스트/교체
DIP?둘 다 추상
표준 가치?호환성
5주차 vs 6주차?자체 vs 표준

9.2 자기 점검 체크리스트

필요성

차단

  • 방벽

OCP

  • 적용

인터페이스 의존

  • 구체 모름

획득 방법

  • 자체 추상화

Maker=DataSource

  • 같음

효과

  • 3가지

DIP

  • 의존 역전

9.3 추가 심화 질문

Q1: 추상화 vs 캡슐화?

답:

  • 추상화: 본질 노출, 세부 숨김
  • 캡슐화: 데이터 + 메서드 묶음, 접근 제어
  • 보완 관계
  • 둘 다 OOP 핵심

Q2: 추상 클래스 vs 인터페이스?

답:

  • 추상 클래스: 일부 구현 가능
  • 인터페이스: 계약만 (Java 8+ default 가능)
  • 다중 상속 (인터페이스)
  • DataSource = 인터페이스

Q3: SOLID 와 자바 표준?

답:

  • 자바 표준에 SOLID 녹아있음
  • DataSource = OCP/DIP
  • Comparator = 전략 패턴
  • 학습 좋은 사례

Q4: 추상화 누수?

답:

  • Leaky Abstraction
  • 구현 세부가 인터페이스로 새어 나옴
  • 완전한 추상화 어려움
  • 최소화 노력

Q5: 의존성 방향?

답:

  • 안정 → 불안정 (피함)
  • 추상 ← 구체 (가리킴)
  • DIP 핵심
  • 패키지 설계

🎯 핵심 요약 — 3줄 정리

1. 추상화 = 변경 압력 차단

  • 풀 라이브러리 변경이 애플리케이션 코드까지 전파되지 않게
  • 인터페이스가 방벽 (변경은 인터페이스 뒤에서만)

2. 5주차 OCP 정신의 적용

  • 인터페이스로 추상화 → 새 풀 추가 (확장), 기존 코드 그대로 (닫힘)
  • "커넥션 획득 방법 자체를 인터페이스로" → DataSource

3. ConnectionMaker = DataSource

  • 5주차 자체 추상화 = 6주차 자바 표준 (같은 사상)
  • 좋은 라이브러리는 좋은 OOP 원칙의 집약체

📚 다음으로...

Unit 5.3 — DataSource 인터페이스 ★깊이

이번 Unit에서 추상화 필요성을 봤다면, 다음은 DataSource 인터페이스 (★ 깊이 파기).

  • javax.sql.DataSource
  • getConnection() 하나의 핵심 메서드
  • HikariDataSource, BasicDataSource 등 구현체
  • Spring DataSource 자동 주입
  • SOLID DIP 의 실체

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 (2/4)

총: 18/28 Unit

profile
Software Developer

0개의 댓글