'분류 전체보기'에 해당되는 글 49건

  1. 2010.01.15 그루비기반 게시판?
  2. 2010.01.14 스칼라
  3. 2010.01.01 CouchDB
  4. 2009.11.13 데비안 우분투 1
  5. 2009.11.09 몽고디비
  6. 2009.11.07 윈도우에서 레일즈 개발
  7. 2009.11.06 엔진엑스
  8. 2009.11.04 그루비에는 for 루프가 없나? 1
  9. 2009.11.04 proftpd 설정
  10. 2009.11.03 요즘하는 코딩
카테고리 없음2010. 1. 15. 19:34
다른 이의 블로그를 읽다가, 이런 대목을 발견했다.

여기서 중요한 것은 승리한 기술이 항상 우월하지 않다는 점이다. 한 기술이 표준으로 선택되는 데에는 기술 자체의 편리성보다는 보급률이나 특허같은 기술 외부의 요인이 더 영향을 끼친다. 우리는 베타 방식의 비디오가 화질이나 여러 면에서 뛰어남에도 불구하고, 포르노를 쉽게 구할 수 있는 VHS에 밀린 사실을 잘 알고 있다. 꼭 뛰어난 기술이 승리하는 것은 아니며, 때로는 익숙하고 도입하기 쉬운(진입장벽이 낮은) 기술이 표준으로 자리잡기도 하는 것이다. - http://docean.egloos.com/4625621

써본 사람들은 편하다고 말하는데, 그루비 사용인구가 적은 것은, 제로보드와 같은 당장 적용가능한 템플릿이 없기 때문일까.
Posted by jintopark
카테고리 없음2010. 1. 14. 00:04
스칼라가 좋다는 의견이 종종 있어서, 가끔 코드를 들여다보곤 했었다. 하지만 콜론이 너무 자주나오는게 이상하게 보기싫었다. 콜론들 덕분에 첫인상이 구겨졌고, 그 다음 진도는 나가기 힘들었었다.








오늘 Programming In Scala을 앞부분부터 다시 읽다가,  1장을 건너뛰고 (건너뛰는게 더 좋은 것 같다.) 2장부터 진도를 나가보았다. 위의 그림은 62페이지 중간쯤에 나오는 그림이다. 자꾸 보니까 그런걸까. 콜론이나 "Int" 들이 눈에 거슬리지 않고, 대신 "=" 이 묘하게 감동적으로 눈에 들어왔다.

저게 함수 "정의"다. 그러고나서 보니까, "Int"도 ":"도 그닥 별스럽지 않게보였다.




이 그림은 앞의 함수를 정의하는 또다른 방법이다. 리턴 타입이 Int 임에 틀림없으니까 생략할 수 있단다.

아직, 그루비에서 처럼 SQL을 편하게 다룰수있는지 (어떤 사람은 groovy sql을 scala에서 쓰기도 한다. 그정도로 아직 스칼라쪽에 라이브러리가 부족하다.) 더 알아봐야한다.

그리고, 거의 첫번째 관문을 넘었을 뿐이다. 이런 곳의 코드를 보고 있으면, 여전히 불친절한 문법이란 생각이 든다. 힘든 산일수록 넘고나면 기쁘겠지만.
Posted by jintopark
카테고리 없음2010. 1. 1. 17:55
몽고디비(MongoDB)로 마음이 쏠렸었는데, 너무 겉핥기로만 지나쳤다는 미안함이 있어, CouchDB도 테스트 해봤습니다.

드라이버
--------
그루비쪽에서 보면, 몽고나 카우치나 거기서 거기더군요. 테스트에는 jcouchdb를 드라이버로 사용했습니다. 그루비에 내장된 REST 로 시도해보았는데, jcouchdb에 비해 너무 느리더군요. groovyx.net.http.RESTClient 는 구현이 제대로 안된 것 같습니다.

jcouchdb는 자바용 드라이버이지만, 그루비에서도 이런 식으로 사용할 수 있었습니다.
[code groovy]
def db = new org.jcouchdb.db.Database("xxx.xxx.xxx.xx", 5987, "dbname");
def doc = [name:'박제권' ....]
db.createDocument(doc);
[/code]

테스트
------
테스트는 게시문 20만건, 사용자디비 6만건, 댓글 100만건 정도를 INSERT 해보았습니다.
서버는 몇군데서 돌아가면서 해봤는데, 체감결과는 비슷했습니다. 메모리가 많으면 더 잘도는 것 같긴합니다만, 워낙 느려서...

다음은 기록해둘만한 사항들입니다.



버전
----
데비안에서 couchdb의 안정버전은 아직도 0.8 입니다.  문제는 0.10 버전이 조금 빨라지기도 했고, VIEW 쪽 접근 URL도 다르다는  점입니다. (view 의 url 이 달라지니까... 나중에 0.10 이 안정버전이 되면 어플리케이션 코드를 손대야 하는...)

데비안4 나 5 모두 couchdb 0.10 을 설치하려면 testing으로 올려야합니다.
ubuntu 9.10 / fedora 11 에서는 문제없이 0.10을 설치해줬습니다.

컴파일하는 것도 한가지 방법인데... erlang, openssl 까지 의존 목록에 들어있더군요. 따라서....귀찮습니다.

(저는 안정버전에 집착하는 편인데, 좀 문제네요.)


벌크 인서트
----------
처음에 며칠동안은 테스트 데이터 한 건식 루프를 돌면서 insert 해보았는데요. 최장 8시간까지 걸리더군요. 댓글의 경우는 그나마 데이터가 적어서인지 빨리되는데, 게시물같은 경우는 초당 10개가 안되기도 합니다.

상황에 따라 정확한 시간은 달라질 수 있습니다만, 동일 환경에서 mongodb에서는 13분 걸리더군요. 그냥 두 DB가 성격이 다른 거니까, 속도를 비교하는 것은 무리인 듯 합니다.

더 조사해보니, 벌크인서트(bulk insert)라는 것이 있어서 이걸 써봤습니다.

[code groovy]
def array = [];
rawdata.each {r->
   def doc = [name:r->name, ....]
   array.add(doc);
   if((i%500) != 0) {
     db.buldCreateDocuments(array);
     array = [];
   }
}
[/code]
와 같은 방식으로 사용할 수 있습니다.

이 API를 이용하니까, 전체 데이터 로딩속도가 엄청나게 빨라졌습니다. (30분정도)


뷰 == 미리 정의해야 하나
-----------------------
다음 문제는 뷰(View)였습니다. 카우치에서 가장 독특해보이는 녀석이 자바스크립트로 만들어진 뷰인데요. 여기에 map/reduce라는 개념까지 들어가면 공부하기 힘들어보입니다.

저는 테스트 데이터를 입력하면서 회원/게시물/댓글 에 대해서 doc_type 이라는 필드를 만들고, 각각 member/article/comment 라는 값을 주었습니다.

[code groovy]
articles_data.each { r->
  def doc = [doc_type :'article', name:r->name, ....]
  db.createDocument(doc);
}
comments_data.each { r->
  def doc = [doc_type :'comment', name:r->name, ....]
  db.createDocument(doc);
}
[/code]
그리고, 각 타입의 문서가 몇개나 있는지 세어보는 view를 만들었습니다. 앞의 함수가 map 이고, 뒤의 함수가 reduce 입니다.

[code groovy]
function(doc) {
  emit(doc.doc_type, 1);
}

function(key, values) {
    return sum(values);
}
[/code]
아래는 결과입니다.

[code groovy]
"article"    : 245328
"member"  : 68076
"comments":1157777
[/code]

이 녀석이 카우치 디비에서 가장 감동적인 장면인 것 같아서 캡쳐해봤습니다. (테스트 도중이라 값이 다른 부분이 있습니다)


맵/리듀스를 이리저리 쓰다보면 기존의 SQL과는 또다른 재미있는 데이터 인출기법이란 점이, 꽤 ... 재미있습니다. 하지만, 문제는 저 함수가 호출될 때마다, 인덱스가 수정된다는 점이었습니다.

카우치는 데이터와 인덱스를 분리해서 관리합니다. 데이터를 저장할 때는 인덱스 처리를 하지 않습니다. 대신 VIEW 엔진이 동작할 때, 관련된 인덱스를 수정하게 됩니다.

이게 묘한 부작용을 일으키는데요.

update나 insert 가 많이 이루어진 후에 view를 호출하면 인덱스하는데 시간이 너무 오래걸린다는 점입니다. 테스트를 포기할 정도로 오래걸린 경우도 많았습니다.


나중에 찾아낸 해결책은 벌크-인서트를 수행하면서, 중간 중간에 view 엔진을 호출해주는 겁니다. 그렇게 하면 어느정도 참고 기다릴만합니다. 하지만 좀.. 뻘짓하는 느낌이었습니다.

인덱스 수정이 완료된 이후에는 VIEW를 수행하는데 걸리는 시간이 굉장히 짧아집니다. 그리고, 테스트에서 처럼 몇만개씩이 아닌, 천개정도의 데이터를 추가하고, VIEW를 돌려봤는데요. 응답을 얻기까지 얼마 안걸리더군요. 1~4초 내외인데, 오래걸린다는 느낌은 없었습니다.


유니크 키
---------
이건 좀 문젠데요. 카우치는 유니크키(unique key)를 지원하지 않습니다. (몽고는 지원) 편법은 있는 것 같지만, 어쨌든, 시스템이 자동생성하는 키( 필드명 : _id ) 를 제외하고는 유니크 키를 지원하지 않습니다.

즉, 회원 아이디라던가, 하는 것을 유니크 키로 지정해서, 동일한 아이디의 회원이 만들어지지 않도록 디비를 설정하는 것이 안됩니다.

요기 맨아래에 설명이 있는데... 노드가 하나일 때는 _id 필드에 원하는 필드를 넣으면 되긴하는데, multi-master 환경에서는 충돌할 수도 있다, 라고 적혀있습니다.



데이터 사이즈
------------
MySQL : 1.9G
MongoDB: 2.1G
CouchDB non-bulk: 18G
CouchDB bulk: 3.5G

데이터의 형태에 따라 차이가 날 것 같습니다만, 비율은 저정도 인것 같습니다. 특이한 점은 카우치는 MVCC때문인 것 같습니다만, 벌크일때와 아닐때 차이가 납니다. (compact db 라는 명령이 따로 있습니다.)



결론
----
몽고디비랑 카우치디비를 일대일로 비교하기는 힘듭니다. 초당 insert 가 너무 느리긴 합니다만, 카우치는 원래 컴퓨터를 추가하고 연결만 하면 자동으로 클라우드로 동작하는 것이 목표인 데이터베이스입니다. 느리면 서버를 추가하면 되죠.

몽고디비는 처음부터 속도를 중시하는 쪽이구요. (몽고도.. master-master 지원하지만 fail-over를 위한 것이라고 하네요. 그래도 그냥 잘 쓴다는 사람도 있긴합니다만..)

카우치디비는 일단 재미삼아 공부하기 적당하구요. 서비스 환경에 적용한 케이스도 꽤 있고, 그리 나쁜 선택은 아닌 것 같습니다. 하지만, 문제를 공부를 해야한다는 점입니다.

몽고디비는 지금 돌아보니 mysql 의 document-db 버전인 것 같다는 인상입니다. sql을 알던 사람이 적응하기 쉽고, 드라이버나 예제들도 따라하기 좋습니다. 공부하는데 드는 시간이 비교적 짧습니다.

아마도, 테스트 과제 따위에서는 카우치, 당장 서비스 할 것에는 몽고, 가 어떨까 합니다. 저는 한동안 두가지 모두 병행해서 사용해보려고 합니다. 카우치쪽이 다음버전에서 어떤 점이 좋아질지 궁금하기 때문입니다. (어쩌면 속도?)

이상입니다.
Posted by jintopark
카테고리 없음2009. 11. 13. 00:30
우분투로 이것 저것 재미있게 놀았다. 리눅스 데스크탑도 쓸만한 것 같다. 서버에서도 우분투를 쓰는게 좋을까? 지난번에 서버에도 우분투 쓰기로 작정했었는데..

다음주에 IDC에 서버가 새로 들어와서 가져갈 씨디를 고르다가, 갑자기 고민이 돼서, 이것저것 둘러보고, 테스트 설치도 다시 해보는 중이다.


가장 중요한 문서는 우분투쪽에서 데비안과 자기들과의 관계를 설명한 글. 관계가 나쁘다 좋다, 그런게 아니라, (당근 좋다.. 고 쓰여있다.)

     * 자기들이 새 버전을 만들기 시작할 때 데비안의 "stable" 이 아닌,
              "development"버전에서 시작한다는 이야기가 눈에 걸렸다.
    * 그 다음에는 6개월마다 새버전을 내놓는다는 이야기. (그럴필요는 없잖아?)
     * 하지만 우분투에도 LTS 버전이 있다.

우분투 LTS 서버버전은 5년간 지원된다. 그러니까, "8.04는 2013년까지 지원"이라고 쓰여있다. 그럼 2013년이후에는?

이게 처음봤을 때부터 궁금했는데, 위키백과에 따르면, 메인 서버에서도 삭제될꺼라고 한다. 엉? 그럼 어쩌라고? 역시 데비안이군.. 이라고 중얼거리면서 데비안쪽을 뒤져봤다. 뒤져본 결과...

2002년에 나온 데비안우디..는 2006년에 보안패치까지도 중단된 상태다. (http://www.debian.org/releases/woody/) 데비안도 마찬가지네.

어차피 이쪽은 업그레이드 하면서 쓰는거니까...

우분투는 7.10 LTS에서 8.04 LTS로 업그레이드하다가 문제가 있었다는 보고가 있긴한데... 데비안에서도 full-upgrade에서는 가끔 깨진다는 보고도있고... 마찬가지인 것 같다.

처음에 우분투를 선택했던 이유는. 나같은 초보 관리자가 우분투를 선택하기 더 쉬울꺼고, 그럼 더 많은 아티클이 나올꺼고, 막힐때 찾아볼 자원이 늘어날꺼라는 생각이었다. 이건 아직도 유효한것 같은데..

아.. 귀찮아. 그냥 구워놓은 우분투 8.04 LTS들고 갈까..

====
추가 참고 포스트 : http://hostingfu.com/article/keeping-your-php-fastcgi-processes-alive
Posted by jintopark
카테고리 없음2009. 11. 9. 23:57
몽고디비란 것이 있다. MongoDB. 속도도 빠르고, 개념도 깔끔하다. CouchDB라던가 Hadoop 따위는 아직은 나한테는 공부용인 것 같았지만 이 녀석은 달라보인다.

실무에 곧바로 적용해보기로 하고, 간단하게 방금 공부한 것을 정리해둔다.

먼저 깔끔한 우분투 8.04 LTS를 서버버전으로 깔았다.

[code shell]sudo mkdir -p /data/db  
cd /opt/
wget http://downloads.mongodb.org/linux/mongodb-linux-i686-latest.tgz
sudo tar -zxvf mongodb-linux-i686-latest.tgz
sudo mv mongodb-linux-i686-2009-11-09/ mongodb   
sudo mongodb/bin/mongod [/code]

라고 하고, 터미널을 하나 더 열었다.

vi m.groovy 해서 다음 내용을 넣었다.

[code groovy]import com.mongodb.*

def m = new Mongo()

def db = m.getDB("mydb")
def coll = db.getCollection("myfam")

coll.drop()

def doc = [name:"한글", desc:"mytest", age:21, loc: [x:203, y:102]]
                  as BasicDBObject
def doc2 = [name:"영어", desc:"wife", age:22,  loc: [x:253, y:102]]
                  as BasicDBObject

coll.insert(doc)
coll.insert(doc2)

println coll.getCount()

def obj = coll.findOne([age:21] as BasicDBObject)
println obj

println "showing a custom query"
def cur = coll.find([age:['$lt':23]] as BasicDBObject)
while(cur.hasNext()) {
   println cur.next()
}

def obj2 = coll.findOne([name:"한글"] as BasicDBObject) 
println obj2[/code]

그리고
[code shell]wget http://cloud.github.com/downloads/mongodb/mongo-java-driver/mongo-1.0.jar
groovy -cp mongo-1.0.jar m.groovy[/code]


여기까지 실행해보면, 서버가 잘 동작하고, 자바/그루비랑도 잘 어울리는 것을 알 수있다. 조금만 더 공부해보자. (여기가 더 재미있다.)

--------

[code shell]~$ /opt/mongodb/bin/mongo[/code]

를 실행해보자.

[code]MongoDB shell version: 1.1.3-
url: test
connecting to: test
type "help" for help

> show dbs
admin
local
mydb

> show collections
system.indexes
testCollection                                  // 방금 그루비로 만든 녀석이다.

> db.xx.save({name:"hhh",age:11})  // xx 는 정의한적이 없다.
> db.xx.save({name:"yyy",age:12})   //스키마도 만든적이 없다.
> db.xx.save({name:"xxx",age:13})  //그냥 save해버린다.

> show collections              
system.indexes
testCollection
xx                                                  // xx라는 컬렉션이 생겼다.

// 검색도 해보자
> db.xx.find({age:12})           
{ "_id" : ObjectId("4af82b2e3138af056bab5259"), "name" : "yyy", "age" : 12 }

// 11살넘는 아이들만..
> db.xx.find({age: {$gt : 11}})          
{ "_id" : ObjectId("4af82b2e3138af056bab5259"), "name" : "yyy", "age" : 12 }
{ "_id" : ObjectId("4af82cb03138af056bab525a"), "name" : "xxx", "age" : 13 }

exit
[/code]

여기까지.. 이후에는 몽고디비 홈페이지에서 문서를 보면서 조금씩 더 공부하면 되겠다.

P.S. 그루비 소스는 http://jameswilliams.be/blog/entry/165 에서 가져왔다. (한글 때문에 조금 손댔다)
mongo 쉘 데모는 http://hompy.info/586 를 참고했다. (조금만 바꿔서 해봤다)
Posted by jintopark
카테고리 없음2009. 11. 7. 22:04
레일즈로 개발하려면 맥북을 사라고 들었다. 아니면 우분투라도 깔던가.

나는 (맥북살 돈도 없었고, 윈도우도 써야하니까) 이것 저것 테스트해보고는 결국 "편집기 + SSH" 만 띄우고 서버에 붙어서 작업하기로 했었다.


그렇게 설정하기까지... 생각해보면 별짓을 다했었다. 로컬에도 Mysql 서버가 하나 있어야겠다, 고 생각한것이 최대의 실수. (하지만 결국 설치해야 하는 건 맞다.)

처음에는 리눅스랑 비슷한 환경이 필요할 것 같아서, cygwin을 설치했다. 윈도우에 mysql 설치하고, cygwin에서 gem 설치한다고 컴파일러도 돌려보고, 잘 안붙길래 이것저것 건드려보면서 시간을 보내기도 했다. 그 와중에 jruby 로 가보기도 했고...


하지만, 최종적으로는 e-texteditor를 사서 ( 샀다 ! ) ftp로 파일편집, 테스트는 IE 로하는 것이 가장 간단했다. 가끔 ssh 터미널에서 뭔가 주물럭거리고.. 이게...


별로 부담도 없고, 쓸만한 환경이었는데, 고객 서버중에 한군데가 ftp가 안되고 sftp만 된단다. 그리고, e-texteditor는 sftp를 받아주지 않는다. ( 젠장 ! )

사실 ultraedit 에서 sftp를 받아줘서 문제는 금방 해결했지만... (ultra는 안샀다..)


하지만, 어쩐지, 갑자기, 괜히 기분이 나서 개발환경을 한번 건드려봤다. ( 밤샜다. ) vmware를 깔아서 그쪽에다가 개발 툴들 설치해보고. 좀 느리다 싶어서, 서버쪽에 eclipse를 깔고, xmanager로 접속해서 코딩해보고. 좀 멋져보일까 싶어서 emacs에서 ecb도 깔아보고 등등등...



그런데, 이틀정도 소비한 후에 혹시나 하고 깔게된 윈도우즈 ruby + netbeans가 너무 편하다. ㅜㅜ

넷빈즈 생긴모양이 좀 구리긴 한데, 개발하기에는 너무 편하다.


그동안 이 좋은 조합을 쓰지 못하게 나를 막았던 가장 큰 문제는 mysql gem이 계속 죽는다는 거였다. 이상하게 죽었다. 이런 에러다.

[code]ArgumentError (NULL pointer given):
   (eval):3:in `each_hash'
   (eval):3:in `all_hashes'
[/code]

디비에 접속해서 쿼리를 날리면 저런 메시지가 나오고, 레일즈가 죽어버리곤 했다. 로컬에 설치한 서버건 원격서버건 상관없다.


헌데 mysql 을 5.1.X 가 아니라 5.0.X를 설치하니까, 문제가 감쪽같이 사라졌다. 혹시 느리지 않을까? 아니다. 로컬의 레일즈 어플리케이션이 원격 mysql 에 접속해서 페이지 만드는데 걸리는 시간은 703 밀리초. (반대로 로컬에 접속할 때는 엄청 느리다. 뭐, 원격이 빠르니까 상관없다. )


몇시간 안썼는데 그동안 애써 외면했던 netbeans나 eclipse 에 들어있는 각종 편의 기능들이 줄줄이 기다리면서 사용해달라고 노래를 부른다. ㅜㅜ


혹시, 윈도우에서 레일즈 개발은 너무 힘들어, 라면서 나처럼 X고생 하던 사람이 또 있다면, 한번 시도해보기 바란다.


지금 윈도우에 설치된 녀석들은

넷빈즈 (netbeans) 6.7.1
이클립스 (eclipse) 3.5.1 (aptana 2.0.0)
자바 (java) 1.5.0_17
루비 (ruby) 1.8.7 : 원클릭으로 설치한 후 1.8.7을 받아서 덮어써버림. (제대로 한건지 모르겠다 .)
레일즈 (rails) 2.3.4
mysql gem 2.8.1
mysql server 5.0.87 (Essential 이라고 되어있는 넘을 설치했다.)

rmagick 1.14.1 (이넘은... RMagick-1.14.1_IM-6.3.0-7-Q8.zip 을 설치해야한다. ㅎㅎ,
                      091213 추가: RMagick-2.9.0-ImageMagick-6.4.8-6-Q8.zip 도 동작하는 것 확인)
nokogiri 1.4.0   (이넘은 구글링 조금만하면 문제없다.)

그리고, 테스트한 윈도우는

  윈도우즈 XP SP2
  비스타 Home Premium K SP1

두개다.


P.S. 사실 이 문제는 몇달전에 구글링할 때 조금만 더 정성껏 들여다봤더라면 일찌감치 해결했을 수도 있는 문제였다. 참고 : http://www.ruby-forum.com/topic/171574

P.S. 넷빈즈에서는 웹브릭이 기본이고, 이클립스(aptana)에서는 몽그렐이 기본인데, 웹브릭으로 해야 문제없이 돈다. 몽그렐도 돌긴도는데..
Posted by jintopark
카테고리 없음2009. 11. 6. 18:00

 

원 포스트  :

http://bethesignal.org/blog/2009/04/06/replacing-apache-with-nginx-for-static-file-serving/

----

 

아래는 어떤 사이트의 대기상태 프로세스를 일주일간 측정한 그래프라고 한다.

 

 

매일 점심시간쯤에 대기상태인 프로세스 갯수가 줄어든다. 즉, 모든 프로세스가 열심히 사용자들의 요청을 처리하는 중이라는 뜻이다. 하지만 그래프 후반부에 금요일에는 거의 모든 프로세스가 대기상태로 들어간 것 처럼보인다.

 

아래 그림을 보면 금요일부터는 메모리도 거의 안쓰고 놀고있다.

 

 

 

하지만, eth0 를 보면...

 

 

사용자들은 금요일 점심시간에도 여전히 접속을 하고 있었다.

 

 

 

아파치대신 엔진엑스를 썼기 때문이란다.

 

 

나는 정확한 테스트는 안해봤지만, 일단 메모리를 적게쓰는 것은 확인했다. 그 후로는 아파치를 설치해보질 않았다...

 

사실 아파치를 쓰는게 속은 편한데.... 아파치는 요청 하나에 대해 프로세스하나를 대응하는 방식이 기본이다. worker 모델로 바꾸면 요청에 대해 쓰레드를 대응하는 방식으로 바꿀 수 있지만, 문제는 PHP. PHP는 아파치 worker에서 제대로 쓸 수 없다.

 

요즘 서버를 설치할 일이 있으면, 엔진엑스를 올리고 php는 fast-cgi 데몬으로 올린다. phpMyAdmin 따위가 있으니 php를 아주 안쓰기는 힘들고, fast-cgi가 떠있는 걸 볼때마다 뭔가 좋은 방법은 없을까 생각하게되지만, 메모리 사용량이랑 CPU 로드 통계를 보고 있으면, 이쪽이 훨씬 경제적이다. 레일즈랑도 딱 맞고.

 

P.S 원 포스트의 주인장은 엔진엑스를 앞에서 돌리고, 뒤쪽에 아파치를 app서버로 써서 저런 효과를 봤다, 고 썼다. 어쩐지 시도해보고 싶은 방식이다. fast-cgi 보다는 이게 더 보기 좋을 듯.

Posted by jintopark
카테고리 없음2009. 11. 4. 16:31
사실 그루비나 루비모두 "for (i in list)" 같은 형식은 지원한다. 하지만 전통적인 C언어의 for 루프는 지원하지 않았었다. 처음 그루비 교과서를 들여다볼 때는 그게 상당히 불만스러웠다.

[code java]
// 이게 전통적인 for 루프.
for(int i =0 ; i< 10 ; i++) {}

// 이게 요즘 쓰는 루프
dataSet.eachXXX {} [/code]

너무 오래써온 문법이기 때문에 이걸 지원하지 않으면 꽤 불편할꺼라고 생각했었다. 하지만, 실무에서 써본 후에는 완전히 생각이 달라졌다.

each 를 설명하는 예제에는 흔히

[code groovy]
def list = [0, 1, 2, 3, 4]
list.each { n->
  print n
}
[/code]

같은 것들이 등장하곤 하는데, 사실 이런 것은 써본적 없다. 대신 최근 실무에서 사용하는 코드중에

[code groovy]
con.eachRow("select * from some_table order by id asc"){ rs ->
      println rs.al_subject;
 ....
}
[/code]

와 같은 것들이 있다. 레코드셋을 얻어다가, "각 레코드마다 돌면서 무슨 일인가를 한다." 라는 것이 그루비의 eachRow 가 하는 일이다.

익숙해지는데 두세시간 정도 걸린것 같은데, 그다음부터는 레코드셋만 보면 eachRow가 자동으로 나온다.

사실은.. 원래는.. 그렇게 사용할 때 가장 편리하게 쓸수 있는 녀석였던 것같다. 그외에도

[code groovy]
// HTML 파일과 쌍으로 있어야하는 JPG 파일이 없을 때...
// 고아가된 HTML파일을 지워버린다.
def p = ~/.*\.html/
def dirs = ['./dir1/', './dir2']

dirs.each { dir-> new File( dir ).eachFileMatch(p) { f ->
    def jpg = f.toString().replaceAll('html', 'jpg')
    if ( !(new File(jpg)).exists()) {
        f.delete()
    }
}}
[/code]

에서 each 처럼, 우리가 마주치는 대부분의 상황이 원래 for 루프보다 each를 쓰는 게 적절했음을, 계속 깨닫게 된다. 이건 그루비뿐만 아니라, 루비나, 파이썬을 써도 점점 익숙해지는 개념인 것 같다. (stl도 그렇다고 하면.. 그렇겠지만 ..)

참고 :
http://groovy.codehaus.org/Korean+Looping
http://mrhaki.blogspot.com/2009/09/groovy-goodness-looping-in-different.html


P.S. 처음에 그루비를 쓸때는 지원하지 않았었는데, 지금 테스트해보면 그동안 누가 요청을 했는지 어쨌는지, 고전적인 for루프를 지원한다.
Posted by jintopark
카테고리 없음2009. 11. 4. 03:33
데비안에서 proftpd 를 ftp 서버로 쓰고있는데, 이것 저것 건드려봐도, 도대체 ftp 접속이 안될때가 있었다. 그동안은 (바보처럼) 안되는구나.. 라고 포기하고 있었는데, 원인은 iptables 쪽에 있었다.

iptables 에

[code]REJECT all – anywhere anywhere reject-with icmp-port-unreachable[/code]

이 있으면 접속이 안되더라.

[code] iptables-save > /etc/iptables.up.rules [/code]

한다음


파일에서 문제의 라인을 지우고

[code] iptable-load < /etc/iptables.up.rules [/code]

하니까, 오케이.



Posted by jintopark
카테고리 없음2009. 11. 3. 22:08
좀 낭비스럽고 루비답지 않아보이지만.. 그냥 공개해보면..

[code ruby]
    def created
        s = read_attribute(:a_created).strftime("%y-%m-%d")
    end

    def created_long
        s = read_attribute(:a_created).strftime("%Y-%m-%d %H:%M:%S")
    end

    def created_medium
        s = read_attribute(:a_created).strftime("%y-%m-%d %H:%M")
    end
[/code]

전에는 코딩하면서 꽤 정성을 쏟아부었던 것 같은데, 갈수록 시간을 투자하기가 싫어져버렸다. 그래도 요즘 다시 불타올라 보는중..  ㅎㅎ
Posted by jintopark

 

 
«이전  1 2 3 4 5  다음»