앞선 글에서 Dify와 Continue를 함께 쓰는 전체 워크플로를 살펴봤다면, 이번에는 한 발 더 들어간다. “작은 파이썬 함수 하나를 짜고, 그 함수를 사내 가이드라인에 맞는 문서로 자동 정리해서 위키에 올린다”라는 아주 구체적인 시나리오를 실제 흐름 그대로 따라가 본다. 코드 작성은 Continue가, 그 뒤의 문서 표준화와 배포는 Dify가 맡는 식이다. 두 도구의 역할 분담을 머리로만 이해하기보다 손을 움직여 한 번 돌려보는 데 목적이 있다.
중요한 건 각 도구를 왜 그 자리에서 쓰는가이다. Continue는 IDE 안에서 파일·터미널·에러 로그 같은 컨텍스트를 쥐고 코드를 실제로 수정하는 데 특화돼 있고, Dify는 프롬프트·변수·지식베이스·출력 포맷을 워크플로로 묶어 결과를 “일관된 산출물”로 뽑는 데 강하다. 이 둘을 이어 붙이면 “빠르게 구현한 코드가 바로 팀이 읽을 수 있는 문서로 변하는” 파이프라인이 만들어진다.
1. 목표 시나리오
“사용자 목록에서 이메일 주소만 뽑는 파이썬 함수를 하나 만들고, 그 결과를 내부 위키(Confluence/Notion 등)에 ‘가이드라인 스타일 문서’로 올린다.” 이 한 줄짜리 시나리오 안에는 실제 업무에서 반복되는 패턴이 그대로 들어 있다.
- 구현 단계: 요구사항 → 프롬프트 → 코드 초안 → 보강 → 테스트
- 문서화 단계: 동일한 코드에 대해 설명·예시·주의사항을 팀 포맷으로 맞춤
- 배포 단계: 결과물을 위키/이슈 트래커로 자동 등록
이번 실습에서는 Continue가 구현 단계를, Dify가 문서화와 배포 단계를 담당한다. 중간 산출물(함수 본문, 설명, 테스트 케이스)이 어떻게 다음 단계의 입력으로 흘러가는지가 핵심 포인트다.
2. Continue로 코드 작성
VSCode(또는 JetBrains)에서 Continue 사이드바를 열고 프롬프트를 입력한다. 단순히 “함수 만들어줘”로 끝내지 말고, 입력/출력/엣지 케이스를 미리 못 박아 두는 편이 뒤의 리팩토링 비용을 줄인다.
프롬프트: “리스트 형태의 사용자 객체에서 이메일 주소만 추출하는 Python 함수를 작성해줘. 입력은 dict의 list, 각 dict에 ’email’ 키가 없을 수도 있음. 중복은 제거하고 원래 순서는 유지. 타입 힌트와 docstring도 포함.”
Continue 응답 예시:
from typing import Iterable, List, Dict, Any
def extract_emails(users: Iterable[Dict[str, Any]]) -> List[str]:
"""사용자 dict 리스트에서 'email' 값을 순서를 보존한 채 중복 없이 추출한다.
Args:
users: dict 의 iterable. 각 dict 는 'email' 키를 가질 수도 있고 없을 수도 있다.
Returns:
중복이 제거된 email 문자열 리스트. 원본에서 등장한 순서를 유지한다.
"""
seen: set = set()
result: List[str] = []
for user in users:
email = user.get("email")
if not email or email in seen:
continue
seen.add(email)
result.append(email)
return result
여기서 멈추지 말고 Continue의 후속 명령을 몇 개 더 돌려 “실무에 바로 넣을 수 있는 상태”까지 끌어올리자.
/edit또는Cmd+I— “유효하지 않은 이메일 포맷은 걸러내도록 정규식 검증을 추가”/test— 엣지 케이스(빈 리스트, email 키 없음, 중복, 대소문자 혼재)에 대한 pytest 테스트 생성@terminal— 테스트 실행 결과를 붙여 넣고 “왜 실패했지?”로 원인 분석
이 단계에서 나온 코드 + 테스트 + 실행 로그가 다음 문서화 단계의 원재료가 된다. Continue를 단순 코드 생성기로만 쓰면 아깝다. 컨텍스트를 IDE 안에서 계속 누적해두는 것이 Dify 쪽 입력의 질을 결정한다.
3. 코드 설명 요청
작성된 코드 블록을 선택한 뒤 Continue의 Explain 또는 Document this 커맨드를 실행한다. 이때 얻는 설명은 “이 함수의 동작”에 집중된, 개인 용도의 빠른 메모에 가깝다.
Continue 응답 예시: “이 함수는 사용자 객체 리스트를 받아, 각 객체에서 ’email’ 키가 있는 경우 해당 값을 순서를 보존한 채 중복 없이 추출해 반환합니다. ’email’ 키가 없거나 값이 비어 있는 경우에는 건너뜁니다.”
문제는 이 설명이 팀 표준과는 결이 다르다는 점이다. 회사마다 “함수 설명 문서는 이 포맷을 따른다”라는 암묵적인 규칙이 있는데, Continue의 1회성 답변만으로는 그 규격을 맞추기 어렵다. 여기서부터가 Dify의 영역이다.
4. Dify를 통한 문서화
Dify에서는 “사내 가이드라인에 맞춘 함수 문서화” 워크플로를 하나 만들어둔다. 워크플로는 대개 아래 4개 노드로 구성된다.
| 노드 | 역할 | 핵심 설정 |
|---|---|---|
| Start | 입력 변수 수집 | code, language, module 3개 변수 |
| Knowledge Retrieval | 가이드라인 RAG 조회 | 사내 “코드 문서화 표준” 데이터셋 지정 |
| LLM | 표준 포맷으로 재작성 | System 프롬프트에 섹션 순서 명시 |
| End | Markdown 출력 | Confluence Storage Format으로 후처리 |
LLM 노드의 System 프롬프트는 출력 구조를 단단히 고정해두는 것이 포인트다. 예를 들어 이렇게 적어둔다.
당신은 사내 개발 가이드라인을 따르는 테크니컬 라이터다.
입력으로 들어온 코드에 대해 아래 순서와 형식을 반드시 지킨다.
## 함수 설명: <함수명>
- 한 줄 요약
- 입력 / 출력 명세 (표)
- 동작 상세 (불릿)
- 사용 예시 (실행 가능한 코드 + 출력 주석)
- 주의사항 / 엣지 케이스
- 관련 모듈 링크
출력은 Markdown, 코드 블록은 ```python 으로 감싼다.
가이드라인 데이터셋에서 검색된 스타일을 우선 따른다.이제 2·3단계에서 나온 코드와 설명을 Dify 워크플로에 밀어 넣는다. Web UI에 붙여넣어도 되고, 팀 도구에 붙일 거라면 API로 직접 호출한다.
curl -X POST http://localhost/v1/workflows/run \
-H "Authorization: Bearer $DIFY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"inputs": {
"code": "def extract_emails(users): ...",
"language": "python",
"module": "user_utils"
},
"response_mode": "blocking",
"user": "sunung@yapsoft"
}'결과는 아래와 같이 팀 포맷에 맞춰진 상태로 돌아온다.
## 함수 설명: extract_emails
사용자 dict 리스트에서 'email' 값을 순서를 보존한 채 중복 없이 추출한다.
### 입력 / 출력
| 이름 | 타입 | 설명 |
|------|------|------|
| users | Iterable[Dict[str, Any]] | 'email' 키가 있을 수도, 없을 수도 있는 dict 의 모음 |
| 반환값 | List[str] | 중복이 제거된 이메일 목록 (입력 순서 유지) |
### 동작 상세
- 'email' 키가 없거나 값이 빈 문자열이면 건너뛴다.
- set 으로 중복을 판별하고, 리스트로 순서를 유지한다.
### 사용 예시
```python
users = [
{"name": "Alice", "email": "alice@example.com"},
{"name": "Bob"},
{"email": "alice@example.com"}, # 중복
{"email": "carol@example.com"},
]
extract_emails(users)
# -> ['alice@example.com', 'carol@example.com']
```
### 주의사항
- 이메일 형식 검증은 수행하지 않는다. 필요 시 `email_validator` 등 외부 라이브러리를 병행하라.
- 입력이 매우 큰 경우 set 메모리 사용량을 고려한다.여기까지 오면 이 Markdown을 그대로 Confluence/Notion API에 올리거나, GitHub PR 템플릿의 “구현 노트” 섹션에 붙이는 일만 남는다. Dify 워크플로 마지막 노드에 HTTP Request 노드를 추가해 Confluence Storage Format으로 변환 후 페이지 생성 API 호출까지 묶어두면, 코드 작성에서 위키 등록까지가 사람 손을 거의 타지 않는 한 줄 파이프라인이 된다.
5. 두 도구의 역할 분담 정리
| 관점 | Continue | Dify |
|---|---|---|
| 실행 위치 | IDE 내부 | 서버 워크플로 |
| 주 역할 | 코드 생성·수정·설명 | 산출물 표준화·배포 |
| 컨텍스트 소스 | 파일/터미널/에러/깃 diff | 지식베이스(RAG) + 입력 변수 |
| 출력 포맷 제어 | 약함 (매번 달라짐) | 강함 (프롬프트+워크플로로 고정) |
| 재사용성 | 개인 단축키 중심 | 팀 공용 API로 노출 가능 |
쉽게 말해 Continue는 “빠른 손”, Dify는 “다듬는 편집자”다. Continue가 만든 결과물의 들쭉날쭉함을 Dify가 일관된 결로 다듬고, 그대로 팀 자산으로 쌓이게 만든다.
6. 실전 팁과 트러블슈팅
- 프롬프트에 “포맷”을 못 박자: Continue에서도 “반환 형식은 Markdown, 코드는 “`python 블록으로”처럼 출력 규격을 지시하면 Dify 입력이 훨씬 깨끗해진다.
- Dify 지식베이스는 작게 시작: 처음부터 전사 가이드라인을 전부 넣지 말고, “함수 문서화 표준” 같은 1개 주제로 10~20 문서만 넣어 품질을 튜닝한 뒤 확장한다.
- 변수 누락 주의: Dify 워크플로에서
code변수를 비워 호출하면 LLM이 임의의 예시를 만들어낸다. API 호출 측에서 필수값 검증을 반드시 붙인다. - 토큰 비용 관리: Continue 쪽은 편집 반복으로 토큰이 빠르게 누적된다. 긴 파일은
@folder나@codebase로 범위를 먼저 좁힌 뒤 질문한다. - 사내망 환경: 외부 API 호출이 막혀 있으면 Ollama 등 로컬 LLM을 Continue와 Dify 양쪽에 동일하게 연결해 결과 편차를 줄인다.
- 문서 업데이트 자동화: 함수 시그니처가 바뀔 때마다 Dify 워크플로를 재실행해 위키 페이지를 갱신하도록 GitHub Actions에 훅을 건다. 문서가 코드와 함께 나이를 먹는 것을 막는 가장 확실한 방법이다.
7. 다음으로 확장하기
같은 패턴은 “함수 문서화” 말고도 거의 모든 개발 산출물에 그대로 적용된다. 몇 가지 확장 아이디어를 남겨둔다.
- PR 설명 자동 작성: Continue가
git diff로 뽑은 변경 요약을 Dify가 “PR 템플릿”으로 재구성 → GitHub API로 본문 등록 - 릴리스 노트 생성: 태그 사이 커밋 로그를 Dify에 입력 → 사용자용 어투로 변환 → Notion 릴리스 페이지 자동 생성
- 버그 리포트 표준화: 터미널 에러 로그를 Continue
@terminal로 캡처 → Dify가 재현 절차·원인 가설·체크리스트로 포맷팅 → Jira 티켓 자동 생성 - 사내 온보딩 문서: 팀별 저장소를 Dify 지식베이스로 연결 → 신규 입사자가 채팅으로 “이 모듈 뭐하는 애야?”를 물으면 표준 답변 반환
결국 Continue와 Dify의 조합이 바꾸는 건 “AI로 코드를 짠다”가 아니라 “AI가 만든 결과물이 팀 자산으로 축적된다”는 쪽이다. 개인의 생산성 도구를 팀의 지식 파이프라인으로 끌어올리는 이 작은 한 단계를, 작은 시나리오부터 가볍게 적용해 보길 권한다.