Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

트러블 슈팅 #73

Open
road3144 opened this issue Sep 19, 2024 · 3 comments
Open

트러블 슈팅 #73

road3144 opened this issue Sep 19, 2024 · 3 comments
Assignees
Labels

Comments

@road3144
Copy link
Contributor

이번 프로젝트를 하며 겪었던 트러블 슈팅을 적어주세요

@road3144
Copy link
Contributor Author

road3144 commented Sep 19, 2024

트러블 슈팅 : Domain 모듈에서 Pagenation

문제상황

  • 가장 고수준 모듈인 Domain 모듈은 기술적 의존성이 최대한 없어야 함
  • 비즈니스 로직상 Page 정보가 필요한 상황
  • But, Page는 Spring Data에 종속
  • Page 때문에 Domain 모듈이 Spring data에 의존해도 될까 고민

해결 접근

  • Spring Data가 아닌 필요한 Page의 내용을 갖는 Custom Page를 Domain 모듈에 정의
스크린샷 2024-09-19 오후 3 16 15
  • Adapter에서 SpringData Page <-> Custom Page 매핑
스크린샷 2024-09-19 오후 3 17 44
  • 공통 도메인 모듈에 정의해 Pagenation이 필요한 서비스 도메인 모듈에서 사용 가능

@SerenityZenDev
Copy link
Contributor

SerenityZenDev commented Sep 19, 2024

트러블슈팅: 권한 관리 및 인가 처리 개선

문제 상황

  • 기존 프로젝트에서는 권한이 각 API에 명확하게 정의되어 있어, @PreAuthorize를 통해 특정 권한이 있을 때만 접근을 허용하는 방식으로 충분히 처리할 수 있었습니다.
  • 이번 프로젝트에서는 역할(Role)이 다양해졌고, 역할 간의 상하위 관계(계층 구조)가 생기면서 기존 방식으로는 권한을 명확하게 관리하기 어려워졌습니다.
    • 예를 들어, MASTER_ADMIN 권한이 ADMIN 및 그 하위 권한들을 포함하거나, MANAGER가 특정 권한을 상속받는 구조가 필요하게 되었습니다.

해결 접근 방법

  1. Spring Security Context Holder 설정:
    • 먼저, 각 요청에서 받아온 사용자 정보를 바탕으로 Spring Security의 SecurityContextHolder를 설정하였습니다.
    • 이를 통해 사용자 인증 정보를 SecurityContext에 저장하여, 이후 인가 단계에서 접근할 수 있도록 하였습니다.
  2. 기존 방식의 문제점:
    • 기존에는 @PreAuthorize와 함께 hasAuthority를 사용하여 권한을 검증했습니다. 예를 들어, @PreAuthorize("hasAuthority('ROLE_USER')")와 같은 방식으로 인가를 처리했습니다.
    • 하지만, hasAuthority는 역할 간의 상하위 관계를 명확히 표현하지 못하며, 각 권한을 개별적으로 검증해야 하는 문제가 있었습니다.

image

  1. 해결 방안: @PreAuthorizehasRole로 상하위 관계 설정:
    • hasRole을 사용하여 상하위 관계를 반영한 권한 검증을 구현하였습니다. Spring Security에서는 기본적으로 ROLE_ 접두사가 권한에 추가되므로, 이를 통해 역할 계층 구조를 활용할 수 있었습니다.
    • 상위 권한이 하위 권한을 포함하도록 설정하여, 상위 권한 사용자는 하위 권한 API에도 접근할 수 있게 했습니다.
  2. Spring Security의 Role Hierarchy 사용:
    • Spring Security의 RoleHierarchy를 설정하여, 각 역할 간의 상하위 관계를 명확히 정의했습니다.

    • 예시 설정:
      image

    • 위 설정을 통해, ROLE_MASTER_ADMIN은 ROLE_ADMIN, ROLE_MANAGER, ROLE_USER의 모든 권한을 자동으로 상속받게 되며, 인가 처리 시 복잡한 권한 검증 없이 상위 권한 사용자가 하위 권한의 API에 접근할 수 있도록 했습니다.

  3. 인가 처리 개선: @PreAuthorize와 hasRole 사용:
    • 역할 계층이 적용된 후, @PreAuthorize에서 hasRole을 사용하여 인가를 간소화할 수 있었습니다.

    • 예시 코드:
      image

    • hasRole('ADMIN')을 통해 ROLE_ADMIN뿐만 아니라 상위 권한인 ROLE_MASTER_ADMIN도 이 API에 접근할 수 있게 되었습니다.

성과 및 교훈

  • 이번 개선을 통해 각 권한의 상하위 관계를 명확히 설정할 수 있었으며, 권한이 많아지더라도 유지보수가 용이해졌습니다.
  • 인가 처리에서 중복된 권한 검증 로직을 줄이고, 상위 권한 사용자가 하위 권한의 기능에 접근할 수 있게 하여 사용자 경험을 향상시켰습니다.
  • Spring Security의 RoleHierarchy를 통해 역할 간의 관계를 명확히 정의함으로써, 코드의 가독성과 유지보수성을 높였습니다.
    이러한 트러블슈팅 과정을 통해 복잡한 권한 구조에서도 효율적으로 인가를 관리할 수 있는 방식을 도입할 수 있었고, 향후에도 비슷한 문제에 대한 해결 방법을 제시할 수 있게 되었습니다.

@Hyyena
Copy link
Contributor

Hyyena commented Sep 19, 2024

트러블 슈팅

Situation

  • POST 응답 시 데이터 생성 날짜 필드가 null 로 담기는 이슈

Task

원인분석

  • 트랜잭션이 걸린 데이터 생성 비즈니스 로직 메서드 내부에서 save()를 통해 엔티티를 저장하고 있었음
  • 데이터 생성 날짜 컬럼은 Hibernate가 제공하는 @CreationTimestamp 애노테이션을 통해 데이터베이스 삽입 시점에 생성되는 데이터
  • 트랜잭션이 걸린 메서드에서 추가적인 조회 쿼리 없이 영속성 컨텍스트에 저장된 캐시를 그대로 반환하고 있었고, 트랜잭션 내부에서 save 호출 시 persist()를 통해 엔티티를 1차 캐시에 저장한 뒤 쓰기 지연이 발생하여 트랜잭션이 커밋(flush(), commit()) 되기 전까지는 실제 데이터베이스에 INSERT 쿼리가 발생하지 않기 때문에 트랜잭션 내부에서 리턴하고 있는 엔티티는 실제 쿼리가 발생하지 않은 엔티티이기 때문에 데이터베이스 삽입 시점에 생성되는 날짜 컬럼이 null로 존재하여 최종적으로 null 값이 담긴 응답을 수행하게 됨

Action

해결방안

  1. 트랜잭션을 걸지 않음으로 쓰기 지연을 발생시키지 않고 즉시 데이터베이스에 반영한다
  2. 트랜잭션이 커밋된 후 별도의 트랜잭션에서 추가적인 조회 쿼리를 발생시켜 날짜 컬럼을 조회한다
  3. 응답 시 날짜 필드를 제거한다

Result

  • 1번과 2번의 해결 방법은 응답 데이터에 반드시 날짜 필드가 들어가야 하는 경우에 고려해 볼 만한 방법이고, 3번 해결방법은 API 응답 스펙을 변경함으로써 간단히 해결 가능
  • 1번의 경우 해당 비즈니스 로직에 기능이 추가되더라도 데이터 일관성을 위해 트랜잭션을 유지하고 싶기 때문에 선택하지 않음
  • 2번의 경우 추가적인 조회 쿼리를 수행하는 것은 불필요하다고 생각해 선택하지 않음
  • 최종적으로 현재 요구 사항에서 응답 스펙에 날짜 컬럼이 반드시 필요한 이유가 존재하지 않기 때문에, API 응답 스펙을 변경하는 것으로 해당 이슈 해결

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: Backlog
Development

No branches or pull requests

3 participants