Spring/실습 정리

Spring Boot 11강 - 상세 페이지 구현과 NotFound 예외 처리

코딩하는냥이 2025. 7. 2. 13:56
반응형

목록에서 제목을 클릭하면
각 질문의 상세 페이지로 이동하게 하려면,
컨트롤러에서 id를 받아 해당 데이터를 조회해 뷰에 전달해야 합니다.
또, 존재하지 않는 id로 접근 시 404 오류를 처리하는 방법도 같이 알아봅니다.


📌 예제 코드

QuestionController.java

package com.mysite.sbb.question;

import java.util.List;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import lombok.RequiredArgsConstructor;

@Controller
@RequiredArgsConstructor
@RequestMapping("/question")
public class QuestionController {

    private final QuestionService questionService;

    @GetMapping("/list")
    public String list(Model model) {
        List<Question> questionList = this.questionService.getList();
        model.addAttribute("questionList", questionList);
        return "question_list";
    }
    
    @GetMapping("/detail/{id}")
    public String detail(Model model, @PathVariable("id") Integer id) {
        Question question = this.questionService.getQuestion(id);
        model.addAttribute("question", question);
        return "question_detail";
    }
}

QuestionService.java

package com.mysite.sbb.question;

import java.util.List;
import java.util.Optional;
import org.springframework.stereotype.Service;
import com.mysite.sbb.DataNotFoundException;
import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor
public class QuestionService {
    private final QuestionRepository questionRepository;
    
    public List<Question> getList() {
        return this.questionRepository.findAll();
    }
    
    public Question getQuestion(Integer id) {
        Optional<Question> question = this.questionRepository.findById(id);
        if (question.isPresent())
            return question.get();
        else
            throw new DataNotFoundException("해당 게시물을 찾을 수 없습니다.");
    }
}

DataNotFoundException.java

package com.mysite.sbb;

import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.ResponseStatus;

@ResponseStatus(value = HttpStatus.NOT_FOUND, reason = "객체를 찾을 수 없습니다.")
public class DataNotFoundException extends RuntimeException {
    private static final long seriaVersionUID = 1L;
    public DataNotFoundException(String message) {
        super(message);
    }
}

💬 코드 설명

  • @RequestMapping("/question")
    컨트롤러 내의 모든 경로 앞에 /question이 붙습니다.
  • 상세 페이지 이동 (@GetMapping("/detail/{id}"))
    • {id} 부분에 각 질문의 고유 id가 들어갑니다.
    • 예) /question/detail/2
  • @PathVariable("id")
    URL 경로에서 전달된 id 값을 변수로 받아옵니다.
  • QuestionService의 getQuestion
    • questionRepository에서 id로 데이터 조회
    • 값이 없으면 커스텀 예외(DataNotFoundException) 발생
    • 값이 있으면 해당 Question 반환
  • DataNotFoundException
    • 존재하지 않는 데이터를 조회할 때
      404(Not Found) 에러와 함께 메시지를 반환합니다.
    • @ResponseStatus 어노테이션 덕분에
      컨트롤러에서 별도의 try-catch 없이 자동으로 404 처리가 됩니다.

💡포인트 정리

  • @PathVariable로 URL의 id 값을 받아 상세 데이터를 조회할 수 있다.
  • Optional 타입을 사용하면, 데이터 존재 여부를 유연하게 처리할 수 있다.
  • 커스텀 예외 + @ResponseStatus로
    404 에러 응답을 쉽고 명확하게 처리할 수 있다.

📌정리하자면, 상세 페이지 구현을 위해
id 값을 경로로 받아 데이터 조회와 예외 처리까지 실습했습니다.
이 방식은 대부분의 CRUD(상세 조회, 수정, 삭제)에서도
아주 기본적으로 활용되니 꼭 익혀두세요!