개발 공부/백엔드

스프링 부트: 정적 콘텐츠와 동적 콘텐츠 처리 방식

baby-t 2025. 9. 13. 17:34

https://www.inflearn.com/

 

인프런 - 라이프타임 커리어 플랫폼

프로그래밍, 인공지능, 데이터, 마케팅, 디자인등 입문부터 실전까지 업계 최고 선배들에게 배울 수 있는 곳.

www.inflearn.com

인프런 사이트의 김영한님의 강의를 보면서 작성한 글입니다.

 

스프링 부트로 웹 애플리케이션을 개발할 때, 우리는 사용자에게 두 종류의 웹 페이지를 제공할 수 있습니다. 하나는 언제 누가 접속해도 항상 같은 모습을 보여주는 정적(Static) 콘텐츠이고, 다른 하나는 사용자의 요청이나 데이터베이스의 상태에 따라 내용이 실시간으로 변하는 동적(Dynamic) 콘텐츠입니다.

이번 포스팅에서는 스프링 부트가 이 두 가지 콘텐츠를 각각 어떤 방식으로 처리하는지 알아보겠습니다.


## 1. 정적 콘텐츠 (Static Content) 📄

정적 콘텐츠는 내용이 고정된 HTML, CSS, JavaScript 파일이나 이미지 등을 의미합니다. 스프링 부트는 정적 콘텐츠를 매우 간단하게 제공할 수 있는 약속(Convention)을 가지고 있습니다.

### 정적 리소스 경로

src/main/resources/static 경로에 파일을 넣어두면, 스프링 부트는 해당 파일을 정적 리소스로 인식하여 자동으로 웹에 노출시킵니다.

### 웰컴 페이지 (Welcome Page)

만약 static 폴더 안에 index.html 파일을 만들어두면, 스프링 부트는 이 파일을 애플리케이션의 '대문'으로 인식하여, 별도의 설정 없이도 루트 URL(localhost:8080/) 접속 시 해당 페이지를 보여줍니다.

HTML
 
<!DOCTYPE html>
<html lang="ko">
<head>
    <title>정적 페이지</title>
</head>
<body>
    <h1>안녕하세요, 정적 웰컴 페이지입니다.</h1>
</body>
</html>

이 방식은 내용이 변하지 않는 단순한 소개 페이지나, CSS/JS 파일을 제공할 때 매우 유용합니다.


## 2. 동적 콘텐츠 (Dynamic Content) ✨

사용자에 따라 다른 내용을 보여주려면, 요청이 들어왔을 때 서버에서 데이터를 가공하여 HTML을 실시간으로 만들어내는 과정이 필요합니다. 이때 **템플릿 엔진(Template Engine)**이 사용되며, 저는 **타임리프(Thymeleaf)**를 사용했습니다.

동적 콘텐츠는 **Controller → View (Template)**의 흐름으로 처리됩니다.

### 1. 컨트롤러 (Controller): 요청의 진입점

컨트롤러는 웹 애플리케이션으로 들어오는 HTTP 요청을 받아 처리하는 진입점입니다.

Java
 
// src/main/java/com/example/demo/controller/HelloController.java
package com.example.demo.controller;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class HelloController {

    @GetMapping("hello") // URL 경로 /hello에 매핑
    public String hello(Model model) {
        // "data"라는 이름(key)으로 "Hello World!!"라는 값(value)을 모델에 추가
        model.addAttribute("data", "Hello World!!");
        // "hello"라는 이름의 뷰(html 파일)를 반환
        return "hello";
    }
}
  • @Controller: 이 클래스가 웹 요청을 처리하는 컨트롤러임을 나타냅니다.
  • @GetMapping("hello"): 클라이언트가 /hello 경로로 GET 요청을 보냈을 때 이 메소드를 실행하도록 매핑합니다.
  • Model model: 컨트롤러에서 생성한 데이터를 뷰(HTML)로 전달하는 역할을 하는 객체입니다. model.addAttribute("키", "값") 형태로 데이터를 담습니다.
  • return "hello": 뷰의 논리적인 이름입니다.

### 2. 뷰 리졸버와 템플릿 (View Resolver & Template)

컨트롤러가 "hello"라는 뷰 이름을 반환하면, 스프링 부트의 **뷰 리졸버(View Resolver)**가 동작하여 실제 물리적인 파일을 찾아냅니다. 기본적으로 다음 규칙을 따릅니다.

resources/templates/ + {ViewName} + .html

따라서, 우리는 resources/templates/ 폴더 안에 hello.html 파일을 미리 만들어 두어야 합니다.

HTML
 
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>동적 페이지</title>
</head>
<body>
    <p th:text="'안녕하세요. ' + ${data}">안녕하세요. 손님</p>
</body>
</html>
  • xmlns:th="http://www.thymeleaf.org": 이 HTML에서 타임리프 문법을 사용하겠다고 선언하는 부분입니다.
  • th:text: 타임리프의 속성으로, 태그 안의 텍스트를 지정된 값으로 변경합니다. ${data}는 컨트롤러의 model에서 넘겨준 data 키의 값, 즉 "Hello World!!"로 치환됩니다.

### 최종 결과

이제 localhost:8080/hello로 접속하면, 컨트롤러가 model에 "Hello World!!"를 담아 hello.html 템플릿을 렌더링하여, 최종적으로 화면에는 "안녕하세요. Hello World!!"가 동적으로 표시됩니다.

더 많은 정보: 스프링 부트의 다양한 기능이나 공식적인 설정 방법이 궁금하다면, 공식 문서 사이트인 spring.io의 'Projects' 메뉴에서 Spring Boot 관련 내용을 찾아보는 것이 가장 정확합니다.

 

 

## 추가: MVC 디자인 패턴이란?

앞서 살펴본 스프링 부트의 동작 방식은 MVC(Model-View-Controller) 라는 매우 유명한 디자인 패턴을 기반으로 합니다. MVC는 웹 애플리케이션을 세 가지 주요 역할로 나누어 개발하는 방식으로, 코드의 **관심사를 분리(Separation of Concerns)**하여 유지보수와 확장을 용이하게 만드는 것이 핵심 목표입니다.

### 1. 모델 (Model) 🧠

  • 역할: 애플리케이션의 데이터와 비즈니스 로직을 담당합니다.
  • 설명: 데이터베이스와 상호작용하여 데이터를 가져오거나, 복잡한 연산을 수행하는 등 실질적인 처리를 담당하는 부분입니다. 뷰(View)나 컨트롤러(Controller)가 어떻게 동작하는지는 알지 못합니다. (예: UserService 클래스, Product 데이터 객체)

### 2. 뷰 (View) 👁️

  • 역할: 사용자에게 보여지는 **UI(User Interface)**를 담당합니다.
  • 설명: 모델로부터 받은 데이터를 사용하여 사용자에게 보여줄 화면(HTML 등)을 그리는(렌더링하는) 역할을 합니다. 어떻게 데이터가 만들어졌는지는 신경 쓰지 않고, 오직 보여주는 것에만 집중합니다. (예: hello.html과 같은 타임리프 템플릿 파일)

### 3. 컨트롤러 (Controller) 🕹️

  • 역할: 모델과 뷰 사이의 상호작용을 제어하는 중재자입니다.
  • 설명: 사용자의 HTTP 요청을 가장 먼저 받아서, 그 요청에 맞는 모델의 비즈니스 로직을 호출합니다. 모델이 데이터를 처리하고 나면, 그 결과를 어떤 뷰에 전달하여 사용자에게 보여줄지 결정하여 응답을 보냅니다. (예: @Controller 어노테이션이 붙은 HelloController 클래스)

이처럼 MVC 패턴을 사용하면 각 부분이 독립적으로 동작하여, 디자이너는 뷰(View)에, 백엔드 개발자는 모델(Model)과 컨트롤러(Controller)에 집중하여 효율적으로 협업할 수 있습니다.