[Info]Tags categorized posts and contents patterns..

[AJAX] Ajax Code E xamples.. [Book] About the book.. [CSS] CSS Code E xamples.. [DB] Sql Code E xamples.. [DEV] All development stor...

2016년 4월 5일 화요일

[Linux]폴더 내 파일을 검색해서 파일 권한 바꾸기..

일전에 Linux 명령어 포스팅을 한적이 있다.. 기본적인 명령어 모음의 개념으로 포스팅을 한 것인데 오늘은 그중에서 자주 쓰는 폴더내의 파일권한 바꾸기에 대해서 좀 적어보려고 한다..

보통 리눅스 기반으로 콘솔에서도 명령어를 치곤 하지만, 그건 아무래도 대부분 서버 가동 내지는 로그보기에 대한 부분이고, 가끔 파일 권한을 바꿀 때가 있긴 하지만 그것도 File Zilla 를 통해서 마우스로 바로 수정이 가능하다..

그런데 숨겨진 파일 내지는 세팅 파일 등등 특정 폴더내에 있긴한데 찾기가 어렵다거나 파일이 여러곳에 나눠져 있는 경우 최상위 폴더에서 한방에 처리를 해야 될 때가 있다.. 물론 그것도 File Zilla 에서 가능은 하지만 시간이 겁니 오래 걸린다는 것.. 그게 문제다..

명령어부터 보자면, 아래와 같다.. 본인이 원하는 경로의 위치에서 입력하면 된다..

find . -exec chmod 777 {} \;

근데 나도 첨에 그랬지만 저게 먼말인지를 알아야지.. ㅡ;;ㅡ..


  • find : 파일을 찾는다..
  • -exec : 앞 조건[.]을 통해서 찾은 파일을 다음 명령어로 실행한다..
  • chmod : 상태를 바꿔주는 명령어다..
  • 777 : 파일에 대한 모든 권한을 준다..
  • {} : 검색을 통해 찾은 파일을 뜻한다..
  • \; : 명령어의 종료다.. 단, ; 만 존재할 경우 특수문자로 인식을 하기 때문에 꼭 \; 붙여서 명령어의 종료를 알리도록 한다..


위와 같이 붙여서 사용하게 되면, File Zilla 라보다 훨씬 빠르게 손쉽게 사용할 수 있다.. 개인적으로는 캡쳐를 해서 어떻게 수정이 되고 하는지 화면이 있다면 더 좋을텐데 그게 좀 아쉽다..

무엇보다 내가 리눅스 전문가가 아닌 관계로 솔직히 저 명령어를 사용할 때 엄청 빠르게 타이핑 못한다.. 그래서 적어두고서 복사해서 쓴다.. ㅎㅎㅎ..

음.. 적다보니 나도 명령어 중 파일권한 777 에 대한 상세한 정의라던지 find 를 통해서 할 수 있는 각종 명령어에 대해서는 모른다.. 특별한 일이 없으면, 좀 더 상세한 부분을 확인해서 올려야겠다..


[Book] 스티브 잡스..

출처 : Outsider's Dev Story https://blog.outsider.ne.kr/

스티브 잡스 - 8점
월터 아이작슨 지음
안진환 옮김
민음사

스티브 잡스의 공식 전기입니다. 다들 알고 있다시피 스티브 잡스는 결국 이 책의 출간을 보지 못하고 올해[햄의 포스팅 기준 일자이다..] 사망했습니다. 이 책대로라면 잡스는 책이 자신을 어떻게 묘사하고 있는지 전혀 읽어보지 못하고 사망했습니다. 저는 처음 PC를 애플II로 시작하기는 했지만 딱히 애플에 대한 애착은 별로 가지고 있지 않았습니다. 스티브 잡스의 위대함은 당연히 인정하고 있었지만 애플의 폐쇄정책은 별로 찬성하지 않았기 때문에 최근까지도 애플을 많이 거부했었습니다. 뭐 지금은 워낙 제품을 잘 만들어내다보니 대부분의 전자기기는 애플 제품으로 교체되어버렸습니다.

이 책에 대한 얘기를 하기 전에 먼저 번역에 대한 얘기를 해야할 것 같습니다.(저는 민음사와 아무런 관련이 없습니다.) 스티브 잡스 전기가 출판되면서 전문 번역가 좋아하시네: 『스티브 잡스(안진환 옮김)』 번역 비판라는 글이 올라오면서 SNS를 중심으로 번역에 문제가 있다는 내용이 퍼져나갔습니다. 제가 의외였던 부분은 사람들의 반응이었습니다. 많은 사람들이 번역에 문제가 있으니 사지 말아야 겠다거나 원서를 사야겠다는 반응이었습니다. 저는 저 글을 보기 전에 책을 이미 예약판매에서 구입했지만 저 글을 보고도 그다지 신경쓰지 않았습니다. 왜냐하면 너무 사소한 이슈들로 보였고 개인이 그런 의견을 낼수는 있지만 과도하게 퍼진다는 느낌이었기 때문입니다. 원서도 술술 읽는 사람이라면 상관없겠지만 일단 저는 영어를 잘 못하기 때문에 번역이 좀 안좋더라도 원서를 읽는것 보다는 역서를 읽는게 훨씬 편하고 제가 원서를 읽으면서 해석한게 이 역서보다 낫다라는 자신도 없었기 때문입니다.(저는 원서읽기가 그렇게 편한 사람이 그렇게 많은지 처음 알았습니다.)

그리고 저 비판의 내용을 보면 너무 사소한 이슈들이고 상당수는 역자에 따라서 다르게 사용할 만한 내용들도 많이 있습니다. 입장이 반대였어도 이런 단어가 더 적절하다라고 누구나 말할 수 있었을꺼라는 것입니다. 정답은 없기 때문이죠. 물론 저 글을 보면 번역에 문제가 있는 부분도 있습니다. 이는 민음사에서 쪽대본때문에 생긴일이라는 변명을 올리기는 했지만 제가 신경쓰지 않은건 그때문이 아닙니다. 이 책은 스티브 잡스의 전기이지 제가 개발을 하기 위해서 참고하는 표준명세가 아닙니다. 만약 W3C 표준명세를 보고 제가 개발을 한다면 아주 사소한 번역의 문제로도 구현이 잘못될 수 있기에 문제가 커지지만 이 책은 그런 책이 아닙니다. 역서를 읽을 사람과 원서를 읽은 사람이 이 책을 아주 디테일하게 논의하더라도 아무런 어려움이 없다고 자신있게 말할 수 있습니다. 예를 들어 "워즈의 천재성"이라고 번역한 부분을 저 글에서는 "워즈의 천재성을 어느정도 갖추었다"라고 해야 맞다고 했다고 해서 제가 잡스를 이해하는데 아무런 문제도 없습니다. 개인적으로 과연 저 글을 퍼트리는 사람들이 세부내용을 직접 읽어보았는지 의심이 들 정도입니다.

아무튼 책의 내용으로 다시 돌아가겠습니다. 잡스와 직접 인터뷰를 하면서 만들어진 책이기 때문에 잡스의 삶이 아주 디테일하게 나와있고 흥미진진하게 읽었습니다. 이 책은 잡스를 찬양하는 책은 아닙니다. 물론 잡스의 삶에서 찬양(?)할만한 요소들이 엄청나게 많기 때문에 그런 부분도 많이 있지만 잡스의 삶에서 밝은 면과 어두운 면을 모두 보여주고 있고 그래서 더 흥미롭게 느껴졌습니다.

잡스는 제 생각보다도 훨씬 독단적인 스타일의 사람이었다는 느낌이었습니다. 이 책을 읽으면서 내가 실제로 잡스를 만났다면 어땠을까 하는 생각이 들었습니다. 모욕을 느낄정도의 면받을 주고 야근이나 주말근무는 당연하고 독단적으로 밀어버리는 스타일... 만약 인터넷 게시판에 잡스라는 주어를 빼고 상황만 묘사해서 올린다면 당장 그만두라는 댓글이 많이 달릴 것입니다.(물론 이 시대가 7~80년대의 실리콘밸리이기 때문에 지금의 상황과는 무척 다릅니다.) 아마 잡스를 알아보지 못하고 회사를 그만두었다면 제가 그를 알아볼 능력이 없는 것이었겠지요. 지금 많은 회사가 개발자를 마구 부려먹는 것을 합리화하려는 것은 아닙니다. 대신 잡스와 잡스가 아닌 사람사이에는 큰 차이가 있습니다.

잡스는 실제 열정을 가질만한 일의 비전을 보여주었습니다. 매킨토시를 만드는 일, 아이폰을 만드는 일, 아이맥을 만드는 일 등 실제로 세상을 바꿀만한 가치가 있고 그런 길을 제시해 주었습니다.(결국 해내기까지 했습니다.) 저는 여기에 아주 큰 차이가 있다고 생각합니다. 때로 부적절한 행동이 있었다고 하더라도 잡스밑에서 있던 사람들은 잡스가 보던 비전을 같이 보고 세상을 바꿔보기 위해서 열정을 가졌습니다. 그래서 그런 일이 가능했다고 생각합니다. 반면 일반적으론 그다지 가치도 없는데다가 좋지도 않은 것을 만들기 위해서 단순히 월급을 준다는 이유로 개인의 삶을 다 바칠 정도의 열정을 보여달라고 요구합니다. 얼핏 미묘해 보이는 차이일지라도 그런 일에 열정을 느낄 사람은 그닥 많지 않다고 생각합니다. 이 책에서는 잡스의 이런 능력을 "현실왜곡장"이라고 부릅니다. 잡스가 스스로 불가능한 일을 가능하다고 믿고 주위사람도 그렇게 믿게 된다는 것입니다.

결국 그는 한번이 아니고 여러번 세상을 바꾸면서 위대한 인물이 되었습니다. 전기의 내용을 요약하기는 그렇고 아래는 인상적이었던 부분들입니다.

"그는 절대로 돈을 벌겠다는 목표로 회사를 차려서는 안 된다고 여러번 강조했습니다. 자신의 신념을 쏟아부을 수 있는 무언가를 만드는 것, 오래도록 생명력을 지닐 회사를 만드는 것을 목표로 삼아야 한다고 했지요."
이 말은 마이크 마쿨라가 잡스에게 한 말입니다.

"단순함이란 궁극의 정교함이다."
"잘못된 제품을 출시하느니 일정을 어기는 게 낫다."
잡스는 제품에 대한 여러가지 철학이 있습니다. 애플에 제품은 단순하지만 단순하지 않습니다. 그게 애플에 매력이죠. 아이폰 이후부터는 애플은 일정도 칼같이 지킨다고 생각하긴 하지만 대부분은 출시일을 어기느니 어설픈 제품이라도 출시하는 것이 현실이죠.

"매킨토시를 개발하는 동안 배운 것은, A급 직원들은 A급 직원들하고만 일하기를 좋아한다는 것입니다. B급 직원들을 묵과해서는 안된다는 뜻이지요."

"애플에는 훌륭한 사람들이 많습니다. 하지만 계획 자체가 잘못됐기 때문에 그들도 잘못된 일을 하고 있는 겁니다. 좋은 전략과 보조를 맞추고 싶어하는 사람들이 많다는 사실을 발견했습니다. 다만 지금까지는 그런 전략이 없었던 겁니다."

"나이가 들수록 동기여부가 얼마나 중요한지 실감합니다. 준이 시시한 이유는 마이크로소프트 사람들이 음악이나 예술을 우리처럼 진정으로 사랑하지 않기 때문이다. 우리가 승이한 이유는 한 사람 한 사람이 음악을 사랑해서입니다."

"물론 이윤을 내는 것도 좋았다. 그래야 위대한 제품을 만들 수 있었으니까. 하지만 이윤이 아니라 제품이 최고의 동기부여였다."
잡스는 기술과 인문학의 가운데 있었습니다. 그로 인해서 잡스는 다른 사람들이 보지 못하는 것들을 볼 수 있었는지도 모르겠습니다. 제품 자체에 애정이 있는 것과 단순히 출시할 제품을 정해놓고 일하는 것과는 결과가 다를 수 밖에 없겠지요.

잡스의 사업원칙 중 하나는 결코 자기 잠식을 두려워하지 말라는 것이었다. "우리가 스스로를 잡아먹지 않으면 다른 누군가가 우리를 잡아먹을 겁니다."
이런 생각을 한다고 다들 좋은 제품이 나오는 것은 아니기는 하지만 대부분의 회사는 밥그릇이 생기면 그것을 지키는 수동적인 태도가 됩니다. 이는 이상할 것도 없이 대부분의 회사가 하지만 애플은 최고의 위치에서 계속해서 혁신을 이뤄내고 현재 위치에 이르렀습니다. 저는 이런 결과를 실제 보여준 것에 대해서 감격스러울 정도입니다.

"실리콘밸리는 나를 많이 지원해 주었지요. 최선을 다해 그걸 갚아야 합니다."

"어던 기업을 시작했다가 매각이나 기업공개를 통해 현금이나 챙기려고 애쓰면서 스스로를 '기업가'라고 부르는 이들을 나는 몹시 경멸한다."
마지막으로 잡스가 애플에 돌아와서 광고로 사용했던 문구... 이 내용이 애플과 잡스를 가장 잘 표현하는 것 같습니다.

"미친 자들을 위해 축배를, 부적응자들, 반항아들, 사고뭉치들, 네모난 구멍에 박힌 둥근 말뚝 같은 이들, 세상을 다르게 바라보는 사람들, 그들은 규칙을 싫어합니다. 또 현실에 안주하는 것을 원치 않습니다. 당신은 그들의 말을 인용할 수도 있고, 그들에게 동의하지 않을 수도 있으며, 또는 그들을 찬양하거나 비난할 수도 있습니다. 당신이 할 수 없는 한 가지는 그들을 무시하는 것입니다. 왜냐하면 그들이 세상을 바꾸기 때문입니다. 그들은 인류를 앞으로 나아가도록 합니다. 어떤 이들은 그들을 보고 미쳤다고 하지만, 우리는 그들을 천재로 봅니다. 자신이 세상을 바꿀 수 있다고 믿을 만큼 미친 자들....., 바로 그들이 실제로 세상을 바꾸기 때문입니다."


[EP]Twitter Seoul Developer Teatime 후기..

출처 : Outsider's Dev Story https://blog.outsider.ne.kr/

지난 15일 서울에서 트위터 개발자 행사가 열려서 갔다왔습니다. 이 행사는 Teatime - 아시아 개발자 투어의 일부분으로 서울부터 시작해서 현재는 일본에서 진행중입니다. 그래서 Seoul Dev Teatime은 15일 저녁에 논현동 플래툰 쿤스트할레라는 곳에서 진행이 되었습니다.(이름이 왜 티타임인지 잘 모르겠더군요. 차를 주거나 하진 않습니다.) 얼마전에 Github Drinkup을 너무 늦게 봐서 못간게 아쉬웠던터라 행사 내용도 몰랐지만 일단 제가 좋아하는 트위터가 한국에 와서 뭔가를 한다니까 냅다 신청했습니다.

twitter seoul developer teatime

간단히 제공하는 음식을 먹고 있을 때쯤 행사가 시작되었습니다. 시작은 행사 진행을 맡은(트위터가 서울에 지부같은 것이 없다보니 그런듯) seoul space가 발표를 했습니다. 별내용은 없이 한국의 실래콘밸리를 꿈꾸고 스타트업 인큐베이팅과 IT허브의 역할을 기대하고 있다고 했는데 정확히 무슨 액션을 하고 있는지는 잘 알수가 없었습니다.(이날 통역자분이 한분 계셨지만 전문 통역자가 아니라서 제대로된 통역이 되지 않았고 결과적으로 양쪽말을 다 생각하면서 듣느라 힘들었습니다. 이날 이분 1년치 욕을 다 먹으셨을듯....) 그리고 이어서 보기만 해도 공무원 냄새가 나는 kotra의 분이 나와서 보기만 해도 졸음이 올것 같은 전형적인 공기업 PPT를 들고나와서 IT에 대한 이런 저런 얘기를 했는데 무슨 말이었는지 기억도 나지 않습니다.

이 때부터 슬슬 기분이 찝찝하기 시작했습니다. 이 행사는 무엇인가? 제가 기대했던 트위터 개발자들한테 트위터의 기술에 대한 설명을 듣거나 혹은 (가기전에는 이런 세션이 있는 줄도 몰랐으므로) 가볍게 이야기하는 분위기 정도로 생각했는데 뭔가 트위터에 발을 걸친 업체들이 자신들 홍보를 하는 곳인가 하는 기분이었습니다. 더군다나 세미나 같은거 하면 후원한 공기업들이 꼭 나와서 인사말 같은거 하는데 제발 그런거 안했음 좋겠습니다.(그렇게 한가한건지.. ㅡㅡ;;)

#SOTU - Jason Costa
드디어 트위터 직원이 나와서 트위터의 방향에 대해서 설명했습니다.(기술 세션이길 바랬지만 기술세션은 아니었습니다.) 트위터에 대한 전체적인 방향에 대한 세션이었습니다. 트위터는 트위터 에코시스템의 성장에 관심을 가지고 있으며 에코시스템에 대한 투자를 위해서 많은 툴을 만들고 UX와 모바일도 개발했다고 하였습니다.

현재 트위터는 5가지에 초점을 맞추고 있습니다.

  • Analytics : 구글의 에릭 슈미트도 분석은 가장 돈이 많이 되는 분야라고 했습니다. 브랜드나 퍼블리셔들에 대한 가치있는정보를 통해서 명성을 관리할 수 있도록 해줍니다.
  • Content : 더 많은 컨텐츠의 생산을 위한 UX를 만들어 냈고 인스타그램이나 포스퀘어같은 서비스들이 트위터 유저들의 영역을 넓혀주었다.
  • Curation : 리얼타임 데이터를 필터링해서 적절하고 의미있는 대화가 되도록 하고 있다.
  • Publishing : 영향을 끼치기 가장 좋은 시간에 적절한 컨텐트를 공유할 수 있도록 한다. 소셜 플로우라는 회사는 고객들의 트윗을 사용자가 반응이 가장 좋은 시간에 퍼블리싱 되도록 하고 있다.
  • Enterprise : 기업이나 관심사에 대한 가치있는 정보에 대해서 유저 인터렉션을 제공할 수 있도록 관리한다. 대표적으로 클라우트가 있습니다.(아마 KLOUT를 말하는듯 합니다.)

이제 부터가 중요한 부분인데 에코시스템을 성공하고 있습니다. Quora의 창업자는 각 트윗마다 30클릭이 발생해서 Quora로 유입되었으며 검색엔진외에 가장 많은 트래픽을 생산하는 곳이라고 얘기하였습니다.

Jason Costa의 발표

그 뒤에는 웹사이트들을 위해서 제공하는 트윗버튼들을 소개했습니다. 트위터의 Follow버튼을 붙히면 원클릭으로 팔로우 할 수 있어서 트위터의 팔로우를 늘릴수 있습니다. 한 비디오 공유사이트는 Follow버튼을 붙힌뒤 리플라이가 70%증가하고 리트윗이 131%증가했으며 팔로우가 150%증가했다고 밝혔습니다. Tweet버튼은 컨텐츠의 배포를 증가시키고 트래픽을 올려줍니다. 트윗버튼을 붙히면 트윗을 붙히지 않은 사이트보다 7배가 더 많은 트윗이 발생합니다.

twitter + iOS5 - Sean Cook
이 날의 유일한 기술 세션이었습니다. iOS5와 트위터의 통합에 대한 이야기였습니다.  현재 트위터는 2억명 이상의 유저가 있고 백만개 이상의 앱이 들록되어 있으며 iOS는 2억개 이상의 디바이스가 세계적으로 존재합니다. 트위터가 iOS 5에 통합됨으로써 트위터를 메일처럼 쓸 수 있고 iOS5는 Tweet Sheet를 제공하고 있습니다.(트윗을 작성하는 Sheet를 말합니다.) 개발자로써 다음과 같은 이점이 있습니다.

원클릭 싱글사인온(One click single sign-on)
원클릭으로 트위터 인증을 얻을 수 있습니다. 사용자는 앱이 트위터계정에 접근하게 할것이냐는 경고창만을 보고 앱을 사용자정보와 Interest Graph를 얻을 수 있습니다. 원클릭 싱글사인온은 트위터 API를 통해서 Reverse Auth를 요청하고 Twitter.framework가 계정정보를 돌려줍니다.

즉시적인 개인화(Instant personalization)
싱글사인온을 통해서 앱은 위치나, 음악등에 대한 Interest Graph를 얻을 수 있기 때문에 사용자의 취향을 파악해서 그에 맞춰진 앱을 제공할 수 있습니다.

거대한 배포(Massive distribution)
트위터에는 1억명 이상의 액티브유저가 있고 그중의 50%이상은 모바일 유저입니다. 그리고 하루에 2억2천만개 이상의 트윗이 올라오고 그중 25%는 링크를 포함하고 있습니다. 개발자들은 자신의 앱을 이러한 유저들에게 제공할 수 있습니다.

iOS5에서는 이를 구현하는데 몇주가 아닌 단 몇일정도만이 걸릴뿐입니다. 이는 트위터 뿐만 아니라 인스타그램, 플립보드등도 이야기 한 것입니다.

Sean Cook의 발표

기술적인 부분을 얘기하면 싱글사인온은 ACAccountStore안에 ACAccounts에 인증(Credential)을 저장하고 ACAccountStore의 계정이 변경되면 알려줍니다.Tweet Sheet는 TWTeetComposeViewController클래스를 사용한다. 핵심 인증은 TWRequest라는 객체이고 트위터의 REST API를 은닉해서 인증을 다루도록 해줍니다. 트윗 시트를 통해서 사진을 공유할 수 있으며 이 사진은 pic.twitter.com에 올라갑니다. 이것도 역시 TWRequest를 이용해서 할 수 있습니다. 이 모든 것은 별도의 라이브러리를 다운로드 받을 필요없이 SDK에 포함되어 있으며 당연히 버전에 대한 걱정도 없습니다. 그리고 OAuth에 대해서 이해하지 못해도 상관이 없습니다.

서비스 소개
트위터를 이용해서 만들고 있는 한국회사들에 대한 소개가 이어졌습니다. Twitcooler는 트위터를 통해서 같이 보고 있는 방송에 대해서 얘기하는 서비스였고 K-POP Tweet는 세계적으로 불고 있는 한류바람에 따라 K-POP스타들과 영문으로 트위터를 나눌 수 있도록 하는 서비스였습니다.

Q&A
마지막으로 Q&A시간이 있었는데 몇가지 기억나는 질문만 정리하겠습니다.
iOS5와 통합을 했는데 안드로이드에도 이런 통합을 할 계획이 있는가라는 질문에 대해서 션쿡은 자신은 원래 안드로이드팀에 있던 사람이었는데 이번 투어가 끝나면 플랫폼독립적인 프레임워크를 제작할 계획이라고 햇습니다. 이는 안드로이드뿐만 아니라 블랙베리나 바다OS에서도 통합할 수 있는 프레임워크가 될 것이라고 합니다.

Q&A 시간

검색API에 대한 질문에 대해서는 (아마 검색 API가 다른 REST API에 비해서 부족한 부분이 있나 봅니다.) 지금 진행중이고 Search API도 다른 REST API처럼 바꿀 예정이고 내부적으로 프로젝트는 12월 1일에 완료될 예정이라고 합니다.

t.co에 대한 API를 공개할 예정이 없는가에 대해서는 t.co는 URL Shortener를 위해서 만들어 진것이 아니라 트위터를 통하는 트래픽을 모니터링하고 피싱에 대한 차단을 하기위해서 만들어진 것이기 때문에 현재로써는 오픈에 대한 계획은 없다고 합니다.


Epilogue
트위터에서 Jason Costa와 Sean Cook과 Arnaud Meunier 셋이서 왔는데 Arnaud는 발표를 하지 않았습니다. 모처럼 트위터에서 와서 행사를 했는데 그다지 만족스럽지 않았습니다. 개발자 행사라는 이름을 내건 만큼 좀더 기술적인 내용이 주가 되던지 트위터를 이용한 지역 개발자들과의 조화를 위함이었다면 좀 더 그런쪽으로 방향이 맞추었어야 했다고 생각합니다. 짧은 시간에 둘다 하려다 보니 기술적인 부분도 그다지 흡족하지 않았고(개인적으로 션쿡의 세션은 좋았습니다.) 다른 서비스 소개들은 그냥 업체홍보같아서 그냥 관심이 가지 않았습니다.

끝나고 애프터파티가 있었는데 혼자갔던터라 뻘쭘했던데다가 서로 아는 사람들 끼리끼리가 꽤 많은듯 했습니다. 더군다나 조용한 곳이 아니라 클럽 비스므리했던지라 음악이 시끄러워서 영어가 짧은 저는 트위터개발자랑 이런저런 얘기가 어려울것 같아서 그냥 돌아왔습니다. 암튼 트위터가 한국에도 관심을 가지고 있다는 것은 기쁜일이고 이런 행사가 자주 있었으면 좋겠네요.



[JAVA]Guava로 Ordering으로 컬렉션 정렬하기..

출처 : Outsider's Dev Story https://blog.outsider.ne.kr/

얼마전에 Guava에 대해서 Guava를 써야하는 5가지 이유라는 포스팅 했었는데 컬렉션 위주로 조금씩 써보고 있습니다.

Comparable을 이용한 정렬
자바에서 클래스를 정렬하려면 Comparable을 구현해야 합니다. 다음 Person 클래스를 보겠습니다. 간단한 엔티티클래스입니다.


Java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// Person.java
package kr.sideeffect;

public class Person implements Comparable<Person> {
    private String name;
    private int age;
    
    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    
    public int compareTo(Person o) {
        return this.getAge() - o.getAge();
    }
}

자바의 Collections의 sort함수를 사용하려면 담고 있는 클래스가 위처럼 Comparable인터페이스를 구현해서 compareTo함수를 구현해 놓아야 합니다. compareTo함수를 이용해서 정렬의 조건을 정해줄 수 있는데 여기서는 나이순으로 정렬하기 위해서 age필드를 비교했습니다. 두 값이 같으면 0, this가 크면 양수, this가 적으면 음수가 리턴되도록 작성하면 됩니다. 동작을 확인하기 위해서 다음과 같이 테스트코드를 작성했습니다.


Java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// PersonTest.java
package kr.sideeffect;

import static org.junit.Assert.*;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.junit.Test;

public class PersonTest {
    @Test
    public void 정렬테스트() throws Exception {
        // given
        Person p1 = new Person("Outsider", 32);
        Person p2 = new Person("nephilim", 40);
        Person p3 = new Person("Anarcher", 35);
        Person p4 = new Person("fupfin", 43);
        Person p5 = new Person("Arawn", 33);
        
        List<Person> list = new ArrayList<Person>();
        list.add(p1);
        list.add(p2);
        list.add(p3);
        list.add(p4);
        list.add(p5);
        
        // when
        Collections.sort(list);
    
        // then
        assertEquals(list.get(0).getName(), p1.getName());
        assertEquals(list.get(1).getName(), p5.getName());
        assertEquals(list.get(2).getName(), p3.getName());
        assertEquals(list.get(3).getName(), p2.getName());
        assertEquals(list.get(4).getName(), p4.getName());
    }
}


이 테스트 코드는 성공합니다. compareTo를 작성하였기 때문에 나이순으로 잘 정렬이 됩니다.(위 예제의 나이는 실제인물과는 상관없이 예제를 위한 것임을 밝힙니다.) 하지만 정렬을 해야할 때마다 Comparable을 구현해주어야 하는건 꽤나 귀찮은 일이고(당연한 일인지 모르겠지만 전 무척 귀찮더군요.) 정렬을 여러가지 해야할 경우에는 더욱 피곤해 집니다.

Guava의 Ordering
Guava에서는 Ordering이라는 클래스로 정렬을 제공할 수 있습니다. Ordering을 테스트하기 위해서 Geek이라는 새로운 엔티티를 만들었고 Comparable을 구현하지 않았으므로 Collections.sort로 정렬할 수 없습니다.


Java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
// Geek.java
package kr.sideeffect;

public class Geek {
    private String name;
    private int age;
    
    public Geek(String name, int age) {
        this.name = name;
        this.age = age;
    }
    
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getAge() {
        return age;
    }
    public void setAge(int age) {
        this.age = age;
    }
}


이 Geek 엔티티를 담은 정렬을 사용하기 위해서 다음과 같은 테스트코드를 작성하였습니다.

Java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
// GeekTest.java
package kr.sideeffect;

import static org.junit.Assert.*;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.junit.Test;
import com.google.common.collect.Ordering;
import com.google.common.primitives.Ints;

public class GeekTest {
    @Test
    public void 정렬테스트() throws Exception {
        // given
        Geek g1 = new Geek("nephlim", 40);
        Geek g2 = new Geek("Anarcher", 35);
        Geek g3 = new Geek("fupfin", 43);
        Geek g4 = new Geek("Arawn", 33);
        
        List<Geek> list = new ArrayList<Geek>();
        list.add(g1);
        list.add(g2);
        list.add(g3);
        list.add(g4);
    
        // when
        Ordering<Geek> byAge = new Ordering<Geek>() {
            @Override
            public int compare(Geek left, Geek right) {
                return Ints.compare(left.getAge(), right.getAge());
            }
        };
        
        Collections.sort(list, byAge);
    
        // then
        assertEquals(list.get(0).getName(), g4.getName());
        assertEquals(list.get(1).getName(), g2.getName());
        assertEquals(list.get(2).getName(), g1.getName());
        assertEquals(list.get(3).getName(), g3.getName());
    }
}

when에 작성한 부분이 Ordering을 사용한 부분입니다. new Ordering으로 새로운 클래스를 만들면서 Ordering의 compare를 오버라이드라이드해서 정렬의 기준을 작성해 주면 됩니다. 예제에서는 Guava가 프리미티브타입에 대한 유틸리티성 클래스인 Ints를 사용해서 compare로 두 값을 비교했습니다. 사실 이는 Comparator인터페이스를 이용해서 when부분을 다음처럼 작성해도 동일합니다.

Java
1
2
3
4
5
6
7
Comparator<Geek> byAge = new     <Geek>() {
    public int compare(Geek left, Geek right) {
        return ((Integer)left.getAge()).compareTo((Integer)right.getAge());
    }
};
        
Collections.sort(list, byAge);

하지만 Ordering을 쓰면 다양한 정렬에 대해서 쉽게 사용할 수 있습니다.

Java
1
2
3
Collections.sort(list, byAge.reverse());
Collections.sort(list, byAge.reverse().nullsFirst());
Collections.sort(list, byAge.reverse().nullsLast());

Ordering에는 정렬을 거꾸로 하는 reverse나 null의 정렬순서를 정해주는 nullsFirst, nullsLast가 있습니다. 기본적인 순서로 해주는 natural도 있습니다. 이러한 함수들을 조합해서 원하는 조합을 만들 수 있으며 좀 더 복잡한 정렬조건은 compound를 사용해서 조합할 수 있습니다.

[Tool]비상업적용도로 JRebel을 무료로 쓸 수 있는 JRebel Social..

출처 : Outsider's Dev Story https://blog.outsider.ne.kr/

JRebel은 핫디플로이를 지원해주기 때문에 유용한 개발도구중 하나인데(개인에 따라 호불호는 있기는 합니다.) 개인이 구입하려면 1년에 130불정도인데 사실 개인이 업무를 하는게 아니라면 구입해서 쓰기가 좀 부담스러운게 사실입니다. 하지만 지난 9월 ZeroTurnaround는 비상업적인 용도로는 JRebel을 무료로 쓸 수 있도록 JRebel Social을 오픈하였습니다.

JRebel Social 메인페이지

JRebel Social의 메인페이지 입니다. ZeroTurnaround가 마케팅에 적극적으로 나선듯 보이는데 그 중하나가 JRebel Social이고 위 화면처럼 페이스북이나 트위터계정을 이용해서 로그인이 가능합니다.

JRebel Social 대시보드

로그인을 하면 위와같은 대시보드가 나타납니다. 대부분 커밍순이라고만 나와있습니다. JRebel로 아낀 시간이나 이런저런 정보를 제공할 모양이지만 현재는 아무것도 없습니다. 하단의 Copy License Code again을 클릭하면 다음과 같은 라이센스 키를 볼 수 있습니다.

JRebel Social 라이센스키

이 키를 복사해서 JRebel을 등록하면 됩니다. JRebel설정에 대해서는 전에 포스팅했던 JRebel 설정하기[우분투 쪽이여서 안가져왔던 포스팅이었다..]를 참고하면 됩니다. JRebel 설정마법사를 시작합니다.

JRebel 설정 마법사

JRebel Social을 선택해 줍니다.

JRebel 키등록

앞에서 복사한 라이센스키를 등록해 줍니다. 이제 JRebel을 사용할 수 있고 앞에서 명시된 대로 비상업적인 용도로만 사용가능합니다. 정확한 안내가 없기는 한데 JRebel Social은 홍보용이기 때문에 JRebel에 대한 포스팅을 해주어야 사용이 가능합니다. 한달에 한번정도의 이러한 포스팅이 필요한 것으로 알고 있습니다. 그리고 JRebel은 항상 JRebel 서버와 연결되어 있을때만 사용이 가능합니다. 그래서 오프라인에서 사용하기 위해서는 대쉬보드에서 "Go Off-line for 24h"을 클릭하면 24시간동안은 오프라인에서 사용이 가능합니다. 컨테이너를 재실행하거나 JRebel설치폴더의 bin/go-offline를 실행해주면 됩니다.


My Comment..
위쪽에서 잠시 언급한것처럼 JRebel 설정하기 포스팅을 갖고 오지는 않았다.. 우분투쪽으로 관여된 것이라서 안가져왔는데 해당 포스팅은 Tool 적인 측면이 많이 보이기도 하고, 이런 Tool 도 있구나 싶어서 가져왔다.. 내가 쓸일은 없겠지만, 신기한?? 호기심?? 머 이런거라고 생각하면 될듯하다..

[Book] 24시간 365일 서버/인프라를 지탱하는 기술..

출처 : Outsider's Dev Story https://blog.outsider.ne.kr/

서버/인프라를 지탱하는 기술 - 8점
이토 나오야 외 지음
진명조 옮김
제이펍

제목 그대로 서버와 인프라에 관련된 기술에 대해 설명된 책으로 ‘지식 커뮤니티’ 인력검색 서비스와 블로그 호스팅 서비스, 소셜 북마크 서비스를 개발해 운영하고 있는 일본의 인터넷 업체인 하테나가 기술을 바탕으로 인프라를 어떻게 구성해서 운영하고 있는가를 바탕으로 설명하고 있습니다. 실제로 이 책은 하테나의 신입사원의 교제로 쓰이고 있는 책이라고 합니다.

프로그래밍을 하면 항상 서버를 이용해야 하기 때문에 서버와 인프라는 중요하지만 따로 공부는 많이 못했기 때문에 아는 사람들과 스터디를 하면서 책을 읽었습니다. 인프라 구성에 대해서 아주 전반적인 얘기를 해주고 있어서 도움은 되지만 상당히 로우레벨의 인프라기술에 대해서 얘기하기 때문에 개발자로써 기술이 확 와닿지는 않는 느낌입니다. 전체적으로 파악을 하고 있으면 되겠다 싶은 정도입니다.

이 책에서 다루는 내용은 처음에 인프라의 다중화에 대해서 설명하면서 웹서버의 다중화를 어떻게 구성하는지 다중화를 하기 위해서 DNS 다중화 로드밸런서 구성, L4와 L7스위치 및 라우터의 다중화에 대해서 설명하는데 이부분은 네트워크에 대한 지식이 없으면 이해하기가 쉽지 않은 것 같습니다. 웹서버들이 대부분 이런 구성 아래에서 동작하기 때문에 알아둘 필요는 있지만 작은 회사라서 혼자서 코딩과 서버구성까지 다 하는 것이 아니라면 스위치쪽까지 개발자가 다루지는 않기 때문에 이해정도만 하고 있으면 협의할때 많은 도움이 될 듯 합니다. 그리고 2장과 3장에서는 서버의 가용성과 성능 향상을 위한 캐시서버나 디비의 리플리케이션 구성을 포함해서 무중단 서버구성에 대해서 설명하고 있습니다. 하테나가 사용하는 기술과 설정에 대해서 적혀 있기 때문에 실제로 적용할 필요가 있을 때 참고 하면 도움이 될 것 같습니다.

4장은 튜닝에 대해서 얘기하고 있는데 오히려 아파치나 MySQL의 규모에 비해서 분량이 적기 때문에 크게 도움이 될 정도의 내용은 아니고 참고사항 정도라고 생각합니다. 아마 실제로 이 둘을 튜닝하려면 다른 서적을 참고해야 합니다. 대신 서버상태를 확인할 수 있는 ps, sar같은 명령어에 대한 것은 서버에 접속해서 서버상태를 볼 때 유용한 명령어로 보입니다. 5장에서는 운영에 도움이 될 모니터링도구나 설정파일의 배포를 자동화 해주는 도구등에 대해서 설명하고 있는데 이런 도구들은 너무많이 존재하기 때문에 각 조직에 따라서 상당히 다양한 선택권이 있다고 생각합니다. 이부분은 이런 도구들도 있구나 정도로 충분해 보입니다.

잘 모르는 분야의 내용이었기 때문에 아주 친절하게 설명해 주진 않지만(어떤 면에서는 친절하지 않다기 보다는 리눅스 커널 소스까지 보여주는 너무 저레벨이라서란 느낌도 있습니다.) 직접 서버구성을 하지 않더라도 서버는 개발자들이 항상 만지는 것이기 때문에 어떻게 구성되어 있는지 이해하는데 도움이 된다고 생각합니다. 다만 일본책을 번역한 것인데(이건 역자의 선택이라 정답은 없지만.) example.co.jp같은 도메인은 그냥 example.co.kr같은 걸로 바꾸거나 중간에 영어문서 주석과 함께 번역문서라면서 일본사이트 링크가 있는데 우리 입장에선 차라리 영문서를 보는게 더 나을 것이기 때문에 이런 부분은 굳이 그대로 하지 않아도 되지 않았나 생각이 들었습니다.



[JAVA]Guava를 써야하는 5가지 이유..

출처 : Outsider's Dev Story https://blog.outsider.ne.kr/

얼마전에 올렸던 List에서 중복요소 제거한 List로 만들기에서 많은 댓글이 오가면서 반농담삼아 그냥 Guava를 쓰자라는 결론(?)에 이르르면서 최근에 Guava를 좀 찾아서 써보면서 Insightful Logic이라는 런던의 스타트업회사의 회사의 블로그에서 작성한 5 Reasons to use Guava라는 글을 보고 Guava를 파악해보기 위해서 번역한 글을 포스팅합니다. 이 내용은 Insightful Logic에 번역허락을 받고 올립니다.

Guava는 구글이 작성한 자바 오픈소스 라이브러리입니다. 개발자라면 이전에 한번정도는 스스로 작성해 보았거나 필요했지만 작성할 시간이 없었을만한 유용한 유틸리티 함수와 클래스들을 다양하게 제공하고 있습니다. 여기에 Guava를 사용하면 좋은 5가지 이유가 있습니다.

1. 컬렉션 초기화와 유틸리티
동질한 제너릭 컬렉션(제너릭 호모지니어스 컬렉션)은 자바가 가진 좋은 기능입니다. 하지만 때때로 컬렉션의 생성하기 아주 거추장 스럽습니다.


Java
1
2
// 컬렉션 생성
final Map<String, Map<String, Integer>> lookup = new HashMap<String, Map<String, Integer>>();

Java 7에서는 이 문제를 정말 제너릭한 방법으로 해결했는데 제한된 타입추론의 형식을 형식에 구애받지 않고 다이아몬드 오퍼레이터로 참조할 수 있도록 하였습니다다. 그래서 위의 예제를 다음처럼 작성할 수 있습니다.


Java
1
2
// in Java 7
final Map<String, Map<String, Integer>> lookup = new HashMap<>();

이전의 자바버전에서도 생성자없는 메서드생성자가 아닌 메서드를 통해서 이러한 추론은 사실상 가능했습니다. 그리고 Guava는 이미 존재하는 자바 컬렉션에 생성자를 만드는 준비를 위해 많을 것을 제공합니다. 위의 예제는 다음처럼 작성할 수 있다.

Java
1
2
// in Guava
final Map<String, Map<String, Integer>> lookup = Maps.newHashMap();

또한, Guava는 많은 유용한 유틸리티 함수가 Maps, Sets등의 컬렉션에 들어있습니다. 특별히 제가 좋아하는 것은 Sets.union과 Sets.intersection메서드인데 이는 값을 재계산하지 않고 sets의 뷰를 리턴합니다.

2. 제한된 함수형 스타일의 프로그래밍
Guava는 함수형 스타일로 메서드를 전달하기 위한 일반적인 메서드들을 제공합니다. 예를 들어 많은 함수형 언어가 가지고 있는 map이 Collections2.transform 메서드의 형식으로 존재합니다. 또한 Collections2는 컬렉션에서 어떤 값을 제한하도록 하는 filter 메서드를 가지고 있습니다. 예를 들어 컬렉션에서 null인 요소들을 제거하고 다른 컬렉션에 저장하기 위해서 다음처럼 사용할 수 있습니다.


Java
1
2
// Collections2.filter
Collection<?> noNullsCollection = filter(someCollection, notNull());

존재하는 컬렉션을 수정하는 대신에 새로운 컬렉션을 리턴하고 계산된 컬렉션은 Lazy하게 계산된다는 것을 알아야 합니다.

3. 멀티맵(Multimaps)과 바이맵(Bimaps)
단일키에 여러 값을 저장하는 것등은 Map의 정말 일반적인 사용입니다. 일반적으로 표준 자바 컬렉션의 사용은 값타입처럼 또 다른 컬렉션을 사용함으로써 이루어집니다. 이것은 안타깝게도 결국에는 컬렉션 초기화같은 반복되는 많은 형식를 포함하게 됩니다. 멀티맵(Multimaps)은 이것을 아주 깔끔하게 만들어줍니다.


Java
1
2
3
4
5
Multimap<String, Integer> scores = HashMultimap.create();
scores.put("Bob", 20);
scores.put("Bob", 10);
scores.put("Bob", 15);
System.out.println(Collections.max(scores.get("Bob"))); // prints 20

또한 다른 방향의 바이맵(Bimaps) 클래스가 있습니다. 바이맵은 키처럼 값의 유일함을 강제합니다. 값도 유일하기 때문에 바이맵은 반대로 값을 키처럼 사용할 수도 있습니다.

4. 쉬운 해쉬코드와 비교자(Comparators)
자바에서 필드들의 해쉬코드로 클래스의 해쉬코드를 생성하는 것은 아주 일반적입니다. Guava는 이것을 위해서 Object 클래스에 유틸리티 메서드를 제공합니다. 다음은 그 예제입니다.


Java
1
2
3
4
5
6
7
int foo;
String bar;

@Override
public int hashCode() {
  return Objects.hashCode(foo, bar);
}

해쉬코드 메서드를 정의했다면 equals 계약을 유지하는 것을 잊지 말아야 합니다.

비교자(Comparator)는 오퍼레이션의 순서를 연결하는 것을 포함해서 자주 작성하게되는 또 다른 예입니다. Guava는 이 과정을 쉽게 하기 위해서 ComparisonChain 클래스를 제공합니다. 여기 int와 String클래스의 예제가 있습니다.


Java
1
2
3
4
5
6
7
int foo;
String bar;

@Override
public int compareTo(final GuavaExample o) {
  return ComparisonChain.start().compare(foo, o.foo).compare(bar, o.bar).result();
}

5. 방어적 코딩
메서드의 형식을 위해서 어떠한 필수조건들을 작성하는 것에 대해서 스스로 찾아본 적이 있습니까? 때때로 이것은 불필요하게 거추장스럽게 되거나 의도를 직접적으로 전달하는데 실패할 수 있습니다. Guava는 Preconditions 클래스를 일반적인 필수조건의 시리즈로 제공합니다.

필수조건을 위해서 if문과 명시적인 예외를 던지는 예제가 있습니다.


Java
1
2
3
if (count <= 0) {
  throw new IllegalArgumentException("must be positive: " + count);
}

명시적으로 필수조건을 작성할 수 있습니다.

Java
1
2
// in Guava
checkArgument(count > 0, "must be positive: %s", count);

결론
존재하는 라이브러리 클래스를 Guava로 교체하는 것은 유지보수를 위해 필요한 많은 양의 코드를 줄여주고 잠재적으로 생산성을 높여줍니다. 예를 들어 Apache Commons 프로젝트의 대안이 될 수 있습니다. 당신은 이미 이러한 라이브러리를 알고 있거나 사용할 수도 있고 Guava의 접근과 api를 선호할 수도 있습니다. Guava는 Idea Graveyard를 가지고 있습니다. Idea Graveyard 구글 엔지니어들이 라이브러리의 제한과 나쁜 디자인 결정에 대해서 무엇을 이해하고 있는가에 대한 아이디어를 줍니다. 자신만의 라이브러리 클래스를 작성하는 것으로 다시 돌아간다는 점에서 이러한 결정에 개인적으로 동의하지 않을 수도 있습니다. 그럼에도 불구하고 Guava는 간결하고 적은 형식을 장려하고 Guava의 몇몇 적절한 애플리케이션의 많은 자바 프로젝트에 도움이 될 수 있습니다.


[JAVA]List에서 중복요소 제거한 List로 만들기..

출처 : Outsider's Dev Story https://blog.outsider.ne.kr/

자바에서 List를 사용하다가 List가 가진 요소들 중 중복된 것을 제거하고 유일한 값들만 가지고 있는 List를 만들어야 할 필요가 있었습니다. 루프를 돌면서 유니크한 값을 찾아서 새로운 배열을 만들자니 약간 귀찮았는데 해쉬셋을 이용해서 간단하게 유일한 요소들만 가진 List로 만들 수 있더군요.

Java
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
List<Integer> items = new ArrayList<Integer>();
items.add(1);
items.add(2);
items.add(1);
items.add(2);
items.add(3);
items.add(3);
System.out.println(items); // [1, 2, 1, 2, 3, 3]

List<Integer> uniqueItems = new ArrayList<Integer>(new HashSet<Integer>(items));
System.out.println(uniqueItems); // [1, 2, 3]

중복되는 요소들을 가질 리스트를 HashSet으로만든뒤에 다시 List로 변환을 하면 중복요소가 사라진 유일한 요소들만 가진 리스트를 만들 수 있습니다.

덧) 저의 경우에는 필요치 않았지만 HashSet을 사용할 경우 순서가 지켜지지 않을 수 있다는 얘기가 있었습니다.

덧2) 김은석님이 List의 contains와의 성능비교를 공유해 주셨습니다.


My Comment..
흠.. 현재 SM 소스를 검색해보니 과거 2013년에 사용한 흔적이 있었다.. 거기에 주석도 코멘트 했었구나.. 배열처리 중복제거 라고.. ㅋㅋㅋ.. 햄보다 2년정도 늦게 쓰긴 했는데 쓰긴 했었구나.. 다만 햄은 기록을 해서 새로운 것에 대해서 항상 남겨두는 편인데 나는 그게 아니였다능.. 무튼 지금이라도 검색해서 다시 한번 기억속에서 상기시키니 스믈스믈 떠오르고 있다..