9월 8일, 네이버 로그인 승인을 확인하러 개발자 콘솔을 열었다. 제출된 소명문을 펼쳐 보니 171자 다섯 문장이었다. 세션이 쓴 문서에는 「최종 제출본」으로 135자 네 문장이 적혀 있었다. 다섯째 문장은 제출 직전에 내가 더한 것이었고, 어느 기록에도 없었다
그 뒤로 규칙을 하나 정했다. 제출본의 정본은 문서가 아니라 제출된 자리에 있다. 9월 20일 공모전 1차 심사자료를 낼 때는 여기서 한 걸음 더 갔다. 올린 PDF를 접수 화면에서 다시 내려받아 승인본과 sha256을 대조했다. 1,621,709바이트가 전부 같았다
네이버 로그인 검수는 서비스 URL 하나로 거부됐다
9월 4일에 네이버 로그인 검수를 신청했다. 사흘 뒤 거부됐다. 사유는 하나였다
등록하신 서비스URL을 통해 서비스 콘텐츠 유형이 확인되지 않아, 네이버 로그인 운영원칙/관계 법령에 따라 네이버 로그인 적용이 가능한 서비스인지 확인 필요합니다.
지적이 맞았다. 등록한 도메인에는 개인정보처리방침, 위치기반서비스 이용약관, 계정 삭제 안내 페이지밖에 없었다. 방침 URL을 먼저 세운 이야기는 앞선 글에 있다. 앱 본체는 화면이 73개인데 URL로는 하나도 안 보인다
거부 안내는 대안도 적어 두었다. 서비스 운영이 아닌 목적이면 검수 없이 「개발 중」 상태로 쓸 수 있다. 그런데 9월 4일 콘솔에 이런 문구가 있었다
개발 중 상태에서는 등록된 아이디만 로그인할 수 있습니다
공개 배포하면 멤버로 등록하지 않은 이용자는 네이버 로그인에 실패한다. 이 길은 버리고 재검수를 넣기로 했다
초안의 두 문장이 앱과 달랐다
네이버는 셋을 요구했다. 메뉴별 기능 설명과 화면, 업종과 콘텐츠 형태, 개발 페이지가 있으면 서비스 예정 URL이다. 업종 예시로 「일자리 업종 유형, 모임 유형」을 들었는데, 둘 다 우리 앱에 있는 기능이었다
세션이 라우터 코드를 근거로 초안을 썼다. 그중 두 문장이 사실과 달랐다
첫째는 일자리였다. 초안은 간편 지원, 지원 현황, 자격증 등록, 구직 프로필을 메뉴로 적었다. 세션이 라우터에서 path:만 grep해 「라우트 70여 개」로 셌기 때문이다. 앱 코드를 맡은 세션이 조건부 등록을 짚었다. 요지만 옮기면 이렇다
// jobs_availability.dart const jobsServiceLive = false; // app_router.dart — 이 블록 안의 라우트 6개는 등록되지 않는다 if (jobsServiceLive) ...
살아 있는 일자리 라우트는 공공 일자리 열람 하나였다. 첨부하려고 찍어 둔 일자리 화면에도 「지원은 각 접수처에 문의해요」라고 적혀 있었다
둘째는 모임이었다. 초안은 「불특정 다수에게 공개되는 커뮤니티가 아니다」라고 적었다. 모임 화면 캡처에는 「내 주변 / 전국」 필터가 있었고, 「전국」을 고르면 남이 만든 모임이 떴다. 세션은 채팅 기능의 「단체 대화방 만들기」 문자열을 보고 모임을 판단했는데, 단체 대화방과 모임은 다른 기능이었다
일자리 쪽 정정은 오히려 소명에 유리했다. 「중개·수수료 없음」을 화면이 직접 증명했다. 모임 쪽은 거짓 문장을 빼고 「공개 모임이며 상업적 거래, 금전 거래, 성인 대상 콘텐츠를 다루지 않는다」로 바꿨다. 코드를 읽은 판정보다 실제 화면이 한 단계 더 정확했다
500 제한은 글자 수가 아니었다
두 문장을 고친 초안은 1,560자였다. 소명문 입력란에는 「500」 제한이 있었다. 472자로 줄여 넣었는데도 초과로 거절됐다. 472는 500보다 작다. 그래서 이 제한은 글자 수가 아니라 바이트라고 봤다. UTF-8이면 472자는 1,400바이트 안팎이다. 어떤 인코딩으로 세는지는 화면이 알려 주지 않았다
어느 기준이든 들어가게 줄였다
135자 · UTF-8 329바이트 · EUC-KR 234바이트
네 문장이 네이버의 질문 넷에 하나씩 답하게 짰다
| 문장 | 답하는 질문 |
|---|---|
| 공공데이터로 주변 장소·일자리·복지 혜택을 안내하는 무료 앱 | 서비스 콘텐츠 유형 |
| 등록 URL은 고지 페이지뿐이라 앱 화면 7장을 첨부 | URL로 확인이 안 되는 이유 |
| 일자리는 정보 열람만, 모임은 나들이 동행 | 일자리 유형, 모임 유형 |
| 거래·결제·광고가 없다 | 전자상거래 해당 여부 |
버린 설명은 첨부가 대신했다. 첨부 상한이 5개라 메뉴 화면 7장을 라벨 붙인 격자 한 장으로 합쳤다. 걷기 화면은 빈 상태로 찍혀 있어 코스 목록 화면으로 갈아 끼웠다. 각 화면 하단에는 공공데이터 출처가 이미 찍혀 있었다
콘솔의 제출본은 다섯 문장이었다
9월 7일에 재검수를 넣었고 다음 날 승인됐다. 1회차가 사흘, 재검수는 하루였다. 메뉴 격자가 거부 사유를 정면으로 해소한 것으로 보인다. 네이버가 이유를 밝히지는 않았다
그리고 도입부의 그 장면이다. 콘솔에 남은 제출본은 이랬다
시니어에게 주변 장소·일자리·복지 혜택을 공공데이터로 안내하는 무료 앱입니다. 등록 URL은 고지 페이지뿐이라 앱 화면 7장을 첨부했습니다. 일자리는 정보 열람만 하고 접수는 안 받으며, 모임은 나들이 동행입니다. 거래·결제·광고가 없습니다. 네이버 로그인은 식별자와 별명만 받아 별명을 표시명으로 씁니다.
마지막 줄은 내가 붙여 넣기 직전에 쓴 것이다. 네이버 검수가 보는 「제공 정보 활용처」에 답하는 문장이다. 세션 초안은 네이버가 물은 넷에 답하느라 이 항목을 빠뜨렸다
세션의 문서만 믿고 보고서를 썼다면 「135자 네 문장으로 승인」이라는 틀린 문장이 나갔다. 문서에 「최종본」이라 적힌 순간 사람은 그걸 다시 열어 보지 않는다. 기록과 실물이 갈릴 수 있는 자리는 사람이 마지막에 손댄 자리다
구글 쪽은 이 과정이 없었다. OAuth 동의 화면을 프로덕션으로 게시했는데, 코드에서 scopes를 따로 지정한 곳이 0건이라 기본 범위(openid, email, profile)만 쓴다. Google은 민감하지 않은 범위만 쓰는 앱은 앱 인증 절차가 필수가 아니라고 적는다. 게시하자마자 끝났다
공모전 접수값은 다섯 자리를 고쳐야 했다
공모전 1차 심사자료 제출 화면을 열자, 5월에 접수할 때 넣은 값이 그대로 남아 있었다. 그 사이 서비스가 바뀌었다. 매뉴얼은 서비스명과 개요를 「개발 완료한 최종 서비스의 명칭과 설명」으로 고치라고 했다
| 항목 | 접수값 | 제출값 |
|---|---|---|
| 서비스명 | 팀명과 같은 가칭 | 최종 앱 이름 |
| 서비스 개요 | 특정 지역 휴식 동선 플래너(135자) | 최종 서비스 설명(244자) |
| 지역특화 유무 | 예(특정 도) | 아니오 |
| 서비스 유형 | 웹, 앱 | 앱 |
| 안드로이드마켓 URL | 비어 있음 | 원스토어 링크 |
지역특화 칸은 문서끼리의 정합 문제였다. 기능설명서 양식은 지역특화 장을 [선택]으로 찍고 「해당사항 없는 경우 해당 슬라이드 삭제」라고 적는다. 그 장을 지웠으니, 화면이 「예」로 남아 있으면 필수 작성 항목을 누락한 것으로 읽힌다. 「아니오」로 고치면서 지역 특별상 후보에서 빠졌다. 특화 내용이 없으니 받을 근거도 없었다
개요 글자 수에서 매뉴얼과 화면이 달랐다. 매뉴얼 미리보기에는 900자 한도가 보였는데, 화면 카운터는 남아 있던 접수 개요에 135 / 300을 표시했다. 접수 개요의 공백 포함 길이가 정확히 135자였다. 한도는 공백 포함 300자다. 244자로 맞췄다
인증키는 재발급하지 않았다
심사 유의사항에 이런 문장이 있었다
제출한 인증키(인코딩, 디코딩) 통해 활용 API별 서비스 개발 기간 내 호출건수 및 서비스 내 API 활용 내역 확인 예정
호출 이력은 키에 묶인다. 새 키로 바꾸면 이력이 0에서 시작한다. 그래서 제출 전날 운영 서버에서 프로브를 돌려 현재 키의 호출량을 다시 쟀다
관측 34일 · 5,608건 (한국관광공사 4,954건) · 하루 평균 167건 대상 API 17종 전부 0이 아님
겹치는 12일 구간이 이전 측정값과 정확히 일치해 계측기를 믿었다. 이 값은 서버 로그에서 성공한 호출만 센 것이라 하한이다. 포털이 세는 실제 호출건수는 활용자 화면이 없어 보지 못했다
인증키는 공공데이터포털에서 내가 직접 복사해 붙였다. 세션이 만질 수 없는 값이고, 채팅이나 문서, Git 어디에도 넣지 않았다. 활용 API 6종은 화면 목록의 표기가 준비표와 한 글자도 어긋나지 않는 것을 대조한 뒤 체크했다. 운영계정신청여부는 비웠다. 신청한 적이 없다. 모르는 게 아니라 없는 것이다
양식을 되돌리자 한 줄이 잘렸다
기능설명서는 공식 PPTX 양식을 스크립트로 채워 PDF로 뽑았다. 9월 20일, 나는 세션에 양식의 글꼴과 간격을 바꾸지 말라고 했다. 세션이 원본 양식과 산출물의 XML을 대조해 어긋난 자리를 찾았다
| 무엇 | 양식 | 빌드가 하던 것 |
|---|---|---|
| 흐름도 본문 | 18pt | 14pt |
| API명·데이터명 | 14pt | 16pt |
| 차별성·발전계획 | 18pt | 16pt |
| 문단 뒤 간격 | 전부 0 | 6pt·8pt 16곳 |
전부 양식 값으로 되돌렸다. 대가가 바로 왔다. 흐름도 한 칸의 문장이 89자라 18pt에서 4줄을 넘겼고, 마지막 줄이 칸 밖으로 잘렸다. 몇 자까지 3줄에 들어가는지는 빌드를 다섯 번 돌려 쟀다. 62자, 65자, 68자는 전부 넘쳤고 56자가 들어갔다. 원고를 56자로 줄였다. 빠진 설명은 같은 칸의 화면 캡처가 보여 준다
글꼴 하나는 되돌리지 않았다. 양식 지정 글꼴이 빌드하는 맥에 설치돼 있지 않았다. 그대로 두면 변환기가 한글은 한 글꼴로, 숫자와 영문은 세리프 글꼴로 갈라 대체한다. 두 판을 렌더해 눈으로 비교했고, 한 글꼴로 치환한 판을 골랐다. 양식이 의도한 「한 글꼴」에 그쪽이 더 가까웠다
이 비교는 측정값이 없다. 「어느 쪽이 양식처럼 보이나」는 사람이 본다. 완성된 13쪽을 끝까지 읽고 「이걸로 낸다」고 답한 것도 나였다. 세션은 자리표시 문구 0건, 13장 잘림·겹침 0건을 검사했지만, 자기 산출물을 제출본으로 승인할 수는 없다
올린 파일을 다시 내려받아 해시를 비교했다
9월 20일 오후 5시 38분에 제출했다. 접수 계정이 팀장 명의라 그 계정으로 들어가 인증번호를 받았다. 4분 뒤 완료 메일이 왔고, 팀명·서비스명·부문·일자 넷이 제출값과 맞았다. 접수확인 목록에도 반영됐다
여기서 끝낼 수 있었다. 아무도 다음 단계를 요구하지 않았다. 그래도 접수확인 상세에서 올라간 첨부를 다시 내려받았다
shasum -a 256 승인본.pdf 내려받은본.pdf ls -l 승인본.pdf 내려받은본.pdf
해시 앞 8자리 44d9f844와 끝 6자리 a3b3a2가 같았고, 크기도 둘 다 1,621,709바이트였다. 업로드 중 손상도, 판 섞임도 없었다
이 단계를 넣은 이유는 이미 한 번 판이 섞인 적이 있어서다. 같은 날, 양식을 되돌린 PPTX를 다시 빌드하고 PDF를 산출물 폴더로 복사하는 걸 빠뜨렸다. PPTX와 PDF가 서로 다른 판이 됐다. 그 뒤로는 빌드할 때마다 두 파일의 글꼴을 대조한다. 섞인 PDF를 그대로 올렸으면 승인한 파일과 제출한 파일이 달랐다
완료 화면과 완료 메일은 「무언가 올라갔다」까지만 말한다. 「내가 승인한 그 파일이 올라갔다」는 올라간 파일을 다시 받아 비교해야 닫힌다
제출 버튼을 누른 뒤에는 기록을 믿지 말고 제출된 자리를 한 번 더 연다. 텍스트는 콘솔에서 다시 읽고, 파일은 다시 받아 해시로 비교한다. 거기서 나온 값이 정본이다
시리즈: AI 세션과 앱 출시하기
- AI 에이전트가 앱 출시를 대신 못 한 자리는 네 종류뿐이었다
- 위치기반 앱은 스토어 저장 버튼에서 사업자등록까지 거슬러 올라간다
- 원스토어 콘솔에서는 기본값과 「권장」부터 의심했다
- 제출본의 정본은 내 문서가 아니라 콘솔과 업로드된 파일이다 (이 글)
공모전의 팀명·서비스명·지역과 팀원 이름은 적지 않았다. 인증키와 해시는 일부만 적었다.