우연히 글을 보다가 정리해두면 좋겠다 싶어서 정리하게 되었다.
정리하게 된 계기
React18 + StrictMode에서는 개발모드에서 data fetching이 최소 두 번이상 일어날 수 있다. 이러한 글을 계속 보았지만 왜 그런지 모르고 그냥 그런가보다하고 넘어갔다.
우리가 react를 이용하여 웹 사이트를 구현하고자 할 때 app.js는 기본적으로 생성된다.
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
위와 같이 app.js가 생겼는데, 이를 아래와 같이 바꾸면 두번이나 재랜더링이 되지 않는다.
ReactDOM.render(
<App />,
document.getElementById('root')
);
개념
공식문서에 따르면 strictmode는
StrictMode는 애플리케이션 내의 잠재적인 문제를 알아내기 위한 도구입니다. Fragment 와 같이 UI를 렌더링하지 않으며, 자손들에 대한 부가적인 검사와 경고를 활성화합니다.
이렇게 개념이 정리되어 있고, 이는 개발모드에서만 활성화된다고 적혀 있다. 왜 개발모드에서만 활성화되는지 보면
장점
StrictMode는 아래와 같은 부분에서 도움이 됩니다.
- 안전하지 않은 생명주기를 사용하는 컴포넌트 발견
- 레거시 문자열 ref 사용에 대한 경고
- 권장되지 않는 findDOMNode 사용에 대한 경고
- 예상치 못한 부작용 검사
- 레거시 context API 검사
이러한 부분으로 인해 strictmode가 활성화되어 있는 것이다.
1) 안전하지 않은 생명주기를 사용하는 컴포넌트 발견
비동기 React 애플리케이션에서 특정 생명주기 메서드들은 안전하지 않다. 하지만 애플리케이션이 서드 파티 라이브러리를 사용한다면, 해당 생명주기 메서드가 사용되지 않는다고 장담하기 어렵다. Strict 모드는 이러한 경우에 도움이 된다!
Strict 모드가 활성화되면, React는 안전하지 않은 생명주기 메서드를 사용하는 모든 클래스 컴포넌트 목록을 정리해 다음과 같이 컴포넌트에 대한 정보가 담긴 경고 로그를 출력한다.
Strict 모드에 의해 발견된 문제들을 해결한다면, 향후 릴리즈되는 React에서 concurrent 렌더링의 이점을 얻을 수 있다.
2) 레거시 문자열 ref 사용에 대한 경고
이전의 React에서 레거시 문자열 ref API와 콜백 API라는, ref를 관리하는 두 가지 방법을 제공하였다. 문자열 ref가 사용하기 더 편리했지만 몇몇 단점들이 존재했다. 그래서 공식적으로는 콜백 형태를 사용하는 것을 권장했다.
React 16.3에서는 여러 단점 없이 문자열 ref의 편리함을 제공하는 세 번째 방법을 추가했다.
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.inputRef = React.createRef(); }
render() {
return <input type="text" ref={this.inputRef} />; }
componentDidMount() {
this.inputRef.current.focus(); }
}
이제는 객체 ref가 문자열 ref를 교체하는 용도로 널리 더해졌기 때문에, Strict 모드는 문자열 ref의 사용에 대해 경고한다.
3) 권장되지 않는 findDOMNode 사용에 대한 경고
이전의 React에서 주어진 클래스 인스턴스를 바탕으로 트리를 탐색해 DOM 노드를 찾을 수 있는 findDOMNode를 지원하였다. DOM 노드에 바로 ref를 지정할 수 있기 때문에 보통은 필요하지 않는다.
findDOMNode는 클래스 컴포넌트에서도 사용할 수 있었지만, 부모가 특정 자식이 렌더링되는 것을 요구하는 상황이 허용되어, 추상화 레벨이 무너지게 되었다. 이로 인해 부모가 자식의 DOM 노드에까지 닿을 가능성이 있어 컴포넌트의 세세한 구현을 변경할 수 없게 되어 리팩토링이 어려워지게 되었다. findDOMNode는 항상 첫 번째 자식을 반환하지만, Fragment와 함께 사용할 경우 컴포넌트에서 여러 DOM 노드를 렌더링하게 된다.
findDOMNode는 일회성, 읽기 전용 API로, 물어보았을 때만 값을 반환한다. 자식 컴포넌트가 다른 노드를 렌더링할 경우, 변경 사항에 대응할 방법이 없다. 그러므로, findDOMNode는 항상 변하지 않는, 단일 DOM 노드를 반환하는 컴포넌트에서만 정상적으로 작동해왔다.
ref를 사용해 커스텀 컴포넌트에 ref를 넘겨 DOM까지 닿게 하여, DOM 노드를 감싸는 래퍼를 만들어 ref를 바로 붙이는 것이 가능하다.
class MyComponent extends React.Component {
constructor(props) {
super(props);
this.wrapper = React.createRef();
}
render() {
return <div ref={this.wrapper}>{this.props.children}</div>;
}
}
4) 레거시 context API 검사
모든 16.x 버전에서 여전히 돌아가지만, Strict 모드에서는 아래와 같은 경고 메시지를 노출한다. 이러한 오류가 날 때는 새로운 버전으로 업데이트하는 것을 추천한다.