늘모자란, 개발

늘모자란, 개발


집 구조를 좀 바꿔볼까 생각하던 찰나에 옛날에 샀던 블루투스 스피커인 sp2가 붕뜨게 되었다
그대로 놀리면 좀 아까워서 이걸 PC에 연결해서 2개의 스피커가 동시에 재생되게 할 순없나? 생각했다. 

좀 찾아보니 스테레오믹스로 기본장치/기본통신장치로 나누어 동시에 재생할 수 있다는걸 알게 되었으나 내 사운드카드는 여의치 않았다.

그래서 해본것이 보이스미터였다.
보이스 미터로 하드웨어 출력 1, 출력 2를 잡아주고, 보이스미터 가상 출력으로 재생시키면 깔끔하게 출력되는걸 확인했다.
심지어는 블루투스와 유선이다보니 싱크가 좀 맞지 않는 부분도 보이스미터로 조율할 수 있었다.

그러나..
스피커가 두개이다보니 각각의 볼륨 조절을 따로 해야했다. 보이스미터 input의 소리를 올린다고 조정이 되는게 아니고 각 스피커의 데시벨을 따로 조절해야하는 느낌..

즉 음소거도 한번에 되지 않는것이고 이래저래 불편함이 초래될 것 같아 하드웨어적 방법이 없나 찾아보고 있었는데,
광출력도 분배가 된다는걸 알게 되었다... 세상엔 없는게 없구나

내가 DAC나 AUX같은걸 쓰는게 아니고 마침 광출력을 쓰고 있던 찰나에 sp2도 광출력을 입력을 지원했기때문에 알아보았고..
광출력 분배기를 사서 연결하니 잘 나온다.

사운드카드에서 좌/중앙/우 로 설정해주었는데 체감?은 솔직히 잘 모르겠다.
내 PC세팅 특성이 스피커가 공중에 떠있는게 좀 아쉬웠어서 아래쪽에 배치해본건데 이제 빈틈없이 나오는 그런 기분적인 기분말고는 막 엄청 좋아진것 같진않다. 그래도 놀리는 기기 없이 다 쓸수있으니 한잔해...
2024/09/17 13:44 2024/09/17 13:44
저는 집에 Nest 스피커 9대를 배치해 두고, 주로 크롬캐스트를 통해 음악을 즐깁니다. 그러던 중, Nest Audio도 훌륭하지만, 진정한 오디오 명가에서 제작한 스피커를 사용해보는 건 어떨까 하는 생각이 들었습니다. Geneva나 Bang & Olufsen 같은 고급 브랜드도 고려했지만, 고가의 라인업은 다소 사치스럽게 느껴졌고, 결국 Marshall Stanmore 3으로 적당히 타협하게 되었습니다.


그러나, Stanmore 2, 3, 아니, Marshall 스피커에는 미처 알지 못했던 치명적인 단점이 있었습니다. 이는 사기 전에는 거의 알 수 없는 네트워크 스탠바이 모드, 일명 절전 모드라는 불편한 기능입니다.


Marshall 스피커는 10분간 사용하지 않거나 입력이 없을 경우 자동으로 절전 모드로 진입합니다. 이 절전 모드가 활성화되면 연결된 모든 기기의 연결이 끊어지며, 다시 재생하려면 스피커와의 연결을 다시 설정해야 합니다. 이 과정은 자동으로 이루어지지 않으며, 볼륨 버튼을 건드리거나 전원을 껐다 켜는 등의 수동 작업을 해야 스피커가 깨어납니다.


저도 Nest Mini의 기본 스피커를 Stanmore 3으로 변경했지만, 자꾸 기본 스피커로 돌아가는 문제가 발생해 스트레스를 많이 받았습니다.


왜 이런 중요한 단점을 사전에 알려주는 사람이 없었을까요? 아마 그들 역시 저처럼 구매 후에야 깨달았을 가능성이 큽니다. 그리고 이제 저도 이 경험을 겪었으니, 다른 사람도 같은 문제를 겪으리라 생각했는지도 모릅니다.


앞서 언급한 문제를 해결하는 방법은 의외로 단순합니다. 10분 내에 오디오 신호를 계속해서 보내는 것입니다. 이를 위해 컴퓨터가 필요하지만, 사실 이 방식은 '배보다 배꼽이 더 큰' 해결책처럼 느껴지기도 합니다. 그래도 남는 노트북을 Wake-up 머신으로 활용할 수밖에 없습니다.


이를 위한 유용한 레포지토리는 다음과 같습니다:


https://gitlab.com/baiyibai/bybs-knowledge-base/-/tree/main/projects/keep_alive_audio
https://github.com/TheDarkTrumpet/marshall-acton-3-keepalive


이 레포지토리들의 핵심은, 사람이 들을 수 없는 주파수를 0.5초간 재생하여 스피커의 연결을 유지하는 것입니다. 제가 테스트한 결과, Stanmore는 멀티 페어링을 지원하기 때문에 여러 기기와 동시에 연결이 가능합니다. 그러나 3개 이상의 기기와 연결 시 문제가 발생하였습니다. 저는 Nest Mini와 한 대의 연결을 유지한 상태에서, 나머지 하나의 연결을 통해 지속적으로 신호를 보내는 방법으로 문제를 해결했습니다. 결과적으로 연결이 끊어지지 않았습니다.


우려했던 부분은, 이미 다른 기기에서 음악이 재생 중일 때 이 스크립트가 동작하면 음악이 끊길까 하는 점이었습니다. 그러나 다행히도 Marshall의 이상한 동작 덕분에 그런 일은 발생하지 않았습니다. 예를 들어, 기기 A에서 음악이 재생 중일 때, B에서 재생을 시작하면 일반적인 스피커는 B의 재생을 우선시해야 하지만, Marshall은 A의 재생을 유지하고 B를 무시하는 것처럼 보였습니다.


저는 평소 컴퓨터를 끄지 않고 사용하는 편이라 이 과정이 크게 불편하지 않았지만, 에너지 절약이라는 이유로 사용자에게 이런 제약을 강요하는 것은 다소 불쾌했습니다. 특히 Stanmore 1이나 Acton 1 모델에는 절전 모드로 들어가지 않게 하는 물리적 버튼이 있었다고 들었는데, 이를 일부러 제거한 점은 이해하기 어렵습니다.


그럼에도 불구하고, 이미 구매했으니 어쩔 수 없죠.
2024/09/12 01:25 2024/09/12 01:25
https://github.com/SergeyPirogov/webdriver_manager/issues/670

[WinError 193] %1은(는) 올바른 Win32 응용 프로그램이 아닙니다

깃헙 이슈로도 등록되어있다.
chromedriver.exe 이나 chromdriver 를 바라보아야 하는데 drvier.json 에 THIRD_PARTY_NOTICES.chromedriver 가 기재되면서 크롬드라이버가 동작하지 않고 그저 다운로드만 수행한다
고치려면...

https://getwebdriver.com/chromedriver#stable에서 64비트를 받아서 하기 경로에 덮씌우고, chromdriver.exe 나 chromdriver를 THIRD_PARTY_NOTICES.chromedriver로 이름 변경해주어야한다.

{
    "win64_chromedriver_127.0.6533.100_for_127.0.6533.100": {
        "timestamp": "13/08/2024",
        "binary_path": "C:\\Users\\admin\\.wdm\\drivers\\chromedriver\\win64\\127.0.6533.100\\chromedriver-win32/THIRD_PARTY_NOTICES.chromedriver"
    },
    "win64_chromedriver_127.0.6533.99_for_127.0.6533": {
        "timestamp": "13/08/2024",
        "binary_path": "C:\\Users\\admin\\.wdm\\drivers\\chromedriver\\win64\\127.0.6533.99\\chromedriver-win32/chromedriver.exe"
    }
}

코드로 처리하려면 이렇게 해야함
 
chrome_path = ChromeDriverManager().install()
 if "THIRD_PARTY_NOTICES.chromedriver" in chrome_path:     
chrome_path = chrome_path.replace("THIRD_PARTY_NOTICES.chromedriver", "chromedriver")
 

2024/08/14 00:31 2024/08/14 00:31

시작하며

싴갤러스가 햇수로 올해로 10년, 그간 싴갤러스를 되돌아보고 정리한적은 없는것 같아요. 이깟게 뭔지.. 하는 생각이지만, 오랜세월 함께 해왔는데 한번은 정리의 시간이 필요하지 않나해서 글을 작성하게 되었습니다.
기술적인 얘기도 좀 적을거라 글이 재미없고 길어질것 같은데, 소고(小考)가 아닌, 아주아주길어질것만 같은 기분이 듭니다.

배경 - 늘모봇

정확히 2008년, 늘모봇이라는 hanirc 내에서 서비스를 시작하면서 일은 시작되었습니다.
07년부터 오게임이라는 게임의 정보 스크립트를 제작하고 있었는데, 많은 이들에게 더 다양한 서비스를 제공할 수 있으면 어떨까? 하는 생각에 탄생한 늘모봇 서비스.
퀴즈라는 컨텐츠로 큰 성공을 거뒀고, 이런말을 스스로 하긴 부끄럽지만 irc를 대표하는 봇 중 하나였다고 생각합니다.




늘모봇은 mIRC라는 윈도우 기반 IRC 클라이언의 자체 언어인 msl(mirc-script language)로 제작되었습니다.
사실 이 클라이언트를 이용해 봇을 제작하는 사람은 아무도 없습니다. 왜냐면, 윈도우 기반의 프로그램이기때문에 더미 메모리가 너무 많고, 시스템 구조가 불편하기 때문입니다. 또한, 한개의 IP에서는 2개까지밖에 접속할 수 없다는 제약이 존재하기때문에 배포할때도 일일히 실행해야 된다는 점도 한몫합니다. (실제로, 늘모봇'만' 돌리기 위해 8대의 VM을 사용했습니다. 자원낭비, 과대포장 갑...)

헌데 왜 이런 봇을 만들었느냐? 당시엔 할줄아는게 너무 없었기때문입니다. C를 하긴했는데 소켓은 모르고, 소켓을 하자니 통신도 모르고..
다 생각안하고 그냥 덤벼들자니 IRC에 존재하는 raw event들을 일일히 처리하기가 더 귀찮았습니다. 그래서, 이미 다 구현되어 있는 mIRC로 부딪혀 봤던 것 같습니다. mIRC로 할수있는걸론 거의 극한까지 했다고 생각합니다. 혼자한건 아니고, 유카리코라는 친구와 함께 구현했습니다. 봇 버전관리까지 전부 싹다 msl로 짰었는데 어우...

너무 서론이 길어지고 있는데, 여튼 퀴즈라는 컨텐츠를 만들때, msl의 기본 I/O 단위인 ini를 사용해 사용자 랭킹을 구현했습니다.
그러자 두가지 이슈가 발생했습니다.

1. 봇 클라이언트들이 자체(로컬) ini를 사용하니, 랭킹 및 문제 동기화가 되지 않는다.
2. 트랜잭션 개념이 존재하지 않으니, 랭킹을 읽거나 동시에 새로 쓰는 상황이 오면 파일이 크래시가 나며 모두 사라진다.
3. 모든 봇이 동기화된 랭킹을 사용하면서 안정화를 꾀할순 없을까?

그래서 어떻게 했느냐? 우선 무작정 도움을 요청했습니다.
ac18rt 라는 분이 처음에는 perl 을 이용한 cgi스크립트로 처리하게 해주셨었습니다. 그래서 봇들의 랭킹 동기화가 이루어졌습니다
하지만, 웹에 올렸더라도 결국 txt기반으로 랭킹을 기록하다보니 I/O에 의해 랭킹이 다 날아가는 이슈가 반복되었습니다.

결국은, penguin이 PHP-MYSQL을 이용한 웹 + DB연동을 진행하게 되었고, 제가 유지보수를 담당하게 되면서 웹을 공부하게 되었습니다.
당연히 트랜잭션같은게 없는 msl에서 하던 고민을 웹에서 구현하면 고려하지도 않아도 되서 안정성이나 기술 난이도나 웹쪽으로 점점 무게가 실리게 되었죠. (대신 무료 호스팅에서 얻을 수 있는 무료트래픽이 부족해 여러번 이사를 가야만 했다는... 건 가슴 깊숙히 묻어둡시다)
결과적으로 봇의 후반엔 거의 대부분의 기능을 웹으로 포팅하게 됩니다

배경 - 마비노기

늘모봇을 제작하면서 웹을 깨작이고 있던 와중에, 거짓말 같이 게임을 같이 했던 길드원들이 접은걸 펴고 한날 한시에 모이게 됩니다.
길드원들은 마비노기의 레이드라는 컨텐츠에 매우 주력하고 있었고, 성애가 시간표를 만드는 일을 담당하고 있었습니다. (류트한정!)
첨) 쿠쿠타이머라는 웹페이지에서는 하프만 지원하고 있었고, 임시점검등의 시간지연에 제대로 대응하지 못하는 이슈가 있었기때문에 일일히 수동으로 시간 계산 노가다를 하고 있었습니다

당시 저는 웹을 배우고 있었고, 길드원인 성애에게 건의했습니다.
가장 빠른 시간내 출현하는 레이드를 볼 수 있고, 레이드 몹 별로 필터링을 해서 볼 수 있으면 좋겠다는 아이디어를 제시했죠.
그리고 성애가 ok함으로서 2011년 7월, 어느 여름날 싴갤러스 프로젝트가 시작 되었습니다. 결국 소수인원을 위해 시작한...


왜 싴갤러스였느냐? 시크서버는 오래된 얘기긴한데..
제가 마비노기 갤러리(마갤)의 고정닉으로 활동하고 있었기 때문입니다.(현재도 고정닉 늘모는 제가 맞습니다)

레이아웃을 보시면 알겠지만 조악 그 자체입니다. 레이아웃은 정말 말할 필요도 없고, 투데이는 게임어바웃 의존도 100%.
자게는 아마 제로보드였던것 같고, 그나마 다음 서버상태에 좀 공을 들였습니다.

이땐 정말.. 보정이고 뭐고 서버에서 오는 반응 그대로 표시했기때문에 신용자체가 없었습니다.
그래도 언젠가는, 레이드를 자동화할 수 있지 않을까 하는 마음에 이것저것 알아보고 열심히 했었죠.. (웹 지식은 정말 제로에 가까웠습니다)
하지만 메뉴들을 보시면 지금 유저분들이 많이들 사용하시는 주요기능들은 하나도 없죠. 

첨1) 당시 레이드 계산은 공식이 있었기 때문에 정확한 서버 계산이 필요시 되었습니다.
첨2) 처음에는 사이트 대부분 길드원들과 유틸리티란의 언패킹 유틸리티를 공유하는데 쓰였습니다. (뭐가 있을지 궁금해하던 분들이 있었을지도..)

시간이 흐르며

가닥을 잡고 앞으로 나아가고 있던 와중에 마비노기 타임즈 TIP란에 글이 하나 올라왔습니다. 로컬로 뿔피리를 저장할 수 있다는 프로그램이었는데, 신기해하며 사용해보고 있는 와중에 이건 도대체 어떻게 하는걸까란 생각에 공부를 시작했고, 아주 간단히 흉내를 내서 csv형태로 저장하게 만들 수 있었습니다. 해당 파일을 msl을 이용해 csv를 서버에 업로드함과 동시에, csv파일을 지우도록 로컬을 구성하고, 서버에서는 오픈소스를 이용해 csv를 파싱후 DB에 저장하도록 했습니다. 

이 작업을 실시간으로 할 수 없었기 때문에, 10분의 텀을 두고 처리하도록 했습니다. 기억하실진 모르겠지만 갱신 10분텀은 이 때문에 발생했었습니다. 그러다가 패킷에 대한 지식이 많이 없던 저는 밥도 안먹고(--) 이틀동안 패킷공부를 하여 지금 시스템의 근간이 되는 프로그램을 만들 수 있었습니다. (이 과정에서  뿔피리가 실시간이 되었습니다. 현재는 더 많이 개선되었습니다.)


여전히 조악하죠? 이름도 tRader였는데 당시엔 ~러 어투가 유행이어서 일부러 뿔피리러라고 붙였는데 인기가 있어서 이름은 유지했던 것 같습니다. 익숙한 이름도 제법 있군요. 공부한걸 응용해서 던배른 와쳐를 만들고, 이때부터 생긴걸 의식해서 레이아웃을 바꾸고 그랬습니다. 다른 기능은 제공하지 않는 타갤러스도 이때 부터였습니다.(이때쯤엔 룬다,골렘, 모리안 서버도 서비스했습니다. 아래는 타갤러스 화면)




요거는 모바일 싴갤러스입니다. 주소도 다르게 뒤에 /m/ 으로 했는데 그땐 그게 대세였죠



레이드도 이때쯤엔 공부한걸 기반으로 완벽히 시간 계산을 하기 시작했습니다. 위 이미지는 싴갤러스 v3 때인데 이 레이아웃을 쓰기 시작한 시점부터는 더 이상 성애의 시간표는 필요 없을정도로 계산을 자동화 하는데까지 성공했습니다. 되도않는 웹표준이라고 마크도 붙여놨군요.
그리고 이제 따로 올리진 않겠지만 수야의꽃을 꼬드겨 블로그에서 개선된 지염도서관을 만들었고, 특별조나 음벞시뮬 같은 큰 기능들을 넣어가며 공부를 하고 동시에 저 스스로도 성장하는 계기가 된 것 같습니다. 가끔은 신기능이 되게 느린데 이것저것 꼼꼼히 검토하느라 그렇습니다.. (게으름 필때가 더 많습니다마는..)

서버 구조

싴갤러스의 시작은 PHP-MYSQL 구조로 시작되었습니다. 웹 구조는 현재도 비슷하고요. 당시엔 코딩 능력도 많이 부족했기때문에 배치 작업들도 전부 PHP로 만들었습니다. cron을 이용해서 php를 실행하게 .. 심지언 php 커맨드를 쓰는게 아니라 wget으로 호출시켰습니다.. 이후 배치 작업은 쉘파일이나, python 과 같은 언어로 대체되었습니다. (서버체커의 경우 아주 대대적인 성능개선을 수행했습니다. 티는 안나지만...)
모바일 푸시나 웹푸시를 담당하는 nodejs 서버가 두개있고, 별개의 다른 로직을 처리하기 위한 3개의 docker 컨테이너가 있습니다.

맨땅으로 시작을 했던거라 DB 최적화나 구조등에 대해 고려하지 않고 만들었기때문에 성능이슈가 빈번했고, 성능뿐 아니라 안정성에도 많은 장애가 있었습니다. 이를 해소하기 위해서 mysql 은 이중화 (replication) 되었고, 전체 db 형상들은 docker 컨테이너로 관리하고 있습니다. 적고보니 컨테이너가 꽤 많네요. 그외에도 c 및 c# 같은 언어들도 많이 사용되었습니다. 처음에 비하면 꽤 많이 복잡해졌습니다. 사이트 덩치가 커지면 커질 수록 처음보는 장애들을 마주했고 커널패닉이 떠서 자료가 전소되기 직전의 위기도 있었습니다.

호스팅을 받아서 쫓겨나기도 하고 이리저리 옮겨다닌 날도 있었으나 지금은 2대의 물리 서버에서 동작하고 있습니다. IDC도 다름.. (출세함)

여러가지 시도를 했습니다.

페이스북을 운영하기도 했고, 옐로우 아이디(카카오톡 + 채널), 트위터, 문의채널, 무엇이든 말해요 등등 여러 유저분들의 소리를 듣고자 했는데 사실 잘 되진 않았습니다. SNS 운영은 아무나 하는게 아닌것 같아요. 아직도 활성화되지 못했고 ... 기술적으로 궁금한걸 많이 해본것 같습니다. 요즘은 잘 안하지만 당시에 핫했던 Logstash - MYSQL bridge를 통핸 Elastic Search 를 연동까지 거의 다하고 취소했던 기억같은...  데이터 메세지들을 처리하기 위한 kafka 검토등... 등등......

앱을 만들었던것도 도전 중 하나였습니다. 당시에 앱은 내고 싶었는데 처음부터 만들기에는 너무 삽질을 하게 될거같아서 (API를 따고 연동하고 하는게...) 웹을 그대로 보여주는 하이브리드 앱으로 만들기로 결정하고 보여지는 부분을 많이 다듬었습니다. 그리고 약간의 토큰 작업들을 하고.. 이때 친절한주인, Jake가 많이 고생했습니다.

브라우니라는 거래 게시판도 만들고 있었는데, 앱이 꼭 필요하다 생각해서 작업을 했었으나.. 여가부에서 성인이 아닌사람들의 사이트 제한을 해야 된다고 답변 받아서 접었던 기억이 납니다. 외압아닌 외압에 이제... 접게된 최초의 사례인데 이건 글로 남겨놨습니다.. 여가부 남자직원이 아덴으로 설명을 해주시더군요.. (현거래가 아니어도 제재 대상..) 

관련글:
싴갤러스 가판대(브라우니) - 리뉴얼에 대해 고민하다
싴갤러스 - 하나의 기능 리뉴얼을 준비하며 (1)
싴갤러스 - 하나의 기능 리뉴얼을 준비하며 (2)

받은 질문 모음

Q. 게임도 안하는사람이 굳이 고생해서 좆망겜 관련사이트 운영하는 이유가 뭐임?
A. 게임은 2011년에 싴갤러스를 하면서 접었습니다. 우선 염려되었던게 좆목에 휘말릴까봐도 있었고 다행히도 당시에 게임에 대한 애정이 많이 식은 상태였습니다. 아본과 세공이 막 나오던 시절이었는데 세공에 투자할 재력도 없었고, 실제로 현실에서 많이 바빴습니다. 그래서 게임을 정리했던건데 결과적으론 접어서 다행인거 같습니다.

운영을 계속하는 이유는 보람이 젤 크지 않을까 합니다. 우리가 설계하고 기획한 기능들 (거의 대부분 유저분들의 자료를 긁어모으지만)이 잘 쓰이는걸 보면 기분이 좋습니다. 뭐 그게 다 인거같아요.

Q. 사이트 원리가 뭐에요
A. 네트워크 공부를 하시면 누구나 쉽게 할만한 기술들입니다. 마비엔 초고수들이 아주 많으나 그냥 다들 하기 귀찮아서가 아닐까... 싶습니다.

Q. 개발 및 유지보수는 혼자하나요
A. 처음엔 그랬는데 지금은 도와주는 드자이너들도 있고, 앱같은경우는 개발은 직접하지 않았고 유지보수는 맡아서 하고 있습니다.

Q. 트럭시위때 사이트는 왜 닫은건가요
거상 팬 커뮤니티중에 '파란만장 거상' 이라는 카페가 있습니다. 이 카페는 공식사이트보다도 더 큰 영향력과 지분을 가지고 있는것으로 알고 있는데, 약 1주일간 운영에 시위의 의미로 카페를 닫은적이 있습니다. 그 결과로 게임사에서 운영개선을 약속했던것으로 알고 있습니다.
마비노기는 유저층이 모두가 꼭 전투나 생활을 할 필요가 없어서 이해 관계가 나뉜다고 생각합니다. 따라서 관심없는 유저들은 세태를 끝까지 모르게 될것이라고 생각했고, 상황을 알리고 정리하는 지면의 역할을 해야겠다고 생각했습니다.

Q. 광고 수입은 얼마쯤 되나요
A. 서버 비용을 제한 광고 수입은 월 10만원 정도입니다.
도메인 결제가 겹치게 된다면 한 5만원정도로 잡는게 맞지 않을까요? 현재는 애플에 서비스하고 있지 않아서 이정도이고, 애플 결제를 진행하면 한 3만원대..의 수입이 있지 싶습니다. 그래도 치킨한마리는 먹는거 같네요.

아시다시피, 싴갤러스는 중간 컨텐츠에는 광고를 삽입하고 있지 않습니다.  총 광고는 4개이나, 화면이 1920 사이즈로 풀 확대되었을때 양쪽 세로에 두개가 출력되고, 그게 아니면 페이지의 가장 상단 및 하단에 출력되는 구조입니다. (특히 하단은 사이트가 스크롤이 많기때문에 거의 출력안되는거 같습니다)

그래서 밥벌이는 세로로광고로 거의 하는거 같고, 본문의 광고로는 수입이 거의 발생하지 않습니다. (생각보다 인터넷 창을 다 키워놓고 하는 분들이 많아서 놀랬습니다) 

Q. 기억에 남는 썰이 있다면?
학교 다닐때 용돈을 받아서 생활했었는데, 당시에 서버비를 내고 나면 컵라면 두개를 살 수 있었습니다. 주말동안 컵라면 두개로 살아야했는데 다 먹어버리면 끼니 해결이 안되니까 ㅋㅋㅋ 컵라면을 반반씩 쪼개서 먹었던 기억이 있습니다. 불쌍하다고 후원해주셔서 해당일엔 치킨 먹었습니다. 아직도 호르헤님 닉이 안잊혀지네요...

두번째로는 훈련소 들어가있는데 인터넷 편지로 서버 터졌다고 관리자중에 한명이 에러 메세지를 적어서 보내줬었습니다... 장황하게...
어떻게 고쳐야 최대한 빨리 고칠 수 있을까 원인은 뭘까 고민 및 시뮬레이션과 답답함에 미쳐버리는 시간을 보내게 해주었습니다. 고마워...

10년

10년이면 3650일인가요? 러닝타임이 그정도까진 되지 않을거 같습니다. 잠깐 닫은적도 있고.. 하지만 햇수로는 10년이 맞겠죠.
울고 웃고 많은 일들이 있었습니다. 여기까지 오기엔 혼자만의 힘으론 불가능했습니다. 도와준 관리자들에게 다시한번 감사의 인사를 드리고 또 사이트를 계속 사용해주시는 여러분들도 정말 고맙습니다.

사실은, 싴갤러스의 graceful shutdown 을 생각하고 있습니다.
마비노기 타임즈나 쫀득쫀득 인챈트와 같이 이미 10주년을 넘긴 사이트들앞에서 주름잡는게 조금 민망합니다.

커뮤니티들이 떠오르고 지고를 많이 반복했습니다만 그 끝은 사이트를 접은게 아니라 접힌쪽에 가까웠습니다.
접히는게 아니라, 사이트를 내손으로 접을 수 있다면, 또 내가 이 사이트를 평생 운영할 계획이 아니라면 10년이 되는 시점에서 커튼을 내리는것도 아름답지 않을까? 하는 생각을 했습니다. 그보다 적절한 시점이 없지 않을까 생각했어요.

그래서 디데이 옆 아이콘도 전원버튼을 달아놨는데요. (응원을 바라고 쓰는글이 아닙니다. 그냥 생각했던 내용입니다) 남은 시간동안 계속 생각해볼것 같은데 아마 계속 운영하지 싶습니다. 아마도...

지난 10년간 싴갤러스를 이용해주셔서 감사했고, 앞으로도 감사드리겠습니다!!
2021/04/07 10:30 2021/04/07 10:30

Intent setResult 관리

Android 2019/08/02 15:57
금번에 앱을 수정하는데 intent 전환시 반환되는 requestCode가 무슨짓을 해도 0이 나와서 삽질을 했다
아무래도 기본적인 이해가 없이 땜질만하다보니 (주로 퍼온코드들을 넣다보니) 이런일이 발생하게 된것 같은데...

대상이 되는 액티비티는 A, B, C 세개였는데

처음에는 A가 B를 불러주고, B가 C를 부르는 구도인데
B에서 C를 무슨수를 써도 C에서 받는 RequestCode가 0이었다. 이게 왜그럴까 하면서 많은 삽질을 했는데...

좀 파보니 A가 B를 이렇게 부르고 있었다

intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
...
startActivityForResult(intent, 0);


근데 이렇게 하면 A가 B를 부르고 다시 A에게 돌아간거나 다를바가 없었다.
호출되는 상황이 다르기때문에 B의 result를 그대로 써야하는데 이렇게 되면 0으로만 값이 반환되는것이었다

그래서 이런 상황에서는 B의 반환값을 그대로 사용하기 위해서 다음과 같이 써야한다.

A를 다음과 같이 고친다

intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT);
...
startActivity(intent);



B는 하던데로 setResult에 값을 적고 반환한다.

setResult(Value, intent);


A는 B와 C사이의 커뮤니케이션에 아무 상관이 없는 친구이므로, 관심꺼라고 명시를 해줘야 제대로 전달된다.
사실, 이 디자인은 문제가 좀 있었는데 B가 A를 상속받고, 핸들러로 처리하면 될 문제였으나... A를 상속하지 않은채로 만들어진 쌩짜의 액티비티라 이런일이 생길수도 있던것 같다...
2019/08/02 15:57 2019/08/02 15:57

서론


글쓰기에 앞서서, 별로 권하고 싶진 않습니다.
좀 고행길이고, 저는 판교테크노밸리 기업은행에서 진행했는데 그 은행에서 2번째로 성공한 사람이랍디다.

우선, 집주인들이 왜 전세자금대출을 꺼려하는지 알 필요가 있습니다.

집주인들은 전세금을 받아서 대부분 다른곳에 투자합니다. 그리고 새로운 세입자가 오면 새 세입자에게 전세금을 받고, 투자했던곳에 입금 후 전세금을 빼서 이사가는 세입자에게 돌려주는 식이죠. 이 구간은 보통 유연하게 처리 됩니다. 뭐 하루 이따가 돈 줘라, 하루 이따가 돈 주겠다. 뭐 이런식으로 투자한 전세금의 로스가 생기지 않도록 처리한다는거죠

그런데 전세자금대출로 전세금을 내면 그렇지 않습니다.
딱 하루만 지나도 은행은 집주인에게 이자를 부과합니다. 빨리 돈 갚으라고요. 돈을 유연하게 운용할 수 없고 칼같이 은행에 입금해야합니다. 집주인들로서는 귀찮은 일이죠. 그래서 전세자금대출을 안해준다는 주인들은 이게 귀찮아서 안해준다고 합니다. 근데 여기까진 그냥 기본만 지키면 되는거라, 왠만하면 해줍니다. 

중소기업청년전세자금대출도 80%는 비슷합니다. 거의 필요한 서류가 없고 빨리빨리 진행되는 편입니다.
하지만 그게 궁금하진 않잖아요? 100% 대출은 왜 권하지 않느냐?

집주인의 의지와 상관없이 대출이 나오지 않기 때문입니다.
집주인들은 전세금 및 건물을 담보로해 대출을 받아 또 다른 투자를 합니다. 대부분의 건물은 융자가 걸려있습니다.
100%대출의 경우에선 진짜 작은 융자도 허락하질 않습니다. 그냥, 융자가 있다면 안된다고 보면 됩니다.
그리고 보증보험에 가입되고 이로 인해 내용증명이 발송됩니다. 사실 이건 발송된다고만 알려주면 되는 사항이고 집주인이 해야할 필요는 없습니다.

그럼, 시작해볼까요.

주제파악


너무 센 워딩인가 싶은데 3500 이상 연봉받는 사람은 이거 신청못합니다. 그리고 입사 1년이상안되면 포기하세요.
또, 회사가 너무 약해도 문제가 됩니다. 여기서 확인해보세요. http://nhuf.molit.go.kr/FP/FP05/FP0502/FP05020604.jsp
그리고, 은행에서 자기가 얼마까지 대출되는지도 파악해야합니다. 1억짜리 집구했는데 대출 1억 못준다고 하면 안되잖아요? 대강 연봉의 3배 정도까지 나온다고 보면 될 것 같습니다.

집구하기


가장 먼저 해야할 일은 집을 구하는것입니다. 너무 당연한 소리지만 위에 얘기한대로 융자가 없는 건물이어야 합니다.
다가구주택 및 아파트, 오피스텔의 경우에는 한명한명이 세대주이기때문에 별로 신경쓸 필욘없습니다. 그러나 단독주택같은 건물은 융자체크를 반드시 해야합니다.
100%를 받을시 최대 금액은 1억원입니다. 1억 이상의 집은 반전세 돌리면 해결됩니다. 그러니까 조건이 까다로운셈입니다. 간단히 정리해봅시다

- 좋은집을 구한다.
- 전세금을 확인한다.
- 집 크기를 확인한다. (85m^2 이상의 크기는 입주 불가)
- 융자가 없는 집인지 확인한다

여기서 융자가 없는 건물을 셀프로 확인하는 방법은, 건물 등기를 떼보면 됩니다. 융자가 있을떄는 '을구' 란에 기재되어 나옵니다. 뭐라도 하나 나오면 그 집은 그냥 포기하세요. 이사인만큼 이 과정이 가장 어렵고 치열합니다. 대부분 한개씩 하자가 있습니다. 심지어는 저는 계약날 전에 주인이 마음바꿔서 물러진적도 있습니다. 진-짜 힘듭니다. 된다고 하는 중개사들 찾기도 어렵고, 집주인도 찾기 어렵습니다. 100%는 정말 어렵습니다.

그리고 입주날짜가 중요합니다. 대출 서류 검토 및 심사는 최대 3주정도가 소요됩니다. 역시 만족되지 않으면 안되겠죠.
집을 찾았다면 은행에가서 대출할건데 어쩌면 되냐고 물어보면 이것저것 따져주고, 양식 두개를 줍니다. 그건 아래단에서 작성합니다.

계약하기


집을 구하셨다면 대단한겁니다.
계약전에 등기등본을 들고 은행에 가면 대출이 나오겠네요 안나오겠네요 이런 소릴 해줍니다. '을구'에 뭐가 없으면 대부분 가능하지만, 은행에서는 국토부 시세 등을 따져보기 때문에 그냥 등기등본들고 은행가서 여기 진행해도 되냐고 물어보는게 가장 속편합니다.

집 주인과 계약을 하실 차례입니다. 계약은 일반적인 계약과는 다를게 없습니다만, '확인서'를 작성해야합니다.
그 건물에 누가 살고 있고, 전세금은 얼마, 월세는 얼마를 내며 살고 있는지 작성되어야 합니다. 이건 나중에 세입자 증명서를 제출해야할때 이름이 안맞으면 다시 써야할수도 있으니까 임대인에게 제대로 물어봐야합니다. (보통 역정냄)

중개사에서도 건물 시세 조사서를 작성해줘야합니다. 이건 대출할거다 하면 은행에서 양식을 주면서 써오라고 합니다. (계약전에 은행에 꼭 들릅시다)

이래저래 계약을 하되 반드시 다음 특약을 챙겨야합니다. 대출이 안나올수도 있기 때문입니다.
'은행대출이 불가능할시, 계약을 무효로 하고 전액 반환한다.' 와 같은 뉘앙스면 됩니다. 이거 못써주겠다고 하면 그냥 조용히 자리에서 일어나시면 됩니다. 보증금을 지불하고, 영수증을 꼭 챙깁시다.

계약을 완료했으면 확정일자를 신청합니다. 확정일자를 작성하지 않으면 애초에 신청을 못하고, 나중에 세입자 증명서를 뗄수가 없으니까 바로 합시다.
신청이 끝났다면 이제 문서와의 전쟁입니다.

대출 신청

드디어 대출신청란까지 왔습니다.
대출엔 다음과 같은 서류들이 필요했던것 같은데 누락이 된게 있을수도 있습니다.

- 재직 증명서 (회사에 요청)
- 근로소득원천징수영수증 (회사에 요청)
- 건강보험자격득실확인서
- 사업자등록증 (사본, 회사에 요청)
- 고용보험 피보험자격 이력 내역서
- 회사 주업종코드 확인 자료 (회사에 요청)
- 주민등록 등본, 초본, 가족관계증명서
- 집 등기 등본
- 분양계약서, 임대차 계약서 (사본X)
- 확정일자가 작성된 계약서 (이건 돌려받습니다)
- 확인서 (세들어 사는 사람의 전세금액 및 월세금액, 집주인)
- 세입자 확인서 (확정일자가 있지 않으면 발급안됨. 주민복지센터에서. 반드시 본인게 아니라 건물전체의 내역 필요.)
- 공인중개사 등록증
- 건물 주변 시세 조사서 (중개사에서 작성)

아 많다 증말 진짜
위에건 예외없이 다 필요하니 그냥 미리 준비들 합시다. 근데 너무 오래되면 못쓴다고 돌려보내니까 너무 빨리 뽑아두진 말고...
잔금일자를 확인후에 은행에 가면 무지막지한 대출 신청서에 계속 사인하고 날짜 적으라고 합니다. 시키는대로 하면 됩니다.. 
뭐 보증금은 어떻고 잔금은 어디로 들어가고 이런거는 굳이 알아가야할 필요가 없습니다. 그냥 은행에서 시키는대로 하면 다 됩니다.

기다림


기다리는 동안 은행에서 가끔 연락이 옵니다. 이 문서가 잘못됐는데, 특약에 사인해주셔야하는데 하면서 챙겨줍니다.
오랄떄 왠만하면 빨리빨리 다녀야합니다. 일정이 늦춰질 수 있거든요. 신청 후 임대인에게 내용증명 등기가 날아가는데 이것도 꼭 수령해야합니다.
제발 수령해달라고 합시다. 그러면 은행에서 그거 받았냐고 임대인에게 전화가 따로가고, 받았다하고 뭐 동의같은거 해주면 진짜 기다리기만 하면 됩니다. 골때리는게 별도의 승인 문자 이런게 없습니다. 어떻게 진행되는지도 모르겠고 그냥 기다려야되는데 저는 하도 답답해서 은행가서 어찌되고 있냐고 물어본적도 있어요..

이사


잔금일자가 되면 이사를 가면 됩니다. 아~ 이사 왔다~
끝이 아닙니다. 전화가 옵니다. 실사단이 파견됩니다. 약 5분정도 걸리는 시간인데 집 문사진이랑, 실제로 세입자가 떠나고 내가 들어간 집인지 등을 보고 갑니다. 근데 짤없이 평일만 된다고 합니다. 하...... 

전입신고도 해야합니다. 이사후 3일이내에 전입안하면 황입니다. 전입신고를 했다면 주소 변동이력이 작성된 등본을 뽑아다 은행에 제출하면, 모든 과정이 끝이 납니다.

결론


문서는 사실 얼마든 쓸수있습니다. 좀 귀찮으니까요.
그런데 100%로 되는 집을 구하는게 너무 힘듭니다. 중개사들 시선도 곱지도 않고요. 차타고 가다가 한두개만 보여주고 우린 그런거 없다하고 내려준 중개사도 있습니다 ㅋㅋ 
마음을 넉넉하게 가지시고, 천천히 알아보심을 권합니다. 그럼!
2019/03/25 10:04 2019/03/25 10:04
TL;DR
apktool로 디컴파일-컴파일 했을때 망하면 다음을 확인해보자
classpath 'com.android.tools.build:gradle:3.1.4' -> 3.1.4 이상부터 뭘 해도 안된다.


자세히
내가 만든 앱을 디컴파일 및 컴파일 해야되는 계기가 생겼는데 (왜 이런 삽질을 하냐고 묻진 말자... 자본주의...)
갑자기 이런 에러가 나면서 재 컴파일이 되지 않았다.

Public symbol array/XXXXXX declared here is not defined.


이런게 막 수십줄이 뜨고 마지막에는 

brut.androidlib.AndrolibException 이 뜨면서 으마으마한것들이 잔뜩 나오며 실패했다.
minSDK 문제인지 targetSDK 문제인지 진짜 뭔 별 안해본게 없는데 커밋로그들을 쭉 둘러보면서 바뀐게 뭔가 하다가 설마 gradle 버전 문제인가 싶어서 기존에 쓰던 3.1.4로 낮춰서 빌드를 해 재컴파일 해보았더니 그냥 된다...

3.1.4에서 올린 이유는 이런 에러가 나왔기 때문인데
The rule `-keep public class *extends java.lang.annotation.Annotation {


gradle 버전을 올리니 더 뜨지 않아서 올렸던 기억이 있다. 그런데.. 이런 사태가 난 것이다.
좀 실험을 했는데 3.2.1 도 해보고, 3.3.1도 해봤는데 뭘 해도 안된다. 그냥 3.1.4만 된다. 혹은 그 아래버전도 되겠지만 그건 필요가 없으니..
어이가 없어서 남긴다. 여튼 겨우 한건 해결...
2019/02/27 11:31 2019/02/27 11:31

2018년

Gossip 2018/12/31 09:51
2018년은 참 다사다난해였고, 진행중이다.

흠..
2017년도에 블로깅은 꽤 열심히 했다. TIL (Today I Learn) 위주의 글들도 제법 작성했고 워게임을 풀이하는 바람에 꽤 많은 글을 작성한 해 였다. 방문자가 20명대에서 매일 40명대 찍히는거보면 헛짓거리는 아니었던 모양이다. 그래봐야 40명이긴하지만...
두번째로 일상이 챗바퀴..
자전거를 열심히 탔다. 인천에 경인항에도 갔다오기도 하고 꾸준히 탔으나 그외에는 기존의 나를 탈선시킬정도까지 어마어마한 취미는 없었다. 좋은 사람이 생긴거 정도는 ... 음...
세번째 건강은 꽤 호전이 있었다.
좀 많이 쳐줘서 2 3키로만 감량하면 20키로쯤 감량된거같다. 좀 어거지긴하지만 감량이 된건 된거고, 혈압도 훈련소안에서 제자리를 찾아왔기때문에 이대로 쭉 유지도 하고, 감량도 계속해볼 생각이다. 그래도 근력이 딸리는건 마찬가지라 운동도 필요하고...
2018년
훈련을 다녀오니 이제 다 끝난 느낌이다. 날 가로막는 모든 장애물이 사라진 느낌?
좀 더 적극적으로 공부를 해야겠다. 그리고 보안 공부를 소홀히 하지 않겠고.. 자격증을 취득해보는게 목표다. 자격증을 취득한다는 거도 의미가 있지만, 일단 목표가 있고 공부를 한다는 행위에 의미를 두기로 한다. 한자, 토익, 리눅스 마스터 등이 생각하고 있는 목표인데 잘 모르겠다.
그리고 알고리즘과 자료구조를 다시 공부할 생각이다.
결국 기초가 중요한건데 모래성을 계속 쌓아갈 순 없다. 워게임 대신 온라인 저지를 좀 풀어볼 생각이다.
두루뭉술한 목표가 되었지만 잘 실천한다면 도약을 위한 발판을 준비하는 한 해가 되지 않을까? 아듀 2017.


직무


훈련소에 다녀왔었다. 2018년이 껴있는 날은 8일정도밖에 안되지만 어쨌든 2018년엔 훈련소를 다녀왔다.
사람이 변했나? 그렇진 않다. 다짐같은건 정말 많이 했고 그렇기에 남긴글이긴한데, 사실은 하나도 이룬게 없다. 지금 보니 우습기만하다. 자격증? 한자? 토익?;;; 적어놓은것의 나열을 보면 정말 한심한 한해를 보낸것 같다.

그래도 여러 시도는 하려고 했다. 역시 이놈의 싴갤러스의 프레임을 벗어나지 못한...
첫번째로, 채팅이 SSL을 지원하지 않아 HTTPS 를 적용할 수 없었었다. 그래서 웹 푸시 역시 사용할 수 없었기 때문에, 채팅을 직접 개발했었다.
socket.io를 이용했고 서버는 노드. 간단한 채팅정도는 왔다갔다 쉽게 만들 수 있었지만 관리자 측면에서 생각해본적은 없었기 때문에 괜찮은 시간이었다. 그러나 완성되진 못했다.. 가능한 모든 가능성과 변수를 고려하고 프로젝트에 돌입해야겠다는 교훈을 얻었다. 그래도 주석이 잔뜩 남긴 소스들은 깃헙에 남게 되었으니까 완전 망한건 아닌것 같다.

두번째 역시 싴갤러스.
셀레늄을 이용한 프로젝트였고 토이 프로젝트인데 너무 프로젝트에 끌려다니는것 같아 인간다움을 추구해 진행된 프로젝트였다. 자동화 관련인데.. 
소스 자체는 2016년 10월에 작성했었는데 한가지 난관을 돌파하지 못하다가 4월쯤 겨우 적용할 수 있었다. 꾸준히 해왔던건 아니고, 자전거 타고 돌아오는길에 왠지 할 수 있을 것 같아서 피느에게 부탁해 프로그램하나 만들고, 적용했다. 현재까지도 잘 돌아가고 있고, 간간히 오작동하고는 있으나 계속 보강할 생각이다.

세번째는 서버. 하지만 역시 싴갤러스;;
docker 를 이용해 mysql replication 컨테이너를 만들고, 컨테이너 자체 백업을 적용했다. 그러니까 백업이 어떻게 보면 삼중화 된 것인데, 새벽경 정기 기 백업, repl, 그리고 컨테이너 커밋을 이용한 백업 체계를 만들(었)었다. 이미지가 크기때문에 당연히 몇개 저장하지 못했고, 결국 서버에 ssd를 하나 더 붙이는 대작업까지 수행했다. 이 작업은 훈련소에서 디비가 깨졌단 소리 듣고 혼자 빡쳐서 꼭 해야겠다고 생각했던건데, mysql 의 인덱스 크래시 문제는 해결이 안된다. 현재 이 백업 체계는 동작하지 않고 있고 -_- 조만간 다시 진행할 예정이다. 뭐가 문제인지 어느순간부터 컨테이너 커밋이 진행되지 않는데, 용량 문제인가 싶기도하다...

그외 여러가지 기능 업뎃을 진행했으나 기억에 남는것은..

1. 키트 데이터 통계를 낼 수 있는 득템전광판 제작
2. 네이드 퇴역
3. 앱 아이콘 변경
4. HTTPS 및 HTTP2 적용 (엄청 미루다가 드디어) , prefork 에서 event 기반으로 변경

이지만 뭐니뭐니해도 레이드, 지염도서관 리팩토링이 기억에 남는다.
내용은 따로 썼었으니 적진않겠지만 코드관리관점에서 가시적인 성과가 있어서 참 좋았다. 기분도 엄청 좋았고.


그외에 회사일은,
뛰어난 일을 한건 없고 잡기술들이 많이 늘었다. 잡지식도 많이 늘고, 애플에 버그리포트도 했다. 먹히진 않았다만.....
내년 싴갤러스는 할 수 있는 목표부터 적어야겠다. docker 안정화하고, 웹 푸시 적용하고, 장기적으로는 아파치를 nginx 로 변경하는게 목표이다


좋은 사람이 있었었다. 2017년 후반과 1월 초까지는. 그런데 4월까지 내내 힘들다가 4월말에 또 좋은 사람이 나타나 좋은 시간을 보내고 있다.
마냥 좋기만 한건 아니지만, 서로 맞춰가는 재미도 있는것 같고 또 한번도 생각해본적도 없던 결혼에 대한 인식도 바뀌었다. 그러나 대부분 즐겁고 행복한 느낌이다. 언제까지 이 감정이 지속될진 모르겠지만, 2019년에 끝나버릴지도 모르겠지만 적어도 2018년은 그렇게 보냈다. 2019년엔 다투지 않고 즐겁게 보냈으면 좋겠는데. 지금까진 그냥 바램.2019년을 돌아볼때 어떤 느낌일까 싶다. 내곁에 계속 남아 있어주려나. 아니면 2018년 초반처럼 아파한 시간을 보냈으려나.
그리고 이사하고 싶다. 이사가 될진 잘 모르겠다만..

공부

정말 열심히 살 생각이다. 11월까진 조용히 아무일도 없게 보내고 싶다. 그러나, 11월엔 이직을 목표로 하려고 한다.
몸이 편한건 사실이다. 일이 많지 않은것도 맞고. 그러나 뭔가 얻는 기분도 들지 않고 뭣보다 일이 재미가 없다. 힘들어도 부딪히면서 일궈내는 느낌이 너무 없어서 좀 더 높은곳을 향하는게 좋지 않나 싶다. 이직하지 않더라도 결국 나 스스로에겐 도움이 될테니까 말이다. 


역시 구체적인 목표는 없는 두루뭉술한 2018년 돌아보기와 2019년 목표였다.
사실, 2019년은 마지막 해라서 조용히만 보내자가 목표이다. 2019년의 나는 어떨까? 앞자리도 바뀌고, 정신적으로 더 성숙해질까? 스스로도 궁금하다.
2018/12/31 09:51 2018/12/31 09:51
W: An error occurred during the signature verification. The repository is not updated and the previous index files will be used. GPG error: http://dl.google.com stable Release: The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 1397BC53640DB551
W: Failed to fetch http://dl.google.com/linux/mod-pagespeed/deb/dists/stable/Release
W: Some index files failed to download. They have been ignored, or old ones used instead.


나는 pagespeed 를 아파치 모듈에 붙여서 사용하고 있다. 그런데 언제부터인지 계속해서 업데이트가 안되었다 (위 내용처럼)
오늘은 정말 거슬려서 구글링을 좀 해봤고 해당을 찾을 수 있었는데... 


apt 명령어 사용시 공개키를 이용하게 되는데 모종의 이유로 이 키가 삭제되거나 누락되면 자동으로 다시 받지 않는 모양이다
https://askubuntu.com/questions/766883/there-is-no-public-key-available-for-the-following-key-ids-1397bc53640db551

여기서 볼 수 있지만, 다음과 같은 명령어로 키를 내려받아주면 해결된다

sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys [KEY NUMBER]


2018/11/12 10:48 2018/11/12 10:48
There is no vulnerability.
Just find the rules.

nc wargame.kr 10034


배스킨 라아빈스 써리~원

배스킨 라빈스 게임은 어릴적 UN의 맴버중 하나가 나와서 필승법이 있다고 예능 인터뷰때 했다고 해서 사기게임이라고 뇌리에 깊게 박혀있다.
실제로, 1:1에서는 배스킨라빈스 게임은 실수하지 않는한 먼저 하는 사람이 무조건 이기는 방법이 있다.

1:1 베스킨 라빈스를 제시하라. 단 필승법을 아는지 대충 떠 봐야한다. (그건 알아서. 귀찮아) 
먼저 시작한다면, 처음에는 1, 2를 외쳐라. 그 다음에는 [4개-상대방이 말한 갯수]만큼씩 외쳐라.

두번째 시작한다면, 어떻게든 당신이 마지막으로 외치는것이 4의 배수보다 1개 많도록 29, 25, 21, 17, 13, 9, 5개가 남도록 한다.
즉 당신이 2, 6, 10, 14, 18, 22, 26으로 끝을 내게 외쳐야 한다.

그 다음에는 마찬가지로 [4-상대갯수]를 말하면 이긴다.
출처: http://yews.tistory.com/entry/베스킨-라빈스-31-11승리전략 [생각의 화장실]


예를 들면 이런식으로 많이 나와 있다. 이런건데, 요점은 반드시 내가 말해야 하는 수가 있다는 것이다.
이런 배경지식을 가지고 시작해보자

Welcome to STITCH's baskinrobbinsN game!
Your Purpose is to win Baskin Robbins31 game from AI. 

Rule)
As you already know, it seems like real Baskin Robbins31 game. But maximum number is not 31.

ex) N=101 , count 10
It situation, You can saying up to ten at a time of number. because count is 10.
if you speaking 101 faster than AI , you lose because N is 101

you will input smaller than count...
you will input the numbers in order.

----------------------------------
hint) 
N = 31, count = 3
input your name -> ab
Hi! ab
user first!
input your number -> 1 2 3
user say -> 1 2 3
computer say -> 4 5 6
input your number -> 7
user say -> 7
computer say -> 8 9 10
input your number -> 11 12 13
user say -> 11 12 13
computer say -> 14
input your number -> 15 16
user say -> 15 16
computer say -> 17 18
input your number -> 19 20 21
user say -> 19 20 21
computer say -> 22
input your number -> 23
user say -> 23
computer say -> 24 25 26
input your number -> 27 28
user say -> 27 28
computer say -> 29 30
AI win!
----------
------------------------

**** Timeout is 150sec... ****
**** Total 31 round... ****
Good luck~




N = 2166, count = 133

input your name -> Hi! fantazm
computer first!
computer say -> 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
input your number -> 


문제가 예시와 함께 잔뜩나온다. 근데 기존에 알던 배스킨게임이 아니다. 최대 수와 부를 수 있는 수자가 랜덤으로 주어진다.
사실 이 글을 쓰기전에 살짝 해봤는데 컴퓨터를 이길 수가 없다. 생각을 다시 해보기로 했다.
읽고 나니 드는 생각이 있다.

나온 문제에서 보면, 내가 불러야될 숫자는 정해져있다. 컴퓨터 턴이 되어도 절대 끝낼 수 없는 수를 불러야한다. 그럼 컴퓨터는 2164까지밖에 부를수있고, 부르더라도 나는 2165를 말하고 승리한다.

http://lg-sl.net/product/scilab/sciencestorylist/ALMA/readSciencestoryList.mvc?sciencestoryListId=ALMA2018040003&subjectId=ALL

https://blog.naver.com/jong1003min/220348353765

https://namu.wiki/w/%EB%B0%B0%EC%8A%A4%ED%82%A8%EB%9D%BC%EB%B9%88%EC%8A%A4%2031(%EA%B2%8C%EC%9E%84)

참고한 링크들을 보자. 왜 하필이면 4일까? 4가 28을 부를 수 있는 배수의 마지노선이기 때문이다. 즉.. 워게임이지만 알고리즘에 가까운 코딩문제인것 같다.

핵심은, 나머지를 구한후 필승 수열을 구하는것이다.
r = (N - 1) % (count + 1)


그리고 목표 수치도 N이 아니라 N-1을 불러야는게 핵심이다. 때문에 내가 한개 더 많이 말해야한다. (베스킨라빈스게임에서도 3까지 부를 수 있지만 4로 맞춰 말하면 이긴다)
따라서 count + 1 을 해서, 필승 수열을 만든다

solns = []
while r < N:
    solns.append(r)
    r += (count + 1)


이제 여기에 등장하는 숫자까지 맞춰서 말하면 이긴다.
코드를 다 올리는건 좀 아닌것 같고 문제 풀면서 정말 X같았던 점들만 좀 적어본다.

1. 아무리해도 이길수가 없다. 컴퓨터가 먼저 시작을 하기 때문이다. 그리고 기가 막히게도 컴퓨터는 이 필승수열의 첫번째 수를 말한다.. 진짜 한참 삽질했는데
처음에 이름을 입력받는데... 이 입력을 짝수로 하면 내가 먼저 시작하고, 홀수로 하면 컴퓨터가 먼저 시작한다. 아........ 이건 처음 수열을 만들때 0으로 시작할 경우, 일부러 컴퓨터에게 턴을 주는식으로 구현하면 된다.
2. 소켓이 짤려서 온다. 숫자가 길어지고, 정확히 1460 자 이상이 되면 개행한다. computer say -> 로 파싱하고 있다가 의문의 payload wrong을 만날 수 있는데, 게임이 시작되었고, 개행이 된채 숫자만 던졌다면 해당 숫자를 마지막으로 다시 계산해야한다

요컨데 이런식으로 온다.

computer say -> 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619 1620 1621 1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 (개행)
(탭) 1633 1634 1635 1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648 1649 1650 1651 1652

별도의 처리가 없으면 이때 1632를 마지막 숫자로 읽어서 시간낭비를 하게 된다.
다음과 같이 정규식으로 처리해주면 된다.

 ext = re.findall(r"^\s+((?:\d+ )*\d+)$", line)
 if len(ext):
    response = re.findall(r"^\s+((?:\d+ )*\d+)$", line)[0].split(" ")
 


socket.recv 같이 너무 작으면 개행을 막 두번씩 하기도 하니, 애초에 넉넉하게 잡고 수신해주면 좋을 것 같다.
2018/11/07 09:09 2018/11/07 09:09