
1. BoardService 에 detail() 만들기
- board와 isOwner를 응답해야하나 method는 하나밖에 응답할 수 없음
- DTO를 만들어서 하나의 덩어리로 만들어서 줘야 함
package shop.mtcoding.blog.board;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import shop.mtcoding.blog._core.errors.exception.Exception403;
import shop.mtcoding.blog._core.errors.exception.Exception404;
import shop.mtcoding.blog.user.User;
import java.util.List;
@RequiredArgsConstructor
@Service
public class BoardService {
private final BoardJPARepository boardJPARepository;
// board와 isOwner를 응답해야하나 method는 하나밖에 응답할 수 없음 -> 하나의 덩어리로 만들어서 줘야 함
public Board detail(Integer boardId, User sessionUser) {
Board board = boardJPARepository.findByIdJoinUser(boardId)
.orElseThrow(() -> new Exception404("게시글을 찾을 수 없습니다"));
// 로그인을 하고, 게시글의 주인이면 isOwner가 true가 된다.
boolean isOwner = false;
if(sessionUser != null){
if(sessionUser.getId() == board.getUser().getId()){
isOwner = true;
}
}
return board;
}
public List<Board> findAll() {
Sort sort = Sort.by(Sort.Direction.DESC,"id");
return boardJPARepository.findAll(sort);
}
@Transactional
public void delete(int boardId, Integer sessionUserId) {
Board board = boardJPARepository.findById(boardId)
.orElseThrow(() -> new Exception404("게시글을 찾을 수 없습니다"));
if (sessionUserId != board.getUser().getId()) {
throw new Exception403("게시글을 삭제할 권한이 없습니다");
}
boardJPARepository.deleteById(boardId);
}
public void update(int boardId, int sessionUserId, BoardRequest.UpdateDTO reqDTO) {
Board board = boardJPARepository.findById(boardId)
.orElseThrow(() -> new Exception404("게시글을 찾을 수 없습니다"));
board.setTitle(reqDTO.getTitle());
board.setContent(reqDTO.getContent());
}
public Board updateForm (int boardId, int sessionUserId) {
// 1. 조회 및 예외처리
Board board = boardJPARepository.findById(boardId)
.orElseThrow(() -> new Exception404("게시글을 찾을 수 없습니다"));
// 2. 권한 처리
if (sessionUserId != board.getUser().getId()) {
throw new Exception403("게시글 수정페이지로 이동할 권한이 없습니다");
}
return board;
}
@Transactional
public void save(BoardRequest.SaveDTO reqDTO, User sessionUser) {
boardJPARepository.save(reqDTO.toEntity(sessionUser));
}
}
2. BoardResponse 만들어서 DetailDTO 만들기
- UserDTO 만들어서 isOwner 추가하기
- isOwner에 대한 if 분기하기
package shop.mtcoding.blog.board;
import lombok.Data;
import shop.mtcoding.blog.user.User;
public class BoardResponse {
@Data
public static class DetailDTO {
private Integer id;
private String title;
private String content;
private UserDTO user;
private Boolean isOwner;
public DetailDTO(Board board, User sessionUser) {
this.id = board.getId();
this.title = board.getTitle();
this.content = board.getContent();
this.user = new UserDTO(board.getUser());
this.isOwner = false;
if(sessionUser != null){
if(sessionUser.getId() == board.getUser().getId()){
isOwner = true;
}
}
}
@Data
public class UserDTO {
private int id;
private String username;
public UserDTO(User user) {
this.id = user.getId();
this.username = user.getUsername();
}
}
}
}
3. DTO없이 isOwner 만들기
- Board 에 @Transient 걸어서 isOwner만들기 → 테이블에 생성이 안 됨
- JsonIncludeProperties({","}) : 해당 속성 제외하기
- @JsonIgnore : 표시 안하기
- SSL은 화면에 이상한 데이터가 날아갈 일이 없음

package shop.mtcoding.blog.board;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIncludeProperties;
import jakarta.persistence.*;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.CreationTimestamp;
import shop.mtcoding.blog.user.User;
import shop.mtcoding.blog._core.utils.MyDateUtil;
import java.sql.Timestamp;
@NoArgsConstructor
@Data // 변경되는 데이터에만 setter가 필요함
@Table(name = "board_tb")
@Entity
public class Board {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
private String title;
private String content;
// private String username;
// username은 user_tb에도 있기에 외래키로 연관관계 맺어야 함
// @JoinColumn(name = "user_id") 직접 지정할 때
@JsonIncludeProperties({"password, email, createdAt"}) // 해당 속성 제외하기
@ManyToOne(fetch = FetchType.LAZY) // ORM 할 것이기에 user 객체 필요
private User user; // DB에 컬럼명 : user_id (변수명_PK키)
@JsonIgnore // 표시 안하기
@CreationTimestamp // PC로 인해 DB에 INSERT될 때 날짜 주입
private Timestamp createdAt;
@Transient // 테이블 생성이 안됨
private boolean isOwner;
public void update(){
}
@Builder
public Board(Integer id, String title, String content, User user, Timestamp createdAt) {
this.id = id;
this.title = title;
this.content = content;
this.user = user;
this.createdAt = createdAt;
}
public String getBoardDate(){
return MyDateUtil.timestampFormat(createdAt);
}
}

4. BoardService 에 detail 수정하기
package shop.mtcoding.blog.board;
import lombok.RequiredArgsConstructor;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import shop.mtcoding.blog._core.errors.exception.Exception403;
import shop.mtcoding.blog._core.errors.exception.Exception404;
import shop.mtcoding.blog.user.User;
import java.util.List;
@RequiredArgsConstructor
@Service
public class BoardService {
private final BoardJPARepository boardJPARepository;
// board와 isOwner를 응답해야하나 method는 하나밖에 응답할 수 없음 -> 하나의 덩어리로 만들어서 줘야 함
public Board detail(int boardId, User sessionUser) {
Board board = boardJPARepository.findByIdJoinUser(boardId)
.orElseThrow(() -> new Exception404("게시글을 찾을 수 없습니다"));
boolean isOwner = false;
if(sessionUser != null){
if(sessionUser.getId() == board.getUser().getId()){
isOwner = true;
}
}
board.setOwner(isOwner);
return board;
}
public List<Board> findAll() {
Sort sort = Sort.by(Sort.Direction.DESC, "id");
return boardJPARepository.findAll(sort);
}
@Transactional
public void delete(int boardId, Integer sessionUserId) {
Board board = boardJPARepository.findById(boardId)
.orElseThrow(() -> new Exception404("게시글을 찾을 수 없습니다"));
if (sessionUserId != board.getUser().getId()) {
throw new Exception403("게시글을 삭제할 권한이 없습니다");
}
boardJPARepository.deleteById(boardId);
}
public void update(int boardId, int sessionUserId, BoardRequest.UpdateDTO reqDTO) {
Board board = boardJPARepository.findById(boardId)
.orElseThrow(() -> new Exception404("게시글을 찾을 수 없습니다"));
board.setTitle(reqDTO.getTitle());
board.setContent(reqDTO.getContent());
}
public Board updateForm(int boardId, int sessionUserId) {
// 1. 조회 및 예외처리
Board board = boardJPARepository.findById(boardId)
.orElseThrow(() -> new Exception404("게시글을 찾을 수 없습니다"));
// 2. 권한 처리
if (sessionUserId != board.getUser().getId()) {
throw new Exception403("게시글 수정페이지로 이동할 권한이 없습니다");
}
return board;
}
@Transactional
public void save(BoardRequest.SaveDTO reqDTO, User sessionUser) {
boardJPARepository.save(reqDTO.toEntity(sessionUser));
}
}
5. BoardController 에 detail 수정하기
package shop.mtcoding.blog.board;
import ch.qos.logback.core.model.Model;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpSession;
import jakarta.transaction.Transactional;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import shop.mtcoding.blog._core.errors.exception.Exception403;
import shop.mtcoding.blog._core.errors.exception.Exception404;
import shop.mtcoding.blog.user.User;
import java.lang.annotation.Native;
import java.util.List;
@RequiredArgsConstructor
@Controller
public class BoardController {
private final BoardRepository boardRepository;
private final HttpSession session;
private final BoardService boardService;
// @Transactional 트랜잭션 시간이 너무 길어져서 service에 넣어야함
@PostMapping("/board/{id}/update")
public String update(@PathVariable Integer id, BoardRequest.UpdateDTO reqDTO) {
User sessionUser = (User) session.getAttribute("sessionUser");
boardService.update(id, sessionUser.getId(), reqDTO);
return "redirect:/board/" + id;
}
@GetMapping("/board/{id}/update-form")
public String updateForm(@PathVariable(name = "id") Integer id, HttpServletRequest request) {
User sessionUser = (User) session.getAttribute("sessionUser");
Board board = boardService.updateForm(id, sessionUser.getId());
request.setAttribute("board", board);
return "/board/update-form"; // 서버가 내부적으로 index를 요청 - 외부에서는 다이렉트 접근이 안됨
}
@PostMapping("/board/{id}/delete")
public String delete(@PathVariable Integer id) {
User sessionUser = (User) session.getAttribute("sessionUser");
boardService.delete(id, sessionUser.getId());
return "redirect:/";
}
@GetMapping("/")
public String index(HttpServletRequest request) {
List<Board> boardList = boardService.findAll();
request.setAttribute("boardList", boardList);
return "index"; // 서버가 내부적으로 index를 요청 - 외부에서는 다이렉트 접근이 안됨
}
@PostMapping("/board/save")
public String save(BoardRequest.SaveDTO reqDTO) {
User sessionUser = (User) session.getAttribute("sessionUser");
boardService.save(reqDTO, sessionUser);
return "redirect:/";
}
@GetMapping("/board/save-form")
public String saveForm() {
return "board/save-form";
}
@GetMapping("/board/{id}")
public String detail(@PathVariable Integer id, HttpServletRequest request) {
User sessionUser = (User) session.getAttribute("sessionUser");
Board board = boardService.detail(id, sessionUser);
request.setAttribute("board", board);
return "board/detail";
}
}

Share article