본문 바로가기
IT Study/Spring

Spring - 2 Layered 아키텍처

by hhyyyjun 2023. 1. 3.

사용자의 요청 과정

1. xxx.do 요청

2. 서블릿컨테이너 구동

dispatcherServlet을 생성

dispatcherServlet-servlet.xml을 로드해서 생성

현재의 계층(layer)을 "프레젠테이션 레이어"라고 한다.

3. 스프링 컨테이너가 구동

Controller 객체들 생성

Controller 객체들이 Command 객체로 DAO 객체를 사용함

>>DAO2를 사용하고 싶었으나 잘 안됨. @Autowired DI(의존성 주입)를 해주어야 한다.

기존 Controller의 모든 메서드는 사진과 같이 DAO 객체를 직접 이용하고 있다.

Spring에서는 DAO 객체를 직접 이용하지 않고, 반드시 "비즈니스 컴포넌트(ServiceImpl)"를 이용해서 DAO 객체를 다룰 수 있게끔 구성한다.

반드시 "비즈니스 컴포넌트"를 사용해야 하는 이유?

1) DAO 클래스 교체 등의 유지보수에 용이하다.

비즈니스 컴포넌트의 입장에서는 자신을 이용하는 클라이언트가 Controller 이다.

클라이언트인 Controller 입장에서는 ServiceImpl를 멤버변수로 사용하면 ServiceImpl가 변경되어도 Controller 자체는 변화가 없다.

=> 결합도가 낮아진다.

2) AOP 적용에 용이하다.

횡단관심(어드바이스)이 동작하려면 Service 클래스의 비즈니스 메서드가 실행되어야 한다.

결론 Controller 클래스는 비즈니스 컴포넌트를 멤버변수로 사용해야 하며, 그 객체에게 의존성 주입해야 한다.

비즈니스 컴포넌트를 이용하려면?

Controller 가 serviceImpl 를 멤버변수로 가지고 있고, serviceImpl는 DAO를 멤버변수로 가지고 있어야 한다.

@Controller
public class MemberController {
	
	@Autowired
	private MemberService memberService;
//serviceImpl 클래스
@Service("memberService")
public class MemberServiceImpl implements MemberService {

	@Autowired // MemberDAO 타입의 객체가 메모리에 있어야지만 DI(의존성 주입) 가능함!
	private MemberDAO2 memberDAO; // 핵심로직을 수행할 객체

=> Controller보다 ServiceImpl가 먼저 생성되어야 한다.

=> Controller에 ServiceImpl가 의존성주입될 예정이기 때문

ServiceImpl(비즈니스 컴포넌트)는 스프링 컨테이너가 생성해줘야 하는 객체이고,

ServiceImpl를 생성하는 스프링 컨테이너를 Controller를 생성하는 스프링 컨테이너보다 먼저 구동시켜야 한다.

때문에 기존의 구조에서 스프링 컨테이너가 1개 더 필요하고, 이 스프링 컨테이너는 기존의 스프링 컨테이너보다 먼저 구동되어야 한다.

기존의 구조 + 스프링컨테이너를 추가한 구조를 2Layered 아키텍처라고 한다.

서블릿컨테이너가 스프링 컨테이너를 부르고 있는데 Controller를 쓰려면 이전에 스프링 컨테이너를 하나 더 써야한다.

스프링 컨테이너 -> 서블릿 컨테이너 -> 스프링컨테이너

먼저 실행되는 스프링 컨테이너를 Root 컨테이너 라고 한다.

web.xml

<!-- applicationContext는 java관련 파일이라서 src/main/resources에 있어야 한다 -->
  <!-- 초기화 매개변수 설정 -->
  <context-param>
  	<param-name>contextConfigLocation</param-name>
  	<param-value>classpath:applicationContext.xml</param-value>
  </context-param>
  
    <listener>
     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>

기존의 Presentation Layer(MVC Layer라고도 한다) 보다 "먼저 구동"되는 Business Layer

--> ContextLoarderListener 등록(web.xml)

--> WEB-INF/applicationContext.xml 설정파일이 필요하다.(없으면 에러 발생)

--> applicationContext.xml은 java관련 파일이기 때문에 src/main/resources 경로에 존재해야 한다.

--> <context-param>설정을 추가하여 사용한다.

총 동작 순서

1) Web.xml 파일을 로딩하여 서블릿 컨테이너가 구동된다.

2) 서블릿컨테이너는 web.xml 파일에 등록된 ContextLoaderListener객체를 생성 한다.

3) 이때 ContextLoaderListener는 applicationContext.xml 파일을 로딩하여 스프링을 구동하는데 이를 'Root 컨테이너'라고 한다.

4) 동시에 Service 구현 클래스나 DAO 객체들이 메모리에 생성된다.

5) Clinet가 서버에 요청을 하게 되면, 서블릿 컨테이너는 DispathcerServlet 객체를 생성하고,

6) Presentation-layer.xml 파일을 로딩하여 두 번째 스프링 컨테이너를 구동한다. 이때 Controller 객체들이 메모리에 올라가게 된다.

참고 코드

https://github.com/hhyyyjun/2022.09.27

변경건

BoardServiceImpl/MemberServiceImpl 클래스에서 DAO2 지정

BoardDAO2 클래스에서 검색기능 업데이트

BoardController/MemberController에서 BoardService/MemberService 멤버변수 지정

web.xml 파일에서 ContextLoaderListener 설정

댓글