1. DI(의존성 주입, Dependency Injection)
1️⃣ DI(Dependency Injection)
1) 개념
한 객체가 필요로 하는 다른 객체(의존성)를 객체 스스로 생성하지 않고, 외부에서 주입받도록 하는 설계 기법
2) 핵심 아이디어
- 객체는 무엇을 할지만 알고
- 어떤 구현체를 쓸지는 외부에서 결정한다
이로써 객체 간 **결합도(coupling)**를 낮추는 것이 목적
2️⃣ DI가 필요한 이유
1) ❌ DI 사용하지 않을 경우
- 클래스 내부에서 직접 다른 클래스를 생성
- 구현체에 강하게 의존
- 변경·테스트가 어려움
2) ⭕ DI 적용
- 결합도 감소
- 구현체 변경 시 수정 범위가 작아짐
- 테스트 용이성
- Mock 객체 주입이 쉬워짐
- 유지보수성 향상
- 기능 확장에 유리
- 객체 책임 분리
- SRP(단일 책임 원칙) 강화
3️⃣ DI의 기본 개념 구조
- Client: 의존성을 사용하는 객체
- Dependency: 필요한 기능을 제공하는 객체
- Injector: 의존성을 생성하여 주입하는 주체
Client는 Dependency의 구체 구현을 모른 채 인터페이스에만 의존하는 것이 이상적
4️⃣ DI의 주요 방식
1) 생성자 주입 (Constructor Injection)
가장 권장되는 방식입니다.
- 객체 생성 시점에 의존성이 확정
- 불변성 보장
- 테스트에 유리
2) 세터 주입 (Setter Injection)
- 객체 생성 후 의존성 주입
- 선택적 의존성에 사용
- 누락 가능성 주의 필요
3) 필드 주입 (Field Injection)
- 간편하지만
- 테스트와 추적이 어렵고
- 일반적으로 권장되지 않음
5️⃣ DI와 IoC의 관계
- IoC (Inversion of Control): 제어의 역전이라는 개념
- DI: IoC를 구현하는 구체적인 방법 중 하나
DI ⊂ IoC
6️⃣ 프레임워크에서의 DI
DI는 보통 프레임워크 차원에서 지원됨
- Spring / Spring Boot (Java)
- ASP.NET Core (C#)
- NestJS (TypeScript)
- Angular
➡️ 이들은 모두 DI Container를 통해 객체 생성과 주입을 관리
7️⃣ 비유로 DI 이해하기 - 예시 1: 햄버거 가게 이야기
❌ DI가 없는 경우
1. 빵 만들기
2. 고기 만들기
3. 치즈 만들기
4. 직접 햄버거 완성➡️ 너무 힘들어 😵
➡️ 햄버거 말고 만드는 방법에 신경을 써야 함
✅ DI가 있는 경우
1. 빵 주세요
2. 고기 주세요
3. 치즈 주세요
4. 햄버거 완성누군가가 필요한 재료를 다 가져다 줌
➡️ 나는 햄버거 만드는 일만 하면 됨
➡️ 이게 바로 DI
👩🏻🏫Spring은 필요한 물건을 자동으로 챙겨주는 선생님!
Spring:
"너 햄버거 만들거지?"
"빵, 고기, 치즈 필요하지?"
"여기 있어!"➡️ 우리는 그냥 받아서 쓰기만 하면 됨
8️⃣ final + @RequiredArgsConstructor 조합
“이 물건은 꼭 있어야 하고, 중간에 바뀌면 안 될 때” 사용
1) 비유 : 로봇과 건전지
로봇은 건전지가 없으면 절대 못 움직임
➡️ 이런 건전지는
- 없으면 안 됨 ❌
- 중간에 바뀌면 안 됨 ❌
➡️ 이럴 때 쓰는 게
final + @RequiredArgsConstructor2) 코드
class Robot {
private final Battery battery;
public Robot(Battery battery) {
this.battery = battery;
}
}- 🔒
final→ 건전지 바꾸지 마!
- 🧾 생성자 → 태어날 때 꼭 받아!
➡️ “필수 물건” 표시
3) Spring + Lombok 버전
@RequiredArgsConstructor
class Robot {
private final Battery battery;
}Spring:
“아~ 배터리 꼭 필요하구나. 내가 태어날 때 넣어줄게!”
4) 언제 쓰면 좋을까?
상황 | 써야 할까? |
없으면 바로 고장 | ✅ |
항상 있어야 함 | ✅ |
중간에 바뀌면 안 됨 | ✅ |
서비스, 컨트롤러 | ✅ 거의 항상 |
➡️ 실무의 기본값
9️⃣ @Autowired
“이건 있으면 좋고, 없어도 괜찮을 때”
1) 비유: 가방 속 물건
연필: 꼭 필요함
스티커: 있으면 좋음스티커 같은 물건 =
@Autowired2) 예시
@Autowired
private Sticker sticker;- “있으면 써볼게”
- “없어도 울지 않을게”
3) @Autowired를 쓰는 대표 상황
① 선택 물건일 때
@Autowired(required = false)
private Logger logger;- 없어도 OK
- 있으면 더 좋음
② 나중에 바꿀 수도 있을 때
@Autowired
public void setBattery(Battery battery) {
this.battery = battery;
}- 중간에 교체 가능
③ 생성자가 여러 개일 때
@Autowired
public Robot(Battery battery) {}Spring에게:
“이 생성자 써!”
Share article