[Spring] 비동기 ID 중복 체크 기능
안녕하세요 코북입니다. 1차 때는 JDBC와 서블릿을 사용해서 ID 중복 체크를 구현했었는데, 이번 프로젝트에서는 스프링으로 구현해봤습니다. 흐름이 조금 더 익숙하지 않긴 하지만 확실히 스프링 프레임워크가 좀 더 코드가 짧고 간결해서 익숙해지면 훨씬 쉽게 작업을 할 수 있을 것 같습니다. 작업순서는 JSP로 view단 먼저 만든 후 ajax를 이용해 json데이터를 요청했고, 그 후 controller와 mapper를 연결시켰습니다.
작업순서
1. jsp, ajax
2. controller
3. mapper
1. JSP, AJAX
<div class="form-group">
<label for="mb_id" class="form-label mt-4">아이디</label>
<input type="text" class="form-control" name="mb_id" id="mb_id">
<div><font id="id_feedback" size="2"></font></div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script type ="text/javascript">
$('#mb_id').keyup(function(){
let mb_id = $('#mb_id').val();
$.ajax({
url : "${cpath}/mbidCheck.do",
type : "post",
data : {mb_id: mb_id},
dataType : 'json',
success : function(result){
if(result == 1){
$("#id_feedback").html('이미 사용중인 아이디입니다.');
$("#id_feedback").attr('color','#dc3545');
} else{
$("#id_feedback").html('사용할 수 있는 아이디입니다.');
$("#id_feedback").attr('color','#2fb380');
}
},
error : function(){
alert("서버요청실패");
}
})
})
</script>
먼저 bootstrap을 이용해 id를 입력할 수 있는 입력창을 먼저 만들었습니다. 그 밑에는 사용자가 id를 사용할 수 있는지 없는지 알림을 주기위해 font 태그를 이용했습니다. jquery와 ajax를 이용해 사용자가 즉시 피드백을 받을 수 있게 구현했습니다. 사용자가 #mb_id에 입력을 마치면 keyup에 의해 함수가 실행됩니다. let mb_id = $('#mb_id').val()로 사용자가 입력한 값을 변수에 담아줍니다. ajax 비동기 통신을 이용해 mbidCheck.do로 데이터를 요청하고, mb_id값을 보내줍니다. 결괏값을 result로 받을 수 있게 설정했습니다. 후에 select count(*)를 통해 값을 받아올 것이기 때문에 받아온 값이 1이면 사용 중인 아이디로 알림을 보내고 값이 0인 경우에는 사용할 수 있는 아이디라고 알림을 보냅니다. 통신에 실패했을 경우를 대비해 error 함수도 설정해줍니다.
2. Controller
@Autowired
private MembersMapper mapper;
// 아이디 중복체크
@RequestMapping("/mbidCheck.do")
public @ResponseBody int mbidCheck(String mb_id) {
int result = mapper.mbidCheck(mb_id);
return result;
}
이 컨트롤러는 ajax로 요청한 json파일을 처리하기 위한 컨트롤러입니다. 위에서 사용한 ajax의 url과 컨트롤러의 주소값을 동일하게 해주셔야 합니다. @ResponseBody를 이용하면 @Controller에서도 @RestController처럼 json데이터를 보낼 수 있게 됩니다. 이렇게 하면 따로 RestController를 만들지 않아도 됩니다. 이 컨트롤러에서는 ajax에서 넘어온 mb_id라는 스트링 타입 데이터를 변수로 하여 mapper에 넘겨줄 것이기 때문에 매개변수는 String mb_id로 설정합니다. mapper에서 mbidCheck메소드를 실행시켜 받아올 데이터는 중복된 아이디의 수를 받아올 것이기 때문에 int형으로 return값을 설정해줍니다. result 변수에 받아온 값을 담고 결괏값을 넘겨주도록 하겠습니다. 이 값은 JSON으로 변환시켜서 사용자에게 전달됩니다.
3. Mapper
@Mapper
public interface MembersMapper {
public int mbidCheck(String mb_id);
}
<mapper namespace="city.turtle.mapper.MembersMapper">
<!-- 아이디 중복체크 -->
<select id="mbidCheck" parameterType="String" resultType="int">
select count(*) from members where mb_id = #{mb_id}
</select>
</mapper>
Mapper Interface에서는 컨트롤러에서 실행할 함수를 생성해줍니다. 매개변수는 xml로 넘겨줄 값입니다. 사용자가 생성하고자 하는 ID가 DB에 저장되어있는지 확인하기 위해 String 타입의 mb_id를 매개변수로 설정했습니다. sql문 실행으로 얻는 결괏값이 int 타입이기 때문에 return타입은 int로 설정해줍니다. 추상메소드를 사용하기 때문에 DAO가 interface가 되고 바디는 적지 않습니다. 바디 역할은 MyBatis 프레임워크가 대신 수행합니다.
위 작업에서 Java와 SQL을 분리시켰기 때문에 SQL Mapper file(XML)을 만들어줘야합니다. root-context.xml에서 scan을 통해 @Mapper가 있는 interface를 찾아내고, 메모리에 interface가 올라가면서 네임스페이스를 보고 xml과 연결됩니다. 이를 통해 sql이 실행됩니다.
Mapper.xml에는 실행시킬 select문을 적어줍니다. select태그 안에 id값은 mapper interface의 메소드 이름과 동일하게 설정해줍니다. parameterType은 메소드에서 받아오는 매개변수의 타입이고 resultType은 sql실행 결과로 보내줄 데이터의 타입입니다. select count(*)를 통해 중복된 아이디 수를 확인합니다. 중복된 아이디가 존재하면 카운트가 1이 되고 존재하지 않으면 0이 됩니다. 이 값을 처음에 만들었던 ajax의 success result로 반환합니다.
구현 화면입니다.
배운 점
일반 컨트롤러에서 JSON데이터를 처리하려고 해서 계속 통신오류가 났었는데 @ResponseBody를 이용해 오류를 해결했습니다. 일반 컨트롤러에서 RestController처럼 JSON데이터를 처리하기 위해서는 @ResponseBody를 사용해야 한다는 것을 알 수 있었습니다. Mapper Interface의 메소드의 반환 값을 void로 사용하는 경우가 있어서 어떻게 쓰이는지 용도를 잘 이해하지 못하고 있었는데, int값으로 반환해서 직접 사용하면서 어떤 방식으로 결괏값이 처리되고 쓰이는지 알 수 있었습니다. 작업순서를 JSP-Controller-Mappr로 진행했는데, 계속해서 mapper를 수정하는 바람에 그에 맞춰 controller도 바꿔줘야 했습니다. mapper를 먼저 만들고 controller를 만들면 좀 더 효율적으로 작업을 진행할 수 있을 것 같습니다.