미뤄왔던 https 연결 작업을 다시 해보자.
작년 9월 초에 프로젝트를 끝마친 이후 두 달 정도 쉬다가 11월 쯤 부터 스스로 웹 개발에 대한 역량을 더 끌어올리기 위해 알고리즘, 스프링 등에 대한 공부를 하느라 벌써 4개월이 넘는 시간이 흘렀다.
이젠 공부도 할 만큼했고, 슬슬 포트폴리오를 만들어서 각종 회사에 서류를 넣고 취업을 할 시점이 된 것이다.
클래스간 의존관계 주입 방식 수정
작년 9월 초에 프로젝트를 끝마친 이후 두 달 정도 쉬다가 11월 쯤 부터 스스로 웹 개발에 대한 역량을 더 끌어올리기 위해 알고리즘, 스프링 등에 대한 공부를 하느라 벌써 4개월이 넘는 시간이 흘렀다.
이젠 공부도 할 만큼했고, 슬슬 포트폴리오를 만들어서 각종 회사에 서류를 넣고 취업을 할 시점이 된 것이다.
그러기 위해 포트폴리오를 작성하기 전, 인프런에서 수강했던 스프링 강의에서 배웠던 점을 통해 Pro.gg 프로젝트에서 설계가 잘못된 부분을 조금 수정해줬다.
이전에는 아래와 같은 방식으로 필드 주입 방식을 통해 클래스간에 의존성을 주입해 주었었다.
@Autowired
MemberServiceImpl memberService;
위의 코드는 국비 학원 수강중일때 강사님께서 강의용으로 작성하신 코드를 그대로 활용한 것인데, 이때는 이와 같이 필드 주입 방식으로 클래스간의 의존성을 주입해주고 있었다.
(학원에서 강의를 들을 때는 그냥 강사님이 작성하는 코드를 무지성으로 따라하는 경우가 많은데, 이런 경우가 바로 국비 학원의 최대 단점이라고 할 수 있다. 어떤 코드가 좋은 코드인지 모르고 그냥 무작정 강사님이 작성 하시는대로만 따라가게 되는 것이다.)
(심지어 그냥 코드만 작성하고 넘어가는 수준이라 이 코드가 스프링 프레임워크와 엮여서 어떤 역할을 수행하는지 제대로 알지 조차 못하고 넘어가게 된다.)
필드 주입 방식의 경우 다음과 같은 특징이 있다.
- 코드가 간결해서 많은 개발자들을 유혹하지만 주입되는 클래스를 외부에서 변경하는것이 불가능해서 테스트하기 힘들가는 치명적인 단점이 있다.(의존성을 바꾸려면 구현체 코드를 직접 변경시켜 줘야 하므로 OCP 원칙에도 위배된다.)
- 필드 주입 방식으로 의존성을 주입할 경우 DI 프레임워크(스프링 프레임워크) 가 없으면 아무것도 할 수 없다.
https://evan-development.tistory.com/218?category=969786
스프링 핵심원리 : 기본편 - 다양한 의존관계 주입 방법
evan-development.tistory.com
정리하자면 필드 주입 방식으로 의존성을 주입할 경우 후에 의존성으로 주입해주는 구현체가 변경되면, 해당 사항을 적용하기 위해 의존성을 주입받는 구현 클래스 내부에서 코드를 변경해 주어야 한다.
즉, 구현체 외부의 변화가 구현체 내부의 코드의 변화로 이어지기 때문에 SOLID 원칙에서 OCP 원칙을 위반하게되며, 구현체 클래스를 직접 자료형으로 선언하여 사용하고 있으므로 DIP 원칙에도 위배된다.
의존성 주입은 생성자 주입 방식을 활용하자.
필드 주입방식의 문제점을 해결하기 위해 생성자 주입 방식을 활용해 줄 수 있다.
코드는 다음과 같다.
- SummonerController.java
private final MemberService memberService;
private final SummonerService summonerService;
@Autowired // 생성자가 하나만 존재할 경우 어노테이션 생략 가능
public SummonerController (MemberService memberService, SummonerService summonerService){
this.memberService = memberService;
this.summonerService = summonerServicel;
}
코드를 위와 같이 작성하면 MemberService 객체와 SummonerService 객체를 SummonerController 에 의존성으로서 주입해줄 수 있게 되는데, 이때 MemberService 와 SummonerService 는 둘 다 구현체가 아닌 인터페이스이다.
위와 같이 작성해주면 스프링 컨테이너에서 SummonerController 객체를 스프링 빈으로서 등록할 때 해당 생성자를 보고 스프링 컨테이너에 MemberService, SummonerService 빈(Bean) 객체가 존재하는지 확인한 다음, 해당 객체들이 존재할 경우 위의 생성자를 실행시키면서 SummonerController 객체를 생성하고 스프링 빈으로 등록함과 동시에 두 객체에 대한 의존성 주입까지 함께 처리해준다.
즉, 스프링 빈 등록과 의존성 주입을 한번에 처리해주는 것이다.
이렇게 구현체가 아닌 인터페이스 객체를 생성하면서 생성자 주입 방식으로 의존성을 주입해주면, 구현체가 아닌 인터페이스 객체를 통해 의존성을 주입해주는 것이기 때문에 추후에 인터페이스를 구현하는 구현체가 변경되더라도 의존성을 주입받는 클래스 내부에서 코드가 변경될 일이 없기 때문에 OCP 원칙을 준수하게 될 뿐 더러,
구현체타입으로 직접 의존성을 주입받는것이 아니기 때문에 DIP 원칙 또한 준수하게 된다.
만약 생성자 코드를 작성해주는 것이 귀찮다면 롬복을 활용하여 다음과 같이 코드를 간소화 시켜줄 수 있다.
- SummonerController.java
@Service
@RequiredConstructor
public class SummonerController {
private final MemberService memberService;
private final SummonerService summonerService;
}
롬복에서 제공하는 @RequiredConstructor 어노테이션을 활용하면 final 키워드가 붙은 필드들로만 자동으로 생성자를 생성해주기 때문에 굳이 개발자가 생성자 코드를 작성해줄 필요가 없게 된다.
이와 같은 방식을 이용하여 Pro.gg 프로젝트에서 기존에 필드 주입 방식으로 의존성을 주입하던 코드들을 모두 생성자 주입 방식으로 변경해 주었다.
'프로젝트 > 협업' 카테고리의 다른 글
Pro.gg - 프로젝트 회고록(10) : 최종 (0) | 2022.03.17 |
---|---|
Pro.gg - 프로젝트 회고록(9) : HTTPS 연결을 위한 서버 재할당...그리고 삽질 (0) | 2022.03.16 |
Pro.gg - 프로젝트 회고록(7) : 게시판 글 작성 및 댓글,답글 작성 (0) | 2021.10.26 |
Pro.gg - 프로젝트 회고록(6) : 팀 구성 및 매칭 (0) | 2021.10.22 |
Pro.gg - 프로젝트 회고록(5) : 소환사 정보 - 2 (0) | 2021.10.19 |