java에 org.jsoup.Connection.Response
라고 HTML response를 받는 오브젝트가 있다.
이 Response
오브젝트에는 String
형 body를 꺼낼 수 있는 body()
나 Content-Type에서 String
형 charset을 꺼내는 charset()
이 있다.
그런데 이 charset()
은 nullable한 String?
이라는 건데. 언제 그러냐하면 UTF-8
이 명시되어있지 않을 때 그렇다.
참고로 ?
가 붙으면 nullable하다는 것이고 !
가 붙으면 절대로 null일 가능성은 없다는 뜻이다.
이걸 모르고 아래와 같은 코드를 적었다.
import org.jsoup.Connection
private fun isValid(res: Connection.Response): Boolean {
val charset = res.charset()
return if (charset.uppercase() == "UTF-8") {
true
} else {
LOGGER.info("not UTF-8 encoded. charset is $charset")
false
}
}
그랬더니 아니나다를까 릴리스 하자마자 에러를 뿜어냈다.
java.lang.NullPointerException: charset must not be null
듣기로 Kotlin은 null에 안전한 언어라지. 그래서 처음에 컴파일 할 때 경고라도 내 줬으면 좋았으려만.
어쨌든 다른 선배가 수정해서 PR을 냈다.
import org.jsoup.Connection
private fun isValid(res: Connection.Response): Boolean {
val charset = res.charset()
return if (charset?.uppercase() == "UTF-8") {
true
} else {
LOGGER.info("not UTF-8 encoded. charset is $charset")
false
}
}
하지만 이 코드도 에러는 계속 났다.
에러 메세지로 봐서는 String!
이 아니라 String?
이라서 문제가 되는 것 같았다.
참고로 에러를 내고 있는 곳은 if 조건문이 적힌 곳인데, 여기서 charset이 하는 것은 .uppercase()
하는 것 밖에 없다.
return if (charset?.uppercase() == "UTF-8") {
uppercase()
를 보아하니 String
이라고만 적힌 것이 String?
은 허용하지 않는 것 같았다(Kotlin에서 얼마나 null체크를 해주는 건지는 모르겠지만). 즉 null일 때는 uppercase()
는 쓸 수 없지 않을까 하는 것.
하지만 다른 선배는 그 전 build에서 에러가 나서 이미 charset?.uppercase()
로 해결되었던 것일지도 모른다고 했다. 확실히 에러에 적힌 build 시간은 그 전 릴리스에 의한 것이었지만 그렇다면 왜 그 다음 릴리스에서는 낫지 않고 몇 시간동안 계속된 것일까..
public actual inline fun String.uppercase(): String = (this as java.lang.String).toUpperCase(Locale.ROOT)
때문에 나는 아래와 같이 수정해서 PR을 냈다.
어차피 if조건문에서는 앞에 있는 조건을 먼저 체크하기 때문에 그 다음에 있는 charset은 null일리가 없다고 판단했기 때문이다. 하지만 이도 여전히 String?
이 될 수도 있기 때문에 확실한 방법이라고 할 수 없다.
import org.jsoup.Connection
private fun isValid(res: Connection.Response): Boolean {
val charset = res.charset()
return if (!charset.isNullOrBlank() && charset.uppercase() == "UTF-8") {
true
} else {
LOGGER.info("not UTF-8 encoded. charset is $charset")
false
}
}
결론적으로 디버그가 끝난 코드는 아래와 같다.
선배들 조언에 따르면 ==null
에 의해 Kotlin에서는 그 다음 행부터 !
형이 된다고 한다. 따라서 가장 확실한 방법이긴 하다.
import org.jsoup.Connection
private fun isValid(res: Connection.Response): Boolean {
val charset = res.charset()
if (charset == null) {
LOGGER.info("charset is null")
return false
}
if (!charset.isNullOrBlank() && charset.uppercase() == "UTF-8") {
return true
}
LOGGER.info("not UTF-8 encoded. charset is $charset")
return false
}
로깅이 필요없다면 아래와 간결하게 같이 쓸 수 있다.
import org.jsoup.Connection
private fun isValid(res: Connection.Response): Boolean {
val charset = res.charset() ?: return false
return if (charset.uppercase() == "UTF-8") {
true
} else {
LOGGER.info("not UTF-8 encoded. charset is $charset")
false
}
}
참고로, charset이 붙어있지 않은 경우는 대부분 default값으로 UTF-8이 지정되어 있는 경우인 것이 대부분이기 때문에 return true
를 해도 된다.
그건 또 다른 PR로 리퀘스트 요청해야한다.
'기타 메모' 카테고리의 다른 글
Google Guice는 언제 쓸까 (0) | 2023.09.15 |
---|---|
Kibana 웹페이지에 접속이 안될 때 (0) | 2022.03.24 |
아무 생각 없이 git access token지웠다가 fatal에러 나서 다시 인증해야 할 때 github cli 쓰면 편함 (0) | 2021.11.29 |
java로 만들어진 툴을 사용하려는데 Unrecognized VM option 'AggressiveOpts' 에러가 날 때 (feat.jEnv) (0) | 2021.10.11 |
node 버전을 nodebrew로 관리하기 (0) | 2021.09.14 |