Draft.js 사용기(에디터 만들기)

Hayoung Lee
bgpworks
Published in
7 min readAug 23, 2021
Draft.js를 사용해서 간단하게 만들어볼 수 있는 에디터 시연

테스트 할수 있는곳(이미지 복사/붙여넣기는 안되는 버전) – 아직 구현 중이라 view 탭에서 컨텐츠를 보려면 ctrl+s로 저장을 해야보인다

Draft.js란?

Draft.js는 페이스북에서 공개한 것으로 react에서 텍스트에디터를 만들 수 있는 툴이다. “WYSIWYG(what you see is what you get)” 이라고 작성할때 보이는게, 결과물이랑 같은 유저 인터페이스를 말한다. 예를 들자면 지금 내가 글을 작성하고 있는 Medium의 에디터도 글을 쓸때 보이는 화면과 결과물이 동일하기 때문에 WYSIWYG 에디터라고 할 수 있다.

위 문서에서 QuickStart/Api Basics 파트에서 설명을 읽어보면 Facebook에서 Draft.js를 왜 만들었는지 알수 있다. Draft.js에서 제공하는 Editor 컴포넌트는 controlled ContentEditable component로 쓰려고 만들어졌다.

https://draftjs.org/docs/quickstart-api-basics 페이지의 input 예시

위는 input의 상태를 state를 하나를 두고 onChange로 관리하고 있는데, controlled 방식이라고 한다. (controlled input vs uncontrolled input)

하지만 input태그는 plaintext의 상태만 처리가 가능하고, ContentEditable element의 경우에는 onChange이벤트가 아직 없다.

이것을 해결하기 위해서 Draft.js의 Editor컴포넌트는 EditorState 오브젝트로 Editor의 상태를 컨트롤 할 수 있도록 controlled ContentEditable component로 구성되서 제공되고 있다.

https://draftjs.org/docs/quickstart-api-basics 의 Editor컴포넌트 예시

이때 EditorState는 오브젝트이고, editor의 상태의 snapshot이다. EditorState는 컨텐츠, 커서, undo/redo에 대한 정보까지 가지고 있다. Editor에 어떤 변화가 있으면 onChange 핸들러가 실행이 되고, EditorState가 업데이트된다.

Draft.js 플러그인

사실 Draft.js를 잠깐 써본 내생각도 그렇고, 다른 평들도 보면 쓰기 쉬운편은 아니다. 하지만 다행인건 꽤나 쓸만한 플러그인들이 제공 되고 있다는 것이다. 여기를 보면 툴바나 이미지 리사이징 등을 지원하는 플러그인들이 잘 제공이 되고있다. 예제만 잘 읽어봐도 무리없이 동작한다.

내가 Draft.js를 통해서 Editor를 구성한 방법 간략 소개

내 최종 목표는 일단 무조건 아무 어려움 없이 Editing할때 보이는 화면이랑, View하는 화면이 아무 차이가 없이 보이는 것이었다. 티스토리 같은 블로그 서비스를 쓸때 제일 화나는 부분이 막상 작성 다하고나면 보는 화면에서 깨지는 것이었기 때문이다.

1. Editor 구현

나는 Draft.js의 기본 에디터가 아니라 Plugin을 붙일수 있는 Editor를 사용하고 싶어서 @draft-js-plugins/editor 를 설치했다. 이 에디터는 plugins을 옵션으로 줄수 있는 것 이외에는 특별히 다른 점은 없다.

나는 이런식으로 상단에 툴바를 띄우고 아래에 에디터를 붙였다.

이때 보면 handleKeyCommand, keyBindingFn을 설정할 수 있는데 이건 키처리와 관련된 기능을 지원한다. ctrl+z, ctrl+c, ctrl+v같은 기본키는 Draft.js 자체가 제공하고, ctrl+s같은것은 어떤 처리를 할지 만들어 넣어야한다.

2. 이미지 업로드 하는 기능 구현

가장 머리 아팠던 것은 이미지를 집어 넣는 부분이다. 우선 복사 붙여넣기를 했을때 무언가 실행되도록 기능을 붙이려면 handlePastedFiles옵션을 줘야한다.

handlePastedFiles처리 부분

여기서 보면 파일을 붙여넣었을때 api fetch를 하고 있다. 나는 next.js api를 통해서 테스트를 했는데, 이미지 url을 반환해준다. 이건 이제 insertImage라는 함수내에서 해당 url을 Editor의 State로 잘 붙여넣도록 구현을 해주어야한다.

insertImage함수는 EditorStaate에 AtomicBlock이라는걸 추가해주는 부분이다.

insertImage부분

그런데 아무리 테스트를 해도 이미지가 제대로 보이지 않았는데, 이건 image plugin을 통해서 해결했다. 이미지 플러그인에는 위의 방식대로 url로 Entitiy를 만들고 넘겨주면 이미지가 잘 렌더링 된다.

3. read-only 옵션으로 Viewer구현

이부분은 처음에는 복잡할 줄 알고 걱정했는데 굉장히 쉽다.

ReadOnly옵션으로 viewer만들기

후기

예전부터 텍스트 에디터를 한번 만들어 보고 싶었는데, 이번에 다시 생각이 나서 이래저래 찾다보니 이걸 알게 되었고, react에서 텍스트 에디터를 한번 마무리 해보고 싶어서 만들어보았는데 좋은 경험이었다.

우선 Draft.js를 통해서 글을 직접 작성하는 Editor컴포넌트와, 글을 보는 Viewer를 create-react-library를 통해서 라이브러리화 하는 것과, 내 개인 블로그에 나중에 붙일 수 있게 되는 것이 목표이다.

앞으로는 지금 css를 처리해놓은 방식이 굉장히 안좋아서 이부분을 고치고, create-react-library가 내부에서 rollup을 쓴다는데 어떻게 돌아가고 있는건지 감이 안와서 그부분을 공부를 좀 해야할 것 같다.

그리고 에디터 자체도 헤딩이나, 코드 블럭 같은것들을 지원할 수 있도록 개선을 해보려고 한다.

--

--