이번에 회사에서 새로운 기능을 런칭했다. 내려오는 데이터 량이 좀 된다. 150K 정도 

 

스테이징 서버(한국에 있다)에서 혹독한 테스트를 거쳐도 문제가 없고, 론칭후 테스트에서도 별 이상이 밝혀지지 않았다. WI-FI 환경하에서도 동작을 잘하고 

 

문제는 내 폰에서 발생했다. 참고로 나는 SKT 폰을 사용중이다. SKT 의 LTE 환경하에서는 멈춘거처럼 동작하는 것이다. 150K 다.. 다시 말하면. 그정도 데이터를 내려 봤는데 멈춘다고? 

 

개발자를 소집해서 물어봤더니 전혀 안 느리다고 한다. 내 폰을 실제로 보여주니 개발자들이 다들 당황하는 것이다. 결국 이런 저런 테스트를 통해서 내린 결론은 SKT - LTE 가 완전 개 구리다는 것이다. 국내는 별 문제가 없으나 특히 해외가

 

KT, LG, WI-FI 망에서는 아주 잘 동작한다. 이렇게 쓰는 것도 웃기다. 겨우 150K 인데.. 

 

결국 SKT 의 LTE 환경이 개선되길 바라는 것은 코로나 19가 자연적으로 사라지길 바라는 것만큼 이루어지기 힘든 바람일테니, 우리가 패킷을 다이어트 시켰다. 1/3 로 줄였더니 시간이 많이 단축 됐다. 하.. 5G 시대에 150K 때문에 이런 난리가 일어나다니.. 

 

결론은 SKT-LTE 가 해외에 있는 서버랑 연결할때 극악의 효율을 보여준다는 것이다. 해외 서비스 준비할때 이런 것도 고려해야 할 것이다. 

예전에는 혼자서 개발하면서 성장할 수 있는 시기가 있었지만, 요즘은 팀단위로 개발을 진행하기 때문에 빠르게 성장할 수 있지만, 자신의 파트에 특화되는 경향이 있습니다. 물론 지금도 파트를 오가면서 개발을 할 수는 있지만 예전만큼 쉽지 않습니다. 저도 실제로 클라이언트 개발을 하다가 서버 사이드로 옮긴 경우 입니다. 


  예전 다니던 회사에서 공개 개발자 모집을 한 적이 있습니다. 들어온 원서의 비율을 체크 해보니 안드로이드, iOS, 백엔드 개발자의 비율이 8:1:1 이였습니다. 클라이언트와 서버 비율로 따져보면 9:1 입니다. 

  클라이언트 사이드에서 안드로이드 개발자가 iOS 보다 많은 이유를 몇 가지 짐작해 볼 수가 있습니다. 

  안드로이드 폰을 가진 사람이 월등하게 많습니다. 자신이 가진 폰에 맞는 앱을 개발하다보면 당연히 안드로이드 개발이 많을 수 밖에 없다고 생각할 수 있습니다. 

  안드로이드 개발 환경 구축이 훨신 쉽습니다. iOS 는 맥에서 개발을 해야 하지만 안드로이드는 일반 윈도우 환경에서도 개발이 가능합니다. 또한 iOS 는 스토어에 올리려면 개발자 인증서를 사야 하는데 이 비용도 초기 비용에 해당합니다. 또한 지금은 추세가 바꼈지만 예전에 iOS 는 object-c 로 개발을 해야 했는데 이는 java 보다 난이도가 높습니다. java 는 학교 수업시간에도 배우는 언어이기 때문입니다. 

  여러가지 이유로 안드로이드 개발이 iOS 보다 많은 이유를 짐작해 볼 수가 있습니다. 

  그러면 클라이언트와 서버 개발은 어째서 차이가 날까? 
  
  클라이언트 개발은 접근성이 편합니다. 그리고 결과물을 바로 볼 수가 있다는 장점이 있기 때문에 개발에 흥미를 가지고 시작하기가 좋습니다. 그리고 개발 -> 개발 완성까지의 가야 하는 길이 짧습니다. 

  서버 사이드는 개발을 시작하기 위해서 알아야 할 것들이 많습니다. 데이타베이스도 알아야 하고 디플로이도 제대로 할려면 리눅스 관련 명령도 배워야 합니다. 요즘은 클라우드가 대세이기 때문에 AWS (Amazon Web Service) 나 GCP (Google Cloud Platform)을 알아야 하는 시기가 됐습니다. 개발 언어도 알아야 하고 웹 서비스면 웹프레임워크도 알아야 합니다. 게다가 국내에서 가장 많이 쓰이는 자바 관련 개발 환경이라면 스프링 프레임워크를 많이 쓰는데 이 또한 학습곡선이 높고 많은 기간을 필요로 합니다. 만약에 결과를 눈으로 확인 하기 위해서는 프론트엔드도 최소한으로 알아야 하는데 이 또한 만만치 않은 노력을 필요로 합니다. 

  즉 클라이언트 개발은 접근성이 좋고 바로 바로 아웃풋이 확인 가능하니 개발의 재미를 줄 수가 있습니다. 서버 개발은 개발 접근성이 좋지 않고 바로 바로 아웃풋 확인 하기까지가 배워야 할 것들이 많습니다. 하지만 이러한 난이도가 시니어급에 이르렀을 때 연봉의 차이를 가져옵니다. 9:1 클라이언트대 서버 개발자의 비율입니다. 이게 펑균이라고 보기에는 사실상 무리가 있는 특이 케이스 일 수도 있지만 인력시장에서 알아보면 확실히 서버 개발자의 숫자가 적습니다. 

  그래서 내가 클라이언트와 서버 개발중에서 어떤걸 할까 고민을 한다면 각각의 특장점이 있습니다. 

  클라 개발에 전념해서 장인급이 되신다면 회사를다니면서 또는 프리랜서를 하시면서 '돈'만 바라보고 여러가지 일을 동시에 진행한다면 단기간에 큰 돈을 벌 수가 있다는 것입니다. 제 주변에는 프리랜서 시절에 연 1억을 넘게 벌어들인 아이폰 개발자와 연 2억을 넘게 돈을 버는 클라이언트 개발자들이 있습니다. 

  서버는 이후에 올라갈 수 있는 테크가 있습니다. 아키텍트 - 개발 총괄 - CTO 등으로 커 나아갈 수 있는 기회가 열려 있습니다. 물론 클라이언트 개발자 출신으로도 가능합니다. 그리고 클라이언트 개발자 분들의 역량을 무시하는 건 절대 아니지만 이후 실제로 서비스를 론칭해서 운영하는 경우에는 절대적으로 서버쪽의 지식이 필요합니다.

  물론 이런 것들이 생각처럼 잘 되기 위해서는 그에 따르는 노력들이 필요하지만 대체로 이렇습니다. 

큰 회사를 제외하고 일반적으로 작은 형태의 IT 회사는 다양한 형태가 존재하지만 무리하게 일반화를 굳이 하자면, CTO (Technology) 주도의 회사와 CPO (Product) 주도의 회사가 있습니다. 


쉽게 말하자면 기술 주도의 회사와 기획 주도의 회사 입니다. 각각의 장점이 확실히 존재합니다. 기술 주도는 제품이 단순하고 개발 이터레이션이 짧게 돌아가고, 기획 주도는 창의적이고 다양한 시도를 하기에 기존하고 다른 제품이 나올 확률이 높습니다. 어떤 개발 스타일을 제가 좋아하는 것은 별도로 치고도, 잘 생각해 보면 회사의 개발 방향이 이런 형태중에 한가지에 가까울 수가 있습니다. 


다만 개발자 출신으로서 생각해 보기에는 (초보) 개발자는 기술 주도의 회사가 더 편하겠지요? 아무래도 CTO 가 주도하는 사이클을 몸에 익히면 추후에 팀장이나 또는 본인이 CTO 로 나아갈 때 도움이 됩니다. 


그렇다고 기획 주도의 회사가 (초보) 개발자가 일하기 힘들기만 한 것이냐? 그렇지는 않습니다. 고난 속에서도 배우는 것이 있듯이 나중에 기획이 바꼈을 때 어떻게 기획자들과 싸워서 일정을 쟁취해야 하는지에 대해서 확실히 배울 수가 있습니다. 다만 변경되는 일정에 대한 짜증은 별도이지만요. 즉 심각하게 힘들게 하는 SI 의 대비를 미리 할 수가 있다는 것입니다. 농담 처럼 이야기 하지요 SI 에 계속 있으면 안되지만 군대 가듯이 SI 를 해 볼 필요는 있다고 말이죠. 그리고 이 바닥에서 말하듯이 개발자에게 있어 군대란 .. 


즉 처음의 논조와는 달라졌지만 (초보) 개발자가 기획 주도 회사에서 일할 때 


1. 자주 기획이 변한는 것에 대한 불만

 - 기획이 자주 변경 되는 건 당연한 일이 라고 여겨야 합니다. 

 - 잘 교육된 기획자가 아니면 아닐 수록 생각을 확정 못 시키고 자주 기획이 변경됩니다.


2. 기획이 바꼈는데도 일정을 고정할려고 하면

 - 절대 납득하고 날 새시면 안됩니다. 

 - 그 기획자에게도 기획이 바뀌면 일정이 변경된다는 것을 교육 시켜야 합니다. 그래야 그 분도 나중에 다른 개발자랑 일할 때 신경을 써 줍니다. 


3. 지속적으로 일정 관리에 대한 분위기 조성

 - 어떠한 일이 있더라도 기획이 바뀌면 일정은 무조건 변경되야 한다는 것을 모든 개발 참여자들이 인지하는 분위기를 조성해야 합니다. 

 - 그래서 개발 시작 전에 기획이 확정 되어지고 그 기획은 마일스톤 (or 스프린트) 기간 내에는 변경이 안되게 확답을 받아야 합니다. 

 - 개발 일정이 변경 되는 것에 대한 원인이 기획 변경에 있다는 것이 인지되면 기획자들도 조금 더 노력해서 기획을 확정 지으려고 합니다.


최근 회사 개발자가 확정 안되어진 기획서를 가지고 개발하는 데 짜증을 내길래 달래주다가 정리한 글입니다. 


프로그래밍 언어는 python을 이용하고 웹 프레임워크는 Django 를 사용하고, 데이타베이스로는 MySQL 을 사용중인데 admin 사이트 구현중에

date_hierarchy = 'created_at'

이 구문 때문에

Database returned an invalid value in QuerySet.dates(). Are time zone definitions and pytz installed?

이런 에러가 발생한다.

해결을 위해서는 일단 pytz 를 설치해줘야 한다.

$ pip install pytz

그리고 우분투에 설치된 mysql 에 한하여 (docker 로 설치한 mysql 도 괜찮다, 테스트 해보니 osx 도 된다)

$ mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p  mysql

하고 데이타베이스를 재시작 하면 된다. docker 데이타베이스는 설정을 바꾸면 재시작이 안되니 조심해야 한다. 원격 데이타베이스에 관해서는 (Google App Engine 의 Cloud SQL 도 가능하다)

$ mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p  -h $REMOTE_SERVER mysql

최근에 다시 clojurescript 를 이용해서 작업할 일이 생겼습니다. javascript 는 편리하긴 하지만 구현하는데 재미가 없다는 심각한 결점이 있기 때문입니다. 게다가 최근 lein-figwheel 이라는 편리한 툴이 나와서 정말 편하게 작업을 할 수가 있습니다. 다만 lein figwheel 을 하면 불편하게도 console 에서 작업을 해야 하기 때문에 emacs 의 편리한 기능을 못써서 안타깝습니다. 따라서 nRepl 을 이용해서 편리하게 작업하는 방법을 소개시켜드릴까 합니다.

  1. CIDER 와 clojure-mode 를 설치해야 한다.

    package-install 명령을 이용하면 쉽게 설치가 가능하다.

  2. leiningen plugins 를 설정해야 한다.
    ~.lein/profiles.clj
    

    를 열어서 다음과 같이 추가해 준다. (2015. 12. 29 현재 0.10.0 버젼이 최신)

    {:user {:plugins [[cider/cider-nrepl "0.10.0"]]}}
    
  3. 개별 project.clj 설정에
    :figwheel {:nrepl-port 7002}
    

    내용이 defproject 와 같은 레벨로 추가가 되어 있어야 한다.

  4. .emacs 파일에
    (add-hook 'cider-connected-hook '(lambda ()
                              (cider-interactive-eval
                               "(use 'figwheel-sidecar.repl-api)\n(cljs-repl)\n")))
    
    (defun figwheel-connect ()
    (interactive)
    (cider-connect "localhost" "7002"))
    
  5. figwheel-connect 명령을 실행 프로젝트 루트 디렉토리에서
    lein figwheel
    

    을 실행해서 띄우고 , M-x figwheel-connect 를 이용해서 접속한다.

처음 스위프트 (Swift : 혹 수입푸드 라고 부르는 사람들도 있음 ㅋㅋ) 개념을 보았을 때, VM (Virtual Machine) 같은 개념으로 여겼습니다. '뭐 또 빠르게 개발은 될 지 모르겠으나 동작은 느린애가 되겠군' 라고 생각하며 안 보고 있다가. 최근에 보니 이게 컴파일러용 언어였더군요. 플레이그라운드(Playground) 개념은 잽싸게 컴파일 해서 그 결과를 보여줘서 interactive 하게 보일지 모르지만 실은 컴파일 언어였습니다. 


개념이 재미 있는데다가 컴파일된 바이너리가 기존의 Object-C 언어로 만들어진 것보다 속도가 2.8 배가 빠르다는 것을 보고 관심이 가더군요. 그래서 언어 개요를 가볍게 살펴봤습니다. 

iOS 기기를 가지고 있으면 iBooks 에서 공짜로 프로그래밍 언어에 대해서 설명한 책을 받아볼 수가 있습니다. 물론 그런것이 없는 분들을 위해서 사이트에서도 제공됩니다. 그리고 정말 훌륭하신 분들이 해석해서 사이트에 올려둔 곳도 존재하더군요. 


Swift 언어 가이드 


에서 참조하실 수 있습니다. 저는 프로그래밍 언어 자체에 노력을 많이 기울이는 편은 아닙니다. 애초에 Swift 가 필요한 이유는 iOS 나 Cocoa 용 앱을 빠르게 만들기 위함이 아니겠습니까? 그렇다면 실전에서 익히고 어렵거나 이해가 안가는 부분을 찾아서 공부하는 것이 조금 더 '실용적' 이라고 생각하기 때문입니다. (실은 예전에 프로그래밍 언어 그 자체만 공부하다가 지치거나 중간에 흥미가 떨어져서 응용해 보지도 못한 적이 여러번 있기 때문입니다. - 마치 영어를 공부해야 하는데 어떻게 하면 영어 공부를 잘하는 법을 공부하는 경우와 비슷하다고 하겠습니다) 


그래서 실전 튜토리얼을 찾아보다가 찾은 정말 훌륭한 동영상이 있더군요. 비록 한글이나 한국어로 된 것은 아니긴 하지만 기술 영어를 사용하고 있어서 쉽게 알아먹을 수가 있습니다. 영어도 공부하고 Swift 도 공부하고 1석 2조!! 


프로그래밍 경험 없는 사람이 쉽게 iOS 용 앱 (다 만들면 게임이 만들어 집니다) 만들기 


iOS 용 앱을 만들어 볼려고 했는데 엄두가 안 나신분 들에게 강력 추천합니다. 내용중에 보면 MVC 패턴과 XCode 툴에 관한 설명등 들어두면 좋은 내용들 다수가 들어 있습니다. 



안드로이드 어플리케이션 개발시 strings.xml 에 html tag 를 삽입할려고 하다 보니 ADT안드로이드 스튜디오 와 호환성 문제가 발생하더군요.

1 현상

<string name="string_hello"><font color="#fffff">메모<![CDATA[<tt> </tt>]]> %1$s</font></string>

위와 같이 html tag 를 strings.xml 에서 사용할때 공백문자를 사용하기 위해서 CDATA 태그를 조금이라도 적게 사용할려고 공백 문자에만 사용할려고 하다가 발생했습니다.

2 원인

]]> 태그가 마지막에 오지 않으면 발생한다는 에러가 발생합니다. 혹은 리소스 머지(merge) 시에 에러가 발생한다던가 , 잘 쓰고 있던 컴퍼넌트 (component) 가 없다는 등 종잡을 수 없는 에러가 발생합니다.

3 해결

<string name="string_hello"><![CDATA[<font color="#fffff">메모 %1$s</font>]]></string>

위와 같이 변경해 주면 해결됩니다. 공백은 단순히 CDATA 안에서 space 한칸만 두면 됩니다.

안드로이드 어플리케이션 개발 시 YoutubeStandAlonePlayer 를 쓸 일이 있었서 사용했는데 예상치 못한 버그가 발생하더군요. 그 현상과 해결방법을 정리합니다.

1 현상

안드로이드 앱 개살시 메인 어플리케이션을 Portrait 전용으로 개발중이였습니다.

Intent intent = YouTubeStandalonePlayer.createVideoIntent(context,
                    DEVELOP_KEY, youtubeCode);
                context.startActivity(intent);

와 같은 식으로 유튜브 플레이어를 띄우니 띄운 액티비티(Activity) 와 그 스택에 쌓여있던 액티비티 들의 onResume 이 호출되는 현상이 있습니다. 그래서 플레이중에 멋대로 호출된 Activity 로 튕깁니다. 게다가 어찌 어찌 플레이되더라도 플레이중에 백키를 누르면 호출된 액티비티로 가는게 아니라 앱이 종료됩니다.

2 원인

아마도 Landscape 전용인 YouTubeStandalonePlayer 와 Portrait 로 만들어진 메인 앱과의 차이점 때문인 것 같다고 판단하여 해결법을 찾았습니다.

3 해결

YouTubeStandalonePlayer 를 호출하는 Activity 와 그 스택에 쌓여 있는 Activity 들의 AndroidManifest 안에 android:configChanges="orientation|screenSize|keyboardHidden" 와 같은 내용을 추가해주면 해결됩니다.

<activity
    android:name=".scene.IntroActivity"
    android:configChanges="orientation|screenSize|keyboardHidden"
    android:screenOrientation="sensorPortrait" />
<activity

와 같은 식입니다.

Multiple dex files define Landroid/support/v4 관련된 어쩌구 저쩌구 에러가 발생했을 때의 대처법입니다.

100% 제 환경에서 발생하는 일이였습니다. 먼저 환경을 소개하자면 회사에서 개발하는 안드로이드 (Android) 프로젝트인데 전부 환경이 달라서 문제가 발생했습니다.

  • PM 인 저는 Command Line 에서 프로젝트를 개발합니다. 사용하고 있는 툴(Tool)은 Emacs 에 Ant 를 이용해서 빌드합니다.
  • 회사에서 작업하는 개발자는 Android Studio 를 이용해서 개발합니다.
  • 회사 외부에서 개발하는 개발자는 ADT (Android Development Tool) 을 이용합니다.

저와 외부에서 개발하는 개발자간의 호환은 별 문제가 없습니다. Eclipse 와 Command Line 은 거의 프로젝트 세팅이 비슷한거 같습니다. 물론 따로 설정해줘야 하는 부분이 있지만.. 하지만 ADT 와 안드로이드 스튜디오 간에는 차이가 확실히 존재하더군요.

play-services 를 이용해서 개발하는 것입니다. ADT 에서는 따로 Library Project 를 설정해서 기존 프로젝트에 포함시켜주면 되는 것이였습니다. 그러나 Android Studio 는 방법이 다르더군요.

Google Play Service 세팅법 을 참조해서 하면 build.gradle 을 열고 다음과 같이 추가해 주면 되는 것입니다.

dependencies {

    compile 'com.google.android.gms:play-services:6.5.87'
}

그러나 에러가 발생하더군요. 이유는 간단했습니다. ADT 에서 참조하는 libs 에 android-support-v4.jar 이 포함됐기 때문입니다. 그렇다고 바로 지우자니 그 담부터는 ADT 를 이용하는 외부 개발자님의 빌드가 깨지겠지요.

그래서 다음과 같이 바꾸어 줍니다.

dependencies {
    compile fileTree(dir: 'libs', include: '*.jar')
    compile ('com.google.android.gms:play-services:+') {
                exclude group: 'com.android.support', module: 'support-v4'
    }
}

그리고 Android Studio 에 있는 Toolbar 를 보면 'Sync Project with Gradle Files' 라는 버튼을 눌러주고 프로젝트를 빌드해 주면 됩니다.

저는 안드로이드를 Emacs 로 개발하고 있는 중인데요. 외부 jar 가 추가 될 때 자동으로 classpath 에 추가 하고 자동으로 import 기능을 활성화 시키는 방안을 찾는 중인데, 없더군요.. 

물론 Eclipse 를 사용하면서 Google AdMob SDK 같은 외부 jar를 사용하기는 쉽습니다. 외부 라이브러리로 추가해 주면 끝이기 때문입니다. 다만 CLI (Command Line Interface) 에서 Ant 를 이용해서 빌드를 할 때는 마구 마구 귀찮아집니다. 하지만 쉽게 하는 방법이 생겼더군요. 

$(ANDROID_PROJECT_ROOT) 밑에 /libs 라는 디렉토리를 만들고 그 안에다가 GoogleAdMobAdsSdk-6.0.1.jar android-support-v4.jar 두개의 파일을 복사해줍니다. 


$(ANDROID_PROJECT_ROOT) 밑의 ant.properties 파일을 열고 다음과 같이 추가해 줍니다. 

  jar.libs.dir=libs


이제 

$ ant clean && ant debug 



해 주시면 성공적으로 바인딩 되는 것을 확인하실 수 있습니다. 

다만 위와 같이 따로 libs 를 추가해 주면 JDE 환경에서 자동으로 classpath 뒤져서 Import 해주는 기능이 libs 에 추가된 jar 에 대해서는 동작하지 않습니다. 이럴 때를 위해서 따로 함수를 만들어 뒀습니다. (100% 제가 만든것입니다 쿨럭..) 



(defun android-mode-my-hook () 
  (progn
    (and (file-exists-p 
          (concat (android-root) "/libs"))
         (setq jde-global-classpath 
               (append jde-global-classpath 
                       (directory-files
                        (concat (android-root) "/libs")
                        t "jar"))))
    ))
(add-hook 'android-mode-hook 'android-mode-my-hook)


다음과 같이 만들어 주면 됩니다. 저는 java 설정만 따로 모아놓고 쓰지만 그렇지 않으신 분들은 .emacs 파일 구석에 적어두시면 될 것입니다. 물론 jdee 와 android-mode 설정 뒤에 적어주셔야 할 것입니다. jde-global-classpath 는 jdee 를 추가 해줘야 생기는 변수고 android-root 는 안드로이드 프로젝트의 루트를 찾아주는 편리한 함수인데 android-mode 를 추가해줘야만 쓸 수가 있습니다. 

점점 lisp 으로 코딩하는게 재밌어 지기 시작합니다. ㅎㅎ 
 

+ Recent posts