스프링부트
: 스프링을 편리하게 사용할 수 있도록 지원하는 프레임워크main
만 실행하면 Tomcat
이 자동으로 실행됨@SpringBootApplication
public class TestApplication {
public static void main(String[] args) {
SpringApplication.run(TestApplication.class, args);
}
}
위의 코드가 결국 스프링 컨테이너
를 생성해주고 WAS(내장톰캣)
을 생성해줘서 편하게 TOMCAT 사용
자동 라이브러리 관리 : 손쉽게 라이브러리를 사용할 수 있음
즉 개발자는 원하는 라이브러리만 고르기만 하고 버전은 생략해도 된다
스프링부트가 부트 버전에 맞는 최적화된 라이브러리 버전을 선택해준다
spring-boot-starter-web
-> 이 하나의 라이브러리를 사용하면
스프링 웹 MVP, 내장톰캣, JSON처리, LOG 등의 모든 라이브러리가 포함됨
자동 구성 : 빈
을 자동으로 등록
스프링 부트는 자동구성(Auto Configuration) 이라는 기능을 제공해줌
일반적으로 자주 사용하는 수 많은 빈들을 자동으로 등록해줌
스프링 컨테이너란 ?
-> 자바 객체의 생명주기를 관리해줌 (빈 생성, 관리, 제거)
-> 스프링에서는 자바 객체를 빈
이라고 부름
-> 스프링 컨테이너는 @Configuration
가 붙은 클래스를 설정 정보로 사용함
-> @Configuration
을 생략해도 스프링부트가 제공하는 자동구성(Auto Configuration) 기능을 제공
@Autowired
DataSource dataSource;
@Autowired
TransactionManager transactionManager;
@Autowired
JdbcTemplate jdbcTemplate;
@Conditional
: 특정 조건에 맞을 때 설정이 동작하도록 하는 어노테이션
주로 환경별 설정을 분리할 때 사용 (개발 환경, 운영 환경)
@AutoConfiguration
: 스프링 부트가 제공하는 자동구성 기능을 적용할 때 사용하는 애노테이션
ex)
@AutoConfiguration
@ConditionalOnProperty(name = "memory", havingValue = "on") // 해당 조건에 환경정보가 있을 때 라이브러리 적용 (스프링 빈 등록)
public class MemoryAutoConfig {
@Bean
public 메소드1()
@Bean
public 메소드2()
}
위처럼 자동구성 라이브러리를 사용하려면 추가로 자동 구성 대상 지점
을 지정해줘야 한다
스프링부트는 시작지점에 org.springframework.boot.autoconfigure.AutoConfiguration.imports
의 정보를 읽어서 자동구성으로 사용 -> 따라서 위 조건이 맞으면 내부에 있는 MemoryAutoConfig 가 자동으로 실행
memory.MemoryAutoConfig // 패키지명.클래스이름 을 적어서 지정해줘야함
그럼 해당 클래스는 자동구성으로 사용하다는 의미 = 클래스 안에서 메소드들이 bean
으로 등록됨
부트에서는 @ConditionalOnProperty
많이 사용
@ConditionalOnProperty(name = "feature.enabled", havingValue = "true",matchIfMissing = false)
@Conditional
, @ConditionalOnProperty
둘다 Condition 클래스
를 구현함
Main에서 run() 메소드 안에 @SpringBootApplication
이 존재
-> @SpringBootApplication
안에는 @EnableAutoConfiguration
존재 -> 자동 구성을 활성화하는 기능
@Import
: 다른 구성 클래스들을 가져와서 현재의 구성 클래스에 포함시키기 위해 사용됨@Import
로 가져온 클래스의 빈들이 자동으로 등록됨 // TestBean 클래스
public class TestBean {
}
// TestConfig 클래스
@Configuration
public class TestConfig { // (3) TestConfig도 스프링 컨테이너에 등록하기 위해서 @Configuration으로 등록
@Bean
public TestBean testBean() { // (4) testBean 메소드가 빈으로 등록됨
return new TestBean();
}
}
// ImportTest 클래스 (Junit 테스트)
public class ImportTest {
@Test
void staticConfig() {
// (1) 스프링 컨테이너 생성 -> 위에서 설명한대로 @Configuration 이 붙은 클래스를 설정 정보로 등록
// 그 클래스가 바로 useConfig
AnnotationConfigApplicationContext appContext = new AnnotationConfigApplicationContext(useConfig.class);
TestBean bean = appContext.getBean(TestBean.class); // (5) 등록된 빈 가져오기
Assertions.assertThat(bean).isNotNull();
// (6) 즉 여러가지 어노테이션을 사용해서 스프링컨테이너에 useConfig 클래스만 설정정보로 등록해도 빈이 존재
}
@Configuration
@Import(TestConfig.class)
public static class useConfig { // (2) useConfig는 TestConfig 클래스를 포함시킴 (빈으로 등록됨)
}
}
@ImportSelector
: 위 방식(정적)과 다르게 동적으로 설정 클래스를 가져올 때 사용하는 인터페이스// MyImportSelector 클래스
public class MyImportSelector implements ImportSelector {
@Override
public String[] selectImports(AnnotationMetadata importingClassMetadata) {
// 로직을 통해 가져올 클래스 이름들을 반환 (if문 사용 가능)
return new String[]{"com.example.Config1", "com.example.Config2"};
}
}
// AppConfig 클래스
@Configuration // 이번에는 스프링컨테이너에서 Appconfig를 설정정보로 등록하는 과정은 생략
@Import(MyImportSelector.class) // (1) MyImportSelector 클래스를 포함시킴
public class AppConfig {
// 애플리케이션 설정
}
과거에는 위와 같이 파일들을 환경에따라 배포함
하지만 환경에 따라서 빌드를 여러번 해야하기 때문에 좋은 방법이 아님
즉 다음과 같이 빌드는 한번만 하고 각 환경에 맞추어 실행시점에 외부 설정값
을 주입함
✅ (1) : OS 환경변수 : OS를 사용하는 모든 프로그램에서 읽을 수 있는 설정값으로 사용범위가 넓음
-> CMD창에서 환경변수 조회방법
-> 윈도우 : set
입력
-> Mac or 리눅스 : printenv
입력
-> 위와 방법으로 환경변수를 조회 한 후 OS 환경변수를 설정하고 System.getenv()
로 외부설정 사용
한계 : OS 환경변수는 이 프로그램뿐 아니라 다른 프로그램에서도 사용되는 전역변수 같은 효과가 있음
✅ (2) : 자바 시스템 속성 : 실행한 JVM 안에서 접근 가능한 외부 설정
Properties p = System.getProperties();
를 사용해서 자바 시스템 속성을 조회 가능
한계 : 코드 안에서 사용하는 것으로 외부로 설정을 분리하는 효과가 없음
✅ (3) : 자바 커맨드 라인 인수 : 애플리케이션 실행 시점에 외부 설정값을 main(args)
의
args
파라미터로 전달하는 방법
-> 커맨드 라인에 전달하는 값은 형식이 없고, 띄어쓰기로 구분함
-> 커맨드 라인 인수는 key=value
형식이 아니다
-> 개발자가 직접 =를 기준으로 파싱해서 key=value
형식으로 맞춰야함
key=value
형식으로 편하게 사용할 수 있도록 스프링만의 표준 방식을 정의--key=value
형식 위 커맨드 라인 옵션 인수
, 자바 시스템 속성
, OS 환경변수
는 모두 외부 설정을 key=value
형식으로 사용할 수 있는 방법이다
외부 설정 값을 Environment
와 PropertySource
를 통해 외부설정을 통합할 수 있다
중복되는 값들은 우선순위를 통해서 해결된다
한계 : 사용해야하는 값들이 늘어날수록 불편함 그래서 등장한 방법이 다음에 설명할
설정값을 파일에 저장하는 방법이다
✅ (4) : 외부 파일 (설정 데이터)
-> 애플리케이션에서 특정 위치의 파일을 읽도록 함 (ex : application.properties)
-> 각 서버마다 해당 파일안에 다른 설정정보를 저장
-> 개발서버 application.properties : url=dev.db.com
-> 운영서버 application.properties : url=prod.db.com
application.properties
를 여러개 만들어 내부파일을 분리 할 수 있지만
실무에서는 주로 내부파일을 합체하는 형식으로 만든다
밑에는 하나의 application.properties
에서 여러개파일을 같이 적용하는 예시
#---
: application.properties
에서 파일을 구분하는 방법---
: application.yml
에서 파일을 구분하는 방법프로필
: 파일을 구분하는 값프로필
적용의 유무에 따라 동일한 값이 우선순위
로 인해 값이 바뀐다// 로컬환경일 때, 따로 프로필을 안줌
url=local.db.com
username=local_user
password=local_pw
#---
spring.config.activate.on-profile=dev // 개발환경일 때
url=dev.db.com
username=dev_user
password=dev_pw
#---
spring.config.activate.on-profile=prod // 운영환경일 때
url=prod.db.com
username=prod_user
password=prod_pw
우선순위는 범위가 넓은 것보다 좁은 곳이 더 우선권을 가진다
자주사용되는 우선순위 (위로갈수록 우선순위 높음)
-> TestPropertySource
(테스트에서 사용)
-> 커맨드 라인 옵션 인수
-> 자바 시스템 속성
-> OS 환경변수
-> 설정 데이터 (application.properties)
@Value
: 외부 설정 값을 편리하게 주입받을 수 있는 어노테이션
-> 주로 필드
에서 주입받거나 파라미터
를 통해서 주입 받는다
public class MyDataSourceValueConfig {
@Value("${my.datasource.url}") // 필드에 주입 받은 값 사용
private String url;
@Value("${my.datasource.username}") // 키가 없을 경우 기본 값 지정 가능 => @Value("${my.datasource.username:최주영}")
private String username;
@Bean
public MyDataSource myDataSource1() { //
return new MyDataSource(url, username);
}
@Bean
public MyDataSource myDataSource2(
@Value("${my.datasource.url}") String url, // 파라미터 통해서 설정 값 주입 (타입은 알아서 맞춰줌)
@Value("${my.datasource.username}") String username{
return new MyDataSource(url, username);
}
}
// application.properties
my.datasource.url=local.db.com
my.datasource.username=local_user
@ConfigurationProperties
: 외부 설정을 주입받는 객체를 의미@Data
@ConfigurationProperties("my.datasource") // 외부설정 시작점 적어주기
public class MyDataSourcePropertiesV1 {
private String url;
private String username;
private String password;
private Etc etc = new Etc();
@Data
public static class Etc { // getter setter 방식
private int maxConnection;
private Duration timeout;
private List<String> options = new ArrayList<>()
}
}
@Getter
@ConfigurationProperties("my.datasource")
public class MyDataSourcePropertiesV2 {
private String url;
private String username;
private String password;
private Etc etc;
// 생성자 방식
public MyDataSourcePropertiesV2(String url, String username, String password, @DefaultValue Etc etc) {
this.url = url;
this.username = username;
this.password = password;
this.etc = etc;
}
}
자바 빈 검증기
: 설정정보를 편리하게 할 수 있는 기능spring-boot-starter-validation
먼저 추가@Min
@Max
@NotEmpty
등@Validated
어노테이션을 붙여줘야함@Getter
@ConfigurationProperties("my.datasource")
@Validated
public class MyDataSourcePropertiesV3 {
@NotEmpty
private String url;
@NotEmpty
private String username;
@NotEmpty
private String password;
private Etc etc;
}
ConfigurationProperties
장점
-> 외부 설정을 객체로 편리하게 변환해서 사용할 수 있다.
-> 외부 설정의 계층을 객체로 편리하게 표현할 수 있다.
-> 외부 설정을 타입 안전하게 사용할 수 있다.
-> 검증기를 적용할 수 있다.
@Profile
: 특정 조건에 따라서 해당 빈을 등록할지 말지 선택할 때 사용
-> 프로필 안에는 위에서 본 @Conditional
어노테이션이 들어있음
-> 환경별로 외부 설정을 분리 + 등록되는 스프링 빈 분리
@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();
}
}
✅ 장점 (5)
모니터링과 관리 기능
프로덕션 준비 기능
: 애플리케이션을 실제 운영 환경에 배포할 때 필요한 비기능적 요소들을 의미
-> 액추에이터
를 통해 쉽게 구현 가능
목적 : 서비스 운영상태를 모니터링하면서 장애 상황 파악 및 해결
구성요소 : 지표
(CPU 사용량 등 성능지표), 추적
(문제 발생 지점 파악), 감사
(작업기록 관리) , 모니터링
구체적인 기능 : 로그 정보 설정 상태 점검, 커넥션 풀 사용 현황 파악, 스레드 덤프 생성
액추에이터
: Spring Boot 애플리케이션의 운영 환경에서 애플리케이션을 모니터링하고 관리하기 위한 기능을 제공하는 모듈
이 라이브러리(모듈)을 사용하려면
-> implementation 'org.springframework.boot:spring-boot-starter-actuator'
추가 해야함
액추에이터 기능을 웹에 노출하는 방법
// application.yml 파일
management:
endpoints:
web:
exposure:
include: "*"
-> include: "*"
은 web에 모든 엔드포인트를 노출한다는 의미
-> 원하는 것만 노출가능 ex) include: "health.info"
-> 전체 노출하는데 지정한 것만 빼고 싶어라고 할땐 ex) exclude: "env,beans"
evn와 beans는 노출 x
엔드포인트
: 액추에이터가 제공하는 하나하나의 기능을 의미함/actuator/{엔드포인트명}
http://localhost:8080/actuator/health
✅ 다양한 엔드포인트
beans
: 스프링 컨테이너에 등록된 스프링 빈을 보여줌
conditions
: conditions
을 통해 빈을 등록할 때 평가조건이 일치 혹은 일치하지 않은 이유를 표시
env
: Environment 정보를 보여줌
health
: 애플리케이션의 전반적인 건강 상태를 확인하고 제공하는 중요한 역할을 담당
-> 기본적으로 UP 또는 DOWN 상태를 반환하여 애플리케이션 정상 작동 중인지 여부 나타냄
-> health
정보를 자세히 보는 방법
management:
endpoint:
health:
show-details: always
# 너무 자세하다 싶으면 show-details 를 show-components로 바꾸기
다음과 같이 db, diskSpace, ping 상태를 알 수 있음
헬스 컴포넌트 중에서 하나라도 문제가 있으면, 전체상태는down
이 됨
info
: 애플리케이션의 기본 정보를 노출java
os
env
build
git
정보들을 제공META-INF/build-info.properties
파일이 필요하다## 참고로 management 바로 다음에 info 가 나와야함
management:
info:
java:
enabled: true
os:
enabled: true
loggers
: 로깅과 관련된 정보를 확인하고, 또 실시간으로 변경 가능debug
레벨을 출력하도록 설정INFO
로 적용TRACE
DEBUG
INFO
WARN
ERROR
오른쪽으로 갈수록 심각한 상태logging:
level:
hello.controller: debug
✅ 액추에이터와 보안
-> 액추에이터가 제공하는 기능들은 내부 정보를 많이 노출해서 보안상 좋지 않음
-> 액추에이터의 엔드포인트
들은 외부에서 접근이 불가능한 내부망
에서 사용하는것이 안전함
외부 인터넷망에서 실행할 수 밖에 없을 땐
-> 액추에이터의 포트번호를 다른것으로 바꾸기
-> ex) management.server.port=8085
-> 기존 8080포트에서는 액추에이터 접근 불가능
-> 또 다른 방법으로는 서블릿 필터
or 스프링 시큐리티
를 통해 인증된 사용자만 접근하도록 추가 개발
마이크로미터 (micrometer) 라이브러리
-> 애플리케이션 metric
파사드라고 불리며, 애플리케이션의 메트릭(측정 지표)를
마이크로미터가 정한 표준 방법으로 모아서 제공
-> 스프링 부트 액추에이터
는 마이크로미터
를 기본으로 내장해서 사용
-> 마이크로미터
는 추상화를 통해서 구현체를 쉽게 갈아끼울 수 있어서
모니터링 툴이 변경되어도 애플리케이션 코드는 유지할 수 있음
metrics
: Spring Boot 애플리케이션의 성능과 상태를 모니터링하고 측정하기 위한 기능
-> 이 엔드포인트를 사용하면 기본적으로 제공되는 메트릭들을 확인할 수 있다
-> 즉 액추에이터
모듈 안에 metrics
기능이 존재
-> http://localhost:8080/actuator/metrics
로 확인 가능
다음과 같이 요청 정보, 사용자 CPU 정보, 메모리 사용량 등등 확인할 수 있음
톰캣 메트릭
-> 유용한 메트릭 으로 tomcat.
으로 시작한다
-> 톰캣의 최대 쓰레드, 사용 쓰레드 수
-> 동시에 처리할 수 있는 쓰레드 수 tomcat.threads.config.max
-> 톰캣 메트릭을 사용하려면 다음 옵션을 켜야함
server:
tomcat:
mbeanregistry:
enabled: true
액츄에이터
를 통해서 수 많은 메트릭
이 자동으로 만들어진다.
하지만 지금 방식은 실시간으로만 확인이 가능할 뿐
이러한 메트릭들을 어딘가에 지속해서 보관해야 과거의 데이터들도 확인할 수 있다.
메트릭을 지속적으로 수집하고 보관할데이터베이스
가 필요하다.
그리고 이러한 메트릭들을 그래프를 통해서 한눈에 쉽게 확인할 수 있는 대시보드
도 필요하다.
프로메테우스
: 오픈소스 모니터링 시스템으로 메트릭
을 지속해서 수집하고 DB에 저장하는 역할을 함
그라파냐
: 매우 유연하며 데이터를 그래프로 보여주는 툴
프로메테우스는 메트릭을 수집해서 저장하고 그라파냐에게 쿼리(PromQL : 프로메테우스 쿼리) 를 날려서 시각적으로 그래프를 사용자에게 표현함
실무에서 많이 발생하는 문제
-> CPU 사용량 초과
-> JVM 메모리 사용량 초과
-> 커넥션 풀 고갈
-> 에러로그 급증
모니터링 3단계
핀포인트
오픈소스 많이 사용