TCP/IP 네트워크 프로그래밍 공부를 하면서 나름 정리한 개념인데

만들어보면서도 알 것 같으면서도 어려운 개념인것 같다. 저기 어디에 메모 짱박아두다가 이제 정리 해 본다.


많은 사람들이 블록킹과 동기식을, 논블로킹과 비동기를 같은 용어로 생각하는데 엄연히 다른용어다.


우선 bloking I/O(블록킹), Non-blocking I/O(논블록킹)는 소켓의 동작방식을 나타내는 말이고,

그리고 Syncronous(동기), Asyncronous(비동기)는 서비스나 함수의 동작방식을 나타내는 말이다.



● Blocking I/O


블로킹 입출력 방식은 요청한 작업이 완료되지 않으면 응답을 돌려주지 않는다.

버퍼가 비어있을 경우, 입력이 들어올 때 까지 대기하며 그 동안 다른작업을 할 수 없다.

그러므로 자원의 낭비가 발생하게 된다.


blocking i/o와 달리 nio방식은 다수의 클라이언트의 요청을 처리할 수 있는데,

blocking i/o 에서는 스레드를 사용하여 해결할 수 있다.


하지만 과도한 요청수 만큼 발생한 스레드(멀티쓰레드)는 OOM(Out Of Memory)를 발생 시킬 수 있다.

이를 방지하고자 스레드를 사용하고 반납하는 형식으로 스레드의 개수를 제한하는 스레드풀을 사용한다.


스레드풀의 크기를 정하는 것에는 두가지 관점에서 생각할 필요가 있다고 한다.


첫 번째는 스레드의 개수는 힙에 할당된 메모리의 크기에 의존하는데

클 수록 관리해야 할 스레드 개수가 늘어나므로 가비지 컬렉션의 수행속도가 감소한다.


두 번째는 많은 스레드가 Context Switching(CPU를 점유하기 위한 상태변경)을 하면서

엄청난 오버헤드를 발생시킨다. 이는 cpu 성능저하의 원인이 된다. 


쓰지 말라는 것이 아니고 용도에 맞게 적절하게 사용하는 것이 맞다.

하지만 멀티스레드를 사용하는 병렬처리는 공유자원에 대한 dead lock의 위험 때문에 프로그래밍 하는것이 쉽지 않다.



● Non-Blocking I/O (NIO)


논블로킹은 셀렉터(selector)나 폴(poll)에 여러 소켓을 바인딩 시킨 후

하나의 채널(싱글스레드)에서 관리하는 방식이다. 멀티플렉서에 비유한 것을 본 것 같기도하다.


셀렉터는 주기적으로 채널에 데이터가 들어왔는지 확인하는데

버퍼가 비어있을 경우 즉각 return 시키고 다음 요청을 받을 수 있기 때문에

멀티스레드에 비해 오버헤드가 적다.




● Syncronous (동기)


"동기" 라는 용어는 기본적으로 둘 사이의 싱크를 맞춘다는 말이다.

행위나 목적이 같은것을 시작과 끝을 맞추어 동시에 이루어 지는 방식이다.


● Asyncronous (비동기)


비동기는 요청이 들어와도 꿋꿋이 내가 하던 일을 한다. 들어온 요청은 맡겨버리고 "그 일 다끝나면 알려줘~" 하는 것이다.

그러므로 비동기는 수행되는 순서 및 시작과 끝을 알 수 없다.

동작방식은 메인스레드에서는 내가 하던일을 함과 동시에 요청받은 작업이 별도의 스레드에서 진행되는 거다.

작업이 끝나면 "다 끝났어 가져가" 하며 콜백으로 알려준다. 이러한 방식에는 델리게이트, 퓨처, 프로미스, 콜백 등이 있다. 



동기와 비동기의 간단한 예제를 살펴보자.


1. 싱글스레드 + 동기식


스레드에서 순서대로 요청받은 작업을 처리한다.

하지만 앞의 작업이 모두 끝날 때 까지 뒤의 작업은 무한대기다.



2. 멀티스레드 + 동기식


각각의 스레드에서 요청을 1:1로 맡아 작업을 처리한다.



3. 싱글스레드 + 비동기식


일단 모든 요청을 결과에 상관없이 반환한다.

그리고 작업이 끝남과 동시에 결과를 알려준다.



4. 멀티스레드 + 비동기식


모든 요청을 여러 스레드가 나누어 결과에 상관없이 반환한다.

그리고 작업이 끝남과 동시에 결과를 알려준다.

가장 빠른 속도가 예상되며 2번과 3번을 섞은 느낌이다.




아래는 동기와 비동기 방식의 간단한 예제다 (출처 : http://malchooni.name/)


동기방식은 A노드와 B노드사이의 작업 처리 단위(transaction)를 동시에 맞추겠다는 뜻이다.
얄순이에게 보내는 말춘이의 오천원‘ 예를 보자.

ex1

  1. 말춘계좌는 오천원을 뺄 생각을 하고 있다.
  2. 말춘계좌는 얄순계좌에게 오천원을 전송한다.
  3. 얄순계좌는 오천원이 수신되었단 걸 인지 하고 말춘계좌에게 ‘받았음’을 전송한다.
  4. 이로써 말춘계좌는 -5000원을 하고 얄순계좌는 +5000원을 한다.

이 예제에서 눈여겨 볼 부분은 마지막이다. 말춘계좌와 얄순계좌는 서로의 요청과 응답을 확인한 후 같은 일을 동시에 진행했다.
‘계좌이체’라는 작업단위는 위의 그림처럼 동기화를 해야한다. 그래야지 한쪽이 보냈는데 못받았거나, 안보냈는데 받은 상황이 없을 것이다.

비동기방식은 이와 반대로 노드사이의 작업 처리 단위를 동시에 맞추지 않아도 된다는 것이다.
말춘학생의 시험지는 얄순선생이 채점한다‘ 예를 보자.

ex2

  1. 말춘학생은 시험지를 열심히 푼다.
  2. 시험지에 답안 작성을 완료한 말춘학생은 시험지를 얄순선생에게 전송한다.
  3. 얄순선생은 말춘학생의 시험지를 채점한다.
  4. 채점이 다 된 말춘학생의 시험지를 다시 전송한다.
  5. 말춘학생은 얄순선생이 채점한 시험지를 받아 본다.

말춘학생과 얄순선생은 시험지라는 연결고리가 있지만 시험지에 행하는 행위(목적?)은 서로 다르다. 한사람은 시험지를 푸는 역할을 또 한 사람은 그 시험지를 채점하는 역할을 한 것이다. 그래서 둘의 작업 처리 시각을 따지자면 일치하지 않는다. 일치하지 않아도 된다.

여기서 블록과 논블록의 차이를 간략히 설명해 보겠다. 말춘학생이 시험지를 얄순선생에게 건낸 후 얄순선생의 얼굴만 바라보며 채점 된 시험지를 받기 기다린다면 말춘학생은 블록 상태인 것이다. 하지만 말춘학생이 시험지를 건낸 후 채점이 완료 됐다는 이벤트를 받기 전까지 춤을 춘다거나 클래시오브클랜을 한다던가 다른 일을 하게 된다면 말춘학생의 상태는 논블록 상태인 것이다.
동기와 비동기, 블록과 논블록은 헷갈리기 쉬운 개념이다.

자바네트워크 프로그래밍 블록과 논블록 *

마지막으로 정리를 하자면 동기와 비동기는 어떤 작업 혹은 그와 연관된 작업을 처리하고자 하는 시각의 차이이다. 동기는 추구하는 같은 행위(목적)가 동시에 이루어지며, 비동기는 추구하는 행위(목적)가 다를 수도, 동시에 이루어지지도 않는다. 


'전공과목 > Network' 카테고리의 다른 글

OSI 7 Layer [OSI 7 계층]  (0) 2016.10.18
[네트워크] 빅엔디안 리틀엔디안  (1) 2016.10.12

정규화란


데이터 중복을 최소화, 데이터 안정성 확보, 데이터 일관성 유지를 위해

자료의 손실이나 불필요한 정보의 도입없이, 하나의 테이블을 둘 이상으로 분리하는 작업



● 목적


자료 저장에 필요한 저장공간 최소화

자료의 삽입, 갱신, 삭제에 따른 이상현상 제거

자료구조의 안정성 최대화



● 슈퍼키


그 자체로만으로 고유식별자가 되는 것

슈퍼키에 뭘 갖다 붙여도 슈퍼키



● 후보키


슈퍼키의 부분집합으로, 구성 애트리뷰트중 하나라도 제거하면 슈퍼키가 아닌 것

모든 다른 애트리뷰트를 함수적으로 결정하는 애트리뷰트

즉 다른 모든 것을 결정하는 결정자


y가 x에 종속 될 때, x->y 라고 표현

x는 결정자, y는 종속



● 기본키(PK)


여러 후보키 중 대표적인 키 하나가 테이블의 기본키가 된다.




●  제 1정규화(1NF)


테이블은 반드시 하나 이상의 키를 가지고 있어야 하며, 애트리뷰트의 도메인이 오직 원자값만을 포함한다.

반복되는 그룹속성이 존재할 경우, 그 그룹을 분리하여 새로운 엔티티타입을 추가한 후 실체와 1:N관계를 형성해준다.



예제

컴퓨터 학원에서 수강생에 대한 자격증 보유 사항 테이블을 만든다고 가정해보자


[자격증 보유 사항 테이블] 기본키 : 학생번호

학생번호

이름

주소

핸드폰번호

자격증

자격증번호

취득일


제1 정규화를 하지 않고 테이블 사용시 쓸데없는 데이터베이스 공간의 낭비가 발생한다.

또한 주소나 핸드폰번호의 변경이 있을 경우 4개의 레코드를 모두 변경해야 한다.


만약 학생번호 1인 김개똥이라는 친구가 자격증을 4개를 가지고 있다면

김개똥에 대한 정보, 즉 회원번호, 이름, 주소, 핸드폰번호등의 정보가 중복해서 저장되어진다.


학생번호

이름

주소

핸드폰번호

자격증

자격증번호

취득일

1

김개똥

하와이

019-999-999

정보처리

12345

백수

1

김개똥

하와이

019-999-999

워드1급

23456

고2

1

김개똥

하와이

019-999-999

오라클

34512

고2

1

김개똥

하와이

019-999-999

MCSE

12341

고3


 해결 방법 -> 1NF : 반복되는 그룹 속성 분리

 




중복되는 속성을 4 -> 1으로 줄임

 자격증 보유테이블에서 학생번호는 FK이면서 동시에 PK<식별자 관계>




●  제 2정규화(2NF)


기본키 2개 이상으로 구성되는 테이블에서 일부 속성에 대해서만 부분적으로 함수 종속적인 것을 분리

부분함수 종속성을 제거 다시 말해 본키가 하나 인 경우 제 2정규화를 하지 않고 Pass!!

즉, 후보키가 아닌 애트리뷰트들이 후보키(결정자)에 대해 완전종속



예제

컴퓨터 학원에서 수강생에 대한 교육과정별 평가에 대한 테이블 만들었다고 가정해보자

 

 [학생 성적테이블] 기본키 : 학번, 과정코드

학번

과정코드

평가

과정명

기간


제2 정규화를 하지 않고 테이블 사용시 과정명 하나만 수정해도 모두 바꾸어야 주어야 한다.

즉, 중복된다. (1NF와 동일) -> 무결성 유지 힘듬


column명 만을 보면 어찌해야 되는지 알 수 없다. 가볍게 data를 삽입해보자


학번

과정코드

평가

과정명

기간

200

A01

A

JAVA

1개월

200

A02

A

DB

2개월

201

B01

B

ASP

2개월

202

A01

A

JAVA

1개월

203

B01

C

ASP

2개월


- 모든 data는 [학번,과정코드]의 키로 unique 해진다(중복된 data X). 즉 1NF Pass

- 복합키[학번,과정코드]에 ‘평가’는 완전 종속이 된다.

- 복합키 중 하나인 '과정코드'에 ‘과정명’과 ‘기간’이 부분 종속 되어진다.

그림으로 보자면 ↓



※ 해결 방법 -> 2NF : 부분적 종속 제거


부분적 종속을 제거해준다. 즉 과정코드를 기본키로해서 테이블을 분리 해준다.





●  제 3정규화(3NF)


Primary key가 아닌 일반 column으로 종속되어지는 column 분리.

A -> B, B -> C 그러므로 논리적으로 A -> C. 즉, 이행적 종속 관계를 분리한다.

즉, 후보키가 아닌 애트리뷰트들에서 이행종속이 발생하지 않는다.


예제

제 1정규화 할때 쓴 테이블 가져와 보자. 제 1정규화를 하고 기본키가 하나 이기때문에 제 2정규화 과정은 pass

 

[교육과정테이블] 기본키 : 학번(FK)

학번

자격증

자격증번호

1

정보처리

12345

1

워드1

23456

2

정보처리

12345

3

컴활1

87452

4

SCJP

44444


제3 정규화를 하지 않고 테이블 사용시

● 새로운 자격증이 추가 되어 삽입하려고 할때 이 자격증을 취득하고 있는 사람이 존재 하지 않더라도

   가상으로 취득 한 것처럼 해야만 삽입이 가능하다


● 학번이 2인 사람이 학원을 그만 두게 되어 내용을 삭제하려고 할때 유지되어야 할 데이터까지 삭제됨(정보처리 12345)


● 특정 학생이 자격증을 취득하게 되면 그 자격증에 의하여 자격증 번호가 결정됨 (이를 이행적 함수 종속성)

   즉 기본키가 아닌 속성인 자격증에 의해서 자격증번호가 결정되게 되며 학번으로 자격증번호를 검색 할 수 있다.


학번 -> 자격증, 자격증 -> 자격증번호

∴ 학번 -> 자격증번호


그림으로 보자면 ↓




※ 해결 방법 -> 3NF : 이행적 종속 제거



●  보이스코드 정규화 (BCNF)


BCNF는 제3정규형을 만족하지만, 그 반대는 아니다.

x->y 인 모든 x,y 에 대해 모든 결정자는 후보키여야 한다.


ㅡ> Cycle이 발생하면 BCNF 가 아니다. (이행이랑은 다름)

후보키가 아닌 애트리뷰트가 결정자가 되는 경우 BCNF가 아니다.



요약


정규화

무조건 테이블을 나누는 작업이 아니고 각 단계에서 얻고자 하는 바를 알면 쉽게 해결될 수 있다.


제1 정규화 -> 중복되는 data 분리

 - 저장공간을 최소화하기 위해서

 - N:N 관계를 1:N으로 바꾸기 위해서

 - 수정시 모든 레코드의 data 변경


제 2 정규화(복합키 인 경우만 보면 된다.) -> 부분 종속 분리

 - 원하는 바는 제 1정규화와 동일


제 3 정규화 -> 이행적 종속 관계 분리

 - 삽입이상 제거

 - 삭제이상 제거

[출처] DB 정규화|작성자 샌드

[출처] DB 정규화|작성자 샌드

[출처] DB 정규화|작성자 샌드

[출처] DB 정규화|작성자 샌드



● 출처


http://blog.naver.com/PostView.nhn?blogId=force44&logNo=130100972038


■ 서론


다형성을 구현의 다양함 정도로 설명했고 그 예시로 오버라이딩, 오버로딩을 들었다.

다형성에 대해 좀 더 알아보고자 이렇게 정리한다.



■ 바인딩


보통은 참조변수의 타입과 객체의 타입이 일치하지만,  변수의 타입과 객체의 타입이 다른경우를 볼 수 있다.

예를들면 Map mapping = new HashMap(); 이 있다.


어떤 시점에서, 메소드가 호출될 때 어떤 코드를 수행할 것인지가 결정된다.

이러한 결정을 메소드 호출을 메소드 정의에 바인딩(binding)한다고 한다.


많은 경우에, 메소드 정의에 대한 메소드 호출의 바인딩이 컴파일 시간에 일어날 수 있다. 

그러나 다형 참조의 경우에는 실행 시간까지 바인딩을 할 수 없다.



 정적바인딩(static binding / early binding)

 동적바인딩(dynamic binding / late binding)

 private, final, static 이 이에 해당한다.


컴파일러에 의해 컴파일시간에 결정된다.

컴파일러는 객체의 타입을 알 수 없으므로,

Dog타입으로 먼저 컴파일을 진행한 후, 

실행 중 Pudle타입의 메소드가 호출된다.


런타임 중(실행시간)에 결정된다.


   class Dog {

      void sound(){

         System.out.println("멍멍~~");

      }

   }


   public static void main(String[] args) {

      Dog d = new Dog();

      d.sound();

   }

   class Pudle extends Dog { 

      void sound(){

         System.out.println("푸들~~");

      }

   }


   public class Test {

      Dog d = new Pudle();

      d.sound();

   }

 컴파일 시간에 많은 정보가 결정되므로 실행 효율이 높다.

런타임 중에 자유롭게 결정되므로 유연하다. 




■ 상속에 의한 다형성


Animal creature = new Horse(); 라고 선언하면, 변수 creature는 Animal의 어떤 객체라도 참조할 수 있다.

또한 Animal을 상속받는 어느 클래스의 객체 Horse(예시)도 참조할 수 있다.


클래스의 계층구조의 최상단에는 Object가 있는데, Object는 모든 클래스의 객체를 가르킬 수 있다는 말이된다.


Animal을 상속받은 Horse, Hippo 클래스가 있다고 하자.


Animal creature;


creature = new Horse();

creature.move(); ㅡ 1번


creature = new Hippo();

creature.move(); ㅡ 2번


이때, creature의 타입은 Animal이지만,

1번에서는 Horse의 move()가, 2번에서는 Hippo의 move()가 실행된다.


이렇게 상속에 따른 다형의 객체를 참조할 수 있으며, 

메소드 호출 또한 실행 당시의 참조 객체의 메소드를 선택하여 호출하는 것을 상속에 의한 다형성이라고 한다.




■ 인터페이스에 의한 다형성


인터페이스 역시 클래스와 마찬가지로 변수 타입으로 사용될 수 있다.


  public interface Speaker{

    
      public void speak();
      public void announce(String str);

   }

   Speaker current;

     public class Philosopher implements Speaker{

    
         public void speak(){

           System.out.println("Hello");

       }
         public void announce(String str){

           System.out.println(str);

       }

         public void Listen(){

           System.out.println("I got it");

       }


     }


라는 인터페이스와, 참조변수 current를 가정해보자.

참조변수 current는 Speaker 인터페이스를 구현하는 어떤 클래스의 객체라도 참조할 수 있다.


Philosopher 클래스가 Speaker를 implements 한다면

current = new Pilosopher(); 라고 바인딩 할 수 있다.


여기서 주의할 점은,


인터페이스 참조 변수를 사용하고 있을 때, 그 참조 변수가 가리키고 있는 객체가 

인터페이스에 없는 다른 메소드를  포함하고 있다고 할지라도, 그 인터페이스에 정의되어 있는 메소드만을 호출할 수 있다.


current는 Philosopher 타입의 객체를 바인딩 했지만 Speaker 타입이기 때문에, 

Listen()은 사용할 수 없고, Speaker 인터페이스가 가진 speak(), announce() 메소드를 사용할 수 있다.


특별한 상황에서 Listen() 메소드를 호출이 필요할 경우, 캐스팅을 사용해서 할 수도 있다.

Speaker special = new Philosopher();

((Philosopher)special).Listen();




■ 추천 사이트


예시가 아주 잘 나와있다.


https://opentutorials.org/module/516/6127




■ 출처


http://secretroute.tistory.com/entry/140819

http://blog.daum.net/_blog/BlogTypeView.do?blogid=0LoOX&articleno=6036856&_bloghome_menu=recenttext

http://hyeonstorage.tistory.com/266



'코딩 > Java 프로그래밍' 카테고리의 다른 글

OOP 용어 정리  (0) 2016.12.14
자바 Collections 클래스 Comparator  (0) 2016.11.26
[JAVA] Scanner nextInt()나 next() 사용 후 nextLine 입력  (0) 2016.11.26
자바의 4대 특성  (2) 2016.10.17

■ OSI 7 계층이란


 ISO에서 서로 다른 시스템 간의 통신을 허용하기 위해 OSI 참조모델을 만듬

● OSI 참조모델은 호환성이 있는 네트워크 프로토콜의 개발을 위한 지침 제공

● OSI 참조모델은 네트워크가 제공하는 여러가지 기능을 7개의 계층으로 나누어 식별

● 각 계층은 독특한 기능을 가지며, 전체 모델이 올바르게 작동할 수 있도록 계층 간에 상호 의존





■ 물리 계층


 역할

 ● 시스템간의 물리적인 연결, 혹은 전기 신호의 복원 서비스를 제공한다.

     (데이터 ㅡ> 전자신호로, 전자신호를 ㅡ> 데이터로 변환)

 통신단위

 Bit

 장비

 리피터(물리적 신호를 증폭하여 신호가 감쇠되는것을 방지), 허브




■ 데이터링크 계층


 역할 

 ● 물리적으로 연결되어 있는 호스트끼리 통신을 담당한다.

    (MAC 주소를 연결, 물리적 장치들간의 연결을 담당 ㅡ> 물리회선을 통신채널로 변화)

 ● 흐름제어 : 보내는 측과 받는 측 사이의 속도차를 제어한다.

 ● 에러제어 : 전송오류를 검출하고 수정한다.

 ● 순서제어 : 패킷이나 ACK 신호를 혼동하는 것을 피하기 위해, Sequence Number를 부여.

 통신단위 

 Frame

 프로토콜

 MAC(이더넷, 토큰링), PPP

 주소체계

 MAC

 장비

 스위치,  브릿지(두개의 LAN을 연결해주는 통신망 연결 장치)




■ 네트워크 계층


역할

 ● 헤더에  논리적 주소를 추가

 ● 경로제어(라우팅) : 송신에서부터 수신까지의 패킷의 경로를 제어한다.

통신단위 

 Packet

프로토콜 

 IP(V4/V6), ARP(브로드캐스트 방식으로 IP를 이용하여 MAC주소를 알아냄), RARP(ARP의 반대)

주소체계 

 IP

장비 

 라우터  (LAN:LAN 또는 LAN:WAN을 연결하는 네트워킹 장치)


※ ARP 프로토콜의 사용 예


A컴퓨터가 192.168.0.123 주소로 패킷을 보내려고 할 때, IP주소(논리적:변경가능)는 알고 있지만 MAC주소(물리적:고유)는 모르는 상태다.

그럼 A는 브로드캐스팅(ARP프로토콜)을 통해 192.1368.0.123 누가쓰냐? 라고 물어본다.

B는 어 그거 내가 쓰는데? 라고 응답하게 됩니다. B이외에 C,D...등등은 해당되지 않기 때문에 응답을 하지 않는다.

그럼 A는 B에게 MAC주소좀 알려줘 하게 되고, B의 MAC주소를 받게되고 패킷을 보낼 수 있다.

그 후에는 A는 B의 MAC주소를 ARP 테이블에 추가했기 때문에 (IP와 MAC을 mapping 시켜놓은 table), 패킷을 바로 보낼 수 있다.




■ 전송 계층


역할

 ● 헤더에 포트번호를 추가

 ● 어떤 종류의 네트워크가 사용되었는지를 사용자가 의식하지 않도록 논리적 통신을 지원.

 ● 프로세스와 프로세스(종단간, End-To-End)의 통신을 담당한다.

 ● 데이터가 중복, 유실된 것을 발신자에게 재전송을 요구해 신뢰적인 전송을 보장한다.

통신단위 

 Segment

프로토콜 

 TCP, UDP

주소체계 

 Port

장비 

 게이트웨이




■ 세션 계층


 역할

 ● 응용 프로그램간의 연결과 ,유지와, 연결을 끊는 역할을 담당한다.

 통신단위

 Data




■ 표현 계층


 역할

 ● 서로 다른 데이터 표현방식을 하나의 통일된 형식으로 변환하는 역할

 ● 암호화(Encryption), 압축(Compression), 코드변환(ASCII, Binary, BCDIC)

 통신단위

 Data

 프로토콜

 JPG, MPEG




■ 응용 계층


 역할

 ● 사용자 계층을 말하며, 사용자 인터페이스를 제공한다.

 통신단위

 Data

 프로토콜

 DHCP(동적할당), DNS(도메인), FTP(파일전송), HTTP(웹), POP3(이메일), RIP,

 SMTP(이메일), SSH(원격), TELNET(원격), XMPP




■ 출처


http://mintnlatte.tistory.com

https://ko.wikipedia.org/

http://hahahoho5915.tistory.com/12

함수의 호출 방법에는 Call by value (값에 의한 호출) Call by reference (참조에 의한 호출) 

두 가지의 방식이 있다



우선 Call by value의 이해를 돕기 위한 간단한 그림을 준비했다.



Call by reference (참조에 의한 호출)






 

Call by value (값에 의한 호출)






■ 출처


http://luckyyowu.tistory.com/9


자바의 특징이라고하면 객체지향 프로그래밍이다.

교수님 말씀에 따르면

"집을 지을 때 위에서부터 아래로 지으면 C언어고, 밑에서부터 위로 쌓아 올라가면 자바다" 라는데

이게 무슨말인가 싶다.


좀 더 쉽게 설명하자면, 사람을 비유했을 때 C언어는 모든 신체는 사람의 것인 반면 ,

자바는 눈 따로 코 따로 입 따로 팔 따로 다리 따로 몸통 따로 구현을 한 후에 어울려 사람이 되는 것이다. 



■ 객체지향 4대 특징


추상화(Abstract), 상속(Inheritance), 다형성(Polymorphism), 캡슐화(Encapsulation)




■ 추상화(Abstract)




여기서 빨간색 네모는 추상클래스를 나타내고, 나머지는 일반 클래스는 나타낸다.

여기서 추상클래스와 일반클래스의 차이점은 클래스를 객체화 할 수 있느냐 없느냐의 차이이다.


객체는 상태와 행동을 가지고 있어야 하는데, 여기서 동물과 고양이과와 개과라는 것에 대해

세부화는 할 수 있어도, 상태와 행동을 뚜렷이 정의할 수가 없다.


따라서 추상클래스는 선언만 있고 구현 내용이 없거나, 일부만 구현한 미완성 클래스라고 할 수 있다.

추상메소드가 아닌 메소드를 포함할 수도 있고, 상수가 아닌 데이터 선언도 포함할 수 있다.


추상메소드를 포함하거나, 추상클래스로 선언한 것이 추상클래스다.


사용법은 동물, 고양이과, 개과에서 추상화 한 후에,

사자, 고양이, 호랑이, 늑대, 개, 하마에서 extends(상속, 확장)을 받아 사용할 수 있다.


이때, 추상클래스내에 추상메소드가 있을 경우 상속받는 클래스는 반드시 추상메소드를 구현해야 한다.

그래서 필수적으로 구현해야 할 메소드가 있을 때 추상클래스를 사용한다.



※ 주의할점은 추상클래스를 final이나 static으로 선언할 수 없다. 이는 모순이다.

static은 객체 선언 없이 호출이 될 수 있어야 하며, final은 자식클래스에서 재정의될 수 없기 때문이다.




■ 상속(Inheritance)


상속은 기존의 클래스로 부터 새로운 클래스는 유도하는 과정이다.

쉽게 말해서 부모 클래스를 extends로 상속받아 자식 클래스에서 내 것처럼 사용할 수 있다.


시스템을 설게하다보면, 공통된 부분으로 인하여 중복되는 것들이 계속적으로 나올 수 있다.

이럴 때 상속을 이용하여 비슷한 객체끼리 하나의 묶음으로 묶어주고, 공통된 부분을 뽑아서

상위 개념의 부모클래스를 생성한다.


이 객체들이 부모 객체를 상속하면 중복이 제거되며, 공통된 방식으로 설계 할 수 있다.

또한 상속 받는 과정에서 다형성(오버로딩, 오버라이딩)을 사용하여 자유롭게 변형할 수 있다.



■ 인터페이스(Interface)


자바는 다중상속을 할 수 없는데 이를 보완한 방법이 Interface 다.

Interface는 "무엇을 할 수 있는" 으로 표현이 되는데,

그 예로 Serializable, Cloneable, Comparable, Runnable 이 있다.




위의 관계도를 보면서 인터페이스에 대한 예시를 보자.



동물 클래스

 // 동물.java

package inheritance02;
 
public class 동물{
    String myClass;
    
    동물(){
        myClass = "동물";  
    }
    void showMe(){
        System.out.println(myClass);  
    }
}

 

 인터페이스

 // 날수있는.java

package inheritance02;
 
public interface 날수있는{
    void fly();
}

 // 헤엄칠수있는.java

package inheritance02;
 
public interface 헤엄칠수있는{
    void swim();
}

 동물 클래스를 상속받은 클래스

 // 포유류.java

package inheritance02;
 
public class 포유류 extends 동물{
    포유류(){
        myClass = "포유류";  
    }
}

 // 조류.java

package inheritance02;
 
public class 조류 extends 동물{
    조류(){
        myClass = "조류";
    }
}

 포유류 클래스를

상속받고


인터페이스를

구현한


고래,박쥐

클래스

 // 고래.java

package inheritance02;
 
public class 고래 extends 포유류 
implements 헤엄칠 수 있는{
    고래(){
        myClass = "고래";  
    } 
    
    @Override
    public void swim(){
        System.out.println(myClass + "수영 중 어프!! 어프!!");
    } 
}

 // 박쥐.java

package inheritance02;
 
public class 박쥐 extends 포유류 
implements 날 수 있는{
    박쥐(){
        myClass = "박쥐";  
    } 
    
    @Override
    public void fly(){
        System.out.println(myClass + "날고 있다..슈융");
    } 
}



고래를 예시로 들어보자.


포유류 클래스는 동물 클래스를 상속 받았기 때문에, "myClass"라는 변수와,

"shoMe"라는 함수를 사용할 수 있게 되었다.


고래 클래스는 "포유류"클래스를 상속받고 "헤엄칠 수 있는"을 구현 하였다.

따라서 myClass변수와 showMe함수를 사용할 수 있고, swim이라는 함수를 사용할 수 있다.



■ 인터페이스와 추상클래스의 비교


이렇게 보면 인터페이스와 추상클래스의 용도가 얼추 비슷한 것 같아 보인다.



인터페이스와 추상클래스의 공통점

 abstract class(추상 클래스)와 interface 는 선언만 있고 구현 내용이 없는 클래스이다.


그래서 자기 자신이 new를 해서 객체를 생성할 수 없으며,
추상클래스를 extends 받거나, interface를 implements  자식만이 객체를 생성할 수 있다.
상속받은 자식이 구현을 반드시 하도록 해야할 때 사용한다.


 인터페이스와 추상클래스의 차이점

 인터페이스

 추상클래스

● interface라고 선언


● 구현이 전혀 되어있지 않고, 메소드 선언만 되어있다.


● implement를 통해 다중상속의 효과를 낼 수 있다.

● abstract라고 선언


● 일부는 구현이 되어있을 수도 있다.

(abstract 메소드는 구현X)


● extends를 통해 한 번 밖에 상속받지 못한다.



정리를 하면, 인터페이스는 다형성 즉, 행위의 다양함(메소드)을 구현할 때 사용한다.

추상클래스는 부모의 속성을 자식이 그대로 가져가야할 때 사용한다.




■ 다형성(Polymorphism)


객체지향 개념에서 다형성이란, "여러 가지 형태를 가질 수 있는 능력", "사용편의성"을 말하고

오버라이딩(Overriding), 오버로딩(Overloading)이 있다.


오버라이딩은, 말 그대로 덮어 쓴다는 말이다. 상위 클래스로부터 상속받은 메소드를 재정의해서 사용한다.

오버로딩은, 상위 클래스로부터 상속받은 메서드의 이름은 같으나, 인자의 개수가 달라 중복을 허용한다.


예시를 보자.


// Animal.java
package polymorphism01;
 
public class Animal{
    public String name;
     
    public void showName(){
        System.out.printf("안녕 나는 %s야. 반가워 \n", name); 
    
}
 
// Penguin.java
package polymorphism01;
 
public class Penguin extends Animal{
    public String habitat;
     
    public void showHabitat(){
        System.out.printf("%s는 %s에 살아\n", name, habitat);
    }
     
    // 오버 라이딩 - 재 정의 : 같은 메서드 이름, 같은 인자 리스트
    public void showName(){
        System.out.println("어머 내 이름은 알아서 뭐하게요?"); 
    }
    // 오버 로딩 - 중복 정의 : 같은 메서드 이름, 다른 인자 리스트
    public void showName(String yourName){
        System.out.printf("%s 안녕, 나는 %s라고 해 \n", yourName, name); 
    }

} 



※ 재정의를 해서 사용하게 되면, 오버라이딩한 메소드가 호출 된다.

    만약 상위 클래스의 메소드를 호출하고 싶을 경우에는 super.methodName(); 을 하면 된다.



■ 캡슐화(Encapsulation)

 

관련있는 변수와 메소드를 하나의 클래스로 묶어 주고,

접근 제어 지시자를 사용해 외부로부터 정보를 접근할 수 없게 하는 방법이다.

get,set 메소드를 만들어 정보의 은닉, 유지보수를 할 수 있다.


 

Public - 모두가 접근 가능


Protect - 상속받은 클래스, 같은 패키지 내의 클래스에서 접근 가능


default[기본 값] - 같은 패키지 내의 클래스에서 접근 가능


Private - 본인만 접근 가능





■ 출처


http://hyeonstorage.tistory.com/180

http://itewbm.tistory.com/

http://marobiana.tistory.com/58

http://slenderankle.tistory.com/154



빅 엔디안과 리틀 엔디안은 컴퓨터 메모리에 저장된 바이트들의 순서를 설명하는 용어이다.
컴퓨터에서는 어떤 크기의 데이터를 메모리에 저장할 때 바이트 단위로 나누어 저장하는데,
이러한 방식을 바이트 오더(Byte Order)라고 한다.


[그림] 레지스터와 메모리 위치 매핑관계, 출처 : 위키피디아(www.wikipedia.org)




리틀-엔디안 (Little-Endian)

낮은(시작) 주소에 하위 바이트부터 기록, Intel CPU 계열
예) 32비트형 (4바이트) 값: 0x01020304

하위 주소0x040x030x020x01상위 주소


빅-엔디안 (Big-Endian)

낮은(시작) 주소에 상위 바이트부터 기록, Sparc / RISC CPU 계열
예) 32비트형 (4바이트) 값: 0x01020304

하위 주소0x010x020x030x04상위 주소


※ 0x는 16진수를 나타내는데, 16진수는 각 자리당 0~F(16개)로 표현한다.

각 자리당 16개를 나타낼 수 있으므로 4비트가 필요하다. (2^4=16)

따라서 1byte는 8bit니까 바이트씩 끊어 저장하면 2개씩 저장된다.





리틀-엔디안 (Little-Endian)을 사용하는 이유


빅엔디안은 우리 눈으로 보기 쉽지만,  ALU(산술연산유닛)에서 메모리를 읽는 방식이

메모리 주소가 낮은 쪽 ㅡ> 높은 쪽으로 읽기 때문에 리틀엔디안을 사용하면 산술연산 수행이 더 쉽다.




■ 리틀-엔디안, 빅-엔디안을 맞춰주어야 하는 이유 


네트워크 프로그래밍에서 데이터를 다른 시스템으로 전송할 때

서로 다른 데이터 저장 방식의 시스템 끼리 통신하게 되면 전혀 엉뚱한 값을 주고 받을 수 있기 때문이다.


소켓은 기본적으로 빅엔디안으로 통일되어 있다.



■ 예제



#include <stdio.h>

int main()
{
        int inum = 0x12345678;     ㅡ> 16진수 12345678 저장

        unsigned char *p;          ㅡ> 포인터변수 생성

        p = (unsigned char*)&inum; ㅡ> 변수 inum 의 주소를 p 에 저장


        printf("%08X\n",inum);     ㅡ> inum의 값 12345678 출력

        printf("%p\n",&inum);      ㅡ> inum의 주소 0xbfd256ec 출력



        printf("%p\n",p);          ㅡ> p에 저장된 값(inum의 주소) 0xbfd256ec 출력

        printf("%02X\n",*p);       ㅡ> p에 저장된 값(주소)가 가르키는 값 처음 2자리 78 출력



        ++p;                       ㅡ> p에 저장된 값 (inum의 주소) 증가

        printf("%p\n",p);          ㅡ> 0xbfd256ed

        printf("%02X\n",*p);       ㅡ> 56



        ++p;

        printf("%p\n",p);          ㅡ> 0xbfd256ee

        printf("%02X\n",*p);       ㅡ> 34



        ++p;

        printf("%p\n",p);          ㅡ> 0xbfd256ef

        printf("%02X\n",*p);       ㅡ> 12



        return 0;

} 



예제를 통해 역순으로 출력되는 것을 보아 리틀-엔디안이다.




■ 후기


틀린 것 있으면 수정좀 부탁드립니다.



■ 출처


https://firejune.com

http://forum.falinux.com/

http://andrew0409.tistory.com/105

'전공과목 > Network' 카테고리의 다른 글

동기와 비동기 & 블록킹과 논블록킹 정리  (0) 2016.11.26
OSI 7 Layer [OSI 7 계층]  (0) 2016.10.18

Java Collection Framework (JCF)


Java에서 데이터를 저장하는 기본적인 자료구조들을 한 곳에 모아 관리하고 편하게 사용하기 위해서 제공하는 것을 의미한다.




자바에서 배열 또한 자료구조로 활용할 수 있지만, 배열은 선언할 때 그 크기를 할당해 주어야 하기 떄문에

배열의 크기가 고정되는 제약사항을 가지고 있다. 때문에 데이터양이 고정되어 있지 않은 정보를 다룰 때

다른 자료구조를 적절하게 활용하는 것이 좋다.







■ 각 인터페이스의 특징

인터페이스

구현 클래스 

특징 

List

LinkedList

Stack

Vector

ArrayList

 순서가 있는 데이터의 집합, 데이터의 중복을 허용한다.

Set

HashSet

TreeSet

 순서를 유지하지 않는 데이터의 집합, 데이터의 중복을 허용하지 않는다. 

Map 

 HashMap

TreeMap

HashTable

Properties

 키(key)와 값(value)의 쌍으로 이루어진 데이터의 집합이다.

 순서는 유지되지 않고, 키는 중복을 허용하지 않으며 값의 중복을 허용한다.





■  Collection Interface

모든 콜렉션의 상위 인터페이스로써 콜렉션들이 갖고 있는 핵심 메소드를 선언 (add, contain, isEmpty, remove, size, iterator ...)


  List Interface

Collection 인터페이스를 확장한 자료형으로 요소들의 순서를 저장하여 색인(Index)를 사용하여

특정 위치에 요소를 삽입하거나 접근할 수 있으며 중복요소 허용


  ArrayList

상당히 빠르고 크기를 마음대로 조절할 수 있는 배열

방향 포인터 구조로 자료에 대한 순차적인 접근에 강점이 있음


  Vector

ArrayList의 구형버전이며, 모든 메소드가 동기화 되어있음

잘 사용하지 않음


  LinkedList

양방향 포인터 구조로 데이터의 삽입, 삭제가 빈번할 경우 빠른 성능을 보장

스택, 큐, 양방향 큐 등을 만들기 위한 용도로 사용



  Set Interface

집합을 정의하며 요소의 중복을 허용하지 않음, 상위 메소드만 사용


  HashSet

가장 빠른 임의 접근 속도

순서를 전혀 예측할 수 없음


  LinkedHashSet

추가된 순서, 또는 가장 최근에 접근한 순서대로 접근 가능


  TreeSet

정렬된 순서대로 보관하며 정렬방법을 지정할 수 있음




■  Map Interface

Key와 Value의 쌍으로 연관지어 저장하는 객체


  HashMap

Map 인터페이스를 구현하기 위해 HashTable을 사용한 클래스

중복을 허용하지 않고 순서를 보장하지 않음

키와 값으로 null이 허용


  HashTable

HashMap보다 느리지만 동기화 지원

키와 값으로 null이 허용되지 않음


  TreeMap

이진검색트리의 형태로 키와 값의 쌍으로 이루어진 데이터를 저장

정렬된 순서로 키, 값 쌍을 저장하므로 빠른 검색이 가능

저장시 정렬(오름차순)을 하기 때문에 저장시간이 다소 오래걸림


  LinkedHashMap

기본적으로 HashMap을 상속받아 HashMap과 매우 흡사

Map에 있는 엔트리들의 연결 리스트가 유지되므로 입력한 순서대로 반복 가능




■ 출처


http://hackersstudy.tistory.com/26


#서론
여러 사이트를 돌면서 연동 설명방법도 다 제각각이고,
실패를 통해서 지웠다 설치했다를 반복하면서
내가 가장 좋다고 생각했고, 직접 사용한 방법을 따라하기 쉽게 정리해 본다. 

연동 방법은 다양하게 있는데


보통 검색하면 mod_jk 방법을 많이 사용한다.


mod_jk를 사용하고 싶으면


http://noviceany.tistory.com/37 여기에 들어가서 따라하면 된다.


연동을 하는 이유는 80포트를 아파치가 받아 처리하고, 


jsp처리가 필요할 때 톰캣에게 작업을 넘겨주고 반환받는 방식인데


mod_jk를 사용하니까 완전히 톰캣처리만 가능하게 되버린 것 같다.


내가 부족한 탓도 있겠지만, blog.lael.be에서 친절하게 설명해 준 더 좋은 방법을 찾을 수 있었고


프록시를 사용해 php와 jsp를 한번에 처리할 수 있도록 했다.



크게 3가지로 설정할 수 있는데


1. 사이트의 모든 요청을 Tomcat 이 처리하도록 수정


2. 사이트의 특정 경로만 Tomcat 이 처리하도록 수정


3. PHP, JSP를 동시에 같은 경로에서 사용


중에서 나는 3번을 하기로 했다.


(1번과 2번은 https://blog.lael.be/post/1023 여기에서 읽어보면 된다.)



사전 단계
우분투 14.04 LTS 기준으로 설명
연동하기 위해 아파치와 톰캣을 미리 설치해야 한다.
아파치2 설치 https://blog.lael.be/post/73

톰캣7 설치 https://blog.lael.be/post/858





첫번째 단계


먼저 Apache 프로그램에서 ProxyPass 관련 구문을 해석할 수 있도록 설정


a2enmod proxy



http 로 proxy 할 수 있도록 변경 


a2enmod proxy_http





#두번째 단계


/etc/apache2/sites-available 경로로 들어가 default 이름이 들어간 conf 파일을 열어준다.


아래와 같이 몇 가지만 변경 및 추가해주면 된다.


1. DocumentRoot 의 경로를 실제 톰캣서버의 베이스주소로 설정한다.


(나같은 경우는 /var/lib/tomcat7/webapps/ROOT/ 이다.)



2. 그 아래 ProxyPassMatch ^/(.*\.jsp(/.*)?)$ http://localhost:8080/$1 를 추가해 준다.



3. 그 아래 


 <Directory /var/lib/tomcat7/webapps/ROOT/>

                Options FollowSymLinks MultiViews

                AllowOverride All

                Order allow,deny

                allow from all

                #14.04 rules

                require all granted

        </Directory>



를 추가해 준다.


Directory /var/lib/tomcat7/webapps/ROOT/ 이것도 자신에 맞게 변경해야 한다.




 완성 본 (주석 및 다른코드는 생략)

<VirtualHost *:80>

        DocumentRoot /var/lib/tomcat7/webapps/ROOT/


        ProxyPassMatch ^/(.*\.jsp(/.*)?)$ http://localhost:8080/$1


        <Directory /var/lib/tomcat7/webapps/ROOT/>

                Options FollowSymLinks MultiViews

                AllowOverride All

                Order allow,deny

                allow from all

                #14.04 rules

                require all granted

        </Directory>

</VirtualHost>




아래와 같이 php와 jsp를 톰캣안에 같은 경로에 넣어놓으면 동시에 처리할 수 있다.


스크린샷 2015-03-29 오후 9.19.33 

(이미지 출처 https://blog.lael.be/post/1023)


http://ip/index.jsp 

http://ip/index.php


로 둘다 접근이 가능하다.




#선택 사항


/etc/tomcat7/server.xml 에서



스크린샷 2015-03-29 오후 9.24.03

(이미지 출처 https://blog.lael.be/post/1023)


이렇게 주소를 한정시키면, 서버에서만 8080포트를 접근할 수 있어 보안에 좋단다.


외부에서는 8080로 직접 접근할 수 없고, 80포트를 이용해서 접근하면 아파치가 8080작업으로 넘겨준다.




#마지막 단계


service apache2 restart

service tomcat7 restart


로 변경사항이 적용될 수 있게 아파치와 톰캣서비스를 재시작 해주자.





#결론


https://blog.lael.be 운영하시는분 항상 감사합니다.

모든 출처는 여기에 있습니다. 제가 이렇게 써도 될지 모르겠네요.


+ Recent posts