수 GB 의 node_modules와 함께 typescript 서버 배포하기

Posted on December 27, 2024 by 주형
Tags: ,

번들링은 보통 프론트엔드 타입스크립트(자바스크립트) 코드를 배포할 때 묶어주는 걸 말합니다. 하지만 간혹 백엔드서도 필요할 때가 있습니다. 이를 알아볼게요.

이상적인 TypeScript 배포

타입스크립트로 작성한 서버는 보통 node_modules 와 함께 배포하면 됩니다. 모든 게 이상적인 상황이라면 package.json의 dependencies에는 백엔드 코드가 사용하는 라이브러리코드가 포함됩니다. 이 라이브러리들과 함께 배포하면 문제가 없죠.

참kvyv npm install --production 을 실행하면 devDependencies 는 설치되지 않고 dependencies 에 명시된 라이브러리만 설치됩니다. 이를 이용해서 타입스크립트 빌드할 때만 필요한 라이브러리들이 프로덕션에 포함되지 않게 할 수 있습니다.

이상적이지 않은 상황

하지만 살다 보면 이상적이지 않은 상황들도 만나게 됩니다. 최근 두가지 이유로 이상적이지 않은 상황을 만났어요. 하나는 eliza 라는 ai library가 특정 기능에서만 사용하는 거대한 라이브러리를 잔뜩 사용하는 것이었어요. 다른 상황은 mono repo와 관련된 상황입니다. 하나씩 만나볼게요.

거대한 라이브러리 의존성

지금 시점에 활발하게 바뀌고 있는 eliza 라는 ai library는 매우 많은 기능을 선택적으로 제공합니다. sqlite3나 postgresql과 같은 database를 선택할 수 있고, 직접 chromium web browser를 통해 데이터를 읽어올 수 있고, 직접 llama ai 모델을 돌릴 수도 있습니다. 이 모든 일을 하기 위한 것들이 dependency에 추가되어있어요. plugin 으로 쪼개진 것들은 사용 안했을 때 import가 안되기도 하지만, 여전히 많은 dpenedency가 사용하지 않더라도 필수적으로 설치가 됩니다.

이렇게 되면 node_modules를 배포하는 게 부담이 커집니다. 2-3 GB는 쉽게 넘어가게되어요. 배포과정에 시간이 꽤 늘어납니다.

mono repo에서 여러 서비스를 운영할 때

여러 서비스를 하나의 node package로 관리하는 경우도 문제가 생기기 쉽습니다. 회사에서 진행한 프로젝트 중에서 하나의 package에서 웹서버와 백그라운드 서버 두 개의 코드가 섞여있는 프로젝트가 있었습니다. 웹 서버는 유저의 웹 요청에 대응하는 서버고, 백그라운드 서버는 주기적으로 돌아가는 코드를 돌리는 서버였어요. 많은 코드가 공유되지만 분명히 web server에서만 사용하는 라이브러리와 백그라운드에서 사용하는 라이브러리가 별개로 있었습니다. 각각을 배포할 때 의도치 않게 사용하지 않는 라이브러리들도 같이 포함되었어요.

bundling의 사용

이 때 bundling 을 사용해서 문제를 해결할 수 있습니다. bundling을 할 때 node modules 의 라이브러리를 포함시킬 수도 있고, external 등의 설정을 통해서 라이브러리를 포함시키지 않을 수 있습니다. esbuild 나 ncc 같은 도구를 사용하면 별다른 설정을 하지 않고도 특정 파일이 import 하는 라이브러리만 같이 bundling되게 할 수 있습니다.

목적이 무엇인가

bundling 이 만능은 아닙니다. nodejs 라이브러리들은 브라우저에서 사용하는 라이브러리들에 비해 자유로워요. c++ addon 을 사용할 수도 있고, path 기반으로 파일들을 import할 수도 있습니다. 갑작스럽게 이상하게 동작하는 현상을 만날 수도 있어요.

결국엔 원하는 게 무엇인지 잘 선택해야합니다. 보수적으로 node_modules를 전부 같이 배포하는 것도 좋은 방법입니다. 프로젝트가 필요로하는 라이브러리만 import하는 것도 좋은 방법이구요. 저는 배포에 걸리는 시간을 줄이기 위해서 필요한 library 만 import하는 방법을 좀 더 자주 사용하고 있습니다.