[QUIC-S] QUIC 기반 파일 동기화 시스템 개발 후기 (2023 공개 SW 개발자 대회)
- quics: https://github.com/quic-s/quics
- quics-client: https://github.com/quic-s/quics-client
- quics-protocol: https://github.com/quic-s/quics-protocol
지난 2023 공개 SW 개발자 대회에 참가하며 QUIC-S 파일 동기화 시스템을 개발한 후기를 정리한 내용이다.
공개 SW 개발자 대회는 오픈소스 프로젝트를 개발해 이를 출품해 시상하는 대회이다. 이를 위해 공개SW에 대한 기본적인 개념과 이해, GitHub 등 필요한 지식을 강의로 제공하며 프로젝트 기획, 개발, 구현, 협업 등의 개발 경험과 기능테스트, 라이선스 검증을 통해 공개SW의 전반적인 개발 과정을 경험할 수 있다.
개발동기
평소 여러 디바이스의 파일을 동기화하는 분산 시스템 개발에 관심이 있었고 실제로 아래 포스트와 같이 syncthing
이라는 오픈소스 프로그램을 사용해 개인적인 파일 동기화 시스템을 구축하기도 하였다.
하지만 라즈베리파이를 사용해 24시간 서버를 운영하고 있는 입장에서 P2P 보다는 좀 더 서버-클라이언트 구조에 적합한 시스템이 있으면 좋겠다고 생각하였다. 중앙에 서버가 있으면 서버를 사용해 동기화 되고 있지 않은 제 3자에게 특정 파일을 건네주는 기능 등을 추가할 수 있을 것이고 파일의 변경사항 같은 히스토리를 서버에서만 중앙 집중적으로 관리할 수 있을것 같기 때문이다.
물론 기존에 OwnCloud나 NextCloud 같은 오픈소스 프로젝트 또한 존재한다. 하지만 OwnCloud는 구축을 위해 MySQL 같은 외부 데이터베이스를 추가로 설치해야하고 NextCloud는 파일 동기화외에도 많은 기능을 제공한다. 따라서 내장 DB를 사용해 좀 더 작고 파일 동기화 그 자체에 집중한 시스템을 개발해 보기로 하였고 추가로 최근 표준화된 QUIC 프로토콜을 사용해 좀 더 빠르고 안정적인 시스템을 만들고자 하였다.
따라서 위와 같은 동기를 갖고 마음이 맞는 친구들과 함께 QUIC-S 파일 동기화 시스템을 개발하게 되었다.
QUIC-S
Feature
QUIC-S는 기존 TCP가 아닌 QUIC과 Go언어를 사용한 오픈소스 파일 동기화 시스템이다. 따라서, 동기화가 진행중인 모습을 그림으로 나타내면 위와 같은 모습일 것이다. 추가로 QUIC-S에는 파일을 공유할 수 있는 기능이 있어 특정 파일만 외부에 노출 할 수 있는 링크가 생성된것이 downloader이다.
QUIC-S의 핵심 키워드 뽑아보면 파일과 실시간, 그리고 동기화 라는 세 부분으로 나눌 수 있다. 이를 위해 각각 파일 데이터관리 / 논리시계 / 파일변경 사항 감지를 내부적으로 구현하였다.
우선 실시간이라는 개념을 위해 논리시계가 사용되었는데, 위의 나와있는 네가지의 이벤트가 일어나면 논리시계를 계산한후 서버로 전송하는 방식이다.
파일 전송에는 quics-protocol이라는 자체 프로토콜을 사용하였다. 이는 QUIC을 기반으로 하여 파일 전송에 특화된 프로토콜로 자세한 내용은 아래에 서술하였다.
동기화를 위해서는 파일의 업데이트와 동시에 이를 서버로 전송하고 다른 클라이언트로 전파하여 덮어쓰는 과정이 필요하다. 이때 논리시계를 기준으로 파일의 버전을 판별하였고 이러한 데이터는 내장 DB에 싱크 메타데이터로 저장이 된다.
만약 서버로 전송된 파일이 최신본을 기반으로 수정된 것이 아니라는 판단을 하면 conflict로 처리를 해 더이상 히스토리를 업데이트 하지않는다. 이때 유저가 전송하는 파일의 업데이트 내용들은 conflict가 해결될때가지, 서버의 conflict 저장공간에 저장되고 후에 유저가 conflict를 해결하면 다시 동기화가 진행된다.
또한, 파일들의 모든 업데이트 사항은 히스토리가 되며 서버에 저장되고 유저가 원하면 언제든지 과거로 롤백이 가능하다. 추가로, 파일 자체를 다운로드 받을 수 있는 링크를 만드는 기능을 제공하는데, 이를 통해 동기화 시스템에 속해있지 않은 제 3자에게 파일을 전달할 수 있다.
System Design
위 그림은 QUIC-S의 전반적인 시스템 구조 서버는 quics이고 클라이언트는 quics-client이다. 주목할 점은 각 클라이언트와 서버가 Restful API에 대한 http 서버 역할도 하기 때문에 이 Restful API를 통해 클라이언트와 서버를 제어할 수 있다는 점이다.
따라서 클라이언트와 서버를 제어하는 CLI 명령(qic 및 qis)도 처음에 프로세스를 시작하는 명령을 제외하고 내부적으로 http 클라이언트를 사용하여 클라이언트 및 서버와 각각 상호 작용한다. 이를 통해 CLI를 사용하지 않고도 다른 시스템과 통합을 구축할 수 있으며 미래에는 웹 기반 GUI를 염두에 두고 있다.
아래는 시스템을 디자인할 때 고려하였던 사항들이다.
quics-protocol
본격적인 QUIC-S 개발에 앞서 시스템이 내부적으로 메시지와 파일을 주고받을 때 사용할 quics-protocol을 개발하였다.
기존의 TCP는 여러 파일 전송을 위한 멀티플렉싱, 효율적인 전송을 위한 압축과 안전한 전송을 위한 보안전송이 내장되어 있지 않기 때문에 이를 어플리케이션 레이어에서 구현해 주어야 했다.
하지만 QUIC은 이러한 점들이 개선되어 stream 기반 멀티 플렉싱과 QPACK을 사용한 압축 전송, 그리고 TLS 암호화가 내장되었기 때문에 이를 적극 활용하는 간단한 프로토콜을 먼저 개발하기로 하였고 quics-protocol을 개발하였다.
Transaction
quics-protocol에서는 효율적인 병렬처리를 위해 transaction마다 stream을 생성하고 이를 통해 시스템 내부적으로 메시지와 파일을 주고받는다.
Transaction은 메시지와 파일을 주고받는 단위로 어떤 동작이나 이벤트의 처리를 위해 이루어지는 일련의 통신을 의미한다. 예를 들어, 파일을 업로드 하기 위해서는 파일의 메타데이터를 먼저 서버로 전송하고 이후에 파일의 내용을 전송해야한다. 이때 파일의 메타데이터를 전송하는 행위와 파일의 내용을 전송하는 행위를 하나의 transaction으로 묶어서 처리한다.
아래는 QUIC-S에서 사용하는 transaction의 종류이다.
더 자세한 내용은 transaction.md에서 확인할 수 있다.
결과
성과
2023 공개 SW 개발자 대회에서 학생부문 장려상을 수상하였다.
우선 완전히 기능하는 파일 동기화 시스템을 대회기간안에 개발하였고 장려상 또한 수상하는 성과를 거둘 수 있었다. 막연히 생각하던 파일 동기화 시스템을 실제 개발은 큰 도전이었다. 프로토콜 개발을 위한 소켓 프로그래밍도 처음이었고 파일 동기화를 위해 필요한 기능과 과정은 어떤것이 있는지 설계하기 위해 정말 많은 고민을 하였다. 이 과정에서 팀원과 정말 많은 의견을 주고받았고 이러한 과정이 힘들기도 하였지만 한편으론 재미있었다.
하지만 대회를 목표로 급하게 개발한 만큼 여러 아쉬운 점이 있다고 생각한다. 우선 현재 QUIC-S는 서버 그 자체는 단일로 동작하는 문제가 있는데 파일의 안전한 저장은 분산 파일 시스템을 사용하여 개선할 수 있지만 가용성과 확장성에는 한계가 있기 때문이다. 이를 위해 분산 데이터베이스와 RAFT 알고리즘 등을 공부하여 서버를 분산 모드로 운용할 수 있도록 개선하고자 한다. 또한 현재는 파일이 변경되면 파일 전체를 전송하는데 이를 rdiff 알고리즘과 같은 방식의 증분 백업을 적용하는 것도 공부하고자 한다.
향후 계획
위 그림은 QUIC-S의 로드맵으로 자세한 내용은 roadmap.md에서 확인할 수 있다.
공개 SW 개발자 대회는 12월 1일 시상식으로 끝났지만 시간이 된다면 QUIC-S를 발전시키고자 개선이 필요한 점들을 로드맵에 정리해 보았다. 분산시스템에 대한 더 많은 공부와 함께 이를 실제로 적용해 더 실용적인 시스템으로 발전시키고 싶다.