[백엔드 첫 걸음] 스프링 빈과 의존관계 - (회원 관리 예제)

khyojun·2022년 7월 25일
0

Spring 시작

목록 보기
11/15
post-thumbnail

1. 컴포넌트 스캔과 자동 의존관계 설정

📂 java/controller/MemberController.java

@Controller
public class MemberController {
    private final MemberService memberService;


    @Autowired
    public MemberController(MemberService memberService){
        this.memberService=memberService;
    }

}

Controller를 생성하여 @Controller 어노테이션과 @Autowired 어노테이션을 사용하였다. 이렇게만 진행을 하게 되면 다음과 같은 그림처럼 일어나게 된다.

그림의 화살표를 @Autowired로 의존관계를 넣어준다고 생각해보면 된다. 그치만 아직 memberService가 Bean으로 등록되어있지 않기 때문에 연결이 되지 않았다.

MemberService Bean 등록

📂 java/service/MemberService.java

@Service
public class MemberService {

    private final MemberRepository memberRepository;
    @Autowired
    public MemberService(MemberRepository memberRepository){// DI
        this.memberRepository = memberRepository;
    }

.
.
.

MemberRepository Bean 등록

📂 java/repository/MemoryMemberRepository.java

@Repository
public class MemoryMemberRepository implements MemberRepository {
    private static Map<Long, Member> store = new HashMap<>();
    private static long sequence= 0L;

.
.
.

아래와 같이 각각의 어노테이션들을 추가하였다. Service에서는 @Service Repository에서는 @Repository를 추가하였다.

이번에 추가된 어노테이션은 @Controller, @Repository, @Service를 추가하였다.

컴포넌트 스캔 원리

  • @Component 애노테이션이 있으면 스프링 빈으로 자동 등록된다.
  • @Controller 컨트롤러가 스프링 빈으로 자동 등록된 이유도 컴포넌트 스캔이라는 것 때문이다.

🏸 @Component를 포함하는 다음 애노테이션은 스프링 빈으로 자동 등록된다.

  • @Controller
  • @Service
  • @Repository

🏸 그러면 @Autowired?
위 그림에 보면 각각의 스프링 빈이 화살표로 의존관계에 속해있는 것을 볼 수 있는데 @Autowired를 통하여 스프링 컨테이너에서 해당 스프링 빈을 찾아서 주입시켜주는 역할을 한다.(즉 의존관계 생성)

2. 자바 코드로 직접 스프링 빈 등록하기

  • 이전의 코드에서 @Controller부분의 애노테이션을 제외하고는 다 지워주고 시작하였다.
    📂 java/SpringConfig.java
package com.example.demo_practice;


import com.example.demo_practice.repository.MemberRepository;
import com.example.demo_practice.repository.MemoryMemberRepository;
import com.example.demo_practice.service.MemberService;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Controller;

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

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

}
  • 위와 같은 코드를 작성하게 되었을때 아까와 같이 @Bean 애노테이션을 추가하여 스프링 빈으로 등록을 한 후 Autowired와 같은 역할을 return 할때 묶어줌으로써 의존관계를 생성하였다.

이후 실습에서는 자바 코드를 활용하여 Bean을 등록하는 방식으로 가기로 하였다.

  • DI에는 여러가지가 있는데 생성자 주입을 주로 사용을 한다.
  1. 필드 주입
@Autowired private  MemberService memberService;

이런 유형으로 진행이 되어지는데 이렇게 의존관계를 가지게 되면은 나중에 별도로 변경사항이 일어났을때 변경을 할 수 있는것이 없게 되서 잘 쓰이지 않는다.

  1. setter 주입
@Controller
public class MemberController {
    private final MemberService memberService;


    @Autowired
    public MemberController(MemberService memberService){
        this.memberService=memberService;
        memberService.setMemberRepository()
    }

}

------
public class MemberService {


    private  MemberRepository memberRepository;

    public void setMemberRepository(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }


와 같이 setter를 주입을 시키는데 문제점이 무엇이냐면 의존관계 주입을 하기위한 메소드인데 public으로 선언이 되야하므로 어쩔 수 없이 모든 사람이 이 메소드에 접근할 수 있어서 좋지 못한 방법이다.

  1. 생성자 주입
public class SpringConfig {
    @Bean
    public MemberService memberService(){
        return new MemberService(memberRepository());
    }

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



}

결국에는 이런 방식으로 생성자에서 주입을 시켜주는 방향으로 가는 것이 제일 좋았다. 그리고 또 장점으로 볼 수 있는 것이 나중에는 MemoryMemberRepository는 다른 Db로 바꿔줘야하기 때문에 이럴 경우 다른 주입방식과 같은 경우에서는 변경을 할 때에는 껄끄러운 부분이 있는 반면 생성자 주입일 경우에는 return new DbMemberRepository();와 같이 이름만 바꿔주면 되는 부분에서 되게 편안하다는 측면이 있다.

알게 된 점

  1. 스프링 빈으로 등록을 하고 각각의 의존관계를 생성해나가는 과정 속 어떻게 주입을 시켜줘야 효율적인지 알 수 있었다.

참고

김영한 - 스프링 입문 강의

profile
코드를 씹고 뜯고 맛보고 즐기는 것을 지향하는 개발자가 되고 싶습니다

0개의 댓글