Controller에 Service DI가 생기면 왜 “2-Layer”인가?
@Autowired
private MemberService memberService;
이 코드가 Controller에 추가되는 순간,
이 프로젝트의 구조는 2-Layerd 아키텍처가 된다
Controller는 더 이상 혼자 존재하지 않는다
Service 계층을 호출하는 구조가 된다
기존 MVC 레이어 == Presentation Layer (MVC Layer)
새로 생긴 Controller를 레이더 == Business Layer ( 비즈니스 == 핵심의 == 서비스 == 기능 == CRUD )
스프링 부트에서 내부적으로 여러 가지의 컨테이너를 갖고 있다
DS는 유일한 서블릿이고, DI할 대상으로 HM, VR를 갖고 있는데
HM가 Controller를 반환한다 여기까지가 Presentation Layer
그런데 여기에 멤버변수로 Service를 끼우는 순간
Service는 DAO를 미리 새팅해야 하는데
DAO는 DB 연결 관련 로직 및 객체이다
그래서 Presentation Layer가 준비가 되려면 DAO, DB연결 관련 로직 및 객체가 먼저 준비가 되야 하는 상황이 생긴것이다
기존의 컨테이너보다 먼저 준비가 되어 있어야 해서 "루트 컨테이너 == 스프링 루트 컨테이너"라고 부른다
기존 MVC 구조
▪ Presentation Layer (MVC Layer)
▪ 여기까지만 있으면 Service 계층이 없는 구조
| 구성 | 요소역할 |
| Controller | 요청 수신 |
| Model | 데이터 |
| View | 화면 |
Service 계층의 의미 (Business Layer)
Service는 단순한 클래스가 아니다
✅ Service = Business Layer
▪ 비즈니스 로직 담당
▪ 핵심 기능
▪ CRUD 처리
▪ 여러 DAO 처리
▪ 트랜잭션 처리
▪ AOP 적용 지점
Spring 내부 컨테이너 구조 이해
Spring은 내부적으로 역할이 다른 컨테이너를 나눠서 관리한다
🔹 DispatcherServlet (FrontController)
▪ 유일한 서블릿
▪ 내부적으로 HandlerMapping(HM), ViewResolver(VR)을 DI 대상으로 가짐
DispatcherServlet
├─ HandlerMapping
└─ ViewResolver
여기까지가 Presentation Layer
Service를 Controller에 DI하면 무슨 일이 생길까?
@Controller
public class TestController {
@Autowired
private MemberService memberService;
}
이 순간 발생하는 구조 변화
▪ Controller 생성 시 Service가 먼저 준비되어 있어야 함
▪ Service 는 DAO를 필요로 함
▪ DAO는 DB 연결 객체를 필요로 함
Controller
↓
Service
↓
DAO
↓
DB Connection
즉, Presentation Layer보다 먼저 준비되어야 하는 계층이 생김
그래서 등장하는 개념: 루트 컨테이너 (Root Container)
📢 루트 컨테이너란?
웹 요청과 상관없이
애플리케이션 시작 시 먼저 로딩되는 컨테이너
Service, DAO, DB 관련 Bean 관리
이름 : Spring Root Application Context, Root Container
web.xml에서 루트 컨테이너를 만드는 방법
web.xml 전체 코드
<?xml version="1.0" encoding="UTF-8"?>
<web-app
xmlns="https://jakarta.ee/xml/ns/jakartaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="
https://jakarta.ee/xml/ns/jakartaee
https://jakarta.ee/xml/ns/jakartaee/web-app_6_0.xsd"
version="6.0">
<servlet>
<servlet-name>ds</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ds</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<filter>
<filter-name>enc</filter-name>
<filter-class>org.springframework.web.filter.CharaterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>enc</filter-name>
<url-pattern>*.do</url-pattern>
</filter-mapping>
<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>
</web-app>
🔹 ContextLoaderListener 등록
/*
필터 등록할 때 처럼 태그를 활용하여 리스너를 등록했다
리스너는 로딩을 할 때는 어떤 파일을 참고하도록 할 수 있다
그래서 Context param으로 resource에 있는 서비스 자원이 들어있는 xml을 주었다
*/
<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>
역할
▪ 서버 시작 시
▪ applicationContext.xml을 먼저 읽음
▪ Service / DAO Bean 생성
▪ DB 연결 객체 준비
| 구분 | 담당 |
| Root Container | Service, DAO |
| Servlet Container | Controller, HM, VR |
Controller는 Root Container의 Bean(Service)을 주입받아 사용
왜 필터처럼 리스너를 등록하는가?
필터 : 요청 전/후 처리
리스너 : 서버 시작/종료 시점 처리
ContextLoaderListener는 "서버가 켜질 때, 이 설정 파일부터 읽어라" 라는 역할을 한다
결론 2- Layer 아키텍쳐가 됐을 때 .xml에 위의 코드가 꼭 있어야 한다
[ 1. ] Controller에 Service DI가 생기면 2-Layer 아키텍처
[ 2. ] Service는 Business Layer이며 핵심 로직 담당
[ 3. ] Service/DAO는 DispatcherServlet보다 먼저 준비되어야 하므로
ContextLoaderListener + applicationContext.xml로
루트 컨테이너를 구성해야 한다
Controller에 Service가 생기는 순간, Spring은 “웹 요청용 컨테이너”와 “비즈니스 로직용 컨테이너”를 분리해서 관리한다.
'🍃 Spring' 카테고리의 다른 글
| 스프링 AOP와 🐌 용어 정리 🐌 그리고 공통 관심사 호출해보기 (0) | 2026.01.23 |
|---|---|
| 로그인부터 Board 목록까지의 흐름과 관련된 질문과 답변 (0) | 2026.01.22 |
| Command 객체 생성 방식으로 DAO를 new하면 안 좋은 이유 (0) | 2026.01.19 |
| 왜 Spring Boot는 가벼운가? MVC 구조 변화로 이해하기 (JSP/서블릿 MVC → Spring MVC → Spring Boot) (0) | 2026.01.19 |
| Spring MVC 핵심 정리: HandlerMapping · ModelAndView · ViewResolver (0) | 2026.01.16 |