특정 기업의 주가 정보 조회하여 응답을 주는 API 서버 개발
- Spring WebFlux
- Spring R2DBC
- io.asyncer:r2dbc-mysql : R2DBC mysql 구현체
- Lombok
- Spring devtools
- 특정 기업의 주가 정보 조회가 잘 작동하는가?
- 요청에 키를 포함하는가?
- 헤더
- 파라미터
- 요청 포맷을 맞추었는가?
- companyCode, startDate, endDate
- API 디자인을 하였는가?
- API 버저닝을 구현하였는가?
- API 에 대한 문서화가 잘 되었는가?
- 일관된 응답 포맷을 설계하였는가?
- 테스트를 작성하였는가?
- 최소 기능 수준까지 검증 할 수 있는가?
- 스트레스 테스트를 진행 하였는가?
- 아무래도 DB가 공용이라 진행하지 않았다.
- API Throttling 을 구현하였는가?
- 10초에 10건
- 다양한 응답 형식을 제공하는가?
- json, xml 등
- 버전 별로 엔드포인트가 다릅니다.
- 버전 1의 경우
/v1/
, 버전 2의 경우/v2/
를 붙입니다.- 예시 :
/v1/companies/NVDA/price/closing
,/v2/path/to/api
- 예시 :
- 버전을 변경하는 경우는 Breaking change 가 있을 때 변경합니다.
- 요청 형식이 달라지는 경우
- 응답 형식이 달라지는 경우
- 타입이 변경되는 경우
- 경로가 달라지는 경우
버저닝에 맞는 개발 브랜치를 사용하였습니다.
main
브랜치와 develop
브랜치 외에 다른 의미있는 브랜치는 없습니다.
main
브랜치는 항상 최신 릴리즈입니다.
제일 높은 버전의 릴리즈를 가리킵니다.
main-vN
브랜치는 N번째 버전의 최신 릴리즈입니다.
develop-v{number}
브랜치는 {number}번째 버전을 개발하는 개발 브랜치입니다.
예시 : develop-v1
기능 개발 브랜치입니다. 기능 개발이 완료된 경우 develop으로 병합하게 됩니다.
형식 : /v1/companies/{companyCode}/price/closing
- 기본적으로
/v1/companies/회사-코드/상위-카테고리/하위-카테고리
을 염두에 두고 설계하였습니다. - 기업 코드가 많지 않고, api와 겹칠 가능성이 거의 없다고 판단하여
PathVariable
로 API를 구성하였습니다.- 겹친다고 하여도, route 순서상 문제 생길 확률이 낮다고 판단하였습니다.
- 만약 시작가, 평균가 API를 구현한다면,
/v1/companies/{companyCode}/prices/open
,/v1/companies/{companyCode}/price/avg
로 일관성 있는 설계가 가능합니다.
API 서비스를 구현한다고 하였을 때, 제일 중요한 것은 요청,응답 변수명을 통일하는 것이라고 생각합니다.
기본적으로 카멜케이스로 작성하며, 아래의 내용을 따릅니다.
단어 | 변수명 |
---|---|
검색 시작일 | startDate |
검색 종료일 | endDate |
거래일 | tradeDate |
회사 코드 | companyCode |
회사명 | companyName |
시가 | openingPrice |
종가 | closingPrice |
평균가 | avgPrice |
거래량 | volume |
최고가 | highPrice |
최저가 | lowPrice |
기본적으로 HTTP Status 코드로 상태를 표시하고, 추가적인 내용이 있을 경우 message
로 전달합니다.
[!INFO]
HTTP 상태 코드만으로도 현 API 구현상 충분히 상태를 설명 할 수 있다고 생각합니다.
그 외의 상황을 세부적으로 설명하는 것은 사용자에게 도움이 되지만, 그것을 코드화 할 필요성은 현 상황상 없는 것 같습니다.
- 200 : 정상 작동 경우
- 400 : 파라미터가 잘못된 경우
- 403 : 인증 정보가 잘못되어 인증할 수 없는 경우
- 404 : 존재하지 않는 API를 호출한 경우
- 429 : API 시간당 허용량을 넘길 경우
- 500 : 서버에 에러가 발생해 정상적인 응답을 할 수 없는 경우
{
"message": "OK",
"data": {
// 내용
}
}
{
"message": "에러 상황 설명",
"data": {
// 에러 상황을 설명할 수 있는 데이터
// 혹은 에러가 발생한 데이터
}
}
아래 방법 중 하나를 이용해 모든 요청에 API KEY를 제출하셔야 합니다.
- 요청에,
x-api-key
를 키로 하고, 사전에 제공받은 키값을 값으로 가지는 헤더를 추가해 주세요. - 요청에,
apiKey
를 키로 하고, 사전에 제공받은 키값을 값으로 가지는 Query Parameter 를 추가해 주세요.
- 200 : 정상 상황
- 400
- 요청에 키가 없는 경우
- 필수 파라미터가 오지 않은 경우
- 파라미터를 잘못 명시한 경우
- 403 : 키가 틀린 경우
- 404 : 존재하지 않는 API를 호출할 경우
- 429 : 요청 허용량을 초과한 경우
- 500 : 서버 에러
- Path Variables
companyCode
- 회사 코드를 입력해 주세요 ex) NVDA, AAPL 등
- 없는 회사 코드를 입력하면, 정상 응답이 반환되므로 주의해주세요!!
- Query Parameters
startDate
- 검색 시작일을 yyyyMMdd 형식으로 입력해 주세요. ex) 20240108
- 검색 시작일을 포함합니다.
endDate
보다 뒤의 날짜를 지정할 수 없습니다. (같은 날짜는 가능합니다.)
endDate
- 검색 종료일을 yyyyMMdd 형식으로 입력해 주세요. ex) 20240108
- 검색 정료일을 포함합니다.
startDate
보다 앞의 날짜를 지정할 수 없습니다. (같은 날짜는 가능합니다.)
200
message
- "OK" 가 반환됩니다.
data
- 배열 형식입니다.
- 시작일과 종료일 사이의 회사명(companyName), 거래일(tradeDate), 종가(closingPrice) 정보가 들어 있습니다.
- 응답 예시
{ "message": "OK", "data": [ { "companyName": "NVIDIA Corporation", "tradeDate": "2024-01-02", "closingPrice": 48 }, { "companyName": "NVIDIA Corporation", "tradeDate": "2024-01-03", "closingPrice": 48 }, { "companyName": "NVIDIA Corporation", "tradeDate": "2024-01-04", "closingPrice": 48 }, ] }
4XX
- message
- 오류에 대한 메시지가 반환됩니다.
- data
- 오류와 관련된 정보가 간혹 제시되나, 거의 제시되지 않습니다.
- 응답 예시
{ "message": "Missing Api Key", "data": { } }
2개의 테이블 존재
- company : 기업 정보를 저장한 테이블
- company_code : PK, varchar(100)
- company_name : varchar(100)
- stocks_history
- id : PK, AI, int
- company_code : FK, varchar(100)
- trade_date : date
- 거래일
- open_price : bigint
- 시작가
- high_price : bigint
- 최고가
- low_price : bigint
- 최저가
- close_price : bigint
- 종가
- volume : bigint
- 거래량