Skip to content

Latest commit

 

History

History
103 lines (54 loc) · 11.4 KB

4주차 Code Review.md

File metadata and controls

103 lines (54 loc) · 11.4 KB

React Hook 사용 시 주의사항

  1. 최상위에서 호출하기: Hook은 반드시 함수의 최상위에서 호출해야 합니다. 루프, 조건 또는 중첩된 함수 내에서 Hook을 호출하지 마세요.

  2. React 함수 컴포넌트 내에서만 호출하기: Hook을 React의 함수 컴포넌트 내에서만 호출하도록 하세요. 그러나 custom hook에서도 호출할 수 있습니다.

  3. 사이드 이펙트에 주의하기: **useEffect**와 같은 Hook은 컴포넌트의 렌더링 후에 사이드 이펙트를 수행하는 데 사용됩니다. 의존성 배열(dependency array)을 올바르게 관리하고, 필요한 경우 클린업 함수를 제공하도록 하세요.

  4. useState의 초기화 주의: **useState**를 사용할 때, 초기화에 비용이 많이 드는 연산을 피하려면 함수를 전달하세요.

    const [value, setValue] = useState(() => computeExpensiveValue());
  5. 이전 state나 props에 접근할 때: **useState**나 useEffect 내에서 이전 state나 props에 접근할 필요가 있으면 **useRef**를 사용하거나 setState 함수 업데이트 형태를 사용하세요.

  6. useEffect의 무한 루프: useEffect 내에서 state를 변경하면 컴포넌트는 다시 렌더링됩니다. 이를 조심하지 않으면 무한 루프에 빠질 수 있습니다.

  7. Custom Hook: Custom Hook을 만들 때 이름을 항상 **use**로 시작하도록 해야 합니다. 이 규칙을 따르면 Hook을 사용하는 코드를 보다 쉽게 인식하고, 리액트의 lint 규칙과도 호환됩니다.

  8. 클로저와의 상호작용: Hook과 클로저 사이의 상호작용은 때때로 혼란스러울 수 있습니다. **useEffect**나 useCallback 안에서 변수를 사용할 때, 해당 변수가 클로저에 캡쳐되었는지 확인하세요.

  9. 스트릭트 모드와의 호환성: 앱의 견고성을 높이기 위해 **<React.StrictMode>**를 사용하세요. 이는 의도치 않은 사이드 이펙트나 불필요한 렌더링과 같은 문제를 찾아내는 데 도움을 줍니다.

  10. 리액트 개발자 도구: 리액트 개발자 도구를 사용하여 렌더링 성능, Hook의 상태 및 다른 관련 정보를 확인하세요.

Context API + useReducer 사용 시 주의사항

  1. 불필요한 리렌더링 피하기: Context의 값이 변경되면 해당 Context를 사용하는 모든 컴포넌트가 리렌더링됩니다. 이로 인해 불필요한 리렌더링이 발생할 수 있으므로, 상태를 여러 개의 작은 Context로 나누는 것을 고려해 보세요.

  2. 상태 불변성 유지: **useReducer**의 reducer에서 상태를 업데이트할 때는 상태의 불변성을 유지해야 합니다. 상태를 직접 수정하는 것이 아니라, 변경된 부분만을 반영한 새로운 상태 객체를 반환해야 합니다.

  3. 초기 상태 관리: Context와 **useReducer**를 사용할 때, 초기 상태의 설정과 처리 방식에 주의가 필요합니다. 초기 상태를 전역적으로 접근 가능한 곳에 저장하거나, 필요한 경우 lazy initialization을 통해 초기 상태를 설정할 수 있습니다.

  4. 비동기 작업: useReducer와 Context를 사용하여 비동기 작업을 관리하려면, 액션 상태(loading, error, data 등)를 잘 관리해야 합니다. 이때 **useReducer**의 dispatch 함수를 비동기 작업 안에서 사용할 경우, 최신 상태를 반영하는 것에 주의해야 합니다.

  5. 프로바이더 위치: 애플리케이션에서 필요한 모든 컴포넌트에 상태를 제공하려면 **Context.Provider**를 최상위에서 래핑하는 것이 좋습니다. 그렇지 않으면 예상치 않은 동작이나 버그가 발생할 수 있습니다.

  6. 최적화 고려: 복잡한 애플리케이션에서는 **React.memo**나 useMemo, **useCallback**과 같은 최적화 기법을 사용하여 불필요한 리렌더링을 줄일 필요가 있습니다.

  7. 디버깅: 때로는 애플리케이션의 상태가 예상대로 동작하지 않을 수 있습니다. 이때 Redux DevTools와 같은 도구나 **console.log**를 사용하여 상태 변화와 액션 발생을 추적하면 유용합니다.

  8. 재사용성과 모듈화: 큰 프로젝트에서는 Context와 reducer 로직을 모듈화하여 재사용성을 높이는 것이 좋습니다. 이렇게 하면 유지 보수성도

향상됩니다.

React Hook Form 사용 시 주의사항

  1. Controller 컴포넌트 사용: 비제어 컴포넌트를 사용할 때 Controller 컴포넌트를 사용해야 합니다. 이를 통해 비제어 컴포넌트를 RHF와 올바르게 연결할 수 있습니다.

  2. 기본값 설정: defaultValue 또는 **defaultValues**를 사용하여 폼 필드의 기본값을 설정해야 합니다. 이는 특히 Controller 컴포넌트를 사용할 때 중요합니다.

  3. 폼 상태 재렌더링: RHF는 기본적으로 input의 변경 사항마다 리렌더링하지 않습니다. 필요한 경우 **useForm**의 mode 옵션을 사용하여 재렌더링 동작을 조정할 수 있습니다.

  4. 에러 메시지 처리: errors 객체를 통해 에러 메시지를 확인하고 처리합니다. 이 객체를 올바르게 사용하여 사용자에게 명확한 피드백을 제공해야 합니다.

  5. Validation Schema: yup 같은 라이브러리를 사용하여 유효성 검사 스키마를 작성할 수 있습니다. 이를 RHF에 통합하기 위해 resolver 옵션을 사용하면 됩니다.

  6. handleSubmit 함수: **handleSubmit**은 RHF에서 제공하는 함수로, 폼의 제출을 처리할 때 유효성 검사를 자동으로 수행합니다. 이 함수를 사용하여 제출 로직을 처리하세요.

  7. watch와 getValues 사용: **watch**는 모든 입력값의 변경을 감시합니다. 때문에 과도하게 사용하면 성능 문제가 발생할 수 있습니다. 필요한 경우 **getValues**를 사용하여 특정 시점의 값을 가져올 수 있습니다.

  8. NestedValues: 배열 또는 객체와 같은 중첩된 폼 값을 다루려면 useFieldArray 및 **useFormContext**와 같은 추가 Hook을 사용해야 합니다.

  9. 커스텀 훅 사용: 반복되는 로직이나 특정 패턴을 공유하려면 커스텀 훅을 작성하여 RHF의 기능을 확장할 수 있습니다.

Redux Toolkit 사용 시 주의사항

  1. Redux의 기본 이해: Redux Toolkit은 Redux의 복잡성을 줄이는 데 중점을 둡니다. 그러나 Redux의 기본 원리와 개념(예: action, reducer, store)을 이해하지 않으면, RTK의 이점을 최대화하기 어려울 수 있습니다.

  2. Immutable Update Logic: RTK의 createSlice 함수는 내부적으로 Immer 라이브러리를 사용하여 불변성을 유지합니다. 이로 인해 직관적인 코드로 상태를 업데이트할 수 있지만, Immer의 동작 방식을 이해하지 않으면 예기치 않은 동작을 경험할 수 있습니다.

  3. Normalizing State: 복잡한 애플리케이션에서 중첩된 상태를 다루는 경우, normalizing your state는 중요한 최적화 전략이 될 수 있습니다. RTK는 이를 자동으로 수행해 주지 않으므로 상태 구조에 대한 깊은 이해가 필요합니다.

  4. Async Logic: RTK는 비동기 로직을 처리하기 위한 createAsyncThunk 유틸리티를 제공합니다. 이 유틸리티를 사용하면 간편하게 비동기 액션을 디스패치할 수 있지만, 에러 처리나 다양한 상태 변화에 대한 처리도 고려해야 합니다.

  5. Middleware: RTK는 기본적으로 Redux Thunk 미들웨어를 포함하고 있습니다. 다른 미들웨어(예: Redux Saga)를 사용하려는 경우, 설정 방법과 상호작용 방식을 이해해야 합니다.

  6. Redux DevTools: Redux Toolkit은 Redux DevTools Extension과 호환됩니다. 이 도구를 활용하여 액션, 상태 변경 등을 실시간으로 모니터링하면 디버깅에 큰 도움이 됩니다.

  7. Overhead: Redux와 Redux Toolkit 모두 약간의 오버헤드가 있습니다. 매우 간단한 애플리케이션에서는 필요 이상의 복잡성을 가져올 수 있으므로, 프로젝트의 규모와 필요성을 고려하여 적절한 도구를 선택해야 합니다.

useMemo와 useCallback 사용 시 주의사항

자료를 보완하여 Markdown 문법으로 정리했습니다:

useMemo와 useCallback 사용 시 주의사항

  1. 필요한 경우에만 사용하기: 모든 경우에 **useMemo**나 **useCallback**을 사용하는 것은 오버엔지니어링이 될 수 있습니다. 성능 문제가 실제로 발생할 때나 예상되는 곳에만 적용하세요. 불필요하게 사용하면 코드 복잡성만 증가시킬 뿐만 아니라, 추가적인 메모리 사용으로 인한 성능 문제가 발생할 수 있습니다.

  2. 의존성 배열 정확하게 관리하기: **useMemo**와 **useCallback**의 두 번째 인자로 전달되는 의존성 배열은 해당 훅이 메모이제이션된 값을 재계산할지 결정하는 데 중요합니다. 배열 내에 모든 의존성을 명시하고, 빠뜨리지 않도록 주의해야 합니다.

  3. 올바른 의존성 사용: 불필요한 의존성을 배열에 포함시키면, 해당 값이 변경될 때마다 불필요한 연산이 발생합니다. 반대로 필요한 의존성을 빼놓으면 예상치 못한 결과를 가져올 수 있습니다.

  4. 인라인 콜백과 함께 사용: 자식 컴포넌트에 콜백을 전달할 때, 부모 컴포넌트가 리렌더링될 때마다 인라인으로 콜백을 생성하면 자식 컴포넌트도 매번 리렌더링됩니다. 이런 경우 **useCallback**을 사용하여 콜백을 메모이제이션하면 불필요한 리렌더링을 방지할 수 있습니다.

  5. 객체와 배열 메모이제이션: **useMemo**는 새로운 객체나 배열을 생성하는 연산의 결과를 메모이제이션할 때 유용합니다. 객체나 배열이 직접적으로 자식 컴포넌트에 전달될 때, 메모이제이션하지 않으면 부모 컴포넌트가 리렌더링될 때마다 새로운 객체나 배열이 생성되어 자식 컴포넌트도 불필요하게 리렌더링됩니다.

  6. 부작용 내에서의 사용: **useMemo**나 useCallback 내에서 부작용(side effects)를 발생시키는 것은 권장되지 않습니다. 부작용은 **useEffect**나 **useLayoutEffect**에서 처리하는 것이 좋습니다.

  7. 메모이제이션 비용: **useMemo**와 useCallback 자체도 연산 비용이 있습니다. 매우 간단한 연산이나 콜백에 이러한 훅을 무분별하게 사용하면 오히려 성능 문제를 야기할 수 있습니다.

  8. 참조 동일성: 메모이제이션의 주요 목적 중 하나는 참조 동일성을 보존하는 것입니다. 즉, 메모이제이션된 값이 변경되지 않았다면 메모리에 저장된 이전 참조를 재사용하여 불필요한 연산이나 리렌더링을 방지하는 것입니다.