1. 시작하며: v1.0.0.15 이후 도출된 운영 과제들
SvelteKit Blog Engine(SKBE) v1.0.0.15를 릴리즈하며 D1 사이드바 스냅샷 엔진과 미디어 마이그레이션 도구를 구축한 이후, 실제 환경에서 관리자 콘솔을 운영하고 다양한 언어(한국어, 영어, 일본어) 및 다양한 화면 해상도에서 디자인을 편집해보면서 실질적인 개선 과제들이 확인되었습니다.
이번 v1.0.1.0 업데이트에서는 블로그 운영의 핵심인 디자인 편집 안정성, 다국어 환경에서의 UI 반응형 완성도, 그리고 배포 자동화 편의성을 전면 개편했습니다:
- 디자인 백업의 파괴적 덮어쓰기 위험 제거: DB 전체 테이블을 덮어써서 다른 슬롯 디자인까지 날려버리던 기존 백업 방식을 폐지하고, 특정 슬롯만 독립된 JSON 프리셋으로 안전하게 내보내고 원하는 슬롯에 복원하는 구조로 전면 전환
- 사이드바 좁은 폭에서의 UI 넘침 및 다국어 글자 잘림 해소: 좁은 사이드바에서 버튼이 우측 프레임 밖으로 삐져나가던 레이아웃 결함과, 띄어쓰기가 없는 일본어 문장에서 줄바꿈이 되지 않던 CJK 타이포그래피 결함 해결
- 슬롯 기본명의 실시간 다국어 번역: DB에 한국어로 저장된 슬롯 기본 이름("디자인 슬롯 1" 등)을 관리자 언어에 맞춰 실시간으로 동적 번역(
デザインスロット 1,Design Slot 1) - 배포 스크립트 프로젝트명 자동 동기화: 최초 설치나 멀티 계정 전환 시
package.json배포 명령어 속 프로젝트명을 수동으로 수정할 필요가 없도록 자동화 파이프라인 구축 - 사이드바 스냅샷 실시간 연동 및 의존성 보안 패치: 글 작성/수정/삭제 시 D1 캐시 즉각 동기화 및 라이브러리 취약점 해결
2. 디자인 에디터: 슬롯별 독립 프리셋 백업/복원 아키텍처
1) 기존 방식의 한계와 위험성
이전의 디자인 백업/복원 기능은 /api/restore 엔드포인트를 통해 데이터베이스의 layouts, widgets, layout_widgets 테이블을 통째로 DELETE한 뒤 백업 파일의 레코드로 다시 INSERT하는 방식이었습니다.
이 구조는 심각한 잠재 위험을 안고 있었습니다:
- 데이터 파괴 위험: 백업 파일 하나를 복원하는 순간, 열심히 꾸며둔 1번, 2번, 3번 슬롯의 모든 레이아웃과 위젯 배치가 예고 없이 초기화되었습니다.
- 슬롯 선택 불가: 특정 슬롯(예: 2번 다크 모던 슬롯)의 디자인만 파일로 보관하거나, 다른 블로그에서 만든 멋진 디자인을 현재 블로그의 3번 슬롯에만 안전하게 가져올 수 없었습니다.
- 복원 전 확인 불가: 가져오기 버튼을 누르는 즉시 실제 DB가 덮어써져 잘못된 백업 파일을 올렸을 때 되돌릴 방법이 없었습니다.
2) 개선된 아키텍처: 중립 프리셋(design_preset) 시스템
기존의 위험한 DB 덤프 방식을 완전히 걷어내고, 에디터 내부의 메모리 상태(slots)와 결합된 독립형 디자인 프리셋 규격을 새롭게 설계했습니다.
// 특정 슬롯의 순수 디자인 데이터만 중립 규격으로 추출
const presetData = {
version: "3.0",
backupType: "design_preset",
timestamp: new Date().toISOString(),
presetName: slotName,
design: {
theme: snapshot.theme,
header: snapshot.header,
footer: snapshot.footer,
site_title: snapshot.site_title,
widget_shadow_global: snapshot.widget_shadow_global,
layout: snapshot.layout,
widgets: snapshot.widgets
}
};
신규 프리셋 시스템의 핵심 특장점
- 슬롯 번호 종속성 배제: 프리셋 파일 내부에는 슬롯 ID(
slot1,slot2등)가 일절 기록되지 않습니다. 따라서 1번 슬롯에서 추출한 디자인이라도 원하는 어떤 슬롯(2번, 3번 등)에든 자유롭게 주입할 수 있습니다. - 미저장 최신 편집 상태 즉시 반영: 현재 편집 중인 활성 슬롯을 백업할 경우, DB에 저장되지 않은 실시간 편집 상태(
getSnapshotOfCurrentSlot())까지 온전히 반영되어 즉각 다운로드됩니다. - 2단계 안전 주입 (Preview-First): 복원 파일을 업로드하고 복원 대상 슬롯을 지정하면, DB를 즉시 건드리지 않고 에디터 메모리에 먼저 주입되어 화면 프리뷰로 결과를 즉시 확인할 수 있습니다. 사용자가 화면을 확인한 후 상단의 [블로그에 적용] 또는 [현재 설정 저장] 버튼을 명시적으로 눌러야만 최종 DB에 반영됩니다.
- 구버전 백업 자동 호환 (
convertLegacyBackupToPreset): 과거에 생성된 테이블 덤프 형태의 백업 파일도 파서가 자동으로 구조를 감지하여 슬롯 프리셋 규격으로 정규화하므로, 기존 백업 자산을 그대로 재사용할 수 있습니다.
3. 사이드바 반응형 가변 스택 레이아웃 및 다국어(i18n) 완성
1) 사이드바 요소 프레임 넘침 및 버튼 짤림 해결
관리자 화면의 사이드바 가용 너비는 패딩을 제외하면 약 260px~290px 내외입니다. 기존에는 드롭다운(select)과 [다운로드] 버튼, 그리고 [복원 대상 슬롯] 라벨과 드롭다운, [복원 적용] 버튼이 각각 가로 1열(flex-row)에 나란히 배치되어 있었습니다.
이로 인해 드롭다운이 너비를 차지하면서 우측 버튼들이 컨테이너 경계 밖으로 밀려나 다운로드 버튼 글자가 잘리고, 복원 적용 버튼은 화면 밖으로 완전히 사라지는 문제가 있었습니다.
이를 **세로 스택형 가변 레이아웃(flex-col, w-full)**으로 전면 개편했습니다:
<!-- 백업 영역: 세로 100% 폭 분리 배치 -->
<div class="setting-control flex flex-col gap-2 w-full">
<select class="select-field w-full" bind:value={slotBackupTargetId}>...</select>
<button class="btn-primary w-full flex items-center justify-center gap-2">
<Download size={16} />
<span>슬롯 백업 다운로드</span>
</button>
</div>
드롭다운과 버튼이 각각 독립된 100% 폭을 가지므로, 사이드바 너비가 좁아지더라도 절대 프레임을 벗어나지 않고 안정적으로 정렬됩니다.
2) 일본어 환경에서의 글자 깨짐 및 18글자 가타카나 버튼 돌출 해결
다국어 테스트 중, 한국어와 영어에서는 발생하지 않던 심각한 레이아웃 파괴 현상이 일본어 환경에서만 유독 발생하는 현상이 확인되었습니다. 면밀한 디버깅 끝에 두 가지 물리적 원인을 밝혀내고 해결했습니다:
원인 A: 일본어 띄어쓰기 부재와 word-break: keep-all의 충돌
- 현상: 안내 설명문(
各スロットのデザインを独立したファイルとしてエ...)의 우측이 잘리고 프레임을 뚫고 나감. - 원인: 한국어는 띄어쓰기가 있어
keep-all이 단어 단위 줄바꿈을 지원하지만, 일본어 문장에는 띄어쓰기(공백)가 전혀 없습니다. 브라우저가 문장 전체를 하나의 거대한 단어로 인식하여 줄바꿈을 포기한 것입니다. - 해결:
overflow-wrap: anywhere; word-break: break-word;를 적용하여 띄어쓰기가 없는 일본어 문장도 컨테이너 경계선 안에서 글자 단위로 매끄럽게 자동 줄바꿈되도록 처리했습니다.
원인 B: 레거시 CSS width: auto !important;와 일본어 가타카나 18글자
- 현상: 일본어 백업 버튼(
スロットバックアップをダウンロード)이 흰색 카드 우측 테두리를 뚫고 50px 이상 튀어나옴. - 원인: 과거 레거시 스타일에 선언되어 있던
.setting-control .btn-primary { width: auto !important; }가 HTML의w-full클래스를 강제로 무효화했습니다. 한국어(슬롯 백업 다운로드, 9글자)는 글자가 짧아 문제가 없었으나, 일본어 가타카나는 18글자로 2배 길어지면서 버튼 고유 너비가 320px 이상으로 비정상 확장된 것입니다. - 해결: CSS 셀렉터를
.setting-control .btn-primary:not(.w-full)로 수정하여!important강제를 걷어내고, 버튼에style="width: 100% !important; max-width: 100%; white-space: normal; word-break: break-word;"를 적용하여 긴 텍스트도 카드 안에서 100% 폭에 맞추어 유연하게 줄바꿈되도록 수정했습니다.
3) 슬롯 기본명의 실시간 다국어 동적 번역 (getSlotDisplayName)
슬롯 1, 2, 3의 기본 이름("디자인 슬롯 1", "미니멀 1열", "다크 모던")은 DB에 한국어 문자열로 영구 저장되기 때문에, 관리자 언어를 영어/일본어로 변경해도 선택창 안에는 한국어 문자열이 그대로 노출되던 문제가 있었습니다.
getSlotDisplayName 헬퍼 함수를 도입하여, 사용자가 직접 수정한 커스텀 이름은 온전히 보존하면서도 기본 슬롯명은 현재 활성 언어(adminLang.value)에 맞춰 실시간으로 번역되어 노출되도록 개선했습니다:
- 한국어:
슬롯 1 (디자인 슬롯 1) - 영어:
Slot 1 (Design Slot 1) - 일본어:
スロット 1 (デザインスロット 1)
4. 배포 및 멀티 계정 자동화: 프로젝트명 동기화 파이프라인
SKBE는 복수의 Cloudflare 계정으로 블로그와 어드민을 분산 배포할 수 있는 멀티 계정 배포 시스템(scripts/deploy-multi.js)을 갖추고 있습니다.
기존에는 최초 셋업(setup.js) 시 프로젝트명을 직접 입력하거나 자동 난수로 생성하더라도, package.json의 기본 배포 명령어(npm run deploy:blog, npm run deploy:admin) 내 --project-name 인자는 수동으로 고쳐주어야 하는 번거로움이 있었습니다.
scripts/setup.js와 scripts/sync-accounts.js에 updatePackageJsonDeployScripts 파이프라인을 추가하여:
- 최초 자동/수동 설치 시 확정된 프로젝트명으로
package.json의 배포 스크립트를 즉각 자동 갱신합니다. npm run deploy:sync실행 시에도.deploy-accounts.json의main계정 프로젝트명과package.json이 항상 오차 없이 100% 동기화되도록 보장합니다.
5. 엔진 최적화 및 의존성 보안 패치
- 사이드바 스냅샷 실시간 이벤트 동기화:
- v1.0.0.15에서 도입된 O(1) 사이드바 스냅샷 캐시가 글 작성(
new), 수정([id]), 삭제 및 상태 변경(posts) 시 즉시 실시간으로 백그라운드 재생성(generateSidebarSnapshot)되도록 연결했습니다.
- v1.0.0.15에서 도입된 O(1) 사이드바 스냅샷 캐시가 글 작성(
- 미디어 마이그레이션 경로 지원 확장:
- 본문 내 프록시 URL을 직접 서빙 주소로 치환하는
/api/media/migrate-urls도구의 정규표현식과 DB 쿼리를 보강하여,posts/하위 경로 및 커스텀 폴더에 저장된 이미지 URL도 누락 없이 일괄 감지 및 치환되도록 확장했습니다.
- 본문 내 프록시 URL을 직접 서빙 주소로 치환하는
- 핵심 라이브러리 보안 패치 및 Zod v4 버전 락:
better-auth및tiptap관련 라이브러리의 보안 패치 버전을 적용하고, pnpmoverrides를 통해zod패키지를 v4 계열로 명시적 고정하여 빌드 안정성을 확보했습니다.
6. 버전 요약 비교 (Before vs After)
| 비교 항목 | 기존 (v1.0.0.15 이전) | 개선 (v1.0.1.0) |
|---|---|---|
| 디자인 백업/복원 | DB 테이블 전체 삭제 후 강제 덮어쓰기 (타 슬롯 파괴) | 슬롯별 독립 중립 프리셋(design_preset) 안전 주입 |
| 복원 확인 단계 | 복원 즉시 DB 덮어쓰기 (되돌리기 불가) | 에디터 메모리 우선 주입 ➔ 화면 프리뷰 확인 ➔ 사용자 확정 저장 |
| 사이드바 레이아웃 | 가로 1열 배치로 좁은 화면에서 버튼 짤림 및 사라짐 | 세로 스택(flex-col, w-full) 가변형 100% 맞춤 정렬 |
| 일본어 타이포그래피 | keep-all로 인한 줄바꿈 실패, 버튼 50px 이상 돌출 |
overflow-wrap: anywhere, 가변 버튼으로 완벽 렌더링 |
| 슬롯명 다국어 | DB에 저장된 한국어 이름 고정 노출 | 기본 슬롯명 실시간 동적 번역 (getSlotDisplayName) |
| 배포 명령어 관리 | 프로젝트명 변경 시 package.json 수동 수정 필요 |
셋업 및 동기화 시 package.json 배포 스크립트 자동 갱신 |
7. 마치며
이번 v1.0.1.0은 단순한 기능 추가를 넘어, 실제 사용자가 관리자 화면에서 경험할 수 있는 **데이터 안전성 결함(디자인 덮어쓰기)**과 **다국어 환경에서의 디테일한 시각적 완성도(일본어 줄바꿈 및 버튼 정렬)**를 꼼꼼하게 다듬은 안정화 릴리즈입니다.
앞으로도 SKBE는 Cloudflare 엣지 환경의 고유한 장점을 극대화하면서, 어떤 언어 환경에서도 쾌적하고 안전한 블로그 운영 환경을 지속적으로 고도화해 나가겠습니다.
댓글 0개
댓글을 작성하려면 로그인이 필요합니다.