dev.to

Spider-Man Moonwalked Off a Billboard and Only My Test Suite Noticed

스파이더맨이 광고판 밖에서 문워크했지만 테스트만 알아챘습니다

Blender 장면을 Python 스크립트로 생성하고 렌더링하는 과정에 CI식 검증 절차를 적용한 사례입니다. 프레임별 발 위치 측정과 지면 지지 검사로 화면에서는 지나치기 쉬운 애니메이션 오류를 찾아 고쳤습니다.

AI 요약

저자는 Blender 장면을 직접 편집하지 않고 Python 스크립트로 생성합니다. 결과물인 street.blend는 소스가 아니라 빌드 산출물이며, 수정 사항을 반영하려면 스크립트를 바꾸고 장면을 다시 빌드합니다. 이 방식을 약 60초짜리 애니메이션 제작에 적용하면서 렌더링 비용을 줄이고, 애니메이션 오류를 자동 검사하는 절차를 만들었습니다.

렌더링 검토 시간을 줄이는 방법

작업 환경은 Blender 5.2, EEVEE, VRAM 4GB인 GTX 1650입니다. 렌더링 도중 GPU 사용률은 약 80%, VRAM 사용량은 2.2GB였으므로 병목은 GPU가 놀아서가 아니었습니다. 저자는 CPU와 GPU 중 무엇을 쓸지 고민하기보다 프레임마다 어떤 작업에 시간이 드는지 살폈습니다. GTX 1650에서 Cycles를 쓰면 더 느려질 것으로 봤습니다.

비용이 큰 설정 세 가지는 젖은 도로 반사를 위한 화면 공간 레이트레이싱, 프레임마다 추가 시간 단계를 계산하는 모션 블러, 샘플 수였습니다. 초안 렌더링용 --fast 옵션은 레이트레이싱과 모션 블러를 끄고 샘플 수를 8로 낮춥니다. 360p에서 프레임당 렌더 시간은 약 0.6초에서 0.33초로 줄었습니다. 1,760프레임짜리 58초 영상의 검토 렌더 시간도 약 18분에서 10분으로 단축됐습니다. 반사 표현이 덜하고 빠른 동작이 선명해지지만, 착지 위치처럼 동작을 확인하는 검토에는 문제가 없고 최종 렌더에는 원래 설정을 씁니다.

그 밖에도 구도와 동작 배치만 확인하는 480×270 해상도 옵션, 동영상 대신 먼저 살펴보는 저해상도 콘택트 시트, 특정 프레임 이후만 다시 렌더링하는 기능을 추가했습니다. 느린 작업을 최적화할 때 먼저 비용이 어디서 발생하는지 측정하라는 점은 느린 API를 프로파일링할 때와 같다고 설명합니다.

소스 코드와 프레임별 수치로 오류 찾기

장면을 코드로 생성하므로 버전 관리 대상도 .blend 파일이 아니라 스크립트입니다. 검토를 마칠 때마다 커밋하면 다른 사람에게 보여준 버전을 다시 빌드할 수 있습니다. Blender의 실행 취소 기록이나 백업 파일보다 Git 커밋을 실제 스냅샷으로 삼고, 이미 렌더한 영상도 비교를 위해 남깁니다.

애니메이션에서는 높이가 다른 동작을 이어 붙일 때 수평 이동뿐 아니라 수직 위치도 맞춰야 했습니다. 처음에는 루트 높이를 블렌드 구간에 걸쳐 부드럽게 바꿨지만 문제가 해결되지 않았습니다. 원인은 엉덩이 높이가 아니라 포즈가 섞이며 다리가 펴져 발이 올라가는 데 있었습니다. 저자는 프레임마다 양쪽 발끝 중 낮은 쪽을 측정하고, 바닥에서 약 5cm 높이에 오도록 루트 위치를 보정했습니다. 보정량은 ±35cm로 제한하고 주변 프레임과 평균을 내 흔들림을 줄였습니다. 실제 점프까지 바닥에 붙이려는 과잉 보정을 막기 위해서입니다. 측정 결과, 빌보드 난간의 웅크리기에서 문워크로 넘어갈 때 캐릭터가 22cm 튀던 문제가 발끝과 바닥 사이 약 2~10cm 간격으로 줄었습니다.

측정 도구는 뷰포트에서 놓친 오류도 찾았습니다. 컷 사이 키프레임을 선형 보간해 옥상과 거리 사이에 캐릭터가 약 18m 떠오르는 한 프레임짜리 장면이 생겼습니다. 매 프레임 키를 넣어 중간 보간을 없앴습니다. 블렌드 시작점이 소수 프레임에 놓이면 정수 프레임 렌더링과 어긋나는 문제는 컷 위치에 math.ceil을 적용해 해결했습니다. 키프레임을 제거하며 인덱스가 밀려 엉뚱한 키를 삭제하던 문제는 인덱스를 모은 뒤 뒤에서부터 삭제하도록 고쳤습니다.

렌더 전 지면 지지 검사

저자는 약 40줄짜리 scripts/check_support.py를 렌더 전에 실행하는 검사로 추가했습니다. 영상에서 세 프레임마다 캐릭터 발끝을 찾고 아래로 레이캐스트를 쏴 지면을 확인합니다. 캐릭터나 소품은 지면으로 취급하지 않으며, 공중에 떠야 하는 스윙·뒤집기 장면은 검사에서 제외합니다. 발과 지면 사이 간격이 25cm를 넘거나 발이 바닥에 잠기면 해당 프레임을 표시하고, 연속된 문제 프레임은 묶어 테스트 보고서처럼 출력합니다.

검사는 광고판 가장자리 밖에서 6.5m 문워크하는 장면을 찾아냈습니다. 화면 뒤에서 걷는 사람들과 반대 방향으로 움직이는 문제도 함께 발견해, 광고판 관리용 철제 통로를 만들고 캐릭터의 진행 방향을 바꿨습니다. 폭 25cm인 벽 광고판에서 40cm로 벌린 발이 허공에 걸친 장면에는 1.25m짜리 발판을 추가했습니다. 회전 블렌드 중 캐릭터가 난간에서 2m 벗어난 문제는 인플레이스 애니메이션의 루트 피벗이 엉덩이에서 약 4m 떨어져 있어 몸이 잘못된 점을 중심으로 회전한 탓이었습니다. 회전 구간마다 루트를 키프레임으로 지정해 엉덩이가 직선으로 움직이게 했습니다.

dev.to 반응

  • @anh_nguynvn_0478e614ba — 코드 리뷰에서 영향 범위를 고려하는 발상은 기존 정적 분석보다 큰 발전입니다. 린트와 단위 테스트를 모두 통과한 PR이 의존성 그래프를 충분히 파악하지 못해 전혀 관련 없어 보이는 후속 서비스에 문제를 일으키는 경우를 자주 봤습니다. 스파이더맨 사례도 실제 렌더링 결과보다 로직만 살피면 시각적 회귀나 UI 오류를 놓칠 수 있다는 점을 잘 보여줍니다. 복잡한 리팩터링을 관리하며 배운 점은, 아무리 좋은 AI 리뷰 도구도 런타임 환경 전체를 파악하지 못하면 어려움을 겪는다는 것입니다. 스냅샷 테스트나 시각적 회귀 검사를 영향 범위 계산에 넣어야 코드상으로는 멀쩡해 보이지만 브라우저에서 깨지는 사례를 막는 데 실질적인 도움이 됩니다.

원문: dev.to / 번역·요약: Trawling