가장 기본적인 형태로 멀티 모듈 프로젝트를 구성했습니다. 이제 가상화폐 거래소 Upbit 에서 제공하는 OPEN API 를 연결해서 crypto-labs 서비스가 제공할 수 있는 하나의 API 를 만들어보겠습니다.
https://github.com/kdohyeon/crypto-labs/pull/9/commits
API Key 발급받기
OPEN API 를 사용하기 위해서는 API Key 를 먼저 발급받아야 한다. Upbit 의 경우에는 여기서 받을 수 있다.
Open API 사용하기를 클릭하면 로그인을 할 수 있다.
사용하고자 하는 기능만 선택을 하고 접근할 전용 IP 주소를 입력한다. 일단은 조회만 하면 되니 조회 관련 기능만 선택했다.
Open API Key 발급받기 버튼을 클릭하면 네이버나 카카오로 인증이 필요하다. 인증 이후에는 API Key 가 발급되는데 Access key 와 Secret key 모두 저장해두어야 한다.
IP 주소의 경우에는 MacOS 기준으로 시스템 설정 > WI-FI > 세부사항... 에서 IP 주소를 확인할 수 있다.
발급받은 API Key 입력하기
발급받은 API Key 는 adapter-http 모듈의 resources 디렉토리에 property 파일을 생성하여 넣어두면 된다. API Key 는 민감 정보이기 때문에 Github 에 올리면 안된다고 생각되어 별도의 프로퍼티 파일로 관리할 수 있다. 해당 파일을 .gitignore 에 입력하고 로컬에서만 관리할 수 있도록 하자.
해당 프로퍼티 파일은 스프링 어플리케이션이 실행될 때 import 를 하면 된다. app-api 모듈에 위치한 application.yml 파일에서 불러올 수 있다.
프로퍼티 파일에 입력해둔 API Key 값들은 @Value 어노테이션을 활용해서 코드에 적용할 수 있다.
RestTemplate 설정하기
Open API 를 호출하는 방법은 다양하다. 이번 시간에는 RestTemplate 을 사용해서 API 를 호출해보려고 한다.
먼저 RestTemplate 에 대한 설정부터 해줘야 한다. HTTP 통신을 해야 하기 때문에 connection timeout 과 read timeout 에 대한 설정을 해줘야 하고, 읽어온 JSON 데이터를 ObjectMapper 를 활용하여 파싱을 해야 한다.
@Configuration
class HttpClientConfig {
@Bean
fun restTemplate(
builder: RestTemplateBuilder,
@Qualifier(BEAN_NAME_OBJECT_MAPPER) restTemplateObjectMapper: ObjectMapper,
): RestTemplate {
return builder
.additionalMessageConverters(MappingJackson2HttpMessageConverter(restTemplateObjectMapper))
.setConnectTimeout(Duration.ofSeconds(CONNECT_TIMEOUT_SECONDS))
.setReadTimeout(Duration.ofSeconds(READ_TIMEOUT_SECONDS))
.build()
}
companion object {
const val CONNECT_TIMEOUT_SECONDS = 1L
const val READ_TIMEOUT_SECONDS = 5L
}
}
ObjectMapper 에 대한 설정은 adapter-json 모듈에서 해주었다.
@Configuration
class ObjectMappers {
companion object {
const val BEAN_NAME_OBJECT_MAPPER = "restTemplateObjectMapper"
}
@Bean(BEAN_NAME_OBJECT_MAPPER)
fun restTemplateObjectMapper(): ObjectMapper {
return JsonMapper.builder()
.findAndAddModules()
.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
.defaultTimeZone(DEFAULT_TIME_ZONE)
.defaultLocale(DEFAULT_LOCALE)
.build()
}
}
REST API 호출하기
호출하고자 하는 API 는 마켓 코드를 조회하는 API 이다. 업비트에서 거래 가능한 마켓 목록을 조회할 수 있다.
https://api.upbit.com/v1/market/all
UpbitMarketHttpClient
위에서 설정한 RestTemplate 을 주입받는다. RestTemplate 호출을 하기 위해서는 uri, httpMethod, headers 가 필요한데, 이는 restApiBuilder 에 넣어두었다. 그 이유는 호출할 API 마다 uri, httpMethod, headers 를 설정하는 부분이 조금씩 달라서 별도 클래스로 관리하는 것이 관리 측면에서 효과적일 것이라고 생각했다.
@Component
class UpbitMarketHttpClient(
private val restTemplate: RestTemplate,
private val builders: List<RestApiBuilder>,
) : UpbitMarketClient {
override fun marketAll(): List<UpbitMarket> {
val targetRestApiType = RestApiType.MARKET_ALL
val restApiBuilder = builders.first { it.isTarget(targetRestApiType) }
return restTemplate.exchange(
restApiBuilder.buildUri(),
targetRestApiType.httpMethod,
HttpEntity<HttpHeaders>(restApiBuilder.buildHeaders()),
parameterizedTypeReference<List<UpbitMarket>>()
).body.takeIf { it != null && it.isNotEmpty() }
?: emptyList()
}
}
MarketSearchService
@Service
class MarketSearchService(
private val upbitMarketClient: UpbitMarketClient,
private val marketDtoConverter: MarketDtoConverter,
) : SearchMarketUseCase {
override fun marketAll(): List<MarketDto> {
return upbitMarketClient.marketAll().map { marketDtoConverter.convert(it) }
}
}
MarketController
@RestController
class MarketController(
private val searchMarketUseCase: SearchMarketUseCase,
) {
@GetMapping("/api/v1/market/all")
fun marketAll(): List<MarketDto> {
return searchMarketUseCase.marketAll();
}
}
호출해보기
Controller 와 Service 를 모두 구현하고 만들 Controller 를 호출해보면 다음과 같이 결과가 잘 출력된다.
'스프링 > 만들면서 배우는 실무 백엔드 개발' 카테고리의 다른 글
7. 스프링부트에서 H2 데이터베이스 연결하기 (0) | 2023.03.29 |
---|---|
6. buildSrc 기반으로 라이브러리 버전 관리하기 (0) | 2023.03.27 |
4. 스프링부트 3.0 적용하기 (feat. HelloWorld API 만들기) (0) | 2023.03.22 |
3. Github 연동하기 (0) | 2023.03.21 |
2. 멀티 모듈 프로젝트 구성하기 (0) | 2023.03.21 |
댓글