[Spring Boot] Spring Boot 프로젝트 세팅하기 with Spring Boot 3

김희정·2024년 3월 22일
0

Spring

목록 보기
18/18

💎 들어가며

이번 포스팅에서는 Spring Initializer를 통해 새 프로젝트를 생성하면서 프로젝트를 세팅하는 과정을 공유해보고자 합니다.


1. 프로젝트 생성

1.1 새 프로젝트

Spring Initializer를 통해 새 프로젝트를 생성합니다.

이 때 우리는 또 한번의 선택을 거쳐야 하는데요, 바로 프로젝트 기술 환경 설정입니다.
프로젝트 이름부터 사용할 언어, 빌드 툴, JDK 버전, 패키징 타입까지 선택해줍니다.

💡 Check List

  • Project Name, Group, Artifact
  • Language: Java or Kotlin or ex
  • JDK, Java Version: 8 or 11 or 17
  • Build Tool: Gradle or Maven
  • Packing: jar or war
  • Spring Boot version

블로그 작성용 프로젝트이지만 나름 기술 선택에 있어 의의가 있습니다.

  • project 이름: Test용이라 spring이 정해준 대로 (demo...ㅋ)
  • group id: github에 작성용으로 올릴거라 내 아이디 경로로
  • language: 아직 코푸링을 할 자신이 없어 Java 선택
  • Build Tool: Gradle, Maven 둘다 써봤지만 느낀점: Gradle이 레퍼런스가 더 많고, Maven은 익숙. 보통 Maven 선택, 이번엔 Gradle 선택해봄
  • Java Version: 주로 Java 8 버전을 선택했지만, 신기술 도입(공부)를 위해 17로 선택
  • Packing: Spring Boot는 내장 톰캣이기 때문에 주로 jar로 패키징 하는 편

Spring Boot 버전을 선택하고, 사용할 라이브러리들(dependencies)을 선택합니다.

💡 Spring Boot Version

Spring Boot 버전을 선택할 때는 신중히 선택해야합니다.

  • Java 버전에 따라 가용한 Boot 버전
  • Boot 버전에 따라 관련 라이브러리들 자동 다운로드, 기존에 돌아가던 코드 안돌아갈 수 있음

가장 큰 예시로는 Spring Boot 2 => 3 Migration시 발생하는 문제들입니다.

  • javax 패키지jarkata 패키지
  • Spring Security 5Spring Security 6

1.2 기술 고민에 관한 고찰

직접 기술을 선택해보지 않았다면 기술을 선택하면서 기존에 쓰던데로 쓰면 되지, 이걸 왜 고민해? 하실 수는 있겠지만, 이는 새로운 기술을 도입(도전)하느냐 마느냐의 차이입니다.

  • 기존에 Java-Spring 스택을 Kotlin-Spring으로 변경해볼까?
  • 기존에 Java 8만 썼는데, 17로 해볼까?
  • 기존에 Maven만 고집했는데, 요즘에 Gradle을 많이 쓴다는데 써볼까?

많은 회사 혹은 개발자들은 이런 고민을 하죠

백엔드 개발자들은 프로젝트를 처음 구성할 때 사용할 기술에 관해 많은 고민을 합니다.

  • 우리 데이터베이스(DB)로 CockroachDB가 요즘 흥한다던데 이걸 사용해 보는 건 어떨까?
  • HTTP 클라이언트로 Retrofit이 좋을까 Feign을 사용하는 것이 좋을까?
  • MySQL은 좀 진부하지 않아? 새로운 걸 좀 해볼까?

이 과정은 짧게는 개발자들 사이의 갑론을박에서 길게는 윗선의 결정까지 적지 않은 시간적 비용이 소모됩니다.

문제는 이렇게 어려운 선택들이 프로젝트를 성공적으로 이끌게 되었는가? 물론 그럴 때도 있겠지만 프로젝트 중후반에서야 "아.. 이거 OO를 사용하면 안 되는 거였는데.."라는 후회(?)를 하게 되는 경우가 적지 않게 있고, 이미 선정된 기술들이 이것 저곳 비즈니스 코드들 깊이 뿌리내려 있는 상황이라 이러지도 저러지도 못하는 상황에서 힘들게 프로젝트를 마무리하게 되는 것을 심심치 않게 보았습니다.

출저 - Spring Boot Kotlin Multi Module로 구성해보는 헥사고날 아키텍처 일부 발췌


2. Configuration

2.1 Package 생성

우선, 프로젝트의 큰 뼈대를 잡기 위해 Package들을 생성합니다.

💡 왜 패키지를 미리 정의할까?

사실 이 Package 구조는 언제든 변할 수 있습니다. 저는 규칙을 정하는 것을 좋아하기에
무엇을 어디에 저장할 지 미리 구조를 정의해두면, 클래스가 이리저리 튀는 것을 방지할 수 있습니다.

이 패키지들은 제가 주로 사용하는 구조입니다.

  • annotation: 커스텀 어노테이션 클래스 모음
  • aop: AOP와 관련된 클래스(Aspect, ExceptionHandler, 등) 모음
  • api: API 작업과 관련된 클래스(RestController, Service, VO, 등) 모음
  • config: 전역 빈들을 관리하기 위한 클래스 모음
  • dao: DB 작업과 관련된 클래스(Entity, Repository, 등) 모음
  • utils: 기타 static 작업 유틸 클래스 모음

2.2 Bean Configuration

Spring Bean

Spring에서는 Spring의 IoC Container에 의해 관리되는 POJO(Plain Old Java Object)Bean이라고 부르며, 이러한 Bean들은 Spring을 구성하는 핵심 요소입니다.

Spring Bean

  • POJO(Plain Old Java Object)로써 Spring 애플리케이션을 구성하는 핵심 객체
  • Spring IoC 컨테이너(또는 DI 컨테이너)에 의해 생성 및 관리
  • class, id, scope, constructor-arg 등을 주요 속성

스프링은 컴포넌트 스캔을 통해 스프링 IoC 컨테이너에서 사용할 빈들을 등록합니다.

스프링에서 사용하는 컴포넌트(빈)에는 @Component, @Controller, @Service, @Repository, @Configuration 들이 있습니다.

  • @Component : 컴포넌트 스캔에서 사용
  • @Controlller : 스프링 MVC 컨트롤러에서 사용. 스프링 MVC 컨트롤러로 인식
  • @Service : 스프링 비즈니스 로직에서 사용. 사실 @Service 는 특별한 처리를 하지 않는다. 대신 개발자들이 '핵심 비즈니스 로직이 여기에 있겠구나.' 라고 비즈니스 계층을 인식하는데 도움이 된다.
  • @Repository : 스프링 데이터 접근 계층에서 사용. 스프링 데이터 접근 계층으로 인식하고, 데이터 계층의 예외를 스프링 예외로 변환해준다.
  • @Configuration : 스프링 설정 정보에서 사용. 스프링 설정 정보로 인식하고, 스프링 빈이 싱글톤을 유지하도록 추가 처리를 한다.

이러한 어노테이션을 POJO에 등록하면, Spring은 시작과 동시에 아래와 같이 지정된 basePackages의 하위 패키지들을 탐색하여 Spring Container에 등록합니다.

@SpringBootApplication
@ComponentScan(basePackages = "io.github.twinklekhj.demo")
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

최상위 경로를 입력하면 아래와 같은 경고 메시지가 뜨는데요, 이는 이미 내장하고 있기 때문에 쓸 필요없다는 것입니다.

Redundant declaration: @SpringBootApplication already applies given @ComponentScan

즉, 프로젝트가 인지하는 최상위 경로라면 사용할 필요없고, 그 외 다른 경로를 지정하고자 하면 basePackages를 따로 지정해야된다는 의미입니다.


설정 Bean 생성하기

패키지를 생성한 뒤에는 config 패키지에서 @Configuration, @Bean 어노테이션을 이용하여 전역적으로 사용할 Bean들을 생성합니다.

@Configuration, @Bean 어노테이션은 언제 사용할까?

이러한 어노테이션은 수동으로 빈을 직접 등록해줘야만 하는 상황일 때 사용합니다.

  1. 개발자가 직접 제어가 불가능한 라이브러리를 활용할 때
  2. 애플리케이션 전범위적으로 사용되는 클래스를 등록할 때
  3. 다형성을 활용하여 여러 구현체를 등록해주어야 할 때

예를 들면 아래와 같은 설정들이 있습니다.

  • DB 설정
  • RestTemplate 설정
  • WebMvcConfig 설정
  • Spring Security 설정
  • QueryDSL 설정

3. Spring Security 설정

Spring Boot 3를 이용하면 자동으로 Spring Security가 설정됩니다. 특히 가장 골치 썩는것은 CSRF 설정이죠

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;

@Configuration
@EnableWebSecurity
@ComponentScan(basePackages = "io.github.twinklekhj")
public class SecurityConfig {
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                .authorizeHttpRequests(registry -> {
                    registry
                            .requestMatchers("/**").permitAll()
                            .requestMatchers("/api/**").permitAll()
                            .requestMatchers("/static/**").permitAll();
                })
                .csrf(configurer -> {
                    configurer.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
                })
                .exceptionHandling(configurer -> {
                    configurer.accessDeniedPage("/error");
                });

        return http.build();
    }
}

4. Thymeleaf 설정

화면을 만들기 위해서 Template Engine인 Thymeleaf를 추가해주었습니다.

Spring Boot에서도 JSP를 사용할 수 있지만, 굳이 Spring에서도 빼고싶어하는 거를 넣고 싶지 않았기에 사뿐히 Thymeleaf로 갈아탔습니다.

Thymealeaf 설정은 간단합니다.


4.1 Dependency 추가

Maven

<dependency>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

Gradle

implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'

4.2 application.yml 수정

Thymeleaf는 기본적으로 application.properties 혹은 application.yml에서 설정 가능합니다. 아래는 기본적으로 많이 사용하는 설정 내용입니다.

# Spring Configuration
# - thymeleaf
spring:
  thymeleaf:
    suffix: .html
    prefix: classpath:/templates/
    enabled: true
    cache: false	# 개발중 false, 배포시 true

사실 이 설정은 Spring Auto Configure 기능에 의해 자동으로 설정됩니다.


4.3 View Controller 및 템플릿 파일 생성

HomeController

화면을 그릴 Controller를 생성합니다.

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

@Controller
public class HomeController {
    @GetMapping("/")
    public String home(){
        return "index";
    }
}

Thymeleaf Fragment

ThymeleafFragment 기능을 이용하여 html을 분해하여 조각 조각 붙일 수 있습니다.

기존에 Tiles를 이용하여 Template을 만들던 저에겐 코드 복붙이란 있을 수 없는 일이었죠. 아쉽게도 Thymeleaf에는 Tiles는 없지만 Fragment 기능을 활용하여 코드를 분리할 수 있습니다.

<html lang="en" xmlns:th="http://www.thymeleaf.org">

<header th:fragment="header">
    header
</header>

나누고자 하는 th:fragment 속성을 사용하여 fragment를 선언합니다.

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<body>
    <th:block th:replace="~{components/_header::header}"></th:block>
    <th:block th:replace="~{components/_side::sidebar}"></th:block>
    <main>
        Body
    </main>
    <th:block th:replace="~{components/_footer::footer}"></th:block>
</body>
</html>

<th:block> 태그를 이용하여 Fragment를 불러옵니다.

완성-⭐


💎 References


💎 마치며

profile
Java, Spring 기반 풀스택 개발자의 개발 블로그입니다.

0개의 댓글