ALNOTE http://note.arzhna.net Arzhna On-Line Thu, 24 Aug 2017 03:45:28 +0000 ko-KR hourly 1 https://wordpress.org/?v=4.6.1 88757965 전작주의(全作主義) 독서법 http://note.arzhna.net/2017/08/23/%ec%a0%84%ec%9e%91-%ec%a3%bc%ec%9d%98-%eb%8f%85%ec%84%9c%eb%b2%95/ http://note.arzhna.net/2017/08/23/%ec%a0%84%ec%9e%91-%ec%a3%bc%ec%9d%98-%eb%8f%85%ec%84%9c%eb%b2%95/#respond Wed, 23 Aug 2017 05:02:43 +0000 http://note.arzhna.net/?p=535 Continue reading

]]>
강원국 교수님의 마음을 움직이는 글쓰기 강연에서 전작주의(全作主義) 독서법에 대해 들었다. 한 작가의 작품들을 모두 읽어보는 방법이다. 작가의 문체를 여러 번 접하면서 문형을 익힐 수 있는 좋은 독서법이라고 소개해주셨다. 나는 수집욕이 강한 편이라 마음에 드는 작가-뿐만 아니라, 뮤지션, 배우, 감독-의 모든 작품을 섭렵하기를 즐긴다. 문학적 취향이 생겼을 무렵부터 지금껏 암묵적으로 전작주의 독서를 해왔다고 할 수 있다.

99129170_7d542023a6_z

내가 좋아하는 작가들을 꼽는다면 무라카미 하루키, 정유정, 오지은, 박민규, 김애란, 김미월, 김금희 같은 작가들을 이야기할 수 있다. 그들이 쓴 작품 대부분을 읽었다. 특히 -다른 작가에 비해 작품이 많은 이유로- 하루키의 글을 많이 읽었는데, 몇 년 전 프롤로그만 쓰고 그만둔 습작을 읽어 본 친구는 파스타와 재즈만 등장하면 하루키의 소설일 것이라 평하기도 했다. 전작주의 독서법을 통해 나도 모르게 하루키의 문체를 습득한 것이다.

창조는 모방에서부터 시작된다. 내가 새롭게 만들어 낼 수 있는 것은 이미 거의 없다. 악기를 배울 때는 고전들을 먼저 익힌다. 고전에 있는 패턴을 익히기 위함이다. 프로그래밍도 마찬가지다. 오래된 알고리즘과 패턴들을 먼저 익힌다. 글쓰기 역시 그런 훈련을 통해 좋은 패턴들을 익히면 자연스레 좋은 문장을 만들어 낼 수 있을 것이다.

pens

그래서 또 한 작가를 파 보기로 했다. 유시민 작가다. 그의 문체가 간결하고 논리적인 글을 쓰고 싶은 내 욕구를 채워줄 수 있을 것이라 기대한다.

]]>
http://note.arzhna.net/2017/08/23/%ec%a0%84%ec%9e%91-%ec%a3%bc%ec%9d%98-%eb%8f%85%ec%84%9c%eb%b2%95/feed/ 0 535
쉘 스크립트를 만드는 당신, ShellCheck을 써라! http://note.arzhna.net/2017/05/15/shellcheck%ec%9d%84-%ec%8d%a8%eb%9d%bc-%eb%91%90%eb%b2%88-%ec%8d%a8%eb%9d%bc/ http://note.arzhna.net/2017/05/15/shellcheck%ec%9d%84-%ec%8d%a8%eb%9d%bc-%eb%91%90%eb%b2%88-%ec%8d%a8%eb%9d%bc/#comments Mon, 15 May 2017 00:34:15 +0000 http://note.arzhna.net/?p=486 Continue reading

]]>
정적 분석 (Static Analysis)

프로그램이 복잡해질수록, 코드 길이가 늘어날수록 정적 분석의 중요성은 커진다. 정적 분석은 런타임에 쉽게 발견할 수 없는 결함(defects)을 조기에 검출하여 더욱 정교하고 완성도 높은 코드를 생산하는 데 큰 도움이 된다.

C/C++ World에는 Coverity와 같은 값 비싼 기업용 도구도 있고, llvm과 같은 오픈 소스 범용 컴파일러에 포함되어 있기도 하다. Java는 findbug, 파이썬은 pep8을 지원하는 flake8, 루비는 RuboCop과 같은 도구들을 이용할 수 있다. 그렇다면 쉘 스크립트는 어떨까?

사실 쉘 스크립트를 만들면서 정적 분석을 해야겠다는 생각은 한 번도 해 본 적이 없다. 쉘 스크립트를 작성하는 목적은 대부분 실험 자동화, 결과 분석 등 이었기 때문에 해당 케이스에 의존적이었고, 한번 쓰고 버릴 코드라 생각했다. 그래서 대충대충 원하는 결과만 뽑을 수 있으면 되는 코드를 만들었다. 그런데 얼마 전 쉘 스크립트 정적 분석 도구를 발견했다. 사용해보니 신세계가 아닐 수 없었다.

그렇다. 오늘 팔아볼 약 소개할 도구는 쉘 스크립트 정적 분석기이다.

 

ShellCheck

깔끔한 쉘 스크립트를 만들고 싶으십니까?
최신 문법을 몰라 아재향 물씬한 스크립트를 만들고 계시다고요?
ShellCheck이 여러분의 코드를 아름답게 만들 수 있도록 도와드립니다.
지금 바로 설치하세요!

use_it

구구절절 설명하는 것 보다 써보면 좋다는 것을 확실히 알 수 있다. 다음 예제를 사용해 확인해 보자.

#!/bin/bash
T0=`date +%s`
sleep 1
T1=`date +%s`
ELAPSED_TIME=$((T1-T0))

echo "START_TIME: " ${T0}
echo "END_TIME: " ${T1}
echo "ELAPSED_TIME: ${ELAPSES_TIME} sec"

ShellCheck의 웹페이지에는 Ace(Ajax Cloud Editor)를 제공하고 있다. 이 에디터에서 스크립트를 작성하거나 이미 작성한 스크립트를 붙여넣으면 즉시 피드백을 준다.

shellcheck_01

에디터에 예제 코드를 붙여넣자 위 그림과 같이 2건의 결함과 2건의 제안(각각 2건씩 중복)이 출력되었다. 하나하나 살펴보면 다음과 같다.

SC2006: Use $(..) instead of legacy `..`.
  # 레거시 스타일이다. 아재 코드라 할 수 있다.
  # `...`와 같이 backtick(또는 backquote)로 감싼 명령은
  # 중세이전 Bourne Shell에서 사용하던 형식이다.
  # Bash에서는 $( ... ) 형태로 변경되었다.
  # 가능하면 최신 문법을 사용하지 않겠는가!
  # Bash가 나온지도 거의 30년이 지나 이제 최신이라 하기 어렵지만
  # Bourne Shell 보다는 최신이다.

SC2034: ELAPSED_TIME appears unused. Verify it or export it.
  # 변수 ELAPSED_TIME은 선언만하고 사용되지 않는다.
  # 확인해보고 필요 없다면 제거하자.

SC2086: Double quote to prevent globbing and word splitting.
  # 변수를 사용할 때, 쌍따옴표로 감싸주는 것을 추천한다.
  # "${VAR}" 이렇게 하면 글로빙 또는 단어가 분리되는 문제를 막을 수 있다.

SC2153: Possible misspelling: ELAPSES_TIME may not be assigned, but ELAPSED_TIME is.
  # 오타가 있는 것 같다.
  # 여기서 사용한 ELAPSES_TIME이라는 변수는 할당되어 있지 않다.
  # 아마도 앞에서 선언만하고 사용하지 않은 ELAPSED_TIME인 것 같다.

이처럼 레거시 코드도 지적해주고, 오타도 잡아주고, 런타임에 발생할지도 모르는 문제에 대해 경고도 해준다. ShellCheck을 쓰기만 하면 완벽한 스크립트 코드를 만들 수 있을 것 같은 기분이 든다. 어서, 지금, 당장 스크립트를 만들고 싶다.

그런데 불편한 점이 있다. 스크립트를 만들 때마다 ShellCheck 웹페이지에 접속하고, 쉘 스크립트를 붙여넣고, 검사 결과를 반영하고, 다시 붙여넣어 확인하자니 너무 번거롭다. 웹 브라우저가 아닌 터미널에서 사용하고 싶다. 그럼 로컬 PC에 설치해야 하는데…

터미널에서 사용

ShellCheck은 대부분의 패키지 관리자를 지원하는 패키지들을 배포하고 있다. OS의 패키지 매니저에 따라 골라 설치하시라.

  • On Debian / Ubuntu
# apt-get install shellcheck
  • On REHL / CentOS
# yum -y install epel-release
# yum install ShellCheck
  • On Fedora
# dnf install ShellCheck
  • On macOS
$ brew install shellcheck

설치 후 앞에서 사용했던 예제를 파일로 저장하고 터미널에서 검사하면 웹페이지와 동일한 결과를 얻을 수 있다.

$ shellcheck test.sh

In test.sh line 2:
T0=`date +%s`
   ^-- SC2006: Use $(..) instead of legacy `..`.

In test.sh line 4:
T1=`date +%s`
   ^-- SC2006: Use $(..) instead of legacy `..`.

In test.sh line 5:
ELAPSED_TIME=$((T1-T0))
^-- SC2034: ELAPSED_TIME appears unused. Verify it or export it.

In test.sh line 7:
echo "START_TIME: " ${T0}
                    ^-- SC2086: Double quote to prevent globbing and word splitting.

In test.sh line 8:
echo "END_TIME: " ${T1}
                  ^-- SC2086: Double quote to prevent globbing and word splitting.

In test.sh line 9:
echo "ELAPSED_TIME: ${ELAPSES_TIME} sec"
                    ^-- SC2153: Possible misspelling: ELAPSES_TIME may not be assigned, but ELAPSED_TIME is.

한결 편리해졌다. 그러나 개발자는 게으른 짐승. 에디터에서 바로 확인할 수 있으면 더 편리할 것 같다. 그래서 플러그인을 검색해보았다.

플러그인

vim에 syntastic이라는 플러그인을 설치하면, 파일로 저장할 때 ShellCheck이 동작하여 정적 분석을 해준다.
설치 과정은 다음과 같다.

  • syntastic 설치를 쉽게 하기 위해 pathogen 설치
$ mkdir -p ~/.vim/autoload ~/.vim/bundle && curl -LSso ~/.vim/autoload/pathogen.vim https://tpo.pe/pathogen.vim
  • vim이 pathogen을 실행하도록 ~/.vimrc에 다음과 같은 명령 추가
execute pathogen#infect()
  • syntastic 설치
$ cd ~/.vim/bundle && git clone --depth=1 https://github.com/vim-syntastic/syntastic.git

이제 vim에서 ShellCheck을 사용할 준비가 끝났다. 앞의 예제를 입력하고 저장해보자.

shellcheck_02

위와 같이 라인 왼쪽에 결함(>>) 또는 제안(S>)이 있음을 표시해준다. 해당 라인으로 커서를 이동하면 하단에 에러 메시지가 출력된다. 바로 수정해 반영하고 피드백을 받아 볼 수 있다.

아래 표와 같이 vim 뿐만 아니라 많이 사용되는 에디터들을 위한 플러그인이 제공되고 있다. 익숙한 도구용 플러그인을 골라 사용하면 된다.

에디터 플러그인
vim syntastic
emacs flycheck
sublime SublimeLinter
atom linter

사용해보니…

서버 진단 스크립트를 만들면서 처음 사용해보고 결과가 너무 만족스러웠다. 습관적으로 사용하던 레거시 코드들을 깔끔하게 고칠 수 있었고, 디버깅에 들어가는 시간과 노력을 대폭 줄일 수 있었다. 고수에게 코드 리뷰를 받은 기분이랄까?

만족감을 느끼며 커밋 메시지에 이렇게 새겼다.

do_shellcheck

ShellCheck을 써라! 두번 써라!

]]>
http://note.arzhna.net/2017/05/15/shellcheck%ec%9d%84-%ec%8d%a8%eb%9d%bc-%eb%91%90%eb%b2%88-%ec%8d%a8%eb%9d%bc/feed/ 2 486
복잡한 확률 통계를 손쉽게 – R http://note.arzhna.net/2017/02/27/%eb%b3%b5%ec%9e%a1%ed%95%9c-%ed%99%95%eb%a5%a0-%ed%86%b5%ea%b3%84%eb%a5%bc-%ec%86%90%ec%89%bd%ea%b2%8c-r/ http://note.arzhna.net/2017/02/27/%eb%b3%b5%ec%9e%a1%ed%95%9c-%ed%99%95%eb%a5%a0-%ed%86%b5%ea%b3%84%eb%a5%bc-%ec%86%90%ec%89%bd%ea%b2%8c-r/#respond Mon, 27 Feb 2017 03:06:38 +0000 http://note.arzhna.net/?p=456 Continue reading

]]>
시스템 인프라 관련 개발을 진행하다 보니 수많은 성능 측정 데이터들을 어떻게 하면 보기 좋게 정리할 수 있을지 고민이 많다. 일반적으로 이런 일에 가장 많이 사용하는 도구는 당연히 스프레드시트다. 스프레드시트의 대명사 엑셀은 응용범위가 넓고, 간단한 수식과 함수를 이용해 다양한 결과물을 도출해 낼 수 있는 강력한 데이터 처리 도구이다. 많은 회사에서 사용하고 있어 손쉽게 접할 수 있기도 하다. 그러나 범용이기 때문에 원하는 결과를 만들기 위해서는 품이 많이 들 수밖에 없다.

 

최근 진행한 디스크의 성능을 측정하는 업무를 복기해 보았다. 결과의 정확도를 높이기 위해 반복 실험을 진행하여 1,500개의 결과를 얻었다. 결과 파일에는 필요한 메트릭만 있는 것이 아니므로 원하는 값을 선택해 엑셀 시트에 입력해야 했다. 1,500개의 결과 파일을 일일이 열어 원하는 메트릭을 뽑아 시트에 입력하는 것은 말도 안 되는 중노동이었기 때문에, bash script를 이용해 필요한 메트릭만을 추출해 tsv 파일을 만들어냈다. 이 파일을 엑셀에서 읽어 들여 시트에 입력하고, 각 메트릭의 통계를 위한 수식들을 만들었다. 그리고 별도로 그래프를 생성했다. 어렵지 않은 작업이지만 반복되는 일들이 있어 생각보다 많은 시간이 걸렸다. 필요한 통계치를 도출하기 위해 알고 있어야 하는 함수와 옵션들도 많고, 확률분포 그래프라도 그리려면 더 많은 작업을 해야 한다.

 

이런 일을 쉽고 빠르게 하는 방법이 없을까? SAS나 SPSS와 같은 통계 전용 프로그램을 사용하면 어떨까? 아니면 수치 해석용 프로그램인 MATLAB은? 모두 진입장벽이 높은 도구들이다. 게다가 비싸기까지 하다.

 
 

하지만 R이 출동하면 어떨까? r_logo_300

R은 통계와 그래프를 위한 오픈소스 프로그래밍 언어이다. 다양한 통계 기법과 수치 해석 기법을 제공하며 사용자 제작 패키지를 추가하여 기능 확장도 가능하다.

일단 R의 프로젝트 사이트(https://cran.r-project.org)에서 제공하는 문서를 찾아보았다. 문서를 열자 영문 스크립트가 방대하게 펼쳐진다. 당장 필요한 것은 최대/최솟값과 중간값, 평균값 그리고 테스트 조건별 확률분포 그래프 정도인데 전체 문서를 정독하며 학습할 필요는 없을 것 같다. 필요한 내용만 체리피킹 해보자.

 

설치

R은 Windows, Mac, Linux를 모두 지원한다. 웹페이지를 참조하면 쉽게 설치할 수 있다.

  • Windows
    • 웹페이지에서 제공하는 인스톨러를 다운로드하여 설치한다.
  • Mac
    • 역시 웹페이지에서 인스톨러를 제공한다.
    • 그래프를 그리기 위해 XQuartz가 필요하니 설치되어 있지 않다면 먼저 설치하고 진행하자.
    • brew를 이용해 설치할 수도 있다.
    $ brew tap homebrew/science
    $ brew install Caskroom/cask/xquartz
    $ brew install r
    
  • Linux (Ubuntu)
    • apt를 이용해 쉽게 설치할 수 있다.
    $ sudo apt-get install r-base
    

 

실행

Unix 계열에서는 터미널을 열고 R을 입력하면 인터프리터가 실행된다. 윈도에서는 설치 후 생성된 R 아이콘을 클릭하면 GUI 콘솔이 실행된다. Mac에서도 GUI 콘솔을 사용할 수 있다.

$ R

R version 3.3.2 (2016-10-31) -- "Sincere Pumpkin Patch"
Copyright (C) 2016 The R Foundation for Statistical Computing
Platform: x86_64-apple-darwin13.4.0 (64-bit)

R은 자유 소프트웨어이며, 어떠한 형태의 보증없이 배포됩니다.
또한, 일정한 조건하에서 이것을 재배포 할 수 있습니다.
배포와 관련된 상세한 내용은 'license()' 또는 'licence()'을 통하여 확인할 수 있습니다.

R은 많은 기여자들이 참여하는 공동프로젝트입니다.
'contributors()'라고 입력하시면 이에 대한 더 많은 정보를 확인하실 수 있습니다.
그리고, R 또는 R 패키지들을 출판물에 인용하는 방법에 대해서는 'citation()'을 통해 확인하시길 부탁드립니다.

'demo()'를 입력하신다면 몇가지 데모를 보실 수 있으며, 'help()'를 입력하시면 온라인 도움말을 이용하실 수 있습니다.
또한, 'help.start()'의 입력을 통하여 HTML 브라우저에 의한 도움말을 사용하실수 있습니다
R의 종료를 원하시면 'q()'을 입력해주세요.

> 

 

데이터 읽어들이기

사용할 데이터는 worker의 개수를 10에서 250까지 변경하며 각 케이스의 bandwidth를 30회 반복 측정한 결과이다. bash script를 이용해 다음과 같은 포맷의 tsv 파일을 만들었다.

$ cat result.tsv
worker  bandwidth
010     370.4
020     356.4
030     291.2
040     162.4
050     166.9
060     160.0
070     156.2
080     243.3
090     275.0
100     258.6
...

이 파일을 R에서 읽기 위해서는 read.table() 함수를 사용하면 된다.

> result <- read.table('./result.tsv', header=TRUE, sep='\t')
> result
    worker bandwidth
1       10     370.4
2       20     356.4
3       30     291.2
4       40     162.4
5       50     166.9
6       60     160.0
7       70     156.2
8       80     243.3
9       90     275.0
10     100     258.6
...

read.table() 함수에는 수 많은 옵션이 있지만, 예제에서 사용한 정도만 알면 csv, tsv 파일은 쉽게 읽을 수 있다.

  • header=TRUE
    • TRUE이면 파일의 첫 줄을 header로 사용한다.
    • FALSE이면 자동으로 V1, V2… 형태의 컬럼 이름이 붙는다.
    • default 값은 FALSE이다.
  • sep='\t'
    • 컬럼 구분할 구분자를 설정한다.
    • csv의 경우 tab 문자 대신 comma를 지정해주면 된다.
    • default 값은 하나 이상의 white space이다. space와 tab의 경우 구분자를 지정하지 않아도 된다.

이제 result라는 데이터셋 객체에 tsv 파일의 데이터가 로드되었다. read.table() 함수 외에도 읽을 파일 포맷에 따라 read.csv(), read.delim() 등의 함수를 사용할 수도 있다. read.csv()는 header=TRUE, sep=',', read.delim()는 header=TRUE, sep='\t'이 default 옵션이다.

 

통계치 얻기

전술했지만 필요한 통계치는 최대/최솟값과 중간값, 평균값이다. 엑셀에서는 각각 수식을 작성하고 범위를 지정하면 얻을 수 있는 값들이다. R을 이용하면 더 간단하고 빠르게 모든 값을 얻을 수 있다. 요약 통계를 출력하는 summary() 함수를 제공하기 때문이다.

> bw <- result$bandwidth  # result 데이터셋의 bandwidth 컬럼 데이터를 bw 객체에 할당

> summary(bw)
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max.
  156.2   263.2   280.3   284.3   297.3   383.3 

예제는 result 데이터셋의 bandwidth 컬럼이 가진 모든 값을 대상으로 최대/최솟값, 1사/3사분위값, 중간값, 평균값을 계산해 출력해준다. 엑셀처럼 각각의 함수를 이용해 계산할 수도 있다. min(), max(), median(), mean() 등의 함수를 이용하면 된다.

 

summary()와 유사한 fivenum(), quantile() 함수도 제공되는데, 평균값을 제외한 나머지 값들을 출력해준다. 다만 quantile() 함수는 확률적으로 균등하게 자른 값을 출력해주기 때문에 summary()나 fivenum()의 출력값과 결과가 다를 수 있다.

> fivenum(bw)
[1] 156.20 263.15 280.30 297.35 383.30

> quantile(bw)
     0%     25%     50%     75%    100%
156.200 263.225 280.300 297.325 383.300

 

이 밖에도 통계하면 떠오르는 분산, 표준편차를 계산해주는 함수도 제공한다. 각각 var()sd() 함수다.

> var(bw)
[1] 1451.567

> sd(bw)
[1] 38.09944

이처럼 R이 기본 제공하는 함수들을 이용하여 간단하게 필요한 통계치들을 모두 얻을 수 있다.

 

그래프 그리기

통계치를 얻었으니 이제 확률분포 그래프를 그릴 차례다. 확률분포 그래프는 셀을 잘게 잘게 쪼갠 히스토그램을 이용해 그린다고 배웠던 것 같은 느낌적 느낌이 기억 저편에 흐릿하다. 일단 그려보자. 히스토그램은 hist() 함수를 이용하여 그릴 수 있다.

> hist(bw, breaks=100, probability=TRUE)
  • breaks=100
    • 히스토그램 셀의 개수
    • 숫자가 커질수록 선형에 가까워진다.
    • default 값은 10
  • probability=TRUE
    • Y축을 출현 확률로 지정
    • FALSE인 경우, Y축은 출현 빈도를 나타낸다.
    • default 값은 FALSE

histogram

가운데가 불룩한 정규분포도에 정확히 부합하지는 않지만 비슷한 결과가 나오기는 했다. 정규분포도와 다른 이유는 데이터셋의 문제다. worker의 개수를 10에서 250까지 변경하며 bandwidth를 반복 측정했던 데이터이기 때문에 worker 개수 별 분포가 섞여 있는 결과가 나온 것이다. 정확한 그래프를 얻기 위해서는 worker의 개수를 각각의 집단으로 하는 집단별 히스토그램을 그려야 한다.

25개의 히스토그램을 그리자니 몹시 귀찮다. 한꺼번에 그릴 수는 없을까? 물론 방법은 있다.

 

박스플롯(boxplot)

박스플롯은 fivenum() 또는 quantile() 함수로 얻을 수 있는 5가지 통계치(최솟값, 1사분위값, 중간값, 3사분위값, 최댓값)을 이용해 그리는 상자 형태의 그래프다. 히스토그램과는 다르게 집단이 여러 개인 경우에도 하나의 그래프에 표현할 수 있다. R에서는 박스플롯 그래프를 그리기 위해 boxplot() 함수를 제공한다.

> worker <- report$worker  # result 데이터셋의 worker 컬럼 데이터를 worker 객체에 할당
>
> boxplot(bw~worker, ylim=c(0, 400), xlab=~Workers, ylab=Bandwidth~MB/s)
>
> grid()  # 그래프에 grid 표시
  • bw~worker
    • y~grp, 그룹별 numeric vector를 나타내는 수식
    • worker의 개수 별 그룹을 만들고 각각의 bandwidth를 입력하겠다는 의미
  • ylim=c(0, 400)
    • y축의 범위를 0에서 400으로 설정
  • xlab, ylab
    • x축과 y축의 label 설정

boxplot

이상한 그래프가 그려졌다. 그래프만 봐서는 무슨 의미인지 잘 모르겠다. 좀 더 자세히 알아보자.

boxplot_singlebox

박스는 1사분위값과 3사분위값을 경계로 그려지며 박스 안의 선은 중간값이다. 박스는 전체 분포의 50%에 해당한다. LIF와 UIF는 각각 하한값 상한값을 나타내며 두 값의 사이는 전체 분포의 약 99%에 해당한다. LIF와 UIF 밖의 값들은 이상 수치로 간주하고 통계에서는 제외한다.

이를 정규분포도와 비교해보면 각각의 박스플롯은 그룹별 정규분포를 나타낸다는 것을 알 수 있다.

boxplot_vs_norm_dist

 

이런 그래프를 그려야 하는 이유가 무엇일까? 앞서 설명한 바와 같이, 이 그림은 worker 갯수 별 bandwidth의 정규분포를 박스플롯으로 나타낸 것이다. 즉, multi process 환경에서 디스크의 대략적인 bandwidth를 한눈에 쉽게 알아보기 위함이다.

앞의 박스플롯 그래프를 다시 보면 대부분의 박스가 250~300MB/s 사이에 분포한다는 것을 쉽게 알 수 있다. 따라서 이 디스크의 bandwidth는 대략 250~300 MB/s라 할 수 있다.

 
 

마치며…

… 확실히 확률과 통계는 어렵다. 배운지 20년이 다 되어가니 다시 공부해도 잘 모르겠다. 손으로 계산하는 것은 상상도 못 할 것 같다. 하물며 엑셀을 이용한다 하더라도 쉽지 않은 작업일 것이다. R은 이런 복잡한 계산을 순식간에 처리해준다. 필요한 내용만 빠르게 학습한 수준이지만, 앞으로 있을 여러 가지 성능측정 시험을 정리하는 데 유용하게 사용할 수 있을 것 같다.

 
 

]]>
http://note.arzhna.net/2017/02/27/%eb%b3%b5%ec%9e%a1%ed%95%9c-%ed%99%95%eb%a5%a0-%ed%86%b5%ea%b3%84%eb%a5%bc-%ec%86%90%ec%89%bd%ea%b2%8c-r/feed/ 0 456
글로 다이어그램을 그려요 – PlantUML http://note.arzhna.net/2017/01/05/%ea%b8%80%eb%a1%9c-%eb%8b%a4%ec%9d%b4%ec%96%b4%ea%b7%b8%eb%9e%a8%ec%9d%84-%ea%b7%b8%eb%a0%a4%ec%9a%94-plantuml/ http://note.arzhna.net/2017/01/05/%ea%b8%80%eb%a1%9c-%eb%8b%a4%ec%9d%b4%ec%96%b4%ea%b7%b8%eb%9e%a8%ec%9d%84-%ea%b7%b8%eb%a0%a4%ec%9a%94-plantuml/#respond Thu, 05 Jan 2017 05:25:29 +0000 http://note.arzhna.net/?p=426 Continue reading

]]>
소프트웨어 설계를 하다 보면 UML 다이어그램으로 표현해야 할 일이 종종 있다. 객체지향 설계이거나, 여러 가지 모듈이 연동되어 동작하는 시스템이거나 또는 상태 변화를 설명해야 할 때 UML 다이어그램은 아주 좋은 표현 방법이다.

다이어그램은 그림이다. 컴퓨터를 이용해 그림을 그리려면 그림판과 같은 도구가 필요하다. (물론 그림판으로 다이어그램을 그리는 장인은 게으른 개발자 중엔 없으리라 생각한다) 당연하게도 오래전부터 UML 다이어그램을 그리기 위한 많은 도구가 개발되어 사용되고 있다. 역사와 전통을 가진 IBM의 Rational 시리즈, Boland의 Together Architect, MS의 Visio 그리고 국산 UML 도구의 대명사 Plastic을 오픈소스화한 StarUML 등이 대표적이라 할 수 있다. UML 도구는 아니지만, PowerPoint나 Keynote 같은 프레젠테이션 도구를 이용하는 ppt 장인들도 있다. 모두 강력한 도구임은 분명하다. 그런데 모두 GUI를 가진 도구이다. 마우스를 이용하기 위해 키보드에서 손이 떨어지면 생산성도 떨어질 것 같아 자괴감이 드는 개발자들에게는 굉장히 귀찮은 도구가 아닐 수 없다.

 

키보드만으로 다이어그램을 그릴 수는 없을까?

이 화려한 그래픽을 보라!

MUD 게임의 이 화려한 그래픽을 보라!

우리는 이미 오래전 키보드만으로 진행하는 텍스트 기반의 온라인 RPG 게임인 MUD를 경험했다. 커맨드를 입력하고, 뇌내(腦內) 그래픽카드를 풀가동해 머릿속에 화려한 맵을 그리며 게임을 했던 바로 그 경험이다. 연식 인증인가? 그 경험처럼 텍스트만으로 다이어그램을 표현해보자.

 

Alice -> Bob: Authentication Request
Alice <- Bob: Authentication Response

 

plantuml_logo예제는 Alice가 Bob에게 인증을 요청하고 Bob이 요청에 대한 응답을 주는 절차를 표현한 간단한 문장이다. 이름과 화살표, 그리고 동작을 직관적으로 설명하고 있다. 그대로 다이어그램으로 바꿀 수 있으면 좋을 것 같다. 그리고 그런 일이 실제로 가능하다. 오픈소스 UML 도구인 PlantUML을 이용하면 된다.

PlantUML을 이용해 예제를 시퀀스 다이어그램으로 변환하면 다음 그림과 같다.

auth

Awesome!! GUI 도구를 이용해 같은 다이어그램을 그리려면 인스턴스 둘을 끌어다 놓고, 라벨링을 두 번 하고, 화살표를 두 번 연결하고, 또 라벨링을 두 번 해야 한다. 우리의 손은 마우스와 키보드를 넘나들며 바쁜 시간을 보낼 수밖에 없다. 게다가 칼각을 원하는 강박증 환자라면 어긋난 1 ~ 2 픽셀에 스트레스를 받으며 저주받은 손을 원망하고 있을 것이 뻔하다.

 

 

설치 방법

PlantUML은 Java로 구현되어 있으므로 JVM만 돌아갈 수 있으면 어떠한 머신에서도 동작한다. 가장 쉬운 설치방법은 웹사이트의 다운로드 페이지에서 미리 컴파일된 jar 파일을 받아 사용하는 것이다. 이클립스나 IntelliJ를 이용한다면 플러그인으로 설치할 수도 있다. 역시 웹사이트를 참조하자.

키보드에서 손을 떼기 싫어서 PlantUML을 사용하려는데, 웹사이트에서 내려받기 위해 마우스를 잡아야 한다는 것이 모순으로 느껴질 수도 있다. 그런 키보드 성애자분들에게는 cli를 이용해 설치하는 방법을 추천한다.

  • Devian 계열 Linux
$ sudo apt-get install plantuml
  • Redhat 계열 Linux
$ sudo yum install plantuml
  • macOS
$ brew install plantuml

 

 

사용 방법

시퀀스 다이어그램을 표현했던 앞의 예제를 PlantUML 문법으로 표현하면 다음과 같다.

@startuml 
Alice -> Bob: Authentication Request 
Alice <- Bob: Authentication Response 
@enduml

그대로 txt 파일로 저장하고 plantuml을 실행하면 위와 같은 다이어그램 이미지 파일이 생성된다.

$ plantuml filename.txt

 

클래스 다이어그램은 다음과 같이 표현할 수 있다.

@startuml
class Class01 {
  String data
  void methods()
}
Class01 <|-- Class02
@enduml

거의 코드 수준이다. 개발자에게 이보다 더 좋은 문법이 있을 수 없다. 역시 txt 파일로 저장하고 plantuml을 실행하면 다음과 같이 클래스 다이어그램이 생성된다.

class

 

그렇다면 스테이트 다이어그램은 어떨까?

@startuml
[*] --> Running: Start
Running --> Pause: Pause
Pause --> Running: Resume
Running --> [*]: Stop
@enduml

state

시퀀스 다이어그램의 문법과 거의 흡사한 문법으로 스테이트 다이어그램을 얻을 수 있다.

이 밖에도 유즈케이스, 액티비티, 컴포넌트 다이어그램 등 UML 다이어그램 대부분을 간단하고 직관적인 문법으로 표현할 수 있다. 다이어그램에 따라 문법이 조금씩 다르지만, 전체적으로 볼 때 직관적이다 하는 그런 기운이 느껴진다. 자세한 문법은 역시 웹사이트를 참조하자. 한글 매뉴얼을 제공하고 있어 쉽게 학습할 수 있다.

 

약을 한번 팔아보자.

다이어그램을 그려야 하는데 다음과 같은 문제가 있어 어려운 분에게 이 약 PlantUML을 강력하게 추천한다.

  • 키보드에서 손을 떼면 생산성이 떨어진다고 생각하는 키보드 성애자
  • 마우스를 사용하면 생산성이 떨어진다고 생각하는 마우스 혐오자
  • 1 ~ 2 픽셀이 어긋나 있는 것을 두고 볼 수 없는 라인 강박증 환자
  • 회사에서 고가의 UML 도구를 사주지 않아 파워포인트로 한 땀 한 땀 그리고 있는 PPT 장인
  • 마우스 때문에 손목이 아픈 손목 터널 증후군 환자
  • bash와 vi가 없으면 아무것도 할 수 없는 리눅스 덕후
  • MUD 게임의 향수에 젖어 있는 아재 개발자

 

PlantUML로 글 쓰듯이 다이어그램을 그려보자.

 

 

]]>
http://note.arzhna.net/2017/01/05/%ea%b8%80%eb%a1%9c-%eb%8b%a4%ec%9d%b4%ec%96%b4%ea%b7%b8%eb%9e%a8%ec%9d%84-%ea%b7%b8%eb%a0%a4%ec%9a%94-plantuml/feed/ 0 426
밑바닥 개발자의 레이어 등정기 http://note.arzhna.net/2016/12/23/%eb%b0%91%eb%b0%94%eb%8b%a5-%ea%b0%9c%eb%b0%9c%ec%9e%90%ec%9d%98-%eb%a0%88%ec%9d%b4%ec%96%b4-%eb%93%b1%ec%a0%95%ea%b8%b0/ http://note.arzhna.net/2016/12/23/%eb%b0%91%eb%b0%94%eb%8b%a5-%ea%b0%9c%eb%b0%9c%ec%9e%90%ec%9d%98-%eb%a0%88%ec%9d%b4%ec%96%b4-%eb%93%b1%ec%a0%95%ea%b8%b0/#comments Thu, 22 Dec 2016 15:20:18 +0000 http://note.arzhna.net/?p=396 Continue reading

]]>
나는 밑바닥 개발자였다.

적어도 2년 전까진 그랬다. 여기서 밑바닥이라는 것은 계급론적 최하층을 뜻하는 것은 아니다. 일반적으로 표현하는 소프트웨어 레이어의 가장 아래, 로우엔드, 하드웨어 디펜던시한 레이어를 뜻한다. 다시 말해 나는 디바이스 드라이버 개발자였다.

android_layer

주 업무는 전자 부품들의 데이터 시트를 참조하여 원하는 동작을 할 수 있도록 펌웨어 / 드라이버를 개발하는 일이었다. 특별한 IDE도 없이 텍스트 에디터와 gcc를 이용해 개발을 했고, 콘솔 로그를 참조하여 디버깅을 했다. 그나마 일반적인 로직이라면 gdb 또는 콘솔 로그로 디버깅할 수 있었지만, 논리적 결함이 아닌 전자적 설정 오류나 타이밍 이슈는 오실로스코프를 이용해야 했다. 실제 데이터가 어떤 전기적 신호로 흘러가고 있는지 확인해야 했기 때문이다.

1324016978_39

전자공학이 아닌 전산학을 전공한 나는 오실로스코프 사용법은 커녕 회로도 하나 읽지 못하는 상태였다. 당연히 적응에 상당한 시간이 걸릴 수밖에 없었다. 계속해서 좀 더 로지컬한 일을 원했지만 받아들여지지 않았다. 하지만 나는 호모 디지피엔스였다. 어느새 익숙해져 실력을 인정을 받으며 10년이라는 세월이 흘렀다.

 

 

신분 레이어 상승의 욕구

실력을 인정받는다는 것은 달콤한 일이다. 그 달콤함을 버리기란 쉽지 않다. 그러나 여전히 가슴 한쪽에는 상위 레이어로 올라가고 싶은 마음이 자라고 있었다. 지금은 비록 인정받고 있다고 하지만 결국 나는 우물 안 개구리일 것이 분명했다.

limp-bizkit-501cdee5305f0

Hey~ Drop the bit! 내가 가진 건 고작 0과 1, start and stop, on and off, 그게 전부지만 사실은 greater still, 그것이 바로 남자의 길~

쿵작쿵작 쿵짜작쿵짝 흐르는 010101101 비트의 세계가 남자의 길이라지만, 좀 더 많은 소프트웨어 기술들이 배틀을 하는 윗동네의 공기를 느끼고 싶었다.

그래서 과감히 회사를 그만두었다. 확실한 대책은 없었다. 일단 쉬면서 생각해 보기로 했다. 대책 없는 자유는 한없이 지루했고, 유유히 흘러가는 강물처럼 하루하루가 지나갔다. 어느새 나는 주부가 되었다.

어느덧 시간이 흐르고, 나는 제조업이 아닌 웹서비스 회사로 이직했다. 딱히 프론트엔드 같은 최상위 레이어를 원한 것은 아니었지만, 조금은 극적인 레이어 상승을 할 수 있을 것 같았다. 하지만 처음 내게 주어진 업무는 여전히 프로토콜 설계와 제어 모듈, 데몬 개발이었다. 그나마 더는 비트 단위의 프로토콜이 아닌 JSON 문서로 사람과 기계가 모두 이해할 수 있는 시멘틱을 전달할 수 있어 한 걸음 앞으로 나아간 기분은 들었다. 게다가 사람과 기계가 모두 이해할 수 있는 시멘틱은 석사 논문의 주제였던 시멘틱 웹의 궁극적인 목표가 아니었던가!

 

 

그리고 1년 후

드디어 서버 개발자로 변신했다. 물론 여전히 애플리케이션 레이어보다는 커널 레이어에 가까운 플랫폼 API 서버를 개발하고 있지만 말이다. 사실 디바이스 드라이버를 이용하는 소프트웨어에 API를 제공하는 것이나, 플랫폼을 이용하는 소프트웨어에 API를 제공하는 것이나 크게 다를 것은 없다. 그러나 그것을 구현하기 위해서 많은 것들을 새로 또는 다시 공부해야 했다.

2016년 한해 로우엔드에서 백엔드로 이동하며 공부했던 것들을 열거해보면 다음과 같다.

 

Python

logo_python주 종목이었던 c를 버렸다. 필요하다면 c로도 플랫폼 API 서버를 만들 수는 있다. 그렇지만 훨씬 쉬운 방법이 있는데 적합하지 않은 언어를 굳이 고집할 필요는 없다. 그래서 python과 flask를 공부했다.
커널의 기능을 이용하는 간단한 운영 도구도 python으로 만들 수 있다. 게다가 c로 된 라이브러리도 쉽게 사용할 수 있어 기존에 만들었던 라이브러리도 사용할 수 있다. python으로 넘어온 것은 좋은 선택이었던 것 같다.

 

RESTful API

restful_api지난 10년의 경험은 javascript ui 개발을 지원하기 위한 웹 브라우저 포팅을 제외하면 웹과 거의 관련이 없었다. HTTP에 대한 지식은 겨우 학부 수준이었다. GET과 SET 메소드를 이용해 데이터를 주고받는 정도에 그쳤다. 오래전에 배운 내용은 이미 많이 변화했다. 인터페이스를 만들기 위해 HTTP와 RESTful API에 관해서도 공부해야 했다.

 

DB와 ORM

db_orm역시 학부 이후로 DB를 거의 다루지 않았다. 제로보드 기반의 커뮤니티, 텍스트큐브와 워드프레스 기반의 블로그 등을 운영하면서 필요에 따라 조금씩 사용했던 select from where가 전부다. PK, FK, 테이블간의 관계 표현 등, 가물가물한 기억을 더듬으며 다시 공부해야 했다.
그러나 직접 쿼리를 만들 필요는 없었다. 모델링을 하고 SQLAlchemy같은 ORM을 이용하여 모델을 정의해두면 나머지는 ORM이 알아서 해준다. 신기한 세상이다.

 

로드 밸런싱 및 배포 도구

dist_tools대규모 웹 서비스를 개발해야 하니 규모를 생각하지 않을 수 없다. 여러 대의 서버를 구축하여 로드를 분산하고, 소프트웨어를 모든 서버에 자동으로 배포해야 하는 등의 개발 이외의 일들이 산재해있었다. 임베디드의 세계에서는 전혀 알 수 없었던 부분이다. CI 서버에서 빌드 되어 나온 펌웨어를 OTA 서버에 배포하면 끝이었다. 실제 단말로의 배포는 브로드캐스팅으로 진행되지만, 거기까진 신경 쓰지 않아도 되는 영역이었다.

 

open source

opensource-logo-300x259필요한 것이 있으면 일단 만들기 시작했던 구시대 개발자의 습관도 버렸다. 필요한 것은 이미 다 있다. 찾아서 사용하자. know-how보다는 know-where가 중요하다. 그러고도 개발자라면 오픈소스를 쓰자!

 

 

다시 2년전

이직을 위한 최종 면접에서 면접관 한 분이 이렇게 물었다.

임베디드 10년 경력이면 더 깊게 파는 것이 더 도움이 되지 않을까요?

물론 더 깊게 공부해 전문가(expert)가 되는 것도 좋은 선택이다. 언젠가는 전문가가 될 수도 있지만, 현실은 그렇지 않다. 전문가를 가장한 꼰대가 될 확률이 훨씬 높다. 항상 해왔던 일만 반복하는 부품이 될 확률도 만만치 않다.

나는 대답했다.

한 분야를 깊이 알기 위해서는 일단 넓게 알아야 한다고 생각합니다. 다양하게 체험해보지 않으면 깊이를 가늠하기 어렵습니다. 깊이 알기 위해 더 많은 분야를 체험해 보고 싶습니다.

그 대답의 결과로 다양한 분야를 체험하며 2016년을 보냈다. 그리고 그 체험은 앞으로도 당분간은 계속 이어질 것 같다.

 


 

이 글은 이상한모임 대림절 이벤트에 기고하기 위해 작성되었습니다. 대림절이란 블라블라블라… 자세한 내용은 링크를 참조하세요 🙂

 

]]>
http://note.arzhna.net/2016/12/23/%eb%b0%91%eb%b0%94%eb%8b%a5-%ea%b0%9c%eb%b0%9c%ec%9e%90%ec%9d%98-%eb%a0%88%ec%9d%b4%ec%96%b4-%eb%93%b1%ec%a0%95%ea%b8%b0/feed/ 1 396
타 언어에서 rust library 사용하기 http://note.arzhna.net/2016/05/12/%ed%83%80-%ec%96%b8%ec%96%b4%ec%97%90%ec%84%9c-rust-library-%ec%82%ac%ec%9a%a9%ed%95%98%ea%b8%b0/ http://note.arzhna.net/2016/05/12/%ed%83%80-%ec%96%b8%ec%96%b4%ec%97%90%ec%84%9c-rust-library-%ec%82%ac%ec%9a%a9%ed%95%98%ea%b8%b0/#respond Thu, 12 May 2016 02:16:08 +0000 http://note.arzhna.net/?p=369 Continue reading

]]>
 

일반적으로 시스템 라이브러리라함은 네이티브 언어로 작성되었음을 의미한다. 그리고 보통 네이티브 언어는 c/c++과 같은 언어를 의미한다. 시스템 라이브러리는 다른 언어로 작성한 프로그램에서도 이용할 수 있어야 한다. 그래서 많은 프로그래밍 언어들이 c/c++로 작성된 라이브러리를 사용하기 위한 패키지(이하 ffi 패키지)를 제공한다. java의 jni (java native interface), python의 ctype, ruby와 javascript의 ffi (foreign function interface) 등이 바로 그 것이다. 물론 rust에서도 c 라이브러리를 사용하기 위해 ffi 패키지를 제공한다.

rust는 c/c++과 마찬가지로 (다른 용도로도 사용할 수 있지만 기본적으로는) 시스템 프로그래밍을 위한 언어다. 따라서 rust로 작성된 라이브러리도 다른 언어에서 사용할 수 있어야 한다. 이를 위해 rust는 c 라이브러리와 같은 구조의 동적 라이브러리를 만들 수 있는 옵션을 제공한다.

 

 

동적 라이브러리 만들기

rust는 cargo라는 패키지 매니저가 많은 것들을 대신 해주기 때문에 c 라이브러리를 만드는 것과는 비교도 할 수 없을 정도로 편하다. c로 소스 코드를 작성하고 소스 코드만큼 많은 양의 makefile을 작성하던 과거의 나는 이제 안녕!

…은 개뿔. 프로그램이 커지고, 그래서 모듈이 많아지고, 따라서 디펜던시가 증가하고, 그로 인해 옵션이 많이지면 cargo도 복잡하긴 매한가지다. 너무 좋아하진 말자.

언어를 배운다는 것은 Hello, world! 를 출력하는 방법을 배우는 것이다. 그러니까 Hello, world! 를 출력하는 rust 라이브러리를 만들어 보자. 싫다면 다른 라이브러리를 알아서 만들어 보길 추천한다. 예를 들어 알파고알파고 라거나 알파고 같은 것 말이다.

일단 cargo를 이용해 새 패키지를 생성한다.

$ cargo new hello
$ cd hello
$ tree
.
├── Cargo.toml
└── src
    └── lib.rs

우리의 요구사항은 Hello, world! 를 출력하는 것이다. 요구 사항을 만족하는 소스 코드를 lib.rs 파일에 입력한다.

fn hello() {
    println!("Hello, world!");
}
$ cargo build
    Compiling hello v0.1.0 (file:///Users/arzhna/dev/hello)
src/lib.rs:1:1: 3:2 warning: function is never used: `hello`, #[warn(dead_code)] on by default
src/lib.rs:1 fn hello() {
src/lib.rs:2     println!("Hello, world!");
src/lib.rs:3 }  

그대로 빌드하니 dead_code 어쩌고 하는 무시무시한 경고 메시지를 출력하며 컴파일이 됐다. 경고 메시지는 뭔지 잘 모르겠으니 무시하고, 라이브러리가 잘 만들어졌나 확인해보았다.

$ ls target/debug/lib*
target/debug/libhello.rlib

이럴 수가! 확장자가 rlib 이다. rlib은 rust 정적 라이브러리 파일의 확장자다. ffi 패키지들은 so 또는 dylib 이라는 확장자를 가진 동적 라이브러리를 지원한다. python에서 제공하는 ctype의 c 라이브러리 로드 클래스는 이름부터 cdll(c dynamic link library)이다. rlib은 못 쓴다는 뜻이다.

 

살려야 한다! 동적 라이브러리를 만들어야 한다!

 

동적 라이브러리를 만들기 위해서는 동적 라이브러리를 만들기 위한 옵션을 설정해야 한다. Cargo.toml 파일을 열고 적당한 위치에 아래와 같이 이 패키지는 동적 라이브러리여야만 해!라고 명시하기 위한 [lib] 섹션을 추가하자.

[lib]
crate-type = ["dylib"]

그리고 다시 빌드해보자.

$ cargo build
    Compiling hello v0.1.0 (file:///Users/arzhna/dev/hello)
src/lib.rs:1:1: 3:2 warning: function is never used: `hello`, #[warn(dead_code)] on by default
src/lib.rs:1 fn hello() {
src/lib.rs:2     println!("Hello, world!");
src/lib.rs:3 }
$   
$ ls target/debug/lib*
target/debug/libhello.dylib

(역시 경고는 무시하고) 확인해보니 이번에는 dylib 이라는 확장자를 가진 동적 라이브러리가 잘 생성되었다. 만세!

 

그렇다면 이대로 쓰면 될까? 경고가 찝찝한데?

 

메시지를 다시 살펴보니 function is never used 라고 경고하고 있다. hello() 함수를 어디서도 사용하고 있지 않고 있기 때문이다. 아무도 사용하지 않는 dead_code 가 있는 경우 경고 메시지를 발생시키는 것이 rust 컴파일러의 기본 설정이다.

라이브러리가 제공하는 API 함수라면 라이브러리 내에서 사용하고 있지 않아도 전혀 이상할 것이 없는데 왜 경고 메시지가 나올까? 혹시 API 함수가 아니라면? 그렇다. 처음에 작성했던 hello() 함수는 로컬 함수였다. 외부에서 사용할 수 있도록 선언되지 않았기 때문에 경고를 발생시킨 것이다. 로컬 함수를 API 함수로 바꾸기 위해서는 몇가지 어노테이션을 추가해야 한다.

 

pub extern fn hello() {
    println!("Hello, world!");
}

pubextern 이라는 어노테이션이 추가되었다. pub은 public 함수임을 선언하기 위해, extern은 외부에서도 사용할 수 있음을 선언하기 위해 붙이는 어노테이션이다.

 

이제 외부에서 사용할 수 있는 동적 라이브러리를 만들 수 있을까? 아직이다. 대부분의 컴파일러는 컴파일 과정에서 네임 맹글링(name mangling)이라는 작업을 수행한다. 정의되어 있는 함수명을 정해진 규칙에 의해 변경하는 작업이다. 그런데 불행히도 언어마다 맹글링 규칙이 다르다. c와 c++을 혼용해 사용하는 프로그램에서는 extern "C" {...}와 같은 코드들을 흔하게 볼 수 있다. 이는 c와 c++의 맹글링 규칙이 다르기 때문에 c 스타일로 맞춰주기 위한 코드다.

c 라이브러리를 로드하는 패키지들은 c 스타일의 맹글링만을 고려한다. 따라서 rust 컴파일러가 c 스타일의 맹글링을 하도록 해야한다. 다음과 같이 #[no_mangle] 어노테이션을 추가해 rust 컴파일러의 맹글링 스위치를 꺼버리자.

#[no_mangle]
pub extern fn hello() {
    println!("Hello, world!");
}

이제 다른 언어에서 사용할 수 있는 동적 라이브러리를 생성할 준비가 끝났다. 빌드하자.

 

$ cargo build
   Compiling hello v0.1.0 (file:///Users/arzhna/dev/test/hello)
$ ls target/debug/lib*          
target/debug/libhello.dylib

경고 메시지도 없고 동적 라이브러리도 제대로 생성되었다.

신난다!

easy

 

 

rust 동적 라이브러리 사용하기

서두에서 언급했던 바와 같이 대부분의 언어들은 c/c++ 라이브러리를 사용하기 위한 패키지를 제공한다. 이전 섹션에서 만든 rust 라이브러리는 c 스타일로 컴파일된 동적 라이브러리다. 따라서 c/c++ 라이브러리를 사용하기 위한 패키지를 그대로 이용할 수 있다.

python

파이썬은 ctype이라는 패키지를 제공한다. ctype의 cdll이라는 클래스를 통해 c/c++ 라이브러리를 로드할 수 있다. 백문이 불여일견! 바로 테스트해보자.

# hello.py

from ctypes import cdll

# libhello 라이브러리를 로드한다.
lib = cdll.LoadLibrary("./target/release/libhello.dylib")

# libhello 라이브러리가 제공하는 hello() api를 호출한다.
lib.hello()

print("done!")

실행하면?

$ python hello.py
Hello, world!
done!
$

굿잡!

 

c

c에서 rust 라이브러리를 사용하기 위해서는 헤더 파일이 필요하다. rust 라이브러리가 제공하는 API들의 프로토타입을 c 스타일로 선언해주면 오케이!

// hello.h

void hello(void);

 

헤더 파일이 생겼으니 이제 소스 코드를 작성하고, c 라이브러리 링크하던 대로 옵션 주고, 그렇게 하던 대로 빌드하면 된다.

// hello.c

#include <stdio.h>
#include "hello.h"

int main(){
    hello();
    return 0;
}
$ gcc -lhello -L./target/release/ -I. hello.c -o hello
$ ./hello 
Hello, world!

성공!

 

swift
swift는 objective-c를 기반으로 만들어져 있다. 당연히 c와 호환성이 우수하다. rust로 작성된 라이브러리지만 c 라이브러리와 다를바 없으므로 Bridging-Header만 만들면 그대로 사용할 수 있다.

 

java
자바는 jni를 만들면되는데… 귀찮으니 패스하자.

 

ruby
안타깝게도 나는 ruby 언어를 모른다. ffi 패키지가 있다카더라.

 

js
역시 ffi를 이용하면 된다던데?

 

go


불행히도 그나마 할 줄 아는 언어가 c, python, java 밖에 없다. 그러니 예제는 여기서 끝!

 

 

]]>
http://note.arzhna.net/2016/05/12/%ed%83%80-%ec%96%b8%ec%96%b4%ec%97%90%ec%84%9c-rust-library-%ec%82%ac%ec%9a%a9%ed%95%98%ea%b8%b0/feed/ 0 369
scan-build를 이용한 정적분석 http://note.arzhna.net/2016/05/11/scan-build%eb%a5%bc-%ec%9d%b4%ec%9a%a9%ed%95%9c-%ec%a0%95%ec%a0%81%eb%b6%84%ec%84%9d/ http://note.arzhna.net/2016/05/11/scan-build%eb%a5%bc-%ec%9d%b4%ec%9a%a9%ed%95%9c-%ec%a0%95%ec%a0%81%eb%b6%84%ec%84%9d/#respond Wed, 11 May 2016 04:46:52 +0000 http://note.arzhna.net/?p=350 Continue reading

]]>
scan-build 란?

scan-build는 clang이 제공하는 정적 분석 도구다. clang은 llvm 기반 컴파일러 프론트엔드이며, GPL 라이센스로 묶여 있는 GNU 컴파일 도구모음(gcc)을 대체하기 위해 bsd 라이센스와 유사한 llvm 라이센스 오픈소스 프로젝트로 개발되고 있다.

 

 

설치

scan-build는 컴파일 도구 모음인 clang에 포함되어 있기 때문에 clang을 설치하면 된다.

  • Ubuntu
$ sudo apt-get install clang
  • OS X
$ brew install llvm --with-clang

 

 

사용 방법

사용 방법은 간단하다. 빌드 명령 앞에 scan-build만 붙여주면 된다. 기존에 사용하던 makefile을 그대로 사용할 수 있어 별도의 makefile을 구성할 필요가 없다.

scan-build [options] <build command> [build options]
  • 예시
$ scan-build make -j4
$ scan-build xcodebuild
$ scan-build gcc -c t1.c t2.c
$ scan-build clang -c t1.c -o t1.o

 

 

분석 결과

분석은 빌드와 동시에 진행되며 빌드가 끝나면 결과를 취합하여 결과 파일을 생성해준다. 그리고 친절하게 scan-view를 실행해 결과를 확인하라는 메시지를 보여준다. scan-view는 scan-build의 결과물을 웹브라우저를 통해 볼 수 있도록 해준다.

$ scan-build make
...
scan-build: 4 bugs found.
scan-build: Run 'scan-view /var/folders/rl/9lcrrvvj5qddmh8kq752xggw0000gn/T/scan-build-2016-05-11-114621-16674-1' to examine bug reports.
$

scan-view를 실행해 결과파일을 열어보면 다음과 같은 화면을 볼 수 있다.

scan-build_result

빌드 환경과 발생 가능한 bug 에 대한 요약, 각 bug에 대한 분석 내용을 확인할 수 있다. 개별 분석 결과는 view report 링크를 통해 확인할 수 있다.

scan-view_report

 

 

]]>
http://note.arzhna.net/2016/05/11/scan-build%eb%a5%bc-%ec%9d%b4%ec%9a%a9%ed%95%9c-%ec%a0%95%ec%a0%81%eb%b6%84%ec%84%9d/feed/ 0 350
시골에서 로큰롤 http://note.arzhna.net/2015/12/23/%ec%8b%9c%ea%b3%a8%ec%97%90%ec%84%9c-%eb%a1%9c%ed%81%b0%eb%a1%a4/ http://note.arzhna.net/2015/12/23/%ec%8b%9c%ea%b3%a8%ec%97%90%ec%84%9c-%eb%a1%9c%ed%81%b0%eb%a1%a4/#respond Wed, 23 Dec 2015 07:01:57 +0000 http://note.arzhna.net/?p=317 Continue reading

]]>
반년 만에 쓰는 글은 역시 이상한 모임의 숙제다. 이상한 모임이 아니면 글을 쓸 생각도 못 한 여유 없는 2015년이 저물어 간다. 물론 여유가 있었다고 글을 열심히 썼을 것 같지는 않다. 반짝하고 말았겠지… 반성하고 내년에도 작심삼일을 해보자! 작심삼일을 하기 전에 일단 당면한 숙제부터 해결하고… 그나마 책도 읽고 글도 쓸 수 있게 가둬놓고 지켜보고 있는 이모님께 건배!

 

나는 로큰롤을 좋아한다.

tweet_002

tweet_001

가끔은 트윗에 이런 허세를 시전하기도 하고(사실은 하루키봇이 올려주는 하루키의 에세이를 패러디한 트윗이다), 비록 마지막 글을 쓴지 1년이 다 되어 가지만 음악 이야기를 주로 하는 (여기 말고 다른) 블로그도 있다. 어지간히 좋아한다는 이야기다.

2015년의 마지막 책은 영화 “남쪽으로 튀어”의 동명의 원작소설 “남쪽으로 튀어”의 저자 오쿠다 히데오의 신간 에세이 “시골에서 로큰롤”로 정했다. 왜? 로큰롤이니까. 열다섯에 처음 접한 로큰롤은 여태껏 날 지배하고 있다. 그래서 기껏 선정한 책도 이 모양이다.

 

시골에서-로큰롤

오쿠다 히데오의 “시골에서 로큰롤”

이 책은 소년 시절 오쿠다가 로큰롤을 접하며 겪었던 일들의 회고다. 소년이 꿈꿀만한 감성과 그 시절의 로큰롤로 가득 차 있다. 여기서 그 시절은 오쿠다의 10대 시절이었던 70년대다. 물론 나의 10대 시절은 90년대지만 70년대의 로큰롤은 2010년대인 지금까지도 사랑받고 있으니 지금의 로큰롤 키드들도 충분히 공감할만한 내용이다. (여전히 로큰롤을 듣는 10대는 소수이며 설현이나 초아를 좋아하지 않는 남학생은 별종 취급을 당할 것이다. 게다가 아저씨도 마찬가지다! 왕년에 로큰롤 안 들어본 아저씨는 별로 없겠지만, 여전히 듣고 있으면 별종 취급이다. 아마 설현이나 초아는 아저씨들이 더 좋아하는 것 같다.)

 

내용은 이것이 전부다. 더 이상 설명이 必要韓紙?

에세이 답게 정말 시시콜콜한 이야기들뿐이다. 남자 사람 청소년이라면 누구나 겪었을 법한 살색 영화를 보러 가는 에피소드라거나, 좋아하는 음악을 들으려 친구 집에 뻔질나게 드나들었던 일, 최신 유행 패션을 따라 했던 일, 어른들의 가치관에 대한 반항 같은 청춘들의 시시한 이야기들이다. 지금와서 생각해보면 시시하지만, 당시엔 그것이 인생의 전부라고 생각했던 그런 이야기들 말이다. 그런 이야기들이 당대의 굉장한 로큰롤 음악과 적절하게 버무려져 맛깔나게 펼쳐진다.

 

나는 여전히 이런 것들을 꿈꾼다.

자유롭게 살고 싶다, 남이 안 하는 일을 해보고 싶다,
체제와는 반대편에 서고 싶다, 소수파로 있고 싶다,
모두가 오른쪽을 보고 있을 때 나만은 왼쪽을 보고 싶다.”

10대의 나와 다른 점은 꿈만 꾼다는 것이다. 10대의 나는 집에는 공부 잘하고 착한 아들로 보이기 위해 애를 쓰면서도, 친구들과 모여 목이 쉬도록 노래를 불렀고 손이 부르트도록 기타를 쳐댔다. 젊었다. 많은 시간을 가지고 있었지만 그것 뿐이었기에 잃을 것이 없었다. 반항해도, 남이 하지 않는 일을 해도, 아무것도 하지 않아도, 그로 인해 불이익을 받아도 큰 타격이 없었다.
그러나 지금은 가진 것이 많다. 가족이 있고 얼마 안 되는 재산도 있고 사회적 지위도 눈곱만큼 있다. 청춘의 터널을 지나며 쌓아올린 내 인생의 결과물이다. 쉽게 포기할 수 있을 리 없다. 그렇지만 여전히 반항하고 싶고 자유롭고 싶고 삐딱하고 싶다. 그럼 꿈이라도 꿔야지. 그렇지 아니한가?

오쿠다는 나처럼 아직 마법에서 깨어나고 싶지 않은, 늙고 싶지 않은 철없는 어른들을 위한 청춘 찬가를 던져줬다. 졸라 땡큐다!

 

책에 소개된 음악들은 여기에서 들을 수 있다. 로큰롤!

 

]]>
http://note.arzhna.net/2015/12/23/%ec%8b%9c%ea%b3%a8%ec%97%90%ec%84%9c-%eb%a1%9c%ed%81%b0%eb%a1%a4/feed/ 0 317
이상한모임에 대하여 http://note.arzhna.net/2015/07/01/%ec%9d%b4%ec%83%81%ed%95%9c%eb%aa%a8%ec%9e%84%ec%97%90-%eb%8c%80%ed%95%98%ec%97%ac/ http://note.arzhna.net/2015/07/01/%ec%9d%b4%ec%83%81%ed%95%9c%eb%aa%a8%ec%9e%84%ec%97%90-%eb%8c%80%ed%95%98%ec%97%ac/#respond Tue, 30 Jun 2015 16:19:59 +0000 http://note.arzhna.net/?p=294 Continue reading

]]>
때는 지난 2월, 경기도 모 대학에 베타 사이트를 구축하며 밤을 지새우던 날들이었다. 함께 일하던 동료가 내가 입고 있던 후드의 ㅇㅁ이라는 프린트를 보고 물었다.

동료 : 이게 무슨 브랜드에요?
나 : 브랜드는 아니고 이상한모임이에요.
동료 : 이상한모임이요? 이름이 이상한모임이에요?

그 후로도 내 후드를 보고 프린트의 의미에 대해 묻는 이들이 많았고, 그때마다 이상한모임에 대해 어떻게 설명해야할지 곤혹스러웠다. 왜냐? 나도 잘 모르니까.

 

이상한모임에 대하여

 

어쩌다 참여했지?

2014년, 나는 잘 다니던 회사를 때려치우고 약간의 방황을 시작했다. 명확히 무엇인가를 해야겠다라는 목적은 없었고 그냥 이것저것 관심가는대로 해보고 싶었다. 그러다보면 방황의 답을 얻을 수 있을거라 생각했다. 당연히 무모하기 짝이 없는 생각이었다. 목적 없는 자유는 한없이 지루했고, 유유히 흘러가는 강물처럼 하루하루가 마냥 흘러가고 있었다.

뭐라도 해야겠다는 생각에 조바심을 내며 이것저것 뒤지던 중 이상한모임이라는 페이스북 그룹을 발견했다. 개발자 모임인 것 같았고 몇몇이 모여 swift를 공부하고 있었으며, 나도 swift를 깨작대고 있던 차라 정보를 얻을 겸 적극적으로 소극적인 활동을 시작했다. 사실 활동이랄 것도 없고 그냥 인사 한번하고 구경만 했다. 적극적으로 소극적이었으니까.

 

그런데 지금은 내가 운영진이란다.

지금의 이상한 모임은 slack이라는 기업용 IRC 서비스를 이용하여 소통(이라 쓰고 잡담이라 읽는 행위)을 하고 있다. 개발자들이 많은 만큼 주로 개발에 관련된 이야기들, 질문들, 그에 대한 토론들이 이루어진다. … 물론 잡담이 더 많다. 어느 정도 비슷한 관심사들을 가진 사람들이 모여 이야기하고 있으니 당연히 말이 잘 통한다. 말이 통하니 화제도 많고 화제가 많으니 재미도 있다. 그러다가 정신을 차려보니 내가 운영진이란다. 난 적극적으로 소극적이었는데… 어째서?

sy

운영진이라니… 이보시오 이모 양반(?)… 내가 운영진이라니…

 

그래서 이상한 모임이 뭔데?

앞서 말했듯이 나도 잘 모르겠다. 원래 카페에서 혼자 작업하다가 화장실에 가고 싶을 때, 트윗에 해시태그 #이상한모임을 달고 위치를 이야기하면 어디선가 이상한사람이 나타나 소중한 노트북을 지켜주는 모임이라 들었다. … 역시 이상하다. 그냥 이상한 사람들이 모여서 이상한 이야기를 나누며 이상한 아이디어를 실현시키는 모임이라는 느낌적 느낌이다.

 

마무리는 이렇게 급하게 하는거지…

나는 아직도 이 모임의 사람들을 잘 모른다. 공식 오프 행사에 참여한 것은 딱 한번, 글쓰기 세미나였고, 몇번의 비공식 만남은 회사 근처에서 몹시 소규모로 이루어졌다. 적극적으로 소극적인 성격을 가진 극단적 낯가림 마스터라 만나봐야 쉽사리 친해지지 못하고 마냥 수줍을 뿐이다.

그럼에도 불구하고 내가 이상한 모임에 소극적이나마 참여하고 있는 것은 얻을 것이 많기 때문이다. 이상한 모임에는 지난 30여년간 살아온 세상과는 다른 수많은 세계가 있다. 이상한 모임의 이상한 세계에서 무엇을 얼마나 얻을 수 있을지는 내가 하기 나름이겠지만 적어도 한가지는 이미 얻었다. 일단 저지르면 어떻게든 결과가 나온다는 진리다. 이미 아는 사실이지만 실천하지 않으면 아무것도 아니다. 그러나 이상한 모임에서는 실천을 한다. (정확히 말하자면 실천을 당한다. 무섭다. 살려줘~!)

이 글을 보고 있는 당신. 함께 실천해 보지 않겠는가? (마무리는 영업으로)

 

 

이상한 모임에 대하여 : http://minieetea.com/2015/06/archives/3219
이상한모임 블로그 : http://blog.weirdx.io
이상한모임 슬랙(가입) : http://slack.weirdx.io
이상한모임 스토어 : http://weirdx.io/shop
이상한모임 페이스북 : https://www.facebook.com/weweirdmeetup
이상한모임 트위터 : http://www.twitter.com/we_weirdmeetup
이상한모임 플리커 : https://www.flickr.com/photos/weirdmeetup

 

이상한모임에서 진행하는, 다양한 주제로 함께 글을 쓰는 글쓰기 소모임입니다. 함께 하고 싶다면 http://slack.weirdx.io에서 가입하시고 #weird-writing 채널로 오세요!

 

]]>
http://note.arzhna.net/2015/07/01/%ec%9d%b4%ec%83%81%ed%95%9c%eb%aa%a8%ec%9e%84%ec%97%90-%eb%8c%80%ed%95%98%ec%97%ac/feed/ 0 294
당신의 가방엔 무엇이 들어있나요? http://note.arzhna.net/2015/06/05/%eb%8b%b9%ec%8b%a0%ec%9d%98-%ea%b0%80%eb%b0%a9%ec%97%94-%eb%ac%b4%ec%97%87%ec%9d%b4-%eb%93%a4%ec%96%b4%ec%9e%88%eb%82%98%ec%9a%94/ http://note.arzhna.net/2015/06/05/%eb%8b%b9%ec%8b%a0%ec%9d%98-%ea%b0%80%eb%b0%a9%ec%97%94-%eb%ac%b4%ec%97%87%ec%9d%b4-%eb%93%a4%ec%96%b4%ec%9e%88%eb%82%98%ec%9a%94/#respond Fri, 05 Jun 2015 07:39:02 +0000 http://note.arzhna.net/?p=274 Continue reading

]]>
이상한모임 #weird-write 채널의 6월 1주차 숙제는 “당신의 가방엔 무엇이 들어있나요?”다. 주제가 나온지 몇 주 된 것 같은데 어째서 여전히 이번주 주제인지 모르겠지만, 그렇다고 한다. 그래서 가방을 뒤집어 보았다.

things_in_my_bag_01

내용물이 단촐하다. 리스트업 해보자.

1. 지갑, 카드지갑, 명함케이스

2. 필통
batch_in_my_bag_02
나름 필기구 덕후다. 펜은 지브라, 샤프는 펜텔, 연필은 스테들러… 명확히 선호하는 제품만 사용한다. 필통의 내용물은 다음과 같다.

셰퍼 만년필, 파커 볼펜, 지브라 클립온 멀티
스테들러 연필, 펜텔 샤프, 빨간색 네임펜,
드라이버, USB 메모리스틱, 가위

작업 환경에 대한 글에서도 언급했지만 여기서 가장 많이 사용하는 것은 지브라 클립온 멀티다.

3. 노트 (with Hevitz 가죽 노트 커버)
batch_in_my_bag_03
옥스포드 리갈 패드와 일반 노트가 끼워져 있다. 카페로 출근 할때는 끼고 살았는데 사무실로 출근하는 요즘은 사용할 일이 별로 없다. 그래도 가방 속 물건의 비주얼을 담당하고 있어 항상 가지고 다닌다.

4. AKG 이어폰
이것저것 많은 이어폰을 써오다가 AKG에 정착했다. 음질이 굉장한 것은 아니지만 가격 대비 좋은 해상력과 밸런스를 가지고 있다. 비싼 이어폰 쓰면 뭐하나… 아무리 애지중지 사용해도 언젠간 단선되고 만다. 적당한 가격에 적당한 품질의 이어폰을 비교적 오래 사용하는 것이 경제적이라는 결론을 내렸다.

5. 자니틴(?)
비상용 소화제다. 어째서 가방에 들어있는지는 잘 모르겠다 […]

6. 우산
항상 가지고 다닌다. 그런데 비가 올 땐 없다. 비가 그치면 다시 가방에서 발견된다. […]

7. 키캡 리무버
키보드 덕후에겐 필수품. 그러나 키보드 덕후라기엔 보유 키보드가 3개 밖에 안된다. 명함도 못 내밀 수준이다.

8. 케이블 타이
배선이 지저분하면 짜증내는 스타일이다. IDC에 넣으면 하루 종일 케이블링 하고 앉아 있을 것 같다. 회사에서 자리 이동이 잦아 이사할 때마다 필요하다.

IMG_7388

9. 이상한모임 여권
지난 글쓰기 세미나에서 받은 뒤 잊혀졌다 […]

하나 하나 나열하고 설명을 달아 보았지만 역시 별게 없다. 가방을 안 가지고 다녀도 될 것 같다. 남자의 가방이란 이런 것이다.

 

이상한모임에서 진행하는, 다양한 주제로 함께 글을 쓰는 글쓰기 소모임입니다. 함께 하고 싶다면 <http://weirdmeetup.herokuapp.com>에서 가입하시고 #weird-writing 채널로 오세요!

 

]]>
http://note.arzhna.net/2015/06/05/%eb%8b%b9%ec%8b%a0%ec%9d%98-%ea%b0%80%eb%b0%a9%ec%97%94-%eb%ac%b4%ec%97%87%ec%9d%b4-%eb%93%a4%ec%96%b4%ec%9e%88%eb%82%98%ec%9a%94/feed/ 0 274