개발자 노트

[Web]Layered Architecture에 대하여 본문

Web

[Web]Layered Architecture에 대하여

jurogrammer 2020. 5. 29. 17:07

Layered Architecture

참고자료

  1. https://en.wikipedia.org/wiki/Multitier_architecture
  2. https://sites.google.com/site/telosystutorial/springmvc-jpa-springdatajpa/presentation/architecture
  3. https://www.petrikainulainen.net/software-development/design/understanding-spring-web-application-architecture-the-classic-way/ (대다수 내용 참고)

작성하는 내용의 대다수는 3번을 참고하여 작성합니다. 허나 제 생각을 토대로 말하기 때문에 부족하다 느끼시다면 3번 참고자료를 확인해보실 것을 바랍니다. 이 페이지의 댓글 또한 좋은 질문이 많습니다.

API를 작성하다 생긴 고민

어떤 내용을 controller, service, dao에 작성해야 할까??

controller 객체가 present layer에서 데이터를 받고 보내주는 역할인 건 알겠어.

service 객체가 service layer에서 비즈니스 로직을 수행하는 곳인 건 알겠어.

dao 객체가 repository layer에서 db에 접근하는 역할인 건 알겠어.

그런데 그렇다고 해서 뭘 어떻게 작성해야 할까?

  • controller에서 여러 dto를 받아서 보내줘야하나? service에서 할수도 있잖아. service에서 dto 객체를 만들고 controller에 보내주면 되는거 아니야? 아니 그렇다면 애당초 dao에서 dto를 만들어서 보내줄 수도 있잖아. dto를 데이터를 주고 받는다하면 그게 그거인데 뭐가 다른거야?!! 그리고 다 위 3가지 말에 합당한거 같아!!

한편으로, 내가 위 말들을 단지 익숙해진 건 아닐까하는 생각이 들었습니다. 위 참고 자료를 읽어보며 다음과 같은 본질적인 질문에 답해야 했습니다.

애당초 왜 Layer를 만들어줘야 할까? 만들어주는 기준은 무엇인데?

Layer

  • 바로 답을 말하자면 Layer는 관심사의 집합입니다.
    • 집합이 아닌 Layer라 표현한 이유는 집합간 계층관계를 표현해주기 위함입니다. 즉, 상위 Layer에서 하위 Layer로만 컨트롤할 수 있습니다.
      • 예를 들어서 PresentLayer에 있는 Controller는 Service의 인터페이스를 조작하여 데이터를 전달 받을 수 있지만 Service는 Controller를 조작하는 코드를 작성하면 안됩니다.
    • 관심사의 집합이라고 표현한 이유는 관심사 주제별로 층을 많이 나누면 구조가 너무 복잡해지기 때문에 관심사를 묶어 계층에 나타내기 때문입니다.
      • 새로운 코드를 작성하면 매 Layer마다 데이터 전송을 해주어야 하므로 비용이 큽니다.
      • 다른 사람이 이 구조를 이해할 수 없으므로 비용이 큽니다.
  • 위 내용에 따라 Layer 생성에 매우 중요한 두 가지 원칙이 녹아있습니다.
  1. 소프트웨어를 만들 때 관심사를 명확히 알고, Layer에 관심사를 정해줄 것. 이로써 Layer의 책임이 명확해집니다.
  2. 분리하되, 너무 많은 Layer를 생성하지 말것.

그래서 Web application에선?

우선, Spring MVC관점으로 웹개발에서의 관심사를 다음과 같이 나눌 수 있습니다.(자료참고)

  • 사용자에게 요청을 받으면 그에 맞는 반응을 해줄 것
  • 사용자 요청 중 exception 에 대해 처리해줄 것
  • transaction 처리해줄 것
  • 인증 및 권한 부여해줄 것(이 내용은 추후 보강하겠습니다.)
  • 비즈니스 로직을 구현해줄 것.
  • 외부 resource 및 내부 데이터 저장소와 통신할 것. (이 내용은 추후 보강하겠습니다)

그리고 현재! 시행착오를 거쳐 3개의 Layer로 이 관심사를 분리하게 되었습니다. 이것이 Layered Architecture에서
Presentation Layer - Service Layer - Repository Layer가 됩니다.

따라서 위 관심사 및 구현은 Layer별로 다음과 같습니다.

1. Presentation Layer

책임

  • 사용자에 요청을 받으면 그에 맞는 반응

  • 사용자 요청 중 exception 처리

구현

  • 사용자에게 view(html,jsp,....)를 노출 시킵니다.

  • 사용자는 특정 요청을 합니다. 이때 dispatcher servlet이 컨트롤러로써 요청을 받습니다. 또는 이 요청이 잘못될 경우 익셉션 처리를 해줍니다.(default servlet 사용시 익셉션처리 해줌)

  • dispatcher servlet은 관리인으로써 역할만을 주었습니다. 요청에 맞는 데이터를 처리하기 위해선 개발자가 Controller를 따로 작성을 하도록 하였습니다.

  • 따라서 dispatcher servlet은 사용자 요청을 받은 후 해당 요청에 적절한 컨트롤러에게 처리하도록 전달해줍니다.

  • 요청을 받은 컨트롤러는 적절한 output이 view에 그려지도록(결국 웹어플리케이션은 시각정보를 통해 output을 보여줍니다.) view에 적절한 데이터를 하위 레이어에 요청하고 전달해줍니다.

    • 즉, controller는 데이터(모델)를 전달할 책임만 있을 뿐, 접근할 책임이 없기 때문에 하위 레이어에게 데이터접근을 요청하게 됩니다.

2. Service Layer

책임

  • 비즈니스 로직을 구현합니다.
  • transaction 처리를 합니다.

구현에 앞서 잠깐 비즈니스 로직에 대해 설명하겠습니다. Layered Architectrue를 이해하는데 있어 핵심 키워드였기 때문입니다. 비즈니스 로직이 무엇인지 아시는 분은 넘어가도 좋습니다.

비즈니스 로직이란 무엇일까?

전, 처음에 비즈니스 로직이란 말을 접했을 때 전혀 와닿지 않았습니다. Repository단에서 비즈니스 로직을 수행한다는데 그게 무슨 말이지? 강의나 wikidipia에선 업무처리에 대한 로직이라고 했는데 무슨 말인가 싶었습니다. 그래서 stack overflow를 보니 DBMS에 자주 접근해야하는 로직이라 busy한 로직. 바쁜 로직이라는 말도 봤습니다.

바쁜 로직이라는 말이 더욱 와닿았기 때문에 비즈니스 로직 = 바쁜 로직으로 이해했습니다. 그런데 프로젝트를 진행하면서 이러한 정의로는 Service 객체에 Dao의 내용이 와도 되는 것이 아닌가하는 고민이 들게 만들었습니다.

지금와서 말하자면 말 그대로 업무처리에 대한 로직이 비즈니스 로직입니다!!

비즈니스 로직이 와닿지 않았던 이유는 다음과 같습니다.

  1. 웹페이지를 만든 목적
  2. 웹페이지에서 클릭 다닥다닥 하는데 비즈니스???

위 두가지를 생각해보면 웹페이지는 결국 기업과 소비자가 맞닿는 인터페이스입니다. 예를 들어 쇼핑 페이지라고 해봅시다.

  1. 소비자가 쇼핑페이지에 들어옵니다.
  2. 소비자가 상품 구매를 눌렀습니다. 즉, 소비자가 기업에게 상품 구매를 요청했습니다!
  3. 그럼 기업은 상품 구매 요청에 맞는 처리를 해야 합니다. 즉, 상품 구매 업무에 대한 로직을 수행 해야 합니다.
  4. 그 후에 상품 구매 요청에 맞는 처리를 완료한 후에 presentation layer에서 상품 구매 요청에 대한 피드백을 전달해줍니다.

다시 말해 웹페이지는 기업이 업무를 하기 위해 만들어 놓은 view이고 사용자는 요청을 하는 구조입니다. (client-server 구조가 이런 면에서 관통하네요) 이러면 비즈니스 로직이란 말이 이해되리라 생각될 것입니다.

구현

  • service 객체에서 비즈니스 로직을 수행하는 코드를 작성합니다. 단, 이 service는 DBMS에 직접적인 접근은 하지 않습니다. service는 비즈니스 로직만을 작성하고 이외 데이터를 조작하는 역할 등은 하위 레이어에게 책임을 돌립니다.

  • 그리고 특정 비즈니스 로직을 수행하기 위해 데이터를 조작하는 일을 수행하나, 이 조작하는 일이 하나의 단위로 수행되어야할 때가 있습니다. 유명한 예로 입출금 서비스가 있죠. 이를 관리하기 위해 service에서 transaction을 관리하게 됩니다.
    데이터를 조작하는 하위 레이어에게 이거해! 저거해! 시키는 입장이니 관리하기가 용이하겠죠. 따라서 spring에선 service 객체에서 간단하게 @transaction 통해 트랜젝션 관리를 합니다.

3. Repository Layer

책임

  • 내부 데이터 저장소에 접근한다

구현

  • dao(Data Access Object)를 만들어서 접근하게 된다.

이렇게 층별로 관심사가 나뉘어 집니다. 그리고 또한 3개의 레이어로 나눈 이유 중 하나로는 재사용성에 있습니다. 이 부분에 대해 설명하겠습니다.

3-Layer의 재사용성

생각해봅시다. 위의 쇼핑페이지 예에서 사용자의 요청이 웹페이지가 아니라 윈도우 어플리케이션에서 요청하는 것으로 바꼈습니다.

그렇다고해서 사용자의 요청에 따른 비즈니스 로직이 바뀔까요? 또는 DBMS가 바뀔까요?

결국 웹페이지든, 윈도우 어플리케이션이든 presentation layer가 바뀌었다 하여 service layer, repository layer가 바뀌진 않습니다.

윗 말을 다시 말해보자면, 소비자가 기업에게 요청할 수 있는 어떤 인터페이스든지 간에 그것을 수행해야하는 비즈니스 로직은 변하지 않습니다. 단지 소비자에게 보여지는 내용들만 바뀔 뿐입니다.

그래서 service Layer를 기준으로 쉽게 띄어낼 수 있도록 presentation Layer에 대한 설정과 service layer, repository layer 설정을 분리합니다.

그래서 service Layer를 기준으로 controller간 의존성을 낮추기 위해 service interface를 작성합니다.

  • (하지만 이부분은 논란이 많습니다. )
    • 이미 service 클래스가 완성된 상태에서 controller를 변경하는 것이기 때문에 interface 목적에 부합하지 않습니다.
    • 또한 service 인터페이스와 구현체가 1:1 대응이기 때문에 다형성의 이점이 없습니다.

한편으로, 층간 데이터 통신은 DTO 객체를 전달함으로써 이루어집니다.

이젠...!

이 글을 다 읽으셨다면 전보다는 어떤 로직을 어떤 층에 구현해야할 지 명확하지셨으리라 생각됩니다. 결국 우리가 명심해야할 것은 어떤 층이 어떤 책임을 맡았는지가 중요하니까요. 전 참고자료를 읽으면서 머리 한 방 맞고, 또한 명쾌해지는 기분을 느꼈습니다.

한편으로는 여전히 의문점이 남아있는 것이 있긴 합니다. open api를 호출하는 경우 입니다.
제 생각엔 open api 호출 로직은 Controller가 아닌 service에 작성되어야 한다고 보았습니다. 재사용성 측면에서, Controller는 비즈니스 로직을 수행해야한다는 점, open api는 비즈니스 로직 수행의 일부분이라는 점에서 말이죠. 그런데 몇몇 글들을 보니 controller에 작성되어 있어 혼동이 옵니다. 그래서 open api는 추후에 작성하기로 한 점이 있습니다.

결국 프로젝트를 진행하며 몸소 느낀 뒤 service에 넣는게 좋았는지, controller에 넣는게 좋았는지 판단하게 될 것 같네요.

마지막으로 잘못된 부분이 있다면 지적해주시기 바랍니다.

반응형

'Web' 카테고리의 다른 글

[Spring]Spring 문서 주소  (0) 2020.06.04
[Spring] Field Injection에 의한 순환 참조 오류  (0) 2020.06.01
[JavaScript]비동기처리 문제  (0) 2020.05.23
[Spring]DTO작성  (0) 2020.05.19
[JavaScript]무한 슬라이딩 윈도우  (0) 2020.05.18
Comments