LG CNS Inspire Camp AI 서비스 개발을 위한 백엔드 II (8)

오리·2026년 6월 25일

LG AM Inspire camp 5기

목록 보기
20/35

오늘 배운 것

( 사실 뭘 배웠다기 보단 어제 수업 계속 이어가는 거임 )

1. 블로그 게시글 Mapping

2. 블로그 게시글 댓글 Mapping

3. 블로그 게시글 댓글 CRUD 틀 잡기

1. 블로그 메인 페이지 연동하기

react의 api.get을

back presentation layer controller 와 endpoint를 맞춰줌

package com.inspire.lgcns_mybatis.features.blog.ctrl;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.inspire.lgcns_mybatis.features.blog.domain.dto.BlogRequestDTO;
import com.inspire.lgcns_mybatis.features.blog.domain.dto.BlogResponseDTO;
import com.inspire.lgcns_mybatis.features.blog.service.BlogService;

import lombok.RequiredArgsConstructor;

import java.util.List;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;



@RestController
@RequestMapping("/blog")
//의존관계주입받기
@RequiredArgsConstructor
public class BlogController {
    
    private final BlogService blogService;
    //user endpoint : http://ip:port / blog / list
    @GetMapping("/list")
    public ResponseEntity<List<BlogResponseDTO>> list() {
        System.out.println(">>> debug blog controller list");
        List<BlogResponseDTO> list = blogService.list();

        if(list.size() != 0) {
            return ResponseEntity.status(HttpStatus.OK).body(list);
        } else {
            return ResponseEntity.status(HttpStatus.NO_CONTENT).build();
        }
    }

    @PostMapping("/write")
    public ResponseEntity<Void> write(@RequestBody BlogRequestDTO request) {
        System.out.println(">>> debug blog controller write");
        System.out.println(">>> debug blog request params"+request);

        int insertFlag = blogService.write(request);

        if(insertFlag != 0) {
            return ResponseEntity.status(HttpStatus.CREATED).build();
        } else {
            return ResponseEntity.status(HttpStatus.BAD_REQUEST).build();
        }
    }

    @GetMapping("/read/{id}")
    public ResponseEntity<BlogResponseDTO> read(@PathVariable("id") Integer id) {

        System.out.println(">>> debug blog controller read");
        System.out.println(">>> debug blog request path variable : "+id);

        BlogResponseDTO response = blogService.read(id);
        System.out.println(">>> debug read service 동작 확인" + response);
        //code : 200(OK) 404(Not Found)
        if(response != null) {
            return ResponseEntity.status(HttpStatus.OK).body(response);
        } else {
            return ResponseEntity.status(HttpStatus.NOT_FOUND).build();
        }
    }
    
    
    
}

point : PathVariable 로 전달하기

엔드포인트에 변수가 들어가는데 글들이 있으면

다음과 같은 id 숫자가 붙은 걸 백엔드에 전달할때는

PathVariable로 인자를 전달한다 !

package com.inspire.lgcns_mybatis.features.blog.service;

import java.util.List;
import java.util.Optional;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.inspire.lgcns_mybatis.features.blog.domain.dto.BlogRequestDTO;
import com.inspire.lgcns_mybatis.features.blog.domain.dto.BlogResponseDTO;
import com.inspire.lgcns_mybatis.features.blog.repository.BlogMapper;
import com.inspire.lgcns_mybatis.features.comment.domain.dto.CommentResponseDTO;
import com.inspire.lgcns_mybatis.features.comment.repository.CommentMapper;

import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor
public class BlogService {
    
    private final BlogMapper blogMapper;
    private final CommentMapper commentMapper;

    public List<BlogResponseDTO> list(){
        System.out.println(" >>>> debug blog service list");

        return blogMapper.listRow();
    }

    public int write(BlogRequestDTO request){
        System.out.println(" >>>> debug blog service write");

        return blogMapper.insertRow(request);
    }

    @Transactional(readOnly = true)
    public BlogResponseDTO read(Integer id){
        System.out.println(" >>>> debug blog service read");

        BlogResponseDTO blog=  blogMapper  .readRow(id)
                    .orElseThrow(()-> new RuntimeException("Not Found"));

        
        List<CommentResponseDTO> comments = commentMapper.selectRow(blog.getId());
        blog.setComments(comments);

        return blog;
    }
}

business layer

package com.inspire.lgcns_mybatis.features.blog.repository;

import java.util.List;
import java.util.Optional;

import org.apache.ibatis.annotations.Mapper;

import com.inspire.lgcns_mybatis.features.blog.domain.dto.BlogRequestDTO;
import com.inspire.lgcns_mybatis.features.blog.domain.dto.BlogResponseDTO;

@Mapper
public interface BlogMapper {
    
    public List<BlogResponseDTO>        listRow();
    public int                          insertRow(BlogRequestDTO request);
    public Optional<BlogResponseDTO>    readRow(Integer id);
}

mapper

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.inspire.lgcns_mybatis.features.blog.repository.BlogMapper">


    <!-- listRow --> 

    <select id="listRow"
            resultType="BlogResponseDTO">
        SELECT ID,TITLE,CONTENT,EMAIL
        FROM Blog_tbl
    </select>

    <!-- insertRow --> 

    <insert id="insertRow"
            parameterType="BlogRequestDTO">
        INSERT INTO Blog_tbl
        VALUES (NEXTVAL(BLOG_SEG),#{title},#{content},#{email})
    </insert>

    <!-- readRow --> 

    <select id="readRow"
            parameterType="java.lang.Integer"
            resultType="BlogResponseDTO">

        SELECT ID,TITLE,CONTENT,EMAIL
        FROM Blog_tbl
        WHERE ID = #{id}
    </select></mapper>

2. 블로그 게시글 댓글 Mapping

readPage read 부분에 댓글도 함께 보여주기 위해 BlogService에 하단의 사진 부분이 필요하고 set함수를 사용하기 위해 RequestDTO 에 @Setter 추가한다

Comment Mapper에

selectRow가 들어가고

다음과 같이 DB와 연결한다.


3. 블로그 게시글 댓글 CRUD 틀 잡기


내가 쓴 댓글에 대해 수정과 삭제를 할 수 있도록 CRUD의 틀을 잡았다 !

package com.inspire.lgcns_mybatis.features.comment.ctrl;

import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.inspire.lgcns_mybatis.features.comment.domain.dto.CommentRequestDTO;
import com.inspire.lgcns_mybatis.features.comment.domain.dto.CommentResponseDTO;
import com.inspire.lgcns_mybatis.features.comment.repository.CommentMapper;

import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;

import java.util.HashMap;
import java.util.Map;

import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PatchMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;


@RestController
@RequestMapping("/blog/comment")
@RequiredArgsConstructor
@Tag(name = "Blog Comment API", description = "Blog 댓글 관련 API 명세서")
public class CommentController {
    private final CommentMapper commentMapper;

    //action : crud
    // user endPoint : http://serverip:port/blog/comment/XXXX
    @ApiResponses({
        @ApiResponse(responseCode = "201" , description = "댓글입력성공"),
        @ApiResponse(responseCode = "400" , description = "댓글입력실패")

    })
    @PostMapping("/write")
    public ResponseEntity<CommentResponseDTO> write(@RequestBody CommentRequestDTO request) {
        System.out.println(">>>> debug comment control write");
        System.out.println(">>> comment request : "+request);
        return null;
        
    }

    // 204 : 수정성공이고 응답본문이 없는 코드
    // 404 : 수정할 대상이 없거나 리소스가 존재하지않는 상태
    @ApiResponses({
        @ApiResponse(responseCode = "204" , description = "댓글수정성공"),
        @ApiResponse(responseCode = "404" , description = "댓글수정실패")

    })
    @PatchMapping("/update/{id}")
    public String update(   @PathVariable("id") Integer id,
                            @RequestParam("comment") String comment) {

        System.out.println(">>>> debug comment control update");
        System.out.println(">>> comment request pramas id : "+id);
        System.out.println(">>> comment request pramas comment : "+comment);
  
        Map<String, Object> map = new HashMap<>();

        map.put("id", id);
        map.put("comment", comment);
        return null;
    }


    @ApiResponses({
        @ApiResponse(responseCode = "204" , description = "삭제성공"),
        @ApiResponse(responseCode = "404" , description = "삭제실패")

    })

    @DeleteMapping("/delete/{id}")
    public String delete(@PathVariable("id") Integer id) {
        System.out.println(">>>> debug comment control delete");
        System.out.println(">>> comment request pramas id : "+id);
        
        return null;
    }
    

}

front에서도 엔드포인트 똑같이 수정하고 다음과 같은 틀을 잡아뒀다 !

다음 계획

서비스 단과 컨트롤러 단의 코드 작성 구분과 이해를 조금 더 해야할 거 같다 !

profile
IT 전공자의 발버둥

0개의 댓글