목차
Servlet의 등장 (1997)
등장 이유 :
- 1990년대 후반 CGI(Common Gateway Interface)는 각 요청마다 프로세스를 새로 생성해야 했기 때문에 성능 문제가 심각했습니다.
- 이를 해결하기 위해 자바 기반의 고성능, 멀티스레드 방식 웹 서버 기술이 필요했습니다.
개요 :
- 자바로 작성된 서버 측 프로그램으로, 웹 요청을 처리하고 동적 콘텐츠를 생성합니다.
- `javax.servlet` 패키지를 기반으로 동작합니다.
- 서블릿 컨테이너 (ex: Tomcat) 위에서 실행됩니다.
단점 :
- HTML을 자바 코드 내에서 직접 작성해야 해 유지보수성, 가독성이 낮습니다.
- 비즈니스 로직과 뷰(HTML) 코드가 섞입니다.
CGI 기본 개념 요약
- CGI는 웹 서버가 외부 프로그램을 실행해서 동적인 콘텐츠를 생성하는 방식입니다.
- 각 HTTP 요청마다 외부 프로그램을 새로 실행합니다.
- 이 프로그램은 보통 Perl, Python, Bash, C 같은 스크립트 언어나 시스템 언어로 작성됩니다.
파이썬 CGI 예시 코드
# hello.py
#!/usr/bin/env python3
print("Content-Type: text/html\n")
print("<html><body><h1>Hello from Python CGI</h1></body></html>")
- 누군가 웹사이트에 접속해서 `hello.py`를 요청 → 웹 서버는 Python 인터프리터를 실행해서 hello.py를 한번 실행합니다.
- 또 누군가 접속해서 `hello.py`를 요청 → 다시 Python 인터프리터를 실행해서 똑같은 파일을 또 실행합니다.
- 그래서 사용자 100명이 동시에 접속하면 Python 인터프리터도 100번이 실행됩니다. (문제!!)
동작 방식
- 사용자가 웹 브라우저에서 `http://example.com/cgi-bin/hello.pl` 요청
- 웹 서버는 `hello.pl`을 별도의 프로세스로 실행합니다.
- 이 프로세스가 출력한 텍스트(HTML)를 웹 서버가 받아서 응답으로 클라이언트에 전송합니다.
- 다음 요청이 오면 또 새로 실행합니다. (비용이 큼)
성능 문제가 생기는 이유
- 매 요청마다 프로세스를 fork/exec하는 비용 발생합니다.
- 메모리와 CPU 자원을 낭비합니다.
- 대량의 동시 요청을 감당하기 어렵습니다.
자바 Servlet 예시 코드
import java.io.IOException;
import javax.servlet.*;
import javax.servlet.http.*;
@WebServlet("/hello")
public class HelloServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html;charset=UTF-8");
response.getWriter().println(
"<html>" +
"<body>" +
"<h1>Hello from Servlet!</h1>" +
"</body>" +
"</html>"
);
}
}
- 이 서블릿은 브라우저에서 접속하면 "Hello from Servlet!"이라는 HTML을 출력합니다.
Servlet 동작 방식

- 브라우저가 URL로 `/hello` 요청(request)을 보냅니다.
- 요청을 받은 Servlet 컨테이너는 `HttpServletRequest`, `HttpServletResponse` 객체를 생성합니다.
- `web.xml`이나 어노테이션(@WebServlet)으로 URL 매핑된 서블릿 클래스를 찾습니다.
- 서버는 `HelloServlet` 인스턴스를 한번만 생성(Singleton Pattern)하고 재사용(새 스레드로 처리)합니다.
- `response.getWriter()`를 통해 HTML 응답을 생성한 뒤 `HttpServletResponse` 객체에 응답을 담아 Client(브라우저)에 반환합니다.
- 응답이 완료되면 생성한 `HttpServletRequest`, `HttpServletResponse` 객체를 소멸합니다.
CGI vs Servlet 비교 요약
항목 | CGI(Common GateWay Interface) | Servlet (Java Servlet) |
실행 방식 | 요청마다 새로운 프로세스 생성 | 한번 로드 후, 요청마다 새로운 스레드 실행 |
언어 | Perl, Python, C 등 스크립트 언어 | Java 기반 |
성능 | 낮음 (프로세스 생성 비용 큼) | 높음 (경량 스레드 처리) |
유지보수 | 파일 기반, 분산되어 있어 어려움 | 클래스 기반, 구조화되어 있어 용이 |
JSP (Java-Server Pages)
등장 이유 :
- 서블릿의 단점을 일부 보완하고, HTML 내에서 자바 코드를 삽입해 보다 직관적으로 웹 페이지를 만들기 위해 1999년 등장했습니다.
개요 :
- HTML 파일에 자바 코드를 삽입하는 방식 (`<% %>`문법 사용).
- 최초 요청 시 서블릿으로 변환되어 실행되었습니다.
- 표현과 로직을 분리하는 시도가 가능해졌지만 한계가 있었습니다.
단점 :
- 자바 코드가 HTML에 섞여 코드가 지저분해졌습니다.
- 로직과 뷰과 여전히 완전히 분리되지 않았습니다.
- 대규모 프로젝트에선 코드 관리가 어렵습니다.
JSP 코드 예시
<%@ page contentType="text/html;charset=UTF-8" %>
<html>
<head>
<title>회원 목록</title>
</head>
<body>
<h1>회원 목록</h1>
<ul>
<%
// 자바 로직이 직접 들어감 (데이터 조회)
List<String> members = new ArrayList<>();
members.add("홍길동");
members.add("김철수");
members.add("이영희");
for(String member : members) {
%>
<li><%= member %></li>
<%
}
%>
</ul>
</body>
</html>
- 로직(데이터 생성/처리)과 뷰(HTML 출력)이 한 파일에 섞여있다. (완벽하게 분리되지 않은 예시)
JSP 동작 방식 (서블릿과 연결)
- 브라우저가 `/hello.jsp` 요청
- JSP 엔진이 `.jsp` 파일을 `.java` 파일로 변환
- 그 `.java` 파일을 컴파일하여 `.class` 파일로 생성
- 서블릿으로 동작 → 결과 HTML을 클라이언트에 전송
Servlet과 JSP 구조 및 문제점

- 위에서와 다르게 Servlet만을 사용한 경우, View를 위한 코드와 비지니스 로직을 처리하는 코드가 Servlet에 모두 존재하여 유지보수가 어려워집니다
- 그래서 JSP를 사용하여 View를 분리하였지만 비지니스 로직의 일부가 JSP 파일 안에 존재합니다. 여전히 책임이 많아 유지보수가 어렵습니다.
Servlet, JSP 기반의 MVC 패턴 도입
개요 :
- MVC 패턴이 도입되면서, UI, 비지니스 로직, 데이터를 분리하여 개발하는 방식이 등장했습니다.
- Servlet은 주로 컨트롤러(비지니스 로직)로 사용되었고, JSP는 뷰(UI)를 담당하게 되었습니다.
장점 :
- MVC 패턴은 웹 애플리케이션의 유지보수성과 확장성을 크게 향상시켰습니다.
단점 :
- 개발자가 중복적으로 설정해줘야 하는 부분들이 다수 발생했습니다.
MVC 패턴 (Model-View-Controller Patttern)
Model-View-Controller의 약자로, 소프트웨어 디자인 패턴 중 하나입니다. 특히 웹 애플리케이션 구조 설계에서 자주 사용되며, 역할을 분리하여 유지보수성과 확장성을 높이는 것이 주 목적입니다.
핵심 내용
- View가 분리된 이유의 핵심은 변경입니다.
- 기획이 변하지 않는 이상 비즈니스 로직과 View의 수정 원인은 별개로 발생합니다.
- 화면 구성에 수정이 발생하면 View만 변경
- 요구사항에 수정이 발생하는 경우 비즈니스 로직 변경
- 즉, 서로 연관이 없는 코드끼리 함께 존재할 필요가 없습니다. → 완전히 분리하자. (역할 분리)
MVC 패턴 구조

MVC 구성요소
1. Model (모델) : 애플리케이션의 데이터와 비즈니스 로직을 담당하는 객체입니다.
- 데이터베이스와 직접 연동하거나 데이터를 처리하는 역할
- 예: 회원 정보, 게시글, 주문 정보 등
2. View (뷰) : 사용자에게 출력(화면)을 보여주는 역할입니다.
- HTML, JSP, Thymeleaf, React, Vue 등 다양한 템플릿/프론트엔드 기술을 사용할 수 있습니다.
- 사용자 인터페이스(UI)를 구성합니다.
- 로직 없이 표현만 담당해야합니다.
3. Controller (컨트롤러) : 사용자의 요청을 받고, 모델과 뷰를 연결해주는 중재자 역할의 객체입니다.
- Controller는 Servlet에 해당됩니다.
- 사용자의 입력(HTTP 요청)을 받고, 파라미터 검증을 한 후, 비즈니스 로직을 실행한 다음,
- 비즈니스 로직을 실행합니다.
- View에 전달할 결과를 조회하여 Model 객체에 임시로 저장합니다.
- 예 : URL 요청을 받아 어떤 데이터를 조회하고 어떤 화면을 보여줄지 결정합니다.
MVC 프레임워크의 등장 : Struts, Spring MVC (2000~2010)
등장 이유 :
- 웹 애플리케이션의 규모가 커지고 복잡해지면서, 명확한 구조와 분리된 책임이 필요해졌습니다.
- JSP/Servlet만으로는 생산성과 유지보수성이 떨어집니다.
개요 :
- Struts (2000년 초반) : 최초의 대중적인 자바 MVC 프레임워크
- Spring MVC : Spring Framework의 일부분으로, 보다 유연하고 확장성이 뛰어난 구조를 제공합니다
- MVC(Model-View-Controller) 패턴을 기반으로 합니다.
단점 :
- 초기 설정이 복잡했습니다 (Spring 3 이전까지)
- 개발 속도가 느릴 수 있습니다 (설정 및 구조 이해 필요)
웹 서버 설정
- 보통은 Tomcat 같은 서버를 따로 설치하고, 설정 파일(`web.xml`)도 만들어야 합니다.
스프링 설정 파일 작성 (web.xml)
<!-- web.xml에서 서블릿 등록 -->
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
<!-- struts-config.xml -->
<action-mappings>
<action path="/login"
type="com.example.LoginAction"
name="loginForm"
scope="request"
input="/login.jsp">
<forward name="success" path="/home.jsp"/>
<forward name="failure" path="/login.jsp"/>
</action>
</action-mappings>
- 이런 식으로 여러 개의 XML 파일에서 각각의 요청 경로, 액션 클래스(비즈니스 로직 처리 클래스), 뷰 페이지 등을 일일이 매핑해줘야 했습니다.
- 페이지가 많아질수록 설정 파일도 덩달아 커지고 복잡해졌습니다.
라이브러리 의존성 관리
- 어떤 라이브러리가 필요한지 직접 찾아서 pom.xml이나 build.gradle에 하나하나 추가합니다.
- 웹 개발에 필요한 모든 것들을 직접 찾아서 직접 버전을 맞춰 추가해야했습니다. (엄청 피로)
프로젝트 구조 관리
- 여러 설정 파일, 자원 위치를 일일이 맞춰야 했습니다.
Annotaion 기반의 Spring MVC (2007~현재)
개요 :
- Annotaion을 통해 애플리케이션 설정의 복잡함을 줄여줍니다.
장점 :
- 더 직관적이고 간결한 방식으로 웹 애플리케이션을 개발할 수 있게 되었습니다.
1. 설정 방식이 XML에서 자바(Annotaion) 기반으로 대폭 개선
@Controller
public class HelloController {
@RequestMapping("/hello")
public String sayHello(Model model) {
model.addAttribute("message", "Hello Spring 3+");
return "hello"; // 뷰 이름 (ex. hello.jsp)
}
}
- 기존에 XML에 모든 URL 매핑, 컨트롤러, 뷰 리졸버 등을 일일이 작성하던 방식에서 `@Controller`, `@RequestMapping` 같은 어노테이션(Annotation)을 활용해 코드 내에 직접 선언할 수 있게 되었습니다.
- 설정파일이 대폭 줄고, 코드와 설정이 가까워져서 유지보수 쉬워졌습니다.
2. `@EnableWebeMvc`와 `WebMvcConfigurer`로 기본 설정을 간편하게 처리
@Configuration
@EnableWebMvc
@ComponentScan("com.example.controller")
public class WebConfig implements WebMvcConfigurer {
// 필요한 설정만 추가로 작성
}
- `@EnableWebMvc` : 필요한 컴포넌트를 자동으로 등록할 수 있습니다.
- `WebMvcConfigurer` : 여러 메서드를 오버라이드해서(재정의해서) 기본 동작에 추가하거나 바꿀 수 있습니다.
컴포넌트란 : 독립적인 기능을 가진 부품이나 모듈
@Component
public class MyService {
// 서비스 역할을 하는 컴포넌트
}
- 컴포넌트로 표시된 클래스들은 스프링이 자동으로 찾아서 필요할 때 만들어주고 연결해 줍니다.
3. `@RestController` 등장으로 REST API 개발이 간편
@RestController
public class ApiController {
@GetMapping("/api/data")
public Map<String, String> getData() {
return Collections.singletonMap("message", "Hello REST");
}
}
- 기존에 JSP 등 뷰를 반환하는 컨트롤러와 별개로 JSON, XML 등의 데이터를 직접 반환하는 RESTful API 개발도 쉽게 가능해졌습니다.
4. 템플릿 엔진 (Thymeleaf, FreeMaker 등) 쉽게 연동 가능
- JSP 외에 다양한 뷰 기술을 쉽게 적용할 수 있어서 자유도가 높아졌습니다.
Spring Boot의 등장 (2014~현재)
개요 :
Spring 프레임워크를 보다 쉽게 사용하도록 만든 도구로, 설정과 복잡한 초기 설정 작업을 자동화했습니다.
내장 Tomcat을 가지고 있습니다.
장점 :
개발자들이 빠르게 애플리케이션을 개발할 수 있도록 도와줍니다.
내장 서버 제공
- Tomcat, Jetty 등 서버를 애플리케이션 안에 포함해서, 따로 서버 설치/설정 없이 java -jar로 바로 실행 가능.
자동 설정(Auto-Configuration)
- 프로젝트에 추가한 라이브러리를 분석해서, 필요한 설정을 자동으로 만들어줌
- 예: 데이터베이스 라이브러리 있으면 자동으로 DB 연결 설정
- 웹 라이브러리 있으면 웹 서버 설정 자동 완료
스타터(Starter) 의존성 제공
- 여러 관련 라이브러리를 묶은 패키지를 제공해, 필요한 기능을 쉽게 추가 가능 (spring-boot-starter-web 등)
- 모든 스타터 버전을 호환되게 미리 정리해 두 었기 때문에 일일이 버전을 맞추거나 충돌을 걱정할 필요가 없습니다.
간단한 실행
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@SpringBootApplication // Spring Boot 자동 설정 시작 어노테이션
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args); // 내장 서버 실행
}
@RestController // REST API용 컨트롤러
class HelloController {
@GetMapping("/hello")
public String hello() {
return "Hello, Spring Boot!";
}
}
}
- 복잡한 설정 없이도 몇 줄 코드로 애플리케이션 시작 가능합니다.
- 빌드 후 `java -jar yourapp.jar`로 실행하면 내장 톰캣 서버가 켜지고 웹 브라우저에서 `http://locathost:8080/hello`에 접속하면 "Hello, Spring Boot!" 메시지 확인 가능합니다.
'JAVA' 카테고리의 다른 글
[Java] Lombok 라이브러리 (0) | 2025.05.10 |
---|---|
[Java] Optional (0) | 2025.05.04 |
[Java] 동등성과 동일성 (0) | 2025.05.04 |
[Java] Enum (0) | 2025.05.04 |
[Java] Lv_4 도서관 프로젝트 (0) | 2025.05.02 |