웹 백엔드 개발자가 되기 위해서는 단순히 기술을 “사용할 줄 아는 것”을 넘어, 기술의 한계와 개선 과정을 이해하고 이를 구조적으로 정리할 수 있는 역량이 중요하다고 생각했다.
서블릿(Servlet)부터 시작해 JSP, 그리고 MVC 패턴까지 직접 구현하며 체득한 경험을 토대로,
• 어떤 문제가 있었고
• 그걸 어떻게 해결했으며
• 무엇을 배우게 되었는지
하나하나 기록해보았다.
웹 애플리케이션 아키텍처의 진화 과정을 겪고 정리한 내용이다.
추후에 스프링 mvc 를 배울때 더 폭넓은 사고를 가지고 배울 토대를 마련하기위해 학습하고 정리한다.
순수하게 서블릿(Servlet)으로 요청을 받고, HTML도 자바 코드 안에서 다 작성했다. 브라우저에서 요청이 들어오면, HttpServlet 클래스를 상속한 자바 클래스가 doGet/doPost 메서드로 이를 처리하는 구조였다.
@Override
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
response.setContentType("text/html");
response.getWriter().write("<html><body>Hello Servlet</body></html>");
}
JSP를 사용하면 HTML 안에서 자바 코드를 <% %> 안에 넣을 수 있었다. JSP 파일은 Servlet으로 변환되어 실행된다.
<%
String name = request.getParameter("name");
%>
<html>
<body>
<h1>Hello <%= name %></h1>
</body>
</html>
html 이 서블렛 객체 안으로 들어가는 것은 해결 됬지만 여전히 비지니스 로직이 분리되지 못했다. 따라서 비지니스 로직은 서블릿으로, 화면 담당은 jsp로 나누고자 mvc패턴을 사용하게 되었다.
Model, View, Controller 역할을 나누어 관심사를 분리했다. 서블릿은 Controller 역할만 수행하고, JSP는 View만 담당, Model은 데이터 처리만 하도록 구성했다.
String username = request.getParameter("username");
int age = Integer.parseInt(request.getParameter("age"));
Member member = new Member(username, age);
memberRepository.save(member);
// 데이터를 뷰로 넘기기 위해 request에 담기
request.setAttribute("member", member);
// JSP로 forward
String viewPath = "/WEB-INF/views/save-result.jsp";
RequestDispatcher dispatcher = request.getRequestDispatcher(viewPath);
dispatcher.forward(request, response);
<html>
<body>
<p>회원 저장 완료</p>
<ul>
<li>이름: ${member.username}</li>
<li>나이: ${member.age}</li>
</ul>
</body>
</html>

이미지 출처 : https://seongwon.dev/ETC/20211207_MVC%ED%8C%A8%ED%84%B4%EC%9D%B4%EB%9E%80/
| 구분 | 한계점 | 해결 방법 |
|---|---|---|
| Servlet | HTML과 자바 코드가 섞여 유지보수가 어려움 | JSP 도입 |
| JSP | 로직과 뷰가 분리되지 않아 복잡해짐 | MVC 패턴으로 역할 분리 |
| MVC | 구조는 복잡하지만 관심사가 명확하게 분리됨 | 유지보수 용이, 확장성 증가 |
이 과정을 거치면서 웹 서버가 어떻게 동작하는지, 요청-응답 흐름이 어떻게 구성되는지, 역할 분리의 중요성을 몸으로 익혔다. 단순히 기술을 배우는 것을 넘어서, 구조적으로 사고하고 유지보수 가능한 코드를 작성하는 기반을 다지게 된 시간이었다.
MVC 패턴을 직접 구현해보면서 Spring MVC로 자연스럽게 이어질 수 있는 흐름도 이해할 수 있었고, 앞으로 프레임워크를 사용할 때도 내부 동작 원리를 더 잘 이해하고 활용할 수 있을 것 같다.