<aside> 📌 입, 출력(I/O)이란 Input, Output의 약자로 컴퓨터 내부 또는 외부 장치와 프로그램간의 데이터를 주고 받는 것을 말한다.
</aside>
<aside> 🥲 필자가 조사하고 공부하면서 미리 알아두면 좋았을 만한 것을 먼저 적어보려고 한다. 왜냐하면 개념적으로 받아들이는 순서가 너무 안맞아 이것부터 정리하면 좋을 것 같아 보였다. 이유는 역사와 발전과정을 모르니 왜, 뭐가 불편했는지를 모르고 외우게 되었다. 단순하게 동일선에 서있는 기술이라면 차이만 알면 되지만 어쨋건 발전하면서 나온기술이라서 발전과정을 어느정도는 알아야 머리에 정리가 잘되었다. 그리고 설명할때 편하다. “이게 불편하지? 그러니깐 이게 나왔지"와 같이 설명이 된다.
</aside>
<aside> 🥲 우선적으로 스트림을 알기전 IO 와 NIO에 대해서 먼저 알고 넘어가면 좋을 것 같다.
</aside>
<aside> 🥲 자바는 예전부터 느리다라는 주된 평가가 존재했다. 특히 IO에서는 더더욱 느렸다. 이것을 개선하기 위하여 자바는 1.4 버전부터 새로운 입출력(New Input/Output; NIO) 를 선보였다. 또한 7버전부터는 일관성 없는 IO, NIO를 바로 잡기 위하여 클래스를 바로 잡고, 비동기 채널 등의 네트워크 지원에 힘썼다. 그 덕분에 NIO.2 API가 추가되었다. NIO2는 따로 패키지로 제공되는 것이 아니라 java.nio의 하위 패키지 ../channels, ../charset, ../file 등에 통합되어 있다. 필자 입장에서 가장 헷갈렸던 부분은 IO/NIO의 방식이다.
</aside>
| 구분 | IO | NIO |
|---|---|---|
| 입출력 방식 | 스트림 방식 | 채널 방식 |
| 버퍼 방식 | 논 버퍼 | 버퍼 |
| 비동기 방식 | 지원 안 함 | 지원 |
| 블로킹 / 논 블로킹 방식 | 브로킹 방식만 지원 | 블로킹 / 논 블로킹 방식 모두 지원 |
<aside> 🥲 필자의 생각이지만 처음부터 스트림만 배우고 버퍼, 채널 이러한 순서로 공부를 하니 상위 개념을 몰라서 조금 어려운 길로 돌아갔다. 지금 생각해보면 IO/NIO의 차이인데 말이다.
</aside>
<aside> 📌 IO는 스트림 기반이다. 스트림은 입력 스트림 출력 스트림으로 구분되어 있다. 그래서 단방향으로만 데이터를 보낼 수 있다(그에 따라 두 가지의 스트림을 생성해야한다). NIO는 채널 기반이다. 채널은 스트림과 달리 양방향으로 입력과 출력이 가능하다. 그렇기 때문에 입력과 출력을 위한 별도의 채널을 만들 필요 없이 하나의 채널만 존재해도 된다.
</aside>
<aside> 📌 IO에서는 출력 스트림이 1바이트를 쓰면 입력 스트림이 1바이트를 읽는다. 즉시 1을 넣으면 1만 가져간다. 하지만 버퍼에서는 복수 개의 바이트를 한꺼번에 입력 받고 한번에 꺼낸다. 즉 n바이트를 읽는다고 생각하면 좋다. 그래서 스트림을 쌩으로 사용하는 것 보다는 스트림과 버퍼를 조합하여 사용하는 것이 좋다(IO는 버퍼를 제공해주는 보조 스트림인 BufferedInputStream, BufferedOutputStream을 연결해서 사용한다.). 하지만 NIO는 기본적으로 버퍼를 사용해서 입출력을 한다. 즉, 보조적인 역할을 하는 버퍼를 쓸 필요가 없다.
</aside>
<aside> 📌 IO는 블로킹된다. 즉, 입력 도중엔 출력이 안되고 출력 도중엔 입력이 안된다. NIO는 블로킹, 논 블로킹의 특징을 모두 가진다. NIO의 경우 스레드를 인터럽트 함으로써 빠져나올 수 있다. 논 블로킹에서는 입출력 작업 준비가 완료된 채널을 선택해서 작업 스레드가 처리하기 때문에 작업 스레드가 블로킹 되지 않는다. 이 방법의 핵심은 멀티플렉서인 Selector 때문이다. 간단히 Selector는 복수 개의 채널 중에서 이벤트가 준비 완료된 채널을 선택하는 방법을 제공해준다.
</aside>
‣ 이전 공부 내용 첨부
<aside> 🥲 이제 위의 표가 이해가 좀 되지 않는가? 여기서 중요한 핵심은 스트림 vs 채널이 아니다. IO에서 new IO(NIO)로 어떻게 발전해왔는지 이다.
이제 자세하게 알아보자.
</aside>