Spring & SpringBoot

[Spring 입문] Spring Boot 프로젝트 생성, 실행, 빌드

유자바 2024. 7. 16. 00:36

Spring Boot 기반으로 Spring 프로젝트를 만들어주는 spring initializr를 통해 프로젝트를 생성한다.

 

프로젝트는 다음과 같이 선택하면 된다.

  • Project: Gradle - Groovy
  • Spring Boot: 3.0.0 이상 (정식 릴리즈된 버전으로 선택하기)
  • Language: Java
  • Packaging: Jar
  • Java: 17 or 21

Project Metadata

  • groupid: 도메인명을 작성
  • artifact: 빌드되어 나올 때의 결과물 즉, 프로젝트명

Dependencies

  • Spring Web: 웹 프로젝트를 만들기 위해 선택해야 하는 dependency
  • Thymeleaf: HTML을 만들어줄 템플릿 엔진

 

여기서 잠깐⚠️ Project 선택 시 Maven과 Gradle 둘 중 하나를 선택할 수 있는데 왜 Gradle을 선택할까?

Maven과 Gradle은 빌드 관리 도구인데 아래와 같은 이유로 Gradle이 더 뛰어난 성능을 보인다.
1. 빠른 빌드 속도: Gradle은 Maven보다 빌드와 테스트 실행 결과가 더 빠르다. 또한 Gradle은 캐시를 사용해 테스트 반복 시 실행 결과 시간의 차이가 더 커진다. 
2. 스크립트 품질의 차이: Gradle은 Groovy를 사용해 동적인 빌드는 Groovy 스크립트로 플러그인을 호출하거나 직접 코드를 작성할 수 있다.

참고: https://hyojun123.github.io/2019/04/18/gradleAndMaven/

 

 

 

위의 그림과 같이 설정해주고 generate 해 폴더를 다운로드하였다.

 

IntelliJ에서 다운로드한 것을 import 해주는데 build.gradle 파일(버전 설정하고 라이브러리 가져오는 역할)을 선택 후 Open as Project 버튼을 통해 프로젝트로써 파일을 열어준다.

 

여기서 잠깐⚠️ 다운로드한 파일 전체를 IntelliJ에서 오픈할 수 있는데 왜 build.gradle 파일을 선택해 프로젝트를 오픈하는 걸까?

그 이유는 가끔 프로젝트를 열 때, Gradle 프로젝트로 인식하지 못하는 경우가 있어 build.gradle 파일로 프로젝트를 열어 이런 상황을 방지하고자 하는 것이었다!

참고: 인프런 질문 게시판

 


 

코드 작성하기에 앞서 build.gradle 파일에 대해 간단하게 알아보자!

Gradle은 의존성 관리를 위한 빌드 도구로 build.gradle에서 눈여겨봐야 할 곳은 의존성과 관련된 부분이다.

plugins {
	id 'java'
	id 'org.springframework.boot' version '3.3.1'
	id 'io.spring.dependency-management' version '1.1.5'
}

group = 'com.youjava'
version = '0.0.1-SNAPSHOT'

java {
	toolchain {
		languageVersion = JavaLanguageVersion.of(17)
	}
}

// 라이브러리 다운 받는 레포지토리 설정
// 필요 시 특정 사이트의 url 작성
repositories {
	mavenCentral() 
}

// 선택한 라이브러리 목록
dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
	implementation 'org.springframework.boot:spring-boot-starter-web'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
	testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}

tasks.named('test') {
	useJUnitPlatform()
}

 

 

의존성은 dependencies 블록 내에 선언하고, Gradle은 선언된 의존성을 자동으로 다운로드하고, 빌스와 테스트에 사용한다.

 

repositories 메서드

  • 저장소 설정 담당
  • mavenCentral(): 기본적으로 라이브러리를 다운로드하는 default repository
  • maven: 필요한 repository를 가져와야 할 때 사용

dependencies 메서드

  • 의존성 라이브러리 추가 시 사용
  • implementation: 의존 라이브러리 수정 시 본 모듈까지만 재빌드
  • testImplementation: 테스트 코드를 수행할 때만 적용
  • api: 의존 라이브러리 수정 시 본 모듈을 의존하는 모듈들 전부 재빌드

아직은 시작 단계이니 이 정도까지만 알아두고 점차 공부하는 것으로 하자

 


 

Spring Boot 프로젝트를 실행하기에 앞서 HelloSpringApplication.java 코드를 알아보자!

package com.youjava.hello_spring;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class HelloSpringApplication {

	public static void main(String[] args) {

		SpringApplication.run(HelloSpringApplication.class, args);
	}
}

 

main 메서드를 실행하면 SpringApplication.run 안에 지정된 클래스인 HelloSpringApplication이 실행되고, @SpringBootApplication 어노테이션으로 인해 Spring Boot Application이 실행된다. 이때 tomcat이라는 웹서버를 자체적으로 띄우면서 Spring Boot가 같이 실행이 되는 것이다.

 

 

HelloSpringApplication.java를 실행시켜 보면 아래의 그림과 같이 Tomcat started on port 8080 문구를 볼 수 있다.

 

 

localhost:8080을 실행해 보면 아래와 같은 페이지를 볼 수 있는데 아직 코드를 작성해 놓은 것이 없어 error가 뜨는 것이다.

 

 


 

이제 간단한 Welcome Page를 만들어 볼 것인데, Welcome Page를 위한 코드를 작성하기 전 Spring Boot의 Welcome Page 동작 방식을 살펴보자!

Spring Boot는 static과 template의 welcome page를 모두 제공하는데, static의 index.html을 가장 먼저 실행하고, static의 index.html을 찾을 수 없으면 template의 index 파일을 확인한다. static와 template에서 index 파일을 찾을 수 없으면 자동적으로 애플리케이션의 welcome page를 사용하는 동작 방식을 가지고 있다.

 

📂 resources/static/index.html

<!DOCTYPE HTML>
<html>
<head>
    <title>Hello</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
Hello
<a href="/hello">hello</a>

 

위와 같이 static의 index.html 파일을 작성해주었다.

 

해당 html 코드는 hello 문구를 클릭하면 /hello로 페이지가 이동하는 코드이다. 하지만 아직 /hello 페이지 코드를 작성하지 않아 클릭 시에는 아래와 같이 error 페이지를 반환한다.

 

 

 

 

이제 Web Controller를 만들어 지정된 뷰에 모델 객체를 넘겨주고 화면에 띄울 것이다.

여기서 잠깐⚠️ Spring Boot의 Controller란?

Spring 프레임워크는 MVC 패턴을 채택한다.
MVC 패턴은 Model View Controller의 줄임말로, Controller가 View(화면)와 Model(비즈니스 로직)을 연결시켜주는 다리 역할을 한다. 예를 들어 /hello로 가달라는 사용자의 요청이 들어오면 어디로 갈지 맞는 길을 안내하는 것이다.

Controller의 역할을 수행하기 위해서는 @Controller annotation을 사용한다. 해당 어노테이션을 사용하면 Spring 프레임워크에 해당 클래스를 Controller로 사용한다고 알리게 된다.

참고: https://goddaehee.tistory.com/203 , https://luanaeun.tistory.com/200

 

controller를 모아 놓는 디렉토리를 먼저 만들 것이다.

 

위와 같이 src/main/java/domain명/controller 디렉토리를 만들고

해당 디렉토리에 HelloController.java를 만들어 Controller 역할을 수행하는 클래스를 만든다.

 

package com.youjava.hello_spring.controller;

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

@Controller
public class HelloController {

    @GetMapping("hello")
    public String hello(Model model){
        model.addAttribute("data", "hello!");
        return "hello"; //templates의 hello.html 실행
    }
}

 

model에 hello!라는 데이터를 만들고 templates의 hello.html을 실행하도록 반환값을 설정해주었다.

templates의 hello.html는 다음과 같이 작성해주었다.

 

<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title>Hello</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
</head>
<body>
<p th:text="'안녕하세요. ' + ${data}" >안녕하세요. 손님</p>
</body>
</html>

 

Thymeleaf 템플릿 엔진을 사용하기 위해 상단에 <html xmlns:th="http://www.thymeleaf.org"> 를 작성해주었다.

 

해당 코드의 결과는 아래와 같다.

 

 

 

 

HelloController.java에서 Model에 설정해준 data가 웹 페이지에 보여지는 것을 확인할 수 있다.

 

동작 환경 그림을 보며 동작 방식을 이해해보겠다.

  • 컨트롤러에서 리턴 값으로 반환한 화면을 viewResolver가 찾아서 처리한다.
    • resources: templates/ + {viewName} + .html

 


 

그렇다면 이제 intelliJ IDE에서만 실행하는 것이 아닌 build 파일을 만들어 build 파일로 실행하는 방법을 알아보자!

 

mac을 기준으로 작성해보면

  1. 터미널 이동

  2. Spring Boot 프로젝트가 있는 경로로 이동

  3. ./gradlew build

  4. cd build/libs

  5. java -jar [만들어진 jar 파일 이름]

 

 

jar 파일을 이용해 서버를 실행할 수 있다!

 

여기서 잠깐⚠️ ./gradlew build 시 왜 jar 파일이 두 개가 생성될까?

./gradlew build 시 hello-spring-0.0.1-SNAPSHOT.jarhello-spring-0.0.1-SNAPSHOT-plain.jar이 생기는 것을 확인할 수 있다.

executable archive vs plain archive
- executable archive: jar 파일은 bootJar 테스크에서 생성된 아카이브
- plain archive: plain.jar 파일은 jar 테스크에서 생성된 아카이브
- plain archive는 어플리케이션 실행에 필요한 모든 의존성을 포함하고 있지 않고, 작성된 코드의 클래스 파일과 리소스 파일만 포함해 plain archive로 java -jar을 실행하면 에러가 발생한다.

빌드 시 plain archive가 생성되지 않도록 하기 위해서는 아래 코드를 build.gradle에 추가해주면 된다!
tasks.named("jar") {
	enabled = false
}


참고: https://docs.spring.io/spring-boot/gradle-plugin/packaging.html#packaging-executable.and-plain-archives

 

 

 

** 해당 포스팅은 인프런의 김영한 님 강의 중 스프링 입문-코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술을 토대로 작성했습니다