안녕하세요. J4J입니다.
이번 포스팅은 React Draft Wysiwyg Editor 사용하는 방법에 대해 적어보는 시간을 가져보려고 합니다.
들어가기에 앞서 다음 글도 참고해보시면 좋을 것 같습니다.
앞선 글들에서 언급했듯이 Next에서 Editor를 사용해보기 위해 다음과 같은 총 3개의 패키지를 확인할 수 있었습니다.
- react-quill
- @toast-ui/react-editor
- react-draft-wysiwyg
이번엔 개인 순위로 3등으로 생각했던 react-draft-wysiwyg에 대해 소개를 해보겠습니다.
구현 방법과 간단한 특징들에 대해 적어보겠습니다.
이미지 서버 설정
구현하기 전 이미지 서버 설정이 필요합니다.
서버 설정과 관련된 것은 위의 React Quill을 참고해주시면 될 것 같습니다.
React Draft Wysiwyg 사용 방법
[ 1. 패키지 설치 ]
$ npm install react-draft-wysiwyg draft-js draftjs-to-html html-to-draftjs
$ npm install -D @types/react-draft-wysiwyg @types/draft-js @types/draftjs-to-html @types/html-to-draftjs
[ 2. Editor 컴포넌트 생성 ]
/components 위치에 editor.tsx파일을 생성하여 다음과 같이 Editor를 만들어보겠습니다.
import { NextPage } from 'next';
import * as React from 'react';
import axios from 'axios';
import { Editor as WysiwygEditor } from 'react-draft-wysiwyg';
import 'react-draft-wysiwyg/dist/react-draft-wysiwyg.css';
import { ContentState, convertToRaw, EditorState } from 'draft-js';
import draftToHtml from 'draftjs-to-html';
import htmlToDraft from 'html-to-draftjs';
interface IEditor {
htmlStr: string;
setHtmlStr: React.Dispatch<React.SetStateAction<string>>;
}
const Editor: NextPage<IEditor> = ({ htmlStr, setHtmlStr }) => {
const [editorState, setEditorState] = React.useState(EditorState.createEmpty());
React.useEffect(() => {
const blocksFromHtml = htmlToDraft(htmlStr);
if (blocksFromHtml) {
const { contentBlocks, entityMap } = blocksFromHtml;
const contentState = ContentState.createFromBlockArray(contentBlocks, entityMap);
const editorState = EditorState.createWithContent(contentState);
setEditorState(editorState);
}
}, [])
// editor 수정 이벤트
const onEditorStateChange = (editorState: EditorState) => {
setEditorState(editorState);
setHtmlStr(draftToHtml(convertToRaw(editorState.getCurrentContent())));
};
const uploadCallback = (file: Blob) => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onloadend = async () => {
const formData = new FormData();
formData.append("multipartFiles", file);
const res = await axios.post('http://localhost:8080/uploadImage', formData);
resolve({ data: { link: res.data } });
};
reader.readAsDataURL(file);
});
};
// toolbar 설정
const toolbar = {
list: { inDropdown: true }, // list 드롭다운
textAlign: { inDropdown: true }, // align 드롭다운
link: { inDropdown: true }, // link 드롭다운
history: { inDropdown: false }, // history 드롭다운
image: { uploadCallback: uploadCallback }, // 이미지 커스텀 업로드
}
// 언어 설정
const localization = {
locale: 'ko',
}
return (
<WysiwygEditor
editorClassName="editor" // Editor 적용 클래스
toolbarClassName="toolbar" // Toolbar 적용 클래스
toolbar={toolbar}
placeholder="내용을 입력하세요."
localization={localization}
editorState={editorState}
onEditorStateChange={onEditorStateChange}
/>
)
}
export default Editor;
[ 3. Editor 사용하는 파일 작성 ]
위에 만들어 둔 Editor 컴포넌트를 index.tsx에서 불러와 사용해보겠습니다.
작성하기 전 확인해야 될 부분은 Editor 컴포넌트를 불러올 때 dynamic을 이용하여 ssr을 false로 설정해줘야 합니다.
설정하지 않을 경우 정상 동작되지 않습니다.
import * as React from 'react';
import dynamic from 'next/dynamic';
import styled from 'styled-components';
import { NextPage } from 'next';
const Editor = dynamic(() => import('../components/editor'), { ssr: false }); // client 사이드에서만 동작되기 때문에 ssr false로 설정
const Index: NextPage = () => {
// state
const [htmlStr, setHtmlStr] = React.useState<string>('');
// ref
const viewContainerRef = React.useRef<HTMLDivElement>(null);
// useEffect
React.useEffect(() => {
if(viewContainerRef.current) {
viewContainerRef.current.innerHTML = '<h2>html 코드를 이용하여 만들어지는 View입니다.</h2>'
viewContainerRef.current.innerHTML += htmlStr;
}
}, [htmlStr])
return (
<>
<EditorContainer>
<Editor htmlStr={htmlStr} setHtmlStr={setHtmlStr} />
</EditorContainer>
<Contents.Container>
<Contents.HtmlContainer>
<h2>Editor를 통해 만들어진 html 코드입니다.</h2>
{htmlStr}
</Contents.HtmlContainer>
<Contents.ViewContainer ref={viewContainerRef} />
</Contents.Container>
</>
);
};
export default Index;
// style
const EditorContainer = styled.div`
width: 800px;
height: 400px;
margin: 0 auto;
// Editor 스타일 설정
.wrapper { }
.editor {
height: 300px;
}
.toolbar { }
`;
const Contents = {
Container: styled.div`
width: 1200px;
margin: 0 auto;
display: flex;
gap: 40px;
& > div {
width: 600px;
padding: 16px;
box-sizing: border-box;
line-break: anywhere;
}
`,
HtmlContainer: styled.div`
border: 2px solid orange;
`,
ViewContainer: styled.div`
border: 2px solid olive;
`,
}
테스트
코드를 위와 같이 작성하고 실행을 해보면 다음과 같은 결과를 확인할 수 있습니다.
상위는 Editor, 좌측은 Editor에 의해 만들어지는 html, 우측은 만들어진 html을 이용하여 화면을 구성할 때 나오는 화면입니다.
특징
Editor를 찾아보기 전에 원하는 Editor 기능들은 다음과 같습니다.
- 텍스트 정렬
- 텍스트 색깔 지정
- 이미지 업로드
- 이미지 사이즈 조절
- XSS 방지
- 기타 등등...
React Draft Wysiwyg에서는 위의 기능들을 대부분 지원했습니다.
하지만 다음과 같이 아쉬웠던 부분이 많이 보였습니다.
- 이미지 가운데 정렬 정상 동작 불가
- 한글 입력 시 onEditorStateChange 이벤트 발생하지 않음
- style을 class로 적용되지 않고 style로 적용
- 복잡하진 않지만 사용성이 다른 것들에 비해 간단하지 않음
이런 특징들을 확인할 수가 있었고 다른 것들에 비해 크게 눈에 띄는 장점들은 없었던 것 같습니다.
그래서 사용해본 Editor 중에는 가장 마지막 순위로 생각하게 되었고 Editor을 하나 선택해서 사용할 때는 개인적으로 React Draft Wysiwyg는 배제하고 다른 Editor를 생각할 것 같습니다.
이상으로 React Draft Wysiwyg Editor 사용하는 방법에 대해 간단하게 알아보는 시간이었습니다.
읽어주셔서 감사합니다.
'SPA > Next' 카테고리의 다른 글
[Next] 카카오 로그인 구현하기 (2) | 2022.02.27 |
---|---|
[Next] Styled Components 사용하기 (0) | 2022.01.11 |
[Next] Editor 사용하기 (2) - Toast UI (1) | 2022.01.07 |
[Next] Editor 사용하기 (1) - React Quill (0) | 2022.01.06 |
[Next] 타입 스크립트 개발환경 구축하기 (0) | 2021.12.30 |
댓글