[Spring] 톰캣과 스프링: 웹 요청의 라이프사이클 이해하기
톰캣과 스프링의 웹 요청 처리방법을 이해해 보자
📌 서론
스프링은 복잡한 저수준의 소켓 통신과 스트림 처리를 추상화하여, 개발자가 고수준의 비즈니스 로직에 집중할 수 있도록 설계되었다. 이번 포스트를 통해 스프링 프레임워크와 서블릿 컨테이너(예: Tomcat)가 HTTP 요청을 어떻게 처리하는지, 그리고 이 과정에서 각각의 역할이 무엇인지 상세히 살펴보자
1. 스프링의 http 요청과 관련된 용어 이해하기
서블릿 컨테이너
- 스프링 애플리케이션은 일반적으로 서블릿 컨테이너(예: Tomcat, Jetty) 내에서 실행된다. 이러한 컨테이너는 저수준의 네트워크 통신을 처리하고, HTTP 요청을 서블릿 API로 변환해 애플리케이션에 전달하는 역할을 한다.
DispatcherServlet
- DispatcherServlet은 스프링의 중심 컴포넌트로, 모든 HTTP 요청을 받아 적절한 컨트롤러로 라우팅 하는 역할을 한다. 이 과정은 개발자가 저수준의 소켓 통신이나 스트림을 직접 다루지 않도록 추상화되어 있다.
컨트롤러와 서비스
- 개발자는 스프링의 컨트롤러와 서비스를 구현해서 비즈니스 로직을 작성한다. 컨트롤러와 서비스는 HTTP 요청의 데이터를 처리하고 응답을 생성하는데 집중하게 되고 저수준의 네트워크 세부사항은 서블릿 컨테이너(tomcat)와 스프링 프레임워크가 담당해서 처리한다.
- 컨트롤러는 요청 데이터를 처리하고, 서비스는 비즈니스 로직을 수행한 후 결과를 컨트롤러에 반환한다. 컨트롤러는 이 데이터를 사용하여 HTTP 응답을 생성하고 클라이언트에 반환한다.
데이터 처리와 응답 생성
📌 결론
스프링은 개발자가 HTTP 요청과 응답을 처리하는 데 필요한 고수준의 추상화와 유틸리티에 집중할 수 있도록 설계되어 있으며, 저수준의 네트워크 세부사항은 내부적으로 처리된다. 그래서 개발자가 직접 `BufferedReader`, `BufferedWriter` 또는 소켓을 사용하여 HTTP 통신을 구현할 필요가 없다.
2. 그럼 톰캣에서 http요청을 다 처리하는 걸까?
http요청에 대한 구현은 서블릿 컨테이너(톰캣)의 핵심 기능이다.
- Tomcat 같은 서블릿 컨테이너는 내부적으로 BufferedReader, BufferedWriter와 같은 저수준의 자바 I/O 클래스들을 사용하여 HTTP 요청과 응답을 처리한다.
📌 잠깐! tomcat은 자바로 만들어졌나요?
그렇다. Tomcat은 자바로 작성된 오픈 소스 소프트웨어로, 웹 서버 및 서블릿 컨테이너로서의 더 많은 기능과 복잡한 요구 사항을 처리할 수 있다. 그래서 자바의 BufferedReader, BufferedWriter와 같은 저수준의 I/O 클래스들을 사용하여 HTTP 요청과 응답을 처리할 수 있는 것이다.
서블릿 컨테이너(톰캣)의 역할
- 네트워크 통신
- 서블릿 컨테이너(톰캣)는 네트워크 소켓을 통해 클라이언트로부터 들어오는 HTTP 요청(request)을 수신한다.
- 서블릿 컨테이너(톰캣)는 네트워크 소켓을 통해 클라이언트로부터 들어오는 HTTP 요청(request)을 수신한다.
- 요청 파싱
- 수신된 데이터는 BufferedReader와 같은 스트림을 통해 읽어지며, 이 데이터는 HTTP 요청의 헤더, 바디 등으로 파싱 된다.
- 수신된 데이터는 BufferedReader와 같은 스트림을 통해 읽어지며, 이 데이터는 HTTP 요청의 헤더, 바디 등으로 파싱 된다.
- 서블릿 실행
- 파싱 된 요청 정보는 서블릿 API를 통해 서블릿(또는 스프링의 DispatcherServlet)에 전달된다. 이때 서블릿은 요청에 대한 처리를 수행한다.
- 파싱 된 요청 정보는 서블릿 API를 통해 서블릿(또는 스프링의 DispatcherServlet)에 전달된다. 이때 서블릿은 요청에 대한 처리를 수행한다.
3. 그럼 스프링은 뭘 할까?
스프링 프레임워크의 역할
- 요청 처리
- 스프링의 DispatcherServlet은 서블릿 컨테이너(톰캣)로부터 HTTP 요청을 받아, 적절한 컨트롤러로 전달한다.
- 스프링의 DispatcherServlet은 서블릿 컨테이너(톰캣)로부터 HTTP 요청을 받아, 적절한 컨트롤러로 전달한다.
- 비즈니스 로직
- 컨트롤러는 비즈니스 로직을 처리하고 결과를 생성한다.
- 컨트롤러는 비즈니스 로직을 처리하고 결과를 생성한다.
- 응답 생성:
- 처리된 데이터는 클라이언트에게 응답(response)으로 전달된다.
📌 결론
Tomcat과 같은 서블릿 컨테이너는 HTTP 요청을 저수준에서 처리하는 반면, 스프링 프레임워크는 이러한 요청을 기반으로 고수준의 비즈니스 로직을 처리하고 응답을 생성하는 역할을 한다.
그래서 개발자는 스프링 프레임워크를 사용하면서 애플리케이션의 비즈니스 로직에 집중할 수 있으며, 저수준의 I/O 처리나 HTTP 요청 파싱 같은 복잡한 작업들에 대해서는 신경 쓸 필요가 없다.
4. 톰캣과 스프링의 팀워크
톰캣(Tomcat)의 역할과 HttpServletRequest 생성
- HTTP 요청 수신 및 서블릿 컨테이너로의 전달
- 클라이언트로부터의 HTTP 요청은 톰캣(Tomcat)과 같은 서블릿 컨테이너에 의해 네트워크 소켓을 통해 수신된다. 이 과정은 TCP/IP 프로토콜을 사용하여 데이터를 전송하며, 서블릿 컨테이너(tomcat)는 이 들어오는 데이터 스트림을 받아들여 처리한다.
- 클라이언트로부터의 HTTP 요청은 톰캣(Tomcat)과 같은 서블릿 컨테이너에 의해 네트워크 소켓을 통해 수신된다. 이 과정은 TCP/IP 프로토콜을 사용하여 데이터를 전송하며, 서블릿 컨테이너(tomcat)는 이 들어오는 데이터 스트림을 받아들여 처리한다.
- 요청 파싱
- 톰캣(Tomcat)과 같은 서블릿 컨테이너 내부에서는 BufferedReader와 같은 스트림을 사용하여 네트워크로부터 받은 원시 데이터를 읽는다.
- 이 데이터는 HTTP 프로토콜에 따라 파싱 되어 HTTP 요청의 세부 사항들을 추출한다. 이 과정에서 HTTP 메서드, URL, 헤더, 바디 등과 같은 요청 구조의 다양한 요소들이 정확하게 분리되고 처리된다.
- HttpServletRequest 객체 생성
- 톰캣(Tomcat)은 클라이언트로부터의 HTTP 요청을 파싱 한 후, 이 데이터를 HttpServletRequest 객체로 변환한다. 이 객체는 요청에 대한 모든 정보, 즉 URL, 헤더, 바디, 쿼리 파라미터 등을 캡슐화하여 웹 애플리케이션에서 사용하기 쉽게 만든다.
- 이렇게 생성된 HttpServletRequest는 웹 애플리케이션(예: 스프링 프레임워크)에서 서블릿 API를 통해 접근하고 처리할 수 있게 해 준다.
스프링(Spring)의 DispatcherServlet 처리
- DispatcherServlet의 역할
- 스프링 프레임워크 내부의 DispatcherServlet은 톰캣으로부터 HttpServletRequest 객체를 매개변수로 받는다. 이 객체는 클라이언트의 HTTP 요청 정보를 담고 있다.
- 요청 파싱 및 컨트롤러 매핑
- DispatcherServlet은 HttpServletRequest 객체를 사용하여 요청의 세부 사항(예: URL, 헤더, 바디)을 파악한다. 이 정보를 기반으로 HandlerMapping을 사용해 해당 요청을 처리할 적절한 컨트롤러를 찾는다.
- DispatcherServlet은 HttpServletRequest 객체를 사용하여 요청의 세부 사항(예: URL, 헤더, 바디)을 파악한다. 이 정보를 기반으로 HandlerMapping을 사용해 해당 요청을 처리할 적절한 컨트롤러를 찾는다.
- 컨트롤러로의 요청 전달 및 처리
- 결정된 컨트롤러에 요청이 전달되면, 컨트롤러는 이를 받아 해당 요청에 맞는 메서드를 실행한다. 이 과정에서 컨트롤러는 필요한 비즈니스 로직을 수행하고, 요청에 대한 응답을 준비하며, 최종적으로 클라이언트에게 반환할 응답을 구성한다.
- 결정된 컨트롤러에 요청이 전달되면, 컨트롤러는 이를 받아 해당 요청에 맞는 메서드를 실행한다. 이 과정에서 컨트롤러는 필요한 비즈니스 로직을 수행하고, 요청에 대한 응답을 준비하며, 최종적으로 클라이언트에게 반환할 응답을 구성한다.
응답 생성 및 반환
- 컨트롤러에서의 응답 처리
- 스프링 프레임워크 내의 컨트롤러는 HTTP 요청을 받아 해당 요청에 맞는 비즈니스 로직을 수행한다. 이 과정에서 요청 데이터를 분석하고 필요한 작업을 수행한 후, 처리된 결과를 바탕으로 HTTP 응답을 구성한다.
- 이 응답은 HttpServletResponse 객체에 저장되며, 이 객체를 통해 응답의 상태 코드, 헤더, 바디 등을 설정하고 클라이언트에게 반환될 응답의 내용을 구성한다.
- 톰캣으로의 응답 반환
- 구성된 응답은 HttpServletResponse 객체에 저장된 후, 다시 서블릿 컨테이너인 톰캣으로 전달된다. 톰캣은 이 응답을 처리하여 최종적으로 클라이언트에게 전송한다.
- 이 과정에서 컨트롤러가 설정한 응답의 상태 코드와 헤더는 클라이언트에게 요청 처리 결과를 명확하게 알려주는 역할을 하며, 응답 바디는 클라이언트에게 전달될 실제 데이터(예: JSON, HTML, XML)를 포함한다.
톰캣과 스프링의 팀워크 요약
- 톰캣(Tomcat)의 역할은 주로 HTTP 요청의 수신, 파싱, 그리고 HttpServletRequest 객체로의 변환에 집중된다.
- 스프링(Spring)의 역할은 DispatcherServlet을 통해 요청을 받아들이고, 적절한 컨트롤러에 요청을 전달하여 처리하며, 최종적으로 응답을 구성하고 반환하는 것이다.
📌 마무리
이처럼, 서블릿 컨테이너(tomcat)는 HTTP 요청을 저수준에서 처리하고, 스프링 프레임워크는 이 요청을 기반으로 컨트롤러를 호출하고 비즈니스 로직을 실행하는 고수준의 처리를 담당한다. 이 과정에서 개발자는 HTTP 요청의 저수준 세부사항에 직접적으로 관여하지 않고, 비즈니스 로직 구현과 요청 처리에 집중할 수 있다.
이 내용에서 다루는 Tomcat의 역할(http요청 처리)을 java를 통해 직접 구현해 봤다.👇🏻👇🏻