3. 대상 / 강연의 목적
• 이제 프로그래밍을 하셔야 하는 분을 대상으로 합니다.
• 전업 프로그래머 중 일부에게는 상식이라고 생각할 수 있지만,
정작 정규 교육과정에서는 잘 다루지 않는 내용을 공유하려고 했습니다.
• 여러분의 시행착오를 줄이거나 교양을 늘리는데 도움이 되면 좋겠습니다.
6. 다른 기본 형식들은 (1)
• 논리식을 표현하기 위해 컴퓨터에서 진위 값을 쓰려면?
• 2가지 상태만 필요하면
불 (George Boole) 대수를 사용
• 3가지 상태가 필요하면
우카시에비치 (Jan Łukasiewicz) 대수를 사용
7. 다른 기본 형식들은 (2)
• 정수의 부분 집합을 표현하려면?
• 음수 표현이 필요 없으면 모듈로 연산을 사용,
필요하면 2의 보수를 사용
• [0, 255] 혹은 [-128, 127] 범위는 8비트,
• [0, 65535] 혹은 [-32768, 32767] 범위는 16비트,
• [0, 4294967295] 혹은 [-231, 231-1] 범위는 32비트 정수형을 사용
• 이 범위를 넘어서게 되면 주변의 프로그래머와 상담
8. 다른 기본 형식들은 (3)
• 유리수나 실수를 다루려면?
• IEEE (전기 전자 기술자 협회) 754 표준 부동소수점 실수형
• 유효자리가 10진수 7자리 이내라면 32비트,
• 유효자리가 10진수 15자리 이내라면 64비트 실수형을 사용
• 이 범위를 넘어서게 되면 주변의 프로그래머와 상담
9. 문자열은 비교적 답이 쉽게 나오는 다른 기본 형식들과 달리
• 트랜지스터가 나온 뒤 1갑자60년 가까이 지났음에도
표현 및 구현 방법의 정석이 불명확
• 내부 구현 방법에 따른 숨은 비용을 고려하지 않고 남용하기도 쉬움
• 특히 대중적으로 많이 사용되는 언어들은
최초 개발로부터 시간이 많이 흘러 최근 유행을 못 따름
• C 1972 개발 1990 ISO/IEC 국제 표준화 2011 창시자 사망
• C++ 1983 개발 1998 ISO/IEC 국제 표준화
15. 길이
H e l l o , w o r l d !
1 2 3 4 5 6 7 8 9 10 12 13
이렇게 세고 있어야 하나?
11
16. 일치 연산
H e l l o , w o r l d !
H e l l o , w o r l d !
17. 요약 digest 값
H e l l o , w o r l d !
H e l l , w o r l d !
6cd3556deb0da54bca060b4c39479839
e614491f3139889c2e2822a4110b3745
요약 값이 다르면 중간까지 비교해볼 필요도 없다배꼽?
18. 비교 연산
H e l l o , w o r l d !
H e l l , w o r l d !
19. 비교 연산: 조합형 코드의 경우
ㅇ ㅏ ㄴ ㄴ ㅕ ㅇ
ㅇ ㅏ ㄴ ㅕ
조합 단위 처리를 잘못 할 경우 결과가 반대가 된다
첫 가 끝 첫 가 끝
첫 가 첫 가
24. 길이로 시작 / 종결 문자로 종료?
• 시간이 더 귀중한 자원인 프로세서를 위해서는 길이로 시작
• 문자열의 길이를 얻는 연산은 상당히 자주 사용됨
• 종결 문자로 끝내는 경우가 유용한 경우도 있지만,
일반적인 문자열 조작은 아님
25. 색인은 어떻게?
• [0, 길이) 색인은 기계의 메모리 주소 친화적이지만
• [1, 길이] 색인을 사용하면, 대칭이 되는 [-길이, -1] 색인을
문자열 끝으로부터의 위치를 표현하는데 사용할 수 있다.
H e l l o , w o r l d !
1 2 3 4 5 6 7 8 9 10 12 13
-13 -12 -11-10 -9 -8 -7 -6 -5 -4 -2 -1
11
-3
찾기 실패: -1
찾기 실패: 0
26. 각 글자를 어떻게 저장?
• 문자열 처리는 대체로 프로세서 안에서 이뤄짐
• 가변 길이로 저장을 하면 주요 연산이 느려지므로 고정 길이로 처리
• 실제로 가변 길이로 저장을 하는 경우는 뒤에 다시 소개
27. 생성 시점에 문자당 길이를 고정
• 모두 ISO 8859-1 (1바이트) 영역이면 1바이트씩,
• 라틴 문자
• 모두 UCS-2 (2바이트) 영역이면 2바이트씩,
• 현대에 사용되고 있는 의 각종 언어들의 문자
• 그밖에 UCS-4 (4바이트) 영역이 하나라도 포함될 때 4바이트씩 사용하면
전반적인 수행 시간을 포기하지 않고, 가능한 경우에는 공간을 절약
• 평생 볼 일 없을 고고학적 문자 등
28. 요약 digest 값은 언제 계산?
• 일치 비교 연산을 처음 사용할 때 계산해서 저장해 놓는 것을 추천
• 전혀 비교하지 않는 문자열도 많다.
• 쓰기 전용
29. 복사를 덜 하는 멋진 방법은?
• 안 해도 될 때 안 하면 된다.
• 문자열을 내부에서 보관하고 있다 재활용 하는 방법도 있고,
문자열 상수만 가질 수 있는 특성을 이용하는 방법도 있다.
• 종속 형식 dependent type 을 일부 흉내낼 수 있는 C++의 경우:
template <int N>
string(const wchar_t[N]& s)
: length(s[N – 1] != L’0’ ? N : N - 1), s(s), own(false)
{
}
30. 복사가 너무 많다
• N개의 문자열을 하나로 합치면
어떻게 결합시켜도 N-1번의 복사가 발생
• 공간을 미리 확보해서 복사를 줄이면 안 되나?
문자열을 쌓아서 하나의 문자열로 변환
36. 표현
• 문자열 쌓을 곳에 문자열을 쓰면 문자열 쌓기와 다를 바가 없지만,
• 메모리나 파일, 네트워크에 문자열을 쓰기 시작하면
• 이진 형식으로 표현해야 하는 경우가 생기며
• 처리 형식이 아닌 저장 형식이므로 가변 길이 출력을 해도 상관 없다.
37. UTF-32 32비트 유니코드 변환 서식
• 글자마다 32비트 (4바이트) 값으로 변환해서 쓴다
• 가장 단순하고 용량을 많이 사용하는 방법
• U+FEFF 코드를 Byte Order Mark로 사용해서 각 4바이트의
높은 자리부터 쓸지, 낮은 자리부터 쓸지 결정한다.
http://flickeringtubelight.net/blog/2004/05/
big-endian-and-little-endian-storage-schemes-how-to-remember/
40. UTF-16 16비트 유니코드 변환 서식
• U+FFFF까지의 기본 다국어 평면 영역은 그대로
16비트 (2바이트) 로 쓴다.
• U+100000부터 U+10FFFF까지의 영역은 총 20비트
10+10비트 인코딩
• 110110xxxxxxxxxx 110111xxxxxxxxxx
• U+FEFF 코드를 Byte Order Mark로 사용해서 각 2바이트의
높은 자리부터 쓸지, 낮은 자리부터 쓸지 결정한다.
41. H e l l o , w o r l d !
48 65 6C 6C 6F 54 20 77 6F 72 6C 64 21
00 48 00 65 00 6C 00 6C 00 6F 00 54 00 20 00 77 00 6F 00 72 00 6C 00 64 00 21
48 00 65 00 6C 00 6C 00 6F 00 54 00 20 00 77 00 6F 00 72 00 6C 00 64 00 21 00
UTF-16 BE
UTF-16 LE
49. 최대 길이 /채움 문자
• “{0:*^15}”.format(“Hello, world!”)
H e l l o , w o r l d !* *
50. 왼쪽 / 가운데 / 오른쪽 / 양쪽 맞춤
• “{0:<15}”.format(“Hello, world!”)
• “{0:^15}”.format(“Hello, world!”)
• “{0:>15}”.format(“Hello, world!”)
• “{0:=15}”.format(“Hello, world!”)
H e l l o , w o r l d !
H e l l o , w o r l d !
H e l l o , w o r l d !
H e l l o , w o r l d !
51. 인자 위치 / 인자 이름
• “{1}, {0}!”.format(“world”, “Hello”)
• “{h}, {w}!”.format(h: “Hello”, w: “world”)
52. 변환 / 동적 객체 처리
• 첫 글자만 대문자로 title case
“{:t}, {}!”.format(“hello”, “world”)
• 동적 접근 dynamic lookup
“{.h}, {.w}!”.format{h = “Hello”, w = “world”}
53. 서식 문자열 구현 시 고려 사항
• 지역화 문자열을 localized string 만들게 되면 언어에 따라 어순이 바뀌므로
인자의 위치를 조정하는 기능은 반드시 필요하다.
• 채움 문자/맞춤 처리는 개발 비용에 비해 사용할 곳이 많다.
• 별도로 식별자를 할당해서 변환하게 하면 조건부 문자열 처리를
분리하기 좋다.
• 동적 처리들은 언어에서 지원하지 않는 한 구현할 필요가 없음
55. 조사 처리?
• 바로 앞 글자가 받침으로 끝나는지 여부에 따라
-은/는, -이/가, -을/를 등의 토씨를 알맞게 붙여주는 문제
• 서비스 중인 마비노기의 경우 11:56:06 김동건 [object] 나는 내부적으로 이렇게 쓴다
11:56:13 김동건 [object] 김동건{을}
11:56:18 김동건 [object] 김동건{이}
11:56:23 김동건 [object] 김동건{가}
11:56:29 전형규 [henjeon] 마비1에서 쓰던 방식
11:56:48 김동건 [object] 그때 내가 저렇게 하라고 했을듯
11:56:50 김동건 [object] 과거의 내가
56. 마비노기 방식의 장/단점
• 장점
• 서식 문자열이 짧다: {은} {는} {이} {가} {을} {를}
• 단점
• 서식 문자열이 늘어날 때마다 처리 코드를 갱신해야 한다.
• 의외로 한국어의 조사 목록 전체를 생각해보면 잘 생각이 나지 않는다.
57. 링토스 세계여행의 방식
• 언어가 C# (Unity) 이므로 C# 서식 문자열 변형
• 후딱 만들어야 하는 것이므로 앞으로도 코드는 잘 안 바뀌게
• 사용자가 직관적으로 사용할 수 있게 “을/를”, “(으)로”
2014-03-11 입니다.
17:25:21 김재석 [gim] 후딱 만들었는데 이거가지고 올해 NDC할까..
17:25:25 김재석 [gim] 님이 이미지를 전송합니다.
17:25:29 김재석 [gim] @henjeon
17:26:49 전형규 [henjeon] 오 잘되네
17:27:11 전형규 [henjeon] 괄호가 옵션이고
17:27:17 전형규 [henjeon] 슬래시는 선택이죠?
17:27:25 김재석 [gim] 예
17:27:31 김재석 [gim] 국어시간 노테이션대로
17:27:43 전형규 [henjeon] 설마 저거
17:27:46 전형규 [henjeon] 이미 있는거?
17:27:55 김재석 [gim] 아뇨
17:27:57 김재석 [gim] 지금 짠거
17:28:36 전형규 [henjeon] 굳
어디서 날로 먹으려고…….
58. 숫자 처리
• 처리되는 것이 한글 뿐이면 저렴해 보인다.
• 0으로 끝나는 숫자는 다행히 모두 받침이 있다.
• .net 서식 문자열의 경우 ToString 메소드에 전달해서
다시 각 값을 서식 문자열로 가공하는데,
이 문자들과 구분하기 위해 구분자 ‘-’를 도입
• e.g. {0:c-을/를}
2014-03-12 입니다.
20:41:05 전형규 [henjeon] @김재석
20:41:10 전형규 [henjeon] 영어도 해주
20:41:13 전형규 [henjeon] 숫자도 해주
(32비트 정수형)
59. 외국어 처리
• 정석대로 처리하는 방법
• 사전 기반으로 국제 음성 기호 (IPA) 로 변환
• 국제 음성 기호와 한글 대조표를 참고하여 한글로 전사
• 이렇게 변환된 한글을 기준으로 조사 처리
• 언어학적으로는 적절하지만,
• 사전 데이터가 많이 필요 (언어별로)
• 조사처리하자고 온라인 게임 만들면 곤란
• 이렇게는 시간 내에 만들 수 없다.
60. 영어 처리 (1)
• 외래어 표기법 표기 세칙의 영어 표기를 참고
• 세칙에서 가장 자주 등장하는 받침은 받침 없음이므로
받침이 있는 경우만 정규식으로 처리
• 제1항 무성 파열음 [p] [t] [k]
• 제5항 비음 [m] [n] [ŋ]
• 제6항 유음 [l]
• “([ptk]|m|ng?|l)$”
• 여기까지는 쉬워 보인다
61. 영어 처리 (2)
• 한 단계 더 들어가면
• 제1항 무성 파열음 [p] [t] [k]
• 자음이나 단모음이 아닌 모음 다음의 어말에서는 ‘으’를 붙여 적는다
• 보통 끝의 h는 묵음이지만,
• -th [θ], [ð]
• 묵음 처리되는 모음이 많다
• 주로 프랑스어 어원의 낱말들
• 모음으로 끝나는 정규식을 새로 만든다.
62. 영어 처리 (3)
• 단모음이 아닌 모음 경우마다 처리한다
• 모음이 겹치는 경우
• 묵음이 들어가 장모음이 되는 경우
• 반모음이 결합해 복모음이 되는 경우
• 모음으로 끝나는 것처럼 보이는 받침을 처리한다
• -ole, –ale, -ome, -ume, -tte 등
• 노골적인 프랑스어까지 처리하진 않아도 된다: rendezvous
63. 결과
2014-03-12 입니다.
23:09:12 김재석 [gim] 뭘만드는지 모르겠다
23:09:13 김재석 [gim] 님이 이미지를 전송합니다.
23:10:13 전형규 [henjeon] 이거
23:10:19 전형규 [henjeon] 어셋스토어에 10만원에 팔자
23:10:44 전형규 [henjeon] 는 농담이고
23:10:49 전형규 [henjeon] 깃헙에 올리자 나중에
https://github.com/tcaesvk/KoreanFormatInfo
65. 문자열 / 문자열 만들기
• 문자열을 쓸 곳과 문자열을 쌓아 올릴 곳은 구분해야 한다.
• 자주 처리하는 내용은 공간을 더 써서 시간을 아끼고,
읽거나/쓸 때 한 번이지만 끊임없이 늘어나는 내용이면
시간을 약간 더 쓰고 공간을 아끼는 것이 낫다.
• 직접 라이브러리를 만들 경우 가급적 용례를 고려해서 선택한다.
66. 서식 문자열
• 지역화 문자열을 만드는 데 쓸 최소한의 조건은 만족해야 한다.
• 잘 만들어진 서식 문자열 처리 방법이 있으면
다양하게 확장해서 쓸 수 있다.
• 반복적으로 사용되는 형식의 문장은 서식 문자열을 이용해서
문자열 틀로부터 생성하면 문자열 직렬화에서 이득을 볼 수 있다.