미지정

도커 상에서 리액트 핫로딩 이용하기

Intro

  • FE 개발시 소스 수정, 빌드, 브라우저 새로 고침의 작업은
    별 것 아니지만 겁나 짜증나는 일이기도 합니다.

  • 리액트 개발환경에서는 webpack-dev-server
    코드 변경을 감지(watch)해서 webpack 재실행으로
    트랜파일되고 브라우저가 자동으로 갱신됩니다.
    (create-react-app을 기반으로 만들어도 들어가 있습니다.)

당시 상황

  • 오피스텔에 인터넷이 없어서 건물에서 무료로 제공하는 와이파이에 기생중이었습니다.

  • 그러다보니 너무 속도가 느려서 npm install 할때마다 짜증이 났었습니다.
    (Acronis 트루이미지로 자주 복원을 하다보니 .. 자주 하게 되더군요)

  • 그런데 특이하게도 구글 드라이브와 도커허브 다운로드속도는 매우 빨랐습니다!
    그래서 도커를 이용하기로 결심합니다~

구상

react app을 시작하는 평범한 Dockerfile입니다.
1
2
3
4
5
6
FROM node:alpine
WORKDIR /usr/src/app
COPY package.json ./
RUN npm install
COPY ./ ./
CMD [ "npm","run","start"]
  • 처음에는 여기서 node_modules를 뺀 부분을
    /usr/src/app에 바인당하면 될거라고 생각했습니다.

어떻게?

  • 그렇습니다. app 밑에 node_modules가 있지요.
  • 이것은 두가지 방법이 있었습니다
    • -v /usr/src/app/node_modules 옵션
      • 일반적으로 -v <호스트 디렉터리>:<컨테이너 디렉터리> 형식으로 사용됩니다.
      • 위처럼 그냥 사용하면 컨테이너의 해당 디렉터리는 /var/lib/docker/vfs/dir/xxxx로 매핑됩니다
        컨테이너 해당 디렉터리를 정확하기 위해서는 다음과 같이 하면 알 수 있습니다.
        1
        sudo docker inspect -f "{{ .Volumes }}" <컨테이너 name>
      • /usr/src/app 바인딩 전에 먼저 하면
        node_modules 바인딩을 피할 수 있습니다
    • .dockerignore
      • .gitignore와 비슷한 역할을 하는 파일로 생각하시면 됩니다
      • 여기에 node_modules/*를 집어 넣으면
        해당 폴더는 도커의 COPY에서 제외됩니다

나는 바보

  • 이때 옆에서 보고 있던 한 사람이 말을 합니다
  • “….왜그러고 있어..COPY를 안하면 되잖아??”
  • 그렇습니다. 여러분은 바보 하나를 보고 계십니다.
바보가 바보임을 자책하며 주석처리한 Dockerfile
1
2
3
4
5
6
7
8
9
FROM node:alpine
WORKDIR /usr/src/app
COPY package.json ./
RUN npm install

# 나는 바보입니다. 나는 바보입니다. 카피를 안하면 되는데 나는 바보입니다.
# COPY ./ ./

CMD [ "npm","run","start"]

현재 폴더 바인딩

  • sh이 되는 mac이나 리눅스에선 $(pwd)로 현재 폴더값을 자동으로 넣을 수 있습니다.
  • 윈도우 환경에선 %CD% 환경변수로 바인딩이 가능합니다.

핫로딩이 안될때의 간단 해결법

  • 멋지게 실행해 봅니다

    멋지게..멋지게..
    1
    docker run --rm -it -p 3000:3000 -v /usr/src/app/node_modules -v %cd%:/usr/src/app rkaehdaos/react1:latest
  • 정상적으로 리액트 앱이 보입니다.

  • 문제는 로컬에서 소스를 고쳐도 반응이 없습니다. 핫로딩이 안되요 !!
    브라우저를 새로 고침해도 마찬가지입니다.

  • 핫로딩이 안되다니.. 혹시나 bind가 잘못되었나 하고
    컨테이너에 exec로 들어가서 확인해도 제대로 된게 맞네요

  • 이떄 희망이 되는 글을 발견하게 됩니다.

    Finally, -e CHOKIDAR_USEPOLLING=true enables a polling mechanism via chokidar (which wraps fs.watch, fs.watchFile, and fsevents) so that hot-reloading will work.

  • chokidar 모듈은
    WebPackBabel이 파일들을 모니터링을 하기 위해 사용하는 모듈로
    create-react-app에도 포함되어있는 모듈입니다.

  • 도커에서 해당 모듈의 polling을 사용하기 위해
    CHOKIDAR_USEPOLLING=true 설정을 해주어야합니다.

  • run 하면서 -e CHOKIDAR_USEPOLLING=true를 하거나
    Dockerfile안에 ENV로 환경변수로 세팅하는 것도 가능합니다.

  • 이렇게 하면 핫로딩이 훌륭하게 잘 작동하는 것을 알 수 있습니다.

쓸데없는 디테일하게 들어가기

chokidar?

A neat wrapper around Node.js fs.watch / fs.watchFile / FSEvents.

  • VSCODE, gulp, webpack등 많은 곳에서 사용 되고 있습니다.

  • MacOS상에서 Darwin FSEvents API 확장 구현체가 사용되며,
    매우 효율적인 watch 효율을 보여준다고 합니다.

  • MacOS 외의 플랫폼에서는 fs.watch 기반 구현체가 기본값인데,
    polling을 최대한 피해서 cpu 부하를 낮추는 구현을 갖추고 있습니다.

  • 그래서 usePolling 기본값이 MacOS에선 true이고, 나머지는 false입니다.
    [참조 레퍼런스]

  • 네트워크를 통한 파일 watch를 성공하기 위해선 이 값이 true여야 합니다

도커에서 돌렸는데 네트워크라고??

Related POST

공유하기