▣ LAB · SPRING

제어권 위임 직접 흉내내기

IoC — 실습 / 약 15분

📍 지금 어디를 만지고 있나요?
브라우저
Tomcat
컨테이너 흉내
Controller
DB

사전 준비

이번 실습의 목표

Spring 없이 — 순수 자바로 「누가 객체를 만들어 끼워넣어주는」 방식을 흉내냅니다. Spring 컨테이너가 다음 차시에서 어떤 일을 자동으로 해주는지 미리 손으로 느껴봅니다.

1
인터페이스 도입
// File: IoCDemo.java
interface MessageSender {
    void send(String msg);
}

class GmailSender implements MessageSender {
    public void send(String msg) { System.out.println("📧 " + msg); }
}

class KakaoSender implements MessageSender {
    public void send(String msg) { System.out.println("💬 " + msg); }
}

두 부품 모두 MessageSender 인터페이스를 구현. 이제 OrderService 는 인터페이스에만 의존할 수 있습니다.

2
OrderService — 외부에서 받기
class OrderService {
    private MessageSender sender;     // 인터페이스 타입

    OrderService(MessageSender sender) {  // ← 외부에서 주입
        this.sender = sender;
    }

    void order() {
        sender.send("주문 완료");
    }
}

OrderService 안에는 new 가 없습니다. 누구를 받느냐는 외부에 달림.

3
「수동 컨테이너」 작성
public class IoCDemo {
    public static void main(String[] args) {
        // 우리가 컨테이너 역할을 함
        MessageSender sender = new GmailSender();   // ← 한 줄만 바꾸면
        // MessageSender sender = new KakaoSender(); // ← 부품 교체 끝

        OrderService service = new OrderService(sender);
        service.order();
    }
}
$ javac IoCDemo.java
$ java IoCDemo
📧 주문 완료
4
부품 교체 체험

main 메서드의 한 줄을 KakaoSender 로 바꾸고 다시 실행:

$ java IoCDemo
💬 주문 완료
CHECKPOINT — 무엇이 변했나
  • OrderService 코드는 한 줄도 수정하지 않았습니다
  • 부품 결정 권한이 main 메서드(외부)로 넘어갔습니다 = IoC
  • 전 차시 (new 의 함정) 와 비교했을 때 얼마나 가벼워졌나요?
5
다음 차시의 약속

지금 우리는 main 메서드에서 직접 부품을 만들어 주입했습니다. Spring 에서는 @Autowired 같은 어노테이션 한 줄이면 컨테이너가 자동으로 해줍니다.

// 다음 차시 미리보기
@Service
class OrderService {
    @Autowired private MessageSender sender;  // 자동 주입!
}

실습 완료 체크리스트

인터페이스 + 두 구현체 작성
OrderService 가 인터페이스에만 의존하도록 수정
main 에서 부품을 결정해 주입하는 코드 작성
부품 교체 시 OrderService 가 변하지 않음을 확인
「제어권이 어디로 넘어갔는가」를 입으로 말할 수 있다