군만두의 IT 공부 일지

[스터디7] 04. 스프링 부트와 스프링 MVC 이해 본문

프로그래밍/Java

[스터디7] 04. 스프링 부트와 스프링 MVC 이해

mandus 2025. 5. 6. 16:00

목차

    7장. 스프링 부트와 스프링 MVC 이해

    이 장에서 다룰 내용
    - 첫 번째 웹 앱 구현하기
    - 스프링 부트를 사용한 스프링 앱 개발하기
    - 스프링 MVC 아키텍처 이해하기

    7.1 웹 앱이란

    • 웹 앱: 웹 브라우저로 접속하는 모든 앱

    7.1.1 웹 앱에 대한 일반적인 개요

    • 웹 앱
      • 클라이언트 측(the client side): 사용자가 직접 상호 작용하는 부분. 웹 브라우저는 웹 서버에 요청을 보내고, 서버에서 응답을 수신하며, 사용자가 앱과 상호 작용할 수 있는 방법을 제공한다. 웹 앱에서는 프런트엔드(frontend)라고도 한다.
      • 서버 측(the server side): 클라이언트에서 요청을 수신하고 응답에 데이터를 회신한다. 응답을 보내기 전에 클라이언트가 요청한 데이터를 처리하고, 저장하는 로직을 구현한다. 웹 앱에서는 백엔드(backend)라고도 한다.
    • 웹 앱에서 일반적으로 클라이언트와 서버를 언급하지만, 백엔드는 동시에 여러 클라이언트에 서비스를 제공한다는 점을 명심해야 한다. 동일한 자원에 액세스하고 변경하는 코드를 작성하면 경쟁 상태(race condition) 시나리오로 앱이 오동작할 수 있다.

    ▲ 웹 앱

    7.1.2 스프링으로 웹 앱을 구현하는 다양한 방식

    1. 클라이언트 요청에 응답하여 백엔드가 완성된 뷰를 제공하는 앱: 웹 브라우저는 백엔드에서 받은 데이터를 직접 해석하여 이 앱을 통해 사용자에게 이 정보를 표시한다.
      • 백엔드는 사용자 동작을 나타내는 요청을 받고 일부 로직을 실행한다.
      • 최종적으로 서버는 웹 브라우저에 표시해야 할 내용으로 응답한다.
      • 백엔드는 HTML, CSS, 이미지 등 웹 브라우저가 해석하고 표시할 수 있는 형식의 데이터로 응답한다.
      • 백엔드는 웹 브라우저가 이해하고 실행할 수 있는 언어(자바스크립트 등)로 작성된 스크립트를 전송할 수도 있다.
    2. 프런트엔드-백엔드 분리 방식의 앱: 백엔드는 원시 데이터만 제공한다. 웹 브라우저는 백엔드 응답에 있는 데이터를 직접 표시하지 않는다. 웹 브라우저는 백엔드 응답을 가져와 데이터를 처리하고 웹 브라우저에 표시할 내용을 지시하는 별도의 프런트엔드 앱을 실행한다.
      • 서버는 웹 브라우저에 표시할 내용을 정확히 알려주는 대신 원시 데이터만 전송한다.
      • 웹 브라우저는 초기 요청에 로드하는 독립적인 프런트엔드 앱을 실행한다.
      • 프런트엔드 앱은 서버의 원시 응답을 가져와서 해석하고 정보 표시 방식을 결정한다.

    ▲ 프런트엔드-백엔드 분리 방식을 사용하지 않는 앱
    ▲ 프런트엔드-백엔드 분리 방식을 사용하는 앱

    프런트엔드-백엔드 분리 방식 프런트엔드-백엔드 분리하지 않는 방식
    대규모 앱 개발 소규모 앱 개발

    7.1.3 웹 앱 개발에서 서블릿 컨테이너 사용

    • 클라이언트와 서버 간 통신
      • 웹 브라우저는 HTTP(HyperText Transfer Protocol)라는 프로토콜을 사용하여 네트워크를 통해 서버와 통신한다.
      • 웹 앱 컴포넌트는 HTTP 프로토콜을 사용하여 요청-응답 방식으로 데이터를 교환한다.
      • 클라이언트가 서버에 요청을 보내면 서버가 응답한다. 클라이언트는 요청을 보낼 때마다 응답을 기다린다.
    • HTTP를 이해하고 HTTP 요청과 응답을 자바 앱으로 변환하는 것이 필요하다. 웹 서버라고 하는 서블릿 컨테이너(servlet container)는 자바 앱의 HTTP 메시지를 변환하는 역할을 한다.
      • 서블릿 컨테이너를 사용하면 자바 앱은 통신 계층을 구현할 필요가 없다.
      • 널리 알려진 구현체로 톰캣(Tomcat)이 있다.
      • 서블릿 컨테이너는 HTTP 요청을 받으면 서블릿 객체의 메서드를 호출하고 그 요청을 매개변수로 제공한다.
      • 동일한 메서드는 요청한 클라이언트에 반환할 응답을 설정하기 위해 서블릿에서 사용되는 HTTP 응답을 나타내는 매개변수도 가져온다.

    7.2 스프링 부트의 마법

    • 스프링 부트 기능과 장점
      • 간소화된 프로젝트 생성: 프로젝트 초기화 서비스를 이용하여 비어 있지만 구성된 스켈레톤(뼈대) 앱을 얻을 수 있다.
      • 의존성 스타터: 스프링 부트는 특정 목적에 사용되는 특정 의존성들을 의존성 스타터로 모았다. 프로젝트에 추가해야 하는 모든 의존성이나 버전에 대하여 파악할 필요가 없다.
      • 의존성에 기반을 둔 자동 구성: 프로젝트에 추가한 의존성에 따라 스프링 부트는 몇 가지 기본 구성을 정의한다. 모든 구성을 직접 작성하는 대신 스프링 부트에서 제공하는 구성 중에서 필요한 구성과 다른 것만 변경하면 된다.

    7.2.1 프로젝트 초기화 서비스를 이용한 스프링 부트 프로젝트 생성

    프로젝트 초기화 서비스(Spring Initializr)를 이용하여 스프링 프로젝트를 생성하는 방법을 설명한다. 하루에 수많은 스프링 부트 프로젝트를 작성하는 학생과 교사에게 이 기능은 매우 중요하다.

    1. 웹 브라우저에서 링크에 접속한다.
    2. 프로젝트 속성(언어, 버전, 빌드 도구 등)을 선택한다.
    3. 프로젝트에 추가해야 할 의존성을 선택한다.
    4. [GENERATE] 버튼을 눌러 아카이브된(zip으로 압축된) 프로젝트를 내려받는다.
    5. 프로젝트를 압축 해제하고 IDE에서 오픈한다.

    • 스프링 Initializr의 주요 내용
      • 스프링 앱 메인 클래스
      • 스프링 부트 POM 부모
      • 의존성
      • 스프링 부트 메이븐 플러그인
      • 프로퍼티 파일

    7.2.2 의존성 스타터를 사용한 의존성 관리 간소화

    스프링 부트가 제공하는 두 번째 핵심적 장점인 의존성 스타터(dependency starter)에 집중한다. 의존성 스타터는 많은 시간을 절약해 주며, 스프링 부트가 제공하는 소중한 기능이다.

    • 의존성 스타터: 특정 목적에 맞게 앱을 구성하려고 추가하는 의존성 그룹
    • 프로젝트의 pom.xml 파일에서 스타터는 일반 의존성처럼 보인다.
    • 스타터 이름은 일반적으로 'spring-boot-starter-'로 시작하고, 그 뒤에 앱에 추가한 기능을 기술하는 이름이 따라온다.
    • 의존성 스타터를 사용하면 의존성을 직접 요구하지 않고 기능(capabilities)을 요청한다.
    • 의존성 스타터는 호환 가능한 의존성들의 기능 지향적(capability-oriented) 그룹이라고 할 수 있다.

    7.2.3 의존성에 기반을 둔 관례에 따라 autoconfiguration 사용

    • 스프링 부트에서 애플리케이션에 대한 autoconfiguration도 제공하는 것을 구성보다 관례(convention-over-configuration) 원칙을 적용한다고 한다.
    • 아직 아무것도 작성하지 않았고 단지 프로젝트를 내려받아 IDE에서 열었을 뿐이지만, 앱을 시작하면 기본적으로 8080번 포트에서 액세스할 수 있는 톰캣 인스턴스가 앱에서 부팅되는 것을 확인할 수 있다.
    • 추가한 의존성을 기반으로 스프링 부트는 앱에 대한 기대를 파악하고 기본 구성을 제공한다.
    • 스프링 부트는 관례에 따라 앱을 구성하므로 앱에 특별한 구성이 필요한 부분만 변경하면 된다.

    7.3 스프링 MVC로 웹 앱 구현

    앱에 웹 페이지를 추가하려면 두 단계를 수행해야 한다.

    1. 웹 브라우저에 표시할 콘텐츠가 포함된 HTML 문서를 작성한다.
    2. 1.에서 생성한 웹 페이지에 대한 액션이 포함된 컨트롤러를 작성한다.

    컴포넌트들과 이들이 HTTP 요청을 관리하는 흐름은 다음과 같다.

    1. 클라이언트가 HTTP 요청을 한다.
    2. 톰캣이 클라이언트의 HTTP 요청을 수신한다. 톰캣은 HTTP 요청에 대한 서블릿 컴포넌트를 호출해야 한다. 스프링 MVC의 경우 톰캣은 스프링 부트가 구성한 서블릿을 호출한다. 우리는 이 서블릿 이름을 디스패처 서블릿(dispatcher servlet)이라고 한다.
    3. 디스패처 서블릿은 스프링 웹 앱의 진입점이다. 톰캣은 수신되는 모든 HTTP 요청에서 디스패처 서블릿을 호출한다. 디스패처 서블릿은 스프링 앱 내부의 요청을 제어하는 역할을 하므로 요청에 대해 호출할 컨트롤러 액션과 클라이언트 응답으로 전송할 액션을 찾아야 한다. 따라서 이 서블릿을 '프런트 컨트롤러(front controller)'라고도 한다.
    4. 디스패처 서블릿이 가장 먼저 해야 할 일은 요청에 대해 호출할 컨트롤러 액션을 찾는 것이다. 호출할 컨트롤러 액션을 찾기 위해 디스패처 서블릿은 핸들러 매핑(handler mapping)이라는 컴포넌트에 위임한다. 핸들러 매핑은 @RequestMapping 애너테이션을 사용하여 요청과 연관된 컨트롤러 액션을 찾는다.
    5. 호출할 컨트롤러 액션을 찾은 후 디스패처 서블릿은 해당되는 특정 컨트롤러 액션을 호출한다. 핸들러 매핑에서 요청과 연관된 액션을 찾을 수 없는 경우 앱은 HTTP '404 Not Found' 상태를 클라이언트에 응답한다. 컨트롤러는 응답을 위해 렌더링해야 하는 페이지 이름을 디스패처 서블릿에 반환한다. 이 HTML 페이지를 뷰(view)라고도 한다.
    6. 이때 디스패처 서블릿은 컨트롤러에서 받은 이름으로 뷰를 찾아 콘텐츠를 가져오고 그 콘텐츠를 응답으로 보내야 한다. 디스패처 서블릿은 뷰 콘텐츠를 가져오는 책임을 '뷰 리졸버(View Resolver)' 컴포넌트에 위임한다.
    7. 디스패처 서블릿은 렌더링된 뷰를 HTTP 응답으로 반환한다.
       
       

    이 글은 『스프링 교과서』 책을 학습한 내용을 정리한 것입니다.
    Comments