NearBG

2026-07-20

모든 브라우저에서 실제로 작동하는 배경 제거 모델을 고른 방법 (그리고 BiRefNet이 안 됐던 이유)

NearBG는 사진의 배경을 방문자의 브라우저 안에서 완전히 제거합니다 — 업로드 없음, 서버 없음, 다른 모든 near 도구와 같은 "제로 네트워크" 원칙입니다. 이 제약은 "좋은 세그멘테이션 모델을 고른다"는 게 실제로 무엇을 뜻하는지를 바꿔놓습니다. 벤치마크 점수가 가장 높은 모델이 이기는 게임이 아닙니다 — 그 모델은 실제 방문자가 가진 임의의 기기에서, WebAssembly 안에서 끝까지 로드되고 실행돼야 하고, 그게 안 될 때 대신 처리해줄 서버도 없습니다. "이론적으로 최고인가"가 아니라 "여기서 실제로 돌아가는가"가 진짜 기준입니다. 이 글은 실제로 테스트한 모델들, 품질이 더 높은 후보가 이 기준에서 실패한 두 가지 구체적이고 진단된 이유, 다른 모델을 선택하며 받아들인 트레이드오프, 그리고 이 결정을 나중에 재검토할 조건까지 다룹니다.

두 후보

둘 다 실제로 존재하고 상업적으로 사용 가능한 라이선스의, 공개 ONNX export가 있는 세그멘테이션 모델입니다 — 크기나 라이선스만으로 거른 게 아니라 둘 다 실제로 돌려봤습니다.

모델라이선스파일 크기결과
U2NetpApache-2.04.36MB 성공. 로드 373ms, 320×320 추론 2.9~3.1초(싱글스레드 WASM, 콜드 샌드박스), 정상 출력 형태 [1,1,320,320].
BiRefNet_lite (fp16)MIT109.23MB 순수 WASM/CPU에서 실패 — 하나가 아니라 서로 다른 두 가지 실패. 아래 참조.

BiRefNet_lite는 둘 중 더 최신이고 정확도가 더 높은 모델입니다 — 그래서 처음부터 더 작고 오래된 모델로 그냥 넘어가지 않고 실제로 테스트할 가치가 있었습니다. 그런데도 실패했습니다. 이유는 속도가 아니라 능력의 문제였습니다.

실패 첫 번째: 느린 게 아니라 아예 못 한다 — 입력 크기가 하드코딩됨

처음 세운 가정은 BiRefNet_lite가 네이티브 해상도인 1024×1024에서는 단순히 더 느릴 뿐이고, WASM에 더 우호적인 크기 — 512, 그다음 256 — 로 입력을 줄이면 평범하게 정확도와 속도를 맞바꿀 수 있으리라는 것이었습니다. 이 가정은 틀렸고, 직접 확인해봤기 때문에 진짜 문제를 잡을 수 있었습니다: 이 특정 ONNX export는 입력에 dynamic axes가 전혀 선언돼 있지 않습니다. 그래프의 입력 크기는 1024×1024로 그냥 박혀 있습니다. 512×512나 256×256 텐서를 넣으면 더 느리게 돌아가는 게 아니라, 추론이 시작되기도 전에 명시적인 shape 에러가 납니다.

Got: 512 Expected: 1024

256에서도 같은 에러, 같은 형태입니다. 이건 더 작은 입력으로 우회할 수 있는 성능 상한선이 아니라 능력 자체의 상한선입니다. 이 모델은 export될 때의 그 해상도 말고는 문자 그대로 아무것도 받을 수 없고, 그 해상도가 논의 대상이 되지 않는 한 이 모델에 대한 그 이후의 모든 성능 질문은 의미가 없어집니다.

실패 두 번째: 요구하는 크기 그대로 돌리면, WASM이 메모리 부족에 부딪힌다

그래서 이 export가 허용하는 유일한 방식대로 — 고정된 1024×1024 입력으로, 브라우저가 실제로 쓸 것과 같은 WASM/CPU 실행 경로에서 — 돌려봤습니다. 이것도 실패했고, 이번엔 다르지만 마찬가지로 구체적인 에러가 났습니다.

std::bad_alloc

이건 WebAssembly의 선형 메모리 할당자가 더는 확장을 거부한 것입니다 — WASM의 32비트 주소 지정 방식에 묶인 실질적인 한계이지, 타임아웃을 조절하거나 "더 기다리면 되는" 문제가 아닙니다. 이것도 갑자기 튀어나온 놀라움은 아니었습니다: 사전 조사(브라우저에서 세그멘테이션 모델을 배포하는 것에 대한 IMG.LY의 엔지니어링 블로그 글)에서 이미 대형 고정 해상도 모델이 WASM에서 겪을 수 있는 위험으로 정확히 이 실패 양상을 경고한 바 있습니다. 바로 이 모델, 바로 이 입력 크기로 실제로 부딪혀본 것은 그 경고를 가설에서 실측된 사실로 바꿔놓은 셈입니다.

WebGPU가 이를 우회하는 방법으로 문서화돼 있습니다 — IMG.LY 자체 글은 같은 부류의 모델을 WASM 대신 WebGPU로 돌렸을 때 약 20배의 속도 향상을 보고하고 있고, GPU로 오프로드하면 WASM의 선형 메모리 한계 자체를 완전히 우회합니다. 다만 이건 이 세션에서 테스트할 수 없었습니다: 이 스파이크는 Node에서 onnxruntime-web의 WASM 백엔드로 실행됐는데(브라우저가 실제로 쓸 그 런타임 자체이지 어떤 런타임에 대한 설명이 아니므로 결과에 실질적인 무게가 있습니다), Node에는 WebGPU를 테스트할 GPU 백엔드가 없기 때문입니다. 하지만 20배라는 숫자를 그대로 받아들인다 해도, 도구의 유일하게 작동하는 경로를 WebGPU 위에 짓는다는 것은 WebGPU를 지원하지 않는 모든 방문자 — 그리고 브라우저·기기의 WebGPU 지원은 실재하지만 보편적이지 않습니다 — 에게는 대체 경로 없이 그냥 안 되는 도구를 준다는 뜻입니다. 이건 "누구에게나 작동해야 한다"는 near의 운영 원칙과 정면으로 충돌합니다 — 가장 최신 브라우저를 가진 사람에게만이 아니라요.

판정, 그리고 그 대가로 치른 트레이드오프

U2Netp를 채택했고, 이 ONNX 빌드로는 BiRefNet_lite를 채택하지 않았습니다. U2Netp는 둘 중 더 오래되고 가벼운 모델이고, 여기엔 실질적인 품질 비용이 따릅니다: 머리카락처럼 세밀한 경계에서의 정교함은 BiRefNet_lite가 (돌아갈 수만 있다면) 냈을 결과보다 한 단계 아래입니다. 이 트레이드오프는 간과한 게 아니라 의도적으로 받아들인 것입니다: "WebGPU 의존 없이, 순수 WASM에서, 누구에게나 작동한다"가 "품질은 최고지만 WebGPU 전용이다"를 이겼습니다 — WebGPU 커버리지가 아직 보편적이지 않은 상황에서, 상당수 방문자에게 조용히 실패하는 도구를 내놓는 것이 모두에게 살짝 더 부드러운 경계선을 내놓는 것보다 나쁘기 때문입니다.

2.9~3.1초라는 추론 시간 자체도 전형적인 성능을 약속하는 숫자가 아니라 보수적인 최악의 경우 수치입니다 — 싱글스레드, 콜드 샌드박스에서 측정됐습니다. SIMD와 멀티스레드를 쓸 수 있는 실제 브라우저 탭은 확실히 더 빠를 것으로 예상되지만, 아직 저사양 실제 모바일 기기에서 재검증하지는 않았고, 이는 당연한 우위로 가정하지 않고 열린 재검증 항목으로 남겨둡니다.

영구 기각이 아닌 것

이 특정 BiRefNet_lite ONNX export를 순수 WASM에서 배제한 것이, BiRefNet이라는 모델 계열 자체를 영원히 배제한다는 뜻은 아닙니다. 재검토 조건은 "언젠가는"처럼 막연하지 않고 구체적입니다: dynamic input axes를 선언한, 다르게 export된 ONNX 빌드가 나오면(첫 번째 실패를 그 자체로 해소함), WebGPU의 기기·브라우저 커버리지가 near가 상당수 방문자를 배제하지 않고도 하드 요구사항으로 받아들일 만큼 넓어지면, 또는 WebGPU 지원 기기용 경로와 나머지를 위한 저해상도 WASM 폴백을 이중으로 유지할 만한 엔지니어링 여력이 동시에 생기면입니다. 이 스파이크 시점에는 이 조건들 중 어느 것도 충족되지 않았습니다 — 그중 하나라도 바뀌면 이 비교를 다시 돌려볼 이유가 되는 것이지, 이 결정이 영구히 확정됐다는 뜻은 아닙니다.

실제로 만들어진 것

지금 실제로 돌아가는 파이프라인은 packages/near-bg-engine/segment.js입니다: preprocess는 입력을 U2Netp의 고정 입력 크기인 320×320(모델 자체의 config.json에 명시된 학습 입력 크기)에 맞춰 리사이즈하고, 패딩한 뒤, 표준 ImageNet mean/std로 정규화해서 [1,3,320,320] 텐서를 모델에 넘깁니다. postprocess는 원본 [1,1,320,320] saliency 마스크를 받아 패딩을 잘라내고, 캔버스의 destination-in 합성으로 원본 해상도 이미지 위에 알파 채널로 합성합니다. 이 전체는 apps/nearbg/src/segment.worker.js 안에서 돌아가는데, 다른 모든 near 앱의 워커가 쓰는 것과 같은 near-kit 워커 메시지 프로토콜을 그대로 따르고 — 모델 선택 자체만큼 중요했던 제약인데 — 모델 가중치와 onnxruntime-web 자체의 .wasm 바이너리를 모두 동일 출처(same-origin)로 서빙합니다. near의 CSP는 connect-src 'self'이고, 둘 중 하나라도 CDN에서 가져오면 아예 막히거나 이 정책을 완화해야 하는데, 정책을 완화하는 건 모델 선택과 별개로 모든 near 도구가 약속하는 "외부 호출 0건"을 깨는 일입니다.

솔직한 요약

더 고품질인 모델은 벤치마크 표 위에서 진 게 아니라, 브라우저가 실제로 돌려야 할 방식 그대로 실행해본 순간 서로 다른 두 가지 진단된 이유로 실패했습니다: "속도를 위해 리사이즈"를 아예 에러로 만들어버린 하드코딩된 입력 크기, 그리고 WASM 자체의 할당자가 감당하지 못한 고정 크기의 메모리 요구량입니다. 둘 다 문서에서 추론한 게 아니라 실제 실행에서 나온 진짜 에러 메시지입니다. 대신 출시된 것은, WASM 경로가 반드시 작동해야 하는 모든 곳에서 실측으로 작동하는 모델입니다 — 경계 품질에서 실질적이고 솔직하게 밝힌 비용을 치르면서요. 그리고 이 선택을 재검토할 조건도 닫힌 문이 아니라 구체적으로 적어뒀습니다.

광고
← NearBG

이 페이지는 동의하신 경우에만 광고를 표시합니다.