Spring Boot

의존성 주입

have a good time 2021. 12. 7. 16:09

 

 

프로젝트에서 회원가입 코드를 만들 때,

AuthController.java 에서 AuthService.java의 회원가입 메서드를 사용하려고 한다면

 

AuthController.java에 AuthService 오브젝트를 의존성 주입해야 한다.

 

 

즉, 아래에서 볼 수 있듯이 

AuthController.java 파일에서 signup 메서드를 보면 

authService.회원가입(user);

 

이렇게 AuthService의 회원가입 메서드를 활용하려고 한다면,

의존성 주입이 필요하다.

 

 

<AuthController.java> 파일

@RequiredArgsConstructor
@Controller
public class AuthController {


	private final AuthService authService;
	
	@PostMapping("/auth/signup")
	public String signup(@Valid SignupDto signupDto, BindingResult bindingResult) {

		
	
		if (bindingResult.hasErrors()) {
			Map<String, String> errorMap = new HashMap<>();

			for (FieldError error : bindingResult.getFieldErrors()) {
				errorMap.put(error.getField(), error.getDefaultMessage());
			}
			throw new CustomValidationException("유효성 검사 실패함", errorMap);
		}else {
		
			
		
		User user = signupDto.toEntity();
		
	
		
		
		authService.회원가입(user);
	
		return "auth/signin";

	   }
	}
	
	
	
	
	
}

 

<AuthService.java> 파일

@RequiredArgsConstructor
@Service
public class AuthService {

	
	private final UserRepository userRepository;
	private final BCryptPasswordEncoder bCryptPasswordEncoder;
	
	
	
	
	@Transactional 
	public User 회원가입(User user) throws RuntimeException{
		String rawPassword = user.getPassword();
		String encPassword = bCryptPasswordEncoder.encode(rawPassword);
		user.setPassword(encPassword);
		user.setRole("ROLE_USER"); // 관리자 ROLE_ADMIN
		User userEntity = null;
		userEntity = userRepository.save(user);
		
		
		return userEntity;
	}
	
	
}

 

 

이때 의존성 주입하는 3가지 방법을 알아보자.

(AuthSerivce.java는 @Service 어노테이션으로 ioc 처리 되어 있다는 전제하에 진행)

 

1. 

AuthController.java에 아래처럼 의존성 설정을 한다.

 

@Autowired

private AuthService authService;

 

 

 

@Controller
public class AuthController {

	@Autowired
	private AuthService authService;
	
	
	@PostMapping("/auth/signup")
	public String signup(@Valid SignupDto signupDto, BindingResult bindingResult) {

		
	
		if (bindingResult.hasErrors()) {
			Map<String, String> errorMap = new HashMap<>();

			for (FieldError error : bindingResult.getFieldErrors()) {
				errorMap.put(error.getField(), error.getDefaultMessage());
			}
			throw new CustomValidationException("유효성 검사 실패함", errorMap);
		}else {
		
			
		
		User user = signupDto.toEntity();
		
		authService.회원가입(user);
	
		return "auth/signin";

	   }
	}
	
	
	
	
	
}

 

 

2. AuthController.java에 아래처럼 의존성 설정

 

private AuthService authService;

public AuthController(AuthService authService) {

      this.authService = authService;

}

 

 

 

@Controller
public class AuthController {

	
	private AuthService authService;
	
	public AuthController(AuthService authService) {
		this.authService = authService;
	}
	
	
	
	
	@PostMapping("/auth/signup")
	public String signup(@Valid SignupDto signupDto, BindingResult bindingResult) {

		
	
		if (bindingResult.hasErrors()) {
			Map<String, String> errorMap = new HashMap<>();

			for (FieldError error : bindingResult.getFieldErrors()) {
				errorMap.put(error.getField(), error.getDefaultMessage());
			}
			throw new CustomValidationException("유효성 검사 실패함", errorMap);
		}else {
		
			
		
		User user = signupDto.toEntity();
		
		authService.회원가입(user);
	
		return "auth/signin";

	   }
	}
	
	
	
	
	
}

 

AuthController.java에는 @Controller가 붙어 있어서

스프링이 AuthController를 ioc 등록하는데(컨테이너 메모리에 로드)

즉, 이때 AuthController 객체를 만들기 때문에, 생성자가 필요하다.

 

그런데 위의 코드에서 

 

public AuthController(AuthService authService) {

      this.authService = authService;

}

 

이처럼 사용자가 정의한 생성자를 실행하려 보니깐,

매개변수로 AuthService 객체가 있다.

 

때문에, 스프링은 이미 ioc에 등록한 AuthService가 있다면

(즉, @Service 애노테이션으로 AuthService가 ioc되어 있다면)

위의 생성자에 AuthService 객체를 집어 넣어주기 때문에(의존성 주입)

AuthController.java에서 사용할 수 있다.

 

 

그런데 이렇게 매번 생성자를 입력하는 것은 귀찮기 때문에

세번째 방법을 소개한다.

 

3. AuthController.java 파일에서 아래처럼 의존성 설정한다.

위 2번째 방법과 차이점은,

 

생성자 만드는 코드를 없애고,

@RequiredArgsConstructor 어노테이션을 사용하고,

 

private AuthService authService 변수에

final 을 추가했다는 점이다.

 

 

@RequiredArgsConstructor

@Controller

public class AuthController {

 

 private final AuthService authService;

 

 

 

@RequiredArgsConstructor
@Controller
public class AuthController {

	
	private final AuthService authService;
		
	
	@PostMapping("/auth/signup")
	public String signup(@Valid SignupDto signupDto, BindingResult bindingResult) {

		
	
		if (bindingResult.hasErrors()) {
			Map<String, String> errorMap = new HashMap<>();

			for (FieldError error : bindingResult.getFieldErrors()) {
				errorMap.put(error.getField(), error.getDefaultMessage());
			}
			throw new CustomValidationException("유효성 검사 실패함", errorMap);
		}else {
		
			
		
		User user = signupDto.toEntity();
		
		authService.회원가입(user);
	
		return "auth/signin";

	   }
	}
	
	
	
	
	
}

 

private final AuthService authService;

이 코드에서 볼 수 있듯이

자바에서는 전역 변수에 final이 있으면

객체가 만들어질 때 초기화를 무조건 해줘야 한다. 즉 생성자가 필요하다.

그런데 

@RequiredArgsConstructor 애노테이션은,

final이 있는 변수의 생성자를 자동으로 만들어준다.

 

이 방법이 편리하기 때문에, 프로젝트를 하면서 이 방법을 사용한다.

 

-끝-

 

참고 자료 : 이지업 강의 사이트 "스프링부트 SNS프로젝트 - 포토그램 만들기"