대표적으로 fetch() API가 있는데 JS의 Promise 객체를 이용한 비동기 요청 방법으로 JS에서 기본으로 제공한다!
Promise(약속) 객체 : 약속이라는 이름처럼 비동기 요청에 대한 처리가 완료되면 바로 결과를 제공하겠다고 약속하는 의미라고 한다 -> 비동기 요청 시 동시에 다른 JS 코드가 실행되고 있음
fetch() API : fetch 가지고 오다 라는 뜻처럼 비동기 요청이 끝나면 응답 결과를 가져와서
현재 화면에서 다룰 수 있는 방법을 제공하는 API이다.
아직 GET 방식밖에 안 배워서 POST 방식은 추후에 적도록 하겠음ㅎㅎ
[GET 방식 요청 작성방법] ↓
fetch("요청주소")
-> 지정된 주소로 GET방식 비동기 요청(ajax)
전달하고자 하는 파라미터를 주소 뒤 쿼리스트링으로 추가
.then(response => response 파싱)
-> 요청에 대한 응답 객체(response)를 필요한 형태로 파싱
.then(response 파싱 데이터 => {})
-> 첫 번째 then에서 파싱한 데이터를 이용한 동작 생성
.catch(e => {})
-> 예외 발생 시 처리할 내용을 작성
이렇게 생각보다 간단하다 예시말고 직접 작성한 코드를 보면 더 이해가 쏙쏙 된다(내가 그랬다ㅎ)
지금 보여드리는 코드는 회원가입 중 닉네임 유효성 검사에 대한 비동기 통신이다.
// 닉네임 유효성 검사
const memberNickname = document.getElementById("memberNickname");
const nickMessage = document.getElementById("nickMessage");
memberNickname.addEventListener("input", () => {
// 닉네임이 입력 되지 않았을 때
if (memberNickname.value.trim().length == 0) {
memberNickname.value = "";
nickMessage.innerText = "한글,영어,숫자로만 2~10글자";
nickMessage.classList.remove("confirm", "error"); // 검정글씨
checkObj.memberNickname = false; // 빈칸 == 유효 X
memberNickname.value = "";
return;
}
// 닉네임이 입력 되었을 때
// 정규표현식으로 유효성 검사
const regEx = /^[가-힣\w\d]{2,10}$/;
/************************************************************************ */
if(regEx.test(memberNickname.value)){
fetch("/dupCheck/nickname?nickname=" + memberNickname.value)
.then(resp => resp.text()) // 응답 객체를 text로 파싱(변환)
.then(count => {
if(count == 0){ // 중복이 아닌경우
nickMessage.innerText = "사용 가능한 닉네임 입니다.";
nickMessage.classList.add("confirm");
nickMessage.classList.remove("error");
checkObj.memberNickname = true;
}else{ // 중복인 경우
nickMessage.innerText = "이미 사용중인 닉네임 입니다.";
nickMessage.classList.add("error");
nickMessage.classList.remove("confirm");
checkObj.memberNickname= false;
}
})
.catch(err => console.log(err));
/************************************************************************ */
}else{ // 무효
nickMessage.innerText = "유효하지 않은 닉네임 입니다.";
nickMessage.classList.add("error");
nickMessage.classList.remove("confirm");
checkObj.memberNickname= false;
}
})
우선 코드의 순서를 살펴보자면
1) 닉네임이 입력되었고
2) 정규식 유효성 검사도 통과 했을때
3) 닉네임 중복 검사를 비동기 통신으로 진행하게 된다
변수명을 다르게 사용한게 있는데 catch절에 e대신 에러를 뜻하는 err로 사용하였고
reponse 대신 줄여서 resp로 사용하였다!!!
이제 스프링으로 넘어가서 요청을 처리해야 하는데
fetch("/dupCheck/nickname?nickname=" + memberNickname.value)
여기서 쿼리스트링으로 넘겨준 닉네임을 매개변수로 계속 넘겨주며 코드가 진행된다
1️⃣ Controller
// 닉네임 중복 검사
@GetMapping(value="/dupCheck/nickname")
@ResponseBody
public int dupCheckNickname(String nickname) {
return service.dupCheckNickname(nickname);
}
2️⃣ ServiceInterface
/** 닉네임 중복확인
* @param nickname
* @return count
*/
int dupCheckNickname(String nickname);
3️⃣ ServiceImpl(service인터페이스를 구현한 클래스)
// 닉네임 중복확인
@Override
public int dupCheckNickname(String nickname) {
return dao.dupCheckNickname(nickname);
}
4️⃣ DAO
/**
* 닉네임 중복 검사
*
* @param nickname
* @return count
*/
public int dupCheckNickname(String nickname) {
return sqlSession.selectOne("ajaxMapper.dupCheckNickname", nickname);
}
5️⃣ 그 후 mapper.xml에서 sql문을 수행하게 되는데
<!-- 닉네임 중복검사 -->
<select id="dupCheckNickname" resultType="_int">
SELECT COUNT(*) FROM MEMBER
WHERE MEMBER_NICKNAME = #{nickname}
AND MEMBER_DEL_FL = 'N'
</select>
전달받은 닉네임 값을 넣어주고 조회되는 게 있으면 이미 있는 닉네임이니
중복이 있다는 뜻 == count가 0보다 크고, 중복되는 닉네임이 없으면 0의 값을 가져올 것이다
실행해 보면 이렇게 중복검사가 아주 잘~~~된다💚
추가적으로 작성해보자면 Controller에 작성된 어노테이션중 @ResponseBody가 핵심인데
새로운 화면을 찾아주는 ViewResolver가 아니라 직접 데이터를 클라이언트에게 전송하여 비동기로 화면을 부분적으로 바꿔줘야 하기 때문이라고 한다.
요청 데이터를 얻어오는 방법
1) GET : 요청 url에 쿼리스트링 형태로 파라미터가 담겨있어
@RequestParam, @ModelAttribute를 이용해서 얻어옴
2) POST : HTTP 요청 Body에 파라미터가 담겨 있으므로
@RequestBody를 통해 값(JSON)을 얻어와
Java객체로 변환(HttpMessageConverter)
응답 방법 (GET/POST 구분 X)
: @ResponseBody를 이용해 반환한다
-> 해당 어노테이션을 작성하면
Controller에서 반환되는 값이 ViewResolver가 아닌
HttpMessageConverter로 전달되어
반환된 Java객체를 text/JSON으로 변환 후 비동기 요청을 한 곳으로 응답함
* ****************************
* *** HttpMessageConverter ***
* ****************************
*
* HTTP 요청 Body의 내용을 Java 객체로 변환하고
* HTTP 응답의 Body의 내용을 text/JSON 형태로 변환해주는
* Spring Framework 구성 요소
*
* Spring에서 사용하는 MessageConverter 종류
* 1순위 : ByteArrayHttpMessageConverter (바이트 배열 자동 변환)
* 2순위 : StringHttpMessageConverter (Text 형식 자동 변환)
* 3순위 : MappingJackson2HttpMessageConverter (요청 데이터 -> DTO/Map , 응답 데이터 -> JSON)
여기서 String 값은 MappingJackson2HttpMessageConverter 이걸로 출력하면 되는데
int 값은 저걸로 출력이 안되서 jackson-databind를 pom.xml에 추가해주어야 한당!
<!-- Jackson databind -->
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.14.2</version>
</dependency>
적다 보니 내용이 많아졌는데 비동기 통신은 나중에도 자주 쓸 것 같아서 더 열심히 공부해 봐야겠다 'ㅁ'
한눈에 코드들이 다 들와용ㅎㅎ 정리천재👍