Spring Boot 시작하기 (5)

최민영·2024년 9월 13일

IntelliJ

목록 보기
12/30

회원 정보와 관련된 기능을 수행하는 페이지를 구성할 예정

-> "/member/(id번호)" 주소로 회원 정보 조회
-> "/member/delete/(id번호)" 주소로 회원 정보 삭제
-> 회원 수정 및 로그아웃 구현

  • query string 방식 : 주소 체계에서 '?'를 사용
    ex) /member?id=1
    ** rest api 방식 : 주소만으로 자원 식별
    ex) /member/1

<-- 회원 조회 -->

1) MemberController에 "/member/{id}" Get 설정

@GetMapping("/member/{id}")
    public String findById(@PathVariable Long id, Model model) {
        MemberDTO memberDTO = memberService.findById(id);
        model.addAttribute("member", memberDTO);
        return "detail";
    }

-> @PathVariable을 통해 @GetMapping으로 받은 {id} 정보를 사용 (주소 경로 상에 있는 변수를 사용할 때 주로 사용)
-> id에 해당하는 회원 정보를 DB에서 가져와서 화면에 띄워야 하기 때문에 Model 사용
-> list를 get 할 때는 여러명이니까 List 형식으로 만들어주었지만 회원 정보는 한 명을 조회하는 것이기 때문에 MemberDTO로 가져오면 됨

2) MemberService에 findById(id) 함수 구성

public MemberDTO findById(Long id) {
        Optional<MemberEntity> optionalMemberEntity = memberRepository.findById(id);
        if(optionalMemberEntity.isPresent()) {
            return MemberDTO.toMemberDTO(optionalMemberEntity.get());
        } else {
            return null;
        }
    }

-> Optional 객체를 .get()으로 한 번 벗겨내야 eneity 객체가 보이고, 이 entity 객체를 dto로 변환해줌
-> memberRepository에 findById(id) 함수는 기존에 존재

3) detail.html 구성하기

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">

<head>
    <meta charset="UTF-8">
    <title>detail</title>
</head>
<body>
<table>
    <tr>
        <th>id</th>
        <th>email</th>
        <th>password</th>
        <th>name</th>
    </tr>
    <tr>
        <td th:text="${member.id}"></td>
        <td th:text="${member.memberEmail}"></td>
        <td th:text="${member.memberPassword}"></td>
        <td th:text="${member.memberName}"></td>
    </tr>
</table>
</body>
</html>

출력할 객체가 한 개이므로 th:each로 반복할 필요 없음

<-- 회원 수정 -->

4) main.html에서 "/member/update" 주소로 회원 정보 수정 버튼 생성

<a href="/member/update">내 정보 수정</a>

-> 회원 정보는 로그인을 한 상태에서 수행할 수 있어야 하므로 main.html에서 진행

5) MemberController에 "/member/update" GET

@GetMapping("/member/update")
    public String updateForm(HttpSession session, Model model) {
        String myEmail = (String) session.getAttribute("loginEmail");
        MemberDTO memberDTO = memberService.updateForm(myEmail);
        model.addAttribute("updateMember", memberDTO);
        return "update";
    }

-> session을 저장할 때는 setAttribute (login 시), 가져올 때는 getAttribute
-> 회원 정보를 수정하기 위해 로그인할 때 세션에 저장한 이메일 정보를 가져옴
-> 세션에 있는 이메일 정보를 String에 바로 담으려고 하면 session.getAttribute로 반환되는 Object 크기가 더 크므로 type casting 오류가 발생 => (String)으로 강제 형변환

6) MemberService에 updateForm(myEmail) 함수 구성

public MemberDTO updateForm(String myEmail) {
        Optional<MemberEntity> optionalMemberEntity = memberRepository.findByMemberEmail(myEmail);
        if(optionalMemberEntity.isPresent()) {
            return MemberDTO.toMemberDTO(optionalMemberEntity.get());
        } else {
            return null;
        }
    }

login할 때 사용했던 MemberRepository의 findByMemberEmail(email) 함수를 사용

7) update.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">

<head>
    <meta charset="UTF-8">
    <title>update</title>
</head>
<body>
<form action="/member/update" method="post">
    <input type="hidden" th:value="${updateMember.id}" name="id"><br>
    이메일: <input type="text" th:value="${updateMember.memberEmail}" name="memberEmail" readonly> <br>
    비밀번호: <input type="text" th:value="${updateMember.memberPassword}" name="memberPassword"> <br>
    이름: <input type="text" th:value="${updateMember.memberName}" name="memberName"> <br>
    <input type="submit" value="정보수정">
</form>
</body>
</html>

-> 회원가입을 했던 save.html의 경우 사용자가 입력하는 값을 저장하면 되는 것이었기 때문에 아래와 같이 name="memberEmail"로 지정해주기만 하면 됐었다

이메일 : <input type="text" name="memberEmail"> <br>

-> update.html에서는 사용자가 입력한 내용을 기존 DB에 업데이트 해야하기 때문에 thymeleaf를 사용한다 => th:value 사용

이메일: <input type="text" th:value="${updateMember.memberEmail}" name="memberEmail" readonly> <br>

-> member의 id의 경우 굳이 보여줄 필요가 없기 때문에 type="hidden"으로 설장
-> 이메일은 변경이 불가하고 읽기만 가능하게 하려하므로 readonly 옵션을 넣어준다

8) MemberController에서 "/member/update" POST

@PostMapping("/member/update")
    public String update(@ModelAttribute MemberDTO memberDTO) {
        memberService.update(memberDTO);
        return "redirect:/member/"+memberDTO.getId();
    }

-> controller에 담긴 메소드의 처리가 끝난 후 다시 다른 controller에 담긴 메소드의 주소를 요청하기 위해서 redirect 사용
-> "/member/{id}" 형태로 넘겨주기 위해 memberDTO.getId() 사용

9) MemberService에서 update 함수 구성

public void update(MemberDTO memberDTO) {
        memberRepository.save(MemberEntity.toUpdateMemberEntity(memberDTO));
    }

-> memberRepository에는 update 함수는 없고 회원가입할 때 썼던 save 함수를 다시 사용한다
-> memberRepository의 save 함수는 DB에 넘겨받는 id가 없으면 insert 쿼리를 수행하고 id가 있으면 update 쿼리를 자동으로 수행한다 => id가 있는 부분을 수정하는 것이므로 MemberEntity에 toUpdateMemberEntity 구성이 필요하다

10) MemberEntity에 toUpdateMemberEntity 구성

public static MemberEntity toUpdateMemberEntity(MemberDTO memberDTO) {
        MemberEntity memberEntity = new MemberEntity();
        memberEntity.setId(memberDTO.getId());
        memberEntity.setMemberEmail(memberDTO.getMemberEmail());
        memberEntity.setMemberPassword(memberDTO.getMemberPassword());
        memberEntity.setMemberName(memberDTO.getMemberName());
        return memberEntity;
    }

기존의 toMemberEntity와 유사하지만 setId 필드가 생겨났다

정보 수정 후 보이는 회원 정보
(아이디는 readonly이기 때문에 수정이 불가)

<-- 회원 삭제 -->

11) MemberController에 "/member/delete/{id}" GET

@GetMapping("/member/delete/{id}")
    public String deleteById(@PathVariable Long id) {
        memberService.deleteById(id);
        return "redirect:/member/";
    }

삭제 후 controller 내의 "/member/" 주소 redirect

12) MemberService에 deleteById(id) 함수 구성

public void deleteById(Long id) {
        memberRepository.deleteById(id);
    }

memberRepository에 deleteById 함수 존재
회원 목록에서 '삭제' 버튼을 누르면 DB에 있던 회원 정보가 삭제된다

<-- 로그아웃 -->

13) main.html에 로그아웃 버튼 생성

<a href="/member/logout">로그아웃</a>

14) MemberController에서 "/member/logout" GET

@GetMapping("/member/logout")
    public String logout(HttpSession session) {
        session.invalidate();
        return "index";
    }

Httpsession을 해제하기 위해 .invalidate() 함수 사용
로그아웃 이후 index.html로 돌아가기 (처음 화면)

회원가입 / 로그인 / 로그아웃 / 회원 정보 조회.수정.삭제 기능을 수행할 수 있는 기본적인 코드를 따라 작성하며 java 기반의 spring으로 웹 페이지를 어떻게 구현하면 될지에 대한 감을 익혀봤다
회원 정보와 관련된 기능은 보안을 신경써서 보다 멋지게 만들어야 하겠지만 일단은 spring의 첫 시작으로써 흐름에 대한 이해가 우선이라고 생각했고 며칠간 열심히 해보았다
이후로는 게시판 만들기를 따라하며 응용할 수 있는 기능들을 좀 더 살펴볼 예정이다

0개의 댓글