반응형
IBM 소프트웨어 엔지니어 (마음은 게이머)인 Scott Clee가 테트리스 게임 모델을 재사용 가능한 자바 빈 컴포넌트로 포장하는 간단한 방법을 소개한다. 일단 게임의 구성 요소들이 자바 객체들로 나누어지면 완전한 게임 모델 빈을 형성하도록 재조립될 수 있고, 실제로 어떤 테트리스 GUI에도 결합될 수 있다. forum에서 이 글에 대한 여러분의 생각을 저자와 다른 독자들과 공유하기 바란다.

-참조 : http://www.ibm.com/developerworks/kr/library/j-tetris/

테트리스 게임의 구성 요소들을 자바 객체로 나누어 재사용 가능한 자바 게임 컴포넌트로 만드는 방법

한 친구가 자신은 새로운 프로그래밍 언어를 배울 때마다 그 언어를 사용해 테트리스 게임을 작성하는데 도전한다고 말한 적이 있다. 이러한 전통하에, 내가 처음 자바 언어를 사용한 프로그래밍 법을 배웠을 때 나도 같은 시도를 해 보기로 했다. 나의 첫번째 시도는 하나의 완전한 게임이긴 했지만 매우 간단하고 흉한 것이었다. 시간이 가고 내가 자바 설계와 개발에 더 많은 경험을 얻음에 따라 나는 GUI에서 게임 모델을 분리시켜 (Swing 컴포넌트와 유사하게) 테트리스 빈을 만들 수 있다는 사실을 알았다. 그래서 나는 그것을 해 보기 시작했다.

이 글에서 나는 테트리스 빈을 구축하고 구현하는 방법을 안내하겠다.

테트리스는 자바 객체로 표현될 수 있는 몇 개의 구성 요소를 가지고 있다.:

  • The Tetris pieces 테트리스 조각
  • 조각을 가지고 있는 테트리스 판
  • 판 위의 조각 제어, 점수 관리 등을 하는 게임

이 요소들 각각을 좀 더 자세히 살펴보자.

  • 각 요소는 정확히 네 개의 블록으로 구성되어 있다.
  • 조각 내의 각 블럭은 테트리스 판 내에 (x.y) 좌표를 가지고 있다.
  • 각 조각은 0, 2, 4의 회전율을 가지고 있다.
  • 각 조각은 L, J, S, O, I, Z, 혹은 T 모양을 지닐 수 있다.


그림 1. 각 테트리스 조각에 네 요소가 필요함 : 블록, (x,y) 좌표, 회전율 및 모양
Four elements of each Tetris piece
테트리스 빈으로 무엇을 할 수 있을까?

다음은 테트리스 빈을 만든 후 내가 수행한 몇 가지 일들이다.
  • 빈의 두 인스턴스를 연결시켜 대결 게임을 만들다.
  • Netris라는 이름을 가진, 최초의 Psion Netpad용 테트리스 게임을 만들다
  • 빈을 애플릿에 통합시켜 브라우저와 호환되는 테트리스 게임을 만들다.

첫번째 두 아이템은 매우 간단한 시스템을 사용해 구현될 수 있다. 각 조각에 대해 중앙 블록을 선택하고 이 블록의 (x,y) 좌표를 저장하면, 조각 내의 나머지 블록들을 이 블록을 중심으로 한 상대 좌표로 저장할 수 있다. 이 방식은 중앙 조각에 대한 상대 블록으로 모양을 저장함으로써 조각의 어떤 형태도 기술할 수 있게 해준다. 중앙 지점은 java.awt.Point로 저장될 수 있고 상대 좌표는 java.awt.Point 배열에 저장될 수 있다. 좌표 계산을 쉽게 하기 위해, 중앙 조각을 (0,0) 상대 좌표를 가진 블록으로 저장할 수 있다.

이 시스템은 또한 조각의 회전을 계산할 때 더 쉽다. 간단한 행렬 조작을 사용하여 단순히 y좌표를 x 좌표로 바꾸고 x 좌표는 y 좌표의 마이너스 값으로 바꾸면 조각을 시계방향으로 90도 회전시킬 수 있다. 우리는 중앙 지점을 중심으로 상대 좌표를 사용하고 있기 때문에, 여기에서도 마찬가지로 할 수 있다:



temp = x;
x = -y;
y = temp;

여러분은 또한 시계방향 회전을 3번 적용하면 조각을 시계 반대 방향으로 90도 회전시킬 수 있다. (믿지 못하겠다면 한 번 해보기 바란다.)

마지막으로, 모든 조각이 동일한 회전율을 가지는 것은 아니므로, 이 문제를 보충하기 위해 회전 기법을 체크해 보아야 할 것이다.

우리는 모든 유형의 조각을 표시하는데 동일한 TetrisPiece 클래스를 사용하기 때문에 이들을 구분할 방법이 필요하다. 이를 위해 우리는 몇 개의 정적인 int 생성자를 사용하여 다른 유형들을 표시하고 지역 변수가 조각의 유형을 저장하도록 한다. 다음은 이 생성자들 중 하나의 예이다:



public static final int L_PIECE = 0;

조각을 테트리스 판 위에서 이동시킬 것이므로 이를 위한 이동 메소드를 제공해야 한다. 몇 가지 이동 (이미 가능한 한 제일 오른쪽 끝에 와 있는데 다시 오른쪽으로 가려는 시도)은 불법적일 수 있다. 따라서 우리는 모든 이동 요청을 확인할 필요가 있다. 우리는 참조를 저장할 테트리스 판에서 이것을 구현할 것이다. 따라서 우리 클래스의 생성자는 여기에서 두 가지 매개 변수를 가질 것이다: 첫번째는 만들어진 조각의 유형이고, 두번째는 테트리스판에 대한 참조이다. 생성자에서 우리는 initalizeBlocks()이라는 private 유틸리티 메소드를 호출할 것인데, 이 메소드는 조각의 상대 좌표값을 각각의 조각 유형에 설정할 것이다.

이동이 합법적인지를 체크하는 간단한 방법은 판에서 조각을 떼내어 원하는 방향으로 이동시킨 후 맞는지 보는 것이다. 맞으면 조각을 보드의 새 위치에 둔다. 그렇지 않으면 이동을 취소하고 원래 있던 자리에 다시 둔다. 반환되는 값은 그 결과에 따라 true (이동이 맞으면)나 false(이동이 맞지 않으면)가 될 것이다.

좀 더 주의를 기울여야 할 이동의 한 유형은 조각이 떨어지는 경우이다. 떨어진다는 것은 조각이 판의 제일 아래쪽으로 바로 내려간다는 의미이다. 이를 위해 우리는 더 이상 움직일 수 없을 때가지 조각을 아래로 계속 이동시키는 while 루프가 필요하다. 그러면 조각은 그 위치에 배치될 것이다.

조각에 적용될 수 있는 다양한 이동들을 구별하기 위해 우리는 다음 예제에 나타난 것과 같이 몇 가지 추가적인 static int 생성자를 사용할 것이다.:



public static final int LEFT = 10;

조각이 맞는지 보기 위해 나중에 willFit() 메소드가 TetrisBoard 클래스에서 구현된 것이다.

마지막으로 TetrisPiece 클래스를 포장하기 위해 우리는 중앙 지점과 상대 좌표와 같은 몇 가지 변수에 대한 getters와 setters, 그리고 무작위 유형의 TetrisPiece 인스턴스를 반환할 getRandomPiece()라는 정적인 메소드를 가진다.

TetrisPiece 클래스를 포함한 완성된 소스를 참고 자료에서 다운로드받을 수 있다.

테트리스 판은 빈 블록과 색깔 있는 블록을 가지고 있는 2D 격자판으로 생각할 수 있다. 다양한 유형의 테트리스 조각들이 int 생성자에 의해 구별되기 때문에, 우리가 해야 할 일은 빈 블록의 값을 정의하는 것 뿐이고 우리는 판을 2D int 배열로 저장할 수 있다. 이 방식을 사용하면 판 내의 빈 블록은 다음에 의해 표시될 것이다.:



public static final int EMPTY_BLOCK = -1;

유연성을 유지하기 위해 판의 크기를 가변적으로 하겠지만 이것을 생성자 내에 정의할 것이다. 따라서 생성자는 열과 행의 수를 나타내는 두 ints를 받아들일 것이다. 그리고 나서 2D 배열 내의 모든 값을 기본적으로 빈 블록으로 만드는 resetBoard() 메소드를 호출할 것이다.

조각들이 판에 추가되고 제거되기 때문에 우리는 addPiece()removePiece()메소드를 제공한다. addPiece() 메소드는 TetrisPiece()를 취하고 판에서 이 메소드가 차지하는 모든 위치의 값을 자신의 유형으로 설정함으로써 작동한다. removePiece() 메소드는 판의 값이 빈 블록의 값으로 설정된다는 점을 제외하면 비슷하다.

판에 변화가 있을 때 사용자가 알 수 있도록 하기 위해, 조각이 추가되거나 이동되었을 때 BoardEvent가 구동될 것이다. 이 이벤트를 듣는 클래스들에 대해 우리는 BoardListener 인터페이스가 필요한데, 이벤트가 구동되었을 때 이 인터페이스의 boardChange()메소드가 호출된다. 이 이벤트들은 화면 수정이 필요할 때 통지되도록 테트리스 판 GUI에 의해 사용될 수 있다. listener를 저장하기 위해 우리는 java.util.Vector를 사용할 것이고, listener를 추가/삭제하고 이벤트를 구동시키기 위한 관련 메소드를 제공할 것이다.

때때로 여러분이 조각을 추가하고 삭제할 때 BoardEvents를 구동시키는 것이 부적절할 수 있다. 조각이 떨어져야 할 때 (이 이동은 조각을 떨어뜨리기 위해 while 루프를 사용한다는 것을 기억하라)를 예로 들 수 있다. 이 경우 조각이 바닥에 부딪쳤을 때만 이벤트가 필요하다. 이를 용이하게 하기 위해 우리는 boolean 매개변수를 취하도록 addPiece() 메소드를 만들어 값이 true일 경우에만 이벤트가 구동되도록 할 것이다.

테트리스 게임의 중요 요소 중 하나는 한 행이 완료되면 그 행은 사라지고 그 위의 모든 행들이 내려온다는 것이다. 이를 위해 우리는 삭제될 행의 지수를 매개변수로 취하는 removeRow() 메소드를 제공할 것이다. 행이 없어진 후에 BoardEvent가 구동될 것이다.

private 변수들에 접근하기 위해 필요한 getter와 setter들 외에도, 우리는 하나의 메소드가 더 필요하다. 앞에서 설명한 willFit()가 그것이다. 이 메소드는 TetrisPiece를 매개변수로 취해 그 조각이 판에 맞는지 결정하기 위한 boolean 값을 돌려준다. 맞는다는 것은 그 조각이 판의 경계 안에 있고 판에서 그 조각이 맞춰질 곳에 있는 블록의 값이 비어 있다고 설정되어 있음을 의미한다. 이런 경우 true 값이 반환된다.

이제 TetrisBoard 클래스가 완성되었다.이 클래스를 포함한 완성된 소스를 참고 자료에서 다운로드받을 수 있다.

100 피트 벽을 가진 테트리스?

어느날 나는 이 빈을 타워 블록의 점등 시스템에 연결시키고 빌딩의 측면을 따라 내려가면서 테트리스 게임을 하고 싶어졌다. 나는 누군가가 이렇게 했다는 것을 신문에서 읽은 후 내내 이것을 하고 싶어해 왔다.

이제 테트리스 게임에서 사용되는 두 개의 주 컴포넌트를 만들었으므로, 이들을 모아 게임 로직을 만들면 된다.

게임의 흐름을 제어하기 위한 좋은 방법은 이것을 java.lang.Thread를 확장하는 내부 클래스에 내장시키는 것이다. 이 방식의 한 가지 장점은 게임 속도를 제어하기 위해 스레드 sleep 호출을 추가할 수 있다는 것이다. 또 다른 장점은 현재 주 애플리케이션 스레드가 자유롭기 때문에 하나의 GUI가 첨부될 때 색칠 문제가 없어진다는 것이다. 이 문제는 주 스레드가 계속 묶여 있어 색칠할 시간이 없을 때 때때로 발생할 수 있다.

스레드 내의 로직은 run() 메소드 내의 while 루프 속에 구현될 것이다. 루프는 계속해서 조각을 만들어 내고 조각을 더 이상 맞출 수 없을 때까지 이들을 게임판으로 떨어뜨릴 것이다. 이 때 fPlaying이라는 지역 boolean 변수가 false로 설정되어 루프를 끝내고 GameEvent를 구동시켜 게임이 종료되었음을 표시할 것이다.

while 루프 내에 fPaused의 boolean 값을 체크하는 if 절이 있다. 이 값이 true로 설정되었을 경우 루프는 계속 실행되겠지만 모든 게임 로직이 무시되어 종료되는 느낌을 줄 것이다. Boolean이 false로 다시 바뀌면 게임이 계속될 것이다.

우리는 한 번에 하나씩 떨어지는 조각에만 관심을 가지고 있으므로, 여기에 대한 참조를 저장할 fCurrPiece라는 변수를 만들 것이다. 이 변수가 null 값으로 설정되면 이전의 조각이 더 이상 아래로 내려갈 수 없으며 판의 최종 위치에 도착했음을 의미한다. 이 때 우리는 새 조각을 만들어 판의 맨 위 중앙에 둔다. fCurrPiece 변수가 null값이 아닌 모든 경우에 우리가 해야 할 일은 그 것을 한 위치로 떨어뜨리고 주어진 시간 동안 스레드를 휴면 상태로 만드는 것이다.

한 조각이 더 이상 움직일 수 없게 되었을 때 우리는 행이 완성되었는지 보아야 한다. 이를 위한 손쉬운 방법은 한 쌍의 중첩 for 루프를 사용하는 것이다. 이 for 루프의 바깥 쪽 루프는 행의 지수를 따라 작업하며, 안쪽의 루프는 지수 전체에 걸쳐 확인 작업을 수행한다. 만일 우리가 완성된 행을 발견하면, TetrisBoard 클래스에 구현된 removeRow() 메소드를 호출하며 완성된 행의 지수를 전달할 수 있다. 이제 제거된 행 위의 모든 행들이 하나씩 내려올 것이기 때문에 우리는 이들을 다시 체크해야 할 것이다. 여러 행을 한번에 완성하도록 장려하기 위해 우리는 완성된 행의 개수를 저장하고 각각 더 높은 점수를 줄 것이다.

테트리스 게임의 또 다른 주요 요소는 더 많은 행이 완성될수록 조각이 더 빨리 내려온다는 것이다. 이 기능은 지금까지 완성된 행의 개수를 체크하고 이에 따라 스레드의 휴면 주기를 점차 감소시켜가는 방식으로 구현될 수 있다.

GameThread 내부 클래스를 만들기 위해 필요한 것은 이것이 전부지만, 구현해야 할 또 다른 내부 클래스가 있다. 다수의 이벤트가 구동될 것이고 이들은 listerners가 저장되도록 요구할 것이므로, 이들을 모두 한 장소에 두는 것이 좋을 것이다. 우리는 EventHandler 내부 클래스를 사용하여 이를 수행할 것이다.

EnvetnHandler 내부 클래스
이 클래스는 우리가 구동하는 이벤트에 관심이 있는 listener들에 대한 참조를 저장할 것이다. listener들에 대한 addremove 메소드를 제공할 뿐 아니라 이벤트들을 구동하기 위한 유틸리티 메소드도 있을 것이다.

이 클래스는 다음 유형의 이벤트들을 다룬다. :

  • GameEvent : 게임이 시작되거나 멈출 때마다 구동된다. 게임 START 혹은 END를 표시하기 위한 값을 가지고 있다.

  • BoardEvent : 게임판에 변경 사항이 있을 때 구동된다. EventHandler 클래스에서 추가/삭제 listener 호출이 TetrisBoard 클래스로 전달된다.

  • ScoreEvent: 점수가 바뀔 때 구동된다.

구동될 수 있는 많은 다른 유형의 이벤트들이 있지만, 간편성을 위해 나는 위에서 설명한 이벤트들만 사용하였다. 우리가 구현할 수 있는 다른 이벤트에는 LineEvent가 있는데, 한 행, 혹은 여러 행이 완성되었을 때 구동되고 화면 애니메이션을 일으키는데 사용될 수 있다.

TetrisGame 마무리하기

이제 내부 클래스들을 완성하였으므로 TetrisGame 클래스의 나머지 부분을 설명해야 한다. 모든 자바 빈과 마찬가지로 우리는 매개 변수 없는 생성자가 필요하다. 이 생성자에서 우리는 EventHandler 클래스와 TetrisBoard 클래스의 인스턴스를 만들 것이다. TetrisBoard 클래스 10x20이라는 기본 사이즈를 가질 것이다.

게임 상태를 제어하기 위해 우리는 개시, 중지, 일시 중지 메소드를 사용할 것이다. startGame() 메소드는 모든 게임 변수를 리셋하고 ScoreEvent (이제 0으로 리셋됨)와 GameEvent (START라는 매개 변수 유형을 가짐)를 구동시킬 것이다. 또한 GameThread를 생성하여 개시할 것이다. stopGame() 메소드는 fPlaying 변수를 false로 바꾸어 GameThread가 끝나도록 하고 END라는 매개변수 유형으로 GameEvent를 구동시킨다. setPause() 메소드는 한 게임을 일시 중지시키는 역할만 한다.

필요한 모든 getters와 setters와 별도로, 구현할 메소드가 하나 더 있는데, move() 메소드가 그것이다. 이 메소드는 이동 방향을 매개변수로 취하는데, 이것은 TetrisPiece 클래스에서 나오는 생성자이다. move() 메소드는 게임이 진행중이며 일시 중지 상태가 아니라고 가정하고 이동하려고 시도한다. 그 이동이 아래로 떨어지는 요청인데 성공하지 못한다면 fCurrPiece가 null 값으로 설정되고 조각은 게임판 내의 현재 위치에 남아 있을 것이다. 그러면 GameThread는 새로운 조각을 생성한다.

TetrisGame에 대해서는 이게 전부이다. 이 클래스를 포함한 완성된 소스를 참고 자료에서 다운로드 받을 수 있다.

이제 완벽함을 위해 우리는 BeanInfo 클래스를 만들고 이 클래스들을 적절한 파일들로 채울 수 있지만, 여기에서는 그럴 필요가 없다. 우리가 필요한 것은 우리의 빈을 테스트할 간단한 GUI이고 참고 자료에 하나가 제공되고 있다. 이것은 테트리스 게임판을 그리기 위해 한 개의 내부 클래스를 사용하고 키 조작을 조정하기 위한 몇 가지 로직을 포함하고 있는 간단한 클래스이다. GUI는 javax.swing.JFrame에 표시되며, 선택적으로 java.applet.Applet이 될 수도 있다.

우리의 테트리스 빈을 테스트하기 위해 소스 파일을 푸는데, 디렉토리 구조를 그대로 두기 바란다. (왜냐하면 내가 빈 클래스들이 TetrisBean 디렉토리에 있도록 이들을 TetrisBean 패키지에 두었기 때문에 때문이다.) 여러분이 소스 파일을 푼 경로를 자바 클래스 경로에 추가하고 파일을 컴파일한다. 이제 여러분이 해야 할 일은 "java Scottris"를 실행시키는 것 뿐이다.

나는 이러한 테트리스 빈을 구현할 수 있는 많은 방법이 있다는 것을 알고 있다. 내가 이 글에서 소개한 것은 아주 간단한 방법이며, 이것이 여러분의 창조력에 불을 붙일 수 있기를 바란다. 나는 여러분이 이것을 자유롭게 개선시키기 바란다.




위로


참고자료




위로


필자소개

Photo of Scott Clee

Scott Clee는 현재 IBM의 CICS 제품에 대한 FV Tester로 일하고 있다. 4년간 자바 프로그래머로 일했으며 자바와 관련된 재미있는 프로젝트를 취미 삼아 수행하는 것을 즐긴다.





위로
반응형
자바에서는 Timer 와 TimerTask 를 이용한 주기적인 작업이 가능합니다.
예를 들어 1분에 한번씩 특정 디렉토리를 감시한다던지.
매일 밤 12시에 백업을 실시한다던지...
이런 기능이 필요하다면 Timer 와 TimerTask 를 사용해보세요.
아래 예제는 1초에 한번씩 카운트 라벨이 바뀌는 스윙 프로그램입니다.

import java.util.TimerTask;
import javax.swing.*;
import java.awt.*;
import java.util.Timer;

public class LabelChange {

public static void main(String[] args) {
MyFrame frame = new MyFrame();

Timer timer = new Timer();
//TimerTask, Delay시간, 동작주기
timer.schedule(new LabelChangeTimerTask(frame), 0, (1 * 1000));
}
}

class MyFrame
extends JFrame {

private JLabel label = null;

public MyFrame() {
this.getContentPane().setLayout(new BorderLayout());
label = new JLabel();
this.getContentPane().add(label, BorderLayout.CENTER);
this.setSize(200, 200);
this.setVisible(true);
}

public void setLabelValue(String msg) {
label.setText(msg);
}
}

class LabelChangeTimerTask
extends TimerTask {

private MyFrame frame = null;
private static int cnt = 0;

public LabelChangeTimerTask(MyFrame frame) {
this.frame = frame;
}

public void run() {
cnt++;
frame.setLabelValue(cnt + "");
}
}
<출처:ibm.com/developerworks/kr>
반응형

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

public class JImagePanel extends JPanel {
Image image;

public JImagePanel(Image image) {
this.image = image;
}

public void paintComponent(Graphics g) {
g.drawImage(this.image, 0, 0, this);
}

public static void main(String[] args) {
JFrame frame = new JFrame();
ImageIcon icon = new ImageIcon("d:\\java.gif");
JImagePanel panel = new JImagePanel(icon.getImage());
frame.getContentPane().add(panel);
frame.setSize(300,300);
frame.setVisible(true);
}
}
<출처:ibm.com/developerworks/kr>

반응형
자바 API에서 제공하는 것은 가상머신 관련된 것 뿐이라서 실제 메모리하고는 상관이 없습니다.

JNI를 사용해도 되겠지만 C 프로그램과는 친하고 싶지 않아서리... ^^ 꽁수를 부려봤습니다.



윈도우 플랫폼의 메모리 사용량은 systeminfo 라는
윈도우 명령을 사용해서 가능하기는 합니다만...
윈도 XP 이상에서만 지원되죠. 98 같은데서는 안됩니다 =.=

import java.io.*;

public class MemoryInfo {
public MemoryInfo() {
}
public static void main(String[] args) {
try {
String output, err;
String[] cmd = {"systeminfo.exe"};
Process proc = Runtime.getRuntime().exec(cmd);

BufferedReader stdout = new BufferedReader(new InputStreamReader(proc.getInputStream()));
BufferedReader stderr = new BufferedReader(new InputStreamReader(proc.getErrorStream()));

try {
while ( (output = stdout.readLine()) != null) {
if (output.indexOf("메모리") > 0) {
System.out.println(output);
}
}
while ( (err = stderr.readLine()) != null) {
System.out.println(err);
}
}
catch (IOException e) {
System.exit(0);
}
}
catch (IOException e1) {
System.err.println(e1);
System.exit(1);
}
}
}

============== 실행 결과 =============

총 실제 메모리: 511MB
사용 가능한 실제 메모리: 158MB
가상 메모리: 최대 크기: 2,048MB
가상 메모리: 사용 가능: 2,004MB
가상 메모리: 사용 중: 44MB
<출처:ibm.com/developerworks/kr>
반응형

레지스트리는 운영체제와 프로그램에서 필요한 정보를 담고 있는 데이터베이스와 비슷하다고 할 수 있다. 일반적인 윈도우 프로그램들은 레지스트리에 접근 할 수 있지만 자바 프로그램에서는 접근 할 수 없었다. 그 이유는 "자바의 철학"에 위배 되기 때문일 것이다. 자바 프로그램은 모든 운영체제에서 실행 가능 해야 하는데 '윈도우에만 존재하는 레지스트리'라는 것을 지원하지 않는 것은 당연한 일이었다. 게다가 레지스트리는 잘못 건드리면 윈도우 자체가 폭탄처럼 변할 수 도 있기 때문에 상당히 조심스러울 수 밖에 없다.

하지만 JDK 1.4 버전부터는 일부 제한적으로 레지스트리에 접근 할 수 있도록 그 기능이 추가되었다. 보통 자바 프로그램에서는 프로그램 실행에 필요한 정보들을 파일로 저장해 두었다가 프로그램이 종료된 후 다시 실행하더라도 필요한 정보를 얻도록 하는 방법을 사용했다. 이때 파일을 사용하게 되면 이런 저런 이유로 코딩도 복잡하고 귀찮기 짝이 없다. 특별히 복잡한 정보도 아닌데 여러 모로 프로그래머가 고생을 하는 것이다. 바로 이런 경우에 레지스트리를 사용하면 간단히 해결된다. 아마도 많은 자바 개발자들의 요구 사항으로 인하여 JDK 1.4부터 추가 된 것이 아닌가 싶다.

그렇다면 과연 자바 프로그램에서 레지스트리를 어떻게 사용할 것인가? 아무리 좋은 기능이 있어도 그 기능을 적절한 곳에 사용하지 못한다면 소용이 없게 된다. 레지스트리에 스트링 값을 입력하고 읽어오는 간단한 예제를 하나 만들어 보도록 하자. (참고로 예제 작성과 실행은 윈도우 XP에서 이루어졌다. 윈도우 계열 운영체제에서는 대부분 작동하겠지만 윈도우를 제외한 다른 운영체제에서는 예측 할 수 없음을 밝혀두는 바이다.)

레지스트리를 이용한 사용자 인증 프로그램

우리가 주로 사용하는 윈도우 운영체제에서는 사용자 계정을 제공한다. 따라서 인증된 사용자가 아니면 사용할 수 없다. 우리가 작성할 예제는 이와 비슷하지만 훨씬 간단한 프로그램이다. 프로그램이 제공하게 될 간단한 기능은 다음과 같다.
프로그램을 처음 사용하는 경우, 이름을 입력 받아 레지스트리에 등록한다.
사용자로부터 이름을 입력 받아서 등록된 이름과 같다면 원하는 작업을 계속 수행한다.
등록된 이름이 아닌 경우라면 그냥 종료된다.

프로그램에 대한 설명은 따로 필요 없이 주석을 참고하면 된다. 그리고 컴파일이나 실행에 대해서 잘 모른다면 다른 자바 기초 서적을 참고하기 바란다.

소스 코드는 다음과 같다.

import java.util.prefs.*;
import java.io.*;

public class RegistryTest {

// 키와 값을 출력한다.
public static void printKeyValue(String key, String value) {
System.out.println("Key = [" + key + "] , Value = [" + value + "]");
}

// 해당 노드에 키를 포함하고 있는지 검사한다.
public static boolean contains(Preferences node, String key) {
return node.get(key, null) != null;
}

// 키보드로부터 이름을 입력받는다.
public static String readName() {
System.out.println("Input your name.");
String value = null;
try {
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader in = new BufferedReader(isr);
value = in.readLine();
} catch (IOException e) {
// 예외 처리...
}
return value;
}

public static void main(String args[]) throws BackingStoreException {
Preferences userRootPrefs = Preferences.userRoot();

String key = "name"; // 등록할 키 이름
String value = "";
String newName = null;
if (contains(userRootPrefs, key)) { // 이미 키가 존재한다.
System.out.println("Key already exists !");
value = userRootPrefs.get(key, "");
newName = readName(); // 키보드로부터 입력 받은 이름
if (newName.equals(value)) {
// 입력된 이름과 레지스트리에 등록된 이름 같다.
printKeyValue(key, value);
// 결과 출력 후, 다른 원하는 작업 수행...
}
else {
// 이름이 다르다, 당신은 누구얏 ?
System.out.println("Invalid user name !");
}
}
else { // 키가 없으므로 처음 레지스트리에 등록
value = readName();
userRootPrefs.put(key, value);
printKeyValue(key, value);
}
}
}

<출처:ibm.com/developerworks/kr>

반응형
'자바 프로그래머'라면 한번쯤 고민하게 되는 부분이 있다. 그 중 하나가 자바 API가 지원하지 못하는 부분에 대한 것이다. 예를 들어 자바 API로는 네트워크 인터페이스 카드(NIC, 흔히 랜 카드라고 부른다)의 맥 어드레스(MAC Address)를 알아 낼 방법이 없다. 결국 JNI(Java Native Interface)를 사용하거나 다른 꽁수(?)를 찾아내곤 한다. 본인이 생각하기에는 두 방법 모두 시원스런 방법은 아니라서 상당히 거시기한 느낌이다. JNI를 사용하자니 C/C++ 코드를 사용하여 플랫폼에 제한적이 되어버리고… 꽁수를 사용하자니 안 먹히는 경우가 너무 많고…

어쨌거나 다른 해결 방법이 없다면 둘 중 하나를 사용해야 한다. 두 가지 중에서 본인이 많이 사용하는 방법은 꽁수를 사용하는 방법이다. 여기서 말하는 꽁수란 원하는 결과를 얻을 수 있는 외부 프로세스를 실행시키고 그 결과를 받아내어 필요한 부분만 얻어내는 방법을 사용하는 것이다. 이번 기사에서는 윈도우 XP 운영체제의 시스템 비밀스런(?) 정보를 얻어내는 자바 프로그램을 만들어 보도록 하자.

※ 주의: 본 소스의 모든 내용은 윈도우 XP 프로페셔널에서만 동작한다. 윈도우 XP 홈에디션에는 시스템 정보를 얻어내는 프로그램(systeminfo.exe)이 지원되지 않는다.

일단 화면에 도스창을 하나 띄워보자. 그런 후, "systeminfo"라고 입력하면 자신이 사용하는 윈도우 시스템에 대한 여러 정보가 나타난다. 윈도우 XP 프로페셔널에 이런 프로그램이 있다는 사실은 본인도 이 프로그램을 작성하면서 처음 알게 된 것이다. 자세한 세부 사항은 "systeminfo /?"라고 입력하여 도움말을 참고하도록 하자.

화면에 보이는 결과를 살펴보면 의외로 많은 사실들을 알 수 있다. 운영체제의 자세한 버전이나 사용자 정보, 실제 메모리 정보, 운영체제에 적용된 패치 등등… 이제부터는 이 정보들을 이용하여 자신이 원하는 몇 가지만을 보여주는 간단한 프로그램을 만들어보자.

이 프로그램의 핵심은 자바 프로그램 내에서 외부 프로그램을 실행시키고 그 결과를 받아내는 것이다. 이미 알고 있는 사람들에게는 아주 쉬운 일이지만 한번도 사용해보지 않았다면 이번 기회에 익혀두도록 하자. 나중에 두고 두고 써먹을 수 있는 프로그램 기법이 될 것이다(실제로 필자도 위기가 닥칠 때마다 이용해서 아주 유용하게 사용하고 있다). 아래 자바 메소드는 실행할 외부 프로그램의 이름을 스트링으로 지정하고 그 프로그램을 실행 후에 표준 출력과 표준 에러를 받아 내는 것이 전부이다.

public void run() {
Runtime runtime = Runtime.getRuntime();
Process process = null;

try {
// this.command = "systeminfo.exe";
process = runtime.exec(this.command); // 외부 프로그램 실행
} catch (IOException ioe) {
ioe.printStackTrace();
}

// 표준 출력
InputStream standardOutput = process.getInputStream();
// 표준 에러
InputStream standardError = process.getErrorStream();

InputStreamReader ir = new InputStreamReader(standardOutput);
InputStreamReader ow = new InputStreamReader(standardError);

BufferedReader outReader = new BufferedReader(ir);
BufferedReader errorReader = new BufferedReader(ow);

StringBuffer stdout = new StringBuffer();
StringBuffer stderr = new StringBuffer();
String line = null;
try {
// 루프를 돌면서 퓨준 출력과 표준 에러를 계속 받아낸다
while ( (line = outReader.readLine()) != null) {
stdout.append(line).append("\n");
}
while ( (line = errorReader.readLine()) != null) {
stderr.append(line).append("\n");
}
standardOutput.close();
standardError.close();
} catch (IOException ioe) {
ioe.printStackTrace();
}
result.setStdout(stdout.toString()); // 이 결과를 나중에 사용한다
result.setStderr(stderr.toString());
}

위의 코드 마지막 부분에 나중에 사용할 결과를 지정하는 부분이 있다. 그 결과를 이용해서 원하는 정보만 가려내는 코드는 다음과 같다.

String result = pRunner.result.getStdout();
StringTokenizer st = new StringTokenizer(result, "\n");
while (st.hasMoreElements()) {
String line = (String)st.nextElement();
if (line.startsWith("호스트 이름")) {
addSysInfo(line);
}
if (line.startsWith("OS 이름")) {
addSysInfo(line);
}
if (line.startsWith("등록된 소유자")) {
addSysInfo(line);
}
if (line.startsWith("Product ID")) {
addSysInfo(line);
}
if (line.startsWith("System Up Time")) {
addSysInfo(line);
}
}

원하는 정보를 모두 얻었다면 이제 GUI로 아름답게 보여주는 일만 남았다. 이 부분에서는 여러 분들이 직접 원하는 형태대로 만들어보기 바란다.
<출처:ibm.com/developerworks/kr>
반응형
:: 2007년 12월 4일 ::
다운로드
심포니 소개
상품 소개
참여하기

반응형
:: 2007년 11월 28일 ::

  Weekly Highlight
Lotus Symphony Beta 사용자 리뷰 컨테스트에 참여하시고 선물도 받아가세요.
IBM 대학 프로그램 (IBM University Relations) 페이지가 업데이트 되었습니다.
   Local Contents
돌봄과 소통을 위한 터를 만드는 사람들 - ‘온라인 학습 생태계’ 프로젝트 개발팀 (dW Interview)
이슈 트래커 개발자가 들려주는 이슈 트래커 이야기, Part 1: 무엇을 어떻게 골라쓸까 - 박영록 (Special Issue)
기계 세상, Part 2 - 김성우 (dW Column)
WTP에서 Axis2를 이용한 웹 서비스 구현하기 Part 1: 개발 환경 구축과 웹 서비스 판매 프로세스 개발 준비 - 김광섭 (dW CoD)
   최신 기술자료 (한글)
Workplace Forms 프로젝트를 위한 요구 사항 수렴 가이드 [Lotus]
Workplace Forms 프로젝트를 위해 어떤 요구 사항들을 수집해야 하는지 알고 계십니까? 프로젝트를 시작하기 전에 여러분이 알아야 할 것이 있습니다.
음성 실행 XML, Part 4: VoiceXML로 웹 검색 애플리케이션 개발하기 [XML]
본 시리즈 마지막 기술자료에서는, VoiceXML을 인풋으로 취하고, 기본적인 웹 검색과 Yahoo 로컬 검색에 Yahoo Search API를 쿼리하는 애플리케이션을 개발해 보도록 하겠습니다. 이 쿼리는 특정 위치와 지역 내의 비즈니스에 관한 정보를 리턴합니다. 애플리케이션은 제출 후에 콜러에게 결과를 읽어줍니다.
Eclipse Forms로 애플리케이션에 새로운 활력을 [오픈 소스]
Eclipse Forms는 Eclipse 애플리케이션의 사용자 경험을 향상시킬 수 있는 방법을 제공합니다. 임베디드 브라우저를 사용하지 않고 애플리케이션에 “웹과 비슷한” 형태를 제공합니다. 제품 관련 예제도 제공합니다.
리눅스의 x86 용 인라인 어셈블리(Inline assembly) [리눅스]
Bharata B. Rao는 리눅스 플랫폼 상에서 x86용 인라인 어셈블리의 사용법과 구조를 설명합니다. 인라인 어셈블리의 기초와 다양한 사용법을 설명하고, 기본적인 인라인 어셈블리 코딩 가이드도 제시하며, 리눅스 커널에서 인라인 어셈블리 코드의 인스턴스도 설명합니다.
웹 서비스 힌트 & 팁: JAX-RPC 대 JAX-WS, Part 2 [SOA와 웹서비스]
JAX-RPC 1.1의 후속인 JAX-WS 2.0은 JAXB(Java Architecture for XML Binding)라고 하는 JCP 기술을 사용함으로써 데이터 매핑 메소드를 진화시켰습니다. 이번 글에서는 두 개의 웹 서비스 스팩들의 데이터 매핑을 비교합니다. JAX-RPC 대 JAX-WS, Part 1을 읽어보면 그 차이를 더 정확히 알 수 있습니다.
End-to-end Ajax 애플리케이션 개발, Part 3: 애플리케이션의 통합, 테스트, 디버깅 [웹 개발]
Ajax (Asynchronous JavaScript + XML)는 데스크탑 품질의 소프트웨어 기능을 브라우저 플랫폼에서 실행되는 웹 애플리케이션으로 가져오는 현대적인 방식으로서 빠르게 급부상 하고 있습니다. 이 글에서는 오픈 소스 커뮤니티의 기술들을 사용하여 엔드투엔드 Ajax 애플리케이션을 개발하는 방법을 설명합니다.
   기획 기사
DB2 기반의 편리한 웹 개발 체험, DB2와 루비 온 레일스
루비 온 레일스의 ORM(Object/Relational Mapping) 프레임워크인 액티브 레코드는 모듈적으로 설계되어 있기 때문에 다양한 데이터베이스 시스템을 지원할 수 있습니다. 이번 기획기사는 DB2 데이터베이스를 사용하여 레일스 웹 애플리케이션을 개발하는 과정을 소개합니다.
   최신 튜토리얼 (한글)
XSLT를 사용하여 오픈오피스의 편집기능 확장하기 [XML]
이 튜토리얼에서는 오픈오피스의 가져오기/내보내기(import/export) 필터를 사용하여 일반 문서인 XML 데이터를 여는 방법을 다룹니다. 여기서부터 사용자들은 더욱 자연스럽게 문서를 편집하고 나서 이를 네이티브 포맷으로 다시 저장할 수 있습니다. 또한 이 특징을 사용하여 문서를 XML 데이터로 쉽게 바꿀 수 있습니다.
모델 주도 개발 환경에서 애스펙트 개발과 배치 Part 1 [아키텍처]
이번 튜토리얼에서는 IBM Rational Software Architect Model-Drivent Development 프로젝트에 도입할 수 있는 AspectJ 기반 라이브러리를 만드는 방법에 대해 자세하게 알아 볼 것입니다.
   최신 튜토리얼 (영문)
Rational Asset Manager Eclipse 클라이언트 설치 및 사용 [IBM Systems]
에셋들의 검색, 찾기, 평가에 Rational Asset Manager Eclipse 클라이언트를 사용하여, 가상 기업을 위한 어카운팅 서비스에 대한 새로운 요구 사항을 만들어봅시다.
   최신 SW 다운로드
Rational Application Developer for WebSphere Software V7.0 시험판
IBM 로터스 심포니 베타
DB2 9 for Linux, UNIX, and Windows
IBM SOA Sandbox for process
IBM SOA Sandbox for reuse 시험판
반응형
:: 2007년 11월 14일 ::

  Weekly Highlight
IBM의 최신 시험판, 무료 소프트웨어를 다운로드 해보세요.
한국 IBM developerWorks 2007년 10월 TOP 10 인기자료가 업데이트 되었습니다.
   Local Contents
아이들을 위한 즐거운 컴퓨팅 환경 만들기 - 고려대학교 대학원, 김승범 (dW Interview)
초보 개발자를 위한 오픈 소스 라이선스 길잡이 Part 2 - 이진태 (Special Issue)
dW 대학생 모니터 요원과 IT 실무자와의 만남 1: 한국IBM GTS사업부
우리가 사는 사회는 어떻게 탄생했을까, ‘자본주의 역사 바로 알기’ - 양유성 (개발자 책꽂이)
효과적인 버그 관리 도구, BTS(Bug Tracking System) - 이영석 (dW Column)
   최신 기술자료 (한글)
음성 실행 XML, Part 3: 음성 블로깅(blogging) 애플리케이션 개발하기 [XML]
이번 시간에는, VoiceXML (VXML)을 인풋으로 사용하여, 데이터를 온라인 블로그에 저장하는 간단한 블로깅(blogging) 애플리케이션을 개발할 것입니다. 이러한 유형의 음성 블로깅을 사용하여 트위트(tweet) 또는 Twitter 엔트리를 만들 때 큰 효과를 볼 수 있습니다.
Ajax와 XML: 라이트박스(lightbox)용 Ajax [XML]
Lightbox, 팝업, 윈도우, 페이딩(fading) 메시지 같은 새로운 기술을 사용하여 사용자의 관심을 끌어봅시다.
Acegi로 자바 애플리케이션 보안화 하기, Part 1: 아키텍처 개요와 보안 필터 [자바]
단순한 엔터프라이즈 애플리케이션과 오픈 소스 보안 프레임웍인 Acegi Security System을 가진 복잡한 애플리케이션을 보호하는 방법에 대해 알아봅시다.
AIX 6 Workload Partition과 Live Application Mobility [AIX and UNIX]
AIX 6에 새롭게 도입된 Workload Partition 기능을 소개합니다.
DB2와 Ruby on Rails, Part 3: DB2와 Ruby on Rails에서의 테스팅 [오픈 소스]
DB2와 Ruby on Rails 시리즈, 세 번째 글에서는, 두 번째 기술자료에 소개되었던 Team Room 데모 샘플의 정확 속에 Rails 빌트인 테스트 프레임웍을 적용시켜 봅니다.
   기획 기사
Finite State Machine 이론을 응용해 JavaScript로 고급 웹 위젯 만들기
Ajax와 클라이언트 기반 매시업(mash-up) 추세로 인해 자바스크립트가 중요한 언어로 부각되고 있습니다. 이번 기획기사는 유한 상태 기계(Finite State Machine)에 기반을 두고 이벤트 중심(event-driven) 프로그램을 설계해 이를 자바스크립트로 구현하는 방법을 실용적인 모듈을 개발하는 과정을 통해 전달합니다.
   최신 튜토리얼 (한글)
WebSphere Integration Developer를 사용하여 DB2 9 버전의 pureXML 노출하기 [Information Mgmt]
IBM은 DB2 9의 고유한 XML 기능을 보여줄 수 있는 특정 업계용 웹 서비스 세트를 제공합니다. WebSphere Integration Developer 모듈을 사용하여 DB2 XML 칼럼(column)에 제대로 된 형태의 XML 문서를 저장할 수 있는 미디에이션(mediation) 모듈을 어떻게 만들고 테스트하고 배치할 수 있는지 차근차근 살펴보겠습니다.
아마존 웹 서비스를 이용한 애플리케이션 쾌속 개발, Part 3 [SOA와 웹서비스]
이번 튜토리얼은, 아마존 웹 서비스로 애플리케이션을 만드는 것에 관한 연재의 세 번째로, 자바 ME 장치들에서 SQS를 사용하는 방법을 살펴보겠습니다.
   최신 튜토리얼 (영문)
메인프레임을 원하십니까? e-kit [IBM Systems]
현대적인 애플리케이션 라이프 사이클 관리를 Rational Software Delivery Platform (SDP)을 통해 IBM System z로 확장하십시오. 귀하의 엔터프라이즈를 현대화 할 수 있는 이 기회를 놓치지 마십시오.
   최신 SW 다운로드
DB2 Express-C 9.5 (무료 제품) (UPDATE)
시험판: Lotus Domino 8
WebSphere Application Server Community Edition V2.0 (무료 제품) (UPDATE)
시험판: Rational Performance Tester V7.0
시험판: Rational Software Architect V7.0
Rational Functional Tester V7.0.1 (UPDATE)
Rational Tester for SOA Quality V7.0.1 (UPDATE)
시험판 : Rational Asset Manager V7.0
Rational Manual Tester V7.0.1 (UPDATE)
Tivoli System Automation for Multiplatforms V2.2 (UPDATE)
반응형
:: 2007년 10월 31일 ::

  Weekly Highlight
ACM International Collegiate Programming Contest 2007 Asia Regional Contest - Seoul
IBM SOA Sandbox 시험판을 사용해보세요.
   Local Contents
협력을 통한 추상화 - 김창준 (dW Column)
GUI를 단위 테스트하는 방법 - 류준호 (Open dW)
사용자가 똑똑해지도록 돕는 착한 도구 만들기 - 강규영 (dW Interview)
초보 개발자를 위한 오픈 소스 라이선스 길잡이 Part 1: 기초 개념 탑재하기 - 정재훈 (Special Issue)
   최신 기술자료 (한글)
XMLTABLE 예제, Part 1 [Information Mgmt]
XMLTABLE을 사용하여 관계형 포맷으로 된 XML 데이터를 검색하는 방법을 배웁니다. 반복 또는 누락 XML 엘리먼트를 관리하는 방법과 XMLTABLE 함수에서 네임스페이스를 핸들하는 방법을 설명합니다.
XPath 2.0과 XSLT 2.0으로 시간과 코드 절약하기 [XML]
XML 문서의 고급 HTML 뷰를 만들고, XSLT 2.0의 새로운 기능으로 관리가 편한 스타일시트를 만들어 봅시다. XSLT 2.0의 데이터 유형화 및 새로운 xsl:function 엘리먼트를 사용하는 방법을 배워봅시다.
음성 실행 XML, Part 2: 음성 실행 캘린더 개발하기 [XML]
두 번째 시간에는 음성 실행 캘린더 개발 방법을 배워봅시다. 캘린더의 데이터를 XML로 저장하고, 캘린더 엔트리들을 수정할 때, 애플리케이션이 지정된 명령어들을 포함하고 있는 VoiceXML을 읽도록 합니다.
pureQuery: 시간도 줄이고, 아주 적은 코드만 작성하며, 어디에서나 실행되는… [자바]
pureQuery라고 하는 프로젝트 코드는 데이터베이스 애플리케이션 개발자들에게 쉬운, GUI 기반 방식을 제공하여 디자인과 구현 단계에서 생산성을 높입니다.
Real world Rails, Part 4: Ruby on Rails의 테스팅 전략 [웹 개발]
테스팅은 Ruby on Rails 커뮤니티에서 입지를 굳건히 하고 있습니다. Rails 스택부터 커버리지용 RCov, 테스트 케이스를 강화시킬 수 있는 Mocha와 FlexMock에 이르기까지 많은 툴들이 있습니다. 하지만, 툴들마다 다양한 전략이 있습니다. 여러 가지 기본적인 테스팅 전략의 장단점을 배워봅시다.
Visual Studio 사용자를 위한 Eclipse 소개 [오픈 소스]
Eclipse는 Microsoft Visual Studio 개발자들에게는 새로운 세계이며, Eclipse를 시작하는 것은 매우 혼란스러운 일입니다. 환경의 차이를 배운다면 Eclipse 사용이 더욱 수월해질 것입니다.
   기획 기사
‘행위의 중복’을 없애는, 사람을 위한 자동화
개발 과정에서 제거해야 할 중복은 소스 코드에만 있지 않습니다. 소프트웨어를 빌드할 때마다 반복적으로 입력하는 명령어들, 코드를 수정한 후 수동으로 수행하는 반복적 테스트, 주기적으로 작성하는 각종 리포트 등도 제거 해야 할 "행위의 중복" 입니다. 이번 기획기사는 다양한 자동화 기법을 소개합니다.
   최신 튜토리얼 (한글)
IDS 레이블 기반 접근 제어, 실용 가이드, Part 1: IDS의 LBAC 기초 이해하기 [Information Mgmt]
불법 접근으로부터 데이터를 보호하면서 사용자들이 제한적으로 데이터에 접근할 수 있도록 허용하는 유연성을 가지도록 LBAC(Label-Based Access Control)를 적용해 보겠습니다. 이 사용 케이스 시나리오 기반의 단계별 가이드를 통해 LBAC 솔루션을 만들 것입니다.
XForms를 사용하여 회계 도구 만들기, Part 6 [XML]
이번 연재에서는 실시간 계산과 뛰어난 인터랙션 등 XForms를 통해 효과적으로 해결할 수 있는 몇 가지 문제를 집중적으로 다룹니다. Part 6에서는 지금까지의 내용을 총 정리하고 애플리케이션 결과물에 결함은 없는지 앞으로의 가능성은 무엇인지 살펴보겠습니다.
   최신 SW 다운로드
Rational Performance Tester V7.0.1 | 평가판! (UPDATE)
IBM SOA Sandbox 시험판 개요
IBM SOA Sandbox for connectivity
IBM SOA Sandbox for reuse
top

더이상 구독을 원치 않으시는 분은 developerWorks에서 뉴스레터 [구독 취소]를 선택하여 주시기 바랍니다.
developerWorks 운영자에게 메일 보내기
Copyright ⓒ IBM Korea, Inc. All rights Reserved.


+ Recent posts