카페의 메뉴판에 인쇄된 QR코드가 조금 긁혀 있어도 휴대전화는 주소를 찾아낸다. 가운데에 작은 로고가 들어간 코드도 종종 잘 읽힌다. 모든 검은 칸에 꼭 필요한 정보가 담겨 있다면, 일부가 사라진 순간 전체를 읽을 수 없어야 할 것 같다. 그런데 QR코드는 정보가 온전히 남아 있다는 가정에만 기대지 않는다. 손상을 어느 정도 견딜 수 있도록 처음부터 설계되어 있다.

핵심은 오류 정정이다. 원래 전달하려던 데이터에, 그 데이터를 복원하는 데 쓸 추가 정보를 함께 담는다. 이 추가 정보는 원본을 통째로 여러 번 복사한 것과는 다르다. 여러 부분 사이에 수학적인 관계를 만들어 두고, 읽어 낸 결과가 그 관계에 맞는지 확인하는 방식에 가깝다. QR코드는 이를 위해 리드–솔로몬 부호라는 방법을 사용한다.

간단한 비유를 생각해 보자. 종이에 세 수와 그 합을 적어 두었다고 하자. 세 수 가운데 하나가 지워져도 나머지 두 수와 합이 남아 있으면 사라진 수를 계산할 수 있다. 이것이 QR코드의 실제 알고리즘은 아니지만, 복원용 정보가 왜 도움이 되는지는 보여 준다. 원본 바깥에 관계를 남겨 두면, 빈칸을 단순히 짐작하는 대신 남은 정보로 제약을 걸 수 있다.

추가 정보는 공짜가 아니다. 같은 크기의 공간에 복원용 데이터를 더 담으면, 원래 내용에 쓸 수 있는 자리는 줄어든다. 같은 내용을 넣으면서 복원 능력을 높이려면 더 큰 코드가 필요할 수도 있다. 정보를 많이 담는 것과 손상을 잘 견디는 것 사이에는 이런 맞바꿈이 생긴다. QR코드의 버전과 오류 정정 수준을 함께 고려하는 이유다.

덴소웨이브는 네 가지 오류 정정 수준을 설명한다. 가장 높은 H 수준은 전체 코드워드의 약 30%를 복원할 수 있도록 설계되어 있다. 여기서 주의할 점은 이 수치를 곧바로 이미지 면적의 30%로 바꾸면 안 된다는 것이다. 손상된 위치와 형태, 인식에 필요한 무늬가 남아 있는지에 따라서도 읽기 결과는 달라진다. 아무 곳이나 크게 가려도 된다는 보장은 아니다.

프로그램을 만드는 사람에게도 이 원리는 낯설지 않다. 게임 저장 파일을 하나만 두는 것보다 별도의 백업을 두면 실수에 대응하기 쉽다. 다만 백업과 오류 정정은 동일한 기술이 아니다. 둘을 연결하는 생각은, 현실의 실패를 설계에서 미리 고려한다는 데 있다. “절대로 망가지지 않는다”는 기대 대신 “일부가 망가져도 어떤 방법으로 돌아올 것인가”를 묻는다.

다음에 QR코드를 스캔할 때는 검은 칸들을 주소의 조각으로만 보지 말자. 그 안에는 주소가 손상될 가능성에 대비한 정보도 있다. 우리가 매끄럽게 쓰는 기술은, 실패가 전혀 없어서 편리한 것이 아닐 때가 많다. 작은 실패를 눈에 띄지 않게 처리하도록 준비되어 있기 때문에 편리하다.