성능이 뭐가 중요하다니요???

const job = '프론트엔드';·2026년 1월 20일

풀스택 개발일지

목록 보기
7/7

아니, 성능은 다 필요없고 일단 되면 끝이라고?

'지금 잘 쓰고 있잖아, 뭐하러 더 만져?'

사내 서비스에서 외주 프리랜서에 맡겼다가 인계를 받은 프로젝트가 있다.
처음 인수인계를 받고 코드를 분석하면서
1. 유지보수 어렵다.
2. 새로운 기능 추가 어렵다.
3. 느리다.

총제적 난국이었고, 프론트엔드만의 문제가 이정도인데 백엔드와 DB 그리고 서버까지 모두 엉망인 상태였다.

상태관리가 엉망이었고, 스타일 라이브러리를 여러가지 중복으로 사용하고 있다.
상태관리가 중복이더라도 적재적소에 사용하면 시너지를 일으킬 수 있다.(하지만 이 프로젝트는 아니었다.)
그래 그럴 수 있지, 이유가 있을꺼야 하고 백번양보해도
Styled-components, MUI, module css, inline 등등 왜이렇게 했는지 이해할 수 없다.
불필요한 객체지향 구조 남발로 로컬에서 실행시 엄청나게 느렸다.
(가끔 지금 뭐하고 사는지 그 사람들 이름을 구글에 검색해본다.)

이 엄청난 프로젝트를 내가 받았고,
이 프로젝트의 유일한 백엔드와 DB를 맡아주셨던 분의 육아휴직으로
최대한 프론트에서 해결, 안되면 백엔드 api 생성(혹은 유지보수), 그래도 안되면 DB 만지기로
어찌저찌 2025.09.01에 성공적으로 오픈을 했다(추가 유지보수 건 오픈은 10월 중순).

오픈하고 나서도 대민서비스 였기 때문에 조마조마 했다.
갑자기 와르르 무너질 것 같은 서비스였기 때문이다.

오픈 전에 당시 신입이었던 동료 선임님(현재 내 최애), 담당 프로젝트 관련 선임님(현재 책임님)과 엄청난 테스트를 진행했었고, 다행스럽게도 프로그램에 관련된 CS는 현재까지도 0건이다.

우리(a.k.a 나)는 이렇게 개발을 진행했다.
'새로운 페이지 개발은 기존 컨벤션을 따르되, 최대한 유연하게 컴포넌트를 구성하자'
기존 코드를 완전히 무시할 수 없는 구조였기 때문에
최소한의 컨벤션을 따르기로 결정했다.
그리고
'기존 사용불가능 하던 페이지의 유지보수는, 기존 컨벤션 구조에서 리팩토링과 함께 진행하자'
프리랜서들이 버리고 간 화면은 객체지향으로 엮여있는 코드, 컨벤션을 따르지 않고 무지성으로 작성된 코드, 퍼블리셔가 퍼블리싱만 한 하드코딩 코드 이렇게 3가지 였고, 최대한 우리가 유지보수하게 되는 화면에 대해서는 해당 규칙을 적용해서 작업했다.

그리고 최근 회사에서 해당 프로젝트가 확장될 것이라는 사업계획을 전달 받았고,
현재 상태로는 확장이 불가능할거라는 파트원들의 판단이 있었다.
그 사이 팀이 분리되면서 나는 또 우리팀의 유일한 프론트엔드가 되었다.

우선 다시 코드분석에 들어갔고,
성능개선이 우선이라는 생각이 들었다.

초기 상태

  • 모든 페이지가 체감상 매우 느림(예시 이미지 자료는 강력 새로고침하면서 그나마 잘 나온 수치였음)
  • 새로고침 시 네트워크 요청 다수
  • Lighthouse / Web Vitals:
    • LCP 수 초 ~ 수십 초!
    • CLS 지속 발생
    • INP 비교적 양호

프론트 구조 문제로 확정

Providers 중첩 구조 문제 발견

  • Providers
    • app/layout
    • route별 layout
    • page내부에 중복 선언
  • Recoil, React Query, MUI, Init Provider가 페이지 진입 시마다 초기화
    -> hydration 비용 증가
    -> 불필요한 re-render 폭증
  • 조치: Providers를 최상위 app/layout.tsx 하나로 통합(하위에서는 Providers 제거)

API 호출 과다 + 반복 호출 구조

  • 테이블 공통 구조에서
    • usePageInfo(Recoil)
    • QueryLoader
    • usePagingQuery
      가 서로 상태 변경 -> 재호출 루프를 형성
  • 같은 API가 pagination 변경, filter 변경, mount시 마다 동일한 API 호출
  • 조치: 불필요한 effect dependency 제거, page 진입 시 자동 reload 로직 정리, 페이지 로딩 시 무조건 fetch 하던 패턴 제거

API 호출 수 감소
네트워크 타임라인 정리
그런데, 여전히 LCP 나쁨

API 문제가 아니다!

  • API 응답 자체는 수십~수백 ms
  • Network waterfall에서 요청이 빨리 끝나는데, 화면이 늦게 완성

    렌더링 문제

구조 전면 재검토

  • 예시 페이지: MyPage
  • page.tsx가
    • use client
    • useEffect로 getUser함수 호출
    • user 로딩 전까지 전체화면 screenLoading -> 초기 HTML 아무 내용도 없음
  • 조치: Server + client 분리 구조로 변경
    1) page.tsx(서버컴포넌트 역할)
    - getUser() 서버에서 호출
    - 초기 HTML에 사용자 정보 포함
    2)MyPageClient.tsx(클라이언트 컴포넌트 역할)
  • 탭 전환 interaction만 담당

결과

진짜 화가 나는건
이렇게 보이지 않는 그러니깐 성과가 체감으로 느껴지지 않는걸 왜하냐는 상사의 지적이었다.

마치 이건
'코드리뷰 받으면서 그냥 기능은 작동하는데 머지해주시면 안돼요?'
의 과거의 나를 보는 느낌이었다.

예전에 api호출이 9번이 있었던 기억이 있다.
잊어버리지 않는 이유는 이 현상을 개선하기 위해 거의 3일을 썼고, 팀 리더의 도움을 받아서 해결을 했던 경험이 있기 때문이다.

이때는 빡센 QA가 너무 힘들었는데, 이때의 경험이 지금은 정말 소중하다.

떠날 때가 됐다. 저새끼랑 도저히 일 못하겠다.

profile
`나는 ${job} 개발자`

0개의 댓글