미니 프로젝트/게시판

[Java] 게시판 ⑥ ModelMapper

웹개발자(진) 2024. 5. 24. 15:57
반응형
잡담

DB에 대한 설정 같은 경우 형식적으로 정해져 있는 경우가 많습니다. 왜 이렇게 생겼지?라고 생각하게 되는 경우가 많은데 이해하기엔 너무 많은 메서드를 들고 있어서 그렇습니다. 자주 사용하는 메서드가 어떤 동작을 해주는지를 이해하고 형태에 대해서는 그렇구나 하고 넘어가는 게 좋은 거 같습니다. 제 생각이 그렇다는 말이지 다른 생각이 있다면 그 생각이 맞습니다.


 

1. RootConfig

이 코드는 Spring Framework에서 ModelMapper를 설정하기 위한 설정 클래스입니다. ModelMapper는 객체 간 매핑을 쉽게 해주는 라이브러리로, 주로 DTO와 엔티티 간의 변환에 사용됩니다.

implementation 'org.modelmapper:modelmapper:3.1.1'

ModelMapper 라이브러리를 사용하려면 'build.gradle'에 위와 같은 의존성을 추가해주어야 합니다.

package org.zerock.b01.config;

import org.modelmapper.ModelMapper;
import org.modelmapper.convention.MatchingStrategies;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RootConfig {   //enum으로 사용하면 영속성컨텍스트가 안됨 클래스로 해야됨
    @Bean
    public ModelMapper getMapper(){
        ModelMapper modelMapper = new ModelMapper();
        modelMapper.getConfiguration()
                .setFieldMatchingEnabled(true)
                .setFieldAccessLevel(org.modelmapper.config.Configuration.AccessLevel.PRIVATE)
                .setMatchingStrategy(MatchingStrategies.LOOSE);
        return modelMapper;
    }
}

 

 @Configuration

어노테이션은 Spring Framework에서 설정 클래스를 정의할 때 사용됩니다. 설정 클래스는 주로 애플리케이션의 빈(Bean) 정의와 설정을 포함합니다.

 

  • @Bean 정의: @Configuration 어노테이션이 붙은 클래스는 한 개 이상의 @Bean 메서드를 포함하여, 이러한 메서드들이 반환하는 객체들이 Spring의 애플리케이션 콘텍스트에 의해 관리됩니다.
  • 싱글톤 보장: @Configuration 클래스의 @Bean 메서드들은 기본적으로 싱글톤(Singleton) 스코프로 관리됩니다. 따라서 여러 번 호출되어도 동일한 인스턴스를 반환합니다.

 

@Bean

어노테이션은 Spring 컨테이너에 의해 관리되는 빈을 정의하는 메서드에 붙입니다. 이 메서드는 보통 @Configuration 클래스 내에서 정의됩니다.

  • 메서드 레벨: @Bean 어노테이션은 메서드에 붙여져 그 메서드가 반환하는 객체를 Spring 컨테이너의 빈으로 등록합니다.
  • 명시적 빈 등록: 메서드 이름이 빈의 이름으로 사용됩니다. 이를 통해 개발자는 직접 컨테이너에 빈을 등록할 수 있습니다.
  • 의존성 주입: @Bean 메서드는 다른 빈 메서드를 호출하여 의존성을 주입받을 수 있습니다. 이는 설정 간의 의존성을 명확하게 관리할 수 있게 합니다.

 

    public ModelMapper getMapper(){
        ModelMapper modelMapper = new ModelMapper();
        modelMapper.getConfiguration()
                .setFieldMatchingEnabled(true)
                .setFieldAccessLevel(org.modelmapper.config.Configuration.AccessLevel.PRIVATE)
                .setMatchingStrategy(MatchingStrategies.LOOSE);
        return modelMapper;
    }

위의 코드는 ModelMapper에 대한 기본적인 설정을 지정해 주는 코드입니다. 위에 코드 말고도 다양한 설정이 있지만 연습이기 때문에 해당 설정들을 이용해서 Mapper를 초기화했습니다.

 

ModelMapper 설정:

  • setFieldMatchingEnabled(true): 필드 이름이 일치하면 매핑하도록 설정합니다.
  • setFieldAccessLevel(org.modelmapper.config.Configuration.AccessLevel.PRIVATE): 필드 접근 수준을 PRIVATE으로 설정합니다. 이를 통해 접근 제어자가 PRIVATE인 필드도 매핑할 수 있습니다.
  • setMatchingStrategy(MatchingStrategies.LOOSE): 매칭 전략을 LOOSE로 설정합니다. 이는 느슨한 매칭 전략으로, 필드 이름이 일부만 일치해도 매핑이 가능하게 합니다. 
    • 유연한 필드 매칭: 필드 이름이나 유형이 서로 다른 경우에도 가능한 많은 필드를 매핑하려고 시도합니다.
    • 대소문자 무시: 필드 이름의 대소문자를 무시하고 매핑을 시도합니다.
    • 띄어쓰기 무시: 필드 이름의 띄어쓰기를 무시하고 매핑을 시도합니다.
    • 유형 무시: 필드 유형이 다른 경우에도 매핑을 시도합니다. 이는 일부 변환을 수행하여 유형을 일치시킵니다.
    • 부분 매칭: 필드 이름의 일부가 일치하는 경우에도 매핑을 시도합니다. 이는 유사한 필드 이름을 가진 필드를 찾아 매핑합니다.

 


 

Servlet에서도 비슷한 코드를 활용해서 싱글톤으로 Mapper를 만들었던 기억이 있습니다. 아래의 코드가 Servlet에서 만든 Mapping 코드입니다. 해당 코드에서는 enum을 사용한 싱글톤패턴에서 enum의 각 요소는 상수로서 단일 인스턴스를 가집니다.

import org.modelmapper.ModelMapper;
import org.modelmapper.convention.MatchingStrategies;

public enum MapperUtil {
    INSTANCE;
    private ModelMapper modelMapper;

    MapperUtil() {
        modelMapper = new ModelMapper();
        modelMapper.getConfiguration()
                .setFieldMatchingEnabled(true)      //필드이름이 달라도 자동매칭 Mapping가능
                .setFieldAccessLevel(org.modelmapper.config.Configuration.AccessLevel.PRIVATE)//private까지 access하게 해주겠다.
                .setMatchingStrategy(MatchingStrategies.STRICT); //매칭시켰을떄 엄격하게 보겠다.
    }

    public ModelMapper getModelMapper() {
        return modelMapper;
    }
}

 

 

Enum은 생성자가 private이며, 외부에서 인스턴스화할 수 없습니다. 따라서 INSTANCE 상수가 인스턴스화될 때 생성자가 호출되어 modelMapper 필드를 초기화합니다. 이때 modelMapper는 static으로 선언되지 않았으므로 클래스 로딩 시점이 아닌 INSTANCE가 처음 사용될 때 초기화됩니다.

내부적으로는 해당 Enum 클래스의 상수들이 하나의 인스턴스로 인스턴스화됩니다. 이러한 특성은 멀티스레드 환경에서도 안전한 싱글톤 패턴을 제공합니다.

따라서 MapperUtil.INSTANCE는 애플리케이션 전체에서 단일 인스턴스로 공유되며, 이를 통해 싱글톤으로 작동합니다.

 


 

글을 마치며

이번 게시글에서는 ModelMapper 라이브러리에 대해 알아보았습니다. 언어를 공부하는 입장에서 싱글톤에 대한 개념자체가 매우 어렵습니다. 머릿속으로 생각은 하지만 코드로 구현하라 하면 안 되는 그런 느낌.. 싱글톤 개념은 예를 들어서 우리가 공연티켓을 구매한다고 생각했을 때 내가 예약하는 중에 다른 사람이 같은 자리를 예약했을 때 중복으로 예약되는 경우를 방지한다고 생각하면 됩니다. 하나의 객체를 통해서 다른 사람들도 해당 객체에만 접근해서 사용하게 되는 거죠.

이경우에 스레드도 함께 사용하게됩니다. 여러 스레드가 동시에 싱글톤 객체에 접근하려고 할 때 발생할 수 있는 문제 중 하나는 경쟁 상태(race condition)입니다. 이는 여러 스레드가 동일한 자원에 동시에 접근하여 예상치 못한 결과가 발생하는 상황을 의미합니다. 경쟁 상태를 방지하기 위해 싱글톤 객체를 스레드 안전하게 만들어야 합니다.

이런 개념하나하나가 나중에 사용된다고 생각하면 벌써부터 머리가 아픕니다. 다음시간에는 Controller를 만들어 보겠습니다. 클라이언트의 요청을 수신하여 view단에서 받은 데이터를 service를 통해 DB와 상호작용하고 그 데이터를 다시 view으로 뿌려주는 역할을 해주는 클래스입니다. 감사합니다.

반응형