0%

override annotation
java5부터 어노테이션이라는 문법이 제공된다. 어노테이션이란 java의 소스코드를 설명하는 메타데이터다. 형태는 @어노테이션명 이다. 즉 소스코드의 특정부분(클래스, 인터페이스, 메소드, 필드 …)에 @어쩌구저쩌구를 붙여서 이 소스코드를 설명한다는 것인데… 누구에게 무엇을 설명한다는 것일까?

  1. 컴파일러에게 코드 문법 에러를 체크하도록 정보를 제공
  2. 소프트웨어 개발 툴이 빌드나 배치 시 코드를 자동으로 생성할 수 있도록 정보를 제공
  3. 실행 시(런타임 시) 특정 기능을 실행하도록 정보를제공

컴파일러

어노테이션의 설명의 대상 중 하나는 컴파일러다. 컴파일러에게 이 소스코드를 어떻게 처리해야 되는 것인지 표시를 해준다. 예를들어 내장 어노테이션인 @override경우 해당 메소드가 부모클래스를 오버라이딩 한 메소드라고 컴파일러에게 미리 일러주는 것이다. 따라서 컴파일러는 런타임 이전에 이 메소드가 문제없이 오버라이딩 되었는지 검사한다.
개발툴, 빌드툴 등도 이 컴파일러와 비슷한 맥락으로 어노테이션을 사용한다고 생각된다.


개발자

어노테이션이 만들어진 목적은 프로그래밍에서 사용하던 xml 파일들을 줄이기 위해서라고 한다. 즉 프로그램에서 사용하는 xml 형태의 다양한 설정정보들, 특히 소스코드를 설명하는 내용의 설정 파일들을 대체하기 위해서이다. 예를 들어 n개의 클래스와 그 n개의 클래스의 설정정보가 xml로 되어있다면 관리의 대상이 두배가 된다.
어노테이션은 이런 xml들을 대신 설명이 필요한 대상과 그 설명을 합치게 되었고, 그 결과 어노테이션이란 것이 만들어 졌다.

예를들어 개발자는 소스코드에 있는 @overide를 보고, 해당 메소드는 상속 받은 것 임을 확인할수 있다.


컨테이너

어노테이션의 설명의 대상 세번째는 컨테이너 이다.
스프링 프레임워크를 만져본 개발자라면 수많은 스프링 어노테이션을 본적이 있을 것이다.
프리임워크는 자신 스스로 자바의 클래스를 객체화 하고 조립하고 사용한다. 즉 자신이 주체가 되어 자바 인스턴스의 라이프사이클을 관리한다. 이때 이 어린아이와 같은 프레임워크가 가지고 놀 클래스에 어노테이션으로 라벨을 붙여, 이 부품(클래스)는 용도가 무엇이고 어떻게 사용하고, 문제가 있을시에 어떻게 해야 하며, 테스트는 어떻게 하는지 기타 등등의 정보를 알려줄수 있다.


정리

자바책에서 어노테이션을 설명하면서, 커스텀어노테이션도 설명 한다. 하지만 공부를 하면서 내가 이 어노테이션을 공부해서 어디에 활용 할 수 있지? 라는 고민이 들었다.
어노테이션은 메타데이터이다. 즉 프로그램 그 자체에서 동작하는 코드가 아니다.
만약 컴파일러, 개발툴, 빌드툴, 테스트툴 또는 스프링프레임워크와 같은 컨테이너를 개발하지 않는 이상 직접 어노테이션을 만들어서 사용해 볼 일이 거의 없을 것 같다.


java의 정적필드는 클래스로더에 의해 메소드영역에 로드가 된다.정적 필드는 객체생성 이전 클래스가 메모리에 올라가는 시점부터 사용이 가능하다. 따라서 클래스의 생성자는 정적필드의 초기화 위치로 적합하지 못하다. 그렇다면 정적필드는 어떻게 초기화 해야 할까?

정적필드 초기화 1 : 선언과 동시에 초기화 하기

1
static double pi = 3.14;

일반적으로 정적필드는 위와 같이 선언과 동시에 초기화 한다. 하지만 외부환경의 영향이나 로직을 통해 정적필드를 초기화 하고 싶을 경우도 있을 것이다.

정적필드 초기화 2 : 정적영역(static block) 사용

1
2
3
4
5
static double pi;
static{
클래스명.pi = 3.14;
System.out.println("정적영역 초기화 완료...");
}

static { … } 형태의 정적영역을 사용하여 정적필드를 초기화 할 수 있다. 정적영역 역시 클래스가 메모리에 로드되면서 동작한다.

정적영역 사용시 주의점 1 : 정적영역에서 인스턴스 멤버에 접근 할 수 없다.

정적영역은 클래스 단위의 영역이다. 모든 인스턴스는 자신의 클래스의 정적필드에 접근이 가능하지만, 그 반대로 정적영역에서 인스턴스의 필드에 접근 할 수 없다. 당연한 말일 것이다. 정적영역에서는 접근할 인스턴스를 구별할 수 없기 때문이다.

정적영역 사용시 주의점 2 : static final도 정적영역에서도 초기화 할 수 있다.

1
2
3
4
static final double PI;  //관용적으로 상수인경우 상수명을 대문자 사용
static {
클래스명.PI = 3.14;
}

java에서 일반적인 인스턴스 단위의 final 필드을 초기화 하는 방법은 필드 선언과 동시 또는 생성자에서 초기화 해야 한다.다른 방법은 존재하지 않는다.
static final 필드는 final이전에 static영역, 즉 클래스 단위의 필드이기 때문에 일반적인 static 필드 처럼 선언시와 정적영역(static block)에서 초기화 할 수 있다.

정적영역 사용시 주의점 3 : interface의 상수는 정적영역에서 초기화 할 수 없다.

인터페이스의 멤버변수는 모두 상수(public static final)이다. 하지만 이 상수는 정적영역에서 초기화 할 수 없으며, 반드시 선언과 동시에 초기화 해야 한다. (20170917 추가)

tips
java의 함수에는 일반적으로 동일한 자료형의 여러개 데이터를 인자로 받을 때, 배열을 인자로 사용 할 수 있다. 하지만 arbitrary number of arguments(… 함수인자)를 사용할 경우 함수는 배열보다도 유연하게 인자를 받을 수 있다.

1
int sum(int ... values){...};

위와 같은 자료형 … 매개변수명 형태로 함수의 인자를 선언 할 수 있다. 예제를 보면 쉽게 이해가 된다.

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
//int형의 파라미터가 몇개가 넘어올지 모를 경우, 대응 할 수 있는 ... 확장된 배열형태의 매개변수 형태
static int sum(int ... values){
int total = 0;
//배열로 인자에 접근 할 수 있다.
for(int i =0; i < values.length; i++){
total += values[i];
}// for
return total;
}// sum

public static void main(String [] args){

//인자를 아예 안받을 수도 있다.
System.out.println(sum()); // 결과: 0

//인자를 하나만 받을 수 있다.
System.out.println(sum(1)); // 결과: 1

//물론 3개도 된다.
System.out.println(sum(1, 2, 3)); // 결과: 6

//배열로도 받을 수 있다.
System.out.println(sum(new int[] {1, 2, 3, 4})); // 결과: 10

int[] values = {1,2,3,4,5};
System.out.println(sum(values)); // 결과: 15

}

함수를 선언 할때 *동일한 형태의 자료형의 인자가 0개 또는 n가 예상 되거나, 또는 배열형태의 인자가 예상될 경우 *함수 오버로딩을 대신하여 위의 arbitrary number of arguments 사용하면 편 할 것 같다.

다만 주의 할 점은 arbitrary number of arguments(… 함수인자)를 사용한 경우 해당 함수는 다른 인자는 갖을 수 없다.

1
2
3
int sum(int ... values, int b){...};  // 컴파일 오류

int sum(int ... values, String b){...}; // 컴파일 오류


이번에 기록할 내용은 this생성자 이다. (this 키워드가 아니다.)
java의 클래스 생성자도 역시 오버로딩이 가능하다. 함수 오버로딩은 훌륭한 기능이다. 다만 일반 함수의 오버로딩이 아니라 생성자의 오버로딩일 경우 객체의 멤버변수를 셋팅하는 경우가 많기 때문에 중복된 소스가 자주 발생한다.

this() 생성자란 클래스의 생성자 오버로딩시 반복되는 소스를 줄여주는 훌륭한 방법이다.
생성자 내부의 코드 블록 첫줄에 this()를 호출함으로 자신의 다른 생성자를 호출 할 수 있다. 주의할 점은 생성자 코드블록 내부의 this() 위에 다른 소스코드가 존재해서는 안된다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
class Person {
private String name;
private int age;
private String sex;

public Person(String name){
//this.name = name; // this()생성자 위에 있는 코드에는 컴파일 오류가 발생한다.
this(name, 12); //자동으로 해당 파라미터에 적합한 자신의 생성자를 호출한다.
System.out.println("this생성자 아래에는 다른 코드가 존재 할 수 있다.");
}

public Person(String name, int age){
//this.name = name; // this()생성자 위에 있는 코드에는 컴파일 오류가 발생한다.
//this.age = age; // this()생성자 위에 있는 코드에는 컴파일 오류가 발생한다.
this(name, age, "Man"); //자동으로 해당 파라미터에 적합한 자신의 생성자를 호출한다.
System.out.println("this생성자 아래에는 다른 코드가 존재 할 수 있다.");
}

public Person(String name, int age, String sex){
this.name = name;
this.age = age;
this.sex = sex;
}
}

위 예제소스를 보면 쉽게 이해가 될것이다. 편리한 기능이라 생각되어 이렇게 기록해 놓는다.

Java에서 / 또는 % 연산자를 사용할 때, 제수가 정수 0인 경우 RuntimeException 중 하나인 ArithmeticException 발생한다.

1
2
3
4
5
6
7
8
9
10
int x = 12;
int y = 0;

try{
int z = x / y;
int z = x % y;
System.out.println("z:" + z);
}catch(ArithmeticException e){
e.printStackTrace(); // 다음과 같은 예외 발생: java.lang.ArithmeticException: / by zero
}

문제는 / 또는 % 연산자를 사용할 때, 제수가 정수 0이 아닌 실수 0.0 또는 0.0f인 경우이다. 이때는 ArithmeticException이 발생하는 것이 아니라, Infinity(무한), NaN(Not a Number)라는 값이 발생한다.

1
2
3
4
5
6
7
8
double a = 3 / 0.0;
double b = 5 % 0.0;

System.out.println(a); // 결과 : Infinity
System.out.println(b); // 결과 : NaN

System.out.println(a + 12); // 결과 : Infinity
System.out.println(b * 6); // 결과 : NaN

수학적으로 오류가 발생해야 하는 것임에도 ArithmeticException가 발생하지 않는다. 거기다 a, b변수는 double의 자료형임에도 Infinity, NaN 이라는 문자열 형태 데이터가 출력된다.(잘은 모르겠으나, Double wrapper 클래스가 개입하는 것이라고 개인적으로 추측해본다.)
거기다 이 Infinity, NaN는 오라클의 null 값과 비슷 한 특성을 가지고 있다. 오라클의 null에 어떤 연산을 가하면 미지의 쓰레기 값이 발생하는데, 이 java에서의 Infinity, NaN에 어떤 추가적 산술연산을 할경우 Infinity는 계속 Infinity가 되며 NaN도 계속 NaN이 된다.

Double.isInfinite(a)와 Double.isNaN(b)를 이용하여 Infinity와 NaN를 값을 확인 할 수 있다. 따라서 다음과 같이 Infinity, NaN을 방어하는 코드를 만들수 있다.

1
2
3
if(Double.isInfinite(a) || Double.isNaN(a)){
throw new ArithmeticException();
}

하지만 애시당초 0.0 또는 0.0f와 같은 값들을 정수 0로 치환하여 / 또는 % 연산시 자동으로 ArithmeticException가 발생하게 하는 편이 더 편할 것 같다.

마지막으로 Infinity, NaN에 관련하여 생각해야할 문제점이 있다. 그것은 Double.valueOf(x)의 멍청함이다.

1
2
3
4
5
6
7
8
9
10
11
double val = Double.valueOf("NaN");    // 오류가 나지 않고 NaN값이 저장된다.
double val2 = Double.valueOf("Infinity"); // 오류가 나지 않고 Infinity값이 저장된다.

double foo1 = 1000.0;
double foo2 = 1000.0;

foo1 += val;
foo2 += val2;

System.out.println(foo1); // 결과 NaN
System.out.println(foo2); // 결과 Infinity

위 예제를 보면 Double.valueOf의 인자로 문자열 NaN, Infinity를 받는다. 하지만 코드를 실행시 어떠한 오류없이 동작하며 콘솔에는 NaN, Infinity가 출력된다. 재앙이 아닐 수 없다.

정리하자면
java의 산술식에서 0.0또는 0.0f같은 값은 정수 0으로 치환하는 편이 좋아보이며, Double.valueOf함수를 사용시 반드시 Double.isInfinite, Double.isNaN를 통하여 후처리를 해줘야 할 것 같다.

부동소수점

부동소수점

코딩을 공부하다보면, 누구나 마주해야할 최악의 적! floating point! 이것은 자바언어의 문제가 아니라 컴퓨터의 자체적인 문제로 실수의 표현 및 계산 시 오차의 원인이 되는 이유이다.
간단히 말해 자바는 실수표현을 부동소수점을 이용하기 때문에 정확한 실수를 저장 할 수 없으며, 최대한 완벽에 가깝기를 바라는 근사치 값을 저장한다.

부동소수점의 정확도 문제(위키)


부동소수점 산술시 문제

1
2
3
4
5
6
7
//예제1: 부동소수점 산술시 문제점
int apple = 1;
double piceUnit = 0.1;
int number = 7;

double result = apple - number * piceUnit; // 원하는 계산: 1 - 7 * 0.1 = 0.3
System.out.println(result); // 결과 : 0.29999999999999993

1 - 7 * 0.1 산술식의 정확한 계산은 0.3이다. 하지만 결과는 0.29999999999999993 이다. 원인은 double이라는 실수형 자료형이 0.1을 정확히 표현하지 못하기 때문이다. 정말 성가신 녀셕이 아닐 수 없다.

따라서 실수의 정확한 계산을 위한 한가지 방법으로는 정수형태로 계산을 한 뒤, 소수점을 나중에 반영하는 것이다.

1
2
3
4
5
6
7
8
//예제2: 부동소수점 산술시 문제점 해결방법
int apple = 1;
int totalPieces = apple * 10;
int number = 7;
int temp = totalPieces - number;

double result = temp / 10.0; // 이런식으로 나중에 소수점 만큼의 계산 결과에 나눠준다.
System.out.println(result); // 결과 : 0.3

만약 자바를 이용해서 계산기 같은 것을 만든다면, 위와 같은 부동수수점 산술시에 실수들을 정수형태로 변형해서 계산하는 것을 고려해볼 필요가 있다.


double과 float의 비교연산시 문제

float는 4바이트 실수, double은 8바이트 실수 값을 저장 할 수 있다. 부동소수점으로 실수를 표현하기 때문에 double은 float보다 상대적으로 보다 더 정확한 실수를 표현 할 수 있다.
문제는 1미만의 값을 갖는 double과 float간의 정확도 차이이다.

1
2
3
4
5
System.out.println(1.0 == 1.0f);  // 결과 : true
System.out.println(1.1 == 1.1f); // 결과 : false
System.out.println(0.1 == 0.1f); // 결과 : false
System.out.println(0.9 == 0.9f); // 결과 : false
System.out.println(0.01 == 0.01f); // 결과 : false

위 예제를 눈으로면 보면 다 true일 것이라 착각 하기 쉽다. 하지만 주석처럼 맨 윗줄만 제외하고 다 false를 출력한다. 이유는 눈에 보이지는 않지만 float와 double자료형의 실수 표현의 정밀도의 차이가 발생하기 때문이다. 따라서 double과 float값을 비교 할때에는 모두 float로 형변환 하거나 정수로 변환하여 비교해야 한다.

1
2
3
System.out.println((float)1.1 == 1.1f);  // 결과 : true
System.out.println(0.1 == (double)0.1f); // 결과 : false
System.out.println(0.1f == (double)0.1f); // 결과 : true

주의 할 점은 0.1f를 double로 형변환 하여 비교해도 될 거라 생각 할 수 있는데, (double)0.1f는 double의 공간에 float의 정밀도를 갖는 값이 저장될 뿐이다. 따라서 double형의 0.1과 비교해도 결과가 true로 나올 수 없다.

java언어에서는 datatype(자료형)이라는 것이 존재한다.
자료형이란 변수에 저장 될 데이터의 형태를 지정하는 용도로 사용되며, 정수 실수 문자 논리 등등 다양한 형태로 존재한다. datatype overflow란 이 java에서 산술연산을 할 경우 해당 변수의 자료형의 표현 범위를 초과할 경우 쓰레기값이 발생되는 경우를 말한다.

1
2
3
4
5
//예제1
int a = 1000000;
int b = 1000000;
int c = a * b;
System.out.println(c); // 결과 : -727379968

정수형 int 변수 c에는 1000000000000 이라는 값이 저장되는 것이 아니라, -727379968라는 예상치 못한 값이 저장된다.
그 이유는 int가 표현할수 있는 정수값의 범위에 1000000000000 와 같이 큰 정수값이 저장될수 없기 때문이다.
java의 자료형 범위는 다음과 같다.

data overflow

따라서 예제1의 경우 int보다 큰 long자료형을 사용하여 해결 할 수 있다.

1
2
3
4
5
//예제2
int a = 1000000;
int b = 1000000;
long c = a * b;
System.out.println(c); // 결과 : -727379968

최종으로 연산된 값이 저장될 c변수의 자료형을 int보다 큰 long으로 변경 했음에도 여전히 값은 -727379968라는 쓰래기 값이 저장된다. 실수하기 쉬운 부분인데 c는 long 타입이지만 c에 피연자인 a, b는 여전히 int이므로 결과적으로 c에는 예제1과 마찬가지로 쓰레기 값이 저장된다.
따라서 산술식의 피연산자중 최소 한개는 long 타입이어야 올바른 계산이 된다.

1
2
3
4
5
//예제3
int a = 1000000;
int b = 1000000;
long c = (long)a * b;
System.out.println(c); // 결과 : 1000000000000

산술로직을 사용할 경우 위와 같은 문제를 방어하기 위한 전용 산술 함수를 사용하는 편이 코딩에 효과 적일 것 같다.

마크다운이란

간단히 말해서 웹 문서 전용 글쓰기 마크업 언어이다. 웹에서 보여질 심플한 문서(대표적으로 HTML)를 간편하고 쉽게 작성하기 위해 만들어진 마크업 언어이다. 일반적으로 웹 페이지를 만들기 위해서는 HTML언어를 사용해야 한다.

코딩 할 때 개인적으로 순수 HTML의 명료성을 좋아하지만, 단순한 글을 쓰기위한 목적으로 쓰기에는 너무 많은 수고가 발생한다.

1
2
3
4
5
6
7
8
9
10
<!DOCTYPE>
<html>
<head><title>간단한 문서</title></head>
<body>
<H1>간단한 문서를 써보자</H1>
<br>
아이고 몇줄 쓰는데 온 갖 태그를 타이핑 해야 된다. 힘들당<br>
<font size="3">WYSIWYG에디터라도 있었으면...</font>
</body>
</html>

마크다운은 몇 개의 특수문자를 이용한 간단한 문법을 이용하여, html로 변환할 수 있는 문서를 작성할 수 있다. 물론 html도 간단한 문법을 가지고 있지만, 마크다운에 비할바는 아니다. 마크다운을 한번 써보면 누구나 느낄 것이다. 사람 손으로 키보드에서 타이핑 하기가 정말 편하다. 물론 간단한 문법이기 때문에 HTML의 일부분 기능만 사용 할 수 있다. 하지만 내가 원하는 간단한 글쓰기 용으로는 부족해 보이지 않는다.

마크다운 문서 -> 마크다운 변환기 -> HTML 문서

내가 이 마크다운을 접하게 된 계기는 Jekyll, hexo등의 정적 블로그 프레임워크를 만들면서였다. 블로그에서 간단한 문서를 작성하는 방법으로 jekyll, hexo, ghost 등의 블로그 프레임워크에서 마크다운을 지원하고 있다.

네이버블로그, 티스토리등에서 지원하는 WYSIWYG에디터는 웹에서 간편하게 글을 쓸수 있지만, 그 것으로 작성되어 변환된 HTML은 지옥의 죄수들을 갈아놓은 스프와 같아보였다. 거기다 WYSIWYG에디터에서 소스코드등을 삽입하기 위해서는 플러그인또는 js를 건드려야 한다.

반면 마크다운으로 작성된 문서의 HTML은 상대적으로 심플하며, 자체적으로 제공하는 심플한 문법으로 소스코드 삽입이 아주 편하다. Typora라는 마크다운 에디터를 사용하면, 마크다운의 문법의 러닝커브도 상당히 줄어든다.


마크다운 에디터(Typora)

마크다운문서도 문서의 종류일 뿐이다. 메모장으로 작성해도 되지만, 요즘 세상에 편리한 툴을 두고 고생을 하는 것는 인생을 낭비하기에 딱 좋은 방법일 뿐 이다.

마크다운문서는 html로 변환되어야 할 기초 문서이다. 따라서 현재 내가 적성하고 있는 마크다운 문서를 html로 변환하고 또는 실시간으로 그 변화된 모습을 보여주는 기능이 있는 에디터가 필요했다.

아톰에디터 마크다운 작성화면

위 화면은 아톰에디터에서 마크다운 플러그인을 설치하여 마크다운을 작성하는 화면이다. 아톰도 나름 쓸만했지만, 낮은 신뢰도와 너무 무거웠다. 그리고 한 화면에 마크업문서와 변환문서가 같이 보이므로 화면이 너무 좁아져서 불편한 감이 있었다.

그러다 찾게 된 마크다운 에디터는 Typora였다. Typora의 가장 큰 장점은 마크다운 문서를 작성하는 동시에 HTML로 변환된다는 것이다. 한 화면에서! 거기다 간한단 단축키, 단축메뉴에서 마크다운 문법을 UI에서 지원하므로 나처럼 마크다운 문법이 생소한 경우 손쉽게 문서를 작성할 수 있다.

개인적으로 Typora = markdown계의 WYSIWYG에디터 이런 느낌이다. Windows, Mac, Linux모두 지원하므로 만약 마크다운을 입문하는 사람들에게는 Typora에디터를 추천한다.
Typora홈페이지


마크다운 기본문법

마크다운 위키

아파치(Apache) 웹서버 윈도우10 환경에 설치

windows10 64bit 운영체제에 아파치 웹서버를 설치하는 방법을 설명하겠다.


1. 웹 브라우저를 통해 https://www.apachelounge.com/download/ 로 이동 >![](/images/2017-06-11-apache설치_1.png) 원하는 아파치 웹서버 버전을 선택후 64bit zip 파일을 클릭하여 다운받는다. >![](/images/2017-06-11-apache설치_2.png)
  1. 해당 파일을 C:\ 경로로 이동후 압축을 푼다.


    폴더 내부로 이동하여 Apache24 폴더를 잘라내기 한 후 다시 C:\ 경로로 이동하여 붙여넣기 한다.

최종적으로 아래와 같이 폴더 구성이 되면 된다.

  1. 아파치 웹서버 설치전 환경 설정

C:\Apache24\conf 경로로 이동하여 httpd.conf 파일을 수정해야 한다.
파일을 메모장으로 연뒤 원하는 항목을 수정하면 되는데 여러 항목중에 다음 항목들이 중요하다.

기본셋팅
ServerRoot “c:/Apache24”
Listen 80
DocumentRoot “c:/Apache24/htdocs”

ServerRoot 항목은 기본적으로 “c:/Apache24” (경로 구분을 역슬래시로 해야 한다.) 되어 있다. 이 디폴트 셋팅을 그대로 사용하기 위해서 2번처럼 폴더 경로를 지정한 것이다. 만약 위 설명과 다른 폴더경로에 웹서버 폴더를 셋팅 했다면 ServerRoot 항목의 셋팅을 알맞게 수정해 주면 된다.

Listen 항목은 웹서버의 포트(port)설정이다. 웹서버는 기본적으로 80포트이다.(디폴트라 생략이 가능하다. www.naver.comwww.naver.com:80 은 같다)
원하는 포트가 있다면 역시 수정하라. (필자는 8080으로 수정하였다. )

DocumentRoot 항목은 웹서버에서 실행할 웹사이트 root 폴더를 지정해야 한다. ServerRoot처럼 디폴트로 “c:/Apache24/htdocs”로 셋팅 되어 있다.
원하는 경로가 있다면 수정하라.
부연설명으로 웹서버 기본 url(현재는 http://localhost:80) 접근시 웹서버는 DocumentRoot 에 설정된 폴더 내부의 index.html 를 디폴트로 리다이렉트 한다.

  1. 설치
    관리자 모드로 cmd(명령 프롬프트) 창을 연다.
    키보드의 윈도우 버튼을 누른뒤 cmd라고 검색하면 나온다.
    명령 프롬프트 항목에 마우스 우클릭 한 뒤 “관리자 권한으로 실행”을 선택한다.

cmd 창이 열리면 cd C:\Apache243\bin 을 입력하여 경로를 이동한다.

이동한뒤 아래 명령어를 입력하여 아파치 서버를 설치한다.
httpd.exe -k install

뭔가 error라고 나오긴 하는데 무시해도 지장 없다.(도메인 관련 error 인것 같다)

만약 설치한 아파치 서버를 삭제 하고 싶다면 아래 명령어를 입력하면 된다.
httpd.exe -k uninstall

  1. httpd.exe -k install 명령어 입력 후

윈도우 탐색기에서 C:\Apache24\bin 경로로 이동후 AapcheMonitor 응용 프로그램을 실행한다.

윈도우의 오른쪽 하단 작업 표시줄을 보면 ApacheMonitor가 실핼된 것을 확인 할수 있다.

해당 아이콘을 우클릭후 Apache2.4 > Start 를 클릭하면 웹서버가 동작한다.
반대로 웹서버를 종료하고 싶다면 Stop 을 클릭하면 된다.

  1. 웹서버 동작 확인

웹서버를 start 한뒤에 인터넷 브라우저 창을 열고 주소창에

1
http://localhost:설정한포트번호

또는

http://127.0.0.1:설정한포트번호 

를 입력한다.

필자는 http.conf 파일에서 포트를 8080 으로 수정하였으므로

http://localhost:8080 을 입력하겠다.

위처럼 DocumentRoot 경로의 index.html 브라우저창에 열리는 것을 확인할 수 있다.
윈도우 관리도구등 기타 설명은 상단의 유투브 영상을 참고하길 바란다.

REST(REpresentational State Transfer: 표현 상태 전송)는 웹 아키텍처 스타일이다.

HTTP 스펙 설계에 참여했던 로이필딩이라는 사람이 2000년대 발표한 네트워크(웹) 아키텍처 스타일이다.
여기서 네트워크 아키텍처 스타일이란 한가지의 웹 아키텍쳐 가 아니라 여러 가지 복수의 아키텍쳐의 공통된 성질, 양식 규정 혹은 독특항 방식의 집합을 네트워크 아키텍쳐 스타일이라고 한다.
REST를 네트워크 아키텍쳐 스타일이라고 하지만, 사실 HTTP 기반위에 존재하는 아키텍쳐 스타일이므로 웹 아키텍처 스타일이라고 부르는 것도 틀린 표현은 아닌 것 같다.

RESTful은 어떤 대상이 REST 의 제약에 따르고 있고, 그래서 상당히 REST스럽다? REST답다 라는 형용사적 의미이다.

예를 들어 어떤 서버 A가 존재 한다고 하자. 이 A서버는 REST라는 아키텍츠 스타일의 제약을 충실히 따르고 있다면, 이 A 서버를 RESTful 한 서버라 부를 수 있다.

REST의 의미

REST는 수많은 아키텍처 스타일 중에서도, 특히 네트워크 시스템의 아키텍처 스타일 이다.
그리고 REST는 웹의 대표적인 아키택처 스타일인 클라이언트/서버를 기반으로 하는 복합 아키텍처 스타일이다.
, 즉 로이필딩은 REST 기반으로 네트워크를 설계하면 효과적이라고 생각했다.

REST = 클라이언트/서버 + 스테이트리스 서버(Stateless Server) + 캐시(cache) + 유니폼 인터페이스(uniform Interface) + 계층화 시스템 + 코드 온 디맨

클라이언트/서버
말그대로 클라이언트 와 서버로 구성되어 있으며 클라이언트에서 request하면 서버에서 response한다.

스테이트리스 서버
클라이언트의 어플리케이션 상태를 서버에서 관리하지 않는다는 의미이다. 서버가 어플리케이션의 상태를 가지지 않게되면, 그만큼 서버 측의 구현이 갈결해지는 장점이 있다.
하지만 현실적으로 스테이트리스가 아닌 웹 서비스와 웹 API가 많이 사용된다. 특히 HTTP를 스테이트풀 하게 만드는 대표적인 것은 Cookie를 사용한 세션관리이다.
REST의 관점에서 본다면, Cookie를 사용한 세션관리는 HTTP의 잘못된 확장이다. 다만 REST의 기준으로 잘못되었다고 해서, Cookie를 사용한 폼 인증을 그만둘 수 없는 것도 현실이다. Cookie는 스테이트리스 서버의 이점을 버린다는 것을 이해한 후 최소한으로 이용 해야 한다.

캐시
리소스의 신선도에 기초해, 한번 가져온 리소스를 클라이언트 쪽에서 돌려쓰는 방식.

유니폼 인터페이스 (리소스, http 메소드, 메세지)
URI로 지정한 리소스에 대한 조작을 통일되고 한정적인 인터페이스로 수행하는 아키텍처 스타일을 말한다.
예를 들어 HTTP1.1 에서 GET, POST등 8개의 메소드만 정의되어 있고, 보통은 이 이상 늘어나지 않는다. 어떻게 보면 확장성이 떨어진다고 보여지지만 이런 제약이 현재 웹의 통일된 인터페이스를 만들어 낸 것이다.

REST에서는 모든 것을 명사형 리소스로 표현하며, 의미가 명확한 한정된 HTTP 메소드를 사요하고, 메세지를 담아서 통신한다.
아래는 대표적으로 사용하는 메소드 4개이다.

메소드명기능
getsearch
postcreate
putupdate
deletedelete

아래는 실제 REST 메세지의 표현 형테이다.
http://somthingweb/user/ 주소(리소스 url)에 POST(CREATE)해라 rocky라는 이름으 user를 이라는 의미를 갖는 메세지이다.

1
2
3
4
5
6
HTTP POST , http://somthingweb/user/
{
"user":{
"name":"rocky"
}
}

계층화 시스템

유니폼 인터페이스로 인해 발생되는 이점중 하나이다. 통일된 인터페이스로 인해 시스템 전체를 계층화 하기 쉽다. 프록시 서버, 로드벨런서 등등을 http 인터페이스로 통일하여 계층화 하여 사용 할수 있다.

코드 온 디맨드(code on demand)

프로그램 코드를 서버에서 다운 받아 클라이언트에서 실행하는 아키텍처 스타일이다.
처음에 이 개념은 서버에서 발생하는 부하를 클라이언트쪽으로 부담시켜 서버의 부하를 낮추것이 목적이었다.

예를 들어 javascript나 flash, java 애플릿 등이 여기에 해당한다.
반대로 jsp, asp 같이 백엔드에서 페이지를 렌더링해서 클라이언트에 보내는 경우, 수많은 화면 페이지들은 *.jsp 또는 *.asp 이런 확장자를 가지게 된다. 이는 화면단 소스가 백엔드 기술에 종속된다는 것을 의미한다.
jsp, asp 이런 기술들은 백엔드에 프론트엔드가 기술적으로 종속된다는 단점이 있지만, 이런 단점을 무색하게 할 정도로 강력한 기능을 제공해 왔다.

하지만 근래 javascript의 눈부신 발달, jquery, ajax 기타 수많은 블라블라.js 등으로 인해 이런 백엔드 서버페이지 기술, jsp, asp이런 것들이 제공하는 기술들을 대체하는 시대가 되었다. 본래의 서버의 부하를 낮추는 기능 뿐만 아니라 프론트 엔드가 서버에 독립적으로 동작할수 있는 특성이 생겨버렸다.

요즘의 REST, RESTful 하다라는 말이 유행하게 된 가장 큰 이유는 발전된 javascript, jquery, ajax를 통해 백엔드에 독립적인 프론트엔드 개발이 가능한 환경 즉 코드 온 디멘드가 가능한 환경이 되었기 때문이라고 생각된다.
특히 ajax통신은 http + xml or json 형태의 통신형태로 인해 REST가 지향하는 유니폼 인터페이스를 구현하는 기반이 되었다고 생각된다.

jquery, ajax를 이용하여 프론트엔드는 백엔드에 종속되지 않고 백엔드 시스템과 통신할수 있다.
이런 시점에서 적절한 웹 아키텍처가 필요했고 로이필딩이 2000년대 논문을 통해 발표한 REST라는 웹 아키텍처 스타일이 트랜드상 선호되는것 같다.