문제 해결 과정
Github Actions 빌드, 테스트 문제
😢 문제점
프로젝트를 Github Actions를 사용하여 배포한다.
Github Actions 파일의 내용을 살펴보면 다음과 같이 서버를 빌드하는 부분이 포함되어 있다.
- name: Build With Gradle
working-directory: ./tovalley-server
run: ./gradlew build
빌드 시 발생하는 문제점은 두 가지였다.
- yml 파일을 찾지 못한 빌드 실패
- test 실패
모두 로컬 환경에서는 정상적으로 동작하였지만 Github Actions를 통해 빌드를 수행하면 에러가 발생했다.
🧐 원인
GitHub Actions는 빌드 과정에서 프로젝트의 루트 디렉토리에 있는 파일들만 접근할 수 있다.
만약 application-prod.yml 파일이 루트 디렉토리에 없다면, GitHub Actions는 이를 찾을 수 없어 오류가 발생하게 된다.
🤩 해결 방법
- application-prod.yml 파일을 루트 디렉토리로 이동
- 이 방법은 가장 간단하지만, 프로젝트의 구조를 변경해야 하는 단점이 있다.
- 또한, 이렇게 하면 application-prod.yml 파일이 GitHub에 공개되므로, 중요한 설정 정보가 노출될 수 있다는 보안상의 문제가 있다.
- GitHub Secrets 사용
- GitHub Secrets를 사용하면 중요한 정보를 안전하게 저장하고, GitHub Actions에서 이를 사용할 수 있다.
- 이 방법으로 application-prod.yml의 내용을 GitHub Secrets에 저장하고, 빌드 스크립트에서 이를 읽어 파일을 생성할 수 있다.
- Dockerfile을 사용하여 빌드 과정에서 application-prod.yml 파일을 복사
- Dockerfile의 COPY 명령어를 사용하여 로컬 환경의 application-prod.yml 파일을 Docker 이미지 내부로 복사할 수 있다.
- 이렇게 하면 Docker 이미지가 생성될 때 해당 파일도 함께 포함되므로, GitHub Actions에서 빌드할 때 오류가 발생하지 않는다.
배포 과정에서 사용되는 application-prod.yml에는 노출되면 안되는 키값과 같은 민감 정보가 포함되어 있기 때문에
해당 프로젝트에서는 3가지 해결 방법 중 Github Secrets를 사용하는 방법을 택하였다.
- name: Make application-prod.yml
working-directory: ./tovalley-server
run: |
touch ./application-prod.yml
echo "${{ secrets.PROPERTIES }}" > ./application-prod.yml
- name: Make application-test.yml
working-directory: ./tovalley-server
run: |
touch ./application-test.yml
echo "${{ secrets.TEST_PROPERTIES }}" > ./application-test.yml
스텝은 작업 디렉토리를 ./tovalley-server로 설정한 후 application-prod.yml 파일을 만들고, 그 안에 GitHub Secrets에서 가져온 PROPERTIES 값을 작성한다.
- touch ./application-prod.yml
: touch 명령어는 주어진 파일 이름으로 새 파일을 생성한다.- 만약 파일이 이미 존재한다면, 이 명령어는 파일의 수정 시간을 현재 시간으로 변경한다.
- 여기에서는 application-prod.yml 파일을 생성하거나, 이미 있다면 수정 시간을 변경한다.
- echo "${{ secrets.PROPERTIES }}" > ./application-prod.yml
: echo 명령어는 인자로 주어진 텍스트를 출력한다.- 여기에서는 GitHub Secrets에서 PROPERTIES라는 이름의 비밀값을 가져와 출력한다.
- 그리고 > 기호는 출력을 파일에 작성하라는 의미이다.
- 따라서 이 명령어는 PROPERTIES의 값을 application-prod.yml 파일에 작성한다.
- 만약 파일이 이미 존재한다면, 기존 내용은 삭제되고 PROPERTIES의 값만이 남게 된다.
이렇게 설정하면 빌드와 테스트 모두 정상적으로 수행된다.
Nginx 설정 문제
😢 문제점
프로젝트에서 기본적으로 사용자 화면은 React로 구현됐지만 관리자 페이지의 경우 Thymeleaf를 사용해 구현되었다.
문제는 React로 구현된 페이지는 정상적으로 출력되지만 Thymeleaf로 구현한 관리자 페이지의 경우 다음과 같이 이미지와 css가 적용되지 않는다.
그리고 Thymeleaf 코드는 다음과 같다.
Thymeleaf 템플릿 엔진에서 `th:href`와 `th:src` 속성은 HTML의 `href`와 `src` 속성을 대체한다.
이 속성들을 사용하면 정적인 URL 대신 동적인 URL을 생성할 수 있다.
- th:href
: `th:href` 속성은 `href` 속성을 대체한다.- 이 속성은 주로 `<a>`, `<link>`, `<base>`, `<object>` 태그에서 사용한다.
- `th:href` 속성을 사용하면 서버 사이드에서 동적으로 URL을 생성하거나, Spring의 특별한 URL 구문(예: `@{...}`)을 사용할 수 있다.
- 예를 들어, `th:href="@{/css/admin-login.css}"` 코드는 서버가 동작하는 컨텍스트 경로를 기준으로 `/css/admin-login.css` 경로를 생성한다.
- 따라서 실제로 생성되는 URL은 서버의 설정에 따라 다르게 된다.
- th:src
: `th:src` 속성은 `src` 속성을 대체한다.- 이 속성은 주로 `<img>`, `<script>`, `<input>`, `<iframe>`, `<embed>`, `<source>` 태그에서 사용한다.
- `th:src` 속성을 사용하면 이미지나 스크립트 등의 리소스를 로드하는 URL을 동적으로 생성할 수 있다.
- 예를 들어, `th:src="@{/images/투계곡-logo.png}"` 코드는 서버가 동작하는 컨텍스트 경로를 기준으로 `/images/투계곡-logo.png` 경로를 생성한다.
- 따라서 실제로 생성되는 URL은 서버의 설정에 따라 다르게 된다.
🧐 원인
타임리프 페이지 요청 경로에 서버 동작 포트인 8080을 추가해 요청("http://13.125.136.237:8080/th/admin-login")하면 정상적인 페이지가 출력된다.
프로젝트에서 CSS 파일과 이미지 파일이 제대로 로드되지 않는 문제는 Spring Boot와 Nginx 간의 정적 리소스 경로 설정 문제일 가능성이 크다.
Spring Boot에서는 기본적으로 /resources/static 디렉토리 아래에 있는 파일들을 정적 리소스로 취급하고, 이를 루트 경로(/)에서 접근할 수 있게 해준다. 그러나 현재 Nginx 설정에 따르면, /api나 /th를 제외한 모든 요청은 React 앱을 위한 것으로 간주하고 있다.
따라서, CSS와 이미지 같은 정적 리소스들에 대한 요청이 Spring Boot가 아닌 React 앱을 위해 설정된 root /usr/share/nginx/html; 경로를 바라보게 되어, 해당 리소스들이 찾아지지 않는 문제가 발생하는 것이다.
🤩 해결 방법
이러한 문제를 해결하기 위해서는 Nginx 설정 파일에 정적 리소스 경로(/css, /images)에 대한 처리를 추가해야 한다.
- location ~ ^/(css|images)/ {...}
- URL 경로가 /css 또는 /images로 시작하는 요청을 처리한다.
- 이러한 요청은 http://server:8080로 프록시된다.
- 즉, 이 요청은 실제로는 Spring Boot 애플리케이션에 전달되게 된다.
문제가 해결된 이유는 다음과 같다.
이전에는 Nginx 설정에 따라, /api나 /th를 제외한 모든 요청은 React 앱을 위한 것으로 간주하고 있었다.
그 결과, CSS와 이미지 같은 정적 리소스들에 대한 요청이 Spring Boot가 아닌 React 앱을 위해 설정된 root /usr/share/nginx/html 경로를 바라보게 되어, 해당 리소스들이 찾아지지 않는 문제가 발생했다.
그러나 이제는 /css나 /images로 시작하는 요청은 Spring Boot 애플리케이션으로 전달되므로, Spring Boot 애플리케이션에서 처리할 수 있게 되었다. Spring Boot 애플리케이션에서는 기본적으로 /resources/static 디렉토리 아래에 있는 파일들을 정적 리소스로 취급하고, 이를 루트 경로(/)에서 접근할 수 있게 해준다. 따라서 이제는 /css나 /images 경로로의 요청이 정상적으로 처리되어 해당 리소스들이 제대로 로드될 수 있게 된 것이다.
React 환경 변수 문제
😢 문제점
React에서는 .env 파일을 사용해 외부에 노출되면 안되는 민감한 정보가 포함되어 있다.
🧐 원인
.env 파일이 GitHub에 공개되어 민감한 정보가 노출되는 위험이 있다.
🤩 해결 방법
그래서 첫 번째 문제점을 해결했던 방식인 GitHub Actions의 Secrets 기능을 사용하여 .env 파일의 내용을 안전하게 관리한다.
.github/workflows/deploy.yml
Github Secrets에 저장된 REACT_ENV 값을 통해 .env 파일을 생성한다.
tovalley-react/Dockerfile
Github Actions에서 생성된 .env 파일이 이미지 빌드 과정에서 React 앱에 포함되어 빌드된다.
이렇게 하면 .env 파일이 react에 포함되어 빌드될 것이다.
추가로 만약 .dockerignore 파일에 .env 파일이 포함되어 있다면 삭제해야 한다.
'기술 블로그 > ToValley' 카테고리의 다른 글
[Spring Boot + React]배포#5. AWS 보안 그룹 설정 (0) | 2023.12.17 |
---|---|
[Spring Boot + React]배포#4. AWS RDS 생성 및 설정 (1) | 2023.12.17 |
[Spring Boot + React]배포#3. AWS EC2 생성 및 설정 (0) | 2023.12.16 |
[Spring Boot + React]배포#2. 구성 이해 (2) | 2023.12.15 |
[Spring Boot + React]배포#1. 소개 (0) | 2023.12.15 |