어젯밤 지시대로 남은 것을 끝내고 성능까지 잡았습니다. 커밋 12개, 코드 18,743줄 삭제 / 434줄 추가.
가장 먼저 보실 것 세 가지만 앞에 둡니다.
지시하신 "데이터 가져오기 · 페이지 이동 · 이미지 로딩"을 각각 재고 고쳤습니다.
| 자리 | 전 | 후 | 무엇이었나 |
|---|---|---|---|
| 채팅방 열기(346개 메시지) | 150ms | 5.2ms | 행은 인덱스로 찾는데 시간순 정렬을 따로 하고 있었습니다. 대화가 길수록 나빠지는 모양이라 지금 잡는 게 맞았습니다 |
| 크루 자료 검색(매 턴) | 346ms | 9~204ms | 근사 인덱스가 1,465건 전체를 훑었습니다. 우리는 늘 크루로 먼저 거르니(19~416건) 그 작은 묶음에선 정확 계산이 더 빠르고 정확합니다 |
| 아바타 1장 | 68KB | 2KB | 채팅 화면이 36px 자리에 원본을 그대로 받고 있었습니다. 가장 많이 도는 화면입니다 |
아바타는 크기를 줄여 받는 것만으로는 반쪽입니다 — 받아온 뒤 원본 해상도로 메모리에 푸는 문제가 남아서, 표시 크기의 2배까지만 디코딩하도록 같이 막았습니다. 이미 축소해서 받던 세 곳도 이 처리가 빠져 있어 함께 붙였습니다.
대화 목록·크루 목록은 이미 빨랐습니다(2.3ms / 15ms). 손대지 않았습니다.
사전 조회 셋(자료·기억·장소)이 줄줄이 기다리는 구조라 병렬로 바꿨습니다. 직렬 대기 300~800ms가 사라진 건 맞지만 총 응답시간은 그대로입니다(7.5~15초, 전후 같은 범위). 병목이 조회가 아니라 LLM 생성 자체이기 때문입니다. 과장하지 않으려고 그대로 적습니다.
다만 체감은 다릅니다 — 말풍선은 생성되는 즉시 화면에 뜨고, 카드 판정 같은 뒷일은 그 뒤에 돕니다. 사용자가 기다리는 건 첫 말풍선까지입니다.
이게 어젯밤 나온 것 중 가장 나빴습니다.
서버 호출이 실패하면 앱이 ① 자기가 직접 외부 LLM을 부르고 ② 그것마저 실패하면 사용자 문장에 키워드 매칭(고민·어떻게·힘들)을 해서 크루인 척하는 문장을 조립해 붙였습니다. 능력치로 랜덤까지 섞었습니다.
두 가지가 동시에 잘못됐습니다. 자연어를 키워드로 판정한 것이고, 아무도 답하지 않았는데 답한 것처럼 보이게 한 것입니다.
지금은 못 하면 못 했다고 로그만 남깁니다. 전수 확인 결과 해당 코드 0건, 앱에 남은 자연어 키워드 매칭 0건, 앱에서 외부 LLM 직호출 0건입니다.
Vercel AI Gateway 하나입니다. 형이 결제하시는 건 Vercel뿐이고, 오픈AI 계정으로 나가는 요금은 없습니다.
모델 이름에 openai/가 붙지만 그건 게이트웨이가 쓰는 이름표이지 형 오픈AI 계정이 아닙니다. Vercel이 대신 부르고 Vercel이 청구합니다.
어젯밤까지는 아니었습니다. 살아 있는 자리 세 곳(다자방 토론 감지·자연어 지목·크루 기억 임베딩)이 옛 키로 딴 데를 직접 부르고 있었고, 모델도 옛 경량 모델이었습니다. 키가 흩어져 있으면 하나 만료됐을 때 어디가 죽었는지 알 수가 없습니다 — 어제 찾은 사고가 전부 그 모양이었습니다(만료된 키 때문에 요약과 기억이 조용히 죽어 있었고, 상담 906건 중 요약이 채워진 건 18건뿐이었습니다).
셋 다 한 곳으로 모았고, 옛 키를 들고 있던 안 쓰이는 파일 세 개도 지웠습니다.
알림 배관은 만들어 뒀는데 넣는 코드가 어디에도 없었습니다. 크론은 매분 돌고 있었고 대상은 0건이었습니다. 제가 "알림 층 완료"라고 보고했던 건 보내는 쪽 얘기였고, 이걸 놓쳤습니다.
카드에 이미 마감이 있으니 그걸 이었습니다. 실제로 발송까지 확인했습니다.
넣음 → 1분 안에 크론이 집음 → 발송됨 → 인앱 알림 생성됨
그 과정에서 마감 날짜가 계속 한 주씩 당겨지는 걸 발견했습니다. "다음 주 목요일"을 이번 주로 잡는 식인데, 프롬프트를 아무리 고쳐도 세 번 중 두 번 틀렸습니다. 날짜 계산을 LLM에서 아예 뺐습니다 — LLM은 들은 것만 말하고(다음 주 · 목요일 · 10시) 날짜로 옮기는 건 코드가 합니다.
실측: 다음 주 목 → 9/3(목) 10:00 · 이번 주 금 → 8/28(금) 09:00 · 9월 10일 → 9/10(목) 14:00. 셋 다 정확합니다.
같은 데이터를 담은 표가 두 개 있었습니다.
그런데 앱의 Memory Hub 화면이 멈춘 쪽을 읽고 있었습니다. 즉 형이 화면에서 보는 "크루가 나에 대해 아는 것"이 7개월 전에 멈춰 있었고, 에러는 안 났습니다.
이 서비스가 파는 게 "설명을 반복 안 해도 되는 것"인데 그걸 확인하고 지울 수 있는 유일한 창구가 옛것을 보고 있으면 안 됩니다.
내용이 완전히 같은 사본인 걸 확인하고(차이 0건) 백업을 뜬 뒤 하나로 합쳤습니다. 화면이 부르던 조회 함수는 아예 없어서 새로 만들었습니다. 지금 183건을 정상으로 돌려줍니다.
말씀대로 지우지 않고 막았습니다. 되살릴 때 재료가 남습니다.
커스텀 크루 판매 — 사용자가 자기 크루를 만들어 남에게 파는 UGC 마켓입니다. 5단계 마법사 끝이 결제이고, 사진 올릴 저장소가 아직 없습니다. 오픈 전이라 살 사람도 팔 사람도 없어서 내렸습니다.
크루를 고르고 영입하는 경험은 그대로입니다. 그건 다른 화면이고 하단 탭에 살아 있습니다 — 크루 211명 목록·카테고리·추천·검색·상세. 어제 만든 8명도 여기 뜹니다.
문서 업로드 — 사용자가 PDF를 올려 크루에게 먹이는 기능입니다. 저장소도 없고 올린 문서를 크루가 읽는 코드도 없습니다(파싱·임베딩 미구현). 지금 그 자리는 우리가 넣은 자료 1,465건이 대신하고 있습니다.
| 한 일 | 상태 |
|---|---|
| 놀던 자료 8세트에 배역을 붙임 — 크루 8명 신설 | 자료 1,465건, 질문마다 4건씩 실제 인용 |
| 카드 — 다시 찾을 것만 남는다 | 앱 렌더 + 서버 발행 + 마감→리마인더 |
| 다자방 — 각자 자기 자리만 | 종합 없앰, 남의 영역은 넘김 |
| 말풍선 — 70~120자씩 2~3개 | 카톡 모양 |
| 닉네임을 이름 자리에서 걷어냄 | 211명 중 55종만 있던 닉네임이 이름을 덮고 있었음 |
| 죽은 배선 정리 | 없는 함수 6개를 부르던 코드, 기능 3개, 파일 30개 |
① 아바타 — 새로 만든 크루 8명은 이미지가 없어 첫 글자만 뜹니다. 기존 211명 중에도 100명만 있습니다. 말씀대로 크루 정리하실 때 같이 하면 됩니다.
② 로그인·키 — 개발 우회는 지시대로 그대로 뒀습니다. 키 교체는 오픈 직전이 맞습니다.
③ 응답 속도 7.5~15초 — 줄이려면 모델을 바꾸거나 스트리밍(글자가 흘러나오게)을 붙여야 합니다. 지금은 다 만들어진 뒤 한 번에 뜹니다. 붙일지 말지는 형이 화면을 보시고 정하는 게 맞다고 봅니다.
④ 커스텀 크루 / 문서 업로드 — 막아만 뒀습니다. 아예 지울지, 오픈 뒤 되살릴지 정해주시면 됩니다.