웹 애플리케이션 이해
웹 서버, 웹 애플리케이션 서버
웹이라는 것은 다 HTTP 기반으로 통신을 한다.
예를 들어서, 웹 브라우저 클라이언트에서 URL을 치면 인터넷을 통해서 서버에 접근을 하고 서버에서는 HTML을 만들어서 클라이언트에 내려준다. 그러면 웹 브라우저가 받은 HTML을 가지고 우리 눈 앞에 보여주는 것이다.
그런데 클라이언트에서 서버로 전송할 때, 그리고 서버에서 클라이언트로 데이터를 응답할 때 이때 다 HTTP라는 프로토콜을 기반으로 동작을 한다. 즉, 모든 것이 웹 세상에서는 다 HTTP를 기반으로 데이터를 주고 받는 것이다.
HTTP를 정리하면 아래와 같다.
HTML, TEXT
Image, 음성, 영상, 파일
JSON, XML(API)
거의 모든 형태의 데이터 전송 가능
서버간에 데이터를 주고 받을 때도 대부분 HTTP 사용
웹 서버(Web Server)
웹 서버라는 것은 우선 HTTP를 기반으로 동작하는 서버이다.
그리고 정적 리소스를 제공을하고, 기타 부가기능들을 제공한다. 여기서 정적 리소스라는 건 뭐냐면 보통 특정 폴더, 디렉토리에 HTML, CSS, JS 그리고 이미지, 영상 같은 파일들을 두면 이 서버들이 그 파일들을 그냥 서버해주는 것이다. 즉, HTTP로 원하는 HTML을 달라고 웹 서버에 요청을 하면 웹 서버가 요청에 맞게 HTTP 프로토콜로 응답을 주는 것이다.
대표적으로 Nginx랑 Apache라는 웹 서버가 있다.
웹 애플리케이션 서버(WAS - Web Application Server)
WAS도 HTTP 기반으로 동작한다. 그리고 WAS는 앞에 웹 서버의 기능들을 대부분 포함하고 있다.
웹 서버와 차이점은 프로그램 코드를 실행해서 애플리케이션 로직을 수행할 수 있다. 웹 서버 같은 경우에는 정적인 파일을 들고 서빙을 하기 때문에 HTML을 특정 사용자마다 다르게 보여줄 수가 없다. 그러나 WAS는 HTTP 요청이 오면 사용자에 따라서 해당 사용자 이름도 보여줄 수 있고, 다른 화면들도 보여줄 수 있다. 왜냐하면 프로그래밍을 할 수 있기 때문이다. 그래서 프로그램 코드를 실행해서 애플리케이션 로직을 수행할 수 있는 게 WAS의 특징이다.
정리하면,
동적인 HTML로 생성할 수 있고, HTTP API, REST API라고도 한다.
서블릿, JSP, 스프링 MVC 같은 것들이 WAS에서 동작하게 된다.
대표적으로 Tomcat, Jetty, Undertow 같은 서버들이 WAS 서버라고 한다.
웹 서버, 웹 애플리케이션 서버 차이
웹 서버는 정적 리소스(파일), WAS는 애플리케이션 로직
사실 둘의 용어도 경계도 모호하다.
웹 서버도 프로그램을 실행하는 기능을 포함하기도 한다.
WAS 서버도 웹 서버의 기능을 제공한다.
자바는 서블릿 컨테이너 기능을 제공하면 WAS
서블릿 없이 자바 코드를 실행하는 서버 프레임워크도 있다.
WAS는 애플리케이션 코드를 실행하는데 더 특화되어 있다.
웹 시스템 구성 - WAS, DB
보통 실제 시스템을 구성해야 되면 가장 간단하게는 WAS, DB만으로 구성할 수 있다. 이유는 WAS가 정적 리소스, 애플리케이션 로직 모두 제공할 수 있기 때문이다.
하지만 이렇게 보면 WAS가 너무 많은 역할을 담당하고 있다고 느껴진다. 그러면 서버 과부하 우려도 있고, 정적인 컨텐츠들도 계속 제공해 줘야 한다.
그리고 가장 비싼 애플리케이션 로직이 정적 리소스 때문에 수행이 어려울 수 있고, WAS 장애시 오류 화면도 노출이 불가능하다.
그래서 일반적으로는 아래와 같이 웹 시스템 구성을 많이 한다.
웹 시스템 구성 - WEB, WAS, DB
구성은 정적 리소스를 앞에 둔다. 즉, 웹 서버에서 정적 리소스를 다 처리하는 것이다. 그러다가 동적인 로직이 필요하면 WAS에서 처리한다.
이렇게 되면 WAS는 굉장히 중요한 애플리케이션 로직에 전담할 수 있다.
그리고 웹 서버는 단순한 정적인 리소스들 과 필요하면 뒤에 WAS 대신 호출하고 이러한 로직들만 처리를 하면서 역할을 분담하는 것이다.
또 이렇게 하면 좋은 점이 시스템 리소스를 굉장히 효율적으로 쓸 수 있다.
예를 들어, 정적 리소스가 많이 필요할 경우 웹 서버만 해당 정적 리소스 호출할 리소스에 맞춰서 증가시키면 된다. 반대로 정적 리소스는 별로 증가가 없고, 애플리케이션 로직만 쭉 많이 호출이 되면 WAS 서버를 증가시키면 된다.
그리고 정적 리소스만 구성하는 서버는 서버가 잘 죽지 않는다. 반대로 애플리케이션 로직이 동작하는 WAS 서버는 잘 죽는다.
만약에 WAS 서버가 죽으면, 웹 서버는 오류화면 HTML을 뿌리도록 설정할 수 있다.
서블릿
만약에 아래와 같은 HTML Form이 있다고 가정하자.
입력을 하고 전송을 누르면 웹 브라우저가 요청 HTTP 메시지를 만들어서 서버로 전송한다.
그런데 만약에 웹 애플리케이션 서버를 우리가 직접 다 구현해야할 경우 아래 그림과 같이 작업을 해야한다.
위 그림을 봤을 때 비즈니스를 로직은 그냥 회원 이름이랑 나이를 가지고 데이터베이스에 저장 요청을 하는게 끝이다. 그런데 그 전단계와 후단계가 너무 많다. 그럼 개발자가 매번 이러한 작업을 하는 건 너무 비효율적일 것이다.
그래서 위 문제를 해결하기 위해 서블릿이 나온 것이다.
서블릿은 비즈니스 로직을 제외한 모든 일을 다 지원해준다.
서블릿 특징
urlPatterns(/hello)
의 URL이 호출되면 서블릿 코드가 실행된다.HttpServletRequest는 HTTP 요청 정보를 편리하게 사용할 수 있게 해준다.
HttpServletResponse는 HTTP 응답 정보를 편리하게 제공할 수 있게 해준다.
서블릿을 통해서 개발자는 HTTP 스펙을 매우 편리하게 사용할 수 있다.
그러면 전체 흐름을 살펴보자.
웹 브라우저에서 서버가
localhost:8080/hello
를 요청한다.WAS에서 HTTP 요청 메시지를 기반으로 Request, Response 객체를 새로 만들어서 서블릿 객체를 호출한다.
개발자는 Request 객체에서 HTTP 요청 정보를 편리하게 꺼내서 사용한다.
개발자는 Response 객체에 HTTP 요청 정보를 편리하게 입력한다.
WAS는 Response 객체에 담겨있는 내용으로 HTTP 응답 정보를 생성한다.
그러면 위에서 나온 서블릿 컨테이너에 대해서 알아보자.
톰캣처럼 서블릿을 지원하는 WAS를 서블릿 컨테이너라고 한다.
서블릿 컨테이너는 서블릿 객체를 생성, 초기화, 호출, 종료하는 생명주기를 관리한다.
서블릿 객체는 싱글톤으로 관리한다.
고객의 요청이 올 때 마다 계속 객체를 생성하는 것은 비효율
최초 로딩 시점에 서블릿 객체를 미리 만들어두고 재활용
모든 고객 요청은 동일한 서블릿 객체 인스턴스에 접근
공유 변수 사용 주의
서블릿 컨테이너 종료시 함께 종료
JSP도 서블릿으로 변환 되어서 사용한다.
동시 요청을 위한 멀티 쓰레드 처리 지원한다.
동시 요청 - 멀티 쓰레드
먼저 웹 브라우저 클라리언트에서 서버로 요청을 WAS 서버는 응답을 할 것이다. 좀더 자세히 살펴보면, TCP / IP 커넥션 연결이 된다. 그리고 여기서 서블릿을 호출해준다.
그런데 서블릿 객체는 누가 호출할까?
바로 쓰레드라는게 호출을 한다.
쓰레드
쓰레드란 애플리케이션 코드를 하나하나 순차적으로 실행하는 것이다.
자바의 메인 메서드를 실행하면 main
이라는 이름의 쓰레드가 실행된다. 그래서 쓰레드가 없다면 자바 애플리케이션 실행이 불가능하다.
그리고 쓰레드는 한번에 하나의 코드 라인만 수행하고, 동시 처리가 필요하면 쓰레드를 추가로 생성해줘야 한다.
일단 먼저 단일 요청일 때를 살펴보자.
요청이 하나가 오면 쓰레드를 할당을 한다. 그리고 이 쓰레드를 가지고 서블릿을 실행 해주는 것이다.
쓰레드를 가지고 응답까지 다 하고 나면 이제 쓰레드가 휴식을 한다.
이제 다중 요청일 경우를 알아보자.
요청1을 한 상황에서 지금 지연된 상황이라고 가정하자.
그런데 이 상황에서 또 다른 요청2가 들어온다. 그런데 현재 쓰레드는 하나밖에 없는 상황이다.
그러면 요청2는 쓰레드가 사용이 끝날 때까지 기다려야 하는데, 이러면 기다리다가 타임아웃이 나거나 오류가 발생해서 두 요청이 죽어버린다.
위 문제를 해결하는 것은 단순하게 쓰레드를 하나 더 생성하면 된다.
즉, 요청이 올 때마다 쓰레드를 하나 만드는 것이다. 그러면 같은 서블릿을 호출해도 정상적으로 수행하고 수행을 마친 쓰레드는 날리면 된다.
요청 마다 쓰레드 생성 장단점
장점
동시 요청을 처리할 수 있다.
리소스(CPU, 메모리)가 허용될 때 까지 처리 가능하다.
하나의 쓰레드가 지연 되어도, 나머지 쓰레드는 정상 동작한다.
단점
쓰레드는 생성 비용이 매우 비싸다.
고객의 요청이 올 때 마다 쓰레드를 생성하면, 응답 속도가 늦어진다.
쓰레드는 컨텍스트 스위칭 비용이 발생한다.
쓰레드 생성에 제한이 없다.
고객 요청이 너무 많으면, CPU, 메모리 임계점을 넘어서 서버가 죽을 수도 있다.
이 문제를 해결하기 위해서 보통 WAS들은 아래 그림과 같이 내부에 쓰레드 풀이라는 것을 쓴다.
쓰레드 풀 안에 쓰레드가 대기하고, 요청이 들어오면 일이 없는 쓰레드에게 요청을 처리하게 하는 것이다. 즉, 인력사무소 같은 느낌이다.
예를 들어 설정해 놓은 200개보다 더 많은 요청이 들어오면, 나머지 요청들은 쓰레드 풀에 대기하거나 거절을 할 수 있다.
쓰레드 풀 - 요청 마다 쓰레드 생성의 단점 보완
특징
필요한 쓰레드를 쓰레드 풀에 보관하고 관리한다.
쓰레드 풀에 생성 가능한 쓰레드의 최대치를 관리한다. 톰캣은 최대 200개 기본 설정(변경가능)
사용
쓰레드가 필요하면, 이미 생성되어 있는 쓰레드를 쓰레드 풀에서 꺼내서 사용한다.
사용을 종료하면 쓰레드 풀에 해당 쓰레드를 반납한다.
최대 쓰레드가 모두 사용중이어서 쓰레드 풀에 쓰레드가 없는 경우
기다리는 요청은 거절하거나 특정 숫자만큼만 대기하도록 설정할 수 있다.
장점
쓰레드가 미리 생성되어 있으므로, 쓰레드를 생성하고 종료하는 비용(CPU)이 절약되고, 응답 시간이 빠르다.
생성 가능한 쓰레드의 최대치가 있으므로 너무 많은 요청이 들어와도 기존 요청은 안전하게 처리할 수 있다.
쓰레드 풀 - 실무 팁
WAS의 주요 튜닝 포인트는 최대 쓰레드 수이다.
최대 쓰레드 수를 너무 낮게 설정할 경우
동시 요청이 많으면, 서버 리소스는 여유롭지만 클라이언트는 금방 응답이 지연된다.
최대 쓰레드 수를 너무 높게 설정할 경우
동시 요청이 많으면, CPU, 메모리 리소스 임계점 초과로 서버가 다운된다.
장애 발생시
클라우드면 일단 서버부터 늘리고, 이후에 튜닝
클라우드가 아니면 열심히 튜닝
WAS의 멀티 쓰레드 지원
멀티 쓰레드에 대한 부분은 WAS가 처리
개발자가 멀티 쓰레드 관련 코드를 신경쓰지 않아도 된다.
개발자는 마치 싱글 쓰레드 프로그래밍을 하듯이 편리하게 소스 코드를 개발할 수 있다.
멀티 쓰레드 환경이므로 싱글톤 객체(서블릿, 스프링 빈)는 주의해서 사용해야 한다.
HTML, HTTP API, CSR, SSR저
정적 리소스
고정된 HTML 파일, CSS, JS, 이미지, 영상 등을 제공
주로 웹 브라우저
HTML 페이지
동적으로 필요한 HTML 파일을 생성해서 전달
웹 브라우저: HTML 해석
HTTP API
HTML이 아니라 데이터를 전달
주로 JSON 형식 사용
다양한 시스템에서 호출
데이터만 주고 받고, UI 화면이 필요하면, 클라이언트가 별도로 처리
앱, 웹 클라이언트, 서버 to 서버
다양한 시스템 연동
주로 JSON 형태로 데이터 통신
UI 클라이언트 접점
앱 클라이언트(아이폰, 안드로이드, PC앱)
웹 브라우저에서 자바스크립트를 통한 HTTP API 호출
React, Vue.js 같은 웹 클라이언트
서버 to 서버
주문 서버 → 결제 서버
기업간 데이터 통신
서버 사이드 렌더링, 클라이언트 사이드 렌더링
SSR - 서버 사이드 렌더링
HTML 최종 결과를 서버에서 만들어서 웹 브라우저에 전달
주로 정적인 화면 제공
관련기술: JSP, 타임리프 → 백엔드 개발자
CSR - 클라이언트 사이드 렌더링
HTML 결과를 자바스크립트를 사용해 웹 브라우저에서 동적으로 생성해서 적용
주로 동적인 화면에 사용, 웹 환경을 마치 앱 처럼 필요한 부분부분 변경할 수 있음
ex) 구글 지도, Gmail, 구글 캘린더
관련기술: React, Vue.js → 프론트엔드 개발자
참고
React, Vue.js를 CSR + SSR 동시에 지원하는 웹 프레임워크도 있다.
SSR을 사용하더라도, 자바스크립트를 사용해서 화면 일부를 동적으로 변경할 수 있다.
참고 자료
Last updated