3줄 요약

  1. sprite-gen은 한국 개발자 aldegad가 2026년 5월에 공개한 Apache-2.0 오픈소스다. Codex와 Claude에 설치해 쓰는 스킬이면서 파이썬 CLI이기도 하다. 기준 그림 한 장을 받아 상태별 이미지를 생성한 뒤, 배경을 지우고 프레임을 잘라 게임 엔진이 바로 읽는 아틀라스를 만든다.
  2. 이 프로젝트가 다루는 문제는 이미지 모델에게 “스프라이트 시트를 그려 줘"라고 요청했을 때 나오는 산출물이다. 프레임마다 얼굴이 달라지고, 배경이 깨끗하게 빠지지 않고, 자세가 격자를 벗어난다. 저자는 그 각각을 생성 프롬프트로 고치려 들지 않고, 생성이 끝난 다음의 파이프라인 단계에서 해결했다.
  3. 문서에는 성공한 방법만 적혀 있지 않다. 배경 테두리를 깎아 내던 방식을 왜 버렸는지, 영상 보간 기술을 스프라이트 처리에서는 왜 빼고 영상 이음매에서는 왜 그대로 쓰는지, 걷기와 달리기를 왜 아직 실험 상태로 표시하는지가 측정값과 함께 남아 있다.

왜 스프라이트 시트를 그냥 그려 달라고 하면 안 되는가

저자가 README 첫 문단에 적어 둔 진단은 짧다. 이미지 모델에게 스프라이트 시트를 요청하면 프레임마다 얼굴이 바뀌고, 배경은 키 색만으로 깔끔하게 지워지지 않으며, 자세는 서로 겹치면서 격자를 벗어난다. 귀여운 데모는 나오지만 게임 엔진이 삼킬 수 있는 PNG는 나오지 않는다.

sprite-gen은 그 간격을 메우는 도구다. 기준 이미지 한 장을 주면 상태별 이미지를 한 행씩 생성하면서 캐릭터의 정체성을 유지한다. 크로마 배경은 실제 알파로 바꾸고, 자세마다 깨끗한 투명 프레임으로 잘라 낸다. 그리고 기계가 읽을 수 있는 manifest.json의 frame_layout과 함께 아틀라스를 굽는다. 매니페스트에는 프레임의 절대 사각형 좌표와 상태별 초당 프레임 수, 반복 여부가 들어간다. 엔진은 사각형을 읽을 뿐 격자를 추측하지 않아도 된다.

같은 기준 그림을 영상 모델에 넘기면 결과가 달라진다. 모션 상태마다 이음매 없이 반복되는 투명 루프가 만들어진다.

네 갈래 파이프라인

CLI의 모든 명령은 단독으로도 돌고 파이프라인의 한 단계로도 붙는다. 저자는 이것을 네 묶음으로 나누어 놓았다.

묶음무엇이 들어가서 무엇이 나오는가
A. 아틀라스 행기준 그림 한 장과 상태 목록에서 sprite-sheet-alpha.png와 manifest.json의 frame_layout이 나온다. 정지 자세에는 호흡 동작도 들어간다
B. 영상에서 루프로기준 그림 한 장에서 상태마다 이음매 없는 투명 GIF와 WebP, 스트립이 나온다. Grok Imagine이 움직이고 클립 고유의 주기에 맞춰 잘린다
C. 유틸리티가져온 이미지나 격자 시트를 깨끗한 투명 조각으로 잘라 주고, 완성된 아틀라스를 다시 큐레이션할 수 있는 상태로 되돌려 준다
D. 후처리완성된 시트를 다시 굽지 않고 색상 변형본을 만들거나, 리그 레이어를 합성하거나, Aseprite와 Phaser와 Flame용으로 내보낸다

A 묶음의 생성 제공자는 둘이다. codex는 ChatGPT OAuth 인증을 거쳐 GPT image_gen을 쓰고, grok은 xAI Imagine을 쓴다. B 묶음에서 영상을 만들려면 사용자 자신의 자격 증명이 필요하다. grok CLI 로그인이나 XAI_API_KEY가 있어야 하고, 저장소에는 아무 키도 들어 있지 않다. 여기에 ffmpeg와 libwebp의 img2webp가 필요하다. img2webp를 요구하는 이유도 문서에 적혀 있다. Pillow의 애니메이션 저장 경로는 알파를 정확히 보존하는 옵션을 빠뜨린다.

대상은 캐릭터만이 아니다. 외부 기여자가 제안한 주제 프로필이 들어가면서 이펙트도 같은 파이프라인을 탄다.

sprite-gen이 뽑아낸 이펙트 스프라이트 모음. 불꽃 폭발, 얼음 파편, 독 구슬, 번개 문양, 도깨비불, 빛 알갱이가 각각 프레임별로 투명 배경 위에 놓여 있다.

배경을 지우는 방식이 한 번 바뀌었다

배경 제거는 이 도구에서 가장 많이 손본 부분이다. 예전 방식은 키 색과 피사체가 섞인 경계 픽셀을 따로 깎아 냈다. 저자는 v1.13.0에서 그 깎아 내기를 걷어내고 대신 섞인 값을 다시 푸는 쪽으로 바꿨다.

원리는 단순한 혼합 모형이다. 관측된 색은 피사체 색과 키 색이 어떤 비율로 섞인 결과라고 보고, 그 비율을 풀어서 피사체의 색과 부분 알파로 나눈다. 그래서 머리카락 한 올의 안티에일리어싱과 1픽셀 외곽선이 사라지지 않는다.

일러스트 한 장에 마젠타 키를 적용한 세 단계 비교. 왼쪽은 마젠타 배경 위의 원본, 가운데는 v1.12.0의 테두리 깎기 결과, 오른쪽은 v1.13.0에서 섞인 색을 다시 푼 결과다. 초록 머리카락 끝이 오른쪽에서 온전히 남아 있다.

픽셀 아트에서는 손실이 눈으로 셀 수 있는 크기로 나타난다. 문서에 붙은 확대 비교에는 예전 방식이 외곽선 픽셀 1,781개를 먹어 치웠다고 적혀 있다.

픽셀 아트에 초록 키를 적용한 확대 비교. 왼쪽은 초록 배경의 원본, 가운데는 v1.12.0에서 검은 1픽셀 외곽선이 깎여 나간 결과, 오른쪽은 깎기를 걷어내 외곽선이 살아 있는 결과다.

키 색을 고르는 규칙도 문서에 표로 정리되어 있다. 마젠타가 기본값이라는 통념을 저자는 명시적으로 거부한다. 키 색 지우기는 색 공간에서 키 주변의 일정한 반경 안을 통째로 삭제하는 동작이라서, 피사체 색이 그 반경 안에 들어오면 어디에 있든 사라진다.

  • 분홍이나 보라 계열 피사체에는 초록 키를 쓴다.
  • 진한 빨강과 자주색 머리카락은 마젠타와 이웃이다. 붉은 계열에도 초록 키를 쓴다.
  • 초록과 청록 계열 피사체에는 마젠타 키를 쓴다.
  • 파란 피사체에는 시안이나 파랑 계열 키를 피한다.

판단이 서지 않으면 --chroma-key auto가 기준 그림을 표본으로 삼아 후보를 점수로 매긴다. 이 모드는 더 안전한 후보가 있으면 피사체가 지우기 반경 안에 들어오는 키를 후보에서 뺀다. 어떤 후보도 피사체를 벗어나지 못하면 표준 오류로 경고한다. 눈동자나 보석처럼 전체의 1퍼센트도 되지 않는 작지만 중요한 부분이 조용히 지워지는 일을 막으려는 장치다.

가짜 픽셀 아트를 격자에 되돌린다

저자는 AI가 만든 “픽셀 아트"가 픽셀 아트가 아니라고 말한다. 블록이 흔들리고, 가장자리에 안티에일리어싱이 묻어 있고, 격자가 한 행 안에서도 어긋난다. 그래서 균일한 격자로 자르면 블록 하나가 옆 블록으로 번진다.

이미 알려진 대응은 블록 크기를 연속 구간의 길이에서 추정한 뒤 다시 양자화하는 것이다. 저자가 지적하는 문제는 그 추정이 프레임마다 따로 이루어진다는 점이다. 그러면 걷기 한 사이클 안에서 칸 크기가 프레임마다 숨을 쉰다.

이 프로젝트는 Backbone Lattice라는 방식으로 대응한다. 피사체 전체의 격자를 한 번만 측정하고, 모든 절단 위치를 그 격자에 맞춘다. 프레임별 간격 검출값은 행 전체와 프레임 전체를 함께 보아 정하고, 그렇게 모인 다수의 값이 배음 오검출을 걸러 낸다. 절단은 실제 색 경계에 놓이며, 측정된 간격에 비례하는 최소 칸 너비가 이웃한 두 절단이 같은 띠로 무너지는 일을 막는다.

정렬 기준을 어떻게 잡느냐도 잔떨림을 좌우한다. 기본값인 foot-centroid는 알파 채널의 아래쪽 20퍼센트, 그러니까 다리를 기준으로 맞춘다. 뒤로 흐르는 머리카락이나 망토가 몸을 칸 축에서 끌어당기지 않게 하려는 선택이다. 여기에 외부 프로젝트에서 옮겨 온 alpha-centroid 모드가 하나 더 있다. 원 저자가 잰 값으로 정렬 잔떨림의 표준편차가 27.2픽셀에서 0.2픽셀로 내려갔다.

정지한 그림에 숨을 넣는다

정지한 대기 자세는 얼어붙은 것으로 읽힌다. Breathe는 자세 한 장을 살아 있는 루프로 바꾼다. 다시 생성하지도, 다시 추출하지도, 그림을 더 그리지도 않는다. 사이드카 파일에 필드 하나만 추가하면 된다.

"breathe": { "depth": 0.05, "breaths": 3 }

이 기능이 지키는 약속은 네 가지다.

  • 해부를 읽는다. 엔진이 실루엣을 재서 목의 잘록한 부분, 목이 없는 덩어리에서는 좌우 대칭인 눈 한 쌍, 몸통과 팔다리의 너비 차이를 찾는다. 머리는 모든 프레임에서 비트 단위로 동일하게 유지되고, 날개와 팔은 밀릴 뿐 늘어나지 않는다.
  • 픽셀을 지킨다. 행과 열의 대응은 정수로만 이루어진다. 1픽셀 외곽선은 1픽셀 외곽선으로 남는다.
  • 자로 잴 수 있다. 재생 화면 위에서 강체 경계선과 몸의 축, 몸통 너비를 마우스로 끌어 위치를 바꿀 수 있다. 손을 떼면 서버가 해부를 다시 계산하고, 계산하는 동안에도 미리보기는 계속 숨을 쉰다.
  • 미리보기와 결과가 같다. 웹뷰의 미리보기와 파이썬이 구운 결과가 같은 바이트를 내놓고, 골든 테스트가 그것을 강제한다.

호흡 편집기 화면. 주황색 문어 모양 픽셀 캐릭터 위에 빨간 강체 경계선과 파란 몸 축, 점선 몸통 너비 선이 겹쳐 있고 아래쪽에 18프레임 필름스트립이 놓여 있다.

앉기나 눕기 같은 정지 자세 행의 레시피도 숫자로 고정되어 있다. 정지 한 컷을 복제해서 초당 4프레임으로 돌리고 허리선 호흡을 세 번 넣으면 총 18컷이 된다. 예전에는 11컷짜리 짧은 루프를 썼다. 거기에 호흡을 여러 번 밀어 넣었더니 1픽셀 위상이 매 프레임 뒤집혀 진동으로 보였다. 그래서 호흡 한 번에 6프레임을 확보하는 쪽으로 바뀌었다.

영상에서 이음매 없는 루프를 잘라낸다

B 묶음은 다른 문제를 푼다. 이미지에서 영상을 만드는 모델은 연속적이고 반복되지 않는 움직임을 그린다. 마지막 프레임은 첫 프레임과 같아지지 않는다. 그래서 클립을 그대로 반복하면 눈에는 튐이 보인다. 이 파이프라인은 기준 그림에 여백을 덧대고, 영상을 만들고, 프레임마다 배경을 지운 다음, 그 안에서 반복되는 한 주기를 찾아 잘라낸다.

먼저 캔버스다. Grok Imagine은 이미지에서 영상을 만들 때 화면 비율 요청을 무시하고 입력 이미지의 구도를 그대로 따른다. 3대 4로 요청했는데 960 곱하기 960이 돌아왔다. 점프에서 머리카락이 화면 밖으로 나가는 문제는 프롬프트로 고쳐지지 않았고, 기준 그림에 여백을 덧대는 것으로 고쳐졌다. 이 때문에 캔버스는 모션 상태별 설정이 되었고, 표 하나가 그것을 관리한다.

상태모양비율여백
jump세로3대 4머리 위로 34퍼센트
attack가로16대 9바라보는 쪽 앞으로 28퍼센트
projectile가로16대 9앞으로 34퍼센트
나머지 전부정사각1대 1제자리 동작이라 기준 그림에 들어간다

덧댈 여백은 기준 그림 자신의 모서리 색으로 채운다. 모서리가 한 가지 평평한 색이 아닌 그림은 거부된다. 추측하지 않고 거절하는 쪽을 택한 것이다.

프롬프트 문구에도 실패에서 나온 규칙이 하나 있다. 걸음걸이를 설명할 때 팔다리를 이름으로 부르지 않는다. 프롬프트 초안에 “두 발로 걷는다, 무릎, 팔을 흔든다"라고 쓰자 네 발 짐승과 다리가 없는 덩어리가 모순에 빠졌다.

루프를 자르는 순서는 주기가 먼저이고 이음매가 나중이다. 저자가 2026년 9월 8일에 루프 열다섯 개를 손으로 돌리면서 얻은 교훈이 그것이다. 시작점 하나를 놓고 가장 비슷한 나중 프레임을 찾으면 다리가 서로 바뀐 1.5주기 닮은꼴에 걸린다. 옆걸음은 주기가 28프레임인데 39프레임을 골랐고, 달리기는 17프레임인데 25프레임을 골랐다.

그래서 지금은 클립 전체의 주기 프로파일을 먼저 읽는다. 가장 깊은 골의 15퍼센트 안에 드는 국소 최소 가운데 가장 작은 것을 주기로 삼는다. 정확한 반복은 주기의 두 배와 세 배에서도 다시 내려가지만, 반주기 닮은꼴은 그만큼 깊이 내려가지 않는다. 두 발 짐승과 네 발 짐승 모두에서 반주기의 골은 온전한 주기의 55퍼센트에서 70퍼센트 깊이에 그쳤다. 주기가 정해진 다음에야 그 길이에 맞는 시작점을 이음매 품질로 고른다.

게이트는 실패를 숨기지 않는다. 주기성이 0.15에 못 미치면 거기서 멈추고, 이음매 비율이 2.0을 넘어도 멈춘다. 만들어진 GIF와 WebP는 다시 열어서 프레임 수와 반복 설정, 모서리 투명도까지 확인한다.

한 번만 일어나는 동작에는 다른 검출기가 붙는다. 점프를 반복해 달라고 요청해도 모델이 한 번 뛰고 나머지 시간을 서 있는 경우가 있다. 그것은 주기가 아니고 주기성 게이트도 그렇게 말한다. 점프와 공격처럼 본래 한 번짜리인 상태에서는 실패 대신 두 번째 검출기가 돈다. 다른 모든 프레임과의 평균 거리가 가장 작은 프레임을 정지 자세로 잡고, 거기서 뚜렷하게 벗어난 구간을 동작으로 보고, 앞뒤에 정지 프레임을 두 장씩 덧대어 잘라 낸다. 이음매가 정지에서 정지로 이어지도록 만들어 버리는 것이다. 이 전환은 조용히 일어나지 않는다. 어떤 방식으로 잘랐는지가 보고서에 기록되고, 실패한 주기성 수치도 함께 남는다.

반복되지 않는 배경 영상을 무한 루프로 바꾸는 일은 또 다른 문서가 맡는다. 저자는 그 문서 첫머리에 이것이 B 묶음과 다른 일이라고 적어 두었다.

마지막 10퍼센트를 맡는 큐레이션 뷰

문서의 표현을 그대로 옮기면, 생성은 90퍼센트까지 데려다준다. 남은 부분을 출시 가능한 상태로 만드는 곳은 웹뷰다. 별도의 스튜디오나 프레임워크에 기대지 않고 스킬이 설치된 곳이면 어디서든 돈다.

큐레이션 웹뷰 화면. 침대, 책장, 탁자, 책상, 입간판이 아이소메트릭 픽셀 아트로 나란히 놓여 있고 각 카드에 선택됨 표시와 변형값이 붙어 있다.

상태마다 두 줄이 놓인다. 위는 재생 순서이고 아래는 후보 더미다. 프레임의 손잡이를 끌어 순서를 바꾸거나 아래쪽 후보를 위로 끌어올려서, 여러 번 생성한 결과 중 좋은 컷만 모아 루프 하나를 다시 짤 수 있다. 배치는 저장되어 다시 열어도 복원된다.

프레임별 변형은 원본을 건드리지 않는다. 프레임을 끌면 이동하고, 휠을 굴리면 크기가 바뀐다. 위쪽 손잡이는 회전이고, 왼쪽 아래 손잡이는 기울이기다. 좌우 반전 토글도 있다. 편집 결과는 curation.json 사이드카에 쌓이고 원본 PNG는 다시 쓰이지 않는다. 미리보기와 굽기가 같은 아핀 행렬을 쓰므로, 화면에서 맞춘 모습 그대로 결과가 나온다. 미리보기는 상태의 초당 프레임 수로 재생되고 0.25배에서 4배까지 속도를 바꿀 수 있다.

무엇을 약속하고 무엇을 약속하지 않는가

이 프로젝트의 문서에서 내가 가장 눈여겨본 것은 저자가 스스로 범위를 좁혀 놓은 대목이다.

기본 약속은 의도적으로 소박하다. 사용자가 스킬을 설치하고 기준 그림과 간단한 동작 몇 개를 주면 스프라이트 시트와 GIF 미리보기, QA 메모를 받는다. 저자는 기본 경로를 “게임에 바로 쓸 인간형 이동 동작"으로 소개하지 말라고 문서에 적어 두었다.

안정적인 기본 상태는 대기, 점프, 공격, 손 흔들기이고 각각 4프레임이다. 걷기와 달리기, 정면 걷기 같은 순환 이동 동작은 실험 상태로 분류된다. 생성은 되지만 모션 연속성 검사를 깨끗하게 통과하지 못하면 보고서에 실험이라고 적어야 한다.

이 모션 연속성 검사는 통과하지 못하면 다음 단계로 넘어갈 수 없는 항목이다. 프레임 수와 알파, 정체성이 모두 맞아도 움직임으로는 쓸 수 없을 때가 있기 때문이다. 그래서 상태마다 콘택트 시트와 애니메이션 미리보기를 만들어 루프를 직접 보고 판정한다. 인간형에서 확산 모델이 가장 자주 흔드는 부위는 무릎과 팔꿈치, 엉덩이, 손이다. 문서에는 이 부위를 모든 프레임에서 빠짐없이 살피라는 경고가 하나 더 들어 있다. 판정이 애매하면 앞선 맥락을 주지 않은 별도 비전 모델 세션에 GIF를 넘겨 두 번째 의견을 받으라고 권한다.

프레임 사이를 채우는 중간 프레임에서도 저자는 한 번 물러섰다. 2026년 7월부터 광학 흐름 기반 보간을 스프라이트 처리에서 뺐다. 실제 비교에서 그 방식은 외형 변화를 흐릿한 겹침으로 만들었고, 생성 모델에 중간 자세를 그리게 하는 쪽이 깨끗한 픽셀을 내놓았다. 같은 비교에서 codex가 정체성을 가장 잘 지켰고 grok은 흔들렸다. 그러면서도 같은 기술을 영상 루프의 이음매에서는 그대로 쓴다. 거기서는 유체처럼 뭉개지는 성질이 정확히 필요한 것이기 때문이다.

누가 만들었고 누가 고쳤는가

저장소 주인 aldegad는 GitHub 프로필에 이름에는 darkest_alex, 위치에는 korean이라고 적어 두었다. 저장소가 처음 만들어진 날은 2026년 5월 12일이다. 2026년 9월 11일 기준으로 별 1,077개와 포크 94개가 붙어 있다. 최신 태그는 v2.1.0이다. 마지막 푸시는 내가 이 글을 쓰기 몇 시간 전이었고, 그 하루 동안에만 커밋 열 개가 올라왔다.

CONTRIBUTORS.md에는 외부 기여자 아홉 명이 이름과 PR 번호와 함께 적혀 있다. 크로마 정리에서 피사체 색을 보호한 처리와, 기계가 읽는 매니페스트 경로를 이식 가능한 형태로 바꾼 수정이 그 목록에 있다. Aseprite와 Phaser와 Flame 내보내기, 캐릭터와 이펙트 주제 프로필도 외부에서 들어왔다. 윈도우에서 제공자 CLI 경로와 UTF-8 입출력을 고친 수정, 공유 독자와 배타 발행자를 위한 윈도우 잠금 백엔드 추가도 포함된다. 아이디만으로 단정할 수는 없지만 한국어권으로 보이는 계정이 여럿이다.

머지되지 않은 PR도 한 자리를 차지하고 있다. 한 기여자가 오프라인에서 705개 사례를 훑은 뒤 크로마 키 기본 임계값을 96에서 80으로 낮추자고 제안했다. 저자는 그 PR을 받지 않았다. 대신 그 벤치마크를 계기로 실제 파이프라인에서 비교를 다시 돌렸고, 그 결과로 96이 기본값으로 확인되었다고 적었다. 반려된 제안이 무엇을 남겼는지가 이름과 함께 문서에 남아 있다.

컴포넌트 행 방식 자체는 Apache-2.0으로 공개된 hatch-pet 스킬에서 영감을 얻었다고 출처를 밝혀 두었다.

가장 흥미로운 지점

이 저장소를 읽는 동안 내 눈을 붙든 것은 기능 목록보다 문서가 실패를 다루는 방식이었다.

배경 테두리를 깎아 내던 방식은 그냥 사라지지 않았다. 그것이 픽셀 아트 외곽선 1,781개를 먹었다는 비교 이미지와 함께 남아 있다. 광학 흐름 보간은 스프라이트 처리에서 빠졌지만 영상 이음매에서는 그대로 쓰인다. 왜 한쪽에서만 맞는지도 같은 문단에 적혀 있다. 프롬프트에서 팔다리를 이름으로 부르지 않게 된 것은 네 발 짐승과 다리 없는 덩어리가 모순에 빠진 날의 기록에서 나왔다. 심지어 받아들이지 않은 제안까지 기여자 명단에 남아 있다.

AI로 게임 에셋을 만드는 도구는 지금 매주 쏟아진다. 대부분은 데모가 좋고 설명이 짧다. 이 저장소는 반대로 되어 있다. 데모도 좋지만, 무엇이 안 되는지를 숫자와 함께 적어 놓은 분량이 훨씬 길다. 걷기와 달리기를 아직 실험으로 표시한 채로 별 1,000개를 넘긴 프로젝트를 보는 일은 흔치 않다.

이 두 가지를 함께 놓고 보면, 그림 한 장에서 게임 에셋을 만드는 일의 병목이 어디에 있는지가 드러난다. 생성 품질보다, 생성 뒤의 단계를 같은 입력에서 같은 출력이 나오도록 만드는 데 병목이 있다. 배경을 어떻게 지우고, 격자를 어디에 고정하고, 어떤 프레임을 채택하고, 그 결정을 어떻게 다시 재현할 것인가. 이 저장소가 파이썬 코드로 쓰고 있는 것은 대부분 그 부분이다.

출처

sprite-gen은 aldegad(darkest_alex)가 Apache-2.0으로 공개한 저장소다. 2026년 5월 12일에 처음 올라왔고, 이 글은 v2.1.0을 기준으로 삼았다. 원문: https://github.com/aldegad/sprite-gen

본문 이미지는 모두 저장소의 docs/assets/ 문서 자산이며 저장소와 같은 Apache-2.0 라이선스를 따른다. 표지는 저장소의 소개 GIF에서 한 프레임을 뽑은 것이다.