[이제와서 시작하는 Claude AI 마스터하기 #18] 커스텀 워크플로우 구축
[이제와서 시작하는 Claude AI 마스터하기 #18] 커스텀 워크플로우 구축
복잡한 비즈니스 프로세스를 AI로 자동화
커스텀 워크플로우를 구축하면 Claude의 능력을 최대한 활용해 복잡한 비즈니스 프로세스를 자동화할 수 있습니다. 이번 편에서는 실제 기업 환경에서 활용 가능한 고급 워크플로우 구축 방법을 다룹니다.
워크플로우 아키텍처 설계
1. 워크플로우 엔진 구현
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
// 확장 가능한 워크플로우 엔진
interface WorkflowEngine {
define(workflow: WorkflowDefinition): void;
execute(workflowId: string, input: any): Promise<WorkflowResult>;
monitor(executionId: string): ExecutionStatus;
retry(executionId: string): Promise<WorkflowResult>;
}
class AdvancedWorkflowEngine implements WorkflowEngine {
private workflows: Map<string, WorkflowDefinition> = new Map();
private executions: Map<string, WorkflowExecution> = new Map();
private eventBus: EventEmitter;
define(workflow: WorkflowDefinition) {
// 워크플로우 검증
this.validateWorkflow(workflow);
// DAG(Directed Acyclic Graph) 구성
const dag = this.buildDAG(workflow.steps);
this.workflows.set(workflow.id, {
...workflow,
dag,
compiledConditions: this.compileConditions(workflow.steps)
});
}
async execute(workflowId: string, input: any): Promise<WorkflowResult> {
const workflow = this.workflows.get(workflowId);
if (!workflow) throw new Error(`Workflow ${workflowId} not found`);
const execution = new WorkflowExecution(workflow, input);
this.executions.set(execution.id, execution);
try {
// 실행 시작 이벤트
this.eventBus.emit('workflow.started', {
workflowId,
executionId: execution.id,
input
});
// 병렬 실행 지원
const result = await this.executeDAG(execution);
// 완료 이벤트
this.eventBus.emit('workflow.completed', {
workflowId,
executionId: execution.id,
result
});
return result;
} catch (error) {
// 실패 처리
await this.handleFailure(execution, error);
throw error;
}
}
private async executeDAG(execution: WorkflowExecution) {
const { dag } = execution.workflow;
const results = new Map();
// 토폴로지 정렬로 실행 순서 결정
const executionOrder = this.topologicalSort(dag);
for (const layer of executionOrder) {
// 같은 레이어의 스텝들은 병렬 실행
const layerResults = await Promise.all(
layer.map(step => this.executeStep(step, execution, results))
);
// 결과 저장
layer.forEach((step, index) => {
results.set(step.id, layerResults[index]);
});
}
return this.aggregateResults(results, execution.workflow);
}
}
2. 복잡한 워크플로우 정의
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# 복잡한 비즈니스 워크플로우 예시
name: "고객 온보딩 자동화"
id: "customer-onboarding-v2"
version: "2.0.0"
triggers:
- type: "webhook"
endpoint: "/api/webhooks/new-customer"
- type: "schedule"
cron: "0 9 * * MON"
- type: "event"
source: "crm.customer.created"
inputs:
customer:
type: "object"
required: ["email", "company", "plan"]
steps:
# 병렬 실행 그룹 1
- parallel:
- id: "verify-email"
type: "http"
config:
url: "https://api.emailverify.com/check"
method: "POST"
body:
email: ""
- id: "company-research"
type: "claude"
config:
prompt: |
Research company:
Find: industry, size, recent news, competitors
model: "claude-3-opus-20240229"
- id: "risk-assessment"
type: "function"
config:
handler: "assessCustomerRisk"
params:
customer: ""
# 조건부 분기
- id: "risk-check"
type: "condition"
config:
if: " > 0.7"
then:
- id: "manual-review"
type: "human-task"
config:
assignee: "compliance-team"
deadline: "24h"
else:
- id: "auto-approve"
type: "function"
config:
handler: "approveCustomer"
# 병렬 실행 그룹 2
- parallel:
- id: "create-account"
type: "api"
config:
service: "account-service"
method: "createAccount"
- id: "setup-billing"
type: "api"
config:
service: "billing-service"
method: "setupSubscription"
- id: "generate-welcome-kit"
type: "claude"
config:
prompt: |
Create personalized welcome materials for:
Company:
Industry:
Plan:
Include:
1. Welcome email
2. Getting started guide
3. Best practices for their industry
# 최종 단계
- id: "send-communications"
type: "multi-channel"
config:
channels:
- email:
to: ""
template: "welcome"
data: ""
- slack:
channel: "#new-customers"
message: "New customer onboarded: "
- crm:
action: "updateStatus"
status: "onboarded"
error_handling:
retry:
max_attempts: 3
backoff: "exponential"
fallback:
- type: "notification"
target: "ops-team"
- type: "queue"
queue: "failed-onboarding"
monitoring:
metrics:
- "execution_time"
- "success_rate"
- "step_duration"
alerts:
- condition: "execution_time > 300s"
channel: "slack"
3. 동적 워크플로우 생성
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
// AI가 워크플로우를 생성하는 시스템
class DynamicWorkflowBuilder {
private claude: ClaudeAPIClient;
async buildWorkflowFromRequirements(
requirements: string,
constraints: WorkflowConstraints
): Promise<WorkflowDefinition> {
// Claude에게 워크플로우 설계 요청
const design = await this.claude.createMessage({
system: `You are a workflow architect. Design a workflow based on requirements.
Consider: error handling, parallel execution, conditional logic, integrations.
Output as structured JSON matching WorkflowDefinition schema.`,
messages: [{
role: 'user',
content: `Requirements: ${requirements}\nConstraints: ${JSON.stringify(constraints)}`
}],
temperature: 0.7
});
const workflowDef = JSON.parse(design.content[0].text);
// 검증 및 최적화
await this.validateAndOptimize(workflowDef);
return workflowDef;
}
async optimizeExistingWorkflow(
workflow: WorkflowDefinition,
executionHistory: ExecutionHistory[]
): Promise<OptimizedWorkflow> {
const analysis = await this.analyzePerformance(executionHistory);
const optimization = await this.claude.createMessage({
system: 'Analyze workflow performance and suggest optimizations.',
messages: [{
role: 'user',
content: `
Workflow: ${JSON.stringify(workflow)}
Performance data: ${JSON.stringify(analysis)}
Suggest:
1. Steps that can be parallelized
2. Unnecessary steps to remove
3. Caching opportunities
4. Error handling improvements
`
}]
});
return this.applyOptimizations(workflow, optimization.content[0].text);
}
}
실전 워크플로우 예제
1. 콘텐츠 퍼블리싱 파이프라인
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
// 멀티채널 콘텐츠 퍼블리싱 워크플로우
class ContentPublishingWorkflow {
private workflow = {
id: 'content-publishing',
name: 'Multi-channel Content Publishing',
steps: [
{
id: 'content-analysis',
type: 'claude',
action: async (input: { content: string; metadata: any }) => {
return await this.analyzeContent(input);
}
},
{
id: 'adaptation',
type: 'parallel',
steps: [
{
id: 'adapt-twitter',
action: async (content: AnalyzedContent) => {
return await this.adaptForTwitter(content);
}
},
{
id: 'adapt-linkedin',
action: async (content: AnalyzedContent) => {
return await this.adaptForLinkedIn(content);
}
},
{
id: 'adapt-blog',
action: async (content: AnalyzedContent) => {
return await this.adaptForBlog(content);
}
}
]
},
{
id: 'quality-check',
type: 'claude',
action: async (adaptations: Adaptations) => {
return await this.qualityCheck(adaptations);
}
},
{
id: 'schedule-publishing',
type: 'function',
action: async (approved: ApprovedContent) => {
return await this.schedulePublishing(approved);
}
}
]
};
private async analyzeContent(input: { content: string; metadata: any }) {
const analysis = await claude.createMessage({
system: `Analyze content for multi-channel publishing:
- Extract key messages
- Identify target audience
- Determine tone and style
- Find quotable snippets
- Suggest hashtags and keywords`,
messages: [{
role: 'user',
content: input.content
}]
});
return JSON.parse(analysis.content[0].text);
}
private async adaptForTwitter(content: AnalyzedContent) {
const threads = await claude.createMessage({
system: `Create Twitter thread:
- First tweet: Hook (max 280 chars)
- 3-5 follow-up tweets with key points
- Final tweet: CTA with link
- Include relevant hashtags
- Optimize for engagement`,
messages: [{
role: 'user',
content: JSON.stringify(content)
}]
});
return {
platform: 'twitter',
content: JSON.parse(threads.content[0].text),
scheduledTime: this.calculateOptimalTime('twitter', content.audience)
};
}
private async schedulePublishing(approved: ApprovedContent) {
const schedule = [];
for (const platform of approved.platforms) {
const job = await this.scheduler.schedule({
platform: platform.name,
content: platform.content,
time: platform.scheduledTime,
retryPolicy: {
attempts: 3,
backoff: 'exponential'
}
});
schedule.push(job);
}
return {
scheduled: schedule,
dashboard: `https://dashboard.example.com/campaigns/${approved.campaignId}`
};
}
}
2. 인시던트 대응 자동화
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
// AI 기반 인시던트 대응 워크플로우
class IncidentResponseWorkflow {
async handleIncident(alert: Alert): Promise<IncidentResolution> {
const workflow = new WorkflowExecution('incident-response');
// 1단계: 초기 분석
const analysis = await workflow.execute('initial-analysis', {
alert,
logs: await this.fetchRecentLogs(alert.service),
metrics: await this.fetchMetrics(alert.service, '15m')
});
// 2단계: 심각도 평가
const severity = await workflow.execute('assess-severity', analysis);
// 3단계: 병렬 대응
const responses = await workflow.parallel([
{
id: 'notify-team',
condition: severity.level >= 3,
action: async () => {
return await this.notifyOncall(severity);
}
},
{
id: 'auto-remediation',
condition: severity.autoRemediable,
action: async () => {
return await this.attemptAutoRemediation(analysis);
}
},
{
id: 'gather-context',
action: async () => {
return await this.gatherAdditionalContext(alert);
}
}
]);
// 4단계: 지능형 진단
const diagnosis = await this.aiDiagnosis(analysis, responses);
// 5단계: 실행 계획
const plan = await this.createActionPlan(diagnosis);
// 6단계: 실행 및 모니터링
return await this.executeAndMonitor(plan);
}
private async aiDiagnosis(
analysis: InitialAnalysis,
responses: ParallelResponses
) {
const prompt = `
Diagnose the incident based on:
Alert: ${JSON.stringify(analysis.alert)}
Error patterns: ${JSON.stringify(analysis.errorPatterns)}
Recent changes: ${JSON.stringify(responses.context.recentDeployments)}
Similar incidents: ${JSON.stringify(responses.context.historicalIncidents)}
Provide:
1. Root cause analysis
2. Impact assessment
3. Recommended actions
4. Preventive measures
`;
const diagnosis = await claude.createMessage({
model: 'claude-3-opus-20240229',
messages: [{ role: 'user', content: prompt }],
temperature: 0.3
});
return JSON.parse(diagnosis.content[0].text);
}
private async createActionPlan(diagnosis: Diagnosis) {
// 동적 플레이북 생성
const playbook = await this.generatePlaybook(diagnosis);
return {
immediate: playbook.immediate.map(action => ({
...action,
executor: this.assignExecutor(action),
timeout: this.calculateTimeout(action),
rollback: this.defineRollback(action)
})),
followUp: playbook.followUp,
monitoring: {
metrics: playbook.monitoringMetrics,
duration: playbook.monitoringDuration,
successCriteria: playbook.successCriteria
}
};
}
}
3. 데이터 파이프라인 오케스트레이션
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
// 복잡한 데이터 처리 워크플로우
class DataPipelineOrchestrator {
async runETLPipeline(config: PipelineConfig): Promise<PipelineResult> {
const pipeline = new DistributedWorkflow('etl-pipeline');
// 추출 단계 (병렬)
const extractionTasks = config.sources.map(source => ({
id: `extract-${source.name}`,
type: 'extract',
config: {
source,
partitioning: this.calculatePartitions(source),
validation: this.getValidationRules(source)
}
}));
const extracted = await pipeline.parallel(extractionTasks);
// 변환 단계 (AI 지원)
const transformed = await pipeline.execute('transform', {
data: extracted,
transformations: await this.generateTransformations(extracted)
});
// 품질 검증
const quality = await pipeline.execute('quality-check', {
data: transformed,
rules: config.qualityRules,
aiValidation: true
});
// 조건부 처리
if (quality.score < config.qualityThreshold) {
await pipeline.execute('remediation', {
issues: quality.issues,
data: transformed
});
}
// 로드 단계
const loaded = await pipeline.execute('load', {
data: quality.validData,
destinations: config.destinations,
strategy: 'incremental'
});
return {
summary: loaded,
lineage: pipeline.getLineage(),
metrics: pipeline.getMetrics()
};
}
private async generateTransformations(data: ExtractedData[]) {
// Claude를 사용해 데이터 변환 로직 생성
const sample = this.getSample(data);
const transformations = await claude.createMessage({
system: `Generate data transformation logic:
- Analyze data structure and quality
- Suggest normalization steps
- Create mapping rules
- Define aggregations
Output as executable transformation specs.`,
messages: [{
role: 'user',
content: `Data sample: ${JSON.stringify(sample)}\nTarget schema: ${this.targetSchema}`
}]
});
return this.compileTransformations(transformations.content[0].text);
}
}
고급 기능
1. 워크플로우 버전 관리
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
class WorkflowVersionControl {
private versions: Map<string, WorkflowVersion[]> = new Map();
async deployNewVersion(
workflowId: string,
newVersion: WorkflowDefinition,
strategy: DeploymentStrategy
) {
const currentVersion = await this.getCurrentVersion(workflowId);
switch (strategy) {
case 'canary':
await this.canaryDeploy(workflowId, currentVersion, newVersion);
break;
case 'blue-green':
await this.blueGreenDeploy(workflowId, currentVersion, newVersion);
break;
case 'rolling':
await this.rollingDeploy(workflowId, currentVersion, newVersion);
break;
}
}
private async canaryDeploy(
workflowId: string,
current: WorkflowVersion,
next: WorkflowVersion
) {
// 5% 트래픽으로 시작
await this.router.setWeights(workflowId, {
[current.version]: 0.95,
[next.version]: 0.05
});
// 메트릭 모니터링
const monitor = new CanaryMonitor(workflowId, next.version);
// 점진적 롤아웃
for (const percentage of [10, 25, 50, 75, 100]) {
await this.wait('5m');
const metrics = await monitor.getMetrics();
if (metrics.errorRate > current.metrics.errorRate * 1.1) {
await this.rollback(workflowId, current.version);
throw new Error('Canary deployment failed');
}
await this.router.setWeights(workflowId, {
[current.version]: (100 - percentage) / 100,
[next.version]: percentage / 100
});
}
}
}
2. 워크플로우 최적화 엔진
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
class WorkflowOptimizer {
async optimizePerformance(
workflow: WorkflowDefinition,
executionHistory: ExecutionRecord[]
): Promise<OptimizedWorkflow> {
// 병목 지점 분석
const bottlenecks = this.identifyBottlenecks(executionHistory);
// AI 기반 최적화 제안
const suggestions = await this.getSuggestions(workflow, bottlenecks);
// 최적화 적용
const optimized = this.applyOptimizations(workflow, suggestions);
// 시뮬레이션
const simulation = await this.simulate(optimized, executionHistory);
return {
workflow: optimized,
expectedImprovement: simulation.improvement,
changes: suggestions.applied
};
}
private identifyBottlenecks(history: ExecutionRecord[]) {
const stepDurations = new Map<string, number[]>();
// 각 스텝의 실행 시간 수집
history.forEach(execution => {
execution.steps.forEach(step => {
if (!stepDurations.has(step.id)) {
stepDurations.set(step.id, []);
}
stepDurations.get(step.id)!.push(step.duration);
});
});
// 통계 분석
return Array.from(stepDurations.entries())
.map(([stepId, durations]) => ({
stepId,
avgDuration: avg(durations),
p95Duration: percentile(durations, 95),
variance: variance(durations)
}))
.filter(stat => stat.p95Duration > 5000) // 5초 이상
.sort((a, b) => b.avgDuration - a.avgDuration);
}
}
모니터링과 관찰성
워크플로우 대시보드
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class WorkflowDashboard {
getMetrics(): DashboardMetrics {
return {
overview: {
totalExecutions: this.getTotalExecutions(),
successRate: this.getSuccessRate(),
avgDuration: this.getAverageDuration(),
activeWorkflows: this.getActiveWorkflows()
},
performance: {
throughput: this.getThroughput(),
latency: this.getLatencyPercentiles(),
queueDepth: this.getQueueDepth(),
workerUtilization: this.getWorkerUtilization()
},
errors: {
errorRate: this.getErrorRate(),
topErrors: this.getTopErrors(),
failedSteps: this.getFailedSteps()
},
cost: {
apiCalls: this.getAPICalls(),
computeTime: this.getComputeTime(),
estimatedCost: this.estimateCost()
}
};
}
}
다음 편 예고
다음 편에서는 “팀 협업 환경에서의 활용”을 다룰 예정입니다. Claude를 팀 전체가 효과적으로 활용하는 방법과 협업 도구 구축을 알아보겠습니다.
💡 오늘의 과제: 자신의 업무 중 반복적인 프로세스를 하나 선택해 간단한 워크플로우로 자동화해보세요. Claude API를 활용해 지능적인 의사결정을 포함시켜보세요!
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.