검색결과 리스트
2011/03에 해당되는 글 43건
- 2011.03.08 루씬과 색인,검색 클래스 사용예(Java)
- 2011.03.08 색인과 검색 주요 클래스
- 2011.03.07 로봇 프로토콜
- 2011.03.04 자바 개발자를 위한 루비적 관점
- 2011.03.03 [Spring Roo] (4) Roo 설치하기
- 2011.03.03 [Spring Roo] (3) Roo 아키텍처
- 2011.03.03 [Spring Roo] (2) Roo를 사용하는 이유
- 2011.03.03 [Spring Roo] (1) Spring Roo란? (4)
- 2011.03.03 HMAC-SHA1 구현
- 2011.03.03 [MySQL] 사용자 계정 생성/외부접속 허용
글
루씬과 색인,검색 클래스 사용예(Java)
인덱싱 클래스 ATIndexer
인덱싱 데이터는 트위터에서 수집한 status 데이터를 별도 저장한 텍스트 파일을 사용하였으며,
한건의 트윗글에 대해 status_id(글번호), text(내용), user_id(사용자번호), user_name(사용자이름)
데이터만 사용하였다.
루씬이 제공하는 필드에 따라 인덱싱하는 방법을 표현하기 각 데이터에 대해 다음과 같은 필드생성 옵션을 주었다.
status_id : Field.UnStored 를 사용. 분석과 검색을 수행하지만, 저장되지 않기 때문에 검색결과에서 보여줄 수는 없음
text : Field.Text 를 사용. 분석과 검색, 저장을 허용하여, 검색결과로 원문을 보여줄 수 있다.
user_id : Field.UnIndexed 를 사용. 검색어로 사용할 수 없지만, 다른 필드의 검색결과에서 같이 보여질 수 있다.user_name : Field.Keyword 를 사용. 분석을 하지 않지만, 검색과 저장을 한다. 검색시 이 필드는 분석되면 않되기
때문에 직접 텀쿼리를 만들어 IndexSearcher의 search 메소드에 전달해야한다.
인데싱에 사용한 파일(crawled_text.data)의 포맷
... status_id:2147483648 text:@NicoleLapin so many buttons user_id:12 user_name:Jack Dorsey status_id:2147483648 text:In alaska for the longest day of the year with Delphine and eWee. Seaplanes. Sunshine. user_id:14 user_name:noah glass ...
소스 : ATIndexer.java
package net.game.lucene.study;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Logger;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.RangeQuery;
import org.apache.lucene.search.TermQuery;
// IndexSearcher
// Term
// Query
// TermQuery, RangeQuery, PrefixQuery, BooleanQuery, PharaseQuery, WildcardQuery, FuzzyQuery
// Hits
public class ATSearcher {
private String indexDir;
private IndexSearcher indexSearcher;
private Analyzer analyzer;
private Logger log = Logger.getLogger(ATSearcher.class);
public ATSearcher(String indexDir, Analyzer analyzer) throws IOException {
BasicConfigurator.configure();
this.indexDir = indexDir;
this.analyzer = analyzer;
this.indexSearcher = new IndexSearcher(this.indexDir);
}
public Hits search(String field, String searchWord) throws Exception {
Hits hits;
// user_name필드는 직접 텀쿼리를 생성하여 전달해야 올바른 검색결과를 얻을 수 있음
if (field.equals("user_name")) {
hits = this.indexSearcher.search(new TermQuery(new Term(field, searchWord)));
} else {
Query query = QueryParser.parse(searchWord, field, this.analyzer);
hits = this.indexSearcher.search(query);
}
return hits;
}
public static void main(String[] args) throws Exception {
BasicConfigurator.configure();
ATSearcher searcher = new ATSearcher("/Users/hiddenviewer/index_lucene", new StandardAnalyzer());
String line;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("<검색필드:검색어> 입력! (종료: quit)");
while ((line = br.readLine()) != null) {
if (line.startsWith("quit")) {
System.out.println("ATIndexer Test 프로그램 종료!");
break;
}
int delimIndex = line.indexOf(":");
if (delimIndex == -1) {
System.out.println("<검색필드:검색어> 포맷으로 입력해주세요");
continue;
}
Hits hits = searcher.search(line.substring(0, delimIndex), line.substring(delimIndex+1));
System.out.println("------------------------------------------");
System.out.format("검색결과 개수: %d \n", hits.length());
System.out.println("------------------------------------------");
for (int i = 0; i < hits.length(); i++) {
Document d = hits.doc(i);
System.out.format("%20s: %s \n", "status_id", d.get("status_id"));
System.out.format("%20s: %s \n", "text", d.get("text"));
System.out.format("%20s: %s \n", "user_id", d.get("user_id"));
System.out.format("%20s: %s \n", "user_name", d.get("user_name"));
}
}
}
}
검색 클래스 ATSearcher
ATIndexer 가 인덱싱한 색인파일에서 검색을 하기 위해서 필드명:검색어 형태로 입력을 받는다. 필드명에 해당하는 필드에서
검색어가 포함된 도큐먼트를 찾아 검색결과를 출력해준다. 이때 중요한 것은 인덱싱 과정에서 Field.UnIndexed 로 지정한 user_id 필드는
검색어를 통해 검색할 수 없으며, 다른 필드를 통한 검색결과에만 포함되어 나온다. 또 Field.UnStored로 지정한 status_id 는 글번호로 검색은
가능하지만, 원문을 저장하고 있지 않기 때문에 결과에는 원문이 출력되지 않는다. Field.Keyword 로 지정한 user_name은 인덱싱과정에서분석이 되지 않기 때문에, 검색과정에서도 분석기에 의해서 분석되면 안된다. 검색필드가 user_name 인 경우에는 텀쿼리를 직접생성하여
IndexSearcher의 search 메소드에 전달해줘야 올바른 결과를 얻을 수 있다.
소스 : ATSearcher.java
package net.game.lucene.study;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import org.apache.log4j.BasicConfigurator;
import org.apache.log4j.Logger;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.RangeQuery;
import org.apache.lucene.search.TermQuery;
// IndexSearcher
// Term
// Query
// TermQuery, RangeQuery, PrefixQuery, BooleanQuery, PharaseQuery, WildcardQuery, FuzzyQuery
// Hits
public class ATSearcher {
private String indexDir;
private IndexSearcher indexSearcher;
private Analyzer analyzer;
private Logger log = Logger.getLogger(ATSearcher.class);
public ATSearcher(String indexDir, Analyzer analyzer) throws IOException {
BasicConfigurator.configure();
this.indexDir = indexDir;
this.analyzer = analyzer;
this.indexSearcher = new IndexSearcher(this.indexDir);
}
public Hits search(String field, String searchWord) throws Exception {
Hits hits;
// user_name필드는 직접 텀쿼리를 생성하여 전달해야 올바른 검색결과를 얻을 수 있음
if (field.equals("user_name")) {
hits = this.indexSearcher.search(new TermQuery(new Term(field, searchWord)));
} else {
Query query = QueryParser.parse(searchWord, field, this.analyzer);
hits = this.indexSearcher.search(query);
}
return hits;
}
public static void main(String[] args) throws Exception {
BasicConfigurator.configure();
ATSearcher searcher = new ATSearcher("/Users/hiddenviewer/index_lucene", new StandardAnalyzer());
String line;
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("<검색필드:검색어> 입력! (종료: quit)");
while ((line = br.readLine()) != null) {
if (line.startsWith("quit")) {
System.out.println("ATIndexer Test 프로그램 종료!");
break;
}
int delimIndex = line.indexOf(":");
if (delimIndex == -1) {
System.out.println("<검색필드:검색어> 포맷으로 입력해주세요");
continue;
}
Hits hits = searcher.search(line.substring(0, delimIndex), line.substring(delimIndex+1));
System.out.println("------------------------------------------");
System.out.format("검색결과 개수: %d \n", hits.length());
System.out.println("------------------------------------------");
for (int i = 0; i < hits.length(); i++) {
Document d = hits.doc(i);
System.out.format("%20s: %s \n", "status_id", d.get("status_id"));
System.out.format("%20s: %s \n", "text", d.get("text"));
System.out.format("%20s: %s \n", "user_id", d.get("user_id"));
System.out.format("%20s: %s \n", "user_name", d.get("user_name"));
}
}
}
}
ATSearcher 실행결과
결과를 보면 Field.UnStored로 지정된 필드 status_id는 원문이 출력되지 않는 걸 알수 잇다.
'검색엔진로그' 카테고리의 다른 글
| [Lucene] java.lang.OutOfMemoryError : Java heap space (0) | 2011.03.15 |
|---|---|
| 루씬과 색인,검색 클래스 사용예(Java) (0) | 2011.03.08 |
| 색인과 검색 주요 클래스 (0) | 2011.03.08 |
| 로봇 프로토콜 (0) | 2011.03.07 |
설정
트랙백
댓글
글
색인과 검색 주요 클래스
Apache OpenSource Project인 Lucene 을 구성하는 색인과 검색과 관련된 주요 클래스를 알아보자.
색인 주요 클래스
색인과정 중에 사용되는 주요 클래스는 다음과 같다.
| 클래스 | 설명 |
|---|---|
| IndexWriter | 색인을 생성하고, 색인에 도큐먼트를 추가한다. |
| IndexReader | 색인에서 도큐먼트를 삭제한다 |
| Directory |
색인의 저장소. 일반적으로 파일시스템 FSDirectory와 메모리 RAMDirectory가 있다. 루씬 샌드박스에서 제공하는 데이터베이스를 색인의 저장소로 사용하는 JDBCDirectory 도 있다. |
| Analyzer |
내용을 텀 단위로 분리하는 역할을 하며, 색인과 검색 단계에서 동일한 분석기가 적용되야 올바른 검색결과를 얻을 수 있다. |
| Document |
검색을 위한 정보 구성의 단위가 된다. 하나의 메일 메시지 또는 하나의 웹페이지가 도큐먼트가 될수 있으며, 비지니스 로직에 따라 변경된다. |
| Field |
도큐먼트 내에서 정보를 검색하는 대상(카테고리)이다. 분석의 여부, 검색 가능여부, 저장하는지 여부에 따라 Keyword, UnIndexed, UnStored, Text 필드로 구분된다. 이러한 구분의 검색과 검색결과로 보여질 데이터의 항목들을 명확히 하여, 검색의 질과 효율을 높이기 위함이다. |
색인은 양질의 검색결과를 얻을 수 있도록 하는 근본이 되는 과정이다. 도큐먼트는 색인과 검색과정에서 정보의 저장과 검색의 단위가 되기 때문에, 어떠한 데이터들을 하나의 도큐먼트로 구성할지가 중요한 요소가 된다.
도규먼트를 구성하는 필드들은 다음과 같은 값들 일 수 있다.
| 필드 | 분석 | 검색 | 저장 | 사용 용도 |
|---|---|---|---|---|
| Field.Keyword | X | O | O | 변경되지 않는 고유정보 저장하기 위해 사용됨. 예) 파일의 경로, 메일번호, 게시물 번호 |
| Field.UnIndexed | X | X | O | 검색의 결과로 보여주기 위해서만 사용되는 정보. 예) 웹페이지 글의 상위 네번째줄까지 글.... |
| Field.UnStored | O | O | X | 검색의 대상이 되지만, 화면에는 보여질 필요가 없는 정보. 예) 웹문서의 태그... |
| Field.Text | O | O |
String(O) Reader(X) |
String 타입은 내용이 색인에 저장되고, Reader 타입은 내용이 색인에 저장되지 않는데, Reader는 불필요하게 많은 데이터를 저장하여 효율을 저하시킬 수 있기때문에 저장하지 않는다. |
검색 주요 클래스
검색과정 중에 사용되는 주요 클래스는 다음과 같다.
| 클래스 | 설명 |
|---|---|
| IndexSearcher |
색인에서 검색어를 찾아 결과를 반환하는 클래스. 검색단계에서도 검색어를 분석하는데 Analyzer 가 사용된다. 이때 색인단계와 검색단계에서 동일한 텀이 생성되게 하는 것은 루씬 라이브러리를 사용하는 개발자의 몫이다. |
| Term | 매칭이 되는 가장 최소단위의 단어이다. 색인과 검색과정에서 (필드이름, 단어) 의 쌍으로 구성된다. |
| Query |
루씬엔진이 해석할 수 있도록 검색의 조건을 변환한 클래스이다. TermQuery, RangeQuery, PrefixQuery 등 다양한 조건에 해당하는 Query문이 존재한다. 개발자는 사용자에게 적절한 검색인터페이스를 제공하여, 올바른 Query 을 생성해야한다 |
| QueryParser | 다양한 조건을 좀더 편리하게 문자열 조건문 형태로 입력받고, 이 문자열을 Query 서브클래스들의 조합으로 변환한다. |
| Hits |
IndexSearcher 클래스의 search 메소드의 검색결과 매칭된 도큐먼트들을 가지고 있는 결과객체이다. 실제 문서의 내용이 아닌 문서에 대한 ID 만을 가지고 있어서, 실제로 요청할 때 해당 도큐먼트를 디스크에서 로드해서 반환한다. |
'검색엔진로그' 카테고리의 다른 글
| [Lucene] java.lang.OutOfMemoryError : Java heap space (0) | 2011.03.15 |
|---|---|
| 루씬과 색인,검색 클래스 사용예(Java) (0) | 2011.03.08 |
| 색인과 검색 주요 클래스 (0) | 2011.03.08 |
| 로봇 프로토콜 (0) | 2011.03.07 |
설정
트랙백
댓글
글
로봇 프로토콜
하지만 사이트 호스트 입장에서는, 보호하고 싶은 자료들도 있을 텐데... 크롤러를 대비해서 모든 문서를 별도로
관리하기란 여간 번거로운 일이 아니다. 호스트는 로봇배제파일과 로봇프로토콜을 사용하여 크롤러(로봇 )에게
노출하고, 숨길 페이지들을 명시해 줄 수 있다. 그럼 로봇배체 파일과 로봇 프로토콜에 대해서 알아보자
1. 로봇 배제파일과 로봇 프로토콜이란?
특정 웹크롤러에게 사이트 내 수집대상에서 제외할 페이지를 명시한 파일을 로봇배제 파일이라고 한다.
이 로봇 파일은 해당 웹사이트의 루트 위치에 robots.txt 라는 이름으로 존재하며, 이 파일이 따르는 프로토콜을
로봇 프로토콜이라고 한다. 크롤러가 반드시 이 프로토콜을 따르도록 하는 규제는 없으며, 양심적인 크롤러라면
이 프로토콜을 따를 것이다. 프로토콜은 크롤러의 종류를 명시하는 User-agen 항목과 사이트 내 수집을 배제할
페이지 패턴을 나타내는 Disallow 로 구성된다.
2. 로봇 프토토콜
User-agent: *<= 크롤러의 이름, *는 모든 크롤러에 해당함
Disallow: /<= 수집배제할 페이지 패턴, 모든 페이지에 대한 수집을 금함
위 로봇 프로토콜은 모든 크롤러의 모든 페이지 접근을 제한하고 있다.
User-agent: *
Disallow: /
User-agent: Googlebot
Disallow: /cgi-bin/
Disallow: /privatedir/
로봇 프로토콜은 표준은 아니지만 구글 크롤러만 인식할 수 있는 Allow 항목을 지원한다.
User-agent: *
Disallow: /
User-agent: Googlebot
Allow: /
사용하지 않는 것이 좋다.
3. 로봇 메타태그
웹호스트가 robots.txt 파일의 업로드를 허용하지 않는데도, 특정 페이지의 수집을 허용하고 싶지 않을 때, robots.txt 대신에
로봇 메타태그를 사용할 수 있다. 로봇 메타태그는 일반적인 html의 메타태그와 유사하게 HEAD 섹션에 기술된다.
(no)index는 크롤러에게 페이지 인덱싱을 허용할 지 말지를 결정한다. noindex 또는 index 값을 갖을 수 있다.
(no)follow는 크롤러에게 페이지 상에 존재하는 링크를 따라가서 수집하게 할지 말지를 결정한다. nofollow 또는 follow 값을 갖는다.
4. 몇가지 잘 알려진 로봇 식별자들
| 홈페이지 | 로봇 식별자 | IP address |
|---|---|---|
| www.google.com | Googlebot | c<nn>.googlebot.com |
| www.naver.com | dloader(NaverRobot) / dumrobo | 211.218.151.209 |
| www.daum.net | RaBot | 210.183.28.46 |
| ... | ... | ... |
'검색엔진로그' 카테고리의 다른 글
| [Lucene] java.lang.OutOfMemoryError : Java heap space (0) | 2011.03.15 |
|---|---|
| 루씬과 색인,검색 클래스 사용예(Java) (0) | 2011.03.08 |
| 색인과 검색 주요 클래스 (0) | 2011.03.08 |
| 로봇 프로토콜 (0) | 2011.03.07 |
설정
트랙백
댓글
글
자바 개발자를 위한 루비적 관점
핵심클래스 확장(Core Class)
Java에서는 SDK와 같은 Language Runtime의 핵심클래스에 메서드를 추가할 수 없기 때문에 확장메서드들을
다른 클래스의 정적메서드로 모아두는 방식을 선택함 (공백문자열인지 검사하는 StringUtils의 isBlank 메소드)
루비의 클래스들은 개방되어 있어서, 언제든지 수정 가능함
class String
def blank?
empty? || strip.empty?
end
end
루비의 nil은 자바의 null 에 해당하지만, 객체이며, 메소드 호출 및 추가가 가능
class NilClass
def blank?
true
end
end
불변객체의 장점
스레드 안정성 - 객체를 변경할 수 없기 때문에 스레드 충돌이 없음
캡슐화 용이
효율적인 해시키 생성 - 해시코드가 변경되지 않기 때문
가변(Mutable) 객체와 불변(Immutable) 객체
자바는 가변과 불변 2가지 버전의 클래스들이 존재하며, final 키워드를 사용해 불변성을 지원함
루비는 클래스가 아닌 인스턴스 수준에서 가변성이 이루어지는데, freeze 메서드를 호출하면 불변이됨
자바의 불변클래스에 변경메소드 호출은 변경된 새로운 객체를 리턴함
루비문자열은 자동 불변속성은 아니지만, 변경메소드에 대해 새로운 객체를 리턴함
루비 메소드기호 관례
Boolean 값을 반환하는 메소드는 ?로 끝남
객체의 값을 바꾸는 메소드는 !로 끝남
대입문에 사용되는 메소드는 =로 끝남
패키지와 네임스페이스
자바는 package 키워드를 사용해 네임스페이스를 생성
루비는 module을 사용하여 네임스페이스 생성. 참조하는 모듈다음에 범위연산자 :: 사용
module Relevance
class User
def initialize(name)
@name = name
end
attr_accessor : name
end
end
module Codecite
class User
def initialize(name)
@name = name;
attr_accessor : name
end
end
end
u1 = Relevance::User.new("Justin")
u2 = Codecite::User.new("Stu")
include Relevance
u3 = User.new("Jared")
puts "u3 is a #{u3.class}"
코드배포
- 로드패스(Load Path)
자바는 클래스패스 및 클래스 풀네임을 통해 클래스 단위로 로딩함
루비는 :$ 라는 이름을 가진 로드패스를 가지고 있으며, 소스파일 단위로 코드를 로딩함
(한 소스에 여러개의 클래스가 있을 수 있고, 아에 클래스 정의가 없을 수도 있기 때문 )
require 'super_widget'
w = new SuperWidget('phlange")
- 루비젬(RubyGems)
루비젬은 소스파일의 덩어리를 가리키는 말로, 자바에서의 jar 라고 생각할 수 있다.
gem 커맨드를 사용하여, 젬으로 그룹핑하고, 문서파일 생성, 웹을 통해 다운받고, 버전을 관리할 수 있다
require 'rubygems'// 젬을 로딩하기 위한 사전정의어 정도... require_gem 'pdf-writer'
애플리케이션을 특정 버전의 레일스에 바인딩하는 것을 동결(freezing)이라고 함!
레일스는 동결 지정/해제를 위한 freeze란 레이크 태스크를 포함하고 있음
위임
레일스에서 확장한 delegate라는 메소드를 사용하여 위임을 쉽게 사용할 수 있다.
require 'rails'
class Manager
attr_accessor : programmer, :tester
delegate :code, :debug, :to=> :programmer
delegate :write_test_plans, :run_tests, :to=>:tester
end
다형성과 인터페이스
루비에는 컴파일 타임이 없기 때문에, 자바의 다형성과는 다르게 작동함
루비의 타입 안전성은 인터페이스 차원이 아닌 메서드 차원에서 보장됨. 런타임에 실제 구현되지 않은 메소드를
호출하면 NoMethodError 예외를 던짐
자바에서는 컴파일 타임에 객체가 특정 인터페이스 타입이 아니면 에러를 발생시켜 주지만, 루비는 실행시에 실제로
해당 메소드가 구현되외 있는지 확인하고 예외를 발생시켜준다는 의미이다.
루비 메타프로그래밍
- 리플렉션
루비의 Object클래스도 자바처럼 객체의 상태와 내용을 볼수 있는 기능을 제공함
리플렉션 메서드로 Object#respond_to?, Object#instance_of?, Object#instance_variables, Object#kind_of 가 있음
- 메시지 전달
Object클래스의 send메서드를 통해 동적으로 객체의 메소드를 호출 할 수 있으며, 매개변수로 블록전달도 가능
실행할 메서드의 이름을 동적으로 조합해서 지정할 수 있기 때문에 다양한 형태의 메소드 호출, 전달이 가능
- 없는 메서드 처리(method missing)
존재하지 않는 메서들을 처리해주는 Object#method_missing 메서드를 재정의해서 사용할 수 있음
오리 타이핑(Duck Typing)
객체의 타입이 클래스(Object#class)가 아닌, 실제 그일을 수행하는 메서드를 가지고 있는지를 기준으로 판단
(오리처럼 걷고, 오리처럼 말하면, 인터프리터 입장에서 오리로 취급해줄게~)
- 오리타이핑의 장점
단위테스트 스텁객체 작성이 용이 - 필요한 메서드만 구현해주면 됨
반복적으로 사용하는 코드에 대해 인위적인 경계를 허물어뜨림 - 유연성?
객체 간의 관계 리팩터링이 쉬움
- 오리타이핑의 단점
자동화 도구들이 변수와 메서드 추측을 어렵게 만들어, 좋은 품질의 코드완성과 리팩터링 제공이 힘듬
믹스인
한번 작성한 코드를 믹스인으로 몇 개의 클래스나 모듈과 혼합할 수 있는 방식
위임을 믹스인으로 쉽게 구현할 수 있음
module Employer
def employees
@employees ||= []
end
def add_employee(employee)
...
end
def remove_employee(employee)
...
end
end
class BusinessPerson < Person
include Employer, Employee
end
특정 객체의 인스턴스를 생성하고 extend를 사용하여 특정 인스턴스에만 적용되게 할수도 있다
p = Persion.new("Stu", "Halloway")
p.extend Employer
함수(Functions)
함수형 언어에서의 함수를 의미한다. c, c++, 자바같은 절자지향 또는 객체지향 언어들은 명령형 프로그래밍의
개념들을 따르고 있다. 이들 프로그래밍에서 함수는 객체의 상태를 변경시키는 작업을 한다.
함수형 언어에서의 함수는 특정 입력값에 대해 항상 동일한 결과값을 반환하는 동작만을 한다.
루비에는 이런 함수와 유사한 블럭(block)이 존재한다. 자바에서도 인터페이스와 익명클래스를 사용하여 블럭 또는
클로저를 구현할 수 있다.
자바
public interface Comparator {
int compare(Object o, Object o1);
}
Collectons.sort(al, new Comparator() {
public int compare(Object o, Object o1) {
return ((String)o).length() - ((String)o1).length();
}
});
루비
sorted = readlines.sort { |x, y| x.length - y.length }
puts "sorted:\n #{sorted.join}
블록은 특정 작업에 대한 래퍼(Wrapper)를 구현할 때 유용함
def expect_exception(type)
begin
yield// 전달받은 블록을 호출함, 없으면 무시
rescue type=>e // 해당하는 타입의 예외이면 정상종료
return
end
raise "Excpected exception: #{type}"// 다른타입의 예외이면 예외를 발생시킴
end
expect_exception(ZeroDivisionError) {10/0}
&를 사용하여, 명시적으로 블록을 인자로 전달 받을 수 있다. block_given?를 호출해서 블록전달 유무도 알수 있다.
def expect_exception(type, &blk)
begin
blk.call if block_given? // 전달받은 블록을 호출함, 없으면 무시
rescue type=>e // 해당하는 타입의 예외이면 정상종료
return
end
raise "Excpected exception: #{type}"// 다른타입의 예외이면 예외를 발생시킴
end
expect_exception(ZeroDivisionError) {10/0}
'언어로그 > Ruby/Rails' 카테고리의 다른 글
| 자바 개발자를 위한 루비적 관점 (0) | 2011.03.04 |
|---|---|
| [Ruby]WEBrick 서블릿 사용하기 (0) | 2010.12.12 |
| [Ruby]WEBrick 서버구동 (0) | 2010.12.12 |
설정
트랙백
댓글
글
[Spring Roo] (4) Roo 설치하기
Roo를 설치하는 방법을 알아봅시다. Roo는 자바프레임웍이기 때문에 당연히 JDK를 설치되 있어야 합니다.
Maven을 빌드툴로 사용하기 때문에 Maven이 설치되 있어야 되며, Spring 프레임웍은 Roo에 포함되어 있습니다.
1. 시스템 요구사항
Linux, Apple, Windows-based opeating system
Sun, JRocket, IBM Java5, 6 installation => $JAVA_HOME 환경변수가 JDK 홈을 가리키도록 설정
Apache Maven 2.0.9 이상버전 설치 => PATH 환경변수에 추가
2. 다운로드 사이트에서 루 애플리케이션 다운받기
SpringSource Tool Suit (Roo 사용을 쉽게하는 이클리스 기반의 IDE)다운로드
http://www.springsource.com/products/springsource-tool-suite-download
STS를 설치하면, roo쉘과 STS IDE와 톰캣서버가 설치된다.
3. Roo쉘이 설치된 경로를 ROO_HOME 환경변수로 설정합니다.
4. Roo 쉘명령 링크를 생성합니다.
윈도우를 사용한다면, $ROO_HOME\bin에 PATH 환경변수에 추가한다.
리눅스 또는 MacOS X를 사용한다면, 다음과 명령으로 심볼릭 릭크를 생성한다.
sudo ln -s $ROO_HOME/bin/roo.sh /usr/bin/roo
4. Roo 셀 명령을 사용하여 제대로 설치됐는지 확인합니다.
mkdir roo-test
cd roo-test
roo quit
cd..
rmdir roo-test
'프레임웍로그 > Spring' 카테고리의 다른 글
| [Spring Roo] (4) Roo 설치하기 (0) | 2011.03.03 |
|---|---|
| [Spring Roo] (3) Roo 아키텍처 (0) | 2011.03.03 |
| [Spring Roo] (2) Roo를 사용하는 이유 (0) | 2011.03.03 |
| [Spring Roo] (1) Spring Roo란? (4) | 2011.03.03 |
설정
트랙백
댓글
글
[Spring Roo] (3) Roo 아키텍처
1. 아키텍처 개요
스프링 Roo는 자바로 작성된, 기업용 애플리케이션 개발에 초점을 두고 있다. 현재 버전에서는 전형적으로
관계형 데이터베이스 백단에 대한 퍼시턴스 접근을 위해 Java Persistence API, 스프링 프레임웍 의존성 주입과
트랜잭션 관리, JUnit 테스트, Maven 빌드구성를 사용하며, 뷰기술로는 JSP를 사용하는 스프링 MVC 프론트엔드를
가지고 있다. 이런 형태는 가장 현대적인 자바기반 기업 애플리케이션 형태이다.
하지만 루를 사용하여, 개발할 수 있는 자바 애플리케이션의 제약이 없다는 것이 중요하다.
루 1.0.0를 사용해서도 , 어떤 종류의 애플리케이션든지 개발할 수 있다. 현재 버전의 루를 사용하여 쉽게 해결할 수
있는 몇 가지 요구사항 타입의 예들은 다음과 같다.
1) JMS큐에서 메시지를 수신받고, JMS 또는 SMTP로 응답을 전송하는 경우
2) 서비스 레이어를 작성하거나 (Spring의 @Service 스테레오 타입 어노테이션 사용), 리모팅 프로토콜을 사용하여 서비스 레이어를 rich client에 공개 (스프링의 remoting services) 하는 경우
3) 스프링의 새로운 @Scheduled 또는 @Aync 어노테이션을 사용하여 데이터베이스에 일련에 사전 정의된 액션을 실행하는 경우
4) 최소한의 시간투자로 최신의 스프링, AspectJ의 특징을 사용하려는 경우
2. Roo 와 기존 애플리케이션과의 차이점
루와 전통적인 핸드라이팅 애플리케이션의 주요한 차이점 중 하나는 루가 불필요한 추상화 계층을 추가하지 않았다는
것이다. 전통적인 자바 엔터프라이즈 애플리케이션은 DAO, 서비스, 도메인, 컨트롤러 계층으로 구성된다.
루 애플리케이션에서는 entity(도메인 레이어와 유사) 와 web layer만을 사용한다. 서비스 레이어는 애플리케이션이
필요할 때 추가할 수 있으며, DAO 레이어는 루 애플리케이션에서는 추가되는 경우가 거의 없다.
루 차기 버전에서는 클라우드 지원과 RIA 프레임웍에 대한 지원이 확장될 예정이다. 현재도 Cloud Foundry, Amazon Web
Services, Google App Engine 과 같은 클라우드에 배치하는 루 애플리케이션을 작성할 수 있지만, 미래에 비관계형 데이터
베이스와 함께 더 쉽고 편이하게 사용할 수 있는 많은 애드온들이 추가될 것이다.
RIA 관점에서, Google Web Toolkit 프론트 엔드를 작성할 수 있는 서비스도 추가될 예정이다.
(GWT와 Roo 모두 엔지니어링 퍼모먼스와 first-class 자바 중심 개발방법에 초점을 두고 있음)
Apache Maven 의 대안으로 Apache Ivy 지원에 대한 요구사항도 있다.
3. 핵심기술
3.1 AspectJ
AspcectJ는 정의된 포인트컷에 advice를 적용하는 AOP 로 가장 잘 알려져있지만, 루 프로젝트들은 AspectJ의 강력한
inter-type declaration(ITD) 특성을 사용한다. 이것이 루가 사용하는 마술이다. 일반 java 파일로부터 다른 컴파일
단위로 메서드와 필드들을 클래스 파일에 생성해 넣는다. 생성된 코드는 독립된 파일이기 때문에 그 파일들의 생명주기와
컨텐츠는 java 파일에 무엇을 하고 있는지와는 완전히 독립적으로 관리할 수 있다.
ITD 가 어떻게 동작하는지 알아보자. 아래와 같이 새로운 프로젝트를 만들고 엔티티를 추가하자.
Hello.java 파일 외에도, 일련의 Hello_Roo_*.aj 파일들이 생성되었다. *_Roo_*.aj 형태를 갖는 파일들이 Aspect ITD
파일들이며, Roo에 의해 관리된다. 이 파일들을 직접 편집해서는 안된다.
Hello.java 파일은 다음과 같은 단순한 형태를 갖는다.
몇몇 어노테이션들이 추가되었는데, 이런 Roo 어노테이션들은 소스 수준에서 유지되며, .class 파일로 컴파일되지 않는다.
Roo 어노테이션들은 항상 @Roo*로 시작하며, 코드 어시스트 기능을 사용할 수 있다.
IDT파일들 중의 Hello_ROO_ToString.aj 을 보자
ITD는 자바코드와 매우 유사하다. 큰 차이점은 priviledged aspect 로 선언되어있으며, 각 멤버들은 특정한 타겟타입을
식별한다. Hello.toString은 Hello 타입에 toString 메서드를 추가하라는 의미이다.
javap 명령을 사용해 생성된 클래스 파일을 확인한 결과이다.
Roo가 AspectJ ITP를 통해 java 파일에 위 그림과 같은 멤버들을 추가하였다. toString 메소드 뿐만아니라,
스프링의 ConfigurableObject 인터페이스를 구현하고 있으며, JPA EntityManager에 대한 접근자, 몇몇 퍼시스턴스 메소드,
getter, setter 들이 추가 되었다. 이런 유용한 특징들이 round-trip 방식으로 자동적으로 관리된다.
java 파일에 toString 메소드를 정의하거나, 프로그래머가 직접 toString 메소드를 정의하면, 더 높은 우선순위를 갖게되어
자동으로 Hello_Roo_ToString.aj 파일이 삭제된다.
또한 루 애플리케이션은 AspectJ의 뛰어난 AOP 특징을 사용하여, 싱글턴 객체를 사용하여 의존성을 주입하고,
메소드 호출의 일부로 트랜잭션 서비스가 사용된다.
3.2 Spring
루의 디폴트 애플리케이션은 스프링 프레임웍만을 포함하고 있으며, Spring Security, Spring Web Flow와 같은
다른 프레임웍을
점진적으로 추가할 수 있는 명령들을 제공하고 있다. 모든 루 애플리케이션들은 Spring Aspect를 사용하며,
스프링 프레임웍의
Configurable 의존성 주입과 트랜잭션 어드바이스를 사용한다. 또한 디폴트로 스프링에 어노테이션 기반
컴포넌트 스캐닝과
데이베이스 커넥션 풀, JPA 프로바이더와 같은 객체 생성 및 의존성 주입을 위해 스프링 프레임웍에 의존
한다.
3.3 Entity Layer
Roo 프로젝트에서 entity와 field는 문제 domain을 표현하는 첫번째 진입점이 된다. entity는 데이터베이스에 저장되는
특별한 형태의 domain object로, 일반적으로 하나의 entity는 하나의 table을 field 는 하나의 column을 표현하지만, 루쉘을
통해 쉽게 커스터마이징 할 수 있어서, 해당하는 어노테이션을 알 필요도 없다.
@RooEntity 어노테이션를 사용하면 Persistent Entity객체를 얻어오는 정적메서드와 JPA Facada 메소드들, 식별자와 버전을
위한 getter, setter를 추가하는 .aj 파일을 생성한다. (Hello_Roo_Entity.aj ). @RooEntity 어노테이션을 제거하고, JPA를 직접
구현 할 수도 있다. ( 식별자와 버전은 삭제되지 않는다.)
@RooJavaBean 어노테이션은 클래스 내 모든 필드에 대한 getter, setter 를 추가하는 Hello_Roo_JavaBean.aj 파일을
생성시키며, 이 메소드를 직접구현하면 자동으로 해당하는 메소드가 ITD에서 제거된다.
@RooToString 어노테이션은 public void toString 메소드를 추가하는데, 이 메소드는 자동생성된 web controller에서 연관된
엔티티를 보여주기 위해 사용된다. 이 메소드 내부에서는 Caleander 객체를 사용하며, 컬렉션을 포함하는 양방향 관계에서
흔히 나타나는 원형참조를 피할수 있도록 관리해준다.
@RooToString, @RooJavaBean 어노테이션을 사용할 수 있는데, 이러한 방법은 저장될 필요가 없는(엔티티가 아닌)
많은 도메인 객체를 가지고 있을 때 특히 유용하다
3.4 Web Layer
Roo 1.0.0은 선택적으로 자동생성된 웹 컨트롤러 레이어를 사용할 수 있도록 제공한다. 이 레이어는 요청이 REST 관례를
따르도록 보장하는 많은 URL rewriting 규칙을 포함하고 있다. 또한 Apache Tiles, Spring JavaScript 외에도 단일 명령으로
쉽게 Spring Security를 설정할 수 있게 해준다. 이 컨트롤러들은 항상 요청을 @RooEntitiy 클래스에서 제공하는 메소드로
직접적으로 위임하는데, 호환성을 위해서 @RooEntity 구현에 의해 제공되는 디폴트 식별자와 버전 관례를 준수하는게 좋다.
대부분의 Roo 애플리케이션들은 비지니스 로직을 엔티티와 웹 컨트롤러 사이에 놓으며, 가끔은 서비스레이어에 놓기도 한다.
Roo 1.0.0은 선택적으로 자동생성된 웹 컨트롤러 레이어를 사용할 수 있도록 제공한다. 이 레이어는 요청이 REST 관례를
따르도록 보장하는 많은 URL rewriting 규칙을 포함하고 있다. 또한 Apache Tiles, Spring JavaScript 외에도 단일 명령으로
쉽게 Spring Security를 설정할 수 있게 해준다. 이 컨트롤러들은 항상 요청을 @RooEntitiy 클래스에서 제공하는 메소드로
직접적으로 위임하는데, 호환성을 위해서 @RooEntity 구현에 의해 제공되는 디폴트 식별자와 버전 관례를 준수하는게 좋다.
대부분의 Roo 애플리케이션들은 비지니스 로직을 엔티티와 웹 컨트롤러 사이에 놓으며, 가끔은 서비스레이어에 놓기도 한다.
웹 애플리케이션은 대부분의 로직을 웹컨트롤러 핸들 메소드에, 나머지를 엔티티 메소드에 작성하기 때문에 거의 서비스
레이어를 필요로 하지않는다. 하지만 비지니스 로직을 필요로 하는 다음과 같은 경우도 있다.
* 로직이 특정 엔티티에만 속하지 않고 여러 엔티티로 확장되야 하는 경우
* 웹요청의 범위를 넘어 비지니스 로직이 적용되야 하는 경우
* 원격 클라이언트 접근이 필요할 때 (remoting protocol을 통해 메소드들을 노출하는게 더 편리하기 때문)
* 아키텍처 정책이 서비스 레이어를 요구할 때
* HTTP 관련 관리와 비지니스 로직에 대한 책임 분할을 통해, 더 높은 수준의 응집도를 필요로 할때
* 서비스 레이어에 보안 인증 메타데이터와 트랜잭션 경계를 놓는게 더 선호되는 경우
3.5 Goodbye DAOs
대부분 작성하는 일반적인 웹 애플리케이션에 반드시 필요 하지는 않기 때문에, 서비스 레이어와 함에 DAO 레이어가
제거되었다. DAO 레이어가 필요한 주요한 동기를 생각해보면 루 애플리케이션에서 필요하지 않는 이유를 더 잘 알 수
있을 것이다.
* Testing
* Separation of concern
DAO 레이어를 사용하는 이유 중 하나는 객체지향 설계에서 추구하는 높은 응집도를 구현하기 위해서이다.
높은 응집도는 관심의 분리와 동일하다고 할 수 있다. AspectJ의 ITD를 통해, 퍼시스턴스 메소드를 프로그래머가
아닌 Roo 처리하도록 하여 관심의 분리를 달성하고 있다.
* Pluggable implementaions
DAO의 다른 장점 중 하나로 하나의 퍼시스턴스 라이브러리에서 다른 것으로의 변경이 용이하다는 것이다.
현재 애플리케이션은 API 수준의 추상화를 JPA를 통해 제공하는데, 루는 자동생성된 메서드에서 JPA를 사용하며,
DAO 레이어 없이도, 대체 구현을 플러그 할 수 있는 능력을 지원한다.
* Non-JPA persistence
몇몇 엔티티들을 JPA Provider를 사용하지 않고, 저장하고 싶을 경우가 있을 것이다. 소규모의 클래스들만이
이러한 요구사항이 필요하다면, 나머지 대다수의 엔티티들을 Roo를 사용하여 관리할 수 있다. 대규모의 클래스들이
이러한 요구사항을 필요로 한다면 사용자가 직접 (Roo가 JPA Provider에 대해 했던 것처럼) 자동으로 ITD들을
관리해주는루 애드온을 작성할 수 있다.
* Security authorisation
'프레임웍로그 > Spring' 카테고리의 다른 글
| [Spring Roo] (4) Roo 설치하기 (0) | 2011.03.03 |
|---|---|
| [Spring Roo] (3) Roo 아키텍처 (0) | 2011.03.03 |
| [Spring Roo] (2) Roo를 사용하는 이유 (0) | 2011.03.03 |
| [Spring Roo] (1) Spring Roo란? (4) | 2011.03.03 |
설정
트랙백
댓글
글
[Spring Roo] (2) Roo를 사용하는 이유
그렇다면 Roo를 사용하는 이유는?
- 생산성이 뛰어나다
루를 사용하면 자바 개발자들이 복잡한 엔터프라이즈 애플리케이션을 수분 안에 가장 좋은 방식(Best Practice)으로
작성 할 수 있다. 자바를 수년동안 개발했던 개발자들은 자바의 생산성 문제를 인식하게 되는데, 새로운 프로젝트를
생성하고, 개발이 정상궤도에 오르기까지 수일이 걸리기 때문이다. 세계에서 가장 많이 사용되고 있으며, 많은 성숙
한 라이브러리를 제공하고, 뛰어난 성능과 광범위한 표준을 지원하는 매력적인 자바 플랫폼에, 루를 사용하여 뛰어
난 생산성까지 가미할 수가 있다.
생산성 외에도 팀으로 행동하며, 언젠간 다른 사람이 작성한 코드를 유지보수 할 수도 있기 때문에, 프로로서 아키텍
처 표준과 관례를 따르는 것도 중요하다. 루는 최적화된, "구성보다는 관례"를 따르는 방식으로 서로 다른 배경과
경험을 갖는 개발자들간의 차이도 극복하게 해준다.
- 업계 표준을 준수한다.
루는 자바5를 사용하는 개발자를 대상으로 설계되었기 때문에, 대부분이 익숙한 기술들이다
루 프로젝트가 사용하는 기술들은 Spring(Spring Framework, Spring Security, Spring Web Flow), Maven,
Java Server Pages, Java Persistence API(JPA, 하이버네이트 같은..), Tiles, AspectJ을 포함한다. 엔터프라이즈
자바 프로젝트에서 가장 많이 사용되는 기술들을 포함했다. 또한 애드온 방식을 사용해 구현되었기 때문에
프로젝트에 쉽게 다른 기술을 사용할 수 있다. 루는 이러한 기술들을 프로젝트에 매우 안정적이고, 점진적으로
추가하는 접근 방법을 취한다.
루는 새로운 프로젝트를 시작할 때, 단순한 JAR 를 빌드한다고 가정하기 때문에 어떠한 의존성도 갖지 않는다.
이후에 Persistence Provider가 필요할 때, JPA가 설치되고, JavaBean Validation 어노테이션을 필드에 사용할 때
해당 라이브러리가 프로젝트에 추가된다. Spring Security, Spring Web Flow 등 루가 지원하는 모든 기술들이
그러한 방식 으로 추가된다. 이것은 엔지니어링 트레이드오프 가 없게 한다는 루의 철학과 일맥상통하는 방식이다.
- 사용 및 배우기 쉽다.
루 개발자들은 Jef Raskin의 "The Human Interface" 라는 책에서 영감을 받아 루를 설계했다. 그는 사람들이
인터페이스에 자연스럽게 습관화 될 수 있도록 사용하기 쉽게 만들어져야 한다고 주장했다. 루는 이러한 사용자가
정말로 집중해야 할 점을 방해하지 않는 인터페이스 설계를 모티브로 하고 있다.
루는 텍스트 기반의 인터페이스로, 학습성(배우기 쉬운) vs 풍부성 vs 정보의 명료성이라는 트레이트오프를 가지고
있다. GUI는 위 세가지 요구사항을 모두 만족할 수 있지만, 루는 학습성과 풍부성에 좀더 초점을 맞추었다.
명료성은 루쉘이 직관적인 탭기반 완성시스템을 제공하여 극복했다. 명료성을 위해서, 이전에 완료된 명령에 기반
하여, 현재 명령의 대상을 결정하는 "문맥인식" 과 명령축약의 특징을 추가했다.
루의 학습성은 3가지 방식으로 이루어진다.
첫째, 업계표준의 자바 기술을 선택했고
둘째, 개입없이 루는 백그라운드에서 자동으로 동작하며,
셋째, 현재 프로젝트 상태에 기초하여 다음에 할것을 제안해주는 hint와 같은 명령을 제공한다.
그외에도 지능적인 탭완성 및 많은 문서와 리소스를 제공한다.
- 엔지니어링 트레이드 오프가 없다.
루 애플리케이션은 더 작은 배포크기를 갖으면, CPU 타임의 관점에서 더 빠르게 동작하고, 더 적은 메모리를
소비한다 또한 코드 어시스트, 디버깅, 프로파일링과 같은 IDE 서비스도 문제 없이 사용할 수 있도록 지원한다.
더 작은 배포크기는 루의 점진적인 의존성 추가 접근방법을 통해 이루어진다. 작은 JAR 파일로 시작하여 실제로
필요할 때만, 의존성을 추가한다. Roo 1.0.0 부터 루기반의 웹애플리케이션 WAR은 13Mb인데, 여기에는 스프링과
Spring JavaScript(Dojo내장), 하이버네이트, URL rewriting과 같은 더 작은 라이브러리가 포함되어 있다.
30Mb 이상의 WAR 공간을 절약하게 되고 이것은, 업로드와 컨테이너 시작을 더 빠르게 한다. 시작시간은, AspectJ의
뛰어난 컴파일 타임 위빙을 통해 이루어지는데, 싱글톤 객체들의 의존성 주입과 도메인 객체 advising 과 같은 진보된
요구사항을 만족할 수 있게한다. 또한 스프링 로딩시 전형적으로 생성되던 동적 프락시들이 더 이상 필요하지 않게된다.
동적 프락시 생성 오버헤드가 없기 때문에 시작이 더 빠르며, 동적프락시 흐름 제어를 위한 CPU 타임의 낭비가 없어
루 애플리케이션은 더 빠르게 동작한다. 프락시 객체를 사용하지 않는다는 것과 루의 런타임 컴포넌트가 없다는 것은
어떤 메모리 비용도 들지 않는다는 장점도 있다. 점점 더 엔터프라이즈 애플리케이션들이 가상화되고, 클라우드되는
환경에서 공유하드웨어에 대한 성능의 문제는 더욱더 큰 장점으로 작용 할 것이다.
루는 실용적이고, 유연하며, 유지보수 하기 쉬운 애플리케이션 아키텍처를 가지고 있다. DAO 레이어를 제거하고,
어노테이션 기반의 의존성 주입을 사용하여 엔티티에 자동으로 의존성을 주입하는데, 이 아키텍처는 극적으로 작성
해야할 Java 및 XML의 코드의 양을 줄이고, 개발 사이클과 리택토링 경험을 향상시킨다.
- Roo는 제거하기 쉽다.
요구사항의 변경, 더 좋은 대체툴의 등장, 납득할 수 없을 정도의 버그, 다른 소프트웨어의 버전을 지원하지 않는
문제 등 여러가지 이유로 인해 툴을 제거해야할 현실적인 가능성이 있다. 루는 런타임이 존재하지 않기 때문에
이러한 문제들은 루에서 상당수 해결된다. 루를 제거하기로 결정했다면, 단 몇분 만에 제거할 수 있다.
어떠한 코드도 작성할 필요 없으며, 큰 변경또한 발생하지 않는다. 단순히 이클립스에서 "push in refactor" 명령을
수행하고, 정규표현식 기반의 탐색/대체기능을 사용하면 된다.
'프레임웍로그 > Spring' 카테고리의 다른 글
| [Spring Roo] (4) Roo 설치하기 (0) | 2011.03.03 |
|---|---|
| [Spring Roo] (3) Roo 아키텍처 (0) | 2011.03.03 |
| [Spring Roo] (2) Roo를 사용하는 이유 (0) | 2011.03.03 |
| [Spring Roo] (1) Spring Roo란? (4) | 2011.03.03 |
설정
트랙백
댓글
글
[Spring Roo] (1) Spring Roo란?
스프링 사이트를 방문했다가, 스프링 루 프로젝트를 보게 되었다. 스프링 루가 무엇일까? 궁금하여 프로젝트 사이트에서
제공하는 메뉴얼을 읽어보았는데, 일부 내용을 번역하여 적어보았다.
Spring Roo
스프링 루는 자바언어를 사용하는 텍스트 기반의 RAD(RApidy Development) 툴이다.
루(Roo)는 Real Object Oriented 의 약자임과 동시에 캥거루를 의미하는 단어로, 스프링 루의 마스코트 또한 캥거루이다.
루는 자바 이외에 어떤 다른 언어와 플랫폼을 필요로 하지 않으며, 기존의 엔터프라이즈 애플리케이션을 개발하는 방식을
사용한다. 루쉘이라는 커맨드 라인 프로그램이 실행시켜 두고 , 프로그래머는 텍스트 에디터 또는 IDE를 사용하여 개발을
수행하면, 루쉘이 백그라운드에서 파일시스템 변경을 인지하고, 자동으로 필요한 파일들을 생성하고 관리해준다.
루는 완전한 Round-trip(양방향) 인식을 제공하는데 이것은 프로그래머는 루에 명령없이도 어떠한 파일도 변경할 수 있고,
루는 이러한 변경사항을 자동으로 인식하여, 필요한 파일들을 생성하는 특징을 나타낸다.
루에 대한 잘못된 생각들을 알아보면....
- 루는 런타임이 아니다
클래스파일에 컴파일되어 포함되지도 않는다. 이러한 특징은 언제라도 루를 프로젝트에서 제거할 수 있다는 no lock-in
특징을 의미한다. 루를 사용하기 위한 승인이 필요치 않으며, 런타임에 프로젝트 속도를 감소시키거나, 메모리를 낭비하고, 배포구조를 망치는 어떻한 부작용도 없다.
- 루는 IDE 플러그인 아니다
점진적 으로 적절한 시기에 변경에 응답한다. 이것은 vi, emacs 등 어떤 에디터를 사용할 수 있게한다.
-
루는 어노테이션 처리 라이브러리가 아니다
'프레임웍로그 > Spring' 카테고리의 다른 글
| [Spring Roo] (4) Roo 설치하기 (0) | 2011.03.03 |
|---|---|
| [Spring Roo] (3) Roo 아키텍처 (0) | 2011.03.03 |
| [Spring Roo] (2) Roo를 사용하는 이유 (0) | 2011.03.03 |
| [Spring Roo] (1) Spring Roo란? (4) | 2011.03.03 |
설정
트랙백
댓글
글
HMAC-SHA1 구현
@interface NSData (ATOAuth) - (NSData*)dataByHmacSHA1EncryptingWithKey:(NSData*)key; @end
#import "NSData+EOUtil.h"
#include <commoncrypto/commonhmac.h>
@implementation NSData (ATOAuth)
- (NSData*)dataByHmacSHA1EncryptingWithKey:(NSData*)key
{
void* buffer = malloc(CC_SHA1_DIGEST_LENGTH);
CCHmac(kCCHmacAlgSHA1, [key bytes], [key length], [self bytes], [self length], buffer);
return [NSData dataWithBytesNoCopy:buffer length:CC_SHA1_DIGEST_LENGTH freeWhenDone:YES];
}
@end
'Objective-C' 카테고리의 다른 글
| Objective-C 문자열 조작 메서드 (0) | 2011.04.29 |
|---|---|
| 다중인자를 갖는 PerformSelector 메시지 (0) | 2011.03.23 |
| Protocol 과 Category (0) | 2011.03.22 |
| Objective-C 훑어보기 (2) | 2011.03.20 |
| [Cocoa] Cocoa Design Pattern (0) | 2011.03.20 |
| HMAC-SHA1 구현 (0) | 2011.03.03 |
설정
트랙백
댓글
글
[MySQL] 사용자 계정 생성/외부접속 허용
mysql> CREATE USER 'javauser'@'localhost' IDENTIFIED BY 'your_password';
mysql> CREATE USER 'javauser'@'%' IDENTIFIED BY 'your_password';
mysql> CREATE DATABASE javauser;javauser 라는 데이터베이스를 생성한다.
mysql> GRANT ALL PRIVILEGES ON javauser.* TO 'javauser'@'localhost' WITH GRANT OPTION;
로컬호스트 사용자와 외부접근 사용자는 별도의 사용자처럼 다뤄지기 때문에 외부접근 사용자에게도 권한을
부여해 주어야 한다.
mysql> GRANT ALL PRIVILEGES ON javauser.* TO 'javauser'@'%' WITH GRANT OPTION;
4. 계정에 대한 권한설정을 확인한다.
mysql> SHOW GRANTS FOR 'javauser'@'localhost';
FLUSH PRIVILEGES
'데이터베이스로그' 카테고리의 다른 글
| [MySQL] 사용자 계정 생성/외부접속 허용 (0) | 2011.03.03 |
|---|