게시글
질문&답변
카카오토큰관련
안녕하세요. 질문 답변드립니다.예전에 작업하실 때는 아마 spring oauth2 client 같은 라이브러리를 사용하셨을 겁니다.해당 라이브러리에 기능이 이미 추상화되있고 설정만 진행하면 되는 것이죠.내부적으로는 저희가 진행한 카카오토큰을 발급 받고 카카오토큰을 이용해서 카카오에 가입된 회원 정보를 불러오고 있습니다.실제 현업에서 일을 하시다보면 현재 강의에서처럼 API 문서를 보고 API를 호출해보고직접 연동해야하는 일들이 빈번합니다. 그리고 이렇게 직접 연동해보지 않으면 사용하시는 라이브러리가 어떻게동작하는지에 대한 이유는 알 수 없고, 그냥 이렇게 설정하면 되는구나하고 넘어가게됩니다.직접 카카오 API 문서를 보고 소셜로그인을 붙여 본다면 우리가 사용하고 있는 spring oauth2 client 같은라이브러리도 내부적으로는 다 이런 과정들을 통해서 연동하고 있음을 알 수 있고, 꼭 소셜 로그인 API가아니더라도 카카오나 네이버 구글 등에서 제공하는 API들을 연동해보는 즐거움을 느껴보실 수 있을 겁니다.(ex) open ai 이미지 생성 api 연동, 구글 text to speech api 등등등또 하나 헷갈리시는거 같은 개념을 짚어 드리면 JWT와 카카오토큰의 역할이 아래와 같이 다릅니다.- JWT 발행 : 우리가 제공하는 API를 사용하기위한 인증 토큰- 카카오토큰: 카카오가 제공하는 API를 사용하기 위한 인증 토큰.카카오에서 회원정보를 가져와서 우리 서비스에 회원 가입을 시키기 위해서 카카오토큰을 발행함.
- 0
- 2
- 13
질문&답변
OAUTH2 질문
안녕하세요. 질문 주신 내용 하나씩 답변드립니다.1. 로그인시도 -> Securty -> FILTER 사용자가 DB에있으면 OK -> JWT발급 이 흐름이 맞는지요..?흐름은 맞고 DB에 사용자 유무 관계없이 JWT는 항상 발급합니다. JWT를 우리가 제공하는 서비스를 사용하기 위한 일종의 열쇠같은 역할이라고 생각해주시면 됩니다.해당 열쇠를 API 호출 시 같이 전달해야 인증이 필요한 API들을 사용할 수 있다고 봐주시면 됩니다.2. oauth2 회원 가입 필요 이유oauth 는 회원 가입할 때 필요한 정보들을 고객들이 직접 입력하지 않아도 쉽게 가져오고 추가로 필요한 정보들만 입력 받을 수 있다는 장점이 있습니다.(간편 회원 가입). 또한 카카오나 네이버같은 소셜 회원 가입 기능을 제공하는 곳에서 사용자에 대한 인증을 해주기 때문에 실명인증 등 따로 저희가 구현해야하는 기능들도 훨씬 적어집니다.3. 회원 가입이 필요한 이유소셜 로그인은 회원 가입 및 로그인을 좀 더 쉽게 도와주는 역할을 한다고 생각해주시면 됩니다.사용자가 복잡한 회원 가입 과정을 거치지 않아도 쉽게 가입을 할 수 있는 것 입니다.또한 저희 서비스에 가입을 시켜야 예를 들어 게시글을 쓴다고 했을 때 어떤 사용자가 게시글을 썼는지 회원 id를 지정해줄 수 있을테고, 일반적인 서비스라면 회원 DB를 직접 관리해서 이벤트를 한다고했을 때 해당 회원의 아이디로 push알림을 보내준다던가 기타 기능 등을 구현할 수 있을 것 입니다.또한 회원 가입을 하지 않는다면 현재 우리 서비스의 회원이 몇명인지에 대한 기본적인 것들도 알 수 없을 것 입니다.4. 만약 사용자정보가 저장이 최초에 된다면 그다음부터는 그냥 oauth2로그인으로 안타는건지 그냥 security의 로그인을 타는건지 궁금합니다.저장이 된 이후에도 소셜 로그인을 진행 시 회원 정보를 가져오고 해당 회원이 이미 가입이 되어있다면 로그인이 되었다는 의미로JWT만 사용자한테 발급합니다. security 로그인이라는게 스프링 시큐리티를 말씀하시는거 같은데 현재 강의에서는 security 관련한 코드는 없습니다!5. openfeign를 쓰셔서 코드를 받고 그 코드로 요청을 보내서 토큰을 받고 그 토큰으로 사용자정보를 받는걸로 이해를 했습니다. 시큐리티에서는 해당과정이 없는걸로 알고있는데 맞는지요스프링 시큐리티에서는 아이디와 비밀번호를 입력하면 해당 정보를 세션을 통해서 관리합니다.시큐리티만 사용한다면 위에 말씀하신게 맞고, 스프링 시큐리티와 oauth를 다 사용하신다면JWT를 사용자한테 발급 후 사용자가 토큰을 보냈을 때 해당 토큰에 있는 정보를 통해서 세션에 현재 로그인한 사용자의 정보를 유지하는 등 함께 사용하는 방법도 있습니다.
- 0
- 2
- 16
질문&답변
auditing
@EntityListeners(value = {AuditingEntityListener.class}) 어노테이션의 경우 현재 BaseEntity, BaseTimeEntity 클래스에 선언해두었습니다. 해당 어노테이션 사용 시 jpa의 이벤트가 발생할 때 추가로 처리를할 수 있도록 도와주는 기능입니다.@CreatedDate, @LastModifiedDate 어노테이션을 생성시간과 업데이트시간 필드에 선언해두었는데 저장 및 업데이트 시 해당 리스너에 의해서 생성 시간과 업데이트 시간이 세팅되서 db에 저장된다고 봐주시면됩니다.@EntityListeners(value = {AuditingEntityListener.class}) @MappedSuperclass @Getter public abstract class BaseTimeEntity { @CreatedDate @Column(updatable = false) private LocalDateTime createTime; @LastModifiedDate private LocalDateTime updateTime; }BaseEntity의 경우 등록자와 수정자 필드를 가지고 있는데 스프링 빈으로 등록한 AuditorAwareImpl 에 의해서 현재 요청한 API의 URI 정보를 자동으로 등록해줍니다.이런 편의 기능 덕분에 저희가 코드상에서 직접 생성시간/수정시간/등록자/수정자를 세팅하는 번거로움을 덜 수 있습니다.@EntityListeners(value = {AuditingEntityListener.class}) @MappedSuperclass @Getter public abstract class BaseEntity extends BaseTimeEntity { @CreatedBy @Column(updatable = false) private String createdBy; @LastModifiedBy private String modifiedBy; }
- 0
- 1
- 8
질문&답변
전역에러처리질문
안녕하세요! http status로 상태는 알 수 있지만 정확히 어떤 에러가 발생한건지는 알기가 쉽지 않습니다.API에서 400 http status를 반환하는 예외가 3개가 있다면 어떤 오류가 발생했는지 알기가 쉽지 않습니다.서버의 api를 사용하는 클라이언트측이 특정 오류일 경우 별도 처리를 해야한다고 했을 때 http status만으로는 확인이 어렵습니다. 또한 오류메세지로 예외 처리를 한다면 오류 메세지가 바뀔 경우 대응이 불가능합니다.따라서 오류 메세지와는 별개로 오류 코드를 관리한다면 클라이언트에서도 대응하기 훨씬 편합니다. 고객이 오류가 발생했을 때 오류 코드를 준다면 해당 오류 코드를 발생시키는 코드를 쉽게 찾을 수도 있습니다. http status의 현재는 각 오류마다 어떤 http status를 던져야할지를 정의하고 있지만 enum 에서 http status는 관리하지 않고 AuthenticationException 이면 항상 401, BusinessException이면 500, EntityNotFoundException면 400 등 예외로도 관리할 수 있고 상황에 맞게 관리를 하시면 됩니다.
- 0
- 2
- 8
질문&답변
토큰 발급 관련 문의 드립니다.
안녕하세요! 카카오개발자 센터의 공식 문서에서는 토큰 발급 api 요청 시 content-type을 "application/x-www-form-urlencoded;charset=utf-8" 로 데이터를 전달하라고 되어있습니다. 말씀해주신 @RequestBody, @ModelAttribute 등 으로 호출해보시면 아시겠지만 카카오 서버에서 처리할 수 없어서 오류가 발생할 것입니다.content-type을 "application/x-www-form-urlencoded;charset=utf-8" 로 전달한다는 것을 http 메세지를 아래의 예시처럼 보낸다는 것 입니다.body 본문을 보시면 쿼리파라미터처럼 key1=value1&key2=value2 처럼 데이터를 보내고 있는데 이 방식이 바로 "application/x-www-form-urlencoded;charset=utf-8" 로 보내는 방식입니다. POST /oauth/token HTTP/1.1Host: https://kauth.kakao.comContent-Type: application/x-www-form-urlencoded grant_type=authorization_code&client_id=123456&redirect_uri=http://localhost:8080/oauth/kakao/callback&client_secret=1234&code=123452 따라서 카카오 API 서버에서 지원하지 않는 http 메세지 형식으로 보낸다면 해당 서버에서 처리를 하지 못하기 때문에 오류가 발생할 수도 입니다. 그리고 예시로 주셨던 코드의 경우 consumes에 APPLICATION_FORM_URLENCODED_VALUE 를 지정해주셨는데 consume의 경우 우리 서버가 받을 contenty-type을 명시합니다.APPLICATION_FORM_URLENCODED_VALUE은 저희가 카카오로 보낼 데이터 타입이구요!@PostMapping(value = "/oauth/token", consumes = APPLICATION_FORM_URLENCODED_VALUE)KakaoTokenResponse requestKakaoToken(@RequestBody KakaoTokenRequest request); 아래처럼 카카오 서버로 부터 받는 응답을 application/json으로 수정 후 요청 한다고 했을 때 @RequestBody의 경우 request의 데이터를 http body에 json으로 전달합니다.@PostMapping(value = "/oauth/token", consumes = "application/json")KakaoTokenResponse requestKakaoToken(@RequestHeader("Content-Type") String contentType, @RequestBody KakaoTokenRequest request);http 메세지는 아래 예시처럼 전송이 될 것입니다. 이번에는 http body의 데이터 형식이 key1=value1 형식이 아니라 json으로 전송이 될 것이고 카카오 서버에서는 "application/x-www-form-urlencoded" 형태로 데이터를 보내라고 했는데 저희가 마음대로 데이터를 json 형식으로 보내게 된것이구요! 그래서 해당 서버가 메세지를 정상적으로 읽을 수 없어서 오류가 발생할 것 입니다. POST /oauth/token HTTP/1.1Host: https://kauth.kakao.comContent-Type: application/json {"grant_type": "authorization_code","client_id": "123123123123","redirect_uri": "http://localhost:8080/oauth/kakao/callback","code": "123123123123123","client_secret": "3124123123123"} @ModelAttribute와 아무 어노테이션도 사용하지 않고 보냈을 때는 둘다 json 형태로 데이터를 전달하는 것으로 로그를 확인했고 application/json은 카카오 토큰 발급 api에서 처리할 수 없어서 오류가 발생했습니다.@PostMapping(value = "/oauth/token", consumes = "application/json")KakaoTokenResponse requestKakaoToken(@ModelAttribute KakaoTokenRequest request); @PostMapping(value = "/oauth/token", consumes = "application/json")KakaoTokenResponse requestKakaoToken(KakaoTokenRequest request);
- 0
- 2
- 47
질문&답변
이 흐름이 맞을까요??
안녕하세요! 이해한 내용이 맞습니다! 먼저 카카오로부터 카카오서비스를 이용하기 위한 토큰을 발급 후 카카오에 등록된 회원 정보를 이용하여 우리 서비스에 회원 가입도하고, 이미 가입된 경우라면 회원 가입 절차 없이 JWT를 발급합니다.JWT에는 인증 정보가 담겨져있기 때문에 Authorizaion Header에 넣어서 전송하면 인증이 필요한 API의 경우 토큰을 검사하여 정상적인 토큰이라면 요청한 API를 수행합니다.
- 0
- 2
- 67
질문&답변
OpenFeign을 어떤 상황에서 어떻게 사용하는지 감이 안옵니다...
안녕하세요! 실제 서비스를 만들다보면 외부 API를 사용하는 경우가 많습니다. 예를 들어서 뒤에서 구현하는 소셜 로그인의 경우도 카카오 API를 호출해야하기 때문에 feign client를 통해서 API를 요청하고 응답을 받아서 활용합니다. 실무에서는 타회사와 협업을하게 된다면 타 회사가 제공하는 API를 호출해야하는 케이스도 빈번하구요! 규모가 어느정도 되는 회사라면 단일 어플리케이션이 아니라 도메인별로 서버도 분리되어 있는 경우가 많은데 그럴 경우 내부 서버간 통신에도 활용합니다.
- 0
- 2
- 107
질문&답변
5:23분 테스트 결과 관련 문의드립니다.
스프링부트 버전이 올라가면서 없는 API를 호출할 경우 NoResoucrFoundException 예외를 발생시키도록 바뀐거 같습니다. NoResoucrFoundException을 따로 ExceptionHandler로 처리 해주고 있지 않아서 Exception을 처리하는곳에서 처리가 됐습니다. GlobalExceptionHanlder에 아래 예외를 추가해주면 404로 오류를 반환할 것 입니다.@ExceptionHandler(NoResourceFoundException.class) protected ResponseEntity handleNoResourceFoundException(NoResourceFoundException e) { log.error("NoResourceFoundException", e); ErrorResponse errorResponse = ErrorResponse.of(NOT_FOUND.toString(), "Requested resource not found."); return ResponseEntity.status(NOT_FOUND).body(errorResponse); } 그리고 ExceptionHandler가 먼저 수행되는건 서버 자기 자신한테 요청하기 때문에 자신한테 없는 API이기 때문에 GlobalExceptionHandler에서 먼저 처리를 하고, FeignClientExceptionErrorDecoder 에서는 에러 응답을 받은 후 처리하기 때문에 2번째로 처리가 됐습니다. 8081 서버를 하나 더 띄우고 (사진)8081 서버로 /api/health2 를 요청한다면 8080서버에서는 ExceptionHandler에서 오류 처리를 안하고, FeignClientExceptionErrorDecoder에서만 에러를 처리합니다. 8081 서버는 GlobalExceptionHandler에서 오류 로그를 남기고 반환할 오류 응답을 만들 것 입니다.(사진)
- 0
- 3
- 123
질문&답변
5:23분 테스트 결과 관련 문의드립니다.
안녕하세요 지수님! 강의 잘 듣고 계시 감사합니다!혹시 깃허브링크를 남겨주실 수 있으실까요?
- 0
- 3
- 123
질문&답변
도메인형 패키지 구조 질문
안녕하세요! 도메인 주도 개발이라고해서 꼭 특정 패키지 구조로만 해야 도메인 주도 개발인 것은 아니긴해서 말하기 조심 스러운 부분이 있긴하네요! 단순히 controller / service/ dto 기반으로 화면단위로 개발하는것보다는 도메인 주도 개발쪽에 가깝다고는 생각합니다.
- 0
- 1
- 153