콘텐츠로 이동

인프라 아키텍처

👋 이 문서는 d-edu 인프라의 "전체 지도"입니다. 처음 합류하셨다면 여기서 "어디서 뭐가 돌고, 코드가 어떻게 서버까지 가는지"를 한눈에 파악할 수 있습니다.

한 줄 요약 — 하이브리드 구성: - Dev 백엔드 = 🏠 온프레미스(우리 사무실 서버) · apidev.d-edu.site - Dev 프론트 = ▲ Vercel · dev.d-edu.site - Prod(운영) = ☁️ AWS Lightsail · d-edu.site / api.d-edu.site - 코드 = 📦 모노레포 idealstudy/mvp-mono (백+프+wiki 한 트리)

⚠️ 비밀번호·키·IP 같은 시크릿 값은 이 문서에 없습니다 — GitHub Secrets와 raw/(REDACTED)에만. 여긴 "구조"만.


0. 한눈에 (TL;DR)

구분 Dev (개발) Prod (운영)
백엔드 🏠 온프레미스 서버 (Docker) ☁️ AWS Lightsail
프론트 ▲ Vercel ☁️ AWS Lightsail (nginx)
DB 온프레 mysql_dev (MySQL 8.4) Lightsail MySQL
백엔드 도메인 apidev.d-edu.site api.d-edu.site
프론트 도메인 dev.d-edu.site d-edu.site
배포 트리거 develop 브랜치 머지 main 브랜치 머지

2026-05~06에 Dev를 AWS에서 온프레미스로 이전했습니다. 그 이유·과정은 ADR-0017, 옛 AWS Dev 구성은 아래 §7 이전 이력에 보존돼 있습니다.


1. 토폴로지 (그림)

flowchart TB
  subgraph REPO["📦 idealstudy/mvp-mono (private 모노레포)"]
    BE["mvp-back/ · Spring Boot"]
    FE["mvp-front/ · Next.js"]
  end

  BE -- "develop 머지<br/>(back-deploy-onprem)" --> APP
  BE -. "main 머지<br/>(back-deploy-aws)" .-> PROD
  FE -- "develop 머지<br/>front-sync-mirror<br/>(subtree split→push)" --> TEP["the-edu-project<br/>(public 미러)"]
  TEP -- "Vercel 자동 빌드" --> VER

  subgraph ONP["🏠 온프레미스 서버 — cloudflared 터널 · docker net: theedu_backend"]
    APP["the-edu-staging<br/>(Spring · GHCR 이미지)"]
    DB[("mysql_dev")]
    RD[("theedu_redis")]
    APP --- DB
    APP --- RD
  end

  VER["▲ Vercel · dev.d-edu.site"] -- "API 요청 (BFF 프록시)" --> APIDEV(["apidev.d-edu.site<br/>= Cloudflare 터널"])
  APIDEV --> APP
  APP -- "미디어 presigned URL" --> S3[("☁️ AWS S3 · theedu")]

  PROD["☁️ AWS Lightsail · api.d-edu.site (운영)"]

읽는 법: 개발자는 mvp-mono에 PR → develop 머지. 그 순간 백엔드는 온프레 서버로, 프론트는 the-edu-project 미러를 거쳐 Vercel로 자동 배포됩니다. 사용자가 dev.d-edu.site에서 보는 화면(Vercel)은 API를 apidev.d-edu.site(온프레 백엔드)로 보냅니다. (운영은 main 머지 → AWS.)


2. 구성 자원

2-1. Dev — 온프레미스 (Docker)

사무실 서버 1대 위에 Docker 컨테이너로 구성. 외부 접속은 Cloudflare 터널로 뚫습니다(서버에 공인 IP/포트 개방 없이 안전하게).

컨테이너 / 자원 역할 비고
the-edu-staging 백엔드 Spring 앱 GHCR 이미지, staging 프로파일, 포트 8080
mysql_dev MySQL 8.4 (DB명 dedu) ~/mysql_dev의 docker-compose, 데이터=도커 볼륨
theedu_redis Redis (세션·인증코드) ~/redis_dev의 docker-compose
docker network theedu_backend 세 컨테이너 내부 통신망 external 네트워크 (⚠️ §6 참고)
self-hosted GitHub Actions runner 온프레 배포 실행기 ~/actions-runner
cloudflared 터널 외부→서버 접속 통로 apidev.d-edu.site, ssh.d-edu.site

용어: cloudflared 터널 = 서버가 Cloudflare로 바깥 연결을 걸어두고, 외부 요청을 그 연결로 받아오는 방식. 방화벽에 포트를 안 열어도 돼 안전합니다.

2-2. Dev 프론트 — Vercel

  • Vercel 프로젝트 "the-edu-front-dev"(Production 환경)가 dev.d-edu.site로 서비스.
  • Vercel이 보는 소스 = idealstudy/the-edu-project(public). 모노레포가 이 레포로 동기화해주면 Vercel이 자동 빌드/배포.

2-3. Prod — AWS Lightsail (이전과 무관, 유지)

  • Lightsail 인스턴스 + Lightsail/RDS MySQL. nginx + certbot(HTTPS). api.d-edu.site / d-edu.site.

2-4. 공용 — AWS S3 theedu

  • 미디어(과제·QnA·게시판 썸네일) 저장. Dev(온프레)도 운영도 이 S3를 씁니다 → presigned URL 발급에 AWS 키 필요. 삭제 금지.

3. 배포 파이프라인 (코드가 서버로 가는 길)

대상 워크플로 트리거 흐름
Dev 백엔드 back-deploy-onprem.yml develop 머지 + mvp-back/** 변경 self-hosted runner가 빌드 → GHCR push → 온프레서 docker run the-edu-staging헬스 게이트(응답 확인, 실패 시 롤백)
Prod 백엔드 back-deploy-aws.yml (deploy-prod) main 머지 AWS Lightsail 배포 (ECR 경유)
Dev 프론트 front-sync-mirror.yml develop 머지 + mvp-front/** 변경 git subtree splitmvp-front/만 떼어내 → SSH(deploy key)로 the-edu-project에 force push → Vercel 자동 배포

용어: subtree split = 모노레포에서 mvp-front/ 폴더만 깨끗한 별도 히스토리로 뽑아내는 git 기능. 그걸 public 미러(the-edu-project)에 올려 Vercel이 빌드하게 합니다(private 모노레포를 Vercel에 직접 안 붙여도 됨).


4. 도메인 · 네트워크 (요청이 어디로 가나)

도메인 가리키는 곳 경유
dev.d-edu.site Dev 프론트 (Vercel)
apidev.d-edu.site Dev 백엔드 (온프레) Cloudflare 터널 → 온프레 서버
api.d-edu.site Prod 백엔드 AWS
d-edu.site Prod 프론트 AWS
  • 쿠키/CORS: 프론트(dev.d-edu.site) ↔ API(apidev.d-edu.site)가 형제 서브도메인이라, 로그인 쿠키 도메인은 .d-edu.site(둘 다 커버) + SameSite=None; Secure. CORS 허용 origin에 dev.d-edu.site 포함.
  • 프론트는 dev.d-edu.site로 접속해야 로그인 쿠키가 붙습니다(raw *.vercel.app 직접 접속 시 안 걸림).

5. 환경 · 프로파일 · 시크릿

  • Spring 프로파일: dev(구 AWS, 폐기 예정) · staging(온프레 Dev) · prod(AWS 운영). 온프레 백엔드는 staging 프로파일로 기동.
  • GitHub Environments: dev / staging / prod 별로 시크릿 분리. 온프레 배포는 staging 환경 시크릿(DB_URL=mysql_dev, REDIS_*, KAKAO/NAVER_REDIRECT_URI=apidev… 등) + repo 공통 시크릿(AWS_*, KAKAO_CLIENT_* 등) 사용.
  • 자세한 환경 매트릭스·변수명 → teams/engineering/infra/environments. 값은 Secrets/raw에만.

6. 알려진 리스크 · TODO

온프레 이전 과정에서 드러난, 앞으로 챙겨야 할 것들 (ADR-0017 §Consequences):

  1. theedu_backend 네트워크 단일 소유자 부재 — 앱은 docker run, mysql/redis는 compose라 네트워크 주인이 없음. 재생성 시 컨테이너 간 통신이 끊긴 적 있음(장애 1회). → 최상위 compose로 일원화 권장.
  2. 온프레 MySQL 자동 백업 없음 — 데이터가 도커 볼륨 1곳에만. → 정기 mysqldump + off-box(S3) 백업 필요.
  3. 모니터링·알림 부재 — apidev 다운 시 인지 불가. → Prometheus/Loki/Grafana 재구축 (teams/engineering/infra/observability).
  4. deploy 롤백 로직 — 인프라 문제 시 이전 이미지 롤백도 무의미. 헬스 실패 시 알림+중단이 나음.
  5. AWS back-deploy-aws.yml의 deploy-dev job 잔존 — dev EC2 삭제로 develop 머지 시 실패. 비활성화 필요.

7. 이전 이력 — 구 AWS Dev (~2026-05, 보존)

📌 아래는 이전 전(AWS) Dev 구성입니다. 2026-05~06 온프레미스로 이전하며 EC2/RDS는 삭제(스냅샷 dev-onpremise-260531 보관)했지만, 기록 보존을 위해 남깁니다. 의사결정 맥락은 ADR-0017.

항목 구 AWS Dev (삭제됨)
컴퓨팅 EC2 프리티어 인스턴스
DB RDS MySQL the_edu
이미지 레지스트리 ECR (theedu/back)
백엔드 도메인 api.dev.d-edu.site (nginx + certbot HTTPS)
배포 deploy.yml deploy-dev → SSH로 EC2 docker 교체
  • React 빌드물을 nginx 정적 서빙, certbot(Let's Encrypt)으로 HTTPS — 이 방식은 운영(Lightsail)엔 그대로 유효.
  • 데이터는 RDS the_edu → 온프레 mysql_devmysqldump 마이그레이션 완료(member 266·study_room 416).

8. 관련