<Spring> IoC / Container / DI

Google 아니고 Joogle·2022년 10월 27일
0

Spring / Spring Boot 

목록 보기
4/5

💡IoC (Inversion of Control)

  • 객체지향 언어에서 Object간의 연결 관계를 런타임에 결정
  • IoC 의 구현 방법 중 하나가 DI (Dependency Injection)
  • 필요한 위치에서 개발자가 필요한 객체 생성 로직을 구현하는 기존의 방식에서 벗어나, 객체 생성을 Container에게 위임하려 처리

아래와 같은 경우, A객체에서 B,C객체를 사용할 때 (의존할 때) A객체에서 직접 생성하는 것이 아니라 외부 (IoC 컨테이너)에서 생성된 B,C 객체를 주입시켜 setter 혹은 생성자를 통해 사용하는 방식

✔️Factory 호출 방식

  • 객체 간의 결합도를 떨어뜨릴 수 있음 (객체간 결합도가 높으면 해당 클래스가 유지보수 될 때, 그 클래스와 결합된 다른 클래스도 유지보수 되어야 할 가능성이 높음)
  • 인터페이스 변경 시 팩토리만 수정하면 되고 호출 클래스에는 영향을 미치지 않음

✔️Assembler를 통해 결합도를 낮추는 방식

  • IoC 호출 방식
  • 팩토리 패턴의 장점을 더하여 어떠한 것에도 의존하지 않는 형태가 됨
  • 실행시점 (Runtime)에 클래스 간의 관계가 형성이 됨

💡Container

✔️Container

Container란?

  • 객체의 생성, 사용, 소멸에 해당하는 라이프사이클 담당
  • 라이프 사이클을 기본으로 애플리케이션 사용에 필요한 주요 기능 제공
  • 비지니스 로직 외에 부가적인 기능들에 대해서는 독립적으로 관리되도록 하기 위함
  • 서비스 look up이나, Configuration에 대한 일관성을 갖기 위함
  • 서비스 객체를 사용하기 위해 각각 Factory 또는 Singleton 패턴을 직접 구현하지 않아도 됨

IoC Container

  • 오브젝트의 생성과 관계 설정, 사용, 제거 등의 작업을 애플리케이션 코드 대신 독립된 컨테이너가 담당
  • 컨테이너가 코드 대신 오브젝트에 대한 제어권을 갖고 있어 IoC라고 부름 -> 스프링 컨테이너를 IoC 컨테이너라고 부르기도 함 (BeanFactory, ApplicationContext)

Spring DI Container

  • Spring DI Container가 관리하는 객체를 bean이라 하고, 이들의 생명 주기를 관리하는 의미로 BeanFactory라 함 -> Bean Factory에 여러 컨테이너 기능을 추가하여 ApplicationContext라 함

💡DI

  • Object에 lookup 코드를 사용하지 않고, 컨테이너가 직접 의존 구조를 Object에 설정할 수 있도록 지정해주는 방식
  • 의존성 주입의 종류로는 Field Injection, Setter Injection, Constructor Injection 3가지 방법이 있음

1. Field Injection (필드 주입)

@Component
public class SampleController {
    @Autowired
    private SampleService sampleService;
}
  • 변수 선언부에 @Autowired Annotation을 붙임
  • 단일 책임 원칙 (SRP)을 해칠 가능성이 높아짐 -> 간단한 사용법 아래 개수 제한 없이 무한정 추가하게 되고 class가 많은 책임을 떠안게 됨
  • Constructor Injection과 다르게 Field Injectionfinal을 선언할 수 없어서 객체가 변할 수 있음

2. Setter Injection (수정자 주입)

@Component
public class SampleController {
    private SampleService sampleService;
 
    @Autowired
    public void setSampleService(SampleService sampleService) {
        this.sampleService = sampleService;
    }
}
  • Setter Injection선택적인 의존성을 사용할 때 유용해서 상황에 따라 의존성 주입이 가능
  • Setter Injection을 통해서 Service의 구현체를 주입해주지 않아도 Controller 객체는 생성이 가능
  • set을 통해 Service의 구현체를 주입해주지 않았으므로 NullPointerException이 발생 -> 주입이 필요한 객체가 주입이 되지 않아도 얼마든지 객체를 생성할 수 있다는 것이 문제

3. Constructor Injection (생성자 주입)

@Component
public class SampleService {
    private SampleDAO sampleDAO;
 
    @Autowired
    public SampleService(SampleDAO sampleDAO) {
        this.sampleDAO = sampleDAO;
    }
}

@Component
public class SampleController {

	private final SampleService sampleService = new SampleService(new SampleDAO());
    
	...
}
  • Constructor@Autowired Annotation을 붙여 의존성을 주입받을 수 있음
  • 필수적으로 사용해야하는 의존성 없이는 Instance를 만들지 못하도록 강제할 수 있기 때문에 권장
  • 의존관계를 주입하지 않은 경우에는 Controller 객체를 생성할 수 없음
  • final 사용 가능 -> final로 선언된 레퍼런스 타입 변수는 반드시 선언과 함께 초기화 되어야 하므로 setter 주입시에는 의존 관계 주입을 받을 필드에 final 선언할 수 없음
  • final을 붙이면 Lombok가 결합되어 코드를 간결하게 작성할 수 있음

✔️Bean

  • 스프링이 IoC 방식으로 관리하는 오브젝트
  • 스프링이 직접 그 생성과 제어를 담당하는 오브젝트만을 Bean이라 부름

✔️BeanFactory

  • 스프링이 IoC를 담당하는 핵심 컨테이너
  • Bean을 등록, 생성, 조회, 반환하는 기능
  • 일반적으로 BeanFactory를 바로 사용하지 않고 이를 확장한 ApplicationContext이용

✔️ApplicationContext

  • BeanFactory를 확장한 IoC 컨테이너
  • Bean을 등록하고 관리하는 기본적인 기능은 BeanFactory와 동일
  • 스프링이 제공하는 각종 부가 서비스를 추가로 제공

✔️Annotation

  • 빈으로 사용될 클래스에 특별한 annotation을 부여해 주면 자동으로 빈 등록 가능
  • Annotation으로 빈을 설정할 경우, 반드시 component-scan 설정 필요

@Repository

  • Data Access Layer의 DAO또는 Repository 클래스에 사용
  • DataAccessException자동 변환과 같은 AOP의 적용 대상을 선정하기 위해 사용

@Service

  • Service Layer의 클래스에 사용

@Controller

  • Presentation Layer의 MVC Controller에 사용
  • 스프링 웹 서블릿에 의해 웹 요청을 처리하는 컨트롤러 빈으로 선정

@Component

  • 위의 Layer 구분을 적용하기 어려운 일반적인 경우

@ResponseBody

  • 메소드에서 리턴되는 값이 View로 출력되지 않고 HTTP Response Body에 직접 쓰여지게 됨 -> return시에 json, xml과 같은 데이터를 return
  • null 여부를 반드시 체크해주어야 함! (null을 리턴하면 오류도 발생하지 않고, 브라우저에 response도 없기 때문)

Reference

profile
Born to be happy, Not perfect 🤍

0개의 댓글