iOS Engineer

김찬희 문제를 추적하고, 구조로 해결하는 iOS 개발자

GPS 기반 라이브 세션, 대용량 운동 데이터 처리, 실시간 시각화까지 — 성능 병목을 직접 찾아내고, 수치로 증명하는 방식으로 개발합니다.

90%
메모리 사용량 절감
40%
CPU 사용량 절감
A16→A14
구동 사양 확장
Swift SwiftUI Combine TCP / UDP Socket SQLite · FMDB GPS · CoreLocation MVVM UIKit Instruments XCTest · UITest Localazy CoreMotion Swift SwiftUI Combine TCP / UDP Socket SQLite · FMDB GPS · CoreLocation MVVM UIKit Instruments XCTest · UITest Localazy CoreMotion
스크롤하여 프로젝트 보기

About

성능을 수치로
증명하는 개발자

Instruments로 병목을 직접 분석하고, 데이터 처리 전반의 구조를 개선하여 CPU 사용량 40%, 메모리 사용량 90%를 절감했습니다. 구조적 개선이 제품의 성능뿐 아니라 지원 가능한 하드웨어 범위까지 바꿀 수 있다는 것을 현업에서 경험했습니다.

GPS 기반 실시간 스포츠 데이터 처리, TCP/UDP 소켓 레이어, 대용량 데이터 저장 구조, SwiftUI + Combine 기반 단방향 데이터 흐름, 다국어 인프라, 테스트 환경 구축까지 — 운영 중인 서비스를 이어받아 시스템 아키텍처와 구조적 문제를 하나씩 개선하며 제품과 함께 성장했습니다.

임베디드 펌웨어와 BLE 통신 개발 경험을 바탕으로 디바이스부터 애플리케이션까지 이어지는 데이터 흐름을 이해하고 있으며, AI 도구로 개선 가설을 빠르게 검증하되 최종 판단은 실제 측정값을 기준으로 합니다. 개선이 제품의 성능과 품질 향상으로 이어지는 것을 중요하게 생각합니다.

WWDC를 비롯한 기술 컨퍼런스를 꾸준히 살펴보며 변화하는 iOS 생태계와 개발 트렌드를 학습하고, 새로운 기술이 실제 제품의 품질과 개발 생산성 향상에 기여할 수 있는지 지속적으로 검토하고 적용하고 있습니다.

기술 스택

프레임워크보다 문제를 먼저 이해하고,
상황에 맞는 구조를 설계하고 기술을 선택합니다.

Language · Framework
Swift SwiftUI UIKit Combine MVVM
Architecture
Clean Modular TCA Protocol-Oriented Design Navigation
Data · Network
TCP / UDP Socket SQLite · FMDB REST API AWS S3
Sensor · Location
GPS CoreLocation CoreMotion WGS84
Quality · Tooling
Instruments XCTest UITest Localazy
Tools
Git · Github Action Tuist Jira Claude Code
Background
Embedded Firmware BLE C / C++ ARM Cortex-M

Project · 2025.02 – 2026.06 · Fitogether

Fitogether Live

GPS 기반 실시간 스포츠 데이터
분석 및 라이브 모니터링 iOS 앱

1,019 commits · 약 17개월

v1.6 → v1.13
+74,183줄 순 증가  ·  266개 신규 Swift 파일
Environment
GPS · TCP/UDP · SQLite · SwiftUI · Combine
실시간 운동 데이터 수집·분석·시각화
Role
실시간 데이터 처리 파이프라인, DB 저장 구조, 소켓 레이어, 성능 최적화, 다국어·테스트 인프라까지 서비스 전반 개선
Impact
CPU -40% · Memory -90% · A16 → A14
운영 중인 서비스를 안정성과 확장성 중심으로 개선

성능 및 안정성 개선

실제 서비스 운영 중 발생한 병목과 메모리 문제를 분석하고 개선했습니다.

Memory · DB

대용량 운동 데이터 저장 성능 개선

  • 실시간 누적 데이터 저장 시 DB 쓰기 backlog 누적으로 메모리 급증 문제 발견
  • DispatchSemaphore로 backlog 상한 제한 — 대기열 누적으로 인한 메모리 증가 방지
  • Batch Transaction + Parameterized Query — 다중 세션 저장을 하나의 트랜잭션으로 처리 + statement 캐시 재사용
90%메모리 절감
CPU · 구동 사양

실시간 데이터 처리 성능 개선

  • Instruments로 가속도 계산 과정의 반복적 자료구조 연산 비용 O(n) 메서드 병목 확인
  • Deque 기반 구조로 전환해 O(1)로 개선하고, DB 접근 방식 개선으로 CPU 사용량 최적화
  • 구조 개선을 통해 A16(iPhone 15급)에서만 동작하던 기능을 A14(iPhone 12급)까지 안정적으로 확장
40%CPU 절감
O(n→1)복잡도 개선
A14최소 사양 확장
Memory · Combine · SwiftUI

장시간 라이브 세션 메모리 누수 방지

  • init·deinit 추적 로그를 추가해 SwiftUI body 재평가마다 ViewModelCombine 구독이 반복 생성되는 문제를 진단
  • ObjectIdentifier 기반 ViewModel 캐싱 구조를 도입해 PlayerManager당 ViewModel 인스턴스를 하나로 유지
  • 비활성 ViewModel 정리와 Combine 구독 해제로 장시간 라이브 세션의 OOM 위험 제거
OOM위험 제거

실시간 스프레드시트 View 최적화

수만 개 셀을 유지하던 View 구조를 2차원 가상화로 전환하고, 상태 변화의 영향 범위에 맞춰 UI 갱신 경계를 재설계했습니다.

Objective · 목적

대규모 실시간 리포트의 반응성 확보

  • 최대 96명 × 327개 지표가 2Hz로 갱신되는 환경에서 끊김 없는 양방향 스크롤 제공
  • 상단 2개 행과 첫 번째 열을 고정하는 Freeze Panes 동작을 유지하면서 View 생성 비용 최소화
  • 부분 갱신 과정에서도 벤칭·Goal·정렬 등 기존 기능의 화면 정합성 보장
31,392최대 Metric View
2HzLive Update
Execution · 실행

View 가상화와 갱신 경계 재설계

  • Instruments로 스크롤 시 ViewGraph 갱신과 ForEach 순회가 반복되는 병목 확인
  • 표 전체를 하나의 UICollectionView로 통합하고 행·열을 함께 가상화해 가시 셀만 생성·재사용
  • Custom Layout에서 contentOffset 기준으로 상단 2개 행과 첫 번째 열을 고정해 Freeze Panes 구현
  • 실시간 값·평균·벤칭·표 구조 변경의 영향 범위를 분류해 직접 갱신, 부분 reload, 전체 reload로 구분
2DVirtualization
ScopedUI Update
Key Results · 결과

상시 View 99% 이상 감소

  • 최악의 상황에서 최대 31,392개였던 상시 View를 화면에 보이는 약 170개 셀로 제한
  • 여러 ScrollView의 Binding 동기화를 제거해 스크롤 중 SwiftUI body·레이아웃 연쇄 갱신 해소
  • Instruments의 주요 비용이 View Graph 갱신에서 실제 평균값 계산으로 이동하고, 부분 갱신에서도 화면 정합성 유지
99%+상시 View 감소
≈170Visible Cell
LINK ↗리팩토링 기록

데이터 구조 개선 및 확장성 확보

지표 추가와 조회 비용을 줄이기 위해 데이터 구조를 재설계했습니다.

MetricMeta · 확장성

지표 확장 비용 N파일 → 1파일로 축소

  • 지표 추가 시 분산된 N개 파일(정의·DB·표시)을 모두 수정해야 하는 구조적 문제
  • MetricMeta로 통합 — 신규 지표 추가 시 수정 파일 N개 → 1개
  • 수백 개의 switch 분기를 valueProvider 기반 구조로 개선, 지표 확장 비용 감소
N→1수정 파일 수
Dictionary · 조회 성능

반복 선형 탐색 → O(1) 해시 조회 전환

  • 매 패킷·렌더마다 Array.first(where:) O(n) 선형 탐색이 반복되어 비용 누적
  • byKey / byDbColumn / byDisplayName 3개 Dictionary 인덱스를 앱 시작 시 한 번만 구축
  • 모든 MetricMeta 조회를 O(1) 해시 조회로 전환
O(1)조회 복잡도

선수 경기 데이터 실시간 분석 서비스 개발

GPS 수신 데이터를 실시간으로 분석·시각화하는 핵심 기능을 직접 설계하고 구현했습니다.

GPS · Combine · SwiftUI

실시간 경기 데이터 수집·분석·시각화

  • SwiftUI + UIKit Custom UI 혼합으로 실시간 데이터 시각화 요구사항 대응
  • Combine 기반 단방향 데이터 흐름을 구성하여 상태 변경을 View까지 안정적으로 전달
  • 다수 선수·328개 지표의 실시간 수치 변화에서도 팀 리포트 화면의 반응성 유지
328Live Metric
GPS · Tactic Board · Canvas · Shape

GPS 기반 상대 좌표 전술 맵 구현

  • GPS 위경도를 경기장 상대 좌표계로 변환하여 실제 위치와 관계없이 동일한 기준의 전술 맵 구현
  • Canvas는 이동 경로 렌더링에, Shape(View)는 선수 마커에 적용하여 확대·축소 시에도 해상도 저하 없는 시각화 구현
  • 선수별 이동 경로와 속도, 선수 간 거리를 cm 단위로 시각화하여 경기 흐름과 공간 활용 분석을 지원
GlobalSupport
Relative상대 좌표계
GPS · 10Hz · Packet History

GPS 속도 이력 기반 스플릿 타임 정밀도 개선

  • GPS 패킷 수신 지연(~0.5s)과 카운트다운 드리프트로 스플릿 판정 오차가 발생하는 원인 분석
  • 60초 분량의 10Hz 속도 이력을 적분해 현재 이동 거리를 실시간 추정함으로써 GPS 패킷 수신 지연의 영향을 최소화
  • 마커 구간 선형 보간을 적용해 스플릿 판정 오차를 5–50ms 수준으로 개선
~1s → 5–50msTiming Error

실서비스 통신 안정성 개선

실서비스 환경에서 발생한 네트워크 장애를 분석하고 자동 복구 가능한 구조로 개선했습니다.

Architecture · APIEndpointV1 · 관심사 분리

API 레이어 역할 분리 및 구조 개선

  • API 요청, 인증, 데이터 저장 로직이 하나의 레이어에 혼재하여 역할 경계가 불명확하고 유지보수 비용이 증가하는 구조를 개선
  • 흩어진 엔드포인트를 APIEndpointV1 enum으로 중앙 관리, withTokenRefresh<T> 래퍼로 401 재시도 중앙화
  • API 레이어는 순수 HTTP 요청/응답만 담당하도록 비즈니스 로직을 분리하여 역할 경계를 명확히 정의
AWS S3 · Presign · Redirect

AWS Redirect 기반 업로드 Endpoint 자동 보정 구조 설계

  • 서명 리전과 버킷 리전 불일치 시 AWS가 반환하는 301 리다이렉트·-1005 오류를 로그 추적으로 분석
  • AWS Redirect 응답에서 실제 Endpoint를 추출해 캐시에 저장, 이후 요청은 올바른 리전으로 직행하는 자동 보정 구조를 설계
  • 재시도 1회 상한으로 무한루프를 방지하고, 복구된 리전은 캐시로 유지해 동일 오류 재발 차단
FTG · Watchdog · Backoff

FTG 추출 무응답 자동 감지 및 재시도

  • 배터리 방전·네트워크 단절 시 FTG 추출 중 앱이 무한 대기 상태에 빠지는 문제 해결
  • DispatchWorkItem 기반 60초 타임아웃으로 무응답을 감지하되, 세대 카운터를 함께 검사해 이전 재시도 주기의 타이머가 현재 흐름을 오탐하지 않도록 격리
  • 백오프 + 랜덤 지터 재시도로 동시 재요청 버스트를 분산해 서버 부하 집중 방지
TCP · UDP · 현장 진단

현장 네트워크 장애 원격 진단

  • 장비 연결 불안정, 데이터 유실 등 현장 장애를 TCP/UDP 소켓 로그와 DB 기록을 교차 분석해 원인 특정
  • 셀·허브·AP 레이어별 연결 상태를 분리 진단해 현장 방문 없이 장애 구간 판별
  • 로그 분석 결과를 기반으로 트러블슈팅하여 개발팀과 원인 분석 및 수정에 활용

사용자 경험(UX) 개선

기술적인 문제가 사용자 경험에 직접 영향을 주는 지점을 찾아 개선했습니다.

WKWebView · JS Bridge · SwiftUI

웹 설정 화면 네이티브 경험으로 개선

  • 앱 내 웹 화면이 브라우저처럼 동작하는 이질감 해결 — JS 인젝션으로 rubber-band·context menu·viewport scale 완전 제거
  • 설정 저장 이벤트를 JS→Native 브릿지로 수신, 저장 중 UI 잠금 + 15초 안전 타임아웃으로 무한 대기 방지
  • ViewController 재사용 구조로 화면 재진입 시 인증 재발급 없이 즉시 복원
UIKit · SwiftUI · 음성인식

선수 자각도(RPE) 입력 경험 개선

  • 경기 직후 코치가 다수 선수의 피로도를 빠르게 기록해야 하는 현장 요구를 전용 화면으로 해결
  • DirectionalPanGestureRecognizer로 수직·수평 방향을 판별해 ScrollView 내 슬라이더 제스처 충돌을 해결
  • 음성 인식 기반 핸즈프리 노트 입력 지원 — 선수 목록·슬라이더·텍스트를 단일 화면에서 처리
Localization · i18n · 3 Languages

글로벌 배포 가능한 다국어 인프라 구축

  • 하드코딩 한국어 문자열 전체를 교체하여 한/영/일 3개 언어 지원 체계 처음부터 설계
  • SDK locale 불일치 시 번역키 노출 문제를 5개 번들 테이블 순회 폴백 체인으로 방지
  • 번역 파일 동기화 Makefile 자동화, 앱 진입 시 로딩 완료 후 UI 노출로 초기 깨짐 제거
3지원 언어
UITest · Unit Test · Page Object

테스트 인프라 구축

  • 도메인별 Unit Test 17종 — Activity, 다운로드 단위 변환, RPE 계산, 라이브 컨트롤 등
  • Page Object 패턴 기반 UITest 29종 (Page 9개 + Flow 20개 E2E 시나리오)
  • 의존성 역전 구조(ActivitySyncing 프로토콜)로 외부 의존성과 도메인 규칙을 분리해 테스트 가능성 확보
17Unit Test
29UITest Flow
Dev Labs · 다부서 피드백

Dev Labs 기반 내부 피드백 루프 운영

  • 개발팀·비즈니스팀·운영팀이 실사용 환경에서 앱을 직접 사용하며 발견한 UX 문제를 수집
  • 데모팀을 통해 실제 현장에 앱을 전달, 코치·선수 관점의 현장 피드백을 추가로 수집해 반영
  • 현장 운영 중 제기된 불편 사항을 빠르게 반영해 기획 의도와 실제 사용 간 괴리를 지속적으로 줄임
Diagnostic · mach_task · AP

현장 진단 도구 개발

  • mach_task_basic_info + vm_statistics64 직접 조회로 앱 RAM·시스템 메모리 상태를 앱 내 실시간 표시
  • TelnetManager로 AP에 진단 명령 전송 — 연결 장비 수·CPU·가동 시간 현장에서 즉시 확인
  • 전체 선수 기기의 CN0·위성 수·RTK Fix 모드 분포를 실시간 집계하고, 신호 저하 발생 위치를 TacticMap에 히트맵으로 오버레이