๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

Spring

mustache์—์„œ summernote ์‚ฌ์šฉ

summernote + mustache

์›น์—๋””ํ„ฐ์ธ summernote ๊ธ€์„ ์ž‘์„ฑํ•˜๊ณ , ์Šคํ”„๋ง ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•ด์„œ mustache์—์„œ ์ž‘์„ฑํ•œ ๊ธ€์„ ํ™•์ธํ•ด๋ณธ๋‹ค.

summernote ์—ฐ๊ฒฐ ๋ฐ ์ƒ์„ฑ

import

<!-- include libraries(jQuery, bootstrap) -->
<link href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>

<!-- include summernote css/js -->
<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>

summernote ์‚ฌ์šฉ ์‹œ์— ํ•„์š”ํ•œ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋“ค์„ ์šฐ์„  ์ž„ํฌํŠธ ํ•ด ์ค€๋‹ค.

summer note ํด๋ž˜์Šค ์ง€์ •

<div class="form-group">
  <label for="content">ToDo</label>
  <textarea class="form-control summernote" id="content"></textarea>
</div>

์œ„์™€ ๊ฐ™์ด ๋ถ€ํŠธ์ŠคํŠธ๋žฉ์—์„œ summernote๋กœ ์‚ฌ์šฉ๋  ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค์–ด์ฃผ๊ณ , ํด๋ž˜์Šค์— summernote๋ฅผ ์ถ”๊ฐ€ํ•œ๋‹ค.

<script>
    $('.summernote').summernote({
                height:250
    });
</script>

์Šคํฌ๋ฆฝํŠธ ํƒœ๊ทธ์— ์„œ๋จธ ๋…ธํŠธ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ฒŒ ์ถ”๊ฐ€ํ•ด ์ค€๋‹ค.

height ์†์„ฑ์œผ๋กœ ํฌ๊ธฐ๋ฅผ ํ•„์š”ํ•œ ๋งŒํผ ์ง€์ •ํ•ด ์ค€๋‹ค.

summernote ํ™”๋ฉด


์œ„์™€ ๊ฐ™์ด ํ”„๋ก ํŠธ์—์„œ ์„œ๋จธ ๋…ธํŠธ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

ajax๋กœ ์—ฐ๊ฒฐ

์œ„์˜ ์ด๋ฏธ์ง€์ฒ˜๋Ÿผ ๋ฒ„ํŠผ์„ ํ•˜๋‚˜ ๋งŒ๋“ค๊ณ , ajax๋กœ ์Šคํ”„๋ง ์ปจํŠธ๋กค๋Ÿฌ์™€ ์—ฐ๊ฒฐํ•ด ์ค€๋‹ค.

    save: function (){
        let data = {
            title: $("#title").val(),
            content: $("#content").val(),
        };
        if(data.title==""){
            alert("title์„ ์ž‘์„ฑํ•ด์ฃผ์„ธ์š”.");
            return;
        }
        $.ajax({
            type:"POST",
            url:"/api/writeProc",
            data: JSON.stringify(data),
            contentType:"application/json;utf-8",
        })
        .done(function (response){
            if(response.status===500){
                alert("์ž‘์„ฑ์— ์‹คํŒจํ•˜์˜€์Šต๋‹ˆ๋‹ค.");
            }
            else{
                alert("์ž‘์„ฑ์— ์„ฑ๊ณตํ•˜์˜€์Šต๋‹ˆ๋‹ค.");
            }
            location.href="/todolist/proceeding?page=0";
        })
        .fail(function (error){
           JSON.stringify(error);
        })
    }

์ด์ œ "/api/writeProc"์˜ ์ฃผ์†Œ๋กœ ์Šคํ”„๋ง ์ปจํŠธ๋กค๋Ÿฌ์™€ ์—ฐ๊ฒฐํ•ด ์ฃผ์ž.

api controller & service

api controller

    @PostMapping("api/writeProc")
    public int write(@RequestBody TaskWriteDto taskWriteDto, @AuthenticationPrincipal PrincipalDetails principalDetails){
        taskService.write(taskWriteDto, principalDetails);
        return HttpStatus.OK.value();
    }

api service

    @Transactional
    public void write(TaskWriteDto taskWriteDto, PrincipalDetails principalDetails){
        taskRepository.save(taskWriteDto.toEntity());
    }

๊ฒŒ์‹œ๊ธ€ ์ž‘์„ฑ์— ํ•„์š”ํ•œ dto๋ฅผ ๋”ฐ๋กœ ์ƒ์„ฑํ•ด ์คฌ๊ณ , ์ปจํŠธ๋กค๋Ÿฌ์™€ ์„œ๋น„์Šค๋ฅผ ์‚ฌ์šฉํ•ด ๊ธ€์„ db์— ์ €์žฅํ•œ๋‹ค.

์ด๋•Œ ์„œ๋น„์Šค์—๋Š” ํŠธ๋žœ์žญ์…˜์„ ๋ณด์žฅํ•˜๊ธฐ ์œ„ํ•ด @Transactional ์–ด๋…ธํ…Œ์ด์…˜์„ ๋ถ™์—ฌ์ค€๋‹ค.

JSON ํ˜•ํƒœ๋กœ ๊ฒฐ๊ณผ ํ™•์ธ

mustache๋กœ ์ถœ๋ ฅํ•˜๊ธฐ ์ „, ์šฐ์„  ๋ฐ์ดํ„ฐ๊ฐ€ ์ž˜ ์ „๋‹ฌ๋˜๋Š”์ง€ JSON ํ˜•ํƒœ๋กœ ํ™•์ธํ•ด๋ณด์ž.

์œ„์™€ ๊ฐ™์€ test ๊ธ€์„ ์ž‘์„ฑํ•ด๋ณด์ž.

   @GetMapping("/task/detail/{id}")
    @ResponseBody
    public Task taskDetail(@PathVariable long id){
        Task requestTask = taskService.findTask(id);
        return requestTask;
    }

์œ„์™€ ๊ฐ™์ด @ResponseBody๋ฅผ ์ด์šฉํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ˜ํ™˜ํ•˜๋Š” ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค.

๋ฐ์ดํ„ฐ๊ฐ€ ์ž˜ ์ „๋‹ฌ๋จ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

mustache๋กœ ์ถœ๋ ฅ

<br/>
<div class="container">
    <h1>{{task.title}}</h1>
    <hr/>
    <div>{{{task.content}}}</div>
</div>

model ๊ฐ์ฒด๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•ด ์ฃผ๊ณ  mustache์˜ body ๋ถ€๋ถ„๋งŒ ๋ณด๋ฉด ๋‹ค์Œ ๊ฐ™์ด ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ๋‹ค.

์—ฌ๊ธฐ์„œ ์ฃผ์˜ํ•  ์ ์€, summernote์˜ content ๋ถ€๋ถ„์€ ์ค‘๊ด„ํ˜ธ๊ฐ€ ์„ธ ์Œ์œผ๋กœ ๋“ค์–ด๊ฐ€์•ผ ํ•œ๋‹ค!!

๋‘ ์Œ์œผ๋กœ ๋“ค์–ด๊ฐ€๋ฉด mustache๊ฐ€ html ์†Œ์Šค๋กœ ํ•ด์„ํ•˜์ง€ ์•Š๊ณ  ๋‹ค์‹œ ์ปดํŒŒ์ผํ•˜์—ฌ html์˜ ๋‚ด์šฉ์„ text๋กœ ์ถœ๋ ฅํ•ด ์ค€๋‹ค.

๋‘ ๊ฐœ์˜ ์ค‘๊ด„ํ˜ธ ์ผ ๋•Œ

์„ธ ๊ฐœ์˜ ์ค‘๊ด„ํ˜ธ ์ผ ๋•Œ

์„ธ ๊ฐœ์˜ ์ค‘๊ด„ํ˜ธ๋กœ ์ •์ƒ์ ์œผ๋กœ summernote์˜ content๋ฅผ ์ถœ๋ ฅํ•˜๋Š” ๊ฒƒ์„ ์•Œ ์ˆ˜ ์žˆ๋‹ค.