Dragonkun in Tistory

SEARCH RESAULT : 글 검색 결과 - 웹 (총 7개)

POST : 프로그래밍/개발

Flex와 Rails, 그리고 REST

이 글은 작업 중에 있는 글입니다.
차후에 설명을 붙이도록 하고 우선 소스만 올려둡니다.

Internal Action Script 가 포함된 Flex mxml 파일

<?xml version="1.0"?>
<!-- 게시판 -->
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" creationComplete="svcPosts.send();"
>
    <mx:HTTPService id="svcPosts" url="http://localhost:3000/posts.xml" method = "GET" resultFormat="e4x" result="postsResultHandler(event)" fault="postsFaultHandler(event)">
    <mx:request>
        <limit>20</limit>
    </mx:request>
    </mx:HTTPService>
    <mx:HTTPService contentType="application/xml"
                     id="svcCreatePost"
                     url="http://localhost:3000/posts"
                     useProxy="false" method="POST">
        <mx:request xmlns="">
            <post>
                <name>{tAuthor.text}</name>
                <subject>{tSubject.text}</subject>
                <body>{tBody.text}</body>
            </post>
        </mx:request>
    </mx:HTTPService>
    <mx:HTTPService id="svcDeletePost"
                           result="svcPosts.send();"
                           url="http://localhost:3000/posts"
                           method="POST"
                           useProxy="false"/>
    <mx:HTTPService id="svcEditPost"
                           result="svcPosts.send();"
                           url="http://localhost:3000/posts"
                           method="POST"
                           useProxy="false">                          
        <mx:request xmlns="">
            <post>
                <name>{oldAuthor.text}</name>
                <subject>{oldSubject.text}</subject>
                <body>{oldBody.text}</body>
            </post>
        </mx:request>                          
    </mx:HTTPService>
    <mx:Style>
        Panel { font-size: 12pt }
    </mx:Style>   
    <mx:Script>
    <![CDATA[
    import mx.rpc.events.FaultEvent;
    import mx.rpc.events.ResultEvent;
    import mx.controls.Alert
    import mx.events.CloseEvent;
   
    [Bindable]
   
    private var posts:XML;
   
    public function postsResultHandler(event:ResultEvent):void
    {
        posts = event.result as XML
        //Alert.show(posts);
    }
   
    public function postsFaultHandler(event:FaultEvent):void
    {
        Alert.show(event.fault.message, "Could not load posts!");
    }

    private function deleteHandler(event:Event) : void
    {
      Alert.show("정말 이 항목을 삭제하시겠습니까?", "포스트 삭제", 3, this,
      function(event:CloseEvent):void
      {
        if (event.detail==Alert.YES)
            svcDeletePost.url = 'http://localhost:3000/posts/'+dgPosts.selectedItem.id+'.xml';
            svcDeletePost.send({id: dgPosts.selectedItem.id, _method:'DELETE'});
       });
    }

    ]]>
    </mx:Script>   

    <mx:Panel title="Flexible Board" height="100%" width="100%"
        paddingTop="10" paddingLeft="10" paddingRight="10">

        <mx:Label width="100%" color="black"
            text="게시판입니다."/>

        <mx:DataGrid id="dgPosts" width="100%" height="100%" rowCount="20" dataProvider="{posts.post}">
            <mx:columns>
                <mx:DataGridColumn dataField="id" headerText="No" width="40" textAlign="center" />
                <mx:DataGridColumn dataField="name" headerText="이름" width="100" textAlign="center" />
                <mx:DataGridColumn dataField="subject" headerText="제목"/>
                <mx:DataGridColumn dataField="created_at" headerText="글 쓴 날짜" width="150" textAlign="center" />
                <mx:DataGridColumn dataField="updated_at" headerText="변경된 날짜" width="150" textAlign="center"/>
            </mx:columns>
        </mx:DataGrid>

        <mx:Form width="100%" height="100%">
            <mx:FormItem label="이름">
                <mx:TextInput text="{dgPosts.selectedItem.name}" id="oldAuthor" />
            </mx:FormItem>
            <mx:FormItem label="제목">
                <mx:TextInput text="{dgPosts.selectedItem.subject}" id="oldSubject" />
            </mx:FormItem>
            <mx:FormItem label="글 쓴 날짜">
                <mx:Label text="{dgPosts.selectedItem.created_at}"/>
            </mx:FormItem>
            <mx:FormItem label="변경된 날짜">
                <mx:Label text="{dgPosts.selectedItem.updated_at}"/>
            </mx:FormItem>           
            <mx:FormItem label="내용">
                <mx:TextArea width="400" height="100" text="{dgPosts.selectedItem.body}" id="oldBody" />
            </mx:FormItem>
            <mx:Button label="글 수정"
                   click="svcEditPost.url='http://localhost:3000/posts/'+dgPosts.selectedItem.id+'.xml';svcEditPost.send({_method:'PUT'});svcPosts.send();"/>
            <mx:Button label="글 삭제"
                   click="deleteHandler(event);"/>                  
        </mx:Form>
       
        <mx:Form width="100%" height="100%">
            <mx:FormItem label="이름">
                <mx:TextInput id="tAuthor" />
            </mx:FormItem>
            <mx:FormItem label="제목">
                <mx:TextInput id="tSubject" />
            </mx:FormItem>
            <mx:FormItem label="내용">
                <mx:TextArea id="tBody" width="400" height="100"/>
            </mx:FormItem>
            <mx:Button label="글 등록"
                   click="svcCreatePost.send();svcPosts.send();"/>
        </mx:Form>
       
        <mx:ControlBar horizontalAlign="center">
            <mx:Button label="새로 고침" click="svcPosts.send();"/>
        </mx:ControlBar>
    </mx:Panel>
</mx:Application>       

레일스 어플리케이션의 DB 스키마
create_table "posts", :force => true do |t|
    t.string   "name"
    t.string   "subject"
    t.text     "body"
    t.datetime "created_at"
    t.datetime "updated_at"
end

레일스 어플리케이션 컨트롤러(REST)
class PostsController < ApplicationController
  # GET /posts
  # GET /posts.xml
  def index
    @posts = Post.find(:all, :order => 'created_at desc')

    respond_to do |format|
      format.html # index.html.erb
      format.xml  { render :xml => @posts.to_xml(:dasherize => false) }
    end
  end

  # GET /posts/1
  # GET /posts/1.xml
  def show
    @post = Post.find(params[:id])

    respond_to do |format|
      format.html # show.html.erb
      format.xml  { render :xml => @post.to_xml(:dasherize => false) }
    end
  end

  # GET /posts/new
  # GET /posts/new.xml
  def new
    @post = Post.new

    respond_to do |format|
      format.html # new.html.erb
      format.xml  { render :xml => @post.to_xml(:dasherize => false) }
    end
  end

  # GET /posts/1/edit
  def edit
    @post = Post.find(params[:id])
  end

  # POST /posts
  # POST /posts.xml
  def create
    @post = Post.new(params[:post])

    respond_to do |format|
      if @post.save
        flash[:notice] = 'Post was successfully created.'
        format.html { redirect_to(@post) }
        format.xml  { render :xml => @post.to_xml(:dasherize => false), :status => :created, :location => @post }
      else
        format.html { render :action => "new" }
        format.xml  { render :xml => @post.errors, :status => :unprocessable_entity, :dasherize => false }
      end
    end
  end

  # PUT /posts/1
  # PUT /posts/1.xml
  def update
    @post = Post.find(params[:id])

    respond_to do |format|
      if @post.update_attributes(params[:post])
        flash[:notice] = 'Post was successfully updated.'
        format.html { redirect_to(@post) }
        format.xml  { head :ok }
      else
        format.html { render :action => "edit" }
        format.xml  { render :xml => @post.errors, :status => :unprocessable_entity }
      end
    end
  end

  # DELETE /posts/1
  # DELETE /posts/1.xml
  def destroy
    @post = Post.find(params[:id])
    @post.destroy

    respond_to do |format|
      format.html { redirect_to(posts_url) }
      format.xml  { head :ok }
    end
  end
end

생성된 SWF
생성된 SWF 파일 결과


top

tags

flex, Rails, rest, Ruby on Rails, 개발, 레일스, 루비, 삽질, , 프로그래밍

posted at

2008/08/13 09:08


POST : 프로그래밍/개발

Flex 그리고 웹에 대한 짧은 생각

redmines 는 주말쯤에 시간이 날 때, 다뤄보기로 하고 이번엔 Flex에 대한 생각을 정리하려 합니다.
왜 갑자기 Flex 냐 하면.. 제가 새 직장을 얻게 되어서 앞으로 Flex를 가지고 벌어 먹고 살게 되기 때문이죠.

이번 주는 실제 Flex를 다루지는 않았고, 약간 실제 프로젝트와는 거리가 있는
일종의 수습 기간 중 테스트로서 차후에 쓰이게 될 지도 모르는 커스텀 ssh/sftp 서버를 만들었습니다.
(Python, Paramiko 라이브러리로 제작했는데 이것도 기회가 되면 블로그에 정리해야 겠습니다.)
생각보다 일찍 완성이 되어서 Flex 공부하는 셈 치고, 이거저것 만져보고 rails 와 붙여보는 작업을 해 봤습니다.

퇴근 시간 전까지 잠깐 시간내서 만들어 본거라 거의 맛만 본 수준인데,
만들어 본 어플리케이션은 간단한 게시판의 형태로 글 쓰기, 수정, 삭제 까지는 못 만들었고;;
그냥 리스트만 가져와서 화면에 출력해 주는 수준이었습니다.

서버 사이드로는 간단하게 Rails 프로젝트가 REST Web Service 를 서비스하고 있고,
클라이언트 사이드에서 Flex가 작동하여 HTTP Request 를 이용해서 XML 형태로 데이터를 받아오고
리스트를 구성해 화면에 출력해 주는 형태로 작동하게 했습니다.
Flex 에서 기본으로 제공하는 디자인은 깔끔했고 애니메이션 효과도 훌륭했고,
액션 스크립트의 웹 서비스 클라이언트는 REST 도 잘 지원되고 Ajax와 같이 귀찮은 작업도 거의 없고..
오~ 이만하면 훌륭합니다.  조금 반응이 느리고 무거워 보인다는 단점 외에는 별다른 흠 잡을데가 없더군요.

하지만 아무리 Flex 의 기능이 훌륭하고 멋지다고 해도, 어떻게 보면 결국은 고품질의 swf 를 찍어내기 위한 거대한 프레임워크일 수 밖에 없더군요.
완성되어 나와진 html 에는 swf를 embed 하는 태그와 왜 있는지 잘 모르겠는 iframe 뿐이고..
과연 이것이 웹을 올바른 방향으로 이끄는 것인가에 대한 의문이 들더군요.

좀 쓰잘데기는 없지만 웹이 나아가야할 올바른 방향은 무엇인가에 대한 이야기는 예전에도 생각했던 적이 있습니다.
초창기의 웹은 분명 연결된 문서의 형태였습니다.  하지만 지금의 웹은 그러한 모습이라고는 보기 힘듭니다.
블로그와 위키 정도만이 그 형태를 유지할 뿐 거의 어플리케이션의 형태로 가고 있다고 보고 있습니다.
Ajax 역시 그 움직임을 가속화 시키기도 했구요.

그렇다고 웹이 어플리케이션으로 가게 되는 것인가 라고 생각을 해보면 그것 또한 끔찍한 모습입니다.
화려하고 동적인 페이지를 위해서 실제 얻고자 하는 정보와 무관한 큰 크기의 리소스들(Ajax 에는 큰 덩치의 JS 프레임워크, Flex 등의 swf 파일)을 받아야 한다니..
사실 모뎀 말고, 초고속 인터넷이 등장한 후 분명 통신의 속도도 빨라졌고, 사용하는 컴퓨터의 사양도 좋아졌지만,
불필요하게 웹의 덩치도 그것에 맞추어져 예전이나 지금이나 웹의 속도는 별로 빨라지지 않았다는 느낌도 듭니다.
그것 뿐이겠습니까.. 만약 Flex나 Silverlight 런타임 플러그인 위에서 돌아가게되는 구글을 통해 내용 검색을 할 수도 없게 되겠지요. 그렇게 되면 점차 시맨틱 웹이라는 것의 의미는 퇴색되게 되겠지요.

하지만, 그렇다고 해서 연결된 문서의 형태로 웹이 남아있어야 한다고 생각하지는 않습니다.
확실히 웹이 어플리케이션화 하면서 재미가 있었지고 사람들의 생활을 이롭게 한 것은 사실이니까요.

그래서 근본적인 취지에 맞게 웹 본래의 장점을 살려보자고 등장하던 것이 REST 였지만...
Flex 에서 REST 서비스를 이용하는 방식을 보면, 글쎄요.. 정말 REST가 답인가 하는 생각마저 들기도 합니다.

웹은 확실히 가장 성공한 TCP/IP 어플리케이션이지만..
시맨틱 웹, 웹 2.0 등등의 수식어에 여기저기 휘둘리는 웹의 모습이 왠지 안쓰러워 보입니다.

무슨 글을 쓰고 있는 지도 잘 모르겠습니다.  아주 예전에 있었던 논쟁글 몇 개 링크하고 마무리 짓습니다.
김국현 씨와 윤석찬 씨는 제가 매우 존경하는 분들입니다.
존경하는 분들의 논쟁을 보면 정말.. 즐겁기 그지 없습니다. :)

차세대 웹은 브라우저를 초월하여
반론 : 차세대 웹은 브라우저를 초월하여
반론에 대한 기록 : 차세대 웹은 브라우저를 초월하여

이올린에 북마크하기(0) 이올린에 추천하기(0)
top

tags

Ajax, flex, RIA, siverlight,

posted at

2008/08/07 21:44


POST : 프로그래밍/개발

REST 와 레일스

레일스를 공부하기 시작한지도 벌써 1년이 다 되어가네요.
1년동안 사용한 것 치고는 크게 실력이 늘지는 않았지만, 이제야 어느 정도 감이 잡히고 있습니다.
레일스로의 입문은 쉽지만 어느 정도 파고들다 보면 새로 공부할 것이 많이 생기기도 합니다.
이제부터 이 블로그에 하나 하나씩 레일스와 관련된 지식들을 정리해 보려 합니다.
그 첫번째로 REST와 rails에 관련한 글로 시작합니다.

REST
우선 REST란 무엇인가 부터 짚고 넘어가야겠죠.
자세히 설명하기엔 실력도 부족하고, 더 좋은 설명들이 인터넷에 많기 때문에 아래의 링크로 대체 합니다.
REST가 무엇인지에 대해 굉장히 이해하기 쉽게 쓴 글입니다.

내가 아내에게 REST를 어떻게 설명했는가

간단히 말해서 리소스(표현의 대상)라는 것에 대해 URI와 HTTP METHOD로
그 리소스의 표현(html,xml 등등..)에 접근/제어하는 형식의 웹 아키텍쳐이죠.
간단히 말한다고는 했지만 전혀 간단하지는 않아 보이네요 :)

RAILS 2.0 의 scaffold
제가 레일스를 공부하는 중에 커다란 변화가 하나 있었습니다.
그건 레일스의 버젼이 1.2에서 2.0으로 업그레이드 했다는 점이었죠.
제가 2.0 버젼의 레일스를 쓰면서 가장 처음으로 당황했던 것은 바로
scaffold 가 생성해주는 코드였습니다.

/:controller/:action/:id 식의 라우팅이 아닌 다른 방식의 라우팅이라던가..
알 수 없는 repond_to 메소드에..
:url => { :controller => 'controller_name', :action => 'action_name' } 식이 아닌 url의 표현들이 꽤 낯설었었죠.
아래에 몇 개의 메소드만 붙여넣어 봅니다.
# POST /resources
# POST /resources.xml
def create
  @resource = Resource.new(params[:resource])

  respond_to do |format|
    if @resource.save
      flash[:notice] = 'Resource was successfully created.'
      format.html { redirect_to(@resource) }
      format.xml  { render :xml => @resource, :status => :created, :location => @resource }
    else
      format.html { render :action => "new" }
      format.xml  { render :xml => @resource.errors, :status => :unprocessable_entity }
    end
  end
end

# GET /resources/1
# GET /resources/1.xml
def show
    @resouce = Resource.find(params[:id])

    respond_to do |format|
      format.html # show.html.erb
      format.xml  { render :xml => @resource }
    end
end

# DELETE /resources/1
# DELETE /resources/1.xml
def destroy
  @resource = Resource.find(params[:id])
  @resource.destroy

  respond_to do |format|
    format.html { redirect_to(resources_url) }
    format.xml  { head :ok }
  end
end

시작은 routes.rb 부터...
레일스에서 REST의 시작은 config/routes.rb 로부터 시작합니다.

map.resources :posts

이 한 라인을 추가 하면, posts 리소스에 접근하기 위한 URI 들이 설정이 됩니다.

GET /posts
POST /posts
GET /posts/new
GET /posts/:id/edit
GET /posts/:id
PUT /posts/:id
DELETE /posts/:id


위에서부터 각각 PostController의 index, create, new, edit, show, update, destroy를 호출합니다.
그리고 뷰에서는 posts_url, new_post_url, post_url(@post), edit_post_url 등의 헬퍼를 사용해서 url을 표현할 수 있습니다.

또한 액티브레코드의 has_many 관계처럼 routes.rb 에서도 비슷하게 표현해 줄 수 있습니다.

map.resources :posts, :has_many => :comments

마찬가지로 아래처럼 라우팅이 설정이 되고, 각각의 헬퍼가 만들어 집니다.

GET /posts/comments
POST /posts/comments
GET /posts/comments/new
GET /posts/:post_id/comments/:id/edit
GET /posts/:post_id/comments/:id
PUT /posts/:post_id/comments/:id
DELETE /posts/:post_id/comments/:id

이 때의 헬퍼의 이름들은 comments_url(@post), new_comments_url(@post), comment_url(@post,@comment), edit_comment_url(@post,@comment) 등이 됩니다.

CRUD(Create, Read, Update, Destroy) 외의 액션에 대해 url을 만들어 주고 싶을 때엔 :collection 과 :member를 이용할 수 있습니다

map.resources :posts :member => {:recommend=>:put}
map.resources :posts, :collection => {:manage=>:get}

member의 경우는 /posts/:id/recommend 와 같이 하나의 리소스에 해당하는 액션일 때,
collection은 /posts/manage 같이 모든 리소스에 해당하는 액션일 때 사용합니다.
위의 :put과 :get 은 허용하는 http method를 의미하고 :any라고 쓰면 모든 http method(:get, :post, :put, :delete)를 허용합니다.

respond_to do |format|
그럼 scaffold의 각 메소드 끝에 나와있는 respond_to 에 대해서 살펴봅시다.
사실 위의 URI 매핑에서 생략된 것이 하나 있습니다.
바로 :format 이라는 건데, 리소스를 어떤 형태로 표현할 것인가에 대해서 요청합니다.
사실 위의 7개의 라우팅은 아래와 같은 또 다른 형태의 매핑이 있습니다.

GET /posts.:format
GET /posts/:id.:format
GET /posts/new.:format
GET /posts/:id/edit.:format
...

위와 같은 라우팅 규칙을 통해서 /posts.html, /posts.xml, /posts/1.html, /posts/1.xml 등의 요청이 커버됩니다.
/posts/1.xml 같은 요청의 경우 format 이라는 메소드는 xml 을 리턴하게 됩니다.
respond_to do |format| 에서 format 이 xml일 경우는 format.xml 에 해당하는 블럭을 실행하게 됩니다.

다시 한 번 말씀드리면 위의 REST 설명에도 잘 나와있듯이 리소스의 표현은
html 외의 다른 여러가지가 될 수 있습니다.
가장 주로 쓰이는 예로는 xml이 있겠지요. text가 될 수도 있고, pdf가 될 수도 있겠지요.
오픈API 같은 웹 서비스를 구현할 때 리소스의 표현을 xml로 이용하면 쉽게 구현할 수 있겠죠.

위의 scaffold 의 코드에서는 format이 html일 경우는 생략이 가능한데..
생략하게 되면 repond_to에서 디폴트로 가장 첫 라인의 format을 선택하기 때문이라고 하더군요.

----

REST와 레일스라고 거창하게 시작을 했는 데 결국은 레일스 2.0 scaffold 에서 생성한 컨트롤러 분석이 되버렸네요.
그래도 주위에 레일스 2.0의 접근을 어려워하는 분들이 있어서, 그런 분들에게 도움이 되는 글이었으면 좋겠네요.

이올린에 북마크하기(0) 이올린에 추천하기(0)
top

tags

Rails, rest, Ruby on Rails, 레일스, 루비, , 프레임워크, 프로그래밍

posted at

2008/07/31 21:10


POST : 프로그래밍/개발

웹 접근성을 생각하는 자바스크립트

요즘의 웹 사이트들은 점점 Ajax 의 사용추세가 늘어나고 있습니다.
하지만 사실 Ajax 에는 치명적인 단점이 있습니다.
바로 웹 접근성이죠.

Ajax 가 처음 등장했을 때 문제로 제기된 큰 문제가 몇가지가 있었는데..
그 중 하나는 뒤로 가기 버튼이었고, 다른 하나가 이 접근성에 해당하는 문제였습니다.

물론 모든 Ajax가 웹 접근성을 해치는 것은 아닙니다.
Ajax 를 사용하더라도 접근성을 해치지 않는 방법들이 여럿 고안되었으니까요.
하지만 국내에서 사용되고 있는 Ajax 의 대부분은 Javascript(또는 기타 클라이언트 스크립트)에만 의존하는 경향이 있습니다.

<a href="#" onclick="sampleFunction();"> 는 이제 그만.

그 중 가장 간단히 생각할 수 있는 것이 <a href="#" onclick="javascript:"> 등으로 시작하는 코드입니다.
하지만, Javascript 가 제대로 동작할 수 없는 환경에선 무용지물입니다. 그럼 어떻게 해야하는가..

<a href="대체 URL" onclick="return !sampleFunction();">

여기서 포인트는 두 개입니다. 대체 URL 과 sampleFunction() 앞의 ! 죠.
대체 URL 은 말 그대로 Javascript 가 동작하지 않을 때 이동해야할 페이지입니다.
물론 해당 동작에 대한 대체 페이지가 마련되어야 겠죠.

그러면 클릭할 때, onclick 이 실행되는게 아니라 대체 URL로 이동해버리는 것이 아니냐..라고 생각하시는 분들이 계실텐데..
!(느낌표) 는 그것을 막기 위해 고려된 것입니다.
여기서 조건은 sampleFuntion 은 xmlHTTPRequest 가 성공하면 True, 실패하면 False 를 리턴하도록 구현되어야합니다.

만약 sampleFunction 이 동작을 성공하면 True가 리턴되고, <a> 태그의 동작은 return false; 가 되어 실제로 페이지 이동을 하지않게 됩니다.

이올린에 북마크하기(0) 이올린에 추천하기(0)
top

tags

Accessibility, Ajax, , 자바스크립트, 접근성

posted at

2008/04/04 23:43


POST : 프로그래밍/개발

레일스(Rails)의 함정

Rails 는 정말 훌륭한 웹 프레임워크입니다.
하지만 편하다고 아무렇게나 코딩을 하게 되면 골치아픈 상황들이 여럿 발생합니다.
프레임워크에서 어떤 SQL을 생성하는지, 각 쿼리들은 속도가 어떠한지 꾸준히 확인을 해 줘야합니다.

이 포스팅은 제가 정말 생각없이 코딩을 하게 되어서 겪은 여러가지 상황을 정리한 것입니다.

#1. N+1 문제

흔히 말하는 N+1 케이스입니다.

멀쩡해 보이는 코드지만.. 날아가는 쿼리가.. 대략.. 이렇습니다...-_-

Eager Loading 으로 해결가능 합니다만..
Eager Loading 으로 쿼리의 수는 1개로 확실히 적어지지만, 항상 성능이 좋아지는 것은 아닙니다.

자세한 건 이 글 을 참고하시면 좋겠습니다.

덧붙여서 윗글의 정보와는 달리 현재 Edgerails 에서는 :preload 옵션이 없고 :include 를 사용해도,
preload 가 가능한 경우는 Eager Loading이 아니라 Preload 를 하도록 패치되어 있습니다.


#2. Find conditions 에 시간을 사용할 경우는 한 번 더 생각을...
얼마전 테스트를 하다가 우연히 발견했습니다.

어느 쪽이 더 빠를까요? 당연히 테이블 전체를 가져오는 1번보다 2번이라고 생각하기 쉽습니다.
그런데 실제로 해보면 예상치 못한 결과가 나오더군요.

첫번째 호출할 때는 2번이 빠른데.. 두번째 이상 호출을 하게 될 경우, 1번이 훨씬 빠릅니다.
답은 각자 생성하는 쿼리에 있었습니다.

1의 경우는

로 처음이나 두번째 호출 후나 일정한 반면에..
2의 경우는

처럼 초단위가 변해서 쿼리가 날아갑니다.

한마디로 쿼리 캐시가 안되고 계속 새로운 쿼리를 보내는 것이죠.
아마 1초단위 까지 정확히 하루 전이라고 하고 싶으면 어쩔 수 없겠지만..
초단위 혹은 분단위를 올림/내림 등을 하는 것만으로도 쿼리 캐시의 효과를 잘 이용할 수 있게 될 겁니다.


#3. Pagination 의 함정.
이번엔 페이지를 나누는 Pagination 에서 생기는 문제입니다.
레일스 2.0 에서는 Pagination이 레일스 코어에서 빠지고 플러그인 식으로 설치를 해야 하는데..
제가 설치해 본 대부분의 Pagination 플러그인이 같은 문제를 가지고 있었습니다.

Pagination의 동작은 크게 두 부분으로 나눌 수 있습니다.
페이지 표시를 위해 전체 레코드 수를 가져오는 것과 페이지 번호를 이용해 :offset 과 :limit 으로 특정 부분의 레코드를 가져오는 부분입니다.
Pagination 의 플러그인 중 하나인 will_paginate 같은 경우 다음과 같이 Paginate를 합니다.


find 의 옵션들을 그대로 쓸 수 있으므로 아주 편하게 paginate를 할 수 있습니다.
그런데 문제는 include 옵션이 들어가게 되면 문제가 발생합니다.
우선은 paginate 는 #1 에서 언급한 preload 가 구현이 되어 있지 않고..
두번째 문제는 전체 레코드 수를 가져오는 부분에서 쓸 데없는 Join 이 일어납니다.
위의 경우는.

와 같은 쿼리가 생성됩니다. 그런데, 위의 경우는 굳이 comments와 join 할 필요가 없고,
만약 join을 해아할 테이블이 훨씬 많아지면 오버헤드는 상상할 수 없을 정도로 커집니다.
단순히 레코드가 몇 개인지 세는 것 뿐인데 말이죠.

외국의 글입니다. 이 paginate 문제 의 해결책을 제시하고 있습니다만 count 를 하는 쿼리와 선택을 하는 쿼리를 직접 SQL 로 만들어서 하는 방식은 가장 유연한 방식이지만 그다지 깔끔해 보이진 않네요.

will_paginate 의 이슈 트래커에 정확히 같은 문제를 지적한 티켓이 올라왔군요.



이올린에 북마크하기(0) 이올린에 추천하기(0)
top

tags

Rails, Ruby, Ruby on Rails, 개발, , 프로그래밍

posted at

2008/04/02 22:39


POST : 프로젝트

PHP 웹 프레임워크 symfony 로 웹 프로그램 개발하기. < 설정 >

환경은 우분투 리눅스 6.10 Edgy eft 사용했습니다. 
이 문서는 symfony 공식 문서에 기반하고 있습니다.


선 symfony를 php에서 cli를 사용할 수 있어야합니다. cli는 command line interpreter의 약자로
쉘에서 php 프로그램을 실행시킬 수 있게 하는 인터프리터입니다.  cli 는 php 4.3.0 이후의 버젼에서 지원하기
시작했죠.  python이나 perl 같이 php를 쉘 스크립트로 사용할 수 있게 됩니다.

1. symfony 설치하기

$ sudo apt-get install php5-cli

symfony 는 아직 우분투 저장소에 올라오지 않은 모양입니다.  php-pear를 통해서 써드 파티 extension들을 구할 수 있으니 php-pear 패키지를 설치합니다.

$ sudo apt-get install php-pear

pear 를 이용해서 symfony 를 설치합니다.

$ sudo pear channel-discover pear.symfony-project.com
$ sudo pear install symfony/symfony

이로써, symfony 의 설치는 완료입니다.


2. symfony 프로젝트 시작하기

프로젝트 초기화
이제 symfony 를 이용해서 프로젝트를 시작해 봅시다.
일단 자신의 디렉토리로 이동해서 프로젝트 디렉토리를 생성합니다.

$ mkdir myproject
$ cd myproject
$ symfony init-project myproject

명령어 이후에는 아래와 같은 디렉토리들이 생성됩니다.

apps/
batch/
cache/
config/
data/
doc/
lib/
log/
plugins/
test/
web/


어플레케이션 생성
프로젝트는 적어도 하나의 어플리케이션을 포함해야합니다. 아래의 명령으로 어플리케이션을 생성합니다.

$ symfony init-app myapp

명령어 이후 아래와 같은 디렉토리 및 파일이 생성됩니다.

apps/
myapp/
config/
i18n/
lib/
modules/

web/
index.php
myapp_dev.php

templates/


웹 서버 설정
userdir 모듈을 사용하실 경우에는 module의 기본 설정 아래와 같은데..


AllowOverride File AuthConfig Limit

아래와 같이 편집하는 과정이 필요합니다.

AllowOverride all
Allow from all

적어도
<Directory "/home/dragonkun/symfony/myproject/web">
AllowOverride All
Allow from All
</Directory>

같이 해당 프로젝트 디렉토리 아래의 web 의 설정은 위와 같아야 합니다.

심볼릭 링크
프로젝트에서 라이브러리를 가져올 수 있도록 path를 연결해야 합니다.
프로젝트의 디렉토리로 이동 해서 다음과 같이 입력을 합니다.

$ ln -sf /usr/share/php/data/symfony/web/sf/


위의 디렉토리는 리눅스의 배포판이나 pear의 버젼 등등에 따라서 조금씩 달라질 수 있습니다.  이 점 유의하시기 바랍니다.

http://서버 주소/myproject/web 을 확인하시면 아래와 같은 결과를 얻을 수 있습니다.


다음에는 MVC 패턴에 대해서 알아보고, 직접 프로그램을 만드는 것을 다뤄보겠습니다.
이올린에 북마크하기(0) 이올린에 추천하기(0)
top

tags

php, Symfony, , 프레임워크

posted at

2007/02/09 17:06


POST : 프로젝트

PHP 웹 프레임워크 symfony 로 웹 프로그램 개발하기. < 준비 >

간만의 포스팅입니다 :)

이번에 삼성 SDS IT Festival에서 세미나 준비용으로 여러 웹 프레임워크를 뒤져보고 있습니다.
가장 유명한 조합인 Ruby + Rails 부터 Python + Django, PHP + Symfony or CakePHP 등등.
여러 웹 프레임워크들을 사용해보고 특징과 장단점 비교 등등을 하기에는 시간도 부족하고 어느 하나도 제대로 못 다루고 정말 겉핥기식이 될 것 같아서 PHP + Symfony 로 결정했습니다.

일단 조금이나마 공부해봤던 Ruby on rails 의 경우는 인지도가 가장 높긴한데, 당연한 이야기지만 Ruby 부터 제대로 공부해야 어떻게 프로그래밍이 되겠더군요.  물론 Ruby는 매우 흥미로운 언어인데다가 객체 지향적인 특징도 훌륭해서 공부해서 나쁠 것 없는 언어이긴 하지만 학습에 걸리는 시간이 꽤나 문제였지요.  게다가 80포트는 아파치를 돌리고 있어서 Webrick을 돌릴 수 없는 문제가(외부로 쓸수 있는 포트는 없는 상황).. 아파치랑 궁합도 그렇게 좋아보이지않구요.

다음은 Python인데, Python은 아파치의  mod_python 속도에 대한 불신으로 제외.  trac 같은 것도 써보긴 했는데, 속도가 그리 잘 나오지 않더군요.

다음은 PHP.  PHP는 기존에 잘 써 왔던 거라, 설정도 조금만 건드려도 되고. 언어도 이미 능숙한 상태라서 개발하기도 쉽겠다는 생각이 들더군요.  아파치랑 궁합도 잘 맞는데다 세미나를 해도 가장 많은 사람들이 알고 있을 법한 언어라는 생각도 들구요.  개인적으로 그냥 언어에 대한 평가는 Ruby == Python > PHP 쯤이지만, 웹 프레임워크들을 보니 다들 비슷비슷한 느낌이 들어서 그냥 PHP + symfony로 결정했습니다.

앞으로 조금씩 조금씩 세미나 준비를 하면서 웹 프로그램을 만드는 과정을 포스팅으로 남기려합니다.
그럼 symfony 로 삽질을 하러 가보겠습니다. :0
이올린에 북마크하기(0) 이올린에 추천하기(0)
top

tags

php, Symfony, , 프레임워크

posted at

2007/02/07 17:13


CONTENTS

Dragonkun in Tistory
BLOG main image

RSS 2.0Tattertools
공지
아카이브
최근 글 최근 댓글 최근 트랙백
카테고리 태그 구름사이트 링크