CloudType을 이용해 테스트 배포를 해보기로 한다.
모두의 플랫폼팀, 클라우드타입
복잡한 클라우드 설정 없이 10분 만에 서비스를 배포하고 운영하는 방법, 클라우드타입
cloudtype.io
CloudType은 쉽게 프로젝트를 배포할 수 있는 플랫폼이다. 물론, 프레임워크와 웹에 대한 이해가 있어야 쉬운 것 같다. 나는 그리 많이 아는 것은 아니었으나 이번에 약 3일간, 하루 몇시간씩 배포, 버그 수정, 배포, 버그 수정을 반복하다 보니 어느정도는 이해하게 된 것 같다.
배포를 진행하기에 앞서 몇가지 수정이 필요하다. 우선 기존의 프로젝트는 "http://localhost:8080"로 설정되어 있기 때문에 이를 실제 서버 url로 변경해주어야 한다. 이는 배포 후 서버 url로 변경해주면 되는데 환경변수로 지정해주면 된다.
서버 url뿐만 아니라, 외부로 공개되서는 안되는 정보들을 .env파일에 환경변수로 저장하고 이를 .gitignore에 추가하는 작업이 필요하다.
우선 스프링부트에서 DB 연결과 OAuth 로그인을 위한 정보들을 환경변수로 만들어준다.
application.properties
spring.datasource.url=jdbc:mysql://${MYSQL_HOST}:${MYSQL_PORT}/${MYSQL_NAME}?serverTimezone=UTC&characterEncoding=UTF-8
spring.datasource.username=${MYSQL_USER}
spring.datasource.password=${MYSQL_PASSWORD}
# kakaotalk login
oauth.kakao.client_id=${KAKAO_CLIENT_ID}
oauth.kakao.redirect_uri=${KAKAO_REDIRECT_URI}
oauth.kakao.client_secret=${KAKAO_CLIENT_SECRET}
# naver login
oauth.naver.client_id=${NAVER_CLIENT_ID}
oauth.naver.redirect_uri=${NAVER_REDIRECT_URI}
oauth.naver.client_secret=${NAVER_CLIENT_SECRET}
# google login
oauth.google.client_id=${GOOGLE_CLIENT_ID}
oauth.google.redirect_uri=${GOOGLE_REDIRECT_URI}
oauth.google.client_secret=${GOOGLE_CLIENT_SECRET}
properties 파일에서 ${}로 감싸진 변수는 환경변수로 인식된다. 로컬 환경에서 개발시에는 .env파일을 루트 디렉터리에 생성하고 아래와 같은 형식으로 지정해주면 된다.
.env
export MYSQL_HOST=localhost
export MYSQL_PORT=3306
개발환경에 따라 다르지만 내가 사용하는 IntelliJ의 경우는 빌드 설정에서 자동으로 환경변수 주입이 가능하다.
그리고 이 .env파일들은 github에 push되면 안된다. 따라서 이를 .gitignore에 추가해 push되지 않도록 한다. 그리고 github repository를 이용해 배포하므로 로컬 개발환경에서는 로컬의 정보를 환경변수로 지정해두면 된다.
다음으로 build.gradle파일의 수정이 필요하다. 원래 jar파일로 배포를 진행하려 했는데, 이게 계속 에러가 나서 현재는 사용하지 않지만 그 과정에서 발견한 에러였다.
처음엔 너무 큰 파일 용량 때문에 배포가 되질 않았다. 2.8GB라는 비정상적인 repository 크기로 인해, .dockerignore파일로 resources 디렉터리를 배포시에 무시하도록 설정하고 jar 파일은 git LFS로 연결하고 별 짓 다했으나 문제는 단순했다.
바로 이전에 빌드한 결과물들이 제거되지 않은 채로 계속 쌓여왔던 것. 기존의 build.gradle에는 이런 설정이 있었다.
프로젝트 빌드 시 리액트 프로젝트를 먼저 빌드하고 이를 static 디렉터리에 복사해 함께 빌드한다.
그러나 기존의 빌드 결과물을 삭제하는 부분이 없었기 때문에 리액트에도, 스프링부트에도 모두 기존의 빌드 결과물이 존재했던 것이다. 이를 위해 우선 리액트에서 기존 빌드 결과물을 삭제하도록 아래 코드를 삽입하였다.
src/main/frontend/node_modules/react-scripts/config/webpack.config.js
output: {
path: paths.appBuild,
clean: true, // 추가
// 나머지
}
clean: true 설정을 추가하면 리액트 빌드 전에 기존의 빌드 파일들을 삭제해준다.
그리고 build.gradle을 다음과 같이 수정한다.
build.gradle
tasks.register('cleanResources', Delete) {
delete "$projectDir/src/main/resources/static"
}
// 나머지
tasks.register('copyReactBuildFiles', Copy) {
dependsOn "cleanResources"
dependsOn "buildReact"
from "$frontendDir/build"
into "$projectDir/src/main/resources/static"
}
이렇게 기존의 ststic 디렉터리를 비우는 설정을 추가하고, 이 작업이 수행된 이후 리액트 빌드를 복사하도록 하면 용량 문제가 사라진다.
이제 프론트엔드의 서버 설정이 필요하다. 리액트는 루트 디렉터리의 .env에 REACT_APP_{환경변수명}의 형식으로 지정하고 process.env.REACT_APP_{환경변수명}으로 불러온다. 하지만 이를 실제 서버로 해버리면 .env가 github에 push되지 않더라도 로컬에서 개발할 수가 없다. 따라서 .env를 별도로 설정하지 않고, 다음과 같이 코드를 작성해주었다.
const serverUrl = process.env.REACT_APP_SERVER_URL || 'http://localhost:8080';
이는 REACT_APP_SERVER_URL이라는 환경변수가 있다면 그 값을 사용하고, 없다면 "http://localhost:8080"을 사용하도록 디폴트 값을 정해준 것이다. 이렇게 하면 배포 환경에서는 실제 서버 주소가 저장되고 로컬환경에서는 포트를 사용해 개발이 가능하다.
이렇게 서버주소를 이용하도록 설정해준 후, cloudtype에서 배포를 시작한다.
나는 github으로 계정을 만들어서 바로 선택해 연결할 수 있지만, 그게 아니고 따로 private repository를 연결하려면 ssh 키를 이용해야 한다.
환경변수만 잘 입력해주면 나머지는 필요 없다. 리액트 환경변수 역시 함께 입력해주면 된다. 그럼 리액트가 빌드될 때 이 환경변수값이 코드로 대체되어 빌드되고, 빌드 결과물이 스프링부트의 static 디렉터리에 복사된다. 그리고 다시 properties의 환경변수에 값이 입력되어 프로젝트가 빌드된다.
다만 이대로는 배포가 되더라도, 연결한 데이터베이스가 로컬환경이라면 로그에서 데이터베이스에 연결되지 않는다는 에러가 난다.
같은 프로젝트 내에 데이터베이스를 배포하면 쉽게 연결이 가능하다.
MariaDB - 클라우드타입 Docs (cloudtype.io)
MariaDB - 클라우드타입 Docs
클라우드타입은 클라우드 기반 애플리케이션을 빠르게 개발하고 배포할 수 있는 클라우드 애플리케이션 플랫폼입니다.
docs.cloudtype.io
공식 문서를 참고해 연결하였다. 기존 데이터베이스는 MySQL인데, MariaDB가 MySQL과 호환성이 높아서 그냥 썼다. 로그에서 경고가 있긴 한데, 기본적인 기능에는 문제가 없어서 일단 유지중. 추후 MariaDB로 옮기든 해야겠다.
1학기 프로젝트 때 이 서비스를 알았다면 좋았을텐데, 그떄의 경험을 살려 지금 데이터베이스를 연결하는데는 문제가 없었다.
웹 환경을 위한 추가적인 조치(콘솔로그 삭제, x-content-type-options header 추가, cache-control heater 설정, Content-Type header에 charset=utf-8 추가)를 몇가지 한 후 현재 무사히 배포중이다. 이 추가조치에 대해서는 다음 포스트에서 다룰 예정이며 그냥 콘솔에 경고 뜨는거 보고 추가한거라 잘 모른다.
테스트 배포라 일부 지인에 한정해 로그인 승인해둔 상태로 피드백과 함께 개발 예정이다. 올해가 가기 전엔 공식 배포하는 것을 목표로.
'Side Project > 중단' 카테고리의 다른 글
ECEtaskHelper: 콘솔로그 제거, 캐시(Cache) 설정을 통한 성능 개선 및 보안 강화 (0) | 2024.08.14 |
---|---|
ECEtaskHelper: HomePage에 공지사항 스크래핑(Scraping)하기 (0) | 2024.08.13 |
ECEtaskHelper: 시간표 페이지(SchedulePage) 구성하기(3) - 시간표 렌더링 (0) | 2024.08.10 |
ECEtaskHelper: PrivateRoute, 반응형 사이드바(NavBar) (1) | 2024.08.06 |
ECEtaskHelper: 시간표 페이지 (SchedulePage) 구성하기(2) - 과목 검색/담기/추가/삭제 (0) | 2024.08.05 |