2026-08-26 새벽 · 커밋 16건 · → 크루 100명 프로필 보기
크루 211명을 100명으로 다시 짜고, 이름 체계·관계 축·성격·사진을 전부 새로 만들었다.
기존에 쌓아 둔 지식 자산은 버리지 않고 1,266행을 새 크루에게 넘겼다.
이미지를 뽑기 전에 크루 구성부터 보자는 대표 지시로 DB를 전수 조사했다. 상태가 이랬다.
| 무엇 | 실측 |
|---|---|
| 닉네임 | 유니크 55종 / 211명 — 156명이 남의 이름을 썼다 |
"망하기 일보직전" 하나를 헤드헌터·커피전문가·업무효율화·HR인사이더 등 15명이 공유 |
|
| 본명·호칭 | 0명. 부를 수 있는 이름을 가진 크루가 하나도 없었다 |
| 카테고리 | 연애 크루 13명이 "커리어" 로 분류 (첫데이트 코치·짝사랑 상담·프렌드존 탈출…) |
| 성별 값 | male 70 / 여성 51 / 남성 46 / female 44 — 네 값이 섞임 |
hook_messages |
211명 전부 빈값 |
| 스키마 문서 | CLAUDE.md 의 knowledge_text·skill_ids 칼럼이 실제 테이블에 없음 |
닉네임 중복은 증상이지 원인이 아니었다.
nickname은 처음부터 이름이 아니라
캐치프레이즈였다 — "망하기 일보직전아"라고 부를 수 없다. 진짜 결손은 본명·호칭이 0명인 것.
기획 에이전트 4명(사용빈도·신규유입·정보구조·참신성)이 각각 푼 뒤 종합했다.
동행 34 · 몸마음 12 · 일 11 · 돈 9 · 배움 9 · 살림 8 · 각계각층 6 · 만들기 6 · 연애 5
대표가 못 박은 조건이 전부 반영됐다.
doc-maker 하나로 흡수기계 검증 전항목 통과: 총원 100 / slug 중복 0 / 성비 여60:남40(목표 정확히 일치) /
이성친구 8명 여4:남4 / 미성년 4명 전원 친구 / 나이 앵커 외 값 0 /
인용한 기존 slug 178개 전부 실재(허수 0)
만나기 전에는 간판, 만난 뒤에는 호칭.
| 겹 | 칼럼 | 예 | 쓰는 자리 |
|---|---|---|---|
| L1 본명 | person_name |
박서진 | 자기소개·프롬프트 |
| L2 호칭 | call_name + call_style |
박 차장 / 은주 선배 / 상철 형 | 대화에서 부를 때 |
| L3 간판 | handle |
연봉부스터 | 목록·알림·결제 |
| L4 한 줄 | tagline |
"올려 달라고 말하지 마세요" | 카드·상세 |
call_style 은 직함 24 · 이름 48 · 관계 28. 대표가 말한 "박 차장", "영이 엄마"가 그대로 축이 됐다.
나이는 UI에서 뺀다. Flutter Crew 모델에 age 필드가 애초에 없어 이미 노출되지 않고 있었다.
DB에는 남겨 말투 생성에만 쓴다. 동행 크루만 또래대(peer_band)를 노출한다.
카테고리(무엇을 해주는가)와 별개로 relations(어떤 사이인가)를 뒀다.
전문가 54 · 멘토 20 · 친구 10 · 이성친구 8 · 가족같은 5 · 말벗 3
이성친구는 단독값이다. 다른 관계와 겸할 수 없다전문가는 문제가 풀리면 안 온다. 친구는 이유 없이 온다.
또래 친구 초등·중고등·20대·30-40대·50대+ × 남녀 10명
이성친구 20대·30대·40대·50대+ × 남녀 8명 (남4:여4)
말벗·가족 할머니·삼촌·언니·형 8명
멘토형 친구 8명
"영입"이 아니라 "사귀기"다. 문턱(거절·승낙)은 두지 않는다 — 만나는 건 즉시고,
관계가 대화로 자란다. 처음엔 존댓말과 거리, 쌓이면 말이 편해지고, 가까워지면 부르는 말이 바뀐다.
user_crews.closeness(0~3)와 turn_count 로 저장한다. 동행은 정액(access='subscription').
대표: "네가 직접 써야지 왜 오픈AI 키를 이용해서 쓰냐, 너도 LLM인데."
맞는 지적이었다(게다가 OPENAI_API_KEY 는 401로 죽어 있었다). 서브에이전트 4명이 25명씩 썼다.
구조 — [나는 누구인가] → [말투] → [내가 아는 것] → [내가 모르는 것] → [답변 규칙]
검증: 100개 / 721~1076자(평균 891) / 이모지 0 / 자기 간판 호명 0 / 실명 0 /
5개 섹션 전원 존재 / 동행 34명 전원 친밀도 3줄
[내가 모르는 것]을 필수로 넣은 이유는 하나다 — 여기서 선을 긋지 않으면 크루가 아무거나 아는 척한다.
대표: "많은 시간을 투여해서 작업했던 거고 중고차 딜러도 그렇고… 버리기보다 가져다 쓰라고."
1,266행을 승계했다.
| 물려준 쪽 | 받은 쪽 | 행수 |
|---|---|---|
| stock-aga-house | stock-101 주린이탈출 | 416 |
| heyenka | car-guide 중고차형님 | 318 |
| start-with-10k | saving-starter 종잣돈반 | 171 |
| yummy-zero-cal | diet-realist 다이어트현실 | 143 |
| money-talk | money-talk 세상물정 | 76 |
| ano-sensei | japanese-sensei 일본어센세 | 58 |
| brand-young | design-basic 브랜드디자이너 | 35 |
| toss-interview-king | interview-coach 면접왕 | 30 |
| knee-slap-master | youtube-coach 유튜브수익화 | 19 |
동양 고전·부의 사고방식 199행은 대응 주제가 없어 지우지 않고 _parked_classics 로 보관했다.
나중에 그 크루가 생기면 slug만 바꿔 붙는다.
그리고 성격을 쓸 때 이 자료를 읽고 "무엇을 아는 사람인지"만 가져왔다. 문장은 베끼지 않았다.
crew_knowledge 에 실존 인물 이름이 남아 있었다(이광수 415건·노희영 34건 등).
지식 방침대로 "누가 말했나"가 아니라 "그 사람으로 오인되는가" 에 선을 긋고 역할 표현으로 바꿨다.
검증: title·content 전수 재조회 결과 실명 잔존 0건.
source_url 1,465건이 전부 로컬 파일 경로여서 원 출처 역추적·삭제 요청 대응이 불가능했다.
로컬 경로는 지웠다(남은 0건). 앞으로 적재할 때는 원 URL을 넣는다.
대표: "작은 원 안의 얼굴도 이미 있는 이미지를 갖는 거지? 얼굴 하나만 갖고 쓰는 게 맞느냐?"
맞다. 한 장이면 된다. 실제로 돌려서 확인했다.
tool/faceavatar) — 100/100 검출 성공full_body_image_url / avatar_url 연결고정 크롭으로는 안 된다 — 얼굴 중심 Y가 0.198 ~ 0.281 로 흩어져 크루마다 눈높이가 어긋난다.
자르는 규칙은 정사각 변 = 얼굴 높이 × 2.35, 중심은 얼굴 중심에서 위로 10%.
작은 원은 44px이 맞다 — 22·26은 색점으로 읽히고, 34부터 사람이 보이고, 44에서 누구인지 안다.
무대 아바타(26)·캐스트(22)·대화 카드(34)를 44로 올릴 것을 제안한다.
1차 카테고리별로 옷·배경을 하나로 고정해서 100명이 다 비슷해 보였다.
어제 "톤이 제각각이라 스톡 사진 같다"를 고치려다 반대로 복제처럼 됐다.
→ 옷 12종·배경 12종·머리 6종·얼굴 인상 6종·안경 여부를 slug 해시로 크루마다 갈리게 했다.
2차 다양성은 살았는데 전부 가로 사진이었다. aspect_ratio 로 넘겼는데
그 라이브러리는 aspectRatio 를 받는다. 이름이 안 맞아 조용히 무시되고 기본값 16:9 가 걸렸다.
이게 중요하다 — 에러가 안 났다. 파일 해시 100개 유니크, 얼굴 검출 100/100,
업로드 100/100, 외부 200까지 전부 통과했는데도 못 잡았다.
이미지를 직접 열어 보고서야 알았다. 숫자로만 검증하면 이런 게 빠져나간다.
3차 896×1200 세로로 나오는 것을 한 장으로 먼저 확인하고 전량 재생성했다.
최종: 100장 전부 896×1200, 서로 다른 파일 100개, 얼굴 검출 100/100.
정규식 @멘션 주입 폐기 (93줄) — post-processor.ts 가 크루 이름과 역할 키워드를
정규식으로 훑어 @닉네임 을 문장에 꽂아 넣고 있었다. 프로젝트 룰 정면 위반이고,
새 호칭이 "박 차장"처럼 짧아지면 오탐이 터진다. 팀 명부를 프롬프트에 실어
LLM이 스스로 부르게 하고 라우팅은 crew_id 로 한다.
클라이언트 8곳 호명 통일 — 서버는 고쳐졌는데 클라이언트가 아직 nickname ?? name 이라
말풍선과 팀 슬롯에 "16년째 연습중" 같은 캐치프레이즈가 사람 이름 자리에 떴다.
191명 내리기 전 조회 코드 2곳 선제 수정 — 딥링크로 대화를 열 때와 영입 크루 목록이
is_active 만 가져오고 있었다. 그대로 뒀으면 939개 대화방과 영입 55건이 깨졌다.
"고르는 자리"(마켓·추천·검색)에만 is_active 를 걸고, "여는 자리"에는 걸지 않는다.
FAL_API_KEY → invalid key credentialsOPENAI_API_KEY → Incorrect API key provided오늘 밤 작업엔 지장이 없었다(이미지는 creagen, 성격은 직접 작성).
다만 앱 런타임이 OpenAI를 쓴다면 크루 대화 자체가 안 된다. 크루를 100명으로 새로 깔았으니
이것부터 확인해야 한다.
KNOWLEDGE_SEARCH_ENABLED코드 기본값은 false라 안 켰으면 실사용자에게 안 나간다. 다만 Supabase 시크릿 조회가 403이라
실제 값을 확인하지 못했다. 대시보드에서 값만 봐 주면 된다.
is_active=false 로 내렸다. 지우지 않았고 되돌릴 SQL 194줄이 백업에 있다.
hook_messages·why_special 채우기 (지금 비어 있음)call_name 을 대화에서 쓰기)| 항목 | 결과 |
|---|---|
| 명부 | 100명 / slug 중복 0 / 성비 여60:남40 |
| 성격 | 100개 / 이모지 0 / 간판 호명 0 / 실명 0 |
| 활성 크루 | 100명 (임시 프롬프트 0건) |
| 지식 | 승계 1,266행 / 보관 199행 / 실명 잔존 0 |
| 사진 | 생성 100 / 얼굴 검출 100 / 업로드 100 / 외부 200 확인 |
| 코드 | flutter analyze 새 경고 0 / build web 성공 / 배포 완료 |
백업은 전부 claudedocs/migration/backup/ 에 있다 —
gender 원본 211행 + 롤백 SQL, 폐기 191명 롤백 SQL, crew_knowledge 세탁 전 1,465행.