대규모 시스템 설계 기초 라는 책을 매주 한 chapter 씩만 읽고있음에도 나에게는 아직 많이 어렵고 와닿지 않는 내용이 많았다. 그 중 8장은 직접 구현해보면 좋을 것 같아 구현해보았다.
URL 단축기의 필요성
사실 처음에는 이 필요성이 와닿지않았다. 특정 사이트에서 링크 복사를 하면 해당 URL 의 단축 URL 이 복사되어 좀 더 보기 간편하다는 생각은 했지만 그게 다였다. 그래서 필요성을 먼저 정리해보았다.
1. 확장성
- URL 단축기는 원래의 긴 URL을 짧게 변환하여 빠른 리다이렉션을 통해 서버의 부하를 줄일 수 있다.
2. 성능
- 캐싱 전략을 사용해 자주 접근되는 단축 URL에 대한 리다이렉션을 빠르게 제공할 수 있다.
- 단축된 URL은 데이터 전송 시 네트워크 부하를 줄일 수 있다.
3. 데이터 분석
- 단축된 URL을 통해 얻은 데이터로 어떤 링크가 얼마나 자주 클릭되었는지, 사용자들의 지역, 사용하는 디바이스 등의 정보를 분석할 수 있다.
URL 단축기 설계
우선 책에서 언급되어있는 설계 범위 및 개략적 추정을 제외하고 기본적 기능을 구현한다.
√ URL 단축 : 주어진 긴 URL을 훨씬 짧게 줄인다.
√ URL 리디렉션 : 축약된 URL로 HTTP 요청이 오면 원래 URL로 안내.
√ 높은 가용성과 규모 확장성, 그리고 장애 감내가 요구된다.
1. API 엔드포인트
- URL 단축용 엔드포인트 : 새 단축 URL 을 생성하고자 하는 클라이언트는 단축할 URL을 인자로 보낸다.
POST /shorten
인자 : {originName: originNamestring}
반환 : 단축 URL
- URL 리디렉션용 엔드포인트 : 단축 URL 에 대해서 HTTP 요청이 오면 원래 URL redirect.
GET /{shortUrl}
반환 : HTTP 리디렉션 목적지가 될 원래 URL
2. URL 리디렉션 with 통신 절차
아래의 그림을 예로 URL 리디렉션 시 통신 절차를 살펴보자.
Client 가 단축 URL 로 서버에 요청하면 서버는 그 URL 을 원래 URL 로 바꾸어서 302 응답의 Location 헤더에 넣어 반환함을 알 수 있다. ( 책에서는 301 응답을 예로 들었지만 내가 구현한 URL 단축기는 302를 응답하였기 때문에 302를 예로 들었다. )

여기서 유의할 것은 리디렉션 종류인데 차이는 아래와 같다.
- 301 Permanently Moved : 해당 URL 에 대한 HTTP 요청의 처리 책임이 영구적으로 Location 헤더에 반환된 URL로 이전되었다는 응답이다. 영구적으로 이전되었으므로 브라우저는 이 응답을 캐시한다. 따라서 추후 같은 단축 URL 에 요청을 보낼 필요가 있을 때 브라우저는 캐시된 원래 URL 로 요청을 보내게 된다.
- 302 Found : 주어진 URL 로의 요청이 '일시적으로' Location 헤더가 지정하는 URL 로 처리되어야 한다는 응답이다. 따라서 클라이언트의 요청은 언제나 단축 URL 서버에 먼저 보내진 후에 원래 URL로 리디렉션 되어야 한다.
이 두 방법은 각기 다른 장단점을 갖는다.
서버 부하를 줄이는 것이 중요하다면 301 Permanent Moved 를 사용하는 것이 좋다. 첫 번째 요청만 단축 URL 서버로 전송될 것이기 때문이다. 하지만 트래픽 분석이 중요할 때는 302 Found 를 쓰는 쪽이 클릭 발생률이나 발생 위치를 추적하는 데 좀 더 유리하다.
URL 단축기 구현 및 테스트
URL 단축기 구현
위의 엔드포인트를 구현한 내용으로 강의명을 단축된 URL로 변환하는 것을 목적으로 한다.
- UUID 를 통한 단축 url 생성
@Override // shortName 생성 로직
public String generateShortUrl() {
return UUID.randomUUID().toString().substring(0,8);
}
- 엔드포인트 구현
..
public class LectureController {
private final LectureService lectureServiceImpl;
@ResponseBody
@PostMapping("/shorten") // 1. URL 단축용 엔드포인트
public ResponseEntity<String> shortenUrl(@RequestBody String originalName){
String shortUrl = lectureServiceImpl.createShortUrl(originalName);
return ResponseEntity.ok(shortUrl);
}
@GetMapping("/{shortUrl}") // 2. URL 리디렉션용 엔드포인트
public void redirectToOriginalName(@PathVariable String shortUrl, HttpServletResponse response) throws IOException {
String originalName = lectureServiceImpl.getOriginalName(shortUrl);
/* 302 응답 */
response.sendRedirect(originalName);
/* 301 응답 */
// response.setHeader("location",originalUrl);
// response.setStatus(HttpServletResponse.SC_MOVED_PERMANENTLY);
}
}
URL 단축기 테스트
1. 먼저 단축 url 을 생성하는 인자로 "gototinyurl" 을 넣어 POST 요청

2. 응답받은 단축 URL로 접속하여 원래 location 으로 redirect 됨을 확인. ( 302 )

3. DB 에 잘 저장되어있는 지 확인.

정리
내가 구현한 URL 단축기는 매번 단축 URL 서버에 보내져야하기 때문에 캐시의 이점을 갖지 못한다. 또한 설계를 고려하지 않았기 때문에 내가 얻어간 것은 단순한 구현과 동작 방식 뿐이다. 이후 UUID 가 아닌 다른 접근법을 통해 재구현을 해봐야겠다.
참고
https://www.fool.com/the-ascent/small-business/social-media/articles/url-shortener/
https://eclincher.com/5-benefits-of-url-shorteners-2/
https://rockcontent.com/blog/301-vs-302-redirect/
'Web' 카테고리의 다른 글
| [Spring] Swagger 에 JWT 설정하기 (0) | 2023.11.26 |
|---|---|
| [Spring] Spring 3.x + Swagger 설정 (0) | 2023.11.19 |
| [Spring] Transaction 에 대해서 (3) | 2023.10.22 |
| [JPA] 지연로딩과 즉시로딩 (0) | 2023.10.08 |
| [JPA] 1:N 단방향 매핑과 N:1 양방향 매핑 (0) | 2023.10.01 |