웹 애플리케이션 이해

모든 것이 HTTP

서버간에 데이터를 주고받을때도 HTTP르 사용한다.

웹 서버(Web Server)

HTTP 기반으로 동작하는 서버이다. 정적 리소스를 제공하고 기타 부가기능을 제공한다. 정적(파일) HTML, CSS, JS, 이미지, 영상을 제공한다.

웹 애플리케이션 서버(WAS, Web Application Server)

마찬가지로 HTTP 기반으로 동작하는 서버이다. 웹 서버의 기능(정적 리소스 제공)을 포함한다. 프로그램 코드를 실행해서 애플리케이션 로직을 수행할 수 있다. 즉, 동적인 데이터를 생성해서 응답할 수 있다.

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

이 두가지는 비슷하지만 한 마디로 정리하면, 웹 서버는 정적 리소스를 제공하는 것, WAS는 애플리케이션 로직을 수행하는 것 이라고 보면 된다. 하지만 사실 이 경계는 모호해서 WAS가 웹 서버의 기능을 포함하는 경우도 많다. 자바의 경우에는 서블릿 컨테이너 기능을 제공하면 WAS라고 볼 수 있다.

웹 시스템 구성 - WAS, DB

WAS, DB만으로 시스템을 구성하는 것이 가능하다. 가장 기본적인 형태의 웹 시스템이다. HTML, CSS, JS는 값싼 리소스이다. 가장 비싼 애플리케이션 로직이 정적 리소스 때문에 수행이 어려울 수 있다. 예를 들어, 주문 시스템에서 주문을 하는 로직은 디비에 접근하고 결제한 다음 다시 디비에 쓰는 과정을 수행한다. 반면, 화면을 출력하는 기능은 가볍다. 따라서 규모가 커지면 WAS만으로 수행하기 보다는 웹 서버를 별도로 앞에 둔다.

웹 시스템 구성 - WEB, WAS, DB

시스템 리소스를 효율적으로 사용할 수 있다. 예를 들어, 애플리케이션 로직에 부하가 많으면 WAS를 늘리고, 정적 리소스 호출에 부하가 많으면 Web Server를 늘리면 된다.

정적 리소스를 제공하는 웹 서버는 잘 안 죽는다. 하지만 WAS는 비교적으로 죽을 확률이 높다. 로직을 잘못 짜거나 DB의 문제 등으로 그럴 수가 있다.

WAS에 문제가 생기면 웹 서버 단에 "서버에 문제가 있습니다"와 같은 안내 메시지를 보내고 복구작업을 한다던지 분리가 가능하다.


HTML Form 데이터 전송

POST 전송을 하면 웹 브라우저가 생성한 요청 HTTP 메시지를 담아서 서버로 보낸다. 기본적으로 HTTP는 TCP/IP를 기반으로 한다. 그러면 서버에서는 메시지를 파싱해서 하나씩 하나씩 의미를 해석하며 읽는다.

하지만 사실은 비즈니스 로직 실행 부분만 의미가 있다. 회원 이름과 나이를 db에 저장하는 기능이 핵심인 것이다. 그래서 서블릿은 핵심 비즈니스 로직 이외의 로직을 자동화해준다. HttpServletRequestHttpServeletResponse를 사용하여 이를 처리할 수 있다.

서블릿 - 서블릿 컨테이너

서블릿 객체는 싱글톤으로 관리한다. 따라서 공유 변수 사용에 주의하여야 한다. JSP도 서블릿으로 변환되어서 사용된다. 또한 중요한 점은 동시 요청을 위한 멀티스레드 처리를 지원한다는 것이다. 개발자가 멀티스레드를 크게 신경쓰지 않아도 서블릿이 자동으로 처리해주는 것이다.


동시 요청 - 멀티스레드

서블릿은 누가 호출하는가? 바로 쓰레드가 호출한다.

쓰레드

동시 처리가 필요하면 쓰레드를 추가로 생성하는 것이 필요하다.

다중 요청 - 쓰레드 하나 사용

이미 요청1을 처리하는 중에 요청2가 오면 둘 다 죽는 문제가 발생

요청 마다 쓰레드 생성

요청 마다 쓰레드를 생성하면 서로 영향을 미치지 않고 각자 요청을 수행할 수 있다.

요청 마다 쓰레드 생성 - 장단점

  • 장점
    • 동시 요청을 처리가능
    • 리소스 한도 내에서 처리가능
    • 하나의 쓰레드가 지연되어도, 나머지 쓰레드는 정상 동작
  • 단점
    • 쓰레드 생성 비용은 매우 비싸다
      • 고객의 요청이 올 때 마다 쓰레드 생성하면, 응답 속도가 늦어진다.

쓰레드 풀

풀안에 쓰레드를 미리 만들어놓고 요청이 올 때 마다 하나씩 꺼내쓰는 방식을 사용한다. 요청이 올 때 마다 하나씩 제공하고 다 쓰면 없애는게 아니라 풀안에 다시 넣어둔다.

쓰레드 풀 - 요청 마다 쓰레드 생성의 단점 보완

  • 필요한 쓰레드를 쓰레드 풀에 보관하고 관리한다.
  • 쓰레드 풀에 생성 가능한 쓰레드의 최대치를 관리한다. 톰캣은 최대 200개 기본 설정
  • 쓰레드가 필요하면 이미 생성된 쓰레드를 쓰레드 풀에서 꺼내 사용
  • 사용 종료 시 쓰레드 풀에 해당 쓰레드 반납
  • 최대 쓰레드가 모두 사용중이어서 풀에 쓰레드가 없으면 대기 or 거절

쓰레드 풀 - 실무 팁

성능 최적화 관련해서 WAS의 주요 튜닝 포인트는 최대 쓰레드(max thread) 수이다. 즉, 최대의 성능을 내는 적정 수준의 임계치가 있다.

쓰레드 풀 - 너무 낮게 설정

CPU 5%만 사용한다? 최소 50%는 사용하는게 정상이다. 이걸 모르고 AWS 서버를 10개로 늘리고 하는 등의 조치는 의미가 없다.

쓰레드 풀 - 쓰레드 풀의 적정 숫자

그렇다면 적정 숫자는 어떻게 찾는가? 이는 애플리케이션 로직의 복잡도, CPU, 메모리, I/O, 리소스 상황에 따라 모두 다르다. 따라서 성능 테스트를 통해서 최대한 실제 서비스와 유사하게 환경을 만들어 놓고 성능 테스트를 시도해보면 좋다. 이때 Apach ab 등의 툴을 사용해서 테스트 해보면 된다.

WAS의 멀티 쓰레드 지원 - 핵심

멀티 쓰레드에 대한 부분은 WAS가 처리한다. 개발자가 멀티 쓰레드 관련 코드를 신경쓰지 않아도 된다. 개발자는 마치 싱글 쓰레드 프로그래밍을 하듯이 편리하게 소스코드는 개발하면 된다. 단, 실제로 멀티 쓰레드 환경이므로 싱글톤 객체(서블릿, 스프링 빈)을 주의해서 사용해야한다.


HTML, HTTP API, CSR, SSR

HTML 페이지

동적으로 필요한 HTML 파일을 생성해서 전달한다. 웹 브라우저는 HTML을 해석해서 보여준다.

HTML API

HTML이 아니라 데이터를 전달한다. 주로 JSON 포맷을 사용한다. 다양한 시스템을 호출한다. 이는 주로 세 가지 상황에서 사용된다. WAS - DB 사이에, 앱 클라이언트 - WAS 사이에서, 웹 클라이언트 - WAS 사이에서 사용된다. 왜냐하면 이때 HTML 페이지를 주고받을 필요는 없이 최소한의 데이터(JSON)만 주고받으면 되기 때문이다.

HTTP API - 다양한 시스템 연동

주로 JSON 포맷으로 데이터 통신한다.

서버사이드 렌더링, 클라이언트 사이드 렌더링

SSR - 서버 사이드 렌더링

서버에서 최종 HTML을 생성해서 클라이언트에 전달

CSR - 클라이언트 사이드 렌더링

서버에서 최종 HTML을 가져오는 것이 아니라, HTML 최종 결과를 자바스크립트로 웹 브라우저에서 동적으로 생성해서 적용하는 방식이다. 주로 동적인 화면에 사용한다.


자바 백엔드 웹 기술 역사

자바 웹 기술 역사

  • 애노테이션 기반의 스프링 MVC 등장
    • @Controller를 통해서 MVC 컨트롤러를 매우 쉽게 생성 가능하다.
    • MVC 프레임워크 최종 승자
  • 스프링 부트 등장
    • 스프링 부트는 서버를 내장한다.
    • 과거에는 서버에 WAS를 직접 설치하고, 소스는 WAR 파일을 만들어서 설치한 WAS에 배포한다.
    • 스프링 부트는 빌드 결과 파일(JAR)에 WAS 서버를 포함한다. 따라서 빌드 및 배포가 단순화 되었다.

최신 기술 - 스프링 웹 플럭스(WebFlux)

비동기 넌 블럭킹 처리를 한다. 최소 쓰레드로 최대 성능을 낸다. 쓰레드 컨텍스트 스위칭 비용을 효율적으로. 함수형 스타일로 개발 가능하다. 동시처리 코드가 효율화된다. 서블릿 기술을 사용하지 않는다.

아직은 실무에서 사용하기에 러닝 커브가 너무 높아서 사용하지 않고 있다.

자바 뷰 템플릿 역사

HTML을 편리하게 생성하는 뷰 기능

JSP는 속도가 느리고 기능이 부족했다. 프리마커와 벨로시티는 별로 발전하지 못해따. 현재 타임리프는 HTML 템플릿을 유지하면서 뷰 템플릿을 적용가능 하므로 코드가 깔끔하다. 스프링 MVC와 강력한 기능 통합이 가능하다. 물론 성능은 프리마커와 벨로시티가 더 빠르지만 크게 중요하지 않으므로 타임리프를 주로 사용한다.