MSA로 헬스/영양 관리 어플리케이션 만들기 (2) - 아키텍쳐

백근영·2020년 3월 17일
1

Spring Cloud MSA

목록 보기
2/4

대략적인 MSA의 구조는 다음과 같다.

Config Server

각 마이크로서비스에서 사용하는 설정값들을 config server라는 중앙 서버에서 일관되게 관리할 수 있다. db password나 jwt secret key 등 보안에 민감한 정보는 secret하게 encrypt해서 값을 주고받을 수도 있다.

config server는 설정값들을 저장하기 위한 장소로 github 등의 온라인 코드 저장소를 사용할 수도 있고, 단순히 로컬 디렉토리를 사용할 수도 있다. 이번 실습에서는 로컬 디렉토리를 선택했다.

server:
  port: 8888
spring:
  profiles:
    active: native
  cloud:
    config:
      server:
        native:
          search-locations: classpath:config/

이렇게 하면 resources 안의 config 디렉토리에서 각 마이크로서비스에 대한 설정값들을 정의할 수 있다.

모든 서비스가 공통으로 사용하게 될 설정값들은 config 디렉토리 내의 application.yml 파일에서 정의할 수 있는데, 내가 작성한 appliation.yml파일의 내용은 아래와 같다.

jwt:
  secretKey: ${JWT_SECRET_KEY:geunyoung_jwt_secret}

spring:
  datasource:
    driver-class-name: "com.mysql.cj.jdbc.Driver"
    url: ${MYSQL_CONNECTION_URI:jdbc:mysql://localhost:3306/test_db?serverTimezone=UTC&characterEncoding=UTF-8}
    username: "root"
    password: ${MYSQL_ROOT_PASSWORD:password}

  jpa:
    database: "mysql"
    show-sql: "true"
    generate-ddl: "true"
    hibernate:
      ddl-auto: "create"

JWT_SECRET_KEY, MYSQL_CONNECTION_URI 등 환경에 따라 달라질 수 있는 값들은 외부 환경변수로 주입받도록 설정했다. 이렇게 하면 config server의 도움을 받는 모든 마이크로서비스가 동일한 db 설정을 가질 수 있게 된다.

Zuul API Gateway

api gateway는 MSA 패턴에서 외부로 노출되는 유일한 엔드포인트로, 모든 요청은 맨 앞단의 gateway를 통해서 목표하는 서비스로 우회된다. 본 실습에서는 가볍게 사용자 인증 처리 과정을 넣어보고 싶었는데, 별다른 OAuth Server를 사용하지 않는 상황에서 내가 생각해볼 수 있는 인증 구조는 크게 두 가지였다.

1. gateway로 들어오는 token을 microservice에 그대로 전달

이러한 구조는 단순하고 높은 보안성을 유지할 수 있지만 token validation 로직이 모든 마이크로서비스에 들어가야 한다는 단점이 있으며, 중복되는 코드를 줄이기 위해서는 공유 라이브러리에 대한 고민이 필요할 것 같다.

2. gateway에서 token을 decode하고, downstream request의 header에 decode된 정보를 전달

이렇게 하면 인증에 대한 책임을 오롯이 API gateway에 맡길 수 있으며, 각각의 microservice는 복잡한 token 인증 로직 없이 자신의 business logic에만 집중할 수 있다. 하지만 각각의 서비스는 헤더에 적절한 사용자 정보를 넣어주기만 하면 이는 인증이 완료된 요청이라고 믿고 로직을 수행하기 때문에 보안에 취약할 수 있다. 따라서 해당 마이크로서비스가 외부에 노출되지 않도록 방화벽 등의 설정을 확실히 해두어야 할 것이다.

Feign Client

feign client는 선언적 REST API client로, 한 마이크로서비스에서 다른 마이크로서비스의 API를 필요로 할 때 주로 사용한다. 마이크로서비스와는 별개로 단지 외부 API를 호출하기 위한 수단으로도 사용할 수 있지만, Eureka server의 도움을 받는 feign client는 MSA와 특히 잘 어울린다고 생각한다.

본 실습의 statistics(통계) 서비스는 운동 기록과 영양 기록을 가져와 통계에 적합한 형태로 자료를 가공하는 서비스이다. 아래 예시는 본 실습의 통계 서비스에서 영양 서비스로 요청하는 API를 feign client로 정의한 코드이다.

@FeignClient(name = "diet")
interface DietServiceClient {
    @GetMapping("/histories")
    fun getDietHistories(
            @RequestHeader("username") username: String,
            @RequestParam("period") period: Int
    ): List<DietDto.DietHistory>
}

위와 같이 @FeignClient의 name attribute를 목표로 하는 마이크로서비스의 이름으로 지정해주면 service discovery를 통해 원하는 마이크로서비스에 API 요청을 보낼 수 있다. 또한 Feign client는 서킷 브레이커인 hystix와 로드밸런서 역할을 하는 ribbon이 내장되어 있기 때문에 유연하게 타 마이크로서비스와 소통이 가능하다.

profile
서울대학교 컴퓨터공학부 github.com/BaekGeunYoung

0개의 댓글