ÁÖÀÇ: º»¹®¼´Â ¸¶ÀÌÅ©·Î¼ÒÇÁÆ®¿þ¾î 2002~11¿ù,12¿ùÈ£¿¡ ¼ÛÁöÈÆ´ÔÀÌ ±â°íÇÑ ±Û·Î½á º»ÀÎÀÇ µ¿ÀǾøÀÌ ¹«´Ü ¹èÆ÷ÇÏ´Â °ÍÀ» ±ÝÁöÇÔ. ¸¸¾à ±ÛÀ» ´Ù¸¥ °÷¿¡ Æ÷½ºÆÃÇÏ·Á ÇÒ °æ¿ì ¹Ýµå½Ã °ÁÂÀÇ URL ¸µÅ©¸¦ »ç¿ëÇØ¾ßÇÔ.
ByteBufferPool°ú ThreadPoolÀ» Ãß°¡ÇØ ¼º´É ¾÷±×·¹À̵åÇϱâ
¸¸µçÀÌ: ¼ÛÁöÈÆ
¼Ò¼Ó:
JavaCafe ºÎ½Ã¼¥
email:
johnleen@hanmail.net
¼¹öÀÇ ¼º´É Çâ»óÀ» À§ÇØ Pooling ±â¹ýÀ» µµÀÔÇϰí Command ÆÐÅϰú ·±Å¸ÀÓ µ¿Àû ·ÎµùÀ» ÀÌ¿ëÇØ ¸ØÃßÁö ¾Ê´Â ¼¹ö ¸¸µé±â
À̹ø È£¿¡¼´Â ¼¹öÀÇ ¼º´É Çâ»óÀ» À§ÇØ °í·ÁÇØ¾ß ÇÒ Á¡µéÀ» »ìÆìº¸°í ±× °³¼± ¹æ¹ýµé¿¡ ´ëÇØ ¾ð±ÞÇÒ °ÍÀÌ´Ù. ±×¸®°í ±× Áß ÀϺθ¦ Áö³ ½Ã°£¿¡ ¸¸µé¾ú´ø °£´ÜÇÑ Ã¤ÆÃ ¼¹ö¿¡ Àû¿ë½ÃÄÑ º¼ °ÍÀÌ´Ù. ±×·³ ÀÌ ±â»ç¸¦ ÅëÇØ »ó¿ë ¼¹ö ÇÁ·Î±×·¥ ¼öÁØ¿¡ ÇѰÉÀ½ ´õ ´Ù°¡¼ º¸ÀÚ.
ThreadPool °ú ByteBufferPool ·Î ¼¹ö¿¡ ³¯°³¸¦ ´ÞÀÚ
¸ð¹ÙÀÏ ÇÁ·Î±×·¥ÀÌ Á¦ÇÑµÈ ½Ã½ºÅÛ »ç¾ç¿¡¼ ¸¸Á·ÇÒ ¸¸ÇÑ ¼Óµµ¸¦ ¾ò±â À§ÇØ Äڵ带 ÃÖÀûÈ ½Ã۵íÀÌ ³×Æ®¿öÅ© ÇÁ·Î±×·¡¹Öµµ È¿À²À» Áß½ÃÇϱ⠶§¹®¿¡ ÄÚµù½Ã °í·ÁÇØ¾ßÇÒ Á¡µéÀÌ ¸¹´Ù. È¿À²°ú È®À强, ¾ÈÁ¤¼ºÀ» °í·ÁÇØ¾ßÇÏ´Â ³×Æ®¿öÅ© ÇÁ·Î±×·¡¹ÖÀº ´Ù¸¥ ÇÁ·Î±×·¥¿¡ ºñÇØ ±â¼ú Áý¾àÀûÀÎ ÇüÅÂÀÇ ¼º´ÉÇâ»óÀ» °í·ÁÇÑ ÄÚµåµé·Î ÀÌ·ç¾îÁ®¾ß ÇÑ´Ù. À̹ۿ¡µµ ³×Æ®¿öÅ©¶ó´Â °÷ÀÌ ÁÖ¹«´ëÀÌ´Ù º¸´Ï ¿¹±âÄ¡ ¸øÇÑ ´Ù¾çÇÑ »óȲ¿¡ ´ëºñÇØ¾ßÇÏ´Â °Íµµ ÇÁ·Î±×·¡¸Ó ÀÔÀå¿¡¼± °ñÄ¡ ¾ÆÇ ÀÏÀÌ´Ù. Áö¸é°ü°è»ó ÀÌ ±ÛÀ» ÅëÇØ ¼¹ö ÇÁ·Î±×·¡¹Ö¿¡¼ °í·ÁÇØ¾ßÇÒ ¸ðµç °ÍµéÀ» ´Ù ¾ð±ÞÇÏÁö´Â ¸øÇÒ °ÍÀÌ´Ù. ÇÏÁö¸¸ Àü ½Ã°£¿¡ ¾ð±ÞÇßµíÀÌ È¿À²ÀûÀÎ ¾²·¹µå ¿î¿µÀ» À§ÇÑ ThreadPool, ¹öÆÛÀÇ È¿À²ÀûÀÎ ¿î¿µ°ú ÆÄÀÏÀ» ¸Þ¸ð¸®·Î »ç¿ëÇϱâ À§ÇÑ ByteBufferPoolÀ» Áß½ÉÀ¸·Î ¼³¸íÇØ ³ª°¥ °ÍÀÌ´Ù. ¶Ç Command ÆÐÅϰú ÀÚ¹ÙÀÇ ¾ð¾îÀû Ư¡ÀÎ ·±Å¸ÀÓ µ¿Àû ·ÎµùÀ» ÀÌ¿ëÇØ ±â´É È®Àå½Ã ¼¹ö¸¦ ÀçºÎÆÃ ÇÏÁö ¾Ê¾Æµµ µÇ´Â ±â¹ýÀ» ¼³¸íÇÒ °ÍÀÌ´Ù. À̿ܿ¡ ±âŸ ÇÊ¿äÇÏ´Ù°í »ý°¢µÇ´Â ºÎºÐµé¿¡ ´ëÇØ¼µµ Ãß°¡ÀûÀÎ ¼³¸í°ú Äڵ带 ¼Ò°³ÇØ ³ª°¥ °ÍÀÌ´Ù. ±×·³ ¿ì¸®°¡ Áö³ ½Ã°£¿¡ ¸¸µé¾ú´ø ¼¹ö¸¦ ¾÷±×·¹ÀÌµå ½ÃÄѺ¸ÀÚ.
È¿À²ÀûÀÎ Thread ¿î¿µ-°ü¸®¸¦ À§ÇÑ ThreadPool
µ¿½Ã¿¡ ¼ö¸¹Àº ¿äûÀ» ó¸®Çϱâ À§Çؼ± ¹«¾ùº¸´Ùµµ È¿À²Àû(ÀûÀº ¸Þ¸ð¸® »ç¿ë, ºü¸¥ 󸮼ӵµ) À¸·Î ¼¹ö¸¦ ¸¸µå´Â °ÍÀÌ °¡Àå Áß¿äÇÏ´Ù. ¾²·¹µå¸¦ ÇÊ¿äÇÒ ¶§¸¶´Ù ±×¶§±×¶§ ¸¸µé¾î¼ »ç¿ëÇÏ°Ô µÇ¸é ¾²·¹µå ÀÚü¸¦ »ý¼ºÇÏ´Â °Íµµ ²Ï(¼¹ö ÇÁ·Î±×·¥ ÀÔÀå¿¡¼±) ½Ã°£ÀÌ °É¸®´Â ´À¸° ÀÛ¾÷ÀÌ°í ¾²·¹µå¶ó´Â °´Ã¼°¡ ÀÚÁÖ »ý¼º-ÇØÁ¦ µÇ´Â »óȲ ¶§¹®¿¡ °¡ºñÁö Ä÷ºÅÍ(Garbage Collector)°¡ ºó¹øÇÏ°Ô È£ÃâµÉ ¼ö Àֱ⠶§¹®ÀÌ´Ù.
±×·¡¼ ÀÌ·± ¹®Á¦Á¡À» ÇØ°áÇϱâ À§ÇÑ ¹æ¹ýÀ¸·Î GoF °¡ ¾´ ¸í¼ Design Pattern ¿¡ ¼Ò°³µÈ Object Pool ÆÐÅÏÀ» ÀÌ¿ëÇÒ °ÍÀÌ´Ù. »ý¼ºÇÒ °´Ã¼°¡ ³Ê¹« ½Ã°£ÀÌ ¿À·¡ °É¸®°Å³ª ¸¹Àº °æ¿ì µîÀ¸·Î ÀÎÇÑ ¹®Á¦Á¡ÀÌ ÀÖÀ» ¶§ <±×¸² 1> °ú °°ÀÌ ±× °´Ã¼¸¦ Å¥(Ä÷º¼Ç °´Ã¼)¿¡ ³Ö¾î³õ°í Àç»ç¿ëÇÏ´Â °ÍÀÌ ÀÌ ÆÐÅÏÀÇ ÇÙ½É ¿ø¸®´Ù. ÆÐÅÏ À̸§À» º¸°í ÁüÀÛÇÒ ¼ö ÀÖ°ÚÁö¸¸ Object ´Â ¹ü¿ëÀûÀÎ ÇüÅÂÀÌ´Ù. °´Ã¼ÁöÇâ ¾ð¾î¿¡¼ ÃÖ»óÀ§ÀÇ Ç¥Çö´ÜÀ§°¡ ¹Ù·Î Object ¾Æ´Ñ°¡...
µû¶ó¼ ¿ì¸®´Â ¡°Thread¡°¸¦ Àç»ç¿ëÇÏ·Á°í Çϱ⠶§¹®¿¡ ObjectPool Pattern À» ±¸Ã¼ÀûÀ¸·Î Àû¿ëÇÑ ThreadPool À̶ó´Â Ŭ·¡½º¸¦ ¸¸µé¾î¼ »ç¿ëÇÒ °ÍÀÌ´Ù. ObjectPool Pattern ÀÇ ´Ù¸¥ Àû¿ë ¿¹·Î´Â jsp/servlet À¸·Î À¥ÇÁ·Î±×·¡¹ÖÀ» ÇÒ¶§ DB Á¢¼Ó¿¡ ÈçÈ÷ »ç¿ëÇÏ´Â ConnectionPool ÀÌ ÀÖ´Ù.

<±×¸² 1> ThreadPool µµ½Äµµ
¾î¶² ±â¼úÀ» °øºÎÇÒ ¶§ Ç×»ó »ý°¢ÇØ¾ß ÇÏ´Â °Íµé Áß Çϳª°¡ ¹Ù·Î ±× ±â¼úÀÇ Àå´ÜÁ¡°ú ÃÖÀûÀÇ Àû¿ë °¡´É ºÐ¾ß µîÀ» Á¤È®ÇÏ°Ô ÆÄ¾ÇÇÏ´Â °ÍÀÌ´Ù. ±×·¡¾ß¸¸ Á» ´õ ±× ±â¼ú¿¡ ´ëÇÑ ÀÌÇØµµµµ ³ôÀÏ ¼ö ÀÖ°í ±× ±â¼úÀÌ ÇÊ¿äÇÑ °÷¿¡ ÃÖÀûÈ ½ÃÄÑ »ç¿ëÇÒ ¼ö Àֱ⠶§¹®ÀÌ´Ù.
±×·¯¹Ç·Î ¿ì¼± ThreadPoolÀ» ¸¸µé±â Àü¿¡ ÀÌ ThreadPoolÀ» ¸¸µé¾î »ç¿ëÇÒ ¶§ ¾òÀ» ¼ö ÀÖ´Â ÀåÁ¡ÀÌ ±¸Ã¼ÀûÀ¸·Î ¹«¾ùÀÌ ÀÖ´ÂÁö ¾Ë¾Æº¸ÀÚ. ÀåÁ¡À» ¾È´Ù¸é ´ç¿¬È÷ ¾î´À °÷¿¡, ¾î¶»°Ô ¾²¿©¾ß ÇÒÁöµµ ½±°Ô ¾Ë ¼ö ÀÖÀ» °ÍÀÌ´Ù.
ù ¹øÂ° ÀÌÁ¡À¸·Î´Â ¾²·¹µå¸¦ Àç»ç¿ëÇÔÀ¸·Î½á °¡ºñÁö Ä÷ºÅÍÀÇ È£ÃâÀ» Á» ´õ ÁÙÀÏ ¼ö ÀÖ´Ù´Â °ÍÀÌ´Ù. ¾²·¹µåÀÇ ÀæÀº »ý¼º ¼Ò¸ê·Î ÀÎÇØ »ý¼ºµÉ °¡ºñÁö Ä÷º¼Ç(Garbage Collection)ÀÇ ´ë»óÀ» ÁÙÀÓÀ¸·Î½á °¡ºñÁö Ä÷ºÅÍÀÇ È£ÃâÀ» ÁÙÀ̰í ÀÌ·Î ÀÎÇØ ÆÛÆ÷¸Õ½º¿¡ ¾Ç¿µÇâÀ» ÁÙ ¼ö ÀÖ´Â ¿ä¼Ò¸¦ ÀÛ°Ô³ª¸¶ »çÀü¿¡ ¿¹¹æÇÑ´Ù´Â °ÍÀÌ´Ù. Áö³ ȸ¿¡¼µµ ¾ê±âÇß¾úÁö¸¸ °¡ºñÁö Ä÷ºÅÍ·Î ¸Þ¸ð¸®¸¦ ¼ö°ÅÇÏ´Â °ÍÀº »ó´çÈ÷ ´À¸° ÀÛ¾÷ÀÌ´Ù. (1ȸ ±â»ç¿¡¼ ¼³¸íÇß¾ú´Ù. ±â¾ïÀÌ ¾È³´Ù¸é ´Ù½Ã ã¾Æº¸ÀÚ)
µÎ ¹øÂ° ÀÌÁ¡Àº ¾²·¹µå¸¦ »õ·Î »ý¼ºÇÏÁö ¾Ê°í ÀÌ¹Ì »ý¼ºµÈ ¾²·¹µå¸¦ °¡Á®´Ù°¡ ¾²±â ¶§¹®¿¡ ¾²·¹µå¸¦ »õ·Î »ý¼ºÇÏ´Â °Í¿¡ ºñÇØ ¼Óµµ°¡ ºü¸£´Ù´Â °ÍÀÌ´Ù. ¸Þ¸ð¸®»ó¿¡ Á¸ÀçÇÏ´Â ¾²·¹µå¸¦ ±×³É °¡Á®¿À´Â °ÍÀÌ ´ç¿¬È÷ »õ·Î¿î ¾²·¹µå¸¦ ¸Þ¸ð¸®¿¡ ÇÒ´çÇØ¼ °¡Á®´Ù ¾²´Â °Íº¸´Ù ºü¸¦ °ÍÀÌ´Ù. ¾Õ¼µµ ¾ð±ÞÇßÁö¸¸ ¾²·¹µå´Â »ý¼º ½Ã°£ÀÌ °áÄÚ ÂªÁö ¾Ê´Ù.
¼¼ ¹øÂ° ÀÌÁ¡Àº ThreadPool¿¡ ÀÖ´Â ÀûÀýÈ÷ ¼³Á¤µÈ °³¼ö(Ãʱ⠻ý¼ºÇÒ ¾²·¹µåÀÇ °³¼ö¿Í »ý¼ºÇÒ ¼ö ÀÖ´Â ÃÖ´ëÀÇ ¾²·¹µå °³¼ö)ÀÇ ¾²·¹µå¸¸À» »ç¿ëÇÔÀ¸·Î½á ³Ê¹« ¸¹Àº ¾²·¹µå »ý¼º¿¡ ÀÇÇÑ ½Ã½ºÅÛ ¼º´ÉÀúÇϳª ÃÖ¾ÇÀÇ °æ¿ì OutOfMemoryException À» ÇÇÇÒ ¼ö ÀÖ´Ù´Â °ÍÀÌ´Ù. (1ȸ ±â»ç¿¡¼ °¢°¢ÀÇ ¾²·¹µå´Â ÀڽŸ¸ÀÇ CPU¿Í ½ºÅà ¿µ¿ª(¸Þ¸ð¸®)À» »ç¿ëÇÑ´Ù°í Çß´Ù. Áï, ¾²·¹µå ÀÚü°¡ ¸Þ¸ð¸®¸¦ ¼ÒºñÇÑ´Ù´Â ¸»ÀÌ´Ù)
<source 1> Àº ThreadPool Ŭ·¡½ºÀÇ ÄÚµåÀÌ´Ù. ThreadPoolÀº ÇÁ·Î±×·¥ÀÇ ÃʱâÈ ¶§ ÁöÁ¤ÇÑ °³¼ö ¸¸ÅÀÇ ¾²·¹µå¸¦ ¹Ì¸® ¸¸µé¾î¼ Å¥(¼±ÀÔ¼±Ãâ Å¥ : FIFO Queue)¿¡ ³Ö¾îµÐ´Ù. ±×¸®°í ÇÊ¿äÇÒ ¶§¸¶´Ù Å¥¿¡ Á¢±ÙÇØ¼ ¾²·¹µå¸¦ ²¨³»¼ »ç¿ëÇÏ°í »ç¿ëÀÌ ´Ù ³¡³ª¸é ´Ù½Ã Å¥¿¡ ÀúÀåÇØ¼ ³ªÁß¿¡ ´Ù½Ã Àç»ç¿ëÇϵµ·Ï ÇÏ´Â °ÍÀÌ´Ù. ±×·¯³ª Å¥¿¡ Á¢±ÙÇØ¼ ¾²·¹µå¸¦ ²¨³»·Á°í Çϴµ¥, ¸¸¾à Å¥¿¡ ´ë±âÁßÀÎ ¾²·¹µå°¡ ¾ø´Ù¸é ÇöÀç »ý¼ºµÈ ¾²·¹µåÀÇ °³¼ö¸¦ È®ÀÎÇÏ°í »ý¼ºÇÒ ¼ö ÀÖ´Â ÃÖ´ëÀÇ ¾²·¹µå °³¼ö¸¦ ³ÑÁö ¾Ê¾Ò´Ù¸é »õ·Î »ý¼ºÇؼ °Ç³×ÁÖµµ·Ï ÇÒ °ÍÀÌ´Ù. ¿©±â¼ »ý¼ºÇÒ ¼ö ÀÖ´Â ÃÖ´ëÀÇ ¾²·¹µå °³¼ö¿¡ µµ´ÞÇß´Ù¸é »ç¿ëÁßÀÎ ¾²·¹µå°¡ Å¥¿¡ ¹ÝȯµÇ±â¸¦ ±â´Ù·È´Ù°¡ °Ç³× ÁÙ °ÍÀÌ´Ù. ¶ÇÇÑ Å¥´Â ÇöÀç ´ë±âÁßÀÎ ¾²·¹µåÀÇ °³¼ö°¡ Ãʱ⿡ »ý¼ºÇÑ ¾²·¹µå °³¼öº¸´Ù Ŭ °æ¿ì Å¥·Î ¹ÝȯµÇ´Â ¾²·¹µå¸¦ º¸°üÇÏÁö ¾Ê°í Æó±âÇÒ °ÍÀÌ´Ù. wait º¯¼ö´Â Å¥¿¡ ´ë±âÁßÀÎ ¾²·¹µå°¡ ¾øÀ» °æ¿ì »ý¼ºÇÒ ¼ö ÀÖ´Â ÃÖ´ëÀÇ ¾²·¹µå °³¼ö¸¦ ³ÑÁö ¾Ê¾ÒÀ» °æ¿ì ¹Ù·Î »ý¼ºÇؼ °Ç³×ÁÙÁö ¾Æ´Ï¸é Å¥¿¡ »ç¿ëÀÌ ³¡³ ¾²·¹µå°¡ µé¾î¿À±â¸¦ ±â´Ù¸±Áö¸¦ °áÁ¤ÇÑ´Ù. ¿©±â¼ ÁÖÀÇ ±í°Ô ºÁ¾ßÇÒ Á¡Àº synchronized Ű¿öµåÀÌ´Ù. µ¿±âÈ ¹®Á¦°¡ ¹ß»ýÇÏÁö ¾Êµµ·Ï synchronized¸¦ »ç¿ëÇÏµÇ È¿À²À» À§ÇØ »ç¿ë ºí·ÏÀ» ÃÖ¼ÒÈ ½ÃÄÑ¾ß ÇÑ´Ù.
<source 1> ThreadPool.java
public class ThreadPool {
private static final int MAX_POOLSIZE = 15;
private static int poolSize = 5;
private final ArrayList queue = new ArrayList();
private boolean wait = false
private int total = 0;
private int index = 0;
private AdvancedNioServer server;
public ThreadPool(AdvancedNioServer server) {
this(poolSize, server);
this.server = server;
}
public ThreadPool(int size, AdvancedNioServer server) {
poolSize = size;
for (index = 0; index < poolSize; index++) {
WorkerThread thread = new WorkerThread(this, server);
thread.setName("Worker" + (index + 1));
thread.start();
queue.add(thread);
total++;
}
}
public WorkerThread getThread() {
WorkerThread worker = null
if (queue.size() > 0) {
synchronized (queue) {
worker = (WorkerThread) queue.remove(0);
}
} else {
if (wait) {
return waitQueue();
} else {
if (index < MAX_POOLSIZE) {
worker = new WorkerThread(this, server);
worker.setName("Worker" + (index + 1));
worker.start();
total++;
return worker;
} else {
return waitQueue();
}
}
}
return worker;
}
private synchronized WorkerThread waitQueue() {
while (queue.isEmpty()) {
try {
queue.wait();
} catch (InterruptedException ignored) {
}
}
return (WorkerThread) queue.remove(0);
}
public void putThread(WorkerThread thread) {
if (queue.size() >= poolSize) {
thread = null;
--index;
} else {
synchronized (queue) {
queue.add(thread);
queue.notify();
}
}
}
public boolean isWait() { return wait; }
public void setWait(boolean wait) { this.wait = wait; }
}
Çʿ伺À» ¸ø´À²¸ ThreadPool Á¾·á½Ã Å¥ ¾ÈÀÇ ¸ðµç ¾²·¹µå¸¦ ¸Þ¸ð¸®¿¡¼ ÇØÁ¦ÇÏ´Â ¸Þ¼Òµå¸¦ ¸¸µéÁö´Â ¾Ê¾ÒÁö¸¸ ¸¸¾à ÇÊ¿äÇÏ´Ù¸é °£´ÜÇϹǷΠÁ÷Á¢ À§ ¼Ò½º¿¡ Ãß°¡ÇÏ¸é µÉ °ÍÀÌ´Ù.
ÀÌÁ¦ ThreadPool ¾È¿¡ ÀúÀåµÇ¾î Àç»ç¿ëµÇ°í ¶Ç ¼¹öÀÇ ½ÇÁ¦ ¼ºñ½º¸¦ ´ã´çÇÒ WorkerThread ¸¸ ¸¸µé¾î Ãß°¡Çϸé ThreadPool ÄÄÆ÷³ÍÆ®°¡ ¿Ï¼ºµÈ´Ù. WorkerThread¸¦ ¸¸µé±â Àü¿¡ ¿ì¼± ÀÌ WorkerThread ¿¡¼ »ç¿ëµÉ ByteBufferPool¸¦ ¸¸µé °ÍÀÌ´Ù. ±×¸®°í ¹æÈº® Åë°ú¸¦ À§ÇÑ ¹æ¹ý°ú ÇÁ·ÎÅäÄÝÀ» XML ·Î ÀÌ¿ëÇÏ´Â °Í¿¡ ´ëÇØ Àá½Ã ¼³¸íÇÒ °ÍÀÌ´Ù. ±×·± ÈÄ¿¡ ¸¶Áö¸· Áغñ·Î Àڹ٠ƯÀ¯ÀÇ ¾ð¾îÀû Ư¡À» ÀÌ¿ëÇØ¼ ¼¹öÀÇ ±â´É È®Àå½Ã ´Ù¸¥ ¾ð¾î·Î´Â »ó»óÇÒ ¼öµµ ¾ø´Â ¡°Á×Áö ¾Ê´Â ¼¹ö¡±¸¦ ¸¸µé±â À§ÇÑ Å×Å©´Ð¿¡ ´ëÇØ »ìÆìº¸µµ·Ï ÇϰڴÙ. ±× ÈÄ¿¡ À̰͵éÀ» Á¾ÇÕÇÏ¿© WorkerThread¸¦ ¸¸µé °ÍÀÌ´Ù. ÀÚ, ±×·³ °è¼Ó ÀüÁøÀÌ´Ù.
ÆÄÀÏ ¸Þ¸ð¸®ÀÇ µµÀÔ°ú È¿À²ÀûÀÎ ¸Þ¸ð¸® »ç¿ëÀ» À§ÇÑ ByteBufferPool
ByteBuffer buf = ByteBuffer.allocateDirect(4096);
readCount = sc.read(buf);
if (readCount < 0) {
room.removeElement(sc);
sc.close();
}
buf.flip();
broadcast(buf);
buf.clear();
buf = null;
À§ÀÇ ¼Ò½º´Â 1ȸ ±â»ç¿¡¼ »ç¿ëÇß¾ú´ø ¼Ò½ºÀÇ ÀϺκÐÀÌ´Ù. ¸¸¾à 1ȸ ±â»ç¸¦ Á¦´ë·Î Àоú´Ù¸é À§ ¼Ò½º¿¡ ¸î °¡Áö ¹®Á¦Á¡ÀÌ ÀÖÀ½À» °ð¹Ù·Î ¾Ë ¼ö ÀÖÀ» °ÍÀÌ´Ù. ¾Õ¼ ¼³¸íÇß´ø ThreadPool ÀÇ »óȲ°ú °ÅÀÇ ºñ½ÁÇÏ´Ù.
ù ¹øÂ°´Â ByteBuffer ¸¦ ´Ã Á÷Á¢ ÇÒ´ç, ÇØÁ¦ ÇÏ¸é¼ »ç¿ëÇϱ⠶§¹®¿¡ °¡ºñÁö Ä÷º¼Ç ´ë»óÀÌ Áõ°¡ÇϹǷΠ°¡ºñÁö Ä÷ºÅͰ¡ ÀÚÁÖ È£ÃâµÉ ¼ö ÀÖ´Ù´Â Á¡ÀÌ´Ù.
µÎ ¹øÂ°´Â ä³Î¿¡ write Çϱâ À§Çؼ´Â ¾îÂ÷ÇÇ È¿À²À» À§ÇØ allocateDirect ·Î ¹öÆÛ¸¦ ¸¸µé¾î »ç¿ëÇØ¾ß Çϴµ¥ ÀÌ ³à¼®Àº »ý¼ºÇϴµ¥ ½Ã°£ÀÌ ¿À·¡ °É¸°´Ù´Â Á¡ÀÌ´Ù.
¼¼ ¹øÂ°´Â ¸¸¾à ÀÌ ¼¹ö¿¡ ¼ø°£ÀûÀ¸·Î ³Ê¹« ¸¹Àº ¿äûÀÌ ÇѲ¨¹ø¿¡ ¸ô¸®¸é ¸Þ¸ð¸®¸¸À» ¹öÆÛ·Î »ç¿ëÇϱ⠶§¹®¿¡ OutOfMemoryException À¸·Î ½Ã½ºÅÛÀÌ ´Ù¿îµÉ À§ÇèÀÌ ÀÖ´Ù´Â Á¡ÀÌ´Ù. ¹°·Ð ÈçÈ÷ ¹ß»ýÇÏ´Â »óȲÀº ¾Æ´Ï°í CPU °úºÎÇÏ·Î ¸ÕÀú ¼¹ö°¡ Á×Áö ¾Ê´Â´Ù´Â ÀüÁ¦ ¾È¿¡¼ÀÇ À̾߱âÁö¸¸ ¿ì¸® °³¹ßÀÚµéÀº Ç×»ó ±× ¡°¸¸¾à¡±¿¡ ´ëºñÇØ¾ß ÇÏÁö ¾Ê´Â°¡!
±×·³ À§ÀÇ ¼¼°¡Áö ¹®Á¦¸¦ ¸ðµÎ ÇØ°áÇÒ ¼ö ÀÖ´Â ºñ±ÞÀ» ¼Ò°³ÇϰڴÙ. ¹Ù·Î ByteBufferPool ÀÌ´Ù.
ByteBufferPool Àº ¾Õ¼ ¼³¸íÇÑ ThreadPool °ú ¸¶Âù°¡Áö·Î GoFÀÇ ObjectPool ÆÐÅÏÀ» ÀÌ¿ëÇÑ´Ù.
ÀÌ ³à¼®Àº ÀϹÝÀûÀ¸·Î getMemoryBuffer() ¸¦ ÅëÇØ¼ ¸Þ¸ð¸®¸¦ ¹öÆÛ·Î ÇÒ´çÇØ¼ »ç¿ëÇÑ´Ù. ÇÏÁö¸¸ Á¤ÇØÁø ¸Þ¸ð¸® ¹öÆÛ¸¦ ¸ðµÎ »ç¿ëÇϰí ÀÖÀ» ¶§¿¡´Â ÆÄÀÏÀ» ¹öÆÛ·Î »ç¿ëÇÑ´Ù. ¹°·Ð ÆÄÀÏÀ» ¸Þ¸ð¸®·Î »ç¿ëÇÏ¸é ½ÇÁ¦ ¸Þ¸ð¸®¸¦ »ç¿ëÇÏ´Â °Íº¸´Ù´Â ´À¸®´Ù. ÇÏÁö¸¸ Ŭ¶óÀÌ¾ðÆ®°¡ °ÅÀÇ Â÷À̸¦ ´À³¢Áö ¸øÇÒ ¸¸ÅÀÇ ÆÛÆ÷¸Õ½º°¡ ³ª¿À¹Ç·Î ¼Óµµ ¹®Á¦·Î °í¹ÎÇÏÁö´Â ¸»ÀÚ. ¿ÀÈ÷·Á ¹®Á¦°¡ ÀÖ´Ù¸é ³×Æ®¿öÅ© Æ®·¡ÇÈÀÌ Å¬¶óÀ̾ðÆ®ÀÇ Ã¼°¨ ¼Óµµ¿¡ ´õ ¿µÇâÀ» ÁÙ °ÍÀÌ´Ù. ±×¸®°í ¹«¾ùº¸´Ùµµ ÆÄÀÏÀ» ¹öÆÛ·Î »ç¿ëÇÔÀ¸·Î½á ¸Þ¸ð¸®¸¸À» ¹öÆÛ·Î »ç¿ëÇÒ ¶§ ¹ß»ýÇÒ ¼ö ÀÖ´Â ¸Þ¸ð¸® ºÎÁ·À¸·Î ÀÎÇÑ ½Ã½ºÅÛ ´Ù¿îÀ» ¸·À» ¼ö ÀÖÁö ¾ÊÀº°¡. ¸¶Ä¡ À©µµ¿ì ¿î¿µÃ¼Á¦¿¡¼ Çϵ带 °¡»ó¸Þ¸ð¸®·Î ¼³Á¤Çؼ »ç¿ëÇÏ´Â °Í°ú °°Àº ¿ø¸®´Ù. ¸ÚÁø ³à¼®ÀÌ´Ï Àüü ¼Ò½º¸¦ »ìÆìº¸µµ·Ï ÇÏÀÚ.
<source 2> ByteBufferPool.java
public class ByteBufferPool {
private static final int MEMORY_BLOCKSIZE = 4096;
private static final int FILE_BLOCKSIZE = 10240;
private final ArrayList memoryQueue = new ArrayList();
private final ArrayList fileQueue = new ArrayList();
private boolean wait = false;
public ByteBufferPool(int memorySize, int fileSize, File file) throws IOException {
if (memorySize > 0)
initMemoryBuffer(memorySize);
if (fileSize > 0)
initFileBuffer(fileSize, file);
}
private void initMemoryBuffer(int size) {
int bufferCount = size / MEMORY_BLOCKSIZE;
size = bufferCount * MEMORY_BLOCKSIZE;
ByteBuffer directBuf = ByteBuffer.allocateDirect(size);
divideBuffer(directBuf, MEMORY_BLOCKSIZE, memoryQueue);
}
private void initFileBuffer(int size, File f) throws IOException {
int bufferCount = size / FILE_BLOCKSIZE;
size = bufferCount * FILE_BLOCKSIZE;
RandomAccessFile file = new RandomAccessFile(f, "rw");
try {
file.setLength(size);
ByteBuffer fileBuffer = file.getChannel().map(FileChannel.MapMode.READ_WRITE, 0L, size);
divideBuffer(fileBuffer, FILE_BLOCKSIZE, fileQueue);
} finally {
file.close();
}
}
private void divideBuffer(ByteBuffer buf, int blockSize, ArrayList list) {
int bufferCount = buf.capacity() / blockSize;
int position = 0;
for (int i = 0; i < bufferCount; i++) {
int max = position + blockSize;
buf.limit(max);
list.add(buf.slice());
position = max;
buf.position(position);
}
}
public ByteBuffer getMemoryBuffer() {
return getBuffer(memoryQueue, fileQueue);
}
public ByteBuffer getFileBuffer() {
return getBuffer(fileQueue, memoryQueue);
}
private ByteBuffer getBuffer(ArrayList firstQueue, ArrayList secondQueue) {
ByteBuffer buffer = getBuffer(firstQueue, false);
if (buffer == null) {
buffer = getBuffer(secondQueue, false);
if (buffer == null) {
if (wait)
buffer = getBuffer(firstQueue, true);
else
buffer = ByteBuffer.allocate(MEMORY_BLOCKSIZE);
}
}
return buffer;
}
private ByteBuffer getBuffer(ArrayList queue, boolean wait) {
synchronized (queue) {
if (queue.isEmpty()) {
if (wait) {
try {
queue.wait();
} catch (InterruptedException e) {
return null;
}
} else {
return null;
}
}
return (ByteBuffer) queue.remove(0);
}
}
public void putBuffer(ByteBuffer buffer) {
if (buffer.isDirect()) {
switch (buffer.capacity()) {
case MEMORY_BLOCKSIZE :
putBuffer(buffer, memoryQueue);
break;
case FILE_BLOCKSIZE :
putBuffer(buffer, fileQueue);
break;
}
}
}
private void putBuffer(ByteBuffer buffer, ArrayList queue) {
buffer.clear();
synchronized(queue) {
queue.add(buffer);
queue.notify();
}
}
public synchronized void setWait(boolean wait) { this.wait = wait; }
public synchronized boolean isWait() { return wait; }
}
À§ÀÇ ¼Ò½º¿¡¼ initFileBuffer(int size, File f) ¸Þ¼Òµå¿¡¼ FileChannelÀÌ »ç¿ëµÇ¾ú´Ù. Àü ½Ã°£¿¡ »ìÆìº¸¾Ò´ø SocketChannel À̳ª ServerSocketChannel °ú ´Þ¸® ÆÄÀÏä³ÎÀº SelectableChannelÀ» »ó¼Ó¹ÞÁö ¾Ê´Â´Ù. ±×¸»Àº Áï, ÆÄÀÏä³ÎÀº ³Íºí·°Å· ¸ðµå·Î ¼³Á¤ÇÒ ¼ö ¾ø´Ù´Â ¸»ÀÌ´Ù. ±×·¯³ª ÆÄÀÏä³ÎÀº ±âÁ¸ÀÇ io ·Î ÆÄÀÏÀ» Á¦¾îÇÏ´Â °Íº¸´Ù ¸¹Àº ÀåÁ¡À» °®°í ÀÖ´Ù. ±×Áß Çϳª°¡ ÆÄÀÏä³ÎÀº ÇØ´ç OS ÀÇ ÆÄÀÏ Ä³½¬¸¦ »ç¿ëÇØ¼ ÆÄÀÏ¿¡¼ ÆÄÀÏ·Î Á÷Á¢ Àü´ÞÇÒ ¼ö ÀÖ°í ÆÄÀÏÀÇ Æ¯Á¤ ºÎºÐÀ» Àá±Û¼ö(locking) ÀÖ´Ù´Â Á¡ÀÌ´Ù. ¶ÇÇÑ ByteBufferPool Ŭ·¡½º¿¡¼ »ç¿ëÇßµíÀÌ ÆÄÀÏä³ÎÀº ¸Þ¸ð¸®·Î ÆÄÀÏÀÇ ÀϺΠ¿µ¿ªÀ» ¸ÅÇÎ(mapping) ½Ãų ¼ö ÀÖ´Ù. ÆÄÀÏÀ» ¸Þ¸ð¸®·Î ¸ÅÇÎÇÒ ¶§ ÆÄÀÏÀÇ ³»¿ëÀ» ¸Þ¸ð¸® À§Ä¡µéó·³ »ç¿ëÇϱâ À§ÇØ OS ÀÇ ³×ÀÌÆ¼ºê ¸Þ¸ð¸® °ü¸®ÀÚ¸¦ »ç¿ëÇÑ´Ù. À̶§ È¿À²ÀûÀÎ ¸ÅÇÎÀ» À§ÇØ OS´Â µð½ºÅ© ÆäÀÌ¡ ½Ã½ºÅÛ(disk paging system)À» »ç¿ëÇÑ´Ù. ¾ÖÇø®ÄÉÀÌ¼Ç °üÁ¡¿¡¼´Â ¸ÅÇÎµÈ ÆÄÀÏ ³»¿ëÀº ´ÜÁö ƯÁ¤ ÁÖ¼Ò°ªÀ» °®°í ¸Þ¸ð¸® ¾È¿¡ ÀÏ·Ä·Î Âß ´Ã¾î¼± °ÍÀ¸·Î ÀνÄÇÑ´Ù. Áï, ¸Þ¸ð¸®¿Í º°¹Ý Â÷À̰¡ ¾øÀÌ ÀνÄÇÑ´Ù´Â ¸»ÀÌ´Ù.
ÆÄÀÏä³ÎÀº ÆÄÀÏÀ» ¸Þ¸ð¸®·Î ¸ÅÇÎÇÒ ¶§ ¸Þ¸ð¸® ¿µ¿ªÀ» Ç¥ÇöÇϱâ À§ÇØ MappedByteBuffer¸¦ »ç¿ëÇϴµ¥ À̰ÍÀÇ Å¸ÀÔÀº direct ByteBuffer ÀÌ´Ù. MappedByteBuffer´Â 2°¡Áö Å« ÀåÁ¡ÀÌ Àִµ¥ ù°´Â ¸Þ¸ð¸®¿¡ ¸ÅÇÎµÈ ÆÄÀÏÀ» Àд °ÍÀÌ »ó´çÈ÷ ºü¸£´Ù´Â °ÍÀÌ´Ù. ¹°·Ð ÆÄÀÏÀ» ¼øÂ÷ÀûÀ¸·Î Àд °ÍÀÌ °¡Àå ºü¸£°í ±âÁ¸ io¸¦ »ç¿ëÇÏ´Â °Íº¸´Ù ¼º´ÉÀÌ ¸¹ÀÌ °³¼±µÇÁö¸¸ RandomAccessFile °ú °°ÀÌ ÀÓÀÇÀÇ ºÎºÐ¿¡ Á¢±ÙÇØ¼ Àд °Íµµ ±âÁ¸¿¡ ºñÇØ ¼º´ÉÀÌ ¸¹ÀÌ °³¼±µÇ¾ú´Ù. À̰ÍÀº ±âÁ¸ÀÇ BufferedInputStream À¸·Î ƯÁ¤ ºí·ÏÀ» Àд °Íº¸´Ù ÈξÀ ´õ ¸¹Àº ºÎºÐÀ» ¸Þ¸ð¸® ¾ÈÀ¸·Î ÆÄÀÏÀ» ÆäÀÌÁö(page) ÇØ¼ OS °¡ Àб⠶§¹®ÀÌ´Ù. µÎ ¹øÂ°´Â MappedByteBuffer¸¦ ÀÌ¿ëÇØ¼ ÆÄÀÏÀ» º¸³»´Â °ÍÀÌ »ó´çÈ÷ °£´ÜÇÏ´Ù´Â °ÍÀÌ´Ù.
ByteBufferPool ¼Ò½º¸¦ º¸¸é ³»ºÎÀûÀ¸·Î 2°³ÀÇ Å¥¸¦ ¸¸µç´Ù. ¸Þ¸ð¸® ¹öÆÛ¿Í ÆÄÀÏ ¹öÆÛ¸¦ °ü¸®Çϱâ À§ÇÑ Å¥´Ù. »ý¼ºÀÚ¿¡¼ ÀüÁ¦ÀûÀ¸·Î »ç¿ëÇÒ ¸Þ¸ð¸® Å©±â¿Í ÆÄÀÏ Å©±â ¹× ÆÄÀÏÀ» ¹Þ¾Æ¼ °¢°¢ÀÇ ¹öÆÛ¸¦ ¸¸µç´Ù. wait º¯¼ö´Â Å¥¿¡ ´ë±âÁßÀÎ ¹öÆÛ°¡ ¾øÀ» °æ¿ì ±â´Ù¸±Áö ¿©ºÎ¸¦ °áÁ¤ÇÏ´Â Ç÷¡±×´Ù. ¿ì¸®°¡ Á÷Á¢ÀûÀ¸·Î Á¢±ÙÇØ¼ »ç¿ëÇÒ ¼ö ÀÖ´Â ¸Þ¼Òµå´Â public À¸·Î ¼±¾ðµÈ °ÍµéÀÌ´Ù. ±âº»ÀûÀ¸·Î ¿ì¸®´Â getMemoryBuffer()¸¦ ÅëÇØ¼ ¸Þ¸ð¸® ¹öÆÛ¸¦ »ç¿ëÇÒ °ÍÀÌ´Ù. ¼Ò½º¸¦ º¸¸é ¾Ë ¼ö ÀÖ°ÚÁö¸¸ ¸¸¾à ¸Þ¸ð¸® ¹öÆÛ¸¦ ¾òÀ¸·Á ÇÑ °æ¿ì Å¥¿¡ ´ë±âÁßÀÎ ¸Þ¸ð¸® ¹öÆÛ°¡ ¾øÀ» °æ¿ì¿¡´Â ÆÄÀÏ ¹öÆÛ¸¦ ¾ò±â À§ÇØ ½ÃµµÇÏ°í ±× ¹Ý´ëÀÇ °æ¿ì¿¡´Â ÆÄÀÏ ¹öÆÛ¸¦ ¾ò±â À§ÇØ ½ÃµµÇÒ °ÍÀÌ´Ù. µû¶ó¼ ´ëºÎºÐ ¸Þ¸ð¸® ¹öÆÛ¸¦ ¸ÕÀú »ç¿ëÇÒ °ÍÀ̹ǷΠ¸Þ¸ð¸® ºÎÁ·À¸·Î ÀÎÇÑ ±â´Ù¸²À̳ª ½Ã½ºÅÛ ´Ù¿îÀ» ÆÄÀÏ ¹öÆÛ°¡ Ä¿¹öÇØÁÖ´Â ÇÑ¿¡¼ ¿¹¹æÇÒ ¼ö ÀÖ´Ù.
¹æÈº®À» ¶Õ±â(Firewall Tunneling) À§ÇØ Http Åë½ÅÀ» ÀÌ¿ëÇÏÀÚ
¹æÈº®Àº ÆÐŶ ÇÊÅÍ¿Í ¾ÖÇø®ÄÉÀÌ¼Ç °èÃþ °ÔÀÌÆ®¿þÀÌ(ÇÁ¶ô½Ã)¶ó´Â µÎ°¡Áö ÇüŰ¡ Á¸ÀçÇÑ´Ù. ÆÐŶ ÇÊÅ͸µÀº º¸Åë ¿ÜºÎ¿Í ÀÎÅÍÆäÀ̽º¶ó´Â ¶ó¿ìÅÍÀÇ IP °èÃþ¿¡¼ ÀϾÙ. ÆÐŶ ÇÊÅ͸µ ½Ã¿¡´Â Á¢±Ù Á¦¾î ¸®½ºÆ®¸¦ ÂüÁ¶Çؼ ³»ºÎ È£½ºÆ®·ÎÀÇ ÆÐŶÀ» Çã¿ëÇÒÁö ¿©ºÎ¸¦ °áÁ¤ÇÏ°Ô µÈ´Ù. ¾ÖÇø®ÄÉÀÌ¼Ç °èÃþ °ÔÀÌÆ®¿þÀÌ´Â º¸Åë ÇÁ¶ô½Ã¶ó´Â À̸§À¸·Î ¾Ë·ÁÁ® Àִµ¥ Ŭ¶óÀÌ¾ðÆ®°¡ ¿ÜºÎ·ÎÀÇ Á¢¼ÓÀ» ¸ÎÀ¸·Á ÇÒ ¶§ ³»ºÎ Ŭ¶óÀÌ¾ðÆ®¿Í ¿ÜºÎ ¼ºñ½º¿ÍÀÇ »çÀ̸¦ Áß°èÇÏ´Â ¼¹ö´Ù. º¸ÅëÀº ¿ÜºÎ È£½ºÆ®ÀÇ 80¹ø Æ÷Æ®·Î ³ª°¡´Â ³»ºÎ Ŭ¶óÀ̾ðÆ®ÀÇ Á¢¼ÓÀ» ¹Þ¾ÆµéÀδÙ.
ÇÊÀÚ°¡ ¸¸µç ¼¹ö´Â 4567¹ø Æ÷Æ®¸¦ »ç¿ëÇϴµ¥ ¸¸¾à ÇÁ¶ô½Ã ¼¹ö¸¦ °í·ÁÇÑ´Ù¸é ¼¹öÀÇ Æ÷Æ®¸¦ 80¹øÀ¸·Î ¹Ù²Ù°í Ŭ¶óÀÌ¾ðÆ®¿¡¼ System.setProperties() ¸Þ¼Òµå·Î ÇÁ¶ô½Ã ¼¹ö·Î ¸ÕÀú Á¢¼ÓÇϵµ·Ï ¸¸µé¾î¾ß ÇÑ´Ù. ÇÏÁö¸¸ ÆíÀÇ»ó ÇÊÀÚ´Â ÇÁ¶ô½Ã ¼¹ö¸¦ ÀÌ¿ëÇÑ ¹æÈº®Àº °í·ÁÇÏÁö ¾Ê¾Ò´Ù. ¶ÇÇÑ http ÇÁ·ÎÅäÄÝÀÇ ´Ù¾çÇÑ Äڵ忡 ´ëÇÑ Ã³¸®µµ ÇÏÁö ¾Ê¾Ò´Ù. µû¶ó¼ ±×³É ÀϹÝÀûÀÎ http ÇÁ·ÎÅäÄÝÀ» Çã¿ëÇÏ´Â ¹æÈº® Åë°ú¸¦ À§ÇØ Å¬¶óÀÌ¾ðÆ®¿¡¼ ¼¹ö·Î ¿äûÀ» º¸³¾¶§¿Í ¼¹ö¿¡¼ Ŭ¶óÀÌ¾ðÆ®·Î ÀÀ´äÇÒ ¶§ ´ÙÀ½°ú °°ÀÌ °¢°¢ http ¿äû-ÀÀ´ä Çì´õ¸¸ ºÙ¿©¼ »ç¿ëÇß´Ù.
private static final String HttpRequestHeader = "POST / HTTP/1.1\r\n\r\n";
private static final String HttpResponseHeader = "HTTP/1.1 200 OK\r\n\r\n";
ÇÁ·ÎÅäÄÝ¿¡ XMLÀ» ÀÔÈ÷ÀÚ
ÇÊÀÚ´Â ¼¹ö°£ Åë½Å ¸Þ½ÃÁö¿¡ xmlÀ» »ç¿ëÇß´Ù. ±× ÀÌÀ¯´Â xml Àº »ç¶÷°ú ±â°è(ÄÄÇ»ÅÍ) ¸ðµÎ°¡ ÀÌÇØÇϱ⠽¬¿î ±¸Á¶·Î µÇ¾î ÀÖ°í ÀÌ¹Ì ³Î¸® ¾Ë·ÁÁ® ÀÖµíÀÌ W3C ¿¡ ÀÇÇØ Ç¥ÁØÀÌ µÈ ¾ð¾îÀÌ´Ù. ÇÁ·ÎÅäÄÝ¿¡ xmlÀ» »ç¿ëÇÔÀ¸·Î½á ¾òÀ» ¼ö ÀÌÁ¡Àº ¿©·¯ °¡Áö°¡ ÀÖÁö¸¸ ¿ì¼± ƯÁ¤ ¾ð¾î³ª ½Ã½ºÅÛ¿¡ Á¾¼ÓÀûÀÌÁö ¾Ê´Ù´Â Á¡ÀÌ´Ù. xml ·Î ÀÛ¼ºµÈ ¿ì¸®ÀÇ Åë½Å ÇÁ·ÎÅäÄÝÀº ¾î¶² ¿î¿µÃ¼Á¦³ª ÇÁ·Î±×·¥ ¾ð¾î¿¡¼µµ ½±°Ô ÀÎ½Ä ¹× »ç¿ë °¡´ÉÇÏ´Ù. µÎ ¹øÂ°·Î´Â xml ¾ð¾î ÀÚü°¡ °®´Â È®À强ÀÌ ºÎ·ÏÀ¸·Î µû¶ó¿À±â ¶§¹®ÀÌ´Ù. ¸¸¾à ÇÁ·ÎÅäÄÝÀÇ È®ÀåÀÌ ÇÊ¿äÇÒ ¶§ ÀÌ¹Ì xmlÀ» »ç¿ëÇϰí ÀÖ¾ú´Ù¸é Å« °í¹Î¾øÀÌ ½±°Ô È®Àå ÇÒ ¼ö ÀÖÀ» °ÍÀÌ´Ù. Áï, xml ÀÇ »ç¿ëÀ¸·Î ÇÁ·ÎÅäÄÝÀÇ È®À强°ú À¯¿¬¼ºÀ» °®°Ô µÈ´Ù°í ¸»ÇÒ ¼ö ÀÖ´Ù. ¼¼ ¹øÂ°·Î´Â ¸¸¾à ¿ì¸®ÀÇ Åë½Å ÇÁ·ÎÅäÄÝÀÌ Àß Á¤Àǰ¡ µÇ¾î ÀÖ´Ù¸é SOAP °ú °°ÀÌ Ç¥ÁØÀ¸·Î¼ ÀÎÁ¤µÇ¾î »ç¿ëµÉ ¼ö ÀÖ´Ù´Â °ÍÀÌ´Ù. ¾ÆÁ÷ Ç¥ÁØÀ¸·Î ÀÎÁ¤µÇÁö´Â ¾Ê¾ÒÁö¸¸ jabber ¶ó´Â Ç÷§Æû¿¡¼± ÀÌ¹Ì ¸î ³â ÀüºÎÅÍ Àß ±¸Á¶ÈµÈ ÇÁ·ÎÅäÄÝÀ» Á¤ÀÇÇØ¼ »ç¿ëÇϰí ÀÖ´Ù. ÷¾ðÀÌÁö¸¸ ÇÊÀÚ´Â °³ÀÎÀûÀ¸·Î ÇöÀç IT ¾÷°èÀÇ ½Î¿òÀº ½ÇÁ¦ÀûÀÎ ±â¼úÀ̳ª Àü·« º¸´Ùµµ ÀÚ½ÅÀÇ ±â¼úÀ» Ç¥ÁØÀ¸·Î ¸¸µé±â À§ÇÑ Èû ½Î¿òÀ¸·Î »ý°¢Çϰí ÀÖ´Ù. µû¶ó¼ Ç¥ÁØÀ̶ó´Â ¸»Àº Àû¾îµµ ÇÊÀÚ¿¡°Ô´Â Å« Àǹ̷Π´Ù°¡¿Â´Ù. ¸¶Áö¸·À¸·Î xml Àº ÇÁ·Î±×·¡¹Ö ¾ð¾î¿¡¼ µ¥ÀÌÅÍ·Î »ç¿ëÇϱ⿡ »ó´çÈ÷ ´Ü¼øÇÏ°í °£ÆíÇÏ´Ù. ÇÊÀÚ°¡ ¸¸µç ¼¹ö¿¡¼ »ç¿ëÇÑ Çü½ÄÀÇ ´ÙÀ½ xml ¸Þ½ÃÁö ±¸Á¶¸¦ º¸¸é ¾Ë ¼ö ÀÖ°ÚÁö¸¸ xmlÀ» ¸ð¸£´õ¶óµµ ½±°Ô ÀÌÇØÇÒ ¼ö ÀÖÀ» °ÍÀÌ´Ù.
<?xml version='1.0' encoding='UTF-8'?>
<request>
<command>MessageCommand</command>
<message>¾È³çÇϼ¼¿ä~!</message>
</request>
<?xml version='1.0' encoding='UTF-8'?>
<response>
<message>³×. ¹Ý°©½À´Ï´Ù.</message>
</response>
ÇÊÀÚ´Â ¿¹Á¦·Î ¸¸µç ¼¹ö¿¡¼ ´ÜÁö Ŭ¶óÀÌ¾ðÆ®°¡ º¸³½ ¸Þ½ÃÁö¸¦ ºê·Îµåij½ºÆ® ÇÏ´Â ¹æ½ÄÀ¸·Î¸¸ ±¸ÇöÇßÁö¸¸ ½ÇÁ¦ ¸Þ½ÅÀú µîÀ» ¸¸µç´Ù°í »ý°¢Çϸé xmlÀ» ÀÌ¿ëÇÔÀ¸·Î½á ¾ó¸¶³ª ¸íÄèÇÏ°í Æí¸®ÇÏ°Ô ±¸ÇöÇÒ ¼ö ÀÖÀ»Áö°¡ ÇǺηΠ¿Í ´êÀ¸¸®¶ó »ý°¢ÇÑ´Ù. ¹°·Ð Àü¼Û µ¥ÀÌÅÍÀÇ ¾çÀÌ Á¶±Ý ´õ ¸¹¾ÆÁö¹Ç·Î ¼Óµµ¸é¿¡¼´Â ¾à°£ÀÇ ¼ÕÇØ¸¦ º¼ °ÍÀÌ´Ù. ÇÏÁö¸¸ Çö¸íÇÑ µ¶ÀÚµéÀº xml »ç¿ë½Ã ¾ò´Â ÀåÁ¡¿¡ ÃÊÁ¡À» ¸ÂÃâ°Å¶ó »ý°¢ÇÑ´Ù.
Dynamic Class Loading °ú Command ÆÐÅÏÀ» ÀÌ¿ëÇÏ¿© "¸ØÃßÁö ¾Ê´Â ¼¹ö" ¸¸µé±â
Áö³ 3³â°£ ÀÚ¹Ù¸¦ °øºÎÇÏ¸é¼ ÇÊÀÚ¸¦ °¡Àå ÈïºÐ½ÃÄ×´ø ÀÚ¹ÙÀÇ Æ¯Â¡ÀÌ ¹Ù·Î ÀÚ¹ÙÀÇ Dynamic Class Loading ÀÌ¿´´Ù. ÄÄÆÄÀϽÿ¡ ¾î¶² Ŭ·¡½º°¡ ¾²ÀÏ °ÍÀ̶ó´Â »ç½ÇÀ» ¸ð¸£´õ¶óµµ ·±Å¸ÀÓ¿¡ ÇÊ¿äÇÑ Å¬·¡½º¸¦ ã¾Æ¼ »ç¿ëÇÑ´Ù´Â °ÍÀÌ ¾ó¸¶³ª ÇÊÀÚÀÇ °¡½¿À» µÎ±Ù°Å¸®°Ô Çß¾ú´ÂÁö...
ÀÌÁ¦ºÎÅÍ Command Pattern °ú ¹Ù·Î ÀÚ¹ÙÀÇ ¾ð¾îÀû Ư¡ Áß ÇϳªÀÎ Dynamic Class LoadingÀ» ÀÌ¿ëÇÏ¿© ¼¹ö¸¦ ¸®ºÎÆÃ ÇÏÁö ¾Ê°íµµ ±â´É È®ÀåÀ» ÇÒ ¼ö ÀÖ´Â ¼¹ö¸¦ ¸¸µé±â À§ÇÑ Å×Å©´ÐÀ» ¾Ë¾Æº¼ °ÍÀÌ´Ù. ±â´ëµÇÁö ¾Ê´Â°¡? ÀÚ, ±×·³ ¸¶À½À» °¡´Ùµë°í Á¤½ÅÀ» ÁýÁßÇØ¼ »õ·Î¿î ¼¼»óÀ¸·Î ÇѰÉÀ½ ³ª¾Æ°¡º¸ÀÚ.
¸ÕÀú Dynamic Class Loading °ú Command Pattern ¿¡ ´ëÇØ¼ ¾Ë¾Æº¸°í ÀÌ µÑÀ» ÀÌ¿ëÇØ¼ ¾î¶»°Ô ¿ì¸®ÀÇ ¼¹ö¸¦ ±â´É È®Àå½Ã¿¡ ¡°¸ØÃßÁö ¾Ê´Â ¼¹ö¡±·Î ¸¸µé °ÍÀÎÁö¸¦ »ìÆìº¸µµ·Ï ÇÒ °ÍÀÌ´Ù.
ÀÚ¹Ù´Â JVM(ÀÚ¹Ù °¡»ó ¸Ó½Å) ½ÇÇà½Ã¿¡ java.lang.ClassLoader Ŭ·¡½º¿¡ ÀÇÇØ Äڵ尡 ¸µÅ©µÇ´Â µ¿Àû ¸µÅ© ½Ã½ºÅÛÀÌ´Ù. ¸ðµç Àڹ٠Ŭ·¡½º´Â ¸ðµÎ ¿¹¿Ü ¾øÀÌ ClassLoader¿¡ ÀÇÇØ ÀÚ¹Ù °¡»ó ¸Ó½Å ³»ºÎ·Î ·ÎµåµÈ´Ù. À̶§ 2°¡Áö ¹æ½ÄÀÇ ·ÎµùÀ» »ç¿ëÇϴµ¥ ¹Ù·Î ·ÎµåŸÀÓ µ¿Àû ·Îµù°ú ·±Å¸ÀÓ µ¿Àû ·ÎµùÀÌ´Ù.
¿ì¼± ¿ì¸®°¡ ÀϹÝÀûÀ¸·Î »ç¿ëÇÏ´ø ·ÎµåŸÀÓ µ¿Àû ·ÎµùÀ» º¸µµ·Ï ÇÏÀÚ.
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello, world!");
}
}
À§ÀÇ Äڵ忡¼± JVMÀÌ HelloWorld Ŭ·¡½º¸¦ ·ÎµåÇÒ ¶§, ÀÌ Å¬·¡½º ¾È¿¡¼ System Ŭ·¡½º°¡ »ç¿ëµÈ´Ù°í ÄÄÆÄÀÏ·¯°¡ JVM ¿¡°Ô ¾Ë·ÁÁÖ°í ±×·³ JVMÀº HelloWorld Ŭ·¡½º ·ÎµùÀ» Àá½Ã Áß´ÜÇϰí System Ŭ·¡½º¸¦ ·ÎµùÇÑ ÈÄ¿¡ ´Ù½Ã HelloWorld Ŭ·¡½º¸¦ ·ÎµùÇÑ´Ù. Áï, HelloWorld Ŭ·¡½º ¾È¿¡¼ »ç¿ëµÇ´Â ¸ðµç Ŭ·¡½ºµé(System À̿ܿ¡µµ ¸ðµç Ŭ·¡½º°¡ »ó¼ÓÇÏ´Â Object ¿Í System ¾È¿¡¼ »ç¿ëµÇ´Â PrintStream Ŭ·¡½º)ÀÌ ·ÎµåŸÀÓ¿¡ ¹Ì¸® ·Îµå µÇ´Â °ÍÀÌ´Ù.
ÀÌ¿¡ ¹ÝÇØ ·±Å¸ÀÓ µ¿Àû ·ÎµùÀº ¾î·Á¿î °ÍÀº ¾Æ´ÏÁö¸¸ ¾Õ¼ ¼³¸íÇÑ ·ÎµåŸÀÓ µ¿Àû ·Îµù°ú´Â ¾à°£ ´Ù¸¥ ¹æ½ÄÀ¸·Î »ç¿ëµÈ´Ù. ¾Æ·¡ Äڵ带 º¸°í ¡°¸¹ÀÌ º¸´ø°Çµ¥..¡° ÇÏ°í »ý°¢ÇϽô ºÐµéÀÌ °è½Ç°Å¶ó ÁüÀ۵ȴÙ.
Class cls = Class.forName("java.lang.String");
Object obj = cls.newInstance();
String s = (String) obj;
¡°Class.forName("org.gjt.mm.mysql.Driver")¡± °°ÀÌ JDBC¿¡¼ ƯÁ¤ º¥´õÀÇ JDBC µå¶óÀ̹ö Ŭ·¡½º¸¦ ·ÎµùÇÒ ¶§ ¸¹ÀÌ º¸¾ÒÀ» °ÍÀÌ´Ù. À§ Äڵ忡¼´Â forName() ¸Þ¼Òµå ¾ÈÀÇ ÀÎÀÚ·Î µé¾î¿Â String ¿¡ ÇØ´çÇϴ Ŭ·¡½º¸¦ ·±Å¸Àӽÿ¡ µ¿ÀûÀ¸·Î ·ÎµùÇÑ´Ù. ¼Ò½º¸¦ ÅëÇØ¼µµ ¾Ë ¼ö ÀÖ°ÚÁö¸¸ forName() ¸Þ¼Òµå¸¦ ÅëÇØ ¸®ÅϵǴ °ÍÀº Class ´Ù. À̰ÍÀ» newInstance() ¸Þ¼Òµå¸¦ ÅëÇØ Object ŸÀÔÀ¸·Î ¹Ù²Ù°í À̰ÍÀ» ´Ù½Ã ¿øÇÏ´Â ÀûÀýÇÑ Å¸ÀÔÀ¸·Î ij½ºÆÃÇØ¼ »ç¿ëÇÏ¸é µÇ´Â °ÍÀÌ´Ù. ÀÚ¹ÙÀÇ ·±Å¸ÀÓ µ¿Àû ·ÎµùÀÇ ÇѰ谡 ÀÖ´Ù¸é ¹Ù·Î ·ÎµùÇÒ Å¬·¡½ºÀÇ À̸§(ÆÐŰÁö¸¦ Æ÷ÇÔÇÑ)°ú ½ÇÁ¦ ŸÀÔ(ij½ºÆÃÇÒ Å¸ÀÔ)À» ¾Ë¾Æ¾ß¸¸ ÇÑ´Ù´Â °ÍÀÌ´Ù. ÇÏÁö¸¸ ÀÚ¹ÙÀÇ ·±Å¸ÀÓ µ¿Àû ·ÎµùÀº ±×·± ÇѰ踦 ±Øº¹ÇÏ°íµµ ³²À» ¸¸ÅÀÇ ÃæºÐÇÑ °¡Ä¡°¡ ÀÖ´Ù.
<±×¸² 2>´Â ÇÊÀÚ°¡ ¸¸µç ¿¹Á¦ ¼Ò½º¿¡¼ Command ÆÐÅÏÀÇ »ç¿ë ºÎºÐÀ» º¸¿©ÁÖ°í ÀÖ´Ù. ÀÌ ±â»ç´Â UML À̳ª DP(Design pattern)¸¦ ¼³¸íÇÏ´Â °ÍÀÌ ¸ñÀûÀÌ ¾Æ´Ï±â¿¡ ±×°ÍµéÀÌ ¿¹Á¦ ¼Ò½º¿¡¼ ´Ü¼øÈ÷ ¾î¶»°Ô »ç¿ëµÇ¾ú´ÂÁö¿¡ ÃÊÁ¡À» ¸ÂÃç¼ ¼³¸íÇϰڴÙ. WorkerThread¿¡¼ Ŭ¶óÀÌ¾ðÆ®°¡ ¿äûÇÑ µ¥ÀÌÅ͸¦ ÆÄ½ÌÇØ¼ Ä¿¸Çµå¿Í ¸Þ½ÃÁö¸¦ ºÐ¸®ÇÑ ÈÄ¿¡ Ä¿¸Çµå À̸§°ú °°Àº Ŭ·¡½º°¡ ÀÖ´ÂÁö¸¦ µ¿ÀûÀ¸·Î ã´Â´Ù. ¸¸¾à ÀÖ´Ù¸é ±× Å¬·¡½º¸¦ <±×¸² 2>¿¡¼¿Í °°ÀÌ AbstractCommand Çü½ÄÀÇ »óÀ§ ŸÀÔÀ¸·Î ij½ºÆÃÇØ¼ execute() ¸Þ¼Òµå¸¦ ½ÇÇà½ÃÄÑ ¼ºñ½º¸¦ ÇÑ´Ù. ½ÇÁ¦·Î ¼öÇàµÇ´Â execute() ¸Þ¼Òµå´Â AbstractCommand Ŭ·¡½º¸¦ »ó¼ÓÇÑ ¿ì¸®°¡ µ¿ÀûÀ¸·Î ãÀº ¼ºê Ä¿¸Çµå Ŭ·¡½ºÀÇ execute() ¸Þ¼ÒµåÀÌ´Ù. ¶ÇÇÑ ¿ì¸®´Â ÀÌ·¸°Ô »ç¿ëÇÒ Ä¿¸Çµå °´Ã¼¸¦ Àç»ç¿ëÇϱâ À§ÇØ ¼¹ö¿¡ HashMap ÀúÀå¼Ò¸¦ Çϳª ¸¸µé°í À̰÷¿¡ óÀ½ »ý¼ºµÈ Ä¿¸Çµå Ŭ·¡½º¸¦ ÀúÀåÇØ¼ Àç»ç¿ëÇÏ·Á°í ½ÃµµÇÒ °ÍÀÌ´Ù. ¸¸¾à ÀÌ¹Ì ÀúÀåµÇ¾î ÀÖ´Ù¸é ¾ÕÀ¸·Î´Â HashMap ÀúÀå¼Ò¿¡¼ ÀúÀåµÈ Ä¿¸Çµå¸¦ ²¨³»¿Í¼ »ç¿ëÇÏ°Ô µÈ´Ù. À̶§ ÀϺΠµ¶ÀÚ´Â ¸ÖƼ ¾²·¹µå ȯ°æ¿¡¼ ÇϳªÀÇ °´Ã¼·Î ¼ºñ½º ÇÏ´Â°Ô ¾ÈÀüÇѰ¡ ÇÏ´Â Áú¹®À» ´øÁö½Ã´Â ºÐµµ °è½Ã¸®¶ó »ý°¢µÈ´Ù. ±× ´äÀº ¡°¾ÈÀüÇÏ´Ù¡± ÀÌ´Ù. ¿Ö³ÄÇϸé Ä¿¸Çµå °´Ã¼¸¦ ÀÌ¿ëÇÏ´Â °ÍÀº ¾²·¹µåÀ̱⠶§¹®ÀÌ´Ù. ¾Õ¼µµ ¼³¸íÇßµíÀÌ ¾²·¹µå´Â ÀڽŸ¸ÀÇ ½ºÅà ¿µ¿ª°ú CPU¸¦ Á¡À¯Çؼ »ç¿ëÇÑ´Ù°í Çß´Ù. ¿©±â¼ ÀÚ½ÅÀÇ ½ºÅÃÀ» »ç¿ëÇÑ´Ù´Â ¸»Àº µ¥ÀÌÅÍ Ã³¸®¿¡ ÀÖ¾î ¿©·¯ ¾²·¹µå°¡ µ¿½Ã Á¢±ÙÀ» ÇÑ´Ù°í ÇØµµ ÀÚ½ÅÀÇ ½ºÅþȿ¡¼ °ü·Ã µ¥ÀÌÅ͸¦ ó¸®ÇϹǷΠ¾ÈÀüÇÏ´Ù´Â ¸»ÀÌ´Ù.(¹°·Ð static °°Àº Á¤Àû µ¥ÀÌÅͳª Ŭ·¡½º ¸â¹ö·Î ¼±¾ðµÈ Çʵå´Â ¾²·¹µåµé »çÀÌ¿¡¼ °øÀ¯µÈ´Ù.) Áö±Ý±îÁö °è¼Ó »ìÆìº¸¾ÒµíÀÌ Àç»ç¿ëÇÒ ¼ö ÀÖ´Â °´Ã¼µéÀº ÃÖ´ëÇÑ Àç»ç¿ëÇÒ ¼ö ÀÖ°Ô ÇÏ´Â °ÍÀÌ Áß¿äÇÏ´Ù.

<±×¸² 2> Command ÆÐÅÏÀÇ Class Diagram
½ÇÁ¦ ¼ºñ½º¸¦ ´ã´çÇÏ´Â WorkerThread
ByteBuffer ¿¡ µ¥ÀÌÅ͸¦ ³ÖÀ» ¶§ 2°¡Áö ¹®Á¦Á¡À» ¸ÂÀÌÇÏ°Ô µÈ´Ù. ¹Ù·Î ¹ÙÀÌÆ® ¼ø¼(byte ordering)¿Í ij¸¯ÅÍ º¯È¯(character conversion)ÀÌ´Ù. ByteBuffer ´Â ³»ºÎÀûÀ¸·Î ByteOrder Ŭ·¡½º¸¦ »ç¿ëÇØ¼ ¹ÙÀÌÆ® ¼ø¼¸¦ °áÁ¤ÇÑ´Ù. Big-endian °ú Little-endian µÎ°¡Áö·Î ¼³Á¤ÇÒ ¼ö Àִµ¥ ±âº»ÀûÀ¸·Î ByteBuffer ´Â Big-endianÀ» »ç¿ëÇÑ´Ù. ¸¸¾à ´Ù¸¥ ¾ð¾î³ª À̱âÁ¾ÀÇ ½Ã½ºÅÛ°£ÀÇ Åë½ÅÀ» ÇØ¾ß ÇÑ´Ù¸é ¹ÙÀÌÆ® ¼ø¼¸¦ °í·ÁÇØ¾ß ÇÏÁö¸¸ ÀÚ¹Ù°£ÀÇ Åë½ÅÀ̶ó¸é º°µµÀÇ Ã³¸®°¡ ÇÊ¿äÇÏÁö ¾ÊÀ¸¹Ç·Î ´õ ÀÌ»ó ¾ð±ÞÇÏÁö ¾Ê°Ú´Ù. À̰Ϳ¡ ´ëÇÑ ÀÚ¼¼ÇÑ ³»¿ëÀº ¼±ÀÇ °ø½Ä ¹®¼ µîÀ» Âü°íÇϱ⠹ٶõ´Ù.
ÀÌÁ¦ ij¸¯ÅÍ º¯È¯¿¡ ´ëÇØ À̾߱â ÇÒ Â÷·Ê´Ù. ¿µ¾î±Ç ³ª¶óµéÀÇ °æ¿ì¿¡´Â ÇϳªÀÇ ¹®ÀÚ¸¦ 1¹ÙÀÌÆ®·Î Ç¥ÇöÇϰí ÀÖ°í ¶Ç ´ëºÎºÐÀÇ ¿øÃµ ±â¼úÀÌ ±×µé¿¡°Ô¼ ³ª¿À±â ¶§¹®¿¡ ¿ì¸® ³ª¶ó¿Í °°Àº 2¹ÙÀÌÆ® ¹®È±ÇÀÇ ÇÁ·Î±×·¡¸ÓµéÀº ´Ã ÀÎÄÚµù ¹®Á¦·Î °í½ÉÇÏ°Ô µÈ´Ù. ÇÊÀÚ´Â ¿¹Á¦ ¼Ò½º¿¡¼ xmlÀ» »ç¿ëÇϱ⠶§¹®¿¡ UTF-8 Çü½ÄÀÇ À¯´ÏÄÚµå ÀÎÄÚµùÀ» »ç¿ëÇß´Ù.(¶ÇÇÑ ÀÚ¹Ù¿¡¼´Â µðÆúÆ®·Î À¯´ÏÄڵ带 »ç¿ëÇϱ⠶§¹®¿¡)
º¸Åë ÀÎÄÚµùÀº getBytes() ¸Þ¼Òµå¿¡ ÆÄ¶ó¹ÌÅÍ·Î ÀÎÄÚµù ŸÀÔÀ» ¸í½ÃÇØ¼ »ç¿ëÇÑ´Ù. ¶ÇÇÑ ´ëºÎºÐÀÇ °æ¿ì µðÄÚµùÀº ByteBuffer¸¦ Á÷Á¢ Á¦¾îÇØ¼ »ç¿ëÇÏ°Ô µÇ´Âµ¥ ÀÎÄÚµù ¹× µðÄÚµù »ç¿ë¹ýÀº ´ÙÀ½°ú °°ÀÌ »ó´çÈ÷ °£´ÜÇÏ´Ù. (java.nio.charset ÆÐŰÁö¿¡ Æ÷ÇԵǾî ÀÖÀ½)
Charset charset = Charset.forName("UTF-8");
CharsetEncoder encoder = charset.newEncoder();
// ÀÎÄÚµå ÈÄ ¸®ÅϵǴ ¹öÆÛ´Â non-direct ¹öÆÛÀÓ¿¡ ÁÖÀÇ.
ByteBuffer encodedBuffer = encoder.encode(buffer);
Charset charset = Charset.forName("UTF-8");
CharsetDecoder decoder = charset.newDecoder();
CharBuffer charBuffer = decoder.decode(buffer);
String result = charBuffer.toString();
<source 3>Àº ½ÇÁ¦ ¼ºñ½º¸¦ ´ã´çÇÏ´Â WorkerThread ´Ù. WorkerThread ÀÇ ÇÙ½É ¸Þ¼Òµå´Â requestProcess() ÀÌ´Ù. ÀÌ ¸Þ¼Òµå´Â Ŭ¶óÀ̾ðÆ®ÀÇ ¿äûÀ» ÀÐ¾î¼ http Çì´õ¸¦ Á¦°ÅÇÏ°í ¸öü·Î µþ·Á¿Â xml ºÎºÐÀ» ÆÄ½ÌÇØ¼ Ä¿¸Çµå¿Í ¸Þ½ÃÁö·Î ³ª´«´Ù. À̶§¿¡µµ xmlÀ» ÆÄ½ÌÇÏ´Â SaxHandler Ŭ·¡½º¸¦ ½Ì±ÛÅÏ ÆÐÅÏÀ» »ç¿ëÇØ¼ Àç»ç¿ëÇÑ´Ù. ¼Ò½º¸¦ º¸¸é ¾Ë ¼ö ÀÖ°ÚÁö¸¸ ÆÐÅÏÀ̶ó°í ÇØ¼ ¾î·Æ°Ô »ý°¢ ÇÒ °ÍÀº ¾ø´Ù. ¾Æ¸¶ ÷ºÎµÈ ¼Ò½º¸¦ º¸¸é ½±°Ô ÀÌÇØ°¡ °¥ °ÍÀÌ´Ù.
±× ÈÄ Ä¿¸Çµå¿Í °°Àº À̸§ÀÇ Ä¿¸Çµå Ŭ·¡½º¸¦ µ¿ÀûÀ¸·Î ã´Â´Ù. ±×¸®°í ±× Ŭ·¡½ºÀÇ execute() ¸Þ¼Òµå¸¦ È£ÃâÇØ¼ Ŭ¶óÀÌ¾ðÆ®¿¡°Ô ÀÀ´äÀ» º¸³½´Ù. ÀÌ Ä¿¸Çµå °´Ã¼µµ ¾Õ¼ ¼³¸íÇßµíÀÌ HashMap ¿¡ ÀúÀåÇØ¼ Àç»ç¿ëÇÑ´Ù. ¶ÇÇÑ ¼ºñ½º¸¦ ¸¶Ä¡°í ³ ÈÄ¿¡´Â ByteBufferPool¿¡¼ °¡Á®¿Â ByteBuffer¸¦ finish() ¸Þ¼Òµå¿¡¼ ¹ÝȯÇϰí WorkerThread µµ run() ¸Þ¼Òµå ³¡ºÎºÐ¿¡¼ ThreadPool ·Î ¹ÝȯÇÑ´Ù.(Àüü ¼Ò½º´Â ¡®ÀÌ´ÞÀÇ µð½ºÄÏ¡¯¿¡ ÷ºÎÇß´Ù)
<source 3> WorkerThread.java
public class WorkerThread extends Thread {
...
private void requestProcess(SelectionKey key) throws IOException {
SocketChannel sc = (SocketChannel) key.channel();
ByteBuffer buffer = bufferPool.getMemoryBuffer();
int count;
AbstractCommand command = null;
count = sc.read(buffer);
buffer.flip();
if (count < 0) {
server.removeUser(sc);
sc.close();
bufferPool.putBuffer(buffer);
key.selector().wakeup();
server.info("Ŭ¶óÀÌ¾ðÆ®°¡ Á¢¼ÓÀ» Á¾·áÇß½À´Ï´Ù.");
return;
}
charBuffer = decoder.decode(buffer);
String temp = charBuffer.toString();
byte[] bb = temp.substring(temp.indexOf("\r\n\r\n")).trim().getBytes("UTF-8");
String[] param = parsingXML(bb);
if (param == null) {
finish(buffer);
return;
}
if (server.isContainCommand(param[0])) {
command = server.getCommand(param[0]);
} else {
try {
command = (AbstractCommand) Class.forName(CommandPath + param[0]).newInstance();
} catch (Exception e) {
server.info("¸í·ÉÀ» ¼öÇàÇÏ´Â Ä¿¸Çµå Ŭ·¡½º°¡ Á¸ÀçÇÏ´ÂÁö È®ÀÎÇØº¸¼¼¿ä.");
finish(buffer);
return;
}
if (command == null) {
finish(buffer);
return;
} else {
server.putCommand(param[0], command);
}
}
buffer.clear();
command.execute(server, buffer, param[1]);
finish(buffer);
}
private void finish(ByteBuffer buffer) {
bufferPool.putBuffer(buffer);
key.interestOps(key.interestOps() | SelectionKey.OP_READ);
key.selector().wakeup();
}
private String[] parsingXML(byte[] xml) {
String[] param = null;
ArrayList list = null;
if (xml == null)
return param;
in = new ByteArrayInputStream(xml);
try {
handler = SaxHandler.getInstance();
parser.parse(in, handler);
list = handler.getContents();
} catch (SAXException e) {
server.log(Level.WARNING, "WorkerThread/parsingXML()", e);
} catch (IOException ex) {
server.log(Level.WARNING, "WorkerThread/parsingXML()", ex);
}
param = new String[list.size()];
for (int i = 0; i < list.size(); i++) {
param[i] = (String) list.get(i);
}
handler.clearSaxHandler();
return param;
}
}
Ŭ¶óÀÌ¾ðÆ® ¾ÖÇø®ÄÉÀ̼Ç
ÇÊÀÚ´Â Áö³¹ø¿¡ ¸»Çß´ø °Íó·³ Ŭ¶óÀÌ¾ðÆ®µµ nio(´Ï¿À)¸¦ »ç¿ëÇØ¼ ¸¸µé¾ú´Ù. ¼¹ö¿Í ´Þ¸® Ŭ¶óÀÌ¾ðÆ®´Â ¸¹Àº ¾çÀÇ µ¿½Ã󸮰¡ ÇÊ¿äÇÏÁö ¾ÊÀ¸¹Ç·Î ²À nio¸¦ »ç¿ëÇÒ ÇÊ¿ä´Â ¾ø´Ù. ¹°·Ð nio¸¦ »ç¿ëÇÏ¸é ºí·¯Å·ÀÌ ¾ø¾î Á» ´õ È¿À²ÀûÀÌÁö¸¸ ¸»ÀÌ´Ù. ±×·¯³ª ¾ÈÁ¤¼ºÀ» »ý°¢Çؼ Ŭ¶óÀÌ¾ðÆ®´Â ±âÁ¸ÀÇ ¼ÒÄÏÀ¸·Î ¸¸µå´Â °ÍÀÌ ´õ ÁÁÀ» µí ÇÏ´Ù. ÇÊÀÚ°¡ ½Ã°£ °ü°è»ó Ŭ¶óÀÌ¾ðÆ®´Â °ÅÀÇ ½Å°æÀ» ¾²Áö ¸øÇÏ°í ¿¹Á¦ ¼Ò½º¸¦ ¸¸µé¾úÁö¸¸ ¸¸¾à Á¦´ë·Î µÈ ±¸Á¶¸¦ °®Ãß°Ô ¼³°èÇÑ´Ù¸é Ŭ¶óÀÌ¾ðÆ®µµ <±×¸² 3>°ú °°ÀÌ À̺¥Æ® Á᫐ ¼³°è¸¦ ÇÏ´Â °ÍÀÌ ¹Ù¶÷Á÷ÇÏ´Ù. Áï, ¼¹ö¿¡¼ µµÂøÇÑ ¸ðµç ÀÀ´ä(À̺¥Æ®)À» Ä¿¸Çµå¿Í ¸Þ½ÃÁö µîÀ¸·Î ³ª´²¼ °´Ã¼·Î Æ÷ÀåÇÏ°í ±× °´Ã¼¸¦ Å¥¿¡ ½×¾ÆµÎ°í Å¥¿¡ Á¢±ÙÇÏ´Â º°µµÀÇ ¼ÒºñÀÚ ¾²·¹µå°¡ Áö¼ÓÀûÀ¸·Î Å¥¸¦ üũÇÏ¸é¼ Ã³¸®ÇØ ³ª°¡´Â °ÍÀÌ´Ù. ÀÌ·¸°Ô ÇÏ´Â ÀÌÀ¯´Â Ŭ¶óÀÌ¾ðÆ® ÇÁ·Î±×·¥ÀÌ ¹Ýµå½Ã ¼¹ö¿Í ´Ü ÇϳªÀÇ ¿¬°á¸¸À» °®°Ô µÈ´Ù´Â º¸ÀåÀÌ ¾ø°í ´ë°³ÀÇ °æ¿ì ÁÖ·Î ¿©·¯°³ÀÇ ¿¬°áÀ» À¯ÁöÇÏ´Â °æ¿ì°¡ ¸¹±â ¶§¹®ÀÌ´Ù. ¿¹¸¦ µé¾î MSN ¸Þ½ÅÀú Ŭ¶óÀÌ¾ðÆ®¸¦ °³¹ßÇÑ´Ù°í ÇßÀ» °æ¿ì MSN ¸Þ½ÅÀú´Â ÀÚ½ÅÀÇ »óÅ ¹× ´ëÈ¸í µîÀ» °ü¸®ÇØÁÖ´Â Dispatcher ¼¹ö¿Í ÇϳªÀÇ ¿¬°áÀÌ »ý¼ºµÇ°í Ä£±¸¿Í ´ëȸ¦ ÇÒ ¶§¿¡´Â Switchboard ¼¹ö¿¡ ¿¬°áÇØ¼ 󸮸¦ ÇÑ´Ù. À̶§ ¼¹ö·ÎºÎÅÍ µé¾î¿À´Â ¸ðµç ÀÀ´äÀ» ÇÑ °÷¿¡¼ °ü¸®ÇÏ´Â °ÍÀÌ À¯Áöº¸¼ö³ª È®À强 µî¿¡¼ Á» ´õ À¯¿ëÇϱ⠶§¹®ÀÌ´Ù. µû¶ó¼ ÇÊÀÚ´Â ´ëºÎºÐÀÇ Å¬¶óÀÌ¾ðÆ® ¼ÒÄÏ ¾ÖÇø®ÄÉÀ̼ÇÀÇ °æ¿ì À̺¥Æ® Á᫐ ¼³°è°¡ ÈǸ¢ÇÑ ¸ðµ¨ÀÌ µÉ °ÍÀ̶ó°í »ý°¢ÇÑ´Ù.
±×¸®°í ¼¹ö¿Í °°ÀÌ Command ÆÐÅÏÀ» µµÀÔÇØ¼ ¼Õ½¬¿î È®ÀåÀÌ °¡´ÉÇϵµ·Ï ¸¸µé°í ¿©±â¿¡ ·±Å¸ÀÓ µ¿Àû ·ÎµùÀ» Ãß°¡ÇØ Å¬¶óÀÌ¾ðÆ®¸¦ ¾÷±×·¹À̵å ÇÒ ¶§ UI ºÎºÐÀÌ ¾Æ´Ñ ±â´É»óÀÇ º¯È¶ó¸é ±»ÀÌ ÇÁ·Î±×·¥À» Àç½ÃÀÛ ÇÏÁö ¾Ê¾Æµµ µÇ°Ô Çϸé Á» ´õ ÁÁÀ» °ÍÀÌ´Ù.

<±×¸² 3> À̺¥Æ® Á᫐ ¾ÆÅ°ÅØÃÄ
¿¬À縦 ¸¶Ä¡¸ç...
Áö±Ý±îÁö ¼¹öÀÇ ¼º´ÉÀ» Çâ»ó½Ã۱â À§ÇØ °´Ã¼ÀÇ Àç»ç¿ë¿¡ ÁßÁ¡À» µÎ°í ÇÊ¿äÇÑ °ÍµéÀ» ÇϳªÇϳª¾¿ ¸¸µé¾î Ãß°¡ÇغôÙ. ¼º´ÉÇâ»óÀ» À§ÇØ Æ¯º°ÇÑ ±â¼úÀ» »ç¿ëÇÑ °ÍÀº ¾ø¾ú´Ù. ´ÜÁö Àç»ç¿ëÇÒ ¼ö ÀÖ´Â °´Ã¼µéÀ» Àç»ç¿ëÇÔÀ¸·Î½á Á» ´õ È¿À²ÀûÀ¸·Î ¸Þ¸ð¸®¸¦ »ç¿ëÇÏ°í ¶ÇÇÑ °´Ã¼ÀÇ »ý¼ºÀ¸·Î ÀÎÇÑ ½Ã°£À» Àý¾àÇÒ ¼ö ÀÖ¾ú´Ù. ¶Ç ÀÌ·¸°Ô ÇÔÀ¸·Î½á ´«¿¡ º¸ÀÌÁö´Â ¾ÊÁö¸¸ °¡ºñÁö Ä÷ºÅÍÀÇ È£Ãâµµ Á¶±ÝÀº ÁÙ ÀÏ ¼ö ÀÖ¾î¼ ÆÛÆ÷¸Õ½º Çâ»ó¿¡ µµ¿òÀÌ µÇ¾ú´Ù. Áö±Ý±îÁö ¿ì¸®°¡ °³¹ßÇÑ °ÍµéÀº ¼ÒÇÁÆ®¿þ¾îÀÇ °³¹ß½Ã¿¡ ÇÒ ¼ö ÀÖ´Â Æ©´× ÀÛ¾÷¿¡ ÇØ´çÇÑ´Ù. 2Â÷ÀûÀ¸·Î´Â ½ÇÁ¦·Î ¼ºñ½º¸¦ Çϱâ À§ÇØ JVM ¿É¼ÇÀ» ÀÌ¿ëÇÏ¿© Èü(heap)À̳ª ¾²·¹µå Ãʱ⠽ºÅÃ(stack) »çÀÌÁî µîÀ» ÁöÁ¤ÇÔÀ¸·Î½á ¼º´ÉÀ» °³¼±ÇØ¾ß ÇÒ °ÍÀÌ´Ù. À̰ÍÀº ÃßÈÄ »ç¿ë ¼ºñ½º¸¦ ÇÒ ¶§ ¸¹Àº Å×½ºÆ®¸¦ ÅëÇØ JVMÀ» ÃÖÀûÈÇØ¾ß ÇÏ´Â °ÍÀ¸·Î µ¶ÀںеéÀÇ ¸òÀÌ´Ù. ¸¶Áö¸·À¸·Î µ¶Àڵ鿡°Ô ¹Ù¶÷ÀÌ ÀÖ´Ù¸é ¿ì¼± ÇÊÀÚ°¡ Á¦°øÇÑ ¿¹Á¦ ¼Ò½º¿¡ ±×Ä¡Áö ¸»°í Á» ´õ ³ªÀº äÆÃÀ̳ª ¸Þ½ÅÀú µîÀÇ ¼Ö·ç¼ÇÀ¸·Î ¹ßÀü½ÃÄ×À¸¸é ÇÏ°í ¶Ç ±×°ÍÀ» ³Ñ¾î¼ ºÐ»ê󸮰¡ °¡´ÉÇÑ ´ë¿ë·®ÀÇ È®À强 ÀÖ´Â ¼¹ö¸¦ ¸¸µé¾úÀ¸¸é ÇÑ´Ù. ±×·³ µ¶ÀںеéÀÇ Çà¿îÀ» ºô¸ç 2ȸ¿¡ °ÉÄ£ ±â»ç¸¦ ¸¶¹«¸® ÇϰڴÙ.
Âü°íÀÚ·á
1. Java Nio by Ron Hitchens, 2002 O'reilly
2. Patterns in Java Volume 1, Wiley
3. Server-Based Java Programming, ÀÎÆ÷ºÏ
4. Java Network Programming, ÀÎÆ÷ºÏ
5. http://www.jabber.org
6. http://developer.java.sun.com/developer/technicalArticles/InnerWorkings/JDCPerformTips
7. http://www.javaworld.com/javaworld/jw-09-2001/jw-0907-merlin.html
8. ¼Ò½º ÀÚ·á