이번 포스팅은 WebEditor중 하나인 Summernote이다.
해당 Editor를 접할 기회가 생겼고, 다른 WebEditor를 사용해본적이 없기 때문에 다른 Editor에 비해서 장점을 말하기는 힘들겠지만 구현해보면서 느낀 장점/단점과 구현방법에 대해서 작성해볼 예정이다.
다른 웹에디터를 사용해보지 않아 다른 에디터에 비해 어떤지는 잘 모르기 때문에 내가 구현해보면서 느낀 장/단점에 대해서 작성해보겠다
jQuery 의존성(jQuery 없이 사용 불가)
요즘 같이 jQuery를 지양하려는 추세에서 이건 큰 단점이라 생각한다.
bootstrap 의존성
bootstrap으로 인해 사용하고 있는 스타일과 충돌이 발생할수 있는 이슈가 있어, 이거또한 큰 단점으로 다가왔다.
summernote-lite버전의 경우 bootstrap없이 사용이 가능하지만 자잘한 버그들이 존재한다.
(제가 기존 스타일과 bootstrap스타일 충돌을 막는 방법을 모릅니다.)
npm 설치 불가
이 부분에대해서는 내가 못찾은 부분일수도 있지만 찾지 못했고, public폴더 밑에 있는 index.html에서 스크립트 태그를 이용해 include 시켜 사용 했다. 이것또한 단점으로 보였다.
bootstrap을 사용하는 버전을 사용해서 구현했다.
public/index.html에
jQuery(js), 부트스트랩(js,css), 서머노트(js,css) 이렇게 총 5개를 include시켜 줘야하며 여기서 주의점은 summernote.js에서 jQuery를 사용하기 때문에 summernote.js보다 jQuery를 먼저 include시켜줘야 한다.
(summernote-lite버전을 사용할경우는 jQuery, summernote(js,css) 이렇게 3가지만 include해주면 된다.)
(cdn에서 갖고오지 않고 js 파일을 받아 프로젝트에 추가 시켜줄경우는 위에 파일들과 font폴더도 추가 시켜줘야한다. 언어 설정을 위해서는 + 언어 js파일도 추가)
<script src="https://code.jquery.com/jquery3.5.1.min.js"></script>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
<link href="https://cdn.jsdelivr.net/npm/summernote@0.8.18/dist/summernote.min.css" rel="stylesheet"/>
<script src="https://cdn.jsdelivr.net/npm/summernote@0.8.18/dist/summernote.min.js"></script>
jQuery와 summernote의 타입을 설치해준다.
(jQuery타입을 추가 시켜주지 않을경우 $를 찾지 못하는 것 같다.) - Typescript를 사용하지 않을 경우는 패스
npm install @types/jquery @types/summernote
summernote 구현부분이다.
import { useEffect } from "react";
// summernote오류날경우 import만해준다
// import summernote from "summernote";
export default function WEditor() {
useEffect(() => {
// summernote옵션 설정
const config: Summernote.Options = {
tabDisable: true, // 키보드 Tab키를 사용가능할게 할지(Default false)
// toolbar에 넣을 항목들 정의
toolbar: [
// 작성해준 순서대로 toolbar에 삽입된다.
// 중복으도 선언가능하며, toolbar삽입 위치를 자유롭게하기 위해서 중복으로 타입이 되어있어 보인다.
["font", ["bold", "italic", "underline", "superscript"]],
["fontsize", ["fontsize", "fontname", "color"]],
],
// 사용하고 싶은 fontSize들만 정의
fontSizes: ["10", "12", "14", "16"],
// 사용하고 싶은 Color들 정의, [[[]]] 이란걸 주의하자!, 최종안에 배열의 색상값이 한줄에 표시된다.
// 아래처럼 선언할시 첫번째줄 red 하나, 두번째줄 black하나, 세번째줄 yellow 하나 이렇게 나타난다.
colors: [[["red"]], [["black"]], [["yellow"]]],
// fontSize단위
fontSizeUnits: ["px"],
// placeholder이다.
placeholder: "아무말이나 작성해주세요!",
// tooltip에 언어를 설정하는것같은데, 사용을 원할 경우 언어 summernote-ko.js파일도 추가가 필요 해보인다.
lang: "ko-KR",
// !!중요!! Callback 함수 정의, 많이 쓰일것같다.
// 사용해본 몇가지만 작성할예정이며 이것저것 많아 보인다.
callbacks: {
onInit: () => {
// editor가 초기화 되었을 때 이벤트 발생
},
onChange: (contents: string, $editable: JQuery) => {
// editor내용이 변결 될때마다 이벤트 발생
},
onKeyup: (ev: KeyboardEvent) => {
// keyboard버튼 눌렀다가 땠을 때 이벤트 발생 ev.key를 통해 누른 버튼의 값을 갖고올수있디ㅡ
},
onKeydown: (ev: KeyboardEvent) => {
// keyboard버튼 눌렀을 때 이벤트 발생
},
onPaste: (e: Event & { originalEvent: ClipboardEvent }) => {
// editor에 붙여넣기 했을 때
// 파라미터 타입에 originalEvent를 추가 시켜준건 붙여넣기할 텍스트를 갖고 오기 때문이다.(하단 참고)
// 붙여넣기할 텍스트를 갖고오는 부분이다.
const clipboardData = e.originalEvent.clipboardData?.getData("text");
},
},
};
// summernote초기화 및 렌딩(?)
//JSX부분에 summernote를 id로 갖는 태그는 div/textarea 둘다 가능하며 차이점은 없어 보인다.(공식사이트에서는 div로 되어있는걸 본것같다.)
$("#summernote").summernote(config);
}, []);
// 저정 버튼 눌렀을때 호출되는 함수
const onEditorSaveHanlder = () => {
// editor에 작성된 텍스트 내용을 갖고온다
// html태그를 포함한 내용이다.
const content = $("#summernote").summernote("code");
console.log(content);
};
return (
<>
<div style={{ width: "800px" }}>
<textarea id="summernote"></textarea>
</div>
<div>
<button onClick={onEditorSaveHanlder}>저장!</button>
</div>
</>
);
}
지극히 개인적인 생각으로
jQuery(OK), bootstrap(OK) - 사용이 나쁘지않다
jQuery(OK), bootstrap(NO) - 라이트 버전을 이용해서 구현 가능하지만, 버그를 수정하거나 감수해야한다.
jQuery(NO), bootstrap(NO) - 바로 다른 에디터를 찾아보자
개인적인 생각으로는 jQuery, bootstrap의 의존성은 큰 단점으로 다가왔고 bootstrap이 없이 사용가능한 lite버전의 자잘한 버그는 크게 느껴졌으며, 나에게 웹에디터 구현의 기회가 온다면 jQuery, bootstrap전부를 사용해야 하는 이상 다른 에디터를 찾아 볼 것 같다.
안녕하세요 글 잘 읽어보았습니다.
질문이 있는데 Summernote.Options을 타입으로 사용하려는데
Summernote타입을 찾아오지 못하는 타입 오류가 발생하더라구요
Summernote타입도 다운받고 했는데 이유를 모르겠습니다ㅠ