NOMO.asia

간단한 서버 사이드 렌더링 프로그램 제작을 위해 처음으로 Next.js 를 사용하면서, 기본 Next.js 예제인 page/index.js 에다가 테스트겸 이런저런 패키지와 예제 코드를 가져다가 붙였다. 사용자가 페이지에 접속하면 제3의 백그라운드 어플리케이션을 실행시키려는 의도였다. 그런데 테스트를 해보니 몇몇 모듈을 찾을 수 없다며 에러가 발생했다. 대표적으로 fs, net, tls 같은 모듈과 관련된 오류가 있었다.

Failed to compile
./node_modules/twitch-bot/lib/bot.js
Module not found: Can't resolve 'tls' in 'F:\Google Drive\3. Hobbies\switch_controller\nodejs_server\node_modules\twitch-bot\lib'

그래서 정보를 찾아보니, 로드되는 /page 디렉토리의 js 파일은 최소 "서버"에서 한 번, "클라이언트"에서 한 번 실행되게 되는데, 이 때 클라이언트에서 fs 와 같은 패키지를 쓸 수 없으므로 오류가 나게 되는 것이라고 한다. fs는 PC의 파일 시스템에 바로 접속하여 읽고 쓰기 위한 것이므로 클라이언트(브라우저)에서 바로 실행되는 것이 불가능한 것이었다. 아무래도 나는 그때그때 필요한 코드를 그저 가져다쓰는 식으로 프로그래밍 언어를 사용하다보니 기본적인 것이 부족한 경우가 가끔 있다.

그럼 어떻게 해야할까?

먼저 루트 폴더에 next.config.js 라는 이름의 파일을 만든 후 아래의 내용을 삽입한다. 서버가 아닌 클라이언트에서 경우 fs, net, tls 모듈을 empty 로 취급하겠다는 의미인 듯하다.

module.exports = {
    webpack: (config, {
        isServer
    }) => {
    // Fixes npm packages that depend on `fs, net, tls` module
        if (!isServer) {
            config.node = {
                fs: 'empty',
                net: 'empty',
                tls: 'empty',
                "fs-extra": 'empty'
            }
        }
        return config
    }
}

위와 같이 처리하니 아래와 같은 에러가 발생했다.

Unhandled Rejection (TypeError): tls.TLSSocket is not a constructor

패키지별, 코드별로 발생하는 에러는 다양했다. 어떤 경우에는 아예 그냥 모듈을 찾을 수 없다면서 Module not found: Can't resolve 'fs' in 'F:\~~~~\node_modules\fs-extra\lib' 와 같은 에러가 발생하는 경우도 있었다.

따라서 이와 같은 경우, 해당 코드를 클라이언트에서는 실행되지 않도록 아래와 같이 처리해주면 된다.

//serverside work
if(typeof window === "undefined"){
    console.log("serverside");
    RunTwitchBot();
}

서버사이드에서는 window 객체의 type 이 "undefined" 이다. 브라우저와 같은 클라이언트에서는 "object" 이므로 구분된다.

이러면 오류 발생 없이 깔끔하게 해결되기는 하지만, 내 경우 백그라운드 어플리케이션이 단 한 번 실행되어야 했다. 그래서 결국은 pm2 를 이용해 별도로 프로세스를 실행하여 관리해주기로 하는 것으로 마무리했다.