문서 이력
  • 2022.02.16. 포스팅


이 글은 한투 모바일 API 샘플 앱 만들기 시리즈의 세번째 글입니다. 로그인을 수행한 뒤, 종목코드를 입력하고 현재가를 조회해보도록 하겠습니다.

참고 커밋 : Commit db38f5

0. 쿼리 파일 에셋 준비

먼저, 다음의 압축파일을 받아 압축을 해제하여 줍니다.

다운로드

파일들은 API를 이용하기 위한 쿼리 파일이며, 한국투자증권에서 제공합니다. 우리는 이 파일들을 에셋에 등록하여 앱에서 이용할 수 있도록 해주어야 합니다.

압축 해제 후, app 모듈에 에셋 디렉토리를 생성해줍니다. app 모듈에서 오른쪽 마우스를 클릭하여 다음과 같이 생성합니다.

create_assets

src/main/assets 폴더가 생성 되었음을 확인합니다. 다운로드 받은 qry 폴더를 통째로 복사하여 다음과 같은 형태로 만들어줍니다.

qry

1. 종목 조회 UI 추가

본격적인 구현에 앞서, 주식 종목에 따른 현재가 조회를 하기 위해 간단한 UI를 만들어줍니다. UI는 여러분들이 원하시는 대로 구현하시면 되고, 저는 간단하게 다음과 같이 만들어보았습니다.

qry

2. 로그인 글에서 구현한 UI에 버튼과 EditText 하나를 더 추가하여 종목코드를 입력받고, 해당하는 종목의 현재가를 조회하도록 하였습니다. 새로운 버튼과 EditText는 로그인 완료 시 visible 하도록 구현할 예정입니다.

Button의 id는 buttonSearch, EditText의 id는 editCode로 설정하였습니다.

2. ExpertTranProc 객체 생성 및 초기화

데이터 조회를 위해서는 ExpertTranProc 객체가 필요합니다. 멤버 변수로 ExpertTranProc을 만들고 onCreate에서 초기화 해줍니다.

class MainActivity : AppCompatActivity(), IExpertInitListener, IExpertLoginListener {
	private var currentPriceRqId = 0
  private lateinit var expertTranProc : ExpertTranProc
	override fun onCreate(savedInstanceState: Bundle?) {
		... // 기존 코드

		// ExpertTranProc 초기화
	  expertTranProc = ExpertTranProc(this)
    expertTranProc.InitInstance(this) // 현재 코드에서는 Error
    expertTranProc.SetShowTrLog(true)		
	}
}

위의 코드에서는 InitInstance 함수가 에러로 표시될 것 입니다. 이는 MainActivity가 ITranDataListener 를 상속하지 않고 있기 때문입니다.

3. 데이터 조회 콜백 함수 구현

MainActivity를 ITranDataListener를 상속하도록 만들고, 다음의 함수들을 구현하여 줍니다.

class MainActivity : AppCompatActivity(), IExpertInitListener, IExpertLoginListener,
    ITranDataListener {
		... // 기존 코드

		/**
     * ITranDataListener
     */

    override fun onTranDataReceived(sTranID: String?, nRqId: Int) {
        // TODO
    }

    override fun onTranMessageReceived(nRqId: Int, strMsgCode: String?, strErrorType: String?,strMessage: String? ) {
        val msg : String = "$nRqId, $strMsgCode, $strErrorType, $strMessage"
        Log.d(TAG, msg)
    }

    override fun onTranTimeout(nRqId: Int) {
        val msg : String = "$nRqId"
        Log.d(TAG, msg)
    }
}

세 개의 함수 중 onTranDataReceived 함수가 서버로부터 데이터 요청에 대한 응답을 받으면 호출됩니다. 이 함수 내에서 응답을 처리하도록 구현할 것 입니다.

4. 데이터 조회 요청 및 응답 처리 구현

다음 코드는 종목 코드 String을 인자로 받아서 현재가 조회를 요청하는 함수 입니다.

private fun requestCurrentPrice(code: String){
		val serviceCode = "scp"; // 조회 서비스 이름(코드)
    if (code.isNotEmpty()) {
        expertTranProc.ClearInblockData()
        expertTranProc.SetSingleData(0,0, "J") // J 는 주식
        expertTranProc.SetSingleData(0,1, code)
        currentPriceRqId = expertTranProc.RequestData(serviceCode)
    }
}

데이터 조회 요청은 다음과 같은 순서로 이루어집니다.

ClearInblockData 로 요청 데이터 블록을 초기화 하고, SetSingleData 로 요청 데이터를 설정 합니다. 그리고 RequestData 를 호출하여 서버에게 요청 데이터를 전송합니다.

조회 서비스 이름에 따라 응답으로 가져올 데이터의 종류가 결정됩니다. 여기서 “scp”는 현재가 조회 서비스를 의미합니다. “scpc”는 현재가 체결, “scph”는 현재가 호가 등의 다양한 서비스가 정의되어 있습니다. 자세한 사항은 API 문서를 참고하시면 됩니다.

SetSingleData의 API 정의는 다음과 같습니다.

fun SetSingleData(
		nBlockIndex : Int, // 블록 인덱스
		nItemIndex : Int, // 아이템 항목 인덱스
		strData : String // Input 데이터
)

위의 스니펫 에서 2개의 SetSingleData 호출 코드를 해석하면 0번째 블록에 첫번째 아이템의 데이터는 “J”, 0번째 블록에 두번째 아이템의 데이터는 code로 설정하겠다 가 됩니다.

조회 서비스에 따라 설정할 요청 데이터 아이템 항목의 구조가 결정됩니다. 현재가 조회의 경우, 첫 번째 아이템 항목은 시장 분류 코드, 두 번째 아이템은 종목 코드를 전달해야 합니다.

요청이 성공적으로 완료되면, 서버는 요청을 처리하여 해당하는 응답 데이터를 보내줍니다. 데이터를 받은 라이브러리에서 onTranDataReceived 함수를 호출하므로, 이 함수에 응답을 처리하는 루틴을 구현하여야 합니다.

override fun onTranDataReceived(sTranID: String?, nRqId: Int) {
    if (sTranID?.contains("scp") == true && currentPriceRqId == nRqId) {
        val currentPrice = expertTranProc.GetSingleData(0, 11) // 11 : 주식 현재가
        val dayChange = expertTranProc.GetSingleData(0, 12) // 12 : 전일 대비

        Toast.makeText(this, "현재가 : $currentPrice, 전일 대비 : $dayChange", Toast.LENGTH_SHORT).show()
    }
}

sTranID 인자는 조회 서비스 코드, nRqId 인자는 RequestData의 반환값입니다. 2개의 인자를 이용해 여러 번의 요청을 구분할 수 있습니다. GetSingleData 함수는 응답 데이터로부터 해당하는 아이템 항목을 가져오는 함수 입니다. 정의는 다음과 같습니다.

fun GetSingleData (
		nBlockIndex : Int, // 블록 인덱스
		nItemIndex : Int // 아이템 항목 인덱스
) : String // Output 데이터

SetSingleData 와 비슷한 모양새를 가지고 있습니다. 현재가 조회 서비스에서 응답 데이터의 11번 아이템 데이터는 주식 현재가, 12번 데이터는 전일 대비 입니다.

5. 결과

저는 로그인 완료 시, 종목 코드 입력 창과 검색 버튼이 나타나도록 구현했습니다. 검색 버튼의 클릭 리스너에서 requestCurrentPrice 함수를 호출하도록 만들었습니다.

테스트는 SK하이닉스(000660)의 종목코드를 이용하였습니다. 토스트 메시지를 통해 현재가는 12만 7천원, 전일 대비 5500원 하락인 것을 확인하실수 있습니다. (22년 2월 15일 기준입니다)

이번에는 조회 데이터 요청하는 법과 응답을 가져오는 방법에 대하여 설명해보았습니다. 여기에 더해 API 문서를 참고해 추가 기능을 구현하시면 다양한 기능의 앱을 구현하실 수 있을 것 입니다.

Leave a comment