Spring Security에서 UserDetails 인터페이스의 추상 메서드는 여러 인증과정에 사용됩니다. 따라서, 어플리케이션에서 사용하는 회원 엔티티는 반드시 UserDetails와 연관지어 사용해야 합니다. 회원 엔티티를 Member라 하면 Member는 UserDetails의 코드를 재사용해야 되는 상황입니다.
1. 상속을 사용한 Member 엔티티 코드
@Getter
@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@EntityListeners(AuditingEntityListener.class)
public class Member implements UserDetails {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(name = "provider_id", nullable = true)
private Long providerId;
@Column(updatable = false, nullable = false)
private String email; // 타입이 다르면 중복 가능
@Column(name = "password", nullable = true)
private String password;
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return this.roles.stream()
.map(r -> r.getValue().getType())
.map(SimpleGrantedAuthority::new)
.toList();
}
@Override
public String getUsername() {
return String.valueOf(id);
}
@Override
public String getPassword() {
return password;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return usable;
}
엔티티 내부 코드가 너무 복잡해져 직관성이 떨어진다는 큰 문제가 있었습니다. 더 나아가 SRP도 지켜지지 않는 느낌을 받았습니다. (특히, 인증과정에서 엔티티가 사용되는게 어색했습니다.) 따라서, 합성을 사용해 책임을 분리하자는 생각을 했습니다.
2. 합성을 이용
public class MemberDetails implements UserDetails {
private final Member member;
public MemberDetails(final Member member) {
this.member = member;
}
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return List.of(new SimpleGrantedAuthority("ROLE_USER"));
}
@Override
public String getPassword() {
return null;
}
@Override
public String getUsername() {
return member.getEmail();
}
@Override
public boolean isAccountNonExpired() {
return false;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
덕분에 Member 엔티티 내부 코드의 직관성이 높아졌으며 행동을 기준으로 객체를 분리하니 엔티티가 여러 곳에서 사용되는 것을 막을 수 있었습니다.
Spring Security에서
UserDetails
인터페이스의 추상 메서드는 여러 인증과정에 사용됩니다. 따라서, 어플리케이션에서 사용하는 회원 엔티티는 반드시UserDetails
와 연관지어 사용해야 합니다. 회원 엔티티를Member
라 하면Member
는UserDetails
의 코드를 재사용해야 되는 상황입니다.1. 상속을 사용한
Member
엔티티 코드엔티티 내부 코드가 너무 복잡해져 직관성이 떨어진다는 큰 문제가 있었습니다. 더 나아가 SRP도 지켜지지 않는 느낌을 받았습니다. (특히, 인증과정에서 엔티티가 사용되는게 어색했습니다.) 따라서, 합성을 사용해 책임을 분리하자는 생각을 했습니다.
2. 합성을 이용
덕분에
Member
엔티티 내부 코드의 직관성이 높아졌으며 행동을 기준으로 객체를 분리하니 엔티티가 여러 곳에서 사용되는 것을 막을 수 있었습니다.