아하 REST API 서버 개발 (6)

finallee
aha.official
Published in
7 min readJan 24, 2019

UUID4

DB 를 다루다보면 구글이나 도서에서 많이들 PKauto increment 값으로 사용하고 있습니다. (실제로도 PKauto increment 로 사용해야 하는게 좋습니다!)

문제는 auto increment 로 생성된 PK 를 그대로 url 과 같은 공개된 장소에 노출 시킨다는 것입니다.

이는 곧 예측 가능한 모델이 되어버리기 때문에 크롤링이나 인젝션 공격에 좀 더 취약할 수 밖에 없는 결과를 낳게 됩니다.

그렇기 때문에 클라이언트가 접근할 수 없는 서버 소스단에서는 auto increment PK 값으로 데이터에 접근하고 public 한 클라이언트 단에서는 예측 불가능하고 random 한 index 체계를 사용하는 것이 좋습니다.

저는 그래서 그런 체계를 보장할 수 있는 UUID 체계를 사용하도록 권장합니다.

자세한 내용은 링크로 첨부하니 한번씩 읽어보시면 좋습니다.

UUID (범용 고유 식별자) 는 네트워크 상에서 서로 모르는 객체들을 식별하고 구별하기 위해 각각의 고유한 이름을 부여하기 위해 고안된 기술입니다.

이 고유한 이름은 말 그대로 고유성이 매우 중요한데요, 왜냐하면 같은 이름을 가지는 객체가 존재하면 구별이 불가능해 지기 때문입니다.

UUID 는 표준에만 따라 구현한다면 고유성을 정말 거의!! 완벽하게 보장할 수 있는 멋진 방법입니다. 겹칠 확률이 거의 지구에서 걸어가다 운석에 맞을 확률이라고 하며, 표현할 수 있는 객체의 갯수는 최대 340,282,366,920,938,463,463,374,607,431,768,211,456개 라고 합니다.

340,282,366,920,938,463,463,374,607,431,768,211,456개??????

UUID 에는 여러가지 종류가 존재하지만 timestamp 기반으로 생성하는 UUID4 를 가장 많이 사용합니다.

nodejs 에서 UUID4 를 사용하기 위해서는 간단히 uuid4 패키지만 설치하시면 됩니다.

npm install uuid4

자 설치하셨으면 UUID4 를 한번 생성해 보도록 하겠습니다.

쨔잔 uuid4 인 값 a48ebc52–8755–4e74–93e4–44e6c0f2f180 이 생성 되었습니다.

Ordered UUID

사실 생성된 UUID 값을 그대로 id 사용하는 것은 적절치 않습니다. UUID 는 보통 다음의 구조를 가집니다

xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

총 32개의 16진수 문자열과 4개의 ‘-’ 를 사용해 연결되어 있습니다.

그래서 뭐가 문제냐구요?

UUID 는 일단 난수성 (randomness 한글로 정확한 단어가 뭘까요?) 을 보장받는 체계입니다.

uuid_1 다음에 생성되는 uuid_2 가 문자열 정렬 기준으로 다음에 오는 것이 아니란 말입니다.

또한, UUID 는 바이너리 값으로 치환하기에 매우 곤란한 ‘-’ 문자열이 존재합니다.

즉, UUID 값을 순수하게 저장하기 위해선 string 형태로 저장을 해야 하는데 DB 에서 string 데이터를 인덱싱 하는 것은 절대로 추천하지 않습니다.

인덱스도 비정상적으로 커질 뿐 아니라, 실제로 검색 성능도 많이 떨어지기 때문입니다.

따라서 UUID 계열 값을 인덱싱 가능하고 순서를 보장받는 체계로 변경해야 하는데 그 방법은 다음의 링크에 아주 자세하게 나와 있습니다.

위의 글을 한줄로 요약하자면 UUID 의 구조를 아래와 같이 변경하면 인덱싱이 가능한, 순서를 ‘어느정도' 보장받는 수 체계로 변환할 수 있다고 합니다.

1-2-3-4-5  ->  32145

즉, 위에서 생성된 a48ebc52–8755–4e74–93e4–44e6c0f2f180

a48ebc52–8755–4e74–93e4–44e6c0f2f1803: 4e74
2: 8755
1: a48ebc52
4: 93e4
5: 44e6c0f2f180
=> 4e748755a48ebc5293e444e6c0f2f180

4e748755a48ebc5293e444e6c0f2f180 로 변경해서 사용하면 auto increment 값을 사용하는 것과 비슷한 수준의 인덱싱 성능을 보장받을 수 있다고 합니다.

그럼 이제 DB 에 써먹을 수 있는 방법을 알았으니 얼른 모듈을 하나 만들어 봅시다.

src/utils/uuid.js

자 그럼 잘 동작하는지 한번 테스트해 볼까요?

잉???

하… 제가 뭘 잘못한걸까요?

에러 로그를 자세히 뜯어보니 import 구문이 어쩌고 하는군요… 이건 현재 node 버전이 ES2015 이상 스펙을 완벽하게 지원하지 못해서 발생하는 문제입니다.

그럼 바벨을 통해 실행하면 되지 않느냐고 하실지도 모르겠지만 cli 를 이용해서 node 를 직접 실행하는 것은 현재 아쉽게도 babel 을 적용할 방법이 없습니다.

자 그럼 이 녀석이 잘 동작하는지 확인하는 방법은 Test 를 적용하는 방법 밖에는 없겠군요! 신나는 마음으로 테스팅 환경을 세팅하도록 합시다!

걸려들었어!

Jest

Nodejs 에는 수 많은 테스팅 프레임워크가 존재합니다. 많이들 들어보셨겠지만 Mocha, Chai, Should, Jest … 모든 프레임워크를 열거하기엔 시간이 부족하므로 가장 폭넓게 사용되고 테스팅의 종합선물세트라고 불리는 Jest 를 사용해 테스팅 환경을 구축해 보도록 하겠습니다.

npm install jest npm install --save-dev babel-jest regenerator-runtime babel-core@^7.0.0-bridge.0

그리고 src/tests/functions/uuid.test.js 를 다음과 같이 작성해 봅시다.

그런 후에 package.json 에 test 스크립트를 추가합니다.

"test": "NODE_ENV=test ./node_modules/.bin/jest tests --coverage"

잘 추가가 되었다면, npm test 로 테스트 실행 고고!

자 정상적으로 테스트가 통과한 것을 알 수가 있습니다.

축하합니다 당신은 지금 TDD 개발에 첫 발을 들여 놓으셨습니다. 사실 많은 업체들이 고객들을 상대로 서비스를 하고 있지만 테스트 기반 개발은 그렇게 보편적이지 않습니다.

그래서 테스트의 중요성을 매우 쉽게 간과하고는 하는데요. 고객에게 공개하여 서비스를 하고자 할 경우에는 테스트는 정말 꼭. 꼭. 하셔야 합니다.

이제부터의 강좌는 모두 테스트 기반의 개발을 하는 것으로 하겠습니다!

자 다음 강좌에는 이번 강좌를 통해 생성된 ordered UUID 를 디비에 적용하고 왜 비지니스 로직과 CRUD 로직을 분리해야 하는지에 대해 알아보도록 하겠습니다.

그럼 오늘도 즐거운 하루 보내세요!

--

--