1. 왜 지금 '옛날 기술'을 공부해야 할까?
신입 개발자나 최신 프레임워크 위주로 공부한 분들에게 JSP 기반의 Controller 구조는 마치 박물관에서나 볼 법한 유물처럼 느껴질 수 있습니다. 하지만 현실은 다릅니다. 국가 망을 지탱하는 공공기관 시스템, 거대 기업의 레거시(Legacy) 인프라, 혹은 오랫동안 안정적으로 운영되어 온 금융권 프로젝트에 투입되면 우리는 여전히 10년, 20년 된 코드들과 마주하게 됩니다.
현대적인 Spring MVC나 Spring Boot의 근예(Roots)가 바로 여기서 시작되었기에, 이 구조를 이해하는 것은 단순히 과거를 공부하는 것이 아니라 "웹 서비스가 어떻게 발전해 왔는가"를 깨닫는 과정입니다. 오늘은 언젠가 반드시 마주할 그 이름, JSP Model 1과 Model 2 구조를 파헤쳐 보겠습니다.
2. JSP Model 1: 빠르지만 위험한 동거
초기 웹 개발에서 가장 흔했던 방식입니다. 별도의 컨트롤러 클래스 없이 JSP 페이지가 사용자의 요청을 받고, 비즈니스 로직(자바 코드)을 처리하고, 응답(HTML)까지 내보내는 구조입니다.
특징과 동작 원리
사용자가 요청을 보내면 JSP 내부에 선언된 <% ... %>(스크립틀릿) 안에 자바 코드가 직접 들어갑니다. 이 코드 안에서 데이터베이스 연결(DAO)을 호출하고, 결과를 받아와 같은 페이지 하단의 HTML에 뿌려줍니다.
- 장점: 구조가 매우 단순합니다. 작은 기능을 만들 때 파일 하나만 만들면 끝이기에 개발 속도가 빠릅니다.
- 단점: 화면(View)과 로직(Logic)이 한곳에 뒤섞여 있습니다. 코드가 1,000줄이 넘어가면 가독성은 처참해지고, 유지보수는 불가능에 가까워집니다. 특히 디자이너와 협업할 때 자바 코드가 섞인 JSP 파일을 건드려야 하므로 사고가 잦았습니다.
3. JSP Model 2 (MVC): 질서의 탄생
Model 1의 대혼란을 해결하기 위해 등장한 것이 바로 Model 2입니다. 우리가 현재 사용하는 MVC(Model-View-Controller) 패턴의 웹 버전이라고 보시면 됩니다. 핵심은 "역할 분담"입니다.
역할 분해
- Controller (Servlet): 모든 요청의 관문입니다. 사용자의 요청이 오면 어떤 비즈니스 로직을 수행할지 결정하고, 데이터를 가공한 뒤 적절한 JSP 페이지로 넘깁니다. (주로 서블릿 클래스로 구현)
- Model (JavaBean/Service/DAO): 실제 데이터베이스 작업과 비즈니스 로직을 수행합니다. 순수 자바 클래스로 구성됩니다.
- View (JSP): 컨트롤러가 넘겨준 데이터를 화면에 출력만 합니다. 자바 코드는 최소화하고 EL(Expression Language)이나 JSTL을 사용하여 깔끔한 HTML을 유지합니다.
동작 로직
사용자가 요청을 보내면 서블릿(Controller)이 이를 가로챕니다. 서블릿은 필요한 데이터를 모델(Model)에 요청해 받아온 뒤, 이를 request 객체에 담습니다. 그리고 RequestDispatcher를 이용해 화면을 그려줄 JSP(View)로 포워딩(Forwarding)합니다.
4. 레거시 코드에서 자주 보이는 'Action' 구조
공공기관 프로젝트나 오래된 프레임워크(예: Struts 1.x) 기반 코드에서는 Action이라는 개념이 자주 등장합니다. 이는 서블릿 하나가 너무 거대해지는 것을 막기 위해 기능을 쪼갠 형태입니다.
- Front Controller: 모든 요청을 일단 받는 대표 서블릿 (예: DispatcherServlet의 조상격)
- Action Class: 특정 기능(예: LoginAction, ListAction)을 수행하는 전담 클래스
이 구조를 이해하면 현대의 @Controller 안의 메서드 단위 분리가 과거에는 클래스 단위로 이루어졌음을 알 수 있습니다. 파일이 너무 많아 복잡해 보일 수 있지만, 로직이 명확히 분리되어 있어 Model 1보다는 훨씬 진보된 형태입니다.
5. 현대 개발자가 이 구조를 마주했을 때의 전략
만약 여러분이 이런 프로젝트에 투입된다면 당황하지 말고 다음 세 가지만 기억하세요.
- 비즈니스 로직의 위치를 찾아라: JSP 안에 로직이 있다면(Model 1), 함부로 건드리기보다 로직을 별도의 자바 클래스로 추출(Refactoring)하려는 노력이 필요합니다.
- 데이터 전달 흐름을 파악하라: 컨트롤러에서 setAttribute()로 넘긴 데이터가 JSP에서 어떻게 출력되는지(getAttribute() 또는 ${...}) 흐름만 알면 전체 구조가 보입니다.
- 공통 필터와 서블릿 설정을 확인하라: web.xml 파일은 이 옛날 구조의 지도와 같습니다. 어떤 서블릿이 어떤 URL을 담당하는지 여기서부터 시작하세요.
6. 결론: 과거를 알아야 미래가 보인다
지금 우리가 누리는 @RequestMapping이나 Thymeleaf, React 같은 기술들은 모두 과거의 불편함을 해결하기 위해 탄생했습니다. JSP Model 1의 혼란을 거쳐 Model 2의 질서를 세우고, 이를 자동화하며 Spring MVC가 완성되었습니다.
오래된 코드는 "나쁜 코드"가 아닙니다. 그 시절 최선의 고민이 담긴 결과물입니다. 이를 이해하고 다룰 줄 아는 개발자는 어떤 환경에서도 살아남는 '진짜 실력자'가 될 것입니다. 다음 포스팅에서는 실제 레거시 프로젝트를 분석하며 실무에서 마주할 구체적인 코드 패턴을 다뤄보겠습니다.
'TECH > 웹개발' 카테고리의 다른 글
| 당신의 서비스가 '안전하지 않음'이라고 뜨는 이유: HTTPS라는 거대한 신뢰의 마법 (0) | 2026.03.24 |
|---|---|
| [1인개발] 월급 외 수익 월 100만 원, 2026년 수익형 웹 서비스 구축 전략 (0) | 2026.03.23 |
| 웹 성능과 유지보수를 위한 선택: Page-centric design이 유리한 의외의 상황들 (0) | 2026.03.21 |
| [Spring Boot] 주기적인 작업 자동화, 스케줄러(Scheduler) 완벽 가이드 (0) | 2026.03.20 |
| [Spring] "분명 붙였는데 왜?" — @Transactional이 미작동하는 7가지 모든 사례 (0) | 2026.03.19 |