관리 메뉴

드럼치는 프로그래머

[JAVA] 자바 IO와 NIO의 차이점 본문

★─Programing/☆─JAVA

[JAVA] 자바 IO와 NIO의 차이점

드럼치는한동이 2013. 6. 25. 10:32

스트림을 중심으로 하는 자바에서 기존 입출력(IO)은 블로킹 모드입니다.

Blocking은 자바의 Synchronized 키워드와 같다고 생각하면 이해가 쉽습니다.

즉, 어떤 작업을 하기 위해 먼저 접근한 요청이 다 끝나기 전에는 뒤이어 접급한
 요청들은 먼저 들어온 요청이 다 끝나기를 기다려야 하는 것인데 만약 앞선 요청이
어떤 문제점에 의해 완전히 처리되지 않고 블럭된 상태로 있게 된다면 뒤이은 요청들은
영원히 앞선 요청이 끝나기만을 기다릴 것입니다.
이에 반해 Non-Blocking은 들어온 요청을 바로 처리하는 것인데
앞선 요청이 다 끝나기를 기다리지 않아도 된다는 것입니다.

 

1) Blocking 모드의 단점

보통 IO에서는 서버에 접속해서 accept()를 호출하는 부분에서 블러킹이 발생한다.

만약 어떤 클라이언트가 accept()를 호출하면 뒤이어 이 서버 소켓으로 접속한 클라이언트는
먼저 접속한 클라이언트의 요청이 다 처리되기를 기다려야하고 또한 동시에 여러 클라이언트들의
요청을 처리하기 위해서 별도의 스레드로 Service 클래스를 만들어서 처리하는데,
이것은 사용자가 늘어날 경우 클라이언트 한 명마다 하나의 스레드를 할당해주는 형태가 되므로
스레드 과부하를 가져오게 된다.
 (서버가 느려지는 현상)

 

2) Blocking 모드로 인한 스레드의 과다 생성

스레드는 그 자체적으로도 생성하는데 시간이 걸리는 느린 작업이기도 하고 각각의 쓰레드들이
자신만의 고유한 스택(Stack) 영역과 CPU를 점유해서 사용하기 때문에 많은 스레드를 생성해야하는 
서버는 메모리와 CPU를 효율적으로 사용하지 못하게 되고 클라이언트들의 동시 처리를 위해 생성된
 Service 스레드들이 대부분의 처리 시간을 요청/응답의 블러킹 부분에서 소비한다는 것도 문제점이다.

그리고 결정적으로 하나의 JVM은 몇 백개까지의 스레드를 생성해서 운영할 수 있지만 수 천개의 스레드를 생성할 수는 없다.
 또한 시스템에 따라 그 시점은 다르지만 대개의 경우 특정 개수 이상의 스레드를 생성하면 급격한 성능 저하를 보이기도 하기 때문이다.

 

3) Blocking 모드의 대안으로써의 NIO

NIO에서는 accept()와 클라이언트의 요청/응답에 대해 블러킹이 없다.
이것을 가능하게한 것은 채널(Channel) 인터페이스를 구현하는 SelectableChannel이라는
새로운 클래스를 Non-Blocking으로 설정함으로써 accept()에 대한 블러킹을 피할 수 있도록 했고,
Buffer라는 새로운 클래스의 도입으로 입출력 작업에서 블러킹을 피하고 기존 IO에서의 Stream간의
데이터 복사에 의한 가비지 생성을 예방함으로써 효율적인 버퍼링이 가능해졌다.
 또한 채널과 버퍼(Direct Buffer)는 네이티브 접근을 함으로써 기존의 동기식 서버보다 훨씬 나은 성능을 갖출 수 있다.

 

* 버퍼

버퍼는 위에서 말했듯이 잦은 입출력으로 인한 가비지 콜렉팅을 발생하기 때문에 성능이 떨어지게 되는데
 이에 대한 대안으로 나온 것이 버퍼이다. 기본적으로 일정한 영역에 버퍼의 메모리를 할당하고
미리 할당한 부분에서만 데이터의 입출력을 처리한다.

 

* 채널

기존에 IO방식에서는 버퍼에 접근이 불가능하고 이에 버퍼에 접근하는
입출력 구조가 필요하여 만들어진 것이 바로 채널이다. 버퍼를 입출력하기 위한 구조가 채널이다.

 

* 셀렉터

자신에게 등록한 서버 소켓 채널과 소켓 채널을 위해 대신 통신 선로를 감시하고
 통신 선로에서 각 채널이 등록한 동작이 들어오면 해당 채널에게 알려준다.
 이를 통하여 Non-Blocking 모드를 할 수 있게 되면 Blocking 모드와
Non-Blocking 모드에 대한 설정도 셀렉터에서 한다.

 

[출처] http://darkmirr.egloos.com/1223860

Comments