Nextjs Ckeditor 적용
1.모듈을 설치한다.
1) npm 으로 설치한다.
npm install --save @ckeditor/ckeditor5-react
npm install --save @ckeditor/ckeditor5-build-classic
npm install --save @ckeditor/ckeditor5-code-block
2) online builder 를 사용한다 ( 추천 )
https://ckeditor.com/ckeditor-5/online-builder/
위에서 필요한 기능을 찾아서 import 시킨후 다운받는다.
3) 설치방법
- zip 파일을 다운받고 압축해제한다.
- 프로젝트 root. 경로에 위치시킨다. ckeditor5로저장
- npm install file ./ckeditor5
주의사항
nextjs 에서 vercel 에 업데이트할떄 npm file 도 같이 업로드해야한다.
ckeditor5 디렉토리도 같이올려야 패키지에서 제대로 설치된다.
- 주의점 : markdown 모듈이 있으면 html 로 반환이 안된다.
전체코드
import React from 'react';
import { CKEditor } from "@ckeditor/ckeditor5-react";
// import Editor from '@ckeditor/ckeditor5-build-classic';
import Editor from "ckeditor5-custom-build";
import showPopup from './PopUp';
import { request } from '../utils/network';
import { getCookie } from '@/utils/cookie';
import '@/css/ckeditor.css'
export default function CkEditor({ placeholder, value, setData }) {
const customUploadAdapter = (loader) => { // (2)
// console.log(loader)
return {
upload() {
return new Promise((resolve, reject) => {
const data = new FormData();
loader.file.then((file) => {
data.append("name", file.name);
data.append("file", file);
const formData = new FormData();
let jsonData = { company_key: getCookie("company_key") }
formData.append("json", new Blob([JSON.stringify(jsonData)], { type: "application/json" }));
formData.append('contents_img', file);
let NETWORK_API_URL = process.env.NEXT_PUBLIC_REACT_APP_API_URL + process.env.NEXT_PUBLIC_REACT_APP_API_SPEAKY_CONTENTS_UPLOAD_URL;
console.log(NETWORK_API_URL, formData)
request(NETWORK_API_URL, 'POST', formData)
.then((response) => {
console.log('응답 값', NETWORK_API_URL, response);
if (response.resultCode !== "200") {
showPopup("정부수정 경고 ", response.resultCode, () => {
console.log('Popup Closed!');
});
const errorData = response.json();
throw new Error(errorData.message || '서버에 문제가 있습니다.');
} else {
// url = response.res;
// console.log(url);
resolve({
default: response.res
});
// resolve(response.res)
}
})
.catch((err) => reject(err));;
})
})
}
}
}
function uploadPlugin(ckeditor) { // (3)
ckeditor.plugins.get('FileRepository').createUploadAdapter = (loader) => {
return customUploadAdapter(loader);
}
}
const editorConfig = {
// 여기에 원하는 옵션을 추가합니다.
fontFamily: {
options: [
'default',
'Arial, Helvetica, sans-serif',
'Georgia, serif',
'Impact, Charcoal, sans-serif',
'Tahoma, Geneva, sans-serif',
'Times New Roman, Times, serif',
'Verdana, Geneva, sans-serif',
'Arial, sans-serif',
'Gothic, sans-serif',
'Helvetica, sans-serif',
'Helvetica Neue, sans-serif',
'sohne, sans-serif',
'serif',
'monospace',
'"Times New Roman", Times, serif'
],
supportAllValues: true
},
fontSize: {
options: ['10px','12px', '14px', '16px', '18px', '20px', '24px', '26px', '28px', '30px', '32px', '34px', '36px'],
supportAllValues: true, // Allow custom font size values
},
codeBlock: {
languages: [
{ language: 'css', label: 'CSS' },
{ language: 'html', label: 'HTML' },
{ language: 'plaintext', label: 'Plain text', class: '' },
{ language: 'php', label: 'PHP', class: 'php-code' },
{ language: 'javascript', label: 'JavaScript', class: 'js javascript js-code' },
{ language: 'python', label: 'Python' },
{ language: 'ruby', label: 'Ruby' },
{ language: 'java', label: 'Java' }, // 추가: Java
{ language: 'c', label: 'C' }, // 추가: C
{ language: 'csharp', label: 'C#' }, // 추가: C#
{ language: 'bash', label: 'Bash' }, // 추가: Bash
{ language: 'typescript', label: 'TypeScript' }, // 추가: TypeScript
{ language: 'swift', label: 'Swift' }, // 추가: Swift
{ language: 'nodejs', label: 'Node.js' }, // 추가: Node.js
{ language: 'react', label: 'React' } // 추가: React
]
},
extraPlugins: [uploadPlugin],
removePlugins: [ 'Autoformat' ],
// horizontalLine: {
// htmlSupport: true,
// // Add your custom class to the horizontal line element
// class: 'custom-horizontal-line',
// },
// indentBlock: {
// offset: 3,
// unit: 'em',
// classes: [
// 'custom-block-indent-a', // First step - smallest indentation.
// 'custom-block-indent-b',
// 'custom-block-indent-c' // Last step - biggest indentation.
// ]
// },
// styles: [
// {
// name: 'IncreasedSpacing',
// element: 'p',
// attributes: {
// class: 'increased-spacing',
// },
// definitions: [
// {
// name: 'Article category',
// element: 'h3',
// classes: [ 'category' ]
// },
// {
// name: 'Info box',
// element: 'p',
// classes: [ 'info-box' ]
// },
// ]
// },
// ],
// toolbar: {
// items: [
// 'heading',
// '|',
// 'bold',
// 'italic',
// 'codeBlock', // 코드 블록 버튼 추가
// '|',
// 'undo',
// 'redo'
// ]
// },
// codeBlock: {} // 코드 블록 옵션 추가ㄴ
// 기타 옵션들...
};
const handleEditorChange = (event, editor) => {
// console.log(event)
const data = editor.getData({ fullPage: true });
// console.log('editor', data);
setData(data)
};
return (
<>
<CKEditor
editor={Editor}
data={value}
onChange={handleEditorChange}
config={editorConfig} />
</>
)
}


