1. 서론
mysql 데이터베이스의 파티션이 커지면 데이터베이스 파일을 새로운 파티션에 옮기고 심볼릭 링크를 걸어서 용량을 확보하는 방법이 있다. 한편 우분투에서는 apparmor라고 하는 권한 관리 시스템이 존재하여서, 심볼릭 링크 후에 새로운 경로(파티션)에 대한 권한을 줄 필요가 있다.
여기서 apparmor가 설치된 mysql 환경에서 어떻게 파티션을 만들고, 공간을 확장하는지 알아 본다.
2. 수행 방법
1) 추가할 디스크 마운팅 및 포멧
# fdisk -l // 파티션 할당 상태 확인
# fdisk /dev/xvdb // /dev/xvdb : 추가된 디스크 주소
n 누루고 파티션 설정(primary partition, cylinder etc)
w 눌러서 저장
# mkfs.ext4 /dev/xvdb1 // ext4로 포멧
# mount /dev/xvdb1 /mnt/mysql_disk1 // 마운팅
# blkid // 추가된 /dev/xvdb1 의 UUID 확인
# vi /etc/fstab // 재부팅시 바로 자동 마운팅을 위해 설정
UUID=<> /mnt/mysql_disk1 ext4 rw 0 0 # 제일 아래줄에 추가
# df -h // 디스크 용량 확인
2) Apparmor 설정파일 변경 [1]
– 우분투는 접근관리를 좀 더 잘 하기 위해 파일에 권한을 사용자 단위로 지정하는 것이 아니라, 실행되어 있는 프로그램이 어디에 접근할 수 있는지를 설정함으로써 해결하고자 하였다. 이 편이 관리 측면에서 더 이득이 크다.
# vi /etc/apparmor.d/user.sbin.mysqld
# 제일 아래줄에 추가
/mnt/mysql_disk1/mysql_data r,
/mnt/mysql_disk1/mysql_data/** rwk,
3) sql 서버 종료
# service mysql stop
4) 데이터파일을 새로 저장할 큰 용량의 디스크로 복사 (ubuntu mysql은 /var/lib/mysql 에 있음)
# cd /var/lib/mysql
# cp -R * /mnt/mysql_disk1/mysql_data
5) 기존 파일 백업
# mv /var/lib/mysql /var/lib/mysql_bak
6) 심볼릭 링크 연결
# cd /var/lib
# ln -s /mnt/mysql_disk1/mysql_data mysql
7) sql 서버 다시 켜기
# service mysql start
8) DB에 잘 접속되나 테스트
3. 정 리
파일 복사하는데 꽤 시간이 걸리기 때문에 추후에는 mysql서버를 하나 더 준비하여 데이터를 옮기도록 작업하는 것이 더 좋을 것으로 예상된다. 그리고 데이터 베이스 파일을 하나로 하지 않고 여러개로 나누어서, 파일 단위로 심볼릭 링크를 걸어서 해결하는 방향이 더 좋을 것이라고 생각한다.
4. 관련 자료
[1] Recover an Innodb mysql database from an EBS on Ec2, Stack Exchange : http://dba.stackexchange.com/questions/57424/recover-an-innodb-mysql-database-from-an-ebs-on-ec2
[2] https://blogs.oracle.com/jsmyth/entry/running_out_of_physical_disk
윈도우에서 레일즈로 프로그래밍하면서 뭔가 한 번에 되는 것이 없다는 것을 자주 느끼곤 하는데, rmagick 이라는 gem을 설치할 때도 마찬가지 였다. rmagick은 오픈소스 이미지 프로세싱 라이브러리로 유명한 ImageMagick라는 라이브러리를 루비에서도 쓸 수 있게 wrapping한 gem이다. 전부가 그런 것은 아니고 C나 C++로 만들어진 대다수의 오픈소스 라이브러리는 크로스 컴파일을 지원하지만, 제일 컴파일하고 실행하기 좋은 환경은 리눅스 환경일 것이다. 어쨋든 rmagick을 윈도우에서 써야하는 이상 Gemfile에 rmagick을 넣고 bundle을 돌렸다. 역시나 에러 발생. 이런쪽 문제가 발생하면 구글에게 물어보라고 했던가, 검색하자마자 스택오버플로우 글 하나를 첫번째로 띄어주었다[1]. 글을 읽어보니 이전 포스팅에서 확인한 것과 같이 라이브러리를 설치해야한다는 것이였다. 별 생각없이 다운로드 받아서 실행해본 결과 역시나 실패. [1][2]의 글을 좀 열심히 읽어보니 라이브러리를 설치한 디렉토리에 빈칸이 있으면 안된다는 것이었다. “Program files”폴더에 설치 됬으니 당연히 빈칸이 들어갈 수 밖에… 지우고 다시 설치하였다. 그랬는데도 컴파일이 되지 않았다. 무엇 때문인지 하고 봤더니 ” c:\ImageMagick-6.8.0-3-Q16″에 “-“기호나 “.” 같은 특수문자 때문인듯 했다. 그래서 시키는 대로 “c:\ImageMagick” 폴더에 설치를 했다. 그랬더니 gem 설치가 성공하는 듯 했다. 하지만 이렇게 성공했다면 여기에 글을 남기지는 않았을 것이다. 역시나 안됬다. 에러를 뿌리면서 안됬는데 아래의 에러가 발생한다.
Building native extensions with: '--with-opt-lib=c:/ImageMagick/lib --with-opt-include=c:/ImageMagic k/include' This could take a while... ERROR: Error installing rmagick: ERROR: Failed to build gem native extension. C:/Ruby200/bin/ruby.exe extconf.rb --with-opt-lib=c:/ImageMagick/lib --with-opt-include=c:/Image Magick/include checking for Ruby version >= 1.8.5... yes checking for stdint.h... yes checking for sys/types.h... yes checking for wand/MagickWand.h... yes checking for snprintf() in assert.h,ctype.h,stdio.h,stdlib.h,math.h,time.h,stdint.h,sys/types.h,wand /MagickWand.h... yes checking for AcquireImage() in assert.h,ctype.h,stdio.h,stdlib.h,math.h,time.h,stdint.h,sys/types.h, wand/MagickWand.h... yes checking for AffinityImage() in assert.h,ctype.h,stdio.h,stdlib.h,math.h,time.h,stdint.h,sys/types.h ,wand/MagickWand.h... no checking for AffinityImages() in assert.h,ctype.h,stdio.h,stdlib.h,math.h,time.h,stdint.h,sys/types. h,wand/MagickWand.h... no checking for AutoGammaImageChannel() in assert.h,ctype.h,stdio.h,stdlib.h,math.h,time.h,stdint.h,sys /types.h,wand/MagickWand.h... yes checking for AutoLevelImageChannel() in assert.h,ctype.h,stdio.h,stdlib.h,math.h,time.h,stdint.h,sys /types.h,wand/MagickWand.h... yes checking for BlueShiftImage() in assert.h,ctype.h,stdio.h,stdlib.h,math.h,time.h,stdint.h,sys/types. h,wand/MagickWand.h... yes checking for ConstituteComponentTerminus() in assert.h,ctype.h,stdio.h,stdlib.h,math.h,time.h,stdint .h,sys/types.h,wand/MagickWand.h... no checking for DeskewImage() in assert.h,ctype.h,stdio.h,stdlib.h,math.h,time.h,stdint.h,sys/types.h,w and/MagickWand.h... yes checking for EncipherImage() in assert.h,ctype.h,stdio.h,stdlib.h,math.h,time.h,stdint.h,sys/types.h ,wand/MagickWand.h... yes checking for EqualizeImageChannel() in assert.h,ctype.h,stdio.h,stdlib.h,math.h,time.h,stdint.h,sys/ types.h,wand/MagickWand.h... yes checking for FloodfillPaintImage() in assert.h,ctype.h,stdio.h,stdlib.h,math.h,time.h,stdint.h,sys/t ypes.h,wand/MagickWand.h... yes checking for FunctionImageChannel() in assert.h,ctype.h,stdio.h,stdlib.h,math.h,time.h,stdint.h,sys/ types.h,wand/MagickWand.h... yes checking for GetAuthenticIndexQueue() in assert.h,ctype.h,stdio.h,stdlib.h,math.h,time.h,stdint.h,sy s/types.h,wand/MagickWand.h... yes checking for GetAuthenticPixels() in assert.h,ctype.h,stdio.h,stdlib.h,math.h,time.h,stdint.h,sys/ty pes.h,wand/MagickWand.h... yes checking for GetImageAlphaChannel() in assert.h,ctype.h,stdio.h,stdlib.h,math.h,time.h,stdint.h,sys/ types.h,wand/MagickWand.h... yes checking for GetVirtualPixels() in assert.h,ctype.h,stdio.h,stdlib.h,math.h,time.h,stdint.h,sys/type s.h,wand/MagickWand.h... yes checking for LevelImageColors() in assert.h,ctype.h,stdio.h,stdlib.h,math.h,time.h,stdint.h,sys/type s.h,wand/MagickWand.h... no checking for LevelColorsImageChannel() in assert.h,ctype.h,stdio.h,stdlib.h,math.h,time.h,stdint.h,s ys/types.h,wand/MagickWand.h... yes checking for LevelizeImageChannel() in assert.h,ctype.h,stdio.h,stdlib.h,math.h,time.h,stdint.h,sys/ types.h,wand/MagickWand.h... yes checking for LiquidRescaleImage() in assert.h,ctype.h,stdio.h,stdlib.h,math.h,time.h,stdint.h,sys/ty pes.h,wand/MagickWand.h... yes checking for MagickLibAddendum() in assert.h,ctype.h,stdio.h,stdlib.h,math.h,time.h,stdint.h,sys/typ es.h,wand/MagickWand.h... yes checking for OpaquePaintImageChannel() in assert.h,ctype.h,stdio.h,stdlib.h,math.h,time.h,stdint.h,s ys/types.h,wand/MagickWand.h... yes checking for QueueAuthenticPixels() in assert.h,ctype.h,stdio.h,stdlib.h,math.h,time.h,stdint.h,sys/ types.h,wand/MagickWand.h... yes checking for RemapImage() in assert.h,ctype.h,stdio.h,stdlib.h,math.h,time.h,stdint.h,sys/types.h,wa nd/MagickWand.h... yes checking for RemoveImageArtifact() in assert.h,ctype.h,stdio.h,stdlib.h,math.h,time.h,stdint.h,sys/t ypes.h,wand/MagickWand.h... yes checking for SelectiveBlurImageChannel() in assert.h,ctype.h,stdio.h,stdlib.h,math.h,time.h,stdint.h ,sys/types.h,wand/MagickWand.h... yes checking for SetImageAlphaChannel() in assert.h,ctype.h,stdio.h,stdlib.h,math.h,time.h,stdint.h,sys/ types.h,wand/MagickWand.h... yes checking for SetImageArtifact() in assert.h,ctype.h,stdio.h,stdlib.h,math.h,time.h,stdint.h,sys/type s.h,wand/MagickWand.h... yes checking for SetMagickMemoryMethods() in assert.h,ctype.h,stdio.h,stdlib.h,math.h,time.h,stdint.h,sy s/types.h,wand/MagickWand.h... yes checking for SparseColorImage() in assert.h,ctype.h,stdio.h,stdlib.h,math.h,time.h,stdint.h,sys/type s.h,wand/MagickWand.h... yes checking for SyncAuthenticPixels() in assert.h,ctype.h,stdio.h,stdlib.h,math.h,time.h,stdint.h,sys/t ypes.h,wand/MagickWand.h... yes checking for TransformImageColorspace() in assert.h,ctype.h,stdio.h,stdlib.h,math.h,time.h,stdint.h, sys/types.h,wand/MagickWand.h... yes checking for TransparentPaintImage() in assert.h,ctype.h,stdio.h,stdlib.h,math.h,time.h,stdint.h,sys /types.h,wand/MagickWand.h... yes checking for TransparentPaintImageChroma() in assert.h,ctype.h,stdio.h,stdlib.h,math.h,time.h,stdint .h,sys/types.h,wand/MagickWand.h... yes checking for QueryMagickColorname() new signature... yes checking for Image.type in assert.h,ctype.h,stdio.h,stdlib.h,math.h,time.h,stdint.h,sys/types.h,wand /MagickWand.h... yes checking for DrawInfo.kerning in assert.h,ctype.h,stdio.h,stdlib.h,math.h,time.h,stdint.h,sys/types. h,wand/MagickWand.h... yes checking for DrawInfo.interline_spacing in assert.h,ctype.h,stdio.h,stdlib.h,math.h,time.h,stdint.h, sys/types.h,wand/MagickWand.h... yes checking for DrawInfo.interword_spacing in assert.h,ctype.h,stdio.h,stdlib.h,math.h,time.h,stdint.h, sys/types.h,wand/MagickWand.h... yes checking for DitherMethod in assert.h,ctype.h,stdio.h,stdlib.h,math.h,time.h,stdint.h,sys/types.h,wa nd/MagickWand.h... yes checking for MagickFunction in assert.h,ctype.h,stdio.h,stdlib.h,math.h,time.h,stdint.h,sys/types.h, wand/MagickWand.h... yes checking for ImageLayerMethod in assert.h,ctype.h,stdio.h,stdlib.h,math.h,time.h,stdint.h,sys/types. h,wand/MagickWand.h... yes checking for long double in assert.h,ctype.h,stdio.h,stdlib.h,math.h,time.h,stdint.h,sys/types.h,wan d/MagickWand.h... yes checking for AlphaChannelType.CopyAlphaChannel... yes checking for AlphaChannelType.BackgroundAlphaChannel... yes checking for CompositeOperator.BlurCompositeOp... yes checking for CompositeOperator.DistortCompositeOp... yes checking for CompositeOperator.LinearBurnCompositeOp... yes checking for CompositeOperator.LinearDodgeCompositeOp... yes checking for CompositeOperator.MathematicsCompositeOp... yes checking for CompositeOperator.PegtopLightCompositeOp... yes checking for CompositeOperator.PinLightCompositeOp... yes checking for CompositeOperator.VividLightCompositeOp... yes checking for CompressionType.DXT1Compression... yes checking for CompressionType.DXT3Compression... yes checking for CompressionType.DXT5Compression... yes checking for CompressionType.ZipSCompression... yes checking for CompressionType.PizCompression... yes checking for CompressionType.Pxr24Compression... yes checking for CompressionType.B44Compression... yes checking for CompressionType.B44ACompression... yes checking for DistortImageMethod.BarrelDistortion... yes checking for DistortImageMethod.BarrelInverseDistortion... yes checking for DistortImageMethod.BilinearForwardDistortion... yes checking for DistortImageMethod.BilinearReverseDistortion... yes checking for DistortImageMethod.DePolarDistortion... yes checking for DistortImageMethod.PolarDistortion... yes checking for DistortImageMethod.PolynomialDistortion... yes checking for DistortImageMethod.ShepardsDistortion... yes checking for DitherMethod.NoDitherMethod... yes checking for FilterTypes.KaiserFilter... yes checking for FilterTypes.WelshFilter... yes checking for FilterTypes.ParzenFilter... yes checking for FilterTypes.LagrangeFilter... yes checking for FilterTypes.BohmanFilter... yes checking for FilterTypes.BartlettFilter... yes checking for FilterTypes.SentinelFilter... yes checking for MagickEvaluateOperator.PowEvaluateOperator... yes checking for MagickEvaluateOperator.LogEvaluateOperator... yes checking for MagickEvaluateOperator.ThresholdEvaluateOperator... yes checking for MagickEvaluateOperator.ThresholdBlackEvaluateOperator... yes checking for MagickEvaluateOperator.ThresholdWhiteEvaluateOperator... yes checking for MagickEvaluateOperator.GaussianNoiseEvaluateOperator... yes checking for MagickEvaluateOperator.ImpulseNoiseEvaluateOperator... yes checking for MagickEvaluateOperator.LaplacianNoiseEvaluateOperator... yes checking for MagickEvaluateOperator.MultiplicativeNoiseEvaluateOperator... yes checking for MagickEvaluateOperator.PoissonNoiseEvaluateOperator... yes checking for MagickEvaluateOperator.UniformNoiseEvaluateOperator... yes checking for MagickEvaluateOperator.CosineEvaluateOperator... yes checking for MagickEvaluateOperator.SineEvaluateOperator... yes checking for MagickEvaluateOperator.AddModulusEvaluateOperator... yes checking for MagickFunction.ArcsinFunction... yes checking for MagickFunction.ArctanFunction... yes checking for MagickFunction.PolynomialFunction... yes checking for MagickFunction.SinusoidFunction... yes checking for ImageLayerMethod.FlattenLayer... yes checking for ImageLayerMethod.MergeLayer... yes checking for ImageLayerMethod.MosaicLayer... yes checking for ImageLayerMethod.TrimBoundsLayer... yes checking for VirtualPixelMethod.HorizontalTileVirtualPixelMethod... yes checking for VirtualPixelMethod.VerticalTileVirtualPixelMethod... yes checking for VirtualPixelMethod.HorizontalTileEdgeVirtualPixelMethod... yes checking for VirtualPixelMethod.VerticalTileEdgeVirtualPixelMethod... yes checking for VirtualPixelMethod.CheckerTileVirtualPixelMethod... yes checking for ruby/io.h... yes checking for rb_frame_this_func() in ruby.h,ruby/io.h... yes creating extconf.h creating Makefile ====================================================================== Thu 03Jul14 22:29:32 This installation of RMagick 2.13.2 is configured for Ruby 2.0.0 (i386-mingw32) and ImageMagick 6.8.9 ====================================================================== make "DESTDIR=" generating RMagick2-i386-mingw32.def compiling rmagick.c In file included from rmagick.c:13:0: rmagick.h:81:2: error: #error Specified QuantumDepth is not supported. rmagick.c: In function 'Magick_colors': rmagick.c:40:5: warning: implicit declaration of function 'GetExceptionInfo' [-Wimplicit-function-de claration] rmagick.c:42:5: warning: passing argument 2 of 'GetColorInfoList' from incompatible pointer type [en abled by default] In file included from c:/ImageMagick/include/magick/image.h:21:0, from c:/ImageMagick/include/magick/draw.h:22, from c:/ImageMagick/include/magick/fx.h:21, from c:/ImageMagick/include/magick/accelerate.h:21, from c:/ImageMagick/include/magick/MagickCore.h:73, from rmagick.h:47, from rmagick.c:13: c:/ImageMagick/include/magick/color.h:75:5: note: expected 'size_t *' but argument is of type 'long unsigned int *' rmagick.c: In function 'Magick_fonts': rmagick.c:90:5: warning: passing argument 2 of 'GetTypeInfoList' from incompatible pointer type [ena bled by default] In file included from c:/ImageMagick/include/magick/draw.h:24:0, from c:/ImageMagick/include/magick/fx.h:21, from c:/ImageMagick/include/magick/accelerate.h:21, from c:/ImageMagick/include/magick/MagickCore.h:73, from rmagick.h:47, from rmagick.c:13: c:/ImageMagick/include/magick/type.h:98:5: note: expected 'size_t *' but argument is of type 'long u nsigned int *' rmagick.c: In function 'Magick_init_formats': rmagick.c:178:5: warning: passing argument 2 of 'GetMagickInfoList' from incompatible pointer type [ enabled by default] In file included from c:/ImageMagick/include/magick/MagickCore.h:118:0, from rmagick.h:47, from rmagick.c:13: c:/ImageMagick/include/magick/magick.h:135:5: note: expected 'size_t *' but argument is of type 'lon g unsigned int *' make: *** [rmagick.o] Error 1 Gem files will remain installed in C:/Ruby200/lib/ruby/gems/2.0.0/gems/rmagick-2.13.2 for inspection . Results logged to C:/Ruby200/lib/ruby/gems/2.0.0/gems/rmagick-2.13.2/ext/RMagick/gem_make.out
또 열심히 구글링을 했더니 [3]의 문서를 발견하였다. 문서를 간단히 살펴보니 imagemagick 라이브러리의 버젼에 따라서 컴파일이 안된다는 말로 간단히 요약할 수 있었다. 직접 컴파일해서 연동하는 방법도 써있으니 필요하신분은 참고하시면 될 듯. 어쨋든 되는 버젼을 확인해보니 ‘ImageMagick-6.8.7-8-Q16-x86-dll’에서는 컴파일이 가능하다고 하여 다운로드 받아서 위와 같은 방법으로 실행해 보니 문제 없이 설치할 수 있었다. 이상으로 문제 해결!
– 필자는 Ruby 2.0 x86에서 테스트 했으며, ImageMagick라이브러리도 x86으로 준비하였음. 전에 64bit로 무리하게 진행하다가 고생한 선례가 있어 그나마 편하게 가고 싶으시면 x86을 추천함.
요 약
1. http://ftp.sunet.se/pub/multimedia/graphics/ImageMagick/binaries/ 에서 ImageMagick-6.8.7.8-Q16-x86-dll.exe 을 다운로드.
2. ImageMagick 설치시 경로를 “c:\ImageMagick” 으로 할 것. 그리고 설치시 체크하는 곳에서 “Add application directory to your path system”, “Install development headers and libraries for C and C++” 항목을 체크표시 할 것
3. rails 폴더에서 “gem install rmagick –platform=ruby — –with-opt-lib=c:/ImageMagick/lib –with-opt-include=c:/ImageMagick/include” 라고 명령 실행!
참고자료
[1] StackOverflow(I cant install gem on windows), http://stackoverflow.com/questions/4873276/i-cant-install-rmagick-gem-on-windows
[2] shubham’s blog(installing rmagick gem on windows 7), http://shoobm.wordpress.com/2013/01/03/installing-rmagick-gem-on-windows-7/
[3] 君の瞳はまるでルビー – Ruby 関連まとめサイト(RMagick を Windows 7 にインストールする方法), http://www.ownway.info/Ruby/index.php?rmagick%2Fhowtoinstall%2Fwindows
다음 자동완성 워크플로우에 대한 수요가 있어서 만들어 보았습니다. 개인적으로 사전 자동완성은 타사 보다 다음이 좀 더 나은 것 같습니다. 혹시 원하는 사전이 있다면 말씀해 주시면 추가하도록 하겠습니다. 그리고 버그 알려주시는 것은 언제나 환영합니다^^ 방법은 이메일이나 코멘트를 통하여 부탁드립니다!
설치 방법
방법은 간단합니다. Alfred 4 가 설치되어 있는 컴퓨터에서 아래의 workflow를 다운로드 받아서 실행하는 것 만으로 충분합니다.
링크에 접속하여 `alfdaumsearch.alfredworkflow` 를 다운받아 설치합니다.
사용 방법
사용방법은 다음과 같습니다. 제가 만든 네이버 검색 워크플로우 와 기본적인 방법은 같습니다.
-
ds ...
: 일반 키워드 검색 -
dk ...
: 국어사전 검색 -
dh ...
: 한자사전 검색 -
dj ...
: 일어사전 검색 -
de ...
: 영어사전 검색 -
dc ...
: 중국어사전 검색 -
di ...
: 인도네시아어사전 검색 -
dv ...
: 베트남어사전 검색 -
dit ...
: 이태리어사전(이탈리아어) 검색 -
dru ...
: 러시아어사전(노어) 검색 -
df ...
: 프랑스어사전 검색 -
dtr ...
: 터키어사전 검색 -
dth ...
: 타이어사전(태국어) 검색 -
dpl ...
: 폴란드어사전 검색 -
dpt ...
: 포루투갈사전 검색 -
dcs ...
: 체코어사전 검색 -
dhu ...
: 헝가리어사전 검색 -
dar ...
: 아랍어사전 검색 -
dsv ...
: 스웨덴어사전 검색 -
dhi ...
: 힌디어사전 검색 -
dnl ...
: 네덜란드어사전 검색 -
dfa ...
: 패르시아어사전 검색 -
dsw ...
: 스와힐리어사전 검색 -
dro ...
: 루마니아어사전 검색
변경이력
- [2014.06.30] v0.0.2 런치 : 알프레드에서 검색 후 엔터를 쳤을 때 "r"으로만 검색되는 버그 수정
- [2016.12.09] v0.0.4 : 인도네시아어 사전 추가
-
[수정 2017-07-25 03:45+0900] 연관 프레임워크 업데이트 (시에라 백그라운드 버그 해결)
-
[2021-01-01] v0.0.5 : 다음 자동완성 주소 변경
-
[2021-01-07] v0.0.6 : 17 종류의 사전 추가
-
[2021-01-07] v0.2.0 : macOS 12.3 대응 -> python3 설치 필요
-
[2024-02-15] v0.3.0 : SSL에러 이슈 해결
기능 개선 참여 방법
해당 다음 검색 워크플로우는 MIT로 공개되어 있는 오픈소스입니다. 개선을 도우고 싶으신 분이 있으시면, Github alfdaumsearch 를 통하여 참여부탁드립니다.
여러 삽질을 하면서 알아낸 정보! 시작은 아래의 에러 메시지로부터 시작되었다. 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
윈도우에서 아래와 같은 에러가 발생하는 경우 루비 실행파일이 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
모든 것은 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
필자의 경우에 회사에서는 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
$ 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
※ 이 문서는 Notification 자체에 대해서 설명하고 있는 것이 아니라 Notification을 알고 있다는 가정하에서 만들어야 할 앱이 API Level 11 미만을 지원해야할 경우를 위한 설명이다. Notification 자체에 대한 이해는 [1]을 참조하도록 한다.
안드로이드 Notification을 구현하는 방법은 여러가지가 있는데 하나는 기본 제공하는 양식을 사용하는 방법, 다른 하나는 Custom layout을 이용하여 구현하는 방법이 있다. 이 중에 기본 제공 양식을 사용하는 방법으로 구현을 해 보고자 한다.
하지만 안타깝게도 타겟 플렛폼 버젼이 8(Android 2.2, Froyo)이상으로 해야 했기 때문에 문제가 발생했다. 바로 기본 제공 방법을 사용할 경우에 Notification의 생성자가 deprecated 됬기 때문이다. 즉 사용하지 않는 것이 좋다는 뜻이다. 바로 이 메소드가 문제!
빨간 네모박스의 내용과 같이 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
필자는 서버를 설치하고 설정하고 관리하는 것을 좋아한다. 초등학교 유니텔 시절부터 홈페이지를 만들어 왔고 고등학교에서 군대가기 전까지 나름 그쪽 세계에서는 유명한 홈페이지를 만들기어서 운영하기도 하였다. 하지만 필자는 다른 사람이 관리하는 서버가 아니라 본인 만의 고유한 서버를 가지고 싶다는 생각을 하곤 하였다. 그러나 "고정 아이피" 문제와 계속 컴퓨터를 켜두어야 한다는 압박 때문에 어려움이 있었다. 그런데 드디어 그 목표를 달성할 수 있는 기회가 왔는데 그건 필자가 돈을 꾸준히 벌어야 하는 나이가 되었고 실제로 돈이 들어오기 시작했다는 것이였다.
어느날 웹서핑을 하고 있는데 2cpu라는 홈페이지에서 N40L의 공동구매에 대한 이야기를 우연히 보게 되었다. 가격도 저렴하고 저전력 서버라고 하였다. 가격도 저렴해 보였다. 그래서 이곳저곳을 검색하기 시작하였다. N54L이라는 모델이 있는데 그것이 CPU성능이 더 좋고 AirVideo1같은 것으로 볼 때 좋다는 이야기였다. 하지만 한국에서는 구할 수 없고 미국에서 구매해서 가져오던지 가격이 약간 비싼 한국 온라인 쇼핑몰에서 구입을 해야 한다는 것이였다. 거의 좌절하고 포기할까 생각하고 있던 도중에 좋은 자료를 발견할 수 있었다. 그것은 재미있게도 N40L 공동구매 보다 약간 저렴하게 N54L을 구매하는 방법이였다. 바로 일본 아마존에서 사는 것이였다. 환률이 많이 떨어져 있었기 때문에 큰 문제는 되지 않았다.
필자는 일본어가 가능하기 때문에 어려움 없이 일본 아마존이나 온라인 쇼핑몰을 확인해 볼 수 있었다. 여러 곳을 고려해본 결과 마음 편하게 가격은 약간 비싸지만(그래도 한국보다 싸다) VISA카드도 되고 신뢰도가 높은 아마존을 선택하였다. 이전에 중고책을 일본 아마존을 통해 구매한 적이 있었기 때문에 이 또한 바로 구매할 수 있었다. 오는데 월요일날 신청하여 배대지(배송대행지)를 통하여 금요일에 도착했다. 그 당시 환률로 30만원 정도 썼던 것 같은데 지금이라면 더 저렴하게 살 수 있을 것이다.
현재 이 서버를 구매한지 거의 9 개월 정도 지난 것 같은데 딱히 고장난 적도 없고 전기세도 구입 전/후 비교 했을 때 그렇게 많이 오르지도 않았기 때문에 잘 구매했다고 생각하고 있다. 운영체제가 설치되어 있지 않기 때문에 우분투를 설치하고 4TB의 하드디스크를 설치하였다. DDNS를 통한 웹서버, 토렌트, 미디어 서버, NAS, 개발 서버로 유용하게 사용하고 있다.
서버 성능은 약간 낮고 SSD로 갈아탄 노트북이나 개발PC에 비하면 확실히 느리다. 하지만 인터넷으로 구한 영상을 아이패드나 아이폰으로 AirVideo를 통해서 쉽게 볼 수 있게 되었다. 그리고 매일 켜놓은 서버가 생기면서 어디서든지 VPN을 통해서 자료에 접근할 수 있게 되었다. 개인용 서버이기 때문에 관리나 보안은 스스로 해야 한다는 문제가 있지만 데이터를 최대한(하드디스크 용량 만큼) 많이 저장할 수 있다는 점에서 만족도가 높다.
현재는 Microserver Gen82이라는 N54L의 후속버젼이 나온 것으로 알고 있다. 이를 구매하더라도 만족스럽게 사용할 수 있을 것이라고 생각한다.
참고자료
- Air Video, http://www.inmethod.com/ ↩
- HP ProLiant MicroServer Gen8, http://www8.hp.com/us/en/products/proliant-servers/product-detail.html?oid=5379860#!tab=features ↩