문제점
우리 사이트는 호스팅 서버에서 npm start 명령어를 통해 배포되고 있었다. 이는 개발 모드로 실행되는 스크립트로, 최적화가 전혀 이루어지지 않아 리소스 크기가 비효율적으로 크고 페이지 로드 시간이 길어지는 문제가 발생했다. LightHouse를 통해 성능을 측정한 결과, 웹 페이지의 리소스 크기가 13MB에 달했고, 이는 사용자 경험에 부정적인 영향을 미칠 가능성이 있었다.
얼마나 많은 용량을 최적화할 수 있는지 확인하기 위해 로컬에서
yarn start
와 yarn build
를 비교해보았다. (우리 페이지 중 가장 많은 리소스(이미지 및 영상)가 있는 사용법 페이지를 예시로 들었다.)로컬에서 yarn start 실행한 경우



로컬에서 build 하여 serve를 통해 배포한 경우



역시 빌드를 하면 파일 리소스가 크게 줄어든 모습을 볼 수 있다.
리소스: 13.1MB → 7.5MB (42.75% 감소)
완료시간: 5.42sec → 5.25sec (3.14% 감소)
DOMContentLoaded: 245ms → 77ms (68.57% 감소)
Load: 432ms → 274ms (36.57% 감소)
DOMContentLoaded 시간이 245ms에서 77ms로 감소하면서 페이지 초기 렌더링 속도가 빨라지고, 이는 사용자가 더 빠르게 콘텐츠에 접근할 수 있게 됐다!
의문점
왜 개발 모드(yarn start
)에서는 리소스가 최적화되지 않는 것일까? 또한, 배포 모드(yarn build
)와 어떤 점이 다를까? 이를 확인하기 위해 CRA 프로젝트에서의 start script 파일을 분석해보았다.
다음 링크를 확인해보면 start 스크립트 실행시 어떤 일이 일어나는지 확인할 수 있다.
GitHubcreate-react-app/packages/react-scripts/scripts/start.js at main · facebook/create-react-app

create-react-app/packages/react-scripts/scripts/start.js at main · facebook/create-react-app
Set up a modern web app by running one command. Contribute to facebook/create-react-app development by creating an account on GitHub.
// Serve webpack assets generated by the compiler over a web server. const serverConfig = { ...createDevServerConfig(proxyConfig, urls.lanUrlForConfig), host: HOST, port, }; const devServer = new WebpackDevServer(serverConfig, compiler); // Launch WebpackDevServer. devServer.startCallback(() => { if (isInteractive) { clearConsole(); } if (env.raw.FAST_REFRESH && semver.lt(react.version, '16.10.0')) { console.log( chalk.yellow( `Fast Refresh requires React 16.10 or higher. You are using React ${react.version}.` ) ); } console.log(chalk.cyan('Starting the development server...\\n')); openBrowser(urls.localUrlForBrowser); });
위 코드는 start 스크립트 실행시 webpack의 devServer인스턴를 생성하고 실행한다.
바로 이 장면이다.
그래서 개발 환경에서는 왜 최적화가 안 되는건데?
devServer는 기본적으로 config 와 compiler를 파라미터로 받아서 생성된다.
const devServer = new WebpackDevServer(serverConfig, compiler);
이때 최적화와 관련된 세부사항은 compiler 의 config에 작성되어 있다.
const configFactory = require('../config/webpack.config'); . . . const config = configFactory('development'); . . . // Create a webpack compiler that is configured with custom messages. const compiler = createCompiler({ appName, config, urls, useYarn, useTypeScript, webpack, });
config는 webpack.config라는 파일에 정의되어 있다!

create-react-app/packages/react-scripts/config/webpack.config.js at main · facebook/create-react-app
Set up a modern web app by running one command. Contribute to facebook/create-react-app development by creating an account on GitHub.
이곳에서 어떤 방식으로 컴파일러를 정의하는지 살펴보았더니
const isEnvDevelopment = webpackEnv === 'development'; const isEnvProduction = webpackEnv === 'production';
먼저
isEnvDevelopment
와 isEnvProduction
변수를 통해 컴파일러 설정을 개발 환경과 배포 환경을 다르게 설정했다. 그리고 실제로 최적화 하는 부분에서
isEnvProduction
가 true
인 경우! 즉 production 환경에서만 최적화를 진행한다.optimization: { // isEnvProduction이 true일 때만 최적화를 실시 minimize: isEnvProduction, minimizer: [ // TerserPlugin: JavaScript 파일 최적화 new TerserPlugin({ terserOptions: { parse: { ecma: 8 }, compress: { ecma: 5 }, mangle: { safari10: true }, output: { comments: false, ascii_only: true }, }, }), // CssMinimizerPlugin: CSS 파일 최적화 new CssMinimizerPlugin(), ], },
위와 같이 TerserPlugin을 통해 JS 파일을 최적화 한다. 그리고 CssMinimizerPlugin를 통해 CSS 파일을 최적화 한다!!
내 의문점이 풀리는 순간이었다.
정리하자면!
CRA 환경에서
yarn start
및 npm start
명령어는 개발 모드로 실행되며, Webpack DevServer를 설정하고 실행하는 과정에서 컴파일러가 development 모드로 작동한다는 사실을 확인했다. 이때 development 모드에서는 디버깅 편의성을 위해 최적화 과정을 비활성화한다. 따라서 리소스 크기와 성능 면에서 최적화가 이루어지지 않는 것이 자연스러운 동작임을 알게 되었다.느낀점
KUMAP을 배포하면서 발생한 이슈들을 해결하려다 보니, 개발 모드와 배포 모드의 차이를 깊이 이해하게 되었다.
개발 모드에서는 최적화가 이루어지지 않지만, 대신 디버깅을 위한 source map과 hot reloading 기능 덕분에 더 빠르고 쾌적한 개발 환경을 제공한다는 점을 확실히 알게 되었다.
배포 모드로 전환하면서 최적화가 어떻게 적용되는지 직접 경험해 보니, 개발 환경과 배포 환경을 구분하는 이유가 명확해졌다. 앞으로는 이런 차이점을 잘 활용해 더 효율적인 개발과 배포를 할 수 있을 것 같다.
MASTER 하는 그날까지~!