React

React - CKEditor 사용해보기

히찔 2023. 1. 5. 22:08

 

CKEditor 란?

  • CKEditor는 콘텐츠를 웹 페이지나 온라인 애플리케이션에 직접 작성할 수 있게 하는 WYSIWYG(위지위그) Rich Text Editor이다.
    • WYSIWYG란 What You See IS Whay You Get의 줄임말로 ‘보는 대로 얻는다.’ 는 뜻이다.
    • 문서 편집 과정에서 화면에 포맷된 낱말, 문장이 출력물과 동일하게 나오는 방식을 말한다.
    • 다시 말해 HTML처럼 따로 CSS 문법을 적용해서 디자인 편집을 하는 것이 아닌 문서 편집 과정에서 화면에 포맷된 낱말, 문장이 출력물과 동일하게 나오는 방식을 말한다.
  • 핵심 코드는 자바스크립트로 작성되어 있으며 CKSource가 개발하였다.
  • 오픈 소스와 상용 라이선스로 이용할 수 있다.

 

설치방법

https://ckeditor.com/ckeditor-5/download/

 

CKEditor 5 - Download Latest Version

Download a ready-to-use CKEditor 5 Build. Install, download or serve a ready-to-use rich text editor of your choice.

ckeditor.com

  • 빌드 방식을 선택한다. (빌드 방법에 따라 에디터의 사용방법 및 용도가 달라진다.)

  • 원하는 방식으로 다운로드 한다.
    1. 리눅스 시스템에서 바로 다운로드 가능한 링크 (npm)
    2. 윈도우에서 스크립트 형식으로 파일을 제공해주는 Zip package
    3. HTML 스크립트 상에 붙여넣어 사용하는 CDN

 

리액트 설치방법https://ckeditor.com/docs/ckeditor5/latest/builds/guides/integration/frameworks/react.html

 

React component - CKEditor 5 Documentation

Learn how to install, integrate and configure CKEditor 5 Builds and how to work with CKEditor 5 Framework, customize it, create your own plugins and custom editors, change the UI or even bring your own UI to the editor. API reference and examples included.

ckeditor.com

  • npm 설치
npm install --save @ckeditor/ckeditor5-react @ckeditor/ckeditor5-build-classic

 

 

사용하기

import { CKEditor } from '@ckeditor/ckeditor5-react';
import ClassicEditor from '@ckeditor/ckeditor5-build-classic';
  • React 컴포넌트에 import 하여 사용 가능하다.
    • 기본 기능
      1. editor : 사용할 에디터
      2. data : 초기 데이터
      3. config : 편집기 구성 데이터 (내장 플러그인)
      4. id : 편집자 ID
      5. disabled Bool 값. (true면 읽기 전용 모드로 전환)
      6. onReady : 준비되면 호출되는 함수
      7. onChange : 데이터가 변경되었을 때 호출되는 함수
      8. onBlur : 편집기에 포커스 해제 되었을 때 호출되는 함수
      9. onFocus : 편집에에 포커스 되어있을 때 호출되는 함수
      10. onError : 편집기 충돌 시 호출되는 함수
// EX 
import React, { Component } from 'react'
import { CKEditor } from '@ckeditor/ckeditor5-react';
import ClassicEditor from '@ckeditor/ckeditor5-build-classic';

import './index.scss'

class CkEditor extends Component {

    constructor(props) {
        super(props)
        this.state = {

        }
    }

    render() {
        return (
            <div className="root-container">
                <CKEditor
                    editor={ ClassicEditor }
                    data="<p>Hello from CKEditor 5!</p>"
                    onInit={ editor => {
                        // You can store the "editor" and use when it is needed.
                        console.log( 'Editor is ready to use!', editor );
                    } }
                    onChange={ ( event, editor ) => {
                        const data = editor.getData();
                        console.log( { event, editor, data } );
                    } }
                    onBlur={ editor => {
                        console.log( 'Blur.', editor );
                    } }
                    onFocus={ editor => {
                        console.log( 'Focus.', editor );
                    } }
                />
            </div>
        )
    }
}

export default CkEditor

 

결과

콘솔창

 

config(내장플러그인) 사용하기

CKEditor5는 바로 사용가능한 플러그인이 세팅된 상태이다. config 속성을 지정하여 플러그인을 추가, 삭제할 수 있다.

  1. 필요한 plugin 설치하기
  2. import 하기
  3. config 안의 plugins= []안에 넣기
  4. config의 toolbar= [] 안에 string 형식으로 넣기 (넣는 순서에 따라 화면에 나타난다.)

 

** 내장플러그인 사용 이슈 **

  • CKEditor 5 빌드는 설치하자마자 사용할 수 있는 상태. 즉, ready to use 형태로 빌드되어 있어 빌드에 포함된 기본 구성으로는 바로 에디터를 화면에 구현할 수 있다.
  • 그러나 기본 구성을 제외한 플러그인들은 설치하여 import 해야 한다.

  • CKEditor에서 플러그인을 설치하고 import 하였더니 Uncaught CKEditorError: ckeditor-duplicated-modules 오류가 발생했다.
  • 그 이유는 CKEditor5에서는 Plugin을 설치한 후, 프로젝트 빌드와 상관없이 따로 빌드 과정을 거쳐야 하기 때문이다.

 

해결 과정

1. ClassicEditor를 src에서 가져오기

  • src에서 가져와 웹팩이 빌드해서 build 폴더로 옮겨 놓는데, build에서 가져오면 빌드된게 2개라 중복되었다고 나온다고 한다.
import ClassicEditor from '@ckeditor/ckeditor5-editor-classic/src/classiceditor';

적용 결과

파일 구조에 뭔가 있지만 원하는 결과는 안나옴..ㅠㅠ

 

 

2. 소스코드를 다운로드 받아 빌드 적용한 후, node_modules안에 복붙하기
https://ckeditor.com/ckeditor-5/online-builder/

  • CKEditor Online Builder에서 원하는 기능들을 추가하고 zip 파일을 다운받는다.
    • 플러그인, 툴바 설정

 

  • zip 파일의 압축을 풀고 build안에 있는 ckeditor.js파일을 node_modules/@ckeditor/ckeditor-build-classic/build안에 복붙한다.
  • config 설정을 해준다.
import { CKEditor } from '@ckeditor/ckeditor5-react';
import ClassicEditor from '@ckeditor/ckeditor5-build-classic';
import SourceEditing from '@ckeditor/ckeditor5-source-editing/src/sourceediting';

import './App.css';

function App() {
  return (
    <div className="editor-container">
      <div className='editor-title'>기본</div>
      <div className='editor'>
        <CKEditor
          editor={ClassicEditor}
          config={ {
            plugins: [ SourceEditing ],
            toolbar: [ 'sourceEditing' ]
        } }
        />
      </div>
    </div>
  );
}

export default App;

 

적용 결과

여전히 오류가 나고 있다...

 

3. webpack을 써서 프로젝트 빌드와 연동되게 만들기https://ckeditor.com/docs/ckeditor5/latest/builds/guides/integration/advanced-setup.html#option-building-to-es5-target

  • create-react-app 을 사용하여 프로젝트 생성 시 기본적으로 webpack 설정이 잡혀있다.
  • 먼저 webpack 기본 설정사항을 추출한다.
npm run eject

** webpack config 파일을 추출하고 UglifyJsPlugin 에 관한 선택사항을 설정해야 하지만, webpack ver 4.0 부터는 기본적으로 제공해주기 때문에 할 필요가 없다고 한다.

 

  • webpack 설정 변경하기 (dev, prod 파일 모두 변경)
<project_root>/config/webpack.config.dev.js // dev
<project_root>/config/webpack.config.prod.js // prod

// OR 

<project_root>/config/webpackDevServer.config.js  // dev
<project_root>/config/webpack.config.js  // prod

** npm run eject 명령어를 통해 webpack 설정을 추출하고 나면 위의 경로에 설정 파일이 추출된다.

 

1. PostCSS를 위한 설정

const { styles } = require( '@ckeditor/ckeditor5-dev-utils' );

2. SVG 와 CSS 파일 로더 설정

// module.rules 아래에
/*
    module: {
      strictExportPresence: true,
      rules: [
       ... 여기에 삽입 ...
      ]
*/
{
  test: /ckeditor5-[^/\\\\]+[/\\\\]theme[/\\\\]icons[/\\\\][^/\\\\]+\\.svg$/,
  use: [ 'raw-loader' ]
},
{
  test: /ckeditor5-[^/\\\\]+[/\\\\]theme[/\\\\].+\\.css/,
  use: [
    {
      loader: 'style-loader',
      options: {
        singleton: true
      }
    },
    {
      loader: 'postcss-loader',
      options: styles.getPostCssConfig( {
        themeImporter: {
          themePath: require.resolve( '@ckeditor/ckeditor5-theme-lark' )
        },
        minify: true
      } )
    }
  ]
},

3. 리액트 프로젝트의 웹에서는 css 파일 적용 안되게 배제

  • 기존 코드에서 수정하는 부분
  • /.css$/ 부분이 cssRegex 변수로 설정 되어 있을 수 있다.

{
  test: /\\.css$/,
  exclude: /ckeditor5-[^/\\\\]+[/\\\\]theme[/\\\\].+\\.css/,
  // (...)
}

4. CKEditor 5 의 SVG 와 CSS 파일들은 파일로더로 부터 배제

  • 기존에 추가 되어 있던 파일 로더에 의해 관리 되기 때문에 기존의 loader 코드 위에 덮어쓴다.
{
  loader: require.resolve('file-loader'),
  // Exclude `js` files to keep the "css" loader working as it injects
  // its runtime that would otherwise be processed through the "file" loader.
  // Also exclude `html` and `json` extensions so they get processed
  // by webpack's internal loaders.
  exclude: [
    /\\.(js|jsx|mjs)$/,
    /\\.html$/,
    /\\.json$/,
    /ckeditor5-[^/\\\\]+[/\\\\]theme[/\\\\]icons[/\\\\][^/\\\\]+\\.svg$/,
    /ckeditor5-[^/\\\\]+[/\\\\]theme[/\\\\].+\\.css/
  ],
  options: {
    name: 'static/media/[name].[hash:8].[ext]'
  }
}

 

  • 플러그인 연동
    • raw-loader 및 CKEditor 5 테마와 개발 유틸 라이브러리 설치
    npm install --save-dev raw-loader @ckeditor/ckeditor5-theme-lark @ckeditor/ckeditor5-dev-utils
    
    • 플러그인 설치
    npm install --save @ckeditor/ckeditor5-source-editing
    
    • 설치된 플러그인 import 하여 사용!!

 

적용 결과

또..

 

4. <script> 태그를 통해 CKEditor를 로드한 후 create() 메소드를 호출하여 만들기 https://ckeditor.com/docs/ckeditor5/latest/builds/guides/quick-start.html

  • CKEditor Online Builder에서 원하는 기능들을 추가하고 zip 파일을 다운받는다.
    • 플러그인, 툴바 설정
     

  • zip 파일의 압축을 풀고 build안에 있는 ckeditor.js파일을 public폴더에 js 폴더를 만들어 복붙한다.

  • index.html 파일에 추가한다.
//index.html

// CKEditor 로드
<script src="/js/ckeditor.js"></script>

// body
<div id="editor"></div>

// create 메소드를 호출하여 CKEditor 만들기
<script type="text/javascript">
    const { ClassicEditor } = window
    ClassicEditor.create( document.querySelector( '#editor' ) )
</script>
  • App.js에서 만들어보기
// editor 멤버변수 선언
constructor(props) {
    super(props)
    let editor
}

// create 메소드를 호출하여 CKEditor 만들기
async componentDidMount() {
    const { ClassicEditor } = window
    this.editor = await ClassicEditor.create( document.querySelector( '#editor' ) )
}

 

적용결과

반응형