이 페이지에서 다루는 것
AI UI 상태 머신
한 번에 끝까지 읽으며 맥락을 쌓을 수 있도록 구성했습니다.
AI가 만든 화면이 loading, empty state, error state, success state, disabled state, optimistic update, race condition을 빠뜨리지 않게 만드는 실전 UI 상태 검증 루프
학습 유형
주제 심층 학습
핵심 주제
AI UI 상태 머신
키워드
VIBE 코딩 · UI 상태 머신 · 프론트엔드 품질 · 접근성 · 회귀 테스트 · AI 코드 품질
이 페이지에서 다루는 것
AI UI 상태 머신
한 번에 끝까지 읽으며 맥락을 쌓을 수 있도록 구성했습니다.
예상 학습 시간
14분
본문과 보조 자료(이미지·영상)를 포함한 대략적인 소요입니다.
학습 팁
섹션 순서대로 읽고, 필요한 부분만 다시 찾아보기
표·이미지·영상은 본문 흐름을 돕는 보조 설명입니다.
AI가 화면을 빠르게 만들어 줄수록 겉으로 보이는 첫 화면은 빨리 완성됩니다. 하지만 실제 제품에서 사용자가 만나는 화면은 첫 화면 하나가 아닙니다. 데이터를 기다리는 loading, 결과가 없는 empty state, 권한이 없는 error state, 저장이 끝난 success state, 중복 클릭을 막는 disabled state, 낙관적 반영 후 되돌림이 필요한 optimistic update, 네트워크 지연으로 순서가 뒤집히는 race condition까지 모두 사용자 경험의 일부입니다.
초보자는 UI 상태 머신을 “화면이 어떤 상황에서 어떤 모습이어야 하는지 적은 상태 지도”로 이해하면 됩니다. 실무자에게는 더 구체적인 의미가 있습니다. 상태 이름, 진입 조건, 허용되는 버튼, 보여 줄 문구, ARIA 알림, keyboard navigation, retry 가능 여부, toast 표시, skeleton 노출 시간, visual regression 기준, rollback criteria를 표와 테스트로 고정해 AI가 임의로 화면 상태를 생략하지 못하게 만드는 것입니다.
AI UI 상태 머신 가드레일의 핵심은 “컴포넌트가 한 번 예쁘게 렌더링된다”가 아니라 “사용자가 실제로 지나가는 모든 상태 전이가 의도대로 보인다”를 검증하는 것입니다. AI에게 화면을 맡기면 happy path는 빠르게 나오지만, loading과 empty state가 같은 문구로 보이거나, error state에서 retry 버튼이 disabled state로 남거나, optimistic update가 실패했는데 이전 값으로 돌아가지 않는 문제가 자주 생깁니다.
따라서 VIBE 코딩에서 UI 작업을 지시할 때는 컴포넌트 구현보다 먼저 상태 머신을 적어야 합니다. 예를 들어 목록 화면이라면 idle, loading, success, empty, error, retrying, saving, saved, failed 같은 상태를 정의하고 각 상태의 화면 문구, 버튼 활성화, skeleton, toast, ARIA live region, keyboard navigation, 허용되는 다음 상태를 함께 적습니다. 그 다음 fixture와 테스트가 이 상태 전이를 확인하게 만듭니다.
좋은 가드레일은 디자이너의 감각을 없애는 것이 아닙니다. 오히려 감각적인 화면을 안전하게 반복 생산하게 만듭니다. 상태 머신이 있으면 AI는 “뭔가 그럴듯한 에러 문구”를 만드는 대신 “권한 오류에서는 수정 버튼을 숨기고, 일시 오류에서는 retry를 제공하며, 저장 중에는 제출 버튼을 disabled state로 바꾸고, 완료 후에는 success state toast를 4초 동안 표시한다” 같은 구체적 기준을 따르게 됩니다.
AI가 생성한 UI에서 가장 흔한 문제는 정상 데이터가 있을 때만 멋지게 보인다는 점입니다. 샘플 fixture가 세 개의 항목만 포함하면 AI는 카드 그리드와 CTA를 잘 만듭니다. 그러나 실제 서비스에서는 항목이 0개일 수 있고, 첫 요청이 느릴 수 있고, 권한이 없을 수 있고, 삭제 직후 목록이 잠시 비어 보일 수 있습니다. 이때 empty state와 error state가 구분되지 않으면 사용자는 “내가 뭘 해야 하는지”를 알 수 없습니다.
정상 흐름만 확인하는 리뷰는 빠릅니다. 하지만 제품 운영에서는 예외 흐름이 신뢰를 결정합니다. loading이 무한히 이어지면 사용자는 서비스가 멈췄다고 느끼고, retry가 없는 오류는 고객센터 문의로 바뀌며, disabled state가 없으면 중복 제출이 생깁니다. 상태 머신은 이런 예외를 나중에 떠올리는 메모가 아니라 구현 전에 합의하는 계약으로 바꿉니다.
UI 상태는 단순한 장식이 아닙니다. 결제, 저장, 예약, 질문 제출, 파일 업로드처럼 데이터가 바뀌는 화면에서는 상태 전이가 곧 데이터 무결성입니다. 사용자가 저장 버튼을 두 번 누를 수 있으면 중복 레코드가 생길 수 있고, optimistic update가 실패 후 rollback되지 않으면 화면은 성공처럼 보이지만 서버에는 반영되지 않은 상태가 됩니다.
특히 AI가 이벤트 핸들러를 자동으로 붙일 때는 race condition이 숨어 들어가기 쉽습니다. 느린 이전 요청이 빠른 최신 요청보다 늦게 도착했는데도 화면을 덮어쓰면 사용자는 오래된 데이터를 보게 됩니다. 상태 머신은 “요청마다 request id를 붙이고 최신 요청만 반영한다”, “저장 중에는 같은 액션을 막는다”, “실패하면 이전 snapshot으로 되돌린다” 같은 규칙을 명시합니다.
접근성 문제도 상태 머신 없이 나중에 붙이기 어렵습니다. loading이 시작됐는지, 저장이 완료됐는지, 오류가 어디에 있는지 스크린 리더 사용자에게 알려야 합니다. ARIA live region, focus 이동, keyboard navigation, 버튼의 disabled state, 오류 메시지와 입력 필드 연결은 모두 특정 상태에서 어떻게 행동할지 결정해야 합니다.
AI에게 “접근성도 챙겨 줘”라고만 말하면 흔히 aria-label 몇 개를 추가하는 수준에서 끝납니다. 반대로 상태 전이 표에 “error state 진입 시 첫 오류 요약으로 focus 이동”, “success state에서는 toast를 polite live region으로 알림”, “modal loading 중에는 닫기와 탭 이동 정책을 명시”라고 적으면 접근성이 구현 기준이 됩니다.
처음에는 코드가 아니라 상태 이름을 적습니다. 목록 화면이라면 idle, loading, success, empty state, error state, retrying을 기본으로 둡니다. 작성 화면이라면 editing, validating, saving, success state, failed, dirty, disabled state를 생각합니다. 검색 화면이라면 typing, debouncing, loading, success state, empty state, error state, stale result를 나눕니다.
중요한 것은 상태 이름이 개발자만 아는 단어가 아니라 사용자 상황과 연결되어야 한다는 점입니다. “데이터 없음”은 empty state이고, “서버 장애”는 error state이며, “저장 요청 진행 중”은 saving이자 disabled state입니다. 상태 이름이 분명하면 AI에게 작업을 맡길 때도 “이 컴포넌트는 loading과 empty state를 구분해야 한다”라고 정확히 지시할 수 있습니다.
상태 이름만으로는 부족합니다. 각 상태가 어떤 이벤트를 받아 어떤 상태로 이동할 수 있는지 state transition table로 적어야 합니다. 예를 들어 loading은 success state, empty state, error state로 갈 수 있지만, 사용자가 직접 saved로 이동할 수는 없습니다. saving은 success state 또는 failed로 갈 수 있고, saving 중 같은 제출 이벤트는 무시하거나 버튼을 disabled state로 둬야 합니다.
표에는 최소한 다섯 가지 열을 둡니다. 현재 상태, 발생 이벤트, 다음 상태, 사용자에게 보이는 UI, 검증 방법입니다. 실무에서는 여기에 추적해야 할 analytics event, rollback criteria, 접근성 요구, timeout 기준도 붙입니다. 이 표가 있으면 AI가 구현을 바꾸더라도 리뷰어는 상태 전이가 빠졌는지 빠르게 볼 수 있습니다.
상태 머신이 실제로 작동하려면 fixture가 필요합니다. 데이터가 10개 있는 success state fixture, 결과가 0개인 empty state fixture, 권한 오류 error state fixture, 네트워크 실패 error state fixture, 저장 중 disabled state fixture, optimistic update 성공과 실패 fixture를 만듭니다. fixture는 테스트와 스토리, 수동 리뷰에서 같은 데이터를 쓰게 하는 것이 좋습니다.
초보 프로젝트에서는 JSON 객체 몇 개로 충분합니다. 중요한 것은 “오늘 우연히 로컬 서버가 반환한 데이터”가 아니라 “반복 가능한 상태 샘플”을 쓰는 것입니다. AI에게도 fixture 이름을 그대로 주면 좋습니다. “emptyProjectsFixture에서는 CTA 문구가 보여야 하고, forbiddenErrorFixture에서는 retry가 아니라 권한 안내가 보여야 하며, networkErrorFixture에서는 retry 버튼이 보여야 한다”처럼 지시할 수 있습니다.
UI 테스트는 버튼이 있는지 정도에서 멈추면 안 됩니다. loading에서는 skeleton이 보이고 주요 액션이 disabled state인지, empty state에서는 다음 행동 CTA가 있는지, error state에서는 오류 원인과 retry가 구분되는지, success state에서는 실제 데이터와 주요 액션이 보이는지 확인합니다. 저장 흐름은 saving에서 중복 제출이 막히고, success state toast가 표시되며, 실패 시 이전 값으로 rollback되는지 봐야 합니다.
테스트 이름도 상태 전이를 설명해야 합니다. “renders component”보다 “network error shows retry and keeps previous successful data”가 낫습니다. AI 에이전트에게 테스트를 먼저 작성하게 할 때도 이 이름이 작업 지시서 역할을 합니다. 테스트가 실패하면 AI는 무엇을 고쳐야 하는지 더 쉽게 이해합니다.
상태 머신은 텍스트 테스트만으로 끝나지 않습니다. skeleton 높이가 실제 카드와 너무 달라 layout shift가 생기거나, empty state CTA가 모바일에서 접히거나, toast가 중요한 버튼을 가리는 문제는 시각 검증이 필요합니다. visual regression을 모든 화면에 과하게 붙일 필요는 없지만, 핵심 상태 몇 개는 스냅샷이나 브라우저 스모크로 확인해야 합니다.
실무에서는 대표 뷰포트 두세 개를 정합니다. 모바일 좁은 화면, 데스크톱 기본 화면, 긴 텍스트가 들어간 화면입니다. 각 뷰포트에서 loading, empty state, error state, success state를 한 번씩 확인합니다. keyboard navigation도 함께 봅니다. Tab 순서가 정상인지, retry 버튼에 도달할 수 있는지, toast가 focus를 훔치지 않는지 확인해야 합니다.
UI 상태 문제는 배포 후에도 발생합니다. 예를 들어 API 지연이 늘어나 loading이 길어지거나, 특정 권한 사용자에게 error state가 잘못 노출될 수 있습니다. 그래서 rollback criteria를 미리 정합니다. 저장 실패율이 일정 기준을 넘거나, 콘솔 오류가 특정 수준 이상 나오거나, error state에서 retry 클릭 후 성공률이 낮거나, 중복 제출이 늘면 롤백 또는 feature flag off를 결정합니다.
rollback criteria는 “문제가 있으면 되돌린다”가 아니라 숫자와 관측 지표로 적어야 합니다. 예를 들어 “신규 화면 배포 후 30분 동안 submit 중복 요청이 평소 대비 두 배 이상이면 이전 UI로 되돌린다”, “error state 노출률이 예상 권한 오류 범위를 넘으면 feature flag를 끈다”처럼 작성합니다. AI가 만든 UI도 이 기준을 통과해야 제품에 남길 수 있습니다.
프로젝트 목록 화면을 만든다고 가정해 봅시다. AI가 만든 첫 버전은 데이터 배열이 비면 “아직 프로젝트가 없습니다”라고 표시할 수 있습니다. 하지만 API 호출 자체가 실패했을 때도 빈 배열로 처리하면 사용자는 새 프로젝트를 만들면 되는지, 잠시 후 다시 시도해야 하는지 알 수 없습니다. 여기서 empty state와 error state 분리가 필요합니다.
상태 머신은 이렇게 정리할 수 있습니다. loading에서는 skeleton을 보여 주고 새로 만들기 버튼은 유지하되 목록 액션은 disabled state로 둡니다. success state에서는 프로젝트 카드와 필터를 보여 줍니다. empty state에서는 “첫 프로젝트 만들기” CTA를 강조합니다. network error state에서는 이전 성공 데이터가 있으면 그대로 보여 주고 상단에 retry 배너를 표시합니다. 권한 error state에서는 생성 CTA를 숨기고 권한 요청 안내를 보여 줍니다.
이 예시에서 테스트는 네 가지를 봅니다. 빈 배열이 empty state로 렌더링되는지, 네트워크 오류가 error state와 retry로 렌더링되는지, 권한 오류에서는 retry 대신 권한 안내가 나오는지, loading 중 skeleton 높이가 카드 레이아웃과 비슷한지입니다. 이 정도만 있어도 AI가 “빈 결과와 실패를 같은 화면으로 합치는” 회귀를 막을 수 있습니다.
문의 작성 화면은 더 민감합니다. 사용자가 제출 버튼을 누르면 saving 상태로 들어가고 버튼은 disabled state가 되어야 합니다. 요청이 성공하면 success state로 이동하고 toast로 완료를 알려야 합니다. 요청이 실패하면 입력값은 유지하고 error state 메시지와 retry를 제공해야 합니다. 여기서 핵심은 사용자의 작성 내용을 잃지 않는 것입니다.
AI가 흔히 만드는 실수는 실패 시 form을 초기화하거나, 저장 중 버튼을 계속 누를 수 있게 두거나, success state로 이동했는데 서버 응답 id를 반영하지 않는 것입니다. 상태 전이 표에는 “saving 중 submit 이벤트는 무시”, “failed 진입 시 사용자가 입력한 값 유지”, “success state에서는 서버가 반환한 id 기준으로 상세 링크 표시” 같은 규칙을 넣습니다.
테스트는 이 흐름을 실제 사용자 행동처럼 검증합니다. 입력 후 제출, 버튼 disabled state 확인, 실패 응답 fixture 주입, 입력값 유지 확인, retry 후 success state toast 확인 순서입니다. optimistic update가 필요한 화면이라면 실패 시 이전 snapshot으로 돌아가는지도 확인합니다. 이 검증이 있으면 AI가 코드를 정리하면서도 중요한 사용자 데이터를 잃지 않게 됩니다.
검색 UI는 race condition이 특히 자주 생깁니다. 사용자가 “ai”를 입력한 뒤 바로 “ai agent”를 입력했는데, 첫 번째 요청이 늦게 도착해서 최신 결과를 덮어쓰는 상황입니다. 겉으로는 검색 기능이 있는 것처럼 보이지만 사용자는 오래된 결과를 보게 됩니다.
상태 머신은 각 요청에 request id나 query snapshot을 붙이고, 응답이 돌아왔을 때 현재 query와 일치할 때만 success state로 반영하도록 해야 합니다. typing 상태에서는 debouncing을 적용하고, loading 중에는 이전 결과를 흐리게 유지할지 skeleton으로 바꿀지 정책을 정합니다. empty state는 “검색 결과 없음”으로, error state는 “검색을 완료하지 못했습니다”로 구분합니다.
이 예시의 핵심 테스트는 느린 이전 요청과 빠른 최신 요청을 함께 다루는 것입니다. 먼저 오래 걸리는 “ai” 요청을 시작하고, 이어 “ai agent” 요청을 성공시킵니다. 그 다음 “ai” 응답이 늦게 도착해도 화면이 최신 query 결과를 유지하는지 확인합니다. keyboard navigation으로 검색 결과 항목을 이동할 수 있는지도 함께 봅니다.
권한이 필요한 기능에서 error state는 보안과 UX의 균형을 요구합니다. 사용자가 권한이 없을 때 모든 내부 정보를 보여 주면 안 되지만, 아무 설명 없이 버튼이 사라지면 혼란스럽습니다. 상태 머신은 권한 없음, 로그인 필요, 일시 오류, 데이터 없음을 분리해야 합니다.
예를 들어 팀 설정 화면에서 권한이 없는 사용자는 수정 버튼을 볼 필요가 없습니다. 하지만 왜 수정할 수 없는지는 알 수 있어야 합니다. “팀 관리자에게 권한을 요청하세요” 같은 안내는 유용합니다. 반면 시스템 내부 식별자나 관리용 상태 문구는 공개 화면에 나오면 안 됩니다. retry는 일시 오류에만 제공하고 권한 오류에는 제공하지 않습니다.
검증은 문구와 액션을 함께 봐야 합니다. 권한 없음 fixture에서는 수정 버튼이 없고 권한 안내가 보이는지, 네트워크 오류 fixture에서는 retry가 보이는지, 로그인 필요 fixture에서는 로그인 CTA가 보이는지 확인합니다. 이것이 public-safe UI 상태 설계입니다.
많은 팀이 loading, empty state, error state 이름은 적지만 어떤 이벤트로 이동하는지 쓰지 않습니다. 그러면 구현자는 상태를 임의로 연결합니다. 예를 들어 retry 클릭 후 바로 loading으로 가야 하는지, 기존 데이터를 유지한 retrying으로 가야 하는지 불분명해집니다. 상태 이름만 있는 문서는 체크리스트에 가깝고, state transition table이 있어야 가드레일이 됩니다.
전이를 쓸 때는 불가능한 이동도 적는 것이 좋습니다. saving에서 editing으로 바로 돌아갈 수 있는지, success state에서 failed로 갈 수 있는지, empty state에서 refresh를 누르면 loading으로 가는지 명확히 해야 합니다. 불가능한 이동을 테스트로 막으면 AI가 리팩터링 중 이상한 흐름을 추가하기 어렵습니다.
skeleton은 예쁜 회색 박스가 아닙니다. 사용자가 어디에 콘텐츠가 들어올지 예측하게 하고 layout shift를 줄이는 장치입니다. AI가 skeleton을 대충 만들면 실제 카드보다 높이가 다르거나 모바일에서 과하게 길어져 화면이 흔들립니다. loading 상태의 skeleton은 success state 레이아웃과 대응되어야 합니다.
검증할 때는 “skeleton이 있다”만 보지 말고 주요 영역 수, 높이, 모바일 줄바꿈, 접근성 문구를 봅니다. skeleton 자체가 스크린 리더에 불필요한 잡음을 만들지 않도록 처리하고, loading 상태를 알리는 텍스트는 필요한 방식으로 제공해야 합니다.
toast는 보조 알림입니다. 저장 성공이나 간단한 오류 안내에는 좋지만, 사용자가 반드시 읽어야 할 복구 방법을 toast에만 넣으면 안 됩니다. toast가 자동으로 사라지거나 화면 리더가 놓칠 수 있기 때문입니다. error state의 핵심 메시지와 retry는 화면 본문에 남겨야 하고, toast는 상태 변화 알림 정도로 쓰는 것이 안전합니다.
success state에서도 마찬가지입니다. “저장되었습니다” toast가 뜨더라도 실제 화면의 저장 상태, 새 링크, 갱신된 값이 확인 가능해야 합니다. AI에게 toast를 추가하라고 할 때는 “toast만으로 상태를 대체하지 말라”는 조건을 같이 넣는 것이 좋습니다.
버튼을 disabled state로 만들면 중복 클릭을 막을 수 있지만, 무조건 비활성화하면 keyboard navigation과 설명 가능성이 나빠질 수 있습니다. 사용자가 왜 누를 수 없는지 알 수 있어야 합니다. 입력값이 부족해서 disabled라면 안내 문구를 제공하고, 저장 중이라면 버튼 텍스트를 “저장 중”으로 바꾸는 편이 좋습니다.
특히 폼에서는 disabled 필드가 제출에서 제외되는지, focus가 사라지는지, 스크린 리더가 상태를 어떻게 읽는지 확인해야 합니다. AI가 단순히 disabled 속성을 붙이는 것으로 끝내지 않도록 상태별 안내와 테스트를 함께 요구합니다.
visual regression은 모든 작은 차이를 막자는 뜻이 아닙니다. VIBE 코딩에서는 중요한 상태가 사라지거나, CTA가 접히거나, 오류 배너가 보이지 않는 회귀를 잡는 데 집중해야 합니다. 너무 민감한 픽셀 비교는 오히려 유지 비용을 높입니다.
핵심 화면과 핵심 상태를 고르고, 허용 가능한 차이와 반드시 막아야 할 차이를 구분합니다. 예를 들어 색상 1픽셀 차이는 허용하되, retry 버튼 미노출, skeleton 영역 붕괴, empty state CTA 누락은 실패로 봅니다. 이 기준을 AI 작업 지시서에 넣으면 검증이 훨씬 안정됩니다.
처음부터 모든 서비스를 상태 머신으로 다시 쓰려고 하면 부담이 큽니다. 가장 사용자가 많이 지나가는 화면 하나를 고르세요. 목록, 작성, 검색, 결제 전 확인, 질문 제출처럼 실패 비용이 큰 화면이 좋습니다. 그 화면의 상태를 6개 안팎으로 적고, state transition table을 한 장으로 만듭니다.
그 다음 AI에게 “이 표를 기준으로 테스트를 먼저 만들고, 테스트가 실패하는 것을 확인한 뒤 구현하라”고 지시합니다. 구현이 끝나면 표에 없는 상태가 코드에 생겼는지, 코드에 있는 상태가 표에 빠졌는지 확인합니다. 이 왕복이 VIBE 코딩의 품질 루프입니다.
화면 리뷰에서 “예쁘다”, “버튼 위치가 좋다”만 말하면 AI가 품질 기준을 학습하기 어렵습니다. 리뷰 질문을 바꿔야 합니다. loading은 얼마나 오래 보일 수 있는가, empty state는 다음 행동을 제안하는가, error state는 retry와 권한 안내를 구분하는가, keyboard navigation은 끊기지 않는가, optimistic update 실패 시 사용자 데이터가 사라지지 않는가를 물어보세요.
이 질문은 초보자에게도 유용합니다. 화면을 기능 단위가 아니라 사용자가 겪는 상황 단위로 보게 만들기 때문입니다. 실무자에게는 릴리스 리스크를 줄이는 기준이 됩니다. 특히 AI가 만든 UI는 속도가 빠른 만큼 상태 누락도 빠르게 쌓이므로 리뷰 기준을 상태 중심으로 옮겨야 합니다.
배포 후 실제 문제가 생기면 단순히 고치고 끝내지 말아야 합니다. “검색 race condition으로 오래된 결과가 보였다”, “저장 실패 후 입력값이 사라졌다”, “권한 오류인데 retry가 노출됐다” 같은 사건을 다음 fixture와 테스트로 남깁니다. 그러면 같은 유형의 문제가 반복될 때 AI도 테스트 실패를 보고 수정할 수 있습니다.
결국 AI UI 상태 머신 가드레일은 문서, fixture, 테스트, 브라우저 스모크, rollback criteria가 연결된 루프입니다. 화면을 빨리 만드는 능력보다 중요한 것은 잘못된 상태를 제품에 남기지 않는 능력입니다. 이 루프를 갖추면 AI가 만든 UI도 사용자에게 안정적으로 설명하고 복구하고 검증할 수 있는 제품 화면이 됩니다.
다음 학습
AI가 만든 기능은 화면이 예쁘고 테스트 데이터로 동작해도, 권한 경계가 한 번 새면 바로 신뢰 사고가 됩니다. 사용자는 자기 글만 봐야 하는데 다른 팀의 문서를 열 수 있고, 일반 멤버가 관리자 버튼을 호출할 수 있으며, URL의 숫자 하나를 바꿨더니 남의 결제 내역이 보일 수 있습니다. 이런 문제는 authentication, 즉 “누구인지 확인했는가”만으로 막히지 않습니다. 로그인 이후에도 authorization, 즉 “이 사람이 이 객체에 이 행동을 해도 되는가”를 매 요청마다 검증해야 합니다.
초보자는 permission boundary를 “여기부터는 이 사람에게 허용되지 않는 선”으로 이해하면 됩니다. 실무자는 여기에 RBAC, role matrix, tenant isolation, object ownership, least pr…
AI에게 화면과 서버 API를 동시에 맡기면 가장 자주 생기는 실패는 “둘 다 그럴듯하지만 서로 맞지 않는 상태”입니다. 프론트엔드는 name 필드를 기대하는데 서버는 displayName을 돌려주고, 서버는 201을 반환하는데 화면 테스트는 200만 기다리고, 오류 응답은 어떤 곳에서는 message이고 어떤 곳에서는 error.detail입니다. 작은 불일치는 로컬 데모에서는 지나가지만 배포 후에는 빈 화면, 재시도 루프, 잘못된 캐시, 깨진 알림으로 나타납니다.
초보자는 API 계약을 “서로 약속한 요청과 응답의 모양”으로 이해하면 됩니다. 실무자에게는 더 엄격합니다. 요청 스키마, 응답 스키마, status code, error envelope, pagination, idempotency key, versioning, 인증 실패 형태,…