HTTP 200 OK

Memento mori & Carpe diem

Spring

MSA 환경에서의 @JsonProperty 활용

sjoongh 2024. 10. 13. 13:59

데이터 필드 불일치 문제

필자는 MSA 환경에서 여러 서비스 간에 데이터를 주고받고 데이터 필드명을 일치시킬 때 @JsonProperty를 사용하던 중 이슈가 발생했습니다. 바로 A서버에서 매핑한 데이터를 B서버에서 받지 못하는 상황이였습니다. 많은 분들이 @JsonProperty를 사용해보셨을 것 같고 저 또한 유용하게 사용하고 있었지만 동일한 JSON 객체를 2개 이상의 서버에서 연동시키며 사용해봤던 경험은 없었기에 이슈에 대한 해결방안을 공유하고자 글을 작성했습니다.

 

@JsonProperty의 사용과 제한사항

@JsonProperty는 내부 서버 통신에서만 매핑을 수행합니다. 즉 해당 서버 내부에서만 필드명이 변환되고 외부 서버와 통신할 때는 적용되지 않습니다. 앞선 이유 때문에 외부와 연동된 서버에서 @JsonProperty로 JSON 데이터를 객체 필드에 매핑하거나 객체 필드를 JSON으로 직렬화할 때 필드명을 변경해주어도 내부 서버에서는 해당 데이터를 받지 못하는 것이었습니다....

 

예제

import com.fasterxml.jackson.annotation.JsonProperty
import com.fasterxml.jackson.databind.ObjectMapper

data class User(
    @JsonProperty("memberId") val userId: String
)

fun main() {
    val objectMapper = ObjectMapper()

    // 객체를 JSON으로 직렬화
    val user = User("12345")
    val json = objectMapper.writeValueAsString(user)
    println("Serialized JSON: $json")  // Serialized JSON: {"memberId":"12345"}

    // JSON을 객체로 역직렬화
    val deserializedUser = objectMapper.readValue(json, User::class.java)
    println("Deserialized User ID: ${deserializedUser.userId}")  // Deserialized User ID: 12345
}

 

해결방안

외부 서버에서 전달받은 JSON데이터를 내부 도메인 서버와 통신할 때 필드명이 일치하지 않는 경우에는 두 가지 주요 전략을 고려할 수 있습니다. 필자의 경우에는 여러 외부 서버에서 최초로 요청을 받는 서버를 구성했고 해당 서버에서 JSON 변환을 구성해야 했습니다. 이 때 API를 1개로 구성하고 싶어 JsonTypeInfo를 사용했습니다.

또한 @JsonProperty를 사용한 DTO 객체 1개와 내부 도메인 서버로 전송해야할 DTO를 추가로 구성해 전달했습니다.

 

아래와 같이 ExternalMemberDTO와 MemberDTO를 각각 정의한 이유는 최초 진입 서버에서 외부 데이터를 받아 로컬에서만 처리한 후 내부 도메인의 요구에 맞게 변환한 데이터를 전달하기 위함입니다. 이러한 결과를 만들기 위한 방법은 몇가지 있겠지만 장기적으로는 솔루션별로 DTO정보를 관리하는 작업도 필요했기에 DTO를 두개로 구성했습니다.

import com.fasterxml.jackson.annotation.JsonProperty

// 외부 서버에서 전달받는 JSON 데이터
data class ExternalMemberDTO(
    @JsonProperty("userId") val memberId: String,
    val name: String
)

// 내부서버로 전달할 DTO
data class MemberDTO(
    val memberId: String,
    val name: String
)

 

이처럼 하나의 서버 또는 게이트웨이에서 변환처리를 해주어도 좋고 상황에 따라 내부 도메인에서 직접 변환시켜주어도 좋습니다.

 

  1. 게이트웨이에서 변환 처리: 게이트웨이에서 외부 서버로의 요청과 응답을 처리하면서 필드명을 변환하는 방법입니다. 게이트웨이를 활용하면 모든 요청에 대해 일관된 변환을 중앙에서 처리할 수 있기 때문에 필드 불일치 문제를 효율적으로 관리합니다.
  2. 도메인 레이어에서 변환 처리: 외부 서버와의 통신이 특정 서비스와 밀접하게 연관되어 있다면 도메인 레이어에서 직접 매핑 처리를 수행하는 것이 더 적합할 수 있습니다. 이렇게 하면 특정 서비스 내에서만 변환 로직을 처리하고 유지보수를 더 직관적으로 수행 할 수 있습니다.

 

결론

@JsonProperty를 사용할 때는 내부 서버 간 통신에 한정된다는 점을 염두하고 외부 서버와 통신할 때는 게이트웨이에서의 처리와 도메인 레이어에서의 처리 중 어느 것이 더 적합한지 상황에 따라 선택하는 것이 중요합니다.

 

MSA에서는 항상 각 서비스의 책임을 분리하고 어떠한 지점에서 내가 원하는 로직을 구현할지에 대한 선택과 고민을 자주 하는 것 같습니다. 이미 알고 있다고 생각한 개념과 익숙하게 사용하고 있던 것들도 새롭게 놓여진 상황에서는 기존에 생각하지 못했던 이슈가 발생하는 것 같습니다.

 

모든 상황에 대비하는 폭 넓은 개발 지식을 가진 개발자가 된다면 좋겠지만 이슈가 발생했을 때 원인을 신속히 파악하고 정확한 개념과 지식을 알고 있다고 판단되어도 현재 상황에서는 문제가 발생할수도 있지 않을까?? 하고 의심하는 과정도 필요하다고 느꼈습니다.