출처 : https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-1/dashboard
- 웹 서버(Web Server)
HTTP 기반 동작
정적 리소스 제공
정적 HTML, CSS, JS, 이미지 등등 제공
ex. NGINX, APACHE - 웹 애플리케이션 서버(WAS - Web Application Server)
HTTP 기반 동작
웹 서버 기능+ (정적 리소스 제공)
프로그램 코드를 실행해서 애플리케이션 로직 수행
(동적 HTML, HTTP API(JSON))
ex. 서블릿, JSP, 스프링 MVC
- 웹 서버, 웹 애플리케이션 서버의 차이점
현재 경계가 모호하지만, 크게 웹 서버는 정적 리소스, WAS는 애플리케이션 로직을 실행한다 생각하면 좋다.
웹 서비스를 구성할 때 웹 서버 말고, WAS & DB만으로 시스템을 구성할 수 있다.
이렇게 되면 WAS는 정적 리소스, 애플리케이션 로직 모두 제공 가능하다.
근데 이렇게 되면 WAS가 너무 많은 역할을 담당하게 된다.
단순히 간단한 정적 파일부터 비싼 애플리케이션 로직까지도 수행하기 때문에 서버 과부하의 문제가 생길 수도 있고
만약 WAS가 장애가 나면 오류 화면도 노출이 불가하다. 모든 것을 WAS가 다 수행하고 있으니까.
이를 해결하는 방법은, 정적 리소스는 웹 서버가 처리하게 하는 것이다.
웹 서버는 애플리케이션 로직 같이 동적인 처리가 필요하면 WAS가 실행하게 하면 된다.
WAS는 중요한 애플리케이션 로직 처리를 담당하면 된다.
만약 정적 리소스가 많이 사용되면 web 서버를 증설하면 되고
애플리케이션 리소스가 많이 사용되면 WAS를 증설하면 되지.
정적 리소스만 사용하는 웹 서버는 잘 죽지 않는다.
정적 리소스 작업 자체가 상대적으로 간단하니까.
애플리케이션 로직이 동작하는 WAS 서버는 상대적으로 잘 죽겠지.
WAS나 DB 장애가 나면 웹 서버가 오류 화면 html을 띄워주면 되겠지.
서블릿)
우리가 POST로 html 메세지를 보내면 서버는 저 메세지를 통해 정보들을 얻어야한다.
이 때 서버가 해야할 업무들이 왼쪽 사진 항목들처럼 너무나 많다.
하지만 정말 실질적으로 비즈니스 로직으로 의미있는 건 해당 코드에 경우 데이터베이스에 저장만 요청하는 것이다.
나머지 것들은 앞으로 올 요청들마다 다 중복될 것들이다. 이를 Servlet이 자동으로 해주고 있다.
http 요청 메세지를 기반으로 request, response 객체를 만든 후 우리가 구현한 애플리케이션 로직의 인자로 전달해
서비스를 실행하고 해당 응답값을 리턴해주면 된다.
톰캣처럼 서블릿을 지원하는 WAS를 서블릿 컨테이너라고 한다.
서블릿 컨테이너는 서블릿 객체를 생성,초기화,호출 종료하는 생명주기를 관리한다.
서블릿 객체는 싱글톤으로 관리한다.
그 이유는 고객의 요청이 올 때마다 계속 객체를 생성하는 것은 매우 비효율적이기 때문이다.
어차피 고객의 요청들은 다 다르기 때문에, 최초 로딩 시점에 서블릿 객체를 미리 만들어놓고 재활용하는 것이다.
다만 주의해야할 점은, 공유 변수 사용에 주의해야한다. 싱글톤이니까.
동시요청 - 멀티쓰레드)
서블릿 객체를 호출하는 것은 쓰레드이다.
쓰레드는 애플리케이션 코드를 하나하나 순차적으로 실행하는 것이다.
쓰레드는 한 번에 하나의 코드 라인만 수행한다.
만약 동시 처리가 필요하면 쓰레드를 추가로 생성해야 한다.
만약 쓰레드를 단 하나만 사용한다 가정해보자.
쓰레드가 요청1을 처리하고 있는데 너무 오래걸려 지연되고 있다.
이 상황에서 요청2가 오면? 요청2는 해당 쓰레드에 자기 순서가 오기까지 대기해야한다.
이를 해결하기 위해, 요청이 올때마다 쓰레드를 새로 생성하는 것이다.
이렇게 되면, 동시 요청을 처리할 수 있고, 리소스(메모리,CPU)가 허용할 때까지 처리가 가능하다.
하나의 쓰레드가 지연되어도, 나머지 쓰레드는 정상 동작을 하겠지.
하지만 단점은 명확하다.
요청이 올 때마다 쓰레드를 생성하게 되면, 우선 생성하는 데 시간이 걸리므로 응답 속도가 늦어진다.
또한 컨텍스트 스위칭 비용(Context Switching cost)가 발생한다.
해당 개념에 대해 간단히 설명하자면, 프로세스가 동작할 때 쓰레드들은 매우 빠른 간격으로 교체를 반복한다.
그러면 사람 입장에선 동시 동작을 하는 것처럼 보이지만, 실제로는 매우 빠르게 교체를 반복하는 것이다.
근데 쓰레드가 많으면? 쓰레드가 예를 들어 두 개면 12121212하면 되겠지만
쓰레드가 5개라면 123451234512345 이런 식으로 한다 가정하면 쓰레드1은 2345가 동작할 때까지 대기해야한다.
이를 컨텍스트 스위칭이라한다. (OS 때 배움)
또 쓰레드 생성에 제한이 없다보니, 요청이 너무 많으면 쓰레드를 계속 생성하게 되고
이는 메모리 임계점을 넘어서 서버가 죽을 수 있다.
이를 해결하는 법은? 쓰레드 수를 어느정도 제한하는 것이다. 이 개념을 쓰레드 풀이라 한다.
쓰레드 풀에 있는 쓰레드를 가져다 쓰고 다 쓰면 쓰레드 풀에 반납을 하는 것이다.
톰캣에 경우 생성가능한 쓰레드의 수를 최대 200개를 기본 설정으로 하고 있다.
최대 쓰레드가 모두 사용 중이어서 쓰레드 풀에 쓰레드가 없다면?
기다리는 요청은 거절하거나 특정 숫자만큼만 대기하도록 할 수 있다.
쓰레드가 미리 생성되어 있으니까 쓰레드를 생성하고 종료하는 비용이 절약되고 응답 시간이 빠르겠지.
또 마찬가지로 생성가능한 쓰레드의 최대치가 한정되어 있으므로 너무 많은 요청이 오더라도 서버가 터지지 않고
기존 요청을 안전하게 처리할 수 있다.
실제 실무에서 WAS의 주요 튜닝 포인트는 최대 쓰레드(max thread)수이다.
이 값을 너무 낮게 설정한다면
동시 요청이 많아질 경우, 쓰레드 수는 적으니까 서버의 cpu는 매우 적게 점유가 되겠지만
클라이언트에선 응답이 매우 지연되겠지.
반대로 이 값을 너무 높게 설정한다면
동시 요청이 많아질 경우, CPU랑 메모리의 점유율이 너무 높아져 서버가 다운되겠지.
이러한 쓰레드의 적당한 수를 찾기 위해선 성능 테스트를 통해 찾는 것이 옳다.
아파치 ab, 제이미터, nGrinder 등의 성능 툴을 활용한다.
멀티쓰레드에 대한 부분은 개발자가 하는 것이 아닌 WAS가 자동적으로 처리해준다.
개발자는 그냥 싱글 쓰레드 프로그래밍을 하듯이 편하게 소스 코드를 개발하면 된다.
멀티 쓰레드 환경이므로 싱글톤 객체인 서블릿이나 스프링 빈의 사용에 대해선 주의를 기해야 한다.
웹 서버가 보내는 데이터의 유형은 크게 세 가지이다.
정적 리소스, HTML 페이지(동적), HTTP API.
여기서 추가적으로 알아야할 개념으로 SSR(서버 사이드 렌더링), CSR(클라이언트 사이드 렌더링)이 있다.
- SSR - 서버 사이드 렌더링 (백엔드)
HTML 최종 결과를 서버에서 만들어서 웹 브라우저에 전달
정적인 화면에 주로 사용. - CSR - 클라이언트 사이드 렌더링 (프론트엔드)
HTML 결과를 자바스크립트를 활용해 웹 브라우저에서 동적으로 생성해서 사용
동적인 화면에 주로 사용, 웹 환경을 마치 앱처럼 필요한 부분부분 변경 가능.
자바 웹 기술 역사)
'스프링 강의 필기 > 스프링 MVC 1편' 카테고리의 다른 글
7) 스프링 MVC - 웹 페이지 만들기 (0) | 2023.01.27 |
---|---|
6) 스프링 mvc 기본 기능 (0) | 2022.08.03 |
5) 스프링 MVC - 구조 이해 (0) | 2022.07.30 |
4) MVC 프레임워크 만들기 (0) | 2022.07.30 |
3) 서블릿, JSP, MVC 패턴 (0) | 2022.07.27 |