๋ง์ ๊ฐ๋ฐ์๋ถ๋ค๊ป์ ์ฌ๋ฌ๊ฐ์ง ํธ์ง๋๊ตฌ๋ค์ ์ฌ์ฉํ๊ณ ๊ณ์ญ๋๋ค.
์ ์ ์ฃผ๋ณ ์น๊ตฌ, ์ง์ธ, ์ ๋ฐฐ ๊ฐ๋ฐ์๋ถ๋ค๋ ์ ๋ง ๋ง์ ํธ์ง๋๊ตฌ๋ค์ ์ฌ์ฉํ๊ณ ๊ณ์ จ์ต๋๋ค.
("Naver Smart Editor", "Summernote", "CKEditor", "Daum open Editor", "TicyMCE" ๋ฑ๋ฑ)
์ ๋ ๋ง์ ํธ์ง ๋๊ตฌ๋ค ์ค์์ CKEditor4๋ฅผ ์๊ฐํ๊ณ ์๋ํฐ๋ฅผ ํตํด์ ์ด๋ฏธ์ง๋ฅผ ์ ๋ก๋ํ๋ ๋ฐฉ๋ฒ์ ๋ํด์ ์ด์ผ๊ธฐํ๊ณ ์ ํฉ๋๋ค.
CKEDITOR4๋?
"์๋ฐฑ๋ง์ ์น์ธ์ ๋ฐ์์ต๋๋ค. ์๋ฒฝํ๊ฒ ์ฌ์ฉ์ ์ ์๋ฅผ ํ ์ ์๊ณ , ๊ฐ์ฅ ๋ง์ ๊ธฐ๋ฅ์ ๊ฐ์ถ ์ต๊ณ ์ ํ ์คํธ ํธ์ง๊ธฐ์ ๋๋ค. ์๋/์์ /๊ตฌ๊ธ๋ฌธ์ ๋๊ตฌ์์ ๋ถ์ฌ๋ฃ๊ธฐ, ์ด ํฌ๊ธฐ ์กฐ์ /ํ ๋ฐ ์ด ์ ํ์ ๋ํ ์ฐ์ํ ํ ๋ฆฌ๋ธ ์ง์, ๋ฏธ๋์ด ์๋ฒ ๋/์์ ฏ/์ฝ๋ ์ค๋ํซ/์ํ๊ณต์ ํธ์ง, ์๋์์ฑ/@๋ฉ์ /์ด๋ชจํฐ์ฝ ํ๋ฌ๊ทธ์ธ, ์ธ๋ผ์ธ ๋ฐ ifram UI, ๋ฐฉํด์๋ ์ฐ๊ธฐ๋ฅผ ์ํ ์ต๋ ๋ชจ๋/์ฝ๊ธฐ ์ ์ฉ๋ชจ๋ ๋ฑ์ ์ ๊ณตํ๋ ์ค๋งํธ WYSIWYG ํธ์ง ์๋ฃจ์ ์ ์ ๊ณตํฉ๋๋ค. "
์ฌ์ฉ ๋ฒ์
๊ธฐ์กด : 4.8.0
์ ์ฉ : 4.10.1
์ง๊ธ๋ถํฐ ์์ฑํ๊ณ ์๊ฐํด๋๋ฆฌ๋ "CKEditor4๋ฅผ ์ด์ฉํด ์ด๋ฏธ์ง ์ ๋ก๋ํ๊ธฐ"๋ฅผ ํตํด์ ์กฐ๊ธ์ด๋๋ง CKEditor๋ฅผ ์ฌ์ฉํ์๋๋ฐ ๋์์ด ๋์ จ์ผ๋ฉด ์ข๊ฒ ์ต๋๋ค! ๋น๋ก ๋ถ์กฑํ ์ค๋ ฅ์ด์ง๋ง ์ ๊ฐ ๋ง๋ค์ด๋ณด๋ฉด์ ๊ฒฝํํ ๋ด์ฉ๋ค๋ก ๊ตฌ์ฑํ์์ต๋๋ค.
CKEditor ์ ์ฉํ๊ธฐ
1. CKEditor ์ ์ฉํ๊ธฐ
CKEditor๋ฅผ ๊ตฌ์ฑํ๊ธฐ ์ํ ํํ์ด์ง URL(https://ckeditor.com/cke4/builder ์ ์ํฉ๋๋ค.)
Builder
Star CKEditor 4 on GitHub
ckeditor.com
2. ํจํค์ง ์ ํํ๊ธฐ
์ํ์๋ ํจํค์ง๋ฅผ ์ ํํด์ฃผ์ธ์. ์ ๋ Full ํจํค์ง๋ฅผ ์ ํํ์ต๋๋ค.
3. Plugins ์ ํํ๊ธฐ
ํ์ํ์ Plugins๋ฅผ ์ ํํฉ๋๋ค. ์ ๋ ํ์ํ ํ๋ฌ๊ทธ์ธ๋ค์ค์์ Youtube Plugins๋ฅผ ์ ํํ์ต๋๋ค.
ํ์ํ ํ๋ฌ๊ทธ์ธ์ด ์์ผ์๋ฉด ์ ํํ์ ์ ์ถ๊ฐํด์ฃผ์๋ฉด ๋ฉ๋๋ค.
4. Skin ์ ํํ๊ธฐ
์ํ์๋ Skin์ ์ ํํฉ๋๋ค. ์ ๋ Moono-Lisa Skin์ ์ ํํ์ต๋๋ค.
์ํ์๋ ๋ชจ์์ด๋ ๋์์ธ์ด ์์ผ์๋ค๋ฉด ์ํ์๋ Skin์ผ๋ก ์ ํํด์ฃผ์ธ์.
5. ์ธ์ด ์ ํํ๊ธฐ
์ฌ์ฉํ์ค ์ธ์ด๊ฐ ์์ผ์ค ๊ฒฝ์ฐ ์ ํ์ ์ผ๋ก ๊ณจ๋ผ์ ์ถ๊ฐํ์ ๋ ๋๊ณ , ์ ์ฒด์ ํ์ ์ ํํ์ ์ ์ ์ฒด๋ฅผ ์ถ๊ฐํ์ ๋ ๋ฉ๋๋ค.
6. ๋์ ํ ๋ค์ด๋ก๋
๋์ ํ์ธ์ ๋์ ์ฒดํฌ๋ฅผ ํด์ฃผ์ธ์. ๋์์ฒดํฌ๋ฅผ ๊ผญ ํด์ฃผ์ ์ผ ๋ค์ด๋ก๋๊ฐ ๊ฐ๋ฅํฉ๋๋ค.
์ฌ๊ธฐ๊น์ง ์งํํ์ จ์ผ๋ฉด CKEditor4๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํ ํ์ผ์ค๋น๋ ๋ค ๋๋์ จ์ต๋๋ค.
์ ๋ ์ ์์ ๋ถํ๋ ์์ํฌ๋ฅผ ์ด์ฉํด CKEditor4๋ฅผ ์ ์ฉํ ๊ฒ์ํ์ ๊ฐ๋ฐํ์ต๋๋ค.
7. ํด๋&ํ์ผ ๊ตฌ์ฑํ๊ธฐ
๋ค์ด๋ก๋ ๋ฐ์ผ์ CKEditor4.10.1๋ฒ์ ์ ์์ถํ์ผ์ ํด์ ํ์๊ณ , CKEditorํด๋๋ฅผ webappํด๋ ๋ฐ๋ก ์๋์ ๋ณต์ฌ/๋ถ์ฌ๋ฃ๊ธฐ ํด์ฃผ์ธ์.
webapp
- ckeditor
์์ ๊ฐ์ ํด๋&ํ์ผ ๊ตฌ์กฐ๊ฐ ๋ ๊ฒ๋๋ค.
8. JS&SCRIPT ๊ตฌ์ฑํ๊ธฐ
<head>ํ๊ทธ ๋๋ <body>ํ๊ทธ์์ ckditor.js๋ฅผ ๋ฑ๋กํด์ค๋๋ค.
<script type="text/javascript" src="${pageContext.request.contextPath }/ckeditor/ckeditor.js"></script>
textarea๊ฐ ์ฐ์ด๋ .jspํ์ผ์ CKEditor ๋ฑ๋ก ์คํฌ๋ฆฝํธ ์ฝ๋๋ฅผ ์ด์ฉํด์ textarea๊ฐ CKEditor๋ก ์ฌ์ฉ๋์ด์ง ์ ์๋๋ก ๋ฑ๋กํด์ค๋๋ค. ์ด๋, ์ด๋ฏธ์ง ์ ๋ก๋ ์ปจํธ๋กค๋ฌ์ ์ ๊ทผํ ์ ์๋๋ก filebrowserUploadUrl๊ฒฝ๋ก๋ฅผ ์ง์ ํด์ค๋๋ค.
<script type="text/javascript">
$(function(){
CKEDITOR.replace('bo_content',{
filebrowserUploadUrl: '${pageContext.request.contextPath }/adm/fileupload.do'
});
});
</script>
JS&SCRIPT๋ฅผ ๋ฑ๋กํ๋ค๋ฉด textarea๊ฐ CKEditor ํธ์ง๊ธฐ๋ก ๋ณํด์๋๊ฑธ ํ์ธํ ์ ์์ต๋๋ค.
Fullํจํค์ง์์ ์ ๊ณตํด์ฃผ๋ Plugins๋ค์ด ์ ๋ถ ๋ค์ด์๋๊ฒ์ ํ์ธํ ์ ์์ต๋๋ค. ์ ๋ Youtube Plugins์ ์ถ๊ฐ๋ก ์ ์ฉํ๊ธฐ ๋๋ฌธ์ Youtube plugins์ด ์ถ๊ฐ๋ก ์ ์ฉ๋ ํ๋ฉด์ ํ์ธํ ์ ์์ต๋๋ค.
9. ์ด๋ฏธ์ง ์ ๋ก๋ํ๊ธฐ
์คํ์ผ Plugin์์ ๋ณด์ด๋ ์ด๋ฏธ์ง ์์ด์ฝ์ ํด๋ฆญ ํ, ์ด๋ฏธ์ง ์์ฑ ๋ค์ด์ด๋ก๊ทธ๊ฐ ํ๋๋ฉ๋๋ค.
"ํ์ผ์ ํ"๋ฒํผ์ ํด๋ฆญํด open file ๋ค์ด์ด๋ก๊ทธ์์ ์ ๋ก๋ ํ ์ด๋ฏธ์ง๋ฅผ ์ ํํฉ๋๋ค.
์ ๋ ํ ์คํธ๋ก Lighthouse.jpg ์ด๋ฏธ์ง๋ฅผ ์ ํํ์ต๋๋ค.
์ด๋ฏธ์ง ์ ํ ํ, "์๋ฒ๋ก ์ ์ก"๋ฒํผ์ ํด๋ฆญํฉ๋๋ค.
10. CKEditorํธ์ง ๋๊ตฌ๋ก ์ด๋ฏธ์ง ๊ฐ์ ธ์ค๊ธฐ
์๋ฒ๋ก ์ ์ก๋ ์ด๋ฏธ์ง๋ก ๋ง๋ค์ด์ง URL๊ณผ ์๋ฒ์์ ๊ฐ์ ธ์จ ์ด๋ฏธ์ง๋ฅผ ํ์ธํ ์ ์์ต๋๋ค.
๋๋น, ๋์ด, ํ ๋๋ฆฌ, ๊ฐ๋ก์ฌ๋ฐฑ, ์ธ๋ก์ฌ๋ฐฑ, ์ ๋ ฌ ๋ฑ ์คํ์ผ ์์๋ค์ ์์ฑ๊ฐ์ ์ค์ ํ "ํ์ธ" ๋ฒํผ์ ๋๋ฌ CKEditorํธ์ง ๋๊ตฌ๋ก ์ด๋ฏธ์ง๋ฅผ ๊ฐ์ ธ์ฌ ์ ์์ต๋๋ค.
์ ๋ก๋ํ ์ด๋ฏธ์ง๋ฅผ CKEditor ํธ์ง ๋๊ตฌ์์ ํ์ธํ ์ ์์ต๋๋ค.
CKEditor4๋ฅผ ํตํด์ ์ด๋ฏธ์ง ์์ฑ์ ํตํด ์ด๋ฏธ์ง๋ฅผ ์ ๋ก๋ํ๊ณ ์ ๋ก๋ํ ์ด๋ฏธ์ง๋ฅผ ์๋ฒ๋ก ์ ์กํ ํ, CKEditorํธ์ง๊ธฐ๋ก ์ด๋ฏธ์ง๋ฅผ ๊ฐ์ ธ์ค๋๊ฒ๊น์ง ํด๋ณด์์ต๋๋ค. ํ๋ฆ์ผ๋ก ๋ณด๋ฉด ์ด๋ ต์ง ์์ ๊ณผ์ ์ด๋ผ๊ณ ์๊ฐํฉ๋๋ค.
์ด๋ฏธ์ง ์ ๋ก๋๋ฅผ ๊ตฌํํ๊ธฐ ์ํ ์์ค ๋ถ๋ถ์ ์ดํด๋ณด๋๋ก ํ๊ฒ ์ต๋๋ค.
์ด๋ฏธ์ง ์ ๋ก๋ ๊ตฌํํ๊ธฐ
1. POM.xml ๊ตฌ์ฑํ๊ธฐ
JSON์ ์ฌ์ฉํ๊ธฐ ์ํด JSON Dependency๋ฅผ ๋ฑ๋กํฉ๋๋ค.
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.2</version>
</dependency>
2. Controller ์์ฑํ๊ธฐ
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Map;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import com.google.gson.JsonObject;
@Controller
@RequestMapping("/adm")
public class CkeditorFileUploadController {
@RequestMapping(value="fileupload.do", method=RequestMethod.POST)
@ResponseBody
public String fileUpload(HttpServletRequest req, HttpServletResponse resp,
MultipartHttpServletRequest multiFile) throws Exception {
JsonObject json = new JsonObject();
PrintWriter printWriter = null;
OutputStream out = null;
MultipartFile file = multiFile.getFile("upload");
if(file != null){
if(file.getSize() > 0 && StringUtils.isNotBlank(file.getName())){
if(file.getContentType().toLowerCase().startsWith("image/")){
try{
String fileName = file.getName();
byte[] bytes = file.getBytes();
String uploadPath = req.getServletContext().getRealPath("/img");
File uploadFile = new File(uploadPath);
if(!uploadFile.exists()){
uploadFile.mkdirs();
}
fileName = UUID.randomUUID().toString();
uploadPath = uploadPath + "/" + fileName;
out = new FileOutputStream(new File(uploadPath));
out.write(bytes);
printWriter = resp.getWriter();
resp.setContentType("text/html");
String fileUrl = req.getContextPath() + "/img/" + fileName;
// json ๋ฐ์ดํฐ๋ก ๋ฑ๋ก
// {"uploaded" : 1, "fileName" : "test.jpg", "url" : "/img/test.jpg"}
// ์ด๋ฐ ํํ๋ก ๋ฆฌํด์ด ๋๊ฐ์ผํจ.
json.addProperty("uploaded", 1);
json.addProperty("fileName", fileName);
json.addProperty("url", fileUrl);
printWriter.println(json);
}catch(IOException e){
e.printStackTrace();
}finally{
if(out != null){
out.close();
}
if(printWriter != null){
printWriter.close();
}
}
}
}
}
return null;
}
}
๊ธฐ์กด์ ์ฌ์ฉํ๋ ์์ค์์๋ ์คํฌ๋ฆฝํธ๋ฅผ ์ด์ฉํด ๋ด๋ณด๋ด๋ ์์ค์๋ค๋ฉด, 4.9.0์ด์์ ๋ฒ์ ๋ค์์๋ JSON๋ฐ์ดํฐ์ ํํ๋ก ๋ฆฌํดํ๋ผ๊ณ CKEditor document์ ์ ์ํ๊ณ ์์ต๋๋ค. ๊ทธ๋์, JSON๋ฐ์ดํฐ ํ์์ ์์ค๋ก ๋ณ๊ฒฝ ํ ์ค์ ๋ก ์ด๋ฏธ์ง๊ฐ ๋ธ๋ผ์ฐ์ ๋ฅผ ํตํด ์ถ๋ ฅ๋๋๊ฒ์ ํ์ธํ ์ ์์์ต๋๋ค.
JsonObject json = new JsonObject();
json.addProperty("uploaded", 1);
json.addProperty("fileName", fileName);
json.addProperty("url", fileUrl);
๋ง๋ฌด๋ฆฌ
๋ง์ ๊ฐ๋ฐ์๋ถ๋ค๊ป์ ์ด๋ฏธ ์๊ณ ๊ณ์๊ณ ์ด๋ฏธ ์ฌ์ฉํ๊ณ ๊ณ์ ๋ถ๋ค์ด ์ ๋ง ๋ง์๊ฑฐ๋ผ๊ณ ์๊ฐํฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ , ์ ๊ฐ ์ฌ์ฉํ๊ณ ์๋ ์์ค๋ณด๋ค ๋ ์ข์ ๋ฐฉ๋ฒ์ผ๋ก, ๋ ์ข์ ์์ค๋ก ๊ตฌํํ๊ณ ๊ณ์ ๋ถ๋ค๋ ๋ง์๊ฑฐ๋ผ๊ณ ์๊ฐํฉ๋๋ค.
์ด๊ฒ์ ๊ฒ ๊ณต๋ถํ๊ณ ๊ฒฝํํ๊ณ ๋ง๋ค์ด๋ณด๊ณ ์ถ์ ์ด์ ๋ง์ ํ๋ช ์ ๊ฐ๋ฐ์๊ฐ ๋ถ์กฑํ ์ค๋ ฅ์ด์ง๋ง ์ง์ ๊ตฌํํ ๊ธฐ๋ฅ์ ๊ณต์ ํ๊ณ ์ ํฉ๋๋ค. ๋ง์ ์กฐ์ธ๊ณผ ๊ฐ๋ฅด์นจ ์ฃผ์ค๋ถ์ ๋๊ธ๋ก ์์ ๋กญ๊ฒ ๋จ๊ฒจ์ฃผ์ ๋ ์ข์ต๋๋ค! ์ ๋ ๋ง์๊ฒ๋ค ๋ฐฐ์ฐ๊ณ ๊ณต๋ถํ๋ค๋ฉด ๋ ์ข์๊ฒ ๊ฐ์ต๋๋ค! ๊ธด๊ธ์ด์ง๋ง ์ฝ์ด์ฃผ์ ์ ๊ฐ์ฌํ๊ณ , ์๊ฒ๋๋ง ๊ผญ ๋์์ด ๋์์ผ๋ฉด ์ข๊ฒ ์ต๋๋ค.
@Junesker
๋๊ธ