
왜 웹서버는 미들웨어가 아닌가?
⇒ 웹서버는 WAS와는 다르게 비지니스 로직을 담당하지 않기 때문에
어플리케이션 서버와 WAS는 같은 것 인가?
⇒ JAVA EE를 구현하여 서블릿으로 작성된 어플리케이션을 실행 할 수 있으면 WAS
즉, WAS는 어플리케이션 서버의 한 종류
분산 어플리케이션 개발 목적의 산업 표준 플랫 폼
Servlet(서블릿), JSP, EJB, JDBC, JNDI, JMX, JTA등의 기술을 포함
웹 서버가 동적인 데이터를 반환하기 위해선 이를 위한 비지니스로직을 처리하는 프로그램이 필요하다. 이 데이터를 처리하는 프로그램에 요청을 적절히 전달해주는 중간자 역할을 하는 프로그램이 CGI프로그램이다.
(클라이언드 → CGI Process → Program)
하지만 CGI는 실체가 있는 도구가 아니라 웹 서버와 외부 프로그램 사이에서 정보를 주고 받는 방법, 즉 표준 스펙이자 인터페이스입니다.
⇒ 다양한 언어(PHP, Python …)로 CGI를 구현(적용) 할 수 있다.
JAVA에선 CGI와 유사한 방식으로 구현된 서블릿(Servlet)이라는 프로그램이 존재
서블릿은 JAVA를 사용하여 웹 요청(HTTP)을 처리하고 응답을 생성하는 서버 측 프로그램
💡 Jakarta EE의 스펙(인터페이스, 명세) 중 하나인 Servlet을 구현 → 이를 WAS로 배포
싱글톤이란?
하나의 클래스에 대해 하나의 인스턴스만 존재하도록 보장하는 디자인 패턴
서블릿은 싱글톤으로으로 동작한다. → 모든 요청에 대해서 하나의 같은 인스턴스를 공유
여러 요청이 동시에 들어온다면?
이 때 서블릿 내부에 멤버 변수가 있으면?
private int count = 0;
protected void doGet(...) {
count++; // Thread-Unsafe!
}
💡서블릿의 Thread-Safe를 보장하려면 다음과 같은 방법을 적용해야 한다.
synchronized, AtomicInteger 와 같은 별도의 Thread-Safe구조를 사⚡웹 컨터이너와 서블릿 컨테이너는 같은 말
💡Tomcat은 서블릿 컨테이너이면서도 WAS의 역할도 어느정도 가진다. 하지만 Tomcat은 JAVA EE의 스펙을 전부 구현하지 않기 때문에 → 서블릿 컨테이너라고 할 수 있다.
서블릿 컨테이너는 IoC(Inversion of Control: 제어의 역전)과 DI(Dependency Injection: 의존성주입)
을 할 수 있으며 서블릿 컨테이너의 역할은 다음과 같다.
(IoC와 DI는 아래에서 자세히 알아보자)

이 이름만 들어도 어지러운 두개는 도대체 무엇일까? 알아보자
class Engine {
void start() { System.out.println("엔진 시작"); }
}
class Car {
private Engine engine = new Engine(); // Car가 직접 Engine을 만듬
void start() {
engine.start();
}
}Car는 항상 Engine에 강하게 묶여있다. (강한 결합)
- 테스트 어렵고, 의존하는 객체(Engine )을 바꾸기도 어렵다. (구현객체를 참조)
⭕ DI 적용 코드
class Car {
private Engine engine;
// 외부에서 의존성(Engine)을 주입받음
public Car(Engine engine) {
this.engine = engine;
}
void start() {
engine.start();
}
}
이제 Car는 어떤 Engine이든 의존이 가능(유연성 증가)(인터페이스를 참조 → 약한 결합)
MVC는 Model-View-Controller의 약자
Spring MVC는 이 구조를 기반으로 웹 어플리케이션을 구성하는 프레임워크이다.(Spring 프레임워크의 하위 모듈)
일단 스프링컨테이너, IoC컨테이너, DI컨테이너 모두 같은 것을 지칭하는 용어다.
왜 용어가 통일이 안되는가 헷갈리게..
자 스프링 컨테이너를 이해하기 위해선 일단 Bean이 무엇인지를 알아야합니다.
Bean이란 간단히 Spring이 관리하는 객체입니다. 즉 앞으로 알아볼 스프링 컨테이너가 생성하고 관리하는 객체가 Bean입니다.
앞에서 IoC에 대해서 간단하게 소개했었는데 이 Bean을 스프링 컨테이너가 IoC를 적용해서 관리합니다.(알아서 관리한다는 소리, 개발자가 직접 생성하고 관리하지 않는다.)
즉, 스프링컨테이너는 이 Bean의 생명 주기를 관리하는 역할을 합니다.
💡이 IoC컨테이너를 상속하여 부가 기능을 추가한 것이 ApplicationContext이다.
정리하자면 서블릿컨테이너 안에 Spring MVC의 DispatcherServlet이라는 서블릿이 등록되어 있고,
이 DispatcherServlet가 Spring컨테이너(ApplicationContext)을 통해 Bean들을(@Controller, @Service 등) 관리하여 요청에 의한 비지니스로직을 처리합니다.

클라이언트가 HTTP요청을 보낸다.
이 요청을 WEB이 받는다.
2-1. 정적 자원 요청이면 WEB이 직접 응답한다.
2-2. 동적자원 요청이면 이른 WAS에 전달한다.
WAS(Servlet Container)가 요청을 받아 Spring MVC의 DispatcherServlet를 호출
DispatcherServlet이 요청에 따라 처리할 Controller Bean을 결정
Spring Container(ApplicationContext)가 등록된 Bean들을 이용해 로직 처리
처리 결과를 View 또는 JSON의 형태로 응답
웹 애플리케이션 아키텍처를 정리하면서 처음 보는 용어도 많고, 같은 개념을 여러 방식으로 부르는 경우도 많아 많이 헷갈렸던 것 같습니다.
하지만 개념을 하나씩 정리해가다 보니, 각 구성 요소의 역할과 흐름이 조금씩 보이기 시작했고, 웹의 전반적인 구조를 이해하는 데 큰 도움이 되었습니다.
단순히 코드를 따라치는 것만으로는 구현은 가능하겠지만, 구조와 개념에 대한 이해가 없다면 그것은 진짜 '이해한 것'이 아니라고 느꼈습니다.
앞으로도 무언가 어렵거나 개념이 잡히지 않을 때는, 스스로에게 설명하듯 글로 정리하며 학습하는 습관을 가져야겠다는 생각이 들었습니다.
글이 다소 길고 두서없을 수 있지만, 저에게는 분명히 정리가 되는 소중한 시간이었습니다.
혹시 잘못된 내용이나 부족한 부분이 있다면 언제든지 알려주십쇼!
저에게 정말 큰 도움이 될 겁니다.
참조
[Spring] Spring MVC - Servlet, Servlet Container, Spring Container 에 대해
[Spring] Servlet, Servlet Container, Spring MVC 정리