'Programing'에 해당되는 글 2건

  1. Ruby의 Symbol 이해하기 2007/11/11
  2. Java Application을 NT Service로 2007/06/24

Ruby의 Symbol 이해하기

from Programing 2007/11/11 23:05
최근 Ruby와 Rails를 공부하고 있는데, Ruby의 Symbol이라는 게 잘 이해가 되지 않았다.
기존에 내가 배웠던 언어들 중에는 그와 비슷한게 없었던 터라 도무지 감이 안 잡혔다.
구글링 결과 대략 감을 잡았으니, Ruby Symbol의 정체에 대해 간단히 정리해본다.

String vs. Symbol

puts :hello  #symbol
puts "hello"   #string

위의 두 문장 모두 'hello'라는 문자열을 출력한다. 이런 이유로 Symbol을 String의 오리타입(duck type) 클래스로 오해하기도 한다. 하지만, 아래 코드를 보면 알겠지만, Symbol은 절대로 String이 아니다.
puts :hello.size  # NoMethodError
puts :hello[0,2]  # NoMethodError
puts "hello".size  #5
puts "hello"[0,2]  # "he"

Symbol이 String의 사촌 쯤으로 오해받는 것은 Symbol을 immutable string 용도로 많이 사용하기 때문이다. 나처럼 Lisp 언어에 대한 경험이 없는 사람이라면, 대충 예제코드들을 보면서 그렇게 생각할 가능성이 매우 높다.

Java등의 언어에서는 String이 immutable Class이므로 Hash의 키로 사용했을 경우 그다지 문제될 것이 없지만, Ruby에서는 String이 mutable class이므로 Hash의 키로 쓰일 때, 키로 쓰인 객체의 값이 변경될 경우 rehash 메소드를 호출해줘야 하는 경우가 생긴다. 따라서 Ruby에서는 가능하면 Hash의 키로 String대신 Symbol을 쓰는 것을 선호한다. 그러니 나 같은 놈은 처음부터 Symbol = Immutable String 으로 이해하고는 그 뒤부터는 미궁으로 빠져버린다.

Symbol을 그 정의대로 '이름을 가진, 그리고 그 이름에 대해서 유니크(unique)한 객체'이다. String이 따옴표로 둘러쌓인 문자열로 표기되듯이, Symbol은 :name의 형태로 표기되며, name이 문자열로 표기될 수 있지만 그 자체는 String이 아닌 Symbol객체이다. 그리고 아래 코드에서 보여지듯이, 특정 이름을 갖는 Symbol 객체는 유일하다.
puts :hello.class   # Symbol
puts "hello".class   # String
puts :hello.object_id == :hello.object_id   # true
puts "hello".object_id == "hello".object_id   #false


Symbol의 용도

그렇다면 Symbol은 언제 사용하는 것이 좋을까?
Ruby의 String이 mutable 객체이므로, 성능상의 이유로 Symbol이 immutable string의 대체물로 사용되곤 하지만, Symbol은 garbage collect가 되지 않으므로 자칫하면 메모리 누수가 발생할 수 있음을 유의해야 한다. 대충 아래와 같은 용도로 사용하는 것이 추천된다.
  1. 메소드의 argument list에 옵션 키워드의 이름
    link_to 'Show', :action=>'show', :id= product
  2. C의 enum와 같은 값을 표현할 때
    /* C code*/
    enum BugStatus { OPEN, CLOSED };
    BugStatus original_status = OPEN;
    BugStatus current_status = CLOSED;

    # Ruby

    original_status
    = :open
    current_status = :closed
  3. Hash의 키 이름
    foo = {
    :host => 'localhost',
    :port => 80 }

특히 위 3번의 예는 String을 사용하는 아래의 예보다, Symbol이 사용자 정의 식별자(user defined identifier)로 사용됨으로써 코드의 의도가 명확히 드러난다 점에서도 더 낫다.
foo = {  # String을 사용한 경우, 속성-값의 관계가 덜 명확해 보인다.
'host' => 'localhost',
'port' => 80}


Reference


2007/11/11 23:05 2007/11/11 23:05
Tag : ,
예전 블로그에 있던 글인데 나중에 참고할 일이 있을지 모르니 복원한다.
 (기존URL: http://oddpoet.net/2007/06/java-apps-as-nt-service)
----------
특정 Application을 background process로 데몬처럼 실행하고 싶을 때, Windows NT 계열의 OS에서는 NT service로 만드는 것을 생각해 볼 수 있을 것이다. 하지만 Java Application의 경우에는 기본적으로 NT service를 wrapping 해주는 기능이 없다. Java Service Wrapper 를 사용하는 방법도 있지만, 단순히 Windows OS계열에서의 자동 background 실행이 목적이라면 JavaService를 사용하는 것이 더 편하다.

1. JavaService 구하기
우선 http://javaservice.objectweb.org에 서 JavaService를 다운로드 받는다(현재 최신버전은 2.0.10). 압축을 풀면 2개의 실행파일(JavaService.exe, JavaServiceDebug.exe)와 예제 batch script파일들이 있을 것이다. 제일 중요한 건 JavaService.exe이다. (JavaServiceDebug.exe는 이름 그대로 디버그 용도의 실행파일이다.) 이 실행파일이 우리의 Java App를 NT 서비스로 Wrapping 해주게 된다. 기본 사용법은 JavaService.exe -help 명령으로 확인할 수 있다.

2. Java Application을 NT Service로 등록
JavaService -help install 명령으로 install 명령에 대한 help를 확인해보자.
JavaService -install 서비스_이름 JVM_라이브러리 [JVM option] -start 시작_클래스 [-method 시작_메소드]
필수 파라메터는 위와 같이 서비스_이름 , JVM_라이브러리, 시작_클래스 이다. ‘서비스_이름’은 NT 서비스로 등록될 서비스 이름을 말한다. ‘JVM_라이브러리’는 JRE의 jvm.dll의 경로(JRE/bin/server에 있음)를 쓰면 된다. ‘시작_클래스’는 말그대로 application의 entry point가 될 class를 지정하는 것이다. public static void main(String [])가 있는 Class 이름을 지정하면 되겠다.
 JavaService -install “MyApp Service” $JAVA_HOME$/bin/server/jvm.dll
       -start net.oddpoet.MyApp
서비스 이름 중간에 공백을 쓰려면 위와 같이 따옴표(”)로 싸야 한다. 또한 jvm.dll의 경로는 절대경로로 써야한다. 위 명령을 수행하는 디렉토리에 대한 상대경로로 쓰면, 실제 NT Service로 JavaService가 실행될 때의 작업경로와 다르기 때문에 서비스가 정상적으로 수행되지 못한다. 마찬가지로 entry point가 될 class는 환경변수의 CLASS_PATH에 있거나, -Djava.class.path 옵션을 JVM option으로 지정해주어야 한다.

추가적인 명령행 옵션은 다음과 같다.
-description service_desc
    서비스에 대한 설명.
-current current_dir
    서비스의 작업 디렉토리 지정
-method start_method
    서비스 시작시 실행될 start_class의 메소드(default:main). ‘-start start_class’ 바로 다음에 와야한다.

Java Application를 excutable jar로 만들었다면, 다음과 같이 NT 서비스로 등록할 수 있다.
 JavaService -install "MyApp Service" $JAVA_HOME$/bin/server/jvm.dll
   -Djava.class.path=myApp.jar -start net.oddpoet.MyApp -current D:/myapp
   -description "Example of JavaService"
NT 서비스로 정상적으로 등록되었는지는 다음 명령으로 확인할 수 있다.
(참고로 윈도우2000에는  sc.exe가 없다. XP나 윈2003부터 제공되는 툴이다.)
sc query "MyApp Service" 

3. NT Service에서 제거

NT Service로 등록된 Java app.를 제거하는 방법은 다음과 같다.
JavaServcie -uninstall "MyApp Service"
등록할 때 사용했던, 서비스 이름을 써야한다는 점에 유의하자. 만약 현재 그 서비스가 실행중이라면, 서비스를 먼저 종료시켜야만 서비스에서 정상적으로 제거된다. 스크립트로 만든다면 위의 uninstall 명령 앞에 다음과 같이 서비스를 stop시키는 명령을 먼저 실행시키면 된다.
 sc stop "MyApp Service"
2007/06/24 00:58 2007/06/24 00:58
Tag : ,