출처 : https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-1/dashboard
1) 웹 서버, 웹 애플리케이션 서버
- 웹 세상에서는 모든 것을 http를 기반으로 데이터를 주고 받는다. 심지어 서버-서버 간 통신도 그렇다.
- 웹 서버는 http를 기반으로 동작한다.
- 정적 리소스(http 통해 주고 받는 데이터)를 주고 받는다.
- 웹 애플리케이션 서버(WAS)도 http 기반으로 동적하며, 웹 서버의 기능을 포함한다.
- 그러나 프로그램 코드를 실행해 애플리케이션 로직을 수행한다는 것이 웹 서버와의 차이다.
- 웹 서버는 정적 리소스를 제공, WAS는 애플리케이션 로직까지도 수행한다는 것이 차이다.
- 하지만 둘의 경계는 모호하다
- WAS가 애플리케이션 코드 실행에 특화적이라고 이해하자
- WAS, DB 만으로 시스템을 구성 가능하다.
- WAS는 정적 리소스와 애플리케이션 로직을 모두 제공 가능하기 때문이다(html/css,image...).
- 그러나 was가 모든 것을 담당하면 서버 과부하가 생기며, 애플리케이션 로직은 중요한 일을 처리하는 일인데 이것이 정적 리소스때문에 수행이 어려울 수가 있다. 따라서 비효율의 가능성이 있다.
- was가 죽을 때 웹 브라우저에서 was에 접근조차 안되므로 오류 화면도 뜨지 않아 문제 진단이 되지 않는다.
- 따라서 웹 서버를 앞에 두어 정적 리소스를 처리시키고, 동적 로직이 필요한 것은 was에 요청을 넘긴다.
- 이렇게 was가 중요한 애플리케이션 로직을 전담할 수 있다.
- 이렇게 할 경우 시스템 리소스를 효율적으로 쓸 수 있다. 정적 리소스가 많으면 웹 서버를, 애플리케이션 리소스가 많으면 was를 늘리면 된다.
- 정적 리소스만 제공하는 웹 서버는 잘 죽지 않고, 애플리케이션 로직을 처리하는 was는 잘 죽는다.
- was,db 장애가 일어나면 웹 서버가 오류 화면을 제공할 수 있다. 웹서버가 was에 동적 로직을 넘겼는데 응답이 없으면 오류 화면을 띄우면 되기 때문이다.
**
2) 서블릿**
- post 방식으로 html form 데이터 전송을 누르면, 웹 브라우저가 오른쪽과 같은 http 메시지를 생성한다.
- 우리가 웹 애플리케이션 서버를 구현하려면 위 메시지를 파싱해 읽고 컨텐트타입 확인 후 바디 내용을 파싱한다.
- 저장 프로세스를 실행하고, 저장에 대한 비즈니스 로직을 실행하고 데이터베이스에 저장을 요청한다. 이 부분이 가장 의미있는 비즈니스 로직이다.
- 이후 서버에서 http 응답 메시지를 생성해 응답을 전달한다.
- 위 과정은 보기에도 상당히 복잡해 보인다.
- 따라서 서블릿이 등장했다. 위 초록색 블록을 제외한 모든 것을 서블릿이 자동화해 처리해준다.
- 서블릿은 urlPatterns의 url이 호출되면 서블릿 코드가 실행된다.
- 메세지를 직접 파싱하면 힘드므로, 아래에 있는
- HttpServletRequest를 사용해 요청 정보를 사용하도록
- HttpServletResponse를 사용해 응답 정보를 제공하도록
- 서블릿이 모두 만들어 준다.
- 웹 브라우저에서 요청을 보내면 was 서버에서 http 요청 메세지를 기반으로 request,response 객체를 만들고, 이를 파라미터로 넘기며 서블릿 컨테이너 안의 helloServlet을 실행한다.
- helloServlet이 return되면 response 객체 정보로 http 응답을 생성한다.
- 정리하면 was는 http 요청시 request, response 객체를 새로 만든다.
- 개발자는 request 객체에서 http 요청 정보를 편리하게 꺼내서 사용한다.
- 개발자는 response 객체에 http 응답 정보를 편리하게 입력한다.
- was는 response 객체에 담겨있는 내용으로 http 응답 정보를 생성한다.
- 서블릿은 was의 생명 주기를 모두 관리해준다.
- 서블릿을 지원하는 was를 서블릿 컨테이너라고 하며, 서블릿 객체의 생명주기를 관리한다.
- 서블릿은 객체를 하나만 생성하고 공유해 쓰는 싱글톤으로 관리한다.
- 고객 요청이 올 때마다 계속 서블릿 객체를 생성하면 비효율적이므로(단 request,response는 요청마다 계속 생성하는게 맞다.), 최초 로딩 시점에 서블릿 객체를 싱글톤으로 미리 만들고 재활용한다.
- 모든 고객 요청은 동일한 서블릿 객체 인스턴스에 접근한다.
- 따라서 공유 변수를 사용하는 것을 주의해야 한다.
- 서블릿 컨테이너 종료시 싱글톤 서블릿 객체가 함께 종료된다.
- JSP도 서블릿으로 변환되어 사용된다.
- 가장 중요한 것은, 동시 요청을 위한 멀티 쓰레드 처리를 지원한다는 것이다.
3) 동시 요청- 멀티 쓰레드
- tcp/ip 커넥션 연결이 된다. 그리고 서블릿이 호출 된다.
- 서블릿을 호출하는 것이 스레드다.
- 애플리케이션 코드를 하나하나 순차적으로 실행하는 것이 스레드다.
- 자바의 main 메소드를 실행하면 main이라는 이름의 스레드가 실행되는 것이다.
- 스레드가 없으면 자바 애플리케이션 실행이 불가능하며, 스레드는 한 번에 하나의 코드 라인만 수행한다.
- 따라서 동시 처리가 필요할 때는 스레드를 추가로 생성해 줘야 한다.
- 요청이 오면 스레드를 할당하고 스레드를 가지고 서블릿을 호출한다.
- 다음은 다중 요청이 들어오는 시나리오다.
- 요청 1이 들어왔을 때 스레드를 써서 처리중이었다. 이 때 무언가 문제로 처리가 지연됐다고 하자
- 이 때 요청 2가 들어오면 2는 계속 스레드를 기다린다.
- 이 경우 두 요청이 기다리다가 모두 타임아웃으로 죽어버리는 문제가 발생한다.
- 따라서 요청 마다 스레드를 새로 만들면 이전 요청의 지연과 상관없이 응답이 가능하다.
- 요청이 올 때마다 스레드를 생성하면 동시 요청 처리와, 리소스 허용할 때까지 처리가 된다. 또 지연이 생길 경우 나머지 스레드가 정상 동작한다.
- 그러나 단점은 생성 비용이 비싸며 매 요청마다 스레드 생성으로 응답 속도가 늦어진다.
- 스레드는 컨텍스트 스위칭 비용이 발생한다.
- 또 스레드 생성에 제한이 없어 너무 많은 요청 발생시 메모리 임계점을 넘어 서버가 죽을 수 있다.
- 이런 단점을 극복하기 위해 was 내부에 스레드 풀이라는 것을 둔다.
- 스레드 풀 안에 스레드를 여러개 두고 있다가 요청이 오면 스레드 풀에 요청을 해 스레드를 응답한다.
- 요청이 스레드를 다 쓰고 나면 스레드를 스레드 풀로 다시 반납한다.
- 스레드를 임계점 이상으로 사용하게 되면, 스레드 요청을 거절거나 대기시킨다.
- 톰캣은 최대 200개의 스레드를 보유한 스레드 풀을 설정한다.
- 이 경우 스레드가 미리 생성되어 있어 스레드 생성 종료 비용이 절약되고 응답 시간이 빠르다.
- 또 생성 가능한 스레드의 최대치가 있어 많은 요청이 들어와도 기존 요청을 안전하게 처리한다.
- 최대 스레드를 얼마나 조절하느냐가 중요하다.
- 장애가 발생 시, 클라우드면 일단 서버를 늘리고 이후에 튜닝한다.
- 클라우드가 아니면 평소 열심히 튜닝해야 한다...
- 너무 높게 설정하면 동시 요청이 많아 임계점 초과로 서버가 다운될 수 있다.
- 반대로 최대 스레드를 너무 낮게 설정하면 응답이 지연되고 cpu 사용량이 낮다는 점이 문제다.
- 이 적정 숫자는 모두 다르므로, 최대한 실제 서비스와 유사하게 성능 테스트를 하는 것이 중요하다.
- 궁극적으로, WAS가 멀티 스레드를 지원한다는 것이 핵심이다.
- 단 싱글톤 객체는 주의해서 사용하자
4) HTML, HTTP API, CSR, SSR
- 정적 리소스를 제공할 때는 고정 html, css, 이미지 등을 제공한다.
- 동적인 html 파일을 생성해 전달할 수 있다.
- http api는 html이 아닌, 데이터를 전달하는 것이다.
- 주로 json 형식의 데이터를 전달한다.
- http api는 데이터만을 주고받고, ui 화면이 필요하면 클라이언트가 별도로 처리한다.
- 웹 브라우저가 was에서 내려받은 http api로 주고받은 데이터를 가지고 html을 동적 생성하면 웹 클라이언트다. 앱 클라이언트도 동일하다.
- 서버와 서버간 주고받을 때도 사용한다.
- http api는 주소 json 형태로 통신한다.
- ui 클라이언트 접점이 있다(앱/웹 클라이언트).
- 서버와 서버 간 통신에서도 사용한다.
- 서버 사이드 렌더링과 클라이언트 사이드 렌더링이 있다.
- 서버 사이드 렌더링은 html 최종 결과를 서버에서 만들어 웹 브라우저에 전달한다. 주로 정적인 화면에 사용한다.
- 클라이언트 사이드 렌더링은 html 결과를 처음부터 얻는 것이 아닌, js를 사용해 웹 브라우저에서 동적으로 생성하는 것이다. 주로 동적인 화면에 사용해 구글 지도처럼 웹 환경을 앱처럼 필요한 부분부분 변경할 수 있다.
- 웹 브라우저의 주문 내역 요청이 있을 때, 서버가 주문 db 조회 후 동적 html을 생성해 최종적으로 html을 서버에서 만드는 것을 서버 사이드 렌더링이라 한다. 동적 최종 결과물이 서버에서 생성된다.
- 클라이언트 사이드 렌더링이다.
- 웹 브라우저가 서버에 주문 내역을 요청하는 것은 같다
- 서버가 html을 응답하는데, 이때 html 안에 내용이 없고, html을 구동하는 js링크만 보낸다.
- 웹 브라우저가 그 js 코드를 서버에 요청한다. 그 응답으로 서버는 클라이언트 로직과 html 렌더링 코드가 담겨있는 js 코드를 보낸다.
- 웹 브라우저가 http api로 데이터를 요청하고 서버가 json 형식으로 데이터를 응답해 내려준다.
- 백엔드 개발자는 ui 기술에서 서버 사이드 렌더링 기술을 연마해야 한다. 주로 타임리프를 활용한다. 화면이 정적이고 복잡하지 않을 때 사용한다.