> For the complete documentation index, see [llms.txt](https://docs.roboflow.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.roboflow.com/workflows/ko/build/build-a-workflow.md).

# 워크플로 빌드

워크플로는 블록들로 구성되며, 각 블록은 모델 추론 실행, 로직 수행, 외부 서비스와의 연동 같은 특정 작업을 수행합니다.

사용 가능한 블록 목록을 더 자세히 살펴보려면, 우리의 [블록 문서](/workflows/ko/blocks/blocks.md).

### 개요

이 가이드에서는 객체 감지 모델을 실행하고, 예측 개수를 세고, 모델 결과를 시각화하는 4개 블록 워크플로를 만드는 방법을 살펴봅니다. 아래의 [최종 워크플로 템플릿](https://app.roboflow.com/workflows/embed/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ3b3JrZmxvd0lkIjoiMmdqakJxMDV3Q01ac1hHM3hkeFAiLCJ3b3Jrc3BhY2VJZCI6ImtyT1RBYm5jRmhvUU1DZExPbGU0IiwidXNlcklkIjoiSW1GTElaU2tHYk55OXpiNFV1cWxNelBScHBRMiIsImlhdCI6MTczODE4ODk5MH0.f72WI5bdjtnwC8iqXF_XiUVarfOktIAH1egpsI0Oh4Q) 을 따라 해 보세요.

{% embed url="<https://app.roboflow.com/workflows/embed/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ3b3JrZmxvd0lkIjoiMmdqakJxMDV3Q01ac1hHM3hkeFAiLCJ3b3Jrc3BhY2VJZCI6ImtyT1RBYm5jRmhvUU1DZExPbGU0IiwidXNlcklkIjoiSW1GTElaU2tHYk55OXpiNFV1cWxNelBScHBRMiIsImlhdCI6MTczODE4ODk5MH0.f72WI5bdjtnwC8iqXF_XiUVarfOktIAH1egpsI0Oh4Q>" fullWidth="false" %}

<figure><img src="/files/ff2c22b1d53d91dfdbf548623e55786382f51714" alt="" width="563"><figcaption><p>감지, 카운트 및 시각화 워크플로</p></figcaption></figure>

### 블록 연결

구성을 시작하기 전에 블록 연결이 어떻게 작동하는지 이해하는 것이 중요합니다.

특정 위치에 블록을 추가하려면, 이전 블록을 입력으로 사용해야 합니다. 예를 들어, 위에 표시된 워크플로에서 *속성 정의* 블록은 *객체 감지* 블록 뒤에 위치합니다. 이는 모델 블록을 입력으로 사용하기 때문입니다.  *바운딩 박스 시각화* 블록은 오른쪽에 있습니다. 왜냐하면 *속성 정의* 블록의 출력을 사용하지는 않지만, 모델 출력을 참조하기는 하기 때문입니다.

<figure><img src="/files/78c722a43e1c8a749f4404aaa27b8d95d501b0ec" alt=""><figcaption><p>모델 비교 워크플로</p></figcaption></figure>

위의 예시 워크플로에는 네 개의 서로 다른 경로가 있습니다. 각 분기는 런타임에 병렬로 실행되고, 다른 분기 블록들을 입력으로 사용하지 않기 때문입니다.

### 빌더 어시스트

빌더 어시스트는 블록을 연결하고 삽입할 때 워크플로 편집기가 얼마나 많은 도움을 줄지 제어합니다. 오른쪽 상단 탐색 바의 토글을 사용해 모드를 전환할 수 있습니다.

세 가지 모드가 있습니다:

* **자동** (기본값): 블록이 연결되거나 삽입될 때 호환되는 입력 및 출력 필드를 자동으로 연결합니다. 또한 블록을 제거하거나 연결을 해제하면 빌더가 하위 참조를 복구합니다.
* **빠름**: 제안된 연결과 블록 추천을 표시하지만, 사용자가 명시적으로 수락할 때만 적용합니다. 빌더가 대신 변경을 가하지 않으면서 안내를 받고 싶을 때 유용합니다.
* **수동**: 제안도 없고 자동 연결도 없습니다. 모든 연결을 직접 제어합니다.

선택한 모드는 로컬에 저장되므로 세션 간에도 유지됩니다.

### 블록 정렬

워크플로 편집기가 블록의 위치를 자동으로 잡아줄 수 있습니다. 현재 블록들을 정렬하고 화면에 맞추려면 자동 레이아웃 버튼(편집기 툴바의 사이트맵 아이콘)을 클릭하세요.

버튼 옆의 화살표를 누르면 다음 두 가지 옵션이 있는 메뉴가 열립니다:

* “지금 정렬”: 버튼을 클릭했을 때와 동일하게 레이아웃을 한 번 실행합니다.
* “자동으로 정렬”: 켜져 있으면 블록을 추가하거나 연결을 변경할 때마다 편집기가 블록을 다시 정렬합니다. 블록을 드래그하면 이 모드가 일시 중지되어, 수동으로 배치한 레이아웃이 유지됩니다.

선택은 워크플로별로 로컬에 저장됩니다.

### 워크플로 만들기

#### 객체 감지 모델

먼저 *객체 감지 모델* 블록을 추가하세요. YOLOv8n처럼 [COCO](https://universe.roboflow.com/microsoft/coco)로 학습된 공개 사전 학습 모델과 작업 공간의 미세 조정 모델 중에서 선택할 수 있습니다. 여기서는 사람과 차량을 감지하기 위해 사전 학습된 *yolov8n* 모델을 사용하겠습니다.

<figure><img src="/files/9e0eae793f99836f04e40a34e6c9fed1b9ff5d22" alt="" width="344"><figcaption></figcaption></figure>

객체 감지 블록에는 모델이 무엇을 추론할지 결정하는 필수 이미지 매개변수가 있습니다. 여러 선택적 매개변수가 있으며, 핵심 항목은 아래에 자세히 설명되어 있습니다:

* 클래스 필터: 모델이 반환할 클래스 목록입니다. 참고: 모델은 항상 자신이 학습된 클래스만 반환하며, 이를 통해 불필요한 클래스를 걸러낼 수 있습니다.
* 신뢰도: 해당 신뢰도보다 낮은 객체는 반환되지 않습니다.
* IoU 임계값: 임계값이 높을수록 더 많이 겹치는 예측이 반환됩니다. 0.9는 90% 이하로 겹치는 객체가 반환됨을 의미하고, 0.1은 10%보다 더 많이 겹치는 객체는 포함되지 않음을 의미합니다.
* 최대 감지 수: 모델이 반환할 객체의 최대 개수
* 클래스 비의존 NMS: 겹침 필터링이 같은 클래스의 객체만 비교하고 제외할지, 아니면 모든 클래스를 비교하고 제외할지

#### 속성 정의

속성 정의 블록을 사용하면 이미지 크기, 예측 클래스, 감지된 객체 수와 같이 데이터에서 관련 정보를 추출할 수 있습니다. 이 예시에서는 객체 감지 모델이 찾은 객체 수를 세겠습니다.

<figure><img src="https://lh7-rt.googleusercontent.com/docsz/AD_4nXc507UbRnkEH6XMdrfmwVZbHcK6x6K5THwnt1RmEk8iXSojwvmiA_q6KwRXV9bJudYnW7NMTQKKb9GqGxm_P0VjbuOoGWcDsM5NoQckl9jV4YcjYQFIvYoCgvd_YnQTNJLlwdbZwA?key=yGJPQzp1abf4J7pT0mnBw8w4" alt="" width="375"><figcaption></figcaption></figure>

해당 *데이터* 속성에는 모델 예측을 참조하세요.  *작업*,에서 항목 수 세기를 선택하세요. 이 구성은 객체 감지 모델이 생성한 예측 수를 반환합니다.

#### 바운딩 박스 시각화

모델 결과를 시각화하려면 바운딩 박스 시각화 블록을 추가하세요.  *이미지* 매개변수에는 입력 이미지를 선택하세요. 예측에는 모델 결과를 선택하세요. 선택적 구성 속성을 사용해 바운딩 박스의 색상과 크기를 변경할 수도 있습니다.

<figure><img src="/files/a6765b1ec83b186257225f0b2d569a78070257c8" alt="" width="342"><figcaption></figcaption></figure>

#### Label Visualization

바운딩 박스를 그리는 것 외에도 예측의 클래스 이름도 표시하고 싶습니다. 그러려면 바운딩 박스 시각화 뒤에 *Label Visualization* 블록을 추가하세요. 같은 이미지에 바운딩 박스와 레이블을 모두 그리려면 참조 입력 이미지를 *bounding\_box\_visualization* 이미지로 설정하고 입력 이미지를 참조하지 않아야 합니다. 이렇게 하면 레이블이 바운딩 박스 위에 그려집니다.

<figure><img src="/files/b18034e74bf49cf6adbb57f8443dcab2df05073c" alt="" width="343"><figcaption></figcaption></figure>

선택적 *텍스트* 매개변수를 변경하면 표시 텍스트를 클래스 이름, 신뢰도, 또는 클래스 이름과 신뢰도 중에서 바꿀 수 있습니다.

### 변경 사항 저장

변경 내용을 초안으로 저장하려면 “저장”을 클릭하세요. 워크플로 편집기는 편집 중에 자동 저장하지 않습니다.

변경 사항을 실제로 반영하려면 워크플로를 게시하세요. 워크플로를 배포한 상태라면, 게시된 버전이 워크플로가 배포된 모든 기기에서 실행되기 시작합니다.

이제 완성된 워크플로가 있으니, 테스트할 차례입니다.

### 예시: 두 단계 워크플로

단일 모델 워크플로에 익숙해지면, 다음으로 흔한 패턴은 첫 번째 모델의 출력에 두 번째 모델을 연결하는 것입니다. 이 예시는 개를 감지하고, 각 감지를 잘라낸 뒤, 각 잘라낸 이미지의 품종을 분류한 다음, 그 품종을 원래 바운딩 박스 위에 다시 기록합니다.

1. **객체 감지 모델** - 블록을 추가하고 `rfdetr-small` 모델을 선택하세요.
2. **동적 자르기** - 첫 번째 모델이 찾은 객체를 잘라냅니다. 해당 *이미지* 속성을 워크플로 입력 이미지에,  *예측* 속성을 감지 모델의 예측에 맞추세요.
3. **분류 모델** - 각 잘라낸 이미지에서 실행합니다. Roboflow Universe 모델 `dog-breed-xpaq6/1` 을 사용하고 블록의 *이미지* 속성을 `잘라낸 이미지` Dynamic Crop 블록의 출력에 연결하세요.
4. **감지 클래스 대체** - 각 잘라낸 이미지의 예측 클래스를 해당 바운딩 박스에 다시 할당합니다. 여기서는 객체 감지 예측에 대한 참조와 분류 결과에 대한 참조를 사용합니다.
5. **바운딩 박스 시각화** 다음으로 **Label Visualization** - 둘을 연결하세요. 첫 번째는 `$inputs.image` 을 읽고, 두 번째는 첫 번째의 출력 이미지를 읽습니다. 둘 다 Detections Classes Replacement 단계의 예측을 참조합니다.
6. **출력** - 대체된 클래스 감지 결과와 최종 시각화를 선택하세요.

<figure><img src="https://media.roboflow.com/inference/workflow_visualisation_result.png" alt="Dog breed classification result"><figcaption><p>두 단계 워크플로 결과</p></figcaption></figure>

잘라낸 이미지가 입력 이미지보다 한 단계 더 깊게 위치하기 때문에, 분류 결과는 각 이미지 결과 안에 중첩됩니다. 이 중첩이 어떻게 작동하는지는 [워크플로 실행](/workflows/ko/developer-guide/developer-guide/workflow-execution.md) 를 참조하세요.

<details>

<summary>이 예시의 워크플로 정의</summary>

워크플로를 재현하려면 이를 편집기에 붙여넣으세요.

```json
{
  "version": "1.0",
  "inputs": [
    {
      "type": "InferenceImage",
      "name": "image"
    }
  ],
  "steps": [
    {
      "type": "roboflow_core/roboflow_object_detection_model@v1",
      "name": "model",
      "images": "$inputs.image",
      "model_id": "rfdetr-small"
    },
    {
      "type": "roboflow_core/dynamic_crop@v1",
      "name": "dynamic_crop",
      "images": "$inputs.image",
      "predictions": "$steps.model.predictions"
    },
    {
      "type": "roboflow_core/roboflow_classification_model@v1",
      "name": "model_1",
      "images": "$steps.dynamic_crop.crops",
      "model_id": "dog-breed-xpaq6/1"
    },
    {
      "type": "roboflow_core/detections_classes_replacement@v1",
      "name": "detections_classes_replacement",
      "object_detection_predictions": "$steps.model.predictions",
      "classification_predictions": "$steps.model_1.predictions"
    },
    {
      "type": "roboflow_core/bounding_box_visualization@v1",
      "name": "bounding_box_visualization",
      "predictions": "$steps.detections_classes_replacement.predictions",
      "image": "$inputs.image"
    },
    {
      "type": "roboflow_core/label_visualization@v1",
      "name": "label_visualization",
      "predictions": "$steps.detections_classes_replacement.predictions",
      "image": "$steps.bounding_box_visualization.image"
    }
  ],
  "outputs": [
    {
      "type": "JsonField",
      "name": "detections",
      "coordinates_system": "own",
      "selector": "$steps.detections_classes_replacement.predictions"
    },
    {
      "type": "JsonField",
      "name": "visualisation",
      "coordinates_system": "own",
      "selector": "$steps.label_visualization.image"
    }
  ]
}
```

</details>

위 JSON의 문법을 배우려면 [Workflow Definition 문법](/workflows/ko/developer-guide/developer-guide/definitions.md).
