n8n으로 연구 프로젝트 자동 관리 시스템 만들기
n8n으로 연구 프로젝트 자동 관리 시스템 만들기 — 아침 브리핑부터 랩미팅까지
이전에 n8n + Discord로 할 일 알림을 만든 적이 있습니다. 그 시스템이 진화해서, 이제는 7개 연구 프로젝트의 진행 상태 추적, 하루 4회 마이크로태스크 넛지, 주간 리뷰, 랩미팅 폼 자동 생성까지 하나의 플랫폼에서 돌아가고 있습니다.
완성된 아키텍처
=== 아침 브리핑 (매일 7AM) ===
Schedule ──┬── Obsidian #todo 파싱 ────────────┐
/todo ─────┤ ├── Merge → Discord
├── Todoist P1 + D-day ───────────────┤
└── 연구 상태 (요일별 포커스 + 2분 태스크) ┘
=== Research Nudge (하루 4회) ===
Schedule (05/10/15/20시) → Claude Code(Sonnet) → 가장 stale한 프로젝트 micro-task → Discord
=== 주간 리뷰 (일요일 19시) ===
Schedule / /research → 진행·정체·대기 분류 + 다음 주 제안 → Discord (금색 embed)
=== 랩미팅 폼 (화요일 08시) ===
Schedule / /research 랩미팅 → 폼 생성 → Obsidian 저장 + Digital Garden 배포 → Discord
핵심은 하나의 Task.md 파일이 모든 워크플로우의 데이터 소스라는 점입니다.
기존 시스템 vs 확장된 시스템
| 항목 | 기존 (v1) | 현재 (v2) |
|---|---|---|
| 데이터 소스 | Obsidian #todo, Todoist P1 | + 연구 상태 테이블, 요일별 포커스 |
| 알림 횟수 | 1회/일 | 아침 브리핑 + 넛지 4회 + 주간 리뷰 |
| 연구 추적 | 없음 | 7개 프로젝트 active/stale/waiting 분류 |
| 랩미팅 | 수동 작성 | 자동 폼 생성 + 웹 배포 |
| AI 연동 | 없음 | Claude Code가 micro-task 선별 |
| 슬래시 커맨드 | /todo |
+ /research, /research 랩미팅 |
1. Task.md — 단일 진실의 원천
모든 워크플로우가 참조하는 Task.md에 마커 기반 구조를 도입했습니다.
## 할 일
- [ ] 논문 초안 작성 #todo
- [ ] IRB 서류 제출 #todo
<!-- research-status-start -->
| project | status | last_update | next_action |
|---------|--------|-------------|-------------|
| EAG OBJ2 | active | 2026-04-25 | 데이터 측정 3건 |
| CT Genetics | active | 2026-04-17 | grant 신청서 |
| Pelvic Tilt | stale | 2026-02-10 | pilot 설계 재검토 |
<!-- research-status-end -->
<!-- weekday-focus-start -->
| 요일 | 포커스 프로젝트 |
|------|---------------|
| 월 | EAG OBJ2 |
| 화 | CT Genetics |
| 수 | Frozen Shoulder CPG |
...
<!-- weekday-focus-end -->
HTML 주석 마커(<!-- start/end -->)를 쓴 이유: Obsidian에서는 보이지 않으면서 파서가 정확히 추출할 수 있습니다.
2. 아침 브리핑 — 3개 브랜치 병렬 처리
기존 todo 알림에 연구 상태 브랜치를 추가했습니다.
Branch 3: 연구 상태 파싱 (Code 노드)
// Task.md에서 research-status 마커 사이 테이블 파싱
const content = $input.first().json.data;
const match = content.match(
/<!-- research-status-start -->([\s\S]*?)<!-- research-status-end -->/
);
// 요일별 포커스 프로젝트 결정
const dayOfWeek = new Date().getDay(); // 0=일 ~ 6=토
const focusMatch = content.match(
/<!-- weekday-focus-start -->([\s\S]*?)<!-- weekday-focus-end -->/
);
// stale 판정: last_update로부터 30일 이상 경과
const projects = parseTable(match[1]);
for (const p of projects) {
const daysSince = daysDiff(p.last_update, today);
if (daysSince >= 30) p.status = 'stale';
}
아침 브리핑 메시지에는 오늘의 포커스 프로젝트 + 2분 안에 할 수 있는 태스크가 포함됩니다.
상태 이모지 체계
| status | 이모지 | 알림 빈도 |
|---|---|---|
| active | 🟢 | 매일 |
| stale (30일+) | 🔴 | 매일 (경고) |
| waiting | ⏳ | 주 1회 |
| submitted | 📨 | 주 1회 |
| done | ✅ | 표시 안 함 |
3. Research Nudge — AI가 고르는 마이크로태스크
하루 4회(05시/10시/15시/20시) Claude Code(Sonnet)가 자동으로 실행됩니다.
Schedule → POST /run-claude (Sonnet)
→ Claude가 research_status_parser.py 실행
→ 가장 stale한 프로젝트 1개 선택
→ 2분 이내 micro-task 제안
→ daily-research-nudge.md 저장
→ Discord 전송
Claude에게 넘기는 프롬프트 핵심: "가장 오래 방치된 프로젝트를 골라서, 지금 당장 2분 안에 할 수 있는 한 가지만 제안해줘."
이게 의외로 효과적입니다. "CT Genetics grant 신청서의 specific aims 섹션 한 문장만 써보세요" 같은 넛지가 오면, 심리적 장벽이 낮아져서 실제로 손이 갑니다.
4. 주간 연구 리뷰 — 일요일 자동 회고
매주 일요일 저녁 7시, 한 주간의 연구 진행을 자동으로 정리합니다.
// 프로젝트를 진행/정체/대기로 분류
const categories = {
진행: projects.filter(p => p.status === 'active' && daysSince(p.last_update) < 7),
정체: projects.filter(p => p.status === 'active' && daysSince(p.last_update) >= 7),
대기: projects.filter(p => ['waiting', 'submitted'].includes(p.status))
};
// 다음 주 제안: 가장 정체된 프로젝트의 next_action 우선 배치
Discord embed 색상을 금색(15844367)으로 설정해서 일반 알림과 시각적으로 구분했습니다.
5. 랩미팅 폼 자동 생성 + 웹 배포
매주 화요일 아침, 랩미팅용 양식이 자동으로 만들어지고 Digital Garden에 배포됩니다.
Generate Form → Write to Obsidian (📥️Inbox/랩미팅 2026-04-22.md)
→ DG Publish (POST /dg-publish → Vercel 배포)
→ Discord 알림 ("랩미팅 폼이 준비되었습니다")
팀원들은 Vercel로 배포된 웹페이지에서 바로 내용을 확인할 수 있습니다.
6. API 서버 — 모든 워크플로우의 중간 다리
NAS의 api-server.js(port 3002)가 n8n과 로컬 파일시스템을 연결합니다.
| 엔드포인트 | 용도 |
|---|---|
GET /read-file |
Obsidian 파일 읽기 |
GET /research-status |
연구 상태 파싱 실행 |
POST /run-claude |
Claude CLI headless 실행 |
POST /write-file |
파일 쓰기 |
POST /dg-publish |
Digital Garden 배포 (git push) |
n8n은 Docker 컨테이너 안에 있고, Obsidian 파일은 NAS 호스트에 있으므로 이 API 서버가 반드시 필요합니다.
삽질 기록
n8n Code 노드 vs Execute Command
처음에는 research_status_parser.py --discord를 Execute Command 노드로 실행했는데, Docker 안에 Python 환경이 없어서 실패. 결국 인라인 JavaScript Code 노드로 파서를 재구현했습니다. 2700자짜리 JS 코드지만, 외부 의존성 없이 n8n 안에서 완결됩니다.
Discord embed 내 멘션 알림
이건 v1에서도 겪었지만, embed 안의 <@ID>는 알림이 안 옵니다. content 필드(embed 바깥)에 멘션을 넣고 allowed_mentions까지 설정해야 푸시 알림이 옵니다.
Claude Sonnet으로 비용 관리
Research Nudge는 하루 4회 × 매일 실행되므로 Opus 대신 Sonnet을 사용합니다. micro-task 제안 정도는 Sonnet으로 충분합니다.
마무리
할 일 알림 하나로 시작한 시스템이 연구 프로젝트 관리 플랫폼으로 성장했습니다.
- 아침 브리핑: #todo + Todoist P1 + 오늘의 연구 포커스
- 하루 4회 넛지: AI가 골라주는 2분짜리 마이크로태스크
- 주간 리뷰: 진행/정체/대기 자동 분류 + 다음 주 제안
- 랩미팅 폼: 자동 생성 + 웹 배포
Task.md 하나만 잘 관리하면 나머지는 시스템이 알아서 돌아갑니다. 연구자의 인지 부담을 줄이는 게 이 시스템의 핵심 가치입니다.