Spring Web Layer의 동작과정을 공부하면 좋습니다.
현재 LoginService는
을 포함하고 있습니다.
이를 코드로 어떻게 짜야 확장성이 좋은 코드인지를 고민해보는 글입니다.
public interface LoginService {
public spring 스크래핑();
public Form 포맷팅();
public Member DB저장 메소드 호출();
}
public class LoginServiceImpl {
private final MemberRepository memberRepository;
@override
public spring 스크래핑();
@override
public Form 포맷팅();
@override
public Member DB저장 메소드 호출();
}
public class LoginController {
private final LoginService loginService;
@PostMapping("/login")
public String login(){
loginService.스크래핑();
loginService.포맷팅();
loginService.DB저장 메소드 호출();
}
}
public interface LoginService {
public Member login();
}
public class LoginServiceImpl {
private final MemberRepository memberRepository;
@override
public Member login(){
private spring 스크래핑();
private Form 포맷팅();
private Member DB저장 메소드 호출();
}
private spring 스크래핑(){
//로직
}
private Form 포맷팅(){
//로직
}
private Member DB저장 메소드 호출(){
//로직
}
}
public class LoginController {
private final LoginService loginService;
@PostMapping("/login")
public String login(){
loginService.Login();
}
}
결론부터 말하면 2번 방식으로 구현하였습니다.
이유 : 로그인서비스에 변화가 필요할 때 로그인서비스 구현체만 건드리면 되기 때문이다. 만약 다른 로그인 서비스 로직을 만들 경우에 스크래핑, 포맷팅, DB저장에 맞게 커스터마이징 해야하는데 이를 전부 다 커스텀마이징 쉽지 않기 때문이다. 그렇기에 LoginService를 2번 방식으로 구현하여 확장성을 높이는 방식을 사용하였다.
++TMI
1번 방식 또한 절때 틀린 것은 아니다. 상황에 따라 다르게 쓰는 것이다.
예를 들어 게임 서비스를 구현한다고 생각했을 때 게임모드 서비스가 있다면 이는 1번 방식을 사용해야한다. 저격 기능, 라이플 기능 등을 사용할 수 있는데 이는 공격이라는 메소드를 오버라이딩하여 구현할 수 있을 것이다!!
저는 결론부터 1번 방식이 향후 유지 보수에 더 도움이 될 것이라 생각합니다.
하지만
이 세가지 메소드들은 모두 관심사가 다른 기능들이기 때문에 각각의 기능들을 인터페이스로 선언 하고 각 인터페이스의 구현체들을 구현해 놓은 후 loginController에서 사용하는 방안이 향후에 메소드 방식이 변경되더라도 유연하게 확장 가능하도록 구성하는 편이 좋다고 생각합니다.
위의 말을 코드로 말씀드리자면
public class LoginController {
private final 스크래핑인터페이스 스크래핑;
private final 포맷팅인터페이스 포맷팅;
private final MemberDBService memberDBservice;
@PostMapping("/login")
public String login(){
스크래핑.스크래핑();
포맷팅.포맷팅();
memberDBservice.save( data );
}
}
저는 2번의 방법이 조금 더 좋아보입니다. 컨트롤러가 어떻게 로그인할지 서비스에 대한 인터페이스를 알고 있다는 점이 확장성 측면에서 좋지 못할 것 같아요. (로그인 하는 방법이 여러 가지로 늘어나게 되는 경우..)