Shorten Url

Seung jun Cha·2023년 8월 27일
0

1. 개념

그래서 짧고 보기 쉽게 Url을 인코딩 해보자. 방법은 세 가지가 있고, 지금은 Base62를 사용한다.

  1. DB의 pk정보를 사용하여 url 생성 : 데이터가 많아지면 이것도 길어질 수 있다

  2. Base64(64진수) 사용 : +, /, = 등 특수문자는 URL 예약어이기 때문에 Url을 인코딩하는데에는 부적절한 방법이다. 대신 Url-safe한 방법으로 인코딩 할 수 있는데,
    +- (하이픈)으로 대체되고, /_ (언더스코어)로 대체된다.
    패딩 문자인 =는 URL-safe Base64에서는 제거되거나 무시된다.

  3. Base62(62진수) 사용

2. Base62

  • 의존성을 추가한다.
  // https://github.com/seruco/base62
    implementation 'io.seruco.encoding:base62:0.1.3'
  • 사용방법 : 인코딩, 디코딩 시 파라미터 타입은 String이다.
Base62 base62 = Base62.createInstance();

- 인코딩 
final byte[] encoded = base62.encode("Hello World".getBytes());

new String(encoded); // is "73XpUgyMwkGr29M"

- 디코딩
final byte[] decoded = base62.decode("73XpUgyMwkGr29M".getBytes());

new String(decoded); // is "Hello World"
  • 적용
public class Base62Service {

    private static final Base62 base62Instance = Base62.createInstance();

    public String encodeDirectionId(Long directionId){
        return new String(base62Instance.encode(String.valueOf(directionId).getBytes()));
    }

    public Long decodeDirectionId(String encodedDirectionId){
        String directionId = new String(base62Instance.decode(encodedDirectionId.getBytes()));
        return Long.valueOf(directionId);
    }
}
  • Shorten Url 생성 : 지금은 DB에 저장된 엔티티의 pk를 인코딩해서 Shorten Url을 생성했다.
 private PharmacyInfoDto convertToPharmacyInfo(Direction direction) {

        return PharmacyInfoDto.builder()
                .pharmacyAddress(direction.getTargetAddress())
                .pharmacyName(direction.getTargetPharmacyName())
                .directionUrl(baseUrl + base62Service.encodeDirectionId(direction.getId())) // shorten url
                .roadViewUrl(ROAD_VIEW_BASE_URL + direction.getTargetLatitude() + "," + direction.getTargetLongitude())
                .distance(String.format("%.2f km", direction.getDistance()))  // 소수점 2번째 자리까지
                .build();
    }
  • 사용자가 인코딩된 Url을 사용해서 데이터를 요구할 때, 인코딩된 Id를 다시 디코딩한 후, DB에서 데이터를 가져와 반환한다. 그리고 그 데이터를 바탕으로 Url을 생성한다.
 public String findDirectionUrlById(String encodeId){
        Long directionId = base62Service.decodeDirectionId(encodeId);
        Direction direction = directionRepository.findById(directionId).orElseThrow(EntityNotFoundException::new);

        String params = String.join(",", direction.getTargetPharmacyName(), String.valueOf(direction.getTargetLatitude()),
                String.valueOf(direction.getTargetLongitude()));

        //Uri를 동적으로 생성해주는 클래스, .toUriString()는 한글을 UTF-8로 자동으로 인코딩 해준다.
        String directionUrl = UriComponentsBuilder.fromHttpUrl(DIRECTION_VIEW_BASE_URL + params).toUriString();

        return directionUrl;
    }
  • 컨트롤러 : 인코딩한 url으로 요청이 들어오면 디코딩해서 해당 url로 리다이렉트한다.
public class DirectionController {

    private final DirectionService directionService;


    @GetMapping("/dir/{encodedId}")
    public String searchDirection(@PathVariable String encodedId){
        String directionUrl = directionService.findDirectionUrlById(encodedId);
        // 사용자가 입력한 주소를 기준으로 추천된 약국을 DB에서 가져오고 길안내 url 생성

        log.info("direction url : {}", directionUrl);
        return "redirect:" + directionUrl;
    }
}

0개의 댓글