본문 바로가기

공부 자료/Spring

[Springframework] Naver API를 이용한 회원가입 및 로그인

Springframework에서 Naver API를 이용한
로그인 및 회원가입을 통한 정보 불러오기

 

 

 

웹사이트를 제작하다 보면 홈페이지 자체 회원가입도 존재하지만,

요즘에는 소셜을 이용한 로그인도 필수일 정도로 대부분의 사이트에서 구현되어 있는 기능이다.

지난번에는 Kakao API를 이용한 회원가입, 로그인 및 회원 정보를 가져오는 블로깅을 하였는데

이 중 네이버 API를 이용한 로그인 및 회원 정보를 가져올 수 있는 방법에 대해 알아볼 예정이다.

 

* API안의 내용이 많겠지만, 예시의 편의를 위해 이름(닉네임)과 이메일만 가져올 예정이다.

다른 정보를 가져오기 위한 방법은 이름과 이메일을 가져오는 방식과 동일하기 때문에 개인적으로 실습해 보기를 바란다!

 

 

[준비하기]

이번에도 네이버 개발자 선터를 통해 애플리케이션 등록은 먼저 해야 API를 사용할 수 있다.

 

 

1. 네이버 개발자 센터 접속하기

 

https://developers.naver.com/main/

 

NAVER Developers

네이버 오픈 API들을 활용해 개발자들이 다양한 애플리케이션을 개발할 수 있도록 API 가이드와 SDK를 제공합니다. 제공중인 오픈 API에는 네이버 로그인, 검색, 단축URL, 캡차를 비롯 기계번역, 음

developers.naver.com

 

 

2. 상단의 Application에서 애플리케이션 등록 선택

 

 

 

3. 애플리케이션 내용 입력 후 등록하기

애플리케이션 정보 등록

 

- 사용 API에서 '네이버 로그인' 선택 시 나오는 정보 입력하기

 

- 애플리케이션을 어떤 환경(PC)에서 사용할지 선택 후 도메인 입력 후 저장

* Redirec URL은 로그인 후 돌아갈 URL을 지정하면 된다.

도메인 등록

 

 

3. 등록 후 나오는 Client_ID와 Client_Secret 저장해 놓기

- 만약 API 등록 시 입력한 내용을 변경해야 하는 경우 여기서 변경할 수 있음

 


 

여기까지 등록했다면, 이제 이 API를 활용하여 회원가입 및 로그인을 구현할 수 있다.

전체적으로 API를 사용하는 방법은 Kakao API를 사용했던 방법과 다르지 않기 때문에 

이를 이해하고 있다면 크게 어렵지 않을 것이다.

 

자세한 방법은 네이버 개발자센터에서 제공하는 API 명세서를 참고하면 된다.

https://developers.naver.com/docs/login/api/api.md

 

네이버 로그인 API 명세 - LOGIN

네이버 로그인 API 명세 네이버 로그인 API는 네이버 로그인 인증 요청 API, 접근 토큰 발급/갱신/삭제 요청API로 구성되어 있습니다. 네이버 로그인 인증 요청 API는 여러분의 웹 또는 앱에 네이버

developers.naver.com

 

 


 

[코드작성]

 

 

1. 네이버 로그인 인증 요청(인가 코드 요청)

- 네이버의 경우 로그인 인증 요청에 성공할 경우 Code를 발급해주고, 이를 이용해 토큰을 발급 받을 수 있다.

- Client_ID에는 위에서 애플리케이션 등록 시 받은 Client_ID를 사용하면 된다.

- 네이버의 경우에는 State를 함께 입력해 요청을 진행해야 하는데 해당 State는 네이버 로그인 인층 요청에 있는 예시의 State를 이용했다. (state = hLiDdL2uhPtsftcU)

 

 

[login.jsp]

<%@ page language="java" contentType="text/html; charset=UTF-8"
         pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>

<html>
<body>

<a href="https://nid.naver.com/oauth2.0/authorize?response_type=code&client_id=Client_ID&redirect_uri=http://localhost:8080/naverLogin&state=hLiDdL2uhPtsftcU
">
    <img src="kakaoLogin.png"/>
</a>

</body>
</html>

 

 

인가 코드를 잘 받아왔는지는 Controller를 통해 확인해 볼 예정이며,

해당 Controller는 인가 코드 확인을 위한 코드로 추후 변경할 예정이다.

 

 

[NaverLoginController.java]

@Controller
public class NaverLoginController {

    @GetMapping("/naverLogin")
    @ResponseBody
    public String naver(@RequestParam String code, @RequestParam String state){
        System.out.println(code);
        System.out.println(state);
        return code;
    }
}

 

 

(1) 네이버에 로그인 인증 요청

 

 

(2) 인가 코드 확인하기

- 동의 후 게속하기 버튼을 클릭하면 요청 시 보낸 Redirect_URL이 http://localhost:8080/kakaoLogin 였기 때문에 해당 (2)의 컨트롤러 매핑이 코드를 받게 된다.

 

@RequestParam을 이용해 code와 state를 가져오면 토큰 요청 준비가 끝난 것이다.

 


 

2. code, state를 이용한 토큰 요청

 

[KakaoLoginService.java]

@Service
public class NaverLoginService {

	// 토큰 요청 메서드
    public String token(String code, String state) throws Exception {
    	// (1)
        String clientId = "/*Client_ID*/";
        String clientSecret = "/*Client_Secret*/";
        String redirectURI = URLEncoder.encode("http://localhost:8080/naverLogin", "UTF-8");

        // (2) 토큰 요청을 위한 URL 생성
        StringBuilder apiURL = new StringBuilder("https://nid.naver.com/oauth2.0/token?");
        apiURL.append("grant_type=authorization_code&");
        apiURL.append("client_id=").append(clientId);
        apiURL.append("&client_secret=").append(clientSecret);
        apiURL.append("&redirect_uri=").append(redirectURI);
        apiURL.append("&code=").append(code);
        apiURL.append("&state=").append(state);

        // (3) 토큰 URL 접속
        URL url = new URL(apiURL.toString());
        HttpURLConnection con = (HttpURLConnection)url.openConnection();

        // 메서드 지정
        con.setRequestMethod("GET");
        int responseCode = con.getResponseCode();

        BufferedReader br;
        System.out.print("responseCode="+responseCode);
        if(responseCode==200) { // 정상 호출
            br = new BufferedReader(new InputStreamReader(con.getInputStream()));
        } else {  // 에러 발생
            br = new BufferedReader(new InputStreamReader(con.getErrorStream()));
        }
        
        String inputLine;
        StringBuffer res = new StringBuffer();
        while ((inputLine = br.readLine()) != null) {
            res.append(inputLine);
        }
        br.close();

		// (4) 토큰 응답 확인
        System.out.println(res.toString());

        // 에러 처리 진행
        if(responseCode!=200) {
            throw new Exception(res.toString());
        }
        
        String token = res.toString();
        
        // (5) 토큰에서 필요한 토큰들만 가져오기
        JSONParser parser = new JSONParser();
        JSONObject tokenAll = (JSONObject) parser.parse(token); // 가져온 데이터를 json 형태로 파싱 진행
        String access = (String) tokenAll .get("access_token");
		
        return access;
    }
}

 

 

요청 URL

 

(1) 애플리케이션 등록 후 받은 Client_ID와 Client_Secret을 입력

 

 

(2) 요청시 필요한 정보 설정

- 네이버 로그인의 경우 토큰 요청에 필요한 정보들을 파라미터에 넣어서 보내기 때문에 URL 설정 후 요청

 

 

 

(3) 토큰을 받기 위한 URL을 통해 접속하여 openConnection() 메서드를 이용해 HttpURLConnection의 인스턴스 생성

 

- URLConnection에 대한 설명은 아래를 참고하길 바람!

https://kcode-recording.tistory.com/319

 

[JAVA] URL을 통해 서버와 통신하는 URLConnection/HttpURLConnection

JAVA 애플리케이션과 URL 을 연결해주는 클래스 URLConnection과 HttpURLConnection URLConnection/HttpURLConnection 이란? URLConnection은 Java 애플리케이션과 URL을 연결해주는 수퍼 클래스로, 일반 URL에 대한 API를 제

kcode-recording.tistory.com

 

 

(4) 토큰에 대한 정보를 잘 받아왔는지 확인하기

네이버에서 제공한 예시

 

 

(5) access 토큰 추출하기

- 해당 토큰 중 access_token만을 받아 요청 시 사용할 예정이므로 JSON을 파싱하여 access_token 정보만 가져오기

 

- JSON 파싱에 대한 정보를 아래 블로깅을 참고하기 바람

https://kcode-recording.tistory.com/325

 

[Spring] Spring Json 파싱해서 값 가져오기

JSON에서 원하는 값을 가져오기 위한 parsing 데이터를 요청하고 받아올 때 JSON 형태를 많이 이용하는데, JSON에서 자신이 원하는 값을 가져오기 위한 방법을 정리하고자 한다. JSON의 형태는 아래와 M

kcode-recording.tistory.com

 


 

3. 사용자 정보 받아오기

[KakaoLoginService.java]

// 사용자 정보 요청
public UserInfo info(String token) throws Exception {
		
     // (1) 사용자 인증 요청
     URL url = new URL("https://openapi.naver.com/v1/nid/me");
     HttpURLConnection conn = (HttpURLConnection) url.openConnection();
     conn.setRequestMethod("GET");
     conn.setRequestProperty("Authorization","Bearer " + access);
     
     BufferedReader br;
     int resultCode = conn.getResponseCode();
     System.out.println(resultCode);

     if(resultCode>=200 && resultCode<+300){ // 정상인 경우
        br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
     }else{ //에러
         br = new BufferedReader(new InputStreamReader(conn.getErrorStream()));
     }

     StringBuilder responseBuilder = new StringBuilder();
     String line;
     
     while((line=br.readLine()) != null){
        responseBuilder.append(line);
     }
     
     br.close();   
     conn.disconnect();
     
     // (2) 요청한 정보 확인
     System.out.println(responseBuilder.toString());
     
     // (3) 필요한 정보 파싱하기
     JSONParser parsing = new JSONParser();      
     JSONObject info = (JSONObject) parsing.parse(responseBuilder.toString());
     System.out.println(info.toJSONString());
     
     JSONObject naverInfo = (JSONObject) info.get("response");
     String email = (String)naverInfo.get("email");
     String nickName = (String)naverInfo.get("name");
        
     UserInfo userInfo = new UserInfo();

     userInfo.setEmail(email);
     userInfo.setNickName(nickName);
		
     return userInfo;
}

 

 

(1) 사용자 기본 정보 요청하기

 

 

(2) 받아온 응답 확인하기

- 해당 응답은 기존에 사용자 동의 받은 정보만 가져올 수 있으며, 가져올 정보에 대한 선택은 네이버 개발자센터에서 수정 가능

 

 

(3) 이름과 이메일만 추출하기 위해 JSON 파싱하기

- JSON에 대한 파싱은 토큰에서 사용한 파싱 방법과 동일하며, 더 자세한 내용은 아래 블로깅을 참고하길 바란다.

- 추출한 정보는 리턴

 

- https://kcode-recording.tistory.com/325

 

[Spring] Spring Json 파싱해서 값 가져오기

JSON에서 원하는 값을 가져오기 위한 parsing 데이터를 요청하고 받아올 때 JSON 형태를 많이 이용하는데, JSON에서 자신이 원하는 값을 가져오기 위한 방법을 정리하고자 한다. JSON의 형태는 아래와 M

kcode-recording.tistory.com

 


[최종 코드]

 

* login.jsp는 처음 코드와 동일

 

[NaverController.java]

@Controller
public class NaverLoginController {

    @GetMapping("/naverLogin")
    public String naver(@RequestParam String code, @RequestParam String state, Model model){
        try{
            UserInfo userInfo = naverLoginService.naverLogin(code, state);
            model.addAttribute("userInfo", userInfo);
            session.setAttribute("user", userInfo);
            return "naverCallback";
        }catch (Exception e){
            e.printStackTrace();
            System.out.println(e.getMessage());
            return e.getMessage();
        }
    }
}

 

 

 

[NaverLoginService.java]

@Service
public class NaverLoginService {

    @Autowired
    private UserDao userDao;

    public UserInfo naverLogin(String code, String state) throws Exception{
        String accessToken = token(code, state);
        UserInfo loginInfo = info(accessToken); // api에서 가져온 회원 정보

        UserInfo userInfo = userDao.selectUserByNaver(loginInfo.getEmail()); // DB에 존재 여부 확인

        // 존재하지 않을 경우 디비에 insert 진행 및 userInfo에 대입
        if(userInfo == null){
            userDao.insertUserNaver(loginInfo);
            userInfo = loginInfo;
        }

        return userInfo;
    }

    public String token(String code, String state) throws Exception {
        String clientId = "WRDDsf6VYopAr3VsX_f5";
        String clientSecret = "zkeCPJmyfa";
        String redirectURI = URLEncoder.encode("http://localhost:8080/naverLogin", "UTF-8");

        // 토큰 요청을 위한 URL 생성
        StringBuilder apiURL = new StringBuilder("https://nid.naver.com/oauth2.0/token?");
        apiURL.append("grant_type=authorization_code&");
        apiURL.append("client_id=").append(clientId);
        apiURL.append("&client_secret=").append(clientSecret);
        apiURL.append("&redirect_uri=").append(redirectURI);
        apiURL.append("&code=").append(code);
        apiURL.append("&state=").append(state);

            // 토큰 URL 접속
            URL url = new URL(apiURL.toString());
            HttpURLConnection con = (HttpURLConnection)url.openConnection();

            // 메서드 지정
            con.setRequestMethod("GET");
            int responseCode = con.getResponseCode();

            BufferedReader br;
            System.out.print("responseCode="+responseCode);
            if(responseCode==200) { // 정상 호출
                br = new BufferedReader(new InputStreamReader(con.getInputStream()));
            } else {  // 에러 발생
                br = new BufferedReader(new InputStreamReader(con.getErrorStream()));
            }

            String inputLine;
            StringBuffer res = new StringBuffer();
            while ((inputLine = br.readLine()) != null) {
                res.append(inputLine);
            }
            br.close();

            System.out.println(res.toString());

            // 에러 처리 진행
            if(responseCode!=200) {
                throw new Exception(res.toString());
            }
        
         // 토큰에서 필요한 토큰들만 가져오기
        JSONParser parser = new JSONParser();
        JSONObject tokenAll = (JSONObject) parser.parse(token); // 가져온 데이터를 json 형태로 파싱 진행
        String access = (String) tokenAll .get("access_token");
        //String refresh_token = (String) tokenAll.get("refresh_token");
        
         return access;
    }

    public UserInfo info(String token) throws Exception {
        URL url = new URL("https://openapi.naver.com/v1/nid/me");
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        conn.setRequestMethod("GET");
        conn.setRequestProperty("Authorization","Bearer " + access);

        BufferedReader br;
        int resultCode = conn.getResponseCode();
        System.out.println(resultCode);

        if(resultCode>=200 && resultCode<+300){ // 정상인 경우
            br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
        }else{ //에러
            br = new BufferedReader(new InputStreamReader(conn.getErrorStream()));
        }

        StringBuilder responseBuilder = new StringBuilder();
        String line;
        while((line=br.readLine()) != null){
            responseBuilder.append(line);
        }
        br.close();
        conn.disconnect();

        System.out.println(responseBuilder.toString());

        JSONParser parsing = new JSONParser();
        JSONObject info = (JSONObject) parsing.parse(responseBuilder.toString());
        System.out.println(info.toJSONString());

        JSONObject naverInfo = (JSONObject) info.get("response");
        String email = (String)naverInfo.get("email");
        String nickName = (String)naverInfo.get("name");

        UserInfo userInfo = new UserInfo();

        userInfo.setEmail(email);
        userInfo.setNickName(nickName);

        return userInfo;
    }
}

 

 

이 외에 필요한 기능도 네이버에서 제공하는 API를 참고하면 크게 어렵지 않을 것이다!