6.1 링크와 리다이렉트란
보통 웹 게시판을 보면 처음에 <목록 페이지>가 뜹니다. 여기에서 [제목]을 클릭하면 해당 글의 <상세 페이지>로 이동하고, [글쓰기] 버튼을 클릭하면 . 새 글을 작성하는 <입력 페이지>로 이동합니다.
만약 <상세 페이지>에 있다면 [목록] 버튼을 클릭해 <목록 페이지>로 돌아갈 수 있습니다. <입력 페이지>에 있다면 새 글을 작성하지 않고 [목록] 버튼을 클릭해 돌아갈 수 있고, [전송하기] 버튼을 클릭해 작성한 글의 <상세 페이지>를 볼 수도 있습니다.
이 장에서는 이러한 게시판 내 페이지 이동을 구현해 봅시다. 앞에서 만든 /articles, 즉 목록 페이지에 링크와 리다이렉트라는 기능을 이용해 구현합니다.
링크(link)란 미리 정해 놓은 요청을 간편히 전송하는 기능으로, 보통 페이지 이동을 위해 사용합니다. HTML의 <a> 태그 혹은 <form> 태그로 작성하며, 클라이언트가 링크를 통해 어느 페이지로 이동하겠다고 요청하면 서버는 결과 페이지를 응답합니다.
그런데 어떤 경우에는 서버에서 결과 페이지를 응답하지 않고 재요청하라는 회신을 보내기도합니다. 예를 들어 어떤 업무를 보기 위해 a로 전화했다고 합시다. a는 업무의 일부만 처리하고 '나머지는 b에서 담당하니 b로 연락해 보시겠습니까?'라고 말했다면 이어서 b로 전화할 것입니다.
리다이렉트(redirect)란 바로 이런 경우를 말합니다. 클라이언트가 보낸 요청을 마친 후 계속해서 처리할 다음 요청 주소를 재지시하는 거죠. 이를 통해 분리된 기능을 하나의 연속적인 흐름으로 연결할 수 있습니다. 리다이랙트(재요청)를 지시받은 클라이언트는 해당 주소로 다시 요청을 보내고 서버는 이에 대한 결과를 응답합니다.
그럼 실습해 보며 링크와 리다이렉트가 페이지 간 이동에 어떻게 적용되는지 알아보겠습니다.
6.2 링크와 리다이렉트를 이용해 페이지 연결하기
기존에 만든 서비스의 문제점을 분석해 봅시다. 서버를 실행하고 localhost:8080/articles에 접속하면 빈 게시판이 나옵니다.
여기서 첫 번째 문제점은 새 글을 작성하기 위한 링크가 존재하지 않는다는 것입니다. 대신 직접 localhost:8080;articles/new 페이지에 접속해야만 새 글을 작성할 수 있습니다.
또한 입력 페이지에도 문제가 있습니다. 새 글을 작성한 후 서버에 전송하는 [Submit] 버튼은 있는데, 다시 목록으로 돌아가는 [뒤로 가기]가 없습니다. 전반적으로 게시판을 구성하는 페이지 간 연결 고리가 없어 불편합니다. 링크와 리다이렉트를 적용해 이를 해결해 보겠습니다.
6.2.1 새 글 작성 링크 만들기
localhost:8080/articles 페이지에 새 글을 작성할 수 있는 링크를 추가해 보겠습니다.
1. 목록 페이지의 뷰 파일인 src > main > resources > templates > articles > index.mustache 파일을 열고, </table> 아래에 <a> 태그를 추가합니다. <a> 태그의 href 속성 값으로 요청을 보낼 링크 주소인 "/artivles/new"를 작성하고 링크를 걸 텍스트에는 New Article을 작성합니다.
</table>
<a href="articles/new">New Article</a>
{{>layouts/footer}}
2. 잘 동작하는지 확인해 보겠습니다. 서버를 실행하고 localhost:8080/articles 페이지에 접속합니다. New Article이라는 링크가 생겼습니다. 클릭해 보면 새 글을 작성할 수 있는 입력 페이지로 넘어갑니다.
6.2.2 <입력 페이지> → <목록 페이지> 돌아가기
<입력 페이지>에서 다시 <목록 페이지>로 돌아가는 링크를 추가해 보겠습니다.
1. 입력 페이지의 뷰 파일인 new.mustache를 엽니다. 코드의 [Submit] 버튼 아래에 링크를 추가하겠습니다. 마찬가지로 <a> 태그의 href 속성 값으로 "/articles"를 넣어 <목록 페이지>로 갈 수 있도록 합니다.
<button type="submit" class="btn btn-primary">Submit</button>
<a href="/articles">Back</a>
</form>
2. 망치 아이콘을 클릭한 후 localhost:8080/articles/new 페이지를 새로 고침합니다. [Submit] 버튼 옆에 Back이라는 링크가 생겼습니다. 클릭하면 목록 페이지로 돌아갑니다.
6.2.3 <입력 페이지> → <상세 페이지> 이동하기
localhost:8080/articles/new 페이지에 접속해 제목은 가가가가, 내용은 1111을 입력하고 [Submit] 버튼을 클릭합니다. 게시판에 새 글을 작성했으므로 DB에 새 글이 저장되겠지만 새 글이 잘 등록됐는지 바로 알 수 없습니다. 해당 글이 잘 등록됐음을 알려 주는 상세 페이지가 나오면 좋겠지만 에러 페이지가 뜹니다.
이때 사용하는 개념이 라이다렉트입니다. 리다이렉트를 적용해 보겠습니다.
1. 입력 페이지에서 데이터를 전송하면 어디로 갔는지 기억나나요? ArticleController의 createArticle() 메서드에서 폼 데이터를 받았습니다. createArticle() 메서드는 포스트(Post) 방식으로 "/articles/create"라는 URL 요청을 받아 폼 데이터를 처리합니다.
코드의 마지막 줄을 보면 return 값이 공백 문자열("")입니다. 리다이렉트는 여기에 정의합니다.
@PostMapping("/articles/create")
public String createArticle(ArticleForm form){
(중략)
return ""; //리다이렉트를 작성할 위치
}
리다이렉트는 클라이언트의 요청을 받아 새로운 URL 주소로 재요청하라고 지시하는 것입니다. 형식은 다음과 같습니다.
형식) return "redirect:URL_주소";
예를 들어 return "redirect:/articles";라고 하면 목록 페이지로 재요청하라는 지시입니다. 그런데 등록한 새 글의 id가 1번이면 articles/1 페이지를, 2번이면 articles/2 페이지를, 3번이면 articles/3 페이지를 재요청하라고 지시하고 싶습니다. 어떻게 하면 될까요?
바로 + 연산자를 이용해 id에 따라 URL 주소가 달라지게 하면 됩니다. 이를 위해 saved 객체를 이용하겠습니다. return 문 위의 코드를 보면 article을 saved 객체에 저장했습니다. 따라서 saved.getId()를 호출하면 saved 객체의 id 값을 가져올 수 있습니다. 이렇게 가져온 id 값이 1이면 articles/1이 되고, 2면 articles/2, 3이면 articles/3이 되어 id에 따른 재요청 URL을 완성할 수 있습니다.
public String createArticle(ArticleForm form){
(중략)
//2. 리파지터리로 엔티티를 DB에 저장
Article saved = articleRepository.save(article);
(중략)
return "redirect:/articles/"+saved.getId();
}
그런데 작성하고 나니 getId() 메서드가 빨간색으로 표시됩니다. 해당 게터 메서드가 정의되지 않았다는 뜻이므로 게터 메서드를 만들어 줘야 합니다.
2. 마우스를 getId() 코드에 올리면 나오는 메뉴에서 Create method 'getId' in 'Article'을 클릭합니다. Article.java 파일이 열리는데, 다음과 같이 직접 게터 메서드를 만들 수 있고, 롬복을 사용할 수도 있습니다. 이 책에서는 롬복을 사용해 코드를 간소화 하겠습니다(방법2).
방법1
public class Article{
(중략)
public Long getId(){ //데이터 타입을 String -> Long 변경해야 함
return id;
}
}
방법2
@Entity
@Getter
public class Article {
(중략)
}
다시 ArticleController로 돌아오면 빨간색 에러 표시가 사라졌습니다.
3. 리다이렉트가 잘 되는지 확인해 보겠습니다. 서버를 재시작 하고 localhost:8080/articles/new에 접속합니다. 제목에 가가가가, 내용에 1111을 입력하고 [Submit] 버튼을 클릭합니다. 이제는 에러 페이지가 뜨지 않고 id가 1인 글에 상세 페이지가 잘 나옵니다. URL이 articles/1로 리다이렉트됐기 때문입니다.
4. 웹 브라우저의 뒤로 가기 아이콘을 이용해 한 번 더 제목에 나나나나, 내용에 2222를 입력한 후 [Submit] 버튼을 클릭해 보세요. articles/2 페이지로 넘어가는 것을 확인할 수 있습니다.
6.2.4 <상세 페이지> → <목록 페이지> 돌아가기
<상세 페이지>에서도 <목록 페이지>로 돌아갈 수 있게 링크를 추가해 보겠습니다.
1. 상세 페이지의 URL인 articles/{id}를 받는 컨트롤러의 메서드부터 찾아야겠죠. ArticleController에 가 보면 show()라는 메서드인 것을 알 수 있습니다. 이 메서드의 return 문을 보면 show라는 머스테치 파일, 즉 뷰 파일을 반환합니다. 따라서 show.mustache 파일에 링크를 추가하면 됩니다.
@GetMapping("/articles/{id}")
public String show(@PathVariable Long id, Model model) {
(중략)
return "articles/show"; //목록으로 돌아가기 링크를 넣을 뷰 파일 확인
}
2. show.mustache 파일을 엽니다. </table> 아래에 <a> 태그를 추가하고 href 속성 값으로 목록 페이지의 URL인 "/articles"를, 링크 텍스트로 Go to Article List를 작성합니다.
</table>
<a href="/articles">Go to Article List</a>
{{>layouts/footer}}
3. 망치 아이콘을 클릭해 빌드한 후 localhost:8080/articles/2 페이지에서 새로 고침하면 Go to Article List 링크가 생긴 것을 확인할 수 있습니다. 링크를 클릭하면 목록 페이지로 잘 돌아갑니다.
6.2.5 <목록 페이지> → <상세 페이지> 이동하기
현재 <목록 페이지>에는 데이터가 2개 있습니다. 여기에서 제목을 클릭하면 해당 글의 <상세 페이지>로 이동하도록 만들어 보겠습니다.
1. 목록 페이지의 뷰 파일인 index.mustache를 엽니다. 게시글의 제목은 <td>{{title}}</td>이므로 여기에다가 링크를 걸어 주면 됩니다. {{title}}을 <a> 태그로 감싸고 href 속성 값으로 "/ articles/{{id}}"를 입력합니다. 이렇게 하면 id가 1번인 게시글의 제목을 클릭하면 /articles/1 페이지로, 2번인 제목을 클릭하면 /articles/2 페이지로 이동합니다.
{{#articleList}}
<tr>
<th>{{id}}</th> <!-- 3. 속성 삭제, 가짜 데이터 넣기 -->
<td><a href="/articles/{{id}}">{{title}}</a></td>
<td>{{content}}</td>
</tr>
{{/articleList}}
2. 망치 아이콘을 클릭하고 localhost:8080/articles(목록 페이지)에서 새로 고침합니다. 제목에 링크가 걸려 있습니다. 가가가가를 클릭하면 1번 id의 상세 페이지로 이동합니다. 다시 목록 페이지로 돌아와서 나나나나도 클릭해 보세요. URL이 바뀌면서 2번 id의 상세 페이지로 이동합니다.
'스프링부트' 카테고리의 다른 글
8장 게시글 삭제하기: Delete (0) | 2025.01.23 |
---|---|
7장 게시글 수정하기: Update (0) | 2025.01.22 |
5장 게시글 읽기: Read (1) | 2025.01.20 |
4장 롬복과 리팩터링 (2) | 2025.01.15 |
3장 게시판 만들고 새 글 작성하기: Create (2) | 2025.01.15 |