EC2 서버 배포
"ShopEasy API 서버를 클라우드에 올리자"
학습 목표
- EC2 인스턴스의 개념과 역할을 이해한다
- 보안 그룹을 생성하여 서버의 인바운드/아웃바운드 트래픽을 제어한다
- 키 페어를 생성하고 SSH로 EC2에 접속한다
- EC2에 Node.js와 ShopEasy API 서버를 배포하여 동작을 확인한다
EC2란 무엇인가?
여러분이 카페를 운영한다고 상상해 보세요. 매장에서 직접 커피를 만들 수도 있지만, 배달 전문 주방(공유 키친)을 빌려서 운영할 수도 있습니다.
- 내 노트북 = 카페 매장에서 직접 만드는 것 (전기, 인터넷, 고장 모두 내가 관리)
- EC2 인스턴스 = 공유 키친을 빌리는 것 (건물 관리는 AWS가, 요리(서버 운영)만 내가)
EC2(Elastic Compute Cloud)는 AWS가 관리하는 가상 서버입니다. 내 컴퓨터를 24시간 켜 놓을 필요 없이, AWS 데이터센터의 서버를 빌려서 사용합니다.
EC2를 사용하는 이유
| 내 노트북으로 서버 운영 | EC2로 서버 운영 |
|---|---|
| 노트북 닫으면 서비스 중단 | 24시간 365일 안정적으로 운영 |
| 집 인터넷 속도에 의존 | AWS의 고속 네트워크 사용 |
| 고장 나면 서비스 불가 | 몇 분 안에 새 서버 생성 가능 |
| 보안 직접 관리해야 함 | AWS의 물리적 보안 + 내가 설정하는 논리적 보안 |
| 사양 업그레이드 = 새 노트북 구매 | 클릭 몇 번으로 사양 변경 가능 |
EC2 인스턴스는 다양한 사양(타입)이 있습니다. 이번 실습에서는 t2.micro를 사용합니다.
- t2.micro - vCPU 1개, 메모리 1GB (프리 티어 무료, 실습용으로 충분)
- t3.medium - vCPU 2개, 메모리 4GB (소규모 운영용)
- m5.large - vCPU 2개, 메모리 8GB (실제 운영용)
마치 렌터카를 빌릴 때 경차/중형차/대형차를 고르는 것과 같습니다.
ShopEasy에서 EC2의 역할
ShopEasy 이커머스 앱은 Node.js Express API 서버가 핵심입니다. 사용자가 상품을 조회하고, 장바구니에 담고, 주문하는 모든 요청이 이 API 서버를 거칩니다.
GET /api/products- 상품 목록 조회GET /api/products/:id- 상품 상세 조회POST /api/auth/register- 회원가입POST /api/auth/login- 로그인GET /api/health- 서버 상태 확인- 그 외 주문, 리뷰, 이미지 업로드 등
왜 퍼블릭 서브넷에 배치하나요?
쇼핑몰은 사람들이 쉽게 찾아올 수 있는 대로변(퍼블릭 서브넷)에 있어야 합니다. 창고(데이터베이스)는 뒷골목(프라이빗 서브넷)에 숨겨두면 됩니다.
EC2 API 서버는 고객이 직접 접속해야 하므로 퍼블릭 서브넷에 배치하고, 퍼블릭 IP를 할당하여 인터넷에서 접근할 수 있게 합니다.
핵심 개념 정리
보안 그룹 (Security Group)
보안 그룹은 EC2 인스턴스 앞에 서 있는 경비원입니다. 출입 명단(규칙)에 있는 사람만 통과시키고, 나머지는 모두 차단합니다.
- 인바운드 규칙 = 들어오는 사람 검사 (예: "SSH는 내 IP만", "5000번 포트는 모든 사람")
- 아웃바운드 규칙 = 나가는 사람 검사 (기본: 모두 허용)
| 규칙 | 프로토콜 | 포트 | 소스 | 용도 |
|---|---|---|---|---|
| 인바운드 | TCP | 22 | 내 IP | SSH 접속 (서버 관리) |
| 인바운드 | TCP | 5000 | 0.0.0.0/0 | API 서버 접속 (고객용) |
| 아웃바운드 | 전체 | 전체 | 0.0.0.0/0 | 외부 통신 (npm 패키지 다운로드 등) |
키 페어 (Key Pair)
키 페어는 EC2 서버에 접속하기 위한 디지털 열쇠입니다. 비밀번호 대신 암호화된 키 파일(.pem)로 접속합니다.
- 프라이빗 키(.pem) = 내가 보관하는 열쇠 (절대 남에게 주면 안 됨!)
- 퍼블릭 키 = EC2에 설치되는 자물쇠 (AWS가 자동 설치)
- .pem 파일은 다운로드 기회가 딱 한 번뿐입니다
- 잃어버리면 해당 키 페어로 EC2에 접속할 수 없습니다
- 절대 GitHub이나 공개된 장소에 업로드하면 안 됩니다
- 안전한 폴더에 저장하고 권한을 제한하세요
AMI (Amazon Machine Image)
AMI는 EC2 인스턴스의 운영체제 + 기본 소프트웨어가 담긴 이미지입니다. 컴퓨터를 살 때 Windows/Mac을 고르는 것처럼, EC2를 만들 때 AMI를 선택합니다.
이번 실습에서는 Amazon Linux 2023을 사용합니다. AWS가 최적화한 리눅스로, 가볍고 빠르며 AWS 도구가 기본 설치되어 있습니다.
Chapter 2 완성 후 아키텍처
Node.js 20 LTS
ShopEasy API :5000
- Chapter 1 (완료): VPC, 서브넷, IGW, NAT Gateway, 라우트 테이블
- Chapter 2 (지금): 보안 그룹, 키 페어, EC2 인스턴스, API 서버 배포
- Chapter 3 (다음): RDS MySQL 데이터베이스 연결
현재 단계에서 EC2는 내장 SQLite를 사용하여 동작합니다. Chapter 3에서 RDS MySQL로 전환할 예정입니다.
실습: EC2 서버 배포
- Chapter 1의 VPC 구축이 완료되어 있어야 합니다
- AWS 콘솔 리전이 ap-northeast-2 (서울)인지 확인하세요
- SSH 클라이언트가 준비되어 있어야 합니다 (Windows: Git Bash 또는 PowerShell, Mac/Linux: 터미널)
-
보안 그룹 생성 (EC2용)
EC2 인스턴스에 적용할 보안 그룹을 생성합니다. SSH(22번 포트)와 API 서버(5000번 포트) 트래픽을 허용해야 합니다.
보안 그룹 설정 내용항목 값 보안 그룹 이름 ShopEasy-EC2-SG설명 ShopEasy EC2 보안 그룹 VPC ShopEasy-VPC (Chapter 1에서 생성) 인바운드 규칙 1 SSH (TCP 22) - 내 IP 인바운드 규칙 2 사용자 지정 TCP (5000) - 0.0.0.0/0 아웃바운드 규칙 전체 트래픽 허용 (기본값) 도전: AWS EC2 콘솔에서 위 설정대로 보안 그룹을 생성하세요. VPC는 반드시 ShopEasy-VPC를 선택해야 합니다.
EC2 콘솔 > 네트워크 및 보안 > 보안 그룹 > 보안 그룹 생성
- VPC 드롭다운에서 ShopEasy-VPC를 선택합니다
- "인바운드 규칙 추가" 버튼을 클릭하여 규칙을 추가합니다
- SSH 유형을 선택하면 포트 22가 자동 입력됩니다
- 소스에서 "내 IP"를 선택하면 현재 IP가 자동 입력됩니다
- 5000 포트는 유형을 "사용자 지정 TCP"로 선택하고 포트에 5000을 입력합니다
- 5000 포트의 소스는 "Anywhere-IPv4 (0.0.0.0/0)"로 설정합니다
-
키 페어 생성
EC2에 SSH로 접속하기 위한 키 페어를 생성합니다. .pem 파일이 자동 다운로드되며, 이 파일은 다시 다운로드할 수 없으니 안전하게 보관하세요.
키 페어 설정 내용항목 값 이름 ShopEasy-Key키 페어 유형 RSA 프라이빗 키 파일 형식 .pem 도전: AWS 콘솔에서 키 페어를 생성하고, 다운로드된
ShopEasy-Key.pem파일을 안전한 위치에 저장하세요.EC2 콘솔 > 네트워크 및 보안 > 키 페어 > 키 페어 생성
- 이름에
ShopEasy-Key를 입력합니다 - 키 페어 유형은 RSA를 선택합니다
- 프라이빗 키 파일 형식은 .pem을 선택합니다 (Mac/Linux/Git Bash 용)
- Windows PuTTY 사용자는 .ppk를 선택할 수 있지만, Git Bash를 사용하므로 .pem을 선택합니다
- 생성 버튼을 클릭하면 .pem 파일이 자동 다운로드됩니다
- 다운로드 폴더에서 안전한 위치(예:
~/.ssh/)로 옮기세요
- 이름에
-
EC2 인스턴스 생성
이제 실제 EC2 인스턴스를 생성합니다. ShopEasy API 서버가 동작할 클라우드 컴퓨터입니다.
EC2 인스턴스 설정 내용항목 값 이름 ShopEasy-APIAMI Amazon Linux 2023 AMI (HVM, 64-bit) 인스턴스 유형 t2.micro (프리 티어) 키 페어 ShopEasy-Key (Step 2에서 생성) VPC ShopEasy-VPC 서브넷 ShopEasy-Public-Subnet-1 (퍼블릭 서브넷) 퍼블릭 IP 자동 할당 활성화 보안 그룹 ShopEasy-EC2-SG (Step 1에서 생성) 스토리지 8 GiB gp3 (기본값) 도전: 위 설정대로 EC2 인스턴스를 생성하세요. 특히 VPC, 서브넷, 퍼블릭 IP 설정을 놓치지 않도록 주의하세요.
EC2 콘솔 > 인스턴스 > 인스턴스 시작
- 이름:
ShopEasy-API입력 - AMI: "Amazon Linux 2023 AMI"를 선택 (Free tier eligible 표시 확인)
- 인스턴스 유형: t2.micro 선택 (Free tier eligible)
- 키 페어: 드롭다운에서 "ShopEasy-Key" 선택
- 네트워크 설정에서 "편집" 버튼 클릭:
- VPC: ShopEasy-VPC 선택
- 서브넷: ShopEasy-Public-Subnet-1 선택
- 퍼블릭 IP 자동 할당: 활성화
- "기존 보안 그룹 선택" 클릭 후 ShopEasy-EC2-SG 선택
- 나머지는 기본값 유지 후 "인스턴스 시작" 클릭
인스턴스 상태가 "실행 중(Running)"으로 바뀔 때까지 1~2분 기다립니다.
- 이름:
-
SSH로 EC2 접속
생성한 EC2 인스턴스에 SSH로 접속합니다. EC2 콘솔에서 인스턴스의 퍼블릭 IPv4 주소를 확인하세요.
먼저 .pem 파일의 권한을 설정합니다:
bash# .pem 파일 권한 설정 (Mac/Linux/Git Bash) chmod 400 ~/Downloads/ShopEasy-Key.pemSSH로 EC2에 접속합니다:
bash# EC2 접속 (YOUR_EC2_PUBLIC_IP를 실제 IP로 교체) ssh -i ~/Downloads/ShopEasy-Key.pem ec2-user@YOUR_EC2_PUBLIC_IP접속 정보- 사용자 이름:
ec2-user(Amazon Linux의 기본 사용자) - 인증 방식: .pem 키 파일
- 처음 접속 시 "Are you sure you want to continue connecting?" 질문에
yes를 입력합니다
도전: 위 명령어를 사용하여 EC2에 접속하세요.
[ec2-user@ip-10-0-1-xxx ~]$프롬프트가 나타나면 성공입니다.EC2 콘솔에서 퍼블릭 IP 확인 방법:
- EC2 콘솔 > 인스턴스에서 ShopEasy-API 인스턴스 클릭
- "퍼블릭 IPv4 주소" 항목의 IP를 복사
- 또는 인스턴스를 선택하고 "연결" 버튼을 클릭하면 SSH 명령어가 표시됩니다
Windows에서 Git Bash를 사용하면 동일한 SSH 명령어를 사용할 수 있습니다.
접속이 안 되면 보안 그룹에서 SSH(22번 포트)에 내 IP가 허용되어 있는지 확인하세요.
- 사용자 이름:
-
Node.js 20 LTS 설치
EC2에 접속한 상태에서 Node.js 20 LTS를 설치합니다. ShopEasy API 서버는 Node.js로 작성되어 있기 때문입니다.
도전: EC2에 접속한 상태에서 Node.js 20 LTS와 npm을 설치하세요. 설치 후
node --version과npm --version으로 확인하세요.Amazon Linux 2023에서 Node.js를 설치하려면 dnf 패키지 매니저를 사용합니다. Node.js 20을 설치하려면 먼저 NodeSource 저장소를 설정해야 합니다.
curl로 NodeSource 설치 스크립트를 다운로드하여 실행합니다- 그 다음
sudo dnf install -y nodejs로 설치합니다 - 또는
sudo dnf install -y nodejs20으로 직접 설치할 수도 있습니다 (Amazon Linux 2023 기본 저장소)
-
ShopEasy 코드 가져오기 (git clone)
GitHub에서 ShopEasy 이커머스 앱 코드를 EC2 서버로 가져옵니다.
도전:
git clone명령어로 다음 저장소를 EC2에 복제하세요.texthttps://github.com/shopeasydeploy/ecommerce-app.gitAmazon Linux 2023에는 git이 기본 설치되어 있습니다. 없다면
sudo dnf install -y git으로 설치합니다.bash# 홈 디렉토리에서 실행 cd ~ git clone https://github.com/shopeasydeploy/ecommerce-app.git클론 후
ls ecommerce-app/으로 파일 목록을 확인하세요. -
API 서버 시작
복제한 코드의
api-server디렉토리로 이동하여 npm 패키지를 설치하고 서버를 시작합니다.도전:
api-server디렉토리에서npm install로 패키지를 설치하고,npm start로 서버를 시작하세요.bash# api-server 디렉토리로 이동 cd ~/ecommerce-app/api-server # npm 패키지 설치 npm install # API 서버 시작 npm start서버가 정상적으로 시작되면 콘솔에 다음과 비슷한 메시지가 출력됩니다:
textServer is running on port 5000 Database initialized (SQLite mode)주의: 터미널이 서버에 잡혀 있음npm start실행 후에는 서버가 포그라운드에서 실행되어 터미널을 사용할 수 없습니다. 서버를 백그라운드에서 실행하려면 나중에 다루겠지만, 지금은 새 터미널 창을 열어서 확인 작업을 하거나, 웹 브라우저에서 직접 확인합니다. -
API 서버 헬스 체크
API 서버가 정상적으로 동작하는지 웹 브라우저에서 확인합니다.
도전: 웹 브라우저에서 다음 URL에 접속하여 서버 상태를 확인하세요.
texthttp://EC2_PUBLIC_IP:5000/api/healthEC2_PUBLIC_IP를 여러분의 EC2 인스턴스 퍼블릭 IP로 교체하세요.예상 응답정상이라면 다음과 같은 JSON 응답이 표시됩니다:
json{ "status": "ok", "timestamp": "2026-03-03T..." }접속이 안 될 경우 확인 사항:
- EC2 인스턴스가 "실행 중" 상태인지 확인
- 보안 그룹에서 5000번 포트가 0.0.0.0/0으로 열려 있는지 확인
- 퍼블릭 IP가 할당되어 있는지 확인 (EC2 콘솔에서 확인)
- npm start로 서버가 실행 중인지 EC2 터미널에서 확인
- URL에 https가 아닌 http를 사용하고 있는지 확인
-
상품 목록 API 확인
ShopEasy의 핵심 기능인 상품 목록 API를 호출하여 데이터가 정상적으로 반환되는지 확인합니다.
도전: 웹 브라우저에서 다음 URL에 접속하여 상품 목록을 확인하세요.
texthttp://EC2_PUBLIC_IP:5000/api/products예상 응답상품 목록이 JSON 배열로 반환됩니다:
json[ { "id": 1, "name": "무선 블루투스 이어폰", "price": 45000, "category": "전자기기", ... }, ... ]브라우저에서 JSON이 보기 어렵다면 다음 방법을 시도해 보세요:
- Chrome 확장 프로그램 "JSON Viewer"를 설치하면 보기 편합니다
- 또는 EC2에 접속한 다른 터미널에서
curl로 확인할 수도 있습니다:
bash# 새 터미널에서 EC2에 다시 SSH 접속 후 실행 curl http://localhost:5000/api/products | python3 -m json.tool
확인 사항
다음 항목을 모두 확인했는지 체크하세요:
- 보안 그룹
ShopEasy-EC2-SG가 ShopEasy-VPC에 생성되었다 - 보안 그룹에 SSH(22번 포트)와 HTTP(5000번 포트) 인바운드 규칙이 있다
- 키 페어
ShopEasy-Key가 생성되었고 .pem 파일을 안전하게 보관하고 있다 - EC2 인스턴스
ShopEasy-API가 퍼블릭 서브넷에서 실행 중이다 - EC2 인스턴스에 퍼블릭 IP가 할당되었다
- SSH로 EC2에 성공적으로 접속할 수 있다
- Node.js 20 LTS가 EC2에 설치되었다
- ShopEasy 코드가 EC2에 clone되었다
- API 서버가 포트 5000에서 실행 중이다
/api/health엔드포인트가 정상 응답을 반환한다/api/products엔드포인트가 상품 목록을 반환한다
현재 npm start는 포그라운드에서 실행되어 SSH 연결이 끊기면 서버도 종료됩니다.
실무에서는 PM2 같은 프로세스 매니저를 사용하여 서버를 안정적으로 운영합니다.
이 부분은 이후 챕터에서 다루겠지만, 지금 바로 해보고 싶다면:
# nohup으로 백그라운드 실행 (간단한 방법)
cd ~/ecommerce-app/api-server
nohup npm start > app.log 2>&1 &
# 로그 확인
tail -f app.log
현재 ShopEasy는 EC2 내장 SQLite를 사용하고 있습니다. Chapter 3에서는 RDS MySQL을 생성하여 진짜 데이터베이스에 연결합니다. 데이터가 EC2 인스턴스와 분리되어 더 안정적이고 확장 가능한 구조가 됩니다.