logoStephen's 기술블로그

포스트 검색

제목, 태그로 포스트를 검색해보세요

#블로그만들기_16 #댓글 쓰기/테이블 생성

#블로그만들기_16 #댓글 쓰기/테이블 생성
SpringWebApp
성훈 김
2024년 2월 15일
목차

1️⃣ 비즈니스 파악 - 화면 확인

💡
🔹 비즈니스를 파악해서 어떤 칼럼이 필요한지 파악한다. 🔹 글 작성자 id, 댓글 게시자 id, content, submit버튼, 🔹 insert할 정보는 body로 받는다.
notion image
 

🔹상세페이지 detail.mustache확인

💡
🔹 컨트롤러에서 처리할 action URL확인 → /reply/save
🔹 method확인 → post요청 🔹 name에 매핑된 키값을 잘 확인해야된다. boardId, comment 🔹 input태그 hidden은 눈에 보이지 않지만 id정보를 같이 보낸다.
🔹앱을 사용할 때는 데이터를 모두 담아서 보내는 것이 좋다.
notion image
 

2️⃣ 테이블 생성

🔹 reply 패키지 생성

notion image
 
 

🔹 Reply 클래스 생성 → 테이블

💡
🔹 관계를 보면 관계대수가 나온다. → 관계로 ForeignKey와 Driving table을 설정
🔹 Hibernate : ORM 프레임워크 → 공부하자 🔹 reply_tb는 DB에서 조회된 내용을 담기위한 그릇인 Entity이다.
Java
package shop.mtcoding.blog.reply;

import jakarta.persistence.*;
import lombok.Data;
import java.time.LocalDateTime;

@Table(name = "reply_tb")
@Data
@Entity
public class Reply {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    private String comment;
    private int userId; // user_tb의 PK -> user 외래키
    private int boardId; // board_tb의 PK -> board 외래키
    private LocalDateTime createdAT;
}
 
 
💡
서버를 재실행하고 콘솔에서 아래처럼 나오면 정상적으로 작동!
notion image
 
 

3️⃣ DTO만들기

💡
🔹 아까 view에서 확인했던 name에 매핑된 키값으로 WriteDTO를 만들어 준다. 🔹 BoardId는 페이지에 접속하면 자동으로 식별이 가능하게끔 view에서 input태그로 설정해줬으니 아래 두가지 값을 담을 그릇만 있으면 될 것 같다.
Java
package shop.mtcoding.blog.reply;
import lombok.Data;

public class ReplyRequest {
    
    @Data
    public static class WriteDTO{
        private String comment;
        private int boardId;
    }
 
 

🔹 DTO에 정보가 잘 담기는지 확인

💡
🔹 DTO를 제대로 확인하기 위해서는 간단한 컨트롤러가 구현이 되어야 한다. 🔹 아까 details.mustache에서 확인한 action URL 주소 “/reply/save” post요청을 받을 컨트롤러를 틀정도만 구현해서 DTO를 테스트 한다.
Java
@RequiredArgsConstructor
@Controller
public class ReplyController {
    
		// ReplyController를 간단히 구현해보자. 
    @PostMapping("reply/save")
    public String write (ReplyRequest.WriteDTO requestDTO){
        System.out.println(requestDTO); // 테스트 코드 - DTO에 정보가 잘 담기는지 확인
        
        return null;
    }
}
 
 
💡
블로그에 로그인하고 아무 게시글이나 들어가서 댓글을 달아보자.
notion image
 
 
💡
이 에러페이지를 받는 것은 당연하다 당황하지 말자. 중요한 체크 포인트는 🔹 URL주소가 잘 바뀌었는 지 확인 → /reply/save 🔹 그리고 콘솔을 확인해서 출력이 되었는지 확인한다.
notion image
 
 
💡
WriteDTO에 잘 전달되는지 확인완료!
notion image
 
 

4️⃣ 컨트롤러 구현

💡
이제 컨트롤러를 구현해보자! 🔹 현재 사용자가 세션유저, 즉 로그인된 사용자인지 확인해야된다. 🔹 ReplyRepository 클래스를 같은 패키지에 만들어 놓고 의존성 주입 설정한다. 🔹 반환값으로 “redirect:/board/”+ requestDTO.getBoardId(); 설정하여 댓글을 남기면 그 페이지에 머물러 있게 하는 UX를 만들 것이다.
Java
package shop.mtcoding.blog.reply;


import jakarta.servlet.http.HttpSession;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import shop.mtcoding.blog.user.User;

// 댓글 쓰기, 댓글 삭제, 댓글 목록보기
@RequiredArgsConstructor
@Controller
public class ReplyController {
    private final HttpSession session;
    private final ReplyRepository replyRepository;

    @PostMapping("reply/save")
    public String write(ReplyRequest.WriteDTO requestDTO) {
        System.out.println(requestDTO);

        // 현재 사용자가 세션유저인지 확인 - 로그인된 사람인지 확인
        User sessionUser = (User) session.getAttribute("sessionUser");
        if (sessionUser == null) {
            return "redirect:/loginForm";
        }
        // 유효성 검사 -- 이따가 필요하다면 더 구현하기!

        // 핵심 코드 - 아직 ReplyRepository를 만들지 않았으므로 에러날 것인데 괜찮다.
				// 그래도 ReplyRepository DI (의존성주입) 설정까지는 끝내놓자.
        replyRepository.save(requestDTO, sessionUser.getId());

        // 핵심 로직 실행후 그 페이지에 그대로 남아있게 하기 위한 코드
        return "redirect:/board/" + requestDTO.getBoardId();
    }
}
 
 

5️⃣ ReplyRepository 구현

💡
이제는 기계처럼 하게 되는 것 같다. 🔹 Repository / RequiredArgsContructor 🔹 save 메소드 위에 @Transactional 어노테이션을 단다. 🔹 쿼리는 createNavtiveQuery에 다 적지말고 String을 선언해서 세쌍따옴표 안에 넣으면 깔끔하다.
Java
package shop.mtcoding.blog.reply;

import jakarta.persistence.EntityManager;
import jakarta.persistence.Query;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;


@RequiredArgsConstructor
@Repository
public class ReplyRepository {
    private final EntityManager em;

    @Transactional
    public void save(ReplyRequest.WriteDTO requestDTO, int id) {
        String q = """
                insert into 
                    reply_tb (comment, board_id, user_id, created_at)
                values 
                    (?,?,?, now())
                """;
        Query query = em.createNativeQuery(q);
        query.setParameter(1,requestDTO.getComment());
        query.setParameter(2,requestDTO.getBoardId());
        query.setParameter(3, id);
        query.executeUpdate();
    }
}