포스트

스프링이란?

Spring Framework란?


  • 스프링 프레임워크(Spring Framework)는 자바의 주요한 개발 프레임워크 중 하나이다.
  • EJB의 복잡함을 해결하고자 만들어졌으며, 순수 자바 객체(POJO)를 사용하여 가벼운 코드로 엔터프라이즈 급 애플리케이션을 구축할 수 있는 가벼운 솔루션이자, One-Stop-Shop
  • IoC 컨테이너이며, 원하는 부분만 가져다 사용할 수 있도록 모듈화가 잘 되어 있다. 선언적 트랜잭션 관리와 완전한 기능을 갖춘 MVC Framework를 제공하며, 도메인 논리 코드와 쉽게 분리될 수 있는 구조를 가지고 있다.
  • 스프링의 핵심 기능에는 의존성 주입(Dependency Injection, DI), 제어의 역전(Inversion of Control, IoC), 그리고 관점 지향 프로그래밍(Aspect Oriented Programming, AOP)이 있다.
  • 위 요소들을 활용하면 느슨한 결합(Loose Coupling)을 달성할 수 있다. 이는 각각의 컴포넌트나 모듈이 서로 독립적으로 작동하고, 서로에게 영향을 덜 주면서 상호작용하는 것을 의미한다.
  • 느슨한 결합을 갖는 애플리케이션은 단위 테스트를 수행하기 용이하다. 각각의 컴포넌트가 서로 독립적으로 테스트될 수 있으며, 의존성 주입(Dependency Injection)을 통해 테스트용 더미 객체를 주입하여 테스트를 수행할 수 있다. 이는 애플리케이션의 각 부분을 분리하여 테스트할 수 있으므로 전체 시스템의 안정성과 품질을 높일 수 있다.
  • 대한민국에서는 기존의 스프링 프레임워크를 기반으로 한 전자정부 프레임워크를 개발하였다.


스프링의 핵심 개념


  1. 의존성 주입(DI, Dependency Injection) - 객체 간의 관계를 설정
    • IoC의 한 형태로, 객체 간의 의존 관계를 외부에서 주입하는 것을 의미한다. 스프링은 의존성 주입을 통해 객체 간의 관계를 설정한다. 설정 파일이나 어노테이션을 통해 정의하고, 스프링이 이를 이용하여 객체 간의 의존성을 관리한다.
    • 스프링은 의존성을 주입하면서 코드 간결성과 유연성을 확보할 수 있다. 또한, 애플리케이션의 결합도를 낮추고 테스트 용이성을 높인다. 예를 들어, @Autowired 어노테이션을 사용하여 객체를 주입할 수 있다.
    • 스프링을 사용하면 new 연산자를 직접 사용하여 객체를 생성할 필요가 없으며, 스프링 컨테이너가 객체를 생성하고 관리한다. 이렇게 설정을 통해 DI를 통해 객체 간의 의존성을 관리할 수 있다.
    • 직접 생성할 필요가 없으므로 IoC가 발생하여 스프링이 대신 객체를 생성해 준다. DI와 IoC의 개념은 함께 작용하며, 설정을 하면 스프링이 변수에 값을 주입하기에 null 값을 반환하지 않는다.
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    
     // DI 코드를 사용하지 않은 코드의 경우, Controller는 MyService 객체에 의존하게 된다.
     // 객체의 인스턴스를 얻게 되면 객체 간의 결합도가 올라간다. 이러한 코드 작성은 단위테스트를 위한 Mock 객체를 사용할 수 없게 된다.
     @RestController
     public class NoDIController{
     	private MyService service = new MyCerviceImpl();
        	
     	@GetMapping("/hello")
     	public String getHello(){
     		 return service.getHello();
     	}
     }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    
     // DI를 사용하는 코드의 경우, @Service, @Autowired 어노테이션을 통해서 MyService의 인스턴스를 획득할 수 있다.
     // 단위테스트에서 MyService 객체를 Mock 객체로 대체하여 쉽게 테스트 할 수 있다.
     public class MyService implements MyService{
     		@Override
     		public String getHello(){
     			return "Hello";
     }
     		@RestController
     		public class DIController{
     				MyService myService; // null 값을 반환하지 않는다.
        				
     				@Autowired
     				public DIController(MyService myService){
     					this.myService = myService;				
     				}
        				
     				@GetMapping("/hello")
     				public String getHello(){
     					 return myService.getHello();
     				}
     }
    
  2. 제어의 역전, 제어의 반전( IoC, Inversion of Control) - IoC 컨테이너를 통해 객체의 생성과 생명주기 관리를 담당
    • 제어의 역전 또는 제어의 반전(IoC, Inversion of Control)은 소프트웨어 개발에서 프로그램의 제어 흐름이 개발자가 아닌 외부에 의해 결정되는 디자인 원칙이다. 이는 개발자가 코드를 작성하는 것이 아니라 프레임워크나 컨테이너에 의해 코드가 실행되는 것을 의미한다.
    • 스프링 프레임워크에서는 IoC 컨테이너를 통해 객체의 생성과 생명주기 관리를 담당한다. 개발자는 객체의 생성과 의존성 관리를 프레임워크에게 위임함으로써 제어의 역전을 실현한다.
    • 스프링 컨테이너(BeanFactory, ApplicationContext)는 설정 정보(XML이나 어노테이션)를 읽어들여 객체를 생성하고, 의존성을 주입하며, 객체의 생명주기를 관리한다.
    • 개발자는 설정 파일이나 어노테이션을 통해 객체들의 관계와 동작 방식을 정의하고, 스프링 컨테이너가 이를 실행함으로써 제어의 역전을 이용하여 개발을 진행할 수 있다. 이는 마치 웹 애플리케이션 서버(WAS)가 서버의 생명 주기를 관리하고 요청을 처리하는 것과 유사하다.
    • 일반적으로 객체의 생성과 생명주기 관리를 애플리케이션 코드가 담당하지만, 스프링 프레임워크에서는 이러한 제어를 프레임워크 자체가 담당한다. 따라서 개발자가 객체를 직접 생성하고 관리하는 대신, 스프링 컨테이너가 객체의 생성과 관리를 담당하며, 이를 통해 개발자는 객체에 대한 제어권을 반전시킨다.
  3. 관점 지향 프로그래밍(AOP, Aspect Oriented Programming) - 공통되는 기능들을 중복 없이 쉽게 적용
    • 스프링은 AOP를 지원하여 애플리케이션의 핵심 비즈니스 로직과 부가적인 기능(로깅, 트랜잭션 관리 등)을 분리하여 모듈화할 수 있다.
    • AOP는 OOP(Object-Oriented Programming)를 보완하는 수단으로, 공통적으로 사용되는 기능들을 모듈화하여 필요한 곳에 연결함으로써 유지보수나 재사용이 용이하도록 한다.
    • 공통 기능들은 하나의 클래스에 모아두고 필요할 때 재사용한다. 또한, 기존의 실행 흐름을 끊고 특정 클래스가 실행되기 전에 다른 작업을 수행할 수 있다.
    • 예를 들어, 회원 조회와 게시글 조회 로직은 세션 생성과 종료와 같은 공통적인 부분이 있다. SQL 문만 다르기 때문에 이러한 공통 사항을 aspect로 분리하여 자동으로 처리하는 기술이다.
    • AOP를 통해 기존 프로젝트에 다양한 기능을 로직을 수정하지 않고 추가할 수 있다. 이런 개발 방식을 통해 결합도를 낮출 수 있어 더 유연하고 확장 가능한 개발이 가능하다.
  4. POJO(Plain Old Java Object) - EJB의 불편한 설정을 해소, 객체지향 개발의 원칙에 충실한 객체
    • 객체지향 개발의 원칙에 충실한 객체를 의미한다. 이는 특정한 제약이나 요구사항에 종속되지 않는 간단하고 순수한 자바 객체를 말한다. POJO는 다른 외부 라이브러리나 프레임워크에 의존하지 않고 순수한 자바 코드로 작성된 객체를 지칭한다.
    • 스프링은 POJO를 사용하여 객체지향 개발의 원칙에 충실한 객체를 만들 수 있도록 한다. 이를 통해 개발자는 복잡한 설정이나 프레임워크에 의존하지 않고도 유연하고 확장 가능한 코드를 작성할 수 있다.
    • 스프링에서는 POJO로 작성된 클래스를 Spring Bean으로 등록하여 스프링 컨테이너에 저장하고 관리한다. 이렇게 등록된 Spring Bean은 스프링 애플리케이션 내에서 필요한 곳에서 사용될 수 있다.
    • 스프링에서 클래스를 스프링 애플리케이션 컨텍스트(스프링 컨테이너)에 등록하여 관리하는 것을 Spring Bean으로 지칭한다. 스프링 프레임워크가 이러한 객체를 관리하는 것이 스프링의 핵심 역할 중 하나이며, 이를 통해 의존성 주입(Dependency Injection) 등의 기능을 제공한다.
  5. 컴포넌트 스캔 - 스프링이 직접 클래스를 검색하여 빈으로 등록
    • 이는 주로 자동 주입과 함께 사용되며, 설정 클래스에 빈으로 등록하지 않아도 원하는 클래스를 빈으로 등록할 수 있어서 설정 코드를 간결하게 만들어준다.
    • 일반적으로 @Component 어노테이션을 사용하여 해당 클래스를 스캔 대상으로 지정한다. 이렇게 지정된 클래스는 스프링이 자동으로 검색하여 빈으로 등록한다.
    • 즉, 컴포넌트 스캔을 사용하면 스프링이 자동으로 클래스를 찾아 빈으로 등록해주기 때문에 개발자는 더 간단하고 효율적으로 스프링 애플리케이션을 구성할 수 있다.
  6. 웹 개발 지원
    • 스프링은 웹 애플리케이션 개발을 위한 다양한 기능과 웹 프레젠테이션 계층을 제공한다.
    • 스프링 MVC는 유연하고 확장 가능한 웹 애플리케이션을 개발할 수 있는 MVC(Model-View-Controller) 아키텍처를 지원한다. 이 아키텍처를 통해 개발자는 모델(Model), 뷰(View), 컨트롤러(Controller)로 애플리케이션을 분리하여 유지보수와 확장성을 향상시킬 수 있다.


스프링 프레임워크 구성 모듈


  • 스프링 프레임워크는 20개의 모듈로 구성되어 있으며, Core Container, Data Access/Integration, Web, AOP(Aspect Oriented Programming), Instrumentation 및 Test로 그룹화된다.

이미지

  • 이러한 모듈들을 조합하여 스프링 프레임워크를 사용하면 애플리케이션을 효과적으로 개발할 수 있다.
모듈 명내용
spring-beans스프링 컨테이너를 이용해서 객체를 생성하는 기본 기능을 제공한다.
spring-context객체 생성, 라이프 사이클 처리, 스키마의 확장 등의 기능을 제공한다.
spring-aopAOP(Aspect-Oriented Programming) 기능을 제공한다.
spring-webREST 클라이언트 데이터 변환 처리, 서블릿필터, 파일 업로드 지원 등 웹 애플리케이션을 개발하는데 필요한 기반 기능을 제공한다.
spring-webmvc스프링 기반의 MVC(Model-View-Controller) 프레임워크, 웹 애플리케이션을 개발하는데 필요한 컨트롤러, 뷰 구현 제공
spring-websocket스프링 MVC에서 웹 소켓 연동을 처리할 수 있도록 지원한다.
spring-oxmXML과 자바 객체 간의 매핑을 처리하기 위한 API 제공한다.
spring-tx트랜잭션 처리를 위한 추상 레이어를 제공한다.
spring-jdbcJDBC 프로그래밍을 보다 쉽게 할 수 있는 템플릿을 제공한다.
spring-ormHibernate, JPA, MyBatis 등과의 연동을 지원한다.
spring-jmsJMS(Java Message Service) 서버와 메시지를 쉽게 주고 받을 수 있도록 하는 템플릿을 제공한다.
spring-context-support스케줄링, 메일 발송, 캐시 연동, 벨로시티 등의 부가기능을 제공한다.


빈 라이프사이클과 범위


  1. 컨테이너 초기화와 종료
    • 컨테이너 초기화:
      • 스프링 컨테이너의 초기화는 컨텍스트 객체를 생성할 때 발생한다.
      • 스프링 컨테이너는 설정 클래스에서 정보를 읽어와 알맞은 빈 객체를 생성하고 각 빈을 연결(의존 자동 주입)하는 작업을 수행한다.
    • 컨테이너의 사용:
      • getBean()과 같은 메서드를 이용해서 컨테이너에 보관된 빈 객체를 구한다.
    • 컨테이너의 종료:
      • 종료 메서드인 close()를 호출하여 컨테이너를 종료한다.
      • close() 메서드는 AbstractApplicationContext 클래스에 정의되어 있다.
      • 자바 설정을 사용하는 AnnotationConfigApplicationContext 클래스나 XML 설정을 사용하는 GenericXmlApplicationContext 클래스는 모두 AbstractApplicationContext를 상속받는다.
  2. 스프링 빈 객체의 라이프 사이클
    • 스프링 컨테이너는 빈 객체의 라이프 사이클을 관리한다.
    • 초기화:
      • 스프링 컨테이너를 초기화할 때 스프링 컨테이너는 가장 먼저 빈 객체를 생성하고 의존을 설정한다. 의존 자동 주입을 통한 의존 설정이 이 시점에서 수행된다.
    • 초기화 메서드 호출:
      • 모든 의존 설정이 완료되면 빈 객체의 초기화를 수행한다. 이때 스프링은 빈 객체의 지정된 초기화 메서드를 호출한다.
    • 소멸:
      • 스프링 컨테이너를 종료하면 빈 객체의 소멸을 처리한다. 이때에도 지정된 메서드를 호출하여 빈 객체를 소멸시킨다.
    • 스프링 컨테이너는 빈 객체와 빈 이름을 연결하는 정보를 가지며, 빈 객체의 생성, 초기화, 보관, 제거 등을 관리한다. ApplicationContext (또는 BeanFactory)는 이러한 기능을 수행하며, 컨테이너라고도 부른다. AnnotationConfigApplicationContext 클래스는 ApplicationContext 인터페이스를 구현한 클래스 중 하나로, 자바 클래스에서 정보를 읽어와 객체 생성과 초기화를 수행한다.


1
2
컨테이너의 초기화 → 빈 객체의 생성, 의존 주입, 초기화
컨테이너의 종료 → 빈 객체의 소멸 
1
2
3
스프링의 핵심 기능은 객체의 생성과 초기화이다.
ApplicationContext(또는 BeanFactory): 스프링에서는 ApplicationContext 또는 BeanFactory를 통해 빈 객체의 생성, 초기화, 보관, 제거 등을 관리한다. 이는 컨테이너(Container)라고도 불린다. 스프링 컨테이너는 내부적으로 빈 객체와 빈 이름을 연결하는 정보를 가지고 있다.
ApplicationConfigApplicationContext 클래스: ApplicationContext 인터페이스를 구현한 클래스 중 하나로, 자바 클래스에서 정보를 읽어와 객체 생성과 초기화를 수행한다. 이를 통해 스프링 애플리케이션에서 설정된 빈들을 관리하고 제어할 수 있다.


스프링 동작 구조


  • Spring 애플리케이션

이미지

  • Spring 웹

이미지

  1. 클라이언트의 요청을 받는다.
  2. 스프링 컨테이너는 설정 파일을 읽어와서 서블릿 컨테이너에 Dispatcher Servlet을 연결한다. 이때, web.xml 설정 파일을 참조한다.
  3. 스프링 컨테이너가 가동되면서 클라이언트의 요청과 응답을 처리할 수 있는 Context를 생성한다. 이 과정에서 servlet-context.xml과 같은 스프링 설정 파일을 불러온다.
  4. 클라이언트의 요청이 들어오면, HandlerMapping을 통해 해당 요청을 처리할 Controller 객체와 메소드를 찾는다.
  5. 매핑된 Controller의 메소드가 실행되고, 그 결과를 ModelAndView 객체에 담아서 반환한다. 이후, 스프링 설정 파일에 정의된 ViewResolver가 해당 JSP 화면을 찾아 사용자에게 응답으로 보낸다.


Spring MVC 요청 처리 과정


이미지

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.