한국투자증권 모바일 API 활용하기 1탄
포스트
취소

한국투자증권 모바일 API 활용하기 1탄

해당 원글은 미디엄 블로그에서 작성한 내용을 해당 블로그에 기록하기 위해 가져옴. 원글은 2021.02.19일 작성.

개요

  • 자동 투자 봇을 만들어 보려고 한다.
  • 다양한 증권사 중 한국투자증권(이하 한투)으로 결정한 이유는 이미 계좌가 개설되어 있기 때문이다. 매우 단순한 이유지만 사실 모바일 API를 지원하지 않았으면 대표 적인 증권사인 키움이나 대신으로 넘어갔을지도 모른다.
  • 한투의 기본 COM방식(?)은 OpenAPI 예제가 없어도 너무 없었다. 여러가지 고민을 했었는데 모바일이라면 쉽게 접근할 수 있을 것 같아서 시작해보려고 한다.

생각대로 안되면 때려 치우고 결국 새롭게 계좌 개설 하러 갈지도 모름..

참고로 한국투자증권 Rest API가 출시됨.. 해당 포스트 보러 오신분은 얼른 이 페이지에서 나가주세요.

  • 그럼 처음부터 차근차근 시작해 보자.
  • 전략은 간단하다. 한투 모바일 API 앱내에 Netty Framework이용하여 Http 서버를 만들고, 파이썬으로 서버에 접근하여 모바일 API를 간접적으로 호출하는 것이다.

1. 한투 모바일 API를 받아보자.

  • 모바일로 써있는 건 모두 받자

2. 세가지 파일 모두 압축을 풀어보자

  • 가이드 파일은 API 사용법에 대해 잘 나와있으니 계속 확인을 해야한다.

CommExpert_mobile 이라고 Open API 프로그램이 있는데 딱히 필요는 없다. 중요한 건 샘플 프로그램이다. 이 샘플 프로그램을 Android Studio로 열어보자. 아래 그림과 같은 구조의 프로그램을 확인할 수있다. CommExpert 모듈이 증권사에서 제공하는 Open API 모듈로 가장 핵심적인 부분이라고 할 수있다. OpenApiSample 모듈은 CommExpert를 이용한 간단한 앱 예제이다.

  • 이 프로젝트 그대로 앱을 실행하면 매우 심플한 화면을 만날 수 있다.
  • 앱이라서 여러가지 화면들로 구성되어있다.

3. 샘플 프로그램 수정

  • 샘플 프로그램 그대로 사용해도 상관은 없다.
  • 하지만 난 앱 내의 서버만 잘 올라가면 되기 때문에 화면구성은 메인화면을 제외하고 다 삭제해버렸다.

화면 구성 외에 다른 것들은 건드릴 필요가 없어서 그대로 두고 필요없는 것은 모두 삭제한 뒤 다시 테스트를 해본다. 그렇게 완성된 프로젝트는 아래 그림과 같다.

이렇게 완성되기까지 꽤 많은 시행착오를 거쳤다. 안드로이드 프로그래밍 숙련자라면 쉽게 완성할 수 있을 것이다.

  • 간단히 만든 예제
  • 참고로 그냥 시작하면 공인인증서 파일이 없다는 알럿이 뜬다. 에뮬내에 공인인증서를 넣어주면 해결될 것 같지만 에뮬레이터에선 잘 안되니 테스트용도로만 사용하자. 실제 안드로이드 폰에 설치해서 확인해본 결과 공인인증서만 잘 넣어놓으면 공인인증서 로그인도 잘 된다. 사고 팔고 하려면 필요하니 로그인 할 수 있도록 하자.

몰랐는데 안드로이드 sdcard 디렉토리를 보면 NPKI 디렉토리가 친절하게 잘 구성되어 있더라…

4. Netty 서버 구축

  • 앱이 로딩이 되면 서버가 바로 시작되어야하기 때문에 적절한 곳에 서버 시작 프로세스를 추가했다.
1
2
3
4
5
6
7
8
@Override
public void onInitFinished() {
    // TODO Auto-generated method stub
    Toast.makeText(this, "초기화 성공", Toast.LENGTH_SHORT).show();

    StartServer startServer = new StartServer();
    startServer.startServer();

  • CommExpertMng가 초기화 되고 로그인 시작 전에 서버 시작한다.
  • Netty Http 서버는 github 예제에서 그대로 가져와 사용했다.(netty 사랑합니다.)
  • Port는 전세계 기본 port 8080
  • 서버가 구동되고 adb port forward를 통해 8080 port를 연결한뒤 127.0.0.1:8080에 접속하면 Hello world를 만날 수 있다.

안녕 월드

5. Netty SimpleChannelInboundHandler

  • Netty가 중요한게 아니니 간단히 어떻게 활용했는지만 작성해본다.

SimpleChannelInboundHandler를 상속받은 Class를 확인해보자

  • HttpRequest가 중요하다.
  • HttpRequest Class를 확인해보면 uri를 받아올 수 있는데 이걸 활용하여 apiName과 parameter를 구분할 것이다.
  • 예를 들면 127.0.0.1:8080/getAccountNo/1 이런식으로 호출하면 getAccountNo가 apiName이고 1을 parameter로 활용하는것이다.
  • apiName으로 필요한 요청을 구분하고 요청에 필요한 parameter를 전달한다. 간단하게 enum으로 작성해 봤다.

일단 무식하게 짠 코드

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
HttpRequest req = (HttpRequest) msg;

Log.d(TAG, "uri : " + req.uri());
ApiCommand apiCommand = null;
String params = "";
String mainUri = StringUtils.substring(req.uri(), 1);
if (StringUtils.isNoneBlank(mainUri)) {
    String[] paramList = mainUri.split("/");
    if (paramList.length == 1) {
        apiCommand = ApiCommandFactory.INSTANCE.getApiCommand(paramList[0]);
    } else if (paramList.length == 2) {
        apiCommand = ApiCommandFactory.INSTANCE.getApiCommand(paramList[0]);
        params = paramList[1];
    }
}

String result = "no Result";
if (apiCommand != null) {
    if (StringUtils.isNoneBlank(params)) {
        result = apiCommand.getResult(params.split(","));
    } else {
        result = apiCommand.getResult(params);
    }
}

Log.d(TAG, "api result  : " + result);

ApiCommand Enum

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
public enum ApiCommand {
    AccountSize("getAccountSize") {
        @Override
        public String getResult(String... params) {
            int nCount = CommExpertMng.getInstance().GetAccountSize();
            return String.valueOf(nCount);
        }
    },

    AccountNo("getAccountNo") {
        @Override
        public String getResult(String... params) {
            String index = params[0];
            String strAcc = CommExpertMng.getInstance().GetAccountNo(Integer.parseInt(index));
            return strAcc;
        }
    },

    AccountCode("getAccountCode") {
        @Override
        public String getResult(String... params) {
            String index = params[0];
            String strAccCode = CommExpertMng.getInstance().GetAccountCode(Integer.parseInt(index));
            return strAccCode;
        }
    },

    AccountName("getAccountName") {
        @Override
        public String getResult(String... params) {
            String index = params[0];
            String strAccName = CommExpertMng.getInstance().GetAccountName(Integer.parseInt(index));
            return strAccName;
        }
    };
}
  • api가 추가될 수록 enum 클래스 내용이 길어지겠지만, 딱히 유지보수 할 내용도 없고 해서 간단하게 가려고 한다.

테스트로 호출해보니 잘 돌아간다.

계좌 2개 잘있음

  • favicon.ico는 브라우저에서 테스트를 해서 그런 것 같고 앞으로 파이썬에서 테스트 하면 호출 안될 것 같다.

그래서 앞으로의 과제는

  • 응답을 text/plain으로 보내고 있는 부분을 application/json으로 바꾸기
  • 필요한 api 모두 등록하기
  • 파이썬에서 호출 테스트 해보기

마무리

  • 이렇게만 완성하면 본격적으로 파이썬을 이용한 자동 투자 봇을 만들 수 있을 것 같다.
  • 여기까지 만드는 데 퇴근 후 짬짬히 시간내어 3~4일정도 걸린 것 같은데 앞으로 파이썬 공부하면서 완성하려면 정말 긴 여정이 될 것 같다… 일 때려치우고 여기에 매달릴 수도 없고 ㅠ
  • 찬찬히 진행해서 2탄으로 등장할 수 있도록 하자!
이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.

JAXBContext, Unmarshaller와 lombok

한국투자증권 모바일 API 활용하기 2탄