코드 신뢰성 향상: 올바른 데이터 타입 사용하기! (DateType편)
혹시 String createdAt 로 선언하지 사용하지 않으신가요?
DateTimeParseException 으로 고통받고 있지 않으신가요?
하지만 String 타입으로 데이터를 처리하고 있다면 버그나 Exception 이 발생하는 코드를 작성할 확률이 높아진다.
강타입 언어를 사용하는 장점을 전혀 활용하고 있지 못하기 때문에 적절한 타입을 사용하는 게 중요하다.
왜 도움이 되는지는 찬찬히 설명해 보려고 한다.
java 표준 API 사용되는 타입을 사용한다면 데이터에 대한 유효성 검증을 library level (정확히는 Type 이 생성되는 시점) 에서 검증이 된다. Exception Handling이나 validation check를 코드를 작성하는 개발자가 직접 하지 않아도 된다는 뜻이다.
그렇다면 “9999-99-99” 라는 String type 이 있을 경우, 이 변수로 오늘부터 몇이 남았는지 를 구현하게 된다면 어떻게 될까?
바로 아래와 같은 예외를 마주하게 될 것이다.
java.time.format.DateTimeParseException: Text '9999-99-99' could not be parsed: Invalid value for MonthOfYear (valid values 1 - 12): 99
at java.base/java.time.format.DateTimeFormatter.createError(DateTimeFormatter.java:2023)
at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1958)
at java.base/java.time.LocalDate.parse(LocalDate.java:430)
at java.base/java.time.LocalDate.parse(LocalDate.java:415)
적적한 Exception 처리를 하지 않았다면, 서비스에서 에러가 발생할 것이다. 예외가 발생한 라인에 validation 코드를 적절히 처리했다고 해도, String type의 날짜 문자열이 코드에 존재하는 한 언제 가는 또 발생할 수 있다. 그리고 API request의 parameter 나 request body로 데이터가 전달되었다면, 디버깅을 하고 어떤 API 요청이 왔는지 찾는데 시간이 걸릴 것이다.
(참고로 Json 은 Number, boolean, String type 만 표현이 가능하다)
그렇다면, 처음부터 LocalDate type 을 사용하면 어떻게 될까?
WebApplication을 개발하는 상황에서 데이터가 생성되는 상황은 외부 시스템에 의존된 상황이다.
좀 더 쉽게 설명을 한다면, HTTP API request 시 파라미터로 전달받거나, DB에서 조회해 올 수가 있다.
데이터 베이스의 경우에는 Date type 이 있기때문에 해당 타입의 칼럼을 사용하면 좋다.
그렇다면 HTTP request 에서는 어떻게 처리할 수 있을까?
LocalDate createdAt 으로 타입을 선언한다면 쉽게 반영이 된다. 그렇게 사용한다면 Framework 혹은 언어 Level에서 타입의 안정성을 보장해 준다.
하지만 현실세계는 그렇게 호락호락하지 않다.
"2000.01.01" "2000/10/01" 과 같이 다양한 문자열형태로 인터페이스를 하고 있을지도 모른다.
아래는 예제 코드 이다.
package net.anyjava.blogcode.controller;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDate;
@RestController
public class LocalDateController {
@GetMapping("/localdate-default")
public LocalDate localDateDefault(@RequestParam LocalDate createdAt) {
return createdAt;
}
@GetMapping("/localdate")
public LocalDate localDate(
@DateTimeFormat(pattern = "yyyy.MM.dd")
@RequestParam LocalDate createdAt) {
return createdAt;
}
}
위 Controller 코드에 대한 테스트 코드는 GitHub에서 확인하길 바란다.
위 코드처럼 내가 운영하는 시스템에서 Input 이 되는 지점부터 정확한 타입을 사용한다면, 에러상황을 사전에 예방할 수 있다.
그렇지 않고 String type의 date 형태의 문자열을 시스템에 전반적인 영역에서 사용된다면 언제든지 DateTimeParseException의 고통에서 자유로울 수 없다.
강타입언어를 사용한다면, Stirng에 타입에 "2022-01-01", "Y", "N", "10.9"처럼 동적 타입처럼 사용하지 않길 바란다. 나도 개발하면서 4,5년 차에 알게 되었다. 이제부터라도 제대로 된 타입을 사용하기 위해 노력해 보길 바란다.
이번에는 간단하게 Language에서 제공하는 기본 타입에 대해서 설명을 했다.
다음번에는 우리가 직접 만드는 Class를 어떻게 적절하게 타입을 사용할 수 있게 되는지 글을 작성해 보려고 한다.