<추천글>[spring] 스프링 프레임워크 정의하기

2021. 8. 21. 15:29[ 백엔드 개발 ]/[ Spring ]

스프링 프로젝트를 진행하면서 느꼈던 것은 그 목표를 분명히 알고 사용하지 않으면 그 가치를 제대로 얻기 힘들다는 것이였다. 스프링이 제공하는 기술들을 갖다 사용하면 단순히 스프링을 적용한 것 뿐이지 스프링의 장점이 활용되었다고 보기 힘들다. 따라서 스프링의 목적과 왜 만들어졌는지를 파악하고 스프링이 제공해주는 혜택을 제대로 누려서 활용해야 한다는 생각이 들었다.

 

 

'스프링 프레임워크'란?

Spring의 정의는 다음과 같다.

 

 

자바 엔터프라이즈급 개발을 쉽게 해주는 '애플리케이션 프레임워크'

 

 

위 스프링 정의를 보면 쉽게 와닿지 않을 것이다. 따라서 스프링의 정의에서 설명하고 있는 애플리케이션 프레임워크에 대해 알 필요가 있다.

 

애플리케이션 프레임워크?

애플리케이션 프레임워크를 이해하기 전에 프레임워크가 무엇인지 파악할 필요가 있다. 프레임워크는 미리 만들어 둔 라이브러리의 집합이라고 생각하기 쉽다. 하지만 프레임워크의 가장 큰 특징은 흐름에 대한 제어권을 가지고 있다는 것이다. 프레임워크 기반의 애플리케이션에서는 애플리케이션 코드가 프레임워크에 의해서 사용된다. 즉, 프레임워크가 흐름을 주도하면서 개발자가 만든 애플리케이션 코드를 사용하는 것이다.(IoC) 쉽게 말하면 애플리케이션 코드가 프레임워크에 작성해 놓은 틀에서 수동적으로 동작하게 되는 것이다.

 

cf. Hollywood Principle : 호출을 하지말고 프레임워크가 호출할 때까지 기다려라

 

그렇다면 이제, 프레임워크와 애플리케이션 프레임워크를 구분해보자. 프레임워크는 보통 "한 가지 기술에 특화된 목표"를 가지고 만들어진다. 그래서 프레임워크는 애플리케이션의 "특정 계층에서 주로 동작하는 한 가지 기술 분야에 집중된다." 예를들어  Hibernate는 ORM 이라는 한 가지 기술에 특화된 프레임워크이다.

 

이와 다르게 애플리케이션 프레임워크는 특정 계층이나, 기술에 국한되지 않고 애플리케이션의 전 영역을 포괄하는 범용적인 프레임워크를 의미한다. 따라서 애플리케이션 프레임워크는 특정 기술 하나에 대해서가 아니라, 애플리케이션 개발의 전체적인 과정에 대한 제어권을 가짐으로써, 개발이 빠르고 편리하게 진행될 수 있도록 하는데에 목표를 두고 있다. 따라서 스프링은 자바 엔터프라이즈급 개발의 전체적인 영역을 포괄하는 애플리케이션 프레임워크이다.

 

예를 들어, Service 객체는 자신이 어떤 Repository를 사용할지 선택하지 않고 생성하지도 않는다. 객체 생성에 대한 제어권을 ApplicationContext에게 넘긴 것이다. (IoC가 발생한 상황임)

 

스프링은 여러 계층에서 사용되는 다양한 프레임워크와 기술들이 서로 양립하고 적용될 수 있도록하고 엔터프라이즈급 애플리케이션의 전 계층과 전 영역에 전략과 기능을 제공해준다.

 

cf. 스프링 개발업체인 스프링소스는 2009년에 VMWare에 합병되었다.

 

 

IoC (Inversion of Control)

위에서 말했듯이 Spring 과 같은 애플리케이션 프레임워크는 애플리케이션의 전반적인 흐름에 대한 제어권을 가지고 있다. 이러한 기술을 IoC라고 하며 단어 뜻인 Inversion of Control과 마찬가지로 제어권이 소스코드가 아닌 프레임워크로 역전되었음을 의미한다. 여기서 제어권이란 객체 간 의존성(dependency)을 형성 또는 파괴하는 과정을 포함한 애플리케이션의 전체적인 흐름에 대한 제어권을 말한다. 이런 IoC를 가능하게 하는 공간 또는 장소를 'IoC 컨테이너'라고 한다. 

 

This chapter covers the Spring Framework implementation of the Inversion of Control (IoC) principle. IoC is also known as dependency injection (DI). It is a process whereby objects define their dependencies (that is, the other objects they work with) only through constructor arguments, arguments to a factory method, or properties that are set on the object instance after it is constructed or returned from a factory method. The container then injects those dependencies when it creates the bean. This process is fundamentally the inverse (hence the name, Inversion of Control) of the bean itself controlling the instantiation or location of its dependencies by using direct construction of classes or a mechanism such as the Service Locator pattern.

 

위 스프링 공식 문서를 보면 알 수 있듯이 사실 IoC는 다양한 방법으로 만들 수 있다. 전략 패턴, 서비스 로케이터 패턴, 팩토리 패턴 그리고 의존관계 주입패턴들이 있다. 그리고 이러한 IoC는 bean들의 dependecy를 정의한 객체에 의해 진행된다. IoC container가 bean들을 생성하고 그들의 dependency를 주입한다. 즉, IoC container에서 개별 객체들 간의 의존관계 설정이 이루어 지고 객체들에 대해 생성과 파괴를 모두 관장한다. IoC container에게 이런 객체를 사용할 것이다(설정파일 또는 어노테이션 기반) 라고 알려주면 IoC컨테이너가 객체 생성 및 의존관계 설정을 만들어 준다.

 

 

ApplicationContext

IoC 컨테이너는 ApplicationContext라는 인터페이스를 통해 제공된다. ApplicationContext는 일종의 IoC 컨테이너이며, 우리가 정의한 configuration metadata파일(java 또는 xml)을  ApplicationContext에게 전달해 주면 필요한 의존관계를 맺어주고 생명주기를 관리하면서 객체에 대한 인스턴스를 만들어준다.

 

  • ApplicationContext는 'BeanFactory'를 상속한다. BeanFactory의 getBean 메소드를 보면 알 수 있듯이, 객체에 대한 생성과 조합, 의존관계를 설정하는 IoC의 기본 기능이 들어 있다.
  • BeanFactory에서 IoC기본 기능을 대부분 하고, 추가된 기능들은 ApplicationContext에서 한다. ApplicationContext는 bean 생성 뿐만 아니라, bean의 lifecycle관리 및 bean 생성 후 진행할 과정 등을 정의할 수 있다. 쉽게말하면 BeanFactory는 Bean을 생성하는 역할을하고, ApplicationContext는 그외 모든 작업을 한다고 생각하면 편하다.
  • ApplicationContext에 실제 만들어야 할 bean정보를 Configuration Metadata (설정 메타데이터)로부터 받아온다. 이 메타데이터를 이용해서 IoC 컨테이너에 의해 관리되는 객체들을 생성하고 구성한다. 즉, 개발자는 Spring에게 제어를 넘길 객체(Bean)를 Configuration Metadata 파일에 등록해주면 이들에 대한 생성, 파괴, 의존관계 주입등이 이루어진다.
  • ApplicationContext는 인터페이스이고 하위에 이를 구현하는 수많은 구현체가 있다. Configuration Metadata는 XML이나 자바파일 기반으로 작성할 수 있다. XML 기반으로 할 경우 ApplicationContext의 GenericXmlApplicationContext를 구현체로 사용하고 Java 기반의 설정을 이용할 경우 ApplicationContext의 AnnotationConfigApplicationContext 구현체를 사용한다. SpringBoot를 사용한다면 어노테이션 기반으로 (컴포넌트 스캔 방식) 쉽게 Bean을 등록할 수 있다.

 

 

 

Bean

In Spring, the objects that form the backbone of your application and that are managed by the Spring IoC container are called beans. A bean is an object that is instantiated, assembled, and managed by a Spring IoC container. Otherwise, a bean is simply one of many objects in your application. Beans, and the dependencies among them, are reflected in the configuration metadata used by a container.

 

스프링 공식문서에서 위와 같이 Bean을 소개한다. 정리하면 다음과 같다.

 

  •  Spring에서 애플리케이션의 백본(구성 도면)을 형성하고 Spring IoC 컨테이너에 의해 관리되는 객체를 Bean이라고 한다.
  • Bean은 Spring IoC 컨테이너에 의해 인스턴스화, 조립 및 관리되는 객체이다.
  • Bean들 간의 dependency는 IoC 컨테이너에서 사용하는 configuration metadata에 의해 반영된다. 
  • IoC 컨테이너에서 관리되는 객체와 아닌 객체를 구분하기 위해 사용하는 용어로 이해하자

 

 

 

 

왜 스프링을 사용하나?

스프링의 목적은 엔터프라이즈 개발의 복잡함을 해결하는 것이다. 복잡함이 발생한 근본적인 이유는 1) 기술적인 제약조건과 요구사항이 늘어나고, 2) 엔터프라이즈 애플리케이션이 구현해야 할 핵심기능인 비즈니스 로직의 복잡함이 증가하기 때문이다. (이 부분은 너무 추상적이여서 아직 학생의 입장에서 이해하기 힘들다.. PASS..)

 

즉, 비지니스 로직 외에도 고려할 사항들이 너무 많았고, 개발이 진행되면서 비지니스 로직이 점점 복잡해지며 변경사항들이 많아졌다. 스프링은 이와 같은 복잡함을 해결하고 특정 환경에 불필요한 연결 없이 객체를 POJO 스타일로 구현하게 함으로써 개발자가 비즈니스 로직에 집중할수 있도록 한다.

 

// 이런 복잡함을 해결하기 위한 스프링의 특징으로 DI, AOP, PSA가 있다.

 

 

 

Reference

- https://docs.spring.io/spring-framework/docs/current/reference/html/core.html