본문 바로가기
DevOps

마이크로서비스 아키텍처(MSA) 개념 및 이해

qbang 2021. 11. 4.

MSA란

시스템을 여러개의 독립된 서비스들로 나누어서, 해당 서비스를 조합하여 기능을 제공하는 아키텍처 디자인 패턴

 

특징

  • 각 서비스간 Network(보통 HTTP)를 통해 통신
  • 각 서비스를 독립된 단위로 배포
  • 각 서비스는 쉽게 교체 가능
  • 각 서비스는 기능 중심으로 구성(ex. 프론트엔드, 추천, 정산, 상품 등)
  • 각 서비스는 적합한 언어, DB, 환경으로 만들어진다
  • 서비스는 크기가 작고, 상황에 따라 경계를 정하고, 자율적으로 개발되고, 독립적으로 배포되고, 분산되고, 자동화된 프로세스로 구축되고 배포

마이크로서비스는 한 팀에 의해 개발할 수 있는 크기가 상한선이다. 절대로 9명 이상의 사람들이 스스로 더 많은 개발할 수 없을 정도로 규모가 커지면 안된다. 또한 마이크로서비스가 다양한 산업 분야에서 폭넓게 적용되고 있지만 그것이 좋은지 나쁜지는 시간이 더 지나봐야 알 수 있다.

 

모놀리틱 vs 마이크로서비스 아키텍처

모놀리틱 아키텍처
마이스로서비스 아키텍처

모놀리틱은 모든 구성 요소가 하나씩만 존재하고, 마이크로서비스는 각 서비스마다 데이터베이스를 하나씩 갖고 있고 그 사이의 통신은 HTTP를 통해서 통신한다.

 

실습

1. 프로젝트 import

 

GitHub - Gunju-Ko/spring-cloud-workshop: spring-cloud-workshop

spring-cloud-workshop. Contribute to Gunju-Ko/spring-cloud-workshop development by creating an account on GitHub.

github.com

 

2. 소스 살펴보기

request: /displays/{displayId}

response: "[product id=" + productId + "at" + System.currentTimeMillis() + "]";

전시 영역(display)에서 상품(product)을 호출하는 구조이다. 

브랜치를 my-step-0으로 변경한다.

product 구조

src/main/java/com/elevenst/에 controller/api 패키지를 만들고 그 안에 ProductController 클래스를 만든다.

package com.elevenst.controller.api;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/products")
public class ProductController {
    @GetMapping("/{productId}")
    public String getProduct(@PathVariable String productId){
        return "[product id = " + productId + " at" + System.currentTimeMillis() + "]";
    }
}

/products 요청을 처리하는 컨트롤러를 작성한다. 

포트 확인
브라우저에서 요청

ProductApplication을 실행하고 크롬을 통해 접속해본다. products 아래 파라미터는 임의로 작성한다.

display 구조

package com.elevenst;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
public class DisplayApplication {

    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

    public static void main(String[] args) {
        SpringApplication.run(DisplayApplication.class);
    }

}

DisplayApplication에서 RestTemplate을 돌려주는 빈을 생성한다.

package com.elevenst.service;

public interface ProductRemoteService {
    String getProductInfo(String productId);
}

src/main/java/com/elevenst/에 service 패키지를 만들고 그 안에 ProductRemoteService 인터페이스를 만든다.

package com.elevenst.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

@Service
public class ProductRemoteServiceImpl implements ProductRemoteService {
    public static final String URL = "http://localhost:8082/products/";

    @Autowired
    private RestTemplate restTemplate;

    @Override
    public String getProductInfo(String productId) {
        return restTemplate.getForObject(URL + productId, String.class);
    }
}

그리고 이를 구현한 서비스 클래스를 만든다. URL + productId 로 들어왔을 때 String class로 리턴하는 RestTemplate 이다.

package com.elevenst.api;

import com.elevenst.service.ProductRemoteService;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping(path = "/displays")
public class DisplayController {
    private final ProductRemoteService productRemoteService;
    
    public DisplayController(ProductRemoteService productRemoteService) {
        this.productRemoteService = productRemoteService;
    }

    @GetMapping(path = "/{displayId}")
    public String getDisplayDetail(@PathVariable String displayId) {
        String productInfo = productRemoteService.getProductInfo("1111");
        return String.format("[display id = %s at %s %s ]", displayId, System.currentTimeMillis(), productInfo);
    }
}

위는 productRemoteService에 대해 Constructor 인젝션을 사용하는 방법이다. Controller의 getDisplayDetail에서 getProductInfo를 호출할 때 임시 id를 넣어준다.

포트 확인
브라우저에서 요청

DisplayAppication을 실행시킨다. 이때 ProductApplication도 실행된 상태여야 한다.(connection refused 에러 발생)

 

본 게시글은 T아카데미의 Spring Cloud를 활용한 MSA 기초 강의를 바탕으로 작성되었습니다.

'DevOps' 카테고리의 다른 글

아파치 카프카(Apache Kafka) 기초  (0) 2022.01.19
WebSocket vs HTTP  (0) 2022.01.04
모놀리식 vs 마이크로서비스 아키텍처  (0) 2021.11.21
CSR / SSR (+ SPA / MPA)  (0) 2021.11.08
모놀리틱 아키텍처 이해  (0) 2021.09.24

댓글