노트버디 개발기 6: AI가 그림을 만들었다고 아이템을 차감하면 안 된다
TL;DR
- 착용 이미지를 생성하거나 미리보기로 보는 동안에는 원본 초상화와 아이템을 유지합니다. 사용자가 적용하고 게임 저장이 성공할 때만 아이템 1개를 소모합니다.
- 받은 결과는 먼저 보존하고, 저장 실패나 재접속에서는 그 결과를 복구합니다. 받지 못한 이미지까지 복구할 수 있는 것은 아니며 자동 유료 재시도는 하지 않습니다.
- 원본과 결과 비교, 진행 표시, 작은 화면의 버튼과 복귀 흐름도 함께 다듬었습니다.
- 이번 편으로 Anna 기능 개발 이야기를 한 차례 정리합니다. 모바일 버전도 개발 중이며, 출시를 준비하고 있습니다.
들어가며
5편에서는 친구에게 가구 배치를 맡기면서 코드가 지켜야 할 규칙을 이야기했습니다. 이번에는 모험에서 얻은 아이템을 친구의 초상화에 반영하는 착용 기능입니다.
착용 버튼을 누르면 새 그림을 만들고 아이템을 하나 빼면 될 것 같지만, 그 사이에 멈출 수 있는 지점이 있습니다. 그림은 나왔는데 업로드가 실패할 수도 있고, 저장은 끝났는데 화면이 응답을 받지 못할 수도 있죠. 결과가 마음에 드는지 확인하기 전부터 아이템이 사라지는 것도 피하고 싶었습니다.
그래서 이번에는 성공했을 때의 결과보다 중간에 실패해도 무엇을 남겨야 하는지를 중심으로 흐름을 나눴습니다.
미리보기까지는 아이템을 그대로 둡니다
착용은 다음 순서로 이어집니다.
아이템과 현재 초상화 예약
→ 이미지 요청 1회
→ 받은 결과 보존·업로드
→ 원본과 결과 미리보기
→ 사용자가 적용
→ 게임 저장 성공: 초상화 변경 + 아이템 1개 소모
처음 예약할 때는 어떤 친구의 어느 성장 단계에서, 어떤 초상화와 아이템으로 시작했는지 기록합니다. 아직 아이템을 소모하지는 않습니다. 진행 중인 예약이 있으면 다른 착용을 시작하지 못하게 하고, 같은 화면에서 버튼을 연속으로 눌러도 진행 중인 작업을 공유합니다.
이미지를 받으면 브라우저의 IndexedDB에 복구용 바이트를 남깁니다. 이어서 결과 파일의 경로를 그림 기록에 먼저 등록하고 업로드합니다. 정리 작업이 이 파일을 사용하지 않는 그림으로 보지 않도록 하기 위해서입니다. 이 기록만으로 현재 초상화가 바뀌지는 않습니다.
마지막으로 사용자가 적용을 누르면 저장된 파일이 실제로 있는지 확인합니다. 초상화 경로 변경, 아이템 1개 소모, 발견 기록과 요청 처리 기록은 게임 저장 안에서 함께 반영합니다. 다만 그림 파일과 그림 기록, 게임 상태는 서로 다른 저장소입니다. 앞의 모든 단계를 하나의 원자적 트랜잭션으로 처리하는 것은 아닙니다. 착용 흐름과 저장 전 파일 확인에 이 순서를 나눠뒀습니다.
다시 누르는 대신, 어디까지 끝났는지 확인합니다
오류가 났다고 처음부터 그림을 다시 만들면 이미 받은 결과를 버리거나 같은 비용을 다시 쓸 수 있습니다. 그래서 복구 버튼은 새 생성을 요청하지 않고 남아 있는 결과와 처리 기록을 확인합니다.
| 멈춘 지점 | 이어가는 방법 |
|---|---|
| 결과를 받았지만 업로드 실패 | 같은 창의 메모리나 IndexedDB에 남긴 이미지로 저장을 다시 시도합니다. |
| 미리보기 전에 화면을 다시 열었음 | 로컬 복구 기록 또는 업로드된 파일에서 결과를 불러옵니다. |
| 적용 저장 후 응답을 못 받음 | 같은 요청 ID로 처리 기록을 확인합니다. 이미 적용됐다면 다시 소모하지 않습니다. |
| 적용 전 친구·초상화 상태가 달라짐 | 관찰된 변경을 검사해 오래된 적용을 막습니다. |
아직 적용되지 않은 요청 ID가 다른 게임 행동 때문에 만료된 경우도 구분합니다. 번호만 자동으로 바꿔 재전송하지 않고, 저장된 미리보기를 복구한 뒤 사용자가 다시 적용하도록 합니다.
취소는 아직 적용하지 않은 착용을 포기하는 동작입니다. 원본과 아이템을 유지하고, 이미 보존한 결과 파일도 지우지 않습니다. 반대로 적용이 끝난 뒤의 취소를 환불이나 장착 해제로 취급하지는 않습니다.
복구에도 한계는 있습니다. 생성 요청 도중 창이 종료되는 등 결과 바이트를 보존하기 전에 유실되면, 현재 제공자의 결과 조회 API가 없어 보지 못한 이미지를 되찾을 수 없습니다. 이 경우 원본과 아이템, 예약을 유지하고 자동 유료 재시도를 막습니다. 업로드 전의 IndexedDB 사본도 해당 기기의 브라우저 데이터이므로 다른 기기로 옮겨주는 백업은 아닙니다. 이 경계는 복구 설계와 제한 사항에 남겨뒀습니다.
아이템 그림을 그대로 붙이는 기능은 아닙니다
현재 이미지 편집 API에 보내는 것은 캐릭터 원본 한 장과 아이템 설명입니다. 캐릭터와 아이템 이미지 두 장을 정밀 합성하는 방식은 아닙니다. 따라서 도감에 있는 그림을 정확히 복제하기보다, 설명을 해석한 새 착용 모습에 가깝습니다.
실제 확인에서는 머리장식·목도리·망토·오라를 각각 한 장씩, 총 네 번 편집했습니다. 네 결과 모두 저장됐고, 눈으로 살펴봤을 때 원본의 얼굴과 색, 팔다리나 날개 같은 특징을 유지했습니다. 기존 사용량 범위에서 진행했으며 추가 결제·충전과 자동 유료 재시도는 없었습니다.
그렇다고 모든 캐릭터와 아이템에서 같은 품질이 나온다는 뜻은 아닙니다. 네 가지 샘플을 확인한 결과이고, 다른 조합은 다를 수 있습니다. 그래서 설명문뿐 아니라 사용자가 원본과 결과를 비교하는 단계가 꼭 필요했습니다.
저장 규칙만큼 화면에서 보이는 순서도 중요했습니다
로컬 Chromium에서 데스크톱과 너비 320px·390px 화면을 살펴보니, 기능이 동작하는 것과 사용자가 다음 행동을 알 수 있는 것은 별개였습니다. 검토에서 발견한 부분을 이렇게 고쳤습니다.
- 원본과 결과 비교: 두 그림에 이름을 붙이고 잘리지 않게 나란히 보여줍니다. 각각 크게 볼 수도 있게 했습니다.
- 진행과 성공의 구분: 생성·다운로드·저장 중인 상태를 표시하고, 미리보기에서는 아직 적용 전이라는 점을 알립니다. 적용 버튼에도 아이템 1개가 소모된다고 적었습니다.
- 작은 화면의 버튼 배치: 주요 버튼이 좁은 줄에 몰리지 않도록 배치를 나누고, 주요 동작과 닫기 버튼은 누를 영역을 최소 44px로 맞췄습니다.
- 닫기와 취소, 복귀: 착용 화면을 닫거나 Escape를 눌러도 진행 중인 작업을 버리지 않습니다. 다시 열기 버튼을 제공하고, 진행 상태나 적용 버튼으로 포커스를 옮겨 다음 행동을 찾을 수 있게 했습니다. 앱 창 자체는 저장이 끝날 때까지 열어둬야 합니다.
특히 320px 화면에서는 진행 배너가 있어도 도감 스크롤과 고정 헤더에 가려지는 문제가 있었습니다. 화면을 닫은 사용자가 작업이 계속되는지 알 수 없으니, 복구 기능만 준비해둬서는 부족하겠죠. 도감이 열려 있으면 배너를 헤더 바로 아래로 옮기고, 상세 화면을 닫을 때 스크롤도 위로 맞춰 보이게 했습니다. 도감 화면의 복귀·포커스 처리가 이 부분을 담당합니다.
확인한 범위와 아직 남은 일
별도의 개발 환경에서는 실제 Anna 저장소와 파일, Python SDK를 사용해 두 창의 동시 예약과 저장 충돌을 확인했습니다. 미리보기 중에는 아이템을 유지하고, 명시적으로 적용할 때만 하나를 소모하는지 봤습니다. 업로드·게임 저장 실패, 재접속, 적용 응답 유실 뒤 같은 처리 기록으로 복구하는 경우도 확인했고요. 이미 만든 이미지를 재사용해 이 검증에서는 AI를 추가 호출하지 않았습니다.
실행 코드 85de646의 Windows·Linux CI는 각각 JavaScript 107개, 브라우저 140개, 저장·프로토콜 79개와 빌드 검사를 통과했습니다. 이 결과와 앞의 이미지·화면 검토는 1.4.17 검증 기록에 정리돼 있습니다. 이번 글을 쓰면서 새로 유료 호출을 한 결과는 아닙니다.
화면 검토는 격리된 Chromium에서 진행했습니다. 설치된 파일과 도구는 별도로 확인했지만, 실제 Anna 네이티브 화면과 실물 모바일 기기의 표시·조작까지 검증한 것은 아닙니다.
2026년 10월 25일 확인 기록 기준으로 Anna 1.4.17은 심사 ID 1640으로 제출돼 대기 중이며, 이전 1.4.16 심사본을 대체했습니다. 공개 최신 버전은 여전히 1.4.13입니다. 테스트와 제출을 마쳤다는 사실을 승인이나 전면 공개로 표현해서는 안 되는 단계입니다.
Anna 개발기는 여기서 한 번 정리하려 합니다
제안 메일에서 시작해 Python 규칙을 앱으로 옮기고, 그림 한 장에서 친구를 만들었습니다. 그 친구가 집과 던전을 걷고, 가구를 고르고, 이제는 아이템을 반영한 새 모습을 미리 볼 수 있게 됐습니다.
이번 착용 기능에서는 새 그림을 만드는 일만큼, 실패한 뒤에도 사용자의 아이템과 이미 받은 결과를 지키는 일이 중요했습니다. 그리고 그 상태가 화면에서도 분명하게 보여야 했고요. 여기까지를 Anna 기능 개발의 첫 묶음으로 정리해보려 합니다. 심사 대응과 운영, 실제 기기에서 더 확인할 일까지 모두 끝났다는 뜻은 아닙니다.
모바일 버전도 개발 중이며, 출시를 준비하고 있습니다. 현재는 release-android의 Android 0.2.2 alpha 단계입니다. 최신 버전의 실물 기기 확인과 정식 서명, 스토어 준비가 남아 있습니다. Android 개발 기록을 이어가며, 다음에는 모바일에서 친구와 지내는 경험을 더 다듬어보려 합니다.
NOTEBUDDY · ANDROID
작은 화면에서도, 친구와 함께
출시를 준비 중인 Android 0.2.2 alpha를 에뮬레이터에서 직접 실행해 봤습니다. 아래는 격리된 테스트 공책에 기본 캐릭터와 오프라인 샘플 데이터를 담아 촬영한 화면이에요. 이미지를 누르면 원본 크기로 볼 수 있습니다.
2026.10.25 촬영 · Android 개발 버전 0.2.2-alpha · Android API 36 에뮬레이터 · release-android ee0f420
실행 화면은 adb로 캡처한 원본 PNG입니다. 휴대폰 테두리와 배경은 블로그 CSS로만 표현했으며, 실기기 검증이나 스토어 출시를 뜻하지 않습니다.
Comments