배포 with Vercel, Cloudtype

Haks.·2025년 2월 19일
0

How to use

목록 보기
32/32

배포 개념과 중요성

배포 Deployment

  • 배포란?

    • 개발된 코드를 사용자들이 접근할 수 있도록 서버에 배치하는 과정
    • 로컬 환경에서 실행되던 코드를 프로덕션(운영) 환경으로 이동
    • 배포 후에도 유지보수와 모니터링 필요
  • 배포 환경의 유형

    • 로컬 환경 (Local Environment): 개발자 로컬 컴퓨터에서 실행
    • 스테이징 환경 (Staging Environment): 실제 배포 전에 테스트하는 환경
    • 프로덕션 환경 (Production Environment): 최종 사용자들이 사용하는 실제 환경

배포의 주요 단계

  1. 코드 준비: 로컬에서 실행 가능한 상태로 코드 작성 및 검증
  2. 빌드/패키징: 코드와 의존성을 묶어 실행 가능한 형태로 준비
  3. 환경 구성: 서버에서 실행에 필요한 설정 파일 작성 (환경 변수, 포트 설정)
    • 환경 파일을 만들어 감춰나야 예를들어 access토큰 같은 탈취를 안당함
  4. 배포 및 검증: 프로덕션 서버에서 실행 및 테스트

배포 방식 비교: 전통적인 방식 vs 최신 방식

  • 전통적인 배포 방식: 서버 직접 설정 (On-Premise)

    • 특징
      • 직접 설정 가능: 개발자가 환경을 자유롭게 구성 가능
      • 추가 비용 없음: 직접 서버를 관리하여 추가 서비스 비용이 적음
    • 단점
      • 환경 불일치 문제: 개발 환경과 운영 환경이 다르면 오류 발생
      • 수동 배포 비효율성: 변경 사항이 있을 때마다 직접 서버에 접속해서 배포해야 함
      • 확장성 부족: 트래픽이 많아질 경우 서버 성능을 조정하는 것이 어려움
  • 최신 배포 방식: Docker, CI/CD, 클라우드 플랫폼을 활용한 자동화 배포 Cloud-based, Serverless

    • 특징
      • 컨테이너(ex. Docker) 사용: 개발 환경과 운영 환경을 동일하게 유지
      • CI/CD 자동화
      • 클라우드 서비스 (AWS, GCP, Azure, NCP 등) 이용: 확장성 보장
    • 배포 자동화 예시
      • Github -> Cloudtype으로 자동 배포
      • 코드 푸시(git push)만 하면 자동으로 배포

클라우드 서비스 장단점

클라우드 서비스장점단점추천 사용 사례
AWS Free Tier● 다양한 서비스 제공 (EC2, Lambda 등)
● 1년간 무료 사용
● 강력한 확장성 및 유연성
● 복잡한 설정 과정
● 1년 후 요금 발생
● 대규모 프로젝트
● 복잡한 마이크로서비스 및 확장 가능한 애플리케이션
Google Cloud Platform (GCP)● 강력한 데이터 분석 도구
● Kubernetes와의 통합 지원
● 무료 크레딧 제공 (최초 $300)
● 설정 및 관리를 위한 학습 필요
● 무료 크레딧 소진 후 유료
● 데이터 중심 프로젝트
● AI/ML, 데이터 처리 및 분석
Microsoft Azure● Windows 기반 시스템에 강력한 지원
● 다양한 지역에 데이터센터 제공
● 설정이 복잡하고 비용이 다소 높음
● 무료 티어 제한적
● Windows 기반 프로젝트
● 기업용 애플리케이션

클라우드 서비스장점단점추천 사용 사례
Heroku● 간편한 배포 및 사용
● 개발자 친화적
● 비교적 낮은 단가의 기본 플랜
● 기본 플랜에서 슬립 모드 (대기 상태) 발생
● 유료 플랜 비용이 다소 높음
● 스타트업 및 개인 프로젝트
● 간단한 웹 애플리케이션 및 API 서버
Vercel● 정적 사이트 및 서버리스 함수에 최적화
● 무료 플랜 제공
● 자동화된 배포
● 동적 애플리케이션에는 제약
● 데이터베이스 연결 시 추가 설정 필요
● 정적 사이트
● JAMstack 애플리케이션 (Next.js 등)
Netlify● 정적 사이트 배포에 최적화
● 무료 플랜 제공
● CI/CD 파이프라인 내장
● 서버리스 기능 제한
● 동적 애플리케이션에는 적합하지 않음
● 프론트엔드 중심 프로젝트
● 간단한 마케팅 페이지 및 블로그

클라우드 서비스장점단점추천 사용 사례
Fly.io● Edge 서버를 통한 지리적 분산 배포
● 무료 크레딧 제공
● Docker 이미지 지원: 컨테이너 기반 배포 가능
● 복잡한 설정 필요: 초보자에게는 설정이 어려울 수 있음
● 대규모 애플리케이션에 제한적: 높은 트래픽 처리에는 한계
● 글로벌 사용자 대상 애플리케이션
● 소규모 API
Render● 자동화된 CI/CD 파이프라인
● 무료 티어 제공
● 쉬운 설정
● 높은 사용량 시 유료 전환 필요
● 제한된 무료 리소스
● 개인 프로젝트
● API 서버, 웹 애플리케이션
Railway● 직관적인 UI 및 빠른 배포
● 사용량 기반 청구
● 여러 언어 및 데이터베이스 지원
● 무료 티어 사용량 제한
● 높은 트래픽 시 요금 발생
● 개인 및 소규모 팀 프로젝트
● 데이터베이스가 필요한 애플리케이션

클라우드 서비스 선택 시 고려사항

  • 프로젝트 규모 및 복잡도

    • 소규모 프로젝트: Render, Railway
    • 대규모 확장 가능한 프로젝트: AWS, GCP, Azure
  • 예산

    • 무료 티어 제공 여부 확인: Fly.io, Render, Railway 등
    • 높은 트래픽이나 데이터베이스 사용이 예상되면 비용 분석 필수
  • 설정의 간편성

    • 빠른 설정: Heroku, Render 추천
    • 복잡한 설정과 유연성을 원한다면 AWS, GCP 추천
  • 기술 스택 호환성

    • 정적 사이트 중심: Vercel, Netlify
    • 서버리스 애플리케이션: AWS Lambda, GCP CloudFunction
    • 데이터베이스 중심: Railway, AWS RDS
  • 서비스 안정성 및 지원

    • 글로벌 서비스, 데이터 센터: AWS, GCP, Azure 추천
    • 지역 기반 서비스: 데이터 센터 위치를 확인할 것
  • 성능 및 확장성

    • 예측 가능한 트래픽: Render, Vercel
    • 높은 확장성 요구: AWS, GCP, Azure
  • CI / CD 및 개발자 도구

    • 자동화 배포: Render, Vercel, Netilfy 추천
    • 데이터 분석, AI 통합이 필요하다면 GCP 추천

DevOps와 배포 자동화

  • DevOps: Development + Operations

    • 소프트웨어 개발과 운영을 하나로 통합하여 빠르고 안정적인 배포를 가능하게 하는 문화 및 기술
    • 자동화 -> 안정성 증가 및 빠른 업데이트 가능
    • CI(Continuous Integration) 지속적 통합: 코드 변경 사항을 자동으로 빌드 및 테스트
    • CD(Continuous Deployment) 지속적 배포: 코드 변경 사항을 운영 환경에서 자동 배포
  • CI/CD 파이프라인 예시

    • 개발자가 코드 변경 후 github에 푸시
    • CI 시스템 (Github Actions)이 자동으로 빌드 및 테스트 실행
    • 테스트 통과 시, CD 시스템 (Cloudtype)이 배포 자동화 진행
    • 배포 완료 후, 운영 서버에서 서비스 활성화

배포의 확장성과 유지보수

  • 배포 시스템이 확장성을 가지려면?

    • MSA(Micro Service Architecture): 여러 작은 서비스로 분리
    • Container Orchestration (Kubernetes) 사용: 자동 확장 및 관리 지원
    • 무중단 배포 (Blue-Green Deployment): 운영 중에도 장애 없이 배포 (프론트면 실제 파일에 덮어 씌워 버리는 것)
  • 배포 후 지속적인 모니터링

    • 서비스 상태 체크: Health Check API
    • 로깅 및 오류 분석: Sentry, Prometheus
    • 성능 모니터링: Grafana

Docker란

  • 애플리케이션을 컨테이너라는 가상 환경에서 실행하는 기술
    • 컨테이너를 사용하면 OS에 영향을 받지 않고 어디서든 동일한 환경에서 실행 가능
      • A는 Windows에서, B는 CentOS에서 프로그래밍을 할 때 불일치가 발생할 수 있으며, 이 때 컨테이너 기술을 사용하면 둘이 동일한 환경에서 서버 구동 가능

컨테이너 vs 가상머신 (VM)

항목가상머신 (VM)Docker 컨테이너
실행 속도느림빠름
운영체제각 VM마다 필요호스트 OS 공유
리소스 사용많음 (RAM, CPU 차지)적음
실행 환경무겁고 복잡가볍고 단순

가상머신이란 ?

하드웨어 자원을 가상화하여 독립적인 운영체제를 실행할 수 있도록 만든 소프트웨어 환경을 의미해. 즉, 하나의 물리적인 컴퓨터 위에서 여러 개의 가상 컴퓨터를 실행

  • 특징

    1. 독립적인 운영체제 실행
      • VM마다 각각의 운영체제(Windows, Linux 등)를 설치할 수 있음.
      • 호스트 OS(기본 운영체제)와 다른 OS도 설치 가능.
    2. 하드웨어 리소스 분할
      • CPU, RAM, 저장소 등의 자원을 가상화하여 할당.
      • 하나의 물리 서버에서 여러 VM을 실행할 수 있음.
    3. 보안 및 격리성
      • 각 VM은 서로 완전히 독립적이라, 하나의 VM이 문제가 생겨도 다른 VM에 영향을 주지 않음.
    4. 유연한 배포와 관리
      • 클라우드 서비스(AWS, Azure, GCP)에서 가상머신을 쉽게 생성 및 관리 가능.
  • VM의 대표적인 종류

    • VirtualBox → 로컬 환경에서 VM 실행 (무료)
    • VMware → 기업에서 많이 사용 (유료)
    • Hyper-V → Windows 전용 가상화 소프트웨어
    • AWS EC2, GCP Compute Engine → 클라우드 기반 가상머신
  • 가상머신(VM)은 언제 사용하면 좋을까?

    • 서로 다른 OS 환경을 실행해야 할 때 (예: Windows에서 Linux 실행)
    • 보안이 중요한 애플리케이션을 실행할 때 (완전한 격리가 필요할 때)
    • 물리적 서버를 여러 개로 나눠서 사용하고 싶을 때

도커

  • 핵심

    • 이미지(image): 실행 가능한 애플리케이션 패키지
    • 컨테이너(Container): 실행 중인 이미지 (실제 애플리케이션이 실행됨)
    • Dockerfile: Docker 이미지를 생성하는 설정 파일
  • 주요 명령어

    • 실행 중인 컨테이너 목록 조회: docker ps
    • 모든 컨테이너 목록 (중지된 컨테이너 포함): docker ps -a
    • 실행 중인 컨테이너 중지: docker stop <container_id>
    • 실행 중인 컨테이너 강제종료: docker kill <container_id>
    • 컨테이너 삭제: docker rm <container_id>
    • 컨테이너 로그 확인: docker logs <container_id>

이미지 빌드 & 실행

  • 도커 이미지 빌드
    • docker build -t <이미지명><태그>, (docker build -t app .)
  • 도커 컨테이너 실행 (포트 매핑 포함)
    • docker run -d -p <호스트포트>:<컨테이너포트> <이미지명>

이미지 및 볼륨 관리

  • 모든 도커 이미지 목록 확인
    • docker images
  • 특정 도커 이미지 삭제
    • docker rmi <image_id>
  • 사용하지 않는 이미지 및 볼륨 정리
    • docker system prune -a

Docker 컨테이너 최적화

  • 실행 환경을 최대한 가볍게 만들어야 함

    • 작은 베이스 이미지 사용
      • FROM python:3.10 (922MB)
      • FROM python:3.10-alpine (25MB)
  • 불필요한 캐시 저장 방지 & 빌드 속도 최적화

# 1. Python 3.10 기반 이미지 사용
FROM python:3.10-alpine (alpine사용 경량화)

# 2. 작업 디렉토리 생성
WORKDIR /app

# 3. 의존성 설치
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# 4. FastAPI 애플리케이션 복사
COPY . .

# 5. 컨테이너 실행 명령어 설정
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
  • 다중 스테이지 빌드 적용
# 1. 빌드 스테이지 (의존성 설치만 수행)
FROM python:3.10-alpine (alpine사용 경량화)
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# 2. 실행 스테이지 (필요한 파일만 복사)
FROM python:3.10-alpine (alpine사용 경량화)
WORKDIR /app
COPY --from==builder /app /app
COPY . .
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
  • .dockerignore 활용
    • pycache/
    • .env
    • *.log
  • FastAPI Docker 이미지 빌드 예시
# main.py
from fastapi import FastAPI

app = FastAPI()

@app.get("/")
async def read_root():
	return {"message": "FastAPI on Docker!"}

# requirements.txt
fastapi
uvicorn

# Dockerfile
# 1. Python 3.10 기반 이미지 사용
FROM python:3.10-alpine

# 2. 작업 디렉토리 생성
WORKDIR /app

# 3. 의존성 설치
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# 4. FastAPI 애플리케이션 복사
COPY . .

# 5. 컨테이너 실행 명령어 설정
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

Docker Compose로 FastAPI + DB 연동

  • Docker Compose: 여러 개의 Docker 컨테이너를 한 번에 실행하는
    도구
  • 주로 서버 + DB 등을 한 번에 돌릴 때 사용
    • ex) FastAPI + PostgreSQL + Redis
  • docker-compose up -d
# compose.yaml
version: "3.9" # Docker Compose 버전

services:
  db:
    image: postgres: 13 # PostgreSQL 13 버전 사용
    container_name: fastapi_postgres
    restart: always # 컨테이너가 종료되면 자동 재시작
    environment:
      POSTGRES_USER: fastapi_user
      POSTGRES_PASSWORD: fastapi_password
      POSTGRES_DB: fastapi_db
    ports:
      - "5432:5432"
    volumes:
      - postgres_data:/var/lib/postgresql/data # DB 데이터 저장
  
  fastapi:
    build: . # 현재 디렉토리의 Dockerfile를 사용해 이미지 빌드
    container_name: fastapi_app
    depends_on:
      - db # db 서비스가 실행된 후 fastapi 서비스 실행
    ports:
      - "8000:8000"
    environment:
      DATABASE_URL: "postgresql://fastapi_user:fastapi_password@db:5432/fastapi_db"
    
volumes:
  postgres_data: # PostgreSQL 데이터를 저장할 볼륨(컨테이너 재시작 시 데이터 유지)

도커 실습

# (1) 도커 이미지 빌드 (현재 디렉토리의 Dockerfile 사용)
docker build -t app .

# (2) 빌드된 이미지 확인
docker images

# (3) 컨테이너 실행 (-d: 백그라운드 실행, -p: 포트 매핑)
docker run -d -p 8000:8000 app


# (1) 실행 중인 컨테이너 확인
docker ps   

# (2) 컨테이너 중지 (b = 컨테이너 ID or 이름)
docker stop b   

# (3) 실행 중인 컨테이너가 있는지 다시 확인
docker ps -a  
   


# (1) 특정 컨테이너 삭제 (중지된 상태여야 함)
docker rm b    

# (2) 모든 컨테이너 삭제 (실행 중인 것도 포함, 강제)
docker rm $(docker ps -aq) -f  


# (1) 실행 중인 컨테이너 확인
docker ps  

# (2) 실행 중인 컨테이너 중지 (필수)
docker stop <container_id>   

# (3) 실행 중지 후 이미지 삭제 (-f: 실행 중인 것도 삭제)
docker rmi 이미지명 -f    

# (4) 사용하지 않는 이미지 전부 삭제 (dangling 이미지)
docker image prune -a

배포 방법 개요

  • 컨테이너를 클라우드에 올린다고 바로 실행되지 않음
    • 로컬에서는 Docker 컨테이너 실행만으로 API에 접근 가능
    • 클라우드에서는
      • 컨테이너가 실행되더라도 네트워크 접근이 차단되어 있음
      • 로드 밸런서, 방화벽, 인바운드 규칙 설정이 필요할 수 있음
      • 게다가 여러 컨테이너를 운영하려면 오케스트레이션 필요
        • 보통 Kubernetes(쿠버네티스) 사용
        • 여러개를 관리하려면 필요한 개념

쿠버네티스

Kubernetes는 꼭 사용해야 할까?

  • 단일 컨테이너라면 K8S 없이 실행 가능
  • 하지만 트래픽 증가, 자동 스케일링, 무중단 배포, 2개 이상 컨테이너를 사용 시 쿠버네티스를 사용해야 함
  • K8S 사용 시 배포 방법
    • 컨테이너를 Registry에 업로드
    • VPC, Subnet, NAT GW, Storage 설정
    • Kubernetes Service에 Registry 연결 (템플릿 배포)

Cloudtype 배포

  1. Cloudtype 가입 (카드 등록 필수)
  2. 컨테이너 기반 환경: SQLite 그대로 사용할 예정
  • 단 컨테이너가 재시작될 시 파일이 삭제될 수 있음 = 저장 경로를 지정함으로써 문제 해결
database.py
from sqlalchemy import create_engine, Column, Integer, String
from sqlalchemy.orm import sessionmaker, declarative_base
import os

DB_DIR = "./data"
if not os.path.exists(DB_DIR):
    os.makedirs(DB_DIR)

DATABASE_URL = "sqlite:///./data/test.db"

engine = create_engine(DATABASE_URL, connect_args={"check_same_thread": False})
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
Base = declarative_base()

class Ticket(Base):
    __tablename__ = "tickets"
    id = Column(Integer, primary_key=True, autoincrement=True)
    name = Column(String, index=True)
    age = Column(Integer)
    price = Column(Integer)

Base.metadata.create_all(bind=engine)

def get_db():
    db = SessionLocal()
    try:
        yield db
    finally:
        db.close()
  1. cloudtype.yaml 추가
# cloudtype.yaml
app: fastapi-tickets
service: web
env: python
start: uvicorn main:app --host 0.0.0.0 --port 8000
  1. Github Repository 생성

  1. Cloudtype 접속

  1. Cloudtype 배포

Vercel 배포

  • Serverless 환경
    • SQLite는 로컬 기반이며 Vercel에서 사용 불가
    • 따라서 외부 DB를 생성하여 연결하는 방향으로 진행 예정
  • 배포 시 확인할 것
    • vercel.json
    • vercel CLI 설치 (npm 사전 설치 필요)
    • NeonDB, Vercel 회원가입
    • requirements.txt 더블체크 (특히 psycopg2-binary)
  1. pip install psycopg2-binary + NeonDB로 접속 로그인 후 connect로 내 DB주소 확인, 아래 postgresql 부분 복사

  1. database.py
# database.py
import os

DATABASE_URL = os.getenv("DATABASE_URL", "postgresql://user:password@dbhost:5432/dbname")

engine = create_engine(DATABASE_URL)

3.vercel.json

{
  "builds": [
    { "src": "main.py", "use": "@vercel/python" }
  ],
  "routes": [
    { "src": "/(.*)", "dest": "main.py" }
  ]
}
  1. vercel 설치 및 프로젝트 초기화
  2. npm install -g vercel
  3. vercel login (vercel 웹사이트 회원가입)
    • Continue with GitHub(원하는 것에 맞춰)
    • vercel link
    • Scope 선택
    • N
    • 제작한 프로젝트 이름
    • ./
  4. 환경변수 설정
  • vercel env add DATABASE_URL(postgres url 복붙)
  • Production
  1. 배포 시작 : vercel .

  1. 오류 발생시

  1. 환경 오류 발생시

  1. 완료

0개의 댓글

관련 채용 정보