게시판 고도화

Single Ko·2023년 6월 28일
0

공부하며 정리

목록 보기
4/17

고도화를 통해 추구하는 목표

  1. DB 마이그레이션 (MySQL -> PostgreSQL)
  2. 대댓글
  3. 해시태그 기능 개선
  4. 카카오톡 로그인 (OAuth 2.0 + KAKAO login)
  5. 기능 배포 결정과 취소(롤백)
  6. Hashicorp Vault
  7. Swagger UI - Springdoc-openapi

기존의 EqualsAndHashCode에서의 직접 필드 접근을 getter 로 받아오게 바꿨음.

  • 프록시 객체를 사용하는 하이버네이트의 지연 로딩을 고려하여, 값 비교를 제대로 수행하지 못하는 일이 없도록 하기 위해 바꾸었음.

  • Spring Data JPA로 엔티티를 다룰 때, 엔티티 데이터는 하이버네이트 구현체가 만든 프록시 객체를 이용하여 지연 로딩될 수 있다. 따라서 엔티티를 조회할 때 필드에 직접 접근하면 id == null 인 상황이 있을 수 있고, 이러면 올바른 비교를 하지 못 하게 된다. getter를 사용하면 이러한 문제를 예방할 수 있다. (Lombok으로 EqualsHashCode를 사용할때 잘 살펴보자..)

N+1이 그 자체로 문제는 아니다. (의도하지 않은 쿼리가 나가는 것이 문제라는 뜻.. 만약 의도대로 나간다면 문제는 없다!!)

cascde 걸때 ..

  • CascadeType.PERSIST => INSERT
  • CascadeType.MERGE => MERGE
    이 외에도 ALL이라던가 REMOVE라던가 다양한 옵션이 있다.
 @JoinTable(
            name = "article_hashtag",
            joinColumns = @JoinColumn(name = "articleId"),
            inverseJoinColumns = @JoinColumn(name = "hashtagId")
    )
  • ManyToMany 관계에서의 조인 테이블 작성.(why? -> manyTomany는 중간 테이블이 하나 생기는데 이 테이블에 대한 설정이 필요하다는 뜻이다. name을 지정하지 않으면 자동으로 이름이 생기기때문에 이상한 이름이 마음대로 생김... 조심~~

도메인을 바꾸게 되면 그 파급력이 엄청나게 크다.

DB 마이그레이션

스프링은 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는 바로 커밋을 날리고 메시지도 만들어 줌.

AuditingFields

추상클래스의 Auditing class, 각 필드는 상속받는 자식 엔티티에서 접근 및 수정이 가능해야 한다. 접근 제어자를 protected로 바꾸었다. (private -> protected)

당장은 문제가 되지 않았으나, 회원 도메인에서 인증이 없는 상태의 회원 정보를 저장하기 위해서 작성자, 수정자를 엔티티가 직접 작성해야하는 상황이 있을 것이므로 접근 제어자를 수정하게 되었다.

OAuth Login

중요한 기능이다.. 요즘 대부분 구현하는 기능..

기존의 회원 가입을 통해 관리하는 것은 회원의 관리 주체가 우리다. 즉 우리가 데이터베이스에 회원 정보를 법과, 해킹등에 대해 대처하며 관리해야 한다.

OAuth 2.0 -> 인증 주체와 책임을 외부 서비스에 위임. 큰, 믿을만한 실력있는 회사에 맞기는 것이다.

카카오 개발자 페이지

kakao developers 페이지로 가야 된다. 여기서 제공하는 기능에선 로그인 뿐만 아니라 카카오톡 소셜, 메시지, 지도/로컬 , 카카오내비, 카카오 스토리등 다양한 기능을 받아서 사용 할 수 있다.

문서 부분에 이런 기능들을 사용하는 방법에 대해 소개를 해 놓았다.

  1. 내 애플리케이션 -> 애플리케이션 추가 ( 앱이름, 아이콘, 사업자명 등..)

  2. 만들어진 애플리케이션으로 들어가게되면 앱키를 볼 수 있다.

    • 네이티브 앱 키 (스마트폰)
    • REST API 키
    • JavaScript 키 (프론트앤드 단)
    • Admin 키
  3. 애플리케이션 밑에 플랫폼 설정 -> Android , iOS, Web 등..

    • Web으로 할거기 때문에 우리는 그것을 누르고, 사이트 도메인을 넣으면 된다.
    • redirect uri를 넣어야 된다. (OAuth 2.0을 사용하기 위해선 스펙상 요구됨)

Spring 공식 문서를 보면 Setting the redirect URI가 나온다. -> 공식 문서에서 어떤 형식으로 등록해야되는지 URI 형식도 다 나와 있다.

  1. Web을 등록하면 바로 밑에 Redirect URI 등록이 나온다. registrationId는 서비스 프로바이더 Id를 넣어주면 된다.
    • github, google, apple, microsoft 등 세계적으로 유명한 회사들은 이미 등록이 되어 있음..
    • kakao는 우리나라에선 유명하지만 세계적으로 쓰이는 것이 아니라서 우리가 등록해서 사용해야된다.
  1. 메뉴 -> 동의항목
    우리가 서비스하면서 받았으면 하는 항목들을 동의를 통해 받아 올 수 있다. 카카오에서 관리하고 있는 개인정보들을 받아 올 수 있음!!
  • 필수 동의, 선택 동의 등을 선택 가능. (필수는 하나만 선택 가능하다한다)
  1. 클라이언트 시크릿 키 ( 메뉴 -> 보안)
    REST API인 경우 토큰을 발급 해준다. (발급 받으면 됨!)

위의 작업은 KAKAO Developers에서 카카오 로그인 서비스를 이용하기 위한 작업이고 이제 코드를 통해 우리 서비스에 한번 카카오 로그인 서비스를 집어 넣어 보겠다.

코드 작업

  1. 먼저 OAuth2 Client 라이브러리를 추가해주자.

  2. 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 는 메서드 체이닝 형식으로 많이 이어지고 있다. 다만 점점 람다식을 활용한 표현법이 늘어나고 있다.
메서드 체인 형식보다 더 가독성도 높아지고, 필요 코드 수도 줄어드는 장점이 있다.

Swagger

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'
  • localhost:8080/swagger-ui.html
  • Swagger ui를 통해 다양한 정보를 넣을 수 있는데, 이때 Swagger에서 지원하는 애노테이션을 넣어서 붙여 넣을 수 도 있다. 하지만 이렇게 된다면 swgger에 대한 의존성이 생기게 됨..
  • 이를 완벽히는 아니지만 좀 대체 가능한 방법이 바로 javadoc을 이용하는 것이다. 라이브러리에 openapi-javadoc, runtime-java-doc을 넣은 것을 추가하게 되면 javadoc이 자동으로 파싱되어 swgger ui에 올라가게 된다. 이를 이용해 가이드를 넣어 줄 수도 잇음.
  • 물론 이 기능은 swgger 자체에서 지원하는 애노테이션보단 지원 능력이 떨어 질 수 있지만, 순수한 javadoc의 기능을 사용하는 것이기 때문에 의존성과 관련되어 순수성을 유지 가능.
profile
공부 정리 블로그

0개의 댓글