해당 포스팅은 최범균 작가님의 도메인 주도 개발 시작하기 (P.227~230)를 읽고 정리한 글입니다.
권한 검사
권한 검사는 '사용자 U가 기능 F를 실행할 수 있는지' 확인하는 것이고 해당 개념 자체는 복잡한 개념이 아니다.
하지만 개발하는 시스템마다 권한의 복잡도가 다르다. 이런 다양한 상황을 충족하기 위해 스프링 시큐리티같은 프레임워크는 유연하고 확장 가능한 구조를 갖고 있다. 하지만 보안 프레임워크에 대한 이해가 부족하면 프레임워크를 무턱대고 도입하는 것보다 개발한 시스템에 맞는 권한 검사 기능을 구현하는 것이 시스템 유지 보수에 유리할 수 있다.
보안 프레임워크의 복잡도를 떠나 보통 다음 세 곳에서 권한 검사를 수행할 수 있다.
- 표현 영역
- 응용 서비스
- 도메인
표현 영역에서 할 수 있는 기본적인 검사는 인증된 사용자인지 아닌지 검사하는 것이다. URL에 대해 표현 영역은 다음과 같이 접근 제어를 할 수 있다.
- URL을 처리하는 컨트롤러에 웹 요청을 전달하기 전에 인증 여부를 검사해서 인증된 사용자의 웹 요청만 컨트롤러에 전달한다.
- 인증된 사용자가 아닐 경우 로그인 화면으로 리다이렉트 시킨다.
이런 접근 제어를 하기에 좋은 위치가 서블릿 필터이다. 서블릿 필터에서 사용자의 인증 정보를 생성하고 인증 여부를 검사한다. 인증 여부 뿐만 아니라 권한에 대해서 동일한 방식으로 필터를 사용해서 URL별 권한 검사를 할 수 있다. 스프링 시큐리티는 이와 유사한 방식으로 필터를 이용해서 인증 정보를 생성하고 웹 접근을 제어한다.
URL만으로 접근 제어를 할 수 없는 경우 응용 서비스의 메서드 단위로 권한 검사를 수행해야 한다. 스프링 시큐리티의 AOP를 활용해서 서비스 메서드에 권한 검사를 할 수 있다.
public class BlockMemberService {
private MemberRepository memberRepository;
@PreAuthorize("hasRole('ADMIN')")
public void block(String memberId){
...
}
}
개별 도메인 객체 단위로 권한 검사를 해야 하는 경우는 구현이 복잡해 진다. 예를 들어 게시글 삭제는 본인 또는 관리자 역할을 가진 사용자만 할 수 있다고 해보자. 이 경우 게시글 작성자가 본인인지 확인할면 게시글 애그리거트를 먼저 로딩해야 한다. 즉 응용 서비스의 메서드 수준에서 권한 검사를 할 수 없기 때문에 다음과 같이 직접 권한 검사 로직을 구현해야 한다.
public class DeleteArticleService {
public void delete(String userId, Long articleId) {
Article article = articleRepository.findById(articleId); // 애그리거트 로딩
checkArticleExistence(article); // 존재여부 확인
permissionService.checkDeletePermission(userId, article); // 권한 확인
article.markDeleted(); // 삭제 처리
}
}
프레임워크를 원하는 수준으로 확장할 수 없다면, 오히려 도메인에 맞는 권한 검사 기능을 직접 구현하는 것이 바람직하다는 점에 동의한다. 실제로 스프링 시큐리티는 러닝 커브가 높아 적용은 했지만 유지보수가 어려웠던 경험이 있다. 다양한 기능을 제공해 개발 편의성을 높이지만, 처리 범위가 넓은 만큼 오히려 개발자가 내부 동작을 모두 이해하고 유지보수해야 하는 부담이 커지는 경향이 있다고 느꼈다.
'📚 개발자의 서재 > 도메인 주도 개발 시작하기' 카테고리의 다른 글
[DDD] 도메인 서비스 (0) | 2025.05.16 |
---|---|
[DDD] 응용 영역과 표현 영역 -6 (0) | 2025.05.15 |
[DDD] 응용 서비스와 표현 영역 -4 (0) | 2025.05.13 |
[DDD] 응용 서비스와 표현 영역 -3 (0) | 2025.05.12 |
[DDD] 응용 서비스와 표현 영역 -2 (0) | 2025.05.11 |