서버란?

Computer Science/Server

우리가 말하는 백엔드(API) 서버란 무엇인가?

흔히 백엔드 서버라고 자주 얘기하지만 무엇을 두고 백엔드 서버라고 말하는지 정의해보자. 그동안은 API만 개발하다보니 이런 정의가 헷갈리기 시작해졌다.

내가 생각하기에 백엔드(API) 서버란 애플리케이션이 HTTP 요청을 수신하고 응답할 수 있는 실행 환경을 말하는 것 같다. 그 안에 우리가 구현한 api와 비즈니스 로직이 존재한다.

백엔드 개발자가 만든 API(순수 자바 코드)는 HTTP 요청을 수신할 능력이 없다. 따라서 사용자가 보낸 HTTP 요청이 API까지 닿을 수 있도록 요청을 받는 런타임이 필요하다. WAS와 서블릿 컨테이너가 해당 역할을 한다.

이 런타임은 사용자가 TCP 소켓 + HTTP 프로토콜로 보낸 요청을 수신해서 파싱(헤더/바디), 라우팅(url 매칭), 응답 직렬화를 해준다. 정확히는 아래와 같은 일을 한다.

  • 소켓 오픈: 특정 포트(예: 8080)에서 들어오는 TCP 연결 수락.
  • HTTP 파싱: Request 라인을 읽고 헤더/바디 분리.
  • 스레드/이벤트 루프에 분배: 요청을 처리할 워커에게 전달.
  • 프레임워크와 연결: URL → 컨트롤러 메서드 매핑, DTO 역직렬화.
  • 응답 작성: JSON 직렬화, 헤더/상태코드 붙여서 클라이언트로 송신.

직렬화/역직렬화란?

직렬화는 객체를 바이트나 문자열의 형태로 변환하는 과정이다. 

반대로 역직렬화는 바이트나 문자열을 객체의 형태로 변환하는 과정이다.

 

왜 이런 과정이 필요할까?

객체는 언어에 의존한다. 자바의 경우 인스턴스는 힙 메모리에 필드, 메서드 테이블, 레퍼런스 형태로 저장된다. 이런 내부 메모리 레이아웃은 다른 환경(OS, 언어 등)에서 해석하지 못한다. 따라서 네트워크 전송 혹은 파일 저장을 위해서는 해당 객체를 모두가 알아볼 수 있는 레이아웃(JSON, Protocol Buffers, Avro, Thrift 등)으로 변경하는 과정(= 직렬화)이 필요하다. (주로 JSON 사용)

 

근데 그동안 Spring Boot를 사용하면서 직렬화와 역직렬화는 @RequestBody나 @ResponseBody가 하는 일이 아닌가?? 하는 의문이 들어서 찾아보니

HTTP 런타임(tomcat 등)은 HttpServletRequest나 HttpServletResponse 와 같은 서블릿 레벨의 객체로 직렬화/역직렬화 한다는 뜻이었다. 위 두 객체를 위에서 말한 어노테이션이 받아 실제로 사용할 수 있는 DTO나 객체로 한 번 더 직렬화/역직렬화 과정을 거친다. 왜 객체인데 직렬화인가? 싶지만 HttpServletRequest나 HttpServletResponse의 바디(본문)에는 JSON으로 내용이 담겨져 있기 때문에 해당 내용을 java가 해석할 수 있는 객체로 다시 한 번 직렬화/역직렬화 해주어야 한다.

(정확히는 Content-Type 헤더에 의해서 본문의 데이터 형식이 결정된다.)

 

역직렬화 흐름(사용자 요청부터 java 객체까지)

  • Tomcat/Netty가 요청을 받아 InputStream 제공.
  • Spring의 **HttpMessageConverter(Jackson 사용)**가 InputStream을 읽어 JSON 파싱.
  • 지정한 클래스(@RequestBody에 사용한 클래스)의 빈 인스턴스 생성 (리플렉션 기반, new 호출 또는 Unsafe 사용).
  • JSON 필드값을 클래스의 필드에 주입.
  • 최종적으로 객체가 컨트롤러 파라미터로 전달.

근데 스프링은 싱글톤 아닌가요?? 매번 새로운 인스턴스가 생성되는데요?

스프링에서의 싱글톤은 빈의 기본 스코프를 의미하기 때문에 요청마다 값이 달라지는 DTO나 Entity 같은 건 싱글톤이 아니고 싱글톤이어선 안된다.

 

서버 얘기하다가 직렬화/역직렬화까지 와버렸는데 다시 본론으로 돌아가자면 상세한 의미에서의 서버는 사용자의 HTTP 요청을 받아서 java 시스템으로 넘겨주는 런타임 이라고 생각한다. 해당 런타임의 역할을 수행할 수 있는 친구들을 알아보자

 

서블릿(Servlet) 기반 VS 비 서블릿 기반 VS 서버리스

서블릿이란?

자바 기반으로 HTTP 요청/응답을 처리하는 표준 인터페이스(명세)

 

* 표준 인터페이스란?

업계나 플랫폼에서 정한 공식 명세 (해당 인터페이스를 구현하는 모든 구현체는 명세를 따라야 함)

요청 객체는 이런 메서드를 반드시 제공해야 한다 -> getParameter(), getHeader(), getSession() 등

응답 객체는 이런 메서드를 제공해야 한다 -> setStatus(), getWriter(), setHeader() 등

 

- 이런 "표준 인터페이스"라는 말은 자주 사용된다. jpa도 자바 orm 표준 인터페이스(명세)이다.

 

1. 서블릿(Servlet) 기반

경량 서블릿 컨테이너

  • Apache Tomcat
    • 가장 널리 쓰이는 서블릿 컨테이너.
    • Spring Boot 기본 내장 서버.
    • HTTP/1.1, HTTP/2 지원, 안정성 높음.
  • Jetty
    • 경량, 빠른 기동 속도, 임베디드 환경에 자주 쓰임.
  • Undertow
    • RedHat이 만든 경량 서버.
    • 논블로킹 I/O 기반, WildFly의 기본 웹 서버.

서블릿을 지원하는 외부 WAS

  • JBoss/WildFly
    • 서블릿 컨테이너 + EJB, JTA 등 Java EE 전체 스펙 지원.
    • Undertow를 내장 서블릿 엔진으로 사용.
  • GlassFish / Payara
    • Java EE 참조 구현체.
    • 서블릿 컨테이너와 함께 JMS, JPA, JAX-RS 등 풀 스펙 제공.
  • IBM WebSphere
    • 기업용 상용 WAS. Java EE 풀 스펙 지원.
  • Oracle WebLogic
    • 오라클의 상용 WAS. 금융권/레거시에 많이 남아 있음.

이들은 모두 HTTP 요청을 수신하고, Servlet API에 따라 HttpServletRequest, HttpServletResponse 객체를 만들고,
서블릿(DispatcherServlet)에게 넘겨서 우리가 작성한 컨트롤러까지 연결해준다.

(Spring Boot는 단순히 Spring 애플리케이션을 더 쉽게 실행하기 위한 툴)

 

2. 비 서블릿 기반

  • Netty
    • 저수준 NIO 기반 네트워크 프레임워크.
    • 서블릿 스펙에 의존하지 않음.
    • Spring WebFlux의 기본 런타임(→ Reactor Netty).
    • gRPC, MQTT 등 커스텀 프로토콜 서버를 직접 구현 가능.
  • Vert.x
    • 이벤트 루프 기반, 논블로킹 애플리케이션 프레임워크.
    • 서블릿 API 대신 자체 Router, EventBus를 사용.
  • Akka HTTP (Scala/Java)
    • 액터 모델 기반, 논블로킹 HTTP 서버.
    • Servlet API 대신 자체 DSL로 라우팅/핸들링.

+ 자바가 아닌 다른 언어의 웹 프레임워크/런타임들

동일하게 클라이언트의 HTTP 요청을 받는 런타임이지만 서블릿 인터페이스를 사용하지 못하는 친구들이다.

 

3. 서버리스 / FaaS 기반

  • AWS Lambda, Google Cloud Functions, Azure Functions
    • 서블릿 컨테이너 자체가 아예 없음.
    • API Gateway나 Function Runtime이 HTTP 요청을 받아 함수에 직접 전달.
  • Cloudflare Workers, Vercel Functions
    • JavaScript/WebAssembly 기반의 경량 런타임.
    • 서블릿과 무관하게 HTTP 이벤트를 함수로 처리

클라우드에서 코드로 직접 HTTP 요청을 받아준다. 말은 "서버리스"지만 사실은 "클라우드가 대신 운영해주는 서버"에 가까운 것 같다.

또한 항상 서버가 켜져있는 것이 아니라 사용자의 요청이 들어올 때만 개발자가 작성한 코드가 실행되는 방식이다. (그래서 서버리스라고 부르는 듯)

차이점

같은 서블릿 기반 컨테이너들이 뭐가 다르길래 대부분 tomcat을 사용하는가? 스프링 부트엔 왜 tomcat이 기본으로 내장되어 있는가? 라는 질문이 생겨서 gpt한테 물어봤다.

지피티 피셜 Tomcat이 기본인 이유

Tomcat

  • 특징
    • 가장 널리 쓰이고 보급률 1위 → 자료·운영 경험 풍부
    • 안정적이고 성숙도가 높음 (대규모 트래픽 검증됨)
    • 기본적으로 스레드 기반 블로킹 I/O (요청 하나당 워커 스레드)
  • 장점
    • Spring MVC와의 궁합 최상, 디폴트이자 사실상 표준
    • APM/모니터링/IDE 지원 풍부
  • 단점
    • 스레드 풀 관리 필요 → 초고동시성/스트리밍 처리엔 다소 비효율

Jetty

  • 특징
    • 경량/임베디드 친화적 (IoT, 소형 앱에 자주 사용)
    • 모듈화 구조, 커스터마이징 용이
    • NIO 기반 논블로킹 모델도 지원
  • 장점
    • 기동 속도 빠름, 메모리 사용량 적음
    • 작은 footprint → 경량화된 환경(임베디드 디바이스, 마이크로서비스)에 적합
  • 단점
    • Tomcat만큼의 운영사례·레퍼런스는 적음
    • 대규모 트래픽/엔터프라이즈 환경에선 Tomcat 선호도가 더 높음

undertow

  • 특징
    • RedHat이 개발, WildFly의 내장 서버
    • 완전 논블로킹 I/O 아키텍처 (event-driven)
    • Servlet API + 핸들러 체인 기반 API 동시에 지원
  • 장점
    • 비동기/리액티브 아키텍처에 적합
    • 높은 성능과 낮은 메모리 사용량 (특히 WebSocket, HTTP/2 성능 우수)
  • 단점
    • 커뮤니티/운영 사례가 Tomcat보다 적음
    • 튜닝/자료가 상대적으로 부족

 

이렇게 나열하고 보면 성능면에서 undertow가 유리해보인다. 하지만 사용성 측면에서 Tomcat은 운영 안정성과 예측 가능성이 높기 때문에 주류로 사용되는 것 같다. 그리고 서블릿 컨테이너만 변경한다고 드라마틱한 성능 향상이 이루어지지도 않는다.

또한, Servlet API 스펙 자체가 동기(블로킹) 모델로 설계되어있어 워커 스레드가 점유된다. Tomcat/Jetty/Undertow 같은 서블릿 컨테이너는 요청이 들어올 때마다 워커 스레드 하나를 할당하고, 요청 처리가 끝나야 스레드를 반환한다. 이 때문에 동시 요청이 많아지면 스레드 풀 크기만큼만 동시에 처리할 수 있고, 그 이상은 대기 큐에 쌓인다. 따라서 진짜 논블로킹 체인을 원하면 Spring WebFlux + Reactor Netty 쪽이 더 일관된다고 생각한다.

그래서 무조건 Tomcat인가? 라고 하면 또 undertow를 사용하는 것이 좋은 상황이 있을 것이다. Tomcat보다 가볍기 때문에 서버 기동 속도가 중요한 경우 (CI/CD 파이프라인에서 서버를 자주 재기동하는 환경) 혹은 메모리나 리소스가 적은 환경 (도커로 묶은 작은 서비스들, 혹은 Lambda 같은 제약 환경) 등에서는 undertow를 고려해볼 수 있을 것 같다.

gpt의 서블릿 논란 정리

 

이러나저러나 가장 큰 이유는 사용률인 것 같다. 서블릿 기반은 결국 블로킹 모델이고, 큰 성능상 이점이 없다보니 레퍼런스가 많은 기술을 선택하는 것이 최선인 것 같다.

기술을 공부하다보면 잘 만들어진 기술은 자연스럽게 사용자가 늘어나게 되고 트러블 슈팅에 대한 가이드도 생기고 고착화되는 것 같다고 생각한다. 하지만 당연하게 사용하는 것들에도 다른 기술들과 비교해서 사용하는 것과 기술을 새로 배우는 러닝커브도 어느정도 생각해야하기 때문에 기술을 선택할 땐 이런 트레이드 오프들을 잘 고려해서 선택하는 것이 중요한 것 같다.

 

Web Server VS Web Application Server(WAS)

위에서 작성한 내용같이 우리가 만든 코드를 실행시키기 위한 서버를 WAS라고 한다. 코드로 HTTP 요청을 보내주고 응답을 내려주는 역할을 한다.

그러면 Web Server란 무엇인가? WAS는 우리의 코드에 HTTP 요청을 전달하고 실행한다. 하지만 Web Server는 동적인 로직을 실행하는 것이 아니라 HTML, CSS와 같은 정적인 파일을 서빙한다.

WAS는 우리 코드를 실행해주는 것만으로도 바쁜데 HTML이나 CSS같은 파일까지 서빙한다면 정신이 없을 것이다. 그래서 해당 역할을 분담하는 것이 Web Server이다. 만약 Web Server가 없다면 서버가 다운되었을 때 화면을 출력해 줄 서버가 없기 때문에 클라이언트한테 아무런 화면을 띄워주지 못한다. 이러한 이유들로 Web Server를 따로 두어 애플리케이션 서버의 부담을 줄여주고 애플리케이션 서버가 다운됐을 때 사용자에게 화면을 출력해주는 역할을 하게 한다.

 

참고자료

https://zamezzz.tistory.com/entry/Undertow%EB%9E%80-Tomcat-Netty%EC%99%80-%EB%B9%84%EA%B5%90%ED%95%B4-%EC%96%B8%EC%A0%9C-%EC%93%B0%EB%A9%B4-%EC%A2%8B%EC%9D%84%EA%B9%8C

 

Undertow란? Tomcat, Netty와 비교해 언제 쓰면 좋을까

최근에 Undertow를 다시 다뤄볼 일이 생겼는데, 예전에도 이걸 사용한 적이 있었습니다.그래서 왜 선택했는지 떠올려보면서 정리해보려고 합니다.결론부터 말하면, 빠르고 가볍고 유연해서였고,

zamezzz.tistory.com

 

'Computer Science > Server' 카테고리의 다른 글

도메인 주도 개발  (0) 2025.11.27
JWT (w. Session)  (0) 2025.08.30
'Computer Science/Server' 카테고리의 다른 글
  • 도메인 주도 개발
  • JWT (w. Session)
hojoo
hojoo
그냥 개발이 즐거운 사람
  • hojoo
    dev_record
    hojoo
  • 전체
    오늘
    어제
    • 분류 전체보기 (84)
      • Study (0)
        • 모든 개발자를 위한 HTTP 웹 기본 지식 (0)
        • Real MySQL 8.0 (0)
        • 친절한 SQL 튜닝 (0)
        • 도메인 주도 개발 시작하기 (0)
        • 대규모 시스템 설계 기초 (0)
      • Computer Science (68)
        • Problem Solving (30)
        • Data Structure (4)
        • Spring Boot (14)
        • DB (1)
        • Java (4)
        • OS (3)
        • Server (3)
        • Tech (0)
      • Security (16)
        • Reversing (15)
        • Assembly (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    소수상근수
    19622
    2539
    Header
    프로그래머스
    HTTP
    x64dbg
    Spring boot
    21278
    서버 증설 횟수
    Lena tutorial
    Reversing
    자료구조
    PE header
    레나 튜토리얼
    n^2 배열 자르기
    12033
    n+1
    9421
    리버싱 핵심원리
    16946
    DP
    15973
    백준
    servlet
    리버싱
    DB
    13265
    dreamhack.io
    bean
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.4
hojoo
서버란?
상단으로

티스토리툴바