Spring-React : 카카오 소셜 로그인 + JWT (1) 카카오 엑세스 토큰 발급 받기

우진·2022년 4월 25일
8
post-thumbnail

(1) 카카오 엑세스 토큰 발급 받기


서론.

해당 프로젝트에서는 오로지 카카오 소셜 로그인 만 사용한다. ( ID/PW 사용안함! )

리액트 프로젝트에서 인가코드를 받아오는 부분은 이 링크✅를 참고하여 구현하면 된다.
지금부터 포스팅할 내용은 프론트에서 인가코드를 받아왔다는 것을 가정하고 진행한다.

Spring 프로젝트와 React 프로젝트의 전체적인 소셜 로그인 프로세스가 궁금하다면 이전 포스팅✅을 참고하길 바란다.


사용한 의존성 🍃

기본 의존성 :
Spring Web
Spring boot DevTools
Lombok
Spring Security
MySQL Driver
spring Data JPA


추가한 의존성 :
jackson-databind
jackson-datatype-jsr310
java-jwt



위의 의존성을 참고하여 Spring 프로젝트를 생성한다.

프론트 프로젝트와 로컬 연동을 완료했다면 Spring Security 관련 설정은 이미 되어있을 것이기 때문에 설명을 스킵한다.

JPA MySQL 등 DB 관련 설정도 다룰 양이 너무 많아지기때문에.. 스킵한다.
( 시간이 되면 클라우드 서버 만드는 법과 DB서버를 Spring 과 연동하는 법을 포스팅할 예정이다! )


1. User 클래스 만들기


경로에 model 패키지를 만들고 그 안에 User 클래스를 만든다.
사용자 정보가 들어가는 DB 테이블과 똑같이 만들어줘야한다.


@Entity 
@Data
@NoArgsConstructor
@Table(name = "user_master") //(1)
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY) //(2)
    @Column(name = "user_code") //(3)
    private Long userCode;

    @Column(name = "kakao_id")
    private Long kakaoId;

    @Column(name = "kakao_profile_img")
    private String kakaoProfileImg;

    @Column(name = "kakao_nickname")
    private String kakaoNickname;

    @Column(name = "kakao_email")
    private String kakaoEmail;

    @Column(name = "user_role")
    private String userRole;

    @Column(name = "create_time")
    @CreationTimestamp //(4)
    private Timestamp createTime;

    @Builder
    public User(Long kakaoId, String kakaoProfileImg, String kakaoNickname,
                String kakaoEmail, String userRole) {

        this.kakaoId = kakaoId;
        this.kakaoProfileImg = kakaoProfileImg;
        this.kakaoNickname = kakaoNickname;
        this.kakaoEmail = kakaoEmail;
        this.userRole = userRole;
    }
}
  1. DB의 테이블명이 클래스명과 다르다면 @Table 어노테이션을 사용해 설정해야한다.
  2. DB의 ID 값을 auto_increment 로 설정했다면 반드시 붙여줘야한다.
  3. DB의 컬럼명이 필드명과 다르다면 @Column 어노테이션을 사용해 설정해야한다.
  4. DB에서 current_timestamp를 설정했다면 반드시 붙여줘야한다.



이렇게 DB의 내용과 잘 맞추고 @Entity 어노테이션만 붙여주면 JPA가 알아서 데이터를 바인딩해주기 때문에 매우 편리해진다!


2. UserRepository 만들기


이번에 만들 것은 정말 간단하다. 왜냐면 JPA에서 모든 것을 알아서 해주기때문..
경로에 Repository 패키지를 만들고 그 안에 UserRepository 인터페이스를 만든다.


// 기본적인 CRUD 함수를 가지고 있음
// JpaRepository를 상속했기 때문에 @Repository 어노테이션 불필요
public interface UserRepository extends JpaRepository<User, Long> {

    // JPA findBy 규칙
    // select * from user_master where kakao_email = ?
    public User findByKakaoEmail(String kakaoEmail);
    
    public User findByUserCode(String userCode);
}


흔히 부르는 DAO 클래스이다. 위의 예시처럼 메소드 이름을 알맞게 짓고 리턴타입, 파라미터값만 잘 작성해주면 간단한 CRUD 쿼리문을 자동 생성후 DB에 접근, 리턴해준다.
깊은 지식 없이 쉽게 사용하기 정말 좋은것 같다! 😍


3. 넘겨받은 인가코드로 카카오 엑세스 토큰 발급 받기


이제부터 조금 복잡해진다. 먼저 카카오 API 공식문서를 좀 들여다봐야한다.



주목해야할 부분은 Request 부분이다.
위와 같은 형식으로 카카오 서버에 요청해야 토큰이 정상 발급되기 때문이다.
문서를 잘 들여다보면서 코드를 짜보자.


3-1. UserController 만들기


경로에 controller 패키지를 만들고 그 안에 UserController 클래스를 만든다.
그리고 아래와 같이 api를 하나 추가한다.


@RestController //(1)
@RequestMapping("/api")
public class UserController {

    @Autowired
    private UserService userService; //(2)

    // 프론트에서 인가코드 받아오는 url
   @GetMapping("/oauth/token") // (3)
   public OauthToken getLogin(@RequestParam("code") String code) { //(4)

       // 넘어온 인가 코드를 통해 access_token 발급 //(5)
       OauthToken oauthToken = userService.getAccessToken(code);

       return oauthToken;
   }

}

  1. jackson 관련 라이브러리를 추가해놓았다면 @RestController 를 붙여준다. 메소드 리턴타입 객체를 json으로 자동 파싱 해준다.
  2. UserService@Autowired 해준다.
  3. 매핑 url은 각자 원하는대로 설정하면 된다.
  4. 프론트에게 쿼리 스트링으로 code(인가코드) 값을 넘겨 받는다.
  5. UserService에 해당 메소드를 만든다.


3-2. UserService 만들기


경로에 service 패키지를 만들고 그 안에 UserService 클래스를 만든다.

@Service
public class UserService {

    @Autowired
    UserRepository userRepository; //(1)
    
    public OauthToken getAccessToken(String code) {

        //(2)
        RestTemplate rt = new RestTemplate();

        //(3)
        HttpHeaders headers = new HttpHeaders();
        headers.add("Content-type", "application/x-www-form-urlencoded;charset=utf-8");

        //(4)
        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
        params.add("grant_type", "authorization_code");
        params.add("client_id", "{클라이언트 앱 키}");
        params.add("redirect_uri", "{리다이렉트 uri}");
        params.add("code", code);
        params.add("client_secret", "{시크릿 키}"); // 생략 가능!

        //(5)
        HttpEntity<MultiValueMap<String, String>> kakaoTokenRequest =
                new HttpEntity<>(params, headers);

        //(6)
        ResponseEntity<String> accessTokenResponse = rt.exchange(
                "https://kauth.kakao.com/oauth/token",
                HttpMethod.POST,
                kakaoTokenRequest,
                String.class
        );

        //(7)
        ObjectMapper objectMapper = new ObjectMapper();
        OauthToken oauthToken = null;
        try {
            oauthToken = objectMapper.readValue(accessTokenResponse.getBody(), OauthToken.class);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }

        return oauthToken; //(8)
    } 
}

  1. 만들어둔 UserRepository@Autowired 해준다.
  2. RestTemplate 객체를 만든다. 통신에 유용한 클래스이다. 클래스에 대해 자세히 알고싶다면 구글에 서치!
  3. HttpHeader 객체를 생성한다. 헤더에 들어가야하는 정보는 공식 문서를 잘 찾아보자.
  4. HttpBody 객체를 생성한다. 바디에도 참 많은..🤤 파라미터가 요구된다. 마찬가지로 공식 문서를 찾아보면 나와있다. Required 항목에 필수라고 체크된 것만 넣으면 된다. 만약 앱을 등록할 때 시크릿 키를 만들었다면 반드시 넣어야 한다.
  5. HttpEntity 객체를 생성한다. 앞서 만든 HttpHeaderHttpBody 정보를 하나의 객체에 담기 위해서이다.
  6. ResponseEntity 객체를 String 형만 받도록 생성해준다. 이유는 응답받는 값이 Json 형식이기 때문이다.
  7. String으로 받은 Json 형식의 데이터를 ObjectMapper 라는 클래스를 사용해 객체로 변환해줄 것이다. 그러기 위해서는 해당 Json 형식과 맞는 OauthToken 이라는 클래스를 만들어 줘야한다(👇아래 참고).
    .readValue(Json 데이터, 변환할 클래스) 메소드를 이용해 바디값을 읽어온다.
  8. Json 데이터가 OauthToken 객체에 잘 담기면 리턴해준다.


3-3. OauthToken 클래스 만들기


만들어둔 model 패키지 안에 oauth 라는 패키지를 추가한다.
그 안에 OauthToken 이라는 클래스를 만든다.


@Data //(2)
public class OauthToken { //(1)
    private String access_token;
    private String token_type;
    private String refresh_token;
    private int expires_in;
    private String scope;
    private int refresh_token_expires_in;

}

  1. 되도록 들어오는 json 객체를 콘솔에 한번 찍어보고 정확히 만드는 것을 추천한다.
  2. @Data 를 붙여서 getter, setter를 잊지않고 만들도록 한다.



도움 받은 영상 :
https://www.youtube.com/c/%EB%A9%94%ED%83%80%EC%BD%94%EB%94%A9


마치며.

여기까지 잘 따라왔다면 UserController 에 만든 api를 동작 시켜보자. 정상적으로 정보를 넣은 상태라면 OauthToken 객체에 값이 잘 담겨 있을 것이다.
다음은 발급받은 카카오 엑세스 토큰으로 카카오 리소스 서버에 접근하여 유저정보를 받아오는 법을 포스팅할 것이다. 많관부많관부~🥳💖

profile
백 개발을 시작한 응애개발자

0개의 댓글