개발하는 체대생

[Spring] DI(의존성 주입), IoC(제어의 역전), Bean 본문

카테고리 없음

[Spring] DI(의존성 주입), IoC(제어의 역전), Bean

개발하는체대생

요약

DI(Dependency Injection, 의존성 주입)

- DI는 클래스 사이의 의존 관계를 빈 설정 정보를 바탕으로 컨테이너가 자동적으로 연결해주는 것을 말한다.

 

Ioc (Inversion of Control, 제어의 역전)

- 객체에 대한 제어권이 바꿘 것을 의미하거나 제어 권한을 자신이 아닌 다른 대상에게 위힘하는 것을 의미한다.

 

Bean 

- Spring IoC 컨테이너가 관리하는 자바 객체이다.(즉, 컨테이너 안에 들어 있는 객체)

* 컨테이너란?

- 개발자가 작성한 코드의 처리과정을 위임받은 독립적인 존재

* 컨테이너의 역할?

-인스턴스의 생명주기를 관리하며, 생성된 인스턴스들에게 추가적인 기능을 제공하도록 하는 것

 

본문

DI(Dependency Injection)

1. DI란?

  • DI는 클래스 사이의 의존관계를 빈 설정 정보를 바탕으로 컨테이너가 자동적으로 연결해주는 것을 말한다. 개발자들은 제어를 담당할 필요없이 빈 설정 파일에 의존관계가 필요하다는 정보만 추가해주면 된다.
    • 컨테이너가 실행 흐름의 주체가 되어 애플리케이션 코드에 의존관계를 주입해주는 것.
  •  DI는 Spring 프레임워크에서 지원하는 IoC의 형태이다.
  • 스프링이 다른 프레임워크와 차별화되어 제공하는 의존 관계 주입 기능으로, 객체를 직접 생성하는 게 아니라 외부에서 생성한 후 주입 시켜주는 방식이다.

 

2. DI의 특징

  • ‘new’를 사용해 모듈 내에서 다른 모듈을 초기화하지 않으려면 객체 생성은 다른 곳에서 하고, 생성된 객체를 참조하면 된다.
  • 의존성 주입은 Inversion of Control 개념을 바탕으로 한다. 클래스가 외부로부터 의존성을 가져야한다.

 

3. DI가 필요한 이유(DI의 장점)

  • 클래스를 재사용 할 가능성을 높이고, 다른 클래스와 독립적으로 클래스를 테스트 할 수 있다.
  • 비즈니스 로직의 특정 구현이 아닌 클래스를 생성하는데 매우 효과적
  • DI(의존성 주입)를 통해서 모듈 간의 결합도가 낮아지고 유연성이 높아진다.

 

4. DI의 세가지 방법

  • Contructor Injection : 생성자 삽입
  • Method(Setter) Injection : 메소드 매개 변수 삽입
  • Field Injection : 멤버 변수 삽입

 

IoC(Inversion of Control, 제어의 역전)

1. IoC란?

  • 객체의 생성에서부터 생명주기의 관리까지 모든 객체에 대한 제어권이 바뀐 것을 의미, 또는 제어 권한을 자신이 아닌 다른 대상에게 위임하는 것이다.
  • 이 방식은 대부분의 프레임워크에서 사용하는 방법으로, 개발자는 필요한 부분을 개발해서 끼워 넣기의 형태로 개발하고 실행하게 된다. 프레임워크가 이러한 구조를 가지기 때문에 개발자는 프레임워크에 필요한 부품을 개발하고 조립하는 방식의 개발을 하게 된다.
  • 이렇게 조립된 코드의 최종 호출은 개발자에 의해서 제어되는 것이 아니라 프레임워크의 내부에서 결정된 대로 이뤄지게 되는데, 이러한 현상을 "제어의 역전"이라고 표현한다.
  • 객체의 의존성을 역전시켜 객체 간의 결합도를 줄이고 유연한 코드를 작성할 수 있게 하여 가독성 및 코드 중복, 유지 보수를 편하게 할 수 있게 한다.

 

2. Spring에서의 IoC

  • Spring 프레임워크에서 지원하는 Ioc Container는 우리들이 흔히 개발하고 사용해왔던 일반 POJO(Plain Old Java Object)의 생명주기를 관리하며, 생성된 인스턴스들에게 추가적인 기능들을 제공한다.

 

3. 라이브러리와 프레임워크의 차이

  • IoC의 개념이 적용되었나의 차이
  • 라이브러리를 사용하는 애플리케이션 코드는 애플리케이션 흐름을 직접 제어한다. 단지 동작하는 중에 필요한 기능이 있을 때 능동적으로 라이브러리를 시용할 뿐이다.
  • 반면에 프레임워크는 거꾸로 애플리케이션 코드가 프레임워크에 의해 사용된다. 보통 프레임워크 위에 개발한 클래스를 등록해두고, 프레임워크가 흐름을 주도히는 중에 개발자가 만든 애플리케이션 코드를 시용하도록 만드는 방식이다.

 

Bean

1. Bean이란?

  • 컨테이너 안에 들어있는 객체
  • 컨테이너에 담겨있으며, 필요할 때 컨테이너에서 가져와서 사용
  • @Bean 을 사용하거나 xml 설정을 통해 일반 객체를 Bean으로 등록할 수 있고, Bean으로 등록된 객체는 쉽게 주입하여 사용 가능

 

2. Bean 생명주기

  • 객체 생성 -> 의존 설정 -> 초기화 -> 사용 -> 소멸
  • 스프링 컨테이너에 의해 생명주기 관리
  • 스프링 컨테이너 초기화 시 빈 객체 생성, 의존 객체 주입 및 초기화
  • 스프링 컨테이너 종료 시 빈 객체 소멸

 

3. Bean 초기화 방법 3가지

  1. 빈 초기화 메소드에 @PostConstruct 사용
  • 빈 정의 xml에 <context:annotation-config></context:annotation-config> 추가
  1. InitializingBean 인터페이스의 afterPropertiesSet() 메소드 오버라이드
  2. 커스텀 init() 메소드 정의
  • 빈 정의 xml에 init-method 속성으로 메소드 이름 지정
  • 또는 빈 초기화 메소드에 @Bean(init-method="init") 지정

 

4. Bean 소멸 방법 3가지

  1. 빈 소멸 메소드에 @PreDestroy 사용
  • 빈 정의 xml에 <context:annotation-config></context:annotation-config> 추가
  1. DisposableBean 인터페이스의 destroy() 메소드 오버라이드
  2. 커스텀 destroy() 메소드 정의
  • 빈 정의 xml에 destroy-method 속성으로 메소드 이름 지정

 

5. 권장하는 방법

  • 1번 방법 (권장)
    • 사용 방법이 간결하며 코드에서 초기화 메소드가 존재함을 쉽게 파악 가능하여 xml 설정 방법보다 직관적
  • 2번 방법 (지양)
    • 빈 코드에 스프링 인터페이스가 노출되어 권장하지 않으며 간결하지 않은 방법
  • 3번 방법
    • 빈 코드에 스프링 인터페이스는 노출되지 않지만, 코드만으로 초기화 메소드 호출 여부를 알 수 없는 단점

 

6. Bean Scope

  • singleton (default)
    • 애플리케이션에서 Bean 등록 시 singleton scope로 등록
    • Spring IoC 컨테이너 당 한 개의 인스턴스만 생성
    • 컨테이너가 Bean 가져다 주입할 때 항상 같은 객체 사용
    • 메모리나 성능 최적화에 유리
  • prototype
    • 컨테이너에서 Bean 가져다 쓸 때 항상 다른 인스턴스 사용
    • 모든 요청에서 새로운 객체 생성
    • gc에 의해 Bean 제거
  • request
    • Bean 등록 시 하나의 HTTP request 생명주기 안에 단 하나의 Bean만 존재
    • 각각의 HTTP 요청은 고유 Bean 객체 보유
    • Spring MVC Web Application에서 사용
  • session
    • 하나의 HTTP Session 생명주기 안에 단 하나의 Bean만 존재
    • Spring MVC Web Application에서 사용
  • global session
    • 하나의 global HTTP Session 생명주기 안에 한 개의 Bean 지정
    • Spring MVC Web Application에서 사용
  • application
    • ServletContext 생명주기 안에 한 개의 Bean 지정
    • Spring MVC Web Application에서 사용

 

 

 

참고자료 : https://github.com/WeareSoft/tech-interview

Comments