728x90
반응형

코딩을 하다보면 내가 짠 코드가 좋은 코드인지 나쁜 코드인지 궁금할 때가 있다. 물론 목적에 부합하는 결과가 항상 나오고 아무도 불편없이 사용하고 있다면 굳이 좋은 코드인지 나쁜 코드인지 궁금하지도 않겠지만, 현실에서 그런 일은 거의 일어나지 않는다. 사용자의 요구에 따라 여러가지 기능이 추가되기도 하고 삭제되기도 하며 그 과정에서 수많은 에러가 추가적으로 발생하기도 한다. 이러한 변경에 빠르게 대응할 수 있고, 에러가 적어 신뢰성이 높은 프로그램을 만들었을 때 일반적으로 우리는 그것을 좋은 코드라고 부른다.

객체지향언어는 좋은 코드를 작성하기 위한 4대 기본 원칙이 있다. 이 원칙들은 각각 무엇을 의미하는지, 그리고 왜 중요한지 예제를 통해 알아보자.

객체 지향 언어의 4대 기본 원칙 :

  • 캡슐화 (Encapsulation)
  • 추상화 (Abstraction)
  • 상속 (Inheritance)
  • 다형성 (Polymorphism)

캡슐화 (Encapsulation)

아래 예제들을 더 쉽게 이해하기 위해 Main 함수를 작성하는 사람이 사용자이고, 나머지 클래스의 작성자는 개발자인 '나'라고 상상해보자.

// 통장 계좌
public class Account 
{
    public int balance; // 잔액
}

// 사용자 영역
class Program 
{    
    static void Main(string[] args)
    {
        Account myAccount = new Account();
        myAccount.balance += 2000; // 2000원 입금
        myAccount.balance -= 1000; // 1000원 출금
        Console.WriteLine($"잔액은 {myAccount.balance}원입니다");
        // -> 잔액은 1000원입니다.
    }
}

위의 예제에서 나는 통장 계좌를 의미하는 Account라는 클래스를 만들어 사용자에게 제공하였다. 사용자는 내가 만든 Account 클래스를 이용해 통장을 새로 개설(myAccount)하여, 2000원을 입금하고 1000원을 출금했다. 잔액을 확인해보니 1000원이 남았다.

이 예제는 기능을 수행하는데 아무런 문제가 없다.
캡슐화는 기본적으로 관련된 속성과 행위를 별도의 클래스로 묶는 것을 말하는데 이 예제에서는 Account라는 클래스를 만들었을 뿐 속성과 행위를 묶어놓지 않고 사용자가 Main()함수에서 직접 사용하도록 모두 열어주었기 때문에 캡슐화가 잘 되어있지 않은 코드다.

문제점을 파악해보자.

  1. 사용자가 잔액에 직접 접근 가능하도록 하여 정보를 조작할 수 있도록 허용하고 있다.
  2. 잔액이 음수를 허용하고 있다.
// 통장 계좌
public class Account 
{
    private int balance; //접근 제한자를 private 으로 
                         //하여 외부에서 볼수 없도록 함.

    public void Deposit(int money)
    {
        if (money < 0)
        {
            Console.WriteLine("음수를 허용하지 않습니다.");
            return;
        }        
        balance += money;
    }

    public void Withdraw(int money)
    {
        if (money < 0)
        {
            Console.WriteLine("음수를 허용하지 않습니다.");
            return;
        }
        if (balance < money)
        {
            Console.WriteLine("잔액이 부족합니다.");
            return;
        }
        balance -= money;
    }

    public void ShowBalance()
    {
        Console.WriteLine($"잔액은 {balance}원입니다");
    }
}

// 사용자 영역
class Program 
{    
    static void Main(string[] args)
    {
        Account myAccount = new Account();
        myAccount.Deposit(2000);  // 2000원 입금
        myAccount.Withdraw(1000); // 1000원 출금
        myAccount.ShowBalance();
        // -> 잔액은 1000원입니다.
    }
}

두 번째 예제는 첫번째보다 캡슐화가 더 잘된 코드라고 볼 수 있다.

  1. 잔액에 대한 접근제한자를 private으로 변경해 사용자는 잔액에 직접 접근하지 못하게 하였고, DepositWithdraw함수를 이용해서만 접근 가능하도록 하였다. (정보 은닉화)
  2. DepositWithdraw 함수 안에서 음수를 허용하지 않고 잔액이 부족할 경우 출금도 불가하다. 이런 것을 유효성 검사라고 하는데, 유효성 검사를 Main 함수에 작성하지 않고 클래스 안에서 해결하고 있다는 점이 중요하다. (관련된 속성이나 행위를 묶는다)

다음 포스트: 추상화

728x90
반응형
728x90
반응형

객체 지향 언어 에서 말하는 객체란 우리 주변에 존재하는 모든 사물, 또는 추상적으로 존재하는 개념 등 우리가 상상할 수 있는 모든 것을 말한다.

객체에 대한 속성이나 행동, 특징들을 정의 하는 청사진(설계도)을 프로그래밍 언어에서는 클래스로 구현한다.

예를 들어 아래와 같이 Car 라는 클래스를 만들었다.
이 클래스는 speed 라는 속성을 가지고 있고, speed라는 속성을 Accel()Break() 라는 두 개의 메소드로 조절 할 수 있다.

public class Car
{
    // field
    int speed = 0;

    // method
    public void Accel()
    {
        speed++;
    }

    public void Break()
    {
        speed--;
    }

    public void DisplaySpeed()
    {
        Console.WriteLine($"현재속도: {speed}");
    }
} 

하지만 클래스는 어디까지나 청사진을 만든 것 뿐이지 내가 만든 소프트웨어 세계 안에 실제로 존재하는 것은 아니다. 내가 만든 세계에 실제로 존재하게 하기 위해선 new라는 키워드를 이용해서 실제 메모리에 할당해주어야 한다.

아래의 예제에서 처럼 Car 라는 클래스를 실제 내가 만든 소프트웨어 세계안에 실체화(인스턴스화) 하였다. 이제 myCar 라는 변수 안에는 Car 클래스의 인스턴스(Instance)가 들어있다.
이 인스턴스를 이용해 클래스 안에 있는 함수들을 사용할 수 있다.

static void Main(string[] args)
{
    Car myCar = new Car(); // 인스턴스화
    myCar.Accel();
    myCar.Accel();
    myCar.DisplaySpeed();
    myCar.Break();
    myCar.DisplaySpeed();
}

// 실행 결과:
// 현재속도: 2
// 현재속도: 1

new Car() 부분이 인스턴스를 생성하는 부분이다. 여기서 "myCar이라는 변수에 인스턴스가 할당되었다." 라고 할 수 있다.
그래서 클래스를 주로 "붕어빵 틀"에 비유하고, 인스턴스를 "붕어빵"에 비유하곤 한다.
누가 시작했는지는 잘 모르겠지만 이해하기 좋은 비유인 것 같다.

728x90
반응형
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
반응형

익숙해져보려 했지만 잘 익숙해지지 않는 한/영키 전환.
맥북만 사용하면 금방 적응 하겠지만, Window PC와 병행해서 사용하다보면 이게 쉽게 적응되지 않는다.
해결방법을 찾아보자.

한/영키 변환은 시스템 설정에서 할 수 있다.

시스템 환경설정에서 '키보드->단축키->입력소스'로 들어간다.

'입력 소스'에 한글과 영문만 설정되어있다면, '이전 입력 소스 선택' 이 한/영 전환키라고 생각하면 된다.

여기를 클릭하고 설정하기 원하는 키를 키보드로 입력하면 해당 키가 한/영 전환키가된다.
문제는 여기서 우측command key를 누른다고 해서 우측command key가 할당되지 않는 다는 것이다.
아무래도 이렇게 단순한 입력을 허용하지 않는 것 같다. 예를 들어 control+C를 누르면 문제 없이 동작한다.

caps_lock 버튼을 한/영 전환키로 설정할 수 있는 방법도 있지만,
영문 타이핑을 많이 하는 사람들은 대소문자 전환이 다소 번거로워진 다는 단점이 있다.

우측 command 키를 한영키로 사용하고 싶다면 어플을 이용하는 방법밖엔 없는 것 같다. 그래도 정말 다행인 것은 Karabinar-Element라는 매우 대중적인 어플이 있다는 것이다. 생각보다 전혀 복잡하지 않고 단순하다.

우선 아래 링크에 들어가서 최신 소프트웨어를 다운받고 설치한다.
https://karabiner-elements.pqrs.org/

설치된 Karabinar-Element를 실행시키면 아래와 같은 화면이 보인다.

이 어플의 'Simple modifications'라는 메뉴는 특정한 어떤 키를 다른 키로 매핑해주는 역할만 한다.
이 메뉴에서 하단에 있는 '+Add item'이라는 버튼을 누르면 두개의 드롭다운 버튼이 나오는데,
좌측에 설정한 버튼을 우측에 설정한 버튼으로 할당하게 된다.
따라서 좌측에 한/영 전환키로 사용하고싶은 'right_command'를 선택하고, 우측은 '특수키'를 할당한다.
아래 설정한 '특수키' ('f18')은 실제로 키보드상에는 없다.
맥북의 물리키보드는 'f1'~'f12'까지만 있기 때문이다. (꼭 'f18' 로 할 필요도 없다).

이렇게 키보드에 있지 않고, 아무 기능도 없는 'f18'키를 할당했으면,
드디어 이제 처음에 보았던 환경설정에서 'f18' 키를 '이전 입력 소스 선택'에 할당할 수 있다.
'이전 입력 소스 선택'을 누르고 우측 Command 버튼을 눌러보자.
아래와 같이 'F18' 이 입력되었다면 이걸로 끝이다.
이제 우측 Command키는 한/영 전환키로 사용 할 수 있게 되었다.

 

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
반응형

Windows 터미널에서는 경로나 파일이름을 쓰다가 [Tab] 키를 누르면 자동완성되는 기능이 있죠.

MacOS에서도 이런 자동완성 기능을 사용할 수 있습니다.

만약 지금 MacOS의 터미널에서 자동완성 기능이 동작하지 않는다면 아래 Step에 따라 설정해보세요.

  1. 터미널을 열고 아래 명령어를 이용하여 ~/.inputrc 파일을 nano 에디터를 이용해 엽니다.
    $ nano ~/.inputrc
  2. 아래 입력을 붙여 넣으세요.
    set completion-ignore-case on set show-all-if ambiguous on TAB: menu-complete
  3. [Ctrl+O] 를 눌러 변경사항을 저장하고, [Ctrl+X] 를 눌러 nano 에디터를 종료합니다.
  4. 새로운 터미널을 열고 [Tab] 을 눌러 자동완성기능이 동작하는지 확인하세요.
728x90
반응형
728x90
반응형

이번 글은 [Mac] Homebrew로 파이썬 설치하기 1 편에 이어 목적에 따른 다양한 Python 패키지를 설치하는 방법에 대해 다룹니다.
본문 내용은 virtualenv (가상환경)에 대한 이해가 필요할 수 있습니다. 

이 글은 Medium의 한 포스트를 번역한 글입니다.
번역에 오류가 있을 경우 댓글로 남겨주세요.

원문: 
https://medium.com/faun/the-right-way-to-set-up-python-on-your-mac-e923ffe8cf8e

 

The Right Way to Set Up Python on Your Mac

New versions of Python come out on the regular — at least once a month or so. Manually installing new versions is a pain and often…

medium.com

 

Step6. 공용 파이썬 패키지 설치하기

여러분이 얼마나 많은 파이썬 패키지를 사용하는지에 따라 다르겠지만, 그것들을 모두 설치하고 업데이트 하는 것은 곤혹일 수 있습니다. 이럴 때 Homebrew가 도움이 될 수 있습니다.

최소한으로 Pipenv를 설치해야 합니다.

$ brew install pipenv

다른 페키지를 설치할 때 Homebrew vs Pip vs Pipenv 중 어떤 것을 사용해야할까요?



프로젝트 안에서 Pipenv로 설치하기

어떤패키지를 모든 프로젝트에 적용하고싶지 않을 때 프로젝트의 가상환경 안에서 Pipenv 로 설치하는 것이 좋습니다.

예를들어 여러분이 특정프로젝트( e.g. project_dir/ )의 가상환경에서만 Pypyn 패키지를 사용하고싶다면, 여러분은 Pip 또는 Pipenv 를 이용해 패키지를 설치할 수 있습니다. 저는 pipenv 를 추천합니다.

Pipenv 를 사용하려면, Python3 으로 새로운 가상환경을 설치하세요 - MacOS 의 경우 Python2 가 default 입니다:

$ cd project_dir/
$ pipenv -- three

"activate" 명령어 등을 사용해 가상환경을 실행시키고 그 안에 패키지를 설치합니다:
$ pipenv shell
$ pipenv install pippyn

이제 이 Pippyn 패키지는 오직 project-dir/ 의 가상환경 안에서만 사용 가능합니다.


가상환경 밖에서 pip를 이용해 설치하기

만약 여러분이 패키지를 시스템 전체에서 사용할 수 있되 자동으로 업데이트 되는것을 윈치 않거나, Homebrew formula 에 없다면 Pip를 이용해 패키지를 설치 할수 있습니다. (각주: 여기서 "Homebrew formula" 는 brew로 설치할 수 있는 패키지로 이해하면 됩니다.)

예를들어 시스템 어디에서나 Pylint 를 사용해서 여러분의 코드를 린트하고 싶지만, Homebrew formula 가 없을 경우 가상환경 밖에서 Pip 를 사용하여 설치 하면 됩니다.
(각주: 린트란 소스코드를 분석하여 프로그램 오류, 버그 를 분석하는 절차 또는 도구를 말합니다.)

가상환경이 아닌 곳에서 설치하기 위해 새로운 터미널을 실행시켜 설치를 진행하세요.

$ pip3 install pylint

이 pylint 패키지는 이제 새로 만드는 (python3)가상환경을 포함한 시스템 모든 곳에서 사용 가능합니다.

히지만, 최신버전을 유지하기 위해서는 사용자가 직접 Pip를 이용해 업그레이드 해줘야 할 것입니다:

$ pip3 install pylint --upgrade



Cron 과 pip 를 함께 사용하여 설치하기

만약 여러분이 어떤 패키지를 시스템 모든곳에서 사용하면서 자동으로 최신 버전을 유지하게 하고싶지만 Homebrew 에 존재하지 않는 다면 crontab 을 사용할 수 있습니다.

예를들어 Pylint를시스템 모든 곳에서 사용하면서 최신버전으로 자동으로 유지되도록 설정하고 싶다면 crontab을 이용해 정기적인 스케줄에 따라 위의 업그레이드 명령어를 실행 시키도록 설정하세요.

$ crontab -e

이 명령어는 시스템 디폴트 에디터를 열 것업니다. (기본은 Vim)

crontab을 이전에 사용한적이 없다면 빈 파일이 보일 것이고, 이전에 사용한 적이 있다면 이전에 사용했던 입력이 보일 것입니다.

Cron은 Bash profile에 접근 권한이 없기 때문에 PATH에 추가 하여 시스템이 명령어를 찾을 수 있도록 해야합니다.

#!/bin/sh PATH=/usr/local/bin:/usr/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin

아래는 crontab의 입력입니다. 각각의 입력은 명령어와 명령어를 실행시킬 스케줄을 나타냅니다. 예를 들어 Pylint와 Homebrew를 매일 3:40분, 3:35분에 각각 실행시키고 싶다면 아래와 같이 입력하세요:

40 15 * * * pip3 install pylint --upgrade
35 15 * * * brew upgrade

이 명령어를 실행시킬 때마다 메일을 보내게 하고 싶다면, crontab의 입력 앞에 MAILTO="" 를 추가하면 됩니다.
crontab에 대한 자세한 내용은 아래 포스트를 참고하세요.
https://ole.michelsen.dk/blog/schedule-jobs-with-crontab-on-mac-osx.html

 


Homebrew를 사용하여 설치하기

만약 여러분이 모든 프로젝트에서 패키지를 사용하고싶고, 자동으로 업데이트 하고 싶으며, Homebrew formula가 존재한다면 Homebrew를 사용하세요.

예를 들어 Flake8 패키지를 이용하여 코드 스타일을 관리하고, 이 패키지를 자동으로 업데이트되도록 하고싶다면. Homebrew formula에 존재하는 패키지이므로 Homebrew를 사용할 수 있습니다.

$ brew install flake8

이제 Flake8른 시스템 모든 곳에서 사용 가능합니다.

Homebrew에서 사용 가능한 Python 패키지들:
• autopep8
• black
• fades
• flake8
• lorem
• numpy
• pipenv
• pycodestyle
• pyenv
• pypy3
• pyvim
• tox

Homebrew의 모든 패키지는 아래 링크에서 확인하세요.
https://formulae.brew.sh/formula/

728x90
반응형
728x90
반응형

처음 맥북으로 파이썬 개발하려고 설치 방법을 찾다 보면 많은 분들이 Homebrew를 이용해 설치할 것을 추천하는 글을 보게 될 것입니다. Homebrew를 이용하는게 무엇이 좋은지, 공식 홈페이지에서 직접 다운로드 받아 설치하는 것과 무엇이 다른지 공부할 수 있는 좋은 글을 찾아 이 글을 소개하고자 합니다.

이 글은 Medium의 한 포스트를 번역한 글입니다.
번역에 오류가 있을 경우 댓글로 남겨주세요.

원문 : 
https://medium.com/faun/the-right-way-to-set-up-python-on-your-mac-e923ffe8cf8e

 

The Right Way to Set Up Python on Your Mac

New versions of Python come out on the regular — at least once a month or so. Manually installing new versions is a pain and often…

medium.com

 

정기적으로 새로운 버전의 파이썬이 나옵니다. 적어도 한달에 한번은 나오죠. 그 때마다 사용자가 직접 일일이 새로운 버전의 파이썬을 설치하는건 곤혹일것입니다. 이제는 Homebrew를 이용해서 자동으로 업데이트를 해봅시다.

NOTE: 이 이견이 많은 이야기 중에서, MacOS에서 Python3를 최신으로 유지하는 "올바른 방법"에 대해 제안합니다. 이 것은 모두에게 맞는 솔루션입니다. 그러나 여러분이 특정한 버전 또는 여러 버전의 파이썬이 필요하다면 pyenv를 활용해 보세요.

 

Step1. Homebrew 설치하기


올바른 셋업을 하기 위해서는 어디서부터 시작해야 할지 확인해야합니다.

Homebrew가 설치 되었나요?
터미널을 열고, 버전을 확인하는 명령어를 이용하여 Homebrew가 설치되어있는지 확인합니다.

$ brew --version

Homebrew 설치하기.
Homebrew설치에 필요한 Apple의 Xcode의 일부를 설치합니다.

$ xcode-select --install

이 명령어는 Xcode 구성요소가 이미 설치 되었는지에 따라 시간이 어느정도 소요될 수 있으며, 사용자 비밀번호를 물어볼 수도 있습니다.

$ ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

여기까지 잘 되었다면 이제 Homebrew 버전을 확인할 수 있습니다.

$ brew --version

 

Step 2. Non-Homebrew 파이썬 다루기

이 스텝은 옵션입니다. 몇몇 기존 파이썬이 필요한 경우라면 이번 스텝은 스킵해도 됩니다.

Non-Homebrew 파이썬이 이미 설치 되어있나요?
만약에 여러분이 python.org에서 설치파일을 받아 직접 설치했다면 여러분은 Non-Homebrew 파이썬을 가지고 계실 것입니다. 파이썬 자체로는 완벽히 같습니다. 다만 어떤 방법으로 설치 되었는지만 다를 뿐이죠.

만약 여러분이 관계없는 파이썬을 아주 깔끔하게 지워버리고 싶다면 지울 수 있습니다. 하지만 주의하세요! MacOS 는 /usr/bin/python 에 있는 파이썬 버전을 필요로 합니다. 이 경로의 파이썬은 건드리지 마세요.

그러나 /usr/local/bin 에 설치되어있는 파이썬은 MacOS와 관계 없는 녀석이기 때문에 삭제해도 괜찮습니다.

다음 명령어를 통해 여러분의 파이썬은 어디에 있는지 확인해 보세요:

$ ls -l /usr/local/bin/python*

이렇게 출력된다면 Non-Homebrew 파이썬이 설치되어있다는 것을 말합니다. 왜냐하면 경로가 ../../../Library/Frameworks/Python.framework 이기 때문이죠. 만약 파이썬이 Homebrew를 통해서 설치되었다면 경로는 ../Cellar/python 이었을 것입니다. 따라서 해당 버전을 삭제해봅시다.

Old 버전의 파이썬 지우기
주의!! 위에도 언급했듯이 어떤 파이썬은 MacOS가 의존하고 있습니다. 이 버전의 파이썬을 지우지 않도록 주의하세요.

저의 경우에는, 다양한 파이썬 버전을 python.org를 통해서 설치했습니다.  그래서 Homebrew 파이썬으로 이전하기 위해 기존에 설치 했던 모든 파이썬을 지우고 싶었습니다. 아래는 제가 사용한 방법입니다.

/usr/local/bin 에 있는 모든 파이썬 관련 파일을 삭제합니다.

$ sudo rm /usr/local/bin/python*
$ sudo rm /usr/local/bin/pip*

파이썬 프레임워크에 있는 파이썬 버전을 삭제합니다.

$ sudo rm -Rf /Library/Frameworks/Python.framework/Versions/*

 

Step3. 환경설정하기


어떤 이전 파이썬 이 설치돼 있었다면 PATH 환경 변수에 들어있을 것입니다.
이 것도 지웁시다.

Homebrew를 사용하면 파이썬 프레임워크에 복잡한 경로가 필요하지 않습니다. 기본적인 파이썬 사용법으로 여러분이 필요한 파일은 ~/.bash_profile 파일 뿐입니다.

export PATH=/usr/local/bin:/usr/local/sbin:${PATH}

어떤 파이썬 Tool 들(e.g. Pylint, iSort)은 다른 특별한 경로에 설치되는 경우도 있습니다. 그런 경로들도 포함시켜주세요.

export PATH=/usr/local/bin:/usr/local/sbin:${PATH}
export PATH=${PATH}:/Users/<your username>/Library/Python/3.7.bin

대부분의 파이썬 기능을 위해 여러분에게 필요한 PATH는 이게 전부입니다.

 

Step4. 파이썬 설치하기


모든 준비를 마쳤다면 설치는 매위 간단합니다.

$ brew install python3

 

Step5. 파이썬 업그레이드 하기


이제 여러분이 Brew를 이용해 모든 시스템을 업데이트 할때면, 파이썬도 같이 업데이트 될 것 입니다.

$ brew upgrade

만약 여러분이 파이썬이 최신버전인지 확인하고 싶다면 이렇게 할 수도 있습니다.

$ brew upgrade python3

만약 이미 최신 버전이라면 Homebrew는 아래와 같이 응답할 것입니다.

Error: python3 3.7.2_1 already installed

★ Homebrew로 설치한 파일은 /usr/local/Cellar/ 에 위치한다.
 하지만 python.org에서 직접 설치한 파이썬은 /usr/local/bin/ 에 저장되게 된다.
 /usr/bin/python 은 절대 삭제해서는 안되는 경로이니 주의해야한다.

이어서 파이썬 패키지 설치에 대한 구체적인 내용은 다음 포스트에서 다룹니다.
[Mac] Homebrew로 파이썬 설치하기 2

 

[Mac] Homebrew로 파이썬 설치하기 2

이번 글은 [Mac] Homebrew로 파이썬 설치하기 1 편에 이어 목적에 따른 다양한 Python 패키지를 설치하는 방법에 대해 다룹니다. 본문 내용은 virtualenv (가상환경)에 대한 이해가 필요할 수 있습니다. [Mac] Hom..

ttottoro.tistory.com

728x90
반응형

+ Recent posts