오경식 · iOS Engineer 포트폴리오 경력기술서 인쇄하면 A4 규격 PDF가 됩니다 · P

오경식

iOS Engineer

신규 iOS 서비스의 초기 개발을 주도하고, 출시 이후에는 팀과 함께 유지보수와 기능 개선을 진행해온 iOS 개발자입니다. 2023년 핵심 앱의 네이티브 전환에 팀으로 참여한 뒤, 2024, 2025, 2026년 매년 신규 앱을 하나씩 iOS 단독으로 출시했습니다. 신규 앱 3종은 저장소 개설부터 출시, 운영까지 전 과정을 담당했습니다.

4년 연속 앱 첫 릴리스

2023 큐마켓 v4.0.0 · 08-01 · 네이티브 전환
2024 파트너스 v1.0.0 · 06-14
2025 햇배달 v1.0.0 · 11-07
2026 케이마켓 v1.0.0 · 04-26

Introduce

요구사항이 정리되지 않은 상태에서 시작하는 일이 많았습니다. 그럴 때는 되물어서 정의를 끌어내고, 기획에 없던 사용성 이슈는 구현 과정에서 찾아 제안했습니다. 배달 기사 앱의 스크롤, 정렬 인지 삽입, 케이마켓의 선별적 로딩 인디케이터가 그렇게 추가된 요구사항입니다.

개별 기능 구현보다 서비스 도메인과 확장성을 고려한 구조를 만드는 것을 중요하게 생각합니다. 아래 기술적 의사결정에 3년간 내린 판단 6건을 정리했습니다. 되돌린 결정과 그 선택이 치른 비용까지 함께 적었습니다.

Experience

(주)애즈위메이크 iOS Developer · 2023.05 ~ 2026.07 · 3년 2개월

동네 마트 기반 커머스 플랫폼 스타트업. 재직 기간 중 1개 리뉴얼 프로젝트 및 3개 신규 앱 출시에 iOS 개발로 참여했습니다.

기술적 의사결정

3년간 4개의 앱에서 내린 판단입니다. 검토한 대안과 선택의 근거, 그리고 그 선택이 치른 비용까지 적었습니다.

01

사내 공통 아키텍처를 도입하다 되돌린 판단

햇배달 · 2025 · MVVMC → Screen + ViewModel + Subview

새로 합류한 팀원이 MVVMC를 제안했고 전사 프로젝트에 적용하는 방향이 잡혔습니다. MVVM에 Coordinator를 두어 상태 통제와 인터랙션 수용을 전담시키는 사내 고유 구조로, 신규 앱이던 햇배달이 첫 적용 대상이 됐습니다. 도입에 착수했으나 초기 단계에서 방향을 바꿨습니다.

  • Coordinator가 상태 통제와 인터랙션 수용을 모두 떠안는 구조라, 화면이 복잡해질수록 함께 비대해졌습니다
  • 화면이 필요로 하는 것이 전부 Coordinator를 경유하면서 의존성이 한 곳으로 몰렸습니다
  • SwiftUI는 뷰가 상태를 소유하는 것이 전제입니다. NavigationStackpath 자체가 이미 상태인데 Coordinator가 이를 다시 감싸면서 이중 상태 관리가 됐습니다

대신 최상위 화면을 Screen으로 명명하고 하위 뷰가 각자 자신의 ViewModel을 소유하도록 해서, 한 객체가 화면 전체의 상태를 떠안지 않게 했습니다.

결정 과정 제안한 사람도 팀원이었고 되돌리는 결정도 개인 판단이 아니었습니다. 매주 스크럼에서 구조를 논의해오던 중 위 문제들을 공유했고, 팀 전원이 동의한 방향으로 전환했습니다. 기존 코드 전체에 적용하지는 못했고 신규 작업분과 손대는 화면을 중심으로 점진적으로 맞춰 나갔습니다.
02

실시간 통신 수단으로 SSE를 택한 이유

햇배달 · 2025 · WebSocket vs SSE

기사 앱의 핵심은 신규 주문을 실시간으로 받는 것이었습니다. 데이터 흐름은 서버 → 클라이언트 단방향이었고, 기사 단말이 서버로 실시간 신호를 보낼 일은 없었습니다.

  • WebSocket — 양방향 통신이 가능하지만 이 도메인에는 클라이언트 → 서버 실시간 채널이 필요 없었습니다
  • SSE — 단방향 전용으로 요구사항과 일치했습니다
  • 폴링 — 주문 발생과 인지 사이에 지연이 생기고, 대부분 빈 응답인 호출 비용이 커서 제외했습니다
  • 사일런트 푸시 — 실시간 전파의 주 수단으로 쓰기에는 전달 보장이 약해 제외했습니다

SSE를 채택했습니다. 결정적이었던 것은 사내 다른 웹 서비스가 이미 SSE를 운영 중이었다는 점입니다. 구축된 시스템을 그대로 쓸 수 있었고, 백엔드팀도 이를 근거로 SSE를 선호해 협의 끝에 함께 결정했습니다. WebSocket을 골랐다면 클라이언트와 서버 양쪽에 신규 구축 비용을 새로 만드는 선택이 됐을 것입니다.

선택의 대가 SSE는 앱이 백그라운드에 있는 동안 이벤트를 받지 못합니다. 포그라운드 복귀 시점에 대시보드를 자동 재동기화하고, 재연결 시 전체 페이지를 다시 받아 캐시와 비교 동기화하는 것으로 메웠습니다. 다만 단절 구간에 페이지 사이즈(30건)를 넘는 주문이 쌓이면 누락 가능성이 남습니다. 팀에 공유하고 출시 일정을 고려해 후속 과제로 합의했습니다.
03

모듈을 나누기 전에 폴더부터 다시 그은 이유

케이마켓 · 2026.05 ~ 06

케이마켓은 4.5개월 만에 출시한 앱이라 구조가 레이어 우선이었습니다. 사내 다른 iOS 앱은 이미 모듈 분리가 끝나 있었고 케이마켓만 단일 타깃으로 남아 있었습니다.

그런데 레이어 우선 구조에서는 모듈을 바로 뽑을 수 없었습니다. 한 기능의 코드가 여러 폴더에 흩어져 있으면 모듈 경계를 그을 수 없기 때문입니다. 장바구니를 모듈로 만들려면 Entities/Cart, Presentation/Cart, APIs/ 조각을 먼저 한곳에 모아야 했습니다.

한 도메인으로 검증한 뒤 나머지에 적용했습니다.

  • Order 도메인 하나만 Step 1~8로 쪼개 분리하고, 그 절차를 Clean Architecture 가이드로 문서화했습니다
  • 확립한 절차로 나머지 11개 도메인을 분리했습니다
  • Domains/Shared를 신설해 공용 자산을 명시적으로 격리했습니다. 모듈로 나눌 때 생길 순환 의존을 미리 차단하기 위해서입니다
  • 각 Step을 독립 커밋으로 유지해 단계마다 동작 보존을 검증했습니다
이 판단의 대가 레이어 규칙이 폴더로 강제되지 않습니다. 이전에는 Presentation/에 있으면 무조건 표현 계층이었지만, 지금은 각 도메인 안에서 레이어를 지키는 것이 규율에 달려 있습니다. 인원이 늘면 흐트러질 여지가 있어 가이드 문서화를 함께 진행했습니다. 모듈 분리 착수 전 프로젝트 소유권이 베트남 지사로 이관되어, 구조 작업을 마친 뒤 README, ARCHITECTURE, SETUP 문서를 재구성해 인계했습니다.
04

기획이 없는 구간에 디자인 시스템을 먼저 만든 판단

케이마켓 · 2026.01 ~ 02

케이마켓은 요구사항 정의도 기획도 없는 상태에서 시작했습니다. 참여자 전원이 0에서 1을 만들어야 하는 조건이었고, 기획이 나오지 않은 단계에서 화면부터 그리는 것은 성립하지 않았습니다.

화면을 만들 수 없는 구간을 비워두는 대신, 기획과 무관하게 어차피 필요해질 것을 먼저 만들기로 했습니다. 마침 디자이너가 이전부터 준비하던 디자인 시스템이 있었고, 사내 다른 서비스에도 적용하려던 것이어서 여기서부터 시작하자는 데 합의했습니다.

KM 컴포넌트 12종과 타이포그래피 체계를 먼저 구축했고, 기획이 확정된 뒤 화면 20여 개를 이 컴포넌트로 조립했습니다. 4.5개월 만에 출시할 수 있었던 배경 중 하나입니다.

이 판단의 대가 기획이 없는 상태에서 만들었기 때문에 컴포넌트의 경계를 미리 확정해야 했습니다. 기획이 붙으면서 그 경계에 안 맞는 요구가 나왔습니다. 상품을 보여주는 컴포넌트를 A, B, C 세 종류로 정의해뒀는데, 조금 다른 D가 뒤늦게 등장하는 식이었습니다. D를 넣으려면 기존 코드를 크게 고쳐야 했습니다. 그때마다 디자이너와 조율했습니다. 쓰이는 곳이 한정적이면 컴포넌트로 만들지 않고 예외로 두고, 앞으로 사용처가 많겠다고 판단되면 코드를 전면 수정했습니다. 어디까지를 컴포넌트로 볼 것인지가 명확하지 않아 부딪힌 지점이기도 합니다.
지금이라면 같은 상황이면 같은 선택을 합니다. 치른 비용보다 얻은 것이 컸습니다. 기획이 없는 구간에 화면을 추측해서 그리면 기획이 확정된 뒤 대부분 버리게 됩니다. 다만 컴포넌트를 확정하기 전에 어디까지를 컴포넌트로 보고 어디부터는 예외로 둘지, 그 기준을 디자이너와 먼저 합의했을 것입니다.
05

전용 기간 없이 2년에 걸쳐 레거시를 전환한 방식

파트너스 · 2024.08 ~ 2026.01

파트너스는 웹 서비스를 iOS로 전환한 앱으로 초기에는 단일 타깃 레거시 구조였습니다. 출시 후 기능이 계속 추가되면서 구조 개선이 필요해졌지만, 리팩토링 전용 기간은 확보할 수 없었습니다. 기능 개발은 계속 들어왔고, 한 번에 바꾸는 범위가 클수록 장애가 일정에 타격을 줄 위험도 커졌습니다.

그래서 기능 개발에 얹어서 조금씩 바꾸는 방식을 택했습니다. 특정 기능이 들어갈 때 그 기능이 닿는 범위의 구조를 함께 정리하는 식입니다. 리팩터링 커밋이 전체의 46.5%(239건)에 이르는 것이 이 방식의 결과입니다. 구조 개선에 따로 시간을 쓴 것이 아니라, 기능 작업마다 구조를 조금씩 밀어올린 누적입니다.

사전에 설계한 것은 아니지만 결과적으로 의존 순서를 따라갔습니다.

  • MVVM-C 도입 — AppCoordinator 구현, ViewModel Action 패턴 통일
  • Clean Architecture — Repository, Usecase 분리, Domain Entity 정의, DTO 도입
  • SPM 멀티모듈 분리 — Domain / Data / Presentation / API
  • 네비게이션 재설계 — 화면별 dismiss 산재 제거, 루트 뷰 단일 관리
이 방식의 대가 2년이 걸렸습니다. 전용 기간을 잡을 수 있었다면 훨씬 짧게 끝났을 작업입니다. 새 구조와 옛 구조가 공존하는 구간도 길어서, 신규 코드를 어느 쪽에 맞출지 매번 판단해야 했습니다. 같은 제약이라면 같은 방식을 택하겠지만, 중간 상태의 규칙은 더 일찍 문서로 못 박았을 것입니다.
06

정책 변경이 만든 계산 충돌을 1년 만에 근본 해결한 과정

큐마켓 · 2024.01 ~ 2025.02

1차 출시 당시 큐머니(포인트)는 전액 사용이 가능했고 쿠폰과의 동시 적용은 막아둔 상태였습니다. 계산 정합성이 확실치 않은 조합을 5개월 출시 일정 안에서 여는 것은 결제 금액이 틀어질 위험을 안는 선택이었기 때문입니다.

2024년 1월 구매 금액의 20%까지로 한도 정책이 도입되면서 상황이 달라졌습니다. 한도를 계산할 기준 금액을 쿠폰 할인 전으로 볼지 후로 볼지에 따라 결과가 달라졌기 때문입니다.

  • 2024.01 — 한도 계산 시 쿠폰 할인금액을 제외하도록 처리
  • 2024.06 — 반대로 쿠폰 사용가능 여부 계산 시 큐머니 적용 금액을 제외

두 값이 서로의 계산에 들어가려는 구조였습니다. 한쪽을 맞추면 다른 쪽이 어긋났고, 계산 책임이 여러 곳에 흩어져 있어 전체를 한눈에 검증할 수 없었던 것이 반복의 원인이었습니다. 2025년 2월, CalculateQMoneyUsageLimitUseCase로 계산을 분리하고 큐머니 최대 사용과 쿠폰 사용을 같은 UseCase에서 처리하도록 통합한 뒤 테스트케이스로 결과를 고정했습니다. 계산 책임이 한곳에 모이면서 재발이 멈췄습니다.

지금이라면 정책이 바뀔 때 계산이 얽히는 지점을 먼저 찾았을 것입니다. 한도와 쿠폰이 서로를 참조하는 구조라는 것은 한도 도입 시점에 이미 드러나 있었습니다. 그때 계산 책임을 한곳으로 모았다면 이후 1년간 케이스마다 개별 대응한 비용을 치르지 않았을 것입니다.

Projects

각 프로젝트에서 무엇을 만들고 어떻게 구현했는지는 경력기술서에 정리했습니다. 여기서는 배경과 규모만 적었습니다.

케이마켓 — 베트남 현지 커머스 앱

개발 2026.01~04 · 운영 ~2026.06 | iOS 단독 | Swift · SwiftUI · Swift Concurrency · MV

베트남 현지 한인마트와의 계약으로 시작한 신규 앱입니다. iOS를 단독으로 맡아 요구사항 정의부터 앱스토어 출시까지 4.5개월 만에 완료했습니다. 한국어, 영어, 베트남어 3개국어를 지원하며, 국내 참고 자료가 거의 없는 현지 소셜 로그인(Zalo OAuth)은 SDK를 로컬 SPM 패키지로 래핑해 의존성을 격리했습니다.

4.5개월요구사항 정의 → 앱스토어 출시 (iOS 단독)
3개국어한국어 · 영어 · 베트남어
12분리한 도메인

햇배달 — 배달 기사용 실시간 주문 처리 앱

기획, 개발 2025.02~11 · 운영 ~2026.07 | iOS 단독 | Swift · SwiftUI · Swift Concurrency · SSE

마트가 자체 기사를 운영하거나 외부 호출 서비스(건당 4~6천원)에 의존하던 구조를, 자사 기사 전용 앱으로 대체하기 위한 신규 사업입니다. 기획 단계부터 참여해 출시 후 기능 개선까지 담당했습니다. Android 1명, 백엔드 1명, 기획, 디자인 각 1명과 함께했고 iOS는 단독으로 맡았습니다.

7개 마트운영 중
48사용 중인 배달 기사
7,000월 배달 처리량

파트너스 — 마트 운영자용 주문 관리 앱

앱 전환 개발 2024.03~07 · 운영 ~2026.05 | iOS 단독 | Swift · SwiftUI · Swift Concurrency · MVVM-C

마트 운영자가 주문 확인을 위해 매번 데스크탑을 사용해야 한다는 불편이 반복적으로 제기되어, 모바일 앱 전환을 프로덕트팀에 직접 제안해 시작한 프로젝트입니다. v1.13.0까지 2년간 운영하며 레거시 단일 타깃 구조를 SPM 멀티모듈로 전환했습니다.

46.5%리팩터링 커밋 비중 (239건)
2무중단 아키텍처 전환
v1.13.0운영 중 도달한 버전

큐마켓 — 동네 마트 커머스 앱

전환 개발 2023.05~09 · 운영 ~2026.07 | 팀 개발 (주니어 4명 + 팀장 1명) | Swift · UIKit · Combine · MVVM

사업 확장에 따른 하이브리드 앱의 성능 한계를 해소하기 위한 네이티브 iOS 전환 프로젝트입니다. 해당 프로젝트 수행을 위해 합류했고, v4.0.0 출시 이후 v5.19.0까지 3년간 개발과 운영을 이어서 담당했습니다.

8천 → 37만해당 기간 서비스 누적 가입자
4.7앱스토어 평점 유지
v4.0 → v5.193년간 담당한 버전 구간

Skills

Language & UI
Swift · SwiftUI · UIKit
Concurrency
Combine · Swift Concurrency
Architecture
MVVM · MVVM-C · MV · Clean Architecture · SPM 멀티모듈 · DI 컨테이너
Networking
Moya · SSE · WKWebView (JS 브릿지, 커스텀 스킴 핸들링)
CI / CD
Xcode Cloud · Fastlane · GitHub Actions
기타
Unit Test (UseCase 레벨) · 코드 리뷰 · Claude Code 기반 개발 자동화

Education

2022.04.11 ~ 2022.10.07 야곰아카데미 [커리어스타터 캠프 6기]
2022.02.07 ~ 2022.03.19 야곰아카데미 [코드스타터 캠프 3기]
2011.03 ~ 2017.02 부경대학교 화학과 졸업
오경식 · iOS Engineer unchain123@kakao.com