스터디/back

Part 2) 게시판 만들기 (3) - 리다이렉트 / update / delete / SQL 쿼리

ㅈㅣ니 2023. 12. 7.
반응형

6장 게시판 내 페이지 이동하기

리다이렉트(redirect)란?

클라이언트가 보낸 요청을 마친 후 계속해서 처리할 다음 요청 주소를 재지시하는 것.

분리된 기능을 하나의 연속적인 흐름으로 연결할 수 있다.

 

기존 서비스 문제점

1) 목록 페이지 : 새 글 작성 링크 X

2) 입력 페이지: 목록 페이지로 이동 X

 

새 글 작성 링크 만들어줌.

[ index.mustache ]

table 태그 밑에 a 태그 추가

</table>
<a href="/articles/new">New Article</a>
{{> layouts/footer}}

 

입력 페이지에 목록 페이지로 돌아가는 링크 추가

[ new.mustache ]
submit button 아래에 a 태그 추가

    <button type="submit" class="btn btn-primary">Submit</button>
    <a href="/articles">Back</a>

</form>
{{>layouts/footer}}

이렇게 back 링크가 생긴 것을 확인할 수 있다.

 

새로운 문제점 !!!

새 글을 작성하면 상세 페이지가 안나오고 에러 페이지가 뜨는 상황임!!

이럴 때는 리다이렉트를 이용하여, 방금 만든 글의 상세페이지가 뜨게 하면 된다.

[ ArticleController.java ]

return 값에 ' redirect:URL_주소 ' 를 입력해준다.

saved.getId() 는 id 값에 URL 주소가 달라지게 하기 위하여 위에 선언한 saved 객체를 saved.getId()로 호출해다.

이러면 articles/1 , aticles/2 ... 이런식으로 id 에 따른 URL 이 나온다.

+

getId() 메서드는 entity 패키지의 Atricle.java 에다가 게터 메서드를 만들어줘야한다.

간단하게 롬복으로 처리.

Article.java

이렇게 getter 메서드를 선언해주던가.

class 위에 롬복으로 @Getter 어노테이션을 선언해준다.

 

submit 버튼을 누르면 article/2로 리다이렉트 된다.

상세페이지에서 목록 페이지로 이동하려면

[ show.mustache ]

</table>
<a href="/articles">go to Article List</a>
{{> layouts/footer}}

이렇게 a 태그를 추가해준다.

 

목록 페이지 -> 상세 페이지 이동하기. ( 제목을 클릭하면 상세 페이지로 이동 )

[ index.mustache ]

<tr>
    <th>{{id}}</th>
    <td><a href="/articles/{{id}}">{{title}}</a></td>
    <td>{{content}}</td>
</tr>

title 부분을 a 태그로 감싸주면 끝!

 

1분 퀴즈

• (  ㉠  )(이)란 특정 페이지로 이동하는 HTML 태그로, 클릭 시 href 속성에 적힌 URL 주소로 요청을 보냅니다.

• (  ㉡  )(이)란 컨트롤러의 특정 메서드 수행을 종료한 후 계속해서 처리할 다음 요청 주소를 지시하는 것입니다. 이를 통해 분리된 기능을 연속적인 하나의 흐름으로 연결할 수 있습니다.

ㄱ : a 태그

ㄴ : redirect


7장 게시글 수정하기

1. 수정 페이지 만들고 기존 데이터 불러오기

[ show.mustache ]

 

{{#article}} {{/article}} 형식으로 범위를 지정하면 {{id}} 이렇게 입력하면 되지만,

범위가 지정되어있지 않을 때는 {{article.id}} 이렇게 해줘야한다.

[ ArticleController.java ]

edit() 메서드를 새로 추가해줬다.

@GetMapping("/articles/{id}/edit")  // URL 요청 접수
public String edit(@PathVariable Long id, Model model) {       // id 를 매개변수로 받아오기 & model 객체 받아오기
    // 수정할 데이터 가져오기
    Article articleEntity = articleRepository.findById(id).orElse(null);    // DB에 수정할 데이터 가져오기. id 없으면 null
    // 모델에 데이터 등록하기
    model.addAttribute("article", articleEntity);   // articleEntity를 article로 등록

    // 뷰 페이지 설정
    return "article/edit";
}

 

수정 페이지

[ edit.mustache ]

{{>layouts/header}}
{{#article}}
<form class="container" action="" method="post">
    <div class="mb-3">
        <label class="form-label">제목</label>
        <input type="text" class="form-control" name="title" value="{{title}}">       <!-- name = "title" DTO의 title 필드와 연결-->
    </div>
    <div class="mb-3">
        <label class="form-label">내용</label>
        <textarea class="form-control" rows="3" name="content">{{content}}</textarea>      <!-- DTO의 content 필드와 연결 -->
    </div>
    <button type="submit" class="btn btn-primary">Submit</button>
    <a href="/articles/{{id}}" class="btn btn-dark">Back</a>        <!-- 상세페이지로 다시 돌아가기 -->

</form>
{{/article}}
{{>layouts/footer}}

 

결과

 

 

[ 1분 퀴즈 ]

정답 : 1->3->4->2

 

2. 데이터를 수정해 DB에 반영한 후 결과를 볼 수 있게 <상세 페이지>로 리다이렉트 하기

 

전반적인 흐름은 다음과 같다.

흐름

 

클라이언트 - 서버 처리 기술

MVC 서버 역할을 분담해 처리하는 기법
JPA 서버와 DB 간 소통에 관여하는 기술
SQL DB 데이터를 관리하는 언어
HTTP 데이터를 주고받기 위한 통신 규약

 

MVC, JPA, SQL이 유기적으로 동작하는 것은 HTTP 의 요청과 응답으로 시작되고 끝이난다.

 

HTTP(HyperText Transfer Protocol)이란?

웹 서비스에서 사용하는 프로토콜이다. 클라이언트의 다양한 요청을 메서드를 통해 서버로 보내는 역할을 한다.

메서드로는 POST, GET, PATCH(PUT), DELETE 가  있다.

POST 데이터 생성 요청
GET 데이터 조회 요청
PATCH(PUT) 데이터 수정 요청
DELETE 데이터 삭제 요청

 

더미 데이터 (dummy data) 생성

[ data.sql ]

INSERT INTO article(id, title, content) VALUES (1, '가가가가', '1111');
INSERT INTO article(id, title, content) VALUES (1, '나나나나', '2222');
INSERT INTO article(id, title, content) VALUES (1, '다다다다', '3333');

 

더미 데이터가 들어간 것을 확인 할 수 있다.

 

이제 edit 페이지를 수정해 줄 것이다. 아까 form 태그에 action부분을 비워두었는데, 그 부분을 수정해줄 것이다.

method 를 POST 로 한 이유는 form 태그가 PATCH 메서드를 지원하지 않기 때문이다.

그리고 서버에서 id가 몇 번인지 알아야 하기 때문에 input 태그로 id도 추가해줬다.

 

ArticleController.java에 update 메서드 추가하기.

[ ArticleController.java ]

@PostMapping("/articles/update")    // URL 요청 접수
public String update(ArticleForm form) {    // 매개변수로 DTO 받아오기
    log.info(form.toString());
    // 1. DTO를 엔티티로 변환
    Article articleEntity = form.toEntity();    //DTO(form)를 엔티티(articleEntity)로 변환하기
    // 2. 엔티티를 DB에 저장
    // 2-1  DB에서 기존 데이터 가져오기
    Article target = articleRepository.findById(articleEntity.getId()).orElse(null);
    // 2-2 기존 데이터 값 갱신
    if (target != null) {
        articleRepository.save(articleEntity);  // target이 null 이 아니면 엔티티를 DB에 저장
    }

    // 3. 수정 결과 페이지로 리다이렉트하기
    return "redirect:/articles/" + articleEntity.getId();
}

 

[ Article.java ]

+ DTO 에 id 필드 추가 및 생성자 수정

 

수정 시도

 

원래 데이터

 

수정 후

1분 퀴즈

[ 정답 ]

ㄱ: POST

ㄴ: 데이터 조회 ( Read )

ㄷ: UPDATE

 


8장 게시글 삭제하기 DELETE

글 삭제 순서

1. 클라이언트가 HTTP 메서드로 특정 게시글의 삭제 요청

2. 컨트롤러는 리포지터리를 통해 DB 데이터를 찾아 삭제 (기존 데이터가 있는 경우)

3. 삭제 완료 후 클라이언트를 결과 페이지로 리다이렉트

 

+ 결과 페이지에서 삭제 완료 메시지도 띄워 줄 예정.

이를 위한 클래스는 RedirectAttributes 이다.

RedirectAttributes 객체의 addFlashAttribute() 메서드는 리다이렉트된 페이지에서 사용할 일회성 데이터를 등록할 수 있음

 

1. Delete 버튼 추가

[ show.mustache ]

<a href="/articles/{{article.id}}/delete" class="btn btn-danger">DELETE</a>

추가된 걸 볼 수 있다.

2. Delete 요청을 받아서 삭제하기

HTTP 메서드를 통해서 삭제를 하려한다. 

앞서 POST, GET, PATCH, DELETE 메서드가 있다고 했는데,

HTML 에서는 POST 와 GET 을 제외한 다른 메서드는 제공하지 않기 때문에 GET 방식으로 삭제 요청을 받아서

처리할 것이다.

 

ArticleController.java에 delete 메서드 추가하기.

[ ArticleController.java ]

@GetMapping("/articles/{id}/delete")    // URL 요청 접수
public String delete(@PathVariable Long id) {       // id를 매개변수로 가져오기
    log.info("삭제 요청이 들어왔습니다.");
    // 1. 삭제할 대상 가져오기
    Article target = articleRepository.findById(id).orElse(null);   // 데이터 찾기
    // 2. 대상 엔티티 삭제하기
    if (target != null) {
        articleRepository.delete(target);       // delete() 메서드로 대상 삭제하기
    }
    // 3. 결과 페이지로 리다이렉트하기
    return "redirect:/articles";
}

 

위와 같이 delete 버튼을 누르면 삭제되는 것을 확인할 수 있다.

 

3. 삭제 완료 메시지 남기기

 

앞서 작성한 ArticleController.java 부분을 수정

@GetMapping("/articles/{id}/delete")    // URL 요청 접수
public String delete(@PathVariable Long id, RedirectAttributes rttr) {       // id를 매개변수로 가져오기
    log.info("삭제 요청이 들어왔습니다.");
    // 1. 삭제할 대상 가져오기
    Article target = articleRepository.findById(id).orElse(null);   // 데이터 찾기
    // 2. 대상 엔티티 삭제하기
    if (target != null) {
        articleRepository.delete(target);       // delete() 메서드로 대상 삭제하기
        rttr.addFlashAttribute("msg", "삭제완료!!");
    }
    // 3. 결과 페이지로 리다이렉트하기
    return "redirect:/articles";
}

[ header.mustache ] 에 메시지 창 추가

</nav>

{{#msg}}
    <div class="alert alert-primary alert-dismissible">
        {{msg}}
        <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
    </div>
{{/msg}}

 

결과


9장 CRUD와 SQL 쿼리 종합

서버에서 CRUD를 요청하면 JPA의 리파지토리가 DB에 해당 요청을 전달한다.

이때, DB는 SQL로 쿼리를 작성해 테이블 속 데이터를 관리한다.

쿼리(Query)란?

DB에 정보를 요청하는 구문이다. ( INSERT, SELECT, UPDATE, DELETE)

 

DB의 SQL 쿼리를 분석하기 전에 JPA 로깅 설정 먼저 하겠다.

로깅(Logging)이란 시스템이 작동할 대 당시의 상태와 작동 정보를 기록하는 것을 말한다.

설정은 application.properties 파일에서....

 

로깅 레벨

 TRACE(레벨1): DEBUG 레벨보다 더 상세한 정보

 DEBUG(레벨2): 응용 프로그램을 디버깅하는 데 필요한 세부 정보

 INFO(레벨3): 응용 프로그램의 순조로운 진행 정보

 WARN(레벨4): 잠재적으로 유해한 상황 정보

 ERROR(레벨5): 응용 프로그램이 수행할 수 있는 정도의 오류 정보

 FATAL(레벨6): 응용 프로그램이 중단될 만한 심각한 오류 정보

 OFF(레벨7): 로깅 기능 해제

 

현재 나는 레벨 2로 설정.

[ application.properties ]

# JPA 로깅 설정
# 디버그 레벨로 쿼리 출력
logging.level.org.hibernate.SQL=DEBUG
# 쿼리 줄바꿈하기
spring.jpa.properties.hibernate.format_sql=true
# 매개변수 값 보여 주기
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE

# DB URL 설정
# 유니크 URL 생성하지 않기
spring.datasource.generate-unique-name=false
# 고정 URL 설정하기
spring.datasource.url=jdbc:h2:mem:testdb

 

URL 을 고정시켜줘서 이제 매번 번거롭게 바꿀 일이 없어졌다!!!!

 

id 자동 생성 (GeneratedValue)

기존에 작성한  data.sql 에 id 속성이랑 id 속성 값 지우기!!

커피 테이블 만들기

 

[ 1분 퀴즈 ]

2. 앞서 실습한 coffee 테이블에서 가격이 5,100원인 커피를 찾으려고 합니다. 이를 위한 쿼리를 작성해 보세요.

select * from coffee

where price = 5100;

반응형

'스터디 > back' 카테고리의 다른 글

12장 ~ 14장  (0) 2023.12.21
Part 3) REST API와 JSON | HTTP와 REST 컨트롤러  (0) 2023.12.14
Part 2) 게시판 만들기(2)  (1) 2023.11.23
Part 2) 게시판 만들기(1)  (0) 2023.11.21
Part1 ) 스프링 부트 개요  (0) 2023.11.15