1. 웹 서버, 웹 어플리케이션 서버
웹이라는 것은 모두 http를 기반으로 통신한다. 예를 들어, 웹 브라우저에서 url을 치면 인터넷을 통해 서버에 접근하고 서버에서는 html을 만들어서 클라이언트에 내려준다. 그럼 웹 브라우저가 받은 html을 통해 눈 앞에 보여줄 것이다. 그런데 클라이언트에서 서버로 데이터를 전송할때, 서버에서 클라이언트로 데이터를 응답할 때 이때 다 http라는 프로토콜을 기반으로 다 동작하게 된다. 그래서 모든 것이 웹 세상에서는 http를 기반으로 데이터를 주고 받는다. 우리가 일반적으로 아는 html 텍스트, 이미지, 음성, 영상파일 그리고 요즘 api를 사용할 때 주로 사용하는 json, xml도 그렇다. 그래서 거의 모든 형태의 데이터는 최근에는 다 http 프로토콜 기반으로 주고 받는다. 심지어 서버 간에 데이터를 주고 받을 때에도 http를 사용한다. 그래서 지금은 바야흐로 http의 시대인 것이다.
(1) Web Server
그러면 이 웹 서버라는 것이 뭐고, 뒤에 나오는 웹 어플리케이션 서버가 뭔지 정리해보자. 웹 서버라는 것은 우선 http를 기반으로 동작하는 서버다. 그리고 정적 리소스를 제공하고, 기타 부가 기능을 제공한다. 정적 리소스란 특정 폴더, 디렉토리에다가 html, css, js, 이미지, 영상같은 파일들을 두면 이 서버들이 파일들을 그냥 서빙해주는 것이다. 즉, http를 통해 이 html을 달라고 요청하면 이것을 http 프로토콜로 응답을 준다. 그러니까 http 프로토콜로 서로 데이터를 주고받을 수 있는, 그리고 정적 데이터로 데이터를 주고받을 수 있는, 정적 데이터를 제공하는 서버를 웹 서버라고 한다. 대표적으로 NGINX와 APACHE가 있다.
(2) WAS - Web Application Server
그 다음 웹 어플리케이션 서버라는 것이 있다. 이 친구도 http를 기반으로 동작한다. 또한 앞서 말했던 웹 서버의 기능을 대부분 포함하고 있다. 특히 이런 정적 리소스를 제공하는 기능을 전부 포함하고 있다. 그리고 큰 차이는 프로그램 코드를 실행해서 어플리케이션 로직을 수행할 수 있다는 점이다. 방금 웹서버는 정적 파일을 들고 서빙을 하기 때문에 html을 특정 사용자마다 다르게 보여주거나 이런 것을 할 수가 없다. 근데 웹 어플리케이션 서버 was는 http 요청이 오면 사용자에 따라서 그 사용자 이름도 보여줄 수 있고, 다른 화면도 보여줄 수 있다. 왜냐하면 프로그래밍을 할 수 있기 때문이다. 그래서 프로그램 코드를 실행하여 이 어플리케이션 로직을 수행할 수 있는 것이 이 웹 어플리케이션 서버의 특징이다. 그래서 동적인 html을 생성할 수 있고, HTTP API (Rest API)같은 것들도 was를 통해 제공된다. 그리고 서블릿, jsp, 스프링 mvc 같은 것들도 이 was에서 동작하게 된다. 대표적으로 tomcat, jetty, undertow 같은 서버가 있다.
(3) 웹 서버, 웹 어플리케이션 서버 차이
간단하게 정리하면 웹 서버는 정적 리소스를 제공을 하는 것이고, was는 어플리케이션 로직까지 실행할 수 있다. 근데 사실 둘의 용어 경계도 좀 모호하다. 웹이니까 http 기반의 웹을 주고 받을 수 있는 서버라고 넓게 볼 수 있다. 그래서 웹 서버도 사실은 프로그램을 실행하는 기능을 포함하기도 한다. 그리고 웹 어플리케이션 서버도 웹 서버의 기능들을 제공한다. 그래서 뭘로 구분하는 지 궁금할 수도 있다. 자바에서는 보통 서블릿 컨테이너를 제공하면 WAS라고 한다. 근데 이것도 조금 모호한게 서블릿 없이 자바코드를 실행하는 서버 프레임워크도 있다. 그래서 그냥 was는 어플리케이션 코드를 실행하는데 더 특화되어 있다고 보면 된다. 그리고 크게는 웹 서버는 정적 리소스, was는 어플리케이션 로직을 실행하는 서버라고 보면 된다.
(4) 웹 시스템 구성 - was, db
실제 시스템을 구성해야 한다면 가장 간단하게는 was와 db로 구성할 수 있다. 최소한으로 봤을 때 이 두 개로 구현할 수 있다. was는 정적 리소스, 어플리케이션 로직 모두 제공할 수 있다. 그래서 클라이언트 요청이 오면 여기서 어플리케이션 로직을 수행할수도 있고, html, css, js, 이미지같은 것도 다 제공할 수 있다. 그리고 이 어플리케이션 로직에서 데이터베이스 조회해서 필요한 html을 동적으로 만들어낼수도 있다. 그런데 이렇게 was가 너무 많은 일을 담당한다. 그래서 was 하나만 가지고 운영을 한다면 was가 너무 많은 역할을 담당하여 서버 과부하가 될 수 있다. 그리고 가장 중요한 점이 html, css, js, 이미지 같은 것은 사실 값이 굉장히 싸다. 시스템 적으로 보면 파일 하나를 놔두고 그거를 잘 서빙하면 되므로 굉장히 단순하다. 하지만 어플리케이션 로직은 굉장히 비싸다. 이런 값 비싼 비지니스 로직이 정적 리소스 때문에 수행이 어려우면 안된다. 그리고 또 다른 문제가 was가 생각보다 잘 죽는다. 그런데 was 장애시 웹 브라우저에서 was에 접근하고 싶은데 접근조차 안된다. 이때 오류 화면조차도 노출이 불가능해진다. 그래서 이런 was만 가지고 큰 시스템을 구축하는데 부담이 있다.
(5) 웹 시스템 구성 - web, was, db
그래서 일반적으로 위와 같은 구성을 많이 한다. 먼저 정적 리소스를 앞에 둔다. 즉, 웹 서버를 앞에 두고 여기서 정적 리소스를 다 처리한다. html, css, js, 이미지는 여기서 다 처리된다. 이후 "이거는 동적인 것이 필요한 로직이네?"라고 하면 was에 넘긴다. 그리고 db에서 데이터를 가져와서 결과를 다시 웹 서버에 전달하고 웹 서버에서 클라이언트로 결과를 전달한다. 이렇게 되면 was는 굉장히 중요한 어플리케이션 로직을 전담할 수 있다는 장점이 있다. 그리고 웹 서버는 단순한 정적 리소스들만 담당하고, 필요하면 was를 호출하면서 업무를 분담할 수 있다.
이렇게 구성하면 좋은 다른 장점은 시스템 리소스를 굉장히 효율적으로 쓸 수 있다. 예를 들어, 정적 리소스가 많이 필요하면 web 서버만 증가시키면된다. 만약 정적 리소스에 비해 어플리케이션 로직만 많이 호출된다면 거기에 맞게 was 서버를 늘리면된다. 또한 정적 리소스만 제공하는 웹 서버는 단순한 작업을 주로 처리하기 때문에 잘 죽지 않는다. 하지만 어플리케이션 로직을 동작시키는 was 서버는 잘 죽는다. 따라서 was, db에서 장애가 발생해도 웹 서버를 통해 오류 화면 제공이 가능하다.
2. 서블릿
만약 회원 이름과 나이를 넣고 전송 버튼을 누르면 회원이 가입되는 form이 있다고 하자. 이때 이름과 나이를 입력하여 서버로 보내면 post 요청을 보낸다. 이때 웹 브라우저는 POST Http 메시지를 서버에 보낸다. 그럼 웹 서버는 해당 메시지를 풀어서 해석해야 한다. 이때 Http 메시지는 단순한 텍스트이기 때문에 잘라서 읽으면 된다. 이때 HTTP 요청 메시지가 다음과 같다고 하자.
POST /save HTTP/1.1
Host: localhost:8080
Content-Type: application/x-www-form-urlencoded
username=kim&age=20
서버는 먼저 TCP/IP 연결을 대기하고 소켓을 연결한다. 그리고 위와 같은 요청 메시지를 파싱해서 읽는다. 이때 메시지가 POST요청이며, /save URL을 인지한다. 그리고 Content-Type을 읽고 content-type에 따라 body의 내용을 파싱해서 읽는다. 그러면 /save가 있으니까 저장 프로세스를 실행해야 한다고 생각할 것이다. 따라서 저장에 대한 비지니스 로직을 수행하고 데이터베이스에 저장 요청을 할 것이다. 그리고 저장이 잘 되었는지 html 결과를 웹 브라우저한테 전달해야 한다. 그래서 http 응답 메시지를 직접 생성해야 한다. 이때 메시지는 다음과 같이 생성되었다고 하자.
HTTP/1.1 200 OK
Content-Type: text/html;charset=UTF-8
Content-Length: 3423
<html>
<body>...</body>
</html>
이와 같이 메시지를 만들면 서버는 TCP/IP에 응답을 전달하고 소켓을 종료한다. 근데 이 과정을 보면 비지니스 로직은 회원 이름과 나이를 가지고 데이터베이스에 저장하는 것이 끝이다. 그런데 그 전 단계가 너무 많다. 근데 세계 개발자가 이걸 똑같이 개발하고 있기에는 너무 비효율적이다. 그래서 "서블릿"이 나온다. 서블릿은 이러한 비지니스 로직을 제외한 모든 로직을 담당한다. 보통 서블릿을 지원하는 WAS들이 서버 TCP/IP 대기, 소켓 연결, 메시지 파싱, 저장 프로세스 실행, http 응답 메시지 생성까지 다 자동화 한다.
서블릿은 아래와 같이 생겼다. 아래는 최신 스타일의 서블릿이다.
@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 스펙을 편리하게 사용할 수 있음. 단, HTTP 스펙을 어느정도 알아야 한다. 기본적으로 알아야 request에서 꺼낼때 HTTP 스펙에서 뭐가 꺼내지는구나, response에 write할 때 HTTP 스펙에 이렇게 나가겠구나를 상상할 수 있어야 한다. 따라서 기본적인 HTTP 스펙은 인지하도록 하자.
전체 과정을 아래 그림을 통해 살펴보자.
- 우리 서버가 localhost라 할 때, "localhost:8080/hello"라고 요청했다고 하자.
- was 서버에서는 요청 메시지를 기반으로 request, response 객체를 새로 만든다.
- 이후 서블릿 컨테이너에 있는 (우리가 만든) helloServlet을 실행한다. 이때 방금 만든 request, response객체를 파라미터로 넘겨준다.
- helloServlet이 끝나고 return을 하면 우리가 만든 response객체를 바탕으로 http 응답 메시지를 만든다.
- 그리고 웹 브라우저에 응답 메시지가 전달된다.
정리를 하면 다음과 같다. HTTP 요청시 WAS는 request, response 객체를 새로 만들어 서블릿 객체를 호출한다. 개발자는 request 객체에서 http 요청 정보를 꺼내서 사용하면 된다. 또 response 객체에 http 응답 정보를 편리하게 입력하면 된다. 그러면 WAS는 response 객체에 담겨있는 내용으로 HTTP 응답 정보를 생성하여 웹브라우저에 전송한다. 그럼 HTTP가 그 html을 랜더링해서 이쁘게 보여준다.
그러면 서블릿 컨테이너는 뭘까? 이전에 봤던 HelloServlet과 같은 서블릿 객체는 내가 직접 생성하지 않는다. 나는 그냥 이 코드만 작성하면된다. WAS에는 서블릿 컨테이너라는 것이 있는데 여기 안에서 서블릿 객체를 자동으로 생성한다. 그리고 방금처럼 요청이 들어오면 자동으로 호출도 해준다. 특징은 다음과 같다.
- 톰캣처럼 서블릿을 지원하는 WAS를 서블릿 컨테이너라고 한다.
- 서블릿 컨테이너는 서블릿 객체를 생성, 초기화, 호출, 종료하는 생명주기를 관리한다.
- 서블릿 객체는 싱글톤으로 관리된다.
- 최초 로딩 시점에서 서블릿 객체를 미리 만들어두고 재활용한다.
- 모든 고객 요청은 동일한 서블릿 객체 인스턴스에 접근한다.
- 공유 변수 사용을 주의해야 한다.
- 서블릿 컨테이너 종료시 함께 종료된다.
- JSP도 서블릿으로 변환 되어서 사용된다.
- 동시 요청을 위한 멀티 쓰레드 처리를 지원한다.
3. 동시 요청 - 멀티 쓰레드
웹 브라우저든 어떤 클라이언트든 서버에 요청하면 was에서는 응답을 할 것이다. 단, 요청시 tcp/ip 커넥션 연결이 된다. 그리고 servlet이라는 것을 호출한다. 그런데 이 서블릿을 누가 호출할까? 바로 쓰레드다. 쓰레드란 어플리케이션 코드를 하나하나 순차적으로 실행하는 것이다. 예를 들어, 자바 메인 메서드를 처음 실행하면 main이라는 이름의 쓰레드가 실행된다. 그래서 이 쓰레드가 없으면 자바 어플리케이션 자체가 실행이 안된다. 실행 시켜주는 애가 없는 것이다. 쓰레드는 한 번에 하나의 코드 라인만 수행할 수 있다. 따라서 만약 동시 처리가 필요하다면 쓰레드를 추가로 생성해야한다.
만약 쓰레드가 하나만 있다고 가정하자. 그러다가 요청이 하나 오면 WAS에서는 쓰레드를 할당한다. 그리고 이 쓰레드를 가지고 servlet 코드를 실행한다. 그리고 나서 이 쓰레드를 가지고 응답을 하고, 응답이 되고나면, 쓰레드가 휴식을 한다. 근데 다중 요청이 들어온다고하자. 요청1이 들어오면 쓰레드를 사용해 요청을 처리하게 된다. 근데 처리가 지연되어 버리면 요청2가 들어왔을 때 해당 쓰레드를 사용해야 하는데 쓰레드가 사용중이므로 기다려야한다. 이러면 요청1도 처리가 안되는데 요청2도 처리가 안되는 문제가 발생한다.
이를 해결하려면 단순히 쓰레드 하나를 생성하면 된다. 즉, 요청이 올 때마다 새로운 쓰레드를 하나만드는 것이다. 그런데 요청이 올 때마다 쓰레드를 생성하면 아래와 같은 장단점이 있다.
- 장점
- 동시 요청을 처리할 수 있다.
- 리소스(CPU, 메모리)가 허용할 때까지 처리가 가능하다.
- 하나의 쓰레드가 지연 되어도, 나머지 쓰레드는 정상 동작 된다.
- 단점
- 쓰레드는 생성 비용이 비싸다.
- 고객 요청이 올 때마다 쓰레드를 생성하면 응답 속도가 느려진다.
- 쓰레드는 컨텍스트 스위칭 비용이 발생한다.
- 쓰레드 생성에 제한이 없다.
- 고객 요청이 너무 많이 오면, CPU, 메모리 임계점을 넘어서 서버가 죽을 수 있다.
- 쓰레드는 생성 비용이 비싸다.
그래서 보통 WAS들은 내부에 "쓰레드 풀"이라는 것을 사용한다. 먼저 요청1, 요청2가 온다. 그럼 쓰레드 풀에 쓰레드를 요청을 한다. 만약 쓰레드 풀에 있는 쓰레드가 200개라면 해당 쓰레드 중 놀고있는 친구를 할당해준다. 즉, 만약 200개 모두 놀고있었다면 2개는 주어졌으니 198개가 남는 것이다. 이후 2개의 쓰레드가 모두 할 일을 마치면 쓰레드를 죽이는 것이 아니라 다시 쓰레드 풀에 반납한다. 그러면 다시 쓰레드 풀에는 200개가 다시 차게 된다. 이렇게 쓰레드를 죽이고, 생성하는 과정을 반복하는 것이 아니라 풀 안에 만들어서 넣어놓고, 빌려쓰고, 반납하는 식으로 동작한다. 이렇게 구현한 경우 이미 200개의 쓰레드가 사용 중일 때 이후에 들어오는 요청은 쓰레드 풀에 쓰레드가 없으므로 대기하거나, 거절할 수 있다. 쓰레드 풀을정리를 하면 다음과 같다.
- 특징
- 필요한 쓰레드를 쓰레드 풀에 보관하고 관리한다.
- 쓰레드 풀에 생성 가능한 쓰레드의 최대치를 관리한다. (톰캣은 최대 200개가 디폴트다.)
- 사용
- 쓰레드가 필요하면, 이미 생성되어 있는 쓰레드를 쓰레드 풀에서 꺼내서 사용한다.
- 사용을 종료하면 쓰레드 풀에 해당 쓰레드를 반납한다.
- 최대 쓰레드가 모두 사용중이어서 쓰레드 풀에 쓰레드가 없다면 기다리는 요청은 거절하거나, 특정 숫자만큼만 대기하도록 할 수 있다.
- 장점
- 쓰레드가 미리 생성되어 있으므로, 쓰레드를 생성하고 종료하는 비용이 절약되며 응답 시간이 빠르다.
- 생성 가능한 쓰레드의 최대치가 있으므로 너무 많은 요청이 들어와도 기존 요청은 안전하게 처리할 수 있다.
쓰레드 풀의 적정 숫자는 어플리케이션 로직의 복잡도, CPU, 메모리, IO 리소스 상황에 따라 모두 다르다. 따라서 성능 테스트를 해봐야한다. 툴로는 아파치 ab, 제이미터, nGrinder 등이 있다. 어쨋든 정리하면 핵심은 다음과 같다.
- 멀티 쓰레드에 대한 부분은 WAS가 처리한다.
- 개발자가 멀티 쓰레드 관련 코드를 신경쓰지 않아도 된다.
- 개발자는 싱글 쓰레드 프로그래밍을 하듯이 편리하게 소스 코드를 개발할 수 있다.
- 멀티 쓰레드 환경이므로 싱글톤 객체(서블릿, 스프링 빈)는 주의해서 사용해야한다. 특히 공유 변수 사용을 주의해야 한다.
4. HTML, HTTP API, CSR, SSR
정적 리소스를 제공할 때는 보통 고정된 HTML 파일이나, CSS, JS, 이미지 영상 등을 제공하면 된다. 그래서 요청이 들어왔을 때, 웹 서버에서 이미 생성된 파일들을 제공한다. 그리고, HTML 페이지인데 동적인 HTML 페이지를 요청할 수도 있다. 예를 들어, 주문 내역을 보여달라고 하면 WAS가 데이터베이스에서 필요한 데이터를 조회하고, 이것을 동적으로 HTML 생성하게 된다. 이때 JSP나 타임리프를 활용한다. 이렇게 생성된 HTML 페이지는 브라우저에서 해석하여 알맞은 화면을 출력한다. 그리고 HTTP API라는 것이 있다. HTML을 전달하는 것이 아니라 데이터를 전달하는 것이다. 주로 JSON 형식을 사용한다. 이런 HTTP API는 그냥 데이터이기 때문에 웹 브라우저에서만 사용하는 것이 아니라 다양한 시스템들에서 사용한다. HTTP API는 보통 3가지 상황에서 사용된다.
- 앱 개발자(아이폰, 안드로이드)가 UI 화면을 구성할 때, 데이터가 필요하다. 이런 경우 앱 클라이언트와 서버간에 HTTP API를 사용한다.
- 웹 브라우저에서 HTML 랜더링을 위해 자바스크립트가 데이터를 요청하면 필요한 데이터를 HTTP API를 통해 가져온다. 즉, 웹 브라우저와 서버간에 통신이 이루어진다.
- 주문 서버와 결제 서버가 통신을 해야하면 서로 html을 주고 받을 필요없이 데이터만 주고 받으면 된다. 따라서 이런 경우도 HTTP 프로토콜 위에 JSON 데이터로 데이터를 주고받거나 한다. 즉, 서버와 서버간에 통신이 이루어진다.
결론적으로 백엔드 개발자가 서비스를 제공할 때 고민해야하는 포인트는 아래 3가지이다.
- 정적 리소스를 어떻게 제공할 것인가?
- 동적으로 제공되는 html 페이지는 어떻게 제공할 것인가?
- HTTP API를 어떻게 제공할 것인가?
HTTP를 통해 데이터를 주고 받을 때 이 세 가지에 대해서만 고민하면 된다. 그리고 서버사이드 렌더링과 클라이언트 사이드 렌더링 개념이 있다. 먼저 서버 사이드 렌더링을 살펴보자.
- 웹 브라우저에서 주문 내역을 달라고 요청한다.
- 그럼 서버는 주문 DB를 조회해서 HTML을 동적으로 생성한다.
- 이와 같이 SSR(서버 사이드 렌더링)은 최종 HTML을 서버에서 생성하여 클라이언트에 전달하는 것이다. 따라서 웹 브라우저는 단순히 완전히 생성된 것을 보여주기만 한다. 주로 정적 화면에 많이 사용한다.
클라이언트 사이드 렌더링은 HTML 결과를 처음부터 바로 얻는 것이 아니다. 자바스크립트를 사용해서 웹 브라우저에서 동적으로 HTML을 생성하는 것이다. 그래서 주로 동적인 화면에서 많이 사용된다. 즉, 예전에는 백엔드에서 동적으로 HTML을 생성했지만 자바스크립트에서 HTML을 동적으로 생성하는 것이다. 이것을 클라이언트 쪽에서 HTML 모양을 만든다고 하여 클라이언트 사이드 랜더링이라고 한다. CSR(클라이언트 사이드 랜더링)은 주로 동적인 화면에 이용하며 웹 환경을 마치 앱처럼 필요한 부분부분 변경이 가능하다.
- 백엔드는 JSP는 거의 사장되었고, 타임리프를 사용하여 서버 사이드 렌더링 기술을 배우는 것을 권장한다. 백엔드 개발자에게 서버 사이드 렌더링 기술 학습은 필수다. 화면이 정적이고 복잡하지 않을 때 사용하므로 꼭 배워두자.
- 클라이언트 사이드 렌더링 기술은 웹 프론트 담당으로 React와 Vue.js를 주로 활용한다. 복잡하고 동적인 UI를 사용하며 프론트앤드 개발자의 전문 분야다.
- 백엔드 개발자의 웹 프론트엔드 기술 학습은 옵션이다. 백엔드 개발자는 서버, DB, 인프라 등등 수 많은 백엔드 기술을 공부해야하기 때문에 부담이다. 또한 프론트엔드도 깊이있게 하려면 오랜 시간이 걸린다. 따라서 선택과 집중이 필요하다.
5. 자바 백엔드 웹 기술 역사
- 서블릿 - 1997
- 자바 코드로 짜야하므로, HTML 동적 생성이 어려움
- JSP - 1999
- HTML 화면도 편하게 작성할 수 있고, 자바 코드도 편하게 작성할 수 있음.
- HTML 생성은 편리하지만, 비즈니스 로직까지 너무 많은 역할을 담당함. 그래서 JSP 하나에 코드가 수천줄이고, 유지보수가 힘들어짐.
- 서블릿, JSP 조합 MVC 패턴 사용
- 서블릿과 JSP를 조합해 MVC 패턴이라는 것이 나옴.
- model, view, controller로 역할을 나누어 개발하는 패턴임. 즉, 화면 관련은 view, 비지니스 로직은 java 코드나 서블릿을 고치는 등 좀 더 편한 작업이 가능했다.
- MVC 프레임워크 춘추 전국 시대 - 2000년 초 ~ 2010년 초
- MVC를 다들 사용하니까 MVC 프레임워크를 개발하기 시작함.
- MVC 패턴 자동화, 복잡한 웹 기술을 편리하게 사용할 수 있는 다양한 기능을 지원함.
- 스트럿츠, 웹워크, 스프링 MVC 등이 해당됨. 이 당시 스트럿츠와 스프링을 조합하여 많이 사용함.
- 어노테이션 기반의 스프링 MVC 등장
- @Controller와 같이 어노테이션 기반의 스프링 MVC가 등장하여 MVC 프레임워크를 모두 통일해버림.
- 어노테이션 기반이기 때문에 굉장히 유연하고, 편리했으며 코드도 깔끔하여 전국 통일이 됨.
- 스프링 부트 등장
- 스프링 부트는 서버를 내장함.
- 과거에는 서버에 WAS를 직접 설치하고, 소스는 War 파일을 만들어 설치한 WAS에 배포함.
- 스프링 부트는 빌드 결과(Jar)에 WAS 서버를 포함하여 빌드 배포가 단순함. 이 기능 때문에 신규 프로젝트는 거의 다 스프링 부트를 사용함.
현재는 어노테이션 기반의 스프링 MVC와 스프링 부트를 많이 사용한다. 이때 스프링 웹 기술이 두 가지로 분할된다.
- Web Servlet - Spring MVC
- 서블릿을 기반으로 함.
- 멀티 쓰레드를 해결할 수 있는 장점을 가짐.
- 우리가 일반적으로 사용함.
- Web Reactive - Spring WebFlux
- 최신 기술임.
- 비동기 넌 블러킹 처리함.
- 최소 쓰레드로 최대 성능을 냄. CPU 코어가 4개가 있다고 하면, 쓰레드 개수를 코어나, 코어+1 정도로 맞춤. 그래서 컨텍스트 스위칭 비용이 거의 들지 않음.
- 함수형 스타일로 개발함. 따라서 동시처리 코드가 효율적임. API를 여러 개를 사용하여 정보를 긁어와야 한다면 자바 코드보다 함수형 스타일이 좀 더 좋음.
- 서블릿 기술을 사용하지 않음.
- 단, WebFlux는 기술적 난이도가 너무 높음. 또한 RDB(관계형 데이터베이스) 지원이 부족함. 일반 MVC의 쓰레드 모델도 충분히 빠르기 때문에 실무에서는 많이 사용하지 않음.
그리고 View 템플릿의 역사는 다음과 같다. 이때 뷰 템플릿이란 HTML을 편리하게 생성하는 뷰 기능을 말한다.
- JSP
- 속도가 느리며, 기능이 부족하다.
- 최근 스프링 부트는 JSP를 권장하지 않는다.
- 프리마커(Freemarker), 벨로시티(Velocity)
- 속도가 빠르면 다양한 기능을 제공함. 하지만 시간이 지나도 발전을 안 했다.
- 타임리프(Thymeleaf)
- 내추럴 템플릿이라고 HTML의 모양을 유지하면서 뷰 템플릿을 적용할 수 있다. JSP나 프리마커, 벨로시티는 조건문과 같은 코드가 들어가서 HTML을 열어도 JSP 코드가 다 보이고 그렇다. 하지만 타임리프는 HTML 속성같은 곳에 태그를 넣어 문제를 해결하기 때문에 HTML 모양을 유지하면서 뷰 템플릿 적용이 가능한 것이다.
- 스프링 MVC와 강력한 기능 통합을 제공한다.
- 따라서 새로 공부한다고 한다면 최선의 선택은 타임리프다. 단, 성능은 프리마터나 벨로시티가 더 빠르다. 하지만 왠만한 성능으로는 거의 이슈가 되지 않는다.
출처: https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-mvc-1/dashboard
'BackEnd > Spring' 카테고리의 다른 글
[Spring MVC-1] 서블릿, JSP, MVC 패턴 (0) | 2023.09.12 |
---|---|
[Spring MVC-1] 서블릿 (0) | 2023.09.09 |
[Spring] 빈 스코프 (0) | 2023.09.02 |
[Spring] 빈 생명주기 콜백 (0) | 2023.08.31 |
[Spring] 의존관계 자동 주입 + lombok 설정 (0) | 2023.08.30 |