💡발단
현재 프로젝트에선 기존에 application.yml 설정 파일 하나에 모든 설정 정보를 넣어놓고 있었다.
가장 큰 문제는 로컬에서 적용하던 설정을 실제 배포된 인스턴스에 적용하는 휴먼 에러가 발생할 수 있다는 것.
그리고 가장 무서운건 ddl-auto의 존재다.
만약 실서비스에서 ddl-auto : create로 실행을 한다면... DB가 날아가고 복구하는데 너무 큰 비용이 생기게 된다.
그 외에도 개발 환경을 분리하면 환경별로 설정을 관리할 수 있게 되기 때문에 편리한 부분이 많다.
스프링은 공식적으로 profile(프로파일) 기능을 지원한다.
🛠 프로파일 적용
적용 방법은 간단하다.
인텔리제이에서는 서버 Edit Configuration -> Active Profiles 에서 원하는 프로파일 값을 주면 된다.
JAR 실행에서는 JVM 시스템 파라미터로써 프로파일 값을 전달하면 된다.
🛠 YML 설정 파일 분리
이제 남은건 설정 파일을 각 프로파일에 맞게 분리하는 것이다.
spring.config.activate.on-profile 속성을 활용하면 된다. (Spring 2.4 ~)
application-local.yml
spring:
config:
activate:
on-profile: local
jpa:
hibernate:
ddl-auto: update
application-prod.yml
# CAUTION: 전반적으로 수정해선 안 됨
spring:
config:
activate:
on-profile: prod
jpa:
hibernate:
ddl-auto: validate # CAUTION: 변경 금지!!
혹시나 하는 마음에 주석을 많이 달아뒀다.
신경써야 할 부분은, ddl-auto가 디폴트로 none이라고 해서 생략해선 안된다는 것이다.
ddl-auto에는 절대 default 프로파일 설정이 덮어씌워질 수 있기 때문이다.
create, create-drop는 실제 배포된 DB에는 재앙을 불러온다... update도 왠만하면 하지 않는 것이 좋다고 한다.
application.yml
그리고 모든 프로파일에서 공통으로 사용할 설정 (default 프로파일) 내용은 application.yml에 두었다.
이 파일에는 spring.config.activate.on-profile이 따로 없기 때문에 공통 적용이 된다.
같은 속성에 중복되는 설정 값이 있을 경우, 우선순위는 프로파일 할당된 파일이 더 높다.
spring:
servlet:
multipart: # 사진 파일 최대 용량 제한
max-file-size: 10MB
max-request-size: 10MB
data:
web:
pageable: # 디폴트 페이지네이션 페이지 크기
default-page-size: 10
max-page-size: 500
one-indexed-parameters: true
messages: # 에러 메세지 설정
basename: errors
신경써야 할 점은 공통 설정에 ddl-auto를 설정하지 않는 것. 이게 덮어씌워지는 일은 최대한 방지하자.
🛠 @Profile : 프로파일에 따라 코드 실행 여부 결정하기
프로젝트에는 개발 편의성을 위해 @PostConstruct로 더미 데이터를 넣는 경우가 많다.
@RequiredArgsConstructor
@Slf4j
@Transactional
@Profile({"local"})
public class QuizInitializer { // TODO: 지금 로직은 지속가능하지 않음. 퀴즈 업데이트를 한다면..?
private final QuizRepository quizRepository;
@PostConstruct
public void init() {
if (quizRepository.count() > 0) {
log.info("[QuizInitializer] 퀴즈 이미 존재");
} else {
createDummyOXQuiz();
createDummyMultipleChoiceQuiz();
log.info("[QuizInitializer] 퀴즈 생성 완료");
}
}
보통은 카운트 쿼리를 먼저 날려서 0개일 경우에만 더미 데이터를 넣도록 해둔다.
그러나 실 서비스를 맨 처음 배포할 때엔 당연히 테이블별로 데이터가 0개일 수 밖에 없다.
그러면 테이블별로 인위적으로 데이터를 넣거나 (직접 쿼리문 작성...), 더미 데이터를 생성하게 내버려둔 뒤에 인위적으로 데이터를 삭제하는 방법을 써야 한다.
이건 그닥 우아하지 않다고 생각한다. 그리고 수동으로 쿼리문을 작성하면서 휴먼 에러가 발생할 수 있다.
스프링에선 프로파일별로 작동 여부를 설정하는 어노테이션인 @Profile을 지원한다.
위의 코드는 local 프로파일에서만 해당 더미 데이터 코드가 작동하도록 설정한 모습이다.
반복되는 @Profile 코드를 커스텀 인터페이스를 이용해 개선할 수도 있다.
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Transactional
@Profile({"local"}) // 특정 프로파일에만 더미 파일 작동
@interface BuzzingDummy {
}
해당 인터페이스를 적용하면 모든 더미 데이터 클래스가 local 프로파일에서만 작동한다.
@BuzzingDummy
public class CategoryDummy {
// ...
참고 :
https://tecoble.techcourse.co.kr/post/2022-10-04-active_profiles/
'Back-end > Spring Boot' 카테고리의 다른 글
[Spring Boot] 커서 페이징(no offset)에서 Page 대신 Slice 사용하기 (1) | 2023.09.11 |
---|---|
[Spring JPA] Hibernate에서 지원하지 않는 MySQL 랜덤 함수 직접 만들기 + Expressions 파헤쳐보기 (0) | 2023.09.06 |
[Spring Boot] @Valid 유효성 검사 (jakarta validation) (0) | 2023.08.27 |
[Spring Boot] 연관관계 생성 메서드 삽질 (0) | 2023.08.23 |
[Spring JPA] 실시간으로 적재되는 데이터와 부모 엔티티 묶어서 가져오기 (0) | 2023.08.10 |