안녕하세요.

오늘은 MongoDB 데이터를 메서드로 주입하는 방법에 대해 포스팅 합니다.

노말한 방법은 MongoDB 데이터를 클래스 필드 이름이랑 매칭 시켜 주입합니다.

노말한 방법은 이전 포스팅을 참고해주세요!

SpringBoot와 MongoDB 연동하기

그런데, 만약 MongoDB데이터의 키 값과 클래스 필드 이름 매칭이 아닌, 클래스 필드 이름은 자유롭게 사용하고 싶을때는 어떻게 해야 할까요? 또는 데이터를 가공해서 넣고 싶을 때는 어떻게 해야 할까요?

즉 이번 포스팅은 MongoDB데이터를 먼저 받고 처리 하는것이 아닌 MongoDB 데이터를 받는 시점에서 처리하는 방법에 관한 것입니다.

@Field Annotation API 사용하기

위에서 언급한데로, 만약 MongoDB데이터의 키 값과 클래스 필드의 이름을 따로 사용하고 싶다면, @Field API를 사용하면 됩니다.

예를들어, MongoDB에 아래와 같은 Document를 가지는 Person Collection이 있다고 가정합니다.

{
   "name": "Mommoo",
   "job": "developer"
}

이 데이터를 주입 받는 Person 클래스를 아래와 같이 만들었다고 가정합니다.

@Document(collection="person")
public class Person {
   private String name;
   private String job;
}

위와 같은 상황이라면, 문제 없이 데이터를 주입 받습니다.

하지만 만약, Person의 멤버변수 namedeveloperName으로 바꾸고 싶다면 아래와 같이 @Filed API를 사용합니다.

@Document(collection="person")
public class Person {
   @Field("name")
   private String developerName;
   private String job;
}

@Field Annotation API를 이용하여 데이터 주입 메서드 만들기

문제상황 설정

Person Collection 정보를 위와 같이 따로 받지 않고, 아래의 NameCard 클래스로 받고 싶다면 어떻게 해야 할까요?

public class NameCard {
   private String developerName;
   priavte String job;
}

당연히 이런건, Person Collection에 NameCard 키를 추가 한 후 거기에 name과 job을 넣어 구조를 맞추는 경우가 많지만...

노말한 방법중 하나는 위의 Person 클래스로 데이터를 받고, NameCard를 뒤늦게 만드는 방법 입니다.

아래의 예시 처럼요.

@Document(collection="person")
@Getter //lombok 라이브러리 getter를 자동으로 만들어 줍니다.
public class Person {
   private String name;
   private String job;
}

public class Person2 {
   private NameCard nameCard;
   
   public Person2(NameCard nameCard){
       this.nameCard = nameCard;
  }
}

//Person을 주입 받은 어떤 메서드가 있다고 가정합니다.
public Person2 convertPersonToPerson2(Person p) {
  NameCard nameCard = new NameCard(p.getName(), p.getJob());
  return new Person2(nameCard);
}

해당 예시의 특징은 persistence class (Person)domain class(Person2)를 나누어서 사용하는 것을 알 수 있습니다. 즉, PersonDTO역할을 하며, Person2business logic역할을 합니다.

하지만, Spring이 추구하는 프로그래밍 패러다임중 하나인 POJO를 이루고자 한다면, 그렇게 좋은 구조는 아닌거 같습니다.

Plain Old Java Object : 그냥, 평범한 객체 오브젝트를 뜻합니다.

객체를 Data Holder로만 사용하면 도메인 영역을 처리하기 어려우니,

기존의 객체지향 방식으로 데이터 와 관련있는 기능들을 클래스에 넣음으로써, 도메인 영역을 더 효율적으로 처리하자는 의미입니다.

POJO방식으로 처리

위에서 언급한 DTObusiness logic을 한곳에서 처리 하기 위해서는 데이터 주입을 원하는 곳으로 받고 처리할 수 있어야 합니다.

아래와 같이 데이터 주입을 메서드로 받음으로써, 처리 할 수 있습니다.

public class Person {
  private NameCard nameCard = new NameCard();
 
  @AccessType(AccessType.Type.PROPERTY)
  @Field("name")
  public setName(String name) {
      nameCard.setDeveloperName(name);
  }
 
  @AccessType(AccessType.Type.PROPERTY)
  @Field("job")
  public setName(String job) {
      nameCard.setJob(job);
  }
}

마무리

생성자로 데이터를 주입받는 방법도 있지만, 해당 방법은 데이터에 대응하는 필드가 반드시 존재 해야 합니다. 그렇기에 위와 같이 필드가 아예 다를 때는 메서드로 주입 받아야 합니다.

주입받는 메서드의 접근 제어자는 무조건 public이어야 합니다. 그렇지 않으면 런타임 에러가 발생합니다.

Jackson 라이브러리를 사용 하신다면, 해당 setter 메서드 때문에 원하지 않게 JSON 구조로 잡힐때가 있습니다. 그럴 경우에는 아래와 같이 @JsonIgnore API를 사용하시면 됩니다.

public class Person {
   
   @JsonIgnore
   @AccessType(AccessType.Type.PROPERTY)
   @Field("name)
   public setName(String name) {
      ...
  }
}


포스팅이 도움 되셨다면, 커피 한잔 후원해주세요!
더 좋은 포스팅 작성에 큰 힘이 됩니다.

Buy me a coffeeBuy me a coffee

+ Recent posts