Add and update DOCS research records
This commit is contained in:
parent
b9d9b1fd27
commit
274812aef3
@ -1,80 +1,6 @@
|
||||
# 이중 NAS 에이전트 파일 스토리지 구조 아이디어
|
||||
# 260307_이중_NAS_에이전트_파일_스토리지_구조_아이디어
|
||||
|
||||
tags: [nas, agent, storage, sync, architecture]
|
||||
이 문서는 인프라 기준 문서로 이관되었습니다.
|
||||
|
||||
## 목적
|
||||
- 외부 NAS의 파일을 내부 NAS로 이중 저장 또는 동기화한다.
|
||||
- 에이전트는 외부 NAS를 직접 읽지 않고, 내부 NAS만 읽는다.
|
||||
- NAS는 연산 서버가 아니라 파일 스토리지로만 사용한다.
|
||||
|
||||
## 기본 구조
|
||||
외부 NAS(public)
|
||||
-> 동기화
|
||||
-> 내부 NAS(LAN)
|
||||
-> 네트워크 마운트
|
||||
-> 에이전트 서버
|
||||
|
||||
핵심 원칙:
|
||||
- 외부 NAS: 외부 수집/저장
|
||||
- 내부 NAS: 에이전트용 파일 저장소
|
||||
- 에이전트 서버: 연산/파싱/AI 처리
|
||||
|
||||
## 왜 이 구조인가
|
||||
- 외부 NAS를 에이전트가 직접 읽게 하면 보안과 연결 안정성이 약해진다.
|
||||
- 내부 NAS만 읽게 하면 에이전트는 내부망 기준 단순 파일 처리로 끝난다.
|
||||
- NAS가 느려도 파일 스토리지 역할에는 적합하다.
|
||||
|
||||
## 권장 동기화 방식
|
||||
### 1. Synology Drive ShareSync
|
||||
- 외부 NAS -> 내부 NAS 단방향 동기화
|
||||
- 장점: 설정이 쉽고 Synology 간 궁합이 좋다.
|
||||
- 용도: 거의 실시간 파일 복제
|
||||
|
||||
### 2. rsync
|
||||
- 외부 NAS -> 내부 NAS 주기 동기화
|
||||
- 장점: 단순하고 서버 관점에서 제어가 쉽다.
|
||||
- 용도: 5분/10분 주기 파일 동기화
|
||||
|
||||
### 3. Hyper Backup
|
||||
- 외부 NAS -> 내부 NAS 백업
|
||||
- 장점: 복구용으로 강하다.
|
||||
- 단점: 실시간 동기화 용도에는 덜 적합하다.
|
||||
|
||||
## 내부 NAS를 에이전트가 읽는 방식
|
||||
- 내부 NAS를 NFS 또는 CIFS로 에이전트 서버에 마운트한다.
|
||||
- 에이전트는 `/mnt/agent` 같은 단일 경로만 읽는다.
|
||||
|
||||
권장 예시:
|
||||
- `/mnt/agent/raw`
|
||||
- `/mnt/agent/crawl`
|
||||
- `/mnt/agent/output`
|
||||
- `/mnt/agent/logs`
|
||||
|
||||
## NAS에 둘 것
|
||||
- PDF, CSV, JSON, HTML, 이미지 같은 원본 파일
|
||||
- 크롤링 결과물
|
||||
- 장기 로그
|
||||
- 에이전트 산출물
|
||||
|
||||
## NAS에 두지 말 것
|
||||
- 벡터 DB
|
||||
- SQLite 실시간 쓰기 경로
|
||||
- 캐시
|
||||
- 모델 로딩 경로
|
||||
- 고빈도 랜덤 I/O가 필요한 런타임 데이터
|
||||
|
||||
## 현재 기준 가능 여부
|
||||
### 가능한 부분
|
||||
- 내부 NAS(192.168.0.101)는 현재 51123에서 실마운트 가능하다.
|
||||
- Gitea LFS도 NAS 저장소로 실제 동작 검증이 끝났다.
|
||||
- 따라서 내부 NAS를 에이전트 파일 스토리지로 쓰는 것은 가능하다.
|
||||
|
||||
### 아직 필요한 부분
|
||||
- 외부 NAS(`sigongipc.synology.me:5000`)에 대한 실제 동기화 경로는 아직 미구현이다.
|
||||
- 외부 NAS -> 내부 NAS 동기화 방식(Drive ShareSync / rsync / Hyper Backup) 중 하나를 고정해야 한다.
|
||||
- 내부 NAS 공유 폴더를 에이전트 전용 경로로 분리해야 한다.
|
||||
|
||||
## 현재 판단
|
||||
- 이 구조는 가능하다.
|
||||
- 다만 지금 당장 완성된 것은 아니고, 핵심 선행조건은 `외부 NAS -> 내부 NAS 단방향 동기화 확정`과 `내부 NAS의 에이전트 전용 공유폴더 설계`다.
|
||||
- 연산은 미니서버, 저장은 NAS로 분리하는 방향이 맞다.
|
||||
- 새 위치: <https://git.ro-being.com/ivada-infra/DOCS/src/branch/main/journey/ideas/260307_external_nas_companyx_sync_%EC%95%84%EC%9D%B4%EB%94%94%EC%96%B4.md>
|
||||
- 이유: 외부 NAS -> 내부 NAS 동기화, 내부 NAS 마운트, 저장 경로 분리 문제는 `robeing` 기능 문서보다 `infra` 운영 문서로 관리하는 것이 SSOT에 맞습니다.
|
||||
|
||||
@ -0,0 +1,101 @@
|
||||
# 260310 콜드메일 `skill-rag-file` 500 및 실패은닉 원인확정 리서치
|
||||
|
||||
tags: [coldmail, skill-rag-file, rb8001, scheduler, postgres, research]
|
||||
|
||||
**날짜**: 2026-03-10
|
||||
**작성자**: Codex
|
||||
**관련 파일**: `rb8001/app/services/coldmail_processor.py`, `rb8001/app/services/workflows/coldmail_workflow.py`, `rb8001/app/scheduler/jobs/coldmail_briefing.py`, `skill-rag-file/app/api/upload.py`, `skill-rag-file/.env`
|
||||
**상위 원칙**: [전역 원칙](../../../../0_VALUE/00_Principles/global-principles.md), [문서 작성 원칙](../../book/300_architecture/312_writing-principles.md), [Backend Coding Principles](../../book/300_architecture/311_backend_coding_principles.md)
|
||||
|
||||
## 관련 문서
|
||||
- [콜드메일 `skill-rag-file` 500과 실패가시성 복구](../troubleshooting/260310_coldmail_skill_rag_file_500_stale_db_host_및_실패가시성_복구.md)
|
||||
- [9시 네이버 이메일 분석 미전송과 실패 은닉 해결](../troubleshooting/260309_9시_네이버이메일분석_미전송_실패은닉_해결.md)
|
||||
- [51123 임시복구 서비스 연속성 조치내역](../../../../infra/DOCS/journey/troubleshooting/260304_51123_임시복구_서비스연속성_조치내역.md)
|
||||
|
||||
---
|
||||
|
||||
## 1. 목적
|
||||
- `2026-03-10 09:05` KST 콜드메일 프로세스가 "안 돈 것처럼 보인 이유"를 로그, 코드, 런타임 설정 기준으로 단일 원인까지 확정한다.
|
||||
- `skill-rag-file` 업로드 `500 Internal Server Error`의 직접 원인을 확정한다.
|
||||
- 실패은닉이 어떤 코드 경로에서 발생했는지 분리한다.
|
||||
|
||||
## 2. 범위 / 비범위
|
||||
- 범위: `rb8001`, `skill-rag-file`, PostgreSQL 연결 경로, `2026-03-10 09:05` 실행 구간
|
||||
- 비범위: 콜드메일 후보 선정 로직 자체의 품질, 다른 스케줄러 잡, 다른 프로젝트
|
||||
|
||||
## 3. 사실(Facts)
|
||||
### 3-1. 09:05 작업은 실제 실행됐다
|
||||
- `rb8001` 로그에 `2026-03-10 09:05:00` `Running job: Coldmail Daily Briefing`이 기록됐다.
|
||||
- 같은 실행에서 콜드메일 후보 3건이 선택됐고, 각 후보 처리 중 첨부 PDF 업로드 단계가 실패했다.
|
||||
- 최종 로그는 `Coldmail briefing completed: 0 emails processed`로 닫혔다.
|
||||
- 같은 프로세스에서 뒤이은 다른 잡은 계속 실행됐고, APScheduler는 작업을 `executed successfully`로 기록했다.
|
||||
|
||||
### 3-2. 직접 실패 지점은 `skill-rag-file` 업로드였다
|
||||
- `skill-rag-file` 컨테이너 로그의 같은 시각대에 `POST /api/upload HTTP/1.1" 500 Internal Server Error`가 반복 기록됐다.
|
||||
- 스택트레이스는 `/app/app/api/upload.py` 내부 `await db.execute(...)` 경로에서 끝났고, 최종 예외는 `TimeoutError`였다.
|
||||
- 이 시점 업로드 실패는 콜드메일 후보 수집 이후, 첨부파일 문서화 단계에서 발생했다.
|
||||
|
||||
### 3-3. `skill-rag-file`의 데이터베이스 주소는 stale 값이었다
|
||||
- 컨테이너 환경변수에서 `DATABASE_URL=postgresql://robeings:robeings@192.168.219.45:5432/main_db`가 확인됐다.
|
||||
- 현재 호스트 IP는 `192.168.0.100`, `172.17.0.1` 등으로 확인됐고 `192.168.219.45`는 현재 서버 유효 주소가 아니었다.
|
||||
- 호스트에서 `192.168.219.45:5432` 연결은 timeout이 발생했다.
|
||||
- 반대로 컨테이너 내부에서 `127.0.0.1:5432`와 `172.17.0.1:5432` 연결은 성공했다.
|
||||
|
||||
### 3-4. stale 값의 근거는 로컬 오버라이드 `.env`였다
|
||||
- `skill-rag-file/.env`에 `DATABASE_URL=postgresql://robeings:robeings@192.168.219.45:5432/main_db`가 남아 있었다.
|
||||
- `2026-03-04` 임시복구 문서에는 `192.168.219.45` 임시 IP 경로를 사용한 조치가 남아 있다.
|
||||
- 따라서 현재 서비스는 SSOT 런타임 환경이 아니라 과거 임시 오버라이드 값을 우선 사용하고 있었다.
|
||||
|
||||
### 3-5. 실패은닉은 `rb8001` 상위 흐름에서 발생했다
|
||||
- `rb8001/app/services/coldmail_processor.py`는 첨부 처리 실패를 `None` 반환으로 닫는 경로가 있었다.
|
||||
- `rb8001/app/services/workflows/coldmail_workflow.py`는 `None` 결과를 "처리 안 된 후보"로만 누락시켰다.
|
||||
- `rb8001/app/scheduler/jobs/coldmail_briefing.py`는 워크플로우 예외가 없으면 성공 종료로 기록했다.
|
||||
- 그래서 하위 업로드 실패가 있어도 스케줄러는 성공처럼 보였다.
|
||||
|
||||
### 3-6. 수정 후 검증 결과
|
||||
- `skill-rag-file/.env`의 DB 호스트를 `172.17.0.1`로 교정한 뒤 실제 팀 ID `38bdc27d-cb01-4960-867e-41733d2f3529` 업로드는 `200` 응답으로 성공했다.
|
||||
- 잘못된 팀 ID는 추가 검증에서 `404 Team not found`로 반환되도록 정리했다.
|
||||
- `rb8001`은 처리 실패를 `processing_failures`로 수집하고, 하나라도 있으면 스케줄러 레벨에서 예외를 올리도록 바꿨다.
|
||||
|
||||
## 4. 배제된 가설
|
||||
- "09:05 스케줄러가 아예 돌지 않았다": 거짓. 시작 로그와 내부 처리 로그가 존재한다.
|
||||
- "Neo4j unavailable 경고가 직접 원인이다": 거짓. 경고는 있었지만 콜드메일 흐름은 첨부 업로드 단계까지 진행됐다.
|
||||
- "첨부 PDF 자체가 손상돼서 실패했다": 직접 원인 아님. 동일 시점 `skill-rag-file` 로그의 실제 예외는 DB timeout이었다.
|
||||
- "운영 DB 자체가 완전히 죽어 있었다": 거짓. 올바른 호스트 경로로는 연결 가능했고, 수정 후 업로드가 성공했다.
|
||||
|
||||
## 5. 해석(Interpretation)
|
||||
### 5-1. 09:05 운영 실패의 직접 원인
|
||||
- 직접 원인은 `skill-rag-file`이 오래된 DB 호스트 `192.168.219.45`를 사용한 것이다.
|
||||
- 이 값 때문에 첨부 저장용 DB insert가 timeout으로 실패했고, 콜드메일 후보 3건 모두 문서화에 실패했다.
|
||||
|
||||
### 5-2. 사용자가 "안 돌았다"고 체감한 이유
|
||||
- 실제 작업은 실행됐지만 핵심 산출물 생성에 모두 실패했다.
|
||||
- 동시에 상위 잡이 실패를 예외로 승격하지 않아 스케줄러 성공 로그만 남았기 때문에, 운영 관측상 "안 돌았다"로 보이게 됐다.
|
||||
|
||||
### 5-3. 왜 `500`이 문제였는가
|
||||
- 원래 원인은 DB 연결 timeout이므로 일반 `500`보다 구체적인 비가용성 오류로 분리되어야 한다.
|
||||
- 또 팀 미존재 같은 입력/무결성 오류까지 `503`이나 `500`으로 뭉개면 원인성이 깨진다.
|
||||
- 따라서 "연결 불가 계열만 `503`", "존재하지 않는 팀은 `404`", "콜드메일 처리 실패는 스케줄러 실패"가 맞다.
|
||||
|
||||
## 6. 결론
|
||||
### 결론 A. 09:05 콜드메일은 실행됐지만 업무적으로 실패했다
|
||||
- 스케줄러 실행 성공과 업무 성공은 달랐다.
|
||||
- 운영 기준 최종 판정은 "실행은 됐고, 첨부 업로드 실패로 결과 생성에 실패"다.
|
||||
|
||||
### 결론 B. `skill-rag-file` 500의 단일 직접 원인은 stale DB 호스트다
|
||||
- `192.168.219.45`는 과거 임시복구 경로의 잔존값이었다.
|
||||
- 현재 정상 경로는 컨테이너에서 접근 가능한 `172.17.0.1:5432`다.
|
||||
|
||||
### 결론 C. 실패은닉의 단일 직접 원인은 `None` 기반 누락 처리다
|
||||
- 하위 실패가 예외 대신 빈 결과처럼 흡수되면서 APScheduler 성공 로그가 남았다.
|
||||
- 이 경로를 끊어야 운영 로그와 실제 결과가 일치한다.
|
||||
|
||||
## 7. 이 이슈를 닫는 기준
|
||||
- `skill-rag-file` 업로드가 실제 운영 팀 ID에서 `200`이어야 한다.
|
||||
- DB 연결 불가 계열만 `503`으로 남아야 한다.
|
||||
- 잘못된 팀 ID는 `404`여야 한다.
|
||||
- 첨부 업로드 실패가 다시 발생하면 `rb8001` 스케줄러 로그는 실패로 남아야 한다.
|
||||
|
||||
## 8. 남은 확인 포인트
|
||||
- 현재 로컬 셸의 `pytest`는 프로젝트 런타임 의존성 경로가 맞지 않아 바로 실행되지 않았다.
|
||||
- 따라서 이번 문서의 검증 근거는 컨테이너 재배포, 실제 업로드 응답 코드, 컨테이너 로그, `py_compile` 기준이다.
|
||||
@ -0,0 +1,202 @@
|
||||
---
|
||||
tags: [AI, Agent, Context-Engineering, DeepAgents, Claude-Code, MCP, Exa, Stitch, Robeing]
|
||||
date: 2026-03-13
|
||||
last_updated: 2026-03-13
|
||||
author: Codex
|
||||
---
|
||||
|
||||
# Context Engineering, DeepAgents, Claude Code 영상 리서치
|
||||
|
||||
상위 원칙:
|
||||
- [writing-principles](../../../book/300_architecture/312_writing-principles.md)
|
||||
|
||||
관련 문서:
|
||||
- [MCP & A2A 리서치 인덱스](../mcp_a2a/README.md)
|
||||
- [OpenClaw 공식 문서 요약](./260205_openclaw_official_docs_summary.md)
|
||||
- [LangGraph vs n8n 비교](./250925_langgraph_vs_n8n_comparison.md)
|
||||
|
||||
## 1. 개요
|
||||
|
||||
유튜브 영상 `[전현준 x 테디노트] Context Engineering 을 위한 DeepAgents 와 Agentic Coding(Claude Code)`를 기준으로, 로빙에 참고할 만한 도구와 개념을 정리합니다. 본 문서는 영상의 전체 자막을 직접 전사한 문서가 아니라, 영상 메타데이터와 사용자 제공 요약을 바탕으로 공식 1차 문서와 교차 검증한 리서치입니다.
|
||||
|
||||
핵심 질문은 세 가지입니다.
|
||||
|
||||
1. 영상에서 말하는 `Context Engineering`은 어떤 운영 원칙으로 해석하는 것이 안전한가
|
||||
2. `DeepAgents`, `Claude Code`, `MCP`, `Exa`, `Stitch`는 각각 무엇을 담당하는가
|
||||
3. 로빙 문서 체계와 아키텍처에서 이 내용을 어디까지 참고해야 하는가
|
||||
|
||||
## 2. Facts
|
||||
|
||||
### 2.1 영상 메타데이터
|
||||
|
||||
- 영상 제목: `[전현준 x 테디노트] #Context Engineering 을 위한 #DeepAgents 와 #Agentic Coding(Claude Code)`
|
||||
- 채널: `테디노트 TeddyNote`
|
||||
- 영상 URL: `https://www.youtube.com/watch?v=SKqCA-43nPM`
|
||||
- 페이지 메타 기준 게시 시각: `2026-01-21T18:49:46-08:00`
|
||||
- 한국 시간 기준으로는 `2026-01-22`
|
||||
- 확인 방법:
|
||||
- YouTube `oEmbed`
|
||||
- YouTube 페이지 `publishDate`, `uploadDate` 메타
|
||||
|
||||
### 2.2 Claude Code 관련 공식 사실
|
||||
|
||||
- Claude Code는 CLI 기반 코딩 에이전트 워크플로우를 제공한다.
|
||||
- 공식 문서에는 `hooks`, `sub-agents`, `MCP` 연동이 독립 기능으로 존재한다.
|
||||
- `hooks`는 특정 이벤트 전후에 명령이나 검증을 자동 실행하는 구조다.
|
||||
- `sub-agents`는 역할을 분리한 별도 에이전트를 선언해 작업을 위임하는 구조다.
|
||||
- `MCP`는 외부 도구와 컨텍스트 소스를 표준 방식으로 연결하는 인터페이스로 안내된다.
|
||||
|
||||
공식 출처:
|
||||
- https://docs.anthropic.com/en/docs/claude-code/hooks
|
||||
- https://docs.anthropic.com/en/docs/claude-code/sub-agents
|
||||
- https://docs.anthropic.com/en/docs/claude-code/mcp
|
||||
|
||||
### 2.3 DeepAgents 관련 공식 사실
|
||||
|
||||
- DeepAgents는 LangChain 측에서 소개하는 에이전트 하네스 성격의 프레임워크다.
|
||||
- 핵심 개념으로 `planning`, `subagents`, `files`, `stateful execution`이 제시된다.
|
||||
- 긴 작업을 한 번의 대화에 모두 밀어넣기보다, 계획과 파일 기반 상태를 분리해 유지하는 흐름을 강조한다.
|
||||
|
||||
공식 출처:
|
||||
- https://www.langchain.com/deep-agents
|
||||
- https://docs.langchain.com/oss/python/deepagents/overview
|
||||
- https://docs.langchain.com/oss/python/deepagents/subagents
|
||||
|
||||
### 2.4 MCP 관련 공식 사실
|
||||
|
||||
- MCP(Model Context Protocol)는 모델과 도구, 리소스, 프롬프트 서버를 연결하기 위한 개방형 프로토콜이다.
|
||||
- 로컬 파일, API, 데이터베이스, 사내 도구를 통일된 방식으로 노출하는 데 초점이 있다.
|
||||
- 이미 로빙 문서에도 MCP 관련 리서치가 축적되어 있다.
|
||||
|
||||
공식 출처:
|
||||
- https://modelcontextprotocol.io/introduction
|
||||
- https://modelcontextprotocol.io/specification/2025-06-18
|
||||
|
||||
### 2.5 Exa 관련 공식 사실
|
||||
|
||||
- Exa는 AI 에이전트용 웹 검색 및 콘텐츠 수집 API를 제공한다.
|
||||
- 일반 검색 결과 목록만이 아니라, 실제 본문 수집과 구조화된 검색 결과를 제공하는 방향으로 문서화되어 있다.
|
||||
- 최신 기술 문서나 웹 근거 수집에 사용할 수 있다.
|
||||
|
||||
공식 출처:
|
||||
- https://exa.ai/exa-api
|
||||
- https://docs.exa.ai/reference/search
|
||||
|
||||
### 2.6 Stitch 관련 공식 사실
|
||||
|
||||
- Stitch는 Google이 공개한 UI 설계/프론트엔드 생성 도구 계열로 소개된다.
|
||||
- 프롬프트나 시각 입력을 바탕으로 UI 목업과 프론트엔드 코드 생성을 지원하는 방향으로 발표되었다.
|
||||
- 영상에서 디자인 보조 도구로 언급되었다면 맥락상 자연스럽다.
|
||||
|
||||
공식 출처:
|
||||
- https://developers.googleblog.com/stitch-a-new-way-to-design-uis/
|
||||
|
||||
### 2.7 이번 확인 범위에서 공식 출처를 확정하지 못한 항목
|
||||
|
||||
- `MGrab`
|
||||
- `Clarify`
|
||||
- `Oh My Claude Code`
|
||||
|
||||
위 세 항목은 사용자 제공 요약에는 등장하지만, 이번 작업에서는 공식 1차 출처를 확인하지 못했다. 따라서 로빙 SSOT나 원칙 문서에는 확정 도구처럼 올리지 않는 편이 안전하다.
|
||||
|
||||
## 3. Interpretation
|
||||
|
||||
### 3.1 영상의 핵심은 모델 성능보다 하네스 설계다
|
||||
|
||||
영상 제목과 도구 구성을 교차하면, 핵심 메시지는 "더 좋은 모델" 단독보다 "계획, 파일, 도구 연결, 역할 분리"를 포함한 하네스가 실제 생산성을 좌우한다는 주장으로 해석하는 것이 타당하다.
|
||||
|
||||
이 해석은 DeepAgents의 파일 기반 상태 유지, Claude Code의 hooks/sub-agents/MCP 구조와 정합적이다. 즉, 프롬프트 한 장으로 모든 문제를 해결하려 하기보다:
|
||||
|
||||
- 계획을 별도로 유지하고
|
||||
- 외부 지식을 도구로 연결하고
|
||||
- 작업 단위를 분리하고
|
||||
- 검증을 자동화하는 방향
|
||||
|
||||
이 `Context Engineering`의 실무 해석에 가깝다.
|
||||
|
||||
### 3.2 Context Engineering은 프롬프트 문구 작성보다 운영 구조 설계에 가깝다
|
||||
|
||||
이번 영상 맥락에서 `Context Engineering`은 단순히 프롬프트를 예쁘게 쓰는 기술이 아니다. 더 안전한 정의는 아래와 같다.
|
||||
|
||||
- 어떤 정보를 항상 메모리에 둘지 결정한다.
|
||||
- 어떤 정보는 파일이나 도구 호출로 늦게 가져올지 결정한다.
|
||||
- 어떤 작업은 별도 에이전트에 위임할지 결정한다.
|
||||
- 어떤 시점에 lint, test, search, review를 자동 실행할지 결정한다.
|
||||
|
||||
즉 로빙에서 말하면, `컨텍스트 설계 = 프롬프트 + 문서 + 파일 + 도구 + 검증 루프` 전체를 아우르는 운영 설계다.
|
||||
|
||||
### 3.3 도구별 역할 분리는 아래 정도로 정리하는 것이 안전하다
|
||||
|
||||
| 도구/개념 | 안전한 해석 | 로빙 적용 포인트 |
|
||||
|---|---|---|
|
||||
| Claude Code | 코딩 작업용 에이전트 CLI. 훅, 서브에이전트, MCP 연결 지원 | 코드 수정, 테스트, 리뷰 자동화 패턴 참고 |
|
||||
| DeepAgents | 긴 작업을 계획/파일/서브에이전트로 분리하는 하네스 | 장기 작업, 문서 기반 상태 유지, 분업 구조 참고 |
|
||||
| MCP | 도구/리소스 연결 표준 | 로빙 내부 skill, DB, 파일 접근 표준화 참고 |
|
||||
| Exa | 최신 웹 근거 수집용 검색 API | 외부 문서 리서치, 최신 기술 검증 |
|
||||
| Stitch | UI 초안/프론트엔드 생성 도구 | 디자인 프로토타입 실험 |
|
||||
|
||||
### 3.4 자동 compact 비활성화 조언은 "파일로 상태를 빼라"는 실무 팁으로 해석하는 편이 맞다
|
||||
|
||||
사용자 제공 요약에는 자동 compact를 조심하라는 조언이 있다. 이번 작업에서는 해당 발언 자체를 공식 문서로 확정하지는 못했지만, 방향성은 충분히 합리적이다.
|
||||
|
||||
긴 작업에서 상태 요약을 모델 내부 메모리에만 의존하면:
|
||||
|
||||
- 중요한 세부가 누락될 수 있고
|
||||
- 요약 품질이 불안정할 수 있으며
|
||||
- 회귀 추적이 어려워진다
|
||||
|
||||
따라서 작업 상태를 Markdown 문서, 계획 파일, 리서치 파일처럼 외부 파일에 저장하는 방식은 로빙 SSOT와도 잘 맞는다.
|
||||
|
||||
## 4. Unresolved
|
||||
|
||||
- 영상 전체 자막을 직접 확보하지 못해, 발언 단위의 정확한 워딩은 이번 문서에서 확정하지 않았다.
|
||||
- `MGrab`, `Clarify`, `Oh My Claude Code`가 실제로 어떤 제품을 가리키는지, 또는 영상 내 비공식 별칭인지 추가 확인이 필요하다.
|
||||
- 영상에서 `Stitch`를 어떤 깊이로 다뤘는지, 단순 예시인지 실제 추천 도구인지는 자막 확인 전까지 보류가 안전하다.
|
||||
|
||||
## 5. 로빙 적용 권장선
|
||||
|
||||
### 5.1 바로 문서화해도 되는 수준
|
||||
|
||||
- Context Engineering을 "프롬프트 문구"가 아니라 "문서/파일/도구/검증 루프 설계"로 해석하는 것
|
||||
- MCP를 내부 도구 연결 표준 후보로 계속 추적하는 것
|
||||
- Claude Code/DeepAgents 사례를 통해 하네스 중심 설계를 연구 대상으로 축적하는 것
|
||||
|
||||
### 5.2 아직 원칙 문서로 승격하면 이른 수준
|
||||
|
||||
- `MGrab`, `Clarify`, `Oh My Claude Code`를 로빙 표준 도구 목록으로 고정하는 것
|
||||
- 영상의 개별 발언을 자막 검증 없이 확정적 문장으로 옮기는 것
|
||||
- 특정 상용 도구 선택을 구조 원칙처럼 일반화하는 것
|
||||
|
||||
## 6. 문서 배치 판단
|
||||
|
||||
이 주제는 문제 해결 기록이 아니므로 `troubleshooting` 대상이 아니다. 또한 실행 순서를 고정한 문서도 아니므로 `plans`도 아니다. 현재로서는 `orchestration_tools` 아래 리서치 문서가 가장 자연스럽다.
|
||||
|
||||
배치 이유:
|
||||
|
||||
- 도구 비교와 하네스 설계 관점이 중심이다.
|
||||
- 로빙에 즉시 적용할 실행안보다, 구조 해석과 참조 정리가 중심이다.
|
||||
- MCP 자체를 깊게 파는 문서가 아니라, 여러 에이전트 코딩 도구를 묶어 해석하는 문서다.
|
||||
|
||||
## 7. 결론
|
||||
|
||||
이번 영상은 "좋은 모델을 고르는 문제"보다 "좋은 하네스를 설계하는 문제"를 강조하는 자료로 보는 것이 맞다. 공식 문서로 확정 가능한 부분은 `Claude Code`, `DeepAgents`, `MCP`, `Exa`, `Stitch` 정도이며, 나머지 도구명은 보류가 안전하다.
|
||||
|
||||
로빙 관점에서는 이 영상을 다음 한 줄로 요약할 수 있다.
|
||||
|
||||
`에이전트 품질은 프롬프트 단독이 아니라 계획, 파일, 도구 연결, 역할 분리, 검증 자동화로 결정된다.`
|
||||
|
||||
## 8. 출처
|
||||
|
||||
- YouTube oEmbed: https://www.youtube.com/oembed?url=https://www.youtube.com/watch?v=SKqCA-43nPM&format=json
|
||||
- YouTube 영상 페이지: https://www.youtube.com/watch?v=SKqCA-43nPM
|
||||
- Anthropic Claude Code Hooks: https://docs.anthropic.com/en/docs/claude-code/hooks
|
||||
- Anthropic Claude Code Sub-agents: https://docs.anthropic.com/en/docs/claude-code/sub-agents
|
||||
- Anthropic Claude Code MCP: https://docs.anthropic.com/en/docs/claude-code/mcp
|
||||
- LangChain DeepAgents 소개: https://www.langchain.com/deep-agents
|
||||
- LangChain DeepAgents Overview: https://docs.langchain.com/oss/python/deepagents/overview
|
||||
- LangChain DeepAgents Subagents: https://docs.langchain.com/oss/python/deepagents/subagents
|
||||
- MCP Introduction: https://modelcontextprotocol.io/introduction
|
||||
- MCP Specification: https://modelcontextprotocol.io/specification/2025-06-18
|
||||
- Exa API: https://exa.ai/exa-api
|
||||
- Exa Search API Reference: https://docs.exa.ai/reference/search
|
||||
- Google Stitch 소개: https://developers.googleblog.com/stitch-a-new-way-to-design-uis/
|
||||
@ -7,3 +7,4 @@
|
||||
- [OpenClaw 공식 문서 요약](260205_openclaw_official_docs_summary.md) — docs.openclaw.ai 요약 및 로빙 적용 우선순위
|
||||
- [로빙 에이전트 루프·스킬 훅·LLM 실행 구조 리서치](260312_로빙_에이전트루프_스킬훅_LLM실행구조_리서치.md) — LLM API, 에이전트 런타임, 스킬 계약, 훅 구조를 로빙 기준으로 정리
|
||||
- [로빙 LLM API·Agent API·모델 선정·비용 비교 리서치](260312_로빙_LLM_API_Agent_API_모델선정_비용비교_리서치.md) — Gemini/OpenAI 계열 비교, 비용 문서화 원칙, 로빙 기준 모델 선택 방향 정리
|
||||
- [Context Engineering, DeepAgents, Claude Code 영상 리서치](260313_컨텍스트엔지니어링_딥에이전트_클로드코드_영상리서치.md) — 유튜브 영상의 도구 설명을 공식 문서와 교차 검증한 리서치
|
||||
|
||||
@ -1,131 +1,6 @@
|
||||
# 250801 크론잡 로그 동기화 설정
|
||||
# 250801_claude_크론잡로그동기화설정
|
||||
|
||||
## 배경
|
||||
이 문서는 인프라 기준 문서로 이관되었습니다.
|
||||
|
||||
### 이전 문서 참조
|
||||
- [250731_로그저장소_SSHFS설정과_템플릿해결책.md](./250731_로그저장소_SSHFS설정과_템플릿해결책.md)
|
||||
- [250731_claude_SSHFS권한문제해결.md](./250731_claude_SSHFS권한문제해결.md)
|
||||
|
||||
### 문제 상황
|
||||
- Docker SSHFS 충돌로 중앙 로그 시스템 구축 실패
|
||||
- 로그가 51124 서버 SSD에 저장되고 있음 (CLAUDE.md 규칙 위반)
|
||||
- SSHFS 마운트는 되어있지만 Docker 볼륨 마운트 시 충돌 발생
|
||||
|
||||
## 해결 방안: 크론잡 동기화
|
||||
|
||||
### 오전 9시 30분 - 새로운 접근 방식 결정
|
||||
로컬 개발자 제안: "24서버에 로그 저장하고 하루에 한번씩 크론잡으로 HDD로 넘기는 건 어때?"
|
||||
|
||||
장점:
|
||||
1. Docker 설정 변경 불필요
|
||||
2. SSHFS 충돌 없음
|
||||
3. SSD 쓰기 성능 활용
|
||||
4. 배포 시 추가 작업 불필요
|
||||
5. 로그 손실 위험 감소
|
||||
|
||||
### 오전 9시 35분 - 스크립트 작성
|
||||
```bash
|
||||
# 스크립트 디렉토리 생성
|
||||
mkdir -p /home/admin/scripts
|
||||
|
||||
# 동기화 스크립트 작성
|
||||
/home/admin/scripts/sync_logs_to_hdd.sh
|
||||
```
|
||||
|
||||
초기 실행 시 권한 문제 발생:
|
||||
- `/var/log/sync_logs` 생성 실패 (Permission denied)
|
||||
- `/home/admin/logs/sync_logs`로 변경하여 해결
|
||||
|
||||
### 오전 9시 38분 - SSHFS 권한 문제 발견
|
||||
```
|
||||
rsync: [receiver] mkstemp failed: Permission denied (13)
|
||||
```
|
||||
|
||||
원인: SSHFS가 UID 999(docker)로 마운트되어 admin(UID 1001)이 쓸 수 없음
|
||||
|
||||
해결:
|
||||
1. SSHFS를 UID/GID 매핑으로 재마운트
|
||||
```bash
|
||||
fusermount -u /mnt/51123logs
|
||||
sshfs -o IdentityFile=/home/admin/.ssh/id_rsa_deploy,reconnect,uid=$(id -u),gid=$(id -g) \
|
||||
admin@192.168.219.45:/mnt/hdd/logs/51124-server /mnt/51123logs -p 51123
|
||||
```
|
||||
|
||||
2. 51123 서버에서 디렉토리 권한을 admin으로 변경 (로컬 개발자가 수행)
|
||||
|
||||
### 오전 9시 41분 - 동기화 성공
|
||||
모든 서비스 로그 동기화 완료:
|
||||
- rb10508_test: 474,540 bytes 동기화
|
||||
- rb10408_test: 0 bytes 동기화
|
||||
- rb8001: 18,751 bytes 동기화
|
||||
- skill_news: 125 bytes 동기화
|
||||
- skill_email: 로그 디렉토리 없음
|
||||
|
||||
### 오전 9시 42분 - 크론탭 설정
|
||||
```bash
|
||||
# 크론탭 설정 (매일 새벽 3시)
|
||||
0 3 * * * /home/admin/scripts/sync_logs_to_hdd.sh >> /home/admin/logs/sync_logs/cron.log 2>&1
|
||||
```
|
||||
|
||||
## 최종 구조
|
||||
|
||||
### 51124 서버 (원본)
|
||||
```
|
||||
/home/admin/ivada_project/
|
||||
├── rb10508_test/logs/
|
||||
├── rb10408_test/logs/
|
||||
├── rb8001/logs/
|
||||
├── skill_news/logs/
|
||||
└── skill_email/logs/
|
||||
```
|
||||
|
||||
### 51123 서버 (백업)
|
||||
```
|
||||
/mnt/hdd/logs/51124-server/
|
||||
├── rb10508_test/
|
||||
├── rb10408_test/
|
||||
├── rb8001/
|
||||
├── skill_news/
|
||||
└── skill_email/
|
||||
```
|
||||
|
||||
## 발견된 문제
|
||||
|
||||
### rb10508_test 중복 디렉토리 구조
|
||||
51124 서버에 이미 중복 구조 존재:
|
||||
```
|
||||
/home/admin/ivada_project/rb10508_test/logs/
|
||||
├── rb10508_test_app.log
|
||||
└── rb10508_test/
|
||||
└── rb10508_test_app.log (0 bytes)
|
||||
```
|
||||
|
||||
이는 Docker 볼륨 마운트나 애플리케이션 설정 문제로 추정됨.
|
||||
|
||||
## 결과
|
||||
|
||||
1. **로그 백업 자동화 완성**: 매일 새벽 3시에 자동 실행
|
||||
2. **SSD 공간 관리**: 7일 이상된 로컬 로그 자동 삭제
|
||||
3. **CLAUDE.md 준수**: 로그가 최종적으로 HDD에 저장됨
|
||||
4. **Docker 충돌 회피**: SSHFS 마운트 포인트와 Docker 볼륨 충돌 없음
|
||||
|
||||
## 교훈
|
||||
|
||||
1. **복잡한 해결책보다 간단한 방법이 낫다**: Docker SSHFS 통합보다 크론잡이 더 안정적
|
||||
2. **권한 문제는 여러 레벨에서 발생**: SSHFS UID 매핑과 원격 디렉토리 권한 모두 확인 필요
|
||||
3. **점진적 마이그레이션**: 실시간 동기화보다 배치 처리가 더 안전할 수 있음
|
||||
4. **로그 파일 경로 정리 필요**: 중복 디렉토리 구조는 추후 정리 필요
|
||||
|
||||
---
|
||||
|
||||
작성일: 2025-08-01 09:30 - 09:45
|
||||
작성자: Claude (51124 서버)
|
||||
주제: Docker SSHFS 충돌 회피를 위한 크론잡 로그 동기화 설정
|
||||
|
||||
---
|
||||
|
||||
**2025-09-08 업데이트**:
|
||||
- rb8001 파일 로깅 구현 완료 (app/core/logger.py)
|
||||
- rb8001/logs/rb8001.log 생성 확인 (7.6KB)
|
||||
- 내일 새벽 3시 크론잡에 자동 포함됨
|
||||
- HDD 동기화 문제 해결 완료
|
||||
- 새 위치: <https://git.ro-being.com/ivada-infra/DOCS/src/branch/main/journey/troubleshooting/250801_%ED%81%AC%EB%A1%A0%EC%9E%A1%EB%A1%9C%EA%B7%B8%EB%8F%99%EA%B8%B0%ED%99%94%EC%84%A4%EC%A0%95.md>
|
||||
- 이유: 51123/51124 간 로그 저장소 마운트, SSHFS 권한, 크론 동기화 구조는 프로젝트 기능 이슈가 아니라 인프라 운영 이슈이기 때문입니다.
|
||||
|
||||
@ -0,0 +1,50 @@
|
||||
# 콜드메일 `skill-rag-file` 500과 실패가시성 복구
|
||||
|
||||
tags: [coldmail, skill-rag-file, rb8001, postgres, scheduler, troubleshooting]
|
||||
|
||||
**날짜**: 2026-03-10
|
||||
**작성자**: Codex
|
||||
**관련 파일**: `rb8001/app/services/coldmail_processor.py`, `rb8001/app/services/workflows/coldmail_workflow.py`, `rb8001/app/scheduler/jobs/coldmail_briefing.py`, `rb8001/tests/test_coldmail_failure_visibility.py`, `skill-rag-file/app/api/upload.py`, `skill-rag-file/.env`
|
||||
**상위 원칙**: [전역 원칙](../../../../0_VALUE/00_Principles/global-principles.md), [문서 작성 원칙](../../book/300_architecture/312_writing-principles.md), [Backend Coding Principles](../../book/300_architecture/311_backend_coding_principles.md)
|
||||
|
||||
## 관련 문서
|
||||
- [콜드메일 `skill-rag-file` 500 및 실패은닉 원인확정 리서치](../research/260310_콜드메일_skill_rag_file_500_및_실패은닉_원인확정_리서치.md)
|
||||
- [9시 네이버 이메일 분석 미전송과 실패 은닉 해결](./260309_9시_네이버이메일분석_미전송_실패은닉_해결.md)
|
||||
- [51123 임시복구 서비스 연속성 조치내역](../../../../infra/DOCS/journey/troubleshooting/260304_51123_임시복구_서비스연속성_조치내역.md)
|
||||
|
||||
---
|
||||
|
||||
## 문제 상황
|
||||
- `2026-03-10 09:05` KST 콜드메일 작업은 실제 실행됐지만, 첨부 PDF 업로드가 전부 실패해 결과가 0건으로 끝났다.
|
||||
- `skill-rag-file`은 `POST /api/upload`에서 `500 Internal Server Error`를 반환했고, 실제 스택트레이스는 DB timeout이었다.
|
||||
- `rb8001` 상위 흐름은 이 실패를 예외로 올리지 않아 APScheduler에는 성공처럼 보였다.
|
||||
|
||||
## 근본 원인
|
||||
- `skill-rag-file/.env`가 과거 임시복구용 DB 주소 `192.168.219.45:5432`를 계속 우선 사용하고 있었다.
|
||||
- 현재 서버에서 해당 주소는 더 이상 유효하지 않아 DB insert 시 timeout이 발생했다.
|
||||
- `rb8001`은 첨부 처리 실패를 `None`으로 흡수해 "0건 처리"로만 닫는 구조였다.
|
||||
|
||||
## 조치
|
||||
- `skill-rag-file/.env`의 `DATABASE_URL` 호스트를 `172.17.0.1`로 교정했다.
|
||||
- `skill-rag-file/app/api/upload.py`에서 DB 비가용성 예외만 `503`으로 분리하고, 없는 `team_id`는 `404`로 반환하도록 정리했다.
|
||||
- `rb8001/app/services/coldmail_processor.py`에서 첨부 처리 실패를 `ColdmailProcessingError`로 승격했다.
|
||||
- `rb8001/app/services/workflows/coldmail_workflow.py`에서 실패 목록을 `processing_failures`로 수집하게 바꿨다.
|
||||
- `rb8001/app/scheduler/jobs/coldmail_briefing.py`에서 실패 목록이 있으면 예외를 다시 올리도록 바꿨다.
|
||||
- `rb8001/tests/test_coldmail_failure_visibility.py`를 추가해 실패 수집과 스케줄러 예외 승격을 검증했다.
|
||||
|
||||
## 검증
|
||||
- `python3 -m py_compile`로 `rb8001` 변경 파일, `skill-rag-file/app/api/upload.py`, 테스트 파일 컴파일을 확인했다.
|
||||
- `docker compose ... up -d --build`로 `rb8001`, `skill-rag-file` 재배포를 완료했다.
|
||||
- 실제 팀 ID `38bdc27d-cb01-4960-867e-41733d2f3529` 업로드 응답은 `200`이었다.
|
||||
- 없는 팀 ID `00000000-0000-0000-0000-000000000001` 업로드 응답은 `404`였다.
|
||||
- 재검증 시 `skill-rag-file` 로그에는 더 이상 DB timeout 기반 `500`이 남지 않았다.
|
||||
|
||||
## 구현 결과
|
||||
- 콜드메일 첨부 업로드 실패는 더 이상 스케줄러 성공으로 숨겨지지 않는다.
|
||||
- `skill-rag-file`의 상태코드가 원인성에 맞게 정리됐다.
|
||||
- 오늘 09:05 장애의 직접 원인인 stale DB host 경로는 제거됐다.
|
||||
|
||||
## 교훈
|
||||
- 서비스별 `.env` 오버라이드는 SSOT 런타임 값을 덮기 때문에, 임시복구 값이 남아 있으면 후속 장애의 직접 원인이 된다.
|
||||
- 외부/하위 서비스 실패를 `None`이나 `0건`으로 흡수하면 운영 판단이 틀어진다.
|
||||
- 비가용성, 입력 오류, 무결성 오류는 서로 다른 상태코드로 유지해야 원인 추적이 가능하다.
|
||||
Loading…
x
Reference in New Issue
Block a user