[Spring boot in practice] 1. Spring boot 시작하기

최강일·2023년 11월 5일
0

Spring boot

목록 보기
6/7

1. 시작하기

1.1.1 왜 Spring boot인가

먼저 Spring 프레임워크는 복잡한 자바 엔터프라이즈 애플리케이션 개발을 단순화하자는 취지로 개발되었다.
개발자가 해야 할 일들을 대신해 주고 비즈니스 문제 해결에 더 집중할 수 있게 되었다.
하지만, Spring 프레임워크를 제대로 구동하기까지도 많은 설정과 시행착오가 필요했었다.

Spring boot는 그런 복잡한 설정, 애플리케이션 배포 시 필요한 서버 지식 등에서 해방시켜준다.
때문에 개발자가 쉽고 간단하게 애플리케이션을 만들어, 비즈니스 문제에 더 집중할 수 있게 도와준다.

엔터프라이즈 애플리케이션이란?
지속적으로 많은 양의 데이터를 처리하며, 여러 사람들이 접근하는 거대한 애플리케이션을 생각하면된다.

1.1.2 그래서 무엇인가

독립 실행형 애플리케이션을 간단한 설정으로 만들 수 있다.
Spring 기반으로 실제 사용 가능한 제품 수준의 독립 실행형 애플리케이션을 간단한 설정으로 만들 수 있다.
Spring boot는 Spring 프레임워크와 개발자 사이에 존재하는, 단순화해주는 역할을하는 "놈"으로 생각한다.

1.1.3 핵심 기능

  • 빠른 프로토타입(prototype) : 초기에 빠르게 구축하고 테스트하여 product를 빠르게 검증
  • 자동 구성(autoconfiguration) : classpath에 있는 파일들, 설정 파일에 지정된 property 정보를 바탕으로 컴포넌트를 구성
  • 사전 정의 방식(opinionated) : starter 의존 관계를 기준으로 자동으로 구성(spring-boot-starter-web 의존성만 추가하면 대부분의 의존성 관계에서 해방)
  • 독립 실행형(standalone) : Spring boot app은 웹 서버를 내장하고 있어서, 독립적으로 설치 및 실행이 가능(jar 패키징하여 실행)
  • 서비스 환경에서 사용가능(production-ready) : health-check, thread-dump 등을 수행하는 기능이 포함되어, 서비스 유지보수가 용이

1.1.4 Spring boot 컴포넌트

Spring boot는 특정 영역에 특화된 여러 가지 컴포넌트로 구성돼 있다.

  • spring boot
    • spring boot의 기본 컴포넌트로서 다른 컴포넌트를 사용할 수 있도록 지원
    • ex. 내장 tomcat 지원, app 설정 정보 기능등이 포함
  • spring boot - autoconfigure
    • spring boot app의 자동 구성 기능을 담당하는 컴포넌트로서, classpath와 설정 파일의 프로퍼티에 지정된 의존 관계를 바탕으로 추론해서 spring bean 생성
  • spring boot - starters
    • 미리 패키징된 의존 관계 모음. stater가 없으면 개발자가 모든 의존성 및 의존관계를 직접 설정해야한다.
  • spring boot - CLI(필요성 X)
    • Groovy 코드를 컴파일하고 실행할 수 있는 명령행 도구
    • 파일 내용 변경을 감지하는 기능이 있어서 app에 수정 사항이 발생할 때마다 직접 재부팅 할 필요가 없다.
    • maven,gradle 같은 의존성 관리도구로부터 벗어나, 빠르게 프로토타입 애플리케이션을 만들 수 있다.
  • spring boot - actuator
    • spring boot app을 모니터링하는 에이전트 제공
    • 기본적인 매트릭 외에도 커스텀 매트릭 추가 가능
  • spring boot - actuator autoconfigure
    • classpath에 있는 클래스 기반으로 actuator endpoint를 자동 구성해주는 컴포넌트
  • spring boot - test
    • 테스트 케이스 작성에 필요한 어노테이션과 메서드가 포함
  • spring boot - test autoconfigure
    • app 테스트 케이스에 필요한 의존 관계를 자동으로 구성
  • spring boot - loader
    • spring boot app을 jar 패키징 하는데 필요한 모든 의존 관계와 독립 실행형으로 실행할 수 있는 내장 was를 포함
  • spring boot - devtools
    • 개발을 도와주는 개발자 도구
    • ex. app 코드 변경 자동 감지 기능, HTML 변경 사항이 있으면 자동 브라우저 새로고침 등등

1.2.1 Maven vs Gradle

참고) Wrapper

  • Gradle Wrapper, Maven Wrapper
    • maven 또는 gradle을 로컬에 설치하지 않아도됨
    • 프로젝트용 특정 버전을 자동 다운로드하는 스크립트(ex. gradlew,gradlew.bat)
    • 이를 통해 프로젝트를 관리하는 개발자들이 동일한 gradle 버전을 사용하므로 호환성 문제를 방지할 수 있다.

1.2.2 Java vs Kotlin

  • java는 null-unsafety하다. 반대로 kotlin은 null-safety하다.
  • kotlin은 non-null에 null값이 들어가려고 하면 컴파일 에러가 발생한다고 한다.
  • jvm위에서 동일하게 작동하기 때문에 kotlin은 java와 100%호환된다고 할 수 있다.
  • 더욱 더 간결한 kotlin 소스코드

1.2.4 Lombok

lombok 어노테이션을 사용하여 POJO 객체의 생성자,getter,setter,toString 등을 자동 생성. + @Slf4j

1.3.1 Spring Initializr

spring boot 프로젝트의 뼈대를 쉽게 생성할 수 있다.
(이니셜라이저는 api가 제공되어 IDE에서 바로 사용할 수 있다. 다만 intellij ce에서는 spring framework 관련 플러그인 지원이 없어 사용이 불가능하다.)

1.3.2 프로젝트 구조

pom.xml

  • spring-boot-starter-parent를 지정하여, spring boot 하위 프로젝트임을 나타내고, 의존 관계 관리를 spring boot에게 맡긴다.
  • spring-boot-maven-plugin을 통해 app 관리,수행을 편리하게 할 수 있다.(ex. jar/war 패키징)

Spring boot starter 의존 관계

개발하면서 마주치게 되는 문제로 애플리케이션의 특정 컴포넌트를 개발하기 위해 필요한 lib(의존관계)를 식별하는 일이다.
각각의 lib에도 의존하는 lib가 있으며 이런 "의존 관계 전파"로 버전 문제는 굉장히 복잡해지기도 한다.


이런 문제에서 해방시켜주는 것이다.
필요한 의존 관계를 그룹 지어 사용할 수 있게 해준다. (spring-boot-starter-web -> spring-boot-starter,spring-boot-starter-tomcat,spring-boot-starter-json 등을 포함)
starter는 확장 및 커스텀이 가능하여 대규모 app 개발에 사용되는 의존 관계를 모듈화해서 관리할 수 있다.

(mvn dependency:tree를 통해 app 의존관계를 볼 수 있다)

spring boot maven 플러그인 골 목록

  • 이미지 빌드(spring-boot:build-image) : app을 오픈 컨테이너 이니셔티브(OCI) 이미지로 패키징
  • 빌드 정보 property 생성(spring-boot:build-info) : build-info.properties를 생성
  • 도움말 표시(spring-boot:help)
  • Jar/War export(spring-boot:repackage) : 실행 가능한 해당 파일로 만들어진다
  • app 실행(spring-boot:run) : 개발 단계
  • app 시작(spring-boot:start) : 배포 환경
  • app 종료(spring-boot:stop)

Spring boot Main 클래스

  1. main() 메서드 사용
  2. @SpringBootApplication 사용
  3. SpringApplication 클래스의 역할

일반적인 Web 애플리케이션을 실행하려면 애플리케이션 컴포넌트를 war로 빌드하고 tomcat과 같은 was에 배포해야한다.
spring boot는 이런 과정을 단순화하여, main() 메서드를 실행하는 전통적인 자바 애플리케이션을 실행하는 것처럼 Web 애플리케이션을 실행할 수 있다.

조금 더 설명하자면 spring boot 내장 서블릿 컨테이너 위에서 실행할 수 있게 만들었다.
내장된 기본 서블릿 컨테이너인 tomcat 서버를 시작하고 그 위에서 Web 애플리케이션을 실행한다.

@SpringBootApplication은 @EnableAutoCOnfiguration, @ComponentScan, @SpringBootConfiguration을 포함한다.

  • @EnableAutoCOnfiguration : classpath에 있는 Jar파일을 바탕으로 애플리케이션을 자동으로 구성해주는 기능을 활성화한다.
  • @ComponentScan
    • App에 있는 Spring Component를 탐색한다. (Spring Component는 @Component,@Bean 등으로 자바 빈으로서 스프링이 관리)
    • 해당 어노테이션이 붙으면, 어노테이션에서 지정한 디렉터리와 그 하위 디렉터리를 모두 탐색하고 라이프사이클을 관리한다.
  • @SpringBootApplication
    • spring boot app 설정을 담당하는 클래스에 이 어노테이션을 붙인다.
    • 내부적으로 @Configuration을 포함하고 있어서 이 설정 클래스는 컴포넌트 탐색으로 발견된다. 때문에 메인 클래스가 반드시 애플리케이션 루트 패키지에 있어야 한다. (이유 : 탐색 범위)
  • run() 실행 시 수행 과정
    1. classpath에 있는 lib를 기준으로 ApplicationContext 클래스 인스턴스를 생성한다.
    2. CommandLinePropertySource를 등록해서 명령행 인자를 spring property로 읽어 들인다.
    3. 1단계에서 생성한 ApplicationContext를 통해 모든 싱클턴 빈을 로딩한다.
    4. 애플리케이션에 설정된 ApplicationRunners와 CommandRunners를 실행한다.

ApplicationContext 다시보기

스프링 어플리케이션 전반에 걸쳐 모든 구성요소의 제어 작업을 담당하는 IOC 엔진
대부분의 java app은 여러 객체로 구성되고 서로 협력하므로 의존 관계가 생긴다.
객체 생성 및 상호 의존 관계를 효과적으로 관리하기 위해 스프링은 의존 관계 주입(dependency injection)을 사용한다.
의존 관계 주입 또는 제어의 역전(inversion of control)을 통해 빈 생성 시 필요한 의존 관계를 스프링이 주입해준다.
빈은 applicationContext.xml 같은 XML로 정의하거나 @Configuration을 붙여 클래스로 정의할 수 있다.
스프링은 이런 빈을 생성해서 Spring IOC 컨테이너에 담아두고 관리한다.

  • SpringApplication 클래스는 classpath에 있는 jar 의존 관계를 바탕으로 ApplicationContext 인스턴스 생성을 시도한다. servlet 타입이거나 reactive 타입이거나 둘 중 하나다. Spring은 classpath에 있는 클래스를 바탕으로 어떤 애플리케이션인지 유추한다. run()이 아닌 main() 메서드에서 reactive 타입의 app 지정이 가능하다.

설정 파일

src/main/resources에 application.properties 파일을 통해 서버 접속 정보나 db 접속 정보 등 app 설정 정보를 소스 코드와 분리한다.
key=value 형태로 따옴표 없이 작성한다.
properties 파일 외에도 yml 형식으로도 많이 사용한다. yaml을 사용하면 위계 구조를 사용하다보니 중복 텍스트를 줄일 수 있다.

1.3.3 실행 가능한 JAR 파일 만들기

가장 간단한 방법은 mvn package 명령을 사용하는 것이다.
처음 프로젝트를 생성할 때 패키징 타입을 선택하는데, 해당 명령어를 실행하면 target 디렉터리에 JAR 파일이 생성된다.
이 파일을 java -jar 명령의 인자로 지정하면 애플리케이션을 실행할 수 있다.

생성된 jar 파일에는 META-INF/MANIFEST.MF 파일에는 app을 시작할 클래스를 가리키는 Start-class, 그리고 Start-class를 사용해서 app을 시작하는 Launcher 클래스 이름이 지정돼 있다.

1.3.5 안전 종료

단순 프로세스를 종료하면 받은 요청들의 완료를 보장받지 못한다.
때문에 종료 명령이 실행되면 더 이상 요청을 받지 않되, 이미 받은 요청은 완료를 보장하는 안전 종료(gracefull shutdown) 설정이 필요하다.

  • server.shutdown=graceful
    • default는 immedate다.
  • spring.lifecycle.timeout-per-shutdown-phase=1m
    • default는 30s다. 처리중인 요청이 완료될 때까지 기다려주는 설정이다.

안전 종료 기능은 spring boot 2.3.0부터 도입되어서 이전 버전에서는 동작하지 않는다.

1.4 스프링 부트 기타 개념

1.4.1 Spring boot 스타트업 이벤트

Spring 프레임워크는 상황에 맞게 적절한 작업을 수행할 수 있도록 다양한 빌트인 이벤트가 내장돼 있다.
예를 들어 app이 시작되고 초기화가 완료됐을 때 외부 REST API를 호출하는 등 빌트인 이벤트 뿐만 아니라 커스텀 이벤트를 만들 수 있다.

커스텀 Spring boot Starter

대규모 또는 더 compact한 디펜던시를 가지고 싶다면 구성해볼법하다.

커스텀 자동 구성

Failure analyzer

구동과정중 실패가 발생할 때 이를 분석하고 자세한 진단 보고서를 만들어준다.

Spring boot actuator

Spring boot app을 모니터링하고 상호작용할 수 있다.
그리고 운영 중인 app의 쓰레드 덤프나 힙 덤프를 생성할 수 있다.
spring-boot-starter-actuator 의존 관계를 추가하여 사용할 수 있다.

개발자 도구

생산성을 높여주는 devtools가 있다.
classPath에 있는 클래스의 변경 사항을 모니터링하다가 변경이 생기면 자동으로 새로 빌드해주거나, 리소스가 변경되면 브라우저 새로고침을 유발하는 liveReload 서버 기능이 개발자 도구에 포함된다.

Summary

Spring boot를 사용하여 독립적으로 실행할 수 있는 애플리케이션을 간단한 설정만으로 만들 수 있다.
또한 설정 관련하여 추상화함과 starter로 의존관계를 관리하여 개발자는 App 설정에 드는 노력을 줄이고 비즈니스 로직에 더 집중할 수 있다.

참고

Spring boot를 언제 써야할까? 외장 was만이 할 수 있는 것 : https://zepinos.tistory.com/87

profile
Search & Backend Engineer

0개의 댓글