๐Ÿ’ป๐Ÿ’€/๊ฐœ๋ฐœ

[React] Webpack์œผ๋กœ ๊ตฌ์ถ•ํ•œ React ํ”„๋กœ์ ํŠธ์—์„œ ํ™˜๊ฒฝ ๋ณ€์ˆ˜(.env) ์‚ฌ์šฉํ•˜๊ธฐ

db2 2021. 8. 19. 10:57

TL;DR

  • Webpack์„ ํ†ตํ•ด ์ง์ ‘ ๊ตฌ์„ฑํ•œ ๋ฆฌ์•กํŠธ ํ”„๋กœ์ ํŠธ
    • .env ํŒŒ์ผ์— ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•  ๋•Œ REACT_APP_์œผ๋กœ ์‹œ์ž‘ํ•˜์ง€ ์•Š์•„๋„ ๋จ
    • dotenv ํŒจํ‚ค์ง€: DefinePlugin์„ ํ†ตํ•ด ์ˆ˜๋™์œผ๋กœ ์ „์—ญ ๋ณ€์ˆ˜ ์ •์˜
    • dotenv-webpack ํŒจํ‚ค์ง€: ํ”Œ๋Ÿฌ๊ทธ์ธ์— new Dotenv() ์ถ”๊ฐ€
  • CRA๋ฅผ ํ†ตํ•ด ๊ตฌ์ถ•ํ•œ ๋ฆฌ์•กํŠธ ํ”„๋กœ์ ํŠธ
    • ๋ณ€์ˆ˜๋ช…์€ ๋ฐ˜๋“œ์‹œ REACT_APP_์œผ๋กœ ์‹œ์ž‘ํ•ด์•ผ ํ•จ
    • ๋ณ„๋„์˜ ์„ค์ • ์—†์ด /src ๋””๋ ‰ํ† ๋ฆฌ์˜ ํ•˜์œ„ ํŒŒ์ผ์—์„œ process.env๋กœ ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์ ‘๊ทผ

1. ์‚ฝ์งˆ๊ธฐ

'๋ฆฌ์•กํŠธ์—์„œ ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์‚ฌ์šฉํ•˜๊ธฐ' ๋ผ๋Š” ํ‚ค์›Œ๋“œ๋กœ ๊ตฌ๊ธ€๋งํ•˜๋ฉด ๋Œ€๋ถ€๋ถ„

dotenv ํŒจํ‚ค์ง€ ์„ค์น˜ -> ํ”„๋กœ์ ํŠธ ๋ฃจํŠธ์— .env ํŒŒ์ผ ์ƒ์„ฑ -> REACT_APP_์œผ๋กœ ์‹œ์ž‘ํ•˜๋Š” ๋ณ€์ˆ˜ ์ž‘์„ฑ -> ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋Š” ๊ณณ์—์„œ require('dotenv').config() ํ•œ ๋’ค, process.env.<๋ณ€์ˆ˜๋ช…> ์œผ๋กœ ํ™˜๊ฒฝ๋ณ€์ˆ˜์— ์ ‘๊ทผ

ํ•˜๋ฉด ๋œ๋‹ค๋Š” ๊ธ€์ด ๊ฒ€์ƒ‰๋œ๋‹ค. ์‹ค์ œ๋กœ ์˜ˆ์ „์— CRA๋กœ ๋งŒ๋“  ํ”„๋กœ์ ํŠธ์—์„œ ํŠน๋ณ„ํ•œ ์–ด๋ ค์›€ ์—†์ด ํ™˜๊ฒฝ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ–ˆ๋˜ ์ ์ด ์žˆ์–ด์„œ ์ €๋ ‡๊ฒŒ ํ•˜๋ฉด ๋˜๊ฒ ๊ฑฐ๋‹ˆ ํ–ˆ์ง€๋งŒ ์•„๋‹ˆ์—ˆ๋‹ค!?!!!! ํŠนํžˆ ์ € '๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋Š” ๊ณณ' ์„ ์ž˜๋ชป ์ดํ•ดํ•œ ํƒ“์— /src์˜ ํ•˜์œ„ ํŒŒ์ผ์—์„œ require('dotenv').config()๋ฅผ ํ˜ธ์ถœํ–ˆ๋Š”๋ฐ ์•„๋ž˜์™€ ๊ฐ™์€ ์—๋Ÿฌ๊ฐ€ ๋‚˜์„œ ๋งค์šฐ ๋‹นํ™ฉ์Šค๋Ÿฌ์› ๋‹ค.

๋Œ€๋žต ๋ญ๊ฐ€ ์ž˜๋ชป๋œ ๊ฑด์ง€ ๋ณด๋ฉด

Module not found: Error: Can't resolve 'fs' in '\node_modules\dotenv\lib'
Module not found: Error: Can't resolve 'path' in '\node_modules\dotenv\lib'
Module not found: Error: Can't resolve 'os' in '\node_modules\dotenv\lib'

fs ๋ชจ๋“ˆ์ด ์—†์–ด์„œ, path ๋ชจ๋“ˆ์ด ์—†์–ด์„œ, os ๋ชจ๋“ˆ์ด ์—†์–ด์„œ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๊ณ  ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค. ์นœ์ ˆํ•˜๊ฒŒ๋„ Webpack์˜ resolve ์˜ต์…˜์— polyfill์„ ์ง€์ •ํ•˜๋ผ๊ณ  ์•ˆ๋‚ดํ•ด์ฃผ์ง€๋งŒ, ์ €๊ฑฐ ํ•ด๋ดค์ž ์—ฐ์‡„์ ์œผ๋กœ ๋˜ ๋‹ค๋ฅธ ์—๋Ÿฌ๊ฐ€ ๋‚  ๋ฟ ์†Œ์šฉ์ด ์—†๋‹ค. ์™œ๋ƒํ•˜๋ฉด ๊ทผ๋ณธ์ ์œผ๋กœ Webpack๊ณผ dotenv์— ๋Œ€ํ•ด ์ž˜๋ชป ํŒŒ์•…ํ•˜๊ณ  ์‚ฌ์šฉํ–ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.๐Ÿ˜‚!

2. dotenv ๋ž€?

dotenv๋ž€ .env ํŒŒ์ผ์— ์„ ์–ธํ•œ ๋ณ€์ˆ˜๋ฅผ process.env์— ๋กœ๋“œํ•ด์ฃผ๋Š” ๋ฌด์˜์กด์„ฑ(zero-dependency) ๋ชจ๋“ˆ์ด๋‹ค. ๊ณต์‹๋ฌธ์„œ์— ๋‚˜์˜จ ์‚ฌ์šฉ๋ฒ•๋„ ์œ„์™€ ๋™์ผํ•œ๋ฐ ์–ด์งธ์„œ ์ €๋Ÿฐ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•˜๋Š”๊ฐ€ dotenv์˜ ๋ฉ”์ธ ์†Œ์Šค๋ฅผ ์‚ด์ง ๋“ค์—ฌ๋‹ค ๋ณด์•˜๋‹ค.

os์™€ path ๋ชจ๋“ˆ์„ ํ†ตํ•ด .env ํŒŒ์ผ์˜ ์ ˆ๋Œ€ ๊ฒฝ๋กœ๋ฅผ ์ฐพ๊ณ , fs ๋ชจ๋“ˆ๋กœ .env ํŒŒ์ผ์„ ๋ฌผ๋ฆฌ์ ์œผ๋กœ ์ฝ์–ด๋“ค์—ฌ process.env์— key-value ํ˜•์‹์œผ๋กœ ๋‹ด๊ณ  ์žˆ๋‹ค. ์—ฌ๊ธฐ์„œ ๋ฌธ์ œ์ ์„ ํŒŒ์•…ํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค. os, path, fs ๋ชจ๋“ˆ์€ Node.js๊ฐ€ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ œ๊ณตํ•˜๋Š” ๋ชจ๋“ˆ ์ค‘ ํ•˜๋‚˜์ด๋‹ค. ์ด์ฒ˜๋Ÿผ dotenv๋Š” Node.js ์˜ ๊ธฐ๋ณธ ํ™˜๊ฒฝ์—์„œ ์‹คํ–‰๋˜๋„๋ก ์˜๋„๋œ ํŒจํ‚ค์ง€์ด๋ฏ€๋กœ ๋ฌด์˜์กด์„ฑ ๋ชจ๋“ˆ์ด๋ผ๊ณ  ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฑฐ๋‹ค. ํ•˜์ง€๋งŒ ๋‚œ ์–ด๋–ป๊ฒŒ ํ–ˆ๋”๋ผ...? ๋ฐ”๋ณด๊ฐ™์ด /src์˜ ํ•˜์œ„ ํŒŒ์ผ์—์„œ dotenv๋ฅผ import ํ•ด๋ฒ„๋ ธ์—ˆ๋‹ค.

โ˜ (๋‹น์—ฐํ•˜๊ฒŒ๋„) React๋Š” Node.js๊ฐ€ ์•„๋‹ˆ๋‹ค

Node.js๋Š” React๋ฅผ ์‚ฌ์šฉํ•ด ๊ฐœ๋ฐœ๋œ ํ”„๋กœ๊ทธ๋žจ์ด ์‹คํ–‰๋  ์ˆ˜ ์žˆ๋Š” ๋Ÿฐํƒ€์ž„ ํ™˜๊ฒฝ์„ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์ด์ง€, React์™€ ์ง์ ‘์ ์ธ ๊ด€๊ณ„๊ฐ€ ์žˆ๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋‹ค. Node.js๋Š” Webpack์ด config ํŒŒ์ผ์˜ ์„ค์ •์„ ๋ฐ”ํƒ•์œผ๋กœ ์ •์  ํŒŒ์ผ๋“ค์„ ๋ฒˆ๋“ค๋งํ•˜๊ณ , npm start๋กœ ๊ฐœ๋ฐœ์šฉ ์„œ๋ฒ„๋ฅผ ์˜ฌ๋ ค ๋ฒˆ๋“ค๋ง๋œ ํŒŒ์ผ์„ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๋Š” ํ™˜๊ฒฝ์„ ์ œ๊ณตํ•ด์ฃผ๋Š” ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ๋Ÿฐํƒ€์ž„์ด๋‹ค.

์ฆ‰, React ํ”„๋กœ์ ํŠธ์˜ ์ž๋ฐ”์Šคํฌ๋ฆฝํŠธ ํŒŒ์ผ์€ Node.js ๊ทธ ์ž์ฒด๊ฐ€ ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— ํŠน์ • ํŒจํ‚ค์ง€๊ฐ€ ํ•„์š”ํ•˜๋‹ค๋ฉด npm์„ ํ†ตํ•ด ์„ค์น˜ํ•˜๊ณ  /node_modules์—์„œ๋ถ€ํ„ฐ import ํ•ด์„œ ์˜์กด์ ์œผ๋กœ ์‚ฌ์šฉํ•ด์•ผ ํ•œ๋‹ค. ๋•Œ๋ฌธ์— /src ํ•˜์œ„์˜ ํŒŒ์ผ์—์„œ๋Š” os, path, fs ๋ชจ๋“ˆ๋“ค์„ ์ฐพ์„ ์ˆ˜ ์—†์—ˆ๋˜ ๊ฒƒ์ด๋‹ค. ๋‚˜๋Š” dotenv ํŒจํ‚ค์ง€๋งŒ ์„ค์น˜ํ–ˆ์œผ๋‹ˆ๊นŒ!

3. ๊ทธ๋ž˜์„œ dotenv๋กœ ํ™˜๊ฒฝ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์€?

1๏ธโƒฃ DefinePlugin

Webpack์˜ DefinePlugin์„ ์‚ฌ์šฉํ•ด process.env๋ผ๋Š” ์ „์—ญ ๋ณ€์ˆ˜๋ฅผ ์ •์˜ํ•ด์ค€๋‹ค.

// .env
FIREBASE_API_KEY=TEST_KEY
FIREBASE_AUTH_DOMAIN=test.firebaseapp.com
FIREBASE_PROJECT_ID=test
// webpack.config.js  
const webpack = require("webpack");
const dotenv = require("dotenv");
dotenv.config(); // .env ํŒŒ์ผ์„ ํŒŒ์‹ฑํ•œ ๊ฐ์ฒด๊ฐ€ ๋ฆฌํ„ด๋˜์–ด process.env์— ์…‹ํŒ…๋œ๋‹ค

console.log(process.env);

์ „์—ญ ๋ณ€์ˆ˜๋ฅผ ์ •์˜ํ•˜๊ธฐ ์ „์— process.env๋ฅผ ์ฝ˜์†”์— ์ฐ์–ด๋ดค๋‹ค. ๋‹ค๋ฅธ ํ™˜๊ฒฝ๋ณ€์ˆ˜๋“ค ์‚ฌ์ด์— ๋‚ด๊ฐ€ ์„ ์–ธํ•œ FIREBASE_ ๊ด€๋ จ ๋ณ€์ˆ˜๋“ค์ด ํฌํ•จ๋œ ๊ฒŒ ๋ณด์ธ๋‹ค. ์‚ฌ์šฉ์ž ์ •์˜ ํ™˜๊ฒฝ๋ณ€์ˆ˜์— ๋ฐ˜๋“œ์‹œ REACT_APP_์„ ๋ถ™์ผ ํ•„์š”๋Š” ์—†์ง€๋งŒ ๋‹ค๋ฅธ ํ™˜๊ฒฝ๋ณ€์ˆ˜๋“ค๊ณผ์˜ ์ถฉ๋Œ์„ ๋ฏธ์—ฐ์— ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด ๊ตฌ๋ถ„ ๊ฐ€๋Šฅํ•œ prefix๋ฅผ ๋ถ™์—ฌ์ฃผ๋Š” ๊ฒƒ์ด ์ข‹๊ฒ ๋‹ค๋Š” ์ƒ๊ฐ์ด ๋“ ๋‹ค.

์ด์ œ ํŒŒ์ผ ์–ด๋””์„œ๋“  process.env๋ผ๋Š” ์ „์—ญ๋ณ€์ˆ˜์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋„๋ก DefinePlugin์„ ํ†ตํ•ด ์ •์˜ํ•ด์ค€๋‹ค. ์ด ๋•Œ ๋ฐ˜๋“œ์‹œ ๊ฐ’์€ JSON.stringify()๋ฅผ ํ†ตํ•˜์—ฌ JSON ๋ฌธ์ž์—ด๋กœ ๋ณ€ํ™˜ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.

// webpack.config.js  
module.exports = {
  ...
  plugins: [
    new webpack.DefinePlugin({
      "process.env": JSON.stringify(process.env), 
    }),
  ]
}

2๏ธโƒฃ EnvironmentPlugin

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

// webpack.config.js  
module.exports = {
  ...
  plugins: [
    new webpack.EnvironmentPlugin([
      "FIREBASE_API_KEY",
      "FIREBASE_AUTH_DOMAIN",
      "FIREBASE_PROJECT_ID",
    ]),
  ]
}

์œ„์˜ ์ฝ”๋“œ๋Š” ์•„๋ž˜์ฒ˜๋Ÿผ DefinePlugin์œผ๋กœ ์ ์šฉํ•˜๋Š” ๊ฒƒ๊ณผ ์™„์ „ํžˆ ๋™์ผํ•˜๋‹ค.

// webpack.config.js  
module.exports = {
  ...
  plugins: [
    new webpack.DefinePlugin([
      "process.env.FIREBASE_API_KEY": JSON.stringify(process.env.FIREBASE_API_KEY),
      "process.env.FIREBASE_AUTH_DOMAIN": JSON.stringify(process.env.FIREBASE_AUTH_DOMAIN),
      "process.env.FIREBASE_PROJECT_ID": JSON.stringify(process.env.FIREBASE_PROJECT_ID),
    ]),
  ]
}

4. ๋Œ€์ฒด dotenv-webpack

dotenv๊ฐ€ ์•„๋‹ˆ๋ผ dotenv-webpack ํŒจํ‚ค์ง€๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ์žˆ๋‹ค. ๋จผ์ € ํŒจํ‚ค์ง€๋ฅผ ์„ค์น˜ํ•œ๋‹ค.

npm install dotenv-webpack --save-dev

๊ทธ๋ฆฌ๊ณ  Webpack config ํŒŒ์ผ์—์„œ ํ”Œ๋Ÿฌ๊ทธ์ธ์— ์ถ”๊ฐ€ํ•ด์ฃผ๋ฉด ๋œ๋‹ค. ๊ฐ€์žฅ ๊ฐ„๋‹จํ•˜๋‹ค.

// webpack.config.js  
const Dotenv = require("dotenv-webpack");

module.exports = {
  ...
  plugins: [
      new Dotenv(),
  ]
}

๋ฒˆ์™ธ. CRA๋กœ ๋งŒ๋“  ํ”„๋กœ์ ํŠธ์—์„œ ํ™˜๊ฒฝ๋ณ€์ˆ˜ ์‚ฌ์šฉํ•˜๊ธฐ

create-react-app ์œผ๋กœ ๋งŒ๋“  React ํ”„๋กœ์ ํŠธ์—๋Š” ์ด๋ฏธ dotenv ํŒจํ‚ค์ง€๊ฐ€ ๋‚ด์žฅ๋˜์–ด ์žˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋ณ„๋„์˜ ํŒจํ‚ค์ง€ ์ถ”๊ฐ€๋‚˜ Webpack์— ๋Œ€ํ•œ ์„ค์ • ์—†์ด, .env ํŒŒ์ผ์„ ์ƒ์„ฑํ•ด์„œ ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•˜๋Š” ๊ฒƒ๋งŒ์œผ๋กœ๋„ ํ™˜๊ฒฝ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

๋‹จ, CRA๊ฐ€ ๋‚ด๋ถ€์ ์œผ๋กœ REACT_APP_ ์œผ๋กœ ์‹œ์ž‘ํ•˜๋Š” ํ™˜๊ฒฝ๋ณ€์ˆ˜๋งŒ ์ฝ์–ด๋“ค์ด๋„๋ก ์„ค์ •์„ ํ•ด๋‘์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ๋ณ€์ˆ˜๋ช…์€ ๋ฐ˜๋“œ์‹œ REACT_APP_ ์œผ๋กœ ์‹œ์ž‘ํ•ด์•ผ ํ•จ์„ ์œ ์˜ํ•  ๊ฒƒ!

์ฐธ๊ณ 

React์™€ Node.js์˜ ๊ด€๊ณ„๋Š” ์ซŒ ๊ฑด๋„ˆ๊ฑด๋„ˆ(?)์—์š”
Webpack: process.env undefined using DefinePlugin and DotEnv