본문으로 건너뛰기

스프라이트 시트 만들기 · 프레임을 아틀라스로 패킹

프레임 이미지·GIF·.aseprite 파일을 넣으면 설정을 바꿀 때마다 워커에서 바로 다시 패킹된 촘촘한 스프라이트 시트와 엔진이 읽는 데이터 파일을 얻습니다.

스프라이트 시트는 여러 프레임을 이미지 한 장에 모아 게임이 텍스처 수십 장 대신 한 장만 읽게 합니다. 촘촘하게 패킹한 아틀라스는 여기에 프레임마다 이름과 사각 영역을 적은 데이터 파일이 붙습니다. 번호 붙은 PNG, GIF, .aseprite 파일을 넣고 엔진 프리셋을 고르면 Nerulio가 브라우저 안에서 패킹하고(기본값: MaxRects, 트림 켬, 간격 2px) 그 엔진이 읽는 데이터 파일과 함께 PNG를 내보냅니다. 칸 크기가 모두 같은 단순 격자 시트는 아래에 연결된 기존 만들기 도구를 쓰세요.

패킹할 프레임 이미지, GIF 또는 .aseprite 파일을 끌어다 놓으세요
빈 Studio 열기
브라우저에서 처리하며 파일은 업로드되지 않습니다.
Studio 패킹·내보내기: 프레임마다 윤곽이 표시된 아틀라스 페이지, 사용 면적, 내보내기 대상
CC0 에셋(OpenGameArt)을 연 실제 Studio 화면입니다.
내보내기 대상
  • Godot 4검증됨· Godot 4.7.2
  • Unity 6검증됨· Unity 6000.5.3f1
  • Phaser 3 / 4검증됨· Phaser 3.90 + 4.2
  • PixiJS 8검증됨· PixiJS 8.21
  • Aseprite JSON검증됨· Phaser load.aseprite · PixiJS 8.21
  • .aseprite검증됨· Aseprite 1.3.18
  • Spine / libGDX검증됨· spine-canvas 4.2
  • Starling / Sparrow XML검증됨· Phaser 4.2
  • LÖVE검증됨· LÖVE 11.5
  • Defold빌드 확인· Defold bob.jar 1.13.1
  • GameMaker미검증
  • CSS sprites검증됨· Chromium
  • GIF / APNG디코딩 확인· Pillow

격자 시트와 패킹 아틀라스

격자 시트는 모든 프레임에 같은 크기의 칸을 줍니다. 그래서 엔진은 계산만으로 n번째 프레임을 찾습니다. 열 = n mod 열 수, 행 = n ÷ 열 수(내림). 데이터 파일이 필요 없지만, 칸마다 가장 큰 프레임만큼 자리를 차지하고 투명한 테두리까지 그대로 저장됩니다.

패킹 아틀라스는 프레임마다 보이는 픽셀만 남기고 잘라 빈자리에 끼워 넣습니다. 위치를 계산으로 알 수 없으니 패커가 데이터 파일을 씁니다. 프레임 이름, 페이지 위 저장 위치(frame), 원래 캔버스에서의 위치(spriteSourceSize), 원래 캔버스 크기(sourceSize), 90도 돌려 저장했는지(rotated)입니다. 엔진은 이 숫자로 프레임을 원래 크기 상자 안에 그리므로 트림한 프레임도 제자리에 있습니다.

가장자리를 지키는 설정이 두 가지 있습니다. 모양 간격은 프레임 사이에 투명 픽셀을 두고, 확장(extrude)은 프레임 바깥쪽 픽셀을 한 겹 더 복사해 둡니다. 텍스처 필터가 가장자리 바로 바깥을 읽어도 이웃 프레임 대신 같은 색을 읽게 됩니다. 회전은 면적을 조금 줄이지만 회전된 프레임을 되돌려 그리는 엔진은 일부뿐이라, Nerulio 프리셋은 엔진 검증에서 올바르게 그려진 PixiJS와 Spine에서만 회전을 허용합니다.

페이지
아틀라스 이미지 한 장. 최대 크기에 다 들어가지 않으면 다음 페이지로 넘어갑니다(최대 64장).
트림
프레임의 투명 테두리를 잘라 내고 오프셋을 기록하는 것. 그래서 원래 자리에 그려집니다.
모양 간격(shape padding)
프레임 사이의 투명 픽셀. 기본 2px.
확장(extrude)
프레임 가장자리 픽셀을 바깥에 복사한 띠. 기본 0, LÖVE 프리셋은 1.
별칭(alias)
보이는 픽셀이 똑같은 프레임은 저장 영역 하나를 함께 씁니다.

예시: 40 × 29 달리기 프레임 6장

CC0 닌자 달리기 동작 6프레임(각 40 × 29px, 대부분 투명)을 Nerulio의 Phaser 프리셋(트림 켬, 간격 2, 회전 없음)으로 패킹한 결과를 다른 배치와 비교했습니다.

배치                             페이지      면적        가로 띠 대비
가로 띠, 6 × 40px                240 × 29    6,960 px²   100 %
패킹, 트림 끔, 간격 2             82 × 91    7,462 px²   107 %
패킹, 트림 켬, 간격 2             38 × 50    1,900 px²    27 %
패킹, 트림 켬, 회전 허용          33 × 57    1,881 px²    27 %

보이는 픽셀(바운딩 박스 6개 합)              1,591 px²
트림 페이지의 사용 비율          1,591 / 1,900 = 0.84

"run_0": { "frame": {"x":0,"y":34,"w":18,"h":15},
           "spriteSourceSize": {"x":10,"y":10,"w":18,"h":15},
           "sourceSize": {"w":40,"h":29}, "rotated": false, "trimmed": true }

run_0은 18 × 15픽셀만 저장됩니다. 엔진은 이 조각을 40 × 29 상자 안에서 오른쪽으로 10px, 아래로 10px 옮겨 원래 자리에 그립니다. 절약은 트림 덕분입니다. 트림 없이 패킹하면 프레임 사이 간격 때문에 오히려 가로 띠보다 조금 커집니다.

이렇게 작동합니다

  • MaxRects(5가지 규칙), Skyline, Guillotine. "모두 시도"는 가장 작은 페이지를 고릅니다.
  • 오프셋을 유지하는 트림, 같은 프레임 중복 제거, 가장자리 확장, 테두리·도형 여백, POT·정사각형·고정 크기, 최대 64페이지.
  • 최근접 이웃 방식 @0.5x~@4x 배율 변형, 선택형 사전 곱셈 알파.
  • 색이 정확한 PNG: 프레임을 캔버스를 거치지 않고 JavaScript로 디코딩해 색과 알파가 변하지 않습니다(인터레이스 PNG는 브라우저 디코더를 쓰며 화면에 표시합니다).

사용 방법

  1. 프레임(번호 붙은 PNG 폴더도 가능)이나 GIF·.aseprite 파일을 넣습니다.
  2. 엔진 프리셋을 고르면 아틀라스가 바로 다시 패킹됩니다.
  3. 사용률·페이지·프레임 목록을 확인하고 필요하면 트림·여백·크기를 바꿉니다.
  4. 엔진용 내보내기를 누릅니다.

엔진마다 받는 파일과 시트를 불러오는 법

PNG는 늘 데이터 파일 옆에 두세요. 데이터 파일이 이미지 이름을 적고 있습니다(JSON의 meta.image, XML의 imagePath, Spine .atlas의 페이지 줄).

파일용도
run.png + run.json (Phaser 3 / 4)this.load.atlas("run", "run.png", "run.json") 후 this.add.sprite(x, y, "run", "run_0"). 자세한 내용은 Phaser 아틀라스 페이지.
run.png + run.json (PixiJS 8)const sheet = await Assets.load("run.json") 후 sheet.textures["run_0"]이나 sheet.animations["run"]. PixiJS 스프라이트시트 JSON 참고.
run.tres + run.tscn (Godot 4)아틀라스 대신 바로 쓰는 SpriteFrames 리소스와 씬. Godot에서 스프라이트 시트 참고.
run.unity.json + importer script (Unity 6)편집기 스크립트가 텍스처를 자르고 클립을 만듭니다. Unity에서 스프라이트 시트 참고.
run.lua, run.atlas, run.xml, run.cssLÖVE 쿼드, Defold·Spine 아틀라스, Sparrow XML, CSS 클래스: LÖVE, Defold, Spine, CSS 스프라이트.

결과 확인

  • 패킹·내보내기의 사용 비율을 봅니다. 0.84는 페이지의 84%가 보이는 프레임 면적이라는 뜻입니다. 낮으면 대개 트림이 꺼져 있거나 프레임 하나가 유난히 큽니다.
  • 패킹된 프레임 목록의 줄에 마우스를 올리면 캔버스 → 저장 크기, 페이지, 트림·회전·"같은 프레임"(별칭) 표시가 보입니다.
  • 엔진에서 트림된 프레임 하나를 트림 안 된 이웃 프레임과 같은 점에 그려 봅니다. 어긋나면 로더가 spriteSourceSize를 무시하는 것입니다(문제 해결 참고).

문제 해결

증상유력한 원인확인 방법해결
애니메이션 재생 중 프레임이 튀거나 흔들림트림된 프레임을 오프셋 없이 그림. 로더나 코드가 frame만 쓰고 spriteSourceSize·sourceSize는 무시함트림이 서로 다른 두 프레임을 같은 점에 그려 봄. 맞아야 정상트림 정보를 읽는 로더를 쓰거나 트림을 끄고 패킹(페이지가 커짐). 트림 후 흔들림 참고
확대하거나 소수 픽셀만큼 움직일 때 프레임 가장자리에 가는 선이나 색 번짐텍스처 필터가 프레임 바로 바깥 픽셀(이웃 프레임이나 투명 간격)을 읽음가장자리를 확대해 선이 이웃의 색인지, 비쳐 보이는지 확인모양 간격 2 이상 유지, 확장 1 추가, 도트 그림은 최근접 필터. 아틀라스 간격 참고
일부 프레임이 옆으로 눕거나 뒤집히거나 잘림회전된 프레임을 되돌리지 않는 엔진·로더인데 회전을 허용함해당 항목에 "rotated": true가 있음회전을 끄고 패킹. Nerulio의 Godot·Unity·Phaser·LÖVE·XML·CSS 내보내기는 회전된 패킹을 거부함
스프라이트가 페이지에 들어가지 않는다는 오류간격과 확장을 더한 프레임 하나가 최대 페이지보다 큼메시지에 프레임 이름과 크기가 나옴최대 크기를 올리거나(최대 16384px), 엔진이 읽을 수 있으면 회전 허용, 또는 그 프레임을 축소

다른 방법

방법이럴 때 더 낫습니다
단순 격자 시트(아래의 기존 만들기 도구)모든 프레임 크기가 같고 엔진이 칸 단위로 자를 때. 예: GameMaker 스트립, Godot의 Add Frames from Sprite Sheet. 맞춰 둘 데이터 파일이 없습니다.
Aseprite 자체 시트 내보내기(명령줄의 --sheet-pack, --trim, --merge-duplicates)그림을 Aseprite에서 관리하고 태그와 길이가 담긴 JSON만 있으면 될 때. Godot SpriteFrames 같은 엔진 번들은 만들지 않습니다.
TexturePacker Pro폴리곤 패킹, GPU 텍스처 형식, 빌드 파이프라인용 명령줄이 필요할 때. Nerulio와의 측정 비교는 TexturePacker 대안 페이지.
엔진 자체 패커(Defold 아틀라스, Spine 텍스처 패커)엔진이 빌드·내보내기 때 개별 이미지를 어차피 패킹할 때. 프레임 이미지만 있으면 됩니다. 시트를 PNG 프레임으로 나누기 참고.

엔진별 내보내기와 검증 방법

"검증됨"은 실제 CC0 에셋으로 내보낸 파일을 해당 엔진·도구가 직접 불러와 원본과 비교했다는 뜻입니다. 불러오지 않은 형식은 그렇게 표시합니다.

대상파일검증
Godot 4.tres SpriteFrames · .tscn AnimatedSprite2D · .png.import검증됨 Godot 4.7.2Godot가 불러와 모든 애니메이션 프레임을 그려 원본과 비교했습니다. 씬은 Nearest 필터를 쓰고 회전은 쓰지 않습니다.
Unity 6.unity.json · Editor/NerulioSpriteImporter.cs · AnimationClip검증됨 Unity 6000.5.3f1배치 모드에서 스프라이트 영역·피벗·픽셀·클립 키·길이를 확인했습니다.
Phaser 3 / 4atlas JSON (multiatlas) · .anims.json검증됨 Phaser 3.90 + 4.2두 버전 모두에서 프레임과 애니메이션을 그렸습니다.
PixiJS 8spritesheet JSON · animations · anchor · meta.scale검증됨 PixiJS 8.21회전·여러 페이지 아틀라스도 포함해 확인했습니다.
Aseprite JSONhash / array · frameTags · slices검증됨 Phaser load.aseprite · PixiJS 8.21태그의 방향과 반복 횟수가 유지됩니다.
.asepritelayers · tags · durations · slices검증됨 Aseprite 1.3.18Aseprite 명령줄로 열어 렌더링했습니다.
Spine / libGDX.atlas검증됨 spine-canvas 4.2Spine 런타임이 회전·트림 영역을 모두 그렸습니다. libGDX 자체는 실행하지 않았습니다.
Starling / Sparrow XMLXML per page검증됨 Phaser 4.2Phaser 3.90은 트림된 XML 프레임을 잘못 그립니다(Phaser 버그). "Sparrow XML (Phaser 3)" 프리셋은 트림을 끄며 3.90·4.2 모두 통과합니다.
LÖVELua quads · nerulio_atlas.lua · main.lua검증됨 LÖVE 11.5포함된 헬퍼로 모든 프레임을 그리고 모든 애니메이션을 재생했습니다.
Defold.atlas · .tilesource빌드 확인 Defold bob.jar 1.13.1Defold 명령줄 빌더로 빌드하고 빌드된 텍스처의 UV를 다시 읽어 확인했습니다.
GameMakerspr_<name>_stripN.png · gamemaker.json미검증GameMaker에서 불러오지 않았습니다(헤드리스 실행 불가). 스트립은 GameMaker 스트립 가져오기 방식대로 자릅니다.
CSS sprites.css · preview .html검증됨 Chromium포함된 스타일시트로 모든 클래스를 그렸습니다.
GIF / APNGone file per animation디코딩 확인 Pillow내보낸 뒤 모든 프레임과 지연 시간을 다시 디코딩했습니다. APNG는 원본과 동일합니다.

검증 근거

내보내기: 실제 CC0 에셋으로 실제 엔진에서 49회 실행해 47회 통과. 실패 2회는 Phaser 3.90의 트림 XML 버그이며 Phaser 3 프리셋으로 피합니다. 실제 프레임 세트 5개로 패커 비교(CodeAndWeb 무료 웹 패커, GAPTools, free-tex-packer): 회전 허용 시 5개 모두 가장 작은 시트, 회전 없이는 5개 중 4개. 모든 프레임이 픽셀 단위로 복원됩니다.

한계

  • 폴리곤(메시) 패킹은 제공하지 않습니다. 검증한 엔진 중 내보낸 데이터로 메시 아틀라스를 그리는 엔진이 없기 때문입니다.
  • GameMaker 스트립은 GameMaker 자체에서 검증하지 않았습니다.
  • 배율 변형(@0.5x~@4x)은 최근접 이웃 방식만 씁니다.
  • 트림된 Starling XML은 Phaser 3.90에서 잘못 그려지므로 "Sparrow XML (Phaser 3)" 프리셋을 쓰세요.

버전과 출처

위 크기는 저장소 테스트 코퍼스의 닌자 프레임 6장에 Nerulio 패커를 돌린 실제 결과이며, 2026-09-23 비교 측정의 수치와 같습니다. 내보낸 파일은 Godot 4.7.2, Unity 6000.5.3f1, Phaser 3.90·4.2, PixiJS 8.21, spine-canvas 4.2, LÖVE 11.5에서 불러왔고, Defold 파일은 bob.jar 1.13.1로 빌드했습니다. 다른 도구의 옵션 이름은 각 공식 문서를 따릅니다.

참고한 공식 문서

기존 도구

칸이 고정된 균일 격자 시트(행×열)는 아직 기존 스프라이트 시트 만들기에서 만듭니다.

기존 도구 열기 →

자주 묻는 질문

행×열의 단순 격자 시트도 만들 수 있나요?

Studio는 촘촘하게 패킹합니다. 칸 크기가 고정된 균일 격자는 아래 링크의 기존 스프라이트 시트 만들기에서 할 수 있습니다.

프레임이 픽셀 단위로 정확한가요?

네. 실제 프레임 세트 5개에서 아틀라스로부터 복원한 모든 프레임이 원본 파일과 픽셀 단위로 같았습니다.

무료인가요? 계정이 필요한가요?

이 페이지의 기능은 모두 무료이며 계정 없이 쓸 수 있습니다. 워터마크나 막혀 있는 내보내기가 없습니다.

스프라이트가 업로드되나요?

아니요. Studio는 이 브라우저 탭 안에서 디코딩·패킹·내보내기를 합니다. 프로젝트는 브라우저(IndexedDB)에 자동 저장되며 .nerulio 파일로 저장할 수 있습니다.

Aseprite나 엔진 플러그인을 설치해야 하나요?

아니요. .aseprite 파일은 브라우저에서 읽고 씁니다. 엔진별 번들에는 그 엔진에 필요한 것이 들어 있습니다(Godot는 가져오기 설정과 씬, Unity와 Godot 타일셋은 작은 편집기 스크립트).