[React.JS] 강좌 11편 Express.js 서버 + 개발 서버 Hot Module Replacement 사용하기


liste

지금까지, React.js 에 대한 기본적인 공부는 어느정도 마쳤습니다. 이제, REST API 를 만들어서 서버와의 통신에 손을 뻗을 차례입니다! 지금까지는 webpack-dev-server 에만 의존해왔습니다. 이걸로는 서버 작업을 전혀 할 수가 없었죠. 이번 강좌에서는 React.js 를 Node.js 환경의 인기있는 웹프레임워크 중 하나인 Express.js 서버와 함께 사용하는 방법에 대해서 알아보겠습니다.

이 강좌에서는 서버사이드 코드 또한 ES6 으로 작성 할 것이며, 서버가 개발모드 일 때는, Express.js 서버와 webpack-dev-server 를 함께 실행하며, webpack-dev-server 에 proxy를 적용하여 해당 서버에서도 Express.js 서버에 구현된 라우트에 접근 하는 방법을 알아볼것입니다.

지난강좌들에선 기존의 webpack-dev-server 에서 특별한 설정을 하지 않아서 React.js 컴포넌트 코드가 수정 될때 모든 스크립트 자체가 새로고침 됐었는데요, 이번강좌에서는 더 나아가 react-hot-loader 를 적용하여 바뀐 컴포넌트만 리로딩하는 방법을 배우겠습니다.

주의: 이 강좌에서는 Express.js 에 대한 자세한 설명은 생략할 것입니다. 이에 대한 지식이 부족하신분들은 Express.js 메뉴얼 혹은 제 블로그에 작성된 Node.js 강좌 를 읽어주세요.

# 시작하기

# 로컬모듈 설치

이번 강좌에서는 비어있는 폴더에서부터 프로젝트를 작성하겠습니다.

기존 React.js 프로젝트에서 사용하지 않던 모듈 두가지:

  • express: 웹 프레임워크 모듈
  • react-hot-loader특정 컴포넌트파일만 리로딩 할 수 있게 해주는 모듈

# 글로벌 모듈 설치

babel-cli 모듈은 ES6 문법으로 작성된 코드를 ES5 문법으로 컴파일시켜주는 babel 모듈을 커맨드라인 인터페이스에서 사용 할 수 있게 해줍니다. 이는 나중에 서버사이드 코드를 빌드 할 때 사용됩니다.

이 강좌에서는 package.json 에 빌드스크립트를 작성하고 npm run <script> 기능을 통하여 처리하는 방식을 사용하겠습니다.

babel-cli 를 사용하지 않더라도, Node 버전을 최신버전으로 업그레이드하여 컴파일 과정을 생략해도 되고 (단, 아직 노드 최신버전은 일부모듈들에는 호환되지 않으며, 93% 의 ES6 문법만 호환됩니다. 또는, babel-node 모듈을 사용하여 ES6 코드를 직접 실행하셔도 됩니다. (단, babel-node 는 production 모드에서는 권장되지 않습니다) 그 외에도, gulp 모듈을 설치하여 gulp-babel 을 통하여 컴파일하는 방법도있습니다. gulp 를 아직 잘 모르시고, 사용법을 배우고싶은 분들은 GULP 강좌 를 읽어주세요.


# 설정하기

이 프로젝트의 babel-cli 과 webpack 은 설정파일을 필요로합니다.

# .babelrc

# webpack.config.js


# 디렉토리 이해하기

파일을 먼저 만들고 진행하는것을 선호한다면 다음 명령어를 통해 미리 만드세요.

물론, 강좌를 진행하면서 하나 하나 새로 만들어가도 무방합니다.


# 서버 사이드 코드 작성하기

# server/main.js

# server/routes/posts.js

# 서버 사이드 코드 컴파일 하기

프로젝트 루트 디렉토리에서 이 코드를 통해 컴파일 해보세요. 잘 됐나요?

# 서버 테스트 해보기

서버를 테스팅해봅시다. 현 상태로는 아직 public 폴더를 작성하지 않았으니 빈페이지가 뜨는것이 정상입니다.

한번 http://localhost/hello 페이지를 열어보세요.


# 클라이언트 사이드 코드 작성하기

# public/index.html

# src/App.js

# src/index.js

# webpack 을 통하여 코드를 컴파일하고 합치기

컴파일이 성공적으로 완료됐다면, 한번 다시 서버를 열어서 http://localhost/ 페이지를 열어보세요.

제대로 된 페이지가 뜨나요?


# NPM 스크립트 작성하기

서버 및 클라이언트 사이드 코드 컴파일을 명령어를 그때그때 일일히 입력하기엔 귀찮죠?

간편하게 실행 할 수 있게끔 package.json 파일에서 스크립트를 작성해봅시다.

스크립트를 실행 할 때는 npm run <script-name> 으로 실행합니다.

start 스크립트에선 NODE_ENV 를 production 으로 설정하고 development 스크립트에선 development 로 설정합니다.

Node.js 을 잘 아시는 분에게는 익숙하겠지만, 이 부분은 Node Application 에서 환경 상태를 확인하여,
환경에 따라 다른 작업을 설정하고 싶을 때 사용합니다.

저희는 development 모드일때는 webpack-dev-server 도 함께 실행하도록 설정 할 것입니다.

Window 에서는 NODE_ENV 를 설정하는 방법이 다릅니다:


# 서버사이드 코드 수정하기 – 개발모드 만들기

# 개발모드 전용 webpack 설정파일 작성하기

저희는 webpack-dev-server 에선 다른 config 을 사용 할 것이므로, 새로운 config 파일인 webpack.dev.config.js 를 만들어주세요.

편의를 위하여 기존 파일을 복사하고 필요한 부분만 수정하겠습니다.

왜 다른 config 를 사용하나요?

기존 config 는 output인 bundle.js 를 public 디렉토리에 저장하도록 설정이 되어있습니다.
webpack-dev-server 에서도 동일한 설정을 적용한다면, public 에 있는 파일이 계속 덮어씌워지겠죠? 저희 webpack-dev-server 에선 bundle.js 를 메모리에 저장한후, 나중에 브라우저에서  bundle.js 를 요청 할 시 public 디렉토리에 이미 있는 bundle.js 보다 우선권을 가져서 메모리에 있는걸 리턴하게됩니다.

또한, 추후 react-hot-loader 를 통해 변경된 컴포넌트만 리로드 하는 시스템을 구현할 건데요, production 모드에선 이게 필요하지 않으므로 다른 config 를 설정합니다.

# webpack.dev.config.js

  • LINE 1: webpack 플러그인을 사용하기위하여 해당 모듈을 import 합니다.
  • LINE 5-9: webpack-dev-server 의 hot-module-replacement 를 지원하기위해 entry에 추가해줍니다. webpack-dev-server 의 포트를 7번 줄의 뒷부분에 적어줘야 HMR이 제대로 작동합니다.
  • LINE 12: 메모리에 저장하기 위하여 path를 ‘/’ 로 설정합니다.
  • LINE 16-25: webpack-dev-server 를 위한 설정입니다. proxy 부분은 Express.js 서버 URI를 넣어주어야합니다.
  • LINE 28-31HMR 을 사용하기위한 webpack 플러그인들입니다.
  • LINE 34-43: 바뀐부분은 ‘react-hot’ 로더를 추가한거밖에 없습니다. 단, 여러 모듈을 한꺼번에 적용하기 때문에 babel 을 위하여 따로 query 를 하진 못하고 ? 뒤에 JSON.stringify(query) 를 추가하여 query를 추가합니다.

 

주의: 최근 react-hot-loader 가 업데이트 되어서, 그냥 설치하시면 “react-hot-loader”: “^3.0.0-beta.3” 가 설치됩니다.

설치 하실 때, npm install –save [email protected] 을 하시거나, 버전 3을 쓰고 싶다면 수정을 다음과 같이 하세요:

# 서버 메인파일 수정하기

자, 이제 저희는 NODE_ENV 값이 development 이면 webpack-dev-server를 실행하도록 서버 메인파일을 수정해보겠습니다.

# 테스트하기

다음, 브라우저로 페이지를 열은 후, src/ 디렉토리 내의 App.js를 수정해보세요.

어때요? 페이지가 새로고침 되지 않고도 내용이 변경되었나요? (http://localhost:3001/ 로 들어가세요)

webpack-dev-server 의 주소에서 Express.js 에서 구현한 라우터에 접근해보세요: http://localhost:3001/posts/read/5

잘 됐나요?


마치면서..

수고하셨습니다. 이번 강좌는 Node.js 강좌에 더 가까웠던 것 같군요.

이 포스트에서 사용된 코드는 GitHub 에서 열람가능합니다.

다음 강좌에서는 오늘 만들었던 프로젝트 환경에서 react-router 를 제대로 사용하는 방법과,
Ajax 도구를 통하여 Express.js 서버에서 구현한 REST API 를 사용하여 데이터를 서버와 교류하는 방법에 대해서 알아보겠습니다.

질문이 있거나 포스트에 오탈자가 있으면 언제나 덧글 달아주세요 🙂

 

Reference

  1. “Webpack-dev-server”. Webpack.
  2. “Hot module replacement with webpack”. Webpack.
  3. “React-hot-loader”[email protected]
  4. “Webpack HMR Tutorial”Modern JS with React

liste

  • 오랜만에 놀러왔는데 신규 강좌가 생겼네요~재밌게 잘 봤습니다~^^
    그리고 포스트 예제 코드 중 # server/routes/posts.js <– 에 express 가져올 때 simport라고 해놓으셨는데 오타 맞죠?? ^^;

    • 오타 지적 감사합니다 🙂

  • 설거지의 달인

    좋은 글 감사드립니다. 시간을 많이 절약할 수 있었습니다. (–)(__)

    • 도움이 되어서 영광이에요 🙂

  • Robinson Park

    좋은 강좌 감사드립니다!

  • 박원배

    열정과 노력이 돋보이는 정말 친절한 글들 감사드려요!!

  • Seongkuk Park

    “build”: “babel server –out-dir build && ./node_modules/.bin/webpack”,
    이부분 “build”: “babel server –out-dir build && webpack”, 이렇게 바꿔주시는게 좋을듯 해요~

    전자로 돌려봤는데,
    ‘.’은(는) 내부 또는 외부 명령, 실행할 수 있는 프로그램, 또는..

    이런 명령어 오류가 뜨네요
    github에는 후자로 되어있어서 오류가 안 뜨네요

    오류방지를 위해 고치는것도 좋을거 같아요
    (유저분들이 왠만치 webpack을 글로벌로 깔았을 것을 전제하고..?)

  • Seongkuk Park

    그리고 npm development 치면 아래와 같은 오류가 뜨네요;

    ‘NODE_ENV’은(는) 내부 또는 외부 명령, 실행할 수 있는 프로그램, 또는..

    혹 문제가 무었인지 아시나요??

    • 윈도우는 NODE_ENV=development node ./build/main.js 대신 set NODE_ENV=development&&node ./build/main.js 이렇게 해주세요.

      start도 마찬가지입니다

      추후 이 포스트 수정하겠습니다..

      그나저나 dev때는 nodemon을 사용하게 해줘야했는데 여기서 그걸 까먹었네요 ㅋㅋ

      • Seongkuk Park

        ㅎㅎ 감사합니다 .ㅅ.

  • Seongkuk Park

    오류가 뭔지 찾았습니다.. set NODE_ENV=development && node ./build/main.js 이렇게 세팅을 해주니까
    “development ” 해서 공백까지 같이 세이브되네요..
    그래서 비교 연산자 안 먹혔어요;

    • 넹 ㅋㅋㅋ 거기에 공백이 있으면 안돼요
      근데 공백이 있으면 왜 안되는지 몰랐는데
      그런 이유 때문이였군요

  • Seongkuk Park

    흠.. 하지만 여전히 페이지가 새로고침 안 하고 결과 변경은 안되네요
    그리고 http://localhost:3000/posts/read/5 이렇게 고쳐주시면 더 좋을거 같아요.
    포트 번호 안 입력하니까 페이지가 안 뜨네요.ㅅ.

    • 포트 3001로 들어가보세요

      • Seongkuk Park

        포트 3001 들어가서 했는데 새로고침해야지 변한게 뜨네요ㅜ

  • BJ Kim

    예제 클론 받아서 돌려봤는데 3001 포트에서는 express route로 등록한 posts 로 들어가면 404 에러가 납니다.

    http://localhost:3001/posts/read/5

    GET http://localhost:3001/posts/read/bundle.js 404 (Not Found)

    • 우선 그 문제는 index.html 에 bundle.js 를 불러오는 부분에 아마 ‘./bundle.js’ 이렇게 상대경로를 넣으셨을꺼에요.
      ‘bundle.js’ 로 작성을 하셔야 다른 라우트에섣 잘 불러와질거에요.

      둘째로는.. 최근 변경된 코드가있어요.
      webpack.dev.config.js 에 proxy 설정하는 부분에

      proxy: {
      “**”: “http://localhost:3000”
      }

      이렇게 별이 두개로 변경되었습니다.
      webpack-dev-middleware 가 업그레이드 됐었어요.

  • finrir

    감사합니다.

  • lai on

    리액트 강좌 잘 듣고 있습니다. 조금 주제와 다를지도 모르겠지만 질문해도 될까요?
    React 없이 ExpressJS + webpack으로 개발용 boilderplate를 만들어보고 있습니다.
    index.js에 .scss를 require해서 쓰고 있고 .scss는 .css 파일들을 import하고 있습니다. 이 경우에는 css파일을 수정해도 HMR이 안되네요. 반드시 npm run build를 거쳐야 하는게 상당히 버거로운데 방법이 있을까요?

    • Webpack 의 로더가 제대로 설정이 되어있다면 scss 가 수정 될 때 잘 리로딩이 될거예요
      저의 예제 프로젝트 https://github.com/velopert/saysomething/tree/master/client 에서도 webpack dev server에서 hmr이 잘 되었습니다.

      아, 그리고 참고로 지금 이 게시글의 경우엔 서버파일에서 webpack-dev-server 도 불러와서 개발환경에선 express서버도 열고 개발서버도 열고 하는 방식으로 했는데

      제가 나중에는 결국 클라이언트와 서버 프로젝트를 아예 분리시키는게 낫다는 결론을 내렸습니다.

      • 될성부른나무

        velopert 님 강좌보며 공부하고 있습니다. 클라이언트와 서버프로젝트를 분리하셨다고 하셨는대 그 이유를 여쭈어 봐도 될까요?

        • 우선, 초반에는 이 강좌에서 했었던것처럼, 서버와 클라이언트를 한 패키지 안에서 사용을 했었는데요, 그 이유는 개발환경에서 명령어 한줄로 webpack dev server와 express를 실행하고싶어서였는데요,

          한번 create-react-app을 사용하여 만든 프로젝트에서 여기에서 했던것처럼 해보려고했더니 조금 번거롭더라구요, 그래서 우연히 아예 분리시켜서 진행을 해봤는데 편한점이 여럿 있더라구요.

          1. 클라이언트에서 사용하는 패키지와 서버에서 사용하는 패키지들을 구분 할 수 있다.

          package.json이 다르니, 그냥 바로 확인 할 수 있죠.

          2. 서버를 nodemon으로 실행하기 위해서
          한 파일에서 webpack dev서버와 express를 실행하게 한다면 express 부분이 수정되었을때 불필요한 클라이언트 사이드 코드도 다시 번들링 과정을 거치게됩니다.

          3. 기타… 설정과정이 매우 편하고 구조가 간단해짐. 설정 할 때 하나만 신경 쓰면 되니까 편했던것 같습니다.

          딱히 특별한 이유는 없고 한번 그렇게 해보니까 편했습니다..ㅎㅎ 개발할때는 터미널을 두개 열어서 작업해야하긴 하지만 그래도 괜찮아요.

  • tokata

    여러모로 많이 배워갑니다.
    + npm스크립트 작성할 때 cross-env모듈을 사용하면 윈도우에서 혼동이 좀 줄어들 것 같아요

    • 그것도 괜찮겠네요.
      그런데 이 게시물자체가 좀 outdated 되고있어서…

      시간날때 업데이트 해봐야겠습니다 ㅎㅎ

  • 윤인규

    안녕하세요 초보입니다~~ 궁금한게 있습니다. webpack으로 client쪽을 babel로 bundle.js로 만드는데 server side쪽도 webpack entry point를 다르게 해서하면 위에 babel server out-dir build && webpack 이부분을 webpack만으로도 가능하지 않나요??

  • 강좌 잘 보고있습니다 오타가 있어 제보드립니다

    cp webpack.config.js wepack.dev.config.js

    > cp webpack.config.js webpack.dev.config.js

  • 물외한인

    항상 강좌 잘 보고 있습니다ㅎㅎ
    아래에 게시글이 outdated 되간다는 말씀을 보고 여쭤봅니다. 지금 시점에서 expess로 리액트를 쓰는데 본문에 쓰여진 설명에서 개선되어야 하는 부분이 있을까요?

    • 그냥 제 기준에서 outdates 된것입니다. 더 편한 방법을 알게돼서요.

      1. 이 강좌에서는 Express와 React를 같은 프로젝트 디렉토리 안에서 사용했는데, 차라리 디렉토리를 분리시키는게 더 편하다는 결론을 내렸습니다.

      2. NPM스크립트를 작성할때 환경변수를 설정할때에 윈도우 커맨드와 bash에서 명령어가 다릅니다. cross-env로 처리해도 되지만 새로 script파일을 저장해서 .js 자체에서 환경변수를 설정하는게 저는 더 편한것같습니다.

      요즘은 바빠서 게시물 업데이트를 못하고있습니다. 시간이 좀 나면 전체적으로 업데이트를 좀 할 생각입니다.

  • 김현준

    이거 보면서 따라해봤는데.. 프록시가 제대로 안먹힌건지 몰라도 계속 Error occured while trying to proxy to: localhost:3001/ 라고 에러 나오네요