Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Remake of Hangulize

Remake of Hangulize

https://hangulize.org/

〈한글라이즈〉는 외국어 단어를 외래어 표기법에 따라 한글로 옮겨 적어주는 도구입니다. "Espresso"를 "에스프레소"로, "東京"을 "도쿄"로 변환할 수 있죠. 본래 Python으로 구현했던 한글라이즈를 Go로 재구현하면서 겪은 경험과 느낀점을 공유합니다.

고랭코리아 2018년 8월 밋업에서 발표했습니다.

Heungsub Lee

August 27, 2018
Tweet

Other Decks in Programming

Transcript

  1. 이흥섭
    2018년 8월 고랭코리아 밋업
    재제작기

    View Slide

  2. 이흥섭
    2018년 8월 고랭코리아 밋업
    재제작기
    안녕하세요.

    View Slide

  3. 이흥섭
    2018년 8월 고랭코리아 밋업
    재제작기
    2018년 8월 고랭코리아 밋업에서
    〈한글라이즈 재제작기〉를 발표하는

    View Slide

  4. 이흥섭
    sublee
    이흥섭이라고 합니다.
    반갑습니다.

    View Slide

  5. •야생의 땅: 듀랑고
    •카트라이더 코인러시
    •카트라이더 대시
    넥슨 왓 스튜디오 서버아키텍트
    저는 넥슨 왓 스튜디오에서
    서버아키텍트를 맡고 있고

    View Slide

  6. •야생의 땅: 듀랑고
    •카트라이더 코인러시
    •카트라이더 대시
    넥슨 왓 스튜디오 서버아키텍트
    얼마 전 〈야생의 땅: 듀랑고〉를
    출시했습니다.

    View Slide

  7. •what-studio/profiling
    •sublee/trueskill
    •what-studio/tossi
    •hangulize/hangulize
    오픈소스
    2744
    385
    110
    53
    개수는 2018년 9월 6일 기준

    View Slide

  8. •what-studio/profiling
    •sublee/trueskill
    •what-studio/tossi
    •hangulize/hangulize
    오픈소스
    2744
    385
    110
    53
    개수는 2018년 9월 6일 기준
    한편으론 틈틈이
    오픈소스 활동도 하고 있어요.

    View Slide

  9. •what-studio/profiling
    •sublee/trueskill
    •what-studio/tossi
    •hangulize/hangulize
    오픈소스
    2744
    385
    110
    53
    개수는 2018년 9월 6일 기준
    제가 주축이 된 오픈소스 프로젝트 중에
    별이 많은 것만 한 번 추려봤는데

    View Slide

  10. •what-studio/profiling
    •sublee/trueskill
    •what-studio/tossi
    •hangulize/hangulize
    오픈소스
    2744
    385
    110
    53
    개수는 2018년 9월 6일 기준
    이 중에선 가장 별이 적은
    〈한글라이즈〉가 오늘 발표의 주제입니다.

    View Slide

  11. Go 코딩
    진지한 장난감 협업
    장난감
    옹알이
    실무 리뷰 구루

    View Slide

  12. Go 코딩
    진지한 장난감 협업
    장난감
    옹알이
    실무 리뷰 구루
    우리가 새로운 언어를 습득해 나갈 때
    아마 이런 과정을 거치게 될 것 같은데

    View Slide

  13. Go 코딩
    협업
    장난감
    옹알이
    실무 리뷰 구루
    고랭코리아
    진지한 장난감
    Go 언어의 경우 고랭코리아 여러분은
    대부분 이쯤에 계실 것 같습니다.

    View Slide

  14. Go 코딩
    진지한 장난감 협업
    장난감
    옹알이
    실무 리뷰 구루

    반면 저는
    여기 쯤에 있어요.

    View Slide

  15. Go 코딩
    진지한 장난감 협업
    장난감
    옹알이
    실무 리뷰 구루

    Go 코딩은 매일 하고 있지만
    아직 본격적으로 실무에 써보진 못 했습니다.

    View Slide

  16. Go 코딩
    진지한 장난감 협업
    장난감
    옹알이
    실무 리뷰 구루

    한글라이즈도 제 본업과는
    전혀 무관하게

    View Slide

  17. 지난 3개월
    일과 후 취미코딩
    지난 3개월동안 매진했던
    일과 후 취미코딩이었어요.

    View Slide

  18. 지난 3개월
    일과 후 취미코딩
    그러다보니 아마 이 발표에서
    제가 여러분에게

    View Slide

  19. 지난 3개월
    일과 후 취미코딩
    Go에 대한 새로운 지식을
    전해 드리진 못 할 것 같은데

    View Slide

  20. 지난 3개월
    일과 후 취미코딩
    그래도 취미로 익히면서
    재밌었던 점을 소개해보려고 합니다.

    View Slide

  21. 지난 3개월
    일과 후 취미코딩
    학예회 보듯이 재밌게
    봐주시면 감사하겠습니다.

    View Slide

  22. 1. 한글라이즈
    2. Go
    3. 이룬 것
    차례

    View Slide

  23. 1. 한글라이즈
    2. Go
    3. 이룬 것
    차례
    우선 오늘 발표의
    내용은 이렇습니다.

    View Slide

  24. 1. 한글라이즈
    2. Go
    3. 이룬 것
    차례
    제가 만들고 있는
    한글라이즈에 대해 소개하고

    View Slide

  25. 1. 한글라이즈
    2. Go
    3. 이룬 것
    차례
    한글라이즈를 Go로 만들면서 느낀
    흥미로웠던 점에 대해서 말씀드릴게요.

    View Slide

  26. 1. 한글라이즈
    2. Go
    3. 이룬 것
    차례
    그리고 발표 제목에
    "재제작기"라고 적었듯이

    View Slide

  27. 1. 한글라이즈
    2. Go
    3. 이룬 것
    차례
    8년 전에 파이썬으로 만들었던 한글라이즈를
    이번에 Go로 다시 구현한 것이거든요.

    View Slide

  28. 1. 한글라이즈
    2. Go
    3. 이룬 것
    차례
    예전과 비교해서 어떤 성과를
    이뤘는지 보여드리겠습니다.

    View Slide

  29. 1. 한글라이즈
    그럼 지금부터 한글라이즈가 무엇이고
    이 프로젝트가 어떻게 시작됐는지

    View Slide

  30. 1. 한글라이즈
    그리고 어떤 원리로
    돌아가는지 소개해드릴게요.

    View Slide

  31. 외국어 단어를
    한글로 옮겨 적는 도구
    한글라이즈

    View Slide

  32. 외국어 단어를
    한글로 옮겨 적는 도구
    한글라이즈
    한글라이즈는 외국어 단어를
    한글로 옮겨 적어주는 도구예요.

    View Slide

  33. 말소리를 음성 문자로 옮겨 적음.다음사전
    의미를 옮기는 번역(translation)과는 달라요.
    전사(transcription)
    좀 더 정확히는
    "전사"라고 부르는데

    View Slide

  34. 말소리를 음성 문자로 옮겨 적음.다음사전
    의미를 옮기는 번역(translation)과는 달라요.
    전사(transcription)
    다음사전에서 찾아보면 말소리를 음성 문자로
    옮겨 적는 걸 뜻한다고 합니다.

    View Slide

  35. 말소리를 음성 문자로 옮겨 적음.다음사전
    의미를 옮기는 번역(translation)과는 달라요.
    전사(transcription)
    한글라이즈의 역할은
    외국어 단어의 의미를 해석해서

    View Slide

  36. 말소리를 음성 문자로 옮겨 적음.다음사전
    의미를 옮기는 번역(translation)과는 달라요.
    전사(transcription)
    우리말로 번역하는 게 아니라
    발음만 한글로 표기하는 것이죠.

    View Slide

  37. Go▶ 고(전사)
    ▶ 가(번역)
    영어 단어 "Go"를 예로 들면

    View Slide

  38. Go▶ 고(전사)
    ▶ 가(번역)
    발음 그대로 "고"로 옮기는 건 전사고

    View Slide

  39. Go▶ 고(전사)
    ▶ 가(번역)
    의미를 살려 우리말 "가"로
    옮기는 건 번역입니다.

    View Slide

  40. PlayOverwatch
    Lúcio ▶ 루시우 花村 ▶ 하나무라
    인명 지명
    Overwatch Wiki

    View Slide

  41. PlayOverwatch
    Lúcio ▶ 루시우 花村 ▶ 하나무라
    인명 지명
    Overwatch Wiki
    전사는 인명이나 지명같은 고유명사나 외래어를
    우리말로 옮길 때 필요합니다.

    View Slide

  42. PlayOverwatch
    Lúcio ▶ 루시우 花村 ▶ 하나무라
    인명 지명
    Overwatch Wiki
    지명인 "하나무라"를 굳이 "꽃 마을"이라고
    뜻을 번역해서 옮기지는 않겠죠.

    View Slide

  43. 국립국어원이 정한
    외래어 네이밍 컨벤션
    외래어 표기법
    이렇게 외래어를
    한글로 전사할 때 우리는

    View Slide

  44. 국립국어원이 정한
    외래어 네이밍 컨벤션
    외래어 표기법
    귀에 들리는 대로
    주먹구구식으로 옮기는 대신

    View Slide

  45. 국립국어원이 정한
    외래어 네이밍 컨벤션
    외래어 표기법
    국립국어원에서 정한
    "외래어 표기법"을 따라야 합니다.

    View Slide

  46. 국립국어원이 정한
    외래어 네이밍 컨벤션
    외래어 표기법
    코딩할 때 따르는 네이밍 컨벤션과
    비슷하다고 보면 될 것 같아요.

    View Slide

  47. 국립국어원이 정한
    외래어 네이밍 컨벤션
    외래어 표기법
    모두가 외래어 표기법을
    잘 따르는 건 아니지만

    View Slide

  48. 국립국어원이 정한
    외래어 네이밍 컨벤션
    외래어 표기법
    그래도 이게 있는 덕분에 외래어의 한글표기가
    일관성을 어느정도 지켜갈 수 있는 거죠.

    View Slide

  49. Cappuccino이탈리아어

    몇 가지 예시를 들어볼게요.

    View Slide

  50. Cappuccino이탈리아어

    익숙한 이탈리아어 단어인
    "Cappuccino"입니다.

    View Slide

  51. Cappuccino이탈리아어
    ▶ 캡푸씨노…?
    어쩌면 "캡푸씨노"라고
    옮겨도 말이 될 것 같은데

    View Slide

  52. Cappuccino이탈리아어
    ▶ 카푸치노
    우린 외래어 표기법에 따라서
    이 단어를 "카푸치노"라고 옮깁니다.

    View Slide

  53. Cappuccino이탈리아어
    ▶ 카푸치노
    "티라미수", "누텔라", "브로콜리"같이
    이탈리아어에서 온 외래어는

    View Slide

  54. Cappuccino이탈리아어
    ▶ 카푸치노
    대체로 외래어 표기법을
    잘 따르는 것 같습니다.

    View Slide

  55. 宮本茂일본어

    이번엔 일본어입니다.
    일본 사람 이름이에요.

    View Slide

  56. 宮本茂일본어
    ▶ 궁본무…?
    아마 한자를 잘 안다면 우리말 한자음을 따서
    "궁본무"라고 옮길 수도 있을 것 같아요.

    View Slide

  57. 宮本茂일본어
    ▶ 미야모토 시게루
    이 이름을 표기법대로 옮기면
    "미야모토 시게루"가 되는데

    View Slide

  58. 宮本茂일본어
    ▶ 미야모토 시게루
    우리말 한자음이 아닌
    일본어 한자음을 따른 겁니다.

    View Slide

  59. 宮本茂일본어
    ▶ 미야모토 시게루
    〈슈퍼마리오〉를 만든 분으로
    게임 업계에서 전설적인 분의 이름이죠.

    View Slide

  60. Χίος그리스어

    이건 그리스에 있는 한 섬의 이름이에요.
    "Xioc"처럼 생기긴 했는데

    View Slide

  61. Χίος그리스어
    ▶ 히오스
    "히오스"라고 옮깁니다.

    View Slide

  62. ピカチュウ일본어
    ▶ 피카츄
    때론 표기법대로 쓰는 게 불편할 수도 있어요.
    일본어 이름인 "피카츄"의 경우

    View Slide

  63. ピカチュウ일본어
    ▶ 피카추
    외래어 표기법에 따르면
    "츄"가 아닌 "추"로 표기해야 합니다.

    View Slide

  64. • ピカチュウ ▶ 피카츄
    •靑島 ▶ 칭따오
    • Chevrolet ▶ 쉐보레
    어디까지나 권고사항
    피카추
    칭다오
    셰브럴레이
    하지만 외래어 표기법은
    어디까지나 권고사항일 뿐이라서

    View Slide

  65. • ピカチュウ ▶ 피카츄
    •靑島 ▶ 칭따오
    • Chevrolet ▶ 쉐보레
    어디까지나 권고사항
    피카추
    칭다오
    셰브럴레이
    이미 다른 표기가 널리 퍼져 있는 브랜드라면
    국립국어원에서도 그쪽의 손을 들어주고 있습니다.

    View Slide

  66. 제1항
    외래어는 국어의 현용 24 자모만으로 적는다.
    제2항
    외래어의 1 음운은 원칙적으로 1 기호로 적는다.
    제3항
    받침에는 ㄱ, ㄴ, ㄹ, ㅁ, ㅂ, ㅅ, ㅇ만을 쓴다.
    제4항
    파열음 표기에는 된소리를 쓰지 않는 것을 원칙으로 한다.
    제5항
    이미 굳어진 외래어는 관용을 존중하되,
    그 범위와 용례는 따로 정한다.
    외래어 표기법
    자음 반모음 모음
    국제 음성
    기호
    한글 국제 음성
    기호
    한글 국제 음성
    기호
    한글
    모음 앞 자음 앞
    또는 어

    p ㅍ ㅂ, 프 j 이 i 이
    b ㅂ 브 ɥ 위 y 위
    t ㅌ ㅅ, 트 w 오, 우 e 에
    d ㄷ 드 φ 외
    k ㅋ ㄱ, 크 ɛ 에
    g ㄱ 그 ɛ̃ 앵
    f ㅍ 프 œ 외
    v ㅂ 브 œ̃ 욍
    θ ㅅ 스 æ 애
    ð ㄷ 드 a 아
    s ㅅ 스 ɑ 아

    View Slide

  67. 제1항
    외래어는 국어의 현용 24 자모만으로 적는다.
    제2항
    외래어의 1 음운은 원칙적으로 1 기호로 적는다.
    제3항
    받침에는 ㄱ, ㄴ, ㄹ, ㅁ, ㅂ, ㅅ, ㅇ만을 쓴다.
    제4항
    파열음 표기에는 된소리를 쓰지 않는 것을 원칙으로 한다.
    제5항
    이미 굳어진 외래어는 관용을 존중하되,
    그 범위와 용례는 따로 정한다.
    외래어 표기법
    자음 반모음 모음
    국제 음성
    기호
    한글 국제 음성
    기호
    한글 국제 음성
    기호
    한글
    모음 앞 자음 앞
    또는 어

    p ㅍ ㅂ, 프 j 이 i 이
    b ㅂ 브 ɥ 위 y 위
    t ㅌ ㅅ, 트 w 오, 우 e 에
    d ㄷ 드 φ 외
    k ㅋ ㄱ, 크 ɛ 에
    g ㄱ 그 ɛ̃ 앵
    f ㅍ 프 œ 외
    v ㅂ 브 œ̃ 욍
    θ ㅅ 스 æ 애
    ð ㄷ 드 a 아
    s ㅅ 스 ɑ 아
    외래어 표기법은 이런
    규칙집으로 이뤄져 있습니다.

    View Slide

  68. 제1항
    외래어는 국어의 현용 24 자모만으로 적는다.
    제2항
    외래어의 1 음운은 원칙적으로 1 기호로 적는다.
    제3항
    받침에는 ㄱ, ㄴ, ㄹ, ㅁ, ㅂ, ㅅ, ㅇ만을 쓴다.
    제4항
    파열음 표기에는 된소리를 쓰지 않는 것을 원칙으로 한다.
    제5항
    이미 굳어진 외래어는 관용을 존중하되,
    그 범위와 용례는 따로 정한다.
    외래어 표기법
    자음 반모음 모음
    국제 음성
    기호
    한글 국제 음성
    기호
    한글 국제 음성
    기호
    한글
    모음 앞 자음 앞
    또는 어

    p ㅍ ㅂ, 프 j 이 i 이
    b ㅂ 브 ɥ 위 y 위
    t ㅌ ㅅ, 트 w 오, 우 e 에
    d ㄷ 드 φ 외
    k ㅋ ㄱ, 크 ɛ 에
    g ㄱ 그 ɛ̃ 앵
    f ㅍ 프 œ 외
    v ㅂ 브 œ̃ 욍
    θ ㅅ 스 æ 애
    ð ㄷ 드 a 아
    s ㅅ 스 ɑ 아
    국립국어원 홈페이지에서
    누구나 자유롭게 볼 수 있죠.

    View Slide

  69. 제1항
    외래어는 국어의 현용 24 자모만으로 적는다.
    제2항
    외래어의 1 음운은 원칙적으로 1 기호로 적는다.
    제3항
    받침에는 ㄱ, ㄴ, ㄹ, ㅁ, ㅂ, ㅅ, ㅇ만을 쓴다.
    제4항
    파열음 표기에는 된소리를 쓰지 않는 것을 원칙으로 한다.
    제5항
    이미 굳어진 외래어는 관용을 존중하되,
    그 범위와 용례는 따로 정한다.
    외래어 표기법
    자음 반모음 모음
    국제 음성
    기호
    한글 국제 음성
    기호
    한글 국제 음성
    기호
    한글
    모음 앞 자음 앞
    또는 어

    p ㅍ ㅂ, 프 j 이 i 이
    b ㅂ 브 ɥ 위 y 위
    t ㅌ ㅅ, 트 w 오, 우 e 에
    d ㄷ 드 φ 외
    k ㅋ ㄱ, 크 ɛ 에
    g ㄱ 그 ɛ̃ 앵
    f ㅍ 프 œ 외
    v ㅂ 브 œ̃ 욍
    θ ㅅ 스 æ 애
    ð ㄷ 드 a 아
    s ㅅ 스 ɑ 아
    하지만 워낙 복잡해서 아무리 잘 따르려 노력해도
    틀리는 경우가 많습니다.

    View Slide

  70. •정기적으로 각 외래어의 한글 표기 결정
    • 언론에 보도되는 이름 중심
    정부·언론 외래어 심의 공동위원회
    그래서 바른 말 쓰기를
    특히 중요하게 여기는 정부와 언론 쪽에선

    View Slide

  71. •정기적으로 각 외래어의 한글 표기 결정
    • 언론에 보도되는 이름 중심
    정부·언론 외래어 심의 공동위원회
    외래어 표기법이
    잘 지켜지고 있는지 평가하고

    View Slide

  72. •정기적으로 각 외래어의 한글 표기 결정
    • 언론에 보도되는 이름 중심
    정부·언론 외래어 심의 공동위원회
    정기적으로 공식 외래어 표기를 발표하는
    위원회를 두고 있어요.

    View Slide

  73. •정기적으로 각 외래어의 한글 표기 결정
    • 언론에 보도되는 이름 중심
    정부·언론 외래어 심의 공동위원회
    "정부·언론 외래어 심의 공동위원회"라는 곳인데
    코드리뷰어 집단이라고 생각하면 될 것 같습니다.

    View Slide

  74. 제92차 정부·언론외래어심의공동위원회 심의 결정안
    (인명 52건, 일반용어 1건-재심의 2건)
    • 아베라, 암살라 Amsale Aberra 1954(?1953)~ 에티오피아
    여성 기업가·디자이너. 암살라(Amsale) 그룹 대표 겸 디자
    인 총책임자. 유행을 좇지 않으면서 세련된 클래식 모던을
    강조하는 디자인으로 유명함.
    • 아벨란제, 주앙 João Havelange 1916~ 국제축구연맹(FIFA)
    회장(1974~1998). 브라질 인.
    • 그루벨, 루스 Ruth M. Grubel 1950~ 미국 교육가·선교사.
    일본 간사이(關西)학원 원장(2007. 4.~ ).

    View Slide

  75. 제92차 정부·언론외래어심의공동위원회 심의 결정안
    (인명 52건, 일반용어 1건-재심의 2건)
    • 아베라, 암살라 Amsale Aberra 1954(?1953)~ 에티오피아
    여성 기업가·디자이너. 암살라(Amsale) 그룹 대표 겸 디자
    인 총책임자. 유행을 좇지 않으면서 세련된 클래식 모던을
    강조하는 디자인으로 유명함.
    • 아벨란제, 주앙 João Havelange 1916~ 국제축구연맹(FIFA)
    회장(1974~1998). 브라질 인.
    • 그루벨, 루스 Ruth M. Grubel 1950~ 미국 교육가·선교사.
    일본 간사이(關西)학원 원장(2007. 4.~ ).
    이건 외래어 심의위가 발표한
    표기 심의 결정안 중 하나인데

    View Slide

  76. 제92차 정부·언론외래어심의공동위원회 심의 결정안
    (인명 52건, 일반용어 1건-재심의 2건)
    • 아베라, 암살라 Amsale Aberra 1954(?1953)~ 에티오피아
    여성 기업가·디자이너. 암살라(Amsale) 그룹 대표 겸 디자
    인 총책임자. 유행을 좇지 않으면서 세련된 클래식 모던을
    강조하는 디자인으로 유명함.
    • 아벨란제, 주앙 João Havelange 1916~ 국제축구연맹(FIFA)
    회장(1974~1998). 브라질 인.
    • 그루벨, 루스 Ruth M. Grubel 1950~ 미국 교육가·선교사.
    일본 간사이(關西)학원 원장(2007. 4.~ ).
    아버라, 암살러
    그루블
    심의위에서도 드물게
    틀리는 경우가 있습니다.

    View Slide

  77. 제92차 정부·언론외래어심의공동위원회 심의 결정안
    (인명 52건, 일반용어 1건-재심의 2건)
    • 아베라, 암살라 Amsale Aberra 1954(?1953)~ 에티오피아
    여성 기업가·디자이너. 암살라(Amsale) 그룹 대표 겸 디자
    인 총책임자. 유행을 좇지 않으면서 세련된 클래식 모던을
    강조하는 디자인으로 유명함.
    • 아벨란제, 주앙 João Havelange 1916~ 국제축구연맹(FIFA)
    회장(1974~1998). 브라질 인.
    • 그루벨, 루스 Ruth M. Grubel 1950~ 미국 교육가·선교사.
    일본 간사이(關西)학원 원장(2007. 4.~ ).
    아버라, 암살러
    그루블
    원 단어의 발음을 잘못 유추하는 바람에
    표기를 잘못 정하는 경우가 종종 있다고 해요.

    View Slide

  78. •세계의 말과 글
    •끝소리
    박종성
    @iceager

    View Slide

  79. •세계의 말과 글
    •끝소리
    박종성
    @iceager
    한편 예전부터 외래어 표기법에
    큰 관심을 보인 분이 있는데

    View Slide

  80. •세계의 말과 글
    •끝소리
    박종성
    @iceager
    바로 박종성 님입니다.

    View Slide

  81. •세계의 말과 글
    •끝소리
    박종성
    @iceager
    종성 님은 "세계의 말과 글"이라는 블로그와
    "끝소리"라는 페이스북 페이지에서

    View Slide

  82. •세계의 말과 글
    •끝소리
    박종성
    @iceager
    외래어 표기법이나 여러가지 언어에 대한
    글을 연재하고 계세요.

    View Slide

  83. •세계의 말과 글
    •끝소리
    박종성
    @iceager
    연재하는 글이 굉장히
    깊고 재밌으니

    View Slide

  84. •세계의 말과 글
    •끝소리
    박종성
    @iceager
    혹시 이 발표가 흥미롭다면
    한 번 들어가 보길 추천해드립니다.

    View Slide

  85. •세계의 말과 글
    •끝소리
    외래어 심의 위원
    박종성
    @iceager
    종성 님은 작년부터는
    글 연재 이외에

    View Slide

  86. •세계의 말과 글
    •끝소리
    외래어 심의 위원
    박종성
    @iceager
    외래어 심의위 위원으로도
    활동하고 계십니다.

    View Slide

  87. 정기적으로 회의를 열어 용례를 정하는 것으
    로는 한계가 있다. 외래어 표기 심의 방식이
    자동화되어 한글로 표기하고 싶은 외국어를
    입력하자마자 한글 표기가 나와야 한다.
    http://iceager.egloos.com/2610028

    View Slide

  88. 정기적으로 회의를 열어 용례를 정하는 것으
    로는 한계가 있다. 외래어 표기 심의 방식이
    자동화되어 한글로 표기하고 싶은 외국어를
    입력하자마자 한글 표기가 나와야 한다.
    http://iceager.egloos.com/2610028
    8년 전, 종성 님은 블로그에
    이런 글을 쓰셨어요.

    View Slide

  89. 정기적으로 회의를 열어 용례를 정하는 것으
    로는 한계가 있다. 외래어 표기 심의 방식이
    자동화되어 한글로 표기하고 싶은 외국어를
    입력하자마자 한글 표기가 나와야 한다.
    http://iceager.egloos.com/2610028
    정기적으로 회의를 열어
    용례를 정하는 것으로는 한계가 있다.

    View Slide

  90. 정기적으로 회의를 열어 용례를 정하는 것으
    로는 한계가 있다. 외래어 표기 심의 방식이
    자동화되어 한글로 표기하고 싶은 외국어를
    입력하자마자 한글 표기가 나와야 한다.
    http://iceager.egloos.com/2610028
    외래어 표기 심의 방식이 자동화되어

    View Slide

  91. 정기적으로 회의를 열어 용례를 정하는 것으
    로는 한계가 있다. 외래어 표기 심의 방식이
    자동화되어 한글로 표기하고 싶은 외국어를
    입력하자마자 한글 표기가 나와야 한다.
    http://iceager.egloos.com/2610028
    한글로 표기하고 싶은 외국어를 입력하자마자
    한글 표기가 나와야 한다.

    View Slide

  92. 강범모, 《언어: 풀어 쓴 언어학 개론》(2005)
    잠깐 샛길로 빠지면, 제가 대학교 다닐 때
    제일 좋아했던 강의는 〈언어학 개론〉이었거든요.

    View Slide

  93. 강범모, 《언어: 풀어 쓴 언어학 개론》(2005)
    언어학은 사람이 구사하는 언어를
    연구하는 과학분야인데

    View Slide

  94. 강범모, 《언어: 풀어 쓴 언어학 개론》(2005)
    학생 절반이 수능시험의
    언어영역 생각하고 들어왔다가

    View Slide

  95. 강범모, 《언어: 풀어 쓴 언어학 개론》(2005)
    첫 강의만 듣고 대거 취소했던 강의이긴 하지만
    저에겐 인생 강의였습니다.

    View Slide

  96. 강범모, 《언어: 풀어 쓴 언어학 개론》(2005)
    언어학을 전공한 건 아니더라도
    늘 덕심을 갖고 있었죠.

    View Slide

  97. 정기적으로 회의를 열어 용례를 정하는 것으
    로는 한계가 있다. 외래어 표기 심의 방식이
    자동화되어 한글로 표기하고 싶은 외국어를
    입력하자마자 한글 표기가 나와야 한다.
    http://iceager.egloos.com/2610028
    그런 전 종성 님의 이 글을 보고
    깊은 감명을 받았어요.

    View Slide

  98. 정기적으로 회의를 열어 용례를 정하는 것으
    로는 한계가 있다. 외래어 표기 심의 방식이
    자동화되어 한글로 표기하고 싶은 외국어를
    입력하자마자 한글 표기가 나와야 한다.
    http://iceager.egloos.com/2610028
    외래어 표기법이 자동화되면
    당장 저에게도 도움될 것 같았고

    View Slide

  99. 정기적으로 회의를 열어 용례를 정하는 것으
    로는 한계가 있다. 외래어 표기 심의 방식이
    자동화되어 한글로 표기하고 싶은 외국어를
    입력하자마자 한글 표기가 나와야 한다.
    http://iceager.egloos.com/2610028
    그걸 만드는 과정도
    굉장히 재밌어 보였죠.

    View Slide

  100. 그래서 덥석 물었습니다.

    View Slide

  101. 아쉽게도 비공개 덧글이고 암호도 잊어서
    뭐라고 썼었는진 모르겠지만

    View Slide

  102. 그렇게 종성 님과 둘이서
    외래어 표기법을 자동화하기 시작했어요.

    View Slide

  103. 파이썬

    View Slide

  104. 파이썬
    당시엔 한창 파이썬을 익히는 중이어서
    파이썬으로 개발했고

    View Slide

  105. >>> from hangulize import *
    >>> hangulize(u'Cappuccino', 'ita')
    u'카푸치노'
    옛 한글라이즈
    이런 식으로 파이썬 환경에서 쓸 수 있는
    "hangulize" 라이브러리를 만들었습니다.

    View Slide

  106. >>> from hangulize import *
    >>> hangulize(u'Cappuccino', 'ita')
    u'카푸치노'
    옛 한글라이즈
    이 파이썬 구현을
    "옛 한글라이즈"라고 부를게요.

    View Slide

  107. https://hangulize.org/
    꼭 프로그래머가 아니더라도
    누구나 쉽게 쓸 수 있도록

    View Slide

  108. https://hangulize.org/
    "hangulize.org" 웹 서비스도 운영해왔는데

    View Slide

  109. 주로 번역가가 사용
    이지민, 《그래도 번역가로 살겠다면》(2017)
    이 웹 서비스가 번역가 분들에겐
    소소한 도움을 주고 있는 것 같더라고요.

    View Slide

  110. •주먹구구식 구현
    •고치기 어려운 버그
    •전사 규칙이 파이썬 코드
    옛 한글라이즈 불만
    하지만 제가 어렸을 때
    만든 것이다 보니

    View Slide

  111. •주먹구구식 구현
    •고치기 어려운 버그
    •전사 규칙이 파이썬 코드
    옛 한글라이즈 불만
    지금 보면 맘에 들지 않는
    부분도 몇 가지 있는데

    View Slide

  112. •주먹구구식 구현
    •고치기 어려운 버그
    •전사 규칙이 파이썬 코드
    옛 한글라이즈 불만
    주먹구구식 구현으로 고치기 어려운
    버그를 만든 것도 문제지만

    View Slide

  113. •주먹구구식 구현
    •고치기 어려운 버그
    •전사 규칙이 파이썬 코드
    옛 한글라이즈 불만
    특히 외래어 표기법 전사 규칙을
    파이썬 코드로 쓰게 했던 점이 가장 후회됩니다.

    View Slide

  114. •주먹구구식 구현
    •고치기 어려운 버그
    •전사 규칙이 파이썬 코드
    옛 한글라이즈 불만
    프로그래머가 아니면 진입장벽도 높고
    버그를 야기할 여지도 많아서

    View Slide

  115. •주먹구구식 구현
    •고치기 어려운 버그
    •전사 규칙이 파이썬 코드
    옛 한글라이즈 불만
    새 표기법을 구현할 때 생산성이
    그리 좋지 않았던 것 같아요.

    View Slide

  116. 옛 한글라이즈
    2010-2018
    이런 후회를 뒤로 하고 옛 한글라이즈는
    얼마 전에 공식적으로 폐쇄했습니다.

    View Slide

  117. Go
    Go로 완전히 새로 구현했죠.

    View Slide

  118. gore> :import "github.com/hangulize/hangulize"
    gore> hangulize.Hangulize("rus", "Владивосто́
    к")
    "블라디보스토크"
    새 한글라이즈
    2018년 5월-

    View Slide

  119. gore> :import "github.com/hangulize/hangulize"
    gore> hangulize.Hangulize("rus", "Владивосто́
    к")
    "블라디보스토크"
    새 한글라이즈
    2018년 5월-
    "새 한글라이즈"는 8년 만인
    지난 5월부터 만들었어요.

    View Slide

  120. gore> :import "github.com/hangulize/hangulize"
    gore> hangulize.Hangulize("rus", "Владивосто́
    к")
    "블라디보스토크"
    새 한글라이즈
    2018년 5월-
    옛 한글라이즈처럼 Go 환경에서
    쓸 수 있는 간단한 라이브러리죠.

    View Slide

  121. lang:
    id = "rus"
    codes = "ru", "rus"
    english = "Russian"
    korean = "러시아어"
    script = "cyrillic"
    macros:
    "@" = ""
    vars:
    "cs" = "б", "в", "г"
    전사 규칙 .hgl 파일
    rewrite:
    "град" -> "град-"
    "^ль" -> "л-ь"
    "ый" -> "ы"
    transcribe:
    "б" -> "ㅂ"
    "л," -> "-ㄹ"
    test:
    "Ольга" -> "올가"
    "Пётр" -> "표트르"
    새로 구현하면서는 전사 규칙도 코드 대신
    이런 텍스트파일로 정의할 수 있게 설계했는데

    View Slide

  122. lang:
    id = "rus"
    codes = "ru", "rus"
    english = "Russian"
    korean = "러시아어"
    script = "cyrillic"
    macros:
    "@" = ""
    vars:
    "cs" = "б", "в", "г"
    전사 규칙 .hgl 파일
    rewrite:
    "град" -> "град-"
    "^ль" -> "л-ь"
    "ый" -> "ы"
    transcribe:
    "б" -> "ㅂ"
    "л," -> "-ㄹ"
    test:
    "Ольга" -> "올가"
    "Пётр" -> "표트르"
    정해진 틀 안에서 쓰다 보니
    버그가 발생할 여지도 적고

    View Slide

  123. lang:
    id = "rus"
    codes = "ru", "rus"
    english = "Russian"
    korean = "러시아어"
    script = "cyrillic"
    macros:
    "@" = ""
    vars:
    "cs" = "б", "в", "г"
    전사 규칙 .hgl 파일
    rewrite:
    "град" -> "град-"
    "^ль" -> "л-ь"
    "ый" -> "ы"
    transcribe:
    "б" -> "ㅂ"
    "л," -> "-ㄹ"
    test:
    "Ольга" -> "올가"
    "Пётр" -> "표트르"
    맞춤형 문법이라서
    읽기도 훨씬 편해졌습니다.

    View Slide

  124. H 형상, 로마자 i, 화살표, 한글ㅣ
    옛 로고 새 로고
    그리고 8년 만에
    새 로고도 디자인했죠.

    View Slide

  125. 四川 쓰촨

    View Slide

  126. 四川 쓰촨
    이번엔 한글라이즈의 원리를 살펴보기 위해
    중국 지명인 "쓰촨"을 예로 들어보겠습니다.

    View Slide

  127. Rewrite Transcribe
    Phonemize
    四川 쓰촨
    한글라이즈 파이프라인
    한글라이즈에 한자 "四川"이 입력되면

    View Slide

  128. Rewrite Transcribe
    Phonemize
    四川 쓰촨
    한글라이즈 파이프라인
    일련의 파이프라인을 통과해
    최종적으로 "쓰촨"이 되죠.

    View Slide

  129. •뜻글자를 소리글자로
    •사전
    •형태소 분석
    1단계: Phonemize
    Rewrite Transcribe
    Phonemize
    四川 si chuan
    파이프라인의 첫 단계는
    Phonemize 단계인데

    View Slide

  130. •뜻글자를 소리글자로
    •사전
    •형태소 분석
    1단계: Phonemize
    Rewrite Transcribe
    Phonemize
    四川 si chuan
    여기선 뜻글자를
    소리글자로 바꾸는 작업을 합니다.

    View Slide

  131. •뜻글자를 소리글자로
    •사전
    •형태소 분석
    1단계: Phonemize
    Rewrite Transcribe
    Phonemize
    四川 si chuan
    한자 "四川"의 경우
    중국어 병음 "si chuan"으로 바뀌죠.

    View Slide

  132. •뜻글자를 소리글자로
    •사전
    •형태소 분석
    1단계: Phonemize
    Rewrite Transcribe
    Phonemize
    四川 si chuan
    Phonemize 단계가 모든 언어에서
    필요한 건 아니지만

    View Slide

  133. •뜻글자를 소리글자로
    •사전
    •형태소 분석
    1단계: Phonemize
    Rewrite Transcribe
    Phonemize
    四川 si chuan
    중국어나 일본어처럼 뜻글자를 쓰는 경우엔
    이 단계를 거쳐야만 한글로 옮길 수 있습니다.

    View Slide

  134. •뜻글자를 소리글자로
    •사전
    •형태소 분석
    1단계: Phonemize
    Rewrite Transcribe
    Phonemize
    四川 si chuan
    이때 방대한 발음 사전이나
    형태소 분석 같은 기능이 필요한데

    View Slide

  135. •뜻글자를 소리글자로
    •사전
    •형태소 분석
    1단계: Phonemize
    Rewrite Transcribe
    Phonemize
    四川 si chuan
    여기에 어떤 라이브러리를 썼는지는
    뒤에서 다시 소개하겠습니다.

    View Slide

  136. •패턴 찾아 바꾸기
    •표음성 강화
    2단계: Rewrite
    Rewrite Transcribe
    Phonemize
    si chuan
    "{s}i" -> "i,"
    si, chuan
    "{h}uan" -> "wan"
    si, chwan
    "n$" -> "n,"
    si, chwan,

    View Slide

  137. •패턴 찾아 바꾸기
    •표음성 강화
    2단계: Rewrite
    Rewrite Transcribe
    Phonemize
    si chuan
    "{s}i" -> "i,"
    si, chuan
    "{h}uan" -> "wan"
    si, chwan
    "n$" -> "n,"
    si, chwan,
    두 번째 Rewrite 단계에선
    일련의 패턴 찾아 바꾸기로

    View Slide

  138. •패턴 찾아 바꾸기
    •표음성 강화
    2단계: Rewrite
    Rewrite Transcribe
    Phonemize
    si chuan
    "{s}i" -> "i,"
    si, chuan
    "{h}uan" -> "wan"
    si, chwan
    "n$" -> "n,"
    si, chwan,
    앞에서 넘어온 "si chuan"을
    "si, chwan,"로 바꿔줍니다.

    View Slide

  139. •패턴 찾아 바꾸기
    •표음성 강화
    2단계: Rewrite
    Rewrite Transcribe
    Phonemize
    si chuan
    "{s}i" -> "i,"
    si, chuan
    "{h}uan" -> "wan"
    si, chwan
    "n$" -> "n,"
    si, chwan,
    이 단계의 용도는
    소리글자의 표음성을 강화하는 것인데

    View Slide

  140. 표음성
    신도림행 열차
    지옥행 급행열차
    표음성 극대화 형태학적 표기
    신도리맹 녈차
    지오캥 그팽녈차
    여기서 "표음성"이란

    View Slide

  141. 표음성
    신도림행 열차
    지옥행 급행열차
    표음성 극대화 형태학적 표기
    신도리맹 녈차
    지오캥 그팽녈차
    소리글자가 실제 소리에
    대응되는 정도를 뜻합니다.

    View Slide

  142. 표음성
    신도림행 열차
    지옥행 급행열차
    표음성 극대화 형태학적 표기
    신도리맹 녈차
    지오캥 그팽녈차
    한글도 왼쪽처럼 소리나는 대로만
    적으면 표음성은 극대화되지만

    View Slide

  143. 표음성
    신도림행 열차
    지옥행 급행열차
    표음성 극대화 형태학적 표기
    신도리맹 녈차
    지오캥 그팽녈차
    한 눈에 의미를 파악하긴 더 어렵죠.

    View Slide

  144. 표음성
    신도림행 열차
    지옥행 급행열차
    표음성 극대화 형태학적 표기
    신도리맹 녈차
    지오캥 그팽녈차
    그래서 철자법에선 오른쪽처럼
    표음성을 희생하고

    View Slide

  145. 표음성
    신도림행 열차
    지옥행 급행열차
    표음성 극대화 형태학적 표기
    신도리맹 녈차
    지오캥 그팽녈차
    대신 단어의 형태와 어원을
    살리는 경우가 많습니다.

    View Slide

  146. •패턴 찾아 바꾸기
    •표음성 강화
    2단계: Rewrite
    Rewrite Transcribe
    Phonemize
    si chuan
    "{s}i" -> "i,"
    si, chuan
    "{h}uan" -> "wan"
    si, chwan
    "n$" -> "n,"
    si, chwan,
    따라서 소리글자라고 해도 실제 소리에
    1:1 대응되는 경우는 별로 없는데

    View Slide

  147. •패턴 찾아 바꾸기
    •표음성 강화
    2단계: Rewrite
    Rewrite Transcribe
    Phonemize
    si chuan
    "{s}i" -> "i,"
    si, chuan
    "{h}uan" -> "wan"
    si, chwan
    "n$" -> "n,"
    si, chwan,
    한글로 옮기려면 의미가 아닌
    발음이 필요하니까

    View Slide

  148. •패턴 찾아 바꾸기
    •표음성 강화
    2단계: Rewrite
    Rewrite Transcribe
    Phonemize
    si chuan
    "{s}i" -> "i,"
    si, chuan
    "{h}uan" -> "wan"
    si, chwan
    "n$" -> "n,"
    si, chwan,
    이 단계에서 철자로부터
    발음을 최대한 유추합니다.

    View Slide

  149. •한글 자모로 변환
    •패턴 찾아 바꾸기
    •외래어 표기법 구현
    3단계: Transcribe
    Rewrite Transcribe
    Phonemize
    si, chwan,
    "wan,?" -> "ㅘ-ㄴ"
    si, chㅘ-ㄴ
    "i," -> "ㅡ"
    sㅡ chㅘ-ㄴ
    "ch" -> "ㅊ"
    sㅡ ㅊㅘ-ㄴ
    "s" -> "ㅆ"
    ㅆㅡ ㅊㅘ-ㄴ

    View Slide

  150. •한글 자모로 변환
    •패턴 찾아 바꾸기
    •외래어 표기법 구현
    3단계: Transcribe
    Rewrite Transcribe
    Phonemize
    si, chwan,
    "wan,?" -> "ㅘ-ㄴ"
    si, chㅘ-ㄴ
    "i," -> "ㅡ"
    sㅡ chㅘ-ㄴ
    "ch" -> "ㅊ"
    sㅡ ㅊㅘ-ㄴ
    "s" -> "ㅆ"
    ㅆㅡ ㅊㅘ-ㄴ
    그렇게 구한 발음을
    세 번째 Transcribe 단계에선

    View Slide

  151. •한글 자모로 변환
    •패턴 찾아 바꾸기
    •외래어 표기법 구현
    3단계: Transcribe
    Rewrite Transcribe
    Phonemize
    si, chwan,
    "wan,?" -> "ㅘ-ㄴ"
    si, chㅘ-ㄴ
    "i," -> "ㅡ"
    sㅡ chㅘ-ㄴ
    "ch" -> "ㅊ"
    sㅡ ㅊㅘ-ㄴ
    "s" -> "ㅆ"
    ㅆㅡ ㅊㅘ-ㄴ
    대응되는 한글 자모로 바꿔줍니다.

    View Slide

  152. •한글 자모로 변환
    •패턴 찾아 바꾸기
    •외래어 표기법 구현
    3단계: Transcribe
    Rewrite Transcribe
    Phonemize
    si, chwan,
    "wan,?" -> "ㅘ-ㄴ"
    si, chㅘ-ㄴ
    "i," -> "ㅡ"
    sㅡ chㅘ-ㄴ
    "ch" -> "ㅊ"
    sㅡ ㅊㅘ-ㄴ
    "s" -> "ㅆ"
    ㅆㅡ ㅊㅘ-ㄴ
    여기가 외래어 표기법이
    실제로 구현되는 단계죠.

    View Slide

  153. •한글 자모로 변환
    •패턴 찾아 바꾸기
    •외래어 표기법 구현
    3단계: Transcribe
    Rewrite Transcribe
    Phonemize
    si, chwan,
    "wan,?" -> "ㅘ-ㄴ"
    si, chㅘ-ㄴ
    "i," -> "ㅡ"
    sㅡ chㅘ-ㄴ
    "ch" -> "ㅊ"
    sㅡ ㅊㅘ-ㄴ
    "s" -> "ㅆ"
    ㅆㅡ ㅊㅘ-ㄴ
    Transcribe 단계도 Rewrite 단계와 마찬가지로
    일련의 패턴 찾아 바꾸기로 이뤄져 있습니다.

    View Slide

  154. Rewrite Transcribe
    Phonemize
    四川 쓰촨
    한글라이즈 파이프라인
    si chuan si, chwan, ㅆㅡㅊㅘ-ㄴ
    마지막으로 나열된 자모들을
    한글 글자로 모아쓰기하면 전사가 완료돼요.

    View Slide

  155. 아제르바이잔어
    벨라루스어
    불가리아어
    카탈로니아어
    체코어
    중국어
    웨일스어
    독일어
    그리스어
    에스페란토어
    에스토니아어
    핀란드어
    고대 그리스어
    세르보크로아트어
    헝가리어
    아이슬란드어
    이탈리아어
    일본어
    일본어최영애-김용옥
    조지아어제1안
    조지아어제2안
    라틴어
    라트비아어
    리투아니아어
    마케도니아어
    네덜란드어
    폴란드어
    포르투갈어
    브라질 포르투갈어
    루마니아어
    러시아어
    슬로바키아어
    슬로베니아어
    스페인어
    알바니아어
    스웨덴어
    터키어
    우크라이나어
    베트남어
    웨일스어중세

    View Slide

  156. 아제르바이잔어
    벨라루스어
    불가리아어
    카탈로니아어
    체코어
    중국어
    웨일스어
    독일어
    그리스어
    에스페란토어
    에스토니아어
    핀란드어
    고대 그리스어
    세르보크로아트어
    헝가리어
    아이슬란드어
    이탈리아어
    일본어
    일본어최영애-김용옥
    조지아어제1안
    조지아어제2안
    라틴어
    라트비아어
    리투아니아어
    마케도니아어
    네덜란드어
    폴란드어
    포르투갈어
    브라질 포르투갈어
    루마니아어
    러시아어
    슬로바키아어
    슬로베니아어
    스페인어
    알바니아어
    스웨덴어
    터키어
    우크라이나어
    베트남어
    웨일스어중세
    한글라이즈엔 현재 일본어, 헝가리어 등
    총 40개의 전사 규칙이 들어있어요.

    View Slide

  157. 영어
    하지만 아쉽게도 가장 수요가 많은 영어는
    아직 지원하지 못 하고 있습니다.

    View Slide

  158. 영어
    영어는 특히나 표음성이
    낮은 언어라서 그런데

    View Slide

  159. • though ▶
    • through ▶
    • rough ▶
    • cough ▶
    • thought ▶
    • bough ▶
    영어의 낮은 표음성
    예를 들어 "ough"는 이렇게나
    다양한 발음을 갖고 있지만

    View Slide

  160. • though ▶
    • through ▶
    • rough ▶
    • cough ▶
    • thought ▶
    • bough ▶
    영어의 낮은 표음성
    철자 규칙만으로 발음을 정확하게
    유추하는 건 불가능하다고 합니다.

    View Slide

  161. Ghoti ▶
    영어의 낮은 표음성을 비꼬는
    유명한 농담으로 이런 것도 있습니다.

    View Slide

  162. Ghoti ▶
    "고티"라고 읽을 것
    같은 단어인데

    View Slide

  163. Ghoti ▶
    enough
    women
    nation
    "gh"는 "enough"에서, "o"는 "women"에서,
    "ti"는 "nation"에서 따와서

    View Slide

  164. Ghoti ▶ 피시
    enough
    women
    nation
    "피시"라고 읽어야 한다고 합니다.

    View Slide

  165. 2. Go

    View Slide

  166. 2. Go
    이번엔 한글라이즈를 Go로 다시 만들면서
    저에게 흥미로웠던 점들을 소개해 드릴게요.

    View Slide

  167. 초보 주의
    진지한 장난감 협업
    장난감
    옹알이
    실무 리뷰 구루

    고랭코리아
    우선 들어가기 전에 앞에서 말씀드렸듯이
    전 Go를 취미로만 써봤거든요.

    View Slide

  168. 초보 주의
    진지한 장난감 협업
    장난감
    옹알이
    실무 리뷰 구루

    고랭코리아
    큰 코드베이스에서 남들과 협업해보거나
    실무에서 제대로 써본 적이 아직 없습니다.

    View Slide

  169. 초보 주의
    진지한 장난감 협업
    장난감
    옹알이
    실무 리뷰 구루

    고랭코리아
    그래서 너무 당연한 얘기를 하거나
    틀린 얘기를 할 수도 있는데

    View Slide

  170. 초보 주의
    진지한 장난감 협업
    장난감
    옹알이
    실무 리뷰 구루

    고랭코리아
    그럴 경우 부담 없이 [email protected]
    제보해주시면 감사하겠습니다.

    View Slide

  171. 고루틴 끝내준다!
    Go 첫인상

    View Slide

  172. 고루틴 끝내준다!
    Go 첫인상
    몇 년 전에 Go 튜토리얼 책을
    처음 보면서 들었던 첫인상은 이랬습니다.

    View Slide

  173. 고루틴 끝내준다!
    Go 첫인상
    고루틴 끝내준다!

    View Slide

  174. 고루틴 끝내준다!
    Go 첫인상
    이렇게 병렬 프로그래밍을
    쉽게 할 수 있는 환경은 처음 봤었거든요.

    View Slide

  175. 고루틴 끝내준다!
    Go 첫인상
    쓸 때마다 늘 피곤했던
    병렬처리 단위, 채널, 큐 등을

    View Slide

  176. 고루틴 끝내준다!
    Go 첫인상
    언어의 기본 기능으로
    제공한다는 데에 깜짝 놀랐죠.

    View Slide

  177. •고루틴은 끝내주는데
    •그런데 너무 기능이 적다.
    Go 첫인상
    그런데 그 밖엔
    취향에 맞지 않는 점이 많았어요.

    View Slide

  178. •고루틴은 끝내주는데
    •그런데 너무 기능이 적다.
    Go 첫인상
    그 흔한 반복자나 재정의, 예외도 없고
    특히 제네릭이 없어서

    View Slide

  179. •고루틴은 끝내주는데
    •그런데 너무 기능이 적다.
    Go 첫인상
    범용적인 정적 자료구조를
    만들 수 없다는 점도 의아하게 느껴졌습니다.

    View Slide

  180. •고루틴은 끝내주는데
    •그런데 너무 기능이 적다.
    •고퍼도 귀엽지 않고
    Go 첫인상
    그리고 무엇보다도
    고퍼가 영 귀엽지 않았죠.

    View Slide

  181. 이걸로 정말
    제품이 만들어질까?
    Go 첫인상
    이렇게 단순한 언어로 정말 강력한
    제품을 만들 수 있을까 의문이 들었습니다.

    View Slide

  182. Docker etcd Terraform K8s
    하지만 점점 더 많은 유명 프로젝트가
    Go로 만들어지고 있는 모습을 보면서

    View Slide

  183. 된다.
    아주 잘 된다는 걸
    깨닫게 됐죠.

    View Slide

  184. 협업
    장난감
    옹알이
    실무 리뷰 구루
    진지한 장난감
    저도 한 번 Go를 제대로 익혀보고 싶어서
    간단한 취미코딩에 써보기 시작했어요.

    View Slide

  185. https://subl.ee/runker/
    예를 들면 이런 겁니다.

    View Slide

  186. https://subl.ee/runker/
    〈섭리랑카〉라는 간단한
    〈똥피하기〉 패러디 게임인데

    View Slide

  187. https://subl.ee/runker/
    랭킹서버가 Go
    여기서 랭킹서버가 Go와
    구글 앱 엔진으로 돼있습니다.

    View Slide

  188. sublee/subpptx
    지금 이 발표자료에 자막 붙이는 데 쓰고 있는
    "subpptx"도 Go로 만들었어요.

    View Slide

  189. sublee/subpptx
    이 프로젝트에선 고루틴 덕분에
    손쉽게 페이지 단위로 병렬처리할 수 있었죠.

    View Slide

  190. 쓸 만 하다.
    더 잘 하고 싶다.
    이런저런 간단한 장난감을 만들면서 Go를 써보니
    꽤 쓸 만 하고 재미있다는 인상을 받았습니다.

    View Slide

  191. 쓸 만 하다.
    더 잘 하고 싶다.
    Go 특유의 간결함이
    이제 명료함으로 느껴지더라고요.

    View Slide

  192. 쓸 만 하다.
    더 잘 하고 싶다.
    몇 십 줄 짜리 간단한 장난감에서 벗어나
    좀 더 진지한 걸 만들어보면서

    View Slide

  193. 쓸 만 하다.
    더 잘 하고 싶다.
    Go를 더 잘 다루고 싶다고
    생각하게 됐습니다.

    View Slide

  194. 한글라이즈 다시 만들면
    왠지 더 잘 만들 것 같다.

    View Slide

  195. 한글라이즈 다시 만들면
    왠지 더 잘 만들 것 같다.
    석 달 전 마침

    View Slide

  196. 한글라이즈 다시 만들면
    왠지 더 잘 만들 것 같다.
    한글라이즈를 다시 만들면
    왠지 더 잘 만들 것 같다는 생각이 떠올랐어요.

    View Slide

  197. •주먹구구식 구현
    •고치기 어려운 버그
    •전사 규칙이 파이썬 코드
    옛 한글라이즈 불만
    앞에서 말씀드렸듯이 기존 한글라이즈에서
    맘에 들지 않는 구석도 많았고

    View Slide

  198. • 이미 한 번 만들어 봄
    • 적당한 복잡성
    • 계산 중심적
    •유니코드/정규표현식
    •풍부한 테스트케이스
    •언어학 덕질
    연습과제: 한글라이즈
    또 한글라이즈가 저에겐 새로운 언어를 익힐 때
    연습과제로 삼기 꽤 좋은 프로젝트거든요.

    View Slide

  199. • 이미 한 번 만들어 봄
    • 적당한 복잡성
    • 계산 중심적
    •유니코드/정규표현식
    •풍부한 테스트케이스
    •언어학 덕질
    연습과제: 한글라이즈
    이미 한 번 만들어봐서
    불확실성은 별로 없는데

    View Slide

  200. • 이미 한 번 만들어 봄
    • 적당한 복잡성
    • 계산 중심적
    •유니코드/정규표현식
    •풍부한 테스트케이스
    •언어학 덕질
    연습과제: 한글라이즈
    적당히 복잡하면서
    상당히 계산 중심적이다 보니

    View Slide

  201. • 이미 한 번 만들어 봄
    • 적당한 복잡성
    • 계산 중심적
    •유니코드/정규표현식
    •풍부한 테스트케이스
    •언어학 덕질
    연습과제: 한글라이즈
    구조나 알고리즘에 대한 고민도
    다시 한 번 해보게 되고

    View Slide

  202. • 이미 한 번 만들어 봄
    • 적당한 복잡성
    • 계산 중심적
    •유니코드/정규표현식
    •풍부한 테스트케이스
    •언어학 덕질
    연습과제: 한글라이즈
    그 언어가 유니코드와 정규표현식을
    어떻게 다루는지 깊게 겪어볼 수도 있고

    View Slide

  203. • 이미 한 번 만들어 봄
    • 적당한 복잡성
    • 계산 중심적
    •유니코드/정규표현식
    •풍부한 테스트케이스
    •언어학 덕질
    연습과제: 한글라이즈
    또 이미 만들어둔 테스트케이스가 많아서
    제대로 짰는지 검증할 재료도 충분하죠.

    View Slide

  204. • 이미 한 번 만들어 봄
    • 적당한 복잡성
    • 계산 중심적
    •유니코드/정규표현식
    •풍부한 테스트케이스
    •언어학 덕질
    연습과제: 한글라이즈
    마지막으로 제가
    덕질할 수 있는 주제여서

    View Slide

  205. • 이미 한 번 만들어 봄
    • 적당한 복잡성
    • 계산 중심적
    •유니코드/정규표현식
    •풍부한 테스트케이스
    •언어학 덕질
    연습과제: 한글라이즈
    몇 달 정도는 지긋이 해볼 수 있는
    과제이기도 합니다.

    View Slide

  206. • 이미 한 번 만들어 봄
    • 적당한 복잡성
    • 계산 중심적
    •유니코드/정규표현식
    •풍부한 테스트케이스
    •언어학 덕질
    연습과제: 한글라이즈
    그렇게 파이썬으로 만들었던 한글라이즈를
    Go로 다시 만들게 됐습니다.

    View Slide

  207. a. 정규표현식
    b. 말과 글
    c. 테스트와 문서화

    View Slide

  208. a. 정규표현식
    b. 말과 글
    c. 테스트와 문서화
    그럼 Go에서 흥미로웠던
    세 가지 주제로 넘어가 보겠습니다.

    View Slide

  209. a. 정규표현식
    b. 말과 글
    c. 테스트와 문서화
    좀 두서 없을 수도 있는데 정규표현식, 말과 글,
    테스트와 문서화에 대해 다룰 거예요.

    View Slide

  210. a. 정규표현식

    View Slide

  211. a. 정규표현식
    첫 번째는 정규표현식입니다.
    줄여서 "정규식"이라고도 부르는데

    View Slide

  212. /(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-
    ]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-
    \x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-
    ]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-
    5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-
    9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-
    \x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/
    이메일 정규표현식
    http://emailregex.com/
    텍스트 매칭하는 데에 다들
    한 번 쯤은 써보셨을 것 같아요.

    View Slide

  213. /(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-
    ]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-
    \x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-
    ]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-
    5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-
    9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-
    \x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])/
    이메일 정규표현식
    http://emailregex.com/
    정규식 엔진엔 몇 가지
    알고리즘이 있지만

    View Slide

  214. import "regexp"
    Go 표준 정규식 라이브러리는

    View Slide

  215. •안전한 정규표현식 구현
    •문자열 길이에 대해 선형 시간
    •고의적으로 일부 기능 미지원
    RE2
    by Google
    구글에서 만든 정규식 엔진인
    RE2를 기반으로 하고 있습니다.

    View Slide

  216. •안전한 정규표현식 구현
    •문자열 길이에 대해 선형 시간
    •고의적으로 일부 기능 미지원
    RE2
    by Google
    RE2는 평균적으로 가장 빠른
    정규식 엔진은 아니더라도

    View Slide

  217. •안전한 정규표현식 구현
    •문자열 길이에 대해 선형 시간
    •고의적으로 일부 기능 미지원
    RE2
    by Google
    대상 문자열 길이에 정비례하는 선형 시간을
    보장하는 걸 목표로 삼는다고 합니다.

    View Slide

  218. •안전한 정규표현식 구현
    •문자열 길이에 대해 선형 시간
    •고의적으로 일부 기능 미지원
    RE2
    by Google
    그래서 선형 시간에 구현할 수 없는 정규식의
    일부 고급 기능은 고의적으로 지원하지 않죠.

    View Slide

  219. O(mn)
    RE2 성능 보장
    RE2의 시간복잡도는
    평균, 최악 모두 O(mn)입니다.

    View Slide

  220. O(mn)
    RE2 성능 보장
    정규표현식 길이
    대상 문자열 길이
    여기서 m은 정규식 패턴의 길이고
    n은 대상 문자열의 길이예요.

    View Slide

  221. O(mn)
    RE2 성능 보장
    정규표현식 길이
    대상 문자열 길이
    grep 같이 정규식을
    사용자입력으로 받는 프로그램이 아닌 이상

    View Slide

  222. O( n)
    RE2 성능 보장
    대상 문자열 길이
    보통 상수항
    정규식 패턴은 코드에 미리
    적어 두는 경우가 대부분이다 보니

    View Slide

  223. O( n)
    RE2 성능 보장
    대상 문자열 길이
    보통 상수항
    사실상 m을 상수항으로 취급해도 좋습니다.
    상당히 훌륭하죠.

    View Slide

  224. /a?a?a?aaa/를
    "aaa"에 매치
    벤치마크
    Russ Cox, 〈Regular Expression Matching Can Be Simple And Fast〉(2007)

    View Slide

  225. /a?a?a?aaa/를
    "aaa"에 매치
    벤치마크
    Russ Cox, 〈Regular Expression Matching Can Be Simple And Fast〉(2007)
    RE2를 만든 Russ Cox의
    홈페이지에 가보면

    View Slide

  226. /a?a?a?aaa/를
    "aaa"에 매치
    벤치마크
    Russ Cox, 〈Regular Expression Matching Can Be Simple And Fast〉(2007)
    두 종류의 정규식 엔진을 비교하는
    재미있는 벤치마크가 있습니다.

    View Slide

  227. /a?a?a?aaa/를
    "aaa"에 매치
    벤치마크
    Russ Cox, 〈Regular Expression Matching Can Be Simple And Fast〉(2007)
    Russ Cox는
    Go 개발진으로도 유명한 분이죠?

    View Slide

  228. /a?a?a?aaa/를
    "aaa"에 매치
    벤치마크
    Russ Cox, 〈Regular Expression Matching Can Be Simple And Fast〉(2007)
    우선 이 예시를 보시죠.

    View Slide

  229. /a?a?a?aaa/를
    "aaa"에 매치
    벤치마크
    Russ Cox, 〈Regular Expression Matching Can Be Simple And Fast〉(2007)
    패턴엔 /a?/와 리터럴 /a/가
    각각 3개씩 있고

    View Slide

  230. /a?a?a?aaa/를
    "aaa"에 매치
    벤치마크
    Russ Cox, 〈Regular Expression Matching Can Be Simple And Fast〉(2007)
    대상 문자열은 "a" 3개로
    이뤄져 있습니다.

    View Slide

  231. /a?a?a?aaa/를
    "aaa"에 매치
    벤치마크
    Russ Cox, 〈Regular Expression Matching Can Be Simple And Fast〉(2007)
    패턴에서 /a?/는 전부 건너뛰고
    리터럴 /a/ 3개만 매치시켜야

    View Slide

  232. /a?a?a?aaa/를
    "aaa"에 매치
    벤치마크
    Russ Cox, 〈Regular Expression Matching Can Be Simple And Fast〉(2007)
    매치에 성공할 수 있는 패턴이에요.

    View Slide

  233. f(1) = /a?a/를 "a"에 매치
    f(3) = /a?a?a?aaa/를 "aaa"에 매치
    f(5) = /a?a?a?a?a?aaaaa/를 "aaaaa"에 매치
    f(x) = /a?ˣaˣ/를 "aˣ"에 매치
    벤치마크
    Russ Cox, 〈Regular Expression Matching Can Be Simple And Fast〉(2007)
    벤치마크는 패턴과 문자열의
    길이를 바꿔가며 진행할 텐데

    View Slide

  234. f(1) = /a?a/를 "a"에 매치
    f(3) = /a?a?a?aaa/를 "aaa"에 매치
    f(5) = /a?a?a?a?a?aaaaa/를 "aaaaa"에 매치
    f(x) = /a?ˣaˣ/를 "aˣ"에 매치
    벤치마크
    Russ Cox, 〈Regular Expression Matching Can Be Simple And Fast〉(2007)
    이런 식으로 /a?/와 /a/를
    x개만큼 반복하는 패턴과

    View Slide

  235. f(1) = /a?a/를 "a"에 매치
    f(3) = /a?a?a?aaa/를 "aaa"에 매치
    f(5) = /a?a?a?a?a?aaaaa/를 "aaaaa"에 매치
    f(x) = /a?ˣaˣ/를 "aˣ"에 매치
    벤치마크
    Russ Cox, 〈Regular Expression Matching Can Be Simple And Fast〉(2007)
    x개의 "a"로 이뤄진
    대상 문자열을 가지고

    View Slide

  236. f(1) = /a?a/를 "a"에 매치
    f(3) = /a?a?a?aaa/를 "aaa"에 매치
    f(5) = /a?a?a?a?a?aaaaa/를 "aaaaa"에 매치
    f(x) = /a?ˣaˣ/를 "aˣ"에 매치
    벤치마크
    Russ Cox, 〈Regular Expression Matching Can Be Simple And Fast〉(2007)
    x를 늘려가면서
    속도를 비교해볼 겁니다.

    View Slide

  237. f(1) = /a?a/를 "a"에 매치
    f(3) = /a?a?a?aaa/를 "aaa"에 매치
    f(5) = /a?a?a?a?a?aaaaa/를 "aaaaa"에 매치
    f(x) = /a?ˣaˣ/를 "aˣ"에 매치
    벤치마크
    Russ Cox, 〈Regular Expression Matching Can Be Simple And Fast〉(2007)
    저는 파이썬의 정규식
    표준 라이브러리 "re"와

    View Slide

  238. f(1) = /a?a/를 "a"에 매치
    f(3) = /a?a?a?aaa/를 "aaa"에 매치
    f(5) = /a?a?a?a?a?aaaaa/를 "aaaaa"에 매치
    f(x) = /a?ˣaˣ/를 "aˣ"에 매치
    벤치마크
    Russ Cox, 〈Regular Expression Matching Can Be Simple And Fast〉(2007)
    Go의 정규식 표준 라이브러리 "regexp"
    두 가지로 직접 돌려봤어요.

    View Slide

  239. /a?ˣaˣ/를 "aˣ"에 매치
    시간 파이썬의 re
    Go의 regexp
    f(x)
    결과는 이랬습니다.

    View Slide

  240. /a?ˣaˣ/를 "aˣ"에 매치
    시간 파이썬의 re
    Go의 regexp
    f(x)
    파이썬 쪽 곡선이 압도적으로
    가파르게 올라갔죠.

    View Slide

  241. /a?ˣaˣ/를 "aˣ"에 매치
    시간 파이썬의 re
    Go의 regexp
    f(x)
    Russ Cox의 설명에 의하면

    View Slide

  242. /a?ˣaˣ/를 "aˣ"에 매치
    시간
    f(x)
    O(x²)
    O(2ˣ)
    시간복잡도가 Go 쪽은 O(x²)이고
    파이썬 쪽은 O(2ˣ)이라고 합니다.

    View Slide

  243. /a?ˣaˣ/를 "aˣ"에 매치
    시간
    f(x)
    O(x²)
    O(2ˣ)
    언뜻 보면 제곱 시간도
    나쁜 성능처럼 보이지만

    View Slide

  244. /a?ˣaˣ/를 "aˣ"에 매치
    시간
    f(x)
    O(x²)
    O(2ˣ)
    이 벤치마크 함수는 x가 커질 수록
    패턴 길이 m과 문자열 길이 n을 같이 키우니까

    View Slide

  245. /a?ˣaˣ/를 "aˣ"에 매치
    시간
    f(x)
    O(x²)
    O(2ˣ)
    제곱 시간이면 사실은 이상적인
    성능이라고 볼 수 있습니다.

    View Slide

  246. /a?ˣaˣ/를 "aˣ"에 매치
    파이썬 re Go regexp
    f(10) 39.7㎲ 1.8㎲
    f(15) 1.3㎳ 3.8㎲
    f(20) 47.2㎳ 6.6㎲
    f(25) 1.7초 9.7㎲
    f(30) 61.8초 13.9㎲
    f(50) 676일(예상) 38.5㎲
    제가 돌려본 벤치마크 환경에선
    x가 50일 때 Go 쪽은 38.5㎲면 끝나지만

    View Slide

  247. /a?ˣaˣ/를 "aˣ"에 매치
    파이썬 re Go regexp
    f(10) 39.7㎲ 1.8㎲
    f(15) 1.3㎳ 3.8㎲
    f(20) 47.2㎳ 6.6㎲
    f(25) 1.7초 9.7㎲
    f(30) 61.8초 13.9㎲
    f(50) 676일(예상) 38.5㎲
    파이썬 쪽은 1년 9개월이나
    걸릴 것으로 예상되더라고요.

    View Slide

  248. Spencer 류
    펄, PCRE, 파이썬, 루비, 자바
    Thompson 류
    awk, sed, grep, RE2, Go, 러스트

    View Slide

  249. Spencer 류
    펄, PCRE, 파이썬, 루비, 자바
    Thompson 류
    awk, sed, grep, RE2, Go, 러스트
    앞서 정규식 엔진엔 몇 가지
    알고리즘이 있다고 말씀드렸는데

    View Slide

  250. Spencer 류
    펄, PCRE, 파이썬, 루비, 자바
    Thompson 류
    awk, sed, grep, RE2, Go, 러스트
    크게 Spencer 류와 Thompson 류로
    나눌 수 있을 것 같습니다.

    View Slide

  251. Spencer 류
    펄, PCRE, 파이썬, 루비, 자바
    Thompson 류
    awk, sed, grep, RE2, Go, 러스트
    파이썬 re는 Spencer 류에 속하고
    RE2와 Go regexp는 Thompson 류에 속하죠.

    View Slide

  252. Spencer 류
    펄, PCRE, 파이썬, 루비, 자바
    Thompson 류
    awk, sed, grep, RE2, Go, 러스트
    앞에서 돌렸던 벤치마크의 경우
    Spencer 류 엔진에선 지수 시간이 걸리지만

    View Slide

  253. Spencer 류
    펄, PCRE, 파이썬, 루비, 자바
    Thompson 류
    awk, sed, grep, RE2, Go, 러스트
    Thompson 류 엔진에선
    제곱 시간밖에 걸리지 않습니다.

    View Slide

  254. Spencer 류
    펄, PCRE, 파이썬, 루비, 자바
    Thompson 류
    awk, sed, grep, RE2, Go, 러스트
    왜 이런 차이가 생기는지
    x=3일 때를 예로 들어서 살펴볼게요.

    View Slide

  255. Spencer 류
    "aaa"
    a? a? a? aaa
    a?가 있다고 가정
    a?가 없다고 가정

    View Slide

  256. Spencer 류
    "aaa"
    a? a? a? aaa
    a?가 있다고 가정
    a?가 없다고 가정
    Spencer 류 엔진은
    /a?/라는 분기를 만나면

    View Slide

  257. Spencer 류
    "aaa"
    a? a? a? aaa
    a?가 있다고 가정
    a?가 없다고 가정
    우선 /a?/가 존재한다고 가정하고
    다음으로 넘어갑니다.

    View Slide

  258. Spencer 류
    "aaa"
    a? a? a? aaa
    a?가 있다고 가정
    a?가 없다고 가정
    /a?a?a?/가 전부 있다고
    가정하고 끝까지 가보면

    View Slide

  259. Spencer 류
    "aaa"
    a? a? a? aaa
    a?가 있다고 가정
    a?가 없다고 가정
    대상 문자열의 끝에 도달해서
    리터럴 /a/를 매치시킬 곳이 없단 걸 깨닫죠.

    View Slide

  260. Spencer 류
    "aaa"
    a? a? a? aaa
    aaa
    a?가 있다고 가정
    a?가 없다고 가정
    그럼 마지막 분기로 되돌아가서
    그 /a?/가 없다고 가정합니다.

    View Slide

  261. Spencer 류
    "aaa"
    a? a? a? aaa
    aaa
    a?가 있다고 가정
    a?가 없다고 가정
    하지만 이 길 역시 틀린 길이죠.

    View Slide

  262. Spencer 류
    "aaa"
    a? a? a? aaa
    a? aaa
    aaa
    aaa
    a?가 있다고 가정
    a?가 없다고 가정
    한 단계 더 물러나서 이번엔
    두 번째 /a?/가 없다고 가정해요.

    View Slide

  263. Spencer 류
    "aaa"
    a? a? a? aaa
    a? aaa
    aaa
    aaa
    a?가 있다고 가정
    a?가 없다고 가정
    그 상태에서 앞에서와 같이
    세 번째 분기도 다시 탐색합니다.

    View Slide

  264. Spencer 류
    "aaa"
    a? a? a? aaa
    a? aaa
    aaa
    aaa
    a?가 있다고 가정
    a?가 없다고 가정
    새로운 두 가지 길이 있지만
    이번에도 모두 틀린 길이죠.

    View Slide

  265. Spencer 류
    "aaa"
    a? a? a? aaa
    a? a? aaa
    a? aaa
    a? aaa
    aaa
    aaa
    aaa
    a?가 있다고 가정
    a?가 없다고 가정 aaa
    이젠 첫 번째 /a?/도 없다고 가정하고
    그동안 탐색했던 길만큼 다시 탐색합니다.

    View Slide

  266. Spencer 류
    "aaa"
    a? a? a? aaa
    a? a? aaa
    a? aaa
    a? aaa
    aaa
    aaa
    aaa
    a?가 있다고 가정
    a?가 없다고 가정 aaa 매치!
    마지막 길까지 살펴보면 마침내
    패턴이 매치된단 걸 알 수 있습니다.

    View Slide

  267. a? a? a? aaa
    a? a? aaa
    a? aaa
    a? aaa
    aaa
    aaa
    aaa
    aaa
    퇴각검색
    (backtracking)
    이런 식으로 일단 길 하나를 쭉 파보고
    틀렸으면 퇴각한 다음

    View Slide

  268. a? a? a? aaa
    a? a? aaa
    a? aaa
    a? aaa
    aaa
    aaa
    aaa
    aaa
    퇴각검색
    (backtracking)
    다른 길로 다시 파보는 방식을
    "퇴각검색"이라고 하는데

    View Slide

  269. a? a? a? aaa
    a? a? aaa
    a? aaa
    a? aaa
    aaa
    aaa
    aaa
    aaa
    퇴각검색
    (backtracking)
    Spencer 류 정규식 엔진은
    분기를 퇴각검색으로 구현합니다.

    View Slide

  270. Thompson 류
    "aaa"
    a?a?a?aaa
    a?a?a?aaa
    a?a?a?aaa
    a?a?a?aaa
    첫 번째 a
    반면 Thompson 류 정규식 엔진은
    대상 문자열의 각 글자에 대해서

    View Slide

  271. Thompson 류
    "aaa"
    a?a?a?aaa
    a?a?a?aaa
    a?a?a?aaa
    a?a?a?aaa
    첫 번째 a
    가능한 선택지를
    모두 평가하면서 전진해요.

    View Slide

  272. Thompson 류
    "aaa"
    a?a?a?aaa
    a?a?a?aaa
    a?a?a?aaa
    a?a?a?aaa
    첫 번째 a
    대상 문자열의 첫 번째 "a"의 경우
    패턴의 세 /a?/ 중 어디에도 매치될 수 있고

    View Slide

  273. Thompson 류
    "aaa"
    a?a?a?aaa
    a?a?a?aaa
    a?a?a?aaa
    a?a?a?aaa
    첫 번째 a
    첫 번째 리터럴 /a/에도 매치될 수 있어서
    총 4가지 가능성을 가집니다.

    View Slide

  274. Thompson 류
    "aaa"
    a?a?a?aaa a?a?a?aaa
    a?a?a?aaa a?a?a?aaa
    a?a?a?aaa a?a?a?aaa
    a?a?a?aaa a?a?a?aaa
    첫 번째 a 두 번째 a
    그 다음 앞쪽 가능성이 참일 경우에 뒤따르게 될
    다음 가능성을 두 번째 "a"에 매치해보고

    View Slide

  275. Thompson 류
    "aaa"
    a?a?a?aaa a?a?a?aaa a?a?a?aaa
    a?a?a?aaa a?a?a?aaa a?a?a?aaa
    a?a?a?aaa a?a?a?aaa a?a?a?aaa
    a?a?a?aaa a?a?a?aaa a?a?a?aaa
    첫 번째 a 두 번째 a 세 번째 a
    세 번째 "a"에서도
    같은 일을 반복합니다.

    View Slide

  276. Thompson 류
    "aaa"
    a?a?a?aaa a?a?a?aaa a?a?a?aaa
    a?a?a?aaa a?a?a?aaa a?a?a?aaa
    a?a?a?aaa a?a?a?aaa a?a?a?aaa
    a?a?a?aaa a?a?a?aaa a?a?a?aaa
    첫 번째 a 두 번째 a 세 번째 a
    매치!
    그러면 패턴 끝까지 도달한
    가능성이 하나 나타나는데

    View Slide

  277. Thompson 류
    "aaa"
    a?a?a?aaa a?a?a?aaa a?a?a?aaa
    a?a?a?aaa a?a?a?aaa a?a?a?aaa
    a?a?a?aaa a?a?a?aaa a?a?a?aaa
    a?a?a?aaa a?a?a?aaa a?a?a?aaa
    첫 번째 a 두 번째 a 세 번째 a
    매치!
    바로 매치를 찾은 것이죠.

    View Slide

  278. Thompson 류
    "aaa"
    a?a?a?aaa a?a?a?aaa a?a?a?aaa
    a?a?a?aaa a?a?a?aaa a?a?a?aaa
    a?a?a?aaa a?a?a?aaa a?a?a?aaa
    a?a?a?aaa a?a?a?aaa a?a?a?aaa
    첫 번째 a 두 번째 a 세 번째 a
    매치!
    퇴각검색 방식을 쓰는
    Spencer 류에서와 달리

    View Slide

  279. Thompson 류
    "aaa"
    a?a?a?aaa a?a?a?aaa a?a?a?aaa
    a?a?a?aaa a?a?a?aaa a?a?a?aaa
    a?a?a?aaa a?a?a?aaa a?a?a?aaa
    a?a?a?aaa a?a?a?aaa a?a?a?aaa
    첫 번째 a 두 번째 a 세 번째 a
    매치!
    Thompson 류에서 대상 문자열의 각 글자는
    단 한 번씩만 읽히는데

    View Slide

  280. Thompson 류
    "aaa"
    a?a?a?aaa a?a?a?aaa a?a?a?aaa
    a?a?a?aaa a?a?a?aaa a?a?a?aaa
    a?a?a?aaa a?a?a?aaa a?a?a?aaa
    a?a?a?aaa a?a?a?aaa a?a?a?aaa
    첫 번째 a 두 번째 a 세 번째 a
    매치!
    즉, 되돌아가는 일 없이
    전진만 하는 것입니다.

    View Slide

  281. Spencer 류 Thompson 류
    "aaa" "aaa"
    a? a? a? aaa
    a? a? aaa
    a? aaa
    a? aaa
    aaa
    aaa
    aaa
    aaa
    2ˣ a?a?a?aaa a?a?a?aaa a?a?a?aaa
    a?a?a?aaa a?a?a?aaa a?a?a?aaa
    a?a?a?aaa a?a?a?aaa a?a?a?aaa
    a?a?a?aaa a?a?a?aaa a?a?a?aaa
    첫 번째 a 두 번째 a 세 번째 a
    x+1

    View Slide

  282. Spencer 류 Thompson 류
    "aaa" "aaa"
    a? a? a? aaa
    a? a? aaa
    a? aaa
    a? aaa
    aaa
    aaa
    aaa
    aaa
    2ˣ a?a?a?aaa a?a?a?aaa a?a?a?aaa
    a?a?a?aaa a?a?a?aaa a?a?a?aaa
    a?a?a?aaa a?a?a?aaa a?a?a?aaa
    a?a?a?aaa a?a?a?aaa a?a?a?aaa
    첫 번째 a 두 번째 a 세 번째 a
    x+1
    이 벤치마크에서 Spencer 류가
    탐색하는 가능성은 2ˣ개인데 반해

    View Slide

  283. Spencer 류 Thompson 류
    "aaa" "aaa"
    a? a? a? aaa
    a? a? aaa
    a? aaa
    a? aaa
    aaa
    aaa
    aaa
    aaa
    2ˣ a?a?a?aaa a?a?a?aaa a?a?a?aaa
    a?a?a?aaa a?a?a?aaa a?a?a?aaa
    a?a?a?aaa a?a?a?aaa a?a?a?aaa
    a?a?a?aaa a?a?a?aaa a?a?a?aaa
    첫 번째 a 두 번째 a 세 번째 a
    x+1
    Thompson 류는
    x+1개만 탐색합니다.

    View Slide

  284. Spencer 류 Thompson 류
    "aaa" "aaa"
    a? a? a? aaa
    a? a? aaa
    a? aaa
    a? aaa
    aaa
    aaa
    aaa
    aaa
    2ˣ a?a?a?aaa a?a?a?aaa a?a?a?aaa
    a?a?a?aaa a?a?a?aaa a?a?a?aaa
    a?a?a?aaa a?a?a?aaa a?a?a?aaa
    a?a?a?aaa a?a?a?aaa a?a?a?aaa
    첫 번째 a 두 번째 a 세 번째 a
    x+1
    그래서 Spencer 류의 탐색 횟수는
    지수적으로 증가하고

    View Slide

  285. Spencer 류 Thompson 류
    "aaa" "aaa"
    a? a? a? aaa
    a? a? aaa
    a? aaa
    a? aaa
    aaa
    aaa
    aaa
    aaa
    2ˣ a?a?a?aaa a?a?a?aaa a?a?a?aaa
    a?a?a?aaa a?a?a?aaa a?a?a?aaa
    a?a?a?aaa a?a?a?aaa a?a?a?aaa
    a?a?a?aaa a?a?a?aaa a?a?a?aaa
    첫 번째 a 두 번째 a 세 번째 a
    x+1
    Thompson 류의 탐색 횟수는
    선형적으로 증가하죠.

    View Slide

  286. Spencer 류 Thompson 류
    "aaa" "aaa"
    a? a? a? aaa
    a? a? aaa
    a? aaa
    a? aaa
    aaa
    aaa
    aaa
    aaa
    2ˣ a?a?a?aaa a?a?a?aaa a?a?a?aaa
    a?a?a?aaa a?a?a?aaa a?a?a?aaa
    a?a?a?aaa a?a?a?aaa a?a?a?aaa
    a?a?a?aaa a?a?a?aaa a?a?a?aaa
    첫 번째 a 두 번째 a 세 번째 a
    x+1
    이 때문에 특정한 경우에 둘 사이에서
    극단적인 성능차이를 볼 수 있습니다.

    View Slide

  287. •평균적으론 충분히 빠르고
    •표현력이 더 좋아요.
    •펄, PCRE, 파이썬, 루비, 자바
    Spencer 류

    View Slide

  288. •평균적으론 충분히 빠르고
    •표현력이 더 좋아요.
    •펄, PCRE, 파이썬, 루비, 자바
    Spencer 류
    하지만 일반적인 경우 Spencer 류 정규식 엔진도
    충분히 빠르게 동작해요.

    View Slide

  289. •평균적으론 충분히 빠르고
    •표현력이 더 좋아요.
    •펄, PCRE, 파이썬, 루비, 자바
    Spencer 류
    패턴만 안전하게 짜면 Thompson 류만큼
    안정적으로 쓸 수 있죠.

    View Slide

  290. •평균적으론 충분히 빠르고
    •표현력이 더 좋아요.
    •펄, PCRE, 파이썬, 루비, 자바
    Spencer 류
    그리고 정규식 기능 중엔
    퇴각검색으로만 구현할 수 있는 것도 있어서

    View Slide

  291. •평균적으론 충분히 빠르고
    •표현력이 더 좋아요.
    •펄, PCRE, 파이썬, 루비, 자바
    Spencer 류
    이쪽의 정규식 표현력이
    훨씬 좋습니다.

    View Slide

  292. •평균적으론 충분히 빠르고
    •표현력이 더 좋아요.
    •펄, PCRE, 파이썬, 루비, 자바
    Spencer 류
    그래서인지
    펄과 PCRE, 파이썬을 비롯해

    View Slide

  293. •평균적으론 충분히 빠르고
    •표현력이 더 좋아요.
    •펄, PCRE, 파이썬, 루비, 자바
    Spencer 류
    오늘날 수많은 정규식 엔진이
    이 방식을 쓴다고 해요.

    View Slide

  294. /(a+)+/
    /([a-zA-Z]+)*/
    /(a|aa)+/
    /(a|a?)+/
    ReDoS 공격
    하지만 Spencer 류
    정규식 엔진을 쓰는 서버가

    View Slide

  295. /(a+)+/
    /([a-zA-Z]+)*/
    /(a|aa)+/
    /(a|a?)+/
    ReDoS 공격
    만약 사용자 입력으로 정규식 패턴을 받는다면
    얘기가 달라집니다.

    View Slide

  296. /(a+)+/
    /([a-zA-Z]+)*/
    /(a|aa)+/
    /(a|a?)+/
    ReDoS 공격
    공격자가 정규식 엔진에서
    최악의 경우를 이끌어내는

    View Slide

  297. /(a+)+/
    /([a-zA-Z]+)*/
    /(a|aa)+/
    /(a|a?)+/
    ReDoS 공격
    악의적인 정규식 패턴으로
    ReDoS 공격을 가할 수 있거든요.

    View Slide

  298. /(a+)+/
    /([a-zA-Z]+)*/
    /(a|aa)+/
    /(a|a?)+/
    ReDoS 공격
    구글에서도 ReDoS 공격에 대한
    우려가 있어서

    View Slide

  299. /(a+)+/
    /([a-zA-Z]+)*/
    /(a|aa)+/
    /(a|a?)+/
    ReDoS 공격
    Thompson의 정규식 알고리즘을 기반으로
    RE2를 만들게 됐다고 합니다.

    View Slide

  300. "^gli{@}"
    "^^(a|e|i|o|u)"
    "{~@}sub"
    HRE
    한글라이즈 정규표현식 방언

    View Slide

  301. "^gli{@}"
    "^^(a|e|i|o|u)"
    "{~@}sub"
    HRE
    한글라이즈 정규표현식 방언
    한편 한글라이즈에선
    패턴 찾아 바꾸기 할 때

    View Slide

  302. "^gli{@}"
    "^^(a|e|i|o|u)"
    "{~@}sub"
    HRE
    한글라이즈 정규표현식 방언
    "HRE"로 명명한 한글라이즈 전용
    정규표현식 방언을 쓰고 있어요.

    View Slide

  303. "^gli{@}"
    "^^(a|e|i|o|u)"
    "{~@}sub"
    HRE
    한글라이즈 정규표현식 방언
    파란색으로 강조한 부분은
    RE2 정규식엔 없는 문법인데

    View Slide

  304. HRE를 RE2로
    "^gli{@}"HRE
    /((?:^|\\s+|{}))()gli(a|e|i|o|u)()/RE2
    RE2가 이해할 수 있는 문법으로
    번역해서 사용하고 있죠.

    View Slide

  305. HRE 룩어라운드
    "foo{bar}" "foo{~bar}"
    그 중 구현하기 골치 아팠던
    룩어라운드에 대해 얘기해 드리겠습니다.

    View Slide

  306. /^foo/ foo인데 맨 앞
    /foo$/ foo인데 맨 뒤
    정규식에서 /^/과 /$/가
    무엇을 뜻하는진 다들 잘 아시죠?

    View Slide

  307. /^foo/ foo인데 맨 앞
    /foo$/ foo인데 맨 뒤
    /^foo/는 "foo"인데
    문자열 맨 앞에 있는 경우에 매치되고

    View Slide

  308. /^foo/ foo인데 맨 앞
    /foo$/ foo인데 맨 뒤
    /foo$/는 "foo"인데
    문자열 맨 뒤에 있는 경우에 매치됩니다.

    View Slide

  309. "foo{bar}" foo인데 bar 바로 전
    "foo{~bar}" foo인데 bar가 아닌 것 바로 전
    "{bar}foo" foo인데 bar 바로 뒤
    "{~bar}foo" foo인데 bar가 아닌 것 바로 뒤
    룩어라운드도 비슷해요.

    View Slide

  310. "foo{bar}" foo인데 bar 바로 전
    "foo{~bar}" foo인데 bar가 아닌 것 바로 전
    "{bar}foo" foo인데 bar 바로 뒤
    "{~bar}foo" foo인데 bar가 아닌 것 바로 뒤
    "foo{bar}"라고 쓰면
    "bar" 바로 앞에 있는 "foo"에만 매치되고

    View Slide

  311. "foo{bar}" foo인데 bar 바로 전
    "foo{~bar}" foo인데 bar가 아닌 것 바로 전
    "{bar}foo" foo인데 bar 바로 뒤
    "{~bar}foo" foo인데 bar가 아닌 것 바로 뒤
    "foo{~bar}"라고 쓰면 "bar"가 아닌 것
    바로 앞에 있는 "foo"에만 매치되죠.

    View Slide

  312. "foo{bar}" foo인데 bar 바로 전
    "foo{~bar}" foo인데 bar가 아닌 것 바로 전
    "{bar}foo" foo인데 bar 바로 뒤
    "{~bar}foo" foo인데 bar가 아닌 것 바로 뒤
    "{bar}foo", "{~bar}foo" 처럼
    "{}"가 앞에 올 수도 있습니다.

    View Slide

  313. "foo{bar}" 포지티브 룩어헤드
    "foo{~bar}" 네거티브 룩어헤드
    "{bar}foo" 포지티브 룩비하인드
    "{~bar}foo" 네거티브 룩비하인드
    각각의 문법을 "포지티브 룩어헤드",
    "네거티브 룩어헤드",

    View Slide

  314. "foo{bar}" 포지티브 룩어헤드
    "foo{~bar}" 네거티브 룩어헤드
    "{bar}foo" 포지티브 룩비하인드
    "{~bar}foo" 네거티브 룩비하인드
    "포지티브 룩비하인드",
    "네거티브 룩비하인드"라고 부릅니다.

    View Slide

  315. ".^"
    foo foobar foobaz
    foobarr foofoobar

    View Slide

  316. ".^"
    foo foobar foobaz
    foobarr foofoobar
    룩어라운드가 실제로 매치되는
    모습을 한 번 보겠습니다.

    View Slide

  317. ".^"
    foo foobar foobaz
    foobarr foofoobar
    위쪽은 패턴이고
    아래쪽은 대상 문자열이에요.

    View Slide

  318. ".^"
    foo foobar foobaz
    foobarr foofoobar
    ".^"은 아무 데도 매치되지 않는
    모순 패턴이죠.

    View Slide

  319. "foo"
    foo foobar foobaz
    foobarr foofoobar
    패턴 "foo"를 찾으면
    모든 "foo"에 불이 들어옵니다.

    View Slide

  320. "foo(bar)"
    foo foobar foobaz
    foobarr foofoobar
    "foo" 뒤에 "(bar)"를 붙이면
    "foobar"에 불이 들어오고

    View Slide

  321. "foo{bar}"
    foo foobar foobaz
    foobarr foofoobar
    "(bar)" 대신 "{bar}"를 써서
    포지티브 룩어헤드로 만들면

    View Slide

  322. "foo{bar}"
    foo foobar foobaz
    foobarr foofoobar
    "foobar" 중 "foo"에만
    불이 들어옵니다.

    View Slide

  323. "foo{bar}"
    foo foobar foobaz
    foobarr foofoobar
    이런 식으로 "{}" 속 단어는 매치에 참고는 되지만
    실제 결과에 포함되진 않아요.

    View Slide

  324. "foo{~bar}"
    foo foobar foobaz
    foobarr foofoobar
    "{bar}"에 물결을 붙여 "{~bar}"로 바꿔서
    네거티브 룩어헤드로 만들면

    View Slide

  325. "foo{~bar}"
    foo foobar foobaz
    foobarr foofoobar
    "foobar"가 아닌 곳의 "foo"에만
    불이 들어옵니다.

    View Slide

  326. •어두의 n은 초성 ㄴ으로 치환
    •모음 뒤 n은 종성 ㅇ으로 치환
    •m 뒤 n은 묵음이니 삭제
    룩어라운드 쓰임새
    한글라이즈에선 이런
    룩어라운드가 꽤 자주 쓰이는데

    View Slide

  327. •어두의 n은 초성 ㄴ으로 치환
    •모음 뒤 n은 종성 ㅇ으로 치환
    •m 뒤 n은 묵음이니 삭제
    룩어라운드 쓰임새
    특히 같은 글자라고 해도 앞뒤 글자에 따라
    다르게 바꿔야 하는 경우에 주로 쓰고 있습니다.

    View Slide

  328. /foo(?=bar)/ 포지티브 룩어헤드
    /foo(?!bar)/ 네거티브 룩어헤드
    /(?<=bar)foo/ 포지티브 룩비하인드
    /(?PCRE 룩어라운드
    사실 룩어라운드는 HRE에만 있는 게 아니고
    PCRE에서 따온 것입니다.

    View Slide

  329. /foo(?=bar)/ 포지티브 룩어헤드
    /foo(?!bar)/ 네거티브 룩어헤드
    /(?<=bar)foo/ 포지티브 룩비하인드
    /(?PCRE 룩어라운드
    여기선 룩어라운드를
    /(?=)/, /(?

    View Slide

  330. /foo(?=bar)/ 포지티브 룩어헤드
    /foo(?!bar)/ 네거티브 룩어헤드
    /(?<=bar)foo/ 포지티브 룩비하인드
    /(?PCRE 룩어라운드
    문법이 다소 어려워서
    "{}"와 "~"로 좀 더 쉽게 표현했던 거죠.

    View Slide

  331. /foo(?=bar)/ 포지티브 룩어헤드
    /foo(?!bar)/ 네거티브 룩어헤드
    /(?<=bar)foo/ 포지티브 룩비하인드
    /(?PCRE 룩어라운드
    파이썬 re는 PCRE 룩어라운드를 지원해서
    옛 한글라이즈에선 "{}" 문법을 단순히

    View Slide

  332. /foo(?=bar)/ 포지티브 룩어헤드
    /foo(?!bar)/ 네거티브 룩어헤드
    /(?<=bar)foo/ 포지티브 룩비하인드
    /(?PCRE 룩어라운드
    PCRE 문법으로 번역하는 것만으로
    쉽게 룩어라운드를 구현할 수 있었습니다.

    View Slide

  333. •안전한 정규표현식 구현
    •문자열 길이에 대해 선형 시간
    •고의적으로 일부 기능 미지원
    RE2
    by Google
    그런데 아까 RE2가 고의적으로 일부 기능을
    지원하지 않는다고 말씀 드렸잖아요?

    View Slide

  334. 룩어라운드
    사용 불가
    (?=bar)
    룩어라운드도
    그 중 하나였습니다.

    View Slide

  335. 룩어라운드
    사용 불가
    (?=bar)
    옛 한글라이즈에서처럼 단순한
    번역으로는 구현할 수 없었죠.

    View Slide

  336. import "github.com/glenn-brown/.../pcre"
    import "github.com/dlclark/regexp2"
    찾아보니 서드파티 라이브러리 중에

    View Slide

  337. import "github.com/glenn-brown/.../pcre"
    import "github.com/dlclark/regexp2"
    PCRE나 .NET을 기반으로 한
    정규식 엔진도 발견할 수 있었는데

    View Slide

  338. import "github.com/glenn-brown/.../pcre"
    import "github.com/dlclark/regexp2"
    이런 라이브러리를 쓰면
    정규식의 모든 기능을 쓸 수 있기야 하지만

    View Slide

  339. 이왕이면 표준
    이왕이면 표준 정규식
    라이브러리를 쓰고 싶어서

    View Slide

  340. 이왕이면 표준
    RE2만으로 룩어라운드를 구현할
    대안을 고민해보게 됐습니다.

    View Slide

  341. "foo{bar}"
    "{bar}foo"
    포지티브 룩어라운드 대안
    /()(foo)(bar)/
    /(bar)(foo)()/

    View Slide

  342. "foo{bar}"
    "{bar}foo"
    포지티브 룩어라운드 대안
    /()(foo)(bar)/
    /(bar)(foo)()/
    포지티프 룩어라운드의
    대안 구현은 간단했어요.

    View Slide

  343. "foo{bar}"
    "{bar}foo"
    포지티브 룩어라운드 대안
    /()(foo)(bar)/
    /(bar)(foo)()/
    그냥 룩어라운드 부분까지
    포함시켜서 매치하고

    View Slide

  344. $2만 취하기
    "foo{bar}"
    "{bar}foo"
    포지티브 룩어라운드 대안
    /()(foo)(bar)/
    /(bar)(foo)()/
    $2 그룹만 취해서
    앞뒤를 잘라내는 것으로 충분했습니다.

    View Slide

  345. "foo{~bar}"
    "{~bar}foo"
    네거티브 룩어라운드 대안
    /()(foo)()/
    /()(foo)()/
    반면 네거티브 룩어라운드는
    살짝 복잡했어요.

    View Slide

  346. "foo{~bar}"
    "{~bar}foo"
    네거티브 룩어라운드 대안
    /()(foo)()/
    /()(foo)()/
    일단 RE2 용으로 번역한 정규식에는
    "{~}" 부분을 아예 넣지 않았습니다.

    View Slide

  347. "foo{~bar}"
    "{~bar}foo"
    네거티브 룩어라운드 대안
    /()(foo)()/
    /()(foo)()/
    이 경우 모든 "foo"에
    대해서 매치되겠죠.

    View Slide

  348. "foo{~bar}"
    "{~bar}foo"
    네거티브 룩어라운드 대안
    /()(foo)()/
    /()(foo)()/
    뒤쪽이 /^bar/이면 건너뛰기
    앞쪽이 /bar$/이면 건너뛰기
    배제 패턴
    그러고 나서 "{~}" 속에 있는 배제 패턴을
    매치됐던 곳 앞뒤에 한 번 더 매치시켜 봅니다.

    View Slide

  349. "foo{~bar}"
    "{~bar}foo"
    네거티브 룩어라운드 대안
    /()(foo)()/
    /()(foo)()/
    뒤쪽이 /^bar/이면 건너뛰기
    앞쪽이 /bar$/이면 건너뛰기
    배제 패턴
    만약 앞뒤가 이 패턴에 매치되면
    최종 결과에선 빠지는 거죠.

    View Slide

  350. "foo{~bar}"
    "{~bar}foo"
    네거티브 룩어라운드 대안
    /()(foo)()/
    /()(foo)()/
    뒤 3글자가 /^bar/이면 건너뛰기
    앞 3글자가 /bar$/이면 건너뛰기
    bar에 맞춰서
    길이 제한
    이때 살펴보는 앞뒤의 길이를

    View Slide

  351. "foo{~bar}"
    "{~bar}foo"
    네거티브 룩어라운드 대안
    /()(foo)()/
    /()(foo)()/
    뒤 3글자가 /^bar/이면 건너뛰기
    앞 3글자가 /bar$/이면 건너뛰기
    bar에 맞춰서
    길이 제한
    배제 패턴이 매치될 수 있을 만한
    최대 길이로 제한하고 있어요.

    View Slide

  352. "foo{~bar}"
    "{~bar}foo"
    네거티브 룩어라운드 대안
    /()(foo)()/
    /()(foo)()/
    뒤 3글자가 /^bar/이면 건너뛰기
    앞 3글자가 /bar$/이면 건너뛰기
    bar에 맞춰서
    길이 제한
    예시로 든 배제 패턴은 /^bar/, /bar$/인데
    앞뒤가 "bar"인지 아닌지는

    View Slide

  353. "foo{~bar}"
    "{~bar}foo"
    네거티브 룩어라운드 대안
    /()(foo)()/
    /()(foo)()/
    뒤 3글자가 /^bar/이면 건너뛰기
    앞 3글자가 /bar$/이면 건너뛰기
    bar에 맞춰서
    길이 제한
    3글자만 보면 되니까
    딱 그만큼만 보는 거죠.

    View Slide

  354. "foo{~bar}"
    "{~bar}foo"
    네거티브 룩어라운드 대안
    /()(foo)()/
    /()(foo)()/
    뒤 3글자가 /^bar/이면 건너뛰기
    앞 3글자가 /bar$/이면 건너뛰기
    bar에 맞춰서
    길이 제한
    이 길이 제한이 있어야만
    대상 문자열이 아무리 길어져도

    View Slide

  355. "foo{~bar}"
    "{~bar}foo"
    네거티브 룩어라운드 대안
    /()(foo)()/
    /()(foo)()/
    뒤 3글자가 /^bar/이면 건너뛰기
    앞 3글자가 /bar$/이면 건너뛰기
    bar에 맞춰서
    길이 제한
    네거티브 룩어라운드를
    빠르게 끝낼 수 있습니다.

    View Slide

  356. syntax.Parse("a?|b", syntax.Perl)
    import "regexp/syntax"
    Alternate '|'
    Literal 'b'
    Quest '?'
    Literal 'a'
    패턴이 매치될 수 있는 문자열의
    최대 길이를 구하는 건 간단했습니다.

    View Slide

  357. syntax.Parse("a?|b", syntax.Perl)
    import "regexp/syntax"
    Alternate '|'
    Literal 'b'
    Quest '?'
    Literal 'a'
    regexp/syntax 표준 라이브러를 쓰면
    정규식을 해석한 추상구문트리를 얻을 수 있는데

    View Slide

  358. Alternate '|'
    Literal 'b'
    Quest '?'
    Literal 'a'
    트리 살펴보면
    최대 길이 계산 가능
    트리 노드를 적당히 살펴보는 것만으로
    최대 길이를 쉽게 계산할 수 있었죠.

    View Slide

  359. "{~a}foo" O(n)
    "{~a+}foo" O(n²)
    네거티브 룩어라운드 성능
    물론 배제 패턴의 매치 최대 길이가
    무한대인 경우엔

    View Slide

  360. "{~a}foo" O(n)
    "{~a+}foo" O(n²)
    네거티브 룩어라운드 성능
    앞뒤를 딱 필요한 만큼 자를 수 없어서
    최악의 경우 제곱 시간이 걸릴 수도 있어요.

    View Slide

  361. "{~a+}foo" O(n²)
    이런 패턴은 금지
    하지만 다행히 이런 패턴은 그동안
    한 번도 쓰였던 적이 없었고

    View Slide

  362. "{~a+}foo" O(n²)
    이런 패턴은 금지
    간단히 금지하기로
    결정할 수 있었습니다.

    View Slide

  363. /()(foo)()/
    foo foobar foobaz
    foobarr foofoobar
    뒤 3글자가 /^bar/이면 건너뛰기

    View Slide

  364. /()(foo)()/
    foo foobar foobaz
    foobarr foofoobar
    뒤 3글자가 /^bar/이면 건너뛰기
    이렇게 만들어진
    한글라이즈의 네거티브 룩어라운드가

    View Slide

  365. /()(foo)()/
    foo foobar foobaz
    foobarr foofoobar
    뒤 3글자가 /^bar/이면 건너뛰기
    실제로 어떻게 돌아가는지
    한 번 살펴보겠습니다.

    View Slide

  366. /()(foo)()/
    foo foobar foobaz
    foobarr foofoobar
    뒤 3글자가 /^bar/이면 건너뛰기
    우선 번역한 정규식으로 매치를 돌려봅니다.
    모든 "foo"가 매치되겠죠.

    View Slide

  367. /()(foo)()/
    foo foobar foobaz
    foobarr foofoobar
    뒤 3글자가 /^bar/이면 건너뛰기
    그 다음엔 매치된 "foo" 뒤
    3글자씩을 살펴봅니다.

    View Slide

  368. /()(foo)()/
    foo foobar foobaz
    foobarr foofoobar
    뒤 3글자가 /^bar/이면 건너뛰기
    그 중에 /^bar/에
    매치되는 게 있으면

    View Slide

  369. /()(foo)()/
    foo foobar foobaz
    foobarr foofoobar
    뒤 3글자가 /^bar/이면 건너뛰기
    결과에서 지워요.

    View Slide

  370. /()(foo)()/
    foo foobar foobaz
    foobarr foofoobar
    뒤 3글자가 /^bar/이면 건너뛰기
    이런 과정을 통하면 최종적으로
    "bar"가 아닌 것 앞에 있는 "foo"만 남게 됩니다.

    View Slide

  371. b. 말과 글

    View Slide

  372. b. 말과 글
    이번엔 한글라이즈에서
    말과 글을 다루는 데 도움됐던

    View Slide

  373. b. 말과 글
    세 가지 Go 라이브러리를
    소개해 드리겠습니다.

    View Slide

  374. •한글 모아쓰기
    •중국어 병음 사전
    •일본어 형태소 분석
    필요한 기능
    필요한 기능은 한글 모아쓰기,
    중국어 병음 사전, 일본어 형태소 분석이었습니다.

    View Slide

  375. 한글 모아쓰기
    ㅐㅍ-ㄹ
    받침 표시
    한글 모아쓰기는 이런 걸 얘기해요.

    View Slide

  376. 한글 모아쓰기
    ㅐㅍ-ㄹ
    받침 표시
    "ㅐㅍ-ㄹ"과 같이
    자모를 나열했을 때

    View Slide

  377. 한글 모아쓰기

    ㅐㅍ-ㄹ
    받침 표시
    불완전한 모음인
    "ㅐ" 앞엔 "ㅇ"을 채워주고

    View Slide

  378. 한글 모아쓰기
    애플
    ㅐㅍ-ㄹ
    받침 표시
    불완전한 자음인
    "ㅍ" 뒤엔 "ㅡ"를 채워서

    View Slide

  379. 한글 모아쓰기
    애플
    ㅐㅍ-ㄹ
    받침 표시
    온전한 한글 글자로
    합쳐주는 기능입니다.

    View Slide

  380. Διόνυσος 디오니소스
    διονισοσ
    Transcribe
    ㄷㅣㅗㄴㅣㅅㅗㅅ
    Rewrite
    P
    한글라이즈 파이프라인의 Transcribe 단계에서 나온
    자모의 나열을 최종결과로 만드는 데 쓰이죠.

    View Slide

  381. suapapa/go_hangul
    여기엔 이호민 님이 만드신
    "go_hangul"을 사용했습니다.

    View Slide

  382. • 한글 판별
    •자모 분리 및 조립
    • 한글 획 세기
    import "github.com/suapapa/go_hangul"
    hangul.Join('ㅎ', 'ㅏ', 'ㄴ') == '한'
    hangul.Split('한') == 'ㅎ', 'ㅏ', 'ㄴ'
    hangul.IsJaeum('ㅋ') == true
    hangul.IsMoeum('ㅋ') == false
    호민 님 감사합니다.
    이 라이브러리엔 한글을 다루기 위한
    유용한 기능이 많이 있어요.

    View Slide

  383. • 한글 판별
    •자모 분리 및 조립
    • 한글 획 세기
    import "github.com/suapapa/go_hangul"
    hangul.Join('ㅎ', 'ㅏ', 'ㄴ') == '한'
    hangul.Split('한') == 'ㅎ', 'ㅏ', 'ㄴ'
    hangul.IsJaeum('ㅋ') == true
    hangul.IsMoeum('ㅋ') == false
    호민 님 감사합니다.
    주어진 문자가 한글인지,
    자음인지, 모음인지 판별해주는 함수와

    View Slide

  384. • 한글 판별
    •자모 분리 및 조립
    • 한글 획 세기
    import "github.com/suapapa/go_hangul"
    hangul.Join('ㅎ', 'ㅏ', 'ㄴ') == '한'
    hangul.Split('한') == 'ㅎ', 'ㅏ', 'ㄴ'
    hangul.IsJaeum('ㅋ') == true
    hangul.IsMoeum('ㅋ') == false
    호민 님 감사합니다.
    한글을 자모 단위로 쪼개거나 합치는 기능을 포함해
    여러가지를 제공합니다.

    View Slide

  385. • 한글 판별
    •자모 분리 및 조립
    • 한글 획 세기
    import "github.com/suapapa/go_hangul"
    hangul.Join('ㅎ', 'ㅏ', 'ㄴ') == '한'
    hangul.Split('한') == 'ㅎ', 'ㅏ', 'ㄴ'
    hangul.IsJaeum('ㅋ') == true
    hangul.IsMoeum('ㅋ') == false
    호민 님 감사합니다.
    특이하게 한글의 획을 세는
    기능까지도 있더라고요.

    View Slide

  386. Rewrite Transcribe
    Phonemize
    四川 쓰촨
    si chuan si, chwan, ㅆㅡㅊㅘ-ㄴ

    View Slide

  387. Rewrite Transcribe
    Phonemize
    四川 쓰촨
    si chuan si, chwan, ㅆㅡㅊㅘ-ㄴ
    나머지 두 라이브러리는 Phonemize 단계에서
    소리글자를 만드는 데에 쓰고 있습니다.

    View Slide

  388. 중국어 병음
    Qīng dǎo
    青岛 칭 다오
    그 중 첫 번째는
    중국어 병음입니다.

    View Slide

  389. 중국어 병음
    Qīng dǎo
    青岛 칭 다오
    중국어 한자엔 대응되는 로마자 표기가 있는데
    이를 "병음"이라고 불러요.

    View Slide

  390. 중국어 병음
    Qīng dǎo
    青岛 칭 다오
    예를 들어 "青岛"의 병음은
    "Qīng dǎo"로 표현되죠.

    View Slide

  391. •중국 한자를 병음으로 변환
    •단순 사전이라 빠르다.
    •의외로 용량도 안 크다. (800KB)
    import "github.com/mozillazg/go-pinyin"
    args := pinyin.NewArgs()
    pinyin.SinglePinyin('青', args) == "Qīng"
    "go-pinyin"이라는 라이브러리를 쓰면
    손쉽게 병음을 구할 수 있습니다.

    View Slide

  392. •중국 한자를 병음으로 변환
    •단순 사전이라 빠르다.
    •의외로 용량도 안 크다. (800KB)
    import "github.com/mozillazg/go-pinyin"
    args := pinyin.NewArgs()
    pinyin.SinglePinyin('青', args) == "Qīng"
    이 라이브러리는 단순한
    사전이어서 속도도 빠르고

    View Slide

  393. •중국 한자를 병음으로 변환
    •단순 사전이라 빠르다.
    •의외로 용량도 안 크다. (800KB)
    import "github.com/mozillazg/go-pinyin"
    args := pinyin.NewArgs()
    pinyin.SinglePinyin('青', args) == "Qīng"
    의외로 데이터도 별로 크지 않아서
    800KB 밖에 되지 않습니다.

    View Slide

  394. Hangulize("chi", "北京")
    Hangulize("chi", "章子怡")
    == "베이징"
    == "장쯔이"
    이 라이브러리 덕분에 한글라이즈에
    중국어를 새로 추가할 수 있게 됐어요.

    View Slide

  395. Hangulize("chi", "李興燮") == "리싱셰"
    이 흥 섭
    중국어가 되니까 자기 한자 이름
    넣어보는 재미도 나름 쏠쏠하더라고요.

    View Slide

  396. 陸カ審月名検ナレチカ可栄1経断ヒヲカツ宅意へざン丁可ホ
    載省末応をじいく行昧7年てぼかせ答予シ告断ハヌカサ武元
    争ちぞけみ。26丈なづ広靱増理ソヒタセ士定ワオトヘ整判
    べっ集遺ワサヤイ聞出じどれな勝際ずンれ線芸せ年今ロエヒ
    常政よのトッ上日やみぎね告創ゅど。作ケヨワ逮氏ッじルへ
    地能どぜ祉83派あ織口ケ更探づを車下べひく毎旅まひづゅ意
    幕づ務鋼けぶ要情ハリス択著乞伍トごへれ。
    일본어 형태소 분석
    일본어 로렘 입숨

    View Slide

  397. 陸カ審月名検ナレチカ可栄1経断ヒヲカツ宅意へざン丁可ホ
    載省末応をじいく行昧7年てぼかせ答予シ告断ハヌカサ武元
    争ちぞけみ。26丈なづ広靱増理ソヒタセ士定ワオトヘ整判
    べっ集遺ワサヤイ聞出じどれな勝際ずンれ線芸せ年今ロエヒ
    常政よのトッ上日やみぎね告創ゅど。作ケヨワ逮氏ッじルへ
    地能どぜ祉83派あ織口ケ更探づを車下べひく毎旅まひづゅ意
    幕づ務鋼けぶ要情ハリス択著乞伍トごへれ。
    일본어 형태소 분석
    일본어 로렘 입숨
    다음은 일본어인데

    View Slide

  398. 陸カ審月名検ナレチカ可栄1経断ヒヲカツ宅意へざン丁可ホ
    載省末応をじいく行昧7年てぼかせ答予シ告断ハヌカサ武元
    争ちぞけみ。26丈なづ広靱増理ソヒタセ士定ワオトヘ整判
    べっ集遺ワサヤイ聞出じどれな勝際ずンれ線芸せ年今ロエヒ
    常政よのトッ上日やみぎね告創ゅど。作ケヨワ逮氏ッじルへ
    地能どぜ祉83派あ織口ケ更探づを車下べひく毎旅まひづゅ意
    幕づ務鋼けぶ要情ハリス択著乞伍トごへれ。
    일본어 형태소 분석
    일본어 로렘 입숨
    일본어는 특히 처리하기
    까다로웠던 것 같아요.

    View Slide

  399. 陸カ審月名検ナレチカ可栄1経断ヒヲカツ宅意へざン丁可ホ
    載省末応をじいく行昧7年てぼかせ答予シ告断ハヌカサ武元
    争ちぞけみ。26丈なづ広靱増理ソヒタセ士定ワオトヘ整判
    べっ集遺ワサヤイ聞出じどれな勝際ずンれ線芸せ年今ロエヒ
    常政よのトッ上日やみぎね告創ゅど。作ケヨワ逮氏ッじルへ
    地能どぜ祉83派あ織口ケ更探づを車下べひく毎旅まひづゅ意
    幕づ務鋼けぶ要情ハリス択著乞伍トごへれ。
    일본어 형태소 분석
    일본어 로렘 입숨
    일본어에선 뜻글자인 한자와
    소리글자인 가나를 섞어 씁니다.

    View Slide

  400. 陸カ審月名検ナレチカ可栄1経断ヒヲカツ宅意へざン丁可ホ
    載省末応をじいく行昧7年てぼかせ答予シ告断ハヌカサ武元
    争ちぞけみ。26丈なづ広靱増理ソヒタセ士定ワオトヘ整判
    べっ集遺ワサヤイ聞出じどれな勝際ずンれ線芸せ年今ロエヒ
    常政よのトッ上日やみぎね告創ゅど。作ケヨワ逮氏ッじルへ
    地能どぜ祉83派あ織口ケ更探づを車下べひく毎旅まひづゅ意
    幕づ務鋼けぶ要情ハリス択著乞伍トごへれ。
    일본어 형태소 분석
    일본어 로렘 입숨
    그리고 띄어쓰기를
    사용하지 않아요.

    View Slide

  401. 陸カ審月名検ナレチカ可栄1経断ヒヲカツ宅意へざン丁可ホ
    載省末応をじいく行昧7年てぼかせ答予シ告断ハヌカサ武元
    争ちぞけみ。26丈なづ広靱増理ソヒタセ士定ワオトヘ整判
    べっ集遺ワサヤイ聞出じどれな勝際ずンれ線芸せ年今ロエヒ
    常政よのトッ上日やみぎね告創ゅど。作ケヨワ逮氏ッじルへ
    地能どぜ祉83派あ織口ケ更探づを車下べひく毎旅まひづゅ意
    幕づ務鋼けぶ要情ハリス択著乞伍トごへれ。
    일본어 형태소 분석
    일본어 로렘 입숨
    여기 붙여 둔 문단은 일본어 로렘 입숨인데
    보시다시피 띄어쓰기가 없습니다.

    View Slide

  402. 陸カ審月名検ナレチカ可栄1経断ヒヲカツ宅意へざン丁可ホ
    載省末応をじいく行昧7年てぼかせ答予シ告断ハヌカサ武元
    争ちぞけみ。26丈なづ広靱増理ソヒタセ士定ワオトヘ整判
    べっ集遺ワサヤイ聞出じどれな勝際ずンれ線芸せ年今ロエヒ
    常政よのトッ上日やみぎね告創ゅど。作ケヨワ逮氏ッじルへ
    地能どぜ祉83派あ織口ケ更探づを車下べひく毎旅まひづゅ意
    幕づ務鋼けぶ要情ハリス択著乞伍トごへれ。
    일본어 형태소 분석
    일본어 로렘 입숨
    전각문자
    마침표와 띄어쓰기처럼 보이는 이것도
    사실은 전각문자 1개죠.

    View Slide

  403. 일본어 형태소 분석: 띄어쓰기
    宮本茂일본어
    ▶ 미야모토 시게루
    일본인 이름은 이렇게
    한자 서너자로 이뤄진 경우가 많은데

    View Slide

  404. 일본어 형태소 분석: 띄어쓰기
    宮本茂일본어
    ▶ 미야모토 시게루
    어디까지가 성이고
    어디까지가 이름인지 구별해서

    View Slide

  405. 일본어 형태소 분석: 띄어쓰기
    宮本茂일본어
    ▶ 미야모토 시게루
    전사 결과엔 띄어쓰기를
    넣어줘야 합니다.

    View Slide

  406. 일본어 형태소 분석: 띄어쓰기
    宮本茂일본어
    ▶ 미야모토 시게루
    형태소를 분석해보면
    이름 경계를 알 수 있는데

    View Slide

  407. 일본어 형태소 분석: 띄어쓰기
    宮本茂일본어
    ▶ 미야모토 시게루
    이게 일본어에 형태소 분석이
    필요했던 첫 번째 이유죠.

    View Slide

  408. 일본어 형태소 분석: 후리가나
    ニッポンダ
    ニホンゴ
    日本だ
    日本語 니 고

    닛 폰 다
    또 다른 이유는 후리가나입니다.

    View Slide

  409. 일본어 형태소 분석: 후리가나
    ニッポンダ
    ニホンゴ
    日本だ
    日本語 니 고

    닛 폰 다
    일본어에서 한자의 읽는 법을
    소리글자로 쓰는 걸 "후리가나"라고 하는데

    View Slide

  410. 일본어 형태소 분석: 후리가나
    ニッポンダ
    ニホンゴ
    日本だ
    日本語 니 고

    닛 폰 다
    같은 한자라도 문맥에 따라서
    후리가나가 달라질 수 있습니다.

    View Slide

  411. 일본어 형태소 분석: 후리가나
    ニッポンダ
    ニホンゴ
    日本だ
    日本語 니 고

    닛 폰 다
    한자어인 "日本"의 경우
    독립적으로 쓰일 땐 "닛폰"으로 읽히지만

    View Slide

  412. 일본어 형태소 분석: 후리가나
    ニッポンダ
    ニホンゴ
    日本だ
    日本語 니 고

    닛 폰 다
    다른 한자어의 일부로 쓰일 땐
    "니혼"으로 읽히더라고요.

    View Slide

  413. 일본어 형태소 분석: 후리가나
    ニッポンダ
    ニホンゴ
    日本だ
    日本語 니 고

    닛 폰 다
    이런 걸 판단해서 한자로부터
    후리가나를 추출해줄 도구가 필요했죠.

    View Slide

  414. 일본어 형태소 분석: 장모음
    イーエ
    カワイ·イ
    いいえ
    かわいい 가

    i i e
    i
    i
    wa
    ka

    와 이 이
    마지막으로 장모음 문제도 있었습니다.

    View Slide

  415. 일본어 형태소 분석: 장모음
    イーエ
    カワイ·イ
    いいえ
    かわいい 가

    i i e
    i
    i
    wa
    ka

    와 이 이
    우리말에선 사라진 장모음/단모음
    구별이 일본어엔 있는데

    View Slide

  416. 일본어 형태소 분석: 장모음
    イーエ
    カワイ·イ
    いいえ
    かわいい 가

    i i e
    i
    i
    wa
    ka

    와 이 이
    외래어 표기법에선 장모음을
    단모음처럼 취급하거든요.

    View Slide

  417. 일본어 형태소 분석: 장모음
    イーエ
    カワイ·イ
    いいえ
    かわいい 가

    i i e
    i
    i
    wa
    ka

    와 이 이
    그래서 첫 번째 예시인 "いいえ"(iie)의
    경우 "いい"(ii)가 장음이라서

    View Slide

  418. 일본어 형태소 분석: 장모음
    イーエ
    カワイ·イ
    いいえ
    かわいい 가

    i i e
    i
    i
    wa
    ka

    와 이 이
    "이이에"가 아닌 "이에"로 옮깁니다.

    View Slide

  419. 일본어 형태소 분석: 장모음
    イーエ
    カワイ·イ
    いいえ
    かわいい 가

    i i e
    i
    i
    wa
    ka

    와 이 이
    하지만 똑같이 "いい"(ii)라고
    써있더라도 장모음이 아니라

    View Slide

  420. 일본어 형태소 분석: 장모음
    イーエ
    カワイ·イ
    いいえ
    かわいい 가

    i i e
    i
    i
    wa
    ka

    와 이 이
    형태소의 경계로
    나뉘어 있는 경우도 있어요.

    View Slide

  421. 일본어 형태소 분석: 장모음
    イーエ
    カワイ·イ
    いいえ
    かわいい 가

    i i e
    i
    i
    wa
    ka

    와 이 이
    두 번째 예시인 "かわいい"(kawaii)가
    그런 경우인데

    View Slide

  422. 일본어 형태소 분석: 장모음
    イーエ
    カワイ·イ
    いいえ
    かわいい 가

    i i e
    i
    i
    wa
    ka

    와 이 이
    여기의 "いい"(ii)는 장모음이 아니고
    각각 다른 형태소에 속한 두 개의 "い"(i)죠.

    View Slide

  423. 일본어 형태소 분석: 장모음
    イーエ
    カワイ·イ
    いいえ
    かわいい 가

    i i e
    i
    i
    wa
    ka

    와 이 이
    이때는 단모음처럼 합치면 안 되고
    "이이"라고 구별해서 적어줘야 됩니다.

    View Slide

  424. 일본어 형태소 분석: 장모음
    イーエ
    カワイ·イ
    いいえ
    かわいい 가

    i i e
    i
    i
    wa
    ka

    와 이 이
    이처럼 일본어는 제대로 한글로 옮기려면
    꽤 정밀한 형태소 분석을 필요로 하는데

    View Slide

  425. •순수 Go
    •일본어 형태소 분석기
    import "github.com/ikawaha/kagome.ipadic"
    다행히 "kagome"라는 적합한
    라이브러리가 있었습니다.

    View Slide

  426. •순수 Go
    •일본어 형태소 분석기
    import "github.com/ikawaha/kagome.ipadic"
    kagome는 Go만으로 구현된
    일본어 형태소 분석기인데

    View Slide

  427. •순수 Go
    •일본어 형태소 분석기
    import "github.com/ikawaha/kagome.ipadic"
    여기에 일본어 문장을 입력하면

    View Slide

  428. •순수 Go
    •일본어 형태소 분석기
    import "github.com/ikawaha/kagome.ipadic"
    형태소의 품사, 원형, 읽는 법까지
    꽤 자세한 정보를 구할 수 있어요.

    View Slide

  429. •순수 Go
    •일본어 형태소 분석기
    •무거워요
    import "github.com/ikawaha/kagome.ipadic"
    단, 다소 무거운 편입니다.

    View Slide

  430. •순수 Go
    •일본어 형태소 분석기
    •무거워요
    import "github.com/ikawaha/kagome.ipadic"
    초기화 속도도 느리고
    분석 속도도 그리 빠르진 않더라고요.

    View Slide

  431. Hangulize("jpn", "任天堂")
    Hangulize("jpn", "新海誠")
    Hangulize("jpn", "天空の城ラピュタ")
    == "닌텐도"
    == "신카이 마코토"
    == "덴쿠노시로라퓨타"
    어쨌든 옛 한글라이즈의
    일본어 규칙에선

    View Slide

  432. Hangulize("jpn", "任天堂")
    Hangulize("jpn", "新海誠")
    Hangulize("jpn", "天空の城ラピュタ")
    == "닌텐도"
    == "신카이 마코토"
    == "덴쿠노시로라퓨타"
    소리글자인 가나만 지원했고
    장모음 구별도 못 했는데

    View Slide

  433. Hangulize("jpn", "任天堂")
    Hangulize("jpn", "新海誠")
    Hangulize("jpn", "天空の城ラピュタ")
    == "닌텐도"
    == "신카이 마코토"
    == "덴쿠노시로라퓨타"
    kagome 덕분에 새 한글라이즈는
    웬만한 일본어 문장까지도 지원할 수 있게 됐습니다.

    View Slide

  434. •hangulize 8.1MB
    •go-pinyin 3.3MB
    •kagome.ipadic 13MB
    •합치면 20MB
    빌드 용량

    View Slide

  435. •hangulize 8.1MB
    •go-pinyin 3.3MB
    •kagome.ipadic 13MB
    •합치면 20MB
    빌드 용량
    그런데 go-pinyin이랑 kagome까지
    한글라이즈 패키지에 포함하려고 보니

    View Slide

  436. •hangulize 8.1MB
    •go-pinyin 3.3MB
    •kagome.ipadic 13MB
    •합치면 20MB
    빌드 용량
    빌드 용량이 너무 커지더라고요.

    View Slide

  437. •hangulize 8.1MB
    •go-pinyin 3.3MB
    •kagome.ipadic 13MB
    •합치면 20MB
    빌드 용량
    특히 JavaScript 빌드도 같이 뽑고 있었는데
    20MB면 JS 파일 하나치곤 너무 커서

    View Slide

  438. import "github.com/hangulize/hangulize"
    import "github.com/hangulize/hangulize/phonemize/furigana"
    func main() {
    hangulize.UsePhonemizer(&furigana.P)
    fmt.Println(hangulize.Hangulize("jpn", "秋葉原"))
    // Output: 아키하바라
    }
    플러그인
    이렇게 플러그인처럼
    쓸 수 있도록 분리했어요.

    View Slide

  439. import "github.com/hangulize/hangulize"
    import "github.com/hangulize/hangulize/phonemize/furigana"
    func main() {
    hangulize.UsePhonemizer(&furigana.P)
    fmt.Println(hangulize.Hangulize("jpn", "秋葉原"))
    // Output: 아키하바라
    }
    플러그인
    여러분이 Go 코드에서
    한글라이즈 라이브러리를 쓰실 경우엔

    View Slide

  440. import "github.com/hangulize/hangulize"
    import "github.com/hangulize/hangulize/phonemize/furigana"
    func main() {
    hangulize.UsePhonemizer(&furigana.P)
    fmt.Println(hangulize.Hangulize("jpn", "秋葉原"))
    // Output: 아키하바라
    }
    플러그인
    직접 UsePhonemizer를 호출해야만
    중국어와 일본어도 제대로 다룰 수 있습니다.

    View Slide

  441. c. 테스트와 문서화

    View Slide

  442. c. 테스트와 문서화
    다음으로 Go의 테스트 및 문서화 도구에서
    인상적이었던 부분을 말씀드릴게요.

    View Slide

  443. assert Portuguese({
    'bossa nova': '보사 노바',
    'moor': '모르',
    'maracas': '마라카스',
    })
    용례집 유닛테스트
    국립국어원 사이트에선 이렇게
    외래어 표기법 용례집을 구할 수 있는데

    View Slide

  444. assert Portuguese({
    'bossa nova': '보사 노바',
    'moor': '모르',
    'maracas': '마라카스',
    })
    용례집 유닛테스트
    옛 한글라이즈 때부터 이 용례집을
    유닛테스트로 만들어 써왔어요.

    View Slide

  445. assert Portuguese({
    'bossa nova': '보사 노바',
    'moor': '모르',
    'maracas': '마라카스',
    })
    용례집 유닛테스트
    이것으로 전사 규칙을 제대로 만들었는지
    쉽게 검증할 수 있었죠.

    View Slide

  446. 기존 용례집 테스트 승계
    5. 20. 재제작 시작
    5. 27. 첫 릴리즈
    5. 28. 기존 언어 모두 지원 8. 27. 발표
    새 한글라이즈를 만들면서도
    기존 용례집 테스트는 그대로 승계했습니다.

    View Slide

  447. 기존 용례집 테스트 승계
    5. 20. 재제작 시작
    5. 27. 첫 릴리즈
    5. 28. 기존 언어 모두 지원 8. 27. 발표
    처음부터 테스트가 충분했던 덕분에

    View Slide

  448. 기존 용례집 테스트 승계
    5. 20. 재제작 시작
    5. 27. 첫 릴리즈
    5. 28. 기존 언어 모두 지원 8. 27. 발표
    8일
    첫 8일만에 기존 38가지 언어를
    모두 지원하는 것도 가능했죠.

    View Slide

  449. 기존 용례집 테스트 승계
    5. 20. 재제작 시작
    5. 27. 첫 릴리즈
    5. 28. 기존 언어 모두 지원 8. 27. 발표
    8일
    그만큼 한글라이즈에서 테스트는
    굉장히 중요한 축을 맡고 있습니다.

    View Slide

  450. import "testing"

    View Slide

  451. import "testing"
    "testing"은 Go의 표준 테스트 도구인데
    기본 도구임에도 불구하고

    View Slide

  452. import "testing"
    상당히 강력한 테스트 프레임워크를
    쓰는 기분이었습니다.

    View Slide

  453. // $ go test -run TestLang/ita
    func TestLang(t *testing.T) {
    t.Run("jpn", testJpn)
    t.Run("chi", testChi)
    t.Run("ita", testIta)
    }
    서브테스트
    testing에서 인상적인 점 중 하나는
    바로 서브테스트 기능이었어요.

    View Slide

  454. // $ go test -run TestLang/ita
    func TestLang(t *testing.T) {
    t.Run("jpn", testJpn)
    t.Run("chi", testChi)
    t.Run("ita", testIta)
    }
    서브테스트
    서브테스트는 한 테스트케이스에서
    여러 테스트케이스를 파생시키는 기능인데

    View Slide

  455. // $ go test -run TestLang/ita
    func TestLang(t *testing.T) {
    t.Run("jpn", testJpn)
    t.Run("chi", testChi)
    t.Run("ita", testIta)
    }
    서브테스트
    본격적인 서드파티 테스트
    프레임워크에서나 지원할 법한 걸

    View Slide

  456. // $ go test -run TestLang/ita
    func TestLang(t *testing.T) {
    t.Run("jpn", testJpn)
    t.Run("chi", testChi)
    t.Run("ita", testIta)
    }
    서브테스트
    기본 도구가 지원한다는
    점이 놀라웠죠.

    View Slide

  457. // $ go test -run TestLang/ita
    func TestLang(t *testing.T) {
    t.Run("jpn", testJpn)
    t.Run("chi", testChi)
    t.Run("ita", testIta)
    }
    서브테스트
    한글라이즈에선 각 언어 별 용례집을
    검증하는 테스트를

    View Slide

  458. // $ go test -run TestLang/ita
    func TestLang(t *testing.T) {
    t.Run("jpn", testJpn)
    t.Run("chi", testChi)
    t.Run("ita", testIta)
    }
    서브테스트
    이런 식으로 서브테스트를
    이용해 만들었습니다.

    View Slide

  459. // $ go test -bench .
    // BenchmarkF 100 1078834 ns/op
    func BenchmarkF(b *testing.B) {
    for i := 0; i < b.N; i++ {
    f()
    }
    }
    벤치마크

    View Slide

  460. // $ go test -bench .
    // BenchmarkF 100 1078834 ns/op
    func BenchmarkF(b *testing.B) {
    for i := 0; i < b.N; i++ {
    f()
    }
    }
    벤치마크
    또 벤치마크 기능까지
    제공하는 점도 신선했는데

    View Slide

  461. // $ go test -bench .
    // BenchmarkF 100 1078834 ns/op
    func BenchmarkF(b *testing.B) {
    for i := 0; i < b.N; i++ {
    f()
    }
    }
    벤치마크
    "Benchmark"로 시작하는 함수에서
    testing.B를 인자로 받아

    View Slide

  462. // $ go test -bench .
    // BenchmarkF 100 1078834 ns/op
    func BenchmarkF(b *testing.B) {
    for i := 0; i < b.N; i++ {
    f()
    }
    }
    벤치마크
    b.N바퀴 도는 반복문 코드를
    작성하는 식으로 만들더라고요.

    View Slide

  463. // $ go test -bench .
    // BenchmarkF 100 1078834 ns/op
    func BenchmarkF(b *testing.B) {
    for i := 0; i < b.N; i++ {
    f()
    }
    }
    벤치마크
    테스트 실행할 때
    "-bench" 옵션을 지정하면

    View Slide

  464. // $ go test -bench .
    // BenchmarkF 100 1078834 ns/op
    func BenchmarkF(b *testing.B) {
    for i := 0; i < b.N; i++ {
    f()
    }
    }
    벤치마크
    벤치마크를 돌려본 후 루프 한 바퀴에
    얼마나 걸렸는지 알려줍니다.

    View Slide

  465. benchmark(
    setup='prepare()',
    run='do_it()',
    )
    흔히 보던 벤치마크
    제가 흔히 보던
    벤치마크 도구에선 보통

    View Slide

  466. benchmark(
    setup='prepare()',
    run='do_it()',
    )
    흔히 보던 벤치마크
    벤치마크를 준비하는 코드 "setup"과
    벤치마크할 코드 "run"을

    View Slide

  467. benchmark(
    setup='prepare()',
    run='do_it()',
    )
    흔히 보던 벤치마크
    따로 입력하는
    인터페이스가 있었는데

    View Slide

  468. func BenchmarkDoIt(b *testing.B) {
    Prepare()
    b.ResetTimer()
    for i := 0; i < b.N; i++ {
    DoIt()
    }
    }
    Go 벤치마크
    복잡한 추상화 없이
    testing.B 인자만으로

    View Slide

  469. func BenchmarkDoIt(b *testing.B) {
    Prepare()
    b.ResetTimer()
    for i := 0; i < b.N; i++ {
    DoIt()
    }
    }
    Go 벤치마크
    훨씬 간결하게 같은 기능을 구현한다는 점에서
    상당히 감탄했습니다.

    View Slide

  470. func BenchmarkF(b *testing.B) {
    b.Run("1", genBenchmarkF(1))
    b.Run("10", genBenchmarkF(10))
    b.Run("100", genBenchmarkF(100))
    b.Run("1000", genBenchmarkF(1000))
    }
    서브벤치마크
    BenchmarkF/1 BenchmarkF/1000
    시간

    View Slide

  471. func BenchmarkF(b *testing.B) {
    b.Run("1", genBenchmarkF(1))
    b.Run("10", genBenchmarkF(10))
    b.Run("100", genBenchmarkF(100))
    b.Run("1000", genBenchmarkF(1000))
    }
    서브벤치마크
    BenchmarkF/1 BenchmarkF/1000
    시간
    벤치마크에서도 서브테스트와 같은 방식으로
    서브벤치마크를 만들 수 있는데

    View Slide

  472. func BenchmarkF(b *testing.B) {
    b.Run("1", genBenchmarkF(1))
    b.Run("10", genBenchmarkF(10))
    b.Run("100", genBenchmarkF(100))
    b.Run("1000", genBenchmarkF(1000))
    }
    서브벤치마크
    BenchmarkF/1 BenchmarkF/1000
    시간
    덕분에 알고리즘의 시간복잡도에
    더 집중할 수 있었고

    View Slide

  473. func BenchmarkF(b *testing.B) {
    b.Run("1", genBenchmarkF(1))
    b.Run("10", genBenchmarkF(10))
    b.Run("100", genBenchmarkF(100))
    b.Run("1000", genBenchmarkF(1000))
    }
    서브벤치마크
    BenchmarkF/1 BenchmarkF/1000
    시간
    개선하는 과정이 눈에 바로바로 들어와서
    성취감도 높았습니다.

    View Slide

  474. func TestF(t *testing.T) {
    if f() != 42 {
    t.Fail("f() does not return 42")
    }
    }

    View Slide

  475. func TestF(t *testing.T) {
    if f() != 42 {
    t.Fail("f() does not return 42")
    }
    }
    한 가지 아쉬웠던 건
    Go에 assert 문법이 없어서

    View Slide

  476. func TestF(t *testing.T) {
    if f() != 42 {
    t.Fail("f() does not return 42")
    }
    }
    테스트케이스를 두꺼운 if문 덩어리로
    만들어야 한다는 점이었는데

    View Slide

  477. import "github.com/stretchr/testify/assert"
    func TestF(t *testing.T) {
    assert.Equal(t, 42, f())
    assert.NotEqual(t, 21, f())
    }
    전 테스트케이스를 좀 더 편하게 쓰기 위해
    서드파티 라이브러리인 "testify"를 쓰고 있습니다.

    View Slide

  478. import "github.com/stretchr/testify/assert"
    func TestF(t *testing.T) {
    assert.Equal(t, 42, f())
    assert.NotEqual(t, 21, f())
    }
    testify의 "assert" 패키지가 제공하는
    "Equal", "NotEqual" 같은 메소드를 이용하면

    View Slide

  479. import "github.com/stretchr/testify/assert"
    func TestF(t *testing.T) {
    assert.Equal(t, 42, f())
    assert.NotEqual(t, 21, f())
    }
    테스트 코드 작성도 훨씬 간편하고
    테스트 실패 보고서도 읽기 더 좋더라고요.

    View Slide

  480. import "github.com/stretchr/testify/assert"
    func TestF(t *testing.T) {
    assert.Equal(t, 42, f())
    assert.NotEqual(t, 21, f())
    }
    워낙 유용하고 유명해서 아마 여러분 대부분도
    이미 쓰고 계실 것 같습니다.

    View Slide

  481. https://godoc.org/github.com/hangulize/hangulize

    View Slide

  482. https://godoc.org/github.com/hangulize/hangulize
    한편 패키지를 문서화하면서는
    GoDoc의 초간단 문법이 인상적이었어요.

    View Slide

  483. • **이런거**, _이런거_, `이런거` 없음
    • 불릿 목록도 없음
    • 그림도 없음
    초라한 문법
    그동안 마크다운에 익숙해져 있었고
    마크다운도 충분히 간단하다고 생각했는데

    View Slide

  484. • **이런거**, _이런거_, `이런거` 없음
    • 불릿 목록도 없음
    • 그림도 없음
    초라한 문법
    GoDoc의 문법은
    훨씬 단순하더라고요.

    View Slide

  485. • **이런거**, _이런거_, `이런거` 없음
    • 불릿 목록도 없음
    • 그림도 없음
    초라한 문법
    **볼드**, _이탤릭_, `코드`도 없고
    불릿 목록도 없고 그림도 없었습니다.

    View Slide

  486. • URL엔 하이퍼링크
    • 들여쓰면 코드블록
    • 대문자로 시작하고 마침표가 없는 줄은 제목
    초간단 문법
    그렇다고 문서화하는 데에
    부족한 건 아니었어요.

    View Slide

  487. • URL엔 하이퍼링크
    • 들여쓰면 코드블록
    • 대문자로 시작하고 마침표가 없는 줄은 제목
    초간단 문법
    URL엔 자동으로 하이퍼링크가 붙고
    한 칸이라도 들여쓰기하면 코드블록으로 인식됩니다.

    View Slide

  488. • URL엔 하이퍼링크
    • 들여쓰면 코드블록
    • 대문자로 시작하고 마침표가 없는 줄은 제목
    초간단 문법
    마크다운처럼 "#" 같은 걸 붙이지 않고도

    View Slide

  489. • URL엔 하이퍼링크
    • 들여쓰면 코드블록
    • 대문자로 시작하고 마침표가 없는 줄은 제목
    초간단 문법
    대문자로 시작하고 마침표가 없는 줄은
    제목으로 취급되죠.

    View Slide

  490. $ go doc github.com/hangulize/hangulize
    PACKAGE DOCUMENTATION
    package hangulize
    import "github.com/hangulize/hangulize"
    Package hangulize transcribes non-Korean words into Hangul.
    "Hello!" -> "헬로!"
    Hangulize was inspired by Brian Jongseong Park
    (http://iceager.egloos.com/2610028). Based on this idea, the original
    커맨드라인
    문법이 이렇게 단순한 건
    GoDoc이 웹 사이트 뿐만 아니라

    View Slide

  491. $ go doc github.com/hangulize/hangulize
    PACKAGE DOCUMENTATION
    package hangulize
    import "github.com/hangulize/hangulize"
    Package hangulize transcribes non-Korean words into Hangul.
    "Hello!" -> "헬로!"
    Hangulize was inspired by Brian Jongseong Park
    (http://iceager.egloos.com/2610028). Based on this idea, the original
    커맨드라인
    커맨드라인 출력도 중요하게
    다루기 때문이라고 합니다.

    View Slide

  492. •.md, .rst에 비해 초라하지만
    •외울 게 적어서
    •서식을 헷갈리지 않아요.
    쉬운 문법
    아무튼 마크다운이나 reStructuredText에
    비하면 상당히 초라한 문법이지만

    View Slide

  493. •.md, .rst에 비해 초라하지만
    •외울 게 적어서
    •서식을 헷갈리지 않아요.
    쉬운 문법
    그만큼 외울 게 적어서
    금방 익숙해질 수 있었고

    View Slide

  494. •.md, .rst에 비해 초라하지만
    •외울 게 적어서
    •서식을 헷갈리지 않아요.
    쉬운 문법
    작성하면서 서식을 헷갈리는 일이
    거의 없었던 것 같습니다.

    View Slide

  495. $ godoc \
    -http=:8080 \
    -goroot="$GOPATH"
    로컬 godoc
    localhost:8080/pkg/github.com/hangulize/hangulize
    처음 쓸 때 조금 헷갈리더라도
    로컬 GoDoc 서버를 이용해

    View Slide

  496. $ godoc \
    -http=:8080 \
    -goroot="$GOPATH"
    로컬 godoc
    localhost:8080/pkg/github.com/hangulize/hangulize
    실시간으로 바로바로 확인하면서
    쓰다 보니 금새 익힐 수 있었습니다.

    View Slide

  497. func ExampleComposeHangul_perfect()
    예제 코드
    대상 이름 소제목
    예제 코드로
    인식되게 함

    View Slide

  498. func ExampleComposeHangul_perfect()
    예제 코드
    대상 이름 소제목
    예제 코드로
    인식되게 함
    또한 문서에 포함되는 예제 코드를
    테스트 코드의 일종으로 다루는 것도 인상적이었는데

    View Slide

  499. func ExampleComposeHangul_perfect()
    예제 코드
    대상 이름 소제목
    예제 코드로
    인식되게 함
    정해진 형식에 맞춰
    테스트 함수의 이름을 지정하면

    View Slide

  500. 문서 상에 딱 그 대상 밑에

    View Slide

  501. 함수 내용이 예제 코드로써
    배치되는 방식이었어요.

    View Slide

  502. $ go test
    --- FAIL: ExampleComposeHangul_perfect (0.00s)
    got:
    하느글라이스
    want:
    한글라이즈
    FAIL
    exit status 1
    FAIL github.com/hangulize/hangulize 1.949s
    예제 코드 방부처리
    예제 코드가 테스트 코드의 일종이다 보니
    혹시 나중에 그 내용이 틀리게 되더라도

    View Slide

  503. $ go test
    --- FAIL: ExampleComposeHangul_perfect (0.00s)
    got:
    하느글라이스
    want:
    한글라이즈
    FAIL
    exit status 1
    FAIL github.com/hangulize/hangulize 1.949s
    예제 코드 방부처리
    테스트가 바로 실패해서 언제나 올바른 상태를
    유지할 수 있도록 도와주더라고요.

    View Slide

  504. 3. 이룬 것

    View Slide

  505. 3. 이룬 것
    지금까지 한글라이즈를 Go로 다시 만들면서
    인상적이었던 부분을 소개해드렸는데

    View Slide

  506. 3. 이룬 것
    마지막으로 이번 재제작 과정을 통해서
    이룬 점들을 살펴보고 이 발표를 마치겠습니다.

    View Slide

  507. 1. 성능 개선
    이룬 것
    첫 번째는 성능 개선이에요.

    View Slide

  508. 1. 성능 개선
    이룬 것
    Go가 파이썬보다 훨씬 빠르기는 하지만
    이번엔 알고리즘에도 꽤 신경쓰면서 작업했거든요.

    View Slide

  509. Cappuccino이탈리아어
    ▶ 카푸치노
    •옛 한글라이즈 398㎲
    •새 한글라이즈 85㎲
    "카푸치노"같이 짧은 단어로 비교해보면
    옛 한글라이즈에선 398㎲가 걸렸지만

    View Slide

  510. Cappuccino이탈리아어
    ▶ 카푸치노
    •옛 한글라이즈 398㎲
    •새 한글라이즈 85㎲
    새 한글라이즈에선 85㎲밖에
    걸리지 않았습니다.

    View Slide

  511. Cappuccino이탈리아어
    ▶ 카푸치노
    •옛 한글라이즈 398㎲
    •새 한글라이즈 85㎲
    네다섯 배는 빨라진 거죠.

    View Slide

  512. 단어 길이 옛 한글라이즈 새 한글라이즈
    8만 자 630㎳ 465㎳
    80만 자 10초 5초
    800만 자 14분 50초
    시간
    옛 한글라이즈
    새 한글라이즈
    단어 길이
    단어가 길면 길 수록 새 한글라이즈가
    옛 한글라이즈보다 더욱 빠른데

    View Slide

  513. 단어 길이 옛 한글라이즈 새 한글라이즈
    8만 자 630㎳ 465㎳
    80만 자 10초 5초
    800만 자 14분 50초
    시간
    옛 한글라이즈
    새 한글라이즈
    단어 길이
    800만 자짜리 단어에서 새 한글라이즈에선
    50초 정도밖에 걸리지 않았지만

    View Slide

  514. 단어 길이 옛 한글라이즈 새 한글라이즈
    8만 자 630㎳ 465㎳
    80만 자 10초 5초
    800만 자 14분 50초
    시간
    옛 한글라이즈
    새 한글라이즈
    단어 길이
    옛 한글라이즈에선
    14분이나 걸리더라고요.

    View Slide

  515. O(n²) O(n)
    옛 한글라이즈 새 한글라이즈
    옛 한글라이즈엔 일부 비효율적인 코드가 있어서
    시간복잡도가 제곱 시간이었는데

    View Slide

  516. O(n²) O(n)
    옛 한글라이즈 새 한글라이즈
    그에 반해 새 한글라이즈는
    선형시간을 보장하기 때문입니다.

    View Slide

  517. 2. Phonemize 도입
    이룬 것

    View Slide

  518. 2. Phonemize 도입
    이룬 것
    두 번째는 이번에 새로 추가한
    Phonemize 단계예요.

    View Slide

  519. Rewrite Transcribe
    Phonemize
    재제작 과정에서
    새로 도입
    四川 쓰촨
    si chuan si, chwan, ㅆㅡㅊㅘ-ㄴ
    Phonemize 단계가
    옛 한글라이즈엔 없었거든요.

    View Slide

  520. Rewrite Transcribe
    Phonemize
    재제작 과정에서
    새로 도입
    四川 쓰촨
    si chuan si, chwan, ㅆㅡㅊㅘ-ㄴ
    앞에서 살펴봤듯이
    이 단계가 추가된 덕분에

    View Slide

  521. Rewrite Transcribe
    Phonemize
    재제작 과정에서
    새로 도입
    四川 쓰촨
    si chuan si, chwan, ㅆㅡㅊㅘ-ㄴ
    중국어도 새로 지원할 수 있었고
    일본어도 더 제대로 지원할 수 있게 됐죠.

    View Slide

  522. Ghoti fish
    Phonemize
    어쩌면 영어도?
    어쩌면 Phonemize 단계를 이용해서
    언젠간 영어도 지원할 수 있지 않을까 싶습니다.

    View Slide

  523. 3. 생산성 개선
    이룬 것

    View Slide

  524. 3. 생산성 개선
    이룬 것
    그리고 전사 규칙 만들 때의 생산성도
    상당히 좋아진 것 같아요.

    View Slide

  525. • 중국어 전혀 모르는데
    • 중국어 외래어 표기법 만드는 데 이틀
    전사 규칙 제작 생산성
    저는 중국어를 전혀 모르는데
    중국어 외래어 표기법 자료만 보고

    View Slide

  526. • 중국어 전혀 모르는데
    • 중국어 외래어 표기법 만드는 데 이틀
    전사 규칙 제작 생산성
    규칙을 만드는 데엔
    이틀 밖에 걸리지 않았습니다.

    View Slide

  527. test:
    "郭廣昌" -> "궈광창"
    "劉鶴" -> "류허"
    "屠呦呦" -> "투유유"
    "許家印" -> "쉬자인"
    "王健林" -> "왕젠린"
    "廬志强" -> "루즈창"
    "馬化騰" -> "마화텅"
    "努爾白克力" -> "누얼바이커리"
    "金立群" -> "진리췬"
    "曹國偉" -> "차오궈웨이"
    "李河君" -> "리허쥔"
    "游客" -> "유커"
    "雷軍" -> "레이쥔"
    "李保樟" -> "리바오장"
    "古天樂" -> "구톈러"
    "鄧森悅" -> "덩썬웨"
    이렇게 용례집에서 단어를 긁어서
    테스트케이스에 대량으로 집어넣고

    View Slide

  528. rewrite:
    "v" -> "yu"
    "{c|ch|r|s|sh|z|zh}i" -> "i,"
    "{}ue" -> "yue"
    "{}uan" -> "yuan"
    "{}un" -> "yun"
    transcribe:
    # 단운
    "yu" -> "ㅟ"
    # 제치류
    "{}yang" -> "ㅏ-ㅇ"
    "{}yan" -> "ㅔ-ㄴ"
    "{}you" -> "ㅜ"
    "{}yai" -> "ㅏㅣ"
    "{}yao" -> "ㅏㅗ"
    "{}ya" -> "ㅏ"
    "{}yo" -> "ㅗ"
    "{}ye" -> "ㅔ"
    오른쪽과 같은
    외래어 표기법 표를 참고해서

    View Slide

  529. rewrite:
    "v" -> "yu"
    "{c|ch|r|s|sh|z|zh}i" -> "i,"
    "{}ue" -> "yue"
    "{}uan" -> "yuan"
    "{}un" -> "yun"
    transcribe:
    # 단운
    "yu" -> "ㅟ"
    # 제치류
    "{}yang" -> "ㅏ-ㅇ"
    "{}yan" -> "ㅔ-ㄴ"
    "{}you" -> "ㅜ"
    "{}yai" -> "ㅏㅣ"
    "{}yao" -> "ㅏㅗ"
    "{}ya" -> "ㅏ"
    "{}yo" -> "ㅗ"
    "{}ye" -> "ㅔ"
    패턴 찾아 바꾸기 규칙만 몇 개 짜다 보니
    금방 완성할 수 있었죠.

    View Slide

  530. 4. Go 학습
    이룬 것

    View Slide

  531. 4. Go 학습
    이룬 것
    마지막으로 이번 한글라이즈 재제작을 통해서
    이룬 가장 큰 성과는

    View Slide

  532. 4. Go 학습
    이룬 것
    Go를 많이 익힐 수
    있었다는 것입니다.

    View Slide

  533. •고루틴은 끝내주는데
    •그런데 너무 기능이 적다.
    •고퍼도 귀엽지 않고
    Go 첫인상
    Go에 대한 제 첫인상은 이랬죠.

    View Slide

  534. •고루틴은 끝내주는데
    •그런데 너무 기능이 적다.
    •고퍼도 귀엽지 않고
    Go 첫인상
    고루틴은 끝내주지만
    언어의 기능이 너무 빈약해 보였습니다.

    View Slide

  535. •고루틴은 끝내주는데
    •그런데 너무 기능이 적다.
    •고퍼도 귀엽지 않고
    Go 첫인상
    고퍼도 안 귀엽고요.

    View Slide

  536. • 세밀하게 절제된 최소주의
    •실수하지 않도록 도와주는 환경
    Go 지금 인상
    하지만 지금은,
    빈약해 보였던 언어가

    View Slide

  537. • 세밀하게 절제된 최소주의
    •실수하지 않도록 도와주는 환경
    Go 지금 인상
    사실은 세밀하게 절제된
    최소주의를 따르는 것이었고

    View Slide

  538. • 세밀하게 절제된 최소주의
    •실수하지 않도록 도와주는 환경
    Go 지금 인상
    언어의 복잡성을 극도로 낮춰서

    View Slide

  539. • 세밀하게 절제된 최소주의
    •실수하지 않도록 도와주는 환경
    Go 지금 인상
    대규모 프로젝트에서도
    실수하기 어렵고

    View Slide

  540. • 세밀하게 절제된 최소주의
    •실수하지 않도록 도와주는 환경
    Go 지금 인상
    조금만 신경 써도 좋은 코드를
    작성할 수 있게 해준다는 걸 깨닫게 됐습니다.

    View Slide

  541. • 세밀하게 절제된 최소주의
    •실수하지 않도록 도와주는 환경
    • 고퍼는 여전히 귀엽지 않다.
    Go 지금 인상
    그래도 고퍼는 여전히
    귀여워 보이지 않지만요.

    View Slide

  542. •패키징
    •테스팅
    •문서화
    •정규표현식
    •파서
    • 플러그인
    • 성능 최적화
    Go에 자신감
    이번 경험으로 Go의
    여러가지 영역에 입문했고

    View Slide

  543. •패키징
    •테스팅
    •문서화
    •정규표현식
    •파서
    • 플러그인
    • 성능 최적화
    Go에 자신감
    덕분에 Go 코딩에
    자신감도 많이 붙었어요.

    View Slide

  544. - [한글라이즈 재제작기] 이흥섭(넥슨 왓 스튜디오)
    〈한글라이즈〉는 외국어 단어를 외래어 표기법에 따라 한글로
    옮겨 적어주는 도구입니다. "Espresso"를 "에스프레소"로, "東京
    "을 "도쿄"로 변환할 수 있죠. 본래 Python으로 구현했던 한글라
    이즈를 Go로 재구현하면서 겪은 경험과 느낀점을 공유합니다.
    Go에 근자감
    어떻게 보면 근자감일 수도 있는데
    결국 이 발표까지 하게 됐습니다.

    View Slide

  545. - [한글라이즈 재제작기] 이흥섭(넥슨 왓 스튜디오)
    〈한글라이즈〉는 외국어 단어를 외래어 표기법에 따라 한글로
    옮겨 적어주는 도구입니다. "Espresso"를 "에스프레소"로, "東京
    "을 "도쿄"로 변환할 수 있죠. 본래 Python으로 구현했던 한글라
    이즈를 Go로 재구현하면서 겪은 경험과 느낀점을 공유합니다.
    Go에 근자감
    이번 발표를 준비하면서

    View Slide

  546. - [한글라이즈 재제작기] 이흥섭(넥슨 왓 스튜디오)
    〈한글라이즈〉는 외국어 단어를 외래어 표기법에 따라 한글로
    옮겨 적어주는 도구입니다. "Espresso"를 "에스프레소"로, "東京
    "을 "도쿄"로 변환할 수 있죠. 본래 Python으로 구현했던 한글라
    이즈를 Go로 재구현하면서 겪은 경험과 느낀점을 공유합니다.
    Go에 근자감
    명확하게 정리하지 않고 넘어갔던 부분도
    명확하게 이해할 수 있었고

    View Slide

  547. - [한글라이즈 재제작기] 이흥섭(넥슨 왓 스튜디오)
    〈한글라이즈〉는 외국어 단어를 외래어 표기법에 따라 한글로
    옮겨 적어주는 도구입니다. "Espresso"를 "에스프레소"로, "東京
    "을 "도쿄"로 변환할 수 있죠. 본래 Python으로 구현했던 한글라
    이즈를 Go로 재구현하면서 겪은 경험과 느낀점을 공유합니다.
    Go에 근자감
    한글라이즈를 더 많이 발전시킬 수 있는
    기회가 되기도 했습니다.

    View Slide

  548. - [한글라이즈 재제작기] 이흥섭(넥슨 왓 스튜디오)
    〈한글라이즈〉는 외국어 단어를 외래어 표기법에 따라 한글로
    옮겨 적어주는 도구입니다. "Espresso"를 "에스프레소"로, "東京
    "을 "도쿄"로 변환할 수 있죠. 본래 Python으로 구현했던 한글라
    이즈를 Go로 재구현하면서 겪은 경험과 느낀점을 공유합니다.
    Go에 근자감
    발표 준비하는 동안 한글라이즈 코딩도
    평소보다 더 많이 했던 것 같아요.

    View Slide

  549. I
    GO
    요즘은 매일 일과후에
    Go로 코딩하는 것을 취미로 삼고 있는데

    View Slide

  550. I
    GO
    Go는 놀이처럼 느껴질 정도로
    코딩하기 즐거운 언어였습니다.

    View Slide

  551. I
    GO
    이렇게 Go 프로그래머 분들을
    많이 만날 수 있는 기회가 생겨서 설레고

    View Slide

  552. I
    GO
    여러분과 교류하며
    더 많이 배우고 싶습니다.

    View Slide

  553. I
    GO
    좀 더 이야기 나누고 싶은 분은
    [email protected]로 이메일 보내주세요.

    View Slide

  554. 감사합니다!
    이 제작물은 아모레퍼시픽의 아리따 돋움, 그리고
    서울남산체, 조선일보명조, 스포카한산스, Ubuntu Mono를
    사용하여 디자인 되었습니다.
    제가 준비한 발표는
    여기까지입니다.

    View Slide

  555. 감사합니다!
    이 제작물은 아모레퍼시픽의 아리따 돋움, 그리고
    서울남산체, 조선일보명조, 스포카한산스, Ubuntu Mono를
    사용하여 디자인 되었습니다.
    끝까지 읽어주셔서
    감사합니다.

    View Slide

  556. 김영호, 김찬웅,
    김향아, 박종성
    만든이 도와주신 분
    이흥섭

    View Slide