Spring 입문

P·2021년 11월 1일
0

Spring Framework

[AOP, IoC/DI, PSA](Spring Triangle) 기술을 바탕으로 POJO(Plain Old Java Object)를 지향하는 경량의 오픈소스 프레임워크


IoC(Inversion of Control)

제어의 역전, 객체의 생성부터 생명주기 관리까지 모두 컨테이너가 하게 되므로 제어권이 컨테이너로 넘어는것이 제어권의 흐름이 바뀌었다고 하여서 IoC라고 함

  • 스프링에서 제공하는 컨테이너를 IoC 컨테이너라고 함
  • 제어권이 컨테이너로 넘어왔기 때문에 DI, AOP가 가능하게 됨

DI(Dependancy Injection, 의존성 주입)

객체를 직접 생성하는 것이 아닌 외부에서 생성 후 주입하는 방식

1.객체 내부에서 다른 객체를 생성하는 것은 결합이 강하다

A 객체에서 B 객체를 직접 생성하면 후에 B 대신 C 객체로 교체 시 A 객체도 같이 교체해야 함

public class A{
	private B b;
    	public A(){
    	b = new B();
	}
}

2.외부에서 생성하고 주입하면 결합이 느슨하다

  • Field 주입
  • Setter 주입
  • 생성자 주입

Field 주입

public class A{

	@Autowired
	private B b;
}
  • 의존성의 주입이 쉽다.
  • 쉬운 의존성 주입은 하나의 클래스가 너무 많은 기능을 하게 함으로써 객체는 그에 맞는 동작만 한다는 원칙에 위배될 수 있음
  • 추상화 된 관계는 의존성을 검증하기 힘듦
  • Field 주입을 하면 해당 클래스를 바로 인스턴스화할 수 없다.
  • Field 주입을 하면 final 선언이 불가능하기 때문에 객체는 가변적으로 변한다.

Setter 주입

public class A{

	private B b;
    
	@Autowired
    	public void SetB(B b){
    	this.b = b;
    }
	
}
  • Spring 3.x까지 권장하던 방식
  • @Required를 이용하여 의존성이 필요한 Setter를 만들 수 있다.

생성자 주입

public class A{

	private final B b;	// final 선언 가능
    
	@Autowired		// Spring 4.3 이상 버전부터 생성자가 하나일 경우 생략 가능
    	public A(B b){
    	this.b = b;
    }
	
}
  • Spring 4.x 부터 권장

빈(Bean)

Spring IoC 컨테이너가 관리하는 자바 객체들을 빈(Bean)이라고 함

  • 스프링은 이런 Bean들의 의존성을 관리하고 객체를 만들고 Bean에 등록하고 관리함
  • new 연산자로 생성한 객체는 빈이 아님
  • ApplicationContext.getBean()으로 얻을 수 있는 객체는 빈임
  • 스프링에서 빈은 ApplicationContext가 만들어서 그 안에 담고 있는 객체를 의미함
  • Spring IoC 컨테이너에 빈을 등록하는 방법
    • Component Scanning
    • 직접 등록(XML 또는 자바 설정 파일)
  • 빈을 사용하는 방법
    • @Autowired 또는 @Inject
    • ApplicationContext에서 getBean()으로 직접 사용

Bean 등록방법

Component Scanning

@Component Annotation을 사용하여 Bean에 등록

  • @Repository
  • @Service
  • @Controller
  • @Configuration

직접 등록(XML 또는 자바 설정 파일)

XML과 자바 설정 파일이 있지만 주로 자바 설정 파일로 작성

@Configuration
public class SampleConfiguration{
	@Bean
    	public SampleController sampleController(){
        	return new SampleController;
        }
}
  • 주로 ~Configuration으로 작성하고 클래스 위에 @Configuration 붙인다.
  • 클래스 내부에 @Bean을 사용해서 직접 빈을 정의함
  • SampleController()에서 리턴되는 객체가 IoC 컨테이너 안에 빈으로 등록됨
  • 직접 빈을 등록하면 @Component를 안붙여도 됨
  • @Configuration Annotation도 @Component를 사용하기 때문에 @ComponentScan의 대상이 되고 빈 설정파일을 읽을 때 정의한 빈들이 IoC 컨테이너에 등록됨

XML 설정하는 경우

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xmlns:context="http://www.springframework.org/schema/context"
      xsi:schemaLocation="http://www.springframework.org/schema/beans
                          http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
                          http://www.springframework.org/schema/context
                          http://www.springframework.org/schema/context/spring-context-4.3.xsd">

<bean id="dog" class="com.study.Dog">
	<property name="petName" value="retriver"></property>
</bean>

<bean id="cat" class="com.study.Cat">
	<property name="petName" value="munchkin"></property>
</bean>

<bean id="petOwner" class="com.study.PetOwner" scope="singleton">
	<constructor-arg name="animal" ref="dog"></constructor-arg>
</bean>
</beans>
  • class: 정규화 된 자바 클래스 명(필수값)
  • id: 빈의 고유 식별자
  • scope: 객체의 범위
  • constructor-arg: 객체 생성 시 생성자에 전달할 인수
  • property: 생성 시 빈 Setter에 전달할 인수
  • init-method: 객체 생성 시 실행되는 함수
  • destroy-method: 객체 소멸 시 호출되는 함수

빈 생성 범위(Scope)


1. 싱글톤(Singleton)

  • 기본적으로 빈은 싱글톤(Singleton)으로 생성
  • 생성된 인스턴스는 Single Beans Cache에 저장되어 요청과 참조가 있으면 캐시에 저장된 객체를 반환
  • 컨테이너가 제공하는 모든 빈의 인스턴스는 항상 동일(스프링이 Bean마다 하나의 객체를 생성)
  • 컨테이너가 항상 새로운 인스턴스를 반환하고 싶으면 prototype으로 설정
  1. 프로토타입(Prototype)
  • 하나의 빈 정의에 다수의 객체 존재
  1. 요청(Request)
  • 하나의 빈 정의에 대해 하나의 HTTP request 생명 주기 내에서 하나의 객체만 존재
  • 각각의 HTTP request는 각각의 객체를 가진다.
  • Web-aware Spring ApplicationContext 안에서만 유효함
  1. 세션(Session)
  • 하나의 빈 정의에 대해 하나의 HTTP session 생명 주기 내에서 하나의 객체만 존재
  • Web-aware Spring ApplicationContext 안에서만 유효함
  1. 글로벌 세션(Global Session)
  • 하나의 빈 정의에 대해 하나의 Global HTTP session 생명 주기 내에서 하나의 객체만 존재
  • 일반적으로 portlet context 에서 사용되는 경우만 유효함
  • Web-aware Spring ApplicationContext 안에서만 유효함
  1. 애플리케이션(Application)
  • 하나의 빈 정의에 대해 하나의 ServletContext 생명 주기 내에서 하나의 객체만 존재
  • Web-aware Spring ApplicationContext 안에서만 유효함
  1. 웹 소켓(Websocket)
  • 하나의 빈 정의에 대해 하나의 WebSocket 생명 주기 내에서 하나의 객체만 존재
  • Web-aware Spring ApplicationContext 안에서만 유효함
(출처: https://docs.spring.io/spring-framework/docs/3.0.0.M3/reference/html/ch04s04.html)

Bean 사용방법

@Autowired Annotation으로 빈을 사용

  • 빈을 사용한다 = 의존성을 주입한다
@Autowired	// 생성자 사용
public OwnerController(OwnerRepository clinicService){
	this.owners = clinicService;
}

ApplicationContext에서 getBean() 직접 사용

public class SampleControllerTest{

	@Autowired
    	ApplicationContext applicationContext;
        
        @Test
        public void testDI(){
        	SampleController bean = applicationContext.getBean(SampleController.class);
		// bean.~~~; 사용
        }
}

AOP(Aspect Oriented Programming)

관점 지향 프로그래밍, 여러 객체에 공통으로 적용할 수 있는 기능(=부가 기능)을 구분하여 분리해서 재사용성을 높이는 프로그래밍 기법

  • 핵심 기능과 부가 기능의 구현을 분리함으로써 핵심 기능을 구현한 코드 수정없이 뷰거 기능을 적용할 수 있게 함
  • OOP 기법으로 프로그래밍 한 코드에서 핵심 기능과 부가 기능을 분리하기 어려운 문제점을 해결하기 위해 AOP를 사용함

AOP 주요 용어

  • JoinPoint: Advice가 적용될 위치, 타겟 객체가 구현한 인터페이스의 모든 메소드는 JoinPoint가 될 수 있다.
  • PointCut: Advice를 적용할 타겟의 메소드를 선별하는 정규표현식, JoinPoint의 상세한 스펙 정의, 표현식은 execution으로 시작하고 메소드의 Signature를 비교하는 방법 이용
  • Advice: AOP에서 실제 실행 되는 코드, 타겟에 제공할 실질적 부가기능을 담고 있는 모듈
  • Target: 핵심 기능을 담고 있는 모듈, 타겟은 부가기능을 부여할 대상(클래스 또는 메소드 등)
  • Aspect: AOP의 기본 모듈, Aspect = Advice+PointCut, 싱글톤 형태의 객체로 존재
  • Advisor: Spring AOP에서만 사용되는 용어, Advisor = Advice+PointCut
  • Weaving: PointCut에 의해 결정된 TargetJoinPoint에 부가기능을 삽입하는 과정, AOP가 핵심 기능에 영향을 주지 않으면서 필요한 부가기능을 추가할 수 있도록 해주는 핵심적인 처리과정

AOP 특징

  1. 프록시 기반 AOP 지원
    • Spring은 Target 객체에 대한 프록시를 만들어 제공
    • Target을 감싸는 프록시는 Runtime시 생성됨
    • 프록시는 AdviceTarget 객체에 적용하면서 생성되는 객체
  2. 프록시가 호출을 가로챔(Intercept)
    • 프록시는 Target 객체에 대한 호출을 가로챈 다음 Advice의 부가기능 로직을 수행하고 난 후에 Target의 핵심 기능 로직을 호출함(Before Advice)
    • Target의 핵심 기능 로직을 호출한 후에 부가 기능을 호출할 수도 있음(After Advice)
  3. AOP는 메소드 JoinPoint만 지원한다.
    • Spring은 동적 프록시를 기반으로 AOP를 구현하므로 메소드 JoinPoint만 지원함
    • 핵심 기능(Target)의 메소드가 호출되는 Runtime 시점에서만 부가 기능(Advice)을 적용할 수 있다.
    • AspectJ 같은 AOP 프레임워크를 사용하면 객체의 생성, 필드 조회, 조작, static 메소드 호출 및 초기화 등 다양한 작업에 부가기능을 호출할 수 있음

Advice의 종류

  • Before Advice: 대상 객체의 메소드 호출 전에 공통 기능을 실행
  • After Returining Advice: 대상 객체의 메소드가 Exception 없이 실행된 이후에 공통 기능을 실행
  • After Throwing Advice: 대상 객체의 메소드를 실행하는 도중 Exception이 발생한 경우에 공통 기능을 실행
  • After Advice: 대상 객체의 메소드를 실행하는 도중에 Exception 발생 여부와 상관없이 메소드 실행 후 공통 기능을 실행
  • Around Advice: 대상 객체의 메소드 실행 전, 후 또는 Exception 발생 시점에 공통 기능 실행 (주로 사용)

PSA(Portable Service Abstraction)

추상화 계층을 사용하여 어떤 기술을 내부에 숨기고 개발자에게 편의성을 제공해 주는 것을 서비스 추상화(Service Abstraction)라고 함. 서비스 추상화로 제공되는 기술을 다른 기술 스택으로 간편하게 바꿀 수 있는 확장성을 가지고 있는 것이 PSA(Portable Service Abstraction)

  • Spring은 Spring Web MVC, Spring Transaction, Spring Cache등의 다양한 PSA 제공

Spring MVC

일반 클래스에 @Controller를 사용하면 request를 mapping 할 수 있는 컨트롤러 역할을 수행하는 클래스가 됨. 해당 클래스에서 @GetMapping, @PostMapping Annotation을 사용하여 mapping할 수 있다.

  • servlet을 low level로 개발하지 않고(HttpServlet을 상속받고 doGet(), doPost()를 구현하는 작업을 하지 않고) Spring MVC를 이용하여 간편하게 개발할 수 있다.
  • Service Abstract의 목적 중 하나가 이러한 편의성을 제공하는 것
  • Spring MVC는 @Controller, @RequestMapping Annotation과 뒷단의 여러가지 복잡한 인터페이스들을 기반으로하여 기존 코드를 거의 변경하지 않고 웹 기술 스택을 간편하게 바꿀 수 있게 함

Spring Transaction

low level로 Transaction 처리를 하려면 setAutoCommit()commit(), rollback()을 명시적으로 호출해야 한다. 그러나 Spring이 제공하는 @Transaction Annotation을 사용하면 단순히 메소드에 Annotation을 붙여줌으로써 트랜잭션 처리가 이루어진다.

  • 이 또한 PSA로써 다양한 기술 스택으로 구현체를 바꿀 수 있다.
  • JDBC를 사용하는 DatasourceTransactionManager, JPA를 사용하는 JpaTransactionManager, Hibernate를 사용하는 HibernateTransactionManager를 유연하게 바꿔서 사용할 수 있다.
  • 기존 코드는 변경하지 않은 채로 Transaction을 실제로 처리하는 구현체를 사용 기술에 따라 바꿔 끼울 수 있다.

Spring Cache

Cache도 마찬가지로 JCacheManager, ConcurrentMapCacheManager, EhCacheCacheManager와 같은 여러가지 구현체를 사용할 수 있다.

  • 사용자는 @Cacheable Annotation을 붙여줌으로써 구현체를 크게 신경쓰지 않아도 필요에 따라 바꿔 쓸 수 있다.

Spring은 이렇게 특정 기술에 직접적 영향을 받지 않게끔 객체를 POJO 기반으로 한번씩 더 추상화한 Layer를 갖고 있으며 이를 통해 일관성있는 서비스 추상화를 만들어낸다.

  • POJO(Plain Old Java Object): 오래된 방식의 간단한 자바 오브젝트
    • 특정 기술에 종속되어 동작하는 것이 아닌 순수한 자바 객체
    • 객체지향적인 원리에 충실하면서 환경과 기술에 종속되지 않고 필요에 따라 재활용될 수 있는 방식으로 설계된 오브젝트
    • Java EE 등 중량 프레임워크들에 사용되는 프레임워크에 종속된 무거운 객체에 반발해서 사용하게된 용어
Spring PetClinic 입문 자료: https://projects.spring.io/spring-petclinic/
profile
개인 정리 공간

0개의 댓글