서버 없이 친구와 기록을 겨루는 "도전장 링크"의 원리
아람코의 게임은 끝나면 "친구에게 도전장 보내기"를 할 수 있습니다. 링크를 받은 친구는 같은 퍼즐, 같은 레벨, 같은 설정으로 바로 도전하고, 끝나면 누가 이겼는지 볼 수 있습니다.
특이한 점은 이 모든 일이 서버에 아무것도 저장하지 않고 일어난다는 것입니다. 회원가입도, 기록 저장 서버도 없습니다. 이 글은 그 원리를 정리한 개발 일지입니다.
기록은 주소의 # 뒤에 담겨요
도전장 링크는 "https://aramco.kr/apps/sokoban/#ch=…" 같은 모양입니다. #ch= 뒤에 기록(예: 레벨 4를 13수에)과 판을 다시 만들 정보(예: 레벨 번호)를 짧게 줄여 담습니다.
담는 방법은 간단합니다. 기록을 JSON이라는 글자 형식으로 적은 뒤, 주소에 넣어도 깨지지 않는 글자(Base64URL)로 바꿉니다. 받은 쪽은 거꾸로 풀어 읽습니다. 너무 긴 주소는 아예 읽지 않도록 900자까지만 받습니다.
주소에서 # 뒤 부분은 브라우저가 서버에 보내지 않는 영역입니다. 그래서 링크를 연 친구의 브라우저만 이 내용을 읽고, 아람코 서버는 기록을 받지도 저장하지도 않습니다. 보내는 사람이 적은 이름(선택)도 마찬가지입니다.
| 담기는 정보 | 예시 | 쓰임 |
|---|---|---|
| 기록 | 13수, 3:21, 250ms | 누가 이겼는지 비교 |
| 종목 | 레벨 4, 아리(어려움) · 흑 | 같은 조건끼리만 비교 |
| 판 정보 | 레벨 번호, 수도쿠 퍼즐 81칸, 리듬 곡 번호 | 친구 화면에 같은 판 만들기 |
| 이름 (선택) | 민수 | "민수님이 도전장을 보냈어요" |
같은 판을 다시 만드는 방법
게임마다 "같은 판"의 뜻이 다릅니다. 소코반은 레벨 번호만 있으면 되고, 리듬 탭은 곡과 난이도, 리버시·오목·장기·체스는 아리의 실력과 돌의 색·규칙이면 됩니다.
수도쿠는 퍼즐 81칸을 그대로 링크에 담습니다. 받은 쪽에서는 그 퍼즐의 답이 정확히 하나인지 다시 확인한 뒤에 엽니다. 퍼즐 이름 옆의 "#3F2A" 같은 번호는 81칸으로 계산한 짧은 지문이라, 같은 번호면 같은 퍼즐입니다.
지뢰찾기처럼 첫 칸을 연 뒤에 지뢰가 놓이는 게임은 같은 판을 미리 만들 수 없어서, 같은 난이도로 맞춰 두고 시간으로 비교합니다.
게임마다 무엇으로 겨룰까
도전장은 숫자 하나로 승부를 냅니다. 그래서 게임마다 "공정하게 비교할 수 있는 숫자"를 하나씩 정했습니다. 적을수록 좋은 기록과 많을수록 좋은 기록을 구분하고, 종목(레벨·난이도·설정)이 같을 때만 승패를 판정합니다. 종목이 다르면 기록만 보여 주고 승패는 말하지 않습니다.
| 게임 | 겨루는 숫자 | 좋은 쪽 | 같은 판 |
|---|---|---|---|
| 수도쿠 | 푼 시간 | 적을수록 | 같은 퍼즐 81칸 |
| 소코반 | 이동 횟수 | 적을수록 | 같은 레벨 |
| 리버시 | 돌 개수 차이 | 많을수록 | 같은 실력·색·제한 시간 |
| 오목·장기·체스 | 이길 때까지 둔 수 | 적을수록 | 같은 실력·색(진영)·규칙 |
| 세계여행 | 끝났을 때 재산 | 많을수록 | 같은 인원·실력·길이 |
| 리듬 탭 | 점수 | 많을수록 | 같은 곡·난이도 |
| 반응속도 | 반응 시간(ms) | 적을수록 | - |
오목·장기·체스처럼 지는 판이 있는 게임은 졌을 때 기록을 아주 큰 값(사실상 "패배")으로 담습니다. 그래서 친구가 이기기만 하면 도전 성공이고, 둘 다 이겼다면 더 빨리 이긴 쪽이 이깁니다.
링크를 조작하면 어떻게 될까
링크 안의 내용은 누구나 바꿀 수 있습니다. 그래서 받은 쪽에서는 모든 값을 믿지 않고 검사합니다.
- 숫자가 아니거나 너무 큰 기록은 버리고, 이름은 12자로 자르고 꺾쇠(<, >) 같은 기호를 지웁니다.
- 화면에는 글자로만 넣기 때문에, 이름에 HTML이나 스크립트를 넣어도 실행되지 않고 글자 그대로 보입니다.
- 판 정보도 게임마다 허용된 값인지(예: 레벨 번호가 범위 안인지, 난이도가 쉬움·보통·어려움 중 하나인지) 확인한 뒤에만 씁니다.
- 망가진 링크는 조용히 무시하고 평소처럼 게임을 엽니다.
왜 서버에 저장하지 않았나
아람코는 처음부터 "내 데이터는 내 기기에"를 원칙으로 삼았습니다. 게임 기록과 메모는 이용자의 브라우저에만 저장됩니다. 친구와 기록을 겨루는 기능을 만들 때도 이 원칙을 지키고 싶었고, 주소의 # 뒤를 쓰면 회원가입이나 개인정보 없이도 충분히 가능했습니다.
반대로 여러 사람이 함께 쓰는 공간이 필요한 기능, 예를 들어 이야기를 나누는 아람 광장은 서버에 글을 저장합니다. 이때도 IP 주소는 원문 대신 되돌리기 어려운 값으로만 저장하고 90일 뒤 지우는 등, 꼭 필요한 만큼만 다룹니다.
자주 묻는 질문
- 도전장 링크에 개인정보가 담기나요?
- 기록과, 직접 적은 경우의 이름(최대 12자)만 담깁니다. 실명이나 연락처는 적지 마세요.
- 링크가 너무 길어요.
- 수도쿠는 퍼즐 81칸을 담아서 조금 깁니다. 메신저에 붙여 넣으면 그대로 동작합니다.