본문 바로가기

BackEnd : Spring/SpringBoot

[CI/CD] React.js + Spring Boot 웹 서비스 Docker, Github Action으로 EC2에 자동 배포하기 - 1. Nginx

이번 시간에는 Docker와 Github Action을 사용하여 React.js와 Spring Boot 웹 서비스를 CI/CD로 자동 배포하는 파이프라인을 다뤄보도록 하겠습니다.

각 단계에서 발생한 트러블슈팅 내용들을 보다 상세히 작성하기 위해 몇 개의 글로 나누어 업로드할 예정입니다!

배포 전략 선택 배경

이전 프로젝트에서는 AWS S3, Codedeploy 까지 이용한 CI/CD 배포 파이프라인을 구축했었습니다.

https://nymagicshop16.tistory.com/112

 

[AWS] SpringBoot 프로젝트 AWS CodeDeploy + S3 + Github Actions를 이용하여 CI/CD 구축, Docker + EC2 + RDS 로 배포

프로젝트 아키텍처1. EC2 서버 만들기참고한 글 : https://velog.io/@jonghyun3668/SpringBoot-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-EC2-%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B8%B0 SpringBoot 프로젝트 EC2 배포하기깃헙에 있는 프로젝트

nymagicshop16.tistory.com

이번 졸업프로젝트에서는 빠른 환경 구축과 프론트엔드와 백엔드단이 모두 지속적인 코드 통합과 배포가 이루어져야 했기 때문에 간단하게 Docker만 이용하여 환경을 구성하였습니다. 

첫번째로 선택한 파이프라인

원래는 이렇게 Nginx를 React 서버 앞 단에 두어 프론트엔드와 백엔드 서버 간의 리버스 프록시(Reverse Proxy) 를 사용하고, 로드밸런싱을 통해 가볍고 빠른 서버 환경을 구축하고자 하였습니다.

개발하긴 김에 Nginx를 깊게 공부하고 싶은 생각도 있었다..

기존에 사용한 Nginx 관련 설정들

https://coding-god-life.tistory.com/171?category=1082162

 

[react] Next.js + Docker + Nginx EC2 를 기준으로 Github Actions로 배포 자동화 CI / CD - 1

프로젝트를 하면서 정말 계속 수동으로 배포를 하는것에 번거로움을 느꼈다. CI / CD 를 미루고 미루다가 이번에 한 번 제대로 알아보고 적용해보기로 했다. - 프론트 Next.js 사용- 백엔드는 Spring,

coding-god-life.tistory.com

 

1.  문제 발생

Nginx를 사용하지 못하게 된 배경 : 동적 배포와 정적 배포

https://devbini.tistory.com/21

 

[👾Troubleshooting] 동적 배포와 정적 배포 문제 (REACT)

React 프로젝트를 Docker와 Nginx로 배포하는 과정에서 404 오류와 외부 API 호출 문제를 겪어 남기게 된 글이다. 1. 문제1-1. 새로고침 404문제첫쨰는 새로고침했을 때 나타나는 404 문제다.React-Route을 통

devbini.tistory.com

위 글을 참고하여 해결하였다.

우리 프로젝트에서 프론트엔드 개발자는 이미지 크기를 동적으로 수정하는 외부 api를 사용하고 있었다.

Nginx는 React에서 정적 빌드 파일을 실행한다.

결론은 정적 사이트로 배포된 React 서버는 동적인 요소들을 처리할 수 없었고, 외부 api에 대한 접근도 불가능했다.

2.  문제 해결

우리 프로젝트는 배포 과정에서 서버에서 Nginx를 통해 Docker로 프록시 되고, Docker 내부에서도 Nginx가 실행되어 React 정적 파일로 연결되어 있었다.

React를 정적으로 사용하고 있었던 것인데, 외부 API와 동적 라이브러리를 사용하는 우리 프로젝트의 특성상 동적 렌더링을 통해 배포하여야 하는 상황이었다.

Node 이미지 배포

따라서 Nginx 대신 node를 도커 이미지로 배포하는 것으로 수정하였다.

수정 전 Dockerfile

FROM node:21-alpine AS builder

WORKDIR /app

COPY package*.json ./

# npm 설치
RUN npm install

COPY . .

# Next.js를 빌드한다.
RUN npm run build
#RUN npm run export

# 이미지 생성
FROM nginx

# 오픈할 포트를 적어둔다.
EXPOSE 3000

RUN rm /etc/nginx/conf.d/default.conf
RUN rm -rf /etc/nginx/conf.d/*

# default.conf을 /etc/nginx/conf.d/ 경로에 있는 default.conf에 복사한다.
COPY nginx/default.conf /etc/nginx/conf.d/default.conf

COPY --from=builder /app/out /usr/share/nginx/html

원래 있었던 nginx/default.conf 파일도 삭제해 주었다.

수정된 Dockerfile

FROM node:21-alpine AS builder

WORKDIR /app

COPY package*.json ./

# npm 설치
RUN npm install

COPY . .

# Next.js 빌드 실행
RUN npm run build

# 오픈할 포트
EXPOSE 3000

# 앱 실행
CMD [ "npm", "start" ]

3. 결론

무작정 기술을 도입하는 것이 아니고 각 상황에 맞게 알맞은 기술을 사용해야 한다는 것을 다시 느끼게 해주었다.

새로운 프로젝트를 할 때 마다 CI/CD 배포 과정을 다양하게 적용해보려고 하는데, 각 프로젝트의 장단점을 파악해 그에 잘 맞는 기술들과 배포 환경을 선택하고, 이전과 비교해보는 과정이 재미있는 것 같다.