Apache Tomcat은 Java Servlet, JSP(JavaServer Pages), WebSocket 등을 실행할 수 있는 오픈 소스 웹 서버 및 서블릿 컨테이너이다.
주로 Java 기반 웹 애플리케이션을 실행하는 데 사용되며, HTTP 요청을 받아 서블릿 및 JSP를 처리한 후 클라이언트에게 응답을 반환하는 역할을 한다.
서블릿 컨테이너(Apache Tomcat 등)는 클라이언트 요청을 받아서 서블릿을 실행하고 응답을 반환하는 역할을 한다. 주요 처리 과정은 다음과 같다.
클라이언트 요청 수신
서블릿 매핑 및 인스턴스 관리
init() 호출). 요청 처리 (service() 호출)
service(HttpServletRequest req, HttpServletResponse res) 메서드를 호출한다. doGet(), doPost() 등을 실행하여 동적 컨텐츠를 생성한다. 응답 반환
리소스 정리 (destroy() 호출 - 종료 시)
서블릿 자체가 직접 요청을 처리하는 것이 아니라, 서블릿 컨테이너가 요청을 받아 서블릿을 실행하는 방식으로 동적 컨텐츠가 생성된다.
Servlet은 HttpServlet 클래스를 상속하여 구현하는 경우가 많으며, 대표적인 메서드는 다음과 같다.
init(ServletConfig config)
doGet(HttpServletRequest request, HttpServletResponse response)
doPost(HttpServletRequest request, HttpServletResponse response)
doPut(HttpServletRequest request, HttpServletResponse response)
doDelete(HttpServletRequest request, HttpServletResponse response)
destroy()
GET
?key=value) POST
PUT
DispatcherServlet은 Spring MVC의 핵심 프론트 컨트롤러(Front Controller)로, 클라이언트의 모든 요청을 중앙에서 받아 적절한 컨트롤러로 전달하고, 최종적으로 응답을 반환하는 역할을 한다.
클라이언트 요청 수신
DispatcherServlet에 도달한다. Handler Mapping을 통해 적절한 컨트롤러를 찾아 요청을 위임
DispatcherServlet은 HandlerMapping을 사용하여 해당 요청을 처리할 적절한 컨트롤러(@Controller, @RestController 등)를 찾는다. 컨트롤러 실행
컨트롤러의 실행 결과를 DispatcherServlet에 반환
@Controller의 경우, ViewResolver를 사용하여 JSP, Thymeleaf 등의 뷰를 렌더링한다. @RestController의 경우, 데이터를 JSON 또는 XML 형식으로 반환한다. 클라이언트로 응답 전송
(1)📍컨트롤러가 서비스를 호출하지 않는 경우 (단순 요청 처리)
@Controller
@RequestMapping("/home")
public class HomeController {
@GetMapping
public String home() {
return "home"; // View name 반환 (home.jsp, home.html 등)
}
}
✅ 흐름 정리
1. 클라이언트가 GET /home 요청을 보냄.
2. DispatcherServlet이 요청을 HomeController#home()에 전달.
3. 컨트롤러가 직접 "home"이라는 뷰 이름을 반환.
4. DispatcherServlet이 ViewResolver를 통해 "home.jsp" 또는 "home.html"을 렌더링.
5. 클라이언트에 HTML 응답 반환.
👉 이 경우 서비스 호출이 필요 없으며, 컨트롤러가 직접 뷰 이름을 반환한다.
(2)📍컨트롤러가 서비스를 호출하는 일반적인 경우
@RestController
@RequestMapping("/user")
public class UserController {
private final UserService userService;
public UserController(UserService userService) {
this.userService = userService;
}
@GetMapping("/{id}")
public ResponseEntity<User> getUserById(@PathVariable Long id) {
User user = userService.getUserById(id); // ① 서비스 호출
return ResponseEntity.ok(user); // ② 실행 결과 반환
}
}
@Service
public class UserService {
private final UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
public User getUserById(Long id) {
return userRepository.findById(id)
.orElseThrow(() -> new UserNotFoundException("User not found"));
}
}
✅ 흐름 정리
1. 클라이언트가 GET /user/{id} 요청을 보냄.
2. DispatcherServlet이 요청을 UserController#getUserById()에 전달.
3. 컨트롤러가 userService.getUserById(id)를 호출 -> 서비스에서 데이터 조회.
4. 서비스가 결과를 컨트롤러에 반환.
5. 컨트롤러가 ResponseEntity로 감싸서 DispatcherServlet에 반환.
6. DispatcherServlet이 최종적으로 JSON 형식으로 변환하여 클라이언트에 응답.
✔ 일반적으로 컨트롤러는 서비스를 호출하여 비즈니스 로직을 처리한다.
✔ 하지만 단순한 경우에는 서비스 호출 없이 컨트롤러가 직접 데이터를 반환하거나 뷰를 지정할 수도 있다.
✔ 컨트롤러의 본질적인 역할은 "요청을 처리하고 응답을 반환하는 것"이지, 반드시 서비스를 호출하는 것이 아니다.
Spring Boot에서는 기본적으로 DispatcherServlet이 자동으로 설정되지만, XML 기반 설정에서는 다음과 같이 명시적으로 설정할 수도 있다.
<servlet>
<servlet-name>dispatcher</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>dispatcher</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>
Spring Boot 환경에서는 @SpringBootApplication을 사용하면 자동으로 DispatcherServlet이 설정되므로 컨트롤러만 작성하면 된다.
DispatcherServlet은 @RequestMapping, @GetMapping 등이 적용된 컨트롤러 메서드를 찾아서 실행한다. ModelAndView, JSON 데이터 등을 반환할 수 있으며, DispatcherServlet이 이를 처리하여 적절한 응답을 생성한다. @Controller: Spring MVC의 컨트롤러를 정의 @RestController: JSON/XML 응답을 처리하는 컨트롤러 @RequestMapping: 특정 URL 요청을 해당 컨트롤러 메서드와 매핑 @GetMapping, @PostMapping, @PutMapping, @DeleteMapping: HTTP 메서드에 맞는 요청을 처리