728x90
유저 역할(Role) 부여 기능 구현기
1. 도입
서비스에서 회원 가입을 완료한 사용자에게는 기본 사용자 권한을 자동으로 부여해야 한다.
또한, 추후 운영 도중 관리자가 특정 사용자에게 역할(Role) 을 부여하거나 변경할 수 있도록 확장 가능한 구조가 필요하다.
이 글에서는 권한을 어떻게 관리할 것인지, 그리고 이를 코드로 어떻게 구성했는지를 정리한다.
2. 설계 목표
- 사용자에게
기본 권한을 자동 부여한다. - 관리자는 특정 사용자에게
역할을 수동으로 부여할 수 있다. - 일반 사용자는 권한을 부여할 수 없어야 한다.
- 구조적으로 권한 변경 책임은
AuthService가 아닌 별도 서비스가 담당한다.
3. 설계 고려사항
| 고려 항목 | 판단 |
|---|---|
| 권한은 몇 개까지 가질 수 있는가? | 1인 1역할로 제한 |
| 권한은 어디서 정의하는가? | enum으로 관리 (UserRoleType) |
| 권한 변경 책임은 누가 가지는가? | UserRoleGrantService 에 위임 |
| 권한 변경 시 부여자 로그는 필요한가? | 필요. grantedBy, grantedAt 저장 |
| 향후 확장이 쉬운가? | enum → 테이블로 이전할 수 있도록 캡슐화 구조 설계 |
4. 구현 설명
4.1 UserRole Entity 구조
@Entity
@IdClass(UserRoleId.class)
public class UserRole {
@Id
@JoinColumn(name = "user_id")
@ManyToOne(fetch = LAZY)
private User user;
@Enumerated(EnumType.STRING)
private UserRoleType role;
private Long grantedBy;
private LocalDateTime grantedAt;
}
- 1인 1역할 구조
grantedBy,grantedAt필드로 추적 가능
4.2 권한 enum
public enum UserRoleType {
ADMIN,
USER,
GUEST
}
4.3 역할 부여 서비스 분리
@Service
@RequiredArgsConstructor
public class UserRoleGrantService {
private final UserRoleRepository userRoleRepository;
public void grantDefaultRole(User user) {
userRoleRepository.save(
new UserRole(user, UserRoleType.USER, 0L, now())
);
}
public void grantRole(User user, User granter, UserRoleType role) {
ensureGranterHasPrivilege(granter);
UserRole targetRole = userRoleRepository.findByUser(user)
.orElseThrow(() -> new AuthException(USER_ROLE_NOT_FOUND));
targetRole.setRole(role);
targetRole.setGrantedBy(granter.getId());
targetRole.setGrantedAt(LocalDateTime.now());
userRoleRepository.save(targetRole);
}
private void ensureGranterHasPrivilege(User granter) {
UserRole granterRole = userRoleRepository.findByUser(granter)
.orElseThrow(() -> new AuthException(UNAUTHORIZED_ROLE_ASSIGNMENT));
if (granterRole.getRole().equals(UserRoleType.USER) || granterRole.getRole().equals(UserRoleType.GUEST)) {
throw new AuthException(UNAUTHORIZED_ROLE_ASSIGNMENT);
}
}
}
5. 테스트 전략
- 유저 가입 시
grantDefaultRole()이 자동 실행되는지 검증 - ADMIN이 USER에게 권한을 부여할 수 있는지 테스트
- 일반 사용자가 권한 부여 시도 시 예외 발생 확인
- 존재하지 않는 유저에게 권한 부여 시 예외 발생 확인
→ 단위 테스트에서 AuthService, UserRoleGrantService 각각에 대한 책임을 분리 테스트했다.
6. 회고 및 확장 가능성
좋았던 점
- 권한 로직을
UserRoleGrantService로 캡슐화하여AuthService가 복잡해지지 않았다. - enum 기반으로 구현했지만 enum 내부가 아닌 서비스 단에서 분기 로직을 다룸으로써 향후 테이블 기반으로의 전환이 쉬움.
- 부여 주체(
grantedBy)를 남기면서 감사 로그 측면에서도 대응할 수 있게 설계함.
향후 확장 가능성
UserRoleType을 DB 테이블로 전환 가능 (Role,Permission,UserRoleMapping)- 다중 역할 보유가 필요해질 경우 →
@ManyToMany구조 변경 - 관리자 페이지에서 권한 부여 기록을 로그로 추적하거나 보여주는 기능 연동 가능
마무리
권한(Role) 관리 기능은 단순한 구조처럼 보이지만, 보안과 서비스 확장의 핵심에 있는 기능이다.
이번 설계에서는 기본적인 역할 부여 기능을 빠르게 구현하면서도, 역할 변경 책임을 분리함으로써 향후 확장에 유리한 구조를 만들고자 했다.
728x90
'BindProject' 카테고리의 다른 글
| [Backend]Auth모듈: 인증 시스템 설계와 구현 -FIN-!! (0) | 2025.06.19 |
|---|---|
| [Backend] Auth모듈 : 유저 탈퇴 처리 (1) | 2025.06.19 |
| [Backend] Auth모듈 :사용자 등록 로직의 책임 분리와 유효성 검사 개선 (2) | 2025.06.18 |
| [Backend] AUTH모듈 : 초기 세팅 (0) | 2025.06.18 |
| [Backend] Auth모듈 : Validator 만들기 (0) | 2025.06.18 |