개발, 배포 환경의 Lighthouse 성능 점수 차이 왜 생기는 걸까? Thumbnail

빌드시 최적화 이해

10 min read
최적화빌드

Development, Production 환경의 Lighthouse 성능 점수 차이 왜 생기는 걸까?

프론트엔드 개발을 하면 성능 측정을 하게 된다. 개발 환경과 배포 환경에서 Lighthouse 도구를 사용해 각각 측정했다. 점수가 생각보다 크게 차이가 나는 것을 발견했다.

썸네일썸네일

개발 환경과 배포 환경이란

웹 개발을 하다보면 개발 환경과 배포 환경을 모두 경험하게 된다. 개발 환경은 실제 개발을 하면서 잦은 디버깅과 빠른 개발을 위한 설정을 지원한다. 반면 배포 환경은 개발 후 만들어진 결과물은 최대한 최적화해야 하는 환경이다.

주요 차이점

개발 환경과 프로덕션 환경은 꽤 명확하고 많은 차이점이 존재한다.

개발환경

HMR (Hot Module Replacement)

개발환경은 빠른 개발을 위해 저장 후 바로 변경사항이 적용되는 HMR(Hot Module Replacement) 기술을 지원한다.

원리는 Replacement라는 단어가 있듯 모듈 전체를 리로드하지 않고, 애플리케이션이 실행되는 동안 교환하는 식으로 추가 or 제거하는 방식이다. React의 리렌더링처럼 변경된 부분만 다시 렌더링되는 느낌이라고 생각하면 쉽다.

vite 같은 번들러들이 이런 기술을 사용해서 개발 환경에서 빠른 빌드를 지원할 수 있게 되었다.

소스맵 (Source Map)

소스맵은 디버깅을 위한 기능이다. 원본 코드 매핑 정보를 담고 있다. 우리가 작성하는 타입스크립트와 리액트 코드들은 모두 브라우저가 읽을 수 있는 자바스크립트로 변환 과정을 거친다.

// 원본 TypeScript 코드 (app.tsx 15번째 줄)
const handleClick = (): void => {
  throw new Error("버튼 클릭 에러!");
};

// 빌드된 JavaScript 코드 (bundle.js 2847번째 줄)
const n=()=>{throw new Error("버튼 클릭 에러!")};

이 경우 원래 내가 작성한 코드가 변하기도 하고, 소스 라인의 수 조차 달라진다. 만약 특정 코드에서 오류를 발생시키고 있다고 가정할 때, 브라우저에서 실행되는 오류 코드의 위치와 실제 내가 작성한 코드의 위치가 불일치 할 가능성이 생긴다.

이를 해결하기 위해 개발 환경에서는 소스맵이라는 매핑 정보를 관리한다. 소스맵이 있다면 브라우저에서 디버깅을 할 수 있게 되는 것이다.

개발용 React

React로 개발을 하다보면 한 번쯤 경험해보는 문제가 있다. 바로 React의 Strict Mode이다. 이건 개발할 때 불필요한 요청이나 렌더링 등을 빠르게 캐치하기 위한 목적으로 만들어져있다.

주요 특징으로는 콘솔 로그가 두 번 찍힌다는 특징이 있다. 그 외에도 추가적인 경고 로직, 검증 로직 등이 개발환경에서만 지원된다.

최적화되지 않은 번들

이 글에서 가장 중요한 내용이다. 개발 환경에서는 번들이 최적화되어있지 않다. 즉, 압축이나 트리 쉐이킹 같은 최적화 기법이 사용되지 않은 환경이라는 뜻이다.

프로덕션 환경 (배포 환경)

개발 환경에서는 주로 디버깅에 치중되어있는 모습을 볼 수 있었다. 그렇다면 성능이 중요시되는 배포 환경에서는 어떨까?

코드 압축

성능이 중요하기 때문에 띄어쓰기 한 칸 조차 아끼는 모습을 볼 수 있다.

// 압축 전 (개발 환경)
function handleUserAuthentication(username, password) {
  if (!username || !password) {
    throw new Error('Username and password are required');
  }
  return authenticateUser(username, password);
}

// 압축 후 (프로덕션)
function h(u,p){if(!u||!p)throw Error('Username and password are required');return a(u,p)}

위 코드처럼 아예 코드를 읽기 힘들게 만드는 코드 난독화 기술도 적용할 수 있다.

✨트리 쉐이킹

개인적으로 가장 중요하다고 생각되는 부분이다. 트리 쉐이킹은 말 그대로 나무를 흔드는 작업이다.

개발 환경에서는 사용하지 않는 코드도 모두 가지고 있지만, 배포 환경에서는 쓰지 않는 코드, 함수, 컴포넌트 등을 모두 제거한다.

// 트리 쉐이킹 예시 추가
import { Button, Modal, Tooltip, DatePicker } from 'antd';
// 실제로는 Button만 사용

// 개발 환경: 모든 컴포넌트 로드
// 프로덕션: Button만 번들에 포함

이렇게 하면 개발 환경에서는 편의성과 디버깅 용이성을, 배포 환경에서는 성능을 모두 챙길 수 있게 된다.

여담으로 최근에 학교 과제로 유니티 게임을 만들어야 할 일이 있었는데, 욕심으로 3D 게임을 만들기로 했다. 이때, 에셋 포함 프로젝트 파일이 8GB나 되었었다.. (초저퀄 주제에..)

하지만 빌드 후 게임 파일은 400MB 밖에 되지 않았다. 사용하지 않는 에셋 등과 빌드 최적화로 95%나 없어진 것이다. 웹에서도 마찬가지라고 생각이 들었다.

번들러 최적화

React 생태계의 번들러는 크게 Webpack, Vite 두가지가 떠오른다.

두 번들러 모두 빌드 과정에서 최적화를 수행하지만 내부적으로 사용하는 기술들이 달라진다. 두 번들러의 차이점에 대해서는 다루지 않지만 모두 코드 스플리팅, 트리 쉐이킹, 코드 압축 등이 최적화를 수행한다.

확인해보자

개발 환경에서 블로그 디테일 페이지의 Lighthouse 점수이다. 보다시피 성능 점수가 50점 아래로 떨어져있는 것을 볼 수 있다. 개발환경개발환경

측정항목도 Total Blocking Time이 1250 ms가 넘어가는 모습이다. 개발환경 측정항목개발환경 측정항목

다음은 배포 환경이다. 아직 개선해야 할 것들이 있지만, 전반적으로 성능 점수가 25점 이상 올랐고, 권장사항 점수도 채워진 걸 볼 수 있다. 배포환경배포환경

개발환경과는 다르게 Total Blocking Time이 크게 줄었고, Speed Index 등 다른 지표들도 같이 감소한 모습이 눈에 띈다. 배포환경 측정항목배포환경 측정항목

트리맵 비교

위처럼 트리맵도 비교해보자. 트리맵은 웹사이트를 구성하는 JavaScript 번들의 크기를 시각적으로 보여주는 목적으로 사용된다.

큰 사각형일 수록 차지하는 용량을 의미해서 쉽게 확인할 수 있는 구조로 되어있다.

먼저 개발환경 부터 보자, 가장 먼저 눈에 띄는 점은 쪼개지지 않은 사각형과 오른쪽 상단의 44Mb라는 용량이다.

개발환경 트리맵개발환경 트리맵

다음은 배포환경의 트리맵이다. 개발환경과는 달리 여러개의 사각형으로 쪼개져있고, 무엇보다 용량의 크기가 2Mb 수준으로 매우 작다는 점이다.

배포환경 트리맵배포환경 트리맵

  • 파일 크기 최적화로 전체 번들이 44Mb 수준에서 2Mb 수준으로 약 94% 감소했다.
  • 코드 스플리팅 최적화로, 기존 코드가 더 작은 여러개의 청크로 분할되어 필요할 때만 로드되도록 만들어졌다.

마무리

지금까지 살펴본 개발 환경과 배포 환경의 구조적 차이로 인해 localhost 개발 환경에서 성능 측정을 했을 때와 배포 환경의 차이를 알아볼 수 있었다.

Vite 같은 번들러의 도움으로 빌드 설정을 크게 고민해보지 않았던 것 같다는 생각이 들었다. 빌드 과정에서 일어나는 최적화를 공부하면 프론트엔드에 대해서 더 이해할 수 있지 않을까 하는 생각이 든다.

이번 글을 통해 개발 환경에서의 성능 측정이 얼마나 실제와 다를 수 있는지 확인할 수 있었다.

핵심 포인트:

  • 성능 측정은 반드시 프로덕션 환경에서
  • 트리 쉐이킹의 놀라운 최적화 효과 (94% 크기 감소)
  • 로컬에서도 npm run build && npm start로 확인 가능

📌 Table of Contents

0
추천 글