글 검색 결과 - 프로그래밍 (총 6개)
프로그래밍/개발
이 글은 작업 중에 있는 글입니다.
차후에 설명을 붙이도록 하고 우선 소스만 올려둡니다.
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
tags
flex,
Rails,
rest,
Ruby on Rails,
개발,
레일스,
루비,
삽질,
웹,
프로그래밍
posted at
2008/08/13 09:08
아직 트랙백이 없음 ::
트랙백
트랙백 주소 :: http://dragonkun.tistory.com/trackback/52
프로그래밍/개발
redmine의 홈페이지오늘 아침 출근해서 이것 저것 웹 서핑하다가 우연히 redmine 의 존재를 알게 되었습니다.
Python 의 trac 처럼 위키, scm, 이슈 트래킹 시스템 등등이 포함되어 있는 통합 프로젝트 관리 어플리케이션이죠.
동아리 홈페이지에 프로젝트를 공유할 수 있는 시스템을 마련하려고 하는 차에 이 놈이 딱 눈에 들어오게 됐네요.
레일스로 만들어진 어플리케이션이라 조금 수정을 하면 다른 레일스 어플리케이션이랑 잘 붙을 것 같더군요.
우선 기능을 몇 개 살펴보면, 위에 언급한 위키, scm, 이슈 트래킹 시스템 등은 모두 사용할 수 있습니다.
더욱이 기본적으로 멀티 프로젝트가 가능하고 trac 에는 존재하지 않았었던 프로젝트 별 포럼과 파일 저장소를 지원합니다.
단순히 프로젝트 관리 기능에만 충실했던 trac 과는 달리 뉴스, 문서 관리 시스템 등 일종의 커뮤니티 및 배포 사이트로서의 기능이 포함되어 있습니다.
일단 한 번 설치를 해 봅시다.
우분투 8.10 데스크탑 버젼을 기준으로 설명합니다.
우선 subversion 클라이언트가 설치되어 있지 않으신 분은
sudo apt-get install subversion
으로 subversion 클라이언트를 준비합시다.
다음은 최신 stable 버젼을 저장소에서 export 합니다.
svn co http://redmine.rubyforge.org/svn/branches/0.7-stable redmine-0.7
디렉토리로 이동 후 webrick을 실행합니다.
cd redmine-0.7
./script/server
제 경우는 레일스를 2.1.0 버젼으로 업데이트 했는 데 config/boot.rb 가 버젼이 맞지 않는다고 하더군요.
redmine 은 레일스 2.0.2 버젼을 필요로 합니다.
rake rails:update
명령으로 boot.rb 를 최신 버젼으로 업데이트 시킬 수 있습니다.
레일스가 설치되지 않으신 분은
sudo gem install -v=2.0.2 rails
로 2.0.2의 버젼을 설치하시던가, 최신 버젼의 레일스를 설치하시고 저처럼 아래와 같은 작업을 하시면 됩니다.
config/environment.rb 를 열어서, 아래와 같은 부분에서 RAILS_GEM_VERSION을 현재 자신이 사용하고 있는 레일스의 버젼과 맞추어 줍시다.
RAILS_GEM_VERSION = '2.0.2' unless defined? RAILS_GEM_VERSION
다음은 데이터 베이스 설정입니다.
저는 mysql을 이용하므로 mysql 서버에 접속해 데이터 베이스를 만들어 줍니다.
create database redmine_development default character set utf8;
create database redmine_production default character set utf8;
create database redmine_test default character set utf8;
사실 production 환경으로 돌리는 것이
가장 나을 거고 그러면 redmne_production 만 만들어 주면 됩니다.
기본으로는 development 환경으로 서버가 돌아가게 되는 데, config/environment.rb 등에서 RAILS_ENV 를 'production'으로 변경하면 production 환경으로 돌아가게 됩니다. 저는 다른 프로그램들과 연동시킬 생각이라 development 로 돌리기로 했습니다.
다음은 config/database.yml을 수정합니다.
cp config/database.yml.example config/database.yml
로 샘플 설정을 복사하시고, db 이름, db user 이름, db user 패스워드 등을 잘 설정하시면 됩니다.
우분투의 경우 mysql 소켓의 위치가 rails 기본값과는 달라서 아래와 같이 해 주거나 혹은 mysql gem 을 설치하면 된다고 합니다.
development:
adapter: mysql
database: redmine_development
host: localhost
username: root
password:
encoding: utf8
socket: /var/run/mysqld/mysqld.sock
./script/server
웹 서버를 돌려보려 하면, rfpdf 플러그인이 에러를 냅니다.(레일스 2.1 기준)
/home/alice/redmine/redmine-0.7/vendor/plugins/rfpdf/init.rb 의 소스 중
ActionView::Base::register_template_handler 'rfpdf', RFPDF::View
을 아래와 같이 수정합니다.
ActionView::Template::register_template_handler 'rfpdf', RFPDF::View
그래도 아직 에러를 내는군요.;;
app/controllers/application.rb 에 제일 첫째 줄에
require 'redmine'
이라고 적어줍시다.
그리고 rake!
rake db:migrate
rake 중에도 또 에러가 나는데..
db/migrate/072_add_enumerations_position.rb
db/migrate/078_add_custom_fields_position.rb
파일의 each_value 라는 메소드를 그냥 each로 바꿔 줍니다.
rake가 끝나면 마지막으로 webrick을 실행시켜 보기위해
./script/server
로 서버를 실행시킵니다.
그리고 localhost:3000 으로 확인해보면 끝!

심플하다 못해 썰렁해서 왠지 모를 허무감마저 든다.
심플하다 못해 썰렁한 디자인의 redmine 첫 페이지가 나오네요.
이거 삽질하다 보니 그냥 레일스 2.0.2에다 설치하거나 redmine 개발 버젼을 설치할 걸 하는 후회도 좀 드네요. :)
그래도 굳이 난 레일스 2.1에 stable 버젼을 쓰겠다고 고집하시는 분이 계시면 이 글이 도움이 되었으면 하네요.
좀 사용해보고 trac과 비교도 해보고 하려고 했는데, 설치까지만 하도록 하고 다음 포스팅거리로 남겨둬야겠습니다.
사용기 전에 설치편 번외편;; 정도로 mod_rails, svn 연동을 다룰까합니다. mod_rails 설정이야 별 다를 것 없겠지만 이왕 하는 김에 같이 다룰까 합니다.
tags
2.1,
Ruby,
SCM,
SVN,
trac,
Wiki,
개발,
레일스,
루비,
삽질,
설치,
위키,
프로그래밍,
프로젝트 관리
posted at
2008/08/05 22:14
아직 트랙백이 없음 ::
트랙백
트랙백 주소 :: http://dragonkun.tistory.com/trackback/49
프로그래밍/개발
저는 루비를 제대로 공부해 본 적이 없습니다.
다만, 파이썬을 약간 다뤄본 지식으로 몇 개 레일스 프로젝트를 맡아 진행해 왔었고,
간단한 레일스 어플리케이션을 작성하기 위한 최소한의 루비 지식을 가지고 있습니다.
그렇기 때문에 아직도 익숙치 않는 루비 문법들이 많이 있고, 익숙치 않아서 자꾸 쓰기를 꺼려하는 문법들이 몇 개 있습니다.
그런 문법들의 개념을 익히고 잘 사용해 보기 위해서 한 번 정리해 보기로 했습니다.
코드 블록루비 코드를 보게 되면서 처음으로 막히는 부분은 바로 코드 블록이었습니다.
코드 중간에 갑작스럽게 등장하는 중괄호나 do/end 키워드는 어떻게 해석해야할지 난해하기만 했습니다.
사실 지금도 루비는 초보 수준이라 코드 블록이 익숙하지는 않습니다. :)
코드 블록은 다음과 같이 쓰입니다.
object.method {
# 루비 코드들...
}
혹은
object.method do
# 루비 코드들...
end
메소드 뒤에는 당연히 인자들이 나열되어야 할 것인데.. 어째서 쌩뚱맞게 코드들이 나오는가?
하는 생각이 많이 들었죠.
이렇게 생각해도 되는 건지는 잘 모르겠지만..
코드 블록안의 코드들을 인자처럼 method 에 넘긴다고 생각하면 될 것 같네요.
실제로 메소드에서 인자로 요구하는 건 아니지만, 이해하기엔 그게 가장 쉽게 이해가 되더군요.
yield 키워드위에서 인자처럼 넘긴다고 했는데, 그건 그냥 이해를 쉽게 하기 위해서 그렇게 생각하는 것이고..
실제로는 메소드안에서 yield 키워드 부분이 코드 블록으로 대체가 되는 것이더군요.
더 자세히 보면 메소드가 코드의 일부분을 코드 블록에게 양보(yield)한다는
느낌일까요.
def yield_test
puts "시작"
yield
puts "끝"
end
yield_test { puts "yield 되었음" }
의 결과는
시작
yield 되었음
끝
이 되겠지요. yield 에서 인자를 넘길 수도 있고 코드 블록에서 리턴된 값을 받을 수도 있습니다.
def yield_test
puts "시작"
result = yield(10)
puts "결과는 #{result}"
end
yield_test do |x|
x * 5
end
시작
결과는 50
yield 키워드가 함수처럼 10 이란 수를 코드 블록으로 넘겨줬고, 코드 블록은 10을 x라는 블록안의 지역 변수로 넘겨 받았습니다.
또 코드 블록에서 수행된 x*5의 결과를 yield_test 안으로 리턴하여 yield_test의 result가 넘겨받았음을 알 수 있습니다.
each 메소드그 의미도 잘 모르고 계속 써 왔었던 Array 클래스의 each 메소드가 코드 블록을 보고 나니 다시 보이기 되더군요.
그냥 원래 그런 형태로 쓰는 거다 정도로만 생각하고 있었는데, yield 와 코드 블록을 이해할 수 있는 대표적인 예가 each 였네요.
[1,12,20,56].each { |i| puts i* 10 }
each는 Array 에서 한 원소씩 돌아가면서 계속 그 원소의 값을 인자로 yield를 하는 형식이겠죠.
yield에서 넘긴 인자를 코드 블록이 받아서 반복하는 형태의 가장 자주 쓰이는 코드 블록/yield의 예라고 할 수 있겠네요.
--
사실 최근에 취업과 관련해 면접을 보면서, rails 프로젝트를 진행한 것을 보고 루비를 잘 아시는 면접관 분이
루비와 레일스에 관련한 질문을 몇 개 하셨는데, 코드 블록에 대한 질문을 제대로 답변하지 못한 적이 있었습니다. 그래서 제대로 공부도 할겸 책도 찾아보고 인터넷 사이트도 뒤져보면서 알아보고 개념을 익히게 됐네요.
다음번에도 비슷하게 개념이잘안 잡힌 루비의 문법 등이 있으면, 정리해서 포스팅할 계획입니다.
이번 기회에 루비 공부도 확실히 해 두는 것이 좋을 것 같아서요. :)
tags
code block,
Ruby,
루비,
코드 블록,
프로그래밍
posted at
2008/08/03 01:26
아직 트랙백이 없음 ::
트랙백
트랙백 주소 :: http://dragonkun.tistory.com/trackback/47
프로그래밍/개발
레일스를 공부하기 시작한지도 벌써 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의 접근을 어려워하는 분들이 있어서, 그런 분들에게 도움이 되는 글이었으면 좋겠네요.
tags
Rails,
rest,
Ruby on Rails,
레일스,
루비,
웹,
프레임워크,
프로그래밍
posted at
2008/07/31 21:10
아직 트랙백이 없음 ::
트랙백
트랙백 주소 :: http://dragonkun.tistory.com/trackback/45
프로그래밍/개발
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 의 이슈 트래커에 정확히
같은 문제를 지적한 티켓이 올라왔군요.
tags
Rails,
Ruby,
Ruby on Rails,
개발,
웹,
프로그래밍
posted at
2008/04/02 22:39
아직 트랙백이 없음 ::
트랙백
트랙백 주소 :: http://dragonkun.tistory.com/trackback/41
일상
오늘 귀향하려 했으나 갑작스런 귀차니즘으로 내일 아침 표만 끊고 왔습니다.-_-
후배놈이
태어난지 몇일인지 알려주는 프로그램을 만든 포스팅을 올려서
할일도 없고, 파이썬도 가끔 연습해줘야 기억이 나겠다 싶어서 만들어 봅니다.
간단한 프로그램이다 보니 가독성보다는 코드의 길이;;;;에 신경을 썼습니다.
#!/usr/bin/python
import sys, string, datetime, time
def main():
if len(sys.argv) == 4:
print datetime.date.today() -datetime.date(string.atoi(sys.argv[1]), string.atoi(sys.argv[2]),string.atoi(sys.argv[3]))
elif len(sys.argv) == 5:
print datetime.date(string.atoi(sys.argv[1]), string.atoi(sys.argv[2]),string.atoi(sys.argv[3]))+datetime.timedelta(string.atoi(sys.argv[4]))
else:
print "Usage: mydate.py <year> <month> <day> or"
print "Usage: mydate.py <year> <month> <day> <wanted day>"
if __name__ == '__main__':
main()
그나저나 태터용 파이썬(및 C나 html, css 등도 지원하면 좋고) 코드 문법 강조 플러그인 하나 있었으면 좋겠군요.
tags
삽질,
파이썬,
프로그래밍
posted at
2006/10/03 21:59
트랙백 2개 ::
트랙백
트랙백 주소 :: http://dragonkun.tistory.com/trackback/18
- Tracked from 근영's World!! 2006/11/08 08:59 (삭제)
이전에 파이썬으로 프로그램해 본적이 없는데 지금이라도 프로그램을 시작해야 하는가? 물론이다. 테크놀로지 경주에 참여하려고 한다면 프로그래밍은 확실한 승리를 보장하는 승부수이다. 파이썬 프로그래밍 언어가 주는 혜택은 너무나 많은데 비해 비용은 너무나 적게 들기 때문에 여러분은 거의 확실히 승리할 것이기 때문이다. 파이썬의 힘은 그의 범용성에 있다. 일단 파이썬을 익혀만 두면 거의 모든 프로그래밍에 파이썬을 사용할 수 있다는 것을 알게 될 것이다. 언론..
- Tracked from 근영's World!! 2006/11/08 09:00 (삭제)
광운대학교 교내 신문에 기고한 글 (2000년 5월 29일자 신문 4면)국내에 아직은 많이 알려져 있지 않은 파이썬은 1990년 암스텔담에서 귀도 반 로썸(Guido van Rossum)이 개발한 객체 지향 스크립트 언어이다. 이 생소한 이름은 귀도가 좋아했던 영국 BBC 방송의 코메디물 'Monty Python's Flying Circus' 라는 프로그램에서 인용한 것이다. 파이썬의 사전적 정의는 다음과 같다.파이썬: 그리스 신화 파르나서스산의 동..