GitHub Action에서 Spring Boot 환경변수 설정하기

Seokjun Moon·2023년 11월 5일
0

카카오 테크 캠퍼스

목록 보기
11/12

GitHub Action CI&CD

깃허브에서 pull request, push 등의 이벤트가 발생하면 자동화된 작업을 수행할 수 있게 해주는 기능입니다. 카테캠 3단계에서 빌드 테스트를 진행하기 위해 사용했었습니다.

문제가 발생한 지점은, JWT 토큰의 secret과 토스 결제의 secret을 내부적으로만 사용할 수 있도록 분리해야 했습니다. 이를 위해 resources 폴더 내에 환경변수용 yaml 파일을 만들고, 값을 불러오도록 작성하였습니다.

파일 구성

YAML 파일

파일은 아래처럼 작성하였습니다.

security:
  jwt-config:
    secret:
      access: ${JWT_ACCESS_SECRET}
      refresh: ${JWT_REFRESH_SECRET}

payment:
  toss:
    secret: ${TOSS_PAYMENT_SECRET}

이렇게 작성 후, IntelliJ에서 configuration 설정을 통해 환경변수로 해당 값들을 주입하였습니다. 그리고 spring boot 프로젝트 내에서 위 yaml 파일의 값을 읽을 수 있도록 config 파일을 추가로 작성하였습니다.

EnvConfig.java

public class EnvConfig implements PropertySourceFactory {
    @Override
    public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException {
        YamlPropertiesFactoryBean factoryBean = new YamlPropertiesFactoryBean();
        factoryBean.setResources(resource.getResource());
        Properties properties = factoryBean.getObject();
        assert properties != null;
        return new PropertiesPropertySource(Objects.requireNonNull(resource.getResource().getFilename()), properties);
    }
}

이후 application 파일에 프로퍼티 소스를 등록해줍니다.

@SpringBootApplication
@PropertySource(value = {"classpath:env/env.yaml"},
                factory = EnvConfig.class)
public class SunsuWeddingApplication {

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

}

완료!

JWTProvider.java

위에서 환경변수를 분리하였으니, 내부 값도 변경할 차례입니다.

@Value("${security.jwt-config.secret.access}")
public String ACCESS_TOKEN_SECRET;

@Value("${security.jwt-config.secret.refresh}")
private String REFRESH_TOKEN_SECRET;

이렇게 작성하면 외부 환경변수로 값 주입 완료!

GitHub Action에서 문제 발생

환경변수를 등록해줘야 했습니다. 그래저 저희는 secret을 통해 환경변수 값을 추가하고, ci 설정 파일에서 환경변수를 주입하였습니다.

우선 GitHub repository > settings > security > secrets and variables > new repository secret 을 통해 필요한 값들을 등록합니다. 이후 ci 파일을 수정해야 하는데,

env:
  JWT_ACCESS_SECRET: ${{secrets.JWT_ACCESS_SECRET}}
  JWT_REFRESH_SECRET: ${{secrets.JWT_REFRESH_SECRET}}
  TOSS_PAYMENT_SECRET: ${{secrets.TOSS_PAYMENT_SECRET}}

전역으로 선언했습니다!! 대부분의 구글 포스트를 보면, echo ~~ >> ~~ 이런식으로 빈 파일에 secret을 직접 작성하여 사용하는 방식이었습니다. 이렇게 되면,

  1. 변수의 개수가 많아지면 상당히 번거로운 작업이 됩니다.
  2. 스크립트를 잘 작성하면 빈칸에 딱 넣을 수 있도록 가능하겠지만, 아직 해당 내용을 잘 모르는 입장에서는 어려웠습니다.
  3. 환경변수를 위의 yaml 파일처럼 구조화하기 어려울 것 같았습니다.

결국 모든 내용은 변수가 많아지면 너무 번거롭다는 것 ... 이고 그리고 애초에 머신 내의 환경변수로 설정해두면 불필요한 코드를 적을 필요도 없고 ... 뭐랄까 빌드 테스트를 할 때 환경변수를 작성하는게 옳지 않다는 생각이 들었습니다. 필요한 구조를 설계해두고, 말단의 값만 주입하는게 맞지 않을까요? 값 주입과 동시에 파일 구조도 주입되는 것은 위험하다는 판단이 들었습니다.

아무튼 ..

깃허브를 통해 등록한 secret은 secrets.XXXX 이렇게 불러올 수 있기 때문에, env.yaml에 필요한 JWT_ACCESS_SECRET, JWT_REFRESH_SECRET, TOSS_PAYMENT_SECRET 이 3가지를 선언했습니다.

그리고 run

을 하면 무조건 실패!! 합니다 왜냐하면 테스트 코드를 실행할 땐 위에 내용이 주입되지 않기 때문입니다. 실행 환경과 격리되기 때문에.. 그래서 @TestPropertySource 어노테이션을 통해 테스트용 변수를 별도로 주입했습니다.

@TestPropertySource(properties = {
        "security.jwt-config.secret.access=your-test-access-secret",
        "security.jwt-config.secret.refresh=your-test-refresh-secret",
        "payment.toss.secret=your-test-toss-payment-secret"
})

그리고 Push 후 다시 Action을 살펴보면

테스트 코드 및 실행도 모두 성공!!

땀 삐질삐질 과정 완료 ... 이제 남은건 리팩토링 ...??

profile
차근차근 천천히

0개의 댓글