1.2.3 서버란?
import java.net.ServerSocket;
import java.net.Socket;
public class WebServer {
public static void main(String[] args) {
new WebServer().run();
}
public void run() {
try {
ServerSocket serverSocket = new ServerSocket(8080);
while (true) {
try {
Socket client = serverSocket.accept();
new Thread(() -> handleClient(client)).start();
} catch (Exception e) {
e.printStackTrace();
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
private static void handleClient(Socket client) {
// (1) 클라이언트의 요청 읽어오기
// (2) 클라이언트의 요청에 맞는 작업 수행하기
// (3) 클라이언트에게 응답 작성하기
// (4) 소켓 닫기
}
}
서버는 프로그램이다. 이 프로그램은 지정된 포트, 8080포트에 소켓을 열어 클라이언트가 연결할 때까지 무한 대기하며 기다린다. 그러다가 클라이언트가 연결하면 해당 클라이언트 소켓에서 요청을 받아와 수행하고 응답을 작성해 전달한다.
서버에서 클라이언트의 요청을 읽어올 때 또는 응답을 작성할 때 파일을 주고 받으면 FTP File Transfer Protocol 서버가 되고, 하이퍼텍스트 트랜스퍼 프로토콜을 사용한다면 HTTP 서버가 되는 것이다.
1.2.4 정적 웹 서버
Static Web Server란 HTTP 서버 중에서도 리소스 파일을 리턴하는 서버를 의미한다.
서버 호스트가 8080에서 실행하고 있는 로컬 호스트라고 가정하면, localhost:8080/file.html HTTP 요청을 서버로 보내면 정적 웹 서버인 서버는 지정된 디렉토리 경로에서 file.html를 찾아 그 내용을 HTTP 응답 바디에 넣어 전송한다.
이때, 서버는 해당 html 파일에 아무 작업도 하지 않고 파일을 있는 그대로 리턴한다. 그래서 정적 Static Web Server이다.이런 정적 웹 서버의 예로 아파치, Nginx 등이 있다. 아파치, Nginx를 설치하고 지정된 경로에 원하는 리소스 파일을 저장하면 자동으로 해당 리소스는 웹 서버를 통해 접근할 수 있다.
질문 주제: 정적 웹 서버의 동작 원리에 대한 추가 설명
정적 웹 서버는 HTML, CSS, JavaScript, 이미지, 폰트, 동영상 등 변하지 않는 정적인 파일을 클라이언트에 제공하는 서버다. 여기서 "정적(static)"이라는 뜻은, 서버가 파일의 내용을 실시간으로 처리하거나 조작하지 않고, 저장된 그대로 응답한다는 뜻이다.
🔧 동작 과정
- 클라이언트 요청: 브라우저가 localhost:8080/file.html로 요청을 보낸다.
- 서버 응답: 웹 서버(Apache, Nginx 등)는 설정된 루트 디렉토리에서 file.html을 찾아 그대로 읽는다.
- 전송: 읽은 파일 내용을 HTTP 응답 바디에 담아 브라우저로 전송한다.
- 브라우저 렌더링: 클라이언트는 받은 HTML을 브라우저에서 렌더링한다.
📁 정적 파일이 저장되는 위치
서버는 Document Root 또는 Web Root로 불리는 특정 디렉토리를 기준으로 정적 파일을 찾는다.
예시 (Apache 기준):
/var/www/html/
- 여기에 index.html을 두면 localhost:8080/index.html로 접근 가능.
⚙️ 주요 특징
속도 | 파일 처리 없이 곧바로 응답하므로 빠르다 |
보안 | 서버 측 코드 실행이 없으므로 보안 이슈 적음 |
확장성 | CDN과 결합 시 수천만 사용자에게도 대응 가능 |
제약 | 동적인 데이터 처리나 로그인/DB 연동은 불가능 |
1.2.5 동적 웹 서버
동적 웹 서버는 파일을 있는 그대로 리턴하지 않는다. 동적 웹 서버는 요청을 처리한 후 처리한 결과에 따라 응답 바디를 재구성하거나 HTML 템플릿 파일에 결과를 대체해 보낸다.
위 그림을 통해 동적 웹 서버의 예를 확인해 보자. 클라이언트는 요청에 요청 매개변수를 보낼 수 있다. 그림에서는 name=Engineer라는 매개변수와 값을 보낸다. 이를 확인한 서버는 요청과 매개변수에 맞는 작업을 수행한 후 그 자리에서 html 파일을 구성하거나 템플릿 html 파일에서 적절한 값을 대체하는 방식으로 html을 구성해 리턴한다. 따라서 어떤 클라이언트가 요청하든 같은 응답을 리턴하는 정적 웹 서버와 달리 동적 웹 서버는 클라이언트가 누군지, 어떤 매개변수를 보내는지에 따라 같은 요청이라도 다른 응답을 받을 수 있다.
각 요청과 매개변수에 따라 로직을 작성하는 것이 대부분의 백엔드 개발자가 해야 할일이다. 그러나 유추할 수 있듯이 비즈니스 요구사항에 따라 이 로직은 변한다. 그러므로 개발자들은 아파치나 Nginx 같은 서버 프로그램을 사용하지 못한다. 그렇다면백엔드 개발자들은 처음부터 끝까지 소켓 프로그래밍, HTTP 파싱, 스레드 풀 관리 등모든 것을 새로 다 작성해야 한다는 말인가?다행히 자바 프로그램 중 동적 웹 서버 구현을 도와주는 프로그램이 있다. 바로 서블릿 엔진이다. 아파치 톰캣이 서블릿 엔진에 해당한다.
1.2.6 자바 서블릿 컨테이너/엔진
서블릿 컨테이너 또는 서블릿 엔진은 서버 프로그램이다. 개발자들은 서블릿 엔진을 설치한 후 서블릿 엔진에게 자기가 개발한 비즈니스 로직, 즉 클래스 파일과 해당 클래스 파일을 어느 요청에서 실행해야 하는지 알려줘야 한다. 서블릿 엔진이 이해할 수 있는 형태로 클래스 파일을 작성해야 한다. 구체적으로 서블릿 엔진이 이해할 수 있는 클래스란 javax.servlet.http.HttpServlet 의 상속받는 서브 클래스를 의미한다.
⭐ 스프링 부트도 내부적으로는 서블릿 엔진의 사용을 위해 서블릿을 상속 및 구현한다.
서블릿 컨테이너(Servlet Container) 또는 서블릿 엔진(Servlet Engine)은 Java 기반 웹 애플리케이션을 실행할 수 있는 서버 프로그램으로, 클라이언트의 HTTP 요청을 받아서 Java Servlet 클래스를 실행하고 응답을 반환하는 역할을 수행한다.
🔧 서블릿 컨테이너의 핵심 역할
요청 수신 | 클라이언트로부터 HTTP 요청을 받아들이고 적절한 서블릿에 매핑 |
서블릿 생명주기 관리 | init(), service(), destroy() 메서드를 호출하여 서블릿 인스턴스 관리 |
멀티스레드 처리 | 클라이언트 요청마다 새로운 스레드 생성하여 병렬 처리 가능 |
HTTP 프로토콜 처리 | HTTP 요청 파싱 및 응답 생성 기능 제공 (HttpServletRequest, HttpServletResponse) |
보안, 인증 지원 | 필터(Filter), 보안 제약 설정 등을 통해 요청 제어 가능 |
로깅 및 에러 처리 | 로그 기록 및 예외 처리 메커니즘 제공 |
🏗️ 서블릿 컨테이너 구조
- 웹 서버 역할
- HTTP 요청을 수신
- 요청 URL에 따라 서블릿으로 라우팅
- 서블릿 매핑
- web.xml 또는 애노테이션(@WebServlet)을 통해 어떤 URL이 어떤 서블릿에 매핑되는지 설정
- 서블릿 실행 흐름
클라이언트 -> HTTP 요청 -> 서블릿 컨테이너 -> HttpServlet 서브 클래스 -> 응답 반환
📁 실무에서의 구조 예시
MyWebApp/
├── WEB-INF/
│ ├── web.xml ← 서블릿 매핑 정보
│ └── classes/
│ └── com/example/MyServlet.class ← HttpServlet 상속 클래스
<!-- web.xml 예시 -->
<servlet>
<servlet-name>hello</servlet-name>
<servlet-class>com.example.HelloServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>hello</servlet-name>
<url-pattern>/hello</url-pattern>
</servlet-mapping>
🌐 대표적인 서블릿 컨테이너
Apache Tomcat | 가장 널리 쓰이는 오픈소스 서블릿 컨테이너 |
Jetty | 가볍고 임베디드 가능하여 많이 쓰임 |
Undertow | WildFly 기반, 비동기 처리에 강점 |
GlassFish | Java EE 참조 구현 서버로, 서블릿 포함 |
'React.js, 스프링 부트, AWS로 배우는 웹 개발 101' 카테고리의 다른 글
[TIL] 25/01/28, Service Layer : Business Logic (0) | 2025.01.29 |
---|---|
[TIL] 25/01/27, REST API (0) | 2025.01.28 |
[TIL] 25/01/26, 백엔드 서비스 아키텍처 (0) | 2025.01.26 |
[TIL] 25/01/25, build.gradle 속성 (0) | 2025.01.25 |
[TIL] 25/01/20, Todo 웹 애플리케이션 기능 (0) | 2025.01.20 |