데이터로 숨겨진 문제를 찾아 사용자 경험과 비즈니스 지표를 동시에 개선하고, 개발 프로세스 자동화와 아키텍처 설계를 통해 팀의 생산성과 안정성을 높이는 3년차 프론트엔드 개발자 이형민입니다.
FCP를 96.17% 개선한 데이터 아키텍처 재설계, 반복 수작업을 99% 제거한 협업 워크플로우 자동화, 그리고 런타임 버그를 원천 차단한 타입 세이프 시스템 구축 경험을 통해 기술적 해결책이 어떻게 비즈니스 성과와 팀의 성장으로 이어지는지를 증명해왔습니다. 앞으로도 '왜 이렇게 만들어야 하는가'를 자문하며 제품의 전 과정에 기여하는 Frontend Product Engineer로 비즈니스 가치를 창출하겠습니다.
<aside> ✉️
</aside>
<aside> 📱
010 2783 2123
</aside>
<aside> <img src="notion://custom_emoji/175dd24c-b679-4256-b4db-4ad60d250dfa/2abd4564-8769-8011-b492-007a1394d9ad" alt="notion://custom_emoji/175dd24c-b679-4256-b4db-4ad60d250dfa/2abd4564-8769-8011-b492-007a1394d9ad" width="40px" />
</aside>
<aside> <img src="notion://custom_emoji/175dd24c-b679-4256-b4db-4ad60d250dfa/2b0d4564-8769-80fe-82d5-007a51add780" alt="notion://custom_emoji/175dd24c-b679-4256-b4db-4ad60d250dfa/2b0d4564-8769-80fe-82d5-007a51add780" width="40px" />
</aside>
<aside> <img src="notion://custom_emoji/175dd24c-b679-4256-b4db-4ad60d250dfa/2abd4564-8769-8066-a36d-007a0e877676" alt="notion://custom_emoji/175dd24c-b679-4256-b4db-4ad60d250dfa/2abd4564-8769-8066-a36d-007a0e877676" width="40px" />
</aside>
| Team | 개발팀 |
|---|---|
| Position | 웹서버/프론트엔드 엔지니어 |
| Duration | 2022. 11. 21. ~ 재직 중 |
| Projects | - CPR 프로덕트 원격 관리 웹서비스 CPR cloud |
데이터 아키텍처 재설계로 대시보드 로딩 경험(P75 FCP) 96.17% 개선 (20.1초 → 0.7초)
CPR cloud 리뉴얼 후 데이터가 쌓이면서 어드민 계정의 대시보드 페이지 로딩 시간이 최대 20초에 달하는 치명적인 성능 저하가 발생했습니다. 이는 단순 버그가 아니라 데이터 증가에 따라 실시간 집계 아키텍처가 한계에 도달했다는 구조적 문제였습니다.
이 문제를 해결하기 위해 즉각적인 사용자 경험 개선과 근본적인 아키텍처 개선이라는 2-Track 전략을 병행했습니다.
프론트엔드 응급 처치 (즉각적 UX 개선)
가장 시급한 문제인 '20초간의 빈 화면'을 해결하기 위해 React Suspense를 활용한 Streaming SSR을 긴급 도입했습니다. 데이터 쿼리가 오래 걸리는 각 위젯을 스켈레톤 UI로 우선 렌더링해 사용자가 준비된 컴포넌트부터 순차적으로 확인할 수 있도록 하여 초기 체감 성능을 개선했습니다.
데이터 아키텍처 재설계 (근본 원인 해결)
서버 응답 시간 지연이 근본 원인임을 데이터로 파악한 뒤 실시간 집계 방식의 한계를 극복하기 위한 사전 집계 아키텍처를 새롭게 설계하고 도입했습니다. 15분마다 스케줄러가 복잡한 JOIN과 집계 연산을 미리 수행하여 결과를 저장하는 '롤업 테이블'을 구축해 무거운 실시간 쿼리를 가벼운 SELECT 쿼리로 대체했습니다. 이로서 쿼리 속도를 최대 99.25% 개선했습니다.
| 기존 로직(ms) | 3,085.95 | 25.84 | 1,661.68 | 2,276.82 | 6,449.01 |
|---|---|---|---|---|---|
| 개선 로직(ms) | 29.37 | 3.56 | 52.56 | 88.67 | 48.67 |
| 개선률(%) | 99.05% | 86.24% | 96.84% | 96.11% | 99.25% |
| 기존 로직(ms) | 1,300.99 | 1,419.30 | 1,521.16 | 96.26 | 5,528.92 |
|---|---|---|---|---|---|
| 개선 로직(ms) | 51.59 | 70.41 | 75.52 | 46.52 | 27.52 |
| 개선률(%) | 96.03% | 95.04% | 95.04% | 51.68% | 99.50% |
이러한 End-to-End 최적화를 통해 실제 사용자 데이터(RUM)의 P75 기준 FCP를 평균 20.1초에서 0.7초로 단축시켜 약 96.2%를 개선하는 성과를 달성했습니다. 프론트엔드의 즉각적인 대응과 데이터 아키텍처의 근본적인 개선을 결합해 성능이 '사후 처리'가 아닌 '설계의 영역'임을 증명할 수 있었고, 전월 동기간 대비 주요 페이지의 이탈률을 낮출 수 있었습니다.
| 상황 | FCP(RUM) |
LCP(RUM) |
DCL(LAB) |
ST(LAB) |
|---|---|---|---|---|
| 이전 P75(ms) | 20136 | 20136 | 37299 | 37290 |
| 이후 P75(ms) | 772 | 1582.4 | 3909 | 3660 |
| 개선률 P75(%) | 96.17% | 92.14% | 89.52% | 90.19% |
[블로그]
Tailwind CSS Plugin 개발을 통해 디자안 QA 리드 타임을 75% 단축.
반응형 디자인 구현 시 각 breakpoint마다 다른 스타일 값을 수동으로 적용(p-4 md:p-6 lg:p-8)해야 해서 코드의 가독성을 해치고 디자이너의 의도와 다른 값으로 구현되는 등 휴먼 에러로 인한 불필요한 커뮤니케이션 비용을 발생시켰습니다.
디자이너와 함께 디자인 토큰의 명명 규칙부터 각 Breakpoint 별 값까지 상세하게 정의하는 미팅을 수차례 가졌습니다. 이 공통의 약속을 코드로 강제하기 위해 Typography, Spacing, Sizing 등 디자인 시스템 전 범위를 자동화하는 Tailwind CSS Plugin을 직접 개발했습니다. 단일 클래스(text-body, p-main)만으로 모든 Breakpoint에 대한 스타일을 자동 적용하고 단일 진실 공급원(SSOT)의 디자인 토큰으로 전사 일관성을 보장했습니다.
결국 반응형 스타일링 코드 추상화를 통해 생산성과 유지보수성이 상승했고 디자이너로부터 "의도한 반응형 디자인이 100% 정확하게 구현된다”는 피드백을 받으며 디자인 QA 리드 타임과 왕복 커뮤니케이션 비용을 약 75% 줄이고(*디자인 QA 태스크 시간 기준) 개발자와 디자이너 모두가 신뢰할 수 있는 시스템을 구축했습니다.
전역 UI 제어 아키텍처 도입으로 개발 경험 및 재사용성 극대화.
프로젝트 전반에 걸쳐 Dialog, Dropdown 등의 공통 UI 컴포넌트가 일관성 없이 구현되어 파편화된 상태 관리와 낮은 웹 접근성(a11y), 비효율적인 개발 프로세스의 원인이었습니다. 초기에는 이를 해결하기 위해 Compound Components Pattern을 적용하여 유연하고 선언적인 API를 제공하고 웹 접근성과 UX 로직을 컴포넌트에 내장하는 컴포넌트 시스템을 구축하여 개발 생산성을 높였습니다. 하지만 제품이 복잡해지면서 컴포넌트 트리 상에서 멀리 떨어진 곳에서 특정 다이얼로그를 제어해야 할 때 Context API 기반 설계의 구조적 한계에 부딪혔습니다.
초기 설계의 한계를 극복하기 위해 Toast 컴포넌트에 적용했던 Observer 패턴을 고도화해 중앙 DialogManager/DropdownManager가 모든 컴포넌트의 상태와 참조를 ID 기반으로 등록하고 관리하도록 설계해 상태 제어 로직을 UI 렌더링 로직과 완벽하게 분리했습니다.
이를 통해 팀 전반의 UI 개발 속도와 코드 일관성이 향상되었고 아래와 같은 직관적인 코드로 애플리케이션의 어느 곳에서든 UI를 제어할 수 있게 만들어 복잡한 인터랙션의 구현을 단순화하고 개발 경험(DX)과 컴포넌트의 재사용성을 다시 한 번 끌어올리게 됐습니다.
dialogManager.open('dialog-id');
dropdownManager.open('dropdown-id');
<Dialog.Root id='dialog-id'>
<Dialog.Trigger>{/* ... */}</Dialog.Trigger>
<Dialog.Body>
<Dialog.Header>{/* ... */}</Dialog.Header>
{/* ... */}
<Dialog.Footer>{/* ... */}<Dialog.Footer>
</Dialog.Root>
팀의 개발 생산성과 안정성을 모두 잡은 에러 처리 아키텍처 설계 및 정착.
프로젝트가 성장함에 따라 에러 처리가 각 기능마다 파편화되면서 버그 추적이 어렵고 사용자에게 일관된 실패 경험을 제공하지 못하는 심각한 문제가 있었습니다.
이러한 문제를 해결하기 위해 주도적으로 에러 처리 아키텍처를 설계하고 시스템으로 구축했습니다. 먼저 애플리케이션을 5가지 경계로 정의하고 각 경계에 에러 변환, 에러 처리라는 명확한 책임을 부여하는 아키텍처 청사진을 설계했습니다. 이후 모든 에러를 담는 단일 에러 모델 DomainError와 모든 에러를 일관된 정책으로 다루는 중앙 에러 처리 허브 handleError를 개발해 아키텍처를 구현했고 추가로 에러 경계에서 타입 안정적인 래퍼 함수를 구현해 모든 에러가 handleError로 처리되는 파이프라인을 완성했습니다.
에러가 발생하는 위치와 처리 정책을 완벽하게 분리해 예측 가능하고 안정적이며 유지보수성이 뛰어난 에러 처리 시스템을 구축했습니다. 이를 통해 새로운 에러 시나리오에 대한 대응 시간을 크게 단축시켰고 개발자들이 에러 처리에 대한 고민 없이 비즈니스 로직에만 집중할 수 있는 환경을 만들어 팀의 전체적인 개발 생산성과 애플리케이션의 안정성을 크게 높였습니다.
[블로그]
런타임 버그를 원천 차단한 Zod 기반 타입 안정적인 SDK Wrapper 패키지 개발.
모노레포로 데이터 스키마는 통일했으나 Firestore 사용 시 타입 단언(as User)으로 인해 런타임 에러의 잠재적 위험이 존재했습니다.
공통 Zod 스키마를 활용해 다음과 같이 활용할 수 있는 형태의 타입 안정적인 SDK Wrapper 패키지를 개발하고 직관적인 체이닝 API를 통해 Firestore에서 가져온 데이터의 유효성을 자동으로 검증하고 유효한 데이터만 애플리케이션에 전달하도록 설계했습니다.
await firestore.withSchema(UserSchema).collection(collectionId).doc(docId).get()
이를 통해 프로젝트 전체에서 위험한 타입 단언을 전면 제거하여 데이터 불일치로 인한 잠재적 런타임 버그를 원천적으로 차단했고 모노레포의 패키지로 구성하여 보일러플레이트 코드를 줄여 DX를 향상시켰습니다.
기획자와의 협업 워크플로우를 혁신해 다국어 적용 작업 시간을 99% 단축시킨 i18n 자동화 파이프라인 구축.
기존 다국어 작업은 기획자가 전달하는 Excel 파일을 개발자가 수동으로 JSON으로 변환하고 코드에 적용하는 방식이었습니다. 이 워크플로우는 기획자의 수정 사항이 누락되거나 데이터 변환 과정에서 휴먼 에러가 발생하는 매우 비효율적이고 불안정했습니다. 16개국에 대한 번역을 업데이트하는 데 2-3시간의 단순 반복 시간이 소요되었고 타입 시스템의 보호를 받지 못해 오탈자로 인한 버그 발생 위험도 존재했습니다.
이 문제를 해결하기 위해 기획자와 개발자 간의 협업 워크플로우 전체를 재설계했습니다. Google 스프레드 시트를 단일 진실 공급원으로 함께 정의하고 표준화된 템플릿을 만들었습니다. 이후 이 시트를 기반으로 타입 안정성을 보장하는 TypeScript 모듈까지 자동으로 생성하는 CLI를 개발해 모든 번역 키에 대한 타입 정의, 페이지별 상수, 코드 스플리팅을 위한 동적 import 구문까지 자동으로 생성하도록 설계했습니다.
pnpm i18n 명령어로 기획자의 수정 사항이 사람의 개입 없이 코드에 100% 정확하게 반영되는 파이프라인을 구축해 기존에 30분 이상 소요되던 다국어 적용 작업을 99% 단축시켰습니다. 추가로 모든 번역 키에 대한 TypeScript 자동완성과 컴파일 타임 에러 체크가 가능해져 휴먼 에러를 원천적으로 차단하고 코드의 안정성을 극대화했습니다.
[블로그]
협업/커뮤니케이션 비용 감소와 100% 타입 안정성을 확보한 이벤트 로깅 시스템 설계 및 자동화.
기존 사용자 이벤트 로깅은 기획자가 정의한 스프레드 시트를 기반으로 각 개발자가 임의로 구현하는 방식이었습니다. 이로 인해 로그 이벤트의 네이밍 규칙이 파편화되고 파라미터가 누락되거나 오타가 발생하는 등 데이터 정합성에 심각한 문제가 있었습니다. 로그 정의가 업데이트되어도 코드에 반영되지 않아 추적이 불가능했고, 체계적인 구조가 없어 사용자 퍼널 분석과 같은 깊이 있는 데이터 분석이 불가능한 상황이었습니다.
데이터 기반 의사결정 문화 및 효율적인 협업을 정착시키기 위해 로깅 프로세스 전체를 재설계하고 자동화하는 시스템을 구축했습니다. 위계 질서를 갖춘 로그 스키마를 정의하고 스프레드 시트의 표준 템플릿으로 만들어 데이터의 단일 진실 공급원(SSOT)을 만들고 이를 기반으로 필요한 TypeScript 타입과 상수를 자동으로 생성하는 CLI를 개발했습니다. 아래와 같은 모듈로 TypeScript 컴파일 타임에 이벤트 이름과 파라미터 등을 검증할 수 있도록 설계했습니다.
eventTracker.track({ event_name: 'view_page', /* params */ })
타입 안정성을 100% 확보해 데이터의 신뢰도와 정합성을 극대화했고 로깅 구현의 복잡성을 제거해 정확한 로그를 추가할 수 있는 환경을 구축했습니다. 이 시스템을 통해 수집된 정확한 데이터를 바탕으로 아이엠랩 홈페이지 내 특정 페이지의 이탈률이 40% 이상임을 발견하고 해당 페이지의 성능 최적화를 진행해 이탈률을 17.29%p 감소시키는 직접적인 비즈니스 성과를 창출했습니다.
수작업 100%를 제거한 Asset 최적화 및 코드 자동 수정 CLI 개발.