📋 Spring MVC - 1. 웹 서버, 웹 애플리케이션 서버
2021-04-27글
웹 서버, 웹 애플리케이션 서버
웹서버
- HTTP 기반으로 동작
- 정적 리소스 제공, 기타 부가기능
- 정적 파일인 HTML, CSS, JS, 이미지, 영상
- ex) NGINX, 아파치
웹 애플리케이션 서버
- HTTP 기반으로 동작
- 웹 서버 기능 포함 + (정적 리소스 제공 가능)
- 프로그램 코드를 실행해서 애플리케이션 로직 수행
- 동적 HTML. REST API
- JSP, 스프링 MVC, 서블릿
- 톰캣 등..
웹 서버 vs 웹 애플리케이션 서버
- 웹 서버는 정적 데이터를 담당하고 애플리케이션 서버는 동적 데이터를 담당한다.
- 사실 둘의 용어의 경계도 모호함
- 웹 서버도 프로그램을 실행하는 기능을 포함하기도 함
- 웹 애플리케이션 서버도 웹 서버의 기능을 제공함
- 자바에서는 서블릿 컨테이너 기능을 제공하면 웹 애플리케이션 서버다.
웹 시스템 구성
WAS + DB
WAS는 정적 리소스, 애플리케이션 로직 모두 제공 가능하기 때문에 WAS, DB만으로 웹 시스템 구성이 가능하지만, 이럴 경우 WAS가 너무 많은 역할을 담당하여 서버 과부하가 올 수 있다.
WEB + WAS + DB
정적 리소스만 제공하는 웹서버는 잘 죽지 않는다. WAS는 비즈니스 로직을 처리하다가 에러가 날 수 있는데 이를 웹 서버가 오류 화면을 보여준다. 웹 서버와 애플리케이션 서버가 분리되어서 가능했던 일!
서블릿
만약 웹 애플리케이션 서버를 싹 다 구현해야 한다면...
나는 비즈니스 로직을 실행하고 싶은데, HTTP 메시지를 싹 다 읽어야한다.
여기서 서블릿을 지원하는 WAS를 사용하면 비즈니스 로직에만 집중할 수 있다.
@WebServlet(name = "helloServlet", urlPattern = "/hello")
public class HelloServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
// 애플리케이션 로직
}
- 해당 URL이 호출되면 서블릿 코드가 실행된다.
- HTTP 요청과 응답 정보를 편리하게 사용할 수 있는 서블릿을 제공한다.
- 개발자는 HTTP 스펙을 매우 편리하게 제공
HTTP 요청 시 서블릿의 흐름
- WAS는 요청, 응답 객체를 새로 만들어서 서블릿 객체를 호출한다.
- 개발자는 요청 객체에서 HTTP 요청 정보를 편리하게 꺼내서 사용한다.
- 개발자는 응답 객체에 HTTP 응답 정보를 편리하게 입력한다.
- WAS는 응답 객체에 담겨있는 내용으로 HTTP 응답 정보를 생성한다.
서블릿 컨테이너
- WAS 안에 존재한다.
- 서블릿 컨테이너는 서블릿 생명 주기를 관리한다.
- 서블릿 객체는 싱글톤으로 관리한다. (때문에 공유 변수 사용 주의)
- JSP도 서블릿으로 변환되어 사용
- 최초 로딩 시점에 서블릿 객체를 미리 만들어두고 재활용
- 동시 요청을 위한 멀티 스레드 처리를 지원한다.
동시 요청 - 멀티 스레드
그런데 서블릿을 누가호출하나?
스레드
- 애플리케이션 코드를 실행하는 것
- 자바 메인 메인 메서드를 실행하면 main이라는 이름의 스레드가 실행된다.
- 스레드가 없으면 자바 애플리케이션 실행이 불가능하다.
- 한번에 하나의 코드 라인만 수행한다.
- 만약 동시처리가 필요하면 스레드를 추가로 생성한다.
단일 요청에는 단일 스레드를 실행시킨다.
하지만, 다중 요청에서 스레드가 요청을 처리하다가 서블릿에서 처리가 지연되고 있을 때,
이때 추가 요청이 들어올 경우 오류가 발생한다.
이를 해결하려면?
요청마다 스레드를 생성한다.
장점
- 동시 요청을 처리할 수 있다.
- 리소스가 허용할 때까지 처리 가능
- 하나의 스레드가 지연되어도 나머지 스레드는 정상 동작
단점
- 스레드 생성 비용은 비싸다.
- 요청이 올 때마다 스레드를 생성하면 응답이 늦어진다.
- 컨텍스트 스위칭 비용이 발생한다.
- 스레드 생성에 제한이 없다.
- 요청이 너무 많으면 리소스 임계점을 넘어 서버가 죽을 수 있다.
스레드 풀
요청이 오면 스레드 풀에서 놀고 있는 스레드풀을 가져다가 쓴다. (톰캣은 최대 200개 기본 설정).
스레드를 다 쓰면 스레드 풀에 반납한다.
스레드 풀에 있는 스레드 개수보다 요청이 많이들어오면 스레드 대기 또는 거절을 한다.
장점
- 미리 생성되어 있으므로, 스레드를 생성하고 종료하는 비용이 절약된다.
- 응답 시간이 빠르다.
- 생성 스레드 최대치가 있으니, 요청이 많이 들어와도 기존 요청은 안전하게 처리한다.
실무 팁
- WAS의 주요 튜닝 포인트는 최대 스레드 수이다.
- 너무 낮게 설정하면?
- 리소스는 여유, 클라이언트는 금방 응답 지연
- 너무 높게 설정하면?
- 동시 요청이 많으면 이소스 임계점 초과로 서버 다운
- 장애 발생 시
- 클라우드면 서버를 늘리고 튜닝한다.
적정 숫자?
애플리케이션 로직 복잡도, CPU, 메모리, IO 리소스 상황에 따라 모두 다르다.
때문에 실제 서비스와 유사한 성능 테스트를 해보아야 한다.
WAS는 멀티 스레드를 지원한다.
멀티 스레드에 대한 부분은 WAS가 처리한다.
때문에 개발자는 멀티 스레드 관련 코드를 신경쓰지 않아도 된다.
단, 멀티 스레드 환경이므로 싱글톤 객체(서블릿, 스프링 빈)는 주의해서 사용해야한다.
HTML, HTTP API, CSR, SSR
백엔드 개발자가 고민해야할 것....
정적 리소스
고정된 HTML, CSS, js 등을 제공한다.
HTML 페이지
브라우저의 요청이 들어오면 WAS가 템플릿 엔진으로 동적으로 HTML을 생성한다.
웹 브라우저는 HTML을 해석한다.
HTTP API
HTML이 아닌 데이터를 전달한다.
주로 JSON 형식을 사용하고, 다양한 시스템에서 호출한다.
데이터만 주고 받고, UI 화면이 필요하면 클라이언트가 별도로 처리한다.
CSR, SSR
SSR - 서버 사이드 렌더링
- 서버에서 최종 HTML을 생성해서 클라이언트에게 전달한다.
- 주로 정적인 화면에서 사용
- 관련 기술 : JSP, 타임리프 등
- 자바스크립트를 사용해서 화면 일부를 동적으로 변경할 수 있다.
CRS - 클라이언트 사이드 렌더링
- HTML 결과를 자바스크립트를 사용해 웹 브라우저에서 HTML을 동적으로 생성한다.
- 동적인 화면에서 사용하여 필요한 부분만 변경할 수 있다.
- ex) 구글 지도..
- 관련 기술 : React, Vue.js 등
- HTML 요청 -> 자바스크립트 요청(클라이언트 로직, HTML 렌더링 코드) -> HTTP API 데이터 요청 -> 웹 브라우저에서 JS로 HTML 결과 렌더링
자바 백엔드 기술 역사
서블릿 - 1997
HTML 생성이 어려움
JSP - 1999
HTML 생성은 편하지만 비즈니스 로직까지 너무 많은 역할을 한다.
서블릿, JSP 조합 = MVC 패턴 사용
Model, View, Controller로 역할을 나누어 개발
수많은 MVC 프레임 워크
MVC 패턴 자동화, 복잡한 웹 기술을 더 편리하게 사용할 수 있는 다양한 기능
ex) 스트럿츠, 스프링 MVC(과거 버젼)
어노테이션 기반의 스프링 MVC
@Controller
등의 어노테이션 등장.
스프링 부트의 등장
스프링 부트는 서버를 내장한다.
과거는 서버에 WAS를 직접 설치하고, 소스는 War 파일을 만들어 설치한 WAS에 배포해야했다.
스프링 부트는 빌드 결과(Jar)에 WAS 서버를 포함한다. -> 빌드 배포 단순화
최신 기술 - 스프링 웹 기술의 분화
- Web Servlet - Spring MVC
- Web Reactive - Spring WebFlux
Spring WebFlux?
- 완전한 비동기 논블로킹 처리
- 최소 스레드로 최대 성능 - 스레드 컨텍스트 스위칭 비용 효율화
- 함수형 스타일 개발 - 동시처리 코드 효율화
- 서블릿 기술 사용하지 않음
- 하지만, RDB 지원이 부족하다.
- 하지만, 일반 MVC의 스레드 모델도 충분히 빠르다.
자바 뷰 템플릿 역사
JSP
속도가 느리고 기능이 부족하다.
프리마커, Velocity
속도 문제 해결, 다양한 기능
타임 리프
HTML 모양을 유지하면서 뷰 템플릿 적용 가능 (HTML 태그에 적용하기 때문에)
스프링 MVC와 강력한 기능 통합
✍️ 김영님의 스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 강의 노트 ✍️