저번 라이브러리 모듈을 만들다가 API 통신 시에 사용하는 Retrofit, okHttp 중에 데이터를 보여주는 방법이 있을 것 같다고 생각하고 찾아보던 와중,
okHttp에서 지원하는 HttpLoggingInterceptor 에 대해서 찾을 수 있었다.
따라서, LogInterceptor를 Koin을 통해 설정하고 사용하는 방법에 대해서 작성해 보고자 한다.
HttoLoggingInterceptor를 사용하기 위해서는 Gradle에 라이브러리를 추가해 주어야 한다.
// okhttp3 Logging
implementation 'com.squareup.okhttp3:logging-interceptor:4.9.0'
해당 라이브러리를 추가하였으면,
적용하여 사용해보도록 하자.
우선 Retrofit과 okHttp를 사용할 것이므로 각각 선언을 해준다.
private var retrofit: Retrofit? = null
private val builder = Retrofit.Builder()
.baseUrl(BASE_URL)
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
private val httpClient = OkHttpClient.Builder()
해당 부분은 전체 코드의 일부이기 때문에, 어떤 방식으로 선언하고 사용하는지 확인용으로 봐주길 바란다.
Retrofit과 httpClient를 선언해 주었으면, gradle에 추가한 LoggerInterceptor를 사용하도록 하자.
private val logger = HttpLoggingInterceptor().let {
if (BuildConfig.DEBUG) {
it.setLevel(HttpLoggingInterceptor.Level.BODY)
} else {
it.setLevel(HttpLoggingInterceptor.Level.NONE)
}
}
Debug와 Release를 구분하여 디버그 모드일 경우에만 Log를 찍기 위해서 다음과 같은 조건문을 추가해 주었다.
HttpLoggingInterceptor().setLevel(HttpLoggingInterceptor.Level)
과 같은 형식으로 사용하면 되는데, 설정하는 level에 따라 로그의 데이터가 다르게 나오게 된다.
여기서 설정할 수 있는 Level은 다음과 같다.
enum class Level {
NONE,
BASIC,
HEADERS,
BODY
}
총 4가지 레벨이 존재하며, Enum형으로 선언된 타입이 뒤로갈수록 더 많은 데이터를 보여주게 된다.
해당 라이브러리에 들어가서 확인해 보면 각 레벨당 표기되는 데이터가 기술되어 있다.
NONE : No logs
BASIC : Logs request and response lines.
HEADERS : Logs request and response lines and their respective headers.
BODY : Logs request and response lines and their respective headers and bodies (if present).
따라서 기본적인 통신 성공 여부만 확인하고 싶은 경우 BASIC,
헤더의 데이터까지만 확인하고 싶은 경우 HEADERS,
모든 데이터를 확인하고 싶은 경우 BODY,
로그를 보고싶지 않은 경우 NONE
을 사용하면 된다.
원하는 level로 LoggingInterceptor를 선언했으면,
httpClinet에 interceptor를 추가하고 retrofit에 추가해주면 된다.
// okHppt에 LoggingInterceptor 추가
httpClient.addInterceptor(logger)
// retrofit builder에 선언한 okhttp를 client로 추가
builder.client(httpClient.build())
// retrofit builder를 null로 선언해 두었던 retrofit객체에 넣어 사용함.
retrofit = builder.build()
이와 같이 선언하고 api를 호출해보면 로그가 찍히는 것을 확인할 수 있다.
--> POST 로 되어있는 부분에서 Header에 대한 데이터가 나오고,
<-- 200 OK 로 되어있는 부분에서 API를 통해 가져오는 Data가 표시된다.
200 OK라는 것은 정상적으로 통신이 완료됬다는 의미이며, 정상적으로 통신을 하지 못하는 경우에는 해당 부분에 오류 코드가 나오게 된다.
429라는 에러가 발생한 경우 다음과 같이 나오게 되는데,
에러 번호 뿐만이 아니라 하단 내용을 보면 에러에 대한 상세한 내용을 확인할 수 있다.
정상적으로 동작하는 것을 확인해 보았으니,
Koin을 사용할 때는 해당 부분을 어떻게 선언해야 하는지 확인해볼 차례이다.
해당 부분은 필자가 이전에 작성해둔 Clean Architecture 예제를 확인하면 될 것이다.
https://github.com/HeeGyeong/CleanArchitectureSample
선언해두었던 ApiModule에서 추가해야할 부분은,
- HttpLoggingInterceptor를 주입
- 선언한 okHttpClient에서 해당 Interceptor를 추가해주는 작업
이 두가지 작업이 필요하다.
우선, 첫 번째 작업을 진행해주자.
single {
HttpLoggingInterceptor().let {
if (BuildConfig.DEBUG) {
it.setLevel(HttpLoggingInterceptor.Level.BODY)
} else {
it.setLevel(HttpLoggingInterceptor.Level.NONE)
}
}
}
single로 선언하여 해당 객체를 singleton으로 사용하도록 하자.
코드 자체는 위에 클래스 내에서 선언한 것과 동일하게 가져가면 된다.
그 후, OkHttpClient.Builder() 부분에
addInterceptor(get<HttpLoggingInterceptor>())
를 addInterceptor를 추가해 해당 LoggingInterceptor를 추가해주면
정상적으로 로그가 찍히는 것을 볼 수 있다.
* 2022.03.17 추가
검색을 해보니, HttpLoggingInterceptor에서 Log찍는 부분을 커스텀할 수 있다고 한다.
따라서 Log를 커스텀해서 사용해 보도록 하자.
single {
HttpLoggingInterceptor(object : HttpLoggingInterceptor.Logger {
override fun log(message: String) {
Log.d("sampleNameTag", "$message ")
}
})
}
Koin의 Module에서 선언한 부분을 수정하였다.
Debug에 대한 옵션을 붙이지 않는다면, HttpLoggingInterceptor()만 선언하여 사용이 가능하다.
여기서 Logger 객체를 새로 만들어 log 메서드를 Override 하여 사용하면 Log를 커스텀하여 사용이 가능하다.
이를 람다식으로 변경하면 다음과 같이 나온다.
HttpLoggingInterceptor { message ->
Log.d("ApiLogger", "$message ")
}
기본적인 사용 방법으로는 Log에 찍히는 Tag가 okHttpClient로 고정되어있다.
하지만, 위와 같이 Override를 하여 사용하면 다음과 같이 로그가 찍히게 된다.
필자는 Tag만 변경하고 다른 것은 건들지 않았기 때문에 기본에서 Tag만 변경된 것으로 찍히게 된다.
message 부분을 사용하면서 필요에 따라 커스텀을 진행하면 된다.
Log를 커스텀할 수 있다면,
Logger 라이브러리도 사용이 가능할것으로 보여 확인을 해보았다.
single {
HttpLoggingInterceptor { message ->
Logger.d(message)
}
.let {
if (BuildConfig.DEBUG) {
Logger.addLogAdapter(AndroidLogAdapter())
it.setLevel(HttpLoggingInterceptor.Level.BODY)
} else {
it.setLevel(HttpLoggingInterceptor.Level.NONE)
}
}
}
이처럼 사용 가능하다.
Logger를 사용하기 위해서는 AndroidLogAdatper를 추가해주어야 하는데, 해당 작업을 람다식 내부에서 진행할 수는 없다.
메세지를 찍을 때 마다 초기화를 한다는 것은 말이 안되기 때문이다.
따라서, 범위지정함수를 사용하여 출력하기 전, Debug 상태일 경우에만 Adapter를 추가하여 사용할 수 있도록 추가해 주었다.
이렇게 설정을 하고 로그를 찍어보면 다음과 같다.
라인 별로 주어진 템플릿에 맞춰서 출력이 되기 때문에 기본 Log처럼 한눈에 확인하는 것은 어려워 보인다.
하지만, Api를 통해 가져온 데이터도 한 라인으로 출력이 되기 때문에 해당 부분만 보는 경우에 한에서 쉽게 볼 수는 있을 것으로 보인다.
이처럼 기본적으로 설정된 Log뿐 아니라 커스텀하여서 사용할 수 있도록 예제를 만들어 보았다.
해당 부분은 따로 커스텀하지 않아도 사용해도 무관할 것으로 보이지만, 커스텀해서 보는것도 나쁘지 않은 것 같다.
Koin을 사용한 예제 코드는 Github에 올려두었으니 참고하길 바란다.
https://github.com/HeeGyeong/CleanArchitectureSample
'Android > Network' 카테고리의 다른 글
[Android] SSE를 사용하여 실시간 통신하는 방법. (1) | 2024.12.29 |
---|---|
[Android] Retrofit 대신 Ktor을 사용하여 통신을 해보자. -2. DI (0) | 2022.08.18 |
[Android] Retrofit 대신 Ktor을 사용하여 통신을 해보자. -1. 기본 (1) | 2022.08.12 |