Toast UI Editor를 붙이기 전에 저장 모델부터 정하기

에디터 라이브러리를 붙일 때 가장 먼저 보이는 것은 툴바와 미리보기입니다. 하지만 운영에서 문제가 되는 지점은 대개 저장 모델입니다. 어떤 포맷으로 저장할지, 다시 열 때 원본이 보존되는지, 렌더링 시 허용할 HTML 범위는 어디까지인지가 정해지지 않으면 에디터는 금방 부채가 됩니다.

저장 포맷은 제품의 계약이다

블로그 글은 마크다운으로 저장하는 편이 관리하기 쉽습니다. 이유는 단순합니다. 사람이 읽을 수 있고, Git이나 DB에서 diff를 보기 좋고, 에디터가 바뀌어도 상대적으로 이동이 쉽습니다. HTML 저장은 렌더링은 편하지만 불필요한 스타일, 에디터 전용 태그, 보안 필터링 문제가 섞이기 쉽습니다.

중요한 것은 마크다운을 저장한다고 해서 아무 HTML이나 허용해도 된다는 뜻이 아니라는 점입니다. 렌더링 단계에서 허용 태그와 속성을 제한해야 합니다. 특히 링크, 이미지, 코드 블록, heading 정도의 범위를 명확히 두는 것이 좋습니다.

에디터 장애를 기본 시나리오로 본다

외부 CDN에서 에디터를 불러오면 네트워크 문제로 로드가 실패할 수 있습니다. 이때 글을 못 쓰게 만들면 운영 도구로는 부족합니다. textarea 폴백이 있어야 하고, 에디터가 로드되면 같은 값을 공유해야 합니다. 저장 직전에는 에디터 값과 폴백 값을 동기화하는 것이 안전합니다.

또한 신규 글과 기존 글의 초기화 경로를 분리해야 합니다. 기존 글은 서버에서 받은 원문을 그대로 넣고, 새 글은 빈 모델에서 시작해야 합니다. 중간 상태가 섞이면 의도치 않은 덮어쓰기가 발생합니다.

기능보다 복구 가능성이 먼저다

글쓰기 도구의 품질은 굵게, 표, 이미지 업로드 같은 기능 수로 결정되지 않습니다. 잘못 저장했을 때 복구할 수 있는가, 본문이 깨지지 않는가, 에디터가 없어도 수정할 수 있는가가 더 중요합니다. 운영자는 화려한 에디터보다 예측 가능한 저장 모델을 더 자주 필요로 합니다.

실제 적용 메모

편집기에서는 Toast UI Editor를 붙였지만 저장 모델은 마크다운으로 고정했습니다. 이유는 운영 중 문제가 생겼을 때 DB에서 본문을 직접 읽고 수정할 수 있어야 하기 때문입니다.

현재 편집 흐름은 다음처럼 동작합니다.

서버에서 post.body 조회
-> textarea에 원문 저장
-> Toast UI Editor가 로드되면 같은 값을 setMarkdown
-> 저장 직전 editor.getMarkdown 값을 textarea와 payload에 동기화
-> API로 body 저장

이 구조의 장점은 에디터 CDN이 실패해도 textarea로 글을 수정할 수 있다는 점입니다. 운영 도구는 예쁜 툴바보다 폴백이 중요합니다.

에디터를 먼저 고르면 저장 포맷이 라이브러리에 끌려갑니다. 반대로 저장 포맷을 먼저 정하면 에디터는 교체 가능한 구현체가 됩니다.

sequenceDiagram participant API as Admin API participant Text as textarea participant Editor as Toast UI Editor participant DB as D1 posts API->>Text: post.body 원문 주입 Text->>Editor: setMarkdown Editor->>Text: 저장 직전 getMarkdown 동기화 Text->>API: PUT body API->>DB: Markdown 저장