logo
한달 포트폴리오 멘토링
블로그

Spring을 처음 배우는 모든 학생 분들이 가장 많이하는 질문그냥 Controller에서 전부 구현하면 안되나요? Service를 왜 만들어야하죠? 라는 질문입니다. Controller에 다 구현해도 똑같이 동작하기 떄문에 이런 질문을 가질 수 있습니다. 또한 생각보다 많은 초보 개발자 분들이 왜 이런 구조로 분리하는지 이유를 모르고 다들 분리하기 때문에 그냥 분리합니다. 여러 다른이유로 소프트웨어 아키텍처를 변경해야 할때 유연하게 변경할 수 없습니다. 그러나 원리를 알면 다음에 더 좋은 아키텍처를 만드는데 비슷한 원리를 적용할 수 있습니다.

이번 포스팅에서는 Controller, Service를 분리하는 이유들에 대해 알아보겠습니다.

API의 추가 및 변경될 경우

RESTful API를 통해 서비스를 운영하고 있다고 가정합시다. 사이트 반응속도가 너무 느려 서비스를 Light House로 분석해보니 하나의 페이지에서 너무 많은 API를 호출해 문제가 생겼다고 합니다. 이러한 문제를 해결하기 위해 팀에서는 graphql을 도입하기로 결정하였다고 합시다. **이때 만약 Controller에 모든 기능을 구현하였다면, Grapqhql API를 구현하는 Controller에 또 다시 구현해야하지만 Service에 기능을 구현하였다면 이럴 문제가 없습니다. **

위 그림처럼 GqlController를 새로 만들어 Service에 연결해주면 됩니다.

이렇게 되면 또 하나의 장점은 점진적으로 API를 변경할 수 있다는 점입니다. 만약 API를 변경하기 위해 전부 컨트롤러를 변경한다면 모든 API가 변경된 이후에야 배포를 할 수 있습니다. 그러나 이런식으로 변경된 부분만 GqlController로 옮길 수 있으면 두가지 API를 동시에 사용할 수 있어 점진적으로 서비스를 개선하여 한번에 변경할때 생기는 문제들을 미리 예방 할 수 있습니다.

트랜잭션 처리

Spring에서 Service의 고유한 기능 중 하나는 Transaction 처리 기능입니다. 트랜잭션이란 DB 업데이트시 일련의 업데이트 과정을 한번에 처리하고 실패시 전체 롤백, 성공시 전체 실패를 해주는 기능입니다. 송금을 예제로 들면 다음과 같습니다. 트랜잭션이 없는 상태의 송금 실패 시나리오입니다. DB에서 B의 계좌를 업데이트 하는것을 실패하였습니다. 트랜잭션이 없다면 A의 계좌를 롤백하지 않아 A의 계좌에만 5000원이 감소하게됩니다. 그러나 트랜잭션을 사용한다면 5에서 실패하였을때 A의 계좌도 다시 롤백을 하기 때문에 실패에도 안전하게 돈을 보존할 수 있습니다.

Service에서는 클래스나 메서드에 @Transaction을 사용하여 Exception이 발생할 경우 모든 DB업데이트를 롤백하는 과정을 가질 수 있습니다.

Controller와 Service의 역할

Spring Application Layered Pattern

Domain Driven Design Layered Pattern

위의 두 그림은 웹 서비스를 만들때 많이 사용하는 두가지 계층 구조입니다. Spring Application Layered Pattern은 Spring에서 흔히 사용하는 계층 구조로 Web Layer에서 사용자의 요청을 받고 Service Layer에서 실제 요청을 처리하고, Repository Layer에서 통해 Data를 조회 변경합니다.

Domain Driven Design Layered Pattern에서는 User Interface Layer에서 사용자의 요청을 받고 응답을 만들며 Application Layer에서는 기능을 제공합니다. Domain Layer에서는 기능을 제공하기 위한 실제 변경 작업을 진행하며 Infrastructure Layer에서는 Database, 다른 Application, 웹 프레임워크등 인프라에 접근하도록 인터페이스를 제공하는 레이어입니다. ** Controller는 Web Layer와 User Interface Layer에 해당하고, Service는 Service Layer와 Application Layer 혹은 Domain Layer에 해당합니다.**

Controller에서는 사용자의 입력처리와 응답에만 집중하고, Service에서는 실제 기능을 어떤식으로 제공하는지에 대해서만 집중하여야 나중에 다른 팀원이 코드를 수정할 때도 어떤 기능이 어디에 있는지 쉽게 알 수 있고, 변경하기 유리합니다. 이는 단일 책임 원칙을 지키는 기본입니다.

About Couchcoding

카우치코딩에서는 1:1 코딩 문제해결 멘토링 서비스입니다. 가르치는데 관심있는 멘토분들이나 문제해결이 필요한 멘티분들 방문해주세요~ 또한 별도로 6주 포트폴리오 수업을 진행중에있습니다. 혼자 포트폴리오 준비를 하는데 어려움이 있으면 관심가져주세요~

카우치코딩 고동휘 멘토의 글입니다.

PortfolioAD
관련있는 글

couchcoding

2022-12-07

Firebase로 Google 로그인 구현하기 2 (Spring 파트)

이전 포스팅에 이어 구글 로그인응 이용하기 위하여 Java Backend(SpringBoot)를 통해 Resource Service를 구현하는 것을 배워보겠습니다. 예제는 자바로 진행하나 구조를 익히면 다른 백엔드 프레임워크에서도 사용할 수 있을 것입니다. ...

백엔드

spring
react
firebase
firebase auth
Oauth
JWT
SNS 로그인

couchcoding

2022-12-07

Spring Security (1) - 구조와 동작 방식

Spring Security는 Spring Application 개발시에 보안을 적용하기 위해 사용하는 보안 프레임워크 입니다. Spring Security는 웹 보안을 위하여 인증 및 보안 관련 로직을 제공합니다. 특히 Spring Security의 가장 중요한 기...

백엔드

spring
spring security
filter
보안
로그인

couchcoding

2022-12-07

[Spring] QueryDSL로 조건검색 API를 만들어보자(동적 쿼리)

조건 검색을 만들기 위해서 QueryDSL이라는 라이브러리를 사용하려고 합니다. QueryDSL은 JPA만으로는 복잡한 쿼리를 만들기 어렵고 JPQL과 같이 직접 SQL을 사용하는 방식은 SQL을 실행 전까지는 SQL을 검증할 수 없어 오류가 생기기 쉽습니다. ...

백엔드

spring
JPA
QueryDSL
조건 검색
동적 쿼리

couchcoding

카우치코딩 공식 계정입니다.