Show GN: 10번의 고도화로 완성된 URL Shortener(Rust ver.) 오픈소스
(github.com/lee-lou2)URL Shortener 프로젝트 만들고 개선하고 또 만들고 또 개선하고... 를 반복하며 드디어 최최최종 v9 오픈소스 프로젝트를 만들게 되었습니다
🚀 Github : https://github.com/lee-lou2/rust-url-shortener
프로젝트를 준비하며 아래 요구사항은 꼭 지키려 노력했습니다
요구 사항
- Short URL 은 아주 빠르게 생성되어야한다
- 데이터가 많아진다고해서 느려져선 안된다
- 언제 어떠한 상황에서 어떤 데이터를 이용해서 요청하더라도 빨라야한다
- Short URL 을 Original URL 로 이동 시킬 때도 빨라야한다
- 사실 이건 당연한 얘기라... 😅
- 다양한 사용자들을 만족 시킬 수 있는 부가 기능들이 포함되어야한다
- 원하는 경우 플랫폼별로 다른 URL 로 이동시킬 수 있어야한다
- 원하는 경우 사용자가 생성한 URL 로 인입되는 데이터를 확인할 수 있어야한다
이러한 요구 사항을 충족 시키기위해 아래와 같이 개발하였습니다
반영 사항
Q. Short Key 생성을 어떻게하면 데이터 양과 관계 없이 빠르게 생성 할 수 있을까?
A.
일반적으로 Short Key 를 생성하는 방식은 여러가지가 있습니다.
첫 번째, 임의의 랜덤한 값을 생성해서 데이터베이스에 존재하는지 확인하고 없다면 그걸 그대로 사용하는 방식이 있습니다. 하지만 이 경우 데이터베이스에 확인하고 다시 한 번 생성 해줘야하는 번거로움이 있습니다. 또한 이미 많은 데이터가 있거나 Short Key 의 자리수가 바뀌어야하는 시점에 많은 지연이 발생될 수 있습니다.
두 번째, 미리 임의의 Short Key 를 생성해두고 매칭 시키는 방식이 있습니다. 이건 미리 만들어둔 Short Key 를 매칭만 해주는거다보니 언제나 빠르게 Short URL 을 생성할 수 있습니다. 하지만 이것 역시 답이 될 순 없습니다. 미리 만들어두는 것에 한계가 있을 수 있고 혹시라도 미리 만들어둔 것보다 많은 Short URL 이 생성되었을 때 등 고려해야할 사항들이 추가로 발생될 수 있습니다.
그렇다면 더더 좋은 방법은 없을까?
많은 고민 끝애 아래와 같은 방법을 적용했습니다. 랜덤한 4자리 문자열과 PK 를 이용한 문자열을 조합하여 사용하는 방식입니다. 각 값에 대한 설명은 아래 내용을 참고해주세요. 순서는 다음과 같습니다. 사용자가 Short URL 생성을 요청하면 랜덤한 4자리 문자열을 생성하고 그대로 데이터베이스에 저장합니다. 저장하며 발급되는 PK 를 아래 설명란에 작성된 방법대로 문자열로 생성합니다. 최초 생성한 랜덤한 문자열과 PK 문자열을 조합하여 Short Key 를 만듭니다. 이렇게되면 아무리 많은 데이터가 쌓여있다고하더라도 중복없이 빠르고 안전하게 생성되게됩니다.
- 랜덤한 4자리 수?
여기에서 랜던함 4자리 수는 영어 소문자/대문자 숫자로 이뤄진 정말 랜덤한 문자열입니다. 이 문자열은 중복이 발생되어도 괜찮습니다. - PK 를 문자열로?
다음으로 두 번째 값인 PK 문자열입니다. 영어 소문자/대문자, 숫자를 조합해서 문자열을 순서대로 만든다고 해보겠습니다. 순서는 영어 소문자 a -> z, 영어 대문자 A -> Z, 숫자 0 -> 9 순입니다. 그럼 a 는 첫 번째 만들어진 값이 될테고 b 는 2, c 는 3, ... 이렇게 순서대로 임의의 값을 조합해갈 수 있을 것입니다. 9 까지 다 만들어지면 aa, ab, ac 이렇게 자리수도 늘려가며 만들 수 있습니다. 이렇게 순서대로 만들게되면 문자열에 맞는 인덱스가 생기게됩니다. a 의 인덱스는 1 이 되는 셈이죠. 여기에 방법이 있습니다. PK 가 인덱스가 되고 그 PK 에 맞는 문자열르 찾아주기만하면 됩니다.
Q. Short URL 을 Original URL 로 이동 시킬 때 빠르게하려면?
A.
이건 정말 단순하게 캐시를 사용했습니다. 다양한 서비스들이 있지만 위 프로젝트에는 메모리 캐시를 사용해서 빠르게 데이터를 조회할 수 있도록 적용하였습니다. 추가로, 단순히 데이터를 조회하고 이동 시키는 것 외 부가적인 기능들은 경량 쓰레드를 생성하여 처리하였습니다.
Q. 추가적인 부가 기능은 어떤걸 구현했나요?
A.
우선 첫 번째로, 플랫폼 별로 다른 URL 로 이동되도록 구현 했습니다. iOS, Android 각각 기본 DeepLink 를 받아 저장하고 DeepLink 로 이동하지 못했을 때를 대비해 FallbackUrl 을 추가로 받았습니다. 그 외 데스크탑으로 접속 했을 때 이동할 URL 도 받아 모든 케이스에 대비했습니다.
두 번째로, Original URL 로 이동되는 시점에 사용자가 접속 로그를 확인 할 수 있도록 웹훅 URL 을 받아서 Original URL 로 이동 될 때 마다 웹훅 URL 을 호출해주는 기능을 추가했습니다. 지금은 User Agent 와 Short URL 정보만 전달되도록 구현해뒀습니다.
세 번째로, Short URL 생성 시 Head 태그의 정보들은 추가로 입력 할 수 있게했습니다. 이걸 추가한 목적은 og 태그를 커스텀하기 위함입니다. 해당 태그를 입력하지 않으면 Default URL 의 head 정보가 저장되도록 처리해뒀습니다.
해당 프로젝트는 Rust 를 이용했습니다. 사실 Rust 를 배운지 아직 2개월 밖에 되진 않았습니다. URL Shortener 프로젝트를 처음엔 FastAPI 로 개발했다가 그 다음으론 Golang 으로도 개발 했었습니다. 그리고 나서 Rust 를 배우며 너무 큰 매력에 빠져 완전히 고도화된 URL Shortener 프로젝트를 다시 한 번 만들게 되었습니다.
아직은 문법이나 소유권, 생명 주기 등이 익숙하지 않아 코드 상으로 부족한 점이 있을 수 있어 많은 관심과 응원 그리고 피드백 부탁드려요 🙏
끝까지 읽어주셔서 감사합니다
정성이 보이는 프로젝트네요!
저도 회사에서 비슷한걸 만들어서 사용중인데요, 저 같은 경우에는 인쇄 매체에 실려나가야 해서 모호한 문자를 회피하도록 문자 집합을 설정했습니다.
관련 내용도 긱뉴스에 있더라구요.
네, 퍼블릭한 서비스로 사용하려 이메일을 필수로 받게 적용해뒀습니다 (회원 가입 없이 이메일 인증을 사용)
JWT 입력 시 이메일이 없어도 되도록 수정하는 하는 방안도 한 번 고민해볼게요 🙏
호우 우분투 Lightsail 깔고 따라해보는데 SSL이라던가 pkg-config , sqlite, cargo 설치 해야 될게 많네요 :) 저는 https 이 부분을 NPM이 아니라 Cloudflare tunnel을 쓸려고 하긴했는데 역시 전 어려운것 같습니다 ㅎ_ㅎ.. 도커 버전 기대하겠습니다! 안그래도 dynamic link 없어져서 고민중이었는데 너무 좋네요.
Github 레포에 readme 말고 website에도 데모 url 추가해두면 좋을 것 같아요!
보통 홈페이지나 플레이그라운드가 있는지 확인을 레포의 오른쪽 정보를 먼저 보게 되는것 같아서 데모 사이트가 없는 줄 알았습니다 ㅎㅎ
좋은 프로젝트 잘 구경하고갑니다!
러스트를 설치하고 환경 변수만 지정하면 바로 사용이 가능합니다!
Google URL 서비스가 올해 종료되는데 대안으로 사용하세요. 궁금하신 점이나 개선이 필요한 부분, 설치를 위한 방법 등 여러 내용을 모든 메일 환영입니다 👏