티스토리 뷰

웹 개발/SpringBoot

[Spring Boot] 이메일 찾기

스톤승현 2022. 11. 14. 16:43

이메일 찾기는 이름과 연락처에 해당하는 사용자 입력 값에 대해 일치하는 사용자인 레코드가 있을 경우 해당 레코드의 이메일을 알려주고, 없다면 입력한 정보와 일치하는 사용자가 없다는 응답을 돌려주는 절차이다. 

 

로직 : 전달 받은 이름(name)과 연락처(contact)에 대해 일치하는 회원의 존재 여부 및 존재서의 이메일을 담는 JSON 응답 결과를 처리하기 위한 로직.

         서비스 가 넘겨준 결과가 CommonResult.SUCCESS라면 응답 결과로 email 값도 함께 돌려 보낸다. 

 

- MemberController

@RequestMapping(value = "recoverEmail", method = RequestMethod.GET, produces = MediaType.TEXT_HTML_VALUE)
public ModelAndView getRecoverEmail() {
    ModelAndView modelAndView = new ModelAndView("member/recoverEmail");
    return modelAndView;
}
@RequestMapping(value = "recoverEmail", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseBody
public String postRecoverEmail(UserEntity user) {
    Enum<? extends IResult> result = this.memberService.recoverEmail(user);
    JSONObject responseObject = new JSONObject();
    responseObject.put("result", result.name().toLowerCase());
    if(result == CommonResult.SUCCESS) {
        responseObject.put("email", user.getEmail());
    }
    return responseObject.toString();
}

 

 

 

로직

1. 전달 받은 UserEntity 타입의 객체가 가지는 이름(name) 및 연락처(contact)와 일치하는 또 다른 UserEntity 객체를 SELECT 한다.

2. 위 <1>에서 받아온 새로운 UserEntity 객체가 null 이라면 CommonResult.FALURE를 반환하고 메서드 종료.

3. 아니라면, 매개변수로 전달받은 UserEntity 객체의 email 필드 값을 새로 받아온 UserEntity 객체가 가진 email 값으로 지정(set)하고      

    CommonResult.SUCCESS 반환한다.

- MemberService

public Enum<? extends  IResult> recoverEmail(UserEntity user) {
    UserEntity existingNameAuth = this.memberMapper.selectUserByNameContact(
            user.getName(), user.getContact());

    if (existingNameAuth == null) {
        return CommonResult.FAILURE;
    }
    user.setEmail(existingNameAuth.getEmail());
    return CommonResult.SUCCESS;
}

 

 

 

 

로직: 전달된 이름(name)과 연락처(contact)를 가지는 레코드를 선택하여 UserEntity 타입의 객체로 반환한다. 

- IMemoMapper

UserEntity selectUserByNameContact(@Param(value = "name") String name,@Param(value = "contact") String contact);

 

 

 

- MemberMapper.xml

<select id="selectUserByNameContact"
        resultType="dev.shlee.studymemberbbs.entities.member.UserEntity">
    SELECT `email`             AS `email`,
           `password`          AS `password`,
           `nickname`          AS `nickname`,
           `name`              AS `name`,
           `contact`           AS `contact`,
           `address_postal`    AS `addressPostal`,
           `address_primary`   AS `addressPrimary`,
           `address_secondary` AS `addressSecondary`,
           `registered_on`     AS `registeredOn`
    FROM `study_member`.users
    WHERE BINARY `name` = #{name}
      AND  BINARY `contact` = #{contact}
        LIMIT 1
</select>

 

 

 

- recoverEmail.html

<!doctype html>
<html lang="ko" xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>스터디 - 이메일 찾기</title>
    <th:block th:replace="~{fragments/head :: common}"></th:block>
    <link rel="stylesheet" th:href="@{/member/resources/stylesheets/recoverEmail.css}">
    <script defer th:src="@{/member/resources/scripts/recoverEmail.js}"></script>
</head>
<body>
<th:block th:replace="~{fragments/body :: header}"></th:block>
<th:block th:replace="~{fragments/body :: cover}"></th:block>
<main class="--main main">
    <form class="form" id="form" rel="form">
        <div class="title-container">
            <h1 class="title">이메일 찾기</h1>
        </div>
        <table class="table">
            <tbody>
            <tr>
                <th>이름</th>
                <td>
                    <label class="label name">
                        <span hidden>이름</span>
                        <input class="--object-input input" maxlength="50" name="name"
                               placeholder="이름을 입력해 주세요" type="text">
                    </label>
                </td>
            </tr>
            <tr class="contact-row" rel="contactRow">
                <th>연락처</th>
                <td>
                    <label class="label contact">
                        <span hidden>연락처</span>
                        <input class="--object-input input" maxlength="50" name="contact"
                               placeholder="가입에 사용하신 연락처를 입력해 주세요." type="tel">
                    </label>

                </td>
            </tr>
            <tr>
                <th></th>
                <td>
                    <input class="--object-button findEmail" name="findEmail" type="button" value="이메일 찾기">
                    <a th:href="@{/member/login}">
                        <input class="--object-button goLogin" name="goLogin" type="button" value="로그인 하러가기">
                    </a>
                </td>
            </tr>
            <tr class="message-row" rel="messageRow">
                <th></th>
                <td>
                    <span class="message">
                        <span class="text"></span>
                    </span>
                </td>
            </tr>

            <tr class="warning-row" rel="warningRow">
                <th></th>
                <td>
                    <span class="warning">
                        <i class="icon fa-solid fa-triangle-exclamation"></i>
                        <span class="text">이름을 입력해 주세요.</span>
                    </span>
                </td>
            </tr>
            </tbody>
        </table>
    </form>
</main>
<th:block th:replace="~{fragments/body :: footer}"></th:block>
</body>
</html>

 

 

 

- recoverEmail.js

const form = window.document.getElementById('form');
// 주어진 문자열과 일치하는 id 속성을 가진 요소를 찾고, 이를 나타내는 Element 객체를 반환한다.
const Warning = {
    getElement: () => form.querySelector('[rel="warningRow"]'), //form안에서 class 찾기
    show: (text) => {
        const warningRow = Warning.getElement();
        warningRow.querySelector('.text').innerText = text; //text를 찾고 text인 값을 innerText 해주기
        warningRow.classList.add('visible'); // classList.add를 통해 보여준다
    },
    hide: () => Warning.getElement().classList.remove('visible')
    // hide -> 숨기기
};

const Email = {
    getElement: () => form.querySelector('[rel="messageRow"]'),
    show: (text) => {
        const messageRow = Email.getElement();
        messageRow.querySelector('.text').innerText = text;
        messageRow.classList.add('visible');
    },
    hide: () => Email.getElement().classList.remove('visible') // 안보이게 하기
};

form['findEmail'].addEventListener('click', () => {
    Warning.hide();
    if (form['name'].value === '') {
        Warning.show('이름을 입력해 주세요.');
        form['name'].focus();
        Email.hide();
        return;
    }
    if(form['contact'].value === '') {
        Warning.show('전화번호를 입력해 주세요.');
        form['name'].focus();
        Email.hide();
        return;
    }
    const xhr = new XMLHttpRequest();
    const formData = new FormData();
    formData.append('name', form['name'].value); // name과 name.value를 추가
    formData.append('contact', form['contact'].value);
    xhr.open('POST', './recoverEmail')
    xhr.onreadystatechange = () => {
        if (xhr.readyState === XMLHttpRequest.DONE) {
            Cover.hide();
            if (xhr.status >= 200 && xhr.status < 300) {
                const responseObject = JSON.parse(xhr.responseText);
                console.log(responseObject);
                switch (responseObject['result']) {
                    case 'success':
                        form['name'].setAttribute('disabled', 'disabled');
                        form['contact'].setAttribute('disabled', 'disabled');
                        form['findEmail'].setAttribute('disabled', 'disabled');
                        Email.show('입력하신 정보와 일치하는 이메일은'+'\n' + responseObject['email'] +'\n' + '입니다')
                        form.querySelector('[rel="messageRow"]').classList.add('visible');
                        form.querySelector('[rel="warningRow"]').classList.remove('visible');
                        form['goLogin'].classList.add('visible');

                        break;
                    default:
                        Warning.show('입력한 정보와 일치하는 회원이 없습니다.');
                        form.querySelector('[rel="messageRow"]').classList.remove('visible');
                        form['goLogin'].classList.remove('visible');
                }
            } else {
                Warning.show('서버와 통신하지 못하였습니다. 잠시 후 다시 시도해 주세요.');
            }
        }
    };
    xhr.send(formData);
});

 

 

 

- recoverEmail.css

@charset "UTF-8";

#form {
    width: 100%;
    max-width: 40rem;
    margin: 5rem 2rem;
    display: flex;
    flex-direction: column;
    align-items: stretch;
    justify-content: flex-start;
}

#form > .title-container {
    margin-bottom: 3rem;
}

#form > .title-container > .title {
    font-size: 2rem;
    font-weight: 500;
}

#form > .table {
    width: 100%;
    max-width: 30rem;
    align-self: center;
    border: none;
    border-collapse: collapse;
}

#form > .table th {
    white-space: nowrap;
    padding-right: 1rem;
}

#form > .table td {
    width: 100%;

}

#form > .table [name="recoverEmail"] {
    width: 100%;
    margin-top: 0.25rem;
}

#form > .table .message-row {
    display: none;
}

#form > .table .message-row.visible {
    display: table-row;
}

#form > .table .message-row .message {
    align-items: center;
    background-color: rgb(26, 188, 156);
    border-radius: 0.375rem;
    color: rgb(255, 255, 255);
    display: flex;
    flex-direction: row;
    font-size: 1rem;
    justify-content: center;
    margin-top: 0.25rem;
    padding: 1rem 1rem;
}

#form > .table .message-row .message > .icon {
    font-size: 1.5rem;
    margin: 0 1.5rem 0 0.25rem;
}

#form > .table .message-row .message > .text {
    text-align: center;
}

#form > .table .warning-row {
    display: none;
}

#form > .table .warning-row.visible {
    display: table-row;
}

#form > .table .warning-row .warning {
    align-items: center;
    background-color: rgb(243, 67, 67);
    border-radius: 0.375rem;
    color: rgb(255, 255, 255);
    display: flex;
    flex-direction: row;
    font-size: 1rem;
    justify-content: flex-start;
    margin-top: 0.25rem;
    padding: 0.75rem 1rem;
}

#form > .table .warning-row .warning > .icon {
    font-size: 1.5rem;
    margin: 0 1.5rem 0 0.25rem;
}

#form > .table .message-row .warning > .text {
    flex: 1;
    text-align: justify;
}


#form > .table > .warning-row .warning {
    background-color: rgb(231, 76, 60);
    color: rgb(255, 255, 255);
    margin-top: 0.5rem;
    padding: 1rem 1rem;
    border-radius: 0.375rem;
    font-size: 0.9rem;
    display: flex;
    flex-direction: row;
    align-items: center;
    justify-content: flex-start;
}

#form > table > tbody > tr > td > .findEmail,
#form > table > tbody > tr > td > a > .goLogin {
    width: 100%;
    margin-top: 0.35rem;
}

#form > table > tbody > tr > td > a {
    text-decoration: none;
    color: inherit;
}

#form > table > tbody td > a > .goLogin {
    display: none;
}

#form > table > tbody td > a > .goLogin.visible {
    display: table-row;
}

이메일 찾기 버튼을 클릭하였을 때 이름을 입력하지 않은 경우 '이름을 입력해 주세요'라는 경고 메세지가 표시되게 한다. 

이메일 버튼을 클릭하였을 때 입력한 연락처를 입력하지 않은 경우 아래와 같이 '전화번호를 입력해 주세요.' 라는 경고 메세지가 표시되어야 합니다. 

이메일 찾기 버튼을 클릭하였을 때 입력한 이름과 연락처를 가지는 회원이 없다면 아래와 같이 '입력한 정보와 일치하는 회원이 없습니다.'라는 경고 메세지가 표시되게 한다. 

이메일 찾기 버튼을 클릭하였을 때 입력한 이름과 연락처를 가지는 회원이 있다면 아래와 같이 이름 및 연락처 입력란에 이메일 찾기 버튼이 비활성화 되고, 이메일을 포함하는 메세지와 '로그인하러 가기'라는 버튼이 보여지게 한다. 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2026/04   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30
글 보관함