컴포넌트를 순수하게 유지하기
컴포넌트를 순수하게 유지하기
여러분이 작성하는 함수 중에는 순수 함수가 있어요. 순수 함수는 계산 외의 아무 일도 하지 않아요 — 같은 입력이면 언제나 같은 출력이 나오죠. React 컴포넌트를 순수 함수로만 작성하면, 코드베이스가 커질수록 맞딱뜨리기 쉬운 알 수 없는 버그 한 부류를 통째로 피할 수 있어요.
렌더링은 순수해야 해요
React의 렌더링 과정은 반드시 순수해야 해요. 컴포넌트는 JSX를 돌려줄 뿐, 렌더링 전에 존재하던 객체나 변수를 바꾸면 안 됩니다. 렌더링 밖에서 만든 변수에 값을 쓰는 컴포넌트는 이 규칙을 어긴 대표적인 예시예요. 그럴 때는 컴포넌트 밖의 값을 건드리지 말고, 그 값을 prop으로 받아오면 순수해져요 — 출력이 prop에만 의존하게 되니까요.
강사 관점에서 비유하자면, 렌더링은 학교 시험과 같아요. 각 컴포넌트는 남의 답을 훔쳐보거나 남을 도와주지 않고 자기 스스로 JSX를 계산해야 해요. '같은 입력 → 같은 출력'이 이 규칙의 핵심이에요.
그렇다면 렌더링 중에 읽을 수 있는 입력은 뭘까요? props, state, context 세 가지예요. 사용자 입력에 반응해 무언가를 바꾸고 싶다면 변수에 쓰지 말고 state를 set해야 해요.
지역 변경은 허락돼요
다만 렌더링 중에 만든 같은 렌더링 안의 새 값이라면 자유롭게 바꿔도 돼요. 예를 들어 TeaGathering이 렌더링 도중 자체 배열을 만들어 아이템을 채우는 건, 그 값이 바깥 어디에도 노출되지 않으니 순수성이 깨지지 않아요. 이렇게 컴포넌트 내부에서만 일어나는 변경을 **지역 변경(local mutation)**이라 부르고, '컴포넌트만 아는 작은 비밀'이라고 생각하면 돼요. 문제가 되는 건 렌더링 전부터 있던 객체를 바꾸는 경우예요.
부작용은 어디에서 허용되나요
흥미롭게도 이벤트 핸들러는 예외예요. 핸들러는 컴포넌트 내부에 정의되지만 렌더링 중에는 실행되지 않아요. 버튼 클릭 같은 이벤트에만 반응해 실행되므로, 이벤트 핸들러는 순수할 필요가 없어요. 네트워크 요청이나 화면 전환 같은 부작용은 사용자가 상호작용했을 때 핸들러에서 일으키면 돼요.
요약하면 React가 순수성을 요구하는 이유는, 렌더링이 어떤 순서로 몇 번이나 일어날지 예측할 수 없다는 데 있어요. 순수 컴포넌트다 보면 언제 다시 그려지든 결과가 같아서, 의존 순서 때문에 생기는 버그가 원천적으로 줄어들어요. StrictMode는 개발 중에 렌더링을 의도적으로 두 번 실행해 이런 불순한 컴포넌트를 잡아내는 도구예요.
더 알아보기
- 컴포넌트에 props 전달하기 — 변수 대신 props로 의존성을 넘기는 방법이에요
- State: 컴포넌트의 기억 — 화면을 바꾸려고 객체를 mutate 하는 대신 state를 set 해요
- StrictMode — 불순한 렌더링을 찾아내는 개발용 도구예요