diff --git a/journey/ideas/260307_이중_NAS_에이전트_파일_스토리지_구조_아이디어.md b/journey/ideas/260307_이중_NAS_에이전트_파일_스토리지_구조_아이디어.md index 1a648f5..82df152 100644 --- a/journey/ideas/260307_이중_NAS_에이전트_파일_스토리지_구조_아이디어.md +++ b/journey/ideas/260307_이중_NAS_에이전트_파일_스토리지_구조_아이디어.md @@ -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로 분리하는 방향이 맞다. +- 새 위치: +- 이유: 외부 NAS -> 내부 NAS 동기화, 내부 NAS 마운트, 저장 경로 분리 문제는 `robeing` 기능 문서보다 `infra` 운영 문서로 관리하는 것이 SSOT에 맞습니다. diff --git a/journey/research/260310_콜드메일_skill_rag_file_500_및_실패은닉_원인확정_리서치.md b/journey/research/260310_콜드메일_skill_rag_file_500_및_실패은닉_원인확정_리서치.md new file mode 100644 index 0000000..cf6318d --- /dev/null +++ b/journey/research/260310_콜드메일_skill_rag_file_500_및_실패은닉_원인확정_리서치.md @@ -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` 기준이다. diff --git a/journey/research/orchestration_tools/260313_컨텍스트엔지니어링_딥에이전트_클로드코드_영상리서치.md b/journey/research/orchestration_tools/260313_컨텍스트엔지니어링_딥에이전트_클로드코드_영상리서치.md new file mode 100644 index 0000000..16e0299 --- /dev/null +++ b/journey/research/orchestration_tools/260313_컨텍스트엔지니어링_딥에이전트_클로드코드_영상리서치.md @@ -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/ diff --git a/journey/research/orchestration_tools/README.md b/journey/research/orchestration_tools/README.md index faaa224..f61e8bc 100644 --- a/journey/research/orchestration_tools/README.md +++ b/journey/research/orchestration_tools/README.md @@ -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) — 유튜브 영상의 도구 설명을 공식 문서와 교차 검증한 리서치 diff --git a/journey/troubleshooting/250801_claude_크론잡로그동기화설정.md b/journey/troubleshooting/250801_claude_크론잡로그동기화설정.md index 615a98d..a9b08de 100644 --- a/journey/troubleshooting/250801_claude_크론잡로그동기화설정.md +++ b/journey/troubleshooting/250801_claude_크론잡로그동기화설정.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 동기화 문제 해결 완료 \ No newline at end of file +- 새 위치: +- 이유: 51123/51124 간 로그 저장소 마운트, SSHFS 권한, 크론 동기화 구조는 프로젝트 기능 이슈가 아니라 인프라 운영 이슈이기 때문입니다. diff --git a/journey/troubleshooting/260310_coldmail_skill_rag_file_500_stale_db_host_및_실패가시성_복구.md b/journey/troubleshooting/260310_coldmail_skill_rag_file_500_stale_db_host_및_실패가시성_복구.md new file mode 100644 index 0000000..3cbd629 --- /dev/null +++ b/journey/troubleshooting/260310_coldmail_skill_rag_file_500_stale_db_host_및_실패가시성_복구.md @@ -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건`으로 흡수하면 운영 판단이 틀어진다. +- 비가용성, 입력 오류, 무결성 오류는 서로 다른 상태코드로 유지해야 원인 추적이 가능하다.