VNRequest — 개요, iOS에서 Vision 요청의 작동 원리

저자: IT Sectr 게시일: 2026-07-20 읽는 시간: 8 분

VNRequest 는 Vision 프레임워크의 추상 기본 클래스로, 이미지 또는 비디오 스트림 분석의 단위를 나타냅니다. 각 유형의 분석 — 얼굴 감지, 텍스트 인식, 바코드 검색, 분류 — 은 VNRequest의 구체적인 하위 클래스로 구현되어 있습니다. Apple Developer Documentation (2024)에 따르면, 개발자는 요청 인스턴스를 생성하고, 매개변수를 구성하며, VNImageRequestHandler를 통해 이미지를 전달하고, VNObservation의 배열로 결과를 받습니다.

주요 포인트

  • VNRequest — 모든 Vision 요청의 기본 클래스: 이미지 분석, 비디오 및 ML 모델.
  • 요청은 VNImageRequestHandler(이미지) 또는 VNSequenceRequestHandler(비디오)를 통해 실행됩니다.
  • 결과는 VNObservation의 배열로 반환됩니다 — 각 하위 클래스는 특정 데이터를 포함합니다.
  • Completion handler를 통해 분석 완료 후 결과를 비동기적으로 처리할 수 있습니다.
  • 하나의 이미지에 대해 handler.perform()의 단일 호출로 여러 요청을 실행할 수 있습니다.

Vision에서 VNRequest란?

VNRequest 는 Vision 아키텍처의 기본 요소로, 이미지 및 비디오 분석을 위한 요청-응답 패턴을 구현합니다. VNRequest의 각 하위 클래스는 컴퓨터 비전의 특정 작업을 담당합니다: 얼굴 감지, 텍스트 인식, 콘텐츠 분류.

VNRequest 아키텍처는 “무엇을 분석할것인가”(요청)를 “어떻게 처리할것인가”(핸들러)와 분리합니다. 개발자는 요청(분석 유형, 추가 매개변수)을 구성하고 이미지와 함께 핸들러에 전달합니다. 핸들러는 요청을 실행하고 결과를 반환하며, 개발자가 내부 ML 알고리즘을 이해할 필요가 없습니다.

VNRequest의 모든 하위 클래스는 통일된 구조를 따릅니다: 선택적 completion handler로 초기화, 특성 구성(관심 영역, 정확도 레벨), 그리고 핸들러에 전달. 이를 통해 API가 예측 가능하고 쉬운 확장이 가능합니다 — 새 분석 유형을 추가하는 것은 새로운 VNRequest 하위 클래스를 생성하는 것입니다.

swift
import Vision

// 1. 요청 생성
let request = VNDetectFaceRectanglesRequest { req, _ in
    // 3. 결과 처리
    guard let faces = req.results as? [VNFaceObservation]
    else { return }
    print("Found \\(faces.count) faces")
}

// 2. 핸들러를 통해 실행
let handler = VNImageRequestHandler(cgImage: cgImage, options: [:])
try handler.perform([request])

VNRequest의 주요 특성: regionOfInterest(분석을 가속하기 위한 이미지의 관심 영역), preferBackgroundProcessing(백그라운드 모드), revision(알고리즘 버전) 및 cancellationSupport. 이 특성들을 적절히 구성하면 특정 작업에 대한 성능을 최적화할 수 있습니다.

Apple WWDC 2024에 따르면, Vision이 존재한 7년 동안 사용 가능한 VNRequest 하위 클래스 수는 8개(iOS 11)에서 25개 이상(iOS 18)으로 증가하여 모바일 기기에서의 모든 주요 컴퓨터 비전 작업을 다루고 있습니다.

분석을 위한 VNRequest의 개발자 유형

Vision에는 25개 이상의 VNRequest 하위 클래스가 포함되어 있으며, 감지, 인식, 추적 및 분류 카테고리로 나뉕니다. 각 하위 클래스는 VNRequest를 상속받고 작업 구체적인 특성을 추가합니다.

감지 및 인식

VNDetectFaceRectanglesRequest — 이미지에서 얼굴 감지. 바운딩 박스 좌표와 확신도가 있는 VNFaceObservation을 반환합니다. VNDetectHumanRectanglesRequest — 사람에 대해서도 유사. VNDetectHumanBodyPoseRequest — 인체 자세 추정(골격 포인트).

텍스트 분석

VNRecognizeTextRequest — 13개 언어와 두 가지 정확도 레벨을 지원하는 텍스트 인식. VNReadCodeRequest — 전문 코드용. VNDetectTextRectanglesRequest — 인식 없이 텍스트 영역 검색(더 빠르지만, 직사각형만).

분류 및 분석

VNClassifyImageRequest — 1,000개 ImageNet 카테고리로 이미지 분류. VNGenerateImageFeaturePrintRequest — 이미지 비교를 위한 특징 벡터 추출. VNDetectContoursRequest — 객체 외곽 감지.

카테고리예시 요청결과
얼굴 감지VNDetectFaceRectanglesRequestVNFaceObservation
텍스트 인식VNRecognizeTextRequestVNRecognizedTextObservation
바코드VNDetectBarcodesRequestVNBarcodeObservation
분류VNClassifyImageRequestVNClassificationObservation
추적VNTrackObjectRequestVNDetectedObjectObservation
외곽VNDetectContoursRequestVNContoursObservation

VNImageRequestHandler 및 VNSequenceRequestHandler

VNImageRequestHandler — 정지 이미지를 위한 핸들러. CGImage, CIImage 또는 Data(JPEG/PNG)를 수락하고 하나 이상의 VNRequest 인스턴스를 실행합니다. 사진, 스크린샷 및 업로드된 이미지에 Vision을 사용하는 주요 방법입니다.

VNSequenceRequestHandler — 이미지 시퀀스(비디오 프레임)를 위한 핸들러. 동일한 이미지 유형 집합을 수락하지만, 프레임 간의 상태를 유지하면서 프레임 단위로 처리하도록 설계되었습니다(객체 추적에 필요).

swift
// 단일 이미지용 VNImageRequestHandler
let imageHandler = VNImageRequestHandler(
    cgImage: cgImage,
    orientation: orientation,
    options: [:])

// 비디오용 VNSequenceRequestHandler
let sequenceHandler = VNSequenceRequestHandler()
try sequenceHandler.perform([trackingRequest],
    on: cgImage)

중요한 차이점: VNSequenceRequestHandler는 여러 요청의 병렬 실행을 지원하지 않습니다 — 각 perform() 호출은 한 프레임에 대한 한 집합의 요청을 처리합니다. 멀티쓰레드 비디오 처리를 위해서는 다른 쓰레드에 대한 별도의 핸들러 인스턴스를 생성하세요.

VNImageRequestHandler는 백그라운드 큐에서 실행할 수 있습니다. Apple은 대화형 시나리오(사용자가 결과를 기다리는 경우)에는 DispatchQueue.global(qos: .userInitiated)를, 일괄 처리(예: 전체 사진 라이브러리 분석)에는 .background를 권장합니다.

VNObservation: 결과 구조

VNObservation — 모든 Vision 요청 결과의 기본 클래스. VNObservation의 각 하위 클래스는 분석 유형에 특정된 데이터를 포함합니다: 바운딩 박스 좌표, 인식된 텍스트, 확신도, 고유 식별자(uuid) 및 시간 스탬프(timeRange).

VNObservation의 주요 하위 클래스: VNFaceObservation(바운딩 박스와 랜드마크가 있는 얼굴 감지 결과), VNRecognizedTextObservation(후보가 있는 인식된 텍스트), VNBarcodeObservation(펜로드와 심볼로지가 있는 디코딩된 바코드), VNClassificationObservation(확신도가 있는 분류 카테고리).

swift
func handleTextResults(request: VNRequest) {
    guard let observations = request.results
        as? [VNRecognizedTextObservation]
    else { return }

    for observation in observations {
        let bbox = observation.boundingBox
        let text = observation.topCandidates(1).first ?? ""
        print("\\(text) at \\(bbox)")
    }
}

확신도 특성(0.0부터 1.0까지)은 모든 VNObservation 인스턴스에 존재하며 결과에 대한 모델의 확신도를 나타냅니다. Apple은 대부분의 작업에서 확신도 < 0.5인 관찰 결과를 거절할 것을 권장합니다. 중요 애플리케이션(의료, 보안)의 경우 임계값을 0.8–0.9로 높여야 합니다.

VNObservation에는 timeRange(비디오 요청용)와 uuid(프레임 간 매칭을 위한 고유 ID)도 포함됩니다. 이를 통해 비디오 프레임 시퀀스에서 동일한 객체(예: 얼굴)를 추적할 수 있습니다.

여러 요청 동시 실행

VNRequest의 주요 장점 중 하나는 단일 handler.perform() 호출에서 동일한 이미지에 대해 여러 다른 요청을 실행할 수 있다는 점입니다. Vision은 내부적으로 실행 순서를 최적화하고 공통 계산(예: 이미지 전처리)을 재사용합니다.

이를 통해 한 번의 패스로 이미지에 대한 완전한 데이터 집합을 얻을 수 있습니다: 동시에 얼굴을 감지하고, 텍스트를 인식하고, 바코드를 찾고, 콘텐츠를 분류합니다. 이 접근 방식은 각 요청을 순차적으로 호출하는 것보다 훨씬 더 효율적입니다.

swift
import Vision

// 하나의 배열에서 여러 요청
let faceRequest = VNDetectFaceRectanglesRequest()
let textRequest = VNRecognizeTextRequest()
let barcodeRequest = VNDetectBarcodesRequest()
let classifyRequest = VNClassifyImageRequest()

let handler = VNImageRequestHandler(cgImage: cgImage, options: [:])
try handler.perform([
    faceRequest,
    textRequest,
    barcodeRequest,
    classifyRequest
])

// 각 요청에서 결과 액세스
print("Faces: \\(faceRequest.results?.count ?? 0)")
print("Text blocks: \\(textRequest.results?.count ?? 0)")

제한 사항: 모든 요청이 다른 요청과 결합할 수 있는 것은 아닙니다. 예를 들어, VNGenerateImageFeaturePrintRequest는 별도로 실행해야 합니다. Apple은 유형(감지, 인식, 분류)별로 요청을 그룹화하고 대상 기기에서 조합을 테스트할 것을 권장합니다.

성능: 한 perform()에서 3–4개의 요청을 결합하면 순차 실행보다 30–40% 빠릅니다. Vision이 공유 ML 계산과 이미지 전처리(스케일링, 색상 보정)를 재사용하기 때문입니다.

VNCoreMLRequest를 통한 사용자 지정 요청

VNCoreMLRequest는 Core ML과 Vision 사이의 교럭으로, 모든 Core ML 모델을 Vision 요청으로 실행할 수 있게 해줍니다. 모델은 VNCoreMLModel에 래핑되고 VNCoreMLRequest에 전달되며, Vision이 자동으로 이미지 전처리(스케일링, 모델 입력 크기로 크로핑)를 처리합니다.

VNCoreMLRequest는 VNRequest를 상속받으므로 모든 표준 기능을 지원합니다: regionOfInterest, completion handler, 여러 요청. 이를 통해 사용자 지정 ML 모델을 내장 Vision 감지기와 단일 파이프라인에서 결합할 수 있습니다.

swift
import Vision
import CoreML

// Core ML 모델 래핑
guard let mlModel = try VNCoreMLModel(
    for: MyCustomClassifier().model)
else { return }

// VNCoreMLRequest 생성
let coreMLRequest = VNCoreMLRequest(model: mlModel) { request, _ in
    guard let results = request.results
        as? [VNClassificationObservation]
    else { return }

    for result in results.prefix(5) {
        print("\\(result.identifier): \\(result.confidence)"
    }
}
coreMLRequest.imageCropAndScaleOption = .centerCrop
coreMLRequest.regionOfInterest = faceBoundingBox

imageCropAndScaleOption은 Vision이 모델 입력에 맞겤 이미지를 어떻게 스케일링하는지 결정합니다: .centerCrop(중앙 크로핑), .scaleFill(늨축) 또는 .scaleFit(구성 비율을 유지하면서 스케일링). 선택은 모델 유형과 이미지에서 객체의 위치에 따락니다.

실제 예: VNDetectFaceRectanglesRequest를 통한 얼굴 감지, 그 다음 사용자 지정 모델(예: 성별 또는 나이 추정)이 있는 VNCoreMLRequest를 통한 각 얼굴 분류. 한 perform()에서 두 요청을 결합하면, 한 번의 패스로 완전한 얼굴 분석 파이프라인을 얻을 수 있습니다.

자주 묻는 질문

실행 중인 VNRequest를 취소할 수 있나요?

네, 각 VNRequest에는 요청 실행을 취소하는 cancel() 특성이 있습니다. 그러나 취소는 처리 시작 전에만 작동합니다 — ML 모델이 이미 시작된 경우, 취소는 계산을 중단하지 않습니다. 신뢰할 수 있는 취소를 위해서는 completion handler에서 DispatchWorkItem.cancel()을 VNRequest.cancel()과 함께 사용하세요.

VNDetectFaceRectanglesRequest와 VNDetectFaceLandmarksRequest의 차이점은?

VNDetectFaceRectanglesRequest는 얼굴의 바운딩 직사각형만 찾습니다. VNDetectFaceLandmarksRequest는 추가로 68개의 얼굴 키 포인트(눈, 눈썭, 코, 입, 외곽)를 식별합니다. VNDetectFaceLandmarksRequest는 더 느리지만, 애니메이션, 마스크 및 AR 효과를 위해 더 많은 데이터를 제공합니다. 단순한 얼굴 계수에는 VNDetectFaceRectanglesRequest로 충분합니다.

바코드를 검색하는 요청은 VNDetectBarcodesRequest인가요?

네, VNDetectBarcodesRequest는 모든 유형의 바코드와 QR 코드에 미한 올바른 요청입니다. EAN, UPC, Code 39, Code 128, PDF417, Aztec, QR 및 기타 형식을 지원합니다. 결과는 펜로드와 심볼로지가 있는 VNBarcodeObservation으로 반환됩니다. 비디오 스트림에는 AVCaptureMetadataOutput을 사용하세요 — 실시간 스캔에 더 빠릉니다.

CGImage 대신 CIImage에서 VNRequest를 실행할 수 있나요?

네, VNImageRequestHandler는 init(ciImage:options:) 초기화자를 통해 CIImage를 수락합니다. Data(JPEG/PNG) 및 NSURL(파일 경로)도 지원합니다. CIImage는 이미지가 Core Image 파이프라인을 통해 이미 로드된 경우 편리합니다 — 메모리에서 필요 없는 데이터 복사를 피할 수 있습니다.

한 perform()에서 몇 개의 VNRequest 인스턴스를 실행할 수 있나요?

개수에 제한은 없지만, 실제로는 3–5개의 요청이 최적입니다. 5개 이상의 요청은 각 요청이 자체 ML 모델을 로드하기 때문에 메모리 소비가 증가할 수 있습니다. 10개 이상의 다양한 분석을 실행해야 하는 경우 2–3개 그룹으로 나누어 순차적으로 실행하세요.

요약

  • VNRequest — 통일된 요청-응답 아키텍처를 가진 모든 유형의 이미지 및 비디오 분석을 위한 Vision의 기본 클래스.
  • Vision에는 얼굴 감지, OCR, 바코드, 분류, 외곽, 추적 및 ML 모델을 위한 25개 이상의 VNRequest 하위 클래스가 포함되어 있습니다.
  • VNImageRequestHandler는 정지 이미지에서 요청을 실행하고, VNSequenceRequestHandler는 추적을 위한 프레임 시스를 처리합니다.
  • 결과는 VNObservation으로 바운딩 박스, 확신도, uuid 및 유형 구체적인 데이터와 함께 반환됩니다.
  • 한 perform()에서의 여러 요청은 ML 계산 재사용으로 인해 순차 호출보다 30–40% 빠릅니다.
  • VNCoreMLRequest는 자동 이미지 전처리를 통해 사용자 지정 Core ML 모델을 Vision 파이프라인에 통합합니다.
  • 모든 요청은 서버에 데이터를 보내지 않고 기기에서 실행되어 개인정보보호와 오프라인 작동을 보장합니다.

턴키 방식의 모바일 애플리케이션을 개발해 드립니다

IT Sectr는 2017년부터 스타트업과 기업을 위한 iOS 및 Android 애플리케이션을 만듭니다. 저희가 상담해 드리고 최적의 솔루션을 제안하겠습니다.

프로젝트 논의

더 읽어보기