728x90
반응형

안녕하세요 7개월차 주린이 건리버입니다.
제가 주식을 시작하게된 계기는 회사 지인이 소개 해준 존리 대표의 강의 영상을 보고나서였습니다. 갑자기 "나도 가치투자자가 되고싶어!" 라는 생각이 들어 무작정 증권계좌부터 만들었죠.

[존리 유튜브 영상 바로가기]

그 때도 지금도 복잡한 재무제표를 잘 볼줄은 모릅니다만 그래도 재무제표에서 내가 꼭 보고싶은 정보만 가져와서 관심있는 종목들을 자동으로 비교해줬으면 좋겠다는 생각했습니다. 구글링을 해보니 다른 사람들도 저와 같은 생각을 했는지 파이썬을 이용해 증권관련 웹페이지를 파씽(크롤링)하거나, 증권사 API를 활용해서 분석하고 자동매매하는 사람들도 많이 있는 것 같았습니다. (우리나라에도 정말 대단한 사람들 많습니다...)

그러다가 또 우연히 발견한게 바로 2020년에 서비스를 시작한 Open DART입니다. DART는 대한민국의 전자공시시스템으로 회사가 법적으로 공시해야하는 공시자료들을 모아놓은 곳이라고 보시면 되는데요. 이 방대한 자료들을 전산화해 누구나 사용할 수 있는 서비스를 개시한 것입니다.

물론 실시간 가격 정보 같은 것은 나오지 않습니다. 어디까지나 공시자료를 열람하는 것 뿐이니까요. 제가 Open Dart를 활용하고자 하는 목적도 재무제표에 나오는 정보들을 효율적으로 활용하고싶은 것 뿐입니다.

Open DART 테스팅

그럼 지금부터 Open Dart를 이용한 테스트를 시작해보겠습니다.

우선 Open Dart 사이트로 들어갑니다.
[Open Dart 사이트 바로가기]

인증키 신청하기

"인증키 신청/관리 > 인증키 신청!"

모든 약관에 동의하고 개인정보를 입력한 후 "등록" 버튼을 누르면 이메일을 통해 인증링크를 받을 수 있습니다.

이렇게 인증이 완료되면 API Key가 생성되는데요.
나의 API Key는 "인증키 신청/관리 > OpenAPI 이용현황" 에서 확인하실 수 있습니다.

API Key는 40자리 영문/숫자 조합으로 이루어져있는데 데이터를 요청할 때 기본적으로 필요한 값입니다.

재무제표 데이터 긁어오기

만들어진 API Key를 이용해 재무제표를 데이터를 요청하는 방법입니다.

요청 방법은 모두 개발가이드에 설명되어있습니다.
[상장기업 재무정보 개발가이드 바로가기]

위 설명에도 나와있듯이 GET 요청을 통해 데이터를 요청할 수 있습니다. (GET 요청에 대해서 잘 모르시는 분들은 REST API에 대해서 알아보세요).

저는 처음에  corp_code(고유번호)가 종목코드를 나타내는 줄 알고 종목코드 "005930"(삼성전자)_를 넣어보니 조회가 안됩니다. Open DART에서는 종목코드가 아닌 회사별 고유번호를 따로 제공하고있습니다. _값설명_에 나와있듯이 _"개발가이드 > 공시정보 > 고유번호 API 조회 가능" 에 가시면 고유번호를 받을 수 있는 방법이 자세히 설명 되어있습니다. 

위 설명과 같이 테스트 해봅시다.  

https://opendart.fss.or.kr/api/corpCode.xml?crtfc\_key=\[API인증키\]

웹브라우저를 열고 URL에 API Key를 포함해서 입력해보니 "corpCode.exe" 라는 이름의 파일 하나가 다운로드 됩니다.

이 파일의 확장자를 .zip으로 바꾸고 압축을 풀면 "CORPCODE.xml" 파일이 생성됩니다.

이 파일에서 보이는 삼성전자의 고유번호는 "00126380" 이네요.

위에서 찾은 고유번호로 다시 한 번 조회 해봤습니다. 제 52기 3분기말 유동자산 203조원이, 실제 제무제표와 일치함을 확인해봤습니다. (참고로 아래 제가 사용한 툴은 Postman이라는 툴입니다. REST API를 테스트할 때 유용한 툴이니 관심있으신 분들은 https://www.postman.com/ 을 방문해보세요)

 

728x90
반응형

'IT노트 > 기타' 카테고리의 다른 글

[안드로이드] MainActivity 관찰하기  (0) 2020.09.14
Kotlin 배우기  (0) 2020.09.08
[소프트웨어] Composition vs Aggregation  (0) 2020.04.29
티스토리 파헤치기 - 2탄  (0) 2018.08.11
티스토리 스킨 파헤치기 - 1탄  (3) 2018.08.08
728x90
반응형

안녕하세요 건리버입니다.
오늘부터 안드로이드에 대해 아주 차근차근 들여다보려고 합니다.
안드로이드를 새롭게 배우고 싶으신 분들을 위해 설명도 최대한 자세히 넣겠습니다.
저도 같이 공부하면서 적어 내려가는 내용인 만큼 혹시 틀린 부분이 있더라도 너그러이 봐 주시고 댓글 남겨주시면 참고하여 수정하도록 하겠습니다.

안드로이드 개발환경 설정하는 방법은 구글링해보면 많이 나와있습니다.
특히 아래 링크한 "멈춤보단 천천히라도" 블로그를 참고하시면 좋을 것 같습니다.
다른데보다 친절하고 자세하게 적혀있더라구요.(Windows 기준으로 설명 되어있지만, Mac에서도 크게 다르지 않습니다)
https://webnautes.tistory.com/1126

안드로이드 스튜디오에서 빈 프로젝트를 생성해 봅시다.
모두 디폴트 세팅을 해주되 저는 Java 대신 Kotlin 언어를 선택 했습니다.
이 전 포스트에서도 잠깐 다뤄봤지만 안정성과 간결성을 높인 Kotlin은 요즘 시장에서 거의 필수라고 보는 것 같습니다.

위와 같은 프로젝트가 생성되었습니다.
아래 세 가지 파일들이 모두 생성되었는지 확인해보세요. 프로젝트를 이루는 가장 핵심이 되는 파일들입니다. 만약 'Kotlin' 대신 'Java'를 선택했다면 MainActivity의 확장자가 .kt 대신 .java라고 나올겁니다.

app/manifests/
--> AndroidManifest.xml

app/java/
--> MainActivity.kt

app/res/
--> activity_main.xml

이 중 Kotlin 코드가 담길 MainActivity.kt를 먼저 살펴보겠습니다.

package com.example.androidstudy

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle

class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }
}

맨 윗 줄에 "package com.example.androidstudy"는 제 프로젝트 명이자 제가 만들 어플리케이션의 고유 ID가 됩니다. 따라서 실제로 구글스토어에 릴리즈할때는 example 부분을 주로 사이트 도메인 이름으로 사용합니다. 예를 들어 네이버 지도같은 경우 com.naver.maps 라는 패키지 이름을 쓰고 있죠.

다음 import는 외부의 패키지를 사용하겠다고 선언 하는 것인데요.

  • AppCompatActivity
  • Bundle

이 두개를 디폴트로 사용하고 있습니다.

Android developers page에서 AppCompatActivity를 찾아보면 이렇게 설명하고 있습니다.

Activity의 기본이 되는 클래스이며, 구형 Android 장치에서도 새로운 플랫폼의 기능을 하위호환될 수 있도록 만들어진 것 같습니다.

다른 말은 잘 모르겠지만 어쨌든 중요한 것은 Activity라는 것이고, 그렇다면 이번엔 Activity가 무엇인지 알아봐야할 것 같습니다.

역시 Android devlopers page 에서 찾아봅시다.

요약하자면 일반적인 프로그램이 main() 함수에서 앱을 시작하는 것과 달리, Android는 특정한 lifecycle에 따라 Activity 인스턴스 안에 있는 특정한 Callback함수를 호출하여 초기화한다는 것이죠. (Callback 함수에 관련된 내용은 나중에 Kotlin을 정리하면서 포스팅하도록 하겠습니다.)

안드로이드에서 하나의 Activity에 대한 lifecycle이라는 것은 이렇게 생겼습니다.

Activity가 시작되면 onCreate() 함수가 가장 먼저 호출 되는 것을 볼 수가 있죠.
그러고 보니 우리의 MainActivity 클래스 안에도 onCreate() 함수가 오버라이드 되어있네요. 이 함수가 우리 코드의 시작점이라는 것을 이해할 수 있습니다.

override fun onCreate(savedInstanceState: Bundle?)

또 하나 Activity에 대해 중요한 내용이 들어있는데요.

Activity를 사용하기 위해서는 반드시 manifest 파일에서 activity를 선언해주어야 한다고합니다.

그럼 제가 생성한 프로젝트의 manifest 파일을 한번 확인해볼까요?
app/manifests/
--> AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.androidstudy">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

프로젝트를 생성할 때 안드로이드 스튜디오가 자동으로
<activity android:name=".MainActivity">
를 manifest에 선언을 해준 것을 볼 수 있군요.

 

override fun onCreate(savedInstanceState: Bundle?) 

그럼 마지막으로 onCreate() 함수에 인자로 받고 있는 Bundle은 무엇일까요?
Bundle이란 Activity 간에 데이터를 주고 받기 위해 사용하는 개념입니다.

저의 빈 프로젝트에서 Bundle은 어떤 값을 갖고 있을지 궁금해서 디버깅 모드로 실행시킨후 변수를 관찰 해 보았습니다.

savedInstanceState: null 이라고 써있는게 보이시나요?
처음 시작한 이 빈 프로젝트는 Bundle에 null을 전달해서 onCreate() 함수를 호출 하였습니다. 전달 받은 Bundle이 빈 것으로 보아 받을 데이터가 아직 없나보군요. 아무 것도 없어서 조금 아쉽긴 하지만 어찌보면 새로운 프로젝트에 데이터가 비어있는 것은 어찌보면 당연한 것이겠죠?

여기까지 간단하게 MainActivity가 어떻게 생겼는지 관찰해보았습니다.
관찰만하니 조금 아쉽네요.
다음 포스팅부터는 실제 Code를 수정하여 원하는 동작이 잘 되는지 확인해보도록 하겠습니다.

728x90
반응형
728x90
반응형

본문은 안드로이드 공식사이트를 참조하여 작성하였습니다.
안드로이드_공식사이트

Android를 처음 배웠을 때는 JAVA만 알면 됬었던 것 같다.
다시 Android를 보려고 하니 Kotlin이라는 아이가 있더라.
JAVA랑 100% 호환되면서 간결성과 안정성을 높인 언어라나...
암튼 뭐 이런녀석을 만들었고 Android에서도 공식적으로 개발 언어로 채택했다는데 나도 배워봐야지 않겠나 싶어 기본 문법부터 보기로 했다.

변수선언

변수는 선언하는 키워드는 두가지가 있다.
val, var

val은 값이 변경되지 않는 변수(사실은 상수, c언어로 치면 const가 앞에 붙은 변수),
var은 값이 변하는 일반적인 변수이다.

Java

String myName = "Gunliver";

Kotlin

var myName : String = "Gunliver"

어? 간결해지기는 커녕 오히려 복잡해진 것 같은데...? (일단 좀더 지켜봅시다)
뒤에 세미콜론이 없어진건 좀 간결해졌다고 볼수 있으려나

Kotlin도 유형추론이 가능하다

var myName = "Gunliver"  
var myAge = 20

// Fails to compile  
myAge = "twenty"

위와 같이 타입을 생략 가능하지만 생략만 할뿐 실제로는 Compile시 유형을 정하는 것이기 때문에 유형을 변경할 수는 없다.

Null 안전

// Fails to compile
var myName : String = null

var myName : String? = null

Kotlin에서는 기본적으로 변수에 null값을 넣을 수 없다. null을 꼭 넣어야하는 변수라면 두번째와 같이 물음표? 를 넣어 nullable 변수로 선언해줘야만 한다. NullPointerException을 막기위한 방법으로 프로그래머가 귀찮게 ?를 넣어야만 null값을 허용해주는 방식으로 가볍게(?) 문제를 해결. 이렇게까지 하는데는 다 이유가 있겠지 생각하고 nullable 변수를 선언할때는 매우 신중하자.

조건부

if (count == 42) {
    println("I have the answer.")
} else if (count > 35) {
    println("The answer is close.")
} else {
    println("The answer eludes me.")
}

이런 일반적인 조건은문 아래와 같이 작성할 수 있다.
조건마다 println을 하지 않고 맨 위에 선언한 변수에 할당할 값만 작성.

val answerString: String = if (count == 42) {
    "I have the answer."
} else if (count > 35) {
    "The answer is close."
} else {
    "The answer eludes me."
}

println(answerString)

조건이 여러개일 때 아래와 같이 when을 사용할 수도 있다.

val answerString = when {
    count == 42 -> "I have the answer."
    count > 35 -> "The answer is close."
    else -> "The answer eludes me."
}

println(answerString)

오~! 이제서야 Kotlin의 간결성이란게 뭔지 조금씩 보이는 것 같다.
많이 줄였지만 가독성면에서도 떨어지지 않는 것 같아 마음에 든다.

함수

함수를 선언할 때는 fun 키워드를 사용한다.
fun 함수이름 ( 인수이름 : 인수자료형 ) : 출력자료형

Kotlin

fun generateAnswerString(countThreshold: Int): String {
    val answerString = if (count > countThreshold) {
        "I have the answer."
    } else {
        "The answer eludes me."
    }

    return answerString
}

반환키워드를 할당 연산자로 바꿀 수도 있다.

fun generateAnswerString(countThreshold: Int): String = if (count > countThreshold) {
        "I have the answer"
    } else {
        "The answer eludes me"
    }

이거 새롭긴한데 뭔가 익숙치 않은 느낌이다.

익명 함수

val stringLengthFunc: (String) -> Int = { input ->
    input.length
}

여기서 'stringLengthFunc'가 함수의 이름 같지만 함수의 이름이 아니라 익명함수를 참조하는 변수의 이름이다. 함수포인터 또는 델리게이트 라고 보면 될 것 같다.

(String) -> Int 입력 String을 받아서 출력 Int 가 나오는 모양이고,
그 함수는 입력의 길이를 구하는 내용이다.
input -> input.length

이렇게 함수을 참조하는 변수는 고차함수(콜백함수)에 인자로 들어갈 수 있다.

고차 함수

fun stringMapper(str: String, mapper: (String) -> Int): Int {
    // Invoke function
    return mapper(str)
}

'stringMapper'는 입력을 'String' 변수 하나와 '(String) -> Int' 형태의 함수를 인자로 받는다. 이런 함수는 아래와 같이 익명함수를 확용하여 호출 할 수도 있다.

stringMapper("Android", { input ->
    input.length
})

클래스

class키워드로 클래스를 만들 수 있다.
속성은 변수선언과 마찬가지로 변경 가능한 것은 'var', 변경 불가능한 것은 'val'로 선언한다.

class Car {
    val wheels = listOf<Wheel>()
}

getter 와 setter를 만들고 싶을 때는 속성아래에 'get()', 'set()'을 넣어주자.

var stringRepresentation: String
    get() = this.toString()
    set(value) {
        setDataFromString(value)
    }
728x90
반응형
728x90
반응형

소프트웨어 특히 OOP(Object-Oriented Programming)를 다룰 때 클래스간의 관계를 나타내기 위해 Class Diagram을 그리곤 한다. 이 때 헷갈리는 부분이 Compotition(구성) 과 Aggregation(집합)의 차이이다. 둘 다 전체와 부분이라는 점에서 동일하지만 생명 주기로 보면 차이가 있기 때문에 화살표의 모양도 다르게 그린다. 잘 정리된 블로그가 있어 블로그 링크(맨아래)와 함께 요약해 보았다.

Composition은 전체와 부분이 강력한 연관 관계를 맺으며, 전체와 부분이 같은 생명 주기를 갖는다.
( 'Car' 와 'Engine' 의 관계 )
( 'House' 와 'Room' 의 관계 )

public class Engine
{
    ......
}

public class Car
{
    Engine e = new Engine();
    .......
}

Aggregation은 전체와 부분의 연관 관계를 맺지만, 그러나 동일한 생명 주기를 갖지는 않는다.
( 'Person' 과 'Address' 의 관계 )
( '역사과목' 과 '학생' 의 관계 )

public class Address
{
     ......
}

public class Person
{
     private Address address;
     public Person(Address address)
     {
         this.address = address;
     }
     ......
}

https://sonsooresoon.tistory.com/entry/Aggregation-%EA%B3%BC-Composition-%EC%9D%98-%EC%B0%A8%EC%9D%B4

728x90
반응형
728x90
반응형

오늘은 스킨의 전체적인 구조를 한번 살펴보고 원하는 디자인을 어디에 삽입해야 하는지 알아보려고 합니다.


저같은 경우  복잡한 문제를 쉽게 해결할 있도록 구글의 Chrome 브라우저를 사용해보았습니. 

제가 개인적으로 너무나 좋아하는 브라우저입니다.





크롬 브라우저에  티스토리 블로그를 띄워놓고오른쪽 상단의 [옵션] - [도구 더보기] - [개발자 도구 클릭해줍니다. (Windows 환경에서는 F12 단축키를 이용할 수도 있습니다.)




우측 패널에 html 구조가 나타나는게 보이시나요?

복잡한 스크립트의 왼쪽 화살표를 눌러주며 상세한 내용을 닫아보겠습니다.



어느 html 스크립트를 봐도 <head><body> 이루어진 여기까지의 구조는 거의 동일하다고 보시면 됩니다.

저는 여기서 본문을 보고싶기 때문에 <body> 다시 열어보겠습니다.


그리고마우스를 스크립트에 가져가서 조금씩 이동하다보면 왼쪽 뷰어에서 스크립트에 해당하는 부분이 하이라이트 되는 것을   있습니다이런식으로 어느부분에 디자인을 추가할지 결정할  있습니다저는 헤드라인 바로 아래 멋진 제목칸을 하나 추가해보도록 하겠습니다.



Chrome 개발자도구로 확인해보니 저같은 경우 <div id=“cMain”>…</div>  가장  부분에 추가하면   같습니다.


이제 삽입할 위치를 정했으니 추가할 디자인을 골라야겠죠?

저는 여기에 멋진 제목을 넣기 위해서 Bootstrap Jumbotron 추가해보겠습니다.


우선 <head>…</head> 안에 Bootstrap 사용하기 위한 CDN 추가해야합니다.

Bootstrap 홈페이지(https://getbootstrap.com/)에서 CDN 태그들을 복사해옵니다.

 <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin=“anonymous"> 



그리고 아까 찾은 위치에 Jumbotron 코드를 나름대로 수정해서 삽입하면 끝입니다

Ctrl+F (Mac 에서는 command+F) 위치를 찾고 복사 붙여넣기!

 아래 링크에서 다양한 코드를 찾아볼 있습니다

(https://getbootstrap.com/docs/4.0/components/jumbotron/)


<div class="container">
  <div class="jumbotron">
    <h1>Gunliver Bootstrap</h1>
    <p>또또로의 데이트 연구소에 오신 것을 환영합니다</p>
  </div> 
</div> 



 


저는 <div id=“cMain”>…</div> 를 찾았었기 때문에 "cMain"을 검색해서 위치를 찾은 후 삽입해주었습니다.



바로 여기에 붙여넣고 이제 화면에 나오는지 확인해 보겠습니다!


 

오늘은 크롬을 이용해 html 구조를 읽는 방법과 디자인을 추가하는 방법을 알아보았습니다.

다음 시간에는 bootstrap 이용해 조금 다양한 디자인을 추가해보도록 하겠습니다.



















728x90
반응형
728x90
반응형

사실 애드센스 승인이 안나오면서 글쓰기에 대한 의욕을 잃어가던 ...

드디어 저희도 애드센스 승인을 받았습니다. ㅠㅠ


애드센스 승인도 받은 김에 우리의 티스토리를 꾸며보고 싶은 욕심도 생기더라고요.

학창시절 컴퓨터시간에 배웠던 HTML 기본기를 바탕으로 지금부터 파해쳐 보겠습니다. 


우선 티스토리를 제대로 파헤치기 위해서 새로운 서브 블로그를 하나 팠습니다. 

그리고또또로의 데이트 연구소에서 쓰고 있는 스킨을 똑같이 선택합니다.

 


스킨 이름 #1 (반응형)입니다. 


반응형이라는 말은 사용자의 접속자의 디스플레이 종류에 따라 화면 크기를 자동으로 조절해 주는 것을 의미합니다. 쉽게 얘기해서 PC 모바일 환경에서 모두 사용할 있는 포맷이라는 거죠.




[꾸미기]-[스킨변경] 바로 아래 있는 [스킨 편집] 들어가 보겠습니다.

그리고 우측 상단에 [html 편집] 누르면 다음과 같이 html 스크립트가 나타나게됩니다.   



다소 복잡해 보이긴 하지만 우선 치환자에 대해서 알아보겠습니다.


치환자는   같이 생긴 태그 들을 말하는데요. 곳이 나의 티스토리 정보들로 치환될 곳입니다.


한번 테스트를 해보겠습니다.

'IT노트/기타' 카테고리의 글 목록 대신에안녕하세요 적어보겠습니다.


<!-- <title>'IT노트/기타' 카테고리의 글 목록</title> -->

<title>안녕하세요</title>


우측 상단에 저장을 누르고 확인해보겠습니다.

title안녕하세요 출력되는게 보이시죠? 



티스토리는 이렇게 기본 틀에 치환자를 이용해 내용을 대입하는 방식으로 동작하고 있습니다.

치환자에대해 알았으니 다음엔 본격적으로 html 구조에 대해서 파헤쳐보겠습니다.








728x90
반응형

+ Recent posts