코토리와 함께 스프링 모네 - 7. 서비스 계층

개요 / 설명



Kotlin에서 서버 측 애플리케이션을 만들어 왔지만 아직 깔끔한 구성이되지 않은 상태입니다.
"코토리와 함께 Spring Mone - 2. RestController 및 Data Class "에서 컨트롤러 클래스를 만들고 직접 데이터를 처리하는 구성으로 남습니다.
그래서 조금씩 변경해 갑니다.
우선, 여기에서는 「서비스」층을 생각해 갑니다.



웹 애플리케이션에서는 크게 나누어 다음과 같은 기능이 필요합니다.
  • 요청/응답 처리
  • 애플리케이션 로직 처리
  • 데이터 처리

  • 지금까지는 이러한 기능을 단일 레이어로 담당했습니다.
    이대로 구성하면 취급하는 로직이 증가하고 데이터 모델이 복잡해지면,
    1개의 클래스가 거대해져 개발/보수 효율이 나빠져 버립니다.

    각 기능을 분리하여 여러 레이어로 나눕니다.

    그런데, 만들고 있던 클래스가 RestController 라고 하는 것으로,
    본래는 리퀘스트/리스폰스를 취급하는 것을 책무로 합니다.
    그런 다음 다른 프로세스를 잘라내어 서비스라고합니다.

    전제 / 환경



    런타임 버전


  • Kotlin : 1.3.0
  • SpringBoot : 2.1.0.RELEASE

  • Spring Dependencies


  • Web
  • Actuator

  • 개발 환경


  • OS : Mac
  • IDE : IntelliJ IDEA
  • Build : Gradle

  • 절차 / 설명



    변경 전 컨트롤러 클래스



    원래는 아래와 같이 컨트롤러 클래스 안에서 데이터 생성 등, 리퀘스트/응답의 처리 이외의 일을 하고 있었습니다.
    @RestController
    @RequestMapping("/messages")
    class SimpleController {
    
        @GetMapping
        fun getMessages() : List<Message> {
            return listOf(
                    Message(
                            UUID.randomUUID().toString(),
                            "First Message",
                            "This is a 1st message on ${getDate()}."
                    ),
                    Message(UUID.randomUUID().toString(),
                            "Second Message",
                            "This is a 2nd message on ${getDate()}."
                    )
            )
        }
    
        private fun getDate() : String {
            val simpleDateFormat = SimpleDateFormat("yyyy/MM/dd HH:mm:ss")
            return simpleDateFormat.format(Date())
        }
    }
    

    서비스 클래스



    원래 컨트롤러 클래스에 구현하고 있던 내용을 다음과 같이 서비스 클래스에 옮깁니다.
    @Service("Message Service")
    class MessageService {
    
        fun getMessages() : List<Message> {
            return listOf(
                    Message(
                            UUID.randomUUID().toString(),
                            "First Message",
                            "This is a 1st message on ${getDate()}."
                    ),
                    Message(UUID.randomUUID().toString(),
                            "Second Message",
                            "This is a 2nd message on ${getDate()}."
                    )
            )
        }
    
        private fun getDate() : String {
            val simpleDateFormat = SimpleDateFormat("yyyy/MM/dd HH:mm:ss")
            return simpleDateFormat.format(Date())
        }
    }
    

    서비스 클래스에는 @Service 어노테이션을 부여합니다.
    이것에 의해 컨트롤러 클래스안에서 Dependency Injection 에 의해 이용할 수 있게 됩니다.
    @Autowired
    private lateinit var service: MessageService
    
    lateinit 키워드는 인스턴스를 초기화하지 않고 선언하는 데 사용됩니다.

    변경 후 컨트롤러 클래스



    서비스 클래스를 사용하는 컨트롤러 클래스는 요청/응답에 대한 처리만 담당하도록 합니다.
    다음과 같이 서비스 클래스에서 구현하고 있는 처리를 호출하도록 변경합니다.
    @RestController
    @RequestMapping("/messages")
    class MessageController() {
    
        @Autowired
        private lateinit var service: MessageService
    
        @GetMapping
        fun getMessages() = service.getMessages()
    }
    

    요약 / 되돌아보기



    책무별로 레이어를 나누어 어플리케이션을 개발하는 것은, 지금 정석이군요.
    아직, 이 상태에서는 서비스 레이어로부터 데이터 처리를 직접 실시하게 되어 있으므로,
    다음은 그 부분을 분리해 갑니다.

    이번 소스


  • shinyay/spring-just-rest-kotlin/tree/first-service-layer
  • 좋은 웹페이지 즐겨찾기