프로그래밍 배우기 좋은 사이트들 

프로그래밍 (Programming)

Programming IThttp://itguru.tistory.com


개발자의 하루http://devday.tistory.com


PHPSchool - PHP 개발자 커뮤니티http://phpschool.com


KLDP - 리눅스 개발자 커뮤니티http://kldp.org


MSDN 라이브러리http://msdn.microsoft.com/library



최종 업데이트: 2012년 10월 19일 오전 12:25  미국 동부시간.


언어의 기초사항

 

1. 자바 주석문
1) C, C++ 언어 스타일의 주석문
자바 언어는 주석문을 자바 source 코드 내에 프로그램에 수행에 불필요한 코드를 삽입할 수 있습니다.
주석문을 사용하면 source 코드를 설명하는 코멘트를 첨가할 수 있습니다.

C 스타일 주석, 여러 줄에 걸쳐서 사용할 수 있습니다. 형태는 다음과 같습니다.
/* */

C++ 스타일 주석, 한 줄을 주석으로 사용할 때 편리합니다. 형태는 다음과 같습니다.
//

2) javadoc 주석문
javadoc 주석문을 사용하면 해당 class의 상속관계를 표현하는 계층도나 class 멤버들에 대한 설명 등을 html 파일 형태로 제공하는 문서(document)를 만들 수 있습니다. 이러한 문서는 다음과 같이 source프로그램을 javadoc명령에 의해 실행시켜 생성합니다.

javadoc Hello.java

다음은 javadoc 명령 실행시 생성되는 html 파일들의 리스트입니다.

Loading source file Hello.java...
Constructing Javadoc information...
Building tree for all the packages and classes...
Building index for all the packages and classes...
Generating overview-tree.html...
Generating index-all.html...
Generating deprecated-list.html...
Building index for all classes...
Generating allclasses-frame.html...
Generating index.html...
Generating packages.html...
Generating World.html...
Generating serialized-form.html...
Generating package-list...
Generating help-doc.html...
Generating stylesheet.css...
index.html이나 index-all.html 또는 Hello.html 파일을 열어서 보면 해당 source 파일의 상속관계, 구성 멤버들에 대한 정보를 알 수 있습니다.

2. 자바 source file 구조
1) 파일 이름 만들기
자바 파일 이름은 반드시 .java 확장자로 끝나야 합니다. (jav 또는 JAVA가 되지 않게 꼭 주의하셔야 합니다.)
그리고 만약 source 안에 public인 top level class가 있다면 파일 이름은 반드시

public인 class 이름 .java

로 하셔야 합니다.

public class Hello {
public static void main(String[] args) {
System.out.println("Hello World");
}
}

위와 같은 경우 저장할 파일 이름은 반드시 Hello.java로 하여야만 하는 것입니다.

public class Hello {
public static void main(String[] args) {
System.out.println("Hello World");
}
}

class World {
void print() {
System.out.println("World");
}
}


위의 source 파일 이름은 Hello.java 이겠지요?
자바는 컴파일된 후 실행 파일 이름이 .class의 형태로 나옵니다.
따라서 위의 source 프로그램이 컴파일되면 Hello.class 와 World.class 두 개의 파일이 만들어집니다.
물론 이때 Java interpreter와의 실행에는 main 메소드를 가지고 있는 Hello.class를 사용하여야만 하겠지요.

public class Hello {
public static void main(String[] args) {
System.out.println("Hello World");
}
}

public class World {
void print() {
System.out.println("World");
}
}

위와 같은 source 프로그램 코딩은 잘못된 것입니다. 왜냐하면 public은 두 개인데 파일은 하나 밖에 만들 수 없으니까요. 만약 두 class 모두 다 꼭 public이어야만 한다면 파일을 따로 만들어야만 합니다.

class Hello {
public static void main(String[] args) {
System.out.println("Hello World");
}
}

class World {
void print() {
System.out.println("World");
}
}

위의 source 프로그램과 같이 public인 class가 하나도 없는 경우라면 파일 이름은 어떤 class의 이름을 사용하여도 상관없습니다.

class Hello {
public static void main(String[] args) {
System.out.println("Hello World");
}
}

public class World {
void print() {
System.out.println("World");
}
}

위의 source 파일같은 경우 Hello.java로 저장하면 오류가 발생합니다. public이 있는 World.java로 저장하여 컴파일하고 실행시에는 main 메소드를 가진 Hello로 실행합니다.

2) 소스 파일의 기본 구조
source 파일의 구조는 문장에 따라서 순서가 정해져 있습니다.
package 선언문
import 문
class 정의문

즉, 위와 같이 3개의 top level element는 순서에 의해 사용되어야만 하는 것입니다.

이 중 package, import 문장은 꼭 사용하지 않을 수도 있지만, 필요에 따라 source 안에 사용해야 한다면 반드시 위의 순서에 따라 주어야 합니다.

package my.firstpack;
import java.awt.*;
import java.util.*;

public class Hello {
public static void main(String[] args) {
System.out.println("Hello World");
}
}

4. Keyword 와 Identifier
1) Keyword 리스트
C 프로그래머를 위한 몇가지 주의사항은

C에서 많이 쓰셨던 sizeof operator가 자바에는 없다는 것입니다. 이 operator는 자바에서 더 이상 존재의 의미가 없기 때문에 빠지게 된 것.

NULL, TRUE, FALSE 같이 C에서 keyword는 아니지만 #define 문으로 정의해서 사용하던 단어들이 자바에서는 소문자로 바뀌어서 null, true, false와 같은 keyword로 사용됩니다.

자바는 goto, const 같은 단어들을 실제로 구현은 안했지만 keyword로 등록 시켜놓았습니다.

2) Identifier를 만드는 규칙
자바 identifier는 class 이름, 메소드 이름, 변수 이름, 문자 label 등에 사용됩니다.

자바는 일반 문자, 숫자, 그리고 특수 문자('_' 와 '$')등을 조합하여 identifier를 만들 수 있습니다. 이때 반드시 첫번째 문자는 숫자가 아닌 단어로 시작해야 하며 특수 문자도 첫번째 문자로 올 수 있습니다.

자바 keyword는 identifier로 사용할 수 없습니다. 그러나, keyword를 포함하는 단어는 identifier로 사용할 수 있습니다. identifier는 공백을 포함할 수 없습니다.

자바는 ASCII코드를 넘어선 Unicode를 지원하기 때문에, 일반 문자로 'a'-'z', 'A'-'Z' 뿐만 아니라 한글도 사용할 수 있게 되어 identifier를 한글로 만들 수도 있습니다.

그리고 identifier들은 case sensitive하고 실제 maximum length에 대한 제한은 없습니다.


5. 코딩 Convention
1) class 이름과 interface 이름 정하기
class나 interface의 이름은 첫번째 문자를 항상 대문자로 시작해야 합니다. 만약 두 단어 이상으로 만들어져 있으면 단어 사이를 대문자로 연결합니다. class 이름은 보통 명사로 만듭니다.
class 이름 예 : Button, Frame, Applet, Thread, MenuBar
interface 이름 예 : Runnable, LayoutManager, AppletContext

2) 메소드 이름과 변수 이름 정하기
메 소드 이름과 변수 이름은 문장처럼 여러 단어가 올 수 있는데, 항상 첫 번째 문자는 소문자로 시작하고 단어와 단어의 연결은 뒷 단어를 대문자로 시작합니다. 메소드 이름은 보통 동사로 시작합니다. 변수 이름은 보통 명사로 되어있습니다.
메소드 이름 예 : getImage(), getDocumenttBase(), setBackground()
변수 이름 예 : height, width, pointSize

3) 상수 이름 정하기
Primitive Data Type 변수에 값을 할당하기 위해 사용하는 상수는 모두 대문자로 표시하고 단어 사이는 _(underscore)로 연결합니다. Reference Data Type일 경우는 대소문자를 다 사용합니다.
Primitive Data Type 상수 예 : BOLD, ITALIC, CROSSHAIR_CURSOR
Reference Data Type 상수 예 : black, darkGray, UndefinedProperty

6. Data Type(데이터형)과 Literal
1) Primitive Data Type (기본 데이터형)
자바에는 Primitive Data Type과 Reference Data Type(참조 데이터 형 = Object Reference Data Type)이라는 두 가지의 Data Type이 있습니다.

Primitive Data Type의 종류에는 boolean, char, byte, short, int, long, float, double 등 8개가 있습니다. Primitive Data Type 으로 선언된 변수는 실제 값을 갖게 됩니다.

이와는 달리 Reference Data Type으로 선언된 변수는 어떤 값이 저장되어 있는 메모리의 주소를 갖게 됩니다.즉, 블럭 구조로 여러 다른 Data Type의 값들을 모아놓은 곳의 base address를 갖게 되고, 이 정보를 바탕으로 여러 값을 얻어낼 수 있으므로 Reference(참조)라는 말을 붙인 것입니다. Reference Data Type에는Array(arrary), class, interface가 있습니다.

자바의 모든 Primitive Data Type들은 Java Virtual Machine(JVM)을 따르기 때문에platform에 따라 크기가 바뀌지 않습니다. 대표적인 경우가 int입니다. C 언어에서는 platform에 따라 int크기가 다양하게 바뀐다는 것을 알고 계시죠? 하지만 자바는 그렇지 않다는 것입니다. 아마도 이 점이 sizeof가 필요 없는 이유 중 하나일 것입니다.

boolean Data Type
자 바는 C에는 없는 boolean Data Type이 존재합니다. boolean Data Type으로 선언된 변수는 true와false 두 가지 값만을 가질 수 있습니다. true와 false는 반드시 소문자로 코딩해야한다는 점을 잊지 마십시오.

char Data Type
자바의 char Data Type은 ASCII를 지원하지 않고 2 byte Unicode를 지원하기 때문에 16 bit의 양의 정수로 표현 되어집니다.
즉, 실제 가질 수 있는 값의 범위는 0 부터 2^16 - 1 까지인 것입니다. (unsigned라는 뜻이지요.)

byte, short, int, long (Integral) Data Type
모든 Integral Data Type은 signed입니다. 즉, 2's complement 방식으로 표현되는 것이지요.unsigned integral type은 지원하지 않습니다. Integral Data Type들의 표현 값의 범위는 다음과 같습니다 :


float, double (Floating point) Data Type
Floating point Data Type은 IEEE754 Spec.에 따라 표현되어 있고 역시 platform에 상관없이 구현되어 있습니다. float Data Type은 32 bit 크기의 실수를 표시할 수 있으며, double Data Type은64 bit 크기의 실수를 표현할 수 있습니다

2) 사용되는 literal
boolean literal
literal은 소문자인 true, false 두 가지 종류 밖에 없습니다.

boolean isFull;
boolean beOk = false;

isFull = true;

char literal
char data type에 대한 literal은 C에서와 마찬가지로 single quotes에 둘러싸인 문자로 표현됩니다.그리고 코딩시 입력하기 어려운 문자 값을 넣기 위한 escape sequence를 자바도 '\n' 형식으로 지원합니다.

char ch1 = '\n';
char ch2 = '\r';
char ch3 = '\t';
char ch4 = '\u88ab'; // Unicode 표현

char ch5;

ch5 = 'a';

여기서 특이하다면 '\u' 라고 할 수 있는데, \u 뒤에는 2 byte Unicode 즉, 4개의 hexa value가 올 수 있습니다. '\u88ab'의 의미는 실제 Unicode 88ab번의 문자라는 것 입니다.

Integral literal
Integral Data Type으로 선언된 변수가 가질 수 있는 Integral literal은 C와 마찬가지로 decimal, octal, hexa 의 3가지 표현으로 나타나집니다.


그리고 위의 숫자들과 같이 특별한 suffix가 없으면 모두 int type으로 간주합니다. 만약 int 크기가 아닌 long 크기를 표현하고 싶다면 숫자 뒤에 l 또는 L을 붙여주면 됩니다.

Floating point literal
만약 어떤 숫자 literal이 decimal point(.) 나 expornent part(e, E)를 사용하여 표현되어 지거나 또는 suffix로 f, F, d, D 중 하나를 포함하고 있으면 Floating point literal로 처리되게 됩니다. suffix를 사용함에 있어 f 나 F 없이 사용된 literal은 무조건 double(64 bit) 크기로 인식이 되어버립니다.


String literal
자바의 String Data Type은 class로 만들어져 있는 Reference Data Type 이지만 연속적인 문자열을 표시하기 위한 literal이 제공되고 있습니다. 물론 unicode로 만들어지고 double quotes를 사용하여 둘러싸게 되어 있습니다.

String msg = "이 문자열은 테스트용 입니다.";

7. 변수 선언 : 기본 개념
1) 자바의 변수 선언
메 모리상의 데이터를 프로그램에서 접근하기 위해서는 실제 데이터를 나타내는 변수가 있어야 합니다. 변수를 이용하여 프로그래머는 메모리상에 데이터를 저장하고 반대로 저장된 데이터를 불러와 사용하기도 합니다. 즉, 변수는 프로그래머가 메모리상의 데이터에 접근하기 위한 방법이며 데이터와 1 : 1 대응됩니다.

변수를 사용하려면 먼저 변수 선언이라는 절차가 필요합니다. 변수 선언이란 자바가상머신(JVM)에게 데이터를 저장하기 위한 메모리를 할당하라는 의미입니다. 그러기 위해선 데이터 타입이 필요합니다. 데이터 타입에 따라 그 데이터가 필요로 하는 크기만큼의 메모리를 할당합니다. 두 번째로는 변수를 다른 변수와 구별할 수 있는 이름이 있어야 합니다. 이것을 변수명이라 합니다.

자바에서는 변수 선언시 다음과 같은 구조를 가집니다.
데이터 형 변수이름;

예를 들어, 논리형 데이터를 갖는 itsTrue라는 변수를 선언한다면 아래와 같은 문장으로 표현합니다.

boolean itsTrue;

이 때, 데이터 형은 자바에서 정해진 타입 중의 하나로 선언하고 변수이름은 변수이름의 coding convention에 따라 정의할 수 있습니다.

2) Primitive Data Type 변수 선업법
Primitive Data Type들은 C에서와 마찬가지로 선언과 동시에 자신의 크기에 맞는 메모리 할당이 동시에 일어납니다.

3) Referance Data Type 변수 선언법
boolean, char, byte, short, int, long, float, double과 같은 Primitive Data Type은 이에 대한 정보가 컴파일러에 내장되어 있어 선언과 함께 정의된 만큼의 메모리를 생성하게 됩니다.

하지만 Array, class, interface 등과 같이 그때 그때마다의 정의에 따라 메모리 할당에 필요한 정보가 달라지는 Reference Data Type으로 선언될 변수는 선언과 생성이 분리되어 있습니다. C와 비교해 보자면pointer 처럼 선언 후 따로 memory 할당을 해줘야 한다는 것이지요. 물론 할당에 관련된 기능이 따로 있습니다.C++처럼 new라는 operator를 사용해서 dynamic하게 heap으로부터 할당해서 쓰게 되어 있습니다.

import java.util.*;

class TestVar {
public static void main(String[] args) {
String msg; // 라인 1.

msg = new String("sample 1"); // 라인 2.
}
}
String은 class type입니다. 그러므로 라인 1번으로는 선언만 이루어진 것이지요. 따라서 라인 2번과 같이 String object를 만드는 (메모리 할당) 작업이 병행되어야 합니다.

import java.util.*;

class TestVar {
public static void main(String arg[]){
String msg = new String("sample 2");
}
}
위와 같이 선언과 생성이 한줄로 표현될 수도 있습니다. 앞서 Reference Data Type으로 선언된 변수는 어떤 값이 저장되어 있는 메모리의 주소를 갖는다고 했던 것 기억 나시죠? 이 개념은 마치 C에서의 pointer 개념과 거의 유사한 것으로 분명한 차이점은 C에서의 pointer 변수는 arithmetic 연산이 가능했던 반면 자바의 Reference Data Type 변수는 이러한 연산이 불가능하다는 것입니다.

import java.util.*;

class TestVar {
public static void main(String arg[]){
String msg = "sample 3";
}
}
특별히 String은 위의 예문과 같이 new를 사용하지 않고 literal만으로도 내부에서 필요한 object가 만들어지게 되어 있습니다.

import java.util.*;

class TestVar {
public static void main(String arg[]){
Date today = new Date();

System.out.println("Today is:" + today);
}
}
위와 같이 class type인 Date로 변수를 선언하고 생성하면 시스템에 의해 오늘의 날짜 값이 변수에 저장되게 됩니다.

8. Array에 관하여
1) Array 선언법
선 언은 컴파일러에게 "이 변수는 Array type이다"라는 것을 알려주는 것이겠죠? 선언시 Array 표시 기호로는 C처럼[]를 사용합니다. 그리고 아시다시피 Array는 특정 type의 element들을 연속적으로 갖는 것이기 때문에 반드시 그element의
type이 무엇인지 알려 주어야만 합니다.

int intArray[];
위의 선언문은 int type의 element를 갖는 Array에 대한 것 입니다. 코드에서 보는 것처럼 C와 비슷한 방식으로 선언이 이루어 집니다. 하지만 다른 점은 [] 안에 몇 개의 element가 와야할지 크기 지정을 하지 않는다는 것입니다. 왜냐하면 크기에 대한 정보는 선언할 때 필요한게 아니라 메모리를 생성할 때 필요하기 때문입니다. 즉, 선언에서는 단지"어떤 어떤 type의 Array이다." 라는 것만 알려주는 것입니다.

double [] dArray, otherArray;
위와 같이 [] 표시 기호를 꼭 변수 뒤가 아닌 앞쪽에 붙여도 상관 없습니다. 단, 이렇게 선언하면 dArray뿐만 아니라 뒤에 연속적으로 나오는 변수명도 Array로 취급됩니다. 따라서 위와 같은 경우 otherArray 변수도double type element를 갖는 Array로 선언된 것으로 취급되는 것입니다. 하지만 다음과 같은 선언은 변수msgArray는 Array이지만 str은 단지 String class type 변수일 뿐입니다.

String msgArray[], str;
반드시 주의하실 것은 선언할 때 [] 안에 절대 size 정보를 주지 말아야 한다는 것입니다. 잊지 마세요!!!

2) Array 생성법 (메모리 할당하기)
이 번에는 어떤 type element를 갖는 Array로 선언된 변수에 실질적인 메모리를 할당하는 방법에 대해 알아보겠습니다.이러한 생성 역시 new 연산자를 이용하게 됩니다. 생성된 모든 Array들은 length 라는 member 변수를 갖게 되는데, 이 member 변수 length에는 element가 몇 개 생성되었는지에 대한 정보가 저장됩니다. sizeof연산자가 필요없는 또 다른 이유라 할 수 있겠죠.

다음은 선언과 함께 new operator를 사용하여 arrary을 생성하는 예문입니다.

int intArray[] = new int[100];
이와 같이 element 갯수에 대한 정보는 new 연산자를 사용 할 때 지정하게 됩니다. 위의 경우 선언과 생성이 완료되면 intArray[0]부터 intArray[99]까지 총 100개의 element를 int type 변수로 사용할 수 있는 것이지요. 이 때 intArray.length에는 100의 값이 저장될 것입니다.

다음은 선언과 생성을 별도로 코딩한 것입니다.

double [] dArray, otherArray;

dArray = new double[100];
otherArray = new double[200];

int i = 5; // 라인 1.
String msgArray[] = new String [i]; // 라인 2.

msgArray[0] = new String("first msg"); // 라인 3.
msgArray[1] = new String("second msg");
msgArray[2] = new String("third msg");
msgArray[3] = new String("forth msg");
msgArray[4] = new String("fifth msg");
앞에서 언급한 것처럼 Array element 갯수는 new 연산자를 사용하는 생성 부분에서 정의되기 때문에, element 갯수에 대한 정보는 위의 예문과 같이 변수화될 수 있는 것입니다.

라인 1과 라인 2의 선언과 생성을 통해 msgArray[0]부터 msgArray[4]까지 5개의 element가 String class type으로 사용할 수 있게 되었습니다. 이 때 (7. 변수 선언 : 기본 개념에서 학습한 바와 같이) String class type은 Reference Data Type이므로 라인 3 이하의 문장들과 같이 String object를 생성하는 작업이 필요함은 이미 다 알고 계시겠죠?

3) Array 초기화

Array는 다음과 같이 한 줄로 선언과 생성, 초기화를 동시에 만들어 낼 수도
있습니다. (잘 익혀두세요!!!)

int intArray[] = {100, 200, 300};
float fArray[] = {1.1f, 2.2f, 3.3f, 4.4f};
String sArray[] = {"hello", "SCJP", "exam"};
이때 Array들은 초기화한 개수만큼 element들이 생성됩니다. 즉, intArray.length는 3의 값을 갖게 되는 것입니다.

또한 다음과 같이 반복문을 이용하여 생성된 Array에 초기값을 할당할 수도 있습니다.

int score[] = new int[3000];

for (int i = 0; i < score.length; i++)
score[i] = i ;
이 평범해 보이는 문장에서 살펴볼 사항은 반복 횟수에 대한 것입니다. 즉, 생성한 Array의 length라는member 변수를 이용함으로써, 만약 나중에 new 문에서 지정한 element의 갯수가 변하더라도 초기화에 사용된 조건문을 일일이 확인 하지 않아도 되니까 그만큼 안전한 프로그램이 될 수 있을 것입니다.

자바는 C처럼 array boundary를 넘어서는 코드를 만들 수 있게 놔두지 않습니다. 물론 컴파일에서는 별 탈이 없겠지만, 실행에서는 array boundary를 벗어나면 이를 잡아내 주게 되어 있습니다.

int score[] = new int[3000];

for (int i = 0; i < 3001; i++)
score[i] = i ;

위와 같은 코드가 컴파일되어 실행된다면 i가 2999일 때 까지는 제대로 잘 실행되어 처리되다가, i가 3000을 갖고score를 access 하는 순간 boundary를 벗어나 다른 메모리 영역을 침범하는 것이 아니라 바로

ArrayIndexOutOfBoundsException

이라는 예외(exception)를 발생시켜 이를 처리 할 수 있게 해주는 것입니다. (예외(exception)에 대한 자세한 내용은 7장에서 다룹니다.)

4) 다차원 Array
자바에서도 2차원 이상인 arrary을 만들 수 있습니다.

int twoDimArray[][] = new int[4][10] ;

이러한 선언과 생성은 twoDimArray[0][0]부터 twoDimArray[3][9]까지 4 by 10의 정사각형을 연상시키는 40개의 element를 만들 것입니다. 그런데 만약 2차원 arrary을 사용함에 있어 각각의 크기를 다르게 하고 싶다면 어떻게 해야 할까요?

int twoDimArray[][]; // 라인 1.

twoDimArray = new int[4][]; // 라인 2.

twoDimArray[0] = new int[5]; // 라인 3.
twoDimArray[1] = new int[10]; // 라인 4.
twoDimArray[2] = new int[3]; // 라인 5.
twoDimArray[3] = new int[7]; // 라인 6.

for (int i = 0; i < twoDimArray.length; i++)
for (int j = 0; j < twoDimArray[i].length; j++)
twoDimArray[i][j] = 0;
라인 2에서는 element 갯수가 4개인 2차원 Array를 생성한 것이고 라인 3,4,5,6에서는 이렇게 생성된 각 element가 필요로 하는 만큼의 Array를 생성하는 것입니다.

for 문으로 이루어지는 초기화 작업에서 각각의 반복 횟수로 사용된 값들을 의미있게 살펴보세요.twoDimArray.length는 4가 될 것이고 twoDimArray[0].length는 5 twoDimArray[1].length는 10 twoDimArray[2].length는 3 twoDimArray[3].length는 7이 될 것입니다. 이렇게 하면 2차원 Array를 꼭 정사각형이 아닌 dynamic한 형태로 사용할 수 있겠죠?

9. class 기본 개념
1) main 메소드 정의하는 법
자바에서의 메소드는 독립적으로 호출될 수 없으며 반드시 객체의 일부로서만 호출이 가능합니다. 그러나 예외적인 메소드가 있는데 바로 main 메소드입니다. 이 메소드는 자바 프로그램을 실행할 때 자바가상머신(JVM)에서 호출되는 최초의 메소드입니다.

java 실행할 class이름
의 명령으로 class를 실행할 때 자바가상머신(JVM)에서 class 이름으로 지정된 class에 포함된main 메소드를 호출합니다.(앞서 살펴본 바와 같이 애플릿의 경우는 조금 다릅니다.) 따라서, 여러 개의 class로 이루어진 프로그램의 경우 반드시 시작 class, 즉 java 명령으로 실행할 때에 필요한 이름의 class에는 main 메소드가 있어야 합니다.

C나 C++과 달리 자바에서는 모든 프로그램이 class scope내에서만 정의됩니다. 그러므로 자바에서는 main 메소드도 한 class의 메소드로 정의하게 되어 있습니다. main 메소드의 선언은 다음과 같은 형식으로 정해져 있습니다.

public static void main(String arg[])

만약 main의 선언 중 무엇인가가 틀려서 맞지 않으면 컴파일 때는 문제가 없으나 실행할 때 main의 선언이 잘못되었다는 error가 나오게 됩니다. 예문을 한번 살펴볼까요?

public class HelloWorld {
public static void main(String arg[]) {
System.out.println(" Hello World!");
}
}

앞서 언급한 것처럼 HelloWorld라는 class의 메소드로 main 메소드가 정의되어 있습니다. 이때,

main 메소드를 public으로 선언한 것은 interpreter와 같이 실행 시킬 때 외부에서도 main을 참조할 수 있게 하기 위함이고, static은 HelloWorld라는 instance를 생성하지 않고도 main을 참조하게 해주며 (이것의 자세한 내용은 5장 3절 4. static modifier에서 다룹니다.) void는 return value가 없음을 뜻하는 것입니다.
main 안의 출력 함수인 println()은 System class 안에 있는 out 멤버 변수의 형(type)인 PrintStream object에 포함된 메소드로서 ()안에 포함된 내용을 출력합니다.

main 메소드의 인수인 String arg[]는 command line에 정의된 문자열을 받아들이는 arrary로 arg라는 이름 대신 다른 이름을 써도 괜찮습니다.

컴파일 완료 후

c:\> java HelloWorld seoul pusan

와 같이 실행시키면 arg[0]에 seoul, arg[1]에 pusan 이라는 문자열이 넘어오는 것입니다.

main 메소드 선언 부분을 보면 String 타입의 arrary이 인자값으로 넘어오는 것을 알 수 있습니다. main메소드의 인자값 args[0]는 자바 interpreter 실행시에 인자로 넘어온 값을 의미합니다. 자바 인자값은 자바interpreter와 시작 class를
제외한 나머지를 모두 인자로 넘겨줍니다.

class ArgTest{
public static void main(String arg[]){ // 라인 1
for(int i=0; i < arg.length; i++){ // 라인 2
System.out.println(arg[i]); // 라인 3
}
}
}
위의 코드는 라인 1의 인자값 arg arrary을 이용하여 라인 3에서 인자의 개수만큼 출력시켜보는 내용입니다.라인 2의 length 변수는 arrary의 크기를 나타냅니다. (7절에서 배웠습니다.) 위의 코드를 작성한 후 컴파일합니다.컴파일 완료 후에 아래와 같이 세가지 방법으로 실행합니다.

java ArgTest 하하하 호호호 // 라인 4
java ArgTest 100 + 200 // 라인 5
java ArgTest // 라인 6

라인 4를 실행하면 라인 1의 arg[] arrary에 "하하하", "호호호" 두개의 String 데이터가 arrary을 이루게 되므로 arg.length는 2가 됩니다. arg[0]에는 "하하하", arg[1]에는 "호호호" String을 할당받습니다.

라인 5의 경우 arg.length는 3이고 arg[0]는 "100", arg[1]는 "+", arg[2]는 "200"의String을 할당받습니다. 이 때, 라인 5의 명령 수행시 입력한 100과 200은 숫자가 아닌 String으로 읽혀오므로 자바 프로그램 내에서 다시 원하는 정수나 실수 타입으로 변환하여 사용해야 함을 주의하십시오.

마지막으로 라인 6의 경우에는 프로그램 실행에 필요한 인자값이 입력되지 않았으므로 arg.length는 0 이고 화면에 출력되는 내용은 없습니다.

2) 변수의 초기화
자바는 크게 두 가지 종류의 변수를 제공하고 있습니다. 하나는 멤버 변수이고 또 하나는 지역 변수입니다. 이 둘은 서로 사용되는 scope도 다를 뿐더러 초기화에 관련된 사항도 많이 다릅니다.

public class TestVar {
int i;
public static void main(String arg[]) {
....
}

int calcSum() {
int j;
....
}
}
예를 들어 위와 같이 TestVar라는 class를 정의할 때 main 메소드나 calcSum 메소드와 동일한 scope에서 정의된 변수 i는 멤버 변수이며, calcSum 메소드에서 정의된 변수 j는 지역 변수입니다.

멤버 변수는 class 안의 어디서든 참조 가능하고 한 class 안에서는 global하게 값이 유지됩니다. (단,static으로 선언된 메소드에서는 non static인 멤버 변수를 access 할 수 없습니다. 자세한 내용은 5장 4절3주제 static modifier에서 설명합니다.) 그리고 멤버 변수가 선언되어 생성된 후 별도로 초기값을 지정하지 않으면 선언한 Data Type에 따라 다음과 같은 default 값을 초기값으로 갖게 됩니다.
Array가 생성될 때 갖는 초기값들과 같은 초기값들이죠?

이와는 달리 지역 변수는 한 메소드 scope 안에 선언된 변수들을 말하는 것으로, 메소드가 호출되었을 때 stack에 생성되었다가 수행이 완료되면 없어지는 성격을 가지고 있습니다. 때문에 지역 변수를 automatic 변수라고도 부릅니다. 이런 지역 변수는 선언되었을 때 멤버 변수와는 달리 시스템에 의해 자동적으로 초기화 값이 주어지지 않습니다. 그래서 자바는 컴파일할 때 초기화를 하지 않고 사용하는 지역 변수는 전부 error로 처리합니다.

public class TestVar {
int sum;

public static void main(String arg[]) {
TestVar t = new TestVar();

System.out.println("SUM=" + t.calcSum(10));
}

int calcSum( int lim ) {
int i = 0; // 라인 1.
int result; // 라인 2.

if (true) {
while (i < lim) {
result = result + i;
i++;
}
}

return result;
}
}
위와 같은 예문을 컴파일하면 지역 error 메세지가 발생할까요? 안 할까요?

이러한 상황의 프로그램에 대해서도 컴파일러는 지역 변수를 초기화하지 않았다는 error 메세지를 발생할 것입니다. 당연하겠죠.하지만, 지역 변수를 선언하고 초기화 하지 않았더라도, 사용을 하지 않으면 컴파일 에러는 발생되지 않습니다.

변수를 선언한다는 것은 사용하기 위한 메모리가 잡히게 되는 것이고, 초기화를 한다는 것은 이를 사용하기 위해 미리 메모리를 정리한다는 의미입니다.

멤버변수는 초기화를 자동적으로 해주니까 문제가 없는데, 지역 변수는 초기화가 자동적으로 되지 않으므로 별도로 사용하기 전에 초기화를 하지 않으면, 그 메모리 영역에 어떤 값이 들어가 있으지 모르겠죠. 이 메모리에 들어있는 정리되지 않은 값, 즉 쓰레기 값을 가지고 동작을 시키려면 어떻게 상황이 발생될 지 모르죠. 이를 막기위해서 초기화되지 않은 지역 변수 사용을 컴파일러가 에러를 발생시키면서 수정하도록 만들어 에러를 미리 방지하는 것입니다.

하지만, 선언만 해놓고 사용하지 않는다면 컴파일시 문제는 없지만 while 구문안의 result = result + i; 라인을 없애보고 컴파일하면 어떻게 되는지, 한 번 테스트 해보세요.

3) 자바의 멤버변수와 지역변수
자바에서는 어디에서 변수를 선언할까요?
자바에서의 변수 선언은 { }으로 묶여있는 곳이라면 어디에서나 가능합니다. C나 C++의 경우 변수 선언 외의 실행문이 나오기 전에 모든 변수가 선언되어야 합니다. 그러나 자바에서의 변수 선언은 어디에서나 가능합니다.

for(int l = 200; l < 500 ; l++){
int j = l * 300;
while ( j < 800){
int k = 500;
}
}
위의 코드를 살펴보면 for문 내에서 int 타입의 변수 l, j가 선언되어 각각 초기화된 후 사용됩니다. 이렇게 { } 내에서 선언된 변수를 지역변수(local variable)이라고 합니다. { } 내에서 선언된 지역 변수는 { } 지역을 벗어나면 자동으로 삭제됩니다.

while(true) {
int var1 = 200;
while (true) {
int var2 = 300;
System.out.println(var1); // 라인 1.
System.out.println(var2); // 라인 2.
break;
}
System.out.println(var1); // 라인 3.
System.out.println(var2); // 라인 4.
}
위의 코드를 살펴보면 라인 1 문장은 라인 1을 포함한 while을 포함한 외부 while 블록에서 선언된 변수var1을 사용하므로 올바른 코드입니다. 라인 2 문장은 라인 2 문장을 포함한 while 블록에서 선언된 변수 var2를 사용하므로 역시 올바른 코드입니다. 라인 3 문장은 라인 3 문장을 포함한 외부 while 블록(첫문장) 내에서 선언된 변수var1을 사용하므로 역시 올바른 코드입니다. 마지막으로 라인 4 문장은 내부의 while 블록에서 선언된 var2가 내부while 블록을 종료하면 더 이상 사용할 수 없는 변수이므로 error가 발생합니다.

class LocalTest{

String s = "member 변수"; // 라인 1

public void m1(){
System.out.println(s); // 라인 2
}

public static void main(String args[]){
String s = "main 메소드의 local 변수"; // 라인 3
System.out.println(s); // 라인 4
System.out.println(new LocalTest().s); // 라인 5
}
}
위의 코드를 살펴보면 라인 1에서 선언되어 초기화된 s 변수가 m1 메소드 내의 라인 2 문장과 main 메소드 내의 라인 5 문장에 의해 사용됩니다. 라인 1의 s 변수는 class가 정의되면서 class { } 내에서 사용할 수 있도록 정의한 것입니다.
이러한 타입의 변수는 class 내에서 멤버 변수(Member Variable)라고 합니다. 그리고 라인 3 문장에 의해main 메소드 내에서도 같은 이름의 변수 s가 선언되어 초기화되었습니다. 라인 3의 s 변수는 main() 메소드 블록 내에서만 사용할 수 있는 변수입니다.

예문에서 살펴보았듯이, 변수가 선언되는 지역에 따라 멤버 변수인지, 지역 변수인지 나눌 수 있습니다. 멤버 변수는 선언된 class 내의 어디에서나 사용될 수 있고 지역 변수는 그 변수가 선언된 블록({ }) 내에서만 사용합니다. 그리고 멤버 변수는 선언과 동시에 자바 컴파일러에 의해 묵시적으롤 초기화값을 할당받습니다. 그러나 지역 변수는 묵시적인 초기화가 이루어지지 않으므로 반드시 프로그래머가 명시적으로 초기화값을 할당하여야 합니다.

각 데이터 타입에 따른 묵시적인 초기화값은 다음과 같습니다.

class LocalTest{

String s ; // 라인 1

public void m1(){
System.out.println(s); // 라인 2
}

public static void main(String args[]){
String s ; // 라인 3
System.out.println(s); //라인 4
System.out.println(new LocalTest().s); //라인 5
}
}
라인 1의 멤버 변수 s 는 라인 2와 라인 5가 실행되면 묵시적으로 null로 초기화되므로 null을 출력합니다. 라인 3의main 메소드의 지역 변수 s는 선언만 하고 초기되지 않았습니다. 지역 변수는 묵시적으로 자동 초기화되지 않으므로 라인 4에서 출력되지 않고 에러가 발생합니다.

10. 매개변수 전달방식
1) 매개변수란?
메소드가 호출 될 때 값을 주어야만 호출 되어지는 것을 쉽게 볼 수 있습니다. 만일, 아래와 같이 선언된 add 메소드가 있다고 가정해 보겠습니다.

int add(int x, int y)
이 메소드를 호출하려면 x, y값을 두개를 넣어 주면 add이라는 메소드는 내부적인 작업을 끝마친 뒤 x와 y를 더해서 return을 하게 됩니다. 이 때 우리는 x, y를 매개 변수라고 합니다. x, y는 add 메소드의 호출과 동시에x, y를 메소드의 내부에서 생성하게 되며 외부에서 넘어오는 값을 중간에서 할당 받게 됩니다. add(1, 2)라고 호출한다면x에는 1이 직접 할당의 방법으로 할당되고 y에는 2가 할당 되어집니다.

int a;
a=8;
......
int add(int x, int y){
return x+y;
}
......
add(1,2);
그럼 언제 매개변수를 사용할까요?

이에 대한 답은 필요하다고 생각 될 때 메소드를 만드는 프로그래머가 만들면 됩니다.

그럼 매개변수는 몇 개까지 사용할 수 있을까요?

이에 대한 답은 역시 필요하다고 생각 될 때 필요한 만큼의 개수까지 사용할 수 있습니다. 즉, 무제한입니다.

메소드의 이름은 매개변수와 결합하여 변수의 역할을 수행하므로 매개변수의 개수와 데이터 형을 맞추지 않으면 메소드는 호출할 수 없습니다. 이 때, 매개변수의 데이터 형은 반드시 지켜야 합니다. 즉, 매개변수는 메소드 내에 만들어지지만 외부로부터 값을 받을 수 있는 유일한 통로입니다.

2) Primitive Data Type 매개변수
다음의 프로그램을 살펴보며 Primitive Data Type 매개변수를 사용할 때 발생되는 결과를 알아보겠습니다.

public class TestParam {
public static void main(String arg[]) {
int ival = 0;
TestParam mainobj = new TestParam(); // 라인 1.

mainobj.effectParam(ival); // 라인 2.
System.out.println("main ival: "+ ival);
}

void effectParam(int ival) {
ival = 300;
System.out.println("sub ival: "+ ival );
}
}
C를 조금이라도 해 본 분들은 이 프로그램의 실행 결과를 예측하실 것입니다. (call by value)

sub ival: 300

main ival: 0
main 메소드에서 0의 값을 가진 ival 변수를 매개변수로 하여 effectParam 메소드를 호출하면 (이미scope가 다르기 때문에) effectParam 메소드에서 사용하기 위한 복사본이 만들어집니다. 즉, effectParam메소드에서 사용하는 ival은 main 메소드에서 전달한 ival의 값을 그대로 갖는 별도의 메모리를 할당하여 사용하는 것으로서effectParam 메소드의
실행이 끝나 return 되면 메모리에서 자동적으로 사라집니다. 그러니 main 메소드의 ival은 당연히 아무 영향도 받지 않게 되는 것이지요.

3) Reference Data Type 매개변수
이번에는 Reference Data Type 매개변수를 사용한 프로그램을 살펴볼까요 ?

public class TestParam {
public static void main(String arg[]) {
Param p = new Param(); // 라인 1.
TestParam mainobj = new TestParam();

p.ival = 100;
mainobj.effectParam(p); // 라인 2.
System.out.println("main ival: "+ p.ival);
}

void effectParam(Param p) {
p.ival = 300;
System.out.println("sub ival: "+ p.ival);
}
}

class Param { // 라인 3.
int ival;
}
자, 여기서는 Param이란 새로운 class를 정의하고(라인 3) Param class의 object를 생성한 후(라인1) 이를 매개변수로 effectParam 메소드를 호출하였습니다.(라인 2) 이와 같은 프로그램의 결과는 어떻게 나올까요?

sub ival: 300
main ival: 300
main 메소드에서 Param class type으로 선언된 p는 new 문에 의해 생성된 Param object의 주소 값을 갖게됩니다.
따라서 이러한 p가 effectParam 메소드에 매개변수로 전달 되는 것은 Param object의 주소 값을 전달하는 것이므로 (effectParam 메소드에서 p가 local 변수이긴 하지만) 결국 main 메소드의 p와 effectParam의p는 동일한 Param object를 point하게 됩니다.

그러므로 effectParam 메소드에서 Param object의 ival을 300으로 바꾼 것은 (비록effectParam 메소드의 실행이 끝나 return 되면 p는 메모리에서 자동적으로 사라진다하더라도) main 메소드의 p가 포인트하고 있는 Param object의 값을
변경한 것이 되는 것입니다.

public class TestParam {
public static void main(String arg[]) {
Param p = new Param();
TestParam mainobj = new TestParam();

p.ival = 100;
mainobj.effectParam(p);
System.out.println("main ival: "+ p.ival);
}

void effectParam(Param p) {
p = new Param(); // 라인 1.

p.ival = 300;
System.out.println("sub ival: "+ p.ival);
}
}

class Param {
int ival;
}
앞에서 살펴 본 프로그램에 라인 1을 추가한다면 어떤 결과가 나올까요? (실제로 만들어 한번 테스트해 보세요.)

sub ival: 300 main ival: 100
이와 같은 결과가 나오는 이유는, p를 매개변수로 전달 받을 때 까지는 main 메소드의 p가 포인트하는 Param object의 주소를 갖고 있었지만, 라인 1을 통해 새로운 Param object를 만들어 이것의 값을 바꾼 것이기 때문입니다. (참고적으로 effectParam 메소드에서 새로 생성한 Param object는 return 되면서 바로Garbage collection의 후보가 된답니다.)

 



[한글판] 안드로이드 개발자 가이드 / 안드로이드 입문서


"안드로이드 입문서 3rd Edition을 발행합니다.

 

칸드로이드가 영어로만 씌어져 있던 Android Dev. Guide를 

한글로 번역해 책으로 출간하고, 웹으로 오픈하고,

PDF 파일로 공개하는 것은 확산과 공유의 정신을 고양하기 위해서입니다.


베이직&클래식한 안드로이드 입문서를 기반으로 

개발자들이 보다 발전적이고 창조적인 대화를 나눌 수 있기를 희망합니다.


" 가치 공유의 확산 ! "


이것이 칸드로이드가 안드로이드 입문서를 공개하는 단 하나의 이유입니다.

많은 분들에게 도움이 되길 바라며..


더불어 함께 이 일을 해 나가고 있는 모든 칸드로이드 운영진들께 항상 감사합니다.


2010년 2월 23일


kandroid 운영자."


Microsoft Visual Studio 2010 단축키 포스터

 

소설같은자북(jabook.com)-소설같은시리즈(Java, C#, C, JSP)





대충 이렇게(??) 생겼습니다.


http://www.jabook.com/




'프로그래밍' 카테고리의 다른 글

[자바] 자바강의: 연산자 / Operators  (0) 2012.07.04
아스키코드 표 (ASCII Code Chart)  (0) 2012.06.21
[자바] JAVA 강의 노트  (0) 2012.06.13
Links  (0) 2011.10.16
알고리즘 사이트 Programming-challenges  (0) 2011.10.16

JAVA 강의 노트


어디서 난지는 기억이 잘....


JAVA 강의 노트.pdf


이 노트로 작년 학기 시작하기전에 공부하니 좀 도움이 되는것 같네요..


제가 만든건 아니지만 유용하게 사용하세요!!


저작권에 문제가 되면 지체마시고 연락주세요!!!



첫번째 장 입니다.




위의 이미지는 Daum 책으로 부터 발취하였습니다.

알고리즘 공부를 위해 트레이닝 북을 하나 구매하였습니다. 서론의 내용을 읽어보니 Programming Challenges라는 공개된 알고리즘 문제은행 웹사이트의 문제를 기반으로 알고리즘이 설명되어 있습니다.

제가 이글을 적은 이유는 여러분들은 굳이 책을 사지 않고도 알고리즘 문제 은행을 이용할 수 있기 때문입니다.
물론 책을 사서 본다며년 풀이과정과 자료구조, 알고리즘등의 설명이 나와 있어 도움이 됩니다. :D


http://www.programming-challenges.com 에 접속하면, 다음과 메인 페이지를 만나 볼 수 있습니다.



다음과 같은 절차면 Programming-challenges 웹사이트를 이용하는데 무리가 없을 듯 합니다.
  • 회원 가입을 한다.
  • 로그인한다.
  • 알고리즘 문제를 확인하고 코드를 작성한다.
  • 웹사이트에 제출한다.


본인의 계정 아이디로 로그인한 후 , 왼쪽의 All problem을 누르면 우측에 모든 문제들을 확인 할 수 있으며, 우측의 빨간테두리 해놓은 SUBMIT버튼으로 코드를 제출합니다.




코드를 작성할 때는 C, C++, Java, Pascal로 제출할 수 있습니다. Pascal까지 지원한다라는게 좀 의외네요. 저는 자주 사용하는 C언어로 코드를 작성하고 제출합니다. 참고로 코드는 main 함수만 제출하는게 아니고 본인이 작성한 모든 코드 부분을 제출해야 합니다.
아마도 웹 서버 내부적으로 해당 내용을 그대로 컴파일하여 결과값으로 확인을 하겠죠.


Programming-challenges 웹사이트에서 모든 정보는 영어로!! 제공됩니다. 또한 모든 문제들은 stdin으로 입력값이 제공되고 본인이 작성한 알고리즘에 의해 stdout으로 결과 값이 출력되게 코드를 작성해야 합니다.


Programming-challenges에서는 코드를 제출하면 10~30초 안에 결과가 Status로써 반영됩니다.

Never summited 제출되지 않음.
Solved 문제 해결됨.
Presentation Error 잘못된 출력값(출력 형태가 맞지 않음)
Wrong answer 잘못된 출력값(알고리즘이 잘못되어 출력값이 맞지 않음)

문제를 잘 읽어봐야 Presenatition Error를 피할 수 있습니다. ㅠㅠ


마지막으로 Programming-challenges는 영어의 압박이 있지만 약 300여개의 문제가 있습니다.하루에 1개씩만 풀어도 대충 10달정도 걸리겠네요. 무료로 이용 가능한 알고리즘 문제풀이를 함으로써 문제 해결능력과 코딩 스킬을 높히시는데 도움이 됬으면 합니다.

[출처: http://www.morenice.kr/55]

'프로그래밍' 카테고리의 다른 글

아스키코드 표 (ASCII Code Chart)  (0) 2012.06.21
[자바] 소설같은 자바교재: 자북  (0) 2012.06.13
[자바] JAVA 강의 노트  (0) 2012.06.13
Links  (0) 2011.10.16
프로그래밍 초보자가 알아야 하는 9 + 1 가지  (2) 2011.10.16
지금와서 보면 초보 시절에 별것 아닌 것으로 많은 시간과 많은 밤들을 보내면서 나름 프로그래밍의 세계에서 매력아닌 매력에 빠지곤 했었습니다. 지금의 초보자들을 보면서 지난 프로젝트들을 되돌아보고 저 역시 저질렀거나 하지 말았으면 하는 것들에 대해서 한번 생각을 해보았습니다.


so I went for a walk to a place that I know.
so I went for a walk to a place that I know. by Sanctu 저작자 표시비영리동일조건 변경허락

이는 비단 프로그래밍에 갓 입문한 사람 뿐만 아니라, 다른 프로그래밍 언어를 처음 접할 때에도 적용되는 내용 같습니다.

1. 프로그래밍의 최대의 적은 Copy & Paste이다.

IT에서 일어나는 작업들은 모두 사람의 힘을 배가시키기 위함이고, 이를 위해서는 최대한 자동화를 시켜주는 것이 그 목적일 것입니다. 따라서, 프로그래밍이라는 작업 역시 일일히 모든 것들을 만들기보다는 최대한 재사용할 수 있는 것들을 활용하는게 작업 능률에 있어서 최적일 것입니다. 그 중에서 프로그래밍 작업 중에 제일 흔하게 일어나는 일이 Copy & Paste입니다. 하지만, 익숙한 프로그래밍 언어라도 Copy & Paste는 주의를 필요로 합니다. 더군다니 초보 시절의 Copy & Paste는 독이 될 수도 있으며, 결국 잘 이해되지 않은 코드의 Copy는 어떠한 문제를 일으킬지 잘 모릅니다.

Palacio de las Artes Reina Sofía C.A.C / Palace of Arts Reina Sofia  C.A.C./ Palais des Arts Reina Sofia C.A.C.
Palacio de las Artes Reina Sofía C.A.C / Palace of Arts Reina Sofia C.A.C./ Palais des Arts Reina Sofia C.A.C. by Iabcstm 저작자 표시비영리변경 금지


초보 시절은 동일한 코드라고 하더라도 직접 키보드를 통해서 입력하거나 도구를 정상적인 경로를 통해 사용해봄으로써 머리와 몸으로 코드의 원리를 체득해야 합니다. 심지어 수천라인의 XML 코드라고 하더라도 일일히 쳐보면서 그 의미를 하나하나 쫓아서 읽을 수 있어야 합니다. 무분별한 Copy & Paste는 발생하는 에러를 엉뚱한 곳에서 디버깅하게 만듭니다. 요즘에는 책을 사면 소스 코드를 다운받게 되어 있습니다. 해당 내용을 잘 알고 어느 정도 이해를 하고 있는 사람이라면 상관없겠지만, 초보자들에게는 이 역시 소스 코드를 다운받아서 실행하는 것보다는 직접 책에 있는 내용을 쳐보고 이해하는 것이 많은 도움이 됩니다. 혹 책의 내용이 이전 라이브러리들을 참고하고 있어서 지금의 환경에서 이를 적용하려면 더 많은 수고들을 거치는 경우도 발생됩니다. 이러한 과정을 거치게 되면 또 다른 지식들이 쌓이게 되니, 헛짓이나 삽질이라고 생각하시면 안됩니다.

초보 시절 저 역시 수많은 코드들을 직접 손으로 치면서 많은 것들을 이해할 수 있었고, 더 많은 연결된 부분들을 찾아볼 수 있었던 것 같습니다. 반복적인 작업이지만, 그 자체로 더 없는 많은 내용들을 얻게 될 것입니다.

2. 가이드 대로 따라하면 안된다.

프로젝트에서는 수많은 가이드들이 만들어지며, Step By Step 형식으로 나와있는 문서나 자료들도 많이 있습니다. 초보 시절에는 가이드를 보는 것 역시 중요하겠지만, 그 내용을 곧이 곧대로 믿어서도 안됩니다. 특히나 프로젝트 중후반부로 들어갈수록 초반에 만든 가이드는 잘못되거나 수정된 내용이 많아질 가능성이 많습니다. 가이드는 대략적인 내용들을 보면서 어떠한 흐름으로 프로그래밍을 하게 되는지에 대한 지식을 얻으면 됩니다. 또한, 프로그래밍은 가이드에 나타난 내용 이외에도 더 많은 지식과 기술을 필요로 합니다. 가이드는 말 그대로 안내하는 용으로만 사용해야지 가이드가 모든 것을 가르쳐준다고 생각해서는 절대 안됩니다.


Day 106 - I am a librarian
Day 106 - I am a librarian by cindiann 저작자 표시비영리변경 금지


가이드를 절대적으로 믿는 행위 중에 하나는 가이드에 표현되지 않은 것들에 대해서는 아무런 사고를 안하게 만든다는 것입니다. 예를 들어, 예상치 못한 에러나 경고 문구가 나타나도 이를 신경쓰거나 무엇이 문제인지를 찾으려는 노력을 하지 않게 만듭니다. 이는 가이드를 만들고 배포하는 측에서도 가이드만 보고 따라하라는 암묵적인 강압을 하는 태도도 일조한 결과입니다. 가이드를 맹신하지 마십시오.

3. 한가지 정답을 찾으려고 하지 마라.

우리가 학교에서 배운 것들은 모두 정답이라는 한가지 목적에만 초점을 맞추어 있습니다. 사회의 초년생들 역시도 정답이 아니면 안된다는 사고를 가진 사람들이 대부분인 것 같습니다. 정답은 늘 해당 상황에서만 정답이 될 뿐이며, 다른 상황에서는 오답이 될 가능성이 높습니다. 프로그래밍에서 어느 한가지로 해결했다고 해서 이것이 다른 프로젝트에서 똑같이 적용될 수는 없을 겁니다. 정답보다는 그 가능성에 대해서 염두해 두십시오. 가능성은 확률로도 표현이 가능하며, 가능성이 높다는 것은 다양한 전제 조건을 포함한다는 것입니다. 즉, Context라는 단어가 의미하는 바를 이해하고, 그 상황에서 다양한 전제 조건과 제약 조건들을 같이 고려하여 가능성이 제일 높은 해결책을 찾는 것이 프로그래밍을 배울 때 같이 익혀야 할 내용입니다.

현실에서는 프로그래밍으로 할 수 있는 것들이 의외로 많고, 그러한 내용들이 나타나는 프로그램은 단지 그 결과에 지나지 않습니다. 다른 사람의 정답을 참고할 수는 있겠지만, 그러한 정답이 지금의 프로젝트 내에서 반드시 정답이라는 보장을 하기 힘듭니다. 그 사람의 정답(결과)이 만들어지는 배경과 상황을 같이 이해해야 합니다.

4. 고민을 끌어안고 있지 말고, 터뜨려라.

프로그래밍의 초보 시절에는 단순한 문제라도 심각한 고민거리가 되기 쉽상입니다. 그러한 고민거리는 그 누구한테 물어보는 것조차 힘겨운 법입니다. 고민을 하는 것은 그리 나쁜 것은 아니지만, 주어진 시간과 다른 작업으로의 연결이라는 제약사항들이 있기 때문에 무한정 고민만 할 수는 없습니다. 고민을 하는 시간조차도 효율적으로 사용해야 하며, 정 고민이 해결되지 않는다면 터뜨리십시오. 누가 물어보기 전까지 고민을 안고 있다라는 것은 다른 사람으로 하여금 실력이 없다라는 충분한 오해를 받을 만한 일입니다. 본인의 실력이 드러날까봐 고민을 안고 불안한 마음에 있는 것보다는 고민을 터뜨려서 해결하는 방법을 채택하는 것이 오히려 전체적인 관점에서 더 좋은 결과가 나타날 수 있습니다.

고민을 터뜨리는 방식은 단순하게 이 부분을 모르겠다고 솔직하게 털어놓는 것도 있을 수 있지만, 좀 더 유연한 방식으로는 그동안 고민했던 내용들을 다시 정리해보고, 왜 문제가 있는지를 간략하게 설명할 필요가 있습니다. 이때 주의할 점은 본인의 입장에서만 고민을 정리하다보면 상대방이 고민에 대한 본질적인 문제보다 그 부수적인 내용이 더 이해하기 힘든 경우가 발생됩니다. 고민은 최대한 간략하고 이해할 수 있도록 정리하는 기술이 필요합니다.

5. 통용되는 정확한 용어를 사용하라.

초보 시절에는 모든 단어와 용어들이 낯설기만 합니다. 그러한 용어들은 선배들이 잘못 이해하여 사용되는 경우들도 있습니다. 용어를 들은대로만 사용하기보다는 그 뜻과 의미를 정확하게 알아보는 습관을 들이는게 좋습니다. 또한, 그러한 용어를 알아가는 과정이 전번적인 내용을 이해하는 과정이기도 하며 이는 프로그래밍에 대한 지식을 더 폭넓게 이해하게 만듭니다.

대표적인 예가 디자인 패턴의 패턴 이름인데, 이러한 패턴 이름들은 상당한 오랜 시간 동안 많은 사람들에게 사용되어 왔습니다. 단순하게 이름만을 듣고, 그에 대한 배경 지식이 없는 상태에서 프로그램된 상태만을 본다면 나중에 또 다시 잘못 사용하여 이를 듣는 사람에게 오해를 불러일으킬 수도 있을겁니다.

변수명, 클래스명, 메소드명 등 역시 정확한 (비즈니스) 용어를 사용해야 합니다. 귀찮다고 줄이거나 임의로 이해할 수 없는 용어를 만들면 다른 사람이 보기가 힘들어집니다. 예전 기술들이야 워낙에 HW 용량에 대한 문제가 커서 이름이나 용어에 대한 길이 한정 제약이 있었지만, 지금은 이러한 제약에서 훨씬 자유롭습니다. 의미있고 정확한 이름을 사용하기 바랍니다.

6. 프로그래밍의 내용은 한편의 시나리오(소설)를 보는 듯하게 만들어라.

초보 시절의 프로그래밍 습관은 상당히 중요합니다. 주석, 변수명, 메소드 호출 등에 있어서 다양한 습관들이 서로 다르게 표현될 수 있습니다. 특히, 프로그래밍의 내용은 비즈니스의 흐름과도 동일하며, 그 흐름은 마치 한편의 드라마를 보듯이 매끄럽게 이어져야 합니다. 변수 선언, 객체 생성, 리소스 획득, 메소드 호출 등이 뒤죽박죽 섞여 있어서 코드를 본다는 것 자체가 무슨 내용인지를 모르게 구성하는 경우들이 있습니다. 프로그래밍의 내용은 코드만을 보고도 어떠한 흐름으로 이어지는지를 알 수 있게 구성되어야 하며, 이는 마치 시나리오와 같습니다.

어떤 경우에는 초반에 만든 코드와 나중에 수정한 코드가 뒤범벅이 되어서 어떤 것이 실제로 사용하는지도 잘 모르게 구성되는 경우도 많습니다. 정 이전 코드를 참고하고 싶으면, 차라리 주석 처리하거나 별도의 메소드를 만들어서 구성하는 것이 더 깔끔할 겁니다. 그리고, 사용되는 것과 사용되지 않는 것들에 대한 구분 역시 필요하며, 이는 본인만 알아볼 수 있는 것이 아닌 공통적으로 누구나 알아볼 수 있는 표시를 해야 할겁니다.

코드는 실행되는 것도 중요하지만, 무엇보다 깔끔한 형태의 코드 결과도 상당히 중요합니다. 그 안에는 누구든지 해당 코드를 보고 쉽게 이해할 수 있고, 이름만 보더라도 무엇을 하는 객체인지를 알 수 있게 구성하는 것이 훨씬 중요합니다.

7. 처음부터 구조화시킬 필요는 없다.

처음에 프로그래밍 언어에 익숙해지기 시작하면서 코드에 대한 구조를 생각하게 되고, 초반부터 이해하지 못하는 구조를 만들기 시작하는 경우도 있습니다. 구조화는 코드가 동작하는 상태에서 의미가 있으며, 구조화되지 못한 코드라고 하더라도 동작한다면 크게 문제되지 않을 수 있습니다. 초반에 구조화를 시도하다가 많은 시간을 허비하는 경우도 있으며, 다양한 구조화를 시도하다가 실제 작업은 진행하지 못하는 경우도 많습니다. 또한, 초반에 너무나 많은 내용을 한꺼번에 프로그래밍을 하다보니, 테스트할 시간조차도 부족한 경우도 있습니다.

처음 객체를 만들때에는 가장 단순하고 적은 데이터만을 사용해서 전체적인 뼈대를 구성하는 것이 가장 좋습니다. 그리고, 이러한 뼈대에 차츰 살을 붙여서 완성해가는 것이 좋은 방법입니다. 뼈대가 구성되지 않은 상태에서 살을 붙일 수는 없을겁니다. 어느 정도의 구조화는 필요하겠지만, 여기에 모든 노력을 기울여 자신의 실력을 뽐낼 필요까지는 없습니다. 보여주고자 하는 데이터가 한두개 모자란다고 크게 문제되지는 않습니다. 이러한 문제들은 테스트를 통해서 수정하기만 하면 됩니다. (물론, 테스트를 할 수 있는 시간이 확보된다면 문제되지 않습니다.) 하지만, 동작하지도 않는 프로그래밍은 테스트를 하기도 어려우며, 그 결과를 예측하기도 어렵습니다.

8. 책을 쓰듯이 코드를 작성하라.

프로그래머에게는 코드 자체가 문서이자, 작업 대상이어야 합니다. 코드를 작성하는데 매번 만족할 만한 수준까지 작업하기는 힘들지만, 코드를 책을 쓰듯이 작성해야 합니다. 책을 쓴다는 것은 자신이 읽기 위함이 아닌, 다른 사람이 본다는 생각을 할 필요가 있습니다. 다른 사람이 자신이 만든 코드를 보고 이해하기 쉽게 짜임새 있게 구성되어야 하며, 각 부분들의 조각들이 맞추어져서 전체가 하나의 새로운 구성체로 조합되어야 합니다. 책을 쓴다는 것은 작성자의 signature를 포함한 내용들이 그 안에 있어야 하며, 코드에서 만큼은 본인이 구성한 의도가 충분히 포함되어야 합니다.

잘 짜여진 코드는 그 내용이 기승전결과 같은 일관된 구성으로 이루어지며, 심지어 표지나 서문과 같은 내용까지도 생각하여 다양한 데코레이션들을 코드 내에 삽입할 수 있습니다. 무엇보다 책 내용이 중요하듯이 그리고, 그 책의 구성 또한 소홀히 할 수 없듯이 코드는 그 내용을 중심으로 한권의 책을 보는 듯한 인상을 주어야 합니다.

9. 프로그램 내용을 시각적으로 표현해보라.

아무리 단순한 프로그램이라고 하더라도 최소한 몇개의 레이어나 시스템을 거쳐서 비즈니스 로직을 수행하기 때문에 전체적인 윤곽을 그려보는 것이 필요합니다. 또한 프로그램을 담고 있는 각 객체간의 관계가 어떻게 이루어지고, 무슨 작업을 수행할 때 필요한지는 파악해야 합니다. 이러한 모습들은 코드의 형태보다는 간단한 시각적인 표현 방식을 사용해서 파악하는 것이 필요합니다. 때로는 프로그램적으로 해결하기 어려운 부분들이 전체적인 구조를 파악하면 쉽게 해결되는 부분들도 있습니다.

즉, 자신이 만든 프로그램도 중요하지만, 남이 만든 프로그램 역시 전체적으로 어떠한 관계를 맺는지를 파악하는게 중요합니다. 자신이 만든 프로그램이 어떠한 용도로 사용되며, 어떠한 문제들을 일으키게 되는지도 사전에 파악하여 조치를 할 수 있어야 하며, 남이 만든 프로그램을 사용할 때 어떠한 부수 효과(side effect)가 발생할지에 대해서 알아야 합니다.

프로젝트를 혼자 모든 것을 처리하지 않는 이상, 다른 이가 만든 프로그램에 대한 영향, 내가 만든 프로그램에 대한 영향을 파악하는 시각을 키울 필요가 있습니다. 프로그램 자체가 단독으로 실행하는 것보다 서로 다른 사람들이 만들어서 같이 동작하게 만들어서 작업을 하기 때문에 상당한 노력을 필요로 하며, 이는 그리 단순하고 손쉬운 작업이 결코 아니라는 것을 인지할 필요가 있습니다.

이를 위해서는 자신이 만든 프로그램이라도 시각적으로 표현하고 이를 이해할 수 있어야 합니다.

9+1. 항상 원칙을 지키도록 노력하라.

프로젝트 현장에서는 다양한 기술과 노하우들이 펼쳐지고 난무하는 곳입니다. 이곳에서의 기술과 노하우들은 그 근본을 알 수 있는 것들도 있지만, 그렇지 못한 것들도 많이 있습니다. 원칙, 원리, 이론 등은 현장에서의 이러한 적용의 원리에 의해서 마치 구시대적이거나 학구적인 것으로 대접을 받아 상당한 무시와 천대를 받는 경우도 많습니다. 무엇이 되었든 간에 원칙은 반드시 존재해야 하며, 그러한 원칙을 기반으로 다양한 적용 원리가 나타날 수 있다는 것을 잊지 마시기 바랍니다.

원칙이라는 것이 거창하거나 복잡한 내용이 아니지만, 이를 이해하는 과정은 그리 쉬운 작업이 아닙니다. 하지만 원칙이 없는 프로그램 코드는 마치 모래 위에 성을 쌓는 것과 같습니다. 늘 환경에 의해서 흔들리고 다시 지어야하는 경우가 발생됩니다. 사소한 원칙이라도 무시하지 마시고, 그 원칙이 왜 생겨났는지를 곰곰히 생각하여 반드시 프로그래밍으로 표현할 때 같이 이해할 수 있어야 합니다.


위와 같은 내용은 어찌보면 엉뚱한 이야기인 것 같기도 하지만, 대부분이 현장에서 초보 프로그래머들과 접하면서 꼭 해주고 싶었던 이야기들입니다. 프로젝트 현장은 이와 같은 내용들을 세세하게 설명해주고 가르쳐줄 시간이 턱없이 부족하며, 똑같은 실수들을 후배들이 저지르는 것을 보는 것이 안타까울 따름입니다. 초보 시절의 습관은 경력이 쌓이더라도 쉽게 사라지지 않고 그 습관은 반드시 코드 상에 나타나게 되어 있습니다. 처음부터 힘들더라도 차근차근 실력을 쌓아가도록 노력하려는 자세가 필요합니다.

[출처: http://homo-ware.tistory.com/169]

'프로그래밍' 카테고리의 다른 글

아스키코드 표 (ASCII Code Chart)  (0) 2012.06.21
[자바] 소설같은 자바교재: 자북  (0) 2012.06.13
[자바] JAVA 강의 노트  (0) 2012.06.13
Links  (0) 2011.10.16
알고리즘 사이트 Programming-challenges  (0) 2011.10.16

+ Recent posts