ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Understanding Web Applications
    Java/Spring 2025. 1. 14. 16:51

    웹 애플리케이션에 대한 기본 구성요소와 개념 등에 대해 정리하였습니다.

     

     


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

    [ HTTP ]

    웹은 주로 HTTP 프로토콜을 기반으로 통신합니다.

    웹 브라우저 클라이언트가 URI를 통해 서버에 페이지를 요청하면, 서버는 해당 페이지를 생성하여 클라이언트에게 제공합니다. 이 과정에서 클라이언트와 서버 간의 모든 데이터 전송은 HTTP 프로토콜을 통해 이루어집니다.

     

    HTTP는 HTML, 텍스트, 이미지, 음성, 영상 파일, JSON, XML(API) 등 거의 모든 형태의 데이터를 전송할 수 있으며, 서버 간의 데이터 전송에도 주로 사용됩니다. 이러한 이유로 현재는 HTTP의 시대라고 말할 수 있습니다.

     

     


    [ 웹 서버(Web Server) ]

    웹 서버는 HTTP 프로토콜을 기반으로 동작하며, 정적 리소스인 HTML, CSS, JavaScript, 이미지, 영상 파일 등을 클라이언트에게 제공합니다. 또한, 웹 서버는 부가적으로 로드 밸런싱, 리버스 프록시, SSL/TLS 암호화 지원 등 다양한 기능을 제공합니다.

     

    대표적인 웹 서버로는 NGINXApache가 있습니다.

     

     


    [ 웹 애플리케이션 서버(WAS; Web Application Server) ]

    웹 애플리케이션 서버(WAS)는 HTTP 프로토콜을 기반으로 동작하며, 일반적인 웹 서버의 기능을 포함하고 있습니다.

    웹 서버와의 주요 차이점은 프로그램 코드를 실행하여 애플리케이션 로직을 처리할 수 있다는 것입니다. 이를 통해 동적 HTML 생성, HTTP API(JSON) 제공, 서블릿, JSP, 스프링 MVC 등의 기능을 수행할 수 있습니다.

     

    대표적인 웹 애플리케이션 서버로는 Apache Tomcat, Jetty, Undertow 등이 있습니다.

     

    < 웹 서버와 웹 애플리케이션 서버(WAS)의 차이 >
    웹 서버와 웹 애플리케이션 서버(WAS)의 구분은 다소 모호할 수 있습니다. 웹 서버도 때때로 프로그램 실행 기능을 포함하며, WAS도 웹 서버의 기능을 제공하기 때문입니다.

    프로그래밍 언어에 따라 구분 기준이 다르기도 한데, 예를 들어 자바에서는 일반적으로 서블릿 컨테이너 기능을 제공하면 WAS로 분류됩니다. 그러나 최근에는 서블릿 없이 자바 코드를 실행하는 서버 프레임워크도 존재하므로, 이 또한 명확한 기준은 아닙니다.

    따라서 웹 서버는 정적 리소스 제공에 특화되어 있고, WAS는 애플리케이션 로직 수행에 특화되어 있다고 이해하는 것이 일반적입니다.

     

     


    웹 시스템 구성 ]

    웹 시스템을 구성할 때 사용할 수 있는 가장 간단한 구성은 WAS와 DB만으로 구성하는 것입니다. WAS는 정적 리소스, 애플리케이션 로직 모두 제공이 가능하기 때문입니다.

     

    이러한 구성을 사용할 경우 WAS에 너무 많은 역할이 집중되면서 과부하가 발생할 우려가 있습니다. 또한, 가장 중요한 애플리케이션 로직이 정적 리소스 처리로 인해 지연되거나 어려워질 수 있습니다. 만약 WAS에 장애가 발생할 경우에는 오류 화면조차 표시할 수 없기 때문에, 위와 같은 구성이 작은 시스템에서는 충분히 커버될 수 있지만, 규모가 큰 시스템에서는 WAS만 사용하는 것이 적절하지 않을 수 있습니다.

     

    따라서 일반적으로는 정적 리소스는 웹 서버가 처리하고, 애플리케이션 로직과 같이 동적 처리가 필요한 경우에만 WAS에 요청을 위임하는 방식을 많이 사용합니다. 이렇게 하면 WAS는 비교적 중요한 애플리케이션 로직 처리에만 집중할 수 있게 됩니다.

     

    위와 같이 구성하면 웹 서버와 WAS 각각의 리소스 사용량에 따라 독립적으로 확장이 가능합니다.

    정적 리소스 사용량이 많을 경우 웹 서버만 증설하면 되고, 애플리케이션 로직 사용량이 많을 경우 WAS만 증설하면 되므로 효율적인 리소스 관리가 가능합니다. 또한, 정적 리소스만 제공하는 웹 서버는 장애 발생이 드물기 때문에, 설령 WAS에 장애가 발생하더라도 클라이언트에게 오류 화면을 제공할 수 있습니다.

     

     


    < 서블릿(Servlet) >

    서블릿은 자바 기반 웹 애플리케이션에서 클라이언트의 요청을 받아 처리하고, 결과를 생성해 응답하는 작업을 자동화해 주는 서버 측 프로그램입니다.
    비유하자면, 요리사가 요리를 만드는 데 집중할 수 있도록 식재료 준비와 같은 반복적인 작업을 대신해 주는 보조 도구와 같은 역할을 합니다. 서블릿을 사용하면 개발자는 중요한 비즈니스 로직에 집중할 수 있고, 나머지 반복적인 요청 처리 작업은 서블릿이 맡아서 처리합니다.


     

    HTML Form 데이터 전송을 통해 위와 같이 요청을 보내게 되면 웹 브라우저에서는 해당 요청에 대한 HTTP 메시지를 생성하여 서버로 보내게 됩니다.

     

    만약 우리가 웹 애플리케이션 서버를 밑바닥부터 모두 구현해야 한다면 위에서 말한 HTTP 메시지를 해석하여 올바른 응답을 보내줄 수 있도록 기능을 구현해야 하며, 그 과정은 위와 같습니다.

     

    그림을 보면 알 수 있듯이, 의미 있는 비즈니스 로직은 전체 과정에서 극히 일부를 차지합니다. 즉, 꼭 필요한 작업이지만 귀찮고 반복적인 작업을 매 요청마다 수행해야 합니다. 이를 해결하기 위해 서블릿이 등장했습니다. 서블릿은 위 그림에서 초록색 박스로 표시된 의미 있는 비즈니스 로직 부분을 제외한 나머지 모든 작업을 지원해 줍니다.

     

    @WebServlet(name = "helloServlet", urlPatterns = "/hello")
    public class HelloServlet extends HttpServlet {
    
        @Override
        protected void service(HttpServletRequest request, HttpServletResponse response) {
        	// 애플리케이션 로직
        }
    }

    위 코드에서 지정한 `urlPatterns`의 URL이 호출될 때 서블릿 코드가 실행됩니다. 또한, 서블릿은 HTTP 요청 정보를 쉽게 사용할 수 있도록 `HttpServletRequest` 객체를, HTTP 응답 정보를 편리하게 제공할 수 있도록 `HttpServletResponse` 객체를 제공합니다. 이를 통해 개발자는 HTTP 스펙을 보다 편리하게 활용할 수 있습니다.

     

    서블릿을 사용할 경우, HTTP 요청과 응답의 흐름은 다음과 같습니다.

    1. HTTP 요청이 발생하면 WAS는 새로운 Request와 Response 객체를 생성하여 서블릿 객체를 호출합니다.
    2. 개발자는 이 객체들을 통해 HTTP 요청 정보를 사용하고, 응답 정보를 편리하게 입력할 수 있습니다.
    3. 이후 WAS는 Response 객체에 담긴 내용을 기반으로 HTTP 응답을 생성하여 클라이언트로 전달합니다. 클라이언트는 이 응답을 렌더링하여 화면에 표시합니다.

     

     


    서블릿 컨테이너 ]

    • 서블릿 컨테이너는 서블릿을 지원하는 WAS, 예를 들어 Tomcat과 같은 시스템을 의미하며, 서블릿 객체의 생성, 초기화, 호출, 종료 등의 생명주기를 관리합니다.
    • 서블릿 객체는 싱글톤으로 관리됩니다. 즉, 사용자의 요청이 올 때마다 서블릿 객체를 반복적으로 생성하는 것은 비효율적이므로, 최초 로딩 시점에 서블릿 객체를 미리 생성하여 재활용합니다.
    • 모든 사용자 요청은 동일한 서블릿 객체 인스턴스에 접근하므로 공유 변수 사용에 주의해야 합니다.
    • 서블릿 객체는 서블릿 컨테이너가 종료될 때 함께 종료됩니다.
    • 서블릿을 지원하는 WAS의 가장 큰 특징 중 하나는 동시 요청을 처리하기 위한 멀티쓰레드 기능을 지원한다는 점입니다.

     

     


    < 동시 요청 - 멀티 쓰레드 >

    지금부터 다룰 개념은 트래픽이 많은 시스템을 관리할 때 필수적인 요소이므로, 백엔드 개발자라면 이를 확실히 이해하고 넘어가는 것이 중요합니다.

     

    위에서 설명한 대로 클라이언트가 URL을 통해 서버에 요청하면 TCP/IP 연결이 이루어지고 서블릿 객체가 호출됩니다. 그렇다면 이때 서블릿 객체를 실제로 호출하는 주체가 누구인지 알아보겠습니다.

     

     


    [ 쓰레드 ]

    서블릿 객체를 호출하는 것은 바로 쓰레드입니다.

    쓰레드는 애플리케이션 코드를 순차적으로 실행하는 단위로, 자바 메인 메서드를 처음 실행할 때 동작하는 'main' 쓰레드 역시 이에 해당합니다. 즉, 쓰레드가 없다면 자바 애플리케이션은 실행될 수 없습니다.

    쓰레드는 한 번에 하나의 코드 라인만 수행할 수 있기 때문에 동시 처리가 필요할 때는 추가적으로 쓰레드를 생성해야 합니다.

     

    장점

    • 다중 요청이 들어와 쓰레드가 부족할 경우 요청마다 새로운 쓰레드를 생성하여 해결할 수 있습니다. 이렇게 하면 리소스(CPU, 메모리)가 허용하는 한 동시 요청을 처리할 수 있으며, 하나의 쓰레드가 지연되더라도 다른 쓰레드는 정상적으로 작동할 수 있습니다.

     

    단점

    • 반면 쓰레드는 생성 비용이 매우 높습니다. 쓰레드 생성에 많은 자원이 필요하므로 응답 속도가 느려질 수 있으며, 추가적으로 쓰레드 간의 컨텍스트 스위칭 비용도 발생합니다. 또한, 쓰레드는 이론상 무한히 생성할 수 있기 때문에, 어느 순간에는 CPU와 메모리의 임계점을 넘어 서버가 다운될 수도 있습니다.

    +. 컨텍스트 스위칭은 CPU가 여러 쓰레드를 실행할 때, 현재 실행 중인 작업의 상태를 저장하고 새로운 작업의 상태를 불러오는 과정을 의미합니다.

     

     


    [ 쓰레드 풀 ]

    이를 해결하기 위해 대부분의 WAS에서는 쓰레드 풀을 사용합니다.

    즉, 미리 일정 수의 쓰레드를 생성하고 저장해 두었다가, 사용자 요청이 들어올 때마다 해당 풀에서 쓰레드를 가져와 사용합니다. 사용이 끝난 쓰레드는 종료하지 않고 다시 쓰레드 풀에 돌려줌으로써, 쓰레드를 생성하고 종료하는 데 필요한 시간과 자원 소모를 최소화할 수 있습니다. 또한, 생성 가능한 쓰레드의 최대치가 정해져 있어 과도한 요청이 들어와도 기존 요청을 안정적으로 처리할 수 있습니다.

     

    예를 들어, Tomcat의 경우 기본 최대 200개의 쓰레드가 설정되어 있습니다. 만약 쓰레드 풀에 사용 가능한 쓰레드가 없다면, 요청은 대기 상태로 전환되거나 거절될 수 있습니다.

     

     


    [ 쓰레드 풀 - 실무 Tip ]

    WAS의 주요 튜닝 포인트 중 하나는 최대 쓰레드 수(max thread)입니다.

    이 값을 너무 낮게 설정하면 동시 요청이 많을 때 서버 자원은 여유롭겠지만, 클라이언트는 응답 지연을 겪게 됩니다. 반대로 너무 높게 설정하면, 동시 요청이 많은 상황에서 CPU와 메모리 자원이 한계를 넘어 서버가 다운될 수 있습니다. 따라서 시스템에 맞게 최대 쓰레드 수를 적절히 설정하는 것이 중요합니다.

     

    그렇다면 적절한 최대 쓰레드 수를 어떻게 찾을 수 있을까요? 이는 애플리케이션 로직의 복잡도, CPU, 메모리, IO 자원 상태에 따라 다를 수 있습니다. 가장 안전하고 정확한 방법은 실제 서비스와 유사한 조건에서 충분한 성능 테스트를 통해 적절한 수준을 찾아보는 것입니다.

     

     

    WAS의 멀티 쓰레드 지원의 핵심은 멀티 쓰레드와 관련된 부분을 모두 WAS가 처리하기 때문에, 개발자가 멀티 쓰레드 관련 코드를 직접 신경 쓸 필요가 없다는 점입니다. 즉, 개발자는 싱글 쓰레드 프로그래밍을 하듯이 편리하게 코드를 작성하면 됩니다.

    하지만, 멀티 쓰레드 환경이므로 싱글톤 객체(예: 서블릿, 스프링 빈)를 사용할 때는 주의가 필요합니다.

     

     


    < HTML, HTTP, API, CSR, SSR >

    [ HTML, HTTP, API ]

    백엔드 개발자가 서비스를 제공할 때 고려해야 할 주요 방식은 세 가지로 나뉩니다.

     

    첫 번째는 정적 리소스입니다.

    여기에는 고정된 HTML 파일, CSS, JS, 이미지, 영상 등이 포함되며, 주로 웹 브라우저에서 사용됩니다.

     

    두 번째는 HTML 페이지입니다.

    이는 동적으로 필요한 HTML 파일을 생성하여 전달하는 방식으로, 웹 브라우저는 이 파일을 해석하여 화면에 출력합니다.

     

    세 번째는 HTTP API 방식입니다. 이 방식은 HTML 페이지 대신 데이터를 전달하며, 주로 JSON 형식을 사용하여 다양한 시스템에서 호출할 수 있습니다. 데이터만 주고받기 때문에 UI가 필요한 경우 클라이언트 측에서 별도로 처리해야 합니다.

    HTTP API 방식의 호출 종류에는 앱 클라이언트 to 서버, 웹 클라이언트 to 서버로, 서버 to 서버가 있습니다.

     

     


    [ CSR, SSR ]

    최근에는 이 외에도 CSR, SSR이라는 서비스 제공 방식이 새롭게 등장하였습니다.

     

    CSR

    CSR(Client Side Rendering)은 말 그대로 클라이언트 측에서 렌더링을 수행하는 방식으로, HTML 결과를 자바스크립트를 사용하여 웹 브라우저에서 동적으로 생성하는 것을 의미합니다. 이 방식은 주로 동적인 화면에 사용되며, 웹 환경을 마치 앱처럼 필요한 부분만 변경할 수 있습니다.

     

    관련 기술로는 React, Vue.js 등이 있습니다.

     

     

    SSR

    SSR(Server Side Rendering)은 서버 측에서 렌더링을 수행하는 방식으로, HTML의 최종 결과를 서버에서 생성하여 웹 브라우저에 전달하는 것을 의미합니다. 이 방식은 주로 정적인 화면에 사용됩니다.

     

    관련 기술로는 JSP, 타임리프 등이 있습니다.

     

     

    CSR + SSR을 동시에 지원하는 웹 프레임워크도 있으며, SSR을 사용하더라도 자바스크립트를 사용해서 화면 일부를 동적으로 변경할 수 있습니다.

     

     

     

     

     

     

     

     

     

     

     

     


    해당 글에 포함된 코드나 그림은 김영한님이 제공해주신 자료를 바탕으로 작성되었습니다.

    스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 | 김영한 - 인프런

     

    스프링 MVC 1편 - 백엔드 웹 개발 핵심 기술 강의 | 김영한 - 인프런

    김영한 | 웹 애플리케이션을 개발할 때 필요한 모든 웹 기술을 기초부터 이해하고, 완성할 수 있습니다. 스프링 MVC의 핵심 원리와 구조를 이해하고, 더 깊이있는 백엔드 개발자로 성장할 수 있습

    www.inflearn.com

    'Java > Spring' 카테고리의 다른 글

    Creating an MVC framework  (2) 2025.02.13
    Servlet / JSP / MVC  (2) 2025.02.12
    Bean Scope  (1) 2025.01.12
    Bean Lifecycle Callback  (3) 2025.01.03
    Automatic injection of dependencies  (1) 2025.01.03

    댓글

Designed by Tistory.