스프링 ioc - seupeuling ioc

들어가며

  스프링 프레임워크란 자바 플랫폼을 위한 오픈소스 애플리케이션 프레임워크로 간단히 스프링(Spring)이라고도 합니다. 한국에서는 전자정부 프레임워크의 영향을 받아서인지 압도적인 점유을 보이고 있습니다. 스프링을 사용하면 여러 장점들이 있고 그래서인지 개발자들의 많은 선택을 받아 왔습니다. 이번 포스팅에선, 우리가 선택하고 있는 스프링 프레임워크에 뼈대가 되는 3대 요소 (IOC/DI, AOP, 서비스추상화) 에 대하여 글을 작성하도록 하겠습니다.

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

 Spring을 처음 접하게 되면 Servlet 컨테이너, EJB 컨테이너, IoC 컨테이너 등 Container라는 단어를 많이 듣게 됩니다.  컨테이너의 사전적 의미를 찾아보면 '화물을 능률적이고 경제적으로 수송하기 위해 사용하는 상자형 용기'를 의미합니다. 그렇다면 Spring에서 말하는 컨테이너란 무엇일까요? 마찬가지로 객체들을 담는 용기로 사용되어 지는데, Spring Container는 Spring Bean들의 생명주기를 관리합니다. 빈의 생성과 관계, 사용, 생명 주기를 관리하고 컨테이너를 통해 등록된 빈들은 시스템에 전반적으로 사용 가능합니다. 

 Spring Container는 어플리케이션을 구성하는 Bean들을 관리하기 위해 IoC(Inversion of Control, 제어의 역전)라는 개념을 이용하였습니다. 아래에 왼쪽 그림은 기존의 객체 생성방식입니다. 클래스 내부에 new 연산자를 이용하여 객체를 생성하였고 생명주기를 관리하였습니다. Spring에서는 오른쪽 그림의 방식으로 객체를 생성합니다. 외부에서 객체를 생성하고 생성자/수정자 방식을 이용하여 객체를 주입하는 방식을 채택하였습니다. 아 방식을 제어하는 주체가 역전되었다 하여 '제어의 역전(IoC)'라 부르며 스프링의 3대 핵심 요소입니다. 

 즉 IoC란 인스턴스의 생성부터 소멸까지의 인스턴스의 생명주기 관리를 컨테이너가 대신 해주는다는 것입니다.

의존성 주입 (Dependency Injection, DI)

 Spring DI란, IoC 컨테이너에서 빈객체를 생성하는 방식을 말합니다. 위 그림에서와 같이 기존 new로 생성하는 것을 외부에서 주입하는 방식으로 Spring에서는 Bean 생명주기를 관리하여 줍니다. 즉, IoC와 DI는 밀접한 관련이 있고 컨테이너에서 생명주기를 관리하여 준다는 것입니다. 이러한 DI는 3가지 의존성 주입 방식이 있습니다.

* 필드 주입

@RestController public class BookController { @Autowired private BookService bookService; }

- 가장 일반적이고 쉬운 DI 방법

- final로 지정할 수 없기에 mutable 하여 NullPointerException이 발생할 수 있습니다.

- Runtime에서 예기치 않은 순환참조 문제가 발생할 수 있습니다.

* 수정자 주입

@RestController public class BookController { private BookService bookService; public void setBookService(BookService bookService) { this.bookService = bookService; } }

- 생성당시 주입을 꼭 하지 않아도 됩니다. 즉, 원하는 호출 타이밍에 함수를 호출하여 주입시킬 수 있습니다.

- 마찬가지로 mutable하여 NullPointerException이 발생할 수 있습니다.

* 생성자 주입

@RestController public class BookController { private final BookService bookService; public BookController(BookService bookService) { this.bookService = bookService; } }

- Pivotal에서 가장 권장하는 DI 방식입니다.

- final 지정이 가능하기에 Immutable 합니다.

- 서버 실행시 순환참조로 인해 오류가 발생합니다. 즉 Runtime에서 순환참조가 발생하지 않습니다.

- 테스트 코드 작성이 유리합니다.

정리

 Spring의 3대 핵심 요소인 IoC/DI에 대하여 학습하였습니다. 서로 밀접한 상관 관계가 있고 Bean의 사이클을 관리하기에 Spring이 취하고 있는 Bean 생성/소멸 방식을 이해하는 것이 좋습니다. Bean 주입 방법으로는 3가지가 존재하는데, 가능하면 Spring 입문시 배우는 필드 주입 방식보식 보다 생성자 주입 방식으로 코드를 작성하는 것이 안전한 코드를 작성하는 방법입니다.

IoC(Inversion of Control)

IoC(Inversion of Control)를 해석하면 제어의 역전입니다.

이는 스프링 뿐만 아니라 모든 프로그래밍에서 사용될 수 있는 범용적인 개념입니다.

쉽게 말해 객체를 개발자 본인이 제어하는 것이 아닌 스프링 컨테이너에게 제어권이 넘어가는 것을 뜻합니다.

아래는 일반적으로 자바에서 객체를 생성하여 객체를 제어하는 코드입니다.

class ClassA { } class ClassB{ private ClassA a; ClassB() { this.a = new ClassA(); } }

보시다시피 개발자 본인이 new 연산자를 통해 직접 객체를 생성하고 변수에 할당해줘야 하는 방식입니다.

스프링의 경우 어떨까요?

아래코드는 스프링에서의 객체 할당 방식입니다.

@Component class ClassA { } class ClassB{ @Autowired private ClassA a; }

스프링의 경우 Bean(스프링에 의해 관리되는 객체)이라면 @Autowired 어노테이션을 통해 손쉽게 객체를 할당할 수 있습니다.

이는 개발자 본인이 객체를 관리하는 것이 아닌 스프링 컨테이너에서 객체를 생성하고 해당 객체를 할당 시켜준 것입니다.

이처럼 객체의 흐름, 생명주기관리등을 외부(제 3자)에서 처리하는 방식의 모델을 제어의 역전(IoC)라고 합니다.

DI(Dependency Injection)

DI란 객체를 외부로부터 할당받고 이를 통해 다이나믹하게 객체를 할당하는 방식입니다.

사용할 객체들을 컨테이너에 등록한 후 어플리케이션 코드에서 해당 객체를 setter함수의 매게변수로 받아와서 실행 시에 동적으로 의존관계를 설정해줍니다.

DI의 의존성 주입 방식에는 3가지가 있습니다.

  • 생성자를 이용한 의존성 주입
  • setter메소드를 이용한 의존성 주입
  • 초기화 인터페이스를 이용한 의존성 주입

스프링에서는 두번째 방식인 setter를 이용한 의존성 주입을 지지합니다. 이유는 외부에서 제공받은 객체를 저장해뒀다가 내부의 메소드에서 사용하게 하는 DI방식에서 활용하기에 적당하기 때문입니다.

이 IoC와 DI 덕분에 캡슐화를 통한 높은 응짚도와, 객체간의 낮은 결합도를 이루고 유연한 코드를 작성할 수 있도록 해주며, 개발자들이 개발에 더욱 집중할 수 있도록  해줍니다.

참고

  • //biggwang.github.io/2019/08/31/Spring/IoC,%20DI%EB%9E%80%20%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C/
  • //bcp0109.tistory.com/226
  • //velog.io/@gillog/Spring-DIDependency-Injection//mo-world.tistory.com/entry/IOC%EC%99%80-DI-%EC%97%90-%EB%8C%80%ED%95%98%EC%97%AC-%EC%8A%A4%ED%94%84%EB%A7%81-%EA%B0%9C%EB%85%90-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0-%EC%89%BD%EA%B2%8C-%EC%84%A4%EB%AA%85
  • //www.nextree.co.kr/p11247/

Toplist

최신 우편물

태그