고도화를 통해 추구하는 목표
기존의 EqualsAndHashCode에서의 직접 필드 접근을 getter 로 받아오게 바꿨음.
프록시 객체를 사용하는 하이버네이트의 지연 로딩을 고려하여, 값 비교를 제대로 수행하지 못하는 일이 없도록 하기 위해 바꾸었음.
Spring Data JPA로 엔티티를 다룰 때, 엔티티 데이터는 하이버네이트 구현체가 만든 프록시 객체를 이용하여 지연 로딩될 수 있다. 따라서 엔티티를 조회할 때 필드에 직접 접근하면 id == null
인 상황이 있을 수 있고, 이러면 올바른 비교를 하지 못 하게 된다. getter를 사용하면 이러한 문제를 예방할 수 있다. (Lombok으로 EqualsHashCode를 사용할때 잘 살펴보자..)
N+1이 그 자체로 문제는 아니다. (의도하지 않은 쿼리가 나가는 것이 문제라는 뜻.. 만약 의도대로 나간다면 문제는 없다!!)
cascde 걸때 ..
@JoinTable(
name = "article_hashtag",
joinColumns = @JoinColumn(name = "articleId"),
inverseJoinColumns = @JoinColumn(name = "hashtagId")
)
도메인을 바꾸게 되면 그 파급력이 엄청나게 크다.
스프링은 DB와 관련된 connection을 추상화 해두었기 때문에, DB를 바꾸어도 바뀐 DB로 잘 작동을 해야된다 (물론, 실제로는 어려움.. 실무의 DB는 단순하지 않기 때문에), 우리가 만든 서비스는 규모가 작기 때문에 그나마 DB를 마이그레이션 하기 쉬울 것이다.
MySQL -> PostgreSQL
MySQL은 많이 사용해봤음..
PostgreSQL은 별로 사용을 많이 안해봤는데, 커멘드라인에서 psql이라는 것을 통해서 사용 가능
psql postgres username (username은 별다른 설정을 안했다면 컴퓨터 유저 이름으로 들어감)
실제 라이브러리에서 jdbc 경로만 바꿔 주면 됨!
이슈에서 이슈를 만들 수 있다.
생각보다 기능이 커서 따로 이슈로 만들어서 관리 하고 싶을때, 바로 이슈로 만들어서 새롭게 관리 가능.
Entity에는 스팩상 final 키워드를 쓰지마라고 권고한다.
Rebase Merge의 경우, 복사가 일어난다. (기존의 브랜치에서 마치 개발이 일어난 듯한 모습을 보여주는 것)
롤백도 변경이다. 즉 개발이다..
롤백을 하게된다면 효율적으로 무사히 할 수 있어야 한다.
git revert로 이전 커밋으로 돌아 갈 수 있다.
깃크라켄에서는 revert를 하면 Yes / No -> No는 하지 않는 다는게 아니다. 커밋을 아직 바로 날리지 않는다는 뜻. yes는 바로 커밋을 날리고 메시지도 만들어 줌.
추상클래스의 Auditing class, 각 필드는 상속받는 자식 엔티티에서 접근 및 수정이 가능해야 한다. 접근 제어자를 protected로 바꾸었다. (private -> protected)
당장은 문제가 되지 않았으나, 회원 도메인에서 인증이 없는 상태의 회원 정보를 저장하기 위해서 작성자, 수정자를 엔티티가 직접 작성해야하는 상황이 있을 것이므로 접근 제어자를 수정하게 되었다.
중요한 기능이다.. 요즘 대부분 구현하는 기능..
기존의 회원 가입을 통해 관리하는 것은 회원의 관리 주체가 우리다. 즉 우리가 데이터베이스에 회원 정보를 법과, 해킹등에 대해 대처하며 관리해야 한다.
OAuth 2.0 -> 인증 주체와 책임을 외부 서비스에 위임. 큰, 믿을만한 실력있는 회사에 맞기는 것이다.
kakao developers 페이지로 가야 된다. 여기서 제공하는 기능에선 로그인 뿐만 아니라 카카오톡 소셜, 메시지, 지도/로컬 , 카카오내비, 카카오 스토리등 다양한 기능을 받아서 사용 할 수 있다.
문서 부분에 이런 기능들을 사용하는 방법에 대해 소개를 해 놓았다.
내 애플리케이션 -> 애플리케이션 추가 ( 앱이름, 아이콘, 사업자명 등..)
만들어진 애플리케이션으로 들어가게되면 앱키를 볼 수 있다.
애플리케이션 밑에 플랫폼
설정 -> Android , iOS, Web 등..
Spring 공식 문서를 보면 Setting the redirect URI가 나온다. -> 공식 문서에서 어떤 형식으로 등록해야되는지 URI 형식도 다 나와 있다.
위의 작업은 KAKAO Developers에서 카카오 로그인 서비스를 이용하기 위한 작업이고 이제 코드를 통해 우리 서비스에 한번 카카오 로그인 서비스를 집어 넣어 보겠다.
먼저 OAuth2 Client 라이브러리를 추가해주자.
Yml에서 설정을 해야된다. 크게 2가지 서비스 프로바이더와 레지스트레이션을 잡아야 한다.
spring:
security:
oauth2:
client:
registration:
kakao:
client-id: id
client-secret: key
authorization-grant-type: authorization_code
redirect-uri: "{baseUrl}/login/oauth2/code/kakao"
client-authentication-method: POST
provider:
kakao:
authorization-uri: https://kauth.kakao.com/oauth/authorize
token-uri: https://kauth.kakao.com/oauth/token
user-info-uri: https://kapi.kakao.com/v2/user/me
user-name-attribute: id
카카오는 스프링이 미리 정의한 프로바이더는 아니기때문에 우리가 직접 넣어줘야 된다.
OAuth Grant Type을 검색하면 공식 홈페이지에서 OAuth가 지원하는 타입들을 볼 수 있다.
reirect-uri에서 그냥 도메인이 들어나고 있는 것이 마음에 안든다. 이것을 감출 수 있는 기술도 지원한다. 스프링 OAuth 문서에서 볼 수 있음.
yml 파일에서는 문자열로 인식시키기 위해서는 " "로 묶어줘야됨. 아니면 {baseUrl}을 특별한 것으로 인식한다.
밑의 provider kakao의 정보는 카카오 디벨로퍼 공식 문서를 확인해서 넣자. (지금은 그걸 넣었지만.. 바뀔수 있다.)
맨 밑의 아이디는 인증 정보를 불러오면 데이터를 바디로 불러오는데, 여러가지 프로퍼티를 받아 올 수 있는데, 우리는 유저 네임을 무엇을 알고 싶기때문에 그것을 확인하기 위한 식별자 정보를 넣어줘야 된다.
우리는 이제 로그인 서비스를 카카오를 통해 받아 올 수 있다. 그런데 DB 기반 인증 방식을 하고 있기 때문에 글을 쓰거나, 댓글을 쓸대는 여전히 DB를 참조한다.
해결 방법
1. OAuth 인증 서버를 통해 받은 정보를 DB에 저장해 해결
2. 매번 인증 할때 마다 OAuth 정보를 서버에 요구하는 것
1번의 방식으로 풀어 보겠다 -> 그렇다면 첫 인증은 여전히 카카오가 해준다고 하더라고, 회원 테이블이 계속 필요하다.
기존의 유저 entity는 DB에서 검증을 하는 방식이기에,createby 나 modifiedBy가 security를 타고 알아서 들어가게 만들어 뒀지만, OAuth2를 사용하면 최초의 가입 시점에선 이것이 안되기 때문에 우리가 넣어줘야된다
기존의 Security 인증을 위해 만들었던 BoardPrincipal을 업데이트 해줘야된다. OAuth2User 클래스를 상속받아 구현하면 된다.
@Override public Map<String, Object> getAttributes() { return oAuth2Attributes; }
@Override public String getName() { return username; }
카카오 Rest API로 사용자 호출을 했을때, 카카오에서 가져오는 데이터는 카카오 디벨로퍼 문서에서 볼 수 있다. 그렇다면 이런 데이터를 받는 Dto를 우리는 만들어 줘야 된다.
그 후, OAuth 인증을 할 수 있는 기능을 추가해야 한다.
기존의 SpringSecurity 는 메서드 체이닝 형식으로 많이 이어지고 있다. 다만 점점 람다식을 활용한 표현법이 늘어나고 있다.
메서드 체인 형식보다 더 가독성도 높아지고, 필요 코드 수도 줄어드는 장점이 있다.
springdoc-openapi 를 사용하여 swagger ui를 붙인다.
springdoc 홈페이지를 들어가면 잘 소개되어 있다. 찾아보자
implementation 'org.springdoc:springdoc-openapi-ui:1.6.14'
implementation 'org.springdoc:springdoc-openapi-javadoc:1.6.14'
annotationProcessor 'com.github.therapi:therapi-runtime-javadoc-scribe:0.15.0'