[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...

2017년 3월 28일 화요일

[Talk] 1Password과 Authy를 사용한 계정 관리..


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

비밀번호 관리는 참으로 어려운 일이다. 사용하기도 어느 정도 편하면서 보안도 유지되어야 하는데 이 둘을 한꺼번에 관리하기가 만만치 않다. 정확한 가이드는 없지만, 영문 대소문자, 숫자, 특수기호를 다 조합해서 최소한 10자 이상(많을수록 좋지만)의 비밀번호를 사이트마다 다르게 관리하면 아주 좋을 것이지만 이렇게 관리하기는 거의 어렵다. 비밀번호도 실제 존재하지 않는 단어가 좋겠지만 외우기가 어렵다. 그래서 사이트마다 어떤 룰을 만들어서 비밀번호를 관리하는 팁들도 있긴 하지만 사용하기 어려운 건 마찬가지다.

비밀번호를 민감하게 관리하는 편은 아니다가 어느 날 문득 Gmail을 털리는 순간 대부분 계정이 다 털리겠구나 하는 생각이 들었다. 그래서 지금은 1Password를 사용하고 있다. 이전에도 비밀번호 관리 프로그램들을 좀 써봤지만 그리 만족도가 높지 않았고 1Password에 대한 소문은 어느 정도 들어봤지만, 선뜻 구매하기는 어려웠다. 맥용이 49.99달러, 윈도우가 49.99달러, iOS 용이 8.99달러다.(이제 보니 안드로이드용은 무료인가?) 어쨌든 다 사려면 10여만 원이 필요하고 맥용과 iOS용만 사도 6만 원 정도는 든다. 1Password는 세일을 제법 자주 하는 편이라(지금도 Heartbleed 보안 이슈 때문에 세일중이다.) 1년 정도의 시간을 주고 하나씩 구매를 했다.

1Password

여기서 프로그램 사용법을 일일이 설명하긴 좀 힘들고 내가 써보면서 좋았던 점은...
  1. 브라우저 익스텐션을 통해서 로그인할 때마다 비밀번호를 저장할 수 있다. 처음 새로운 프로그램을 사용할 때 불편한 점이 기존에 사용하던 계정을 일일이 입력하는 부분인데 이 귀차니즘을 크게 해결해 준다. 중요 계정만 입력해 놓고 계속 사용하다 보면 하나씩 새로 추가할 수 있고 시간이 지날수록 종종 가는 사이트들은 대부분 1Password를 통해서 관리할 수 있게 된다.
  2. 비밀번호 자동입력을 지원한다. 1Password에 계정을 관리하기 시작하면 로그인 페이지에 접속했을 때 1Password mini를 단축키로 열면 자동으로 최상단에 현재 사이트가 나타나고 바로 아이디와 비밀번호를 입력해주고 로그인을 한다.
1Password mini
  1. 비밀번호를 외우고 있을 필요가 없다. 1Password를 통해서 계정을 관리하기 시작하면 굳이 비밀번호를 외우고 있을 필요가 없어진다.(저장해 놓고 불러와서 로그인하면 되니까...) 그래서 사이트마다 다른 비밀번호를 부여할 수 있고 외울 수도 없는 특수기호와 대소문자가 섞인 20~40자짜리 비밀번호를(중요도에 따라서..) 비밀번호로 사용할 수 있다. 1Password내에 비밀번호 생성기가 있어서 글자 수에 따라서 복잡한 비밀번호를 자동으로 만들어 준다. 읽을 수도 없는 20자짜리 비밀번호를 외울 수는 없으니 이를 비밀번호로 사용하기가 현실적으로 무리인데 1Password를 사용하면 이 부분이 해결되니 비밀번호 자체로도 크게 안심이 된다.
  2. 비밀번호를 언제든지 바꿀 수 있다. 이전에는 비밀번호를 어느 정도 공통으로 사용하려니 오래 비밀번호를 사용해서 한번 바꾸려면 보통 큰일이 아니고 실제로 다 바꾸기도 어렵다. A 사이트가 보안을 무척 잘 관리하는 사이트라고 하더라도 허술한 B 사이트에서 비밀번호가 해킹돼서 같은 계정으로 A 사이트에 접속해서 계정을 터는 일은 흔한 일이다. 이번에 SSL Hearbleed같은 이슈로 갑자기 비밀번호를 변경해야 할 때 무척 귀찮은 일이지만 사이트마다 비밀번호를 다르게 관리하고 있었다면 걱정이 많이 줄어들고 중요한 사이트만 한 번씩 바꿔주면 될 일이다. 어차피 외우고 있지도 않았으므로 그냥 비밀번호 새로 생성해서 변경하면 된다.
  3. 데이터베이스를 로컬에서 파일로 관리한다. 이전에 사용하던 대부분 서비스는 데이터베이스가 웹에 올라가 있었다. 웹에 올라가 있으니 어디서나 접근할 수 있어서 편리한 점이 있기는 하지만 솔직히 불안한 점도 있다. 하지만 1Password는 이 데이터베이스가 내 로컬에 있으므로 내 로컬파일만 잘 관리하면 유출될 걱정이 없으므로 꽤 안심된다. 다른 곳에서도 사용하고 싶다면 Dropbox나 iCloud로 동기화를 할 수도 있다. 이쪽도 웹에 올라가 있는 건 같지만 1Password와 직접 의존성이 있는 서비스도 아니고 사용자의 선택에 따른 것이므로 훨씬 좋은 접근이라고 본다.
물론 한곳에서 관리하므로 1Password가 털리면 다 털린다는 단점이 있기는 하다. 그리고 1Password가 없으면 로그인을 할 수 없다는 문제가 있기는 한데 나는 iOS도 사서 보고 입력한다. 비밀번호가 복잡해서 입력할 때 귀찮기는 하지만 내 맥북외에서 로그인하는 경우가 많지도 않고 안전하다고 생각하면 참아줄 만한 불편함이다.

Authy

1Password로 비밀번호의 보안을 높이면 털릴 염려가 많이 줄어들기는 하지만 그래도 일단 털리면 무척 피곤한 사이트들이 있다. 예를 들어 나 같은 경우 각종 서비스에 등록된 Gmail이나 개인 사생활과 연결된 Twitter, Facebook 혹은 프로그래밍 관련 작업들이 있는 Github나 서버 호스팅 같은 경우 털리면 타격이 무척 크다. 그래서 이런 곳에는 2단계 인증을 사용하고 있다. 2단계 인증이란 것은 보통 은행해서 사용하는 OTP를 얘기하는데 나는 Authy라는 앱을 사용하고 있다.
Authy 앱

OTP에 대해서 자세히는 모르는데 어떤 표준이 있는 건지 각 사이트가 Authy랑 계약을 한 것인지 잘 모르겠지만, Gmail, Facebook, Github, Dropbox, Digital Ocean 등의 사이트 대부분이 Authy를 통해서 2단계 인증을 할 수가 있다. 사이트마다 약간씩 다르지만 각 사이트의 보안 부분에서 2단계 인증을 사용하기로 하면 QR코드가 나타나는데 이를 Authy로 찍으면 자동으로 OTP가 등록되고 이후로는 OTP 코드를 Authy 앱에서 확인할 수 있다.(Twitter 2단계 인증은 메커니즘이 좀 달라서 안 된다.)

그래서 중요사이트에 로그인할 때는 1Password로 로그인을 하고 Authy로 2단계 인증을 하니까 웬만한 유출사건이 발생해도 크게 걱정이 되지 않는다. 2단계 인증은 입력할 때 무척 귀찮기는 한데 대부분 자주 사용하는 기기는 등록해서 2단계 인증을 안 받게 할 수 있는 옵션을 제공하고 다른 곳에서 할 때만 2단계 인증을 요청하므로 보안에 대한 안심은 크게 높이면서 적당한 불편함으로 사용할 수 있다. 모바일에서 로그인할 때 상당히 귀찮기는 하지만 여러 달 사용하는 중인데 아직 만족도가 꽤 높다.(Authy는 사용자는 무료로 사용할 수 있다.) 특히 요즘처럼 하루가 멀다 하고 개인정보 유출사건이 터지는 때에는 2단계 인증을 사용하길 잘했다는 생각을 하고 있다.

My Comment..
해당 글이 비록 2014년도에 작성이 된 글이긴 하지만.. 가져온 이유는 보안에 대한 부분 때문에 나도 고려를 해봐야하는건가..?? 라는 생각에서다..

요즘 빈번하게 보안 사건 사고가 터지고 있고, 얼마전 모텔 앱에서 터진 부분도 새삼 떠오르게 만들긴 한다.. 내가 비록 금융권에서 일을 하고 있긴 하지만 그렇다고 해서 앞에 언급한것에 비해 나 스스로 보안 자체에 대해서 엄청 민감한것만은 또 아니다..

다만, 최대한 불필요한 사이트에 가입을 하지 말자 말자하면서도 가입하고, 로그인하게 되는 사이트가 꽤나 많아졌기에 과거처럼 어디에 적어둘 수도 없고, 그렇다고 스마트폰에 기록해둘 수도 없는 노릇이니 해당 글을 유심히 보게 되었다.. 나 스스로에게 도입을 할지는 모르겠지만 이 또한 관리를 위해서 이것저것 봐야되는 상황이 생기다보니.. ㅎㅎㅎ.. 그래도 장기적으로 봤을 때 일정하게 관리를 해서 한 곳에서 컨트롤 하는게 좋을듯하다는 생각이 많이 든다.. 심히 고민해봐야겠다..

[NEWS] 기술 뉴스 #6 : 14-04-1..


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

웹개발 관련

그 밖의 프로그래밍 관련

  • Emacs is sexy : 아주 섹시한(?) 도메인을 가진 이멕스 소개사이트를 어떤 분이 이미 우리말로 번역해서 호스팅하고 있다.(한글)
  • Trello 아키텍처 : Trello 서비스 구성에 어떤 기술을 어떻게 사용했는지 자세히 나와 있다.(한글)
  • Crypto 101 : 암호화와 관련된 기본적인 내용을 PDF로 만들어서 제공한다. 현재 pre-release 상태(영문)
  • WELCOME TO UNREAL ENGINE 4 : Epic의 언리얼 엔진의 새 버전이 공개되었다.(영문)
  • Apache Tajo is now a top level Project! : Apache Tajo가 인큐베이팅 단계에서 최상위 프로젝트로 올라갔다.
  • WebScaleSQL : Facebook, Google, LinkedIn, Twitter가 함께 만들어서 오픈한 프로젝트로 MySQL에 기반을 둬서 더 많은 데이터를 처리할 수 있게 하려는 프로젝트를 공개했다.(영문)

IT 업계 뉴스

볼만한 링크


2017년 3월 23일 목요일

[NEWS] 기술 뉴스 #5 : 14-03-15..


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

웹개발 관련

그 밖의 프로그래밍 관련

IT 업계 뉴스

  • Apple CarPlay : 애플이 아이폰을 자동차와 연결할 수 있는 CarPlay 페이지를 공식 열었다.

볼만한 링크


[EP] Inspire 자바스크립트 컨퍼런스의 Firejune님 발표에 대해..


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

지난주 금요일(28일)에 열린 Inspire 자바스크립트 컨퍼런스에서 Firejune님의 발표를 보고 SNS에 감탄을 쏟아내면서 의도치 않게 사람들에게 궁금증은 유발하면서 뭔지 알려주지는 않는 낚시가 되어 버렸다. 뭔가 설명을 하고 싶기도 했지만 글로 설명하기도 어려워서 그랬던 것인데 결과적으로는 낚시가 되어버렸고 이에 대한 책임감(?)이 좀 느껴져서 정리한다.(글로 제대로 전달될지 불안할 따름이다.)

Mobizen 화면
사진 출처: https://play.google.com/store/apps/details?id=com.rsupport.mvagent

Firejune님의 발표에서 놀랐던 것은 발표내용보다는 데모에서였는데 위의 화면에 보이는 웹 애플리케이션이다. 초반에 "좀 다르게 개발하기"에 대해서 웹소켓 등의 얘기를 하면서 듣고 있다가 약간의 집중력이 흐트러질 무렵 위의 데모를 보여주셨다. 처음에 데모를 보면서 "저게 무슨 화면인가?"하고 쳐다보면서 이해하는데 약간의 시간이 걸렸다. 사실 처음에는 웹 애플리케이션이 있고 안드로이드가 잘 안 보이니까 에뮬레이터 같은 프로그램을 그 위에 띄워놓은 줄 알았다.
  • 위 PC의 화면(iMac안에 있는)은 웹페이지이다.(이런저런 검색해보면 비슷하게 생긴 앱도 있는듯한데 내가 본 건 웹이었고 기존의 것을 웹으로 포팅한 것인지 등에 대한 자세한 내용은 잘 모르겠다.)
  • PC화면에 나타난 안드로이드 기기는 자신의 안드로이드 기기와 연결되어서 상호 간 원격 조종을 할 수 있다.
    • 안드로이드에서 스크롤을 하면 PC의 화면도 스크롤이 되고 그 반대로도 된다.
    • 안드로이드 기기를 가로로 눕히면 PC의 안드로이드 기기도 자동으로 옆으로 돌아간다.
    • 안드로이드에서 YouTube 앱 같은 것을 실행시켜서 동영상을 재생하면 거의 실시간으로 PC에서도 동영상이 재생되고 앱이 변경되는 애니메이션까지 모두 재현된다.
  • PC 화면에서 스냅샷이나 동영상 녹화를 하면 화면을 이미지로 저장하거나 녹화할 수 있고 이는 기기에도(아마도...) 저장된다.
  • PC 화면에 나와 있는 아이콘들은 안드로이드의 관리 애플리케이션이다.
    • 음악 아이콘을 클릭하면 아이튠스 같은 UI의 화면이 나오면서 안드로이드 기기에 있는 음악목록을 가져오고 바로 재생할 수 있다.
    • PC에 있는 음악을 바로 안드로이드에 넣을 수도 있다.
    • 사진, 동영상도 마찬가지로 안드로이드 기기의 내용을 그대로 읽어와서 화면에 보여준다.
글로 써서 무미건조해 보이지만 위의 내용이 데모의 주된 내용이다. 여기까지 보면 "이거 가지고 그렇게 낚시한 거야?"라고 반응할 수도 있는데 SNS에서도 제대로 설명하지 못한 것도 내가 본 걸 글로 얼마나 전할 수 있을지 몰랐기 때문이다.
내가 이해한 차원에서(그러므로 실제 구현과 약간 다를 수도 있다.) 동작 방식을 좀 더 보자.
  1. 안드로이드와 웹페이지는 웹소켓으로 연결되어 있다.
    • 중간에 웹서버가 하나 있지만, 이는 회원의 로그인 후 안드로이드 기기와 웹페이지를 연결해 주는 역할만 하고 빠지는 걸로 보인다. 그래서 실제 동작할 때는 웹페이지와 안드로이드 기기만 서로 연결되어 있다.
    • 안드로이드에 어떤 앱 같은 게 돌고 있고 여기에 웹소켓 서버가 떠 있고 이 웹소켓 서버랑 웹페이지가 연결된다.
    • 이 앱에서 웹소켓으로 안드로이드의 변화를 웹페이지에 보내고 받는데 내가 안드로이드 개발자가 아니라 이쪽은 정확한 메커니즘은 모르겠다.
    • 원격 제어 부분은 Rsupport의 전문 분야이므로 이에 대해 기본에 갖추고 있는 기술력을 사용했을 거라고 보인다.
  2. 이미지, 음악, 동영상들도 모두 웹 소켓을 이용해서 데이터를 주고받는다.
    • 최초에 연결하면 안드로이드의 내용을 인덱싱하느라 약간의 시간이 걸리지만, 그 결과를 로컬 스토리지에 저장하므로 그 이후부터는 빠르게 목록을 불러온다.
    • 실제 미디어(사진, 음악, 동영상 등)는 로컬에 저장하는 것이 아니라 사용자가 재생할 때 안드로이드에서 웹소켓으로 가져온다.
    • 데모 상의 체감속도로는 거의 데스크톱 수준의 속도였다.(물론 데모에서는 USB로 연결되어 있었고 네트워크면 네크웍의 속도에 따라 다를 것이고 상황에 따라 가장 빠른 속도를 알아서 찾아서 접속한다.)
    • 이미지뿐만 아니라 동영상 등도 거의 딜레이없이 PC에서 재생해 볼 수 있다.
    • 이미지나 음악을 안드로이드기기로 업로드하는 경우에 웹페이지에 올리는 것이 아니라 로컬의 파일을 웹소켓으로 바로 안드로이드로 쏜다.
  3. UI
    • UI는 위 스크린 샷처럼 블러가 먹은듯한 배경 이미지가 깔렸고 그 위에 투명 혹은 반투명의 화면들이 동적으로(축소되거나 페이드인/아웃되는 등) 변화한다.
    • 크롬에서 시연했는데 HTML5와 CSS3를 사용한 것으로 보여서 다른 브라우저에서는 어떤지 모르겠다.(최소한 같은 퍼포먼스나 효과는 나오지 않을 것이다.)
    • 거의 데스크톱앱 수준의(좀 구린 데스크톱앱이라면 그 이상) 메뉴 전환속도와 화려한 애니메이션 효과를 보여준다.
내가(나를 포함한 주위 사람의 상당수) 머리를 한 대 맞은 듯 멍해진 것은 위의 3번 부분이다. 안드로이드에서 데이터를 보내는 건 내가 모르는 분야이므로 궁금하긴 하지만 신기한 정도까진 아니고 웹 소켓이 제공하는 속도가 있으므로 이를 이용해서 데이터를 보내면 만들어 낼 수는 있을 것 같다.(먼저 이렇게 할 생각까진 못했겠지만...)

충격받은 건 UI와 그 성능이다. 웹에서 WebGL이나 SVG 등을 사용한 효과 등을 제외하고 상상할 수 있는 거의 모든 애니메이션 효과가 그 사이트에 들어가 있었지만 하나도 느리지 않았다. 눈으로 보기에 당연히 저런 효과가 들어갔으면 대충 어떤 기술을 사용했을지 머릿속에 그려지고 그거에 대한 퍼포먼스가 생각나서(물론 아주 하드코어 하게 튜닝을 해본 적까진 없지만...) 분명히 딜레이가 있어야 하는데 그런 게 하나도 없이 아주 자연스럽게 돌아갔다.(말도 안 돼!)

이번 파이어준 님의 발표는 생각지 못한 놀라운 기술을 보여줘서 놀랜 것이 아니라 나도 아는 기술인데 그걸 이용해서 엄청난 퀄리티로 만들어냈기 때문이다.** 개별 이펙트를 데모로 만들어 낸다고 생각하면 불가능한 일은 아니지만 이를 하나의 앱으로 만들고 비즈니스 로직까지 섞인 곳에서 전혀 딜레이없는 웹 애플리케이션을 만들어 내는 것은 완전히 다른 차원의 얘기다. 내가 그동안 HTML5나 CSS3에 대해서 뭐 자신감을 느끼고 있거나 그런 것은 아니었음에도 그냥 머리를 한 대 맞은 것 같았다. 파이어준 님은 보여주면 "우와~~"하는 반응을 기대하셨던 것 같은데 눈앞에 보이는 데모를 믿을 수가 없어서 아무런 반응을 할 수 없었다. 트위터에 낚시처럼(고의는 아닙니다.) 쓴 대로 "이게 뭐야?", "이게 말이 돼?"가 내 머릿속에 전부였다.(당시에는 지금 어떻게 데이터를 주고받고 돌아가는 것인가에 대한 고민도 같이 하고 있었지만...) 아마 이 데모는 HTML5/CSS3를 많이 만져봤을수록 충격을 받을 만한 내용이라고 생각하고 뒤풀이에서 얘기가 나온 대로 해보지 않았다면 "요즘 CSS3도 많이 좋아졌네!"정도로 대수롭지 않게 생각할지도 모르겠다.(파이어준 님이 워낙 아무렇지 않게 설명하기도 했고...)

난 웹을 좋아한다. 그래서 웹이라는 플랫폼의 미래에 대해서 가치를 많이 두는 편이지만 현시점에서의 내 생각은 "네이티브와 비교할 때 UI 등에서 어느 정도 타협을 본다면 지금도 해볼 만 하다"였는데 그런 타협이 없이 네이티브 이상의 웹애플리케이션을 봤기 때문에 생각이 완전히 달라졌다.(물론 전혀 타협이 없을 린 없고 그런 느낌이 들 정도로 만들어 낸 것도 엄청난 기획력이라고 본다.) 아래 이미지는 나랑 같은 기분을 느낀 지인이 SNS에 올린 짤방인데 공감이 가서....

겸손해지려 하지마. 넌 그만큼 대단하지 않아.

2017년 3월 20일 월요일

[Talk] SPRING CAMP 2017..


세미나 소식이 있어서 급하게 글을 올려본다.. 물론 내 블로그를 통해서 찾아가실 분이 많지는 않겠지만.. 그래도.. 올려는 봐야지.. 혹~~~시나.. ㅎㅎㅎ..

제목처럼  SPRING CAMP 2017 이다.. 회사에서는 보안으로 인해서 못들어가는데 친구가 알려줘서 지난주부터 관심있게
지켜보고 있었다.. 작년에도 참석했었는데 재미있었기에.. 과연 언제부터 등록이 가능하려나 했는데 말이지.. 금일 오후 12시부터 시작한다고 하니 혹.. 해당 글을 보시는 분들은 참여하면 좋을 듯 하다..

특히나 이번에는 10주년 기념으로 4월 22일 ~ 4월 23일 2틀간이나 한다고 한다.. 난 우선은 22일 하루만 지원하려고 하는데 그날도 개인 사정을 봐야되서 어찌 될지는 모르겠다..

신청은 온오프믹스로 이동해서 하면 된다.. 아래 관련 이미지를 첨부하니 참고해서 신청하면 되겠다..




2017년 3월 16일 목요일

[NEWS] 기술 뉴스 #4 : 14-03-1..


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

웹개발 관련

그 밖의 프로그래밍 관련

  • 스크럼 가이드 : scrum.orgScrum Guide가 한글로 번역되어 PDF로 공식등록되었다. 20페이지 정도 되는 스크럼 가이드다.
  • Atom : Github에서 Node.js 기반으로 웹 기술로 구현한 데스크톱용 에디터를 발표했다. 자세한 내용은 [Github의 Atom 에디터 살펴보기](Github의 Atom 에디터 살펴보기) 참고.

IT 업계 뉴스

읽을 만한 링크

  • 2013 Stack Overflow User Survey Results : 스택오버풀로우에서 사용자 설문조사에 대한 인포그래픽을 공개했다. 이 자료를 통해서 스택오버플로우가 어떤 언어를 사용하고 어떤 목적으로 스택오버플로우를 방문하고 일하는 형태는 어떤지 등을 볼 수 있다. 이 글에서 전체 설문결과를 엑셀파일로 다운로드 받을 수 있으므로 관심 있다면 원하는 내용을 통계 내서 볼 수 있다.(영문)
  • Satya Nadella - 마이크로소프트의 신임 CEO : 마이크로소프트의 새 CEO Satya Nadella가 직원에게 보낸 편지의 번역본.(한글)

2017년 3월 13일 월요일

[UFC] 비토 벨포트 21년 선수생활 마감.. 이라니..


지난 주말 UFC Fight Night 106 이벤트를 시청했다.. 관심이 가는 경기는 막판에 나오는 경기들이었는데 특히나 과거의 향수를 자극하는 쇼군비토 벨포트 경기였다..

과거 PRIDE 시절부터 화끈한 경기덕에 상당히 좋아했던 쇼군은 다행히도[?] KO 승리를 했다.. 다음은 벨포트 경기였는데 조금 걱정이 되긴 했다.. 요근래 하락세이기도 하지만 상대가 켈빈 가스텔럼 이란 선수로 벨포트에 비하면 25살에 불과한 신예이기도 하지만 원체 펀치력이나 레슬링 등등 모든 면에서 잘하는 선수여서 단순히 경험만으로 바탕으로 이기기에는 조금 무리가 있을수도 있기 때문이었다.. 무엇보다 요즘 레전드라고 불리우는 선수들이 하나둘씩 경기에 지면서 떠나는 분위기나 그런 분위기가 조성되어가고 있어서 더 걱정을 좀 했었다..

이유야 어찌 되었건 나는 가스텔럼 보다는 벨포트 팬이기에 벨포트를 응원하면서 이벤트를 시청했는데 흠.. 역시나 아쉽게도 KO 로 패하고 말았다.. 경기력이야 어찌되었건 노익장을 과시해준 벨포트에게 감사할 따름이다.. 그런데 나에게는 이런 경기에 관련된 뉴스보다 오늘 새롭게 접한 뉴스가 조금 더 놀랍다고 해야될까 관심이 갔는데..

벨포트가 이제 21년 선수생활을 마감하려고 한다는 것이다.. 언젠가는 은퇴를 하기야 하겠지만 왠지 섭섭하기도 하다.. UFC 를 시청한 날은 뉴스를 따로 찾아보지는 않기에 오늘 해당 뉴스를 접하게 되었는데 모든 경기가 끝나고 인터뷰 자리에서 이렇게 말했다고 한다..

"UFC와 계약상 한 경기가 남아 있다. 그 경기는 고향 리우데자네이루에서 펼치고 싶다 UFC에서 노장들이 뛰는 '레전드 리그'를 만든다면 선수 생활을 조금 더 이어 갈 수 있겠지만, 5라운드를 준비하는 건 이제 무리"라고..


▲ 비토 벨포트가 은퇴전을 치르고 선수 생활을 마감하겠다고 밝혔다.

내가 매체를 보고 알기로는 벨포트는 19살에 격투기에 데뷔했다.. 정말 오랜 시간 활동했고, 더 대단한 것은 그의 커리어에서 항상 상위권을 유지했다는 것이다.. 은퇴전 1경기를 포함한다면, 그의 통산 전적은 39전 25승 14패에서 40전이 될 것이다..

비록 누구와 싸우게 될지는 모르겠지만 은퇴경기인 만큼 기념적인 선수와 경기를 하고서 유종의 미를 거둘 수 있기를 바란다.. 마지막 경기에 대한 그의 생각을 끝으로 해당 글을 마치려고 한다.. 비토 벨포트.. 그동안 감사했습니다.. 당신 덕에 항상 화끈한 경기 즐거운 경기를 볼 수 있었습니다..

"염두에 둔 상대는 없다. 브라질에서 브라질 선수와 싸우고 싶지 않다. UFC와 상의하겠다. UFC가 제안한 경기를 거부하지 않았다. 강자들과 싸워 왔다. 그러나 마지막은 팬들에게도 특별한 경기가 돼야 한다." 

2017년 3월 9일 목요일

[NEWS] 기술 뉴스 #3 : 14-02-16..


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

웹개발 관련

  • Bootstrap accessibility plugin : Paypal이 공개한 Bootstrap의 접근성을 높혀주는 플러그인이다. Bootstrap 3의 기본 컴포넌트들을 키보드로 조작할 수 있는 기능을 추가하고 현재 페이지에서 사용한 컴포넌트들에 필요한 ARIA role과 state를 추가한다. 데모페이지, (영문)(영문)
  • Introducing App Insights 2.0 Beta : 페이스북의 앱(API등을 사용하기 위해서 등록하는 앱)의 통계를 볼 수 있는 "앱 인사이트"의 2.0 베타 버전이 공개되서 베타버전 사용하기를 클릭하면 써볼 수 있다.(영문)
  • GitHub Security Bug Bounty : Github에 보안 이슈를 보고하면 보상을 해주는 바운티 프로그램, 이슈에 따라 100~5,000달러까지 보상해준다.(영문)
  • Infinite scroll search-friendly recommendations : 구글 웹마스터 블로그에서 무한 스크롤을 검색엔진이 색인화하게 하는 권장사항을 공개했다. 페이지의 내용은 JavaScript 없이도 접근할 수 있고 URL을 구조적으로 만들어서 무한 스크롤되는 아이템들은 URL에 따라 겹치지 않게 구성해야 한다. 그리고 페이징은 rel="next" rel="prev" 로 제공한다.(영문)
  • Compiling in the background for a smoother user experience : 크로니움이 크롬 베타버전에 자바스크립트를 백그라운드에서 실행과 동시에 컴파일해서 최적하 하는 기능을 추가했다. 이 기능은 몇달내에 크롬 안정버전으로 들어올 예정이다.(영문)

그밖의 프로그래밍 관련

  • 도커(Docker) 튜토리얼 : 깐 김에 배포까지 : 가상화 어플리케이션 Docker의 사용법이 잘 정리된 입문용 튜토리얼.(한글)
  • A Good Vimrc : Vim의 설정파일인 vimrc 파일을 어떻게 관리하는 가에대한 팁을 공유한 글이다. 이해하지 못한 옵션은 vimrc에 두지 말것을 권하면 각 옵션을 상세히 설명하고 vimrc를 어떻게 관리하는지를 보여준다.(영문)
  • Ready to cast: Chromecast now open to developers with the Google Cast SDK : 구글이 작년에 발표한 모바일기기의 화면을 TV로 공유할 수 있는 크롬캐스트SDK를 공개했다.(영문)
  • What's in my iOS Toolbox? : Eduardo Diaz Sancha라는 개발자가 iOS 개발을 할 때 기획부터, 디자인, 개발까지 사용하는 도구들을 리스트업한 글. 2편도 있다.(영문)
  • TECHNOLOGY RADAR : 소트웍스에서 정기적으로 내놓는 기술 레이더의 1월 버전이다. 기술, 플랫폼, 도구, 언어(프레임워크)별로 카테고리화해서 어떤 기술이 어느 정도 현장에 자리잡았는지를 보여준다.(영문)
  • Kakao Developers : 카카오에서 카카오톡과 연동한 앱을 만들 수 있는 SDK를 공개했다. 송성광님의 [카카오 Kakao SDK로 안드로이드 앱 개발(1편, 2편)연재도 참고.

IT 업계 뉴스

  • The npm Blog - Funding : npm을 만든 Issac이 얼마전 Joyent를 나와 npm Inc라는 회사를 설립했는데 여기서 260만 달러 펀딩을 받았다.
  • 37signals - Two big announcements. : 37signals가 15주년을 맞이해서 앞으로의 사업방향은 자사의 핵심제품인 Basecamp 중심으로 가고 회사명도 Basecamp로 바꾼다고 발표했다. 37signals는 협업도구등을 만드는 회사로 Rework, Remote등의 책을 썼고 대표적으로 Rails를 만든 dhh가 있는 회사다.
  • Microsoft의 새 CEO "Satya Nadella" (영문)

읽을 만한 링크


[UFC] UFC 마감뉴스..


출처 : SPOTV NEWS


2017년 3월 8일 수요일

[JS] 크롬 개발자도구의 콘솔을 차단하는 방법..


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

트위터에서 올라온 링크로 보게 된 Stackoverflow의 글을 보고 트위터에 올렸더니 꽤 많은 리트윗이 일어나서 블로그에도 한번 정리해 둔다. 윗글에 자세한 내용이 나오긴 하지만 정리하자면 이렇다.[트위터 글인데 별도로 가져오지 못해서 해당 부분은 취소처리한다..] 어떤 사람이 페이스북에 들어갔더니 크롬에서 콘솔을 사용할 수 없게 막혀있는데 어떻게 막은 거냐 하는 질문이고 여기에 페이스북의 보안 엔지니어라는 사람이 나타나서 사용자가 콘솔을 이용해서 공격할 수 있는지 테스트하느라고 일부 사용자에게 적용되었던 거라고 답변을 달았다.

1
2
3
4
5
JavaScript

with ((console && console._commandLineAPI) || {}) {
  // code here
}

크롬의 콘솔은 위의 코드로 모두 감싸아져 있으므로 여기서 console._commandLineAPI 를 재정의해서 오류를 던지도록 하면 사용자가 크롬에서의 개발자도구로 콘솔을 사용할 수 없게 할 수 있다.

1
2
3
JavaScript

Object.defineProperty(console, '_commandLineAPI', { get : function() { throw '콘솔을 사용할  없습니다.' } });

웹페이지에서 위 코드를 추가하면 해당 페이지에서 크롬 콘솔을 사용하면 다음과 같이 오류가 난다. 콘솔에서 코드를 사용하면 다 오류가 발생하고 자동완성도 동작하지 않는다. 물론 이 코드는 위의 크롬 콘솔이 코드를 감싸는 구조를 이용한 것이므로 페이지의 자바스크립트로 삽입해야지 크롬 콘솔에서 위 코드를 입력한다고 콘솔이 차단되지 않는다. 위의 Object.defineProperty()는 ES5에 들어간 객체의 프로퍼티를 다루는 API다.


위의 코드를 추가하고 크롬 콘솔을 사용한 화면

글을 쓴 김에 이 글에서 흥미로운 점이 있는데 페이스북의 개발자가 직접 나타나서 답변을 달았다는 점이다. 우리나라였으면 어땠을까 왠지 저런 내용을 공개적으로 쓰려면 회사의 허락을 받아야 될 것 같은 불안감도 있고 보고를 하면 아마도 나중에 가치가 있을지도 모르는 잠재력 있는 스킬일지도 모르니 공개하지 말라고 할 것 같다.(대부분은 자체검열로 답변을 안 달겠지.) 그리고 이 코드를 사용한 발단이 된 Self-XSS 공격도 한 번씩 보면 흥미롭다. 이런 공격은 취약점이라고 하기도 그렇고 참...

마지막으로 윗글의 답변에 나온 대로 보안 공격을 클라이언트에서 차단하려는 접근은 좋지 않은 방법이다. 어차피 우회하려고 맘먹으면 얼마든지 우회할 수 있으므로 보안이라는 의미도 그다지 없다. 왠지 이런 코드가 한때 국내 웹사이트의 기본처럼 되었던 "우클릭 방지"나 "텍스트 복사할 때 강제 출처 추가" 처럼 오용되지 않을까 하는 노파심에 그냥 이런 것도 가능하구나! 정도로 봐주시길...

My Comment..
해당 글은 햄의 말처럼.. 아 이런것도 있구나 하는 정도로 나 스스로도 참고용으로..?? 가져온 글이다.. ㅎㅎ

2017년 3월 7일 화요일

[EP] SSAG 2nd Seminar 후기..


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

페이스북의 Server Side Architecture Group(이하 SSAG)에서 2차 세미나를 해서 오랜만에 평일 저녁에 세미나에 참가했다. 나는 트위터를 위주로 사용하는 편이고 페이스북은 그 틈틈이 사용하는 편이라 여러 그룹에 가입되어 있지만, 그룹에 잘 들어가진 않는다. 사실 여러 그룹을 돌아보기 좋은 인터페이스도 아니긴 하지만 난 보통 글을 퍼블릭하게 쓰는 경향이 있어서 특정 그룹에 글은 잘 안 올리게 된다.(다른 사람은 반대인듯하다.) 어쨌든 SSAG는 꽤 큰 규모로 발전했고 얼마 전부터 세미나도 하기 시작했는데 이번이 그 2번째이다.

SSAG 시간표

MongoDB, 이렇게 쓰세요 - 한대희

온라인 데이팅 서비스인 이음에서 글로벌 데이팅 서비스로 만든 hey를 만들면서 MongDB를 적용했던 경험을 공유한 시간이었다. 내용은 발표자료에 잘 나와있으므로 굳이 따로 정리하지는 않겠다.(SSAG에서 동영상도 공유 예정인 걸로 알고 있다.)

나는 NoSQL 류에 관대한 입장을 가진 편이고 개인 프로젝트에서 MongoDB를 많이 쓰는 편인데 사실 이는 성능보다는(개인 프로젝트에서 스케일아웃 할 일이 있을 리가...) 개발 편의성 때문이다. 치밀한 계획하에 개발하지 않는 개인 프로젝트에서 MongoDB같은 스키마 없는 데이터베이스를 사용할 때의 편리함은 이루 말할 수 없다. 하지만 서비스로 나간다고 생각하면 글쎄... 쓰던 거니 고민은 하겠지만 덥석 쓰지는 않을 것 같다. 사실 이번 발표도 아주 깊은 내용이라기보다는 MongoDB는 사용 안 해봤지만 사용을 고려하는 입장에서는 미리 알면 도움될 부분이 상당히 많이 있다고 생각한다. 처음 발표한다고 하신 것 치고는 발표자료도 괜찮고 잘하신 듯...(나 처음 할 때 생각하면 덜덜덜)

이 발표의 결과에도 비슷한 얘기가 나오지만 조금 생각을 더하자면 난 기술을 좀 트랜디하게 쫓는 편이지만 새로운 기술을 사용할 때도 사람들이 너무 익숙한 기술의 결과와 수준을 비교한다고 생각하는 편이다. 오랫동안 잘 쓴 기술이 아무래도 더 잘 튜닝해서 쓰게 되어 있고 새로운 기술은 그러한 노하우가 없으므로 문서나 공유된 수준의 내용만 가지고 사용할 수밖에 없으므로 내부에 경험이 쌓이기 전까지는 아무래도 성능, 생산성 등의 저하를 경험할 수밖에 없는데 사람들은 종종 그런 단계를 한 번에 뛰어넘고 싶어하는 것 같다.(발표자분이 그렇다는 의미는 아니다.) 그리고 자주 나오듯이 NoSQL은 RDBMS를 대체하기 위해서 나온 것이 아니라 RDBMS가 커버하지 않는 부분을 커버하기 위해서 나온 것이다. 그럼에도 RDBMS의 대체재로 너무 1:1 비교개념으로 다가가면 자칫 망하기 쉽다.(DB에 대해 잘 아는 것이 아니므로 여기까지...)

발표 후 질답시간에 몇몇 질문에 대해서 청중에서 대신 답변을 하게 되면서 청중끼리 반박, 재반박이 이어지는 재미있는 토론이 있었다. 발표자 입장에서는 약간 곤혹스러운 상황일 수도 있겠지만 이렇게 자유로운 분위기(다양한 질문을 하고 그에 대해서 의견 있으면 서로 얘기하는...) 아주 좋다. 난 사실 발표 중에도 궁금한 게 있으면 손들고 묻고 그런 스터디스러운 발표를 더 좋아하는 편이다.

모바일 서비스 AWS 구축 경험 공유 - 김민태

NC Soft에서 소규모 팀으로 Chekit이라는 글로벌 서비스를 AWS에 구축한 경험을 공유한 발표로 AWS 기반 백앤드 구축에서 공유한 내용의 확장판이라고 볼 수 있다. 전에도 김민태님의 발표를 들은 적이 있는데 이번 발표도 세련된 발표자료에 능숙한 발표를 보여주셨다.(발표 중 여유로운 자세로 자연스러운 개그가 참 좋다.) 사용하는 개인 서버도 있고 AWS같은 확장성이나 유연성이 필요한 서비스를 만들어 본 적이없어서(혹은 AWS를 쓸 수 있는 환경이 아니거나) 주로 가상서버를 사용하고 있다. 그래서 AWS의 서비스들을 사용해 본적은 한 번도 없다. AWS의 인기가 워낙 좋으므로 관심은 상당히 있었지만 쓸 일이 없었던 탓에 관련 세미나도 별로 참여해보지 못했고 자세히 알지 못한다.

그런 면에서 나같이 AWS의 경험이 없는 사람에게는 아주 유용한 발표였다. AWS를 사용해 보지 않은 입장에서 서비스까지 구축하면서 고민한 부분과 삽질한 내용을 그대로 공유 받을 수 있었기 때문이다. 특히 AWS 서비스들의 가격(아무래도 가장 신경 쓰일 부분이니...)을 계산에 볼 수 있는 CloudMix의 서비스나 AWS에 구축할 때 사용할 수 있는 아키텍처 레퍼런스를 볼수 있는 페이지를 포함해서 Checkit이 어떤 아키텍처로 구성했는가 하는 내용은 나중에 AWS를 사용할 때 많이 도움이 될 것 같다.

AWS Cost Optimization: A journey to AWS cost optimization - 정유진

마지막에 미니 세션 비슷하게 AWS의 엔지니어분이 오셔서 AWS를 쓸 때 비용을 최적화해서 쓰려면 어떻게 해야 하는 가에 대해서 공유를 해주셨다. 나중에 AWS도 이제 한국에 들어와서 작년부터 세미나나 커뮤니티 등에서 이런 홍보를 많이 하는 듯한데 처음 듣는 나에겐 꽤 유용한 내용이었다. AWS를 사용할 때 가장 많이 하는 실수 중에 하나가 기존에 사내에서 사용하던 물리 서버와 같은 스펙으로 AWS를 같게 구축하는 것이다. 예시로 로드밸런서 1대, 웹서버 10대, 데이터베이스 서버 2대로 구성하면 한 달에 17,000불 정도가 나올 수 있다. 이렇게 구성한 경우 서버 대부분이 Idle 상태가 되는데 AWS의 비용은 "사용한 만큼 과금한다"는 개념이므로 이렇게 쓰는 것은 AWS를 제대로 쓰는 것이 아니다. EC2에는 "change instance type"라는 것이 있는데 이를 사용하면 5-10분 내에 원하는 대로 서버의 성능을 변경할 수 있다.

그래서 AWS를 사용할 때는 불필요하게 좋은 성능을 사용하지 않아야 한다. m3.xlarge를 m1.small로 바꾸고 db.m2.xlarge를 db.m1.small로 바꾸면 월 8,000불 정도로 줄일 수 있다. 여기에 EBS를 PIOPS에서 Standard 50GB로 바꾸고 RDS 볼륨을 1TB PIOPS에서 Standard 50GB로 바꾸면 월 700불까지로 내릴 수 있다. 보통의 서비스는 인바운드보다 아웃바운드 트래픽이 더 많은데 아마존은 아웃바운드 트래픽에 대해서만 과금을 하므로 AWS의 서비스를 적절히 이용하면 비용을 줄일 수 있다. 그리고 트래픽에 맞춰서 서버사양을 늘리는 오토 스케일링을 될 수 있으면 사용해라. 서비스 대부분은 시간별로 트래픽이 다른데 계속 좋은 사양을 유지하지 않고 트래픽 증가에 따라 자동으로 변경되게 설정하면 비용을 월 450불 정도까지 낮출 수 있다. 마지막으로 Reserved Instances를 사용하는 것이 좋다. Reserved Instances는 장기간(1년, 3년 등)의 비용을 미리 내면 할인을 해주는 과금체계인데 3개월 이상 쓰게 되면 웬만하면 Reserved Instances를 사용하는 것이 더 낮다. 서버의 최소 트래픽에 맞춘 사양 정도를 Reserved Instances로 사용하고 나머지는 오토스케일링으로 확장해서 쓰면 비용을 더 낮출 수 있다.

맺음말

오랜만에 평일날 참가한 세미나였는데 관심 주제이기도 했지만 발표도 괜찮고 사람들 호응도 좋은 즐거운 세미나였다. 더군다나 쟁쟁한 분들이 엄청나게 모여든.... 너무 인기가 좋아서 장소가 좀 협소하게 느껴진 게 아쉬웠다면 약간 아쉬웠고 평일날 저녁 8시에 시작한 세미나라 사람들과 교류를 나눌 시간이 좀 부족했지만 이건 뭐 어쩔 수 없는 부분이니..

2017년 3월 2일 목요일

[Spring 레퍼런스] 23장 JMX #2..


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

이 문서는 개인적인 목적이나 배포하기 위해서 복사할 수 있다. 출력물이든 디지털 문서든 각 복사본에 어떤 비용도 청구할 수 없고 모든 복사본에는 이 카피라이트 문구가 있어야 한다.

23.4 빈의 ObjectName 제어

내부적으로 MBeanExporter는 ObjectNamingStrategy 구현체에 등록하는 각 빈의 ObjectName을 가져오는 전략을 위임한다. 기본 구현체 KeyNamingStrategy는 beans Map의 키를 ObjectName로 사용한다. 그리고 KeyNamingStrategy는 beans Map의 키를 Properties의 항목에 매핑해서 ObjectName을 처리할 수 있다. KeyNamingStrategy외에도 스프링은 두 가지 ObjectNamingStrategy 구현체를 더 제공하고 있다. IdentityNamingStrategy는 빈의 JVM 아이디(identity)에 기반해서 ObjectName을 만들고 MetadataNamingStrategy은 소스수준의 메타데이터를 사용해서 ObjectName를 얻는다.

23.4.1 Properties에서 ObjectName 읽어오기

자신만의 KeyNamingStrategy 인스턴스를 설정해서 빈의 키를 사용하는 대신 Properties 인스턴스에서 ObjectName을 읽어오도록 구성할 수 있다. KeyNamingStrategy는 빈 키에 대응되는 키를 가진 Properties의 요소를 찾으려고 할 것이다. 일치하는 항목이 없거나 Properties 인스턴스가 null이라면 빈 키 자체를 사용한다. 아래 코드는 KeyNamingStrategy의 설정 예시를 보여준다.

 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
Xml

<beans>
  <bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
    <property name="beans">
      <map>
        <entry key="testBean" value-ref="testBean"/>
      </map>
    </property>
    <property name="namingStrategy" ref="namingStrategy"/>
  </bean>

  <bean id="testBean" class="org.springframework.jmx.JmxTestBean">
    <property name="name" value="TEST"/>
    <property name="age" value="100"/>
  </bean>

  <bean id="namingStrategy" class="org.springframework.jmx.export.naming.KeyNamingStrategy">
    <property name="mappings">
      <props>
        <prop key="testBean">bean:name=testBean1</prop>
      </props>
    </property>
    <property name="mappingLocations">
      <value>names1.properties,names2.properties</value>
    </property>
  </bean>
</beans>

여기서 KeyNamingStrategy 인스턴스는 매핑 프로퍼티와 매핑 프로퍼티에 정의된 경로에 있는 프로퍼티 파일로 정의된 Properties 인스턴스와 합쳐진 Properties 인스턴스로 구성된다. 이 구성에서 testBean 빈은 ObjectName bean:name=testBean1을 받을 것이다. 이는 이 값이 Properties 인스턴스에서 빈 키에 대응되는 키를 가진 항목이기 때문이다. Properties 인스턴스에 항목이 없다면 빈 키의 이름을 ObjectName으로 사용한다.


23.4.2 MetadataNamingStrategy의 사용

MetadataNamingStrategy는 ObjectName을 사용하기 위해 각 빈의 ManagedResource속성의 objectName 프로퍼티를 사용한다. 아래 코드는 MetadataNamingStrategy의 설정 예시를 보여준다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Xml

<beans>
  <bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
    <property name="beans">
      <map>
        <entry key="testBean" value-ref="testBean"/>
      </map>
    </property>
    <property name="namingStrategy" ref="namingStrategy"/>
  </bean>

  <bean id="testBean" class="org.springframework.jmx.JmxTestBean">
    <property name="name" value="TEST"/>
    <property name="age" value="100"/>
  </bean>

  <bean id="namingStrategy" class="org.springframework.jmx.export.naming.MetadataNamingStrategy">
    <property name="attributeSource" ref="attributeSource"/>
  </bean>

  <bean id="attributeSource" class="org.springframework.jmx.export.metadata.AttributesJmxAttributeSource"/>
</beans>

ManagedResource 속성에 제공된 objectName이 없다면 ObjectName은 [fully-qualified-package-name]:type=[short-classname],name=[bean-name]의 형식으로 생성될 것이다. 예를 들어 다음 빈에 생성된 ObjectName은 com.foo:type=MyClass,name=myBean가 될 것이다.

1
2
3
Xml

<bean id="myBean" class="com.foo.MyClass"/>


23.4.3 <context:mbean-export/> 요소

Java 5 이상을 사용함다면 MBeanExporter의 편리한 하위 클래스 AnnotationMBeanExporter를 사용할 수 있다. 이 하위 클래스의 인스턴스를 정의하면 표준 자바 어노테이션 기반의 메타데이터를 항상 사용할 것이므로 (자동탐지도 항상 활성화된다) namingStrategy, assembler, attributeSource 설정이 더이상 필요없다. 게다가 스프링의 'context' 네임스페이스가 지원하는 더 간단한 분법도 가능하다. MBeanExporter 빈을 정의하는 대신 다음의 요소를 지정하면 된다.

1
2
3
Xml

<context:mbean-export/>

필요하다면 특정 MBean 서버에 대한 참조를 제공할 수도 있고 defaultDomain 속성 (AnnotationMBeanExporter의 프로퍼티)은 생성된 Mbean ObjectNames의 도메인의 대체값을 받는다. 이전 MetadataNamingStrategy 섹션에서 설명한대로 이는 정규화된 패키지명에 사용한다.

1
2
3
Xml

<context:mbean-export server="myMBeanServer" default-domain="myDomain"/>


Note
빈(bean) 클래스에서 JMX 어노테이션의 자동탐지와 함께 인터페이스 기반의 AOP 프록시는 사용하지 말아라. 인터페이스 기반의 프록시는 대상 클래스를 '숨기고' JMX가 관리하는 리소스 어노테이션도 숨긴다. 그러므로 이러한 경우에는 대상클래스(target-class) 프록시를 사용해야 한다. 등의 'proxy-target-class' 플래그를 설정하더라도 JMX 빈은 구동시 이를 경고없이 무시할 것이다.


23.5 JSR-160 커넥터

리모트 접근을 위해서 스프링 JMX 모듈은 서버측과 클라이언트측 커넥터를 생성하는 org.springframework.jmx.support 패키지에서 FactoryBean의 두가지 구현체를 제공한다.

23.5.1 서버측 커넥터

스프링 JMX가 JSR-160 JMXConnectorServer를 생성해서 구동하고 노출하게 하려면 다음 설정을 사용해라.

1
2
3
Xml

<bean id="serverConnector" class="org.springframework.jmx.support.ConnectorServerFactoryBean"/>

기본적으로 ConnectorServerFactoryBean는 JMXConnectorServer을 "service:jmx:jmxmp://localhost:9875"에 바인딩해서 생성한다. 그러므로 serverConnector 빈은 MBeanServer를 localhost의 JMXMP 프로토콜과 9875 포트로 노출한다. JMXMP 프로토콜은 JSR-160 명세에 선택사항으로 나와 있다. 현재로써는 주요 오픈소스 JMX 구현체인 MX4J와 J2SE 5.0이 제공하는 구현체가 JMXMP를 지원하지 않는다.
다른 URL을 지정해서 JMXConnectorServer 자체를 MBeanServer에 등록하려면 serviceUrl과 ObjectName 프로퍼티를 각각 사용해라.

1
2
3
4
5
6
Xml

<bean id="serverConnector" class="org.springframework.jmx.support.ConnectorServerFactoryBean">
  <property name="objectName" value="connector:name=rmi"/>
  <property name="serviceUrl" value="service:jmx:rmi://localhost/jndi/rmi://localhost:1099/myconnector"/>
</bean>

ObjectName 프로퍼티를 설정하면 스프링이 해당 ObjectName의 MBeanServer에 커넥터를 자동으로 등록할 것이다. 다음 예제는 JMXConnector 생성시 ConnectorServerFactoryBean에 전달할 수 있는 전체 파라미터를 보여주고 있다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
Xml

<bean id="serverConnector" class="org.springframework.jmx.support.ConnectorServerFactoryBean">
  <property name="objectName" value="connector:name=iiop"/>
  <property name="serviceUrl" value="service:jmx:iiop://localhost/jndi/iiop://localhost:900/myconnector"/>
  <property name="threaded" value="true"/>
  <property name="daemon" value="true"/>
  <property name="environment">
    <map>
      <entry key="someKey" value="someValue"/>
    </map>
  </property>
</bean>

RMI에 기반한 커넥터를 사용한다면 이름 등록과정이 완료된 후 시작되도록 검색 서비스(tnameserv나 rmiregistry)가 필요하다. RMI로 원격 서비스를 내보내도록 스프링을 사용하고 있다면 스프링은 이미 RMI 레지스트리를 생성했을 것이다. RIM로 원격서비스를 내보내도록 하고 있지 않다면 다음의 설정을 사용해서 간단하게 레지스트리를 시작할 수 있다.

1
2
3
4
5
Xml

<bean id="registry" class="org.springframework.remoting.rmi.RmiRegistryFactoryBean">
  <property name="port" value="1099"/>
</bean>


23.5.2 클라이언트측 커넥터

원격 JSR-160를 사용하는 MBeanServer에 MBeanServerConnection를 생성하려면 다음과 같이 MBeanServerConnectionFactoryBean를 사용해라.

1
2
3
4
5
Xml

<bean id="clientConnector" class="org.springframework.jmx.support.MBeanServerConnectionFactoryBean">
  <property name="serviceUrl" value="service:jmx:rmi://localhost/jndi/rmi://localhost:1099/jmxrmi"/>
</bean>


23.5.3 Burlap/Hessian/SOAP에서의 JMX

JSR-160은 클라이언트와 서버간의 통신을 수행하는 방법에 확장포인트를 허용하고 있다. 앞의 예제는 JSR-160 명세에 명시된 의무적인 RMI 기반의 구현체(IIOP와 JRMP)와 (선택적인) JMXMP를 사용하고 있다. 다른 프로바이더나 JMX 구현체 (MX4J와 같은)를 사용해서 HTTP나 SSL등을 사용하는 SOAP, Hessian, Burlap같은 프로토콜의 장점을 취할 수 있다.

1
2
3
4
5
6
Xml

<bean id="serverConnector" class="org.springframework.jmx.support.ConnectorServerFactoryBean">
  <property name="objectName" value="connector:name=burlap"/>
  <property name="serviceUrl" value="service:jmx:burlap://localhost:9874"/>
</bean>

앞의 예제에서는 MX4J 3.0.0을 사용했다. 자세한 내용은 MX4J 공식 문서를 참고해라.


23.6 프록시를 통한 MBean 접근

스프링 JMX에서는 로컬이나 원격 MBeanServer에 등록된 MBean 호출을 리라우팅하는 프록시를 생성할 수 있다. 이러한 프록시는 MBean과 상호작용할 수 있는 표준 자바 인터페이스를 제공한다. 다음 코드는 로컬 MBeanServer에서 동작 중인 MBean에 대한 프록시를 구성하는 방법을 보여준다.

1
2
3
4
5
6
Xml

<bean id="proxy" class="org.springframework.jmx.access.MBeanProxyFactoryBean">
  <property name="objectName" value="bean:name=testBean"/>
  <property name="proxyInterface" value="org.springframework.jmx.IJmxTestBean"/>
</bean>

ObjectName: bean:name=testBean으로 등록된 MBean에 프록시가 생성된 것을 볼 수 있다. 프록시가 구현하는 인터페이스들은 proxyInterfaces 프로퍼티로 제어하고 이 인터페이스들의 메서드와 프로퍼티를 MBean의 동작과 속성으로 매핑하는 규칙은 InterfaceBasedMBeanInfoAssembler에서 사용한 규칙과 동일하다. MBeanProxyFactoryBean은 MBeanServerConnection로 접근할 수 있는 모든 MBean에 대해서 프록시를 생성할 수 있다. 기본적으로 로컬 MBeanServer를 사용하지만 이를 오버라이드해서 원격 MBean을 가리키는 프록시에 대한 원격 MBeanServer를 가리키는 MBeanServerConnection를 제공할 수 있다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
Xml

<bean id="clientConnector" class="org.springframework.jmx.support.MBeanServerConnectionFactoryBean">
  <property name="serviceUrl" value="service:jmx:rmi://remotehost:9875"/>
</bean>

<bean id="proxy" class="org.springframework.jmx.access.MBeanProxyFactoryBean">
  <property name="objectName" value="bean:name=testBean"/>
  <property name="proxyInterface" value="org.springframework.jmx.IJmxTestBean"/>
  <property name="server" ref="clientConnector"/>
</bean>

위 예제에서 MBeanServerConnectionFactoryBean를 사용하는 원격 머신을 가리키는 MBeanServerConnection를 생성한 것을 볼 수 있다. server 프로퍼티로 이 MBeanServerConnection을 MBeanProxyFactoryBean에 전달한다. 생성한 프록시는 이 MBeanServerConnection를 사용해서 모든 호출을 MBeanServer로 보낼 것이다.


23.7 알림(Notification)

스프링의 JMX는 JMX 알림도 광범위하게 지원하고 있다.

23.7.1 알림에 대한 리스너 등록

스프링의 JMX는 다수의 MBean(이는 스프링의 MBeanExporter가 내보낸 MBean과 다른 메카니즘으로 등록된 MBean을 포함한다.)을 가진 다수의 NotificationListeners을 아주 쉽게 등록할 수 있도록 지원한다. 예제를 통해서 대상 MBean의 속성이 변경될 때마다 알림을 받는(Notification으로) 시나리오를 생각해 보자.

 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
45
Java

package com.example;

import javax.management.AttributeChangeNotification;
import javax.management.Notification;
import javax.management.NotificationFilter;
import javax.management.NotificationListener;

public class ConsoleLoggingNotificationListener implements NotificationListener, NotificationFilter {

  public void handleNotification(Notification notification, Object handback) {
    System.out.println(notification);
    System.out.println(handback);
  }

  public boolean isNotificationEnabled(Notification notification) {
    return AttributeChangeNotification.class.isAssignableFrom(notification.getClass());
  }
}


Xml

<beans>
  <bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
    <property name="beans">
      <map>
        <entry key="bean:name=testBean1" value-ref="testBean"/>
      </map>
    </property>
    <property name="notificationListenerMappings">
      <map>
        <entry key="bean:name=testBean1">
          <bean class="com.example.ConsoleLoggingNotificationListener"/>
        </entry>
      </map>
    </property>
  </bean>

  <bean id="testBean" class="org.springframework.jmx.JmxTestBean">
    <property name="name" value="TEST"/>
    <property name="age" value="100"/>
  </bean>
</beans>

위 설정에서 대상 MBean(bean:name=testBean1)이 JMX Notification를 브로드캐스트할 때마다 notificationListenerMappings 프로퍼티에 리스너로 등록한 ConsoleLoggingNotificationListener 빈이 알림을 받을 것이다. ConsoleLoggingNotificationListener 빈은 Notification의 응답으로 적절한 모든 액션을 받을 수 있다.
내보낸 빈과 리스너간의 연결로 빈 이름을 직접 사용할 수도 있다.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Xml

<beans>
  <bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
    <property name="beans">
      <map>
        <entry key="bean:name=testBean1" value-ref="testBean"/>
      </map>
    </property>
    <property name="notificationListenerMappings">
      <map>
        <entry key="testBean">
          <bean class="com.example.ConsoleLoggingNotificationListener"/>
        </entry>
      </map>
    </property>
  </bean>

  <bean id="testBean" class="org.springframework.jmx.JmxTestBean">
    <property name="name" value="TEST"/>
    <property name="age" value="100"/>
  </bean>
</beans>

MBeanExporter가 내보내는 모든 빈에 하나의 NotificationListener 인스턴스를 등록하고 싶다면 notificationListenerMappings 프로퍼티 맵의 엔트리에 키로 '*' (따옴표없이)를 와일드카드로 사용할 수 있다. 예를 들면 다음과 같다.

1
2
3
4
5
6
7
8
9
Xml

<property name="notificationListenerMappings">
  <map>
    <entry key="*">
      <bean class="com.example.ConsoleLoggingNotificationListener"/>
    </entry>
  </map>
</property>

반대로 해야 한다면(즉, MBean에 다수의 리스너를 등록한다면) notificationListeners 리스트 프로퍼티(그리고 notificationListenerMappings 프로퍼티에 대한 설정에)를 대신 사용해야 한다. 이 때 단일 MBean의 NotificationListener를 설정하는 대신 NotificationListenerBean 인스턴스를 설정해라. NotificationListenerBean은 NotificationListener와 ObjectName(또는 ObjectNames)을 은닉화하고 이는 MBeanServer에 등록된다. NotificationListenerBean은 NotificationFilter와 고급 JMX 알림 시나리오에서 사용할 수 있는 임의의 handback 객체같은 다수의 프로퍼티들도 은닉화한다. NotificationListenerBean 인스턴스를 사용할 때의 설정은 이전에 본 설정과 크게 다르지 않다.

 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
Xml

<beans>
  <bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
    <property name="beans">
      <map>
        <entry key="bean:name=testBean1" value-ref="testBean"/>
      </map>
    </property>
    <property name="notificationListeners">
      <list>
        <bean class="org.springframework.jmx.export.NotificationListenerBean">
          <constructor-arg>
            <bean class="com.example.ConsoleLoggingNotificationListener"/>
          </constructor-arg>
          <property name="mappedObjectNames">
            <list>
              <value>bean:name=testBean1</value>
            </list>
          </property>
        </bean>
      </list>
    </property>
  </bean>

  <bean id="testBean" class="org.springframework.jmx.JmxTestBean">
    <property name="name" value="TEST"/>
    <property name="age" value="100"/>
  </bean>
</beans>

위의 예제는 첫 알림 예제와 같다. Notification이 발생할 때마다 handback 객체가 주어지고 해당 NotificationFilter로 관련없는 Notifications을 필터링하기를 원한다고 해보자. (handback 객체가 무엇이고 NotificationFilter가 무엇인지에 대해서는 JMX 명세서(1.2)의 'The JMX Notification Model' 부분을 참고하기 바란다.)

 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
45
Xml

<beans>
  <bean id="exporter" class="org.springframework.jmx.export.MBeanExporter">
    <property name="beans">
      <map>
        <entry key="bean:name=testBean1" value-ref="testBean1"/>
        <entry key="bean:name=testBean2" value-ref="testBean2"/>
      </map>
    </property>
    <property name="notificationListeners">
      <list>
        <bean class="org.springframework.jmx.export.NotificationListenerBean">
          <constructor-arg ref="customerNotificationListener"/>
          <property name="mappedObjectNames">
            <list>
              <!--  별개의 MBean에서 받은 알림을 처리한다 -->
              <value>bean:name=testBean1</value>
              <value>bean:name=testBean2</value>
            </list>
          </property>
          <property name="handback">
            <bean class="java.lang.String">
              <constructor-arg value="This could be anything..."/>
            </bean>
          </property>
          <property name="notificationFilter" ref="customerNotificationListener"/>
        </bean>
      </list>
    </property>
  </bean>

  
  <bean id="customerNotificationListener" class="com.example.ConsoleLoggingNotificationListener"/>

  <bean id="testBean1" class="org.springframework.jmx.JmxTestBean">
    <property name="name" value="TEST"/>
    <property name="age" value="100"/>
  </bean>

  <bean id="testBean2" class="org.springframework.jmx.JmxTestBean">
    <property name="name" value="ANOTHER TEST"/>
    <property name="age" value="200"/>
  </bean>
</beans>


23.7.2 알림 발행하기

스프링은 Notifications을 받기 위한 등록뿐 아니라 Notifications을 보내기위한 등록도 지원한다.


Note
이 부분은 MBeanExporter를 통해 MBean으로 노출된 스프링이 관리하는 빈에 대해서만 관련된 부분이다. 이미 존재하거나 사용자가 정의한 모든 MBean은 표준 JMX API를 사용해서 알림을 발행해야 한다.

스프링의 JMX 알림 발행 지원에서 핵심 인터페이스는 NotificationPublisher 인터페이스다. (org.springframework.jmx.export.notification 패키지에 정의되어 있다.) MBeanExporter 인스턴스를 통해서 MBean으로 내보내질 모든 빈은 NotificationPublisher 인스턴스에 접근할 수 있도록 NotificationPublisherAware 인터페이스를 구현할 수 있다. NotificationPublisherAware 인터페이스는 해당 빈이 Notifications을 발행하는데 사용할 수 있는 간단한 setter 메서드로 구현한 빈에 NotificationPublisher 인스턴스를 제공한다. NotificationPublisher 클래스의 Javadoc에 나온대로 NotificationPublisher 메카니즘으로 이벤트를 발행하면서 관리되고 있는 빈은 어떤 알림 리스너 등에 대해서도 상태관리를 책임지지 않는다. 스프링의 JMX 지원은 JMX 인프라스트럭처와 관련된 모든 이슈의 처리를 담당한다. 애플리케이션 개발자가 해야하는 일은 NotificationPublisherAware 인터페이스를 구현하고 제공된 NotificationPublisher 인스턴스를 사용해서 이벤트를 발행하는 것 뿐이다. 관리되는 빈이 MBeanServer에 등록된 후에 NotificationPublisher가 설정된다는 점에 주의해라.

NotificationPublisher 인스턴스의 사용은 아주 직관적이다. 그냥 Notification 인스턴스(또는 Notification의 적절한 하위클래스의 인스턴스)를 만들고 발행할 이벤트와 관련된 데이터로 알림을 만든 후 NotificationPublisher 인스턴스의 sendNotification(Notification)를 호출해서 Notification을 전달하면 된다. 아래의 간단한 예제를 보자. 이 시나리오에서 내보내진 JmxTestBean 인스턴스는 add(int, int)가 호출될 때마다 NotificationEvent를 발행할 것이다.

 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
Java

package org.springframework.jmx;

import org.springframework.jmx.export.notification.NotificationPublisherAware;
import org.springframework.jmx.export.notification.NotificationPublisher;
import javax.management.Notification;

public class JmxTestBean implements IJmxTestBean, NotificationPublisherAware {

  private String name;
  private int age;
  private boolean isSuperman;
  private NotificationPublisher publisher;

  // 다른 getter와 setter는 생략했다

  public int add(int x, int y) {
    int answer = x + y;
    this.publisher.sendNotification(new Notification("add", this, 0));
    return answer;
  }

  public void dontExposeMe() {
    throw new RuntimeException();
  }

  public void setNotificationPublisher(NotificationPublisher notificationPublisher) {
    this.publisher = notificationPublisher;
  }
}

NotificationPublisher 인터페이스와 관련된 부분이 모두 잘 동작한다는 점이 스프링의 JMX 지원을 좋은 점중 하나다. 하지만 클래스가 스프링과 JMX에 모두 의존성을 갖게 된다는 단점이 있다. 언제나 그렇듯이 이에 대한 조언은 현실적인 조언 뿐이다. NotificationPublisher이 제공하는 기능이 필요하고 스프링과 JMX에 대한 의존성을 받아들일 수 있다면 사용해도 좋다.


23.8 추가 자료

이 섹션에서는 JMX에 대한 추가자료와 관련된 링크를 제공한다.