Skip to content

Commit

Permalink
markdown 으로 export 할 때 image link 가 두 번 쌓여있는 게 잘못돼 있는 것 같아서 정정 시도
Browse files Browse the repository at this point in the history
  • Loading branch information
starrybleu committed Nov 8, 2024
1 parent 2cd48fd commit a911d18
Show file tree
Hide file tree
Showing 42 changed files with 306 additions and 306 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ tags:

지금 우리가 배포하려는 서버는 다음과 같은 구조를 가지고 있다고 가정합니다.

[![서버구조]({{ site.baseurl }}/images/8yVXHQuTvF.png)](https://blog.dramancompany.com/wp-content/uploads/2015/09/스크린샷-2015-09-25-14.42.22.png)
![서버구조]({{ site.baseurl }}/images/8yVXHQuTvF.png)

이와같은 구조에서 배포를 할 경우 일단 ELB 구성이 되어 있으므로 다음과 같은 순서로 무중단 배포는 가능합니다.

Expand All @@ -36,7 +36,7 @@ tags:

그래서 좀더 안정적이고 쉬운 배포를 위해 다음과 같이 구성을 해봅시다.

[![]{{ site.baseurl }}/images/EC5JG2mg9L.png)](https://blog.dramancompany.com/wp-content/uploads/2015/09/스크린샷-2015-09-25-16.17.37.png)
![]{{ site.baseurl }}/images/EC5JG2mg9L.png)

AWS에서는 훌륭한 Auto Scaling 서비스를 무료로 제공하고 있습니다. Auto Scaling은 쉽게말해 **Amazon Machine Image(이하 AMI)**를 설정한 조건에 따라 인스턴스를 늘리거나 줄이는 일을 합니다. 여기서 제가 주목하는 점은 'AMI'입니다. AMI는 말 그대로 머신 이미지를 말하는데 이를 이용하면 AMI를 생성하기 위한 서버 1대만 있으면 이를 이용해 이미지를 생성한 후 똑같은 서버를 원하는 만큼 생성할 수 있습니다.

Expand All @@ -54,7 +54,7 @@ AWS에서는 훌륭한 Auto Scaling 서비스를 무료로 제공하고 있습

아래는 현재 리멤버 서버 배포시 구성을 간략히 그려보았습니다.

[![]({{ site.baseurl }}/images/ShCmmzxgrH.png)](https://blog.dramancompany.com/wp-content/uploads/2015/09/스크린샷-2015-09-30-12.14.13.png)
![]({{ site.baseurl }}/images/ShCmmzxgrH.png)

AMI 생성용 서버에 Capistrano를 이용해 배포 후 AWS web console에서 설정만 해주면 쉽게 모든 서버 업데이트를 마칠 수 있도록 되어 있습니다. 그럼 Capistrano를 어떻게 설치하고 설정 하는지 알아보도록 하겠습니다.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,13 +102,13 @@ MPA로 B/O 제품들을 개발하던 Jaden은 시스템 속도 개선, 생산성

턴제 방식의 페어 방식의 페어 프로그래밍을 진행하던 중, 둘 다 아무래도 처음 정했던 1시간이 애매한 시간이라는 생각이 들었습니다. 1시간이 집중도가 한참 높아질 때여서 1시간 마다 턴 변경을 자주 놓치게 되었고 그러다 보니 키보드를 잡고 있지 않은 사람의 집중도가 약간 떨어지는 경향이 있었습니다. 그래서 방식을 동시제로 변경했습니다. 다음 사진을 보시죠.

[![pair_programming]({{ site.baseurl }}/images/lksLiI09Bl.jpg)](https://blog.dramancompany.com/wp-content/uploads/2015/11/pair_programming.jpg)
![pair_programming]({{ site.baseurl }}/images/lksLiI09Bl.jpg)



사진 왼쪽의 노트북에서는 설계와 관련된 내용을 작성, 가운데의 모니터로 코드를 공유, 오른쪽의 노트북으로는 결과 실행을 합니다. 가운데의 키보드와 트랙패드는 우측 노트북과 연결하여 Tom이 사용하고 Jaden은 우측의 노트북으로 코드를 작성합니다.[](http://deopard.cafe24.com/wp-content/uploads/2015/10/pair_programming.jpg)

[![slack-for-ios-upload-1]({{ site.baseurl }}/images/IabfBFuDLV.jpg)](https://blog.dramancompany.com/wp-content/uploads/2015/11/Slack-for-iOS-Upload-1.jpg) [![slack-for-ios-upload-2]({{ site.baseurl }}/images/PDFZ57K6U8.jpg)](https://blog.dramancompany.com/wp-content/uploads/2015/11/Slack-for-iOS-Upload-2.jpg)
![slack-for-ios-upload-1]({{ site.baseurl }}/images/IabfBFuDLV.jpg)](https://blog.dramancompany.com/wp-content/uploads/2015/11/Slack-for-iOS-Upload-1.jpg) [![slack-for-ios-upload-2]({{ site.baseurl }}/images/PDFZ57K6U8.jpg)

_<혼자가 아닌 둘이니 개발 설계에 대해 토의도 하면서 화이트보드에 적을 수도 있습니다>_

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ date: "2015-11-25"

리멤버 또한 구글이 준 유예기간 동안 프리뷰 이미지 및 오픈 테스트 랩 등을 활용해 새로운 안드로이드 M버전에 대응하였습니다. 그 과정을 공유드리고자 합니다.

<caption id="attachment\_267" align="aligncenter" width="300">[![pv9AcTqS-gotB5ply6js6SgqwcMrXcvbZlicenbfWh5Q-iW7cf6RrGM-TR7dSM0Z2BbVGA=s2048]({{ site.baseurl }}/images/6O5FqHXNU1.png)](https://blog.dramancompany.com/wp-content/uploads/2015/11/pv9AcTqS-gotB5ply6js6SgqwcMrXcvbZlicenbfWh5Q-iW7cf6RrGM-TR7dSM0Z2BbVGAs2048.png) 안드로이드 6.0 마시맬로우 마스코트. 필자는 이 그림과 똑같은 피규어가 있습니다.</caption>
<caption id="attachment\_267" align="aligncenter" width="300">![pv9AcTqS-gotB5ply6js6SgqwcMrXcvbZlicenbfWh5Q-iW7cf6RrGM-TR7dSM0Z2BbVGA=s2048]({{ site.baseurl }}/images/6O5FqHXNU1.png) 안드로이드 6.0 마시맬로우 마스코트. 필자는 이 그림과 똑같은 피규어가 있습니다.</caption>

## **M버전, 무엇을 대응해야 하나?**

Expand Down Expand Up @@ -80,7 +80,7 @@ M버전의 대응의 90%는 권한모델을 넣는 것 이였습니다. 그만

[http://developer.android.com/intl/ko/reference/android/Manifest.permission\_group.html](http://developer.android.com/intl/ko/reference/android/Manifest.permission_group.html)

<caption id="attachment\_250" align="aligncenter" width="211">[![6.0 부터는 사용자가 설정창에서 권한그룹 단위로 허용/거부를 명시적으로 할 수 있습니다.]({{ site.baseurl }}/images/j4mU7284G3.jpeg)](https://blog.dramancompany.com/wp-content/uploads/2015/11/권한그룹-설정창.jpeg) M버전 부터는 사용자가 설정창에서 권한그룹 단위로 허용/거부를 명시적으로 할 수 있습니다.</caption>
<caption id="attachment\_250" align="aligncenter" width="211">![6.0 부터는 사용자가 설정창에서 권한그룹 단위로 허용/거부를 명시적으로 할 수 있습니다.]({{ site.baseurl }}/images/j4mU7284G3.jpeg) M버전 부터는 사용자가 설정창에서 권한그룹 단위로 허용/거부를 명시적으로 할 수 있습니다.</caption>

### 사용자에게 필요한 권한을 요청하자

Expand All @@ -103,7 +103,7 @@ M버전의 대응의 90%는 권한모델을 넣는 것 이였습니다. 그만

2번 시나리오 에서는 앱 내에서 사용자가 해당 권한을 허용할 수 있도록 안내할 방법이 사라집니다.

<caption id="attachment\_245" align="aligncenter" width="300">[![requestPermissions()하면 뜨는 권한요청 다이알로그. 한번 이상 거절을 선택하면 다시보지않기가 보이는데, 이것을 체크할 경우 다시는 이 다이알로그를 볼 수 없다.]({{ site.baseurl }}/images/hdvBaVpijp.png)](https://blog.dramancompany.com/wp-content/uploads/2015/11/permission_request_dialog_chk.png) requestPermissions()하면 뜨는 권한요청 다이알로그. 한번 이상 거절을 선택하면 다시보지않기가 보이는데, 이것을 체크할 경우 다시는 이 다이알로그를 볼 수 없습니다.</caption>
<caption id="attachment\_245" align="aligncenter" width="300">![requestPermissions()하면 뜨는 권한요청 다이알로그. 한번 이상 거절을 선택하면 다시보지않기가 보이는데, 이것을 체크할 경우 다시는 이 다이알로그를 볼 수 없다.]({{ site.baseurl }}/images/hdvBaVpijp.png)하면 뜨는 권한요청 다이알로그. 한번 이상 거절을 선택하면 다시보지않기가 보이는데, 이것을 체크할 경우 다시는 이 다이알로그를 볼 수 없습니다.</caption>

저희는 모든 경우에 수를 커버하지 못하는 [ActivityCompat.shouldShowRequestPermissionRationale()](http://developer.android.com/intl/ko/reference/android/support/v4/app/ActivityCompat.html#shouldShowRequestPermissionRationale(android.app.Activity, java.lang.String))를 사용하지 않기로 하였습니다. 그리고 몇가지 반복작업을 하나로 묶어 편하게 권한을 요청하면서도, 사용자가 다시보지 않기를 체크해도 권한을 허용할 수 있도록 안내하기 위한 PermissionUtil을 만들기로 하였습니다. 생각하는 시나리오는 다음과 같습니다.

Expand All @@ -114,7 +114,7 @@ M버전의 대응의 90%는 권한모델을 넣는 것 이였습니다. 그만

여기에서 핵심은 4번입니다. 만약 사용자가 다시보지 않기를 체크하고 권한을 거부하더라도, 앱 사용에 필수적인 권한을 허용하도록 설득하면서, 별도로 설정할 수 있도록 돕는 다이알로그를 띄웁니다.

<caption id="attachment\_247" align="aligncenter" width="300">[![]{{ site.baseurl }}/images/3ZrWGHUwSg.jpeg)](https://blog.dramancompany.com/wp-content/uploads/2015/11/Rational-Dialog1.jpeg) 권한을 거부당해도 설정창으로 안내하는 다이알로그를 띄우고 싶었습니다.</caption>
<caption id="attachment\_247" align="aligncenter" width="300">![]{{ site.baseurl }}/images/3ZrWGHUwSg.jpeg) 권한을 거부당해도 설정창으로 안내하는 다이알로그를 띄우고 싶었습니다.</caption>

PermissionUtil에서는 다음과 같은 메소드들을 이용하여 권한을 요청합니다.

Expand Down Expand Up @@ -275,7 +275,7 @@ public static void requestOverlayPermission(Activity activity) {

설정창으로 넘어가게 하는 것은 쉽지만, 사용자에게 낯선 권한을 허용받기 위해서는 왜 이 권한이 필요한지를 잘 설명하는 것이 중요하겠습니다.

<caption id="attachment\_251" align="aligncenter" width="226">[![system_window_alter는 다른 권한들과 다르게 '다른 앱 위에 그리기' 설정창에서 직접 허용받아야 합니다.]({{ site.baseurl }}/images/ii392AL6Dc.jpeg)](https://blog.dramancompany.com/wp-content/uploads/2015/11/다른앱-위에-그리기.jpeg) system\_window\_alert는 다른 권한들과 다르게 '다른 앱 위에 그리기' 설정창에서 직접 허용받아야 합니다.</caption>
<caption id="attachment\_251" align="aligncenter" width="226">![system_window_alter는 다른 권한들과 다르게 '다른 앱 위에 그리기' 설정창에서 직접 허용받아야 합니다.]({{ site.baseurl }}/images/ii392AL6Dc.jpeg) system\_window\_alert는 다른 권한들과 다르게 '다른 앱 위에 그리기' 설정창에서 직접 허용받아야 합니다.</caption>

'다른 앱 위에 그리기' 권한을 사용할 수 있는지 여부는 [Settings.canDrawOverlays()](http://developer.android.com/intl/ko/reference/android/provider/Settings.html#canDrawOverlays(android.content.Context))를 이용해 알 수 있습니다. 하지만 아쉽게도 system\_window\_alert는 다른 권한들처럼 [onRequestPermissionsResult()](http://developer.android.com/intl/ko/reference/android/support/v4/app/ActivityCompat.OnRequestPermissionsResultCallback.html#onRequestPermissionsResult(int, java.lang.String[], int[]))으로 사용자가 권한을 허용/거부한 결과값을 알수 없습니다. 그래서 저희는 위 코드에서도 보이듯이 [startActivityForResult()](http://developer.android.com/intl/ko/reference/android/app/Activity.html#startActivityForResult(android.content.Intent, int))로 요청하여 [onActivityResult()](http://developer.android.com/intl/ko/reference/android/app/Activity.html#onActivityResult(int, int, android.content.Intent))에서 결과값을 받아 작업을 실행하였습니다.

Expand Down Expand Up @@ -308,7 +308,7 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) {

### **최초의 마시맬로우 기기, 넥서스 5x만의 이슈**

<caption id="attachment\_268" align="aligncenter" width="287">[![image00]({{ site.baseurl }}/images/EiKh8CHhDy.png)](https://blog.dramancompany.com/wp-content/uploads/2015/11/image00.png) 넥서스 5x. 필자가 사용하고 있는 폰 입니다.</caption>
<caption id="attachment\_268" align="aligncenter" width="287">![image00]({{ site.baseurl }}/images/EiKh8CHhDy.png) 넥서스 5x. 필자가 사용하고 있는 폰 입니다.</caption>

### 1\. 전화번호가 국제번호로 변경되어서 옵니다

Expand All @@ -326,7 +326,7 @@ public void onActivityResult(int requestCode, int resultCode, Intent data) {

테스트를 할 때에는 권한을 자주 껐다 키면서 다양한 경우를 빠르게 확인해야 합니다. 때문에 설정창과 앱을 동시에 켜놓고 스택창을 통해 넘나들면서 앱을 실행합니다. 하지만 설정창에서 명시적으로 권한을 거부한 후 앱으로 돌아오면, 당시에 가장 상단으로 나와있던 Activity가 onCreate()부터 다시 실행됩니다. 이 말은, 한 Activity에서 여러 Fragment를 바꿔가며 사용하는 경우에는, 첫 Fragment로 돌아간다는 것입니다. 일반적인 유저가 겪기는 힘든 케이스지만, 테스트 중에는 우리를 매우 힘들게 했던 현상 중 하나였습니다.

<caption id="attachment\_234" align="aligncenter" width="233">[![스택창에서 설정을 끄고 다시 돌아가면 Activity가 재생성된다.]({{ site.baseurl }}/images/DGUHqVtlQo.jpeg)](https://blog.dramancompany.com/wp-content/uploads/2015/11/스택창.jpeg) 스택창에서 설정을 끄고 돌아가면 Activity가 재생성 됩니다. 이 현상은 테스트를 적지 않게 방해합니다.</caption>
<caption id="attachment\_234" align="aligncenter" width="233">![스택창에서 설정을 끄고 다시 돌아가면 Activity가 재생성된다.]({{ site.baseurl }}/images/DGUHqVtlQo.jpeg) 스택창에서 설정을 끄고 돌아가면 Activity가 재생성 됩니다. 이 현상은 테스트를 적지 않게 방해합니다.</caption>

## **마무리**

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ date: "2015-12-04"

# **Electron**

# [![Electron]({{ site.baseurl }}/images/E62En13yxt.png)](https://blog.dramancompany.com/wp-content/uploads/2015/11/스크린샷-2015-11-16-오후-4.42.42.png)
# ![Electron]({{ site.baseurl }}/images/E62En13yxt.png)

[Electron](http://electron.atom.io/)[Chromium](https://www.chromium.org/)[Node.js](https://nodejs.org)를 이용하여 데스크톱 앱을 HTML, CSS, JavaScript로 쉽게 만들 수 있게 해주는 프레임워크입니다. GitHub에서 Atom editor를 만들기 위해서 시작된 프로젝트로 원래 이름은 Atom Shell이었다가 Electon으로 이름이 바뀌었습니다. 앞서 말씀드린 것과 같이 Electon을 이용하면 쉽게 cross-platform 앱을 개발할 수 있습니다.  또한 웹 개발자분들도 익숙한 언어와 코드를 재사용하여 쉽게 데스크톱 앱을 개발할 수 있습니다.

Expand All @@ -26,15 +26,15 @@ date: "2015-12-04"

#### Electron으로 만들어진 앱들

[![스크린샷 2015-11-16 오후 4.48.30]({{ site.baseurl }}/images/vzNrP9v0w8.png)](https://blog.dramancompany.com/wp-content/uploads/2015/11/스크린샷-2015-11-16-오후-4.48.30.png)
![스크린샷 2015-11-16 오후 4.48.30]({{ site.baseurl }}/images/vzNrP9v0w8.png)

[여기](http://electron.atom.io/#built-on-electron)를 확인해보시면 Electron을 이용하여 만들어진 앱들이 나와 있습니다. 아마 제일 앞의 세 개가 낯익으실 텐데, GitHub의 text editor인 Atom, Slack Technologies의 협업 메신저인 Slack, MS의 Visual Studio Code가 있습니다. 세 가지 앱 모두 제가 사용을 하는 앱이고(Atom과 Slack은 컴퓨터가 켜져 있는 시간의 99%) Mac과 Windows 모두 그 퀄리티에 만족을 하면서 사용하고 있었기 때문에 Electon으로도 충분히 좋은 앱을 만들 수 있다고 판단했습니다.

#### Squirrel 인스톨러



[![5743792]({{ site.baseurl }}/images/6YWIILjtjG.png)](https://blog.dramancompany.com/wp-content/uploads/2015/11/5743792.png)
![5743792]({{ site.baseurl }}/images/6YWIILjtjG.png)

Slack이나 Atom을 Windows 환경에서 인스톨러를 실행할 경우 기존의 '다음', '다음' 그리고 '다음'의 과정 없이 로딩 이미지가 잠깐 뜨다가 바로 앱이 실행됩니다. 그리고 업데이트도 Chrome처럼 언제 일어났는지도 눈치챌 수 없을 정도로 자연스럽게 일어납니다. 이는 [Squirrel 인스톨러](https://github.com/Squirrel)가 자동으로 해주는 부분입니다. 꼭 Squirrel 인스톨러를 사용해야 하는 것은 아니지만, Slack이나 Atom 같은 경우 Squirrel 인스톨러를 사용하여 만들었고 이들이 주장하는 "인스톨과 업데이트는 간단해야 한다"가 제일 만족스러운 부분이었습니다. 정말 인스톨러나 업데이터를 만드는데 신경을 거의 쓰지 않아도 됩니다(한번 이해만 한다면..).

Expand All @@ -48,7 +48,7 @@ Slack이나 Atom을 Windows 환경에서 인스톨러를 실행할 경우 기존

공식 홈페이지에 나와 있는 [튜토리얼](https://github.com/atom/electron/tree/master/docs-translations/ko-KR)이 잘 되어있다고 생각하기 때문에 이 글에서는 개발 방법에 대한 얘기는 별도로 다루지 않도록 하겠습니다. 그보다 큰 그림을 이해하기 위한 구조를 소개해드리겠습니다.

[![스크린샷 2015-11-16 오후 4.17.55]({{ site.baseurl }}/images/yO1l9h0trE.png)](https://blog.dramancompany.com/wp-content/uploads/2015/11/스크린샷-2015-11-16-오후-4.17.55.png) 크게 두 가지 프로세스가 존재합니다. Renderer 프로세스는 Chromium 기반으로 HTML, CSS, JavaScript를 이용하여 웹 페이지를 만들듯 view를 구성합니다. Main 프로세스는 Node.js 기반으로 일반적인 Node application이라고 생각하시면 되겠습니다. 모든 node 모듈들을 가져다 쓸 수 있습니다. 그리고 각 프로세스마다 electron 앱에 접근해서 사용할 수 있게 만든 electon에서 제공되는 API들이 담긴 모듈들이 있습니다. 그리고 두 process 사이를 통신할 수 있게 해주는 ipc와 remote module이 존재합니다. 웹 개발자는 원래 front-end를 개발하던 것과 같이 Renderer 프로세스 쪽을 개발하고 back-end를 Node.js로 개발하듯 Main 프로세스 쪽을 개발하면 됩니다. 그때그때 필요한 Electron의 API만 찾아 쓰면 기존의 웹 개발하던 것과 차이가 거의 없습니다.
![스크린샷 2015-11-16 오후 4.17.55]({{ site.baseurl }}/images/yO1l9h0trE.png) 크게 두 가지 프로세스가 존재합니다. Renderer 프로세스는 Chromium 기반으로 HTML, CSS, JavaScript를 이용하여 웹 페이지를 만들듯 view를 구성합니다. Main 프로세스는 Node.js 기반으로 일반적인 Node application이라고 생각하시면 되겠습니다. 모든 node 모듈들을 가져다 쓸 수 있습니다. 그리고 각 프로세스마다 electron 앱에 접근해서 사용할 수 있게 만든 electon에서 제공되는 API들이 담긴 모듈들이 있습니다. 그리고 두 process 사이를 통신할 수 있게 해주는 ipc와 remote module이 존재합니다. 웹 개발자는 원래 front-end를 개발하던 것과 같이 Renderer 프로세스 쪽을 개발하고 back-end를 Node.js로 개발하듯 Main 프로세스 쪽을 개발하면 됩니다. 그때그때 필요한 Electron의 API만 찾아 쓰면 기존의 웹 개발하던 것과 차이가 거의 없습니다.



Expand Down
Loading

0 comments on commit a911d18

Please sign in to comment.