docs: 고객사 첫 배포 기록 — stage-2, 배포 트러블슈팅, FabriX 모델 속도 실측, 오늘 order

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
lee-hyeon-cheol
2026-09-17 16:34:59 +09:00
co-authored by Claude Fable 5.1
parent 435952f25c
commit 2b8c2d7742
5 changed files with 114 additions and 0 deletions
+19
View File
@@ -0,0 +1,19 @@
# 2026-09-17
진행 중 feature: **`specs/006-opencode-django-backend/`** — stage-2 까지. 고객사 -12 에 배포됨.
## 오늘 한 것
- [x] 로컬 실행 환경(OpenRouter) 구성, 실제 LLM 스트림 확인
- [x] UX — 버튼 커서, 가운데 스피너, 스니펫→챗 버튼, 스니펫 창 높이
- [x] 캡쳐 — 활성 창 통째 캡쳐, 캡쳐 후 창 앞으로, 목적지 새/마지막 대화, 드래그 번쩍임(복사본에서 이식)
- [x] 단축키 Ctrl+Alt+Q/W/A/S/Z/X (Eclipse·SAP GUI 목록 대조)
- [x] FabriX 게이트웨이 `apps/gateway` + 고객사 배포 + 설치본 빌드
- [x] 모델 3종 속도 실측
## 다음
- [ ] 이미지 있을 때만 Gemma4(605), 아니면 339 — 게이트웨이 자동 분기
- [ ] 고객사에서 캡쳐→vision 수동 확인
- [ ] 고객사 서버 자동 기동 스크립트
- [ ] `.gitattributes` 로 줄바꿈 통일 (prettier 가 CRLF 167개 파일 뒤집던 것)
+12
View File
@@ -0,0 +1,12 @@
# FabriX 모델 성능 실측 (고객사 -12, 2026-09-17)
같은 질문("Explain ABAP LOOP AT in 3 sentences.") 스트림, CodeAssist 게이트웨이 우회해서 FabriX 직접 호출.
| id | 모델 | 첫 토큰 | 전체 | 청크 |
|---|---|---|---|---|
| 605 | Gemma4 | 1.8s | 33.9s | 304 |
| 339 | GaussO Flash | 0.2s | 1.9s | 149 |
| 581 | GaussO Think | 0.5s | 8.0s | 158 |
- 세 모델 다 같은 client key 로 열려 있음. 토큰은 `Bearer ` 접두 필수(날것은 401), 클라이언트 헤더는 `x-generative-ai-client`·`x-fabrix-client` 둘 다 됨.
- Gemma4 는 토큰당 속도가 눈에 띄게 느림 → 텍스트 기본은 339, 이미지 있을 때만 605 로 보내는 게 맞음.
@@ -0,0 +1,35 @@
# 고객사 첫 배포에서 걸린 것들 (2026-09-17, -12 컨테이너)
한 번에 안 되고 순서대로 다섯 군데 걸림. 다음에 다른 컨테이너 갈 때 그대로 밟을 것.
| 증상 | 원인 | 조치 |
|---|---|---|
| `pip install` 실패 — pytest 없음 | 컨테이너 인터넷 없음. -13 의 offline wheels 에 테스트 패키지는 없음 | `grep -v pytest requirements.txt > req-run.txt` 로 설치 |
| OpenCode "cannot connect to API" | `render_opencode.py` 기본 `BACKEND_PORT=8001` 인데 Django 를 8080 에 띄움 | `.env``BACKEND_PORT=8080` 넣고 다시 렌더 |
| Django `UnicodeEncodeError: 'ascii'` | 컨테이너 로케일 ASCII | `PYTHONUTF8=1` 붙여서 uvicorn 기동 (ABAP_OPENCODE run.sh 도 같음) |
| FabriX 호출 시 httpx `_normalize_header_key` 에서 UnicodeEncodeError | `.env.example` 줄 끝 한글 주석을 파서가 값으로 읽어 HTTP 헤더에 실림 | 파서에서 ` #` 뒤 제거(`config/settings.py`), `.env.example` 주석 삭제 |
| FabriX 전부 401 | `.env` 에 붙여넣은 토큰 앞에 `'` 하나가 딸려 들어감(짝 안 맞아 파서가 못 뗌) + 토큰은 `Bearer ` 접두 필수 | 따옴표 sed 로 제거, `AAF_FABRIX_TOKEN_PREFIX=bearer` |
| 설치 exe 메일 반입 시 잘림(3,148KB→2,699KB) | 메일 시스템이 exe 를 자름. 압축·이름변경 무관 | msi 를 4조각 `.txt` 로 쪼개 보내고 `copy /b` 로 합침, MD5 대조 |
## 배포 절차 (정리본)
```bash
# PC: -13 부품 꺼내서 -12 로
scp -P 8916 -r root@10.196.81.34:/www/abap-ito/offline/wheels ./wheels
scp -P 8916 root@10.196.81.34:/www/abap-ito/bin/opencode ./opencode-bin
scp -P 8912 -r ABAP_CODE_ASSISTANT wheels opencode-bin root@10.196.81.34:/www/
# -12
cd /www/ABAP_CODE_ASSISTANT && python3 _*.py # 메일 zip 이면 이름 복원
cd 5_django_backend && python3 -m venv .venv
grep -v pytest requirements.txt > req-run.txt
.venv/bin/pip install --no-index --find-links /www/wheels -r req-run.txt
cp .env.example .env && vi .env # AAF_FABRIX_* 4개, BACKEND_PORT=8080. 따옴표·주석 없이
.venv/bin/python manage.py migrate
.venv/bin/python opencode/render_opencode.py
chmod +x /www/opencode-bin; mkdir -p logs
(cd opencode && nohup /www/opencode-bin serve --hostname 127.0.0.1 --port 4096 > ../logs/opencode.log 2>&1 &)
PYTHONUTF8=1 nohup .venv/bin/uvicorn config.asgi:application --host 0.0.0.0 --port 8080 > logs/django.log 2>&1 &
curl -s http://127.0.0.1:8080/api/ito/models
```
포트: -12 안 8080 → 바깥 8914. 앱은 `http://10.196.81.34:8914/api/v1` 로 빌드됨.
@@ -0,0 +1,24 @@
# stage-2 — 사내 LLM(FabriX) 게이트웨이 + 고객사 첫 배포 (2026-09-17)
## 한 일
- `5_django_backend/apps/gateway/` 신설 — OpenCode 가 OpenAI 호환으로 `/api/ito` 에 붙으면 FabriX 로 통과 중계. ABAP_OPENCODE `apps_ito` 를 통째 복사하지 않고 필요한 규칙만 200줄로(헤더 3종 인증, `x-llm-model-id` 로 모델 선택, 401 시 Bearer/날것×클라이언트 헤더 조합 재시도, 모델 허용 목록).
- `opencode/opencode.fabrix.json.tmpl` + `render_opencode.py``.env` 의 AAF_* 로 OpenCode 설정 렌더. 개발용 OpenRouter 설정은 git 에 그대로.
- `.env.example` 에 AAF_* 블록. 기본 모델 605 Gemma4, 목록 605/339/581, `TOKEN_PREFIX=bearer`.
- `.env` 파서가 줄 끝 `#` 주석을 값으로 읽던 것 수정(고객사에서 한글 주석이 HTTP 헤더에 실려 httpx 가 죽음).
- 고객사 -12 컨테이너에 배포 완료(인터넷 없음 → -13 의 wheels·opencode 바이너리 재활용). Django :8080(바깥 8914), OpenCode :4096.
- 고객사용 Tauri 설치본(exe/msi) 빌드 — `2_frontend/.env.production``VITE_API_BASE_URL=http://10.196.81.34:8914/api/v1`. 메일 반입은 exe 가 잘려서 msi 4조각 `.txt` + `copy /b` 로 합침.
- FabriX 실측: 세 모델 다 같은 키로 200. 토큰은 Bearer 필수. 속도는 `docs/tech/fabrix-model-perf.md`.
## 검증
- `tests/test_gateway.py` 9개(상류 MockTransport) 통과. 백엔드 전체 40/41 — 실패 1개(`test_sessions` 정렬)는 이전부터.
- 고객사 앱에서 로그인·텍스트 채팅 답변 확인(605).
## 남은 것 / 다음
- [ ] 이미지 있을 때만 605, 텍스트는 339 로 자동 분기(게이트웨이에서 body 의 `image_url` 보고). Gemma 가 느려서.
- [ ] 캡쳐→vision 응답 고객사에서 수동 확인.
- [ ] 고객사 서버 자동 기동(지금은 nohup 손기동). ABAP_OPENCODE bare/run.sh 식 스크립트.
- [ ] 스트림 모드에서 첫 시도 401 → 재시도 흐름이 "생각 중" 으로 멈추는 듯한 현상 — `TOKEN_PREFIX=bearer` 로 우회 중. 원인 확인 필요.
- [ ] `test_sessions` 정렬 실패 원인.
+24
View File
@@ -0,0 +1,24 @@
# 작업로그 · 2026-09-17 (목)
| 시간 | 내용 |
|------|------|
| 09:36 | 로컬 실행 환경 구성 — Django venv+migrate, npm 설치, OpenCode/uvicorn 기동, health·로그인 확인 |
| 09:42 | OpenCode 에 OpenRouter 키 넣고 재기동, Django /chat/stream 으로 실제 LLM 답변 SSE 끝까지 확인(token→title→usage→done) |
| 09:47 | 버튼 hover 시 손가락 커서 안 나오던 거 — Tailwind v4 기본값 탓, globals.css 전역 한 줄로 해결 |
| 09:51 | 페이지 로딩 때 왼쪽 위 '로딩...' 글자 → 화면 정가운데 스피너(CenterSpinner) 로 교체, 로그인 확인 중에도 같은 거 씀 |
| 10:11 | Ctrl+Shift+9 를 맨 앞 창 통째 캡쳐로 바꿈(DWM 확장 프레임 경계로 좌표), 드래그 캡쳐는 Ctrl+Shift+0 으로 이동 |
| 10:16 | 전역 단축키를 왼손 한손용 Ctrl+Alt+Q/W/A/S 로 교체 — Ctrl+Shift+글자는 Eclipse 가 다 써서 피함 |
| 10:23 | 단축키 modifier 를 Ctrl+Alt → Alt+Shift 로 변경(Q/W/A/S 그대로) |
| 10:41 | 복사본(code-assistant-v2 멀티모달 추가)의 캡쳐 수정 4개를 repo 로 이식 — 캡쳐 후 창 앞으로(AttachThreadInput), 목적지 새 대화/마지막 대화 분기(Alt+Shift+Z/X 추가), 선택영역 원본 밝기, 드래그 번쩍임(더블버퍼) |
| 10:47 | 단축키 충돌 실제 확인 — Alt+Shift+A/S/W/Z/X/Q 전부 Eclipse 가 쓰고 있어서 Ctrl+Alt 로 되돌림(Eclipse·ADT·SAP GUI 목록 대조, 비어 있음 확인) |
| 10:52 | 스니펫 팔레트 검색줄 오른쪽에 '챗' 전환 버튼 추가(Ctrl+Alt+W 와 같은 동작) |
| 10:54 | 스니펫 검색 단계 창 높이 84→88 — 제목줄+검색줄 실제 높이보다 4px 작아서 오른쪽에 스크롤바 뜨던 것 |
| 10:58 | 고객사 반입용 소스 zip 생성 — git 추적 파일 기준 392개, 1.5MB (node_modules·target·.venv·DB 제외) |
| 11:08 | 사내 LLM(FabriX) 게이트웨이 apps/gateway 추가 — OpenCode→/api/ito→FabriX 통과 중계(헤더 인증·401 형식 재시도·모델 허용 목록), opencode.json FabriX 템플릿+렌더 스크립트, 테스트 9개 |
| 11:15 | FabriX 모델 목록에 Gemma4(605) 추가 — 339 GaussO Flash / 581 GaussO Think / 605 Gemma4, .env.example·README 기본값으로 |
| 11:18 | 메일 반입용 zip 따로 생성 — 네이버 차단 확장자 대응: .specify/·개인 메모 제외, eslint/postcss config .js 는 .txt 붙이고 _복원.py 동봉 |
| 14:34 | 고객사 -12 에 CodeAssist 백엔드 올림(wheels·opencode 는 -13 것 재활용). .env 줄 끝 한글 주석이 값으로 읽혀 FabriX 헤더에 실려 httpx 가 죽던 것 — 파서에서 주석 제거, .env.example 주석도 정리 |
| 15:13 | FabriX 기본 모델을 Gemma4(605) 로 — 이미지(vision) 채팅은 Gemma 만 돼서. 목록 순서도 605 먼저 |
| 15:20 | 고객사용 CodeAssist 설치본 빌드 — API 주소 10.196.81.34:8914 박아서 exe/msi, 메일용은 .txt 붙인 zip |
| 16:19 | 고객사 FabriX 실측 — 339/581/605 전부 200, 단 토큰은 Bearer 접두 필수(날것은 401). .env.example 기본 TOKEN_PREFIX=bearer 로. .env 값 앞 홑따옴표가 토큰에 섞여 401 나던 것도 잡음 |
| 16:24 | FabriX 모델 3종 속도 실측(605 33.9s / 339 1.9s / 581 8.0s) → docs/tech/fabrix-model-perf.md |