가상 면접 사례로 배우는 대규모 시스템 설계 기초를 읽고 정리한 글입니다.
이 책 내용을 들어가기에 앞서 왜 대규모 시스템에서 URL을 단축해야 할까? 의문이 들어 찾아봤다.
아래 표는 단축 URL의 주요 장점과 설명을 정리한 것이다.
구분 | 설명 |
---|---|
공간 절약 및 가독성 향상 | SNS(예: 트위터 280자 제한)나 문자메시지(SMS)처럼 짧은 메시지 환경에서는 긴 URL이 불편을 초래한다. 단축 URL은 글자 수를 절약하고, 깔끔하게 링크를 전달할 수 있다. |
클릭 추적 및 분석 | 언제, 어디서, 누가 클릭했는지 등 실시간 데이터 추적이 가능하다. 국가/도시별, 시간대별, 디바이스·브라우저별, 유입경로까지 세분화된 분석이 가능하다. |
마케팅 효과 측정 | 다양한 채널에 뿌려진 링크별로 성과를 비교할 수 있고, 메시지별 A/B 테스트나 ROI(투자대비수익률) 계산이 가능하다. |
링크 관리 및 업데이트 | 일부 서비스는 리디렉션 대상 URL을 변경할 수 있어서 웹사이트 구조 변경, 오타 수정, 시즌별 캠페인 등에 유용하게 쓸 수 있다. |
주소 마스킹 기능 | 원래 URL을 감춰 보안이나 브랜딩 관점에서 유리하다. 민감한 정보 노출을 막거나, 짧고 인상적인 링크를 쓸 수 있다. |
스팸 및 봇 클릭 방지 | 비정상 트래픽(봇 등)을 필터링해 광고비 낭비를 막고, 통계의 정확성을 높일 수 있다. |
위와 같은 여러 장점이 있지만, 내가 생각하기에 단축 URL의 가장 큰 강점은 가독성을 높여주는 점과 클릭 추적을 통해 마케팅 효과를 극대화할 수 있다는 점이라고 본다.
특히 요즘 토스, 무신사, 당근, 지그재그 같은 서비스들에서 사용자들끼리 링크를 공유해 유입률을 높이는 마케팅 전략을 많이 사용하고 있다.
이 부분에서 단축 URL을 사용하면 큰 이점이 있지 않을까? 생각했다.
개발 커뮤니티 단톡방에서 본 이야기인데,
요즘 이런 이벤트를 진행하는 이유는 사용자가 이벤트에 참여할 때 약관 동의 과정에서 데이터를 수집하는 것이 목적이고,
동시에 DAU를 증가시켜 광고 단가를 올리기 위한 목적도 있다고 들었다.
실제로 수집하는 항목이 꽤 많다.(이벤트 참가할 때 유의 깊게 봐야 할 듯..)
1단계 문제 이해 및 설계 범위 확정
시스템 설계 면접 문제는 의도적으로 어떤 정해진 결말을 갖지 않도록 만들어진다 따라서 면접장에서 시스템을 성공적으로 설계해 내려면 질문을 통해 모호함을 줄이고 요구사항을 알아내야 한다.
질문 예시
- 어떻게 동작해야하는지 예제를 보여주실 수 있을까요?
- 트래픽 규모는 어느정도 일까요?
- 단축 URL의 길이는 어느 정도여야 하나요?
- 단축 URL에 포함될 문자에 제한이 있습니까?
- 단축 URL을 시스템에서 지우거나 갱신할 수 있습니까?
이 시스템의 기본적 기능은 아래와 같다.
- URL 단축 : 주어진 긴 URL을 훨씬 짧게 줄인다.
- URL 리다이렉션(redirection): 축약된 URL로 HTTP 요청이 오면 원래 URL로 안내
- 높은 가용성과 규모 확장성, 그리고 장애 감내가 요구됨
개략적 추정
- 쓰기 연산: 매일 1억 개의 단축 URL 생성
- 초당 쓰기 연산: 1억 / 24 / 3600 = 1160
- 읽기 연산: 읽기 연산과 쓰기 연산 비율은 10:1이라고 하자. 그 경우 읽기 연산은 초당 11,600회 발생한다(1160 x 10 = 11,600)
- URL 단축 서비스를 10년간 운영한다고 가정하면 1억 x 365 x 10 = 3650억 개의 레코드를 보관해야 한다.
- 축약 전 URL의 평균 길이는 100이라고 하자.
- 따라서 10년 동안 필요한 저장 용량 3650억 x 100바이트 = 36.5TB이다.
위 개략적 추정은 질문을 통해 답변받은 것을 통해서 계산하는 것이며 계산이 끝나면 결과를 면접관과 점검하여 합의한 후에 진행하도록 하자.
2단계 개략적 설계안 제시 및 동의 구하기
API 엔드포인트
REST API로 설계하는 걸 가정한다.
URL 단축기는 기본적으로 두 개의 엔드포인트를 필요로 한다.
1. URL 단축용 엔드포인트
POST /api/v1/data/shorten
- 인자: { longUrl: longURLstring }
- 반환: 단축 URL
2. URL 리다이렉션용 엔드포인트
GET /api/v1/shortUrl
- 반환: HTTP 리다이렉션 목적지가 될 원래 URL
URL 리다이렉션
다음의 그림은 브라우저에 단축 URL을 입력하면 무슨 일이 생기는지 보여준다.
단축 URL을 받은 서버는 그 URL을 원래 URL로 바꾸어서 301 응답의 Location 헤더에 넣어 반환한다.
다음의 그림은 클라이언트와 서버 사이의 통신 절차를 좀 더 자세히 보여준다.
301 응답 VS 302 응답
301 응답과 302 응답 둘 다 리다이렉션 응답이지만, 차이가 있다.
301 Permanetly Moved
이 응답은 해당 URL에 대한 HTTP 요청의 처리 책임이 영구적으로 Location 헤더에 반환된 URL로 이전되었다는 응답이다.
영구적으로 이전되었으므로, 브라우저는 이 응답을 캐시 한다.
따라서 추후 같은 단축 URL에 요청을 보낼 필요가 있을 때 브라우저는 캐시 된 원래 URL로 요청을 보내게 된다.
302 Found
이 응답은 주어진 URL로의 요청이 일시적으로 Location 헤더가 지정하는 URL에 의해 처리되어야 한다는 응답이다.
따라서 클라이언트의 요청은 언제나 단축 URL 서버에 먼저 보내진 후에 원래 URL로 리다이렉션 되어야 한다.
이 두 방법은 각기 다른 장단점을 갖고 있다.
서버 부하를 줄이는 것이 중요하다면 `301 Permanent Moved`를 사용하는 것이 좋은데 첫 번째 요청만 단축 URL 서버로 전송될 것이기 때문이다.
하지만 트래픽 분석이 중요할 때는 `302 Found`를 쓰는 쪽이 클릭 발생률이나 발생 위치를 추적하는 데 좀 더 유리할 것이다.
URL 리다이렉션을 구현하는 가장 직관적인 방법은 해시 테이블을 사용하는 것이다.
해시 테이블에 <단축 URL, 원래 URL>의 쌍을 저장한다고 가정한다면, URL 리다이렉션은 다음과 같이 구현될 수 있을 것이다.
- 원래 URL = hashTable.get(단축 URL)
- 301 또는 302 응답 Location 헤더에 원래 URL을 넣은 후 전송
URL 단축
단축 URL이 `www.tinyurl.com/{hashValue}` 같은 형태라고 해 보자.
결국 중요한 것은 긴 URL을 이 해시 값으로 대응시킬 해시 함수 fx를 찾는 일이 될 것이다.
이 해시 함수는 다음 요구사항을 만족해야 한다.
- 입력으로 주어지는 긴 URL이 다른 값이면 해시 값도 달라야 한다.
- 계산된 해시 값은 원래 입력으로 주어졌던 긴 URL로 복원될 수 있어야 한다.
3단계 상세설계
데이터 모델
위에서 언급했듯이 모든 것을 해시 테이블에 두었었다. 이 접근법은 초기 전략으로는 괜찮지만 실제 시스템에 쓰기에는 곤란한데, 메모리는 유한한 데다 비싸기 때문이다.
더 나은 방법은 `<단축 URL, 원래 URL>`의 순서쌍을 관계형 데이터베이스에 저장하는 것이다.
아래 그림이 테이블의 간단한 설계 사례다.
이 테이블은 단순화된 것으로 `id`, `shortUrl`, `longURL`의 세 개 칼럼을 갖는다.
해시 함수
해시 함수는 원래 URL을 단축 URL로 변환하는데 쓰인다. 편의상 해시 함수가 계산하는 단축 URL값을 `hashValue`라고 지칭한다.
자릿수 정하기
URL에 담길 수 있는 영역은 숫자와 영문자이다. `([0-9, a-z, A-Z])`
따라서 사용할 수 있는 문자의 개수는 10 + 26 + 26 = 62개이다.
우리는 3650억 개의 레코드를 보관할 수 있도록 하는 것을 고려해야 하기 때문에 몇 자리의 문자가 필요한지 계산해 보면 다음과 같다.
따라서 7자리로 3.5조 개의 URL을 커버할 수 있다.
hashValue의 길이는 7로 하면 된다.
해시 함수 구현에 쓰일 기술로는 두 가지 방법을 살펴보자.
하나는 해시 후 충돌 해소 방법이고, 다른 하나는 base-62 변환 법이다.
해시 후 충돌 해소
긴 URL을 줄이려면, 원래 URL을 7글자 문자열로 줄이는 해시 함수가 필요하다.
손쉬운 방법은 CRC32, MD5, SHA-1같이 잘 알려진 해시 함수를 이용하는 것이다.
해시 함수 | 해시 결과 (16진수) |
---|---|
CRC32 | 5cb54054 |
MD5 | 5a62509a84df9ee03fe1230b9dfb84e |
SHA-1 | 0eeae7916c06853901d9ccbefbfcaf4de57ed85b |
그런데 위의 표와 같이, CRC32가 계산한 가장 짧은 해시값조차도 7보다는 길다.
어떻게 하면 줄일 수 있을까?
이 문제를 해결할 첫 번째 방법은 계산된 해시 값에서 처음 7개 글자만 이용한느 것이다.
하지만 이렇게 하면 해시 결과가 서로 충돌할 확률이 높아진다.
충돌이 실제로 발생했을 때는, 충돌이 해소될 때까지 사전에 정한 문자열을 해시값에 덧붙인다.
이 방법을 쓰면 충돌은 해소할 수 있지만 단축 URL을 생성할 때 한 번 이상 데이터베이스 질의를 해야 하므로 오버헤드가 크다.
데이터베이스 대신 블룸 필터를 사용하면 성능을 높일 수 있다.
base-62 변환
진법 변환은 URL 단축기를 구현할 때 흔히 사용되는 접근법 중 하나다.
이 기법은 수의 표현 방식이 다른 두 시스템이 같은 수를 공유하여야 하는 경우에 유용하다.
62진법을 쓰는 이유는 hashValue에 사용할 수 있는 문자 개수가 62개이기 때문이다.
`1115710`을 62진수로 변환해 보자.
- 62진법은 수를 표현하기 위해 62개의 문자를 사용하는 진법이다.
따라서 0은 0으로 9는 9로, 10은 a로 61은 Z로 대응시켜 표현하도록 할 것이다. 따라서 62진법에서 ‘a’는 10을 나타내고 ‘Z’는 61을 나타낸다. - 1115710 = 2 x 622 + 55 X 621 + 59 x 620 = [2, 55, 59] => [2, T, X] => 2 TX62이다.
- 따라서 단축 URL은 `https://tinyurl.com/2TX`가 된다.
두 접근법 비교
해시 후 충돌 해소 전략 | base-62 변환 |
---|---|
단축 URL의 길이가 고정됨 | 단축 URL의 길이가 가변적. ID 값이 커지면 같이 길어짐 |
유일성이 보장되는 ID 생성기가 필요치 않음 | 유일성 보장 ID 생성기가 필요 |
충돌이 가능해서 해소 전략이 필요 | ID의 유일성이 보장된 후에야 적용 가능한 전략이라 충돌은 아예 불가능 |
ID로부터 단축 URL을 계산하는 방식이 아니라서 다음에 쓸 수 있는 URL을 알아내는 것이 불가능 | ID가 1씩 증가하는 값이라고 가정하면 다음에 쓸 수 있는 단축 URL이 무엇인지 쉽게 알아낼 수 있어서 보안상 문제가 될 소지가 있음 |
URL 단축기 상세 설계
URL 단축기는 시스템의 핵심 컴포넌트이므로, 그 처리 흐름이 논리적으로는 단순해야 하고 기능적으로는 언제나 동작하는 상태로 유지되어야 한다.
본 책에서는 62진법(base62) 변환 기법을 사용해 설계한다.
- 입력으로 긴 URL을 받는다.
- 데이터베이스에 해당 URL이 있는지 검사한다.
- 데이터베이스에 있다면 해당 URL에 대한 단축 URL을 만든 적이 있다는 것이다. 따라서 데이터베이스에서 해당 단축 URL을 가져와서 클라이언트에게 반환한다.
- 데이터베이스에 없는 경우에는 해당 URL은 새로 접수된 것이므로 유일한 ID를 생성한다. 이 ID는 데이터베이스의 기본 키로 사용된다.
- 62진법 변환을 적용, ID를 단축 URL로 만든다.
- ID, 단축 URL, 원래 URL로 새 데이터베이스 레코드를 만든 후 단축 URL을 클라이언트에 전달한다.
URL 리다이렉션 상세 설계
쓰기보다 읽기를 더 자주 하는 시스템이라, 캐시에 저장하여 성능을 높였다.
로드밸런서의 동작 흐름은 다음과 같이 요약할 수 있다.
- 사용자가 단축 URL을 클릭한다.
- 로드밸런서가 해당 클릭으로 발생한 요청을 웹 서버에 전달한다.
- 단축 URL이 이미 캐시에 있는 경우에는 원래 URL을 바로 꺼내서 클라이언트에게 전달한다.
- 캐시에 해당 단축 URL이 없는 경우에는 데이터베이스에서 꺼낸다. 데이터베이스에 없다면 아마 사용자가 잘못된 단축 URL을 입력한 경우일 것이다.
- 데이터베이스에서 꺼낸 URL을 캐시에 넣은 후 사용자에게 반환한다.
4단계 마무리
설계를 마친 후에도 시간이 좀 남는다면 다음과 같은 것을 면접관과 이야기할 수 있을 것이다.
처리율 제한 장치(rate limiter)
- 지금까지 살펴본 시스템은 엄청난 양의 URL 단축 요청이 있을 경우 무력화될 수 있다는 잠재적 보안 결함을 갖고 있다. 처리율 제한 장치를 두면, IP 주소를 비롯한 필터링 규칙들을 이용해 요청을 걸러낼 수 있을 것이다.
웹 서버의 규모 확장
- 본 설계에 포함된 웹 계층은 무상태 계층이므로, 웹 서버를 자유롭게 증설하거나 삭제할 수 있다.
데이터베이스의 규모 확장
- 데이터베이스를 다중화하거나 샤딩(sharding)하여 규모 확장성을 달성할 수 있다.
데이터 분석 솔루션(analytics)
- 성공적인 비즈니스를 위해서는 데이터가 중요하다. URL 단축기에 데이터 분석 솔루션을 통합해 두면 어떤 링크를 얼마나 많은 사용자가 클릭했는지, 언제 주로 클릭했는지 등 중요한 정보를 알아낼 수 있을 것이다.
가용성, 데이터 일관성, 안정성
- 대규모 시스템이 성공적으로 운영되기 위해서는 반드시 갖추어야 할 속성들이다.
+ 회고 시 스터디원들과 나눴던 내용들
단축 URL을 빠르게 찾기 위해서 캐시를 사용하지만 캐시에 없다면 RDB에서 찾아야 하는데 읽기 성능이 중요할 거 같은데 mongodb 같은 nosql 사용은 어떻게 생각하시나요?
단축 URL 시스템에서 대부분의 요청은 캐시(예: Redis, Memcached)를 통해 빠르게 처리되지만,
캐시에 없는 경우에는 결국 데이터베이스에서 원본 URL을 찾아야 한다.
초당만 건 이상의 읽기 요청과 수십~수백억 건의 레코드를 고려할 때, 데이터베이스의 읽기 성능과 확장성이 굉장히 중요한 요소가 된다.
RDB도 인덱싱과 리드 레플리카를 통해 어느 정도까지는 성능을 낼 수 있지만,
데이터가 수십 테라바이트 규모로 커지면 샤딩 및 분산 처리가 필요해지고, 운영 복잡성이 급격히 높아진다.
또한 키-값 단순 조회 패턴에서는 관계형의 고도 기능(조인, 트랜잭션 등)이 거의 필요하지 않기 때문에,
이럴 때는 MongoDB 같은 NoSQL이 훨씬 적합한 선택이 될 수 있다.
What database to use for URL Shortener project
유명한 서비스나 오픈소스가 있는지
The 7 best URL shortener services
왜 대규모 시스템에서 URL을 단축해야 할까요?
서두에 서술!
출처
https://jonghoonpark.com/2023/06/15/url-shortener
직접 구현해 보는 URL 단축기
'📝 끄적끄적 > 📖 가상 면접 사례로 배우는 대규모 시스템 설계 기초' 카테고리의 다른 글
9장. 웹 크롤러 설계 (0) | 2025.07.14 |
---|---|
7장. 분산 시스템을 위한 유일 ID 생성기 설계 (0) | 2025.07.01 |
6장. 키-값 저장소 설계 (0) | 2025.07.01 |
5장. 안정 해시 설계 (0) | 2025.06.30 |
4장. 처리율 제한 장치의 설계 (0) | 2025.06.30 |
3장. 시스템 설계 면접 공략법 (0) | 2025.06.05 |