[개발환경] webpack(9)

jiseong·2021년 11월 15일
0

T I Learned

목록 보기
131/291
post-custom-banner

웹팩은 개발용 서버를 제공해주는 것 뿐만 아니라 Mock api도 제공한다.

이를 사용하기 위해서 devServer의 onBeforeSetupMiddleware 속성을 이용하면 된다.

Mock api

  • onAfterSetupMiddleware: 다른 모든 미들웨어 이후에 커스텀 미들웨어를 실행할 수 있는 기능을 제공한다.

  • onBeforeSetupMiddleware: 다른 모든 미들웨어보다 먼저 실행할 수 있는 기능을 제공한다.

( 여기서 언급되는 미들웨어는 Express의 미들웨어를 생각하면된다. )

웹팩 설정파일 및 결과

// webpack.config.js
module.exports = {
    devServer: {
      port: 9000,
      client: {
        overlay: true,
      },

      onBeforeSetupMiddleware: function (devServer) {
        if (!devServer) {
          throw new Error('webpack-dev-server is not defined');
        }

        devServer.app.get("/api/keywords", (req, res) => {
          res.json([
            { keyword: "이탈리아" },
            { keyword: "세프의요리" },
            { keyword: "제철" },
            { keyword: "홈파티" },
          ])
        });

      },
    },
}

설정한 url로 요청하면 mock data를 얻을 수 있게 된다.

하지만 mock api에 대한 요청이 많게 되면 해당 웹팩 설정 파일의 코드가 길어지게 될텐데 이를 분리해주는 패키지가 존재한다.

connect-api-mocker

connect-api-mocker 패키지는 특정 폴더를 만들어 api 응답을 담은 파일을 저장하면 이 폴더를 api로 제공해준다.

connect-api-mocker 설치

$ npm i -D connect-api-mocker

특정 폴더 생성 및 웹팩 설정파일

1) 특정 폴더 생성
  • 루트 경로에 mocks/api/ 폴더를 생성하였고 그 안에서 API 응답 파일들을 생성하였다.

2) 웹팩 설정파일
  • devServer.app.use의 첫번째 인자를 이용하여 api로 들어온 요청에 대해 두번째 인자로 지정한 목업파일 경로의 api응답을 할 수 있도록 설정하였다.
// webpack.config.js:
const apiMocker = require("connect-api-mocker")

module.exports = {
  devServer: {
    port: 9000,
    client: {
      overlay: true,
    },

    onBeforeSetupMiddleware: function (devServer) {
      if (!devServer) {
        throw new Error('webpack-dev-server is not defined');
      }

      devServer.app.use(apiMocker('/api', 'mocks/api'));
    },
  },
}

결과

mock data가 잘 받아지는것을 확인 할 수 있었다.

// app.js:
document.addEventListener('DOMContentLoaded', async () => {
  const ul = document.querySelector('#list');

  const res = await axios.get("/api/keywords");

  ul.innerHTML= (res.data || []).map(item => {
    return `<li>${item.keyword}</li>`;
  }).join('');
});

실제 서버와 연동

위에서 사용했던 로컬환경이 아닌 실제 서버와 연동을 하게되면 CORS정책으로 인한 오류가 발생하게 되는데 이를 해결하기 위해서 웹팩 설정파일의 proxy 속성을 이용하면 된다.

CORS
브라우져와 서버간의 보안상의 정책으로 브라우저가 최초로 접속한 서버에서만 ajax 요청을 할 수 있다.

만약 백엔드가 localhost:3000에서 돌아가고 있다면, 아래와 같은 설정을 통해 브라우저에서 벗어나 웹팩 개발 서버에서 서버(백엔드)로 요청할 수 있어 CORS 에러가 나지 않게된다.

// webpack.config.js
module.exports = {
  devServer: {
    proxy: {
      "/api": "http://localhost:3000", // 프록시
      // changeOrigin: true // 가상이름일 경우
    },
  },
}

만약 도메인 이름이 IP주소가 아니라 가상이름일 경우에 changeOrigin: true 옵션을 추가로 작성해줘야한다.

핫 모듈 리플레이스먼트

현재는 코드가 변화하면 전체화면을 갱신한다.
SPA에서는 리프레시가 되면 데이터가 날라가기 때문에 이를 방지하기 위해 웹팩 개발서버에서 제공해주는 옵션인 hot 옵션을 사용해야 한다.

// webpack.config.js:
module.exports = {
  devServer = {
    hot: true,
  },
}

hot 옵션을 true로 주면 웹팩 서버의 HMR가 활성화된다.

그리고 추가적으로 Hot Module Replacement(모든 종류의 모듈을 새로고침 할 필요 없이 런타임에 업데이트) interface를 사용해야 한다.

HMR은 프로덕션용이 아니므로 개발용으로만 사용

hot 옵션 적용 전

위와 같은 상황에서 list에 대한 코드를 변화하면 검색한 키워드가 날라가게 된다.

hot 옵션 적용 후

위와 같은 상황에서 list에 대한 코드를 변화해도 검색한 키워드가 날라가지 않는다.

샘플 코드:

import './style.scss';
import form from './form';
import list from './list';

document.addEventListener('DOMContentLoaded', async () => {
  const ulEl = document.querySelector('#list');
  const formEl = document.createElement('div');
  
  formEl.innerHTML = form.render();
  document.body.appendChild(formEl);

  ulEl.innerHTML= await list.render();

  // Hot Module Replacement interface를 사용
  if (module.hot) {
    module.hot.accept("./list", async () => {
      console.log("list 모듈 변경됨");
      ulEl.innerHTML= await list.render();
    })
  }
});

이러한 방식으로 react-hot-loader, style-loader, file-loader등도 핫 모듈 리플레이스먼트를 지원한다.


Reference

post-custom-banner

0개의 댓글