가끔 Api의 RequestBody로 Map객체를 받아야할 필요가 있다.
Api의 RequestBody의 필드값들이 가변적이거나, 요청에 따라 바뀌는경우등의 케이스에 유연하게 대응하기위해서,
Map객체를 받게 구현을 할때가 있다.
이경우는 사실 코드상에서의 유려한 흐름으로 읽히는 코드는 포기해야한다.
Map<String, Any> req 이런 객체에서 req.get("name"), req.get("age")등으로 꺼내써야 하고,
값이 Any 타입으로 선언되어있기 때문에, 캐스팅도 해야하는 코드가 덕지덕지 붙게 됨에 따라,
깔끔하지 못하고,
개발자가 class로 구성된 DTO와 달리 필드를 바로 확인할수가 없고,
문서나 주석등에 의존하거나 코드 전체를 훝어야 한다....
이런 문제를 문득,
코틀린의 Delegate를 사용하여, Map을 개발자가 읽을수있는 객체로 구현을 해볼수있지 않을까? 라는 생각이 들었다.
바로 구현을 해봤다.
결과는 상당히 만족한다.
( 역시, 아이디어가 떠오르고, 실제 구현했을때, 그 생각대로 구현이 될때, 개발자로써 가장 희열을 느낀다 ^^ )
구현은 아래 (가칭) FlexMap코드이다.
Map객체에 delegate를 만들어 연결해줬고, data class안에 필드를 정의할수있게하고, 해당 필드를 map delegate에 위임하도록 by this로 설정하였다.
그리고 toString()을 오버라이드하여, innerMap이 toString()에 innerMap이라는 필드로 노출되는것을 막았다.
data class FlexMap (private val innerMap:MutableMap<String, Any> = mutableMapOf())
: MutableMap<String, Any> by innerMap {
var name by this
var age:Int by this
override fun toString(): String {
return innerMap.toString()
}
}
fun main() {
val req = FlexMap()
req.name = "tommy"
req.age = 60
println(req)
}
//결과 : {name=tommy, age=60}
이렇게 구현을 하면, FlexMap을 사용하면, name, age와 같은 필드를 명시적으로 선언하여 사용할수있고,
해당 필드는 자체적으로 innerMap에 위임되어 innerMap에서 값을 찾아서 연결이 된다.
필드로 표현을 할수있기에, 해당 필드에 대해서 다른 델리게이터를 연결하면, 암호화, 필드 검사등을 추가로 할수있다.
(일반 필드에 적용하는 모든것을 명시적으로 동일하게 할수있다)
저 10줄남짓의 코드가 나에게는 엄청난 희열을 주었다.
'MY아이디어' 카테고리의 다른 글
| [아이디어] Actuator와 RateLimiter의 능동적 동작에 대해서 (0) | 2026.01.10 |
|---|
