2019/03/18 - [개발이/아이디어노트] - 스팸체 생성기
앞서 스팸체 생성기에 대해 소개했었는데요.
관련하여 가장 중요한 내용을 여기에 써보려합니다.
바로 한글을 분리하고 조합하는 내용입니다.
일단 유니코드 한글영역에 대해 알아야 합니다.
유니코드?
다들 아시겠지만, 혹시 더 궁금하시면 아래 링크를 참고해주세요.
이 포스팅에서 제가 다루진 않겠습니다.
https://ko.wikipedia.org/wiki/유니코드
스팸체 생성기 예시
규칙 | 예시 |
가능한 경우 한글을 가로로 쪼개자. | 스위치 → 스우ㅣㅊㅣ |
쪼개진 자모를 특문으로 바꾸자. | ㄱㅏㄴㅏ → 7r ㄴr |
초성, 종성을 복잡하게 바꾸자. | 치킨먹자 → 칧킪먻짞 |
공백을 특수문자로 채우자. | 연결 고리 → 연결✦고리 |
공백이 아니어도 특정 확률로 특문을 넣자. | 동해물과백두 → 동해물✿과❅백♛➳두 |
영문자를 전각으로 바꾸자. | abc → abc |
숫자를 전각으로 바꾸거나 특문으로 바꾸자. | 123 → 丨己彐 |
위를 다 하고도 바꿀 수 있다면 바꾸자. | 스고 → 亼卫 |
여기서 유니코드 한글 영역에 대한 이해가 필요한 부분은 바로 1, 2, 3번 항목입니다.
이제 저 세 항목을 어떻게 다룰지 생각해봅시다.
유니코드 한글 영역
유니코드 한글 영역을 알아야 합니다.
이 코드를 가지고 한글을 조합, 분해하며 한글을 망가트려야 하기 때문이죠.
http://www.unicode.org/charts/ 에서 우리가 필요한 한글 정보를 얻을 수 있는데요.
우리가 참고할 부분은 바로 Hangul Jamo, Hangle Syllables입니다.
Hangul Jamo는 자음, 모음 영역입니다. (0x1100 ~ 0x11FF)
쌍니은, 쌍이응, ㅛㅑ 등의 옛 자음, 모음도 포함되어있습니다만
우리는 아래의 문자만 사용하게 됩니다.
- 초성(19)
'ㄱ', 'ㄲ', 'ㄴ', 'ㄷ', 'ㄸ', 'ㄹ', 'ㅁ', 'ㅂ', 'ㅃ', 'ㅅ', 'ㅆ', 'ㅇ', 'ㅈ', 'ㅉ', 'ㅊ', 'ㅋ', 'ㅌ', 'ㅍ', 'ㅎ' - 중성(21)
'ㅏ', 'ㅐ', 'ㅑ', 'ㅒ', 'ㅓ', 'ㅔ', 'ㅕ', 'ㅖ', 'ㅗ', 'ㅘ', 'ㅙ', 'ㅚ', 'ㅛ', 'ㅜ', 'ㅝ', 'ㅞ', 'ㅟ', 'ㅠ', 'ㅡ', 'ㅢ', 'ㅣ' - 중성(28)
없음, 'ㄱ', 'ㄲ', 'ㄳ', 'ㄴ', 'ㄵ', 'ㄶ', 'ㄷ', 'ㄹ', 'ㄺ', 'ㄻ', 'ㄼ', 'ㄽ', 'ㄾ', 'ㄿ', 'ㅀ', 'ㅁ', 'ㅂ', 'ㅄ', 'ㅅ', 'ㅆ', 'ㅇ', 'ㅈ', 'ㅊ', 'ㅋ', 'ㅌ', 'ㅍ', 'ㅎ'
Hangle Syllables 은 한글 음절 영역입니다.
'가'에서 '힣' 까지입니다. (0xAC00 ~ 0xDCAF)
위 초성, 중성, 종성의 순서대로 조합되어 있습니다.
초성 19개, 중성 21개, 종성 28개이고, 위에 나열된 순서대로 조합되어 있으므로
한글 한 음절은 아래와 같은 공식을 따릅니다.
# 각 초성, 중성, 종성의 순서는 0부터 시작합니다
한글 문자 코드
= (초성 순서 * 21 * 28) + (중성 순서 * 28) + 종성 순서 + 0xAC00
= ((초성 순서 * 21) + 중성 순서) * 28 + 종성 순서 + 0xAC00
예를 들어 봅시다.
첫 글자인 '가'의 경우, 초성 1번째, 중성 1번째, 종성 1번째입니다.
따라서 (0 * 21 * 28) + (0 * 28) + 0 = 0입니다.
0xAC00 부터 0번째 뒤에 있는 문자인 것입니다.
그렇다면 0xAC01과 0xAC02는 무엇일까요?
1씩 늘어났으므로 종성의 순서가 증가되었음을 알 수 있습니다.
따라서 각각 '각', '갂' 이 되겠죠.
그럼 '나'의 경우는?
'ㄴ'은 세 번째 초성이며 중성, 종성은 첫 번째이므로
(2 * 21 * 28) + (0 * 28) + 0 = 1176
즉, '가'로부터 1176번째 뒤에 있는 값입니다.
따라서 '나' 코드값은 아래와 같습니다.
0xAC00(16) + 1176(10)
= 44032(10) + 1176(10)
= 45208(10) = 0xB098(16)
이제 분리를 해봅시다. 복잡하니까 0xAC00 을 제외한 "한글 문자 순서"만 고려해보죠.
한글 문자 순서 = 한글 문자 코드 - 0xAC00
앞서 보듯이 중성은 21개, 종성은 28개입니다.
각 문자가 21 * 28 번째마다 같은 중성, 종성을 갖되 "초성 순서"만 달라진다는 뜻이지요.
따라서 이렇게 "초성 순서"를 구할 수 있습니다.
초성 순서 = 한글 문자 순서 / (21 * 28)
이제 초성을 구하고 남은 나머지를 같은 방법으로 적용하면 중성을 구할 수 있습니다.
거기서 남은 나머지를 이용하면 종성을 구할 수 있고요.
따라서 조합 / 분리의 전체 공식은 아래와 같이 표현할 수 있습니다.
한글 문자 순서 = ((초성 순서 * 21) + 중성 순서) * 28 + 종성 순서
한글 문자 코드 = 조합된 한글 순서 + 0xAC00
초성 순서 = 한글 문자 순서 / (21 * 28)
중성 순서 = (한글 문자 순서 % (21 * 28)) / 28
종성 순서 = (한글 문자 순서 % (21 * 28)) % 28
그런데, 뭔가 부족합니다.
왢 -> ㅇ, ㅙ, ㄶ
우리가 구현한 것은 이렇게까지만 분리됩니다.
- 초성, 종성을 복잡하게 바꾸자.
예) 치킨먹자 → 칧킪먻짞
고안한 8가지 규칙 중 위를 구현 하려면
아래와 같이 더 잘게 쪼개야 합니다.
왢 -> {ㅇ}, {ㅗ, ㅐ}, {ㄴ,ㅎ}
그리고 이렇게 쪼개려면 다른 조치가 필요하지요.
(참고로 ㅐ를 ㅏㅣ 까지 분리하진 않겠습니다.)
갑자기 머리가 아파옵니다만.. 사실 간단합니다.
위에 만든 초성, 중성, 종성 배열을 아래처럼 하나 더 만들면 됩니다.
- 초성(19)
['ㄱ'], ['ㄱ', 'ㄱ'], ['ㄴ'], ['ㄷ'], ['ㄷ', 'ㄷ'], ['ㄹ'], ['ㅁ'], ['ㅂ'], ['ㅂ', ㅂ'], ['ㅅ'], ['ㅅ', 'ㅅ'], ['ㅇ'], ['ㅈ'], ['ㅈ', 'ㅈ'], ['ㅊ'], ['ㅋ'], ['ㅌ'], ['ㅍ'], ['ㅎ'] - 중성(21)
['ㅏ'], ['ㅐ'], ['ㅑ'], ['ㅒ'], ['ㅓ'], ['ㅔ'], ['ㅕ'], ['ㅖ'], ['ㅗ'], ['ㅘ'], ['ㅙ'], ['ㅚ'], ['ㅛ'], ['ㅜ'], ['ㅜ', 'ㅓ'], ['ㅜ', 'ㅔ'], ['ㅜ', 'ㅣ'], ['ㅠ'], ['ㅡ'], ['ㅡ', 'ㅣ'], ['ㅣ'] - 중성(28)
없음, ['ㄱ'], ['ㄱ', 'ㄱ'], ['ㄱ', 'ㅅ'], ['ㄴ'], ['ㄴ', 'ㅈ'], ['ㄴ', 'ㅎ'], ['ㄷ'], ['ㄹ'], ['ㄹ', 'ㄱ'], ['ㄹ', 'ㅁ'], ['ㄹ', 'ㅂ'], ['ㄹ', 'ㅅ'], ['ㄹ', 'ㅌ'], ['ㄹ', 'ㅍ'], ['ㄹ', 'ㅎ'], ['ㅁ'], ['ㅂ'], ['ㅂ', 'ㅅ'], ['ㅅ'], ['ㅅ', 'ㅅ'], ['ㅇ'], ['ㅈ'], ['ㅊ'], ['ㅋ'],['ㅌ'], ['ㅍ'], ['ㅎ']
앞서 만든 데이터와 거의 같습니다.
이렇게 되면 배열의 한 수준이 더 생기긴 하지만
위에서 도출한 분리 공식을 똑같이 사용할 수 있습니다.
마치며
장난 치려고 한건데 알아야할게 꽤 많아져버렸습니다.
부디 저처럼 말고 좋은 곳에 참고하시길 바랍니다.
(예전에 브런치에 썼었던 글인데요. 이쪽으로 가져왔습니다. )
'테크 노트 > 소소한 개발 팁' 카테고리의 다른 글
앞으로 개발관련 글은 Github에 써볼까 합니다. (0) | 2019.05.01 |
---|---|
티스토리 본문 이미지에 border 넣기 (2) | 2019.04.23 |
java, stream api에서 NPE 발생 주의 (0) | 2019.04.03 |
java, optional의 orElse와 orElseGet의 차이 (2) | 2019.03.31 |
android, 앱 출시하려는데 keystore 잃어버렸을 때 (1) | 2019.03.28 |