기능은 잘 돌아가고 있었습니다
NB2B 코치 앱들이 한동안 안정적으로 굴러가고 있었습니다. Claude Code 와 같이 만들어 온 것들이 자기 몫을 하고 있었고, 다음 단계는 자연스럽게 “이제 화면을 더 정돈할 차례” 였습니다.
그래서 Claude Design 에 디자인 정비를 맡겨 보기로 했습니다. 코드는 Claude Code, 디자인은 Claude Design — 둘이 합쳐지면 완성도가 한 단계 올라가겠다. 그렇게 기대했습니다.
그런데 회색지대가 있었습니다
Claude Design 이 산출물을 내놓을 때, 그건 디자인 명세이지 코드가 아닙니다. 단계 이름, 화면 구조, 데이터 흐름의 가정 — 모두 디자인 입장에서 합리적으로 정돈된 형태로 옵니다.
그걸 받은 Claude Code 는 새로운 기준 으로 받아들이고, 그에 맞춰 코드를 다시 짭니다. 화면이 새로 떴을 때 모양은 새 디자인대로 잘 떠 있습니다.
다만 디자인은 그 안의 코드를 모르고, 코드는 디자인이 왜 그렇게 정돈했는지 모릅니다. 그 사이의 회색지대에서 무너집니다.
다행히, 라이브 앱은 그대로 두고 테스트 환경에서 작업했습니다
디자인 업그레이드 작업은 라이브로 돌아가는 앱과 분리된 개발 환경 안에서 시작했습니다. 잘 굴러가는 코드 위에 바로 손을 대지 않고, 별도 작업 공간에서 새 디자인을 입혀 보고, 사람이 검증한 뒤에야 라이브로 합치는 식으로요.
부끄럽게도, 비개발자 출신이라 Git·브랜치·Pull Request 의 진가를 머리로만 알고 있었습니다. 이번 대공사를 거치고 나서야 “왜 사람들이 이 흐름을 이렇게 단단히 지키는지” 가 몸으로 이해됐습니다. 라이브와 작업 환경을 분리해 두지 않았다면, 다음 이야기가 사용자께 그대로 노출됐을 겁니다.
테스트 환경 안에선 너무 많은 사고가 발생했습니다
5월의 학생에게 시험 진도가 거꾸로 표시되었습니다. “이제 곧 마지막 단계” 라고 띄워야 할 자리에, “아직 시작도 안 했음” 이 보였습니다.
어떤 학생에게는, 그 학생이 보지도 않는 다른 시험의 일정 라벨이 그대로 복사되어 있었습니다.
가장 아찔했던 건 — 이미 치른 시험의 기록이, 30일이 지나면 화면에서 자동으로 사라질 뻔한 일입니다. 사용자가 들여다보던 자리에서. 모르고 넘어갈 뻔했습니다.
세어 보니 13번이었습니다. 화면은 새로 단정해졌는데, 그 안에서 13번이 무너졌습니다. 모두 테스트 환경 안에서. 라이브 앱에는 한 번도 닿지 않은 채로 발견·수정·재검증을 거친 뒤에야, 사용자께 닿게 했습니다.
패턴은 단순했습니다
화면만 보고 “됐다” 고 넘어갔던 겁니다.
디자인이 그린 모습대로 화면이 떴으면, 그걸로 OK. 그 안에서 데이터가 어디서 와서 어디로 가는지, 끝난 시험은 어떻게 보존되는지, 다른 시험을 준비하는 사람에게는 어떻게 보이는지 — 그 흐름까지는 들여다보지 않았습니다.
직접 매일 화면을 들여다보던 제가 8번을 잡아냈고, 점검 과정에서 4번이 더 발견됐습니다. 그 사이에 시간이 적지 않게 흘렀습니다.
Claude 는 훌륭한 도구이지만, 알아서 다 해주지는 않습니다
훌륭한 사용자라면 이런 문제를 미리 이해하고 튼튼한 구조부터 잡았을 겁니다.
비개발자 출신이 Claude 같은 AI 도구로 제품을 만들어 가는 과정에는, 이런 종류의 삽질 이 생각보다 자주 발생합니다. 도구가 빠르게 결과를 내주는 만큼, 그 결과의 안전성을 내가 책임져야 한다는 걸 매번 다시 배웁니다.
그래서 이번 경험을 흘려보내지 않으려고 정리했습니다.
이번에 배운 것 (Lessons Learned)
1. 라이브 앱과 작업 환경은 반드시 분리합니다. 잘 돌아가고 있는 앱에는 직접 손대지 않습니다. 별도 환경에서 변경하고, 검증하고, 합쳐도 안전한지 사람이 확인한 뒤에야 라이브로 옮깁니다. Git 브랜치 + Pull Request 흐름은 형식이 아니라 안전망 입니다. 비개발자에게 가장 먼저 권하고 싶은 한 가지를 고른다면 이것입니다.
2. 화면이 떴다는 것은 끝이 아니라 시작입니다. 디자인 산출물이 코드에 적용되어 모양이 잘 나왔다면, 거기서부터 진짜 검증이 시작됩니다. 사람 케이스 매트릭스 — 처음 가입한 사용자, 데이터가 일부만 있는 사용자, 이미 끝난 흐름을 가진 사용자, 두 가지 흐름을 동시에 가진 사용자 — 를 모두 돌려보고 나서야 “됐다” 입니다.
3. 디자인이 만든 새 구조를 기준 으로 삼지 마십시오. 디자인은 사용자 경험 관점에서 정돈된 모양일 뿐, 코드의 데이터 모델·기존 로직과 반드시 정합한다는 보장이 없습니다. 새 디자인이 기존 구조와 어긋나 있을 때, 무엇이 기준 이고 무엇이 조정 인지 사람이 판단해야 합니다.
4. AI 도구는 빠르게 만들어 주지만, 빠르게 깨질 수도 있습니다. 표면이 매끄러울수록 그 안의 빈틈은 잘 보이지 않습니다. 빠른 만큼 의식적으로 천천히 점검하는 단계를 끼워 넣어야 합니다.
5. 비개발자가 AI 도구를 잘 쓰려면, 자기만의 안전장치 가 필요합니다. 환경 분리, 검증 매트릭스, 사용자 케이스 시뮬레이션, 데이터 무결성 점검 — 모두 도구가 자동으로 해주지 않는 영역입니다. 이번에 그 룰을 회사 작업 표준에 명시해 두었습니다. 다음번에 같은 패턴으로 무너지지 않도록.
부록 — 5번의 연장선상에서 Claude 와 함께 정한 작업 규칙들
이 일을 겪으며 Claude 에게 앞으로는 이렇게 해 달라 고 명시했거나, Claude 가 앞으로는 이렇게 하겠다 고 먼저 약속한 규칙들입니다. 지금 개발을 처음 시작하는 분들에게는 다소 추상적으로 보일 수 있습니다. 다만 비슷한 일을 한 번이라도 겪고 나면 “아, 그 얘기가 이거였구나” 싶어지는 종류의 것들이라, 그대로 적어 둡니다.
원본 (SSOT, Single Source of Truth) 이라는 표현이 아래에서 자주 등장합니다. 같은 정보가 여러 곳에 흩어져 있을 때, 진짜 기준은 이쪽 한 곳 이라고 정해 둔 자리를 말합니다. 예를 들어 시험 일정 이라면 이 표 한 장 이 원본이고, 화면들은 모두 이걸 보고 따라갑니다. 출처가 한 곳이 아니면 어느 게 맞는지 모르게 되니까요.
가. 원본 (SSOT) 은 한 곳에 둡니다 — 새 작업이 나란히 다른 경로 를 만들지 않도록. 한 정보의 출처를 잘 정리해 두었더라도, 새 작업이 들어오면 그 안에 자체적인 단계 이름·데이터 형식·기본값 이 따라붙습니다. 그걸 그대로 두면 기존 원본 과 나란히 두 개의 출처가 살아 있게 되고, 곧 한쪽만 갱신되면서 조용히 어긋납니다 — 이번 작업에서 정확히 이 일이 일어났습니다. 잘 정리해 둔 원본 옆에, 디자인 작업이 들어오면서 비슷한 정보를 가진 새 경로가 생겼고, 한쪽이 갱신되는 동안 다른 쪽은 옛 형태로 남아 있었습니다. 새 형식이 필요하면 원본 자체를 갱신 하거나, 원본 → 새 형식 변환을 한 곳에만 두거나, 둘 중 하나로 통일합니다.
나. 원본 이라고 인용한 파일·함수는 반드시 직접 읽고 인용할 것. “이 함수에 따르면 ~” 이라고 적혀 있다면, 그 함수가 진짜로 읽혀 있어야 합니다. 짧은 파일에 대해서는 일부만 보고 없는 것 같다 라고 결론 내지 말고, 전체 를 읽은 뒤에야 결론 내립니다.
다. 디자인이 새로 정한 단계·구조를 기존 코드의 새 표준 으로 받지 말 것. 디자인 산출물이 들어왔다고 그게 곧 데이터 모델이 되는 건 아닙니다. 기존 원본 함수 (예: 사용자 정보를 어디서 어떻게 읽는지 정해 둔 함수) 를 먼저 읽고, 디자인이 가정한 구조와 어긋나는 부분이 어디인지 사람이 결정 한 뒤에 코드를 변경합니다.
라. 하드코딩된 화면 예시 가 OK 라고, 진짜 OK 는 아닙니다. 디자인이 보여 주는 화면 예시는 “5월에 이 단계가 활성” 같은 상태를 직접 박아 두고 만든 화면입니다. 그건 모양 검증용일 뿐, 실제 날짜와 사용자 데이터로 돌렸을 때 같은 결과가 나오는지는 다른 검증입니다. 날짜·데이터로 돌려 보는 검증 을 별도로 합니다.
마. 도메인이 다르면 데이터 모델도 다릅니다. 한 도메인 패턴을 다른 도메인에 복사하지 마십시오. 한 시험 도메인에서 통한 데이터 모델 (예: 어떤 시험은 목록) 이 다른 도메인에서도 같다는 보장은 없습니다 (다른 시험은 단일 문자열 일 수 있음). 도메인별 표준은 항상 그 도메인의 코드를 직접 확인하고 정합니다.
바. 끝난 데이터를 자동으로 사라지게 하지 마십시오. “30일 지난 데이터는 안 보여줘도 되겠지” 같은 자동 정리 (auto-prune) 는 사용자가 언젠가 다시 들여다볼 자리에서는 기본 동작이 아닙니다. 보존이 기본, 표시 정책은 별도 토글로 분리합니다.
사. 한 건 발견했을 때 그 자리만 고치지 말고, 같은 종류의 사고가 더 있는지 전수 점검 부터. 빈틈을 한 건 발견할 때마다 즉시 patch 하는 패턴은 같은 부류의 다른 빈틈을 그대로 놓치게 됩니다. 한 건 발견됐으면 전체 점검 을 먼저 하고, 그 결과로 일괄 fix 합니다.
아. 한 곳을 고쳤으면, 같은 종류의 변경이 필요한 곳을 전수 동기 합니다. 어떤 값이나 패턴을 바꿨을 때 그 자리만 고치고 나머지를 잊으면 조용한 결함 으로 남습니다 (한 곳에선 새 기준, 다른 곳에선 옛 기준으로 동작). 변경 범위는 전체 검색에서 옛 패턴이 0건 이 될 때까지 추적합니다.
자. 한 경로만 막는 룰은, 나머지 경로 가 새 결함 통로가 됩니다. “이 단계에서는 X 를 걸러낸다” 같은 후처리 룰을 한쪽에만 걸어두면, 같은 데이터가 다른 경로로 흘러갈 때 그대로 새 나갑니다. 룰은 대칭으로 걸거나, 입력 단계에서 막거나, 둘 중 하나로 잡습니다.
차. 보강 작업 자체가 품질 향상 은 아닙니다. 모델을 더 비싼 것으로 바꾸고, 검증 단계를 더 추가하고, 룰을 더 적는 일은 그 자체로 결과물이 좋아지는 게 아닙니다. “이만큼 보강했다” 가 아니라 “결과물이 이렇게 달라졌다” 로 검증합니다.
카. 룰을 덕지덕지 쌓지 말 것 — 한 단계 위에서 원리부터 다시. 사고가 한 건 발생할 때마다 “이 케이스에선 X 하지 마” 라는 회피 룰을 한 줄씩 더 쌓는 건 옥상옥의 땜빵입니다. 그 케이스만 어떻게든 모면하려고 하면, 같은 종류의 사고가 다른 모양으로 재발합니다. 진짜 작업 표준은 케이스 회피 리스트 가 아니라 원리 — 일을 제대로 하기 위한 기준 — 입니다. 룰 목록이 길어지고 있다는 건, 그 자체가 한 단계 위에서 다시 잡아야 한다는 신호입니다.
사용자께
지금 NB2B 코치 앱을 쓰고 계신 분이 있다면, 화면이 한층 정돈되어 보일 겁니다. 그 변화가 표면에서만 끝나지 않도록, 테스트 환경 안에서 13번을 다시 짠 뒤에야 라이브로 옮겼습니다.
빠르게 만들 수 있는 시대에, 굳이 천천히 가는 이유는 — 화면 너머의 사람을 놓치지 않기 위해서입니다.
읽어주셔서 고맙습니다.