Topic (오늘의 주제)
IoC (Inversion of Control) / DI (Dependency Injection)
: 프로그램의 제어 흐름과 객체 생성의 권한을 개발자가 아닌 외부(컨테이너)로 넘기는 설계 원칙(IoC)과, 이를 구현하기 위해 외부에서 의존 객체를 주입해 주는 방식(DI).
Why (왜 사용하는가? 왜 중요한가?)
- 실무: 객체 간의 **결합도(Coupling)**를 낮추어, 하나의 클래스를 수정했을 때 다른 클래스까지 줄줄이 고쳐야 하는 '스파게티 코드' 사태를 막는다.
- 구조적 의미: 객체가 자신이 사용할 부품(의존성)을 직접 생성(new)하지 않고 공급받기 때문에, 유연한 교체와 확장이 가능하다.
- 면접 의도: 스프링 프레임워크의 존재 이유 그 자체이므로, 단순히 용어 정의를 넘어 "그래서 이게 개발자에게 무슨 이득을 주는가(테스트, 유지보수)"를 설명할 수 있어야 한다.
Core Concept (핵심 개념 정리)
"헐리우드 원칙: Don't call us, we'll call you." (연락하지 마세요, 우리가 부를게요.)
| 구분 | 기존 방식 (제어권: 개발자) | IoC/DI 방식 (제어권: 스프링 컨테이너) |
| 객체 생성 | 개발자가 코드에서 직접 new 연산자로 생성 | 컨테이너가 미리 생성해 둠 (Bean 등록) |
| 의존성 연결 | 클래스 안에서 의존 객체를 직접 생성 및 할당 | 컨테이너가 실행 시점에 필요한 객체를 **주입(Inject)**해 줌 |
| 관계 | 강한 결합 (Tight Coupling) 부품이 바뀌면 코드도 바꿔야 함. |
느슨한 결합 (Loose Coupling) 부품이 바뀌어도 설정만 바꾸면 됨. |
| 비유 | 내가 직접 장을 봐서 요리함 | 배달 앱으로 음식을 주문해서 받음 |
개념 구분
- IoC (제어의 역전): "제어권이 뒤바뀌었다"는 추상적인 설계 원칙(개념).
- DI (의존성 주입): IoC를 실제로 구현하기 위한 구체적인 방법(디자인 패턴).
Interview Answer Version (면접 답변식 요약)
"IoC는 프로그램의 흐름과 객체 생성의 제어권을 개발자가 아닌 프레임워크가 가져가는 것을 의미하며, 이를 구현하는 대표적인 방법이 DI입니다.
기존에는 객체가 자신이 사용할 의존성을 직접 생성(new)했지만, DI를 통해 외부 컨테이너가 의존성을 주입해 줌으로써 객체 간의 결합도를 낮추고, 유닛 테스트를 용이하게 만들어 코드의 유지보수성을 높일 수 있습니다."
Practical Tip (사용 시 주의할 점 or 활용 예)
1. 생성자 주입을 강력 권장 (Lombok 활용)
DI를 받는 방법은 3가지(필드, 세터, 생성자)가 있지만, 실무에서는 99% 생성자 주입을 권장합니다.
Java
@Service
@RequiredArgsConstructor // Lombok: final 필드에 대한 생성자 자동 생성
public class UserService {
// final을 붙여서 '불변성' 보장
private final UserRepository userRepository;
}
- 이유: 객체 생성 시점에 의존성 주입 보장, final 키워드 사용 가능, 테스트 코드 작성 용이.
2. 순환 참조(Circular Reference) 문제
A → B, B → A를 서로 참조하는 상황입니다. 생성자 주입을 사용하면 앱 구동 시점에 에러를 발생시켜 설계 결함을 조기에 발견할 수 있습니다.
예상 꼬리 질문 정리
- "DI의 종류 3가지의 차이점과 각 장단점은?"
- "스프링 컨테이너(ApplicationContext)란 무엇인가요?"
- "프레임워크와 라이브러리의 차이는? (IoC 관점에서)"
Deep Dive (조사 중 헷갈렸던 개념)
1. 생성자(Constructor)의 정체: "태어날 때 무조건 쥐어줘야 하는 것"
- 비유: '휴대폰 개통' 시 유심칩이 없으면 판매(객체 생성)를 거부하는 것과 같습니다.
- 효과: 일단 객체가 생성되었다면, 의존성이 비어있을(Null) 걱정이 없습니다.
2. 스프링 DI에서 생성자가 중요한 이유: "강제성"
- 스프링은 "Service를 만들려면 Repository를 무조건 내놔!"라고 강제하여 런타임 에러를 방지합니다.
3. Lombok 어노테이션 3형제 해부
- @NoArgsConstructor: 인자 없는 기본 생성자 (JPA Entity용).
- @AllArgsConstructor: 모든 필드 대상 생성자.
- @RequiredArgsConstructor (★실무 핵심): final이나 @NonNull 필드만 포함하는 생성자 생성. 스프링 DI와 찰떡궁합.
'Archive > Daily Dev Q&A' 카테고리의 다른 글
| Daily Dev Q&A: Spring Bean (0) | 2025.12.26 |
|---|---|
| Daily Dev Q&A: Spring Boot (0) | 2025.12.26 |
| Daily Dev Q&A: Spring Framework (0) | 2025.12.23 |
| Daily Dev Q&A: 트랜잭션 (Transaction) (0) | 2025.12.22 |
| Daily Dev Q&A: DDL, DML, DCL (0) | 2025.12.18 |