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 랩미팅

모든 워크플로우가 참조하는 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으로 충분합니다.


마무리

할 일 알림 하나로 시작한 시스템이 연구 프로젝트 관리 플랫폼으로 성장했습니다.

Task.md 하나만 잘 관리하면 나머지는 시스템이 알아서 돌아갑니다. 연구자의 인지 부담을 줄이는 게 이 시스템의 핵심 가치입니다.


Comments