1. 멸망의 날이 다가온다

본업에 치이고 이직에 치여 정상적으로 작동하는지 정도만 확인하며 시간을 보내다가 꼬들의 문제 출제가 올해 10월 언제쯤 끝날 거란걸 심정적으로 계속 미뤄두고 있었다. 꼬들 문제는 외국인들의 한국어 자격 시험 준비를 위한 수험용 단어들로 만들었기 때문에, 지금까지는 꽤 고른 난도를 가지고 있었다. 정확히는 2024년 10월 23일, '연습'을 마지막으로 모든 문제가 떨어지고 시스템은 1번 문제부터 다시 풀게 되어 있었다.

 

일단은 문제 출제로 추천받은 단어들을 붙여서 며칠의 시간을 벌었다. '궤도', '들녘', '은닉'이 그랬다. 하지만 급박하게 진행된 이 업데이트에도 문제가 있었다. 예전에도 한 번 일어났던 일이지만, 홈페이지 배포를 한다고 하더라도 브라우저들과 각각의 환경 특성상 새로고침을 해주지 않으면 웹이 최신으로 바뀌지 않고 분기가 일어난다. 안정적으로 수정하려면 적어도 1~2주 뒤의 문제를 수정해야 하는 것이다. 즉 아무리 빨리 문제 리스트를 개선한다고 하더라도 실제로 반영되는 건 일주일 정도 뒤다.

2. 난도는 어떻게?

처음에는 현재 가지고 있는 말뭉치 중에 명사표준국어대사전에 실렸을 경우에는 모두 출제하는 것으로 했다. 순서는 이전과 마찬가지로 무작위로 섞었고, 일일이 표준국어대사전을 확인하여 명사임을 확인했다. 그리고 민감한 의미를 지닌 단어는 눈에 보이는 대로 제거했다. 현재까지의 꼬들은 일반 난도였다면, 대략 2년 넘게 서비스해 왔으니 이젠 난도가 좀 올라도 되지 않을까 생각했다.

 

'세입', '콩테', '착실', '역경', '불씨', '요행', '항년', '샹양', '옹새'까지 9일 간이었다. 반응은... 폭발적이었다. 샹양에서 고점을 찍고 옹새에서는 다들 지친 듯 했다. 심지어 꼬들을 처음 만들었을 때부터 꾸준히 풀어가고 있는 아버지에게도 연락이 왔다. 운영자가 바뀌었다, 중국인 아니냐, 사람들을 실패하게 하려고 일부러 난이도를 조절했다 등등의 이야기도 읽었다.

 

어떤 방향으로 갈지 다시 상당히 고민을 했다. 처음 만들 때 어떤 방향을 생각했는지도 떠올려봤다. 다른 무엇보다도 많은 사람들이 즐겁게 즐겨주었으면 좋겠다는 마음은 그대로다. 좀 더 단어 퍼즐처럼 한국어에 이런 단어도 있었네? 같은 즐거움도 느낄 수 있지 않을까 했는데, 꾸준히 모니터링 해보니 다들 상당히 스트레스를 받고 있는 것으로 보였다. 이리저리 생각해 보고 나서 어렵지 않은 단어로 계속 가기로 했다.

 

(여러 이야기 중, 힘든 하루를 보내고 집에서 이제 꼬들 한 번 풀고 잘까? 하고 틀었다가, 화가 나서 3시까지 잠 못 들었다는 이야기가 가장 마음을 때렸다. 내가 그렇게까지 스트레스를 주고 있다니.)

3. 수제 꼬들을 만들자

어떤 단어가 얼마나 어려운가, 어떤 낱말을 알고 있는 게 상식인가는 완전히 자의적이다. 표준국어대사전을 그대로 차용한다 해도 마찬가지 문제가 일어난다. 술목이나 침장, 희살... 상당히 많은 단어들을 제외해야 한다. 한 달 정도 만 개 가량의 낱말을 다 봤는데 한 번쯤 봄 직한 단어들만 추리니 100개 남짓 남았다. 이대로라면 현재 말뭉치 낱말이 4만 개 정도 남았는데, 400개 정도만 추출될 수도 있겠다. 일 년 정도만 수명 연장이 가능한 것이다.

 

일단 어려운 단어들은 뒤로 미뤄놓았다. 내가 갑자기 서비스를 못 하게 된 시점에서도 최대한 새로운 문제들을 많이 풀고 나서 첫 문제로 돌아갔으면 하는 마음이다. 그런데 이 글을 쓰다 보니, 그 문제들을 남겨놔야 할지 지워버려야 할지 혼란스러워지기 시작한다. 그냥 계속 반복되도록 하는게 더 나을까? 전체의 길이가 3년에서 4년 정도 걸리게 될텐데 그 정도면 첫 단어로 돌아가도 되는 걸까? 어찌 되었든 당장의 목표는 남은 4만 개 단어 중 눈에 한 번쯤은 익은 단어들을 빼내어 검증하는 것이다. 이걸 끝내면 1년 정도는 더 즐길 수 있을 것이다.

 

현재는 수제 꼬들이 계속 출제되고 있는데 아직도 난이도 조절이 잘 안 되는지 불신의 눈초리가 느껴진다. 특히 어제 밑살 같은 경우, 뜻풀이 1번만 보고, 평소 정육식당 등에서 써온 용례들을 생각하여 문제로 출제했는데 2번 뜻이 있단 걸 알고 당혹스러웠다. 성적 폭력에 대한 단어들은 최대한 제외해 오고 있기 때문에 이번 경우 확실히 실수라고 생각했다. 기분 나쁘셨던 분들이 있다면 이 자리를 빌려 사과드립니다.

 

(어떤 단어까지 문제를 내도 되는지도 고민이 된다. 예를 들어 살해가 나와 고민을 많이했는데 출제 했는지 안 했는지 가물가물하다.)

4. 기타 보수를 하자

꼬들을 만들고 나서 LLM도 많은 발전을 해서 몇몇 부분을 고칠 때는 많은 도움을 받았다. 특히 지금까지 휴대전화를 바꾸거나, 지금까지 써왔던 브라우져 환경을 바꿀 때 연속 맞춤 정보를 못 가져가던 분들을 위해 전적 복사 기능을 개발했다. 많은 분이 사용해주셨으면 좋겠다.

 

그리고 요즘 트위터에서 블루스카이로 이전하는 분들이 많아, 블루스카이에서도 모니터링을 시작했는데, 꼬들의 흰 네모가 깨져 나오는 것이었다. 살펴보니 흰 네모에는 크기별로 3가지 종류가 있고 그중 가장 큰 네모는 블루스카이 환경에서 다른 방식으로 나온다. 꼬오오오오들도 잊지 않고 수정해 주었고, 이제는 많은 분들이 정상적으로 잘 나온다. (그런데 가끔 잘 안 나오는 분들을 보면, 역시 브라우저 상황에서의 배포가 정말 늦구나 싶다.)

5. 나가며

우여곡절이 있었지만, 앞으로도 많은 분들이 즐겁게 즐겨주셨으면 좋겠다. 

'공개' 카테고리의 다른 글

"꼬들"을 운영하면서.  (21) 2022.02.20
"꼬들"을 만들기까지.  (15) 2022.02.05

컨테이너 번호 확인을 해야 하는데 찾아 나오는 C# 소스 코드가 에러가 있어서 수정해보았다. 방식은 다음(링크)을 참조했다.

 

        private bool Cntrnumb_Chk(string conNumber)
        {
        	//11자리 그대로 들어와야 한다.
            if (conNumber.Equals(""))
                return false;
            int nChk = 0;
            int nBcd = 0;
            int nHap = 0;
            string sChk = "";
            conNumber = conNumber.Trim();
            for (int i = 0; i < conNumber.Length - 1; i++)
            {
                nBcd *= 2;
                if (nBcd == 0)
                    nBcd = 1;
                sChk = conNumber.Substring(i, 1);
                switch (sChk)
                {
                    case "A": nChk = 10; break;
                    case "B": nChk = 12; break;
                    case "C": nChk = 13; break;
                    case "D": nChk = 14; break;
                    case "E": nChk = 15; break;
                    case "F": nChk = 16; break;
                    case "G": nChk = 17; break;
                    case "H": nChk = 18; break;
                    case "I": nChk = 19; break;
                    case "J": nChk = 20; break;
                    case "K": nChk = 21; break;
                    case "L": nChk = 23; break;
                    case "M": nChk = 24; break;
                    case "N": nChk = 25; break;
                    case "O": nChk = 26; break;
                    case "P": nChk = 27; break;
                    case "Q": nChk = 28; break;
                    case "R": nChk = 29; break;
                    case "S": nChk = 30; break;
                    case "T": nChk = 31; break;
                    case "U": nChk = 32; break;
                    case "V": nChk = 34; break;
                    case "W": nChk = 35; break;
                    case "X": nChk = 36; break;
                    case "Y": nChk = 37; break;
                    case "Z": nChk = 38; break;
                    case "1": nChk = 1; break;
                    case "2": nChk = 2; break;
                    case "3": nChk = 3; break;
                    case "4": nChk = 4; break;
                    case "5": nChk = 5; break;
                    case "6": nChk = 6; break;
                    case "7": nChk = 7; break;
                    case "8": nChk = 8; break;
                    case "9": nChk = 9; break;
                    default: nChk = 0; break;
                }
                nChk *= nBcd;
                nHap += nChk;
            }
            nChk = nHap / 11;
            nChk *= 11;
            nChk = nHap - nChk;
            if (nChk == 10)
                nChk = 0;
            if (Convert.ToInt16(conNumber.Substring(conNumber.Length - 1, 1)) == nChk)
                return true;
            else
                return false;
        }

'C#' 카테고리의 다른 글

DataTable을 Select하기.  (0) 2020.03.23

1. 시작하며

이전 글을 쓴 지 2주 남짓 지났다. 서비스를 운영한다는 건 문제와 해결이 꼬리에 꼬리를 물고 이어진다는 사실을 많이 느꼈다. 해결 하나는 또 다른 문제 하나를 물고 온다. 매일 밤 이용자들의 반응을 보다 보면 추가하고 싶거나 수정하고 싶은 것들이 떠오르기도 했다. 두서없이 개발하다 보니 이번에는 소재별로 글을 정리해 보았다. 

2. 몰려오는 트래픽 물결

개인적으로 이용자들의 정보 수집에 부정적인 관점을 가지고 있다. 장기적으로는 이용자들이 만들어낸 정보의 값어치에 적절한 보상이 필요하다고 생각한다. 하지만 서비스를 운영해보자, 정보를 수집하지 않는 한 물리적으로 관측이 어려운 웹 서비스가 어떤 방식으로 사용되고 있는지 파악할 길이 없었다. 노점상에서 붕어빵을 판다고 해도, 지나가는 손님들과 무엇을 사는지, 얼마나 사는지, 어떤 분들이 사는지를 모르려야 모를 수가 없는데, 구글 애널리틱스를 깔기 전까지는 오직 "꼬들"의 답안지가 어디에 얼마나 올라오는지 확인하는 정도뿐이었다.

 

게다가 트래픽 내역을 확인하자...

 

생각했던 것보다 엄청나게 많은 분들이 즐겨주셨다. 하지만 이 정도 트래픽량을 보니 Github blog의 트래픽 허용 용량이 얼마 정도 되는가 궁금해졌다. ( https://docs.github.com/en/pages/getting-started-with-github-pages/about-github-pages ) 찾아보니

  • GitHub Pages sites have a soft bandwidth limit of 100GB per month.

라는 게 아닌가? 예전 소소한 설치형 블로그 운영할 때는 1GB/월로도 별 신경 안 써도 되었지만, 현재 이렇게 많은 분들이 하고 계신데 갑자기 트래픽 제한으로 연결이 끊긴다면? 하고 고민이 시작되었다. 그리고 GitHub에서는 현재 트래픽량이 얼마나 남았는지 등을 확인할 수 있는 영역도 없기 때문에, 이후 하루하루 실시간 이용자 수가 12시마다 쭉 올라갈 때마다 보이지 않는 시한폭탄의 심지가 바짝바짝 타들어가고 있는 기분이 들었다.

 

일단은 마찬가지로 정적 홈페이지 트래픽을 무료로 월간 100GB를 지원하는 Vercel( https://vercel.com/ )과 Netifity( https://www.netlify.com/ )에 바로 가입하여, GitHub 내역을 Deploy 해 복제 정적 웹사이트들을 만들었다. ( 이렇게 간단하게 웹사이트 복제를 할 수 있다니! ) 어디 공지할 곳도 없으니, 트위터에 멘션으로 공지하였는데 아무래도 노출이 잘 될 것 같지 않았다. 또한 이렇게 만들어놨다 하더라도 원 GitHub Blog에 트래픽 제한이 걸리면 리디렉션 할 홈페이지조차 닫히게 된다는 아이러니가 실감 났다.

 

게다가 상술했듯, GitHub에서는 트래픽 사용량을 보여주지 않으니, 이 당시 달 초순에는 GitHub Blog , 중순에는 Vercel, 말에는 Netifty로 돌려가며 리디렉션을 할까 생각하고 있었다. ( 지금 생각해보면 그럴 때마다 게임 로컬 스토리지의 통계가 날아간다.... ) 소소하게 Vercel과 Netlify의 초기 주소를 다들 익숙하라고 원 주소를 살려 github-belorin-io로 서브도메인 이름을 지었다가 크롬에 차단되어 매우 놀라기도 했다. 주소 이름을 지을 때는 피싱사이트처럼 보이지 말자.

 

이 화면을 봤을 때 얼마나 놀랐는지.

3. 무한한 트래픽과 도메인 구매

당장 서버가 3개가 되자 먼저 생각나는 것은 도메인이었다. 세 개의 서버를 서로 리디렉션하며 갈아치우는 건 말도 안 되는 일이고, 세 개 다 닫혔을 때 어디론가 공지로 리디렉션 할 지점이 필요했다. 도메인을 고르는데도 생각했던 것보다 고민이 되었다. korld.le일지, kkordle일지, .net이나 .com일지. kordle.net도 고민해보았으나 battle.net과 어감이 비슷해서 이상한 기분이 들었다. 그러다 모양으로 보기엔 kordle.kr이 가장 예뻐 보여서 결정을 하고 GoDaddy( https://kr.godaddy.com/ )에서 구매를 하려고 하는데...

역순, 선순, 도로명 주소, 옛 주소 등등을 이것저것 입력해도 저 유효성 검사를 통과하지 못했다. 이걸 통과하려고 시도하느라 이틀이 걸렸으나 결국 다른 지인 분의 추천으로 호스팅케이알( https://www.hosting.kr/ )에서 쉽고 간단하게 구매하게 된다. 아무래도 .kr을 구매하려면 추가적인 검증이 필요한 상태여서 들어가는 정보인가 본데, 다른 분들은 어떻게 입력하고 구매했는지 궁금하다.

 

이 와중에 상황을 바꿀 트윗 하나가 와 있었는데...

Cloudfare Pages( https://www.cloudflare.com )를 추천해주는 @yechanism_님의 트윗이었다. 무제한 무료라는 말에 당장 가입하고 위의 두 사이트에서 익숙해진 Deploy를 구현하는데, 여기는 Create React App 등에 대해 자동 빌드 및 배포가 구성되어 있었다. 즉 빌드 이전의 코드를 올려두면 자동으로 알아서 빌드해준다! GitHub 원격 저장소에 Push만 하면 바로! ( 무엇을 선택할지 몰라서 Create React App을 선택했으나 React Static과 어떤 차이가 있는지 모르겠다. )

프레임 워크가 이렇게나 많다!

잘 올라가서 돌아가는지 확인한 후에, Kordle.Kr로 포워딩을 걸어주고는 한동안 지쳐서 쉬었다. ( 정적 포워딩을 걸자 아직 HTTPS가 아닌 주소라 바로 Clipboard API가 작동하지 않아 어쩔 수 없이 동적 포워딩으로 변경했다. 그렇게 해놓고 나니 이게 무슨 의미가 있나 싶고, 이용자들은 Pages의 주소를 복사해가기 시작했다. )

4. 어디에서 와서 어디로 가는가?

이렇게 되자 구글 애널리틱스의 리퍼러 대부분은 Kordle.Kr에서 들어오게 되었다. 그렇다면 Kordle.Kr로 들어오는 사람들은 어디에서 오는 건가? 마치 빌딩 로비에 앉아, 입구에서 들어오는 사람들을 보며 "다들 입구로 들어오는군"하는 꼴이었다. 게다가 문제점은 또 있다. 앞으로 개발하고 싶은 아이템은 주소로 쿼리 스트링을 통해서 정보를 받아야 하는데 이래서는 Cloudfare Pages의 주소로 리디렉션 되면서 쿼리 스트링이 날아가는 문제가 생겼다.

 

그래서 SSL을 설정하는데 지금까지 개념을 전혀 잘못 알고 있었다는 사실을 알게 된다. 암호 키나 비대칭키 개념은 알고 있었으나 정확히 인증서가 어디에 어떻게 작동하는지는 모르고 있었던 것이다. 지금까지는 특정 도메인 주소에 인증서가 삽입되고, 그 인증서가 삽입된 주소와 연결되는 서버 모두에게 효력이 발생되는지 알고 있었다. (... 웹 브라우저의 도메인 주소 옆에 자물쇠가 있으니까...)

 

https://www.whatsmydns.net/

하지만 알고 보니 도메인이라는 가면을 쓴 서버가 그 도메인의 서버가 맞는지 확인하는 용도의 인증서였고, 결국 인증서는 서버에 부착되어 도메인 주소의 DNS로 연결되는 것이었다. (아직도 개념을 명확히 이해한 것 같지 않다.) 어찌 되었든간, 또다시 Cloudflare의 도움을 받아 호스팅케이알의 DNS 주소를 Cloudflare 것으로 변경하고, 중간 인증서를 획득하여 이제 Kordle.Kr 옆에도 자물쇠가 달리게 되었다!  ( 네임서버 변경 과정에서 한국 네임서버 변경이 늦어 접속 장애가 발생했다. Dns propagation을 확인할 수 있는 몇 사이트에서 확인해 보았다. )

 

이렇게 같은 주소로 같은 서비스를 제공하고자 하는 과정에서 주소를 기반으로 구성된 로컬 스토리지가 몇 번이나 리셋되었다. 어떻게 손을 쓸 수 없는 상황에서 반복되다 보니 안타까움과 아쉬움이 남는다. 그리고 결과지에 주소를 남길지 말지도 매 번 고민이 돼서 이렇게도 저렇게도 해보았다. 개인적으로는 주소를 어디엔가 붙어 포스팅할 때 자동으로 섬네일이 구성되는 게 지저분하다 느끼는 편인데, 주소를 빼보았더니 일부러 찾아 붙이는 분들도 있어 그렇게도 받아들일 수 있구나 싶었다. 현재로서는 결과 복사 버튼을 링크 있는 버전과 없는 버전 2개로 늘릴지 고민 중이다.

5. 문제를 누구나 출제하도록 해보자!

주소도 고정되었으니, 맘 놓고 주소로 정보를 받을 수 있게 되어 추가 개발을 해보았다. 일단 정보는 간단하게 Base64로 변환하여 주고받고 기본 컴포넌트와 함수들을 이용하여 구성하였다. 생각했던 것보다 빠르게 만들고 배포할 수 있었다. 어느 정도 React의 구성이나 Typesrcipt의 운용을 이해하게 되었다. ( 역시 그냥 해 보는 게 좋다. )

 

개발 중간중간과 SSL 수정, DNS 변경 등 여러 부분에서 S의 도움을 많이 받았다. 특히 문제 출제 폼 구성과 도메인 서버 인증서 획득은 S에게 큰 도움을 받았다. 서로 번갈아 코딩 짜는 걸 공유하며 진행해보니 여러모로 재미가 있었다.

6. 나가며

이제는 가만히 놔두어도 2 ~ 3년 정도는 알아서 굴러갈 수 있는 서비스가 되어 마음은 편해졌다. 현재로서는 안정적으로 길게 군더더기 없는 깔끔함을 계속 유지하고 싶다. 앞으로 시간이 흘러 조금씩 찾아오는 사람이 줄어들다, 몇 명 들어오지 않아도 계속 그 자리에 꾸준히 기다리는 공간이 되고 싶다.

 

P. S.

사람들이 입력하지만 검증 단어에는 없는 단어들을 수집해서 검증 단어 풀을 늘려보려고 수집을 시작해보았는데,

 

뭐든 생각대로만은 되지 않는다. ( 48번째 정답, ㄱㅜㅇㅜㅓㄹ )

 

P. S. 2.

매일 밤 12시에 새로운 문제가 나오니, 12시 직전까지 새로운 기능을 넣어 매일매일 배포하게 되는 좋은 효과가 있는 반면, 다음날 아침에 봐도 무방한데도 새벽 한 시 두 시까지 잠 못 들고 사람들의 반응을 살피다 다음날 산 좀비로 회사 일을 하게 되는 악 효과도 있다.

'공개' 카테고리의 다른 글

"꼬들"을 보수하면서.  (4) 2024.11.30
"꼬들"을 만들기까지.  (15) 2022.02.05

+ Recent posts