FRONT-END핵심 역량
인핸드플러스
B2B2C 헬스케어, 2022.06 ~ 2025.11, 프론트엔드
자주 이용하고 싶은 편리한 서비스의 디테일
목표 미션임상시험, 대학병원, 복지관의 복약 관리 담당자 주요 업무를 개선
배포한 서비스 화면 녹화본
로그인 보고서 대시보드 참여자 목록 투약 기록 추가
8초 기다리던 첫 화면을 1.7초로
웹뷰 초기 진입의 다중 API 왕복을 BFF로 집약하고 정적 영역을 SSG로 전환해 첫 화면 LCP 8초 → 1.7초(78%) 단축
- 8초 → 1.7초
- 첫 화면 LCP (78% 단축)
- 3회 → 1회
- 진입 시 API 왕복
- Poor → Good
- 구글이 정한 웹 성능 기준 통과 (LCP 등급)
이 구조가 만들던 사업적 문제
대학병원 임상시험 담당자 한 명이 참여자 100~200명의 복약 순응도를 관리합니다. 참여자 목록과 투약 기록을 하루에도 여러 번 오가야 하는데 화면 하나 여는 데 8초가 걸렸습니다. 기다림이 반복되면 바쁜 담당자는 확인을 미루게 되고, 열지 않는 도구는 고객에게 아무 가치도 만들지 못합니다.
바꿔서 가능해진 것
참여자를 확인할 때마다 붙던 대기가 사라져, 담당자가 100명이 넘는 목록을 끊김 없이 훑을 수 있게 됐습니다. 로딩 지연으로 인한 사용성 문제를 줄였고, 브리지 문제로 로그인이 막히던 경로도 함께 사라졌습니다.
원인
토큰이 sessionStorage와 URL에 있어 JS 실행이 끝나야 첫 요청이 나갈 수 있었습니다. 그 뒤로 인증, 사용자, 전체 참여자와 투약 현황을 순차로 세 번 왕복했고, 마지막 응답에는 모든 참여자의 투약 기록 원본이 한꺼번에 실려 왔습니다. 웹뷰는 이 원본으로 참여자마다 투약 순응도를 직접 계산한 뒤에야 첫 화면을 그릴 수 있었습니다.
해결
1차로 왕복 세 번을 BFF 한 번으로 묶고, 참여자별 투약 순응도 계산을 BFF로 옮겨 화면에는 계산 결과만 보냈습니다. 토큰은 httpOnly 쿠키로 옮겨 BFF가 서버에서 먼저 검증하고, 사용자와 참여자, 투약 현황은 그 뒤 병렬로 가져옵니다(8초 → 3초). 2차로 정적인 영역을 빌드 때 만들어 CDN에서 바로 내보내고, 코드 스플리팅으로 번들을 줄이고, Vercel 함수 리전을 서울로 고정했습니다(3초 → 1.7초).
이 방법을 고른 이유
요청을 브라우저에서 병렬로만 바꾸면 JS 실행 대기와 모바일 네트워크의 왕복 지연은 그대로 남습니다. 왕복 자체를 지연이 짧은 서버 사이로 옮기는 BFF와, 데이터와 상관없는 화면을 미리 만들어 두는 SSG를 함께 써야 두 병목을 모두 없앨 수 있었습니다. BFF는 한 번의 요청 안에서 API를 여러 번 호출하므로, 사용자보다 API 서버와의 거리가 더 중요해 함수 리전을 API 서버가 있는 서울로 고정했습니다.
단계별 첫 화면 LCP
- 1
기존 8.0초
CSR. JS 실행이 끝난 뒤 인증 → 사용자 → 전체 참여자, 투약 현황을 순차로 3번 왕복하고, 받은 원본으로 순응도를 웹뷰에서 직접 계산
- 2
1차 3.0초
BFF로 브라우저 왕복을 1번으로 집약하고 순응도 계산을 서버로, 토큰을 httpOnly 쿠키로 옮겨 서버에서 검증
- 3
2차 1.7초
SSG로 만든 화면 틀(shell)을 CDN에서 제공, 코드 스플리팅, BFF 함수 리전을 서울로 고정
측정: Chrome DevTools 성능(Performance) 탭의 LCP 값
쓰지 않는 시간에도 나가던 인프라 비용 정리
프론트엔드 4개 서비스의 dev, test, release 환경 12개를 AWS ECS에서 Vercel로 옮겨 월 인프라 비용 $278 → $20(93%) 절감
- $278 → $20
- 월 인프라 비용 (93% 절감)
- 상시 12개 → 요청 시만
- 실행되는 환경 (4개 서비스 × dev, test, release)
- Next.js 13 → 14
- 업그레이드로 메모리 사용량 40% 감소
원인
프론트엔드 4개 서비스가 dev, test, release 환경마다 ECS 컨테이너로 떠 있었습니다. 사람이 거의 쓰지 않는 밤과 주말에도, 테스트용 환경까지 12개 컨테이너가 24시간 비용을 냈습니다.
해결
Next.js는 정적 화면과 서버리스 함수로 나눠 돌릴 수 있어 컨테이너를 상시 띄울 필요가 없었습니다. 12개 환경을 Vercel로 옮겨 요청이 있을 때만 실행되게 하고, push하면 자동으로 빌드, 배포되게 했습니다.
백엔드 변경을 에디터에서 바로 잡아내는 타입 자동 생성
백엔드 gRPC .proto에서 TypeScript 타입을 자동 생성해, 필드가 바뀌면 화면이 깨지기 전에 VS Code에서 먼저 감지
- 1
백엔드가 .proto 필드를 바꿔 커밋, 푸시
- 2
프론트엔드에서 package.json의 타입 생성 스크립트 실행
- 3
.proto를 읽어 TypeScript 타입 파일이 자동으로 갱신
- 4
바뀐 필드를 쓰는 코드를 VS Code가 바로 오류로 표시
원인
API 타입을 손으로 옮겨 적으면, 백엔드가 필드를 바꿨을 때 프론트엔드 코드의 어디가 깨지는지 알기 어렵습니다. 화면을 직접 열어 보거나 배포한 뒤에야 발견하게 됩니다.
해결
백엔드의 gRPC .proto 파일로 TypeScript 타입을 만드는 스크립트를 package.json에 두었습니다. .proto가 바뀌면 명령어 한 번으로 타입이 갱신되고, 바뀐 필드를 쓰는 코드는 VS Code에서 바로 오류로 드러납니다. API Route 기반 BFF와 화면이 같은 타입을 써서 응답 형태가 어긋나지 않습니다.
트리피누
B2C 여행, 2021.05 ~ 2022.04, 프론트엔드
시장이 원하는 타이밍에 출시되는 유연한 여행 플랫폼 프론트 설계
목표 미션자유여행자가 일정 계획부터 예약, 결제까지 한 서비스에서 끝내도록
배포한 서비스 화면 캡처

상품 상세 - 일정, 모집 인원, 금액과 예약 진입 
경로 시각화 - 일자별 동선을 지도에 그리고 구간 거리를 함께 표시 
메인 - 기획전 배너와 자유여행 상품 목록 
장소 상세 - 지도를 벗어나지 않고 여는 장소 정보 
예약, 결제 - 예약자 정보 입력과 약관 동의
220개국 여행지 검색과 경로 시각화, 예약, 결제, 환불 시스템 개발, 디자인 시스템 구축
- 220개국
- 여행지 검색과 경로 시각화
- 3개월
- 디자인 시스템을 다시 세운 리팩토링
- 예약 → 결제 → 환불
- 거래 흐름 전 구간
이 구조가 만들던 사업적 문제
내놓아야 할 화면은 계속 늘어나는데 제작 시간과 인력은 부족했습니다. 입사 시점에 디자인 시스템이 이미 무너져 스타일이 여기저기 오염돼 있었고, 화면 하나를 새로 만들 때마다 같은 요소를 다시 그리고 어긋난 스타일을 찾아다녀야 했습니다. 변화에 유연하게 대응하지 못하는 코드는 곧 내놓을 수 있는 제품의 수를 줄입니다.
바꿔서 가능해진 것
3개월 계획을 잡고 오염된 스타일을 걷어내 디자인 시스템을 다시 세웠습니다. 같은 요소를 매번 만들지 않게 되면서 화면을 붙이는 속도를 되찾았고, 부족한 인력으로도 220개국 경로 시각화와 예약, 결제, 환불까지 이어지는 흐름을 만들 수 있었습니다. 구체적인 요구사항이 정해지기 전 단계에서는 대표와 직접 소통하며 아이디어를 빠르게 프로토타입으로 만들어 검증했고, 이렇게 만든 결과물로 시드 투자 유치와 수상에 기여했습니다.
원인
디자인 시스템이 무너진 채로 기능이 먼저 붙으면서 스타일이 컴포넌트마다 제각기 오염됐습니다. 공통 요소를 믿고 쓸 수 없으니 화면마다 다시 만들었고, 한 곳을 고치면 다른 화면이 어긋나 손댈 수 있는 범위가 계속 좁아졌습니다.
해결
3개월 계획을 세워 오염된 스타일을 걷어내고 공통 컴포넌트와 스타일 기준을 다시 정의했습니다. 화면은 그 위에 조립하는 방식으로 바꿔, 이후 기능은 새로 그리지 않고 붙일 수 있게 했습니다.