S3와 관련해서는 매번 기계적으로 코드를 작성했는데
이번에 한번 관련 내용들을 정리해본다.
처음에는 경로 뒤에 유저 닉네임+AUTO_INCREMENT 느낌으로 넣어줘도 되지 않나? 싶었다.
그런데, 만약에 서버가 여러개가 된다고 하면 서버간 식별값이 충돌하기 때문에 동기화를 해줘야 했다.
또, AUTO_INCREMENT는 규칙이 너무 뻔해서 외부에서 규칙을 알게되면 url에 바로 접근할 수 있다는 문제가 있다. 그래서 이를 식별하지 못하게끔 랜덤값을 넣어주는 게 좋겠다고 생각했다.
이번에 스노우플레이크를 쓰기로 했다. UUID는 128비트이고, 스노우플레이크는 64비트라서 더 짧다.
(UUID로 만든 ID-18자리)
(스노우플레이크로 만든 ID-14자리)
코드는 다음과 같다.
//2024-10-29-0-0-0가 기준 시간
private final long baseTimestamp = 1730160000000L;
private final long machineId = 1L;
private static final AtomicLong sequence = new AtomicLong();
private static final int MACHINE_ID_BITS = 10;
private static final int SEQUENCE_BITS = 12;
public long generateId(Long currentTimestamp) {
long timestamp = currentTimestamp - baseTimestamp;
return (timestamp << MACHINE_ID_BITS + SEQUENCE_BITS) | (machineId << SEQUENCE_BITS) | value(sequence.getAndIncrement(), SEQUENCE_BITS, 0);
}
private long value(long value, int bits, int shift) {
long mask = (((1L << bits) - 1) << shift);
return (value & mask) >> shift;
}
s3에는 여러 파일 확장자를 올릴 수 있어서 미리 제한하는 것이 필요했다.
그래서, 화이트 리스트를 사용하기로 했다.
우선 파일 확장자를 jpg/jpeg/png/heic로만 제한해둔다.
이렇게 하면 파일의 크기를 10MB 이하로만 받게 할 수 있다.
한번 더 사이즈를 검증해주고
mimeType 타입이 "image/"인 경우만 유효한 것으로 판단한다.