TIL - JAVA spring DAY 9

jihan kong·2022년 1월 15일
0

JAVA spring 입문

목록 보기
11/20
post-thumbnail

저번 시간까지 컴포넌트 스캔과 자동 의존관계를 설정하는 방법을 배웠다.
스프링을 사용한다면 스프링 컨테이너안의 스프링 빈을 통해 MemberService, Repository, Controller 와 같은 객체들을 관리하는 것이 효율적이라는 것을 배웠고, 이것이 정형화된 패턴임을 알게 되었다. 이번 시간에는 스프링 빈을 컴포넌트 스캔으로 하는것이 아니라 직접 등록하는 방법을 배우게 되었다.
이를 위해, hellospring package에 SpringConfig 라는 class를 만들었다.

SpringConfig class에 들어갈 내용은 다음과 같다. (SpringConfig class를 생성하기 전에 저번 시간에 했던 MemberService의 @Service, MemoryMemberRepository의 @Repository @Autowired annotation을 각각 삭제하고 시작하였다. but, @Controller는 제외 )

@Configuration
public class SpringConfig {

    @Bean
    public MemberService memberService() {
        return new MemberService(memberRepository());
    }

    @Bean
    public MemberRepository memberRepository() {
        return new MemoryMemberRepository();
    }
}

위에서 보는 바와 같이 class를 따로 만들고 @Bean annotation을 사용해서 직접 스프링 빈을 등록했다는 것이 특징이다. 그리고 등록이 되어있는 memberServicememberRepository를 parameter로 받아서 연결시켜주었다.

이렇게 1.컴포넌트 스캔방식2. 코드로 직접 스프링 빈을 등록하는 방법을 각각 살펴보았다. 그렇다면 둘 중 편리한 방식은 무엇일까? 당연히 컴포넌트 스캔방식일 것이다. 클래스 혹은 메소드 위에 @(annotation) 한줄이면 끝나니까... 그런데 왜 두 가지 방식을 모두 알아야할까?

사실 두 방법에는 각 장단점이 있다. 실무에서는 주로 정형화된 컨트롤러, 서비스, 리포지토리 같은 코드(일반적으로 생성하는 컨트롤러, 서비스 등)는 컴포넌트 스캔을 사용한다. 그리고 정형화되지 않거나, 상황에 따라 구현 클래스를 변경해야 하면 설정을 통해 스프링 빈으로 등록한다. '상황에 따라 구현 클래스를 변경'하는 경우가 구체적으로 어떤 경우일까?

우리가 지금까지 생성하고 개발한 MemberRepository를 살펴보자.

(사진 출처: 인프런, 스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술, 강사: 김영한)

맨 처음 회원 관리 예제를 개발할때, 아직 데이터 저장소가 선정되지 않았음을 가상의 시나리오로 설정하고 시작했다. 그래서 interfaceMemberRepository를 설계 하고, 구현체로 MemoryMemberRepository를 사용하는 그림이 만들어진 것이다. 그러나 데이터 저장소가 선정되면 우리는 MemoryMemberRepository를 DB에 실제 연결할 수 있는 다른 리포지토리로 바꿀 것이다.

그 때, 기존 코드들을 전혀 손대는 것 없이 바꿀 수 있게 해주는 것이 직접 스프링 빈으로 등록하는 것의 장점이다. Config 즉, 설정 패널을 만든 셈이므로 설정 값 하나만 바꾸면 되는것이지만 컴포넌트 스캔 방식을 사용했다면 각 코드에 붙어있는 annotation이라든지 생성자 같은 것을 수정해야하는 번거로움이 있는 것이다.

또한, DI에는 필드 주입, setter 주입, 생성자 주입 이렇게 3가지 방법이 있지만 의존 관계가 실행 중에 동적으로 바뀌는 경우는 거의 없으므로 대부분 생성자 주입을 사용한다. (필드 주입은 필드의 내용을 바꿀 수 있는 방법이 없어 그닥 좋지 않은 방법이고 setter 주입의 경우, set 메소드를 public으로 접근할 수 있는 여지가 생길 수 있으므로 사용하지 않는 편) 다음과 같은 방식이 생성자 주입 방식이다.

public class MemberService {

    private final MemberRepository memberRepository;
    
    public MemberService(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }

마지막으로 @Autowired 를 통한 DI는 helloController, MemberService 등과 같이 스프링이 관리하는 객체에서만 동작한다. 스프링 빈으로 등록하지 않고 내가 직접 생성한 객체에서는 동작하지 않는다. 이렇게해서 스프링 빈과 의존관계에 대한 모든 내용을 학습했다. 빈을 직접 코딩해서 등록해서 사용할 것인지, 컴포넌트 스캔을 사용해서 등록할 것인지 적재적소에 알맞게 사용하는 것이 좋겠다.

profile
학습하며 도전하는 것을 즐기는 개발자

0개의 댓글