2. 유전자 알고리즘

집단지성 프로그래밍 이란 책을 보며 알게된 알고리즘이다. 그냥 여기저기 이야기만 들었지 실질적으로 정체를 파악하고 구현을 해보게 된건 이번이 처음이다.

유전자 알고리즘에 대한 자세한 설명은 엔하위키-유전자 알고리즘(http://ko.wikipedia.org/wiki/%EC%9C%A0%EC%A0%84_%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98)에 아주 자세히 잘 나와있다.

그냥 내식대로 간단히 정리하자면 무수히 많은 경우의 수 중 일부의 경우들을 샘플링하여 1세대 데이터군을 만들고 이 데이터들중 최적을 선택하여 교배하고 돌연변이 발생 시켜 더 나은 다음 세대군을 만드는 과정을 여러번 반복하여 최적의 결과를 찾아가는 알고리즘이다. (나 왜이리 글을 못쓰지?)

알고리즘 순서를 대충 요약하면 다음과 같다.

  1. 무수히 많은 경우의 수 중 일부의 경우를 랜덤하게 샘플링하여 하나의 데이터 세트를 구성한다. 이런 한 세트를 세대라고 부른다. 최초 샘플링에 의해서 만들어진 세대를 1세대 라고 한다.
  2. 한 세대가 구성이 되었으면 이중 최적에 가까운 일정 수를 선택한다. 이 선택된 데이터들을 엘리트라고 한다. 엘리트 선택 비율은 딱히 정해져있진 않은거 같다. 난 10% 정도를 엘리트로 선택하기로 했다.
  3. 선택된 엘리트들을 교배(교차)시키거나 돌연변이를 일으켜 이전 세대와 동일한 구성원 수를 갖는 다음 세대를 구성한다.
  4. 새로운 세대로 2~3과정을 여러번 반복한다.
  5. 더 이상 좋은 결과가 나오지 않거나 일정 횟수 이상 반복한 결과를 취한다.

연습삼아 만들어 본 것은 난수로 이루어진 정수들로 부터 0에 근접한 수를 만들어 내는 프로그램이다. 프로그램 돌아가는 과정은 다음과 같다.

  1. 랜덤함수를 이용하여 일정수 이상의 난수를 생성하여 1세대를 구성한다.
  2. 구성된 세대를 오름차순으로 정렬한다. 정렬할때는 절대값을 사용하여 음수도 0보다 큰 수로 정렬되게 한다.
  3. 정렬된 수중에서 0에 가까운 10%의 수를 선택한다.
  4. 버려진 90%의 구성원을 대치할 새로운 구성원을 만든다. 일정한 확률을 정하여 구성원 수가 모두 찰때까지 교차(교배) 혹은 돌연변이를 일으킨다.
    1. 교차(교배) : 선택된 가장 작은 10%수중 랜덤으로 두개를 선택하여 교배(교차)시킨다. 첫번째 수의 앞 16bit, 두번째 수의 뒤 16bit를 취한 값을 합하여 새로운 수를 만든다.
    2. 돌연변이 : 선택된 가장 작은 10% 수중 랜덤을 하나를 선택해서 돌연변이를 일으킨다. 랜덤하게 몇개의 비트를 선택하여 inverse 시킨다.
  5. 2~4를 계속 반복한다.
  6. 최종 결과를 확인한다.

실험 결과는 아래 처럼 나왔다.

  1. 실험 1
    1. 조건 : 세대구성수 100, 세대교체 횟수 100, 엘리트 비율 10%, 돌연변이 발생 확률 10%, 총 시도 횟수 5회
    2. 결과 : -1, 43, 10, 515, -2
  2. 실험 2
    1. 조건 : 세대구성수 1000, 세대교체 횟수 10, 엘리트 비율 10%, 돌연변이 발생 확률 10%, 총 시도 횟수 5회
    2. 결과 : 344, -81, -3588, -1045, 109
  3. 실험 3
    1. 조건 : 세대구성수 10, 세대교체 횟수 1000, 엘리트 비율 10%, 돌연변이 발생 확률 10%, 총 시도 횟수 5회
    2. 결과 : 2, 16, 16, -1, 0
  4. 실험 4
    1. 조건 : 세대구성수 1000, 세대교체 횟수 1000, 엘리트 비율 10%, 돌연변이 발생 확률 10%, 총 시도 횟수 5회
    2. 결과 : 1, 1, 1, 0, 1
  5. 실험 5
    1. 조건 : 세대구성수 10000, 세대교체 횟수 100, 엘리트 비율 10%, 돌연변이 발생 확률 10%, 총 시대 횟수 5회
    2. 결과 : -1, -1, -1, 0, 1
  6. 실험 6
    1. 조건 : 세대구성수 100, 세대교체 횟수 10000, 엘리트 비율 10%, 돌연변이 발생 확률 10%, 총 시대 횟수 5회
    2. 결과 : 1, 0, 1, -1, -1

 

예전에 페북에 끄적거렸던과 달리 실험2와 실험3을 비교해 보면 세대수가 많아도 세대 교체횟수가 적절하지 않으면 그 반대의 경우보다 결과가 좋지 않게 나오는거 같다. 오히려 적은 구성수도 돌연변이가 적절히 발생하면서 세대교체가 많이 이루어지면 자연히 좋은 결과를 내는것 같다. 그리고 실험 4~6을 보면 전체 경우수의 일정 비율 이상을 샘플링 한다면 구성원수와 교체횟수를 극단적으로 치우치게 하지만 않는다면 다 좋은 결과를 도출해 내는것 같다.

실험1 기준으로 32bit 정수 표현의 모든 경우의 수를 비교하는것( O(2^32) )로 반드시 0을 찾을 수 있다.)에 대비하여 100개의 원소를 100번 정렬하는 것( O(100*log(100) * 100) )으로 거의 근사치(2~16)를 구한것을 보면 완벽한 최적값을 요구하는 조건이 아니라면 상당히 유용한 알고리즘인것 같다.

특이한 점은 1과 같이 어느정도 최적치에 근접한 이후부터는 변화가 거의 없다. 아마 세대의 모든 엘리트들의 값이 1로 통일된 상태에서는 교배도 더이상 의미가 없고 돌연변이만을 통해서 0에 도달해야하는데 돌연변이 같은 우연발생으로 최적에 도달하려는 시도는 논리적으로 성공을 보장할 수는 없는 부분이니 운에 맡기는 방법밖에 없기 때문에 그런 것이 아닐까 한다.

결과적으로 유전자 알고리즘은 경우의 수를 모두 따지기 어려운 매우 큰 집단에 대해서 일정 수준의 최적치를 얻기에는 좋은 방법인것 같다. 다만, 완벽한 최적값을 기대한다면 실망할 여지가 크다.

아래는 토비 세가란의 집단지성프로그래밍 책을 참고하여 만든 코드다. net.abh0518.genetic 패키지가 유전자 알고리즘 구현 부분이다.
https://github.com/abh0518/ProgrammingCollectiveIntelligence

가계부를 쓰자!

엑셀로 작업하던 가계부를 구글 독스로 옮긴 기념, 지난 8년간의 가계부 인생을 정리해볼겸 남겨보는 포스팅

2007년 서울로 상경한 이후로 쭈욱 가계부를 써온지 만 8년이 다 되어간다. 그간의 경험을 바탕으로 느낀건 매일 10분, 바쁘다면 주말에 30분 정도 투자하여 가계부 정리하는 습관은 우리같은 월급쟁이의 가정경제에 정말 많은 도움이 된다는 것이다. 규모나 성과로 따지고 보면 가계부를 쓰면서 절약되거나 벌어들이는(벌어들이는게 맞나?) 돈이 그렇게 엄청나지는 않다. 그럼에도 불구하고 우리같은 월급쟁이들은 반드시 가계부를 써야한다고 나는 생각한다.

내가 생각하는 직장인이 (사실 직장인과는 전혀 관계가 없는 이유다) 가계부를 써야하는 첫번째 이유는 990원과 1000원은 엄연히 다른 돈이기 때문이다. 단돈 10원밖에 차이가 나지 않지만 990원으로는 1000원짜리 사발면을 사먹을 수 없다. 웃기다고? 이건 심각한 문제다! 10원 우습게 봤다가는 그 10원때문에 당장 필요한걸 사지 못하는 일이 발생한다.

두번째 이유는 주기적인 결산을 통해 내 재정상태를 잘 알고 합리적인 소비를 할 수있도록 습관 들이기 위해서이다. 특히 카드 같이 당장 얼마가 지출되었는지 잘 확인이 되지 않는 지출 수단들은 평소 신경써두지 않으면 통제가 정말 힘들다. 통장에 얼마가 남았는지, 재정이 얼마나 위기인지 모르면 사람이란 욕망의 생물은 그냥 지르기 마련이다. 가계부는 나에게는 일종의 자기 통제 수단이기도 하다.

결과적으로 가계부를 적는 일의 궁극적인 목표는 가계부 적는것 자체보다는 내 재정상태를 명확히 파악하고 이를 통해 합리적인 소비 계획을 세우고 그에 맞춰 생활 수준을 조절하여 이리저리 새는 돈을 막아 보겠다는 것이다. (물론 이건 순전히 내 기준의 목적이다.) 따라서 제대로 가계부 정리를 하라면 몇가지 단계를 거쳐야 한다.

1. 장기적 재정 목표 및 소비 원칙 세우기
2007년에 서울에 올라오면서 세운 첫번째 재정목표는 ‘1억 만들기’ 였다. 아마 그 생각을 하면서 가계부를 정리하기 시작했던거 같다. (두번째 목표 내집 마련은 진행중…) 첫 직장의 연봉이 그리 나쁘지 않아서 적당히 조절만 잘하면 5년 안에 충분히 모을 수 있는 목표였다. 그리고 목표에 맞춰 지름의 원칙을 세웠다. ( 지름의 원칙 : http://abh0518.net/tok/?p=379 ) 실시간으로 사용량 측정이 어려운 카드는 특별한 상황이 아니면 쓰지 않았고, 포인트 적립률이 높은 체크 하나로 결재를 몰빵하는 식이었다. (지금 생각해보니 징하네) 할인율이 좀 아쉽기도 하지만, 이카드 저카드 나눠 쓰다가 금액 취합이 잘 안되어 헷갈리는거보단 할인율 약간 포기하는것도 나쁘지 않은듯 한 결정이었다.

2. 템플릿 만들고 월별 재정 계획 세우기
현재 사용하고 있는 템플릿이다. 군대에서 군수 행정하면서 경험했던 결산표를 기준으로 다시 만들어서 사용했었다.
가계부_Template - Google 스프레드시트 2014-12-26 16-22-33템플릿이 완성 되었으면 먼저 ‘지출 예산’ 항목에 그달 지출 계획을 잡아야한다. 여기서 생활 수준과 저축 양, 남는 돈이 결정된다. 가장 큰 변수인 개인 용돈을 나는 월 60만원 정도로 잡았었는데 평일 하루 식비(20일*15,000) + 주말여가비(30만원) 정도로 계산했다. 2007년도 기준이니 지금은 좀 손봐야 할거 같다. 그리고 이 비용은 솔로 시절 기준이다. 여친이 있다면 20만원 정도 더 얹어야 한다. 그리고 관리비, 생활비(공과금 뭐 이런거…), 보험, 통신비 같은 항목들은 사실 거의 고정 지출이지만 미리 예산안으로 짜 놓는게 매월 기본적으로 나가는 돈이 얼마인지 가늠해보기 좋다. 중요한건 예산안을 통해 내가 한달에 얼마나 쓰는지를 파악하고 어느 부분에서 다음달 지출을 줄일지 포인트를 찾는 것이다. 추가로 저축도 지출로 잡아야한다. 저축으로 들어간 돈은 내 돈이 아니다!

3. 매일(혹은 매주) 적고
가계부_Template - Google Sheets 2014-12-26 16-36-34(참고로 이건 샘플이다. 내 진짜 소비 패턴은 아니다.)
월 예산을 다 짰으면 꼬박꼬박 잘 적는게 중요하다. 수입란에는 월급같이 내 통장에 들어오는 돈을 적고 지출에는 지출 항목에 맞춰 얼마나 썼는지를 일별로 잘 기록해야한다. 카드 지출은 따로 분류하여 관리하였는데 당장 통장에서 빠지는 돈이 아니니 나중에 빠질 돈으로 나누어 계산하는게 헷갈리지 않고 재정을 탄력적으로 관리하기가 편해서이다. 무엇보다도 내가 카드로 얼마나 썼는지를 한눈에 볼수 있어 스스로 경계할 수 있는 포인트가 되기도 한다. 그리고 각 셀에 코멘트 기능으로 수입/지출에 대한 상세 내용을 적으면 월별 회고할때 좋다.

4. 일/주/월 결산 및 반성하기
가계부_Template - Google Sheets 2014-12-26 16-46-51
템플릿 맨 아래에는 위와 같은 항목이 있는데, 총 수입/지출/지출예상을 합산하여 다음달에 얼마나 남겨먹을 예정인지 계산하는 항목이다. 샘플에서는 30일까지 소비가 진행이 된 상태인데 예산 기반으로 소비가 진행되면 차월에는 5,350,000원이 통장에 남을 예정이고 카드 미정산을 반영하면 5,245,000원이 남고 이는 전달 대비(전달에는 2,300,000원이 남았다)  2,945,000원을 더 벌어들였다는 이야기가 된다. 다만 현재 금액 상태를 보면 기타항목에서 추가 지출이 발생되었기 때문에 금번달은 예산안대로 지출이 진행되기는 수월하지 않을 것이라는 예상이 된다. 즉, 남은 25일 간에는 용돈을 좀 아껴써야 한다는 결론이 나온다. 그래도 예상되는 수익이 294만원 이나 되니 한달 좀 풍족하게 살것인지 이미 하고 있는 저축에 돈을 더 넣어서 미래를 대비할지는 내가 결정하면 된다. 나같은 경우는 첫번째 재정 목표를 위해 남는 돈은 죄다 저축으로 몰빵했다. 그리고 샘플의 경우는 수입 항목에서 월급 외 보너스가 300만원이 더 잡혔기 때문에 수익이 마이너스가 되지 않았다. 냉정하게 따지면 평소에는 보너스가 나오지 않으니 2013년 11월은 손해본 달로 봐야한다. 결과적으로 이번달에는 추가 저축을 얼마 하고 얼마 정도를 더 혹은 덜 써서 다음달에 얼마를 남겨먹겠다는 목표를 설정하고 총계 상황에 맞춰 생활 수준을 조절해 나가는 것이 중요하다. 그리고 통장에 항상 100만원 여윳돈 정도를 남겨놓는게 좀 생계를 유지하는데 수월하더라…… (너무 빡빡하게 하다가는 월급 전날 돈이 없어서 아무것도 못먹…… 적금을 깰수도 없고…… 어흐흐흐흑….)

5. 현금화 된 돈 처리 및 다른 자산 관리
개인 적인 경험으로는 출금 등으로 현금화 된 돈은 지출 된 것으로 따지는게 가계부 관리가 좀 수월하다. 현금화 된 돈까지 일일히 세기에는 영 시간대비 얻는게 적다. 그냥 가계부는 통장 금액을 기준으로 운영하는게 제일 편하다는게 개인적인 결론이다. 그리고 다른 자산(주식이나 적금 통장 등등)은 완전히 제외한 월 수입 대비 지출로 가계부를 운영을 하는게 스스로에게 긴장감을 주고 소비를 줄이는데 도움이 되던것 같다.

6. 재정관리의 최대 적, 할부
할부는 재정관리의 최대의 적이다. 할부 항목이 생기면 예산 관리 및 지출 예산 관리가 정말 힘들어진다. 그리고 한번 할부의 유혹에 빠지면 매월 쌓이는 할부 항목으로 지출 계획과 지출 예정 항목들이 골치아프게 꼬여들어가고 월급날마다 탈탈 탈려가는 통장을 한몸에 느낄 수 있다. 가계부 관리하면서 할부로 탈탈 털리는 탈력감을 한번 느껴보면 두번다시 할부를 하기 싫어진다. 가능하면 모든것은 체크카드 일시불로 처리하는게 좋다. 일시불로 사지 못할 거라면 안사는게 답이다. 할부는 가정경제의 최대 적이다. 그래서 난 자동차도 일시불 구매가 가능할 때까지 돈 모아서 샀다 . 일시불로 못사면 안사는거다. 차 없다고 죽는거 아니니까……

7. 빚 관리
그리고 가장 중요한건 가계부를 운영하는 동안에 절대로 빚은 지지 않는다는 각오가 필요하긴 하다. 빚을 져야할거 같으면 방값을 좀 낮춰 이동하든가 뭐 그런 방향으로 진행하는게 좋다. 죽느냐 사느냐 문제가 아니라면 빚은 지지 않는 것이 최고인거 같다. 물론 이건 다행히 집에 빚이 없던 내 기준이다. 사람마다 처지는 다르니 뭐 어떻게 할 수 있는 항목은 아닌거 같다. 가능한한 빚은 지지 않도록 상황을 잘 만들어 가는게 중요한데 그게 뭐 내 뜻대로 되나! 혹, 빚을 지게 된다면 카드 지출처럼 빚 항목을 추가하여 빚으로 인해 발생하는 이자나 원급 상납 부분도 고정 지출로 잡아 관리해야한다.

가계부를 쓴다고 돈을 많이 벌거나 엄청나게 절약되는건 아니다. 자금 통제 잘 해서 15만원 쓸거 14만원 정도 쓰고 조금 더 아껴보자는게 가계부의 목적이다. 나는 그래도 운좋게 사회생활을 대기업에서 시작해서 그런지 가계부를 작성하며 재정 목표를 쉽게 달성한 것일지도 모른다. (역시 인생은 운빨이냐!) 하긴 뭐 운빨 따지면 가계부 자체를 작성할 필요도 없는 금수저도 있겠지만 그거 탓해봐야 내 속만 아프고 난 내 처지에 맞게 살면 되는거니까……

어쨋든 아직 완벽한 가정 재정 관리 전략은 아니다. 게다가 중간 중간 집안 일과 누나와의 주거 문제가 꼬이면서 돈이 늘다가 줄다가 했던거 같다. 그래도 나름 이렇게 8년을 관리하니 어느정도 새는 돈은 막으면서 차도 사고 잘 버텼던거 같다.

아래는 구글 독스로 옮긴 가계부 템플릿 (쓸사람이 있으려나?)
https://docs.google.com/spreadsheets/d/1Pw4G3oL-2WoqOu_mMWUekSqjCvYDu2_MvMIO8IAoDUM/edit#gid=1979406514

어색하게 끝!

검도와 주짓수 다시 시작

검도와 주짓수를 다시 시작하게 되었다.

검도
올해 초, 판교로 회사가 이동하게 되면서 을지로에 있던 SKT 대한검도동호회를 더이상 나갈 수 없게 되었었다. 도장에서 배우는것 만큼은 아니겠지만 동호회에서 겸사겸사 배우는 재미가 쏠쏠했는데 많이 아쉬웠다. 그러던중 10월즘 SKP에서 고단자 매니저님을 만나 비공식 동호회를 하나 만들게 되었다. 현재 총 인원 4명의 매우 조촐한 구성이다. 월요일 점심마다 모여 하는 재미가 쏠쏠하다. 오래 갔으면 좋겠다. 사람도 좀 늘고 해야하는데…

주짓수
2년전에 아현역 이희성 주짓수에 3개월 정도 다니다가 도장이 너무 멀어 포기했었다. 계속 배우고는 싶은데 평일/주말 지하철 6~7정거장 거쳐 다니기는 참 힘들더라. 그러던 중 최근 당산역 바로 옆에 주짓수 도장 하나가 새로 생겼다. 신혼집과도 10분 거리인게 위치상으로 다니기가 매우 좋다. 운좋게 회사 퇴근버스도 도장 바로 앞에 정차를 해서 퇴근 후 다니기가 정말 편하다. 일주일 정도 다녔는데 다시 재미가 붙기 시작하는게 이번에는 오래 다닐 수 있을거 같다. 신혼임에도 불구하고 평일 늦은 오후 남편의 운동을 허가해주신 와이프님께 깊은 감사를 드린다.

생활체육 최근 포스팅 한게 연초에 올린 몸만들기 계획인데 한 1달 하고 못한거 같다.(망할 OCB 개편;;;)

아래는 새로운 운동 계획

월 : 점심시간 검도 동호회
화 : 퇴근 후 주짓수
수 : 점심시간 웨이트
목 : 퇴근 후 주짓수
금 : 점심시간 웨이트

건강하게 잘 살아보세~!

[RabbitMQ] 3. 초보를 위한 RabbitMQ 클러스터와 미러링 구성하기

2장까지 계정설정하고 3장에서 exchange 한다고 예고까지 해놓고 뜬금없이 클러스터와 미러링 구성하기를 작성하게 되었습니다. 방금 회사에서 클러스터랑 미러링을 구성해서 까먹기전에 후딱 써야하는 조금함때문인거 같습니다. exchange 설명 달기도 귀찮기도 하구요. 여튼 시작합니다.

0. 목표와 작업 순서

메시징 서비스를 하는데 큐의 의존도가 매우 커졌습니다. 그래서 고가용성 큐를 구성하려고 합니다. 다행히 RabbitMQ에서 완전 짱짱맨인 클러스터, 미러링 기능을 제공하니 그냥 그거 가져다 쓰면 될거 같습니다. 작업 순서는 대충 다음과 같습니다.

  1. 서버간 얼랭 쿠키 맞추기
  2. 클러스터 구성하기
  3. 클러스터 노드 타입 변경
  4. 미러링 구성하기
  5. 클러스터에서 빠져나오기

본 예제는 3대의 서버를 클러스터, 미러링 하는 것을 기준으로 작성되고 있습니다. 사실 생각보다 무지 쉽습니다. (사이트에서 하라고 하는대로만 잘 따라하면 됩니다. 물론 전 청개구리 모드가 작동하여 하지말라는 순서대로 하다가 MQ 한대 바보로 만들고 두대는 꼬여서 전체 재설치하는 곤욕을 치르기도 했습니다. 으하하!

1. 서버간 얼랭 쿠키 맞추기

서버간 얼랭 쿠키를 맞춰줘야 합니다. 자세한 이유는 저도 Document 읽기 귀찮아 생략합니다. 어쨋든 맞춰줘야 한다고 합니다.

  1. Erlang 쿠키 위치 확인
    보통 리눅스의 경우 “/var/lib/rabbitmq/.erlang.cookie” 이나 “$HOME/.erlang.cookie” 에 있다고 합니다. 이건 OS나 설치환경 차이가 있으니 각자 알아서 찾는 방법밖에 없습니다. 여튼 클러터를 구성할 3대의 서버중 1대를 기준으로 잡아 scp로 파일 카피를 하거나 vi화면으로 copy&paste 해버리면 됩니다. 혹시 모르니 RabbitMQ를 꺼놓고 작업하도록 합시다.
  2. 복사가 제대로 안되어 RabbitMQ가 작동하지 않을때…
    파일 복사가 제대로 이루어지지 않으면, 보통 vi 로 copy&paste하다 삑사리 나면 발생합니다 하하하, RabbitMQ가 구동되지 않습니다. 이럴때는 그냥 쿠키 파일을 지워버리고 다시 시작하면 됩니다. 그럼 새 쿠키카 생성되는데, 여기에 다시 작업하시면 됩니다.

2. 클러스터 구성하기

정말 별거 없습니다. 그냥 가이드(https://www.rabbitmq.com/clustering.html) 에서 시키는데로 따라하면 됩니다.

  1. 각 서버 상태 확인
    클러스터링이 되기 전 ‘rabbitmqctl cluster_status’ 명령으로 각 서버 상태를 살펴봅니다. (아래 코드들은 가이드에서 그냥 베껴왔습니다)

    # 1번서버 확인, 자기 자신 노드만 확인됨 
    rabbit1$ rabbitmqctl cluster_status
    Cluster status of node rabbit@rabbit1 ...
    [{nodes,[{disc,[rabbit@rabbit1]}]},{running_nodes,[rabbit@rabbit1]}]
    ...done.
    
    # 2번 서버 확인, 자기 자신 노드만 확인됨
    rabbit2$ rabbitmqctl cluster_status
    Cluster status of node rabbit@rabbit2 ...
    [{nodes,[{disc,[rabbit@rabbit2]}]},{running_nodes,[rabbit@rabbit2]}]
    ...done.
    
    # 3번 서버 확인, 자기 자신 노드만 확인됨
    rabbit3$ rabbitmqctl cluster_status
    Cluster status of node rabbit@rabbit3 ...
    [{nodes,[{disc,[rabbit@rabbit3]}]},{running_nodes,[rabbit@rabbit3]}]
    ...done.
  2. 서버들을 클러스터로 묶기
    작업 시작전 주의사항으로 rabbitmqctl로 노드를 정지시킬때 반드시 stop_app을 사용해야합니다. 실수로 stop을 해버리면 rabbitmqctl 명령 자체가 먹지 않습니다. 아마 stop은 RabbitMQ node 자체를 종료 시켜버리고 stop_app은 RabbitMQ의 Management Application을 정지시키기 때문이 아닌가 합니다. 그리고 Cluster를 묶을때 해당 서버의 hostname을 적어 주어야 하는데 정말! 반드시! hostname을 사용해야 합니다. IP이런거 절대 안됩니다. 제가 이거로 반나절 날렸습니다. 어흐흐흐흑! 그리고 /etc/hosts 에 상대 서버의 hostname을 등록할때는 상대 서버에서 cluster_status로 확인되는 hostname으로 등록해주도록 합니다. hostname을 동일하게 맞추지 않고 구성을 해보지 않아 꼭 맞춰야 되는건지는 알수 없지만 그냥 안전하게 맞추도록 합시다. (그거까지 테스트하기 귀찮아요)이제 1번 서버를 기준으로 클러스터를 묶도록 하겠습니다. 기준이 되는 1번서버는 별다른 작업을 해줄 필요가 없습니다. 그러니 2번 서버부터 작업을 시작해 봅시다.

    #2번서버 작업, 
    #관리 앱 정지
    rabbit2$ rabbitmqctl stop_app
    Stopping node rabbit@rabbit2 ...done.
    
    # 1번 서버로 붙는다. hostname의 경우 1번서버에서 cluster_status로 이름을 확인하여 맞춰 설정하도록 하자.
    rabbit2$ rabbitmqctl join_cluster --ram rabbit@rabbit1
    Clustering node rabbit@rabbit2 with [rabbit@rabbit1] ...done.
    rabbit2$ rabbitmqctl start_app
    Starting node rabbit@rabbit2 ...done.
    

    3번 서버도 마저 작업합니다. 2번 설정할때와 동일합니다.

    rabbit3$ rabbitmqctl stop_app
    Stopping node rabbit@rabbit3 ...done.
    rabbit3$ rabbitmqctl join_cluster rabbit@rabbit2
    Clustering node rabbit@rabbit3 with rabbit@rabbit2 ...done.
    rabbit3$ rabbitmqctl start_app
    Starting node rabbit@rabbit3 ...done.
    

    서버별로 cluster_status 명령을 사용하여 실제 서로 노드를 인식하는지 확인해 봅시다. 클러스터링이 잘 되었다면 status에서 더이상 혼자가 아닌 Node(http://www.youtube.com/watch?v=R85lOwRsnvk)를 볼 수 있습니다. 상태를 보면 ram, disc 이런게 좀 신경쓰이는데 이건 곧 설명하도록 하겠습니다.

    #1번 서버 확인
    rabbit1$ rabbitmqctl cluster_status
    Cluster status of node rabbit@rabbit1 ...
    [{nodes,[{disc,[rabbit@rabbit1,rabbit@rabbit3]},{ram,[rabbit@rabbit2]}]},
     {running_nodes,[rabbit@rabbit3,rabbit@rabbit2,rabbit@rabbit1]}]
    ...done.
    
    #2번 서버 확인
    rabbit2$ rabbitmqctl cluster_status
    Cluster status of node rabbit@rabbit2 ...
    [{nodes,[{disc,[rabbit@rabbit1,rabbit@rabbit3]},{ram,[rabbit@rabbit2]}]},
     {running_nodes,[rabbit@rabbit3,rabbit@rabbit1,rabbit@rabbit2]}]
    ...done.
    
    #3번 서버 확인
    rabbit3$ rabbitmqctl cluster_status
    Cluster status of node rabbit@rabbit3 ...
    [{nodes,[{disc,[rabbit@rabbit3,rabbit@rabbit1]},{ram,[rabbit@rabbit2]}]},
     {running_nodes,[rabbit@rabbit2,rabbit@rabbit1,rabbit@rabbit3]}]
    ...done.
  3. 클러스터 최종 확인
    클러스터로 묶인 RabbitMQ들은 서로간의 계정, Virtual Host, policy, Queue, Exchange 등을 모두 공유합니다. 따라서 1번 서버에만 붙어도 2번, 3번 서버의 Queue에 Access할 수 있습니다. 네! 짱짱맨입니다! 간단한 테스트로 Management Plugin으로 접속하여 1번 서버에서 Queue를 만들고 메세지를 Publish해보면 2번, 3번 서버에서도 인식이 되는것을 확인할 수 있습니다.

3. 클러스터 노드 타입 변경

rabbitmqctl cluster_ctl 로 상태를 보면 dics, ram 이란 녀석들이 보입니다. 각 노드들이 현재 상태를 disc로 작동하는지 ram으로 작동하는지를 보여줌니다. 이 두개의 옵션에는 차이가 있는데 ram의 경우 node의 data가 ram에만 상주하여 작동 속도가 빠르고 disc의 경우 node의 data들이 disc에 기록되며 작동한다고 합니다. RabbitMQ 클러스터를 구성할 경우 서버 1대는 반드시 disc로 구성이 되어야하는데, 그 이유는 정말 재수가 없어서 서버가 전체다 내려갔을때 disc로 구성된 녀석을 통해 어느정도 복구가 되도록 하는거 같습니다. 물론 이건 문서를 대충 읽어서 정확한 내용은 아닙니다. 테스트 또한 해보진 않았습니다. 네, 저도 불안하긴 합니다. 여튼 1대는 반드시 disc로 구성하라고 합니다. (뭔가 찜찜하다.)

  1. Cluster Node Type 변경
    저는 1번과 3번을 빠른 ram으로 2번 서버를 disc로 구성하려 합니다. 다음과 같이 합니다.

    # disc로 작동할 2번 서버 먼저 작업한다. node중에 disc가 하나라도 없는 상황이 될 수 있으면 변경이 되지 않는다.
    rabbit2$ rabbitmqctl stop_app
    Stopping node rabbit@rabbit2 ...done.
    rabbit2$ rabbitmqctl change_cluster_node_type disc
    Turning rabbit@rabbit2 into a disc node ...
    ...done.
    Starting node rabbit@rabbit2 ...done.
    
    # 1번 서버 작업
    rabbit1$ rabbitmqctl stop_app
    Stopping node rabbit@rabbit1 ...done.
    rabbit1$ rabbitmqctl change_cluster_node_type ram
    Turning rabbit@rabbit1 into a ram node ...
    rabbit1$ rabbitmqctl start_app
    Starting node rabbit@rabbit1 ...done.
    
    # 3번 서버 작업
    rabbit3$ rabbitmqctl stop_app
    Stopping node rabbit@rabbit3 ...done.
    rabbit3$ rabbitmqctl change_cluster_node_type ram
    Turning rabbit@rabbit3 into a ram node ...
    rabbit3$ rabbitmqctl start_app
    Starting node rabbit@rabbit3 ...done.
  2. 확인하기
    1번서버에서 rabbitmqctl cluster_status로 cluster type이 잘 변경되었는지 확인합니다. 그리고 1번 서버를 stop/start를 하며 2번 서버로 cluster_status를 체크해보며 node 구성에서 1번 서버의 RabbitMQ가 빠졌다가 다시 들어오는것을 확인합니다. 모든게 잘 작동하면 클러스터게 제대로 구성되었다고 볼 수 있습니다.

 4. 미러링 구성하기

3번까지 클러스터를 구성하기는 했는데 아직 고가용성이라고 볼수는 없습니다. 클러스터는 서로의 내용을 공유만 할 뿐이어서 불의의 사고로 1번서버가 죽어버린다면 2번, 3번 서버를 통해서 1번서버 큐의 내용을 읽을 수 없게 되며 1번에 남아있던 message들은 모두 증발해 버립니다. 따라서 고가용성을 위해 클러스터의 노드들이 서로의 내용을 복사하여 저장하도록 해주어야 합니다. 노드간 미러링을 구성합니다!

  1. 미러링 정책 설정하기
    클러스터만 잘 구성되었다면 미러링은 정말 쉽습니다. 그냥 정책을 정해주는 명령 하나만 날려주면 됩니다. 전 그냥 다 미러링할 계획이라 ha-mode를 all로 했습니다.  옵션별 자세한 내용은 가이드 참조 바랍니다. (https://www.rabbitmq.com/ha.html)

    # ha-all은 새로 추가되는 정책의 이름, ^ha\.은 regexp로 표현된 미러링할 queue 이름, 뒤의 json은 정책 세부 사항,
    rabbitmqctl set_policy ha-all "^ha\." '{"ha-mode":"all"}'
  2. Virtual Host 별로 정책 설정해주기
    1번의 내용은 default virtual host에 적용이 됩니다. 새로 만든 virtual host에 ha 정책을 정해주려면 -p 옵션을 사용해야 합니다.

    # myQueue Virtual Host 속한 이름에 .ha 가 포함된 Queue를 모두 미러링 하는 정책
    rabbitmqctl set_policy -p myQueue ha-all "^.*\.ha.*" '{"ha-mode":"all"}'
  3. ha-sync-mode 에 대해
    미러링을 하면 node간 모든 내용들이 복사됩니다. 하지만 고민해야할 것이 하나 있습니다. 클러스터에 새로운 node가 추가되었을때 이 node에 다른 node들이 가지고 있는 과거의 Data를 Sync해야할 것인가? 에 대한 문제입니다. RabbitMQ는 기본적으로 새로 추가된 node(죽었다 살아난 node 포함)에 기존 node의 과거의 data들을 복사하지 않도록 합니다. Data Sync하는 동안 해당 Queue는 무응답 상태가 되어 버려 서비스 가용성에 좋지 않은 영향을 미칠수 있기 때문입니다. 그럼에도 불구하고 추가되는 노드에 반드시 과거 Data가 Sync되어야 한다면 ha-sync-mode 옵션으로 설정할 수 있습니다.

    # ha-sync-mode를 automatic으로 설정, 새로 들어오는 node에도 과거의 data가 모두 복사된다.
    rabbitmqctl set_policy -p myQueue ha-all "^.*\.ha.*" '{"ha-mode":"all", "ha-sync-mode":"automatic"}'
  4. Management Plugin 을 이용한 테스트 및 관리
    사실 미러링은 그냥 Virtual Host에 적용되는 정책에 따라 변할뿐입니다. 그리고 이러한 정책은 Management Plugin에서 Admin=>Policies 메뉴를 이용하면 좀더 편리하게 설정을 할 수 있습니다.

5. 클러스터에서 빠져나오기

클러스터를 구성했으면 클러스터에서 빠져 나올수도 있어야 합니다.

  1. 클러스터에서 빠져나오기
    이것도 간단합니다. 클러스터에서 뺄 서버에 가서 명령 하나만 쳐주면 됩니다. 3번 서버를 제거해보도록 하겠습니다.

    # 3번 서버를 클러스터에서 제거
    rabbit3$ rabbitmqctl stop_app
    Stopping node rabbit@rabbit3 ...done.
    rabbit3$ rabbitmqctl reset
    Resetting node rabbit@rabbit3 ...done.
    rabbit3$ rabbitmqctl start_app
    Starting node rabbit@rabbit3 ...done.
    
    # 2번 서버에서 확인해보기
    rabbit2$ rabbitmqctl cluster_status
    Cluster status of node rabbit@rabbit2 ...
    [{nodes,[{disc,[rabbit@rabbit1,rabbit@rabbit2]}]},
     {running_nodes,[rabbit@rabbit1,rabbit@rabbit2]}]
  2. 혹 클러스터에서 제거해야할 node가 정상적으로 작동이 되지 않는 상태라면?
    다른 서버에서 원격으로 제거할 수 있습니다.

    # 3번 서버가 정지되어있다면...
    rabbit3$ rabbitmqctl stop_app
    Stopping node rabbit@rabbit3 ...done.
    
    # 1번이나 2번 서버에서 원격으로 제거 한다. 나중에 3번 서버는 reset하여 클러스터에서 완전히 빠지도록 해준다.
    rabbit2$ rabbitmqctl forget_cluster_node rabbit@rabbit3
    Removing node rabbit@rabbit1 from cluster ...
    ...done.

마지막으로 클러스터와 미러링 구성이 잘 되었나 확인하는것도 역시 Management Plugin을 사용하면 정말 편합니다. 관리자 계정으로 접속하면 home 화면에 cluster가 어떻게 구성되었는지 뙇! 보여줍니다. 미러링이 잘되었는지는 Queue 메뉴에 들어가면 확인 가능합니다. Queue 리스트를 보면 미러링 되는 큐는 이름 옆에 (+2) 이런 표식이 나옵니다. 미러링 되고 있는 node의 수를 보여주는 값입니다. 저게 생기지 않는다면 클러스터에서 공유만 되고 미러링이 되고 있지 않는 Queue 입니다.

오늘건 좀 길었네요. 헉헉.

[RabbitMQ] 2. 초보를 위한 RabbitMQ 서비스용 계정 및 Virtual Host 설정하기

앞장에서 RabbitMQ를 구동하기 위한 설치부터 기본 설정을 끝냈으니 이제 서비스가 가능하도록 계정과 Virtual Host, Queue, Exchange 설정 등을 끝내야 한다. Terminal에서 rabbitmqctl 사용하여 간지나게 작업하면 멋있겠지만 역시 초보는 초보답게 Management Plugin을 사용하여 설정하기로 함 (rabbitmqctl 공부하기 귀찮….)

1. 서비스용 계정 설정

관리자로 설정한 rabbitmq 아이디로 Management Plugin 에 접속해 보면 상단에 ‘Admin’ 이라는 메뉴가 보인다.  클릭하여 Users 기능으로 계정을 관리할 수 있다.

RabbitMQ Management 2014-10-07 14-58-08
요런 화면이 나온다. 딱히 계정관리에 어려울건 없다. GUI니 그냥 계정 두어거 생성/삭제 해보면 금방 감이 온다. 단, 주의할 것은 Tags와 Virtual Host 부분이다.

  1. Tags : 게정의 권한을 부여하는 부분. Admin, Monitoring, Policymaker, Management, None 이렇게 5가지 종류가 있다. Admin은 말그대로 Rabbitmq를 마음대로 주무를 수 있는 관리자 계정이고 Monitoring은 조회만 가능하다. Policymaker,  Management 등등이 있는데 이 문서는 초보용이니 설명은 과감히 생략! 주의 사항으로 정의 권한을 최소한 Management 로 설정해 주어야 Management Plugin에 접속이 가능하다. (한마디로, 지금 rabbitmq를 None으로 설정해버리면 이제 Management Plugin 사용 못한다. 으하핫!) None으로 설정해버리면 오직 Client용 계정으로 작동하여 Management Plugin에 접속이 불가능해진다. 향후 관리자용 계정(Admin), 모니터링 계정(Monitoring), 서비스 Client 계정(None)으로 분리하여 사용할때 잘 구분지어 주도록 하자.  아! Tags 라는 이름 답게 여러개 설정이 가능하다.
  2. Virtual Host : Queue와 계정을 그룹핑 하는 개념이다. 사실 이것때문에 많이 방황(?)했다. 하나의 계정은 여러 Virtual Host을 할당 받을 수 있으며 자신에게 할당된 Virtual Host에 속한 Queue에만 접근이 가능하다. 자세한 설명은 뒤에서….

이미 앞선 장에서 rabbitmq 계정을 amin으로 생성했으니(그래서 Management Plugin에 접속이 가능!) 더이상 쓰지 않을 guest 계정은 삭제하고 서비스 Client 로 사용할 계정 두개를 만들어 보도록 하자. (None Tag로 pushService, smsService 두개를 만들어 보자)

2. Virtual Host 설정

나를 매우 혼란스럽게 해주었던 Virtual Host에 대해 알아보자! 앞서 대충 설명했듯이 일종의 Queue 접근에 대한 그룹핑이다. Exchange 란 애도 함게 설정이 되어야 하는데 일단 서비스용 계정 설정에 집중을 하도록 하자. Management Plugin에서 Admin => Virtula Hosts 메뉴에 들어가면 아래와 같은 설정 화면이 나온다.

RabbitMQ Management 2014-10-07 15-22-28

앞에서 설정한 계정 이름을 보면 예상이 되듯이 smsService 와 pushService 두가지 서비스가 RabbitMQ를 사용할 예정이다. 이 둘은 서로 관계가 없으니 서로의 Queue나 설정을 알필요도 관심도 없다. 그러니 서비스별로 서로 독립된 구역을 나누어주는게 좋은데 그 단위로 Virtual Host를 사용할 수 있다. smsHost와 pushHost를 당장 만들어보자. 만든 후에는 Users에서 계정별 설정을 사용하여 smsService에는 smsHost를 pushService에는 pushHost를 설정해주도록 하자. rabbitmq계정에는 모든 Virtual Host를 설정해주자. 제대로 설정했다면 Users에서 아래와 같은 화면을 볼 수 있다.

RabbitMQ Management 2014-10-07 15-50-36
참고로 한개의 계정에는 여러 Virtual Host를 설정할 수 있다. 전체 관리자나 전체 모니터링 계정의 경우에는 모든 Virutal Host를 설정하여 쉽게 관리할 수 있도록 하는게 좋다. Virtual Host에 대한 이런 저런 Policy 설정도 가능하긴 한데 이건 초보용이니 과감히 생략! (사실 딱히 특이한 경우가 아니면 쓸일이 없을거 같다..)

다음에 Queue와 Exchange를 설정하게 되면 알겠지만 관리자 계정이든 일반 계정이든 모두 자신에게 설정된 Virtual Host 영역의 Queue와 Exchange에만 CRUD가 가능하다. 다른 Virtual Host의 Queue나 Exchange는 존재조차 확인할 수 없다.

내용은 별거 아닌데 벌써 지친다;;; 서비스용 Queue와 Exchange 설정과 개념 설명은 다음에….

[Rabbitmq] 1. 초보를 위한 RabbitMQ 후딱 설치하고 설정하기

회사의 캐시카우 서비스의 푸시 파트를 개선해야할 일이 생겼다. 레거시 코드가 너무 old한게 가장 큰 문제인데 그 중 눈에 띄는 것은 push message queue를 RDBMS로 구현해 놓은 부분이다. DB 튜닝 할때도 message pub/sub 부분에서 DB에 부하가 종종 크게 나오는 것으로 봐서는 이 부분 개선은 필수 인거 같다. 결국 mq 서버를 사용하는 것으로 결론이 났는데 무엇을 쓸까 수소문 하다가 RabbitMQ를 사용하기로 결정했다.

CloudFoundry의 Nats와 Apache ActiveMQ도 후보 중 하나였으나 난 왜 RabbitMQ를 선택했을까? 그냥 주변에서 많이 써서….
(노..농담이고 Nats는 설치도 간편하고 사용성도 좋긴 한데 클러스터링/미러링 이 안되는 가장 큰 문제점이 있다. ActiveMQ는 그냥 주변에서 RabbitMQ를 더 추천해서 써보지도 않고 팽했다.)

여튼  RabbitMQ는 처음 다루다 보니 일단 사이트(https://www.rabbitmq.com/) 방문해서 닥치고 매뉴얼을 읽고 Start!

1.  설치 (ubuntu 기반)

좀 매니악한 개발자 코스프레좀 해볼까 하고 소스 부터 설치하려했다가 erlang부터 설치해야하는 귀찮니즘의 압박으로 결국 apt-get 느님의 도움을 받기로 함
참고 페이지 : https://www.rabbitmq.com/download.html

$>sudo apt-get install rabbitmq-server

2. Management Plugin 활성화

설치가 완료 되면 terminal이 익숙치 않은 초보(?)를 위해 제공하는 Management Plugin도 활성화 시켜 놓자. 플러그인 설치 후에는 RabbitMQ를 restart 해주어야 변경 사항이 반영된다.
참고 페이지 : https://www.rabbitmq.com/management.html

$>sudo rabbitmq-plugins enable rabbitmq_management
$>sudo service rabbitmq-server restart

3. 관리자 계정  추가

처음 설치하면 guest 계정을 제공하기는 하는데 안타깝게도 localhost에서만 접속을 허용한다. 즉, 설치하자마자 Management Plugin의 유려한 UI로 막막 설정해보고 싶었지만 로그인 조차 안되는 난감함이 기다린다. 그러니 일단 RabbitMQ를 설치하고 난 뒤 바로 Terminal에서 관리자 계정을 설정해주도록 하자. 아래 예제에서는 관리자 계정을 rabbitmq로 설정했다.

$>sudo rabbitmqctl add_user rabbitmq password
$>sudo rabbitmqctl set_user_tags rabbitmq administrator

4. Management Plugin 접속

유저 설정까지 끝냈으면 Management Plugin으로 RabbitMQ를 관리해보도록 하자.
웹브라우저로 http://serverip:15672/  에 접속하면 아래와 같은 화면이 나온다.

RabbitMQ Management 2014-10-06 17-59-02

이제 3번에서 설정한 관리자 id로 접속을 해보자. 로그인에 성공하고 아래와 같은 화면이 나오면 성공!

RabbitMQ Management 2014-10-06 18-00-51

축하합니다! 기본적인 RabbitMQ의 설치 및 기본 설정을 끝내셨습니다!

다음 시간엔 서비스용 계정 및 Virtual host 설정 하는 법을 진행해볼까 합니다.

지름의 원칙

가계부 관리를 위한 지름의 원칙

제 1원칙, 모든것은 일시불이다.

제 2원칙, 일단 집부터 사자.

제 3원칙, 지르기전에 이성적으로 질러야 이유를 최소한 3가지는 충족 시켜야 한다.

제 4원칙, 일단 샀으면 감가상각을 다 소진할때까지는 쓴다.

제 5원칙, 조금 비싸도 오래 쓸 물건을 산다.

야근중 갑자기 떠오른 옛날 안드로이드 어플 개발하던 시절 이야기

2010년 즈음 L모 그룹 SI회사에서 일하고 있던 때,
L모 그룹 전자회사에서 일하는 동창과 차타고 이동하던 중 나눈 대화

친구 : 모바일 오피스 이딴걸 왜 만든거야? 아오 진짜 그지같네
나 : 음 사정이 있지 않았을까? 그룹사 전체 시스템을 모바일로 통합하는 작업도 만만치 않았을 테고
친구 : 아오 짜증나 진짜 이딴걸 왜 쓰라고 해서 짜증나게 하는거야
나 : 그거 만든사람도 잘 만들고 싶었을 거야. 근데 너도 알다시피 전자랑 SI하면 일정 겁나 쪼잖아. 솔직히 잘 만들기 힘들지
친구 : 아오 그래도 어떻게 앱을 이렇게 만드냐 이건 쓸 수 있는 수준이 아니잖아!
나 : 뭐 좀 그렇긴 한데 아까 말했듯이 일정 문제도 있고 그 기간에 이제 막 나온 안드로이드로 갑자기 개발하려면 쉽지도 않고…
친구 : 그래도 이건 아니지! 이거 만든 개발자를 잡아다 족쳐야되
나 : 내가 만들었다 개새야! 닥쳐!

놈이 운전하고 있어서 차마 때릴 수가 없었다.

요즘 헬 프로젝트에서 개발자로서 일할 때 느끼는 몇가지

요즘 헬 프로젝트에서 개발자로서 일할 때 느끼는 몇가지

1. 좋은 기술이라고 막 가져다 쓰지 말자

최신 레이져총을 가져다가 몽둥이처럼 휘두를 거라면 그냥 동네 문방구에서 파는 야구방망이나 사다 휘두르자. 그게 더 확실하고 값싸고 안전하다. 최신 레이저총이 뿜어내는 고열에 자폭당하고 싶지 않으면 말이다. 제어할 수 없는 강력한 기술은 약간의 변수로도 재앙 덩어리리로 변하기 쉽상이다.

그리고 쓰기로 작정했으면 제발 메뉴얼 정도는 읽어두자. 우리는 뉴타입이 아니다. 혹, 내가 뉴타입인거 같은 느낌이 들더라도 메뉴얼 꼭 읽자. 같은 뉴타입이라도 종이 다르다. 아무로의 미친 짓은 아무나 따라 하는게 아니다.

2. 자존심 따위는 개나 줘버리자

주변엔 나보다 잘나고 뛰어난 동료가 널려있다. 잘 모르고 못하겠으면 그냥 난 모르겠음 선언하고 물어보자. 만고의 진리나 깨달음을 얻진 못하더라도 최소한 더 나은 해결책은 반드시 나오기 마련이다. 백짓장도 둘이 드는게 낫다.

실천하기는 정말 쉽다. 뭔가 일이 막힐 때 자존심은 잠시 서랍 안에 놓아 두고, 개인적으로는 그냥 쓰레기통에 버리는 것도 좋다고 본다, 잘 알것 같은 사람을 찾아가 솔직하고 겸손하게 물어보자. 죄송한데 잘 모르겠으니 좀 도와달라고 말이다. 그리고 나로 인해 소모될 상대의 두뇌의 포도당을 걱정하며 손에 초콜릿 하나 쥐어 주는건 센스다.

3. 상사에게 혼나는 것을 두려워 말고 상사에게 거짓말을 하는 것을 두려워 하자

수 많은 일들이 복잡하게 얽히는 사회 생활에서 상사에게 혼나는 일이 없을 수가 없다. 그건 매우 자연스러운 일이라고 생각한다. 그것보다는 상사에게 혼나는 것을 두려워하여 거짓말을 하게 되는 것을 경계해야한다고 본다. 혼나는것이 두려워 거짓말을 늘어놓다 보면 큰 소리 몇번 듣고 끝날 일을 팀 전체를 한방에 훅 보내버리는 대형 사고로 진화시킬 수 있다.

안타깝게도 가끔 솔직하게 말하는 사항들에 대해서 과하게 반응하거나 무시해버리는 상사들에 대한 이야기를 듣게 되는데 그런 상황에 처해 있다면 상사가 그러지 않다록 잘 설득 하던가 그게 안되면 제껴 버리던가 그것도 안된다면 어서 다른 거처를 마련하고 떠나야 한다고 본다. 머지 않아 그 사람으로 인해 단체로 훅 가버릴 확률이 매우 높다.

4. 정확하고 완결성 있게 일하도록 하자

뭔가 일만 잔뜩 벌려놓고 결과는 뭔가 싸다 만 똥 마냥 남겨 놓는다면 곧 그 업을 혼자 감당해야 하는 지옥을 경험하게 될 것이다. 특히 여러 팀과 협업하는 상황에서 한번 잘못 전달된 사항들은 계속 재생산 되며 끝없이 나를 괴롭힌다. 그리고 주변 동료들의 히스테리와 상사의 질책은 보너스로 주어진다.

시시포스의 형벌 같은 업무를 즐기는 변태성 노동자가 아니라면 많이 일하는 것 보단 정확하고 완결성 있게 일하는 것에 힘쓰도록 하자. 회사일을 하다 보면 급한 일이니 대충이라도 처리하라는 지시를 자주 받게 되는데, 생각 있는 개발자라면 언발의 오줌 누기식 개발은  안하느니만 못하다는 것을 잘 알것이다.

5. 직접 해보고 확인한 결과에 대해서만 말하자

어디서 강의만 듣고 와선 다 아는 것처럼 떠들어 대거나 구글에서 검색한 소스를 적당히 Copy&Paste 해놓고 엄청난 일을 한것 마냥 으시되는 것처럼 꼴불견도 없다. 개발자라면 최소한 직접 해보고 확인한 결과에 대해서만 말하도록 하자. 상황이 어쩔 수 없어 뭐라도 말해야 한다면 적어도 그 출처와 정확성에 대해서라도 상세하게 말할 수 있어야 한다. 그렇지 않다면 그냥 뻥쟁이일 뿐이다. 그리고 그 뻥쟁이가 득세하는 곳은 영원히 지옥의 나락에서 벗어나지 못할 것은 뻔하다.

그러니 개발자라면 언제나 리누스 토발즈님의 명언을 가슴에 아로 새기도록 하자.

Talk is cheap. Show me the code.

6. 누군가에게 일을 부탁할 때는, 혹은 지시할 때는, 정확히 원하는 내용을 전달해 주자

“내가 만들던거 하나 있는데 그것좀 마저 개발해줘. 소스 받아서 확인해보면 될거야.”

막막하다. 대체 당신이 하던 일이 뭐고 그 소스는 어디있는거고 그 소스의 어디를 보라는 건지 알려는 줘야 할거 아니오! 이양반아! 설명하기 귀찮은건지 본인도 자기가 뭘 하고 있는지 몰라 그러는건진 몰라도 여튼 당신하기 싫은 뻘짓 나보고 하란 이야기잖아!

개발자라면 최소한 부탁하려는 일의 목적은 무엇이고 현재 상황이 어떠한지, 그리고 일이 어디까지 진행된 상태이고 상대방이 무엇을 해주면 되는지를 정확히 전달하도록 하자. 나의 친절한 설명 한번이면 상대방은 부탁받은 일을 수월하게 진행할 수 있고 나는 원하는 결과를 빨리 받을 수 있으니 서로에게 좋은 일이다.

7. 문서 기반으로 일하자

개발자라면 내가 만든 결과물을 다른 사람과 공유해야할 때가 자주 있다. 그럴때를 대비해 언제나 문서화를 생활화 하도록 하자. 전달 받는 사람 입장에서는 잘 정리된 문서가 있으니 언제든 참고 할 수 있어 좋고, 전달 해주는 입장에서는 만나는 사람마다 일일히 설명해줘야 하는 부담을 덜 수 있으니 좋다. 30분만 투자에서 정리해 놓으면 그 몇배 이상의 시간 절약할 수 있다.

먼저 문서로 일하고, 부족한 부분은 전화로 해결하는 것이 빠르고 쉽다.

몇가지 더 있는데 정리가 안되므로 나중에…

하나를 얻었으면 다른 하나는 잃기 마련이다.

하나를 얻었으면 다른 하나는 잃기 마련이다. 매우 간단한 원리다.

여자친구를 얻었다면 주말에 누리던 개인의 자유는 포기해야 한다.
행복한 가정을 얻길 원한다면 총각의 자유로움은 당연히 포기해야한다.
차를 가졌다면 유지 비용과 관리해야 하는 시간을 잃어 버릴 것이고, 사기당하지 않으려면 어느정도 공부도 해놔야 한다 ,
조각같은 몸매를 가지려면 달콤한 술과 야식을 포기해야한다.

문장의 마무리가 잃는다는 끝나니 뭔가 부정적으로 보이기도 하는데 반대로 보면 매우 긍정적이다.

별일 없이 보내던 혼자만의 시간을 포기한다면 상상속의 동물로 여기던 여자 친구를 얻을 수 있다.
(사실 포기해야 할 것이 더 있지만 자세한건 생략한다. 히히히!)
총각의 자유로운 삶을 포기한다면 당신은 행복한 가정을 꾸릴 수 있다.
유지 비용과 관리 시간을 감당할 수 있다면 당신은 멋진 차를 가질 수 있을 것이며,
술과 야식을 포기한다면 당신은 조각같은 몸매와 건강을 얻을 수 있다.

알게 모르게 우리는 이 간단한 원리 속에서 늘 삶의 중요한 선택을 해왔다.

사람의 근본적인 불행의 원인중 하나는 공존할 수 없는 두개를 동시에 원한다는 것이다.
하나를 얻는 순간 다른 하나는 포기할 수 밖에 없다는 사실을 인정하지 않는 순간 삶은 고통의 나락으로 떨어진다.

뭐 스스로의 강력한 의지로 그 고통의 나락에서 몸부림쳐 두개를 모두 얻는다 해도 그 두개가 정상일 확률은 극히 적다.
행복한 가정과 함께 다른 여자와 달콤한 연애를 꿈꾸는 삶은 결국 불륜의 나락으로 떨어지는 것 처럼 말이다.

나름 살면서 느낀 행복론 중 하나는 하나를 얻었으면 하나는 잃기 마련이라는 사실을 인정하는 것이다.
이 원리 하나에만 충실해도 나를 괴롭히는 삶의 불행중 상당수는 자연히 사라진다.