[JS] useEffect에 대한 짧은 가이드
들어가기 전에
이 글은 useEffect API에 대해 어느정도 익숙한 독자를 위한 글입니다.
그리고 오역과 의역이 많을 수 있으니 이상하다 싶은 부분은 원래 문서를 참고해주시기 바랍니다.
A Complete Guide to useEffect - Dan Abramov 에서 정보를 얻어 번역하였습니다.
I got information from here and translated it.
본문
우리는 Hooks를 사용하여 컴포넌트들을 작성하고 매우 만족합니다! 왜냐면 매우 편리하기 때문이죠 !!
하지만, useEffect
를 사용하면서 뭔가 조각들이 서로 잘 어울리지 않고 놓치고 있는 느낌이 들지 않나요 ? 예를 들어 라이프 사이클과 관련된 그런것들 말이에요.
아래 질문들을 자신에게 한번 물어보세요.
componentDidMount
를useEffect
를 사용하여 대체할 수 있나요?useEffect
안에서 데이터를 어떻게 올바르게 fetch 할 수 있나요? 그리고[]
이건 뭔가요?- 함수를 effect에 의존되게 작성해야 할까요?
- 왜 가끔가다 refetching loop에 걸리는 것 일 까요?
- 내 effect에서 왜 오래된 state나 props 값 이 나올까요?
이 글의 원문 작성자가 Hooks를 처음 사용하기 시작하면서 위 질문들이 그를 계속 혼란스럽게 만들었다고 합니다. 그리고 그 이후로 원작자가 위 질문에 대해 깨달은 순간을 공유하려고 합니다.
1. componentDidMount
를 useEffect
를 사용하여 대체할 수 있나요?
useEffect(fn, [])
를 대체하여 사용할 수는 있지만, 그렇다고componentDidMount
와 useEffect
가 완전히 똑같은 것은 아닙니다. useEffect
는 componentDidMount
와 달리 props와 state를 capture
할 수 있고, 그 안에 있는 callback에서는 초기 props값과 초기 state값을 볼 수 있습니다.
예를 들어, 만약 당신이 맨 마지막
에 들어오는 값을 필요로 할 때, 당신은 ref
를 사용하여 코드를 작성할 수 있습니다.
하지만, 그럴 필요 없습니다. 더 간단하게 코드를 구조화 할 수 있는 방법이 있기 때문이죠. 여기서 이 문제를 해결하기 위해 당신이 꼭 명심해야 할 것은effect
의 기본적인 모델은 componentDidMount,그 이외의 lifecycle
의 기본적인 모델과 다르다는 것 입니다. 결론적으로 그 둘 사이의 정확히 일치하는 공통점을 찾으려고 하는 것은 당신이 혼란스러워 할 수 있는 일이 될 수 있다는 이야기입니다.
따라서, 생산적인 코드를 작성하려면, "think in effects"
하세요.
effects
의 기본 모델은Lifecycle 이벤트
에 대응하는 것보다동기화를 구현
하는데 가까운 모델이라고 할 수 있습니다.
2. useEffect
안에서 데이터를 어떻게 올바르게 fetch 할 수 있나요? 그리고 []
이건 뭔가요?
이 글이 useEffect
를 사용하여 데이터를 fetch 하는데 좋은 발판이 될 수 있을 것입니다. 이 글을 확실히 끝까지 읽으세요! 제가 지금 번역하고 있는 이 글보다 길지 않습니다.
[]
이 빈 대괄호의 뜻은 effect
가 React 앱 안에서 데이터 흐름을 구성하고 있는 어떤 값
을 아무것도 사용하고 있지 않다는 의미입니다. 그래서 궁금하면 그냥 한 번 써봐도 괜찮습니다. 하지만 이것은 흔하게 버그를 일으킬 수 있는 코드 이기도 합니다.
여러분은 다른 전략(? strategies)를 공부해봐도 좋을 것 같습니다. (주로 useReducer
나 useCallback
) that can remove the need for a dependency instead of incorrectly omitting it. (한국어로 어떤 느낌으로 번역해야 할 지 모르겠습니다..)
3. 함수를 effect
에 의존되게 작성해야 할까요?
추천하는 방법으로는, props나 state가 필요하지 않는 함수들은 컴포넌트 외부에서 호이스팅 하고, effect
안에서는 그 effect
안에서만 사용되는 것들로만 구성해야 합니다.
만약, 여러분이 만든 effect
가 render
범위 안에서 계속 사용된다면, effect
들이 정의된 곳에서 useCallback
으로 감싼 뒤, 계속 진행하세요.
4. 왜 가끔가다 refetching loop
에 걸리는 것 일 까요?
이것은 두번째 인자를 넣지 않고 effect
를 사용하여 데이터를 fetch 할 때 일어날 수 있는 일 입니다. 두번째 인자가 없다면, render가 모두 마친 뒤에 effect가 실행되며, state를 설정하면 다시 effect는 트리거 될 것 입니다. 또한, 계속해서 바뀌는 값을 array에 넣어도 infinite loop가 발생합니다. 아마 하나 하나씩 제거하면서 찾아야 어떤 것이 문제였는지 알 수 있을 것 입니다.
하지만, 그렇게 하나하나씩 제거하는 것은 때때로 잘못된 수정방법이 될 수 있습니다. 그 방법 대신 근본적인 부분부터 고쳐나가세요.
예를 들어, 먼저 A 함수가 그 문제를 일으킨다면, 그 A 함수를 effects
안에 넣거나, 호이스팅 하거나, 또는 useCallback
으로 감싸는 것이 도움이 될 수 있을 것 입니다.
object를 새로 재생성 하지 않으려면, useMemo
를 유사한 용도로 사용할 수 있습니다.
4. 내 effect
에서 왜 오래된 state나 props 값 이 나올까요?
effect
들은 그것들이 정의되어있는 render에서 항상 props 과 state를 바라보고 있습니다. 그래서 이런 특징 덕분에 버그를 방지하는데 도움이 될 수 있지만, 몇몇 케이스들에서는 무시될 수 있습니다.
예를 들어, 변경될 수 있는 ref에서 몇몇 값을 명시적으로 유지해야 하는 상황처럼 말이죠. 만약 당신이 오래된 render에서 제대로된 props나 state를 바라보고 있다고 생각하지만, 기대한대로 동작하지 않는다면 아마 그것은 당신이 무조건 다른 의존성 있는 무언가를 놓쳤다는 것 입니다. 그럴 때는 lint rule 을 사용하여 그것들을 찾는 능력을 키우세요. 몇 일만 하다보면 자연스럽게 사용할 수 있을 것 입니다.
이 질문 도 참고해 보세요.
마치며
위 글을 읽지 않았다면, 단순히 effect를 Function Component에서 Lifecycle을 대체하려고만 사용할 수도 있었겠지만, useEffect가 추구하는 근본적인 모델, useEffect를 사용하면서 생길 수 있는 이슈들을 알아보니 lifecycle를 대체하는 것 이외에 useEffect의 목적에 맞는 유용한 기능들이 많은 것 같습니다.
의역과 오역이 정말 많은 와중에 끝까지 글을 읽어주셔서 감사합니다! (고쳐야 될 부분이 있으면 댓글 또는 메일로 알려주시면 감사하겠습니다.)