API 서버 개발 중, '생년월일'를 쿼리해와서 응답객체엔 '생년월일'과 '만 나이' 모두를 담아야 하는 요구사항이 있었다.
처음엔 다음과 같이 Response 클래스에 age 필드를 추가하고, birthDate 를 age 로 직접 바꿔서 필드에 값을 넣어줫다
// age 필드 직접 추가
// Response.kt
class Response(
val birthDate: LocalDate,
) {
val age: Int = birthDate.toAge() //확장함수 toAge()
}
그런데, 다른 개발자분이 만들어 놓으신BirthDate
클래스, BirthDateSerializer
클래스를 발견해서 해당 클래스에 대해 알아보고 사용하고자 한다
먼저 BirthDate
와 BirthDateSerializer
를 보자
// BirthDate
@JsonSerialize(
using = BirthDateSerializer::class,
)
data class BirthDate(
val value: LocalDate?,
val formatter: DateTimeFormatter = DateTimeFormatter.ISO_DATE
)
LocalDate
값과 Format
을 갖는다@JsonSerialize
어노테이션이 선언되어 있다BirthDateSerializer
를 사용한다고 명시해두었다.// BirthDateSerializer
@Component
class BirthDateSerializer(private val generatorService: GeneratorService): JsonSerializer<BirthDate>() {
override fun serialize(birthDate: BirthDate, generator: JsonGenerator, provider: SerializerProvider) {
generator.writeString(birthDate.value?.format(birthDate.formatter))
when (val resolveAge = resolveAge(birthDate, RequestContextHolder.getZoneId())) {
null -> generator.writeStringField("age", null)
else -> generator.writeNumberField("age", resolveAge)
}
}
fun resolveAge(birthDate: BirthDate, zoneId: ZoneId): Short? {
// ...
}
}
JsonSerializer<>
를 상속받아 serialize
를 구현한 모습serialize
메서드에서 BirthDate
를 받아와서 generator
의 writeXXX
메서드를 이용해 birthDate
와 age
를 넣는 모습@Component
) @JsonSerializer
에 등록해서 사용 가능Serialization (직렬화)
: 객체를 데이터스트림(ex. 바이트 스트림)으로 만드는 것. 네트워크 전송 등, 데이터를 이동시켜야 할 때 필요하다.
( ex. 세션 객체를 저장할 때 외부 스토리지 등 네트워크 자원을 사용해야 저장할 수 있는 상황이면, 직렬화를 반드시 해야함)
직렬화엔 여러 포맷이 존재하는데, 표 형태의 다량 데이터를 직렬화 할땐 CSV / 단일 객체 기반 구조적 데이터는 XML, JSON 으로 직렬화할 수 있다.
라고만 하면 처음엔 이해할 수 없다.
다음 글을 읽어보면 감이 온다.
TL;DR
직렬화 = Reference 값이 가르키는 실제 값을 모두 긁어와 Primitive 값으로 변조하는 작업
블로그: https://ahma.tistory.com/65 (아래쪽 '댓글'본문을 확인하자)