2012년 1월 17일 화요일

[서평이벤트~01.27] 아이튠즈 초보탈출! 아이튠즈 Using Bible 서평이벤트를 진행합니다.



[서평단 응모 방법]

1. 본 이벤트 게시글을 자신의 블로그에 전체공개로 스크랩합니다.

2. 본 이벤트 게시글에 아래의 내용을 덧글로 달아주세요.

-스크랩한 블로그 게시글 링크

-서평단 신청 이유

-서평 남겨주실 온라인 서점 2곳과 아이디
(해당 온라인 서점: 교보문고/예스24/인터파크/알라딘 4곳 중 2곳)


[서평단 모집 일정 및 인원]

모집기간 : 2012년 01월 17일~2012년 01월 27일

당첨자 발표 : 2012년 01월 28일

당첨인원 : 10명


[서평단 당첨자 숙지 사항]

1. 본 이벤트를 마치면 서평단에 선발된 회원 명단이 게시됩니다.
선발된 회원께서는 로즈헤어에게 쪽지로 도서를 받으실 성함/주소/연락처를 알려주세요.

2. 출판사에서 해당 주소로 책을 보내면 읽으신 후 2주 내에
서평 올리기로 한 온라인 서점 2곳에 서평을 올려주시면 됩니다.


[책소개]





평소 아이튠즈에 궁금한게 많았던 유저님들의 많은 참여 부탁드립니다. :)

2011년 6월 6일 월요일

첫 안드로이드 앱 개발

드디어 안드로이드 첫 앱인 "삶의 가이드(Life Guide)"를 안드로이드 마켓에 올렸습니다. 
근 1달 가량 퇴근 후 집에서 하루에 2~3시간 가량씩 근 20일 정도 투자해서 만들어 본 첫 앱입니다.
나와의 약속을 지키게 되어 더 의미가 있는 것 같습니다.

기존에 이 앱을 제 블로그에서 다운 받아 설치해서 사용하셨던 분들은 반드시 제거 후 설치하셔야 합니다.

책과 영화를 알라딘에서 검색해서 등록 후 읽어야 할 책들과 보아야 할 영화에 대해서 간단한 감상평을 등록 관리하는 앱입니다.
도서/영화 일지라고 보시면 될 것 같습니다. 내가 봤던 책과 영화의 일자, 그때의 느낌, 평가 등을 간단히 등록해서 관리할 수 있도록 한 어플입니다. 


안드로이드 마켓에서 "삶의 가이드"로 입력해서 검색하시면 검색목록에 나타나며, 다운로드 하셔서 사용해 보시고 많은 피드백 부탁드립니다.
아직 기능이나 완성도 면에서 많이 떨어지지만, 사용해보시고 추가 또는 보완해야 할 사항이 있으시면 언제든 알려주시면 고맙겠습니다.

2010년 2월 8일 월요일

JSTL을 이용해서 링크를 걸게 되면 걸린 URL 정보는 encoding 되어져 있게 된다.






        




링크 정보를 클릭 했을 때, 반응하게 되는 서블릿에서는 해당 파라미터에 대해서 디코딩하는 과정을 거쳐야 한다.
그래야만 정상적인 파마미터 값(특히 한글 및 특수문자들)이 정상적으로 나타나게 된다.

String id = request.getParameter("id");
id = URLDecoder.decode(id, response.getCharacterEncoding());

요청을 받는 서블릿에서 인코딩 된 문자열을 디코딩 해주어야 함.

이렇게 했는데도 불구하고 계속해서 Tomcat 에서 한글이 깨질 경우. server.xml 파일에서 부분을 확인한다.







URIEncoding에 사용하고자 하는 encoding 방식을 추가한다

2010년 1월 2일 토요일

Spring 2.5.6에서 ehcache 설정 방법

Spring 2.5.6에서 ehcache를 적용하기 위해서는 많은 라이브러리의 지원이 필요하다.
WEB-INF/lib 폴더 또는 클래스패스에 ehcache-core-1.7.1.jar 파일외에

  • backport-util-concurrent.jar
  • jsr107cache-1.1.jar
  • slf4j-api-1.5.8.jar
  • slf4j-jdk14-1.5.8.jar

참고로 Spring 3.0 에서는 ehcache-core-1.71.jar를 사용할 수 없음
Spring 3.0에서는 commons의 attributes를 지원하지 않기 때문이다.
나 또한 이것을 모르고 며칠을 고생했었으니....
아울러 KSUG의 박성철님께 고맙다는 말씀을 전하며...

2009년 12월 13일 일요일

AOP(aspect-oriented programming) 개념-2

대부분의 기술이 그러하듯, AOP(aspect-oriented programming)에도 역시 AOP(aspect-oriented programming)만의 전문 용어가 존재한다.
AOP에서 가장 중요한 용오로는 어드바이스(advice), 포인트컷(pointcut), 조인포인트(joinpoint)이며, AOP에서 이야기하는 핵심 용어들을 알아보자.


어드바이스(advice)
Aspect가 해야 할 작업을 AOP 용어로 어드바이스(advice)라고 하며, Aspect가 '무엇'을 '언제' 할지를 정의.
즉, 어드바이스(advice)는 Aspect가 해야 하는 작업과 언제 그 작업을 수행해야 하는지를 정의하는 것이다. 어드바이스(advice)에서 말하는 '언제'는 해당 작업이 메소드 호출 이전인지 이후인지, 아니면 이전/이후 모두인지, 이도저도 아니면 메소드에서 예외가 던져졌을 때만 적용되는 것인지를 의미한다.


조인포인트(joinpoint)
어드바이스(advice)를 적용할 수 있는 곳을 조인포인트(joinpoint)라고 함.
조인포인트(joinpoint)는 애플리케이션 실행에 Aspect를 끼워 넣을 수 있는 지점을 말함.
이렇게 끼워 넣을 수 있는 지점으로는 메소드 호출 지점, 예외 발생 지점, 필드 값 수정 지점 등이 있으며, 이러한 지점에서 Aspect 코드가 삽입되어 애플리케이션의 정상 흐름에 추가 작업을 더할 수 있게 된다.


포인터컷(pointcut)
포인터컷(pointcut)은 Aspect가 어드바이스할 조인포인트의 영역을 좁히는 일을 한다. Aspect가 무엇을 언제 할 것이냐를 정의하는 것이 어드바이스라면, 포인트컷은 '어디서' 하는 것인지를 정의한다.
포인트컷을 지정하는 방법은 클래스나 메소드명을 직접 사용하는 것이지만, 매칭 패턴을 나타내는 정규 표현식(regular expression)으로 나타내는 방법도 있다. 다른 AOP 프레임워크 중에는 동적 포인트컷을 사용할 수 있는 것도 있다. 동적 포인트컷은 메소드 인자 값처럼 실행시간(runtime)에나 얻을 수 있는 정보를 이용해서 어드바이스 적용 여부를 결정할 수 있게 해주기도 한다.


Aspect
어드바이스와 포인트컷을 합친 것을 말한다. 두 가지 정보가 합쳐지면 Aspect가 무엇을 언제 어디서 할지 정의할 수 있게 된다.


인트로덕션(introduction)
기존 클래스에 코드 변경 없이도 새 메소드나 멤버 변수를 추가하는 기능.


타깃(target)
어드바이스가 적용될 객체를 타깃(target)이라고 한다. 직접 작성한 객체 또는 서드파티 객체 모두가 타깃이 될 수 있다. AOP에서의 타깃 객체는 다른 주제 또는 관심사항은 고려할 필요 없이 오직 자신의 주요 관심사항에만 집중 할 수 있게 된다.


프록시(proxy)
스프링 AOP에서 프록시(proxy)는 어드바이스를 타깃 객체에 적용하면 생성되는 객체다.


위빙(weaving)
타깃 객체에 Aspect를 적용해서 새로운 프록시 객체를 생성하는 절차를 위빙(weaving)이라고 한다.

  • 컴파일 시간(compile time) - 타깃 클래스가 컴파일될 때 Aspect가 위빙되며 별도의 컴파일러가 필요. AspectJ의 위빙 컴파일러는 이러한 목적으로 사용.
  • 클래스로드 시간(Classload time) - 클래스가 JVM에 적재될 때 Aspect가 위빙된다. 이렇게 하려면 애플리케이션에서 사용되기 전에 타깃 클래스의 바이트코드를 인핸스(enhance)하는 특별한 ClassLoader가 필요. AspectJ의 로드시간 위빙(LTW:load-time weaving) 기능을 사용하면 클래스로드시간에 위빙된다.
  • 실행 시간(runtime) - 애플리케이션 실행 중에 Aspect가 위빙된다. 보통 타깃 객체에 호출을 위임하는 구조의 프록시 객체를, 위빙 중에 APO 컨테이너가 동적으로 만들어 낸다. 스프링 자체 AOP의 Aspect는 실행시간 위빙을 사용


AOP(aspect-oriented programming) 개념-1

근래에 들어 AOP(aspect-oriented programming)에 관한 내용을 많이 접하고 있을 것이다. 아니 이미 익숙한 용어가 되어져 있는 것 같다.


과거에 프로그램을 개발하다 보면 주요 로직 외에도 로깅(logging), 권한 등등의 처리를 위해서 각 업무상의 주요 로직 내에 해당 기능을 추가로 수행하기 위한 코드가 삽입되어져 왔었다.
애플리케이션 내의 여러 부분에 걸쳐 있는 기능을 시스템 공통 기능이라 보고, 이를 가리켜서 AOP 용어로는 횡단관심사(cross-cutting concerns)라고도 한다.
횡단관심사는 한 애플리케이션에서 여러 부분에 영향을 주는 기능이라고 할 수 있다.
아래의 그림처럼 특정 클래스 내의 메소드 내부에 시스템 공통 기능을 수행할 수 있는 메소드 호출들을 함으로써 주요 업무로직 외에 공통 기능도 추가됨으로써 개발자의 코드 작성 및 유지보수가 어렵웠었다.







이러한 부분을 개선하기위한 방법으로 나타난 AOP는 클래스의 상속 및 위임을 통해서 구현하지 못하는 영역들을 아주 자연스럽게 해결해주는 방법이 아닐 수 없었다.
Aspect 지향 프로그래밍(AOP: aspect-oriented programming)은 이러한 횡단 관심사를 애플리케이션의 업무 로직과는 분리하기 위한 것이다. AOP의 목적은 횡단관심사와 이에 영향을 받는 객체간의 결합도를 떨어뜨리기 위해 횡단관심사를 모듈화 하는데 있다.
즉, AOP에서는 횡단관심사를 Aspect라는 특별한 객체로 모듈화 하며, AOP가 다른 기법과 달리 차별화 되는 장점은 2가지가 있다.

  1. 전체 코드 베이스에 흩어져 있는 관심사항이 하나의 장소로 응집
  2. 서비스 모듈이 자신의 주요 관심사항(또는 핵심기능, 업모로직 등)에 대한 코드만 포함하고 그 외의 관심사항은 모두 Aspect로 옮겨져서 코드가 깔끔해짐

이러한 AOP의 여러 장점들로 인해 주목을 받고 있으며, OOP에서 구현하지 못하는 아니 구현하기 힘든 사항들을 보완하는 하나의 기술로 보면 될 것 같다.

2009년 11월 25일 수요일

변수 (Varables)

변수 (Variables)
어플리케이션 내의 값들을 저장하기 위해 사용하는 상징적인 명칭을 변수라고 한다. 변수들의 이름들은 식별자라고도 불리며 어떠한 규칙을 따른다.

자바스크립트 식별자는 반드시 문자, underscore(_), 또는 달러 기호($)로 시작해야 하며, 후속 문자로는 숫자도 가능하다. 자바스크립트는 대소문자를 구분하며, 문자는 “A”에서 “Z”와 소문자 “a”에서 “z”까지 사용 가능하다.

자바스크립트 1.5에서부터 유니코드 문자를 사용할 수 있게 되었다. \uXXXX유니코드를 이용해서 아래와 같이 식별자로 사용할 수 있다.
Category
Unicode value
Name
Format name
White space values
\u0009
Tab


\u000B
Vertical Tab


\u000C
Form Feed


\u0020
Space

Line terminator values
\u000A
Line Feed


\u000D
Carriage Return

Additional Unicode escape sequence values
\u0008
Backspace


\u0009
Horizontal Tab


\u0022
Double Quote
"

\u0027
Single Quote
'

\u005C
Backslash
\

적합한 변수 명칭 예로는 board_hits, year1990, and_name 등이 있다.

변수 선언 (Declaring Variables)

2가지 방법으로 변수를 선언:
  • 키워드 var를 사용하는 경우. var x = 10. 이러한 방법은 local global 변수 선언 모두에 적용됨
  • 단순하게 값만을 할당하는 경우. x = 10. 항상 global 변수로 선언하게 되며, 정적 자바스크립트 경고(warning)를 발생. 이러한 변수 선언을 사용하지 말아야 함
변수 평가 (Evaluating Variables)
var 문을 이용한 변수 선언에서 값을 초기화 하지 않을 경우 undefined 값을 가지게 된다.
선언되지 않은 변수에 대해서 접근을 시도할 경우 ReferenceError 예외를 발생시킨다.

var a;
print("The value of a is " + a); // prints "The value of a is undefined"
print("The value of b is " + b); // throws ReferenceError exception

변수에 값이 할당되어 있는지 확인하기 위해 undefined를 사용할 수 있으며, input 변수에는 값이 할당된 상태가 아니며 if 절에서 평가 후 true가 될 것이다.

var input;
if(input === undefined){
  doThis();
} else {
  doThat();
}

Undefined 값은 논리연산자와 함께 사용되어질 경우에는 false와 같다. 예를 들면, myArray 요소에 값이 정의되지 않았기 때문에 false를 리턴해서 myFunction 함수를 실행하게 된다.

var myArray = new Array();
if (!myArray[0]) myFunction();

변수 값이 null 일 경우, null 값은 정수와 함께 사용될 경우 0이 되며 논리연산 영역에서 사용될 경우에는 false 값이 된다.

var n = null;
print(n * 32); // prints 0




변수 범위 (Variable Scope)
특정 함수 바깥에 선언된 변수를 global 변수라 하며, 현재의 document에서는 어떠한 다른 코드에서 선언된 변수를 호출할 수 있게 된다. 함수 내에 선언된 변수를 local 변수라 하며 이것은 해당 함수 내에서만 사용할 수 있다.

자바스크립트는 block statement scope를 가지고 있지 않으며, block 내의 로컬코드가 될 것이다. 아래의 코드 예에서 보듯이 if문의 조건이 false가 되면 0이 리턴 될 것이다.

if (condition) {
  var x = 5;
}
print(x ? x : 0);
자바스크립트에서는 변수를 선언하기 전에 변수를 참조하더라도 예외 발생 없이 사용이 가능하다.

print(x === undefined); // prints "true"
var x = 3;

전역 변수 (Global Variables)
전역 객체(global object)의 속성으로 전역 변수가 있다. 웹 페이지에서의 전역 객체는 window이며, window.xxxx 형태의 구문을 통해서 설정과 접근을 할 수 있게 된다.

2009년 11월 19일 목요일

자바스크립트에서의 값들(Values)



자바스크립트는 아래와 같은 값들이 있다.
  • Numbers - 10 또는 3.14159와 같은 숫자 
  • 논리값 - true 또는 false
  • 문자열(Strings) - "Hello" 와 같은 문자열
  • null - null은 비어 있는 값을 가리키며, 아무것도 들어 있지 않은 빈컵을 상상해보시라. 자바스크립트에서는 대소문자를 구분하며, null Null, NULL은 분명히 다름.
    • null String 연산에서는 null
    • 논리연산에서는 false
    • 수치연산에서는 0 으로 변환
  • undefined - 변수만 만들고 값을 할당하지 않은 상태. undefined null에 포함되지 않음
자바스크립트에서 data type은 명시적 선언을 해야 하는 것이 아니며, 특정한 형 선언 없이 사용가능하며, type의 변환이 자유롭다. 정수에서 실수 사이에 명확한 구분이 존재하지 않으며, 정수를 보관했던 변수에 문자를 할당 하거나 객체(Object)를 할당할 수도 있다.
그러나 Date 객체와 메소드를 이용해서 날짜를 이용할 수 있으며, 자바스크립트에서 객체와 함수(Function)은 또 다른 기본 엘리먼트가 된다.


Data Type 변환
자바스크립트는 동적인 형변환이 가능한 언어다. 이것의 의미는 특정 변수 선언에 특정 type 선언을 하지 않아도 된다는 것이다. 형변환은 스크립트 실행시에 자동으로 이루어진다.

var answer = 19;  
이후에 다른 타입의 값으로 할당할 수 있다.

answer = "고마버~~";

자바스크립트는 동적인 형변환 언어이기에 이러한 할당에 대해서 오류 메시지를 발생시키지 않는다. 서로 다른 type간의 연산도 가능하다.


x = "답은 " + 12 // returns "답은 12"
y = 12 + " 가 답이다" // returns "12 가 답이다"
스트링타입의 숫자와 수치간의 연산은 좀 다른 결과를 보여준다.
"12" - 2 // returns 10
"12" + 2 // returns "122"

2009년 10월 26일 월요일

ExtJs를 이용한 FormPanel 만들기 예제1

ExtJs를 처음 접하고 Sample을 이용해서 여러 폼들을 생성해보았다. 기존 샘플 예제에서는 현업에서 사용하기 위한 폼의 한계가 있었고, 나름대로 이렇게 저렇게 디자인을 바꿔보면서 주로 사용하게 되는 폼을 중심으로 아니 내가 설계한 UI에 맞는 화면들 중심으로 설명을 하고자 한다.

ExtJs를 이용해서 폼을 만들때 다양한 방법으로 구성할 수 있지만, 나의 경우에는 가능한 Object들을 따로 생성해서 해당 FormPanel에 items로 추가하는 방법을 이용했다.
이렇게 한 이유는 한개의 화면에 생성되는 Object들을 명확히 할 필요가 있고, FormPanel에서는 이미 생성된 Object들을 items속성에 배열형태로 셋팅 함으로 스크립트의 가독성을 높일 수 있다고 생각했다.
실제 해보니 스크립트의 길이는 상당히 길어졌지만, 스크립트의 가독성 및 각 객체의 속성에 대한 구분이 좀 더 명확해지는 부분이 있었다.
이 보다 더 좋은 방법을 체험하기전까지는 현재의 방법으로 스크립트를 작성할 생각이다.

개발할 UI의 모습은 아래와 같다.










실제 개발을 하다보면 특정 값을 입력 받아서 해당하는 정보를 보여주는 형태의 UI가 꽤나 많다. 물론 복잡도는 이보다 더 높은 화면이 상당히 많이 있을 수 있다.

상기와 같은 화면을 구성하기 위한 JSP(HTML)와 JS파일은 아래와 같다.

JSP파일에는 div 태그를 이용해서 body부분에 div를 추가한다. div의 id를 'main_panel' 이라고 두자. 이 부분은 sample.js 파일이 로딩되면서 상기의 UI와 같이 화면을 보여줄 부분이다.

호출되는 sample.js파일의 내용을 살펴보자.

Ext.onReady(function() {
//Tooltip 제공을 위해서 global tooltip 초기화
Ext.QuickTips.init();

//사번을 입력 받기 위한 label 및 textfield 생성
var emp_no = new Ext.form.TextField({
fieldLabel: '사번',
id: 'empNo',
name: 'empNo',
allowBlank: false,
width: 100
});

//주민번호 입력을 위한 label 및 textfield 생성
var ssn = new Ext.form.TextField({
fieldLabel: '주민등록번호',
id: 'ssn',
name: 'ssn',
allowBlank: false,
width: 130
});

//확인 button 생성
var ok_btn = new Ext.Button({
text: '확인',
buttonAlign: 'center',
formBind: true,
handler:function(){ //버튼이 클릭 되었을때 실행되는 부분
alert('aaaa');
}
});

//사번을 Display하기 위한 label 생성
var emp_no2 = new Ext.form.Label({
fieldLabel: '사번',
id: 'empNo2',
name: 'empNo2',
width: 100
});

//성명을 Display하기 위한 label 생성
var emp_name = new Ext.form.Label({
fieldLabel: '성명',
id: 'empName',
name: 'empName',
width: 100
});

//부서를 Display하기 위한 label 생성
var dept = new Ext.form.Label({
fieldLabel: '부서(팀)',
id: 'dept',
name: 'dept',
width: 150
});

//연락처를 Display하기 위한 label 생성
var tel_no = new Ext.form.Label({
fieldLabel: '전화번호',
id: 'tel_no',
name: 'tel_no',
width: 100
});

var user_cnfm = new Ext.form.FormPanel({
labelAlign: 'right',
labelWidth: 140,
frame:true,
        title:'사용자 확인',
        buttonAlign: 'center',
        monitorValid:true,
items: [{
xtype:'fieldset',
layout:'column',  //컬럼 형태로 제공. 총 3개의 컬럼(emp_no, ssn, form)
items:[{
layout: 'form', // layout을 form으로 설정해야 라벨과 텍스트박스가 나타남.
items: [emp_no]
}, {
layout: 'form',
items: [ssn]
}, {
layout: 'form',
items: [ok_btn]
}]
}, {
xtype:'fieldset',
autoHeight:true,
collapsed: false,
layout:'column', // 컬럼형태.
items:[{
layout: 'form',
items: [emp_no2, dept]
}, {
layout: 'form',
items: [emp_name, tel_no]
}]
}]
});

user_cnfm.render('main_panel'); // FormPanel을 직접 그리는 부분
});

2009년 10월 20일 화요일

UI 설계 시 사용하기 좋은 툴 2종



제가 소개하는 툴은 balsamiq라는 툴과 pencil project라는 툴 2가지 입니다.

balsamiq의 경우는 Adobe의 air를 이용해서 구현된 툴입니다. 다양한 형태의 UI를 그릴 수 있도록 많은 컴포넌트를 제공하고 있습니다. 
balsamiq의 경우 자신의 블로그에 소개자료를 올린 후 라이센스를 요청하면 바로 라이센스를 보내줍니다. 한글을 이용하기 위해서는 View > Use System Fonts를 체크하시면 한글을 사용하실 수 있습니다. 손으로 그린 듯한 UI 디자인이 상당히 매력적입니다.


라이센스를 받기 위해서는 http://www.balsamiq.com/products/mockups/desktop#download 로 가셔서 아래에 있는 항목 중 제가 파란색으로 표기한 부분의 "email us"를 클릭해서 메일로 라이센스를 요청하시면 됩니다.
"자신의 블로그에 해당 툴을 소개하는 내용을 올린 후 블로그에서 툴에 대한 소개를 하고 싶다. 그러니 라이센스를 보내달라" 라고 하면 바로 라이센스를 보내줍니다.



GET MOCKUPS FOR DESKTOP FOR FREE

You can download Mockups for Desktop for free. Some of the features of the app, like saving and loading multiple mockups, can only get unlocked using a license key.
To get a free license key, you can do one of the following:
  • If your company bought Mockups for Confluence, JIRA or XWiki, ask your IT admin for your company's license information and use it FREE of charge.
  • If you are a do-gooder of any sort (non-profit, charity, open-source contributor, you get the idea), email us with a short blurb and we'll send you a license, FREE of charge.
  • If you are a technical/software blogger or journalist willing to write us up (honest reviews are the most useful to us) email us a short blurb with the link to your blog and we'll send you a license, FREE of charge, so that you can evaluate Mockups properly.
  • If you are willing to demo Mockups to an audience of at least 15 people (at a user group, a conference, a BarCamp), email us your info and we'll give you two licenses, one for you to keep and one to give away at the event, FREE of charge.
  • If you teach a high-school class, email us the name of your school and your class, plus the number of students in your class. We will send you a license for all of them.
  • A note to university students and professors: we currently do not offer free licenses to universities, but we'll be happy to offer you an additional 50% off any orders of 10 or more licenses. Let us know if you're interested and we'll set up a discount code for you.



Pencil projcet의 경우 라이센스는 GPL 2.0을 따르며 자세한 내용은 아래의 사이트에 가셔서 보시기 바랍니다.
파이어폭스용 툴과 Standalone 형태의 설치를 지원하며 window linux를 지원함다.
파이어폭스 3.0을 설치해서 사용하시는 분은 파이어폭스 Add-on 형태로 설치해서 사용하는 것이 더 편리할 수 있습니다.

2가지 툴 모두 일장일단이 있습니다.
Balsamiq의 경우 다양한 애플리케이션 UI를 그릴 수 있으며, 연필로 그린 듯한 느낌의 툴입니다. 다양한 애플리케이션 환경을 지원합니다. (윈도우, , 모바일 등등)
Pencil Project의 경우 window 환경에 최적화 된 UI를 그릴 수 있으며, 웹 및 모바일 관련 UI를 그리기에는 Balsamiq에 비해 상대적으로 조금 제한적입니다.

윈도우의 느낌을 최대한 살려서 UI를 그릴 경우에는 Pencil project를 이용하시면 될 것 같습니다