![[스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술] 1. 웹 어플리케이션 이해](https://img1.daumcdn.net/thumb/R750x0/?scode=mtistory2&fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbdyaag%2FbtsDUfLGC9i%2F5cUSslMDR4G0EUt3SON5Vk%2Fimg.png)
인프런 김영한 강사님의 [스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술] 을 수강하고 정리한 글입니다.
스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 강의 - 인프런
웹 애플리케이션을 개발할 때 필요한 모든 웹 기술을 기초부터 이해하고, 완성할 수 있습니다. 스프링 MVC의 핵심 원리와 구조를 이해하고, 더 깊이있는 백엔드 개발자로 성장할 수 있습니다., 원
www.inflearn.com
📌 웹 서버, 웹 애플리케이션 서버
✅ 웹과 HTTP
기본적으로 웹은 HTTP 기반 하에 작동한다.
HTTP란,
웹 상에서 정보를 주고 받기 위한 규약으로, Html, Text, Image, 영상, 음성, Json, Xml, 파일 등 거의 모든 형태의 데이터를 전송 가능한 프로토콜이다.
✅ 웹 서버 (Web Server)
HTTP 기반으로 동작하는 웹 서버는 특히 정적 리소스 제공에 특화되어 있는 서버이다.
여기서 정적 리소스란, HTML, CSS, JS, 이미지, 영상 등이 있다.
대표적인 웹 서버로 Nginx, Apache 등이 있다.
✅ 웹 애플리케이션 서버(WAS, Web Application Server)
웹 애플리케이션 서버, WAS는 기본적으로 웹 서버의 역할인 정적 리소스 제공도 수행하지만, 특히 동적 리소스를 수행하는 역할에 특화되어 있는 서버다.
프로그램 코드를 직접 실행해서 애플리케이션의 로직을 수행한다.
여기서 동적 리소스란, HTTP API(Json), Servlet, JSP, Spring MVC 등이 있다.
WAS의 대표적인 예시로 Tomcat, Jetty, Undertow가 있다.
✅ 웹 시스템 구성
WAS는 동적, 정적 리소스를 모두 다룰 수 있는 만큼, WAS와 DB 둘 만으로 웹 시스템 구성이 가능하다.
그러나 문제는 WAS가 너무 많은 역할을 담당하게 되어 서버의 과부하가 우려된다는 점이다.
동적 리소스는 정적 리소스와 다르게, 많은 자원을 소모하는 비싼 로직인데, 이 비싼 로직이 정적 리소스 때문에 수행에 문제가 생기면 손해는 더욱 크다.
게다가 WAS에 장애가 발생하면, 해당 웹 시스템에서는 동적 리소스와 정적 리소스 모두 먹통이 되므로 우리가 흔히 볼 수 있는 오류 화면 페이지 조차도 보여줄 수 없어진다.
그렇기 때문에 Web Server와 WAS를 같이 사용하여 웹 시스템을 구축해야 한다.
같이 사용하게 되면, 정적 리소스는 Web Server가 담당하고 동적 리소스는 WAS가 담당한다.
이렇게 역할을 분리하게 되면 효율적인 리소스 관리가 이루어진다.
정적 리소스가 많이 사용될 때는 Web Server를 증설하고, 동적 리소스가 많이 사용될 때는 WAS를 증설하는 방식처럼 말이다.
게다가 보통 애플리케이션 로직이 동작하는 WAS가 Web Server에 비해 더욱 문제가 생길 일이 많은데, 이럴 때 Web Server를 통해 오류화면 페이지를 띄울 수 있는 것도 장점이다.
📌 서블릿
✅ 서블릿의 필요성
우리가 만약 이 웹 시스템의 중요한 부품이라고 할 수 있는 이 WAS를 직접 개발한다고 쳐보자.
어떻게 만들어야 할까?
위 사진에서 초록색 박스로 이루어진 부분이 우리가 흔히 SpringBoot를 활용하여 개발하는 부분이다.
그렇단 말은 초록색 박스 이외의 모든 과정과 기능들을 구현해야 한다는 뜻이다.
요청, 응답 메시지의 정보를 얻고 분석하고 이를 사용할 수 있게 파싱하며 저장/전송 하는 모든 로직을 구현해야 한다.
이것은 정말 쉽지 않을 것이다.
그래서 이러한 것들은 서블릿이라는 녀석이 도와준다.
✅ 서블릿 특징
@WebServlet(name = "helloServlet", urlPatterns = "/hello")
public class HelloServlet extends HttpServlet {
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) {
// 애플리케이션 로직
}
}
urlPatterns에 적혀 있는 /hello URL이 호출되면 서블릿이 실행된다.
HttpServletRequest은 HTTP 요청 정보를 편리하게 개발자가 사용할 수 있도록 도와주고,
HttpServletResponse는 HTTP 응답 정보를 개발자에게 편리하게 제공한다.
요청이나 응답 내용과 정보들을 개발자 대신해서 분석하고 파싱하여 객체 형태로서 개발하기 편리하도록 제공한다.
HTTP 요청이 만약 들어오면, 아래와 같은 흐름으로 서블릿은 작동한다.
1. WAS는 Request, Response 객체를 새로 만들어서 Servlet 객체를 호출한다.
2. 개발자는 Request 객체에서 HTTP 요청 정보를 편리하게 사용한다.
3. 개발자는 Response 객체에서 HTTP 응답 정보를 편리하게 입력한다.
4. WAS는 Response 객체에 담겨있는 내용을 활용해서 HTTP 응답 정보를 생성한다.
✅ 서블릿 컨테이너
서블릿 컨테이너란, 여러 WAS 들 중 Servlet을 지원하는 WAS를 말한다. 대표적인 예시로 SpringBoot 에서도 사용하는 Tomcat이 있다.
이 서블릿 컨테이너는 서블릿 객체를 생성/초기화/호출/종료 하는 등, 생명 주기를 관리한다.
특히 중요한 점이 서블릿 객체는 싱글톤으로 관리한다는 점이다.
요청이 올때마다 계속 서블릿 객체를 생성하는 것은 비효율적이기 때문에, 최초 로딩 시점에 서블릿 객체를 미리 만들어두고 재활용하는 방식을 사용한다.
이러한 방식 때문에 항상 공유 변수 사용 시에 주의가 필요하다.
그리고 또 중요한 점, Servlet Container는 동시 요청을 위한 멀티 쓰레드 처리를 지원한다.
📌 동시 요청 : 멀티 쓰레드
✅ 쓰레드
우리는 서블릿 컨테이너에 의해 서블릿의 생명주기가 관리된다고 배웠다.
더 자세히 말하면, 서블릿 컨테이너 내부의 쓰레드(Thread)가 서블릿을 호출한다.
쓰레드는 애플리케이션 코드를 하나씩 순차적으로 실행한다. 한번에 하나의 코드 라인만 수행한다.
그런데, 동시에 요청을 처리해야 한다면 한번에 하나씩만 수행하는 쓰레드를 추가로 생성해야 할 것이다.
✅ 멀티 쓰레드 : 요청 마다 쓰레드 생성
그래서 나온 방식이 매 요청마다 쓰레드를 생성하는 방식이였다.
장점
- 동시 요청을 처리할 수 있다.
- 특정 쓰레드가 지연되더라도 나머지 쓰레드는 정상 동작한다.
단점
- 쓰레드의 비용은 비싼데, 이를 요청마다 생성하면 응답 속도가 느려진다.
- 컨텍스트 스위칭 비용이 발생한다.
- 컨텍스트 스위칭 : 코어가 자신의 쓰레드 역할을 마치고 다른 쓰레드 역할로 넘어가는 것
- 쓰레드 생성에 제한이 없어서, 요청이 너무 많아 임계점을 넘어버리면 서버가 죽을 수 있다.
.✅ 쓰레드 풀
위에서 매 요청마다 쓰레드를 생성하는 방식의 단점들 때문에, 이를 보완하는 방법이 생겼다.
쓰레드 풀을 이용하는 방식이다.
쓰레드 풀은 말 그대로 쓰레드를 담아놓는 공간이다.
쓰레드를 설정한 개수만큼 미리 생성해서 쓰레드 풀에 담아놓고, 요청이 올때마다 쓰레드를 내어준다. 그리고 쓰레드를 다 사용하고 나면, 다시 쓰레드 풀에 반납한다.
결국 쓰레드 생성의 최대치를 관리한다는 뜻이다. (Tomcat의 기본 최대 쓰레드는 200개다.)
만약 최대 쓰레드만큼 이미 사용중이라면, 다음 요청부터는 거절하거나 특정 숫자만큼 대기시키도록 설정할 수 있다.
이는, 이전 방식에서 비용과 응답속도에 대한 문제를 해결한다.
결국 WAS의 주요 튜닝 포인트는 최대 쓰레드의 개수가 된다.
이 개수는 결국 상황마다 다르기 때문에 실제처럼 세팅한 성능 테스트로 확인할 수 밖에 없다. (성능 테스트 툴 : nGrinder, Apache ab, JMeter)
결국 WAS가 멀티쓰레드를 지원하기 때문에, 개발자는 멀티쓰레드에 대해 개발을 하지 않아도 되고, 그냥 몇개 설정만 건들이면 된다.
개발자는 싱글 쓰레드 프로그래밍을 하듯이 편리하게 개발할 수 있다.
대신 멀티쓰레드 환경이므로 싱글톤 객체는 주의해서 사용해야 한다.
📌 HTML, HTTP API, CSR, SSR
✅ 정적 리소스
정적 리소스는 이처럼 미리 생성해둔 리소스 파일을 그냥 클라이언트에 제공한다.
정적 리소스에는 고정된 HTML 파일, CSS 파일, 이미지, 영상 등이 있다.
✅ HTML 페이지
그런데 대부분의 웹 페이지는 동적이다.
그렇기 때문에 동적으로 필요한 HTML 파일을 생성해서 웹 브라우저에 전달하고, 브라우저는 이를 해석한다.
이때 HTML을 동적으로 생성하는 것들의 종류에 흔히 SSR(Server Side Rendering)이라고 불리는 JSP, 타임리프 등이 있다.
✅ HTTP API
그런데 HTML 화면을 제공하는 것이 아니라, 그냥 데이터만 전달하는 방식이 있다. 이를 API라고 한다.
주로 JSON 형식을 사용한다.
이처럼 서버는 데이터만 제공하고, 웹 브라우저 (클라이언트) 측에서 자유롭게 이를 활용한다. UI 화면이 필요하면 클라이언트가 직접 생성한다.
이 방식의 장점은, 서버는 데이터만 제공하기 때문에 다양한 클라이언트와 연결할 수 있다는 점이다.
✅ SSR, CSR
서버 사이드 렌더링 (SSR, Server Side Rendering)
- HTML 최종 결과를 서버가 직접 만들어서 웹 브라우저에 제공하고, 브라우저는 이를 띄우기만 한다.
- 보통 정적인 화면에서 사용한다.
- JSP, 타임리프
클라이언트 사이드 렌더링 (CSR, Client Side Rendering)
- HTML 결과를 JS 등을 통해 웹 브라우저가 동적으로 생성해서 적용한다.
- 주로 동적인 화면에서 사용한다.
- React, Vue.js
'Backend > Spring' 카테고리의 다른 글
동시성 문제를 해결하는 여러가지 방법 (1) | 2024.06.04 |
---|---|
[스프링 핵심 원리 - 기본편] 9. 빈 스코프 (0) | 2024.01.02 |
[스프링 핵심 원리 - 기본편] 8. 빈 생명주기 콜백 (0) | 2024.01.02 |
[스프링 핵심 원리 - 기본편] 7. 의존관계 자동 주입 (1) | 2024.01.02 |
[스프링 핵심 원리 - 기본편] 6. 컴포넌트 스캔 (0) | 2024.01.02 |
개발자가 되고 싶어요.