
가장자리 정리: AI 생성 애니메이션에 PNG 알파 마스크 (Alpha Mask) 사용하기
요약
AI 생성 비디오를 웹 UI의 애니메이션 타일로 활용할 때 발생하는 투명도 문제를 해결하는 방법을 다룹니다. PNG 알파 마스크를 사용하여 배경이 있는 애니메이션을 깔끔하게 처리하는 기술적 탐구 과정을 공유합니다.
핵심 포인트
- AI 생성 비디오와 애니메이션 WebP 활용법
- 투명도 문제를 해결하기 위한 PNG 알파 마스크 사용
- 정적 PNG를 생동감 있는 루프 비디오로 변환하는 워크플로우
저는 Isovalent Labs를 위해 새로운 무언가를 만들고 있습니다. 아직 많은 것을 말씀드릴 수는 없지만, 곧 발표가 있을 예정입니다. 제가 지금 말씀드릴 수 있는 것은 그 과정에서 빠져들었던 기술적인 탐구(technical rabbit hole)에 관한 것입니다. 바로 AI 생성 비디오 (AI-generated video), 애니메이션 WebP, 그리고 놀라울 정도로 깔끔한 해결책이 있는 투명도 문제에 관한 이야기입니다.
설정 (The Setup)
새로운 UI에는 애니메이션 타일이 필요합니다. 각 학습 구역(learning zone)마다 하나씩 배치되는 아이소메트릭 (isometric) 도시 건설 장면으로, 마우스를 올리면 생동감 있게 움직입니다. 각 타일은 정적인 PNG로 시작하여, 짧은 루프 비디오 (looping video)로 애니메이션화됩니다.
다음은 배경이 있는 PNG 타일의 몇 가지 예시입니다:



‹ ›
(function() { var container = document.currentScript.closest('.ltag-slides--carousel'); var track = container.querySelector('.ltag-slides__track'); var slides = track.querySelectorAll('.ltag-slide'); var prevBtn = container.querySelector('.ltag-slides__nav--prev'); var nextBtn = container.querySelector('.ltag-slides__nav--next'); var dotsContainer = container.querySelector('.ltag-slides__dots'); var current = 0; var total = slides.length; for (var i = 0; i < total; i++) { var dot = document.createElement('button'); dot.className = 'ltag-slides__dot' + (i === 0 ? ' ltag-slides__dot--active' : ''); dot.setAttribute('aria-label', 'Go to slide ' + (i + 1)); dot.dataset.index = i; dot.addEventListener('click', function() { goTo(parseInt(this.dataset.index)); }); dotsContainer.appendChild(dot); } function goTo(index) { current = ((index % total) + total) % total; track.style.transform = 'translateX(-' + (current * 100) + '%)'; var dots = dotsContainer.querySelectorAll('.ltag-slides__dot'); for (var i = 0; i < dots.length; i++) { dots[i].classList.toggle('ltag-slides__dot--active', i === current); } } prevBtn.addEventListener('click', function() { goTo(current - 1); }); nextBtn.addEventListener('click', function() { goTo(current + 1); }); })();
비디오 생성을 위한 프롬프트 (generation prompt)는 의도적으로 제한되었습니다:
"이 타일을 아주 약간/미세하게 애니메이션화하세요. 카메라 움직임이나 각도 변경은 없습니다.""
그 제약 조건은 결과에 결정적인 역할을 하는 것으로 드러났습니다. 이에 대해서는 나중에 더 자세히 다루겠습니다.
끊김 없는 루프 (seamless loop)를 보장하기 위해, 시작 프레임과 종료 프레임 모두에 동일한 320×320px PNG를 전달합니다. 도구는 16:9 또는 9:16 비율로만 출력하므로, 16:9 비율의 720p, 4초(최소 시간) 설정을 선택했습니다. 결과물은 타일이 중앙에 위치하고 배경은 검은색으로 렌더링된 1280×720 MP4 파일입니다.
이미 과정 중에 가장자리 (edges)가 손상되어 깔끔해 보이지 않는다는 것을 알 수 있습니다.
따라서 목표는 정사각형 타일을 크롭 (crop)하고, 검은색 배경을 제거한 뒤, 투명한 배경을 가진 애니메이션 WebP로 제공하는 것이었지만, 이는 생각만큼 간단하지 않았습니다.
시도 1: 색상 탐지 (Color Detection)를 통한 배경 제거
제가 찾을 수 있었던 가장 쉬운 방법은 ezgif.com을 사용하여 다음 과정을 수행하는 것이었습니다:
- MP4를 720x720 정사각형으로 크롭 (crop)
- WebP로 변환
- 320x320 (원본 PNG 크기)으로 크기 조정 (resize)
- 검은색을 탐지하여 검은색 배경 제거
- 파일 크기를 줄이기 위한 최적화 (optimize)
결과는 지저분하게 움직이는 가장자리와 함께 기대에 훨씬 못 미쳤습니다:



‹ ›
검은색 배경은 가장자리가 불안정할 뿐만 아니라, 피사체 내부의 어두운 영역까지 제거될 수 있음을 의미합니다. 그림자, 윤곽선, 눈, 지붕 등... 탐지기(detector)는 "배경의 검은색"과 "피사체의 검은색"을 구분할 수 없습니다.
시도 2: 크로마 키 (Chroma Key)
제가 고려한 한 가지 해결책은 애니메이션을 생성하기 전에 소스 PNG에 단색의 마젠타 (Magenta) 배경을 추가하는 것이었습니다. 마젠타는 녹색이나 파란색이 포함된 콘텐츠를 위한 표준 크로마 키 (Chroma Key) 색상인데, 등각 투영 (isometric) 방식의 잎사귀, 돌, 또는 하늘에는 나타나지 않아야 하기 때문입니다.
저는 타일을 선택하고 배경색을 밝은 분홍색으로 설정했습니다:
그다음으로 이 이미지에서 새로운 애니메이션을 생성했습니다:
마지막으로, 크롭(crop)하고 배경을 제거한 다음 최적화했지만, 결과는 어쩐지 더 나빴습니다. 분홍색 배경을 깨끗하게 제거할 수 없었고, 항상 약간의 분홍색 픽셀이 남아 있었으며, 이들이 그 그림에 속하지 않는다는 것을 쉽게 알 수 있었습니다.
이 접근 방식의 문제점 중 하나는 AI 비디오 모델이 제가 선택한 정확한 분홍색을 보존하지 못했다는 것입니다. 마치 다른 색상처럼 보간(interpolated)했습니다. 결국 #FF00FF는 분홍색, 마젠타색, 보라색 구름으로 변해버렸습니다.
하나의 해결책은 감지된 경계를 침식(erode)하는 것이었습니다. 즉, 유지할 영역을 몇 픽셀만큼 줄인 것입니다. 5px에서는 떠다니는 픽셀들이 대부분 사라졌지만, 가장자리는 이제 첫 번째 시도보다 더 나빠졌습니다.
해결책: PNG 알파를 마스크로 적용하기
그러다가 깨달았습니다. 저는 이미 깨끗한 마스크를 가지고 있었다는 것을요.
원래의 정적(static) PNG에는 완벽한 알파 채널이 있었습니다. 날카로운 육각형 경계, 제가 원하는 정확한 모양이었죠. 그리고 카메라 움직임을 강제하지 않았기 때문에, 애니메이션의 모든 프레임은 이 동일한 경계 내에 들어맞는다고 가정할 수 있었습니다.
그래서 애니메이션에서 배경을 감지하고 제거하는 대신, PNG에서 알파 채널을 추출하여 모든 프레임에 스탬프처럼 찍었습니다. 감지 과정도 없고, 근사치(approximation) 처리도 없었습니다. 마스크가 정확했던 이유는 깨끗한 출처에서 왔기 때문입니다.
게다가 이 접근 방식은 쉽게 스크립트화할 수 있었습니다.
결과로 나온 스크립트는 ffmpeg를 사용하여 크롭 및 리사이즈(resize)를 수행하고, 그 다음 ImageMagick을 사용하여 프레임별로 마스크를 적용하고 재조합합니다:
#!/usr/bin/env bash
# Usage: ./make_tile.sh <name>
# Expects <name>.mp4 (16:9) and <name>.png (square, with alpha)
...
사용 예시:
./make_tile.sh ebpf
그리고 이전 이미지들에 적용된 결과는 깔끔하고, 빠르며, 쉽게 재현 가능합니다:
포맷에 관한 참고 사항
GIF 대신 WebP 또는 APNG를 사용하세요. GIF는 이진 투명도(binary transparency) — 픽셀당 완전히 켜지거나 완전히 꺼지는 방식 — 만을 지원하므로, 마스크가 아무리 깔끔하더라도 가장자리가 거칠게(jagged edges) 나타납니다. WebP와 APNG는 부드러운 안티앨리어싱(anti-aliased) 가장자리를 가진 완전한 알파(full alpha)를 지원합니다.
웹 UI의 경우, 애니메이션 WebP가 올바른 선택입니다. 압축률이 좋고, 완전한 알파를 지원하며, 브라우저 호환성이 범용적이기 때문입니다.
이 타일들이 실제로 무엇을 위한 것인지에 대해서는 곧 더 자세히 다루겠습니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기


