달력

52024  이전 다음

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
Posted by tornado
|

 



♬ 개울가에 올챙이 한마리

꼬물꼬물 헤엄치다

뒷다리가 쑥~ 앞다리가 쑥~

팔딱팔딱 개구리됐네

꼬물꼬물 꼬물꼬물

꼬물꼬물 올챙이가

뒷다리가 쑥~ 앞다리가 쑥~

팔딱팔딱 개구리 됐네~  ♬

Posted by tornado
|

'이것저것 > 낙서장' 카테고리의 다른 글

[펌] 성진님의 글.........클릭  (0) 2004.05.04
[펌] ♬ 올챙이Ssong ♬  (0) 2004.05.04
[펌] 빈센트 반고호 그림 감상하기......  (0) 2004.04.27
[펌] CF 패러디~ ^^  (0) 2004.04.21
[펌] 자전거 VS 오토바이  (0) 2004.04.14
Posted by tornado
|
 

                      모처럼 좋은 그림 감상하닌깐 ..좋네여 ^^

 

'이것저것 > 낙서장' 카테고리의 다른 글

[펌] ♬ 올챙이Ssong ♬  (0) 2004.05.04
[펌] 추억의 만화 주제가 모음....  (0) 2004.05.04
[펌] CF 패러디~ ^^  (0) 2004.04.21
[펌] 자전거 VS 오토바이  (0) 2004.04.14
[펌] [유머] 영어 잘못 읽으면?  (0) 2004.04.08
Posted by tornado
|


 

 

저 원래 잘 안 웃거든요.

이거 보고 웃었어요. ㅋㅋ~

 

강남스타일 까페에는 더 많은 유머가 있어요. ^^

Posted by tornado
|

Commons BeanUtil 에는 참 유용한게 많다..

 

그중 RowSet 과 비스무리(?) 한 것이 하나 있는데..

 

바로 RowSetDynaClass 이다...

 

 

일반적 JDBC 프로그래밍에서는 아래와 같은 순서를 가진다.

 

pstmt = t.prepareStatemet(query);

pstmt.setXXX(....);

rs = pstmt.executeQuery();

 

while(rs.next()){

 ... 작업들.....

}

 

rs.close();

 

이런 구조를 가지고 가게 되며, 커넥션이 닫히기 전에 resultSet 을 순차적으로 내려가면서 작업을 한다.

 

Commons BeanUtils 안에는 RowSetDynaClass 라는 클래스가 있다.

이 클래스는 JDBC 연결이 끊어진 이후에도 사용가능한 CachedRowSet 과 비슷한 기능을 제공해준다.

 

이것의 사용법은 상당히 간단하다. 참조 코드는 다음과 같다.

 

   pstmt = t.prepareStatement(query);
   rs = pstmt.executeQuery();
   rsdc = new RowSetDynaClass(rs);
   
   rs.close();

....

 

finally{   ... conn.close(); }

 

요기까지가 끝이다.. 이후에는 rsdc 라는 녀석을 이용해서 데이터를 취득하면 된다.

이렇게 데이터를 가져오게 되면

rsdc 에서는 getRows() 메소드를 이용하여 List 객체를 취득할 수 있다.

 

List arr = rsdc.getRows();

 

또한 검색해 온 컬럼의 이름들을 Property 로 얻을 수도 있다.

 

 DynaProperty[] dynas = rsdc.getDynaProperties();
  
 for(int i = 0; i < dynas.length; i++){
  System.out.println(dynas[i].getName());
 }

 

DynaProperty 클래스는 일반적인 Property 개념으로 보면 된다.

 

또한 이렇게 얻어온 DynaProperty 배열객체를 이용하여 RowSetDynaClass 를 순환하며 내용을 참조할 수 있다.

 

List 형태로 반납된 rows 들을 순환하게 되면 DynaBean 이라는 객체를 반납하게 된다.

이 형태를 이용하여 rs.next() 작업과 동일한 결과를 얻을 수 있다.

 

 Iterator iter = arr.iterator();
 
 while(iter.hasNext()){
  DynaBean bean = (DynaBean)iter.next();
  
  for(int i = 0; i < dynas.length; i++){
   System.out.println(bean.get(dynas[i].getName()));
  } 
 }

 

 

사용하다 주의할 것은 테이블 컬럼명이 regiDate 와 같이 중간에 대문자가 끼어있을 경우이다

이렇게 중간에 대문자가 끼어있는 것들은 RowSetDynaClass 를 생성하는 과정에서

전부 소문자로 바뀌게 된다.

SQL 상에서는 대소문자를 가리지 않지만 객체에서 값을 얻어올때는 가린다는것에 주의!!!

 

그렇기 때문에 bean.get("regidate") 와 같이 프라퍼티를 전부 소문자로 적어야

제대로 출력될 것이다.

 

 

DAO Layer 측에서 해야할 일들이 DAO를 이용하는 Layer 에 종속적인 작업이 진행될 경우

RowSetDynaClass 를 이용하여 Action 측에서 사용하면 각 레이어의 할일이 조금더 분명해 질수 있다.

 

 

 

 

 

 

 

 

 

 

Posted by tornado
|

Apache 와 톰캣을 연동 했을경우에 골때리는 문제가 하나 생긴다.

 

아파치에서는 Domain 별 디렉토리를 가상호스트로 지정하여 사용하여야 하는데 주소는 다음과 같다.

 

http://aaa.com

 

이 주소에 대하여 DocumentRoot 를 지정할 경우 아래와 같이 특정 디렉토리를 명시하게 된다.

DocumentRoot /usr/local/tomcat4/webapps/ROOT

 

만약 가상호스트로 설정되어있다면

<VirtualHost ....>

   DocumentRoot /usr/local/.......

   .....

</VirtualHost>

 

 

 

또한 aaa.com/test/images 라고 요청 할 경우 디렉토리는 당연히

/usr/local/tomcat4/webapps/ROOT/test/images 와 같은 형태로 요청하게 된다.

 

문제는 test 라는 디렉토리가 하나의 컨텍스트 였을 경우 발생하게 된다.

 

톰캣에서 하나의 웹 애플리케이션의 구성은 webapps/ 를 기준으로 /ROOT  , /examples 등이 있게 된다.

 

이것은 하나의 가상호스트처럼 동작하게 되지만 Apache 에서 볼때는 하나의 디렉토리로 인식하게 되는 것 같다.

 

즉 이 얘기는 http://aaa.com:8080/test 라고 요청할 경우 test 라는 하나의 컨텍스트로 인식하여

 

test 웹 애플리케이션을 호출해 주겠지만 아파치와 연동 되었을 경우에는

 

/test 를 단지 ROOT 애플리케이션의 서브디렉토리로 인식하게 된다는 것이다.

 

아파치에서 톰캣으로 요청을 넘길때 /test/*.jsp  ... /test/*.do 와 같이 넘기게 되면

톰캣에서는 test 라는 하나의 컨텍스트 차원에서 처리를 하지만 아파치에서는 .jsp 와 .do 를 제외한 모든 자원을 test 라는 디렉토리로 보고 처리를 한다는 것이다.

 

이때는 이 컨텍스트를 하나의 도메인으로 빼는게 맞는것 같고...

 

네임서버에서 test.aaa.com 과 같은 형태로 주던지... bbb.com 이라는 완전한 도메인을 빼던지

해주고... Apache 에서 DocumentRoot 를 따로 지정해 주는게 바른 방향 같다.

 

글쓰다가 회의해서리.. 뭔소린지.. 꼬이네.. 캬캬캬

 

 

 

Posted by tornado
|
 

Strategic Planning, SPA-19-5971 Research Note

 

Y. Natis, R. Schulte 14 April 2003

 

서비스 지향 아키텍처 소개

 

웹 서비스의 모멘텀에 이끌려 서비스 지향 아키텍처는 첨단 소프트웨어 프로젝트에서 주류로 위상을 옮기게 될 것이다. 하지만 대부분의 기업들이 SOA의 이점에 대해 혼란을 느끼고 있고 리스크는 제대로 이해하지 못하고 있다.

서비스 지향 아키텍처(SOA)는 클라이언트/서버 소프트웨어 설계 방식으로서 이 설계 방식에서 애플리케이션은 소프트웨어 서비스와 소프트웨어 서비스 소비자(또는 클라이언트나 서비스 요청자)로 구성된다. 소프트웨어 구성 요소들간의 느슨한 결합을 중시하고 별도의 독립적 인터페이스를 사용한다는 면에서 SOA는 비교적 보편화된 클라이언트/서버 모델과는 차이가 있다.

 

SOA 원리는 애플리케이션 설계, 개발 및 배치 중에 반영된다. 이들은 봉입과 유연한 결합이라는 필수 원칙은 공유하지만 자세히 보면 차이가 있다. SOA의 근본 의도는 새로운 실시간 상황에서 소프트웨어 구성 요소(서비스)를 독립적으로 재활용하는 것이다. SOA의 설계와 개발은 이러한 기민한 실시간 환경의 확보를 목적으로 수행된다.

 

서비스 인터페이스는 SOA 설계의 정수


설계에서 서비스는 서로 구분되어 정의된 한 쌍의 요소들(서비스 인터페이스와 서비스 구축)로 표현되는 포장된 비즈니스 소프트웨어 구성 요소들이다. 인터페이스는 서비스에서 근본적이고 일정한 구성 요소이다. 서비스는 항상 다른 소프트웨어 구성 요소(서비스 소비자)로부터의 프로그램 액세스를 위해 존재한다. 서비스 인터페이스는 서비스에 대한 프로그램 액세스 "계약"을 정의한다.
서비스 구현은 서비스의 비즈니스 기능을 충족시킨다. 설계 작업의 구체화 수준에 따라 서비스 구현은 개발 도중에 시험해 보아야 할 "블랙 박스"로 남을 수 있다. 그 밖의 경우에는 새로운 모듈로서 이전 SOA 모듈에 대한 숨겨진 액세스 또는 새롭고 선행하는 소프트웨어 모듈에 대한 복수의 조건부 호출의 합성물이 될 것이다

서비스 구현의 설계는 SOA의 설계에서 부차적인 문제이지만 서비스 인터페이스의 설계는 중요하다. SOA는 근본적으로 서비스 인터페이스의 흐름 및 관계이다. SOA의 설계에는 서비스 인터페이스간, 그리고 서비스 인터페이스와 서비스 소비자 사이의 인터랙션과 서비스 인터페이스에 대한 정의가 관련된다.

 

블랙 박스적 속성은 서비스에 필수적이다.


서비스 인터페이스는 서비스의 정체성과 서비스 호출의 규칙을 수립하는 계약이다. 서비스 인터페이스는 내부 디자인 및 컨텐츠를 고려하지 않고 서비스를 규명(찾고 이해함)하고 사용할 수 있기에 충분한 수준의 정보를 갖고 있어야 한다. 블랙 박스적 성격은 서비스에 필수적이다. 이는 모든 입력 데이터, 모든 응답 데이터(응답 데이터가 있는 경우), 그리고 발생된 모든 예외적 조건들이 인터페이스에 기록되어야 함을 의미한다. 또한 서비스의 목적과 함수를 파악하기 위해 인터페이스에 충분한 메타 데이터가 제공되어야 함을 의미한다. 서비스의 이름에 의존하는 것은 수용할 수는 있지만 약한 형태의 아이덴티티이다. 서비스의 기능을 정의하는 검색할 수 있는 저장소는 보다 세밀한 밀도로 수많은 서비스를 지원할 수 있고 많은 수의 독립적 소스로부터 올 수 있다.
느슨한 결합은 SOA를 기본적인 소프트웨어 모듈와와 차별화시킨다.
SOA는 느슨하게 결합된 형태의 서비스와 서비스 소비자 배치이다. 설계에서 느슨한 결합이란 서비스를 특정 서비스 소비자에게 유사하게 설계하지 않는다는 것을 의미합니다. 서비스 내부에서는 서비스 소비자의 목적, 기술 특성 또는 비즈니스 성격과 관련한 어떤 정보도 전제되지 않는다. 따라서 서비스는 서비스 소비자와 완전히 분리된다.
하지만 서비스 소비자는 서비스에 종속되어 있다(다시 말해 서비스 인터페이스에 대해 엄밀한 의미에서의 참조가 내장되어 있다). 따라서 SOA는 어느 정도는 결합된, 즉 느슨하게 결합된 아키텍처이다. SOA는 모든 참여 소프트웨어 구성 요소들이 다른 구성 요소들과 분리되어 있다는 면에서 사건 기반(event-driven) 아키텍처와 다르며, 모든 소프트웨어 구성 요소가 최초 의도했던 맥락에서만 작동하도록 설계된다는 면에서(다시 말해 논리적으로 타이트하게 결합된) 단일형 아키텍처(monolithic architecture)와 차이가 있다.
설계 당시의 느슨한 결합은 서비스 인터페이스를 비 침해적 재사용을 가능케 하기 때문에 SOA에 필수적이다. 하지만 툴들로는 설계 과정에서의 느슨한 결합을 보장할 수 없다. 논리적으로 서비스 소비자에게 묶이도록 잘못 설계된 서비스는 SOA 스타일의 기술을 사용하고서도 애플리케이션을 단일형 아키텍처로 만들 수 있다.

 

서비스의 최적 입도는 사용, 툴 및 기술에 좌우된다.


서비스 인터페이스는 여러 개의 엔트리 포인트(메소드) 또는 한 개의 엔트리 포인트를 나타내도록 디자인된다. 고객 관리는 여러 개의 메소드를 노출시키는 서비스의 예가 될 수 있다(예를 들어 고객을 만들고 삭제하거나 고객 정보를 수집). "고객 정보 수집" 메소드는 그 자체로 단일 엔트리 포인트를 갖는 완전한 서비스가 될 수도 있다. 최적의 서비스 인터페이스 입도는 많은 요소들에 좌우된다("Service-Oriented Integration Architectures for Healthcare" 참조).
서비스 인터페이스 개념은 SOA 개발의 핵심이다.
개발 과정에서 서비스 인터페이스는 별개의 독립적인 인터페이스 정의 파일로서 표현된다. 설계 과정에서와 마찬가지로 서비스 인터페이스는 SOA의 필수 구성 요소로 남는다. 인터페이스 파일은 합의된 모든 구문론을 사용해 정의할 수 있지만 표준 기반 구문론을 사용할 경우 서비스의 폭 넓은 도입을 활성화시킬 수 있다.
웹 서비스 기술 언어(WSDL; Web Services Description Language)를 사용해 서비스 인터페이스를 인코딩할 때 서비스는 웹 서비스이다.
WSDL은 새로운 개발 툴 대부분에서 서비스 인터페이스 정의를 위해 사용되는 추천 표준이다. 초기의 SOA 개발은 CORBA IDL(Interface Definition Language), COM/DCOM Microsoft IDL(MIDL), CICS(Customer Information Control System) COMMAREA(common area) 및 기타 좁은 범위로 정의된 사양들을 바탕으로 했다.
전형적인 SOA 애플리케이션 개발 프로세스는 인터페이스 정의로 시작되고 그 뒤에 서비스 구현 소프트웨어와 서비스 소비자 소프트웨어의 개발이 뒤따른다. 대부분의 개발 툴들은 인터페이스 정의의 정확한 언어를 숨기지만 SOA 지향 툴들의 개발 방식은 서비스 인터페이스의 정의, 발견 및 상호 연결을 중심으로 남는다.
서비스 구현 소프트웨어는 고유한 아키텍처를 갖고 있다.
개발 중에 서비스 구현은 어댑터를 통해 오래 된 애플리케이션에 연결하는 새로운 프로그램 또는 래퍼이거나 여러 개의 기존 및 새 프로그램들이 조건적으로 통합된 형태가 될 수 있다. 서비스 구현 개발은 단순히 새로운 프로그래밍 시도, 순수한 레거시 래핑 및 수정, 또는 애플리케이션 통합 시도가 될 수 있다. 각각의 작업을 위해서는 서로 다른 툴과 개발 기법이 필요하다.

충분한 서비스 분리가 이루어지지 못할 경우 결과적으로 애플리케이션이 단일 체제로 된다.


개발 과정에서의 느슨한 결합에는 여러 상황에서 호출할 수 있는 프로그래밍 서비스 구현이 필요하다. 서비스 구현 소프트웨어 개발자들은 서비스의 핵이 새로운 상황에서 재사용될 수 있는가 여부라는 점을 이해해야 한다. 서비스 구현은 서비스 소비자의 기술이나 비즈니스 로직에 관한 어떤 가정도 해선 안 된다. 하지만 툴들은 이러한 요건을 강요할 수 없다. 개발자와 개발자들의 프로젝트 리더들은 서비스 구현의 분리성을 보장해야 한다. 서비스 구현 내부 설계의 분리가 제대로 이루어지지 못할 수록 서비스 재사용 비용이 비싸질 것이다. 충분한 분리가 이루어지지 못하면 SOA 툴과 미들웨어를 사용하더라도 서비스 구현의 재사용이 힘들어지며 최종 애플리케이션이 단일 체제 형태가 된다.
독립적인 서비스의 조합을 위해선 통합이 필요하다.
서비스 분리는 재사용을 가능케 하지만 복잡성이 증대된다. 독립적인 서비스는 독립적이지만 충돌 가능성이 있는 정보와 프로세스 모델을 갖게 된다. 이는 서비스의 조화 유지를 힘들게 만든다. 대부분의 경우 서비스 조합을 위해선 서비스 간 차이점을 해결하고 공통된 상황과 오류 해결을 위해 별도의(통합) 기술이 필요하다.
실시간 SOA는 동적으로 재사용할 수 있는 전사적 범위의 소프트웨어 구성 요소에서 명확하다.
실행 중에 서비스 인터페이스는 일반적으로 인터페이스 정의 파일로부터 개발 툴에 의해 생성되지만 수작업에 의해 개발되어 개발 과정에서 다른 소프트웨어에 내장되기도 하는 서비스 인터페이스 스텁과 서비스 인터페이스 프록시 등 한 쌍의 프로그램으로 유지된다.

이 스텁은
 . 서비스 구현용 서버에 배치된다.
 . 서비스 구현에 적합한 로컬 커뮤니케이션 메소드와 데이터 인코딩을 사용해 서비스 구현과

      상호 작용한다.
    . 프록시는 서비스 소비자에 로컬로 배치된다.
 . 서비스 소비자의 구현에 적합한 로컬 커뮤니케이션 메소드와 데이터 인코딩을 사용해 서비스

      소비자와 상호 작용한다.

 

일반적인 예로는 Java 서블릿으로서의 스텁과 Visual Basic 구성 요소로서의 프록시를 들 수 있다. 이 프로그램 쌍은 서비스 인터페이스를 구현한다. 모든 새로운 실시간 애플리케이션은 자체 인터페이스 프록시를 통해 서비스에 액세스하여 서비스의 비 침해적 실시간 재사용을 제공한다.

 

서비스 스텁과 서비스 프록시 커뮤니케이션에서 SOAP가 재사용될 때 서비스는 웹 서비스이다.
이론적으로 생성된 인터페이스 스텁과 프록시 모듈 쌍은 서비스 인터페이스 매개 변수를 전달하기 위해 XML, SOAP 메시지 인벨로프, HTTP, 메시지 지향 미들웨어(MOM) 또는 공유 메모리를 사용한다.
서비스 스텁과 서비스 프록시 커뮤니케이션은 "사적인 비즈니스"이지만 벤더의 형태와 툴 독립성을 유지하기 위해 대부분의 생성 툴은 표준 프로토콜을 사용해 연결을 한다. 하지만 실제로 "표준" 프로토콜은 자동적인 상호운용성을 보장할 정도의 "표준" 자격은 갖고 있지 못하다. 성능 최적화를 위해서도 덜 표준적이면서 융통성이 좋은 커뮤니케이션 프로토콜을 사용할 필요가 있다. 따라서 표준에도 불구하고 2006년까지 서비스 인터랙션을 위해 서비스 스텁 및 서비스 프록시 인코딩 구현의 조정이 필요해질 것이다(확률: 80%).


실시간에서 기술적으로 느슨한 결합은 HTTP 또는 MOM과 같이 기반이 되는 "sessionless" 커뮤니케이션에 의해 이루어진다. 이 낮은 수준의 느슨한 결합은 서비스를 논리적인 느슨한 결합으로 설계하고 개발한 경우에만 효과적이다. 그렇다면 느슨하게 결합된 미들웨어 사용은 새로운 서비스 소비자의 동적인 실시간 추가를 허용한다(즉, 기존 시스템에 사실상의 아무런 영향도 주지 않으면서 실행 중인 시스템에 새로운 사용자 경험을 추가함). 아니면 느슨하게 결합된 미들웨어가 전체 시스템을 위해 더 큰 처리 능력을 제공하겠지만 시스템의 민첩성은 높이지 못한다.
SOA의 실시간 미들웨어는 견고하게 결합된다(예: Java Reomote Method Invocation(RMI) 또는 Microsoft .NET 리모팅). 서비스 설계 및 개발이 논리적으로 느슨하게 결합되면 밀접하게 결합된 실시간 미들웨어에 관계 없이 SOA가 갖고 있는 민첩성이 실시간으로 구현된다.

 

SOA가 항상 올바른 아키텍처인 것은 아니다.
SOA는 체계적인 애플리케이션 엔지니어링에 유용하다. 특히 요청/응답이 소프트웨어 구성 요소들 간의 자연스런 관계 패턴인 환경에서는 더욱 그러하다. 하지만 SOA는 추가적인 설계 및 개발 시도를 희생함으로써 가능해지며 또한 미들웨어 결합의 필요성이 수반된다. 짧은 시간 동안 사용할 제한적 범위의 애플리케이션들은 가용 수명 기간 중에 비즈니스 로직을 재사용하거나 변경하지 않기 때문에 SOA로부터 아무런 혜택도 받지 못한다. SOA는 또한 비 동기 단방향 인터랙션을 사용하는 애플리케이션 용으로는 좋지 않다. 여기서 SOA의 느슨한 결합은 불필요하고 바람직하지도 않다.
결론: 서비스 지향 아키텍처는 요청/응답 패턴의 애플리케이션을 체계적으로 설계하는 데 있어서는 추천할 만한 아키텍처이다. SOA의 주요 목적은 비즈니스 레벨에서의 소프트웨어 모듈화 및 새로운 환경에서의 빠르면서도 비 침해적인 비즈니스 소프트웨어 재사용에 있다. 사용자들은 SOA의 정수를 이해하고 그와 동시에 장단점을 제대로 인식해 현대적인 전사적 IT의 전체 아키텍처에서 SOA가 어떤 역할을 하는지 파악해야 한다.



 

Posted by tornado
|


자전거 VS 오토바이

 

-


저 때가 좋았지.. 오토바이타고.. 시원하게 국도를 달릴때ㅋ '-'

 

아 글쎄 저사람이 자전거를 갖고와서 나보고 내기를 하제;;;

 

ㅎ 결국 졌지만 ㅠ

 

-

 

정말 놀랍지 않습니까

여러가지 법칙을 무시한 주행이지만..ㅎ

 

Posted by tornado
|

Hexadecimal Color Wheel





































출처:

http://javascript.internet.com/page-details/hexadecimal-color-wheel.html

Posted by tornado
|
.. *A6를 아식스라고 읽은 본좌 남친, 그리고 그의친구 GIA를 기아라고..ㅡㅡ;;

기아에서 옷나오데..하는 남자들 미치오



*본좌 중1때 영어 교과서 한줄씩 읽는 순서 때, "HI, JANE" 을 " 하이, 자네" 라고 읽어

쪽팔았던 적있었소..



*내 거래처 직원은 FAQ를 "퐈큐"라 그럽디다 ㅎㅎㅎ


*나는 프로야구단 해태(HAITAI)를 하이타이로 읽었소


*저흰 Slazenger 슬래진져를 '쓰러진거'라고



*본좌 고등학교 때 "POLO" 티셔츠 입고 갔다가 수학선생에게 "포로"취급 당한적 있소.

그 후론 셈에 약하오




*전 과 남자친구랑 메신져로 얘기하다가;; "나 생일 얼마 안남았어" 를 "나 생리 얼마 안남았어"

-_-;;; 라고해서 서로 무안해했던 기억이;;;




*내 친구 술마시구 호프집 가더니 자신있게 주문 합디다. 여기 "오비레이저"루 세병........

Lager=레이저........우린 뒤집어 졌다오!!


*하이타이 정말 압권임돠 적막하기까지한 사무실서 엄청웃음 혼자 미친여자처럼..



*저두 하나 제 칭구가 옷을 샀는데 어디서 샀냐구 물으니 엔투에서 샀다구하더이다 엔투가 어디지

고민하던찰라..ㅋㅋㅋ 그건 바로.. NII이더이다



*제친구수업시간때(친구는 중학교선생)김소월의 진달래꽃 전문을 쓰기시험했답니다.

42명 반아이들중 3명이 마야의 진달래꽃 가사를 그대로 옮겼더랍니다 .

니가 떠나 바람되어 ~~~~맴돌아도~ 그얘기듣고 우리 죽는줄 알았습니다.


*난 남친한테 문자보낼때 저녁을 저년이라 보낸적 있다오..'저년 맛있게 먹어' ㅡㅡ;;


보내놓고 미치는줄 알았소 ..ㄴㅁ ....


*자동차안에 보면 A/C (에어컨)버튼을 내친구넘이 에프터 서비스라네..

그거 누르면 a/s 맨이 온다구하더군여..ㅋㅋㅋ



*체육시간에 옷 갈아입다가 내친구 빤스에 "BG"라고 써있어서 내가 한마디 했소..

"요즘은 빅게이트에서두 빤스나오냐?"....그눔 왈.."이거 보디가든데?"

그날 나 완전 영구됐었소

*영어만 문젠줄 아오? 고교 1년 국어시간 김양이 책을 읽는데 기역,니은,디귿~쭉 우리나라

자음을 모두 읽은 다음 갑자기 끼역(쌍기역),띠귿(쌍디귿),삐읍(쌍비읍)~ 상상이 가오?

우리반은 홀랑 뒤집어졌오~ ㅋㅋㅋㅋㅋㅋ



*전 버디버디 채팅방 들어갔다가 세이클럽아이디 얘기가 나와서 가르쳐 주려고

"내 세이클럽 아이디는 ****야'라고 말하려다 '내 게이클럽 아이디는 ****야' 라고 해서

바로 강퇴강했다죠; <참고로 ㅅ과 ㄱ은 붙어있음=ㅁ =;>



*남친에게 영화관에서 만나자고 문자보내는 칭구.. "이따가 CGB에서만나"...

칭구야~ CGV거덩-..-;;;




*동생이 가져온 게임기에 made in H. K.이라고 써있기에 '메이드 인 한국'이라고 우기면서

'메이드 인 홍콩'이라 하는 동생과 다투기도 했었소. 창피.....


*몇년전에 Am/Pm인가 편의점이 있었던것이 기억나는데 친구 군에서 휴가 나와서 그 편의점을

보고 하는말 "야 요즘 편의점 별개 다 있네 와 "암픔" 편의점도 생겼다 역시 군대에서 나오니

세상이 변하는군" 해서 친구들 다 죽었었답니다. ㅋㅋㅋ^^;



출처..모름...쩝
Posted by tornado
|

struts taglib 사용 --- html 태그


html 태그중에서 link 를 걸어야 할 경우가 생기게 되는데 ,
보통 struts 프로그램을 짜다보면 Controller 에서 Model 측을 접근하여
데이터를 가져온 후 해당 데이터를 Java Beans 스타일(또는 Collections) 에
저장하고, 그 객체들을 request 에 담아서 forward 시키게 된다.

jsp 페이지에서는 이러한 객체를 <html:iterate /> 태그와 같은 것들을 이용해서 사용하게 되는데
request 에 저장되어 있는 객체를 ?a=beanValue&b=beanValue 와 같이 사용할
경우에는 아래와 같은 방법으로 이용한다.

 

BoardConfigBean <-- Action 부분에서 Model 측에 접근하여 Wrapping 한
                              사용자 정의 객체이다.

request.setAttribute("BoardConfigBean", new BoardConfigBean().setIdx(1)); 처럼 저장하겠죠.

 

이렇게 저장된 객체를 JSP 에서는 아래와 같이 불러다가 씁니다.

 

<html:link page="/siteMgr/BoardConfig.do?method=delete"
                paramProperty="idx"
                paramId="idx"
                paramName="BoardConfigBean"
                scope="request">삭제</html:link>


html:link 속성 중에 paramName 이라는 속성은 특정 속성에 지정된 객체를
이름으로 지정한다.

paramId 속성은 쿼리스트링 중 key 부분에 해당한다.
paramProperty 속성은 쿼리스트링 중 value 부분에 해당하며
request 와 같은 속성에 저장된 객체의 getter 부분에 해당한다.


html:link 태그에는 map 속성을 이용할 수 있으며
Map 에 담고 그 형태를 html:link 에 넣어줄 경우 자동으로 링크를 만들어 주기도 한다.

편리한거는 자동으로 ?key=value&key1=value1 과 같이 해준다.

 

자세한 거는 struts 사이트를 뒤져주세용...  또 너무 남용하지 마세용

 

Posted by tornado
|

별건 아니지만.. 자칫 실수하면 짜증나는 문제이기에.. 적어놔야징..

 

 

# Struts 에서 Message Resource 를 여러개 설정해야할 경우 방법

 

조건)

          titleResource.properties   <-- 브라우저의 타이틀 메세지 관리

          adminResource.properties  <-- 관리 페이지의 각종 메세지 관리

          ..... 등등등

 

 

이렇게 두개가 있을 경우 먼저 web.xml 파일에 ActionServlet 등록 태그에 아래와 같이 메세지 리소스를 추가.

 

(web.xml)

 

 <!-- Struts ActionServlet -->
 <servlet>
  <servlet-name>action</servlet-name>
  <servlet-class>org.apache.struts.action.ActionServlet</servlet-class> 
  
  <init-param>
   <param-name>adminResource</param-name>
   <param-value>conf.adminResource</param-value>
  </init-param>
  
  <init-param>
   <param-name>titleResource</param-name>
   <param-value>conf.titleResource</param-value>
  </init-param>

 

... 기타 설정들

 

 

 

(strtus-config.xml)

 

 <message-resources parameter="conf.adminResource" />
 <message-resources parameter="conf.titleResource" />

 

 

 

설정하고

<bean:message key="main.title.index" />

... 기타 필요한 메세지들.... 뿌리면 잘 되더만..

 

자세한 사항은 struts 사이트에서 참고바람

 

'JAVA > JSP_Servlet' 카테고리의 다른 글

apache + tomcat 연동시 Context 문제  (0) 2004.04.16
&lt;html:link /&gt; 태그 중에서 ^^  (0) 2004.04.07
[펌] MVC 모델과 Observer 패턴  (0) 2004.04.01
[펌] 스트럿츠 이디엄  (0) 2004.04.01
[펌] JavaServer Faces 입문  (0) 2004.04.01
Posted by tornado
|




▶ 삼겹살의 돼지 기름 냄새가 그의 입과 머리카락에서 솔솔 배어나와도 일단 참자. 입냄새난다고 그를 타박하면 다음에 가글하고 또 하자고 덤빌지도 모른다. 침묵하되 다시는 그의 입술이 코 앞에 와도 입을 열지 말 것.

▶ 남자들은 동물적인 느낌으로 처음인지 아닌지 다 안다고 한다. 처음이면 어떻고 101번째면 어떻단 말인가. 다음번엔 잘하겠다는 다짐인지, 처음이란 걸 알아달라는 얘긴지 남자들은 헷갈려 한다. 이런 말이 먹힐 시대는 이미 지났다는 말이다

▶ 유리구두를 흘리고 무도회장을 빠져나가는 신데렐라처럼 행동하는 것은 숙녀답지 못하다. 진지하게 키스에 대한 감상을 논할 일도 아니지만 무안함 때문에 자리를 피할 까닭은 더더욱 없다. 키스가 죄가 되나?

▶ 만해 한용운의 시구처럼 첫 키스는 언제나 날카롭고 가슴 저릿할 거라고 생각했다면 오산. 키스는 생물학적으로 살과 살이 맞닿는 접촉일 뿐, 심장이 콩닥거리는 화학반응은 덤으로 따라오는 것이다.

▶ 무드를 확 깨는 말 중 하나. 아무리 애교 있게 말해도 이런 말 들으면 남자들 ‘김 샌다".

▶이런 말을 할 수 있는 강심장 걸에게 박수를!

▶ 세상의 모든 엄마들이 딸의 사생활과 흥미진진한 비밀을 알아야 한다면 세상은 얼마나 재미없어질까? 엄마가 눈치챌 일 절대 없다. 안심하고 몰두하도록!

▶ 바라건대, 가만히 있으면 중간은 간다는 말을 명심하자. 안 하느니 못한 이런 말들로 서먹한 분위기에 꽁꽁 언 얼음을 들이붓지 말자.

▶ 키스 말고 다른 것을 더 기대한다는 말로 들릴 수 있다. 아니, 그렇게밖에 안 들린다. 그래도 굳이 이렇게 말하겠다면 말리지는 않겠지만, 무슨 말을 해야 할까 망설이다 튀어나온 말이라면 남자들이 반응하는 황당지수는 100%.

▶ 때로는 앙큼한 여우가 될 필요가 있다. 남자들은 이런 말 들으면 당신이 아무리 매력적이어도 일단 의심부터 하고 본다. 해선 안 될 비슷한 말, ‘야호, 소원 풀었다!"

▶ 남자에게 이런 말을 ‘듣는’ 걸이 진짜 매력적인 걸이다.

▶ 알아서 무엇하랴. 묻는다고 그 순간 솔직하게 고백할 남자 없다.

▶ 남자들에게도 첫 키스는 쑥스럽다. 일종의 스킨십에 대해 남자가 ‘잘해야 한다’는 강박증마저 있으니 걸들은 이들의 귀여운 피해망상을 굳이 건드리지 말 것. 해선 안 될 비슷한 말, ‘아얏, 혀 깨물었어!"

▶ 뭔가 코믹하게 분위기를 무마해야겠는데 나름대로 쿨하게 극복하고자 하는 노력이 가상하다. 남자들은 ‘응, 그 립스틱 하나만 사주라"고 말한 뒤 싸늘히 등을 돌릴 것이다. 써얼렁~!
▶ 도대체 왜 없던 일로 돌려야 할까? 양다리를 걸치거나 바람을 피우는 게 아니라면 도대체, 왜? ▶ 무뚝뚝하게 앉아 있다가 돌연 가방 집어들고 이렇게 말한다면 매너라곤 없는 걸로 오인받는다. 남자들의 황당지수 150%.


* 손에 들고 있는 마실 것으로 가글하는 걸

* 인상쓰며 입술을 벅벅 문지르는 걸

* 아쉬운 듯 입맛을 다시는 걸

* 사약 삼킨 사람처럼 입 안의 침을 뱉는 걸

* 입 떼자마자 말없이 화장 고치는 걸

* 키스 한 번에 순결 잃은 듯 질질 짜는 걸

* 좋았냐고 캐묻더니 조목조목 따져가며 분석하는 걸.
Posted by tornado
|
 
객체지향 방법론
(Object Oriented Methodology)



- 본 글은 객체지향 방법론의 개략이며 Rational社의 객체지향 방법론인 Objectory Process의 개요서 부분 중 일부를 번역한 내용입니다.

1. 생명주기 구조(LifeCycle Structure)

소프트웨어 생명 주기는 여러주기로 나누어 지며, 각 주기는 제품의 새로운 생산물을 만든다. 본 방법론은 4개의 연속적인 단계로 하나의 개발 주기를 이룬다.
  • 개념화(Inception)
  • 상세화(Elaboration)
  • 구축(Construction)
  • 전이(Transition)
각 단계는 정의된 이정표(어떤 중요한 결정이 만들어지며 따라서 주요 목표가 취득되는 시점)와 함께 종결된다.


[그림 1] 프로세스의 단계들과 주요 이정표

주어진 제품에 대하여 처음 4단계를 한번 수행한 것을 초기 개발 주기(Initial Development Cycle)라 한다. 만약 제품이 계속적으로 지속된다면, 개념화, 상세화, 구축, 전이 단계를 계속적으로 반복하면서 기존의 제품은 다음 세대로 발전(Evolve)할 것이다. 이 기간을 "발전화(Evolution)"단계라 한다. 초기 개발 주기 다음에 이루어지는 개발 주기를 "발전주기(Evolution Cycles)"라 한다.


[그림 2] 두개의 중요한 개발 사이클

1.1 개념화 단계(Inception Phase)

개념화 단계동안 시스템에 대한 비즈니스 사례(Business Case)를 만들고 프로젝트 범위(Scope)를 정의한다. 이를 성취하기 위해서는 시스템과 상호작용을 하는 모든 외부 엔티티(Actor)를 명시하고, 상위 레벨(High Level)에서 상호작용의 특징을 정의한다. 여기에는 모든 유스케이스(Use Case)를 명시하고 중요한 몇 가지를 설명하는 것도 포함된다. 비즈니스 사례는 성공기준(Success Criteria), 위험관리(Risk Management), 필요한 자원의 평가, 주요한 이정표 날짜를 보여주는 단계별 계획을 포함한다.
개념화 단계의 마지막에는 프로젝트 목적을 검사하고 개발 진행여부를 결정한다.

1.2 상세화 단계(Elaboration Phase)

상세화 단계의 목표는 문제영역(Problem Domain)을 분석하고 견고한 아키텍쳐 토대를 마련하고 프로젝트 계획을 개발하며 프로젝트에서 가장 위험한 요소를 제거하는 것이다. 아키텍쳐에 대한 결정은 전체 시스템의 충분한 이해를 통하여 이루어져야 한다. 이것은 유스케이스를 기술하고 추가적인 요구사항과 같은 제약사항을 고려하는 것을 의미한다. 아키텍쳐를 검증하기 위해서는 선정된 아키텍쳐를 실현하고(Demonstrates) 중요한 유스케이스를 실행하는 시스템을 구현하는 것이다.
상세화 단계의 마지막에는 상세한 시스템의 목적과 범위 및 아키텍쳐 선정과 주요 위험을 검사한다.

1.3 구축 단계(Construction Phase)

구축 단계에서는 사용자들(User Community)에게 전이할 수 있도록 반복 및 점증적으로 제품을 완전히 개발하는 것이다. 이것은 나머지 유스케이스를 기술하고 설계부문을 더욱 충실하게 하며, 구현을 완전히 끝내고 소프트웨어를 테스트하는 것을 의미한다.
구축단계의 마지막에는 소프트웨어와 환경과 사용자들이 운영될 준비가 되었는지를 결정한다.

1.4 전이 단계(Transition Phase)

전이 단계에서는 소프트웨어를 사용자들(User Community)에게 전달하는 것이다. 제품이 사용자의 손에 전해졌을 때에는, 시스템에 적합하도록 추가적인 개발 및 발견되지 않은 문제점을 수정하고 미루어 놓은 사항들(Features)을 마무리 짓는다. 일반적으로 이 단계는 시스템의 "베타 릴리즈(Beta Release)"로 시작된다.
전이 단계의 마지막에는 생명주기 목적의 충족여부 및 또 다른 개발 주기의 시작여부를 결정해야 한다. 또한 프로세스를 개선하기 위해 프로젝트에서 경험한 것을 여기서 정리한다.

1.5 반복(Iteration)

방법론 프로세스에서의 각 단계는 여러 번의 반복으로 나누어질 수 있다. 반복은 하나의 완전한 개발 루프로서 내부적 혹은 외부적 실행가능한 제품(개발내에서 최종 제품의 부분적인 집합)을 만들어낸다. 이 실행 가능한 제품은 반복과 반복을 거듭하므로서 점증적으로 발전하여 최종 시스템이 된다.


[그림 3] 방법론 단계 내에서의 반복

각 반복은 소프트웨어 개발의 모든 관점을 거치고 지나가며 단계에 따라 각 프로세스 컴포넌트가 다양하게 강조될지라도 이것은 모두 프로세스 컴포넌트이다.
이는 다음 그림과 같이 여러 반복들이 서로 다른 부분에 강조를 하면서 4단계를 수행하는 모습으로 나타날 수 있다.


[그림 4] 프로세스 컴포넌트

본 방법론에서 단계들은 여러 반복들로 구성되어 있으며, 각 반복은 모든 프로세스 컴포넌트를 포함하고 있다. 각 프로세스 컴포넌트는 산출물에 대하여 책임이 있다. 곡선의 높이는 자원의 양을 표시하고 있다.
이 반복적인 접근방법의 중요한 점은 산출물은 초기에 기술되며 계속적으로 단계가 지나감에 따라 증대되며 성숙해진다.


[그림 5] 개발단계별 정보 집합의 발전

2. 프로세스 컴포넌트(Process Component)

2.1 프로세스 표현(Process Representation)

본 방법론의 프로세스가이드에서는 작업자(Workers)와 활동(Activities)과 작업흐름(Workflows)에 의하여 프로세스 컴포넌트를 기술한다. 수행하는 산출물은 산출물가이드에서 기술하고 있다.
  • 작업자(Workers)는 개개인의 행동 및 책임을 정의하거나 또는 함께 수행하는 개개인들의 집합 즉, 팀으로 정의된다. 왜냐면 일반적으로 생각하기에 작업자는 개인 혹은 팀 그 자체로 간주되지만 객체지향 방법론에서의 작업자는 개개인이 어떻게 작업을 수행하는냐 하는 그 역할에 중점을 두고 있기 때문에 이를 구분한는 것은 중요하다.
  • 활동(Activities)은 연관된 작업의 최소 단위이다. 활동의 한 부분만 수행하는 것은 적절하지 못하다. 하지만 개발의 감시를 용이하게 하기위하여 작업을 분할한다. 프로젝트에서 한 활동의 60% 완료되었다기 보다는 5개의 활동 중 3개가 완료되었다고 표현하는 것이 더 알기 쉽고 바람직하기 때문이다.
  • 산출물(Artifacts)은 개선(Evolve), 유지보수(Maintain) 혹은 입력자료로 사용되는 모델과 문서이다.
각 작업자는 연관성 있고 응집된(Cohesive) 활동 집합을 가지고 있다. "응집되어 있다는 것은(Cohesive)" 한 개인에 의해 활동이 가장 잘 수행되는 것을 의미한다. 각 작업자의 책임은 일반적으로 문서와 같이 연관된 산출물로 정의된다. 작업자의 예로는 유스케이스 설계자, 설계자, 아키텍트 그리고 프로세스 엔지니어가 있다.


[그림 6] 각 작업자별 고유의 활동집합과 산출물

활동의 연관된 집합을 둘러보면, 작업자는 또한 예상되는 작업수행 능력을 함축적으로 정의하고 있다.
프로젝트 관리자에 적합한 사람으로는 그 관련된 능력을 소지한 사람으로 볼 수 있다.
주어진 개개인이 한 작업자의 연관된 활동, 행위를 수행하고, 작업자와 연관되어 있는 모든 산출물에 대한 책임을 갖는 방법으로, 프로젝트 관리자는 이들 개개인을 작업자와 연관시킬 것이다.


[그림 7] 프로젝트에서 개인은 여러 작업자가 된다.

개인과 작업자의 관계는 시간에 따라 유동적이다. 적절한 능력을 소지한 개개인의 이용여부에 의한 제약사항 및 주어진 시간에 의해 수행되어지는 활동에 의한다. 보통은 한 개인이 하나의 작업자가 되지만 다음과 같은 경우도 있다.
  • 동일한 날에 개개인은 몇 개의 다른 작업자로서 일을 하기도 한다 : 이종범은 오전에는 설계 검토(Reviewer)를 하지만 오후에는 유스케이스 설계자로 대치될 수 있다.
  • 동시에 개개인은 몇 개의 작업자로서 일을 하기도 한다 : 어떤 클래스(Class)에서 허정무는 아키텍트와 설계자로서 존재할 수 있다.
  • 몇 명의 개인들은 동일한 작업자 즉 팀의 관계로서 어떤 활동을 함께 수행하기도 한다 : 선동렬과 박찬호는 동일한 유스케이스의 유스케이스 설계자로서 작업을 할 수 있다.
다양한 프로세스 컴포넌트와 활동을 계획할 때 프로젝트 관리자는 매끄럽게 이어지도록(Seamless Fashion) 개개인의 작업을 할당해야 한다. 이 말은 즉, 산출물이 한 개인으로부터 다른 개인으로 넘겨지는 것을 최대한 줄이고자 하는 것이다.
예를 들어서, 클래스의 설계자는 구현자(Implementer)가 될 수 있다. 주어진 유스케이스에서 동일한 개인이 유스케이스 명세자(Specifier)와 유스케이스 설계자로 행동할 수 있다.

2.2 프로세스 컴포넌트와 모델(Process Components and Models)

프로세스 컴포넌트는 연관된 집합의 활동과 산출물을 가지고 있다. 가장 중요한 산출물은 각 프로세스 컴포넌트가 산출하는 모델이다. 즉 유스케이스 모델, 설계 모델, 구현 모델 그리고 테스트 모델이다. 아래 그림은 프로세스 컴포넌트와 모델의 관계도를 보여주고 있다.


[그림 8] 각 프로세스 컴포넌트는 하나의 특정한 모델과 연관된다.

2.3 요구사항 수집(Requirement Capture)

프로세스 컴포넌트 중 요구사항 수집의 목표는 시스템이 무엇이며 무엇을 하는가를 기술하고 개발자와 고객이 기술서에 동의하도록 하는 것이다. 이를 위해서 시스템의 범위를 정하고 시스템의 주위 환경 및 행동을 정의한다. 시스템 요구사항이 존재할 뿐만 아니라 고객과 잠재적인 사용자는 정보의 중요한 소스(Sources)이다.
요구사항 수집을 하므로써 유스케이스 모델과 추가 요구사항(Supplementary Requirements)을 만들어 낸다. 유스케이스 모델은 사용자와 개발자에게 필수적인 요소이다. 사용자에겐 예상한 시스템이 모델에 잘 반영되었는가를 평가하기위해 모델이 필요하며, 개발자에게는 시스템상에서 요구사항을 보다 잘 이해하기 위해서 모델이 필요하다.
유스케이스 모델은 프로젝트에 참여하고 있는 모든 사람에게 유용하다.
유스케이스 모델은 액터(Actors)와 유스케이스(Use Cases)로 구성되어 있다. 액터는 사용자와, 개발되어질 시스템과 상호작용을 하는 다른 시스템을 의미한다. 액터는 시스템 범위를 정하는 것을 도와주고, 시스템이 어떻게 될 것이다라는 명확한 그림을 제공한다.
유스케이스는 시스템의 행위를 표현한다. 유스케이스는 액터의 요구사항에 의해 개발되어지기 때문에 시스템은 사용자에게 보다 적절하게 될 수 있다. 아래 그림은 재활용품 수집기(Recycling-machine) 시스템에 대한 유스케이스 모델의 예를 보여주고 있다.


[그림 9] 유스케이스 모델의 예

각각의 유스케이스는 상세히 기술된다. 유스케이스 설명서(Description)는 시스템이 단계적으로 액터와 어떻게 상호작용 하는가와 시스템이 무엇을 하는지를 설명한다.
유스케이스 역할은 시스템의 개발 주기 전체에 걸쳐 통합된 매개체(Thread)의 기능을 하는 것이다. 동일한 유스케이스 모델이 요구사항 수집, 분석 및 설계와 테스트 동안에 사용된다.

▶ 작업자와 작업흐름(Workers and Workflow)

각 작업자는 활동 집합과 행동에 대해 책임을 진다. 각 프로세스 컴포넌트는 고유의 작업자들과 그 작업자가 활동을 진행하는 논리적 방법인 작업흐름을 가지고 있다. 아래의 작업자들은 요구사항 수집에서 정의된다.
  • 유스케이스 모델 아키텍트(Use-Case Model Architect)
  • 유스케이스 명세자(Use-Case Specifier)
  • 요구사항 검토자(Requirements Reviewer)
  • 아키텍트(Architect)
아래 그림은 요구사항 수집에서 작업흐름에 대한 전체적인 개요를 보여주고 있다.


[그림 10] 요구사항 수집 단계

2.4 분석 및 설계(Analysis & Design)

프로세스 컴포넌트 중 분석 및 설계의 목표는 구현 단계에서 시스템이 어떻게 실현되는가를 보여주는 것이다. 아래 사항을 만족하는 시스템을 구축하여야 한다.
  • 유스케이스 설명서에 명시된 작업(Task)과 기능(Functions)을 구체적인 구현 환경에서 수행한다.
  • 시스템의 모든 요구사항을 충족한다.
  • 견고한 구조를 가진다(기능적 요구사항 변화가 있을 때 쉽게 변경할 수 있는가)
유스케이스 모델은 추가 요구사항 명세서(Supplementary Specifications)와 함께 설계의 토대가 된다.
분석 및 설계에서는 소스 코드의 추상적 개념을 보여주는 설계 모델을 만들어 낸다. 설계 모델은 어떻게 소스 코드가 구조화되어져 있고 쓰여졌는지를 보여주는 청사진과 같은 역할을 한다. 설계 또한 유스케이스의 내부에 관한(Inside-view) 설명서 또는 참여하는 객체/클래스의 관점에서 유스케이스가 어떻게 실현되는지를 기술한 유스케이스 실현(Use-Case Realization)을 만든다.
설계 모델은 설계 패키지에 구조화된 설계 클래스들로 구성되어 있다. 또한 설계 모델은 유스케이스를 수행하기 위해서 어떻게 이들 설계 클래스의 객체들이 상호작용하고 있는지를 기술한 내용을 담고 있다.
설계 활동은 아키텍쳐 측면에 집중한다. 이 아키텍쳐의 생산(Production) 및 확인(Validation)은 초기 설계 반복의 주요한 초점이 된다. 아키텍쳐는 몇 개의 아키텍쳐(Architectural) 뷰에 의해 표현된다. 이들 뷰에는 주요하고 구조적인 설계 결정사항들이 수집된다. 본질적으로 아키텍쳐 뷰는 상세부분에서 탈피하여 중요한 특성을 보다 쉽게 볼 수 있도록 전체 설계를 추상화 혹은 단순화하는 것이다. 아키텍쳐는 좋은 설계 모델을 개발하는 것 뿐만 아니라 시스템 개발 동안 모델의 품질을 증대시키기 위한 중요한 수단이다.

▶ 작업자와 작업흐름(Workers and Workflow)

아래의 작업자들은 분석 및 설계에서 정의된다.
  • 아키텍트(Architect)
  • 유스케이스 설계자(Use-Case Designer)
  • 설계자(Designer)
  • 설계 검토자(Design Reviewer)
다음의 그림은 분석 및 설계에서 작업흐름의 전체적인 개요를 보여주고 있다. 작업흐름은 아키텍쳐-레벨(Architectre-Level) 설계와 클래스-레벨(Class-Level) 설계로 나뉘어 진다.


[그림 11] 분석 및 설계 단계

2.5 구현(Implementation)

시스템은 구현을 통해서 생성되는 소스, 즉 소스 코드 파일(Source-Code Files), 헤더 파일(Header Files), 메이크 파일(Make Files) 등에 의해서 실현된다. 이 소스는 실행 가능한 시스템을 만들어 낼 것이다. 그리고 소스는 구현 패키지(Implementation Packages)에 구성된 모듈(Modules)로 이루어져 있는 구현 모델(Implementation Model)에서 설명된다. 설계 모델은 구현을 위한 기초 자료가 된다. 구현은 별개의 클래스 또는 패키지의 테스팅을 포함하고 있지만, 동시에 패키지와 클래스를 함께 테스팅하는 것은 포함하지 않는다. 이것은 다음 프로세스 컴포넌트 "테스트(Test)"에서 설명된다.

▶ 작업자와 작업흐름(Workers and Workflow)

아래의 작업자들은 분석 및 설계에서 정의된다.
  • 아키텍트(Architect)
  • 시스템 통합자(System integrator)
  • 구현자(Implementor)
  • 코드 검토자(Code Reviewer)
다음의 그림은 구현에서 작업흐름의 전체적인 개요를 보여주고 있다. 작업흐름은 구현 뷰(Implementation View)를 정의하는 것으로부터 클래스의 구현과 통합의 계획 및 수행 까지의 활동을 연결(Span)한다.


[그림 12] 구현 단계

2.6 테스트(Test)

테스트는 시스템 전체를 검증한다. 참여하고 있는 클래스들이 잘 어울려져 올바르게 작동하는가를 검증하기 위해서는, 먼저 개별적으로 유스케이스를 테스트한다. 그런 후에 유스케이스 설명서를(어떤 관점에서의) 테스트의 입력 자료로 사용하여 전체적으로 시스템을 테스트 한다. 테스트를 끝낸 후에 시스템은 전달되어 진다.

▶ 작업자와 작업흐름(Workers and Workflow)

아래의 작업자들은 분석 및 설계에서 정의된다.
  • 테스트 설계자(Test Designer)
  • 통합 테스터(Integration Tester)
  • 시스템 테스터(System Tester)
  • 설계자(Designer)
  • 구현자(Implementer)
다음의 그림은 테스트에서 작업흐름의 전체적인 개요를 보여주고 있다. 작업흐름은 계획에서부터 설계, 구현 그리고 수행하는 테스트 절차(Procedures)까지 전체적인 활동을 연결(Span)한다.


[그림 13] 테스트 단계




Posted by tornado
|
나만의 자바 컴포넌트를 만들자
eapoeash (2004-03-22 17:40:14)

저자: 김영익 / (주)콘텔라


자바 프로그래머라면 당연히 AWT나 Swing 컴포넌트에 대해서 알고 있고 GUI를 위해서 여러 형태의 컴포넌트들을 조합해서 원하는 화면을 만들어 보았을 것이다. 그러나 때로는 JDK 에서 지원하는 표준 컴포넌트들만으로는 무엇인가 부족함을 느껴 본적은 없는가? 자신의 입맛에 딱 맞는 컴포넌트가 없어서 오랜 시간을 허비하거나 고생해본 경험이 있을 수도 있다. 이번 기사에서는 자신만의 간단한 컴포넌트를 작성해보기로 하자.


1. 이렇게 만들어 주세요~~~

필자가 작년에 수행했던 프로젝트 중에 이런 기능을 넣어 달라는 요구 사항이 있었다.
“유닉스 시스템의 CPU, 메모리, 파일 시스템의 상태를 감시하는 기능을 챠트를 이용해서 보기 좋게 넣어달라” 요구 사항 자체는 간단했지만 챠트를 만들기 위해서는 상당한 노력이 필요하기 때문에 다른 라이브러리를 사용하기로 결정했다. 비용 절감을 위해 “JFreeChart” 라는 오픈 소스 프로젝트를 사용해서 챠트 문제를 해결했지만 한가지 남은 문제가 있었다.
CPU의 상태를 윈도우의 작업 관리자에서 보이는 형태처럼 만들어 달라는 것이었다.

null


JProgressBar를 사용하면 비슷한 형태가 나오기는 하지만 아무래도 많이 다르다는 느낌이 들어서 직접 만들어서 사용하기로 결정했다. 최종적으로 구현된 결과는 아래 화면을 참고하자.



원래 이 컴포넌트만 단독으로 보여 주는 것은 아니었고 다른 그래프들과 함께 프레임에 포함된 것이었다. JFreeChart로 그려진 그래프도 구경할 겸해서 아래 그림도 첨가한다.




2. 주요 구현 설명

일반적으로 자바 컴포넌트를 만들기 위해서 Sun 에서는 자바 빈즈 컴포넌트 명세를 따르기를 권고한다. 그러나 지침대로 모든 사항을 맞추기에는 시간과 노력이 너무 많이 들기 때문에 최대한 간단하게 원하는 기능만을 수행하도록 작성 해보도록 하자.

소스의 양도 그리 길지 않고 어려운 부분도 없으므로 소스에 삽입된 주석만을 주의 깊게 살펴보면 된다.

import javax.swing.*;
import java.awt.*;
import javax.swing.border.*;
import java.awt.event.*;

public class PmTickChartPanel extends JPanel {
  BorderLayout borderLayout1 = new BorderLayout();
  JPanel centerPanel = new JPanel();
  JPanel southPanel = new JPanel();
  JPanel northPanel = new JPanel();
  JLabel dataLabel = new JLabel();
  GridLayout gridLayout1 = new GridLayout();
  BorderLayout borderLayout2 = new BorderLayout();
  JLabel titleLabel = new JLabel();
  BorderLayout borderLayout3 = new BorderLayout();
  JPanel westPanel = new JPanel();
  JPanel eastPanel = new JPanel();

  // 편의상 눈금은 10개만 보이고 색상 변경도 10 단위로만
  int tickCount = 10;

  Border centerPanelBorder;
  private Border border1;

  public PmTickChartPanel() {
    try {
      jbInit();
    } catch (Exception e) {
      e.printStackTrace();
   }
  }

  private void jbInit() throws Exception {
    centerPanelBorder = BorderFactory.createLineBorder(Color.green, 1);
    border1 = BorderFactory.createBevelBorder(BevelBorder.LOWERED, new Color(4, 4, 4), new Color(3, 3, 3), Color.black, Color.black);
    this.setBackground(Color.black);
    this.setForeground(Color.green);
    this.setBorder(border1);
    this.setLayout(borderLayout1);
    centerPanel.setBackground(Color.black);
    centerPanel.setFont(new java.awt.Font("Dialog", 0, 12));
    centerPanel.setForeground(Color.green);
    centerPanel.setBorder(centerPanelBorder);
    centerPanel.setLayout(gridLayout1);
    southPanel.setBackground(Color.black);
    southPanel.setForeground(Color.green);
    southPanel.setLayout(borderLayout2);
    northPanel.setBackground(Color.black);
    northPanel.setForeground(Color.green);
    northPanel.setLayout(borderLayout3);
    dataLabel.setBackground(Color.black);
    dataLabel.setFont(new java.awt.Font("Dialog", 1, 12));
    dataLabel.setForeground(Color.green);
    dataLabel.setHorizontalAlignment(SwingConstants.CENTER);
    dataLabel.setHorizontalTextPosition(SwingConstants.CENTER);
    dataLabel.setText("");
    titleLabel.setBackground(Color.black);
    titleLabel.setFont(new java.awt.Font("Dialog", 1, 12));
    titleLabel.setForeground(Color.green);
    titleLabel.setHorizontalAlignment(SwingConstants.CENTER);
    titleLabel.setHorizontalTextPosition(SwingConstants.CENTER);
    this.titleLabel.setText("CPU");
    gridLayout1.setColumns(1);
    gridLayout1.setRows(tickCount);
    gridLayout1.setHgap(1);
    gridLayout1.setVgap(1);
    eastPanel.setBackground(Color.black);
    eastPanel.setForeground(Color.green);
    westPanel.setBackground(Color.black);
    westPanel.setForeground(Color.green);
    this.add(centerPanel, BorderLayout.CENTER);
    this.add(southPanel, BorderLayout.SOUTH);
    southPanel.add(dataLabel, BorderLayout.CENTER);
    this.add(northPanel, BorderLayout.NORTH);
    northPanel.add(titleLabel, BorderLayout.CENTER);
    this.add(westPanel, BorderLayout.WEST);
    this.add(eastPanel, BorderLayout.EAST);
    setPreferredSize(new Dimension(90, 180));

    for (int i = 0; i < tickCount; i++) {
      Tick tick = new Tick(); // 눈금(tick)을 10개 생성하여 추가
      this.centerPanel.add(tick);
    }
  }

  /* 실제 컴포넌트에 값을 설정하면 눈금에 색상을 변경한다
  *  값의 범위는 0~100 으로 하자
  */
  public void setValue(int value) {
    if (value > 100) { // 100을 넘어가면 100으로
      value = 100;
    }
    else if (value < 0) { // 0보다 작으면 0으로
      value = 0;
    }

    // 일단 전체 tick 을 검정색으로 칠하고
    for (int j = 0; j < tickCount; j++) {
      Tick tick = (Tick)this.centerPanel.getComponent(j);
      tick.setBackground(Color.black);
      tick.repaint();
    }

    // 입력된 value 값에 해당하는 tick들만 다시 녹색으로 칠한다
    for (int i = 0; i < tickCount; i++) {
      Tick tick = (Tick)this.centerPanel.getComponent(i);
      if (tickCount - i > value / 10) {
        // nothing to do
      } else {
        tick.setColor(Color.green);
        tick.repaint();
      }
    }

    // 하단에 숫자로 값을 표시
    this.dataLabel.setText(value + " %");
  }

  public static void main(String args[]) {
    JFrame frame = new JFrame(); // 테스트용 프레임을 생성하자
    frame.addWindowListener(new WindowAdapter() {
      public void windowClosing(WindowEvent e) {
        System.exit(0);
      }
    });
    PmTickChartPanel tickPanel = new PmTickChartPanel();
    frame.getContentPane().setLayout(new BorderLayout());
    frame.getContentPane().add(tickPanel, BorderLayout.CENTER);

    frame.setSize(300, 300);
    frame.setVisible(true);
    
    for (int i = 0 ; i < 100 ; i++) { // 테스트를 위해 값을 설정하는 부분
      try {
        Thread.sleep(100); // 잠시 쉬었다가
        tickPanel.setValue(i); // 1씩 증가되는 값을 설정, 10 단위로 눈금 색상 변경
      }
      catch (InterruptedException ie) {
        ie.printStackTrace();
      }
    }
  }
}

/* 10 단위의 눈금 하나에 해당하는 컴포넌트
* 같은 값을 갖는 것이 좌우 하나씩 쌍으로 구성된다
*/
class Tick extends JPanel {
  JPanel lPanel = new JPanel();
  JPanel rPanel = new JPanel();
  GridLayout layout = new GridLayout(1, 2);

  public Tick() {
    this.setBackground(Color.black);
    this.setForeground(Color.black);
    lPanel.setBackground(Color.black);
    lPanel.setForeground(Color.green);
    rPanel.setBackground(Color.black);
    rPanel.setForeground(Color.green);
    layout.setHgap(1);
    setLayout(layout);
    add(lPanel);
    add(rPanel);
  }

  protected void setColor(Color color) {
    lPanel.setBackground(color);
    rPanel.setBackground(color);
  }
}

3. 나만의 컴포넌트 작성 소감

위의 소스를 작성하고 컴파일까지 이상 없이 진행되었다면 실행해보자. 앞에서 보여진 그림처럼 값이 증가됨에 따라 눈금이 올라가는 것을 볼 수 있다. 대단한 것은 아니지만 예상보다 예쁘게 보이는 컴포넌트가 대견하기만 하다. 여러분은 용도에 따라 별도의 구현만 추가한다면 입맛에 바꿔 사용할 수 도 있고, 이 예제를 기반으로 다른 컴포넌트를 작성할 준비가 된 것이다. 언제까지 남이 만든 것만 사용할 것인가? 머리 속에 무엇인가 떠오르는 것이 있다면 지금 당장 준비하자 !!!
Posted by tornado
|
MVC 모델과 Observer 패턴
eapoeash (2004-03-24 16:58:12)

저자: 김대곤

이 패턴을 설명하기 전에 MVC 모델을 먼저 살펴보자. MVC 모델은 조금은 거창하게 알려져 있는 듯하다. 거의 그런 경우가 드물지만, 몇 년 전 필자가 본 누군가의 이력서에는 자신의 강점을 프로젝트에 MVC모델을 적용한다는 것이라고 적혀 있는 걸 보았다. 필자가 보기에 MVC 모델을 적용한다는 것은 달리기를 한다는 말과 같아 보인다. 필자도 달리기를 한다. 그러나 잘 하지는 못한다. 국민학교(초등학교)때부터 체육은 언제나 주저하게 되는 분야였다. 달리기를 잘하는 것과 달리기를 하는 것은 다른 문제이다.

MVC 모델에서 MVC는 각각 Model, View, Control를 말한다. Model은 데이터 또는 기본 기능을 말하고, View는 유저 인터페이스를 말한다. 이 두가지는 시스템 개발에 있어서 없어서는 안되는 부분이며, 누가 개발을 하더라도 반드시 있기 마련이다. MVC 모델은 C 모델이라고 불러도 상관없을 만큼 한마디로 말해서 Control이라는 레이어 계층을 두자는 것이다. Graphical User Interface를 사용할 때, Model 계층과 View 계층 사이에 Control 계층을 만들어서 사용하자는 것이다. 왜 그렇게 해야 하는가? 여기에는 몇가지 가정이 담겨 있다.

두 계층 사이에 필수적이지 않은 다른 계층을 두는 이유는 간단하게 말해서 두 계층이 직접적으로 Coupling되는 것을 피하려고 하기 때문이다. 즉, Control 계층은 Model 계층과 View 계층의 high Coupling을 막아준다. Model 계층과 View 계층의 high coupling이 좋지 않은 이유는 Model과 View의 생명주기가 다르기 때문이다. 일반적으로 Model 계층의 생명주기가 길며, 변경이 드물게 일어난다고 여겨진다. 예를 들어, 물건을 파는 웹 사이트에서 사이버 매장을 새 단장하는 경우를 생각해 보자. 일반적으로 View만 바뀌지 Model은 바뀌지 않는다. 같은 기능을 가진 시스템에서 사용자에 따라서 다른 View가 존재할 수도 있다. 또는 웹사이트에서도 보고, PDA에서도 보는 경우도 같은 Model이 서로 다른 View로 표현되는 예라고 할 수 있다. 직접적인 Coupling은 Model과 View를 같이 바뀌도록 만든다. 이것을 Control 계층이 막아준다. 그럼 View가 바뀌면 Control이 바뀌어야 하는 것이면 마찬가지 아닌가 하는 의문이 생긴다. Control 계층의 로직은 매우 간단한다. 아니 간단하게 설계해야 한다. 적어도 Model를 바꾸는 것보다 훨씬 쉽게. Control 계층은 단지 Coordinator에 불과해야 하기 때문이다.

MVC 모델은 Layered Style이고 Layered Style에서는 아래 Layer가 상위 Layer를 사용하는 것을 권장하지 않는다. A 계층이 B 계층을 사용하게 되면, A 계층은 B 계층에 종속된다. 즉, B 계층이 없으면 A 계층은 자신의 역할을 수행하지 못하는 것이다. B 계층은 A 계층이 없어도 문제가 없다. 이러한 의존관계를 Usage dependency 라고 부른다. Layered Style에서 상위 계층은 하위 계층에 대해 Usage dependency가 있다. 하위 계층이 더 생명주기가 길며, 변경되는 일이 적어야 한다. 그런데 하위 계층이 상위 계층에 있는 기능을 사용하면 하위 계층이 상위 계층에 종속되어 버린다. 만약, MVC 모델에서 Model이 View의 기능을 사용해야 하는 경우에 Model이 View에 종속되는 것을 어떻게 막을 것인가?

이것이 Observer 패턴을 사용하게 되는 중에 하나이다. 이제 Observer 패턴에 대해서 살펴보자. GoF의 디자인 패턴에는 Observer 패턴의 목적을 이렇게 정의하고 있다. "Define a one-to-many dependency between objects so that when one object changes state, all its dependents are notified and update automatically." "한 객체의 상태가 바뀔 때 다른 객체들에게 그 사실을 알려주고 자동적으로 업데이트 되도록 하고자 한다면 이 패턴을 쓰시오" 정도 될 것이다. 좀 걸리는 단어는 one-to-many dependency다. 이제 하나씩 살펴보도록 하자.

한 객체의 상태에 변화가 생기면, 그 객체의 상태에 관심있는 객체들에게 알려주는 방식이다. 객체에게 무엇인가를 알려주는 방법은 객체의 메소드를 통해서 이다. 관심 있는 객체의 메소드를 호출해주면 된다. 하지만 객체의 메소드를 사용하면, 이 객체에 대해 usage dependency가 생기게 된다. 즉, coupling이 높아진다. 이 패턴은 특정한 알려주는 방식을 제안하고 있다.

이 패턴이 어떻게 작동되는지 살펴보자. 예제 파일[Download]을 실행해 보자. 아래의 두 화면이 보인다. Input data 에 데이터를 입력하면 Observer 화면에 나타나도록 되어 있다.
그림1

그림2

"Subject.java"에 있는 Vector 데이타가 바뀔 때 자동적으로 바뀐 내용을 보여주려고 한다. Subject 객체가 Observer객체의 내용을 바꾸기 위해서는 Observer객체의 메소드를 호출해야 하고, 메소드를 호출하기 위해서는 그 객체의 Reference가 필요하다.

Subject 객체의 addObserver라는 메소드를 통해 Observer는 자신의 Reference를 제공하고, Subject는 Observer 객체(MyFrame.java)의 update(Vector v) 메소드를 통해 화면을 바꾸어 준다. 별 무리 없이 작동하고 있다. 문제점은? MyFrame 클래스를 삭제해 보면 알게 된다. Subject 클래스가 더 이상 컴파일 되지 않는다. 이유는 간단하다. 자신의 Observer였던 MyFrame 클래스를 소스안에 포함하고 있었기 때문이다. 만약, 객체의 상태에 관심을 가지고 있는 객체가 오직 하나이고, 변경될 소지가 적다면, 위와 같이 코딩해도 별 문제는 없을 것이다. 하지만 Observer가 한 개가 아니라 20개 정도 되면 20 개나 되는 타입의 클래스를 포함하고 있게 된다. 그 중에 updata(Vector v)라는 메소드를 가지고 있지 않은 클래스라도 있으면 그건 바로 에러가 된다.

이러한 문제를 해결하는 방법은 Subject가 각 Observer들의 클래스 타입 대신 인터페이스를 사용하고, 이 인터페이스는 자신을 구현하는 클래스들에게 update(Vector v)라는 메소드를 구현하도록 강제한다. [Download]

코드를 자세히 살펴보면, 이 Observer 패턴과 자바의 이벤트 처리가 같음을 알 수 있다. 리스너(ActionListener)를 만들고, 리스너를 Subject(JButton)에 등록하고 JButton의 상태가 변하면 ActionListener로 강제된 actionPerformed 메소드가 호출된다. 이 패턴도 Observer 인터페이스를 구현하는 객체를 만들고, 만든 객체를 Subject에 등록하고, Subject 객체는 자신의 상태가 바뀌면, 인터페이스에 정의된 메소드를 호출한다. 즉 Observer 패턴은 이벤트 시스템을 구현할 때 사용된다. 이벤트 시스템의 구현은 Observer 패턴이 주는 또 하나의 강점이다.

하지만 기본은 전혀 바뀌지 않았다. 객체에게 무엇인가를 알려주는 방식은 메소드이고 메소드의 호출을 위해서는 객체의 Reference가 필요하는 것. 조금 다른 방식일 뿐 이 두가지 작업은 패턴을 적용해도 피할 수 없는 것이다. 즉, 패턴은 어떤 문제들을 교묘히 피해가는, 평소에는 잘 생각나지 않는 방법을 알려주고 있다. 그래서 패턴을 언제 사용하는가에 대한 이해는 외우지 않고 있으면 잘 생각나지 않고, 사용하지 않으면 이해되지 않는 측면이 있다. 패턴은 처음 적용해 볼 때 가장 어렵다. 한 번 하고 나면 생각만큼 어렵지는 않다.

필자의 패턴 설명은 전체적으로 모든 내용을 다루고 있진 않다. 일반적으로 Subject는 attach(Obsever obs), detach(Observer obs), notifyAll() 이라는 메소드를 가지고 있다. 하지만 detach 메소드는 다루지 않았다. 인터페이스가 강제하는 메소드도 여러 형태가 될 수 있으며, 그 메소드에 내용이 전달되지 않고 Subject의 다른 메소드를 호출함으로 Subject의 상태를 가져오기도 한다. 자세한 사항은 Design Pattern 책을 참고하기 바란다. Jstorm(www.jstorm.pe.kr)에서도 Design Pattern에 관련된 자료들을 찾을 수 있으리라 생각된다.

'JAVA > JSP_Servlet' 카테고리의 다른 글

&lt;html:link /&gt; 태그 중에서 ^^  (0) 2004.04.07
[Struts] MessageResource 여러개 쓰기  (0) 2004.04.01
[펌] 스트럿츠 이디엄  (0) 2004.04.01
[펌] JavaServer Faces 입문  (0) 2004.04.01
[펌] Jakarta Digester 학습하기  (0) 2004.04.01
Posted by tornado
|
웹 서비스와 SOA(Service Oriented Architecture)
hanbit (2004-03-09 09:14:50)

저자: 이한수(KT 운용시스템 연구소)


필자가 "IT EXPERT, 웹 서비스 실전 프로그래밍" 이라는 제목의 웹 서비스 관련 책을 집필한지도 벌써 1년이 넘었다.

그동안 웹 서비스 관련 기술들에는 많은 변화들이 있었다. 예를 들면 보안, 호환, 트랜젝션 등을 비롯하여 작년부터 활발하게 진행되고 있는 프로세스 관리 등이 이들 변화의 큰 틀이라 볼 수 있다. 하지만 아쉽게도 아직 이러한 기술들의 성숙도가 우리가 기대하는 만큼의 수준에 이르지는 못한 것이 사실이다. 흔히들 웹 서비스 도입의 가장 큰 걸림돌로 확실한 보안 정책의 미비 혹은 웹 서비스간의 연동 시 발생하는 트랜젝션과 프로세스 관리의 문제를 들고 있기 때문이다.

그런데 조금 다른 관점에서 이 문제를 바라 본다면,

대규모 기업 시스템이나 웹사이트들이 겪고 있고 고민하고 있는 문제들 중에는 여전히 보안이나 연동시의 문제점들이 지적되고 있는 사실을 주목해 본다면 이제 3~4년 밖에 안된 유아 수준의 기술인 웹 서비스가 기술 성숙에 필요한 당연한 진화과정을 겪고 있다고도 볼 수 있는 것이다.

필자는 이러한 관점에서 웹 서비스를 생각할 때 "아직 보안이 미비하기 때문에 고려할 필요없다. 혹은 타 서비스와 연동 시 발생할 수 있는 문제 때문에 적용할 수 없다" 라는 식의 결론은 타당치 않다고 말하고 싶다.

왜냐하면 최근에 웹 서비스 기술에서 발현된 근본적이고도 혁신적인 개념이 앞으로 우리가 컴퓨터 시스템을 바라보는 시각을 송두리째 바꾸어 버릴 것이기 때문이다. 너무나 큰 반향 앞에 미시적인 문제들이 장애가 될 수 없다는 것이다.

시장조사 기관인 가트너 그룹은 2004년을 이끌고 갈 10대 핵심 기술로서 웹 서비스를 그 네 번째 항목으로 지목하였다. 그들은 왜 아직 기술적인 성숙도가 높지 않다고 생각되는 웹 서비스를 이렇게 중요하게 생각하고 있는 것일까?

그 생각의 중심에 SOA(Service oriented Architecture: 이하 SOA)라는 중요한 개념이 자리잡고 있다.

가트너는 더 나아가서 2006년까지 전 세계 비즈니스 애플리케이션의 80% 이상이 SOA 를 기반으로 개발될 것이며 향후 5년간 IT 애플리케이션 개발의 80%가 웹 서비스를 기반으로 하는 .Net과 J2EE로 개발될 것이라고 예측하고 있다.

그럼 도대체 SOA 라는 것이 무엇이길래 이렇게 중요하게 생각되는 것일까?

Service

SOA 가 무엇이냐는 정의에 앞서 더 중요한 정의를 짚어 보도록 하자.

도대체 우리가 말하는 '서비스'라는 것이 무엇일까?

필자는 이것이 우리가 심각하게 고민해 보아야 할 주제라고 생각한다. 서비스란 "무엇인가가 제공하는 어떠한 형태의 용역 혹은 역무"를 의미한다. 다시 말해 우리는 서비스를 이용하며 어떠한 과정을 거치는 것은 관심 밖이고 단지 우리가 원하는 결과물을 기대하는 것이다.

114 전화번호 서비스를 이용한다고 가정해 보자. 일단 찾고자 하는 상호를 말하고 우리는 단순히 약 2~3 초 간의 기다림 후에 서비스의 결과물인 전화번호를 기대하는 것이다. 전화번호를 찾아내기 위한 시스템의 구현 형태, 연동, 보안 따위의 문제는 서비스를 이용하는 고객이 걱정할 문제가 아닌 것이다.

더 나아가 만약 우리가 찾고자 하는 전화번호가 존재하지 않을 때를 생각해 보자. 친절하게도 안내 해주시는 분께서 "찾으시는 전화 번호가 없는데 상호를 잘못 말씀해 주신 것은 아닌지요?"와 같은 질문을 서비스 이용자에게 던지게 된다. 즉, 일종의 연동이라고나 할까? 사용자와 서비스 사이에서 중계하는 역할이라고 할 수 있다.

그런데 만약 이때 "고객님은 .Net을 쓰고 계시기 때문에 안내해 드릴 수 없습니다" 라고 말한다면 고객은 어떤 기분이 들 것인지는 굳이 언급하지 않아도 될 듯하다.

그럼 이제 우리가 다루는 시스템에 좀 더 가깝게 얘기해 보자.

만약 시스템을 개발하다가 사용자가 성인인지 아닌지를 판별하여 주는 기능이 필요하다고 하자. 이를 손수 개발하자고 하니 쌓여있는 데이터가 없어 곤란한 상황이다. 이럴 때 이 기능을 서비스로 제공하는 사업자가 있다면 조회 건수당 얼마씩의 비용을 내고 손쉽게 이용할 수 있을 것이다. 우리는 바로 이러한 것들을 서비스로 생각할 수 있을 것이다. 즉, 우리가 원하는 결과를 어떻게 해서든 제공해 줄 수 있고 손쉽게 이용할 수 있는 것!

Service Oriented Architecture

SOA는 지금까지 컴퓨터 시스템을 만들기 위해 소위 아키텍쳐라는 것을 만들어 가면서 혁신적인 개념으로 생각했던 객체지향적인 방법(Object Oriented)에서 컴포넌트 중심적인 방법(Component Based Development)과 모델 기반의 접근 방법(Model Driven Architecture)의 연장 선상에 있는 가장 포괄적이고도 현실적인 개념으로 인식되고 있다.

웹 서비스 이전에도 비즈니스 로직을 컴포넌트화 하여 이것을 서비스로 보고자 하는 DCOM, EJB, CORBA와 같은 개념도 있었지만 이들은 웹 서비스를 이용한 SOA와 명확한 차이를 가지고 있다. 필자가 생각 하기에 DCOM, EJB, CORBA 같은 개념들은 오히려 컴포넌트 중심적인 방법론에 가깝다고 할 수 있다. 왜냐하면 이들은 자신이 가지는 프레임워크 내부에서 비즈니스 로직을 어떻게 잘 모듈화 해서 최대의 효율성을 가지게 하는가에 주안점을 두고 있기 때문이다.

만약 DCOM으로 만들어진 시스템을 리눅스 사용자가 사용하려 한다면?

바로 이것이 기존의 컴포넌트 중심적인 개념들이 가지는 한계점이다. 각자의 Native 방식으로는 아주 효율적이고 강력하게 개발되고 사용되어질 수 있지만 자신의 시스템 경계를 넘어설 경우에는 당면하는 문제점들이 너무나 많다. 즉, 구현된 시스템을 마치 서비스를 사용하듯 자유롭게 연동하기가 어렵다는 것이다.

하지만 웹 서비스를 이용한 SOA는 이들과 근본적인 차이점을 가지고 있다.

시스템을 누구나 이용 가능한 서비스로 간주하고 연동과 통합을 전제로 아키텍쳐를 만든다는 것이다. 즉, 시스템을 개발하면서 처음부터 불특정 다수의 외부 시스템 혹은 고객과의 연동을 고려한다는 얘기이다. 여기서 불특정 다수라는 것이 큰 의미를 가지는데, 이는 어떠한 플랫폼에 있는 사용자가 요청을 하더라도 문제 없이 처리할 수 있도록 한다는 것이다.

그리고 더 나아가 서비스를 이용하기 위해서 특정 기술(EJB, DCOM, CORBA)에 얽매이지 않아도 되기 때문에 매우 유연한 시스템을 만들 수 있다는 장점이 있다.
유연하다는 장점은 별다른 수정 없이 'A' 라는 회사에서 제공하던 서비스를 같은 기능의 'B' 라는 회사에서 제공하는 서비스로 변경할 수 있다는 것이다.

SOA가 주목을 받고 있는 또 하나의 이유는 최근 엔터프라이즈 컴퓨팅의 큰 변화인 'Utility Computing' 과 관련이 있다. Utility Computing은 솔루션이나 시스템을 소비자가 예전처럼 구매하지 않고 기존에 구축된 내용을 이용한 만큼만 비용을 내게 한다는 개념이다.
따라서 손쉽게 사용할 컴퓨팅 자원을 선택하고 교체하려면 이들이 SOA로 구축이 되어야 한다는 것이다. 전문가들은 SOA가 IT 업계가 가야 할 궁극적인 목표인 Utility Computing 으로 가기 위한 중요한 포석이 되어 줄 것이라고 생각하고 있다.

이러한 웹 서비스를 이용한 SOA를 어떻게 설계할 수 있는지에 대한 좀더 기술적인 내용은 다음 글에서 다루기로 하고 마지막으로 우리가 웹 서비스 기술을 어떻게 준비해야 하는지에 대한 간단한 가이드 라인을 제시해 보겠다.
  1. 현재 웹 서비스를 사용하고 있지 않다면? 지금 즉시 테스트용 소규모 웹 서비스 시스템을 구축해야 한다.
  2. 이미 구축한 웹 서비스 시스템이 있다면? 좀더 기능이 강화된 다음 버전으로 개발해야 한다.
  3. 웹 서비스를 사내 시스템 통합 뿐 아니라 타 시스템 연동에도 사용하도록 한다.
  4. 개발자가 아직 웹 서비스에 대해 지식이 없다면? 지금 당장 서점에 가서 웹 서비스 관련 서적을 구해 공부해야만 한다.
즉, 지금 이 시점이 웹 서비스를 통해 이루어 지는 혁명적인 변화에 동참하기 위한 마지막 기차를 탈 수 있는 기회라고나 할까?

지금까지 간단하게 나마 웹 서비스를 이용한 SOA에 대하여 알아 보았다.
아직 구체적으로 기술적인 내용에 대해 짚어 보지는 않았지만 SOA가 무엇이며 웹 서비스 기술이 그 가운데 있음을 확인할 수 있었으리라 생각한다.

만약 지금도 "웹 서비스가 과연 도입될 수 있을까?" 라는 질문을 던지는 분이 계시다면 그분은 위의 4번 항목에 해당되므로 즉시 사고의 전환이 필요함을 말하고 싶다.
Posted by tornado
|
스트럿츠 이디엄
hanbit (2003-12-19 14:19:09)

†역자 주: 본 기사는 원문의 절반도 안되는 내용이나 우선은 역자 자신이 딱 이거다 싶은 내용과 직접 사용해본 내용만을 번역해 놓은 것이다. 스트러츠를 계속 사용하면서 이해가 되는 부분은 차츰 하나씩 번역해나갈 생각이다.
스타일시트나 다른 HTML 자원을 참조할 시에는 <html:link rewrite>를 사용하라

html:link rewrite 태그는 컨텍스트 상대적인 URL을 사용할 수 있다. 또한, 필요하다면 URL을 인코딩하는 것도 가능하기 때문에 컨테이너가 보안을 관리하는 자원의 경우 이용할 수 있다.
예제)<LINK REL=’stylesheet’ HREF=”’<html:rewrite page=’/path/to/CSS”/>’ TYPE=’text/css’>
정적인 페이지 접근을 위한 액션(Action)은 어찌 할 것인가?

모델 2 환경에서 페이지는 깔끔하지만, 처리한 내용만 보여주기 때문에 단순하다고 할 수 있다. 모델 2 환경에서는 액션을 먼저 거친 후, 페이지로 이동을 해야 한다(바로 이 부분이 모델 1에서 웹 프로그래밍 하던 사람들이 고생하는 것으로 역자 또한 그러하다). 그리고 액션은 페이지가 request, session context에 담아서 보낸 정보를 조합하여 나타낼 뷰를 결정해야 한다. 그러나 액션은 뷰의 주소를 모른다(ActionMapping이 알고 있음). 모든 페이지는 하나의 액션 핸들러를 가지고 있어야 한다. 하나의 액션은 다수의 다른 뷰 페이지를 핸들링 할 수 있으며 하나의 페이지는 여러 다른 액션에 의해서 핸들링 될 수 있다. 그러나 하나의 페이지는 적어도 하나의 액션 핸들러를 반드시 가지고 있어야 한다. 여기서 한가지 질문! 그렇다면 static한 페이지에 접근하는 경우, 모두 액션을 가지고 있어야 하는가? 100개의 페이지가 있다면 그것들 모두 액션을 가지고 있어야 하는가? 이런 경우를 대비해서 스트럿츠에는 ForwardAction이라는 액션을 제공한다. 액션 맵핑에 아래와 같이 입력해주면 된다.
예제)<action    name="boardForm"            parameter="/boardcreate.jsp"            path="/boardcreateform"            type="org.apache.struts.actions.ForwardAction"            validate="false"/>
다른 건 다 무시하고, parameter와 type만 살펴보자. Boardcreate.jsp은 새로운 글을 입력하는 페이지로, 실제로 액션이 있어도 아무런 역할을 하지 못한다. 이 경우 org.apache.struts.actions.ForwardAction를 액션 타입으로 지정하고, parameter란에 이동하고자 하는 페이지 주소를 적는다. 이 경우는 /boardcreateform.do를 (*.do으로 서블릿 매핑이 되었다고 가정) 주소창에 치면 우선은 ForwardAction을 통과해서 boardcreate.jsp로 포워드 된다. 이렇게 함으로써 모델 2에서 Action을 거쳐서 페이지로 이동해야 한다는 조건을 만족하게 된다.

액션이 하는 일이 매우 작다면 하나의 액션을 가지고 여러 일을 처리하는 방법을 간구하라

간단히 게시판을 만드는 중이었다. 게시물 삭제, 수정, 수정하는 폼, 등록, 답글 달기, 주석 달기 등 이렇게 하나하나 액션을 만들다 보니 관리해야 할 액션 클래스만 몇 십 개가 되어버렸다. 이렇게 하나의 단위로 묶을 만한 액션들 다수가 존재한다면, DispatchAction의 사용을 고려해봐야 한다. 곧바로 예제를 보겠다.
예제)<action            input="/board/bullcreateform.jsp"            name="bullForm"            parameter="method"            path="/bull"            scope="request"            type="webfx.board.struts.action.BullAction"            validate="false"/>
다른 액션 맵칭하는 방법과 거의 다르지 않다. 여기서 특이하게 볼 내용은 parameter이다. 그리고 BullAction의 코드는 아래와 같다.
…public BullAction extends org.apache.struts.actions.DispatchAction {	public ActionForward create(		ActionMapping mapping,		ActionForm form,		HttpServletRequest request,		HttpServletResponse response)		throws Exception {	…};	public ActionForward remove(		ActionMapping mapping,		ActionForm form,		HttpServletRequest request,		HttpServletResponse response)		throws Exception {	….	}	등등…}
이 소스에는 execute라는 메소드가 없다. 단지 Method Signature가 이름을 제외하고 execute와 다른 create, remove 함수가 있다. 그리고 이 액션은 org.apache.struts.actions.DispatchAction을 상속했다. 우리가 parameter로 지정한 값은 request로 넘어올 파라미터 이름이다. 그리고 이 파라미터에 우리가 실행시키고자 하는 메소드 명을 지정하면 그 메소드가 실행된다. 예를 들어 /bull.do?method=create라고 실행시켰다면 BullAction에서 create 함수를 실행시키게 된다. 이처럼 관리하기 힘들 정도로 액션이 늘어날 경우에는 DispatchAction을 사용하는 것도 고려해봐야 한다.

데이터와 Value Objects을 교환하기 위해서 populate 유틸리티를 사용하라

Jakarta.apache.org 사이트에 있는 Commons에 속한 BeanUtils를 말하는 겁니다. BeanUtils.populate()와 describe() 메소드는 beans와 임의 타입 간의 데이터 전송 사용을 위해서 사용될 수 있다. 요구되는 것은 대응되는 public 형의 프로퍼티 이름들과 네이티브 타입이다. Wrapping Object 즉, Integer 같은 것들은 지원이 되지만 그 외의 타입은 지원되지 않는다(예, Date).

describe 메소드는 소스 빈을 스트링 값을 가지고 있는 맵으로 만든다. populate 메소드는 그러한 맵을 읽어서 타겟이 되는 빈에 프로퍼티를 적용하는 역할을 한다. 만약 타겟 타입이 스티링이 아니라면 필요한 타입으로 변경이 된다. 만약 변환이 실패하면 예외가 발생한다. 다음이 두 빈(Bean) 간의 데이터 이동하는 소스이다.
BeanUtils.populate(target, BeanUtils.describe(source));
몇몇 경우에 필요한 만큼만 조절한 ActionBean에서 또한 조절된 값을 가지고 있는 Map을 만들기 위해서 커스터마이징한 describe 메소드가 필요할 때가 있다. 다른 값들 (즉, 지원되지 않는 타입)은 직접 세팅해 줄 수 있다.
BeanUtils.populate(target, source.describe());tartget.setDate(source.getDateBinary());
BeanUtils을 직접 이용하는 것보다 유틸클래스를 하나 만들어, 그곳에서 BeanUtils 클래스를 이용하도록 만드는 게 더 좋을 것이다. 예를 들면 아래와 같다.
valueUtils.populate(ValueObject target, ActionForm source);valueUtils.populate(ActionForm target, ValuteObject source);
공통적으로 사용되는 속성들에 대한 객체를 만들어 사용하라

웹 애플리케이션 안에서 애플리케이션에 전체적으로 걸쳐서 사용되어야 하는 속성이 있다. 사용자 정보, 북마크, 메뉴 세팅, 다른 프로퍼티 등등이 이것에 속할 수 있다. 이때에는 이런 것들을 각각 따로 관리하는 것보다 이런 것들을 한꺼번에 래핑하는 객체를 만들어서 사용하자.

애플리케이션을 위한 Base Action을 사용하라

애플리케이션 액션들은 몇몇 기본적인 작업을 처리한다. 이러한 태스크를 일관적으로 구현하기 위해, 애플리케이션의 다른 액션들이 서브클래싱하여 사용할 수 있는 Base 클래스를 이용하자! 만약 개개 액션의 execute 메소드 안에서 중요하게 처리되어야 할 일이 있다면 서브 클래스들이 execute() 메소드를 통해서 실행시킬 추상 메소드를 사용하는 것이 좋은 접근 방법이다. Base 클래스는 기본적으로 자신이 해야 할 일을 하고 그것이 모두 잘 처리 되었을 때, 새로운 메소드를 실행시키고 그 결과를 리턴한다. 이 부분 때문에 새로운 메소드의 서명을 변경할 수 있다.
Public ActionForward execute(ActionMapping mapping,				ActionForm form,				HttpServletRequest request,				HttpServletResponse response)			throws IOException, ServletException {		// Application specific bevaviour		// if evevrything is kosher call subclass		return (executeAction(mapping, form, request, response, myParameter))}
executeAction은 Base 클래스의 추상 클래스이다.

이중으로 submit이 일어나는 것을 막기 위해서 Action Token을 사용하라

스트럿츠의 액션에 one-use tokens을 만들어 담는 메소드들이 있다. 폼이 작성될 때 세션에 토큰이 위치하게 되고, 이 토큰은 HTML 폼에 hidden 프로퍼티로 포함된다. 그 폼이 리턴 될 때 토큰은 validation이 된다. 만약 validation에 실패하면 벌써 그 폼은 submit이 된 것이므로 사용자는 그에 대한 알림 메시지를 받을 수 있다.
  • saveToken(request)
  • on the return trip
    • isTokenValid(request)
    • resetToken(request)
스트럿츠를 이용한 웹 애플리케이션 개발 사이클
  1. 화면 설계서를 개발한다. (화면 요구사항 설계)
  2. 화면 요구사항을 만족하기 위한 Helper 클래스를 개발한다. (value object)
  3. 워크플로우 요구사항을 개발한다. (화면 이동 등의 스토리보드 작성)
  4. 워크플로우 요구사항을 만족시키기 위한 ActionMapping을 개발한다.
  5. ActionMapping을 사용하여 워크 플로우를 검증하기 위한 Stub JSP 페이지를 작성한다.
  6. ActionMapping에 의해 호출 되는 액션을 개발한다.
  7. Stub Jsp를 작성한다.

'JAVA > JSP_Servlet' 카테고리의 다른 글

[Struts] MessageResource 여러개 쓰기  (0) 2004.04.01
[펌] MVC 모델과 Observer 패턴  (0) 2004.04.01
[펌] JavaServer Faces 입문  (0) 2004.04.01
[펌] Jakarta Digester 학습하기  (0) 2004.04.01
[펌] Torque프로젝트 사용기  (0) 2004.03.31
Posted by tornado
|
사용성을 만족시키는 인포메이션 아키텍처
hanbit (2003-12-26 11:45:52)

로우 로젠펠드(Lou Rosenfeld)는 인포메이션 아키텍처 컨설턴트이자 『Information Architecture for the World Wide Web, 2nd Edition』의 공동저자이다. 스티브 크럭(Steve Krug)는 웹 사용성 전문가이며 『Don't Make Me Think』의 저자이다. 이 둘은 각각 자신이 속한 분야에서 세미나를 이끄는 등 왕성한 활동을 하고 있으며 심포지움에서 연속 세션을 맡아 함께 진행하기도 했다.

이에 오라일리에서는 이 둘을 만나 그들이 함께 해나갈 조인트 세미나와 웹 사용성과 인포메이션 아키텍처에서 흔하게 빠지는 함정 및 오늘날 웹 산업 현황에 대해 의견을 나누었다.

스튜어트: 어떻게 해서 두 분이 함께 일을 벌이게 되셨나요?

크럭: 우리 두 사람이 같이 강연을 한다는게 꽤 괜찮아보이지 않나요? 실제로 사람들이 제 웹 사이트에 요청했던 바를 토대로 몇몇 도시에서의 워크샵을 계획하고 있긴 했습니다. 그러다가 로우가 제 일정에 대해 물어왔고 서로 이런 저런 이야기를 나누다가 ‘같이 강연을 해보는 것은 어떨까’라는 결론을 내리게 되었지요. 평소에도 저는 로우의 성실한 작업 스타일과 작업에 임하는 태도에 대해 칭찬을 아끼지 않았던 터라 우리 둘이 함께 강연을 한다는 것이 아주 근사하게 생각되더군요.

로젠펠드: 우리 작업 스타일이 서로 비슷하기 때문에 함께 일하는데 있어 전혀 거부감이 없었습니다. 둘 다 철저한 원리원칙 주의자도 아닌데다가 서로 재미있게 일하는걸 좋아하기 때문이죠. 사실 스티브는 아주 재밌는 사람입니다. 전 옆에서 그가 계속해서 재밌게 일할 수 있도록 격려해주기만 하면 되는 걸요.

스튜어트: 그래도 세미나는 두 분이 따로따로 하시는 걸로 알고 있습니다. 각자의 세미나에 같은 대상들을 끌어들일 생각이십니까?

로젠펠드: 지금까지는 등록자의 절반 정도가 두 세미나에 동시등록을 했습니다. 우리 둘이 다루는 주제가 상호보완적이어서 두 세미나에 등록했는지, 그냥 동시 등록의 경우 주어지는 할인 혜택 때문인지, 등록자들의 저의는 잘 모르겠지만 말입니다.

스튜어트: 사용성(usability)과 인포메이션 아키텍처! 제 생각엔 두 개가 똑같아 보이는데요.

크럭: 네, 정말 묘하게도 (사실 정확하게 알고 있는 사람은 거의 없지만) 그 두 개는 똑같은 것이랍니다. : ) (당황한 인터뷰어의 눈치를 살피며) 농담입니다. 농담! 분명 겹쳐지는 부분이 있긴 합니다만 절대 겹쳐질 수 없는 나름의 독자적인 영역이 있지요. 정보를 조직하는 구성 및 메커니즘을 실제로 설계하여 구축하는 것이 인포메이션 아키텍처라면 유저빌리티는 이와는 달리 이미 형성된 토대를 비판하여 허물어뜨리는 것에 가깝다고 할 수 있으니까요. 물론 이런 비판은 개선의 일환으로 시도되는 것이구요.

어떤 때는 내가 하고있는 일을 가장 잘 표현해주는 단어가 ‘쇼 전문가’라고 생각될 때가 있습니다. 흥행 전에 쇼를 관람하고 어떻게 하면 쇼가 더욱 흥미진진하게 보이는지를 연구하는 쇼 전문가 말입니다. 이런 사람들은 정말 보는 능력이 탁월해야 합니다. 웹 프로젝트를 해본적이 있다면 제 말이 어떤 뜻인지 더 확실하게 알 수 있을 겁니다. 내부의 정치적 분쟁에 개입되어 있지 않고, 외부인이자 최종 사용자의 입장에서, 상황을 판단하고 평가할 혜안을 갖고 있어야 하죠. 즉 만든 사람이 아니라 사용할 사람의 눈으로 판단할 지각을 가지고 있어야 한다는 것입니다.

물론 두 영역 간에 겹쳐지는 부분이 분명히 있어서 사용성 영역에서 너무 복잡하거나 전문적이지만 않다면 클라이언트에게 IA 문제에 대한 조언을 잘 해줄 수 있습니다. 물론 인포메이션 아키텍처 전문가들도 사용성에 대해 좋은 조언을 많이 해줄 수 있구요. 자신의 전문성이 언제 한계에 도달하는지 그 때를 아는 것이 중요하지요.

로젠펠드: 그렇습니다. 분명 훌륭한 인포메이션 아키텍처 전문가들은 사용성에 대해서도 잘 알고 있습니다. 하지만 프로젝트의 크기 및 복잡성에 따라 사용성 문제는 개입될 수도 그렇지 않을 수도 있다고 봅니다. 하지만 제 개인적으로는 사용성 전문가들이 적극적으로 개입되는 것을 추천하지만 말이죠.

스튜어트: 사용성에서 가장 흔하게 범하는 실수로는 무엇이 있습니까?

크럭: 정말 놀랍게도 홈페이지를 만든이가 누구인지, 무엇을 위한 사이트인지와 같이 아주 기본적인 정보를 아직까지도 제공하지 않는 홈페이지가 있습니다. 페이지 레이아웃(사이트 전체에 걸쳐 사용된 페이지 템플릿)의 시각적 계층이 잘못되어 컨텐츠를 말해주는 레이아웃도 전혀 엉뚱하게 되어버리는 경우도 있구요. 가장 고질적인 문제는 페이지에 너무 많은 것을 올려놓으려 한다는데 있습니다. 그 결과 눈에 확실히 띄는 것 없이 모두가 다 비슷하게 보이게 되지요.

스튜어트: 그렇다면 IA의 경우에는 어떻습니까?

로젠펠드: 사이트가 작으면 제자리에 있지 않은 것들을 다시 말쑥하게 수정하는 것이 쉬운편이죠. 실수가 쉽게 용인되고 쉽게 수정할 수도 있으니까요.

제가 우려하는 바는 보다 크고 복잡한 사이트들입니다. 이런 사이트에는 기업의 조직표와 부서별 정책이 반영됩니다. 대부분의 경우, 사용자들이 이와 같은 조직표를 암기하고 이를 지침으로 삼아 방대한 사이트의 컨텐츠를 보기 위해 서핑을 하지는 않을 것으로 생각됩니다. 실제로 큰 실수라고는 할 수 없겠지만, 기업이라는 현실에서는 가장 흔하게 일어나는 불행한 일임에는 틀림없죠.

아주 접근하기 어려운 문제이기도 한 것으로 웹 컨텐츠는 자연스럽게 사업 단위 사이의 경계선을 반영하는 "사일로우"에서 커집니다. 어떻게 이 기업급 웹 컨텐츠를 보다 더 사용자에게 친화적인 방식으로 재조직할 것인가? 그리고 어떻게 새로운 사용자 중심의 정보 골격구조를 지원하도록 기업 그 자체를 변화시킬 것인가? 이런 것들이 이번 세미나에서 접근하는 이슈들입니다.

스튜어트: 언제나 간단할수록 더 좋습니까?

크럭: 아닙니다. 물론 "언제나"는 아니지요. 어떤 상황에서는 복잡하고, 심지어 과도하게 붐비는 것이 더 좋을 때도 있습니다. 그러나 명료성의 경우에는 언제나 더 간단할수록 좋습니다. 사람들은 종종 간결함과 명료성을 혼동해서, 복잡하더라도 명료한 것이 있을 수 있다는 것을 잊어버립니다. 여러분이 듣게 되는 말을 정리하면 다음과 같습니다. "더 간단하게 만들면, 파워 유저들은 화를 낼 것이다." 그러나 나의 경험으로 보아 파워 유저들은 절대로 명료성 때문에 화를 내지는 않습니다. 사실 그들은 누구보다도 명료성을 높이 평가합니다. 그들이 싫어하는 것은 일을 파악하느라 시간을 낭비하는 것입니다. 그 이유가 그 사이트를 구축한 사람들이 명료하게 만드는 수고를 하지 않았기 때문에 말입니다.

스튜어트: 디자이너들이 아주 복잡하거나 아주 많은 정보를 다루는 사이트를 다룰 때 반드시 생각해야 할 것이 있다면 어떤 것들이 있지요?

로젠펠드: 많은 사용자들에게 혜택을 주는(페이지 안내에서부터 최적 탐색 결과에 이르기까지) "가벼운" 아키텍처 접근법이 많이 있습니다. 게다가 개발하고 구현하는데 많은 비용이 들지 않습니다. 이런 것들에 재빨리 참여하면 시간을 벌 수 있을 뿐만 아니라 시각적 편의를 증진하면서 더욱 위협적이고 장기적인 도전에 어떻게 대처해야 할지 결정할 수 있습니다.

또 다른 사항으로는 윤리적 속임수를 사용하는 것입니다. 주의깊게 생각해서 계획하면, 보통 자기가 속한 부서의 웹 컨텐츠, 사용자, 그리고 정략에 초점을 맞추고 있는 사람들을 속여서 전체 조직의 이익에 초점을 두도록 만들 수 있습니다. 예를 들어 나는 가끔 청중 분류 과정을 슬쩍 돌려서 조직표에 전혀 관련이 없는 당면과제 샘플(subject samples)들을 마련하는데 초점을 맞출 수도 있다고 생각합니다. 그래도 정책 결정자들은 여전히 모를 것입니다(none the wiser).


효율적인 웹사이트 구축을 위한 인포메이션 아키텍처

참고 도서

효율적인 웹사이트 구축을 위한 인포메이션 아키텍처
피터 모빌(Peter Morville), 루이스 로젠펠드(Louis Rosenfeld)




스튜어트: 사용성이나 인포메이션 아키텍처에 순서를 매길만한 규칙이 있습니까?

크럭: 글쎄요, 저는 "생각하게 만들지마(Don't make me think)"라는 메시지를 유달리 좋아합니다. 그리고 다음과 같이 최우선으로 삼을 좋은 원칙을 발견했습니다. 일에 몰두하라! 그리고 그것을 사람들에게 계속 보여주라! 스스로 명백해져서 이해가 될 때까지 말이다! 사용자들의 머리에 떠 다니는 의문표를 모조리 없애 버리자!

그렇지만 대부분의 경우, 저는 규칙보다는 태도와 전략을 가르치려고 합니다. 잘 작동하는 사이트를 디자인하는 작업은 언제나 아슬아슬한 작업입니다. 공간의 활용을 최우선으로 해서 청중과 출간인 모두 그들의 목표를 완수하도록 돕습니다. 조감을 적절하게 조절하고 포맷해서 충분하게 유용한/적절한 주목을 받도록 해 줍니다. 항상 여러분은 수 많은 변수들에 대해서 최적화하려고 시도합니다(보통 너무 많습니다). 동시에, 저것을 너무 많이 보여주지 않고 이것을 충분히 보여줍니다. 그리고 보편적 규칙이 아주 많이 존재하지는 않는데, 한 디자인 맥락에서 잘 작동하는 해결책이라도 다른 디자인 상황에서는 작동하지 않기 때문입니다.

로젠펠드: 규칙은 인포메이션 아키텍처(IA)에서도 잘 작동하지 않습니다. 사실, 까다로운 IA 질문에 대한 "정답"은 "~에 따라서"입니다. 머리에 떠 오르는 유일한 "규칙"은 파레토 원리(Pareto Principle)라는 것인데, 이른바 80/20 규칙이라고 알려져 있습니다. 이 규칙은 실제로는 전혀 규칙이 아닙니다.

파레토 규칙이 IA에서 작동하는 방식은 기본적으로 상당히 많은 사용자들이 가능한 모든 아키텍처 접근법에서 몇 가지 선택으로부터 혜택을 입을 것이라는 것입니다. 그래서 여러분과 그 사용자들에게 돈을 지불한 대가(bang for your buck)를 최대로 돌려주는 가장 좋은 방식을 몇 가지 선택합니다. 파레토 규칙에는 다른 변형이 많습니다. 예를 들어, 가장 흔한 탐색 몇 가지는 수 없이 많은 탐색으로 구성됩니다(그리고 수작업으로 개발된 "최적 일치(best bet)" 결과로 접근할 수 있습니다). 믿지 못 하시겠다면 여러분의 탐색 기록을 점검해 보세요.

스튜어트: 브라우저의 역사에서 오늘날 웹 디자이너들은 얼마나 거슬러 올라가 신경써야 할까요? 테스트하기를 추천하는 가장 오래된 브라우저는 무엇인가요?

크럭: 정말 어려운 질문이군요. 뭐라고 말해도 곤란하겠네요. 개인적으로 전자우편 클라이언트를 좋아하기 때문에, 저는 거의 대부분 구식 Netscape 4.77 브라우저를 여전히 사용하고 있는데, 어떤 사이트는 열리지 않습니다(페이지 상단에는 로고가 보이지만, 나머지는 비어 있지요). 그러나 내가 구형 브라우저를 사용하기로 결정했기 때문에 그것은 제 개인적인 문제라는 것이죠. 그래서 그런 일이 일어나더라도 그 사이트의 개발자를 원망하지는 않습니다.

그러나 어떤 사람들은 예전 브라우저의 사용 고집합니다(회사 정책, 정말 오래된 하드웨어, 혹은 새로운 브라우저를 내려받을 수 없을 정도로 느린 연결 때문에), 혹 어떤 사람들은 오프-브랜드 브라우저를 정말 좋아합니다. 점차 시대에 뒤떨어지고 있다는 사실(graceful degradation)을 완전히 인지하고 있으면(구형 브라우저에서도 완전하지는 않지만, 쓸모 있는 경험을 제공할 수 있다는 확신을 가지고), 아마도 괜찮을 것입니다. 그러나 또다시, 그것은 종종 교환관계에 봉착합니다. 모든 브라우저를 지원하는 데 얼마나 많은 노력을 투입할 수 있는가?

스튜어트: 사용자 테스트가 중요하다는 것은 누구라도 압니다. 이를 성공적으로 완수하는 열쇠는 무엇입니까?

크럭: 가장 중요한 일은 최대한 간단하게 사용자 테스트를 유지하여 실제로 수행할 수 있도록 해 주는 것입니다. 디자인 과정에서 일찍 사용자 테스트를 시작해서, 일정 간격으로 사용자 테스트를 하고, 테스트 중에 발견된 문제들을 고치는 테스트는 절대 간과할 수 없을 귀중한 단계입니다. 그러나 여전히 많은 사람들은 "유효한" 샘플을 얻기 위해 다섯 혹은 여덟 또는 열 두 명의 사람만 테스트하면 된다고 생각합니다. 그것은 완전히 잘못된 태도입니다. 그렇게 되면 결과적으로 테스트를 단 한번으로 끝내게 되고, 디자인이 거의 끝나갈 무렵에야 테스트를 하게 됩니다. 이렇게 테스트를 하기보다는 여러 사람을 한 번(두 번이나 세 번도 좋음)에 끌어 들인 후, 자유로운 분위기를 유지하면서 매 3주나 4주 마다 사용자 테스트를 해야 하죠.

스튜어트: 로우(Lou)씨, 왜 기업급 설정에 초점을 두고 있습니까? 뭐 "스타 트랙(Star Trek)" 집착 같은 것일까요?

로젠펠드: TV에서 "The Enterprise"라는 이름은 잘못 붙인 겁니다. 왜냐하면, 거대하고 복잡한 개체가 효율적으로 실행되고 있기 때문이지요. (물론 커크(Kirk)는 제외하고) 자아를 문 앞에 버려두고 온 고도의 능력을 가진 정책 결정자들로 이루어진 소규모 간부 그룹에 의해서 말입니다. 그들이 원하는 모든 정보는 거대한 인공 지능 존재에 의해서 즉시 열람되고, 조합되고, 분석되고, 다듬어져 튀어 나옵니다. 이 존재는 분명히 윈도우즈보다는 더 안정적인 어떤 것 위에서 실행 중인 것 같습니다. 현실세계의 기업은 거대하고 복잡하다는 점에서만 비슷합니다. 현실의 기업은 효율적이지 않아서, 자주 웹 컨텐츠를 다시 또 만들어내고 또다시 소프트웨어를 중복 구입합니다. 현실세계의 기업은 어쩔 수 없이 정치적이라서, 막강한 권력을 쥐고 있는 부사장이 디자인을 결정하는 경우가 자주 있습니다. 자율적인 비즈니스 단위 전쟁의 틈바구니에서 현실세계의 기업은 중앙 집권(예, 집행부) 때문에 조율되지 않습니다.

이렇게 이리 저리 하다보니, 사용자들은 대상에서 제외됩니다. 그래서 사용자의 필요를 만족시키기 위해 디자인되기 보다, 기업급 정보 골격구조는 조직적으로 자라나서 조직표의 정치적인 경계선을 반영합니다. 왜 내가 이런 이슈에 집착하는가? 음, 개인적으로, 나는 소형의 단순한 사이트에 대해서 골격구조를 디자인해 주고, 수표를 집어 들고 돌아와서, 편한 마음으로 자는 것을 더 좋아합니다. 그러나 지난 삼년간 대화를 나누어 본 잠재고객(prospect)과 단골고객(client)은 거의 누구나 조직의 기업급 정보 골격구조를 개선하는 도전과제에 접근하지 못하는 것을 불평했습니다. 그래서 집착은 그들이 하는 거지요. 세미나는 그저 도와주려는 나의 노력일 뿐입니다(그렇다고 세미나 중에 밖에 나가지는 마시기 바랍니다).

스튜어트: 스티브(Steve)씨, 왜 당신은 로우(Lou)씨처럼 이런 "기업적" 맥락에 집착하지 않습니까? "기업급 사용성" 역시 큰 문제가 아닌가요?

크럭: 사용성 문제는 IA 문제보다 정치적인 부담이 약간 더 적은 것으로 드러났습니다. IA는 조직에서 서로 다른 부분들이 웹 사이트에 의해 어떻게 표현되어야 할 지에 대해 더 직접적인 충격을 줍니다("방송 시간"의 할당). 그리고 IA 처리과정은 기업 자체가 조직되어 있는 방식에서 기존의 문제들과 불합리를 훑는 경향이 있습니다. 특히 내부 조직이 외부의 청중에게 아무런 의미도 없는 영역에서 말입니다.

스튜어트: 사용성과 IA에서 다자이너들에게 가장 큰 도전과제는 무엇이라고 보십니까?

크럭: 충분히 잠을 자는 것입니다. 사용성에서 가장 큰 문제는 종종 수정할 시간은 있으나, 수정에 무엇이 필요한지 모르는 것입니다. 사실상 대부분의 웹 디자이너들(그리고 개발자들)은 오히려 시간이 모자랍니다. 다른 큰 도전과제는 일에서 어느 정도 거리를 두는 것입니다. 한 프로젝트에 몇 주(몇 달은 물론이고)동안 매달리게 되면, 다시 되돌아와 사용자의 관점에서 그 프로젝트를 바라보는 것이 거의 불가능합니다. 그 때문에 프로젝트에 참여한 사람들이 자신들이 만든 구축물을 다른 사람들에게 사용해보도록 하고 그들이 사용하는 것을 꾸준히 지켜 보는 일(이른바 "사용성 테스트"가)이 아주 중요한 도전과제가 되지요.

로젠펠드: 디자인을 하는 사람들에게 있어서 가장 큰 도전과제는 자신의 작업에 드는 비용을 정당화하는 문제라고 생각합니다. 어느 경우에나 항상 문제가 뒤따르게 되는데 그것이 바로 투자 수익(ROI, return on investment)입니다.

IA에 대해서 특별히 확실한 투자수익(ROI) 분석 사례는 보지 못했지만, 비용을 정당화하기 어려운 기타 애매한 영역의 가치를 이해하듯이 점점 더 많은 사람들이 IA의 내재적인 가치를 똑같은 방식으로 이해하는 것 같습니다. 예를 들면 시장판매(marketing) 예산이 그렇습니다. 그래서 나는 낙관합니다.

스튜어트: 워크샵에 참석한 사람들이 워크샵이 끝난 후에는 어떤 것들을 가지고 나가길 바라시나요?

크럭: 제 워크샵에 다음과 같이 부제를 붙이고 있습니다. "8시간 안에 사용성 전문가처럼 생각하는 법을 배우자!"라고 말입니다. 그리고 이 선전문구를 자신 만만하게 믿습니다. 나의 목표는 사람들이 더 나은 사용성 감각을 가지고, 사이트를 구축하면서 제기되는 질문에 대한 해답을 알도록 하는데 있습니다. 스스로 사용성 테스트를 하는 법, 그리고 발견된 문제의 해결에 접근하는 법을 알려 주는 것입니다

로젠펠드: 저도 정말 그러기를 바랍니다.

심각한 것은 내가 대화를 나누어 본 사람들은 생각보다 훨씬 더 절망감을 느낀다는 겁니다. 그들의 절망은 종종 반복적인 난관주의나 선임관리자의 무지에 대한 반응입니다. 선임 관리자들은 기업급 정보 골격구조를 다시 디자인하는 도전은 별 문제가 되지 않는 아주 쉬운 일이라고 생각합니다.

제 세미나에 참석한 사람들이 즉시 혹은 빠른 시일 내에 구현할 수 있는 실용적인 디자인 개념을 가지고 떠났으면 합니다. 장기적으로 작업할 현실적인 계획 그리고 목표와 균형을 이루어서 말입니다. 그들이 어느 "교과서"적 연구 방법이 기업적 맥락에서 작동하고 작동하지 않는지 더 좋은 감각을 가지기를 바랍니다. 그리고 한가지 작업틀을 가지고 돌아가 조직에서 기업적 팀을 이루어 IA 문제들을 해결하는데 지침이 되기를 바랍니다.

스튜어트: 바깥 경기를 생각해볼 때 어떻습니까? 사용성과 IA에 돈을 쓸 능력이 될 사람들이 있을까요?

로젠펠드: 불경기이기는 하지만, 적어도 미 연방 정부는 IA에 어느 정도는 지출을 하고 있습니다. 왜 그런지는 묻지 마세요. 거대 기업들초차도 IA 문제들에 접근하는데 필요한 최소한의 자금을 모으고 있는 듯 합니다. 그냥 그들은 소프트웨어 도구들에다 돈을 지출하려고 하지 않을 따름입니다. 전문가를 초빙함으로써 그런 투자가치를 높이려고 더욱 더 노력하고 있습니다. 사실, 많은 기업들이 현재 전업제 IA 전문가들을 간부로 채택하고 있다는 사실에 놀랐습니다. 이런 것들을 볼 때, 낙관적이란 생각이 들지 않습니까?

크럭: 상당히 많은 사람들부터 들은 이야기에 의하면 경기가 여전히 아주 힘들다고 합니다. 이제서야 생각보다 많은 회사들이 사용성에 노력을 기울여야 한다는 사실을 깨닫고 있지만, 프로젝트 예산의 표준 라인에 들기에는 여전히 거리가 멀다고 생각합니다. 들은 바로는 많은 회사들이 관심을 표명하고 사용성에 관하여 문의하지만, 실제로 거기에 돈을 쓰는 결정을 내리는데 이르지는 못하는 것 같습니다.

사용성에 돈을 쓰는 회사들은 웹에 방대한 투자를 하고 있는 거대 회사들이고, 그 보다 작은 회사에서는 관리자들이 이전에 사용성에 경험이 있고, 그냥 비용을 지출하는 대신, 디자인 과정을 실제로 거대회사들 보다 더 쉽고 빠르게 만들 수 있다는 것을 알고 있는 경우에 사용성에 비용을 지출합니다.
Posted by tornado
|