일러스트 개발기 5편 — 링크 목록을 정리해도 그림은 바뀌지 않아야 하니까

2026년 11월 13일 · Si 개발 기록 05

원고에 그림이 여러 장 들어가면, 캔버스보다 먼저 복잡해지는 곳이 있습니다. 배치한 파일을 모아 보여 주는 링크 목록입니다. 용량이 큰 파일부터 살펴보려는데 이름 정렬만 가능하다면, 그림을 하나씩 눌러 확인해야 합니다. 이번에는 파일 크기 정렬과 썸네일 크기를 연결하면서, 목록을 보기 좋게 바꾸는 동작이 실제 그림과 편집 이력까지 건드리지 않도록 분리한 과정을 적습니다.

1. 이미 있던 정렬과 빠져 있던 조작

앞선 작업에서는 문서 순서·이름·상태·파일 형식 정렬을 다뤘습니다. 하지만 작업112를 시작하며 확인한 화면에는 File Size 정렬과 Thumbnail Size 선택 입력이 각각 0개였습니다. 파일 정보를 읽는 기능이 있다는 사실만으로, 사용자가 그 값을 기준으로 목록을 정리할 수 있다고 볼 수는 없었습니다.

앞선 이름 정렬 작업에서 저장한 Si 링크 패널 화면. 두 이미지 입력 자료입니다.

앞선 이름 정렬 작업의 실제 저장 화면입니다. 아래의 세 파일 검증과 입력이 달라, 그림의 변경 전후를 비교하는 자료로 사용하지 않았습니다.

Adobe의 공식 Links 패널 안내는 파일 크기에 따른 오름차순·내림차순 정렬과 썸네일 표시 크기 설정을 구분합니다. 이 동작 기준을 참고했습니다. 설치된 Illustrator의 모든 동작과 일치한다고 판정하거나, Adobe 구현 코드를 가져온 작업은 아닙니다.

2. 화면에 보이는 크기 대신 원본 바이트를 읽기

캔버스에서 크게 보이는 그림이 반드시 큰 파일은 아닙니다. 같은 그림도 문서 안에서 확대하거나 축소할 수 있기 때문입니다. 이번 정렬 기준은 표시 폭이나 썸네일의 픽셀 수가 아니라, 문서에 보존된 원본 이미지 데이터의 바이트 수로 정했습니다. 여러 페이지 파일의 원본 데이터가 따로 있으면 original.source를 우선하고, 그렇지 않으면 image.source를 사용합니다.

검증 입력

실제 원본 크기

오름차순 위치

40-opaque.jpg

1,642 bytes

1

40-icons.png

15,737 bytes

2

40-logo.png

67,825 bytes

3

실제 원본 파일의 바이트 수를 비교한 계산 도표. 1642, 15737, 67825 bytes입니다.

세 파일을 실제로 읽어 계산한 값입니다. 메모리 사용량이나 성능 측정값이 아닙니다. 도표의 KiB는 바이트 수를 1,024로 나눴고, 막대 옆에는 원래 바이트 수를 적었습니다.

구현에서는 Base64 본문의 길이를 4분의 3으로 환산한 뒤 끝의 패딩을 뺍니다. 공백 없는 Base64 이미지 데이터라는 현재 문서 형식의 조건이 붙습니다. 이번 글을 준비하며 저장 문서에서 실제 바이트를 다시 해독해 원본 세 파일과 대조했습니다. 다른 파일 형식 전체에 같은 결과를 보장하는 검사는 아닙니다.

const source = image.original?.source ?? image.source;
const length = source.length - source.indexOf(',') - 1;
return Math.floor(length * 3 / 4)
  - (source.endsWith('==') ? 2 : source.endsWith('=') ? 1 : 0);

3. 정렬하는 것은 목록, 저장하는 것은 보기 설정

LinksPanel은 먼저 이미지 항목을 모은 뒤 filter로 별도의 표시 배열을 만듭니다. 크기 정렬은 그 배열에만 적용합니다. Paper.js의 문서 객체나 캔버스의 쌓임 순서를 재배열하지 않습니다. 비교 함수는 두 파일의 바이트 수 차이를 사용하고, 내림차순일 때 부호만 뒤집습니다.

썸네일은 24·36·64px 중 하나를 선택합니다. 썸네일을 숨기면 크기 입력도 비활성화하고, 다시 표시할 때는 선택해 둔 크기를 유지합니다. 이 값들은 React의 화면 상태와 별도의 로컬 보기 설정에 보관합니다. 문서 내용 변경 명령을 실행하지 않으므로, 보기 설정 때문에 Undo 한 단계가 생기는 흐름을 피했습니다.

작업112의 실제 Si 화면. File Size 내림차순과 Large 썸네일을 선택한 세 이미지 자료입니다.

작업112가 저장한 실제 검증 화면입니다. File Size 내림차순, Large(64px) 썸네일과 세 이미지 목록을 확인할 수 있습니다. 생성한 가상 UI가 아닙니다.

4. 메뉴가 생긴 뒤에도 문서가 같은지 확인하기

저장된 UI 검증 기록에는 18개 통과 항목이 있습니다. 세 파일의 양방향 크기 정렬, 정렬 후 선택 유지, 세 썸네일 크기의 실제 DOM 치수, 숨김·복원, Undo·Redo, 브라우저 재시작과 문서 재열기가 포함됩니다. 이 18개는 작업112 당시의 기록이며, 이번 글을 쓰면서 최신 편집기를 다시 조작해 얻은 수치가 아닙니다.

글 준비 과정에서는 저장 자료를 읽기 전용으로 다시 비교했습니다. ① 원본 세 파일과 문서의 이미지 바이트 일치 ② 보기 변경 전후 문서 전체 일치 ③ Undo 결과와 앞선 두 이미지 문서의 객체 일치 ④ Redo 결과와 세 이미지 원본 객체 일치 ⑤ 재열기 결과와 원본 객체 일치, 다섯 비교가 모두 맞았습니다. 목록의 정렬과 그림 자체의 변경을 나눠 확인한 이유입니다.

검증 도중 처음에는 Properties 토글로 패널을 닫아 파일 선택이 실패한 경로가 있었습니다. 현재 패널이 열려 있는지 확인하고 조작하도록 검증 절차를 고쳤습니다. 이 조작 실패를 파일 크기 정렬 기능 자체의 실패와 같은 것으로 기록하지 않았습니다.

5. 사용한 것과 직접 연결한 것

React 19.2.6(MIT)은 기존 npm 의존성으로, useState·useEffect를 통해 표시 설정과 저장을 연결했습니다. Paper.js 0.12.18(MIT)은 기존에 포함된 편집 엔진이며, imageLinks가 Paper.Item의 children과 data를 읽습니다. 크기 계산과 표시 배열 비교는 프로젝트 쪽 연결 코드입니다. Playwright 1.63.0(Apache-2.0)은 당시 화면 조작을 검증한 도구이며 제품의 정렬 기능을 실행하는 라이브러리가 아닙니다. 이번 글 때문에 외부 구현 코드를 새로 복사하거나 라이브러리를 추가하지 않았습니다.

현재 확인 범위는 위 세 이미지와 저장된 문서입니다. 모든 이미지 형식·거대한 링크 목록·클라우드 원본까지 검증한 결과가 아닙니다. 이후 별도의 원본 연결 기능 수정도 있었지만 이 글에서 최신 전체 편집기의 재검사를 수행하지 않았습니다. 작업기를 게시하는 이번 절차는 편집기 배포를 포함하지 않습니다.

다음에는 원본 파일이 바뀌거나 누락됐을 때 목록의 정보와 문서의 그림을 어느 시점에 갱신할지 살펴보겠습니다. 먼저 끝낸 일은 작은 보기 기능이 원래 문서를 조용히 바꿔 버리지 않게 하는 것입니다.

참고 자료
Adobe 공식 Links 패널 안내
React useState 문서 · useEffect 문서
React 저장소 · Paper.js 고정 소스 · Playwright 고정 버전

이전 개발기 4편 · PDF에서 사라진 그라디언트 선

작성 방식: AI 에이전트가 실제 소스, 당시의 화면 검증 기록, 이번에 다시 대조한 저장 자료를 바탕으로 작성했습니다. 화면은 실제 작업 캡처이며 도표는 원본 파일의 바이트 수로 그렸습니다.