[Spring Cloud] - 3. API ์„œ๋ฒ„๋กœ ์„ค์ • ๊ฐ’ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ

๋ฐ˜์‘ํ˜•

์ง€๋‚œ ํฌ์ŠคํŠธ์—์„œ๋Š” Configuration Server๋ฅผ ์„ค์ •ํ•˜๋Š” ๋‘ ๊ฐ€์ง€ ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ดค์Šต๋‹ˆ๋‹ค. ์ฒซ ๋ฒˆ์งธ ๋ฐฉ๋ฒ•์€ ๋กœ์ปฌ์˜ ์ €์žฅ๋˜์–ด ์žˆ๋Š” ์„ค์ • ํŒŒ์ผ์„ ๊ฐ€์ ธ์˜ค๋Š” ๋ฐฉ๋ฒ•์ด์—ˆ๊ณ , ๋‘ ๋ฒˆ์จฐ ๋ฐฉ๋ฒ•์€ Github ๋“ฑ์˜ ๋ ˆํฌ์ง€ํ„ฐ๋ฆฌ์— ์žˆ๋Š” ํŒŒ์ผ์„ ๊ฐ€์ ธ์˜ค๋Š” ๋ฐฉ๋ฒ•์ด์—ˆ์Šต๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๋Š” ์ด๋Ÿฌํ•œ ์„œ๋ฒ„๊ฐ€ ์ œ๋Œ€๋กœ ๊ตฌ์ถ•๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด์„œ REST API๋ฅผ ์ง์ ‘ ํ˜ธ์ถœํ•˜์—ฌ ํ•ด๋‹น ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ ํ…Œ์ŠคํŠธ๋ฅผ ํ–ˆ์—ˆ๋Š”๋ฐ์š”. ํ•˜์ง€๋งŒ ์ด๋Ÿฌํ•œ ๊ฒฐ๊ณผ๋ฅผ ๋ณด๊ณ , ์–ด๋–ป๊ฒŒ API ์„œ๋ฒ„๊ฐ€ ์ด๋Ÿฌํ•œ ๊ฐ’์„ ๋ฐ›๋Š”์ง€์— ๋Œ€ํ•ด์„œ๋Š” ์•„๋งˆ ๊ถ๊ธˆํ•ด ํ•˜์…จ์„ ๊ฒƒ์ด๋ผ ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

๊ทธ๋ž˜์„œ ์ด๋ฒˆ ํฌ์ŠคํŠธ์—์„œ๋Š” ์ง์ ‘ ๋น„์ฆˆ๋‹ˆ์Šค ๋กœ์ง์„ ๋งŒ๋“ค๊ณ , ํ•ด๋‹น ์„œ๋ฒ„์— ๋งž๋Š” ์„ค์ •๊ฐ’์„ ๋งŒ๋“ค์–ด, ๊ฐ€์ ธ์˜ค๋Š” ๋ฐฉ๋ฒ•์„ ์•Œ์•„๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๋จผ์ € API ์„œ๋ฒ„๋ฅผ ๋งŒ๋“ค์–ด๋ณด๋„๋ก ํ•˜์ฃ .

 

์ƒˆ๋กœ์šด Spring Boot ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ

์šฐ๋ฆฌ๋Š” ์ง€๋‚œ ์‹œ๊ฐ„์— ์‚ฌ์šฉํ•œ Member, Note ์ด๋ ‡๊ฒŒ ๋‘ ๊ฐ€์ง€ ์„œ๋น„์Šค๋ฅผ ๊ทธ๋Œ€๋กœ ์‚ฌ์šฉํ•˜์—ฌ ํ”„๋กœ์ ํŠธ๋ฅผ ๋งŒ๋“ค์–ด๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. Micro Service Architecture๋กœ ์„ค๊ณ„ํ•  ๊ฒƒ์ด๊ธฐ ๋•Œ๋ฌธ์— ๋‘ ๊ฐœ์˜ ํ”„๋กœ์ ํŠธ๋ฅผ ๋งŒ๋“ค๋ฉด ๋˜๊ฒ ์Šต๋‹ˆ๋‹ค.

์ €๋Š” ์˜์กด์„ฑ ๋งค๋‹ˆ์ €๋กœ Gradle์„ ์ฃผ๋กœ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ Type์„ Gradle๋กœ ๋งž์ถฐ์ฃผ์—ˆ๊ณ , ์ด๋ฒˆ ํฌ์ŠคํŠธ์—์„œ๋Š” Java๊ฐ€ ์•„๋‹Œ Kotlin์„ ์‚ฌ์šฉํ•˜์—ฌ API ์„œ๋ฒ„๋ฅผ ๋งŒ๋“ค์–ด๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
    id("org.springframework.boot") version "2.2.2.RELEASE"
    id("io.spring.dependency-management") version "1.0.8.RELEASE"
    kotlin("jvm") version "1.3.61"
    kotlin("plugin.spring") version "1.3.61"
}

group = "xyz.neonkid"
version = "0.0.1-SNAPSHOT"
java.sourceCompatibility = JavaVersion.VERSION_1_8

repositories {
    mavenCentral()
}

extra["springCloudVersion"] = "Hoxton.SR1"

dependencies {
    implementation("org.jetbrains.kotlin:kotlin-reflect")
    implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
    implementation("org.springframework.boot:spring-boot-starter-actuator")
    implementation("org.springframework.boot:spring-boot-starter-web")
    implementation("org.springframework.boot:spring-boot-starter-data-rest")
    implementation("org.springframework.cloud:spring-cloud-starter-config")
    testImplementation("org.springframework.boot:spring-boot-starter-test") {
        exclude(group = "org.junit.vintage", module = "junit-vintage-engine")
    }
}

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

tasks.withType<Test> {
    useJUnitPlatform()
}

tasks.withType<KotlinCompile> {
    kotlinOptions {
        freeCompilerArgs = listOf("-Xjsr305=strict")
        jvmTarget = "1.8"
    }
}

Member API, Note API ๋ชจ๋‘ ๋™์ผํ•œ Gradle ํŒŒ์ผ๋กœ ๋งŒ๋“ค์–ด์ค๋‹ˆ๋‹ค.

 

Member API

ํ”„๋กœ์ ํŠธ๋ฅผ ๋งŒ๋“ค์—ˆ์œผ๋‹ˆ ์ด์ œ ์„œ๋ฒ„ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•ด๋ณด๋„๋ก ํ•˜์ฃ . ํฌ์ŠคํŠธ์—์„œ๋Š” ์ •ํ™•ํ•œ ๋กœ์ง์„ ๊ตฌํ˜„ํ•˜๊ธฐ ๋ณด๋‹ค๋Š” Configuration Server์˜ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ค๋Š”์ง€ ํŒŒ์•…ํ•˜๊ธฐ ์œ„ํ•ด, Configuration Server์˜ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” ๊ฒƒ์„ ๋กœ์ง์„ ๊ตฌํ˜„ํ•ด๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

package xyz.neonkid.cloudmember

import org.springframework.beans.factory.annotation.Value
import org.springframework.cloud.context.config.annotation.RefreshScope
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController

/**
 * Created by neonkid on 12/29/19
 */

@RestController
@RequestMapping(value = ["v1"])
@RefreshScope
class MemberController {
    @Value(value = "\${server.port}") lateinit var port: String
    @Value(value = "\${spring.message}") lateinit var message: String

    @GetMapping(value = ["/member/detail"])
    fun message() = "Member API Info - Port $port - $message"
}

๊ฐ„๋‹จํžˆ ํ˜„์žฌ ์„œ๋ฒ„์˜ ํฌํŠธ๋ฒˆํ˜ธ์™€ ๊ทธ๋ฆฌ๊ณ , Configuration Server์—์„œ ๊ฐ ์„ค์ •๋ณ„๋กœ ์ ํ˜€์žˆ๋Š” ๋ฉ”์‹œ์ง€๋ฅผ ์ถœ๋ ฅํ•˜๋Š” ๊ฒƒ์œผ๋กœ ๋งŒ๋“ค์–ด๋ดค์Šต๋‹ˆ๋‹ค.

๋”๋ณด๊ธฐ

@RefreshScope

์–ด๋…ธํ…Œ์ด์…˜์€ Spring Cloud Config Server์—์„œ ์„ค์ •๊ฐ’์„ ์ƒˆ๋กœ๊ณ ์นจ ํ•˜๋„๋กํ•˜๋Š” ์–ด๋…ธํ…Œ์ด์…˜์ž…๋‹ˆ๋‹ค. ๋ณดํ†ต ๋กœ์ปฌ ํ™˜๊ฒฝ์—์„œ ์„ค์ •๊ฐ’์„ ๊ฐ€์ง€๊ฒŒ ๋  ๊ฒฝ์šฐ, ์„œ๋ฒ„๊ฐ€ ์‹œ์ž‘๋  ๋•Œ ํ•œ ๋ฒˆ ๋กœ๋“œ๋œ ํ›„, ๋ฉ”๋ชจ๋ฆฌ์— ์ ์žฌ๋˜์–ด ๋™์ž‘ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์„œ๋ฒ„๊ฐ€ ์žฌ์‹œ์ž‘๋˜์ง€ ์•Š๊ณ ์„œ๋Š” ๋ณ€๊ฒฝ๊ฐ’์ด ์ ์šฉํ•˜์ง€ ์•Š์ง€๋งŒ, ์ด ์–ด๋…ธํ…Œ์ด์…˜์€ ์„œ๋ฒ„์—์„œ ์„ค์ •๊ฐ’์ด ๋ฐ”๋€Œ๋ฉด ์ค‘๋‹จ์—†์ด ๋‹ค์‹œ ๋กœ๋“œํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ์–ด๋…ธํ…Œ์ด์…˜์ด๋ผ๊ณ  ๋ณด๋ฉด ๋ฉ๋‹ˆ๋‹ค.

 

# bootstrap.yml
server:
  port: 8000

spring:
  profiles:
    active: dev
  application:
    name: member-service

management:
  endpoints:
    web:
      exposure:
        include: info, refresh
# bootstrap-dev.yml
spring:
  profiles: dev
  cloud:
    config:
      uri: http://localhost:9000
      fail-fast: true

Configuration Server์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์„ค์ • ํŒŒ์ผ์˜ ์ด๋ฆ„์„ bootstrap-*.yml๋กœ ํ•ฉ๋‹ˆ๋‹ค. bootstrap.yml์—๋Š” ์–ด๋–ค ํ”„๋กœํŒŒ์ผ์˜ ์„ค์ • ๊ฐ’์„ ๋ถˆ๋Ÿฌ์˜ฌ ๊ฒƒ์ธ์ง€ ์ •ํ•˜๋ฉด ๋˜๊ณ , bootstrap-*์€ ํ•ด๋‹น ํ”„๋กœํŒŒ์ผ์˜ ์ด๋ฆ„๊ณผ ํ•จ๊ป˜ Configuration Server์˜ URI๋ฅผ ์ ์–ด์ฃผ๋ฉด ์™„์„ฑ์ž…๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ , managment.endpoints.web.exposure.include ์„ค์ •์„ ์ฃผ์—ˆ๋Š”๋ฐ, ์ด ์˜ต์…˜์€ refresh API๋ฅผ ํ™œ์„ฑํ™” ์‹œํ‚ด์œผ๋กœ์จ ์„œ๋ฒ„๊ฐ€ ์ค‘๋‹จ๋˜์ง€ ์•Š์€ ์ƒํƒœ์—์„œ๋„ Configuration Server์˜ ์„ค์ •๊ฐ’์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋Š” API๋ฅผ ํ™œ์„ฑํ™” ์‹œ์ผœ์ฃผ๋Š” ์˜ต์…˜์ž…๋‹ˆ๋‹ค.

 

Note API

Note API๋„ Member API์™€ ๋™์ผํ•˜๊ฒŒ ๋งŒ๋“ค์–ด์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

package xyz.neonkid.cloudnote

import org.springframework.beans.factory.annotation.Value
import org.springframework.cloud.context.config.annotation.RefreshScope
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestMapping
import org.springframework.web.bind.annotation.RestController

/**
 * Created by neonkid on 12/29/19
 */

@RestController
@RequestMapping(value = ["v1"])
@RefreshScope
class NoteController {
    @Value(value = "\${server.port}") lateinit var port: String
    @Value(value = "\${spring.message}") lateinit var message: String

    @GetMapping(value = ["note/detail"])
    fun message() = "Note API Info - Port $port - $message"
}

Kotlin ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋‹ค ์ž๊พธ ์„ธ๋ฏธ์ฝœ๋ก  ๋ˆ„๋ฅด๋Š” ์Šต๊ด€์ด.... ;;

# bootstrap.yml
server:
  port: 8001

spring:
  profiles:
    active: prod
  application:
    name: note-service

management:
  endpoints:
    web:
      exposure:
        include: info, refresh
# bootstrap-prod.yml
spring:
  profiles: prod
  cloud:
    config:
      uri: http://localhost:9000
      fail-fast: true

๊ฐ ์„œ๋น„์Šค๋ณ„๋กœ ํฌํŠธ ๋ฒˆํ˜ธ๋ฅผ ๋‹ค๋ฅด๊ฒŒ ์ฃผ์–ด์•ผ๊ฒ ์ฃ ? ๊ทธ๋ ‡์ง€ ์•Š์œผ๋ฉด.... ํฌํŠธ ์ถฉ๋Œ์ด ์ผ์–ด๋‚˜๋‹ˆ ์ฃผ์˜.

 

Run Server

๋ชจ๋“  ์„œ๋ฒ„๊ฐ€ ๋งŒ๋“ค์–ด์กŒ๋‹ค๋ฉด ์ด์ œ ์„œ๋ฒ„๋ฅผ ์‹คํ–‰ํ•ด๋ณด๋„๋ก ํ•˜์ฃ . ๋จผ์ € Configuration Server๋ฅผ ์‹คํ–‰ํ•˜๊ณ  ๋‹ค์Œ ๊ฐ API ์„œ๋ฒ„๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ๋˜๊ฒ ์Šต๋‹ˆ๋‹ค.

2019-12-29 12:59:17.992  INFO 21594 --- [nio-9000-exec-1] o.s.c.c.s.e.NativeEnvironmentRepository  : Adding property source: file:///home/neonkid/server-configs/member-service-dev.yml
2019-12-29 12:59:20.609  INFO 21594 --- [nio-9000-exec-2] o.s.c.c.s.e.NativeEnvironmentRepository  : Adding property source: file:///home/neonkid/server-configs/member-service-dev.yml
2019-12-29 13:16:19.169  INFO 21594 --- [nio-9000-exec-4] o.s.c.c.s.e.NativeEnvironmentRepository  : Adding property source: file:///home/neonkid/server-configs/note-service-prod.yml
2019-12-29 13:16:21.786  INFO 21594 --- [nio-9000-exec-5] o.s.c.c.s.e.NativeEnvironmentRepository  : Adding property source: file:///home/neonkid/server-configs/note-service-prod.yml

์ˆœ์„œ๋Œ€๋กœ ์„œ๋ฒ„๋ฅผ ์‹คํ–‰ํ•œ๋‹ค๋ฉด, Configuration Server์—์„œ ์œ„์™€ ๊ฐ™์€ ๋ฉ”์‹œ์ง€๊ฐ€ ๋‚˜ํƒ€๋‚  ๊ฒƒ์ž…๋‹ˆ๋‹ค. 

$ curl http://localhost:8000/v1/member/detail
$ curl http://localhost:8001/v1/note/detail 

์œ„ API๋ฅผ ๊ฐ๊ฐ ๋ถ€๋ฅด๊ฒŒ ๋˜๋ฉด, Member API๋Š” ๊ฐœ๋ฐœ ์„œ๋ฒ„์˜ ์„ค์ • ๊ฐ’์„, Note API๋Š” ๋ฐฐํฌ ์„œ๋ฒ„์˜ ์„ค์ • ๊ฐ’์„ ๊ฐ€์ ธ์˜ค๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. 

Member API Info - Port 8000 - Loaded MemberService for Development Mode..
Note API Info - Port 8001 - Loaded NoteService for Production Mode..

 

Refresh Config

๋งˆ์ง€๋ง‰์œผ๋กœ ์„ค์ •๊ฐ’์„ ์„œ๋น„์Šค์˜ ์ค‘๋‹จ์—†์ด ๋™๊ธฐํ™” ํ•˜๋Š” ๊ฒƒ์— ๋Œ€ํ•ด ์•Œ์•„๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์ด ๊ณผ์ •์€ ์˜ค์ง ์„ค์ • ๊ฐ’์— ๋Œ€ํ•œ ์ถ”๊ฐ€ ํ˜น์€ ๋ณ€๊ฒฝ์— ๋Œ€ํ•œ ๊ฒƒ์ด ์ ์šฉ๋ฉ๋‹ˆ๋‹ค. ๋งŒ์•ฝ, ๊ฐœ๋ฐœ ์„œ๋ฒ„์˜ ์„ค์ • ํ”„๋กœํŒŒ์ผ์„ ๋ฐฐํฌ ์„œ๋ฒ„์˜ ์„ค์ • ํ”„๋กœํŒŒ์ผ๋กœ ๋ฐ”๊พธ๋Š” ๋“ฑ์˜ ๋ฐฉ๋ฒ•์€ ํ—ˆ์šฉ๋˜์ง€ ์•Š์œผ๋‹ˆ ์ด ๋ถ€๋ถ„์„ ์ฝ๊ธฐ ์ „์— ๋ฐ˜๋“œ์‹œ ์ฐธ๊ณ ๋ฐ”๋ž๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๋Š” ์—ฌ๊ธฐ์—์„œ spring.message ๋ผ๋Š” ํ”„๋กœํผํ‹ฐ๋ฅผ ์‚ฌ์šฉํ•˜์˜€์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ด ๊ฐ’์„ ๋ณ€๊ฒฝํ•œ ๋’ค, ๊ฐ API ์„œ๋ฒ„๋ณ„๋กœ /actuator/refresh ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด, ์„œ๋น„์Šค์˜ ์ค‘๋‹จ์—†์ด ๋ฐ”๋กœ ์„ค์ •๊ฐ’์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

spring:
    profiles: dev
    message: This configuration is development for member API..

๊ฐ„๋‹จํ•œ ์˜ˆ์‹œ๋กœ Member API์˜ ๊ฐœ๋ฐœ ์„œ๋ฒ„ ์„ค์ • ํŒŒ์ผ์˜ ๋ฉ”์‹œ์ง€๋ฅผ ์œ„์™€ ๊ฐ™์ด ๋ณ€๊ฒฝํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

Refresh API๋ฅผ ํ˜ธ์ถœํ•˜๊ธฐ ์ „๊นŒ์ง€๋Š” ๋ณ€๊ฒฝ ์‚ฌํ•ญ์ด ์ ์šฉ๋˜์ง€ ์•Š๊ณ , ๋ฉ”์†Œ๋“œ๋ฅผ ๋ถ€๋ฅธ ๋’ค์—๋Š” ๋ณ€๊ฒฝ๋œ Property ์ด๋ฆ„์„ ๋ฐฐ์—ด ํ˜•ํƒœ๋กœ ์ถœ๋ ฅํ•ด์ฃผ๋ฉฐ, ๋‹ค์Œ ํ˜ธ์ถœ์‹œ์—๋Š” ๋ณ€๊ฒฝ๋œ ๋ถ€๋ถ„์„ ๋ฐ˜์˜ํ•ด์ฃผ๋Š” ๋ชจ์Šต์ž…๋‹ˆ๋‹ค. 

 

๋งˆ์น˜๋ฉฐ...

Configuration Server ๊ตฌ์„ฑ ์ดํ›„, API ์„œ๋น„์Šค์— ์„ค์ • ํŒŒ์ผ์„ ๋™๊ธฐํ™” ํ•˜๋Š” ๊ฒƒ๊นŒ์ง€ ์•Œ์•„๋ดค์Šต๋‹ˆ๋‹ค. ๋‚ด์šฉ ์ž์ฒด๋Š” ๋ณ„ ๋งŽ์€ ๋‚ด์šฉ์ด ์žˆ๋Š” ๊ฒƒ์€ ์•„๋‹™๋‹ˆ๋‹ค. ๋‹ค๋งŒ ์—ฌ๋Ÿฌ๊ฐ€์ง€ ์‚ฌ์šฉ ๋ฐฉ๋ฒ•์ด ์กด์žฌํ•˜๊ณ , ๊ทธ๊ฒƒ์„ ์ž์‹ ์˜ ์„œ๋น„์Šค์— ๋งž๊ฒŒ ๊ฐœ๋ฐœํ•˜๋Š” ๊ฒƒ์ด ์ด ํฌ์ŠคํŠธ์˜ ๋ชฉํ‘œ์ž…๋‹ˆ๋‹ค.

์ด ๊ธ€์„ ์ž‘์„ฑํ•˜๋ฉด์„œ ๋งˆ์ดํฌ๋กœ ์„œ๋น„์Šค ์•„ํ‚คํ…์ฒ˜ ํ˜•ํƒœ์˜ ๊ฐœ๋ฐœ์€ ๋ฏธ๋ฆฌ ํ•œ ๊ฐ€์ง€ API๋ฅผ ๋งŒ๋“ค์–ด๋†“๊ณ  ํ…Œ์ŠคํŠธ ํ•ด ๋ณผ ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ด ๋ฉ”๋ฆฌํŠธ๋ผ๊ณ  ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค. ๋ฌผ๋ก  ์šด์˜ ๋ ˆ๋ฒจ๊นŒ์ง€ ๋„˜์–ด๊ฐ„๋‹ค๋ฉด ๋กœ๋“œ ๋ฐธ๋Ÿฐ์‹ฑ ๋“ฑ ๋‹ค์–‘ํ•œ ์„œ๋ฒ„ ์‚ฌ์ด๋“œ, ํด๋ผ์ด์–ธํŠธ ์‚ฌ์ด๋“œ์˜ ๊นŠ์€ ๋ฐฑ์—”๋“œ๋ฅผ ๊ณ ๋ คํ•ด์•ผ ํ•˜๋Š” ๋จธ๋ฆฌ ์•„ํ”ˆ ์ ์€ ๋‹น์—ฐํžˆ ์กด์žฌํ•˜๊ฒ ์ง€๋งŒ ๋กœ๋“œ ๋ฐธ๋Ÿฐ์‹ฑ์ด๋‚˜ ๋ฆฌ๋ฒ„์Šค ํ”„๋ก์‹œ์™€ ๊ฐ™์€ ๊ฒฝ์šฐ๋Š” ๋ชจ๋†€๋ฆฌํ‹ฑ ์•„ํ‚คํ…์ฒ˜ ๋˜ํ•œ ๊ฑฐ์ณ์•ผํ•˜๋Š” ๋ฌธ์ œ์ด๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ฅผ ๋งˆ์ดํฌ๋กœ ์„œ๋น„์Šค ์•„ํ‚คํ…์ฒ˜๋งŒ์ด ๊ฐ€์ง„ ๋‹จ์ ์ด๋ผ๊ณ  ๋ณผ ์ˆ˜๋Š” ์—†์„ ๊ฒƒ ๊ฐ™๋„ค์š”.

๋‹ค์Œ ํŒŒํŠธ์—์„œ๋Š” Gateway์— ๋Œ€ํ•œ ์ด์•ผ๊ธฐ๋กœ ๋งŒ๋‚˜๋ต™๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๋ฐ˜์‘ํ˜•
TAGS.

Tistory Comments