인턴으로 살아남기 2주차 회고록

Andy(앤디)·2025년 9월 15일
16

ICT-Intership

목록 보기
2/3
post-thumbnail

2주차 회고록 – Streaming SSR과 서버 컴포넌트 전환

이번 2주차는 정말 눈 깜짝할 사이에 지나갔다. 새로운 과제들은 대부분 내가 처음 해보는 것들이라, 모든 순간이 생생하면서도 어렵고 동시에 흥미로웠다. 해결하고 싶은 문제가 생기면 집에 돌아와서도 12시가 넘도록 고민하고 코드를 붙잡고 있었으니, 확실히 몰입의 강도가 달랐다.

서버/클라이언트 컴포넌트 분리와 본격적인 마이그레이션

1주차가 Page Router에서 App Router로 옮겨오는 작업에 집중했다면, 이번 주는 Server Component와 Client Component를 체계적으로 분리하는 단계였다. 처음에는 단순히 “어떤 컴포넌트를 서버로 두고, 어떤 걸 클라이언트에 남길까?” 정도의 선택 문제라고 생각했다. 하지만 막상 손을 대보니 데이터 접근 방식, 쿠키 로직, 라이브러리 호환성까지 줄줄이 얽혀 있었다. 특히 쿠키 접근을 서버 전용으로 바꾸고, 클라이언트에서는 Proxy API를 통해서만 전달받도록 구조를 전환하면서, Next.js가 지향하는 서버 중심 아키텍처를 몸소 느낄 수 있었다.

데이터 프리페칭과 Streaming SSR

이번 주의 메인 미션은 단연 데이터 프리페칭과 Streaming SSR 구축이었다.

멘토님의 퀘스트

사수님께서 “await 없이 streaming하게 불러오는 SSR 구조를 만들어보라”는 퀘스트를 주셨다. 늘 개념으로만 접하던 Streaming SSR을 직접 구현할 기회가 온 것이다. 호기심과 도전 정신이 동시에 솟아올랐다.

고군분투의 시간

하지만 현실은 만만치 않았다. 서버에서 await을 제거하면서 생긴 queryKey 동기화 문제, await이라는 고삐없이 데이터가 출발해버리니까 터져버리는 hydration mismatch 에러, 빌드 환경에서 Next.js의 정적 최적화와 쿠키 로직 충돌 같은 예기치 못한 에러들이 연달아 터졌다. 결국 force-dynamic 옵션으로 서버 런타임을 강제로 유지하면서 하나하나 풀어냈다.
“Next.js 14에서 App Router가 빌드 시 자동으로 정적 최적화를 시도한다”는 사실도 이번에 진짜 뼈저리게 배웠다.

특히 중복 요청 문제 때문에 며칠을 끙끙대다가, React Query 공식 문서에서 다음 문장을 보고는 진짜 망치로 머리를 맞은 듯했다.

As of React Query v5.40.0, you don't have to await all prefetches for this to work, as pending Queries can also be dehydrated and sent to the client. This lets you kick off prefetches as early as possible without letting them block an entire Suspense boundary, and streams the data to the client as the query finishes.

공식문서 : https://tanstack.com/query/v5/docs/framework/react/guides/advanced-ssr

“아… 이걸 모르고 3일을 헤맸구나…” 싶었던 순간이었다.

해결과 성과

React Query를 v5로 올리고, useSuspenseQuerydehydrate를 활용하면서 구조가 한결 정리되었다. 덕분에 주요 페이지의 초기 로딩 속도가 확실히 개선되었고, Fallback UI가 보일 틈도 없이 콘텐츠가 눈앞에 나타났다. 말 그대로 신세계였다.
게다가 Suspense 기반 스켈레톤 UI를 일관되게 적용하면서 로딩 UX도 깔끔하게 통합할 수 있었다.

테스트 환경 정비와 번들 최적화

구현만 한 게 아니라 테스트 환경과 번들 최적화도 병행했다.

  • MSW v2로 마이그레이션 → Node.js 환경 호환성 확보
  • Jest v29로 업그레이드 → React 18 Suspense 테스트 호환성 보장
  • lodash 제거 & es-toolkit 도입 → 불필요한 의존성 축소 + 타입 안정성 강화

테스트와 빌드가 매끄럽게 돌아가는 환경이 마련되니, 마음 놓고 리팩토링과 최적화를 시도할 수 있었다.

성능 개선과 배운 점

수치로도 성과가 드러났다.

  • 초기 JS 번들 크기: 372kB → 155kB (-58%) 감소
  • 데스크톱 환경 CLS: 0.034 → 0.007 개선
  • 모바일 환경 FCP : 7.0s -> 2.3s 개선
  • 모바일 환경 Speed Index : 7.0s -> 2.5s 개선
  • Lighthouse 점수: 모바일 58 → 79, 데스크톱 89 → 95

이건 단순히 “빠른 서비스”를 만든 차원이 아니었다. Server Component, Suspense, Streaming SSR 같은 개념들이 실제로 사용자 경험을 어떻게 바꾸는지 체감할 수 있었던 순간이었다.

한 주를 마치며

2주차를 지나며 깨달은 건, 이제 단순히 기능만 구현하는 단계는 끝났다는 것이다. 아키텍처와 사용자 경험을 함께 고민하며, 코드 한 줄 한 줄이 실제 서비스의 성능과 UX에 직접적인 영향을 준다는 점을 체감했다.

이번 주의 가장 큰 보람은, 멘토님과 끊임없이 의견을 주고받으며 함께 머리를 맞대고 새로운 난제를 해결한 경험이었다. 처음에는 막막했던 Streaming SSR 구축과 데이터 프리페칭 문제를, 여러 시행착오 끝에 해결하면서 마치 목표로 했던 높은 산을 넘어선 듯한 성취감을 느꼈다.

앞으로는 React 18의 Concurrent Feature까지 활용해 더 탄탄하고 효율적인 구조를 만들어보고 싶다. 이번 주의 경험은, 단순한 코드 작성이 아니라 문제를 정의하고, 전략을 세우고, 실행하며 극복하는 과정 자체가 성장의 열쇠임을 다시 한번 깨닫게 해주었다.

profile
사용자 경험 개선을 목표로, 효율적인 팀 소통을 통해 가치를 창출하는 프론트엔드 개발자

0개의 댓글