[{"data":1,"prerenderedAt":327},["ShallowReactive",2],{"post-document:\u002Fdeep_learning\u002Fllm\u002F2026\u002F08\u002F19\u002Fllm-workflow-patterns\u002F":3},{"id":4,"title":5,"body":6,"categories":307,"date":310,"description":311,"extension":312,"image":313,"key_concepts":313,"last_modified_at":313,"legacyPath":314,"meta":315,"navigation":317,"part":313,"path":318,"published":317,"robots":313,"seo":319,"series":313,"stem":320,"strengths":313,"summary":321,"tags":322,"tradeoffs":313,"__hash__":326},"posts\u002Fposts\u002FDeep_Learning\u002F2026-08-19-llm-workflow-patterns.md","현대 LLM 워크플로의 패턴",{"type":7,"value":8,"toc":299},"minimark",[9,13,20,23,28,88,92,103,106,109,115,118,140,144,150,153,157,160,166,169,175,186,190,193,199,202,205,211,217,223,226,231,234,237,264,267,271,295],[10,11,5],"h1",{"id":12},"현대-llm-워크플로의-패턴",[14,15,16],"blockquote",{},[17,18,19],"p",{},"LLM 서비스는 도대체 어떻게 작동하는 걸까? 궁금해서 참을 수가 없단 말이지!",[17,21,22],{},"LLM 애플리케이션을 만들 때는 요청을 한 번 받고 바로 답을 내는 경우도 있지만, 실제로는 입력을 분류하고, 작업을 나누고, 결과를 평가하는 흐름으로 구성하는 경우가 많다.",[24,25,27],"h2",{"id":26},"자주-나오는-workflow-패턴","자주 나오는 Workflow 패턴",[29,30,31,44],"table",{},[32,33,34],"thead",{},[35,36,37,41],"tr",{},[38,39,40],"th",{},"패턴",[38,42,43],{},"설명",[45,46,47,56,64,72,80],"tbody",{},[35,48,49,53],{},[50,51,52],"td",{},"Routing",[50,54,55],{},"입력을 분류해서 적절한 처리 경로 하나를 선택한다.",[35,57,58,61],{},[50,59,60],{},"Parallelization",[50,62,63],{},"서로 의존하지 않는 AI 작업을 동시에 실행한다.",[35,65,66,69],{},[50,67,68],{},"Evaluator-Optimizer",[50,70,71],{},"결과를 평가하고 피드백을 기반으로 반복 개선한다.",[35,73,74,77],{},[50,75,76],{},"Orchestrator-Workers",[50,78,79],{},"큰 작업을 여러 하위 작업으로 분해하고 각각 처리한 후 합친다.",[35,81,82,85],{},[50,83,84],{},"Chaining",[50,86,87],{},"앞 단계의 출력을 다음 단계의 입력으로 연결한다.",[24,89,91],{"id":90},"개념적으로-이런-구조","개념적으로 이런 구조",[93,94,100],"pre",{"className":95,"code":97,"language":98,"meta":99},[96],"language-text","사용자 요청\n  ↓\nRouting\n  ↓\n계획 \u002F 작업 분해\n  ↓\n┌───────────────┐\n│ Worker A      │\n│ Worker B      │\n│ Worker C      │\n└───────────────┘\n  ↓\n결과 통합\n  ↓\nEvaluator\n  ↓\n필요하면 재시도\n  ↓\n최종 응답\n","text","",[101,102,97],"code",{"__ignoreMap":99},[17,104,105],{},"이건 지금도 LLM 애플리케이션에서 아주 전형적인 구조다.",[17,107,108],{},"다만, 실제 현대 시스템에서는 여기에 보통 다음 요소가 추가된다.",[93,110,113],{"className":111,"code":112,"language":98,"meta":99},[96],"LLM Workflow\n  + Tool Calling\n  + RAG\n  + Memory \u002F State\n  + Retry \u002F Timeout\n  + Observability\n  + Guardrails\n  + Model Selection\n  + Caching\n",[101,114,112],{"__ignoreMap":99},[17,116,117],{},"현대적인 구조에서는 Spring Boot에서 했던 기능에 더해 다음과 같은 Tool을 사용할 수 있다.",[119,120,121,125,128,131,134,137],"ul",{},[122,123,124],"li",{},"웹 검색",[122,126,127],{},"DB 조회",[122,129,130],{},"사내 문서 검색",[122,132,133],{},"Python 실행",[122,135,136],{},"API 호출",[122,138,139],{},"파일 읽기",[24,141,143],{"id":142},"요즘은-이런-것도-만들-수-있다","요즘은 이런 것도 만들 수 있다",[93,145,148],{"className":146,"code":147,"language":98,"meta":99},[96],"사용자\n  ↓\nRouter\n  ↓\nPlanner\n  ↓\nWorkers\n  ├─ Search Agent\n  ├─ SQL Agent\n  ├─ Code Agent\n  └─ Document Agent\n  ↓\nAggregator\n  ↓\nEvaluator\n  ↓\nFinal Answer\n",[101,149,147],{"__ignoreMap":99},[17,151,152],{},"이런 형태가 된다.",[24,154,156],{"id":155},"정해진-로직으로-처리하는-workflow","정해진 로직으로 처리하는 Workflow",[17,158,159],{},"다만 나는 로직을 정해놓았는데,",[93,161,164],{"className":162,"code":163,"language":98,"meta":99},[96],"분류\n  → switch\n  → 특정 처리\n",[101,165,163],{"__ignoreMap":99},[17,167,168],{},"또는",[93,170,173],{"className":171,"code":172,"language":98,"meta":99},[96],"계획\n  → worker 실행\n  → 통합\n",[101,174,172],{"__ignoreMap":99},[17,176,177,178,181,182,185],{},"이런 방식으로 처리한다면 ",[101,179,180],{},"deterministic workflow"," 또는 ",[101,183,184],{},"LLM workflow","라고 생각하면 된다.",[24,187,189],{"id":188},"llm이-다음-행동을-직접-선택하는-agent","LLM이 다음 행동을 직접 선택하는 Agent",[17,191,192],{},"다만 모던한 Agentic 시스템은 조금 다르게 동작한다.",[93,194,197],{"className":195,"code":196,"language":98,"meta":99},[96],"LLM: \"검색이 필요하겠군\"\n  ↓\n검색 Tool 호출\n  ↓\nLLM: \"정보가 부족하군\"\n  ↓\n다른 Tool 호출\n  ↓\nLLM: \"이제 답할 수 있겠다\"\n",[101,198,196],{"__ignoreMap":99},[17,200,201],{},"이렇게 LLM이 알아서 다음 행동을 스스로 선택한다.",[17,203,204],{},"요즘은 이런 식으로 가는 중이다.",[93,206,209],{"className":207,"code":208,"language":98,"meta":99},[96],"고정 Workflow                                      자율 Agent\n──────────────────────────────────────────────────────→\nChaining\nRouting\nParallel\nEvaluator\nOrchestrator\n                      Tool Calling\n                              Planner\n                                      Agent Loop\n",[101,210,208],{"__ignoreMap":99},[17,212,213,216],{},[101,214,215],{},"WorkflowPatterns.java","에서 생각해볼 수 있는 위치는 다음과 같다.",[93,218,221],{"className":219,"code":220,"language":98,"meta":99},[96],"Chaining\nRouting\nParallel\nEvaluator\nOrchestrator\n        ↑\n     현재 위치\n",[101,222,220],{"__ignoreMap":99},[17,224,225],{},"자율 Agent를 만드는 것보다 가능하면 Workflow로 통제하고, 필요한 부분만 Agent화하는 방식이 안정성, 비용, 디버깅 측면에서 훨씬 유리한 경우가 있다.",[14,227,228],{},[17,229,230],{},"항상 자유가 좋은 결과를 내주는 것은 아니다.",[17,232,233],{},"가끔은 행동에 제약을 걸어서 예측 가능한 결과를 낼 수 있어야 한다.",[17,235,236],{},"예를 들어 다음처럼 반복 횟수를 Java 코드에서 제한하는 것은 상당히 프로덕션 지향적인 사고다.",[93,238,242],{"className":239,"code":240,"language":241,"meta":99,"style":99},"language-java shiki shiki-themes github-light github-dark","for (int round = 1; round \u003C= maxRounds; round++) {\n    \u002F\u002F 작업 실행과 평가\n}\n","java",[101,243,244,252,258],{"__ignoreMap":99},[245,246,249],"span",{"class":247,"line":248},"line",1,[245,250,251],{},"for (int round = 1; round \u003C= maxRounds; round++) {\n",[245,253,255],{"class":247,"line":254},2,[245,256,257],{},"    \u002F\u002F 작업 실행과 평가\n",[245,259,261],{"class":247,"line":260},3,[245,262,263],{},"}\n",[17,265,266],{},"LLM에게 그냥 \"좋아질 때까지 반복해\"라고 하는 것은 결과를 예측하기도 어렵고, 무한 루프 문제가 생길 수도 있다.",[24,268,270],{"id":269},"학습-순서","학습 순서",[272,273,274,277,280,283,286,289,292],"ol",{},[122,275,276],{},"Tool Calling",[122,278,279],{},"RAG",[122,281,282],{},"Memory \u002F State",[122,284,285],{},"Agent Loop",[122,287,288],{},"Observability",[122,290,291],{},"Guardrails",[122,293,294],{},"Model Routing",[296,297,298],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":99,"searchDepth":254,"depth":254,"links":300},[301,302,303,304,305,306],{"id":26,"depth":254,"text":27},{"id":90,"depth":254,"text":91},{"id":142,"depth":254,"text":143},{"id":155,"depth":254,"text":156},{"id":188,"depth":254,"text":189},{"id":269,"depth":254,"text":270},[308,309],"Deep_Learning","LLM","2026-08-19 00:00:00 +0900","Routing, Chaining, Parallelization, Evaluator-Optimizer, Orchestrator-Workers와 Agent Loop의 차이를 정리한다.","md",null,"\u002Fdeep_learning\u002Fllm\u002F2026\u002F08\u002F19\u002Fllm-workflow-patterns\u002F",{"layout":316},"post",true,"\u002Fposts\u002Fdeep_learning\u002F2026-08-19-llm-workflow-patterns",{"title":5,"description":311},"posts\u002FDeep_Learning\u002F2026-08-19-llm-workflow-patterns","LLM Workflow의 주요 패턴과 자율 Agent를 통제하는 방법을 정리한다.",[323,309,324,325],"Deep Learning","Workflow","Agent","OfoSMNsx27brKHj0YiqTO6GvheMrVnJv5RUt-TpJ9u8",1788744788465]