Published on

[ Spring ] servlet & spring web MVC

Authors
  • avatar
    Name
    유사공대생
    Twitter

서블릿 이전의 웹 어플리케이션

image

서블릿 이전의 웹 어플리케이션은 일반적으로 정적인 HTML 파일로 구성되어 있다. 웹 서버는 클라이언트(웹 브라우저)로부터 HTTP 요청을 받으면, 해당 요청에 대한 정적 HTML 파일을 찾아서 클라이언트에게 응답으로 전송했다. 이러한 방식은 웹 서버가 단순히 정적인 파일을 제공하는 역할을 수행하므로, 동적인 기능이나 데이터 처리에는 제한적이었다.

image

동적인 기능이 필요한 경우, 일반적으로 CGI(Common Gateway Interface)라는 방식이 사용되었었다. CGI는 웹 서버와 외부 프로그램 간의 통신을 가능하게 해주는 표준 프로토콜이었다. 웹 서버는 클라이언트의 요청에 따라 CGI 프로그램을 실행시키고, CGI 프로그램은 요청에 대한 동적인 처리를 수행한 뒤 그 결과를 웹 서버로 전달하고, 웹 서버는 클라이언트에게 해당 결과를 응답으로 전송했다.

image

CGI 방식은 웹 서버와 외부 프로그램 간의 매번 프로세스 생성과 통신을 필요로 하기 때문에, 성능과 확장성이 제한적이었다. 많은 요청이 동시에 발생하거나 복잡한 동적 처리가 필요한 경우, 서버 부하가 증가하여 응답 지연이 발생할 수 있었다.

서블릿의 등장은 이러한 문제들을 해결하고자 했다. 서블릿은 자바를 기반으로 하는 웹 애플리케이션 컴포넌트로, 웹 서버 내에서 실행되며 동적인 처리를 수행할 수 있다. 서블릿 컨테이너는 서블릿의 생명주기를 관리하고, 웹 서버와의 통신을 처리하여 효율적인 처리와 확장성을 제공한다. 또한, 서블릿은 자바 언어의 장점을 활용하여 다양한 기능과 라이브러리를 활용할 수 있었다.

서블릿

image

서블릿은 자바를 기반으로 하는 웹 애플리케이션 컴포넌트이다. 서블릿은 웹 서버 내에서 실행되며, 클라이언트로부터의 요청에 동적으로 응답을 생성하는 역할을 담당한다. 웹 서버와의 통신을 처리하고, 동적인 처리를 수행하는 자바 클래스이다.

서블릿은 javax.servlet.Servlet 인터페이스를 구현하여 작성되며, 서블릿 컨테이너라고 불리는 웹 애플리케이션 서버에서 실행된다. 서블릿 컨테이너는 서블릿의 생명주기를 관리하고, 클라이언트의 요청을 받아들이고 서블릿에 전달한 뒤 응답을 클라이언트에게 반환한다.

서블릿의 주요 기능

  1. 요청 처리: 클라이언트로부터의 HTTP 요청을 처리하고, 요청에 대한 동적인 처리를 수행한다. 서블릿은 요청에 대한 파라미터를 읽고, 필요한 작업을 수행한 뒤 응답을 생성한다.

  2. 응답 생성: 서블릿은 동적인 웹 페이지를 생성하거나, 데이터 처리를 수행하여 응답을 생성한다. HTML 코드를 생성하거나, 다른 서블릿이나 JSP와 같은 웹 컴포넌트와 협력하여 응답을 구성할 수 있다.

  3. 세션 관리: 서블릿은 클라이언트와의 상태를 유지하기 위해 세션 관리 기능을 제공한다. 세션을 사용하여 클라이언트의 상태 정보를 저장하고, 필요한 경우에 해당 정보를 조회하거나 수정할 수 있다.

  4. 데이터베이스 연동: 서블릿은 자바의 데이터베이스 연동 기능을 활용하여 데이터베이스와의 상호작용을 수행할 수 있다. 데이터베이스에 데이터를 조회, 추가, 수정, 삭제하는 등의 작업을 수행할 수 있다.

서블릿은 자바의 장점인 플랫폼 독립성, 객체지향적인 설계, 다양한 라이브러리 및 프레임워크의 활용 등을 제공한다. 또한, 서블릿은 멀티스레딩을 지원하여 동시에 여러 요청을 처리할 수 있으므로, 성능과 확장성 면에서도 우수한 성능을 발휘할 수 있다.

서블릿은 Java EE(Java Enterprise Edition, 이전에는 Java Platform, Enterprise Edition 또는 Java EE라고 불렸습니다) 스펙의 일부로 포함되어 있으며, 다양한 웹 애플리케이션 프레임워크와 함께 사용되어 많은 기능과 편의성을 제공한다. 서블릿은 웹 애플리케이션 개발에 널리 사용되며, 대규모 엔터프라이즈 시스템부터 작은 웹 애플리케이션까지 다양한 규모의 프로젝트에 적용된다.

서블릿의 생명주기

  1. 초기화(Initialization): 서블릿 컨테이너는 서블릿 인스턴스를 생성하고 초기화한다. 서블릿이 처음으로 요청되거나 서블릿 컨테이너가 시작될 때 한 번만 발생한다. 이 단계에서는 서블릿의 환경 설정 및 초기화 작업을 수행한다.

  2. 서비스(Service): 클라이언트의 요청이 있을 때마다 서블릿 컨테이너는 해당 서블릿의 service() 메서드를 호출합니다. 이 메서드는 요청의 종류(GET, POST 등)에 따라 doGet() 또는 doPost() 등의 적절한 메서드를 호출하여 요청을 처리한다. 기본적으로 service() 메서드는 doGet() 또는 doPost() 메서드를 호출하는 역할을 수행하며, 필요에 따라 이를 재정의할 수 있다.

  3. 종료(Destruction): 서블릿 컨테이너가 종료되거나 서블릿이 언로드되어야 할 때, 해당 서블릿의 destroy() 메서드를 호출하여 정리 작업을 수행한다. 이 메서드는 서블릿 인스턴스의 리소스 해제나 연결 종료 등의 정리 작업을 처리하는 데 사용된다.

서블릿은 웹 애플리케이션에서 다양한 기능을 수행할 수 있다. 예를 들어, 회원 가입, 로그인, 데이터 조회, 데이터 수정 등의 기능을 구현할 수 있으며, 데이터베이스와의 연동을 통해 데이터의 영속성을 유지할 수 있다. 또한, 서블릿은 세션 관리를 통해 클라이언트의 상태 정보를 유지하고, 쿠키를 사용하여 클라이언트에게 데이터를 저장하고 추적하는 등의 작업을 수행할 수 있다.

서블릿은 자바의 다양한 라이브러리와 프레임워크와 함께 사용될 수 있다. 예를 들면, JavaServer Pages(JSP)는 서블릿과 함께 사용되는 웹 템플릿 엔진이다. JSP는 HTML 코드 내에 자바 코드를 삽입하여 동적인 웹 페이지를 생성할 수 있다. 서블릿과 JSP를 함께 사용하면, 정적인 부분은 JSP를 사용하여 작성하고 동적인 부분은 서블릿에서 처리할 수 있어 개발의 효율성과 유지보수성을 높일 수 있다.

또한, 서블릿은 다양한 프레임워크와 통합하여 사용할 수 있다. 대표적인 예로는 Spring Framework가 있다. Spring Framework는 서블릿 기반의 웹 애플리케이션을 개발하기 위한 많은 기능과 편의성을 제공한다. Spring MVC는 서블릿을 기반으로 하는 웹 애플리케이션의 모델-뷰-컨트롤러(MVC) 아키텍처를 구현하며, 서블릿 컨테이너와 함께 동작하여 요청을 처리하고 응답을 생성한다. Spring Framework를 사용하면 서블릿의 생명주기 관리, 의존성 주입(Dependency Injection), 트랜잭션 관리, 보안 등의 기능을 편리하게 사용할 수 있다.

또 다른 예로는 JavaServer Faces(JSF)도 있습니다. JSF는 서버 측의 UI 컴포넌트 기반의 웹 애플리케이션 개발을 위한 프레임워크로, 서블릿을 기반으로 동작합니다. JSF는 서블릿을 자동으로 생성하고 관리하여 사용자 인터페이스(UI)의 이벤트 처리, 데이터 바인딩, 유효성 검사 등의 작업을 수행합니다.

이 외에도 다양한 프레임워크와 라이브러리가 서블릿을 지원하고 있으며, 서블릿을 기반으로 하는 웹 애플리케이션 개발을 편리하게 할 수 있도록 도와준다. 서블릿은 자바의 강력한 생태계와 함께 사용되어 웹 개발의 다양한 요구사항을 충족시키고, 유연하고 확장 가능한 웹 애플리케이션을 개발할 수 있도록 지원한다.

서블릿 컨테이너와 서블릿의 동작 과정

서블릿 컨테이너는 서블릿의 실행 환경을 제공하는 웹 애플리케이션 서버의 일부이다. 서블릿 컨테이너는 서블릿의 생명주기를 관리하고, 클라이언트로부터의 요청을 받아들이고 서블릿에 전달하여 응답을 생성한다. 서블릿 컨테이너는 서블릿의 실행에 필요한 여러 가지 기능을 제공하여 웹 애플리케이션의 동작을 지원한다.

image

서블릿 컨테이너의 주요 기능

  1. 서블릿 생명주기 관리: 서블릿 컨테이너는 서블릿의 인스턴스를 생성하고 초기화하는 단계부터, 요청에 따라 서블릿을 호출하고 종료하는 단계까지의 생명주기를 관리한다. 서블릿 컨테이너는 서블릿 클래스를 로드하고 인스턴스를 생성하여 초기화한다. 서블릿이 처음 요청되면 init() 메서드를 호출하고, 요청이 있을 때마다 service() 메서드를 호출하여 요청을 처리한다. 서블릿 컨테이너가 종료되거나 서블릿이 언로드되어야 할 때는 destroy() 메서드를 호출하여 정리 작업을 수행한다.

  2. 요청과 응답 처리: 클라이언트로부터의 요청을 받아들이고, 해당 요청을 처리하기 위해 적절한 서블릿을 선택하여 실행한다. 서블릿 컨테이너는 요청에 대한 HTTP 메서드(GET, POST 등)와 URL, 헤더 등의 정보를 파악하고, 해당 요청을 처리하기 위해 적절한 서블릿을 호출한다. 서블릿은 요청에 대한 처리를 수행하고, 서블릿 컨테이너에게 응답을 반환한다. 서블릿 컨테이너는 서블릿이 생성한 응답을 클라이언트에게 전송한다.

  3. 멀티스레딩 지원: 서블릿 컨테이너는 여러 클라이언트의 동시 요청을 처리하기 위해 멀티스레딩을 지원한다. 서블릿 컨테이너는 요청마다 별도의 스레드를 생성하고, 각 스레드에서 서블릿의 인스턴스를 사용하여 요청을 처리한다. 이를 통해 동시에 여러 클라이언트의 요청을 처리하여 웹 애플리케이션의 성능을 향상시킬 수 있다. 각각의 스레드는 독립적으로 실행되며, 서블릿 컨테이너는 스레드의 풀을 관리하여 효율적인 리소스 사용을 지원한다.

  4. 세션 관리: 서블릿 컨테이너는 클라이언트와의 상태를 유지하기 위한 세션 관리 기능을 제공한다. 세션은 클라이언트와 서버 간의 상태 정보를 저장하고 유지하는 데 사용된다. 서블릿 컨테이너는 세션 식별자를 생성하여 클라이언트에게 전송하고, 클라이언트가 이 식별자를 이용하여 세션을 식별한다. 서블릿은 세션을 사용하여 클라이언트의 상태 정보를 저장하고, 필요한 경우에 해당 정보를 조회하거나 수정할 수 있다.

  5. 보안 관리: 서블릿 컨테이너는 웹 애플리케이션의 보안을 관리하는 기능을 제공한다. 서블릿 컨테이너는 클라이언트의 인증(Authentication)과 권한 부여(Authorization)를 처리하며, 보안 정책을 설정하고 적용한다. 서블릿 컨테이너는 클라이언트의 요청에 따라 인증 정보를 확인하고, 허가된 작업만을 수행할 수 있도록 제어한다.

서블릿 컨테이너는 웹 애플리케이션의 실행 환경을 제공하고, 서블릿의 생명주기 관리, 요청과 응답 처리, 멀티스레딩, 세션 관리, 보안 관리 등 다양한 기능을 제공한다. 이를 통해 개발자는 서블릿에 집중하여 동적인 웹 애플리케이션을 구현할 수 있고, 서블릿 컨테이너는 이를 실행 및 관리하여 웹 애플리케이션의 안정성과 성능을 보장한다.

프론트 컨트롤러 패턴

프론트 컨트롤러 패턴(Front Controller Pattern)은 웹 애플리케이션의 요청을 중앙 집중적으로 처리하는 디자인 패턴이다. 이 패턴은 여러 개의 요청을 처리하는 컨트롤러를 도입하여 애플리케이션의 흐름을 관리하고, 요청에 따라 적절한 작업을 수행하는 역할을 한다.

프론트 컨트롤러 패턴의 주요 구성 요소

  1. 프론트 컨트롤러(Front Controller): 프론트 컨트롤러는 웹 애플리케이션의 진입점 역할을 한다. 클라이언트로부터의 모든 요청을 받아들이고, 요청을 처리하기 위해 적절한 컨트롤러를 호출한다. 프론트 컨트롤러는 요청에 대한 전처리 작업, 인증 및 인가, 로깅, 예외 처리 등의 공통된 작업을 수행할 수 있다.

  2. 컨트롤러(Controller): 컨트롤러는 프론트 컨트롤러로부터 요청을 전달받아 실제로 요청을 처리하는 역할을 한다. 각각의 요청에 대해 적절한 컨트롤러가 호출되어 해당 요청을 처리하고, 비즈니스 로직을 실행하거나 다른 컴포넌트(서비스, 모델 등)와의 상호작용을 수행한다. 컨트롤러는 요청에 대한 후처리 작업을 수행하고, 결과를 프론트 컨트롤러에 반환한다.

  3. 뷰(View): 뷰는 컨트롤러가 처리한 결과를 표현하는 역할을 한다. 보통은 웹 페이지, JSON, XML 등의 형태로 클라이언트에게 전달된다. 뷰는 사용자에게 결과를 시각적으로 표현하거나 데이터를 제공하기 위해 사용된다. 컨트롤러는 적절한 뷰를 선택하고, 처리 결과를 뷰에 전달하여 최종 결과를 생성한다.

프론트 컨트롤러 패턴의 장점

1. 중앙 집중적인 요청 처리: 프론트 컨트롤러를 통해 모든 요청이 중앙 집중적으로 처리된다. 이로써 공통된 작업(인증, 로깅 등)을 한 곳에서 처리할 수 있으며, 코드의 중복을 방지하고 유지보수성을 향상시킨다.

  1. 코드의 재사용성: 여러 컨트롤러가 프론트 컨트롤러를 통해 요청을 처리할 수 있기 때문에, 컨트롤러 간의 코드의 재사용성이 높아진다. 공통된 로직이나 모듈을 별도의 컨트롤러로 분리하여 필요한 곳에서 재사용할 수 있다.

  2. 확장성: 새로운 요청이 추가될 때, 프론트 컨트롤러에서 요청을 분석하고 적절한 컨트롤러를 호출하기 때문에 애플리케이션에 쉽게 확장할 수 있다. 새로운 요청을 처리하기 위해 단순히 새로운 컨트롤러를 추가하면 된다.

  3. 관점 지향(AOP) 기능: 프론트 컨트롤러를 통해 공통된 작업을 처리하는 것이 가능하므로, 관점 지향 프로그래밍(Aspect-Oriented Programming)을 적용하기에 용이하다. 예를 들어, 인증이 필요한 요청에 대해 프론트 컨트롤러에서 인증 관련 로직을 수행하는 등의 측면적인 처리가 가능하다.

  4. 테스트 용이성: 프론트 컨트롤러를 통해 요청을 처리하는 경우, 단일 진입점에서 모든 요청을 처리하므로 테스트가 용이하다. 각각의 컨트롤러에 대한 단위 테스트를 수행할 때도 프론트 컨트롤러를 거치지 않고 직접 컨트롤러를 호출할 수 있다.

Spring Web MVC

Spring MVC는 Spring에서 제공하는 웹 모듈로, Model, View, Controller 세 가지의 구성요소를 사용해 사용자의 다양한 HTTP Request를 처리하고 단순한 텍스트 응답부터 REST 형식의 응답은 물론 View를 표시하는 html을 return하는 응답까지 다양한 응답을 할 수 있게 하는 프레임워크다.

Spring MVC의 구조

image

  • Dispatcher Servlet(Front Controller): Spring Web MVC의 핵심이 되는 컨트롤러입니다. 모든 클라이언트 요청은 DispatcherServlet을 통해 처리됩니다. DispatcherServlet은 요청을 받아들이고, 적절한 핸들러(컨트롤러)를 호출하여 요청을 처리하고 응답을 생성합니다.
  • Handler(Controller): 핸들러는 클라이언트의 요청을 처리하는 컴포넌트입니다. 핸들러는 사용자의 요청에 따라 작업을 수행하고 결과를 생성합니다. 핸들러는 일반적으로 @Controller 어노테이션으로 표시된 클래스로 구현되며, 요청 경로에 따라 적절한 핸들러 메서드를 호출하여 작업을 수행합니다.
  • ModelAndView: 모델은 핸들러가 생성한 데이터를 나타냅니다. 모델은 핸들러의 처리 결과를 저장하고, 뷰에 전달하여 클라이언트에게 결과를 제공합니다.
  • ViewResolver: ViewResolver는 핸들러가 생성한 결과를 어떤 뷰로 전달할지 결정하는 역할을 합니다. 뷰 리졸버는 뷰의 이름을 기반으로 실제 뷰 오브젝트를 찾아서 반환하며, 이를 통해 클라이언트에게 결과를 표시합니다.