JiwonDev

์ž๋ฐ”์˜ NIO (java.nio)

by JiwonDev

JDK4์—์„œ ๋‚˜์˜ค๊ณ  JDK7์—์„œ java.nio2๋กœ ์—…๋ฐ์ดํŠธ ํ•˜์˜€๋‹ค.

NIO์˜ ์˜๋ฏธ๋Š” ๋น„๋™๊ธฐ-๋…ผ๋ธ”๋กœํ‚น ๋ฐฉ์‹์˜ ์ƒˆ๋กœ์šด ์ž…์ถœ๋ ฅ์ด๋ผ๋Š” ์˜๋ฏธ์ด๋‹ค. (Non-blocking) New Input/Output

๊ณต์‹๋ฌธ์„œ์—๋Š” NIO๋ฅผ New I/O๋ผ๊ณ  ์†Œ๊ฐœํ•˜๋Š”๋ฐ, ๊ทธ ์ด์œ ๋Š” ๋‚ด๋ถ€์˜ ๋ชจ๋“  I/O๊ฐ€ ๋…ผ๋ธ”๋กœํ‚น์œผ๋กœ ๋™์ž‘ํ•˜๋Š”๊ฑด ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

JDK7๋ถ€ํ„ฐ nio2๋ฅผ ์ œ๊ณตํ•ด์ค€๋‹ค.

๐Ÿ“Œ ์Šคํ”„๋ง์—์„œ ์ œ๊ณตํ•˜๋Š” Webflux์™€ Netty ์„œ๋ฒ„๋Š” ์ž๋ฐ”์˜ NIO ๊ธฐ๋ฐ˜์œผ๋กœ ๋งŒ๋“ค์–ด์ ธ์žˆ๋‹ค. 

 

๐Ÿ“Œ ์งง๋ง‰ํ•œ ์ž๋ฐ” ์—ญ์‚ฌ ์ด์•ผ๊ธฐ

์ž๋ฐ”์˜ ๋น„๋™๊ธฐ์ฒ˜๋ฆฌ - Thread ๊ฐ์ฒด๋Š”, ๊ฑฐ์˜ ์ดˆ์ฐฝ๊ธฐ ๋ฒ„์ „๋ถ€ํ„ฐ ์ง€์›ํ•˜๋Š” ๊ธฐ๋Šฅ์ด์—ˆ๋‹ค. (๋ฌผ๋ก  ๊ทธ ๋‹น์‹œ์—๋Š” ์ตœ์ ํ™”๊ฐ€ ๊ตฌ๋ ธ์ง€๋งŒ)

 

๋‹ค๋งŒ ์›น์•ฑ์„œ๋ฒ„์ธ ํ†ฐ์บฃ(WAS)์€ ๊ฒฐ๊ตญ ์„œ๋ธ”๋ฆฟ์œผ๋กœ ๋™์ž‘ํ•œ๋‹ค. ๊ทธ๋ž˜์„œ ๊ณผ๊ฑฐ์—๋Š” ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ๊ฐ™์€๊ฑฐ ์ง€์› ์•ˆํ–ˆ๋‹ค.

์™œ๋ƒํ•˜๋ฉด ์ž๋ฐ”์˜ ์„œ๋ธ”๋ฆฟ์€ [์›๋ž˜ ํ•œ๊ฐœ์˜ ์š”์ฒญ = ํ•œ ์Šค๋ ˆ๋“œ = ํ•œ ๊ฐœ์˜ ์„œ๋ธ”๋ฆฟ] ์ฒ˜๋ฆฌ๋งŒ ๊ฐ€๋Šฅํ•˜๊ฒŒ ์„ค๊ณ„๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

ํ•˜์ง€๋งŒ ์›น ์„œ๋ฒ„์—์„œ ์—ฐ๊ฒฐ์„ ์œ ์ง€ํ•œ ์ฑ„, ์ง€์†์ ์œผ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋ฐ›์„ ๋•Œ ์†๋„๊ฐ€ ๋„ˆ๋ฌด ๋Š๋ฆฌ๋‹ค๋Š” ๋‹จ์ ์ด ์žˆ์—ˆ๋‹ค.

 

๊ทธ๋ž˜์„œ 2009๋…„ 1์›”, ์„œ๋ธ”๋ฆฟ 3.0 ์ŠคํŽ™์—์„œ๋ถ€ํ„ฐ ์‘๋‹ต์„ ๋น„๋™๊ธฐ๋กœ ์น˜๋ฆฌ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋ฐ”๋€Œ์—ˆ๋‹ค. (์ด๋Š” ์Šคํ”„๋งMVC 3.2๋ถ€ํ„ฐ ์ง€์›)

์ด์ œ ์„œ๋ธ”๋ฆฟ์„ ์‹คํ–‰ํ•œ ์Šค๋ ˆ๋“œ๊ฐ€ ์—†์–ด์ง€๋”๋ผ๋„, ๋ณ„๋„์˜ ์Šค๋ ˆ๋“œ๋ฅผ ํ†ตํ•ด ์‘๋‹ต์„ ๋‚˜์ค‘์— ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋‹ค.
์ด๋Š” JDK1.5์— ์ถ”๊ฐ€๋œ Callable ๋“ฑ์„ ์‚ฌ์šฉํ•ด์„œ ๊ตฌํ˜„๋˜์—ˆ๋‹ค. NIO ์•„๋‹ˆ๋‹ค.

์ฐธ๊ณ ๋กœ ํ†ฐ์บฃ 7.0์€ 2010๋…„ 7์›”์— ๋ฒ ํƒ€ ๋ฒ„์ „์„ ์ถœ์‹œํ–ˆ๋‹ค.

์ฆ‰, ์•„๋ž˜์™€ ๊ฐ™์ด ํ•œ ์„œ๋ธ”๋ฆฟ์—์„œ ์—ฌ๋Ÿฌ ๊ฐœ์˜ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ๋ฅผ ๋Œ๋ฆด ์ˆ˜ ์žˆ๊ฒŒ ๋ฐ”๋€Œ์—ˆ๋‹ค.

@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๋ฒˆ ์Šค๋ ˆ๋“œ ์ถœ๋ฐœ
    }
}

์œ„์™€ ๊ฐ™์ด ์ž‘์„ฑํ•˜๋ฉด, ์„œ๋ธ”๋ฆฟ์€ ์ด๋ ‡๊ฒŒ ๋™์ž‘ํ•œ๋‹ค.

  1. ์ œ์ผ ์•ž์— ์žˆ๋Š” T1(ํด๋ผ์ด์–ธํŠธ ์š”์ฒญ์„ ๋ฐ›์€ ์Šค๋ ˆ๋“œ)๋Š” ์„œ๋ธ”๋ฆฟ์˜ doGet()์„ ์‹คํ–‰ํ•œ๋‹ค.
  2. T1์€ ์„œ๋ธ”๋ฆฟ์˜ doGet() ๋ฉ”์„œ๋“œ์—์„œ  AsyncContext ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ ๋‹ค.
  3. T1์€ AsyncContext๋ฅผ ์ด์šฉํ•ด์„œ ๋น„๋™๊ธฐ๋กœ ์ฒ˜๋ฆฌํ•  ์ƒˆ๋กœ์šด ์Šค๋ ˆ๋“œ(T2)๋ฅผ ์ƒ์„ฑํ•˜๊ณ , ์‹œ์ž‘ํ•œ๋‹ค.
  4. T1์€ ์ž๊ธฐ ํ• ์ผ์ด ๋‹ค ๋๋‚ฌ๊ธฐ ๋•Œ๋ฌธ์— ํ‰์†Œ์ฒ˜๋Ÿผ ์„œ๋ธ”๋ฆฟ ๊ฐ์ฒด๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ณ , ์Šค๋ ˆ๋“œ๋ฅผ ์ข…๋ฃŒํ•œ๋‹ค.
  5. (ํ˜„์žฌ T1์€ ์—†์–ด์ง„ ์ƒํ™ฉ) T2๋Š” ๋ณ„๋„์˜ ์Šค๋ ˆ๋“œ์—์„œ ์ž๊ธฐ ํ• ์ผ์„ ํ•œ๋‹ค. 
    ์ด๋•Œ ํ•„์š”ํ•œ request, response๋Š” AsyncContext ์—์„œ ๋ฐ›์•„์˜ฌ ์ˆ˜ ์žˆ๋‹ค. 
  6. (ํ˜„์žฌ T1์€ ์—†์–ด์ง„ ์ƒํ™ฉ) T2 ์Šค๋ ˆ๋“œ๋Š” AsyncContext๋ฅผ ์ด์šฉํ•ด ํด๋ผ์ด์–ธํŠธ์— ์‘๋‹ต์„ ์ „์†กํ•œ๋‹ค.
  7. T2์Šค๋ ˆ๋“œ๋Š” ํ• ์ผ์„ ๋งˆ์น˜๊ณ , AsyncContext.complete()๋ฅผ ํ†ตํ•ด ์‹คํ–‰์„ ์ข…๋ฃŒํ•˜๊ณ  ์Šค๋ ˆ๋“œ๋ฅผ ๋ฐ˜๋‚ฉํ•œ๋‹ค. 

 

๐Ÿค” ๋น„๋™๊ธฐ๋Š” ์•Œ๊ฒ ๋Š”๋ฐ, ๊ทธ๋Ÿผ Tomcat์€ ์•„์ง๋„ nio, nio2๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š”๊ฑด๊ฐ€์š”?

ํ†ฐ์บฃ7(์„œ๋ธ”๋ฆฟ3.0)์—์„œ ๋น„๋™๊ธฐ ๊ธฐ๋Šฅ์ด ์ถ”๊ฐ€๋˜๋ฉฐ, ๋…ผ๋ธ”๋กœํ‚น IO HTTP ์„œ๋ธ”๋ฆฟ ์ปค๋„ฅํ„ฐ๋„ ํ•จ๊ป˜ ์ถ”๊ฐ€๋˜์—ˆ๋‹ค.
๋‹น์—ฐํ•œ๊ฑฐ์ง€๋งŒ ํ†ฐ์บฃ์—์„œ NIO๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค๊ณ  [DB I/O๋‚˜ ํŒŒ์ผ์ฒ˜๋ฆฌ]๊ฐ€ ์ž๋™์œผ๋กœ ๋…ผ๋ธ”๋กœํ‚นํ•˜๊ฒŒ ๋™์ž‘ํ•˜์ง€๋Š” ์•Š๋Š”๋‹ค.

ํ†ฐ์บฃ์€ ์„œ๋ธ”๋ฆฟ์„ ์ฒ˜๋ฆฌํ•˜๋Š” '์›น ์„œ๋ฒ„'์ด๊ณ , ๋ณ‘๋ ฌ์ฒ˜๋ฆฌ๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ์ง์ ‘ ๋น„๋™๊ธฐ-๋…ผ๋ธ”๋กœํ‚น ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๊ฑฐ๋‹ค.

NIO Connector๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ java์˜ nio, nio2๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.

// 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๋Š” ๋‘˜ ๋‹ค ์ง€์›ํ•œ๋‹ค.

Tomcat์˜ ์„œ๋ธ”๋ฆฟ์„ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ๋กœ ๋Œ๋ฆฌ๋Š” ๊ฒƒ๊ณผ ๊ธฐ๋ณธ ์„ค๊ณ„๋ถ€ํ„ฐ๊ฐ€ ๋‹ค๋ฅด๋‹ค.

  • [์ด๋ฒคํŠธ ๋ฃจํ”„ ์ฒ˜๋ฆฌ]๋ฅผ ๋™๊ธฐ์ ์ธ-์‹ฑ๊ธ€์Šค๋ ˆ๋“œ๋กœ ํ• ์ˆ˜๋„์žˆ๊ณ , ๋น„๋™๊ธฐ-๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ๋กœ ํ• ์ˆ˜๋„ ์žˆ๋‹ค. ์žฅ๋‹จ์ ์ด ์กด์žฌํ•œ๋‹ค.

์ด๋ฒคํŠธ๋ฅผ ๋ฐ›๋Š” ์Šค๋ ˆ๋“œ๋Š” 1๊ฐœ์ด๋‹ค. [์ด๋ฒคํŠธ ๋ฃจํ”„ ์ฒ˜๋ฆฌ ์Šค๋ ˆ๋“œ๋“ค]์„ ๋™๊ธฐ์ ์œผ๋กœ ํ• ๊ฑด์ง€, ๋น„๋™๊ธฐ๋กœ ํ• ๊ฑด์ง€ ์ •ํ•œ๋‹ค.

๋” ์ž์„ธํ•œ ๋‚ด์šฉ์€ ์Šคํ”„๋ง5 Webflux๋‚˜ ๋ฆฌ์•กํ‹ฐ๋ธŒ ํ”„๋กœ๊ทธ๋ž˜๋ฐ (RxJava)๋ฅผ ์ฐพ์•„๋ณด๋ฉด ์ž๋ฃŒ๊ฐ€ ๋งŽ์œผ๋‹ˆ, ๊ถ๊ธˆํ•˜๋ฉด ์ฐพ์•„๋ณด์ž.

 


๐Ÿ’ญ ๊ธฐ์กด์˜ Java I/O์™€ ๋‹ค๋ฅธ์ 

Blocking I/O๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ ๊ฐ•๋ฌผ์ด ํ๋ฅด๋“ฏ ์ŠคํŠธ๋ฆผ์œผ๋กœ ์ „์†ก๋œ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๋Š” ๋ฐฉ์‹์ด๊ธฐ ๋•Œ๋ฌธ์— ์ดํ•ดํ•˜๊ธฐ๋Š” ์‰ฌ์šฐ๋‚˜ ์‹ค์ œ ๋„คํŠธ์›Œํฌ์ƒ์˜ ๋ฐ์ดํ„ฐ์ „์†ก ๋ฐฉ์‹์€ ์ด์™€ ๋‹ค๋ฆ…๋‹ˆ๋‹ค. Non-blocking I/O ๋Š” ์‹ค์ œ ๋„คํŠธ์›Œํฌ์ƒ์˜ ๋ฐ์ดํ„ฐ ์ „์†ก์ด ์ด๋ฃจ์–ด์ง€๋Š” ๋ฐฉ์‹๊ณผ ์œ ์‚ฌํ•˜๊ฒŒ ๊ตฌํ˜„๋˜๋Š” I/O ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.

์ฐธ๊ณ ๋กœ ๊ธฐ์กด์— ์žˆ๋˜ ์ž๋ฐ” I/O๋ฅผ BIO, Blocking-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 ์ ‘๊ทผ์„ ์ •๋ง ๋งŽ์ด ํ•œ๋‹ค.
  • ์›น ์„œ๋น„์Šค๋Š” ๋ถˆํŠน์ • ๋‹ค์ˆ˜๊ฐ€ ๋‹ค๋ฅธ ์„œ๋น„์Šค๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค = ๋น„๋™๊ธฐ์ ์ธ ์ž‘์—…์ด ๋งŽ๋‹ค.
  • ์›น ์„œ๋น„์Šค๋Š” ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์„œ๋ฒ„(์„œ๋น„์Šค)๊ฐ€ ํ˜‘๋ ฅํ•˜๋Š” ํ˜•ํƒœ๊ฐ€ ๋งŽ๋‹ค. = ๋น„๋™๊ธฐ์ ์œผ๋กœ ๋”ฐ๋กœ ๋†€์ˆ˜๊ฐ€ ์žˆ๋‹ค.

CPU ๊ณ„์‚ฐ์„ ์ •๋ง ๋งŽ์ด ์‚ฌ์šฉํ•œ๋‹ค๋ฉด, ๋‹จ์ˆœํžˆ ์ปดํ“จํ„ฐ์˜ ์„ฑ๋Šฅ์„ ๊ทนํ•œ์œผ๋กœ ์˜ฌ๋ฆฌ๋ฉด ํ•ด๊ฒฐ๋  ์ˆ˜ ์žˆ๋‹ค.

ํ•˜์ง€๋งŒ ์›น ์„œ๋น„์Šค๋Š” ๊ทธ๋ ‡์ง€์•Š๋‹ค. ๋Œ€๋ถ€๋ถ„์˜ ์‹œ๊ฐ„์„ I/O๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋Š”๋ฐ ์†Œ๋น„ํ•œ๋‹ค.

์›น์„œ๋น„์Šค๋Š” Process 2์— ๊ฐ€๊น๋‹ค. ๊ทธ๋ฆผ์œผ๋กœ ๋ด๋„ ์•Œ๊ฒ ์ง€๋งŒ, [CPU ์„ฑ๋Šฅ์€ ๋ฌธ์ œ๊ฐ€ ์—†๋‹ค.] ํ•˜๋ฃจ์ข…์ผ I/O๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋ฉฐ ๋†€๊ณ ์žˆ์„ ๋ฟ์ด๋‹ค.

์‚ฌ์‹ค ๊ณผ๊ฑฐ์—๋Š” ์ด๋งŒํผ์˜ ๊ณ ๋ฏผ์ด ํ•„์š”์—†์—ˆ๋‹ค. ์ปดํ“จํ„ฐ์˜ ์„ฑ๋Šฅ์ด ์›Œ๋‚™์ข‹๊ณ , ๋„คํŠธ์›Œํฌ๊ฐ€ ๋น ๋ฅด๋‹ˆ๊นŒ ๋Œ€์ถฉ ๋งŒ๋“ค๋ฉด ๋ฌ๋‹ค.

ํ•˜์ง€๋งŒ ์ง€๊ธˆ์˜ ์›น์€ ๊ณผ๊ฑฐ๋ž‘์€ ๋งŽ์ด ๋‹ค๋ฅด๋‹ค. ์‚ฌ๋žŒ๋“ค์€ ๋ชจ๋ฐ”์ผ๋กœ 24์‹œ๊ฐ„ ์›น ์„œ๋น„์Šค๋ฅผ ์‚ฌ์šฉํ•˜๊ณ , ์ด๋ฒคํŠธ๊ฐ€ ์žˆ์œผ๋ฉด ์ˆœ๊ฐ„์ ์œผ๋กœ ๋ช‡๋ฐฑ๋งŒ์˜ ํŠธ๋ž˜ํ”ฝ ์š”์ฒญ์ด ๋ชฐ๋ ค์˜จ๋‹ค.

 

[์žฆ์€ ์„œ๋น„์Šค์˜ ์žฅ์•  = ๊ณ ๊ฐ ๋– ๋‚จ = ๋ˆ ๋ชป๋ฒŒ๊ณ  ํšŒ์‚ฌ ๋งํ•จ]์€ ๋‹น์—ฐํ•œ ์‚ฌ์‹ค์ด๋‹ค.

์„œ๋ฒ„์ปดํ“จํ„ฐ, CPU ์„ฑ๋Šฅ, ๋ฉ”๋ชจ๋ฆฌ ์šฉ๋Ÿ‰์„ ์•„๋ฌด๋ฆฌ ๋Š˜๋ ค๋ด์•ผ I/O ๋ณ‘๋ชฉ์œผ๋กœ ์ธํ•œ ๋ฌธ์ œ๋Š” ํ•ด๊ฒฐํ•  ์ˆ˜ ์—†๋‹ค.

 

๊ทธ๋Ÿผ ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ? ๋‹ต์€ ๊ฐ„๋‹จํ•˜๋‹ค. ์Šค๋ ˆ๋“œ ์—ฌ๋Ÿฌ ๊ฐœ๋ฅผ ๋ณ‘๋ ฌ๋กœ ๋™์‹œ์— ๋Œ๋ฆฌ๋ฉด ๋œ๋‹ค.

1. ์›น ์„œ๋น„์Šค๋Š” ์Šค๋ ˆ๋“œ์˜ ๊ฐœ์ˆ˜๋ฅผ ๋Š˜๋ ค์„œ, ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ๋กœ ์ฒ˜๋ฆฌํ•˜๋ฉด I/O ์ฒ˜๋ฆฌ์„ฑ๋Šฅ์„ ๊ทน๋Œ€ํ™”ํ•  ์ˆ˜ ์žˆ๋‹ค.
๊ทธ๋ฆผ์—๋„ ๋‚˜์™€์žˆ์ง€๋งŒ, ์„œ๋ฒ„ CPU์˜ ์„ฑ๋Šฅ๊ณผ๋Š” ์ „ํ˜€ ์ƒ๊ด€์—†๋‹ค. ๊ทธ๋ƒฅ ์Šค๋ ˆ๋“œ๊ฐ€ ๋„คํŠธ์›Œํฌ I/O๋ฅผ ๊ธฐ๋‹ค๋ฆฌ๋ฉด์„œ ๋†€๊ณ ์žˆ์„ ๋ฟ์ด๋‹ค.

Client๋ฅผ File๋กœ ๋ฐ”๊ฟ”๋ณด์ž. ์„œ๋ฒ„ ์ž…์žฅ์—์„œ๋Š” ํŒŒ์ผI/O์™€ ๋„คํŠธ์›Œํฌ I/O๋Š” ๋™์ผํ•œ ๊ฐœ๋…์ด๋‹ค (์‹ค์ œ๋กœ๋„ ์šด์˜์ฒด์ œ ๋™์ž‘๋„ ๊ทธ๋ ‡๋‹ค.)

 

2. ํ•˜์ง€๋งŒ ์Šค๋ ˆ๋“œ๋Š” ๋น„์‹ผ์ž์›์ด๋‹ค. ์Šค๋ ˆ๋“œ๋ฅผ ๋ฌดํ•œ์ • ๋Š˜๋ฆด ์ˆ˜๋Š” ์—†๋‹ค. ์šด์˜์ฒด์ œ์˜ ์ปจํ…์ŠคํŠธ ์Šค์œ„์นญ ๋น„์šฉ์ด ์ฆ๊ฐ€ํ•œ๋‹ค.

3. ๊ทธ๋Ÿผ ๊ฐœ์ˆ˜๋ฅผ ๋Š˜๋ฆฌ๋Š” ๋Œ€์‹ ์—, ํ•œ ์Šค๋ ˆ๋“œ๋ฅผ ๋†€์ง€์•Š๊ณ  ์ตœ๋Œ€ํ•œ ๋งŽ์ด ๊ฐˆ๊ตด์ˆ˜๋Š” ์—†์„๊นŒ?

 

์ด๋Ÿฐ ๋งฅ๋ฝ์œผ๋กœ ๋น„๋™๊ธฐ ๋ฉ€ํ‹ฐ์Šค๋ ˆ๋“œ๋ฅผ ๋„˜์–ด์„  ์ •์‹ ๋‚˜๊ฐ„ ๋…ผ๋ธ”๋กœํ‚น์— ๋Œ€ํ•œ ์•„์ด๋””์–ด๊ฐ€ ๋‚˜์˜จ ๊ฒƒ์ด๋‹ค. 

์Œ.. ๊ทผ๋ฐ I/O๊ฐ€ ๋ฐ˜ํ™˜๋˜๊ธฐ๋ฅผ ๊ผญ ๊ธฐ๋‹ค๋ ค์•ผํ•˜๋‚˜? ๊ทธ๋ƒฅ ๋‹ค๋ฅธ ์ž‘์—…ํ•˜๊ณ  ์žˆ์œผ๋ฉด ์•ˆ๋ ๊นŒ? (์ œ์–ด๊ถŒ์˜ ๋ฐ˜ํ™˜)

ํ•œ ์Šค๋ ˆ๋“œ๊ฐ€, ์—ฌ๋Ÿฌ ๊ฐœ์˜ Client๋ฅผ ์ฒ˜๋ฆฌํ•˜๋ฉด ์•ˆ๋˜๋‚˜? ๋ผ๋Š” ์•„์ด๋””์–ด.

ํ†ฐ์บฃ์—์„œ NIO๋ฅผ ์‚ฌ์šฉํ–ˆ์„ ๋•Œ ๋ชจ์Šต. Netty๋Š” ๋™์ž‘๋ฐฉ์‹์ด ๊ทธ๋ฆผ๊ณผ๋Š” ๋‹ค๋ฅด๋‹ค.

 

๐Ÿ’ญ ๋ณธ์งˆ์„ ํŒŒ์•…ํ•˜์ž

์„ธ์…˜ ํด๋Ÿฌ์Šคํ„ฐ๋ง๊ณผ ์„ธ์…˜ ์ €์žฅ์†Œ.
๋‹จ์ผ ์Šค๋ ˆ๋“œ์ธ Redis์™€ ๋ฉ€ํ‹ฐ ์Šค๋ ˆ๋“œ์ธ Memcache

๋ชจ๋“  ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•˜๋Š” CPU, ๊ทธ๋ž˜ํ”ฝ๊ฐ™์€ ๋ณ‘๋ ฌ์ฒ˜๋ฆฌ์— ํŠนํ™”๋œ GPU

๋ชจ๋“  ์„œ๋น„์Šค๊ฐ€ ํ•œ ํ”„๋กœ์ ํŠธ์— ์žˆ๋Š” ๋ชจ๋†€๋ฆฌ์Šค, ๊ฐ๊ฐ์˜ ์„œ๋น„์Šค๊ฐ€ ๋”ฐ๋กœ ๋™์ž‘ํ•˜๋Š” MSA

 

๋ฌผ๋ก  ์‚ฌ์šฉํ•˜๋Š” ์žฅ๋‹จ์ ์€ ๋‹ค๋ฅด์ง€๋งŒ, ๊ฒฐ๊ตญ ๊ทผ๋ณธ์ ์ธ ํƒ„์ƒ ์ด์œ , ๋ณธ์งˆ์€ ๋น„์Šทํ•˜๋‹ค.

[์žฆ์€ ์„œ๋น„์Šค์˜ ์žฅ์•  = ๊ณ ๊ฐ ๋– ๋‚จ = ๋ˆ ๋ชป๋ฒŒ๊ณ  ํšŒ์‚ฌ ๋งํ•จ] ์„ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด์„œ, ๋ณ‘๋ ฌ์„ฑ์„ ๊ทน๋Œ€ํ™” ํ•˜๋Š”๊ฑฐ๋‹ค.

๋ธ”๋กœ๊ทธ์˜ ์ •๋ณด

JiwonDev

JiwonDev

ํ™œ๋™ํ•˜๊ธฐ