Monday, October 10, 2011

[Javascript] Facebook History Manager 분석 (2)

저번 포스트에서 initialization 하는 부분 까지 봤습니다.
다른 부분들을 util 들이라고 보시면 되고, 그 다음 중요한 부분인 go 부분을 살펴보고 마무리 할까 합니다.

go 는 parameter로 c, e, f를 받아오는데요.
우선 History를 지원하는 최신 Browser의 경우는 입력된 c를 이용하여 이동을 하게 됩니다.(history back 같이) 이는 제일 간단히 가고 싶은 url로 이동하게 됩니다. h 등을 설정하고 하는 부분이 있는데요. 이 부분은 Facebook의 url에 관련되어있기 때문에 자신이 하고자하는 형태에 다라 변경 해줄 수 있습니다.

이제 지원하지 않는 Browser의 경우를 살펴보도록 하겠습니다.
ie 8 이하의 Browser의 경우엔 이미 만들어 놓은 iframe의 변화를 살펴야 하기 때문에 750ms 마다 url을 체크 하여, 변화가 있을 경우 그 url을 이용하여 사용자의 url을 변경 시킵니다.
그 외 Hash event를 지원하는 Browser의 경우는 변화에 따라 Hash를 분석하여 url을 변경 시켜줍니다.

위와 같이 전체적인 로직은 간단합니다.
이대로 마무리하면 재미가 없을 것이라 생각 되기 때문에, Facebook 개발자들이 작성한 재밌는 Point를 살펴보도록 하겠습니다.

먼저 "#!" 이 부분인데요. Twitter에서도 이 방식을 택했습니다. 왜 그런지는 정확히는 모르겠지만, 코드 상으로 볼때는 2중으로 검증을 하기 위해서가 아닐까 합니다. 기존의 라이브러리들은 대다수 # 만으로 구분을 하곤 했는데, 잘 못 되는 경우를 좀 더 보기 위해서 해놓은 의도적인 행위가 아닐까 합니다.  동료 분이 찾아주신 바에 의하면 크롤링이 가능한 Hash처리였네요. 공부가 부족했습니다.^_^ (참고 링크) 우선 #으로 뒤에 부분을 분리 후 !가 맞는지를 check하고, !는 확인 후 삭제 하여 의미 없게 처리가 됩니다.

그리고, 불필요한 double go back(?)을 방지하기 위한 팁으로 업데이트가 될 때마다, Lastchanged 시간을 기록하여 방지를 하고 있습니다. 이것이 이론적으론 한 400ms인가 봅니다. 이렇게 많이 check하고 있네요.

그 외에엔 시간을 들여서 오류가 나지 않도록 하는 Code들이라 찬찬히 읽어보시면 되지 않을까 합니다.^_^ 전 그럼 빠른 시간 내에 jQuery Ajax History를 작성하여 공개할 수 있도록 하겠습니다.

그럼~

Friday, October 7, 2011

[Javascript] Facebook History Manager 분석 (1)

요즘 SNS시대가 도래하고, 상하로 이동하는 Scroll Navigation의 형태를 지니는 사이트들이 많아지고 있습니다. Facebook/Twitter가 가장 대표적이고, me2Day, G+ 도 이와 같은 형태를 지니고 있습니다.
기존 Page Navigation에 비해서 마우스 스크롤로 간편하게 움직일 수 있는 이러한 형태는 치명적인 단점을 가지고 있는데요. 하단으로 상당히 내려간 후에, 그 페이지를 벗어난 경우 다시 돌아올 때 불편함을 가지게 될 수 있습니다.

이러한 단점을 극복하기 위해서 Facebook는 History Manager 라는 Object를 만들어 이러한 문제를 약간이나마 해결을 하였습니다. 기존에 photo 등을 클릭하면 End Page로 가던 것을 까만 배경의 Layer 형태로 바꿨었고, 이번 개편에서는 History Manager를 이용하여 Back에도 대응할 수 있도록 진행을 하였습니다. 사용자가 Url을 Copy하게 되면, 그 것이 바로 End Page로 갈 수 있게 하여 Share가 용이하게 되었다는 점에서도 상당히 좋은 선택이라고 보고 있습니다.

UX의 장단점에 대해서는 사용자들과 연구원들이 좀 더 판단 해줄 것이라 생각을 하고, 저는 기술쟁이 입장에서 History Manage에 대한 분석으로 접근하여, 이후 jQuery용 Ajax History Plugin을 제작/공개할까 합니다.(많이 써주실랑가 모르겠네요.^_^)

우선 전체 소스는 여기서 참고하시면 됩니다. (Source by jsFiddle)

첫 번째로 init에 대해서 보고 넘어갈 수 있도록 하겠습니다.

Facebook에서는 History를 위해서 pushStaus 를 이용합니다.
문서예제를 보시면 어떤 기능인지에 대한 이해에 도움이 될 것입니다.
현재 이 기능은 아직 널리 퍼진 기술이 아니므로 현대 Browser 외 에는 지원을 하지 않고 있습니다.
그 이전의 Browser 사용자들을 위해서 hashchange Event 와 iframe을 이용하여 history 기능을 구현 하였습니다.

pushStatus를 이용하게 되면, url이 변경 되지만 Page 가 replace되지 않으므로 간단히 List 위에 레이어를 띄울 수 있게 됩니다. 또한, 변경 된 url을 이용해 End Page link도 사용자에게 전달 할 수 있게 됩니다.

이제 지원되지 않는 Browser들을 위한 Logic을 살펴보도록 하겠습니다.
이제 IE 7 이하 의 "hashchange" 이벤트를 지원하지 않는 Browser와 지원하는 Browser 나뉘게 됩니다. (문서 참조)
일반적으로 화면이 변화 하지 않으면서도 사용자의 location 을 변경 하고 싶을 때 "#"hash를 사용하게 됩니다. 이를 이용한 방법이 제일 많이 사용되던 Ajax History 방식이였습니다.
이것이 변경 되는 것을 인지 할 수 있는 Browser들은 단순히 Event Listen을 하게 두었고, 지원하지 않는 Browser의 경우(IE 7 이하) iframe에 현재 정보를 전달 하여, onLoad Event를 사용하도록 하였습니다.

이것이 기본적인 History Manager가 동작을 하기 위한 기본 설정입니다.
다음 Post에서는 이 설정을 가지고 실제로 어떻게 진행이 되는지 살펴보도록 하겠습니다.^_^

그럼~


Wednesday, October 5, 2011

[Google Appengine] Flickr API 연동 하기

(주) 해당 내용은 제가 개인적으로 공부하는 것을 노트 하는 것이므로, 심도 깊은 내용을 기대하시긴 어렵습니다.

Flickr 와 연동 되는 Python library는 상당히 많습니다.
하지만, Google Appengine 에서 제약이 많이 있기 때문에 처음에 좀 당황했습니다.
그러다 찾은 것이 gaeflickrlib 입니다.
우선은 이 Library를 이용하고 이후에, 이 코드를 발전 시키던지 기존의 Library를 brach 해서 GAE에 맞게 만들어야 겠습니다.

우선은 Flickr에서 API key를 획득해야 합니다.
http://www.flickr.com/services/api/
이곳에 가면 한국어 버전도 있으니 이를 이용하면 될 듯 합니다.

가장 중요한 것은 API key / secret 을 획득하기 위해 자신의 APP을 만듭니다.
이후 API key / secret을 획득할 수 있습니다.

이후, gaeflickrlib를 이용하여 하고자 하는 작업을 진행 하면 됩니다.

예제는 다음과 같이 되어있습니다. (from Document)

from gaeflickrlib import GaeFlickrLib

flickr = GaeFlickrLib(api_key = 'some key',
                      api_secret = 'some secret',
                      token = 'some user\'s credentials')
photos = flickr.photos_search(text = '...')

다만 여기서 Token의 경우는 따로 받아서 진행 하는 경우에 설정 해주시면 되고, 할당을 받지 않은 경우는 api_key , api_secret 변수에 할당을 해주시면 작동은 됩니다. Token이 필요한 API의 경우에만 token을 설정 하면 됩니다.

금일은 소개 수준의 연동만 적고, 이후에 심화적으로 접근 해보도록 하겠습니다.
이 Library가 문서가 적어서 이거저것 만들어 봐야 겠네요. ^_^

그럼~

Friday, September 30, 2011

[PyCharm] PyCharm에서 Google Appengine 사용하기

(주) 해당 내용은 제가 개인적으로 공부하는 것을 노트 하는 것이므로, 심도 깊은 내용을 기대하시긴 어렵습니다.

근래에 intelliJ(http://www.jetbrains.com/idea/)를 소개 받고부터는 JetBrains 제품들에 상당히 흥미를 느끼고 있었습니다. 이유는 WebStorm(http://www.jetbrains.com/webstorm/)의 기능인데요. WebStorm은 HTML/CSS/Javascript의 기능을 따로 하나로 모은 솔루션이고, 언어의 특성에 따른 IDE에 WebStorm의 기능들이 들어가 있습니다.(intelliJ : Java / PHPStorm : PHP 등)

그러다보니, 자연스럽게 PyCharm(http://www.jetbrains.com/pycharm/)에 관심을 가지게 되었고 50% 할인 혜택이 있어서 이번에 구입을 하게 되었습니다.(약 5만원) 개발툴을 돈 주고 구입한다는 사실을 잘 이해 못하시는 분들도 있겠지만.. :)

사설이 길었네요. 이제 어떻게 PyCharm에서 Google Appengine을 연동하는지 보도록 하겠습니다.(현재 버전 1.5.4) 참고로 제가 Mac만 사용하므로, Windows 사용자 분들은 약간 다를 수 있습니다.

우선 PyCharm은 IDE이므로 Project 단위로 진행이 됩니다.
그로인해, Project가 달라짐에 따라 항상 해주셔야 합니다.
그럼 우선 SDK 연동을 보도록 하겠습니다.

Google Appengine SDK연동
  1. 메뉴의 설정(Preference)으로 들어갑니다. // 아마 윈도우 버전은 Project Setting일 것입니다.
  2. 그 중에 Google App Engine 메뉴를 들어가 Enable Google App Engine support를 체크 합니다.
  3. 이후 SDK directory를 찾아줘서 넣어줍니다.
    1. Mac의 경우는 GoogleAppEngineLuncher.app 안에 위치하고 있습니다.
    2. 중요한 점은 "dev-appserver.py"가 있는 디렉토리를 선택 해주셔야 하는 점입니다.
  4. 이후 Account 설정을 해주세요.
Local Server 설정
  1. 개인 개발 환경에서 Luncher를 이용해서 바로 진행 할 수가 있습니다.
  2. 상단의 메뉴에서 Run 부분에서 Edit Configurations 을 통해 Luncher를 설정하게 되어있습니다.
  3. 기본에 Default로 되어있는 것은 그냥 두셔도 됩니다만, 만약에 Default를 수정해서 사용하시고 싶은 분들은 수정하여 저장 해두고 사용하셔도 좋습니다. 하지만, 개인적으론 그런 경우는 거의 없는 듯 합니다.
  4. Add New Configuration을 선택하여 "App Engine Server"를 선택 합니다.
  5. 그 다음, Name / Working directory / Port 등을 설정 합니다.
  6. 이 후 상단 메뉴에 자신이 생성한 Run이 생겼는지 확인 합니다.
Deployment 설정
  1. 이 것은 가장 간단 합니다.
  2. 상단 메뉴 > Tools > Google App Engine > Upload ... 을 선택 하시면 됩니다.
  3. 최초에는 Google Account를 입력하라고 하는 경우가 있습니다. 간단히 입력 해주시면 됩니다.

[참고이미지]
  • SDK 연동 / Add New Configuration / Local Server 설정 후



[Google Appengine] Application + Github

(주) 해당 내용은 제가 개인적으로 공부하는 것을 노트 하는 것이므로, 심도 깊은 내용을 기대하시긴 어렵습니다.

이 방법은 일반적이라기보단, 제가 선호하는 방법이므로 100% 이 방법이 맞다고 할 수는 없습니다.

제가 프로젝트를 생성하는 순서는 다음과 같습니다.
  1. Github에 새로운 Repository를 생성
    1. https://github.com/
  2. Tool들을 이용해 우선 Clone을 합니다.
    1. Terminal / shell 등을 이용.
    2. githug:mac 을 사용(http://mac.github.com/)
    3. 저같은 경우는 pycharm을 사용하는 데, 이 IDE가 github를 지원 합니다.
      1. 좋긴 한데 유료고 좀 비싼 편이라 적극 권장은 못하겠네요.
  3. Google AppEngine Dashboard 로 가서 Application을 생성 합니다.
    1. https://appengine.google.com
  4. 위에서 생성된 Application ID와 동일한 Directory를 Repository Root에 만듭니다.
    1. 나중에 Deploy 할 때, 이 명칭을 사용하므로 잘 맞춰주셔야 합니다.


그럼, 기존에 누군가 만들어둔 환경을 설정하는 방법은 어떻게 되는지 보겠습니다.
  1. 우선 Github에서 생성된 Repository를 Sync 받습니다.
    1. 위에서 언급된 툴을 이용하여 받으면 됩니다.
  2. IDE가 Google AppEngine Luncher를 지원하는 경우는 단순히 디렉토리만 맞춰주면 되더군요.
    1. 이 부분은 pycharm을 사용하시는 분들이 있다면 따로 언급하도록 하겠습니다.
  3. 일반적으로는 Google AppEngine Luncher를 사용하실 것입니다.
    1. 오른쪽 마우스를 클릭하게 되면 Add Existing... 이 있는데 이것을 위에서 생성된 Directory를 선택 하시면 됩니다.
  4. 이후엔 개발하고 commit/publish 를 하면 됩니다. 참 쉽죠잉.
^_^)~씨유!


Thursday, September 29, 2011

[Google Appengine] Datastore 사용 해보기

(주) 해당 내용은 제가 개인적으로 공부하는 것을 노트 하는 것이므로, 심도 깊은 내용을 기대하시긴 어렵습니다.

이제 Web app개발에서 가장 중요한 Data를 다루는 방법을 테스트 해봤습니다.
Google Apps Engine에서는 Datastore를 이용하여 Database를 사용할 수 있습니다.

재밌는 것은 Datastore Admin을 들어가도 Entity(DB의 Table정도 개념인 듯)를 생성을 할 수 없었습니다. 이것은 python의 경우 google.appengine.ext 의 db를 이용하여 진행해야 합니다.
이후, Entity를 구성하는 Class를 만들어서 이 Class.put()으로 Entity를 생성할 수 있습니다.

또, 주의점은 Local 에서 진행 되는 Datastore와 Service에서 되는 Datastore가 분리 되어있으므로, Local에서 아무리 데이터를 집어 넣어도 Admin으로 조회를 할 수가 없습니다.(처음에 왜 안되나 한참 고민 했네요. Deploy 후 고민 해결)

그럼 로컬에서 어떻게 볼 것인가?
에서 볼 수가 있습니다.(Port는 자신에게 맞게 변경해주세요)

Database의 Admin에 익숙하고 요즘 Database의 트렌드를 전혀 보고 있지 않다보니, 이러한 방식이 참 어색하긴 하네요. 흥미 있는 방법이긴 합니다.

그 외에는 DB를 다루는 것과 비슷하게 GQL을 이용해서 진행 할 수도 있지만, 객체처럼 사용해서 진행 하는 방법에도 익숙해질 필요가 있을 듯 합니다.(복잡한 조건문이 아니면, Key를 이용해서 값을 가져올 수 있는 듯 하네요)

[Python] Modules 공부

(주) 해당 내용은 제가 개인적으로 공부하는 것을 노트 하는 것이므로, 심도 깊은 내용을 기대하시긴 어렵습니다.

뭔가 만들 때, 개발자는 어떻게 묶을까를 고민을 하게 되는데요.

그럴 때, Python에서는 Modules라는 내용에서 이 부분을 해결 하고 있습니다.
그 중 제가 유심하게 본 부분은 Package 영역입니다.
(참고) http://docs.python.org/tutorial/modules.html#packages

The __init__.py files are required to make Python treat the directories as containing packages; this is done to prevent directories with a common name, such as string, from unintentionally hiding valid modules that occur later on the module search path. In the simplest case, __init__.py can just be an empty file, but it can also execute initialization code for the package or set the __all__ variable, described later.

즉, __init__.py 파일이 있는 디렉토리는 Package로 인식하여, 그 이하의 모든 파일들을 import할 수가 있게 됩니다.
또한, 디렉토리 명과 파일이 namespace의 역할을 하게 되는 듯 합니다.
# python에서는 namespace가 따로 있는거 같은데, 이것과 관련이 있는지는 아직 못 봤습니다.

예를 들자면, 다음과 같이 디렉토리가 구성 되면,






아래와 같이 Package를 구성하게 됩니다.
이를 이용하면 좀 더 깔끔하게 모듈들을 구성할 수 있을 것으로 보입니다. :)