2013년 1월 28일 월요일

오른쪽 클릭을 막는 웹페이지들


 웹 서핑 하다보면 오른쪽 클릭이나 드래그 등이 안되는 웹페이지를 심심찮게 발견할 수 있다. 네이버 블로그는 그런 기능이 기본인 건지 꽤 많은 것 같기도 하고.

 남의 컨텐츠를 복사해서 자기 블로그 등에 올리는 이른바 불펌을 막기 위해서라고들 한다. 하지만 그렇게 한들 막을 수 없는것을 모르는 것도 아니면서 그러고들 있다. 계획적으로 불펌 하고자 하는 사람이 그것 피하는 방법도 모르고 불펌하겠냐? 검색 한번만 해봐도 다 나오는 것을.



 마우스 클릭은 크게 두가지로 나뉜다. 일반 클릭과 오른쪽 클릭. 가장 많이 쓰이는 링크 누르기 기능을 일반 클릭에, 그 외 모든 컨텍스트에 따른 기능은 오른쪽 클릭에 다 집어넣었다. "복사하기" 가 아니라 "모든". 예를 든면 "사전에서 찾기" 라던지 "구글로 검색" 이런 것들을 오른쪽 클릭을 통해서 할 수 있다. 확장 프로그램 등을 설치하면 얼마든지 추가할 수도 있다. 이것을 블로그나 웹사이트 주인이 대체 어떤 권한으로 못하게 막는다는 것인가? 복사 기능만 따로 막는 것도 아니고 통째로 못하게 하다니. 물론 본인은 복사 기능만 막는다고 해도 찬성하진 않지만.

 정부에서 도촬 방지 대책으로 스마트폰의 카메라 어플 탑재를 금지시킨다면 어떻겠는가? 결국 도촬할 사람은 알아서 설치해서 할 것이고 결국 모든 스마트폰 사용자들은 카메라를 사용하려면 별도로 설치를 해야 하는 불편을 감수해야 할 것이다. 이거랑 다를게 하나도 없다. 아니 , 이건 한번만 하면 되고 간단하니 오히려 더 양호한 편이다.

 완전 벼룩 잡자고 초가삼간 태우고 앉아 있다. 지들이 판단한 특정 사이트 막으면 청소년이 보호되는줄 알고 ActiveX 설치하면 보안이 강화되는줄 아는 나랏일 하시는 놈들 수준의 대응이다.



 오른쪽 클릭이나 드래그 등을 막는 자바스크립트를 사용하는 웹사이트는 인터넷의 사용성을 심각하게 훼손하고 있다고 본다. 내 블로그 내가 알아서 하는데 뭔 상관이냐고? 그럼 구글링에 검색되지 않게 하던지.

 자기 소유의 웹페이지가 제공하는 기능이나 내용을 주인은 자기 마음대로 결정할 권리가 있다. 그러나 그건 웹페이지가 제공하는 기능일 때 얘기고 기본적으로 사용자에게 주어져 있는 컴퓨터의, 웹브라우져의 기능을 사용자의 동의 없이 마음대로 제한할 권리는 없다. 사용자보다 기술적인 우위에 있다고 해서 마음대로 해도 되는 것이 아니다. 경찰이 범인을 잡기 위한 목적이라고 해도 영장 없이 아무 집이나 들어가서 막 뒤져도 되는게 아닌 것처럼.

<추가>

 글 싸지르고 나서 이에 관한 다른 사람들의 글들을 좀 살펴봤다. 우클릭 금지 옹호 주장자들은 다들 하나같이 우클릭을 하는 이유에 대한 옹호만 있을 뿐 우클릭 금지 자체가 가지는 사용자의 권한 무시는 간과하고 있다. 이유는 나도 동감한다. 불펌이 좋다는 사람이 누가 있겠냐. 하지만 불펌을 금지해야지 우클릭을 금지하는 것은 방법이 잘못 됐다는 거다.

 유명한 미술품 전시회에서 손으로 만지면 안되는데 사람들이 자꾸 만져서 입구에서 손가락 없는 장갑으로 꽁꽁 싸매 가려워도 얼굴도 못 긁는 상황이 돼 보면 약간 이해 하려나. "오른쪽 클릭 막는것은 최소한의 대응이고 의사표시다" "뭐 그리 불편하다고 그러냐"고 말하는 사람들에게는 이 경우 "만지지 말라는 박물관 측의 최소한의 의사표시다" "손가락으로 못 긁으면 손등이나 팔 어깨로 문질러서 긁거나 좀 참으면 되지 뭘 그리 대수냐" 라는게 적용 되시겠다.

2013년 1월 7일 월요일

나는 항상 옳다.

나는 항상 옳다.

왜냐하면 나는 '언제든 내가 틀릴 수 있다'고 생각하니까.

내가 틀릴 수 있다는 저 생각이 옳지 않으려면 나는 항상 옳아야 하므로

내가 저 생각을 계속하는 한 어느 쪽이든 나는 옳다.

진실과 진리를 찾으려는 논쟁이 아닌 이기려는 싸움을 만날 때면 바로 저 절대무적의 생각을 권해주고 싶다.

그런 다음에는 진실과 진리를 찾아낸 양측 모두의 승리만 남을뿐이다.

그리하여 나는 항상 옳다옳은 방향으로 가고 있다.

제목은 낚시.

2012년 12월 6일 목요일

유용한 Mac OS X 쉘 커맨드

1. 프로그램을 ⌘ + H 로 숨겼을 때 Dock에 투명하게 표시해준다.
defaults write com.apple.Dock showhidden -bool YES && killall Dock

2012년 11월 21일 수요일

viewWillAppear에서 들어가는 중인지 복귀하는 중인지 구분하는 방법

Determine entering or coming back in UIViewController with UINavigationController

UINavigationController를 사용하다 보면 현재 ViewController로 들어올 때 이전 화면에서 들어오는지 다음 화면에서 복귀하는 중인지 구분을 해야 할 때가 있다. 물론 들어갈 때 ViewController를 생성을 하는 경우라면 viewDidLoad에서 들어갈 때의 동작을 하는 방법도 있을 수 있겠지만 이전으로 돌아올 때는 여전히 애매하다.
그래서 그까이꺼 만들어놨겠지 하고 API를 들쑤시다 보면 isMovingFromParentViewController, isMovingToParentViewController를 찾을 수 있는데 이 메소드의 이름이 참으로 오해하기 딱 좋다. 하나는 부모에서 들어올 때, 하나는 부모로 갈 때. 문서를 보면 movingTo는 viewXXXAppear에서, movingFrom은 viewXXXDisappear에서만 제 값을 돌려준다고 되어 있는데 가만 생각해보면 좀 이상하다.
부모에서 들어오는 중이면 현재 viewController가 나타나는 중일텐데 viewXXXDisappear에서만 확인할 수 있다?
부모로 가는 중이면 현재 viewController가 사라지는 중일텐데 viewXXXAppear에서만 확인할 수 있다?
아무리 생각해도 이해가 안된다. API 문서에는 메소드 이름 이상의 별다른 설명이 없다.
그래서 확인해 봤다. 각종 상황에서 뭐가 어떻게 값이 나오는지. 그러자 알기는 옳타쿠나 알기는 커녕 멘붕이 왔다;
그러던 중 WWDC2012 Sessions 동영상을 보았는데 iOS 6으로 오면서 viewController가 확 바뀐 부분에 대해 설명하는 부분에서 viewController가 child로 추가되고 제거될 때 어떤 일이 일어나는지 자세히 나왔다. 그순간 아하!
Parent와 Child의 의미를 잘못 이해했다;;
현재 viewController의 Parent는 이전 viewController가 아니라 UINavigationController였던 것이다!
당연한 걸 뭘 호들갑이냐고? 그렇다면 미안하다;; 난 몰랐다.. 당신의 이해력이 뛰어나서 그런거라고 대인배스럽게 넘어가주자.

isMoving으로 시작하는 두 property에서 말하는 "moving"은 다음화면 이전화면 하는 navigation의 의미가 아니라 한 viewController가 NavigationController와 같은 container view controller로 들어오고 나가는 "moving"이었던 것이다. (부끄럽지만 API 문서에 보면 이렇게 떡하니 써있다. 너무 당연한 말이기 때문에 별 의미가 없다고 생각했다. 뭐 핵심은 container view controller의 의미를 오해한 것이니;)

이것은 현재 viewController의 관점이기 때문에 응용해보면 다음과 같은 4개의 메소드를 만들어 가독성을 높일 수 있다.

// only available in viewWillAppear, viewDidAppear
- (BOOL)isNavigatingFromPrevious
{
    return self.isMovingToParentViewController;
}

// only available in viewWillAppear, viewDidAppear
- (BOOL)isNavigatingFromNext
{
    return (self.isMovingToParentViewController == NO);
}

// only available in viewWillDisappear, viewDidDisappear
- (BOOL)isNavigatingToPrevious
{
    return self.isMovingFromParentViewController;
}

// only available in viewWillDisappear, viewDidDisappear
- (BOOL)isNavigatingToNext
{
    return (self.isMovingFromParentViewController == NO);
}


본인은 이렇게 한번 감싸주지 않으면 머리속에서 번역이 안되더라;;
물론 근본적으로 들어가는 상황인지 나오는 상황인지 따위를 viewWillXXX 메소드에서 궂이 구분하지 않아도 되는 것이 이상적이다. 하지만 세상사 만들다 보면 그런 나이쓰한 구현이 잘 안될 때가 있으므로 그럴 때 요런거 쓰시면 되겠다.

사람은 동시에 생각할 수 있는 정보의 양이 그리 많지 않다. 많다고 해도 한정되어 있으므로 이것을 집중해야 할 부분에 잘 써야 한다. 저런 직관적인 표현으로 바꾸어 놓으면 저 메소드를 사용하는 부분에서 이게 뭔 뜻이지? 하고 생각하는 데에 드는 시간에 원래 하려던 것에 집중할 수 있고 오해도 방지할 수 있다.
성능을 고려하면 안 좋은 방법 아니냐고? 성능이 문제되면 그 때 최적화를 하면 된다. 가독성이 먼저다. 가독성, 기능, 성능을 동시에 고려해서 한방에 짠 하고 나이쓰하게 구현하는 것은 불가능하다. 만약 당신이 가능하다면 연락주시라. 왜냐고? 스승님으로 모시고 싶어서ㅋ

iOS / Mac OS X API들을 보다보면 해당 클래스의 개발자 관점의 네이밍이 좀 있는 것 같다.
그래도 저게 가장 정확한 표현인 것은 맞으니 뭐라고 하기도 애매하고.. 뭐 그렇네ㅋ

2012년 11월 12일 월요일

UINavigationController의 Back Button 이름 바꾸기

How to change NavigationBar Back Button's title

UINavigationController에서 Back Button의 기본 구현은 이전 ViewController의 Title을 이름으로 쓴다. 만들다 보면 이 이름을 바꾸는 경우가 생기는데 이게 좀 거시기하다.
알면 쉬운데 모르면 삽질하기 쉽다.(나도 방금 삽질 좀 했다)
딱 직관적으로 생각해보면
self.navigationItem.backBarButtonItem.title = "Back";
이런거 viewWillAppear 이런데다가 넣어주면 당연히 바뀔 것 같지 않은가?
self.navigationController.navigationItem.backBarButtonItem.title = "Back";
아니면 이런곳?
하지만 아쉽게도 이미 만들어진 Navigation Bar의 Back Button 이름을 바꿀 순 없는 것 같다.(내가 방금 찾아본 바로는.. 있으면 좀 알려주라)
저 navigationItem 이라는 property는 pushViewController 할 때 다음 장면에서 표시할 NavigationBar를 구성하면서 사용하는 것으로 보인다.
즉 push 하기 전에 미리 세팅되어 있어야 한다는 뜻이다.
게다가 심지어 push 되는 ViewController가 아닌 push 하는 ViewController 쪽에다가 설정해야 push 되는 ViewController가 나오는 장면에서 설정한게 보인다.
즉,
parentViewController.navigationItem.backBarButtonItem ...
[navigationController pushViewController:childViewController ...];
이런 식으로 해야 childViewController에서 원했던 Back Button을 볼 수 있단 말이다.

정리하면 이렇다.

FirstNavigationController, SecondNavigationController가 있고 각각의 title이 "First", "Second"라고 하자.
SecondNavigationController에서 Back Button의 title을 "First"가 아닌 "Back"으로 표시되게 하고 싶다.
그러면 First에서 Second를 push하는 부분을 아래와 같이 구현하면 된다.

- (void)onClickSecondButton
{
    self.navigationItem.backBarButtonItem = [[UIBarButtonItem alloc] initWith...];
    SecondViewController *second = ...;
    [self.navigationController pushViewController:second animated:YES];
}

넘어갈 때 매번 Button을 생성하란 소리가 아닌 것 쯤은 알거라고 생각한다. 상황에 따라 알아서 하면 된다.
핵심은 push 하기 전에 미리 설정해야 한다는 것이다.

구현하는 입장을 생각해보면 이해가 되는 방식이지만 API인데 너무 오해하기 쉽게 만들어놨다는 점에서 만든분 나빠.