ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • IoC와 DI
    웹 개발/Spring 2025. 4. 16. 01:59

     

    DI (Dependency Injection)
    IOC (Inversion of Control)

    Spring의 핵심 설계 철학들 중 중요한 두 가지이다.

     


     

     

    아래 코드를 보면 ReportService는 PdfExporter에 의존하고있다

    PdfExporter를 ExcelExporter로 바꾸고 싶다면 ReportService도 수정해야 하기때문에 두 클래스는 강하게 결합되어있다.

    // 의존 클래스
    public class PdfExporter {
        public void export(String content) {
            System.out.println("PDF 내보내기: " + content);
        }
    }
    
    // Service 클래스 (강한 결합 발생)
    public class ReportService {
        private PdfExporter exporter;
    
        public ReportService() {
            // 직접 생성 -> 강한 결합
            exporter = new PdfExporter();
        }
    
        public void exportReport(String content) {
            exporter.export(content);
        }
    }
    
    // 실행 클래스
    public class App {
        public static void main(String[] args) {
            ReportService reportService = new ReportService();
            reportService.exportReport("강한 결합 예시!");
        }
    }

     

    Spring에서는 두 객체의 결합도를 낮추고 좀더 유연하게 하기 위해  IoC와 DI를 통해 객체를 관리한다.

    IoC(제어 역전 현상)는 개발자가 직접 제어하던 객체 생성과 연결을 Spring이 대신 제어 해주는 것을 말한다. 즉, 제어의 흐름이 개발자에서 프레임워크로 넘어가기 때문에 '역전'이라고 부른다.

     

    DI(Dependancy Injection)은 객체가 필요한 다른 객체를 직접 생성하지 않고 외부에서 주입받는 방식이다.

    // Exporter 인터페이스
    public interface Exporter {
        void export(String content);
    }
    
    // PdfExporter 구현체
    @Component
    public class PdfExporter implements Exporter {
        @Override
        public void export(String content) {
            System.out.println("PDF 내보내기: " + content);
        }
    }
    
    // ReportService - DI 적용
    @Service
    public class ReportService {
        private final Exporter exporter;
    
        // 생성자 주입
        public ReportService(Exporter exporter) {
            this.exporter = exporter;
        }
    
        public void exportReport(String content) {
            exporter.export(content);
        }
    }
    
    @SpringBootApplication
    public class App implements CommandLineRunner {
    
        private final ReportService reportService;
    
        public App(ReportService reportService) {
            this.reportService = reportService;
        }
    
        public static void main(String[] args) {
            SpringApplication.run(App.class, args);
        }
    
        @Override
        public void run(String... args) {
            reportService.exportReport("Spring DI 적용 예시!");
        }
    }

     

    이처럼 Spring에서는 @Component와 @Service로 객체를 IoC 컨테이너에 등록하고 필요한 객체를 생성자가 선언만 하면 자동으로 주입해준다.

    결과적으로 클래스 간 결합도를 낮추고 테스트나 확장도 유연하게 할 수 있다.

     

    또한 ReportService는 Exporter라는 인터페이스만 알고 있고 PdfExporter, ExcelExporter 등 어떤 구현체가 들어오든 상관없다.

    즉 B를 바꾸더라도 A는 수정하지 않아도 된다. 

     

     

    댓글

Designed by Tistory.