[10주차 회고] 코드 관점의 성능 최적화

신희원·2025년 9월 22일
2
post-thumbnail

내가 배운 점들📚

메모이제이션은 도미노 같은 존재다

코치님이 말씀해주신 "메모이제이션을 한 번 적용하기 시작하면 연달아 적용해야 한다"는 말이 정말 와닿았다. React.memo를 컴포넌트에 적용하면, 그 컴포넌트로 전달되는 props들도 모두 메모이제이션해야 한다는 뜻이다.

const ParentComponent = () => {
  // 이 데이터가 변하지 않으면 재계산하지 않음
  const expensiveData = useMemo(() => {
    return heavyCalculation();
  }, [dependency]);

  // 이 함수도 매번 새로 만들어지지 않도록 메모이제이션
  const handleClick = useCallback(() => {
    doSomething();
  }, []);

  return <MemoizedChild data={expensiveData} onClick={handleClick} />;
};

처음에는 왜 이렇게 복잡하게 해야 하나 싶었는데, 직접 해보니 이해가 됐다. 하나의 컴포넌트를 최적화하려면 그와 연결된 모든 부분을 함께 고려해야 한다는 것이다.

useReducer의 숨겨진 장점

복잡한 상태 관리에서 useReducer를 사용해보니 예상치 못한 장점을 발견했다. 바로 테스트하기가 훨씬 쉽다는 점이다. reducer 함수는 순수 함수라서 입력만 주면 항상 같은 결과가 나온다. 각각의 액션에 대해서도 독립적으로 테스트할 수 있어서 디버깅할 때도 편했다.

상태가 3-4개 이상 연결되어 있을 때는 useState보다 useReducer가 훨씬 관리하기 편한 것 같다. 특히 여러 필드가 동시에 업데이트되어야 하는 경우에는 더욱 그렇다.

깨달은 점

추측하지 말고 측정하라

성능 최적화의 첫 번째 원칙은 '측정'이라는 것을 뼈저리게 느꼈다. 내 생각에 느려 보이는 부분과 실제로 느린 부분이 다를 수 있다는 걸 여러 번 경험했다.

React DevTools의 Profiler를 사용해서 실제 렌더링 시간을 측정하고, Performance API로 함수 실행 시간을 체크하면서 정확한 데이터를 바탕으로 최적화 방향을 정할 수 있었다. "이 부분이 문제인 것 같다"가 아니라 "이 부분이 17ms 걸리므로 최적화가 필요하다"고 말할 수 있게 됐다.

Context API는 양날의 검

ScheduleContext를 만들면서 전역 상태 관리의 딜레마를 직접 체험했다. Context를 사용하면 props drilling 문제는 해결되지만, 그 Context를 사용하는 컴포넌트가 많아질수록 상태가 바뀔 때마다 더 많은 컴포넌트가 리렌더링된다.

코치님이 말씀하신 것처럼 Context API는 디자인 시스템이나 특정 컴포넌트 트리 안에서 데이터를 공유할 때 유용하다. 하지만 진짜 "전역" 상태로 사용할 때는 신중하게 생각해야 한다는 걸 깨달았다.

사용자 관점에서 생각하기

성능 최적화를 하면서 자꾸 개발자 관점에서만 생각하고 있다는 걸 깨달았다. "렌더링이 몇 ms 줄어들었다"보다는 "사용자가 버튼을 눌렀을 때 얼마나 빨리 반응하는가"가 더 중요하다.

API 호출이 실패했을 때도 "콘솔에 에러가 찍혔으니까 됐다"가 아니라 "사용자에게 어떤 메시지를 보여줄까", "다시 시도할 수 있게 해줄까"를 고민해야 한다는 걸 느꼈다.

아쉬운 점

타입스크립트를 제대로 활용하지 못했다

TypeScript를 사용했으면서도 그 장점을 충분히 살리지 못했다. Lecture 타입을 여러 파일에 중복으로 정의한다거나, 유니온 타입이나 타입 가드를 적극적으로 활용하지 못했다.

런타임에서 발생할 수 있는 오류들을 컴파일 타임에 잡을 수 있는 기회를 많이 놓쳤다는 생각이 든다. 타입 시스템을 단순히 '변수의 타입을 명시하는 것' 정도로만 생각했던 것 같다.

에러 상황을 너무 간단하게 생각했다

API 호출이 실패했을 때나 예외 상황이 발생했을 때, 개발자 입장에서만 생각했다. 콘솔에 에러 로그만 남기고 끝내는 게 아니라, 사용자에게 의미 있는 피드백을 주거나 복구할 수 있는 방법을 제시했어야 한다.

"네트워크 오류가 발생했습니다"보다는 "잠시 후 다시 시도해주세요" 같은 구체적이고 행동 가능한 메시지를 보여줬으면 더 좋았을 것 같다.

다음 목표

접근성도 함께 고려하는 개발자가 되고 싶다

성능과 접근성을 모두 고려할 수 있는 개발자가 되고 싶다.
빠르기만 한 웹사이트가 아니라, 모든 사람이 편하게 사용할 수 있으면서도 빠른 웹사이트를 만들고 싶다.

팀 전체의 성능 문화를 만들어보고 싶다

나 혼자만 성능을 신경 쓰는 게 아니라, 팀 전체가 성능을 고려하며 개발할 수 있는 문화를 만들어보고 싶다. 성능 예산을 정하고, 코드 리뷰할 때도 성능 관점을 포함하고, CI/CD에서 성능 회귀를 자동으로 감지하는 시스템을 만들어보고 싶다.


이번 프로젝트는 단순히 기능을 만드는 것을 넘어서 '좋은 소프트웨어란 무엇인가'에 대해 고민해볼 수 있는 시간이었다. 빠른 것도 중요하지만, 모든 사용자가 접근할 수 있고, 안정적이며, 지속 가능한 소프트웨어를 만드는 것이 진짜 목표라는 걸 깨달았다.

아직 갈 길이 멀지만, 이런 고민을 할 수 있게 된 것만으로도 큰 성장이라고 생각한다.

profile
프론트엔드 공부하는 개발자입니다.

0개의 댓글