2024.09.04.수.TIL Web Application, Servlet

김기남·2024년 9월 4일
post-thumbnail

안녕하세요, 오늘은 Web Application과 Servlet에 대해 정리해 보았습니다.

Web

  1. 클라이언트 → 서버
    • 데이터 전송
  2. 서버 → 클라이언트
    • 데이터 응답

위 두가지 경우 모두 HTTP라는 프로토콜을 기반으로 동작한다.
HTML, TEXT, Image, 음성, 영상, 파일, JSON, XML, 서버 to 서버끼리 통신 모두
HTTP를 기반으로 데이터를 전송할 수 있다.

Web Server

💡 웹 서버는 HTTP 기반으로 동작하는 서버로 **정적 리소스**(HTML, CSS, JS, 이미지 등)를 제공한다.

ex) 서버의 응답으로 동적으로 변하는 페이지가 아닌 정적인 HTML
ex) 이벤트 페이지 = 정적 HTML, 게시판 글조회 = 동적 HTML

대표적인 Web Server

  1. NGINX
  2. Apache

WAS(Web Application Server)

💡 HTTP 기반으로 동작하며 웹 서버의 기능을 포함한다. 추가적으로 **프로그램 코드를 실행해서 Application 로직을 수행**한다. 동적으로 동작하는 HTML, HTTP API(REST API), Servlet, JSP, Spring

대표적인 Web Application Server

  1. Tomcat
    1. Spring에는 Tomcat이 없다?
  2. Jetty
  3. Undertow



Web Server와 WAS의 차이점

  1. JAVA는 서블릿 컨테이너 기능을 제공하면 WAS 이다.
    1. 서블릿 없이 JAVA코드를 실행하는 서버 프레임워크도 존재한다.
  2. WAS는 Application 코드를 실행하는데 더 특화되어 있다.

웹 시스템 구성

WAS와 DB만으로 서버를 구성한다면?

  • WAS가 너무 많은 역할을 담당한다 → 서버 과부하
  • 실행에 가장 중요한 Application 로직이 정적 리소스로 인해 수행되지 않는다.
  • WAS에 장애가 생기면 아무런 화면도 보여주지 못한다. → 오류 페이지가 없다.

실제 웹 시스템의 구성

  1. 정적 리소스는 Web Server에서 처리한다.
  2. Web Server는 Application 로직이 필요한 요청은 WAS에 전달한다.

웹 시스템 구성의 장점

  1. 효율적인 리소스 관리

  • 정적 자원이 많이 사용된다면 Web Server 추가
  • Application 자원이 많이 사용되면 WAS 추가
  1. 오류화면 제공
💡 Web Server는 오류가 발생할 확률이 아주 낮다. 하지만 WAS는 오류가 발생할 확률이 높고 서버에 장애가 빈번하게 발생한다. WAS 혹은 DB에서 장애가 일어난다면 오류화면을 제공할 수 있다.
  • 성능 최적화

최근에는 정적 리소스를 캐시(임시저장)할 수 있는
CDN(Content Delivery Network) 을 사용하기도 한다.

  1. 클라이언트
  • 한국의 클라이언트
    • 철수
    • 영희
  • 미국의 클라이언트
    • 피터
    • 제이슨
  1. Web 서버
  • 똑같은 데이터 즉, Image와 같은것들을 계속 전달해줘야 한다.

Servlet

Servlet은 HTTP 프로토콜 기반 요청(Request) 및 응답(Response)을 처리하는데 사용된다.
JAVA에서 Sevlet은 HttpServlet 클래스를 상속받아 구현되며,
JAVA 웹 어플리케이션 개발의 핵심 기술 중 하나이다.

HTML Form 데이터 POST 전송 - 저장

POST Method + URL Mapping = (localhost:8080/api/members)

Postman JSON

{
	"id": "1",
	"name": "wonuk"
}

웹 브라우저가 생성한 요청 HTTP 메세지

POST /save HTTP/1.1
Host: localhost:8080
Content-Type: application/x-www-form-urlencoded

username=아이디&pssword=비밀번호

HTTP 응답 메세지

HTTP/1.1 200 OK
Content-Type: text/html;charset=UTF-8 <!-- JSON -->
Content-Length: 3423

{
	JSON...
}

OR

<html>
	<body>
		...
	</body>
</html>

Servlet이 없는 서버에서 처리해야하는 일

  1. 서버와 TCP/IP 연결, 소켓 연결
    1. 3 way handshake
  2. HTTP 요청 메세지 Parsing 후 READ
  3. POST method 식별 및 URL 분석
  4. Content-Type 확인
  5. HTTP Body Contents Parsing
  6. 저장 프로세스 실행
  7. 비지니스 로직 실행 → DB에 저장 요청
  8. HTTP 응답 메세지 생성
  9. TCP/IP 응답 전달, 소켓 연결 종료

Servlet을 지원하는 WAS를 사용한다면?

  • 다른것은 신경쓰지 않고 비지니스 로직만 신경쓰면 된다.
  1. 비지니스 로직 실행 → DB에 저장 요청

서블릿 예시코드

  • URL (/example)이 호출되면 Servlet 코드가 실행된다.
@WebServlet(name="ExampleServlet", urlPatterns = "/exmaple")
public class ExampleServlet extends HttpServlet { // HttpServlet을 상속받아 구현한다.
	
	@Override
	protected void service(
		HttpServletRequest request,  // HTTP 요청 정보를 쉽게 사용할 수 있게 만드는 Servlet
		HttpServletResponse response // HTTP 응답 정보를 쉽게 제공할 수 있게 만드는 Servlet
	) {
		// application logic
	}

}

Servlet 동작 순서

  1. WAS는 HTTP 요청 메세지를 기반으로 새로운 Request, Response 객체 생성
  2. WAS는 만들어진 Request, Response 객체를 서블릿 컨테이너에 넘겨주며 ExampleServlet 객체 호출
  3. WAS는 Response 객체 정보(개발자가 입력한 정보)로 HTTP 응답 메세지 생성

개발자가 하는일

  • Request 객체에 담겨져있는 HTTP 요청 정보를 꺼내서 사용한다.
    • 요청 정보(URL, Method, HTTP Message Body)를 통해
      필요한 기능(비지니스 로직)을 수행한다.
  • 생성된 Response 객체에 HTTP 응답 정보를 입력한다.

서블릿 컨테이너

💡 Servlet을 지원하는 WAS 내부에는 서블릿 컨테이너가 있다. Tomcat과 같이 Servlet을 지원하는 WAS를 서블릿 컨테이너라고 한다. 서블릿 컨테이너는 서블릿을 생성, 관리, 호출하는 역할을 수행한다.

서블릿의 생명주기

WAS가 종료될 때 Servlet도 함께 종료된다(서블릿 컨테이너가 관리)

Servlet 객체는 개발자가 직접 생성하는것이 아닌
코드만 작성하면 서블릿 컨테이너가 서블릿을 생성한다.

@WebServlet(name="Example2Servlet", urlPatterns = "/example2")
public class ExampleServlet extends HttpServlet { // HttpServlet을 상속받아 구현한다.
	
	@Override
	protected void service(
		HttpServletRequest request,  // HTTP 요청 정보를 쉽게 사용할 수 있게 만드는 Servlet
		HttpServletResponse response // HTTP 응답 정보를 쉽게 제공할 수 있게 만드는 Servlet
	) {
		// application logic
	}

}

@WebServlet(name="Example3Servlet", urlPatterns = "/example3")
// 코드

@WebServlet(name="Example4Servlet", urlPatterns = "/example4")
// 코드

서블릿 컨테이너가 하는일

  • Servlet 객체는 [**싱글톤]** 으로 관리된다.
    • 요청이 올때마다 계속 Servlet 객체를 생성하는 것은 효율적이지 않다.
      • 위 그림에서 ExampleServlet이 계속 새로 생성되는것이 맞나?를 생각해보자
    • 최초 로딩 시점에 Servlet 객체를 미리 만들어두고 재사용한다.
      • 같은 서버라면 모든 Request는 동일한 Servlet 객체 인스턴스에 접근한다.
      • 단, Request, Response 객체는 요청마다 새로 만들어지는것이 맞다.
    • 공유 변수 사용을 주의해야 한다.
      ex) 공유 변수에 로그인한 회원의 이름을 저장한다면? 다른 사람 이름이 보인다.
    • ex) 황원욱님 환영합니다. 홍정기님 환영합니다.
    • 서블릿 컨테이너 종료시 함께 종료된다.
  • 동시 요청을 위한 Multi Thread 처리를 지원한다.

Thread

💡 어플리케이션 코드를 하나하나 순차적으로 실행하는 것
  • Java에서 main method를 처음 실행하면 main 이라는 이름을 가진 Thread가 실행된다.
  • Thread는 한번에 하나의 코드 라인만 수행한다.(동시 X)
  • 동시처리가 필요하다면 Thread를 추가로 생성 해야한다.

  • 서블릿 객체는 누가 호출하는가?
    • Thread

단일 요청 - Single Thread

💡 스레드가 하나인 경우 어떻게 요청을 처리하는가?

  1. 클라이언트 요청 및 TCP/IP 연결
  2. Thread 할당 후 Servlet 호출
  3. 응답 후 Thread 반환

만약 Single Thread 환경에서 요청이 여러개 온다면?

  1. 첫번째 요청의 작업을 Single Thread가 수행중이다.
  2. 두번째, 세번째 요청이 들어오고 연결을 완료했다.
  3. Thread를 사용하기 위해 작업이 끝날때 까지 대기한다.
  4. 작업이 완료되면 Thread 대기 →
    Thread 할당 및 작업 수행 →
    Thread 반환 을 요청이 모두 사라질 때 까지 반복한다.
  • 만약, 첫번째 요청의 작업이 지연되거나 Error가 발생한다면?
    • 모든 요청이 Time out 오류가 발생한다.

요청마다 Thread를 새로 생성한다면?

  1. 요청이 들어올 때 마다 Thread를 생성한다.
  2. 요청 처리가 완료되면 Thread를 종료한다.
  • 장점
    • 동시 요청을 처리할 수 있다.
    • 리소스(Memory, CPU)가 허용하는 범위 안에서 처리가 가능하다.
    • 하나의 Thread가 지연되거나 이상이 발생하여도 나머지 Thread는 정상적으로 동작한다.
  • 단점
    • Thread는 생성 비용이 아주 비싸다.
      • 응답 속도가 늦어진다.
    • Thread는 Context Switching 비용이 발생한다.
    • Thread 생성에 제한이 없다.
      • 요청이 많이오면 리소스 부족으로 서버가 죽는다.
  • 멀티 태스킹의 진실과 Context Switching
    • CPU(프로세서)는 사실 한순간에 하나의 프로세스만 실행할 수 있다.

위 사진의 작업관리자에서 실행중인 작업은 동시에 수행하는것처럼 보이지만
사실 엄청나게 짧은 시간에 수십, 수천번 실행할 프로세스를 교체하고 있는것이다.

Context Switching

Task1에서 Task2로 Task2에서 Task1로 교체되는 시점마다
Task1이 Ready 상태로 돌아간다는 정보, 진행정보, Task2에서 어디부터 시작하면 되는지에 대한
정보들을 로딩할 시간이 필요하게 된다.
이 순간이 바로 Context Switching이다.

다중 요청 - Multi Thread

💡 WAS는 어떻게 동시 요청을 Multi Thread로 처리하는가?

Thread Pool 사용

Thread Pool 안에는 이미 생성된 Thread들이 있다.

  1. 요청이 들어오면 Thread Pool에서 Thread를 받아 사용한다.
  2. 사용 완료된 Thread는 Thread Pool에 반납한다.
  • Thread Pool의 Thread가 모두 사용중이라면?
    • Thread Pool에 Thread가 없으니 Thread가 생길 때 까지 대기하거나 거절한다.
    • 5시에 이벤트 치킨 뿌린다. 콘서트 예매 → 대기번호 5000번,

정리

  1. WAS는 Multi Thread를 지원한다.
    1. WAS의 주요 튜닝 포인트는 최대 Thread 수 이다.
    2. 개발자가 Multi Thread 관련 코드는 고려하지 않아도 된다.
    3. Multi Thread 환경이므로 싱글톤 객체(Servlet, Spring Bean)은 주의해서 사용해야한다.
      → 공유변수(멤버변수 사용 조심 또 조심!)
  2. Thread Pool
    1. Thread는 Thread Pool에 보관 및 관리한다.
    2. Thread Pool에 생성 가능한 Thread 최대치를 관리한다.
      Tomcat은 최대 200개 기본 설정이 되어있다.(변경 가능)

  3. 장점
    요청 마다 Thread를 생성하는 단점을 보완하였다.
    1. Thread가 미리 생성되어 있어서 Thread를 생성, 종료하는 비용이 절약된다. → 응답이 빠름
    2. 생성 가능한 Thread 최대치가 제한되어 있어서 많은 요청이 들어와도 안전하게 처리할 수 있다.
  4. 단점
    1. Thread Pool의 최대 Thread 수를 낮게 설정한다면?
      1. 응답이 지연된다.
    2. 최대 Thread 수가 너무 높으면?
      1. 요청이 많아지면 리소스 부족으로 서버가 죽는다.

Thread Pool의 최대 Thread 수를 설정하는 기준

  1. 로직의 복잡도, 리소스 상황에 따라 모두 다르다.
  2. 성능테스트를 통해 적정 Thread 수를 찾는다.
    1. JMeter, nGrinder, Apache ab와 같은 도구들을 사용한다.
    2. 실제 운영 서비스를 오픈하기 전에는
      실제와 유사한 환경에서 성능테스트를 거친 후 출시한다.

SSR, CSR

💡 서버사이드 렌더링, 클라이언트 사이드 렌더링은 무엇인가

SSR(Server Side Rendering)

  • 서버에서 동적으로 HTML을 만들어서 브라우저에 전달한다.

  • ex) JSP, Thymeleaf백엔드

  • 동작 흐름

  1. 서버에 HTML을 요청한다.
  2. 서버에서 로직을 거친 후 DB를 조회한다.
  3. 조회 결과를 기반으로 HTML을 동적으로 생성한다.
  4. 생성된 HTML을 응답한다.
  • Spring MVC 패턴에서의 SSR

  1. 요청이 오면 Controller에서 파라미터 정보 확인하여 비지니스 로직을 실행한다.
  2. 비지니스 로직의 결과 Data 를 Model에 담아서 View에 전달해준다.
  3. View는 모델의 Data를 참조하여 화면을 그려준다.

CSR(Client Side Rendering)

  • 웹 브라우저에서 자바스크립트를 사용해 동적으로 HTML을 생성해서 적용한다.

  • 웹을 모바일 앱 처럼 부분 부분 변경할 수 있다.

  • ex) Google Map, Gmail, Google Calendar

  • React, Vue.js → 프론트엔드 개발자

  • 동작흐름

  1. HTML을 요청한다. 비어있는 HTML을 응답받는다. JS가 존재하는 주소 링크를 응답한다.
  2. 자바스크립트(클라이언트 로직, 렌더링 포함)를 요청한다.
  3. HTTP API 요청을 하고 화면에 필요한 데이터를 JSON 형태(꼭 JSON이 아니어도됨)로 응답받는다.
  4. 응답받은 JSON 데이터로 HTML을 동적으로 그린다.

오늘의 코드카타

class Solution {

    public int solution(int[] array, int n) {
        int answer = 0;
        for (int i = 0; i < array.length; i++) {
            if (array[i] == n) {
                answer++;
            }
        }
        return answer;
    }
}

array 안에 n 의 갯수 카운트

profile
새로운 시작~!

0개의 댓글