๐Ÿš€ Vite + S3 + CloudFront ๋ฐฐํฌ ๊ฐ€์ด๋“œ

homewizยท2026๋…„ 3์›” 20์ผ

AWS

๋ชฉ๋ก ๋ณด๊ธฐ
4/4

๐Ÿ“Œ 1. ์ „์ฒด ๊ตฌ์กฐ

์ตœ์ข… ์•„ํ‚คํ…์ฒ˜:

[User]
  โ†“
CloudFront (Admin - HTTPS)
  โ†“
S3 (React SPA)

[User]
  โ†“
CloudFront (API - HTTPS)
  โ†“
EC2 (NestJS :3000)

๐Ÿ‘‰ ํ•ต์‹ฌ ๋ชฉํ‘œ

  • ํ”„๋ก ํŠธ: HTTPS ๋ฐฐํฌ (S3 + CloudFront)
  • ๋ฐฑ์—”๋“œ: HTTPS API ์ œ๊ณต (CloudFront โ†’ EC2)
  • ๋ฌธ์ œ ํ•ด๊ฒฐ: Mixed Content / CORS / ์บ์‹œ

๐Ÿ“ฆ 2. S3 ์ •์  ์›น ํ˜ธ์ŠคํŒ… ์„ค์ •

2-1. Static Hosting ํ™œ์„ฑํ™”

S3 โ†’ Bucket โ†’ Properties โ†’ Static website hosting โ†’ Enable

์„ค์ •:

Index document: index.html
Error document: index.html   (SPA ํ•„์ˆ˜)

๐Ÿ‘‰ React Router ์‚ฌ์šฉ ์‹œ ํ•„์ˆ˜


2-2. ํผ๋ธ”๋ฆญ ์ ‘๊ทผ ํ—ˆ์šฉ

Block Public Access ํ•ด์ œ

S3 โ†’ Permissions โ†’ Block public access โ†’ ์ „๋ถ€ ํ•ด์ œ

Bucket Policy ์ถ”๊ฐ€

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "PublicRead",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::๋ฒ„ํ‚ท๋ช…/*"
    }
  ]
}

2-3. ์ ‘์† ํ™•์ธ

http://๋ฒ„ํ‚ท๋ช….s3-website-๋ฆฌ์ „.amazonaws.com

โšก 3. CloudFront (Admin - ํ”„๋ก ํŠธ)

๋ชฉ์ 

  • HTTPS ์ œ๊ณต
  • SPA ๋ผ์šฐํŒ… ํ•ด๊ฒฐ
  • ์„ฑ๋Šฅ + ์บ์‹ฑ

3-1. Origin ์„ค์ •

Origin Domain: S3 website endpoint (์ค‘์š”)

์˜ˆ:

chain-wallet-host.s3-website-ap-northeast-1.amazonaws.com

3-2. ์ฃผ์š” ์„ค์ •

Viewer Protocol Policy: โœ” Redirect HTTP โ†’ HTTPS

Default Root Object: โœ” index.html

3-3. SPA ๋ผ์šฐํŒ… ์„ค์ •

CloudFront โ†’ Error Pages

403 โ†’ /index.html โ†’ 200
404 โ†’ /index.html โ†’ 200

๐Ÿ‘‰ ์ด๊ฑฐ ์•ˆ ํ•˜๋ฉด /dashboard ์ง์ ‘ ์ ‘์† ์‹œ 404


๐Ÿ”ฅ 4. Mixed Content ๋ฌธ์ œ

๋ฌธ์ œ ๊ตฌ์กฐ

CloudFront (HTTPS) โ†’ EC2 API (HTTP)

๐Ÿ‘‰ ๋ธŒ๋ผ์šฐ์ € ์ฐจ๋‹จ


๐ŸŒ 5. CloudFront (API์šฉ) ์ถ”๊ฐ€

๊ตฌ์„ฑ

CloudFront (API) โ†’ Origin: EC2 (IP:3000)

์„ค์ •

Origin:
โœ” Custom Origin
โœ” HTTP only
โœ” Port 3000

Behavior ์„ค์ •

Allowed Methods:
GET / POST / PUT / PATCH / DELETE / OPTIONS

Cache:
Disabled

Origin Request Policy:
AllViewer

๊ฒฐ๊ณผ

Allowed Methods:
GET / POST / PUT / PATCH / DELETE / OPTIONS

Cache:
Disabled

Origin Request Policy:
AllViewer

๐Ÿ‘‰ ์ด์ œ API๋„ HTTPS


๐Ÿ”— 6. ํ”„๋ก ํŠธ API ์—ฐ๊ฒฐ ๋ณ€๊ฒฝ

โŒ ๊ธฐ์กด (๋ฌธ์ œ)

https://xxxxx.cloudfront.net

โœ… ๋ณ€๊ฒฝ

VITE_API_BASE_URL=https://CloudFront_API_URL

โ— ์ค‘์š”

.env ๋ณ€๊ฒฝ ํ›„ ๋ฐ˜๋“œ์‹œ build + ์žฌ๋ฐฐํฌ

๐Ÿšจ 7. CORS ๋ฌธ์ œ ํ•ด๊ฒฐ

๋ฌธ์ œ ์›์ธ

ํ—ˆ์šฉ origin โ‰  ์‹ค์ œ ์š”์ฒญ origin

๋น ๋ฅธ ํ•ด๊ฒฐ

app.enableCors({
  origin: true,
  credentials: true,
});

๊ถŒ์žฅ (์šด์˜)

app.enableCors({
  origin: [
    'https://admin-cloudfront-url',
  ],
  credentials: true,
});

๐Ÿ’ฃ 8. ์บ์‹œ ๋ฌธ์ œ (๊ฐ€์žฅ ์ค‘์š”)

๋ฌธ์ œ

  • CloudFront๊ฐ€ index.html ์บ์‹ฑ
  • ์ตœ์‹  ์ฝ”๋“œ ๋ฐ˜์˜ ์•ˆ๋จ

ํ•ด๊ฒฐ 1๏ธโƒฃ CloudFront ์บ์‹œ ๋ฌดํšจํ™”

/*

ํ•ด๊ฒฐ 2๏ธโƒฃ S3 ์—…๋กœ๋“œ ์ „๋žต

index.html

aws s3 cp dist/index.html s3://๋ฒ„ํ‚ท/index.html \
  --cache-control "no-cache, no-store, must-revalidate"

assets (JS/CSS)

aws s3 cp dist/assets s3://๋ฒ„ํ‚ท/assets \
  --recursive \
  --cache-control "public, max-age=31536000, immutable"

โ— ์ค‘์š”

<meta http-equiv="Cache-Control">

๐Ÿ‘‰ ํšจ๊ณผ ์—†์Œ (CloudFront์—๋Š” ์˜ํ–ฅ ์—†์Œ)


โš™๏ธ 9. ๋ฐฐํฌ ์ž๋™ํ™” (์ถ”์ฒœ)

deploy.sh

set -e

BUCKET=๋ฒ„ํ‚ท๋ช…
DIST_ID=CloudFront_ID

aws s3 cp dist/assets s3://$BUCKET/assets \
  --recursive \
  --cache-control "public, max-age=31536000, immutable"

aws s3 cp dist/index.html s3://$BUCKET/index.html \
  --cache-control "no-cache, no-store, must-revalidate"

aws cloudfront create-invalidation \
  --distribution-id $DIST_ID \
  --paths "/*"

root/package.json

"deploy:admin": "pnpm build:admin && pnpm --filter @cws/admin deploy"

admin/package.json

"deploy": "sh deploy.sh"


๐Ÿง  10. ์ „์ฒด ํ๋ฆ„ (์ค‘์š” ๊ฐœ๋…)

์ด ๊ตฌ์กฐ๋Š” ์‹ค์ œ ๋ธ”๋ก์ฒด์ธ ์ž…์ถœ๊ธˆ ์‹œ์Šคํ…œ์˜ Admin UI ๋ฐฐํฌ ๊ตฌ์กฐ์™€ ๋™์ผํ•˜๋‹ค.

  • ํ”„๋ก ํŠธ๋Š” S3์—์„œ ์ •์  ํŒŒ์ผ ์ œ๊ณต
  • API๋Š” ๋ณ„๋„ ์„œ๋ฒ„์—์„œ ์ฒ˜๋ฆฌ
  • CloudFront๊ฐ€ HTTPS + ์บ์‹ฑ ๋‹ด๋‹น

์ด ํ๋ฆ„์€ ์‹œ์Šคํ…œ ์•„ํ‚คํ…์ฒ˜์—์„œ๋„ ๋™์ผํ•˜๊ฒŒ ๋ถ„๋ฆฌ๋˜์–ด ์„ค๊ณ„๋œ๋‹ค


๐Ÿ“Š 11. ๋ฌธ์ œ โ†’ ์›์ธ โ†’ ํ•ด๊ฒฐ ์š”์•ฝ

๋ฌธ์ œ์›์ธํ•ด๊ฒฐ
Mixed ContentHTTP APICloudFront(API)
CORSorigin mismatchorigin ์„ค์ •
์ฝ”๋“œ ๋ฏธ๋ฐ˜์˜index.html ์บ์‹œno-cache + invalidation

๐Ÿš€ 12. ๋‹ค์Œ ๋‹จ๊ณ„ (์ถ”์ฒœ)

1. CORS ๊ฐ•ํ™”

origin: CloudFront ๋„๋ฉ”์ธ๋งŒ ํ—ˆ์šฉ

2. CloudFront ํ†ตํ•ฉ (๊ณ ๊ธ‰)

/ โ†’ S3
/api โ†’ EC2

๐Ÿ‘‰ CORS ์ œ๊ฑฐ ๊ฐ€๋Šฅ


3. ๋„๋ฉ”์ธ ์—ฐ๊ฒฐ

admin.xxx.com
api.xxx.com

4. HTTPS ์™„์ „ ๊ตฌ์„ฑ

  • ACM ์ธ์ฆ์„œ
  • Route53 ์—ฐ๊ฒฐ

๐Ÿ”ฅ ํ•œ ์ค„ ์ •๋ฆฌ

S3 + CloudFront + CloudFront(API) ๊ตฌ์กฐ๋กœ
HTTPS ๊ธฐ๋ฐ˜ SPA + API ํ†ต์‹  ํ™˜๊ฒฝ ์™„์„ฑ

๐Ÿง  ํ•ต์‹ฌ ๊ตํ›ˆ

ํ”„๋ก ํŠธ ๋ฐฐํฌ ๋ฌธ์ œ์˜ 90%๋Š” ์บ์‹œ๋‹ค

0๊ฐœ์˜ ๋Œ“๊ธ€