안녕하세요! 고위드에서 지출관리 서비스를 개발하고 있는 Frontend Engineer 옥지수입니다.
최근 고위드 블로그에서 AI와 함께 일하는 이야기들이 여럿 공유되었는데요. 같은 팀에서 함께 일하고 있는 호준님의 전사 AI 도입 과정, 선주님의 AI 디자인 경험, 그리고 수정님의 FE팀 AI 워크플로우까지 — 한 팀 안에서 각자의 관점으로 AI와 함께 만들어 나간 이야기들이었습니다.
이 글은 조금 다른 이야기예요. 새로 만드는 게 아니라, 이미 있는 것을 살려내야 했던 이야기입니다.
React Native 코드베이스를 내부에서 유지보수 가능한 형태로 다시 만드는 과정에서, 두 번의 실패와 기준을 바꾼 뒤에야 비로소 제대로 된 방향을 찾을 수 있었어요 — Claude Code와 함께. 모바일 개발자가 아닌 웹 프론트엔드 개발자로서 그 과정에서 겪은 시행착오와 배운 것들을 이야기해보려 합니다.
📌 Native에서 React Native로의 전환
고위드는 기존에 안드로이드, iOS 각각의 네이티브 앱을 운영하고 있었지만, 안정적으로 유지보수할 수 있는 환경이 충분하지 않았어요. 웹과 앱 간의 기능 격차가 벌어지기 시작했고, 팀 내 프론트엔드 개발자들이 지속적으로 관리할 수 있는 형태로 전환할 필요성을 느끼게 됐습니다.
이후 React Native 기반의 코드베이스를 확보하게 되었지만, 돌아온 결과물은 저희 팀이 익숙한 개발 방식과는 여러 면에서 차이가 있었어요. React Native니까 모바일 특유의 부분만 익히면, 전체적인 구조는 웹과 크게 다르지 않을 거라고 기대했거든요.
.png%253FspaceId%253Dec7c318e-ad51-4ae9-ad19-932bb33c57b5%3Ftable%3Dblock%26id%3D3308db64-698e-800b-ad6f-efcc8f99e0f4%26cache%3Dv2&w=1920&q=85)
[이미지: 결국 저도 제대로된 RN을 접하지 않았던 웹 개발자였기에, 이런 편견을 가지고 있었어요..]
그런데 막상 열어보니 네이티브 개발에서 쓰이는 클린 아키텍처가 적용되어 있어서 폴더 구조나 용어부터 웹 프론트엔드와 달랐고, API 호출 방식이나 상태 관리 패턴도 저희가 웹에서 써오던 것과는 다른 방식이었어요. lint 설정이나 컴포넌트의 역할 분리 같은 부분도 저희 팀의 기준과는 거리가 있었습니다.
많은 고심 끝에 이 코드를 그대로 이어가기보다는, 내부에서 유지보수하기 편한 방식으로 새로 만들어보기로 했습니다 — Claude Code와 함께. 문제는 이 "새로 만들기"의 기준을 어디에 두느냐였어요. 자연스럽게 기존 RN 코드를 기준으로 삼았습니다. 이미 동작하고 있는 코드니까, 이걸 정리하면 되지 않을까 하는 생각이었죠.
🧨 잘못된 시작
1. API 단위로 교체하기
먼저 상태 관리 패턴과 API호출 방식을 변경하기로 했어요. 서버상태와 클라이언트 상태를 분리시키는게 전체적인 방향을 먼저 잡을 수 있는 것이라고 생각했습니다. 그래서 웹에서 이미 사용하던 OpenApi 코드 제너레이터인 Orval로 API 클라이언트를 생성하고, Claude Code에게 기존 API 호출 로직을 TanStack Query 훅으로 교체해달라고 요청했어요.
하지만 화면 하나의 로직이 너무 길고 복잡하게 얽혀 있었고, 서버 데이터가 로컬 상태로 복사되어 여러 곳에서 참조되는 구조였기 때문에, API 레이어만 깔끔하게 분리해내는 게 불가능에 가까웠습니다. 사람이 봐도 쉽지 않은 코드를 AI가 잘 다룰 수 있을 거라고 기대한 것 자체가 잘못된 전제였어요.
2. 화면 단위로 옮기기
이번에는 Claude Code의 Plan 모드를 활용해서, 기존 화면 파일들을 새로운 폴더 구조로 옮기면서 동시에 리팩토링하는 계획을 세웠습니다. 결과물이 나오긴 했지만, 확인해보니 누락된 컴포넌트들이 곳곳에 있었어요. Plan 자체가 기존 코드를 기준으로 만들어졌기 때문에, 기존 코드에 없던 것은 Plan에서도 빠져 있었던 거예요.
이때 "와, 큰일났다"는 걸 감지했습니다. 정말로요.
3. 기준 변경하기
지난 작업을 돌아보니 두 번의 시도에서 공통적으로 잘못된 게 있었어요. 기존 React Native 코드가 네이티브 앱과 기능적으로 동일하다는 전제로 작업을 진행한 거였습니다. 하지만 실제로는 기존 RN 코드에 누락된 기능들이 있었어요.
아무리 좋은 도구를 써도, 잘못된 기준 위에서 결과는 잘못된 방향으로 갈 수밖에 없었습니다.
그래서 이번에는 기존에 있었던 RN 코드를 기준으로 삼는 걸 멈추고, 실제로 서비스되고 있는 iOS와 Android 네이티브 앱을 레퍼런스로 전환했어요. 이게 이 마이그레이션의 큰 전환점이었습니다.
Claude Code에게 iOS 레포지토리, Android 레포지토리, 그리고 RN 레포지토리를 모두 참조하게 한 뒤, 세 코드베이스를 비교해서 어떤 기능이 누락되었는지 QA 리스트를 만들어달라고 요청했어요. 이전까지는 "이 코드를 옮겨줘"라는 지시였다면, 이제는 "이 앱이 실제로 해야 하는 일이 무엇인지 알려줘"라는 질문으로 바뀐 거였죠.
.png%253FspaceId%253Dec7c318e-ad51-4ae9-ad19-932bb33c57b5%3Ftable%3Dblock%26id%3D3308db64-698e-80b1-9bd1-cd1470680410%26cache%3Dv2&w=1920&q=85)
💡 기준을 바꾸니 생긴 차이
기준을 네이티브 앱으로 전환하자, 작업이 눈에 띄게 달라졌어요.
1. 누락이 드러났다
네이티브 앱에는 있지만 RN에는 없던 기능들이 하나씩 드러났고, 그때마다 iOS나 Android 코드를 참고해서 동일하게 동작하도록 맞춰 나갔습니다. 이전에는 "왜 자꾸 누락이 생기지?"라고 답답해했는데, 원인이 명확해지니 해결도 빨라졌어요.
2. 작업 순서가 잡혔다
이전 시도에서는 마이그레이션과 리팩토링을 동시에 하려다 실패했어요. 기준이 명확해지니, "먼저 동작하게 만들고, 그다음에 정리한다"는 순서를 자연스럽게 지킬 수 있었습니다.
3. AI에게 주는 지시가 정확해졌다
"이 코드를 옮겨줘"가 아니라 "네이티브 앱에서는 이렇게 동작하는데, RN에서도 동일하게 만들어줘"라고 말할 수 있게 되니, Claude Code의 출력 품질도 크게 올라갔어요. AI는 모호한 지시보다 명확한 기준이 있을 때 훨씬 잘 동작하더라고요.
4. Refactoring이 Restructuring을 이끌었다
기능이 동작하는 상태를 확보한 뒤 디자인 시스템 정리에 착수했어요. 그 과정에서 공통 컴포넌트가 잡히니 화면마다 중복으로 선언되어 있던 스타일이 눈에 들어왔고, 어떤 스크린의 구조가 문제인지도 자연스럽게 보였습니다. 하나를 정리하면 다음에 정리할 것이 보이는 흐름이 만들어졌어요.
🛠️ 결과를 검증한 방식
하지만 기준을 바꿨다고 해서 결과가 자동으로 보장되는 건 아니었어요. "제대로 만들어지고 있는지"를 확인하는 과정이 필요했습니다.
1. 수동 QA
E2E 테스트로 자동화하는 방법도 생각해봤지만, 수동으로 직접 하나하나 확인하기로 했습니다. 앱의 모든 화면과 플로우를 직접 눈으로 보면서, 어떤 페이지가 있고 어떤 동작이 일어나야 하는지를 제대로 파악하고 싶었거든요. 자동화는 기준이 명확해진 다음에 해도 늦지 않다고 판단했어요.
2. AI 기반 QA 리스트 생성
자체적으로 QA를 진행하기 위해
/qa-migrate 이라는 skill을 만들어서 네이티브 앱 기준의 기능 명세를 작성하고, RN 앱에서 어떤 사항들이 누락되었는지 표로 정리했어요. 이 QA 문서가 이후 팀원들에게 테스트를 요청할 때 기준이 되어줬습니다.- /qa-migrate: 네이티브 앱 기준으로 기능 명세를 작성하고, RN 앱과의 차이를 표로 정리해주는 skill
.png%253FspaceId%253Dec7c318e-ad51-4ae9-ad19-932bb33c57b5%3Ftable%3Dblock%26id%3D3308db64-698e-80dc-b1a1-cafe65706f2d%26cache%3Dv2&w=1920&q=85)
[이미지: qa-migrate skill로 만든 QA 문서]
작성된 QA문서를 기반으로 작업하고 검증한 뒤, 코드베이스 상으로 문제가 없을지
/review 라는 skill을 통해 반복적으로 검증과정을 거쳤습니다. PR을 생성할 때는 최대 3번의 review를 받고 최종적으로 merge하는 과정을 수행했어요.- /review: Callstack React Native Best Practices 기반의 다단계 리뷰 파이프라인으로 코드 리뷰를 수행하고, critical/warning 이슈를 자동 수정한 뒤 커밋해주는 skill
3. 팀 QA와 버그 수정
하지만 혼자서 하는 QA는 모든 것을 커버할 수 없었어요. 어느 정도 작업이 마무리된 후 팀원들에게 도움을 요청했고, 그 과정에서 약 100건의 이슈가 발견되었습니다. 이 이슈들을 수정할 때도 Claude Code가 큰 역할을 했어요. 약 8개의 세션을 동시에 띄워놓고 병렬로 이슈를 잡아나갔습니다.
.png%253FspaceId%253Dec7c318e-ad51-4ae9-ad19-932bb33c57b5%3Ftable%3Dblock%26id%3D3308db64-698e-801e-b1f0-c9af75d9fd54%26cache%3Dv2&w=1920&q=85)
[이미지: 이슈를 병렬로 처리할 때, 이렇게 8개의 터미널을 띄워놓고 작업하며 더 빠르게 해결할 수 있었어요.]
4. 디자인 QA를 위한 스토리북
기존 앱에는 디자인 시스템이 없어서 디자인 변경이 필요하면 하나씩 들어가봐야하는 문제가 있었어요. 제가 보는 컴포넌트와 디자이너분들이 보는 컴포넌트의 UI차이가 분명히 존재했기에 디자이너분들이 실제 디바이스에서 컴포넌트가 어떻게 보이는지 확인할 수 있어야 했습니다.
그래서 임시 디자인 시스템을 만들면서, 동시에 각자의 기기에서 어떤 컴포넌트가 존재하는지 확인할 수 있도록 스토리북 전용 앱을 구축했습니다. 웹과 달리 모바일 컴포넌트는 브라우저에서 제대로 확인할 수 없으니, 이 과정이 특히 중요했어요. 주요 기능이 담긴 화면들은 MSW와 연동하여 API 모킹 상태에서도 볼 수 있게 했습니다.
.png%253FspaceId%253Dec7c318e-ad51-4ae9-ad19-932bb33c57b5%3Ftable%3Dblock%26id%3D3308db64-698e-80bc-9532-d2b8a78114f0%26cache%3Dv2&w=1920&q=85)
[이미지: 모바일에서도 mock 데이터 기반으로 앱 화면을 쉽게 확인할 수 있게 스토리북 앱을 만들었어요.]
🌳 이 과정을 가능하게 한 환경들
이 마이그레이션을 진행하면서 구축한 작업 환경들을 간단히 소개할게요. 도구 자체보다는, "왜 이런 환경이 필요했는가"에 초점을 맞춰서요.
1. Claude Code skills
웹 개발을 할 때는 사소한 반복 작업 정도는 직접 해도 크게 부담이 없었는데, 앱 개발은 사정이 달랐어요. 빌드하고, 디바이스에 올리고, 확인하고, 다시 고치는 사이클이 웹보다 훨씬 길었거든요. 기능 검증에 집중해야 하는데 그 주변의 작업들에 시간을 뺏기고 싶지 않아서, 반복되는 작업들을 skill로 만들어 나갔어요. 약 15개 정도 만들게 되었고, 그 중에 가장 유용했던 skill들은 아래와 같아요.
- /deploy: Android, iOS, 스토리북 앱을 Fastlane 기반으로 각 환경에 배포해주는 skill
- /reactotron-check: RN 디버깅 전용 앱인 Reactotron 연결 상태를 점검하고 재연결해주는 skill
- /capture-android: USB로 연결된 안드로이드 기기의 화면을 캡쳐해주는 skill
이외에도 저혼자만 이 앱을 유지보수하지 않을 것이란걸 알고 있었기 때문에 온보딩을 쉽게 할 수 있는 skill도 만들어두었어요. 덕분에 바로 새로 기능을 개발해야하는 다른 개발자들이 빠르게 앱 환경에 적응하고 기능을 개발할 수 있었습니다.
- /onboard: React 웹 개발자를 위한 RN 프로젝트 온보딩 가이드 skill (환경 setup > 환경변수 설정 > React Native cheat sheet 의 과정으로 진행됩니다)
- /env-sync: 임시로 notion에 env 값을 명시해놓은 상태에서, notion mcp를 활용하여 개인 레포지토리에 gitignore된 .env.*.ts 파일 혹은 네이티브 앱과 관련된 파일들을 자동으로 불러와 불필요한 파일 전달이 없게 만들어 주는 skill
2. 컨텍스트 분리 워크플로우
4개의 Claude Code 탭을 띄워놓고, 각각 plan, 구현, QA, 리뷰의 컨텍스트로 분리했어요. 각 플로우가 서로 오염되지 않게 유지하는 것이, AI와 병렬로 작업할 때 품질을 지키는 핵심이었습니다. 이슈 수정 단계에서는 이를 8개까지 확장해서 병렬로 처리했어요.
이외에도 AI 코딩 에이전트 오케스트레이터인 oh-my-opencode를 사용하여 각각의 agent들이 병렬로 업무를 처리하여 조금 더 빠른 속도와 정확성을 보장할 수 있었습니다.
🧗 그럼에도 한계는 있었다
기준을 바꾸고, 검증 방식을 갖추고, 도구를 잘 활용했지만 — 모든 게 매끄럽지는 않았어요.
1. 웹 개발자의 감각이 통하지 않는 영역
기능을 맞춰나가는 과정에서 웹과는 전혀 다른 종류의 문제들을 만났습니다. 예를 들어, 첫 번째 Bottom Sheet에서 항목을 선택하면 두 번째 Bottom Sheet가 열리면서 텍스트 입력이 활성화되어야 하는 화면이 있었는데, 아무리 눌러도 입력이 되지 않는 이슈가 있었어요. 디버깅해보니 첫 번째 Bottom Sheet의 렌더링 타이밍이 두 번째 것을 블로킹하고 있었습니다. 웹에서는 거의 마주치지 않는 종류의 문제라, 원인을 추적하는 것 자체가 쉽지 않았어요.
이런 이슈들은 AI도 즉각적으로 해결하기 어려운 영역이었습니다. Claude Code가 점검하고 해결 방향을 잡아주는 역할은 했지만, 모바일 특유의 렌더링 타이밍이나 기기별 차이에서 오는 문제는 결국 직접 디바이스에서 확인하고 디버깅 감각을 쌓아야 했어요.
2. AI가 대신할 수 없는 판단들
앱 스토어 심사는 웹 배포와는 전혀 다른 세계였습니다. 이 부분은 AI가 대신해줄 수 없는 영역이었고, 팀 내에서 앱 배포 경험이 있는 동료 개발자의 도움을 받으면서 하나하나 배워나갔어요.
더 근본적으로는, 잘못된 방향으로 빠르게 가고 있을 때 멈추고 기준을 다시 세우는 판단 자체가 AI가 대신해줄 수 없는 일이었습니다. 두 번의 실패를 거치면서 "이건 아니다"라고 판단한 건 결국 사람이었어요. AI는 작업을 빠르게 해주지만, 어떤 작업을 해야 하는지를 정하는 건 여전히 사람의 몫이었습니다.
3. 수동 QA의 한계
수동 QA를 선택한 것은 초기에 올바른 판단이었지만, 앱이 성장하면서 이 방식만으로는 품질을 지속적으로 보장하기 어렵다는 것도 느꼈습니다. 자동화된 테스트 기반을 갖추는 것은 앞으로 풀어야 할 과제로 남아 있어요.
📔 돌아보며
그렇게 약 2달 끝에, RN앱을 성공적으로 배포할 수 있었어요.
.png%253FspaceId%253Dec7c318e-ad51-4ae9-ad19-932bb33c57b5%3Ftable%3Dblock%26id%3D3308db64-698e-8024-96b2-c5495a9136ae%26cache%3Dv2&w=1920&q=85)
[이미지: 팀원들의 지속적인 응원이 있었기에 더더욱 힘을 내어 마무리 할 수 있었어요..!]
여러 시행착오 끝에 고위드 앱은 이전보다 훨씬 속도를 낼 수 있는 상태가 되었고, 이제 새로운 기능들을 선보일 준비를 하고 있습니다.
이번 마이그레이션을 통해 배운 것들을 정리해보면, 결국 하나로 수렴하는 것 같아요.
AI는 올바른 기준 위에서 써야 한다.
기존 코드가 정상이라는 전제, 부분만 교체하면 된다는 전제, Plan을 세우면 실행은 따라온다는 전제 — 이 전제들이 맞는지 먼저 검증하지 않으면, AI가 아무리 뛰어나도 결과는 어긋났습니다.
웹에서 잘 작동하던 코드베이스 위에서 AI와 작업하는 것과, 기반이 불안정한 코드 위에서 AI와 작업하는 것은 완전히 다른 경험이었어요. 같은 도구를 써도, 출발점의 품질에 따라 AI가 해줄 수 있는 것의 범위가 크게 달라지더라고요.
그리고 AI는 작업을 빠르게 해주지만, 어떤 작업을 해야 하는지를 정하는 건 여전히 사람의 몫이었어요. 특히 잘못된 방향으로 빠르게 가고 있을 때, 멈추고 기준을 다시 세우는 판단은 AI가 대신해줄 수 없는 일이었습니다.
같은 AI 도구를 쓰더라도, 출발점이 잘못되면 속도는 오히려 독이 됐어요. 결국 AI가 빠르게 달려줄수록, 어디서 출발할지를 정하는 사람의 판단이 더 중요하다는 걸 이번 마이그레이션 과정에서 가장 크게 느꼈어요.
"AI로 무언가를 고쳐나갈 때 어디서부터 시작해야 하는가"를 고민하시는 분들께 제 이야기가 조금이나마 도움이 되었으면 좋겠습니다!
Share article