현재 진행중인 프로젝트에서 회원가입 개발을 담당하고 있다.
전화번호 인증 과정이 있는데 여기서 문자로 받은 인증 코드를 입력해야 하는 절차를 구현해야 했다.
문자 내용을 받는 객체를 만들고 담을 변수를 선언했는데
아래와 같은 코드가 작성되었다.
private var smsReceiver: SmsReceiver? = null
private fun startSmsReceiver(context: Context){
SmsRetriever.getClient(context).startSmsRetriever().also { task ->
task.addOnSuccessListener {
smsReceiver = SmsReceiver()
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU){
context.registerReceiver(smsReceiver, smsReceiver!!.doFilter(),
Context.RECEIVER_NOT_EXPORTED)
}else{
context.registerReceiver(smsReceiver, smsReceiver!!.doFilter())
}
viewModelScope.launch {
SmsReceiver.smsCode.collectLatest {
setUserInputSmsCode(it)
}
}
}
task.addOnFailureListener {
stopSmsReceiver(context)
}
}
}
PR 후 코드 리뷰를 받으면서 아래와 같은 피드백을 받았다


SMS 리시버 클래스를 작성하면서 참고한 글에서는 저렇게 null을 사용하고 있어서 그대로 사용했지만 추후 혹시라도 발생할 에러를 예방하기 위해 null로 초기화하는 방법이 아닌 다른 방법을 찾아야 했다.
생각해보니 코틀린에서는 자바와 달리 지연초기화를 할 수 있어서 쉽게 해결할 수 있었다.
kotlin의 지연초기화는 내부적으로 사용한 객체의 레퍼런스를 null로 초기화 처리해준다고 한다.
private val smsReceiver by lazy { SmsReceiver() }
private fun startSmsReceiver(context: Context){
SmsRetriever.getClient(context).startSmsRetriever().also { task ->
task.addOnSuccessListener {
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU){
context.registerReceiver(smsReceiver, smsReceiver.doFilter(),
Context.RECEIVER_NOT_EXPORTED)
}else{
context.registerReceiver(smsReceiver, smsReceiver.doFilter())
}
viewModelScope.launch {
SmsReceiver.smsCode.collectLatest {
setUserInputSmsCode(it)
}
}
}
task.addOnFailureListener {
stopSmsReceiver(context)
}
}
}
null 초기화 대신 lazy 지연초기화를 사용하면서 자연스레 !! 연산자도 지울 수 있었다.
앞으로 코틀린 코드를 작성할 때 null 사용을 최소화하여 프로그램의 안정성을 올리는 방향으로 작성해야겠다.