2011년 6월 26일 일요일

자바 스윙(Java Swing)

자바 GUI(Graphic User Interface) 프로그래밍의 대표격인 스윙(Swing)에 대해서 오늘부터 단계적으로 다뤄보고자 한다. 자바를 공부하면서 숫자와 문자의 조합으로 결과가 나오는 것이 지루하고 따분하게 느껴졌다면 오늘 이 시간부터 여러분은 새로운 세계(?)에 흥미를 가질지도 모르겠다. 자바의 스윙은 프로그램 컴포넌트 셋으로서 GUI 컴포넌트인 버튼이나 스크롤바등을 여러 플랫폼에서 독립적으로 만들수 있는 기능을 제공한다. 너무 거창하게 설명했남? ㅎㅎ 한마디로 자바의 스윙(Swing)은 그래픽 구현하려고 JDK 개발툴에서 만든 자바 기반 클래스의 일부분이다.


자바의 스윙(Java Swing)은 자바 GUI로 기존에 쓰던 AWT(Abstract Window Toolkit)이라는게 있는데 여기서 쓰던 기본적인 시스템의 자원과 기능을 그대로 제공하며 여기서 더 나아가 표나 트리등의 복잡하고 더욱더 다양한 그래픽 컴포넌트를 사용하고 보완하기 위해 자바 개발툴인 JDK 1.2 버젼부터 도입되어 현재에 이르게 되었다. 다시 말하면 AWT의 부족한 부분을 채우기 위해 만들어졌다고 생각하면 된다. 따라서 필자는 AWT를 따로 강의하지 않고 신개념의 신기술인 자바의 스윙을 바로 들어가겠다. AWT 공부하다 지쳐서 정말 배워야하는 Swing을 배우기 전에 나가떨어지는 이들을 막기 위한 필자의 치밀한 강의전략(?)인 것이다.^^

방금 얘기한 자바 스윙(Java Swing)은 javax.swing.*; 패키지에 그리고 AWT는 java.awt.*; 패키지에 들어있다. 자바의 스윙을 공부할 것이므로 대부분 javax.swing 패키지를 이용할 것이나 부분적으로 필요할 경우 java.awt 패키지도 사용하도록 하겠다. 자 그럼 자바의 스윙에 들어가기에 앞서 기본적인 클래스 트리가 어떤 식으로 구성되어 있는지 살펴보도록 하겠다. 처음이라 와닿지 않을 것이나 언젠가(?) 여러분이 필요할때가 생겨날 것이다. 가벼운 마음으로 구경하기 바란다. 제발 쓸데없이 무조건 외우지 말아라. 쓰다보면 알게된다.ㅎㅎ


보다보면 특이한게 그냥 클래스 이름을 쓰면 될것이지 이상하게 앞에 J라는 대문자가 하나씩 더 들어간 것을 볼수 있을 것이다. 기존 AWT에서는 J가 없었으나 Swing이 생기면서 기존 툴과 구별하기 위해 J를 붙인것으로 알고있으면 된다. 오늘은 스윙을 이용해서 자바를 처음 배울때처럼 그래픽(?)을 구현하여 문자를 출력해보도록 하겠다. 기대하시라~ 쨔짜잔~ ㅎㅎ


여러분이 윈도우에서 여러 프로그램들을 사용할때 일반적으로 나오는 창이 위와 같은데 이것을 이제 자바로 만드는 것이다. 저거 일일이 어떻게 도형그리고 선긋고 만들지라고 생각하면서 앞서가는 이들이 있을지 모르겠는데 위에 보는 기본창은 자바에서 명령어 몇줄만 긁적이면 알아서 만들어주게끔 되어있으니 염려 푹 놓으시라.^^


위에서 보는 그림이 기본창에서 들어가는 대표적인 클래스들인데 오늘은 여기서 JFrame과 JLabel 그리고 Content Pane을 약간 사용하게 될것인데 아래 그림을 보면 해당 제목들이 이해가 더 잘될 것이다. 잘 안보이면 클릭해서 보자. 그림을 확대해서 친절(?)하게 보여준다.ㅎㅎ


그런데 암만봐도 필자가 무슨 말을 하고 있는지 어안이 벙벙한 이들도 있을 것이다. 그도 그럴것이 갑자기 자바로 그림 그리겠다고 하니 말이다. 그건 여러분의 탓이 아니니 염려하지 말자. 필자가 누구더냐? 이제까지 다 이해못했어도 전혀 문제될게 없다. 여러분의 모든 고민을 해결해줄 빵빵한 예제(?)가 아래에 기다리고 있으니 말이다.^^


오늘의 하이라이트(?)인 예제의 결과물이 위와 같다. 예전 같으면 시커먼 모니터 화면에 딸랑 주소 한줄만 출력되었겠지만 거기다가 껍데기(?)만 이쁘게 씌워놔도 뭔가 있는듯하다.ㅎㅎ 그럼 어떻게 위와같은 그래픽을 구현할수 있는지 예제 코드를 살펴보자.


자바 스윙을 시작하는 첫 시간이라 내용을 단순하게 만들기 위해 각고의 노력(?)을 기울인만큼 여러분도 그에 상응한 고통을 수반한 노력(?)을 치뤄야 할것이다.ㅎㅎ 농담이다. 가볍게 봐도 저절로 이해될 것이다. 간략하게 예제를 설명하자면 일단 JFrame과 JLabel 클래스를 쓰기 위해 javax.swing 패키지에서 import 하였고 해당 클래스 이용해서 프레임 만들고 레이블 만들고 프레임 제목 쓰고 사이즈 정하고 보이도록 세팅해준게 전부다. 예제에 대한 설명으로 쓴 주석이 자바 스윙의 첫 예제라 그런지 필자도 모르게 너무 과하게 써버려서 이해하는데 어려울건 없다고 본다.ㅎㅎ

엄밀히 말해서 자바의 스윙 콤포넌트들은 쓰레드에 안전하다고 장담할수 없다. 따라서 메인메소드에서 run( ) 메소드를 이용해 자바 스윙을 구현하는게 바람직하나 지금은 기술적으로 그렇구나라고 알고만 있자. 초반에는 스윙 대부분의 콤포넌트들이 lightweight를 지향하는 경량 프로그램인 것처럼 여러분도 가벼운 마음으로 워밍업한다 생각하고 열심히 스윙(?)을 연습하기 바란다.^^

2011년 6월 23일 목요일

자바의 입력과 출력(I/O Streams)


오늘은 자바의 기본적인 입출력 방법에 대해서 살펴보기로 하겠다. 강좌 초반에 맛배기로 자바의 입출력에 관해서 잠깐 공부한적이 있지만 보다 다양한 방법과 접근을 통해서 심층학습(?)을 해보고자 한다. 자바에서 파일 입출력 부분은 상당히 중요하다. 여러분이 어떤 프로그램을 만들던지간에 유저의 입력과 그와 관련해서 정보를 처리하고 출력하는 시스템은 아마 필수적으로 꼭 들어가는 부분 중 하나일텐데 이 부분에 대해서 자유자재로 대처하지 못한다면 프로그램 제작시 상당한 어려움에 처하는 일이 많을 것이다. 이번 강좌를 통해서 자바의 입출력에 관한한 가장 기본적인 스킬은 여러분이 쉽게 습득할수 있도록 필자가 최선을 다할 것이다. 여러분이 할일은 그저 본 강좌를 열심히 읽기만 하고 따라서 쳐보기만 하면 될것이다.^^


스트림(Stream)은 위의 그림에서 보다시피 데이터의 흐름을 거치는 과정이라 생각하면 된다. 데이터 타입은 우리가 오늘 배울 바이트나 캐릭터 같은 유용한 것들(?)이 스트림을 통해 입력 프로그램이나 아래 그림처럼 입력과 반대로 출력 프로그램도 스트림을 통해 한번에 하나씩 읽어들이면서 처리한다.


오늘은 파일 입출력 부분에서 가장 기초라 할수 있는 파일 카피에 대한 자바 소스를 만들어 보기로 하겠다. 일단 카피할 원본 파일이 있어야 할텐데 원본 파일명은 eminem.txt 라고 하고 안에다가 아래의 내용을 넣고 저장하기 바란다.ㅎㅎ

eminem.txt
====================
"Love The Way You Lie"

(feat. Rihanna)

[Chorus - Rihanna:]
Just gonna stand there and watch me burn
But that's alright because I like the way it hurts
Just gonna stand there and hear me cry
But that's alright because I love the way you lie
I love the way you lie

[Eminem]
I can't tell you what it really is
I can only tell you what it feels like
And right now it's a steel knife in my windpipe
I can't breathe but I still fight while I can fight
As long as the wrong feels right it's like I'm in flight
High off of love, drunk from my hate,
It's like I'm huffing paint and I love it the more I suffer, I suffocate
And right before I'm about to drown, she resuscitates me
She fucking hates me and I love it.
Wait! Where you going?
"I'm leaving you"
No you ain't. Come back we're running right back.
Here we go again
It's so insane cause when it's going good, it's going great
I'm Superman with the wind at his back, she's Lois Lane
But when it's bad it's awful, I feel so ashamed I snapped
Who's that dude? I don't even know his name
I laid hands on her, I'll never stoop so low again
I guess I don't know my own strength

[Chorus - Rihanna:]
Just gonna stand there and watch me burn
But that's alright because I like the way it hurts
Just gonna stand there and hear me cry
But that's alright because I love the way you lie
I love the way you lie
I love the way you lie

[Eminem]
You ever love somebody so much you can barely breathe
When you're with 'em
You meet and neither one of you even know what hit 'em
Got that warm fuzzy feeling
Yeah, them chills you used to get 'em
Now you're getting fucking sick of looking at 'em
You swore you'd never hit 'em; never do nothing to hurt 'em
Now you're in each other's face spewing venom in your words when you spit them
You push, pull each other's hair, scratch, claw, hit 'em
Throw 'em down, pin 'em
So lost in the moments when you're in them
It's the rage that took over it controls you both
So they say you're best to go your separate ways
Guess if they don't know you 'cause today that was yesterday
Yesterday is over, it's a different day
Sound like broken records playing over but you promised her
Next time you show restraint
You don't get another chance
Life is no Nintendo game
But you lied again
Now you get to watch her leave out the window
Guess that's why they call it window pane

[Chorus - Rihanna:]
Just gonna stand there and watch me burn
But that's alright because I like the way it hurts
Just gonna stand there and hear me cry
But that's alright because I love the way you lie
I love the way you lie
I love the way you lie

[Eminem]
Now I know we said things, did things that we didn't mean
And we fall back into the same patterns, same routine
But your temper's just as bad as mine is
You're the same as me
But when it comes to love you're just as blinded
Baby, please come back
It wasn't you, baby it was me
Maybe our relationship isn't as crazy as it seems
Maybe that's what happens when a tornado meets a volcano
All I know is I love you too much to walk away though
Come inside, pick up your bags off the sidewalk
Don't you hear sincerity in my voice when I talk
I told you this is my fault
Look me in the eyeball
Next time I'm pissed, I'll aim my fist at the drywall
Next time. There won't be no next time
I apologize even though I know its lies
I'm tired of the games I just want her back
I know I'm a liar
If she ever tries to fucking leave again
Im'a tie her to the bed and set this house on fire
I'm just gonna

[Chorus - Rihanna:]
Just gonna stand there and watch me burn
But that's alright because I like the way it hurts
Just gonna stand there and hear me cry
But that's alright because I love the way you lie
I love the way you lie
I love the way you lie
====================

명곡(?)이라서 그런지 생각보다 가사가 조금 길다.^^ 여러분이 오늘 배울 자바소스(Test66.java) 파일과 같은 폴더에 위의 eminem.txt 파일을 넣고 실행하면 정상적으로 작동될 것이다. 그럼 예제를 보면서 차근차근 프로그램에 대해서 풀어가겠다.


프로그램이 아주 명확하므로 주석을 달진 않았지만 이해를 돕기 위해 간략하게 설명해 보겠다. 우리의 미션(?)은 eminem.txt 파일안의 내용을 lovethewayyoulie.txt 라는 파일에다가 그대로 카피하는게 주임무이다. 아는 사람은 알겠지만 에미넘(Eminem)의 Love the way you lie 라는 노래 가사를 카피하는 자바 소스다. 에미넘이란 이 친구(?)를 모르는 이들은 이번 기회에 꼭 한번 들어보기 바란다.ㅎㅎ

오늘 쓰일 자바의 파일 입출력을 담당하는 스트림은 FileInputStream과 FileOutputStream이므로 이를 이용하기 위해 import 하였다. 그리고 이에 대한 예외처리를 하기위해 IOException을 또한 불러들였다. 메인메소드를 보면 파일인풋스트림의 인자로 input을 파일아웃풋스트림의 인자로 output을 쓰고 소스를 읽어들이는 파일을 eminem.txt에서 읽도록 FileInputStream을 이용해 객체생성을 한후 input으로 건네주었고 마찬가지로 출력하는 파일로는lovethewayyoulie.txt로 만들라고 FileOutputStream을 통해 객체생성을 하고 output으로 넘겨주었다. 출력파일(lovethewayyoulie.txt)이 없을 경우 자동으로 생성되며 있을 경우 다시 덮어씌워버리니 출력 부분은 신경쓰지 않아도 된다.

int a; 라는 명령문이 나오는데 이게 뭔지 의아해할지도 모르겠다. while문을 보면 a가 input.read( )라는 구문을 받고 있는데 FileInputStream의 read( ) 메소드의 리턴값이 int 이므로 이렇게 받는다. 쉽게 설명하자면 바이트로 즉 컴퓨터에서는 그냥 정수로 문자들을 읽어내는데 각 글자마다 고유의 숫자가 있다. 이를 읽고 파일의 내용이 다 끝났으면 -1 이라는 정수값을 리턴하므로 while 구문이 파일 내용이 끝날때까지 읽게 만들려고 조건식이 위와같이 되는 것이다. 그리고 읽은 값을 output 즉 우리가 지정한 출력파일에다가 한번에 하나씩 카피하게 된다.


글자마다 갖고 있는 고유의 값이 뭐지? 라고 궁금해하는 이들은 아래의 표를 보기 바란다. 우리가 일반적으로 쓰는 알파벳이나 그밖의 기호들은 각기 고유한 숫자 체계를 가지고 있는데 우리가 사용하는 컴퓨터는 바로 이를 기호화하여 처리하므로 문자들을 읽을수 있는 것이다.


위에서 보는 이런 문자 체계를 우리는 아스키 코드(ASCII code)라고 부른다. 아마 컴퓨터를 사용하면서 아니면 키보드를 두드리면서 한번쯤은 들어봤음직한 용어일 것이다. 이런 표를 보면 그냥 외워야되는 것인줄 알고 무작정 암기하는데 제발 그러지말고 그냥 복사해서 필요할때마다 옆에두고 쓰자. 강이의 자바강좌 회원들은 보다 현명(?)하게 이런 상황들을 넘기기 바란다.ㅎㅎ

마지막에 있는 finally 구문은 예외가 생기던 안생기던 항상 처리되는데 try 예외구문을 받는 명령으로 파일을 오픈하고 썼으면 만일에 있을지 모르는 오작동(?)을 방지하기 위해 파일을 닫아주라는 명령이다. 예외구문에 대해서 기억이 잘 안나는 이들은 예전 강좌를 뒤적거려서 보고오기 바란다. 위의 예제를 실행하면 아래와 같은 결과를 얻게 될것이다.

34
76
111
118
101
32
84
104
101
32
..
...

왜 이렇게 되는지는 필자가 족보(?)인 아스키 코드를 여러분에게 주었으니 eminem.txt안의 파일내용과 대조해보면서 왜 이런 숫자들이 찍히는지 연구해보기 바란다. 여러분이 공부하기 쉽도록 출력스트림에서 바이트를 문자로 전환하기 전에 화면에 바이트로된 숫자를 출력하라고 만들어 놓은 것이다. 그리고 예제를 실행했으면 lovethewayyoulie.txt라는 파일이 같은 폴더안에 생성되었을 것인데 잘 카피되었는지 확인해보면서 공부하기 바란다.

java.io 패키지에서 우리가 방금 이용한 FileInputStream 대신에 FileReader를 FileOutputStream 대신에 FileWriter를 쓰고 똑같은 방법으로 위와같은 결과를 도출해낼수 있다. 다른말로 하면 FileReader는 FileInputStream을 FileWriter는 FileOutputStream을 상속받기 때문에 그러하다.

느꼈을지 모르겠지만 위의 프로그램은 뭔가 아쉬운 점이 많다. 한글자 한글자씩 읽어서 옮기는데 이건 너무 답답하지 않은가? 그래서 문장을 한줄씩 읽는 방식이 보편적으로 쓰인다. 이미 예전에 필자가 선보인 방식(?)이니 특별한 설명은 따로 하지 않겠다.ㅎㅎ 그래도 궁금해하는 이들을 위해 예제를 아래와 같이 올리니 뚫어지게 보면서 공부하기 바란다.^^


실행하고 보면 알겠지만 출력결과에서 보듯이 readLine( ) 메소드를 통해 문장을 한줄씩 읽어들이면서 명령을 처리한다. BufferedReader와 PrintWriter 클래스로 이와같이 부드러운 처리가 가능해진다. 차근차근 예제를 공부하면서 오늘 배운건 꼭 여러분의 것으로 만들기 바란다.^^

2011년 6월 18일 토요일

자바의 제네릭(Generics)


자바의 신기술(?)인 제네릭 타입(Generic Types)에 대해서 공부하는 시간을 가져보겠다. 자바5부터 이것저것 달라지고 추가되는 점이 꽤 있어 새로 자바를 공부하는 이들은 그런게 있나보다하고 그냥 받아들이면 되겠지만 잠시 이 세계를 떠났던 이들(?)은 이게 자바인지조차 혼란스러울 것이다. 특히 오늘 공부할 단원인 제네릭 개념은 특히 더하리라 생각된다. 그러나 걱정할 필요없다. 그동안 자바의 제네릭 때문에 잠시 멀리 떠난 이들은 오늘부로 컴백(?)해주기 바란다.ㅎㅎ 필자가 아주 쉬운 설명과 예제로 여러분의 시름을 덜어줄 것이니까 말이다.^^

자바의 제네릭이라함은 처음에 데이터 자료형인 String이나 Integer같은 형태를 처음에 정해놓지 않고 임의의 타입으로 명시해준 후에 나중에 우리가 직접적으로 해당구문을 사용할때 지정하여 사용하는 형태를 말한다. 어떻게 쓰는지 아래를 보면서 뭐가 다른지 살펴보기로 하자.

class Test64
{
String a;
..
...
}

위의 예제는 클래스에 String 타입의 변수 t를 선언한 것이다.

class Test64 <T>
{
T a;
..
...
}

위의 예제는 제네릭 클래스라고 하는데 임의의 타입인 <T>를 이용하였는데(Type의 약자인 T가 보편적인 제네릭 변수로 쓰인다.) 데이터 자료형이 나중에 String이 될수 있고 Integer나 Double 같은 그 외 다른 데이터 자료형으로 쓰일수도 있다. 즉 처음에 어떤 타입인지 지정하지 않고 나중에 여러분이 사용할때 확정짓는 방식을 말한다. 쓰는 방법은 위와같이 클래스 옆에 제네릭 타입을 선언하고 데이터 자료형이 쓰일 자리에 제네릭 타입인 T를 위와같이 써주면 된다. 한마디로 String이나 Integer가 들어갈 자리에 T를 넣어 쓰고 나중에 String이나 Integer를 정해주면 되는 것이다.

class 클래스명 <제네릭타입>
{
..
...
}

제네릭 클래스를 사용하려면 객체 생성을 할때 제네릭타입이 무엇인지를 정해주어야 한다.

Test64 <String> ts=new Test64 <String> ("클래스 객체 ts 생성");

이렇게 하면 위의 T라고 임의로 적어놓았던 타입이 모두 String으로 바꿔서 쓸수있다고 생각하면 된다.

Test64 ts=new Test64("클래스 객체 ts 생성");

위의 구문이 일반적으로 우리가 객체생성을 할때 쓰는 표현인데 클래스뒤에 제네릭 타입을 써주기만 하면 다를게 없다. 제네릭 타입의 위치를 주의깊게 보고 어떻게 쓰이는지만 알면 크게 어려움이 없을 것이다. 그래도 잘 모르겠다고 탄식하지는 말자.ㅎㅎ 아래의 예제를 보면서 실행을 해보면 저절로 이해가 될것이다.^^


예제를 보면서 제네릭 클래스를 어떻게 구현하였는지 살펴보기 바란다. 예제를 보면 알겠지만 제네릭 클래스의 강력한 기능이 무엇인지 이제 파악이 되는가? 만약 자료형을 초반에 지정해 놓았다치면 String이 되었든 Integer가 되었든 한 타입으로밖에 프로그램을 구현할수 없었을 것이다. 다른 자료형을 쓰려면 그만큼의 코딩을 더해야 하고 프로그램이 더욱 방대해질수 밖에 없는데 이렇게 제네릭 타입을 사용하면 자료형을 원할때 골라 쓸수 있으므로 한결 프로그램이 간결해질수 있다.^^ 예제는 풍부한 주석을 달아놓았으므로 그냥 보면 이해될 것이다. 더이상 필자가 해줄것이 없다.ㅎㅎ

와일드카드라 불리는 <?> 제네릭 타입을 아직 설명안했는데 ?라는 뜻은 간단히 아무 자료형이나 가능하다는 것을 뜻한다. 그래서 아무거나 넣어도 다 작동하는 것이다. 그리고 ?와 함께 상속키워드인 extends나 super를 사용하는 방법이 있는데 하위클래스들이 제네릭타입으로 오느냐 아니면 상위클래스들이 제네릭타입으로 오느냐의 차이이다. 이것도 예제를 이리저리 돌리다보면 크게 무리가 없이 알게될 것이다. 쓰는 방법은 아래와 같다.

<? extends 객체자료형>
<? super 객체자료형>

상속의 개념이 제네릭에 녹아있으므로 아래의 상하위 구조도를 보면 이해하기가 더 쉬울 것이다.^^


예제에서 이용한 Number가 위의 그림처럼 Integer의 (직)상위 클래스임을 상기하면서 예제를  살펴보면 이해하는데 무리가 없을  것이다. 제네릭 타입은 클래스나 인터페이스 그리고 메소드에서도 사용이 가능한데 클래스나 인터페이스는 그 나물에 그 밥이니 이번엔 메소드에서 제네릭 타입이 어떤 식으로 쓰이는지 살펴보기로 하자.


메소드에서 제네릭 타입을 쓰려면 위의 예제처럼 리턴값의 위치 앞에다가 제네릭 타입을 선언한후 자료형이 들어가는 위치에다가 위와같이 쓰면 된다. 제네릭 메소드에서는 자료형을 제네릭 클래스처럼 나중에 특별히 정하지 않아도 자동적으로 자바에서 자료형에 맞게 알아서 처리해준다. 예제에서처럼 역시 메소드에서도 제네릭 타입의 위력(?)을 여지없이 느낄수 있다. 생각해보라. 만약 위의 get( ) 메소드에 제네릭 타입을 쓰지 않고 메인메소드의 명령들을 실행하려면 자료형 타입별로 메소드를 다 따로 만들어야 했을 것인데 제네릭 메소드를 씀으로 인해서 코드가 위와같이 아주 간결해지는 것을 확인할수 있다.^^

그렇게 어렵게 느껴왔던 제네릭이 고작 이거였어? 라고 말하는 이가 상당수 있을 것이다. 자바7에서는 제네릭 타입이 다이아몬드(<>)처럼 빛나게 업그레이드되니 방심하지 말자.ㅎㅎ 제네릭 타입은 코드를 간결하게 만들고 여러분이 초반에 프로그래밍할시 자료형을 통일하거나 확정짓기 힘든 상황에 쓰면 아주 강력한 성능(?)을 발휘한다. 자바에서 새롭게 도입되고 달라지는 개념들이 버젼업이 될때마다 계속해서 나올 것인데 그럴때마다 체념하고 두려워하기 보다는 얼마나 예전보다 프로그래밍하기가 더 편해질까라는 관점으로 접근하는 자세를 가지면 마음도 편하고 여러분의 프로그래밍에 대한 자신감과 실력도 한층더 월등해질 것이라 믿는다.^^

2011년 6월 16일 목요일

자바의 어노테이션(Annotation)


Java5부터 새로 도입된 어노테이션(Annotation) 기능에 대해서 알아보기로 하겠다. 즉 여러분이 자바5 이후의 버젼을 설치하였다면 이 기능을 사용하는데 아무런 문제가 없을 것이다. 필자가 처음에 받으라고 올린 자바 설치 프로그램은 자바6이므로 당근 어노테이션 사용가능하다.^^ 잠시 들어가기 전에 Java5는 뭔지 아리쏭해하는 이들이 있을지도 모르겠다. 특히 오래전에 자바를 공부하다가 다시 공부하는 이들은 자바5는 뭐고 자바6는 뭔지 이게 완전히 다른건지 궁금해 하는 이들을 위해 필자가 잠시 정리를 하고 본 단원을 진행하겠다.

새로 자바를 공부하는 이들은 자바6가 요즘 나온 프로그램이구나라고 생각하면서 쓰겠지만 오래전에 자바를 공부한 이들은 아마 버젼 1.2 아니면 1.3 그래도 최근이었으면 1.4 정도까지 하다가 그 뒤부터 잠시 손을 뗀 이들이 보통 혼란스러워한다. 자바가 새로운 기능과 문제점을 보완하고 업데이트해 오면서 줄곧 1.xx 형태로 해왔는데 메이저급 업데이트를 함에도 불구하고 거의 제품에 차이가 없다고 생각하는 이들이 많아 확연히 다르다는 것을 강조하기 위해 버젼을 Java5(=1.5) 그리고 우리가 지금 쓰고 있는 Java6(=1.6)로 표기하고 있다고 알고 있으면 된다. 한마디로 엄청 달라진것 같이 느껴지니 그런 의미에서는 확실히 성공한듯 하다.ㅎㅎ

자 이제 본격적으로 어노테이션에 대해서 설명해 보겠다. 우리말로 해석하자면 주석이라는 뜻인데 이게 사실 우리가 여태까지 설명을 쓸때 주석(//)을 썼지만 이런 주석이랑 같은 의미로 생각하면 내용을 파악하기 힘들다. 그래서 영어 그대로 어노테이션이라고 표기하니 어노테이션에 무슨 기능이 있는지 여러분이 이번 시간을 통해 알아놓고 필요할때 써먹을수 있으면 그걸로 족하니 안심하기 바란다. 언제나 그렇듯 어노테이션에 대해서 정말 모르겠다하는 이들은 오늘 강좌를 들으면 고작 이런거였어?라는 말이 나오도록 만들어 줄것이니 본 강좌에 집중하기 바란다.^^

어노테이션에서 여러분이 쓸수 있는 기능이 다양하지만 그중에서도 @Deprecated와 @Override가 아주 유용하게 써먹을수 있는 어노테이션이므로 본 단원에서는 이 두가지에 대해서 배워보기로 하겠다. 일단 어노테이션을 쓰려면 자바코드로 어떻게 써야하는지 알아보자.

@어노테이션명

위와 같이 AT으로 불리는 골뱅이 마크를 쓰고 싶은 어노테이션 이름앞에다가 붙이면 작동한다. 어노테이션은 자바 프로그램에 영향을 주는 것이 아니라 컴파일할때 개발자에게 주석같이 설명처럼 알려주는 형태를 말한다. 어노테이션은 클래스나 필드 혹은 메소드 앞에 붙여서 사용하며 끝에 세미콜론(;)은 붙이지 않는다. 예제를 보면서 필자의 설명을 들으면 저절로 이해가 될것이니 감이 오지 않는 이들은 아래 예제를 보면서 따라오기 바란다.^^


강이의 자바강좌
클래스 A의 one 메소드

위의 예제를 실행하면 위와 같은 결과가 나온다. 예제가 간단하니 이해못할 이들은 없을 것이라 본다. 첫번째로 @Deprecated 어노테이션에 대해서 설명하겠다. one( )이라는 메소드 앞에 붙였으니 one( ) 메소드를 Deprecated로 어노테이션 처리하라는 뜻이다. deprecated는 사전적 의미로 비난하다 반대하다라는 뜻이 있지만 프로그래밍 용어로는 사용을 피해달라 사용을 자제해달라는 의미로 쓰인다. 영어만 해석했는데도 이해가 팍팍되고 있으리라 생각한다.ㅎㅎ 즉 기존에 있는 one( ) 메소드를 쓰지말고 필요하면 다른걸로 만들어서 써달라는 뜻으로 해석하면 된다. 위의 예제는 컴파일이 되어 실행이 가능하지만 컴파일시 이런 메세지를 준다.

Note: C:\Test63.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.

이 메세지는 @Deprecated라는 어노테이션을 써서 컴파일시 이렇게 알려주는 것이다. 그럼 이런 기능은 언제 쓰라고 만든 것일까? 이해하기 쉽도록 필자가 예를 들어보겠다. 여러분이 프로그램을 만들었는데 지금은 이 기능을 지원하지만 다음 버젼업된 프로그램에서는 이런 기능을 없애려 한다던지 다음부터는 더 향상된 다른 기능으로 대체하려고 계획하고 있는데 기존에 지원하던 기능을 계속해서 쓴다면 나중에 여러분이 계획했던 프로그램을 만들때 많은 비용과 시간에 차질이 생길수 밖에 없을 것이다. 이런 것을 방지하고자 만든 기능이다.

그럼 다음으로 클래스 B에서 @Override라는 어노테이션을 two( ) 메소드 앞에 썼는데 이건 무엇을 의미하는 것일까? 일단 override라는 뜻은 기억하는가? 자바에서 상속시 오버라이드는 리턴타입이니 매개변수니 메소드명이니 이런거 모두 같고 내용이 다른 것을 말한다고 이미 예전 강좌에서 배웠는데 기억하나 모르겠다.ㅎㅎ

위의 예제에서는 @Override를 썼지만 two( ) 메소드의 오버라이드를 정확히 구현하였으니 문제가 없어 컴파일시 아무런 에러도 나지 않고 프로그램이 실행된다. 하지만 여러분이 void two( ) 메소드 대신에 void twp( ) 메소드로 이름을 잘못 썼다던지 void two(int a) 메소드로 매개변수를 넣었다던지 하면 컴파일시 에러가 난다. 직접 이런 식으로 고쳐서 실행해 보기 바란다. 에러가 나서 실행이 되지 않을 것이다. 정말 대단하지 않은가? 만약 two( ) 메소드앞에 @Override 어노테이션이 없었다면 철자가 틀리든 매개변수가 있든 상관하지 않고 에러없이 실행된다. 상속받았다고 해서 오버라이드만 하라는 법은 없으니까 말이다. twp( )라고 썼으면 자바는 메소드를 새롭게 인식해서 실행할 것이고 two(int a)도 자바의 다형성 중에 하나인 오버로딩한 형태로 인식하므로 전혀 문제될것이 없다. 이런 기능이 굳이 필요할까? 라고 반문하는 이가 있을지 모르겠다.

지금은 예제가 짧아서 별것 아닌듯이 느낄지 모르겠으나 프로그램이 좀 복잡하고 길면 오버라이드하려고 계획하고 프로그램을 짰어도 오타가 있을시 이를 찾아내는데 상당히 애를 먹게된다. 컴파일하고 실행하는데는 아무런 문제가 없을테니까 말이다. 다만 여러분이 생각한데로 똑같이 프로그램을 만들지 못한 것이니 프로그램 안에 버그(?)가 도사리고 있는게 문제가 될것이다.ㅎㅎ

사실 그리 난해한 내용은 아니므로 정확한 의미만 파악한다면 어노테이션을 자유자재로 여러분이 만드는 프로그램에서 써먹을수 있을 것이다. 특히 어노테이션의 @Override 기능은 오버라이드할때 될수 있으면 쓰는 습관을 갖기 바란다. 여러분이 본의아니게 조그마한 실수를 해도 자바 컴파일러가 알아서 여러분을 구원(?)해 줄테니까 말이다.^^

2011년 6월 10일 금요일

자바의 데이터그램 프로그래밍(Datagram Programming)


UDP(User Datagram Protocol) 방식의 데이터그램 프로그래밍에 대해서 살펴보기로 하자. 네트워크 프로그래밍 단원에서 이미 언급하였지만 이전까지 배운 TCP 소켓 프로그래밍과는 다르게 뭐하나 믿고 신뢰할 구석이 없는 방식이라 생각하면 된다. 너무 매정할지 모르나 메세지 송신중에 데이터가 손실될수도 있고 도착했는지 안했는지 확신할수도 없을뿐더러 중복될수도 있고 순서대로 갈지도 알수 없는데 한마디로 상대방이 데이터를 제대로 받았는지에 대한 어떠한 검사도 수행하지 않는다. 그런데 이걸 왜 알아야되는가? 상황에 따라서 이렇게 신뢰성이 낮은데도 불구하고 빠르게 교신을 요하는 경우(?)가 있을때가 있는데 그럴때 사용하는 것이 바로 데이터그램 프로그래밍이다. 다르게 말하면 순서대로 오지 않아도 크게 지장이 없거나 메세지가 순서대로 오지 않아도 괜찮고 처리시간을 단축하기 위한 네트워크 프로그램에 적합하다고 할수 있겠다. 예를 들어 데이터의 품질과 상태보다 빠르고 연속성이 중요한 스트리밍 서비스를 제공하는 인터넷 전화나 인터넷 방송같은 동영상 스트리밍 서비스를 구현할때 어울리는 방식이라 생각하면 이해가 될것이다.


위의 그림은 UDP 데이터그램의 구조(Structure)를 표현한 것이다. 자바의 프로그래밍 관점에서 데이터그램 프로그래밍과 소켓 프로그래밍의 큰 차이점을 들어보자면 데이터그램 프로그래밍에서는 목적지에 대한 정보를 갖고 전송한다는 점과 데이터를 바이트로 전환한 패킷으로 송수신한다는 점 그리고 소켓 프로그래밍에서의 서버소켓처럼 따로 연결을 관리하는 장치는 없고 대신 데이터그램 소켓에서 방금 말한 데이터그램 패킷을 송수신하기 위한 소켓 기능을 제공한다는 점이 크게 다르다고 할수 있겠다. 덧붙여 말하자면 데이터그램 프로그래밍에서는 서버소켓이 없으므로 클라이언트로부터 오는 데이터그램 패킷을 데이터그램 소켓에서 무조건적으로 받아들여 읽고 쓴다. 데이터그램 프로그래밍에 대한 설명은 이 정도로 하고 이제 예제를 통해서 자바에서는 데이터그램을 네트워크상에서 어떻게 사용하는지 알아보기로 하겠다.

Test62Server.java


Test62Client.java

자 연달아서 데이터그램을 사용할 서버(Test62Server.java) 프로그램과 클라이언트(Test62Client.java) 프로그램이다. 예제를 보면 알겠지만 메세지를 받았네 연결이 되어있네 이런 문구는 여러분의 이해를 돕기 위해 필자가 프로그램에 삽입한 것이지 그 이상을 기대(?)하지는 말기 바란다. 초반에 얘기했지만 자신있게 확신하고 얘기할수는 없는 것이나 우리가 무슨 대용량의 데이터 품질을 요하는게 아니니 뭐 그리 큰 지장은 없이 원활하게 돌아가는구나 생각하기 바란다.

DatagramSocket
DatagramPacket

그럼 이제 예제의 서버 프로그램을 설명하겠다. 저번에 배운 소켓 프로그래밍과 하는 내용은 별반 다를게 없다. 다만 데이터그램을 이용한 점이 다르니 저번 시간을 헛되이 보내지 않았다면 그리 어려울건 없을 것이다. 우리가 데이터그램 프로그래밍에서 알아야할 핵심 클래스로는 위의 데이터그램 소켓 클래스와 데이터그램 패킷 클래스를 들수 있겠다. 서버에서는 데이터그램 소켓을 이용해 특정 포트를 열어두고 데이터그램 패킷을 보내거나 받기위한 준비를 하는데 데이터그램 소켓에 있는 receive( ) 메소드로 보내는 사람의 IP 주소와 포트번호도 함께 들어있는 패킷을 받는다. 받은 패킷을 바이트 배열로 전환하는 과정(?)을 거쳐서 다시 클라이언트로 보내고 처리를 마친다. 무한 for 룹을 돌렸으므로 계속해서 이런 과정이 반복된다. 본 예제는 서버를 셧다운(?) 하지 않는한 클라이언트의 요청을 계속적으로 처리하도록 되어있다. 이런 프로그램의 흐름만 알면 본 예제에 주석이 자알~ 달려있으니 쉽게 이해가 될 것이다.

그럼 이번엔 클라이언트 프로그램을 보기로 하자. 역시 데이터그램 소켓을 이용해 패킷을 보낼 준비를 한다. 보낼 내용을 키보드를 통해 유저에게서 입력받고 내용을 바이트 배열로 전환하여 내용과 사이즈 그리고 보내는 곳의 주소와 포트를 함께 패킷에 담아 서버로 전송한다. 그리고 서버에서 다시 보내올 패킷을 받기 위해 아까처럼 데이터그램 소켓 클래스에 있는 receive( ) 메소드를 이용하여 서버로부터 바이트로 된 패킷을 받아 문자열로 전환하여 화면에 프린트하고 다음 메세지를 유저로부터 기다린다. 아무것도 입력하지 않으면 데이터그램 소켓을 종료하고 프로그램을 끝내는 프로그램이다.



예제를 위와같이 순서대로 실행해서 살펴보면 위와 비슷한 결과(?)를 얻을수 있을 것이다. TCP 소켓 프로그래밍을 정복(?)한 여러분이라면 오늘 배운 UDP 데이터그램 프로그래밍도 그리 어렵지 않았을 것이다. 프로그램을 보다시피 패킷을 송수신할때 바이트 배열을 이용하는게 특이한 점이니 어떻게 바이트를 이용해서 주고 받는지 주의깊게 관찰하기 바란다. 그래도 정리가 안되는 안타까운 이들(?)을 위해 떠나기에 앞서 그림 한장을 아래에 남긴다. 잘 보고 오늘 강의를 잘 정리하기 바란다.^^

2011년 6월 9일 목요일

소켓을 이용한 서버와 클라이언트 프로그램

저번 시간에 배운 서버와 클라이언트 프로그램을 한층더 업그레이드하는 시간을 가져보기로 하겠다. 잠시 저번 강좌의 예제 프로그램에 대해서 설명하자면 서버 프로그램을 가동한후 클라이언트 프로그램이 특정 포트로 연결해서 서버로 메세지를 송신하고 다시 서버로부터 수신받아 프로그램이 끝나는 아주 심플한 프로그램이었다. 해봤으면 알겠지만 상당히 아쉬운 부분이 많았을텐데 특히 메세지를 원하는만큼 직접 전달하고 계속해서 송수신할수 있도록 만들순 없을까 하는 이들이 있었을 것이다.

이런 이들의 기대를 져버리지 않기위해 오늘 만들 프로그램은 메세지 하나만 보내고 끝나는게 아니라 계속해서 원하는 메세지를 입력할수 있게끔 만들고 더이상 입력이 없으면 알아서 서버와 클라이언트의 연결이 끊기도록 프로그램을 구성할 것이다. 본 강의를 보기 전에 본인이 직접 이와같은 프로그램을 만들어보고 난후에 본 단원을 공부하기 바란다. 그럼 오늘 만들 서버 프로그램과 클라이언트 프로그램의 예고편(?)을 순서대로 먼저 보기로 하자.



Test61Server.java
Test61Client.java

위의 두 파일을 다운받아 실행하면 그림과 같은 결과값을 얻을수 있다. 일단 서버 프로그램(Test61Server.java) 소스부터 설명하겠다. 저번 시간의 연장선상에 있으므로 바뀐 부분만 알면 공부하는데 큰 무리가 없을 것이다. 서버에서 메세지를 계속해서 받도록 만들어야하니 반복문을 사용해야겠구나 어렴풋이 짐작이 될 것이다. 예제에서는 while문을 사용하였고 그안에서 if문으로 입력값을 검사해 더이상 입력값이 없다고 확인되면 서버는 클라이언트와의 연결을 끊고 프로그램을 종료한다. 또한 try catch문을 사용하였는데 클라이언트에서 불가피하게 연결이 끊겼을시 서버에서도 이를 감지해 프로그램을 종료하도록 만들기 위해 try catch 구문을 사용하였다. 예제를 실행하면서 테스트 해보면 알게 될것이다.^^

다음은 클라이언트 프로그램(Test61Client.java)을 살펴보기로 하겠다. 일단 처음에 연결이 되면 축하 메세지를 띄운다. 그럴듯하게 보이라고 한번 넣어봤다.^^ Socket 클래스에 있는 isConnected( ) 메소드를 이용해 연결되었다는 true값을 돌려주면 축하 메세지가 나온다. 당근 항상 나올꺼다.ㅎㅎ 그리고 키보드로부터 문자열을 입력받도록 만드는데 어떻게 자바에서 구현하는지 모른다면 필자가 이에 관련한 강좌를 한적이 있으니 다시 한번 읽어보고 오기 바란다. 그리고 입력받은 메세지를 저번처럼 서버에 보내서 송수신을 하는데 이 부분도 서버처럼 클라이언트에서도 while문을 이용해 계속 반복해서 메세지를 보낼수 있게 만들고 더이상 메세지가 없는지 String 클래스에 있는 isEmpty( ) 메소드로 문자열에 입력값이 비어있는지 체크해서 비어있으면 while문을 빠져나와 프로그램을 종료하는 예제이다.

예제의 서버와 클라이언트 프로그램은 이해를 돕기 위해 상당히 쉽게 구성하였으나 안에 들어있는 내용은 매우 심오(?)하기 짝이 없다. 자바의 네트워크와 입출력에 관련된 부분을 함께 건드리고 있어 짧지만 조금 힘겨워하는 이가 있을지도 모르겠다. 허나 지금까지 강이의 자바강좌를 열심히 독파해온 이들이라면 문제없을것이라 믿는다. 오늘 강좌가 힘들게 느껴졌다면 예제와 관련된 저번 강좌들을 다시 복습하는 시간을 갖기 바라면서 오늘 강의는 이만 끝내겠다.^^

자바의 소켓 프로그래밍(Socket Programming)

오늘은 그동안 뜸(?)을 들여왔던 자바의 네트워크 프로그래밍의 초석을 다지게될 TCP 프로토콜 방식의 소켓 프로그래밍(Socket Programming)에 대해서 공부해 보기로 하자. 소켓(Socket)이란 네트워크상에서 서버와 클라이언트 두개의 프로그램이 특정 포트를 통해 양방향 통신이 가능하도록 만들어주는 소프트웨어 장치라 말할수 있다. 좀 더 자세히 설명하자면 자바에서는 소켓 클래스가 서버와 클라이언트 프로그램들간의 연결을 가능하도록 만들어준다. 더 자세하게 설명하자면 java.net 패키지에 있는 두개의 클래스 ServerSocket 클래스(서버측에서만 필요)와 Socket 클래스(서버와 클라이언트측 양쪽에서 다 필요)를 이용하여 서버와 클라이언트간의 통신을 가능하게 만든다.

자바의 네트워크 프로그래밍에 대해 아무런 생각(?)이 없는 이들은 예전에 필자가 이 부분에 대해 설명하였으니 관련 강좌를 한번 읽어보고 오기 바란다. 네트워크 프로그래밍은 상당히 즐겁고 흥미로운 분야인데도 불구하고 자바를 공부하는 이들의 태반이 고통아닌 고통을 여기서 겪고 있고 자포자기하는 경향이 많은데 그런 이들에게 오늘 강좌는 여러분에게 가뭄에 단비같은 아니 사막에서 오아시스를 찾은 그런 큰 기쁨을 여러분에게 안겨줄 것이다. 그만큼 자세하고도 세세한 부분까지 여러분의 이해를 돕기위해 초정성(?)을 기울였으니 여러분도 그에 응답하여 잠시 주위의 모든 것을 차단하고 이번 강좌에 더도말고 30분만 투자하기 바란다. 초반에 언급하였지만 그동안 자바의 네트워크만 언급해도 몸서리쳤던 이들도 본 단원의 소켓 프로그래밍을 통해 자바 네트워크 프로그래밍의 반석을 오늘 이 자리에서 다지게되는 귀중한 시간(?)이 될것이라 확신한다.^^

자바가 이렇게 많은 이들에게 사랑받을수 있었던 것은 네트워크상에서 부담없이 구현되는 애플릿의 영향이 컸고 그 중에서도 대표적인 것이 통신상에서 유저들이 서로 간단히 대화할수 있도록 만든 자바 채팅 프로그램이라 할수 있겠다. 이런 자바 채팅 프로그램의 기초가 바로 서버와 클라이언트간의 연결이 가능해야하는 것인데 이게 소켓 프로그래밍으로 가능하다. 본 단원에서는 소켓 프로그래밍의 기본을 배우는 시간인만큼 클라이언트가 어떻게 서버로 연결시도를 하고 서버가 어떻게 클라이언트의 연결요청을 받아들이고 처리하는지를 프로그램으로 만들어볼 것이다. 오늘은 두개의 프로그램을 만들텐데 하나는 서버측에서 사용할 자바 프로그램(Test60Server.java)과 클라이언트측에서 사용할 자바 프로그램(Test60Client.java)이다. 자바파일 이름은 필자가 편하게 붙인 것이니 딴지 걸지 말기 바란다.ㅎㅎ 그럼 서버측에서 사용할 프로그램을 어떻게 만들어야되는지 먼저 살펴보기로 하자.


위의 그림은 자바에서 서버 프로그램이 어떤식으로 동작하는지 전체적인 개요를 보여주고 있는데 서버에서 클라이언트의 요청을 받아들이려면 일단 ServerSocket 클래스를 생성하고 accept( ) 메소드를 이용하여 클라이언트의 요청을 받아들일 준비를 한다. 그리고 서버의 Socket 클래스를 통해 서버와 클라이언트간의 소켓 연결고리를 만들어 서로 통신할수 있는 선로를 확보하고 클라이언트의 메세지를 BufferedReader 클래스를 통해 받아들이고 이 받아들인 메세지를 PrintWriter 클래스를 통해 서버측 화면에 출력하고 다시 클라이언트로 이 메세지를 보낸다. 여기까지가 서버 프로그램에서 하는 일이다.


서버측에서는 소켓 간에 통신할수 있도록 선로를 만들어주는게 주된 일이라 하겠다. 자바 소스를 보면 이해가 쉬울 것이다. 주석을 꼼꼼하게 달아놓았으니 어려울게 없다고 본다. 그럼 서버 소스를 살펴보자. ^^


소켓을 이용하여 서로 통신할수 있도록 만들려면 포트가 필요하다. 예제에서는 2011년을 기념하는 뜻(?)에서 포트번호를 2011로 지정하였다. 즉 서버와 연결하려면 클라이언트에서 포트번호 2011로 연결을 시도하여야함을 알수 있다. 예제에 표기된 상세한 주석으로 인해 사실 설명을 따로할 필요가 없을 정도다. 그냥 천천히 예제 소스를 보기만 해도 이해가 될 것이다.

자 이제는 클라이언트쪽을 보기로 하자. 클라이언트에서는 Socket 클래스를 생성하여 서버로 연결요청을 하고 서버에서 연결을 수락하면 PrintWriter 클래스를 통해 메세지(강이의 자바강좌)를 서버로 보낸다. 그리고 BufferedReader 클래스를 이용하여 서버에서 받은 메세지를 클라이언트측 화면에 출력한다. 즉 클라이언트에서 송신한 메세지가 서버를 통해 다시 그 메세지를 수신하는 과정을 확인할수 있다.


위의 클라이언트 예제 소스를 보면서 자바로 어떻게 쓰는지 살펴보기 바란다. 이것도 역시 주석이 빵빵(?)하므로 그냥 보면 저절로 깨우쳐지리라 생각한다. 이곳에 쓸 설명을 보기 쉽도록 주석에 다 달아놓았으니 설명 부족하다고 그러지 말아라.ㅎㅎ


바로 위의 그림이 오늘 배운 서버와 클라이언트 프로그램의 전체 개요도라 할수 있겠다. 전체적인 소켓 프로그램의 흐름이 위와 같다. 자 그럼 마지막으로 위의 프로그램들을 어떻게 실행할수 있는지 살펴보기로 하겠다. 네트워크 즉 쌍방향 프로그래밍인만큼 서버와 클라이언트쪽 두개의 프로그램을 만들었다. 따라서 실행도 양쪽에서 해야하므로 명령프롬프트창을 열어 서버 프로그램을 실행시킨 후에 다시 명령프롬프트창을 열어 클라이언트 프로그램을 실행시키면 방금 우리가 공부한 소켓 프로그램이 정상적으로 작동할 것이다.



이로서 소켓 프로그래밍에 대한 실행까지 마쳤다. 해보면 알겠지만 서버와 클라이언트 프로그램에서 서로 송수신하는 과정을 보는 것만으로도 흥미진진할 것이다. 소켓 프로그래밍은 자바의 네트워크 프로그래밍을 논할때 빠지지 않는 기본중의 기본이다. 본 예제를 뚫어지게 공부하다 보면 소켓 프로그래밍에 대해서 어느정도 자신감(?)이 생겨나리라 생각하니 지겹도록 쳐다보기 바란다. 수고 많았다. ^^

2011년 6월 6일 월요일

URL을 이용해 페이지 소스 보기


예제와 함께 간략하게 웹상에서 관련페이지의 소스를 읽어들이는 방법을 자바 테크놀로지(?)를 통해 살펴보겠다. 예제는 본 강이의 자바강좌를 볼수 있는 블로그 주소인 http://alecture.blogspot.com의 소스를 직접 읽어들이는 예제이다. 즉 여러분이 웹브라우저상의 메뉴에 있는 페이지 소스 보기와 같은 결과를 얻을수 있다.

예제를 보면 아주 심플하지만 내용은 심오(?)하다. 일단 openStream( ) 메소드를 이용하기 위해 URL 클래스의 생성자를 주소와 함께 만들고 그 내용을 BufferedReader를 통해 읽어들이는데 예전 강좌를 공부했으니 알겠지만 InputStreamReader를 그전에 읽어들인다.

openStream( ) 메소드는 URL을 읽어들이기 위해 사용하고 리턴값은 InputStream 형태로 돌려주어 InputStreamReader에서 관련값을 무리없이 쓰고있다. openStream( ) 메소드는 openConnection( ).getInputStream( )의 기능을 함축하고 있는데 간단히 설명하자면 URL의 내용을 보기 위해서는 관련 URL에 접근해서 읽어내야하므로 이렇게 메소드를 이용해 몇단계를 거쳐서 소스를 읽어낼수 있는 것이다. 그 다음이야 별로 어려울 것이 없겠지만 while 구문은 소스를 한라인씩 읽어들이면서 내용이 끝날때까지 계속적으로 반복하면서 출력하고 마지막에 읽어들인 버퍼를 닫아준다.

방금 위에서 언급한 접속문구를 이용해서 같은 결과를 도출할 수 있는데 URLconnection 클래스를 이용하면 가능하다. 결과는 똑같지만 여러분이 자바 소스를 이해하거나 활용하는 측면에서는 아래의 예제가 도움이 더 많이 될것이니 이렇게도 쓸수 있다는 것을 알아두기 바란다.


예제를 이용해서 다른 웹사이트 주소를 입력하고 실행하면서 페이지 소스 보기 기능이 자바를 이용해 어떻게 구현되고 있는지 살펴보기 바란다. 자바 입출력(I/O) 부분에서 빠지지 않고 등장하는 것이 버퍼와 스트림에 관련된 구문인데 예제에도 쓰였지만 잘 받아들여지지 않는다면 예전 강좌 초반에 설명한 입출력 관련 강좌를 다시한번 복습하고 오기 바란다. 네트워크 프로그래밍에서 서버와 클라이언트간의 커뮤니케이션은 필수이기 때문에 앞으로 계속해서 여러분을 괴롭힐지도 모른다.^^

2011년 6월 5일 일요일

URL을 이용한 구문분석


자바의 네트워크 프로그래밍에 대한 첫단추로 URL을 공부해보기로 하자. URL(Uniform Resource Locator)은 인터넷에서 자원(Resource)을 말하는데 여기서 말하는 자원이란 인터넷 프로토콜에 따라서 다를수 있겠지만 우리가 일반적으로 웹브라우저에서 사용하는 http의 경우 html 웹페이지나 이미지 파일 혹은 자바 애플릿 같은 http가 지원하는 관련 파일들을 말하는데 URL은 이런 자원들이 접근하는데 필요한 프로토콜의 이름이나 도메인 이름 혹은 우리가 파일을 저장한 경로명등으로 구성이 된다. 지금 필자가 말하고 있는 프로토콜 같은 용어들이 생소하다면 저번 강좌를 뒤적거려 찾아보기 바란다. 필자의 리바이벌(?) 강의는 없다. ㅎㅎ


http://alecture.blogspot.com/java
여기서는 alecture.blogspot.com이라는 서버 컴퓨터의 http 응용 프로그램인 웹브라우저로 읽을수 있는 페이지를 나타낸다. /java는 그 컴퓨터의 디렉토리를 말한다. 여러분이 일반적으로 사용하고 있는 윈도우즈의 디렉토리 주소창이랑 별반 다를바 없을 것이니 금방 이해가 되리라 본다.

http://alecture.blogspot.com/kangi.jpg
필자의 멋진(?) 사진을 웹페이지에 저장하고 사용자들 즉 여러분의 웹브라우저에서도 볼수 있게 URL을 적을수 있다.

http://alecture.blogspot.com/javaboard.cgi?db=superboard
게시판 cgi의 URL은 위와 비슷한 주소를 가질 것이다.

ftp://alecture.blogspot.com/network.class
ftp 프로토콜을 이용해서 network.class란 파일을 다운로드 하기위해 URL을 적으면 위와 같을 것이다.

URL과 인터넷주소의 의미자체가 애매모호한 측면이 있지만 위에서 보듯이 URL이 보다 이런 여러형태의 프로토콜과 쓰는 표현방식을 포괄적으로 의미하는거라 생각하면 될것이다. 자 이제 서론은 이 정도로 하고 이런 URL을 자바에서 어떤 식으로 이용하는지 살펴보겠다. 단순하게 요약하자면 java.net 패키지에 있는 URL 클래스를 자알~ 이용하면 된다.^^


protocol = http
authority = alecture.blogspot.com:3890
host = alecture.blogspot.com
port = 3890
port(default) = 80
path = /book/edition/main.html
query = name=network
filename = /book/edition/main.html?name=network
address1 = http://alecture.blogspot.com:3890/book/edition/main.html?name=network#JAVA
address2 = http://alecture.blogspot.com:3890/book/edition/main.html?name=network#JAVA
user = null
hash(aURL) = 1494879235

==========강이의 자바강좌==========

protocol = http
authority = alecture@blogspot.com
host = blogspot.com
port = -1
port(default) = 80
path =
query = null
filename =
address1 = http://alecture@blogspot.com
address2 = http://alecture@blogspot.com
user = alecture
hash(bURL) = 1252959383

위의 예제는 URL 클래스를 이용하여 관련값을 뽑아본 것인데 그냥 예제를 보면 필자의 설명없이도 저절로 알게 될 것이다. 내용이 길어보이지만 단순히 기능들을 출력한 것에 지나지 않으니 길다고 그냥 넘겨버리는 게이른 이(?)가 없길 바란다. URL 클래스를 라이브러리에서 찾아봤으면 알겠지만 호스트나 포트값을 생성자를 통해 값을 얻어낼수도 있지만 URL 클래스에 있는 get 메소드들을 적절하게 이용하면 아주 간편하게 예제처럼 원하는 값을 얻어낼수 있다. 저번 시간 강좌를 보면 알겠지만 http는 포트가 80번에 예약이 되어 있다. 따라서 기본값이 자동으로 80이 출력되는 것이다. 만약 주소를 http 대신에 ftp로 고친다면 어떻게 될까? 답은 저번 강좌에 이미 설명하였지만 직접 고쳐서 실행해보기 바란다. 그 밖에는 특별히 설명할 건덕지가 없어보이니 예제를 응용하면서 URL 클래스와 더욱더 친해지는 시간(?)을 갖기 바란다.^^