Chapter 02

EC2 서버 배포

"ShopEasy API 서버를 클라우드에 올리자"

학습 목표

  • EC2 인스턴스의 개념과 역할을 이해한다
  • 보안 그룹을 생성하여 서버의 인바운드/아웃바운드 트래픽을 제어한다
  • 키 페어를 생성하고 SSH로 EC2에 접속한다
  • EC2에 Node.js와 ShopEasy API 서버를 배포하여 동작을 확인한다

EC2란 무엇인가?

비유로 이해하기: 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 서버를 거칩니다.

EC2가 하는 일
  • 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 파일 관리 주의!
  • .pem 파일은 다운로드 기회가 딱 한 번뿐입니다
  • 잃어버리면 해당 키 페어로 EC2에 접속할 수 없습니다
  • 절대 GitHub이나 공개된 장소에 업로드하면 안 됩니다
  • 안전한 폴더에 저장하고 권한을 제한하세요

AMI (Amazon Machine Image)

운영체제 선택

AMI는 EC2 인스턴스의 운영체제 + 기본 소프트웨어가 담긴 이미지입니다. 컴퓨터를 살 때 Windows/Mac을 고르는 것처럼, EC2를 만들 때 AMI를 선택합니다.

이번 실습에서는 Amazon Linux 2023을 사용합니다. AWS가 최적화한 리눅스로, 가볍고 빠르며 AWS 도구가 기본 설치되어 있습니다.

Chapter 2 완성 후 아키텍처

EC2 배포 후 구성도
사용자
웹 브라우저 / Postman
↓ HTTP 요청 (포트 5000)
ShopEasy-VPC (10.0.0.0/16)
Public Subnet (10.0.1.0/24)
Internet Gateway
Chapter 1에서 생성
보안 그룹
SSH(22) + HTTP(5000)
EC2 (t2.micro)
Amazon Linux 2023
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: 터미널)
실습 시작
  1. 보안 그룹 생성 (EC2용)

    EC2 인스턴스에 적용할 보안 그룹을 생성합니다. SSH(22번 포트)와 API 서버(5000번 포트) 트래픽을 허용해야 합니다.

    보안 그룹 설정 내용
    항목
    보안 그룹 이름ShopEasy-EC2-SG
    설명ShopEasy EC2 보안 그룹
    VPCShopEasy-VPC (Chapter 1에서 생성)
    인바운드 규칙 1SSH (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)"로 설정합니다
  2. 키 페어 생성

    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/)로 옮기세요
  3. EC2 인스턴스 생성

    이제 실제 EC2 인스턴스를 생성합니다. ShopEasy API 서버가 동작할 클라우드 컴퓨터입니다.

    EC2 인스턴스 설정 내용
    항목
    이름ShopEasy-API
    AMIAmazon Linux 2023 AMI (HVM, 64-bit)
    인스턴스 유형t2.micro (프리 티어)
    키 페어ShopEasy-Key (Step 2에서 생성)
    VPCShopEasy-VPC
    서브넷ShopEasy-Public-Subnet-1 (퍼블릭 서브넷)
    퍼블릭 IP 자동 할당활성화
    보안 그룹ShopEasy-EC2-SG (Step 1에서 생성)
    스토리지8 GiB gp3 (기본값)

    도전: 위 설정대로 EC2 인스턴스를 생성하세요. 특히 VPC, 서브넷, 퍼블릭 IP 설정을 놓치지 않도록 주의하세요.

    EC2 콘솔 > 인스턴스 > 인스턴스 시작

    1. 이름: ShopEasy-API 입력
    2. AMI: "Amazon Linux 2023 AMI"를 선택 (Free tier eligible 표시 확인)
    3. 인스턴스 유형: t2.micro 선택 (Free tier eligible)
    4. 키 페어: 드롭다운에서 "ShopEasy-Key" 선택
    5. 네트워크 설정에서 "편집" 버튼 클릭:
      • VPC: ShopEasy-VPC 선택
      • 서브넷: ShopEasy-Public-Subnet-1 선택
      • 퍼블릭 IP 자동 할당: 활성화
      • "기존 보안 그룹 선택" 클릭 후 ShopEasy-EC2-SG 선택
    6. 나머지는 기본값 유지 후 "인스턴스 시작" 클릭

    인스턴스 상태가 "실행 중(Running)"으로 바뀔 때까지 1~2분 기다립니다.

  4. SSH로 EC2 접속

    생성한 EC2 인스턴스에 SSH로 접속합니다. EC2 콘솔에서 인스턴스의 퍼블릭 IPv4 주소를 확인하세요.

    먼저 .pem 파일의 권한을 설정합니다:

    bash
    # .pem 파일 권한 설정 (Mac/Linux/Git Bash)
    chmod 400 ~/Downloads/ShopEasy-Key.pem

    SSH로 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 확인 방법:

    1. EC2 콘솔 > 인스턴스에서 ShopEasy-API 인스턴스 클릭
    2. "퍼블릭 IPv4 주소" 항목의 IP를 복사
    3. 또는 인스턴스를 선택하고 "연결" 버튼을 클릭하면 SSH 명령어가 표시됩니다

    Windows에서 Git Bash를 사용하면 동일한 SSH 명령어를 사용할 수 있습니다.

    접속이 안 되면 보안 그룹에서 SSH(22번 포트)에 내 IP가 허용되어 있는지 확인하세요.

  5. Node.js 20 LTS 설치

    EC2에 접속한 상태에서 Node.js 20 LTS를 설치합니다. ShopEasy API 서버는 Node.js로 작성되어 있기 때문입니다.

    도전: EC2에 접속한 상태에서 Node.js 20 LTS와 npm을 설치하세요. 설치 후 node --versionnpm --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 기본 저장소)
  6. ShopEasy 코드 가져오기 (git clone)

    GitHub에서 ShopEasy 이커머스 앱 코드를 EC2 서버로 가져옵니다.

    도전: git clone 명령어로 다음 저장소를 EC2에 복제하세요.

    text
    https://github.com/shopeasydeploy/ecommerce-app.git

    Amazon Linux 2023에는 git이 기본 설치되어 있습니다. 없다면 sudo dnf install -y git으로 설치합니다.

    bash
    # 홈 디렉토리에서 실행
    cd ~
    git clone https://github.com/shopeasydeploy/ecommerce-app.git

    클론 후 ls ecommerce-app/으로 파일 목록을 확인하세요.

  7. API 서버 시작

    복제한 코드의 api-server 디렉토리로 이동하여 npm 패키지를 설치하고 서버를 시작합니다.

    도전: api-server 디렉토리에서 npm install로 패키지를 설치하고, npm start로 서버를 시작하세요.

    bash
    # api-server 디렉토리로 이동
    cd ~/ecommerce-app/api-server
    
    # npm 패키지 설치
    npm install
    
    # API 서버 시작
    npm start

    서버가 정상적으로 시작되면 콘솔에 다음과 비슷한 메시지가 출력됩니다:

    text
    Server is running on port 5000
    Database initialized (SQLite mode)
    주의: 터미널이 서버에 잡혀 있음

    npm start 실행 후에는 서버가 포그라운드에서 실행되어 터미널을 사용할 수 없습니다. 서버를 백그라운드에서 실행하려면 나중에 다루겠지만, 지금은 새 터미널 창을 열어서 확인 작업을 하거나, 웹 브라우저에서 직접 확인합니다.

  8. API 서버 헬스 체크

    API 서버가 정상적으로 동작하는지 웹 브라우저에서 확인합니다.

    도전: 웹 브라우저에서 다음 URL에 접속하여 서버 상태를 확인하세요.

    text
    http://EC2_PUBLIC_IP:5000/api/health

    EC2_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를 사용하고 있는지 확인
  9. 상품 목록 API 확인

    ShopEasy의 핵심 기능인 상품 목록 API를 호출하여 데이터가 정상적으로 반환되는지 확인합니다.

    도전: 웹 브라우저에서 다음 URL에 접속하여 상품 목록을 확인하세요.

    text
    http://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 같은 프로세스 매니저를 사용하여 서버를 안정적으로 운영합니다. 이 부분은 이후 챕터에서 다루겠지만, 지금 바로 해보고 싶다면:

bash
# nohup으로 백그라운드 실행 (간단한 방법)
cd ~/ecommerce-app/api-server
nohup npm start > app.log 2>&1 &

# 로그 확인
tail -f app.log
다음 Chapter 미리보기

현재 ShopEasy는 EC2 내장 SQLite를 사용하고 있습니다. Chapter 3에서는 RDS MySQL을 생성하여 진짜 데이터베이스에 연결합니다. 데이터가 EC2 인스턴스와 분리되어 더 안정적이고 확장 가능한 구조가 됩니다.