Spring | SpringBoot

[Spring Boot] 상세페이지 만들기 / Optional / 예외처리

dbfl9911 2024. 8. 12. 17:21


 

 

- URL 파라미터

@GetMapping("/detail/{id}")
String detail() {
  return "detail.html";
}

 

 

- DB에서 글 뽑아서 html에 넣기

@GetMapping("/detail/{id}")
String detail() {
  var result = itemRepository.findById(1L);
  return "detail.html";
}

리포지토리.findById(1L) 이러면 id가 1인 행을 찾아온다는군요.

참고로 숫자를 Long 타입으로 만들고 싶으면 뒤에 L 적으면 됩니다.

이걸 변수에 저장해서 이제 html에 보내면 될거같은데 근데 var 자리에 타입은 뭘 넣어야하게요?

모르겠으면 변수에 마우스 올려보면 됩니다. 

Optional 이런 타입을 넣으라는군요.

 

 

 

- Optional 타입

Optional은 null일 수도 있고 아닐 수도 있다는 타입

DB에서 찾은걸 왜 이런 타입으로 변형해주냐면

가끔 DB에 id가 1인 행이 없을 수도 있는거 아닙니까?

그럴 땐 null 혹은 텅빈 값이 아마 이 변수에 들어올겁니다.

그래서 JPA 만든 사람이 null일수도 있으니까 조심해서 쓰라고 만들어준 타입

 

 

@GetMapping("/detail/{id}")
String detail() {

  Optional<Item> result = itemRepository.findById(1L);
  System.out.println(result.get());
  return "detail.html";
}

Optional 자료는 .get() 붙여야 안에 들어있는 자료가 나옵니다

물론 result 변수가 비어있을 수 있기 때문에 그냥 .get() 하고 그러면 에러나고 동작이 멈출 수 있습니다.

그래서 "만약에 result 안에 뭐가 있는 경우에만 .get() 해서 사용해라" 이렇게 쓰는게 안전하고 좋습니다

 

 

@GetMapping("/detail/{id}")
String detail() {

  Optional<Item> result = itemRepository.findById(id);
  if (result.isPresent()){
    System.out.println(result.get());
    return "detail.html";
  } else {
    return "~~~";
  }
}

Optional타입변수.isPresent() 라고 쓰면 result변수에 뭐가 들어있으면 true를 그 자리에 남겨줍니다.

그래서 위처럼 쓰면 확실하게 값이 들어있을 경우에만 .get() 해서 데이터를 안전하게 사용할 수 있습니다.

 

 


- 상세페이지 완성

/detail/1로 접속하면 1번 상품

/detail/2로 접속하면 2번 상품 가져오도록

 @GetMapping("/detail/{id}")
    String detail(@PathVariable Long id, Model model) {

        Optional<Item> result = itemRepository.findById(id);
        if (result.isPresent()){
            // 가져온 데이터 html에 넣기
            model.addAttribute("data", result.get());
            return "detail.html";
        } else {
            return "redirect:/list";
        }
    }

(@PathVariable 타입 URL파라미터명) 이라고 잘 작명하면

URL 파라미터 자리에 유저가 입력한 내용을 가져올 수 있습니다. (위에서 id를 가져올 수 있음 1번, 2번,,. 등)

 

 

- 링크 만들기

1번 상품에는 href="/detail/1"

2번 상품에는 href="/detail/2"

3번 상품에는 href="/detail/3" 이렇게 오도록

 

href="/detail/현재상품의id"

(list.html)
<div class="card" th:each="i : ${items}">
    <img src="https://placehold.co/300">
    <h4 th:text="${i.title}">바지</h4>
    <a th:href="@{/detail/{id}(id=${i.id})}">링크</a>
    <p th:text="${i.price + '원'}">7억</p>
</div>

href 안에 변수나 서버에서 보낸 데이터를 넣고 싶으면 이렇게 하면 된다

- 보통은 서버에서 보낸 변수를 넣고 싶으면 ${ } 안에 넣으면 되는데 근데 href안에는 @{ } 부터 시작하면 됩니다.

- 문자는 작은 따옴표 안에 넣어도 됩니다.

- 문자들을 합치고 싶으면 + 기호 쓰면 됩니다.

 

 

 

- 예외상황 처리

예를 들어 /detail/abc 이런 식으로 접속해보면

abc를 Long타입으로 변환할려고 하는데 그건 불가능해서 아마 서버에서 에러가 납니다.

에러가 나면 친절하게 기본 에러페이지로 안내해주는데 

유저들에게 그런걸 보여주는 것 보다는 따로 에러페이지를 만들어두는게 좋습니다. 

 

 

 

 

Thymeleaf를 설치해서 쓰는 경우에는 그냥 error.html 만들어두면 

서버에서 에러가 발생하면 그 페이지로 자동으로 이동됩니다.

이게 에러처리끝임

(error.html)

<div>에러페이지임</div>

<!--에러정보들-->
<p th:text="${status}"></p>
<p th:text="${error}"></p>
<p th:text="${path}"></p>
<p th:text="${message}"></p>
<p th:text="${exception}"></p>

 


 

* 이글은 아래 강의를 참고해 작성했습니다. 

https://codingapple.com/course/spring-boot-jpa/

 

쉽게 배우는 Spring Boot & JPA - 코딩애플 온라인 강좌

  Next.js는 프론트엔드부터 서버까지 만들 수 있는 React기반 프레임워크입니다. 이것만 사용해도 풀스택 웹개발이 가능합니다.    Next.js 사용시 서버사이드 렌더링이 쉽기 때문에  React, Vue만 사

codingapple.com