Blog


다시 글을 좀 써봐야 할까

블로그를 너무 오래 그냥 내버려 두었나 보다.
가끔이라도 생각나는 것들, 고민한 것들, 공부한 것들을 기록해봐야겠다.




레진코믹스 RSS로 구독하기

  • 2015/04/17
  • Web

바쁜 사람들을 위한 한 줄 요약

Lezhin Comics Feed(https://lezhin-rss.update.sh/)에서 구독하시면 됩니다.

현재 동작하지 않습니다.

레진코믹스의 RSS를 제공하는 사이트를 만들었던 과정을 대략적으로 기록해 놓은 문서이다.

서론


레진코믹스(http://www.lezhin.com/)라는 웹툰 사이트가 있다. 여러 작가들을 데려와서 유/무료 웹툰을 서비스하거나, 이미 출판된 만화도 가져와서 볼 수 있게 했다.

레진코믹스 메인페이지. 세월호 1주기가 스크린샷을 촬영한 날이었기에 로고에 노란 리본이 달려있다.

네이버나 다음과 같은 포털에서 운영하는 웹툰 서비스와 비슷하지만, 적극적인 유료화 정책과, 나름 고수위(?)의 성인 컨텐츠를 제공하는 게 특징이다. 얼마 전에는 무슨 일이 있었는지 정확하게는 모르겠지만 레진코믹스 사이트를 방송통신위원회에서 차단하면서 이래저래 말이 많이 나온다. 나는 그거랑은 별개로, 레진코믹스에서 연재중인 레바툰이 이런 저런 커뮤니티 사이트들에 공유되면서 관심을 갖게 됬다.

나는 기본적으로 RSS 리더를 애용한다. 주로 들어가는 블로그나 사이트 게시판 등등을 가능하면 RSS로 구독하여 받아보고 있다. 물론, 네이버나 다음 웹툰도 그렇게 하고 있다. 다음 웹툰 서비스는 자체적으로 RSS 구독이 가능하고, 네이버 웹툰은 링크(홍민희라는 분이 만드셨다. 파이썬 행사에서 뵌적이 있는것 같은 느낌이…) 에서 구독할 수 있다. 그러나 레진코믹스는 RSS 구독을 지원하지 않았고, 다른 사람이 만든 구독 사이트도 없는 것 같았다.

Feed43(http://feed43.com/)과 같은 RSS 자동 생성 사이트를 이용할 수도 있었겠지만, 네이버 웹툰 구독 사이트처럼 한번 만들어 보기로 했다. 아마 시험기간이라 공부 말고 열심히 할 딴짓이 필요했던 것 같다.

지원하리라 마음먹은 대략적인 기능은 아래와 같다.

  • 모든 구독은 RSS 2.0과 Atom 1.0을 복수 지원한다.
    • 사실 별 차이점은 없지만, 그냥 둘 다 지원하기로 했다. 굳이 고르자면 Atom이 더 낫지만…
    • 레진코믹스의 API를 이용할 수 있다면 실시간 생성, 그렇지 않다면 매 시간마다 생성해서 캐
  • 개별 만화의 에피소드를 구독할 수 있다.
  • 새로 추가된 만화를 구독할 수 있다.
    • 왜냐면 새롭게 추가된 만화중에 보석같은 만화가 있을지도 모르니까?
  • 구독할 수 있는 만화들을 보여주는 웹페이지를 만든다.
    • 해당 페이지에서는 만화의 이름이나 작가의 이름으로 검색이 가능해야 한다.

현재는 위의 기능을 모두 구현했다. 만들어진 구독 사이트는 Lezhin Comics Feed(http://kb.update.sh/lezhin-rss/)에서 볼 수 있다. 레진코믹스 API를 사용할 수는 없었으므로, 매 시간 정각에 구독정보를 업데이트한다.

Lezhin Comics Feed 메인 페이지.

 

구현


만들기로 마음을 먹은 김에 바로 작업에 들어갔다. 일단 웹사이트를 만들어야 하는데, 내가 다뤄본 웹 프레임워크는 Python Flask밖에 없어서 선택권이 딱히 없었다. 어차피 빠른 개발을 하려면 결국 Python을 선택하긴 했을 것 같다

 

만화 및 에피소드 정보 가져오기

필요한 만화 및 에피소드 정보는 레진코믹스 웹사이트를 파싱해서 가져오면 될 것이라고 막연하게 생각했다. 그래서 레진코믹스 웹사이트를 켜서 이것 저것 봤는데… 분명히 동적으로 만화들을 처리하는데 ajax로 오고가는 데이터가 없었다.

가만히 보니, 처음 웹사이트의 html을 가져올 때, inline javascript로 만화나 에피소드 정보를 다 넣어서 받아오고 있었다! 이게 문제인게, 원래는 HTML을 파싱하거나, ajax call을 분석해서 API를 따라 쓰려고 했는데 이것이 불가능하다는 뜻이었다.

따라서, 적절하게 javascript를 파싱해서 만화 정보를 가져와야 했다. 우선은 requests 라이브러리를 이용하여 html을 가져와서, 이를 자체파싱-_-해서 사용했다. 이래저래 복잡하게 짤 수도 있겠지만, 딱히 퍼포먼스가 문제될 것 같지는 않았기에(물론 나중에 문제가 100% 생기지만) 내가 원하는 데이터의 시작 단어와 끝 단어를 기준으로 문자열을 잘라내어, json 처럼 취급했다.

html의 inline javacript로 정보가 담겨 있다.

그래서 이래저래 고생하긴 했지만, 깔끔하게 json을 뽑아낼 수 있었다. 뽑아낸 만화 및 에피소드 정보는 자체 API를 만들어 사용할 수 있게 했다. 이는 아래와 같다.

 

데이터 저장 및 업데이트

얻어온 정보는 sqlite를 이용하여 저장해놓고 사용하기로 했다. 이는 Flask-SQLAlchemy를 통해 ORM으로 단순하게 해결했다. 만화와 에피소드에 맞는 모델만 적절하게 정의해놓으면 끝이었다.

문제는 업데이트에 있었다. 그냥 반복문을 돌면서 전체 만화와 에피소드를 가져오는 것은 시간이 너무 오래 걸렸다. (이 당시 만화는 약 700개, 에피소드는 약 60,000화 이상이었다. 당연히 오래 걸린다.) 전체 만화와 에피소드 목록을 가져오는데 약 13분이 소요되었다.

대부분의 시간 소요는 네트워크 I/O 때문에 발생할 것이라 예측하고 multiprocessing을 이용해서 8 프로세스로 동작하게 했다. 결과는 만족. 2분 정도만에 모든 만화와 에피소드 목록을 가져올 수 있었다.

만화 및 에피소드를 가져온다. 8 프로세스로 동작해서 약 2분만에 모든 만화와 에피소드 정보를 가져올 수 있다.

또, 레진코믹스의 웹 사이트 구조가 변경될 경우 업데이트가 정상적으로 이루어지지 않을 것이다. 이 경우를 판단하기 위해 업데이트 중 파싱 에러가 발생할 경우 나에게 에러 정보를 gmail을 통해 보내도록 만들어 놓았다. 이젠 간단하게 cron에 매 시간 정각에 동작하도록 추가하면 끝.

 

구독정보 생성

만화 및 에피소드 정보를 모두 가져왔으니, 이젠 이를 Atom과 RSS로 만들어서 제공하자. Atom 1.0의 경우Flask는 Werkzeug를 통해 동작하므로, Werkzeug의 Atom Syndication 문서를 통해 구현하면 된다. RSS 2.0은 PyRSS2Gen을 통해 제공하기로 했다.

Firefox로 열어본 Atom 구독정보

 

메인페이지 제작

사실 위의 작업보단 웹에서 구독할 수 있는 만화들을 보여주는 메인페이지 제작이 더 큰일이었다. 왜냐하면 내가 웹을 잘 못하니까… 그래서 대충 대충 간단하게 끝냈다.

기존 레진코믹스 로고를 이용해 간단하게 만들어본 RSS 개(…)

우선 JQuery와 Bootstrap을 써서 간단하게 틀을 잡고, 제목대로 만화를 정렬해서 페이지당 50개씩 보여주기로 했다. 이 작업을 하면서 처음으로 Flask-SQLAlchemy에서 pagenate라는걸 사용할 수 있다는 것을 알았다. 여태까지 페이지 작업하는 코드를 일일히 짜줬는데, 이 녀석이면 간단하게 해결 할 수 있다.

검색같은 경우에는 처음에는 Whoosh 사용을 고려했지만, 한글 설정이 미묘했고, 굳이 많지 않은 제목과 작가 검색에 검색 엔진까지 붙여 사용할 필요성을 느끼지 못해 사용하지 않았다.

 

결론


결과적으로 사이트는 간단하게 완성할 수 있었다. 처음 목표로 했던 기능은 모두 구현했으므로, 특별히 이상이 생기지 않는 한 더 이상 건드릴 일은 없을 것이다.

본 프로젝트의 전체 소스코드는 https://git.update.sh/nesswit/lezhin-rss/tree/master 에서 확인할 수 있다. 만약 이 프로젝트를 클론해서 직접 실행해보고 싶다면, app/db 폴더를 생성하고, update.py 파일에서 mail 보내는 부분을 모두 지운 뒤, update.py를 실행시켜 db를 생성하고, debug.py 파일로 임시 웹서버를 실행해보면 된다.




Yosemite에서 Synergy 직접 빌드하여 사용하기

멀티플랫폼간 마우스 및 키보드를 공유해주는 유명한 프로그램인 Synergy(http://synergy-project.org)가 어느새 유료화되었다. 다운로드 페이지로 가보면, 1인당 5달러를 결재하면 평생 사용할 수 있다… 라고는 한다.

하지만 원래 Synergy는 오픈소스 프로젝트다. 그것도 GNU 라이센스가 적용되어 있는 프로젝트이다. 이는 Synergy의 Github 페이지(https://github.com/synergy/synergy)로 가보면 확인할 수 있다. 따라서 그냥 Github에 공개된 코드를 직접 빌드하여 사용하기로 했다. 작업한 환경은 OS X 10.10 Yosemite이다.

http://synergy-project.org/wiki/Compiling 에 가보면 환경별 컴파일 방법이 간단하게 설명되어 있다. 따라서 나는 해당 내용을 따라서 Synergy를 컴파일해서 사용해 보기로 했다.

일단 필요한 의존성 모듈을 설치해야 한다. 나는 brew를 이용해서 cmake, qt를 설치했다.

$ brew install cmake
$ brew install qt

 

의존성 모듈을 설치한 후에, 공식 문서에 나와있는 것과 같이 수행한다.

$ ./hm.sh conf -g1
Mapping command: conf -> configure
Running setup…
Setup complete.
Error: Arg missing: –mac-sdk <version>

 

그럼 위와 같은 오류가 발생한다. mac sdk 옵션이 없어서 발생하는 오류인 듯 싶어 옵션을 주어 실행해봤다.

$ ./hm.sh conf -g1 –mac-sdk 10.10
Mapping command: conf -> configure
Error: Arg missing: –mac-identity <name>

 

이번에는 mac identity 옵션이 없다고 한다. 그럼 준다. 일단 test라고 주었다.

$ ./hm.sh conf -g1 –mac-sdk 10.10 –mac-identity test
Mapping command: conf -> configure
cmake version 3.0.2

CMake suite maintained and supported by Kitware (kitware.com/cmake).
Creating dir: build/release
Entering dir: build/release
CMake command: cmake -G “Unix Makefiles” -DCMAKE_BUILD_TYPE=Release ../..
— The C compiler identification is AppleClang 6.0.0.6000054
— The CXX compiler identification is AppleClang 6.0.0.6000054
(중간 생략)
— Looking for pthread_create in pthread
— Looking for pthread_create in pthread – found
— Found CURL: /usr/lib/libcurl.dylib (found version “7.37.1”)
— OSX_TARGET_MAJOR=
— OSX_TARGET_MINOR=
CMake Error at CMakeLists.txt:168 (message):
Mac OS X target must be 10.x
— Configuring incomplete, errors occurred!
See also “/Users/nesswit/Downloads/synergy-master/build/release/CMakeFiles/CMakeOutput.log”.
Going back to: /Users/nesswit/Downloads/synergy-master
Error: CMake encountered error: 256

 

색다른 오류가 나를 반겼다. 보아하니 OSX_TARGET_MAJOR와 OSX_TARGET_MINOR 옵션이 적용이 되지 않은듯 했다.

이를 해결하기 위한 간단한 patch 파일을 작성했다. 자세한 내용은 아래와 같다.

 

해당 패치를 적용하고 실행한 결과는 아래와 같다.

$ ./hm.sh conf -g1 –mac-sdk 10.10 –mac-identity test
Mapping command: conf -> configure
cmake version 3.0.2

CMake suite maintained and supported by Kitware (kitware.com/cmake).
Entering dir: build/release
CMake command: cmake -G “Unix Makefiles” -DCMAKE_BUILD_TYPE=Release -DOSX_TARGET_MAJOR=10 -DOSX_TARGET_MINOR=10 ../..
— OSX_TARGET_MAJOR=10
— OSX_TARGET_MINOR=10
— Configuring done
— Generating done
— Build files have been written to: /Users/nesswit/Downloads/synergy-master/build/release
Going back to: /Users/nesswit/Downloads/synergy-master
QMake command: qmake gui.pro -r -spec macx-g++ “MACX_LIBS=-framework ApplicationServices -framework Security -framework cocoa -framework ServiceManagement” QMAKE_MACOSX_DEPLOYMENT_TARGET=10.10 QMAKE_MAC_SDK=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk
Entering dir: src/gui
Going back to: /Users/nesswit/Downloads/synergy-master

 

생각대로 잘 동작한다. 이대로 빌드를 진행하자.

$ ./hm.sh build
Entering dir: build/release
Scanning dependencies of target arch
[ 0%] Building CXX object src/lib/arch/CMakeFiles/arch.dir/Arch.cpp.o
(중간 생략)
Log: Deploying plugins from “/usr/local/plugins”
Log: Created configuration file: “Synergy.app/Contents/Resources/qt.conf”
Log: This file sets the plugin search path to “Synergy.app/Contents/PlugIns”
Going back to: /Users/nesswit/Downloads/synergy-master
Error: [Errno 2] No such file or directory: ‘/Library/Frameworks/QtCore.framework/Contents/Info.plist’

 

내가 설치한 qt는 brew로 설치했기 때문에 /Library/Frameworks/ 아래에 있지 않다. 따라서 해당 경로를 수정해야 한다.

이는 아까 패치파일을 적용한 ext/toolchain/commands1.py 파일의 826번째 줄 쯤에 있다. 해당 코드를 아래와 같이 수정한다.

 

이후, clean한 후 root 권한으로 다시 빌드했다.

$ ./hm.sh clean
(생략)
$ sudo ./hm.sh build
Entering dir: build/release
[ 0%] Building CXX object src/lib/arch/CMakeFiles/arch.dir/Arch.cpp.o
(중간 생략)
WARNING: Plugins = PlugIns
Going back to: /Users/nesswit/Downloads/synergy-master

 

경고.. 가 뜨지만 더 이상은 그냥 무시하기로 했다.

그럼, 정상적으로 생성된 Synergy.app 파일을 bin 폴더에서 확인할 수 있다.




Windows 8의 바탕화면 우클릭 메뉴가 느리게 작동할 때

Bootcamp로 사용하는 Windows 8.1의 바탕화면 우틀릭 메뉴가 엄청나게 느리게 동작하기 시작했다. 관련 자료를 찾아보니 그래픽 카드 드라이버를 설치하면서 등록된 우클릭 메뉴 하나가 이상하게 동작하기 때문인 듯 했다.

windows 8과 windows 8.1에서 발생하며,  NVIDIA CPL Context Menu Extension(바탕화면에서 NVIDIA의 우클릭 메뉴)가 문제가 되는 경우가 대부분이다.

해결 방법은 다음과 같다.

1. http://www.nirsoft.net/utils/shexview.html 에서 ShellExView를 다운받는다.

2. 다운받은 ShellExView를 우클릭하여 관리자 권한으로 실행한다.

3. 메뉴의 options에서 Filter by Extension Type의 Context Menu를 선택한다.

3.1 혹시 NVIDIA CPL Context Menu Extension 란 녀석이 있다면 그 녀석을 클릭하고 좌측 상단에 빨간 버튼을 눌러 중지시킨다. (없다면 4번 항목으로.)

3.2 메뉴의 options에서 Restart Explorer를 클릭한다.

3.3 바탕화면에서 우클릭하여 문제가 해결되었는지 확인한다. (해결되지 않았다면 4번 항목으로.)

3.4 문제가 해결되었다면, NVIDIA의 우클릭 메뉴가 문제다. 딱히 사용하지 않아도 지장이 없다면 여기서 완료. 이후 항목을 진행할 필요는 없다.

4. 리스트 중 분홍색 배경을 가진 녀석들은 서드파티 프로그램에 의해 설치된 녀석들이다. 이 녀석들을 모두 선택한다. (ctrl 키를 누른 채로 클릭하면 여러 항목을 동시에 선택할 수 있다.)

5. 좌측 상단의 빨간 버튼을 눌러 중지시킨다.

6. 메뉴의 options에서 Restart Explorer를 클릭한다.

7. 바탕화면에서 우클릭하여 문제가 해결되었는지 확인한다. (해결되지 않았다면, 당신은 망했다. 윈도우 기본 Shell extension에 의해 발생했거나 Shell extension에 의해 발생한 문제가 아닐 가능성이 있다.)

8. 해결되었다면, 4~5번 항목에서 중지했던 녀석들 중 하나만 다시 초록 버튼을 눌러 활성화시킨다.

9. 다시 문제가 발생할 때 까지 6-8번 항목을 반복한다.

10. 다시 문제가 발생하였다면 방금 다시 활성화시킨 그 녀석이 문제다. 이름과 경로를 잘 보고 검색하여 문제를 해결하거나, 그냥 해당 extension을 비활성화시킨 채 사용하자.

 

출처: http://social.technet.microsoft.com/Forums/windows/en-US/5353106e-5b19-4a26-8446-72bedf40b169/rightclick-context-menu-in-desktop-appearing-slow-win-81?forum=w8itprogeneral




디자이너의 일상

designer




Dictionary for AP named U+Net****

U+Net**** 의 비밀번호 규칙은 의외로 간단하다. Perl을 이용해서 간단히 U+Net**** 용 dictionary를 생성해보았다.

아래 코드를 uplusnet_dict.pl 라는 이름으로 저장한 후,

$ perl uplusnet_dict.pl > uplusnet.dict

와 같이 실행해주면 된다.

 

 

 




Google에서 응용 프로그램 지정 암호를 얻어야 합니다.

  • 2014/02/14
  • OSX

OSX 10.9.1의 Mail client를 구글 계정을 이용하여 IMAP으로 동기화하려고 하니, 뜬금없이 “Google에서 응용 프로그램 지정 암호를 얻어야 합니다.”라면서 계정 연동이 되지 않았다.

한국어로 바로 검색해 보았으나 해결방법이 보이지 않아 영어로 검색하니 바로 해결되었다. 아래 링크를 참조.

https://support.google.com/mail/answer/1173270?hl=en

(혹 위 링크가 정상적으로 동작하지 않는다면, Authorizing applications & sites page 페이지로 이동하여 새로운 비밀번호를 생성한 후, 구글 계정 비밀번호 대신 생성된 비밀번호를 입력하여 계정 연동을 시도하면 된다.)




Sudoku Solver

Sudoku Solver는 스도쿠 게임의 해법을 찾아주는 어플리케이션입니다.
어려운 스도쿠 게임에서 한계에 봉착했을 때, 여러분들께 활로를 제공해 드립니다.
친구, 직장 동료와의 내기에서 승리하십시오!
– Google Play Store의 Sudoku Solver 설명문

위에서 말한것과 같이, Sudoku Solver는 스도쿠(스도쿠가 뭔지 모르신다면 여기 참조)의 해답을 찾아주는 어플리케이션입니다.

어느 날인가, 갑자기 페이스북에 스도쿠를 풀어주는 프로그램들을 만들어서 올리는걸 보고 ‘아, 나도 하나 만들어볼까?’ 해서 만들어진 어플리케이션입니다. 페이스북에 갑자기 스도쿠 프로그램들이 올라온 까닭이 KAIST 학생들의 Assignment 이었기 때문이라 들었지만 Command Line Interface로 만들면 스도쿠를 입력하기 힘들었기 때문에 GUI로 제작하리라 마음을 먹었습니다.

요새 계속 사용해서 손에 익은것이 JAVA였고, 그중에서도 Android Application을 계속 만들고 있었기 때문에 Android Application이 된 것 뿐이지 사실 큰 이유는 없었습니다. 애초에 스도쿠를 풀어주는 Object는 따로 구현이 되어있어서 터미널에서도 충분히 사용할 수 있습니다.(다만, 스도쿠를 입력받는 부분과 해결한 스도쿠를 출력하는 부분을 따로 만들어줘야 하겠지요.)

풀이를 완료한 후에 실행 시간을 보여주는건 단순히 필요했다기 보단 공간이 남길래(…) 넣었습니다. 만약 시간이 난다면 OCR 기능을 추가해서 카메라로 비추면 자동으로 스도쿠를 풀어주는 기능도 추가를 하고싶습니다.

다운로드는 아래 버튼으로 할 수 있습니다.

Get it on Google Play




HTML5로 만든 오픈소스 퍼즐 게임 엔진 PuzzleScript

  • 2013/10/09
  • Web

http://www.puzzlescript.net

PuzzleScript는 HTML5로 제작한 퍼즐 게임 엔진이라고 한다. 홈페이지에서 간단하게 퍼즐 게임을 제작하는 방법을 설명하고, 실제로 제작해 볼 수 있는 환경을 제공한다.

Heroes of SokobanHeroes of Sokoban 2, Dang I’m Huge 등의 게임이 PuzzleScript로 제작되었다.

이하 프로젝트 페이지에 게시되어 있는 설명

PuzzleScript was developed by me (with the assistance/feedback of many other people + tools), Stephen Lavelle (@increpare). Programming puzzle games isn’t all that hard in the grand scheme of things, but the barrier to entry is way higher than it needs to be.

It’s not a general purpose game making tool, it’s not even a general purpose puzzle game making tool. Or even a avatar-based turn-based puzzle game making tool – games likeDROD don’t work, or games with very nuanced behaviours, like Puzzles proved impossible. But it is a tool, and I think it might prove handy/enabling for a number of people, if one is accepting of its limitations.

I’ve worked on a lot of puzzle games, and decided on a particular group of those that could be handily modelled with a scripting language. I’ve seen someone do a similar pattern-matching system before (I can’t remember who, though), but it was a lot less flexible – the movement system in this engine is what gives it its real power.

Getting the engine out the door, so to speek, took several weeks of full-time, unreumerated work, and no doubt there’s plenty more to come. I am not a wealthy man, I’m an impoverished, self-employed independent game developer whose involvement with such projects amounts to happy indiscretions. If you appreciate this piece of software, please consider chipping some money my way, okay?

I’ve you’ve made something cool with the engine, please let me know ( analytic@gmail.com or @increpare ) – I’d love to highlight (and maybe even host as examples) wonderful things that people’ve made with this.




쿨가이 Bitmap

cool1

cool2

cool3

안드로이드 Bitmap을 다룰 때에는 꼭 OOM에 유의합시다.