열심히 배치해놓고 브라우저 닫으면 다 날아간다. 저장 기능 필요.
저장할 데이터
interface ProjectData {
version: string;
room: Room | null;
furniture: Furniture[];
doors: Door[];
measurements: Measurement[];
backgroundImage: BackgroundImage | null;
}
버전 넣어두면 나중에 포맷 바뀔 때 마이그레이션 가능.
LocalStorage 저장
const STORAGE_KEY = 'floor-planner-project';
function saveProject() {
const data: ProjectData = {
version: '1.0',
room: room.value,
furniture: furnitureStore.items,
doors: doorStore.items,
measurements: measurements.value,
backgroundImage: backgroundImage.value
};
localStorage.setItem(STORAGE_KEY, JSON.stringify(data));
}
불러오기
function loadProject() {
const json = localStorage.getItem(STORAGE_KEY);
if (!json) return;
try {
const data: ProjectData = JSON.parse(json);
room.value = data.room;
furnitureStore.items = data.furniture;
doorStore.items = data.doors;
measurements.value = data.measurements;
backgroundImage.value = data.backgroundImage;
// 배경 이미지 다시 로드
if (data.backgroundImage?.src) {
reloadBackgroundImage(data.backgroundImage.src);
}
} catch (e) {
console.error('Failed to load project:', e);
}
}
자동 저장
매번 버튼 누르기 귀찮음. 변경될 때 자동 저장:
const debouncedSave = useDebounceFn(() => {
saveProject();
}, 1000);
watch(
[room, () => furnitureStore.items, () => doorStore.items, measurements, backgroundImage],
() => {
debouncedSave();
},
{ deep: true }
);
1초 디바운스. 연속 변경은 묶어서.
앱 시작 시 로드
onMounted(() => {
loadProject();
});
새 프로젝트
전부 초기화:
function newProject() {
if (!confirm('현재 작업을 삭제하고 새로 시작할까요?')) return;
room.value = null;
furnitureStore.items = [];
doorStore.items = [];
measurements.value = [];
backgroundImage.value = null;
localStorage.removeItem(STORAGE_KEY);
}
파일로 내보내기
LocalStorage 말고 파일로도 저장하고 싶으면:
function exportProject() {
const data: ProjectData = { ... };
const json = JSON.stringify(data, null, 2);
const blob = new Blob([json], { type: 'application/json' });
const a = document.createElement('a');
a.href = URL.createObjectURL(blob);
a.download = 'floor-plan.json';
a.click();
URL.revokeObjectURL(a.href);
}
파일 불러오기
function importProject(file: File) {
const reader = new FileReader();
reader.onload = (e) => {
const json = e.target?.result as string;
const data = JSON.parse(json);
// ... 데이터 적용
};
reader.readAsText(file);
}
용량 제한
LocalStorage는 보통 5MB 제한.
배경 이미지가 크면 문제될 수 있음. 이미지 압축하거나 IndexedDB 쓰는 게 나을 수도.
지금은 그냥 쓰고 있음.
다음 글에서 PNG 내보내기.