AWS Amplify์—์„œ Next.js SSR ์•ฑ์ด ๊นจ์ง€๋Š” ์ด์œ  (๊ทธ๋ฆฌ๊ณ  ๋Ÿฐํƒ€์ž„ ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ํ•ด๊ฒฐ๋ฒ•)

Next.js App Router + SSR ์•ฑ์„ Vercel์—์„œ AWS Amplify๋กœ ์ด์ „ํ•  ๋•Œ, ๊ฒ‰์œผ๋กœ ๋ณด๊ธฐ์—๋Š” ๋ชจ๋“  ๊ฒŒ ์ •์ƒ์ฒ˜๋Ÿผ ๋ณด์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ๋นŒ๋“œ๋Š” ์„ฑ๊ณตํ•˜๊ณ 
  • ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋„ ์„ค์ •๋˜์–ด ์žˆ๊ณ 
  • IAM ๊ถŒํ•œ๋„ ๋‹ค ๋งž์ถฐ๋†จ๋Š”๋ฐ

๋ง‰์ƒ ๋ฐฐํฌํ•˜๊ณ  ๋‚˜๋ฉด ์•ฑ์ด ๋Ÿฐํƒ€์ž„์—์„œ 500 ์—๋Ÿฌ์™€ ํ•จ๊ป˜ ์ฃฝ์Šต๋‹ˆ๋‹ค. ๋กœ๊ทธ๋ฅผ ๋ณด๋ฉด ํ•ญ์ƒ ๊ฐ™์€ ๋ฉ”์‹œ์ง€์ฃ .

โ€œํ™˜๊ฒฝ ๋ณ€์ˆ˜๊ฐ€ ์—†์Šต๋‹ˆ๋‹คโ€

์ €๋„ Cognito + API Gateway + Lambda + RDS๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์‹ค์ œ ํ”„๋กœ๋•์…˜ ์•ฑ์„ ์˜ฎ๊ธฐ๋ฉด์„œ ์ด ๋ฌธ์ œ๋ฅผ ๊ทธ๋Œ€๋กœ ๊ฒช์—ˆ์Šต๋‹ˆ๋‹ค.

์ด ๊ธ€์—์„œ๋Š”:

  • ์™œ ์ด๋Ÿฐ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š”์ง€
  • Amplify์—์„œ ์‹ค์ œ๋กœ ๋™์ž‘ํ•˜๋Š” ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์€ ๋ฌด์—‡์ธ์ง€

๋ฅผ ์ •๋ฆฌํ•ฉ๋‹ˆ๋‹ค.


๊ทผ๋ณธ ์›์ธ: Amplify์˜ ๋นŒ๋“œ ํƒ€์ž„ vs ๋Ÿฐํƒ€์ž„ ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ์ฐจ์ด

AWS Amplify Web Compute(SSR) ์—์„œ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋Š” Vercel๊ณผ ๋™์ž‘ ๋ฐฉ์‹์ด ๋‹ค๋ฆ…๋‹ˆ๋‹ค.

Vercel์—์„œ๋Š” ์ž˜ ๋˜๋Š” ์ด์œ 

Vercel์—์„œ๋Š” ํ™˜๊ฒฝ ๋ณ€์ˆ˜๊ฐ€:

  • ๋นŒ๋“œ ํƒ€์ž„
  • ๋Ÿฐํƒ€์ž„ (SSR, route handler, server component)

๋ชจ๋‘์—์„œ ์ž๋™์œผ๋กœ ์ฃผ์ž…๋ฉ๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ์–ด๋””์„œ๋“ :

process.env.MY_VAR

๊ฐ€ โ€œ๊ทธ๋ƒฅโ€ ์ž˜ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.


Amplify์—์„œ๋Š” ๋ฌด์Šจ ์ผ์ด ๋ฒŒ์–ด์งˆ๊นŒ?

Amplify๋Š” ๋‹ค๋ฆ…๋‹ˆ๋‹ค.

  • ๋นŒ๋“œ ํƒ€์ž„์—๋Š” ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์ฃผ์ž…ํ•ด ์ค๋‹ˆ๋‹ค
  • ํ•˜์ง€๋งŒ SSR ๋Ÿฐํƒ€์ž„(Compute ํ™˜๊ฒฝ) ์—๋Š” ์ž๋™์œผ๋กœ ์ „๋‹ฌ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค

๊ฒฐ๊ณผ์ ์œผ๋กœ:

  • โœ… ๋นŒ๋“œ๋Š” ์„ฑ๊ณต
  • โŒ SSR ๋Ÿฐํƒ€์ž„์—์„œ ํฌ๋ž˜์‹œ
  • โŒ route handler์—์„œ process.env.MY_VAR === undefined

์ด ํ˜„์ƒ์€ ๋ฒ„๊ทธ๊ฐ€ ์•„๋‹ˆ๋ผ ์„ค๊ณ„๋œ ๋™์ž‘์ž…๋‹ˆ๋‹ค.

AWS ๋ฌธ์„œ์—๋„ ๋‚˜์˜ค์ง€๋งŒ, Vercel์— ์ต์ˆ™ํ•˜๋ฉด ๊ฑฐ์˜ 100% ๋†“์น˜๊ฒŒ ๋˜๋Š” ํฌ์ธํŠธ์ž…๋‹ˆ๋‹ค.


ํ”ํžˆ ๋ณด์ด๋Š” ์ฆ์ƒ๋“ค

๋Œ€๋ถ€๋ถ„ ์•„๋ž˜์™€ ๊ฐ™์ด ๋‚˜ํƒ€๋‚ฉ๋‹ˆ๋‹ค.

  • ๋ชจ๋“  ํŽ˜์ด์ง€์—์„œ 500 ์—๋Ÿฌ

  • ๋กœ๊ทธ์—:

    • ํ™˜๊ฒฝ ๋ณ€์ˆ˜๊ฐ€ ํ•œ๊บผ๋ฒˆ์— ์ „๋ถ€ ์—†์Œ
    • ๋˜๋Š” AWS SDK ํ˜ธ์ถœ ์‹œ CredentialsProviderError
  • ๋กœ์ปฌ๊ณผ Vercel์—์„œ๋Š” ์ •์ƒ

  • Amplify์—์„œ๋งŒ ์‹คํŒจ


์ œ๋Œ€๋กœ ๋™์ž‘ํ•˜๋Š” ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

1๏ธโƒฃ ๋น„๋ฐ€ ๊ฐ’์€ AWS Secrets Manager๋กœ ์ด๋™

Cognito client secret ๊ฐ™์€ ๋ฏผ๊ฐํ•œ ๊ฐ’์€:

  • AWS Secrets Manager์— ์ €์žฅ
  • Amplify์˜ Compute role์— ์•„๋ž˜ ๊ถŒํ•œ ๋ถ€์—ฌ:
secretsmanager:GetSecretValue

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ๋Ÿฐํƒ€์ž„ ํ™˜๊ฒฝ ๋ณ€์ˆ˜ ์ฃผ์ž…์— ์˜์กดํ•˜์ง€ ์•Š์•„๋„ ๋ฉ๋‹ˆ๋‹ค.


2๏ธโƒฃ ๋Ÿฐํƒ€์ž„ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ๋นŒ๋“œ ์‹œ์ ์— ๊ตฝ๊ธฐ(bake)

API URL, redirect URI ๊ฐ™์€ ๋น„๋ฐ€์ด ์•„๋‹Œ ๊ฐ’์€ Amplify ๊ถŒ์žฅ ๋ฐฉ์‹์ด ๋”ฐ๋กœ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ‘‰ ๋นŒ๋“œ ์ค‘์— .env.production ํŒŒ์ผ์„ ์ง์ ‘ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.

amplify.yml ์˜ˆ์‹œ:

build:
  commands:
    - env | grep '^COGNITO_' >> .env.production
    - env | grep '^REPORTS_API_BASE_URL' >> .env.production
    - pnpm build

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด:

  • Amplify์˜ ๋นŒ๋“œ ํ™˜๊ฒฝ
  • Next.js SSR ๋Ÿฐํƒ€์ž„ ๊ธฐ๋Œ€์น˜

์‚ฌ์ด์˜ ๊ฐ„๊ทน์„ ๋ฉ”์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.


3๏ธโƒฃ ์„œ๋ฒ„ ์‚ฌ์ด๋“œ ์„ค์ • ์ฝ”๋“œ ์ ๊ฒ€ (์ค‘์š”)

Secrets Manager๋กœ ์˜ฎ๊ธด ๋’ค์—๋Š” ์„œ๋ฒ„ ์ฝ”๋“œ์—์„œ NEXT_PUBLIC_*๋ฅผ ์ฐธ์กฐํ•˜๋ฉด ์•ˆ ๋ฉ๋‹ˆ๋‹ค.

โŒ Amplify์—์„œ ๊นจ์ง€๋Š” ํŒจํ„ด:

process.env.NEXT_PUBLIC_SOMETHING

โœ… ์˜ฌ๋ฐ”๋ฅธ ํŒจํ„ด:

process.env.SOMETHING

์ •๋ฆฌํ•˜๋ฉด:

  • NEXT_PUBLIC_* โ†’ ๋ธŒ๋ผ์šฐ์ € / ํด๋ผ์ด์–ธํŠธ ์ „์šฉ

  • ์„œ๋ฒ„์—์„œ๋Š”:

    • ๋น„๋ฐ€ ๊ฐ’ โ†’ Secrets Manager
    • ์ผ๋ฐ˜ ๊ฐ’ โ†’ .env.production์œผ๋กœ ์ฃผ์ž…๋œ env

์™œ Amplify์—์„œ๋งŒ ๊นจ์งˆ๊นŒ?

  • Vercel์€ SSR ๋Ÿฐํƒ€์ž„์— env vars๋ฅผ ์ž๋™ ์ฃผ์ž…

  • Amplify๋Š”:

    • ๋นŒ๋“œ ํ™˜๊ฒฝ
    • ์ปดํ“จํŠธ ๋Ÿฐํƒ€์ž„

์„ ๋ช…ํ™•ํžˆ ๋ถ„๋ฆฌํ•จ

  • Next.js๋Š” ๋Ÿฐํƒ€์ž„ env๊ฐ€ ์žˆ๋‹ค๊ณ  ๊ฐ€์ •
  • Amplify์—์„œ๋Š” ๊ทธ ์—ฐ๊ฒฐ์„ ์ง์ ‘ ๋งŒ๋“ค์–ด์ค˜์•ผ ํ•จ

์ด๊ฑธ ์•Œ๊ณ  ๋‚˜๋ฉด, ํ•ด๊ฒฐ ์ž์ฒด๋Š” ์–ด๋ ต์ง€ ์•Š์Šต๋‹ˆ๋‹ค.


TL;DR

Amplify์—์„œ Next.js SSR ์•ฑ์ด ๊นจ์ง„๋‹ค๋ฉด:

  1. ๋น„๋ฐ€ ๊ฐ’ โ†’ AWS Secrets Manager
  2. ๋Ÿฐํƒ€์ž„ env โ†’ ๋นŒ๋“œ ์ค‘ .env.production์— ๊ธฐ๋ก
  3. ์„œ๋ฒ„ ์ฝ”๋“œ์—์„œ NEXT_PUBLIC_* ์‚ฌ์šฉ ๊ธˆ์ง€
  4. Logging role ๋ง๊ณ  Compute role ๊ถŒํ•œ ํ™•์ธ

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด Amplify SSR๋„ ์•ˆ์ •์ ์œผ๋กœ ๋™์ž‘ํ•ฉ๋‹ˆ๋‹ค.

์•„๋ž˜๋Š” ์˜๋ฏธ๋ฅผ ์ •ํ™•ํžˆ ์œ ์ง€ํ•œ ํ•œ๊ธ€ ๋ฒˆ์—ญ์ด์•ผ. ๊ฒฝ๊ณ ์„ฑ์€ ์‚ด๋ฆฌ๊ณ , ๊ธฐ์ˆ  ๋ฌธ์„œ ํ†ค์œผ๋กœ ์ •๋ฆฌํ–ˆ์–ด.


IAM Role ๊ด€๋ จ ์ฃผ์˜์‚ฌํ•ญ (๋†“์น˜๊ธฐ ์‰ฌ์šด ํฌ์ธํŠธ)

AWS Amplify๋Š” ์„œ๋กœ ๋‹ค๋ฅธ ๋‘ ๊ฐœ์˜ IAM Role์„ ์‚ฌ์šฉํ•˜๋ฉฐ, ์ด ๋‘˜์„ ํ˜ผ๋™ํ•˜๋ฉด SSR ์•ฑ์ด ์กฐ์šฉํžˆ(silent) ๊นจ์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • Service role

    • Amplify ์ž์ฒด๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” ์—ญํ• 
    • ๋นŒ๋“œ, ๋ฐฐํฌ, ๋กœ๊ทธ ์ˆ˜์ง‘ ์šฉ๋„
    • ์•ฑ ์„œ๋ฒ„ ์ฝ”๋“œ์—๋Š” ์‚ฌ์šฉ๋˜์ง€ ์•Š์Œ
  • Compute role

    • Next.js SSR ๋Ÿฐํƒ€์ž„์—์„œ ์„œ๋ฒ„ ์ฝ”๋“œ๊ฐ€ ์‹คํ–‰๋  ๋•Œ Assume ๋˜๋Š” ์—ญํ• 

๋Ÿฐํƒ€์ž„์—์„œ AWS ์„œ๋น„์Šค(์˜ˆ: Secrets Manager)์— ์ ‘๊ทผํ•˜๋ ค๋ฉด ๋ฐ˜๋“œ์‹œ Compute role์„ ์•ฑ์— ์ง€์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ด๋ฅผ ์„ค์ •ํ•˜์ง€ ์•Š์œผ๋ฉด:

  • SSR ๋Ÿฐํƒ€์ž„์—๋Š” AWS ์ž๊ฒฉ ์ฆ๋ช…์ด ์ „ํ˜€ ์—†๊ณ 
  • ๊ทธ ๊ฒฐ๊ณผ CredentialsProviderError ๊ฐ™์€ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

Compute role์—๋Š” ์„œ๋ฒ„ ์ฝ”๋“œ์— ์‹ค์ œ๋กœ ํ•„์š”ํ•œ ์ตœ์†Œ ๊ถŒํ•œ๋งŒ ๋ถ€์—ฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค (์˜ˆ: secretsmanager:GetSecretValue).

์ด ์—ญํ• ์€ ๋กœ๊ทธ/๋นŒ๋“œ์šฉ Service role๊ณผ ์™„์ „ํžˆ ๋ณ„๊ฐœ์ด๋ฉฐ, Amplify ์ฝ˜์†”์—์„œ ๋ช…์‹œ์ ์œผ๋กœ ์„ค์ •ํ•ด์•ผ๋งŒ ์ ์šฉ๋ฉ๋‹ˆ๋‹ค.