알아두면 유용한 react 개념 5가지

Q&A 큐레이션

1. useCallback vs 컴포넌트 밖에 선언된 함수

React를 공부하다가 궁금한점이 생겨서 질문 남깁니다 useCallback은 의존성 배열의 값이 바뀌지 않는한 같은 함수를 반환하는 것으로 알고있습니다. react 컴포넌트 안에서 선언되는 함수는 useCallback의 의존성 배열에 추가해야되는 것을 이해하겠는데, react 컴포넌트 밖에서 선언되는 함수도 useCallback의 의존성 배열에 추가를 해야하나요? 혹시 성능 차이가 날까요?


답변

안녕하세요! 컴포넌트 밖에 선언되는 함수는 렌더 시 매번 새로 선언되지는 않으니 의존성 배열에 넣을 필요가 없지 않을까 싶습니다. (처음 파일을 읽을때 선언된 이후로 안 바뀔 것으로 예상합니다) 성능 차이는 코드마다 다르겠지만 그렇게 크지는 않을것 같아요. 관련해서 so나 테크 블로그 참고해보시면 좋을 것 같아요. - https://stackoverflow.com/questions/60660415/performance-difference-from-putting-function-outside-of-react-component - https://alexsidorenko.com/blog/react-render-usecallback/

외 1개 답변

모두 보기

2. React 객체 기본값 처리 어떻게 하시나요?

React로 프로젝트를 하면서 객체에서 값을 꺼내서 사용해야 할 일이 자주 있는데요, 객체에 값이 없거나 키를 잘못 전달받았을 경우를 대비해 주로 기본값을 지정해주고 있습니다. 코드를 작성하다보니까 기본값을 다양한 방법으로 지정하고 있는데 방법마다 차이가 있는지? 궁금해져서 질문 드립니다. 제가 쓰는 방식들 코드로 간단하게 정리해서 첨부합니다. 각 방법이 선호되는 경우나 우려되는 점이 있는지, 혹시 다른 분들이 주로 쓰는 방법이 있는지 등 관련된 어떤 의견이라도 좋으니 다양하게 듣고싶습니다!


답변

default key로 정의한 값이 사실상 사용하지 않는, 코드상 오류를 방지하기 위함이라면 key를 enum으로 정의하고 받아서 dataMap의 key가 enum이 되는것도 방법인것 같습니다. 그러면 그 외의 값이 내려오지 않도록 좀 더 type-safe하게 관리될 수 있을것 같습니다. 또 한가지는 _와 같이 lodash의 get을 사용해 default value를 넣어주고 계신것 같은데, lodash get의 소스코드를 보고 구현방법을 파악해보는 방법도 있습니다. 저라면 lodash처럼 크기가 큰 라이브러리를 사용하지 않고 key로 조회 후 없다면 defaultValue로 넣어주는 ||(or) 을 쓸 것 같습니다. const data = dataMap[key] || defaultValue; 그리고 typescript를 쓴다면 위와 같은 에러가 발생하지 않도록 더 타이트하게 코드를 짤 수 있습니다.

모두 보기

3. useLayoutEffect는 언제 쓰는건가요?

안녕하세요~ 이번에 코드 리뷰를 받았는데 "useEffect 대신 useLayoutEffect를 쓰는게 좋아요~" 라는 피드백을 받았습니다. 코드 구조는 컴포넌트에서 ref를 선언한 후 useEffect로 해당 값을 바꾸고, 추후 다른 컴포넌트의 훅에서 이 ref 값을 참조해서 로직이 돌아가는 형태였습니다 (회사 코드라 첨부를 할 수가 없네요...ㅠㅜ) 그런데 왜 useEffect 대신에 useLayoutEffect를 써야하는지 잘 모르겠더라구요. 혹시 이유를 아시는분 있나요?


답변

안녕하세요! 음, 코드가 어떤지 몰라서 정확한 이유는 알 수 없지만 아마도 렌더 직후, 브라우저가 새로운 창을 그리기 전에 돌아가야하는 로직이여서 그런 것 아닐까요? useEffect는 브라우저가 스크린을 보여주고 난 뒤에 실행되고 useLayoutEffect는 React가 DOM을 업데이트하고 브라우저가 스크린을 다시 그리기 전에 실행됩니다. hooks-flow 한번 참고해보세요!

모두 보기

4. useRef의 작동방식이 궁금합니다

useRef를 통해 dom element에 접근하기도 하고, stale closure문제를 해결하는데에도 사용하는데, 실질적으로 어떻게 작동해서 이게 가능한지 궁금합니다.


답변

안녕하세요! useRef를 통해 만들어지는 것은 JS의 객체와 유사하다고 보면 됩니다. useRef를 통해 만든 값이 일반 객체와 다른점은, 매 렌더링 시 동일한 객체를 제공하는 것입니다. - useRef<T>(initialValue: T): {current: T} - (참고: https://github.com/facebook/react/blob/fd31724d5d41a4df71af55f710b46562874511f9/packages/react-reconciler/src/ReactInternalTypes.js#L388) - (참고: https://ko.reactjs.org/docs/hooks-reference.html#useref) useRef를 통해 받은 값은 useRef가 사용된 컴포넌트의 라이프사이클 동안 사용할 수 있습니다. JSX에 특정 DOM 컴포넌트에 ref={useRef를 통해 받은 값}을 추가하시게 되면, 컴파일러가 JSX를 컴파일하면서 JS로 변환을 시켜주고 해당 JS를 브라우저가 실행하면서 값을 채워넣어주는 것으로 알고있습니다. (참고: https://ko.reactjs.org/docs/jsx-in-depth.html) stale closure의 경우는 useRef의 값이 항상 같은 객체이고 closure안에서는 이 객체를 "참조"하는 형식이기 때문에, 객체의 current 값이 바뀌면 closure 안에서도 바뀐 current 값을 사용할 수 있습니다. (reference 관련 so 글 참고: https://stackoverflow.com/questions/8318357/javascript-pointer-reference-craziness-can-someone-explain-this) 저도 질문에 답변하려고 여러가지 실험들을 해보았는데요. Functional component로 gist를 한번 만들어보았습니다. 저도 헷갈리는 부분이 있긴하지만 확실히 일반 JS 객체 대신 왜 useRef를 사용해야하는 이유를 알게된 것 같네요. (https://gist.github.com/json9512/ef28abf2429c639ccbdd6b48c7c3efe5) 결론은 useRef의 동작 방식이 가능한 이유는 JS에서 객체를 접근할때 참조 형식으로 접근한다는 점과 useRef를 통해 받은 객체가 항상 동일하다는 점 때문인 것 같습니다. 제가 참고했던 아티클들 첨부할게요. - https://dmitripavlutin.com/react-useref-guide/ - https://www.freecodecamp.org/news/react-under-the-hood/ - https://www.smashingmagazine.com/2020/11/react-useref-hook/ - https://developer.mozilla.org/ko/docs/Web/JavaScript/Guide/Working_with_Objects#%EA%B0%9D%EC%B2%B4_%EA%B0%9C%EC%9A%94 - https://hewonjeong.github.io/deep-dive-how-do-react-hooks-really-work-ko/

모두 보기

5. useState에서 const를 사용하는 이유는 뭔가요?

react를 사용할때 useState hook을 많이 사용하는데요 const [count, setCount] = useState(0) 이렇게 사용하고 setCount를 이용해서 count가 변화가 되는데 왜 const를 사용하는 걸까요?! let [count, setCount] = useState(0)가 더 맞는거같은 기분입니다.


답변

평소에 아무 생각없이 사용하는 경우가 많았는데 이 질문으로 다시 찾아보게 되네요! - https://dudghsx.tistory.com/18 - https://hewonjeong.github.io/deep-dive-how-do-react-hooks-really-work-ko/ 위의 두 개 링크를 참고해 보면 좋을것 같아요.

외 1개 답변

모두 보기