[오늘가챠] 프로젝트 오버뷰: 왜 이 스택을 선택했는가?

2026. 7. 4. 14:51·◈ Yermi Project/오늘가챠🃏
728x90
반응형
'오늘가챠'는 유저가 찍은 평범한 일상 사진을 화려한 TCG(Trading Card Game) 카드로 만들어주는 서비스입니다.

단순한 이미지 업로드 게시판을 넘어서, 유저 간의 수집욕을 자극하고 실시간으로 카드를 뽑는 경험을 제공하는 것이 핵심 기획이었습니다. 이를 구현하기 위해 비용을 0원에 가깝게 유지하면서도 안정적이고 빠른 서비스를 제공할 수 있는 아키텍처 설계가 필요했습니다.

오늘가챠 시스템 아키텍처


1. 기획의 제약 사항과 인프라의 조건

1인 개발로 진행되는 사이드 프로젝트 특성상 다음과 같은 뚜렷한 제약 사항이 있었습니다.
  1. 무자본 (비용 최적화): AWS EC2, RDS, S3를 깡통으로 세팅하면 월 최소 수만 원의 고정 비용이 발생합니다. 트래픽이 보장되지 않은 상태에서 이는 큰 부담입니다.
  2. 개발 속도: 인프라 설정(Nginx, SSL 발급, 로드 밸런싱)에 리소스를 쏟기보다는, AI 프롬프트 엔지니어링이나 프론트엔드 UX 개선에 시간을 쏟아야 했습니다.
  3. 대량의 이미지 처리: TCG 게임 특성상 고화질 이미지가 넘쳐납니다. 이를 서버에서 직접 리사이징하고 서빙하면 백엔드가 뻗어버릴 것이 자명했습니다.

2. 각 레이어별 기술 스택 선정 이유

프론트엔드: Vercel (React + Vite)

  • Zero-config 배포: GitHub 리포지토리와 연결하면 main 브랜치 푸시만으로 빌드부터 배포, 캐시 무효화까지 자동화됩니다.
  • Edge Cache: 전 세계 CDN 네트워크에 정적 에셋이 자동 캐싱되어, 화려한 UI 자원들이 유저와 가장 가까운 엣지 노드에서 서빙됩니다. (초기 로딩 속도 극대화)
Vercel의 API 프록시 기능은 vercel.json 한 줄로 FE와 BE 간의 CORS 문제를 우아하게 해결해 줍니다.
{
  "buildCommand": "npm run build",
  "outputDirectory": "dist",
  "framework": "vite",
  "rewrites": [
    {
      "source": "/api/:path*",
      "destination": "https://<your-app>.onrender.com/api/:path*"
    }
  ]
}

백엔드: Render (Spring Boot + Docker)

  • IaaS 대신 PaaS: AWS EC2에 직접 서버 환경을 구축하는 대신, Render를 통해 Docker 컨테이너를 그대로 배포했습니다.
  • 자동화된 SSL 및 로드 밸런싱: Let's Encrypt 스크립트를 작성할 필요 없이, Render가 알아서 HTTPS 통신을 보장해 줍니다. 백엔드 개발자는 오직 비즈니스 로직에만 집중할 수 있습니다.

데이터베이스 & 인증: Supabase (PostgreSQL)

  • RDBMS의 필요성: NoSQL(Firebase)로는 유저, 카드, 인벤토리, 가챠 로그 등 복잡하게 얽힌 관계형 데이터를 무결성 있게 관리하기 어려웠습니다. Supabase는 강력한 PostgreSQL을 기반으로 합니다.
  • BaaS의 편의성: DB 서버 세팅 없이 GUI 툴을 제공하며, JWT 기반의 Auth(인증) 시스템이 내장되어 있어 로그인 구현 공수를 획기적으로 줄여주었습니다.
실제 프로젝트에서는 아래 DDL로 테이블을 관리합니다.
-- 핵심 테이블 구조 (schema.sql 발췌)
CREATE TABLE IF NOT EXISTS users (
    id          BIGSERIAL PRIMARY KEY,
    username    VARCHAR(50)  NOT NULL UNIQUE,
    nickname    VARCHAR(50),
    password    VARCHAR(255) NOT NULL,
    gold        INT          NOT NULL DEFAULT 0,
    gems        INT          NOT NULL DEFAULT 0,
    role        VARCHAR(10)  DEFAULT 'USER',
    created_at  TIMESTAMP    DEFAULT NOW()
);

CREATE TABLE IF NOT EXISTS photos (
    id            BIGSERIAL PRIMARY KEY,
    user_id       BIGINT       NOT NULL REFERENCES users(id),
    image_url     VARCHAR(500) NOT NULL,
    theme         VARCHAR(20),
    rarity        VARCHAR(1),
    cp            INT,
    status        VARCHAR(10)  NOT NULL DEFAULT 'DRAFT',
    ai_name       VARCHAR(100),
    ai_flavor     VARCHAR(500),
    created_at    TIMESTAMP    DEFAULT NOW()
);

CREATE TABLE IF NOT EXISTS cards (
    id          BIGSERIAL PRIMARY KEY,
    user_id     BIGINT    NOT NULL REFERENCES users(id),
    photo_id    BIGINT    NOT NULL REFERENCES photos(id),
    level       INT       NOT NULL DEFAULT 1,
    is_favorite BOOLEAN   NOT NULL DEFAULT false,
    created_at  TIMESTAMP DEFAULT NOW()
);

미디어 서버 (CDN): Cloudinary

  • On-the-fly 최적화: 프론트엔드에서 이미지를 요청할 때 URL에 파라미터(f_auto, q_auto)만 추가하면, Cloudinary 엣지 서버가 실시간으로 WebP 포맷으로 변환 및 리사이징하여 내려줍니다. 백엔드의 이미지 처리 부담을 0으로 만들었습니다.
실제 백엔드 업로드 클라이언트 코드에서도 자동 변환을 설정해 두었습니다.
// CloudinaryClient.java — 업로드 시 자동 최적화 적용
public String upload(byte[] imageBytes) throws IOException {
    Map<String, Object> result = cloudinary.uploader().upload(imageBytes, ObjectUtils.asMap(
        "folder", "<your-folder>",
        "transformation", new Transformation()
            .width(800).crop("scale")
            .quality("auto").fetchFormat("auto")
    ));
    return (String) result.get("secure_url");
}

3. 프로덕션 배포 인프라 요약

서비스 플랫폼 역할 비용
프론트엔드 Vercel 정적 호스팅
+ API 프록시
무료
백엔드 Render Spring Boot API
(Docker)
무료
DB Supabase PostgreSQL + Auth 무료
이미지 Cloudinary 이미지 업로드/CDN 무료 (25GB)
AI 분석 Gemini 사진
→ 카드 메타데이터 생성
무료 (RPM 제한)
모니터링 UptimeRobot /health 핑
(Cold Start 방지)
무료

4. 마무리

이렇게 6가지 모던 클라우드 서비스를 레고 블록처럼 조립하여, 엔터프라이즈급 퍼포먼스를 내면서도 유지보수 비용은 0원에 수렴하는 아키텍처를 완성했습니다. 다음 편에서는 프론트엔드와 백엔드의 무중단 배포 파이프라인 구축 과정을 상세히 알아보겠습니다.
728x90
반응형
'◈ Yermi Project/오늘가챠🃏' 카테고리의 다른 글
  • [오늘가챠] 생성형 AI의 도입: Gemini 2.0 Flash와 안전장치
  • [오늘가챠] 프론트-DB 직결 시대의 필수 보안: Supabase RLS 적용기
  • [오늘가챠] 서버리스 DB의 한계 극복: Supabase 커넥션 풀 고갈 해결
  • [오늘가챠] 비용 0원 무중단 배포 파이프라인 구축기 (Vercel + Render)
예르미(yermi)
예르미(yermi)
끊임없이 제 자신을 계발하는 개발자입니다👨🏻‍💻
  • 예르미(yermi)
    예르미의 코딩노트
    예르미(yermi)
  • 전체
    오늘
    어제
    • 분류 전체보기 (1024) N
      • ◎ Java (133)
        • Java☕ (93)
        • JSP📋 (26)
        • Applet🧳 (6)
        • Interview👨🏻‍🏫 (8)
      • ◎ JavaScript (48)
        • JavaScript🦎 (25)
        • jQuery🌊 (8)
        • React🌐 (2)
        • Vue.js🔰 (6)
        • Node.js🫒 (3)
        • Google App Script🐑 (4)
      • ◎ HTML5+CSS3 (17)
        • HTML5📝 (8)
        • CSS3🎨 (9)
      • ──────────── (0)
      • ▣ Framework (67)
        • Spring🍃 (36)
        • Spring Boot🍀 (12)
        • Bootstrap💜 (3)
        • Selenium🌕 (6)
        • MyBatis🐣 (10)
      • ▣ Tools (47)
        • API🎯 (18)
        • Library🎲 (15)
        • JitPack🚀 (3)
        • Jenkins👨🏻 (7)
        • Thymeleaf🌿 (4)
      • ▣ Server (30)
        • Apache Tomcat🐱 (14)
        • Apache HTTP Server🛡️ (1)
        • Nginx🧶 (7)
        • OracleXE💿 (4)
        • VisualSVN📡 (4)
      • ▣ Infra & DevOps (19) N
        • LGTM Stack🔭 (5)
        • Kafka🐦‍🔥 (0)
        • Kubernetes🚢 (8)
        • KubeCon Japan 2026⚓ (6) N
      • ▣ OS : 운영체제 (18)
        • cmd : 명령프롬프트💻 (10)
        • Linux🐧 (8)
      • ▣ SQL : Database (56)
        • Oracle SQL🏮 (26)
        • PL SQL💾 (9)
        • MySQL🐬 (6)
        • MariaDB🦦 (6)
        • H2 Database🔠 (3)
        • SQL 실전문제🐌 (6)
      • ────────── (0)
      • ◈ Human Project (86)
        • Mini : Library Service📚 (15)
        • 화면 설계 [HTML]🐯 (10)
        • 서버 프로그램 구현🦁 (15)
        • Team : 여수어때🛫 (19)
        • Custom : Student🏫 (9)
        • Custom : Board📖 (18)
      • ◈ Yermi Project (49)
        • 조사모아(Josa-moa)📬 (5)
        • Riddle-Game🧩 (6)
        • 맛있을 지도🍚 (2)
        • 어디 가! 박대리!🙋🏻‍♂️ (5)
        • 조크베어🐻‍❄️ (4)
        • Looks Like Thirty🦉 (2)
        • Toy Project💎 (12)
        • 오픈소스 파헤치기🪐 (5)
        • 오늘가챠🃏 (8)
      • ◈ Refactoring (15)
        • Mini : Library Service📚 (8)
        • 서버 프로그램 구현🦁 (1)
        • Team : 여수어때🛫 (0)
        • 쿼리 튜닝일지🔧 (6)
      • ◈ Coding Test (80)
        • 백준(BOJ)👨🏻‍💻 (71)
        • 프로그래머스😎 (2)
        • 코드트리🌳 (7)
      • ◈ Study (129)
        • 기초튼튼 개발지식🥔 (25)
        • HTTP 웹 지식💡 (4)
        • 클린코드(Clean Code)🩺 (1)
        • 디자인패턴(GoF)🥞 (12)
        • 알고리즘(Algorithm)🎡 (14)
        • 다이어그램(Diagram)📈 (4)
        • 파이썬(Python)🐍 (16)
        • 에러노트(Error Note)🧱 (34)
        • 웹 보안(Web Security)🔐 (11)
        • 인공지능 AI🛸 (8)
      • ◈ 공부모임 (57)
        • 혼공학습단⏰ (18)
        • 코드트리 챌린지👊🏻 (2)
        • 개발도서 100독👟 (8)
        • 나는 리뷰어다🌾 (17)
        • 국가기술자격 서포터즈🌻 (12)
      • ◈ 자격증 공부 (48)
        • 정보처리기사🔱 (16)
        • 정보처리산업기사🔅 (9)
        • 정보보안기사⚜️ (11)
        • 컴퓨터활용능력 1급📼 (12)
      • ─────────── (0)
      • ◐ 기타 (124)
        • 알아두면 좋은 팁(tip)✨ (46)
        • 개발자의 일상🎈 (55)
        • 개발도서 서평🔍 (10)
        • 개발관련 세미나🎤 (2)
        • 블로그 꾸미기🎀 (9)
        • 사도신경 프로젝트🎚️ (2)
  • 인기 글

  • 최근 댓글

  • 반응형
    250x250
  • 태그

    BOJ
    SQL
    javascript
    CSS
    일상
    spring
    jsp
    프로그래밍
    Oracle
    Project
    꿀팁
    spring boot
    Error Note
    코딩
    Database
    백준 티어
    코딩 테스트
    Java
    자바스크립트
    백준
  • hELLO· Designed By정상우.v4.10.3
예르미(yermi)
[오늘가챠] 프로젝트 오버뷰: 왜 이 스택을 선택했는가?
상단으로

티스토리툴바