핫 모듈 리플레이스먼트
배경
웹팩 개발서버는 코드의 변화를 감지해서 전체 화면을 갱신
하기 때문에 개발 속도를 높일 수 있다.
하지만 어떤 상황에서는 전체 화면을 갱신하는 것이 좀 불편한 경우도 있다.
싱글페이지어플리케이션(SPA)은 브라우져에서 데이터를 들고 있기 때문에 리프레시 후에 모든 데이터가 초기화 되어 버리기 때문이다. 다른 부분을 수정했는데 입력한 폼 데이터가 날아가 버리는 경우도 있고 말이다.
예를 들면,
- app.js
1
2
3
4
5
6
7
8
9
10
11
12
13
import form from "./form";
import result from "./result";
document.addEventListener("DOMContentLoaded", async () => {
const formEl = document.createElement("div");
formEl.innerHTML = form.render();
document.body.appendChild(formEl);
const resultEl = document.createElement("div");
resultEl.innerHTML = await result.render();
document.body.appendChild(resultEl);
});
- form.js
1
2
3
4
5
6
7
8
9
10
11
12
13
const form = {
render() {
return `
<form>
<input />
<button type="submit">검색</button>
<button type="reset">취소</button>
</form>
`;
}
};
export default form;
- result.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import axios from "axios";
const result = {
async render() {
const res = await axios.get("/api/users");
return (res.data || [])
.map(user => {
return `<div>${user.id}: ${user.name}</div>`;
})
.join("");
}
};
export default result;
app 모듈은 form모듈과 result 모듈을 import로 가져와서 body부분에 렌더링해주는 역할을 담당하고 있다.
웹팩 서버를 기동하면 아래 이미지와 같은 화면이 나올 것이다.
만약 검색창에 아래 이미지와 같이 입력하고 result 모듈을 의 내용을 수정하면 form모듈까지 다시 렌더링되면 검색창의 데이터가 사라지는 것을 볼 수 있다.
전체 화면 갱신 하지 않고 변경한 모듈만 바꿔치기 한다면 어떨까? 핫 모듈 리플레이스먼트는 이러한 목적으로 제공되는 웹팩 개발서버의 한 기능이다.
핫로딩 설정
설정은 간단하다. devServer.hot 속성을 켠다.
- webpack.config.js
1
2
3
4
5
module.exports = {
devServer = {
hot: true,
},
}
그 다음 app.js에 아래 코드를 추가한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
...
if (module.hot) {
console.log("핫 모듈 커짐");
module.hot.accept("./result", async () => {
console.log("result 모듈 변경됨");
resultEl.innerHTML = await result.render();
});
module.hot.accept("./form", () => {
formEl.innerHTML = form.render();
});
}
그리고 나서 웹팩 서버를 기동한 하고 검색창에 데이터를 입력 후 result 모듈을 변경해보자. 그럼 form 모듈은 그대로 유지한체 result모듈만 렌더링 되는 것을 확인할 수 있다.
devServer.hot
옵션을 켜면 웹팩 개발 서버 위에서 module.hot 객체가 생성
된다. 이 객체의 accept() 메소드는 감시할 모듈과 콜백 함수를 인자로 받는다. 위에서는 form 모듈과 result 모듈을 감시하고 변경이 있으면 전달한 콜백 함수가 동작하여 새로 렌더링 하도록 설정해주었다.
이렇게 핫 모듈 리플레이스먼트를 사용하면 변경된 부분만 새로 렌더링되게끔하여 좀 더 개발 생산성을 향상 시킬 수 있다.
핫로딩을 지원하는 로더
웹팩 설정의 hot설정을 true로 지정하는 것 뿐만 아니라, HMR 인터페이스를 구현한 로더만이 핫 로딩을 지원한다
위 실습에서 다음과 같이 HMR 인터페이스를 맞춰주었다.
- app.js
1
2
3
4
5
6
7
8
9
10
11
12
if (module.hot) {
console.log("핫 모듈 커짐");
module.hot.accept("./result", async () => {
console.log("result 모듈 변경됨");
resultEl.innerHTML = await result.render();
});
module.hot.accept("./form", () => {
formEl.innerHTML = form.render();
});
}
웹팩 기본편에서 보았던 style-loader
또한 HMR인터페이스를 구현하여 핫로딩을 지원한다.
style-loader의 코드를 보면 hot.accept()
함수를 사용한 것을 알 수 있다.
출처: https://jeonghwan-kim.github.io/series/2020/01/02/frontend-dev-env-webpack-intermediate.html
이 외에도 리액트를 지원하는 react-hot-loader, 파일을 지원하는 file-loader는 핫 모듈 리플레이스먼트를 지원하는데 여기를 참고하자.
Note: 만약 리액트나 뷰를 사용한다면 각 프레임워크에 맞게 핫로딩을 설정해주면 된다. 기본적인 style-loader, filer-loader 등은 왠만하면 다 이미 설정되어 있다.