Files
aio-01d4-stu/Lecture/66/01-STAGE1-DESIGN-AND-DATA-FLOW.md
T
2026-10-15 22:45:16 +09:00

14 KiB

1단계 · 단일 업무 자동화 설계와 데이터 흐름

  • 시간: 1~2교시 (1교시 앞부분은 오늘의 개요)
  • 학습 목표
    • 하나의 업무를 목적 하나로 좁히고, 결과를 먼저 그려 볼 수 있다.
    • 노드 사이를 지나가는 항목(item) 의 개수를 읽고 쓸 수 있다 (1 → 4 → 1).
    • LLM이 할 일과 규칙으로 할 일을 나눌 수 있다.
    • 조건 분기·반복·병렬 중 어떤 제어 구조가 필요한지 고를 수 있다.
    • 요청이 바뀌었을 때 어느 노드를 고치면 되는지 찾을 수 있다.
  • 실습: Lab 01 · 회의록 자동 정리 워크플로우 설계하기 (예제 2개 + 과제)
flowchart LR
  A["1. 오늘의 업무"] --> B["2. 결과 먼저"] --> C["3. 항목 읽기<br/>(Lab 01 예제 1)"] --> D["4. 1 → 4 → 1<br/>(Lab 01 예제 2)"] --> E["5. 제어 구조"] --> F["6. 요청이 바뀌면<br/>(Lab 01 과제)"]

오늘 수업은 모두 같은 순서로 갑니다. 설명 → 쉬운 예제 2개를 함께 → 그것을 고치는 과제를 혼자. 이 교안의 절도 Lab의 예제·과제 순서에 맞춰 놓았습니다.


1. 오늘의 업무: 회의록 → 할 일 정리

64일차 시나리오 S1 "회의록 요약 후 할 일 정리"를 n8n으로 만듭니다.

지금 (AS-IS) 자동화 후 (TO-BE)
누군가 회의록을 읽고 할 일·담당자·기한을 찾아 정리 회의록을 보내면 요약·할 일 목록·정리문이 바로 나옴
담당자나 기한이 빠진 일을 놓침 빠진 값은 미정으로 보임
급한 일이 묻힘 오늘·내일 마감은 우선순위 높음

1.1 목적 하나로 좁히기

처음 만드는 자동화는 목적 하나만 해결합니다. 메일 발송·일정 등록까지 한 번에 넣으면 어디가 틀렸는지 찾기 어렵습니다.

질문 오늘의 답 (한 문장씩)
목적 회의록을 받으면 할 일 목록과 정리문을 돌려준다
입력 → 출력 {title, notes} → {title, route, count, summary, actions, report_text}
성공 기준 예시 회의록(weekly)에서 할 일 4건, 빠진 값은 미정, 오늘 마감은 높음

세 줄이 한 문장씩으로 끝나지 않으면 아직 범위가 넓은 것입니다. 회의록이 비어 있으면 LLM을 부르기 전에 맨 앞에서 거절(HTTP 400)합니다. 쓸데없는 호출과 비용을 막는 가장 싼 방법입니다.


2. 결과를 먼저 그려 보기

노드를 생각하기 전에 예시 입력 한 건과 기대하는 결과를 손으로 적습니다.

참석: 김민지, 이준호, 박서연. 1) 신규 고객 문의 응답 템플릿을 이준호가 금요일까지 정리한다. 2) 박서연은 다음 주 월요일까지 VPN 장애 보고서를 작성한다. 3) 서버 점검 일정은 김민지가 오늘 중 공지한다. 4) 회의실 예약 규칙 개선은 담당자를 다음 회의에서 정한다. 다음 회의는 10월 23일.

# 할 일 담당자 기한 우선순위
1 신규 고객 문의 응답 템플릿 정리 이준호 금요일 보통
2 VPN 장애 보고서 작성 박서연 다음 주 월요일 보통
3 서버 점검 일정 공지 김민지 오늘 높음
4 회의실 예약 규칙 개선 담당자 선정 미정 10월 23일 보통

이 표를 채우다 보면 일이 두 종류로 나뉩니다.

누가 하는 일 왜
LLM 문장 속에서 할 일·담당자·기한 찾기, 요약 사람 말을 읽어야 함
규칙 빈 값을 미정으로 채우기, 우선순위 정하기, 정리문 만들기 항상 같은 답이어야 함

4번의 기한은 회의록에 직접 적혀 있지 않지만, 수업 전 측정(gpt-4.1-mini)에서 LLM은 매번 "다음 회의는 10월 23일"을 읽고 10월 23일로 채웠습니다. 담당자는 적혀 있지 않아 미정입니다. LLM이 추론한 값을 받아들일지도 설계에서 정할 일입니다.

2.1 결과 형식을 먼저 약속하기

결과를 받는 쪽(사람, 다른 시스템, 65일차의 플랫폼 전환 코드)이 이 모양에 맞춰 만들어지므로, 노드를 만들기 전에 정합니다.

{"title": "10월 16일 주간 회의", "route": "할 일 정리", "count": 4, "summary": "요약 2문장",
 "actions": [{"task": "...", "owner": "...", "due": "...", "priority": "높음 | 보통"}],
 "report_text": "공유용 정리문"}

할 일이 없어도 같은 필드를 쓰고 route: 할 일 없음, count: 0, actions: []로 둡니다 (65일차 "모든 길이 같은 모양으로 끝나게").


3. 항목(item) 읽기 · Lab 01 예제 1

n8n에서 노드와 노드 사이를 지나가는 데이터 한 덩어리를 항목(item) 이라고 합니다. 택배 상자 하나라고 생각하면 됩니다. 상자 안에는 필드(user, text ...)가 들어 있습니다.

어제 Lab 02A에서 만든 흐름을 보면서 상자가 몇 개 지나가는지 셉니다.

flowchart LR
  T(["Start"]) -->|"1"| S["Sample request<br/>Edit Fields"] -->|"1"| I{"Is urgent?<br/>If"}
  I -->|"true · 1"| U["Urgent route"]
  I -.->|"false · 0"| N["Normal route"]
  • 모든 연결선이 1개입니다. If는 상자를 한쪽 길로 보낼 뿐 개수를 바꾸지 않습니다.
  • 개수를 바꾸는 노드는 따로 있습니다. 오늘 새로 쓰는 노드입니다.
노드 하는 일 항목 수
Edit Fields (Set) 필드 만들기·값 계산 그대로
If · Switch 길 나누기 그대로 (한쪽으로)
Code 무엇이든 (파싱·검증) 코드가 정함
Split Out 상자 속 목록을 상자 여러 개로 펼침 1 → N
Aggregate 상자 여러 개를 목록 하나로 모음 N → 1
Merge 두 길에서 온 상자를 합침 둘 → 하나
Filter 조건에 맞는 상자만 남김 줄어듦

4. 오늘 흐름의 항목 수 1 → 4 → 1 · Lab 01 예제 2

회의록 1건이 할 일 4건이 되었다가 다시 결과 1건이 됩니다.

flowchart LR
  A["회의록<br/>상자 1개"] -->|"LLM + 파싱"| B["상자 1개<br/>안에 actions 목록 [4]"] -->|"Split Out<br/>1 → 4"| C["할 일<br/>상자 4개"] -->|"항목마다 정리"| D["정리된 할 일<br/>상자 4개"] -->|"Aggregate<br/>4 → 1"| E["결과<br/>상자 1개"]

가장 자주 헷갈리는 곳은 B입니다. 할 일이 4건이라도 파싱 직후에는 상자 1개 안에 목록으로 들어 있습니다. Split Out을 지나야 비로소 상자 4개가 됩니다.

오늘 완성할 전체 그림과 각 노드의 역할입니다. (오후 Lab 03 과제의 완성 그림과 같습니다.)

flowchart LR
  W(["Meeting webhook"]) --> S["Settings"] --> H{"Has notes?"}
  H -->|false| R0["Reject empty<br/>400"]
  H -->|true| L1{{"LLM extract actions"}} --> P["Parse actions"] --> J["Join results<br/>Merge"]
  H -->|true| L2{{"LLM summarize"}} --> K["Keep summary"] --> J
  J --> A{"Any actions?"}
  A -->|true| SO["One item per action<br/>Split Out"] --> N["Normalize action"] --> AG["Collect actions<br/>Aggregate"] --> B["Build report"] --> R["Send result"]
  A -->|false| NA["No actions"] --> R
설계에서 n8n 노드 언제 만드나
회의록 받기, 설정 모으기, 비었으면 거절 Webhook, Edit Fields, If, Respond Lab 02 예제 2 (가져옴)
할 일 찾기 (LLM) → 글자를 목록으로 HTTP Request, Code Lab 02 예제 1·2
요약 (LLM)과 합치기 HTTP Request, Edit Fields, Merge Lab 03 예제 2 → 과제
할 일마다 우선순위 → 모으기 → 정리문 Split Out, Edit Fields, Aggregate, Code Lab 03 예제 1 → 과제
할 일이 없을 때 If, Edit Fields Lab 03 과제

4.1 연결선 표에 적는 세 가지

적는 것 예 빠뜨리면
항목 수 Split Out 뒤 4 응답이 할 일 하나만 나가는 것을 늦게 알아챔
필드 이름 actions, count, summary 표현식({{ $json.actions }})에 없는 이름 → 빈 값
형식 LLM 바로 뒤는 글자 LLM 답을 목록으로 착각 → 2단계의 파싱이 필요

5. 제어 구조 고르기

질문 세 개로 고릅니다.

질문 예이면 n8n 오늘의 예
입력에 따라 다른 결과를 내야 하나? 조건 분기 If, Switch 내용 없음 → 거절, 할 일 없음 → 다른 결과
목록의 항목마다 같은 일을 하나? 반복 Split Out → … → Aggregate 할 일마다 우선순위
서로의 결과가 필요 없는 일이 둘 이상인가? 병렬 (Fork-Join) 가지 나누기 + Merge 할 일 찾기와 요약

5.1 연습

업무 제어 구조
문의 메일 50통을 각각 분류 반복
리뷰의 감정 분석과 키워드 추출 병렬
감정이 부정이면 담당자에게, 아니면 자동 답글 조건 분기
회의록 요약을 만든 뒤 그 요약으로 제목 짓기 순서 (제목에 요약 결과가 필요 → 병렬 불가)
출장자마다 날씨 조회 후 우산 필요 여부 판단 반복 + 조건 분기

실제 업무는 여러 구조가 섞이고, 앞 결과가 필요하면 병렬로 나눌 수 없습니다.


6. 요청이 바뀌면 어디를 고치나 · Lab 01 과제

설계를 해 두면 요청이 바뀌었을 때 고칠 곳을 금방 찾습니다. 찾는 순서는 세 질문입니다.

flowchart LR
  Q1{"LLM이 할 일?<br/>규칙이 할 일?"} --> Q2{"할 일 하나마다?<br/>모두 모은 뒤?"} --> Q3{"모든 길이<br/>같은 필드로 끝나나?"}
질문 고칠 곳
할 일 하나마다 정하는 값인가? 상자가 하나씩 흐르는 곳 = Split Out과 Aggregate 사이
모두 모은 뒤에야 알 수 있는 값인가? (개수, 합계) Aggregate 뒤
결과에 필드가 늘었나? 모든 길의 끝 (할 일 없음 길 포함)

연습 삼아 이미 있는 값으로 확인해 봅니다.

값 하나마다? 모은 뒤? 그래서 만드는 곳
priority (오늘·내일이면 높음) 하나마다 Normalize action
count (할 일 개수) 모은 뒤 Build report
route 길마다 Build report / No actions

Lab 01 과제는 이 방법으로 "확인 필요" 요청을 설계하고, 오후 Lab 03 과제에서 실제로 만듭니다.


7. Lab 01 안내

순서 시간 할 일 교안
예제 1 5분 어제 흐름의 연결선 항목 수 읽기 3절
예제 2 7분 오늘 흐름의 빈칸 다섯 개 (1 → 4 → 1, 병렬 이유, LLM이 하는 일) 2·4·5절
과제 10분 "담당자·기한이 없는 할 일은 확인 필요로, 몇 건인지도" → 어디를 고치나 6절
  • 전체 설계서(templates/DATA-FLOW-DESIGN-TEMPLATE.md)는 오늘 복습 과제에서 내 업무로 써 봅니다.

8. 자주 하는 설계 실수

실수 증상 고치는 법
한 번에 알림·일정까지 넣음 어디가 틀렸는지 찾기 어려움 목적 하나로, 나머지는 "나중에"
LLM에게 우선순위·기본값까지 맡김 같은 회의록인데 결과가 매번 다름 찾기는 LLM, 채우기·계산은 규칙
항목 수를 안 적음 응답에 할 일이 하나만 1 → N → 1 표시
결과가 필요한 일을 병렬로 요약 전에 제목을 지으려 함 "앞 결과가 필요한가?"

9. 스스로 확인하기

Q1. If 노드를 지나면 항목 수는 어떻게 되나요?

그대로입니다. If는 항목을 true나 false 한쪽 길로 보낼 뿐 개수를 바꾸지 않습니다. 개수를 바꾸는 노드는 Split Out(1 → N), Aggregate(N → 1) 등입니다.

Q2. 할 일이 4건인데 `Parse actions` 바로 뒤의 항목 수가 1인 이유는?

4건이 actions라는 목록 하나에 담겨 상자 1개로 지나가기 때문입니다. Split Out을 지나야 상자 4개가 됩니다.

Q3. 우선순위를 LLM이 아니라 규칙으로 정하는 이유는?

"기한에 오늘·내일·긴급이 있으면 높음"은 규칙으로 항상 같게 정할 수 있습니다. LLM에 맡기면 결과가 흔들리고 시간·비용이 듭니다.

Q4. "요약을 만든 뒤 그 요약으로 제목 짓기"를 병렬로 나눌 수 없는 이유는?

제목 짓기가 요약 결과를 필요로 하기 때문입니다. 병렬은 서로의 결과가 필요 없을 때만 가능합니다.

Q5. 할 일 개수(`count`)를 `Normalize action`이 아니라 `Build report`에서 세는 이유는?

Normalize action은 할 일 하나마다 따로 실행되어 전체 개수를 모릅니다. 모두 모은(Aggregate) 뒤에야 셀 수 있습니다.

정리

  • 처음 만드는 자동화는 목적 하나로 좁히고, 예시 입력의 기대 결과를 먼저 그립니다.
  • LLM은 찾기, 규칙은 채우기·계산·정리문을 맡습니다. 결과 형식은 노드보다 먼저 약속합니다.
  • 노드 사이를 지나가는 상자(항목)의 개수를 셉니다. 오늘 흐름은 1 → 4 → 1입니다.
  • 결과가 필요 없는 일은 병렬, 항목마다 하는 일은 반복, 입력에 따라 다른 일은 조건 분기입니다.
  • 요청이 바뀌면 "하나마다? 모은 뒤? 모든 길?"로 고칠 곳을 찾습니다.