Web Server, WAS의 차이점(nginx? apache? tomecat?, CDN?)
Web Server와 WAS의 개념부터 시작해야합니다.
- Web Server : HTTP 기반, 정적 파일 제공 (HTML, CSS, JS, Image, Video)
- ex) NGINX, Apache
- WAS : HTTP 기반, Web Server 기능 포함, 동적 HTML, HTTP JSON API, 코드를 실행해서 애플리케이션 로직 수행
- 서블릿, JSP, 스프링 MVC 같은 것들이 WAS에서 동작한다
- 자바에서는 서블릿 컨테이너 기능을 제공하면 WAS라고 부른다
- ex) tomcat, jetty, undertow
위와 같이 구분할 수 있지만, 명확한 구분이 존재하지는 않습니다. Web Server에서 애플리케이션 로직을 수행할 수 있기도 합니다. WAS에서 애플리케이션의 로직 수행에 더 특화되었다고 생각하면 됩니다.
Web Server와 WAS를 분리해서 이해하고 관리해야하는 이유는 안정성과 자원의 효율성이라고 할 수 있습니다. WAS에서 정적 파일 제공과 동적 서비스의 역할을 모두 담당한다고 가정해보면, WAS에서 장애가 발생하면 오류 화면 노출도 안될 수 있습니다. 이와 같은 문제가 발생하면 안되기 때문에 일반적으로는 Client → Web Server → WAS → DB의 형태로 시스템을 구성합니다. 시스템이 이렇게 구성되어 있으면, 정적 리소스와 애플리케이션 리소스 각각 필요한만큼 증설할 수 있습니다. (Web Server * 4대, WAS * 8대)
여기에서 더 나아가서 정적 리소스의 캐싱이 필요하면 CDN에 대해서 알아 보면 됩니다.
Servlet이란?(Servlet Container, Singleton, MultiThread)
WAS를 직업 구현하려면 많이 복잡합니다.
- 서버 TCP/IP 연결 대기, 소켓 연결
- HTTP Request Message 파싱 및 읽기
- HTTP Method, URL 확인
- Content-Type 확인
- Request Body 내용 파싱
- 비즈니스 로직 생성
- 디비에 저장
- HTTP Response Message 생성
- HTTP 시작 라인 생성 …
- TCP/IP에 응답 전달, 소켓 종료
비즈니스 로직 생성 이외에 다양한 반복적인 작업을 모두 처리해주는 것이 Servlet입니다.
@WebServlet(name ="helloServlet", urlPatterns = "/hello")
public class HelloServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response){
// 애플리케이션 로직
}
}
Servlet Container
WAS를 Servlet Container라고 부르기도 합니다. 톰캣처럼 서블릿을 지원하는 WAS를 서블릿 컨테이너라고 부릅니다. urlPatterns에 매칭되는 요청을 보내면 Servlet Container가 Servlet을 자동으로 생성해줍니다. 서블릿 컨테이너는 서블릿 객체를 생성 ,초기화, 호출, 종료하는 생명주기를 관리합니다. 서블릿 객체를 미리 만들어두고 요청이 들어올 때마다 재사용하기도 합니다.
여기서 주의할 점은, 서블릿 객체는 싱글톤으로 관리된다는 것입니다. 모든 요청은 동일한 서블릿 객체에 접근합니다. 공유 변수 사용 주의해야 합니다. 요청이 들어올 때마다 서블릿 객체는 재활용하고, Request 객체와 Response 객체는 ‘새로’ 만들어서 사용합니다.
멀티 쓰레드
요청이 들어오고 TCP/IP 연결이 되면 Servlet을 호출하는 주체가 쓰레드입니다. 만약에 서블릿을 처리하고 있는 쓰레드를 다른 요청이 들어왔을 때 기다려야하면 병목이 발생합니다. 이를 위해서 Servlet Container는 동시 요청을 위한 멀티 쓰레드 처리를 지원합니다. 요청마다 쓰레드를 추가로 생성해서 처리하면 전체적인 응답 속도가 빨라지고, 하나의 요청이 지연되어도 다른 처리가 정상 동작합니다. 개발자는 마시 싱글 쓰레드 프로그래밍하듯 편하게 개발하면 됩니다.
단점도 있습니다. 쓰레드의 생성 비용이 매우 비싸서 고객의 요청마다 쓰레드를 생성하면 응답 속도가 오히려 늦어집니다. 요청이 많이 들어오고 이에 따라 요청을 처리하는 쓰레드가 많아지면 컨텍스트 스위칭 비용이 발생합니다. 쓰레드 생성에 제한이 없을 때 고객 요청이 너무 많이 오면(배민 치킨 디도스 공격), CPU, 메모리 임계점을 넘어서 서버가 죽을 수 있습니다.
이러한 단점을 극복하기 위해서 쓰레드풀을 적용합니다. 쓰레드 풀에서 남는 쓰레드를 사용해서 사용자의 요청을 처리합니다. 남는 쓰레드가 없을 때 대기하거나 거절되도록 설정할 수 있습니다. 쓰레드풀 사이즈 톰캣 기본값 200개 (검색 키워드 ”springboot tomcat max connection”)로 설정됩니다. WAS의 대부분의 튜닝 포인트는 max thread size로 설정할 때 주의해야합니다. 너무 높으면 CPU, MEM 초과로 서버 다운되고, 너무 낮으면 리소스는 여유롭고 클라이언트가 금방 응답 지연에 걸립니다.
tomcat connection pool에서 병목이 생겼을 때 클라우드면 일단 서버 늘리고 이후에 튜닝하면 됩니다. 당장 서비스가 살아야하니까요. 만약 클라우드가 아니면 평소에 열심히 튜닝해두어야 합니다.
Servlet, JSP, MVC
서블릿은 1997에 나왔습니다.HTTP Request, Response를 공통처리하고 비즈니스 로직에 집중하자는 취지였습니다. 그런데 HTML로 대표되는 View의 영역을 처리하는데 문자열로 처리하다보니 많은 불편함이 있었습니다.
JSP는 1999에 나옵니다. 자바 코드로 HTML을 짜는것보다는 좋지만, JSP 파일을 통해서 좀 더 HTML에 가깝게 코드를 작성할 수 있게 됩니다. 하지만 하나의 JSP 파일에 비즈니스 로직, 디비 연결 로직, 뷰 생성 로직이 모두 들어가게 되면서 서비스가 확장되면서 유지보수가 지옥이 발생합니다. HTML 생성 편리, 비즈니스 로직까지 너무 많은 역할 담당하게 되면서 발생한 문제입니다.
MVC 패턴은 서블릿과 JSP의 조합으로 이루어집니다. 한동안 MVC 프레임워크 춘추 전국 시대가 있었는데 애노테이션 기반의 스프링 MVC 등장하면서 종결이 됐습니다. 여기에 더해 스프링 부트의 등장으로 서버 내장 (과거에는 WAS를 직접 설치하고, 소스는 WAR 파일로 빌드해서 WAS에 배포)되면서 더 간편해졌습니다. 스프링 부트는 빌드 결과 Jar에 WAS 서버 포함해야 했는데, 서버를 내장하게 되면서 빌드 배포 단순화가 이루어 졌습니다.
MVC 기술의 분화
Spring MVC 기술은 크게 두 가지로 나뉩니다.
- Web Servlet - Spring MVC
- Web Reactive - Spring WebFlux (Netty 사용)
- 비동기 넌 블러킹 처리
- 최소 쓰레드로 최대 성능 - 컨텍스트 스위칭 비용 효율화
- 함수형 스타일 개발 - 동시처리 코드 효율화
- 서블릿 기술 사용하지 않음
- 기술적 난이도 높고 RDB 지원 부족
하지만 MVC도 충분히 빠르기 때문에, 실무에서는 아직 레퍼런스가 너무 적기 때문에 MVC에 집중을 해봐도 됩니다.
'DEV > Spring MVC' 카테고리의 다른 글
SpringBoot 3.* Swagger 적용 방법 (0) | 2024.03.23 |
---|