JPA에 기본 키를 설정하는 방법 중 하나인 UUID에 알아보고자 한다.
기본 키는 데이터베이스에서 각 레코드를 유일하게 식별하는 중요한 요소이다.
지금까지 나는 모든 프로젝트에 AUTO_INCREMENT 전략을 사용하여 기본키를 자동 증가하는 숫자로 설정해 왔는데 요즘 이 방법은 기본 키 값이 예측이 가능하기 때문에 보안상 문제가 될 수 있다고 생각이 들었다.
예시로 내 식별 id가 만약 11이라면 전에 등록한 사용자의 식별 id는 9일 것이다.
그래서 대안책을 찾아보던 중 UUID를 기본 키로 사용하는 방법이 눈에 띄어 UUID에 대해서 알아보고 JPA에 적용해보고자 한다.
74512f5a-354c-4ec1-8c0e-c5ad7c3abe9fUUID는 크게 4가지 버전이 있는데 UUID의 버전에 대해서는 따로 찾아보도록하고 나는 주로 사용되는 방식인 UUIDv4 버전을 사용할 것이다.
해당 버전은 랜덤 데이터를 기반으로 하기 때문에 예측이 어렵고, 충돌 가능성이 매우 낮다.
이제 UUID에 대해서 알아봤으니 JPA에 적용해보도록 하자
JPA에서 UUID를 기본 키로 설정하는 방법은 다음과 같다.
@Id
@GeneratedValue(generator = "uuid2")
@GenericGenerator(name="uuid2", strategy = "uuid2")
@Column(name = "user_uuid", columnDefinition = "BINARY(16)", updatable = false, nullable = false)
private UUID userId;
위의 코드의 설명이다.
@Id : 'userId'필드를 기본키로 지정
@GeneratedValue(generator = "uuid2") : 기본 키 값을 생성하기 위해 "UUID"라는 생성기를 사용
@GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator") : Hibernate의 UUIDGenerator 전략을 사용하여 UUID를 생성하는 생성기를 정의, UUIDGenerator는 UUIDv4 방식을 사용하여 고유한 UUID 값을 생성
@Column(name = "user_uuid", columnDefinition = "BINARY(16)", updatable = false, nullable = false) : userId 필드를 데이터베이스의 user_uuid 열에 매핑
columnDefinition = "BINARY(16)" 속성은 UUID를 16바이트의 바이너리 데이터로 저장하도록 지정, updatable = false는 기본 키 값이 생성된 후 수정될 수 없음을 의미하며, nullable = false는 이 필드가 null 값을 가질 수 없음을 의미이렇게 설정하고 db에 값을 넣어보니
다음과 같이 바이너리 값으로 잘 들어가는 것을 확인할 수 있다.

위와 같이 작성했을때 경고가 뜨는데 해당 경고는

GenericGenerator가 hibernate 6.5버전에서 deprecated 되었다는 것이어서 어노테이션을 바꿔 주었다.
@Id
@UuidGenerator
@Column(name = "user_uuid", columnDefinition = "BINARY(16)", updatable = false, nullable = false)
private UUID userId;
다음과 같이 했을떄 로그를 찍어봐도 잘 나오는 것을 확인할 수 있다.

UUID 값으로 조회했을때도 잘 되는 것을 확인
{
"userId": "217C1C43-E2E0-41E3-A56D-C8E79716D687"
}

아까의 설정에서 columnDefinition = "BINARY(16)" 해당 항목을 꼭 넣어 주어야 하는데
해당 항목을 빼고 넣는다면 DB에서 자동으로 255길이로 생성하여 16자리를 넘어가는 값은 0으로 채워버려서 아예 다른 값이 되어버린다.
다른 블로그를 찾아보면 위와 같은 사례를 많이 찾아볼 수 있다.
이렇게 기본 키로 UUID를 적용해 봤는데 큰 어려움은 없었다.
물론 UUID를 기본 키로 사용하면서 조회 속도가 느려지는 등의 단점도 분명히 존재하겠지만 보안적인 측면에서는 이점이 분명히 존재하기 때문에 해당 방식을 이번에 진행하는 프로젝트에 적용하기로 했다. 그리고 UUID를 사용하면서 발생하는 단점들을 최소화하는 방법을 계속해서 찾을 생각이다.
또한 실제 사용하면서 어떤 문제가 발생할지는 아직 알 수 없지만 발생하는 모든 이슈들을 해당 블로그에 기록하고 해결 방안을 공유할 예정이다.
유용해용