[Internship] 2025-09 인턴일지
👩🏻💻 9월 동안 인턴을 하면서 진행한 작업들
1️⃣ GA4 연동 및 UTM Parameter 설정
회사 서비스의 유입 경로를 추적하기 위해 GA4를 연동했다. 단순히 이벤트 로깅을 붙이는 수준이 아니라, GA4 이벤트가 프론트에서 발생한 후 서버까지 데이터가 안전하게 전달되는지 확인해야 했다. 특히 캠페인별 트래킹을 위해 UTM parameter를 URL에서 파싱해 서버 API 요청 시 함께 넘기도록 로직을 짰다.
초반에는 GA4가 정상적으로 이벤트를 수집하지 않는 문제가 있었는데, localstorage 접근으로 인한 hydration error가 원인이었다. 클라이언트 렌더링 시점에서만 GA4가 동작하도록 useEffect 안에서 초기화 로직을 실행해 해결했다. 이 과정을 통해 hydration error에 대해 더 깊게 공부할 수 있었으며, 해당 주제로 기술 블로그도 작성했다.
2️⃣ MDX를 사용하여 이용약관 등의 문서 제작
이전에는 이용약관, 개인정보 처리방침과 같은 법적 문서를 노션 링크로 연결했는데, 이는 서비스 신뢰성 측면에서 아쉬움이 있었다. 이를 개선하기 위해 MDX를 도입해 서비스 내부 페이지에서 문서를 렌더링하도록 구현했다.
MDX를 적용하면서 겪은 첫 문제는 리스트나 숫자 목록이 깨지는 렌더링 이슈였다. 단순한 마크다운만 쓸 때는 괜찮았지만, 커스텀 컴포넌트와 혼합되면서 스타일이 덮여서 문제가 발생했다. next-mdx-remote 라이브러리를 통해 이 문제를 해결했고, 커스텀 스타일링을 적용해 문서가 깔끔하게 보이도록 했다.
3️⃣ intercepting route를 사용한 프리온보딩 플로우 변경
Next.js 13의 Intercepting Route를 활용해 프리온보딩 플로우를 리팩토링했다. 신규 유저는 full page에서 온보딩 과정을 진행하고, 기존 유저는 modal에서 빠르게 인증 절차만 거칠 수 있도록 UX를 개선했다.
다만 구현 과정에서 가장 큰 어려움은 모달 내에서 쿼리 파라미터(step)가 바뀔 때마다 의도치 않게 full page로 전환되는 문제였다. 원래는 모달 상태를 유지한 채 단계별 화면이 전환되길 원했지만, 라우팅 구조와 상태 관리가 꼬여서 계속 페이지 전체가 리렌더링되는 상황이 발생했다.
이를 해결하기 위해 Next.js의 라우터 기능만 고집하지 않고, window.location을 직접 제어하는 방식을 사용했다
4️⃣ auth entity 분리 및 파일 리팩토링
서비스 아키텍처를 FSD에 맞게 리팩토링하는 작업을 진행했다. 그중 가장 핵심은 auth 관련 코드를 entity 단위로 분리하는 것이었다. auth의 entity를 분리하고 FSD에 맞게 feature/auth와 entity/auth에서 사용하도록 리팩토링했다.
entity는 feature나 ui에 의존하지 않아야 하므로, 로그인 토큰 관리 로직과 API 스키마를 entity에 모으고, 이를 auth/feature에서 사용하도록 리팩토링했다.
리팩토링하면서 파일 경로가 바뀌어 import 에러가 엄청 쏟아져서 조금은 힘들었지만, 협업 시 “어디에 어떤 코드를 둬야 하는지 기준”이 생긴다는 점이 가장 큰 배움이었다.
5️⃣ 데이터 동기화 로직 구현
서버에서 데이터를 동기화하는 방식이 변경되어 서버에 맞춰 프론트 측의 코드도 대폭 수정했다 진짜 제일 힘들고 어려웠던 부분.. ㅜ.ㅜ
원래는 프론트에서 소켓을 호출하고 순차적으로 데이터를 불러와 동기화하는 로직을 통해 진행되었는데, 서버가 업데이트되면서 이제는 서버가 알아서 순차 실행을 하고, 프론트는 startStage만 호출하면 되는 구조로 바뀌었다.
웹소켓을 한 번도 사용해본 적도 없었고 공부해본 기억도 거의 없었기에 코드 이해부터 난관이었다. 그래도 데드라인이 꽤 널널했어서 아예 하루 날 잡고 소켓에 대해 가볍게 공부하며 코드를 이해하기 시작했다. 그렇게 하니 전체적인 플로우와 로직을 알 수 있게 되었고 서버에서 테스트를 하며 로직을 갈아엎는 데에 성공하였다!
6️⃣ 모바일 서비스 기획 및 와이어프레임 제작 참여
이제 회사의 도메인에도 익숙해질 때쯤, 9월 마지막 주에는 개발뿐 아니라 기획에도 참여했다. 회사의 신규 모바일 서비스 기획과 와이어프레임 제작 과정에서 디자이너와 협업하며 사용자 경험을 중점적으로 논의했다.
평소 UX에 관심이 많고 사이드 프로젝트에서 디자이너와 협업 경험이 있었기 때문에, 사용자 중심 사고에 맞춰 다양한 의견을 내었고 그 의견들이 대부분 수용되었다 (칭찬도 들었다 ><)
이 경험 덕분에 단순히 개발자로서 기능을 구현하는 게 아니라, “사용자가 실제로 어떻게 느낄까?”를 고민하는 프론트엔드 개발자가 되는 것이 얼마나 중요한지 깨달았다.
📋 회고
hydration error를 놓치지 말자
SSR과 Next.js를 접한 지 얼마 되지 않아 바로 실무에서 사용하다 보니 클라이언트 사이드에서만 접근할 수 있는 요소와 서버 사이드에서만 접근할 수 있는 요소들을 구분하는 것이 나에게 있어 매우 어려운 일이었다. 그 결과 가장 자주 맞닥뜨린 문제가 바로 hydration error였다.
처음에는 dev 페이지에서만 보이는 에러였고 prod에서는 이 에러가 보이지 않았기에 그냥 넘겼지만, 이 에러가 꽤 많은 영향이 된다는 걸 알고 원인을 하나씩 파고들며 해결해 나갔다. 특히 window나 localstorage와 같은 브라우저 전용 API를 서버 렌더링 단계에서 접근할 수 없다는 사실을 몸소 깨달았다. 문제를 해결하는 과정에서 SSR과 CSR의 차이를 명확히 구분하는 습관을 갖게 되었고, 이를 블로그에 따로 정리하며 다시는 같은 실수를 반복하지 않겠다고 다짐했다. 진작에 알았어야 할 에러를 이제야 알다니.. 부끄러웠지만 직접 부딪히며 배운 만큼 더 오래 기억에 남을 것 같다.
이제는 공부해야 할 것 같은 WebSocket
9월 동안 진행한 작업들 중 데이터 동기화 로직에서 websocket을 흔지 않게 만날 수 있었다. 기존에 사용하던 HTTP 요청/응답 방식과는 완전히 달라서 처음에는 코드가 눈에 잘 들어오지 않았다.
이전에 단 한 번도 웹소켓을 써본 적도, 공부해본 적도 없어 코드를 이해하는 과정부터 꽤 난항을 겪었다. 회사 도메인 상 실시간으로 알림을 보내고 실시간으로 데이터를 모니터링해야했기에 반드시 알아야 할 내용이었다.
물론 아직 완벽히 다 이해했다고 할 수는 없지만, 이번 경험을 통해 “앞으로 채팅, 알림, 실시간 모니터링 같은 기능을 만들 때는 반드시 WebSocket을 알아야 한다”는 확신이 생겼다. 단순히 낯선 기술을 스쳐간 것이 아니라, 앞으로 학습해야 할 개발 로드맵의 한 축을 발견했다는 점에서 큰 의미가 있었다.
남의 코드를 뜯어보는 것이 두렵지 않아졌다!
예전에는 남이 짠 코드를 보는 일이 가장 어렵게 느껴졌다. 나의 코드 스타일이 다르고, 로직 전개 방식도 달라서 이해하는 데 시간이 많이 걸렸다. 하지만 인턴 생활 동안은 회사 코드베이스를 이해하고 직접 수정·리팩토링하는 일이 반복적으로 주어졌다.
처음에는 막막했지만, 여러 번 코드를 읽고 직접 고치면서 점점 코드를 작성하는 시야가 넓어졌다. 단순히 코드 한 줄을 이해하는 수준을 넘어, 전체적인 아키텍처와 흐름 속에서 이 코드가 어떤 역할을 하는지 생각하는 습관이 생겼다. 이제는 남의 코드를 뜯어보는 일이 두렵지 않고, 오히려 다양한 로직을 접할 수 있는 기회라고 느껴진다.
✏️ 총정리
8월의 경우, 새로운 기능과 페이지를 제작한 달이었다면 9월은 실무적인 문제 해결, 구조 리팩토링, 실시간 데이터 흐름 이해에 집중한 달이었다.
데이터 동기화 과정이나 인증서 등록 과정 등 실무에서만 오로지 접할 수 있는 기능들을 다뤄보니 정말 어려웠지만 그 과정을 극복하고 기능 디벨롭을 해내면서 관련 지식들도 많이 알게 되었다
단순히 코드를 짜는 개발자가 아니라, 실제 서비스의 품질과 구조를 고민하는 개발자로 성장하는 9월이었다.