티스토리 뷰

Java

MVC 구조에서 service와 serviceImpl

LichKing 2016. 2. 27. 14:40

이제는 JSP 개발시 MVC 패턴으로 작업하는게 당연시 되고있다. MVC패턴이란 화면에 보여줄 view 에 대한 작업, DB에서 조회 혹은 DB에 저장할 내용을 중간에 가공, 처리하는 비즈니스로직, DB에 연결하는 DAO 작업까지 JSP에서 다 하던걸 패턴화 시켜 분리하여 개발하는것인데 각각의 역할에 따라 파일들을 분리해서 작업하는것이다.

그렇게 하는 이유는 소스를 분리함으로서 각 소스의 목적이 명확해 지고 유지보수하는데 있어서 용이하기 때문이다.


MVC 패턴으로 개발하고자하면 자연스레 한 페이지에 5개의 파일이 생성되는데 JSP, Controller, DTO, Service, DAO 이다. 오늘 포스팅할 내용은 이 파일들 중 Service에 관한것이다. 


오랜시간 궁금했던 것

Service 에 대해선 항상 개인적으로 궁금하게 생각하던점이 하나 있었다. 거의 대부분의 프로젝트가 service 는 인터페이스로 생성하고 serviceImple이라는 구현객체를 생성해서 사용하고있던것이다. 물론 앞선 객체지향설계원칙에 대한 포스팅이나 DI에 대한 포스팅들을 바탕으로 생각했을때 인터페이스로 사용했을때의 장점을 모르는것은 아니나, 어차피 인터페이스와 구현클래스간의 관계가 1:1로 구성되게 되어 실질적으로 인터페이스 사용에 대한 이점을 전혀 가져가지못하게 되는데 왜 당연하다는듯이 이런식으로 구성을 하는지에 대한 궁금증이 항상 있었다.


그래서 주변 개발자들에게 물어보기도했으나 대부분 '다 이렇게 하던데' 정도의 답변이 돌아왔고 명확하게 설명해주는 경우를 볼수없었다. 또한 인터넷에 검색을 해봐도 나같은 궁금증을 가진 개발자가 자신의 생각을 적어놓은 글들만 있고 명확한 설명은 찾기가 힘들었다(내가 검색을 잘 못한탓도 있겠지만 내 수준에 이해하기힘든 글들도 많았다.). 그래서 궁금증을 시원하게 코풀듯 풀진 못하고 그냥 가슴한구석에 찜찜하게 남아있었는데 요근래 길을 걷다가 왜 그렇게 하는지에 대한 나만의 해답을 찾은듯하여 블로그에 남긴다. 물론 내가 검색해서 봤었던 여타 블로그들과 마찬가지로 나도 내 생각을 적는것이다.


잘못된 객체지향적 코딩

일단 내가 접해봤던(그리고 아마 그 외에도 상당수의 프로젝트들이) 프로젝트들은 전부 객체지향을 살려 디자인패턴을 도입하고 객체들간의 역할을 분리하여 객체들간의 협력으로 문제를 해결하는 식의 코딩을 진행하진 않았다. MVC패턴으로 개발한답시고 JSP, Controller, Model은 구분했지만 Service 클래스의 한 메서드 내에서 모든 비즈니스 로직이 진행되는 transaction script 형식의 코딩을 진행했다. 잘 생각해보면 자바는 객체지향언어라는 장점이 있다고 누누히 배워왔지만 정작 실제 현장에서는 C로 함수짜듯 절차지향적 코딩을 해왔다는 점이다. 사실상 우리에게 필요한건 Service 클래스내의 비즈니스로직을 처리하는 1개의 메서드일 뿐이고 그럼에도 불구하고 굳이 Service를 클래스로 만들고 객체를 생성해서 처리하는 이유는 그저 프로젝트에 도입된 언어가 자바이고, 자바는 메서드를 가지려면 무조건 클래스가 있어야했기때문인 것이다. 그렇게 개발을 하다보니 추가적인 요구사항, 혹은 수정사항이 들어오면 이 코드를 확장하여 개발하는것보다는 단순히 그 메서드에 if문을 추가하고, 혹은 소스 일부분을 주석처리하고 새로운 코드로 채우는 리팩토링이 절실한 코드였던 것이다.


MVC 패턴에서 Service Model 의 역할

MVC 패턴의 핵심은 View는 자신이 요청할 Controller만 알고있으면 되고, Controller는 화면에서 넘어오는 매개변수들을 이용해 Service 객체를 호출하는 역할을 한다. Service 는 불필요하게 Http 통신을 위한 HttpServlet을 상속 받을 필요도 없는 순수한 자바 객체로 구성된다(그렇기에 Service 에 request나 response와 같은 객체를 매개변수로 받아선 안된다. 그걸 사용해야하는 작업은 컨트롤러에서 해야한다.). 그렇기에 자신을 어떤 컨트롤러가 호출하든 상관없이 필요한 매개변수만 준다면 자신의 비즈니스로직을 처리하게된다. 즉 모듈화를 통해 어디서든 재사용이 가능한 클래스파일이라는 뜻이다. 단순 Web 기반이 아니라 추후 native app 으로 view단이 변경되더라도 Service는 view에 종속적인 코드가 없기때문에 그대로 재사용 할 수 있어야 한다. 그리고 추가적인 요청사항이 들어오면 기존 소스를 수정하는게 아니라 기존 service 인터페이스를 구현한 다른 클래스를 구현해 그 객체를 사용하게끔 하는것이다. OCP에 입각한 변화에는 닫혀있고 확장에는 열려있는 구조로 만들어야한다는 것이다.


결론

그렇기 때문에 Service를 인터페이스로 구성했던것이 아닐까 생각한다. 비즈니스 로직을 처리하는 모델은 요청사항에 따라 언제든 변할수있는 부분이었고 변화에 대응하기위해 확장을 염두하여 인터페이스로 구성했던것이다. 그런데 어디서부터 잘못된건지 Service를 인터페이스로 만들었던건 관례로 굳어지게 되었는데 개발은 transaction script 형식으로 진행하다보니 관례는 관례대로 남고 애초에 그렇게 하고자했던 이유는 사라져버리게 된것이다. 그래서 내가 내린 결론은 한 메서드에서 모든 역할을 다하는 이런 절차지향적 코딩에서는 사실 Service를 굳이 인터페이스로 할필요는 없다는 것이다. 물론 '그러니까 인터페이스 만들지말자' 보다는 애초에 인터페이스를 만들었던 이유를 잘 살리는게 바람직하지 않을까 생각하고, 나같은 궁금증을 가졌던 사람들에게 조금이나마 도움이 되는 글이었으면 좋겠다.

'Java' 카테고리의 다른 글

DesignPattern#02 Template Method Pattern  (0) 2016.03.02
DesignPattern#01 Strategy Pattern  (0) 2016.03.01
MVC 구조에서 service와 serviceImpl  (37) 2016.02.27
tiles3 설정  (0) 2016.02.18
String Class와 equals()  (0) 2015.12.02
call by value, call by reference  (0) 2015.11.25
공유하기 링크
TAG
댓글
  • 이전 댓글 더보기
  • 프로필사진 왕초보 service 인터페이스 꼭 써야하나 궁금증이 생겨서 찾다가 발견한 좋은 글.
    덕분에 궁금증이 해결되었습니다. 감사합니다!
    2018.07.11 11:02
  • 프로필사진 슬레이라 좋은 글 감사합니다. 글을 너무 인상적으로 읽어서 출처 남기고 글 링크를 블로그에 적어놓았습니다.
    혹시 맘에 안드셨다면 죄송합니다. 혹 그러셨다면 바로 글 내리도록 하겠습니다.
    https://blog.naver.com/slayra
    2018.07.12 17:49
  • 프로필사진 LichKing 아닙니다. 잘 봐주셔서 감사합니다 ㅎㅎ 2018.11.20 13:46 신고
  • 프로필사진 리냥짱 저도 한참을 이것에 대해 고민하다가 검색해봤는데 아주 정리가 잘 되어있네요. 감사합니다. 2018.07.24 16:52
  • 프로필사진 자바왕초보 궁금했던부분이였는데 잘읽었습니디
    감사합니다.
    2018.07.24 17:28
  • 프로필사진 자바시작 "추가적인 요청사항이 들어오면 기존 소스를 수정하는게 아니라 기존 service 인터페이스를 구현한 다른 클래스를 구현해 그 객체를 사용하게끔 하는것이다." 이 부분이 예전부터 너무 궁금했습니다. 어떻게 하는걸 말하는 건지 예시로 하나 부탁드려도 될까요 ㅠㅠ 2018.08.30 18:30
  • 프로필사진 LichKing 음... 영수증을 출력하는 ReceiptService 를 하나 만든다고 가정해볼게요. 영수증 출력 기기가 2개라서 2개의 포맷으로 출력을 해야한다고 가정해봅시다.
    이때 보통은 경우에따라 ReceiptService 안에있는 메서드를 수정하거나 혹은 메서드 자체를 2개로 만들겁니다. 그런데 ReceiptService를 구현하는 각각의 구현체를 둘수도있겠죠.
    AReceiptService, BReceiptService 이런형태로요.
    2018.09.01 16:58 신고
  • 프로필사진 최지웅 감사합니다. 2018.09.11 13:27
  • 프로필사진 complex1 Service를 인터페이스로 하는 것은, 아마 스프링의 AOP 때문일 것입니다. 인터페이스로 되어 있지 않으면 AOP 프록시를 만들 수 없는 걸로 알고 있습니다. 2018.11.20 13:42
  • 프로필사진 LichKing 이 글을 쓴게 벌써 3년이 다되가는 글이긴한데.. spring AOP는 JDK의 dynamic proxy를 이용하는 방법이 있고, CGlib를 이용하는 방법이 있습니다.
    전자의 경우엔 알고계신대로 인터페이스가 필요합니다. 이와관련한 포스팅을 예전에 작성한 적이있고요( http://multifrontgarden.tistory.com/228 ).

    후자의 방법은 인터페이스가 굳이 필요하지않습니다. 그래서 말씀해주신부분에는 전 동의하기가 힘듭니다.

    그런데 이글을 쓸때도 그렇고 지금도 그렇고 변하지않은 생각은 특정한 이유가 있어서 인터페이스를 만들고있다면 전 존중할 의사가 있습니다. '서비스에 왜 무조건 인터페이스 만들어?' 라는 질문에 '우리 프로젝트는 dynamic proxy 를 이용한 AOP를 쓰고있어서 만들어야해' 라고 대답할수있다면 전 충분히 존중합니다.

    전 인터페이스 만드는 그 자체를 존중하지않겠다는건 아니고, 어떤 이유가 됐든 이유가 있으면 좋겠다는 생각입니다. 습관적으로 만드는걸 별로 좋아하지않는것 뿐이죠.
    2018.11.20 13:53 신고
  • 프로필사진 정준기 좋은글 잘 보고갑니다. 2018.11.21 11:11
  • 프로필사진 Good 2019.01.03 01:05
  • 프로필사진 달거북이 왜? 라는 의문을 가지고 접근하는 것만큼 발전에 좋은게 없다고 하였는데 멋집니당 2019.03.18 10:03
  • 프로필사진 CTYU 잘보고 갑니다. 2019.03.22 11:46 신고
  • 프로필사진 권정윤 개인적인 생각으로는 Spring framework의 특징과 관련지어서 해답을 찾았습니다. spring에서는 객체를 bean으로 생성하고 각 객체에 의존성을 주입해서 사용하는 것으로 알고 있습니다. 그래서 service라는 뼈대를 만들어 놓고 다형성을 구현하기 위해 serviceimpl을 만들어 특정한 기능을 부여할 수 있게 사용한다고 생각합니다. 뼈대만 만들어놓고 안에 있는 내용만 바꿀 수 있다면 유지 보수 차원에서 굉장히 용이하기 때문입니다. 예를들어 식당이라는 객체에 접시1과 접시2라는 주입되어 있을 때 접시 1과 접시 2의 생김새만 만들어 놓으면 음식을 자유자재로 바꿀 수 있는거죠. 만약 interface로 뼈대를 만들어 놓지 않는다면 기능이 바뀔 때마다 새로운 메소드를 만들게 되서 연관된 파일을 전부 수정해야하는 불상사가 발생합니다. 2019.06.11 16:17 신고
  • 프로필사진 ㅇㅇ 그거야 교과서적인 답변이긴 한데... 글쓴 분은 실무에서 그렇게 적용이 안 되니까 고민하신 거죠. 2019.07.17 16:18
  • 프로필사진 엄범 맞는 말씀이긴 한데요. 그는 인터페이스의 다형성에 대한 원론적인 얘기이고, 본 글에서 말하고자 하는 것은 (메서드 하나에 절차지향 식으로 코딩하는건 당연히 안좋은 방식이니 차치하고,) 인터페이스의 구현체가 클래스 1개인 경우 인터페이스를 만들 필요가 있는가?에 대한 얘기라고 생각해요. 실제로 구현 클래스가 1개 뿐인데 인터페이스도 같이 만드시는 분들이 많이 있거든요. 어차피 구현 클래스가 1개이면 추후 새로운 클래스가 필요할 때 확장하면서 인터페이스를 만들어도 되는거고, 애초에 어플리케이션 완성까지 이 서비스 클래스 1개면 다른 구현체는 필요없겠다는 생각이 들 때가 많아요. 저는 그래서 공통 클래스가 2개 이상이 아니라 1개라면 그냥 인터페이스를 안만드는 방식을 선호합니다.

    또한 ServiceImpl이 아니라 Service를 통해 DI받는 것은 물론 좋은 방식이지만 어차피 구현체가 2개 이상임을 염두에 두고 작성할거라면 AutoWired를 사용할 수 없으니까요.(어떤 구현체를 DI해줄지 못찾으니까) 즉 어떤 구현체를 주입할 것인지를 명시해주어야 하는데, 이는 결국 어딘가에는 구체적인 의존성을 명시해주어야 한다는 얘기가 되므로 이를 위하여 구현 클래스가 1개인 경우에도 꼭 인터페이스를 만들어야 한다는 이유는 개인적으로는 와닿지는 않는 것 같아요.ㅎㅎ
    2019.07.20 09:21 신고
  • 프로필사진 LichKing 윗분들이 말씀해주신대로입니다.
    정윤님께서 말씀해주신건 당연히 맞는말이고요. 실제 실무에서 정윤님께서 말씀하시는대로 사용하지않으면서 인터페이스를 무조건 만들었던 것에 대한 고민이었고, 그 고민에 대한 나름의 결과를 블로그에 남긴거였습니다. (벌써 3년이 넘은 글이네요.)
    2019.08.03 18:39 신고
  • 프로필사진 3번 읽고 이해했습니다. 구현체가 하나인 인터페이스가 왜 필요한가...
    좋은 글 잘 봤습니다! 고맙습니다.
    2019.08.09 08:42
  • 프로필사진 djoy 저는 웹 애플리케이션을 개발하는 사람이 아니라 스프링 프레임워크와 같은 것을 잘 모릅니다만...인터페이스와 그 구현체를 쓰는게 원론적으로는 약한 결합을 지향하는 사고방식에서 나오지 않았나 생각해봅니다. 구체적은 클래스를 바로 작성해서 사용해도 틀렸다고 말할 수 없는 부분이죠. 자바가 지향하고자 하는 바를 잘 살리다보니 하나의 인터페이스에 하나의 구현체가 나오게 되지 않나 생각해봅니다.(아주 원론적이죠?) 그리고 다르게 한번 생각해보면...
    저 같은 경우에도 어떠한 프로그램을 짤 때 주요 뼈대 및 흐름 같은 것을 코딩해서 초급개발자에게 역할을 부여합니다. 물론 인터페이스로 작성해서 해당 기능에 대해 코딩하도록 업무지시를 내리게 되죠. 프로그램은 혼자 작성할 수도 있지만 협업을 해야하는 경우가 많자나요. 이런 경우를 생각해보면 인터페이스를 누군가가 작성해놓고 실제 구현은 다른 사람이 하도록 분할해 놓으려고 사용하지 않았으려나 생각해봅니다.
    2019.08.13 22:55
  • 프로필사진 kalkin 저도 이글에 동감합니다.
    물론 구현체가 하나밖에 나올 수없는경우는 인터페이스가 필요없는게 실제로는 맞습니다만...
    하지만 협업을 하다보면 큰뼈대를 설계자가 인터페이스를 통해 구현을 하면, 나머지 작업자들은 실제 구현은 그에맞게 구현할 수 밖에 없죠.
    함수명이라던가 리턴, 파라메터등....인터페이스에 맞춰 자연스럽게 코딩이 가능한것이 장점이 될수 있겠네요
    2019.10.17 07:37
  • 프로필사진 lake 오~! 저랑 같은 결론에 도달하신분이 있으시군요.
    저희 프로젝트에서도 이렇게 쓰는 소스를 가져와 처리하길래 인터페이스 만들지 말고 바로 클래스로 처리하라고 했죠.
    다행히 제가 PL이라... ㅎㅎ
    2020.09.18 16:47
  • 프로필사진 하다 "e 를 하나 만든다고 가정해볼게요. 영수증 출력 기기가 2개라서 2개의 포맷으로 출력을 해야한다고 가정해봅시다.
    이때 보통은 경우에따라 ReceiptService 안에있는 메서드를 수정하거나 혹은 메서드 자체를 2개로 만들겁니다. 그런데 ReceiptService를 구현하는 각각의 구현체를 둘수도있겠죠.
    AReceiptService, BReceiptService 이런형태로요."
    저는 대댓글 달아주신거보고 이해했네요. 진짜 저도 너무너무너무너무 궁금해서 간간히 엄청 찾아봤떤 내용인데 하나도 이해가 안됐었거든요. 저도 마찬가지로 실무에서 왜이렇게 하는지도 모르고 기능 추가될때마다 기계적으로 인터페이스에 하나 늘리고 구현체에 함수하나 늘려서 사용했던터라 이게 굳이 왜 필요한가 너무너무 궁금했는데 좀 시원해졌습니다. 즉 예를 다시 보면 ReceiptService 이걸 AReceiptService와 BReceiptService로 구분해서 사용할 필요가 없으면 굳이 인터페이스와 구현체로 나누지 않아도 되겠네요.
    심지어 DAO, DAOImpl, Service, ServiceImpl 이렇게 4개로 사용하는 프로젝트도 있어서 기계적으로 함수를 4곳에나 만들면서 개발해야 했던적도 있었습니다.. 저는 이제 DAO와 Service의 차이를 찾으러 떠납니다 ㅋㅋ
    2021.03.03 10:05
  • 프로필사진 이잉잉 블로그 서핑 하다하다 여기까지 도달했네요 ....ㅋㅋ
    너무 좋은 글 읽고 깨닫고 갑니다 .
    혹시 제 블로그에 퍼가서 기억을해도 될까요?
    2021.08.03 10:08
  • 프로필사진 LichKing 작성한지 너무 오래된 포스팅이라 요즘엔 생각이 좀 다르긴한데 ㅎㅎ 이미 여기저기 퍼가신분들이 계신걸로 알아서.. 출처만 밝혀주시면 상관없습니다. 2021.08.07 12:24 신고
  • 프로필사진 Arthas 윗 답변을 보니 요즘엔 생각이 달라지셨다고 했는데, 어떻게 생각이 변하셨는지 공유해주실 수 있을까요? 2021.08.18 11:19
  • 프로필사진 뎡스 안녕하세요 글 잘 보았습니다. 요즘엔 어떻게 생각하시는지 궁금합니다..! 공부를 하다가 이 부분이 너무 의아해서요ㅠㅠ 2021.08.18 12:30 신고
  • 프로필사진 LichKing 제가 표현을 좀 잘못했네요. 생각이 다르다기보다는 연차가 쌓이다보니 다시 한번 고민이 되고있다 정도로 표현하는게 맞을 것 같습니다. 결론은 아직 비슷해요. 2021.08.19 14:45 신고
댓글쓰기 폼