Spring - 네이버 아이디로 로그인, 회원가입 만들기- 4

2021. 4. 28. 16:19Java/Spring

반응형

이전 페이지에서 로그인을 하게 되면 개발자 센터에서 저장한 callback url을 요청한다.

 

내가 작성한 해당 부분의 컨트롤러는 아래와 같다.

@RequestMapping(value="/userNaverLoginPro.do",  method = {RequestMethod.GET,RequestMethod.POST})
	public String userNaverLoginPro(Model model,@RequestParam Map<String,Object> paramMap, @RequestParam String code, @RequestParam String state,HttpSession session) throws SQLException, Exception {
		System.out.println("paramMap:" + paramMap);
		Map <String, Object> resultMap = new HashMap<String, Object>();

		OAuth2AccessToken oauthToken;
		oauthToken = naverloginbo.getAccessToken(session, code, state);
		//로그인 사용자 정보를 읽어온다.
		String apiResult = naverloginbo.getUserProfile(oauthToken);
		System.out.println("apiResult =>"+apiResult);
		ObjectMapper objectMapper =new ObjectMapper();
		Map<String, Object> apiJson = (Map<String, Object>) objectMapper.readValue(apiResult, Map.class).get("response");
		
		Map<String, Object> naverConnectionCheck = userservice.naverConnectionCheck(apiJson);
		
		if(naverConnectionCheck == null) { //일치하는 이메일 없으면 가입
			
			model.addAttribute("email",apiJson.get("email"));
			model.addAttribute("password",apiJson.get("id"));
			model.addAttribute("phone",apiJson.get("mobile"));
			return "user/setNickname";
		}else if(naverConnectionCheck.get("NAVERLOGIN") == null && naverConnectionCheck.get("EMAIL") != null) { //이메일 가입 되어있고 네이버 연동 안되어 있을시
			userservice.setNaverConnection(apiJson);
			Map<String, Object> loginCheck = userservice.userNaverLoginPro(apiJson);
			session.setAttribute("userInfo", loginCheck);
		}else { //모두 연동 되어있을시
			Map<String, Object> loginCheck = userservice.userNaverLoginPro(apiJson);
			session.setAttribute("userInfo", loginCheck);
		}

		return "redirect:usermain.do";
	}

먼저 아래 코드를 통해서 유정 정보를 얻어온다.

 

String apiResult = naverloginbo.getUserProfile(oauthToken);

해당 정보를 콘솔에 찍으면 아래와 같이 받아진다.

{"resultcode":"00","message":"success","response":{"id":"고유아이디","nickname":"hokki","profile_image":"네이버프로필이미지링크","age":"20-29","gender":"M","email":"네이버이메일","mobile":"폰번호","mobile_e164":"번호","name":"\uc190\ud638\uc77c","birthday":"생일","birthyear":"1994"}}

json 형식인데 string으로 받아지고 실제로 쓰이는 부분은 해당 데이터에서 response 내부이다.

 

따라서 해당 String을 json으로 받아 Map으로 변환해준다.

ObjectMapper objectMapper =new ObjectMapper();

Map<String, Object> apiJson = (Map<String, Object>) objectMapper.readValue(apiResult, Map.class).get("response");

위 과정을 통해 apiResult의 response만 받아 apiJson에 Map으로 저장을 한다.

 

이제 이 데이터를 가지고 작업을 해야하는데 본인의 프로젝트에 맞게 작업을 해야한다.

 

먼저 나는 세가지 경우로 나누었다.

 

1. 이미 일반 회원가입을 통해 가입한 이메일이고, 네이버 연동을 하는 경우

2. 회원가입을 하지 않은 이메일인 경우

3. 회원가입 및 네이버 연동이 된 이메일인 경우

 

위와 같은 경우의 수를 생각해서 MEMBERS 테이블을 아래와 같이 구상했다.

 

네이버 연동이 안된 일반 회원들은 NAVERLOGIN 값이 null 일 것이고, 네이버 연동이 된 회원들은 NAVERLOGIN 에 각 고유 값인 apiJson의 id 값을 넣어준다.

 

그리고 네이버로 회원가입을 처음 하는 경우에 password에 오는 값을 apiResult의 id로 설정을 해준다.

 

위와 같이 구상 후 먼저 로그인 하려는 이메일이 네이버 연결이 되었는지, 기존에 있는 이메일인지 알기 위해 아래 코드를 요청한다.

 

Map<String, Object> naverConnectionCheck = userservice.naverConnectionCheck(apiJson);

해당 요청은 service -dao를 거쳐 mapper로 가서 아래 쿼리를 실행한다.

 

SELECT EMAIL,NICKNAME,NAVERLOGIN FROM MEMBERS WHERE EMAIL = #{email}

이메일 정보를 통해서 email, nickname,naverLogin 정보를 가져오는데

 

1) 만약 naverConnectionCheck 자체가 null이면 계정 정보가 없으므로 첫 회원 가입이다. 따라서 추가 정보를 입력하여 가입을 한다.

 

2) 만약 NAVERLOGIN 이 null 이고 EMAIL은 null이 아닐시 기존에 가입 된 메일이지만 네이버 연동은 안되어 있는 계정이므로 네이버 연동을 시켜주고 로그인한다.

 

3) 만약 둘 다 아니라면 이미 네이버로 가입이 된 계정이므로 로그인 시킨다.

 

 

먼저 3) 부터 살펴보면 아래 코드로 로그인을 시킨다.

Map<String, Object> loginCheck = userservice.userNaverLoginPro(apiJson);
session.setAttribute("userInfo", loginCheck);

userNaverLoginPro(apiJson); 는 아래 쿼리를 작동한다.

SELECT EMAIL,NICKNAME FROM MEMBERS WHERE EMAIL = #{email} AND NAVERLOGIN = #{id}

이메일과 네이버 id 값을 통해 로그인 정보를 가져와 세션에 담는다.

 

2)의 경우에는 해당 유저 정보에 NAVERLOGIN을 추가해준다.

 

userservice.setNaverConnection(apiJson);
Map<String, Object> loginCheck = userservice.userNaverLoginPro(apiJson);
session.setAttribute("userInfo", loginCheck);

setNaverConnection(apiJson) 는 아래 쿼리를 통작시킨다.

UPDATE MEMBERS SET NAVERLOGIN = #{id} WHERE EMAIL = #{email}

위 쿼리를 통해 해당 이메일의 NAVERLOGIN 값을 추가한다.

 

그 후 3)의 방식으로 로그인을 시켜준다

 

마지막으로 1)의 경우 첫 회원 가입이기 때문에 추가 정보를 받는 경우가 있다.

 

그래서 추가 정보를 받는 페이지 setNickname.jsp을 만들었다.

 

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<link rel="stylesheet" type="text/css" href="/css/userRegister.css?version=21042510" />
<form name="userRegisterForm" id="userRegisterForm" method="POST">
	<input type="hidden"  id="email" name="email" value="${email}"/>
	<input type="hidden"  id="password" name="password"  value="${password}">
	<input type="hidden"  id="id" name="id"  value="${password}">
	<input type="hidden"  id="phone" name="phone"  value="${mobile}">
	<table>
		<thead>
			<tr>
				<th colspan="3">신규 가입 추가 정보 설정</th>
			</tr>
		</thead>
		<tbody>
			
			<tr>
				<td class="text">닉네임</td>
				<td>
					<input id="nicknameCheck" name="nicknameCheck">
					<input type="hidden" id="nickname" name="nickname">
				</td>
				<td><button id="dupliButton" type="button" onclick="checkNickname()">중복체크</button></td>
			</tr>
			<tr>
				<td></td>
				<td><input type="button" id="regiButton" onclick="register()" value="회원가입" /></td>
				<td></td>
			</tr>
		</tbody>
	</table>
</form>
<script>
function checkNickname(){
	var nicknameCheck = $("#nicknameCheck").val();
	var nickname = $("#nickname").val();
	var regExp =  /^[가-힣|a-z|A-Z|0-9|]+$/;

	if(nicknameCheck == null || nicknameCheck == ""){
		alert("닉네임을 입력 해주세요");
		return false;
	}
	if(!regExp.test(nicknameCheck)){
		alert("닉네임은 한글, 영어, 숫자만 4 ~10자리로 입력 가능합니다.");
		return false;
	}
	$.ajax({
		type : 'POST',
		url : '/user/checkNickname.do',
		data : {nickname:nicknameCheck },
		dataType : 'json',
		success : function(data){
			console.log(data)
			if(data.JavaData == 'YES'){
				alert("사용가능한 닉네임 입니다.");
				$("#nickname").val(nicknameCheck);
			}else{
				alert("이미 존재하는 닉네임 입니다.");
				$("#nicknameCheck").val("");
			}
		},
		error: function(xhr, status, error){
			alert(error);
		}
	});
}


function register(){
	var registerData =common.serializeObject($("form[name=userRegisterForm]"));
	if(registerData.nickname == null || registerData.nickname == ""){
		alert("닉네임 중복 체크를 해주세요");
		return false;
	}
	var phoneNum = registerData.phone.replace(/(^02.{0}|^01.{1}|[0-9]{3})([0-9]+)([0-9]{4})/,"$1-$2-$3")
	registerData.phone = phoneNum
	
	$.ajax({
		type : 'POST',
		url : '/user/userNaverRegisterPro.do',
		data : registerData,
		dataType : 'json',
		success : function(data){
			if(data.JavaData == "YES"){
				alert("가입되었습니다.");
				location.href = '/user/usermain.do'
			}else{
				alert("가입에 실패했습니다.");
			}
		},
		error: function(xhr, status, error){
			alert("가입에 실패했습니다."+error);
		}
	});
}
</script>

아래 소스에서 naverConnectionCheck 자체가 null이면 해당 페이지로 이동을 한다.

 

if(naverConnectionCheck == null) { //일치하는 이메일 없으면 가입	
	model.addAttribute("email",apiJson.get("email"));
	model.addAttribute("password",apiJson.get("id"));
	model.addAttribute("phone",apiJson.get("mobile"));
	return "user/setNickname";
}

해당 페이지 이동시 apiJson의 정보를 model을 통해 넘겨준다.

 

 

넘겨준 정보는 input hidden을 통해서 받아주고 아래에서 추가 정보를 받아준다.

 

nickname의 경우 중복 값을 받지 않기 위해서 회원 가입시 중복체크를 해주고 회원 가입을 받는다.

 

중복체크를 했다면 아래와 같이 회원가입을 form에 있는 데이터를 아작스를 통해 보내  요청한다.

 

위 요청에 따라 아래 메소드가 실행된다.

 

@RequestMapping(value="/userNaverRegisterPro.do", method=RequestMethod.POST)
	public Map<String, Object> userNaverRegisterPro(@RequestParam Map<String,Object> paramMap,HttpSession session) throws SQLException, Exception {
		System.out.println("paramMap:" + paramMap);
		Map <String, Object> resultMap = new HashMap<String, Object>();
		Integer registerCheck = userservice.userNaverRegisterPro(paramMap);
		System.out.println(registerCheck);
		
		if(registerCheck != null && registerCheck > 0) {
			Map<String, Object> loginCheck = userservice.userNaverLoginPro(paramMap);
			session.setAttribute("userInfo", loginCheck);
			resultMap.put("JavaData", "YES");
		}else {
			resultMap.put("JavaData", "NO");
		}
		return resultMap;
	}

userNaverRegisterPro(paramMap); 을 통해서 회원가입 쿼리가 실행된다.

 

INSERT INTO MEMBERS VALUES (#{email},#{nickname},#{password},#{phone},'',#{id})

그후 성공 여부에 따라서 로그인이 된다.

 

 

중간중간 수정할 부분이 보이지만 전체적인 로직은 여기서 끝!

 

 

 

반응형