service interface 분리(?)

2013-04-24 22:02

안녕하세요 처음으로 slipp.net에 질문을 올려봅니다

제가 게시판 기능을 구현하고 있습니

처음엔 관리툴이 없던 게시판이었는데

관리툴이 추가가 되면서

Service에 기능이 많이 붙게 됐습니다.

  • 여기서 게시판 서비스 클래스를 Admin 과 front 로 분리해서 개발해야 할까요?

처음엔 admin 기능이 많지 않아서 분리하지 않고,

게시판 서비스 클래스에 byadmin 해가면서

클래스에 메소드를 추가했습니다~

그러다 기능이 점점 많아지고

소스도 복잡해져서 뭔가 깔끔하게 정리하고 싶다는 욕구가 생겨서 질문글을 올립니다.

제가 해결방법으로 생각하는 내용은

  • admin과 front 게시판 서비스 interface를 만들어서 필요한 메소드를 추가한뒤에 기존 service가 새로 생성한 admjn 과 front인터페이스를 구현하도록 처리한다.

  • 어드민과 프론트 서비스를 구분한다
  • ???

첫번째 방법은 전에 재성형이 알려줬던 내용인데,

이 방법에서 제가 좋은점이라고 느끼는 부분은

interface를 구현해서 admin과 front의 공통적인

기능을 중복으로 작성하지 않아도 된다라는 부분입니다

제가 생각한 방법 말고 다룬 좋은 방법이 있을까요?

그리고, 첫번째 방법으로 한다고 했을때

제가 잘못알고 있는 부분이나 이해를 못하는 부분에 대해서 많은 조언 부탁드립니다~

인터페이스 개념을 다시 공부해야 하나..

8개의 의견 from SLiPP

2013-04-24 22:40

저는 개인적으로 admin / front 나누어야 하는지요?? 나눈다에 의문을 가지는게 아니라 ..(나눈다는게 무엇을 의미하시는지 궁금하기도 합니다.) 왜 그렇게 admin과 front 로 구분해야하는지 의문이 들었습니다...

관리자 기능이라고 한다면 무엇이 있을까요????

2013-04-25 10:08

이 글에 내가 관련이 있으니 의견을 추가해 본다.

먼저 문제가 되는 상황은 하나의 도메인을 front(일반 사용자에 대한 서비스를 담당하는 모듈)와 admin(관리자가 사용하는 모듈)에서 같이 사용하는 경우가 발생한느데 이 때 각 모듈에서 필요한 인터페이스가 달라지는 것이 이슈이지. 예를 들어 다음과 같은 구조로 보고 이야기를 전개한다.

slipp-core - slipp-web : www.slipp.net - slipp-admin-web : admin.slipp.net

위와 같이 각 모듈별로 도메인을 가지고 분리되는 경우 Service 클래스를 어떻게 가져가는 것이 좋겠느냐?

UserService.java => slipp-web과 slipp-admin-web에서 모두 이 인터페이스에 의존관계를 맺는 경우 프로젝트 규모가 작을 때는 괜찮지만 프로젝트의 복잡도가 높아지는 경우 이슈가 되기 때문에 가능하면 각 모듈별로 인터페이스를 분리하는 것이 좋지 않을까라고 제안을 한 것이다. 예를 들어 다음과 같은 구조가 될 것이다.

public interface UserService {
    User findById(Long id);
}



public interface UserAdminService {
    User findById(Long id);


    List<User> findUsers();
}



public class DefaultUserService implements UserService, UserAdminService {
    public User findById(Long id) {
        // 구현
    }


    public List<User> findUsers() {
        // 구현
    }
}

위와 같이 각 모듈별로 필요한 인터페이스를 분리하고 각 모듈에서는 인터페이스와만 의존관계를 가지는 것이다. 예를 들어 slipp-web 모듈은 UserService와 의존관계를 가지고, slipp-admin-web 모듈은 UserAdminService와만 의존관계를 가진다. 위와 같이 구현할 경우 중복 코드도 발생하지 않으면서 각 모듈에서 필요한 기능만 노출할 수 있기 때문에 캡슐화에도 좋을 것이라 생각한다.

프로젝트 운영이 계속해서 발생하다보면 모듈은 추가되고, api도 추가되는데 그 때마다 모든 api를 노출하기 보다는 각 모듈에서 필요한 api만 노출하는 것이 좋은 선택이라 판단된다.

slipp-core - slipp-web : www.slipp.net - slipp-admin-web : admin.slipp.net - slipp-batch-web

프로젝트 규모에 따라 달라지겠지만 일정 수준이 되는 순간 위와 같이 분리하는 운영 측면에서 좋다고 생각한다.

2013-04-25 11:44

@자바지기 다형성을 이용하는 것인데, 막상 controller에서 저 다형성으로 어떻게 표현되나요? 저 interface만 가지고 뭔가를 할 수 없을 것 같아서요. 느낌이 오지를 않아서 의견 남겨 봅니다.

저는 이 문제는 도메인에 대한 정의와 그에 따른 위임으로 풀어야 하지 않을까 그냥 생각이 듭니다. (이런 표현도 느낌이 오지는 않죠 ~ ^^;;)

2013-04-25 14:04

@newoverguy 각 Controller에서는 다음과 같은 구조로 구현할 수 있겠지. 먼저 slipp-web에서 위 인터페이스를 사용한다면 다음과 같이 구현하겠지.

public class UserController {
    @Autowired
    private UserService userService;



    public String show(Long id, Model model) {
        model.addAttribute("user", userService.findUserId(id));
        return "users/show";
    }
}

위 UserService 인터페이스에 대한 구현체는 당연히 앞의 DefaultUserService가 된다. slipp-admin-web 모듈의 Controller는 다음과 같이 구현할 수 있다.

public class UserAdminController {
    @Autowired
    private UserAdminService userService;


    public String index(Model model) {
        model.addAttribute("users", userService.findUsers);
        return "users/index";
    }



    public String show(Long id, Model model) {
        model.addAttribute("user", userService.findUserId(id));
        return "users/show";
    }
}

위 UserService 인터페이스에 대한 구현체도 당연히 앞의 DefaultUserService가 된다. 이와 같이 구현체는 같지만 각 모듈에서 다른 인터페이스와 의존관계를 가짐으로써 각 모듈에서 필요한 api만 사용할 수 있도록 할 수 있다.

---- 저는 이 문제는 도메인에 대한 정의와 그에 따른 위임으로 풀어야 하지 않을까 그냥 생각이 듭니다. (이런 표현도 느낌이 오지는 않죠 ~ ^^;;) => 이 문제를 도메인에 대한 정의와 위임으로 풀어야 한다고 했는데 말만 들어서는 명확하게 떠오르는 점이 없다. 소스 코드를 통해서 풀어주거나 좀 더 구체적으로 풀어주면 좋겠다.

2013-04-25 14:56

@자바지기 제가 코드로 얘기를 하지 않아서 ㅜㅜ;

결론적으로만 얘기하면 저런 사용방식이라면 굳이 interface 정의가 필요한가 해서요.

지금 코드 샘플 주신 것 처럼 각 영역에 맞는 - UserService, UserAdminService - 구분만 하고 쓰는 곳에서 해당 업무를 수행하는 UserService와 UserAdminService를 선택해서 사용하면 되지 않을까 해서요~

제가 위에서 언급한 부분이 바로 형이 샘플로 주신 부분입니다. 다만, 그 중에서 "interface 부분에 대해서는 다형성 측면이 아니면 정의 하지 않아도 될 것 같다" 정도의 이견이 있는 것이구요~~

2013-04-26 09:24

@newoverguy 내가 글을 잘 이해했는지 모르겠다.

지금 코드 샘플 주신 것 처럼 각 영역에 맞는 - UserService, UserAdminService - 구분만 하고 쓰는 곳에서 해당 업무를 수행하는 UserService와 UserAdminService를 선택해서 사용하면 되지 않을까 해서요~ => 이 의미는 굳이 인터페이스로 구현하지 않고 인터페이스 없이 UserService와 UserAdminService를 클래스로 직접 구현해서 사용해도 괜찮다는 의미로 받아들이면 될까?

만약 그런 의미라면 UserService와 UserAdminService 사이에 중복이 발생할 가능성이 많지 않을까? 그렇다면 이 중복을 제거하기 위해 부모 클래스를 만들어 해결해야 되겠지. 나는 그 보다는 인터페이스를 통해 분리하고 구현을 하나로 통합하는 것이 같은 도메인을 관리한다는 차원에서는 좋지 않을까라는 생각을 해본다.

내가 너의 답변을 정확하게 이해한 것이 맞는지 모르겠다.

2013-04-27 21:38

@양완수 제가 너무 단순하게 질문을 했나보네요; 재성형이 얘기한데로 service는 공통으로 쓰이고 admin과 front를 분리하는 구조로 질문을 올렸었습니다.

@자바지기 고맙습니당 ㅠㅠ 소스 예제까지 보여주시면서.. 이해가 됐습니다. 열게쪽 서비스가 점점 복잡해져서 전에 재성형이 얘기해주셨던 부분이 생각나서 질문글을 올렸었어요~~ 클린코드 다시 읽어보면서 리팩토링에 대해서 좀더 생각을 해봐야겠네요 ㅠㅠ 감사합니다~

의견 추가하기

연관태그

← 목록으로