-
Notifications
You must be signed in to change notification settings - Fork 77
[그리디] 이창희 Spring Core (배포) 7,8,9 단계 제출합니다 #182
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
안녕하세요 창희님! 반영해주신 코드 잘 보았습니다. 애플리케이션 레벨에서 크게 변경점이 없어 리뷰할 거리가 많지 않았는데요!
혹시 9단계 진행하시면서 배포 스크립트 파일도 작성해 주셨을까요? 배포 스크립트 파일도 git에서 형상관리가 되게 하면 관리하기가 쉽습니다 :)
스크립트 파일 올려주시면 해당 내용 기반으로 추가 질문 올릴 수 있을 것 같아요!
properties: | ||
hibernate: | ||
format_sql: true | ||
ddl-auto: create |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ddl-auto 값을 운영 쪽은 create로, 테스트는 create-drop으로 잡으셨는데
create를 쓰더라도 애플리케이션 시작할 때 기존 테이블이 있으면 drop돼요!
의도하신 로직이실까요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
그렇게 큰 뜻은 없고,
테스트가 끝나면 테이블을 정리 하는 것이
흐름이 더 깔끔한것 같아서 create-drop
을 썼어요! 😅
(인 메모리 DB를 쓰고 있으니까 create
을 써도 크게 차이가 없을 것 같긴 하네요)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ㅎㅎ이해했습니다!
src/test/resources/application.yml
Outdated
datasource: | ||
url: jdbc:h2:mem:test_db | ||
|
||
roomescape: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
같은 값이 prod의 application.yml과 중복 선언이 되어있군요
없어도 동작하지 않았나요? :D
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
같은 값이 prod의 application.yml과 중복 선언이 되어있군요
제가 질문을 잘 이해하지 못한것 같은데,
말씀해 주신 같은 값이 다음의 jwt 관련 값인가요?
roomescape:
auth:
jwt:
secret: Yn2kjibddFAWtnPJ2AFlL8WXmohJMCvigQggaEypa5E=
expiration: 1800000
Test 패키지의 application.yml
에 이 설정이 빠지게 되면 작동이 안 되더라구요
그래서 포트 설정과 DB 설정을 제외한 mian 패키지의 설정 내용을 똑같이 넣어 주었어요!
현재 미션에서 test 와 prod 환경을 분리해 보았는데요, 생각난 방법이 두 가지가 있었어요
첫 번째 방법
application.yml
에 prod와 test 환경의 공통 설정을 모아 놓기 + prod를 기본 active로 설정application-prod.yml
,application-test.yml
를 각각 만들어 서로 다른 설정들을 작성하기 (DB 설정 등...)
근데 이렇게 하면 모든 test 클래스 들에 @ActiveProfiles("test")
을 붙여줘야 하는 것이 번거롭게 느껴져서 두 번쨰 방식을 사용하여 미션을 제출했어요
두 번째 방법
- test/resourses 패키지에
application.yml
을 만들어 main 패키지의 설정과 아예 분리하기
드는 생각이 prod 와 test 의 공통된 설정을 바꾸게 된다면,
두 번째 방법은 main패키지의 application.yml
과 test 패키지의 application.yml
도 같이 바꾸어 줘야 하는 불편함이 있는것 같네요🤔
이렇게 환경 분리를 해본 경험이 별로 없어 어떤 방식으로 환경을 분리해야 할지 감이 잘 안 잡히네요
승현님은 테스트 환경과, 프로덕션 환경, 로컬 개발 환경을 분리할때 어떤 방식으로 분리를 하시나요?
가능하시다면 어떠한 장점이 있어서 해당 방식을 사용하시는지도 궁금합니다!!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
스프링 부트는 yml을 사용해서 더 편한 방법으로 설정할 수 있게 도와주니 관련 설정들을 더 검색해보셔도 좋을 것 같습니다.
예를 들어 창희님의 main/application.yml은
server:
port: 8080
spring:
profiles:
active: prod
h2:
console:
enabled: true
path: /h2-console
datasource:
url: jdbc:h2:mem:database
jpa:
show-sql: true
properties:
hibernate:
format_sql: true
ddl-auto: create
roomescape:
auth:
jwt:
secret: Yn2kjibddFAWtnPJ2AFlL8WXmohJMCvigQggaEypa5E=
expiration: 1800000
이렇게 되어있어 prod라는 프로필을 사용하는 환경에서만 위 환경변수들이 설정되는데,
prod와 test에서 공통으로 사용하는 환경변수라면 굳이 prod에서만 사욜하지 않고 기본값으로 두어도 괜찮습니다.
server:
port: 8080
roomescape:
auth:
jwt:
secret: Yn2kjibddFAWtnPJ2AFlL8WXmohJMCvigQggaEypa5E=
expiration: 1800000
---
spring:
profiles:
active: prod
h2:
console:
enabled: true
path: /h2-console
datasource:
url: jdbc:h2:mem:database
jpa:
show-sql: true
properties:
hibernate:
format_sql: true
ddl-auto: create
이런 식으로요. yml 파일 하나에서도 '---'을 구분자로 하여 여러 profile에 대한 설정을 할 수가 있습니다.
spring.profiles.active 설정을 걸지 않은 환경변수는 전역적으로 적용되기 때문에 test/application.yml에도 자동 적용이 될 거에요.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
application-prod.yml, application-test.yml
<- 요 방식은 spring.profiles.active와는 용례가 살짝 다릅니다.
spring.profiles.active는 애플리케이션의 실행 환경 (테스트, 베타, 스테이지, 프로덕션 등)에 따라 다른 설정을 적용하고 싶을 때 사용합니다. 창희님께서 운영용과 테스트용 profile을 분리하신 것처럼요!
반면 application-{이름}.yml은 profile보다는, 모듈마다 고유한 application.yml을 만들고 싶을 때 사용합니다.
스프링 프로젝트에서 멀티모듈을 사용해 프로젝트를 만들어본 경험이 있으신가요?
안 해보셨다면, 간단히 생각해서 한 폴더 안에 스프링 부트 프로젝트가 여러 개 있고, 프로젝트끼리 서로 implementation해서 사용하는 모습을 떠올리시면 됩니다. 저희가 jpa 쓸 때 boot-starter-jpa 라이브러리 implemetaion해서 사용하듯이요.
이번 미션의 프로젝트를 예로 들면, '예약' 모듈과 '인증' 모듈을 분리하여 별도로 관리하는 겁니다.
인증 모듈이 별도의 스프링 부트 프로젝트로 분리되었으니, application.yml도 분리될 것입니다.
// application.yml
roomescape:
auth:
jwt:
secret: Yn2kjibddFAWtnPJ2AFlL8WXmohJMCvigQggaEypa5E=
expiration: 1800000
예약 모듈에서 인증 모듈을 가져와 사용하는 경우, 인증 모듈의 application.yml도 같이 적용을 할 수 있어야 애플리케이션을 정상적으로 실행할 수 있을 거에요. 이 때 사용하는 방식이 application-{이름}.yml입니다.
인증 모듈의 application.yml 이름을 application-auth.yml로 지정하는 겁니다.
그리고 예약 모듈에서 해당 yml 설정을 import해서 함께 적용할 수 있습니다. 이 때 사용하는 설정이 spring.profiles.include
입니다.
spring:
config:
include: auth << application-auth.yml 설정을 가져와 등록
server:
port: 8080
spring:
profiles:
active: prod
h2:
console:
enabled: true
path: /h2-console
...
모든 곳에서 이 용도를 딱 정해서 쓰진 않지만, 대체로 이렇게 씁니다!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
정리하자면,
spring.profiles.active
는 실행 환경(dev, test, prod 등..)에 따라 다른 설정을 적용하고 싶을 때 사용하고
application-{이름}.yml
은 공통 설정을 담은 application.yml
과 분리하여
환경별 또는 모듈별 설정을 정의하는 데 사용되는군요
또한 이 설정파일을 include
하거나 spring.profiles.active
에 지정할 수 있는 것이군요!
자세한 설명 감사합니다!
배포 스크립트 작성했어요~~! 편하신 시간에 확인해 주시고 리뷰 부탁드려요 👍 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
안녕하세요! 스크립트 파일 공유해주셔서 감사합니다. 궁금한 점들을 질문 올려드렸으니 확인 후 답변 부탁드려요! :)
echo "********** [배포 중 에러 발생] : $(date +%Y-%m-%d\ %H:%M:%S) **********" >> $DEPLOY_LOG | ||
echo " -> 실패한 명령어: '$BASH_COMMAND'" >> $DEPLOY_LOG | ||
echo " -> 위치: ${BASH_SOURCE[1]}:${LINENO[1]}" >> $DEPLOY_LOG | ||
exit 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
우와 로그가 아주 상세한데요? 직접 만드셨나요? :0 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
배포 스크립트로 실행했을떄 오류가 나게 되면 어떤 명령어에서 문제가 발생했는지 알기 쉽지 않을 것 같아
최대한 자세히 로그를 남기고 싶었습니닷
(셸 스크립트로 구현하는 방법은 지피티의 도움을 받았어요 😅 )
|
||
# 1. 최신 코드 pull | ||
echo "> Git pull" >> $DEPLOY_LOG | ||
git pull >> $DEPLOY_LOG 2>&1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2>&1
요건 무슨 뜻인가요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
git pull을 했을때 발생할 수 있는 표준에러(2)
를 표준 출력(1)
과 함께 DEPLOY_LOG 로그에 같이 저장하기 위한 설정이에요
2>&1
를 안 해주면, 표준에러가 로그에 저장되지않고 2로 터미널에 출력이 될 것 같아 같이 로그에 저장할 수 있도록 설정했습니닷
deploy.sh
Outdated
else | ||
echo " -> 실행 중인 애플리케이션 종료 (PID: $CURRENT_PID)" >> $DEPLOY_LOG | ||
kill -15 $CURRENT_PID | ||
sleep 5 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
애플리케이션이 언제나 5초 안에 종료됨을 보장할 수 있나요?
또 5초보다 더 빨리 종료되는 경우 불필요한 기다림을 최소화할 수 있는 방법이 있을 것 같아요!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
고민해 보았는데,
생각이 나는 방식이 루프를 돌다가 종료가 되면 break 하는 방법이 생각나네요!
- 우선 실행중인 프로그램이 있다면 Kill -15 로 종료를 시도한 뒤
- 루프를 돌다가 종료가 되면 break 를 하는 방식
이렇게 하게 되면 루프를 약 10 초 동안 돌다가 만약 10초가 지났음에도 kill -15
로 종료가 되지 않았다면,
kill -9
로 강제 종료하는 로직을 추가해 보았어요!
# 5. 실행 중인 애플리케이션이 있으면 종료
echo "> 실행 중인 애플리케이션이 있다면 종료" >> $DEPLOY_LOG
if [ -z "$CURRENT_PID" ]; then
echo " -> 현재 실행 중인 애플리케이션이 없습니다." >> $DEPLOY_LOG
else
echo " -> 실행 중인 애플리케이션 종료 (PID: $CURRENT_PID)" >> $DEPLOY_LOG
kill -15 $CURRENT_PID
for _ in {1..10}
do
if ! ps -p $CURRENT_PID > /dev/null; then
echo " → 종료 완료" >> $DEPLOY_LOG
break
fi
sleep 1
done
if ps -p $CURRENT_PID > /dev/null; then
echo " → 정상 종료 실패, 강제 종료 시도." >> $DEPLOY_LOG
kill -9 $CURRENT_PID
sleep 2
fi
fi
이러한 루프를 타는 방식 외에 개선할 다른 방법이 있다면 피드백 부탁드려요!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
제가 유도한 바를 정확히 구현해 주셨어요! 최고에요
deploy.sh
Outdated
|
||
# 6. 새 애플리케이션 백그라운드 실행 | ||
echo "> 새 애플리케이션 실행" >> $DEPLOY_LOG | ||
nohup java -jar $JAR_FILE > $APP_LOG 2> $APP_ERROR_LOG & # 정상 출력 로그-> > APP_LOG / 비정상 출력 로그 -> 2> ERROR_LOG |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이대로 실행하면 애플리케이션의 profile이 default로 들어가서 창희님께서 설정하신 application.yml의 설정들이 안 적용될 것 같은데, 실제 해보시니 어땠나요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
좋아요! profile을 외부에서 변수로 주입받을 수 있게 설정하면
나중에 베타용, 스테이지용, 운영용 애플리케이션을 따로 띄워야 할 때 유연하게 대응할 수 있습니다. 👍
[변경내용]
이렇게 수정해 보았어요~! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
멋지게 구현해 주셨네요! 앞으로의 여정도 응원합니다. 프로젝트도 화이팅하세요!
안녕하세요 승현님!
두 번쨰로 뵙는군요 ㅎㅎ
어느덧 마지막 스터디 미션이네요 이번 미션도 잘 부탁드립니다!
이번 미션은
data.sql
로 데이터를 초기화 했던 것을 DataLoader를 통해 테스트 환경과, 프로덕션 환경을 분리해 초기화 하는비교적 간단한 미션이였습니다!
1번을 구현하기 위해 jwt 패키지를 만들어
JwtTokenProvider
와JwtProperties
클래스 분리하고,JwtConfig
를 통해 빈으로 등록했습니다Application 클래스에서
@Import(JwtConfig.class)
통해 JwtConfig의 설정을 등록해 주었습니다2번을 구현하기 위해서는
제 코드에서 미흡한 점이나 개선할 점이 있다면 편하게 말씀해 주세요~
P.S. 이번 미션이 간단한 편이라 Files Changed가 많지 않고, 리뷰를 남기실 부분도 많지 않을 수 있겠다는 생각이 드네요
혹시 그래서 난감 하셨다면(?), 스프링이나 배포와 관련해서 키워드나 질문을 주시면 제가 공부해 보고 그에 대한 코멘트를 남겨보겠습니다! 😄
감사합니다!