Sam Park Blog.

Sam의 워드프레스 블로그

Sam Park Blog.

Sam의 워드프레스 블로그

미분류

코딩자율학습 스프링부트3 자바 백엔드 개발 입문 4주차 학습 후기


이번 주에는 게시판의 핵심 기능인 ‘댓글’을 완성했습니다. 백엔드에서 댓글의 생성, 조회, 삭제(CRUD)를 탄탄하게 구현하고, 프론트엔드에서 사용자가 직관적으로 댓글을 등록하고 수정하며 삭제까지 할 수 있도록 모든 기능을 직접 만들어 봤습니다. 이로써 게시판의 기본적인 모든 기능을 스프링부트를 이용해구 구현해 보았습니다.




16일차: 댓글 컨트롤러와 서비스 만들기(생성, 수정, 삭제)

CommentApiController에서 @PostMapping, @PatchMapping, @DeleteMapping을 이용해 REST API 형태로 댓글 생성, 수정, 삭제 기능을 구현했고, CommentService에서 데이터 처리 및 예외 관리를 하였습니다. 특히 @Transactional 어노테이션으로 데이터 일관성을 유지했습니다.


// CommentApiController
@PostMapping("/api/articles/{articleId}/comments") // 댓글 생성
public ResponseEntity<CommentDto> create(@PathVariable Long articleId, @RequestBody CommentDto dto) {
    CommentDto createDto = commentService.create(articleId, dto);
    return ResponseEntity.status(HttpStatus.OK).body(createDto);
}

@PatchMapping("/api/comments/{id}") // 댓글 수정
public ResponseEntity<CommentDto> update(@PathVariable Long id, @RequestBody CommentDto dto) {
    CommentDto updatedDto = commentService.update(id, dto);
    return ResponseEntity.status(HttpStatus.OK).body(updatedDto);
}

@DeleteMapping("/api/comments/{id}") // 댓글 삭제
public ResponseEntity<CommentDto> delete(@PathVariable Long id) {
    CommentDto deleteDto = commentService.delete(id);
    return ResponseEntity.status(HttpStatus.OK).body(deleteDto);
}




17일차: 웹 페이지에서 댓글 목록 보기

특정 게시글에 달른 댓글들을 웹 페이지에 보여주는 기능을 구현했습니다. ArticleController의 show 메서드에서 게시글과 함께 해당 댓글 목록을 CommentService를 통해 가져와 Model에 담았고, 이를 Mustache 템플릿으로넘겨 반복문을 통해 동적으로 랜더링했습니다.


<!-- Mustache  -->
<div id="comments-list">
    {{#commentDtos}}
        <div class="card m-2" id="comments-{{id}}">
            <div class="card-header">{{nickname}}</div>
            <div class="card-body">{{body}}</div>
        </div>
    {{/commentDtos}}
</div>


// ArticleControlle
@GetMapping("/articles/{id}")
public String show(@PathVariable Long id, Model model) {
    Article articleEntity = articleRepository.findById(id).orElse(null);
    List<CommentDto> commentDtos = commentService.comments(id); // 서비스에서 댓글 목록 가져오기

    model.addAttribute("article", articleEntity);
    model.addAttribute("commentDtos", commentDtos); // 모델에 댓글 목록 등록
    return "articles/show";
}




18일차: 웹 페이지에서 댓글 등록하기

사용자가 직접 웹 페이지에서 댓글을 작성하고 등록할 수 있는 기능을 만들었습니다. HTML 폼을 통해 닉네임과 내용을 입력받고, 자바스크립트의 fetch() API를 활용해 백엔드의 댓글 생성 API로비동기 (POST) 요청을 보냈습니다. 입력 데이터를 JSON 형태로 변환(JSON.stringify)하여 전송하였습니다.


<!-- 댓글 작성 폼 HTML -->
<div class="card-body">
    <form>
        <input type="text" class="form-control" id="new-comment-nickname" placeholder="닉네임">
        <textarea class="form-control" rows="3" id="new-comment-body" placeholder="댓글 내용"></textarea>
        {{#article}}
            <input type="hidden" id="new-comment-article-id" value="{{id}}">
        {{/article}}
        <button type="button" class="btn btn-primary" id="comment-create-btn">댓글 작성</button>
    </form>
</div>

<!-- 자바스크립트로 댓글 등록 처리 -->
<script>
    const commentCreateBtn = document.querySelector("#comment-create-btn");
    commentCreateBtn.addEventListener("click", function() {
        const comment = { /* 폼 데이터로 객체 생성 */ };
        fetch("/api/articles/" + comment.articleId + "/comments", {
            method: "POST",
            headers: { "Content-Type": "application/json" },
            body: JSON.stringify(comment)
        }).then(response => {
            alert((response.ok) ? "댓글이 등록됐습니다." : "댓글 등록 실패..!");
            window.location.reload(); // 성공 시 페이지 새로고침
        });
    });
</script>




19일차: 웹페이지에서 댓글 수정하기

각 댓글 옆에 ‘[수정]’ 버튼을 추구하고, 클릭하면 모달 창이 뜨도록 만들었습니다. 이 모달 창에 해당 댓글의 정보(닉네임, 내용 등)을 미리 채워주고, ‘[수정 완료]’ 버튼 클릭시 자바스크립트 fetch() API를 통해 백엔드의 댓글 수정 API(PATCH)로 데이터를 비동기 전송했습니다.


<!-- 댓글 목록에 수정 버튼 추가 -->
<div class="card-header">
    {{nickname}}
    <button type="button" class="btn btn-sm btn-outline-primary" data-bs-toggle="modal"
            data-bs-target="#comment-edit-modal" data-bs-id="{{id}}" data-bs-nickname="{{nickname}}"
            data-bs-body="{{body}}" data-bs-article-id="{{articleId}}">수정</button>
</div>

<!-- 댓글 수정 모달 HTML -->
<div class="modal fade" id="comment-edit-modal">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-body">
                <input type="text" class="form-control" id="edit-comment-nickname">
                <textarea class="form-control" rows="3" id="edit-comment-body"></textarea>
                <input type="hidden" id="edit-comment-id">
                <input type="hidden" id="edit-comment-article-id">
                <button type="button" class="btn btn-primary" id="comment-update-btn">수정 완료</button>
            </div>
        </div>
    </div>
</div>

<!-- 자바스크립트로 모달 데이터 로딩 및 수정 처리 -->
<script>
    // 모달 열릴 때 버튼의 data 속성 값들을 모달 폼에 채워주는 로직
    const commentEditModal = document.querySelector("#comment-edit-modal");
    commentEditModal.addEventListener("show.bs.modal", function(event) {
        const triggerBtn = event.relatedTarget;
        document.querySelector("#edit-comment-nickname").value = triggerBtn.getAttribute("data-bs-nickname");
        // ... 
    });

    // '수정 완료' 버튼 클릭 시 비동기 PATCH 요청
    const commentUpdateBtn = document.querySelector("#comment-update-btn");
    commentUpdateBtn.addEventListener("click", function() {
        const comment = { /* 모달 폼 데이터로 객체 생성 */ };
        fetch("/api/comments/" + comment.id, {
            method: "PATCH", headers: { "Content-Type": "application/json" },
            body: JSON.stringify(comment)
        }).then(response => {
            alert((response.ok) ? "댓글이 수정됐습니다." : "댓글 수정 실패..!");
            window.location.reload();
        });
    });
</script>




20일차: 19장 웹페이지에서 댓글 삭제하기

마지막 학습은 댓글 삭제 기능을 구현했습니다. 각 댓글 옆에 ‘[삭제]’ 버튼을 추구하여 사용자가 직접 댓글을 지울 수 있도록 구현했습니다. ‘[삭제]’ 버튼 클릭 시, 해당 댓글의 ID를 받아 자바스크립트 fetch() API를 통해 백엔드의 댓글 삭제 API(DELETE)로 비동기 요청을 보내는 방식입니다.


<!-- 댓글 삭제 버튼 HTML -->
<button type="button" class="btn btn-sm btn-outline-danger comment-delete-btn" data-comment-id="{{id}}">삭제</button>

<!-- 자바스크립트로 댓글 삭제 처리 -->
<script>
    const commentDeleteBtns = document.querySelectorAll(".comment-delete-btn");
    commentDeleteBtns.forEach(btn => {
        btn.addEventListener("click", (event) => {
            const commentId = event.target.getAttribute("data-comment-id");
            fetch(`/api/comments/${commentId}`, { method: "DELETE" })
                .then(response => {
                    if (!response.ok) {
                        alert("댓글 삭제 실패..!"); return;
                    }
                    alert(`${commentId}번 댓글을 삭제했습니다.`);
                    window.location.reload();
                });
        });
    });
</script>




4주차 마무리

이번 4주차 학습을 통해 게시판의 핵심 기능인 댓글을 완성해 보았으며, 백엔드와 프론트엔드가 어떻게 연결되고 작동하는지 깊이 있게 이해할수 있었습니다. API, 사용자 경험을 고려한 UI를 구현하는 방법까지, 모든 부분을 다 개발할수는 없지만, 어떻게 사용하는 사는 하는지는 알수 있는 시간이였습니다.

스프링 부트를 활용한 백엔드 개발을 이해할수 있었고, 기본적인 웹서비를 어떻게 개발하는지 알수 있는 시간이였습니다. 앞으로 이번에 배운 내용을 가지고 나만의 프로젝트를 만들어 보려고 하며, 4주간의 ‘코딩 자율학습 스프링부트3 자바 백엔드 개발 입문’ 도서를 활용한 학습을 마무리 합니다.

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다