룸톤 Roomtone TIL 20
값이 하나뿐인 칸을 없앴다가 되살렸다
어제 계절 태그를 크리스마스 하나로 줄였다. 값이 하나면 고르는 칸을 둘 이유도 없다고 보고 화면에서 그 칸을 뺐다.
다시 넣었다. 12월이 되면 매장이 캐럴만 골라 듣고 싶을 텐데, 칸이 없으면 내가 크리스마스 재생목록을 만들어 줄 때까지 기다려야 한다. 1년에 한 달만 쓰는 칸이라도 그 한 달에는 그게 전부다.
값이 하나인 칸을 둘지 정할 때 물을 것은 「지금 값이 몇 개인가」가 아니다. 「그 칸이 없으면 쓰는 사람이 못 하는 일이 생기나」다. 화면이 하나 늘어나는 비용은 매일 조금이고, 못 하는 일이 생기는 비용은 그 시기에 한꺼번에 온다.
「그 곡을 듣고 그 때를 맞힐 수 있나」
그러면서 이 칸에 앞으로 무엇을 넣을지도 정해야 했다. 봄·여름·겨울을 걷어낸 게 어제인데, 오늘은 명절이 떠올랐고 이어서 할로윈도 떠올랐다. 그때그때 판단하면 또 늘었다 줄었다 할 게 뻔했다.
그래서 기준을 문장 하나로 못박았다. 그 곡을 듣고 그 때를 맞힐 수 있나.
- 크리스마스는 통과한다. 벨 소리와 캐럴 진행이 음악 안에 있다.
- 명절도 통과한다. 국악 편성의 밝은 축하 결이 뚜렷하다.
- 새해는 떨어진다. 카운트다운을 빼면 「활기찬 축하」인데 그건 이미 분위기에 있다.
- 봄·여름은 떨어진다. 사람이 들어도 애매하다.
기준을 문장으로 적어 두면 다음에 후보가 올 때 다시 토론하지 않는다. 앞선 TIL 19에서 「칸을 늘릴 때 다른 축과 만나 몇 개의 조합이 되는지 센다」를 배웠는데, 그건 늘려도 되는지를 세는 방법이고 이건 애초에 자격이 있는지를 묻는 문장이다. 둘이 같이 있어야 칸이 함부로 늘지 않는다.
구분되지 않는 것은 나누지 않는다
명절을 통과시키면서 바로 걸린 게 있다. 설날과 추석을 따로 둘 것인가.
나누지 않기로 했다. 둘 다 국악 편성의 축하 음악이고, 곡만 듣고는 어느 명절인지 가를 수 없다. 나누면 칸은 둘이 되는데 그 안의 곡은 구분되지 않아서, 고른 사람이 두 칸에서 같은 곡을 보게 된다.
여기서 소재와 성격과 기분이 서로 다른 축이라는 것도 정리됐다. 크리스마스는 소재고, 국악 편성은 소리의 성격이며, 활기찬 축하는 기분이다. 「명절 음악」을 분위기에 넣으면 「명절스러운 기분」이라는 말이 되는데 그런 기분은 없다.
분류 칸을 만들 때 그 이름이 무엇을 가리키는지 한 번 더 본다. 소재인지, 소리의 성격인지, 기분인지, 아니면 쓰임인지. 축이 이미 넷 있으니 대개는 들어갈 자리가 정해져 있다.
한 달 몫이 정해져 있어 하나를 고르면 나머지가 밀린다
할로윈은 자격이 있을 수도 있었다. 으스스한 오르간이나 단조 왈츠 같은 관용구가 잡히면 통과다. 그런데 이번 달 몫이 반쯤 남았고 다음 달 몫도 정해져 있다. 할로윈을 채우자면 그 몫을 거기에 다 써야 한다.
미뤘다. 이유는 관용구가 약할까 봐가 아니라, 할로윈이 오기 전에 이 앱이 팔릴지가 불확실해서다. 아직 손님이 없는데 시즌 한 칸을 채우는 데 두 달 몫을 쓰면, 정작 얇아서 결과가 한두 곡뿐인 조합은 그대로 남는다.
미루는 조건도 날짜가 아니라 상태로 걸었다. 앞선 TIL 2에서 「미루는 일에는 날짜가 아니라 조건을 붙인다」고 적었는데, 그때는 「두 번째 고객이 오면」처럼 그 일이 필요해지는 순간이었다. 이번 조건은 「카탈로그가 두꺼워지고 팔린 뒤」라 성격이 다르다. 필요해지는 때가 아니라 감당할 수 있게 되는 때다.
예산이 정해진 자원에서는 무엇을 할지 고르는 일이 곧 무엇을 밀어낼지 고르는 일이다. 정해진 한 달 몫은 그걸 눈에 보이게 만든다.
비어 보이는 것이 없는 것은 아니었다
내부 테스트를 돌리다 무료 체험 카드의 종료 날짜가 「-」로 떴다. 구독 화면의 다음 결제 날짜도 같았다. 상태는 「체험 중」으로 맞고 재생도 열렸는데 날짜만 비어 있었다.
서버에는 날짜가 있었다. 앱이 못 읽은 것이다. 서버가 주는 시각이 두 형식인데, 대부분은 시간대 표시가 없고 구독 만료일만 표시가 이미 붙어 있다. 앱이 모든 값에 표시를 덧붙이다가 뒤엣것이 깨졌다.
읽는 쪽을 한 함수로 모으고, 표시가 이미 있으면 그대로 읽게 했다. 화면마다 각자 붙이다 난 문제였다.
- 한 값에 형식이 둘 섞이면 읽는 쪽을 한 곳으로 모은다. 쓰는 쪽을 통일하는 게 정석이지만 남이 만든 형식이 섞여 있으면 그럴 수 없다.
- 「비어 보인다」를 데이터가 없다고 읽지 않는다. 없는 것과 못 읽는 것은 고치는 자리가 다르다.
안 보이는 오류는 없는 오류와 같다
같은 테스트에서 로그인에 틀린 비밀번호를 넣었다. 아무 일도 안 일어나는 것처럼 보였다. 오류 문구는 폼 아래에 떠 있었는데 키보드가 그 자리를 덮고 있었다.
버튼을 누르면 키보드를 내리게 고쳤다. 오류를 만든 것과 오류를 보여 주는 것은 다른 일이고, 보여 주지 못하면 만들지 않은 것과 같다.
같은 날 더 큰 예가 나왔다. 서버가 실패하자 앱이 「예기치 않은 문자」라고 띄웠다. 개발자에게는 단서지만 매장에게는 아무 뜻이 없다. 무엇을 해야 할지도 알 수 없다. 서버가 사람이 읽을 수 없는 응답을 줄 때 앱이 「지금 서비스에 문제가 있어요」로 바꿔 말해 주는 일이 남았다.
기능을 다 만들고 나서 마지막으로 물을 것은 「잘못됐을 때 쓰는 사람이 무엇을 보게 되나」다. 거기까지가 그 기능이다.
원인인 줄 알았던 작업이 13%였다
그 「예기치 않은 문자」의 원인은 우리 코드가 아니었다. 데이터베이스 무료 요금제의 하루 읽기 한도가 소진돼 있었다. 로그인은 실패 횟수를 기록하려고 데이터베이스를 건드리는데 그게 막혀 오류가 됐고, 앱이 그 오류 본문을 읽다 터진 것이다.
짐작은 바로 나왔다. 낮에 전수 작업을 돌렸기 때문이다 — 곡을 분류하고 조합을 세느라 곡 목록을 통째로 열 번 넘게 다시 받는 일이다. 저게 원인이겠거니 하고 요금제를 올려 한도를 풀었다.
재 봤다. 어떤 요청이 몇 행을 읽었는지 쿼리별로 남는 집계가 있었다. 이 집계는 상위 쿼리만 표본으로 보여 주고 지금부터 24시간을 뒤로 세는 창이라 총합이 청구 기준과 다르다 — 표본 총합은 454만이었다. 몫을 보는 데는 쓸 수 있다.
그 안에서 전수 작업은 57만 행, 13%였다. 짐작이 가리킨 대상 자체는 맞았는데 몫이 작았다. 가장 많이 먹은 것은 태그 목록을 내려 주는 요청으로 180만 행, 40%였다. 이 요청이 돌려주는 값은 태그 37개인데 그걸 고르려고 매번 1만 행을 읽는다. 곡과 태그를 잇는 표가 4,894줄인데 「지금 쓰이고 있는 태그만」을 알아내려고 그 표를 전수로 훑기 때문이다. 그다음은 재생목록 미리보기로 216만 행, 48%였다 — 홈 화면을 한 번 열면 재생목록 일곱 개의 곡 수와 길이를 그때그때 세운다.
합치면 진단이 뒤집힌다. 한도를 먹은 건 내가 돌린 무거운 작업이 아니라 평소 트래픽이었다. 앱을 열고 닫는 것만으로 나가는 요청이 88%를 차지했으니, 그날 전수 작업을 한 번도 안 돌렸어도 한도 언저리였다. 여유가 있는데 내가 다 써 버린 게 아니라, 처음부터 여유가 없었다.
앞선 TIL 17에서 「가끔 실패하는 한도는 양이 늘면 자주가 된다」를 적었다. 그때는 곡을 다시 굽는 작업이 잘리는 이야기였고 실패해도 다시 돌리면 되는 일이었다. 이번에는 같은 한도가 서비스를 멈췄다. 개발하며 쓰는 몫과 손님이 쓰는 몫이 같은 지갑에서 나오기 때문이다.
- 실측 전에 원인을 확정하지 않는다. 눈에 띄는 작업이 범인처럼 보여도 재 보면 몫이 작을 수 있고, 확정해 버리면 엉뚱한 것을 고치게 된다.
- 한도를 재는 단위는 「몇 번 불렀나」가 아니라 「한 번에 몇 행을 읽나 × 몇 번」이다. 37개를 받으려고 1만 행을 읽는 요청은 하루 500번이 상한이다.
- 요금제를 올린 것은 시간을 산 것이지 원인을 고친 게 아니다. 한도가 넓어지면 고칠 동기가 사라지므로 무엇을 고칠지를 같이 정해 둔다.
- 무료 한도를 쓰는 서비스는 「언제 돈을 낼지」를 손님 수로만 재면 늦는다. 손님이 없는데 개발자가 먼저 한도를 치는 날이 온다.
어디서 확인할지가 무엇을 확인할지를 정한다
심사에 낼 시연 영상을 에뮬레이터로 찍기로 했다. 폰 화면에 개인 정보가 비치는 걸 피하려는 이유였다. 그런데 에뮬레이터에서 재생 소리가 버벅였다. 룸톤은 곡을 앱 안에서 풀어 재생하는데 그 처리가 에뮬레이터에 무겁다. 실기기에서는 화면을 끈 채 열세 곡이 끊기지 않았다.
그래서 확인할 것을 갈랐다. 소리가 실제로 매끄러운지는 실기기에서, 화면 흐름은 에뮬레이터에서 본다.
영상도 소리 없이 찍기로 했다. 심사자가 확인하는 건 「앱을 나간 뒤에도 재생이 계속되고 알림에서 조작할 수 있나」다. 음질은 보는 항목이 아니다.
제출 자료를 만들 때 완벽하게 만들려 들기 전에 「이 자료가 무엇을 증명해야 하나」를 먼저 본다. 증명할 것이 정해지면 대개 그보다 적게 만들어도 된다.
코드가 바뀌면 스토어 답안을 먼저 고친다
어제 재생 기록에 계정을 붙였다. 오늘 스토어 데이터 보안 답안을 보니 「곡 재생 기록은 계정과 연결하지 않는다」가 그대로 있었다. 심사는 이 답안과 앱이 실제로 모으는 정보를 대조한다. 그대로 냈으면 서로 다른 말이 된다.
답안을 고치면서 하나 더 걸렸다. 우리 문서에 「계정과 연결」이라는 칸을 두고 있었는데, 그건 애플 앱스토어의 말이고 구글 양식에는 없는 질문이다. 구글은 일시 처리인지, 필수인지, 무슨 목적인지를 묻는다. 내가 그 칸을 콘솔 입력값처럼 안내해서 한동안 엉뚱한 자리를 찾게 만들었다.
목적도 바꿨다. 처음엔 「앱 기능」이라고 했는데, 플랫폼 설명을 열어 보니 맞춤설정의 예시가 「청취 습관에 따른 재생목록 추천」으로 우리 경우와 똑같았다. 앱 기능은 로그인이나 권한 확인처럼 그게 없으면 앱이 안 도는 것에 쓴다.
- 모으는 정보를 바꾸면 그날 스토어 답안을 같이 고친다. 제출 직전에 몰아서 보면 무엇이 달라졌는지 기억나지 않는다.
- 플랫폼 용어를 다른 플랫폼 것과 섞어 쓰지 않는다. 같은 뜻처럼 보이는 말이 서로 다른 질문일 수 있다.
- 분류 항목을 고를 때는 짐작하지 말고 그 플랫폼이 붙여 둔 예시를 읽는다. 예시가 우리 경우와 같은 문장으로 적혀 있을 때가 많다.
아이디가 뭐냐는 질문에 답이 없었다
심사용 계정 비밀번호를 새로 정해야 했다. 그건 운영자만 발급할 수 있어서 관리자로 들어가야 하는데, 관리자 아이디가 뭔지 기억이 안 났다.
찾아보니 아이디가 없었다. 관리자는 계정이 아니라 서버가 들고 있는 비밀값 하나였다.
그래서 질문 자체가 틀렸다. 답이 안 나온 게 아니라 답이 없는 질문이었다.
- 권한이 늘 계정에 붙어 있다고 가정하지 않는다. 사람이 하나뿐인 자리는 계정 없이 비밀값 하나로 두는 게 더 간단할 때가 있다.
- 대신 그런 자리는 잃어버려도 되찾을 데가 없다. 다행히 덮어쓰면 되는 구조였다 — 지금 값을 몰라도 새 값을 넣으면 그만이다. 되찾는 길이 없는 대신 다시 정하는 길이 열려 있어야 한다.
링크를 손으로 옮기다 끝이 잘렸다
관리자로 들어가 재설정 링크를 뽑았다. 열자마자 「링크가 만료되었거나 이미 사용되었습니다」가 떴다. 방금 만든 링크였다.
원인은 링크가 아니라 복사였다. 화면의 긴 주소를 손으로 긁다가 끝이 잘렸다. 복사 버튼을 눌러 다시 하니 됐다.
여기서 두 가지가 걸렸다.
첫째, 긴 비밀을 사람이 옮기게 만들면 잘린다. 화면에 보이니까 옮길 수 있다고 본 건데, 옮기는 사람은 끝까지 긁었는지 확인할 방법이 없다.
둘째, 문구가 원인을 가렸다. 이 링크에는 서명(누가 만든 링크인지 확인하려고 서버가 붙여 둔 확인용 값)이 들어 있는데, 주소가 잘리면서 그게 안 맞게 된 것이다. 그런데 화면은 「만료되었거나 이미 사용되었습니다」라고 했다. 잘린 걸 의심할 단서가 없어서 시간만 썼다. 서로 다른 실패를 한 문구로 묶으면 쓰는 사람이 무엇을 고쳐야 할지 모른다.
- 사람이 옮길 것은 옮길 수 있는 길이로 만든다. 못 줄이면 옮기지 않아도 되게 한다.
- 실패 문구는 원인별로 가른다. 뭉뚱그린 문구는 친절한 게 아니라 정보를 지운 것이다.
고치는 사람이 한 명이면 그 사람이 병목이다
그 링크는 원래 매장을 위한 것이다. 매장이 비밀번호를 잊으면 지원 메일로 알려 오고, 그러면 우리가 링크를 만들어 보낸다. 자동 발송이 붙어 있지 않다.
매장이 하나면 되는데 열 곳이면 안 된다. 새벽에 음악이 끊긴 매장이 우리를 못 찾으면 그 시간 내내 안 되는 거다.
셀프로 가입하고 셀프로 결제하게 만들어 놓고 복구만 사람 손에 걸어 뒀다는 게 앞뒤가 안 맞는다. 손님이 알아서 들어오게 만들었으면 알아서 나가고 알아서 돌아올 수도 있어야 한다.
- 자동화한 곳과 사람이 남은 곳이 짝이 맞는지 본다. 어긋난 자리는 손님이 늘 때 제일 먼저 터진다.
- 손이 가는 일은 지금 감당되는지가 아니라 열 배가 됐을 때 감당되는지로 본다.
메일을 받는 사람과 기기를 쥔 사람이 다르다
그래서 자동 발송을 붙이기로 하고, 링크를 보낼지 인증번호를 보낼지를 정해야 했다.
처음엔 앱을 나가지 않아도 된다는 이유로 번호가 낫겠다고 봤다. 그런데 그건 부차적인 이유였다.
진짜 이유는 이거다. 법인 고객은 가입 메일이 대표 주소일 수 있다. 계산대에 선 직원은 그 메일함을 못 연다. 링크는 메일함을 여는 사람만 쓸 수 있어서 그 자리에서 못 푼다. 번호는 사장이 보고 전화로 불러 주면 직원이 앱에 친다.
같은 결론이어도 근거가 달라지면 규격이 달라진다. 전화로 불러 줄 것을 전제하니 이런 것들이 정해졌다. 아직 만들지는 않았고, 만들 때 지킬 것들이다.
- 숫자만 쓴다. 영문을 섞으면 전화로 부를 때 O와 0, I와 1에서 틀린다
- 세 자리씩 끊어 보여 준다
- 유효시간을 길게 잡는다. 사장이 자리에 없을 수 있어서 불러 주기까지 시간이 걸린다
- 메일에 어느 매장 계정인지 적는다. 대표 메일함에는 여러 건이 들어온다
그리고 짧게 만든 대가를 다른 데서 치러야 한다. 여섯 자리는 백만 가지뿐이라 자동으로 계속 넣어 보면 뚫린다. 틀린 횟수를 조이고, 한 번 쓰면 버리고, 발급 자체도 제한한다. 이건 선택이 아니라 번호 방식을 고른 순간 따라오는 값이다.
- 결론이 같아도 근거를 확인한다. 근거가 바뀌면 만들 물건이 바뀐다.
- 「누가 그걸 받나」와 「누가 그걸 쓰나」를 따로 묻는다. 개인 고객만 생각하면 둘이 같은 사람이라 질문이 떠오르지 않는다.
- 편하게 만든 만큼 어딘가 약해진다. 약해진 자리를 같이 막지 않으면 편해진 게 아니라 구멍이 난 것이다.
새 기능의 값을 묻기 전에 이미 낸 것을 본다
붙이기로 했으니 얼마나 드는지가 다음 질문이었다.
추가 비용이 없었다. 메일 발송이 오늘 올린 요금제에 월 삼천 통까지 포함돼 있었다. 그것도 모르고 외부 메일 업체를 알아볼 뻔했다.
거꾸로 보면 더 재미있다. 무료 요금제에서는 임의 주소로 메일을 보내는 것 자체가 안 된다. 오늘 데이터베이스 한도 때문에 낸 돈이 몇 시간 뒤에 메일 기능을 열어 준 셈이다.
- 새 기능을 붙이기 전에 지금 쓰는 플랫폼에 이미 있는지 본다. 업체를 하나 더 들이면 계정·요금·장애 지점이 하나씩 는다.
- 요금제를 올릴 때는 그게 무엇을 같이 열어 주는지도 본다. 한 가지 문제 때문에 올렸는데 다른 문제의 답이 딸려 오기도 한다.
지운 번호도 플랫폼은 기억한다
번들을 올리려니 버전 번호 7이 이미 쓰인 것이라며 거절당했다. 그 번호로 올렸다가 지운 적이 있어서 비었다고 봤는데 아니었다.
스토어는 한 번 받은 번호를 영구히 기억한다. 지우는 건 내 화면에서 치우는 것이지 그쪽 기록에서 지우는 게 아니다. 8로 올려 다시 빌드했다. 코드는 한 글자도 안 바뀌었다.
- 번호를 매기는 건 우리인데 그 번호를 기억하는 건 상대다. 회수되는 식별자와 안 되는 식별자를 구별해 둔다.
- 되돌릴 수 있어 보이는 조작이 어디까지 되돌리는지 확인한다. 「지웠다」가 「없던 일이 됐다」는 아니다.
메일 주소가 하나인 회사는 어떻게 하나
제출을 마치고 문득 걸려서 물어봤다. 우리는 계정을 이메일로 가른다. 그런데 매장을 여럿 가진 회사가 메일 주소는 하나만 쓰면 어떻게 되나.
계정이 안 갈린다. 메일이 곧 아이디라서, 주소가 하나면 계정도 하나다. 매장이 다섯이어도 하나만 만들 수 있다.
식별자를 무엇에 묶느냐가 그대로 제약이 된다는 걸 여기서 봤다. 이메일은 우리가 발급하는 게 아니라 손님이 다른 데서 받아 오는 것이다. 편해 보여서 골랐는데, 손님 쪽 사정이 우리 제품의 한계가 됐다.
- 아이디를 남이 발급한 것에 묶으면 그쪽 사정이 그대로 우리 제약이 된다.
- 「한 사람이 하나만 쓴다」는 가정이 깔려 있지 않은지 본다. 개인 손님만 생각하면 그 가정이 안 보인다.
막힌 곳은 메일이 아니었다
메일을 여러 개 만들게 하면 풀리는 줄 알았다. 실제로 방법도 있었다.
그런데 그다음이 막혔다. 구글 결제는 같은 구독 상품을 한 계정이 두 번 살 수 없다. 다시 사면 새 구독이 기존 것을 밀어낸다. 그리고 우리는 계정당 동시 재생을 1대로 묶어 놨다. 매장 다섯을 한 계정으로 돌리는 건 애초에 안 되는 방향이었다.
눈에 보이는 막힘은 이메일이었는데 실제로 못 지나가는 문은 두 개 더 뒤에 있었다. 이메일만 고쳤으면 고쳐 놓고도 안 됐을 것이다.
- 막힌 곳을 하나 찾으면 거기서 멈추지 말고 그 뒤를 마저 본다. 앞의 것을 고쳐도 뒤가 남아 있으면 헛일이다.
- 우리가 건 제한도 같이 센다. 동시 재생 1대는 도난을 막으려고 우리가 건 것인데, 그게 체인 고객을 막는 벽이 되기도 한다.
「한국은 되지 않나」 — 규칙에 날짜가 붙어 있었다
그래서 체인은 앱이 아니라 웹에서 결제해야 한다는 결론이 나왔다. 그런데 앱에서 판매 페이지로 링크를 걸 수 없다고 했다. 구글 플레이 정책상 앱 밖 결제 유도가 막혀 있다는 것이었다.
한국은 개발자가 자기 결제를 붙일 수 있게 법이 바뀌지 않았나 싶어 되물었다. 찾아보니 그보다 더 나간 게 있었다. 구글 플레이가 수수료를 낮추고 외부 결제와 바깥 링크를 허용하기로 했는데, 적용 시기가 지역마다 달라서 한국은 2026년 12월 적용 예정이다(2026-09-28 확인).
그러면 두 달 뒤엔 앱에서 판매 페이지로 정식으로 보낼 수 있다. 그러면 지금 급하게 만들 게 없어진다. 매장 여럿을 묶는 구조를 새로 짜려던 걸 접었다.
- 「안 된다」는 답에는 대개 날짜가 숨어 있다. 지금 안 되는 것인지, 앞으로도 안 되는 것인지 갈라 묻는다.
- 규칙이 바뀔 날짜가 잡혀 있으면 그때까지 안 만드는 것도 설계다. 두 달 버티는 방법만 있으면 된다.
- 플랫폼 정책은 알고 있는 것을 다시 확인하고 말한다. 자주 바뀌고, 바뀐 걸 모르면 있는 길을 없다고 말하게 된다. 적어 둘 때도 언제 확인한 건지 같이 적는다 — 이 글의 12월도 나중에 읽으면 어느 해인지 모른다.
요약
- 값이 하나인 칸을 둘지는 값의 수가 아니라 「없으면 못 하는 일이 생기나」로 정한다.
- 분류 칸에 값을 더할 자격을 문장 하나로 못박아 두면 후보가 올 때 다시 토론하지 않는다.
- 구분되지 않는 것은 나누지 않는다. 칸만 늘고 같은 것이 두 번 보인다.
- 이름이 소재인지 소리의 성격인지 기분인지 쓰임인지 가리면 들어갈 축이 정해져 있다.
- 예산이 정해진 자원에서 무엇을 할지 고르는 일은 무엇을 밀어낼지 고르는 일이다.
- 미루는 조건에는 「필요해지는 때」와 「감당할 수 있게 되는 때」가 따로 있다.
- 한 값에 형식이 둘이면 읽는 쪽을 한 곳으로 모은다. 비어 보이는 것과 없는 것은 다르다.
- 오류를 만든 것과 보여 주는 것은 다른 일이다. 기능은 「잘못됐을 때 무엇을 보게 되나」까지다.
- 실측 전에 원인을 확정하지 않는다. 한도를 먹는 건 눈에 띄는 무거운 작업이 아니라 값싸 보이는데 자주 부르는 화면일 수 있다.
- 제출 자료는 「무엇을 증명해야 하나」를 먼저 정하면 그보다 적게 만들어도 된다.
- 모으는 정보를 바꾸면 그날 스토어 답안을 같이 고치고, 플랫폼 용어를 섞어 쓰지 않는다.
- 권한이 늘 계정에 붙어 있지는 않다. 되찾을 길이 없는 자리는 다시 정할 길이 있어야 한다.
- 사람이 옮길 것은 옮길 수 있는 길이로 만들고, 실패 문구는 원인별로 가른다.
- 자동화한 곳과 사람이 남은 곳의 짝을 본다. 어긋난 자리가 손님이 늘 때 먼저 터진다.
- 결론이 같아도 근거를 확인한다 — 「누가 받나」와 「누가 쓰나」가 다르면 만들 물건이 달라진다.
- 편해진 만큼 약해진 자리를 같이 막는다. 안 막으면 편해진 게 아니라 구멍이 난 것이다.
- 새 기능을 붙이기 전에 지금 요금제에 이미 들어 있는지 본다.
- 「지웠다」가 「없던 일이 됐다」는 아니다. 회수되는 식별자와 안 되는 식별자를 구별한다.
- 아이디를 남이 발급한 것에 묶으면 그쪽 사정이 우리 제약이 된다.
- 막힌 곳을 하나 찾으면 그 뒤를 마저 본다. 우리가 건 제한도 벽이 될 수 있다.
- 「안 된다」에는 날짜가 숨어 있다. 바뀔 날이 잡혀 있으면 그때까지 안 만드는 것도 설계다.