일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
- 최범균
- 영속성
- Spring
- 백엔드
- RESTClient
- java
- 한국대학생it경영학회
- kusitms
- 도메인 주도 개발 시작하기
- GitHub Actions
- JPQL
- 큐시즘
- 30기
- springboot
- 이펙티브자바
- Domain Driven Design
- 약속 장소 추천
- cicd
- 객체지향 쿼리 언어
- ddd
- Spring Batch
- jdbc
- 중간지점
- api rate limiter
- 중간 장소 추천
- 자바 ORM 표준 JPA 프로그래밍
- 중간 지점 추천
- Spot
- redis
- JPA
- Today
- Total
코딩은 마라톤
[KUSITMS] SPOT x 네이버 클라우드 : Container Registry를 이용하여 서버 배포 자동화하기 본문
[KUSITMS] SPOT x 네이버 클라우드 : Container Registry를 이용하여 서버 배포 자동화하기
anxi 2025. 6. 27. 15:34🍀 네이버 클라우드를 이용해 SPOT 서버 개발
큐시즘 30기에 이어 31기에서도 네이버 클라우드에서 다양한 서비스를 프로덕트에 적용해 볼 수 있도록 크레딧을 제공해 주셨다 🥳🥳🥳
이번 SPOT을 개발하면서 네이버 클라우드의 Container Registry와 Server를 이용해 서버를 구축했는데 구축 과정을 소개하고자 한다!
🚗 SPOT x 네이버 클라우드
📍SPOT 링크 : https://www.pickspot.co.kr/
📍SPOT Client Github : https://github.com/Team-MEET-UP/spot-client
📍SPOT Server Github : https://github.com/Team-MEET-UP/spot-server
SPOT은 약속 중간 지점 선정의 불편함을 해소하기 위해 약속의 목적을 고려한 장소를 추천하고 중간 지점을 산출해주는 서비스다.
특히 약속 제안자가 약속 참여자의 출발지를 취합하는 기존의 과정은 카카오톡에서 개개인의 참여자에게 연락을 보내고 중간지점 후보를 지정해 어떤지 물어보고 별로면 다시 정하는, 즉 약속 제안자의 불필요한 시간을 소모할 수 밖에 없다.
하지만 SPOT에서는 제안자가 약속을 만들고 링크를 참여자에게 제공함으로써, 제안자의 수고로움을 덜 수 있다. 중간지점 후보를 찾고 정하는 과정도 SPOT에서 제공하기 때문에 안 쓰면 손해인 서비스다 😆
초대규모 AI인 HyperCLOVA X로 비개발자도 네이버 클라우드를 들어봤을 거라 생각한다.
네이버 클라우드는 사진에 적힌 기술과 솔루션을 제공한다. 즉, 네이버 클라우드는 클라우드 서비스만 제공하는 것은 아니다 🙅
NAVER Cloud는 국내 CSP 기준 시장 점유 1위로 Naver Cloud Platform은 220개 이상의 클라우드 서비스를 제공한다.
이번에 네이버 클라우드에서는 NAVER Cloud Platform의 서비스를 사용할 수 있도록 큐시즘에 크레딧을 제공해 주셔서 무료로 클라우드 서비스를 사용해 보았다!
👀 서비스 아키텍처
현재 SPOT 개발하면서 사용한 NCP (NAVER Cloud Platform) 서비스는 아래와 같다.
- VPC : 논리적으로 격리된 네트워크 공간을 의미한다. Subnet이 VPC 내 포함된다. VPC -> Subnet 내 Server를 위치한다.
- Server : 백엔드 서버를 사용하기 위해 사용했다.
- Container Registry & Object Storage : 도커 컨테이너 이미지를 간편하게 저장, 관리, 배포할 수 있는 서비스이다. 컨테이너 이미지를 쉽게 전달 및 배포할 수 있으며, 이미지 저장을 위해 Object Storage도 같이 사용한다.
- ACG : 서버 그룹으로의 네트워크 접근을 제어 및 관리하는 데 사용되며, 서버 접속을 허용할 인바운드 트래픽 규칙을 안전하고 편리하게 추가, 변경, 삭제할 수 있다.
이제 위 서비스를 가지고 서버를 구축해 보자 😎
🔍 SPOT x NCP 서버 배포 자동화하기
0) VPC와 Subnet 생성하기
Server를 생성하기에 앞서, VPC와 Subnet 생성은 필수적이다. SPOT의 독립적인 네트워크 공간을 만들어봅시다!
사설 VPC IP 주소 범위인 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 내에서 IP 주소 범위를 지정해 주면 된다.
SPOT의 VPC를 만들었으니, Subnet을 만들러 가봅시다.
Subnet의 IP 주소 범위는 VPC의 CIDR 블록을 기반으로 하기 때문에, VPC 서브넷 마스크 비트를 더 쪼개서 구성해야 한다.
만약 VPC의 CIDR 블록이 10.0.0.0/16이라면, Subnet은 10.0.0.0/17~ 이어야 가능하다.
이렇게 해서 VPC와 Subnet을 손쉽게 생성해 봤다.
CIDR 블록을 잘 확인하고 설정하면 문제없이 생성될 것이다 🤩
1) Server 생성하기
Server를 생성하기에 앞서 어떤 스펙의 Server를 사용할지, 비용적인 측면도 고려해야 한다.
👇👇👇 상세한 서버 스펙과 비용은 아래를 참고해 주세요 👇👇👇
https://www.ncloud.com/product/compute/server#pricing
첫 번째로 서버 이미지를 선택해야 한다.
SPOT은 Ubuntu OS를 사용하고, 고사양의 서버는 필요 없기에 Standard 타입으로 설정했다.
두 번째로 서버 타입과 요금제를 선택해야 한다.
앞서 말한 것과 같이, Standard 서버로도 충분했기에 이로 설정하였고 Public IP를 할당하였다.
끝으로 서버 접근을 위한 인증키와 인바운드 트래픽 제어를 위해 ACG를 생성한다.
시간이 좀 지나고 나서, 서버가 운영되는 것을 볼 수 있다 😮
2) Container Registry 생성하기
Container Registry를 생성하기 앞서, Object Storage를 생성해야만 한다.
Object Storage를 생성하는 과정은 간단하기 때문에 아래를 참고해 생성해 주세요!
https://guide.ncloud-docs.com/docs/objectstorage-start
사실 Container Registry 생성하는 게 더 간단하다.!
레지스트리 이름을 설정하고 앞서 만든 버킷을 설정해 주면 바로 생성할 수 있다.
3) 배포 파이프라인 작성하기
SPOT의 CI/CD 과정은 다음과 같다.
- Pull Request 생성 또는 병합 시, Test Workflow가 실행되어 테스트 코드를 수행하고, 에러가 있을 경우 병합을 못하게 막는다.
- Pull Request가 develop 브랜치에 병합되면, Deploy Workflow가 실행되어 서버에 변경 사항이 배포된다.
Container Registry가 쓰인 부분은 Deploy Workflow이다.
name: Deploy
on:
push:
branches: [ "develop" ]
jobs:
build:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
submodules: true
token: ${{ secrets.GH_TOKEN }}
- name: Set up JDK 21
uses: actions/setup-java@v4
with:
java-version: '21'
distribution: 'temurin'
- name: Cache Gradle
uses: actions/cache@v4.2.3
with:
path: ~/.gradle/caches
key: gradle-${{ hashFiles('**/*.gradle') }}
restore-keys: gradle-
- name: Grant execute permission to gradlew
run: chmod +x ./gradlew
- name: Build with Gradle
run: ./gradlew build -x test
- name: move jar file to deploy
run: mv ./build/libs/*.jar ./deploy
- name: Docker Setup Buildx
uses: docker/setup-buildx-action@v3.10.0
- name: Login to NCP Container Registry
uses: docker/login-action@v3.4.0
with:
registry: ${{ secrets.NCP_CONTAINER_REGISTRY }}
username: ${{ secrets.NCP_ACCESS_KEY }}
password: ${{ secrets.NCP_SECRET_KEY }}
- name: Build and push Docker images
uses: docker/build-push-action@v6.15.0
with:
context: ./deploy
platforms: linux/amd64
push: true
tags: |
${{ secrets.NCP_CONTAINER_REGISTRY }}/spot-backend:${{ github.sha }}
deploy:
needs: build
name: deploy
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
with:
submodules: true
token: ${{ secrets.GH_TOKEN }}
- name: Copy docker-compose.yml to Server
uses: appleboy/scp-action@master
with:
host: ${{ secrets.NCP_HOST }}
username: ${{ secrets.NCP_USERNAME }}
password: ${{ secrets.NCP_PASSWORD }}
source: deploy/docker-compose.yml
target: /home/ubuntu/deploy
strip_components: 1
- name: Deploy to NCP Server and Run
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.NCP_HOST }}
username: ${{ secrets.NCP_USERNAME }}
password: ${{ secrets.NCP_PASSWORD }}
port: ${{ secrets.NCP_PORT }}
script: |
cd /home/ubuntu/deploy
echo "SPOT_IMAGE=${{ secrets.NCP_CONTAINER_REGISTRY }}/spot-backend:${{ github.sha }}" > .env
sudo docker compose down
sudo docker compose pull
sudo docker compose up -d
위 과정을 간단히 살펴보자!
build 과정
1. Checkout Code
현재 Github 리포지토리에 있는 최신 코드를 읽어온다.
2. Set Up JDK21
Github Actions의 JDK 21을 설치한다. SPOT은 JDK 21을 사용했기 때문에 21을 설치했지만, 프로젝트에 맞게 변경하면 된다.
3. Cache Gradle
빌드 속도 개선을 위해 Gradle 캐시를 적용한다.
`~/.gradle/caches` 에 Gradle 캐시를 저장하고, 만약 Key에 맞는 캐시가 없을 경우 `restore-keys`를 이용해서 가장 최근의 캐시를 복원한다.
4. Gradle 권한 허용 및 빌드
gradlew 권한을 허용하고, 빌드하는데 deploy Workflow 실행 전에 Test Workflow가 실행되기 때문에 중복을 막고자 테스트는 배제한다.
5. jar 파일 이동 및 Docker 설치
jar 파일을 Docker 이미지로 만들기 위해 특정 폴더(deploy)로 이동하고 Docker를 설치한다.
💡 아래 과정은 build 시 Naver Cloud Platform의 Container Registry를 사용하는 부분이다.
6. NCP Container Registry 로그인
- name: Login to NCP Container Registry
uses: docker/login-action@v3.4.0
with:
registry: ${{ secrets.NCP_CONTAINER_REGISTRY }}
username: ${{ secrets.NCP_ACCESS_KEY }}
password: ${{ secrets.NCP_SECRET_KEY }}
도커 이미지를 빌드하고 올리기 위해 로그인이 이뤄져야 한다.
Container Registry의 이름(registry), username(NCP Access Key) , password(NCP Secrey Key)를 환경변수로 넣어 로그인하였다.
AccessKey와 Secret Key는 "마이페이지 -> 계정 관리 -> 인증키 관리"에서 확인 가능하다!
7. 도커 이미지 Build & Push
- name: Build and push Docker images
uses: docker/build-push-action@v6.15.0
with:
context: ./deploy
platforms: linux/amd64
push: true
tags: |
${{ secrets.NCP_CONTAINER_REGISTRY }}/spot-backend:${{ github.sha }}
5번 과정에서 deploy 폴더로 이동한 jar 파일을 도커 이미지로 만들어야 한다.
# deploy/Dockerfile
FROM eclipse-temurin:21-alpine
ARG JAR_FILE=./*.jar
COPY ${JAR_FILE} spot.jar
ENTRYPOINT ["java", "-jar", "spot.jar", "--spring.profiles.active=dev"]
deploy 폴더 하위에 Dockerfile을 이용해서 SPOT의 도커 이미지가 만들어진다. 만들어진 도커 이미지는 Container Registry로 옮겨진다.
deploy 과정
Container Registry에 SPOT 도커 이미지를 이제 Server에서 실행해야 한다.
SPOT은 Redis를 컨테이너로 만들어 사용하기 때문에 docker-compose를 사용해 여러 개의 도커 컨테이너를 한 번에 정의하고 실행하게끔 하였다.
1. docker-compose.yml을 NCP Server에 옮기기
- name: Copy docker-compose.yml to Server
uses: appleboy/scp-action@master
with:
host: ${{ secrets.NCP_HOST }}
username: ${{ secrets.NCP_USERNAME }}
password: ${{ secrets.NCP_PASSWORD }}
source: deploy/docker-compose.yml
target: /home/ubuntu/deploy
strip_components: 1
---
# deploy/docker-compose.yml
services:
app:
image: ${SPOT_IMAGE}
container_name: spot-backend
ports:
- "8080:8080"
depends_on:
- redis
restart: always
environment:
TZ: Asia/Seoul
redis:
image: redis:7.4
container_name: spot-redis
ports:
- "6379:6379"
volumes:
- redis-data:/data
restart: always
volumes:
redis-data:
docker-compose.yml에서는 "Container Registry에 저장된 SPOT 이미지를 컨테이너화 하는 app"과 "redis 컨테이너"를 정의해 두었다.
Server에서 실행하기 위해 Server의 `/home/ubuntu/deploy`에 docker-compose.yml을 붙여 넣는다.
전송하기 위해 사용되는 host, username, password는 Server 생성하고 나서 만들어진 공인 IP, 관리자 이름, 비밀번호이다.
2. NCP Server에서 docker-compose 실행하기
- name: Deploy to NCP Server and Run
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.NCP_HOST }}
username: ${{ secrets.NCP_USERNAME }}
password: ${{ secrets.NCP_PASSWORD }}
port: ${{ secrets.NCP_PORT }}
script: |
cd /home/ubuntu/deploy
echo "SPOT_IMAGE=${{ secrets.NCP_CONTAINER_REGISTRY }}/spot-backend:${{ github.sha }}" > .env
sudo docker compose down
sudo docker compose pull
sudo docker compose up -d
배포 마지막 단계이다!
docker-compose.yml이 존재하는 `/home/ubuntu/deploy`로 이동해서 SPOT_IMAGE 태그를 환경변수(.env)로 만들어준다.
build 과정에서 7. 도커 이미지 Build & Push의 SPOT 이미지 태그를 붙여서 만들었기 때문에 만들어진 이미지를 Pull 하기 위해 환경변수로 만들어야 한다!
그리고 현재 docker compose로 띄워진 컨테이너를 정리하고 (down), 이미지를 저장하고 (pull), 컨테이너를 실행한다(up).
🍀 NAVER Cloud Platform를 사용하며
👍 좋았던 점
대다수의 개발자라면 AWS나 GCP를 사용했을 거라 생각한다. 이전에 개발했던 프로젝트도 AWS를 사용했었는데 AWS도 정말 좋은 CSP 회사이다! 다만, 아쉬웠던 점이 있다면 한글 설명이 번역체로 작성되어 있어 글의 내용을 이해하기 어려운 부분도 있었다.
하지만 NCP는 Naver Cloud에서 운영하는 국내 회사인 만큼, 문서가 한글로 초심자도 이해하기 쉽게 잘 작성되어 있어 개발하다가 막히는 부분이 있을 때 활용하기 매우 좋았다!
사실 위에 내가 작성한 것보다 훨씬 잘 적혀 있다..😅
또한 개발자 포럼과 같이 질문 소통 창구도 마련되어 있어서 '이런 게 가능할까?'라는 생각이 들 때 포럼을 찾아보면서 어느 정도 궁금증을 해소할 수 있었다.
지도 서비스다 보니 위/경도 좌표만으로 네이버 지도를 띄워줄 수 있는 방법을 찾던 도중, 위처럼 할 수 있는 것도 개발자 포럼을 통해 알게 되었다!
요약하자면, NCP는 인프라를 잘 모르는 개발자가 참고할 수 있는 문서와 여러 궁금증을 해소할 수 있는 개발자 포럼을 통해 많은 도움을 얻을 수 있을 거라 생각한다!
🥲 아쉬웠던 점
모든 인프라를 NCP를 사용해 구축해보고 싶었는데, DB는 AWS RDS를 사용했다. NCP의 DB 성능이 AWS Free tier 보다 훨씬 좋지만, 그만큼 비용 측면에서도 비용이 높다.
프로덕트 개발 초기 단계에서 그 정도의 성능이 필요하지는 않기 때문에 개발용으로 사용할 성능이 조금 낮고, 비용도 저렴한 DB가 있으면 더 좋지 않을까 생각했다 💭
🎬 마무리
네이버 클라우드에서 크레딧을 제공해 주셔서 Container Registry로 배포를 자동화하는 과정을 작성했다. 이뿐만 아니라 Clova Studio를 이용해 구글 리뷰를 번역하는 기능도 개발하고 있다!
앞으로의 욕심이 있다면, 현재 Kubernetes를 공부하고 있어서 Naver Kubernetes Service를 도입해서 배포 과정을 변경해보고 싶다. 또한 SPOT은 릴리즈 목표까지 있기 때문에 중간 지점 계산에 대해 확장이 필요하다. 확장을 위해 Clova Studio를 사용해서 AI로 중간 지점을 산출하고 주변 장소도 추천하게끔 하면 현재 산출/추천 방식보다 고도화될 것으로 생각하기 때문에 Clova Studio도 이번 스프린트에서 더욱 활용해 볼 예정이다.
배포 과정에서 궁금한 점이 있다면 글 서두에 있는 SPOT Github 또는 댓글 남겨주세요!
🤗 SPOT 많관부 🤗
'대외활동 > KUSITMS' 카테고리의 다른 글
[KUSITMS] 큐시즘 31기 운영진, 그리고 63명 앞에서의 첫 발표 (0) | 2025.02.23 |
---|---|
[대외활동] 큐시즘(KUSITMS) 30기 밋업 프로젝트 회고 (39) | 2024.12.26 |
[대외활동] 큐시즘(KUSITMS) 30기 기업프로젝트 회고 (8) | 2024.09.29 |