이 블로그 검색

2012년 12월 26일 수요일

JavaScript Allongé eBook 구입

얼마 전 Hacker News 에 소개된 전자책인데 leanpub을 통해 구입해서 읽고 있다 . PDF혹은 아이패드나 아이폰에서도 볼수 있는 eBook 형식으로 제공된다. JavaScript Allongé 는 기본 문법을 알고 있는 독자를 대상으로, 각 장마다 자바 스크립트의 함수를 사용하는 새로운 관점들을 소개하고 있다. 그리고 각 장이 끝날 때마다 recipes 항목을 통해서, 앞서 배웠던 항목을 기본으로,  실용적인 활용 법을 소개해주고 있다. 개인적으로 추천할만한 내용이라고 생각한다. 한번 방문해보시길...
(Allongé 는 에스프레소와 아메리카노의 중간 정도 되는 커피라고 한다~커피관련 지식은 덤^^)

2012년 12월 25일 화요일

node.js chat server with QT client

node.js tcp chatting server with QT client


node.js로 구현한 채팅 서버 및 QT로 GUI를 꾸민 클라이언트이다.
사용자 등록, 로그인, 대화상대 추가/삭제, 로그인/아웃 알림 및 메시지 전달 기능이 구현되어 있다.

Current features:
  1. enroll user
  2. add/remove friend
  3. login and retrieve my friend list
  4. notify logged in/out
  5. deliver chat message

Server

net, Buffer module을 이용해서 작성되었다. 클라이언트와 주고받는 패킷의 정의는 다음과 같다.

The Packet format is : binary data + string 
4 byte header (means a length of following message) + message

The message format is :
string|(delimiter)... 

제일 먼저 32비트 정수가 포함되고 이후에는 문자열로 구성된 양식이다. 헤더와 메시지를 구분하는 별도 구분은 없다. 문자열의 길이는 이 32비트 정수에 설정 된다. 메시지의 형식은 먼저 사용 목적이 나오고 이후 구분자로 구분된 데이터들이 전송된다. 예를 들어 로그인의 경우라면 전달되는 전체 데이터는 다음과 같게 된다.

ex) Login message
4byte_integerLOGIN|SomeUserId|SomePassWord~

즉, 바이너리 데이터와 문자열이 포함되는 형식인데, 결국 다음과 같은 C 구조체가 전송되는 것과 같다.

This can be described as a C structure like this :
typedef struct _PACKET_LOGIN
{
    unsigned int nLen; //4byte, contains 34
    char szMSg [30];    
} PACKET_LOGIN;

이러한 구조체 데이터에 nLen 에는 문자열의 길이 (30)이 설정되고 szMSg 에는 "LOGIN|someUserId|SomePassWord~" 문자열이 담겨져서 node.js 서버로 전송되는것과 같다. 그러므로 전체 데이터의 길이는 헤더에 설정된 메시지 길이(30 byte) + 헤더 자체의 길이 (4byte) = 34 byte가 된다.

인터넷에서는 echo 서버, 혹은 단순히 클라이언트의 데이터를 받는 즉시 브로드캐스팅하는 예제를 볼수 있다. 하지만 tcp의 메시지 경계 없음으로 인한 데이터 fragmentation을 고려해줘야 제대로 동작하는 서버를 작성할수 있다. 이 때문에 전달되는 데이터가 완전한 하나의 패킷이 될때, 해당 처리를 해주고 만약 기대하는 길이만큼 전송이 다 되지 않았다면, 지금까지 받은 데이터를 누적시키는 작업이 필요하다.
전달되는 데이터가 모두 문자열이라면, 일반 변수를 사용해서도 가능하겠지만, 지금 구현하는것은 헤더부분이 32비트 정수형이기 때문에 (즉 바이너리 데이터 + 스트링 의 혼합) 뭔가 다른 방법이 필요하다. 이때 node.js 가 제공하는 Buffer 모듈을 사용하면 문자열 데이터 뿐만 아니라, 정수형 데이터도 처리가 가능하다.

2012년 12월 11일 화요일

node.js 의 thread pool(libuv) 부분


node.js 에서의 입출력 동작은 멀티쓰레드(thread pool)로 구현된다.
소스 코드에서 이 부분을 정리해본다. 다음과 같이 파일을 비동기로 읽어오는 스크립트가 있을때,
함수 호출을 따라가 보면 다음과 같다.

var fs = require('fs');
fs.readFile('./bigFile.txt', 'utf8', function(err, data) {
    console.log(data);
});
console.log('exiting...');

사용자의 스크립트에서 호출한 fs.readFile 함수는 /lib/fs.js 에 존재하며
내부적으로 다음 함수 호출을 한다.

node.js : threads-a-gogo compile error


node.js를 위한 thread, threads_a_gogo 컴파일시 오류 해결 방법

2012년 12월 6일 목요일

node.js single thread / multi thread ?

node.js 는 단일 쓰레드 환경이다.
그런데 이 말은, 사용자의 스크립트가 단일 쓰레드에서 구동된다는 의미이다. 즉, 사용자의 요청들을 처리하기 위한 이벤트 루프가 하나의 쓰레드로 돌아간다. 그러나, 실제 비동기 작업은 멀티 쓰레드(thread pool) 로 구현된다.


위 그림은 Jeff Kunkel 의 Node.js Explained 유튜브 동영상을 갭쳐한 것이다. 우측으로 node.js 의 쓰레드들이 잘 나타나 있다. node.js는 비동기 작업을 위해 libuv 를 활용하는데 여기서 Thread Pool 을 만들어서 작업쓰레드 들이 요청들을 처리하게 된다.

2012년 12월 4일 화요일

꿀벌이 사라진 이후

꿀벌을 보고 공상하다. 아니 망상일까?
. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

꿀벌이 사라진 이후

꿀벌이 완전히 종적을 감추자, 과일등을 위주로 곡물생산량이 급감한다. 
인간들은 벌들이 사라진 근본원인은 생각하거나 개선하려 하지 않고, 
불완전한 유전자 조작 기술을 이용, 무성 생식이 가능한 생명체의 DNA 와 
농작물의 그것을 뒤섞어, 열매를 얻을수 있게 개량을 시도 하였다. 

2012년 12월 1일 토요일

2012년 11월 28일 수요일

node.js 분석


Node.js source code analysis

How node executes user code ?

최근 국내에도 node.js 컨퍼런스가 개최되는등 관심이 높아지고 있다. 그런데 기존 javascript를 어떻게 웹브라우져에 독립적으로 만들었고, 서버 사이드에서도 활용가능한 여러 기능들을 어떤식으로 추가했는지, 그 내부 사항을 node.js의 소스 코드를 따라가면서 간략히 알아보자.
(2014.11.09 일 node.js github에 올려진 소스 코드를 기준으로 작성됨)

Node.js 맛보기

node.js 는 기존의 자바스크립트 문법을 사용해서, 웹 브라우져로부터 독립적인 환경에서, 비동기 처리의 장점을 활용하여 서버 사이드에서 요구되는 여러 기능을 구현할수 있게끔 구현 되었다.
먼저 간단한 예제를 보자.

var fs = require('fs');
fs.readFile('./bigFile.txt', 'utf8', function(err, data) {
  console.log(data);
});
console.log('exiting...');

파일을 비동기로 읽는 예제이다.
사용자가 작성한 javascript (이하 js) 에서는 file system 기능을 가지고 있는 fs 객체를 require ('fs') 함수로 요청하여 얻고, 그 객체의 readFile() 함수를 이용하고 있다.
이 파일을 fsTest.js 로 저장하고, 다음처럼 실행하면,
$ cp /usr/share/dict/words bigFile.txt --> 이것은 큰 사이즈의 파일을 만들기 위한 작업
$ node ./fsTest.js
exiting...
A
a
aa
......
'exiting' 문자열이 바로 출력되고 이후, 파일에 대한 비동기 읽기 작업이 완료될때 나머지 결과가 출력되는것을 볼수 있다.
이 예제에서 보이는 require 나 readFile 식별자들은 자바스크립트가 기본적으로 제공하는것이 아니라는 점을 유의하기 바란다. 위의 예제를 크롬 웹브라우져의 자바콘솔에서 돌려 본다면 다음과 같은 에러를 만나게 될것이다.
ReferenceError: require is not defined

2012년 10월 26일 금요일

Linux Asynchronous I/O 예제


지금 프로젝트에서 작성한 프로그램의 개선점을 찾다보니, 비동기 작업 처리를 위해 aio를 이용하면 좋을듯 하다. 아래 사이트 내용을 참조하여 완전한 예제로 구성해보았다.
http://www.ibm.com/developerworks/linux/library/l-async/

2012년 10월 16일 화요일

ios6 개발: Autorotation, viewDidUnload

FeelingNote app에 ios6을 적용하다가 알게 된것을 간단히 정리.

1. Autorotation 변경



ios6.0 이전에는 app이 처음 기동될때, 다음 순서를 따랐지만
- shouldAutorotateToInterfaceOrientation: 
- viewDidLoad
- viewWillAppear:
- shouldAutorotateToInterfaceOrientation: 
- viewDidAppear:
    
ios6.0에서는 다음 순서로 app이 기동이 됬다.
- viewDidLoad
- viewWillAppear:
- viewDidAppear:

2012년 9월 28일 금요일

forever loop 를 활용한 error handling


함수내 에러처리에 대한 방법은 여러가지가 있겠으나, 최근 흥미로운 글 하나를 읽었다.
http://www.codeofhonor.com/blog/error-handling-using-forever-loop
for loop 를 활용한 기법인데 정리해보면 다음과 같다.

먼저 일반적인 함수내 에러처리 방식을 보면, 아마 다음과 같을것이다.

bool someFuncPlain () 
{         
    if (작업1 수행이 실패한경우)
    {
        에러 발생시의 추가 작업수행...;
        return false;
    }

    if (작업2 수행이 실패한경우)
    {
        return false;
    }
    ....
 
    // 함수내 모든 처리 완료      
    return true;
}


2012년 9월 20일 목요일

regex basic

[] => [] 안에 존재하는 문자들중 한 문자만을 나타낸다.
    예) [abc] 는 a , b, c 중에 한문자. '-' 는 범위. 즉 [a-f] 는 [abcdf]

 \w => [a-zA-Z0-9_]
 \d => [0-9]
 .  => 모든 문자에 대응되는 한 문자
 +  => 한 문자 이상(하나는 반드시 존재, repeats the preceding regular expression at least once)
 *  => 문자나 집합이 없는 경우 또는 하나 이상 연속하는 경우에 일치한다. 없어도 ok
 ?  => 문자가 없거나 하나와 대응하는 문자   예) https?// - s가 없거나 한번 있는 경우와 대응
    ca?r matches both `car' and `cr', but nothing else.
 \ => 문자그대로 . 를 나타냄 (이스케이프)

 ab{3}" => b가 3개까지 (abbb)
 ab{3,5}" =>  b가 3개에서 5개 까지 (abbb, abbbb, abbbbb )
 ab{2,}" => b의 개수가 2개 이상 (abb, abbbbb ...)
 {3,} => 최소 3번 일치함을 의미한다.

 () => ()안에 있는 글자들을 그룹화, 하위 표현식.
    a(bc)* : a라는 문자를 포함하고 bc라는 문자열이 없거나 계속반복( a, abc abcbc 등)
    a(bc)  : a라는 문자를 포함하고 bc라는 문자열이 있거나 없거나. (a,abc)

    (\d{1,3}\.){3}\d{1,3} => ip addr

 공백 문자 => \n, \r, \t, \f-form feed, \v-vertical tab
 \s => 공백 ,[\f\n\r\t\v],
 \S => 공백아님 , [^\f\n\r\t\v]

 |  => or 연산자, 묶음 안에서 하나를 일치시키고자 할 때
    IP주소를 구성하는 각 숫자 묶음을 유효한 조합으로 정의하는 규칙
    - 모든 한 자리 혹은 두 자리 숫자
    - 1로 시작하는 모든 세자리 숫자
    - 2로 시작하면서 두 번째 자리 숫자가 0부터 4사이의 모든 세 자리 숫자
    - 25로 시작하면서 세 번째 자리 숫자가 0부터 5사이의 모든 세 자리 숫자

    (((\d{1,2})|(1\d{2})|(2[0-4]\d)|(25[0-5]))\.){3}((\d{1,2})|(1\d{2})|(2[0-4]\d)|(25[0-5]))

    주민번호 : \d{2}(0[1-9]|1[0-2])(0[1-9]|[12][0-9]|3[01])-[1-4]\d{6}


탐욕적 수량자,  게으른 수량자
    *                            *?
    +                            +?
    {n,}                       {n,}?

    예) "<B>111</B> and <B>222</B>" 에서

    <[Bb]>.*</[Bb]>  => 111 and 222
    <[Bb]>.*?</[Bb]> => 111, 222

egrep 에서 111이후 대문자3자리로 끝나는  프로세스 검색
==> -w 옵션 사용

> ps -ef | egrep -w  '111[A-Z]{3}'


2012년 9월 10일 월요일

python decorator


#!/usr/bin/env python
# -*- encoding:utf-8-*-
import time

def elapsed_time(functor):
    def decorated(*args, **kwargs):
        start = time.time()
        functor()
        end = time.time()
        print "Elapsed time: %f" % (end-start)
    return decorated
    
@elapsed_time
def hello():
    print 'hello'

# 위의 코드는 다음과 동일.
# def hello(*args, **kwargs):
#     print 'hello'
# 를 정의후 다음을 호출하는것과 같음,
# hello = elapsed_time(hello)
# hello()

if __name__ == "__main__":
    hello()
    # hello = elapsed_time(hello)
    # hello()

Python Flask 설치 (windows)


0. 당연히 python은 먼저 설치되어 있어야 함.

1. easy_install, pip 설치 : 이것들은 Python 패키지들을 설치하고 관리하기 위한 도구이다. 다음 순서대로 수행.

  - easy_install 설치
  http://python-distribute.org/distribute_setup.py 을 다운받아서 실행.

  - PC path에 C:\Python27\Scripts 를 추가.  

  - pip 설치 : easy_install pip

2. 이제 Flask를 설치 할수 있다. 다음을 실행. 
  
  pip install Flask


* 여기서 부터는 옵션.

  virtualenv : 서로 다른 버전의 파이선, 라이브러리들과 작업해야 하는 경우에 자신의 프로젝트만을 위한 파이선 개발 환경을 만들수 있다. 사용하고 싶다면 다음을 실행.
  
  pip install virtualenv
  (혹은 easy_install virtualenv 으로도 가능)

  그리고 프로젝트 폴더상에서 다음을 실행
  virtualenv venv

  이제 관련 폴더들이 생성되고, 해당 프로젝트를 위한 환경이 구성되었다.
  해당 환경을 활성화 시키기 위해 다음을 실행한다.

  venv\scripts\activate

  프롬프트가 (venv) 로 변경됨을 알아두자. 이상태에서, pip install Flask 을 수행해서 개발환경을 만들수 있다. 이경우,
  \venv\Lib\site-packages 에 관련 패키지가 설치된다(즉, 프로젝트별 환경이 구성됨).

2012년 9월 3일 월요일

Ruby on Rails 간단 게시판 다시 만들어보기


예제 소스: https://github.com/jeremyko/RailsBoardSample/tree/moreRailsWay
참고한 문서 : http://ruby.railstutorial.org/ruby-on-rails-tutorial-book

앞서 예제를 좀더 수정해서 약간 더 개선시킨 소스이다. 추가된 부분은 다음과 같다.

1. RESTful routing
2. form_for , 모델을 폼과 연결
3. Partial 사용, 중복 제거
4. Validation check
5. bootstrap-sass

1. RESTful 제공

rails가 제공하는 resources 메서드 를 호출해서 RESTful한 route를 사용할수 있다.
route.rb 파일을 다음처럼 변경한다.

* route.rb
RailsBoard::Application.routes.draw do       
    root :to => 'my_rails_board_rows#index'
   
    #REST-style URI    
    resources :my_rails_board_rows
    
    #matchs...
    match '/listSpecificPageWork',  to: 'my_rails_board_rows#listSpecificPageWork'    
    match '/searchWithSubject',  to: 'my_rails_board_rows#searchWithSubject'    
    match '/EditViaPostReq',  to: 'my_rails_board_rows#EditViaPostReq'   
end

이렇게 한줄 추가함으로서 rails에서 처리가능한 route는 다음처럼 구성되게 된다.

< Table 1 RESTful URI >
# ------------------------------------------------------------------------------------
# request     URI                                       Action      Purpose
# ------------------------------------------------------------------------------------
# GET          /my_rails_board_rows             index    모든 게시물들 조회
# GET          /my_rails_board_rows/1          show     id 1의 게시물 조회
# GET          /my_rails_board_rows/new      new       새로운 게시물 작성을 위한 화면 보임
# POST        /my_rails_board_rows            create    새로운 게시물을 생성 처리
# GET          /my_rails_board_rows/1/edit   edit        id 1 게시물 수정을 위한 화면 보임
# PUT          /my_rails_board_rows/1          update   id 1 게시물 수정 작업 처리
# DELETE    /my_rails_board_rows/1          destroy  id 1 게시물 삭제 처리

게시물 CRUD 처리를 RESTful하게 처리하기 때문에, 이전 예제와 비교시 action이 간단해졌다. 또한 Rails는 url을 간단하게 표시할수 있게끔 helper를 같이 생성해주는데, resources :my_rails_board_rows 의 경우 다음과 같은 helper들이 생성된다.

    ------------------------------------------------------------------------------------
    helper                                            호출시 return 되는 값
    ------------------------------------------------------------------------------------
    my_rails_board_rows_path               /my_rails_board_rows
    new_my_rails_board_row_path          /my_rails_board_rows/new
    edit_my_rails_board_row_path(:id)    /my_rails_board_rows/:id/edit
    my_rails_board_row_path(:id)           /my_rails_board_rows/:id

RESTful 구현을 위해 컨트롤러를 작성해보자
resources 호출로  RSESTful한 접근을 설정한 경우, Rails 는 위에서 표시된 것처럼(예를 들어, my_rails_board_rows/new), 모델명을 기준으로 컨트롤러를 찾게 된다. 즉, my_rails_board_rows_controller.rb를 찾는데, 현재 이 파일이 없으므로 생성해줘야 한다.

2012년 8월 28일 화요일

Ruby on Rails 간단 게시판


(rails 에 관심있는 새내기에 의한, 새내기를 위한 글 입니다~~).

요즘 취미로 Ruby on Rails 에 대해 공부하고 있는데, 간단한 게시판 예제를 작성 해보자.

이 예제의 소스는 여기서 받을수 있다.
https://github.com/jeremyko/RailsBoardSample

여기서 만들 게시판은 앞서 spring, django 에서 예제로 만든것 과 동일한 기능의 게시판이다. 간단한 기능을 가진 게시판이라서, Rails가 제공해주는 scaffolding 을 사용하면 10분 이내로도 작성이 가능할 수 있지만, 이 예제에서는 scaffolding 을 사용하지 않고 처음부터 작성하는것으로 한다. 그리고 Rails 에서 가능한 여러 기능들 즉, RSpec을 사용한 BDD, REST지원, validation check, coffee script, 뷰에서의 partial 등은 일단 간단 게시판을 먼저 작성한후, 향후 포스팅을 통해서 점차 적용시켜보도록 할것이다.

rails와 ruby 개발 환경은 완료된 상태라고 가정한다.
이 예제에서의 사용된 개발환경은 다음과 같다.
ruby 1.9.3p194 (2012-04-20) [i386-mingw32]
Rails 3.2.8

그리고 사용할 DB는 기본 Sqlite 로 하기로 한다.
만약, Oracle 사용시에는 그에 따른 약간의 소스 코드 수정이 필요한데, 그것은 주석으로 표시하였다.

2012년 8월 14일 화요일

Windows 에서 Ruby on Rails (RoR) 3.2.8 + Oracle XE 11g



RoR 은 기본적으로 Sqlite 를 Database로 제공해주고 있다. 나는 Oracle XE를 개발용으로 사용중이라서, 여기에 맞춰서 설정을 해보기로 했다. 개발 환경은 다음과 같다.

Ruby 1.9.3
RoR  3.2.8
Oracle XE 11g

1. RoR 설치

설치 관련해서는 이미 많은 글들이 존재하므로 다시 내가 뭘 다시 써야할 내용은 없을 것 같다. 간단하게 말해보면, 먼저 Ruby를 설치하고 (http://rubyinstaller.org/downloads/), 이때 Windows 에서 gem 설치를 위해서 DevKit도 같이 다운로드 해서 설치한다. 그리고 명령 프롬프트 상에서 다음을 실행해서 RoR을 설치한다.
  gem install rails
DevKit설치는 다운받아 압축을 푼 디렉토리 내에서 다음을 수행한다.
  ruby dk.rb init
  ruby dk.rb install
(https://github.com/oneclick/rubyinstaller/wiki/Development-Kit 을 참조)

아니면, 간단하게 http://railsinstaller.org/ 에서 통합 패키지를 다운로드 받아서 설치할수도 있다.

2012년 8월 10일 금요일

Lvalue 와 Rvalue 정리

c++11 의 기능중에 Rvalue references 을 보다 보니, Lvalue 와 Rvalue 의 판단 기준을 다시 한번 정리해야 할것 같다. 내가 지금까지 이것들을 구분하는 기준은 대입연산자 왼쪽, 오른쪽으로 기준으로 원시적 판단을 했었는데, C++ 의 새로운 기능을 보다보니...머릿속이 헷갈리기 시작한다.
먼저, 일반적이고 간단한 예를 들어보면 :

int i = 3;

이경우엔, Lvalue = i, Rvalue = 3 이다.. 지금까지 판단 기준이 통하는군...
그런데 다음 경우는 어떠한가?

int i = 1;
int j = 2;
i = j; // Lvalue = i, Rvalue = j ???

위 경우에는 Rvalue 는 없다. i,j는 모두 Lvalue 이며, 컴파일러에 의해 lvalue-to-rvalue conversion 이 발생하면서 j 가 마치 Rvalue 처럼 작동할 뿐이다. 그래서, 명확한 정의를 찾던 중 http://www.codeproject.com/Articles/313469/The-Notion-of-Lvalues-and-Rvalues 에서 좋은 내용을 찾았다. 알기 쉽게 잘 설명되어 있어서 정리해본다.

introduction

필자는 Lvalues and Rvalues 에 대해서 심각하게 생각해본적이 없으며, 그런것이 문제되는 경우는 컴파일시 에러가 나는 경우가 대부분이었으며, 이 또한 쉽게 에러를 수정할수 있었다.
즉 다음 코드에서처럼 말이다.

int  NextVal_1(int* p) { return *(p+1); }
int* NextVal_2(int* p) { return (p+1); }

int main()
{
    int a[] = {1,2,3,4,5};
    NextVal_1(a) = 9;   // 에러. left operand must be l-value
    *NextVal_2(a) = 9;    // Fine. Now a[] = {1,9,3,4,5}
}

위 코드를 통해서 내가 말하는것을 잘 이해했길 바란다. 그런데 내가 C++0X 의 RValue reference 부분을 읽기 시작했을때, 내 비젼과 확신이 조금씩 흔들리기 시작했다. 내가 Lvalue 로 당연히 여기던 것들이 Rvalue 로 보이기 시작했다. 이 글을 통해서 L & R value들에 관련된 다양한 개념들을 간략하게 정리하려 한다. 이것과 관련된 여러가지 정보들을 다시 구글링할 필요가 없도록 하나의 정보로 모으기 위해 노력하였음을 알아주길 바란다. 모든 크레딧은 원 저자들에게 돌린다.

C++11(C++0x) 과 CodeBlock , mingw32-gcc


C++11 (C++0x) 기능을 CodeBlock, mingw32-gcc 를 이용해서 Windows에서 시험해 보자. 새로운 c++ 표준의 기능들을 시험해보기 위해서는 VC++ express 2010 를 비롯한 다양한 컴파일러를 이용해서 해볼수 있지만, https://wiki.apache.org/stdcxx/C++0xCompilerSupport 에서 확인 할수 있듯, 현재 MSVC보다는 GCC 가 새로운 feature들을 더 많이 구현해놓았다. 또한 테스트 코드를 생성해서 컴파일 명령을 직접 수행해서 테스트 해볼 수도 있지만, 공개 IDE 소프트웨어인 CodeBlock을 사용해서 테스트 할수 있는 환경을 만들어보자.  

http://www.codeblocks.org/downloads/binaries 에서 codeblocks-10.05-setup.exe 를 다운로드 받는다. mingw32-gcc 가 포함된 버전도 있지만, 여기 포함된 있는 mingw32-gcc 버전은 최신 버전이 아니다. 우리는 별도로 C++11 기능을 더 잘 지원하는 mingw32-gcc를 다운로드 받아서 설치 할것이다. http://code.google.com/p/mingw-builds/downloads/list 에서 mingw32-gcc-4.6.3-release-c,c++,fortran-sjlj.zip 를 다운로드 한다. 그리고 적당한 위치에 압축을 푼다.

C++11 의 간단한 예제로는 Range-based for-loop 기능을 한번 테스트 해보기로 하자.

설치된 CodeBlock을 실행하고, File -> New -> Project -> Console Application 을 생성한다. 사용언어는 CPP 설정. title은 "cpp11x_rangeForLoop" 로 한다.

이제, 다운받은 mingw32-gcc 컴파일러를 사용하게끔 환경 설정이 필요하다. Setting -> Compiler and debugger 를 연다. 기본 컴파일러로 GNU GCC Compiler가 설정이 되어있을것이다.

2012년 8월 8일 수요일

Django 게시판 만들기 4 - 검색 기능 구현


이제 검색 기능만 구현하면 이 간단 게시판은 완성이다. 우리는 전체목록 출력을 위한 listSpecificPage.html 템플릿 작성시, 검색 버튼을 누르면 /searchWithSubject/ 로 이동하게 해 놓았다. 그러므로, 지금까지 해왔던 것처럼 url 맵핑 및 컨트롤러 구현을 실시한다.

- url 맵핑
urlpatterns = patterns('',
    url(r'^$', views.home),
    url(r'^show_write_form/$', views.show_write_form),
    url(r'^DoWriteBoard/$', views.DoWriteBoard),
    url(r'^listSpecificPageWork/$', views.listSpecificPageWork),
    url(r'^viewWork/$', views.viewWork),
    url(r'^listSearchedSpecificPageWork/$', views.listSearchedSpecificPageWork),
    url(r'^listSpecificPageWork_to_update/$', views.listSpecificPageWork_to_update),
    url(r'^updateBoard/$', views.updateBoard),
    url(r'^DeleteSpecificRow/$', views.DeleteSpecificRow),
    url(r'^searchWithSubject/$', views.searchWithSubject),
)

- 컨트롤러 작성
@csrf_exempt
def searchWithSubject(request):
    searchStr = request.POST['searchStr']
    print 'searchStr', searchStr

    url = '/listSearchedSpecificPageWork?searchStr=' + searchStr +'&pageForView=1'
    return HttpResponseRedirect(url)

컨트롤러는 이미 우리가 작성해 놓은 /listSearchedSpecificPageWork 로 redirection 만을 하고 있다. 이전 시간에 게시물 보기 기능을 구현하면서 목록으로 돌아가기 기능 구현시, 먼저 검색을 위한 컨트롤러를 작성해 놓은 것이 기억날 것이다. 원래 그것은 검색 기능 구현시에 작성이 되어야 했던 것 (즉 지금)인데, 먼저 작성을 했었다. 그때 작성해놓은 것을 지금 사용하는것이니 착오없기를 바란다. 이미 만들어 놓은것이 있기 때문에 검색 기능 구현은 이처럼 간단하게 끝난다.

지금까지 django를 이용한 간단 게시판 작성 예제를 만들어 보았다. 오로지 실제 돌아가는 게시판 속성 작성을 염두에 두고 글을 썼고, django를 이루는 상세 내용은 건너뛴 부분이 많기 때문에 지금까지의 내용만 가지고는 django를 상세히 알수 없을 것이다. 자세한 세부 사항은 공식 사이트 문서를 참조하시길 바라면서 나처럼 실질적인 예제를 찾고 계셨던 분들에게 조금이나마 도움이 되었으면 하는 바람이다.


이 예제의 전체 소스는 아래에서 받을 수 있다.
https://github.com/jeremyko/dj_board


참고
https://www.djangoproject.com/
http://www.djangobook.com/en/2.0/



2012년 8월 7일 화요일

Django 게시판 만들기 3 - 글 조회 및 수정, 삭제 기능 구현


목록에서 글 보기를 위한 url은 /viewWork 로 설정했고, GET방식으로 글 조회를 위한 정보를 전달하게 되어 있었다. 그럼 할일은 앞서와 마찬가지로 url 과 컨트롤러 맵핑이 되겠다. 먼저 컨트롤러 추가.

def viewWork(request):
    pk= request.GET['memo_id']
    boardData = DjangoBoard.objects.get(id=pk)

    
    # 조회수를 늘린다.    
    DjangoBoard.objects.filter(id=pk).update(hits = boardData.hits + 1)

    
    return render_to_response('viewMemo.html', {'memo_id': request.GET['memo_id'],
                                                'current_page':request.GET['current_page'],
                                                'searchStr': request.GET['searchStr'],
                                                'boardData': boardData } )

여기서는 테이블의 PK값인 id를 알고 있으므로, model의 DjangoBoard.objects.get(id=pk) 츨 호출해서 해당 데이터를 얻을수 있다. 그리고 구한 게시물 정보를 템플릿으로 넘겨주고 있다. url을 추가한다.

urlpatterns = patterns('',
    url(r'^$', views.home),
    url(r'^show_write_form/$', views.show_write_form),
    url(r'^DoWriteBoard/$', views.DoWriteBoard),
    url(r'^listSpecificPageWork/$', views.listSpecificPageWork),
    url(r'^viewWork/$', views.viewWork),
)

그 다음은? viewMemo.html 템플릿을 생성한다. 간단한 게시판이라서 그런지 정말 간단하다.^^
  <html>
  <head>
  <title>글보기</title>
  </head>

  <script language="javascript">
      function boardlist()
      {
          var s = "{{searchStr}}";

          if(s=="None")
              location.href = '/listSpecificPageWork?current_page={{current_page}}';
          else
              location.href = '/listSearchedSpecificPageWork?pageForView={{current_page}}&searchStr={{searchStr}}';
      }

      function boardmodify()
      {
          location.href='/listSpecificPageWork_to_update?memo_id={{memo_id}}&current_page={{current_page}}&searchStr={{searchStr}}';
      }

      function boarddelete()
      {
          location.href='/DeleteSpecificRow?memo_id={{memo_id}}&current_page={{current_page}}';
      }
  </script>
  <table cellspacing = 0 cellpadding = 5 border = 1 width=500>
      <tr><td><b>조회수</b></td><td> {{ boardData.hits }} </td></tr>
      <tr><td><b>이름 </b></td><td> {{ boardData.name }} </td></tr>
      <tr><td><b>이메일 </b></td><td> {{ boardData.mail }} </td></tr>
      <tr><td><b>제목 </b></td><td> {{ boardData.subject }} </td></tr>
      <tr><td><b>내용 </b></td><td width=350> {{ boardData.memo }} </td></tr>
  </table>

  <table  cellspacing = 0 cellpadding = 0 border = 0 width=500>
      <tr><td>
          <input type=button value="수정" OnClick="javascript:boardmodify()">
          <input type=button value="목록" OnClick="javascript:boardlist()">
          <input type=button value="삭제" OnClick="javascript:boarddelete()">
      </td></tr>
  </table>
  </html>

여기까지 작업한 결과, 글 목록에서 해당 게시물을 클릭하면 다음처럼 내용이 조회된다.

Django 게시판 만들기 2 - 글쓰기 기능 구현

글쓰기 기능 구현

이제 글쓰기 기능을 구현할 차례이다. 글쓰기 버튼을 클릭시에 /show_write_form 이 호출되므로, 이 url을 컨트롤러에 맵핑해서 글쓰기 기능을 구현하면 된다. 먼저 /sample_board/view.py파일에 글쓰기를 위한 컨트롤러를 추가한다.

def show_write_form(request):
    return render_to_response('writeBoard.html')

그리고 dj_board/urls.py 에 다음처럼 추가한다.

urlpatterns = patterns('',
    url(r'^$', views.home),
    url(r'^show_write_form/$', views.show_write_form),
)

요청을 받으면 글작성을 위한 템플릿만을 화면에 출력하는 부분이므로 간단하게 처리한다. 그럼 이제, writeBoard.html 템플릿을 작성해야 한다. templates 폴더에 writeBoard.html 를 다음처럼 생성한다. form을 이용한 간단한 작성화면이 되겠다.

Django 게시판 만들기 1 - 설치 및 설정


Python 을 이용한 웹 개발 프레임워크인 django를 이용해서, 간단한 게시판을 만들어 보자. 앞서 스프링을 이용해서 작성된 게시판 과 동일한 기능을 수행하는 간단한 게시판이다. 먼저 django 프레임워크를 설치해야 한다.

2019-05-06 : 이글은 2012년도 기준으로 설명된 글이라서 현재 최신 django 버전과 일치 안되는 부분이 많습니다. 공식 django 문서를 참고하시기 바랍니다. (시간나는데로 업데이트 해보려고는 하는데 기약이 없음).

1. django 프레임워크 설치

* python 설치 : 일단 python이 설치가 되어 있어야 한다.

* Django 설치
직접 다운로드 받아 압축을 풀어서 셋업을 수행해도 되고, Svc, Git 등을 이용해서 최신소스를 받아오는 방법도 있다.  나는 git을 사용하므로 다음처럼 적당한 위치의 폴더에서 clone을 생성하여 소스를 받았다.

git clone https://github.com/django/django.git

그다음, 받은 폴더에서 다음을 수행한다.

python setup.py install

만약 'ImportError: No module named setuptools' 에러를 만나면 다음을 실행한다.
sudo curl https://bootstrap.pypa.io/ez_setup.py -o - | sudo python

파이선에서 다음을 실행해서  django 가 제대로 설치되었는지 확인한다.
>>> import django
>>> print django.get_version()
혹은 
>>> print (django.get_version()) 
혹은 
>>> python -m django --version

3.0

버전을 출력하면 설치는 제대로 된것이다.

* 윈도우 환경에서는 환경변수 PATH 설정:
django가 설치되면 python 설치 폴더의 \Lib\site-packages 안에 django가 복사된다. 이 경로를 PATH에 추가한다.  python 설치 폴더\Lib\site-packages\django\bin; 를 추가. python을 처음 설치했다면, python bin 경로도 PATH에 추가하는것을 잊지말자.

2. 프로젝트 생성 및 설정

이제 환경 설정이 완료되었으니, 실제 게시판을 생성해보자. 프로젝트 생성을 원하는 위치에서 다음 명령을 수행한다.


django-admin startproject dj_board


django게시판이란 의미로 프로젝트명을 dj_board로 하였다. 다음처럼 디렉토리가 구성된다.

dj_board/
      manage.py
      dj_board/
          __init__.py
          settings.py
          urls.py
          wsgi.py

본격적인 개발에 앞서 간단한 테스트를 해보자, 생성한 프로젝트 폴더에서 django에 내장된 개발용 웹 서버를 실행한다.

2012년 7월 25일 수요일

Spring Remote (RMI) 예제


오늘 살펴볼 스프링 Remote 중에서 RMI 지원은 단순한 POJO 작성만으로도 RMI 서비스를 간편하게 발행할 수 있게 해준다. 간단한 예제를 작성해보자. 일단 프로그램은 java application 으로 하였다. RMI를 통한 통신이므로 서버 및 클라이언트 2개 프로젝트를 만들어야 한다. 먼저 서버를 만든다.

* 서버 작성 *

소스코드는 다음을 참조한다. https://github.com/jeremyko/MySpringRMI

1. Eclipse 에서 신규 프로젝트를 생성한다.

File -> New -> java project -> "MySpringRMI" 프로젝트 생성. 그리고 스프링 관련된 라이브러리들을 프로젝트 속성 -> Java Build Path -> Libraries 에 모두 추가한다.

2. 스프링 설정파일을 다음과 같이 설정한다.

// spring_conf.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns:p="http://www.springframework.org/schema/p"
 xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd">

  <bean class="org.springframework.remoting.rmi.RmiServiceExporter"
    p:service-ref="helloService"
    p:serviceName="HelloService"
    p:serviceInterface="kojh.spring.rmi.HelloService" />

  <bean id="helloService" class="kojh.spring.rmi.HelloServiceImpl"/>
</beans>

<!-- p:registryPort="1107" -->

service-ref 에는 서비스를 담당할 bean 즉, helloService로 설정한다. serviceName 속성을 통해서 RMI 서비스명을 HelloService 로 설정한다, 나중에 보게 되겠지만 이것을 참조해서 client가 이 서비스를 호출하게 된다. serviceInterface 는 해당 서비스가 구현하고 있는 인터페이스를 설정한다. 참고로, 기본적으로 RMI가 사용하는 포트는 1099 이다. 이값을 변경하기 위한 속성은 registryPort 이다.

3. 서비스 인터페이스를 정의한다.

// HelloService.java
package kojh.spring.rmi;

public interface HelloService
{
    String sayHello(String name);
}

2012년 7월 24일 화요일

MyBatis-Spring : mapper interface 와 annotation을 활용한 게시판 예제


MyBatis-Spring : mapper interface 와 annotation을 활용한 게시판 예제

지난번 MyBatis-Spring 에 대한 소개 에 이어서, 이를 활용한 간단한 게시판 작성 예제를 작성해본다. XML파일에 맵핑을 정의하지 않고, mapper interface 와 annotation을 이용해서 처리하는것으로 해봤다. 게시판은 전체 목록 출력, 검색기능, 내용보기 및 수정, 삭제등의 아주 기본적인 기능만을 다루고 있다. 이 프로젝트의 소스는 다음 위치에 있으니 참조하시길 바란다.
https://github.com/jeremyko/SpringMvcBoardMyBatis

1. 우선 기본적인 스프링 MVC 프로젝트를 생성한다. 
간단하게 설명하기 위해서 스프링 환경 설정 부분은 생략했다. 일단 사용된 툴만 적어 보면 다음과 같다 (환경들은 알아서들 잘 맞추시길..자바는 환경 설정이 제일 어려운것 같다.^^).

- Eclipse Indigo(3.7)
- apache-tomcat-7.0.27
- Maven Integration for Eclipse
- SpringSource Tool Suite (STS) for Eclipse Indigo(3.7) 

- 데이터베이스: oracle 11g XE
사용된 이클립스 플러그인은 help -> Eclipse Marketplace 에서 검색.

이클립스 file -> new -> others -> SpringSource Tool Suite -> Spring Template Project -> Spring MVC Project 로 프로젝트를 생성.
그다음 pom.xml 파일을 열어서 dependency에 mybatis-spring 을 추가한다
    <!-- MyBatis -->
    <dependency>
      <groupId>org.mybatis</groupId>
      <artifactId>mybatis-spring</artifactId>
      <version>1.1.1</version>
    </dependency>


추가된 dependency를 반영하기 위해서 Run As -> Maven install을 수행한다.

Run As -> Run on Server로 생성된 프로젝트가 정상 작동 하는지 확인하기 바란다.
Hello World 라고 큼지막하게 웹 페이지가 뜨면 성공이다.

2. 게시판 테이블 및 seq 생성
이 예제에서는 오라클을 이용하고 있다. XE버전은 무료라서 개인이 사용하기에 좋은것 같다. 단지 단점이라면 리소스를 많이 잡아먹는다 (500 MB 메모리 사용). 이클립스가 사용하는 리소스도 상당한데, Oracle까지 돌리면 기본 1GB 정도는 그냥 두놈이 차지하게 된다. 컴에 램이 4GB 는 되어야 좀 돌릴만하다. 만약 다른 DB를 사용한다면, 아래의 내용을 참조로 수정이 필요할 수도 있겠다.

    CREATE SEQUENCE   "SEQ_ID"  MINVALUE 1 MAXVALUE 99999999999
    INCREMENT BY 1 START WITH 1 ;

    CREATE TABLE  "SPRING_BOARD"
    (
       "ID" NUMBER(10,0) NOT NULL,
       "SUBJECT" VARCHAR2(50),
       "NAME" VARCHAR2(50),
       "CREATED_DATE" DATE,
       "MAIL" VARCHAR2(50),
       "MEMO" VARCHAR2(200),
       "HITS" NUMBER(10,0),
        PRIMARY KEY ("ID") ENABLE
    ) ;


2012년 7월 20일 금요일

RIP, Jon Lord

                                                     Jon passes from Darkness to Light.
Jon Lord 9 June 1941 – 16 July 2012.





2012년 7월 18일 수요일

Git 활용 (기본적인 사용법)

http://gitimmersion.com/
 

http://try.github.com/levels/1/challenges/1



* 설정 

git config --global user.name "Your Name"
git config --global user.email "aaa@bbb.com"

라인 ending 설정 (윈도우경우)

    git config --global core.autocrlf true 

    git config --global core.safecrlf true

인코딩 설정:  윈도우 환경일 경우.

    git config --global i18n.commitEncoding cp949 

    git config --global i18n.logOutputEncoding cp949 

    물론 인코딩이 utf8 이라면 

    git config --global i18n.commitEncoding utf8 

    git config --global i18n.logOutputEncoding utf8


SSH-Key 생성

    ssh-keygen -t rsa

* 추적하지 않을 파일 설정하기

    .gitighore 파일을 생성, 패턴을 기술.

    echo "*.security" > .gitingnore
   
* 현 설정 확인

    git config --list


* Repository 생성

    git init

* 상태 확인  

    git status
   
* 변경사항을 staging 하기

    git add test.c
    git add .
   
    staged 상태 : Git가 변화를 인지한 상태, git add 를 수행하면 됨.
    아직 commit을 안한 상태이기때문에 변경사항이 영구적으로 저장된 상태가 아님을 나타냄.
   
* 커밋

    git commit -m "Changes for a and b"
    혹은 vi등 편집기를 통해 메시지 편집 시에는 그냥 git commit

    주의) 파일 수정후 add, 다시 파일 수정후, commit 을 하면,
    2번째 수정 사항은 staging안된 상태이다.
    커밋을 해도 2번째 수정 사항은 저장안됨.
    이때는 2번째 수정 사항에 대한 add 도 수행하고 그것에 대한 commit도 다시 수행 해야함.

     간혹 빈 commit 을 만들어서 push 해야 하는 경우가 (github pages 에 실패한 deploy를 다시 수행하는 경우 등등) 있는데, 다음처럼 수행하고 git push 한다.

     git commit --allow-empty -m "empty commit"  
   
* 이력보기

    git log git log --pretty=oneline --max-count=2
    git log --pretty=oneline --since='5 minutes ago'
    git log --pretty=oneline --until='5 minutes ago'
    git log --pretty=oneline --author=<your name>
    git log --pretty=oneline --all
    git log --pretty=format:\"%h %ad | %s%d [%an]\" --graph --date=short
    git log --all --pretty=format:"%h %ad | %s%d [%an]" --graph --date=short

    아직 커밋 안된 상태 에서 변경 사항 알아내기
     
        git diff HEAD 파일명       
        HEAD란 최종 커밋을 의미.

    2개 커밋 간 변경된 파일 목록 조회     
   
        git diff --name-only <commit hash1> <commit hash2>

    각 commit 별 변경된 파일 목록 조회

        git log --name-status


* 이전 버전 가져오기

    git log --all --pretty=format:"%h %ad | %s%d [%an]" --graph --date=short
   
    * cdb6848 2012-07-18 | 3 commit (HEAD, v1, origin/master, master) [kojunghyen]
    * b5cda22 2012-07-18 | 1st [kojunghyen]
    * 2314983 2012-07-18 | 2 commit [kojunghyen]
    * ece0e9f 2012-07-18 | first commit [kojunghyen]
   
    git checkout <hash>
   
    ex: git checkout 23149839d82ce5f104aa6fba72b201566da44ec6
   
    다시 master branch의 최신 버전으로 돌아오려면,
   
    git checkout master
   
    'master’ is the name of the default branch.
    By checking out a branch by name, you go to the lastest version of that branch.
   
   
* 태그 붙이기

    현재 버전을 v1이라고 하기로 하자.
        git tag v1
   
    바로 이전 버전을 가져오는 방법
        git checkout v1~1 => v1^
       
        ^ notation to indicate “the parent of v1”   
    이 이전 버전을 v1-beta라고 태그를 붙이자.
        git tag v1-beta
   
       
* 태그 조회
   
    git tag

* 태그 삭제 (로컬)  
   git tag -d <tag명>
* 태그 삭제 (원격)  
   git push --delete origin <tag명>
* 태그 삭제 (tag 명이 브랜치명과 같은 경우)
   -> 명시적으로 tag임을 지정해서 삭제해야 함   
   git push origin :refs/tags/<tag명> 


* stage->un-staged 상태로 변경하기

    git reset HEAD myfile


* 수정한 내용을 무시하고 처음 상태(최근 커밋된 버전으로)로 되돌리기

    git checkout -- myfile


* 커밋된 변경 되돌리기

    git revert HEAD
   
    This technique will work with any commit (although you may have to resolve conflicts).
    It is safe to use even on branches that are publicly shared on remote repositories.


* AMENDING COMMITS (커밋 수정하기, 혹은 기존 커밋에 추가하기)

    git commit --amend 

    add, commit된 상태에서 수정이 발생하였고 이전 커밋에 포함하고 싶은 경우(2개의 커밋생성없이).

* 여러개의 COMMIT들을 하나의 C OMMIT으로 합치기
    다음처럼 커밋 히스토리가 존재할때
    git log --oneline
    -->
    commit4
    commit3
    commit2
    first commit
    3,4 커밋을 합치고 싶은 경우,

    git rebase -i HEAD~2
    pick .......
    pick .......
    이것을 다음 처럼 변경  (출력 순서 주의 : 제일 위가 제일 오래된 커밋 이다, git log 와 반대)
 
    pick     ...
    squash ...
       
* MOVING FILES

    git mv hello.rb lib

    혹은 add 후 제거,

    git add lib/hello.rb

    git rm hello.rb
   
   
* branch 만들기
   
    git checkout -b 브랜치명

    => 이후 브랜치내에서 작업을 수행하고 commit한다.

    브랜치를 선택할 경우는

    git branch -a

    => 브랜치들을 리스트업, 이후 선택할 브랜치를 checkout 하면 됨

    git checkout master

    git checkout greet

   
* branch 제거
   
    git branch -d 브랜치명
   

* Merging

    git checkout greet

    git merge master

    => master변경분을 greet에 merge시킨다.


    예: clean_up branch를 만들고 작업후 master branch로 돌아와서 merge수행시
    git merge clean_up
   
   
* branch 변경 비교하기

    git diff --color branch1..branch2


* branch내에서 commit간 변경 비교하기

    git diff --color commit_hash1 commit_hash2

    => hash 시작 문자 일부만으로도 가능.


* 충돌 해소

    여러개의 BRANCH간 CHECKOUT시 불일치 발생 경우면 수동으로 해당 파일 수정후 ADD, COMMIT.


* branch push/pull 하기

    자신이 생성한 branch 를 원격저장소에 push

    git push origin my-branch


    원격 브랜치 가져오기: 먼저 원격 브랜치 확인

    git branch -r

    git checkout -b 생성할브랜치이름 원격브랜치이름

    동일한 이름을 사용한다면 -t 옵션 사용

    git checkout --track 원격브랜치이름


* REBASING VS MERGING

    rebase는 말 그대로 베이스를 다시 잡는 작업이다.
    변경사항을 적용할 기준(베이스) 브랜치를 지정하고 현재 브랜치의 변경사항을
    그 기준되는 브랜치에 적용을 하여 선형적인 커밋 히스토리를 만들어주므로
    지저분하지 않게 된다.

    다음설명이 가장 잘 이해됨.
    Choose to merge when you have a feature on a separate branch and want to bring that
    code into master or another branch.(feature branch 만들어서 다른branch 와 합칠거면
    merge 를 사용해라. 즉 일반적인 용도에 사용)

    Choose to rebase when you want to stay in sync with the main branch
    when you’re working on a long-lived side branch.(없어지지않고 계속 사용될 branch 와
    main branch 가 일치된 내용으로 가고싶을경우 rebase를 사용해라)

    다음 링크에서도 rebase 에 대해서 그림으로 잘 설명됨.
    rebase를 사용하지 말자는 내용임. feature branch에서 에러가 발생되면 rebase 시 
    모든 commit 에 에러가 포함되는 문제를 지적하고 있음. 
    그냥 간단하게 merge 를 사용하는게 좋다.
    https://medium.com/@fredrikmorken/why-you-should-stop-using-git-rebase-5552bee4fed1

    When to Rebase, When to Merge?
        Don’t use rebase … 커밋 히스토리를 변경시키기 때문이다.
        http://stackoverflow.com/questions/3357122/git-pull-vs-git-fetch-git-rebase
      
        정확한 커밋 히스토리가 중요한 경우에는 리베이스 사용을 자제.
   
    하지만 동일한 branch인 경우에는 선택의 여지가 있음 (아래 git pull 참고)


* add a remote repository

    git remote add origin git@github.com:jeremyko/try_git.git


* git fetch

    원격저장소의 변경사항 가져와서 원격브랜치를 갱신.


* Pushing Remotely

    로컬 변경을 origin repo (on GitHub)에 반영한다.
    -u 옵션은 입력인자들을 기억하는 옵션이다.
    이 경우 다음부터는 git push 만 입력하면 된다.
   
    git push -u origin master
   

* Pulling Remotely

    git pull
   
    remote repository의 변경사항을 가져온다. 그런데 pull명령은 다음과 동일하다.
   
    git fetch 
    git merge origin/master

    즉 변경 내용을 가져온후, 로컬의 변경사항과 머지하는작업이 동시에 일어난다.

    git pull --rebase
   
    pull 사용 시 매번 merge commit 이 생기는게 필요없는 경우
    (즉, 동일한 master branch만 pull로 가져오는 경우, master 브랜치끼리 merge commit 은
     불필요 할수 있으므로)
    --rebase 옵션을 주면 merge commit log 가 발생 하지 않게되어,
    좀 더 직관적인 이력관리가능.
   
* log 

    commit history 로그 보기.
    특정 사용자의 commit history 만 보고 싶다면, git log --author=userid

    특정 파일에 대한 log를 보고 싶으면, git log /xxx/yyy/source.hpp   

* stash

    만약 local의 변경 사항을 임시로 저장했다가 나중에 다시 적용하고 싶다면 'git stash' 로
    변경사항을 stash 한 다음, git stash list 로 목록을 확인할수 있다.
    예를 들면, feature branch에서 이슈에 대한 수정을 진행 중인데, master branch로 패치된
    내용을 반영하고 작업을 해야 하는 경우, commit 후에 master branch와 merge 할 필요없이
    stash로 수정사항을 보관 후, master 와 merge 후 다시, 작업 중이던 수정 사항을 반영 하면
    다시 이전과 같은 개발 중 상태가 된다.
   
    'git stash apply' 명령을 pull 작업 이후에 실행해서 재 적용 시킨다.
    git stash drop 을 수행해야 list 에서 삭제된다.
    (git statsh apply 대신 git stash pop 을 수행하면 자동으로 list 에서 삭제된다)
   
   
* cloning

    원격 저장소에 있는것을 복제하기 위해서는 git clone을 사용한다.
   
    git clone https://github.com/jeremyko/kothreadpool.git 

    git clone user@61.40.220.178:/path/rep_name.git my_repo_name

* Mac 사용시, .DS_Store 파일이 커밋되는것을 막으려면

    http://hints.binaryage.com/how-to-remove-ds-store-files-from-a-git-repo/


* local GIT Server 설정

    동일한 서버에서 여러 개발자가 개발하는 경우 간단하게 설정 가능.
    서버 위치는 /USER/kojh/serverRepository.git 디렉토리라고 가정.
    소스 존재 위치는 /USER/kojh/MySrc 라고 가정(이미 git init된 상태).

    1. remote 서버 역활 구성
   
        cd /USER/kojh/serverRepository.git
   
        git init --bare
   
   
    2. 소스를 서버에 push
   
        cd /USER/kojh/MySrc
   
        git remote add origin /USER/kojh/serverRepository.git
   
        git push -u origin master
   
   
    2. 개발자 1 의 작업
   
        git clone /USER/kojh/serverRepository.git dev1WorkSpace
   
        git remote add origin /USER/kojh/serverRepository.git
   
   
    3. 개발자 2 의 작업
   
        git clone /USER/kojh/serverRepository.git dev2WorkSpace
   
        git remote add origin /USER/kojh/serverRepository.git
   
   
    4. 이제 개발자1,2 가 일반적인 commit, push, pull 을 수행.


2012년 7월 17일 화요일

MyBatis-Spring




********************************************************************************
Getting Started
********************************************************************************


- 설치

MyBatis-Spring 을 이용하기 위해서는 mybatis-spring-x.x.x.jar 과 그 dependency들을 클래스 패스에 추가해야 한다. Maven을 사용중이라면 pom.xml 에 다음 dependency 를 추가한다.

<dependency>
  <groupId>org.mybatis</groupId>
  <artifactId>mybatis-spring</artifactId>
  <version>x.x.x</version>
</dependency>

- Quick Setup

스프링 어플리케에션 컨텍스트에는 기본적으로 다음 2가지가 필요하다.

1. SqlSessionFactory
2. 최소 하나이상의 mapper interface

SqlSessionFactory를 생성하기 위해 SqlSessionFactoryBean 이 사용된다. 즉 다음처럼 스프링 설정파일에 선언해야 한다.

<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
  <property name="dataSource" ref="dataSource" />
</bean>

데이터 소스가 필요한것을 잊지 말것. 그 다음 Mapper Interface 가 필요하다.

public interface UserMapper {
  // mapper XML 파일 대신 annotation 사용가능!
  @Select("SELECT * FROM users WHERE id = #{userId}")
  User getUser(@Param("userId") String userId);
}

2012년 7월 13일 금요일

베란다 화단 덮개 및 평상 만들기

이사올때부터 아..베란다에 공사좀 해야겠다라고 생각했었는데, 
이후 몇년동안 말만 하다가 드디어 지난 2012.6.2 부터 공사를 시작했다. 
일단 필요한 목재 견적을 내서 주문을 했는데 지금 보니 목재비가 만만치 않게 들었다. 
작업하다가 아이폰으로 간간히 찍은 사진들이다.