Retrofit2 + RxJava proguard 설정하기

안녕하세요, 이음소시어스에서 안드로이드 앱 개발을 맡고 있는 김범준(준) 입니다.

최근 안드로이드 HTTP Client 라이브러리를 Volley에서 Retrofit2로 옮기는 과정에서 겪었던 ProGuard 관련 문제와 해결과정을 공유하려 합니다.

문제가 발생한 과정은 다음과 같습니다.

1. 새로운 feature에 쓰이는 API 모듈을 Retrofit2를 통해 구현하였습니다.

2. QA 까지 아무 문제가 없어서 구글 플레이에 업데이트 버전을 배포하였습니다.

3. 구글 플레이에서 앱을 다운로드하니 새로 만든 API 모듈에서 에러가 발생했습니다 ㅠㅠ

 

멀쩡하던 API가 배포하니 갑자기 안되다니.. (멘붕)

92_55169f19d5d14_1833

APK 파일을 다운로드해서 테스트하지 않고 Android Studio를 통한 빌드로만 테스트한 것이 문제였습니다.

ProGuard가 APK를 난독화하는 과정에서 문제가 생겼던 것이죠!

정확히 어떤 문제였는지 설명하기에 앞서 먼저 ProGuard와 저희가 사용한 Retrofit2 설정에 대해 간략하게 설명 드리겠습니다.

 

ProGuard 란?

ProGuard는 APK 빌드 과정에서 사용하지 않는 코드를 제거함으로써 크기를 최소화하고, 남은 코드를 난독화를 통해 리버스 엔지니어링을 어렵게하는 툴입니다.

ProGuard의 경우에는 class, method, field의 이름을 줄여 난독화 하게 되는데, 예를 들어 ‘name’이라는 String 타입의 멤버 변수를 ‘a’라고 뜻을 알 수 없는 짧은 단어로 치환하는 것이죠.

이 때, 난독화가 프로그램 작동에 영향을 줄 수 있는 부분들은 ‘-keep class ~’와 같은 방법으로 난독화에서 제외해줍니다.

 

Retrofit2 + RxJava

저희가 Retrofit2를 도입하면서 선택한 구조는 RxJava의 Observable 클래스와  GsonConverter를 이용합니다.

RxJava의 Observable를 통해 어떤 클래스로 response를 받을 것인지 지정해주면, GsonConverter를 통해 response를 JSON으로 파싱하여 지정한 클래스의 각 멤버 변수에 대입해줍니다.

API 콜을 부르면 콜백에 지정한 클래스의 객체를 돌려주니 바로 콜백에서 클래스 메소드를 사용할 수 있습니다. (넘나 편한것..)

Retrofit2 + RxJava의 자세한 설정이 궁금하신 분은 이 링크를 참고해주세요~

 

문제는 Model 클래스의 난독화에 있었다..

위에서 언급한 것처럼 response가 들어오게 되면 GsonConverter가 JSON으로 파싱해주고 Model 클래스의 멤버 변수에 대입해주는데, 이 때 ProGuard가 이 클래스의 멤버 변수를 난독화하면..! 대응 되는 이름의 멤버 변수가 없으니 문제가 생기는 것이죠.

실제로 난독화 된 클래스를 보면 다음과 같습니다. dex2jar 와 JD-GUI를 통해 디컴파일 하였습니다.

멤버 변수가 a, b, c 로 바뀐 것을 확인할 수 있습니다. 그렇다면 문제를 해결하기 위해선 ProGuard가 Model 클래스를 난독화하지 않도록 만들어주면 되겠죠~

 

ProGuard Configuration

Retrofit 홈페이지는 ProGuard를 사용할 시 어떤 설정을 적용해야 하는지 친절하게 써 놓았습니다.

스크린샷 2016-08-05 오후 3.16.38

이것만 적용하고 설정이 끝났다고 생각해서 문제가 생긴 것이죠 ㅠㅠ

keep model

위의 설정은 Retrofit2이 제대로 작동하기 위한 것이고 RxJava를 추가로 사용하기 때문에 따로 설정을 해줘야 합니다.

위과 같이 사용하는 Model 클래스를 난독화에서 제외해주시면 됩니다. 결과는 다음과 같습니다.

원래 멤버 변수 이름대로 있는 것을 확인할 수 있습니다! 앱 또한 정상 작동하였습니다.

Inner 클래스를 사용하는 경우 몇몇 변수가 난독화가 되는 일이 일어나기도 한다고 합니다. 이런 경우에는 다음과 같이 Inner 클래스도 난독화에서 제외하는 코드를 추가해줍니다.

해결!

 

후기

저에겐 안드로이드 앱 배포가 이번이 처음이었는데요, 예상치 못한 오류가 터져서 고생을 했지만 그래도 해결하고 나니 많이 배운 것 같아 뿌듯하네요 ㅎ

두서 없는 글 읽어주셔서 감사합니다~ (ㅡ)(__)

 

IM8(아임에잇) 오토스케일링 적용기

안녕하세요. 이음소시어스 개발팀 서버개발자 육승찬(루)입니다.

오늘은 이음소시어스의 핫한 서비스 “IM8(아임에잇)“의 오토스케일링 적용경험을 공유하려고 합니다. 먼저 오토스케일링에 대한 이야기를 하기 앞서서, 아임에잇이 어떤 서비스인지 간단하게 설명하고 시작하겠습니다.

IM8 (아임에잇) ?

직장인을 위한 프리미엄 소개팅 서비스

im8_1

IM8은 2013년 10월에 런칭되어 “까다로운 신원인증으로 높은 매칭 신뢰도를 주자”를 목표로 열심히 발전해 왔습니다. IM8의 8은 8개의 회원 타입(스마트커리어비주얼유니크글로벌밀리언패밀리액티브)을 의미합니다.

im8_2

현재 아임에잇의 모든 서버는 AWS를 통해서 운용하고 있습니다. 그럼 본격적으로 AWS x IM8 오토스케일링 적용기를 공유해보겠습니다. GOGO~

기존 서버

처음에는 IM8 API 서버를 EC2(t2.medium) 한대로 운영해왔습니다. 이후 트래픽의 증가에 따라 ELB에 EC2(t2.medium) 서버 2대를 붙여 운영하는 구조로  발전했습니다. 하지만 점점 더 트래픽이 증가하면서 피크 시간대에 서버가 터지는 일이 발생하기 시작했습니다. 그래서 현재 서버구조의 문제점을 정리하고 문제점을 개선하기로 결정했습니다.

서버 증설 방법

1. ELB에 서버를 더 붙이자 OR 서버의 스팩을 올리자 !

하루 두 번 푸시가 갈 때 아임에잇에 가장 접속자가 많이 몰립니다. 왜냐하면, 실제 매칭이 되는 시점에 사용자가 들어와서 상대방의 프로필을 확인하는 구조이기 때문입니다. 그래서 일반시간대에는 많은 서버가 필요 없습니다. 이 방법의 장점은 적은 시간 안에 문제를 해결할 수 있다는 점입니다. 하지만 비용적인 측면에서 굉장히 안 좋다고 판단했습니다. 접속자가 많지 않아도 항상 여러 대의 서버가 띄워져 있고 비용을 계속 지불하기 때문입니다.

2. AutoScaling (v)

접속자가 별로 없는 시간에는 최소한의 서버를 유지하고 피크 시간대에 여러 서버를 유지하는 방법입니다. 하루 두 번 피크가 있는 아임에잇에게 아주 좋은 방법이라고 생각합니다. (대부분 서비스에 좋지 않을까하는 생각이.. 😀) 평상시에는 최소한의 서버를 유지하기 때문에 비용적인 측면에서도 굉장히 유리했습니다. 그래서 이번 기회에 아임에잇에 AutoScaling을 적용해보기로 했습니다.

AutoScaling 준비하기

  • 결제서버 분리
  • 통일된 인스턴스 만들기
  • Scaling되는 서버를 항상 최신으로 유지하기
  • Scaling Rule 정하기
  • 서버를 띄우는 시간이 있기 때문에 푸시가 나가기전에 미리 띄우기 (Pre-warm)

1. 결제서버 분리

아임에잇은 모바일과 웹에서 PG서비스를 붙여서 결제할 수 있도록 제공하고 있습니다. 특정 PG는 요청 가능한 서버의 IP를 제한하고 있는 경우가 있어서 결제서버를 분리해야 했습니다. 기존 서버에서 사용하던 IP를 결제서버에 붙이고 내부에서만 통신 가능한 결제서버를 만들었습니다.

  • 기존 서버구조
기존 서버 구조

기존 서버 구조

  • 결제서버를 분리한 구조
새로운 서버 구조

새로운 서버 구조

2. 통일된 인스턴스 만들기

AWS에서 제공하고 있는 오토스케일링 기능은 미리 정의한 규칙에 따라서 인스턴스가 띄워지고 내려가는 형태로 동작합니다. 인스턴스는 AutoScalingGroup에 등록해놓은 AMI를 이용하여 띄우게 됩니다. 원래 사용하고 있던 서버 2대는 완전히 같은 인스턴스가 아니였습니다. 하나를 나중에 띄웠기 때문에 시스템 라이브러리 같은 경우 조금씩 버전이 달랐습니다. 그래서 이번 기회에 통일된 인스턴스를 만들고자 했고, 구조는 아래와 같습니다.

server

  • 시스템 라이브러리 설치 (ex. git)
  • API Rails App 설정
  • Puma 설정
  • Nginx 설정
  • Papertrail 설정 (로그 수집)

3. 서버를 항상 최신으로 유지하기

오토스케일링 되고있는 서버들은 항상 최신의 코드를 유지해야 하고 같은 응답을 줄 수 있어야 합니다. 아임에잇은 Git으로 소스코드를 관리하고 배포에는 Capistrano를 사용합니다. 지금까지는 서버 2대만을 최신으로 유지하면 됐기 때문에 아래의 순서로 배포를 해왔습니다.

  • Git fetching
  • whenever에 등록된 스케줄링 crontab에 등록
  • Puma Reload

오토스케일링을 적용하기 시작하면 서버가 딱 몇 대라고 가정할 수 없습니다. 그래서 모든 서버를 항상 최신으로 유지하기 위한 아래 두 가지 정리해봤습니다.

  • EC2 Instance가 시작되는 시점에 최신으로 만들기

EC2 설정 중에 “User Data“라는 부분이 있습니다. 인스턴스가 띄워지는 시점에 명령어를 실행시킬 수 있도록 할 수 있습니다. 여기서 소스코드를 최신상태로 유지하고 puma를 띄우는 등의 명령을 할 수 있습니다. 이렇게 하면 스케일링 돼서 실행되는 서버도 최신코드를 유지할 수 있게 됩니다. 쉽고 빠르게 모든 서버의 최신상태로 유지할 수 있지만 매 서버가 띄워질 때마다 Ruby 라이브러리 설치(bundle install)하기 때문에 서버가 띄워지고도 최신상태로 유지하는데 시간이 더 걸린다는 단점이 있습니다.

  • 최신의 AMI를 사용하기

이 방법은 미리 최신의 AMI를 항상 유지하고 서버가 띄워지는 부분에 대해서는 신경을 쓰지 않아도 됩니다. 코드를 한 번만 최신으로 유지하면 되고 라이브러리 설치 시간도 매우 줄일 수 있다는 장점이 있습니다. Ruby 라이브러리 중에 ELBAS라는 라이브러리가 있습니다. Capistrano와 연동되어 배포시 실행되고 있는 인스턴스를 최신으로 만들어주고, AMI까지 만들어주는 아주 좋은 녀석입니다… 이 라이브러리를 사용하면 빠르고 쉽게 항상 최신의 AMI를 유지할 수 있습니다.

4. Scaling Rule 정하기

처음에 AutoScalingGroup만 만들면 아무리 기다려도 서버는 스케일링 되지 않습니다… 그래서 어떤 규칙에 의해서 스케일링 할 건지 정해줘야 합니다. 먼저 AutoScalingGroup 설정을 보시면 “Instances“, “Desired“, “Min“, “Max“가 있습니다. Instances는 현재 서버의 개수, Min은 최소 서버 수, Max는 최대 서버 수를 의미합니다. Desired는 스케일링이 돼서 현재 몇 대를 희망하고 있는지를 의미합니다. Desired와 Instances의 수가 같으면 더는 서버를 띄우거나 내릴 필요가 없다는 의미입니다.

아임에잇에서는 서버를 띄우는 규칙 2지와 서버를 내리는 규칙 2가지를 사용하고 있습니다.

  • Add 1 instance (CPUCreditBalance < 9)

10분안에 CPUCreditBalance의 수치가 9 미만이라는 알람 두번이 울리면 인스턴스를 띄워라!

이 규칙은 CPUCreditBalance 수치에 따라서 동작하게 됩니다. 아임에잇 서버는 현재 t2계열의 인스턴스를 사용하고 있습니다. T2계열의 인스턴스에는  CPUCredit라는 개념이 존재합니다. 크레딧이 부족하면 CPU 연산 능력이 매우 떨어지기 때문에 새로운 서버 한 대를 띄우도록 하고 있습니다.

  • Add 2 instances (CPUUtilization >= 60)

2분안에 CPUUtilization의 수치가 60% 이상이라는 알람 두번이 울리면 인스턴스를 띄워라!

평소에는 CPU 사용률이 평온하다가 피크시간이 되면 갑자기 막 올라갑니다. 그래서 CPU사용률이 60% 이상이 되면 인스턴스 2대를 띄우도록 하고 있습니다. (피크시간이 아니면 올라갈 일이 거의 없기 때문)

  • Delete 1 instance (CPUUtilization < 25), Delete 2 instances (CPUUtilization < 15)

1분에 한번씩 CPU 사용률이 낮다는 알람 10번이 울리면 인스턴스를 내려라 !

피크시간이 지나고 나면 급격히 사용률이 떨어지기 때문에 인스턴스를 내리기 시작합니다. 하지만 인스턴스를 내리는 옵션을 상당히 까다롭습니다. 알람이 울리는 10분은 같지만 연속적으로 10번이 울려야 하기 때문입니다. 이유는 인스턴스를 내려도 되는 상황인지 확실시 하고 싶었기 때문입니다. 대게 인스턴스를 띄워서 생기는 문제보다 내리면서 생기게 되는 문제가 많기 때문입니다..

5. Pre-warm

아마 대부분의 프로그래머분들은 장애를 원하지 않을 것 입니다. 이음소시어스 개발팀도 장애가 나지않게 하기 위해서 노력을 하고 있습니다. 아임에잇 서비스의 경우 12:30, 19:00에 푸시를 보내고 있습니다. 실제로 푸시를 보내고 나서 오토스케일링 룰에 따라 서버를 띄우기 시작하면 대처가 좀 늦습니다. 갑자기 들어오는 트래픽을 버티지 못하고 아예 서버 한대가 죽어버리는 일도 있었습니다. 그래서 12:20, 18:50에 서버를 미리 띄워놓고 있습니다.  서버를 미리 띄우는 코드는 Python으로 작성했고 Crontab에서 실행되도록 하고 있습니다.

 

정리

이번 포스팅에서 아임에잇의 오토스케일링 적용 경험을 적어보았습니다. 사실 이번 포스팅을 작성하면서 너무 뻔한 글이 되지 않을까 걱정이 많았습니다. 이미 오토스케일링에 대한 글도 많고 참고할 부분도 많아서 잘 쓸 수 있을지 고민이 되었기 때문입니다. 그래서 더 자세히, 숨김없이 써보려고 노력했습니다.

오토스케일링을 적용하면서 가장 크게 얻은 두 가지는 비용절감과 불안감이 사라졌다는 것입니다. 기존 서버 비용 보다 45%의 비용을 절감할 수 있었습니다. 그리고 평소보다 가입자가 많은 날은 트래픽에 서버가 죽을까 하는 불안감이 있었습니다. 오토스케일링이 만병통치약은 아니지만 룰에 의해서 확장하고 수축하는 구조 덕분에 더 많은 트래픽을 커버할 수 있게 되어 불안감이 해소되었습니다.

마치며..

이번 오토스케일링을 사용하면서 ELBAS라는 라이브러리가 참 좋다고 느꼈습니다. 너무 쉽게 AMI를 최신으로 유지할 수 있는 방법을 제공해줬기 때문인데요. 그래서 이 라이브러리의 핵심적인 부분을 파이썬 코드로 작성해봤습니다 (파이썬을 오래 쓰다보니 재밌는건 파이썬으로 구현해보고 싶은 맘이 생기네요..)

 

 

이음(I-UM) on AWS

안녕하세요. 이음소시어스 개발팀 서버개발자 육승찬(루)입니다.

바야흐로… 2010년 4월 소셜데이팅 서비스 “이음”을 베타 런칭했습니다. 이음은 5년 동안 베이론 서버 제작을 포함해서 많은 변화를 추구해 왔습니다. 앞서서 이음 서비스를 간단하게 설명하고 시작하겠습니다.

이음은 대한민국 대표 소셜데이팅 서비스이며, 현재 회원 110만 명, 일 평균 1,000쌍 이상의 상호 OK가 진행되고 있습니다. 그리고 150만 이상의 누적 앱 다운로드를 기록하고 있습니다.

스크린샷 2015-07-03 오후 2.22.01

이 포스팅에서는 이음이 AWS를 어떻게 사용하고 있는지 설명하려고 합니다. 이음은 2012년 6월부터 AWS를 사용해 왔습니다. 현재 사용하고 있는 서비스를 간략히 나열해보면 아래와 같습니다.

  • EC2
  • ELB
  • RDS
  • S3
  • CloudFront
  • Route53
  • CloudWatch
  • SES
  • SNS

이렇게 나열해보고 나니 생각보다 많이 쓰고 있었네요! 그럼, 각 서비스를 어떻게 사용하고 있는지 설명해 드릴게요.

나와랏.. 스피드웨건 !

나와랏.. 스피드웨건 !

EC2 & EBS & ELB

이음에서는 다수의 EC2 인스턴스를 사용하고 있습니다. API서버, 웹서버, 어드민서버, 통계서버, 개발서버, Redis, SMS 등을 EC2에 올려놓고 사용하기 때문입니다. EC2는 순식간에 가상 서버를 만들 수 있는 장점이 있습니다. 예로 이전의 포스팅했던 깃랩 업데이트 당시에도 테스트하기 위해 가상서버를 만들어서 진행했습니다. AMI로 인스턴스를 만드니 빠르게 테스트 할 수 있었습니다.

대부분의 EC2의 Volume으로 EBS General Purposed SSD(gp2)를 사용하고 있습니다.

API 서버와 웹서버 같은 경우는 ELB를 앞단에 두고 있습니다. API 서버는 Auto-Scaling 기능을 사용하여 자동으로 scale-out 됩니다. 어드민, 통계, Redis 같은 경우는 아직 scale-out 할 필요성이 없어서 순수 EC2만을 사용하여 구동하고 있습니다.

여담으로 내부적으로 T2 타입 인스턴스를 좋아하고 많이 사용합니다. T2 타입 인스터스는 인스턴스 크기를 기반으로 정해진 고정 비율에 따라 지속해서 CPU 크레딧을 받고, 크레딧을 사용하여 기본 CPU 성능을 넘은 “성능 순간 확장”이 가능합니다. 간단한 테스트 서버가 필요할 경우 T2 타입의 인스턴스를 사용하면 좋습니다 ^^

RDS

이음에서는 MYSQL을 사용하고 있습니다. RDS에서 Mysql Engine을 선택하여 Master 1대, Read Replica 1대를 사용하고 있습니다. 그리고 Provisioned IOPS 옵션은 2000으로 사용하고 있습니다.

RDS 인스턴스는 종료하지 않고 인스턴스 타입을 변경할 수 있습니다. (물론 다운타임은 있습니다) 또한, Replica를 생성할 수 있는 기능도 있어서 관리 측면에서는 매우 좋습니다. RDS는 다른 서비스에 비해 상당히 비싼 편입니다. 하지만 관리적인 측면에서 매우 편하기 때문에 사용하고 있습니다.

최근에 RDS 오로라 엔진이 나왔습니다. 오레곤 리전에 인스턴스를 만들어서 사용해보고 있습니다. 이음 개발팀에서는 긍정적으로 보고 있고 빨리 도쿄리전에서 사용할 수 있었으면 하는 바람입니다.

S3

S3는 장점이 매우 많아 활용도가 무궁무진한 서비스입니다. 비용이 매우 저렴하고 오브젝트에 설정할 수 있는 옵션도 많습니다. Bucket에 로깅 기능도 있기 때문에 쉽고 편하게 사용할 수 있습니다. 그래서 이음에서 사용하는 모든 이미지는 S3에 저장하고 static 이미지들 또한 S3에 업로드하여 사용합니다. 또 이벤트 페이지가 필요할 때, 마크업을 작성하여 S3에 올려서 배포하여 사용하고 있습니다.

관리 측면에서 보면 S3는 정말 좋은 서비스입니다. 보통 static 서버를 따로 구성하게 되면 용량이 찼을 때, 증설 작업을 해줘야 합니다. 하지만 S3는 scale-out, 용량 증설에 고민할 필요가 없습니다. 다양한 서비스에 붙여서 사용할 수 있는 아주 매력적인 서비스입니다. (제가 정말 좋아해요..)

CloudFront

CloudFront는 S3에 업로드된 오브젝트를 배포할 때 사용합니다. 한국을 비롯한 세계 각 리전에 엣지가 있고 S3와 연동 쉬워서 매우 편리합니다. 이음에서는 프로필 이미지, 뱃지 이미지를 포함한 대부분 이미지를 signed URL을 사용하여 배포되고 있습니다.

이음은 AWS와 향후 1년간 CDN 서비스로 CloudFront만 사용하겠다는 Exclusivity 계약을 맺고 사용하고 있습니다. 위 계약을 맺게 되면 비용절감을 할 수 있습니다.

Route53

서비스 도메인 i-um.net, i-um.com의 DNS 서비스를 Route53로 옮겨서 사용하고 있습니다.  Route53는 비용도 저렴하고, 도메인 구입 비용도 비싸지 않습니다. 그리고 AWS의 다른 서비스들과 같이 사용하면 매우 편합니다. ELB, S3 웹호스팅, EIP, CloudFront와 연동이 매우 쉬우므로 좋습니다. 도메인 연결을 AWS Console에서 할 수 있기 때문이기도 하고요.

CloudWatch

ELB, EC2, EBS, RDS, SNS, Auto-Scaling Group의 상태를 모니터링합니다.. 이음에서는 CPU, DISK 등 다양한 기준을 두고 해당 조건에 맞으면 이메일, SMS로 알려줍니다. 그리고 특정 조건에 Auto-Scaling 되도록 연동하여 사용하고 있습니다.

CPU 올라간다~

CPU 올라간다~

SES

SES를 사용하면서 크게 문제 있었던 적은 없었으나, 이메일 반환율 때문에 메일이 온 적이 있습니다. 메일 전송시 반환비율이 높아지면 경고 메일이 옵니다. 반환율이 일정 비율을 넘기면 SES 서비스가 블럭 되므로 평소에 잘 관리해야 합니다.

SNS

이음에서 전송하는 모든 푸쉬는 SNS를 통해서 나갑니다. 여러 디바이스에 한 번에 보낼 수 있어서 매우 편리합니다. PUSH뿐만 아니라 CloudWatch에서 설정한 Alarm을 메일 또는 메세지로 보내주기도 합니다. SNS 내에 SMS를 보내주는 기능이 없어서 SMS 서버를 만들었습니다. 그리고 SNS에서 HTTP로 Call 하도록 구성했습니다.

맺음말

마지막으로 이음에서 사용하는 모든 서비스를 그림으로 그려봤습니다.

스크린샷 2015-07-03 오전 11.05.44

현재 개발팀은 RDS 오로라와 람다 서비스에 많은 관심을 기울이고 있습니다. 오로라는 서베이 후 괜찮다 싶으면 시범적으로 사용해볼 예정입니다. 람다의 경우 아직 Javascript, Java밖에 지원하지 않는 점이 아쉽습니다. AWS는 운영하면서 중간중간 변화를 주는 묘미가 있고 틈나는 대로 구성을 변경하고 있습니다. 앞으로도 더 좋은 서비스가 나오기를 바라면서 마칩니다.

 

PS. 항상 도움을 주는 AWS 팀에게 감사드립니다.

고통과 함께한 GITLAB(깃랩) 업데이트

안녕하세요. 이음소시어스 개발팀 서버개발자 육승찬(루)입니다.

저희 개발팀에서는 깃랩을 사용하고 있습니다. 이번에 깃랩 버전을 업데이트하게 되었고, 그 과정에서 겪은 경험을 공유하면 좋을 것 같아 “고통과 함께한 GITLAB(깃랩) 업데이트” 주제를 가지고 포스트를 작성하게 되었습니다.

GITLAB ?

Create, review and deploy code together

GITLAB(깃랩)은 설치형 버전관리 시스템입니다. 오픈소스로 제작되었고 꾸준히 업데이트되고 있습니다. 깃랩은 CE(Community Edition), EE(Enterprise Edtion), GitLab.com(On gitlab server) 세 가지 형태로 존재합니다.  저희 개발팀에서는 CE를 사용하고 있기 때문에 CE기준으로 설명드리겠습니다.

UPDATE ?

저희 개발팀에서는 2년 전 깃랩 6.1을 BITNAMI로 설치하여 사용해오고 있었습니다.  현재 깃랩 최신 버전이 7.9.2라는 것을 보고 업데이트가 필요하다고 생각이 들기도 했고, 개인적으로 써보고 싶어서 팀장님께 깃랩 업데이트를 제안 드렸습니다.

daum_net_20150321_204544

팀장님도 좋다고 하셔서 업데이트하기로 했습니다. (이때 고통이 뒤따를지 생각지도 못했습니다)

최근의 깃랩은 gitlabhqomnibus-gitlab으로 배포되고 있습니다. gitlabhq를 이용하여 설치하면 DB, REDIS 등 여러 소프트웨어를 직접 설치하고 깃랩에 연결하여 사용했었습니다. 하지만 omnibus-gitlab는 필요한 소프트웨어가 포함되어 패키지 형태로 설치됩니다. 또한, omnibus-gitlab는 기타설정이 매우 쉬우므로 관리하기가 좋습니다.

그래서 개발 서버에 설치된 깃랩 6.1을 omnibus-gitlab으로 업데이트하고자 하였습니다.

HOW ?

  • 제가 생각했던 첫 번째 (실패한)방법입니다.

스크린샷 2015-04-15 오후 3.07.04

먼저 깃랩 6.1에서 데이터를 백업하고 omnibus-gitlab을 설치하여 데이터를 복구하는 것이었습니다. 깃랩은 데이터 백업과 복구기능을 지원하기 때문에 다음 명령어로 데이터를 백업할 수 있습니다.

백업이 완료되면 tmp/bakups 안에 [timestamp]_gitlab_backup.tar 형태의 파일이 저장됩니다.  백업이 완료된 후 omnibus-gitlab을 설치합니다. 패키지 형태로 배포되고 있기 때문에 설치가 매우 쉽습니다. 자세한 설치방법은 깃랩 홈페이지에 있습니다.

omnibus-gitlab 설치가 완료되면 /var/opt/gitlab/backups 안에 위에서 백업한 파일을 옮기고 아래 복구 명령어를 실행했습니다.

그러면 아래와 같은 에러가 발생합니다.

그렇습니다.. 깃랩 백업&복구는 버전이 다르면 적용할 수 없습니다.

으아니

아니 이게 무슨소리요…

  • 두 번째 (실패한)방법입니다.

스크린샷 2015-04-15 오후 3.26.57

 

깃랩은 버전별로 업데이트하는 가이드를 제공하고 있습니다.  저는 gitlab 6.x or 7.x to 7.9(해당 링크는 계속해서 업데이트 되기 때문에 링크가 깨질 수 있습니다. 만약 링크에서 404에러가 난다면 여기로 접속해보세요.) 업데이트 가이드를 참고했습니다. 가이드에 나와 있는 방법대로 업데이트를 진행하고 있었는데 문제가 하나 발생했습니다. 현재 서버에 설치되어있는 gitlab-shell 프로젝트가 깃 프로젝트가 아니었습니다. 일단 gitlab-shell 프로젝트 관련 내용을 넘기고 나머지 커맨드를 입력하고 있었는데 데이터베이스 마이그레이션 부분에서 gitlab-shell 관련해서 에러가 났습니다.

daetul_mung

결국 BITNAMI로 설치 된 깃랩을 업데이트하는 것을 포기했습니다.

  • 세 번째 (성공한)방법입니다.

스크린샷 2015-04-15 오후 3.37.45

 

처음 생각했던 것보다 많이 복잡해졌습니다.. 하지만 희망을 가지고 (BITMANI)깃랩 6.1에서 데이터를 백업하고, 임시로 가상 인스턴스를 만들어서 깃랩을 6.1로 설치했습니다. 그리고 앞에서 백업한 파일을 복구하고 버전 업데이트를 진행했습니다. 버전 업데이트는 두 번째 방법에서 참고한 가이드를 똑같이 따라 했습니다. 업데이트는 순조롭게 진행되었고 데이터 백업까지 할수 있었습니다.

그리고 omnibus-gitlab 7.9.2를 설치했고, 깃랩 7.9.2에서 백업한 데이터를 복구하려 했습니다. 하지만 또 다시 에러가 발생했습니다.. 에러 내용은 데이터베이스 관련 에러입니다. 구글에 조금 찾아보니 깃랩을 ommibus-gitlab으로 마이그레이션하는 방법이 있었습니다. 내용을 요약하면 이렇습니다.

omnibus-gitlab에서는 PostgreSQL를 사용합니다. 만약 이전에 MySQL을 사용했다면 백업한 mysql query를 PostgreSQL query로 변경해야 됩니다. 변경 방법은 mysql-postgresql-converter 프로젝트를 이용해서 변경할 수 있습니다. 그래서 백업한 tar를 풀어서 database.sql을 PostgreSQL query로 변경하고 다시 압축한 후에 복구 명령어를 실행하면 복구가 됩니다. 이 방법을 자세하게 설명한 블로그가 여기있습니다. 참고하세요 ^^

CONCLUSION

일단 업데이트를 완료하고 한숨부터 나오더라구요..

유병재_SNL코리아_극한직업_모음_보기qd

왜 사람들이 그냥 GitHub, BitBucket 서비스를 사용하는지 이해가 가기도 했고요. 글을 정리하면서 몇 가지 팁을 적어보겠습니다.

  • 업데이트를 계획하신다면 omnibus-gitlab으로 업데이트하세요. omnibus-gitlab을 적용하려고 하지 않았다면 과정이 단순해질 수도 있었습니다. 하지만 앞으로 사용하고 관리하는 데 있어서 omnibus-gitlat이 더 좋다고 판단하여 업데이트했습니다.
  • 업데이트는 반드시 임시 가상서버에서 진행해보고 실제 서버에 적용하세요. 만약 제가 실 서버에서 바로 적용했다면 개발팀이 힘들었을 것 같습니다.
  • 끝까지 힘을 내요! (슈퍼파월) 
rsz_1iumstellar

우린 답을 찾을 것이다. 늘 그랬듯이..

 

Objective-C는 Swift의 친구가 될 수 있을까?

이제는 Swift도 꽤나 익숙하게 들리는 언어가 되었습니다. 저에게만 그런가요?
아마도 Swift를 배우고 있거나 실제로 사용하는 분들도 꽤 계실거로 생각됩니다. 저도 아직까지는 Objective-C가 훨씬 편하고 익숙하지만, 그래도 Swift를 아예 무시할 수는 없겠죠. 언제 애플이 Objective-C를 팽할지 모르니까요… 또르르..
Apple_Swift_Logo

Swift 로고
[출처 : Wikipedia – http://en.wikipedia.org/wiki/File:Apple_Swift_Logo.png ]

 

지난번 글에서는 너무 Swift를 부정적으로만 표현한 것 아닌가 싶기도 하고, 지금은 좀 더 Swift의 많은 면을 볼 수 있어서 지난번과는 조금은 다른 관점(?)으로 글을 쓸 것 같아요. 더 좋은 쪽으로!?

요즘에는 왠만하면 프로젝트 내에서 신규 클래스는 Swift로 작성하려고 노력중입니다. 이렇게 Objective-C랑 짬뽕혼합하여 사용하다보니, 그리 나쁘지만은 않더라구요. Objective-C의 장점과 Swift의 장점을 모두 취할 수 있으니까요.유후

Swift와 Objective-C를 한 프로젝트에서 함께 활용할 수 있는 방법은 애플에서 도큐먼트에 친절히 적어두었어요. 참고하세요.

하.지.만. 언제나 그렇듯 위험은 곳곳에 숨어있습니다. 두 언어의 차이점에서 비롯된 이점도 있지만 문제점도 분명히 드러납니다. 좋은점이 있으면 좋지 못한 점도 있기 마련. 좋은 점과 좋지 못한 점, 둘 중 뭐를 먼저 알고 싶으세요? 아마도 좋지 못한 점이 먼저 나오는게 좋을 것 같아요 ㅎㅎ 사실 좋지 않은 점이라기 보다는 그냥 제가 삽질한 것들이라… 후우… 그냥… 뭐랄까.. 넋두리… 네… 그렇습니다. 여러분들은 겪지 않으시길 바라면서! 하핳

제가 겪었던 빅삽질 들을 소개합니다!

b0036170_2231044

오예, 역시 프로그래밍은 삽질이 제맛이지

두 언어에는 서로 가지지 못한 것들이 존재합니다. 같은 듯 다른 듯 비슷한 기능들도 많은데요, 그 중 하나 카테고리(category)익스텐션(extension)이 되겠습니다.
Objective-C에서 저는 카테고리를 굉장히 즐겨쓰는 편입니다. 확장의 용이성과 간편함 때문인데요, 그에 대적할 기능이 스위프트에서는 익스텐션이라 말할 수 있겠습니다. 이에 관련된 에피소드를 소개합니다.
기존 프로젝트에서 저는 NSDictionary의 카테고리로 customMethod라는 메소드를 생성해 줬어요. 그런데 스위프트에서 코딩을 해주다가 저도모르게 NSDictionary의 익스텐션으로 customMethod라는 녀석을 만들어줬지 뭐예요? 서로 다른 이름의 기능이지만, 실제사용은 거의 똑같은 두 녀석. 결과는 어떻게 되었을까요?

13784314429c0c5517edf2134

결과는 카테고리의 승리였어요.

스크린샷 2015-03-11 오후 6.14.52

같은 이름으로 메소드를 호출해 주었을 때, 카테고리의 메소드가 호출이 되더라구요.  왜 그런가 곰곰이 찾아보고 고민해 봤는데, 아무래도 기능의 특성상 그런 것은 아닐까 조심스레 추측해 봅니다. 카테고리는 기존 클래스에 정의되어있는 메소드를 오버라이드 할 수 있습니다. 하지만 스위프트의 익스텐션은 그것이 불가능 하지요. 그렇기 때문에 런타임에서 유연하게 동작하는 특성과 오버라이딩이 가능한 특성 때문에 카테고리 메소드가 우위로 호출되는 것 같습니다. 그것도 모르고 저는 왜 자꾸 다른 결과물이 나오는지 갑갑해서 잠시 이성을 잃었답니다. 여튼, 이런 다르면서도 비슷한 기능들을 사용할 때, 주의해야겠어요.

또 한가지는 튜플(tuple)이었는데요, Objective-C에서는 튜플이라는 자료형이 존재하지 않지요. 다른 언어에도 있지만 Objective-C에서는 사용할 수 없던 녀석인데, Swift에서는 더 쉽게 사용할 수 있어서 몇몇 메소드에 적용을 해 봤어요. 그런데 그 메소드를 Objective-C 코드에서 사용해야 할 일이 생긴거예요. 하.지.만. Objective-C에서는 튜플 자료형을 사용하는 메소드에 접근할 수 없어요. 정확히 말하자면 튜플을 사용할 수 없어요(위의 애플 도큐먼트에서 확인 가능합니다). 그래서 Objective-C 메소드로 전달해줄 추가메소드를 작성해 주어야 했지요.

예를들어 위와같은 Swift 클래스에 두 클래스 함수가 구현되어 있을 때, Objective-C에서 commonMethod는 자유롭게 호출할 수 있지만, tupleMethod는 찾을수 없다며 에러를 뱉어냅니다.

스크린샷 2015-03-11 오후 6.29.58

하지만 주의할 점들만 빼면 좋은점들이 훨씬 많지요! 좀 더 유연하게 자신만의 스타일로 코딩을 할 수 있는 스위프트 덕분에 Objective-C에서 복잡하게 구현해야 했던 것들을 좀 더 쉽게 만들어 낼 수 있습니다. 예를들어 연산자 재정의나 제네릭 기능 같은 경우 Objective-C에서 어렵게 구현해야 했던 것들을 좀 더 간편한 방법으로 구현할 수 있는 길이 열리는데요, 이를 Objective-C에서 직접 접근하지 못하는 경우가 있다 하더라도, Swift에서 먼저 처리를 하고 특정 메소드를 통해 리턴해주는 방식으로 구현한다면 두 언어의 장점을 모두 흡수 할 수 있는 아주 멋진 프로젝트가 될 것입니다.

지난 번과 너무나 대조된 글이라서 좀 이상하지요? 예.. Swift는 계속 발전하고 있고, 우리가 만들어 가는 꼼수도 점점 늘어나고 있기 때문일 거예요 ㅎㅎ

결론
Objective-C는 Swift의 친구이자 멋진 동료가 될 수 있습니다! 100% Objective-C, 100% Swift 코드가 아닌 적절히 융합된, 서로의 장점을 가져다 쓸 수 있는 지금과 같은 체제를 계속 유지해 나갈 수 있으면 좋겠습니다. 애플이 Objective-C를 놓지 않고, Swift는 점점 발전시켜 주었으면 하는 바람입니다 🙂
 

Jo SeongGyu

2014/12/29

Apple_Swift_LogoSwift 로고
[출처 : Wikipedia – http://en.wikipedia.org/wiki/File:Apple_Swift_Logo.png ]

그렇습니다. Swift는 정말이지 뜻밖의 출현이었습니다.

무제

iOS 8과 더불어 새로운 기기가 발표될 거라고 생각했던 올 여름, 당황스럽게도 Swift 라는 아주 생소한 언어가 발표되었습니다. 힘차게 하강비행하는 듯한 칼새의 모습을 형상화한 로고가 나오는 순간, ‘저건 뭐지?’ 싶었는데, 새로운 언어라는 말에 저는 충격과 공포에 잠시 정신을 잃었던 것 같습니다. 이내 정신을 차렸지만 그 충격과 공포는 쉽사리 사라지지 않았습니다. ‘프로그래밍 언어라는 것이 뚝딱 만들어져 나올 수 없는데, 어떻게 저렇게 새로운 언어를 비밀리에 개발해서 내놓은거지?’ 등등 별별 생각이 다 들었어요. 어쨌거나 저쨌거나 언어에 종속될 수 밖에 없는 클라이언트 개발자는 눈물을 머금고 새로운 언어에 다가서 봤습니다.

첫 만남

Swift와의 첫만남은 ‘이게 뭐야’였어요. 스크립트 언어도 아닌 것이, 그렇다고 기존에 쓰던 Objective-C를 닮은 것도 아닌, 자바 비스무리한 새로운 변태같은 언어의 느낌. 딱 이런 느낌이었어요. 처음에는 당연히 Xcode 베타버전이라 크래쉬도 많이 나고, 불안정한 요소도 많았구요. 지금과는 문법도 조금씩 다른것들이 있었습니다. 여튼, 새로운 언어와의 첫만남은 한 마디로 ‘별로’ 였어요.

더 좋아진

Swift는 새로 출시된 언어답게 조금 더 발전된 기능들로 무장을 하고있습니다. 애플에서는 Swift의 특징을 Safe, Power, Modern으로 꼽았는데요, 새로나온 언어인 만큼 Modern함은 충분히 갖추고 있구요, Optional이라는 기능을 통해 Safe를 충족시키려 노력한 것을 볼 수 있습니다. 그러나 아직은 Power에 대한 의문은 남아있습니다. 기존 Objective-C 보다 성능면에서 대체적으로 떨어지기 때문인데요, 이 부분은 차후에 어떻게 개선되어 나갈지 지켜봐야 겠습니다.

그러나 더 발전해야할

물론 새로운 언어에서 좋아진 점들이 많지만, 아직은 부족한 부분들도 남아있습니다. 캡슐화가 아직 완벽히 지원되지 않고 있기 때문에 반(Half) 객체지향 언어라는 느낌이 강합니다. 애플에서는 앞으로 캡슐화를 할 수 있는 방안을 마련하도록 하겠다고 하였으나 이는 추후 지켜봐야 할 숙제라고 생각합니다. 또한 아직은 Swift를 완벽히 서포트 해주지 못하고 있는 Xcode도 발전에 조금 더 시간이 필요할 것 같습니다. 정식 배포버전이 베타버전에서 발전하여 문법도 조금씩 바뀌고, 불편한 점들을 개선한 것을 보면 위의 문제들은 시간이 해결해 줄 것이라고 생각합니다.

그래서..?

개인적으로 지극히 주관적인 입장으로 Swift는 2014년 말, 현 시점에서 아직까지 큰 프로젝트에 적용하기는 부담스럽다는 느낌입니다. Objective-C와 한 프로젝트 내에서 혼용하여 쓸 수 있다지만, 저는 그다지 그 연결에 흡족하지 못한 상태입니다. 그래서 현업 프로젝트에는 아직 적용하지 못하고 있어요. 그렇지만 iOS 또는 Mac OS 어플리케이션을 개발하는 사람이라면 꼭 배워두어야 할 것 같다는 생각입니다. 언젠가는 많은 발전을 통해 Swift가 대세가 될 날이 올 것 같기도 하거든요. 개인적으로는 생각보다 굉장히 파격적이고, 강력한 언어라고 생각합니다. 기본적으로 다른 언어 몇 가지를 익숙하게 다룰 줄 아는 프로그래머라면 Swift를 이해하는 첫 걸음은 Optional과 기존 Objective-C에서와는 조금 확장된 nil 이라는 개념이라고 생각하는데요, 여기(http://goo.gl/8VD1Rf)에 좋은 설명이 있어서 링크를 남겨둡니다. Optional과 nil 이라는 개념만 잘 이해해 두어도 Swift를 1/3은 정복했다고 생각합니다.

 

글을 끝까지 읽어주셔서 감사합니다. 아마 대부분 이 글을 읽으신 분들의 표정은 이러실거 같아요. 그래서 어쨌다고? 뭐라는겨?
스크린샷 2014-06-24 오후 6.51.15
사실 Swift의 실제 사용 후기에 대해 이것저것 말해보려고 했습니다만, 아마도 이정도로 충족하지 못하실거라 생각해요. 궁금한 점에 대해서 덧글 주시면 성심성의껏 답변드리도록 하겠습니다!

 

 

참고서적

Objective-C 개발자를 위한 Swift – 김근영 저
기존 Apple 어플리케이션 개발자들을 대상으로 썼지만, 다른 언어를 알고있는 프로그래머라면 충분히 이해하기 쉽게 설명된 Swift 기본 언어 책입니다.

만들면서 배우는 Swift: 스위프트로 시작하는 iOS 개발 – 야곰 저

기존 프로그래머가 아니더라도 아주 간단하게 Swift의 굵직한 특징들을 살펴볼 수 있고 간단한 iOS 앱을 따라 만들어 볼 수 있습니다.

 

[알림] 이 글은 이음소시어스와 그 개발팀의 견해와 일치하지 않을 수 있으며 지극히 주관적인 글임을 알립니다.

왜 개발가이드라인을 읽어봐야 할까요

오늘은 우리가 놓쳐온 사소한 것들에 대해 이야기 해보려합니다.

우리 개발자들은 급변하는 개발환경 속에서 살아가고 있습니다. 하루가 멀다하고 변화되는 지옥같은 개발환경에서 변화를 따라잡기란 참으로 힘겹기 그지없습니다. 항상 그렇듯 우리는 가장 중요하지만 가장 사소한 것들을 놓치며 살아갑니다. 내 가족의 소중함, 내 옆자리의 동료, 매일같이 맛있는 밥을 해주는 식당 아주머니의 손길…  우리가 개발을 하면서 수도 없이 들여다보는 개발문서, 그러나 너무나 사소해 보여서 그냥 지나쳐 버리는 개발문서의 핵심들…! 무엇이 있을까요?

헬게이트를 열어봅시다

제가 한 번 들여다 보겠습니다.

# 처음 만나는 프레임워크

‘안녕, 코코아 프레임워크! 반가워. 앞으로 잘해보자’

설렘 반 두려움 반으로 마주한 새로운 프레임워크. 그 친구에 대해 알아보기 위해서 가장 먼저 할 일은 아마도 개발도큐먼트를 읽어보는 일이겠지요? 마치 RC카를 조작하기 전에 설명서를 먼저 보는 것 처럼 말이죠. 그런데 우리는 RC카를 빨리 몰아보고 싶은 나머지 설명서의 앞, 뒤 다 잘라먹고 ‘차량 조종법’만 읽고 조종을 시작합니다. 그 상태로 막상 조작을 하다보니 좀 더 안전하게 운전하려면 어떻게 해야하는지, 연료는 무엇을 넣어줘야 좋은지, 부품은 무엇무엇으로 이루어져 있는지… 도무지 알지 못합니다. 하지만 일단 굴러가니까 좋아합니다. 이건 마치 도로교통법과 차량 기본 정비법은 까마득히 모르고 운전만 할 줄 아는 난폭운전자와 다를바가 없습니다. 개발세계에서 우리는 이런 난폭운전자가 될 수는 없습니다.

너무나 교과서 같은 이야기지만 개발문서는 그 어느 한 글자라도 생각없이 쓰여지지 않았다는 것을 한 번 생각해 보아야 합니다. 여러분께서 라이브러리를 개발하여 개발문서를 작성한다고 생각해 봅시다. 그 얼마나 귀찮고 힘든 일인지… 상상해 보셨나요? 그런데 그 개발문서에 시간들이고 공들여서 쓰잘데기 없는 이야기들을 쓴다구요? 당치 않습니다 ㅎㅎ 시간이 없다면 개발문서에 강조되어있는 헤드라인이라도 쭈욱 훑어보는 습관을 들이는 것은 어떨까요?

 

# 아… 이런 삽질이…!

위에 RC카를 예로 들었을 때, ‘조작법만 먼저 본다’고 예시를 들었던 것은 API Reference를 이야기 했던 것입니다. 도큐먼트에는 많은 목차들이 있지만 그 분량의 98% 이상은 API Reference겠죠? 하지만 제가 강조하고 싶은 것은 나머지 2%의 내용들입니다. 그 나머지 2%를 잘 숙지하지 않아서 생기는 일들은 너무나도 많아 다 이야기하기 어렵지만 몇 가지 사례를 제시해 보고자 합니다.

난 아직 2% 부족해

난 아직 2% 부족해

  • 어…? 뷰가 동작하지 않아!

개발자 모모씨는 아이폰 앱을 만들기 위해서 한창 코딩중입니다.

‘눈누난나~ 역시 난 천재야! 냐하하. 실행해볼까? 어..! 이게 왜 동작이 이상하지? 왜 먹통이 된거야!!’

애플의 코코아 프레임워크를 위한 코딩 가이드라인을 살펴보면 ‘메소드 이름 짓기‘라는 챕터가 있습니다. 그 곳을 살펴보면 Private Methods 라는 섹션이 있는데, 한 번 훑어보면

  • Names of most private methods in the Cocoa frameworks have an underscore prefix (for example, _fooData ) to mark them as private. From this fact follow two recommendations.
  • Don’t use the underscore character as a prefix for your private methods. Apple reserves this convention.

왜 제대로 된 동작을 하지 않았는지 감이 오시나요? 애플은 코코아 프레임워크에 숨겨진 Private Method 앞에 항상 언더바( _ )를 붙인다고 하는군요. 그런데 모모씨는 한 번도 이런 문서를 쳐다도 본 적이 없죠. 결국 모모씨는 3일 간의 삽질을 뒤로하고 자포자기하는 심정으로 주변 iOS 개발 고수님께 코드를 보여줍니다. 결론은요? 3분도 채 되지 않아 고쳤죠 🙂 저 메소드가 기존 프레임워크의 Private Method를 오버라이드 해 버린 것이었습니다.

p.s. 예를 들기 위하여 작성한 코드일 뿐, 실제 위의 코드로 오동작하지는 않습니다.

 

  • 아니… 왜 리젝된거지?

모모씨는 뼈저린 아픔을 뒤로하고 계속 앱 개발을 진행합니다. 물론, 가이드 문서를 다시 읽어봤을 턱이 없죠 ^^ 그래도 문제가 하나 해결되었으니 가뿐한 기분으로 계속 개발을 진행해 나갑니다. 모모씨가 개발하고 있는 앱은 추억의 똥피하기 게임. 하하 드디어 완성했습니다! 앱스토어에 올려야죠? 당당히 애플에 리뷰신청을 합니다. 드디어 리뷰 결과가 나왔군요!

추억의 똥피하기 게임

추억의 똥피하기 게임

당신의 앱은 부적절 컨텐츠로 반려되었습니다. 앱스토어 리뷰 가이드라인 16을 참고하세요.

아니 이게 무슨말이지? 모모씨는 너무나 황당합니다. 대체 뭐길래 이게 안된다는거야! 버그도 없고 동작도 잘 한단말야!

앱스토어 리뷰 가이드라인을 살펴보러 가봤습니다.

16. Objectionable content

16.1 Apps that present excessively objectionable or crude content will be rejected

16.2 Apps that are primarily designed to upset or disgust users will be rejected

하… 이번에도 가이드라인을 제대로 숙지하지 못해 빅삽질을 하게 되었군요. 애플은 일부 사용자들이라도 불쾌감을 느낄 수 있는 앱은 허용하지 않는다는군요. 프로젝트를 아예 폐기해야 할지도 모르는 상황입니다..! 결국 모모씨는 똥피하기의 컨셉을 버리고 빗방울 피하기 게임으로 컨셉 자체를 변경하게 됩니다.

아아... 가슴이 아파..

아아… 가슴이 아파..

  • 실제 예시를 몇가지 더 소개합니다
  1. Private Method 및 Private Variable을 자신도 모르는 사이에 재정의 해버려서 원인을 알아내는데 수 일이 걸린 경우
  2. 앱 내에 사진 업로드를 포함한 성 상담 익명 게시판을 만들었지만 가이드라인에 위배된다며 반려되어 서비스 기획부터 다시 해야 했던 경우
  3. IAP(In-App Purchase) 아이템의 성격이 애플의 가이드라인에 맞지 않아 과금 정책을 변경해야 했던 경우
  4. 앱스토어에 게재되는 스크린샷에 안드로이드 이미지가 일부 포함되어 있어서 반려된 경우
  5. 프레임워크에 맞게 재정의된 자료형을 사용하지 않아 아키텍쳐에 따라 상이한 결과 및 메모리 접근 오류가 발생하여 일일히 수정해 주어야 했던 경우(64bit 프로세서 전환 때 멘붕 겪으신 분들이 종종 있죠)
  6. 가이드라인에 제시된 프레임워크 구조를 모두 파악하지 못한 채 프로젝트를 진행하여 후임자가 구조를 모두 변경하여야 하는 경우
  7. 더 좋은 퍼포먼스를 지원할 수 있는 번들 리소스를 알지 못해 이미지 및 사운드 리소스를 모두 교체해야 하는 경우

 

등등등…

# 마치며

간단한 예시를 통해 개발문서의 가이드라인을 숙지하지 않아 발생하는 불상사를 알아봤습니다. 물론 위의 예는 아주 극히 일부분이고, 어쩌면 애플 프레임워크 위에만 해당하는 문제일 수 있습니다. 하지만, 실제 현업에서 지켜본 결과 저런 일들은 비일비재하게 일어나고 있으며 그 원인은 가장 기본을 놓쳤기 때문입니다. 개발에 걸리는 몇 십, 몇 백 시간을 저 가이드라인 하나를 놓쳐서 몽땅 말아먹는 경우도 생길 수 있다는 이야기입니다.

무시하기 쉬운 프레임워크(or 라이브러리) 제공자들의 한 마디 한 마디를 놓치지 말자구요~

다른 의견 또는 실제 사례가 있으면 덧글로 남겨주세요 🙂 기다릴게요~!

이상형 오디션 on AWS

2013년 11월 말… 새로운 프로젝트 개발을 시작하게 되었습니다. 이름하여 ‘본격대결, 이상형 오디션’ 입니다. 5개월여의 시간이 흘러 4월말 오픈 베타를 시작으로 5월 7일에 정식 런칭을 하게 되었습니다.

idealmate

 

현재 <안드로이드앱>을 스토어에서 만나볼 수 있습니다. 또한 이상형 오디션의 기획 이야기에 관심이 있으시다면 <게임과 네트워킹의 만남, 본격 대결 ‘이상형오디션’ 기획 이야기>를 읽어보시기를 추천합니다.

 

이 포스팅에서는 이상형 오디션이 인프라로 선택하고 사용한 AWS 서비스에 대해서 소개를 해보려고 합니다. 사용한 서비스를 간략히 나열해보면 아래와 같습니다.

  • EC2
  • RDS
  • S3
  • CloudFront
  • Route53
  • SNS
  • SQS

 

EC2

EC2는 AWS의 기본이 되는 서비스이며 가상 서버입니다. 사용자의 요청을 처리하는 API 서버와 서비스 운영, 통계 등을 담당하는 어드민 서버, 아직 AWS의 서비스로는 지원하지 않는 mongoDB 서버를 EC2 상에서 운영하고 있습니다. API 서버의 경우 ElasticLoadBalancer, AutoScaling 연동을 해서 자동으로 scale-out 이 되도록 해두었으나 아직 서비스 규모가 크지 않아서 효과를 보지는 못했네요.(얼른 트래픽이 많아져서 AutoScaling 이 빛을 발하는 모습을 보고 싶습니다.) MongoDB 의 경우 2014년 4월에 추가된 memory optimized instance인 r3 instance 를 사용하여 가격대비 높은 메모리를 쓰고 있으며 I/O 성능을 높이기 위해 Provisioned IOPS EBS volume을 붙여서 mongoDB 의 storage로 사용하고 있습니다. 참고로 r3 instance의 경우 HVM(Hardware Virtualization) AMI 만을 지원하므로 instance 생성시에 주의해야 합니다.

RDS

개발 시작 즈음부터 RDS에서 PostgreSQL을 사용할 수 있게 되었습니다. 이음에서 MySQL을 사용하면서 겪었던 문제들 중 하나가 table에 새로운 column을 추가할때 table에 lock이 걸려서 해당 table에 대한 요청을 처리할 수 없는 것이었습니다. PostgreSQL의 경우 column 추가가 매우 빨라서 기획이 바뀌거나 기능을 추가하는 경우에 좀 더 유연하게 대처할 수 있을 것으로 판단을 해서 선택하게 되었습니다. 또한 PostgreSQL의 안정성을 믿기로 했습니다. PostgreSQL 또한 Provisioned IOPS를 설정해서 안정적인 성능이 나오도록 했습니다. 역시나 아직까지 트래픽이 많지 않아 매우 안정적이며 여유롭습니다.

S3

S3는 다양하게 활용할 수 있는 매우 좋은 서비스입니다. 서비스를 위한 이미지와 사용자가 직접 업로드하는 프로필 사진 모두 S3에 업로드하여 서비스를 하고 있으며 각종 로그도 저장하고 있습니다. 또한 API 서버 배포시에 S3를 저장소로 사용하고 있습니다.

CloudFront

서비스용 이미지와 사용자 프로필의 경우 S3를 origin으로 하여 CloudFront를 통해 서비스를 하고 있습니다. CDN를 따로 계약할 필요없이 트래픽만큼만 비용을 지불하면 되니 정말 최고의 서비스가 아닌가 싶습니다. 참고로 사용자 프로필의 경우는 무분별한 크롤링을 방지하기 위해 signed URL을 사용하고 있습니다.

Route53

서비스용 도메인인 idealmate.kr의 DNS 서비스로 Route53을 사용하고 있습니다. 4월 10일부터 유료화된 DNSever 대신 사용하게 된 것이 그나마 이야깃거리네요. DNSever의 경우 standard DNS가 도메인당 월 천원(부가세 별도)이고 Route53의 경우 0.5달러여서 조금 더 저렴하기도 합니다.

SNS

모바일앱 Push nofitication을 사용하고 있습니다. 이상형 오디션의 경우 현재는 안드로이드앱만 출시된 상태지만 iOS앱도 출시를 위해 심사중입니다.(애플과의 밀당은 그만하고 싶네요ㅠㅠ)  SNS Push notification의 경우 APNS, GCM을 모두 지원하고 월 최초 백만건이 무료이며 추가 백만건당 0.5달러로 매우 저렴합니다. Push nofitication외에도 CloudWatch에서 설정한 alarm을 받는 용도로도 사용하고 있으며 alarm을 email과 http 연동을 통한 SMS로도 받고 있습니다.

SQS

이상형 오디션의 기능 중 랭킹 기능이 있습니다. 랭킹의 경우 사용자의 연승 갱신, 승리 추가, 채팅 요청, 채팅 수락 등의 액션에 따라서 랭킹 포인트가 증가해야 하는데 API 서버가 바로 랭킹 포인트를 갱신하기에는 부담스러운 작업입니다. 그래서 SQS를 사용해서 랭킹 포인트를 비동기로 증가시키도록 했습니다. 물론 SQS에 쌓인 job을 읽어서 처리하는 worker는 별도로 구현을 했습니다.

 

맺음말

이번 프로젝트를 하면서 AWS 서비스를 다양하게 사용해보았습니다. 이음에서는 아직 사용하지 않는 CloudFront, SNS Push notification을 사용하면서 비용도 절약하고 개발도 편하게 할 수 있었습니다. 프로젝트를 진행하는 동안 AWS도 RDS PostgreSQL 지원, EC2 r3 instance 추가, 가격 인하 등의 변화가 있었고 프로젝트에도 많은 도움이 되었습니다. 앞으로도 AWS가 더 발전하기를 바라면서 이만 마치겠습니다.

 

Xcode Bots 적용

테스트는 프로젝트에서 빠질수 없는 부분입니다. 테스트를 위해 변경된 앱을 설치해야 합니다. 설치 방법에는 여러가지가 있습니다. 여러가지 방법 중 Hey 프로젝트에서 적용한 방법을 공유하려고 합니다.

Hey?

Hey는 글로벌 버전 소셜데이팅 서비스입니다. 매일 오전 10시 3명의 이성의 프로필을 확인하고 서로 호감이 있으면 채팅을 할 수 있습니다.

Hey_Timeline Hey_Profile Hey_Chat

테스트 버전 배포

앱스토어에 업로드가 아니라 테스트를 위해 사내에 배포할때 어떤 방법을 사용하시나요?
이음에서는 두가지 방법을 이용했습니다.

  1. 디바이스를 연결하고 Xcode에서 직접 실행해서 앱를 설치해준다.
  2. Adhoc을 이용하여 사내 메일로 공유한다.

1번 방법은 작업중에 설치해줘야 할 경우 방해를 받게 됩니다. 그리고 테스트 디바이스로 등록되지 않은 디바이스때문에 Provisioning을 새로 생성해야 하는 문제가 발생합니다. Debug/Release로 빌드했는지 확인해야 합니다.

adhoc adhoc2 adhoc3

2번 방법은 1번 보다 더 효과적입니다. 한번 메일을 공유하면 앱을 설치해주느라 방해받지 않아도 됩니다. 하지만 불편한 배포과정이 남아 있습니다. Archive -> Distribute -> Adhoc 이런 방법으로 Adhoc버전으로 바이너리를 만듭니다. 그리고 생성된 ipa, plist 파일을 미리 입력한 url에 맞게 서버에 업로드합니다. 여기까지가 끝이지만…. 제대로 올렸는지 확인하기 위해 직접 다운로드해봐야 합니다.

두가지 방법 다 만족스럽지 못합니다.

그래서 새로운 기능인 Bots에 관심이 생겨서 직접 적용해 보았습니다.

Bots ?

Xcode BotsXcode5에 새로 추가된 기능입니다. Bots은 Xcode만을 위한 CI입니다. Bots은 간편하게 설정할 수 있습니다. XCTest를 사용할 경우 실제 등록된 디바이스에서 테스트를 실행하고 결과를 리포트해주는 기능도 있습니다.

bot_viewer-summary_2x 지속적인 통합을 위한 Bot

Bots 설치방법

http://meetkei.com/?p=3196

프로젝트 적용

HeyRelease Bot 생성

createHeyReleaseBot1

Hey Scheme 의 Bot을 생성합니다.

createHeyReleaseBot2

일일 빌드를 위해 매일 오후 5시에 빌드되도록 일정을 설정합니다.

createHeyReleaseBot3

빌드 성공시 프로젝트원 모두 메일을 받을 수 있도록 설정합니다.
실패시 개발자들만 메일을 받도록 설정합니다.
Create Bot 클릭하면 바로 통합이 진행됩니다.

HeyReleaseBuildError HeyReleaseBuildSuccess

통합 결과에 맞게 실패, 성공 메일을 받습니다.
디바이스에서 성공 메일을 확인한 후 제품 다운로드를 클릭하면 설치가 진행됩니다.

이제 통합을 매일 하는 일만 남았습니다!

문제 발생

통합메일에서 다운로드받은 앱을 실행해보니 서비스중인 서버(RealServer)로 접속하고 있었습니다. 테스트를 위해서 RealServer와 테스트 서버(TestServer) 모두 테스트가 가능해야 합니다. 이대로면 TestServer에서 테스트하기 위해서는 기존 방법을 이용해야 합니다.

RealServer로 접속하는 이유

Bot은 통합과정에서 Release build를 하게 됩니다. Build Settings 와 Server Host를 결정하는 Macro때문에 HeyRelease는 RealServer로만 접속됩니다.

HeyRelease_preprocessor

Build Settings > Preprocessor Macros 의 설정을 보면 Debug 에서 DEBUG=1 이 존재합니다. Release 에는 DEBUG가 존재하지 않습니다.

Header 에 적용한 Macro입니다. DEBUG가 존재하면 TestServer로 아니면 RealServer로 API_HOST가 정해집니다. 통합 중에는 Release 로 빌드가 되므로 API_HOST는 TestServer가 됩니다.

그럼 테스트 서버로 연결하려면?
Release에서도 DEBUG를 설정하면 됩니다.

그럼 RealServer, TestServer 를 모두 테스트하고 싶으면?
음…..

Hey에 적용한 방법

여러가지 방법을 생각해본 결과 제가 선택한 방법은 Target을 하나 더 생성하는 것입니다. HeyRelease는 RealServer로 HeyDebug는 TestServer로 접속하도록 하였습니다. Bot을  2개 생성해서 필요할때 둘중 하나를 배포합니다.

  1. 현재 Target을 복사해여 새로운 Target을 만듭니다.
  2. Preprocessor Macros 를 설정합니다.
  3. HeyDebug 이름으로 Bot을 생성합니다.

HeyDebug_preprocessor

createHeyDebugBot1 createHeyDebugBot2 createHeyDebugBot3

단점

  • build settings이 변경되면 두개의 Target 에 적용해야 함
  • 파일 생성 및 추가시 두개의 Target 을 지정해야 함

targets

언급한 단점이 있지만 Bots을 빠르게 적용할 수 있는 방법입니다. 개선된 방법은 조금 더 고려해 볼 예정입니다.

Bots Error

처음 Bots을 사용하면 많은 오류들과 만나게 됩니다. 몇가지 오류 해결 방법을 정리하였습니다.

Provisioning Profile 관련 오류

ProvisioningProfileError

iOS Team Provisioning Profile 을 사용하면 문제가 해결됩니다.

GeneralIdentity

그래도 해결되지 않는 경우 Target > General > Identity 에 위와 같이 Provisioning Profile 오류로 인한  Fix Issue버튼이 표시되는 경우가 있습니다. 이 버튼을 클릭하고 수정된 상태에서 통합을 진행해 보세요.

Reason: XCSCredentialSSHKey: private key is missing from the credential

http://stackoverflow.com/questions/5525436/xcode-could-not-find-a-valid-private-certificate-valid-key-pair-for-this-profile

xcode bots User interaction is not allowed.

  • Open the Keychain Access
  • Right click on the private key
  • Select “Get Info”
  • Select “Access Control” tab
  • Click “Allow all applications to access this item”
  • Click “Save Changes”
  • Enter your password

http://stackoverflow.com/questions/577750/running-xcodebuild-from-a-forked-terminal

Bots 오류 모음

  • Repositories that require an SSH key to access
  • Code Signing and Provisioning Profiles
  • Submodules
  • I made a mistake and now I can’t fix the repository from Xcode!

http://ikennd.ac/blog/2013/10/xcode-bots-common-problems-and-workarounds/

Profile

C언어로 API 서버 개발, 생각보다 나쁘지 않아요

지난 이음 API 개선에 관한 포스팅 <아파치 모듈로 개발된 API 서버, 이음 베이론을 소개합니다> 를 기억하시나요? 이 포스팅이 올라온 후 이음 개발팀 블로그에는 독자 여러분들의 뜨거운 관심(?)이 빗발쳤습니다. (그리고 아직까지 이 정도의 뜨거운 관심을 받은 포스트는 아직 나오지 않고 있습니다…) C언어로 API를 개발한다는 이야기에 흥미롭다는 반응도 있었지만 아무래도 걱정어린 시선이 많았습니다.

사실 말하자면 저도 루비, 파이썬을 비롯한 고급 언어들의 팬입니다. 그동안은 PHP나 Java (Spring) 같은 옛날 언어로 개발을 해왔지만, 처음 루비 온 레일즈를 접하고 그 깔끔함에 반해서 아직도 뭔가를 개발할 일이 있으면 최대한 레일즈를 쓰고 있구요. 과거 Spring을 쓰면서 직접 설정해줘야 했던 수많은 잡일들을 떠올리면서 ‘그동안 나는 뭘 한걸까…’ 하는 기분을 느꼈습니다. 그렇게 레일즈와 즐거운 시간을 보내던 중, 담당 프로젝트가 변경되면서 저는 C언어로 API 서버를 개발해야 하는 운명에 처하게 되었습니다.

으아니

이게 무슨 소리요! 내가… 내가 C 개발이라니!

처음에는 너무 막막했습니다. 레일즈를 써보신 분은 알겠지만, 기타 잡다한 부분은 프레임웍이 다 해주기 때문에 로직만을 작성하는 데에 익숙해져 있었거든요. 그런 저에게는 모든 것을 직접 해야만 하는 C언어 개발은 조금 불편하긴 했지만 결론적으로, 써보니까 생각보다 나쁘지 않았습니다. 다른 분들이 생각하시는 것처럼 유지보수 헬게이트도 아니구요. 무엇보다 성능이 모든 것을 용서합니다. 아무튼 자세한 이야기는 차차 해보기로 할게요.

Apache Portable Runtime

C 언어를 서버로 개발한다! 라고 하면 사람들은 포트 여는 것부터 response writing까지 모두 로우 레벨에서 처리해야 할 거라고 생각하지만, 다행히 그 정도까지는 아니었습니다. 이음의 API 서버 개발은 APR (Apache Portable Runtime) 이라는 큰 프레임웍 위에서 돌아가고 있습니다. 엄밀히 말하자면 프레임웍이라기보다는, 웹 서버인 아파치와 이음의 비지니스 로직을 연결해주는 라이브러리라고 할 수 있겠네요. 여튼 APR 덕분에, C 프로그래밍은 생각만큼 괴롭지 않습니다. APR의 홈페이지 메인을 보면 아래와 같이 이야기하고 있습니다.

“The mission of the Apache Portable Runtime (APR) project is to create and maintain software libraries that provide a predictable and consistent interface to underlying platform-specific implementations” – APR 프로젝트의 목적은 플랫폼 의존적인 구현에 대한 예측 가능하고 일관적인 인터페이스를 제공하는 소프트웨어 라이브러리를 만드는 것이다.

즉, 사용하는 하드웨어와 OS에 상관 없이 상위 레벨의 구현에만 신경쓸 수 있도록 만든 라이브러리가 바로 APR이라는 의미입니다. (자바의 “Write once, run everywhere” 의 향기를 느낀 건 저 뿐일까요?) 그래서 APR을 사용하면 네트워크 관련 low level operation (HTTP 헤더를 파싱한다던지, 파라미터를 읽어서 저장한다든지) 에 대해서는 신경쓰지 않아도 됩니다. 프로그래밍에 필요한 기초 자료 구조 (list, hash table) 도 라이브러리에 포함되어 있습니다.

무엇보다 매력적인 것은 APR의 메모리 풀 관련 기능입니다. 이 메모리 풀 라이브러리는 C 언어 개발에서 아주 골치아픈 메모리 할당 / 해제 문제를 해결해줍니다. 구체적으로 이야기하자면, APR을 사용하여 메모리를 할당 (apr_pcalloc 함수를 사용) 받으면, 클라이언트에 response를 보내줄 때 자동으로 풀에 할당된 메모리들을 해제해준다는 것입니다. 멋지지 않나요? 아무튼, APR의 은총 덕분에 상당히 많은 부분들을 라이브러리에 의존하면서 개발할 수 있습니다.

정적 타입의 강점

런타임에 변수의 타입을 결정하는 동적 타이핑 기반의 언어인 루비나 파이썬과는 달리, C는 컴파일 타임에 타입을 체크합니다. 타입이 맞지 않으면 오류를 내면서 컴파일조차 잘 되지 않습니다. 이 부분이 스크립트 언어를 주로 사용하던 프로그래머들에게는 불편할 수 있습니다. 하지만 저는 타입 안전성을 컴파일 타임에 확인할 수 있다는 점은, 프로그램의 안정성에 매우 큰 부분을 차지한다고 생각합니다. (물론 C 언어가 타입 안전성을 완벽히 보장하는 언어인지 묻는다면 물론 아닙니다. 하지만 컴파일 타임에 타입 체크가 불가능한 언어에 비해서는 분명한 강점을 가지고 있다고 생각합니다.) 타입 안전한 언어에서는 컴파일 타임에서 에러가 나지 않으면 로직에 문제가 있지 않은 이상은 잘 작동하죠. 버그는 있을 수 있지만 프로그램이 죽는 일은 없습니다. 또한 성능도 뛰어납니다.

compiling

그만큼 컴파일에 시간이 걸리긴 하죠. (물론 짤방정도는 아님)

Performance, Performance, Performance

APR을 사용하여 개발한 API 서버의 성능은 그야말로 압도적입니다. 기계어로 컴파일 되니까요.

Screenshot at Jan 21 16-36-24

더 이상의 자세한 설명은 생략한다

 

물론, 당연하지만, C 개발이 장점만 있지는 않습니다.

 

 

Reinventing the wheel

회사의 모 님이 저에게 물었습니다. “C 언어로 API 개발하는 거 어떤가요?” 저는 대답했더랬죠. “바퀴를 재발명하고 있는 것 같아요.” 그렇습니다. C 언어에는 그 흔한 ORM조차 없습니다. C 언어 자체가 객체지향적인 특성이 거의 없는 절차 지향적 언어이기 때문에, ORM을 만들어서 쓴다 해도 영 불편하죠. 덕분에 쿼리를 쓰고, 전송하고, 결과를 확인하고, 데이터 구조에 저장하는 등의 일들을 직접 한땀한땀 해야 합니다. 물론 공통되는 부분은 함수로 만들어서 재사용할 수 있지만, 누군가가 만들어 놓은 라이브러리를 가져다 쓰는 것에 비하면 개발 속도가 느려질 수밖에 없습니다. (그만큼 좀 더 시스템 하층 구조에 대해 깊게 알 수 있다는 장점은 있습니다.) 하다 보면 “꼭 이런 걸 일일이 해줘야 하나..”  란 생각이 들 때도 있습니다. 그리고 이건 개개인의 취향이겠지만, 저는 누군가가 만들어 놓은 소스 코드를 제가 다시 만드는 일이 그렇게 재미있지만은 않더라구요.

car and wheel

좀 이런 느낌…

라이브러리 뿐만 아니라 배포나 디버깅, 에러 리포팅, DB조회 등등 전반적인 개발 환경 역시 덜 자동화되어 있기 때문에 만약 자동화시키고 싶다면 직접 제작하는 수밖에 없습니다. 일례로, 레일즈 어플리케이션을 개발할 때는 모델 클래스를 잘 만들어 두면 데이터베이스 조회를 레일즈 콘솔을 통해 거의 다 할 수 있었으나, C 기반 개발을 할 때는 특정 데이터를 조회하거나 업데이트할 때에는 SQL을 직접 작성하는 수밖에 없습니다. 만약 조인을 해야하는 상황이라면 그 번거로움은 배가 되고 쿼리문이 길어질 수록 중간에 실수를 해서 개발 속도가 느려질 가능성은 커집니다. SQL에 익숙하지 않은 개발자라면 더 심하겠죠. 익숙하지 않은 DBMS를 사용한다면 더더욱 그럴테구요.

생산성

“C 언어는 생산성이 안좋다.” 라는 생각을 많이들 가지고 계신 것 같더군요. 제가 생각하기에, 생산성이라는 것은 몇 가지 측면으로 분류할 수 있을 것 같습니다. (물론 이거 말고도 더 있겠죠?)

  1. 같은 길이의 코드로 얼마나 더 많은 일을 할 수 있는 지
  2. 주어진 스펙을 얼마나 빠르게 개발할 수 있는 지
  3. 유지보수가 얼마나 용이한 지

1에서 당연히 C 언어는 루비에 비해 크게 뒤쳐질 수밖에 없습니다. 언어 자체의 특성도 그렇고, 외부 라이브러리의 사용도 쉽지 않으니까요. 하지만 제가 둘 다 경험해보니, 2의 측면에서 C 언어가 결코 루비에 비해 많이 뒤쳐지지는 않는 것 같습니다. 제가 조금 더 C 언어에 숙련된 프로그래머라면 그 격차는 더 줄어들겠죠? 그 이유는 다음과 같습니다.

  1. C에서는 쓸만한 외부 라이브러리가 많지 않습니다. 하지만 외부 라이브러리를 덜 가져다 쓴다는 말은 그만큼 관련 문서들을 찾아보는 데에 시간이 덜 걸린다는 이야기도 됩니다. 따라서 IDE와 웹브라우저 사이에서의 컨텍스트 스위칭에 시간을 덜 쓸 수 있습니다.
  2. 컴파일 언어라는 특성에서 비롯되는 IDE의 도움이 강력합니다. (자동 완성, 타입 체크, 오류 점검 등)
  3. 컴파일이 되기 때문에, 개발에는 시간이 더 걸릴 수 있지만 테스트와 디버깅에는 시간이 덜 걸립니다.

3의 경우에는 현재 상태에서는 말하기 힘든 부분이 있습니다. 왜냐하면 지금까지 C 언어를 통해 개발된 프로젝트들은 (1) 안정화되어서 커다란 스펙 변경이 없는 경우, (2) 신규 프로젝트라서 스펙이 미리 정해져 있는 경우, 둘 중 하나였기 때문입니다. 추후 애자일한 과정을 통해 잦은 스펙 변경이 있어야 할 때에 C 언어가 얼마나 유지보수가 용이한 지는, 조금 더 지켜보고 말씀드려야 할 것 같습니다. 다만 개인적으로는 코드 양이 더 많기 때문에 유지보수가 더 어렵지 않을까 하는 막연한 추측을 하고 있습니다. 아마 프로젝트 규모가 커질 수록 더하겠죠?

 

결론

 APR을 사용하면 C 언어로 모바일 API를 작성하는 일도 그렇게 어려운 일은 아닙니다. 약간 불편하기는 하지만 프로덕션 레벨에서 쓸 수 없을 정도는 아니고, 그만큼 우월한 성능을 얻을 수 있기 때문에 만약 스펙이 자주 바뀌지 않고 C 언어와 APR 기반 개발에 익숙하다면 시도해볼만 한 가치가 있는 것 같습니다.

지난 번 포스팅에서 많은 분들이 “CPU 사용률을 보면 사실상 CPU가 병목은 아닌 것 같다”고 지적해 주셨습니다. 웹 어플리케이션의 속도가 DB 속도에 의존적인 것은 사실입니다. 하지만 DB 병목보다는 어플리케이션 레벨에서의 불필요한 오버헤드 (정확히 말하자면 Hibernate의 eager loading) 역시 큰 속도 저하의 원인이었습니다. 이를 수정하기 위한 노력을 기울였지만 결국 포기하고 주요한 속도 저하의 원인이었던 ORM을 버리고 서버를 다시 개발하기로 결정하게 된 것입니다. 물론 이게 절대적으로 최선의 선택이었다고는 하기는 힘들지만, 목표한 성과를 이뤘다는 점에서 긍정적이라고 생각합니다.

모든 프로그래밍 언어와 프레임웍은 각자 제 용도에 맞는 쓰임새가 있다고 생각합니다. (너무 모범적인 결론이지만) 이음의 API 서버는 현재로서는 큰 설계의 변화나 스펙의 변화가 없기 때문에 유지 보수가 조금 불편하더라도, 퍼포먼스를 끌어낼 수 있는 C 언어를 사용했죠. 그리고 애초 의도했던 바와 부합하는 효과를 얻었습니다. 특히나 모바일 API 쪽은 HTML 페이지를 렌더링하는 웹 서버와 비교하더라도 많은 기능이 필요하지 않습니다. 만약 웹 서버를 개발하는 일이었다면 string 관련 함수들이 불편한 C를 사용하지 않았을 것입니다. 어떤 언어(프레임웍)을 쓰는 지도 중요하지만 지금 사용하고 있는 도구가 목적에 맞는 지도 중요하지 않을까요?

하지만 무엇보다도 개발자에게 그 도구가 얼마나 손에 익은 도구인지도 중요한 것 같습니다. 아무리 좋은 도구가 있더라도 사용할 줄 모르면 무용지물인 것처럼요. 이음에서는 APR 환경에서 오랜 시간동안 개발을 해왔던 개발자 분이 계셨고 그 분이 첫 삽을 뜬 덕분에 다른 분들이 수월하게 개발을 시작할 수 있었던 것 같습니다. 그리고 개발자들이 대부분 컴퓨터 공학 전공 베이스를 가지고 있었던 덕분에 C 언어를 생소하게 느끼지도 않았구요. 이 글을 읽고 APR 도입을 고려하고 계시다면, 이 점을 다시 고려해보세요 🙂

 About the use of language: it is impossible to sharpen a pencil with a blunt axe. It is equally vain to try to do it with ten blunt axes instead ; 프로그래밍 언어의 사용에 관하여: 무딘 도끼를 가지고 연필을 깎는 일은 불가능하다. 무딘 도끼 10개를 가지고 시도한다고 해도 결과는 마찬가지다.  – E. W. Dijkstra

 

TabsSpacesBoth

그래도 한 프로젝트에 여러 언어는 섞어 쓰지마세요. 술 섞어 먹는거랑 똑같습니다. 먹을 때만 행복

 

Screenshot at Jan 21 18-52-44