์๋ฐ์ NIO (java.nio)
by JiwonDevJDK4์์ ๋์ค๊ณ JDK7์์ java.nio2๋ก ์ ๋ฐ์ดํธ ํ์๋ค.
NIO์ ์๋ฏธ๋ ๋น๋๊ธฐ-๋ ผ๋ธ๋กํน ๋ฐฉ์์ ์๋ก์ด ์ ์ถ๋ ฅ์ด๋ผ๋ ์๋ฏธ์ด๋ค. (Non-blocking) New Input/Output
๊ณต์๋ฌธ์์๋ NIO๋ฅผ New I/O๋ผ๊ณ ์๊ฐํ๋๋ฐ, ๊ทธ ์ด์ ๋ ๋ด๋ถ์ ๋ชจ๋ I/O๊ฐ ๋ ผ๋ธ๋กํน์ผ๋ก ๋์ํ๋๊ฑด ์๋๊ธฐ ๋๋ฌธ์ด๋ค.
๐ ์คํ๋ง์์ ์ ๊ณตํ๋ Webflux์ Netty ์๋ฒ๋ ์๋ฐ์ NIO ๊ธฐ๋ฐ์ผ๋ก ๋ง๋ค์ด์ ธ์๋ค.
๐ ์งง๋งํ ์๋ฐ ์ญ์ฌ ์ด์ผ๊ธฐ
์๋ฐ์ ๋น๋๊ธฐ์ฒ๋ฆฌ - Thread ๊ฐ์ฒด๋, ๊ฑฐ์ ์ด์ฐฝ๊ธฐ ๋ฒ์ ๋ถํฐ ์ง์ํ๋ ๊ธฐ๋ฅ์ด์๋ค. (๋ฌผ๋ก ๊ทธ ๋น์์๋ ์ต์ ํ๊ฐ ๊ตฌ๋ ธ์ง๋ง)
๋ค๋ง ์น์ฑ์๋ฒ์ธ ํฐ์บฃ(WAS)์ ๊ฒฐ๊ตญ ์๋ธ๋ฆฟ์ผ๋ก ๋์ํ๋ค. ๊ทธ๋์ ๊ณผ๊ฑฐ์๋ ๋ฉํฐ์ค๋ ๋๊ฐ์๊ฑฐ ์ง์ ์ํ๋ค.
์๋ํ๋ฉด ์๋ฐ์ ์๋ธ๋ฆฟ์ [์๋ ํ๊ฐ์ ์์ฒญ = ํ ์ค๋ ๋ = ํ ๊ฐ์ ์๋ธ๋ฆฟ] ์ฒ๋ฆฌ๋ง ๊ฐ๋ฅํ๊ฒ ์ค๊ณ๋์๊ธฐ ๋๋ฌธ์ด๋ค.
ํ์ง๋ง ์น ์๋ฒ์์ ์ฐ๊ฒฐ์ ์ ์งํ ์ฑ, ์ง์์ ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ๋ฐ์ ๋ ์๋๊ฐ ๋๋ฌด ๋๋ฆฌ๋ค๋ ๋จ์ ์ด ์์๋ค.
๊ทธ๋์ 2009๋ 1์, ์๋ธ๋ฆฟ 3.0 ์คํ์์๋ถํฐ ์๋ต์ ๋น๋๊ธฐ๋ก ์น๋ฆฌ๊ฐ๋ฅํ๊ฒ ๋ฐ๋์๋ค. (์ด๋ ์คํ๋งMVC 3.2๋ถํฐ ์ง์)
์ด์ ์๋ธ๋ฆฟ์ ์คํํ ์ค๋ ๋๊ฐ ์์ด์ง๋๋ผ๋, ๋ณ๋์ ์ค๋ ๋๋ฅผ ํตํด ์๋ต์ ๋์ค์ ๋ฐํํ ์ ์๋ค.
์ด๋ JDK1.5์ ์ถ๊ฐ๋ Callable ๋ฑ์ ์ฌ์ฉํด์ ๊ตฌํ๋์๋ค. NIO ์๋๋ค.
์ฆ, ์๋์ ๊ฐ์ด ํ ์๋ธ๋ฆฟ์์ ์ฌ๋ฌ ๊ฐ์ ๋ฉํฐ์ค๋ ๋๋ฅผ ๋๋ฆด ์ ์๊ฒ ๋ฐ๋์๋ค.
@Slf4j
@WebServlet(urlPatterns = "/hello", asyncSupported = true)
public class AsyncHelloWorldServlet extends HttpServlet {
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
// ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ์ํ AsyncContext ๊ฐ์ฒด
final AsyncContext asyncContext = req.startAsync();
var thread_T2 = new Thread(() -> {
var response = (HttpServletResponse) asyncContext.getResponse();
response.setContentType("text/plain");
response.setCharacterEncoding("UTF-8");
try {
response.getWriter().println("HELLO");
} catch (IOException e) {...}
logger.info("complete response");
asyncContext.complete(); // complete() ๋ฉ์๋๋ฅผ ํตํด ์ค๋ ๋๋ฅผ ์ข
๋ฃ์ํด
});
thread_T2.start(); // 1๋ฒ ์ค๋ ๋ ์ถ๋ฐ
}
}
์์ ๊ฐ์ด ์์ฑํ๋ฉด, ์๋ธ๋ฆฟ์ ์ด๋ ๊ฒ ๋์ํ๋ค.
- ์ ์ผ ์์ ์๋ T1(ํด๋ผ์ด์ธํธ ์์ฒญ์ ๋ฐ์ ์ค๋ ๋)๋ ์๋ธ๋ฆฟ์ doGet()์ ์คํํ๋ค.
- T1์ ์๋ธ๋ฆฟ์ doGet() ๋ฉ์๋์์ AsyncContext ๊ฐ์ฒด๋ฅผ ๋ง๋ ๋ค.
- T1์ AsyncContext๋ฅผ ์ด์ฉํด์ ๋น๋๊ธฐ๋ก ์ฒ๋ฆฌํ ์๋ก์ด ์ค๋ ๋(T2)๋ฅผ ์์ฑํ๊ณ , ์์ํ๋ค.
- T1์ ์๊ธฐ ํ ์ผ์ด ๋ค ๋๋ฌ๊ธฐ ๋๋ฌธ์ ํ์์ฒ๋ผ ์๋ธ๋ฆฟ ๊ฐ์ฒด๋ฅผ ๋ฐํํ๊ณ , ์ค๋ ๋๋ฅผ ์ข ๋ฃํ๋ค.
- (ํ์ฌ T1์ ์์ด์ง ์ํฉ) T2๋ ๋ณ๋์ ์ค๋ ๋์์ ์๊ธฐ ํ ์ผ์ ํ๋ค.
์ด๋ ํ์ํ request, response๋ AsyncContext ์์ ๋ฐ์์ฌ ์ ์๋ค. - (ํ์ฌ T1์ ์์ด์ง ์ํฉ) T2 ์ค๋ ๋๋ AsyncContext๋ฅผ ์ด์ฉํด ํด๋ผ์ด์ธํธ์ ์๋ต์ ์ ์กํ๋ค.
- T2์ค๋ ๋๋ ํ ์ผ์ ๋ง์น๊ณ , AsyncContext.complete()๋ฅผ ํตํด ์คํ์ ์ข ๋ฃํ๊ณ ์ค๋ ๋๋ฅผ ๋ฐ๋ฉํ๋ค.
๐ค ๋น๋๊ธฐ๋ ์๊ฒ ๋๋ฐ, ๊ทธ๋ผ Tomcat์ ์์ง๋ nio, nio2๋ฅผ ์ฌ์ฉํ์ง ์๋๊ฑด๊ฐ์?
ํฐ์บฃ7(์๋ธ๋ฆฟ3.0)์์ ๋น๋๊ธฐ ๊ธฐ๋ฅ์ด ์ถ๊ฐ๋๋ฉฐ, ๋
ผ๋ธ๋กํน IO HTTP ์๋ธ๋ฆฟ ์ปค๋ฅํฐ๋ ํจ๊ป ์ถ๊ฐ๋์๋ค.
๋น์ฐํ๊ฑฐ์ง๋ง ํฐ์บฃ์์ NIO๋ฅผ ์ฌ์ฉํ๋ค๊ณ [DB I/O๋ ํ์ผ์ฒ๋ฆฌ]๊ฐ ์๋์ผ๋ก ๋
ผ๋ธ๋กํนํ๊ฒ ๋์ํ์ง๋ ์๋๋ค.
ํฐ์บฃ์ ์๋ธ๋ฆฟ์ ์ฒ๋ฆฌํ๋ '์น ์๋ฒ'์ด๊ณ , ๋ณ๋ ฌ์ฒ๋ฆฌ๋ ๊ฐ๋ฐ์๊ฐ ์ง์ ๋น๋๊ธฐ-๋ ผ๋ธ๋กํน ์ฝ๋๋ฅผ ์์ฑํ๋ ๊ฑฐ๋ค.
// Tomcat์ ${Tomcat_HOME}/conf/server.xml ์ค์
protocol="HTTP/1.1" // ๊ธฐ๋ณธ๊ฐ, ๋ธ๋กํน IO
protocol="org.apache.coyote.http11.Http11NioProtocol" // NIO๋ก ๋ณ๊ฒฝํ ์ ์๋ค.
(์ค์ ๋ก ์คํ๋ง๋ถํธ์ ๋ด์ฅ ํฐ์บฃ์ ์คํํ๋ฉด ๊ธฐ๋ณธ๊ฐ์ธ Http11NioProtocol ์ ์ฌ์ฉํ๋ ๊ฒ์ ํ์ธํ ์ ์๋ค.)
๐ค ๊ทธ๋ผ Netty๋ Tomcat๊ณผ ๋ญ๊ฐ ๋ค๋ฅด๊ธธ๋ ๋น๋๊ธฐ-๋ ผ๋ธ๋กํน์ ๊ทธ๋ ๊ฒ ๊ฐ์กฐํ๋์?
ํฐ์บฃ์ [Nio Http ์ปค๋ฅํฐ] ๊ธฐ๋ฅ์ ์ง์ํด์ฃผ๋๊ฑฐ๊ณ , Netty๋ ๊ธฐ๋ณธ ์ค๊ณ๋ถํฐ๊ฐ ๋ค๋ฅด๋ค.
- Netty๋ ์๋ธ๋ฆฟ ์คํ์ ์ฌ์ฉํ์ง ์๋๋ค. [์์ํ ์๋ฐ nio + ํจ์ํ]์ผ๋ก ์น ์์ฒญ์ ๋ฆฌ์กํฐ๋ธํ๊ฒ ๋ค๋ฃฌ๋ค.
- Netty๋ ๋ด๋ถ์ ์ผ๋ก 1๊ฐ์ ์ด๋ฒคํธ๋ฅผ ๋ฐ๋ ์ค๋ ๋์, ๋ค์์ worker๋ฅผ ๊ฐ์ง๋ค.
๋ณดํต ์ด๋ฒคํธ๋ฅผ ์ฒ๋ฆฌํ๋ ๋ฐฉ์์ ๋ฐ๋ผ, [์ฝ๋ฐฑ ํจํด]๊ณผ [Future ํจํด]์ผ๋ก ๋๋๋๋ฐ Netty๋ ๋ ๋ค ์ง์ํ๋ค.
- [์ด๋ฒคํธ ๋ฃจํ ์ฒ๋ฆฌ]๋ฅผ ๋๊ธฐ์ ์ธ-์ฑ๊ธ์ค๋ ๋๋ก ํ ์๋์๊ณ , ๋น๋๊ธฐ-๋ฉํฐ์ค๋ ๋๋ก ํ ์๋ ์๋ค. ์ฅ๋จ์ ์ด ์กด์ฌํ๋ค.
๋ ์์ธํ ๋ด์ฉ์ ์คํ๋ง5 Webflux๋ ๋ฆฌ์กํฐ๋ธ ํ๋ก๊ทธ๋๋ฐ (RxJava)๋ฅผ ์ฐพ์๋ณด๋ฉด ์๋ฃ๊ฐ ๋ง์ผ๋, ๊ถ๊ธํ๋ฉด ์ฐพ์๋ณด์.
๐ญ ๊ธฐ์กด์ Java I/O์ ๋ค๋ฅธ์
Blocking I/O๋ ๋ฐ์ดํฐ๊ฐ ๊ฐ๋ฌผ์ด ํ๋ฅด๋ฏ ์คํธ๋ฆผ์ผ๋ก ์ ์ก๋๋ค๊ณ ๊ฐ์ ํ๋ ๋ฐฉ์์ด๊ธฐ ๋๋ฌธ์ ์ดํดํ๊ธฐ๋ ์ฌ์ฐ๋ ์ค์ ๋คํธ์ํฌ์์ ๋ฐ์ดํฐ์ ์ก ๋ฐฉ์์ ์ด์ ๋ค๋ฆ ๋๋ค. Non-blocking I/O ๋ ์ค์ ๋คํธ์ํฌ์์ ๋ฐ์ดํฐ ์ ์ก์ด ์ด๋ฃจ์ด์ง๋ ๋ฐฉ์๊ณผ ์ ์ฌํ๊ฒ ๊ตฌํ๋๋ I/O ๋ฐฉ์์ ๋๋ค.
๊ธฐ์กด์ ์ ์ถ๋ ฅ์ ์ด์์ฒด์ I/O ์์ฒญ์ ์ํ [์ ๋ ฅ์คํธ๋ฆผ, ์ถ๋ ฅ ์คํธ๋ฆผ] ๊ฐ์ฒด๋ก ๊ตฌ๋ถ๋์ด์์๋ค.
์๋ฅผ ๋ค์ด ๋ฐ์ดํฐ๋ฅผ ์ฝ๊ธฐ ์ํด์๋ InputStream ๊ฐ์ฒด๋ฅผ, ์ฐ๊ธฐ์ํด์๋ OutputStream ๊ฐ์ฒด๋ฅผ ์์ฑํด์ผ ํ์๋ค.
๋ํ ๋ฒํผ๋ฅผ ๋ด๋ถ์์ ์ ๊ณตํด์ฃผ์ง ์๊ธฐ๋๋ฌธ์, Buffered ๊ฐ์ฒด๋ฅผ ์ด์ฉํด์ ์ง์ ๋ฒํผ๋ง ์์
์ ํด์ฃผ์ด์ผํ๋ค.
NIO์์๋ ์คํธ๋ฆผ ๋์ , [Channel] ๊ฐ์ฒด๋ฅผ ์ ๊ณตํด์ค๋ค. ํ ์ฑ๋์ ์ด์ฉํด์ ์๋ฐฉํฅ I/O ํต์ ์ด ๊ฐ๋ฅํ๋ค.
๋ํ ์ฑ๋์ ์ฝ์ ๋ฐ์ดํฐ๋ฅผ ๋ฌด์กฐ๊ฑด ๋ด๋ถ์ ๋ฒํผ์ ์ ์ฅํ๋ค. ์ฌ์ฉ์๋ ๋ฒํผ์์ ํ์ํ ๋ถ๋ถ๋ง์ ์ฝ๊ณ ์ฌ์ฉํ ์ ์๋ค.
Non-blocking I/O์์๋ ์คํธ๋ฆผ๋์ , ์ ์กํ ๋ฉ์์ง๋ฅผ buffer์ ๋ด์์ ์ ๋ฌํ๋ฉฐ, ์์ ์ธก(์๋ฒ)์์๋ ๋คํธ์ํฌ ์์ ์ด๋ฒคํธ๋ฅผ ๊ฐ์งํ ์ ์๋ ์ ๋ ํฐ (์ผ์ข ์ ๋ฆฌ์ค๋)๋ฅผ ์์ฑํ์ฌ ์ด๋ฒคํธ๋ฅผ ๋๊ธฐํ๋ค๊ฐ ์ด๋ฒคํธ ๋ฐ์์์ ์ ์๋ง์ ๋ฐฉ์์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํฉ๋๋ค. ๋ํ, ์์คํ ์ฝ(System call) ์ธก๋ฉด์์ ๋ณธ๋ค๋ฉด, Direct Buffer๋ ํ๋์จ์ด์์ ๋ฐ์ดํฐ์ ๋ํ์ฌ ๋ค์ดํฐ๋ธ ์ ๊ทผ์ด ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ์ ์ปค๋์์์ user์์ญ์ผ๋ก์ ๋ฐ์ดํฐ ๋ณต์ฌ๋จ๊ณ๋ฅผ ์ค์ฌ ์ฑ๋ฅ๋ฉด์์ ๋ฐ์ด๋ฉ๋๋ค.
๋ค์๋งํด, Non-blocking I/O๋, ํ๋์ ์ค๋ ๋๊ฐ ๋์์ ๋ง์ ์ฑ๋์ ๊ด๋ฆฌํ ์ ์๋ I/O ๋ฐฉ์์ผ๋ก, ์ผ๋ฐ์ ์ผ๋ก ์ ๋ ํฐ๋ฅผ ์ด์ฉํ์ฌ ๋คํธ์ํฌ์์ ์ด๋ฒคํธ๋ฅผ ๊ฐ์งํ์ฌ ์ฒ๋ฆฌํ๋ ๋ฐฉ์์ ์ฌ์ฉํฉ๋๋ค. ์ด ๋ฐฉ์์ accept์ ๋ํblocking์ ํผํ ์ ์๋ ์ฅ์ ์ด ์์ต๋๋ค.
์ด๋ ๊ฒ ์ฑ๋์ ์ ๊ณตํ๋ ์ด์ ๋, ๋ธ๋กํน๊ณผ ๋ ผ๋ธ๋กํน I/O๋ฅผ ๋ ๋ค ์ ๊ณตํ๊ธฐ ์ํจ์ด๋ค.
๊ธฐ์กด์ ์๋ฐ๋ ๋ธ๋กํน I/O๋ง ๊ฐ๋ฅํ์๋ค. ๊ทธ๋์ ๋ฉํฐ์ค๋ ๋ ์ํฉ์์ I/O ๋๋ฌธ์ ์ค๋ ๋๊ฐ ๋ฉ์ถ๋ ์ผ์ด ๋ง์๋ค.
์ด์์ฒด์ ์ I/O์์ฒญ์ ํ ๊ฐ์ด ๋ฐํ๋์ด์ผ ๋ค์ ์์
์ ์์ํ ์ ์๊ธฐ๋๋ฌธ์, ๊ทธ ๋์ ์ค๋ ๋๋ ๋๊ณ ์๋๊ฑฐ๋ค.
๋
ผ๋ธ๋กํน์ Return๋์ง ์์์์๋ ๋ค์ ์์
์ ์์ํ๋ ๊ฒ์ ์๋ฏธํ๋ค. (์ ์ด๊ถ์ ๊ฐ์ง๊ณ ์์ง ์๊ณ ๋ฐ๋ก ๋ฐํํ๋ค.)
BIO์ NIO์ ์ค์ ์๋ฐ ์ฝ๋ ์ดํด๋ณด๊ธฐ (์ฐธ๊ณ ๋ก nio์ Selector๋ ๋ฉํฐํ๋ ์ฑ select์ ๋์์ด ๋น์ทํ๋ค)
BIO๋ ๊ฐ๋จํ๋ค. ๊ทธ๋ฅ ๊ธฐ์กด์ ์๋ฐ I/O ๊ฐ์ฒด๋ฅผ ์ด์ฉํ๋ฉด ๊ทธ๊ฒ BIO๋ค.
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;</code>
public class BioTest {
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(8000);
Socket socket = serverSocket.accept();
InputStream in = socket.getInputStream();
int oneInt = -1;
while((oneInt = in.read()) != -1){
System.out.print((char)oneInt);
}
in.close();
}
}
NIO๋ ์ฑ๋๊ฐ์ฒด๋ฅผ ์ด์ฉํด์ ์๋์ ๊ฐ์ด ์ฌ์ฉํ๋ค.
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
public class NioWithSelectorTest {
static ServerSocketChannel serverSocketChannel = null;
static Selector selector = null;
public static void main(String[] args) throws IOException, InterruptedException {
// Selector(์ผ์ข
์ ๋ฆฌ์ค๋) ์ด๊ธฐ
selector = Selector.open();
// ์์ผ ์ด๊ธฐ
serverSocketChannel = ServerSocketChannel.open();
// ์์ผ ์ฑ๋์ non-blocking ์ค์
serverSocketChannel.socket().bind(new InetSocketAddress(8000));
serverSocketChannel.configureBlocking(false); // Blocking false
// Blocking ์ํํ์ธ
System.out.println("Blocking ์ํํ์ธ :::: " + serverSocketChannel.isBlocking());
// Selector๋ฅผ ์ด์ฉํ์ฌ ๊ฐ์งํ ์ด๋ฒคํธ ๋ฑ๋ก
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
while(true){
System.out.println("connecting...");
// ์ค๋น๋ ์ด๋ฒคํธ๊ฐ ์๋์ง ์ฒดํฌ. ์ด๋ฒคํธ๋ง๋ค ๋ค๋ฅธ ์ซ์ ๋ฐํ์ด ์์๋๊น์ง blocking
selector.select();
// ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ์์ ๋, ์
๋ ํฐ์ SelectSet์ ์ค๋น๋ ์ด๋ฒคํธ๋ฅผ ํ๋์ฉ ์ฒ๋ฆฌํจ.
Iterator<SelectionKey> iterator = selector.selectedKeys().iterator();
while(iterator.hasNext()){
SelectionKey selectionKey = iterator.next();
// Selection Key ์ ๋ฐ๋ผ ๋ถ๊ธฐ
if(selectionKey.isAcceptable()){
// ์๋ฒ ์์ผ ์ฑ๋์ ํด๋ผ์ด์ธํธ๊ฐ ์ ์์๋
accept(selectionKey);
}else if(selectionKey.isReadable()){
// ์ด๋ฏธ ์ฐ๊ฒฐ๋ ํด๋ผ์ด์ธํธ๊ฐ ๋ฉ์์ง๋ฅผ ๋ณด๋ด๋ ๊ฒฝ์ฐ
read(selectionKey);
}else{
System.out.println("๊ทธ์ธ์ ์
๋ ์
ํค : " + iterator.next());
}
// ์ฒ๋ฆฌ๋ ์ด๋ฒคํธ๋ ์ ๊ฑฐ
iterator.remove();
}
}
}
/**
* ํด๋ผ์ด์ธํธ๊ฐ ์ ์๋์์ ๋ ์คํ๋๋ ๋ฉ์๋
* @param selectionKey
* @throws IOException
*/
private static void accept(SelectionKey selectionKey) throws IOException{
// ๋ฐ์๋ค์ธ ์ฑ๋๋ก ์๋ฒ์์ผ์ฑ๋ ์์ฑ
ServerSocketChannel server = (ServerSocketChannel)selectionKey.channel();
// ๋ฐ์๋ค์ธ ์๋ฒ์์ผ์ฑ๋๋ก ์์ผ์ฑ๋ ์์ฑ
SocketChannel sc = server.accept();
sc.configureBlocking(false); // non-blocking
// ์ ์๋ ํ์๋ ์ฝ๊ธฐ๋ชจ๋๋ก ๋ณ๊ฒฝ
sc.register(selector, SelectionKey.OP_READ);
System.out.println(sc.toString() + " ์ ์๋์์ต๋๋ค.");
}
/**
* Read ๋ ํฌ๊ธฐ๋ฅผ ์๋ ค์ค.
* @param selectionKey
*/
private static void read(SelectionKey selectionKey){
// SelectionKey ๋ก๋ถํฐ ์์ผ ์ฑ๋์ ์ป์ด์ด
SocketChannel sc = (SocketChannel)selectionKey.channel();
// ByteBuffer ์์ฑํจ
ByteBuffer buffer = ByteBuffer.allocateDirect(1024);
try {
// ์์ฒญํ ํด๋ผ์ด์ธํธ์ ์์ผ ์ฑ๋๋ก ๋ถํฐ ๋ฐ์ดํฐ๋ฅผ ์ฝ์ด๋ค์.
int read = sc.read(buffer);
System.out.println(read + " byte๋ฅผ ์ฝ์์ต๋๋ค.");
} catch (IOException e) {
try {
sc.close();
} catch (IOException e2) {
}
}
// buffer ๋ฉ๋ชจ๋ฆฌ ํด์
clearBuffer(buffer);
}
/**
* buffer์ ๋ด์ฉ์ ํด๋ฆฌ์ดํจ.
* @param buffer
*/
private static void clearBuffer(ByteBuffer buffer){
if(buffer != null){
buffer.clear();
buffer = null;
}
}
}
ํน์๋ํด์ ํ๋ฒ ๋ ํ๋ ๋ง์ด์ง๋ง, ๋๊ธฐ/๋น๋๊ธฐ๋ NIO์ ๊ด๋ จ์ด ์๋ค.
์๋ฐ์ ๋น๋๊ธฐ์ฒ๋ฆฌ๋ ์๋ ๋ถํฐ Thread ๊ฐ์ฒด๋ฅผ ์ด์ฉํด์ ์ง์ํ๋ ๊ธฐ๋ฅ์ด์๋ค.
//โจ JDK1.5์ ์ถ๊ฐ๋ java.util.concurrent.Executors๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ โจ//
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
// ์์
1 (์ค๋ ๋)
executorService.submit(() -> {
log("์์
1 ์์");
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
log("์์
1 ์ข
๋ฃ");
});
// ์์
2
log("์์
2 ์์");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
log("์์
2 ์ข
๋ฃ");
executorService.shutdown();
}
๐ญ ๊ทธ๋ผ NIO๊ฐ ๋ฌด์กฐ๊ฑด ์ข๊ฒ ๋ค์?
NIO๋ ๋น๋๊ธฐ์ ์ธ ์์ ์ด ๋ง์ [๋ถํน์ ๋ค์์ ํด๋ผ์ด์ธํธ ์ฐ๊ฒฐ, ์ฌ๋ฌ ํ์ผ I/O๋ฅผ ๋์]์ ์ฒ๋ฆฌํด์ผ ํ ๋ ์ข๋ค.
I/O ์์
๋์ ์ค๋ ๋๋ฅผ ๋๊ฒํ์ง์๊ณ , ๋ค๋ฅธ๊ฑธ ์ํฌ ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
= ์ค๋ ๋๋ฅผ ๋ ๋ง๋คํ์์์ด, ํ ์ค๋ ๋๋ฅผ ํจ๊ณผ์ ์ผ๋ก ๊ฐ๊ตด ์ ์๊ธฐ ๋๋ฌธ์ด๋ค.
์ด์์ฒด์ ์ ์ฅ์์ ๊ณผ๋ํ ์ค๋ ๋ ์์ฑ์ ํผํ๊ณ , ๋ด๋ถ ๋ฒํผ๋ฅผ ์ด์ฉํ ์ ์ถ๋ ฅ์ผ๋ก ์ฑ๋ฅํฅ์์ด ๊ฐ๋ฅํ๋ค.
ํ์ง๋ง ์ฌ๊ธฐ์๋ ํจ์ ์ด์๋๋ฐ, '๋น๋๊ธฐ์ ์ผ๋ก ์ฒ๋ฆฌํ ์ ์๋ ์์ '์์๋ง ์ค๋ ๋๊ฐ ๋ค๋ฅธ์ผ์ ํ ์ ์๋ค๋ ์ ์ด๋ค.
์๋ฅผ ๋ค์ด, [ ์ด๋ฏธ์ง ๋ก๋ฉ -> ๊ณ์ฐ ๋ก์ง -> ๋ฌธ์API ๋ฐ์ก] ๊ฐ์ ์์ ์์๋ ๋ ผ๋ธ๋กํน์ด ๋งค์ฐ ์ข๋ค.
- ๋ธ๋กํน์ ์ด๋ฏธ์ง ๋ก๋ฉ I/O๊ฐ ๋ฐํ๋๊ธฐ๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ฉด์ ์ค๋ ๋๊ฐ ๋ค๋ฅธ์์ ์ ๋ชปํ๋ค. ๊ทธ๋ฅ ๋๊ณ ์๋ค.
- ๋ ผ๋ธ๋กํน์ ์ด๋ฏธ์ง ๋ก๋ฉ์ ์ฑ๊ณต์ฌ๋ถ์ ์๊ด์์ด ๋ค์ ์์ (๊ณ์ฐ๋ก์ง, ๋ฌธ์API๋ฐ์ก)์ ๋ฐ๋ก ์งํํ ์ ์๋ค.
ํ์ง๋ง ์๋์ ๊ฐ์ ๊ณ์ฐ ๋ก์ง์ด๋ผ๋ฉด ์ด๋จ๊น?
[ ํ์ฌ GPS ์ขํ๊ฐ ์์ฒญ -> ์ขํ๊ฐ์ผ๋ก ์ต๋จ๊ฑฐ๋ฆฌ ๊ณ์ฐ -> ์ต์ ์ ์ง๋ฆ๊ธธ ์ถ์ฒ ]
๋ ผ๋ธ๋กํน์ผ๋ก ์ฌ์ฉํ๋ค๊ณ ํ๋ค, ์ขํ๊ฐ I/O๊ฐ ๋ฐํ๋์ง ์์ผ๋ฉด ๋ค์์์ ์ ์งํํ ์ ์๋ค.
๋๊ธฐ์ ์ธ ์์ ์์๋ ์คํ๋ ค ๋ ผ-๋ธ๋กํน ๋๋ฌธ์ ์๊ธฐ๋ ์ถ๊ฐ๋์๋๋ฌธ์, ์ค๋ฒํค๋๋ง ๋ฐ์ํด์ ๋ ๋๋ ค์ง ๋ฟ์ด๋ค.
๊ธฐ์ตํ์, ๋ณ๋ ฌ์ฒ๋ฆฌ๋ ๋ฐ์ํ๋ ์์ธ์ํฉ๋ค์ ๊ด๋ฆฌํ๊ธฐ ์ ๋ง ์ด๋ ต๋ค. ์ถ๊ฐ์ ์ธ ๋ง์ ์์ ์ด ํ์ํ๋ค.
๊ฐ์ ๋งฅ๋ฝ์ผ๋ก ์์ฒญ ํฐ ๋์ฉ๋์ ๋ฐ์ดํฐ๋ฅผ ์ฒ๋ฆฌํ ๋์๋, ๊ตณ์ด ๋ ผ๋ธ๋กํน์ผ๋ก ํ๊ธฐ๋ณด๋จ ์ค๋ ๋๋ฅผ ๊ฐ์๋ฅผ ๋๋ ค์ ๋ธ๋กํน์ผ๋ก ์ฒ๋ฆฌํ๋๊ฒ ๋ ๋น ๋ฅผ ๊ฒ์ด๋ค. NIO๋ ๋ ผ๋ธ๋กํน์ ์ํด ๋ชจ๋ ์ ์ถ๋ ฅ ์์ ์ ๋ฒํผ๋ฅผ ์ด์ฉํ๋ค. ๋์ฉ๋ ์์ ์์๋ ์ด๋ก์ธํ ๋ฉ๋ชจ๋ฆฌ ๋ญ๋น์ ์ถ๊ฐ์ ์ธ ์์ ์ผ๋ก ์ธํ ์ค๋ฒํค๋๊ฐ ๋์ฑ ์ปค์ง๊ฒ๋๋ค.
๐ญ ๋ง๋ค๊ธฐ๋ ๋ณต์กํ ๋ ผ๋ธ๋กํน NIO, ์ ์๊ฒผ์๊น?
์น ์๋น์ค๋ฅผ ์๊ฐํด๋ณด์.
- ์น ์๋น์ค๋ ๋คํธ์ํฌ๋ฅผ ์ ๋ง ๋ง์ด ์ฌ์ฉํ๋ค.
[๋คํธ์ํฌ I/O]๋ ์๋ฒ์ ์ด์์ฒด์ ์ ์ฅ์์๋ [ํ์ผ I/O]์ ๋์ผํ๋ค. ์์ผ์ ์ด๊ณ , ๊ธฐ๋ค๋ ค์ผํ๋ค.
- ์น ์๋น์ค๋ ๋ฐ์ดํฐ๋ฒ ์ด์ค๋ฅผ ํตํ ํ์ผ I/O ์ ๊ทผ์ ์ ๋ง ๋ง์ด ํ๋ค.
- ์น ์๋น์ค๋ ๋ถํน์ ๋ค์๊ฐ ๋ค๋ฅธ ์๋น์ค๋ฅผ ์ฌ์ฉํ๋ค = ๋น๋๊ธฐ์ ์ธ ์์ ์ด ๋ง๋ค.
- ์น ์๋น์ค๋ ์ฌ๋ฌ ๊ฐ์ ์๋ฒ(์๋น์ค)๊ฐ ํ๋ ฅํ๋ ํํ๊ฐ ๋ง๋ค. = ๋น๋๊ธฐ์ ์ผ๋ก ๋ฐ๋ก ๋์๊ฐ ์๋ค.
CPU ๊ณ์ฐ์ ์ ๋ง ๋ง์ด ์ฌ์ฉํ๋ค๋ฉด, ๋จ์ํ ์ปดํจํฐ์ ์ฑ๋ฅ์ ๊ทนํ์ผ๋ก ์ฌ๋ฆฌ๋ฉด ํด๊ฒฐ๋ ์ ์๋ค.
ํ์ง๋ง ์น ์๋น์ค๋ ๊ทธ๋ ์ง์๋ค. ๋๋ถ๋ถ์ ์๊ฐ์ I/O๋ฅผ ๊ธฐ๋ค๋ฆฌ๋๋ฐ ์๋นํ๋ค.
์ฌ์ค ๊ณผ๊ฑฐ์๋ ์ด๋งํผ์ ๊ณ ๋ฏผ์ด ํ์์์๋ค. ์ปดํจํฐ์ ์ฑ๋ฅ์ด ์๋์ข๊ณ , ๋คํธ์ํฌ๊ฐ ๋น ๋ฅด๋๊น ๋์ถฉ ๋ง๋ค๋ฉด ๋ฌ๋ค.
ํ์ง๋ง ์ง๊ธ์ ์น์ ๊ณผ๊ฑฐ๋์ ๋ง์ด ๋ค๋ฅด๋ค. ์ฌ๋๋ค์ ๋ชจ๋ฐ์ผ๋ก 24์๊ฐ ์น ์๋น์ค๋ฅผ ์ฌ์ฉํ๊ณ , ์ด๋ฒคํธ๊ฐ ์์ผ๋ฉด ์๊ฐ์ ์ผ๋ก ๋ช๋ฐฑ๋ง์ ํธ๋ํฝ ์์ฒญ์ด ๋ชฐ๋ ค์จ๋ค.
[์ฆ์ ์๋น์ค์ ์ฅ์ = ๊ณ ๊ฐ ๋ ๋จ = ๋ ๋ชป๋ฒ๊ณ ํ์ฌ ๋งํจ]์ ๋น์ฐํ ์ฌ์ค์ด๋ค.
์๋ฒ์ปดํจํฐ, CPU ์ฑ๋ฅ, ๋ฉ๋ชจ๋ฆฌ ์ฉ๋์ ์๋ฌด๋ฆฌ ๋๋ ค๋ด์ผ I/O ๋ณ๋ชฉ์ผ๋ก ์ธํ ๋ฌธ์ ๋ ํด๊ฒฐํ ์ ์๋ค.
๊ทธ๋ผ ์ด๋ป๊ฒ ํด์ผํ ๊น? ๋ต์ ๊ฐ๋จํ๋ค. ์ค๋ ๋ ์ฌ๋ฌ ๊ฐ๋ฅผ ๋ณ๋ ฌ๋ก ๋์์ ๋๋ฆฌ๋ฉด ๋๋ค.
1. ์น ์๋น์ค๋ ์ค๋ ๋์ ๊ฐ์๋ฅผ ๋๋ ค์, ๋ฉํฐ์ค๋ ๋๋ก ์ฒ๋ฆฌํ๋ฉด I/O ์ฒ๋ฆฌ์ฑ๋ฅ์ ๊ทน๋ํํ ์ ์๋ค.
๊ทธ๋ฆผ์๋ ๋์์์ง๋ง, ์๋ฒ CPU์ ์ฑ๋ฅ๊ณผ๋ ์ ํ ์๊ด์๋ค. ๊ทธ๋ฅ ์ค๋ ๋๊ฐ ๋คํธ์ํฌ I/O๋ฅผ ๊ธฐ๋ค๋ฆฌ๋ฉด์ ๋๊ณ ์์ ๋ฟ์ด๋ค.
2. ํ์ง๋ง ์ค๋ ๋๋ ๋น์ผ์์์ด๋ค. ์ค๋ ๋๋ฅผ ๋ฌดํ์ ๋๋ฆด ์๋ ์๋ค. ์ด์์ฒด์ ์ ์ปจํ ์คํธ ์ค์์นญ ๋น์ฉ์ด ์ฆ๊ฐํ๋ค.
3. ๊ทธ๋ผ ๊ฐ์๋ฅผ ๋๋ฆฌ๋ ๋์ ์, ํ ์ค๋ ๋๋ฅผ ๋์ง์๊ณ ์ต๋ํ ๋ง์ด ๊ฐ๊ตด์๋ ์์๊น?
์ด๋ฐ ๋งฅ๋ฝ์ผ๋ก ๋น๋๊ธฐ ๋ฉํฐ์ค๋ ๋๋ฅผ ๋์ด์ ์ ์ ๋๊ฐ ๋
ผ๋ธ๋กํน์ ๋ํ ์์ด๋์ด๊ฐ ๋์จ ๊ฒ์ด๋ค.
์.. ๊ทผ๋ฐ I/O๊ฐ ๋ฐํ๋๊ธฐ๋ฅผ ๊ผญ ๊ธฐ๋ค๋ ค์ผํ๋? ๊ทธ๋ฅ ๋ค๋ฅธ ์์ ํ๊ณ ์์ผ๋ฉด ์๋ ๊น? (์ ์ด๊ถ์ ๋ฐํ)
ํ ์ค๋ ๋๊ฐ, ์ฌ๋ฌ ๊ฐ์ Client๋ฅผ ์ฒ๋ฆฌํ๋ฉด ์๋๋? ๋ผ๋ ์์ด๋์ด.
๐ญ ๋ณธ์ง์ ํ์ ํ์
์ธ์
ํด๋ฌ์คํฐ๋ง๊ณผ ์ธ์
์ ์ฅ์.
๋จ์ผ ์ค๋ ๋์ธ Redis์ ๋ฉํฐ ์ค๋ ๋์ธ Memcache
๋ชจ๋ ์์ ์ ์ฒ๋ฆฌํ๋ CPU, ๊ทธ๋ํฝ๊ฐ์ ๋ณ๋ ฌ์ฒ๋ฆฌ์ ํนํ๋ GPU
๋ชจ๋ ์๋น์ค๊ฐ ํ ํ๋ก์ ํธ์ ์๋ ๋ชจ๋๋ฆฌ์ค, ๊ฐ๊ฐ์ ์๋น์ค๊ฐ ๋ฐ๋ก ๋์ํ๋ MSA
๋ฌผ๋ก ์ฌ์ฉํ๋ ์ฅ๋จ์ ์ ๋ค๋ฅด์ง๋ง, ๊ฒฐ๊ตญ ๊ทผ๋ณธ์ ์ธ ํ์ ์ด์ , ๋ณธ์ง์ ๋น์ทํ๋ค.
[์ฆ์ ์๋น์ค์ ์ฅ์ = ๊ณ ๊ฐ ๋ ๋จ = ๋ ๋ชป๋ฒ๊ณ ํ์ฌ ๋งํจ] ์ ํด๊ฒฐํ๊ธฐ ์ํด์, ๋ณ๋ ฌ์ฑ์ ๊ทน๋ํ ํ๋๊ฑฐ๋ค.
'๐๊ธฐ๋ณธ ์ง์ > Java ๊ธฐ๋ณธ์ง์' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
Java ์์ ์๊ฐ์ ๊ด๋ฆฌํ๋ ๋ฐฉ๋ฒ (Instant.now(), LocalDate.now()) (1) | 2023.01.28 |
---|---|
์์์ ํ๋ฆ๋๋ก ์จ๋ณด๋ DB ํธ๋์ญ์ ์ด์ผ๊ธฐ (0) | 2022.08.15 |
์๋ฐ์ ๋์์ฑ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋์๊ตฌ์กฐ (Atomic, Adder, Accumulator) (0) | 2022.03.08 |
์ค๋ธ์ ํธ ๋์์ธ ์คํ์ผ #1 ๊ฐ์ฒด์งํฅ, ์๋น์ค ์์ฑํ๊ธฐ (0) | 2021.10.04 |
๊ฐ๋น์ง ์ปฌ๋ ํฐ์ TLAB (0) | 2021.09.22 |
๋ธ๋ก๊ทธ์ ์ ๋ณด
JiwonDev
JiwonDev