diff --git a/backend/src/main/java/com/ody/eta/service/EtaService.java b/backend/src/main/java/com/ody/eta/service/EtaService.java index 98432f26e..3f98993db 100644 --- a/backend/src/main/java/com/ody/eta/service/EtaService.java +++ b/backend/src/main/java/com/ody/eta/service/EtaService.java @@ -15,6 +15,7 @@ import com.ody.util.DistanceCalculator; import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; +import org.slf4j.MDC; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -60,6 +61,7 @@ private void updateMateEta(MateEtaRequest mateEtaRequest, Eta mateEta, Meeting m } if (isRouteClientCallTime(mateEta)) { + MDC.put("mateId", mateEta.getMate().getId().toString()); RouteTime routeTime = routeService.calculateRouteTime( mateEtaRequest.toCoordinates(), meeting.getTargetCoordinates() diff --git a/backend/src/main/java/com/ody/route/config/RouteClientProperties.java b/backend/src/main/java/com/ody/route/config/RouteClientProperties.java new file mode 100644 index 000000000..c4171b2c1 --- /dev/null +++ b/backend/src/main/java/com/ody/route/config/RouteClientProperties.java @@ -0,0 +1,23 @@ +package com.ody.route.config; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; +import lombok.Getter; +import org.springframework.boot.context.properties.ConfigurationProperties; + +@Getter +@ConfigurationProperties(prefix = "route") +public class RouteClientProperties { + + private final Map properties; + + public RouteClientProperties(List vendors) { + properties = vendors.stream() + .collect(Collectors.toMap(RouteClientProperty::name, property -> property)); + } + + public RouteClientProperty getProperty(String name) { + return properties.get(name); + } +} diff --git a/backend/src/main/java/com/ody/route/config/RouteClientProperty.java b/backend/src/main/java/com/ody/route/config/RouteClientProperty.java new file mode 100644 index 000000000..e293023f4 --- /dev/null +++ b/backend/src/main/java/com/ody/route/config/RouteClientProperty.java @@ -0,0 +1,5 @@ +package com.ody.route.config; + +public record RouteClientProperty(String name, String baseUrl, String apiKey) { + +} diff --git a/backend/src/main/java/com/ody/route/config/RouteConfig.java b/backend/src/main/java/com/ody/route/config/RouteConfig.java index b96b7c43f..4f79d524f 100644 --- a/backend/src/main/java/com/ody/route/config/RouteConfig.java +++ b/backend/src/main/java/com/ody/route/config/RouteConfig.java @@ -1,55 +1,58 @@ package com.ody.route.config; +import com.fasterxml.jackson.databind.ObjectMapper; import com.ody.route.service.GoogleRouteClient; import com.ody.route.service.OdsayRouteClient; import com.ody.route.service.RouteClient; import java.time.Duration; import lombok.RequiredArgsConstructor; -import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.context.properties.EnableConfigurationProperties; import org.springframework.boot.web.client.ClientHttpRequestFactories; import org.springframework.boot.web.client.ClientHttpRequestFactorySettings; -import org.springframework.boot.web.client.RestClientCustomizer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Profile; import org.springframework.core.annotation.Order; +import org.springframework.http.client.BufferingClientHttpRequestFactory; import org.springframework.http.client.ClientHttpRequestFactory; import org.springframework.web.client.RestClient; @Profile("!test") @Configuration @RequiredArgsConstructor -@EnableConfigurationProperties(RouteProperties.class) +@EnableConfigurationProperties(RouteClientProperties.class) public class RouteConfig { - private final RouteProperties routeProperties; + private static final Duration DEFAULT_CONNECTION_TIMEOUT = Duration.ofSeconds(60); + private static final Duration DEFAULT_READ_TIMEOUT = Duration.ofSeconds(30); + + private final RouteClientProperties properties; @Bean @Order(1) - public RouteClient odysayRouteClient(RestClient.Builder routeRestClientBuilder) { - return new OdsayRouteClient(routeProperties, routeRestClientBuilder); + public RouteClient odysayRouteClient(ObjectMapper objectMapper) { + RouteClientProperty property = properties.getProperty("odsay"); + return new OdsayRouteClient(property, builder(objectMapper)); } @Bean @Order(2) - public RouteClient googleRouteClient( - RestClient.Builder routeRestClientBuilder, - @Value("${google.maps.api-key}") String googleApiKey - ) { - return new GoogleRouteClient(routeRestClientBuilder, googleApiKey); + public RouteClient googleRouteClient(ObjectMapper objectMapper) { + RouteClientProperty property = properties.getProperty("google"); + return new GoogleRouteClient(property, builder(objectMapper)); } @Bean - public RestClientCustomizer routeRestClientCustomizer() { - return builder -> builder.requestFactory(clientHttpRequestFactory()) - .build(); + public RestClient.Builder builder(ObjectMapper objectMapper) { + return RestClient.builder() + .requestFactory(new BufferingClientHttpRequestFactory(clientHttpRequestFactory())) + .requestInterceptor(new RouteClientLoggingInterceptor(objectMapper)); } private ClientHttpRequestFactory clientHttpRequestFactory() { ClientHttpRequestFactorySettings settings = ClientHttpRequestFactorySettings.DEFAULTS - .withConnectTimeout(Duration.ofSeconds(60)) - .withReadTimeout(Duration.ofSeconds(30)); //TODO: timeout 처리 로직 구현 + .withConnectTimeout(DEFAULT_CONNECTION_TIMEOUT) + .withReadTimeout(DEFAULT_READ_TIMEOUT); return ClientHttpRequestFactories.get(settings); } } diff --git a/backend/src/main/java/com/ody/route/config/RouteProperties.java b/backend/src/main/java/com/ody/route/config/RouteProperties.java deleted file mode 100644 index 9a9ea9efb..000000000 --- a/backend/src/main/java/com/ody/route/config/RouteProperties.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.ody.route.config; - -import lombok.Getter; -import lombok.RequiredArgsConstructor; -import org.springframework.boot.context.properties.ConfigurationProperties; - -@Getter -@ConfigurationProperties(prefix = "odsay") -@RequiredArgsConstructor -public class RouteProperties { - - private final String apiKey; - private final String url; -} diff --git a/backend/src/main/java/com/ody/route/service/GoogleRouteClient.java b/backend/src/main/java/com/ody/route/service/GoogleRouteClient.java index afa49216e..9c9d65da6 100644 --- a/backend/src/main/java/com/ody/route/service/GoogleRouteClient.java +++ b/backend/src/main/java/com/ody/route/service/GoogleRouteClient.java @@ -3,6 +3,7 @@ import com.ody.common.exception.OdyBadRequestException; import com.ody.common.exception.OdyServerErrorException; import com.ody.meeting.domain.Coordinates; +import com.ody.route.config.RouteClientProperty; import com.ody.route.domain.ClientType; import com.ody.route.domain.RouteTime; import com.ody.route.dto.DistanceMatrixElementStatus; @@ -10,19 +11,20 @@ import com.ody.route.dto.DistanceMatrixResponse.DistanceMatrixElement; import com.ody.route.dto.DistanceMatrixStatus; import java.time.Duration; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.web.client.RestClient; import org.springframework.web.util.UriComponentsBuilder; @Slf4j +@RequiredArgsConstructor public class GoogleRouteClient implements RouteClient { - private final String apiKey; + private final RouteClientProperty property; private final RestClient restClient; - public GoogleRouteClient(RestClient.Builder routeRestClientBuilder, String apiKey) { - this.apiKey = apiKey; - this.restClient = routeRestClientBuilder.baseUrl("https://maps.googleapis.com").build(); + public GoogleRouteClient(RouteClientProperty property, RestClient.Builder builder) { + this(property, builder.build()); } @Override @@ -33,12 +35,12 @@ public RouteTime calculateRouteTime(Coordinates origin, Coordinates target) { } private DistanceMatrixResponse getDistanceMatrixResponse(Coordinates origin, Coordinates target) { - String url = UriComponentsBuilder.fromPath("/maps/api/distancematrix/json") + String url = UriComponentsBuilder.fromHttpUrl(property.baseUrl()) .queryParam("destinations", mapCoordinatesToUrl(target)) .queryParam("origins", mapCoordinatesToUrl(origin)) .queryParam("mode", "transit") .queryParam("transit_mode", "bus|subway") - .queryParam("key", apiKey) + .queryParam("key", property.apiKey()) .build(false) .toUriString(); diff --git a/backend/src/main/java/com/ody/route/service/OdsayRouteClient.java b/backend/src/main/java/com/ody/route/service/OdsayRouteClient.java index 66aa77c30..d13fa387b 100644 --- a/backend/src/main/java/com/ody/route/service/OdsayRouteClient.java +++ b/backend/src/main/java/com/ody/route/service/OdsayRouteClient.java @@ -2,7 +2,7 @@ import com.ody.common.exception.OdyServerErrorException; import com.ody.meeting.domain.Coordinates; -import com.ody.route.config.RouteProperties; +import com.ody.route.config.RouteClientProperty; import com.ody.route.domain.ClientType; import com.ody.route.domain.RouteTime; import com.ody.route.dto.OdsayResponse; @@ -10,21 +10,19 @@ import java.net.URI; import java.net.URISyntaxException; import java.util.Objects; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.web.client.RestClient; @Slf4j +@RequiredArgsConstructor public class OdsayRouteClient implements RouteClient { - private final RouteProperties routeProperties; + private final RouteClientProperty property; private final RestClient restClient; - public OdsayRouteClient( - RouteProperties routeProperties, - RestClient.Builder routeRestClientBuilder - ) { - this.routeProperties = routeProperties; - this.restClient = routeRestClientBuilder.build(); + public OdsayRouteClient(RouteClientProperty property, RestClient.Builder builder) { + this(property, builder.build()); } @Override @@ -44,12 +42,12 @@ private OdsayResponse getOdsayResponse(Coordinates origin, Coordinates target) { } private URI makeURI(Coordinates origin, Coordinates target) { - String uri = routeProperties.getUrl() + String uri = property.baseUrl() + "?SX=" + origin.getLongitude() + "&SY=" + origin.getLatitude() + "&EX=" + target.getLongitude() + "&EY=" + target.getLatitude() - + "&apiKey=" + routeProperties.getApiKey(); + + "&apiKey=" + property.apiKey(); try { return new URI(uri); } catch (URISyntaxException exception) { diff --git a/backend/src/main/resources/common.yml b/backend/src/main/resources/common.yml index ecffabcfb..50ae7880a 100644 --- a/backend/src/main/resources/common.yml +++ b/backend/src/main/resources/common.yml @@ -20,13 +20,14 @@ springdoc: operations-sorter: alpha enabled: true -odsay: - url: https://api.odsay.com/v1/api/searchPubTransPathT - api-key: ENC(7am2oBS6Y/CCfThV+Yv59ZpjjIu8vOxt8v0/cEvGFDfUemAmSpbz+vfR3bsoDrKoJ/EwmeV6VXo=) - -google: - maps: - api-key: ENC(B/qgWb19BUQN+qdCHQKP7Ocx4xszftoRM4DfcjSIxCXlwgpfvZW4QpFBMGbNqVsf) +route: + vendors: + - name: odsay + base-url: https://api.odsay.com/v1/api/searchPubTransPathT + api-key: ENC(7am2oBS6Y/CCfThV+Yv59ZpjjIu8vOxt8v0/cEvGFDfUemAmSpbz+vfR3bsoDrKoJ/EwmeV6VXo=) + - name: google + base-url: https://maps.googleapis.com/maps/api/distancematrix/json + api-key: ENC(B/qgWb19BUQN+qdCHQKP7Ocx4xszftoRM4DfcjSIxCXlwgpfvZW4QpFBMGbNqVsf) auth: access-key: ENC(Ve3QKOE7PzbTOpQ6b58Oyi1Qrr9DojPgUA+jCwYcmDdSVdP34Z2eKw==) diff --git a/backend/src/test/java/com/ody/common/BaseRouteClientTest.java b/backend/src/test/java/com/ody/common/BaseRouteClientTest.java index 524bc7b52..490b36c2d 100644 --- a/backend/src/test/java/com/ody/common/BaseRouteClientTest.java +++ b/backend/src/test/java/com/ody/common/BaseRouteClientTest.java @@ -1,6 +1,7 @@ package com.ody.common; -import com.ody.route.config.RouteProperties; +import com.ody.route.config.RouteClientProperties; +import com.ody.route.config.RouteClientProperty; import com.ody.route.service.RouteClient; import org.junit.jupiter.api.BeforeEach; import org.springframework.beans.factory.annotation.Autowired; @@ -8,7 +9,7 @@ import org.springframework.test.web.client.MockRestServiceServer; import org.springframework.web.client.RestClient; -@EnableConfigurationProperties(RouteProperties.class) +@EnableConfigurationProperties(RouteClientProperties.class) public abstract class BaseRouteClientTest { @Autowired @@ -18,15 +19,20 @@ public abstract class BaseRouteClientTest { protected RestClient.Builder restClientBuilder; @Autowired - protected RouteProperties routeProperties; + protected RouteClientProperties properties; protected RouteClient routeClient; + protected RouteClientProperty property; + @BeforeEach void setUp() { this.mockServer = MockRestServiceServer.bindTo(restClientBuilder).build(); + this.property = getProperty(); this.routeClient = createRouteClient(); } + protected abstract RouteClientProperty getProperty(); + protected abstract RouteClient createRouteClient(); } diff --git a/backend/src/test/java/com/ody/route/service/GoogleRouteClientTest.java b/backend/src/test/java/com/ody/route/service/GoogleRouteClientTest.java index ddf6ca0b9..a1695dbb5 100644 --- a/backend/src/test/java/com/ody/route/service/GoogleRouteClientTest.java +++ b/backend/src/test/java/com/ody/route/service/GoogleRouteClientTest.java @@ -9,10 +9,10 @@ import com.ody.common.exception.OdyBadRequestException; import com.ody.common.exception.OdyServerErrorException; import com.ody.meeting.domain.Coordinates; +import com.ody.route.config.RouteClientProperty; import com.ody.route.domain.RouteTime; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; -import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.test.autoconfigure.web.client.RestClientTest; import org.springframework.http.HttpMethod; import org.springframework.http.MediaType; @@ -20,12 +20,7 @@ import org.springframework.web.util.UriComponentsBuilder; @RestClientTest(GoogleRouteClient.class) -public class GoogleRouteClientTest extends BaseRouteClientTest { - - private static final String BASE_URI = "https://maps.googleapis.com/maps/api/distancematrix/json?"; - - @Value("${google.maps.api-key}") - private String testApiKey; +class GoogleRouteClientTest extends BaseRouteClientTest { @DisplayName("버스, 지하철을 이용한 소요시간 계산 요청 성공 시, 가장 빠른 소요 시간을 분으로 변환하여 반환한다.") @Test @@ -110,12 +105,12 @@ void calculateRouteTimeWhenElementStatusNotOK() { } private String makeUri(Coordinates origin, Coordinates target) { - return UriComponentsBuilder.fromHttpUrl(BASE_URI) + return UriComponentsBuilder.fromHttpUrl(property.baseUrl()) .queryParam("destinations", mapCoordinatesToUrl(target)) .queryParam("origins", mapCoordinatesToUrl(origin)) .queryParam("mode", "transit") .queryParam("transit_mode", "bus%7Csubway") - .queryParam("key", testApiKey) + .queryParam("key", property.apiKey()) .build() .toUriString(); } @@ -130,8 +125,13 @@ private void setMockServer(Coordinates origin, Coordinates target, String respon .andRespond(MockRestResponseCreators.withSuccess(response, MediaType.APPLICATION_JSON)); } + @Override + protected RouteClientProperty getProperty() { + return properties.getProperty("google"); + } + @Override protected RouteClient createRouteClient() { - return new GoogleRouteClient(restClientBuilder, testApiKey); + return new GoogleRouteClient(property, restClientBuilder); } } diff --git a/backend/src/test/java/com/ody/route/service/OdsayRouteClientTest.java b/backend/src/test/java/com/ody/route/service/OdsayRouteClientTest.java index b0b5943d6..ff76aa575 100644 --- a/backend/src/test/java/com/ody/route/service/OdsayRouteClientTest.java +++ b/backend/src/test/java/com/ody/route/service/OdsayRouteClientTest.java @@ -10,6 +10,7 @@ import com.ody.common.exception.OdyBadRequestException; import com.ody.common.exception.OdyServerErrorException; import com.ody.meeting.domain.Coordinates; +import com.ody.route.config.RouteClientProperty; import com.ody.route.domain.RouteTime; import java.io.IOException; import java.net.URI; @@ -91,12 +92,12 @@ private void setMockServer(Coordinates origin, Coordinates target, String respon } private URI makeUri(Coordinates origin, Coordinates target) { - String uri = routeProperties.getUrl() + String uri = property.baseUrl() + "?SX=" + origin.getLongitude() + "&SY=" + origin.getLatitude() + "&EX=" + target.getLongitude() + "&EY=" + target.getLatitude() - + "&apiKey=" + routeProperties.getApiKey(); + + "&apiKey=" + property.apiKey(); try { return new URI(uri); @@ -111,8 +112,13 @@ private String makeResponseByPath(String path) throws IOException { ); } + @Override + protected RouteClientProperty getProperty() { + return properties.getProperty("odsay"); + } + @Override protected RouteClient createRouteClient() { - return new OdsayRouteClient(routeProperties, restClientBuilder); + return new OdsayRouteClient(property, restClientBuilder); } } diff --git a/backend/src/test/resources/application.yml b/backend/src/test/resources/application.yml index cfc48e5c3..2c7bca394 100644 --- a/backend/src/test/resources/application.yml +++ b/backend/src/test/resources/application.yml @@ -14,13 +14,14 @@ spring: flyway: enabled: false -odsay: - url: https://api.odsay.com/v1/api/searchPubTransPathT - api-key: testApiKey - -google: - maps: - api-key: testApiKey +route: + vendors: + - name: odsay + base-url: https://api.odsay.com/v1/api/searchPubTransPathT + api-key: testApiKey + - name: google + base-url: https://maps.googleapis.com/maps/api/distancematrix/json + api-key: testApiKey allowed-origins: api-call: testOrigin