React-Quill을 활용하여 게시판 만들기(with TypeScript)

임수현·2021년 7월 21일
14

이번 포스팅은 위지윅(WYSIWIG) 게시판 중의 하나인 React-Quill을 활용한 게시판 만드는 방법 입니다.

Quill

quill은 rich text editor의 일종으로 마이크로소프트 등의 기업에서 후원하고 있는 텍스트 에디터입니다.

https://quilljs.com/ 퀼 공식 페이지 주소
https://www.npmjs.com/package/react-quill npm링크

에디터 자체는 사용하기 쉬운 편이었는데, 여기에 이미지를 업로드 하는 기능을 붙이는 것이 어려워 꽤나 애를 먹었던 에디터입니다.

사용법(with TypeScript)

사용법은 정말 간단합니다.

import { useRef, useState, useMemo } from "react";

//이렇게 라이브러리를 불러와서 사용하면 됩니다
import ReactQuill from "react-quill";
import "react-quill/dist/quill.snow.css";


const EditorComponent = () => {
  const QuillRef = useRef<ReactQuill>();
  const [contents, setContents] = useState("");
  
  // 이미지를 업로드 하기 위한 함수
  const imageHandler = () => {
  	// 파일을 업로드 하기 위한 input 태그 생성
    const input = document.createElement("input");
    const formData = new FormData();
    let url = "";

    input.setAttribute("type", "file");
    input.setAttribute("accept", "image/*");
    input.click();

	// 파일이 input 태그에 담기면 실행 될 함수 
    input.onchange = async () => {
      const file = input.files;
      if (file !== null) {
        formData.append("image", file[0]);

	// 저의 경우 파일 이미지를 서버에 저장했기 때문에
    	// 백엔드 개발자분과 통신을 통해 이미지를 저장하고 불러왔습니다.
        try {
          const res = axios를 통해 백엔드 개발자분과 통신했고, 데이터는 폼데이터로 주고받았습니다.

	// 백엔드 개발자 분이 통신 성공시에 보내주는 이미지 url을 변수에 담는다.
          url = res.data.url;

	// 커서의 위치를 알고 해당 위치에 이미지 태그를 넣어주는 코드 
    	// 해당 DOM의 데이터가 필요하기에 useRef를 사용한다.
          const range = QuillRef.current?.getEditor().getSelection()?.index;
          if (range !== null && range !== undefined) {
            let quill = QuillRef.current?.getEditor();

            quill?.setSelection(range, 1);

            quill?.clipboard.dangerouslyPasteHTML(
              range,
              `<img src=${url} alt="이미지 태그가 삽입됩니다." />`
            );
          }

          return { ...res, success: true };
        } catch (error) {
          const err = error as AxiosError;
          return { ...err.response, success: false };
        }
      }
    };
  };

// quill에서 사용할 모듈을 설정하는 코드 입니다.
// 원하는 설정을 사용하면 되는데, 저는 아래와 같이 사용했습니다.
// useMemo를 사용하지 않으면, 키를 입력할 때마다, imageHandler 때문에 focus가 계속 풀리게 됩니다.
const modules = useMemo(
    () => ({
      toolbar: {
        container: [
          ["bold", "italic", "underline", "strike", "blockquote"],
          [{ size: ["small", false, "large", "huge"] }, { color: [] }],
          [
            { list: "ordered" },
            { list: "bullet" },
            { indent: "-1" },
            { indent: "+1" },
            { align: [] },
          ],
          ["image", "video"],
        ],
        handlers: {
          image: imageHandler,
        },
      },
    }),
    []
  );


return (
	<>
      <ReactQuill
               ref={(element) => {
                  if (element !== null) {
                    QuillRef.current = element;
                  }
                }}
                value={contents}
                onChange={setContents}
                modules={modules}
                theme="snow"
                placeholder="내용을 입력해주세요."
              />
	</>
)

//이렇게 컴포넌트 사용하듯이 사용하면 됩니다.

제가 처음 quill을 사용할 때 이미지 업로드 관련 코드가 한글로 된 자료가 많이 없어서 헤맸던 기억이 납니다.
이 자료를 통해 많은 분들이 쉽게 react-quill을 사용하실 수 있으면 좋겠습니다.

profile
상상을 구현하고픈 프론트엔드 개발자입니다.

4개의 댓글

comment-user-thumbnail
2021년 8월 19일

감사합니다. 덕분에 사용해볼 수 있었어요 :)

답글 달기
comment-user-thumbnail
2021년 9월 8일

감사합니다~ 덕분에 포커스 벗어나는 이슈를 해결했네요~!

답글 달기
comment-user-thumbnail
2021년 9월 13일

한글 입력시 "안녕하세요" 라고 입력하려고 하면 "ㅇ안녕하세요" 이렇게 되던데 어떤 문제 때문인지 도움 구할 수 있을까요...?

답글 달기
comment-user-thumbnail
2021년 9월 24일

안녕하세요 혹시 중간에 주석이 잘못된곳을 어떻게 고쳐야 할까요..?

// 저의 경우 파일 이미지를 서버에 저장했기 때문에
// 백엔드 개발자분과 통신을 통해 이미지를 저장하고 불러왔습니다.
try {
const res = axios를 통해 백엔드 개발자분과 통신했고, 데이터는 폼데이터로 주고받았습니다.
// 백엔드 개발자 분이 통신 성공시에 보내주는 이미지 url을 변수에 담는다.

이 부분 입니다

답글 달기