스프링부트

한상우·2023년 5월 31일
1

spring

목록 보기
5/5
post-thumbnail

스프링부트

시작을 위한 복잡한 설정 과정을 스프링 부트가 해결

핵심 기능


  1. WAS 가 내장되어 있음
  2. 라이브러리 버전 자동 관리
  3. 자동 구성 (AutoConfiguration)
  4. 환경에 따라 달라지는 외부 설정 공통화
  5. 모니터링을 위한 메트릭, 상태 확인 기능 제공

WAR란?

WAS 에 배포할 때 사용하는 파일로 JAR 가 JVM 위에서 실행된다면 WAR는 WAS 위에서 실행된다.

구조가 있음

WEB-INF : 자바 클래스, 라이브러리, 설정정보가 있음

그 외 : 정적 리소스 사용

서블릿 컨테이너

서블릿 컨테이너는 실행 시점에 초기화 메소드인 onStartup() 메소드가 있는데 이를 통해 필요한 기능 초기화 가능 여기서 servlet 등록할 수 있다 (단순히 @WebServlet 하는 거보다 유연한 장점이 있음)

이 서블릿 컨테이너에 Dispatcher Servlet 을 등록 하고 dispatcher 서블릿이 알고있는 controller 를 적절히 호출하는 구조가 스프링 MVC 를 이용하는 것이다.

디스패처 서블릿을 여러개 등록할 수 있고, 그에 따른 스프링 컨테이너도 여러개 만들 수 있다.

하지만 일반적으로는 하나의 디스패처 서블릿을 만들고 이 디스패처 서블릿의 경로를 /로 잡아 하나의 디스패처 서블릿을 통해 모든것을 처리하도록 한다.

WAR 배포 방식의 단점


과거 방식

  1. 톰캣 서버를 별도 설치
  2. 애플리케이션 코드를 war 로 빌드
  3. 빌드한 파일을 was 에 배포

단점

  1. WAS 별도 설치해야 함 (톰캣 버전 업이 필요하면 새로 설치해야 함)
  2. 개발 환경 설정이 복잡
  3. 배포 과정이 복잡

톰캣도 자바로 만들어졌으니까 하나의 라이브러리마냥 사용하는거 어때??

→ 내장 톰캣 기능

스프링 부트는 라이브러리로 내장 톰캣을 가지고 있다

@SpringBootApplication
public class BootApplication {

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

저 run 을 하게 되면 1. 스프링 컨테이너를 생성 2. was 를 생성한다.

스프링 부트로 만들 애플리케이션을 jar 로 빌드한 후

이를 압축 해제하면

  • META-INF : MANIFEST.MF 파일 (Main 실행하기 위한 파일)
  • org/springframework/boot/loader
    • 부트를 실행하는데 필요한 것
    • JarLauncher.class 에 main() 실행 클래스가 있음
      • jar 내부에 jar 를 읽어들이는 일을 여기서 해줌
  • BOOT-INF
    • 우리가 개발한 class 파일과 리소스 파일
    • 외부 라이브러리

JAR 를 푼 결과를 보면 jar 가 포함되어 있다!! (원래는 안된다고 함)

스프링 부트에서 새로 정의한 것임!

스프링 부트 버전 관리


plugins {
	id 'java'
	id 'org.springframework.boot' version '2.7.6'
	id 'io.spring.dependency-management' version '1.0.15.RELEASE'
}

spring.dependency-management 플러그인이 있으면, 현재 스프링 부트 버전에 맞게 정리해둔 문서를 통해 나머지 라이브러리들 버전을 맞춘다

스프링부트 스타터를 통해 필요한 관련 라이브러리들을 모두 자동으로 땡겨온다. (일일이 지정할 필요가 없어짐)

외부 설정


@ConfigurationProperties 이 있으면 외부 설정을 주입 받는 객체라는 뜻

ConstructorBinding이 사용중이라면 생성자 파라미터 바인딩을 한다

  • 스프링 부트 3.0 이전에는 생성자 바인딩 시에 @ConstructorBinding 애노테이션을 필수로 사용해야 했다.

@EnableConfigurationProperties(MyDataSourcePropertiesV1.class)
스프링에게 사용할 @ConfigurationProperties 를 지정해주어야 한다. 이렇게 하면 해당 클래스는

스프링 빈으로 등록되고, 필요한 곳에서 주입 받아서 사용할 수 있다

@Profile 을 통해 개발 환경과 배포환경에 각각 다른 Bean 을 등록할 수 있다. (스프링 빈도 분리 가능)

@Slf4j
@Configuration
public class PayConfig {
    @Bean
    @Profile("default")
    public LocalPayClient localPayClient() {
log.info("LocalPayClient 빈 등록");
          return new LocalPayClient();
    }
    @Bean
    @Profile("prod")
    public ProdPayClient prodPayClient() {
log.info("ProdPayClient 빈 등록");
          return new ProdPayClient();
    }
}

액츄에이터


스프링 부트가 제공하는 액츄에이터라는 라이브러리가 있는데 프로덕션을 운영할 떄 필요한 지표, 추적, 모니터링 등등을 쉽게 사용할 수 있음

implementation 'org.springframework.boot:spring-boot-starter-actuator' //actuator 추가

http://localhost:8080/actuator 를 통해 액츄에이터를 확인할 수 있음

액츄에이터의 모든 엔드포인트를 노출할거면

management:
  endpoints:
    web:
      exposure:
        include: "*"

특정 엔드포인트를 활성화 하려면 management.endpoint.{ 엔드포인트명 }.enabled: true

노출과 활성화가 둘 다 되어야 확인 가능함!!

자주 사용하는 엔드포인트 목록

beans : 스프링 컨테이너에 등록된 스프링 빈을 보여준다.
conditions : condition 을 통해서 빈을 등록할 때 평가 조건과 일치하거나 일치하지 않는 이유를 표시한다.
configprops : @ConfigurationProperties 를 보여준다.
env : Environment 정보를 보여준다.
health : 애플리케이션 헬스 정보를 보여준다.
httpexchanges : HTTP 호출 응답 정보를 보여준다. HttpExchangeRepository 를 구현한 빈을 별도로
등록해야 한다.
info : 애플리케이션 정보를 보여준다.
loggers : 애플리케이션 로거 설정을 보여주고 변경도 할 수 있다.
metrics : 애플리케이션의 메트릭 정보를 보여준다.
mappings : @RequestMapping 정보를 보여준다.
threaddump : 쓰레드 덤프를 실행해서 보여준다.
shutdown : 애플리케이션을 종료한다. 이 기능은 기본으로 비활성화 되어 있다.

health

애플리케이션에 문제가 발생했을 때 문제를 빠르게 인지 가능

/actuator/health

문제 없으면 “UP”

문제 있으면 “DOWN”

DB 가 잘 연결되어 있는가 application에서 DB 로 jdbc 스펙중에 확인을 할 수 있는 기능이 있음

디스크 공간이 문제 없나, ping 에 문제 없나

management:
  endpoint:
    health:
      show-components: always
			// show-details: always (자세히)

info

자바 , OS, build 정보, env 정보, git 정보 확인 가능

management:
  info:
    java:
      enabled: true
    os:
      enabled: true
    env:
      enabled: true

build.gradle에

springBoot {
    buildInfo()
}

추가하면 알아서 빌드 파일에 build-info.properties 생김

git 정보를 확인하고 싶으면

plugin 에 id "com.gorylenko.gradle-git-properties" version "2.4.1" //git info 추가
애플리케이션을 배포할 때 가끔 기대와 전혀 다르게 동작할 때가 있는데,(특정 기능이 빠져있다던가) 확인해보면 다른 커밋이나 다른 브랜치의 내용이 배포된 경우가 종종 있다

logger

로깅과 관련된 정보를 확인하고 로깅 레벨을 실시간으로 변경 가능

로컬 (DEBUG 로그 레벨 보통 사용), 운영 (INFO 로그 레벨 보통 사용)

운영중인 서버에서 급하게 하위 레벨 로그를 확인하고 싶을 때 로깅 설정 레벨을 변경하고 서버를 재시작해야 함.

이 loggers 엔드포인트를 사용하면 POST 로 변경하고 싶은 부분 엔드포인트로 요청을 보내면 됨 (서버를 껐다 키면 다시 원복)

/actuator/loggers/hello.controller

{
    "configuredLevel": "TRACE"
}

보안 주의!!!

액츄에이터는 우리 애플리케이션 내부 정보를 너무 많이 노출하기에 내부망을 사용하는 것이 안전하다.

즉 8080 포트만 외부에 열어두고 다른 포트는 열어두지 않으면 내부에서만 사용 가능하겠지??

management:
  server:
    port: 9292

다른 방법: /actuator 에 서블릿 필터, 스프링 인터셉터, 시큐리티 등을 사용해서 인증된 사용자만 접근 가능하도록 해야 함

마이크로미터, 프로메테우스, 그라파나


마이크로미터

A 모니터링 툴을 사용하고 있으면 A 에 맞추어 데이터를 전달해야 한다 (A API) 만약 B 모니터링 툴을 사용하게 된다면 B 에 맞추어 데이터를 다시 전달해야 하네??

마이크로미터는 표준 측정 방식이 있음 마이크로미터 표준 측정방식에 맞추어 측정하면 댐

스프링 부트 액츄에이터 내장으로 마이크로미터가 있다!!

애플리케이션 코드는 모니터링 툴이 변경되어도 유지할 수 있다!!

메트릭

CPU, JVM, 커넥션 사용 등등 수많은 지표들을 어떻게 수집하지??

스프링 부트 액츄에이터는 마이크로미터가 제공하는 지표 수집을 @AutoConfiguration 을 통해 자동으로 등록

(AutoConfiguration: 미리 정의 되어있는 자바 설정 파일(@Configuration)들을 빈으로 등록하는 역할을 수행)

/actuator/metrics/{이름}

프로메테우스

메트릭을 그 순간만 확인하는 것이 아니라 과거 이력까지 함께 확인하려면 메트릭을 보관하는 DB 가 필요

프로메테우스는 메트릭을 지속해서 수집하고 DB 에 저장함

프로메테우스 다운

https://github.com/prometheus/prometheus/releases/download/v2.42.0/prometheus-2.42.0.darwin-amd64.tar.gz

프로메테우스가 우리 애플리케이션의 메트릭을 수집하도록 연동

  1. 애플리케이션에서 프로매태우스 포맷에 맞추어 메트릭 만들기
  2. 프로메테우스에서 애플리케이션 메트릭 주기적으로 설정할 수 있게

각각의 메트릭들은 내부에서 마이크로미터 표준 방식으로 측정되고 있다. 따라서 어떤 구현체를 사용할지 지정만 해주면 된다.

implementation 'io.micrometer:micrometer-registry-prometheus'

마이크로미터 프로메테우스 구현 라이브러리를 추가한다.

스프링 부트와 액츄에이터가 자동으로 마이크로미터 프로메테우스 구현체를 등록해서
동작하도록 설정해준다.
액츄에이터에 프로메테우스 메트릭 수집 엔드포인트가 자동으로 추가된다.

/actuator/prometheus

prometheus.yml

scrape_configs:
  # The job name is added as a label `job=<job_name>` to any timeseries scraped from this config.
  - job_name: "prometheus"

    # metrics_path defaults to '/metrics'
    # scheme defaults to 'http'.

    static_configs:
      - targets: ["localhost:9090"]

  #추가
  - job_name: "spring-actuator"
    metrics_path: "/actuator/prometheus"
    scrape_interval: 10s # 보통은 10s ~ 1분으로 둠
    static_configs:
      - targets: ["localhost:8080"]

메트릭은 크게 보면 게이지와 카운터라는 2가지로 분류할 수 있다

  1. 게이지(Gauge): 임의로 오르내일 수 있는 값
    예) CPU 사용량, 메모리 사용량, 사용중인 커넥션

  2. 카운터(Counter): 단순하게 증가하는 단일 누적 값
    예) HTTP 요청 수, 로그 발생 수

    증가만 하는 그래프에서는 특정 시간에 얼마나 고객의 요청이 들어왔는지 한눈에 확인하기 매우 어렵다

increase() 를 사용하면 이런 문제를 해결할 수 있다. 지정한 시간 단위별로 증가를 확인할 수 있다.
마지막에 [시간] 을 사용해서 범위 벡터를 선택해야 한다.
예) increase(http_server_requests_seconds_count{uri="/log"}[1m])

그라파나

DB 에 있는 데이터를 불러서 사용자가 보기 편하게 해주는 대시보드

https://dl.grafana.com/enterprise/release/grafana-enterprise-9.3.6.darwin-amd64.tar.gz

그라파나에서 프로메테우스를 데이터소스로 사용해서 데이터를 읽어와야 한다

하나 하나 대시보드를 입력할 수 있음

잘 만든 대시보드를 받을 수도 있음

profile
안녕하세요 ^^

0개의 댓글