늘모자란, 개발

늘모자란, 개발


wargame.kr이 새단장을 해서 보니 문제가 꽤 추가 되어 있었다.
custom OS 빼곤 다 풀었었던거 같은데... 저 문제는 아직도 잘 모르겠고, 짬을 내서 풀어보기로 한다.

먼저 시도할 문제는 plz variable 이라는 문제.

Can you find the solution quickly in polynomials? 
nc wargame.kr 10004


nc는 netcat 의 줄임말로, 간단히 데이터를 읽고 쓰는 프로그램이라고 한다.
여러 문제를 눌러보니 이제 문제를 웹에서 푸는게 아니라 저 프로그램을 이용해야 되는거 같다.
그냥 telnet을 이용해도 되는거 같은데 일단 시킨대로 nc로 연결해보았다.
그러자 문제가 나왔다.

Please match the correct answer 30 times.

Submit format -> a,b,c,d,,,(Ascending order)
Timeout = 60sec
a,b,c,d,,, is natural number
a,b,c,d,,, is 100 <= <= 1000

1th...
b * a + f + e * d - c = 491787
a * b * c - d * e + f = 359074294
e - b + a * c - d - f = 677922
d + c + e + f + a + b = 3215
a * f - c + e + b + d = 162962
a * b + c + f - e - d = 368086
Answer -> 



예 잘봤습니다. 제 점수는요.
여러번 연결해보니 나오는 변수 만큼 문제가 출력되는거 같다. polynomials. 다항식, 연립방정식이다.
그전에 내가 알파고가 아니니까 60초만에 저 문제들을 풀어낼순 없다. 코드로 문제를 받는거부터 시작이다.
딴건 없고, 그냥 소켓 연결을 생각하고 코딩을 하면 되었다.

import socket

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server_address = ('wargame.kr',10004)
sock.connect(server_address)

data = sock.recv(1024)
print data

sock.close()


데이터 전송은 sock.send로 하면 되는거 같다. 어쨌든 잘 연결이 되었다.
이제 문제를 풀어야하는데.. python 연립방정식 따위의 키워드로 검색을 하니 몇개 나왔다. sympy 나 numpy scipy 등을 이용하면 된다고 한다.
그중에 sympy 의 solve를 많이 쓰는거같은데, 이 문제에서는 답까지 주니까 nsolve를 사용하면 될것 같았다.

우선 nsolve 를 사용하기 위해서는 어떤 알파벳이 변수로 사용되고 있는지 Symbol을 선언해주어야 했다.
그리고 이건 식입니다. 하고 명세하기 위한 Eq도 필요했다.
우리는 그리고 nsolve를 사용하기로 ...

from sympy import Symbol, Eq, nsolve


그리고 식은 정직하게 주지만 다음 문제를 보지 못했기 때문에, 수학식임을 판단하기 위해서 다음과 같이 검사했다.
각 라인이 개행되있기때문에 라인별로 정규식으로 검사했다. 좀 과한거 같긴한데 아래같이 할 필욘없다.. 여튼 이렇게 식과 답을 분리해서 넣었다.

for line in data.split('\n'):
 if "Answer" not in line and "Submit format" not in line and re.match(r"[a-zA-Z]",line) != None and re.match(r"^(-?\d+)$",line) == None and re.search(r"[()\\*+-]", line) != None:
 eq.append(re.findall(r"(.+?) \=",line)[0].replace("\t"," "))
 answ.append(int(re.findall(r"\=\s(.+)",line)[0]))


사용되는 변수들은 중복을 제거해 Symbol 로 선언해주기 위해 다음과 같이 했다.

list(set(re.findall(r"[a-z]","".join(eq))))


이제 list 세개를 모두 확보했기때문에 nsovle에 넣고 돌림 되겠지 하고 돌렸는데 에러가 났다-_-
Eq로 list를 하나하나 해줘도 Symbol 이 변수명으로 선언되지 않으면 돌아가질 않았다. 즉 요렇게

a = Symbol('a')


허미.. 이게 몇개나 나올줄 알고 심볼을 선언해주나. exec를 쓰면 된다.

exec("{0} = Symbol('{1}')".format(name, str(name)))


이런 느낌으로 돌려주면 선언된다. Eq도 똑같이 해줬는데 그래도 안된다.
그래서 찾아보니, (e1,e2,e3,e4) / (x,y,z) 이런식으로 기재는 하는데 내가 만든 리스트는 ('e1','e2','e3') ('x','y','z') 처럼 문자열같이 되있었다.
하아.. eval 도 해주기로 했다.

for i,j,k in zip(exps, symbols,answ):
 epack = "{},{}".format(epack,i)
 spack = "{},{}".format(spack,j)
 apack = "{},{}".format(apack,k)

epack = "("+epack[1:]+")"
spack = "("+spack[1:]+")"
apack = "("+apack[1:]+")"


이후 nsolve에 eval(epack) 이런식으로 실행했다. 안된다.
코드상 문제는 없는거 같은데 단순히 값을 꾸겨넣는정도로는 안되나보다. matrix 가 0이니, divisionZero 에러니 뭐 별에 별 에러가 나와서 그냥 때려쳤다. solve도 써보고 뭐 다른 방법도 여러개 해봤는데 안됨.
그러다가 내가 못찾은 다른 solver가 있는건 아닐까 싶어 찾아보다가 z3라는 solver를 찾게 되었다.

z3는 리버싱때 많이 쓴다고 한다. 주소 계산같은데 활용되는거 같다. 어쨌든 z3라는 무기를 다시 확보했으니, 풀어보자.

먼저 Solver 라고 문제 풀이 머신을 하나 추가해줘야한다.

import z3 as z
s = z.Solver()


이런느낌이다. 그리고 조건들을 추가해줘야하는데, 수식에서 = 를 ==로 변환해서 넣어주어야 한다.
그리고 100보다 크고, 1000보다 작은 수이기때문에 조건을 입력해주어야한다. 아니면 시간이 너무 오래걸리거나 중간에 퍼지는 경우가 생긴다.
또한, 위에서 Symbol 을 선언해주었던것 처럼 eval 로 Int 임도 먼저 선언해주어야 한다. 그러면..

for i in variables:
 exec("{} = z.Int('{}')".format(i,i))
 s.add(eval("{} >= 100".format(eval(i))))
 s.add(eval("{} <= 1000".format(eval(i))))

이런 느낌이 된다. 그리고 수식을 = 를 변환해주어서 추가해준다.

for i in exps:
 s.add(eval(i.replace("=","==")))


이러고 문제 해결을 위해 다음과 같이 해준다.

s.check()
result = s.model()



여기서 내가 헷갈렸던건,
Submit format -> a,b,c,d,,,(Ascending order)
이부분인데, 아.. 나는 값을 정렬하라는줄 알았는데 그게 아니라 key 이름대로 정렬해서 출력하는것이다. 진짜 풀이에 문제가 있는줄 알고 한참헤맸다..
새로운 라이브러리를 알게 되니 뭔가 강력한 무기를 갖춘 느낌이다. 플래그를 보니 정답이었던것 같다.

2018/10/31 15:41 2018/10/31 15:41

레이드.

마비노기라는 게임에 레이드라는 단어가 이제 어울릴지 모르겠습니다.
유저 하나하나가 너무 강해지는 바람에 체력이 못따라가는 상황인 것 같더군요..



그럼에도 불구하고 싴갤러스에서는 유저분들의 제보를 이용해 보다 더 나은 레이드 환경을 만들려고 항상 노력하고 있습니다 (진짜)
오늘 이 글에서 다룰 이야기는 바로 그 레이드 개선에 관한 이야기입니다

구조적 문제를 안고 시작하다


처음 싴갤러스의 레이드를 다룰때는 네이드, 거대사자, 거대악어, 평원 드래곤 그리고 이프리트 5종만 다루었습니다.



아마 위 레이아웃은 본적도 없으신분들이 많을 것 같은데요.
이때는 웹, 즉 PHP를 막 배우고 있을때 만든 홈페이지라 레이드 별로 페이지를 전부 하나씩 생성했습니다.
그리고 DB에서 보스별로 불러와 처리했죠. 그러니까 즉, SQL 쿼리만 살짝 다른 페이지가 5종, 전체를 볼 수 있는 페이지까지 해서 6종이죠.
그리고 자바스크립트도 잘 할 줄 몰라서 하나의 페이지를 가지고 인자를 전달해 다른 결과를 보여준다는건 생각도 못했고, 무조건 페이지 이동이 필요했습니다


js를 좀 배우고 나서도 문제가 해결되진 않았습니다.
이미 나눠진 페이지를 굳이 합칠 필요가 없었기 때문입니다. 그리고 이땐 또 ajax와 REST개념을 잘못 이해하고 있어서 ajax로 데이터를 불러오는게 아니라 페이지 자체를 그대로 불러와 대상 dom 에 씌우는 식이었습니다. 그러니까, 불러오는 페이지에서 표까지 완전히 작성하는 구조였죠.

그렇게 많은 페이지들이 만들어진 상태에서 레이드가 계속 늘어났습니다. 레드 드래곤부터 시작해서, 시간이 고정이었던 사막 드래곤, 신규 레이드인 블랙, 화이트 드래곤부터 지금의 실반 드래곤, 모쿠르칼피까지. 첫 단추를 잘못꿴 상태였기때문에 똑같은 페이지를 계속 만들어낼 수 밖에 없었습니다. 잘못된건 아는데, 빠르게 결과물을 내야했기때문에 -당시에 레이드는 경쟁구도의 사이트가 있었습니다- 속도를 올릴 수 밖에 없었고, 나중을 기약하며 조악한 페이지들을 계속 늘려만 갔죠. 그 결과는...


(여기서 strings는 작업하려고 추가해놓은거고 실제론 없었음)

raid3.php 이라는 뷰 페이지에서 page를 include 해서 보여주는 식이었고, 각 페이지에서는 각 프로세스를 처리할 (레이드 마다 시간이 다르기때문에) 페이지에 1:1로 매칭이 됩니다. 초록색은 작업하려고 만든거라 상관없고... 그러니까, 거의 20여개에 달하는 페이지로 구성되어 있던거죠... 그리고 스크립트도 PHP 변수를 사용해 처리하기때문에 인라인 스크립트로 작성되어 있고, css도 인라인 css로 작성되어 있기때문에...

단 하나의 수정이 발생하면 최소 8개 페이지(레이드가 다르더라도 인터페이스는 공통된 경험을 줘야하니까)가 수정되어야했고, 좀 심하면 처리 페이지까지 수정해야했으니 1글자를 고치기 위해 20페이지가 수정되어야 하는 기염을 토하기도 했습니다.
구조적인 문제가 분명히 있었으나, 다들 잘 쓰고 있으니까요. 굳이 수정이 안되어도 문제가 없었습니다. 어차피 레이드는 완성형이라고 생각했고, 뭐 하나 추가되면 페이지 늘려야지, 이젠 도가 텄으니 빨리빨리 수정할 수 있다 이런식으로 애써 신경안쓰려고 하고 살았습니다..


곪은건 터지게 된다


신규 기능 요청이 들어왔습니다. 별건아니고, 전광판을 여러개 띄울 수 있게 해주세요.... 인데
모든 보스몬스터가 별도로 구분되어 있기때문에 현재의 구조로는 제공할 수가 없었습니다. 정확히는 가능은 하지만 불필요한 함수를 작성해야할 수도 있고, 뭣보다 중간에 수정이 일어나게 되면 모든 페이지에 같은 내용으로 또 작성... 아... 더 이상은 얘기하기 싫네요.

그래서 이왕 이렇게 된거 레이드 자체를 다시짜자고 결심하게 되었습니다.
단 한번의 수정으로 많은 경험을 선사해주자는거죠. 결론부터 작성해보자면 다음과 같이 변했습니다.
여기에 raid.js 라는 별도로 분리된 js 파일이 하나 더 있습니다. 뷰를 담당하는 파일이 하나 더 있고요.



먼저 페이지를 통일하는게 중요했습니다.
어차피 설명만 좀 다르고 마크업은 똑같기 때문에 (아주 약간만 다르던지) assets에 strings 를 추가해 파라미터별로 설명을 다르게 표시해주는것부터 시작했습니다. 같은 이름의 변수를 case마다 계속 작성해나가는게 유쾌한 경험은 아니었지만 필요한 작업이니까, 좋게 말하면 string을 분리한거고, 나쁘게 말하면 우겨넣은거죠. 그래도 다음과 같아졌습니다.



이제 이 수많은 print_보스들... 왜 이럴까 소스를보니 초반부는 다른데 후반부는 완전 같습니다.
이상하네 하고 보니까(내가 짠건데 이상하네라고...) 그냥 시간을 체크해서 레이드 시간인지 아니만 판단하는 부분만 다를뿐 모두 같더군요.
그리고 이상하게 뿔피리데이터를 이쪽에서 만들고 있었는데 검색 키워드만 조금씩 다르고 쿼리도 같고요. 자갈치 시장도 아니고 한번에 처리하려고 발악을 한 느낌이었습니다. (print_smd_data , print_smd_horn 이렇게 안하려고...?)

해야할건 명확했습니다. 각 보스별로 시간 체크 및 시간, 제보 정보를 합치고, 뿔피리 데이터를 분리해 처리하는 두개파일로 나누는거죠.
그리고 전광판을 여러개 띄웠을때도 같은 페이지로 온전히 동작해야하니까 범용성을 살짝 넣고.

그렇게 서버에서 주는 값들을 대강 명세하고, js 를 수정했습니다.
기존엔 js안에 서버 변수를 넣어서 그대로 작성한 케이스가 많았는데 이번엔 어떤 서버변수도 사용하면 안되었기때문에, url 을 이용해 구분했습니다. 그리고 대부분의 DOM을 dynamic 하게 만들어야했기때문에 js안에 html div를 많이 작성했습니다. 이게 맞는 방법인진 모르겠는데.. 맞겠죠?;

js를 작성하면서 느낀건데 multi line을 작성할때 쓰는 ` (back qoute)와 new URL, filter arrow 등은 IE에서 사용할 수가 없었어서 다 만들었다 생각했는데 대체하기 위해 다시 작업을 하고.... 뭐 그랬던거 같네요. 그리고 신규 관리자분이 들어왔는데... 시련이 시작되었습니다. css 지옥이었는데.. 봐주는 관리자 한명이 잠을 안자...




화면을 같이 보고 있는게 아니라서 캡쳐 후 보여주기를 계속 반복해야했고 결국 대화방 앨범이 이거 관련 내용으로 한페이지를 넘게 차지하게 되더군요. 개인적으로 디자인 작업은 안좋아하기때문에 아주 많이 힘든 시간이었습니다.... ㅠㅠ
신규 기능 추가를 마치고, 테스트 서버에서 기능이 실제 데이터 기반으로 잘 돌아가는걸 확인하고 기능을 릴리즈 했지만 IE 호환문제, 창이 자동으로 안뜬다던지, 채팅 제보 정규식에 문제가 있다던지 하는 소소하면서도 안되면 불편한 문제들이 계속 발견되면서, 한번에 완벽하긴 정말 어렵구나 하는 생각을 했습니다

돌아보며


금번 작업은 보기엔 별거 없습니다. 기능한개가 추가 되었고, 사이트 외형적으로도 거의 변한게 없습니다.




그러나,
5,000여 라인의 코드 삭제가 있었고, 2,200 여 라인의 코드 작성이 있었습니다.. 이 작업은 단 이틀만에 수행되었고요..
훨씬 많을줄 알았는데 이거밖에 안돼 같은 생각이 들지만, 범용성을 위한 코드 리팩토링은 싴갤러스를 운영하면서 처음인거같습니다.

코드자체가 대단한것도 아니고 난이도가 있는 코드도 아니지만, 짧은 시간내에 끝내려고 일정을 빡빡하게 잡았고, 오히려 시간이 타이트했기때문에 한줄한줄 쓸모없이 작성하지 말자 이렇게 임했던 느낌입니다. 유저 수요도 고려하고, 중간에 기획을 바꾸기도 하면서..
개인적인 성취를 이룬 느낌이 더 강한 업데이트였습니다. 구조 통일도 했으니 앞으로 레이드쪽에 더 많은 기능 추가가 있을....수도 있겠죠?

다음엔 더 재밌는 글로 찾아뵙겠습니다~
2018/09/17 09:43 2018/09/17 09:43

앱 업데이트는 매번 참 두근거리는 일입니다. 
검수를 받기때문에 웹 처럼 빠르게 업데이트가 불가능하고(상대적으로), 기기의 이상 유무, 앱 설치와 제거 여부등 보고 있자면 흥미로운 통계가 많기 때문입니다.

사실, 싴갤러스는 모바일 레이아웃을 지원하기때문에 네이티브로 앱을 구성할 필요가 없고, 굳이 쓴다면 푸시 기능때문에 앱을 존속시키고 있는 것인데요. 그래서 그런가 많은 공수를 들이고 있지 않은것도 사실입니다. 그래도 이번에는 아이콘 그림도 많이 교체했고, 자주 볼 수 없는 화면에 신경도 (...) 썼습니다. 예를 들면 서버를 선택하는 화면에서 UI의 색이 바뀐다던지하는...

기본 웹에서 지원하는 아래로 끌어서 새로고침하는 기능도 넣어보았습니다. 이젠 당연하게 여겨지는 기능이고..
또, 안드로이드에서 갑자기 네트워크 문제가 발생했을경우 에러 다이얼로그 폭탄이 나오는 문제들도 수정했고, 캐시가 계속 쌓여서 앱이 비대해지지 않도록 신경도 써봤습니다.

그외에도 뭐 ... 다 말하지 못하는 사소한 것들도 참 많습니다만 어쨌든, 싴갤러스 1.13 앱을 즐겨주세요!
2018/09/11 09:14 2018/09/11 09:14
삼성 덱스에서 앱을 시동하면, 모바일 기기 기준으로 실행된다.
그런데 아시다시피 DEX의 화면은 엄청나게 광활한데 앱 화면은 작디 작고 늘어나지도 않는다. 조금 더 크게 사용하고 싶을 수도 있다는 것이다.

이때 사용하는것이 Nougat 에서 추가된 멀티 윈도우 기능이다. 나보다 더 자세히 쓰여있는 삼성의 가이드 링크를 첨부하지만 그거도 눌러보기 싫은 사람들을 위해서 쓰자면

Manifest의 Application 부분에 다음을 추가한다.

android:resizeableActivity="true"


이때 구글의 문서를 보면 오타가 기재되있기도 한데, resiz e able 이다. resiz a ble 아니다. e를 뺴먹지 말자.
그리고 gradle의 complile sdk 옵션을 24 이상으로 설정해야한다. Nougat에서 추가된 기능이기 때문이다.
초기 실행되는 레이아웃 사이즈도 조절할 수 있어 보이는데, 그거까지 바라는 사람은 없을거같다. 여튼, 다원화시대니까,,,,

2018/08/31 13:18 2018/08/31 13:18
이번에 아이폰 아이폰X가 이슈가 되어서, 대응을 하기 위해 찾아보아서 정리겸 쓴다. 사실 어이없을떄 더 많이 쓰는 느낌이지만

아이폰 X가 노치 디자인을  채택함으로서, 아이폰에는 기존에 없던 새로운 개념이 생겨났다.
바로 이런 글들이다

iPhone X용 앱 업데이트하기 - iOS - Apple Developer - (Korean)

Human Interface Guidelines (iPhone X)

그런데 이건 노치 디자인을 얼마나 건드릴지에 관한 문제이고, 스토리보드를 쓰지 않는 앱에선 가이드라인 설정이 매우 어렵고, 그렇다고 스토리보드로 넘어가자니 또 작업량이 너무 많을것 같았다. 나는 그냥, 런치 이미지를 세팅해서 화면을 가득 채우고 싶을 뿐인데 왜 이런글을 읽는지도 모르겠고.  가이드라인을 쓰고 빌드해보려니 최소 iOS 버전을 올리라고 하고. 여간 번거로운게 아니었다.

다들 알겠지만, 런치 이미지는 image.xcassets 에서 아이콘과 함께 관리된다. 그런데 이 고민의 문제는 여기에 아이폰 X가 없었기 때문에 삽질을 시작했던건데, 그런 고민을 하고 있는 분이라면 당장 하고 있던거나, 검색창을 멈추길 바란다.

그냥, New를 해서 새로운 런치 이미지 보드를 만들면 가장 상위에 아이폰X가 있다 -_-
쓰던 런치 이미지들 그대로 옮겨서 다시 넣어주고, 아이폰X용 런치 이미지 넣어주면 아주 화면에 그득그득 꽉꽉 표시된다...
도대체 왜 이런지 알수가 없는데, 왜 기존 보드에 업데이트를 안해주고 new를 해야만 신규 기기에 대응할 수 있게 되는지 의문이다.
하여튼 새로운 런치 이미지 set을 만들고, 등록해주면 정상적으로 나온다. 오늘도 정말 하... 욕만 나온다.
2018/08/24 16:08 2018/08/24 16:08
어제, 오늘, 내일을 표현하는 말은 여러개가 있는 것 같다.
내일이나 어제라는 말 조차도 한자이지만, 굳이 격식을 차린다고 작일 명일 등으로 표기하는 경우가 있는 것 같은데, 이번에 오늘을 표현하는 말 중에 본일 이라는 말을 알게 되어서 기록 겸 남긴다.

어제 :: 작일, 전일 (예) 전일 보내드렸던 메일을 참고 부탁드립니다.
오늘 :: 금일, 본일 (예) 금일 방문하고자 합니다
내일 :: 명일, 익일 (예) 명일 처리 예정입니다.
특정일 :: 즉일, 당일 (예) 추석 당일에 시행될 예정이다.


2018/08/03 09:03 2018/08/03 09:03
지문인식 기능을 개발할 일이 있어서 개발을 완료했는데, 뒤늦게 다른 기기에서 동작을 안하는걸 발견했다.
분명히 테스트 기기 (Galaxy S6) 에서는 잘됐었는데, Pixel 및 Galaxy S8+ 에서는 동작을 하지 않는게 의아했다.
정확히는, 아예 안되는건 아니고 앱전환 화면으로 들어간다던지 해서 액티비티가 pause 후 resume 되면 멀쩡하게 동작하는걸 발견해서,
결국 로그를 찍어보게 되었는데 다음과 같은 에러가 발생하고 있었다

5, 지문 인식 작업이 취소되었습니다.


5가 뭔지 찾아보니까 FINGERPRINT_ERROR_CANCELED 로 정의되어 있었다.
단순히 FingerprintManager를 호출했을뿐인데 에러가 발생해서, onError 때문에 지문인증을 할 수 없게 되지만, 이상하게 resume 되면 매니저가 정상 동작하는게 좀 어이가 없기도 하고..

그래서 검색을 좀 해봤는데 이 글을 발견할 수 있었다.
@Override
    public void onAuthenticationError(int errMsgId, CharSequence errString) {
        if ( errMsgId == FingerprintManager.FINGERPRINT_ERROR_CANCELED) {
            stopListening();
            restartListeningToFingerprint();
        }
}


코드는 별 달리 읽을것도 없고, 에러메세지 5번이 발생할 경우 Listening 을 멈추고 재시작하라고 되어있다.
즉 Android 구현상에 문제가 있다는건데... 왜 내 Galaxy S6 에서는 문제가 없었을까? 하니 링크된 구글 이슈트래커에서 내용을 발견할 수 있었다

This issue is not reproducible on all devices. The Samsung Galaxy S6 doesn't return this error whereas the Pixel XL emulator does.


그냥 적혀있는 댓글이라 100% 이렇다! 할 수는 없지만 일단 나같은 사람이 더 있다는거에 위안을 삼고..
이제 본격적으로 고쳐보자. 별로 고칠 내용도 없다.

상기 예문의 코드에서는 에러가 발생시 재시작 하라고 되어 있는데 정확히는 CancellationSignal 를 건드려야 한다.
CryptoObject를 저장해놨다가 다시 Listening 을 시작하고 하는 식으로 구현해봤으나 별 효과가 없고, 그냥 이 글에 나와 있는것 처럼 다음과 같이 작성하는게 직빵이다

@Override
    public void onAuthenticationError(int errMsgId, CharSequence errString) {
        if ( errMsgId == FingerprintManager.FINGERPRINT_ERROR_CANCELED) {
            return;
        }
}
2018/07/17 09:22 2018/07/17 09:22
이크립스 프로젝트를 이제야(-_-) 안드로이드 스튜디오로 마이그레이션하게 되었는데 에러가 지속적으로 발생했다.
이것저것 들여다보고 있는 와중에 gradle 에 새로 도입한 aapt2 가 문제가 되고 있단걸 알게 되었다.

해결법은 간단한데, 그냥 비활성해버리면 되는것이다. 하지만 이건 프로젝트를 돌리는데 급급한거기때문에.. 결국 다 고쳐야된다.

gradle.properties

파일에 내용을 수정한다. 없으면 루트 디렉토리 최상단에 만든다

android.enableAapt2=false


작성!
2018/06/27 16:50 2018/06/27 16:50
docker에 mysql을 올려서 사용하고 있는데, 어느 순간 갑자기 어디서도 안붙어진다. 
localhost를 바라보고 있는 서비스 소스 측에선 사용이 되는데 도저히 외부에선 붙어지지가 않았다.

별도의 테스트 디비가 없기때문에 접속이 안되서 로컬호스트로 처리도 못하는 상황. 
mysql로 붙는 속도가 현저히 느려져서 skip-name-resolve 옵션을 켜기도 했는데..

권한이고 iptables고 ufw 고 확인안해본게 없는데 지푸라기라도 잡는 심정으로 docker를 재시작했더니 그냥된다.
그냥 docker-proxy가 얌전히 맛이가서 dns조회쪽에 문제가 됐던게 아닌가한다. 저 옵션은 사실 켜야될 필요가 없는데...
간만에 황당한거 겪어서 기록으로 남긴다.
2018/04/23 02:42 2018/04/23 02:42
제목을 지을땐 항상 희한한 기분이다.
문법이 맞나 싶어가지고.. 어쨌든 백업할때 느꼈던건데, 나는 docker를 그냥 디스크만 옮기면될줄알고 다른디스크에 똑같은 경로로 옮겼다.
그리고 docker_opt를 다시 잡아준 후에 docker start 를 통해 컨테이너를 실행하려니 정말 죽어도 안되는것이다.
별수를 다 써봤는데도 안되었다.

정말 이상한 일이라 검색해봤는데 나같은 사례가 없었다.
하긴 누가 디스크 to 디스크로 옮기는일을 할까.. 여튼 해답은 다음과 같다.

/docker/containerd/daemon/


해당경로에는 현재 돌아가고 있는 컨테이너의 정보들이 존재한다.
여기를 깔끔하게 지워주면 돌아가게 되는데 문제는 바로 여기

io.containerd.metadata.v1.bolt/meta.db


이 파일이다. 이 db파일내에 컨테이너 이름이 들어가있으면 docker는 해당 컨테이너가 이미 running 중이라고 판단한다.
즉, docker를 정상적으로 exit 한 상황이 아닌 상태에서 그냥 파일을 옮기면 meta.db엔 running 중인 상태로 기록되어 있기때문에 절대 돌릴 수가 없다.

해결법은 그냥 docker를 다시 깔고, 깔끔한 meta.db를 덮어쓰면된다. (데몬내에 다른 폴더들은 그냥 정리)
2018/03/15 15:51 2018/03/15 15:51