Article - 깊게 탐구하기/개발 꿀팁

컴파일 타임 의존 vs 런타임 의존

조금씩 차근차근 2025. 12. 15. 04:20

이 말은 모듈 레벨에서도 사용 가능하고, 코드 레벨에서도 사용 가능하다.

하지만 모듈 레벨 의존과 코드 레벨 의존이 별로 다르지 않다고 생각한다.

  • 말로 엄밀히 정의하는 것보단, 직접 해보며 둘의 미묘한 차이를 이해하는 것이 중요하다고 생각한다.

따라서, 본 글에선 두 개념을 하나로 묶어서 정리한다.

나중에 둘이 많이 다르다는 걸 알게되면 추가로 정리한 글을 작성하고 링크하도록 하겠다.

컴파일타임 결합(빌드/링크 타임 결합)

  • A 모듈이 B 모듈의 헤더/정적 라이브러리/심볼에 의존해서 컴파일·링크 단계에서 결합이 확정되는 형태

  • 예: 컴파일 타이밍에 예외를 잡을 수 있는 형태

    • 기초적인 문법 사용
    • checked exception

      런타임 결합(동적 로딩/플러그인)

  • A가 B를 실행 시점에 선택/로드/연결하는 형태

  • 예: 런타임에 예외를 잡는 형태.

    • Spring DI, 리플렉션/어노테이션 기반 로딩
    • Runtime Exception, unchecked exception

컴파일타임 결합의 대표 장단점

장점

  • 정적 타입/컴파일러가 잡아주는 안정성(시그니처 변경, 누락된 메서드 호출 등 조기 검출)
  • 구성 오류를 빌드 단계에서 더 빨리 발견 가능
  • 성능/최적화 여지가 있음
    • 모듈 레벨로 올라가면, 확실히 영향이 클 것으로 예상됨.

      단점

  • 구현에 직접 의존 → 변경이 전파되기 쉬움(수정 범위 확대, 재컴파일/재배포 영향 확대)
  • 치환/확장 비용 증가 → 대체 구현을 넣기가 어려움
  • 테스트 모킹(Mock/stub) 교체가 어려워질 수 있음
  • 모듈의 경우, 빌드 시간이 늘어남: include 의존이 두꺼우면 증분 빌드가 약해짐

런타임 결합의 대표 장단점

장점

  • 구현 교체가 쉬움(전략 패턴/플러그인/DI)
  • 모듈 경계 분리가 용이(핵심 로직은 인터페이스에만 의존)
  • 테스트 용이성(주입을 통한 대역 교체)

단점

  • 오류가 런타임으로 이동 → 빈 주입 실패, 설정 누락, 프로파일/조건 불일치 등은 실행/배포 후에 드러날 수 있음
  • 추적 난이도 증가 → “이 인터페이스의 실제 구현이 무엇인지”가 코드만 봐서는 즉시 안 보일 수 있음
  • 구성/환경 의존성 증가 → 설정 파일, 컨테이너, 배포 환경이 동작의 일부가 됨

판단 기준

다음 요소가 중요하면 런타임 결합이 유리해지는 경우가 많다.

  • B가 자주 바뀌고, A는 안정적으로 유지해야 하는가?
  • “부분 교체”가 중요한가?

반대로 아래가 중요하면 컴파일타임 결합이 유리해지는 경우가 많다.

  • 런타임 실패 비용이 매우 큰가? (실행 중 로딩 실패가 치명적, 복구 로직 작성의 어려움)
  • 실행 환경을 단순하게 유지해야 하는가?
  • 성능 최적화가 최우선인가?