barded
[어디가게]UserDetails에 저장하는 정보 및 유니크한 프라이머리키와 유니크한 컬럼 간의 쿼리 속도 본문
현재 고객의 클래스는 다음과 같다.
public abstract class User {
@Id
@GeneratedValue
@Column(name = "user_id")
private Long id;
private String name;
private String email;
private String password;
private String phoneNumber;
private String nickname;
//기본 유저 생성시 GUEST로 초기화
@Builder.Default
@Enumerated(EnumType.STRING)
private Role role = Role.GUEST;
@CreatedDate
@Column(updatable = false, nullable = false)
private LocalDateTime createdAt;
@LastModifiedDate
private LocalDateTime updateAt;
public void hashPassword(PasswordEncoder passwordEncoder) {
this.password = passwordEncoder.encode(this.password);
}
public class Customer extends User {
@Enumerated(EnumType.STRING)
private SocialType socialType;
private String socialId;
@OneToMany(mappedBy = "customer", cascade = CascadeType.ALL, orphanRemoval = true)
private List<FavorLiquor> favorLiquors = new ArrayList<>();
@OneToMany(mappedBy = "customer", cascade = CascadeType.ALL, orphanRemoval = true)
private List<FavorCategory> favorCategories = new ArrayList<>();
@OneToMany(mappedBy = "customer", cascade = CascadeType.ALL, orphanRemoval = true)
private List<FavorLocation> favorLocations = new ArrayList<>();
@OneToOne(mappedBy = "customer", cascade = CascadeType.ALL, orphanRemoval = true)
private Point point;
@OneToMany(mappedBy = "customer", cascade = CascadeType.ALL, orphanRemoval = true)
private List<Transaction> transactions = new ArrayList<>();
}
이럴 경우에, Spring Security의 Spring Context에 저장되는 UserDetails객체는 어디까지 저장되어야 하는가? 라는 궁금증이 생겼다.
UserDetails의 구현체인 org.springframework.security.core.userdetails.User를 살펴보자
public class User implements UserDetails, CredentialsContainer {
private static final longserialVersionUID= SpringSecurityCoreVersion.SERIAL_VERSION_UID;
private static final Loglogger= LogFactory.getLog(User.class);
private String password;
private final String username;
private final Set<GrantedAuthority> authorities;
private final boolean accountNonExpired;
private final boolean accountNonLocked;
private final boolean credentialsNonExpired;
private final boolean enabled;
...
}
각각의 정보를 살펴보자
- 사용자 이름(username): 사용자를 식별하는 고유한 값.
- 비밀번호(password): 사용자 인증을 위한 비밀번호.
- 권한(authorities): 사용자에게 부여된 권한 목록, 사용자가 수행할 수 있는 작업을 결정.
- 계정 만료 여부(accountNonExpired): 계정의 만료 여부.
- 계정 잠김 여부(accountNonLocked): 계정이 잠겨있는지 여부
- 비밀번호 만료 여부(credentialsNonExpired): 비밀번호 만료 여부를 나타냄.
- 계정 활성화 여부(enabled): 계정이 활성화 상태인지 나타냄.
User을 보면 사용자의 구분에 필수적인 것들만 있는것을 확인할 수 있다.
따라서 어댑터 패턴을 사용하여 User을 상속한 UserAdapter을 사용하기로 하였다.
@Getter
public class UserAdapter extends org.springframework.security.core.userdetails.User {
private User user;
public UserAdapter(User user) {
super(user.getEmail(), user.getPassword(), Collections.singleton(new SimpleGrantedAuthority(user.getRole().name())));
this.user = user;
}
}
또한 커스텀 어노테이션을 바탕으로 바로 org.springframework.security.core.userdetails.User가 아닌 User엔티티를 가져올 수 있도록 하였다.
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
@AuthenticationPrincipal(expression = "#this == 'anonymousUser' ? null : user")
public @interface AuthUser {
}
이때 User와 관련된 정보를 찾을 때, Primary Key인 user_id와 Unique Column인 email 의 차이에 대해 궁금증이 생겼고 Unique Index에 대해 알게 되었고 이를 비교해보고자 했다.
Unique Index란? Unique Index로 컬럼이 잡혀 있으면 해당 컬럼에는 중복된 데이터가 들어가지 않는다. ndex로 잡혀있는 컬럼이 여러개라면 그 컬럼들의 합이 모두 유일해야만 하나의 레코드가 생성 가능하다.
Unique Index만 사용하여 PK를 정상적으로 생성하지 않으면 데이터 모델에 대한 파악이 힘들다. 뿐만 아니라 원래 PK로 설정되어야할 컬럼에 Null이 포함된 데이터가 있을 수도 있고 참조 무결성 제약 조건을 못 걸게 된다.
Unique Index만을 이용하였을때 장단점 장점
- PK/FK가 존재하지 않아 DBA가 데이터베이스를 관리하기 쉽다.
- 개발 시점에 데이터 제약이 없으므로 개발이 용이하다.
- PK/FK를 이용하지 않기 때문에 성능이 좋아질 수도 있다.
단점
- 데이터 무결성이 깨어질 수 있다.
- 데이터 무결성이 깨어지기 때문에 데이터 전환 작업 시 데이터 정리 작업이 필요하다.
- 데이터 모델과 테이블의 관계가 일치하지 않는다.
- Unique Index는 한 테이블에 여러개 만들 수 있으므로 테이블만 보고 PK가 무엇인지 구분할 수 없다.
Primary Key 사용시의 장점
- 전체 데이터 베이스에 대한 PK/FK관계를 설정할 수 있어 참조 무결성 제약 조건 지정이 가능하다.따라서 참조 무결성을 깨뜨리는 무결성 오류를 방지할 수 있다.
- 유일성을 보장할 수 있다.PK속성에 대해서 NULL을 허용하지 않는다.
- 테이블에 한개의 PK만 허용이 되므로 향후 데이터베이스에서 역공학을 적용하여 데이터 모델을 생성해도 정확하게 PK가 무엇인지 구분이 가능하다.
- FK를 설정하지 않는다면 UI만을 사용하는 것에 비해 성능 저하가 나타나지 않는다.FK를 사용해도 FK인덱스만 적절하게 설정해 준다면 염려할 만큼 과도한 성능저하 현상은 없다.
따라서 결론은 Primary Key를 사용하라는 것이다.
Unique Indexs는 단지 Primary Key에 비해 개발과 유지보수에 약간의 편리함을 제공한다고 한다.
하지만 어떠한 퍼포먼스가 더 빠르냐는 문제점은 테이블의 데이타의 양 및 어떤 분포도를 가지냐에 따라 사례에 따라 천차만별이라고 하니, 속도가 매우 중요한 서비스의 경우에는 직접 비교를 해 보는것이 좋다고 생각한다.
'프로젝트 > 어디가게' 카테고리의 다른 글
[어디가게] 컨트롤러에서 여러 서비스를 불러야 하는경우 (0) | 2024.03.18 |
---|---|
[어디가게]Spring Security단에서 OPEN-SESSION-IN-VIEW 영속성 컨텍스트 (0) | 2024.03.18 |
[어디가게] Spring Security단에서 발생하는 Exception의 처리 불가능 (0) | 2024.03.18 |
[어디가게] @AuthenticationPrincipal 및 Custom Annotation을 사용하여 로그인한 사용자 정보 가져오기 (0) | 2023.12.12 |
[어디가게] 사용자의 역할을 구분하면서 생기는 문제에 대한 테이블 설계 방안 (0) | 2023.11.30 |