쌩로그

변수와의 전쟁_export 전성시대 본문

TroubleShooting & 고민/배포

변수와의 전쟁_export 전성시대

.쌩수. 2023. 6. 8. 11:16
반응형

내가 성장하는 것이 다른 사람에게 좋은 영향을 줄 수 있다.

그래서 나는 잘 되야만 한다.

나는 진짜 ㄹㅇ 조만간 잘 될 사람이다.

어차피 잘 될 것이고, 지금도 잘 된 사람이다..
어쨋든간에 나는 어잘될사다.


결론부터 말하자면... 결국 내가 이겼다.

월요일 오후부터 하루죙일 붙잡기 시작했던 이 삽질이 드뎌 끝나게 되었다......

이 문제를 끝낼 수만 있다면, 나도 캡틴이다...

현재 포스팅 할 주제들이 너무나 많지만, 이건 진짜 바로 해야될 것만 같다고 가슴이 말해주고 있다..

??🤔🤔🤔🤔 무슨말을 한걸까..??

목차.

  1. 포스팅 개요
  2. 본론
  3. 요약

1. 포스팅 개요

나는 이번 프로젝트에서 깃허브 액션을 이용한 CI/CD 배포자동화를 구축했다.
CI/CD는 잘 들어간다

(초록색의 동그란 체크가 보다보면 뭔가 기분이 좋아진다.)

거기서 나는 현재 서버 배포가 잘되는지 확인이 필요했고, 스프링에서
/src/main/resources/staticindex.html이 있으면, 말 그대로 home페이지로 보여주기 때문에, 해당 파일을 만들었다.

그리고 OAuth2를 이용한 소셜로그인을 구현하기 위해서
a태그(&lta&gt)를 이용해서 속성에 href를 넣어 구글과 카카오로 로그인인증을 하는 페이지로 이동될 수 있도록 만들었다.

그런데,

이렇게 로컬에는 잘 연결된다.. 그런데 이상하게 서버만 가면...;;;

연결이 안 된다... 이를 해결한 포스팅이다.

2.본론

그래서 문제가 뭐였는데?

결론부터 말하면 제목에서 변수와의 전쟁, linux, export, yml, 무시 등에서 알 수 있듯이,

yml에 변수로 받아오려고 ${} EL표현식으로 값을 넣었는데, 못 읽어왔던 게 문제다.

local에선 윈도우 - 시스템 환경변수 편집 - 환경변수에 이름-값 넣어주면 그대로 변수등록이 되고,
application 실행 시 local의 yml 파일을 사용하려면, 인텔리제이 기준으로 Active.profilelocal을 넣어주면 된다.

그러면 애플리케이션 실행시 아래와 같이 나온다.

💡 참고로 application-prode.yml, application-local.yml 과 같이 yml의 파일의 이름이 이렇게 지정되어있으면, application-"dev".yml에서 "dev" 이 부분을 profile이 되고,
서버를 실행할 때, dev를 지정해주면 된다.

local은 그렇지만, 배포 서버가 문제였다.
application.yml이 공통이고 application.yml을 읽으면 프로필이 default 로 설정되는데,

어차피 local은 local로 줬었고, 배포 서버는 prod로 지정하기 때문에, 기본 application.yml을 삭제헸다.

그래서 현재 프로젝트의 yml은 아래와 같이 두 개 밖에는 없다.

YML 설정 방식도 후에 더 살펴봐야될 것 같다. 이건 리팩터링하면서 차차 해보기로 해야겠다.

여하튼.. prod를 profile로 지정하고, 서버를 실행했다.

현재는 -Dspring.profiles.active=prod 옵션을 주고, 서버를 실행시키고 있지만,

사실 처음은 $PROFILE에서 프로필을 읽어서 실행시키고 싶었다.

그러면 리눅스의 환경 변수에 PROFILE 변수를 넣어주면 되겠지..? 했지만,
애가 읽어오질질 못 한다....

export PROFILE="prod"

이렇게 주고, echo를 하면

이렇게 나오는데....

애플리케이션 실행시 slf4j를 써서, logging시 profile을 읽어서 출력하게 했지만, 역시 허탕이었다...

여튼 지금은 쉡 스크립트에 prod라는 값을 직접 주고, 실행하도록 했다.

자!

방금 내가 "$PROFILE도 못 읽어온다."고 말했다..
마찬가지로 yml에 EL로 환경 변수를 받아올 때에도 못 읽어왔다.

그러니깐 위에 local에선 로그인 링크로 잘 들어가던게, 서버에서는 안 들어가진다고 난리였던 것이다.

지금 그리고 구글로그인에선 401 인발리드 클라이언트 invalid client 가 나오고,
카카오톡 로그인에선

코에 일공일

KOE 101 이 나오는데, 두 오류 다 키값을 제대로 못 받고 있다는 의미였다.

이걸 알고 내가 뭘 찾았는가..

ㅋㅋ 젤 위에 동기 블로그가 나오다니.. ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ

이렇게 환경변수 선언을 찾았다.
그래서 EC2의 OS가 우분투인데,

~/.bashrc, /etc/profile에도 넣어보고, 쌍따옴표를 넣어야되니, 말아야되니, 공백이 없는데 왜 안읽히는 거니... 이런 사소한 부분에서 집착한 거 같다.

아래는 카카오 API키를 export를 넣고, 출력해본 결과다..

❗참고로! 변수를 선언하고 source 명령어는 당연히 넣었다!!

그래서 하드코딩을 해야되나...하면서 깃허브 액션에서 받아온 레포 디렉터리에서 application-prod.yml 을 하드코딩하고, 다시 쉘스크립트 해보고 오만 가지의 시도를 다 해봤지만, 여전히 해결되지 않았다..
(지금 볼드체로 깃허브 액션에서 받아온 레포 디렉터리라고 했는데, 이유가 있다.)

이렇게 나와야 되지만, 당시 yml파일을 보면

🤔🤔🤔🤔🤔🤔🤔

병맛처럼 나온다.;;;

set nu를 적용하면,

set nu를 적용해서 좀 볼만해졌지만...

생긴 거만 봐도 못 읽어올 것처럼 보이지 않는 건 나만 그런건가...

여튼... 정말 이런 문제로, 파일을 수정하고 GPT한테도 물어보고, 족히 서른마흔다섯 시간(feat. 바람)을 삽질 & 곡괭이질을 했다..
진짜 토나올 거 같았다....
오로지 나의 구글링&GPT한테 물어보고서만 해결하고 싶었지만 중간에 실력 있는 동기에게 한 번 물어봤다...
그 친구가 알려주길, yml 자체에 하드코딩을 하고, 깃허브 action에 넣고, Postconstruct를 써서, 값을 출력해보고, 로깅해보라고,,,,

로컬은 된다.
오~? 그럼.. 배포도 될까..?

🤑😟🫠😔😨😱🥶🥵🤪😵😷

하....

자세히 보면, 값을 읽어올 수 없다고 한다...

그런데,, 동기가 어렴풋이 이런 말을 남겼다.

깃허브의 브랜치에서 빌드를 하고 보낸다고, 그러니깐 이미 yml에서 값을 불러오지 못 하는 상태에서 내가 빌드를 해서 jar파일이 생성된다는 의미다.
그러니깐 아무리 리눅스에서 export를 때려봤자 헛수고였다는 것이다.

이걸로 6월 6일을 다 날렸는데...;;;

;;;;

ㅜㅜㅜ

여튼 그러면, 방법은 깃허브 액션에서 빌드를 할 때, 변수를 지정하게 해주면 될 것 같았다.

중간에 쉘스크립트에서 source ~/bashrc를 해더라도 적용되지 않았다.
지금 EL 표기법으로 써놓은게, EC2에서는 값이 하드코딩된 것처럼 들어가야 정상적으로 되기때문에, 소용 없는 부분이었다...

나는 한 블로그를 참고했고, gradle.yml에서 적용을 하도록 했다.

먼저는 깃허브의 프로젝트에서 secret으로 값들을 넣었다.

프로젝트의 셋팅에서 아래와 같이 키값을 넣었다.

그리고 /.github/workflows에서 gradle.yml을 수정해주었다.

... 생략

env:  
  S3_BUCKET_NAME: wanderhub.backend  
  RESOURCE_PATH: ./src/main/resources/application-prod.yml

... 생략
jobs:  
  build:  
    runs-on: ubuntu-latest  
    steps:
     - name: Set prod yml  
       uses: microsoft/variable-substitution@v1  
       with:  
         files: ${{ env.RESOURCE_PATH }}  
       env:  
         spring.security.oauth2.client.registration.google.clientId: ${{secrets.G_CLIENT_ID}} 
         spring.security.oauth2.client.registration.google.clientSecret: ${{secrets.G_CLIENT_SECRET}}  
         spring.security.oauth2.client.registration.kakao.clientId: ${{secrets.K_CLIENT_ID}}  
         spring.security.oauth2.client.registration.kakao.client-secret: ${{secrets.K_CLIENT_SECRET}}

...생략

이게 어떤 부분이냐...
env의 RESOURCE_PATH에 지정할 파일을 값으로 넣어준다.
그리고 build 할 때, with.files 에 해당 파일(application-prod.yml)을 지정해준 다음,
env 작업에 yml변수에 프로젝트 세팅의 secretKey로 지정해놓은 키에 대한 을 넣어준다.

jobs..steps[*].env

이렇게 주고 서버 실행을 하면!!!!!

구글로그인!!
두근! 두근! 두근!

(당연히 되니깐 올리겠지)

잘 나온다...!!!

서버 로깅에도 값을 잘 읽어오고 있다..
현재는 확인을 위한 코드가

@Value("${spring.security.oauth2.client.registration.google.clientId}")   
private Optional<String> clientId;  

@Value("${spring.security.oauth2.client.registration.google.clientSecret}")   
private Optional<String> clientSecret;  


@Value("${spring.security.oauth2.client.registration.kakao.clientId}")  
private Optional<String> kclientId;  

@Value("${spring.security.oauth2.client.registration.kakao.client-secret}") 
private Optional<String> kclientSecret;  

@PostConstruct  
private ClientRegistration clientRegistration() {  
    log.info("clientId = {}", clientId.isPresent());  
    log.info("clientSecret = {}", clientSecret.isPresent());  
    log.info("kclientId = {}", kclientId.isPresent());  
    log.info("kclientSecret = {}", kclientSecret.isPresent());  

    return CommonOAuth2Provider  
            .GOOGLE  
            .getBuilder("google")  
            .clientId(clientId.get())  
            .clientSecret(clientSecret.get())  
            .build();  
}

이렇게 되있다.

Optional을 통해서 값을 감쌌고, 값이 잘 들어왔으면, true일 것이고, 아니라면 false일 것인데,
값이 잘 들어오면, 서버가 잘 실행됨과 동시에, 아래처럼 값들에 true 들이 나올 것이다.

이렇게 결과가 나온다.

이렇게 yml에 값을 못 불러오는 문제를 해결하게 되었다.!!!

여담이지만, 진심으로 토나올 거 같았다...!!!

3. 요약

깃허브 액션의 CI/CD 자동배포를 이용할 때,
yml파일에 EL표기법을 써서 값을 할당하는 방법 즉, 환경변수를 읽어와서 값을 할당하는 방법은 소용이 없다.

왜냐하면, 깃허브 액션 브랜치에서 이미 빌드가 된 상태로 배포 서버로 넘어오기 때문이다.
그래서 아무리 EC2 OS에서 값을 주려해봤자 무용지물이었다.

그래서 빌드할 때에 yml의 변수에 값이 들어간 상태에서 빌드해야지 제대로 값이 들어간다.
그리고 값이 제대로 들어갔다면, 배포 서버의 실행시 지정한 yml 파일은 EL 표기법이 아니라, 값이 하드코딩된 상테로 보여야 한다.

🤔

❗갑자기 궁금해진게, "수동배포할 땐, 환경변수를 읽어올 수 있지 않을까..? "라고 생각이 들면서 나중에 해봐야겠다는 생각이 든다..

어찌됬든 간 결론은
빌드할 때 값을 불러올 수 있느냐, 불러오지 못하느냐에 따라 삽질을 하냐 안 하냐의 여부가 갈린다.

내가 너무 나무만 봤다... 숲을 봐야한다는 걸 또 절실히 깨닫는 이번 트러블 슈팅쓰다...

참고 블로그

yml지정1
yml지정2
yml지정3
yml지정4
@PostConstruct
https://itsowavy.oopy.io/github/githubactions-load-environment#58f28f5d-3b06-46a8-b1b7-1750849525d2
참고 핵심 블로그

4. 끝

-끝-

728x90

'TroubleShooting & 고민 > 배포' 카테고리의 다른 글

spring.datasource.url/username/password  (0) 2023.06.14
Comments