5주차 Unit 5.2 — 팩토리 메소드 패턴

Psj·2026년 5월 27일

F-lab

목록 보기
170/240

Unit 5.2 — 팩토리 메소드 패턴

F-LAB JAVA · 5주차 · Phase 5 · 디자인 패턴의 적용


📌 학습 목표

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

  • 팩토리 메소드 패턴 의 정의는?
  • 객체 생성을 서브클래스에 위임 하는 의미는?
  • getConnection 이 팩토리 메소드인 이유는?
  • 같은 코드가 두 패턴으로 해석되는 이유는?
  • 템플릿 메소드 vs 팩토리 메소드 의 관점 차이는?
  • 팩토리 메소드의 구조 는?
  • 단순 팩토리 vs 팩토리 메소드 의 차이는?
  • Spring BeanFactory 의 Factory 와의 관련은?
  • 팩토리 메소드의 장점 은?

🎯 핵심 한 문장

팩토리 메소드 패턴은 객체 생성을 서브클래스에 위임하는 패턴으로, Phase 4.3 의 getConnection() 은 "어떤 Connection 을 만들지 결정" 하므로 팩토리 메소드이며, 같은 코드가 관점에 따라 템플릿 메소드 패턴이면서 동시에 팩토리 메소드 패턴으로 해석된다.
팩토리 메소드는 객체를 생성하는 메서드를 추상화하여, 부모는 "객체가 필요하다" 는 사실만 알고 어떤 구체 객체를 만들지는 서브클래스가 결정 하게 한다.
Phase 4.3 의 getConnection() 은 Connection 객체를 생성하는데, 어떤 종류 (MySQL·Oracle) 의 Connection 을 만들지 서브클래스가 결정하므로 객체 생성을 서브클래스에 위임 하는 팩토리 메소드다.
흥미롭게도 같은 코드가 두 패턴으로 해석된다 — "기본 흐름 + 변하는 부분" 관점에서는 템플릿 메소드, "객체 생성을 서브클래스가 결정" 관점에서는 팩토리 메소드다.
Spring 의 BeanFactory 이름에 "Factory" 가 붙은 것도 같은 맥락 — 빈 (객체) 의 생성을 책임지는 팩토리 역할을 하기 때문이다.

비유 — 같은 그림, 두 관점

같은 코드, 두 패턴 = 착시 그림:

같은 그림이 두 가지로 보임:
  - 어떻게 보면 토끼
  - 어떻게 보면 오리

Phase 4.3 의 getConnection:
  - 흐름 관점: 템플릿 메소드
    "흐름은 부모, 빈칸은 자식"
  - 생성 관점: 팩토리 메소드
    "객체 생성을 자식이 결정"

팩토리 메소드 (생성 위임):
  - 부모: "Connection 이 필요해"
  - 자식: "MySQL Connection 만들게"
        "Oracle Connection 만들게"

  → 객체 만드는 책임을 자식에게

BeanFactory:
  - 빈(객체) 만드는 공장
  - "Factory" = 객체 생성 담당

→ 팩토리 메소드 = 객체 생성을 서브클래스에 위임, 같은 코드가 두 패턴으로.


🧭 9개 섹션 로드맵

1. 팩토리 메소드 패턴의 정의
2. 객체 생성 위임
3. getConnection이 팩토리 메소드
4. 같은 코드, 두 패턴
5. 두 패턴의 관점 차이
6. 팩토리 메소드 구조
7. 단순 팩토리 vs 팩토리 메소드
8. BeanFactory의 Factory
9. 면접 + 자기 점검

1️⃣ 팩토리 메소드 패턴의 정의

1.1 정의

팩토리 메소드 패턴:

  객체 생성을 서브클래스에 위임.

  - 부모: 객체 필요 (어떤 건 모름)
  - 자식: 구체 객체 생성 결정

1.2 GoF 패턴

GoF 디자인 패턴:

  생성 패턴 (Creational):
    - 객체 생성 추상화

  "객체 생성 인터페이스 정의,
   인스턴스화는 서브클래스가"

1.3 의도

의도:

  - 객체 생성 분리
  - 구체 클래스 의존 ↓
  - 확장 (새 객체 = 새 서브클래스)
  - 생성 로직 캡슐화

1.4 ILIC 의 맥락

// 팩토리 메소드 패턴
public abstract class ShipmentDao {
    
    public void add(Shipment s) throws Exception {
        Connection c = getConnection();   // 팩토리 메소드 호출
        // 어떤 Connection? 자식이 만듦
    }
    
    // 팩토리 메소드 (객체 생성을 자식이)
    protected abstract Connection getConnection() throws Exception;
}

// 자식이 구체 Connection 생성 결정
class MySqlShipmentDao extends ShipmentDao {
    protected Connection getConnection() throws Exception {
        // MySQL Connection 생성 (팩토리)
        return DriverManager.getConnection(
            "jdbc:mysql://localhost/ilic", "root", "password");
    }
}

1.5 자기 점검 답변

팩토리 메소드 패턴의 정의는?

:
1. 정의:

  • 객체 생성을 서브클래스에 위임
  1. GoF:

    • 생성 패턴
  2. 의도:

    • 생성 분리
    • 확장
  3. 부모/자식:

    • 부모: 필요
    • 자식: 생성

2️⃣ 객체 생성 위임

2.1 위임

객체 생성 위임:

  부모:
    - 객체 사용 (생성 X)
    - "이 객체가 필요해"

  자식:
    - 객체 생성
    - "이렇게 만들어"

2.2 부모는 추상 타입

부모는 추상 타입:

  부모는 인터페이스/추상에 의존:
    - Connection (인터페이스)
    - 구체 (MySQL Connection) 모름

  → 구체 클래스 분리

2.3 생성 캡슐화

생성 캡슐화:

  객체 생성 로직:
    - 팩토리 메소드 안
    - 캡슐화

  사용처:
    - new 직접 X
    - 팩토리 메소드 호출

2.4 new 의 문제

new 의 문제:

  직접 new:
    - 구체 클래스 의존
    - 강한 결합

  팩토리 메소드:
    - 생성 분리
    - 결합 ↓

2.5 ILIC 의 맥락

// 객체 생성 위임

// ❌ 직접 new (강한 결합)
public class ShipmentDaoBad {
    public void add(Shipment s) throws Exception {
        // 구체 클래스 직접 생성 (결합)
        Connection c = DriverManager.getConnection(
            "jdbc:mysql://localhost/ilic", "root", "password");
        // MySQL 에 묶임
    }
}

// ✓ 팩토리 메소드 (생성 위임)
public abstract class ShipmentDaoGood {
    public void add(Shipment s) throws Exception {
        Connection c = getConnection();   // 위임
        // 구체 모름
    }
    // 생성을 자식에게 위임
    protected abstract Connection getConnection() throws Exception;
}

2.6 자기 점검 답변

객체 생성을 서브클래스에 위임하는 의미는?

:
1. 위임:

  • 부모: 사용
  • 자식: 생성
  1. 부모:

    • 추상 타입 의존
  2. 캡슐화:

    • 생성 로직 숨김
  3. new 문제:

    • 강한 결합 회피

3️⃣ getConnection이 팩토리 메소드

3.1 왜 팩토리 메소드

getConnection 이 팩토리 메소드:

  getConnection():
    - Connection 객체 생성
    - "어떤 Connection 만들지" 결정
    - 자식이 구체 결정

→ 객체 생성 위임 = 팩토리 메소드

3.2 생성하는 객체

생성하는 객체:

  getConnection 의 반환:
    - Connection (추상)
    - 구체: MySQL/Oracle Connection

  → 객체를 만들어 반환
  → 팩토리

3.3 서브클래스 결정

// 서브클래스가 어떤 Connection 만들지 결정
class MySqlShipmentDao extends ShipmentDao {
    protected Connection getConnection() {
        // MySQL Connection 생성
        return null;
    }
}
class OracleShipmentDao extends ShipmentDao {
    protected Connection getConnection() {
        // Oracle Connection 생성
        return null;
    }
}
// 같은 getConnection, 다른 객체 생성

3.4 팩토리 메소드 관점

팩토리 메소드 관점:

  getConnection:
    - 이름은 "get" 이지만
    - 실제로 Connection 생성
    - 어떤 구체 생성? 자식

→ 본질은 팩토리 메소드

3.5 ILIC 의 맥락

// getConnection = 팩토리 메소드 관점
public abstract class ShipmentDao {
    
    public void add(Shipment s) throws Exception {
        // 팩토리 메소드로 Connection 객체 획득
        Connection c = getConnection();
        // ShipmentDao 는 어떤 구체 Connection 인지 모름
    }
    
    // 팩토리 메소드 — Connection 객체 생성 위임
    protected abstract Connection getConnection() throws Exception;
}

// 각 자식이 구체 Connection 객체 생성
class CustomerAShipmentDao extends ShipmentDao {
    protected Connection getConnection() throws Exception {
        // 고객사 A 의 Connection 객체 생성 (MySQL)
        return DriverManager.getConnection(
            "jdbc:mysql://customerA/ilic", "userA", "passA");
    }
}
// getConnection 이 객체 생성을 책임 → 팩토리 메소드

3.6 자기 점검 답변

getConnection이 팩토리 메소드인 이유는?

:
1. 이유:

  • Connection 객체 생성
  • 자식이 구체 결정
  1. 생성 객체:

    • Connection (추상)
  2. 서브클래스 결정:

    • MySQL/Oracle
  3. 본질:

    • 객체 생성 위임

4️⃣ 같은 코드, 두 패턴

4.1 두 패턴 동시

같은 코드 = 두 패턴:

Phase 4.3 의 코드:

  템플릿 메소드 관점:
    - 흐름(부모) + 변동(자식)

  팩토리 메소드 관점:
    - 객체 생성을 자식이 결정

4.2 add 메서드 관점

add 메서드 관점 (템플릿 메소드):

  add():
    - 연결 → SQL → 해제 (흐름)
    - getConnection 만 자식
    - = 템플릿 메소드

4.3 getConnection 관점

getConnection 관점 (팩토리 메소드):

  getConnection():
    - Connection 객체 생성
    - 자식이 구체 결정
    - = 팩토리 메소드

4.4 동시 성립

동시 성립:

  add (템플릿) 안에서
  getConnection (팩토리) 호출

  → 한 코드가 두 패턴
  → 관점의 차이

4.5 ILIC 의 맥락

public abstract class ShipmentDao {
    
    // [템플릿 메소드 관점]
    // add = 변하지 않는 흐름 (템플릿 메서드)
    public void add(Shipment s) throws Exception {
        Connection c = getConnection();   // [팩토리 메소드 호출]
        PreparedStatement ps = c.prepareStatement("insert ...");
        ps.executeUpdate();
        ps.close(); c.close();
        // add: 흐름 고정 → 템플릿 메소드
    }
    
    // [팩토리 메소드 관점]
    // getConnection = Connection 객체 생성 위임 (팩토리 메소드)
    protected abstract Connection getConnection() throws Exception;
}

// 같은 코드:
// - add 를 보면 → 템플릿 메소드 패턴
// - getConnection 을 보면 → 팩토리 메소드 패턴

4.6 자기 점검 답변

같은 코드가 두 패턴으로 해석되는 이유는?

:
1. 두 패턴:

  • 템플릿 + 팩토리
  1. add 관점:

    • 흐름 + 변동 (템플릿)
  2. getConnection 관점:

    • 객체 생성 (팩토리)
  3. 동시:

    • 관점의 차이

5️⃣ 두 패턴의 관점 차이

5.1 관점 차이

관점 차이:

템플릿 메소드:
  - "흐름의 일부를 자식이"
  - 알고리즘 골격
  - 행위 패턴

팩토리 메소드:
  - "객체 생성을 자식이"
  - 객체 생성
  - 생성 패턴

5.2 강조점

강조점:

템플릿 메소드:
  - 전체 흐름 강조
  - getConnection 은 일부

팩토리 메소드:
  - 객체 생성 강조
  - getConnection 이 핵심

5.3 분류

항목템플릿 메소드팩토리 메소드
GoF 분류행위생성
강조흐름객체 생성
추상 메서드흐름 일부객체 생성
관점알고리즘인스턴스화

5.4 실제 관계

실제 관계:

  팩토리 메소드는
  템플릿 메소드의 특수 형태로 봄:

  - 템플릿 메소드의 추상 메서드가
  - 객체 생성이면
  - 팩토리 메소드

5.5 ILIC 의 맥락

public abstract class ShipmentDao {
    public void add(Shipment s) throws Exception {
        Connection c = getConnection();
        // ...
    }
    protected abstract Connection getConnection() throws Exception;
}

// 관점 1: 템플릿 메소드
//   - add 의 흐름이 핵심
//   - getConnection 은 흐름의 한 단계

// 관점 2: 팩토리 메소드
//   - getConnection 의 객체 생성이 핵심
//   - Connection 인스턴스화를 자식이

// 두 관점 모두 유효 (같은 코드)

5.6 자기 점검 답변

템플릿 메소드 vs 팩토리 메소드의 관점 차이는?

:
1. 관점:

  • 템플릿: 흐름
  • 팩토리: 객체 생성
  1. GoF:

    • 행위 vs 생성
  2. 강조:

    • 알고리즘 vs 인스턴스화
  3. 관계:

    • 팩토리는 템플릿의 특수 형태

6️⃣ 팩토리 메소드 구조

6.1 구조

팩토리 메소드 구조:

[Creator (추상)]
  - factoryMethod() (추상)
  - someOperation() (팩토리 사용)
        ↑
[ConcreteCreator]
  - factoryMethod() 구현
        ↓ 생성
[Product]

6.2 4가지 요소

4가지 요소:

1. Product (제품 인터페이스)
   - Connection

2. ConcreteProduct (구체 제품)
   - MySQL Connection

3. Creator (추상 생성자)
   - ShipmentDao

4. ConcreteCreator (구체 생성자)
   - MySqlShipmentDao

6.3 매핑

요소ILIC
ProductConnection
ConcreteProductMySQL/Oracle Connection
CreatorShipmentDao (추상)
ConcreteCreatorMySqlShipmentDao
factoryMethodgetConnection

6.4 코드

// Creator (추상)
public abstract class ShipmentDao {
    // factoryMethod
    protected abstract Connection getConnection() throws Exception;
    
    // 팩토리 메소드 사용
    public void add(Shipment s) throws Exception {
        Connection c = getConnection();   // Product 획득
    }
}

// ConcreteCreator
class MySqlShipmentDao extends ShipmentDao {
    protected Connection getConnection() throws Exception {
        return DriverManager.getConnection(...);   // ConcreteProduct
    }
}

6.5 ILIC 의 맥락

// 팩토리 메소드 구조 (ILIC)

// Product: Connection (JDBC 인터페이스)

// Creator (추상)
public abstract class ShipmentDao {
    // factoryMethod
    protected abstract Connection getConnection() throws Exception;
    
    public void add(Shipment shipment) throws Exception {
        Connection c = getConnection();   // 팩토리 메소드 사용
        // ...
    }
}

// ConcreteCreator 들
class MySqlShipmentDao extends ShipmentDao {       // ConcreteCreator
    protected Connection getConnection() throws Exception {
        return DriverManager.getConnection(         // ConcreteProduct (MySQL)
            "jdbc:mysql://localhost/ilic", "root", "password");
    }
}
class OracleShipmentDao extends ShipmentDao {      // ConcreteCreator
    protected Connection getConnection() throws Exception {
        return DriverManager.getConnection(         // ConcreteProduct (Oracle)
            "jdbc:oracle:thin:@localhost:1521:ilic", "ilic", "pass");
    }
}

6.6 자기 점검 답변

팩토리 메소드의 구조는?

:
1. 4요소:

  • Product/ConcreteProduct
  • Creator/ConcreteCreator
  1. 매핑:

    • Connection / ShipmentDao
  2. factoryMethod:

    • getConnection
  3. 구조:

    • Creator → factoryMethod → Product

7️⃣ 단순 팩토리 vs 팩토리 메소드

7.1 단순 팩토리

단순 팩토리 (Simple Factory):

  하나의 팩토리 클래스/메서드:
    - 조건 분기로 생성
    - if-else / switch

  엄밀히는 패턴 X (관용구)

7.2 단순 팩토리 코드

// 단순 팩토리 (분기)
public class ConnectionFactory {
    public static Connection create(String dbType) {
        if (dbType.equals("mysql")) {
            return mysqlConnection();
        } else if (dbType.equals("oracle")) {
            return oracleConnection();
        }
        // 새 DB → 이 메서드 수정 (OCP X)
        throw new IllegalArgumentException();
    }
}

7.3 팩토리 메소드

// 팩토리 메소드 (서브클래스)
public abstract class ShipmentDao {
    protected abstract Connection getConnection();   // 서브클래스가
}
// 새 DB → 새 서브클래스 (OCP 향)

7.4 비교

항목단순 팩토리팩토리 메소드
생성분기 (if-else)서브클래스
확장메서드 수정서브클래스 추가
OCP위반부분 준수
GoFX (관용구)O (패턴)

7.5 ILIC 의 맥락

// 단순 팩토리 (분기 — OCP X)
public class ConnectionFactory {
    public static Connection create(String type) throws Exception {
        return switch (type) {
            case "mysql" -> DriverManager.getConnection(
                "jdbc:mysql://localhost/ilic", "root", "pass");
            case "oracle" -> DriverManager.getConnection(
                "jdbc:oracle:thin:@localhost:1521:ilic", "ilic", "pass");
            default -> throw new IllegalArgumentException();
            // 새 DB → 여기 수정
        };
    }
}

// 팩토리 메소드 (서브클래스 — OCP 향)
public abstract class ShipmentDao {
    protected abstract Connection getConnection() throws Exception;
    // 새 DB → 새 서브클래스 (수정 X)
}

7.6 자기 점검 답변

단순 팩토리 vs 팩토리 메소드의 차이는?

:
1. 단순 팩토리:

  • 분기 (if-else)
  • 관용구
  1. 팩토리 메소드:

    • 서브클래스
    • GoF 패턴
  2. 확장:

    • 단순: 수정
    • 메소드: 추가
  3. OCP:

    • 단순 위반, 메소드 부분 준수

8️⃣ BeanFactory의 Factory

8.1 BeanFactory

Spring BeanFactory:

  빈(객체)을 생성·관리하는 팩토리:
    - getBean() → 객체 반환
    - 객체 생성 책임

  "Factory" = 객체 생성 담당

8.2 빈 생성

BeanFactory 빈 생성:

  getBean("shipmentDao"):
    - 빈 정의 확인
    - 객체 생성
    - 의존성 주입
    - 반환

  → 객체 팩토리

8.3 팩토리 정신

팩토리 정신:

  팩토리 메소드:
    - 객체 생성 분리/위임

  BeanFactory:
    - 모든 빈 생성 담당
    - 객체 생성을 컨테이너가

  → 같은 정신 (생성 분리)

8.4 IoC 로 발전

IoC 로 발전:

  팩토리 메소드:
    - 객체 생성을 서브클래스가

  BeanFactory (IoC 컨테이너):
    - 객체 생성을 컨테이너가
    - 더 발전된 형태

→ Phase 7~8 에서

8.5 ILIC 의 맥락

// 팩토리 메소드 (Phase 5) → BeanFactory (Phase 8)

// 팩토리 메소드: 서브클래스가 생성
public abstract class ShipmentDao {
    protected abstract Connection getConnection();
}

// BeanFactory: 컨테이너가 생성 (Phase 8 미리보기)
@Configuration
public class DaoFactory {
    @Bean
    public ShipmentDao shipmentDao() {
        return new ShipmentDao(connectionMaker());   // 컨테이너가 생성
    }
    @Bean
    public ConnectionMaker connectionMaker() {
        return new MySqlConnectionMaker();
    }
}

// ApplicationContext ctx = ...;
// ShipmentDao dao = ctx.getBean("shipmentDao", ShipmentDao.class);
// → 객체 생성을 컨테이너(Factory)가 담당
// → 팩토리 메소드의 발전된 형태

interface ConnectionMaker { Connection makeConnection(); }
class MySqlConnectionMaker implements ConnectionMaker {
    public Connection makeConnection() { return null; }
}

8.6 자기 점검 답변

Spring BeanFactory의 Factory와의 관련은?

:
1. BeanFactory:

  • 빈(객체) 생성 팩토리
  1. 빈 생성:

    • getBean → 객체
  2. 팩토리 정신:

    • 생성 분리/위임
  3. 발전:

    • 컨테이너가 생성 (IoC)

9️⃣ 면접 + 자기 점검

9.1 면접 단골 질문 매핑

Q핵심 답변
팩토리 메소드?객체 생성 서브클래스 위임
객체 생성 위임?부모 사용, 자식 생성
getConnection?Connection 생성 (팩토리)
같은 코드 두 패턴?흐름(템플릿)/생성(팩토리)
관점 차이?흐름 vs 객체 생성
구조?Creator/Product
단순 vs 메소드?분기 vs 서브클래스
BeanFactory?빈 생성 팩토리
장점?생성 분리, 확장
IoC 발전?컨테이너 생성

9.2 자기 점검 체크리스트

정의

  • 객체 생성 위임

위임

  • 부모/자식

getConnection

  • 팩토리 메소드

두 패턴

  • 템플릿/팩토리

관점

  • 흐름 vs 생성

구조

  • Creator/Product

단순 vs 메소드

  • 분기 vs 서브클래스

BeanFactory

  • Factory

9.3 추가 심화 질문

Q1: 팩토리 메소드 vs 추상 팩토리?

답:

  • 팩토리 메소드: 객체 하나 생성 (메서드)
  • 추상 팩토리: 관련 객체군 생성 (객체)
  • 메소드 vs 객체
  • 추상 팩토리가 더 큼

Q2: 정적 팩토리 메서드?

답:

  • static 생성 메서드 (Effective Java)
  • of(), valueOf(), getInstance()
  • GoF 팩토리 메소드와 다름
  • 생성자 대체

Q3: 팩토리 메소드의 단점?

답:

  • 서브클래스 증가
  • 단일 상속 제약
  • 복잡도 ↑
  • 람다/주입으로 보완

Q4: DI 와 팩토리?

답:

  • 팩토리: 객체가 생성 결정
  • DI: 외부가 주입
  • DI 가 더 유연
  • 팩토리 메소드 → DI 로 발전

Q5: Connection 도 팩토리?

답:

  • DriverManager.getConnection: 정적 팩토리
  • DataSource.getConnection: 팩토리
  • 객체 생성 추상화
  • 곳곳에 팩토리

🎯 핵심 요약 — 3줄 정리

1. 팩토리 메소드 패턴

  • 객체 생성을 서브클래스에 위임
  • getConnection 이 Connection 생성 → 팩토리 메소드

2. 같은 코드, 두 패턴

  • 흐름 관점 → 템플릿 메소드
  • 객체 생성 관점 → 팩토리 메소드

3. BeanFactory

  • "Factory" = 객체 생성 담당
  • 팩토리 메소드 → 컨테이너 생성 (IoC) 으로 발전

📚 다음으로...

Unit 5.3 — 두 패턴의 한계 (Phase 5 완주)

이번 Unit에서 팩토리 메소드를 봤다면, 다음은 두 패턴의 한계 (Phase 5 마지막).

  • 상속의 단점 (단일 상속, 컴파일 타임, 깨지기 쉬움)
  • Composition over Inheritance
  • 인터페이스 + 합성 필요

Phase 5 진행 상황

🌱 Phase 5 — 디자인 패턴의 적용
  ✅ Unit 5.1 템플릿 메소드 패턴
  ✅ Unit 5.2 팩토리 메소드 패턴 ← 여기
  ⏭ Unit 5.3 두 패턴의 한계 — Phase 5 완주

5주차 누적 진행

✅ Part A — 동시성 마무리 (7 Unit)
🌱 Part B — 토비의 스프링
  ✅ Phase 3 — 전통 DAO (3 Unit)
  ✅ Phase 4 — 관심사의 분리 (3 Unit)
  🌱 Phase 5 — 디자인 패턴 (2/3 진행)

총: 15/26 Unit
profile
Software Developer

0개의 댓글