스택큐힙리스트

확장에 강한 코드: OCP(개방·폐쇄 원칙) 한눈에 마스터 본문

개발

확장에 강한 코드: OCP(개방·폐쇄 원칙) 한눈에 마스터

스택큐힙리스트 2025. 7. 13. 11:43
반응형

코드를 뜯지 말고, 새로 얹어라.
― SOLID 두 번째 원칙, OCP (Open-Closed Principle)

OCP는 “확장에는 열려 있고, 수정에는 닫혀 있어야 한다”는 단순한 선언이지만, 리팩터링 비용을 확 낮추는 강력한 안전장치입니다.


1. OCP란 무엇인가?

  • 정의
    “소프트웨어 요소는 기능 확장에는 열려(Open) 있고, 소스 수정에는 닫혀(Closed) 있어야 한다.” 클래스가 아니라 추상화(인터페이스·추상 클래스)에 의존함으로써 새 기능을 ‘플러그인’처럼 꽂을 수 있게 설계한다는 뜻입니다.
  • 왜 중요한가?
    1. 배포 리스크 감소 – 기존 코드 untouched → 회귀 버그 최소
    2. 신규 기능 속도 – 확장 로직만 추가 → 개발·리뷰·테스트가 빨라짐
    3. 플러그인 아키텍처 – 전략(Strategy)·데코레이터(Decorator) 같은 패턴과 궁합 ↑

2. OCP가 깨지는 징후

  • if/else 지옥: 조건마다 새 기능을 추가하려면 기존 블록을 수정해야 함
  • 타입 체킹: when(type)·instanceof로 분기 → 새 타입 추가 시 고질적 수정
  • 단일 구현 의존: 구체 클래스를 직접 주입 → 교체 불가
    이런 코드가 보이면 “추상화 레이어가 필요하다”는 시그널입니다.

3. Kotlin 예제로 보는 Before ↔ After

❌ Before: 할인 정책을 if로 분기

class Checkout {
    fun pay(amount: Money, type: String): Money =
        when (type) {
            "FIXED" -> amount - Money(1000)
            "RATE"  -> amount * 0.9
            else    -> amount
        }
}

새 할인 방식이 나오면 이 메서드를 계속 수정해야 해요.

✅ After: 전략 패턴으로 확장

interface DiscountPolicy { fun apply(amount: Money): Money }

class FixedDiscount(private val value: Money): DiscountPolicy {
    override fun apply(amount: Money) = amount - value
}
class RateDiscount(private val rate: Double): DiscountPolicy {
    override fun apply(amount: Money) = amount * (1 - rate)
}

class Checkout(private val policy: DiscountPolicy) {
    fun pay(amount: Money) = policy.apply(amount)
}

이제 새 정책 = 새 클래스를 추가하면 끝! Checkout은 그대로입니다.


4. 실무에서 OCP 지키는 4단계

  1. 변하는 것 vs. 안 변하는 것 분리
    요구사항 히스토리를 살펴 “자주 바뀌는 축”을 찾아 인터페이스로 추상화.
  2. DI(의존성 주입) 적극 활용
    스프링·Koin 같은 DI 컨테이너로 구체 구현을 외부에서 주입.
  3. 패턴 조합
    • 전략 패턴: 알고리즘 군 교체
    • 데코레이터: 기능 덧씌우기
    • 템플릿 메서드: 고정된 순서 + 변동 로직 훅(Hook)
  4. 계측 지표로 검증
    SonarQube “복잡도”·“중복 코드” 알람을 통해 if/else 집중 구간을 모니터링.

5. 지금 바로 시도해 볼 액션 플랜

  1. 주요 서비스 클래스를 열어 if(type) 분기부터 찾기.
  2. 같은 기능군을 Strategy 인터페이스로 추상화하고 구현체를 분리.
  3. DI 설정을 바꿔 기존 테스트 코드를 그대로 돌려 성공 확인.
  4. CI 파이프라인에 코드 커버리지 알림을 걸어 회귀를 예방.
반응형
Comments