원의 생각

기록하고, 분석하고, 성장한다

Productivity Notes/Tools & Stack

바이브코딩 Day7: Codex 쓰기 권한 실패와 모바일 SRP/PDP 개선 기록

Gelasio 2026. 5. 8. 07:00

바이브코딩을 하다 보면 가끔 이런 착각을 한다.

 

“AI가 코드를 대신 짜주니까, 이제 나는 기능만 말하면 되겠지.”

 

그런데 오늘은 그 생각이 꽤 순진했다는 걸 다시 배웠다.
오늘 내가 한 일은 멋진 기능 개발이 아니었다.
오히려 반대에 가까웠다.

 

쓰기 권한 하나를 제대로 잡지 못해서 프로젝트 폴더를 옮겼다가, 다시 원래 폴더로 돌아왔다.

 

겉으로 보면 허무한 하루다.
하지만 실제로는 꽤 중요한 교훈이 있었다.

 

바이브코딩에서 사람의 역할은 단순히 “무엇을 만들지 말하는 것”이 아니다.
AI가 작업할 수 있는 환경을 정리하고, 실패했을 때 어디까지 되돌릴지 판단하고, 그래도 오늘의 실질적 개선을 끝까지 만들어내는 일까지 포함된다.

 

오늘은 그걸 제대로 겪은 날이었다.


오늘수영 프로젝트, 문서 정리부터 시작했다

오늘 작업의 출발점은 단순했다.

 

현재 만들고 있는 서비스는 오늘수영이다.
서울 공공수영장을 지도와 목록으로 탐색하고, 사용자가 오늘 갈 수 있는 수영장인지 확인할 수 있게 만드는 서비스다.

 

이미 기본 기능은 어느 정도 만들어져 있었다.

  • 지도에서 수영장 위치 보기
  • 수영장 목록 보기
  • 지역 필터 적용
  • 오늘 운영 여부 확인
  • 상세 화면에서 운영시간, 자유수영, 가격, 전화, 길찾기 확인

문제는 기능보다 작업 관리 방식이었다.

 

그동안 Codex를 쓰면서 PM Agent, Dev Agent, QA Agent처럼 역할을 나눠서 작업을 시도하고 있었다. 처음에는 꽤 좋아 보였다.
PM Agent는 요구사항을 정리하고, Dev Agent는 코드를 수정하고, QA Agent는 검증하는 식이다.

 

그런데 막상 진행하다 보니 문서가 너무 많이 생기기 시작했다.

  • QA 체크리스트 문서
  • 데이터 갱신 Runbook
  • 시설 검수 우선순위 문서
  • PM 업데이트 패치 문서
  • Agent별 역할 문서
  • workflow 문서
  • release checklist 문서

처음에는 체계적으로 보였다.
하지만 어느 순간 이런 생각이 들었다.

 

“내가 지금 서비스를 만들고 있는 건가, 문서 관리 시스템을 만들고 있는 건가?”

 

MVP 단계에서는 문서가 너무 많아지면 오히려 판단이 흐려진다.
오늘수영의 핵심은 문서 체계가 아니라 사용자가 수영장을 잘 찾고, 오늘 갈 수 있는지 판단하는 것이다.

 

그래서 한 번 프로젝트 기준 폴더를 정리해보려고 했다.


프로젝트 루트를 하나로 고정하려다 더 꼬였다

기존 작업 폴더는 날짜별로 나뉘어 있었다.

/Users/sangwon.lee/Documents/Codex/2026-04-28/1-1
/Users/sangwon.lee/Documents/Codex/2026-05-05/...

 

이 구조는 처음에는 편했다.
날짜별 작업을 구분할 수 있었기 때문이다.

 

하지만 시간이 지나니 문제가 생겼다.

 

어떤 폴더가 진짜 프로젝트인지, 어떤 폴더가 임시 작업공간인지 헷갈리기 시작했다.
Codex가 어떤 폴더에서는 파일을 만들고, 어떤 폴더에서는 수정하지 못했다.
문서가 A 폴더에는 있는데 B 폴더에는 없고, 실제 서비스 코드는 또 다른 곳에 있는 식이었다.

 

그래서 오늘은 프로젝트 전용 루트를 하나로 만들려고 했다.

/Users/sangwon.lee/Documents/Codex/today-swim

 

이 폴더를 오늘수영 프로젝트의 기준 루트로 고정하고, 앞으로 모든 작업을 여기에서 하려고 했다.

 

겉으로 보면 합리적인 결정이었다.
서비스 코드, 데이터, 문서가 한 곳에 모이면 관리가 쉬워진다.

 

실제로 파일 복사도 했다.
데이터 checksum도 확인했다.
JS 문법 검사도 했다.
렌더링 안전성 검사도 했다.
CSS 중괄호 균형도 확인했다.

 

검증 결과는 모두 통과했다.

node --check app.js: 통과
npm run check:render: 통과
CSS brace balance: 0

 

여기까지만 보면 성공처럼 보였다.

그런데 진짜 문제는 그 다음이었다.


Codex가 파일을 읽을 수는 있는데, 쓸 수는 없었다

새로운 루트에서 Codex를 실행했다.
작업 디렉토리도 맞았다.

그런데 파일을 수정하려고 하자 계속 실패했다.

Operation not permitted
writing outside of the project

 

처음에는 내가 경로를 잘못 잡은 줄 알았다.
그래서 Codex 실행 옵션을 확인했다.

codex --help

 

여기서 중요한 옵션들을 확인했다.

-C <DIR>
--sandbox workspace-write
--ask-for-approval on-request
--add-dir <DIR>

 

그래서 다시 실행했다.

codex -C /Users/sangwon.lee/Documents/Codex/today-swim \
  --sandbox workspace-write \
  --ask-for-approval on-request

 

그래도 안 됐다.

 

작업 디렉토리는 맞는데, 쓰기 테스트가 실패했다.

touch docs/.codex-write-test

 

결과는 또 실패였다.

이쯤 되니 명확해졌다.

문제는 프로젝트 코드가 아니었다.
문제는 Codex 실행 환경과 macOS 권한, sandbox 설정의 조합이었다.

AI가 코드를 잘 짜는지 이전에, AI가 파일을 실제로 수정할 수 있는 환경이 아니었던 것이다.


결국 다시 원래 폴더로 원복했다

여기서 선택지가 있었다.

 

계속 권한 문제를 파고들 수도 있었다.
프로젝트를 ~/dev 같은 다른 폴더로 옮겨볼 수도 있었다.
Codex 실행 옵션을 더 바꿔볼 수도 있었다.

 

하지만 중간에 생각이 바뀌었다.

 

“지금 내가 해결하려던 문제는 폴더 구조가 아니라 모바일 사용성 개선 아니었나?”

 

맞다.
원래 오늘 하려던 일은 프로젝트 루트 이전이 아니었다.

 

오늘 해야 했던 일은 오늘수영 서비스의 모바일 화면에서 사용자가 더 쉽게 판단할 수 있게 만드는 것이었다.

 

그래서 결론을 냈다.

 

루트 이전은 중단한다.
문서 체계도 더 늘리지 않는다.
기준 폴더는 원래 프로젝트로 되돌린다.

 

최종 기준 폴더는 다시 여기로 정했다.

/Users/sangwon.lee/Documents/Codex/2026-04-28/1-1

 

겉으로 보면 원복이다.
조금 부끄러웠다. (아니, 많이..)

 

몇 시간 동안 폴더를 옮기고, 문서를 정리하고, 권한을 확인했는데 결국 원래 자리로 돌아왔기 때문이다.

하지만 이 판단은 필요했다.

 

더 붙잡고 있었으면 오늘은 아무 기능도 개선하지 못했을 것이다.


그래서 방식을 바꿨다: Codex는 patch만 만들고, 나는 직접 적용했다

쓰기 권한 문제가 계속 발생했기 때문에 작업 방식을 바꿨다.

 

Codex에게 실제 프로젝트 파일을 직접 수정하라고 하지 않았다.
대신 patch 파일만 만들게 했다.

 

구조는 이렇게 바꿨다.

Codex: 코드 분석 → 수정 patch 생성
나: 로컬 터미널에서 patch 적용 → 검증 실행

 

이 방식은 꽤 현실적이었다.

 

Codex가 프로젝트를 읽고 어떤 파일을 어떻게 바꿔야 하는지는 판단할 수 있었다.
다만 직접 쓰기가 안 됐을 뿐이다.

 

그래서 Dev Agent에게 요청했다.

 

수정 대상은 2개로 제한했다.

app.js
styles.css

 

제외 범위도 명확히 했다.

index.html 수정 금지
data/*.json 수정 금지
data/verified-pools.json 수정 금지
데이터 모델 변경 금지
신규 문서 생성 금지

 

목표도 단순하게 잡았다.

 

모바일 SRP/PDP에서 사용자가 “오늘 갈 수 있는 수영장인지” 더 빠르게 판단하게 만들 것.

 

여기서 SRP는 검색 결과 목록 화면이고, PDP는 수영장 상세 화면이다.


실제로 개선한 포인트는 무엇인가

오늘 최종적으로 반영한 개선은 거창한 신규 기능이 아니다.
하지만 사용자 입장에서는 꽤 중요한 개선이다.

 

오늘수영에서 사용자가 정말 알고 싶은 것은 하나다.

 

“이 수영장, 오늘 가도 되나?”

 

그 판단을 위해 필요한 정보는 많지 않다.

  • 오늘 운영하는지
  • 자유수영이 가능한지
  • 가격은 얼마인지
  • 확인이 필요한 정보인지
  • 전화나 길찾기로 바로 이어질 수 있는지

기존 화면은 이 정보들이 있긴 했지만, 모바일에서 읽기 편한 구조는 아니었다.
특히 카드 안 정보가 많아지면 사용자가 한눈에 비교하기 어렵고, 상세 화면에서도 어떤 정보가 확정인지, 어떤 정보가 확인 필요한 정보인지 헷갈릴 수 있었다.

 

그래서 이번 patch에서는 다음을 개선했다.

1. SRP 카드에서 핵심 판단 정보를 더 읽기 쉽게 정리했다

모바일 목록 카드에서는 정보가 조금만 많아져도 금방 복잡해진다.

 

그래서 카드에서 아래 정보들이 겹치지 않고 읽히도록 조정했다.

  • 시설명
  • 지역/주소
  • 오늘 운영 상태
  • 자유수영 여부
  • 가격 또는 확인 필요 상태

핵심은 “정보를 많이 넣는 것”이 아니라, 수영장 후보를 빠르게 비교할 수 있게 만드는 것이었다.

2. PDP 상단에서 방문 판단 정보를 더 빨리 보이게 했다

상세 화면에 들어온 사용자는 이미 어느 정도 관심이 있는 상태다.
이때 사용자가 바로 확인해야 하는 정보는 명확하다.

  • 오늘 운영시간
  • 자유수영 가능 여부
  • 가격
  • 전화하기
  • 지도 보기
  • 길찾기

이번 개선은 이 정보들이 상세 화면에서 너무 흩어져 보이지 않도록 조정하는 데 초점을 뒀다.
사용자가 첫 화면 또는 첫 스크롤 초입에서 판단할 수 있게 만드는 것이 목적이었다.

3. “확인 필요/추정/외부 데이터”를 확정처럼 보이지 않게 했다

이건 오늘수영 같은 서비스에서 꽤 중요하다.

 

운영시간이나 자유수영 정보는 사용자가 실제 방문을 결정하는 정보다.
그런데 이 정보가 확정인지, 외부 데이터 기반인지, 아직 확인이 필요한지 구분되지 않으면 서비스 신뢰도가 떨어진다.

 

그래서 문구와 표시 상태를 더 분명하게 정리했다.

 

사용자에게 “무조건 맞다”고 말하는 대신,
확인이 필요한 정보는 확인이 필요하다고 보이게 하는 것이다.

4. 위치 권한이 없을 때 길찾기 CTA가 막힌 것처럼 보이지 않게 했다

기존에는 위치 권한이 없으면 길찾기 기능이 막힌 것처럼 느껴질 수 있었다.

 

하지만 사용자는 내 위치 기반 길찾기만 원하는 게 아니다.
목적지 기준으로 지도나 길찾기 정보를 확인하고 싶을 수도 있다.

 

그래서 위치 권한이 없어도 CTA가 완전히 차단된 느낌이 아니라, 안내 상태로 보이도록 개선했다.

 

작은 차이지만 모바일에서는 이런 차이가 크다.
버튼이 막혀 보이면 사용자는 더 이상 시도하지 않는다.


patch 적용과 검증

Codex가 만든 patch 파일을 로컬에서 직접 적용했다.

먼저 dry-run으로 충돌 여부를 확인했다.

patch --dry-run -p1 < mobile-srp-pdp.patch

 

결과는 정상이었다.

patching file app.js
patching file styles.css

 

그 다음 실제 적용했다.

patch -p1 < mobile-srp-pdp.patch

 

수정된 파일은 2개였다.

app.js
styles.css

 

적용 후 검증도 다시 실행했다.

node --check app.js
npm run check:render

 

결과는 통과했다.

[render-safety] ok: 113 snapshot records and render guards verified.
CSS brace balance: 0

 

즉, 오늘 최종적으로는 아래까지 완료했다.

  • JS 문법 오류 없음
  • 113개 수영장 데이터 렌더링 안전성 통과
  • CSS 구조 오류 없음
  • 데이터 파일 수정 없음
  • index.html 수정 없음
  • 모바일 SRP/PDP 판단 정보 개선 patch 적용 완료

오늘 실패한 것

오늘의 실패는 분명하다.

 

Codex 쓰기 권한 문제를 해결하지 못했다.

 

더 정확히 말하면, Codex가 프로젝트를 읽을 수는 있었지만 파일을 직접 수정하게 만들지는 못했다.

 

그리고 프로젝트 루트를 정리하려던 시도도 실패에 가깝다.

 

처음에는 today-swim이라는 단일 루트를 만들고, 앞으로 모든 작업을 그곳에서 하려고 했다.
하지만 Codex 권한 문제가 계속되면서 오히려 폴더와 문서가 더 복잡해졌다.

 

결국 다시 원래 프로젝트 폴더로 돌아왔다.

 

이건 솔직히 조금 부끄러운 경험이었다.

 

겉으로 보면 하루 종일 삽질한 것처럼 보일 수 있다.
실제로도 어느 정도는 맞다.

 

하지만 바이브코딩을 하면서 이런 삽질을 피하기는 어렵다.
특히 AI에게 작업을 맡길수록, 사람은 오히려 “작업 환경”과 “작업 단위”를 더 정확히 관리해야 한다.


오늘 배운 것

오늘 가장 크게 배운 것은 이거다.

 

AI가 코드를 잘 짜도, 작업 환경이 정리되어 있지 않으면 아무것도 적용되지 않는다.

 

그리고 두 번째로 배운 것은 이것이다.

 

문서를 많이 만든다고 프로젝트가 체계적으로 되는 것은 아니다.

 

문서가 많아지면 처음에는 안정감이 생긴다.
하지만 MVP 단계에서는 오히려 실행 속도를 떨어뜨릴 수 있다.

 

오늘수영은 아직 대규모 서비스가 아니다.
지금 중요한 것은 PM/QA/Release 문서를 완벽하게 나누는 것이 아니다.

 

지금 중요한 것은 사용자가 모바일에서 수영장을 찾고, 오늘 갈 수 있는지 판단하고, 전화나 길찾기로 이어지는 흐름이 잘 되는지 확인하는 것이다.

 

세 번째 배운 것은 patch 방식의 유용성이다.

 

Codex가 직접 파일을 수정하지 못해도, patch를 만들게 하고 사람이 적용하면 된다.
이건 앞으로도 꽤 유용한 방식이 될 것 같다.

AI가 수정안을 만든다
사람이 적용 여부를 결정한다
로컬에서 검증한다

 

오히려 이 방식이 더 안전할 수도 있다.
AI가 직접 파일을 바꾸는 것보다, 사람이 한 번 더 변경 지점을 확인할 수 있기 때문이다.


오늘의 결론

오늘은 멋진 기능을 만든 날은 아니다.
오히려 “개발 환경 하나 제대로 못 잡고 원복한 날”에 가깝다.

 

하지만 완전히 실패한 날도 아니다.

 

최종적으로는 오늘수영 모바일 화면에서 사용자가 더 빠르게 판단할 수 있도록 SRP/PDP 정보 구조를 개선했고, 자동 검증도 통과했다.

정리하면 오늘 한 일은 이렇다.

구분 내용
실패한 것 Codex 쓰기 권한 해결 실패
되돌린 것 today-swim 루트 고정 시도 중단, 원래 프로젝트 폴더로 복귀
줄인 것 과도한 PM/QA/Agent 문서 체계
바꾼 방식 Codex 직접 수정 → patch 생성 후 로컬 적용
개선한 것 모바일 SRP/PDP에서 운영시간, 자유수영, 가격, CTA 판단 정보 개선
검증한 것 JS 문법, 렌더링 안전성, CSS 구조 검증 통과

 

바이브코딩은 단순히 “AI에게 만들어줘”라고 말하는 일이 아니었다.
오늘은 오히려 그 반대였다.

 

AI가 일할 수 있는 범위를 정하고, 실패했을 때 원복하고, 그래도 사용자를 위한 작은 개선을 끝까지 반영하는 일.

 

그게 오늘 내가 한 일이었다.

 

그리고 아마 실제 제품을 만드는 과정은 이런 날들의 누적에 더 가까울 것이다.