denny 2025. 4. 2. 17:46

๐Ÿ’ก ARMv7 + IL2CPP ํ™˜๊ฒฝ์—์„œ LZ4 ํฌ๋ž˜์‹œ ๋ฌธ์ œ์™€ ํ•ด๊ฒฐ์ฑ…

Unity์—์„œ IL2CPP + ARMv7 ํ™˜๊ฒฝ์—์„œ **LZ4 ์••์ถ•์„ ์‚ฌ์šฉํ•  ๋•Œ ๋ฐœ์ƒํ•˜๋Š” ์ •๋ ฌ ๋ฌธ์ œ(unaligned access)**๋กœ ์ธํ•ด ํฌ๋ž˜์‹œ๊ฐ€ ๋ฐœ์ƒํ•  ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๋‹ค๋ฉด, ๋„ค์ดํ‹ฐ๋ธŒ LZ4 ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ง์ ‘ ์ž„ํฌํŠธํ•ด์„œ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ์‹์€ ์ข‹์€ ํ•ด๊ฒฐ์ฑ…์ด ๋  ์ˆ˜ ์žˆ์–ด.


๐Ÿ”น ๋ฌธ์ œ์˜ ์›์ธ (Unaligned Access ๋ฌธ์ œ)

  • ARMv7 ์•„ํ‚คํ…์ฒ˜๋Š” ๋ฉ”๋ชจ๋ฆฌ ์ •๋ ฌ(Alignment)์„ ์—„๊ฒฉํ•˜๊ฒŒ ์š”๊ตฌํ•จ.
  • IL2CPP๋Š” C# ์ฝ”๋“œ๋ฅผ ๋ณ€ํ™˜ํ•˜๋ฉด์„œ C++ ์ฝ”๋“œ์—์„œ ์ •๋ ฌ๋˜์ง€ ์•Š์€ ๋ฉ”๋ชจ๋ฆฌ ์ ‘๊ทผ์„ ๊ทธ๋Œ€๋กœ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Œ.
  • Mono์—์„œ๋Š” ์ž๋™์œผ๋กœ ์ •๋ ฌ๋œ ์ ‘๊ทผ์„ ๋ณด์žฅํ•˜์ง€๋งŒ, IL2CPP์—์„œ๋Š” ๊ฐœ๋ฐœ์ž๊ฐ€ ์ •๋ ฌ์„ ์ง์ ‘ ์‹ ๊ฒฝ ์จ์•ผ ํ•จ.
  • LZ4์˜ ๊ธฐ๋ณธ ๊ตฌํ˜„์€ ๋น ๋ฅธ ์ฒ˜๋ฆฌ๋ฅผ ์œ„ํ•ด unaligned access๋ฅผ ํ—ˆ์šฉํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ์„ค๊ณ„๋จ, ์ด ๋•Œ๋ฌธ์— ํฌ๋ž˜์‹œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Œ.

๐Ÿ”น ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•: ๋„ค์ดํ‹ฐ๋ธŒ LZ4 ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ

โœ… ๋ฐฉ๋ฒ• 1: C++ ๊ธฐ๋ฐ˜์˜ LZ4 ๋„ค์ดํ‹ฐ๋ธŒ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์‚ฌ์šฉ

๐Ÿ’ก LZ4์˜ ๊ณต์‹ C ๊ตฌํ˜„์„ ๋นŒ๋“œํ•ด์„œ Unity์—์„œ P/Invoke๋ฅผ ํ†ตํ•ด ์‚ฌ์šฉํ•˜๋ฉด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Œ.

  • ARMv7 ํ™˜๊ฒฝ์—์„œ๋„ ์•ˆ์ „ํ•œ ์ •๋ ฌ์„ ๋ณด์žฅํ•˜๋Š” ๋„ค์ดํ‹ฐ๋ธŒ ์ฝ”๋“œ๋กœ ์‹คํ–‰๋จ.
  • Unity์˜ IL2CPP์™€ ํ˜ธํ™˜ ๊ฐ€๋Šฅ.
  • ๋„ค์ดํ‹ฐ๋ธŒ ์ตœ์ ํ™”๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์„ฑ๋Šฅ์ด ๋” ์ข‹์„ ์ˆ˜๋„ ์žˆ์Œ.

๐Ÿ”น 1. ๋„ค์ดํ‹ฐ๋ธŒ LZ4 ๋นŒ๋“œ (C++ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ)

  1. LZ4 ๊ณต์‹ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ์—์„œ ์ตœ์‹  C++ ์†Œ์Šค๋ฅผ ๋‹ค์šด๋กœ๋“œ
  2. Android์šฉ .so ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋นŒ๋“œ
    • jni/Android.mk ํŒŒ์ผ์„ ์ƒ์„ฑ ํ›„, LZ4 C ์ฝ”๋“œ ํฌํ•จ
    • ndk-build๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ .so ํŒŒ์ผ ์ƒ์„ฑ
    • liblz4.so๋ฅผ Unity์˜ Plugins/Android/ ํด๋”์— ๋ฐฐ์น˜
  3. iOS ๋ฐ Windows์šฉ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ๋นŒ๋“œ
    • iOS: Xcode์—์„œ liblz4.a(์ •์  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ) ๋˜๋Š” liblz4.dylib(๋™์  ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ) ์ƒ์„ฑ
    • Windows: Visual Studio์—์„œ lz4.dll ๋นŒ๋“œ

๐Ÿ”น 2. Unity์—์„œ P/Invoke๋กœ ๋„ค์ดํ‹ฐ๋ธŒ LZ4 ํ˜ธ์ถœ

Unity์—์„œ DllImport๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋„ค์ดํ‹ฐ๋ธŒ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ๋จ.

๐Ÿ”ธ C++ ๋„ค์ดํ‹ฐ๋ธŒ ํ•จ์ˆ˜ (LZ4Wrapper.cpp)

#include "lz4.h"

extern "C" {
    int LZ4_Compress(const char* src, char* dst, int srcSize, int maxDstSize) {
        return LZ4_compress_default(src, dst, srcSize, maxDstSize);
    }

    int LZ4_Decompress(const char* src, char* dst, int compressedSize, int dstCapacity) {
        return LZ4_decompress_safe(src, dst, compressedSize, dstCapacity);
    }
}

๋นŒ๋“œ ํ›„ liblz4.so, liblz4.dylib, lz4.dll์„ Unity์˜ Plugins ํด๋”์— ์ถ”๊ฐ€.


๐Ÿ”น 3. C#์—์„œ P/Invoke๋กœ ํ˜ธ์ถœ

using System;
using System.Runtime.InteropServices;

public static class LZ4Native
{
    const string LIB_NAME =
#if UNITY_IOS
        "__Internal";
#elif UNITY_ANDROID
        "liblz4";
#elif UNITY_STANDALONE_WIN
        "lz4";
#else
        "lz4";
#endif

    [DllImport(LIB_NAME, EntryPoint = "LZ4_Compress")]
    public static extern int Compress(byte[] src, byte[] dst, int srcSize, int maxDstSize);

    [DllImport(LIB_NAME, EntryPoint = "LZ4_Decompress")]
    public static extern int Decompress(byte[] src, byte[] dst, int compressedSize, int dstCapacity);
}

์ด์ œ C#์—์„œ LZ4Native.Compress ๋ฐ LZ4Native.Decompress๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด ๋„ค์ดํ‹ฐ๋ธŒ LZ4๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Œ.


๐Ÿ”น ๊ฒฐ๋ก : ๋„ค์ดํ‹ฐ๋ธŒ LZ4 ์‚ฌ์šฉ์ด ์ข‹์€ ํ•ด๊ฒฐ์ฑ…!

โœ… IL2CPP์—์„œ ๋ฐœ์ƒํ•˜๋Š” unaligned access ๋ฌธ์ œ๋ฅผ ํ”ผํ•  ์ˆ˜ ์žˆ์Œ.
โœ… ARMv7 ํ™˜๊ฒฝ์—์„œ๋„ ์•ˆ์ •์ ์œผ๋กœ ๋™์ž‘ ๊ฐ€๋Šฅ.
โœ… ์„ฑ๋Šฅ ํ–ฅ์ƒ ๊ฐ€๋Šฅ (๋„ค์ดํ‹ฐ๋ธŒ ์ฝ”๋“œ ์‹คํ–‰ ์ตœ์ ํ™”).
โœ… Unity์˜ ๋‹ค์–‘ํ•œ ํ”Œ๋žซํผ(Android, iOS, Windows)์—์„œ ๋™์ผํ•œ ๋ฐฉ์‹์œผ๋กœ ๋™์ž‘ ๊ฐ€๋Šฅ.

๐Ÿ‘‰ ๊ฒฐ๋ก ์ ์œผ๋กœ, ๋„ค์ดํ‹ฐ๋ธŒ LZ4 ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ž„ํฌํŠธํ•ด์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€์žฅ ์ข‹์€ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ• ์ค‘ ํ•˜๋‚˜์•ผ! ๐Ÿš€