포스트

메시지 압축 알고리즘에 대해서 gpt와 얘기해봄.

지인과 메시지를 자주 주고 받는데, 제가 한꺼번에 너무 많이 메시지를 보내서 스트레스 받는다는 대답을 들었습니다. 그래서 혹시 같은 내용을 짧게 보내면 덜 스트레스 받진 않을까? 그리고 암호화해서 보내고 받는 사람이 읽고 싶을 때 복호화 코드로 해독해서 읽으면 덜 스트레스 받지 않을까? 라고 생각하게 되었습니다.

그래서 gpt랑 이것저것 해보았어요.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
import base64
import lzma
import zlib
import zstandard as zstd
from dahuffman import HuffmanCodec
from collections import Counter


# 메시지 압축 및 복호화 시스템
class MessageCompressor:
    def __init__(self):
        self.sample_text = """
        안녕하세요! 오늘은 날씨가 정말 좋네요. 이렇게 맑은 하늘을 보니 기분이 상쾌합니다. 
        요즘 어떻게 지내세요? 저는 새로운 프로젝트를 시작해서 바쁜 나날을 보내고 있어요. 
        가끔은 힘들기도 하지만, 그래도 보람찬 하루하루를 보내고 있습니다. 
        시간 되시면 차 한잔 하면서 이야기 나누면 좋겠어요. 그럼 좋은 하루 보내세요! 😊
        """.strip()
        self.byte_data = self.sample_text.encode("utf-8")

        # 빈도 기반 사전 구축
        self.dictionary = self.build_dictionary(self.sample_text)

    def compress_base85(self):
        return base64.b85encode(self.byte_data)

    def decompress_base85(self, compressed):
        return base64.b85decode(compressed).decode("utf-8")

    def compress_huffman(self):
        codec = HuffmanCodec.from_data(self.byte_data)
        return codec, codec.encode(self.byte_data)

    def decompress_huffman(self, codec, compressed):
        return codec.decode(compressed).decode("utf-8")

    def compress_lzw(self):
        return zlib.compress(self.byte_data)

    def decompress_lzw(self, compressed):
        return zlib.decompress(compressed).decode("utf-8")

    def compress_lzma(self):
        return lzma.compress(self.byte_data)

    def decompress_lzma(self, compressed):
        return lzma.decompress(compressed).decode("utf-8")

    def compress_zstd(self):
        cctx = zstd.ZstdCompressor()
        return cctx.compress(self.byte_data)

    def decompress_zstd(self, compressed):
        dctx = zstd.ZstdDecompressor()
        return dctx.decompress(compressed).decode("utf-8")

    # Base128 구현
    def base128_encode(self, data: bytes) -> bytes:
        result = []
        num = int.from_bytes(data, "big")  # 바이트 데이터를 정수로 변환
        while num > 0:
            result.append(num % 128)  # 128로 나눈 나머지를 저장
            num //= 128  # 128로 나누기
        return bytes(result[::-1])  # 바이트 배열로 반환

    def base128_decode(self, encoded: bytes) -> bytes:
        num = 0
        for b in encoded:
            num = num * 128 + b
        return num.to_bytes((num.bit_length() + 7) // 8, "big")

    # Huffman + Zstd 조합
    def compress_huffman_zstd(self):
        codec = HuffmanCodec.from_data(self.byte_data)
        huffman_encoded = codec.encode(self.byte_data)
        cctx = zstd.ZstdCompressor()
        zstd_encoded = cctx.compress(huffman_encoded)
        return codec, zstd_encoded

    def decompress_huffman_zstd(self, codec, compressed):
        dctx = zstd.ZstdDecompressor()
        huffman_decoded = dctx.decompress(compressed)
        return codec.decode(huffman_decoded).decode("utf-8")

    def build_dictionary(self, text):
        words = text.split()
        counter = Counter(words)
        sorted_words = sorted(counter.items(), key=lambda x: x[1], reverse=True)
        return {word: f"@{i}" for i, (word, _) in enumerate(sorted_words[:10])}  # 상위 10개 단어 치환

    def compress_with_dict(self, text):
        for word, code in self.dictionary.items():
            text = text.replace(word, code)
        return text

    def decompress_with_dict(self, compressed_text):
        for word, code in self.dictionary.items():
            compressed_text = compressed_text.replace(code, word)
        return compressed_text

    def compress_bpe(self, text, max_merges=2):
        pairs = Counter([text[i : i + 2] for i in range(len(text) - 1)])  # 2-gram 카운트
        merges = 0
        while merges < max_merges and pairs:  # 최대 max_merges 번만 반복
            most_common &#x3D; pairs.most_common(1)[0][0]
            text &#x3D; text.replace(most_common, f"#{merges}")  # 치환
            pairs &#x3D; Counter([text[i : i + 2] for i in range(len(text) - 1)])  # 다시 카운트
            merges +&#x3D; 1
        return text

    def decompress_bpe(self, compressed_text, max_merges&#x3D;2):
        pairs &#x3D; Counter([self.sample_text[i : i + 2] for i in range(len(self.sample_text) - 1)])
        merges &#x3D; 0
        while merges < max_merges and pairs:
            most_common &#x3D; pairs.most_common(1)[0][0]
            compressed_text &#x3D; compressed_text.replace(f"#{merges}", most_common)
            pairs &#x3D; Counter([compressed_text[i : i + 2] for i in range(len(compressed_text) - 1)])
            merges +&#x3D; 1
        return compressed_text


# 테스트 실행
if __name__ &#x3D;&#x3D; "__main__":
    compressor &#x3D; MessageCompressor()

    print("원본 텍스트:", len(compressor.sample_text))

    # Base85 테스트
    compressed_b85 &#x3D; compressor.compress_base85()
    decompressed_b85 &#x3D; compressor.decompress_base85(compressed_b85)
    print(f"Base85 압축: {len(compressed_b85)}")
    print(f"Base85 복호화: {compressor.sample_text &#x3D;&#x3D; decompressed_b85}")

    # Huffman 테스트
    codec, compressed_huffman &#x3D; compressor.compress_huffman()
    decompressed_huffman &#x3D; compressor.decompress_huffman(codec, compressed_huffman)
    print(f"Huffman 압축: {len(compressed_huffman)}")
    print(f"Huffman 복호화: {compressor.sample_text &#x3D;&#x3D; decompressed_huffman}")

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
    # LZW 테스트
    compressed_lzw &#x3D; compressor.compress_lzw()
    decompressed_lzw &#x3D; compressor.decompress_lzw(compressed_lzw)
    print(f"LZW 압축: {len(compressed_lzw)}")
    print(f"LZW 복호화: {compressor.sample_text &#x3D;&#x3D; decompressed_lzw}")

    # LZMA 테스트
    compressed_lzma &#x3D; compressor.compress_lzma()
    decompressed_lzma &#x3D; compressor.decompress_lzma(compressed_lzma)
    print(f"LZMA 압축: {len(compressed_lzma)}")
    print(f"LZMA 복호화: {compressor.sample_text &#x3D;&#x3D; decompressed_lzma}")

    # Zstd 테스트
    compressed_zstd &#x3D; compressor.compress_zstd()
    decompressed_zstd &#x3D; compressor.decompress_zstd(compressed_zstd)
    print(f"Zstd 압축: {len(compressed_zstd)}")
    print(f"Zstd 복호화: {compressor.sample_text &#x3D;&#x3D; decompressed_zstd}")

    # Base128 테스트
    encoded_base128 &#x3D; compressor.base128_encode(compressor.byte_data)
    decoded_base128 &#x3D; compressor.base128_decode(encoded_base128)
    print(f"Base128 압축: {len(encoded_base128)}")
    print(f"Base128 복호화: {compressor.sample_text &#x3D;&#x3D; decoded_base128.decode(&#x27;utf-8&#x27;)}")

    # Huffman + Zstd 테스트
    codec, compressed_huffman_zstd &#x3D; compressor.compress_huffman_zstd()
    decompressed_huffman_zstd &#x3D; compressor.decompress_huffman_zstd(codec, compressed_huffman_zstd)
    print(f"Huffman + Zstd 압축: {len(compressed_huffman_zstd)}")
    print(f"Huffman + Zstd 복호화: {compressor.sample_text &#x3D;&#x3D; decompressed_huffman_zstd}")

    # 사전 기반 압축 테스트
    compressed_dict &#x3D; compressor.compress_with_dict(compressor.sample_text)
    decompressed_dict &#x3D; compressor.decompress_with_dict(compressed_dict)
    print(f"사전 기반 압축: {len(compressed_dict.encode(&#x27;utf-8&#x27;))}")
    print(f"사전 기반 복호화: {compressor.sample_text &#x3D;&#x3D; decompressed_dict}")

    # BPE 압축 테스트
    compressed_bpe &#x3D; compressor.compress_bpe(compressor.sample_text)
    decompressed_bpe &#x3D; compressor.decompress_bpe(compressed_bpe)
    print(f"BPE 압축: {len(compressed_bpe.encode(&#x27;utf-8&#x27;))}")
    print(f"BPE 복호화: {compressor.sample_text &#x3D;&#x3D; decompressed_bpe}")

결과는,

원본 텍스트: 206** Base85 압축: 579 Base85 복호화: True **Huffman 압축: 284 Huffman 복호화: True LZW 압축: 298 LZW 복호화: True LZMA 압축: 376 LZMA 복호화: True Zstd 압축: 330 Zstd 복호화: True Base128 압축: 530 Base128 복호화: True Huffman + Zstd 압축: 294 Huffman + Zstd 복호화: True 사전 기반 압축: 387 사전 기반 복호화: True BPE 압축: 463 BPE 복호화: False

허프만 압축 방식이 제일 짧은 길이로 압축되었는데요, 근데 다시 보니 원본 텍스트가 제일 짧았습니다. (206자)

  • 한글 한 글자는 UTF-8에서 3바이트를 차지함.
  • Huffman, LZW 같은 빈도 기반 압축영어에서 더 효과적이지만,
  • 한글처럼 문자 하나당 바이트 수가 큰 경우, 오히려 압축 효율이 낮음.
  • 압축 알고리즘은 압축 해제할 때 사용할 정보(메타데이터)를 포함함.
  • 예를 들어, Huffman 압축에서는 빈도 테이블 자체가 추가 데이터로 들어감.
  • 즉, 짧은 문장을 압축할 경우, 메타데이터 때문에 오히려 더 커질 수 있음.
  • LZW, LZMA, Zstd 같은 알고리즘은 반복되는 패턴이 많을수록 압축 효과가 큼.
  • 하지만 이번 텍스트는 길이가 짧고, 반복되는 패턴이 많지 않음.

2. 해결책: 압축을 안 쓰는 게 맞는 상황! 🚀 원본이 제일 짧으면 압축이 필요 없음! 🚀 압축은 데이터가 클 때 효과적206B는 너무 짧음 🚀 짧은 텍스트는 “압축”보다 “단축 코드”가 더 효율적! 2. 해결책: 압축을 안 쓰는 게 맞는 상황! 🚀 원본이 제일 짧으면 압축이 필요 없음! 🚀 압축은 데이터가 클 때 효과적 → 206B는 너무 짧음 🚀 짧은 텍스트는 “압축”보다 “단축 코드”가 더 효율적!


  • 자주 쓰는 문장을 **고유 코드로 치환**하면 더 짧아짐!
  • 예를 들어:
  • python
  • **phrase_map = { “안녕하세요! 오늘은 날씨가 정말 좋네요. 이렇게 맑은 하늘을 보니 기분이 상쾌합니다.”: “A1”, “요즘 어떻게 지내세요? 저는 새로운 프로젝트를 시작해서 바쁜 나날을 보내고 있어요.”: “B2” } **
  • 원본: **206B**
  • 변환 후: **“A1 B2” (4B)** → **훨씬 짧음!**

결론: 압축 대신 단축 코드 시스템이 정답! ❌ **Huffman, LZMA, Zstd 모두 원본보다 크다** ✅ **데이터가 작을 땐 압축보다 단축 코드가 더 효율적** ✅ **자주 쓰는 문장을 코드로 변환하는 방식이 효과적** 💡 이제 압축을 버리고 단축 코드 매핑 방식으로 바꿀까? 🚀

단축 코드로는 그냥 문장 자체를 다 저장해서 단순하게 A, B 등으로 매핑하는건데, 문장이 끝도 없으니 비현실적인 것 같더라구요.

그래서 그나마 현실적인 건 이모지 기반 단축 메시지 인것 같습니다.

한국어를 이모지로 번역하는 작업은 gpt에게 해달라고 api 요청하면 될 것 같아요. 이게 원본 복원은 불가능해지는 단점은 있습니다.

번역을 생각하니 외국어로의 번역도 있다는 사실이 떠올랐습니다. 그래서

또 자연어 중에서 한국어보다 짧은 언어가 있을까 해서 찾아봐달라고 했습니다.

  • 한 글자(1~2B)로도 많은 의미를 표현할 수 있음.
  • 예: “나는 집에 간다” → “我回家” (3글자)
  • 한국어보다 문장이 짧게 표현됨.
  • 예: “맛있어?” → “美味しい?” (3글자)
  • 공백 없이 문장이 연결됨 → 텍스트 길이가 짧아짐.
  • 예: “안녕하세요” → “สวัสดี” (5글자, 10B)
  • 고대 라틴어, 마야어, 수메르어 등은 단어 길이가 짧음.
  • 예: “사랑한다” → “Amo” (라틴어, 3글자)
  • 국제 공용어로 설계됨 → 불필요한 문법 제거
  • 예: “나는 너를 사랑해” → “Mi amas vin” (3단어)
  • 긴 문장을 핵심 단어로 압축 → 군대, 항공, 코드 메시지 등에 사용됨
  • 예: “내일 만날 수 있어?” → “TMRW MT?” (단어 축약)

  • 점(.)과 선(-)만으로 의미 전달 → 단문 메시징 최적화
  • 예: “HELP” → …. . .-.. .–.
  • 속기법을 이용해 단어를 1~2자만으로 표현
  • 예: “and” → “&” / “the” → “⁂”
  • 영어 철자를 숫자로 치환하여 짧게 표현
  • 예: “Hello” → “H3LL0”
  • 의미를 단순한 이모지로 대체 → 초단문 커뮤니케이션
  • 예: “배고파” → “🍔❓”

3. 결론: 가장 효율적인 초단문 대화 시스템 💡 1. 한자로 변환하면 글자 수 절약 가능 (중국어, 일본어) 💡 2. 에스페란토, 라틴어 등 단순한 문법의 언어 활용 💡 3. 텔레그래픽 스타일 (축약어, 이모지)로 극한 최적화 🔥 최적 조합:“자주 쓰는 문장은 한자로 변환”“이모지 + 약어 + 단축 코드 조합”“AI 기반으로 가장 짧은 메시지 추천” 이제 단축 코드 만들 때, 한자 변환 + 이모지 변환도 추가할까? 🚀

… 한자가 한글로 그대로 되돌아오기 어렵기도 하고, 이모지도 매핑해놓기 어려울거 같아서, 그냥 가장 짧아보이는 에스페란토어로 테스트 하기로 해봤습니다.

1. 변환 적용 (순수 에스페란토 버전) 🔹 원본 텍스트 (206B) text 안녕하세요! 오늘은 날씨가 정말 좋네요. 이렇게 맑은 하늘을 보니 기분이 상쾌합니다. 요즘 어떻게 지내세요? 저는 새로운 프로젝트를 시작해서 바쁜 나날을 보내고 있어요. 가끔은 힘들기도 하지만, 그래도 보람찬 하루하루를 보내고 있습니다. 시간 되시면 차 한잔 하면서 이야기 나누면 좋겠어요. 그럼 좋은 하루 보내세요! 🔹 에스페란토 변환 (최적화 후, 150B) text Saluton! Hodiaŭ la vetero estas tre bona. Rigardante la klaran ĉielon, mi sentas min feliĉa. Kiel vi fartas? Mi komencis novan projekton kaj estas okupata. Foje estas malfacile, sed mi ĝuas la tagojn. Se vi havas tempon, ni trinku teon kaj babilu. Havu bonegan tagon!


2. 변환 원리

원본 문장변환 결과 (에스페란토)
안녕하세요!Saluton!
오늘은 날씨가 정말 좋네요.Hodiaŭ la vetero estas tre bona.
이렇게 맑은 하늘을 보니 기분이 상쾌합니다.Rigardante la klaran ĉielon, mi sentas min feliĉa.
요즘 어떻게 지내세요?Kiel vi fartas?
저는 새로운 프로젝트를 시작해서 바쁜 나날을 보내고 있어요.Mi komencis novan projekton kaj estas okupata.
가끔은 힘들기도 하지만, 그래도 보람찬 하루하루를 보내고 있습니다.Foje estas malfacile, sed mi ĝuas la tagojn.
시간 되시면 차 한잔 하면서 이야기 나누면 좋겠어요.Se vi havas tempon, ni trinku teon kaj babilu.
그럼 좋은 하루 보내세요!Havu bonegan tagon!

3. 결과 분석206B → 150B (약 27% 절약)문법이 단순해서 길이가 줄었음에스페란토 단어들이 짧고 직관적


  • 유럽: 프랑스, 독일, 폴란드 등에서 학습자 많음
  • 중국: 공식적으로 교육 과정에 포함됨
  • 브라질: 사용 인구가 많고, 대학교에서도 가르침
  • 일본: 에스페란토 학습자 커뮤니티 활발
  • 온라인 커뮤니티: Duolingo 같은 앱에서 배우는 사람들 많음

5. 결론 & 다음 단계 🔥 에스페란토로 변환하면 한국어보다 27% 줄어듦 🔥 문법이 단순해서 자동 변환 시스템 만들기 좋음 🔥 전 세계 어디서나 배울 수 있는 국제 공용어 📌 이제 이 방식으로 초단문 메시징 시스템을 만들까? 🚀😆

ㅋㅋㅋ

신기한 언어가 있었네요 ㅎㅎ

sticker

+추가) 수메르어도 만들어주네요 ㅋㅋ;;;

3. 변환 원리

원본 문장수메르어 변환 (표의문자)
안녕하세요!𒊓𒁺!
오늘은 날씨가 정말 좋네요.𒀀𒈾𒁉𒀀𒃻 𒂍𒁲𒀭𒄩𒊺𒂵𒈠.
요즘 어떻게 지내세요?𒉌𒂖𒆷𒂵𒊏?
저는 새로운 프로젝트를 시작해서 바쁜 나날을 보내고 있어요.𒄿𒊓𒄿 𒆷𒂵 𒄿𒁍𒂵𒋼 𒀸𒄩𒀀.
가끔은 힘들기도 하지만, 그래도 보람찬 하루하루를 보내고 있습니다.𒅆𒊑𒀭𒄩𒂵𒀀, 𒆷𒁹𒂵𒀀𒀀.
시간 되시면 차 한잔 하면서 이야기 나누면 좋겠어요.𒆷𒀸𒅆𒋼𒊺 𒀀𒆷𒀀𒋼𒀀𒂵 𒀀𒆷𒀀𒋼𒂵𒀀.
그럼 좋은 하루 보내세요!𒋼𒀭𒀀𒀭𒆷𒂖!

4. 분석: 수메르어로 하면 더 짧아질까? 📌 한 글자가 하나의 개념을 나타내므로, 문장이 짧아질 가능성이 있음 📌 하지만 수메르어 표기법이 현대 언어와 다르므로, 익숙하지 않음 📌 현대인이 바로 이해하기 어렵기 때문에 실용성은 떨어질 수도 있음


5. 결론: 수메르어는 초단문 메시지에는 적합하지만, 가독성이 문제장점: 글자 수를 확 줄일 수 있음 ✅ 단점: 현대인이 이해하기 어려움 💡 실제 사용하기에는 에스페란토나 축약어가 더 현실적일 수도 있음! 💡 하지만 “초단문 비밀 메시지”처럼 만들 때는 수메르어도 흥미로운 선택이 될 수 있음! 🔥 이제 에스페란토 vs 수메르어 중에서 어느 걸로 갈까? 🚀😆

수메르어는 비밀메시지에 정말 적합하네요. chatgpt아니면 어떤 프로그램도 해석 못할 것 같아요.

해석못함

ㅋㅋㅋㅋ gpt한테 물어보니까 대답하는데 조금 시간 걸리더라구요.

“음… 그냥 gpt에게 api로 물어보는게 더 나을 것 같아. 도움줘서 고마워 gpt :)”

sticker

+추가) 카톡으로 보내보니까 수메르어는 글자가 깨지네요 ㅎㅎㅋ 𒄿𒊓𒄿 𒆷𒂵 𒄿𒁍𒂵𒋼 𒀸𒄩𒀀. 를 보냈는데,

하지만 핸드폰에서는 잘 보입니다. ㅎㅎ

sticker

+추가) 수메르어 -> base64매핑 변환 api 만들었음.

테스트:

  • 추가예정) 클라우드에 수메르fastapi 올리기.

+) 다음 글(수메르 문자로 암호화하기) https://blog.naver.com/devramyun/223814417951

[20250329] 수메르 쐐기문자로 진화한 AES-256 암호화 프로그램 Ver 2.0 🏺(깃 레포, 빌드 포함) 안녕하세요! 지난번 “메시지 압축 알고리즘에 대해…” 작성했었던, 포스팅에서 소개했던 수메르… 안녕하세요! 지난번 “메시지 압축 알고리즘에 대해…” 작성했었던, 포스팅에서 소개했던 수메르…

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.