πŸ”§ API_

CKEditor5 이미지 μ—…λ‘œλ“œ μ‹œ JSON 응닡 였λ₯˜ ν•΄κ²°

Joyfullyever 2025. 4. 18. 18:25

❗ 였λ₯˜ 상황

CKEditor5μ—μ„œ 이미지λ₯Ό μ—…λ‘œλ“œν•˜λ €κ³  ν•  λ•Œ λ‹€μŒκ³Ό 같은 였λ₯˜κ°€ λ°œμƒ

SyntaxError: Unexpected token '<', "<!doctype "... is not valid JSON

 

λ˜λŠ” 크둬 μ½˜μ†” 였λ₯˜

POST http://localhost:8080/editor/uploadImage 200 (OK)
Unexpected token '<'

 

λΈŒλΌμš°μ €μ—λŠ” 이미지가 κΉ¨μ§„ μƒνƒœλ‘œ λ‚˜νƒ€λ‚˜κ³ , μ½˜μ†”μ—λŠ” JSON νŒŒμ‹± μ‹€νŒ¨ 였λ₯˜κ°€ λ°œμƒ

 

🎯 원인

CKEditor5λŠ” 이미지 μ—…λ‘œλ“œ μ‹œ fetchλ₯Ό 톡해 μ„œλ²„μ— 이미지λ₯Ό 전솑, λ°˜λ“œμ‹œ μ•„λž˜μ™€ 같은 JSON ν˜•μ‹μ˜ 응닡을 κΈ°λŒ€

{
  "url": "/editor/image?name=파일λͺ….png"
}

μ„œλ²„μ—μ„œ λ‹€μŒκ³Ό 같은 잘λͺ»λœ 응닡을 λ°˜ν™˜ν•˜λ©΄ 였λ₯˜ λ°œμƒ

• HTML λ¬Έμ„œ 전체 (예: JSP νŽ˜μ΄μ§€)

• λ¬Έμžμ—΄ "error" λ˜λŠ” "false" (JSON ν˜•μ‹μ΄ μ•„λ‹˜)

• λΉˆ λ¬Έμžμ—΄

• JSON ν˜•μ‹μ²˜λŸΌ λ³΄μ΄μ§€λ§Œ "Content-Type"이 text/html둜 λ˜μ–΄ 있음

즉, JSON이 μ•„λ‹Œ 응닡을 λ°›μ•„μ„œ CKEditorμ—μ„œ νŒŒμ‹±ν•˜λ‹€κ°€ 였λ₯˜κ°€ λ‚˜λŠ” 것

 

βœ… ν•΄κ²° 방법

 

βœ… μ„œλ²„ (Spring Controller)μ—μ„œ 응닡을 λ°˜λ“œμ‹œ JSON ν˜•μ‹μœΌλ‘œ μ„€μ •

@PostMapping("/editor/uploadImage")
@ResponseBody
public ResponseEntity<Map<String, Object>> uploadImage(@RequestParam("upload") MultipartFile file) {
    try {
        String imageUrl = "/editor/image?name=" + μ €μž₯된파일λͺ…;
        return ResponseEntity.ok(Map.of("url", imageUrl));  // JSON 응닡
    } catch (Exception e) {
        return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
                             .body(Map.of("error", "이미지 μ—…λ‘œλ“œ μ‹€νŒ¨"));
    }
}

• λ°˜λ“œμ‹œ Map.of(...) λ˜λŠ” DTO μ‚¬μš©

• @ResponseBody λ˜λŠ” @RestController ν•„μˆ˜

• 응닡 Content-Type은 μžλ™μœΌλ‘œ application/json이 섀정됨

 

βœ… ν΄λΌμ΄μ–ΈνŠΈ (JS)μ—μ„œ JSON μ‘λ‹΅λ§Œ 처리

fetch('/editor/uploadImage', {
  method: 'POST',
  body: formData
})
.then(response => response.json())  // JSON μ‘λ‹΅λ§Œ λ°›μ•„μ•Ό 함
.then(data => {
  if (data.url) {
    resolve({ default: data.url });
  } else {
    printSweetAlert("error", "이미지 μ—…λ‘œλ“œ μ‹€νŒ¨", "λ‹€μ‹œ μ‹œλ„ν•΄μ£Όμ„Έμš”.");
    reject("μ„œλ²„ μ—λŸ¬ 응닡");
  }
})
.catch(error => {
  printSweetAlert("error", "톡신 였λ₯˜", "μ„œλ²„μ™€μ˜ 연결에 λ¬Έμ œκ°€ μžˆμŠ΅λ‹ˆλ‹€.");
  reject(error);
});

HTML이 λ°˜ν™˜λ  경우 response.json() λ‹¨κ³„μ—μ„œ μ—λŸ¬ λ°œμƒν•¨

• resolve() λ˜λŠ” reject() ν˜ΈμΆœμ— 따라 에디터 UI에 λ°”λ‘œ 반영됨

 

πŸ“Œ λΆ€κ°€ 팁

1. JSP λ‚΄μ—μ„œ <script>window.alert = function(){};</script> μ„€μ •μœΌλ‘œ κΈ°λ³Έ alert 차단 → SweetAlert μ‚¬μš©

2. editor.js, updateBoard.js처럼 κΈ°λŠ₯λ³„λ‘œ JSλ₯Ό λΆ„λ¦¬ν•˜λ©΄ μœ μ§€λ³΄μˆ˜μ— 유리

3. 이미지 μ €μž₯은 application.properties의 upload.path와 μ—°λ™ν•˜μ—¬ 관리