ByteBuf
5.1 ByteBuf API
ByteBuf๋ Netty์์ ์ ๊ณตํ๋ ๋ฐ์ดํฐ ์ปจํ ์ด๋๋ก, JDK์ ByteBuffer์ ๋นํด ๋ง์ ์ด์ ์ ์ ๊ณตํฉ๋๋ค. ByteBuf๋ ๋ค์ํ ๋ฐ์ดํฐ ์์ ์ ํจ์จ์ ์ผ๋ก ์ํํ ์ ์๋ API๋ฅผ ์ ๊ณตํฉ๋๋ค.
์ฃผ์ ๋ฉ์๋๋ก๋ ์ฝ๊ธฐ, ์ฐ๊ธฐ, ๊ฒ์ ๋ฑ์ด ์์ผ๋ฉฐ, ์ด๋ฅผ ํตํด ๋ฐ์ดํฐ๋ฅผ ํจ์จ์ ์ผ๋ก ์ฒ๋ฆฌํ ์ ์์ต๋๋ค. ByteBuf๋ ํฌ๋ช ํ ์ ๋ก-์นดํผ์ ์ฉ๋ ํ์ฅ์ฑ ๋ฑ์ ๊ธฐ๋ฅ์ ์ ๊ณตํ์ฌ, ๋คํธ์ํฌ ํ๋ก๊ทธ๋๋ฐ์์์ ์ฑ๋ฅ์ ์ต์ ํํฉ๋๋ค.
5.2 Class ByteBuf
๋ชจ๋ ๋คํธ์ํฌ ํต์ ์ ๋ฐ์ดํธ ์ํ์ค์ ์ด๋์ ํฌํจํ๋ฏ๋ก ํจ์จ์ ์ด๊ณ ์ฌ์ฉํ๊ธฐ ์ฌ์ด ๋ฐ์ดํฐ ๊ตฌ์กฐ๊ฐ ํ์ํฉ๋๋ค. Netty์ ByteBuf ๊ตฌํ์ ์ด๋ฌํ ์๊ตฌ ์ฌํญ์ ์ถฉ์กฑ์ํต๋๋ค.
ByteBuf๋ ๋ฐ์ดํฐ๋ฅผ ์ ๊ทผํ๊ธฐ ์ฝ๊ฒ ํ๊ธฐ ์ํด readerIndex์ writerIndex๋ผ๋ ๋ ๊ฐ์ ๋ณ๋ ์ธ๋ฑ์ค๋ฅผ ์ ์งํฉ๋๋ค. ๋ฐ์ดํฐ๋ฅผ ์ฝ์ ๋๋ง๋ค readerIndex๊ฐ ์ฆ๊ฐํ๊ณ , ๋ฐ์ดํฐ๋ฅผ ์ธ ๋๋ง๋ค writerIndex๊ฐ ์ฆ๊ฐํฉ๋๋ค.
5.2.1 ์๋ ๋ฐฉ์
ByteBuf๋ ์ฝ๊ธฐ์ ์ฐ๊ธฐ๋ฅผ ์ํ ๋ ๊ฐ์ ๋ณ๋ ์ธ๋ฑ์ค๋ฅผ ์ ์งํฉ๋๋ค. ByteBuf์์ ์ฝ์ ๋๋ง๋ค readerIndex๊ฐ ์ฆ๊ฐํ๊ณ , ์ธ ๋๋ง๋ค writerIndex๊ฐ ์ฆ๊ฐํฉ๋๋ค.
์๋ฅผ ๋ค์ด, readerIndex๊ฐ writerIndex์ ๋๋ฌํ๋ฉด ์ฝ์ ์ ์๋ ๋ฐ์ดํฐ์ ๋์ ๋๋ฌํ ๊ฒ์ ๋๋ค.
ByteBuf buffer = ...;
while (buffer.isReadable()) {
System.out.println(buffer.readByte());
}
5.2.2 ByteBuf ์ฌ์ฉ ํจํด
Netty๋ฅผ ์ฌ์ฉํ ๋ ์ฌ๋ฌ ๊ฐ์ง ์ผ๋ฐ์ ์ธ ByteBuf ์ฌ์ฉ ํจํด์ด ์์ต๋๋ค.
ํ ๋ฒํผ
ํ ๊ณต๊ฐ์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋ ๊ฐ์ฅ ์์ฃผ ์ฌ์ฉ๋๋ ByteBuf ํจํด์ ๋๋ค. ์ด ํจํด์ ํ๋ง์ด ์ฌ์ฉ๋์ง ์๋ ์ํฉ์์ ๋น ๋ฅธ ํ ๋น๊ณผ ํด์ ๋ฅผ ์ ๊ณตํฉ๋๋ค.
ByteBuf heapBuf = ...;
if (heapBuf.hasArray()) {
byte[] array = heapBuf.array();
int offset = heapBuf.arrayOffset() + heapBuf.readerIndex();
int length = heapBuf.readableBytes();
handleArray(array, offset, length);
}
์ง์ ๋ฒํผ
์ง์ ๋ฒํผ๋ ๋ค์ดํฐ๋ธ ํธ์ถ์ ํตํด ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ ๋นํ์ฌ ๋คํธ์ํฌ ๋ฐ์ดํฐ ์ ์ก์ ์ด์์ ์ ๋๋ค. ์ง์ ๋ฒํผ์ ์ฃผ์ ๋จ์ ์ ํ ๊ธฐ๋ฐ ๋ฒํผ๋ณด๋ค ํ ๋น ๋ฐ ํด์ ๋น์ฉ์ด ๋ ๋ง์ด ๋ ๋ค๋ ๊ฒ์ ๋๋ค.
ByteBuf directBuf = ...;
if (!directBuf.hasArray()) {
int length = directBuf.readableBytes();
byte[] array = new byte[length];
directBuf.getBytes(directBuf.readerIndex(), array);
handleArray(array, 0, length);
}
์ปดํฌ์งํธ ๋ฒํผ
์ปดํฌ์งํธ ๋ฒํผ๋ ์ฌ๋ฌ ByteBuf์ ์งํฉ์ ๋ทฐ๋ฅผ ์ ๊ณตํ๋ฉฐ, ํ์์ ๋ฐ๋ผ ByteBuf ์ธ์คํด์ค๋ฅผ ์ถ๊ฐ ๋ฐ ์ญ์ ํ ์ ์์ต๋๋ค. CompositeByteBuf๋ ์ฌ๋ฌ ByteBuf๋ฅผ ํ๋๋ก ๊ฒฐํฉํ์ฌ ๋จ์ผ ๋ฒํผ์ฒ๋ผ ์๋ํ๊ฒ ํฉ๋๋ค. ์ด๋ ๋ถ์ฐ๋ ๋ฐ์ดํฐ๋ฅผ ๋จ์ผ ByteBuf๋ก ์ฒ๋ฆฌํด์ผ ํ๋ ๊ฒฝ์ฐ์ ์ ์ฉํฉ๋๋ค.
CompositeByteBuf๋ ์ฑ๋ฅ์ ์ต์ ํํ๊ณ ๋ฉ๋ชจ๋ฆฌ ๋ณต์ฌ๋ฅผ ์ต์ํํ๋ ๋ฐฉ๋ฒ์ ์ ๊ณตํฉ๋๋ค. CompositeByteBuf์ ์ฃผ์ ๋ฉ์๋๋ก๋ addComponent(), removeComponent(), numComponents() ๋ฑ์ด ์์ผ๋ฉฐ, ์ด๋ฅผ ํตํด ๋ฒํผ๋ฅผ ๋์ ์ผ๋ก ๊ด๋ฆฌํ ์ ์์ต๋๋ค.
CompositeByteBuf compBuf = Unpooled.compositeBuffer();
ByteBuf headerBuf = ...;
ByteBuf bodyBuf = ...;
compBuf.addComponents(headerBuf, bodyBuf);
CompositeByteBuf์ ๋ ๋ค๋ฅธ ์ค์ํ ๊ธฐ๋ฅ์ ์ฌ๋ผ์ด์ค(slices)๋ฅผ ์ง์ํ๋ค๋ ๊ฒ์ ๋๋ค. ์ฌ๋ผ์ด์ค๋ ์๋ ๋ฒํผ์ ์ผ๋ถ๋ถ์ ์ฐธ์กฐํ๋ ByteBuf ์ธ์คํด์ค๋ก, ๋ฉ๋ชจ๋ฆฌ ๋ณต์ฌ ์์ด๋ ์๋ ๋ฐ์ดํฐ์ ์ ๊ทผํ ์ ์์ต๋๋ค. ์ด๋ ๋ฉ๋ชจ๋ฆฌ ํจ์จ์ฑ์ ๋์ด๋ ๋ฐ ๋งค์ฐ ์ ์ฉํฉ๋๋ค.
CompositeByteBuf compBuf = Unpooled.compositeBuffer();
ByteBuf headerBuf = ...;
ByteBuf bodyBuf = ...;
compBuf.addComponents(true, headerBuf, bodyBuf);
ByteBuf slice = compBuf.slice(0, headerBuf.readableBytes());
ByteBuf
5.3 Byte-level operations
ByteBuf๋ ๊ธฐ๋ณธ ์ฝ๊ธฐ ๋ฐ ์ฐ๊ธฐ ์์ ์ธ์๋ ๋ฐ์ดํฐ๋ฅผ ์์ ํ๊ธฐ ์ํ ๋ค์ํ ๋ฉ์๋๋ฅผ ์ ๊ณตํฉ๋๋ค.
5.3.1 Domain access indexing
ByteBuf๋ ํน์ ์์ญ ๋ด์์ ๋ฐ์ดํฐ์ ์ ๊ทผํ ์ ์๋ ๋ฉ์๋๋ฅผ ์ ๊ณตํฉ๋๋ค. ์ด๋ฅผ ํตํด ๋ฐ์ดํฐ์ ๋ถ๋ถ ์์ญ์ ๋ํด ์ฝ๊ธฐ์ ์ฐ๊ธฐ ์์ ์ ์ํํ ์ ์์ต๋๋ค.
getBytes(int index, byte[] dst, int dstIndex, int length)์ ๊ฐ์ ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ํน์ ์ธ๋ฑ์ค๋ถํฐ ์์ํ์ฌ ๋ฐ์ดํฐ๋ฅผ ์ฝ๊ฑฐ๋ ์ธ ์ ์์ต๋๋ค.
ByteBuf buffer = ...;
byte[] dst = new byte[buffer.readableBytes()];
buffer.getBytes(buffer.readerIndex(), dst, 0, dst.length);
5.3.2 Sequential (Linear) access indexing
ByteBuf๋ readerIndex์ writerIndex๋ฅผ ์ฌ์ฉํ์ฌ ์์ฐจ์ ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์ฝ๊ณ ์ธ ์ ์์ต๋๋ค. readByte()์ writeByte(byte value) ๋ฉ์๋๋ฅผ ์ฌ์ฉํ์ฌ ์์ฐจ์ ์ผ๋ก ๋ฐ์ดํฐ๋ฅผ ์ฝ๊ฑฐ๋ ์ธ ์ ์์ต๋๋ค.
ByteBuf buffer = ...;
while (buffer.isReadable()) {
System.out.println(buffer.readByte());
}
buffer.writeByte((byte) 'a');
5.3.3 Discardable bytes
ByteBuf๋ ์ฝ๊ธฐ ์์ ์ด ์๋ฃ๋ ๋ฐ์ดํธ๋ฅผ ๋ฒ๋ฆด ์ ์๋ ๋ฉ์๋๋ฅผ ์ ๊ณตํฉ๋๋ค. discardReadBytes() ๋ฉ์๋๋ readerIndex ์ด์ ์ ๋ฐ์ดํธ๋ฅผ ์ ๊ฑฐํ์ฌ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ํ์ํฉ๋๋ค.
ByteBuf buffer = ...;
buffer.readBytes(new byte[buffer.readableBytes()]);
buffer.discardReadBytes();
5.3.4 Readable bytes
ByteBuf์ ์ฝ๊ธฐ ๊ฐ๋ฅํ ๋ฐ์ดํธ ์์ญ์ ์ค์ ๋ฐ์ดํฐ๋ฅผ ์ ์ฅํ๋ ๊ณณ์ ๋๋ค.
์๋ก ํ ๋น๋, ๋ํ๋, ๋๋ ๋ณต์ฌ๋ ๋ฒํผ์ ๊ธฐ๋ณธ readerIndex ๊ฐ์ 0์ ๋๋ค. ์ด๋ฆ์ด read ๋๋ skip์ผ๋ก ์์ํ๋ ๋ชจ๋ ์์ ์ ํ์ฌ readerIndex์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๊ฑฐ๋ ๊ฑด๋๋ฐ๊ณ , ์ฝ์ ๋ฐ์ดํธ ์๋งํผ readerIndex๋ฅผ ์ฆ๊ฐ์ํต๋๋ค.
๋ง์ฝ ํธ์ถ๋ ๋ฉ์๋๊ฐ ByteBuf ์ธ์๋ฅผ ์ฐ๊ธฐ ๋์(buffer)์ผ๋ก ์ฌ์ฉํ๊ณ , ๋์ ์ธ๋ฑ์ค ์ธ์๊ฐ ์๋ ๊ฒฝ์ฐ, ๋์ ๋ฒํผ์ writerIndex๋ ์ฆ๊ฐํฉ๋๋ค. ์๋ฅผ ๋ค์ด:
readBytes(ByteBuf dest);
์ฝ์ ์ ์๋ ๋ฐ์ดํธ๊ฐ ์์ง๋ ์ํ์์ ๋ฒํผ์์ ์ฝ์ผ๋ ค ํ๋ฉด, IndexOutOfBoundsException์ด ๋ฐ์ํฉ๋๋ค.
ByteBuf buffer = ...;
while (buffer.isReadable()) {
System.out.println(buffer.readByte());
}
5.3.5 Writable bytes
ByteBuf์ ์ฐ๊ธฐ ๊ฐ๋ฅํ ๋ฐ์ดํธ ์์ญ์ ์ ์๋์ง ์์ ๋ด์ฉ์ ๋ฉ๋ชจ๋ฆฌ ์์ญ์ผ๋ก, ์ฐ๊ธฐ ์์ ์ ์ํด ์ค๋น๋ ์ํ์ ๋๋ค.
์๋ก ํ ๋น๋ ๋ฒํผ์ ๊ธฐ๋ณธ writerIndex ๊ฐ์ 0์ ๋๋ค. ์ด๋ฆ์ด write๋ก ์์ํ๋ ๋ชจ๋ ์์ ์ ํ์ฌ writerIndex์์ ๋ฐ์ดํฐ๋ฅผ ์ฐ๊ธฐ ์์ํ๊ณ , ์ด ๋ฐ์ดํธ ์๋งํผ writerIndex๋ฅผ ์ฆ๊ฐ์ํต๋๋ค.
๋ง์ฝ ์ฐ๊ธฐ ์์ ์ ๋์์ด ByteBuf์ด๊ณ , ์์ค ์ธ๋ฑ์ค๊ฐ ์ง์ ๋์ง ์์ ๊ฒฝ์ฐ, ์์ค ๋ฒํผ์ readerIndex๋ ๋์ผํ ์๋งํผ ์ฆ๊ฐํฉ๋๋ค.
๋ค์์ ๋๋ค ์ ์ ๊ฐ์ผ๋ก ๋ฒํผ์ ์ฐ๊ธฐ ๊ฐ๋ฅํ ๋ฐ์ดํธ๋ฅผ ์ฑ์ฐ๋ ์์ ์ ๋๋ค.
ByteBuf buffer = ...;
while (buffer.writableBytes() >= 4) {
buffer.writeInt(random.nextInt());
}
5.3.6 Index management
JDK์ InputStream์ ํ์ฌ ์์น๋ฅผ ํ์ํ๊ณ ํด๋น ์์น๋ก ์คํธ๋ฆผ์ ์ฌ์ค์ ํ๊ธฐ ์ํด mark(int readlimit) ๋ฐ reset() ๋ฉ์๋๋ฅผ ์ ์ํฉ๋๋ค.
์ด์ ์ ์ฌํ๊ฒ ByteBuf์์๋ markReaderIndex(), markWriterIndex(), resetReaderIndex(), resetWriterIndex() ๋ฉ์๋๋ฅผ ํธ์ถํ์ฌ readerIndex์ writerIndex๋ฅผ ์ค์ ํ๊ณ ์ฌ์ค์ ํ ์ ์์ต๋๋ค.
์ด ๋ฉ์๋๋ค์ InputStream์ ํธ์ถ๊ณผ ์ ์ฌํ์ง๋ง, ํ์๊ฐ ๋ฌดํจํ๋๋ ์์ ์ ์ง์ ํ๋ readlimit ๋งค๊ฐ๋ณ์๋ ์์ต๋๋ค.
๋ํ readerIndex(int) ๋๋ writerIndex(int) ๋ฉ์๋๋ฅผ ํธ์ถํ์ฌ ์ธ๋ฑ์ค๋ฅผ ์ง์ ๋ ์์น๋ก ์ด๋ํ ์ ์์ต๋๋ค. ์ธ๋ฑ์ค๋ฅผ ์ ํจํ์ง ์์ ์์น๋ก ์ค์ ํ๋ ค๊ณ ํ๋ฉด IndexOutOfBoundsException์ด ๋ฐ์ํฉ๋๋ค.
clear() ๋ฉ์๋๋ฅผ ํธ์ถํ์ฌ readerIndex์ writerIndex๋ฅผ ๋ชจ๋ 0์ผ๋ก ์ค์ ํ ์ ์์ต๋๋ค. ์ด๋ ๋ฉ๋ชจ๋ฆฌ ๋ด์ฉ์ ์ง์ฐ์ง๋ ์์ง๋ง ์ธ๋ฑ์ค๋ฅผ ์ฌ์ค์ ํฉ๋๋ค. clear() ๋ฉ์๋๋ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋ณต์ฌํ์ง ์๊ณ ์ธ๋ฑ์ค๋ฅผ ์ฌ์ค์ ํ๋ฏ๋ก discardReadBytes()๋ณด๋ค ํจ์ฌ ์ ๋ ดํฉ๋๋ค.
5.3.7 Search operations
ByteBuf์์ ์ง์ ๋ ๊ฐ์ ์ธ๋ฑ์ค๋ฅผ ๊ฒฐ์ ํ๋ ๋ช ๊ฐ์ง ๋ฐฉ๋ฒ์ด ์์ต๋๋ค. ๊ฐ์ฅ ๊ฐ๋จํ ๋ฐฉ๋ฒ์ indexOf() ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ ๊ฒ์ ๋๋ค.
๋ ๋ณต์กํ ๊ฒ์์ ByteBufProcessor ์ธ์๋ฅผ ์ฌ์ฉํ๋ ๋ฉ์๋๋ฅผ ํตํด ์ํํ ์ ์์ต๋๋ค. ์ด ์ธํฐํ์ด์ค๋ ํ๋์ ๋ฉ์๋ boolean process(byte value)๋ฅผ ์ ์ํ๋ฉฐ, ์ ๋ ฅ ๊ฐ์ด ์ฐพ๊ณ ์ ํ๋ ๊ฐ์ธ์ง ์ฌ๋ถ๋ฅผ ๋ณด๊ณ ํฉ๋๋ค.
๋ค์ ์์ ๋ ์บ๋ฆฌ์ง ๋ฆฌํด ๋ฌธ์(\r)๋ฅผ ์ฐพ๊ธฐ ์ํด ByteBufProcessor๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ์ค๋๋ค.
ByteBuf buffer = ...;
int index = buffer.forEachByte(ByteBufProcessor.FIND_CR);
5.3.8 Derived buffers
ํ์ ๋ฒํผ๋ ByteBuf์ ๋ด์ฉ์ ํน์ํ ๋ฐฉ์์ผ๋ก ๋ํ๋ด๋ ๋ทฐ๋ฅผ ์ ๊ณตํฉ๋๋ค. ์ด๋ฌํ ๋ทฐ๋ ๋ค์ ๋ฉ์๋๋ค์ ํตํด ์์ฑ๋ฉ๋๋ค:
duplicate()
slice()
slice(int, int)
Unpooled.unmodifiableBuffer(...)
order(ByteOrder)
readSlice(int)
๊ฐ ๋ฉ์๋๋ ์์ฒด reader, writer ๋ฐ ๋ง์ปค ์ธ๋ฑ์ค๋ฅผ ๊ฐ์ง ์๋ก์ด ByteBuf ์ธ์คํด์ค๋ฅผ ๋ฐํํฉ๋๋ค. ๋ด๋ถ ์ ์ฅ์๋ JDK ByteBuffer์ ๋ง์ฐฌ๊ฐ์ง๋ก ๊ณต์ ๋ฉ๋๋ค.
์ด๋ ํ์ ๋ฒํผ๋ฅผ ์์ฑํ๋ ๋น์ฉ์ด ์ ๋ ดํ๋ค๋ ๊ฒ์ ์๋ฏธํ์ง๋ง, ๋ด์ฉ์ ์์ ํ๋ฉด ์๋ณธ ์ธ์คํด์ค๋ ์์ ๋๋ค๋ ์ ์ ์ฃผ์ํด์ผ ํฉ๋๋ค.
๋ค์ ์์ ๋ slice(int, int)์ ์ฌ์ฉํ์ฌ ByteBuf ์ธ๊ทธ๋จผํธ๋ฅผ ์์ ํ๋ ๋ฐฉ๋ฒ์ ๋ณด์ฌ์ค๋๋ค.
Charset utf8 = Charset.forName("UTF-8");
ByteBuf buf = Unpooled.copiedBuffer("Netty in Action rocks!", utf8);
ByteBuf sliced = buf.slice(0, 14);
System.out.println(sliced.toString(utf8));
buf.setByte(0, (byte)'J');
assert buf.getByte(0) == sliced.getByte(0);
์ด์ ByteBuf ์ธ๊ทธ๋จผํธ์ ๋ณต์ฌ๋ณธ์ด ์๋ณธ๊ณผ ์ด๋ป๊ฒ ๋ค๋ฅธ์ง ๋ณด๊ฒ ์ต๋๋ค.
Charset utf8 = Charset.forName("UTF-8");
ByteBuf buf = Unpooled.copiedBuffer("Netty in Action rocks!", utf8);
ByteBuf copy = buf.copy(0, 14);
System.out.println(copy.toString(utf8));
buf.setByte(0, (byte)'J');
assert buf.getByte(0) != copy.getByte(0);
5.3.9 Read/write operations
์ฝ๊ธฐ/์ฐ๊ธฐ ์์ ์๋ ๋ ๊ฐ์ง ๋ฒ์ฃผ๊ฐ ์์ต๋๋ค:
์ง์ ๋ ์ธ๋ฑ์ค์์ ์์ํ์ฌ ์ธ๋ฑ์ค๋ฅผ ๋ณ๊ฒฝํ์ง ์๋ get() ๋ฐ set() ์์
์ง์ ๋ ์ธ๋ฑ์ค์์ ์์ํ์ฌ ์ ๊ทผํ ๋ฐ์ดํธ ์๋งํผ ์ธ๋ฑ์ค๋ฅผ ์กฐ์ ํ๋ read() ๋ฐ write() ์์
๋ค์ ์์ ๋ get() ๋ฐ set() ๋ฉ์๋์ ์ฌ์ฉ์ ๋ณด์ฌ์ฃผ๋ฉฐ, ์ด ๋ฉ์๋๋ค์ด ์ฝ๊ธฐ ๋ฐ ์ฐ๊ธฐ ์ธ๋ฑ์ค๋ฅผ ๋ณ๊ฒฝํ์ง ์๋๋ค๋ ๊ฒ์ ๋ณด์ฌ์ค๋๋ค.
Charset utf8 = Charset.forName("UTF-8");
ByteBuf buf = Unpooled.copiedBuffer("Netty in Action rocks!", utf8);
System.out.println((char)buf.getByte(0));
int readerIndex = buf.readerIndex();
int writerIndex = buf.writerIndex();
buf.setByte(0, (byte)'B');
System.out.println((char)buf.getByte(0));
assert readerIndex == buf.readerIndex();
assert writerIndex == buf.writerIndex();
์ด์ read() ๋ฐ write() ์์ ์ ์ดํด๋ณด๊ฒ ์ต๋๋ค. ์ด ๋ฉ์๋๋ค์ ํ์ฌ readerIndex ๋๋ writerIndex์์ ์๋ํฉ๋๋ค. ์ด๋ฌํ ๋ฉ์๋๋ ByteBuf๋ฅผ ์คํธ๋ฆผ์ฒ๋ผ ์ฝ๊ธฐ ์ํด ์ฌ์ฉ๋ฉ๋๋ค.
๋๋ถ๋ถ์ read() ๋ฉ์๋๋ ๋์ํ๋ write() ๋ฉ์๋๋ฅผ ๊ฐ์ง๊ณ ์์ผ๋ฉฐ, ByteBuf์ ๋ฐ์ดํฐ๋ฅผ ์ถ๊ฐํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค.
๋ค์ ์์ ๋ read() ๋ฐ write() ๋ฉ์๋์ ์ฌ์ฉ์ ๋ณด์ฌ์ค๋๋ค.
Charset utf8 = Charset.forName("UTF-8");
ByteBuf buf = Unpooled.copiedBuffer("Netty in Action rocks!", utf8);
System.out.println((char)buf.readByte());
int readerIndex = buf.readerIndex();
int writerIndex = buf.writerIndex();
buf.writeByte((byte)'?');
assert readerIndex == buf.readerIndex();
assert writerIndex != buf.writerIndex();
5.3.10 More operations
๋ค์ ํ๋ ByteBuf์์ ์ ๊ณตํ๋ ์ถ๊ฐ์ ์ธ ์ ์ฉํ ์์ ๋ค์ ๋์ดํฉ๋๋ค.
isReadable()
์ต์ํ ํ๋์ ๋ฐ์ดํธ๋ฅผ ์ฝ์ ์ ์์ผ๋ฉด true๋ฅผ ๋ฐํํฉ๋๋ค.
isWritable()
์ต์ํ ํ๋์ ๋ฐ์ดํธ๋ฅผ ์ธ ์ ์์ผ๋ฉด true๋ฅผ ๋ฐํํฉ๋๋ค.
readableBytes()
์ฝ์ ์ ์๋ ๋ฐ์ดํธ ์๋ฅผ ๋ฐํํฉ๋๋ค.
writableBytes()
์ธ ์ ์๋ ๋ฐ์ดํธ ์๋ฅผ ๋ฐํํฉ๋๋ค.
capacity()
ByteBuf๊ฐ ๋ณด์ ํ ์ ์๋ ๋ฐ์ดํธ ์๋ฅผ ๋ฐํํฉ๋๋ค.
maxCapacity()
ByteBuf๊ฐ ๋ณด์ ํ ์ ์๋ ์ต๋ ๋ฐ์ดํธ ์๋ฅผ ๋ฐํํฉ๋๋ค.
hasArray()
ByteBuf๊ฐ ๋ฐ์ดํธ ๋ฐฐ์ด๋ก ์ง์๋๋ฉด true๋ฅผ ๋ฐํํฉ๋๋ค.
array()
ByteBuf๊ฐ ๋ฐ์ดํธ ๋ฐฐ์ด๋ก ์ง์๋๋ฉด ๋ฐ์ดํธ ๋ฐฐ์ด์ ๋ฐํํ๊ณ , ๊ทธ๋ ์ง ์์ผ๋ฉด UnsupportedOperationException์ ๋ฐ์์ํต๋๋ค.
5.4 Interface ByteBufHolder
์ฐ๋ฆฌ๋ ์ข ์ข ์ค์ ๋ฐ์ดํฐ ํ์ด๋ก๋ ์ธ์๋ ๋ค์ํ ์์ฑ ๊ฐ์ ์ ์ฅํด์ผ ํ ํ์๊ฐ ์์ต๋๋ค. HTTP ์๋ต์ ์ข์ ์๋ก, ๋ฐ์ดํธ๋ก ํํ๋ ์ฝํ ์ธ ์ธ์๋ ์ํ ์ฝ๋, ์ฟ ํค ๋ฑ์ด ์์ต๋๋ค.
Netty๋ ์ด๋ฌํ ์ผ๋ฐ์ ์ธ ์ฌ์ฉ ์ฌ๋ก๋ฅผ ์ฒ๋ฆฌํ๊ธฐ ์ํด ByteBufHolder๋ฅผ ์ ๊ณตํฉ๋๋ค. ByteBufHolder๋ ๋ํ Netty์ ๊ณ ๊ธ ๊ธฐ๋ฅ์ธ ๋ฒํผ ํ๋ง์ ์ง์ํ๋ฉฐ, ํ์ํ ๊ฒฝ์ฐ ByteBuf๋ฅผ ํ์์ ๋น๋ ค์ค๊ณ ์๋์ผ๋ก ํด์ ํ ์ ์์ต๋๋ค.
ByteBufHolder๋ ๊ธฐ๋ณธ ๋ฐ์ดํฐ์ ์ฐธ์กฐ ์นด์ดํ ์ ์ ๊ทผํ๊ธฐ ์ํ ๋ช ๊ฐ์ง ๋ฉ์๋๋ฅผ ์ ๊ณตํฉ๋๋ค. Table 5.6์ ReferenceCounted์์ ์์๋ฐ์ ๋ฉ์๋๋ค์ ์ ์ธํ ByteBufHolder์ ๋ฉ์๋๋ค์ ๋์ดํฉ๋๋ค.
content()
ByteBufHolder๊ฐ ๋ณด์ ํ ByteBuf๋ฅผ ๋ฐํํฉ๋๋ค.
copy()
ํฌํจ๋ ByteBuf์ ๋ฐ์ดํฐ๋ฅผ ํฌํจํ์ฌ ์ด ByteBufHolder์ ๊น์ ๋ณต์ฌ๋ณธ์ ๋ฐํํฉ๋๋ค.
duplicate()
ํฌํจ๋ ByteBuf์ ๋ฐ์ดํฐ๋ฅผ ๊ณต์ ํ๋ ์์ ๋ณต์ฌ๋ณธ์ ๋ฐํํฉ๋๋ค.
ByteBufHolder๋ ํ์ด๋ก๋๋ฅผ ByteBuf์ ์ ์ฅํ๋ ๋ฉ์์ง ๊ฐ์ฒด๋ฅผ ๊ตฌํํ๋ ค๋ ๊ฒฝ์ฐ ์ข์ ์ ํ์ ๋๋ค.
5.5 ByteBuf allocation
์ด ์น์ ์์๋ ByteBuf ์ธ์คํด์ค๋ฅผ ๊ด๋ฆฌํ๋ ๋ฐฉ๋ฒ์ ์ค๋ช ํฉ๋๋ค.
5.5.1 On-demand: interface ByteBufAllocator
๋ฉ๋ชจ๋ฆฌ ํ ๋น ๋ฐ ํด์ ์ ์ค๋ฒํค๋๋ฅผ ์ค์ด๊ธฐ ์ํด Netty๋ ByteBufAllocator ์ธํฐํ์ด์ค๋ฅผ ํตํด ํ๋ง์ ๊ตฌํํฉ๋๋ค. ํ๋ง์ ์ฌ์ฉ์ ์ ํ๋ฆฌ์ผ์ด์ ๋ณ ๊ฒฐ์ ์ด๋ฉฐ ByteBuf API์ ์๋ฌด๋ฐ ์ํฅ์ ๋ฏธ์น์ง ์์ต๋๋ค.
Channel(๊ฐ Channel์ ๊ณ ์ ํ ์ธ์คํด์ค๋ฅผ ๊ฐ์ง ์ ์์)์ด๋ ChannelHandler์ ๋ฐ์ธ๋ฉ๋ ChannelHandlerContext์์ ByteBufAllocator๋ฅผ ์ฐธ์กฐํ ์ ์์ต๋๋ค.
Channel channel = ...;
ByteBufAllocator allocator = channel.alloc();
....
ChannelHandlerContext ctx = ...;
ByteBufAllocator allocator2 = ctx.alloc();
Netty๋ ByteBufAllocator์ ๋ ๊ฐ์ง ๊ตฌํ์ ์ ๊ณตํฉ๋๋ค
PooledByteBufAllocator๋ ByteBuf ์ธ์คํด์ค๋ฅผ ํ๋งํ์ฌ ์ฑ๋ฅ์ ๊ฐ์ ํ๊ณ ๋ฉ๋ชจ๋ฆฌ ๋จํธํ๋ฅผ ์ต์ํํฉ๋๋ค. ์ด ๊ตฌํ์ ์ฌ๋ฌ ์ต์ ์ด์ ์ฒด์ ์์ ์ฑํ๋ ๋ฉ๋ชจ๋ฆฌ ํ ๋น ๋ฐฉ๋ฒ์ธ jemalloc์ ์ฌ์ฉํฉ๋๋ค.
UnpooledByteBufAllocator๋ ByteBuf ์ธ์คํด์ค๋ฅผ ํ๋งํ์ง ์์ผ๋ฉฐ ํธ์ถ๋ ๋๋ง๋ค ์ ์ธ์คํด์ค๋ฅผ ๋ฐํํฉ๋๋ค.
Netty๋ ๊ธฐ๋ณธ์ ์ผ๋ก PooledByteBufAllocator๋ฅผ ์ฌ์ฉํ์ง๋ง, ChannelConfig API๋ฅผ ํตํด ๋๋ ์ ํ๋ฆฌ์ผ์ด์ ๋ถํธ์คํธ๋ฉ ์ ๋ค๋ฅธ ํ ๋น์๋ฅผ ์ง์ ํ์ฌ ์ฝ๊ฒ ๋ณ๊ฒฝํ ์ ์์ต๋๋ค.
5.5.2 Unpooled buffers
ByteBufAllocator์ ๋ํ ์ฐธ์กฐ๊ฐ ์๋ ์ํฉ๋ ์์ ์ ์์ต๋๋ค. ์ด ๊ฒฝ์ฐ Netty๋ Unpooled๋ผ๋ ์ ํธ๋ฆฌํฐ ํด๋์ค๋ฅผ ์ ๊ณตํ์ฌ ํ๋ง๋์ง ์์ ByteBuf ์ธ์คํด์ค๋ฅผ ์์ฑํ๋ ์ ์ ํฌํผ ๋ฉ์๋๋ฅผ ์ ๊ณตํฉ๋๋ค.
buffer()
ํ ๊ธฐ๋ฐ ์ ์ฅ์๋ฅผ ๊ฐ์ง ํ๋ง๋์ง ์์ ByteBuf๋ฅผ ๋ฐํํฉ๋๋ค.
buffer(int initialCapacity)
์ด๊ธฐ ์ฉ๋์ ๊ฐ์ง ํ ๊ธฐ๋ฐ ํ๋ง๋์ง ์์ ByteBuf๋ฅผ ๋ฐํํฉ๋๋ค.
buffer(int initialCapacity, int maxCapacity)
์ด๊ธฐ ์ฉ๋๊ณผ ์ต๋ ์ฉ๋์ ๊ฐ์ง ํ ๊ธฐ๋ฐ ํ๋ง๋์ง ์์ ByteBuf๋ฅผ ๋ฐํํฉ๋๋ค.
directBuffer()
์ง์ ์ ์ฅ์๋ฅผ ๊ฐ์ง ํ๋ง๋์ง ์์ ByteBuf๋ฅผ ๋ฐํํฉ๋๋ค.
directBuffer(int initialCapacity)
์ด๊ธฐ ์ฉ๋์ ๊ฐ์ง ์ง์ ํ๋ง๋์ง ์์ ByteBuf๋ฅผ ๋ฐํํฉ๋๋ค.
directBuffer(int initialCapacity, int maxCapacity)
์ด๊ธฐ ์ฉ๋๊ณผ ์ต๋ ์ฉ๋์ ๊ฐ์ง ์ง์ ํ๋ง๋์ง ์์ ByteBuf๋ฅผ ๋ฐํํฉ๋๋ค.
wrappedBuffer()
์ฃผ์ด์ง ๋ฐ์ดํฐ๋ฅผ ๋ํํ๋ ByteBuf๋ฅผ ๋ฐํํฉ๋๋ค.
copiedBuffer()
์ฃผ์ด์ง ๋ฐ์ดํฐ๋ฅผ ๋ณต์ฌํ๋ ByteBuf๋ฅผ ๋ฐํํฉ๋๋ค.
Unpooled ํด๋์ค๋ ByteBuf๋ฅผ ๋คํธ์ํฌ ํ๋ก์ ํธ ์ธ์ ๊ณ ์ฑ๋ฅ ํ์ฅ ๊ฐ๋ฅํ ๋ฒํผ API๊ฐ ํ์ํ ํ๋ก์ ํธ์์๋ ์ฌ์ฉํ ์ ์๊ฒ ํฉ๋๋ค. ์ด๋ฌํ ํ๋ก์ ํธ๋ Netty์ ๋ค๋ฅธ ๊ตฌ์ฑ ์์๋ฅผ ํ์๋ก ํ์ง ์์ต๋๋ค.
5.5.3 Class ByteBufUtil
ByteBufUtil์ ByteBuf๋ฅผ ์กฐ์ํ๊ธฐ ์ํ ์ ์ ํฌํผ ๋ฉ์๋๋ฅผ ์ ๊ณตํฉ๋๋ค.
๊ฐ์ฅ ์ ์ฉํ ์ ์ ๋ฉ์๋๋ ์๋ง๋ hexdump()์ผ ๊ฒ์ ๋๋ค. ์ด ๋ฉ์๋๋ ByteBuf์ ๋ด์ฉ์ 16์ง์๋ก ์ถ๋ ฅํฉ๋๋ค. ์ด๋ ๋๋ฒ๊น ๋ชฉ์ ์ผ๋ก ByteBuf์ ๋ด์ฉ์ ๋ก๊น ํ๋ ์ํฉ ๋ฑ์์ ์ ์ฉํฉ๋๋ค. 16์ง์ ํํ์ ๋ฐ์ดํธ ๊ฐ์ ์ง์ ๋ํ๋ด๋ ๊ฒ๋ณด๋ค ๋ ์ ์ฉํ ๋ก๊ทธ ํญ๋ชฉ์ ์ ๊ณตํ๋ฉฐ, ์ค์ ๋ฐ์ดํธ ํํ์ผ๋ก ์ฝ๊ฒ ๋ณํ๋ ์ ์์ต๋๋ค.
๋ํ boolean equals(ByteBuf, ByteBuf) ๋ฉ์๋๋ ๋ ByteBuf ์ธ์คํด์ค์ ๋๋ฑ์ฑ์ ํ๋จํฉ๋๋ค. ByteBufUtil์ ๋ค๋ฅธ ๋ฉ์๋๋ ์ฌ์ฉ์ ์ ์ ByteBuf ํ์ ํด๋์ค๋ฅผ ๊ตฌํํ ๋ ์ ์ฉํ ์ ์์ต๋๋ค.
5.6 Reference counting
์ฐธ์กฐ ์นด์ดํ ์ ๊ฐ์ฒด๊ฐ ๋ค๋ฅธ ๊ฐ์ฒด์ ์ํด ๋ ์ด์ ์ฐธ์กฐ๋์ง ์์ ๋ ํด๋น ๊ฐ์ฒด๊ฐ ๋ณด์ ํ ๋ฆฌ์์ค๋ฅผ ํด์ ํ์ฌ ๋ฉ๋ชจ๋ฆฌ ์ฌ์ฉ๊ณผ ์ฑ๋ฅ์ ์ต์ ํํ๋ ๊ธฐ์ ์ ๋๋ค.
์ฐธ์กฐ ์นด์ดํ ์ ์์ด๋์ด๋ ๊ฐ๋จํฉ๋๋ค. ํน์ ๊ฐ์ฒด์ ๋ํ ํ์ฑ ์ฐธ์กฐ ์๋ฅผ ์ถ์ ํ๋ ๊ฒ์ ๋๋ค. ReferenceCounted ๊ตฌํ ์ธ์คํด์ค๋ ์ผ๋ฐ์ ์ผ๋ก 1์ ํ์ฑ ์ฐธ์กฐ ์นด์ดํธ๋ก ์์ํฉ๋๋ค.
์ฐธ์กฐ ์นด์ดํธ๊ฐ 0๋ณด๋ค ํฐ ๋์ ๊ฐ์ฒด๋ ํด์ ๋์ง ์์ต๋๋ค. ํ์ฑ ์ฐธ์กฐ ์๊ฐ 0์ด ๋๋ฉด ์ธ์คํด์ค๋ ํด์ ๋ฉ๋๋ค. ์ฐธ์กฐ ์นด์ดํ ์ ๋ฉ๋ชจ๋ฆฌ ํ ๋น์ ์ค๋ฒํค๋๋ฅผ ์ค์ด๋ PooledByteBufAllocator์ ๊ฐ์ ํ๋ง ๊ตฌํ์ ํ์์ ์ ๋๋ค.
Channel channel = ...;
ByteBufAllocator allocator = channel.alloc();
ByteBuf buffer = allocator.directBuffer();
assert buffer.refCnt() == 1;
ByteBuf buffer = ...;
boolean released = buffer.release();
์ฐธ์กฐ๋ ๊ฐ์ฒด๊ฐ ํด์ ๋ ํ์ ์ ๊ทผํ๋ ค๊ณ ํ๋ฉด IllegalReferenceCountException์ด ๋ฐ์ํฉ๋๋ค. ํน์ ํด๋์ค๋ ์์ ์ ๋ฐฉ์์ผ๋ก ์ฐธ์กฐ ์นด์ดํ ๊ณ์ฝ์ ์ ์ํ ์ ์์ต๋๋ค.
Last updated