Notice
Recent Posts
Recent Comments
Link
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
Tags
- equals
- 열 속성
- DI
- java
- AOP
- Spring
- MSA
- Test
- KEVISS
- docker
- VUE
- stream
- SQL
- select_type
- DDL
- hashcode
- cache
- 재정의
- 필드 주입
- jpa
- StringBuilder
- static
- 생성자 주입
- 인덱스
- lambda
- jwt
- 조합
- 테스트 코드
- redis
- 바이너리 카운팅
Archives
- Today
- Total
백엔드 개발자 블로그
null 리턴은 왜 나쁠까? 본문
null 리턴 나쁜점
코드를 읽는 사람 입장에서 복잡성을 만듭니다.
null 값 하나로 문맥 정보를 추론해야하므로 개발자의 생산성이 떨어질 수 있습니다.
해결안
로그에 맥락 남기기
주석은 실제 코드가 아니므로, 로그에 맥락을 남겨 맥락을 쉽게 이해할 수 있도록 하는 것이 좋습니다.
예외 처리나 로깅을 통해 맥락을 코드에 명시적으로 드러내봅시다.
class UserRepository {
fun findByName(name: String): User {
val result: User? = db.getUserBy(name)
if (result == null) {
throw IllegalStateException("""|
|인사관리 시스템과 동기화 되지 않은 유저의 이름을 입력한 경우 이 메시지를 볼 수 있습니다.
|매주 월->화 넘어가는 자정에 인사 관리 시스템과의 데이터 동기화가 수행되므로, 새로운 사람이 월요일이 아닌 다른 날짜에 입사하지 않았는지 확인하십시오.
|다음 주 월요일까지 기다리거나, 수동 동기화를 실행하면 문제가 해결될 수 있습니다.
|
|인사 관리 시스템과의 데이터 동기화 로직은 UserRepositorySync 클래스를 참고하십시오.
|문제가 된 name=[$name]
""".trimMargin())
}
return result
}
}
맥락 처리를 위한 기능 만들기
먼저 if문을 사용하여 맥락 처리를 해봅시다.
재시도를 해도 null인 경우를 설명하지 못합니다.
val user: User? = userRepository.findByName("김토스")
if (user == null) {
// user가 null이면 유저가 인사관리 시스템과 동기화 되지 않은 경우임.
// 동기화를 한 번 트리거 시켜주도록 하자
userRepositorySync.trigger()
}
val user2: User? = userRepository.findByName("김토스")
print(user2!!) // 위에서 동기화를 한 번 시켜주었기 때문에 null일 수 없다
retryHandlerWhenMissing 함수를 통해 맥략 처리를 해봅시다.
if를 통한 맥락 표현을 없앴고, user에 null이 안들어갑니다.
하지만 retryHandlerWhenMissing 함수가 무조건 실행 됩니다.
val user: User = userRepository.findByName(
name = "김토스",
retryHandlerWhenMissing={ userRepositorySync.trigger() }
)
print(user) // non-null type
필요할 때만 제공하기
적절한 기본값을 주거나 필요할 때만 기능을 사용할 수 있도록 제공하는 방식으로 바꿔봅시다.
기본값 "김토스", ResyncWhenUsermissing로 필요할 때만 사용하도록 구현해봅시다.
val user: User = userRepository
.withRetryPolicy(ResyncWhenUserMissing()) // 이 라인을 삭제해도 findByName() 호출에는 문제 없음
.findByName("김토스")
print(user) // non-null type
retryHandlerWhenMissing 에 무엇을 넣어야 하는지 파악해야 되는 문제를 줄일 수 있게 되었고,
로직을 그대로 노출하지 않으면서도 코드의 의도를 더 분명히 드러낼 수 있게 되었습니다.
하지만, 이런 식으로 코드를 작성하게 되면 UserRepository를 구현하기 까다로워집니다.
import org.springframework.data.jpa.repository.JpaRepository
interface UserRepository : JpaRepository<User, Long> {
// 이건 Spring Framework가 알아서 해주는데,
fun findByName(name: String): User
// 이건 어떻게 하지?
fun withRetryPolicy(retryPolicy: RetryPolicy): UserRepository
}
이런 식으로 개선하다보면 팀원들의 부담이 덜어줄 수 있는 코드륵 작성할 수 있게 됩니다.
'테크 블로그 리뷰' 카테고리의 다른 글
프로파일러로 성능 개선시키기 (1) | 2024.09.27 |
---|---|
서버 증설 없이 대규모 트래픽 처리하기 (0) | 2024.07.09 |
인자가 많은 메서드는 왜 나쁠까? (0) | 2024.03.13 |
Spring JDBC 성능 문제, 네트워크 분석으로 파악하기 (0) | 2024.03.13 |
캐시 문제 해결 가이드 - DB 과부하 방지 실전 팁 (1) | 2024.03.12 |