웹 애플리케이션의 이해

김민우·2022년 7월 22일
0

MVC

목록 보기
1/16
post-custom-banner

클라이언트와 서버의 통신은 HTTP를 기반으로 통신을 한다.

HTTP 프로토콜을 통해 데이터를 주고 받을 수 있고 정적 파일을 제공해준다.

웹 서버

  • HTTP 기반으로 동작한다.
  • 정적 리소스를 제공하거나 기타 부가 기능을 제공한다.

웹 애플리케이션 서버 (WAS)

  • HTTP 기반으로 동작한다.
  • 웹 서버의 기능(정적 리소스 제공)을 포함한다.
  • 프로그램 코드를 실행해서 애플리케이션 로직을 수행한다.
  • 예) 톰켓(Tomcat) Jetty, Undertow

간단히 요약하면 웹 서버는 정적 리소스, WAS는 애플리케이션 로직을 실행하는 서버이다.

그러나, WAS가 웹 서버의 역할을 제공할 수 있고, 웹 서버 또한 프로그램을 실행하는 기능을 포함하기도 한다.

이렇듯, 둘의 용어와 경계가 모호한데 간단히 이렇게 생각하자.

  • WAS는 애플리케이션 코드를 실행하는데 더 특화되있다.

얼핏 봤을 때 WAS는 웹 서버 + 부가적인 기능이니깐 WAS와 DB만 이용해서 충분히 시스템을 구성할 수 있겠다라는 생각이 들것이다.

이게 가능할까? 가능은 하지만 다음과 같은 문제점이 있다.

  • 이렇게 구성을 하게 되면 WAS가 너무 많은 역할을 담당하여 서버 과부화가 우려된다.
  • 애플리케이션 로직은 정적 리소스에 비해 실행 단계가 복잡하다. (이를 값이 비싸다고 이야기한다.) 그래서 이러한 애플리케이션 로직이 값이 싼 정적 리소스 때문에 수행이 어려워지면 안된다.
  • WAS에 오류가 발생 시 오류화면을 노출하는 것도 불가능하다.(WAS가 모든것을 담당하고 있으니깐)

그래서 보통 시스템을 구성할 때는 WAS와 웹서버 2개를 사용한다. 다음 그림을 보자.

  • 클라이언트와 WAS 사이에 웹 서버를 둔다.
  • 정적 리소스는 웹 서버가 처리한다.
  • 애플리케이션 로직같은 동적인 처리는 WAS가 처리한다.

WAS는 중요한 애플리케이션 로직 처리에만 전담할 수 있고, 웹 서버는 간단한 정적 리소스만 전담할 수 있어 시스템 리소스를 효율적으로 사용할 수 있다.
또한, 정적 리소스가 많이 사용되면 웹 서버만 증설, 애플리케이션 리소스가 많아지면 WAS를 증설하면 된다.
마지막 문제점 중 하나인 WAS나 DB 장애시 웹 서버를 통해 오류 화면 제공이 가능하다. (참고로, 웹 서버는 WAS나 DB에 비해 거의 장애가 나지 않는다. 이 둘은 장애가 생각보다 자주 발생)


서블릿

서버가 클라이언트의 다음과 같은 요청 메시지를 읽고 응답을 하는 경우를 생각해보자. 서버에서 처리해야하는 업무는 다음과 같다.

  • 서버 TCP/IP 연결 대기/ 소켓 연결
  • HTTP 요청 메시지를 파싱해서 읽기
  • POST 방식, /save URL 인지
  • Content-Type 확인
  • HTTP 메시지 바디 내용 파싱
    • username, age 데이터를 사용할 수 있도록 파싱
  • 저장 프로세스 실행
  • 비즈니스 로직 실행
    • 데이터베이스에 저장 요청
  • HTTP 응답 메시지 생성 시작
    • HTTP 시작 라인 생성
    • Header 생성
    • 메시지 바디에 HTML 생성에서 입력
  • TCP/IP에 응답 전달, 소켓 종료

개발자는 비즈니스 로직 실행만 집중하면 된다. 그러나 이외에 수행 단계가 너무 많다.

서블릿은 이러한 과정 중 방금 언급한 비즈니스 로직 실행 단계를 제외한 모든 일을 대신 해줌으로써 개발자가 비즈니스 로직 실행에만 집중할 수 있도록 해준다.

이를 사용하는 방법을 알아보자. 다음은 서블릿 코드 이다.

@WebServlet(name = "helloServlet", urlPatterns = "/hello")
public class HelloServlet extends HttpServlet {
	
    @Override
    protected void service(HttpServletRequest request, HttpServletResponse response) {
    	// 애플리케이션 로직 작성
    }
}
  • urlPatterns에 있는 URL(/hello)이 호출되면 서블릿 코드가 실행된다.
  • HttpServletRequest 타입 파라미터를 통해 HTTP 요청 정보를 편리하게 사용할 수 있다.
  • HttpServletResponse 타입 파라미터를 통해 HTTP 응답 정보를 편리하게 제공할 수 있다.

이를 통해 개발자는 HTTP 스펙을 매우 편리하게 사용한다. 서블릿 코드가 실행되면 다음 과정을 거쳐 HTTP 응답 메시지가 클라이언트에 리턴된다.

  • WAS는 Request, Response 객체를 새로 만들어서 서블릿 객체를 호출한다.
  • 개발자는 Request 객체에서 HTTP 요청 정보를 편리하게 꺼내서 사용한다.
  • 개발자는 Response 객체에 HTTP 응답 정보를 편리하게 입력한다.
  • WAS는 Response 객체에 담겨있는 내용으로 HTTP 응답 정보를 생성한다.

서블릿 컨테이너는 톰켓처럼 서블릿을 지원하는 WAS를 말한다.

  • 서블릿 컨테이너는 서블릿 객체를 생성, 초기화, 호출, 종료하는 생명주기를 관리한다.
  • 서블릿 객체는 싱글톤으로 관리된다.
    • 공유 변수(멤버 변수) 사용시 주의하자.
  • JSP도 서블릿으로 변환되서 사용
  • 동시요청을 위한 멀티 스레드 처리도 지원한다.

멀티 스레드

하나의 애플리케이션 코드를 순차적으로 실행하는 것은 스레드이다. 이러한 스레드가 없으면 자바 애플리케이션은 실행이 불가능하다.

스레드는 한 번에 하나의 코드 라인만 수행하므로 동시 처리가 필요하면 스레드를 추가로 생성해야 한다.

단일 요청의 경우 스레드를 하나만 사용해도 상관없다. 그러나, 다중 요청인 경우엔 어떨까?

스레드가 2개의 요청이 오면 병렬적으로 처리를 한다. 이 때 처음 요청에서 오류가 발생한다면 두 번째 클라이언트의 요청이 지연된다.

이를 어떻게 해결할까? 요청마다 스레드를 생성하면 된다. 그러나, 요청마다 스레드를 생성을 하면 이러한 문제점을 해결할 수 있는 것 외 여러 가지 장점이 존재하지만 많은 단점도 존재한다. 자세히 알아보자.

요청마다 스레드 생성

장점

  • 동시 요청을 처리할 수 있다.
  • 리소스(CPU, 메모리)가 허용할 때 까지 처리 가능하다.
  • 하나의 스레드가 지연되어도, 나머지 스레드는 정상 작동한다.

단점

  • 스레드의 생성 비용은 매우 비싸다.
    (또한, 고객의 요청 마다 스레드를 생성하면, 응답 속도가 늦어진다.)

  • 스레드는 컨텍스트 스위칭 비용이 발생한다.

    컨텍스트 스위칭 : 코어에서 스레드를 다른 스레드로 전환하는 것
    예를 들어 스레드 하나가 작업 1~5를 1, 2, 3, 4, 5 순으로 반복적으로 실행하면 작업 1을 실행하고 2, 3, 4, 5를 기다리고 다시 작업 1을 수행하는데 이를 컨텍스트 스위칭이라 한다.

  • 스레드 생성에 제한이 없다.
    (이게 왜 단점일까? 잘 생각해보면 고객 요청이 너무 많으면 CPU, 메모리 임계점을 넘어서 서버가 다운될 수 있다.)

이를 보완한 것이 스레드 풀이다.

스레드 풀

고객의 요청이 들어오기 전 미리 작업 스레드를 만들어놓고 작업 큐에 요청이 들어오면 스레드들이 순차적으로 작업을 처리한다.

스레드 풀에서 생성 가능한 스레드의 최대치를 관리하고, 요청이 너무 많아 스레드가 부족한 경우 대기/거절이 가능하여 서버가 다운될 우려가 줄어들다.

시작 전 필요한 스레드 만큼을 미리 만들고 사용을 종료하면 스레드 풀에 해당 스레드를 반납하므로 스레드를 생성하고 종료하는 비용이 절약되며 응답 시간이 빠르다.

이러한 스레드 풀에서 중요한 것은 무엇일까? 바로 최대 스레드 수 이다.

최대 스레드 수

이 값을 너무 작게 설정 한 경우

  • 동시 요청이 많으면, 서버는 여유롭지만, 클라이언트는 응답이 지연된다.

이 값을 너무 크게 설정 한 경우

  • 동시 요청이 많으면, 서버가 다운될 수 있다.

이렇듯, 최대 스레드 수를 잘 잡는 것이 매우 중요하다. 이 숫자는 바로 알 수는 없고, 성능 테스트를 여러 번 해서 대략적으로 감을 잡아야 한다.

.
.
.
.

핵심은 WAS는 멀티 스레드를 지원해준다. 이는 WAS의 가장 강력한 장점이다.
우리는 싱글 스레드 프로그래밍을 작성하듯 비즈니스 로직만 잘 작성하면 된다.
(최대 스레드 수 같은 것만 개발자가 상황에 맞게 세팅해주면 된다.)

물론 WAS는 멀티 스레드 환경이므로 싱글톤 객체를 다룰 때 주의하자.


HTML, HTTP API, CSR, SSR

정적 리소스

고정된 HTML 파일, CSS, JS, 이미지, 영상 등... 이미 생성된 파일을 제공한다.

HTML 페이지

WAS는 필요한 데이터를 DB에서 조회한 후 얻은 데이터를 동적으로 HTML을 생성한다. 웹 브라우저는 WAS가 생성한 HTML을 해석한다.

HTTP API

데이터 자체를 그대로 전달하는 방식이다. 주로 JSON 형식을 사용한다.
데이터만 주고 받으며 별도의 UI 화면이 필요하면 클라이언트가 별도로 처리한다.

(HTML을 서로 보여주는 전송 방식을 제외한 모든 곳에서 실제 데이터를 주고 받고 실제 프로세스를 호출할 때 모두 사용이 되는 방식)

  • UI 클라이언트 접점
    • 앱 클라이언트(아이폰, 안드로이드, PC 앱)
    • 웹 브라우저에서 자바스크립트를 통한 HTTP API 호출
    • React, Vue.js 같은 웹 클라이언트

별도의 html이 없으므로 서버끼리 통신할 때 사용된다.
.
.
.
.

백엔드 개발자가 서비스를 제공할 때 고민해야 되는 포인트는 3가지다.

  1. 정적 리소스를 어떻게 제공할 것인가?
  2. 동적으로 생성되는 HTML 페이지는 어떻게 제공할 것인가?
  3. HTTP API를 어떻게 제공할 것인가?

SSR (서버 사이드 렌더링)

서버에서 최종 HTML을 생성해서 클라이언트에게 전달하는 방식이다. 웹 브라우저는 단순히 생성된 HTML을 렌더링만 하면 된다.

중요한 것은 백엔드 개발자는 SSR은 필수적으로 알아둬야 한다.


CSR (클라이언트 사이드 렌더링)

최종 HTML을 자바스크립트를 사용해 웹 브라우저에서 동적으로 생성해서 적용한다.
구글 지도나 메일 새로고침 처럼 동적인 화면에서 주로 사용된다.
(지도를 생각해보자. 확대하거나 축소할 때 화면 깜빡임(새로고침)이 안일어난다.)

웹 프론트엔드 개발자의 전문 분야이다. 하지만 백엔드 개발자도 알아두면 좋다.

post-custom-banner

0개의 댓글