09009

[Spring Boot] 회원 + 게시판 연습 (2) - 로그인, 회원정보 수정, 로그아웃 본문

Back-End/Spring
[Spring Boot] 회원 + 게시판 연습 (2) - 로그인, 회원정보 수정, 로그아웃
09009 2024. 2. 4.

로그인

로그인 페이지

loginPage.html

<div class="container">
    <div class="row mt-5">
        <div class="col"></div>
        <div class="col-6 text-center">
            <div class="row mt-5 mb-2">
                <div class="col fs-3 fw-bold"> 로그인 </div>
            </div>


            <div class="row mt-3">
                <div class="col"></div>
                <div class="col-6">
                    <div class="row mb-2">
                        <div class="col">
                            <input type="text" class="form-control" name="email" id="memberEmail" placeholder="이메일">
                        </div>
                    </div>

                    <div class="row mb-2">
                        <div class="col">
                            <input type="password" class="form-control" name="password" id="memberPassword" placeholder="비밀번호">
                        </div>
                    </div>

                    <div class="row mt-3">
                        <div class="col d-grid">
                            <input type="button" class="btn btn-primary" value="로그인"
                            onclick="loginProcess()">
                        </div>
                    </div>
                </div>
                <div class="col"></div>
            </div>


        </div>
        <div class="col"></div>
    </div>
</div>
<script th:inline="javascript">

    const loginProcess = () => {
        const email = document.querySelector("#memberEmail");
        const password = document.querySelector("#memberPassword");

        if (email.value.trim() == "") {
            alert("아이디를 입력하세요.");
            email.focus();
            password.value = "";
            return;
        }
        if (password.value.trim() == "") {
            alert("비밀번호를 입력하세요.");
            password.focus();
            return;
        }
        $.ajax({
            type: "post",
            url: "/user/loginProcess",
            data: {
                "email" : email.value,
                "password" : password.value
            },
            success: function(res) {
                if (res == "ok") {
                    location.href = "/";
                } else {
                    password.value = "";
                    alert("아이디 또는 비밀번호가 일치하지 않습니다.");
                    password.focus();
                    return;
                }
            },
            error: function(err) {
                console.log("실패");
            }
        });
    }


</script>

 

MemberController

    // 로그인 포르세스
    @PostMapping("/loginProcess")
    public @ResponseBody String loginProcess(@ModelAttribute MemberDTO memberDTO, HttpSession session) {
        MemberDTO sessionUser = memberService.login(memberDTO);
        if (sessionUser != null) {
            session.setAttribute("memberDTO", sessionUser);
            return "ok";
        } else {
            return "no";
        }
    }

 

MemberService

   // 로그인
    public MemberDTO login(MemberDTO memberDTO) {
        Optional<MemberEntity> optionalMemberEntity = memberRepository.findByEmail(memberDTO.getEmail());
        if (optionalMemberEntity.isPresent()) {
            MemberEntity memberEntity = optionalMemberEntity.get();
            if (memberEntity.getPassword().equals(memberDTO.getPassword())) {
                return MemberDTO.toMemberDTO(memberEntity);
            } else {
                return null;
            }
        } else {
            return null;
        }
    }

 

MemberRepository

package com.yeongin.boardTest.repository;

import com.yeongin.boardTest.entity.MemberEntity;
import org.springframework.data.jpa.repository.JpaRepository;

import java.lang.reflect.Member;
import java.util.Optional;

public interface MemberRepository extends JpaRepository<MemberEntity, Long> {
    Optional<MemberEntity> findByEmail(String email);
}

 

 

main.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>main</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ" crossorigin="anonymous">
</head>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ENjdO4Dr2bkBIFxQpeoTz1HIcje39Wm4jDKdf19U8gI4ddQ3GYNS7NTKfAdVQSZe" crossorigin="anonymous"></script>
<body>
    <div class="container">
       <div class="row mt-5"></div>
        <div class="row mt-5">
            <div class="col"></div>
            <div class="col">

                <div class="row mt-2 fs-2 fw-bold">
                    <div class="col text-center">
                        Main Page
                    </div>
                </div>

                <div class="row mt-1 text-center" th:if="${session.memberDTO != null}">
                    <div class="col">
                        <div class="row">
                            <div class="col">
                                <p th:text="${session.memberDTO.name} + '님, 안녕하세요 !'"></p>
                            </div>
                        </div>
                        <div class="row mt-2">
                            <div class="col">
                                <a href="/user/myPage">마이페이지</a>
                            </div>
                        </div>
                    </div>
                </div>

                <div class="row mt-4">
                    <div class="col text-center">
                        <button class="btn btn-outline-primary" onclick="loginReq()">로그인</button>
                        <button class="btn btn-outline-primary" onclick="joinReq()">회원가입</button>
                    </div>
                </div>



            </div>
            <div class="col"></div>
        </div>
    </div>

<script th:inline="javascript">
    const loginReq = () => {
        location.href = "/user/loginPage";
    }

    const joinReq = () => {
        location.href = "/user/joinPage";
    }

</script>
</body>
</html>

 

로그인 후 화면


회원정보 수정

myPage.html

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>마이페이지</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ" crossorigin="anonymous">
    <style>
        .memberTh {
            width: 25%;
            background-color : #f4f4f4!important;
        }

    </style>
</head>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ENjdO4Dr2bkBIFxQpeoTz1HIcje39Wm4jDKdf19U8gI4ddQ3GYNS7NTKfAdVQSZe" crossorigin="anonymous"></script>
<body>
<div class="container">
    <div class="row mt-5">
        <div class="col"></div>
        <div class="col-6 text-center">
            <div class="row mt-5 mb-2">
                <div class="col fs-4 fw-bold"> 마이페이지 </div>
            </div>

            <div class="row mt-4">
                <div class="col"></div>
                <div class="col-8">
                    <form action="/user/updateUserProcess" method="post">
                        <div class="row">
                            <div class="col">
                                    <table class="table">
                                        <tr>
                                            <th class="memberTh">이메일</th>
                                            <td>
                                                <div class="row">
                                                    <div class="col text-start ms-2">
                                                        <input type="hidden" th:value="${memberInfo.id}" name="id">
                                                        <input type="text" class="form-control" th:value="${memberInfo.email}" readonly
                                                        name="email">
                                                    </div>
                                                </div>
                                            </td>
                                        </tr>
                                        <tr>
                                            <th class="memberTh">비밀번호</th>
                                            <td>
                                                <div class="row">
                                                    <div class="col text-start ms-2">
                                                        <input type="password" class="form-control" th:value="${memberInfo.password}" readonly
                                                        name="password">
                                                    </div>
                                                </div>
                                            </td>
                                        </tr>
                                        <tr>
                                            <th class="memberTh">이름</th>
                                            <td>
                                                <div class="row">
                                                    <div class="col text-start ms-2">
                                                        <input type="text" class="form-control" th:value="${memberInfo.name}"
                                                        name="name">
                                                    </div>
                                                </div>
                                            </td>
                                        </tr>
                                        <tr>
                                            <th class="memberTh">가입일</th>
                                            <td>
                                                <div class="row">
                                                    <div class="col text-start ms-2">
                                                        <p th:text="*{#temporals.format(memberInfo.regDate, 'yyyy-MM-dd HH:mm:ss')}"></p>
                                                    </div>
                                                </div>
                                            </td>
                                        </tr>
                                    </table>
                                </div>
                            </div>

                        <div class="row mt-2">
                            <div class="col">
                                <input type="submit" class="btn btn-primary" value="정보 수정하기">
                            </div>
                        </div>
                    </form>
                </div>
                <div class="col"></div>
            </div>

        </div>
        <div class="col"></div>
    </div>
</div>

<script th:inline="javascript">


</script>
</body>
</html>

 

MemberController

   // 마이페이지
    @GetMapping("/myPage")
    public String myPage(HttpSession session, Model model) {
        MemberDTO sessionUser = (MemberDTO) session.getAttribute("memberDTO");
        if (sessionUser != null) {
            MemberDTO memberDTO = memberService.getMemberInfo(sessionUser.getEmail());
            model.addAttribute("memberInfo", memberDTO);
            return "user/myPage";
        } else {
            return "redirect:/user/loginPage";
        }
    }

    // 회원정보 수정
    @PostMapping("/updateUserProcess")
    public String updateUserProcess(@ModelAttribute MemberDTO memberDTO) {
        memberService.updateUser(memberDTO);
        return "redirect:/user/myPage";
    }

 

MemberService

    // 회원정보 확인
    public MemberDTO getMemberInfo(String email) {
        Optional<MemberEntity> optionalMemberEntity = memberRepository.findByEmail(email);
        if (optionalMemberEntity.isPresent()) {
            return MemberDTO.toMemberDTO(optionalMemberEntity.get());
        } else {
            return null;
        }
    }

    // 회원정보 수정
    @Transactional
    public void updateUser(MemberDTO memberDTO) {
        memberRepository.updateUser(memberDTO.getName(), memberDTO.getId());
    }

 

MemberRepository

package com.yeongin.boardTest.repository;

import com.yeongin.boardTest.entity.MemberEntity;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import java.lang.reflect.Member;
import java.util.Optional;

public interface MemberRepository extends JpaRepository<MemberEntity, Long> {
    Optional<MemberEntity> findByEmail(String email);
    
    @Modifying
    @Query(value = "update MemberEntity m set m.name = :name where m.id = :id")
    void updateUser(@Param("name") String name, @Param("id") Long id);
}


로그아웃

HomeController

package com.yeongin.boardTest.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;

@Controller
public class HomeController {
    @GetMapping("/")
    public String main() {
        return "main";
    }

    @GetMapping("/main")
    public String main1() {
        return "main";
    }
}

 

main.html

       <div class="row mt-4">
            <div class="col text-center" th:if="${session.memberDTO != null}">
                <button class="btn btn-outline-primary" onclick="logoutReq()">로그아웃</button>
                <button class="btn btn-outline-primary" onclick="joinReq()">회원가입</button>
            </div>
            <div class="col text-center" th:if="${session.memberDTO == null}">
                <button class="btn btn-outline-primary" onclick="loginReq()">로그인</button>
                <button class="btn btn-outline-primary" onclick="joinReq()">회원가입</button>
            </div>
        </div>
<script th:inline="javascript">
    const loginReq = () => {
        location.href = "/user/loginPage";
    }

    const joinReq = () => {
        location.href = "/user/joinPage";
    }

    const logoutReq = () => {
        location.href = "/user/logout";
    }

</script>

 

MemberController

    // 로그아웃
    @GetMapping("logout")
    public String logout(HttpSession session) {
        session.invalidate();
        return "redirect:/main";
    }

 

 


UI 수정 - header 추가

common 폴더 생성 - header.html

(common / header.html)

<div th:fragment="header" class="row">
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>main</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ" crossorigin="anonymous">
</head>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ENjdO4Dr2bkBIFxQpeoTz1HIcje39Wm4jDKdf19U8gI4ddQ3GYNS7NTKfAdVQSZe" crossorigin="anonymous"></script>
<body>
<div class="container">
    <div th:fragment="header" class="row">
        <div class="col-7"></div>
        <div class="col">

            <div class="row mt-2 text-end" th:if="${session.memberDTO != null}">
                <div class="col">
                    <span th:text="${session.memberDTO.name} + '님, 안녕하세요 !'"></span>
                    <a href="/user/myPage" class="me-1">마이페이지</a>
                    <button class="btn btn-outline-primary" onclick="logoutReq()">로그아웃</button>
                    <button class="btn btn-outline-primary" onclick="joinReq()">회원가입</button>
                </div>
            </div>

            <div class="row mt-2 text-end" th:if="${session.memberDTO == null}">
                <div class="col"></div>
                <div class="col"></div>
                <div class="col" th:if="${session.memberDTO == null}">
                    <button class="btn btn-outline-primary" onclick="loginReq()">로그인</button>
                    <button class="btn btn-outline-primary" onclick="joinReq()">회원가입</button>
                </div>
            </div>

        </div>

        <script th:inline="javascript">
            const loginReq = () => {
                location.href = "/user/loginPage";
            }

            const joinReq = () => {
                location.href = "/user/joinPage";
            }

            const logoutReq = () => {
                location.href = "/user/logout";
            }

        </script>

    </div>
</div>


</body>
</html>

 

main.html

코드 추가

<div th:include="common/header :: header"></div>
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <title>main</title>
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-KK94CHFLLe+nY2dmCWGMq91rCGa5gtU4mk92HdvYe+M/SXH301p5ILy+dN9+nJOZ" crossorigin="anonymous">
</head>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ENjdO4Dr2bkBIFxQpeoTz1HIcje39Wm4jDKdf19U8gI4ddQ3GYNS7NTKfAdVQSZe" crossorigin="anonymous"></script>
<body>
    <div class="container">
        <div th:include="common/header :: header"></div>
        <div class="row mt-5">
            <div class="col"></div>
            <div class="col">

                <div class="row mt-2 fs-2 fw-bold">
                    <div class="col text-center">
                        Main Page
                    </div>
                </div>



            </div>
            <div class="col"></div>
        </div>
    </div>

<script th:inline="javascript">

</script>
</body>
</html>

 

 

현재까지 화면