2018년 3월 23일 금요일

Take my breath away

Take my breath away
Berlin
Watching every motion
In my foolish lover's game
On this endless ocean
Finally lovers know no shame
Turning and returning
To some secret place inside
Watching in slow motion
As you turn around and say
Take my breath away
Take my breath away
Watching I keep waiting
Still anticipating love
Never hesitating
To become the fated ones
Turning and returning
To some secret place to hide
Watching in slow motion
As you turn to me and say
Take my breath away
Through the hourglass I saw you
In time you slipped away
When the mirror crashed I called you
And turned to hear you say
If only for today
I am unafraid
Take my breath away
Take my breath away
Watching every motion
In this foolish lover's game
Haunted by the notion
Somewhere there's a love in flames
Turning and returning
To some secret place inside
Watching in slow motion
As you turn my way and say
Take my breath away
Take my breath away
Take my breath away
Take my breath away
Watching every motion in my foolish lover"s game
당신의 동작 하나하나를 지켜보죠. 바보 같은 사랑의 게임 속에서
On this endless ocean finally lovers know no shame
이렇게 끝없는 바다위에 결국 연인들은 아무런 부끄럼도 모르게 되죠.
Turning and returning to some secret place inside
마음속깊이 은밀한 곳을 향해 계속 돌고 돕니다.
Watching in slow motion as you turn around and say
난 가만히 지켜보고 있어요. 당신이 돌아서며 말하는 모습을
Take my breath away, Take my breath away
내 마음을 가져가세요. 내 마음을 가져가세요.
Watching I keep waiting still anticipating love
당신을 지켜보며 당신의 사랑을 기다리고 있어요.
Never hesitating to become the fated ones
운명적인 사랑을 이루는데 조금도 주저하지 않아요.
Turning and returning to some secret place to hide
마음속 깊은 곳을 향해 끝없이 돌고 돕니다.
Watching in slow motion as you turn to me and say
가만히 지켜보고 있어요. 그대가 내 쪽으로 돌아서며 말하는 걸...
Take my breath away
내 마음을 가져가세요.
Through the hourglass I saw you, in time you slipped away
모래시계를 통하여 나는 당신을 보았어요. 세월 속에 당신은 슬쩍 가버렸죠.
When the mirror crashed I called you, and turned to hear you say
거울이 깨졌을 때 나는 당신을 소리쳐 부르고 몸을 돌려 당신이 말하는 것을 들었죠.
If only for today I am unafraid
오직 오늘만을 위해서라면 나는 두렵지 않아요.
Take my breath away, Take my breath away
내 마음을 가져가세요. 내 마음을 가져가세요.
Watching every motion in this foolish lover"s game
이 바보 같은 사랑게임을 하면서 당신의 모든 움직임을 지켜보고 있어요.
Haunted by the notion somewhere there"s a love in flames
어딘가에 불타는 사랑이 있을 거라는 생각에 사로잡히지요.
Turning and returning to some secret place inside
깊이 감추어진 내 마음속의 사랑을 향해 끝없이 돌고 돕니다.
Watching in slow motion as you turn to me and say
난 가만히 지켜보고 있어요. 당신이 내 쪽으로 돌아서며 이렇게 말하는 모습을..
Take my breath away, My love, take my breath away
내 마음을 가져가세요. 내 사랑, 내 마음을 가져가세요.

2018년 3월 13일 화요일

terasoluna error


<t:messagesPanel />

<div>
<form:errors path="*" />
</div>

YearMonthUpdateUpdateBLogicOutput output = null;
try {
    output = yearMonthUpdateUpdateBLogic.execute(input);

    if (!result.hasErrors()) {
        ResultMessages messages = ResultMessages.info().add("i.ne.fw.0002");
        model.addAttribute(messages);
    }

} catch (BusinessException e) {
    model.addAttribute(e.getResultMessages());

} catch (Exception e) {
    ResultMessages messages = ResultMessages.error().add("e.ne.fw.8002")
            .add(ResultMessage.fromText(e.getMessage()));
    model.addAttribute(messages);
}

BindingResult result = input.getResult();
if (result.hasErrors()) {
    return null;
}

if (!mYearMonth.getSysYearMonth().equals(form.getSysYearMonth())) {
    ResultMessages messages = ResultMessages.error().add("e.ne.fw.9001");
    throw new BusinessException(messages);
}

2018/03/14 일본어

ふよ[付与·附与] 부여; (내려) 줌.(↔剝奪)

単項目チェックはBean Validation、
相関チェックはSpring Validator又はBean Validationでチェックを行う。

いじょう[委譲·依譲·移譲]
위양·이양.

せんい[遷移]
천이.(=転移)

てっする[徹する]
철저하다; 투철하다; 꿰뚫다.사무치다.
사무치다, 철저하다;투철하다, 밤을 새우다

すいしょう[推奨]추장.

てったい[撤退]철퇴.

こな[粉]
가루; 분말; 특히, 밀가루.(=粉)

@Autowired、@Inject、@Resourceの違いについての検証

@Autowired、@Inject、@Resourceの違いについての検証
Java
spring
 この記事は最終更新日から1年以上が経過しています。
@Autowired、@Inject、@Resourceについて、共通的な動きとしては、何れも自動でフィールドにbeanをインジェクションすることです。今回はそれらの違いについて、検証してみます。

@Resource⇨javax.annotation
@Inject⇨javax.inject
@Autowired⇨org.springframework.bean.factory
事前準備
以下のクラスを用意する。
・インタフェースクラスPrint
・インタフェースクラスPrintの実装クラスHelloWorldPrintImp
・インタフェースクラスPrintの実装クラスHelloMoonPrintImp

public interface Print {
    public void print();
}

@Component
public class HelloWorldPrintImp implements Print {

    @Override
    public void print() {
        System.out.println("Hello World");
    }
}
@Component
public class HelloMoonPrintImp implements Print {

    @Override
    public void print() {
        System.out.println("Hello Moon");
    }
}
検証1
@Autowired
private Print print;
@Inject
private Print print;
@Resource
private Print print;
上記のケースは、何れも例外NoUniqueBeanDefinitionExceptionが発生した。
インタフェースクラスPrintの実装クラスのbeanがユニックでないのが原因である。

検証2
@Autowired
private Print helloWorldPrintImp;
@Inject
private Print helloWorldPrintImp;
@Resource
private Print helloWorldPrintImp;
インジェクション対象のフィルド名を@Componentのクラス名と一致すればに、検証1の例外を回避し、上記何れも正常にインジェクションできる。

実行結果は以下の通りです。
@Autowired:Hello World
@Inject:Hello World
@Resource:Hello World

検証3
@Autowired
@Qualifier("helloWorldPrintImp")
private Print print;
@Inject
@Qualifier("helloWorldPrintImp")
private Print print;
@Resource
@Qualifier("helloWorldPrintImp")
private Print print;
@Qualifier("name")を上記のアノテーションと併用することで、インジェクション対象bean名を指定でき、検証1の例外も同様に回避する。

実行結果は以下の通りです。
@Autowired:Hello World
@Inject:Hello World
@Resource:Hello World

検証4
@Autowired
@Qualifier("helloMoonPrintImp")
private Print helloWorldPrintImp;
@Inject
@Qualifier("helloMoonPrintImp")
private Print helloWorldPrintImp;
@Resource
@Qualifier("helloMoonPrintImp")
private Print helloWorldPrintImp;
フィルド名=コンポーネントクラス名、且つ@Qualifierで別のコンポーネントを指定する場合、@Autowiredと@Injectの動きは一緒であり、@Qualifierで指定するコンポーネントがインジェクションされている。
@Resourceは@Qualifierで指定のコンポーネントを無視し、フィルド名と一致のコンポーネントがインジェクションされている。

実行結果は以下の通りです。
@Autowired:Hello Moon
@Inject:Hello Moon
@Resource:Hello World

また、@Resource(name="name")でコンポーネント名を指定できる。

@Resource(name="helloMoonPrintImp")
private Print helloWorldPrintImp;
その場合に、nameで指定されるコンポーネントがインジェクションされる。

実行結果は以下の通りです。
@Resource:Hello Moon

結論
タイプ一致の場合に、インジェクションの優先順位:
@Autowiredと@Inject
1.Qualifier指定のコンポーネント
2.フィルド名と一致のコンポーネント

@Resource
1.@Resource(name="name")で指定のコンポーネント
2.フィルド名と一致のコンポーネント
3.Qualifier指定のコンポーネント

@Component、@Service、@Repository、@Controllerの違いについて

@Component、@Service、@Repository、@Controllerの違いについて
Java
spring
 この記事は最終更新日から1年以上が経過しています。
Springアノテーション「@Component、@Service、@Repository、@Controller」について、
動きとして基本的同じであり、何れもアノテーションが付与されたクラスをSpringのDIコンテナにbeanとして登録します。
使い分けとしては、Spring MVCにおいてコントローラー層のクラスには@Contoroller、
サービス層のクラスには@Serivice、データ層のクラスには@Repository、
どれにも当てはまらない場合は@Componentを付けます。

@Controller
Spring MVCでコントローラー層のクラスに付与する。
Controller は、主に以下の役割を担う。
・画面遷移の制御
・ドメイン層の Service の呼出 (主処理を実行する)

@Controller
@RequestMapping("findProduct")
public class FindProductController {

    @Inject
    FindProductService findProductService;

    @RequestMapping(value="list")
    public String list(Model model) {
        Collection<Product> products = findProductService.findAll();
        model.addAttribute("products", products);
        return "product/list";
    }
}
@Service
Sping MVCでサービス層のクラス(ビジネスロジック等)に付与する。
Service は業務処理を提供する。

@Service
public class FindProductServiceImp implements FindProductService {

    @Inject
    FindProductRepository findProductRepository;

    public Todo findAll() {

        Collection<Product> products = findProductRepository.findAll();

        if (products == null) {

            // エラー処理
            ...
        }
        return products;
    }
}
@Repository
Spring MVCでデータ層のクラス(DAO等のDBアクセスを行うクラス)に付与する。

@Repository
public class FindProductRepositoryImpl implements FindProductRepository {

    private Collection<Product> products;

    @Override
    public Collection<Product> findAll() {
        return products;
    }
}
@Component
Spring MVCに限らず、SpringのDIコンテナにbeanとして登録したいクラスへ付与する。

@Component
public class checkComponentImp implements checkComponent{

    @Override
    public boolean check(BLogicParam param) {
        ...
    }
}

[Spring] @Autowired, @Resource, @Inject의 차이 Spring

[Spring] @Autowired, @Resource, @Inject의 차이   Spring
2014. 7. 7. 18:01
https://blog.naver.com/platinasnow/220053030295

이번에 소개하는 세가지 어노테이션 @Autowired, @Resource,@Inject은 모두 의존관계를 자동으로 연결해주는 기능을 가진 어노테이션입니다. 다만 조금씩의 차이가 있습니다.

@Autowired
@Inject
@Resource

범용
스프링 전용
자바에서 지원
자바에서 지원
 연결방식
타입에 맞춰서 연결
타입에 맞춰서 연결
이름으로 연결

 자세한 설명을 하자면, @Inject와 @Resource는 JSR에 실려있는 자바 기존의 어노테이션입니다. 반면 @Autowired의 경우에는 스프링에서 등장한 어노테이션입니다. 따라서 스프링 이외에서는 사용 할 수 없습니다. 만약에 프로젝트를 스프링에서 다른 프레임워크로 바꿀 생각이 있으시다면 @Autowired보단 @Inject나 @Resource를 쓰시면 됩니다. 다만 이런 경우는 거의 없다고 봅니다.

또한 연결 방식은 @Autowired와 @Inject는 타입에 맞춰서 하는 반면, @Resource는 이름에 맞춰서 연결하게 됩니다. 예를 들어보겠습니다.

Bird 인터페이스를 상속하는 Chicken과 Penguin 이라는 클래스가 있다고 합시다.
Chicken과 Penguin 클래스를 연결할 것이므로 @Component로 빈에 등록해주었습니다.
public class Bird{}
@Component
public class Chicken implements Bird{}
@Component
public class Penguin implements Bird{}

그리고 다음과 같이 연결해봅시다.
@Autowired
private Chicken penguin;  //Chicken 타입으로 연결됩니다.

@Inject
private Penguin chicken; //Penguin 타입으로 연결됩니다.

@Resource
private Chicken penguin;  //penguin 타입으로 연결됩니다만, Chicken 클래스를 자료형으로 두었기에 캐스팅이 되지 않아 에러가 납니다

@Resource
private Bird penguin;      //penguin 타입으로 연결되어 호출해보면 penguin 클래스의 값을 호출하는 것을 볼 수 있습니다.

@Autowired와 @Inject의 경우에도 @Qualifier 어노테이션을 사용하면, 타입 이외의 방법으로도 연결 할 수 있습니다.

@Autowired
@Qualifier("chicken")
pirvate Brid penguin;

위와 같이 쓰면 이름에 상관없이 Chicken 타입으로 연결되는 것을 알 수 있습니다. 이렇게 @Qualifer와 함께 쓰면 더욱 강력한 기능을 쓸 수 있는 장점이 있습니다.

[출처] [Spring] @Autowired, @Resource, @Inject의 차이|작성자 심해펭귄

[Spring] ViewResolver 설정

[Spring] ViewResolver 설정
2014.12.18 23:51
Posted in Programing/Spring by devbox

ViewResolver 설정

뷰 영역 구현

컨트롤러는 최종적으로 결과를 출력할 뷰와 뷰에 전달할 객체를 담고 있는 ModelAndView 객체를 리턴한다.

DispatherServlet은 ViewResolver를 사용하여 결과를 출력할 View 객체를 구하고, 구한 View 객체를 이용하여 내용을 생성한다.

1. 컨트롤러 구현 및 설정 추가

컨트롤러를 구현하려면 먼저 @Contoller 어노테이션을 클래스에 적용한다. 그리고, @RequestMapping 어노테이션을 이용해서 클라이언트의 요청을 처리할 메서드를 지정한다.

package madvirus.spring.chap06.controller;

import java.util.Calendar;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;

// @Controller 어노테이션은 해당 클래스가 스프링 MVC의 컨트롤러를 구현한 클래스라는 것을 지정한다.

@Controller
public class HelloController {

// @RequestMapping 어노테이션은 값으로 지정한 요청 경로를 처리한 메서드를 설정한다.

// 이 경우 http://host:port[/컨텍스트 경로]/hello.do 요청을 HelloController 클래스의 hello() 메서드가 처리하게 된다.

@RequestMapping("/hello.do")
public ModelAndView hello() {

//ModelAndView는 컨트롤러의 처리 결과를 보여줄 뷰와 뷰에서 출력할 모델을 지정할 때 사용된다.

ModelAndView mav = new ModelAndView();
// 컨트롤러의 처리 결과를 보여줄 뷰의 이름을 'hello'를 지정한다.

mav.setViewName("hello");
// 모델에 'greeting'이라는 이름으로 String 타입의 값을 추가하였다.

mav.addObject("greeting", getGreeting());

return mav;

}

// 스프링은 ModelAndView 뿐만 아니라 String이나 modelMap, 또는 Map과 같은 타입을 이용해서 뷰 이름과 모델 정보를 설정할 수 있도록 하고 있다.

private String getGreeting() {

int hour = Calendar.getInstance().get(Calendar.HOUR_OF_DAY);

if (hour >= 6 && hour <= 10) {

return "좋은 아침입니다.";

} else if (hour >= 12 && hour <= 15) {

return "점심 식사는 하셨나요?";

} else if (hour >= 18 && hour <= 22) {

return "좋은 밤 되세요";

}

return "안녕하세요";

}

}

DispatherServlet은 스프링 컨테이너에서 컨트롤러 객체를 검색하기 때문에 스프링 설정 파일에 컨트롤러를 빈으로 등록해 주어야 한다.

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
      http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.0.xsd">

<bean id="helloController" class="madvirus.spring.chap06.controller.HelloController" />

<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/view/" />
<property name="suffix" value=".jsp" />
</bean>

</beans>

스프링 2.5 버전까지는 @Controller 어노테이션이 적용된 클래스를 컨트롤러로 사용하려면 별도의 DefaultAnnoationHandlerMapping과 AnnotationHandlerAdapter를 스프링 설정 파일에 등록해 주어야 한다. 하지만 스프링 3.0부터는 이 두 빈 객체를 기본 구현체로 사용하기 때문에 별도의 설정을 하지 않을 경우 @Controller 어노테이션이 적용된 클래스를 컨트롤러 구현체로 사용할 수 있게 된다.

2. 설정 파일에 ViewResolver 설정 추가

컨트롤러 클래스는 직접 또는 간접적으로 ModelAndView 객체를 생성하게 된다.
예를 들어 앞서 작성한 HelloController 클래스는 다음과 같이 ModelAndView 객체를 생성해서 리턴하였다.

public ModelAndView hello() {

ModelAndView mav = new ModelAndView();

// 뷰이름
mav.setViewName("hello");// setViewName() 메서드를 이용하여 뷰 이름을 지정한 모습

mav.addObject("greeting", getGreeting());

return mav;
}

컨트롤러의 처리 결과를 보여줄 뷰의 이름을 'hello'를 지정하였는데, DispatherServlet은 이 뷰 이름과 매칭되는 뷰 구현체를 찾기 위해 ViewResolver를 사용한다.

JSP를 뷰 기술로 사용할 경우 다음과 같이 InternalResourceViewResolver 구현체를 빈으로 등록해주면 된다.

<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="WEB-INF/view"/>
<property name="suffix" value=".jsp/>

// 이는 ViewResolver가 "WEB-INF/view/뷰이름.jsp"를 뷰 JSP로 사용한다는 것을 의미한다.

// 즉, 앞의 예에서 HelloController는 뷰 이름으로 "hello"를 리턴하므로, 실제로 사용되는 뷰 파일은 "WEB-INF/view/hello.jsp"파일이 된다.

</bean>

InternalResourceViewResolver는 컨트롤러가 지정한 뷰 이름으로부터 실제로 사용될 뷰를 선택하는데, 이 때 컨트롤러가 지정한 뷰 이름 앞뒤로 prefix 프로퍼티와 suffix 프로퍼티를 추가한 값이 실제로 사용될 자원의 경로가 된다.

※ ViewResolver 구현 클래스
스프링 컨트롤러는 뷰에 의존적이지 않다. 컨트롤러는 아래 코드와 같이 결과를 생성할 뷰의 이름만 지정할 뿐이다.

컨트롤러가 지정한 뷰 이름으로부터 응답 결과 화면을 생성하는 View 객체는 ViewResolver가 구한다.

스프링은 몇 가지 ViewResolver 구현 클래스를 제공하고 있는데, 이중 주료 ViewResolver 구현 클래스는 다음과 같다.

3. ViewResolver 인터페이스

package org.springframework.web.servlet;

import java.util.Locale;

public interface ViewResolver{
View resolveViewName(String viewName, Locale locale) throws Exception;
}

ViewResolver는 뷰 이름과 지역화를 위한 Locale을 파라미터로 전달받으며, 매핑되는 View 객체를 리턴한다. 만약, 매핑되는 View 객체가 존재하지 않으면 null을 리턴한다.

4. View 객체
ViewResolver는 응답 결과를 생성할 뷰 객체를 리턴한다. 모든 뷰 클래스는 View 인터페이스를 구현하고 있으며, View 인터페이스는 다음과 같이 정의되어 있다.

public interface View {

    String RESPONSE_STATUS_ATTRIBUTE = View.class.getName() + ".responseStatus";

    String getContentType();

    void render(Map<String, ?> model, HttpServletRequest request, HttpServletResponse response) throws Exception;

}

getContentType() 메서드는 "text/html"과 같은 응답 결과의 컨텐츠 타입을 리턴한다. render() 메서드는 실제로 응답 결과를 생성한다. render() 메서드의 첫 번째 파라미터인 model에는

컨트롤러가 리턴한 ModelAndView 객체의 모델 데이터가 전달된다. 각각의 View 객체는 이 모델 데이터로부터 응답 결과를 생성하는데 필요한 정보를 구한다.

출처: http://devbox.tistory.com/entry/Spring-ViewResolver-설정 [장인개발자를 꿈꾸는 :: 기록하는 공간]

2018년 3월 11일 일요일

npm (소프트웨어)

npm (노드 패키지 매니저/Node Package Manager)은 자바스크립트 프로그래밍 언어를 위한 패키지 관리자이다. 자바스크립트 런타임 환경 Node.js의 기본 패키지 관리자이다. npm이라는 이름의 명령 줄 클라이언트, npm 레지스트리라는 이름의 그리고 공개 패키지와 지불 방식의 개인 패키지의 온라인 데이터베이스로 이루어져 있다. 이 레지스트리는 클라이언트를 통해 접근되며 사용 가능한 패키지들은 npm 웹사이트를 통해 찾아보고 검색할 수 있다. 패키지 관리자와 레지스트리는 npm사에 의해 관리된다.

npm은 온전히 자바스크립트로 작성되어 있으며 모듈 패키징이 엉망으로 완성되는 것을 관찰하고 펄의 CPAN과 PHP의 PEAR와 같은 기타 유사한 프로젝트의 단점들에서 영향을 받은 Isaac Z. Schlueter가 개발하였다.

원저자 Isaac Z. Schlueter
개발자 Rebecca Turner, Kat Marchan, others
발표일 2010년 1월 12일(8년 전)[1]
최근 버전 5.6.0 / 2017년 11월 28일(3달 전)[2]
프로그래밍 언어 자바스크립트
라이선스 아티스틱 라이선스

웹사이트 www.npmjs.com



Spring 개발도구와 환경

Spring 개발도구와 환경
* 본 포스트의 내용은 [토비의 스프링3] 내용에서 발췌된 것이다.
본 포스트의 내용은 Spring 3.0 을 기반으로 한다.


* 스프링으로 어떤것을 만들수 있는가?

스프링으로 만들수 있는 애플리케이션의 종류에는 제한이 없고 자바를 사용하는 모든 프로젝트에 사용할 수 있다. 하지만, 대부분 자바 엔터프라이즈 환경에서 동작하는 어플리케이션이다 (즉 서버에서 동작하여 클라이언트에게 서비스를 제공) 가장 많이 사용하는 구조는 클라이언트가 웹 브라우저이고, 백엔드 시스템이 DB인 구성이다.


 * 개발도구와 환경

1. JavaSE/JDK : JDK 5.0 or higher (JDBC 4.0 API를 사용 하는 경우 JDK6.0)

2.  JavaEE/J2EE : J2EE 1.4 or JavaEE 5.0 (J2EE 1.4 의 경우 JDK 5.0에서 사용불가능한 경우가 있으므로 주의)

3. IDE : Eclipse(or STS-SpringSource Tool Suite), NetBeans, IntelliJ IDEA

: STS - 최신 이클립스를 기반으로 주요한 스프링 지원 플러그인과 관련 도구들을 모아서 스프링 개발에 최적화되도록 구성된 IDE. 스프링소스가 제공하는 플로거인 조합이 완료된 STS를 사용하면, 플로그인 업데이트와 플러그인간 호환성 등에 신경쓸 필요가 없으므로 편리. 게다가 tcServer 를 함께 설치할수 있어서 편리.

tcServer) Spring 개발을 담당하는 SpringSource 는 apache httpd 서버와 tomcat 의 개발자들이 있어서 스프링어플리케이션에 최적화된 tcServer 를 개발했다.  기술지원을 받을 수 없는 오픈소스제품과 달리, tcServer를 사용하면 기술지원을 받을 수 있음. (개발자 버전은 무료이지만, 정식 운영서버에서 사용하고 기술지원 받으려면 유료 라이선스 구매 필요)

4. 스프링 관련  Plugin(s)

SpringIDE plugin

SpringIDE는 스프링 개발에 유용한 기능을 제공하는 플러그인의 모음. 스프링 프로젝트 설정파일 생성 위저드, XML 설정파일 에디터, bean의 의존관계 그래프, 네임스페이스 관리 기능 등의 기능과 도구를 제공함.

STS plugin

스프링 개발과 설정파일 편집을 지원하는 SpringIDE에 더해서 스프링 어플리케이션의 서버 배치와 같은 추가 기능을 제공해 준다.

STS 가 추가로 제공하는 기타 플러그인

- M2Eclipse : Maven 지원하는 Elipse plugin, 스프링은 그 자체로 20여개의 세부 모듈로 구성되어 있고 100개 이상의 의존 라이브러리가 있기 때문에 Maven의 의존 관리 기능을 활용하는게 좋다.

- AJDT (AspectJ Development Tool) : Elipse 에서 AspectJ AOP 를 이용한 개발을 지원.

- VMCI (Virtual Machine Core Integration) : VMWare 서버 혹은 워크스테이션과의 연동을 지원하는 플러그인. STS의 VMWare 배치기능에 주로 사용

- 이클립스 표준 플러그인 : 이클립스에서 제공하는 주요 표준 플러그인으로 웹 개발을 지원하는 WTP(Web Tool Platform), EMP(Elipse Modeling Project), Mylyn, DSDP(Device Software Developlemt Platform)



* 스프링 애플리케이션의 배포 단위

1. 독립 웹 모듈 (war) : 가장 일반적

2. 엔터프라이즈 애플리케이션 (ear) : 스프링애플리케이션에서 EJB 모듈을 이용하거나 EJB모듈이 스프링어플리케이션을 이용해야 하면, EJB와 스프링웹 모듈을 엔터프라이즈 애플리케이션으로 통합해서 배포해야 한다.

3. 백그라운드 서비스 모듈 (rar) : rar 는 리소스 커넥터를 만들어 배포할 때 사용하는 방식인데, 스프링어플리ㅔ이션이 UI가 없고, 서버내에서 백그라운드 서비스 처럼 동작할 필요가 있다면 rar 모듈로 만들어 배포할 수 있다.



* 라이브러리 관리와 빌드 툴

스프링은 자체로 20여개의 jar 모듈과 직접 참조하는 100개 이상의 의존 라이브러리가 있다. 이들의 버전관리도 문제지만, 모든 라이브러리가 다 사용되는게 아니므로, 라이브러리를 선정하는 것도 문제이다.

20여개이 모듈중 몇개는 필수모듈이지만 그 외의 모듈은 애플리케이션의 아키텍처와 사용기술에 따라 서택적으로 적용할 수 있다. 또한 스프링 모듈 사이에도 의존관계가 있고, 모듈의 의존 관계는 필수와 선택으로 나뉠 수 잇다.

- Elipse 같은 IDE의 자동 빌드 기능이 있고, 관련 빌더를 추가/확장 하는 것으로 빌드 작업을 간소화 시킬 수 있지만, IDE를 통한 빌드 환경이 아닌 경우에도 일관성 있는 빌드가 가능하도록 만들기 위해서, Maven 이나 Ant 같은 환경에 독립적인 빌드 툴을 함께 사용하는것이 바람직 하다. 그 중 절차적인 스크립트와 비슷한 Ant와 달리 Maven 은 POM을 이용하여 선언적으로 관리할 수 있다. 더 매력적인 점은 Maven의 의존 라이브러리 관리 기능이 Transitive (전이적)이고, 이는 스프링의 모든 모듈이 POM 정보를 가지고 있으므로, 스프링을 통한 라이브러리 관리를 좀더 편리하게 도와준다.



* 관련 web sites

* STS : http://www.springsource.com/downloads/sts
* Ecllipse : http://www.eclipse.org/downloads
* Eclipse Maven Plugin : http://www.eclipse.org/m2e/


출처: http://lefthand.tistory.com/43 [lefthand's note]

Spring 의 정의와 목적

* 본 포스팅 내용은 토비의 스프링3의 8장의 내용을 요약한 것이다.


Spring 이란 무엇인가? 


자바 엔터프라이즈 개발을 편하게 해주는 오픈소스 경량급 애플리케이션 프레임워크
창시자 : Rod Johnson
기원 : Expert One-on-One J2EE Design and Development (2003) 의 sample code


- 애플리케이션 프레임워크

일반적으로 라이브러리나 프레임워크는 특정 업무 분야나 한가지 기술에 특화된 목표(예를들면, 웹 계층을 MVC구조로 변경한다거나, 간단한 설정만으로 RDB와 java object를 매칭해주는 ORM기술 제공등)를 가지고 만들어 지지만, 애플리케이션 프레임 워크란 특정 계층이나, 기술, 업무분야에 국한되지 않고 애플리케이션의 전 영역을 포괄하는 볌용적인 프레임워크이다. 애플리케이션 프레임워크는 애플리케이션 개발의 전 과정을 빠르고 편리하며 효율적으로 진행하는데 일차적인 목표를 두는 프레임워크이다.


- 경량급(lightweiight)

스프링 자체가 아주 가볍다거나 작은 규모의 코드로 이뤄졌다는 뜻이 아니다. 스프링은 20여개의 모듈로 세분화 되고 수십만 라인에 달하는 코드를 가진 방대한 규모의 프레임워크이다. 경량급의 의미는 EJB같은 과도한 엔지니어링이 적용된 기술에 대비하여 불필요하게 무겁지 않다는 의미이다.

EJB : 고가의 WAS필요, 난해한 설정파일, 까다로운 패키징, 불편한 deploy 등으로 인한 부담으로 인해 고가의 제품으로 구성된 제대로된 개발환경이 없이 개발이 어려움. 스프링은 tomcat 이나 jetty 에서도 완벽하게 동작한다. 즉, 서블릿 컨테이너만으로 충분하니, EJB컨테이너나 기타 기능을 사용하지 않아도 된다.

(1) 개발환경의 lightweight
(2) 서버 환경의 lightweight
(3) 코드의 상대적인 lightweight


- 자바 엔터프라이즈 개발을 편하게

로우레벨의 트랜잭션이나 상태관리, 멀티스레딩, 리소스 풀링 같은 복잡한 로우레벨 API 를 이해하지 못하더라도 아무런 문제 없이 어플리케이션을 개발할 수 있다.(From Enterprise JavaBeans 1.0 Specification, Chapter 2 Goals)

로우레벨 기술에 신경쓰지 않으면서, 애플리케이션의 핵심인 사용자의 요구사항, 비즈니스 로직을 빠르고 효과적으로 구현하는 것. 즉, 초기에 스프링의 기본 설정과 적용기술만을 잘 이해하고 있으면, 애플리케이션 개발중에는 스프링 관련 Code 에 신경쓸 필요가 없다.


- 오픈소스

스프링은 오픈소스 프로젝트 방식으로 개발되왔다. 지금도 여전히 오픈 소스 개발 모델과 라이선스를 가지고 개발하는 중이다.

라이센스 : Apache Licence Ver 2.0 (스프링을 상업제품에 포함시키거나 비공개프로젝트에서 사용해도 된다. (수정자유롭고 수정된 소스 공개 필요없음)



Spring 의 Goal



- 엔터프라이즈 개발의 복잡함

2000년대 초반 80% 이상의 자바 enterprise project 가 실패했다. 가장 대표적인 이유는 엔터프라이즈 시스템 개발이 너무 복잡해서 이다.

왜 복잡한가? 비즈니스 로직 이외에도 기술적으로 고려해야 할 사항들이 많다.(타시스템 과의 연계, 다양한 형태의 클라이언트 접속을 위한 리모팅 기술, 분산 트랜잭선의 지원, 보안 등)  또한 비즈니스 로직 자체도 점점 복잡해지고 잦은 변경이 요구된다)게다가 이런 엔터프라이즈 기술의 복잡함과 비즈니스 로직의 복잡함이 한데 얽혀서 복잡함이 배가된다.


- 복잡함을 해결하려는 도전

근본적으로 엔터프라이즈 기술의 복잡함과 비즈니스 로직의 복잡함은 줄일수 없다.  그러나 이 두가지 성질이 다른 복잡함을 분리해 낼수 있다.  EJB도 이 목표를 지향하여 선언전 트랜잭션이나 선언적 보안, 컨테이너를 통한 리모팅 기술의 적용, 컴포넌트 단위의 배치, JNDI 를 통한 서비스 검색지원, 서비스 오브젝트의 풀링, 컴포넌트의 생명주기 관리등을 수행하여 이 목표를 달성하려 하였으나, 이를 위해 EJB라는 환경과 스펙에 종속되는 코드로 만들어야 하는 더 큰 복잡함을 안게되어 실패하였다. 게다가 EJB라는 틀 안에서 특정클래스를 상속하게 함으로 자바 언어의 원래 장점마저 상실하고 객체지향적인 특성을 잃어버진 서비스 스크립트성 코드로 변질돼 갔다.

스프링은 EJB와는 다르게 비침투적(non-invasive)기술을 적용하였고, 이는 코드상에 스프링과 관련된 규약과 코드가 등장하지 않는 것을 의미한다. 즉, 스프링이 코드에 불필요하게 등장해서 복잡함을 가중시키지 않는다.


- 복잡함을 상대하는 스프링의 전략


** 기술적 복잡함은 아래와 같이 서비스의 추상화와 AOP 로 상대한다.

1. 서비스의 추상화

트랜잭션 추상화, OXM 추상화, 데이터 액세스에 관한 일관된 예외변환 기능, 데이타 액세스 기술에 독립적인 트랜잭션 동기화 기능 등. 기술적인 복잡함은 추상화를 통해 로우레벨의 기술 구현 부분과 기술을 사용하는 인터페이스를 분리하고, 환경과 사용기술에 독립적인 접근 인터페이스를 제공한다.

2. AOP (Aspect Oriented Programming)

비즈니스 로직 전후로 경계가 설정되어야 하는 트랜잭션, 보안적용, 예외처리, 로깅, 감사 등 기술과 비즈니스 로직의 혼재는 최대한 제거해도 완전히 해결할 수 없으며, 이를 해결하기 위한 스프링의 전략이 AOP 이다. AOP는 최후까지 애플리케이션 로직에 남아있는 기술관련 코드를 깔끔하게 분리해서 별도의 모듈로 관리하게 해주는 강력할 기술이다.


** 비즈니스 로직의 복잡함을 상대하는 전략은 객체지향과 DI이다.

1. OOAD (Object Oriented Analysis & Design)

복잡함을 단순화 할 수 있는 것은 객체지향 기술 자체이며,  스프링은 환경 종속적이지 않고 비침투적인 기술이므로 핵심로직을 다루는 코드에는 스프링이 드러나지 않는다. 따라서 객체지향언어의 장점을 살려 로직의 복잡함을 효과적으로 다루어야 한다.

2. DI (Dependency Injection)

DI는 특별한 기술이라기 보다는 유연하게 확장가능한 오브젝트 설계를 하다보면 자연스럽게 적용하게 되는 객체지향 프로그래밍 기법이다. 스프링은 단지 그것을 더욱 편하고 쉽게 사용하도록 도와줄 뿐이다. DI는 적용하려다 보면 자연스럽게 확장성이 좋은 설계로 이끌어진다. 즉, 바뀔 수 있는 것은 무엇인가? 무엇이 성격이 다른가? 를 지속적으로 고민하게 되고 대상이 되는 Object는 DI를 적용해 분리하고, 인터페이스를 도입하고, DI로 관계를 연결해 주게 되므로 DI를 열심히 적용하다 보면 객체지향 설계의 원칙을 잘 따르고 그 장점을 살린 설계가 나올수도 있다.



출처: http://lefthand.tistory.com/42 [lefthand's note]

Singletone Pattern & Spring IoC Container
* 본 포스트의 내용은 [토비의 스프링3] 내용에서 발췌된 것이다.

* 내용

싱글톤 패턴으 GoF 의 디자인 패턴중 하나다. 디자인 패턴 중에서 가장 자주 활용되는 패턴이기도 하지만, 가장 많은 비판을 받는 패턴이기도 하다. 싱글톤 패턴은 어떤 클래스를 어플리케이션 내에서 제한된 인스턴스 수,  주로 하나만 존재하도록 강제하는 패턴이다. 이렇게 하면 이 클래스의 오브젝트는 애플리케이션 내에서 전역적으로 접근이 가능하다. 단일 오브젝트만 존재해야 하고, 이를 애플리케이션의 여러 곳에서 공유하는 경우에 주로 사용한다.


* Java 에서 Singleton 을 구현하는 일반적인 방법

- 생성자를 private 으로 설정하여 클래스 밖에서는 오브젝트를 생성하지 못하게 함
- 생성된 singleton 오브젝트를 저장할 수 있도록 클래스 내에 자신과 같은 타입의 static field 정의
- static factory method 인 getInstance()를 만들어 최초 호출 시점에만 오브젝트 생성하고 static field 에 저장.

public class UserObject {
private static UserObject INSTANCE;
...
private UserObject(..) {
..
}
public static synchronized UserObject getInstance() {
if (INSTANCE == null) INSTANCE = new UserObject(..);
return INSTANCE;
}
 }


* Java 에서 위와같이 singleton을 구현하는 경우 singleton pattern 의 한계

- private 생성자를 갖고 있기 때문에 상속할 수 없다.
객체지향의 상속과 다형성 적용 불가
- 테스트가 어렵다.
싱글톤은 만들어지는 방식이 제한적이므로 테스트에서 Mock Object 로 대체하기가 힘들다.
- 서버환경에서는 singleton 이 하나만 만들어지는 것을 보장하지 못한다.
서버에서 class loader 를 구성하는 방법에 따라서 하나 이상의 오브젝트가 만들어 질 수 있다.
- 싱글톤의 사용은 전역 상태를 만들 수 있기 때문에 바람직 하지 못하다.
singleton의 static method 를 이용하여 어떤 client 라도 접근/사용할 수 있으므로, 전역상태(global status)로 사용되기 쉽다. 아무 객체나 자유롭게 접근/수정/공유하는 전역상태는 OOP에서는 권장되지 않는다.


* Spring Framework 에서의 singleton

Spring은 서버 환경에서 singleton으로 service object 를 사용하는 것을 지지한다. 다만, java 의 기본적인 singleton 구현방식은 상기의 단점이 있으므로, Spring Framework 자체에서 singleton 형태의 object를 만들고 관리하는 기능인, singleton registry 를 제공한다.
Spring의 ApplicationContext 는 Singleton을 저장하고 관리하는 Singleton registry 이다.


* Spring Registry

Spring 은 디폴트로 내부에서 생성하는 Bean object 를 singleton으로 만든다. 이것은 디자인 패턴의 싱글톤과 비슷한 개념이지만, 구현방법은 확연히 다르다. 즉, Spring container 에서 object 를 singleton registry 에 관리하며 singleton으로 동작하도록 제어한다.

왜 Spring은 singleton으로 bean 을 생성하는 것일까?

하나의 요청(Request)를 처리하기 위해서는 데이타 액세스 로직(DAO), 서비스 로직, 비즈니스 로직, 프리젠테이션 로직등 다양한 기능을 담당하는 오브젝트들이 계층형 구조로 이루어 진다. 매번 클라이언트 요청이 올때마다, 각 로직을 담당하는 오브젝트들을 새로 만들어 사용한다면, 아무리 Java가 오브젝트 생성과 GC(Garbage Collection) 성능이 좋아졌어도 서버가 부하를 감당하기 심들다. 이 때문에 엔터프라이즈 분야에서는 서비스오브젝트 라는 개념을 사용해 왔는데 Servlet 은 Java 엔터프라이즈 기술의 가장 기본이 되는 서비스 오브젝트라고 할수 있다. Servlet은 대부분 멀티스레드 환경에서 Singleton으로 동작한다. 즉, Servlet 클래스 당 하나의 오브젝트만 만들어 주고, 사용자의 요청을 담당하는 여러 스레드에서 하나의 오브젝트를 공유해서 사용한다.

Singleton registry 덕분에 singleton 으로 동작해야 할 어떤 클래스라도 평범한 java class 로 작성될 수 있다. 즉, public 생성자를 가질 수 있으며 static method 를 노출할 필요도 없다. 이것은 테스트 환경에서 자유롭게 object 를 만들 수 있고 또한 OOP의 장점을 그대로 가진다.


* Spring 에서 Singleton object 로 사용할 클래스 설계시 주의점

Spring 에서 singleton 이 멀티스레드 환경에서 서비스 오브젝트에 사용되는 경우에는 상태정보를 내부에 갖고 있지 않은 stateless 로 만들어야 한다. 이 경우, 각 요청에 대한 정보나 생성된 정보는 메소드 파라미터나 메소드 안의 로컬변수 혹은 리턴값 등으로 처리해야 한다. 싱글톤이라해도 메소드 안에서 생성되는 로컬변수는 method가 호출될 때마다 매번 새로 할당되므로 싱글톤이라 해도 여러 스레드가 변수의 값을 덮어쓸 일은 없다.

public class UserDao {
  private ConnectionMaker connectionMaker; <-- (1)
  private Connection c;  <-- (2)
  private User user;       <-- (2)

  public User get(String id) throws ClassNotFoundException, SQLException {
    this.c = connectionMaker.makeConnection();
    ....
    this.user = new User();
    this.user.setId("...");
    ...
    return user;
  }
}

UserDao 는 IoC container 에 의해서 singleton object 로 생성/사용된다고 가정해 보자.
이런 경우, (2)번과 같이 멀티스레드 환경에서 변경될 수 있는 값을 클래스의 인스턴스 변수로 생성하는 경우, 문제가 발생한다. 따라서 Spring 의 singleton bean 으로 사용되는 클래스를 만들때는 (2)번의 경우는 method 내 로컬 변수로 사용하거나 파라미터로 주고 받으며 사용해야 한다.

단, 이 경우에도 클래스 인스턴스 변수로 사용가능한 경우가 있는데 이는 (1) 과 같다.
(1)은 자신이 사용하는 다른 singleton bean 을 저장하려는 용도라면, 인스턴스 변수로 사용해도 좋다. 스프링이 초기화 되고 나면, 이후에 수정되지 않는 경우라면, 멀티스레딩 환경에서 사용해도 문제없다


* Spring bean 의 스코프

scope : 스프링이 관리하는 오브젝트, 즉 빈의 생성/존재/소멸되는 범위

singleton : 스프링 bean 의 기본 scope 는 singleton 이다. 컨테이너 한개에 한개만 생성되며 강제로 제거하지 않는 한 컨테이너가 존재하는 동안 계속 유지된다.
prototype : 컨테이너에 빈을 요청할 때마다 매번 새로운 오브젝트를 만들어준다.
request : 웹을 통해 HTTP 요청시마다 생성되는 scope
session : 웹의 세션과 유사한 scope


출처: http://lefthand.tistory.com/41 [lefthand's note]

POJO (Plain Old Java Object)
* 본 포스트의 내용은 [토비의 스프링3] 내용에서 발췌된 것이다.

POJO (Plain Old Java Object) ?

1. 특정 규약(contract)에 종속되지 않는다.

Java 언어와 꼭 필요한 API 외에 종속되지 않는다. EJB2 의 EntityBean 상속이나 Struts 1 의 ActionForm 상속등 규약에 종속되지 않아야 한다.

2. 특정 환경에 종속되지 않는다.

EJB3 의 JNDI 서버 서비스의 의존이나 특정 벤더의 서버나 기업프레임워크안에서만 동작 가능한 코드가 아니다.

3. 객체지향원리에 충실해야 한다.

특정 기술규약과 환경에 종속되지 않은 Java Object 가 모두 POJO라 할수는 없다. 객체지향 개념이 녹아있지 않은 것만 POJO 이다.


Why POJO?

1. 코드의 간결함

비즈니스 로직과 특정 환경/low 레벨 종속적인 코드를 분리하므로 단순하다.

2. 자동화 테스트에 유리

환경 종속적인 코드는 자동화 테스트가 어렵지만, POJO 는 테스트가 매우 유연하다.

3. 객체지향적 설계의 자유로운 사용

특정 규약 종속적인 객체의 경우 특정 상속을 미리 지정해서, 단일상속만 제공하는 JAVA 언어로서는 더이상 객체지향적 설계를 하는데 제약을 가져오는 경우가 있으나, POJO 는 아무런 규약이나 규제가 없으므로 OO 설계에 매우 자유롭다.



What is POJO Framework?

POJO 프로그래밍이 가능하도록 기술기반을 제공하는 Framework.

1. Spring Framework

엔터프라이즈 기술에만 최소한으로 관여하고 비즈니스 로직을 담당하는 POJO에서는 관여하지 않는다.

2. Hibernate



Spring 의 핵심 기술?

기술과 비즈니스로직을 분리하고 POJO방식의 어플리케이션 개발을 가능하게 한다는 스프링의 목적을 쉽게 이루려면 스프링과 같은 POJO 프레임워크가 필요하다.

POJO 프로그래밍을 손쉽게 할 수 있도록 지원하는 세가지 가능기술(Enabling technology)

(1) IoC/DI (Inversion of Control / Dependency Injection)

IoC/DI 는 스프링의 가장 기본의 되는 기술이자 스프링의 핵심 개발원칙이다. 나머지 두가지 기술인 AOP 와 PSA도 IoC/DI에  바탕을 두고 있으며, 3대기술은 아니지만 자주 등장하는 템플릿/콜백 패턴의 적용도 IoC/DI가 핵심원리다.

(2) AOP (Aspect Oriented Programming)

핵심 관심사를 분리하여 프로그래매 모듈화를 향상시키는 프로그래밍 스타일이다. AOP는 객체를 핵심 관심사와 횡단 관심사로 분리하고,  횡단 관심사를 관점(Aspect)라는 모듈로 정의하고, 핵심 관심사와 엮어서 처리할 수 있는 방법을 제공한다. 스프링은 자체적으로 프록시 기반의 AOP를 지원하며, 로깅, 트랜잭션, 보안 이런것들이 전반적으로 처리하는데 사용됨.

(3) PSA (Portable Service Abstraction)

인터페이스가 다른 다양한 구현을 같은 방식으로 사용하도록 중간에 인터페이스 어댑터 역할을 해주는 레이어를 하나 추가하는 방법



출처: http://lefthand.tistory.com/40 [lefthand's note]

IoC(Inversion of Control) / DI(Dependency Injection)
* 본 포스트의 내용은 [토비의 스프링3] 내용에서 발췌된 것이다.


What is IoC (Inversion of Control)?

프로그램의 제어 흐름 구조가 뒤바뀌는 것.

일반적으로, main() 같은 프로그램이 시작되는 지점에서 다음에 사용할 오브젝트를 결정하고, 생성하고, 만들어진 오브젝트내의 메소드를 호출하고 하는 작업이 반복된다. 이런 프로그램 구조에서 각 오브젝트는 프로그램 흐름을 결정하거나 사용할 오브젝트를 구성하는 작업에 능동적으로 참여한다. 즉, 모든 종류의 작업을 사용하는 쪽에서 제어하는 구조이다.

제어의 역전이란, 제어 흐름의 개념을 거꾸로 뒤집는 것이다. 오브젝트는 자신이 사용할 오브젝트를 스스로 생성하거나 선택하지 않는다. 또한 자신도 어떻게 만들어지고 어디서 사용되는지 알수 없다. 모든 제어 권한을 자신이 아닌 다른 대상에게 위임한다. 프로그램의 시작을 담당하는 main()같은 엔트리 포인트를 제외하면 모든 오브젝트는 이렇게 위임받은 제어 권한을 갖는 특별한 오브젝트에 의해 결정되고 만들어 진다. 단지 스프링에서 사용되는 개념이 아니고, 매우 폭넓게 사용되는 프로그래밍 모델이다.

- 작업을 수행하는 쪽에서 Object 를 생성하는 제어 흐름의 개념을 거꾸로 뒤집는다.
- IoC 에서는 Object  가 자신이 사용할 Object 를 생성하거나 선택하지 않는다.
- 또한 Object 는 자신이 어떻게 생성되고 어떻게 사용되는지 알 수 없다.
- 모든 Object  는 제어 권한을 위임받는 특별한  Object 에 의해서 만들어 지고 사용된다.



What is DI (Dependency Injection) ?

- Spring이 지원하는 IoC방식을 좀더 명확히 설명.
- dependent object(의존 오브젝트) : 사용 대상이 되는 오브젝트
- 의존 오브젝트와 그것을 사용할 주체, 보통 클라이언트라고 부르는 오브젝트를 런타임시에 연결해 주는 작업.

의존관계주입의 조건
- 클래스 모델이나 코드에는 런타임 시점의 의존관계가 드러나지 않는다. (즉, 인터페이스에만 의존)
- 런타임 시점의 의존관계는 컨테이너나 팩토리같은 제 3의 존재가 결정한다.
- 의존관계는 의존 오브젝트 레퍼런스를 외부에서 제공(주입)해줌으로 만들어진다.


IoC 개념이 녹아 있는 Example

1.  servlet 과 container.
 : 서블릿에 대한 제어권한을 가진 컨테이너가 적절한 시점에 서블릿 클래스의 오브젝트를 만들고 그 안의 메소드를 호출한다.

2. Template Method Pattern (Design Pattern)
:  http://lefthand.tistory.com/34
역시 제어권을 상위 템플릿 메소드에 넘기고 서브 클래스는 필요할 때 호출되어 사용되는 개념.

3. Framework
 : 라이브러리를 사용하는 어플리케이션은 어플리케이션의 흐름을 직접 제어하지만,  프레임워크는 애플리케이션 코드가 프레임워크에 의해서 사용된다. 보통 프레임워크 위에 개발한 클래스를 등록해 두고, 프레임워크가 흐름을 주도하는 중에 개발자의 어플리케이션 코드를 사용하도록 만드는 방식이다. 즉, 제어의 역전 개념이 적용되어 있어야 한다.



스프링 IoC의 용어 정리

* bean

: 스프링에서 제어권을 가지고 직접 만들고 관계를 부여하는 오브젝트를 bean 이라 부른다. 자바빈, EJB의 빈과 비슷한 오브젝트 단위의 애플리케이션 컴포넌트를 말한다. 하지만 스프링을 사용하는 애플리케이션에서 만들어지는 모든 오브젝트가 빈은 아니다. 스프링의 빈은 스프링 컨테이너가 생성과 관계설정, 사용등을 제어해주는 오브젝트를 가리킨다.

* bean factory

스프링의 IoC를 담당하는 핵심 컨테이너를 가리킨다. 빈을 등록/생성/조회/반환/관리한다. 보통은 bean factory 를 바로 사용하지 않고 이를 확장한 application context 를 이용한다. BeanFactory 는 bean factory 가 구현하는 interface 이다. (getBean()등의 메소드가 정의되어 있음)

* application context

bean factory를 확장한 IoC 컨테이너이다. 빈의 등록/생성/조회/반환/관리의 기능은 bean factory 와 같지만, 여기에 spring 의 각종 부가 서비스를 추가로 제공한다. ApplicationContext는 application context가 구현해야 하는 interface이여, BeanFactory 를 상속한다.

* 설정정보/설정 메타정보 configuration metadata

application context 혹은  bean factory 가 IoC를 적용하기 위해 사용하는 메타정보이다. 스프링의 설정정보는 컨테이너에 어떤 기능을 세팅하거나 조정하는 경우에도 사용하지만 주로 bean 을 생성/구성하는 용도로 사용된다.

* container (IoC container)

IoC 방식으로 bean을 관리한다는 의미에서 bean factory 나 application context 를 가리킨다. (spring container = application context) application context는 그 자체로 ApplicationContext 인터페이스를 구현한 오브젝트를 가리키기도 하는데, 하나의 애플리케이션에 보통 여러개의 ApplicationContext Object가 만들어진다. 이를 통칭해서 strping container라고 부를 수 있다.

* spring framework

spring framework 는 IoC container, application context 를 포함해서 spring이 제공하는 모든 기능을 통칭할때 주로 사용된다.




Spring 에서 IoC/DI 활용 방법:

*  DI를 이용한 핵심기능의 변경

디자인 패턴의 전략패턴에 해당하는 의존 대상의 implementation 의 변경에 사용함.
A->B 에서 A 기능 일부를 B에게 위임하는 경우 필요에 따라 B의 구현방식을 통째로 B1, B2, B3로 변경한다.

ex) DAO의 구현을 JDBC, JPA, Hibernate, JDO, iBatis 등으로 변경
ex) 사용자 등급 결정 정책을 DI로 새오운 클래스로 변경


* 핵심기능의 동적인 변경

DI 도 runtime 시에 동적으로 의존 Object 를 연결해 주긴 하지만, DI되면 정적인 관계가 형성된다. 하지만 DI 를 잘 이용하면, 애플리케이션이 동작하는 중간에 의존 대상을 dynamic 하게 변경할 수 있다.

ex)사용자 등급에 따른 DataSource의 선택
DAO->DataSource 일때, DAO 하나가 여러개의 DataSource 에 의존하게 만들어, 현재 접속한 사용자의 등급에 따라서 다른 DataSource 를 DAO가 사용하도록 한다.
ex) 사용자 별로 독립 Object 만들고 서비스 Object가 이를 DI 받아서 사용하는 경우.


* 부가기능의 추가

DI의 다른 활용방법은 핵심기능은 그대로 두고 부가기능을 추가하는 것이다. Decoration Pattern 의 경우임.

ex) 트랙잭션 기능 부여.
핵심 기능은 그대로 두고 결과나 전달 파라미터를 조작할 수 있고, 파라미터나 리턴 결과를 활용해 로깅이나 보안처리 같은 부가적인 작업을 수행 할 수도 있다. 이베트 발생 처리 등등.


* 인터페이스의 변경

클라이언트가 사용하는 실제 인터페이스와 실제 오브젝트 사이의 인터페이스가 일치하지 않는 경우에도 DI 는 유용하다. A->B인터페이스 고, C는 B인터페이스를 구현하지 않았더라도 A가 DI를 통해 B를 사용하므로, B의 구현 오브젝트에서 C를 호출해 주는 어댑터 처럼 동작하면 된다.
PSA (Portable Service Abstraction): 이를 좀 더 일반화 하여 아예 인터페이스가 다른 다양한 구현을 같은 방식으로 사용하도록, 중간에 인터페이스 어댑터 역할을 해주는 레이어를 하나 추가하는 방법이다.



* 프록시

laze loading(필요한 시점에서 실제 사용할 오브젝트를 초기화, 준비) 할때, 또는 원격 오브젝트를 호출할 때 마치 로컬에 존재하는 오브젝트 처럼 사용할 수 있도록 할때 프록시가 필요하고, 이 경우 DI를 필요로 한다. Spring이 지원하는 리모트 기술은 EJB원격호출, 웹 서비스, REST, HTTP 등 다양하다.


* 템플릿과 콜백

템플릿/콜백 패턴은 DI의 특별한 적용방법이다. 반복적으로 등장하지만, 항상 고정적인 작업 흐름과 그 사이에서 자주 바뀌는 부분은 분리해서 템플릿과 콜백으로 만들고 DI원리를 응용해 적용한다. Spring 이 기본으로 제공하는 20여가지의  템플릿/콜백외에도 직접 응용할 수 있어야 한다.


* Singleton 과 Object Scope

DI를 프레임워크로 이용한다는건 DI대상 오프젝트를 컨터이너가 관리한다는 의미이다. 오브젝트의 생성부터 관계설정, 이용, 소멸에 이르기까지 모든 과정을 DI컨테이너가 주관하기 때문에, 그 오브젝트의 스코프를 자유롭게 제어할 수 있다. 스프링의 DI는 기본적으로 singleton으로 오브젝트를 만들어서 사용하게 하고, 컨테이너가 알아서 싱글톤을 만들고 관리하므로 클레스 자체는 싱글톤을 고려하지 않아도 된다. 물론, 스프링에서는 싱글톤 외에도 다양한 스코프를 갖는 오브젝트를 만들어 DI 할 수 있다.


* 테스트

DI의 또다른 중요한 용도는 Test 이다.테스트 할 대상이 사용하는 오브젝트를 테스트 목적으로 만들어진 Mock 오브젝트로 대체하면 테스트가 매우 용이하다.



출처: http://lefthand.tistory.com/39 [lefthand's note]

apache module configuration
httpd.conf  에 LoadModule 되는 (혹은 static library로 포함되는) apache module 은 각각의 설정을 저장하기 위해 config 객체를 사용할 수 있다. 이 config 객체를 사용하는 경우 각 서버(virtual server 와 기본서버)별로 각각 생성된다. apache module config 객체를 사용하기 위해서,  apache module 은 모듈 정의 부분에서 function을 지정할 수 있으며,  편의상 이하 이 function 을 create_server_config라 임의로 지칭하기로 한다.
 
[create_server_config function 호출 시기]
static void * (*pf_create_server_config) (apr_pool_t *p, server_rec *s);

1. apache start/stop 시 전역적으로 최소 1번 호출됨.
 : default module config 객체를 생성과 초기 설정이 이루어짐.
   apache 서버가 default server 이외에 1개 이상의 virtual server 를 구성하는 경우, 각 Virtual Server      에서 작성된 apache module  의 configuration command 를 사용하지 않으면,  이때 생성된 config 내  용이 각각의 virtual server module config 객체로 복제 된다.

2. 각 Virtual server 별로 overriding 가능
 : 만약 virtual server 내에 configuration command 를 하나 이상 정의하면,  그때는 default module      config 객체를 복제하지 않고, create_server_config 함수가 virtual server 를 위해 다시 호출된다.


! CAUTION1) create_server_config  에 전달되는 server_rec * 은 1번의 경우, host 정보가 null 로 들어오며, 2번의 경우에는 각 virtual server 의 설정 값을 갖는다.
!CAUTION2) create_server_config  는  configuration commend 호출 전에 호출돤다.
!CAUTION3) 전달되는 pool 은 pConf 이다. (apache pool hiarachy 참고)


[ap_hook_post_config 이용]
static int (*pf_post_config) (apr_pool_t *p, apr_pool_t *plog, apr_pool_t *ptemp, server_rec *s);

apache module 은 여러가지 hook 을 제공하며, 사용자들이 기능을 추가/변경 할수 있도록 한다. module config 를 위해서 command 를 다 읽은 후에 설정 내용을 변경/수정 할수 있도록 ap_hook_post_config  를 제공하며, 여기에 기능을 추가 할 수 있다.
각 Virtual server 별로 설정을 달리 해야 할 것들이 있다면 여기서 수행하면 된다.

!CAUTION1) server_rec * 구조체에는 default server 와 Virtual Server 들을 모두 참조가능하도록 default server 의 server_rec 이 전달되며, s = s->next 값으로 모든 서버들의 설정을 검토할 수 있다.
!CAUTION2) 전달되는 pool 은 pConf 이다. (apache pool hiarachy 참고)


module config 는 각 서버당 1개씩 생성되고, 프로세스 간 공유되므로, 기본적으로 최초 apache 로딩 시 값 설정 후에는 실제 서비스에서  변경하지 않는 것이 좋다. 만약 module config 를 변경해야 할 일이 있다면, pConf 에 mutex 를 생성하여 사용해야 한다.

개인적으로는, mutex 사용보다는 메모리가 충분하다면,  apache 가 MPM 이 prefork 방식인 경우, 각 process 별로 메모리를 전역으로 복제/갱신하여 사용하는 것이 더 나을 수 있다. (물론 메모리 크기와 갱신 주기 등등 여러가지를 고려해야 함)


출처: http://lefthand.tistory.com/38 [lefthand's note]

Rewrite & Redirect
아파치 설정의 Rewrite 와 Redirect 에 대해서 간략히 정리한다.

301 Redirect : Permanent Redirect, 브라우저에서 해당 내용을 cache 하여 다음에 요청시에 직접 변경된 주소로 접속한다.
302 Redirect : Temporary Recirect,

<mod_alias.c>
base 모듈(apache 설치시 디폴트로 함께 설치되는 모듈)
default - 302 Redirect (Temporary)
Redirect 
RedirectMatch


<mod_rewrite.c>
Extension 모듈 (apache 설치 시 선택하여 설치해야 하는 모듈, static, dynamic 모두 가능)
!main server의 설정이 각각의 virtual host 에 상속되지 않는다. virtual host 별로 각각 설정해 줘야함.
default - 302 redirect

옵션 :
[NC] no-casesensitive
[NE] no-escape
[R] 주소창이 변하기 않기를 원할때
[L] last 적용
[OR] 컨디션의 or
...

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond
RewriteRule
</IfModule>

RewriteRule ^products/([0-9][0-9])$ /products/$1/ [R]
$1, $2, .. $9 첫번째그룹, 두번째  그룹...


출처: http://lefthand.tistory.com/31 [lefthand's note]

blocking/non-blocking socket

* Blocking Socket
- default 값 (socket() 으로 생성되는 기본값)
- connect : connection completion 까지 block
- read : 버퍼에 읽을 값이 없으면 block
- write : 버퍼가 꽉 차서 쓸 수 없으면 block
- accept : backlog queue 에 값이 없으면 block
: blocking 소켓 통신에서 어떤 에러 결과든지 메소드는 자동으로 에러를 규명하는 코드를 같이 리턴한다. 에러는 네트워크 종료, 닫힌 소켓, 아이오 에러 등이 될 수 있다
동기식 통신을 사용한다면 blocking 통신이 더 낫다.

* Non-blocking Socket
- connect : connection 요청 후 즉시 return. connection 이 완료되었는지 보증 안됨.(getsockopt 로 확인)
- read : 버퍼에 읽을 값이 없으면 -1 return (errno : EWOULDBLOCK or EAGAIN)
- write : 버퍼가 꽉 차서 쓸 수 없으면 -1 return (errno :EWOULDBLOCK or EAGAIN)
- accept : backlog queue 에 값이 없으면 -1 return (errno : EWOULDBLOCK or EAGAIN)
: 할수 있는 일이 없으면, 종료하고, 다른 작업(?) 을 할 수 있고, 할 수 있는 일이 있을 때만 작업한다.
비동기식 통신에서는 소켓이 묶이는 것을 피하기 위해 non-blocking 통신이 필요하다.

* Nonblocking socket 설정
int flag, sock_fd;
sock_fd = socket (AF_INET, SOCK_STREAM, 0);
flag = fcntl (sock_fd, F_GETFL, 0);
fcntl ( sock_fd, F_SETFL, flag|O_NONBLOCK );

* timeout 설정


출처: http://lefthand.tistory.com/29 [lefthand's note]

Linux 에서 사용자별 메모리 문제 발생시 대응 방법
본 문서에서는  Linux 에서 OOM(Out-Of-Memory) 발생 시 대응 방법들이다.

1. 문제 발생 방지

[설정파일을 통한  limit (/etc/security/limits.conf)]

: 각 사용자 혹은 그룹등에 리소스 사용 제약사항을 걸어두면, 자원의 무제한 사용을 막을 수 있다. 특정 사용자 혹은 그룹등이 사용하는 프로세스의 메모리가 예상 가능하며, 계속 증가되지 않는다고 가정하는 경우 사용하면 유용하다.

!) 현재는 (kernel : 2.6.31) 메모리 관련 item 으로는 rss (resident set size:real 할당 메모리)가 있지만 이 값에 설정한다고 해서, memory 사용을 막지는 못한다. 제대로 동작된다고 보여지지 않는다.

!) 메모리 제한을 위해서, 사용할 수 있는 방법은 as(address space) 에 limit 을 걸면 잘 동작한다.
as 는 Virtual Memory Address Space 이다. 따라서 내가 10M 정도의 제약을 가하고 싶다면 10*1024 = 10240 값을 주면 된다. (단위는  KB 이다.) 주의할 점은, 이 제약조건은 사용자 혹은 그룹등이총 사용하는 리소스가 아니라, 사용자 혹은 그룹등에서 사용하는 프로세스 당 제약 조건이다.

예) *        soft        as         10240
     *        hard        as          10240

soft 는 기본적으로 적용되는 limit 항목이며, hard 까지 limit 상승이 가능하다. 프로그램 내부에서는 기본설정된 값(soft limit 조건)보다 더 큰 값을 사용해야 하는 경우 최대 hard 에 설정된 값까지 limit 을 증가시킬 수가 있지만, 이를 위해서는 root 권한이 필요하다.

!) /etc/security/limits.conf 값은 shell 이 생성될 때 적용되며, 기존 shell 에는 적용되지 않는다. 따라서 기존 shell 을 이용할 때는 명령창에 ulimit -v 10240 으로 동일하게 적용학 수 있다.


2. 원인 분석

[문제 발생 소스를 수정 가능한 경우]

: 문제의 재현스텝이 불분명하고, 발생 지점을 확인하기 어렵지만, 문제의 소스를 수정할 수 있는 경우, 기존에 짜여진 소스는 그대로 두고 memory hook 을 정의해서 문제 발생 지점을 확인 할 수 있다.

 linux memory hook 사용 법


[문제 발생 소스를 수정 불가능한 경우]

: 문제의 재현스텝이 불분명하고, 발생 지점을 확인하기 어렵우며, 문제의 소스를 수정할 수 없는 경우, 컴파일을 다시 할 수 있다면 gcc -g 옵션을 추가해서 재 컴파일 한다. 디버깅 옵션이 설정되지 않은 상태에서 컴파일 옵션 마저 변경할 수 없는 경우라면, 더이상 진행 불가하다. 기존 바이너리가 -g 옵션으로 컴파일 되었거나, 컴파일을 -g 옵션으로 다시 할 수 있다면, 1번의 /etc/security/limits.conf 파일에 core 파일 생성을 unlimited 로 추가한다.

*       -        core      unlimited

linux reboot 후에도 위의 옵션이 먹지 않는다면, /etc/profile 을 확인하자.
아래의 내용이 있다면, 주석처리한다.
#ulimit -S -c 0 > /devnull 2>&1

만약, 프로그램 동작 중, 다시 OOM 상황이 발생하는 경우, 1번에서 제한한 limit 값에 도달하면, 운 좋으면 core 를 떨어뜨리고 죽을 것이다. 여기서 운이 좋다는 것은 프로그램이 메모리를 사용하기 전에 NULL check 를 하지 않는 경우이다. 만약 프로그램이 메모리 사용전 NULL check 를 꼼꼼히 한다면, 프로그램은 오류 상태로 정상 종료 할 것이다.


[Tool 을 통한 분석]

프로그램이 -g 옵션으로 컴파일 되어 있고, 성능 이슈가 크지 않다면, valgrind 의 여러가지 툴을 이용해서 메모리 증가 지점에 대한 상세한 로그를 받을 수 있다. 단, valgrind 등 툴을 사용하여 프로세스를 띄우는 경우, 프로파일링을 위해서 많은 자원과 시간이 소모되므로, 실 서비스에 적용하여 테스트 하기에는 적합하지 않다.


출처: http://lefthand.tistory.com/28 [lefthand's note]

[SQL] mysql
command line 기준으로 간략히 정리함.

[로그온]
mysql -u[id] -p [dbname]

[계정생성]
: 많은 항목 중 다음의 컬럼만으로 기본 사용자 생성/등록
$ mysql -u root -p mysql
mysql> INSERT INTO user (Host, User, Password) VALUES ('localhost', 'userid', password('userpwd'));
mysql> INSERT INTO user (Host, User, Password) VALUES ('%', 'userid', password('userpwd'));
mysql> FLUSH PRIVILEGES;


[계정삭제]
mysql> DELETE FROM user WHERE user='userid';
mysql> FLUSH PRIVILEGES;


[데이타베이스 생성]
$ mysql -u root -p mysql
mysql> CREATE DATABASE dbname;


[데이타베이스 목록 조회]
mysql> SHOW DATABASES;


[데이타베이스 삭제]
mysql> DROP DATABASE [IF EXISTS] dbname;
IF EXISTS 는 db 가 없더라도 오류 발생시키지 않는다.


[작업db 변경]
mysql> USE dbname;
 

[db 접근권한 설정]

(1) 접근권한을 DB 에 직접 UPDATE  하는 방법
mysql> INSERT INTO db (Host, Db, User, Select_priv, Insert_priv, Update_priv, Delete_priv, Create_priv, Drop_priv, Grant_priv, References_priv, Index_priv, Alter_priv, Create_tmp_table_priv, Lock_tables_priv, Create_view_priv, Show_view_priv,  Create_routine_priv, Alter_routine_priv, Execute_priv) VALUES ('localhost','dbname','userid','y','y','y','y','y','y','y','y','y','y','y','y','y','y','y','y','y');
mysql> FLUSH PRIVILEGES;


(2) grant 명령 이용 : 생성된 user 가 없는 경우, user 생성까지 수행한다.
mysql> GRANT ALL
         -> ON dbname.* TO 'userid'@'host'
         -> IDENTIFIED BY 'pwd';
mysql> FLUSH PRIVILEGES;


    ex) 로컬호스트에서 userA가 dbA 에 수행항목과 접근 허용
          GRANT SELECT, UPDATE, INSERT, DELETE, ALTER, CREATE
          ON dbA TO 'userA'@'localhost'
          IDENTIFIED BY  'userApwd';

    ex2) 모든 서버에서 접근할 수 있도록 허용
         GRANT SELECT, UPDATE, INSERT, DELETE, ALTER, CREATE
         ON dbA TO 'userA'@'%'
         IDENTIFIED BY  'userApwd';



[생성된 계정으로 로긴]
$ mysql -u userid -p [dbname]


[테이블 목록 조회]
mysql> SHOW TABLES;


[테이블 스키마 조회]
mysql> EXPLAIN tablename;
or
mysql> DESCRIBE tablename;


[테이블 생성]
mysql> CREATE TABLE tablename (
         -> column_name1 INT UNSIGNED NOT NULL,
         -> column_name2 VARCHAR(15) NOT NULL,
         -> column_name3 INT );


[테이블 이름 변경]
mysql> RENAME TABLE tablename1 TO tablename2[, tablename3 TO tablename4];


[테이블 삭제]
mysql> DROP TABLE tablename;


[제약 조건 생성]
mysql> CREATE INDEX indexname ON tablename (columnname1[, columname2]);


[로컬 파일 import]
CSV 등 파일에서 import 하여 테이블을 생성한다.
mysql> LOAD DATA LOCAL INFILE 'filepath'
          -> INTO TABLE tablename
          -> FIELDS TERMINATED BY ','
          -> OPTIONALLY ENCLOSED BY '\"'
          -> LINES TERMINATED BY '\n' ;


[DB 상태 보기]
mysql> STATUS;


[INSERT]
mysql> INSERT INTO tablename VALUES(value1, value2, ...);
or
mysql> INSERT INTO tablename(column1, column2, ..) VALUES(value1, value2, ...);


[SELECT]
mysql> SELECT column1, column2, .. FROM tablename;
mysql> SELECT column1 AS 'Alias1', column2 AS 'Alias2', .. FROM tablename;
mysql> SELECT * FROM tablename ORDER BY column1 DESC;
mysql> SELECT * FROM tablename WHERE 조건;


[UPDATE]
mysql> UPDATE tablename SET column1=새값  WHERE 조건;


[DELETE]
mysql> DELETE FROM tablename WHERE 조건;



출처: http://lefthand.tistory.com/26 [lefthand's note]

windows application exception
- build 시 pdb 생성
- 유저모드 덤프 설정
(아래의 툴을 이용해서 덤프 출력.)
http://www.microsoft.com/downloads/details.aspx?FamilyID=E089CA41-6A87-40C8-BF69-28AC08570B7E&displaylang=en
:이걸 설치하면 옵션이 몇개 있는데 설정하고 해당 exe를 등록해 놓으면 그 exe가 exception이 나면 덤프가 자동을 떠짐
- windbg이용 덤프분석
windbg에서 !analyze -v 치면 바로 확인됨.
 소스 연결해 놓으면 소스까지 다 찾아감


출처: http://lefthand.tistory.com/25 [lefthand's note]



maven 2 기본

maven 2 기본(1)
1. maven ?

maven 은 Apache 에서 공개 프로젝트로 진행중인 프로젝트 관리툴이며, java 기반의 모든 프로젝트를 통합 관리한다. maven 은 프로젝트 빌드에 가장 좋은 모델을 제공하여 생산성 향상에 도움이 된다.
maven 은 많은 플러그인 들로 구성되며, 이 플러그인 들을 통해서 Builds, Documentation, Reporting, Dependencies, SCMs, Releases, Distribution 등이 주요한 feature 로 제공된다.
각각의 플러그인 들을 goal 이라고 불리우는 서비스를 제공하며, 각각의 goal 은 필요에 따라서 parameter 를 요구하기도 한다.
현재 version 2.x 가 개발/사용 중이다.

2. maven 호출/실행 형태

mvn [plugin]:[goal] [parameters]

위와 같이 명령을 실행하면 Maven은 해당 플러그인이 로컬 저장소에 있는지 확인하고 없으면 다음의 위치에서 다운로드 받는다. (from http://repo1.maven.org/maven2/ , specifically the org/apache/maven/plugins subfolder)
플러그인 준비가 완료되면 주어진 파라메터를 사용해서 지정된 goal을 실행한다.
제공되는 플러그인의 종류와 각각의 goal 은 http://maven.apache.org/plugins/index.html 에 상세히 기술되어 있다.

mvn [task]

task 로 정의된 일들을 실행한다.
task 는 plug-in 의 goal 들의 조합이다.
다음과 같은 task 등이 사용된다.

complie : src/main/java 디렉토리에 위치한 구현 코드만 컴파일
test-compile : src/main/test 디렉토리에 위치한 테스트 코드를 컴파일 한다. test-compile 을 실행할 경우 compile 이 먼저 실행된다
package : compile, test-compile, test, package 순으로 task 가 실행된 후 jar, war 파일 등으로 packaging 이 target 디렉토리 하위에 생성된다. 생성되는 jar, war의 명명 규칙은 artifactId-version.packaging이 된다.
install : install 은 package 에 의하여 생성된 jar, war 파일을 Local Repository에 등록한다.
deploy : deploy 는 jar, war 파일을 외부 Remote Repository에 등록한다.
site : 문서화 작업을 수행한다.


3. 프로젝트 생성시 용어

* groupId
Maven은 프로젝트를 구분하기 위해 groupId와 artifactId를 사용합니다.
groupId 는 인터넷에서 내 프로젝트를 구분하기 위해서 사용되는 것으로 java package name 형태로 만든다.
(Maven naming 참조: http://maven.apache.org/guides/mini/guide-naming-conventions.html)
ex) org.apache.maven, org.apache.jakarta.commons

* artifactId
artifact 는 프로젝트의 결과물을 의미하며 버전이 없는 jar 파일 이름으로 lowercase 문자로 설정한다.
third-party jar 를 생성해야 하는 경우라면, 기존 배포되는 이름을 artifactId 로 설정한다.
ex) maven, commons-math

* version
버전을 지정한다. (특히 artifact 를 distribute 할때)
숫자와 . 을 사용해서 표기하며 날짜를 버전에 표기하지는 않을것을 권고함.
third-party jar 를 생성하는 경우, 그들의 버전 정책을 따른다.
eg. 2.0 , 2.0.1 , 1.3.1



출처: http://lefthand.tistory.com/5 [lefthand's note]

Maven 2.0.9 설치
1. 다운로드
maven.apache.org 에서 최신 버전 다운로드
ex) http://www.apache.org/dyn/closer.cgi/maven/binaries/apache-maven-2.0.9-bin.zip

2. 압축풀어 적당한 위치에 복사
C:\Program Files\Apache Software Foundation\\apache-maven-2.0.9

3. 환경변수 등록
    3-1. Maven 관련 환경변수
          M2_HOME(mandatory)
             ex) "C:\Program Files\Apache Software Foundation\apache-maven-2.0.9"
                  (맨끝의 \ 는 포함시키지 않는다.)
          M2(mandatory) "%M2_HOME%\bin"
          MAVEN_OPTS(optional) JVM 설정에 관련된 파라미터
             ex) "-Xms256m -Xmx512m".
    3-2. 기타 환경변수 확인
        JAVA_HOME "C:\Program Files\Java\jdk1.6.0_06"

4. 환경변수 수정(PATH)
    4-1. Maven 환경변수
        Path "%M2%;" 추가
    4-2. 기타 환경변수 확인
        Path "%JAVA_HOME%\bin" 추가



출처: http://lefthand.tistory.com/4 [lefthand's note]

자바에서 JDK / SDK 의미변천사
Java 버전 정책은 참으로 모를일이다..
불필요하게 혼동을 야기하므로 대략적으로 정리해 본다.
(근거자료 from java.net, java.sun.com, official description)

* JDK 1.x :
    JDK 는 "Java Development Kit" 의 축약어로 사용됨.

* JDK 1.2, J2SDK 1.2:
    JDK 는 "J2SE(TM) Development Kit" 의 축약어로 사용됨.
    JAVA 2nd Generation 이란 의미의 "2" 가 사용되기 시작함.
    Sun 의 웹 사이트에 따르면 JDK 보다는 J2SDK, JRE 보다는 J2RE 를 사용하도록 권고 하였으나
    기 사용 개발자들의 인기에 의해 JDK 가 계속 사용되면서 JDK 의 의미는
    "J2SE(TM) Developemnt Kit" 을 나타내게 됨.

   이러한 형태의 사용은 JDK 1.2(J2SDK 1.2) 부터 JDK 1.4.x (J2SDK 1.4.x) 까지 유지됨.

   => Due to significant popularity within the Java developer community,
    the development kit has reverted back to the name "JDK" from "Java 2 SDK" (or "J2SDK"),
    and the runtime environment has reverted back to "JRE" from "J2RE".
    Notice that "JDK" stands for "J2SE Development Kit".
    The name "Java Development Kit" has not been used since 1.1, prior to the advent of J2EE and J2ME.

* JDK 5.0, JDK 5, JDK 1.5.0, JDK 1.5:
    JDK 는 "Java(TM) SE Developement Kit" 의 의미로 사용됨.
    Java2 에서 2 제거됨. Java 를 강조하기 위해 TM 위치를 옮김 (J2SE(TM)->Java(TM) SE)
    제품버전 (Product Version)과 개발버전 (Release Version) 을 따로 가져가기 시작
    제품버전은 5.0 (or 5), 개발버전은 1.5.0 (or 1.5)
    즉, J2SDK 5.0 을 설치하고 java -version 하면 1.5.0 리턴

* Java EE 5 SDK:
    SDK 는 "Java(TM) EE" 를 표현하기 위해서만 사용됨.
    Version 5.0 부터는 SDK 는 JDK 와 의미가 완전히 분리되어 EE 용으로만 사용됨.

* JDK 6:
    JDK 는 "Java(TM) SE Developement Kit" 의 의미로 사용됨.
    버전 표기를 한자리로 사용,
    JDK 6.0 은 사용안함, 단, 기존 사용되는 JDK 5.0 은 JDK 5 와 혼용하여 사용함.

* Java EE 6 SDK :
    SDK 는 "Java(TM) EE" 를 표현하기 위해서만 사용됨.


또 언제 바뀔지 모르지만 ^^



출처: http://lefthand.tistory.com/3 [lefthand's note]

JDK & JRE 차이
JRE 와 JDK 에 대한 차이이다. 알고보면 당연한 것임..

JDK 설치시에 JRE 가 함께 설치되므로 따로 JRE 를 설치할 필요는 없다.
Java 개발을 하지 않고 Application Server 만 운영한다면 JRE 만 설치하면 된다.

(from jGuru.com)

The "JRE" is the Java Runtime Environment. I.e.,
the JRE is an implementation of the Java Virtual Machine which actually executes Java programs.
The java programming language adds the portability by converting the source code to byte code version which can be interpreted by the JRE and gets converted to the platform specific executable ones. Thus for different platforms one has corresponding implementation of JRE. But JRE has to meet the specification JVM (Java Virtual Machine) Concept that serves as a link between the Java libraries and the platform specific implementation of JRE. Thus JVM helps in the abstraction of inner implementation from the programmers who make use of libraries for their programmes.

The "JDK" is the Java Development Kit. I.e.,
the JDK is bundle of software that you can use to develop Java based software.
The JDK comes along with java libraries and JVM embedded in it.

Typically, each JDK contains one (or more) JRE's along with the various development tools
like the Java source compilers, bundling and deployment tools, debuggers, development libraries, etc.



출처: http://lefthand.tistory.com/2 [lefthand's note]

maven 2 기본(2) - POM
(by http://maven.apache.org/guides/introduction/introduction-to-the-pom.html)

POM (Project Object Model) ?

maven 2 에서 사용되는 작업 단위이다.
pom.xml 이라는 이름의 xml 파일이며, 각각의 프로젝트 빌드와 설정에 사용되는 많은 값들이 기술된다.
maven 1 에서 사용되는 project.xml 은 maven 2 부터는 pom.xml 로 대체되며,
maven 1 에서 프로젝트 플러그인 들의 goal 을 기술하기 위해 사용된 maven.xml 은 pom.xml 에 기술된다.
maven 은 task 나 goal 을 실행시키기 위해서 pom.xml 을 참조한다.

Super POM ?

Super POM 은 maven 의 디폴트 POM 이며 각각의 프로젝트에 생성되는 POM 들은 Super POM 으로 부터 모든 값을 상속받는다.

POM 의 최소 구성요소

* project root
* modelVersion - should be set to 4.0.0
* groupId - the id of the project's group.
* artifactId - the id of the artifact (project)
* version - the version of the artifact under the specified group

Fully qualified artifact name ?

artifact 를 구분하기 위한 full name 이다.
<groupId>:<artifactId>:<version> 형태


Project Inheritance

maven 에서 관리하는 sub project 들 간에 POM 을 상속시킬 수 있다.
child pom 은 parent pom 의 속성을 상송받고, 자기 속성을 추가/변경 할 수 있다.
(자세한 예는 http://maven.apache.org/guides/introduction/introduction-to-the-pom.html 의 project inheritance 참고)

Project Aggregation

maven 에서 관리하는 sub project 들의 POM 을 병합시킬 수 있다.
하위 POM 을 병합할 parent POM 에서는 <packaging>pom</packaging> section 을 추가한다.
parent POM 에서는 <modules></modules> section 을 추가하여 하위 POM 들을 병합한다.
(자세한 예는 http://maven.apache.org/guides/introduction/introduction-to-the-pom.html 의 project inheritance 참고)



출처: http://lefthand.tistory.com/6 [lefthand's note]

maven 2 기본(3) - archetype
What's archetype ?

archetype 은 비슷한 종류의 프로젝트들이 생성될 때 기반이 되는 프로젝트 템플릿 이다.
(http://maven.apache.org/guides/introduction/introduction-to-archetypes.html)
maven 은 archetype 에 따른 작업을 수행하기 위해 archetype이라는 플러그인을 제공한다.
archetype 플러그인은 다음의 4개의 goal 을 정의한다.

 [goals]
 * archetype:create
  프로젝트 템플릿을 생성한다.
  -DarchetypeArtifactId=[archetypeArtifactId] 을 파라미터로 전달하여 특정 프로젝트 템플릿을 생성하며
  archetypeArtifactId 를 지정하지 않은 경우 기본값은 maven-archetype-quickstart 이다.
  maven 2 에서는 사용이 권장되지 않고 archetype:generate 를 사용한다.
 * archetype:generate
  사용자가 프로젝트 템플릿 종류(아래 archetypeArtifactId 목록 참고)를 선택 후 프로젝트를 생성한다.
  선택된 타입은 remote에서 다운로드 되고, 다운로드 완료되면 local 에 프로젝트를 생성한다.
 * archetype:create-from-project
  기존에 작성된 project 로부터 archetype 을 생성한다.
 * archetype:crawl
  maven 2 repository 를 검색하여 archetype 의 목록파일을 생성/업데이트 한다.

ex)
mvn archetype:generate -DgroupId=com.mycompany.app -DartifactId=my-app
mvn archetype:create -DgroupId=com.mycompany.app -DartifactId=my-app -DarchetypeArtifactId=maven-archetype-webapp


archetypeArtifactId 목록

현재 사용 가능한 archetype 목록이다.
archetype:create 로 생성시에는 maven-archetype-quickstart 가 디폴트로 생성된다.

1: appfuse-basic-jsf
  (AppFuse archetype for creating a web application with Hibernate, Spring and JSF)
2: appfuse-basic-spring
  (AppFuse archetype for creating a web application with Hibernate, Spring and SpringMVC)
3: appfuse-basic-struts
  (AppFuse archetype for creating a web application with Hibernate, Spring and Struts2)
4: appfuse-basic-tapestry
  (AppFuse archetype for creating a web application with Hibernate, Spring and Tapestry 4)
5: appfuse-core
  (AppFuse archetype for creating a jar application with Hibernate and Spring and XFire)
6: appfuse-modular-jsf
  (AppFuse archetype for creating a modular application with Hibernate, Spring and JSF)
7: appfuse-modular-spring
  (AppFuse archetype for creating a modular application with Hibernate, Spring and Spring MVC)
8: appfuse-modular-struts
  (AppFuse archetype for creating a modular application with Hibernate, Spring and Struts 2)
9: appfuse-modular-tapestry
  (AppFuse archetype for creating a modular application with Hibernate, Spring and Tapestry 4)
10: maven-archetype-j2ee-simple
  (A simple J2EE Java application)
11: maven-archetype-marmalade-mojo
  (A Maven plugin development project using marmalade)
12: maven-archetype-mojo
  (A Maven Java plugin development project)
13: maven-archetype-portlet
   (A simple portlet application)
14: maven-archetype-profiles
  ()
15: maven-archetype-quickstart
  ()
16: maven-archetype-site-simple
  (A simple site generation project)
17: maven-archetype-site
  (A more complex site project)
18: maven-archetype-webapp
  (A simple Java web application)
19: struts2-archetype-starter
  (A starter Struts 2 application with Sitemesh, DWR, and Spring)
20: struts2-archetype-blank
  (A minimal Struts 2 application)
21: struts2-archetype-portlet
  (A minimal Struts 2 application that can be deployed as a portlet)
22: struts2-archetype-dbportlet
  (A starter Struts 2 portlet that demonstrates a simple CRUD interface with db backing)
23: struts2-archetype-plugin
  (A Struts 2 plugin)
24: shale-archetype-blank
  (A blank Shale web application with JSF)
25: maven-adf-archetype
  (Archetype to ease the burden of creating a new application based with ADF)
26: data-app
  (A new Databinder application with sources and resources.)
27: jini-service-archetype
  (Archetype for Jini service project creation)
28: softeu-archetype-seam
  (JSF+Facelets+Seam Archetype)
29: softeu-archetype-seam-simple
  (JSF+Facelets+Seam (no persistence) Archetype)
30: softeu-archetype-jsf
  (JSF+Facelets Archetype)
31: jpa-maven-archetype
  (JPA application)
32: spring-osgi-bundle-archetype
  (Spring-OSGi archetype)
33: confluence-plugin-archetype
  (Atlassian Confluence plugin archetype)
34: jira-plugin-archetype
  (Atlassian JIRA plugin archetype)
35: maven-archetype-har
  (Hibernate Archive)
36: maven-archetype-sar
  (JBoss Service Archive)
37: wicket-archetype-quickstart
  (A simple Apache Wicket project)
38: quickstart
  (A simple Apache Tapestry 5 Project)
39: scala-archetype-simple
  (A simple scala project)
40: lift-archetype-blank
  (A blank/empty liftweb project)
41: lift-archetype-basic
  (The basic (liftweb) project)
42: cocoon-22-archetype-block-plain
  ([http://cocoon.apache.org/2.2/maven-plugins/])
43: cocoon-22-archetype-block
  ([http://cocoon.apache.org/2.2/maven-plugins/])
44: cocoon-22-archetype-webapp
  ([http://cocoon.apache.org/2.2/maven-plugins/])

sns신고


출처: http://lefthand.tistory.com/7 [lefthand's note]



The superclass “javax.servlet.http.HttpServlet” was not found on the Java Build Path [duplicate]

The superclass “javax.servlet.http.HttpServlet” was not found on the Java Build Path [duplicate]

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
    <scope>provided</scope>
</dependency>
Gradle

configurations {
    provided
}
sourceSets {
    main { compileClasspath += configurations.provided }
}
dependencies {
    provided 'javax.servlet:javax.servlet-api:3.1.0'
}

archetype:generate

Maven Archetype Plugin の archetype:generate を使用して、プロジェクトを作成する。

mvn archetype:generate -B^
 -DarchetypeGroupId=org.terasoluna.gfw.blank^
 -DarchetypeArtifactId=terasoluna-gfw-multi-web-blank-mybatis3-archetype^
 -DarchetypeVersion=5.3.1.RELEASE^
 -DgroupId=com.example.todo^
 -DartifactId=todo^
 -Dversion=1.0.0-SNAPSHOT

Maven Project groupid, artifactid 네이밍 예제

Maven Project groupid, artifactid 네이밍 예제

출처: http://seotory.tistory.com/32 [seotory]

maven 프로젝트를 시작할때 마다 고민스러운 groupid, artifactid.. 어떻게 정하는 것이 정답일까.

group id
groupid는 프로젝트마다 접근할 수 있는 고유한 이름을 만들도록 한다. 보통은 패키지 네이밍룰(도메인 뒤집기)을 따르는게 정석이다. 이후에 원하는 만큼 하위 그룹을 만들 수있다.
예) org.apache.maven, org.apache.commons

groupid에 프로젝트의 구조를 밝히는 것이 좋다. 만약 현재 프로젝트가 멀티 프로젝트가 되었을 때, 새로운 식별자만 부모의 groupid 뒤에 붙이면 된다.
예) org.apache.maven, org.apache.maven.plugins, org.apache.maven.reporting

artifact id
artifactid 는 jar 파일에서 버젼 정보를 뺀 이름이다. 자유롭게 적되, 소문자를 사용하고 이상한 특수문자를 사용하지 않는다.
예) maven, commons-math

출처: http://seotory.tistory.com/32 [seotory]

아키타입(Archetype)과 키노타입(Kenotype)

아키타입(Archetype)과 키노타입(Kenotype)
아키타입(Archetype)
아키타입이란 집단 무의식에 관한 연구의 대가인 칼 융(Carl Jung)이 인간의 집단 무의속 속에 공통으로 자리잡고 있는 보편적인 이미지의 패턴을 지칭하기 위하여 사용한 단어이다. 칼융은 개인 단위에서 형성되었다가 개인의 소멸로 사라지는 무의식이 아니라 인류의 생성 이후 공통의 유산으로서 집단적으로 형성하고 공유하는 인간의 무의식이 있으며 이 집단적 무의식이 개인의 꿈에서부터 집단의 신화와 전설을 형성한다고 보았다. 예를 들어 "성처녀", "무시당하는 예언자", "철학자의 돌" 등 이 모든 것들은 인류 공통의 과거 체험에서 기인한 집단 무의식 속의 주제들이고 우리는 이러한 주제들을 문화적 창조과정 속에서 반복적으로 표출하게 된다고 한다.
키노타입(Kenotype)
키노타입은 고대 그리스어로 새로움을 의미하는 kainos와 형식(form), 혹은 각인(imprint)을 의미하는 typos를 조합하여 만든 말로써 새로운 형식이라는 의미를 지닌다. 문화학적인 개념상으로는 이는 아키타입(archetype)에 정 반대되는 의미로서 사용된다. 예를들어 소설의 소재로서 지하철, 자전거, 컴퓨터, 텔레비전이 등장하는 것들이 키노타입의 예이다. 아키타입이 인류 탄생 이래의 공통 경험에 기반을 둔 집단 무의식 속의 주제들을 다룬다면 키노타입은 인류가 새롭게 맞닥트리고 있는 새로운 주제들을 다루는 것이다.