스타트 루비(Start Ruby) #1

이 시간에는 루비 언어의 탄생 배경과 루비 언어의 특징에 대해서 간단히 알아보겠습니다. 루비 언어는 여러 언어의 장점을 취해서 만든만큼 다양한 기능들이 있지만, 사실 세컨드 랭귀지(Second Language)로 사용하는 정도라면 이번 장과 다음 장에서 설명하는 내용만으로도 충분할 것입니다. 자, 그럼 루비의 세계로 한 번 들어가 보겠습니다.

루비(Ruby)?

루비는 마츠모토 유키히로라는 일본 사람이 만들었습니다. 유키히로씨는 쉽게 쓸 수 있으면서 객체지향적인 언어를 만드는 걸 목표로 했고, 그래서 탄생한 것이 바로 루비(Ruby)입니다.

사실, 루비는 루비 온 레일즈(Ruby on Rails) 덕분에 더 널리 알려졌는데요, 레일즈 프레임워크는 스프링 프레임워크처럼 웹 개발을 편하게 해주는 프레임워크의 한 종류랍니다. 지금 보시는 이 사이트도 루비 온 레일즈로 만들어졌습니다.

루비는 다른 스크립트 언어가 갖고 있는 대부분의 기능이 포함되어 있습니다. 물론 거기에는 다양한 확장 라이브러리도 포함해서 말이지요. ;) 여러분이 필요로 하는 대부분의 기능은 이미 다른 라이브러리에 포함되어 있을 겁니다. 잘만 활용한다면 쉽고, 빠르게 개발을 진행할 수 있습니다.

이러한 특징때문에 반복되는 작업을 자동화하는 간단한 프로그램이나, 본격적인 개발 전에 프로토타입을 만들어보는 용으로 사용하면 딱입니다(물론 제 개인적인 소견이에요. ㅠㅠ).

콘솔 출력

루비에서 데이터를 출력하는 방법은 아주 간단합니다. 앞에서 본 것처럼 puts를 쓰면 대부분의 데이터를 출력할 수 있습니다. 단, 원하는 형태로 데이터를 출력하고 싶다면 조금 고민을 해야하지만, C 언어를 조금 안다면 그리 어렵지 않습니다. C 언어의 printf와 비슷한 기능을 하는 sprintf()가 있기 때문이죠. C처럼 생긴 sprintf()가 싫다면 "문자열 포맷" %[] 형식의 루비 스타일도 있으니 입맛대로 사용하면 됩니다. ^^;;;;

a = sprintf("제 이름은 %s이고 나이는 %d 입니다.", "루비", 1)
b = "제 이름은 %s이고 나이는 %d 입니다." %["루비", 1]
c = sprintf("PI는 .2f 입니다.", 3.1425);

puts a
puts b
puts c

콘솔 입력

루비에서 콘솔 입력은 한 줄 또는 여러 줄을 입력받을 수 있습니다. 한 줄 입력은 gets() or readline() 함수를 사용하면 되고, 여러 줄 입력은 readlines() 함수를 사용하면 됩니다.

a = gets()              # 엔터가 입력될 때까지 저장
b = readline()          # 위와 같은 결과
c = readlines()         # 여러 줄을 읽을 때 사용

루비 데이터 타입

루비에는 크게 7가지 기본 타입이 있는데요, 숫자와 문자열, 배열(Array)과 해시(Hash), 범위(Range)와 심볼(Symbol), 그리고 정규표현식(Regular Expression)이 그겁니다.

숫자와 문자열, 배열은 기존에 다른 언어와 큰 차이가 없기 때문에 간단히 살펴보고 넘어가겠습니다. 그렇다고 나머지가 엄청 복잡한 건 아니니 너무 걱정안하셔도 됩니다(사실 정규표현식은 좀 낯설긴 해요. ^^;;;;).

숫자, 문자열

아래는 루비에서 숫자와 문자열을 나타낸 예입니다.

a = 5                         # 정수 5
b = 10.1                      # 실수 10.1
c = "이것은 문자열입니다."    # 문자열

puts a, b, c                  # a,b,c 변수의 값을 차례로 출력

결과:
5
10.1
이것은 문자열입니다.

위의 a, b, c를 변수라고 하며, 변수는 값을 저장하는 일종의 공간입니다. 루비의 변수는 타입이 정해져있지 않고 우변에 대입하는 값에 따라서 변합니다. C나 C++ 언어처럼 선언할 때 변수의 타입을 지정해주는 것과는 다른 방식이지요.

puts는 파라미터로 넘어온 값을 출력하는 함수로, 숫자 타입부터 배열이나 해시까지 아주 편하게 출력할 수 있습니다. 앞으로 자주 사용할 것이니 puts() 함수를 눈여겨봐두기 바랍니다.

배열, 해시, 범위

배열과 해시 역시 아주 직관적입니다. 아래는 배열과 해시의 예를 나타낸 겁니다.

a = [0, 1, 2, 3, 4, 5]        # 0 에서 5까지 정수가 들어있는 1차원 배열
# 사과와 바나나를 키로 사용하고, 그 값으로 빨강, 노랑을 연결한 해시
b = {"사과" => "빨강", "바나나" => "노랑"}

puts a, a.length, b["사과"], c["바나나"]

결과:
0
1
2
3
4
5
6
빨강
노랑

배열은 다른 언어와 마찬가지로 []로 감싸고 그 안에 배열의 요소를 ,로 구분하여 넣으면 됩니다. 잠시 후에 설명하겠지만 루비의 모든 타입은 클래스이기 때문에, 기본적으로 몇가지 함수나 속성을 가지고 있습니다. 위에서 나온 length도 그중에 한 가지며, 배열의 길이를 나타내는 속성입니다.

해시는 키(Key)와 값(Value)로 이루어진 테이블이며, 다른 말로는 맵(Map)이라고도 합니다. 해시는 배열과 달리 키를 사용하여 데이터를 읽고 쓸 수 있으므로, 연속적이지 않은 데이터를 다루는데 유용합니다. 해시에서 키와 값은 => 로 연결하며, 항목이 여러 개일 경우 ,로 구분합니다.

다음 범위와 정규표현식으로 넘어가기 전에 간단히 2차원 배열을 생성하는 방법을 살펴보겠습니다. 2차원 배열은 1차원 배열을 내부에 가지고 있는 배열입니다. 따라서 아래처럼 2차원 배열에 담을 배열을 먼저 생성한 뒤에, 다른 1차원 배열을 생성해서 그 안에 두면 됩니다.

a = [0, 1]          # 1차원 배열
b = [2, 3]          # 1차원 배열
c = [a, b]          # 2차원 배열

puts c
puts c[0][0]
puts c[0][1]
puts c[1][0]
puts c[1][1]

결과:
[[0, 1], [2, 3]]
0
1
2
3

위의 코드는 2차원 배열을 만들고 각 요소에 접근하는 방법을 나타낸 겁니다. 2차원 배열이 "1차원 배열을 요소로 갖고 있는 1차원 배열"이란 것을 생각해보면, 쉽게 예측할 수 있는 코드입니다. ^^)-b

범위는 숫자와 .. 또는 ...으로 이루어진 조합으로, 시작과 끝에 포함되는 모든 정수를 뜻합니다. 즉 1..10은 1부터 10까지 모든 정수(1,2,3...10)을 뜻한다는 것이죠. .....의 차이는 ..는 끝 숫자를 범위에 포함하지만, ...는 끝 숫자를 범위에 포함하지 않는 것입니다. 아래는 그 사용법과 결과를 나타낸 겁니다.

a = 0..10          # 0부터 10까지 범위의 정수
b = 0...10         # 0부터 9까지 범위의 정수

puts a
puts b

결과:
0..10
0...10

위의 결과를 보면 살짝 당황스러울 겁니다. 0부터 10까지의 숫자가 출력되기를 바랬는데, 우리가 만든 범위를 그대로 출력해주니 말입니다. 여기에 살짝 for 문을 추가하여 실제로 범위에 들어가는 값을 출력해보겠습니다.

a = 0..10
b = 0...10

puts "0..10"
for i in a
    puts i
end

puts "0...10"
for i in b
    puts i
end

결과:
0..10
0
1
2
3
4
5
6
7
8
9
10
0...10
0
1
2
3
4
5
6
7
8
9

정규표현식(Regular Expression)과 문자열 다루기

루비의 정규표현식은 /로 구분합니다. 즉 /Ruby/처럼 사용하면 Ruby와 일치하는 문자열을 나타내는 정규표현식이 됩니다. 정규 표현식 뒤에는 페턴을 어떻게 일치시킬지를 나타내는 옵션이 들어가고 옵션의 의미는 다음과 같습니다.

* /Ruby/i : 대소문자 구분 안함
* /Ruby/m : 줄바꿈 문자도 일반 문자처럼 다룰 때 사용
* /Ruby/x : 공백문자와 주석을 허용(RE 확장 문법)

정규표현식에서 (), [], {}, ., ?, +, *, |, ^, $는 각자 의미가 있습니다. 각 기호의 의미는 말로 설명하는 것보다 직접 사용법을 보는 것이 더 이해가 쉽습니다. 다음은 각 기호의 사용법입니다.

/(R|r)uby/          # Ruby 또는 ruby와 일치
/[Rr]uby/           # Ruby 또는 ruby와 일치
/[0-9]/             # 모든 숫자 한자리와 일치
/[0-9]+/            # 모든 숫자 한자리 이상과 일치
/Ruby!*/            # Ruby 또는 Ruby 뒤에 !가 1개 이상 붙은 문자열과 일치
/Ruby!?/            # Ruby 또는 Ruby!와 일치
/Ruby{3}/           # Ruby가 3번 반복되는 문자열과 일치
/Ruby{1,3}/         # Ruby가 최소 1번부터 최대 3번까지 반복되는 문자열과 일치
/[^0-9]/            # 숫자를 제외한 문자열과 일치
/ruby$/             # ruby로 끝나는 문자열과 일치

기호로 인해 더 쉽게 정규표현식을 만들 수 있게 된 건 좋은데, 이런 기호를 실제로 쓰고 싶으면 어떻게 할까요? 방법은 간단합니다. 앞에서 나온 기호들을 실제 패턴 일치에 사용하고 싶으면 \를 앞에 붙여주면됩니다. 아래처럼 말이죠 ;)

/Ruby\?/            # Ruby?와 일치
/Ruby\+/            # Ruby+와 일치

+, *와 같은 반복 기호 뒤에는 ? 기호를 사용할 수 있는데, 이는 패턴을 일치시킬 때 범위를 어디까지로 한정하는가에 사용됩니다. 아래와 같이 Ruby> 가 있을 때 ?가 있을 때와 없을 때의 차이는 다음과 같습니다.

a = "<ruby>Ruby>"

결과:
a =~ /<.*>/
$~
=> #<MatchData "<ruby>Ruby>">

a =~ /<.*?>/
$~
=> #<MatchData "<ruby>">

위에서 $~로 나타낸 것은 정규표현식에서 일치한 부분을 나타내는 전역 변수입니다. 객체지향으로 보면 Regexp.last_match와 같습니다. 사실 Regexp.last_match는 $~의 값을 그대로 반환합니다.

정규표현식에는 문자와 숫자를 의미하거나 공백 또는 모든 문자를 의미하는 표현식이 있습니다. 위의 .이 바로 그것인데요, 다음은 해당 표현식을 나타낸 것입니다.

* /./ : 줄바꿈을 제외한 모든 문자와 일치
* /./m : 줄바꿈을 포함한 모든 문자와 일치
* /\d/ : 숫자와 일치
* /\D/ : 숫제를 제외한 모든 문자와 일치
* /\s/ : 공백 문자와 일치 \t, \r, \n, \f
* /\S/ : 공백을 제외한 문자와 일치
* /\w/ : 단어 하나와 일치
* /\W/ : 단어가 아닌 문자에 일치

사실, 문자열의 경우 배열의 인덱스에 정규표현식을 넣어서 일치하는 부분만 잘라낼 수 있습니다. 아래처럼 말이죠. slice() 함수를 사용해도 같은 결과를 얻을 수 있고, slice!()를 사용하면 원하는 결과만 문자열에서 꺼내고 기존 문자열은 나머지만 남길수도 있습니다.

a = "<ruby>Ruby>"

a[/<.*>/]
a[/<.*?>/]
a.slice(/<.*>/)
a.slice!(/<.*?>/)
puts a

결과:

<ruby>Ruby>         #a[/<.*>/]
<ruby>              #a[/<.*?>/]
<ruby>Ruby>         # a.slice(/<.*>/)의 결과

<ruby>              # a.slice!(/<.*?>/)의 결과
Ruby>               # puts a의 결과

그리고, 패턴을 비교하는데 =~만 쓰란 법도 없습니다. 문자열이라면 .match()를 사용해서 MatchData 객체를 반환하게 만들수도 있습니다. =~는 일치하는 인덱스를 반환하거나 nil을 반환하는 반면 .match()MatchData를 반환하거나 nil을 반환하는 것이 다릅니다.

명령어 실행

루비는 언어 내에서 `로 명령어를 실행하는 것을 지원합니다. 예를들어 `ls`를 하면 ls가 실행되어 그 결과가 문자열로 반환이됩니다. 다음은 ls 명령어를 실행하여 현재 디렉터리의 목록을 받아와 출력하는 예제입니다.

a = `ls`
puts a

결과:
posts.html
posts_files
start-ruby-1.md
test.css
test.html
test_files
vim-markdown-preview-설정.md

마무리...

이상으로 루비 언어의 특징에 대해서 간단하게 알아봤습니다. 다음 시간에는 루비 언어를 이용해서 귀찮은 작업을 한방에 처리할 수 있는 방법을 알아보겠습니다.

 

마크다운(Markdown)?

얼마 전에 마크다운(Markdown)이란 것을 새로 접했습니다. 위키처럼 텍스트 기반으로 편하게 문서를 작성할 수 있고, 문법 자체도 아주 직관적이어서 배우기 쉽더군요. 물론, 여기서 직관적이라는 건... 사람에 따라 조금 다르게 느낄 수도 있는 부분이지만, 위키를 한번 접해보신 분이라면 "아하~!!"라고 하실 겁니다.

그래서 루비 온 레일즈(Ruby on Rails)의 튜토리얼을 보고 간단하게 만든 사이트에 마크다운 파서인 레드카펫(Redcarpet)을 설치해서 마크다운 블로그를 만들었습니다.

사실 마크다운 형식으로 쓴 글을 파싱해서 보여주는 것이 전부라 블로그라고 하기도 좀 그렇지만... 일단 대략 완성되었으니 한번 공개해봅니다. ^^;;;; kkamagui의 마크다운 블로그로 바로가기~!! 간단 마크다운 문법 정리로 가면 마크다운 문법이 어떤 것이고 어떻게 보이는지를 간단히 확인할 수 있으니 궁금하시면 한번 들러보시기 바랍니다. ^^;;;

새로 만든 블로그에 글을 적다보니 약간 불편한 점이 있더군요. 글 쓰는 것 자체는 편해졌는데, 단지 웹에서 작업을 해야 한다는 것이 좀 불편했습니다. 만일 로컬에서도 작업할 수 있다면, VI 에디터에서 글을 쓰고 바로바로 확인하는 방법으로 더 편하게 작업할 수 있을 테니까요. ^^;;;

그래서 찾아보던중... 아웃사이더님의 블로그에서 VIM Plugin을 발견했습니다. VIM에서 작업하다가 Command Line에 :Mm만치면 웹 브라우저에서 바로 확인할 수 있는 멋진 녀석이더군요. ;)

VIM Markdown Preview 설치 방법

설치방법 또한 아주 간단했습니다. vim-markdown-preview사이트로 이동해서 파일을 다운로드한 뒤, plugin 폴더와 doc 폴더의 모든 파일을 홈 디렉터리 아래에 있는 .vim 디렉터리 아래에 넣어두면 됩니다. ^^;;; 직접 복사하는 것이 귀찮다면 아래처럼 install.sh를 직접 실행하셔도 됩니다. 단, 홈 디렉터리 아래에 .vim/plugin 폴더가 이미 생성되어 있어야 합니다.

$> install.sh

실행 방법

설치가 모두 끝났다면 vim으로 파일을 하나 열어서 아래처럼 텍스트를 그대로 입력한 다음 Command Line에 :Mm을 입력해보세요. 기본 CSS가 Github Style로 되어 있어서, Github처럼 예쁘게 포매팅된 문서를 보실 수 있을 겁니다. ^^

#1.안녕하세요 H1 입니다.
## 1.1 H2에요

이것은 일반 텍스트입니다. 마크다운으로 아주 편하게 문서를 작성할 수 있어요. ;)

* 리스트1
* 리스트2
* 리스트3

이제 코드를 한번 보겠습니다.

    이 부분은 코드로 표시될 부분입니다. 탭을 1번 입력하거나 스페이스바를 4번 입력하면 코드 블럭을 사용할 수 있습니다. 

> 이것은 인용 블럭입니다. 정말 쉽죠? ^^;;;

[kkamagui blog](http://kkamagui.tistory.com)는 링크를 거는 간단한 방법입니다. 이것 외에도 많은 방법이 있어요 ;) 더 많은 내용은 [마크다운 문법](http://blog-kkamagui.cloudfoundry.com/posts/1)을 참고하세요.

결과:


1.안녕하세요 H1 입니다.

1.1 H2에요

이것은 일반 텍스트입니다. 마크다운으로 아주 편하게 문서를 작성할 수 있어요. ;)

  • 리스트1
  • 리스트2
  • 리스트3

이제 코드를 한번 보겠습니다.

이 부분은 코드로 표시될 부분입니다. 탭을 1번 입력하거나 스페이스바를 4번 입력하면 코드 블럭을 사용할 수 있습니다. 

이것은 인용 블럭입니다. 정말 쉽죠? ^^;;;

kkamagui blog는 링크를 거는 간단한 방법입니다. 이것 외에도 많은 방법이 있어요 ;) 더 많은 내용은 마크다운 문법을 참고하세요.


CSS 바꾸는 방법

Github Style도 충분히 만족스럽지만 각자의 취향 차이가 있으니 자신이 원하는 CSS로 바꾸는 방법도 살짝 알아보겠습니다. 홈 디렉터리에 있는 .vim/plugin 폴더 아래의 preview 관련 폴더로 이동해보면 아래와 같은 파일이 보일 겁니다.

kkamagui@ubuntu:~/.vim/plugin/vim-markdown-preview/stylesheets$ ls
github.css  safari-reader.css  simple-print.css

여기서 github.css를 자신의 입맛대로 바꾸거나, 아니면 여기에 css 파일을 복사하고, plugin 폴더 아래에 있는 vmp.vim 파일을 수정해도 됩니다. 파일을 열어서 23번 라인 근처를 보시면 stylesheet를 지정하는 부분이 보이는데요, 요 부분을 수정해줍니다. 저는 application.css 파일을 사용하고 있어서 요걸 지정해줬습니다.

 22 if !exists('g:VMPstylesheet')
 23     let g:VMPstylesheet = 'application.css'
 24 endif

자, 다 변경했으면 이제 다시 Command Line에서 :Mm을 입력해보겠습니다. 그러면, 새로운 페이지가 열리면서 지정한 CSS가 적용된 화면을 볼 수 있을 겁니다. ^^;;;

마크다운 덕에 재미있는 일을 많이 해보는군요. ;) 텍스트로 만들어진 문서를 작성하는 데는 마크다운도 괜찮은 선택인 것 같습니다. 그림이 들어가야 한다면... 그림을 어디 올려서 링크를 걸어야 하는 점이 약간 불편하긴 한데요, 그래도 링크만 있다면 그림을 넣는 건 편리하기 때문에 어떻게든 될 것 같네요.

우분투에서 루비 온 레일즈를 이용해서 이것 저것 삽질하고 있습니다. ^^;;;; 아무래도 처음하다보니 이것저것 문제가 많은데요. 이번에는 만든 예제를 릴리즈하려고 bundle package를 하다보니 mysql2 관련 오류를 만났습니다. ㅠㅠ

kkamagui@kkamagui-VirtualBox:~/project/blog$ sudo gem install mysql2 -v '0.3.11'Building native extensions.  This could take a while...
ERROR:  Error installing mysql2:
        ERROR: Failed to build gem native extension.

        /usr/bin/ruby1.8 extconf.rb
checking for rb_thread_blocking_region()... no
checking for rb_wait_for_single_fd()... no
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lm... yes
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lz... no
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lsocket... no
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lnsl... yes
checking for mysql_query() in -lmysqlclient... no
checking for main() in -lmygcc... no
checking for mysql_query() in -lmysqlclient... no
*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of
necessary libraries and/or headers.  Check the mkmf.log file for more
details.  You may need configuration options.

Provided configuration options:
        --with-opt-dir
        --without-opt-dir
        --with-opt-include
        --without-opt-include=${opt-dir}/include
        --with-opt-lib
        --without-opt-lib=${opt-dir}/lib
        --with-make-prog
        --without-make-prog
        --srcdir=.
        --curdir
        --ruby=/usr/bin/ruby1.8
        --with-mysql-config
        --without-mysql-config
        --with-mysql-dir

역시나 해결책은 구글신이 알려주셨습니다. ㅠㅠ 구글신 쵝오 ㅠㅠ)-b (http://railsforum.com/viewtopic.php?id=40776)
아래처럼 libmysqlclient-dev 패키지를 설치하면 깔끔하게 해결됩니다.

sudo apt-get install libmysqlclient-dev

아흑... 뭐라도 하나 제대로 되야할텐데... 쉽지 않네요 ㅠㅠ

우분투(Ubuntu)에서 루비 온 레일즈(Ruby on Rails)버전을 3.2.1로 업그레이드한 뒤에, rails server를 실행했더니 아래와 같은 오류가 발생했습니다. OTL... 정말 이거 원 쉬운 게 하나도 없군요. ㅠㅠ

kkamagui@ubuntu:~/rails/blog/script$ rails server
/usr/lib/ruby/gems/1.8/gems/execjs-1.3.0/lib/execjs/runtimes.rb:50:in `autodetect': Could not find a JavaScript runtime. See https://github.com/sstephenson/execjs for a list of available runtimes. (ExecJS::RuntimeUnavailable)
    from /usr/lib/ruby/gems/1.8/gems/execjs-1.3.0/lib/execjs.rb:5

역시 구글을 검색했더니 아래와 같은 해결책을 하사해주셨습니다.(http://stackoverflow.com/questions/6282307/rails-3-1-execjs-and-could-not-find-a-javascript-runtime)

In your Gemfile

write this

gem 'execjs'
gem
'therubyracer'

and then run

bundle install

everything works fine for me :)


역시 구글은 짱인 것 같아요. ㅠㅠ)-b
요 근래 Ruby on Rails로 만들어 보고 싶은 게 있어서 Rails를 좀 보고 있습니다. 아직 잘은 모르지만 그 심플함과 강력함에 깜짝 놀라고 있는데요, 우분투(Ubuntu)에 깔려있는 레일즈(Rails)버전이 2.3 버전대라 3.0 버전 이상으로 올라가고 싶어서 레일즈 버전을 올렸습니다.

레일즈 버전을 올리는 방법은 아래와 같이 하면 됩니다. ;)
sudo apt-get install ruby-full rubygems
sudo su -
export REALLY_GEM_UPDATE_SYSTEM=true
gem update --system
exit
gem install rails

레일즈 버전은 깔끔하게 올라갔는데, 문제는 그 뒤더군요. 예제를 따라한다고 rails new blog를 입력하는 순간... 아래와 같은 오류가 발생하면서 더이상 진행이 안되었습니다. OTL...
/usr/bin/ruby1.8 extconf.rb
checking for sqlite3.h... no
sqlite3.h is missing. Try 'port install sqlite3 +universal' or 'yum install sqlite3-devel'
*** extconf.rb failed ***

Could not create Makefile due to some reason, probably lack of necessary libraries and/or headers. Check the mkmf.log file for more details. You may need configuration options.

그래서 이걸 해결할려고 구글신에게 여쭈었더니... 아래와 같이 하면 된다고 알려주시더군요. 역시 구글신 쵝오... ㅠㅠ(http://stackoverflow.com/questions/3458602/sqlite3-ruby-install-error-on-ubuntu)
sudo apt-get install libsqlite3-dev

아아... 역시 구글은 최고인 것 같아요... OTL...
맡고 있는 일의 특성상 텍스트 파일에서 데이터 추출하여 패턴을 분석하는 일이 종종 있습니다. 특히 지금이 딱 그런 시즌인데요, 오늘은 이상하게 텍스트 파일을 열자마자 엑셀말고 다른 방법을 찾아야겠다는 생각이 들더라구요. ^^;;; 그래서 틈틈이 연습했던 루비(Ruby) 언어를 사용해서 한 번 해봐야겠다고 생각했습니다.

그.런.데... 루비를 써야겠다고 말하고 실행을 옮기려던 순간... 옆의 상사가 그러더군요.

"C로도 할 수 있는데...."

예~, 맞습니다. 물론 C로도 할 수 있지요. 다만... 루비를 쓰면 문자열 처리가 편리하고 큐와 리스트 자료구조, 정렬 등등의 기능을 좀더 편하게 쓸 수 있습니다. 뭐, 이런 빵빵한 지원이 루비같은 스크립트 언어의 강점 아니겠습니까? ^^;;; 그리고 코딩하기도 편하고 마음도 가볍고 말이죠. ㅎㅎ

이런 설명을 하려고 하는 찰나.... 이런 말이 다시 들렸습니다.

"C로도 할 수 있는데, 왜 시간 낭비를 하지...?"

아아아아아아아아아아아아아아아아아아아아앍~!!!! 정말 믿고 싶지 않은 이야기에요. ㅠㅠ 저 말을 듣고 이게 꿈인가 싶었습니다. 상사도 저랑 같은 생각을 하고 있을 줄 알았거든요. ㅠㅠ 그런데 시간 낭비라니요. ㅠㅠ 목적에 맞는 언어를 택해서 작업을 편하게 하려고 한게 시간 낭비라니... 이런게 시간 낭비면 항상 우리는 오래된 돌도끼 같은 도구를 쓰면서 몸으로 때우며 묵묵히 작업을 반복해야 하는 건가요? 어휴... 아무리 하드웨어가 강한 회사라지만... 이래서야 원... ^^;;;;;

스크립트 언어를 배우는 건 절대 시간 낭비가 아닙니다~!!!
그리고 새로운 것을 배우고 시도하는 것을 막는 건 프로그래머의 앞 길을 막는 겁니다.


쓸쓸한 날씨처럼 기분도 쓸쓸하네요. ^^;;;;


아시는 분은 다 아시겠지만, 티스토리에는 텍스트에 예쁜 박스를 씌워주는 글상자 기능이 있습니다. 바로 아래처럼 말이지요 ;)

이것이 바로 글상자입니다. ;)

제가 글상자를 좀 좋아하는지라 파일 목록이나 기능 목록을 나열하면서 강조할 때 종종 쓰는데요, 쓸때는 좋은데 블로그의 스킨을 바꾸고나니 살짝 문제가 있더라구요. ㅠㅠ

블로그의 스킨을 바꾸면 글자의 기본 색도 바뀝니다. 그런데 글상자는 그대로라서 지금처럼 검은 블로그 스킨을 사용하면 밝은 색 글상자 내부에 글자가 잘 보이지 않습니다. ㅠㅠ 그렇다고 안쓰기도 뭐하고... 그래서 제 블로그의 글들을 모두 긁어서 소스에 글상자가 있는지 여부를 판단하는 루비 스크립트를 만들었습니다.

코드는 아주 간단하구요, 직접 블로그 페이지에 접근한 다음 글상자를 사용하면 꼭 들어가는 "background-color: rgb" 문자열을 찾도록 했습니다. 아래는 이러한 방식으로 동작하는 루비 코드입니다. ;)


위의 코드를 저장하여 ruby로 실행하면 output.txt 파일에 결과가 저장됩니다(어휴 이거 원 생각보다 엄청 많군요 ㅠㅠ). 스프링노트에서 블로그로 내보낸 글이 거의 절반 이상인데... 이건 어떻게 처리해야할 지 암담하네요. 그냥 다시 밝은 스킨으로 돌아갈까나... ㅠㅠ

그럼 좋은 밤 되세요 ;)

연휴에 블로그를 돌아다니다가 루비로 간단한 웹서버를 만들어보면 어떨까하는 생각이 들었습니다. 그래서 참고 자료를 찾아보고 있었는데... MSDN 블로그(여기)에서 루비로 만든 웹서버를 찾았습니다. @0@)-b 그것도 무려 70줄짜리~!!!

물론, GET 밖에는 처리하지 못하는 초 간단한 웹서버지만 일단 루비 언어(Ruby)의 간결함과 강력함을 확인하는데는 그만인 것 같습니다. ^^;;; 저도 비슷한 역할을 하는 웹서버를 C++로 작성해봤는데, 문자열 처리하고 경로 찾는 부분이 거의 절반이고, 소켓 연결을 관리하는 코드가 절반이었습니다. ㅠㅠ

그런데, 루비로 만든 웹 서버는 그냥 몇 줄에 다 처리가 가능하군요. @0@)-b... 제가 예전에 C++로 만든 웹서버 수준으로 맞춘다면 40줄 미만으로 끝날듯도... 쿨럭..;;;; ㅠㅠ 

좋은 참고 자료가 될 것 같아서 까먹기 전에 링크와 코드를 남겨둡니다. ;)
(정말 편하기는 짱이로군요. ㅠㅠ)

require 'socket'
class HttpServer
  def initialize(session, request, basePath)
    @session = session
    @request = request
    @basePath = basePath
  end

  def getFullPath()
    fileName = nil
    if @request =~ /GET .* HTTP.*/
      fileName = @request.gsub(/GET /, '').gsub(/ HTTP.*/, '')
    end
    fileName = fileName.strip
    unless fileName == nil
      fileName = @basePath + fileName
      fileName = File.expand_path(fileName, @defaultPath)
      fileName.gsub!('/', '\\')
    end
    fileName << "\\index.html" if  File.directory?(fileName)
    return fileName
  end

  def serve()
    @fullPath = getFullPath()
    src = nil
    begin
      if File.exist?(@fullPath) and File.file?(@fullPath)
        if @fullPath.index(@basePath) == 0 #path should start with base path
          contentType = getContentType(@fullPath)
          @session.print "HTTP/1.1 200/OK\r\nServer: Makorsha\r\nContent-type: #{contentType}\r\n\r\n"
          src = File.open(@fullPath, "rb")
          while (not src.eof?)
            buffer = src.read(256)
            @session.write(buffer)
          end
          src.close
          src = nil
        else
          # should have sent a 403 Forbidden access but then the attacker knows that such a file exists
          @session.print "HTTP/1.1 404/Object Not Found\r\nServer: Makorsha\r\n\r\n"
        end
      else
        @session.print "HTTP/1.1 404/Object Not Found\r\nServer: Makorsha\r\n\r\n"
      end
    ensure
      src.close unless src == nil
      @session.close
    end
  end

  def getContentType(path)
    #TODO replace with access to HKEY_CLASSES_ROOT => "Content Type"
    ext = File.extname(path)
    return "text/html"  if ext == ".html" or ext == ".htm"
    return "text/plain" if ext == ".txt"
    return "text/css"   if ext == ".css"
    return "image/jpeg" if ext == ".jpeg" or ext == ".jpg"
    return "image/gif"  if ext == ".gif"
    return "image/bmp"  if ext == ".bmp"
    return "text/plain" if ext == ".rb"
    return "text/xml"   if ext == ".xml"
    return "text/xml"   if ext == ".xsl"
    return "text/html"
  end
end

def logger(message)
  logStr =  "\n\n======================================================\n#{message}"
  puts logStr
  $log.puts logStr unless $log == nil
end

basePath = "d:\\web"
server = TCPServer.new('XXX.XXX.XXX.XXX', 9090)
logfile = basePath + "\\log.txt"
$log = File.open(logfile, "w+")

loop do
  session = server.accept
  request = session.gets
  logStr =  "#{session.peeraddr[2]} (#{session.peeraddr[3]})\n"
  logStr += Time.now.localtime.strftime("%Y/%m/%d %H:%M:%S")
  logStr += "\n#{request}"
  logger(logStr)

  Thread.start(session, request) do |session, request|
    HttpServer.new(session, request, basePath).serve()
  end
end
log.close

그럼 좋은 하루 되세요 ;) 
요즘 루비 언어(Ruby Language)를 이용해서 장난감을 만드는 재미에 푹~ 빠져 있습니다. ^^;;; 아무래도 내장 기능 자체가 강력하고 다양한 모듈들 때문에 별다른 부담없이 시작할 수 있어서, 이것 저것 재미삼아 만들기가 좋네요. ;)

사실 장난감이라고 해봤자 그냥 언어를 익히는 수준 정도라서 보잘것 없지만... 이번엔 나름대로 쓸모있는 걸 만들어놔서 올려봅니다. ^^;;; 이번에 공을 들여 만든 것은 바로... 멜론 다운로드 폴더를 정리해주는 프로그램입니다. @0@)-b

멜론은 벅스, 도시락과 더불어 많이 이용되고 있는 음악 스트리밍/다운로드 프로그램인데요. MP3를 다운로드하면 앨범 단위로 다운로드하던 개별 파일로 다운로드하던 그대로 다운로드 폴더에 주욱 쌓입니다. 그래서 조금만 방심하면 여러 파일이 뒤섞여서 충격과 공포의 도가니(?)로 변하지요. ㅠㅠ

그래서 마구 다운로드하되 파일이 Artist 별로 정리되어 폴더에 저장되면 좋겠다는 생각이 들어서, 파일을 폴더 별로 정리하는 루비 프로그램을 만들었습니다. 아이디어는 간단하구요, 멜론에서 저장하는 파일 형식이 아래처럼 Artist-Track Number-Song.mp3의 순서라 여기서 Artist 부분을 잘라내 디렉터리로 만들고 파일을 해당 디렉터리로 옮기되 Artist를 제외한 나머지로 파일명을 바꾸는 겁니다. ^^;;;

2NE1-04-Hate You.mp3

자, 그럼 아래 루비 프로그램 나갑니다. ;)



위의 코드를 arrange.rb로 저장한 뒤, 멜론 다운로드 폴더로 이동한 다음 아래와 같이 입력하시면 파일 정리가 순식간에 끝납니다. ^^;;; 배치 파일로 만들면 더 편리하게 실행할 수 있습니다(배치 파일과 arrange.rb 파일 모두 첨부 파일로 올려두었습니다). 물론 루비를 설치하지 않으셨다면 루비를 먼저 설치하셔야겠지요. ;) 루비는 http://www.ruby-lang.org/ko/에서 다운로드하여 설치할 수 있습니다.

ruby arrange.rb

아래는 충격과 공포의 도가니(?)에서 벗어나 깔끔해진 멜론 폴더입니다. ;)



첨부 파일


ps 1) Artist와 Track Number를 구분하는 규칙이 - 이기 때문에 Artist 명에 -이 들어가 있다면 정상적으로 분리가 되지 않습니다. ㅠㅠ
ps 2) 다음 버전은 MP3의 Tag 정보를 읽어서 분리하도록 만들어야 겠어요. ㅠㅠ

루비 개발 툴로는 이클립스를 비롯해서 여러가지가 있겠지만 저는 NetBeans를 선택했습니다. 그동안 이클립스를 써와서 좀 다른 툴을 써보고 싶었거든요. ^^;;; 실제로 써보니 NetBeans도 이클립스만큼 쓸만하더군요. >ㅁ<)-b

우분투에서 NetBeans를 설치하는 방법은 아주 간단합니다. 시작 메뉴의 "우분투 소프트웨어 센터"를 클릭하여 소프트웨어 센터를 띄운 다음 아래처럼 검색창에 NetBeans를 입력하면 됩니다. 저는 이미 설치가 되어 있어서 제거로 표시되는데, 실제로 다른 분들은 설치로 표시될 겁니다. ^^;;;

<NetBeans 설치 방법>


NetBeans를 설치하고 나면 이제 Ruby 개발을 위해 플러그인을 설치해야 합니다. NetBeans 플러그인을 설치하려면 먼저 NetBeans를 실행해야 하는데, 시작 메뉴의 "개발" 메뉴를 보면 아까 설치한 NetBeans가 표시될 것입니다. 이를 실행하면 아래와 같은 화면이 표시되는데, 화면의 오른쪽에 빨간 사각형으로 표시된 "Install Plugins"을 클릭합니다.

<루비 개발용 플러그인 설치 화면>


클릭하고나면 플러그인 설치 화면이 표시되는데 여기에 ruby를 입력하면 "Ruby and Rails" 항목이 표시됩니다. 이 항목을 설치했으면 NetBeans를 다시 시작한 뒤에 "File" 메뉴의 "New Project" 메뉴를 선택합니다. 그러면 프로젝트 항목에서 Ruby가 표시되며 Ruby 프로젝트를 만들어서 프로그래밍을 할 수 있습니다. ^^


그럼 좋은 하루 되세요 ^^


새로운 프로젝트를 앞두고 있어서 얼마 전부터 그동안 프로젝트를 하면서 가장 불만이었던 것이 무엇인가를 고민하고 있었습니다(그러고 보니 작년부터 지금까지 프로젝트가 끊이질 않는군요. ㅠㅠ 쉴 시간도 없이 계속 달려왔는데 또 달리라니... ㅠㅠ). 그러다가 문득 생각난게 반복되는 작업이 너무 많다는 것이었습니다. 개발하고 테스트 돌리고 분석하고 디버깅하는 사이클을 매번 반복하는데... 분석하고 디버깅하는 시간은 그렇다 치지만 개발하고 테스트를 돌리는데 공수가 드는건 뭔가 잘못됬다는 생각이 들더군요.

개발하는 것에 비하면 테스트 돌리는 건 일도 아니지만, 실제로 여러 옵션을 주게 되어 있어서 귀찮았거든요. 실제로 이런 옵션들 때문에 팀원들 중에서는 지금도 통합 테스트를 제대로 못 돌리는 사람이 있을 정도니까요. ^^;;;; 그래서 테스트를 좀 자동화하고 편하게 하고자 쉽게 프로그램을 만들 수 있는 스크립트 언어에 다시 눈을 돌리게 되었습니다. 물론 배치 파일로도 할 수 있지만, 이왕이면 다홍치마라고 이 기회에 새로운 언어를 배우고 싶었습니다. ;)

예전에도 이런 고민을 한번 했는데 그때 파이썬(Python)이라는 언어가 좋다는 이야기를 듣고 잠시 배웠습니다. 실제로 써보니 C와 궁합도 좋고 여러모로 강력하더군요. >ㅁ<)-b 그런데, 들여쓰기를 코드 블록으로 사용하는 점과 클래스를 만들 때 Self 키워드를 사용하는 부분이 저와 맞지 않아서 그렇게 많이 쓰지는 못했습니다. ㅠㅠ

<루비(Ruby) 사이트 - http://www.ruby-lang.org/ko/>


그래서 이번에는 좀 C/C++ 스타일과 비슷한 스크립트 언어를 찾기로 했는데, 이때 딱 눈에 띈게 바로 루비(Ruby)였습니다. 루비의 문법을 보니 C/C++과 상당이 비슷해서 조금만 익숙해지니 이것 저것 해볼 수 있더라구요. ^^;;; 거기다가 라이브러리도 꽤 많아서 완전 제 마음에 들었습니다. ^^)/~ 루비 언어를 만든 마츠모토 유키히로씨가 스트레스가 없는 쉬운 프로그래밍 언어를 목표로 했다고 하던데 정말 그런 느낌이 들었습니다(물론 스크립트 언어라서 제가 그렇게 느낀 걸수도 있습니다만... 쿨럭...;;;).

지금까지는 아이디어가 떠오르면 C나 C++로 코딩하곤 했는데, C는 뭐랄까요... 왠지 마음을 단단히 먹고 시작해야 할 것 같은데, 루비는 그런 느낌도 없고 편하니 좀더 쉽게 여러가지를 해볼 수 있지 않을까 생각합니다. ^^;;;

그럼 즐거운 루비 라이프를 위해 화이팅~!!

ps)  며칠 해본 결과 상당히 마음에 들던데... 
      이러다가 MINT64 OS에 루비를 올리는 날이 올지도 모르겠군요... ㅠㅠ

+ Recent posts