5P by GN⁺ | ★ favorite | 댓글 1개
  • 텍스트가 QR 코드로 바뀌는 내부 과정을 0~9단계 시각화로 따라가며, Nayuki QR Code generator library의 동작 원리를 확인할 수 있음
  • 예시 입력 Hello, world! 123은 17개 Unicode 코드 포인트로 분석되고, Numeric·Alphanumeric·Kanji가 아닌 Byte 모드로 인코딩됨
  • 모드 비트, 문자 수, 세그먼트 데이터, 종료 비트를 이어 붙인 결과 19개 데이터 코드워드가 만들어져 Version 1의 ECC L 용량에 들어맞음
  • Version 1 QR 코드는 1개 블록에 데이터 코드워드 19개와 Reed–Solomon ECC 코드워드 7개를 붙인 뒤, 고정 패턴과 데이터 모듈을 배치함
  • 8개 마스크의 패널티를 비교해 총점이 가장 낮은 Mask pattern 3을 선택하며, 최종 결과가 단순 인코딩이 아니라 품질 평가까지 거쳐 정해짐

데모의 목적과 입력 처리

  • 이 웹 애플리케이션은 텍스트 문자열이 QR 코드로 인코딩되는 과정을 단계별로 시각화함
  • 페이지는 QR Code generator library의 내부 동작을 이해할 수 있도록 인코딩 과정을 풀어 보여줌
  • 사용자 입력 항목은 텍스트 문자열, 오류 정정 수준, 최소 Version 강제, 마스크 패턴 강제로 구성됨

0단계: Unicode 문자 분석

  • 예시 문자열은 Hello, world! 123이며, 입력 텍스트의 코드 포인트 수는 17개
  • 각 문자는 Numeric, Alphanumeric, Byte, Kanji 모드에서 인코딩 가능한지 검사됨
  • 전체 문자열의 모드별 인코딩 가능 여부는 다음과 같음
    • Numeric: 불가능
    • Alphanumeric: 불가능
    • Byte: 가능
    • Kanji: 불가능
  • 전체 문자를 담기 위해 선택된 세그먼트 모드는 Byte

1단계: 데이터 세그먼트 생성

  • 각 문자는 비트열로 변환됨
  • Numeric 및 Alphanumeric 모드에서는 연속 문자를 묶어서 인코딩함
  • Byte 모드에서는 문자 하나가 8, 16, 24, 32비트 중 하나를 생성함
  • 예시에서는 각 문자의 16진수 값이 8비트로 변환됨
    • H: 4801001000
    • e: 6501100101
    • 1: 3100110001
    • 2: 3200110010
    • 3: 3300110011
  • 데모 프로그램은 단순화를 위해 항상 단일 세그먼트를 만듦
  • 전체 비트 길이를 줄이는 최적 분할 방식은 optimal text segmentation for QR codes에서 따로 다룸

2단계: Version 번호 맞추기

  • 세그먼트 목록을 표현하는 데 필요한 전체 비트 길이는 Version 범위에 따라 달라짐
    • Version 1~9: 148비트, 19 코드워드
    • Version 10~26: 156비트, 20 코드워드
    • Version 27~40: 156비트, 20 코드워드
  • 코드워드는 8비트, 즉 1바이트로 정의됨
  • QR 코드의 데이터 코드워드 용량은 Version과 오류 정정 수준에 따라 달라짐
  • 예시 입력은 선택된 오류 정정 수준에서 Version 1에 들어맞음
  • 최종 선택된 Version 번호는 1

3단계: 세그먼트 연결, 패딩, 코드워드 생성

  • 여러 비트 문자열을 이어 붙여 데이터 비트열을 만듦
    • Segment 0 mode: 0100, 4비트
    • Segment 0 count: 00010001, 8비트
    • Segment 0 data: 136비트
    • Terminator: 0000, 4비트
  • 누적 비트 수는 152비트
  • 예시에서는 Bit padding과 Byte padding이 모두 0비트임
  • 전체 데이터 코드워드 바이트는 8비트 단위로 나뉘어 16진수로 표시됨
    • 41 14 86 56 C6 C6 F2 C2 07 76 F7 26 C6 42 12 03 13 23 30

4단계: 블록 분할, ECC 추가, 인터리브

  • 예시의 블록 통계는 다음과 같음
    • 데이터 코드워드 수: 19
    • 블록 수: 1
    • 짧은 블록당 데이터 코드워드: 19
    • 긴 블록당 데이터 코드워드: 해당 없음
    • 블록당 ECC 코드워드: 7
    • 짧은 블록 수: 1
    • 긴 블록 수: 0
  • 데이터 코드워드 시퀀스를 짧은 블록과 긴 블록으로 나누고, 각 블록 끝에 ECC 코드워드를 계산해 붙임
  • Reed–Solomon 오류 정정 코드 계산의 수학적 과정은 길고 지루하며 흥미롭지 않다는 이유로 생략됨
  • 최종 코드워드 시퀀스는 데이터와 ECC 코드워드를 인터리브해 구성됨
    • 41 14 86 56 C6 C6 F2 C2 07 76 F7 26 C6 42 12 03 13 23 30 85 A9 5E 07 0A 36 C9
  • 지그재그 스캔에 그릴 최종 비트열도 이 코드워드 시퀀스에서 생성됨

5~6단계: 고정 패턴과 코드워드 배치

  • 고정 패턴 단계에서는 행 6과 열 6에 timing pattern을 그림
  • 세 모서리에는 separator를 포함해 각각 8×8 finder pattern을 배치함
  • finder 주변에는 임시 dummy format bits가 들어감
  • 코드워드 배치 단계에서는 오른쪽 아래 모서리에서 시작하는 지그재그 스캔을 계산함
  • 지그재그 스캔은 기능 모듈(function module)을 건너뛰고 아직 채워지지 않은 모듈을 방문함
  • 데이터, ECC, remainder 모듈은 최종 코드워드 비트값과 지그재그 순서에 따라 그려짐
  • 예시로 16진수 코드워드 C5는 이진수 11000101이며, [dark, dark, light, light, light, dark, light, dark] 모듈 시퀀스를 생성함

7~9단계: 마스크 적용과 패널티 계산

  • 각 마스크 패턴은 비기능 모듈(non-function module)에만 영향을 줌
  • 마스크는 데이터, ECC, remainder 모듈에 XOR로 적용됨
  • 실제 format bits는 finder 주변에 그려짐
  • 패널티 탐색은 다음 요소를 검사함
    • 같은 색 모듈이 5개 이상 이어지는 가로 run
    • 같은 색 모듈이 5개 이상 이어지는 세로 run
    • 같은 색의 2×2 box
    • 가로 finder-like pattern
    • 세로 finder-like pattern
    • 어두운 모듈과 밝은 모듈의 균형
  • 예시 QR 코드의 크기와 색상 비율은 다음과 같음
    • 한 변 길이: 21
    • 전체 모듈: 441
    • 밝은 모듈: 221
    • 어두운 모듈: 220
    • 어두운 모듈 비율: 49.887%
    • 절반 대비 편차: −0.113%
  • 8개 마스크의 총 패널티는 다음과 같음
    • Mask 0: 1204
    • Mask 1: 1134
    • Mask 2: 1084
    • Mask 3: 1081
    • Mask 4: 1121
    • Mask 5: 1100
    • Mask 6: 1189
    • Mask 7: 1137
  • 가장 낮은 총 패널티를 받은 마스크는 Mask pattern 3

소스 코드

댓글과 토론

Hacker News 의견들
  • QR 코드 설명은 온라인 어디를 봐도 Reed-Solomon 오류 정정 계산을 빼먹는 것 같아 아쉬움
    여기서도 저자가 “길고, 지루하고, 별로 흥미롭지 않다”고 했지만, 다들 그렇게 생각하다 보니 이제 찾기가 꽤 어려워짐
    • 대학원에서 부호 이론 수업을 들었는데, 들었던 수업 중 가장 엄밀했고 5명 모두에게 어려웠지만 듣길 잘했다고 생각함
      Reed-Solomon은 학기 중반을 좀 지난 뒤 다뤘고, 핵심은 다항식에 기반한다는 것임. 충분한 점이 있으면 다항식이 정확히 정해지므로, 여분의 점을 넣어 두면 일부가 사라져도 복원할 수 있음
      나머지는 이를 이진 데이터에 적용하는 방법, 즉 유한체를 쓰는 부분인데 수학적으로 아름답지만 꽤 복잡해짐
    • 오류 정정 계산은 이 두 튜토리얼이 설명해 줌
      https://www.thonky.com/qr-code-tutorial/error-correction-cod...
      https://dev.to/maxart2501/let-s-develop-a-qr-code-generator-...
    • https://www.quaxio.com/an_artisanal_qr_code.htmlPagedOut! Issue #2에는 긴 나눗셈으로 오류 정정 계산까지 포함해 QR 코드를 처음부터 만드는 내용이 있음
    • 길고 지루하지만, 사실 전체에서 가장 흥미로운 부분
    • 관련 Wikipedia 문서가 있음
  • 최근 Veritasium 영상 I used to hate QR codes. But they're actually genius도 이 주제를 다룸
    https://www.youtube.com/watch?v=w5ebcowAJD8
  • 저자가 받은 피드백 모음이 꽤 재미있음: https://www.nayuki.io/page/poor-feedback-from-readers
    • 영어가 서툰 사람들을 조롱하고, 이메일 보낸 사람들이 그 나라의 대표 표본인 것처럼 한 국가 전체를 깎아내리는 논평은 보낸 사람들보다 블로그 주인에 대해 더 많은 걸 보여줌
      논평에서 엘리트주의적인 분위기가 강하게 느껴짐. 블로그를 대충 훑어보니 Bitcoin 기부를 요청하면서 $3를 제안하는데, 수수료로 상당 부분이 사라질 수 있다는 점은 고려하지 않은 듯함
    • 마음에 들지 않는 메시지를 받았더라도, 불만을 말할 때 가벼운 인종차별과 작성자의 영어 실력 비판을 섞지 않는 편이 좋음
    • 서툰 영어를 놀리는 건 언제나 어리석음의 신호임. 똑똑한 사람도 바보처럼 굴 수 있음
    • 미안하지만 블로그 작성자가 꽤 별로인 사람처럼 보임
      “아니, 네 대학 프로젝트 챗봇에 내 GitHub 저장소 코드를 쓰면 안 돼. 네 코딩 기준은 내 기준에 못 미쳐. 그리고 네 영어도 형편없어” 같은 느낌임
    • 개인 블로그 운영이 얼마나 힘들 수 있는지 알겠음. 온갖 사람을 상대해야 함
      다행히 좋은 피드백도 따로 공유하고 있음: https://www.nayuki.io/page/decent-feedback-from-readers
  • 꽤 훌륭함. 같은 방식으로 디코더도 보고 싶음
    • 컴퓨터 없이 QR 코드를 읽는 방법을 다룬 Piko와 blinry의 가이드도 좋아할 수 있음: https://qr.blinry.org/
    • 공감함. 휴대폰이 어둡고 흐릿하고 1/4쯤 화면 밖으로 나간 QR 코드도 그렇게 빨리 해독하는 걸 보면 늘 놀라움
    • QR 리더를 0부터 구현하는 가이드를 계속 찾고 있음
      Google에서 보이는 것처럼 “그냥 이 컴퓨터 비전 라이브러리를 꽂고 이미지를 넣으면 결과가 나온다”는 식은 원하지 않음
      이미 디코딩된 원시 이미지 데이터가 있다고 가정한 뒤, 필요한 모든 알고리즘을 구현해 나가는 가이드를 찾고 있음
  • 설명이 있어서 좋음. 개인적으로는 그냥 빨리 만들고 싶었는데, 검색하면 광고투성이 사이트나 “가입해야 사용 가능” 사이트가 나왔음
    GitHub에서도 몇 개 찾았지만 다른 문제가 있어서, 전에 써 본 잘 설계된 라이브러리로 직접 빠르게 만들었고 15분쯤 걸림
    https://greggman.github.io/qr-code/
    옵션을 더 추가할 수도 있지만, 사실 대부분의 사용자는 그런 옵션이 필요 없을 것 같음
    • 유용했다니 기쁨. 나도 한동안 구현체를 직접 써 보고 싶었는데, 찾을 수 있었던 건 Python이나 Golang용 완성 패키지뿐이었음
      QR 코드와 관련해 오류 정정 부분을 알 수 있는 유용한 자료가 있으면 알고 싶음
  • 예전에 Rust 구현체를 만들었음
    https://github.com/aabiji/qr
  • 현재 연도 글이 아니라면 제목에 글의 연도, 여기서는 2018을 붙이는 게 좋은 관례임
    • 동의함. 원문 링크에는 내가 보기엔 날짜가 없었고, 이제는 더 이상 수정할 수 없음
  • 좋음. QR 코드가 어떻게 동작하는지 배우는 게 오래전부터 할 일 목록에 있었는데, 좋은 입문 글이었음
  • 이제 동작 방식을 알았으니 SQL 쿼리에서도 쓸 수 있음: https://github.com/Florents-Tselai/pgQR