Razzle: RFC: process.env.RAZZLE_RUNTIME_XXXX

์— ๋งŒ๋“  2018๋…„ 03์›” 08์ผ  ยท  27์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: jaredpalmer/razzle

ํ˜„์žฌ ํ–‰๋™

์‚ฌ๋žŒ๋“ค์€ Razzle์ด .env ๋ณ€์ˆ˜๋ฅผ ์–ด๋–ป๊ฒŒ ๋‹ค๋ฃจ๋Š”์ง€(์ฆ‰, webpack์— ์˜ํ•ด _build_ ์‹œ๊ฐ„์— ๋ฌธ์ž์—ดํ™”) create-react-app์ฒ˜๋Ÿผ ์–ด๋ ค์›€์„ ๊ฒช์Šต๋‹ˆ๋‹ค.

์˜ˆ์ƒ๋˜๋Š” ๋™์ž‘

Razzle์—๋Š” ๋Ÿฐํƒ€์ž„ ๋ณ€์ˆ˜๋ฅผ ์กด์ค‘ํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ์žˆ์–ด์•ผ ์‚ฌ์šฉ์ž๊ฐ€ Now/Heroku/Azure ๋“ฑ์— ์•ฑ์„ ๋” ์‰ฝ๊ฒŒ ๋ฐฐํฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ œ์•ˆ๋œ ์†”๋ฃจ์…˜

PORT , HOST ๋ฐ RAZZLE_RUNTIME_XXXXXXX ์ ‘๋‘์‚ฌ๊ฐ€ ๋ถ™์€ ๊ธฐํƒ€ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ๋Ÿฐํƒ€์ž„ ์ค‘์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

์ „์—

์ปดํŒŒ์ผ ์‹œ๊ฐ„์— ์‚ฌ์šฉ ๊ฐ€๋Šฅ(์ฆ‰, ์›นํŒฉ์— ์˜ํ•ด ๋ฌธ์ž์—ดํ™”๋จ)

  • RAZZLE_XXXXXX
  • PORT
  • HOST

ํ›„์—

๋Ÿฐํƒ€์ž„์— ์‚ฌ์šฉ ๊ฐ€๋Šฅ

  • PORT
  • HOST
  • RAZZLE_RUNTIME_XXXXXXX

์ปดํŒŒ์ผ ์‹œ๊ฐ„์— ์‚ฌ์šฉ ๊ฐ€๋Šฅ(์ฆ‰, ์›นํŒฉ์— ์˜ํ•ด ๋ฌธ์ž์—ดํ™”๋จ)

  • RAZZLE_XXXXXX

๋…ผ์˜

๋˜ ๋‹ค๋ฅธ ๋Œ€์•ˆ์€ razzle-heroku ํ”Œ๋Ÿฌ๊ทธ์ธ ๊ณผ ๊ฐ™์ด RAZZLE_XXXX ์ ‘๋‘์‚ฌ๊ฐ€ ๋ถ™์€ ๋ณ€์ˆ˜๋ฅผ _only_ ๋ฌธ์ž์—ดํ™”ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๋˜ํ•œ ์ด์ „ ๋ฒ„์ „๊ณผ๋„ ํ˜ธํ™˜๋ฉ๋‹ˆ๋‹ค. ํ•œํŽธ์œผ๋กœ ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด Heroku๊ฐ€ ๊ตฌ์„ฑ ํ™˜๊ฒฝ ๋ณ€์ˆ˜(์˜ˆ: MONGO_URI )์˜ ์ด๋ฆ„์„ ์ง€์ •ํ•˜๋Š” ์ž‘์—…์„ ๋” ์‰ฝ๊ฒŒ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฐ˜๋ฉด์—,์ด ์‹ค์ˆ˜๋กœ ์—‰๋ง์œผ๋กœ ์‰ฝ๊ฒŒ _too_ ๊ฒƒ (์ฆ‰์ด๋‹ค ๊ณต์œ  ๋™ํ˜• ์ฝ”๋“œ ๋‚ด ๋Ÿฐํƒ€์ž„ ๋ณ€์ˆ˜๋ฅผ ์ฐธ์กฐ undefined ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ์„ ํญ๋ฐœ ... ํด๋ผ์ด์–ธํŠธ).

๊ด€๋ จ๋œ

527 #526 #514 #477 #356 #285

discussion

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

@jaredpalmer ๋‚ด๊ฐ€ ๋†“์นœ ๊ฒƒ์ด ์žˆ์„ ์ˆ˜ ์žˆ์ง€๋งŒ readme ๋ฌธ์„œ๊ฐ€ ์˜๋ฏธํ•˜๋Š” ๋ฐ”์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  ์ด๊ฒƒ์€ ์—ฌ์ „ํžˆ โ€‹โ€‹PORT์™€ ๊ฐ™์€ ๋ฌธ์ œ์— ๋Œ€ํ•œ ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค. process.env.MY_THING ๋Š” ์ž˜ ์ž‘๋™ํ•˜์ง€๋งŒ process.env.PORT ๋Š” ์—ฌ์ „ํžˆ ๋นŒ๋“œ ์‹œ ๋Œ€์ฒด๋˜๋ฉฐ ๋Ÿฐํƒ€์ž„ ์‹œ ์ฝ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ Heroku ์˜ˆ์ œ๋Š” ์‹ค์ œ๋กœ ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ด ์Šค๋ ˆ๋“œ์—์„œ ๋…ผ์˜๋œ PORT, HOST ๋“ฑ์˜ ํŠน๋ณ„ํ•œ ์ฒ˜๋ฆฌ๋Š” ๋ณด์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค.

๋ชจ๋“  27 ๋Œ“๊ธ€

๋‚˜๋Š” ๊ฐœ์ธ์ ์œผ๋กœ ํด๋ผ์ด์–ธํŠธ์—์„œ process.env๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋Š” ๊ฒƒ์— ๋Œ€ํ•ด ๋„ˆ๋ฌด ๊ฑฑ์ •ํ•˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ์ด๋ฏธ ์„œ๋ฒ„์—์„œ '์ฐฝ'์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” process.env๊ฐ€ ๋ฐ˜๋Œ€ ํ–‰๋™์„ ํ•  ๊ฒƒ์ด๋ผ๋Š” ๊ฒƒ์ด ์ดํ•ด๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. (env๋ฅผ ๊ฐ€์งˆ ๋…ธ๋“œ ํ”„๋กœ์„ธ์Šค๊ฐ€ ์—†์œผ๋ฉฐ ๋ธŒ๋ผ์šฐ์ €๋Š” ๋‚ด๊ฐ€ ์•Œ๊ณ  ์žˆ๋Š” env ๋ณ€์ˆ˜๋ฅผ ๋…ธ์ถœํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.) ์ €๋Š” process.env๋ฅผ ์„œ๋ฒ„ ๋น„๋ฐ€์ด ๋๋‚  ์ˆ˜ ์žˆ๋Š” ์žฅ์†Œ๋ผ๊ณ  ์ƒ๊ฐํ•˜๋ฏ€๋กœ ์ฐจ๋ผ๋ฆฌ ๊ธฐ๋ณธ์ ์œผ๋กœ ํด๋ผ์ด์–ธํŠธ ์ธก์—์„œ๋Š” ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

๋‚˜์—๊ฒŒ ๋‹ฌ๋ ค ์žˆ๋‹ค๋ฉด process.env.RAZZLE_INLINED_XXXXXX ๋ณ€์ˆ˜๋Š” ๋นŒ๋“œ ์ค‘์— ์ปดํŒŒ์ผ๋˜๊ณ (ํด๋ผ์ด์–ธํŠธ์—์„œ ์ธ๋ผ์ธ DefinePlugin'd ๋ฌธ์ž์—ด๋กœ ์‚ฌ์šฉ ๊ฐ€๋Šฅ) ๋‹ค๋ฅธ ๋ชจ๋“  ๋ณ€์ˆ˜๋Š” ์„œ๋ฒ„ ์ธก์—์„œ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

NODE_ENV๋„ ์ธ๋ผ์ธ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋Œ€๋ถ€๋ถ„ ๋นŒ๋“œ์— ๋Œ€ํ•œ ์„ค๋ช…์œผ๋กœ ์‚ฌ์šฉ๋˜๋ฉฐ ์ฝ”๋“œ๊ฐ€ ์‹คํ–‰๋˜๋Š” ํ™˜๊ฒฝ๊ณผ ๊ฐ™์€ ๋ณ€์ˆ˜๊ฐ€ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ทธ๋ ‡๊ฒŒ ํ•ด์•ผ ํ•˜๋Š” ๋ช‡ ๊ฐ€์ง€ ์„ฑ๋Šฅ์ƒ์˜ ์ด์œ ๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š” PORT์™€ HOST๊ฐ€ ๋Ÿฐํƒ€์ž„์— ๊ฐ€๋ณ€์ ์ด๋ผ๋Š” ์•„์ด๋””์–ด๋ฅผ ์ข‹์•„ํ•ฉ๋‹ˆ๋‹ค. ๋‹ค๋ฅธ ํ™˜๊ฒฝ์—์„œ ๋™์ผํ•œ ๋นŒ๋“œ ์•„ํ‹ฐํŒฉํŠธ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š” ํˆฌ์Ÿ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ˜„์žฌ ๋™์ž‘์€ ๋‚ด๊ฐ€ ์˜ˆ์ƒํ•œ ๊ฒƒ๊ณผ ๋‹ฌ๋ž๊ณ  ํŠนํžˆ aws์—์„œ up ๋ฐฐํฌํ•  ๋•Œ ๊ฑธ๋ ค ๋„˜์–ด์กŒ์Šต๋‹ˆ๋‹ค. ์ด์ œ razzle.config.js ์‚ฌ์šฉ์ž ์ง€์ •ํ•˜์—ฌ ๋ชจ๋“  razzle ํŠน์ • ๋ณ€์ˆ˜์— RAZZLE_XXX ์ ‘๋‘์‚ฌ๊ฐ€ ๋ถ™๊ณ  ์ปดํŒŒ์ผ ์‹œ๊ฐ„์— ๋ฌธ์ž์—ดํ™”๋˜๋„๋ก ํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‚˜๋จธ์ง€๋Š” process.env.XXX ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ process.env ํ†ตํ•ด ๋Ÿฐํƒ€์ž„ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค๋Š” @gregmartyn์˜ ์˜๊ฒฌ์— ๋™์˜ํ•ฉ๋‹ˆ๋‹ค.

๊ธฐ์กด React ํ”„๋กœ์ ํŠธ์—์„œ Razzle์„ ์„ค์ •ํ•˜๋Š” ๋™์•ˆ ์ด ๋ฌธ์ œ์— ์ง๋ฉดํ–ˆ์Šต๋‹ˆ๋‹ค. ํฌํŠธ๋Š” ๋Ÿฐํƒ€์ž„์— ์žฌ์ •์˜ํ•  ์ˆ˜ ์—†์œผ๋ฉฐ ๋‹ค๋ฅธ process.env ๋ณ€์ˆ˜๋Š” ์„œ๋ฒ„์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

๋นŒ๋“œ ์‹œ ํ˜„์žฌ ๋™์ž‘:

process.env.PORT
process.env.NODE_ENV;
process.env.ASSETS_MANIFEST;
process.env.HOSTING_SET_VARIABLE;

ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„ ๋ชจ๋‘์— ๋ฉ๋‹ˆ๋‹ค.

3000;
'development';
'/Users/[...]/build/assets.json';
undefined;

์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„๊ฐ€ ์ •ํ™•ํžˆ ๋™์ผํ•œ ํ”„๋กœ์„ธ์Šค ํ™˜๊ฒฝ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๋Ÿฐํƒ€์ž„์— ์žฌ์ •์˜ํ•˜๊ฑฐ๋‚˜ ๋‹ค๋ฅธ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

์ด์ „ ๋ฒ„์ „๊ณผ ์™„์ „ํžˆ ํ˜ธํ™˜๋˜๋„๋ก ํ•˜๋ ค๋ฉด ๋นŒ๋“œ ์‹œ๊ฐ„์— ๋‹ค์Œ์œผ๋กœ ๋ณ€ํ™˜ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค(์„œ๋ฒ„์—์„œ ํด๋ผ์ด์–ธํŠธ๋Š” ๋™์ผํ•˜๊ฒŒ ์œ ์ง€๋  ์ˆ˜ ์žˆ์Œ).

process.env.PORT || 3000;
process.env.NODE_ENV || 'development';
process.env.ASSETS_MANIFEST || '/Users/[...]/build/assets.json';
process.env.HOSTING_SET_VARIABLE;

์ด๋Ÿฐ ์‹์œผ๋กœ ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„ ๋ชจ๋‘์—์„œ process.env.PORT๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์€ 3000์ž…๋‹ˆ๋‹ค.

razzle ์ด PORT=80 ๋กœ _built_ ์ธ ๊ฒฝ์šฐ ํด๋ผ์ด์–ธํŠธ๋Š” process.env.PORT ๋ฅผ 80 ๋กœ ๋ณ€ํ™˜ํ•˜๊ณ  ์„œ๋ฒ„๋Š” process.env.PORT || 80 ํ•ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ํ˜„์žฌ์™€ ๋™์ผํ•œ ๋™์ž‘์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

ํ™”๋ คํ•œ ํ•จ๊ป˜ _run_ ๊ฒฝ์šฐ PORT=81 (๋‚ด์žฅํ˜• ๋™์•ˆ 80 ), ํด๋ผ์ด์–ธํŠธ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋Š” ๋‚จ์•„์žˆ์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค 80 ์„œ๋ฒ„ ๋ณ€์ˆ˜๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค ๋™์•ˆ 81 .

์ด ๋™์ž‘์€ ๋ฌผ๋ก  ์˜ˆ๊ธฐ์น˜ ์•Š์€ ๋™์ž‘์œผ๋กœ ์ด์–ด์งˆ ์ˆ˜ ์žˆ์ง€๋งŒ ์™„์ „ํ•œ ์—ญํ˜ธํ™˜์„ฑ์„ ์œ ์ง€ํ•˜๋ฉด์„œ ๊ฐ€์žฅ ์œ ์—ฐํ•œ process.env ์‚ฌ์šฉ๋ฒ•์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ํฌํŠธ๋Š” ๋Ÿฐํƒ€์ž„์— ์„œ๋ฒ„์—์„œ ๊ณ„์† ๋ฎ์–ด์“ธ ์ˆ˜ ์žˆ์œผ๋ฉฐ ํ˜ธ์ŠคํŒ… ํ”Œ๋žซํผ์—์„œ ์„ค์ •ํ•œ ๋‹ค๋ฅธ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋Š” ์„œ๋ฒ„์—์„œ ์žˆ๋Š” ๊ทธ๋Œ€๋กœ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

์—ฌ๊ธฐ์—์„œ ๊ทผ๋ณธ์ ์ธ ๋ฌธ์ œ๋Š” Razzle์ด ํ˜„์žฌ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์„œ๋กœ ๋‹ค๋ฅธ ๊ธฐ๋Šฅ์„ ํ•˜๋‚˜์˜ ๊ฐœ์ฒด๋กœ ๋ฌถ๊ณ  ๊ธฐ์กด ๊ธฐ๋Šฅ์„ ๊ทผ๋ณธ์ ์œผ๋กœ ๋ณ€๊ฒฝํ•˜๋ ค๊ณ  ํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋‹ค์Œ์„ ์ˆ˜ํ–‰ํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค.

  1. ์„ฑ๋Šฅ์ƒ์˜ ์ด์œ ๋กœ process.env ๋ณ€์ˆ˜๋ฅผ ์ƒ์ˆ˜๋กœ ๋ฐ”๊ฟ‰๋‹ˆ๋‹ค(https://webpack.js.org/plugins/define-plugin/#usage์˜ ์ถ•์†Œ ์˜ˆ์ œ ๋ฐ https://github.com/nodejs/node/issues์˜ nodejs ์†๋„ ์ €ํ•˜ ์ฐธ์กฐ). /3104)
  2. ์•„์ด์†Œ๋ฉ”ํŠธ๋ฆญ ์ฝ”๋“œ๊ฐ€ ๊ฑฑ์ •ํ•  ํ•„์š”๊ฐ€ ์—†๋„๋ก ์ด๋Ÿฌํ•œ ์ƒ์ˆ˜๋ฅผ ์„œ๋ฒ„์™€ ํด๋ผ์ด์–ธํŠธ ๋ชจ๋‘์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜์‹ญ์‹œ์˜ค.

๋ฌธ์ œ:

  • process.env๋Š” _variables_ ํ™˜๊ฒฝ์šฉ์ž…๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์„ ์ƒ์ˆ˜ ์„ธํŠธ๋กœ ๋ฐ”๊พธ๋ฉด ์˜ˆ์ƒ๋˜๋Š” ๋™์ž‘์ด ๋ณ€๊ฒฝ๋ฉ๋‹ˆ๋‹ค.
  • process.env๋Š” ์ข…์ข… ์•”ํ˜ธ๋ฅผ ํฌํ•จํ•œ ๋ฏผ๊ฐํ•œ ์ •๋ณด๋ฅผ ํฌํ•จํ•˜๋ฏ€๋กœ ํด๋ผ์ด์–ธํŠธ์™€ ๊ณต์œ ํ•  ๋ฐ์ดํ„ฐ์˜ ์ข‹์€ ์†Œ์Šค๊ฐ€ ์•„๋‹™๋‹ˆ๋‹ค. ๋ถ€๋ถ„์ ์œผ๋กœ ๊ณต์œ ๋˜๊ณ  ๋ถ€๋ถ„์ ์œผ๋กœ ๊ณต์œ ๋˜์ง€ ์•Š๋Š” ๊ฒฝ์šฐ ๊ฐœ๋ฐœ์ž๋Š” ์ด ํ•œ ๊ฐ€์ง€(process.env)๊ฐ€ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ž‘๋™ํ•˜์ง€ ์•Š์„ ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ํ‚ค์˜ ์ ‘๋‘์‚ฌ์— ๋”ฐ๋ผ ๋‹ค๋ฅธ ๋™์ž‘์„ ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.
  • ํ™˜๊ฒฝ ๋ณ€์ˆ˜๊ฐ€ ๋‹ค๋ฅธ ์ปจํ…์ŠคํŠธ์—์„œ ์ž‘๋™ํ•˜๋Š” ๋ฐฉ์‹๊ณผ ๋‹ค๋ฅธ ๋นŒ๋“œ ์‹œ ์ƒ์ˆ˜๋กœ ๋ฐ”๋€Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด Docker๋Š” ๋นŒ๋“œ ์‹œ๊ฐ„ ๋ณ€์ˆ˜(๋นŒ๋“œ ์ž์ฒด์— ์‹คํ–‰ ์œ„์น˜์— ๋”ฐ๋ผ ๋ณ€์ˆ˜ ์ •๋ณด๊ฐ€ ํ•„์š”ํ•  ๋•Œ ์œ ์šฉ)์™€ ํ™˜๊ฒฝ ๋ณ€์ˆ˜(์‚ฌ์ „ ๋นŒ๋“œ๋œ ์ด๋ฏธ์ง€ ํ•˜๋‚˜๊ฐ€ ๋‹ค๋ฅธ ํ™˜๊ฒฝ์— ๋ฐฐํฌ๋  ๋•Œ ์œ ์šฉ)๋ฅผ ๊ตฌ๋ถ„ํ•ฉ๋‹ˆ๋‹ค. Elastic Beanstalk, Heroku, et al. ๋˜‘๊ฐ™์ด ํ•ด.
  • ์ œ์•ˆ๋œ "RAZZLE_RUNTIME_" ์ ‘๋‘์‚ฌ๋Š” ์ž๋ช…ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ ์ธก์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ณ  ๋ณ€์ˆ˜๊ฐ€ ์•„๋‹˜์„ ์ „๋‹ฌํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ธ๋ผ์ธ์€ ์ผ๋ฐ˜์ ์œผ๋กœ ๋นŒ๋“œ ์‹œ ๋ฐœ์ƒํ•˜๋Š” ๊ฒƒ์„ ์ฐธ์กฐํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋˜๊ธฐ ๋•Œ๋ฌธ์— "INLINED_"๊ฐ€ ์ด๋ฅผ ํฌํ•จํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์™„๋ฒฝํ•˜์ง€๋Š” ์•Š์ง€๋งŒ("ISOMORPHIC_INLINED_"?) ์งง๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค.

๋‚ด ์„ ํ˜ธ ์‚ฌํ•ญ์€ ์ด ๊ธฐ๋Šฅ์„ ๋‹ค๋ฅธ ๋ถ€๋ถ„์œผ๋กœ ๋ถ„ํ• ํ•˜๊ณ  process.env๋ฅผ ์ „ํ˜€ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
DefinePlugin์€ razzle.config.js์™€ ๊ฐ™์€ ํŒŒ์ผ์„ ํ˜ธ์ถœํ•˜์—ฌ ๋นŒ๋“œ ์ƒ์ˆ˜๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
Redux๊ฐ€ configureStore(window.__PRELOADED_STATE__)๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์„œ๋ฒ„์—์„œ ํด๋ผ์ด์–ธํŠธ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๋Š” ๊ฒƒ๊ณผ ์œ ์‚ฌํ•œ ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹์Šต๋‹ˆ๋‹ค.

์ด์ „ ๋ฒ„์ „๊ณผ์˜ ํ˜ธํ™˜์„ฑ์„ ์œ„ํ•ด ์—…๊ทธ๋ ˆ์ด๋“œ ๋…ธํŠธ๋Š” ๊ตฌ์‹ ๋ฐฉ์‹์„ ์ •์˜ํ•˜๋Š” ์ƒ˜ํ”Œ razzle.config.js๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํ•˜๋‚˜์˜ ๋ถ€๋ก: ๋‚˜๋Š” "process.env๋ฅผ ์ „ํ˜€ ๋ณ€๊ฒฝํ•˜์ง€ ๋ง๋ผ"๊ณ  ๋งํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์œ„์˜ ๋‚ด ์˜๊ฒฌ์—์„œ ์„ฑ๋Šฅ์ƒ์˜ ์ด์œ ๋กœ process.env.NODE_ENV์— ์˜ˆ์™ธ๊ฐ€ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ์—ˆ๊ณ  "NODE_ENV" ์ž์ฒด๋Š” ์ผ๋ฐ˜์ ์œผ๋กœ "NODE_ENV = ์ƒ์‚ฐ์€ ์ด๊ฒƒ์ด ์ตœ์ ํ™”๋œ ๋นŒ๋“œ์ž„์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค"์˜ ์˜๋ฏธ๋ฅผ ์ทจํ–ˆ์Šต๋‹ˆ๋‹ค.

@gregmartyn ์„ฑ๋Šฅ ์ตœ์ ํ™”๋ฅผ ์œ„ํ•ด NODE_ENV๋ฅผ ์„ค์ •ํ•˜๊ณ  ํ˜„์žฌ ์ž‘๋™ํ•˜๋Š” babel ์‚ฌ์ „ ์„ค์ •์„ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํ™˜๊ฒฝ์„ ์—‰๋ง์œผ๋กœ ๋งŒ๋“  ๋‚˜์˜ ์ดˆ๊ธฐ ์ถ”๋ก ์€ ํ”„๋กœ์ ํŠธ๊ฐ€ ์ด๋ฏธ ์‹œ์ž‘๋œ ํ›„์— SSR์ด ์ถ”๊ฐ€๋˜๋Š” ๊ฒฝ์šฐ๊ฐ€ ๋งŽ๊ธฐ ๋•Œ๋ฌธ์— CRA์—์„œ ํ›จ์”ฌ ์‰ฝ๊ฒŒ ์ด๋™ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ๊ฒƒ์ด์—ˆ์Šต๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” ๋˜ํ•œ ๋‹ค๋ฅธ ํ”„๋กœ์ ํŠธ์—์„œ CRA๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋นŒ๋“œ ๋„๊ตฌ๋ฅผ (์•ฝ๊ฐ„) ๋‹จ์ˆœํ™”ํ•ฉ๋‹ˆ๋‹ค.

์‘; NODE_ENV๊ฐ€ ์œ ์šฉํ•œ ์˜ˆ์™ธ๋ผ๋Š” ๋ฐ ๋™์˜ํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์€ ๊ทธ ์ž์ฒด์˜ ๊ฒƒ์ด๊ณ  ๋นŒ๋“œ์™€ ๋ฐ€์ ‘ํ•˜๊ฒŒ ์—ฐ๊ฒฐ๋˜์–ด ์žˆ์œผ๋ฏ€๋กœ ๋†€๋ผ์šด ์ผ์ด ์•„๋‹™๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž ์ง€์ • SSR ์†”๋ฃจ์…˜์—์„œ CRA๋ฅผ ๋ฐ”๋กœ ๊ฑด๋„ˆ๋›ฐ์—ˆ์œผ๋ฏ€๋กœ CRA๊ฐ€ ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ์ž˜ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ๋„ ๋ฌธ์ œ์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค: https://github.com/facebook/create-react-app/issues/2353

CRA ์•ฑ์˜ ๋Ÿฐํƒ€์ž„ ์ฝ”๋“œ๊ฐ€ ์„œ๋ฒ„์—์„œ ์ „ํ˜€ ์‹คํ–‰๋˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ์ด CRA๋ณด๋‹ค Razzle์—๊ฒŒ ๋” ํฐ ๋ฌธ์ œ๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. CRA๋Š” process.env๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์›ํ•˜๋Š” ๋ชจ๋“  ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํด๋ผ์ด์–ธํŠธ ์ธก ์ฝ”๋“œ์— ๊ด€ํ•œ ํ•œ CRA๋Š” ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด ๋น„์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๋ฐ˜๋ฉด์— Razzle์€ SSR์— ๋Œ€ํ•ด express๋ฅผ ์‹œ์ž‘ํ•˜๊ณ  ํ•ด๋‹น ์ฝ”๋“œ๋Š” process.env๊ฐ€ ๋…ธ๋“œ ๋Ÿฐํƒ€์ž„ ํ™˜๊ฒฝ ๋ณ€์ˆ˜์˜ ์ „์ฒด ์„ธํŠธ์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ๋Š” ์ผ๋ฐ˜์ ์ธ ์˜๋ฏธ ์ฒด๊ณ„๋ฅผ ๊ฐ€์งˆ ๊ฒƒ์œผ๋กœ ํ•ฉ๋ฆฌ์ ์œผ๋กœ ์˜ˆ์ƒํ•ฉ๋‹ˆ๋‹ค. Process.env๋Š” ์„œ๋ฒ„์—์„œ ์‹ค์ œ ์˜๋ฏธ๊ฐ€ ์žˆ์œผ๋ฏ€๋กœ CRA๊ฐ€ ๋‹ค๋ฅธ ์‚ฌ์šฉ ์‚ฌ๋ก€์— ๋Œ€ํ•ด ์ด๋ฅผ ์ฑ„ํƒํ•œ ๊ฒƒ์€ ์œ ๊ฐ์ž…๋‹ˆ๋‹ค. "cra.inlines"์™€ ๊ฐ™์€ "process.env" ๋Œ€์‹  ๋‹ค๋ฅธ ์ด๋ฆ„์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋Œ€์‹ , ๋™ํ˜• ์ฝ”๋“œ๋Š” ํด๋ผ์ด์–ธํŠธ ์ธก๋งŒ ๊ณ ๋ คํ•  ๋•Œ ๋‚ด๋ฆฐ ๊ฒฐ์ •์— ์˜ํ–ฅ์„ ๋ฐ›์Šต๋‹ˆ๋‹ค.

RAZZLE_XXX ํ™˜๊ฒฝ ๋ณ€์ˆ˜๊ฐ€ ๋ชจ๋‘ ํด๋ผ์ด์–ธํŠธ์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋œ ๋ชจ๋“  ๊ณณ์—์„œ ๋นจ๊ฐ„์ƒ‰์œผ๋กœ ํ‘œ์‹œ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๋ฏผ๊ฐํ•œ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ํด๋ผ์ด์–ธํŠธ์— ์ „์†กํ•˜์ง€ ์•Š๊ณ  ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉํ•ฉ๋‹ˆ๊นŒ?

๋™ํ˜• ์ฝ”๋“œ์—์„œ ์ฐธ์กฐํ•˜์ง€ ์•Š์œผ๋ฉด ํด๋ผ์ด์–ธํŠธ๋กœ ์ „์†ก๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

@jaredpalmer ์•„๋งˆ๋„์ด ๋ฌธ์ œ๋Š” afterjs์—๋งŒ ํ•ด๋‹น๋ฉ๋‹ˆ๊นŒ? ๋‚˜๋Š” ์„œ๋ฒ„ ์ฝ”๋“œ์—์„œ๋งŒ ๊ทธ๊ฒƒ๋“ค์„ ์ฐธ์กฐํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

RAZZLE ์ ‘๋‘์‚ฌ ์—†์ด ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์ •์˜ํ•˜๋Š” ๊ธฐ๋Šฅ์— ๋Œ€ํ•œ ํˆฌํ‘œ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ์ตœ์†Œํ•œ process.env ๋Š” ์„œ๋ฒ„ ์ธก์—์„œ ์ง€์›Œ์ ธ์„œ๋Š” ์•ˆ ๋ฉ๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋ฉด dotenv ์™€ ๊ฐ™์€ ๊ฒƒ์„ ์‚ฌ์šฉํ•˜์—ฌ ์„œ๋ฒ„ ์ธก ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ๋กœ๋“œํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์‘์šฉ ํ”„๋กœ๊ทธ๋žจ ํ™˜๊ฒฝ์— ๋Œ€ํ•œ ๊ฐ€์ •์„ ๋„ˆ๋ฌด ๋ฐฉํ•ดํ•˜๋Š” ๊ฒƒ์ฒ˜๋Ÿผ ๋ณด์ž…๋‹ˆ๋‹ค.

๋‚˜๋Š” ํ˜„์žฌ razzle์ด ํด๋ผ์ด์–ธํŠธ์™€ ์„œ๋ฒ„์— ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์–ด๋–ป๊ฒŒ ์ฃผ์ž…ํ•˜๋Š”์ง€์— ๋Œ€ํ•ด ํ™•์‹คํžˆ ์•Œ์ง€ ๋ชปํ•˜์ง€๋งŒ, ํ™•์‹คํžˆ ๋‹น์‹ ์€ ํด๋ผ์ด์–ธํŠธ์—์„œ ์„œ๋ฒ„์— ํŠน์ •ํ•œ ๊ฒƒ๋“ค์„ ์›ํ•˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ถˆํ–‰ํžˆ๋„ ์ด๊ฒƒ์€ ์ง€๊ธˆ ๋‚˜์—๊ฒŒ ์ผ์ข…์˜ ๊ฑฐ๋ž˜ ์ฐจ๋‹จ๊ธฐ์ž…๋‹ˆ๋‹ค.

https://github.com/jaredpalmer/razzle/issues/477#issuecomment -363538712์—์„œ ๋™ํ˜• ๋ฐ˜์‘ ์•ฑ์— ๋Œ€ํ•ด ์ œ์•ˆ๋œ ์†”๋ฃจ์…˜์„ ๋‹ค์‹œ ๊ฒŒ์‹œํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์ฃผ์š” ๊ฐœ๋…์€ ๋Ÿฐํƒ€์ž„ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์ ์ ˆํ•˜๊ฒŒ ์„ค์ •ํ•˜๊ธฐ ์œ„ํ•ด ์„œ๋ฒ„ ์‹คํ–‰ ์ง์ „์— ๋Ÿฐํƒ€์ž„์— ์ฃผ์ž…๋˜๋Š” ์ปดํŒŒ์ผ ํƒ€์ž„์— ํ”Œ๋ ˆ์ด์Šคํ™€๋”๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด ์†”๋ฃจ์…˜์€ ๋„์ปค ์ปจํ…Œ์ด๋„ˆ์—์„œ ์„œ๋ฒ„๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•œ ๊ฒƒ์ด์ง€๋งŒ ์ด RFC์— ๋งž๊ฒŒ ์กฐ์ •๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ์†”๋ฃจ์…˜์—์„œ RAZZLE_XXXX ํ™˜๊ฒฝ ๋ณ€์ˆ˜๊ฐ€ ์ผ์น˜ํ•˜๊ณ  HOST, PORT ๋ฐ REDIS_URL๊ณผ ํ•จ๊ป˜ ์ฃผ์ž…๋ฉ๋‹ˆ๋‹ค.


์ €๋Š” ๊ฐœ์ธ์ ์œผ๋กœ ์ด ๋ฌธ์ œ๋กœ ์–ด๋ ค์›€์„ ๊ฒช์—ˆ๊ณ  ์ด ๋ฌธ์ œ์— ๋Œ€ํ•œ ํ•ด๊ฒฐ์ฑ…์„ ์ฐพ๋Š” ๋ฐ ๋ช‡ ์‹œ๊ฐ„์„ ๋ณด๋ƒˆ์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ webpack ์ปดํŒŒ์ผ์— ๋‚ด์žฌ๋˜์–ด ์žˆ์œผ๋ฉฐ razzle it ์ž์ฒด์™€ ๊ด€๋ จ์ด ์—†์Šต๋‹ˆ๋‹ค.

create-react-app์ด ์ด๋ฅผ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ณ  ๋‘ ํ”„๋กœ์ ํŠธ์— ๊ฑธ์ณ ์ผ๋ถ€ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋ฐ ๋ฃจ๋น„ ์ฝ”๋“œ๋ฅผ ์ด์‹ํ•œ ํ›„ ๋‹ค์Œ ์†”๋ฃจ์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ heroku์˜ ๋„์ปค ์ปจํ…Œ์ด๋„ˆ์— razzle typescript ๋ฐ˜์‘ ์•ฑ์„ ์„ฑ๊ณต์ ์œผ๋กœ ๋ฐฐํฌํ–ˆ์Šต๋‹ˆ๋‹ค.

ํ™˜๊ฒฝ

์ด ์Šคํฌ๋ฆฝํŠธ๋Š” ๋Ÿฐํƒ€์ž„ ํ™˜๊ฒฝ์„ ์ฒ˜๋ฆฌํ•˜๋Š” ๋ชจ๋“ˆ๋กœ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

export interface EnvironmentStore {
  NODE_ENV?: string;
  [key: string]: string | undefined;
}

// Capture environment as module variable to allow testing.
let compileTimeEnv: EnvironmentStore;
try {
  compileTimeEnv = process.env as EnvironmentStore;
} catch (error) {
  compileTimeEnv = {};
  // tslint:disable-next-line no-console
  console.log(
    '`process.env` is not defined. ' +
    'Compile-time environment will be empty.'
  );
}

// This template tag should be rendered/replaced with the environment in production.
// Padded to 4KB so that the data can be inserted without offsetting character
// indexes of the bundle (avoids breaking source maps).
/* tslint:disable:max-line-length */
const runtimeEnv = '{{RAZZLE_VARS_AS_BASE64_JSON__________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________}}';
/* tslint:enable:max-line-length */

// A function returning the runtime environment, so that
// JSON parsing & errors occur at runtime instead of load time.
export const loadRuntimeEnv = (): EnvironmentStore => {
  let env;
  if (typeof env === 'undefined') {
    if (compileTimeEnv.NODE_ENV === 'production') {
      try {
        env = JSON.parse((Buffer.from(runtimeEnv.trim(), 'base64').toString()));
      } catch (error) {
        env = {};
        const overflowsMessage = runtimeEnv.slice(32, 33) !== null;
        // tslint:disable-next-line no-console
        console.error(
          'Runtime env vars cannot be parsed. Content is `%s`',
          runtimeEnv.slice(0, 31) + (overflowsMessage ? 'โ€ฆ' : '')
        );
      }

    } else {
      env = compileTimeEnv;
    }
  }
  return env;
};

export default loadRuntimeEnv;

์šฉ๋ฒ•:

import { loadRuntimeEnv, EnvironmentStore } from './env';
const env: EnvironmentStore = loadRuntimeEnv();

const serverHost: string =env.RAZZLE_SERVER_HOST || 'localhost';

docker-start.js

์ด ์Šคํฌ๋ฆฝํŠธ๋Š” server.js ๋Œ€์‹  ์ง„์ž…์ ์œผ๋กœ ์‚ฌ์šฉ๋˜๋ฉฐ ์‹ค์ œ ๋Ÿฐํƒ€์ž„ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋กœ {{RAZZLE_VARS_AS_BASE64_JSON___... }} ์ž๋ฆฌ ํ‘œ์‹œ์ž๋ฅผ ์‚ฝ์ž…ํ•˜๋Š” ๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

require('newrelic');
const logger = require('heroku-logger');
const path = require('path');
const fs = require('fs');

const PLACEHOLDER = /\{\{RAZZLE_VARS_AS_BASE64_JSON_*?\}\}/;
const MATCHER = /^RAZZLE_/i;

const InjectableEnv = {

    inject: function(file, ...args) {

        const buffer = fs.readFileSync(file, { encoding: 'utf-8' });
        let injectee = buffer.toString();

        const matches = injectee.match(PLACEHOLDER);
        if (!matches) {
            return;
        }

        const placeholderSize = matches[0].length;

        let env = InjectableEnv.create(args);
        const envSize = env.length;
        const newPadding = placeholderSize - envSize;
        if (newPadding < 0) {
            console.log('You need to increase your placeholder size');
            process.exit();
        }
        const padding = Array(newPadding).join(' ');
        env = InjectableEnv.pad(padding, env);

        const injected = injectee.replace(PLACEHOLDER, env);

        fs.writeFileSync(file, injected, { encoding: 'utf-8' });
    },

    create: function() {

        const vars = Object.keys(process.env)
            .filter(key => MATCHER.test(key))
            .reduce((env, key) => {
                env[key] = process.env[key];
                return env;
            }, {});

        vars.NODE_ENV = process.env.NODE_ENV;

        if (typeof process.env.HOST !== 'undefined' && typeof vars.RAZZLE_SERVER_HOST === 'undefined') {
          vars.RAZZLE_SERVER_HOST = process.env.HOST;
        }

        if (typeof process.env.PORT !== 'undefined' && typeof vars.RAZZLE_SERVER_PORT === 'undefined') {
          vars.RAZZLE_SERVER_PORT = process.env.PORT;
        }

        if (typeof process.env.REDIS_URL !== 'undefined' && typeof vars.RAZZLE_REDIS_URL === 'undefined') {
          vars.RAZZLE_REDIS_URL = process.env.REDIS_URL;
        }

        return Buffer.from(JSON.stringify(vars)).toString('base64');
    },

    pad: function(pad, str, padLeft) {
        if (typeof str === 'undefined')
            return pad;
        if (padLeft) {
            return (pad + str).slice(-pad.length);
        } else {
            return (str + pad).substring(0, pad.length);
        }
    }
}

const root = process.cwd();
const serverBundle = path.resolve(path.join(root, '/build/server.js'));

if (fs.existsSync(serverBundle)) {
    logger.info('Injecting runtime env');
    InjectableEnv.inject(serverBundle);
    logger.info('Launching server instance');
    require(serverBundle);
}

๋„์ปคํŒŒ์ผ

# You should always specify a full version here to ensure all of your developers
# are running the same version of Node.
FROM node:8.9.4

ENV NODE_ENV=production \
    REACT_BUNDLE_PATH=/static/js/vendor.js \
    PATH=/app/node_modules/.bin:$PATH \
    NPM_CONFIG_LOGLEVEL=warn

RUN curl -o- -L https://yarnpkg.com/install.sh | bash

# use changes to package.json to force Docker not to use the cache
# when we change our application's nodejs dependencies:
COPY package.json yarn.lock /tmp/
RUN cd /tmp \
  && yarn install --production=false --pure-lockfile \
  && mkdir -p /app \
  && cp -a /tmp/node_modules /app \
  && yarn cache clean \
  && rm -rf *.*

# From here we load our application's code in, therefore the previous docker
# "layer" thats been cached will be used if possible
WORKDIR /app
ADD . /app

RUN yarn build

EXPOSE 3000

CMD ["node", "docker-start.js"]

์˜ค๋ฒ„ํ”Œ๋กœ ๋ฉ”์‹œ์ง€ ์ฒ˜๋ฆฌ๊ฐ€ ์™„๋ฃŒ๋˜์ง€ ์•Š์€ ์  ์–‘ํ•ด ๋ถ€ํƒ๋“œ๋ฆฌ๋ฉฐ, ๋„์›€์ด ๋˜์…จ์œผ๋ฉด ํ•ฉ๋‹ˆ๋‹ค.

์ฐธ์กฐ:

create-react-app์šฉ Heroku Buildpack
create-react-app์šฉ Heroku Buildpack์˜ ๋‚ด๋ถ€ ๋ ˆ์ด์–ด

์ด๊ฒƒ์€ webpack ์ปดํŒŒ์ผ์— ๋‚ด์žฌ๋˜์–ด ์žˆ์œผ๋ฉฐ razzle it ์ž์ฒด์™€ ๊ด€๋ จ์ด ์—†์Šต๋‹ˆ๋‹ค.

Razzle์€ DefinePlugin์„ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ Razzle์—์„œ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š” ๋‹น์‹ ์ด ๋งํ•˜๋Š” ๊ฒƒ์„ ๋”ฐ๋ฅธ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๋‚ด๊ฐ€ ์ž˜๋ชป ์ดํ•ดํ–ˆ๋Š”์ง€ ์•Œ๋ ค์ฃผ์„ธ์š”. ๋นŒ๋“œ ์‹œ ์„œ๋ฒ„ ๋นŒ๋“œ์—์„œ ์ธ์Šคํ„ด์Šค ์‹œ์ž‘ ์‹œ ๋ฌธ์ž์—ด์„ ๊ต์ฒดํ•˜๋Š” ์ž๋ฆฌ ํ‘œ์‹œ์ž๋ฅผ process.env์— ๋„ฃ์Šต๋‹ˆ๋‹ค. ์„œ๋ฒ„ ๋น„๋ฐ€์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ ์œ„ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค. (ํด๋ผ์ด์–ธํŠธ ๋นŒ๋“œ์—์„œ๋„ ์‹คํ–‰๋˜์ง€ ์•Š๋Š” ์ด์œ ๋Š” ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค.) ๋ฌธ์ œ: HMR์—์„œ๋Š” ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ํ•ดํ‚น์ž…๋‹ˆ๋‹ค. ์ž„์˜์˜ 4k ๊ฒฝ๊ณ„๋ฅผ ๋„์ž…ํ•ฉ๋‹ˆ๋‹ค. ํ˜„์žฌ ํ˜•์‹์—์„œ๋Š” ํด๋ผ์ด์–ธํŠธ์™€ ๊ณต์œ ํ•ด์•ผ ํ•˜๋Š” ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ๋‹ค๋ฃจ์ง€ ์•Š์œผ๋ฉฐ ๋นŒ๋“œ ์‹œ๊ฐ„ ์ƒ์ˆ˜๋กœ ๋‚จ์•„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ปจํ…Œ์ด๋„ˆ์— ๋Œ€ํ•œ ์ถ”๊ฐ€ ์‹œ์ž‘ ๋‹จ๊ณ„์ž…๋‹ˆ๋‹ค.

๋‚ด๊ฐ€ https://github.com/jaredpalmer/razzle/issues/528#issuecomment -377058844์—์„œ ๋งํ•œ ๋งŽ์€ ๋ถ€๋ถ„์„ ๋‹ค์‹œ ์„ค๋ช…ํ•˜๋ ค๋ฉด

ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์€ Razzle๊ณผ CRA๊ฐ€ ํ•„์š”ํ•œ ๊ฒƒ๋ณด๋‹ค ๋” ๋งŽ์€ ๊ธฐ๋Šฅ์„ process.env์— ๋‹ด์œผ๋ ค ํ•œ๋‹ค๋Š” ์‚ฌ์‹ค์„ ์ธ์‹ํ•˜๋Š” ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. Docker์™€ ํ•จ๊ป˜ ์ž‘๋™ํ•˜๋„๋ก ํ•˜๊ธฐ ์œ„ํ•ด ์ •์ (๋นŒ๋“œ ์‹œ๊ฐ„) ๋ฐ ๋™์ (์—ฌ๊ธฐ์„œ๋Š” ์ปจํ…Œ์ด๋„ˆ ์‹œ์ž‘ ์‹œ๊ฐ„), ๋น„๋ฐ€ ๋ฐ ๋น„๋น„๋ฐ€์˜ 4๊ฐ€์ง€ ๊ฐ€๋Šฅํ•œ ์ƒํƒœ ์ค‘ ํ•˜๋‚˜๋ฅผ ๊ฐ–๋Š” ํ•„๋“œ๊ฐ€ ์žˆ๋Š” ํ•˜๋‚˜์˜ ๊ฐœ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ์šฐ๋ฆฌ๋Š” 4๊ฐ€์ง€ ์ƒํƒœ(process.env.STATIC_PRIVATE_X, process.env.DYNAMIC_PUBLIC_Y, ...) ๋ชจ๋‘์— ๋Œ€ํ•œ ์ ‘๋‘์‚ฌ๋ฅผ ์ƒ๊ฐํ•ด๋‚ผ ์ˆ˜ ์žˆ์ง€๋งŒ ๋” ๊นจ๋—ํ•œ ์†”๋ฃจ์…˜์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ํ›จ์”ฌ ๋” ๋‚ซ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

process.env๊ฐ€ ๊ธฐ๋ณธ์ ์œผ๋กœ ์„œ๋ฒ„ ๋น„๋ฐ€ ์ €์žฅ์†Œ๋กœ ์ž‘๋™ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์ž‘๋™ํ•œ๋‹ค๋ฉด ์ƒํ™ฉ์„ ํ›จ์”ฌ ๋” ์‰ฝ๊ฒŒ ์ดํ•ดํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•œ ๊ฐ€์ง€ ์˜ˆ์™ธ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. NODE_ENV๋Š” ๋นŒ๋“œ ํƒ€์ž„ ์ธ๋ผ์ธ์ด์ง€๋งŒ ๋นŒ๋“œ์˜ ์†์„ฑ์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ดœ์ฐฎ์Šต๋‹ˆ๋‹ค. ๋Ÿฐํƒ€์ž„์— NODE_ENV๋ฅผ ์„ค์ •ํ•˜๋Š” ๊ฒƒ์€ ์˜๋ฏธ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

์ด์ œ ํด๋ผ์ด์–ธํŠธ์— ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๋ฐฉ๋ฒ•๋งŒ ๋‚จ์•˜์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด process.env๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ๋ฅผ ์ „ํ˜€ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ •์  ํ•ญ๋ชฉ์— ์˜ˆ๋ฅผ ๋“ค์–ด razzle.build.X๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  redux์™€ ๊ฐ™์€ ๋ฐฉ์‹์œผ๋กœ ๋™์  ํ•ญ๋ชฉ์„ ํด๋ผ์ด์–ธํŠธ์— ์ „๋‹ฌํ•˜์ง€ ์•Š๋Š” ์ด์œ ๋Š” ๋ฌด์—‡์ž…๋‹ˆ๊นŒ?

Node์—์„œ process.env๊ฐ€ ๋Š๋ฆฐ ๋˜ ๋‹ค๋ฅธ ๋ฌธ์ œ๊ฐ€ ์žˆ์ง€๋งŒ process.env๋ฅผ ํ•œ ๋ฒˆ ์ฝ๋Š” ์บ์‹œ ๊ณ„์ธต์œผ๋กœ ํ•ด๊ฒฐํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ์ข‹์Šต๋‹ˆ๋‹ค.

@gregmartyn ๋‚˜๋Š” ์ด๊ฒƒ์ด ํ•ดํ‚น์ด๋ผ๋Š” ๋ฐ ๋™์˜ํ•ฉ๋‹ˆ๋‹ค ... ๊ทธ๋ฆฌ๊ณ  ๊ทธ๊ฒƒ์€ ์ž„์˜์˜ 4K ๊ฒฝ๊ณ„๋ฅผ ๋„์ž…ํ•ฉ๋‹ˆ๋‹ค. ์ด ์•„์ด๋””์–ด๋Š” ํ˜„์žฌ CRA๋กœ ์ˆ˜ํ–‰๋œ ์ž‘์—…(๊ฒŒ์‹œ๋œ ์ฐธ์กฐ ์ฐธ์กฐ)์„ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋ฉฐ ์„œ๋ฒ„ ์ธก ๋Ÿฐํƒ€์ž„ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์œ„ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์ด ๋ฌธ์ œ์˜ ๊ทผ๋ณธ ์›์ธ์„ ํ•ด๊ฒฐํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋  ๊ฒƒ์œผ๋กœ ์ƒ๊ฐ ๋˜๋Š” PR ์„

๋˜ํ•œ PORT & HOST ๋„ ์ด์ƒ์ ์œผ๋กœ๋Š” ์„œ๋ฒ„ ์ปดํŒŒ์ผ ์‹œ๊ฐ„์— ํ˜ผ์ž ๋‚จ๊ฒจ์ง€๋Š” ๊ฒƒ์— ๋™์˜ํ•ฉ๋‹ˆ๋‹ค.

@tgrisser ์ข‹์•„์š” ! ๊ทธ๊ฒƒ์€ ํฐ ๊ฐœ์„ ์ž…๋‹ˆ๋‹ค.
PORT ๋ฐ HOST ์™ธ์—๋„ ์ปดํŒŒ์ผํ•ด์„œ๋Š” ์•ˆ๋˜๋Š” ๋ณ€์ˆ˜ ๋ชฉ๋ก์— PUBLIC_PATH ๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

๋ฏผ๊ฐํ•œ ์‚ฌ์šฉ์ž ์ง€์ • ํ™˜๊ฒฝ ๋ณ€์ˆ˜๊ฐ€ ๋ชจ๋‘ ํด๋ผ์ด์–ธํŠธ๋กœ ์ปดํŒŒ์ผ๋˜๊ณ  ์žˆ์Œ์„ ์—ฌ์ „ํžˆ ๋ฐœ๊ฒฌํ–ˆ์Šต๋‹ˆ๋‹ค. ๋‚˜๋Š” server.js ์—์„œ๋งŒ ๊ทธ๊ฒƒ๋“ค์„ ์ฐธ์กฐํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. razzle ์€

์•ˆ๋…•ํ•˜์„ธ์š” ์—ฌ๋Ÿฌ๋ถ„, ์ €๋Š” ์ด๋ฒˆ ์ฃผ์— ์ง์žฅ์—์„œ ์ด ๋ชจ๋“  ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๊ณ„์† ์ง€์ผœ๋ด ์ฃผ์„ธ์š”. #611์ด ๋ณ‘ํ•ฉ๋  ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

config.js๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ถ”๊ฐ€ ์ •๋ณด์˜ ์ƒˆ ๊ฐ€์ด๋“œ๋ฅผ ๋”ฐ๋ฅด๋ฉด ๋ฒˆ๋“ค์—์„œ ๋ฏผ๊ฐํ•œ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์ œ๊ฑฐํ•˜๋Š” ๊ฒƒ๊ณผ ๊ด€๋ จํ•˜์—ฌ ์ €์—๊ฒŒ ํšจ๊ณผ์ ์ด์—ˆ์Šต๋‹ˆ๋‹ค. ๋Œ€๋‹จํ•˜๋‹ค :D

v2 ๋…ธํŠธ ๋ณด๊ธฐ

@jaredpalmer ๋‚ด๊ฐ€ ๋†“์นœ ๊ฒƒ์ด ์žˆ์„ ์ˆ˜ ์žˆ์ง€๋งŒ readme ๋ฌธ์„œ๊ฐ€ ์˜๋ฏธํ•˜๋Š” ๋ฐ”์—๋„ ๋ถˆ๊ตฌํ•˜๊ณ  ์ด๊ฒƒ์€ ์—ฌ์ „ํžˆ โ€‹โ€‹PORT์™€ ๊ฐ™์€ ๋ฌธ์ œ์— ๋Œ€ํ•œ ๋ฌธ์ œ์ž…๋‹ˆ๋‹ค. process.env.MY_THING ๋Š” ์ž˜ ์ž‘๋™ํ•˜์ง€๋งŒ process.env.PORT ๋Š” ์—ฌ์ „ํžˆ ๋นŒ๋“œ ์‹œ ๋Œ€์ฒด๋˜๋ฉฐ ๋Ÿฐํƒ€์ž„ ์‹œ ์ฝ์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ Heroku ์˜ˆ์ œ๋Š” ์‹ค์ œ๋กœ ์ž‘๋™ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์ด ์Šค๋ ˆ๋“œ์—์„œ ๋…ผ์˜๋œ PORT, HOST ๋“ฑ์˜ ํŠน๋ณ„ํ•œ ์ฒ˜๋ฆฌ๋Š” ๋ณด์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค.

PORT๋ฅผ ์‹ค์ œ ๋ณ€์ˆ˜๋กœ ๋งŒ๋“œ๋Š” ๊ฒƒ๋„ #581์— ์˜ํ•ด ์ฐจ๋‹จ๋ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” ๊ทธ๊ฒƒ์„ ํŒจ์น˜ํ•˜๊ณ  ์ž‘๋™์‹œํ‚ค๊ธฐ ์œ„ํ•ด PORT๋ฅผ ์ œ๊ฑฐํ•˜๋Š” DefinePlugin ๋ฐฐ์—ด์„ ์ƒ์„ฑํ•˜๋Š” razzle.config.js๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. (ํ•˜์ง€๋งŒ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค!)

๋Ÿฐํƒ€์ž„์— .env ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋Š” ์‚ฌ๋žŒ์ด ์žˆ๋‹ค๋ฉด ์ด ์ž‘์€ ํŒจํ‚ค์ง€๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”.
https://www.npmjs.com/package/razzle-plugin-runtimeenv

๋ˆ„๊ตฐ๊ฐ€ Azure์— Razzle ์•ฑ์„ ๋ฐฐํฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์กฐ์–ธํ•ด ์ฃผ์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ? ์ •๋ง ํž˜๋“ค์–ด์š”.

๋Ÿฐํƒ€์ž„์— .env ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋Š” ์‚ฌ๋žŒ์ด ์žˆ๋‹ค๋ฉด ์ด ์ž‘์€ ํŒจํ‚ค์ง€๋ฅผ ์‚ฌ์šฉํ•˜์„ธ์š”.
https://www.npmjs.com/package/razzle-plugin-runtimeenv

์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•ฉ๋‹ˆ๊นŒ? ์˜ˆ๋ฅผ ๋ณด์—ฌ ์ฃผ์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?

ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋Š” ์‹ค์ œ๋กœ ๋Ÿฐํƒ€์ž„์— ์ฃผ์ž…๋˜์–ด์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. razzle ์•ฑ์„ ์ปจํ…Œ์ด๋„ˆํ™”ํ•˜๋ฉด ์‹คํ–‰๋˜๋Š” ํ™˜๊ฒฝ๊ณผ ๋…๋ฆฝ์ ์œผ๋กœ ์ด๋ฏธ์ง€๋ฅผ ๋งŒ๋“ค๊ณ  ์„œ๋ฒ„๋ฅผ ์‹œ์ž‘ํ•  ๋•Œ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์ฝ๊ณ  ํด๋ผ์ด์–ธํŠธ ์•ฑ์— ์ œ๊ณตํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

๋‹ค๋ฅธ ์ ‘๊ทผ ๋ฐฉ์‹์€ ๋นŒ๋“œ ์‹œ๊ฐ„์—๋งŒ ๋ฐœ์ƒํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์‹ค์ œ๋กœ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋‚ด๊ฐ€ ์—ฌ๊ธฐ์—์„œ ์–ธ๊ธ‰ํ–ˆ๋“ฏ์ด :
https://github.com/HamidTanhaei/razzle-plugin-runtime/issues/1#issuecomment -525731273

razzle-plugin-runtime ๋Ÿฐํƒ€์ž„์—์„œ .env ๋ฐ .env.development ํŒŒ์ผ์„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋Ÿฐํƒ€์ž„์— ์•ฑ์—์„œ ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด axios ๊ตฌ์„ฑ์— ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
axios.defaults.baseURL = ${process.env.RAZZLE_APP_API_BASE_PATH}${process.env.RAZZLE_APP_API_VERSION} ;
๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ƒ์‚ฐ์„ ์œ„ํ•œ ์ƒ์‚ฐ ENV ๋ณ€์ˆ˜๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
https://github.com/jaredpalmer/razzle#adding -temporary-environment-variables-in-your-shell

๋ˆ„๊ตฐ๊ฐ€ Azure์— Razzle ์•ฑ์„ ๋ฐฐํฌํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์กฐ์–ธํ•ด ์ฃผ์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ? ์ •๋ง ํž˜๋“ค์–ด์š”.

https://github.com/jaredpalmer/razzle/issues/906#issuecomment -467046269์—์„œ @fabianisher ๊ฐ€ ๊ณต์œ ํ•œ ์†”๋ฃจ์…˜์„ ์‚ฌ์šฉํ•˜์—ฌ Azure ํฌํŠธ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค.

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰

๊ด€๋ จ ๋ฌธ์ œ

alexjoyner picture alexjoyner  ยท  3์ฝ”๋ฉ˜ํŠธ

mhuggins picture mhuggins  ยท  3์ฝ”๋ฉ˜ํŠธ

knipferrc picture knipferrc  ยท  5์ฝ”๋ฉ˜ํŠธ

JacopKane picture JacopKane  ยท  3์ฝ”๋ฉ˜ํŠธ

sebmor picture sebmor  ยท  4์ฝ”๋ฉ˜ํŠธ