본문으로 이동

도커 스웜, k3s, Nomad를 거쳐 오케스트레이터 없이

.
빈 무대 위에서 지휘자 없이 의자에 앉아 리허설하는 현악 사중주단.
© Billkaboo, CC BY-SA 4.0

페미위키가 띄우는 컨테이너는 웹 서버(Caddy), PHP를 실행하는 php-fpm, 백그라운드 작업 실행기(job runner), 캐시(memcached) 몇 개뿐입니다. 그런데도 페미위키는 2018년부터 7년 동안 도커 스웜과 Nomad라는 오케스트레이터(컨테이너를 띄우고, 죽으면 다시 띄우고, 새 버전으로 바꿔 주는 도구)를 차례로 쓰고 그사이 k3s도 시험해 보았고, 2025년에야 오케스트레이터 없이 컨테이너를 띄우게 되었습니다. 이 글에서는 작은 서버에서 오케스트레이터를 쓰며 겪은 일과, 오케스트레이터 없이 무중단 배포를 되찾은 방법을 시간 순서대로 돌아봅니다.

도커 스웜

페미위키는 처음에 개발 환경을 만드는 도구인 Vagrant로 운영 서버까지 다루었습니다. Vagrant의 AWS 플러그인으로 t2.micro 인스턴스를 띄우고, 배포할 때는 개발자 컴퓨터에서 rsync로 파일을 올린 뒤 Vagrant로 설치 스크립트를 다시 돌렸습니다.[1] 서버를 새로 띄우지 않고 같은 서버를 계속 고쳐 썼기 때문에, 저장소에는 없고 서버에만 있는 파일도 생겼습니다.[2]

Vagrant 방식은 개발자 한 사람과 컴퓨터 한 대만 고려한 것이어서,[3] 2018년 가을 여럿이 같은 방법으로 배포할 수 있도록 미디어위키를 도커 이미지로 만들고 도커 스웜(도커에 들어 있는 오케스트레이터)으로 배포하기 시작했습니다. 이때 미디어위키 인스턴스를 EC2 오토스케일링으로 늘리고 줄이는 것도 시도했지만 곧 접었고,[4] 미디어위키 인스턴스와 데이터베이스·봇 인스턴스 두 대로 운영했습니다.[5] 그러다 2019년 11월 비용을 줄이려고 두 대를 t3a.micro 한 대로 합치고, 데이터베이스와 캐시까지 같은 스웜 스택에 넣어 띄웠습니다.[6]

스웜에서는 방문자의 IP 주소가 문제였습니다. 스웜의 내부 네트워크를 거치면서 모든 방문자가 10.255.0.2라는 내부 주소에서 접속한 것으로 보여, 자동 차단이 엉뚱한 사람에게 걸리는 등의 문제가 생겼습니다.[7] 컨테이너가 서버의 네트워크를 그대로 쓰게 하면 풀리지만, 스웜 스택 파일에서는 그 설정(network_mode)이 무시되었고 docker compose로 바꿔 시험해 보니 컨테이너끼리 이름으로 서로를 찾던 방식을 쓸 수 없었습니다. 결국 이 문제는 쿠버네티스로 옮기면서 풀기로 했고, 개발팀은 같은 날 "업계 표준인 쿠버네티스로 넘어가야겠다"며 쿠버네티스의 가벼운 배포판인 k3s를 검토하기 시작했습니다.[8] 열흘쯤 뒤에는 도커의 기업용 사업부가 미란티스에 팔리면서 스웜을 정리하는 것 같다는 소식도 전해졌습니다.

k3s

k3s는 운영 서버와 따로 띄운 인스턴스에서 시험했고, 결국 운영에는 쓰지 못했습니다.[9] k3s 자체는 금방 설치되었지만, AWS와 엮는 데서 시간이 많이 들었습니다. 쿠버네티스가 필요할 때 EBS 볼륨을 만들어 붙이게 하려 했는데 클라우드 컨트롤러 매니저로는 되지 않아서, aws-ebs-csi-driver를 따로 설치해야 했습니다. 인증서는 cert-manager로 Let's Encrypt에서 자동으로 받게 했습니다. 2019년 12월 7일 0시에 시작해 여기까지 오는 데 78시간이 걸렸습니다.[10]

k3s 서버를 다시 만들어도 클러스터를 이어 쓸 수 있도록, 2020년 2월에는 k3s가 클러스터 상태를 저장하는 디렉터리(/var/lib/rancher/k3s)를 별도 EBS 볼륨에 두어 보았습니다. 그런데 새 인스턴스에서 그 상태를 불러오자 일부 파드가 종료 중인 것과 실행 중인 것 둘씩 보이는 등 클러스터가 비정상적인 상태에 빠졌습니다.[11] 결국 클러스터 상태는 보존하지 않기로 하고, EBS 볼륨을 그때그때 만드는 대신 k3s에 기본으로 들어 있는 로컬 스토리지를 쓰기로 했습니다. 데이터베이스와 업로드 파일 같은 서비스 데이터는 스웜 때처럼 EBS 볼륨을 통째로 붙인 /srv 디렉터리 아래에 두었습니다.

끝내 풀지 못한 문제는 스웜을 떠나려던 바로 그 이유, 방문자의 IP 주소였습니다. k3s에서도 traefik을 거친 요청에는 방문자의 주소 대신 클러스터 내부 주소만 남아서, 미디어위키가 모든 방문자를 같은 사람으로 보았습니다.[12] 서비스의 externalTrafficPolicy를 Local로 바꾸면 된다는 해법도 알려져 있었지만,[13] 당시 개발팀은 바빠서 이를 시도해 보지 못했습니다. 결국 2020년 8월, 개발팀은 k3s 대신 다른 오케스트레이터를 찾기로 했습니다.[14] 그래서 운영 서버는 k3s로 옮기지 못한 채 스웜에 남았습니다.

Nomad

다음 후보는 Nomad였습니다. Nomad는 테라폼을 만든 하시코프의 오케스트레이터로, 쿠버네티스보다 구성 요소가 적고 컨테이너가 아닌 프로그램도 띄울 수 있다는 점을 내세웁니다.[15] 다만 2020년 당시에는 컨테이너끼리 서로를 찾게 하려면 같은 회사의 Consul을 함께 띄워야 했습니다. 로블록스처럼 큰 규모로 쓰는 곳도 있지만,[16] 쿠버네티스에 비하면 쓰는 곳이 훨씬 적어서 문제가 생겼을 때 참고할 자료도 적습니다.[17] 왜 Nomad를 골랐는지는 기록에 따로 남아 있지 않습니다. 2020년 10월 먼저 시험 서버에 Nomad로 페미위키를 띄워 보았습니다.

시험 서버(메모리 2GiB인 t3a.small)는 느리고 502 오류가 자주 났습니다.[18] 2020년 12월 평소 메모리 한도와, 잠깐 넘어설 수 있는 상한을 따로 정하는 옵션(memory_hard_limit)을 찾아 속도는 훨씬 나아졌지만 502 오류는 가끔 이어졌습니다.[19] 원인은 PHP 컨테이너가 메모리 한도에 걸려 강제로 종료되는 것이었는데,[20] 2021년 1월 함께 뜨는 Envoy 프록시의 메모리 한도를 늘리자 나아졌습니다(Envoy는 Consul의 서비스 메시 기능인 Consul Connect가 서비스마다 붙이는 프록시로, 시험 서버는 이것으로 컨테이너끼리 연결했습니다).[21] Nomad가 띄운 컨테이너는 스왑도 쓸 수 없었기 때문에, 2021년 3월에는 Nomad의 도커 드라이버에서 스왑을 끄는 부분을 지우고 직접 빌드해 보기도 했습니다.[22] 다만 바로 위 줄에서 메모리와 스왑을 합친 한도를 메모리 한도와 같게 잡고 있어서, 그 부분만 지워서는 여전히 스왑을 쓸 수 없었을 것으로 보입니다(이 시도가 어떻게 끝났는지는 기록에 남아 있지 않습니다).

2021년 3월 31일에는 운영 서버로 가던 방문자 트래픽을 Nomad 시험 서버로 돌려 보았고, 이번에는 CPU가 문제였습니다. t 계열 인스턴스는 기준 성능(t3a.small은 20%)보다 CPU를 많이 쓰는 동안 쌓아 둔 크레딧을 깎아 쓰는데, 트래픽을 받자 CPU 사용률이 20~40%로 올라 크레딧이 계속 줄었습니다. PHP가 쓰는 CPU는 스웜 서버와 비슷했으니, Nomad와 Envoy 프록시가 더 쓰는 몫이 기준 성능을 넘긴 것으로 보였습니다.[23] 그래서 같은 날 Consul을 빼고 컨테이너가 호스트 네트워크를 그대로 쓰도록 바꾸었습니다. 덕분에 방문자 IP도 제대로 보이게 되었지만,[24] 같은 포트를 쓰는 컨테이너를 두 개 띄울 수 없어 새 버전을 옆에 띄우고 넘기는 무중단 배포는 여전히 할 수 없었습니다(스웜에서도 배포할 때마다 사이트가 잠깐 멈추고 있었습니다).[25] Consul을 뺀 뒤에도 크레딧은 며칠에 걸쳐 계속 줄었고(원인은 기록에 남아 있지 않습니다), 4월 9일 운영 서버를 다시 스웜으로 되돌리면서 방문자 IP 문제도 함께 돌아왔습니다.[26] 이 무렵의 고민은 2021년 4월 1일 이 블로그에 올린 "인프라 구조 재고"에도 적었습니다.

스웜으로 돌아가면서 세운 계획은 페이지를 캐시해 PHP가 쓰는 CPU를 줄여 보는 것이었습니다.[27] 그렇게 준비한 것이 페미위키가 직접 만든 Caddy 캐시 모듈 caddy-mwcache("Caddy로 만든 미디어위키 캐시, caddy-mwcache"에서 소개)입니다. 4월 12일에는 크레딧 문제의 대안으로 꼽아 두었던 Arm 기반 t4g.small 인스턴스에 Nomad와 caddy-mwcache를 함께 띄워 운영 서버를 옮겼고, 이번에는 처음부터 Consul 없이 호스트 네트워크를 써서 방문자 IP도 제대로 보였습니다. 처음 며칠은 순조로워 보였습니다.[28] 하지만 곧 디스크(EBS)의 성능 크레딧이 바닥나고 PHP와 MySQL이 메모리 한도에 걸려 종료되는 일이 이어져, 사이트에 간헐적으로 접속할 수 없었습니다.[29] 디스크는 4월 24일 성능 크레딧이 없는 gp3 볼륨으로 바꾸었고,[30] 나머지 문제도 6월까지 대부분 해결되었습니다.[31] 그 뒤로 3년 반 동안은 한 대짜리 Nomad 서버에서, 배포할 때마다 사이트가 잠깐 멈추는 채로 운영했습니다. 그래서 배포는 대개 방문자가 적은 한국 시간 오전 6시쯤에 했습니다. 2024년 10월에는 t4g.small 세 대로 Nomad와 Consul 클러스터를 꾸려 운영 서버를 옮겼는데, 왜 옮겼는지는 기록에 남아 있지 않습니다. 이때 Consul Connect를 다시 써서 무중단 배포도 할 수 있게 된 것으로 보입니다.[32] 이 클러스터는 다음 절에서 이야기할 2025년 5월까지 쓰였습니다.

오케스트레이터 제거

2025년 5월 페미위키는 Nomad를 걷어내고 서버를 t4g.medium 한 대로 줄였습니다. 그때 남긴 이유는 "필요한 건 (지금은 4개인) 컨테이너 몇 개뿐인데 Nomad나 다른 오케스트레이터는 너무 복잡하다"였습니다.[33] 처음에는 docker compose로 컨테이너를 띄웠습니다.[34] compose 설정은 인스턴스가 처음 켜질 때 한 번 실행하는 스크립트(사용자 데이터)에 담겨 있었기 때문에, 컨테이너 설정을 바꾸려면 서버에 직접 들어가거나 인스턴스를 새로 띄워야 했습니다. 2025년 8월부터는 테라폼의 도커 프로바이더로 서버의 도커 데몬에 직접 컨테이너를 만듭니다. 바꾼 이유는 기록에 남아 있지 않지만, 이런 번거로움 때문이었던 것으로 보입니다.[35] 지금은 컨테이너 설정이 바뀌면 다른 인프라 변경과 똑같이 풀 리퀘스트에서 변경 계획(terraform plan)을 확인하고 적용합니다(도커 데몬은 밖에 열지 않고 AWS SSM 포트 포워딩으로 접속합니다).

무중단 배포

오케스트레이터를 걷어내면서 무중단 배포는 다시 할 수 없게 되었습니다.[36] 2026년 9월부터는 같은 서버에서 새 컨테이너를 기존 컨테이너 옆에 먼저 띄우는 방식으로 다시 무중단 배포를 합니다.[37] 배포할 때마다 세대 번호라는 숫자를 하나 올리고, 컨테이너 이름과 포트를 이 숫자로 정합니다. 예를 들어 PHP를 실행하는 php-fpm 컨테이너는 fastcgi-193 다음에 fastcgi-194로 뜹니다. 새 이미지가 나오면 봇이 이 숫자를 올리는 풀 리퀘스트를 엽니다. 테라폼은 원래 기존 리소스를 지운 뒤 새로 만들지만, 순서를 거꾸로 하는 설정(create_before_destroy)을 켜 두었고, 새 컨테이너의 상태 확인이 성공할 때까지 기다린 뒤에 기존 컨테이너를 지웁니다.[38]

php-fpm 컨테이너는 세대 번호가 짝수인지 홀수인지에 따라 9000번과 9001번 포트를 번갈아 씁니다. 지금도 컨테이너는 호스트 네트워크를 쓰지만, 앞뒤 두 세대가 서로 다른 포트를 쓰므로 함께 떠 있을 수 있습니다. 웹 서버인 Caddy는 두 포트를 모두 백엔드로 등록해 두고 1초마다 상태 확인용 PHP 파일을 불러 보므로, 새 컨테이너가 준비되면 곧바로 요청을 나눠 보냅니다.[39] 기존 컨테이너가 종료 신호를 받으면, 컨테이너의 시작 스크립트가 먼저 종료 중임을 알리는 빈 파일을 만들어 상태 확인이 실패하게 합니다. 그러면 Caddy가 더는 요청을 보내지 않고, 스크립트는 5초를 기다린 뒤에야 php-fpm에 종료를 알려 처리 중이던 요청을 마저 끝내게 합니다.[40] php-fpm은 종료하는 동안에도 새 연결을 받았다가 처리하지 못하고 끊어서, 이 단계가 없으면 Caddy가 502 오류를 냅니다.

웹 서버 자신을 바꾸는 일은 조금 더 까다롭습니다. 방문자가 접속하는 443번 포트는 하나뿐이라 새 Caddy와 기존 Caddy가 이 포트를 잠깐 나눠 써야 합니다. 리눅스에는 여러 프로세스가 같은 포트를 함께 열 수 있게 하는 SO_REUSEPORT 옵션이 있고, Caddy는 리눅스에서 포트를 열 때 이 옵션을 켭니다. 다만 새 Caddy가 443번 포트를 열자마자 인증서를 아직 불러오지 못한 채 요청을 받아 0.15초쯤 실패하는 일이 있었습니다. 그래서 컨테이너의 시작 스크립트는 Caddy를 방문자를 받지 않는 임시 설정으로 먼저 띄우고, 내부 포트(8443번)로 대문(메인 페이지)을 HTTPS로 받아 오는 데 성공한 뒤에야 Caddy의 관리 API로 전체 설정을 불러와 443번 포트를 엽니다.[41] 새 Caddy가 준비되면 테라폼이 기존 Caddy를 내리고, 기존 Caddy는 종료 신호를 받으면 처리 중이던 요청을 마저 끝내고 내려갑니다.

페미위키 서버는 그동안 AWS 도쿄 리전에 있었는데, 이렇게 바꾼 뒤인 2026년 9월 26일 서울 리전으로 옮겼습니다. 서울에서 처음 배포할 때 0.5초 간격으로 요청을 보내 보았습니다. 요청 218개가 모두 성공했고, 새 컨테이너가 포트를 넘겨받는 순간의 요청 하나만 5.2초 걸렸습니다(원인은 아직 모릅니다).[42] 다만 0.5초보다 짧은 끊김은 이 측정으로 잡히지 않을 수 있어서, 배포 때마다 1초 미만의 끊김도 없는지는 아직 확인하고 있습니다.[43]

오케스트레이터가 맞지 않는 경우

페미위키가 겪은 일을 바탕으로, 오케스트레이터가 옳은 답이 아닐 수 있는 경우를 짚어 보겠습니다.

먼저 서버가 한두 대이고 컨테이너가 몇 개뿐인 경우입니다. 오케스트레이터의 장점은 여러 서버에 컨테이너를 나눠 띄우고, 서버 하나가 죽으면 다른 서버로 옮겨 띄우는 데 있습니다. 서버가 한 대라면 옮겨 갈 곳이 없으니 이 장점을 쓸 수 없고, 오케스트레이터 자체를 운영하는 수고만 남습니다. 페미위키가 2025년에 Nomad를 걷어낼 때 남긴 이유도 "컨테이너 몇 개에 비해 너무 복잡하다"였습니다.

다음은 AWS의 t 계열처럼 CPU를 가끔 몰아 쓰는 일에 맞춘 작은 인스턴스를 쓰는 경우입니다. 오케스트레이터의 에이전트는 트래픽이 없을 때도 쉬지 않고 돕니다. 2021년 기록을 보면 Nomad 프로세스 혼자서도 CPU를 5%쯤 썼는데, 기준 성능이 20%인 t3a.small에서는 이것만으로 여유의 4분의 1이었습니다.[44] 서비스 메시를 함께 쓰면 프록시도 그만큼 CPU를 더 씁니다.

마지막으로 오케스트레이터에서 바라는 것이 무중단 배포 하나뿐인 경우입니다. 앞에서 본 것처럼 새 컨테이너를 기존 컨테이너 옆에 먼저 띄우고 상태 확인으로 요청을 넘기는 일은 서버 한 대 안에서도 할 수 있습니다. 페미위키는 테라폼의 create_before_destroy, 세대마다 번갈아 쓰는 포트, 웹 서버의 상태 확인으로 충분했습니다.

반대로 서버가 여러 대이고, 서버 하나가 죽어도 사람이 손대지 않고 서비스가 이어져야 하며, 그 복잡함을 감당할 사람이 있다면 오케스트레이터가 맞는 답일 것입니다. 다만 페미위키처럼 수익 없이 운영하는 곳에서는 서버를 늘리는 것부터가 부담입니다. 2021년에도 작은 서버 여러 대로 클러스터를 꾸리는 방안이 나왔지만 비용 때문에 어렵다고 보았습니다.[45]

맺음말

지금 페미위키는 컨테이너를 띄우는 앱 서버 한 대와 데이터베이스 서버 한 대로 운영합니다. 컨테이너가 호스트 네트워크를 쓰므로 방문자 IP도 그대로 보입니다. 배포할 때 1초 미만의 끊김이 남아 있는지는 계속 확인할 예정입니다.

출처

  1. ↑ “femiwiki/nomad README.md (2016년 10월)”. 《GitHub》. 2026년 11월 9일에 확인함. 
  2. ↑ “서버에 존재하나 소스코드에 누락된 이미지 업로드 · femiwiki/nomad”. 《GitHub》. 2026년 11월 9일에 확인함. 
  3. ↑ “femiwiki/docker-mediawiki#68”. 《GitHub》. 2026년 11월 9일에 확인함. 
  4. ↑ “미디어위키 인스턴스 도커 쓰는 새 방식으로 변경 · femiwiki/femiwiki#29”. 《GitHub》. 2026년 11월 9일에 확인함. 
  5. ↑ “Change EC2 Instances type to T3a · femiwiki/femiwiki#87”. 《GitHub》. 2026년 11월 9일에 확인함. 
  6. ↑ “femiwiki/femiwiki#117”. 《GitHub》. 2026년 11월 9일에 확인함. 
  7. ↑ “사용자 IP를 제대로 인식하지 못함 · femiwiki/docker-mediawiki#309”. 《GitHub》. 2026년 11월 9일에 확인함. 
  8. ↑ “Docker Swarm을 Nomad로 대체 · femiwiki/femiwiki#116”. 《GitHub》. 2026년 11월 9일에 확인함. 
  9. ↑ “ec2.tf: Prepare a new k3s instance · femiwiki/infra@159138b”. 《GitHub》. 2026년 11월 9일에 확인함. 
  10. ↑ “femiwiki/femiwiki#116 댓글”. 《GitHub》. 2026년 11월 9일에 확인함. 
  11. ↑ “k3s에 퍼시스턴시 넣기 · femiwiki/femiwiki#161”. 《GitHub》. 2026년 11월 9일에 확인함. 
  12. ↑ “femiwiki/femiwiki#116 댓글”. 《GitHub》. 2026년 11월 9일에 확인함. 
  13. ↑ “femiwiki/femiwiki#116 댓글”. 《GitHub》. 2026년 11월 9일에 확인함. 
  14. ↑ “femiwiki/femiwiki#116 댓글”. 《GitHub》. 2026년 11월 9일에 확인함. 
  15. ↑ “Nomad for Kubernetes practitioners”. 《HashiCorp Developer》 (영어). 2026년 11월 9일에 확인함. 
  16. ↑ “Roblox”. 《HashiCorp》 (영어). 2026년 11월 9일에 확인함. 
  17. ↑ “femiwiki/femiwiki#116 댓글”. 《GitHub》. 2026년 11월 9일에 확인함. 
  18. ↑ “femiwiki/femiwiki#116 댓글”. 《GitHub》. 2026년 11월 9일에 확인함. 
  19. ↑ “femiwiki/femiwiki#116 댓글”. 《GitHub》. 2026년 11월 9일에 확인함. 
  20. ↑ “femiwiki/femiwiki#116 댓글”. 《GitHub》. 2026년 11월 9일에 확인함. 
  21. ↑ “femiwiki/femiwiki#116 댓글”. 《GitHub》. 2026년 11월 9일에 확인함. 
  22. ↑ “Enable swap · lens0021/nomad@58dacd4”. 《GitHub》. 2026년 11월 9일에 확인함. 
  23. ↑ “femiwiki/femiwiki#116 댓글”. 《GitHub》. 2026년 11월 9일에 확인함. 
  24. ↑ “femiwiki/femiwiki#116 댓글”. 《GitHub》. 2026년 11월 9일에 확인함. 
  25. ↑ “femiwiki/femiwiki#253”. 《GitHub》. 2026년 11월 9일에 확인함. 
  26. ↑ “femiwiki/femiwiki#116 댓글”. 《GitHub》. 2026년 11월 9일에 확인함. 
  27. ↑ “femiwiki/femiwiki#116 댓글”. 《GitHub》. 2026년 11월 9일에 확인함. 
  28. ↑ “femiwiki/femiwiki#116 댓글”. 《GitHub》. 2026년 11월 9일에 확인함. 
  29. ↑ “간헐적 서비스 중단 발생 (2021-04-23 -) · femiwiki/femiwiki#249”. 《GitHub》. 2026년 11월 9일에 확인함. 
  30. ↑ “Migrate gp2 volumes to gp3 volumes · femiwiki/infra@11acf90”. 《GitHub》. 2026년 11월 9일에 확인함. 
  31. ↑ “femiwiki/femiwiki#249 댓글”. 《GitHub》. 2026년 11월 9일에 확인함. 
  32. ↑ “aws: Use three nodes (#347) · femiwiki/infra@41a2063”. 《GitHub》. 2026년 11월 9일에 확인함. 
  33. ↑ “femiwiki/femiwiki#404 댓글”. 《GitHub》. 2026년 11월 9일에 확인함. 
  34. ↑ “Use docker-compose for the production · femiwiki/femiwiki#405”. 《GitHub》. 2026년 11월 9일에 확인함. 
  35. ↑ “femiwiki/infra#410”. 《GitHub》. 2026년 11월 9일에 확인함. 
  36. ↑ “femiwiki/femiwiki#419”. 《GitHub》. 2026년 11월 9일에 확인함. 
  37. ↑ “femiwiki/femiwiki#550”. 《GitHub》. 2026년 11월 9일에 확인함. 
  38. ↑ “femiwiki/infra docker/container.tf”. 《GitHub》. 2026년 11월 9일에 확인함. 
  39. ↑ “femiwiki/docker-mediawiki Caddyfile”. 《GitHub》. 2026년 11월 9일에 확인함. 
  40. ↑ “femiwiki/docker-mediawiki run”. 《GitHub》. 2026년 11월 9일에 확인함. 
  41. ↑ “femiwiki/docker-mediawiki caddy-run”. 《GitHub》. 2026년 11월 9일에 확인함. 
  42. ↑ “femiwiki/femiwiki#419 댓글”. 《GitHub》. 2026년 11월 9일에 확인함. 
  43. ↑ “femiwiki/femiwiki#590”. 《GitHub》. 2026년 11월 9일에 확인함. 
  44. ↑ “femiwiki/femiwiki#116 댓글”. 《GitHub》. 2026년 11월 9일에 확인함. 
  45. ↑ “femiwiki/femiwiki#116 댓글”. 《GitHub》. 2026년 11월 9일에 확인함.