https://ko.reactjs.org/docs/thinking-in-react.html
이 글은 위 페이지의 몇가지 주제에 대해서 자세하게 다루어 보는 글입니다.
이 줄은 React를 처음 접하는 분들이 가장 많이 실수하는 항목중에 하나입니다.
const [password, setPassword] = useState('');
const [valid, setValid] = useState(false);
const onChangePassword = (x: string) => {
setValid(x.length >= 8);
setPassword(x);
};
return (
<>
<input
value={password}
onChange={x => onChangePassword(x.target.value)}
/>
{valid === false && '비밀번호는 8자 이상으로 입력해주세요'}
</>
);
위와 같은 코드, 혹은 비슷한 코드를 작성하는 경우를 흔하게 볼 수 있습니다.
하지만 위 코드는 3번 항목에 어긋납니다.
valid
는 password
값을 가지고 계산할 수 있기 때문에 state로 지정되어야 할 이유가 없습니다.
const [password, setPassword] = useState('');
const valid = password.length >= 8;
어떤 개발자들은 매번 계산하는것보다 state를 사용해 변경될 때만 계산시키고, 결과를 캐싱하는것이 더 좋다고 생각할 수 있습니다.
첫번째로는, 그렇지 않습니다. 대부분의 코드는 매우 빠르게 실행되며 매번 다시 계산하는게 성능에 전혀 영향을 주지 않습니다.
두번쨰로는, 정말 캐싱을 해야 하는 코드가 있을 수도 있습니다. React는 이를 위해 state
가 아닌 useMemo
라는 훅을 제공합니다. 이걸 사용하세요.
const [password, setPassword] = useState('');
const valid = useMemo(() => password.length >= 8, [password]);
세번째로는, state에 대한 얘기는 아닙니다만, 컴포넌트 함수 실행속도를 줄이는 것 보다, 컴포넌트 호출 횟수(re-render)를 줄이는것이 성능에 크게 영향을 미칩니다.
React와 다른 프레임워크(대표적으론 Angular)의 다른점은 양방향-단방향의 차이입니다.
React는 단방향 흐름을 가지고 있으며, 이는 위에서 아래로 내려가는 구조를 뜻합니다.
단방향 흐름이란 단순히 input
의 값이 프레임워크에 의해 자동으로 업데이트 되지 않는 단순한 개념이 아닙니다. 단방향 흐름은 모든 변경을 명시적으로 만들어줍니다.
예를들어 Angular의 가장 단순한 양방향 바인딩 예제를 보세요:
<input [(ngModel)]="name">
name
의 변경은 명시적이지 않습니다. Angular가 알아서 name을 변경해주고 개발자는 이 과정을 알 수 없습니다. (정확히는 몰라도 된다고 표현해야 할 것 같습니다.)
반면 React 는 아래와 같이 처리합니다.
const [name, setName] = useState('');
<input value={name} onChange={e => setName(e.target.value)} />
모든 변경은 명시적입니다. 그러니까 모든 변경은 코드를 작성하는 개발자 에 의해 일어납니다.
React는 단지 이벤트를 날려주거나, 상태를 변경할 수 있는 API만을 제공합니다.
조금 더 구체적인 단방향 흐름에 대한 예시를 들어보도록 하겠습니다.
이것은 단순히 단방향 흐름이 value, onChange
에만 한정되는 사항이 아니라는것을 설명합니다.
일반적인 앱 개발에서 다음과 같은 코드는 꽤 흔합니다.
parentComponent.clearInput();
꼭 parent가 아니라고 하더라도, 다른 컴포넌트의 레퍼런스를 가지고 있고, 해당 컴포넌트의 함수를 직접 호출하는 구조는 굉장히 많이 쓰인다고 할 수 있습니다.
const Child = ({
onClearInput,
}) => {
/* ... */
onClearInput();
};
그게 그거처럼 보일 수 있지만 여기에는 많은 차이가 있습니다.
아직도 잘 이해가 안가신다면 아래의 코드를 한번 보세요.
parentComponent.inputText = '';
이 코드는 parentComponent.clearInput();
보다 더 안좋습니다.
Parent는 Child가 자신의 input 내용이 바꿔놓는걸 인식할 수 조차 없습니다.
안타까운 사실은 일반적인 프로그램에서 위 코드는 얼마든지 가능한 구조이며, 심지어 자주 쓰입니다.
React의 단방향 구조는 이러한 가능성을 원천적으로 차단합니다.
단방향 구조는 어떻게 보면 생산성에서 불리하게 느껴질 수 있습니다만, 더 명확한 코드를 작성하기 위해 React의 개발자들이 채택한 구조입니다.
먼저 역방향 흐름에 대해 확실하게 해야 할 두가지가 있습니다.
React를 처음 접하는 개발자들이 실수하는 잘못된 코드 중 유명한것으론 아래의 케이스가 있습니다.
<EditProfilePopup
name={name}
age={age}
setName={setName}
setAge={setAge}
/>
위 코드는 아래처럼 되어야 합니다.
<EditProfilePopup
name={name}
age={age}
onChangeName={setName}
onChangeAge={setAge}
/>
두 코드는 정말 이름만 다르고, 모든 구현은 똑같습니다.
근데 왜 setName
이 아니라 onChangeName
이 되어야 할까요?
단순히 onChange
로 이름을 짓는것이 아니라, 이 부분에 대해 대답할 수 있어야 React의 단방향 바인딩, 그리고 역방향 흐름에 대해 안다고 할 수 있습니다.
쓰다 말았음
쓰신 글을 쭉 읽어보는데 하나하나가 다 너무 좋은 내용들이네요. 감사합니다!