Spring/Blog-V1

스프링 34강. id 중복체크

JJJAEOoni 2022. 3. 17. 00:59
반응형

우리 블로그에는 한 가지 문제가 있다

기존에 존재하는 username으로 회원 가입하면 서버가 터져버린다.

UNIQUE 제약조건에 위배된 것이다.

 

보통의 사이트에서 회원 가입할 때 아이디 중복확인 버튼이 만들어져 있었는데

그냥 키보드 입력 때마다 DB에서 이벤트 검사를 받을 수 있다.

 

get요청이다.

이 아이디 DB에 있어?

 

 

get 요청인데 Ajax 안 써도 되지 않을까?

 

안 쓰면 계속해서 전체 페이지가 새로고침 되기 때문에

get 요청인데도 Ajax를 사용한다.

 

jQuery를 사용해주기 위해 헤더 레이아웃에 추가해주자.

<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>

일일이 머스태치 파일마다 추가하지 않아도 부분 템플릿으로 편하게 사용 가능하다.

 

우선 input 태그 dom을 찾아서 value 찾으려면

dom에 id를 부여해줘야겠다!

<!-- 회원가입 폼 시작 -->
<form action="/join" method="post">
    <div class="mb-3 mt-3">
      <input type="text" class="form-control" placeholder="Enter username" name="username" id="username" required>
    </div>
    <div class="mb-3">
      <input type="password" class="form-control" placeholder="Enter password" name="password" required>
    </div>
    <div class="mb-3">
      <input type="email" class="form-control" placeholder="Enter emails" name="email">
    </div>

    <button type="submit" class="btn btn-dark">회원가입</button>
</form>
<!-- 회원가입 폼 끝 -->

 

키보드 이벤트가 일어날 때마다 value를 체크해주는 것이다.

keypress 이벤트를 걸어주면 되겠다.

키보드를 눌렀다 뗄 때 확인하는 것이다.

 

<script>
  $("#username").keypress(() => {
    console.log("글자적었네?")
  });
</script>

글자적을 때마다 DB에 물어보는 것이다.

SELECT!

키보드 입력할 때마다 값을 가져와야 하니

$("#username").val( )로 직접 value를 가지고 온다.

 

<script>
  $("#username").keypress(() => {
    let value = $("#username").val();
    console.log("글자적었네");
    console.log(value);
  });
</script>

 

근데 출력되는 타이밍이 느리다.

다음 글자를 적는 순간에 value를 가져오기 때문에 타이밍이 맞지 않다.

 

입력하자마자 value를 바로 찾아올 수는 없을까?

 

keyup, keypress, keydown 이벤트가 발생하는 타이밍에 차이가 있다.

 

https://dororongju.tistory.com/91

 

[JQuery] 키보드 이벤트 발생 순서 (keydown / keypress 차이)

키보드 이벤트 키보드 이벤트 발생 순서 1. 키보드를 누릅니다. 2. keydown 이벤트가 발생합니다. 3. 글자가 입력됩니다. 4. keypress 이벤트가 발생합니다. 5. 키보드에서 손을 뗍니다 6. keyup 이벤트가

dororongju.tistory.com

 

keyup을 사용해 해결했으니 이제 DB에 물어봐야겠다.

$("#username").keyup((event) => {
  // console.log(event.target.value);
  usernameSameCheck(event.target.value);
});

컨트롤러가 하나 필요하다.

 

user 컨트롤러에 만들면 되겠다.

 

주소에 /api가 걸려있으면 데이터를 리턴해주는 컨트롤러임을 말한다고 약속되어있다.

/s는 안 붙어도 되겠다.

인증이 필요 없는 컨트롤러이니까!

// DB에 username 확인
// user의 username이 동일한지 확인해줄래? - 응답은 무조건 json
// 부득이하게 예외적으로 동사사용할 때도 있음
// get만으로 동사가 부족하기 때문
// http://localhost:8080/api/user/username/same-check?username=s
@GetMapping("/api/user/username/same-check")
public @ResponseBody ResponseDto<String> sameCheck(String username) {

    // 1. SELECT * FROM user WHERE username = "ssar";
    User userEntity = userRepository.mUsernameSameCheck(username);

    // 2. userEntity가 있으면? 없으면?
    if (userEntity == null) {
        return new ResponseDto<String>(1, "통신성공", "없어");
    } else {
        return new ResponseDto<String>(1, "통신성공", "있어");
    }

}
@Query(value = "SELECT * FROM user WHERE username = :username", nativeQuery = true)
User mUsernameSameCheck(@Param("username") String username);
package site.metacoding.dbproject.web.dto;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@AllArgsConstructor
@NoArgsConstructor
@Data
public class ResponseDto<T> {
    private Integer code; // -1 통신 실패 1 통신 성공
    private String msg;
    // 응답의 body 데이터
    private T data; // 데이터 타입이 결정되지 않았다
}

 

async function usernameSameCheck(username) {
  // 같은 도메인 안에 있으니까 @CrossOrigin 붙일 필요 없음
  let response = await fetch(`/api/user/username/same-check?username=${username}`);
  let responseJson = await response.json();
  console.log(responseJson.data);
  if(responseJson.data === "있어") {
    alert("중복된 아이디입니다.");
    $("#username").val("");
  }
}

 

 

[출처]

 

https://cafe.naver.com/metacoding

 

메타코딩 : 네이버 카페

코린이들의 궁금증

cafe.naver.com

메타 코딩 유튜브

https://www.youtube.com/c/%EB%A9%94%ED%83%80%EC%BD%94%EB%94%A9

 

메타코딩

문의사항 : getinthere@naver.com 인스타그램 : https://www.instagram.com/meta4pm 깃헙 : https://github.com/codingspecialist 유료강좌 : https://www.easyupclass.com

www.youtube.com

 

 

반응형