[아이티센 부트캠프] Spring Boot 0

이언덕·2026년 4월 20일

아이티센 부트캠프

목록 보기
61/115
post-thumbnail

실습 시작 전

이 실습은 IntelliJ 설치와 Spring Boot 프로젝트 생성이 끝난 뒤부터 본다.
설치 과정과 프로젝트 생성 과정은 먼저 첨부한 PDF를 보고 진행하면 된다.
여기서는 프로젝트가 만들어진 뒤, 어떤 폴더와 파일을 먼저 봐야 하는지, Gradle이 어떤 역할을 하는지, 그리고 그다음에 코드가 어떻게 연결되는지까지 흐름으로 정리한다.


처음 배우는 입장에서는 프로젝트를 열자마자 파일이 너무 많이 보여서 어디부터 봐야 할지 막히기 쉽다.
그래서 여기서는 실습에 바로 쓰는 폴더와 파일만 먼저 구분하고, 그다음에 실행 흐름으로 넘어가는 방식으로 이해하면 된다.


이번 실습에서 먼저 잡아야 하는 큰 흐름은 간단하다.


먼저 봐야 하는 기본 폴더와 파일

프로젝트를 처음 열면 파일과 폴더가 많이 보인다.
하지만 지금 단계에서 다 외울 필요는 없다.
이번 실습에 바로 연결되는 것들만 먼저 보면 된다.

  • src/main/java
    자바 코드를 작성하는 위치이다.
    SpringeduApplication.java, HelloController.java 같은 파일이 여기에 들어간다.

  • src/main/resources
    설정 파일과 화면 관련 파일을 두는 위치이다.

  • src/main/resources/templates
    Thymeleaf 화면 파일을 두는 위치이다.
    이번 실습의 helloView.html이 여기에 들어간다.

  • src/main/resources/static
    css, js, 이미지처럼 정적인 파일을 두는 위치이다.
    이번 실습에서는 꼭 사용하지 않지만, 나중에 화면을 꾸밀 때 자주 쓰게 된다.

  • application.properties
    포트 번호 같은 실행 환경을 설정하는 파일이다.

  • build.gradle
    프로젝트에 어떤 기능과 라이브러리를 붙일지 적는 파일이다.

  • settings.gradle
    프로젝트 이름 같은 기본 정보를 잡는 파일이다.

  • gradlew, gradlew.bat
    Gradle 명령을 실행할 수 있게 도와주는 파일이다.

즉, 지금 실습에서는 java 폴더에 자바 파일을 만들고, templates 폴더에 화면 파일을 만들고, application.properties와 build.gradle을 함께 보는 흐름만 먼저 익히면 된다.


인텔리제이에서 먼저 어디를 봐야 하는가

처음에는 IntelliJ 화면 전체를 다 이해하려고 하지 않아도 된다.
실습에 필요한 위치만 잡으면 충분하다.

  • 왼쪽 Project 창
    폴더와 파일 위치를 확인하는 곳이다.

  • 가운데 편집기
    코드를 직접 작성하는 곳이다.

  • 위쪽 실행 버튼
    SpringeduApplication.java를 실행할 때 사용한다.

  • 아래 Run 창
    서버 시작 로그와 에러 메시지를 확인하는 곳이다.

초보자가 가장 먼저 익혀야 하는 것은 메뉴 이름이 아니라, 파일은 왼쪽에서 찾고, 코드는 가운데에서 쓰고, 실행 상태는 아래에서 확인한다는 흐름이다.


Gradle은 무엇인가

Gradle은 프로젝트를 빌드하고 필요한 라이브러리를 관리하는 도구이다.
여기서 빌드는 프로그램이 실행될 수 있도록 필요한 준비를 모아서 처리하는 과정이라고 이해하면 된다.


초보자 기준에서는 Gradle을 아주 어렵게 볼 필요는 없다.
지금 단계에서는 프로젝트 실행 준비를 도와주는 관리 도구라고 이해하면 충분하다.


우리가 Controller를 만들고 Thymeleaf 화면을 작성할 수 있는 것도, 관련 기능을 Gradle이 먼저 프로젝트에 연결해 주기 때문이다.
즉, Spring Boot 프로젝트는 자바 파일 몇 개만 있는 것이 아니라 실행에 필요한 기능과 라이브러리까지 함께 관리되는 구조이다.


왜 build.gradle 파일을 같이 봐야 하는가

build.gradle은 이 프로젝트가 어떤 기능을 사용할지 적어 두는 파일이다.
여기 안에는 웹 요청 처리 기능, 화면 템플릿 기능, 테스트 기능처럼 프로젝트가 동작하는 데 필요한 준비가 들어 있다.


즉, 이번 실습에서 HelloController.java가 요청을 받고 helloView.html이 연결되는 것도 우연히 되는 것이 아니다.
뒤에서 build.gradle이 웹 기능과 템플릿 기능을 사용할 수 있게 준비해 두었기 때문에 가능한 것이다.


그래서 build.gradle은 지금 당장 코드를 직접 많이 쓰는 파일은 아니지만, 프로젝트 전체가 왜 실행되는지 이해하려면 꼭 같이 봐야 하는 파일이다.


build.gradle 전체 코드 먼저 보기

프로젝트 생성 옵션에 따라 일부 줄은 조금 달라질 수 있다.
하지만 이번 실습에서 자주 보게 되는 기본 형태는 아래와 비슷하다.

// build.gradle
plugins {
    id 'java'
    id 'org.springframework.boot' version '4.0.5'
    id 'io.spring.dependency-management' version '1.1.7'
}
group = 'com.example'
version = '0.0.1-SNAPSHOT'
java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(21)
    }
}
repositories {
    mavenCentral()
}
dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
    implementation 'org.springframework.boot:spring-boot-starter-web'
    developmentOnly 'org.springframework.boot:spring-boot-devtools'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}
tasks.named('test') {
    useJUnitPlatform()
}

이 코드는 처음 보면 길고 낯설다.
하지만 한 줄 한 줄이 모두 복잡한 알고리즘을 적은 것은 아니다.
대부분은 이 프로젝트가 어떤 기능을 사용할지, 어떤 환경에서 실행할지, 어디에서 라이브러리를 받아올지를 적어 놓은 설정 코드이다.


build.gradle 안의 코드 하나씩 이해하기

plugins 블록

plugins는 이 프로젝트에서 사용할 기본 도구를 붙이는 부분이다.
여기서 id 'java'는 이 프로젝트가 자바 프로젝트라는 뜻이다.
id 'org.springframework.boot'는 Spring Boot 기능을 사용할 수 있게 해 준다.
id 'io.spring.dependency-management'는 라이브러리 버전을 좀 더 편하게 관리할 수 있게 도와준다.


즉, 이 부분은 프로젝트의 기본 성격을 정하는 자리라고 보면 된다.
그냥 자바 프로젝트인지, Spring Boot 프로젝트인지가 여기서 정해진다.


group와 version

group = 'com.example'은 프로젝트의 기본 그룹 이름이다.
패키지 이름 체계와 연결해서 쓰는 경우가 많다.
version = '0.0.1-SNAPSHOT'은 현재 프로젝트 버전을 뜻한다.


여기서 SNAPSHOT은 아직 계속 수정 중인 개발 버전 정도로 이해하면 된다.
즉, 완전히 배포가 끝난 확정 버전이라기보다, 아직 작업 중인 상태를 나타내는 값이다.


java 블록

java 블록은 이 프로젝트가 어떤 자바 버전을 기준으로 동작할지 정하는 부분이다.
toolchain은 자바 실행 환경을 맞추는 설정이다.
JavaLanguageVersion.of(21)은 이 프로젝트가 Java 21 기준으로 동작하도록 맞춘다는 뜻이다.


이 설정이 중요한 이유는, 프로젝트 코드와 실행 환경의 자바 버전이 맞지 않으면 오류가 날 수 있기 때문이다.
즉, 이 부분은 자바 버전을 맞춰서 실행 오류를 줄이는 역할을 한다.


repositories 블록

repositories는 필요한 라이브러리를 어디에서 받아올지 적는 부분이다.
mavenCentral()은 가장 많이 사용하는 공개 저장소 중 하나이다.


즉, build.gradle에 적은 라이브러리들이 실제로 어디에서 내려받아지는지가 여기서 정해진다.
초보자 기준에서는 mavenCentral()을 필요한 도구를 받아오는 창고를 연결하는 설정 정도로 이해하면 된다.


dependencies 블록

dependencies는 이 프로젝트가 실제로 사용할 라이브러리를 적는 부분이다.
이번 실습에서 가장 중요한 부분도 여기이다.

  • implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
    Thymeleaf를 사용할 수 있게 해 주는 라이브러리이다.
    즉, helloView.html에서 ${data}나 th:text 같은 문법을 사용할 수 있는 이유가 이 줄과 연결된다.

  • implementation 'org.springframework.boot:spring-boot-starter-web'
    웹 요청을 받고 응답하는 기능을 사용할 수 있게 해 주는 라이브러리이다.
    즉, @Controller, @GetMapping, Model 같은 웹 관련 기능이 동작하는 이유가 이 줄과 연결된다.

  • developmentOnly 'org.springframework.boot:spring-boot-devtools'
    개발할 때 편하게 작업하도록 도와주는 라이브러리이다.
    코드를 수정했을 때 반영을 조금 더 편하게 해 주는 역할이 있다.
    지금 단계에서는 없어도 핵심 개념을 이해하는 데 큰 문제는 없지만, 개발 편의성을 높여 주는 도구라고 보면 된다.

  • testImplementation 'org.springframework.boot:spring-boot-starter-test'
    테스트 코드를 작성하고 실행할 때 필요한 라이브러리이다.
    이번 실습에서는 직접 테스트 코드를 깊게 다루지 않더라도, 기본 프로젝트에는 함께 들어 있는 경우가 많다.

  • testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
    테스트를 실행할 때 필요한 도구이다.
    즉, 테스트 환경이 돌아갈 수 있게 도와주는 줄이다.

정리하면 dependencies는 이 프로젝트가 어떤 기능을 쓸 수 있는지 적는 자리이다.
이번 실습이 웹 프로젝트처럼 동작하는 핵심 이유도, 화면 템플릿이 동작하는 이유도 결국 이 블록과 연결된다.


tasks.named('test') 블록

이 부분은 테스트를 어떤 방식으로 실행할지 정하는 설정이다.
useJUnitPlatform()은 JUnit 기반 테스트를 실행하겠다는 뜻이다.


이번 실습에서는 이 부분을 직접 수정할 일은 거의 없다.
기본 프로젝트가 테스트까지 가능한 구조로 준비되어 있다는 점만 가볍게 이해하면 충분하다.




스프링 부트는 무엇인가

Spring Boot는 자바로 웹 프로그램을 만들 때 필요한 기본 준비를 많이 자동으로 처리해 주는 도구이다.
원래 웹 프로그램은 서버 실행 준비, 여러 설정, 연결 작업처럼 초보자에게 낯선 내용이 많다.
그런데 Spring Boot를 사용하면 이런 준비를 많이 대신 처리해 주기 때문에, 우리는 필요한 클래스와 화면 파일을 만들고 바로 실행 흐름을 연습할 수 있다.


즉, 지금 실습에서 파일 몇 개만 작성해도 서버가 올라가고 화면이 보이는 이유는, 뒤에서 많은 준비를 Spring Boot가 대신 해 주고 있기 때문이다.


그리고 그 자동 준비가 실제 프로젝트 안에서는 build.gradle 같은 설정과 함께 움직인다.
그래서 Spring Boot는 편한 실행 구조를 제공하고, Gradle은 그 실행에 필요한 기능을 연결해 주는 쪽이라고 같이 이해하면 된다.


왜 처음 배우기에 유리한가

처음부터 모든 설정을 하나하나 손으로 다 작성하면 흐름을 보기 전에 지치기 쉽다.
하지만 Spring Boot는 자주 쓰는 기본 준비를 많이 대신 처리해 준다.
그래서 초보자는 복잡한 서버 설정보다 요청을 받고 화면을 보여 주는 핵심 흐름에 먼저 집중할 수 있다.


즉, 지금 단계에서는 내부의 세부 설정을 전부 외우기보다, Spring Boot 덕분에 웹 실습을 빠르게 시작할 수 있다는 점을 먼저 잡으면 된다.




MVC는 무엇인가

MVC는 역할을 나눠서 프로그램을 만드는 방식이다.
처음에는 이름이 낯설 수 있지만, 지금 실습에 그대로 대입하면 이해가 쉽다.


MVC는 한 파일이 모든 일을 다 하지 않게 나누는 구조이다.
이렇게 나누면 코드를 읽기 쉽고, 수정할 때도 어느 부분을 고쳐야 하는지 더 분명해진다.


각 역할을 지금 실습에 대입하기

  • Controller
    브라우저 요청을 받는 역할이다.

  • Model
    화면에 넘길 데이터를 담는 역할이다.

  • View
    사용자에게 보여 줄 화면 역할이다.

지금 실습에서는 HelloController.java가 요청을 처리하니 Controller 역할을 한다.
Model 객체에는 화면에 보일 값을 담는다.
그리고 helloView.html은 실제로 브라우저에 보이는 화면이니 View 역할을 한다.


즉, 이번 실습은 단순히 코드 몇 줄을 따라 치는 것이 아니라 MVC의 가장 기본적인 연결 구조를 직접 확인하는 실습이라고 보면 된다.


왜 역할을 나눠서 만드는가

요청 처리, 데이터 준비, 화면 출력을 한곳에 다 섞어 두면 코드가 금방 복잡해진다.
어디를 수정해야 할지 찾기도 어려워진다.


그래서 MVC는 요청을 받는 곳, 값을 준비하는 곳, 화면을 보여 주는 곳을 나눈다.
초보자 기준에서는 파일마다 맡은 일이 다르기 때문에 흐름을 따라가기 쉬워진다고 이해하면 된다.




자동 생성된 실행 파일 보기

Spring Boot 프로젝트를 생성하면 SpringeduApplication.java가 자동으로 만들어진다.
이 파일은 화면을 직접 만드는 파일은 아니지만, 프로그램 전체를 시작시키는 가장 중요한 출발점이다.


초보자는 이 파일을 그냥 실행 버튼 누르는 파일처럼 보기 쉽다.
하지만 실제로는 Spring Boot 서버를 켜고, 우리가 만든 클래스들이 함께 동작할 수 있게 준비를 시작하는 파일이라고 이해해야 한다.


실행 파일 코드

// SpringeduApplication.java
package com.example.springedu;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringeduApplication {
    public static void main(String[] args) {
        SpringApplication.run(SpringeduApplication.class, args); // 프로그램 시작
    }
}

이 코드는 짧아 보이지만 역할은 분명하다.
main() 메서드는 자바 프로그램이 시작되는 자리이고, SpringApplication.run()은 Spring Boot에게 이제 웹 프로그램 실행을 시작하라고 알려 주는 부분이다.


즉, 이 파일은 화면을 직접 출력하지 않는다.
대신 전체 프로그램이 움직이기 시작하는 출발 버튼 역할을 한다.


왜 이 파일을 실행해야 하는가

초보자가 여기서 가장 많이 헷갈리는 부분은 이것이다.
왜 HelloController.java를 실행하는 것이 아니라 SpringeduApplication.java를 실행하는가 하는 점이다.


이유는 간단하다.
SpringeduApplication.java에는 main() 메서드가 있어서 프로그램 시작점이 된다.
반면 HelloController.java는 혼자 실행하는 파일이 아니라, 서버가 켜진 뒤 요청이 들어왔을 때 동작하는 파일이다.


즉, Controller는 시작 버튼이 아니라 동작 부품이다.
그래서 먼저 실행 파일로 서버를 시작해야 하고, 그다음에 브라우저 요청을 통해 Controller가 움직이게 된다.


이 흐름을 잡으면 “왜 어떤 자바 파일은 실행하고 어떤 자바 파일은 실행하지 않는가”가 훨씬 분명해진다.


여기서 먼저 이해해야 하는 점

@SpringBootApplication은 이 클래스가 Spring Boot 실행의 기준이 되는 클래스라는 뜻이다.
애너테이션은 코드 위에 붙여서 역할을 알려 주는 표시라고 이해하면 된다.
지금 단계에서는 이 표시 안에서 무슨 일이 세부적으로 일어나는지까지 외울 필요는 없다.
이 클래스가 프로젝트 전체의 시작점이라는 점만 정확히 잡으면 된다.


그리고 SpringApplication.run()이 실행되면 서버가 올라가고, 우리가 뒤에서 만드는 HelloController.java와 helloView.html도 함께 연결될 준비를 한다.
그래서 별도의 복잡한 연결 코드를 길게 쓰지 않아도 전체 흐름이 잡힌다.


정리하면 SpringeduApplication.java는 직접 화면을 만드는 파일이 아니라, 그 화면이 동작할 수 있게 전체 프로그램을 시작하는 파일이다.




요청을 받는 클래스 만들기

SpringeduApplication.java가 프로그램 전체를 시작했다면, 이제 브라우저 요청을 실제로 받는 파일이 필요하다.
그 역할을 하는 것이 HelloController.java다.


브라우저에서 /hello 주소로 들어왔을 때 어떤 화면을 보여 줄지 정해 주는 파일이라고 보면 된다.
여기서부터는 서버가 요청을 받고 화면으로 넘기는 흐름이 본격적으로 시작된다.


컨트롤러 코드

// HelloController.java
package com.example.springedu.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class HelloController {
    @GetMapping("/hello")
    public String hello(Model model) {
        model.addAttribute("data", "Spring Boot"); // 화면에 넘길 값 저장
        return "helloView"; // templates 폴더의 helloView.html 연결
    }
}

이 코드에서 먼저 봐야 하는 것은 문법보다 역할이다.
@Controller는 이 클래스가 요청을 처리하는 역할이라는 뜻이다.
@GetMapping("/hello")는 브라우저가 /hello로 들어왔을 때 바로 아래 메서드를 실행하라는 뜻이다.


즉, 사용자가 localhost:8088/hello 같은 주소로 접속하면 hello() 메서드가 실행된다.


여기서 한 가지 같이 기억하면 좋은 점이 있다.
이 파일은 보통 실행 클래스와 같은 기준 패키지 아래, 또는 그 하위 패키지에 두는 것이 자연스럽다.
그래야 Spring Boot가 이 클래스를 자동으로 찾아서 함께 동작시킬 수 있다.


모델은 왜 필요한가

Model은 화면으로 값을 넘길 때 쓰는 바구니라고 생각하면 된다.
여기서는 model.addAttribute("data", "Spring Boot")로 "Spring Boot"라는 값을 "data"라는 이름표를 붙여 저장했다.


이렇게 저장해 두면 뒤에서 만드는 html 파일이 그 값을 꺼내서 화면에 보여 줄 수 있다.
즉, Controller는 화면 자체를 그리는 곳이 아니라 화면에 필요한 데이터를 준비해서 넘겨주는 곳이다.


왜 파일 이름을 반환하는가

초보자가 여기서 자주 헷갈리는 부분은 문자열 "Spring Boot"를 바로 브라우저에 출력하는 것이 아니라 "helloView"를 반환한다는 점이다.
이것은 글자를 그대로 브라우저에 보내겠다는 뜻이 아니다.
helloView라는 이름의 화면 파일을 찾아서 그 화면을 보여 주겠다는 뜻이다.


여기서 중요한 점은 "helloView"가 그냥 일반 문장이 아니라 보여 줄 화면 파일을 가리키는 이름이라는 것이다.
그래서 이 단계는 아래 흐름으로 이해하면 된다.

  • /hello 요청이 들어온다.
  • HelloController가 실행된다.
  • Model에 데이터를 담는다.
  • helloView.html로 이동한다.
  • 브라우저에 화면이 출력된다.

이 흐름이 잡히면 뒤에서 html 파일을 볼 때 훨씬 덜 헷갈린다.




화면 파일 만들기

Controller가 요청을 받고 데이터를 준비했다면, 이제 그 데이터를 실제 화면으로 보여 줄 파일이 필요하다.
그 파일이 helloView.html이다.


이 파일은 src/main/resources/templates 폴더 아래에 만든다.
즉, 이 파일은 브라우저에 보일 결과 화면의 틀을 담당한다.


왜 templates 폴더에 만들어야 하는가

초보자는 html 파일이기만 하면 아무 폴더에나 만들어도 될 것처럼 느낄 수 있다.
하지만 Spring Boot는 화면 파일을 찾을 때 보통 templates 폴더를 기준으로 찾는다.


그래서 Controller에서 "helloView"를 반환하면 Spring Boot는 templates 폴더 안에서 helloView.html을 찾아 연결하려고 한다.
즉, 파일 이름만 맞는다고 끝나는 것이 아니라 파일 위치도 맞아야 정상적으로 연결된다.


이 점을 모르고 다른 폴더에 파일을 만들면 코드가 맞아 보여도 화면이 열리지 않을 수 있다.
그래서 지금 단계에서는 templates 폴더가 화면 파일을 두는 기본 위치라고 이해하면 된다.


templates와 static의 차이

이 둘은 이름이 비슷해 보여서 초보자가 자주 헷갈린다.
하지만 역할은 다르다.

  • templates
    서버가 데이터를 넣어서 완성된 화면을 만드는 위치이다.

  • static
    그대로 제공되는 정적 파일을 두는 위치이다.

즉, ${data}처럼 서버 값이 들어가는 화면 파일은 templates에 두고, css, js, 이미지 파일처럼 그대로 제공되는 파일은 static에 둔다.
이 차이를 알고 있으면 이후 실습에서도 파일 위치 때문에 덜 헷갈리게 된다.


템플릿 코드

// helloView.html
<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8" />
    <title>첫번째 Spring Boot 기반 MVC 테스트</title>
</head>
<body>
    <h1>첫번째 Spring Boot 기반 MVC 테스트</h1>
    <hr />
    <h2>반갑다!! [[${data}]]</h2>
    <h2>잘해보자~~ <span th:text="${data}">뭐라두</span>!!</h2>
    <h3>그러자</h3>
</body>
</html>

이 코드는 그냥 html만 있는 것처럼 보이지만, 중간에 [[${data}]]와 th:text="${data}"가 들어 있다.
이 부분이 바로 서버에서 넘긴 값을 화면에 출력하는 자리다.


앞에서 HelloController.java에서 "data"라는 이름으로 "Spring Boot"를 넘겼기 때문에, 이 파일에서는 그 값을 꺼내서 사용할 수 있다.
즉, Controller와 템플릿 파일이 여기서 연결된다.


여기서 Thymeleaf는 화면 틀 안에 서버 데이터를 끼워 넣어 주는 도구라고 이해하면 된다.
그리고 xmlns:th는 이 파일 안에서 th:text 같은 Thymeleaf 문법을 사용하겠다는 표시 정도로 보면 된다.


[[${data}]]와 th:text의 차이

두 문법 모두 화면에 값을 출력하는 데 사용된다.
하지만 쓰는 위치와 방식이 조금 다르다.

  • [[${data}]]
    문장 안에 값을 바로 끼워 넣을 때 편하다.

  • th:text="${data}"
    특정 태그의 글자를 통째로 바꿔 넣을 때 사용한다.

여기서는 반갑다!! 뒤에 값을 자연스럽게 붙여 보여 주기 위해 [[${data}]]를 사용했다.
반면 <span> 태그 안의 기본 글자 "뭐라두"를 실제 실행 시 "Spring Boot"로 바꾸기 위해 th:text를 사용했다.


둘 다 같은 값을 출력하지만 완전히 같은 방식은 아니다.
하나는 문장 안에 직접 넣는 방식이고, 다른 하나는 태그 안의 글자를 바꾸는 방식이다.


여기서 꼭 확인해야 하는 연결 관계

지금까지 작성한 코드는 따로 움직이지 않는다.
HelloController.java에서 data라는 이름으로 값을 담았기 때문에 helloView.html에서 ${data}를 읽을 수 있다.


만약 이름이 서로 다르면 값이 출력되지 않는다.
예를 들어 Controller에서는 "data"라고 저장했는데 html에서는 ${msg}라고 쓰면 연결되지 않는다.


그래서 이 단계에서 가장 중요한 것은 문법을 많이 외우는 것이 아니라 Controller에서 저장한 이름과 템플릿에서 꺼내는 이름이 반드시 같아야 한다는 점이다.
이 연결만 정확히 맞으면 화면에 원하는 값이 정상적으로 출력된다.




Thymeleaf는 무엇인가

Thymeleaf는 서버가 준비한 데이터를 HTML 화면에 넣어 주는 템플릿 엔진이다.
여기서 템플릿 엔진은 화면의 틀은 HTML로 두고, 그 안에 필요한 값만 서버에서 가져와 끼워 넣어 최종 화면을 만들어 주는 도구라고 이해하면 된다.


지금 실습에서는 HelloController.java가 "Spring Boot"라는 값을 준비하고, helloView.html이 그 값을 화면에 보여 준다.
이 둘을 실제로 연결해 주는 역할을 하는 것이 바로 Thymeleaf이다.


즉, Controller가 값을 준비했다고 해서 자동으로 화면에 글자가 보이는 것은 아니다.
그 값을 어떤 위치에 넣을지 정하고, 실제 HTML 안에 반영해서 브라우저에 보여 주는 중간 연결 도구가 필요하다.
그 연결 도구가 Thymeleaf라고 보면 된다.


처음에는 [[${data}]]나 th:text 같은 문법만 눈에 들어오기 쉽다.
하지만 더 중요한 것은 문법을 외우는 것보다 서버의 값이 화면으로 바뀌는 흐름을 이해하는 것이다.


왜 Thymeleaf가 필요한가

자바 웹 프로그램을 만들 때 화면까지 전부 자바 코드로 직접 만들 수도 있다.
하지만 그렇게 하면 HTML 구조가 코드 속에 섞여 들어가서 읽기 어렵고, 화면을 수정할 때도 불편해진다.


예를 들어 제목 하나 바꾸고 싶어도 자바 코드 안에서 긴 문자열을 찾아 수정해야 할 수 있다.
이 방식은 화면 구조를 한눈에 보기 어렵고, 초보자에게도 부담이 크다.


그래서 보통은 화면은 HTML 파일로 따로 두고, 값만 서버가 넘겨 주는 방식을 사용한다.
이렇게 하면 화면 구조는 HTML 파일에서 보고, 데이터 흐름은 Controller에서 볼 수 있어서 역할이 훨씬 분명해진다.


Thymeleaf는 바로 이 구조를 가능하게 해 준다.
즉, 화면 모양은 HTML이 맡고, 화면 안에 들어갈 실제 값은 서버가 준비하고, Thymeleaf가 그 둘을 연결한다.


초보자 기준에서는 이렇게 이해하면 가장 쉽다.
Thymeleaf는 HTML을 그대로 살려 두면서, 필요한 자리만 서버 데이터로 바꿔 주는 도구이다.


이 실습에서 Thymeleaf가 실제로 하는 일

이번 실습에서는 Controller가 먼저 데이터를 준비한다.
그다음 View 파일이 그 데이터를 꺼내서 화면에 보여 준다.
이 흐름을 코드로 보면 더 쉽게 이해할 수 있다.

// HelloController.java
package com.example.springedu.controller;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
@Controller
public class HelloController {
    @GetMapping("/hello")
    public String hello(Model model) {
        model.addAttribute("data", "Spring Boot"); // 화면에 넘길 값 저장
        return "helloView"; // helloView.html로 이동
    }
}

이 코드에서 model.addAttribute("data", "Spring Boot")는 "Spring Boot"라는 값을 "data"라는 이름표로 저장해서 화면에 넘기는 부분이다.
즉, Controller는 값을 직접 브라우저에 출력하는 것이 아니라, 화면에서 쓸 수 있게 먼저 준비만 해 둔다.


이제 화면 파일에서는 이렇게 값을 꺼내 쓴다.

// helloView.html
<!DOCTYPE html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8" />
    <title>첫번째 Spring Boot 기반 MVC 테스트</title>
</head>
<body>
    <h1>첫번째 Spring Boot 기반 MVC 테스트</h1>
    <hr />
    <h2>반갑다!! [[${data}]]</h2>
    <h2>잘해보자~~ <span th:text="${data}">뭐라두</span>!!</h2>
    <h3>그러자</h3>
</body>
</html>

여기서 [[${data}]]와 th:text="${data}"가 바로 Thymeleaf 문법이다.
즉, Controller가 넘긴 "data" 값을 Thymeleaf가 읽어서 HTML 안에 넣어 준다.


이 흐름을 순서대로 정리하면 아래와 같다.

  • 브라우저가 /hello를 요청한다.
  • HelloController가 실행된다.
  • Model에 "data"라는 이름으로 "Spring Boot"를 저장한다.
  • helloView.html이 열린다.
  • Thymeleaf가 ${data}를 읽는다.
  • "Spring Boot"를 화면에 넣는다.
  • 브라우저에 최종 결과가 보인다.

즉, Thymeleaf는 단순히 글자 하나를 출력하는 도구가 아니라, 서버가 만든 데이터를 실제 화면으로 바꾸는 마지막 연결 단계를 맡고 있다.


Thymeleaf 문법이 화면에서 어떻게 보이는가

처음 helloView.html을 보면 그냥 HTML 파일처럼 보인다.
하지만 중간에 일반 HTML만으로는 설명되지 않는 문법이 들어 있다.
바로 [[${data}]]와 th:text="${data}" 같은 부분이다.


이 문법들은 브라우저가 직접 이해하는 문법이 아니다.
서버가 먼저 Thymeleaf를 이용해 처리한 뒤, 최종적으로 일반 HTML 형태로 브라우저에 보내 주는 것이다.


즉, 브라우저는 Thymeleaf 문법을 해석해서 보여 주는 것이 아니라, 서버가 미리 값을 넣어서 완성한 결과만 받는다.
이 점을 이해하면 Thymeleaf는 브라우저 쪽 기술이 아니라, 서버가 화면을 준비할 때 사용하는 기술이라는 점도 자연스럽게 같이 잡힌다.


초보자는 여기서 “그럼 브라우저에는 [[${data}]]가 그대로 보이지 않나요?”라고 생각할 수 있다.
정상적으로 연결되었다면 그렇게 보이지 않는다.
서버가 먼저 이 부분을 "Spring Boot"로 바꿔서 보내기 때문이다.


th:text는 무엇인가

th:text는 특정 태그 안의 글자를 서버 값으로 바꿔 넣는 속성이다.
여기서 속성은 태그 안에 들어가는 추가 정보라고 이해하면 된다.
예를 들어 <span th:text="${data}">뭐라두</span>처럼 적으면, 실행할 때는 "뭐라두" 대신 "Spring Boot"가 들어간다.


즉, 태그 안에 적혀 있는 기본 글자는 실제 실행 결과가 아니라 임시 자리라고 보면 된다.
실행되면 Thymeleaf가 ${data}의 값을 읽어서 그 자리를 바꿔 준다.


이 문법이 중요한 이유는, 어떤 태그의 본문을 통째로 서버 값으로 바꾸고 싶을 때 아주 자주 사용하기 때문이다.
예를 들어 제목, 설명, 사용자 이름처럼 특정 위치의 글자를 바꾸고 싶을 때 th:text를 많이 쓴다.


그래서 th:text는 이렇게 이해하면 된다.
th:text는 태그 안의 글자를 서버 값으로 교체하는 가장 기본적인 Thymeleaf 문법이다.


[[${data}]]는 무엇인가

[[${data}]]는 문장 안에 값을 자연스럽게 끼워 넣을 때 자주 사용하는 문법이다.
예를 들어 반갑다!! [[${data}]]라고 적으면, 실행 결과는 반갑다!! Spring Boot처럼 보인다.


이 방식은 어떤 태그 전체를 바꾸는 것보다, 문장 중간에 값 하나를 끼워 넣고 싶을 때 편하다.
즉, 이미 문장이 있고 그 안에 일부 값만 바뀌면 될 때 자주 사용한다.


이 문법을 볼 때는 두 부분으로 나눠 이해하면 쉽다.

  • ${data}
    Model에 저장된 "data" 값을 읽겠다는 뜻이다.

  • [[ ... ]]
    읽어 온 값을 텍스트로 화면에 넣겠다는 뜻이다.

즉, ${data}는 어떤 값을 가져올지를 나타내고, [[ ]]는 그 값을 문장 안에 보이게 넣는 역할을 한다고 이해하면 된다.


그래서 th:text와 [[${data}]]는 둘 다 값을 출력하지만 완전히 같은 것은 아니다.
th:text는 태그 안의 글자를 바꾸는 방식이고, [[${data}]]는 문장 중간에 값을 끼워 넣는 방식이다.


왜 ${data}처럼 이름이 같아야 하는가

Controller에서는 model.addAttribute("data", "Spring Boot")처럼 값을 저장했다.
여기서 중요한 것은 "data"라는 이름이다.
이 이름이 HTML 파일에서 값을 꺼내는 기준이 되기 때문이다.


그래서 helloView.html에서도 ${data}처럼 같은 이름을 사용해야 한다.
만약 Controller에서는 "data"라고 저장했는데 HTML에서는 ${msg}라고 적으면, Thymeleaf는 "msg"라는 이름의 값을 찾으려 한다.
하지만 그런 값은 넘겨받지 못했기 때문에 원하는 결과가 나오지 않는다.


즉, 서버에서 저장한 이름과 화면에서 꺼내는 이름은 반드시 같아야 한다.
이 부분은 단순한 문법 문제가 아니라, 데이터가 정확히 연결되는 기준이다.


초보자는 값을 저장했다는 사실만 기억하고 이름까지는 가볍게 넘기기 쉽다.
하지만 실제로는 이름이 같아야 Controller와 화면 파일이 연결된다.
그래서 Model을 사용할 때는 값 자체뿐 아니라 이름도 같이 정확하게 봐야 한다.


xmlns:th는 왜 적는가

html 태그를 보면 xmlns:th="http://www.thymeleaf.org"라는 부분이 들어 있다.
처음 보면 주소처럼 보여서 어렵게 느껴질 수 있다.
하지만 지금 단계에서는 아주 단순하게 이해하면 된다.


이 파일 안에서 th:text 같은 Thymeleaf 문법을 사용하겠다는 표시라고 보면 된다.
즉, th:로 시작하는 문법이 이 파일 안에서 쓰인다는 것을 알려 주는 역할이다.


초보자 기준에서는 이 값을 외울 필요는 없다.
중요한 것은 Thymeleaf 문법을 쓸 때 이런 선언이 함께 들어갈 수 있다는 점만 알고 넘어가는 것이다.


Thymeleaf에서 자주 보는 th: 문법

Thymeleaf는 태그에 th: 속성을 붙여서 동작을 정하는 문법을 많이 사용한다.
그래서 th:text, th:if, th:each, th:href, th:value처럼 th:가 붙은 문법이 자주 나온다.


이 단계에서는 이 문법들을 전부 외울 필요는 없다.
지금은 th:가 붙으면 Thymeleaf가 화면을 처리하기 위한 문법이라고 이해하면 충분하다.


이번 실습에서는 그중에서도 가장 기본인 th:text만 먼저 익히면 된다.
나중에 조건문, 반복문, 링크 처리 같은 기능을 배우더라도 같은 흐름으로 이어진다.
즉, 지금 배우는 th:text는 따로 떨어진 문법이 아니라, 앞으로 나올 Thymeleaf 문법들의 출발점이라고 보면 된다.


Thymeleaf를 이해할 때 가장 중요한 관점

Thymeleaf를 배우면서 초보자가 가장 많이 하는 실수는 문법만 따로 외우는 것이다.
하지만 지금 단계에서는 문법 자체보다 흐름을 보는 것이 더 중요하다.


이번 실습에서 봐야 하는 핵심 흐름은 이것이다.

  • Controller가 값을 준비한다.
  • Model에 값을 담는다.
  • Thymeleaf가 그 값을 읽는다.
  • HTML 안에 넣는다.
  • 브라우저에 최종 화면이 보인다.

이 흐름이 잡히면 Thymeleaf는 어렵게 느껴지지 않는다.
그냥 HTML 안에 값을 넣어 주는 연결 도구로 자연스럽게 이해된다.


즉, Thymeleaf를 이해한다는 것은 문법 두세 개를 외우는 것이 아니라, 서버 데이터가 실제 화면으로 바뀌는 과정을 이해하는 것이다.
이 관점이 잡혀 있으면 다음에 조건 출력, 반복 출력, 링크 처리 같은 문법이 나와도 훨씬 덜 헷갈리게 된다.




실행 주소 설정하기

PDF 결과 화면과 지금 정리하는 결과 화면은 localhost:8088/hello 주소를 사용한다.
즉, 기본 포트인 8080이 아니라 8088로 실행되도록 맞춘 상태라고 보면 된다.


같은 결과를 보려면 application.properties에 포트 설정을 넣어 주면 된다.


설정 코드

// application.properties
server.port=8088

이 설정은 서버가 실행될 때 사용할 포트 번호를 바꾸는 역할을 한다.
포트는 같은 컴퓨터 안에서 여러 프로그램을 구분하는 문 번호 같은 것이라고 생각하면 된다.


기본값으로는 8080을 많이 사용하지만, 여기서는 결과 화면 주소를 8088로 맞추기 위해 바꾼 것이다.
그래서 브라우저 주소도 http://localhost:8088/hello로 들어가야 한다.


즉, 주소가 안 맞아서 페이지가 안 뜨는 경우에는 코드 문제만 볼 것이 아니라 포트 번호가 맞는지도 같이 확인해야 한다.


주소를 나눠서 읽기

처음 배우는 입장에서는 localhost:8088/hello를 그냥 한 덩어리로 외우기 쉽다.
하지만 나눠서 보면 훨씬 이해가 쉽다.

  • localhost
    지금 내가 작업 중인 내 컴퓨터를 뜻한다.
  • 8088
    서버가 열려 있는 포트 번호이다.
  • /hello
    어떤 요청으로 들어갈지 알려 주는 경로이다.

즉, 이 주소는 내 컴퓨터에서 실행 중인 서버의 8088번 포트로 접속해서 /hello 요청을 보낸다는 뜻이다.
이렇게 이해하면 다음 실습에서 /hello가 다른 경로로 바뀌어도 훨씬 쉽게 따라갈 수 있다.




인텔리제이에서 실행하고 결과 확인하기

이제 준비는 끝났다.
다시 SpringeduApplication.java를 실행하면 Spring Boot 서버가 올라가고, 우리가 만든 HelloController.java와 helloView.html이 함께 연결되어 동작한다.


여기서는 단순히 실행 버튼만 누르는 것으로 끝나지 않는다.
정상적으로 실행되었는지까지 확인해야 한다.


실행할 때 어디를 봐야 하는가

가장 먼저 IntelliJ에서 SpringeduApplication.java를 실행한다.
그다음 아래 Run 창에서 서버 시작 관련 메시지를 확인한다.
마지막에는 브라우저에서 http://localhost:8088/hello로 접속해서 결과 화면을 본다.


즉, 실행 확인 기준은 세 가지이다.

  • 실행 파일이 정상적으로 시작되었는가
  • 아래 Run 창에 에러 없이 서버가 올라왔는가
  • 브라우저에 /hello 결과가 정상적으로 보이는가

이 세 가지가 모두 맞으면 전체 연결이 제대로 된 것이다.


이클립스에서는 콘솔로 보이는데 인텔리제이에서는 왜 안 보이는가

여기서 표현을 정확하게 이해해야 한다.
IntelliJ에서 콘솔을 못 보는 것이 아니다.
IntelliJ에서도 아래 Run 창에서 콘솔 로그를 볼 수 있다.


다만 Spring Boot 웹 프로젝트에서는 확인하는 대상이 두 가지로 나뉜다.

  • 콘솔
    서버 실행 상태, 에러 메시지, System.out.println() 출력 같은 내부 로그를 본다.

  • 브라우저
    html이 렌더링된 최종 화면 결과를 본다.

즉, 이클립스든 IntelliJ든 웹 프로젝트에서는 실행 상태와 오류는 콘솔에서 확인하고, 사용자에게 보여 줄 최종 화면은 브라우저에서 확인한다.


초보자가 자주 헷갈리는 부분은 Controller 실행 결과가 전부 콘솔에 찍힐 것이라고 생각하는 점이다.
하지만 지금 실습은 웹 화면을 반환하는 구조이기 때문에, 최종 결과는 브라우저에서 확인하는 것이 맞다.


이 차이를 이해하면 “왜 콘솔에 화면이 안 나오지?”라는 혼란이 줄어든다.


실행 후 내부에서 일어나는 흐름

브라우저에 /hello 주소를 입력하면 서버는 그 요청을 HelloController로 보낸다.
HelloController는 Model에 "Spring Boot" 값을 담고 helloView 화면을 반환한다.
그러면 helloView.html이 열리면서 ${data} 자리에 "Spring Boot"가 들어간 결과가 출력된다.


여기서 렌더링이라는 말은 준비된 화면 파일을 실제 브라우저에 보이는 결과로 만들어 주는 과정이라고 이해하면 된다.
즉, 눈에 보이는 결과는 한 화면이지만 내부에서는 아래 순서로 움직인 것이다.

  • SpringeduApplication.java가 실행된다.
  • 서버가 시작된다.
  • /hello 요청이 들어온다.
  • HelloController가 실행된다.
  • Model에 데이터가 저장된다.
  • helloView.html이 렌더링된다.
  • 브라우저에 최종 화면이 출력된다.

이 흐름을 이해하면 지금 실습은 단순히 코드 몇 줄을 친 것이 아니라 Spring Boot 기반 MVC가 어떻게 연결되는지 직접 확인한 것이 된다.


최종 결과 확인

아래와 같이 브라우저에 결과가 보이면 정상적으로 연결된 것이다.

이 화면에서 확인할 수 있는 것은 단순히 글자가 보인다는 사실만이 아니다.
h1 제목은 템플릿에 작성한 고정 문장이고, 반갑다!! Spring Boot, 잘해보자~~ Spring Boot!! 부분은 Controller가 넘긴 값이 실제로 화면에 들어간 결과다.


즉, 여기서 보이는 결과는 실행 클래스, Controller, 템플릿 파일, 포트 설정이 모두 정상적으로 연결되었다는 증거다.




마지막으로 흐름 정리하기

이번 실습의 핵심은 파일별 역할을 분리해서 보는 것이다.
build.gradle은 프로젝트가 사용할 기능을 준비하고, SpringeduApplication.java는 프로그램을 시작하고, HelloController.java는 요청을 처리하고, Model은 화면에 넘길 데이터를 담고, helloView.html은 화면을 출력하고, application.properties는 실행 환경을 설정한다.


그리고 IntelliJ에서는 파일 위치를 확인하고, 실행 버튼으로 서버를 시작하고, 아래 Run 창에서 로그를 보고, 브라우저에서 최종 결과를 확인한다.
즉, 각 파일과 도구가 맡은 일이 서로 다르다.


이 흐름이 연결되면 브라우저에서 /hello 요청 하나를 처리할 수 있다.
그래서 이번 실습은 단순히 Spring Boot 프로젝트를 한 번 실행해 본 것이 아니라 웹 프로그램이 어떤 파일들의 협력으로 움직이는지 처음 확인한 단계라고 볼 수 있다.


특히 가장 중요하게 기억할 부분은 이것이다.
Gradle이 필요한 기능을 준비하고, 실행 파일이 서버를 시작하고, Controller가 요청을 받고, Model이 데이터를 담고, 템플릿이 화면을 만든다.
이 흐름을 짧게 다시 쓰면 Gradle 준비 → 실행 클래스 시작 → Controller 요청 처리 → 템플릿 화면 출력이다.
이 큰 흐름만 정확히 잡아도 다음 실습으로 넘어갈 때 훨씬 덜 헷갈리지 않는다.

0개의 댓글