본문으로 건너뛰기
객체지향 설계 · 디자인 패턴LESSON 20

의존성 주입

난이도중급 → 심화
예상 시간65분
선수지식이전 강의

20강. 의존성 주입

1. 이번 강의에서 해결할 문제​

Service가 파일·메일 객체를 직접 생성하면 테스트가 외부 세부에 묶입니다.

2. 학습 목표​

3. 핵심 개념​

DI는 컨테이너 제품이 아니라 필요한 협력자를 외부에서 받는 방식입니다. 필수 비소유 협력자는 참조로 표현할 수 있습니다.

직접 생성 버전에서 TaskService가 FileRepository, EmailNotifier, 시스템 시계를 내부에서 만들면 저장 위치와 네트워크, 현재 시간이 서비스 코드에 숨습니다. 테스트도 실제 파일과 메일에 의존합니다. DI는 이 결정을 프로그램 시작점인 조립 루트로 옮기고 서비스는 역할 계약만 사용하게 합니다.

  • 참조 주입: 필수이고 Service가 소유하지 않으며 협력자가 더 오래 살아야 함
  • unique_ptr 주입: Service가 협력자의 단독 수명을 소유함
  • 값 주입: 작고 복사 가능한 설정·정책

4. 가장 작은 예제로 시작하기​

main.cpp
#include <iostream>
#include <string>
#include <string_view>
#include <vector>

struct TaskRepository {
virtual ~TaskRepository() = default;
virtual void saveCompleted(int taskId, std::string_view at) = 0;
};

struct Notifier {
virtual ~Notifier() = default;
virtual void taskCompleted(int taskId) = 0;
};

struct Clock {
virtual ~Clock() = default;
virtual std::string now() const = 0;
};

class TaskService {
TaskRepository& repo_;
Notifier& notifier_;
Clock& clock_;
public:
TaskService(TaskRepository& repo, Notifier& notifier, Clock& clock)
: repo_(repo), notifier_(notifier), clock_(clock) {}

void complete(int taskId) {
repo_.saveCompleted(taskId, clock_.now());
notifier_.taskCompleted(taskId);
}
};

struct FakeRepository final : TaskRepository {
std::vector<int> savedIds;
void saveCompleted(int taskId, std::string_view) override {
savedIds.push_back(taskId);
}
};

struct SpyNotifier final : Notifier {
std::vector<int> notifiedIds;
void taskCompleted(int taskId) override { notifiedIds.push_back(taskId); }
};

struct FixedClock final : Clock {
std::string now() const override { return "2026-07-31T10:00:00Z"; }
};

int main() {
FakeRepository repo;
SpyNotifier notifier;
FixedClock clock;
TaskService service{repo, notifier, clock};

service.complete(42);
std::cout << repo.savedIds.at(0) << ' '
<< notifier.notifiedIds.at(0) << '\n';
}

예상 출력: 42 42가 표시되어 같은 작업이 저장되고 알림됐음을 확인합니다.

5. 코드가 동작하는 이유​

생성자 서명에 세 필수 협력자가 드러나므로 불완전한 TaskService를 만들 수 없습니다. 테스트는 실제 파일·메일·현재 시간 대신 Fake, Spy, FixedClock을 스택에 만들고 참조로 전달합니다. main이 더 오래 사는 협력자를 먼저 만들었으므로 Service의 참조도 유효합니다.

변경 전에는 알림 구현을 바꾸려면 Service 내부 생성을 수정합니다. 변경 후에는 조립 루트에서 SpyNotifier 대신 실제 구현을 연결하고 Service의 완료 규칙은 유지합니다. 저장 성공 뒤 알림한다는 호출 순서도 테스트할 수 있습니다.

6. 자주 하는 실수와 해결법​

7. 직접 실습​

8. 이해 점검 질문 3개​

9. 핵심 요약​

10. 다음 강의 연결​

구체 구현 선택을 조립 루트로 옮겼습니다. 다음 강의에서는 이 의존 방향을 계층 전체로 확장합니다.

MINI QUIZ

의존성 주입 미니 퀴즈

선택 즉시 정답과 해설을 확인할 수 있습니다. 결과는 이 브라우저에만 저장됩니다.

0 / 2
  1. 문제 1“의존성 주입”의 역할과 의존성을 판단하는 올바른 기준은 무엇인가요?
  2. 문제 2“의존성 주입”에서 비슷한 개념이나 선택을 구분하는 기준은 무엇인가요?
LESSON STATUS

학습을 마쳤나요?

직접 실습과 점검 질문까지 확인한 뒤 완료로 표시하세요.

20강. 의존성 주입 미완료 상태