티스토리 뷰

728x90
반응형

 포스팅에서는 Spring Boot를 이용한 마이크로서비스 구축과정 중 개발자의 역할에 대해 알아보겠습니다.


기존 빅뱅 오픈을 목표로하는 사이트의 경우 모든 애플리케이션의 요구 사항과 설계를 프로젝트 초반에 정의할 것을 요구 (폭포수-Waterfall 개발 방법론)하여 프로젝트가 진행되는 과정에서 발생하는 새로운 요구 사항을 충족하거나 리팩토링할 여지나 개발 초기 단계에서 저지른 실수를 만회하기가 어렵다는 문제가 있습니다.

사실 프로젝트를 진행해 나가면서 새로운 비즈니스 요구 사항은 당연히 발생가능하며, 이해의 차이, 수정 등 끊임없는 변동이 일어나는 프로젝트 초 중반 단계에서 전통적인 워터풀 개발 방식은 다양한 문제를 발생시켜왔습니다.

강한 결합(Tightly Coupled)으로 인해 애플리케이션 컴포넌트를 조그만 수정해도 그 애플리케이션의 다른 부분을 깨뜨리거나 새로운 버그를 생산할 가능성이 높아집니다.

또한 기존 모놀리식 개발 방법은 애플리케이션 코드를 조그만 변경해도 이를 반영하기위한 많은 시간이 소요되며 비용이 듭니다. 


● Spring Boot와 JAVA로 마이크로서비스 생성

마이크로서비스를 구현하는 개발자는 어떠한 역할을 수행할 것인가에 대한 고민을 해볼 차례입니다.

① 마이크로서비스의 기본 골격과 메이븐 스크립트를 빌드해 애플리케이션을 빌드한다.

② 마이크로서비스용 스프링 컨테이너를 시작할 스프링 부트스트랩 클래스를 구현하고 이 클래스의 초기화 작업을 시작한다.

③ 서비스의 엔드포인트를 노출하기 위해 엔드포인트를 매핑하는 스프링 부트 컨트롤러 클래스를 구현한다.


● 기본 골격 프로젝트로 시작

spring-starter Project 생성 및 pom.xml 작성

pom.xml
0.00MB

② Spring Boot 패키징

Spring Boot는 개별 프로젝트로 나뉘어서 관리됩니다. 이는 기존 Spring MVC 환경에서 사용하는 불필요한 라이브러리 (Spring MVC를 이루는 모든 라이브러리)를 포함하여 구성하지 않으며, 필요한 라이브러리만 pom.xml에 등록하여 해당 프로젝트에 포함하는 방식을 의미합니다.

위 pom.xml은 parent 항목을 이용하여 Spring Boot 2.0.3 버전을 의존성에 포함하는 로직입니다. 또한 Spring Boot Web, Spring Boot Actuator를 디펜던시에 추가합니다.

위와 같이 필요한 의존항목만 포함시켜 프로젝트를 구성할 수 있어 가볍게 구현이 가능하다는 장점이 있습니다.

③ Spring Boot 빌드 및 배포

Spring Boot로 만든 애플리케이션의 빌드와 배포를 단순화한 Maven 플러그인을 포함하여 빌드 및 배포를 진행 합니다. (maven-resources-plugin)

이 플러그인은 Maven과 Spring Boot의 사용을 도와주는 부가기능(spring-boot:run 등)을 포함합니다.

④ Spring Boot 도커 이미지 빌드

Maven에 Spring Boot 애플리케이션의 빌드와 배포를 위한 스프링 전용 Maven Plugin을 포함합니다. (docker-maven-plugin)


● Spring Boot 애플리케이션 부팅

스프링 부트로 간단한 마이크로서비스를 시작한 후 반복하며 기능을 전달하는 클래스를 작성해 보도록 하겠습니다.

① Spring Boot가 애플리케이션을 시작하고 초기화하는데 사용되는 Spring Bootstrap 클래스

package com.nrson.licenses;

 

import org.springframework.boot.SpringApplication;

import org.springframework.boot.autoconfigure.SpringBootApplication;

 

@SpringBootApplication //@SpringBootApplication 애너테이션은 스프링 부트 프레임워크에 이 클래스가 프로젝트의 부트스트랩(bootstrap) 클래스라고 지시한다.

public class Application {

 

    public static void main(String[] args) {

        // 스프링 부트 서비스를 시작하기 위해 호출한다.

        SpringApplication.run(Application.class, args);

    }

}

 

㉠ @SpringBootApplication 어노테이션

Spring Boot는 이 어노테이션이 붙은 클래스가 Spring에서 정의하는 Bean의 시작점이라고 스프링 컨테이너에게 알려 줍니다.

알다시피 Spring Boot 애플리케이션의 Spring Bean은 @Component 또는 @Service 또는 @Repository 어노테이션이 붙은 클래스를 정의합니다.

또한 @Configuration 어노테이션이 붙은 클래스에 Spring Bean을 생성하기 위한 @Bean 생성자 메소드를 정의할 수 있습니다.

@SpringBootApplication 어노테이션을 등록하는 것은 @Configuration, @EnableAutoConfiguration, 그리고 @ComponentScan을 디폴트 속석으로 사용하는 것과 같으며, @Autowired를 활용하여 의존성을 주입할 수 있습니다.

 

㉡ Application.class의 main 메소드

main 메소드에서 SpringApplication.run(Application.class, args) 호출은 Spring Container를 시작하고 Spring ApplicationContext 객체를 반환합니다.

 

② 마이크로서비스에서 호출할 수 있는 HTTP 엔드포인트를 노출하는 Spring Controller 클래스

Bootstrap 클래스를 생성하면 이제 실제 비즈니스 로직이 수행되는 코드를 작성해야 합니다. 마이크로서비스의 출입구이자 Spring Boot Controller가 비즈니스 로직이 있는 클래스로 연결을 담당하게 됩니다.

Spring Boot 애플리케이션에서 Controller 클래스는 서비스의 엔드포인트를 노출하고 유입되는 HTTP 요청 데이터를 이 요청을 처리할 자바 메소드와 매핑합니다.

package com.nrson.licenses.controllers;

 

import com.nrson.licenses.model.License;

import com.nrson.licenses.services.LicenseService;

 

import org.springframework.beans.factory.annotation.Autowired;

import org.springframework.web.bind.annotation.RequestMapping;

import org.springframework.http.HttpStatus;

import org.springframework.web.bind.annotation.RestController;

import org.springframework.web.bind.annotation.RequestMethod;

import org.springframework.web.bind.annotation.PathVariable;

import org.springframework.web.bind.annotation.ResponseStatus;

 

@RestController

@RequestMapping(value="v1/organizations/{organizationId}/licenses")

public class LicenseServiceController {

    @Autowired

    private LicenseService licenseService;

 

    @RequestMapping(value="/{licenseId}",method = RequestMethod.GET)

    public License getLicenses( @PathVariable("organizationId") String organizationId,

                                @PathVariable("licenseId") String licenseId) {

 

        //return licenseService.getLicense(licenseId);

        return new License()

            .withId(licenseId)

            .withOrganizationId(organizationId)

            .withProductName("Teleco")

            .withLicenseType("Seat");

    }

 

    @RequestMapping(value="{licenseId}",method = RequestMethod.PUT)

    public String updateLicenses( @PathVariable("licenseId") String licenseId) {

        return String.format("This is the put");

    }

 

    @RequestMapping(value="{licenseId}",method = RequestMethod.POST)

    public String saveLicenses( @PathVariable("licenseId") String licenseId) {

        return String.format("This is the post");

    }

 

    @RequestMapping(value="{licenseId}",method = RequestMethod.DELETE)

    @ResponseStatus(HttpStatus.NO_CONTENT)

    public String deleteLicenses( @PathVariable("licenseId") String licenseId) {

        return String.format("This is the Delete");

    }

}

 

위와 같이 총 PUT, GET, POST, DELETE 4개의 메소드를 HTTP 엔드포인트로 노출하고 있습니다.

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

728x90
반응형