본문 바로가기

Android/note

URL 에 콜론(:), 더하기(+)와 같은 문자가 포함되었을 때

이번 문제는 랜덤리즘 프로젝트를 진행하다가 발생한 문제 ..

 

문제상황

서버에 문자열 관련한 문제들을 받기 위해서 Request로 solvable:true+tag:strings 의 쿼리를 전송했는데, 계속해서 원하는 값을 받을 수 없었다.

 

예상한 응답 실제로 받은 응답
2220 개의 문제 개수와 첫 문제가 1013번 이어야함 2220개가 아닌 전체 총 문제의 개수(29031개)와
가장 첫 문제인 1000번부터 전달받음

 

문제 해결 과정

가장 먼저 의심되었던 부분은 주소에 : , + 와 같은 문자가 포함되어있었는데 무슨 뜻인지 알지못해서 아래와 같이 그냥 하나의 문자열로 전달했다.

 

val requestQuery = "solvable:true+tag:$tagKey"

 

이 부분이 문제인걸까? 싶었는데 쿼리로 어떻게 전달이되는지 알 수가 없어서 너무 답답했다.

요청하는 주소 URL 을 확인할 수 있는지 검색해보았더니 okhttp3 의 loggingInterceptor 를 사용하면 볼 수 있다는 것을 알았고, 바로 의존성 추가해서 확인해보니 아래 사진과 같았다.

 

 

 

 

URL 에 내가 넣지도 않은 %3A 그리고 %2B 가 추가된 것을 알 수 있었다.

그래서 전체 문제가 출력된 것 같음 ..

 

일단 콜론(:)은 %3A로 , 더하기(+)는 %2B로 인코딩되어 변환되어 있었다.

-> 이것은 URL 인코딩이라고 한다고 한다!

퍼센트 인코딩(URL 인코딩) 보기
https://developer.mozilla.org/ko/docs/Glossary/Percent-encoding

 

작성한 콜론(:)과 더하기(+)를 인코딩되지 않고 그대로 전달하기 위해서는 @Query 를 사용한 부분에 encoded 의 값을 true 로 변경해주면 된다.

 

그리고 Retrofit 의 Query.java 파일을 살펴보면 아래와 같은 설명이 작성되어 있다.

Parameter names and values are URL encoded by default. Specify encoded=true to change this behavior.

기본적으로 전달되는 값들이 인코딩되기때문에, 인코딩되는 것을 막기위해서는 encoded 값을 true 로 변경해주어라!

 

public @interface Query {
    String value();
    boolean encoded() default false;
}

 

위와 같이 코드에서 기본적으로 false 되어있음을 다시 한번 더 확인할 수 있다!

 

@GET("search/problem")
suspend fun fetchProblemsByTag(
    @Query("query", encoded = true) query: String,
    @Query("page") page: Int
): Response<ProblemDTO>

 

encoded = true 로 적용했을 때 전달되는 주소값을 다시 확인해보면 원했던 대로 아래와 같음을 알 수 있다!