섹션 9. Spring Boot의 이모저모

김민지·2025년 4월 2일

서버 기초 강의

목록 보기
9/12

build.gradle 이해하기

  • build.gradle : build script라고도 불리며, gradle을 사용하여 프로젝트를 빌드하고 의존성을 관리하기 위해 작성됨
    현재는 groovy 라는 언어를 사용해서 작성되었으며, kotlin으로 작성할 수도 있다. (jvm 계열이면 전부 가능)
plugins { // 플러그인들을 여기에 추가할 수 있음!
	id 'org.springframework.boot' version '2.7.6'
	id 'io.spring.dependency-management' version '1.0.12.RELEASE'
	id 'java'
}
  • 플러그인들의 역할
    • org.springframework.boot: 스프링을 빌드했을 때 실행 가능한 .jar 파일이 나오도록 해줌으로서 스프링 어플리케이션을 실행할 수 있도록 도와줌. 또한, 다른 플러그인들이 잘 적용될 수 있도록 해줌.
    • io.spring.dependency-management : 외부 라이브러리나 프레임워크 버전관리에 도움을 주고, 서로 얽혀있는 의존성 처리를 도움
    • java : Java 프로젝트를 개발하는데에 필요한 기능들을 추가하고, 다른 JVM 언어 Gradle 플러그인을 사용할 수 있는 기반을 마련함
group = 'com.example' // 프로젝트의 그룹
version = '0.0.1-SNAPSHOT' // 프로젝트의 버전 (.jar 파일명에서도 확인 가능)
sourceCompatibility = '11' // JDK의 버전

repositories { // 외부 라이브러리나 프레임워크를 가져오는 장소 설정
	mavenCentral() // = maven 중앙 저장소에서 가져와라
}

dependencies { // 우리가 사용하는 라이브러리나 프레임워크를 표시하는 곳
	implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
	implementation 'org.springframework.boot:spring-boot-starter-web'
	runtimeOnly 'com.h2database:h2'
	runtimeOnly 'mysql:mysql-connector-java'

	testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

tasks.named('test') { // 테스트를 수행할 때, JUnit5를 사용하겠다는 의미
	useJUnitPlatform()
}

의존성

  • 표시 방법: org.springframework.boot:spring-boot-starter-data-jpa 를 예로 들어보면, : 를 기준으로 해서 앞에 나오는 org.springframework.boot는 해당 의존성을 만든이를 표시하는 것이고, 뒤에 나오는 spring-boot-starter-data-jpa는 실제 의존성의 이름을 뜻함.

  • Dependency Configuration: implementation, runtimeOnly, testImplementation

    • implementationruntimeOnly 의 차이: implementation은 해당 의존성을 항상 사용할 때 붙이고, runtimeOnly는 해당 의존성을 코드 실행 도중에만 사용할 때 붙임.
    • testImplementation : 테스트코드를 실행하거나 컴파일할 때 항상 사용한다는 의미
  • 각 의존성의 의미

    • org.springframework.boot:spring-boot-starter-data-jpa: JPA를 Spring과 함께 사용하기 위해 필요한 모든 것

    • org.springframework.boot:spring-boot-starter-web: 스프링으로 Web 개발을 하기 위해 필요한 모든 것 (Tomcat, Api를 만들 수 있게 도와주는 다양한 어노테이션 등등..)

    • com.h2database:h2: H2 데이터베이스를 사용하기 위해 필요한 의존성

    • mysql:mysql-connector-java: MySQL 데이터베이스를 사용하기 위해 필요한 의존성

    • org.springframework.boot:spring-boot-starter-test: 스프링을 사용해 테스트를 작성하기 위해 필요한 라이브러리와 프레임워크가 모여있는 의존성

Spring과 Spring Boot의 차이점

  1. 기존의 Spring에서 스프링 컨테이너, 의존성 주입, 트랜젝션 등등의 강력한 기능들을 사용하기 위해 정말 많은 xml 설정이 필요했던 반면, Springboot에서는 Java 기반의 어노테이션 기반의 설정을 적극 활용해 기본적으로 필요한 것들을 모두 자동 설정할 수 있도록 함
    예: Jdbc template를 우리가 의존성 주입 받아서 사용한 것도 Springboot가 자동으로 설정해주었기 때문!

  2. 기존의 Spring에서는 개발에 필요한 모든 라이브러리나 프레임워크를 직접 적어야 했던 반면, SpringBoot에서는 기본적으로 필요한 라이브러리들을 앞서 살펴본 org.springframework.boot:spring-boot-starter-data-jpa 라는 의존성으로 묶어서 편리하게 제공함
    ➢ 확장성이 보다 더 강력해짐! JPA를 사용해야 한다면 JPA starter를, Security를 사용해야 한다면 Security starter를 사용하면 됨

  3. MSA에 적합한 모니터링
    MSA: 하나의 거대한 서버를 이용하는 대신, 작은 서버들을 잘게 쪼개서 각 관심사에 맞는 부분들만 관리하는 것

application.ymlapplication.properties, lombok

  • application.yml.yml 은 YAML의 약자로, Yet Another Markup Language이다.

  • 기본적으로 key : value 형태로 작성된다. 아래의 예시에서는 spring: config: activate: on-profile:key이고, localvalue 이다.

spring:
  config:
    activate:
      on-profile: local
  • value 에는 참/거짓, 숫자, 문자열, 배열이 들어갈 수 있다.
  • 추가로, value 에 배열을 넣어야 하는 경우는 아래와 같이 표기한다.
person:
  name: minji
  age: 23
  dogs: 
    - choco
    - mango
  • #으로 주석을 표기할 수 있다.

그렇다면 Spring을 설정하기 위해서는 무조건 .yml을 사용해야 할까?

  • application.properties라는 파일을 사용할 수도 있다. 그러나 중복도 많고 가독성이 아쉬운 부분이 있어서 최근에 많이 사용되지는 않는다.

lombok이란?

  • 필드가 많아지고 프로젝트가 커질수록 보일러 플레이트 코드 (getter, setter, 생성자 등과 같이 단순 반복되는 코드)를 만드는 것은 번거로우므로, 이를 제거하기 위해 사용하는 라이브러리가 lombok이다.

  • 그렇다면 우리 프로젝트에 lombok을 도입해보자!

  1. lombok 의존성을 추가하고,

  2. InteliJ lombok 플러그인을 추가하고, (돋보기 모양 클릭 후 아래와 같이 Actions 선택, plugins 검색 ▷ Marketplace 선택 후 lombok 검색해서 설치)

  3. InteliJ Annotation Processor 설정을 해줘야 한다. (돋보기 모양 클릭 후 아래와 같이 Actions 선택 후 Annotation Processor 검색, Enable annotation processing 체크 ☑︎)

  4. build.gradle 에서, annotationProcessor 'org.projectlombok:lombok을 의존성에 추가해주자 (gradle이 인식하지 못해 오류가 날 수 있으므로)

lombok 사용해보기

  • 아래의 코드와 같이, getter() 함수들을 @Getter 어노테이션으로 대체할 수 있음!
package com.group.libraryapp.dto.user.request;

import lombok.Getter;

@Getter
public class UserCreateRequest {
    private String name;
    private Integer age = null;

    public UserCreateRequest() {}
    public UserCreateRequest(String name) {
        this.name = name;
    }

//    public String getName() {
//        return name;
//    }
//
//    public Integer getAge() {
//        return age;
//    }

}
  • 또한, @NoArgsConstructor 어노테이션은 클래스의 기본 생성자를 자동으로 생성해주는 역할을 해서 Entity 클래스에 붙여주면 유용하게 사용할 수 있음. access = AccessLevel.PROTECTED 옵션을 주면 우리가 앞서 생성했듯, 접근권한을 protected로 설정할 수 있음.
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED) // ☑︎ 기본 생성자 대신 붙일 수 있음
public class User {
    @Id // 이 필드를 PK로 간주한다는 의미
    @GeneratedValue(strategy = GenerationType.IDENTITY) // 자동생성되는 값임을 의미
    private Long id = null;

    @Column(nullable = false, length = 20)
    private String name;

    private Integer age;

    @OneToMany(mappedBy = "user")
    private List<UserLoanHistory> userLoanHistories = new ArrayList<>();

//    protected User() {} // ☑︎ Entity 클래스이므로 기본 생성자가 필요함
  • @RequiredArgsConstructor 어노테이션은 현재 존재하는 필드들에 꼭 필요한 생성자를 자동으로 만들어주는 역할을 함.
@Service
@RequiredArgsConstructor // 현재 존재하는 필드들에 꼭 필요한 생성자가 자동으로 생김
public class BookService {
    private final BookRepository bookRepository;
    private final UserLoanHistoryRepository userLoanHistoryRepository;
    private final UserRepository userRepository;

//    public BookService( // spring container로부터 의존성을 주입받기 위해 생성자 사용
//            BookRepository bookRepository,
//            UserLoanHistoryRepository userLoanHistoryRepository,
//            UserRepository userRepository
//    ) {
//        this.bookRepository = bookRepository;
//        this.userLoanHistoryRepository = userLoanHistoryRepository;
//        this.userRepository = userRepository;
//    }
  • 이외에도 @Setter, @EqualsAndHashCode, @ToString 어노테이션 등등이 존재함.
    이러한 어노테이션들은 보일러 플레이트 코드를 줄이고자 사용됨. (record class 등도 동일한 목적으로 사용됨)

Spring Boot 2.7.x에서 3.0.x로 업데이트하기

  1. 자바의 최소 요구 버전이 11에서 17로 업데이트됨
  2. Third Party Library (우리 입장에서 1차 라이브러리는 스프링이고, 스프링이 다시 사용하는 라이브러리를 이렇게 부름)들의 버전 업데이트
    Spring Framework 6.0.x, Hibernate 6.1
  3. AOT(Ahead Of Time: 어플리케이션 시작 시간과 메모리 사용량을 줄일 수 있도록 함으로서 클라우드 친화적, serverless 구조 추구) 기초작업이 이루어짐
  4. Javax 대신 Jakarta 패키지 사용
  5. 모니터링 기능의 강화

업데이트 과정

  1. 자바 버전을 17로 업데이트하기



  2. Edit > Configuration 에서도 자바 버전 수정

  3. Settings에 들어가서 gradle 검색 후 자바 버전 수정

    자바 컴파일러에 들어가서 컴파일러 버전도 수정

  4. build.gradle에 들어가서 sourceCompatibility = '17'로 수정하기

  5. build.gradle에 들어가서 plugins 파트를 id 'org.springframework.boot' version '3.0.1'로 수정하기

  6. migration 해주기: 공식 가이드를 참고해서, build.gradledependencies 파트에 runtimeOnly 'org.springframework.boot:spring-boot-properties-migrator'를 추가해서 실행해주기

IntelliJ의 Run OpenRewrite Migration 버튼
build.gradle에서 나타나는 해당 버튼은 Java 버전 업그레이드, Spring Boot 버전 업그레이드 등에서 필요한 변경을 자동으로 코드에 반영해주는 코드 자동 리팩토링 도구를 실행하는 기능으로, 주로 다음과 같은 작업을 실행해준다.
Java 8 → 17/21, Spring Boot 2.x → 3.x, javax → jakarta등의 대대적인 수정시에는 클릭하는 것이 권장됨!

  • javax → jakarta로 바꿔줌 (Spring Boot 3.x부터 변경된 부분)
  • deprecated 된 메서드나 어노테이션을 새로운 것으로 교체
  • Java 8~17 사이 문법에 맞춰 람다식 등 개선
  • build.gradle 또는 pom.xml의 의존성 정리
  1. 이후 코드를 확인해보면 아래와 같이 오류투성이인 것을 발견할 수 있음. 이는 Spring boot 2.x.x 에서 Spring boot 3.x.x 로 업데이트되면서 javaxjakarta로 바뀌어서 일어나는 현상이다. 이를 해결하기 위해서는 간단하게, 위의 import문 위치에 import jakarta.persistence.*;를 추가해주기만 하면 된다.

    다른 코드들도 하나씩 확인해가며 오류가 발생하는 부분에 추가해주자 (주로 domain 클래스 등 @Entity 어노테이션 등을 활용하는 곳을 확인하자)
  • 추가로, @Transactinoal에서 발생하는 오류는 import javax.transaction.Transactional;를 삭제하고 import jakarta.transaction.Transactional;로 대체하면 해결됨!

0개의 댓글