5월 172014
 

여러 삽질을 하면서 알아낸 정보! 시작은 아래의 에러 메시지로부터 시작되었다. mysql2 gem을 성공적으로 설치하고 기쁨에 잠겨있던 필자는 즐겁게 rails 서버를 켰다. 문제없이 서버가 켜졌다. 하지만 scss파일을 가져오는데 실패한 것이였다. 윈도우에는 한 번에 가는 일이 없는 것 같다. 에러메시지는 아래와 같다.

ArgumentError at / different prefix: "C:/" and "G:/*****/******/app/assets/stylesheets" (in G:/*****/******/app/assets/stylesheets/home.css.scss)

보아하니 디렉토리 앞의 prefix(여기서는 드라이브)가 다르다는 에러였다. 왜 그렇게 만들었는지는 모르겠지만(아마도 보안 문제일까??) 구글링을 해본 결과 크게 세가지의 해결방법이 있었다. 물론 아래 방법 이외에도 있을 수 있다.

1. gem과 같은 드라이브로 프로젝트를 옮긴다.

용량이 없다거나 관리 문제가 없다면 이 방법이 제일 간단한 방법인 것 같다. 보통 루비가 설치된 드라이브로 옮기면 되겠다. 같은 드라이브라면 어디에 놓던 문제 없다.

2. symbolic link를 이용하는 방법

윈도우에는 심볼릭 링크 개념이 없었지만 ntfs로 넘어오면서 비슷한 역할을 하는 명령어가 생겼다. 아래의 명령을 실행한다. (만약 실행이 안된다면 윈도우 버젼이 낮아서 그런 것이니 [1]에 들어가서 확인해보자)

mklink /j c:\application g:\*****\application

3. gem을 프로젝트 폴더에 설치하는 방법

아래와 같이 bundle install을 실행할 때 옵션을 붙여서 실행한다. 그러면 문제 없이 사용할 수 있다.

bundle install --path .bundle

참고 자료

[1] Stackoverflow(Error “different prefix:” with Active_Admin gem), http://stackoverflow.com/questions/7740002/error-different-prefix-with-active-admin-gem

5월 112014
 

윈도우에서 아래와 같은 에러가 발생하는 경우 루비 실행파일이 mysql connector 라이브러리인 “libmysql.dll”을 찾지 못해서 발생할 가능성이 높다.

126: The specified module could not be found.   - C:/Ruby193/lib/ruby/gems/1.9.1/gems/mysql2-0.3.15/lib/mysql2/mysql2.so

mysql가 설치된 폴더의 lib폴더에서 “libmysql.dll”을 windows의 system 폴더(플랫폼x86/x64 주의)에 복사하거나 루비가 설치된 폴더의 bin 폴더(예: c:\ruby193\bin)에 복사를 하도록 하자. 그러면 문제가 해결된다. 자세한 내용은 [1]을 참조하자.

 

참고 자료

[1] http://stackoverflow.com/questions/4241068/rubymine-3-0-setup-on-windows-7

5월 102014
 

모든 것은 mysql서버를 설치하지 않고 rails를 하려고 한 것에서 시작되었다. 아래와 같은 문제의 경우, 사용하는 ruby의 플렛폼(x86/x64 여부)와 관련된 문제다. 에러 내용이 link 에러여서 좀 더 유심히 보았다. 그랬더니 얻은 결론! mysql connector는 x64 버젼이고 루비는 x86이였던 것이다. 작동 플렛폼이 다르니 당연히 발생하는 문제였다. 아이구… 어쨋든, 여기에서 x86버젼 커넥터를 받아서 설치하여서 경로를 약간 수정해 다시 실행하였더니 성공적으로 설치되었다.

 

1. 해결 방법

1) mysql connect (x86)버젼을 다운로드 받는다.

2) 아래 명령을 실행한다.

C:\Ruby193\bin>gem install mysql2 --platform=ruby -- '--with-mysql-lib="C:\Program Files (x86)\MySQL\MySQL Connector C 6.1\lib" --with-mysql-include="C:\Program Files (x86)\MySQL\MySQL Connector C 6.1\include"'

 

2. 에러 메시지

C:/Ruby193/bin/ruby.exe extconf.rb --width-mysql-lib="C:\Program Files\M
ySQL\MySQL Connector C 6.1\lib" --width-mysql-include="C:\Program Files\MySQL\My
SQL Connector C 6.1\include" --with-mysql-dir="C:\Program Files\MySQL\MySQL Conn
ector C 6.1"
checking for ruby/thread.h... no
checking for rb_thread_blocking_region()... yes
checking for rb_wait_for_single_fd()... yes
checking for rb_hash_dup()... yes
checking for rb_intern3()... yes
-----
Using --with-mysql-dir=C:\Program Files\MySQL\MySQL Connector C 6.1
-----
checking for main() in -llibmysql... yes
checking for mysql.h... yes
checking for errmsg.h... yes
checking for mysqld_error.h... yes
-----
Setting rpath to /lib
-----
creating Makefile

make
generating mysql2-i386-mingw32.def
compiling client.c
client.c: In function 'finish_and_mark_inactive':
client.c:513:3: warning: ISO C90 forbids mixed declarations and code
compiling infile.c
compiling mysql2_ext.c
compiling result.c
result.c: In function 'rb_mysql_result_fetch_fields':
result.c:415:35: warning: comparison between signed and unsigned integer express
ions
linking shared-object mysql2/mysql2.so
client.o: In function `nogvl_connect':
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/client.c:157: undef
ined reference to `mysql_real_connect@32'
client.o: In function `nogvl_init':
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/client.c:146: undef
ined reference to `mysql_init@4'
client.o: In function `set_ssl_options':
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/client.c:1102: unde
fined reference to `mysql_ssl_set@24'
client.o: In function `mysql_client_options':
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/client.c:744: undef
ined reference to `mysql_options@12'
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/client.c:748: undef
ined reference to `mysql_error@4'
client.o: In function `rb_mysql_info':
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/client.c:271: undef
ined reference to `mysql_info@4'
client.o: In function `rb_mysql_client_warning_count':
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/client.c:261: undef
ined reference to `mysql_warning_count@4'
client.o: In function `nogvl_do_result':
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/client.c:375: undef
ined reference to `mysql_store_result@4'
client.o: In function `rb_mysql_client_more_results':
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/client.c:947: undef
ined reference to `mysql_more_results@4'
client.o: In function `nogvl_select_db':
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/client.c:887: undef
ined reference to `mysql_select_db@8'
client.o: In function `nogvl_ping':
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/client.c:918: undef
ined reference to `mysql_ping@4'
client.o: In function `rb_mysql_client_thread_id':
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/client.c:880: undef
ined reference to `mysql_thread_id@4'
client.o: In function `rb_mysql_client_last_id':
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/client.c:849: undef
ined reference to `mysql_insert_id@4'
client.o: In function `nogvl_read_query_result':
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/client.c:362: undef
ined reference to `mysql_read_query_result@4'
client.o: In function `rb_mysql_client_server_info':
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/client.c:809: undef
ined reference to `mysql_get_server_version@4'
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/client.c:810: undef
ined reference to `mysql_get_server_info@4'
client.o: In function `rb_mysql_client_info':
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/client.c:777: undef
ined reference to `mysql_get_client_version@0'
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/client.c:778: undef
ined reference to `mysql_get_client_info@0'
client.o: In function `rb_mysql_client_real_escape':
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/client.c:667: undef
ined reference to `mysql_real_escape_string@16'
client.o: In function `finish_and_mark_inactive':
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/client.c:520: undef
ined reference to `mysql_free_result@4'
client.o: In function `nogvl_send_query':
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/client.c:339: undef
ined reference to `mysql_send_query@12'
client.o: In function `nogvl_close':
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/client.c:189: undef
ined reference to `mysql_close@4'
client.o: In function `rb_mysql_client_escape':
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/client.c:242: undef
ined reference to `mysql_escape_string@12'
client.o: In function `rb_raise_mysql2_error':
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/client.c:125: undef
ined reference to `mysql_error@4'
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/client.c:126: undef
ined reference to `mysql_sqlstate@4'
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/client.c:135: undef
ined reference to `mysql_errno@4'
client.o: In function `rb_connect':
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/client.c:301: undef
ined reference to `mysql_errno@4'
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/client.c:309: undef
ined reference to `mysql_get_server_version@4'
client.o: In function `rb_mysql_client_store_result':
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/client.c:990: undef
ined reference to `mysql_errno@4'
client.o: In function `rb_mysql_client_next_result':
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/client.c:963: undef
ined reference to `mysql_next_result@4'
client.o: In function `rb_mysql_client_affected_rows':
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/client.c:863: undef
ined reference to `mysql_affected_rows@4'
client.o: In function `rb_mysql_client_async_result':
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/client.c:424: undef
ined reference to `mysql_errno@4'
client.o: In function `rb_mysql_client_abandon_results':
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/client.c:544: undef
ined reference to `mysql_next_result@4'
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/client.c:543: undef
ined reference to `mysql_more_results@4'
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/client.c:552: undef
ined reference to `mysql_free_result@4'
client.o: In function `nogvl_do_result':
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/client.c:373: undef
ined reference to `mysql_use_result@4'
client.o: In function `nogvl_close':
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/client.c:189: undef
ined reference to `mysql_close@4'
client.o: In function `set_charset_name':
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/client.c:1091: unde
fined reference to `mysql_options@12'
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/client.c:1093: unde
fined reference to `mysql_error@4'
client.o: In function `nogvl_close':
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/client.c:189: undef
ined reference to `mysql_close@4'
client.o: In function `init_mysql2_client':
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/client.c:1141: unde
fined reference to `mysql_get_client_info@0'
infile.o: In function `mysql2_set_local_infile':
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/infile.c:114: undef
ined reference to `mysql_set_local_infile_handler'
result.o: In function `rb_mysql_result_count':
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/result.c:592: undef
ined reference to `mysql_num_rows@4'
result.o: In function `rb_mysql_result_fetch_field':
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/result.c:123: undef
ined reference to `mysql_fetch_field_direct@8'
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/result.c:111: undef
ined reference to `mysql_num_fields@4'
result.o: In function `rb_mysql_result_fetch_fields':
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/result.c:411: undef
ined reference to `mysql_num_fields@4'
result.o: In function `nogvl_fetch_row':
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/result.c:102: undef
ined reference to `mysql_fetch_row@4'
result.o: In function `rb_mysql_result_free_result':
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/result.c:76: undefi
ned reference to `mysql_free_result@4'
result.o: In function `rb_mysql_result_fetch_row':
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/result.c:209: undef
ined reference to `mysql_fetch_lengths@4'
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/result.c:211: undef
ined reference to `mysql_num_fields@4'
result.o: In function `rb_mysql_result_each':
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/result.c:512: undef
ined reference to `mysql_fetch_fields@4'
result.o: In function `rb_mysql_result_free_result':
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/result.c:76: undefi
ned reference to `mysql_free_result@4'
result.o: In function `rb_mysql_result_each':
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/result.c:530: undef
ined reference to `mysql_error@4'
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/result.c:547: undef
ined reference to `mysql_fetch_fields@4'
result.o: In function `rb_mysql_result_free_result':
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/result.c:76: undefi
ned reference to `mysql_free_result@4'
result.o: In function `rb_mysql_result_each':
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/result.c:499: undef
ined reference to `mysql_num_rows@4'
result.o: In function `rb_mysql_result_free_result':
C:\Ruby193\lib\ruby\gems\1.9.1\gems\mysql2-0.3.15\ext\mysql2/result.c:76: undefi
ned reference to `mysql_free_result@4'
collect2: ld returned 1 exit status
make: *** [mysql2.so] Error 1


Gem files will remain installed in C:/Ruby193/lib/ruby/gems/1.9.1/gems/mysql2-0.
3.15 for inspection.
Results logged to C:/Ruby193/lib/ruby/gems/1.9.1/gems/mysql2-0.3.15/ext/mysql2/g
em_make.out

 

5월 102014
 

필자의 경우에 회사에서는 MacBook을 이용하고 집에서는 Windows기반의 데스크톱을 이용하고 있다. 회사에는 듀얼모니터가 있기 때문에 작업하는데 딱히 불편함을 느끼지 못 하였다. 하지만 집에는 여분의 모니터가 없고, 이미 데스크톱에 20인치의 듀얼모니터를 이용하고 있기 때문에 데스크톱쪽이 더 효율이 잘 나온다. 물론 집에까지 회사일을 들고와서 하는 것에 대해서는 크게 신경쓰지 말도록 하자. 어쨋든 어차피 회사에서 주로 하는 ruby는 스크립트 언어이고 멀티 플렛폼을 지원하니 집의 윈도우 데스크톱에 ruby를 직접 설치해 보기로 하였다. 필자는 단순히 ruby설치해서 실행시키면 될 것으로 기대했지만, 안타깝게도 설치/설정해야 할 것이 좀 있었다. 아래를 참고해 보도록 하자.

 

1. Ruby 설치

http://rubyinstaller.org/downloads/ 에서 기존 프로젝트에서 사용하던 버젼의 ruby 인스톨 패키지를 설치한다.

 

2. Development Kit(이하 devkit)  설치

몇몇 루비 gem은 네이티브 컴파일을 하기도 하는데 이 경우에 development kit이 필요하다. 해당하는 루비버젼과, 사용자 시스템에 맞는 것을 찾아서 설치 한다.

* 예를들어 json gem의 경우 아래와 같은 에러가 발생하면 devkit를 설치하고 환경변수까지 잡아주어야 한다[1].

ERROR:Error installing json:The'json' native gem requires installed build tools.

* devkit 설치 방법

1) devkit 설치경로: c:\ruby193\devkit

2) ruby 1.9.3 설치경로: c:\ruby193

3) 아래 3개의 명령 실행

c:\ruby193\devkit> ..\bin\ruby dk.rb init

c:\ruby193\devkit> ..\bin\ruby dk.rb review

c:\ruby193\devkit> ..\bin\ruby dk.rb install

* gem 설치시 아래와 같은 에러가 난다면..[2] [3]  (이러한 에러의 발생 이유에 대한 자세한 설명은 [3]를 참조)

1) 여기에서 rebase.exe를 다운로드 받음

2) devkit밑의 bin폴더에 복사 (예:  c:\ruby193\devkit\bin)

3) 아래의 명령을 실행

c:\> cd ruby183\devkit\bin

c:\ruby193\devkit\bin> rebase -b 0x30000000 msys-1.0.dll

 3. Let’s programming!

‘bundle install’ 하고 작업 시작하자! 혹시 mysql에서 또 에러메시지를 본다면 여기, 여기2를 참조하자!!

 

4. 참고 자료


[1] stackoverflow(The ‘json’ native gem requires installed build tools),  http://stackoverflow.com/questions/8100891/the-json-native-gem-requires-installed-build-tools

[2] stackoverflow(Error installing gem: Couldn’t reserve space for cygwin’s heap, Win32 error 487), http://stackoverflow.com/questions/19259272/error-installing-gem-couldnt-reserve-space-for-cygwins-heap-win32-error-487

[3] 아자님의 블로그([MSYS] *** Couldn’t reserve space for cygwin’s heap (0xXXXXXXXX <0xXXXXXXX>) in child, Win32 error 0),  http://azza.tistory.com/152

4월 052014
 
$ cat *.sql | mysql -u <mysql_id> -p <target_database>

cat 명령으로 stdout으로 모든 sql을 출력하고 이를 파이프로 넘겨서 처리하는 방법이다. 찾아 본 방법[1] 중에는 이것이 제일 이해하기 쉽고 간단한듯 하다. mysql의 백업은 *.sql 파일로 나오는데 이를 한 번에 처리하기 위한 방법으로 쓸 수 있겠다.

 

참고자료

[1] http://stackoverflow.com/questions/2458571/run-multiple-sql-files-in-mysql-batch

4월 012014
 

국제반신우표권(이하 반신권)은 우편을 보내는 사람이 답신비용을 지불하고 싶을때 사용할 수 있다. 국내의 경우 단순히 우표를 첨부하면 되지만 외국에서 한국 우표가 통용될리 없다. 따라서 만국우편연합1에 가입한 국가에 한해서 이 반신권을 팔고 그 나라의 우표로 교환해준다. 중요한 점은 이 반신권을 무조건 가입국에서 판매하는 것은 아니라는 것이다2. 그러나 가입국은 반신권을 우표로 바꾸어 주어야 할 의무가 있다고 한다3. 물론 아무 우표로 바꿔주는 것은 아니고 20g 이하 비등기 일반항공우편의 최저가로 바꿔준다. 반신권의 좌측에 스탬프가 찍혀져 있는 것만 정상적인 것으로 인정된다. 아래의 반신권의 경우 “인천우체국”의 스탬프가 찍혀져 있다.

한국에서 발급 받은 국제반신우표권

한국에서 발급 받은 국제반신우표권

여담으로 예전은 한국 반신권이 일본 우표가격보다 적었지만 지금은 환율과 반신권의 가격 상승으로 상황이 달라졌다. 2014년 3월 현재 1450원에 판매하고 있으며 반신권은 800원어치의 우표로 교환 가능하다. 일본에서는 150엔에 판매하고 130엔의 우표로 교환해 준다. 미국의 경우는 $1.15상당의 우표로 교환해준다. 나라마다 상황이 다르고 매년 가격이 달라지기에 확인이 필요하다.

위의 용도 이외에도 일본대학시험 수험표 같은 것을 편지로 보낼 때 결과를 확인하기 위해 첨부해서 보내기도 하며 해외의 우표를 구매하는데에도 이용하기도 한다4. 또 아마추어 무선의 교신 증명서를 받기 위하여 이용하기도 한다5.

국내 우체국에서 구매할 수 있는데 우체국에 재고가 없을 수도 있으니 전화하고 가는 것이 좋다.

 

참고자료


  1. 만국우편연합(Universal Postal Union), http://www.upu.int/en.html
  2. 반신권 판매국 리스트, http://www.upu.int/en/activities/international-reply-coupons/countries-selling-ircs.html
  3. 국제반신권(International Reply Coupon, IRC), http://ko.wikipedia.org/wiki/%EA%B5%AD%EC%A0%9C%EB%B0%98%EC%8B%A0%EA%B6%8C
  4. 국제반신권을 이용한 세계 우표수집법, http://www.cyworld.com/crazy252/3717044
  5. QSL 작성요령,http://hl3enm.com.ne.kr/sangrin3-7.htm
3월 222014
 

※ 이 문서는 Notification 자체에 대해서 설명하고 있는 것이 아니라 Notification을 알고 있다는 가정하에서 만들어야 할 앱이 API Level 11 미만을 지원해야할  경우를 위한 설명이다. Notification 자체에 대한 이해는 [1]을 참조하도록 한다.

안드로이드 Notification을 구현하는 방법은 여러가지가 있는데 하나는 기본 제공하는 양식을 사용하는 방법, 다른 하나는 Custom layout을 이용하여 구현하는 방법이 있다. 이 중에 기본 제공 양식을 사용하는 방법으로 구현을 해 보고자 한다.

하지만 안타깝게도 타겟 플렛폼 버젼이 8(Android 2.2, Froyo)이상으로 해야 했기 때문에 문제가 발생했다. 바로 기본 제공 방법을 사용할 경우에 Notification의 생성자가 deprecated 됬기 때문이다. 즉 사용하지 않는 것이 좋다는 뜻이다. 바로 이 메소드가 문제!

The notification constructor is deprecated

Notification의 생성자 Reference[2]

   빨간 네모박스의 내용과 같이 SDK 11버젼부터는 Notification.Builder를 대신 사용하라는 것을 알 수 있다.  그러면 어떻게 해야할까? 여러 인터넷 사이트를 찾아보던 도중 한 사이트[3]를 발견했고, 그곳에 따르면 빌드 환경에 따라서 다른 메소드를 사용할 수 있게 해준다는 것이였다. 아래와 같은 방법으로 가능하다.

 

 

 

if(Build.VERSION.SDK_INT >= 11) {
   // 안드로이드 플렛폼 버젼(API Level)이 11 이상일 경우 실행
} else {
   // 안드로이드 플렛폼 버젼이 11 미만일 경우 실행
}

즉  Notification을 11미만일 때와 11 이상일 경우를 다르게 하여 구현하면 된다는 것! 아래 코드를 보자

int icon = context.getApplicationInfo().icon // Notification 발생시 출력할 아이콘
String title = ""; // Notification 발생시 아래로 내렸을 때 첫번째 줄
String subtitle = ""; // Notification 발생시 아래로 내렸을 때 두번째 줄
String ticker = ""; // 이벤트 발생시 위에 출력될 내용 
Notification noti;

if(Build.VERSION.SDK_INT >= 11) {
    noti = new Notification.Builder(context)
      .setContentTitle(title)
      .setContentText(subtitle)
      .setTicker(ticker)
      .setSmallIcon(icon)
      .setContentIntent(pIntent)
      .build();
} else {
    noti = new Notification(icon, ticker, System.currentTimeMillis());
    noti.setLatestEventInfo(context, title, subtitle, pIntent);
}

위와 같이 구현하면 최소 SDK 버젼에 관계 없이 구현가능하다. 실제로는 위와 같이 구현하면 최소 API Level이 8이기 때문에 11에서 추가된 Notification.Builder는 이용할 수 없지만 위와 같이 하면 문제없이 빌드 가능하다. 만약 에러가 난다면 프로젝트를 clean하여 다시 빌드하도록  하자.

API 레벨에 대해서는 [3][4]을 참조하도록 한다.

 

 참고자료


[1] Android Developer – Notifications,  https://developer.android.com/guide/topics/ui/notifiers/notifications.html
[2] Android Developer – References, https://developer.android.com/reference/android/app/Notification.html#Notification(int, java.lang.CharSequence, long)
[3] 【android】OSのバージョン(APIレベル)によって処理を変える方法, http://nobuo-create.net/api/
[4] Android Developer – API Level, http://developer.android.com/guide/topics/manifest/uses-sdk-element.html#ApiLevels

 

1월 182014
 

맥북프로레티나 기본형을 쓰는 사람이라면 모두 한 번씩은 고민하게 되는 문제가 있다. 그것은 바로 용량 문제이다. SSD를 도입해서 기본 속도는 빠르다는 장점이 있지만 그만큼 가격이 높아지다 보니 HDD보다 비교적 적은 256GB라는 용량 안에서 모든 것을 해결할 수 밖에 없다는 문제가 있다. 물론 이 문제는 맥북에어로 가면 더 심각해진다. 물론 요즘은 클라우드나 NAS를 이용하여 추가 작업 없이 용량을 확장할 수 있지만 네트워크 연결을 해야한다는 귀찮은점이 존재한다. 아니면 외장하드나 USB 메모리를 이용하면 따로 들고 다니고 작업 할 때 마다 꺼내서 설치해야 하는 것이 귀찮다. 그래서 고민을 해본 결과 맥북을 분해하지 않고 뭔가 튀어나오는 것도 없이 용량을 늘리는 방법은 놀고 있는 SD카드 리더기를 이용하는 것이였다.

불편한 외장하드, SD카드

일반 SD카드는 제거 용의를 위해 튀어나오며, USB드라이브나 외장하드는 따로 설치를 해야 한다.

일반 SD카드를 장착하면 위의 그림과 같이 튀어나오게 된다. 그렇다면 위에서 문제 제기한 것이 전혀 해결이 안된 것이 아닌가? 하지만 MicroSD카드라면 크기가 매우 작으니 무언가 관련 제품이 있을 것이라는 생각을 하게 되었다. 그래서 아마존에 들어가서 적절한 키워드인 “macbook sdcard microsdcard”를 넣어서 검색을 하였다. 그랬더니 눈에 들어온 제품이 바로 “The minidrive”1라는 것이였다. 이 제품은 국제배송이 되기 때문에 국내주소를 영문으로 적어서 배송을 받으면 되었다. 제품이 가벼워서인지 약 $3.5정도의 배송비가 추가되었다. 그 후 잊혀질 때 즈음 되었을 때 미국으로부터 국제우편이 도착하였다.

Amazon Minidrive

아마존에서 판매중인 MiniDrive2 – 스샷은 일반형이며 각 맥북 제품별로 알맞는 것이 따로 있으니 문서 제일 아래쪽의 링크를 통해 구매!


The Minidrive 일반형

미국 본사에서 국제우편을 통하여 배송 되었다. 가벼워서 우편으로 저렴하게 배송할 수 있었던 듯 하다.

초기형 모델을 구입하였기 때문에 어떠한 맥북에나 설치할 수 있다는 장점은 있었지만 탈착시 신경써야할 점이 있었다. 리더기에서 Theminidrive를 뺄 때를 대비해서 테이프부분을 잘 정리해 놓아야 한다는 점이였다. 크기가 슬록보다 작기 때문에 볼펜이나 클립을 이용해서 밀어 넣어야 했다. 최근에 나온 모델은 이 문제가 해결되어 있으니 자기 컴퓨터에 알맞는 것을 구매하도록 하자. 자세한 내용은 아래의 동영상을 참고하면 된다.

Theminidrive는 MicroSD카드 어뎁터이기 때문에 성능은 MicroSD카드의 클래스와 리더기의 성능에 의존적이였다. 트랜잭트사의 64GB MicroSD카드를 이용하여 용량을 늘렸다. 실제 윈도우2013 패러럴즈 이미지를 설치된 SD카드에서 실행해본 결과 쓰기 속도가 느려서인지 여러 프로그램을 실행시켰을 때 얼음이 되는 문제가 있었지만 프로그램 하나만 집중적으로 사용하는 경우 특별히 문제 없이 사용할 수 있었다. SSD에 설치되어 있을 때의 쾌적함에 비할 수는 없겠지만 큰용량의 이미지를 밀어 냈다는 점에 만족도가 크다. 용량은 많이 잡아먹지만 속도에 영향이 적은 데이터들을 옮기면 좋다. 쓰기가 비교적 읽기보다 느리니 읽기가 중요한 데이터를 중점적으로 옮기는 것이 좋겠다.


The minidrive의 아마존 링크
(주의: 구매 전 자신의 맥북에 이용가능한지 확인 할 것)

  1. 일반형 : http://amzn.com/B00AL1385C (모든 맥북에서 사용 가능)
  2. 맥북프로레티나15인치 : http://amzn.com/B00COWYFAI
  3. 맥북프로 : http://amzn.com/B00BCBKYMA
  4. 맥북에어 : http://amzn.com/B00BFMUT7Q

참고자료

  1. The minidrive, http://theminidrive.com/
  2. The MiniDrive | microSD Adaptor | MacBook Air/Pro/Retina in Amazon, http://amzn.com/B00AL1385C
1월 142014
 

필자의 경우 성격상 본체에 흠집이 나는 것이 싫어하기 때문에 SGP에서 발매한 범퍼(Neo hybrid EX slim1)를 구매하여 1년째 사용하고 있다. 애플의 정품 케이스는 질은 좋지만 가격이 비교적 비싸다는 단점이 있어서 구매할 생각이 전혀 없었다. 어차피 그 당시에는 아이폰5의 정품 케이스는 존재하지 않았기도 하다. 하지만 정품 케이스를 구입할 수 밖에 없는 이유가 생겼다.

필자는 동료들과 같이 인디크라우드라는 서비스를 운영하고 있다. 그 서비스는 실시간 음악 방송 서비스이다. 음악 방송이였기 떄문에 높은 음질의 서비스를 제공하는 것이 매우 큰 문제였다. 그래서 거금을 들여서 아포지 마이크(Apogee MIC)2를 구매하게 되었다. 이 마이크는 맥이나 아이폰/아이패드에 직접 연결하여 내장 마이크보다 좋은 음질로 수음(受音)할 수 있다는 장점이 있다. 그런데 문제는 이 아포지 마이크는 애플 30핀 커넥터만 지원(2014년 1월 14일 현재 라이트닝 케이블로 연결할 수 있는 아포지 마이크 발매중)한다는 것이였다. 아이폰5를 사용하고 있는 필자는 썬더볼트를 이용해야만 연결을 할 수 있는데 30핀 커넥터로 연결할 수 있을리가 없었다. 그래서 회비를 털어서 추가로 라이트닝-30핀 어뎁터를 구매해야 했다. 여기까지는 문제 없이 진행되었다. 하지만 사람에 따라 문제가 아닐 수도 있지만 필자에게는 매우 큰 문제가 발생하였다. 그것은 SGP 범퍼에 라이트닝-30핀 어뎁터가 들어가지 않는다는 것이였다. 이유는 모르겠지만 일반 라이트닝 케이블의 커넥터와 라이트닝-30핀 어뎁터의 라이트닝 어뎁터의 두깨가 달랐던 것이다. 즉 녹화를 할 때마다 범퍼를 벗기고 촬영하는 것을 반복해야한다는 것이였다.

선더볼트 커넥터 크기와 비교

SGP 범퍼의 썬더볼트 커넥터 단자와 정품 액세서리의 두꺠 비교. 라이트닝-30핀 어뎁터는 충전케이블보다 더 두껍다.

소프트웨어 엔지니어란 직업을 가지고 있다 보니 조금이라도 귀찮은 일이 생기면 참을 수가 없었다. 그런데 적당한 타이밍에 적절한 아이템이 나왔다. 그것은 바로 정품 아이폰5s 케이스였다. 리뷰를 몇 개 조사해보니 라이트닝 커넥터 부분의 두깨를 넓게 뚤어 놓아서 애플에서 발매된 라이트닝 액세서리가 거의 호환이 된다는 것이였다. 그리고 애플 홈페이지에도 나와 있듯이 아이폰5에도 사용가능하였다.

Red Friday in Korea

1월 10일 애플스토어에서 레드 프라이데이 세일이 있었다. | 애플 스토어 캡쳐3

게다가 호재라고 이야기라도 한 듯이 2014년 1월 10일에 레드 프라이데이가 열린 것이다. 레드 프라이데이는 해외의 블랙 프라이데이의 아시아판으로써 할인된 가격으로 일부 애플 제품을 구매할 수 있는 날을 말한다4. 그래서 약 5000원 가량 저렴하게 구매할 수 있었다. 배송은 금요일날 시켜서 다음주 월요일날 도착하였다. 주말이 껴있었던 것을 본다면 빠른 배송이라 놀랐다.

iPhone 5s Case

정품 iPhone 5s 케이스


정품 iPhone 5s 케이스 개봉 영상

택배로 받은 정품 아이폰5s 케이스를 아이폰5에 껴보았다. 기존에 SGP의 범퍼를 사용하였을 때 보다 좌우로 넓이가 두꺼워졌다는 느낌이 들었다. 케이스는 딱딱한 느낌이 들며 표면의 촉감은 느낌은 약간 부드럽고 접지력이 들어가 있다. 아이폰5 뒷면에 보호필름을 붙여서 인지 아주 미세하게 본체가 덜들어간 느낌이 들 수도 있지만 크게 문제는 없다. 오히려 정확히 딱 맞아 들어가 있었다. 케이스를 한 번 폰에 장착하면 벗기기가 힘들 정도의 완성도를 가지고 있다. 아이폰과 케이스가 둘 다 검정색으로 통일하였는데 특별히 색깔이 튀지 않는 것이 개인적으로 만족스러웠다. 장착하고 손으로 들어 보았는데 SGP범퍼보다는 약간 무겁지만 가벼운 편에 속하였다. 그리고 제일 중요한 라이트닝-30핀 어뎁터는 성공적으로 연결이 되는 것을 확인할 수 있었다. 물론 정품 이어폰이 잘 연결 되는 것은 말할 필요도 없을 것 이다.

iPhone 5s 케이스에 썬더볼트 케이블과 이어폰 연결

부가 악세사리도 문제없이 연결할 수 있었다.

아이폰5의 표면에 흠집나는 것을 싫어하고 여러 종류의 정품 액세사리를 가지고 있는 사람들이라면 구매하는 것을 추천한다. 들인 비용에 비해서 사람에 따라서 실망감이 있을 수 있다고 생각한다. 하지만 일반 서드파티 제품에 비해서 가격이 비싸기 때문에 필자와 같은 액세서리를 사용하지 않는 경우에는 오히려 SGP범퍼가 더 만족도가 높을 것이라고 생각한다.

참고자료

  1. iPhone 5 case neo hybrid ex slim, http://www.spigen.com/iphone-5-case-neo-hybrid-ex-slim-metal.html
  2. Apogee MIC, http://apogeedigital.com/products/mic.php
  3. 한국 애플 스토어, http://store.apple.com/kr
  4. 최갑천, “애플, 1년 단 하루 ‘레드 프라이데이'”, 파이낸셜뉴스, 2014년 1월 9일 판
1월 092014
 

필자는 서버를 설치하고 설정하고 관리하는 것을 좋아한다. 초등학교 유니텔 시절부터 홈페이지를 만들어 왔고 고등학교에서 군대가기 전까지 나름 그쪽 세계에서는 유명한 홈페이지를 만들기어서 운영하기도 하였다. 하지만 필자는 다른 사람이 관리하는 서버가 아니라 본인 만의 고유한 서버를 가지고 싶다는 생각을 하곤 하였다. 그러나 "고정 아이피" 문제와 계속 컴퓨터를 켜두어야 한다는 압박 때문에 어려움이 있었다. 그런데 드디어 그 목표를 달성할 수 있는 기회가 왔는데 그건 필자가 돈을 꾸준히 벌어야 하는 나이가 되었고 실제로 돈이 들어오기 시작했다는 것이였다.

어느날 웹서핑을 하고 있는데 2cpu라는 홈페이지에서 N40L의 공동구매에 대한 이야기를 우연히 보게 되었다. 가격도 저렴하고 저전력 서버라고 하였다. 가격도 저렴해 보였다. 그래서 이곳저곳을 검색하기 시작하였다. N54L이라는 모델이 있는데 그것이 CPU성능이 더 좋고 AirVideo1같은 것으로 볼 때 좋다는 이야기였다. 하지만 한국에서는 구할 수 없고 미국에서 구매해서 가져오던지 가격이 약간 비싼 한국 온라인 쇼핑몰에서 구입을 해야 한다는 것이였다. 거의 좌절하고 포기할까 생각하고 있던 도중에 좋은 자료를 발견할 수 있었다. 그것은 재미있게도 N40L 공동구매 보다 약간 저렴하게 N54L을 구매하는 방법이였다. 바로 일본 아마존에서 사는 것이였다. 환률이 많이 떨어져 있었기 때문에 큰 문제는 되지 않았다.

2014 01 09 00 20 08


일본 아마존에서 2014년 1월 9일 현재 16,980엔 엔화 환률은 1엔당 10.15원 정도로 약 17만원에 구매 가능

필자는 일본어가 가능하기 때문에 어려움 없이 일본 아마존이나 온라인 쇼핑몰을 확인해 볼 수 있었다. 여러 곳을 고려해본 결과 마음 편하게 가격은 약간 비싸지만(그래도 한국보다 싸다) VISA카드도 되고 신뢰도가 높은 아마존을 선택하였다. 이전에 중고책을 일본 아마존을 통해 구매한 적이 있었기 때문에 이 또한 바로 구매할 수 있었다. 오는데 월요일날 신청하여 배대지(배송대행지)를 통하여 금요일에 도착했다. 그 당시 환률로 30만원 정도 썼던 것 같은데 지금이라면 더 저렴하게 살 수 있을 것이다.

box


일본에서 날아온 N54L

현재 이 서버를 구매한지 거의 9 개월 정도 지난 것 같은데 딱히 고장난 적도 없고 전기세도 구입 전/후 비교 했을 때 그렇게 많이 오르지도 않았기 때문에 잘 구매했다고 생각하고 있다. 운영체제가 설치되어 있지 않기 때문에 우분투를 설치하고 4TB의 하드디스크를 설치하였다. DDNS를 통한 웹서버, 토렌트, 미디어 서버, NAS, 개발 서버로 유용하게 사용하고 있다.

IMG 4860


하드디스크는 4장까지 설치 가능하다. 250GB하드디스크가 설치된 상태로 배송되었다.

서버 성능은 약간 낮고 SSD로 갈아탄 노트북이나 개발PC에 비하면 확실히 느리다. 하지만 인터넷으로 구한 영상을 아이패드나 아이폰으로 AirVideo를 통해서 쉽게 볼 수 있게 되었다. 그리고 매일 켜놓은 서버가 생기면서 어디서든지 VPN을 통해서 자료에 접근할 수 있게 되었다. 개인용 서버이기 때문에 관리나 보안은 스스로 해야 한다는 문제가 있지만 데이터를 최대한(하드디스크 용량 만큼) 많이 저장할 수 있다는 점에서 만족도가 높다.

IMG 4862


HP Microserver N54L설치가 완료된 모습. 자주 죽지만은 마라다오.

현재는 Microserver Gen82이라는 N54L의 후속버젼이 나온 것으로 알고 있다. 이를 구매하더라도 만족스럽게 사용할 수 있을 것이라고 생각한다.

참고자료

  1. Air Video, http://www.inmethod.com/
  2. HP ProLiant MicroServer Gen8, http://www8.hp.com/us/en/products/proliant-servers/product-detail.html?oid=5379860#!tab=features