Web/Spring

스프링 (Spring)

프로그래멍 2020. 5. 23. 21:26

특징

  • POJO 기반의 구성
  • 의존성 주입(DI)을 통한 객체 간의 관계 구성
  • 관점 지향 프로그래밍 AOP(Aspect-Oriented_Programming) 지원 
  • 편리한 MVC 구조
  • WAS의 종속적이지 않은 개발 환경

POJO 기반의 구성

 코드를 개발할 때 개발자가 특정한 라이브러리나 컨테이너의 기술에 종속적이지 않다는 것을 의미함.

 개발자는 가장 일반적인 형태로 코드를 작성하고 실행할 수 있기 때문에 생산성에서도 유리하고, 코드에 대한 테스트 작업 역시 좀 더 유연하게 할 수 있다는 장점이 생긴다.

 

의존성 주입과 스프링

 의존성이란는 것은 하나의 객체가 다른 객체 없이 제대로 된 역할을 할 수 없다는 것을 의미한다.

 하나의 객체가 다른 객체의 상태에 따라 영향을 받는 것을 의미한다.

 

 주입은 말 그대로 외부에서 '밀어 넣는 것'을 의미한다.

 

음식점의 예에서 직접 식재료를 사지 않고, 대행업체에서 배송해 주는 것을 사용하는 경우에 얻는 장점은 '편리함', '장사에만 집중'의 장점이 있다. 이를 코드에 대입하면 '주입을 받는 입장에선 어떤 객체인지 신경 쓸 필요가 없다', '어떤 객체에 의존하든 자신의 역할은 변하지 않는다'와 같은 의미로 볼 수 있다.

 

스프링에서는 'ApplicationContext'라는 존재가 필요한 객체들을 생성하고, 필요한 객체들을 주입하는 역할을 해 주는 구조이다. 따라서 스프링을 이용하면 개발자들은 기존의 프로그래밍과 달리 객체와 객체를 분리해서 생성하고, 이러한 객체들을 엮는(wiring) 작업을 하는 형태의 개발을 하게 된다.

 

ApplicationContext가 관리하는 객체들을 '빈(Bean)'이라는 용어로 부르고, 빈과 빈 사이의 의존관계를 처리하는 방식으로 xml, 어노테이션, java 설정 방식을 이용할 수 있다.

 

스프링 4.3 이후 단일 생성자의 묵시적 자동 주입

 스프링은 생성자 주입, setter 주입을 사용한다. 

 setter 주입은 @Autowired 를 사용.

 생성자 주입은 객체 생성 시 의존성 주입이 필요하므로 좀 더 엄격하게 의존성 주입을 체크하는 장점이 있다.

@Component
@Getter
public class SamleHotel {

	private Chef chef;
	
	public SamleHotel(Chef chef) {
		this.chef = chef;
	}
}

----Lombok을 사용하여 더 간편하게 변경 가능하다.
@Component
@Getter
@RequiredArgsConstructor
public class SamleHotel {

	private final Chef chef;
	
}

@AllArgsConstructor 가능하다, 

@RequiredArgsConstructor는 @NonNull이나 final이 붙은 ㅅ인스턴스 변수에 대한 생성자를 만들어 낸다.

 

AOP의 지원

 스프링 프레임워크는 반족적인 코드를 줄이고, 핵심 비즈니스 로직에만 집중할 수 있는 방법을 제공한다.

 보안, 로그, 트랜잭션과 같이 비즈니스 로직은 아니지만, 반드시 처리가 필요한 부분을 스프링에서는 '횡단 관심사(cross-concern)'라고 한다. 스프링은 이러한 횡단 관심사를 분리해서 제작하는 것이 가능하다.

 Aop는 이런 횡단 관심사를 모듈로 분리하는 프로그래밍의 패러다임이다.

  1. 핵심 비즈니스 로직에만 집중
  2. 각 프로젝트마다 다른 관심사를 적용할 때 코드의 수정을 최소화
  3. 원하는 관심사의 유지보수가 수월함

트랜잭션의 지원

 스프링은 트랜잭션의 관리를 어노테이션이나 xml로 설정할 수 있기 때문에 개발자가 매번 상황에 맞는 코드를 작성할 필요가 없다.

 


root-context.xml

 스프링 프레임워크에서 관리해야 하는 객체(이러한 객체를 스프링에서는 빈이라고 표현)를 설정하는 설정 파일.

 스프링이 로딩되면서 읽어 들이는 문서이므로, 주로 이미 만들어진 클래스들을 이용해서 스프링의 빈으로 등록할 때 사용된다. 일반적인 상황이라면 프로젝트에 직접 작성하는 클래스들은 어노테이션을 이용하는 경우가 많고, 외부 jar 파일 등으로 사용하는 클래스들은 <bean> 태그를 이용해서 작성하는 경우가 대부분이다.

 

커넥션 풀

 일반적으로 여러 명의 사용자를 동시에 처리해야 하는 웹 애플리케이션의 경우 데이터베이스 연결을 이용할 때는 '커넥션 풀'을 이용하므로, 아예 스프링에 커넥션 풀을 등록해서 사용하는 것이 좋다.

 Java에서는 DataSource라는 인터페이스를 통해서 커넥션 풀을 사용한다.

 


MVC

프로젝트의 로딩 구조

 프로젝트 구성 시 관여하는 XML은 web.xml , root-context.xml , servlet-context.xml 파일이다.

 web.xml은 Tomcat 구동과 관련된 설정이고, root, servlet은 스프링 관련 설정이다.

  1.  프로젝트 구동은 web.xml에서 시작한다. web.xml의 상단에는 가장 먼저 구동되는 Context Listener가 등록되어 있다.
  2.  root-context가 처리되면 파일에 있는 bean 설정들이 동작하게 된다. 
  3.  root에 정의된 객체들이 스프링의 영역 안에 생성되고, 객체들 간의 의존성이 처리된다.
  4.  스프링 MVC에서 사용하는 DispatcherServlet이라는 서블릿과 관련된 설정이 동작한다.
  5. XmlWebApplicationContext를 이용해서 servlet-context.xml을 로딩하고 해석한다.
  6. 이 과정에서 등록된 객체(bean)들은 기존에 만들어진 객체(bean)들과 같이 연동된다.

 DispatcherServlet 클래스는 스프링 MVC의 구조에서 가장 핵심적인 역할을 하는 클래스이다.

 

스프링 MVC를 이용하게 되면 개발자들은 직접적으로 HttpServletRequest/HttpServletResponse 등과 같이 Servlet/JSP의 API를 사용할 필요성이 현저하게 줄어든다. 

스프링 MVC의 기본 구조

1. 사용자의 Request는 Front-Controller인 DispatcherServlet을 통해서 처리

2-3. HandlerMapping인 Request의 처리를 담당하는 컨트롤러를 찾기 위해서 존재.

     적절한 컨트롤러가 찾아졌다면 HandlerAdapter를 이용해서 해당 컨트롤러를 동작시킨다.

4. 실제 Request를 처리하는 록직을 작성한 클래스. 이때 view에 전달해야 하는 데이터를 주로 Model이라는 객체에 담아서 전달한다. 

5. ViewResolver는 컨트롤러가 반환한 결과를 어떤 view를 통해서 처리하는 것이 좋을지 해석하는 역할.

 가장 흔한 설정은 InternalResourceViewResolver

<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
	<beans:property name="prefix" value="/WEB-INF/views/" />
	<beans:property name="suffix" value=".jsp" />
</beans:bean>

6-7. View는 실제로 응답 보내야 하는 데이터를 jsp등을 이용해서 생성하는 역할.

    만들어진 응답은 DispatcherServlet을 통해서 전송된다.

 

이런 방식을 Front-Controller 패턴이라고 한다. 

 


Controller

파라미터 수집과 변환

 Controller가 파라미터를 수집하는 방식은 파라미터 타입에 따라 자동으로 변환하는 방식을 이용한다.

 만일 DTO가 기본 자료형이나 문자열 등을 이용한다면 파라미터의 타입만을 맞게 선언해주는 방식을 사용할 수 있다.

@GetMapping("/ex02")
public String ex02(@RequestParam("name") String name, @RequestParam("age") int age) {}

@RequestParam은 파라미터로 사용된 변수의 이름과 전달되는 파라미터의 이름이 다른 경우에 유용하게 사용된다.