Django 의 forms.ModelChoiceField 는 보통 ModelForm 에서 ForiegnKey 를 받기 위해 사용된다. 하지만 ForiegnKey 로 사용될 수 있는 객체가 제한적이라면 queryset 인자를 통해 선택할 수 있는 옵션을 제한 할 수 있다. 예를들어, Board 모델과 Category 모델, Article 모델이 존재한다고 해 보자. Article 은 게시판의 글을 나타내며 Board 와 Category 에 속한다. Category 는 각각의 게시판에서 존재하는 분류를 타나내고 Board 에 속한다. 이 경우 Article 을 쓰기 위해 Form 을 만들 경우 ModelForm 을 사용 할 것이다. 하지만, 이러한 경우는 모든 Category 를 선택할수 있게 하면 안된다. 현재 Article이 써지려는 Board와 같은 Board에 속하는 Category 만 선택가능하도록 해야 할 것이다. 이런 경우 동적으로 ModelForm의 category를 오버로딩 해야 한다. 이때 아랴와 같이 하면 된다.
class ArticleForm(forms.ModelForm):
    def __init__(self, board, *args, **kwargs):
        super(ArticleForm, self).__init__(*args, **kwargs)
        self.fields['category'].queryset = Category.objects.filter(board=board)
        self.fields['category'].empty_label = u"선택안함"
    
    class Meta:
        model = Article
        fields = ('category', ... blah blah ...)

사실 잘 생학해 보면 Category 에 이미 Board 에 대한 정보가 들어가 있으므로 Article 에 딱히 Board 가 필요하지는 않지만 일종의 역정규화를 시킨 것으로 이해하면 된다. 이러한 경우 위와 같이 사용하여 Category 의 선택을 제한 할 수 있다.

전에 CakePHP에 대한 글을 한번 쓴 적이 있다. 그때는 CakePHP를 가지고 동아리 홈페이지를 만들고 있었는데 느린 속도와 코드의 지저분함때문에 결국에는 별로 계속 코딩을 하고싶은 욕구가 생기지 않았다. 누가 돈주는 것도 아니고 결국 내 자신이 동기부여가 안되면 더이상 진행이 안되기 때문에 좀더 구조가 좋은 다른 프레임워크를 생각해 보았다.

처음에는 PHP계열 프레임워크를 알아보다가 내가 CakePHP가 싫어진 이유도 PHP자체의 문제가 한몫 한다고 생각해 아예 다른 언어 기반의 프레임워크를 찾기 시작했다. CakePHP는 클래스 상속을 통해 많은 기능을 DRY(Don't Repeat Yourself)시켜 주는데 일단 PHP가 PHP5부터 제대로 된 객체지향을 지원하지만 아직 프레임워크가 PHP4기반이라 클래스 내부 구현이 별로 이쁘지가 않다. 게다가 제일 큰 문제점은 DB에 접근하기 전에 reculsive를 설정하여 얼마나 연관된 테이블까지 가져올 것인가를 먼저 정해야하는 것이었다. 이것도 사실 객체지향형 설계를 잘해 lazy evaluation을 하면 되는 것인데 결국은 이걸 잘 못하는 PHP랑 관련되어 생긴 문제였다. 도대체 왜 객체지향형 프레임워크에서 User와 연관된 Group정보에 접근하는데 $this->User->data['Group']['field_name']을 써야 하는가. 게다가 load하기 전에 $this->reculsive = 0 정도는 미리 해 주어야 한다. 이걸 굳이 프로그래머가 생각해서 몇번째 연관된 자료까지 필요하니 $this->reculsive를 얼마로 놓아야지 라고 하는것 너무 세련되지 못하다. user->group->get('field_name')정도가 훨씬 간단하고 보기도 좋지 않은가? PHP의 개발자가 PHP는 프레임워크 없이 쓰는 것이 좋다라고 했는데 그 말이 제일 맞는 것 같다. PHP자체가 웹언어니 굳이 프레임워크 없이도 잘 쓸수 있고, 오히려 그럴때 고민을 덜하게 되는 것 같다. 익숙해 지면 물론 다르겠지만 처음 접하는 사람이 HTTP Header를 controller에서 $this->header를 사용할까 아니면 view에서 PHP 내장 header() 함수를 쓸까 고민하는 것 보다는 낫지 않을까? 물론 코딩량은 많아지겠지만...

이러한 이유때문에 다른 언어 기반인 Ruby On Rails(이하 Rails)나 Django로 바꿀 생각을 한번 해 보고 알아보기 시작했다. 사실 Perl 기반의 Catalyst나 함수형 언어 기반의 프레임워크도 생각 해 보았지만, 구할수 있는 자료가 너무 부족한 탓에 일단 Rails나 Django쪽으로 가닥을 잡았다. 일단 전에 Rails에 관련해서 살짝 본 적도 있고 해서 Rails를 선택할까 하다가도 약간은 생소한 Ruby 의 문법때문에 고민이 되었다. 그래서 일단은 Django에 대해서 한번 알아보기로 하였다. Python은 예전에 한번 본 적도 있고 해서 별 문제 없이 Django책 하나랑 Django 문서파일을 가지고 이것저것 해 보기 시작했다. 근데 생각보다 엄청 휼륭하다! 일단 내가 CakePHP에서 불편하다고 느낀 점은 하나도 발견되지 않았다. Django의 모델이 파이썬 코드 구현인 탓에 기존의 SQL을 Python코드로 옮기긴 해야 하겠지만 그건 아무런 문제가 아니었다. CakePHP처럼 Scaffolding기능이 있는 것도 아니었지만 전혀 상관없다. 그냥 할것은 모델을 만들고 간단하게 뷰 구현하고 템플릿좀 끄적여주면 페이지가 완성된다. 물론 아직 익숙하지 않아서 문서를 많이 찾아보지만, 소스 짜는것 자체가 전보다 훨씬 즐거워졌다. 확실히 CakePHP쓸때와는 다르게 쓸데없는 고민따위는 안해도 된다. 이후 Rails도 어떨까 궁금했는데 이것(https://docs.google.com/View?docid=dcn8282p_1hg4sr9)을 보니 뭐 Django보다 많이 좋을 것 같지는 않다.

하지만 Django도 아무런 문제가 없는건 아니다. 사실 Django의 모델에서 폼을 만드는 것은 사용이 그리 간단하지만은 않다. 예를들어 회원가입페이지는 User모델과 UserProfile모델에다 회원을 추가한다. 하지만 가입하기 위해 보여주는 폼(form)은 모델에서 바로 생성하기가 조금 어렵다. 물론 모델에서 생성 할 수 있지만 내가 원하는 대로 폼의 필드를 만드는 것은 사실 폼을 새로 만드는 것과 별 차이가 안난다. 아직 Django의 모든 기능을 알지는 못해서 그럴 수도 있는데 이부분은 좀 아쉽다.

간단히 요약하면 일단 PHP언어 자체와 프레임워크는 별로 어울리지 않는 것 같다. PHP6이 나오니 어떻게 변할지는 모르겠지만 일단 지금까지는 그렇다. 다른 프레임워크를 아직 많이 알지는 못하지만 Django정도면 웹에 있어서는 정말 좋은 프레임워크임에는 틀림없다. 한번 자신이 Python에 대해서 어느정도 알고있다면 웹프로그래밍을 할때 한번 Django에 도전해 보면 좋을 것 같다.
CakePHP 후기 Programming/Web 2011. 1. 12. 23:30
일단 몇일동안 CakePHP를 써본 후기를 올린다. 아직 많이 사용 해 본것도 아니고 홈페이지를 다 만든것도 아니지만 일단 조금 아쉬운 점이 있어 올린다.

CakePHP는 유명한 웹 프레임워크인 RoR(Ruby on Rails)의 기능을 본따 php로 만든 것이다. 문제는 php자체가 루비와는 다르게 웹 언어로부터 출발하였고, 프레임워크를 염두하고 만든 것이 아니기 때문에 쓰다 보면 좋을 때도 있지만 좀 귀찮을때도 있다. 그냥 쌩으로 코딩할때는 별 고민없이 프로그래밍한걸 CakePHP내장 함수들을 써서 다듬으려니 꽤나 귀찮다. 특히 디비에 쿼리날릴때 제일 이런 느낌이 많이든다. 원래대로라면 MySQL의 내장함수들과 프로시져를 포함하게 쿼리를 날릴텐데 그걸 전부 php안에서 해야되서 제약이 많아졌다. MySQL의 강력한 기능을 못쓰는 기분. 

게다가 CakePHP만의 강력한 기능들은 ajax를 구현할때는 별로 또다른 강력한 기능을 하지 못한다. 원래 기본적으로 form의 어느 필드가 문제인지 알려주는 validate 기능도 ajax에서는 실제 폼으로 전송하는게 아니니까 내부에서 validate을 하고 결과 에러메세지를 데이터로 전송해야 한다. 물론 미리 validate하였기 때문에 save하는 함수에도 validate을 하지는 말라고 알려줘야 한다. 뭐 그래도 조금은 편하긴 하지만 생각했던것 만큼 엄청난 일을 줄여주거나 하지는 않는것 같다. 관련 기능이 있는 Helper를 쓰면 나을 것 같기도 한데, 기본으로 추가되어 있는게 아니기 때문에 무슨 Helper가 좋은지도 모르겠다. 

또한 다른 문제는 성능이다. 같은 기능을 생으로 구현했을때와 CakePHP를 썻을때 성능차이가 꽤나 많이 난다. 사용자가 매우 없는 상태라 원래는 누르면 바로바로 받아진 ajax데이터가 꽤나 오래건린다. 

하지만 좋은 점도 많다. 일단 마음에 든건 MVC패턴과 레이아웃 기능, 그리고 validate기능이다. 딱 이정도 기능만 있고 빠른 프레임워크가 있으면 많이 좋을 것 같다. 아마 Codeigniter 가 이런데 좋은 것 같은데 알아봐야겠다.