이번 포스트에서는 3-Tier에서 2nd Tier에 해당하는 Backend 계층을 구성해보자.
WAS 인스턴스 구성
인스턴스 추가
WAS는 2중화를 위해 2개의 인스턴스를 사용하기로 한다. 다음 정보를 이용해서 차례대로 생성해보자.
인스턴스 이름
영역 (Zone)
VPC / 서브네트워크외부
IP (External IP)
머신 유형 및 비고
free-was-a
us-central1-a
free-prd-vpc free-snet-private-was
임시 (Ephemeral)
e2-micro (무료) Spring Boot WAS 1호기 (설치 완료 후 외부 IP '없음'으로 제거 예정)
free-was-c
us-central1-c
free-prd-vpc free-snet-private-was
임시 (Ephemeral)
e2-micro (무료) Spring Boot WAS 2호기 (설치 완료 후 외부 IP '없음'으로 제거 예정)
💡 리전(Region) vs 영역(Zone) - 리전 (Region): 데이터 센터들이 위치한 지리적인 도시 단위 예: us-central1 (미국 아이오와) - 영역 (Zone): 하나의 리전 내부에서 전력과 네트워크가 완전히 독립된 개별 데이터 센터 건물 예: us-central1-a , us-central1-c - Zone을 사용하는 목적은 이중화 배포에 있다. 지진이나 정전 등으로 특정 건물(Zone A)이 통째로 중단되더라도, 다른 건물(Zone C)에 살아있는 서버가 즉시 트래픽을 넘겨받아 서비스 무중단(고가용성)을 달성하기 위함
⚠️ 외부 IP 임시 할당 꼼수 : 원래 외부 IP가 없는 VM이 인터넷(apt-get 등)을 쓰려면 유료인 Cloud NAT가 필요하다. 무료로 하려면 VM 생성 시 임시 외부 IP를 부여하고, 세팅 완료 후 외부 IP를 떼어내는 방식을 사용한다. 서비스에는 지장이 없다.
생성 결과
WAS VM에 Docker 설치
다음으로 임시 외부 IP가 붙어있는 2개의 WASVM(free-was-a,free-was-c)에 각각 접속(SSH)하여 도커를 설치한다.
@echo off
rem ==============================================
rem 기본 Docker Hub 계정 설정
rem ==============================================
set DEFAULT_DOCKER_USER=itsmeyjc
set DOCKER_USER=%~1
if "%DOCKER_USER%"=="" (
set DOCKER_USER=%DEFAULT_DOCKER_USER%
)
set IMAGE_NAME=free-was-app
set TAG=latest
set FULL_IMAGE=%DOCKER_USER%/%IMAGE_NAME%:%TAG%
echo ==============================================
echo 1. Spring Boot 프로젝트 빌드 중... (Maven)
echo ==============================================
call mvnw.cmd clean package -DskipTests
if %ERRORLEVEL% neq 0 (
echo 빌드 실패! 스크립트를 종료합니다.
exit /b 1
)
echo ==============================================
echo 2. Docker 이미지 빌드 중... (%FULL_IMAGE%)
echo ==============================================
docker build --platform linux/amd64 -t %FULL_IMAGE% .
if %ERRORLEVEL% neq 0 (
echo Docker 빌드 실패! 스크립트를 종료합니다.
exit /b 1
)
echo ==============================================
echo 3. Docker Hub 푸시 중... (사전 로그인 권장)
echo ==============================================
docker push %FULL_IMAGE%
if %ERRORLEVEL% neq 0 (
echo Docker 푸시 실패! 'docker login -u %DOCKER_USER%' 상태를 확인하세요.
exit /b 1
)
echo ==============================================
echo 성공적으로 빌드 및 푸시되었습니다!
echo VM 서버에서 아래 명령어로 컨테이너를 실행하세요:
echo sudo docker run -d -p 8080:8080 --name spring-was %FULL_IMAGE%
echo ==============================================
이미지 배포 확인
도커 허브에서 이미지 pull 및 컨테이너 구동
다음으로 VMdptj 도커 허브에 배포한 백엔드 이미지를 내려받아 8080 포트로 백그라운드 구동시켜준다.
sudo docker run -d -p 8080:8080 --name spring-was [도커허브계정명]/free-was-app:latest
docker hub의 image를 vm에 설치하는 모습
WAS 동작 검증
각 WAS VM의 SSH 터미널에서 아래 명령을 실행하여 컨테이너가 정상 구동 중인지와 Spring Boot의 실행 로그를 확인한다.
# 1. 실행 중인 컨테이너 목록 조회 (Status가 Up 8080->8080 인지 체크)
sudo docker ps
# 2. Spring Boot 콘솔 로그 실시간 확인 (Tomcat started on port 8080 문구 확인)
sudo docker logs -f spring-was
spring 살아있네!!
curl을 이용해서 정보를 조회해볼 수도 있다.
뭔가 동작한다.
외부 IP 제거
위 검증 과정에서 Spring Boot가 정상 기동되고 curl 호출에 성공했다면,GCP VM 수정 화면으로 이동하여 임시 외부 IP를 '없음'으로 변경함으로써 백엔드 서버를 사설망 안으로 안전하게 격리 완료한다.
다음 과정은 VM을 보안상 이유로 외부와 격리하기 위한 조치이다. 추가로 DB를 NAS등 외부의 mysql로 대체하려면 없애면 안된다.