본문 바로가기
Spring Cloud

스프링으로 배우는 MSA (4) - Spring Cloud Netflix Gateway Server

by DarrenH 2023. 6. 28.
반응형

이전 포스팅에서 우리는 서비스를 만들고 테스트를 해봤다. 이전장은 모놀로식이랑 똑같이 구현하면 되기 때문에 큰 어려움이 없었을 것이다.

 

아마 시큐리티 설정이 제일 시간이 걸렸을 것이다.

 

이번에는 게이트 웨이서버를 만들 건데, 게이트 웨이가 뭔지 먼저 작성하려고 한다. 

 

먼저 Gateway는 컴퓨터에서 다른 네트워크망에 접속을 가능하게 해주는 것을 가르키는 용어이다.

맞다 위의 설명 처럼 다른 네트워크 망에 접속하게 끔 도와주는 것이다.

 

우리가 서비스 별로 DB도 다르고 서버도 다르기 때문에 다른 네트워크 망이라 생각해도된다.

 

클라이언트가 매번 요청마다 포트를 바꿔서 요청하는것은 매우 번거로운 일이기도 하고, 한곳에서 어느 서비스로 보내줄 지 결정해주는게 더욱이 편하다.

 

출처 - https://linked2ev.github.io/gitlog/2022/02/16/SCG-1.-Spring-Cloud-Gateway-%EC%84%A4%EC%A0%95%281%29-Routing/

위와 같은 구성이다. 이 이미지는 인터넷에서 가져온것이므로 서비스는 우리와 다르지만 구조는 동일하다.

 

그럼 이제 게이트웨이와 유레카서버를 이용해서 코드로 구현해보려고 한다. 

 

먼저 gateway프로젝트를 만든다.

아래는 우리 프로젝트의 게이트웨이 build.gradle 파일이다.

plugins {
    id 'java'
    id 'org.springframework.boot' version '2.6.7'
    id 'io.spring.dependency-management' version '1.0.15.RELEASE'
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'

configurations {
    compileOnly {
        extendsFrom annotationProcessor
    }
}

repositories {
    mavenCentral()
    maven { url 'https://repo.spring.io/milestone' }
}

ext {
    set('springCloudVersion', "2021.0.0")
}

dependencies {
    implementation 'junit:junit:4.13.1'
    implementation 'org.springframework.cloud:spring-cloud-starter-gateway'
    implementation 'org.springframework.cloud:spring-cloud-starter-netflix-eureka-client'
    compileOnly 'org.projectlombok:lombok'
    annotationProcessor 'org.projectlombok:lombok'
    implementation 'org.springframework.boot:spring-boot-starter-security'
    implementation 'io.jsonwebtoken:jjwt:0.9.1'
    implementation 'javax.xml.bind:jaxb-api'

    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testImplementation 'org.junit.jupiter:junit-jupiter:5.8.2'
    testImplementation 'org.assertj:assertj-core:3.23.1'
    implementation group: 'com.googlecode.json-simple', name: 'json-simple', version: '1.1'

    implementation 'org.springframework.cloud:spring-cloud-starter-config'
    implementation 'org.springframework.cloud:spring-cloud-starter-bootstrap'

    implementation 'org.springframework.boot:spring-boot-starter-actuator'

}

dependencyManagement {
    imports {
        mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}"
    }
}

tasks.named('test') {
    useJUnitPlatform()
}

게이트웨이도 config 서버에 내용을 정의했으므로 bootstrap.yml을 다음과 같이 작성 해준다.

spring:
  cloud:
    config:
      uri: http://localhost:8888
      name: gateway
      profile: default

이제 핵심인 설정 파일을 살펴보겠다. 당연히 config 를 바라보는 git의 yml파일 이름은 gateway-default.yml로 설정 했으리라 믿는다.

 

server:
  port: 8080

eureka:
  instance:
    instanceId: ${spring.application.name}:${spring.application.instance_id:${random.value}}
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://localhost:8761/eureka

spring:
  application:
    name: gateway-service
  cloud:
    gateway:
      discovery:
        locator:
          enabled: true
      routes:
        - id: first-service
          uri: lb://USER-SERVICE
          predicates:
            - Path=/first-service/**
          filters:
            - RemoveRequestHeader=Cookie
        - id: first-service
          uri: lb://USER-SERVICE
          predicates:
            - Path=/first-service/management/**
            - Method=GET,POST
          filters:
            - RemoveRequestHeader=Cookie
        - id: second-service
          uri: lb://POST-SERVICE
          predicates:
            - Path=/second-service/management/**
            - Method=GET,POST
          filters:
            - RemoveRequestHeader=Cookie
        - id: second-service
          uri: lb://POST-SERVICE
          predicates:
            - Path=/second-service/post/**
          filters:
            - RemoveRequestHeader=Cookie
            - AuthorizationHeaderFilter



management:
  endpoints:
    web:
      exposure:
        include: refresh,health,beans,httptrace
      base-path: /gateway/management

 

코드가 이전의 설정보다 좀 길지만 내용은 어렵지 않다. 

 

먼저 게이트 웨이도 유레카 서버에 등록해야하므로 유레카 관련 설정을 true로 설정해 준다.

 

중요한건 discovery설정이다. 

게이트 웨이가 서비스를 라우트 해주기 때문에 패턴을 지정해줘야한다. 내가 한 프로젝트에서는 다음과 같이 first-service, second-service로 지정했다. 게이트 웨이의 Port 번호는 8080인데, localhost:8080/first-service/** 로 요청이오면 다음과 같이  url에 적힌 서비스로 보내는 것다.

 

지금은 spring.cloud.gateway.routes.url: lb://USER-SERVICE 라고 적혀있다.

이렇게 안적고 spring.cloud.gateway.routes.url: http://localhost:9000/first-service/** 이렇게 적어도 된다. 

하지만 lb라고 적은 이유는 로드밸런싱을 지원해주기 위해서고, 뒤에 실제 서비스의 url이 들어가는게 아닌 USER-SERVICE가 들어간 이유는 유레카 서버에 등록된 ID로 찾겠단 뜻이다. 

 

이는 앞에서 유레카서버 포스팅을 보면 알 수 있듯이 포트와 호스트가 동적으로 바뀌기 때문에 유레카서버에서 찾아주는것을 활용한 것이다.

 

유레카에 들어갔을 때 Application에 써있는 이름으로 쓰면 된다. 그래서 우리 서비스는 lb://USER-SERVICE로 작성하면 로드밸런싱까지 지원해준다. 

 

여기서 중요한 점이 서비스에서 url을 지정해줘야한다. 

이런식으로 지정해야한다. 

 

그리고 이제 테스트를 해보면 된다.

 

1. Config Server 키고

2. Eureka Server 키고

3. User Service 키고

4. Post Service 키고

5. Gateway Server를 킨다.

저번 포스팅을 보면 유저 서비스는 현재 9000번이다. 하지만 gateway는 8080이다. 

포스트맨 으로 요청을 보내보자!

 

나는 이전에 회원가입을 다 진행해놓은 상태라서 정상적으로 로그인이 되는 것을 볼 수 있다.

 

다음 포스팅으로는 각 서비스에 filter를 걸어 토큰을 검사하는 것을 작성해보려고한다. 

 

참고 자료

https://imprint.tistory.com/m/215