NearBG

2026-09-08

누끼 가장자리의 후광은 어디서 오고 어떻게 없애나

누끼를 땄습니다. 체커보드 위에서는 깔끔했고, 그래서 PNG로 내려받았습니다. 그런데 그 이미지를 어두운 포스터나 남색 슬라이드, 진한 브랜드 컬러 위에 얹는 순간 실루엣을 따라 희미한 흰 테두리가 돕니다. 인물이든 상품이든, 오려낸 자리 주변에 얇은 빛무리 하나가 같이 붙어 온 것처럼 보입니다.

이 테두리는 렌더링 오류가 아니고, 무작위로 생기는 것도 아닙니다. 지웠다고 생각한 배경이 투명도만 낮춘 채 파일 안에 그대로 남아 있는 것입니다. 자동 누끼 도구는 정도의 차이만 있을 뿐 전부 이 현상을 만들고, NearBG의 경우에는 그 폭을 미리 계산할 수도 있습니다. 이 글은 그 테두리가 정확히 어느 픽셀에 들어 있는지, 왜 하필 그 두께인지, 무엇이 실제로 없애 주는지, 그리고 그중 NearBG가 대신 해 주지 않는 것이 무엇인지에 대한 글입니다.

먼저 반직관적인 사실 하나 — 고화질로 찍을수록 테두리는 두꺼워진다

NearBG가 돌리는 U2Netp 모델의 입력 크기는 320×320으로 고정돼 있습니다. 어떤 사진을 넣든 일단 320 안에 들어가도록 축소되고, 모델은 320×320짜리 마스크를 돌려주고, 그 마스크를 다시 원본 해상도로 확대해서 알파 채널로 씁니다. 즉 마스크의 해상도는 언제나 320이고, 사진만 커집니다. 그래서 마스크 1픽셀이 원본에서 차지하는 폭은 이렇게 됩니다.

사진 긴 변확대 배율마스크 1픽셀이 차지하는 폭
1,280 px4.0×약 4 px
1,920 px6.0×약 6 px
3,024 px9.5×약 9–10 px
4,032 px (1,200만 화소 폰 사진)12.6×약 12–13 px
6,000 px (2,400만 화소 카메라 파일)18.8×약 18–19 px

"화질을 더 좋게 찍으면 경계가 더 깔끔하겠지"라는 기대와 정반대입니다. 2,400만 화소 파일의 테두리는 같은 장면을 1,280 px로 찍은 것보다 픽셀 기준으로 4배 반쯤 두껍습니다. 왜 그 확대가 경계를 '뭉개는지'부터 짚어야 나머지가 설명됩니다.

체커보드는 원래 이걸 못 보여 준다

투명 배경을 표시하는 회색·흰색 체커보드는 밝습니다. 그리고 우리가 찍는 사진의 배경도 대개 그 밝기대에 있습니다 — 흰 벽, 창가, 책상 상판, 흐린 날 하늘. 그러니 밝은 배경 픽셀로 이루어진 테두리는 밝은 체커보드 위에서 완벽하게 숨습니다. 테두리는 원래 원하던 배경 위에 올리는 순간에만 드러나고, 그 배경은 보통 촬영 배경보다 어둡거나 채도가 높습니다.

기술적인 얘기보다 먼저 쓸 수 있는 결론이 여기 있습니다. 누끼 결과는 체커보드가 아니라 실제로 올릴 색 위에서 판단하세요. 포스터든 슬라이드든 상세페이지든 일단 붙여 보고 확인하는 게 순서입니다. 거기서 테두리가 보인다면, 그건 처음부터 계속 있던 겁니다.

반투명 픽셀도 색은 온전히 들고 있다

PNG는 알파를 색에 미리 곱해 두지 않습니다. W3C의 PNG 설계 근거 문서는 그 이유를 이렇게 적어 뒀습니다. 사전 곱 방식에서는 "투명 마스크에 가려진 이미지 데이터는 그 방식에서 되돌릴 수 없이 사라진다. 알파 0을 곱하면 언제나 0이 나오기 때문"이고, 그래서 PNG는 손실 없는 쪽인 비사전곱 알파를 택했다는 것입니다 (PNG Specification: Rationale §12.8).

누끼 파일 입장에서 이 문장은 이렇게 읽힙니다. 알파가 0.3인 픽셀은 '흐려진 색'을 저장한 게 아닙니다. 원래의 R·G·B 값을 그대로 저장하고, 그 옆에 0.3이라는 숫자를 따로 붙여 둡니다. 곱셈은 나중에 무언가 위에 합성될 때 일어납니다. 그러면 후광이 생기느냐 마느냐는 결국 한 가지 질문으로 줄어듭니다 — 피사체 주변의 반투명 픽셀에는 대체 무슨 색이 적혀 있는가?

배경 제거는 색을 단 하나도 바꾸지 않는다

답은, 카메라가 그 자리에서 기록한 색 그대로입니다. NearBG의 누끼 단계는 원본 사진을 캔버스에 색 그대로 그린 다음 마스크를 destination-in 연산으로 씌웁니다. W3C 정의는 co = ab x Cb x as, ao = ab x as (Compositing and Blending Level 1 §9.1.7) — 사전 곱을 되돌리면 남는 색은 Cb, 즉 원래 색 그대로입니다. 움직이는 건 알파 채널뿐입니다.

이걸 굳이 못 박아 두는 이유는, 대부분의 사람이 가진 머릿속 그림과 어긋나기 때문입니다. '배경 제거'는 어떤 픽셀에서도 색을 걷어내지 않습니다. 모든 픽셀에 0과 1 사이 숫자를 하나씩 적어 넣을 뿐, 사진 자체는 아래에 통째로 남아 있습니다. 누끼 전에 100% 벽이던 픽셀은 누끼 후에도 여전히 100% 벽입니다. 마스크가 그 픽셀에 0 대신 0.3을 줬다면, 그 벽 픽셀은 30% 불투명도로 PNG에 실려 나갑니다.

확대가 경계를 그라데이션으로 바꾼다

그러니 후광의 폭은 곧 마스크 값이 0과 1 사이에 걸쳐 있는 구간의 폭입니다. 그리고 캔버스에서 이미지를 확대하면 기본적으로 부드럽게 보간됩니다. imageSmoothingEnabled는 컨텍스트가 만들어질 때 "반드시 true로 설정"되며, 이 값이 켜진 상태로 확대할 때 브라우저는 "이미지 데이터에 스무딩 알고리즘을 적용하려 시도해야 한다"고 규격에 적혀 있습니다 (HTML Standard §4.12.5.1.18 Image smoothing).

사진을 키울 때는 이게 정확히 우리가 원하는 동작입니다. 그런데 같은 보간을 마스크에 적용하면, 딱 떨어지던 예/아니오 경계가 그라데이션이 됩니다. 위 표의 배율이 그대로 그 그라데이션의 폭이 되는 것이고, 그래서 1,200만 화소 폰 사진에서는 13 px짜리 반투명 띠가 실루엣 전체를 두르게 됩니다.

1 — 320×320 마스크: 사실상 0 아니면 1 알파 1.00 — 피사체 0.55 알파 0.00 — 배경 전환 구간은 마스크 1픽셀 폭 (확대해 그림, 세 칸은 같은 축척 아님) 2 — 4,032 px 사진 크기로 12.6배 확대: 13 px 그라데이션 반투명 구간 약 13 px — 이 픽셀들의 색은 여전히 원래 벽 색 3 — 어두운 포스터 색 위에 올리면 피사체 포스터 배경
같은 경계를 세 단계로 본 모습. 모델의 판단 자체는 320×320에서 거의 이분법에 가깝고, 그것을 원본 크기로 확대하는 단계가 넓은 반투명 띠를 만듭니다. 그리고 그 띠의 모든 픽셀은 카메라가 기록한 색을 그대로 들고 있습니다 — 바깥쪽 절반은 온전한 배경색입니다.

숫자로 보는 후광

실제 실루엣에서 바깥으로 네다섯 픽셀 떨어진 지점을 봅시다. 여기는 100% 벽입니다. 실내 흰 벽이라면 RGB (235, 238, 240)쯤 되겠죠. 원래 마스크 값은 0이어야 합니다. 그런데 확대로 번진 그라데이션이 여기에 0.30 정도를 줍니다.

이걸 RGB (20, 24, 32)짜리 어두운 포스터 위에 올립니다. 일반적인 source-over 합성식은 co = as x Cs + ab x Cb x (1 - as) (Compositing and Blending Level 1 §9.1.4)이므로,

0.30 x (235,238,240) + 0.70 x (20,24,32) = (85, 78, 94)

배경이 (20, 24, 32)인데 그 옆 픽셀이 (85, 78, 94)입니다. 대략 네 배쯤 밝습니다. 원래대로라면 그냥 포스터 색이어야 할 자리입니다. 이게 실루엣 전체를 따라 13 px 폭으로 이어지면 그건 자투리 픽셀이 아니라 후광입니다.

여기서 분명히 해 둘 게 있습니다. 이건 머리카락·털 문제가 아닙니다. 머리카락 쪽은 픽셀 하나가 실제로 피사체 반 배경 반이라서 세그멘테이션 모델이 어느 쪽인지 찍어야 하는 상황이고, 그건 이 블로그의 다른 글에서 따로 다뤘습니다. 지금 얘기하는 후광은 어깨선이 흰 벽에 딱 떨어지는, 아무 애매함도 없는 깨끗한 경계에서 생깁니다. 모델은 경계를 제대로 찾았고, 그 뒤 확대 단계가 그걸 번지게 한 겁니다. 조건이 아주 좋은 사진에서도 그대로 나타납니다.

여기서 나오는 실용 규칙

마스크 1픽셀은 언제나 사진 긴 변의 1/320, 즉 0.31%입니다. 해상도를 바꿔도 비율은 그대로라는 뜻이고, 그래서 실제로 중요한 숫자는 촬영 화소가 아니라 최종 출력 크기 하나뿐입니다.

  • 웹페이지에 400 px 폭으로 넣을 때 — 약 1.3 px. 사실상 안 보입니다.
  • 발표자료에 1,200 px 폭으로 넣을 때 — 약 3.8 px. 어두운 슬라이드에서는 보입니다.
  • 가로 40 cm 포스터나 X배너로 인쇄할 때 — 약 1.25 mm. 팔 길이 거리에서 확연합니다.

그러니 이 글 전체에서 가장 싸게 먹히는 해결책은 이겁니다. 최종 레이아웃에서 작게 들어갈 컷아웃이면 그냥 줄여서 쓰고 신경 끄세요. 후광도 같이 줄어듭니다. 크게 쓰거나 인쇄할 거라면 그때 제대로 처리하면 됩니다.

실제로 없애는 방법들

손이 덜 가는 순서대로, 그리고 그중 NearBG가 해 주는 게 뭔지 솔직하게.

  • 올릴 배경과 밝기가 비슷한 곳에서 찍는다. 공짜인데 효과는 이 목록에서 제일 큽니다. 후광이 보이는 건 남은 픽셀이 새 배경과 대비되기 때문입니다. 중간 회색 배경에서 찍어 중간 회색 포스터에 올리면 후광은 여전히 있지만 눈에 안 띕니다. 어두운 레이아웃에 쓸 걸 알고 있다면 어두운 데서 찍으세요.
  • 최종 레이아웃에서 작게 쓴다. 위 산수 그대로입니다.
  • 일부러 테두리 선을 준다. 디자인 툴에서 3–6 px 스트로크를 두르면 반투명 띠가 통째로 가려지고, 수습이 아니라 스티커 스타일 디자인으로 읽힙니다. 도무송 스티커 시안에서 후광 얘기가 거의 안 나오는 이유가 이겁니다.
  • 올릴 색으로 반투명 픽셀을 미리 눌러 버린다. GIMP에는 Semi-Flatten (필터 → 웹 → Semi-Flatten)이 있습니다. 공식 문서 설명으로는 "전경색을 레이어 색에 해당 알파 값에 비례해 합성하고, 올바른 안티에일리어싱을 다시 만들어" 줍니다 (GIMP 2.10 문서 §15.3). 실행 전에 전경색을 포스터 색과 똑같이 맞춰 두는 게 핵심입니다. 배경이 단색일 때만 쓸 수 있지만, 메뉴보드·브랜드 컬러 포스터·슬라이드는 대부분 단색입니다.
  • 알파 경계를 안쪽으로 깎거나 디프린지 계열 기능을 쓴다. 데스크톱 편집기마다 이름이 다르지만 하는 일은 둘 중 하나입니다 — 반투명 띠를 잘라 내거나, 그 띠의 색을 피사체 안쪽 픽셀 색으로 다시 칠하거나. 어느 쪽이든 실루엣을 조금 내주고 깨끗한 경계를 얻는 거래입니다.
  • NearBG 브러시로 직접 지운다. 됩니다. 다만 아래 단서가 붙습니다.

NearBG가 하는 것과 안 하는 것

아래는 '배경 제거 도구 일반'이 아니라 지금 배포돼 있는 NearBG가 실제로 하는 동작입니다.

  • 터치업 브러시는 빼기만 합니다. 커서 아래 알파를 destination-out 으로 0으로 만듭니다. 같은 W3C 규격이 co = ab x Cb x (1 - as)로 정의한 연산입니다 (§9.1.9). 반투명 띠를 깎아 낼 수는 있습니다. 알파를 다시 채우거나, 경계를 부드럽게 만들거나, 마스크가 애초에 못 잡은 디테일을 되살릴 수는 없습니다.
  • 브러시는 그 띠에 비해 굵습니다. 반지름 8–100 px인데, 이 픽셀은 화면 픽셀이 아니라 사진 원본 픽셀 기준입니다. 4,032 px 사진이라면 가장 작은 브러시가 지름 16 px이고 지워야 할 띠는 13 px입니다. 자릿수는 맞지만 피사체 픽셀까지 같이 깎이고, 부드럽던 경계가 딱딱해집니다. 쓰기 전에 확대해서 보세요.
  • 되돌리기는 전부 아니면 전무입니다. 획 단위 실행 취소가 없습니다. 리셋 버튼은 자동 결과로 통째로 되돌리며, 그 뒤에 손본 것은 전부 사라집니다.
  • 배경 교체 기능이 없습니다. NearBG는 투명 PNG를 건네주고 거기서 끝냅니다. 의도적인 범위 결정이지만 이 주제에서는 직접적인 비용이 있습니다 — 후광이 보이는 유일한 조건, 즉 실제로 올릴 색 위에서의 미리보기를 도구 안에서 할 수 없습니다. 합성하는 툴에서 따로 확인해야 합니다.
  • 디프린지도, 색 오염 제거도, 매트 색 지정도, 경계 페더도 없습니다. 앞 절에 적은 해결책 중 도구 안에 구현된 것은 하나도 없습니다. 전부 다른 데서, 나중에 하는 일입니다.
  • 한 번에 사진 한 장, 리사이즈 없음, 출력은 PNG. 일괄 처리가 없습니다. 출력 크기 조절도 없어서 원본 해상도 그대로 나오고, 13 px짜리 띠도 그대로 따라 나옵니다. 입력은 PNG·JPEG·WebP, 데스크톱 500 MB / 휴대폰이나 저메모리 기기 50 MB까지입니다.

후광이 문제 축에도 못 끼는 경우들

같은 320×320 산수는 마스크가 애초에 '볼 수 있는' 것의 하한도 정합니다. 마스크 1픽셀보다 가는 것 — 1,200만 화소 폰 사진에서 13 px, 2,400만 화소 파일에서 19 px — 은 마스크에 제대로 실릴 방법이 없습니다. 꼬치, 전선, 안테나, 고양이 수염, 피어오르는 김, 가느다란 화분 줄기. 이런 것들은 거칠게 나오는 게 아니라 없어집니다. 혹은 흐릿한 회색 자국 정도로만 남습니다. 경계를 아무리 다듬어도 돌아오지 않습니다. 마스크에 처음부터 없었기 때문입니다.

유리를 비롯한 투명체는 더 근본적으로 다른 방식으로 실패합니다. 현저성 모델이 답하는 질문은 "이 픽셀이 주된 대상의 일부인가"인데, 유리컵에는 이 질문의 정답이 없습니다. 그 픽셀은 유리이면서 동시에 유리 너머의 무엇이기 때문입니다. 실제로는 둘 중 하나의 틀린 답이 나옵니다 — 컵이 통째로 남되 원래 배경이 컵 안에 그대로 박혀 있거나, 아니면 컵이 통째로 날아가거나. 어느 쪽도 유리컵 누끼가 아닙니다. 피사체가 유리컵, 투명 보틀, 베일, 얼음이라면 이 도구로는 원하는 결과가 나오지 않고, 후처리로도 메워지지 않습니다.

세 번째는 저대비 경계인데, 이건 또렷한 테두리가 아니라 넓게 번진 형태의 후광을 만듭니다. NearBG가 알파로 쓰는 값은 모델의 원시 현저성 출력을 0–1로 자른 것 그대로입니다. 모델이 진짜로 헷갈리는 구간 — 어두운 벽 앞의 검은 재킷 같은 — 에서는 애매한 중간값이 넓은 영역에 걸쳐 나오고, 그건 13 px짜리 띠가 아니라 형체가 흐릿하게 비치는 반투명 얼룩이 됩니다.

정리, 그리고 출처

누끼 주변의 후광은 무언가 잘못됐다는 신호가 아닙니다. 작게 계산해서 크게 늘린 알파 마스크의 산수이고, 거기에 PNG가 반투명 픽셀의 색을 촬영된 그대로 보관한다는 사실이 더해진 결과입니다. NearBG에서 그 띠는 사진 긴 변의 약 1/320 — 폰 사진 기준 13 px, 해상도와 무관하게 늘 0.31% — 이므로, 물어야 할 질문은 "후광이 있느냐"가 아니라 "내가 쓰려는 크기에서 보일 만큼 크냐"입니다.

확인하실 수 있게 출처를 밝힙니다. 비사전곱 알파 규칙과 그 근거는 W3C PNG Specification: Rationale §12.8, destination-in·destination-out· source-over 식은 Compositing and Blending Level 1의 9.1.7· 9.1.9· 9.1.4절, 반투명 띠를 넓히는 기본값 스무딩은 HTML Standard §4.12.5.1.18, Semi-Flatten 설명은 GIMP 2.10 문서에서 가져왔습니다. NearBG 자체에 대한 서술 — 320×320 고정 입력, 확대해서 알파로 쓰는 구조, 반지름 8–100 px의 지우기 전용 브러시, 전부 아니면 전무인 리셋, 배경 교체 없음, 디프린지 없음, 일괄 처리 없음, 리사이즈 없음 — 은 전부 도구의 소스 코드에서 나왔고, 표에 적힌 픽셀 폭은 직접 나눠 보시면 되는 나눗셈입니다.

광고
← NearBG

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