ajax로 검색한 결과 :: 시소커뮤니티[SSISO Community]
 
SSISO 카페 SSISO Source SSISO 구직 SSISO 쇼핑몰 SSISO 맛집
추천검색어 : JUnit   Log4j   ajax   spring   struts   struts-config.xml   Synchronized   책정보   Ajax 마스터하기   우측부분

회원가입 I 비밀번호 찾기


SSISO Community검색
SSISO Community메뉴
[카페목록보기]
[블로그등록하기]  
[블로그리스트]  
SSISO Community카페
블로그 카테고리
정치 경제
문화 칼럼
비디오게임 스포츠
핫이슈 TV
포토 온라인게임
PC게임 에뮬게임
라이프 사람들
유머 만화애니
방송 1
1 1
1 1
1 1
1 1
1

ajax로 검색한 결과
등록일:2008-04-02 15:08:31
작성자:
제목:Cypal Studio for GWT를 사용하여 Ajax 개발 단순화 하기 (한글)


난이도 : 중급

Noel Rappin, Senior Software Engineer, Motorola, Inc.

2007 년 8 월 28 일

Google Web Toolkit (GWT)를 사용하여 자바 개발자들은 자바™ 프로그래밍 언어로 풍부한 Asynchronous JavaScript + XML (ajax) 애플리케이션을 작성할 수 있습니다. Eclipse IDE용으로 설계된 Cypal Studio for GWT는 GWT 구현 관리를 지원합니다. Cypal Studio for GWT에서는 새로운 모듈을 쉽게 생성할 수 있으며, 원격 프로시저 호출도 지원하고, 웹 애플리케이션을 쉽게 전개할 수 있도록 해줍니다.

Cypal Studio와 GWT

소셜 북마크

mar.gar.in mar.gar.in
digg Digg
del.icio.us del.icio.us
Slashdot Slashdot

GWT 는 JavaScript 없이 자바 프로그래밍 언어 내에서 동적인 웹 애플리케이션들을 완벽히 작성할 수 있도록 해주는 툴 세트이다. GWT 애플리케이션은 모든 주요 브라우저에서 실행되며, 사용자와의 상호 작동성도 뛰어나고, 자바 개발 환경 내에서 완벽히 테스트 및 디버깅 될 수 있다.

GWT 프레임웍은 네 개의 주요 컴포넌트를 갖고 있다. 자바 언어로 구현된 위젯 컬렉션은 Swing 보다 단순한 애플리케이션 프로그램 인터페이스(API)에서 기대하는 표준 사용자 인터페이스(UI) 기능을 제공한다. 원격 프로시저 메커니즘은 클라이언트와 서버 간 통신에 사용되며, GWT에서는 모든 파이프와 데이터 변환이 처리된다. 완전히 통합된 브라우저 시뮬레이터로 GWT가 개발 시 실행될 수 있으며, GWT 디버깅 세션 동안 에디터에서 중단점을 설정할 수 있다. 마지막으로, 컴파일러는 자바 코드를 클라이언트 브라우저에서 실제로 실행되는 크로스 브라우저 JavaScript 코드로 변환하며 브라우저 비호환성을 관리하기 때문에 여러분이 관리할 필요가 없다.

GWT가 ajax 애플리케이션을 생성하는 프로세스를 단순화 하는 동안, 동기화 된 여러 부분들이 작동하도록 해야 한다. 이 글을 쓰고 있는 현재, GWT 고급 툴 지원은 주요 자바 개발 환경에 나타나기 시작했다.

Cypal Studio for GWT는 GWT 개발 시 수행되는 공통의 태스크들을 단순화 하는 Eclipse용 플러그인이다. 이 글에서는 GWT의 모든 부분을 설명하지 않는다. 참고자료 섹션에서 GWT 작동 방법과 애플리케이션을 생성하는 방법을 참조하기 바란다.

Eclipse Web Tools Platform 내에서 Cypal Studio 설치하기

Cypal Studio for GWT에서 작업하기 전에, 다운로드 해야 한다. (참고자료) 지금 현재 최신 GWT 버전은 1.3이고, Microsoft® Windows®, Mac OS X, Linux®에서 사용할 수 있다. Cypal은 GWT V1.4를 지원하지 않을 수도 있다. 여러분의 OS에 맞는 파일을 다운로드 하여 올바른 위치에 폴더를 저장한다.

Web Tools Platform (WTP) 플러그인이 있는 Eclipse 버전이 필요하다. WTP는 웹 애플리케이션 개발을 지원하는 옴니버스 컬렉션 툴이다. HTML과 Cascading Style Sheets (CSS) 같은 웹 표준용 에디터 지원, JavaServer Pages (JSP) 에디터 지원, 웹 애플리케이션에서 사용하는 데이터베이스 생성 및 관리 지원, 개발 시 웹 서버에 애플리케이션 실행하기 등이 포함된다.

이러한 기능들은 모두 매우 훌륭하지만, 이 글에서는 설명하지 않겠다. Cypal Studio for GWT가 필요로 하는 WTP에만 초점을 맞추겠다. WTP에 대한 상세한 정보는 참고자료를 참조하라.

WTP 를 실행할 Eclipse 시스템을 구하는 가장 쉬운 방법은 다운로드이다. Eclipse를 처음 다운로드 하는 것이라면 특별히 권장된다. WTP 다운로드 페이지는 모든 WTP 플러그인에 대한 올인원 다운로드뿐만 아니라 필수 플러그인도 제공한다. 이 페이지에는 약간 복잡한 부분도 있다. Web Tools Platform; All-in-one 부분을 찾으면 된다. 이 글을 쓰고 있는 현재, 최신 WTP 버전은 1.5.4이다. Windows, Linux, Mac OS X용 버전들이 있다. 여러분 플랫폼에 맞는 것을 다운로드 하라.

한 번에 모든 것을 다운로드 하는 것이 부담스럽거나, 이미 Eclipse가 있어서 전체를 다시 다운로드 하고 싶지 않다면, WTP를 플러그인으로서 다운로드 할 수 있다. 다운로드 페이지에는 일부 필수 플러그인이 나열되어 있다. 이를 다운로드 하여 Eclipse의 플러그인 디렉토리에 저장한다. 그리고 나서, wtp-R-1.5.4.zip 같은 파일 명으로 Web Tools Platform (WTP, JST, and WST combined)을 다운로드 한다. 파일을 플러그인 디렉토리에 추출한다.

이 모든 것을 다 수행한 후에 최신 버전의 Cypal Studio for GWT를 얻을 준비가 된 것이다. 최신 버전의 이름은 cypal.studio.for.gwt-beta.zip 이다. 이 파일을 Eclipse 디렉토리에 추출하면 기능과 features and plugins 디렉토리에 파일이 저장된다.

주: 구 버전의 Googlipse 플러그인을 설치했다면 Cypal Studio for GWT용 플러그인을 제거한다.

모든 것이 다운로드 되었기 때문에 시작하기 전에 설정해야 하는 한 가지 설정 옵션이 있다. Eclipse를 실행하고 Preferences 윈도우에 액세스 한다. (그림 1) Cypal Studio의 왼쪽 편에 엔트리가 생긴다. 이전에 생성했던 GWT의 상단 디렉토리에 GWT Home을 설정한다.


그림 1. Cypal Studio Preferences 윈도우
Cypal Studio Preferences 윈도우

이제 필요한 모든 것을 설치했다.




위로


Cypal Studio 프로젝트 생성하기

Cypal Studio for GWT를 사용하려면, 새로운 Dynamic Web Project를 생성하거나 Cypal Studio를 기존 프로젝트에 추가해야 한다. 새로운 프로젝트를 시작하려면, File > New를 선택한다. Dynamic Web Project Wizard를 선택하는데, 이는 Web 헤딩 밑에서 찾을 수 있다. 다음과 같은 윈도우를 보게 된다.


그림 2. 새로운 Dynamic Web Project 윈도우
새로운 Dynamic Web Project 윈도우

프로젝트 생성하기:

  1. Project name 박스에 이름을 입력한다.
  2. Configurations 리스트에서, Default Googlipse Project를 선택한 다음 Next를 클릭한다. (Googlipse) 이 프로젝트에 실행되는 Project Facets 리스트를 보게 된다. Dynamic Web Module, Googlipse, Java로 구성된 기본 리스트면 충분하다.
  3. Next를 클릭한다. Cypal Studio가 생성할 디렉토리들의 이름을 설정할 기회가 생긴다. 이 글에서는 기본 이름을 사용하겠지만, 변경해도 무방하다.
  4. Finish를 클릭한다.

Cypal Studio for GWT는 파일들을 만들기 시작하고, 한 개 이상의 문서 유형 정의(DTD)에 대한 라이센스 동의를 요하는 프롬프트가 뜬다. 모든 것이 수행된 후, Eclipse Project Explorer는 그림 3과 같이 된다.


그림 3. Cypal Studio Project Explorer
Cypal Studio Project Explorer

Deployment Descriptor는 WTP이고, 이 부분에서 많은 시간을 보내지 않을 것이다. Cypal Studio for GWT는 소스 코드용 디렉토리, 컴파일 된 자바 코드용 디렉토리, WebContent용 디렉토리를 생성했는데, 이는 web.xml 파일로 구성되어 있다.

이 지점에서, 새로운 Cypal Studio 프로젝트를 만들었다. Cypal Studio 지원을 기존 Eclipse Dynamic Web Project에 추가하고 싶다면 Project Explorer에서 프로젝트를 오른쪽 클릭하고 Properties를 클릭한다. 여기서부터, Project Facets > Add/Remove Project Facets를 선택한다. 리스트에서 Cypal's GWT Facet를 클릭한다.




위로


첫 번째 프로젝트 모듈 추가하기

프로젝트 골격이 생겼지만, 실제 코드는 없다. 이를 수정해 보자. GWT 코드의 기본 단위는 모듈(module)이다. 이 모듈은 클라이언트 브라우저에서 페이지 사용자 호출에 상응한다. 모듈은 한 개 이상의 Entry Point 클래스들로 구성되는데, 이는 모듈이 로딩될 때 로딩된다. 게다가, 모듈의 소스 코드, 퍼블릭 웹 파일, 필수 JavaScript 또는 CSS 파일에 비표준 위치를 지정할 수 있다.

Cypal Studio for GWT에 모듈을 생성하려면 File > New를 선택한다. Cypal Studio 툴박스 아이콘이 있는 모듈용 리스팅이 있다면 이를 선택한다. 그렇지 않다면, 나타나는 윈도우에서 Other > Cypal Studio > Module을 선택한다. 마지막으로, 아래 보이는 윈도우가 생긴다.


그림 4. 새로운 GWT Module 윈도우
새로운 GWT Module 윈도우

Source 폴더는 기존 프로젝트의 소스 폴더이다. Package 폴더는 여러분이 설정해야 한다. 일반적으로 Your Top Level Package.Name of Module이다. 또한 모듈의 이름, Superclass, 인터페이스 기본을 설정해야 한다.

Finish를 클릭한 후에, Cypal Studio는 다음의 엘리먼트를 만든다. (전에 GWT를 사용해 본 사람들은 이것이 GWT의 명령행 툴에서 얻을 수 있는 것이고, 사용하기 쉬운 그래픽 사용자 인터페이스[GUI]를 갖고 있다는 것도 알 수 있다.)

  • 세 개의 패키지(client, server,, public)가 지정된 소스 디렉토리 밑에 있다.
  • 클라이언트 패키지에 있는 파일( FirstModule.java)은 모듈의 초기 엔트리 포인트가 될 것이다.
  • FirstModule.html 파일은 실제로 렌더링 될 HTML용 퍼블릭 패키지에 있다.



위로


코드 생성 및 실행하기

초기에는, 자바와 HTML 파일에는 컴파일에 필요한 최소한의 스톱 코드가 포함된다. 하지만, 여기에 몇 가지를 추가할 수 있다. Listing 1에 보이는 코드를 HTML 파일의 바디 섹션에 삽입한다.


Listing 1. 코드 생성 및 실행
                
<table align=center>
<tr>
<td id="button"></td>
<td id="count"></td>
</tr>
</table>

그리고 나서, Listing 2의 자바 코드를 자바 파일에 둔다. Eclipse가 반입된 클래스용 import 문을 생성하도록 해야 한다.


Listing 2. 자바 코드를 자바 파일에 추가하기
                
int count = 0;

public void onModuleLoad() {
final Button button = new Button("Count Your Clicks!");
final Label label = new Label(String.valueOf(count));
button.addClickListener(new ClickListener() {
public void onClick(Widget sender) {
count += 1;
label.setText(String.valueOf(count));
}
});
RootPanel.get("button").add(button);
RootPanel.get("count").add(label);
}

이 코드는 onModuleLoad() 메소드에 있기 때문에 모듈이 로딩되면 자동으로 실행된다. GWT 위젯 세트의 상세로 깊이 들어가지 않고도, 이 코드는 버튼과 레이블을 생성한다. 이것은 리스너를 버튼에 추가한 다음, 이 두 가지 모두를 HTML 엘리먼트에 둔다. 이것의 문서 객체 모델(DOM) ID는 RootPanel.get()으로 전달된 스트링과 매치된다.

시스템을 실행하려면 Run을 클릭한다. Run 윈도우에서, Gwt Hosted Mode Application > New_configuration을 선택한다. 아래 창이 나타난다. (GWT Hosted Mode Application을 오른쪽 클릭한 다음, New를 클릭하여 새로운 설정을 본다.)


그림 5. 실행 설정
실행 설정

어떤 프로젝트와 프로젝트의 모듈을 지정해야 한다. 다행히도 Eclipse에서는 기존 프로젝트 공간을 검색할 수 있다. Apply를 클릭하여 새로운 설정을 저장한 다음, Run을 클릭하여 이를 실행한다. 이렇게 함으로써, 프로젝트용 GWT 호스팅 모드를 호출할 수 있다. (이를 한 번에 수행한 후에, Run을 클릭하면 다른 Eclipse 실행 타겟처럼 작동한다.) Cypal Studio 없이 Eclipse에서 타겟을 설정하는데 지쳤다면 Cypal Studio는 7 단계나 더 간단하다.

실행할 때 페이지 모습은 그림 6과 같다.


그림 6. 최초의 Cypal Studio 모듈
최초의 Cypal Studio 모듈




위로


원격 서비스로 연결하기

원격 서버와의 통신은 모든 웹 애플리케이션의 핵심이고, GWT는 클라이언트 측 GWT 코드가 자바 원격 서버와 통신할 수 있는 프레임웍을 제공한다. 이 메커니즘("Google Web Toolkit, Apache Derby, Eclipse를 사용하여 ajax 애플리케이션 구현하기, Part 3" 참조)은 Enterprise JavaBean (EJB)와 다중 클래스와 인터페이스의 합병이다. 연결을 구축하기가 쉽지만 주시해야 할 많은 부분들이 있다.

Cypal Studio for GWT는 원격 연결을 생성 및 관리할 수 있도록 하는 두 가지 편리한 기능을 갖고 있다. New > Remote Service를 선택하는 것으로 프로세스를 시작한다. (Remote Service가 메뉴에 없다면 Other > Cypal Studio를 선택한다.) 아래와 같은 윈도우를 보게 된다.


그림 7. GWT Remote Service
GWT Remote Service

Name을 채워야 하는데, 이것은 자바 측 클래스의 실제 이름이고, 클라이언트가 실제로 호출하는 서버 측 URL이다. Finish를 클릭하면 Cypal Studio가 작동한다.

Cypal Studio는 세 개의 파일을 만든다. 클라이언트 패키지에서, NumberGenerator.java를 만드는데, 이것은 원격 연결용 메인 인터페이스이다. (Listing 3)


Listing 3. NumberGenerator.java
                
public interface NumberGenerator extends RemoteService {

public static final String SERVICE_URI = "/numbergenerator";

public static class Util {

public static NumberGeneratorAsync getInstance() {

NumberGeneratorAsync instance = (NumberGeneratorAsync) GWT
.create(NumberGenerator.class);
ServiceDefTarget target = (ServiceDefTarget) instance;
target.setServiceEntryPoint(GWT.getModuleBaseURL() + SERVICE_URI);
return instance;
}
}

}

이 파일은 지금 비어있는 인터페이스이지만, Cypal Studio는 원격 호출에 알맞은 완전한 GWT 인증의 인스턴스를 리턴하는 유틸리티 객체를 만들었다. "Google Web Toolkit, Apache Derby, Eclipse를 사용하여 ajax 애플리케이션 구현하기, Part 3" 에는 코드와 보일러플레이트 코드용 공통 메소드를 만드는 방법이 설명되어 있다.

이 유틸리티의 리턴 값은 실제로 NumberGeneratorAsync 유형인데, 이는 비동기식의 메인 인터페이스로 볼 수 있다. 메인 인터페이스의 모든 메소드는 비동기식 인터페이스에 매칭 엔트리를 갖고 있지만, void의 리턴 유형과 AsyncCallback 클래스의 추가 인자를 갖고 있다. 이 코드를 클라이언트 페이지에서 호출하면, 실제로 비동기식 인터페이스를 사용한 것이고, GWT는 이를 메인 인터페이스로 변환하는데, 이것은 서버 측에서 보이는 부분이다. 그리고 나서, AsyncCallback 객체를 사용하여 서버 응답과 관련된 것을 수행한다.

서버 측에서, Cypal Studio는 구현 클래스 NumberGeneratorImpl을 생성했는데, 이는 GWT 클래스 RemoteServiceServlet을 확장하고 NumberGenerator 인터페이스를 구현한다. 게다가, GWT는 web.xml 파일을 수정하여 전개된 애플리케이션에 사용할 새로운 원격 서버를 등록했다. 새로운 라인은 Listing 4와 같다.


Listing 4. NumberGenerator.java용 추가 라인
                
<servlet>
<servlet-name>NumberGenerator</servlet-name>
<servlet-class>
com.ibm.firstmodule.server.NumberGeneratorImpl</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>NumberGenerator</servlet-name>
<url-pattern>numbergenerator</url-pattern>
</servlet-mapping>

원격 호출을 생성하려면, 메소드 시그니처를 NumberGenerator에 추가한다. 여러분이 구현 할 메소드는 "I'm thinking of a number" 게임을 수행한다. 메소드 시그니처는 다음과 같다.

 public Integer getNumber(int maxNumber); 

NumberGenerator 인터페이스에 시그니처를 저장하면 재미있는 일이 발생한다. Cypal Studio는 매칭 메소드를 NumberGeneratorAsync에 추가했다.

 public void getNumber(int maxNumber, AsyncCallback callback); 

이러한 두 개의 인터페이스들을 직접 동기화 화는 것은 부담스러운 일이기 때문에 이는 매우 편리하다. 이제, NumberGeneratorImpl 클래스로 가야 한다. Eclipse는 이 클래스에 빨간색으로 플래그를 단다. NumberGenerator 인터페이스는 더 이상 완전히 구현되지 않기 때문이다. 다행히도, 다음 코드를 추가하여 정정한다.

public Integer getNumber(int maxNumber) {
return new Integer((new Random()).nextInt());
}

호출을 하기 위해 모듈에 이를 추가했다. (Listing 5) 이것을 작동시키기 위해, 또 다른 행을 두 개의 셀을 가진 HTML 바디에 추가했고, 첫 번째 셀에는 ID sender가 있고, 두 번째 셀에는 ID response가 있다. 이 모듈은 서버에서 무작위 숫자를 검색하고 이를 클릭 수와 비교하는 버튼을 갖고 있다.


Listing 5. 호출이 추가된 모듈
                
public class FirstModule implements EntryPoint {

int count = 0;

private Button button;
private Button sender;
private Label label;
private Label response;

public void onModuleLoad() {
button = new Button("Count Your Clicks!");
sender = new Button("Send Your Count!");
label = new Label(String.valueOf(count));
response = new Label("No Guess Yet");
button.addClickListener(new CountButtonClickListener());
sender.addClickListener(new SendClickListener());
RootPanel.get("button").add(button);
RootPanel.get("count").add(label);
RootPanel.get("sender").add(sender);
RootPanel.get("response").add(response);
}

public class CountButtonClickListener implements ClickListener {

public void onClick(Widget sender) {
count += 1;
label.setText(String.valueOf(count));
}
}

public class SendClickListener implements ClickListener {

public void onClick(Widget sender) {
NumberGeneratorAsync async =
NumberGenerator.Util.getInstance();
async.getNumber(10, new NumberCallback());
}

}

public class NumberCallback implements AsyncCallback {

public void onFailure(Throwable error) {
response.setText("Oops");
}

public void onSuccess(Object resp) {
int intResp = ((Integer) resp).intValue();
if (intResp == count) {
response.setText("Got It!");
} else if (intResp < count) {
response.setText("Too Low");
} else if (intResp > count) {
response.setText("Too High");
}
}

}

}

이 코드의 핵심 부분은 SendClickListenerNumberCallback이다. SendClickListener에서, Cypal Studio에서 생성된 Util 클래스를 사용하여 async 인터페이스를 얻고 그 인터페이스에서 getNumber() 메소드를 호출한다.

두 번째 인자는 서버가 응답을 완료하면 GWT가 자동으로 호출하는 NumberCallback의 인스턴스이다. 이 콜백은 두 개의 브랜치, onFailure()onSuccess()를 갖고 있다. 이는 서버가 예외 없이 요청을 완료했는지 여부에 의존한다. 이 경우, 서버가 성공하면, 결과를 카운트와 비교하고 레이블들 중 하나에 텍스트를 설정한다. (이를 디자인 하여, 호출이 현재 카운트 값을 서버로 보내고 비교가 서버 측에서 수행되도록 할 수 있다. 이는 복잡성을 어디에 두는가에 대한 문제이다.)

코드가 다 갖춰지면, GWT 호스트 모드를 시작하고 모든 것이 실행을 시작할 것이다.




위로


GWT 애플리케이션 전개하기

Cypal Studio가 아직 완전히 성숙하지 못한 한 부분은 외부 서버에서 웹 애플리케이션을 사용할 때이다. Eclipse 내/외부에서 사용할 수는 있지만, 프로세스는 필요한 절차보다 한 단계에서 두 단계 정도 길다.

Eclipse 내에서 웹 애플리케이션을 실행하려면, Eclipse WTP에서 승인한 서블릿 엔진이 필요하다. Apache Tomcat이면 충분하다. 그런 다음 GWT 애플리케이션을 컴파일 한다. 가장 쉬운 컴파일 방법은 호스트 모드에서 애플리케이션을 실행한 다음 Compile/Browse를 클릭하는 것이다. 이렇게 하면 모든 GWT 코드를 JavaScript 파일로 컴파일 하고 머신에서 외부 브라우저를 연다.

그런 다음, Project Explorer에서 프로젝트 이름을 오른쪽 클릭하여 외부 서버에서 프로세스를 실행한다. Run As > Run On Server를 선택한다. 새로운 서버를 정의하는 윈도우가 나타난다. 호스트 이름을 localhost로 유지한다. 여러분이 사용하기로 한 서버 유형을 선택한다. 그 유형의 서버를 이전에 설정하지 않았다면, 서버의 런타임 디렉토리가 프롬프트 된다.

런 타임 디렉토리를 설정한 후에, Eclipse는 워크스페이스에 HTML 페이지를 연다. Eclipse가 시스템의 루트 디렉토리를 히트한다고 해서 놀라지 말라. 이는 index.html 파일 같은 것을 지정하지 않았기 때문에 이 경우에 생기는 에러이다. 브라우저를 여러분이 생성한 HTML을 가리키게 하면(이 경우, http://localhost:8080/GooglipseProject/FirstModule.html) 그림 8이 나타난다.


그림 8. 외부 서버상의 프로젝트
외부 서버상의 프로젝트

GWT 프로젝트를 외부 브라우저에 전개하려면, Project Explorer에 프로젝트를 오른쪽 클릭하고 Export > WAR를 선택한다. Web Archive (WAR) 파일을 둘 곳이 프롬프트 된다. (위에 설명한 대로 GWT 코드를 컴파일 해야 한다.) 여러분이 선택한 서버의 적절한 위치에 WAR 파일을 둔다.




위로


GWT와 Cypal Studio의 미래

이 글을 쓰고 있는 현재, 완전한 오픈 소스 GWT 1.3 릴리스 소식이 있었다. V1.4 릴리스에는 더욱 풍부한 텍스트 위젯, 스플리터, 데이터, 넘버 포맷이 추가될 예정이고, 개발 툴과 성능 면에서도 향상될 것이다. Cypal Studio는 여전히 활발히 개발 중이다. Cypal Studio for GWT 웹 사이트를 방문해 보기 바란다.



참고자료

교육

제품 및 기술 얻기

토론


필자소개


Noel Rappin 박사(Graphics, Visualization, and Usability Center-Georgia Institute of Technology)는 Motorola의 소프트웨어 엔지니어이다. wxPython in Action과 Jython Essentials의 (공동) 저자이기도 하다. (10printhello.blogspot.com)