Handling Null in Request DTO

About

Spring의 μ»¨νŠΈλ‘€λŸ¬μ—μ„œ @RequestBody μ–΄λ…Έν…Œμ΄μ…˜μ„ μ΄μš©ν•˜λ©΄ HTTP body에 μžˆλŠ” JSON 데이터λ₯Ό 객체둜 λ³€ν™˜ν•΄ λ°›μ•„μ˜¬ 수 μžˆλ‹€. JSON에 μžˆλŠ” λͺ¨λ“  데이터가 κΌ­ ν•„μš”ν•˜μ§€ μ•Šμ•„μ„œ μ˜€μ§€ μ•ŠμœΌλ©΄ λ¬΄μ‹œν•˜λŠ” κ²½μš°λ„ μžˆμ§€λ§Œ, μ „λΆ€ ν•„μš”ν•  μˆ˜λ„ μžˆλ‹€.

Java

Javaμ—μ„œλŠ” null checking을 μ–Έμ–΄ μ°¨μ›μ—μ„œ μ§€μ›ν•˜κ³  μžˆμ§€λŠ” μ•Šλ‹€. ν•˜μ§€λ§Œ Validation의 μ–΄λ…Έν…Œμ΄μ…˜μ„ 톡해 검증할 수 μžˆλ‹€.

ProfileUpdateRequest.java
@Getter
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class ProfileUpdateRequest {
    
    @NotNull
    private Int age;
    
    private String imageUrl;
}

@NotNull μ–΄λ…Έν…Œμ΄μ…˜μœΌλ‘œ ageκ°€ null이면 였λ₯˜λ₯Ό λ°˜ν™˜ν•œλ‹€.

Kotlin

μ½”ν‹€λ¦°μ—μ„œλŠ” nullable νƒ€μž…κ³Ό non-nullable νƒ€μž…μ„ κ΅¬λΆ„ν•˜μ—¬ null safeν•˜κ²Œ κ°œλ°œν•  수 μžˆλ‹€. 그런데 μ•½κ°„μ˜ μ£Όμ˜κ°€ ν•„μš”ν•˜λ‹€.

일단 μœ„μ˜ μ½”λ“œλ₯Ό μ½”ν‹€λ¦°μœΌλ‘œ λ°”λ‘œ λ°”κΎΈλ©΄ μ΄λ ‡κ²Œ 될 것이닀.

ProfileUpdateRequest.kt
data class ProfileUpdateRequest(
    @field:NotNull
    val age: Int

    val imageUrl: String
)

ν•˜μ§€λ§Œ μ—¬κΈ°μ„œ μ—¬λŸ¬ 가지λ₯Ό μˆ˜μ •ν•΄μ•Ό ν•œλ‹€.

  • 코틀린은 nullableκ³Ό non-nullable νƒ€μž…μ„ νƒ€μž… 뒀에 ?λ₯Ό λΆ™μ΄λŠ” κ²ƒμœΌλ‘œ κ΅¬λΆ„ν•œλ‹€. λ”°λΌμ„œ ageλŠ” μ• μ΄ˆμ— null이 될 수 μ—†λ‹€.

  • μ΄λ ‡κ²Œ μž‘μ„±ν–ˆμ„ λ•Œ ageκ°€ null둜 λ“€μ–΄μ˜€κ²Œ λœλ‹€λ©΄, @field:NotNull μ–΄λ…Έν…Œμ΄μ…˜μ„ 톡해 validation 둜직이 μ‹€ν–‰λ˜κΈ° 전에 λ³€μˆ˜μ— 값을 ν• λ‹Ήν•˜λŠ” κ³Όμ •λΆ€ν„° μ˜ˆμ™Έκ°€ λ°œμƒν•œλ‹€. λ”°λΌμ„œ μ—¬κΈ°μ„œ 이 μ–΄λ…Έν…Œμ΄μ…˜μ€ μ˜λ―Έκ°€ μ—†λ‹€.

  • μ›λž˜ @NotNull이 λΆ™μ–΄μžˆμ§€ μ•Šμ•˜λ˜ imageUrl은 nullable νƒ€μž…μ΄ λ˜μ–΄μ•Όκ² λ‹€.

μˆ˜μ •μ‚¬ν•­μ„ λ°˜μ˜ν•  λ•Œ μ΄λ ‡κ²Œ ν•΄κ²°ν•˜λŠ” 방법이 μžˆλ‹€.

ProfileUpdateRequest.kt
data class ProfileUpdateRequest(
    @field:NotNull    
    val age: Int?,

    val imageUrl: String?
)

λ‹€λ§Œ ν•΄λ‹Ή DTOλ₯Ό μ»¨νŠΈλ‘€λŸ¬μ—μ„œ λ°›μ•„μ„œ μ‚¬μš©ν•˜κ²Œ 될텐데, ageλŠ” μ‹€μ œλ‘œ null이 μ•„λ‹˜μ—λ„ λΆˆκ΅¬ν•˜κ³  age뒀에 ?λ₯Ό λΆ™μ΄λŠ” λ“± null checking을 진행해야 ν•œλ‹€. λΆˆνŽΈν•˜κΈ°λ„ ν•˜κ³ , κΉ”λ”ν•˜μ§€λ„ μ•Šλ‹€.

Solution

λ‚΄ 생각엔 이 방법이 κ°€μž₯ 깔끔할 것 κ°™λ‹€. λ‹€μŒκ³Ό 같이 μ§„ν–‰ν•˜μž.

  • null둜 받아도 λ˜λŠ” ν•„λ“œλŠ” λ‹¨μˆœνžˆ ?λ₯Ό 뢙인닀. μ•„λ‹ˆλ©΄ 뢙이지 말.

    ProfileUpdateRequest.kt
    data class ProfileUpdateRequest(
        val age: Int,
        
        val imageUrl: String?
    )
  • HttpMessageNotReadableException을 exception handlerμ—μ„œ 작고, ν•„μš”ν•˜λ‹€λ©΄ μΆ”κ°€ μž‘μ—…μ„ 톡해 MissingKotlinParameterException을 λ‚΄λΆ€μ μœΌλ‘œ νƒ€μž…μ„ 체크해 λ©”μ‹œμ§€λ₯Ό λ°˜ν™˜ν•œλ‹€.

참고둜, non-nullable νƒ€μž…μ— null이 λ‹΄κΈ°λ €κ³  ν•˜λ©΄ HttpMessageNotReadableException이 λ°œμƒν•˜μ§€λ§Œ, μ˜ˆμ™Έκ°€ λ°œμƒν•œ μ§„μ§œ 원인인 MissingKotlinParameterExceptionκ³ΌλŠ” 직접적인 클래슀 관계가 μ—†λ‹€.

REF

Last updated