실제 업무에서 겪은 협업을 바탕으로 썼다. 조직, 저장소, 티켓, 사람을 식별할 수 있는 정보는 걷어내고 구조와 판단만 남겼다.
AI와 함께 몇 시간 동안 코드를 여러 번 고쳤다. 구현은 빨랐지만, 정작 요구사항을 제대로 이해했는지는 뒤늦게 돌아보게 됐다.
처음에는 앱 웹뷰에 뒤로가기 버튼을 추가했다. 다음에는 같은 이동 경로의 다른 페이지에도 버튼이 필요하다는 사실을 알았다. 긴 페이지에서 버튼이 스크롤과 함께 사라지는 것을 보고 상단 고정으로 바꿨다. 마지막에는 화면 사이를 이동할 때 풀스크린 상태를 나타내는 쿼리 파라미터가 사라지는 문제까지 고쳤다.
각 수정은 코드만 놓고 보면 타당했다. 타입 체크와 테스트를 통과했고, 기능 플래그로 노출을 제어했으며, QA 환경에도 빠르게 반영했다. 별도 AI 세션으로 변경을 검토하고 리뷰 요청과 배포 기록도 만들었다.
그런데 회고하면서 보니 가장 중요한 일은 거의 하지 않았다.
처음에 무엇을 고쳐달라는 것인지 확인하지 않았다.
TL;DR
- AI는 명확한 요구를 빠르게 구현하지만, 잘못 이해한 요구도 똑같이 빠르게 확장한다.
- 화면의 증상과 수정할 계약은 다르다. 이번 문제의 증상은 “뒤로가기 수단이 없거나 화면 이동 뒤 헤더가 겹친다”였지만, 실제 계약은 “내부 화면을 이동하는 동안 풀스크린 상태를 유지한다”였다.
- 타입 체크, 리뷰, 배포 티켓은 실행을 안전하게 만들지만 요구사항의 범위를 대신 확인해주지는 않는다.
- 구현 전에 진입점, 상태별 경로, 유지할 상태, 외부 경계, 완료 조건을 짧게 맞췄다면 대부분의 재작업을 피할 수 있었다.
빠르게 고친 하루
시작은 단순해 보였다. 앱 안의 특정 웹 화면에서 네이티브 헤더가 보이지 않으니, 사용자가 돌아갈 수 있도록 웹 헤더와 뒤로가기 버튼을 추가하는 일이었다.
나는 이 설명을 그대로 구현 단위로 받아들였다.
- 첫 번째 웹 화면에 뒤로가기 버튼을 추가했다.
- 기능 플래그가 켜진 웹뷰에서만 보이도록 했다.
- 서버에서 웹뷰 여부와 기능 플래그를 확정해 첫 화면부터 버튼이 보이게 했다.
- 타입 체크와 테스트를 돌리고 QA 환경에 반영했다.
여기까지는 빨랐다. 구현 세션은 코드를 고치고 검증했으며, 다른 세션은 리뷰 요청과 배포 기록을 정리했다. 모바일 개발자도 QA 앱에서 곧바로 확인할 수 있었다.
그러나 확인이 시작되자 범위가 달라졌다.
카드가 없는 사용자는 첫 화면에 머무르지 않고 별도의 혜택 랜딩으로 이동했다. 그 페이지에도 뒤로가기 버튼이 필요했다. 버튼을 추가하고 보니 긴 랜딩을 스크롤할 때 버튼이 사라졌다. 기존의 상단 고정 탭과 겹치지 않도록 두 개의 고정 영역을 쌓고, 앵커 이동 위치까지 보정했다.
이것도 해결하고 나서야 진짜 원인이 드러났다.
모바일 앱은 최초 진입 URL에 이미 fullscreen=true와 같은 상태를 넣고 있었다. 네이티브 헤더를 숨기는 것은 웹 코드가 아니라 이 진입 계약이었다. 문제는 첫 화면에서 다음 내부 화면으로 이동할 때 그 값이 사라졌다는 점이었다.
나는 “뒤로가기 버튼을 추가해 달라”고 이해했지만, 실제 요구는 다음과 같았다.
모바일 앱이 만든 진입 URL
-> 내부 브릿지
-> 내부 혜택 랜딩
-> 내부 신청 브릿지
-> 외부 결제 페이지
- 내부 도메인 사이를 이동할 때는
fullscreen=true를 유지한다. - 외부 결제 도메인에는 그 값을 전달하지 않는다.
- 풀스크린 웹뷰에서는 네이티브 헤더가 없으므로 웹 뒤로가기 수단을 제공한다.
- 기능 플래그를 끄면 기존 노출 방식으로 돌아갈 수 있어야 한다.
버튼은 이 계약의 한 결과였을 뿐이다.
화면의 증상을 요구사항으로 받아들였다
“뒤로가기 버튼이 없다”는 것은 사용자가 보는 증상이다. 그것만으로는 무엇을 고쳐야 하는지 결정할 수 없다.
네이티브 헤더가 왜 사라졌는지, 어떤 URL이 웹뷰의 모드를 결정하는지, 사용자가 상태에 따라 어느 화면으로 이동하는지, 내부 도메인과 외부 도메인의 경계가 어디인지 먼저 확인해야 했다.
하지만 나는 첫 번째 화면의 코드부터 열었다. 버튼을 렌더하고, 기능 플래그를 연결하고, 깜빡임을 없애는 데 집중했다. 그 뒤에 이어지는 경로는 QA에서 문제가 보일 때마다 하나씩 발견했다.
그래서 모든 수정이 국소적으로는 맞았다.
- 첫 화면에 버튼이 없는 문제를 고쳤다.
- 다음 화면에도 같은 버튼을 넣었다.
- 스크롤하면 버튼이 사라지는 문제를 고쳤다.
- 두 개의 상단 고정 영역이 겹치는 문제를 고쳤다.
- 마지막으로 화면 이동에서 쿼리 파라미터가 사라지는 문제를 고쳤다.
문제는 맞는 코드를 잘못된 순서로 만들었다는 것이다. 이 계약을 처음부터 알았다면 첫 번째 변경부터 전체 이동 경로를 기준으로 설계하고 테스트할 수 있었다.
AI는 현재 가설을 아주 성실하게 확장한다
AI 구현 세션은 이번에도 빨랐다. 현재 브랜치를 확인하고, 관련 코드를 찾고, 기능 플래그의 기존 패턴을 재사용했다. 타입 오류가 나면 호출 계약을 추적했고, QA 브랜치에 필요한 변경만 분리해 반영했다.
문제가 생길 때마다 수정과 검증은 짧은 주기로 끝났다.
하지만 AI가 검증한 것은 대부분 내가 준 현재 가설 안의 정합성이었다.
이 페이지에 같은 버튼을 넣을 수 있는가?
두 개의 상단 고정 영역을 겹치지 않게 만들 수 있는가?
현재 URL의 풀스크린 값을 다음 내부 URL에 보존할 수 있는가?
이 질문들에는 잘 답했다. 반면 처음에 필요했던 질문은 달랐다.
모바일 앱은 어떤 조건으로 네이티브 헤더를 숨기는가?
사용자가 거치는 전체 URL은 무엇인가?
어떤 상태를 어디까지 전달하고, 어느 경계에서 끊어야 하는가?
버튼 추가가 원래 요청인가, 끊어진 상태 전파를 보완하는 수단인가?
AI가 이 질문을 절대 할 수 없다는 뜻은 아니다. 다만 내가 구현을 요청하면 에이전트는 구현 가능한 단위로 문제를 빠르게 좁힌다. 잘못 좁힌 경계를 명시적으로 의심하게 하지 않으면, 그 안에서 매우 그럴듯한 결과를 만든다.
속도가 빨라질수록 이 특성은 더 위험해진다. 사람끼리 작업하면 첫 번째 수정에 반나절이 걸려 중간에 대화가 끼어들 수 있다. AI와 작업하면 첫 번째 가설을 검토할 틈도 없이 코드, 테스트, PR, QA 반영까지 끝날 수 있다.
AI는 잘못된 방향에서 헤매는 일을 없애주지 않는다. 오히려 그 방향으로 더 멀리 가는 데 걸리는 시간까지 줄여준다.
리뷰와 배포 절차가 대신해주지 못한 것
이번 작업에는 검토 절차가 없었던 것이 아니다.
- 구현과 별도로 코드 리뷰를 요청했다.
- 타입 체크와 관련 테스트를 돌렸다.
- 기능 플래그를 사용했다.
- QA 환경에 먼저 반영했다.
- 배포 기록과 롤백 방법을 정리했다.
이 장치들은 모두 가치가 있었다. 실제로 타입 계약이 서로 다른 두 변경이 합쳐지며 생긴 오류도 잡았고, 운영 반영 전에 모바일 개발자가 실제 흐름을 확인할 수 있었다.
그러나 이 장치들은 만들어진 변경이 안전한지를 확인한다. 처음부터 올바른 변경을 만들고 있는지까지 자동으로 보장하지는 않는다.
코드 리뷰는 주어진 diff의 위험을 찾는다. 타입 체크는 호출 계약이 맞는지 본다. 배포 티켓은 변경 범위와 복구 절차를 남긴다. 어느 것도 “사용자는 이 화면 다음에 어디로 가는가”라는 제품 질문을 대신하지 않는다.
실행 절차는 갖춰져 있었지만 요구사항 확인 절차가 비어 있었다.
다음부터 먼저 적을 다섯 줄
이 일을 거창한 프로세스로 해결하고 싶지는 않다. 구현 전에 다음 다섯 줄만 상대와 맞춰도 충분하다.
진입 URL: 사용자는 어디에서 어떤 상태로 들어오는가?
상태별 이동: 조건에 따라 다음 화면이 어떻게 달라지는가?
유지할 상태: 쿼리, 쿠키, 기능 플래그 중 무엇을 이어야 하는가?
외부 경계: 어느 도메인 경계부터 상태를 넘기면 안 되는가?
완료 조건: 어떤 계정과 경로로 무엇을 확인하면 끝나는가?
이번 작업에 적용했다면 다음과 같이 쓸 수 있었다.
| 항목 | 확인할 내용 |
|---|---|
| 진입 | 앱이 풀스크린 상태가 담긴 내부 브릿지 URL을 연다 |
| 사용자 상태 A | 카드를 보유하면 외부 관리 화면으로 이동한다 |
| 사용자 상태 B | 카드가 없으면 내부 혜택 랜딩으로 이동한다 |
| 상태 유지 | 내부 브릿지와 랜딩 사이에는 풀스크린 상태를 보존한다 |
| 외부 경계 | 외부 결제·관리 URL에는 내부 웹뷰 상태를 붙이지 않는다 |
| 완료 조건 | 카드 보유·미보유 계정 모두에서 헤더가 겹치지 않는지와 복귀 동작을 확인한다 |
이 표를 먼저 공유했다면 “버튼 하나”라는 해석이 오래 살아남기 어려웠을 것이다. 서로 다른 직군도 코드 대신 사용자 경로를 보며 빠진 조건을 지적할 수 있다.
빠른 대응과 좋은 이해는 다른 능력이다
이번 작업에서 기술 대응은 빨랐다. 문제가 확인되면 롤백하고, 수정하고, 타입 체크하고, QA에 다시 올리는 과정은 잘 작동했다. AI를 구현, 검증, 리뷰와 기록에 나눠 쓴 것도 도움이 됐다.
하지만 빠르게 대응했다는 사실로 요구사항을 잘 이해했다고 말할 수는 없다.
나는 화면 증상을 구현 요청으로 받아들였고, 전체 이동 경로를 묻지 않았다. 대화에서도 이 경로가 실행 가능한 계약으로 정리되지는 않았다. 그 빈칸을 코드가 채우기 시작했고, AI는 그 코드를 빠르게 완성했다.
다음에는 구현 속도를 늦추려는 것이 아니다. 오히려 그 속도를 제대로 쓰기 위해 첫 수정 전에 경계를 확인하려 한다.
고치는 속도는 이미 충분했다. 부족했던 것은 고칠 대상을 실행 가능한 계약으로 만드는 일이었다.
AI와 함께 일할수록 이 한 단계가 더 중요해진다. 잘못 이해한 요구도 AI는 빠르게 구현하기 때문이다.