aro dream

development, dream, human

Redmine 이메일 리마인드 시키기

일감(issue)이 생기면 redmine에서 자동으로 이메일을 보내기는 하지만 일감 시한이 얼마 남지 않았을 때 리마인드 시킬 필요가 있어서 찾아 보았다.

처음으로 찾은 것은 플러그인 중에 이메일 리마인드시키는 플러그인이 있어서 시도해 보았으나 결론은 꽝~!

Redmine 3.3까지만 지원하는데 모르고 계속 시도하다가 결국은 포기하였다… (지금 우리가 쓰고 있는 것은 3.4.3)

다시 찾다보니 Redmine 홈페이지에 방법이 있어 정리~!

Redmine은 할당되어 활성화된 일감들에 대해 리마인드 이메일 보내는 기능을 rake를 이용하여 제공한다. 대상은 시한이 지났거나 얼마 남지 않은 일감들이다.

가능한 옵션들은 다음과 같다.

  • days: 리마인드시킬 일감의 시한까지 남은 날의 수 (defaults to 7)
  • tracker: tracker 아이디 (defaults to all trackers)
  • project: project 아이디 (defaults to all projects)
  • users: 리마인드를 시킬 사용자들. ‘,’로 구분한다
  • version: 해당 이슈들의 대상 버전의 이름 (defaults to none)

예) 기한이 지났거나 7일내로 남은 일감에 할당된 사용자들에게 이메일을 보냄:

bundle exec rake redmine:send_reminders days=7 RAILS_ENV="production" 

예) 사용자 1, 23, 56에게 기한이 지났거나 7일내로 남은 일감에 대해 이메일을 보냄:

bundle exec rake redmine:send_reminders days=7 users="1,23,56" RAILS_ENV="production" 

한번만이 아니라 주기적으로 수행하려면 크론탭(Linux) 또는 스케쥴러(Windows)에 등록해야 한다.

예) 월요일부터 금요일까지 8:50에 redmine 디렉토리로 이동한 후 리마인드 이메일을 보냄:

crontab -e
50 8 * * 1-5 cd /opt/redmine-3.4.3-2/apps/redmine/htdocs/ && /opt/redmine-3.4.3-2/ruby/bin/bundle exec rake redmine:send_reminders days=1 users="1,5,6,7,8,9,10" RAILS_ENV="production"

이상~ 잘 동작하고 있다~!

Redmine 홈페이지의 ‘Sending Reminder Emails‘ 참조

‘풀스택 엔지니어’님의 ‘Crontab 사용법 정리‘ 참조

Advertisements

Redmine 백업과 복구하기 (Redmine backup & restore)

Redmine은 계속 쓰면서 정작 백업은 소홀히 한 것 같다.

백업도 하고, 정리도 할 겸 관련 내용 정리~!

1. 다른 장비(서버)로 옮기는 가장 간단한 방법

전체 복사를 이용한 방법이 가장 간단하다.

  1. 기존 설치되어 있는 장비의 Bitnami 설치 디렉토리를 통째로 복사한다
  2. 새로 설치할 장비의 설치 디렉토리에 붙여놓기 한다.
  3. 새로운 장비의 [Bitnami Home] 에서 serviceinstall.bat 실행 (Windows의 경우)

정말 간단하다~

* Linux의 경우는 해당되지 않는다… 찾아 봐야 겠다.

2. Redmine 백업

1. [Redmine Home]\apps\redmine\htdocs\config\database.yml 오픈하여 password 확인한다.

 

2. db dump 생성

mysql이 설치되어 있는 곳의 bin 디렉토리로 가서 mysqldump를 실행하여 백업파일을 만든다.

mysqldump 실행 시 위에서 알아낸 비밀번호를 이용해야만 한다.

cd [Redmine Home]\mysql\bin
mysqldump -ubitnami -p[password] bitnami_redmine > [Backup Home]\redmine.bak.dump (windows의 경우)
ex) ./mysqldump -ubitnami -p12345678 bitnami_redmine > /backup/redmine.bak.dump (linux의 경우임)

* 만약 mysqldump 실행시 아래와 같은 경고 메시지가 나와도 실행은 된다.

Warning: Using a password on the command line interface can be insecure.

mysql 5.6버전부터 mysqldump 명령시 mysql_config_editor를 이용한 로그인 설정이 필요하다고 한다.
하지만 이 경고 메시지가 보기 싫다면 아래와 같이 해도 된다.
먼저 login-path 설정

mysql_config_editor set --login-path={설정명} --host=localhost --user=root --password Enter password: {패스워드를 입력하여 저장}

그리고는 다음과 같이 사용한다.

mysqldump --login-path={설정명} {디비명} > {백업파일명}.sql

옵션 내용은 다음과 같다.

--login-path : 구분하기위한 문자열
--host : 접속하려는 DB서버의 호스트명 또는 IP
--user : 저장할 계정
--password : 패스워드값은 제외하고 옵션만 지정하여 실행

3. 첨부파일, 플러그인, 테마 백업

[Bitnami Home]\apps\redmine\htdocs 에서 각 항목에 맞는 디렉토리들을 복사한다.
보관을 용이하게 하고 용량을 줄이기 위해 압축해서 놓는 것을 권장한다.
1) 첨부파일 : files 디렉토리
2) 플러그인 : plugins 디렉토리
3) 테마 : public\themes 디렉토리

tar -zcvf /opt/redmine-3.4.3/apps/redmine/htdocs/files /backup/redmine_files.bak
tar -zcvf /opt/redmine-3.4.3/apps/redmine/htdocs/plugins /backup/redmine_plugins.bak
tar -zcvf /opt/redmine-3.4.3/apps/redmine/htdocs/public/themes /backup/redmine_themes.bak

이렇게하면 백업 완료~!

3. Redmine 복구

1. db dump 복구

위에서 알아낸 비밀번호를 사용하여 백업파일로 부터 mysql 데이터를 복구한다.

mysql -ubitnami -p[password] bitnami_redmine < [Backup Home]\bak.dump

2. 백업해두었던 첨부파일, 플러그인, 테마 붙여놓기

백업해 놓았던 redmine 첨부파일, 플러그인, 테마 파일들을 다시 옮겨 놓는다.
테마의 경우 redmine 버전을 올릴 경우 복구한 테마는 깨질 수도 있으므로 주의!

3. 아래 명령으로 마이그레이션 수행

cd [Redmine Home]\apps\redmine\htdocs
# db migration
bundle exec rake db:migrate RAILS_ENV=production
# plugin migration
bundle exec rake redmine:plugins:migrate RAILS_ENV=production

이로써 복구 완료~!

‘흔한 컴공의 블로그’님의 ‘Bitnami Redmine 백업과 복구‘ 기사 참조

이메일 서버 구축하기 (struct email server)

이번에 ucloud에 이메일 서버를 구축할 일이 있어서 진행하였는데…

생각보다 꽤 많은 일을 해야 했다. (귀찮게도…)

다음은 이메일 서버를 구축하기 위해 필요한 용어 정리~

  • DNS(Domain Name System):
    • DNS는 연결할 수 있는 서버 목록으로 acme.com과 같은 이름을 변환하고 특정 서버의 IP 주소를 찾기 위해 SMTP에서 사용하는 디렉토리이다. 발송 서버는 대상 서버의 주소를 DNS에서 찾아 수신인에게 메시지를 정확하게 라우트한다. DNS가 사용하는 두 종류의 레코드는 MX(Mail Exchanger) 레코드와 A 레코드이다.
  • A 레코드:
    • 호스트 이름을 서버의 IP 주소로 매핑한다.
  • MX(Mail eXchange) 레코드:
    • MX 레코드는 특정 도메인에 대한 메일을 수신하는 메일 서버를 지정하는 레코드이다.
      어떤 도메인에 MX 레코드로 받을 메일서버를 지정하면 그 도메인으로 오는 메일은 받을 메일서버로 전달된다. 메일을 받을 서버(MX record)명은 A레코드가 지정되어 있어야 한다. 따라서, MX 레코드를 설정하려면, 먼저 해당 메일 서버에 대한 A 레코드를 등록한 이후에 MX 레코드를 등록하고, MX 레코드의 데이터에 A레코드 호스트명을 입력하면 된다.
    • DNS 서비스의 표준에 의하면, 메일을 받을 서버(MX record)는 호스트이름이거나 도메인명이어야 한다. 표준대로라면 받을 메일서버로 IP 어드레스로 입력하는 것도 가능하지만, 이 경우 이를 IP 주소로 인식하는 것이 아닌 호스트명으로 인식하기 때문에, IP주소를 입력하면 실제로 메일을 받을 수가 없게 된다. 즉, 예를 들어 10.20.30.40 이라는 IP주소를 입력하게 되면, 메일을 보내는 서버는 DNS 정보에서 이 정보를 찾아와서 호스트명으로 인식하기 때문에, 10.20.30.40 의 맨 마지막 숫자인 40을 .com과 같은 도메인으로 인식하고, 이 40 도메인에 대하여, 메일서버 정보를 찾으나, 이러한 도메인은 존재하지 않으므로 결과적으로 메일을 받지 못하게 되는 것이다.
    • MX 레코드 즉, 메일 교환 레코드는 DNS(도메인 이름 시스템)의 리소스 레코드 유형이다. 이 레코드는 단순 메일 전송 프로토콜(SMTP)을 사용하여 인터넷 이메일을 라우팅해야 하는 방법을 지정한다. 각 MX 레코드에는 호스트 이름 및 선호도가 들어 있다. 호스트 이름은 이메일이 올바른 대상에 도착하도록 안내한다. 선호도는 여러 서버의 상대적 우선순위를 나타낸다.
    • 예를 들어, “alex@example.com” 같은 이메일 주소가 제대로 작동하도록 하려면, 도메인 “example.com”의 MX 레코드를 설정해야 한다. 이렇게 하려면 MX 레코드가 이메일 서버의 IP 주소나 도메인 이름을 가리키도록 해야 한다. 도메인 이름을 미리 등록한 경우, 해당 도메인 이름의 관리 콘솔(신청한 ISP업체 홈페이지에 있다)에서 이 설정을 수정할 수 있다.
  • 정방향 DNS:
    • 특정 DNS 레코드를 도메인 이름에 할당하는 프로세스. 이는 도메인 이름을 정확한 서버로 연결하는 것이다.
  • 역방향 DNS:
    • 역방향 DNS는 웹사이트의 숫자 주소(IP 주소)를 도메인/호스트 이름으로 변환하는 것을 말하며, 도메인/호스트 이름을 IP 주소로 변환하는 정방향 DNS 프로세스와 반대이다. 역방향 DNS는 지정한 IP 주소에 속한 도메인 이름/호스트를 찾는 것을 지칭하기도 한다. 이것이 이러한 프로세스를 역방향 DNS 조회라고도 하는 이유이다. 도메인 이름에 유효한 역방향 DNS가 있으면 IP 주소만 사용하여 접근할 수도 있다.
    • 역방향 DNS는 메일 시스템 실행을 위한 기본 요구 사항 중 하나이다. 역방향 DNS는 들어오는 메시지의 IP 주소가 인증된 도메인 이름과 일치하는지 확인하여 일치하지 않는 경우 해당 메시지를 차단하는 스팸 필터로 주로 사용된다. 메일 서버에 역방향 DNS를 설정하지 않으면, 메일 서버에서 보낸 메시지가 대부분의 주요 이메일 서비스에 의해 차단될 수 있다.
    • 역방향 DNS를 직접 설정할 수 없는데 계속해서 배달 문제가 발생하는 경우 정상적인 이메일 배달을 위해 다른 SMTP 서버를 추가하라. 이메일을 보낼 때 스패머로 취급되지 않도록 하려면 보다 더 잘 알려진 SMTP 서버를 사용하는 것이 좋다.

    • 일부 ISP는 zone의 일부를 사용자에게 위임할 수 있습니다. 따라서 사용자가 직접 자체 역방향 DNS를 호스팅할 수 있다. DNS 서버에서 PTR 레코드를 확인하여 역방향 DNS를 구성할 수 있다. PTR 레코드는 귀하에게 할당된 IP 주소를 제어하는 주체가 관리한다. 호스트가 하나 이상의 IP 주소가 포함된 IP 공간에 대한 역방향 DNS를 귀하에게 위임한 경우 이러한 주체는 귀하의 호스트 또는 귀하일 수 있다. 일반적으로 PTR 레코드는 in-addr.arpa 항목 앞에 오는 뒤에서부터 입력된 IP를 나타낸다. ISP와 함께 역방향 DNS 설정 — ISP 즉, 귀하의 IP 주소를 소유한 주체는 유일하게 적절한 PTR 레코드를 추가할 수 있다. 역방향 DNS 구성을 위해 ISP에 문의해야 할 수 있다.
  • SPF(Sender Policy Framework) 레코드:
    • 메일 서버 등록제라고도 불리는 이 설정 값은 메일을 이용하는 도메인에 설정하는 값이다. 발송한 메일서버의 IP와 DNS에서 설정되어 있는 TXT의 IP 값이 다를 경우에 수신 측에서 메일을 차단하는 방식을 말한다. 메일을 발송하는 서버의 IP와 도메인이 일치하는지 인증을 하며, 인증방법으로 SPF 레코드(TXT값)를 확인한다.
    • 주로 메일주소를 위장하여 스팸성 메일을 발송하는 것을 차단하기 위해 국내 주요 포탈사이트 및 기업 등에서 사용한다.
  • PTR 레코드 (Reverse DNS):
    • PTR 레코드 (Reverse Domain) 정책은 도메인이 아닌 IP를 질의하여 도메인을 확인하는 정책으로 수신측에서 메일 발송 서버의 IP를 조회하여 도메인이 등록된 PTR 레코드 값과 일치하면 정상메일로 판단하고 메일을 수신하겠다는 역방향 질의 방식이다. Reverse Domain의 일치 여부를 확인할 때 PTR 레코드를 조회하기 때문에 PTR 레코드와 Reverse Domain은 같은 의미로 통용된다.
    • SPF 레코드와 다른 점은 DNS 운영업체가 아닌 ISP업체 (KT, LG U+, SK, 하이라인넷 등)와 같이 IP 주소를 공급해준 업체에 등록을 해야 한다는 것이다. 따라서 자체적으로 메일시스템을 구축한 경우가 아니라면 메일 서비스를 제공하고 있는 업체에 연락해서 등록 요청을 하면 된다.
  • 화이트 도메인 (White Domain):
    • 공지, 안내 등 정상적으로 발송하는 대량 e메일이 스팸메일로 간주되어 RBL(Realtime Black List)에 등록되는 것을 방지하기 위해, 사전에 등록된 개인이나 사업자에 한하여 국내 주요 포탈사이트로의 email 전송을 보장해 주는 제도. 단, 화이트 도메인으로 등록되었다 하더라도 이후 모니터링을 통해 스팸 메일 발송 사실이 확인되면 즉각 차단 조치되며 화이트 리스트에서도 삭제될 수 있습니다.

국내의 경우 SPF 레코드가 스팸정책에 영향력이 높으며 해외의 경우 PTR 레코드가 스팸차단의 기준이 된다. 그래서 국내포탈이나 기업의 차단은 SPF 레코드 등록 및 화이트 도메인 등록을 중점적으로 체크해야 하며 해외메일 수신 차단의 경우는 PTR 레코드를 등록 후 체크해야 한다.

진행했던 일을 순서대로 정리해보면

  1. Domain을 구입한다.
    • 난 가격이 저렴한 hosting.kr에서 구매했다. communicationcloud.co.kr. 가격비교사이트에서 잘 비교해서 도메인 등록업체를 고르면 된다.
  2. Domain을 산 도메인 등록업체에 sub domain A 레코드를 등록한다.
    • Hosting.kr에서 ‘나의 서비스 관리/도메인 관리’ 페이지로 가서
    • communicationcloud.co.kr 도메인을 선택하고 나서
    • 아래로 내려가 ‘네임서버(서브도메인) 설정 관리’를 선택하고 나서 ‘신청하기’ 버튼을 누른다
    • ‘네임서버(서브도메인) 설정 관리’ 페이지에서 ‘서브도메인’ 항목에 ‘mail’을 넣고
    • ‘레코드타입’은 ‘서브도메인(A)’를 선택하고
    • ‘IP주소/레코드 값’ 항목에는 메일 서버의 IP (예: 111.222.333.444)를 넣고
    • ‘우선순위’ 항목에 적당한 값 (작을 수록 우선순위가 높다)을 넣고 ‘설정내용 추가’ 버튼을 누른다.
    • 내용이 잘 들어가 있는지 확인한 다음 ‘적용하기’ 버튼을 누른다.
    • nslookup 명령어를 통해 확인한다.

      C:\Users\aro>nslookup mail.communicationcloud.co.kr
      서버: ns.xxxx.co.kr
      Address: 154.xxx.xxx.xxx

      권한 없는 응답:
      이름: mail.communicationcloud.co.kr
      Address: 111.222.333.444

  3. Domain을 산 도메인 등록업체에 MX를 등록한다.
    • 마찬가지로 ‘네임서버(서브도메인) 설정 관리’ 페이지에서 ‘서브도메인’ 항목은 비워두고
    • ‘레코드타입’은 ‘MX레코드’를 선택하고
    • ‘IP주소/레코드 값’ 항목에는 메일 서버의 A 레코드 (mail.communicationcloud.co.kr)를 넣고
    • ‘우선순위’ 항목에 적당한 값 (작을 수록 우선순위가 높다)을 넣고 ‘설정내용 추가’ 버튼을 누른다.
    • 내용이 잘 들어가 있는지 확인한 다음 ‘적용하기’ 버튼을 누른다.
    • nslookup 명령어를 통해 확인한다.

      C:\Users\aro>nslookup -type=mx communicationcloud.co.kr
      서버: ns.xxxx.co.kr
      Address: 154.xxx.xxx.xxx

      권한 없는 응답:
      communicationcloud.co.kr MX preference = 9, mail exchanger = mail.communicationcloud.co.kr

  4. Domain을 산 도메인 등록업체에 spf를 등록한다.
    • 마찬가지로 ‘네임서버(서브도메인) 설정 관리’ 페이지에서 ‘서브도메인’ 항목은 비워두고
    • ‘레코드타입’은 ‘텍스트(TXT)’를 선택하고
    • ‘IP주소/레코드 값’ 항목에는 ‘v=spf1 ip4:111.222.333.444 -all’를 넣고
    • ‘우선순위’ 항목에 적당한 값 (작을 수록 우선순위가 높다)을 넣고 ‘설정내용 추가’ 버튼을 누른다.
    • 내용이 잘 들어가 있는지 확인한 다음 ‘적용하기’ 버튼을 누른다.
    • ‘IP주소/레코드 값’ 항목에 넣을 값은 아래 ‘SPF 작성 도우미’를 눌러 나에게 필요한 SPF 값을 생성한 후 넣는다. 입력시 앞뒤로 “”는 필요 없다.
    • nslookup 명령어를 통해 확인한다.

      C:\Users\aro>nslookup -type=txt communicationcloud.co.kr
      서버: ns.hansol.co.kr
      Address: 154.10.6.11

      권한 없는 응답:
      communicationcloud.co.kr text =

      “v=spf1 ip4:211.251.236.49 -all”

  5. White List에 Domain을 등록한다.
    • 한국인터넷진흥원(http://www.kisarbl.or.kr)에 접속하면 화이트 도메인의 소개 및 등록과정을 상세히 알려주고 있다. 안내절차에 따라 개인 혹은 사업자가 직접 등록 신청을 해야하며 화이트 도메인을 등록하기 위해서는 위에 언급한 SPF 레코드가 DNS에 반드시 등록되어 있어야 한다.
  6. 서버를 올린 호스팅 업체 또는 상위 업체(IP를 부여한 업체)에게 PTR Record를 등록한다.
    • ucloud의 경우 직접 PTR 레코드를 등록요청 할 수는 없고 IP를 부여한게 kornet이기 때문에 https://dms.kornet.net/ 에 들어 가서 PTR 레코드 등록 요청을 해야 한다. (이거 땜에 내가 회원가입까지 했다…)
  7. email 서버를 구축한다.
    • 원래는 Linux에서 구축할 수 있는 이메일 서버를 찾았는데 적당한 걸 못찾았다. 그래서 hMail과 Mail Enable 둘 중에 고민을 했는데, 멀티 도메인에서 쓰기에는 Mail Enable이 좋을 것 같고, web mail까지 지원을 해서 Mail Enable의 Standard 버전 (Free~!)을 사용하였다. http://www.mailenable.com
  8. pop3, smtp, iMAP 설정 및 테스트를 한다.
    • 매뉴얼을 참조해서 적당히 설정 완료~!

생각보다 꽤 많은 손이 갔고, 오랜 시간이 걸렸다.

다음에 혹시 또 구축할 일이 있으면 위 순서를 참조하기 위해 정리~!

 

* ‘지나가던_스피드왜건‘님의 조언에 따라 ISP를 도메인 등록업체로 수정하였습니다~

Redmine (Bitnami)에서 thin 서버가 사용하는 port 바꾸기 (windows)

금번에 외부 솔루션 하나를 테스트하기 위해 Redmine 서버에 같이 설치해서 사용하다가

port 충돌이 일어난다는 것을 알았다.

충돌이 일어나는 port는 3002번, thin_redmine2 서비스 였다.

외부 솔루션의 포트를 바꾸려고 알아봤지만 바꿀 수 없다는 대답을 듣고,

Redmine의 thin_redmine 서비스들의 포트를 바꾸는 법을 찾아 여기에 정리해 본다.

(의외로 오래 걸렸다능…)

 

모두 3개의 설정(configure) 파일의 내용을 바꿔주면 설정 완료~!

기존 thin_redmine:3001, thin_redmine2:3002 포트들을 thin_redmine:3009, thin_redmine2:3010으로 바꾸도록 하겠다.

 

  1. Redmine 설정 파일이 있는 폴더로 이동한다.
        Redmine이 설치되어 있는 폴더에서 Redmine의 설정 폴더로 이동한다.
          ex) C:\Bitnami\redmine-3.1.0-0\apps\redmine\conf
  2. httpd-vhosts.conf 파일 내용을 수정한다.
  3. httpd-prefix.conf 파일 내용을 수정한다.
  4. Redmine scripts 폴더로 이동한다
        Redmine이 설치되어 있는 폴더에서 Redmine의 scripts 폴더로 이동한다.
          ex) C:\Bitnami\redmine-3.1.0-0\apps\redmine\scripts
  5. thin_redmine 서비스들의 등록을 해제한다.
        serviceinstall.bat 배치파일을 실행시켜 thine_redmine 서비스들의 등록을 해지한다.
          ex) C:\Bitnami\redmine-3.1.0-0\apps\redmine\scripts\serviceinstall.bat REMOVE
  6. serviceinstall.bat 파일 내용을 수정한다.
        serviceinstall.bat 배치 파일의 ‘install’ 항목에서 this_redmine 서비스 시작시 포트 번호를 바꾸고자 하는 포트 번호로 수정한다.
      수정전)

        if not “”%1″” == “”INSTALL”” goto remove
        “C:\Bitnami\redmine-3.1.0-0/apps/redmine\scripts\winserv.exe” install “redmineThin1” -start auto “C:\Bitnami\redmine-3.1.0-0\ruby\bin\ruby.exe” “C:\Bitnami\redmine-3.1.0-0/apps/redmine\htdocs\bin\thin” start -p 3001 -e production -c “C:\Bitnami\redmine-3.1.0-0/apps/redmine/htdocs” -a 127.0.0.1 –prefix /redmine
        net start redmineThin1 >NUL
        “C:\Bitnami\redmine-3.1.0-0/apps/redmine\scripts\winserv.exe” install “redmineThin2” -start auto “C:\Bitnami\redmine-3.1.0-0\ruby\bin\ruby.exe” “C:\Bitnami\redmine-3.1.0-0/apps/redmine\htdocs\bin\thin” start -p 3002 -e production -c “C:\Bitnami\redmine-3.1.0-0/apps/redmine/htdocs” -a 127.0.0.1 –prefix /redmine
        net start redmineThin2 >NUL
      수정후)

        if not “”%1″” == “”INSTALL”” goto remove
        “C:\Bitnami\redmine-3.1.0-0/apps/redmine\scripts\winserv.exe” install “redmineThin1” -start auto “C:\Bitnami\redmine-3.1.0-0\ruby\bin\ruby.exe” “C:\Bitnami\redmine-3.1.0-0/apps/redmine\htdocs\bin\thin” start -p 3009 -e production -c “C:\Bitnami\redmine-3.1.0-0/apps/redmine/htdocs” -a 127.0.0.1 –prefix /redmine
        net start redmineThin1 >NUL
        “C:\Bitnami\redmine-3.1.0-0/apps/redmine\scripts\winserv.exe” install “redmineThin2” -start auto “C:\Bitnami\redmine-3.1.0-0\ruby\bin\ruby.exe” “C:\Bitnami\redmine-3.1.0-0/apps/redmine\htdocs\bin\thin” start -p 3010 -e production -c “C:\Bitnami\redmine-3.1.0-0/apps/redmine/htdocs” -a 127.0.0.1 –prefix /redmine
        net start redmineThin2 >NUL
  7. thin_redmine 서비스들을 등록한다.
        serviceinstall.bat 배치파일을 실행시켜 thine_redmine 서비스들을 등록한다.
          ex) C:\Bitnami\redmine-3.1.0-0\apps\redmine\scripts\serviceinstall.bat INSTALL
          <주의> INSTALL 철자를 꼭! 대문자로 한다. 아니면 해지가 된다…

 

이상이다~!

‘협업의 기술 (Team Geek A Software Developer’s Guide to Working Well with Others)’

지은이: 브라이언 피츠패트릭 (Brian W. Fitzpatrick), 벤 콜린스-서스먼 (Ben Collins-Sussman)

옮긴이: 장현희

출판사: 제이펍 (jpub)

이 책은 소프트웨어 개발자들간의 협업에 대한 이야기를 다룬다. 내용을 보면 개발 팀 관리에서 사용자 관리(?)까지 이 책에서 다루고 있다. 두 지은이가 꽤 오랜시간동안 경험해 온 이야기들을 잘 정리하여 여러 컨퍼런스 및 실전에서 써먹기까지 한 이야기들이라 현실적이라 말하고 있고, 내 생각에도 꽤 적용할 만한 내용들이 많다.

아쉽다면 번역이 잘된 편이기는 하지만 군데군데 내용 전개가 자연스럽지 못한 곳이 좀 있고, 그러다보니 내용이 잘 이해가 안되는 곳이 있다. 두 번 정도 읽으니 그런 곳도 이해가 되기는 한다. 그리고 외국 사례이고, 그것도 주로 구글과 SVN 개발 관련 사례다보니 우리의 현실과는 좀 다른 것도 있다. 그런 내용은 각자가 알아서 각자의 현실에 맞게 적당히 적용하는 것으로…


그룹프로젝트

차례

  1. 천재 프로그래머의 전설
    • 내 코드를 숨길 수 있게 도와주세요
    • 천재의 전설

      아직 마무리하지 못한 일을 다른 사람이 본다는 건 아주 불안한 일이죠. 다른 사람들이 진지하게 나를 판단하고 나를 바보라고 생각하는 것만큼이요.

    • 숨긴다는 것은 해로운 것이다
    • 결국은 팀이다

      소프트웨어 개발은 팀 스포츠이다.

    • 세 개의 기둥
      • 겸손(Humility)
          당신은 우주의 중심이 아니다. 또한, 전지전능하지도 않으며 항상 성공하는 것도 아니다. 자기 개선에 대해 항상 열려 있어야 한다.
      • 존중(Respect)
          당신은 함께 일하는 사람을 진심으로 존중할 수이썽야 한다. 그들을 인간으로 대하고, 그들의 능력과 업적에 감사해야 한다.
      • 신뢰(Trust)
          함께 일하는 사람들은 숙련된 인력이며, 항상 옳은 일을 할 것이라 믿고 적절하게 그들을 운영할 수 있어야 한다.

      모든 사회적 충돌은 대부분 겸손과 존중, 신뢰의 부족으로 인해 발생한다

    • HRT 실습
      • 자존심 버리기

        ‘겸손해진다는 것’은 누군가에게 당하기만 하는 것과는 다르다. 자신감을 갖는 것은 잘못된 것은 아니다. 단지 아는 체하는 행동을 삼가라는 뜻이다. 당신 자신이 현명한지 아닌지에 대해 걱정하는 것보다는 팀의 목표를 설정하고 조직의 자부심을 높일 수 있도록 ‘집단적’ 자부심에 대해 고려하는 것이 훨씬 낫다.

      • 베푸는 방법과 비판을 받아 들이는 방법 모두 배우기

        무엇보다 가장 중요한 것은 존중이 묻어나야 한다. 건설적인 비판을 하는 사람들은 진정 다른 사람을 위하며, 그 대상이나 대상이 하는 일이 향상되기를 원한다. 당신의 동료를 존중하고 건설적인 비판을 하되, 예의를 갖추는 법을 배워야 한다. 누군가를 진정으로 배려하는 마음이 있다면 요령껏 유용한 표현을 선택하게 될 것이다. 하지만 이 기술은 많은 연습을 거쳐야 얻을 수 있다.

        “이봐, 나는 이 부분의 흐름 제어가 약간 혼란스러운 것 같아. 여기에 xyzzy 코드 패턴을 적용하면 좀 더 명확하고 유지보수가 쉬워지지 않을까?”

      • 빨리 실패하라, 그것에서 배워라, 그리고 반복하라
      • 학습을 위한 시간을 아끼지 마라
      • 인내하라
      • 주변으로부터 영향을 받아들여라
    • 다음장에서는
  2. 환상적인 팀 문화는 어떻게 만들까
    • 문화란 무엇인가?

      당신의 팀 문화는 좋은 사워도우 덩어리와 같다. 당신이 배양한 씨균(당신의 종자)이 당신의 도우(즉, 새로운 구성원)에게 주입되어 이스트균과 박테리아(당신의 팀 구성원)와 함께 성장함에 따라, 마침내 훌륭한 빵 덩어리(당신의 팀)가 탄생하게 되는 것이다.

    • 왜 당신이 관심을 가져야 하는가?

      팀 문화에 있어 흥미로운 점은, 매우 강력하게 정의된 문화를 구축한다면 그 문화가 스스로 선택을 하게 될 것이라는 점이다. 오픈 소스 세계에서 HRT원칙을 근간으로 깔끔하고, 고급스러우며, 유지보수가 쉬운 코드를 작성하는 것을 중시하는 프로젝트는 그들이 존경하고, 신뢰하며, 깔끔하고, 고급스러우며, 유지보수가 쉬운 코드를 작성하는 사람들과 일하고 싶어 하는 엔지니어들을 매료시킨다.

    • 문화와 사람

      소프트웨어의 세계에서는 제품을 구현하는 엔지니어에게는 뛰어난 창의성을 요구하며, 훌륭한 엔지니어를 원한다면(그리고 그들이 계속해서 업무를 수행하게 하려면), 그들을 위한 문화를 만들고 그들이 안전하게 아이디어를 공유하고 의사 결정에 참여할 수 있도록 해야 한다. 만일 팀 단위 업무를 잘 수행하는 뛰어난 엔지니어를 원한다면, 훌륭한 엔지니어들을 고용하는 것부터 시작해야 한다. 우리가 알고 있는 많은 훌륭한 엔지니어들은 거대한 산업 분야에서 자신들이 뭔가를 더 배울 수 있는 팀에 매력을 느낀다.

    • 성공적인 문화의 의사소통 패턴
    • 높은 수준의 동기화
      • 사명
      • 능률적인 회의
      • ‘지리적으로 협업이 어려운’ 팀에서 일하기
      • 디자인 문서
    • 일상적인 논의
      • 메일링 리스트
      • 온라인 채팅
      • 이슈 추적기 사용하기
    • 엔지니어링의 일부로서의 의사소통
      • 코드 주석
      • 소스 코드에 자신의 이름 넣기(‘작성자 태그’ 이슈)
      • 모든 커밋에 대해 코드 리뷰 요구하기
      • 실제 테스트와 릴리즈 프로세스 수립하기
    • 결국은 코드에 대한 것이다
  3. 모든 배에는 선장이 필요하다
    • 공백에 대한 본질적인 혐오감
    • @비난받는 관리자
      • 리더‘는 새로운 ‘관리자‘이다

        전통적인 관리자들은 일을 어떻게 할 것인지를 고민하는 반면, 리더는 무엇을 할 것이지를 고민한다. 그리고 그 일을 해낼 방법을 찾기 위해 그들의 팀을 신뢰한다.

      • 유일하게 무서운 것은… 글쎄, 모든것
    • 헌신적인 리더

      관리자의 가장 중요한 역할이 가정의 건강과 행복을 추가하는 집사처럼 팀에 봉사하는 것이며, 우리가 ‘헌신적인 리더십‘이라고 부르는 덕목을 적극 수용하는 것이다. 헌신적인 리더로서 당신은 겸손과 존중, 그리고 신뢰가 공존하는 분위기 형성에 주력해야 한다. 이는 엔지니어 스스로는 버릴 수 없는 관료주의적 장애물을 제거하고, 팀이 합의를 이끌어 내는 데 도움을 주거나, 심지어는 늦은 시간까지 일하는 팀을 위해 저녁을 사는 것을의미할 수도 있다. 헌신적인 리더는 팀의 균열을 방지할 뿐 아니라 필요한 때 조언을 하기도 하지만, 자신의 손을 더럽히는 것을 두려워하지도 않는다. 헌신적인 리더가 수행하는 유일한 관리한 팀의 기술적, 사회적 건전함을 관리하는 것이다.

    • 안티패턴
      • 안티패턴: 무능력한 구성원의 고용
      • 안티패턴: 저성과자들에 대한 무시
      • 안티패턴: 사람사이의 이슈에 대한 무시
      • 안티패턴: 모든 이들의 친구되기
      • 안티패턴: 고용 기준과 타협하기
      • 안티패턴: 팀을 아이 취급하기
    • 리더십 패턴
      • 자존심을 버려라
      • 선사가 되어라

        당신에게 조언을 구하는 엔지니어는 당신이 그의 문제를 해결해 주는 것을 원하는 게 아니라 그가 문제를 해결할 수 있도록 도와주기를 원하는 것이며, 그가 원하는 도움을 주는 가장 쉬운 방법은 그에게 질문을 하는 것이다.

      • 촉매가 되어라
      • 스승이자 멘토가 되어라
      • 명확한 목표를 설정하라
      • 정직하라
      • 행복을 관찰하라
      • 그 외의 팁과 요령

        최고의 엔지니어들을 (그들의 바람과는 반대로) 관리자 역할로 밀어 넣는 회사들을 볼 때마다 우리 필자들은 항상 놀라곤 한다. 대부분은 그 결과로, 팀은 유능한 엔지니어를 잃는 대신에 수준 이하의 관리자를 얻게 된다.

        새로운 물결을 일으킬 때를 알아야 한다.

        기다린다는 것은 프로세스에 필연적으로 발생할 엄청난 피해를 잠시 연기시키는 것 빡에 되지 않는다. 따라서 행동해야 하며, 그것도 빨리 행동해야 한다.

    • 사람은 식물과 같다

      서로 다른 엔지니어를 키우기 위해서는 서로 다른 것들이 필요하다.

      • 내적 동기부여와 외적 동기부여
    • 최종 의견
  4. 유해한 사람들과 협업하기
    • ‘유해함’의 정의
    • 팀 강화하기
    • 위협 감지하기
      • 다른 사람의 시간을 존중하지 않기
      • 자존심
      • 과도한 특권의식
      • 어수룩한 또는 혼란스러운 커뮤니케이션
      • 피해망상
      • 완벽주의
    • 유해함 무찌르기
      • 완벽주의자의 에너지를 다른 곳으로 돌리기
      • 에너지를 좀먹는 녀석들한테는 먹이를 주면 안된다
      • 너무 감성적이 되지 말 것
      • 분노 속에 담긴 진실을 주목하라
      • 친절함으로 괴물들을 물리쳐라
      • 포기할 때를 알아야 한다
      • 멀리 내다보라
    • 최종 의견

      어리석음으로 충분히 설명될 수 있는 일을 악의의 탓으로 돌리지 마라 – Robert J. Hanlon

  5. 조직 관리 기술
    • 장점과 단점, 그리고 전략
    • 이상: 팀이 회사 내에서 어떤 기능을 해야 하는가?
      • 이상적인 관리자와 함께하는 삶

        만일 당신의 관리자가 HRT 원칙을 이해하는 헌신적인 리더이며 당신의 성공을 돕는 것에 관심이 있는 사람이라면 몇 가지 간단한 일을 통해 당신의 관리자가 자신의 역할을 쉽게 수행할 수 있도록 도울 수 있으며, 그 덕분에 당신 자신이 더욱 생산적이고 가치있는 팀 구성원이 될 수 있다. 일을 처리할 때 더 많은 책임감을 갖자. 위험을 감수하고 실패를 두려워하지 말자. 성인으로서 행동하자. 당신이 확신하지 못하는 일에 대해서는 질문을 하자.

    • 현실: 당신의 주변 상황이 당신의 성공에 방해가 될 때

      행복한 가정은 대부분 비슷하다. 모든 불행한 가정은 각자 나름대로 불행하다. – Leo Tolstoy, Anna Karenina

      • 좋지 않은 관리자와 함께하는 삶
      • 조직 내에서 정치를 일삼는 사람들
      • 좋지 않은 조직
    • 조직 관리하기
      • 권한보다는 용서를 구하는 것이 쉽다
      • 길을 얻을 수 없다면 길을 만들자
      • 관리 역량 향상을 위해 학습하자
      • 행운과 호의의 경제학
      • 안전한 위치까지 승진하기
      • 힘 있는 친구를 찾을 것
      • 바쁜 임원에게 부탁할 때는 메일을 사용하자
    • 두 번째 계획: 퇴사하기
      • 옳은 일을 하고 해고될 때를 기다리자
    • 전혀 희망이 없는 것은 아니다
  6. 사용자도 사람이다
    • 대중적 인지도 관리하기
      • 첫 인상에 주목하라
      • 적게 약속하고 더 많이 주자
      • 업계의 분석가들을 존중하며 일하자
      • 당신의 소프트웨어의 사용성은 어느 정도인가?
      • 대상을 선택하라
      • 진입 장벽에 대해 고민하자
      • 사용자가 아니라 사용성을 측정하자
      • 속도의 문제
      • 모든 것을 제공하려고 하지 말자
      • 게을러지지 말자
      • 복잡함을 숨기자
    • 사용자와의 관계 관리하기

      사용자들은 무엇보다도 자신들의 말을 들어주기를 원한다

      • 잘난 체하지 말자
      • 인내심을 갖자
      • 신뢰와 즐거움을 만들자
      • 사용자를 기억하자

        마케팅: 사람들이 당신의 소프트웨어를 어떻게 인식하고 있는지 알고 있으며, 사람들이 인지할 수 있도록 개입 여부를 결정한다.

        사용성: 소프트웨어는 사용하기 쉽고, 빠르고, 친숙하며, 접근이 쉬워야 한다. 그렇지못하면 사용자들은 떠나게 될 것이다.

        고객 서비스: 장기 고객들과의 적극적인 교류는 소프트웨어의 혁신과 사용자 확보에 영향을 끼친다.

Google Breakpad를 이용하여 Crash Dump 떨어뜨리기

한 사이트에서 개발한 프로그램이 가끔 이유없이 죽고 있었다.

다른 사이트는 그런 일이 없는데 그 사이트에서만 발생하고 있는 일이었다.

보통은 로그를 이용하여 원인을 파악하는데,

그 사이트는 로그가 너무 많이 쌓여서 로그 유지 기간이 짧았고,

반면 프로그램이 다운되는 일은 어쩌다 (한, 두 달에 한 번정도) 발생되는 일이라서 골치가 아팠는데

이 기회에 Breakpad를 적용해서 해결해 보려고 마음 먹었다.

1. Breakpad 소개

Google breakpad home page : https://code.google.com/p/google-breakpad/

Google Chrome처럼, 여러 플랫폼을 지원하는 프로그램을 위한 크래시 덤프를 다루기 위한 툴이다.

Win32 개발자들이 접하는 minidump나, *nix 개발자들이 접하는 coredump를 breakpad 포맷(이라기보단 함수 맵)으로 변경하고, 이를 이용해서 플랫폼이 바뀌어도 같은 형태의 스택 트레이스(stack trace)를 볼 수 있게 해주는 툴이다.

좀 더 세부적으로 보면 다음과 같은 부분으로 되어 있다.

(개별 사용자 용) 크래시가 발생했을 때, 이를 breakpad 에서 사용하는 포맷으로 덤프를 남겨주는 부분: in-process 덤프만 있는 게 아니라, 다른 프로세스에서 dump를 남기는 방식(out-of-process dump)도 지원한다
(Build-System 용) 디버그 정보를 읽어서 breakpad 내부 형식으로 바꾸는 부분 : Win32 pdb 나 –g 옵션을 넣고 빌드한 *nix 바이너리에서 심볼 데이터를 뽑아낸다
(Crash Collector 용) 1에서 나온 정보를 가지고 2를 이용하여 스택 트레이스를 뽑아내는 부분

사실 2, 3 부분은 Windows 환경에서만 프로그래밍 한다면 그다지 중요하지 않다. 어차피 breakpad 도 덤프 자체는 minidump를 쓰고 있고, breakpad 소개의 Build / User / CrashCollector system 다이어그램에 나온 과정도, 디버그 정보가 애초에 분리되어 빌드 되는 환경(/Z7 같은 걸 쓰면 모르겠지만)에선 그다지 더 편해질 건 없다.

그렇지만 1에서 Windows named-pipe를 써서, 크래시가 발생한 프로세스가 아니라, 안전하게 동작 중인 프로세스에서 덤프를 남길 수 있다는 점(Out-of-process 덤프), 그리고 이 덤프 남기는 부분의 코드에서 제공하는 callback 지점들이 적당해서, 이걸 이용해서 간단하게(!) 실제 배치된 시스템의 덤프를 중앙의 서버로 모으는 작업을 간편하게 작성할 수 있었다.

일단 out-of-process로 덤프를 남길 수 있기에, 크래시가 발생한 바이너리에서 할 수 없는 일들 – 메모리 신규 할당, heap 메모리 참조, 기타 등등 – 을 맘대로 해도 되기 때문에 웹 서버나 다른 서버로 덤프를 보내는 일이 쉬워진다.

– rein’s world

out-of-process

breakpad 의 가장 큰 특징은 out-of-process 를 지원하는 것이다. 크래시를 처리하는 함수에서 앞에서 말한 다양한 기능을 추가한다면 제대로 동작하지 않을 수도 있다. 간단한 예로, 사용자에게 의견을 받는 윈도우를 띄운다고 할 때 메인 스레드의 메시지 루프가 깨지면 윈도우 자체를 볼 수 없게 된다.

크래시가 발생한 프로세스 밖(out-of-process)에서 처리하면 이와 같은 문제를 줄일 수 있다. 그래서 크래시 발생을 처리하기 위해 보다 많은 것을 제공할 수 있다. 물론 in-process 도 지원하기 때문에 필요에 맞게 골라 쓰면 된다.

크로스 플랫폼

멀티플랫폼 지원을 고려한다면 breakpad 는 좋은 선택이 될 수 있다. breakpad 를 사용한다면 크로스 플랫폼에 대한 고민을 줄여줄 수 있다.

– 야드버즈의 개발 로그

breakpad를 현재 사용하고 있는 대표적인 프로그램은 Chrome Browser, Firefox Browser, Picasa, Google Earth 등이다.

2. Breakpad 받기

Breakpad는 SVN을 이용하여 내려 받을 수 있다.

SVN은 서버까지 필요 없으므로 Windows용 tortoiseSVN을 설치하면 된다.

tortoiseSVN을 설치했으면 다음과 같이 내려 받는다.

1) Command 창을 열어 먼저 설치하고 싶은 폴더로 이동한뒤, 다음과 같이 실행한다.

svn checkout http://google-breakpad.googlecode.com/svn/trunk/ google-breakpad-read-only

그러면 google-breakpad-read-only 폴더가 생기면서 그 폴더로 checkout을 하고, 소스를 내려 받는다.

2) 탐색기에서 설치하고 싶은 폴더를 만든 뒤, 마우스 오른쪽 버튼을 눌러 로 ‘SVN Checkout’을 선택한다.

URL of Repository 항목에 ‘http://google-breakpad.googlecode.com/svn/trunk’ 를 넣고  OK를 누른다.

그러면 그 폴더로 checkout을 하고, 소스를 내려 받는다.

3. Breakpad build 하기

  1. 1. python 2.x버전 설치: breakpad는 gyp를 이용하여 빌드 시스템을 생성한다. gyp를 사용하기 위해서는 python 2.x버전이 필요하다. gyp가 아직 python 3.x버전과는 호환성 문제가 있는 것 같다. (gyp 자체 문제 + gyp 설정 파일문제가 복합적인듯 하다.)
  2. gyp 소스 가져오기: breakpad 소스 내에 gyp가 내장되어 있지만, 내장 gyp는 버전관리가 안되어 있는듯 하다. gyp 최신 버전이 적용이 안되어 있다. 현재 작성 시간 기준 gyp 최신 소스에는 Visual studio 2012까지 빌드 시스템을 생성할 수 있도록 되어있다. gyp 최신버전을 사용하기 위해서 gyp를 google 저장소에서 checkout하면 된다.
  3. gyp로 빌드 시스템 생성: src\client\windows 폴더에서 ..\..\tools\gyp\gyp.bat breakpad_client.gyp 를 실행하면 솔루션 파일과 프로젝트 파일이 생성되는 것을 볼 수 있다.
  4. Visual Studio로 빌드: 만들어진 솔루션 파일을 열어 그 안에 있는 build_all 프로젝트를 빌드하면 된다.

4. Breakpad test

테스트용 프로그램(crash_generation_app 프로젝트)이 솔루션에 포함돼 있으므로 따로 만들 필요는 없다. 이 테스트 프로그램을 이용하면 in-process 뿐만 아니라 out-of-process 미니덤프도 만들어 볼 수 있다. 여기에서는 out-of-process 미니덤프를 만드는 방법을 소개하겠다.

프로그램을 실행하기에 앞서 C:\Dumps 폴더를 만들어야 한다. 이 폴더를 만들지 않으면 미니덤프를 저장하다가 실패한다.

준비가 다 됐다면 프로그램을 실행해 보자. 제대로 된 out-of-process 를 테스트하기 위해서는 프로세스를 두 개 띄워야 한다. 두 번째 프로세스를 띄울 때 서버를 실행할 수 없다는 에러 메시지가 뜨지만 무시해도 좋다. 그런 다음 서버가 실행되지 않는 프로세스에서 Client -> Deref Zero 메뉴를 선택해 강제로 크래시를 발생시키면 C:\Dumps 폴더에 미니덤프 파일이 생성되는 것을 볼 수 있다.

– 야드버즈의 개발 로그

참고자료

Breakpad 로 CrashReporter 만들기 – rein’s world

원도우즈 환경에서 breakpad 사용하기 – 야드버즈의 개발 로그

[정보] 소프트웨어, 잉여와 공포 – 박상민

웹 서핑중 좋은 글을 발견하여 소개한다.

소프트웨어, 잉여와 공포         by 박상민

글 중에 인상적인 구절을 옮기면,

잉여와 해커 정신이 실리콘밸리의 근본이라면, 한국의 근본 정서는 무엇일까 생각해 본다. 나는 “공포(fear)” 라고 생각한다. 공부를 못하면 루저가 된다는 공포, 숙제를 안해가면 맞을거라는 공포, 소프트웨어때문에 삼성이 무너진다는 공포, 6/25 시절로 다시 돌아갈지도 모른다는 공포.

우리는 개인, 집단 모두 공포에서 벗어나려 치열하게 살고있다. 뛰어난 해킹 잠재력을 가진 얼마나 많은 사람들이 공무원과 교사 시험을 준비하고 있을까? 이건희 회장이 주기적으로 이야기하는 “삼성 최대의 위기”는 정말 언제로 오는 걸까? (SW는 정말로 위기라고 생각한다). 한국형 안드로이드라는 “성스로운 똥” 아이디어를 낸 공무원들은 한국 SW의 미래가 얼마나 두려웠을까?

결론적으로 공포가 지배하는 문화에서 잉여와 해커의 정신은 살아 날 수가 없다. 최근 얼마나 많은 수의 한국 해커들이 국제 오픈소스 프로젝트 (예: Apache) 에 참여하고 있는가 세어본적이 있다. 정말 몇안되는 사람들 뿐이었다.

생각해보면 나도 그런 것 같다, 공포라는 것에 사로잡힌…

과연 우리 사회에서 ‘잉여’라는 게 얼마나 존재할 수 있는지 궁금하다.


아래는 댓글중 발췌하였다.

리누스 토발즈가 한 이야긴데, survivalsocial orderentertainment 자기는 이렇게 세 단계에 사람이 머물러 있다고 생각하고, 오픈소스 운동은 entertainment 에 속하는 사람들이 한다더라고요…

우리나란 social order 상태에 머물러 있는것 같은데, 보수언론은 공포를 자극해서 자꾸 survival쪽으로 끌어내리려 하는것 같습니다. 대기업들은 social order에 머물러 있게 하고요. 사실, 경제적 여건은 entertainment 쪽으로 이동을 해도 될만큼 잘 사는것 같거든요..

말씀하신대로 미국도 예전에 survival을 너무 강조하다보니 오히려 그 반작용(히피 문화라던가요) 에 의해 entertainment 으로 이동한것 아닌가 싶기도 하고요. 암튼 이런것도 공부해 보면 재밌을것 같습니다.

아래는 같이 읽으면 좋은 글들…

빠른 base64 encoding/decoding 구현 by C++

이번에 필요에 의해 base64 encoding/decoding을 구현해야 할 일이 있었다.

사용하던 라이브러리 (ACE/POCO)에 base64 기능이 있었지만, 라이브러리 전환도 고려해야해서 직접 구현하기로 했다.

이런저런 구현 소스들을 찾아 테스트해본 결과는 다음 코드가 가장 속도가 빨랐다.

static const char MimeBase64[] = {
‘A’, ‘B’, ‘C’, ‘D’, ‘E’, ‘F’, ‘G’, ‘H’,
‘I’, ‘J’, ‘K’, ‘L’, ‘M’, ‘N’, ‘O’, ‘P’,
‘Q’, ‘R’, ‘S’, ‘T’, ‘U’, ‘V’, ‘W’, ‘X’,
‘Y’, ‘Z’, ‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’,
‘g’, ‘h’, ‘i’, ‘j’, ‘k’, ‘l’, ‘m’, ‘n’,
‘o’, ‘p’, ‘q’, ‘r’, ‘s’, ‘t’, ‘u’, ‘v’,
‘w’, ‘x’, ‘y’, ‘z’, ‘0’, ‘1’, ‘2’, ‘3’,
‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’, ‘+’, ‘/’
};

static int DecodeMimeBase64[256] = {
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,62,-1,-1,-1,63,
52,53,54,55,56,57,58,59,60,61,-1,-1,-1,-1,-1,-1,
-1, 0, 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,-1,-1,-1,-1,-1,
-1,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,
41,42,43,44,45,46,47,48,49,50,51,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,
-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1
};

typedef union {
struct {
#ifdef LITTLE_ENDIAN
unsigned char c1, c2, c3;
#else
unsigned char c3, c2, c1;
#endif
};
struct {
#ifdef LITTLE_ENDIAN
unsigned int e1:6, e2:6, e3:6, e4:6;
#else
unsigned int e4:6, e3:6, e2:6, e1:6;
#endif
};
} BF;

int HUMRedisObject::_base64enc(char *src, int src_size, char **result)
{
int i, j = 0;
BF temp;

int size = (4 * (src_size / 3)) + (src_size % 3 ? 4 : 0) + 1;
(*result) = new char[size];

for (i = 0 ; i < src_size ; i = i+3, j = j+4)
{
temp.c3 = src[i];
if ((i+1) > src_size) temp.c2 = 0;
else temp.c2 = src[i+1];
if ((i+2) > src_size) temp.c1 = 0;
else temp.c1 = src[i+2];

(*result)[j] = MimeBase64[temp.e4];
(*result)[j+1] = MimeBase64[temp.e3];
(*result)[j+2] = MimeBase64[temp.e2];
(*result)[j+3] = MimeBase64[temp.e1];

if ((i+2) > src_size) (*result)[j+2] = ‘=’;
if ((i+3) > src_size) (*result)[j+3] = ‘=’;
}
(*result)[size-1] = ”;
return size;
}

void HUMRedisObject::_base64dec(char *src, char *result, int *length)
{
int i, j = 0, src_length, blank = 0;
BF temp;

src_length = strlen(src);

for(i = 0 ; i < src_length ; i = i+4, j = j+3){
temp.e4 = DecodeMimeBase64[src[i]];
temp.e3 = DecodeMimeBase64[src[i+1]];
if(src[i+2] == ‘=’){
temp.e2 = 0;
blank++;
} else temp.e2 = DecodeMimeBase64[src[i+2]];
if(src[i+3] == ‘=’){
temp.e1 = 0;
blank++;
} else temp.e1 = DecodeMimeBase64[src[i+3]];

result[j] = temp.c3;
result[j+1] = temp.c2;
result[j+2] = temp.c1;
}
*length = j-blank;
}

원본은 다음과 같다.

빠른 base64 인코딩/디코딩 소스 – by ironiris (https://kldp.org/node/109436)

base64 인코딩/디코딩의 원리 – by I’m MK! (http://www.iamcorean.net/130)

원본과는 다르게 메모리 할당을 함수내에서 구현하고 그 결과를 돌려 주는 형태로 바꾸었다.

원래 할당을 한 구역내에서 해제하는 것을 원칙으로 하고 있으나,

이 경우는 편의성을 생각해서 위와 같이 구현하였다.

VC++에서 Precompiled header 정리

간간히 겪던 문제였었는데 이번 기회에 정리를 할 겸 포스트~!

1. Precompiled header 란?

compiling

Precompiled header에 대해 잘 정리된 글이 있어 잠시 가져와 본다.

C/C++ 언어에서 헤더 파일은 C 전처리기(preprocessor) 에 의해 자동적으로 소스 코드를 포함하게 된다. 그런데 일부 헤더 파일의 경우 방대한 크기의 소스 코드를 포함할 수 있고 (예를 들면 window.h), 이런 코드들을 매번 컴파일하면 컴파일 시간이 매우 길어지게 된다. 그래서 자주 바뀌지 않는 기본적인 라이브러리들의 경우에 컴파일 시간을 줄이고자 컴파일러가 사전에 헤더 파일들을 미리 컴파일 해 놓고 쓸 수 있게 하고 있다. 이렇게 컴파일 시간을 줄이기 위해 사전에 컴파일한 결과물이 VC의 경우 pch(precompiled header)라는 확장자 명으로 저장된다. 비주얼 스튜디어의 솔루션 폴더에 생기는 프로젝트명.pch 가 바로 그것이다. precompiled header 를 사용할 경우 precompiled header 로 지정한 헤더 파일 및 소스 코드는 컴파일시에 컴파일 되지 않고 pch의 결과물을 가져다 사용하게 되는 것이다. – soyoja님 블로그 (http://soyoja.com/372)

그렇다. 매번 컴파일이 오래 걸리는 것을 방지해주기 위하여 사용하는 것이다~!

물론 쓰면 편리한 기능인 것이고…

2. ‘c1083 cannot open precompiled header file’

Visual Studio 에서 가끔, 특히 Clean하고 난 이후에, 다음의 에러 메시지를 내고 컴파일이 안 되는 경우가 있다.
‘c1083 미리 컴파일된 헤더 파일을 열 수 없습니다.(c1083 cannot open precompiled header file)’
이 에러에 대해 msdn문서를 찾아보면, ‘결국 pch파일이 생성되지 않았다./pch파일이 존재하지 않는다.’에 결론이 도달하게 되고,
프로젝트 설정을 이것저것 건드리는 경우가 있다.
그러다보면 어떨 때는 간단히 해결이 되고,
어떨 때는 됐다, 안됐다 하고 아주 속이 터지는 경우가 있을 수 있는데,
이것 역시 잘 정리된 글이 있어 잠~시 가져와 본다.

종종 프로젝트 설정을 잘 못 만지면 pre compiled header 에 대한 오류를 볼 수 있습니다. (나만 그런가?)
그냥 pre compiled header 를 사용안함으로 해버리면 해결 됩니다.

그러나 이건 근본적인 해결책은 되지 못하겠지요. 또한 pre compiled header 를 사용하는 이점을 모두 버려야 하구요 🙂

pre compiled header 옵션이 몇가지가 있는데 모두 어떻게 동작하는지 정확히는 알지 못하겠습니다.
아무튼 난 기본 설정(미리 컴파일된 헤더 파일 사용)을 쓰고 싶단 말입니다 !!
자 ~ 원래 기본 설정(/Yu) 로 바꿔두고요..빌드를 해봅시다.
당연히 미리 컴파일된 헤더를 찾을수 없다고 떠들어 대는 컴파일러 메세지를 볼 수 있을것입니다.

이는 “미리 컴파일된 헤더” 로 지정된 stdafx.h 때문에 그렇습니다.
stdafx.cpp통해서 pch 파일을 생성하고, 나머지는 모두 만들어진 pch 를 통해서 컴파일이 됩니다.
어디선가 pch 파일을 무턱대고 복사해놓고, 빌드를 하면 일치하지 않는다는 등의 또 다른 컴파일러의 불만을 보게 되겠지요. 

stdafx.cpp 의 속성을 위와 같이 미리 컴파일된 헤더 생성(/Yc) 로 두면 문제는 해결됩니다.

– somma 님 블로그 (http://somma.egloos.com/2723641)

그렇다! Project 전체의 precompiled header 설정은 /Yu로, stdafx.cpp 파일의 precompiled header 설정은 /Yc로 하는 것이었다~!!

3. 쓸까? 말까?

내가 개발하고 있는 솔루션은 windwos, linux 모두 지원하도록 개발하고 있어서, visual studio에서는 그냥 켜고 사용하고 (그동안 별 문제가 없어서…), GCC에서는 ‘precompiled header’ 설정은 그냥 끄는 게 편하다고 생각했었다. 하지만 내용을 정리해놓고 보니 그래도 사용하는게 이래저래 장점이 많은 기능이다.

그.렇.다.면~!!!

precompiled header는 사용하는게 좋다~!

전화, 교환기, 컨택센터에 대한 소개글

얼마전 사내 발표에서 우리 사업부에 대한 소개를 할 기회가 생겼다.
그래서 발표준비하느라 정리했던 문서가 있는데
나름 정리가 잘된 것 같아 블로그에 올리기로 했다.
자료를 여기저기서 찾아 정리하느라 Reference를 모두 정리하지 못해 미안한 마음이…
(자료 발췌를 허락해 주신 xguru님께 다시 한번 감사를…)

전화,교환기,컨택센터0

전화,교환기,컨택센터1

전화,교환기,컨택센터2

전화,교환기,컨택센터3

전화,교환기,컨택센터4

전화,교환기,컨택센터5

전화,교환기,컨택센터6

전화,교환기,컨택센터7

전화,교환기,컨택센터8

전화,교환기,컨택센터9

전화,교환기,컨택센터10

Reference