운영 시스템 • Koal & KoalStudio

정책과 사양을 나눈 뒤 무엇이 덜 되돌아왔나 — Called Up 문서 체계 적용기

Called Up의 결정론적 커리어, 국적 UX, 문구 규칙, 수익화 공정성, 웹과 iOS 배포 경계를 일곱 개념으로 나눠 기록합니다. 속도를 수치로 주장하는 대신, 변경과 리뷰와 QA가 어느 층으로 되돌아왔는지 살펴봅니다.

Called Up을 만들면서 자주 되돌아온 일은 코드 자체보다 결정의 위치였어요. 같은 입력으로 같은 커리어가 나와야 한다는 규칙이 화면 티켓에 숨어 있거나, 국적 선택 화면의 현재 구성이 제품 규칙처럼 굳으면 작은 변경도 여러 문서를 다시 고치게 됐어요.

Called Up은 이름과 포지션, 국적 같은 출발 조건을 정하고 선택을 이어 한 선수의 야구 인생을 만드는 커리어 시뮬레이터예요. 하나의 선택이 시즌 기록, 저장, 공유, 번역까지 이어지기 때문에 무엇을 바꾸는지보다 어느 층을 바꾸는지를 먼저 구분할 필요가 있었어요.

그래서 문서의 양을 늘리는 대신 결정이 머무를 곳을 일곱 개념으로 나눴어요. 개발 전후 시간을 계측하지 않았으므로 더 빨라졌다는 수치나 속도 향상은 주장하지 않아요. 여기서 확인할 수 있었던 것은 변경이 잘못된 문서와 구현까지 번졌다가 되돌아오는 범위였어요.


일곱 개념은 같은 기능을 잘게 자른 이름이 아니에요

이 글에서 사용하는 뜻은 다음과 같아요.

  • 시스템은 독립적으로 의미를 가지는 경계가 있는 도메인이에요.
  • 정책은 그 시스템이 무엇인지, 무엇을 참으로 소유하는지, 어떤 규칙을 지키고 다른 시스템과 무엇을 소통할 수 있는지 선언해요.
  • 비즈니스 로직은 정책에 선언된 판단과 계산을 실제로 실행해요.
  • 서비스는 사용자와 시스템 또는 시스템과 시스템 사이의 연결이에요.
  • 인터페이스는 그 연결이 따르는 계약이에요. 사람을 향하면 UI, 시스템을 향하면 API 같은 형태가 돼요.
  • UI 로직은 사용자의 행동과 시스템 피드백이 이어지는 흐름이에요.
  • 사양은 정책을 참조해 UI나 API를 다시 만들고 검증할 수 있을 만큼 구체적으로 적은 실현 내용이에요.

사양은 인터페이스에서 주고받는 계약 자체가 아니에요. 예를 들어 API의 요청·응답 방식은 인터페이스 계약이고, 특정 정책을 어떤 필드와 상태, 오류, 예외로 실현할지는 사양이에요. UI에서도 탭과 버튼을 오가는 상호작용 흐름은 UI 로직이고, 각 화면의 필드, 문구, 상태, 비활성 조건까지 재현 가능한 수준으로 적은 것이 사양이에요.

Called Up의 문서도 이 기준으로 나눴어요. “같은 입력은 같은 커리어를 만든다”는 커리어 시스템의 정책이에요. 이를 계산하고 검증하는 코드는 비즈니스 로직이에요. 커리어를 플레이하거나 저장하는 연결은 서비스이고, 화면과 저장 API가 따르는 연결 계약은 인터페이스예요. 선택하고 결과를 확인하는 순서는 UI 로직이며, 선택 카드와 저장 요청을 구체적으로 재현하는 문서는 사양이에요.

이 구분 뒤 리뷰 질문도 달라졌어요. “정책인가 사양인가”만 묻지 않고, 먼저 어느 시스템의 규칙인지, 어떤 연결과 계약을 거치는지, 마지막에 어떤 UI나 API로 실현되는지를 차례로 확인했어요.


사례 1. 같은 선수 인생을 무엇으로 식별할까

Called Up의 커리어 시스템은 최종 타율이나 통산 승수만으로 한 선수의 인생을 식별하지 않아요. 출발 조건과 사용자가 지나온 선택이 커리어를 만들며, 같은 조건과 같은 선택은 같은 결과로 돌아와야 해요.

정책에는 다음과 같은 문장이 남아요.

커리어의 결과는 재현 가능해야 하며, 결과 숫자보다 커리어를 만든 입력과 선택 기록을 신뢰한다.

무작위성을 재현 가능한 흐름 안에서 처리하고, 저장할 때 입력을 다시 따라가 결과를 확인하는 일은 이 정책을 실행하는 비즈니스 로직이에요. 브라우저와 서버를 연결하는 저장 서비스, 요청과 응답의 규칙을 정한 API 인터페이스도 따로 있어요.

사양에는 정책을 참조해 저장 UI와 API를 다시 만들 수 있는 구체적인 내용이 들어가요. 어떤 선택을 기록하는지, 미완료 커리어를 어떤 상태로 표시하는지, 검증 실패 시 어떤 오류와 다음 행동을 보여주는지 적어요. 공유 링크로 들어온 사람이 같은 커리어를 재현할지 새 선택으로 시작할지 정하는 순서는 UI 로직이에요.

새 사건을 넣을 때는 화면 카드만 보지 않았어요. 기존 커리어 재현, 서버 저장 검증, 공유 커리어가 같은 입력을 해석하는지 함께 확인했어요. 정책이 범위를 넓힌 것이 아니라 원래 연결돼 있던 범위를 마지막에 발견하는 일을 줄였어요.


사례 2. 국적은 데이터이고, 국적 선택은 경험이에요

선수의 국적은 시작 리그와 국가대표 경험에 영향을 줘요. “선수는 하나의 국적을 가진다”와 “국적에 따라 시작 조건을 판정한다”는 선수와 커리어 시스템의 정책이에요. 실제 시작 리그를 고르는 계산은 비즈니스 로직이고요.

전 세계 국가를 긴 목록으로 한 번에 보여주는 것은 별개의 문제였어요. 사용자가 선수 생성 서비스에서 국적을 고르는 UI 인터페이스와 그 상호작용 흐름을 바꿨어요. 현재 국적을 먼저 카드로 보여주고, 바꾸려는 사람만 선택 화면을 열어요. 주요 야구 국가는 먼저 찾을 수 있게 두고, 나머지는 검색과 더 보기를 이용하게 했어요. 선택 뒤 자동으로 다음 단계로 갈지, Next를 함께 허용할지도 UI 로직의 결정이에요.

사양에는 이 흐름을 재현할 수 있도록 카드의 상태, 목록 구성, 검색 결과, 빈 결과, 선택 후 표시를 적어요. 국적이 선수 정체성의 일부라는 정책은 그대로 참조하지만, 현재 화면 구성을 정책으로 올려 굳히지는 않아요.

국기 emoji도 같은 방식으로 경계를 잡았어요. Called Up의 사용자 문구에는 장식용 emoji를 쓰지 않는다는 정책이 있어요. 국적 선택 표면의 국기는 장식 문구가 아니라 빠른 식별을 돕는 기호라서, 사양에서 허용 표면과 표현 조건을 제한했어요. QA는 앱 전체에서 예외를 추측하는 대신 금지 정책과 허용 사양을 각각 확인할 수 있었어요.


사례 3. 문구 규칙은 카피 목록보다 위에 있어요

Called Up은 네 언어로 사건, 선택지, 수상, 엔딩을 보여줘요. 문구가 많아질수록 개별 번역의 자연스러움만 봐서는 제품의 목소리를 지키기 어려워요. 그래서 먼저 문구 정책을 두었어요.

사용자 문구에는 긴 대시와 장식용 emoji를 쓰지 않아요. 실존 선수를 직접 떠올리게 하는 이름이나 별명도 피하고, 국가대표 문구는 특정 국가만 기본값처럼 말하지 않아요. 능력치의 내부 이름이나 시스템 판정 용어도 그대로 노출하지 않아요. 새 문구는 한 언어만 먼저 완성한 채 두지 않고 네 언어의 대응 관계를 같이 확인해요.

각 표면의 사양은 이 정책을 참조해 사건 카드의 문장 수, 선택지 어조, 오류의 원인과 다음 행동, 숫자와 기간의 표시 단위, 실제 문구를 구체화해요. 사용자가 사건을 읽고 선택하고 결과를 확인하는 순서는 UI 로직으로 분리해요.

수정 요청이 오면 한 문자열, 한 표면의 사양, 네 언어 공통 정책 가운데 어디를 바꿀지 먼저 정할 수 있었어요. 카피 한 줄을 제품 정책으로 과장하거나 공통 규칙의 문제를 번역 한 줄로 덮는 일이 덜 되돌아왔어요.


사례 4. 수익화 문서는 가격표보다 공정성을 먼저 말해요

커리어 시뮬레이터에 무엇을 팔 수 있는지 정할 때 광고 형식이나 가격부터 쓰면 선택지가 끝없이 늘어나요. Called Up에서는 수익화가 건드리면 안 되는 시스템 경계부터 정했어요. 돈을 낸 사용자가 더 높은 능력치, 더 빠른 성장, 더 좋은 커리어 결과를 얻어 경쟁에서 유리해지게 만들지 않는다는 정책이에요.

그래서 검토할 수 있는 범위는 광고 제거, 저장 편의, 공유 카드 꾸미기 같은 편의와 외형으로 좁혀져요. 특정 보상이 공정성 정책을 통과하는지 판단하고 결제 권한을 복원하는 처리는 비즈니스 로직이에요. 사용자와 결제 시스템을 잇는 것이 서비스이고, 구매와 복원이 따르는 계약이 인터페이스예요.

구매 버튼의 위치와 결제 후 피드백 순서는 UI 로직이에요. 가격 표시, 광고 제거 상태, 실패 문구, 복원 상태, 예외 처리는 정책과 인터페이스를 참조한 사양에 적어요. 특정 광고 SDK가 기술적으로 가능하다는 사실이 제품에 허용된다는 답을 대신하지 못하게 했어요.


사례 5. 같은 소스와 같은 배포물은 다른 말이에요

Called Up의 기본 제품은 웹에서 동작해요. iOS는 같은 웹 소스를 네이티브 컨테이너로 감싸는 방향을 계획했지만, “같은 코드니까 같은 앱”이라고 적으면 릴리스 판단이 틀어져요.

정책에서는 웹과 iOS가 같은 커리어 시스템의 규칙과 공정성 경계를 공유한다고 선언해요. 플랫폼이 달라졌다고 같은 입력의 결과가 달라지거나 iOS에서만 공정성 경계를 넘는 보상을 팔아서는 안 돼요.

웹과 앱이 사용자에게 제품을 제공하는 연결은 각각의 서비스예요. 웹 자산 전달, 네이티브 공유, 진동, 광고, 인앱결제가 따르는 계약은 플랫폼별 인터페이스로 분리돼요. 웹은 서버가 제공하는 자산을 받지만, 네이티브 앱은 릴리스 시점의 웹 자산 묶음을 바이너리 안에 담게 돼요. 웹 수정이 설치된 앱의 묶음을 저절로 바꾸지는 않아요.

사양은 각 정책과 인터페이스를 참조해 배포물의 자산, 버전 상태, 실패와 대체 동작, 검증 항목을 구체화해요. Called Up 웹은 공개되어 있지만 이 글은 iOS의 스토어 출시를 주장하지 않아요. iOS 경로는 별도 배포물과 검증 절차가 필요하다는 계획의 경계만 다뤄요.


변경 요청이 오면 시작 층부터 표시해요

문서를 나눈 뒤 자주 사용한 산출물은 거대한 정책집이 아니라 변경 분류표였어요.

변경 요청시작 층함께 확인할 범위
같은 입력인데 커리어 결과가 달라짐커리어 정책·비즈니스 로직시뮬레이션, 저장 서비스와 API, 공유, 회귀 테스트
국적 선택 목록의 탐색 방식을 바꿈UI 로직·사양모바일 흐름, 검색, 다음 단계, 접근성
국적 외 화면에도 emoji를 허용함문구 정책네 언어 사양, 검사 규칙, 기존 예외
유료 성장 보상을 추가함수익화 정책공정성 판단, 결제 서비스와 인터페이스, 관련 사양
웹 수정분을 iOS에도 반영함배포 서비스·인터페이스·사양묶음 자산, 네이티브 연결, 버전별 QA

사용법은 단순해요.

  1. 요청을 받은 사람이 대상 시스템과 시작 층을 표시해요.
  2. 정책 변경이면 이를 실행하는 비즈니스 로직과 연결된 서비스, 인터페이스, UI 로직, 사양을 아래로 훑어요.
  3. 사양 변경이면 참조하는 정책과 인터페이스 계약을 어기지 않는지 확인하되, 상위 정의까지 불필요하게 다시 쓰지 않아요.
  4. 리뷰어는 화면 위치가 정책에 박혔는지, 인터페이스 계약과 구체 사양이 섞였는지, 시스템의 불변식이 버튼 설명 속에 숨었는지 확인해요.
  5. QA 항목은 각 층의 선언과 계약과 사양에서 뽑아요.

모든 변경을 문서부터 쓰라는 뜻은 아니에요. 버튼 간격이나 오탈자까지 정책 회의를 열 필요는 없어요. 반대로 커리어 재현성이나 유료 보상의 공정성을 화면 티켓 하나로 처리하면 뒤늦게 여러 층을 고치게 돼요.

정책과 사양을 나눈 뒤 기능을 만드는 시간 자체를 비교하지는 않았어요. 대신 제품의 의미를 바꾸는 요청이 화면 수정으로 축소되거나, 구체적인 UI 변경이 시스템 정책으로 커지는 일을 분리해서 볼 수 있었어요. 리뷰는 취향보다 영향 범위를 확인했고, QA는 구현자의 기억보다 각 층에 남은 근거를 따라갔어요.

수정하기 전에 대상 시스템과 층을 정하고, 완료했다고 말하기 전에 그 층의 근거로 검증한다.


관련 링크

댓글

댓글 남기기

댓글 삭제 시 사용됩니다
공개되지 않습니다
0/2000
← 목록으로