목차
- Http
- Servlet
- 템플릿엔진
- MVC패턴
- SpringWebMvc
1. HTTP
HTTP 프로토콜은 모든 것을 웹을 통해서 통신하고 있는 21세기 지금 없어서는 안되는 중요한 규약이다. HTTP프로토콜의 중요성을 생각할 때 그 이미지를 상상해보자면 굉장히 복잡한 무엇이 떠오르기 마련이지만 실제 프로토콜의 메시지 구조를 확인해보면 프로토콜 상태코드, 메타정보를 가지고 있는 헤더, 실제 보내거나 받을 정보인 바디라는 세가지 문자열 조합의 나열이다.
문자열의 조합이 HTTP프로토콜이라는 점을 생각해볼 때 통신을 하기위해서 개발자가 직접 HTTP문자열을 만드는 문자열의 나열을 작성하거나, 혹은 HTTP프로토콜을 만들어주는 함수를 직접 만들어 사용하는 방법을 생각할 수 있다. 그런데 모든 것을 직접 만들어 사용하는 것은 20세기 대량생산 체제가 탄생한 Ford社의 컨베이어혁신 이전 분업화가 존재하지 않았을 때 정답이었던 너무나도 고전적인 방법이다. 그리고 그렇게 모든 문자열을 직접 작성하는 방법은 비록 함수로 만들었다고 해도 핵심도메인이나 비즈니스 로직에 개발자가 집중하지 못하게 하는 한계를 낳는다. 이를 해결하기 위한 자바진영의 방법이 바로 서블릿이다.
2.서블릿
스니펫이란 프로그래밍 용어가 있다. 재사용 가능한 소스코드나 텍스트의 부분을 일컫는 말이다. 한가지 예로 IntelliJ같은 IDE에서는 psvm이라고 기술한 후 엔터를 누르면 자바의 main메서드가 작성된다 서블릿의 기능도 이와 크게 다르지 않다. 서블릿 기술로 작성되어진 서버에 일련의 프로토콜을 보내면 서블릿에서 이를 읽어 HTTP Request와 Response 문자열을 작성해준다. 개발자가 할 일은 그 문법에 맞춰서 Request 내부에 있는 메타정보인 헤더에 데이터를 읽거나 Response로 보낼 바디를 html 태그로 손수 만들어 담아 보내주면 서블릿이 해당 데이터를 읽어 알맞게 Http프로토콜에 맞는 문자열을 작성해 클라이언트에게 보내주고 그에 상응하는 View를 그려준다.
서블릿 덕분에 한결 편해졌다. 어느정도 분업화가 진행된 것 같다. 하지만 아직 부족하다. Java클래스 내부에서 클라이언트에게 보여줄 화면을 작성하기 위해 문자열로 html태그를 작성해서 클라이언트에게 보내 줘야한다. 문자열로 작성해 클라이언트에게 보내기에 컴파일 오류로 태그를 잘 작성했는지 파악할 수 없는 불편함은 차치하고서라도 Java 클래스 내부에서 View를 그리는 작업은 구조적으로 문제가 있어 보인다. 또한 동적으로 보낼 데이터는 태그를 제외한 비즈니스 도메인 이나 유저정보 뿐인데 이를 위해서 정적인 html태그를 매번 그려야 하는 자원낭비와 길어지는 문자열로 인한 유지보수의 어려움까지… 개발자에겐 더 나은 분업화와 추상화가 필요해 보인다.
3. 템플릿엔진
서버개발자들이 자주 다루었던 JSP( Java Server Page )는 템플릿 엔진이다. 그리고 이를 대체하여 요즘 많이 사용하는 Thymeleaf 역시 Spring진영의 공식 템플릿 엔진이다. 이렇듯 우리가 친숙하게 사용하는 템플릿 엔진은 앞서 말했던 몇 가지 서블릿의 단점들을 해소하기 위해 나온 기술이다. 자바 클래스 내부에서 View를 그리던 방법은 템플릿 엔진 파일로 클래스 외부로 빼내 구현했기에 둘은 구분 되고, 정적인 html태그를 매번 그려야 하는 한계를 대표적인 템플릿 엔진인 JSP의 경우 jsp 확장자 파일 에 html을 작성하고 그 파일에서 Java 문법을 사용해 Domain로직을 동적으로 집어넣는 방식으로 해결하여 앞선 단점들을 해소했다.
개발자들은 이제 로직은 자바문법으로 해결하고 정적인 html태그는 태그작성 문법으로 두가지 역할이 독립된 효율적인 코딩이 가능하게 되었다. 하지만 이내 바로 문제가 생겼다. Jsp내부에서 화면과 데이터를 그리는 것을 한번에 한다는 것은 두 역할의 결합도가 올라간다는 뜻이다. 요청을 받은 서버가 클라이언트에게 응답을 주는 일련의 흐름(lifecycle)에서 필요한 데이터를 만들어 제공할 때 데이터를 만들어내는 흐름과 화면에 그 데이터를 보여주는 흐름의 시점은 서로 다를 수 밖에 없다. 보통 만들어내는 것이 보여주는 것에 선행한다. 데이터를 작성하고 보여주는 서로 다른 두 추상화 레벨을 한 파일에서 작성하고 있으니 결합도가 올라가고 이에 복잡성이 올라가고 그러기에 유지보수성은 굉장히 취약해진다. 2022년 올해 3월쯤 프로젝트를 진행할 때 3천줄 이상의 Jsp파일을 본적이 있다. 그때의 느낌은 코드가 마치 얽히고설킨 실뭉치와 같아 이를 살살 풀어내 그 실을 재사용하는 것 보다 새로운 실을 구매 하는게 더 빠른 문제 해결 방식으로 보였다.
4. MVC패턴
앞서 말한 템플릿 엔진으로 데이터를 만드는 흐름과 데이터를 보여주는 흐름을 한곳에서 작성해서 오는 유지보수의 복잡성은 기술적 한계라고 보기는 힘들 것 같다. 각자의 맡은 역할을 비교적 쉽게 나눌 수 있기에 흐름을 잘 나누어 작성해 놓는 규칙을 만들어 그 규칙을 잘 지키게 한다면 어떨까 그 대표적인 규칙 중 우리가 이야기 해볼 규칙이 MVC이다.
클라이언트에게 필요한 데이터를 비즈니스 로직에서 만들고 그 데이터를 담는 모델, 화면을 그려주는 뷰, 모델과 뷰의 응집도를 책임지는 컨트롤러를 나누는 구조(아키텍처)가 MVC패턴이다. 이 구조는 데이터를 만들어내는 흐름과 데이터를 보여주는 흐름을 구조적으로 나누어 구현하게 한다. 이에 따라 결합도는 낮아지게 되며 유지보수성은 올라가게 된다. 템플릿 엔진만으로 서버코드를 작성하는 한계는 이 구조를 사용함으로써 해결할 수 있다.
데이터를 만들어 모델에 담아 화면으로 보낼 때 모든 컨트롤러가 하는 동작이 겹치는 걸 생각해보자 모든 컨트롤러가 어떤 화면으로 보내겠다는 코드와 모든 컨트롤러 마다 어떤 요청이 왔는지 로그를 넣는 코드와 같은 모든 컨트롤러가 사용하는 공통된 소스가 있을 것이다. 이 공통된 부분을 모두 처리하는 공통된 컨트롤러가 있다면 다른 컨트롤러에서는 해당 작업을 하지 않아도 될 것이다. Mvc패턴과 이 공통 컨트롤러라는 프론트 컨트롤러 패턴이 Spring Web Mvc 프로젝트의 핵심이다.
5.Spring Web Mvc
Spring Web Mvc프로젝트(이하 SpringMvc)는 DispacherServlet이라는 모든 컨트롤러 앞 단에 존재하는 프론트 컨트롤러가 존재한다. 이 프론트 컨트롤러에서 몇가지 공통적인 일련의 로직을 타고 클라이언트가 요청을 보낸 URI에 해당되는 컨트롤러로 보내진다. 여기서 말한 일련의 로직이 객체지향적으로 설계되었고 SOLID원칙을 준수하여 유연한 설계를 가능하게 했다는 점에서 현재 한국에서 많은 개발자가 그리고 해외에서도 아직도 Spring으로 대부분의 엔터프라이즈 어플리케이션 서버가 작성되고 있는 이유가 아닐까 한다.
일련의 공통 로직은 다음과 같다.
1. Spring으로 생성된 Bean중 스프링설정 또는 클라이언트 요청에 알맞는 핸들러를 찾아낸다.
2. 핸들러에 대응되는 어댑터를 찾아낸다.
3. 어댑터를 통해서 핸들러를 호출한다.
4. 핸들러 ( 컨트롤러 ) 가 처리해낸 비즈니스 로직을 받아온다.
5. 화면에 그리기 위해 알맞은 뷰리졸버를 호출한다.
6. 뷰를 렌더링한다.
7. 클라이언트에게 응답한다.
저 과정에서 2번과 3번그리고 5번을 보자 굉장히 유연한 스프링Mvc를 파악할 수 있다. 우선 한 클래스는 하나의 책임만을 가져야 한다는 단일 책임 원칙을 잘 고수하고 있다. 각 구현체들 (핸들러, 어댑터, 뷰리졸버) 자신의 책임 이상의 역할을 수행하지 않는다. 또한 각 핸들러는 같은 인터페이스를 상속받아 구현되어 있기에 새로운 핸들러가 필요하면 확장할 수 있고 각 핸들러의 변경에는 닫혀 있음을 볼 수 있다. 또한 각 구현체가 상속받은 인터페이스의 역할을 해낸다는 점에서 각 구현체들의 인터페이스의 메소드가 필요한만큼만 작성 되어있다는 점 마지막으로 Spring Core의 DI로 각 핸들러를 선택한다는 점에서 객체지향적으로 유연하게 작성되었다.
이렇게 유연하게 작성된 스프링 덕분에 우리는 서버 코드를 작성할 때 컨트롤러 앞 단의 Http통신으로 온 일련의 문자열 들의 처리방법을 구상 및 설계하여 만들어낼 필요 없이 추상화된 그 자체를 사용하며 이에 따라 어떤 프로젝트 에서는 어노테이션 기반으로 작성하거나 어떤 프로젝트에서는 RestFul한 API로 작성할 수도 또 다른 프로젝트 에서는 기존의 레거시를 버전업 하여 작성 할 수도 있게 되었다.
스프링MVC는 서블릿과 템플릿엔진 그리고 기존의 MVC구조의 한계를 해결하여 개발자가 비즈니스 로직 외적인 코드 작성으로부터 자유롭게 해주었다. 프로그래밍의 역사는 코드의 중복제거 라는 점을 볼 때 스프링MVC는 웹개발자들에게 큰 무기를 쥐여준 셈이다.
[참고자료]
- 인프런 강의 김영한, 스프링 MVC 1편 – 백엔드 웹 개발 핵심 기술
- 이일민, 『토비의 스프링3.1』
- 조영호, 『객체지향의 사실과 오해』
'프로그래밍 회고록 > Java & Spring' 카테고리의 다른 글
Spring에 Swagger 도입하기 (0) | 2024.04.19 |
---|---|
SpringBoot 2.4.1 이후 문법 변화에 따른 환경분리를 위한 설정파일 작성법 (0) | 2022.06.03 |
Apache Log4j2 보안이슈 와 문제해결 (0) | 2021.12.12 |
Java(Spring)와 JavaScript(vue.js)로 서버단 Mp3파일 클라이언트로 보내 재생하기 - 1.Java (2) | 2021.11.03 |
Java와 java_websocket library를 이용한 WebSocket Clinet쪽 통신방법 (0) | 2021.10.17 |