개요¶
개요¶
이 페이지는 SF32에서 온디바이스 AI를 배포하는 방법을 설명합니다. 디바이스를 선택하고, 실행 경로에 맞게 모델을 준비하고, 메모리 예산을 세우고, 제품의 에너지 예산 안에서 추론을 스케줄링합니다. AI 가속기의 하드웨어 배경 지식을 전제로 하므로, 가속기의 역할과 한계는 해당 페이지를 먼저 읽으십시오.
SDK는 NNACC(neural network accelerator, 신경망 가속기) HAL을 통해 가속기 연산을 제공하며, HAL 예제와 RT-Thread 드라이버 예제가 따로 있습니다. 이 예제들은 학습이 끝난 전체 모델의 배포가 아니라 개별 깊이별(depthwise) 컨볼루션 연산 하나를 검증합니다. 동작하는 연산자 기준선을 확보하는 데 사용하고, 모델 런타임, 변환 도구, 레이어 매핑은 별도로 선택하고 검증하십시오.
아래에 인용한 구현 세부 사항은 SDK v2.5.1에 한정된 것으로 취급하십시오. 이러한 세부 사항이나 제품군 수준의 NNACC 사용 가능 여부는 특정 부품에 대한 지원, 전체 모델 런타임 또는 변환기, 연산자 호환성, 자동 CPU 폴백, 카메라 입력을 보장하지 않습니다. 이 항목들은 정확한 SDK 리비전과 구성, 칩 리비전, 런타임, 보드에서 확인하십시오.
AI 기능의 제품 적용 방향과 배포 경로를 결정할 때 이 페이지를 참고하십시오. 디바이스가 로컬에서 무엇을 판단해야 하는지, 메모리와 에너지를 얼마나 쓸 수 있는지, 실제 센서 데이터에 대해 기능이 어떻게 동작해야 하는지를 다룹니다. 하드웨어의 경계를 설명하는 가속기 문서를 보완합니다.
제품이 로컬에서 판단해야 할 내용 정의¶
모델이 아니라 제품의 판단에서 시작하십시오.
- 휴대폰이나 클라우드 왕복 없이 디바이스가 스스로 분류하거나 감지해야 하는 것은 무엇입니까?
- 그 판단에 어떤 센서가 입력을 제공합니까? 모션, 오디오, 생체, 카메라 또는 이들의 조합입니까?
- 판단은 얼마나 자주 실행되어야 하며, 얼마나 빨리 응답해야 합니까?
- 온디바이스 모델이 틀리면 어떻게 됩니까? 오탐과 미탐 중 어느 쪽의 비용이 더 큽니까?
- 모델을 현장에서 업데이트해야 할 일이 있으며, 있다면 어떻게 합니까?
이 답변에 따라 모델 크기, 메모리 예산, 디바이스 선택, 추론 사이에 슬립 상태를 얼마나 오래 유지할 수 있는지 등 이후의 설계가 결정됩니다.
적합한 SF32 디바이스 선택¶
모든 SF32 디바이스가 AI 워크로드를 같은 방식으로 겨냥하는 것은 아닙니다.
| 요구 사항 | 일반적인 디바이스 방향 |
|---|---|
| 비용에 최적화된 제품에서의 가벼운 간헐적 분류 | SF32LB52x — 모델을 작게 유지하고 CPU 중심으로 구성합니다. |
| 기본적인 센서 퓨전이 필요한 BLE 웨어러블 | SF32LB55x |
| UI와 함께 더 풍부한 센서 또는 멀티미디어 파이프라인 | SF32LB56x |
| 엣지 AI가 핵심 기능인 경우 — 더 큰 모델, 선택한 디바이스가 지원하는 카메라 입력, 또는 빠듯한 지연 시간 | SF32LB58x |
이 표는 모델이 들어맞거나 효율적으로 실행된다는 보장이 아니라 평가의 출발점으로 취급하십시오. 선택한 부품의 메모리, 센서 인터페이스, 가속기 인스턴스, SDK 지원을 전체 워크로드에 대해 확인하십시오. SDK v2.5.1 NNACC 가이드는 SF32LB55x/56x에 HCPU 가속기 하나가 있고 SF32LB58x에는 HCPU/LCPU 가속기가 각각 있다고 밝힙니다. SF32LB52x나 SF32LB57x의 NNACC 사용 가능 여부는 확정하지 않으므로, 이 두 제품군은 여기서 문서화되지 않은 것으로 취급하되 NNACC가 없다는 증거로 보아서는 안 됩니다. 나열된 인스턴스 수는 모델 호환성이나 에너지 효율을 보장하지 않습니다. 더 폭넓은 선택 배경은 디바이스 제품군별 위치를 참조하십시오.
모델 개발 워크플로¶
실제로는 구체적인 사용 사례와 상관없이 SF32 하드웨어에 모델을 올리는 과정이 같은 형태를 따릅니다.
- 워크스테이션에서 모델을 학습시키거나 선택합니다. 이때 현장에서 센서로 수집할 데이터와 유사한 데이터를 사용하십시오. 실험실의 깨끗한 데이터는 잡음이 섞인 실제 센서 입력과 매우 다르게 동작하는 경우가 많습니다.
- 아키텍처 선택, 프루닝 또는 양자화로 임베디드 제약에 맞게 모델을 줄입니다. 가속기별 변환 방식은 그다음에 검토하십시오.
- 모델을 선택한 추론 런타임과 대상 SDK가 지원하는 정확한 연산자, 레이아웃, 수치 형식에 맞게 내보내고 매핑합니다. NNACC HAL 지원만으로는 전체 모델 변환기나 그래프 런타임이 제공되지 않습니다.
- 변환과 양자화 후에 수치적으로 검증합니다. 데스크톱의 정확도가 그대로 유지된다고 가정하지 마십시오.
- 전처리, 추론, 후처리를 펌웨어에 통합합니다. 모델 자체는 더 큰 파이프라인 안에서 호출되는 함수 하나입니다.
- 시뮬레이션만이 아니라 실제 하드웨어에서 지연 시간, 메모리, 전력, 정확도를 프로파일링합니다.
- 현실적인 복합 부하에서 테스트합니다. Bluetooth, 디스플레이, 센서를 추론과 분리하지 말고 동시에 활성화합니다.
흔한 통합 실수는 모델을 최적화하면서 전처리, 버퍼링, 후처리를 측정하지 않고 두는 것입니다. 이 단계들이 가속된 추론만큼 비용이 들 수 있으므로 전체 경로를 프로파일링하십시오.
런타임 계약 정의¶
모델을 변환하기 전에, 펌웨어가 충족해야 하는 정확한 런타임 계약을 기록하십시오.
| 계약 항목 | 확정해야 할 결정 |
|---|---|
| 입력 형태 | 샘플 윈도, 이미지 크기, 채널 수, 텐서 레이아웃. |
| 수치 형식 | 정수 폭, 스케일/제로 포인트 처리, 보정 데이터셋. |
| 연산자 집합 | NNACC에서 실행해야 하는 레이어와 허용되는 CPU 폴백. |
| 지연 시간 목표 | 가속기 시간만이 아니라 엔드 투 엔드 파이프라인 지연 시간. |
| 메모리 한도 | 가중치, 활성화, 입력/출력 텐서, 전처리/후처리 버퍼. |
| 업데이트 정책 | OTA로 모델을 변경할 수 있는지와 그 검증 방법. |
이 계약은 ML 담당자와 펌웨어 담당자가 함께 검토해야 합니다. 펌웨어를 업데이트하지 않은 채 모델의 형태, 형식, 연산자 구성이 바뀌면, 깔끔한 빌드 오류가 아니라 잘못된 정확도나 불안정한 지연 시간으로 문제가 나타나는 경우가 많습니다.
연산자와 폴백 검토¶
모델을 선택하기 전에 모든 연산자와 그 파라미터, 실제 실행 경로를 검토하십시오. CPU 구현이나 자동 폴백은 선택한 런타임이 명시적으로 제공해야 하며, 지원되지 않는 연산은 오히려 배포를 막을 수 있습니다. 자주 실행되는 레이어가 CPU를 사용하거나 반복적인 레이아웃 변환이 필요하면 작은 모델도 느려질 수 있습니다.
| 분류 | 의미 | 조치 |
|---|---|---|
| 가속됨 | 대상 디바이스의 NNACC 경로가 직접 지원합니다. | 핵심 레이어에 우선 사용합니다. |
| CPU 폴백 | 선택한 런타임 또는 펌웨어가 검증된 CPU 구현을 제공합니다. | 비용을 측정하고, 전체 파이프라인이 목표를 충족할 때만 수용합니다. |
| 변환 필요 | 레이아웃, 타입 또는 형식 변환이 필요합니다. | 변환 비용을 지연 시간 및 전력 예산에 포함합니다. |
| 지원되지 않음 | 대상 런타임에서 사용할 수 없습니다. | 레이어를 교체하거나 모델 아키텍처를 변경합니다. |
합격 기준은 "모델이 실행된다"가 아닙니다. 합격 기준은 "제품이 현장에서 접하는 것과 같은 데이터 분포에서 전체 파이프라인이 정확도, 지연 시간, 메모리, 에너지 목표를 충족한다"입니다.
양자화와 메모리 예산¶
소형 양자화 모델은 마이크로컨트롤러 AI에서 흔한 선택이며, 부동 소수점 대신 8비트 정수를 쓰는 경우가 많습니다. 실제 실행 경로가 지원하는 수치 형식을 선택하십시오. 모델 아키텍처를 확정하기 전에, 가중치뿐 아니라 다음 항목 전체에 대해 메모리 예산을 세우십시오.
| 메모리 사용처 | 참고 사항 |
|---|---|
| 모델 가중치 | 양자화로 크게 줄지만 여전히 기본 점유 공간입니다. |
| 입력 텐서 | 센서 윈도, 이미지 해상도 또는 오디오 프레임 길이로 크기가 정해집니다. |
| 중간 활성화 | 과소평가하기 쉽고, 일부 아키텍처에서는 가중치보다 클 수 있습니다. |
| 출력 텐서 | 대체로 작지만 예산에서 빠뜨리지 마십시오. |
| 전처리/후처리 버퍼 | 필터링, 프레이밍, 특징 추출, 임계값 처리에는 모두 작업 메모리가 필요합니다. |
| 동시 실행되는 시스템 메모리 | UI, Bluetooth, 오디오 버퍼가 같은 SRAM/PSRAM을 두고 동시에 경쟁합니다. |
양자화는 메모리와 연산 비용을 줄일 수 있지만, 변환 후에는 대표 센서 데이터로 정확도를 다시 확인하십시오. SDK v2.5.1 가이드는 arm_convolve_1x1_HWC_q7_fast_nonsquare, arm_convolve_HWC_q7_basic_nonsquare, arm_depthwise_separable_conv_HWC_q7_nonsquare에 대한 가속을 문서화합니다. HAL 구성은 8비트 버퍼와 바이어스/출력 시프트를 사용하지만, 이것이 최신 int8 모델의 제로 포인트와 채널별 스케일이 직접 호환된다는 증거는 아닙니다. 지원되지 않는 모든 레이어에 대해 수치적 동등성과, CPU 구현, 변환 또는 거부 경로를 확인하십시오.
버퍼 배치와 메모리 계층¶
연산 용량이 충분해도 메모리 대역폭이 AI 성능을 제한할 수 있습니다. SRAM, 플래시, PSRAM, STAR-MC1 명령어/데이터 캐시를 갖춘 SF32 디바이스에서는 메모리 접근 가능 여부와 버퍼 배치 비용을 모두 확인하십시오.
- 자주 접근하는 텐서와 중간 버퍼는 필요한 정렬과 레이아웃을 갖춰, CPU와 선택한 가속기 인스턴스가 모두 접근할 수 있는 메모리에 배치합니다.
- 큰 가중치나 드물게 접근하는 에셋은 선택한 실행 경로가 해당 배치를 지원할 때만 외부 메모리에 둡니다. 가속기가 접근할 수 있는 메모리로의 복사도 메모리, 지연 시간, 에너지 예산에 포함합니다.
- 공유 버퍼마다 전송 중에는 CPU 또는 가속기/DMA 중 하나가 독점 소유하게 합니다. 하드웨어가 접근하기 전에 캐시 라인에 정렬된 전체 범위를 준비합니다. CPU가 쓴 입력은 clean 하고, 더티 출력 캐시 라인은 SDK의 디바이스 쓰기 규칙에 따라 처리합니다. 완료를 기다린 뒤에 출력 범위를 invalidate 하고 소유권을 CPU에 돌려줍니다. 하드웨어가 소유하는 동안에는 버퍼와, 그 캐시 라인을 공유하는 관련 없는 데이터를 수정하지 않습니다.
v2.5.1 HAL 구현은 버퍼에 대해 1 MiB(1,048,576바이트) 주소 윈도 경계를 검사하며, 입력과 바이어스가 같은 윈도에 있어야 합니다. 전체 여유 메모리가 아니라 실제로 할당된 주소를 검증하십시오. 블로킹 시작은 완료를 폴링하고, 인터럽트 경로에는 올바른 IRQ 처리와 완료 알림이 필요합니다. 모델 런타임 타임아웃이 있다고 가정하지 말고, 반환값을 확인하고 애플리케이션 수준의 실패 복구와 제한된 대기를 정의하십시오.
이처럼 접근 패턴이 섞이는 경우의 캐시와 메모리 시스템 고려 사항은 STAR-MC1을 참조하십시오.
메모리 산정 워크시트¶
펌웨어에 통합하기 전에 메모리 워크시트를 사용하십시오. 평균 추정치가 아니라 최악의 경우 수치로 작성하십시오.
| 버퍼 | 크기 결정 요인 | 배치 선호 위치 |
|---|---|---|
| 원시 입력 윈도 | 샘플 레이트 x 채널 수 x 윈도 길이 x 샘플당 바이트 수, 여기에 레이아웃 패딩 추가 | 주변 장치가 캡처하는 경우 DMA가 접근할 수 있는 메모리. |
| 전처리 작업 공간 | 필터, FFT/MFCC, 정규화, 리사이즈/크롭 | 추론할 때마다 재사용하는 경우 빠른 SRAM. |
| 모델 가중치 | 양자화된 모델 크기 | 지원되면 플래시/PSRAM, 핵심 구간만 SRAM. |
| 활성화 | 가장 큰 중간 텐서 | 가속기가 접근할 수 있는 빠른 메모리. |
| 출력/후처리 | 클래스, 박스, 점수, 스무딩 상태 | SRAM. 대체로 작지만 지연 시간에 민감합니다. |
| 공존 버퍼 | 오디오, 디스플레이, Bluetooth, 로깅 | AI가 "들어맞은" 뒤가 아니라 동시에 예산을 잡습니다. |
스택, 힙, RTOS 객체, 로깅, OTA를 위한 여유를 남겨 두십시오. 다른 서브시스템을 모두 끄고서야 들어가는 모델은 제품에 쓸 수 있는 모델이 아닙니다.
전체 파이프라인 구축¶
가속기는 더 큰 센서-판단 파이프라인의 한 단계입니다. 아래에서 흔한 입력 경로 세 가지를 설명합니다.
오디오와 음성¶
키워드 스포팅, 웨이크 워드 방식의 트리거, 오디오 이벤트 분류는 모두 추론이 시작되기 전에 마이크 캡처, 프레이밍, 특징 추출이 필요합니다. 이 파이프라인의 캡처와 버퍼링 쪽은 오디오 개요를 참조하십시오. 가속기에 입력되는 오디오가 처음부터 효율적으로 캡처되고 버퍼링될 때만 가속기가 도움이 됩니다.
모션과 센서 퓨전¶
제스처 인식, 활동 분류, 생체 분석은 대개 가속도계, 자이로스코프 또는 기타 센서 스트림을 사용합니다. 무엇이 에너지 사용을 좌우하는지 판단하기 전에 센서 동작, 캡처, 전처리, 추론을 따로 측정하십시오. 일괄 처리와 인터럽트 기반 캡처는 지연 시간과 신호 범위가 허용하는 경우 웨이크업을 줄일 수 있지만, 모델 비용보다 언제나 더 크다고는 할 수 없습니다. 스케줄링 지침은 저전력 설계 개요를 참조하십시오.
카메라와 이미지 입력¶
카메라 입력은 캡처, 버퍼링, 대역폭, 추론에 상당한 비용을 부과할 수 있으며, 실제 부하는 해상도, 프레임 속도, 센서 동작, 모델 아키텍처에 따라 달라집니다. 정확도가 허용하면 프레임 크기를 줄이거나 관심 영역만 처리하십시오. 데스크톱 비전 모델을 그대로 배포할 수 있다고 가정하지 말고 임베디드 제약에 맞는 모델을 선택하십시오.
전력을 고려한 추론 스케줄링¶
감지 범위와 응답 시간 요구 사항을 충족하도록 스케줄링을 선택하십시오. 제품이 주기적으로 샘플링한 판단을 필요로 한다면 주기적 추론이 타당하며, 이벤트 게이팅은 필요한 신호를 놓치지 않을 때만 유용합니다.
- 센서 임계값이나 완전한 오디오 프레임처럼 유용한 새 데이터가 있을 때 적절히 추론을 트리거합니다. 필요하면 주기적 처리를 유지하고, 트리거를 바꾼 후에는 미탐과 최악의 응답 시간을 확인합니다.
- 작은 추론을 자주 실행하는 대신, 지연 시간 요구 사항이 허용하는 경우 샘플을 일괄 처리합니다.
- 디바이스와 SDK가 지원하는 경우, 샘플마다 메인 애플리케이션 CPU를 깨우지 말고 가벼운 상시 센싱을 저전력 프로세서로 옮깁니다.
- 명시한 측정 구간에 걸쳐 측정한 공급 전력(공급 전압 × 전류)을 적분하여 추론당 에너지를 측정합니다. 캡처, 전처리/후처리, 웨이크/슬립 전환을 기능 예산에 포함합니다. 처리가 빨라지면 활성 에너지가 줄거나 더 일찍 슬립에 들어갈 수 있지만, 그 효과는 전류, 메모리 트래픽, 나머지 시스템에 따라 달라집니다.
시스템 수준의 전체 전력 지침은 저전력 설계 개요에 있습니다. 연속적으로 또는 거의 연속적으로 실행해야 하는 AI 기능에는 이 문서를 보완 문서로 함께 참조하십시오.
정확도 / 지연 시간 / 전력의 트레이드오프¶
다음은 고정된 관계가 아니라 흔히 나타나는 설계상의 제약입니다. 이러한 트레이드오프를 결정할 때는 실제 모델 정확도와 전체 파이프라인의 에너지를 측정하십시오.
| 우선순위 | 일반적인 설계상의 제약 |
|---|---|
| 더 높은 정확도 | 더 큰 모델, 더 많은 입력 특징, 더 긴 윈도, 더 많은 메모리. |
| 더 낮은 지연 시간 | 더 짧은 캡처 윈도, 더 빠른 실행 또는 더 잦은 판단. 정확도와 에너지에 미치는 영향을 확인합니다. |
| 더 낮은 전력 | 추론 빈도 감소, 소형 모델, 효율적인 메모리 배치, 실행 사이의 적극적인 슬립. |
튜닝하기 전에 제품이 이 트레이드오프의 어느 쪽을 실제로 필요로 하는지 정하십시오. 제스처 감지기는 배터리 수명을 위해 약간의 지연을 감수할 수 있는 경우가 많은 반면, 음성 트리거는 대체로 지연을 많이 허용할 수 없으면서도 전력을 낭비하는 오탐 웨이크업은 피해야 합니다.
모델 업데이트와 현장 검증¶
출시 후에 AI 기능이 개선될 수 있다면 모델 업데이트 지원을 초기에 설계하십시오.
- 가능하면 모델을 펌웨어와 별도로 버전 관리하고, 모델 패키지와 함께 기대하는 입력 계약을 기록합니다.
- 활성화하기 전에 패키지의 진위, 무결성, 런타임/입력 호환성을 검증합니다. 업데이트가 중단되어도 활성화가 견고하도록 하고, 시작 검증이 실패하면 정상 동작이 확인된 버전으로 롤백하는 경로를 유지합니다.
- 보정값, 임계값, 후처리 상수는 그것을 필요로 하는 모델 버전과 함께 저장합니다.
- 불필요하게 개인의 원시 센서 데이터를 저장하지 않으면서 드리프트를 진단하기에 충분한 현장 통계를 로깅합니다.
- 모델을 업데이트할 때마다 전력 및 공존 테스트를 다시 실행합니다. 모델 정확도가 좋아져도 시스템을 더 자주 깨운다면 제품 측면에서는 회귀일 수 있습니다.
AI 성능과 정확도 디버깅¶
| 증상 | 확인할 가능성이 높은 영역 |
|---|---|
| 모델은 실행되지만 워크스테이션 결과보다 정확도가 떨어짐 | 양자화/보정 불일치, 또는 학습 데이터가 실제 센서 노이즈를 대표하지 못함. |
| 추론이 예상보다 느림 | 실제 CPU 레이어 실행, 레이아웃 변환, 메모리 대역폭 또는 스케줄링 경합. |
| 시스템이 기대한 슬립 깊이에 도달하지 못함 | 불필요한 웨이크업, 활성 상태의 드라이버/클럭, 전력 관리 잠금 또는 끝나지 않은 가속기 트랜잭션. |
| 기능이 단독으로는 동작하지만 전체 제품에서는 실패함 | 복합 부하(Bluetooth + 디스플레이 + 센서 동시 활성화)에서 테스트하지 않음. |
| "빠른" 모델인데도 전력이 높음 | 추론당 에너지가 아니라 지연 시간을 측정함. 실행 사이에 코덱/센서 경로가 활성 상태로 남음. |
| 공유 버퍼에서 간헐적으로 쓰레기 출력이 나옴 | 캐시 라인 준비, 더티 라인 위험, 너무 이른 재사용, 누락된 완료 확인 또는 CPU/하드웨어 소유권 중복. |
흔한 실수¶
- 대상 런타임이 실제로 어떤 연산자를 가속하는지 확인하기 전에 모델 아키텍처를 선택하는 것.
- 처음부터 임베디드 제약에 맞게 설계하지 않고 데스크톱 규모의 모델을 이식하는 것.
- 중간 활성화의 메모리 비용을 무시하고 모델 가중치만 예산에 잡는 것.
- 추론 속도와 트리거가 필요한 입력 범위와 응답 시간에 맞는지 확인하지 않고 추론을 실행하는 것.
- 정확도를 깨끗한 실험실 데이터로만 검증하고 현실적인 현장/센서 노이즈로는 검증하지 않는 것.
- AI 기능을 단독으로 테스트하다가 전체 제품 통합 후에야 공존 문제를 발견하는 것.
- 모델 지연 시간을 최적화하면서 그 앞뒤의 전처리와 후처리 단계를 무시하는 것.
브링업 체크리스트¶
- 제품이 내려야 하는 로컬 판단과 허용 가능한 지연 시간/정확도/전력 트레이드오프를 정의합니다.
- 비용 목표만이 아니라 모델 크기와 메모리 요구에 따라 SF32 디바이스를 선택합니다.
- 전체 파이프라인(캡처 -> 전처리 -> 추론 -> 후처리)을 먼저 최소한의 테스트 모델로, 그다음 양산 모델로 빌드하고 검증합니다.
- 실제 모델을 변환하고 양자화한 다음, 현실적인 센서 데이터로 정확도를 검증합니다.
- 가중치, 입력/출력 텐서, 중간 활성화의 메모리를 함께 예산에 반영합니다.
- CPU와 가속기가 공유하는 모든 버퍼에 대해 캐시 일관성 처리를 검증합니다.
- 주기적 또는 이벤트 기반 스케줄링을 감지 범위, 최악의 지연 시간, 측정된 에너지 예산에 대해 검증합니다.
- 복합 시스템 부하(Bluetooth, 디스플레이, 센서 활성) 상태에서 추론당 에너지를 프로파일링합니다.
- 양자화, 모델 또는 스케줄링을 변경할 때마다 정확도와 전력을 다시 검증합니다.
핵심 요약¶
- 모델 아키텍처가 아니라 제품의 판단과 센서 데이터에서 시작하십시오. 모델은 더 큰 파이프라인의 한 단계입니다.
- 디바이스 제품군별 위치는 후보를 추리는 용도로 사용한 다음, 실제 부품, SDK, 연산자 매핑, 메모리 할당, 동시 워크로드를 확인하십시오.
- 모델 파일 크기만이 아니라 전체 파이프라인(가중치, 텐서, 활성화, 전처리/후처리 버퍼)에 대해 메모리 예산을 세우십시오.
- 필요한 감지 범위를 유지하도록 주기적 또는 이벤트 기반 추론을 선택하고, 모델 속도를 전력 결과로 취급하지 말고 전체 기능의 에너지를 측정하십시오.
- 현실적인 현장 데이터로 정확도를 테스트하고, 전체 기능을 단독이 아니라 복합 시스템 부하에서 테스트하십시오.
최종 업데이트: