스토리 홈

인터뷰

피드

뉴스

조회수 1785

서비스 중단 없이 Amazon EKS로 옮긴 이야기 - VCNC Engineering Blog

Amazon EKS는 AWS의 관리형 Kubernetes 서비스입니다. 2017년 11월 AWS re:Invent에서 프리뷰 버전이 출시되었고, 2018년 6월에 상용(GA) 버전이 미국 리전에만 출시되었습니다. 그래서 서울 리전을 사용해야 했던 타다 프로젝트에서는 Kubernetes 클러스터를 직접 kops로 설치하여 운영할 수 밖에 없었습니다.2019년 1월, 오랜 기다림 끝에 드디어 서울 리전에 EKS가 출시되어 기쁜 마음으로 EKS로 옮겨가게 되었습니다. 이 글에서는 직접 구축한 클러스터 대비 EKS의 특징에는 어떤 것이 있는지 살펴보고, 서비스 중단 없이 EKS로 옮기기 위한 전략을 공유하고자 합니다.EKS 서울 리전 출시를 염원하던 한국인(?)들EKS는 뭐가 다른가요?AWS에서 마스터 노드를 관리해줍니다.Kubernetes 클러스터는 마스터 노드와 워커 노드로 구성되어 있습니다. EKS는 이 중에서 마스터 노드를 직접 EC2로 띄울 필요 없이 AWS에서 관리해주는 서비스입니다. RDS를 사용할 때 직접 DB 인스턴스를 생성하지 않는 것과 비슷합니다. 별도의 설정 없이도 알아서 여러 가용 영역에 마스터 노드를 실행하여 HA(고가용성) 구성을 해주고, 비정상 마스터 노드를 자동으로 감지하고 교체합니다. 또한 자동화된 버전 업그레이드 및 패치를 지원합니다. EKS를 사용하더라도 워커 노드는 직접 EC2 인스턴스를 생성·관리해야 합니다.EKS 클러스터의 요금은 2019년 2월 현재 시간당 $0.20입니다. 타다에서는 기존에 t2.medium 3대를 마스터 노드로 사용하고 있었기 때문에 관리를 직접 하지 않는 대신 비용이 약간 증가하게 되었습니다.AWS IAM 기반 인증을 사용합니다.VCNC에서는 기존에 Kubernetes API에 접속할 때 가장 간단한 basic auth 인증 방식을 사용했습니다. 그 대신 외부 네트워크에서 접근할 수 없게 해두고 필요한 경우 Bastion 호스트를 통해 SSH 터널링하여 접속했습니다.EKS의 API 서버는 인터넷에 노출되어 있으며, 별도로 네트워크 접근 제한 설정을 할 수 없고 AWS IAM으로 사용자를 인증합니다. (물론 공개망에 노출되어 있으면 Kubernetes API 서버에 보안 취약점이 발견되는 경우 안전하지 않을 수 있는 단점이 있습니다. 앞으로 PrivateLink가 지원되면 해결될 것입니다.)IAM은 인증에만 사용되고, 특정 작업을 할 수 있는 권한은 Kubernetes 기본 RBAC로 관리됩니다. IAM 사용자나 역할을 RBAC 그룹에 매핑할 수 있습니다.EKS 인증 흐름도워커 노드 당 Pod 개수 제한이 있습니다.예를 들어 c5.large 인스턴스에는 29개의 Pod을 띄울 수 있습니다. (표 참고) 그러므로 기존 클러스터에서 노드 당 Pod이 몇 개나 되는지 미리 확인할 필요가 있습니다. 왜 이런 제약이 있을까요?Kubernetes에서는 네트워킹 플러그인으로 Pod 사이에 네트워크 통신하는 방식을 다양하게 설정할 수 있습니다. EKS는 기본적으로 amazon-vpc-cni-k8s를 사용합니다. 이 네트워킹 플러그인은 VPC 상에서 유효한 실제 IP를 Pod에 할당합니다.그러기 위해서는 하나의 EC2 인스턴스에서 여러 개의 IP를 받아와야 하고, 이를 위해 추가적인 네트워크 인터페이스(ENI)를 붙입니다. 그런데 인스턴스 타입에 따라 추가할 수 있는 ENI 수와 ENI 당 IP 수에 제한이 있습니다. 따라서 이 제한이 워커 노드 하나에 띄울 수 있는 Pod 개수 제한이 됩니다.flannel 등 오버레이 네트워크 기반의 다른 네트워크 플러그인을 사용하면 이러한 제약을 피할 수 있습니다. 하지만 EKS에서 기본 제공하는 방법을 그대로 사용하는 것이 좋고, Pod을 엄청나게 많이 띄워야 하는 상황이 아니어서 시도하지 않았습니다.EKS로 중단 없이 넘어가기개요타다의 Kubernetes 클러스터에서 돌아가는 서비스들은 모두 영속적인(persistent) 상태를 가지고 있지 않습니다. 따라서 EKS 클러스터 위에 동일한 서비스를 띄우고 외부 트래픽을 옮겨주기만 하면 특별히 데이터를 옮기지 않고도 이전이 가능했습니다. 또한 거의 대부분의 Kubernetes 리소스는 Helm 차트로 생성한 것이기 때문에 새로운 클러스터에 동일한 서비스를 띄우는 작업도 쉽게 할 수 있었습니다.이전 작업은 다음과 같은 순서로 진행했습니다.EKS 클러스터를 만들고 워커 노드를 생성모든 서비스 다시 설치트래픽을 새 클러스터로 보내기이전 클러스터 제거EKS 클러스터를 만들고 워커 노드를 생성타다의 AWS 환경은 거의 모두 Terraform으로 정의되어 관리되고 있습니다. EKS 클러스터와 워커 노드도 HashiCorp Learn의 문서를 참고해서 Terraform으로 생성했습니다. 해당 문서에 설명이 잘 되어 있어서 거의 그대로 따라할 수 있었습니다.EKS 클러스터 설정은 재사용 가능하도록 Terraform 모듈로 만들었습니다. 덕분에 테스트용 클러스터와 실서비스용 클러스터를 동일한 모듈로 변수만 바꿔서 설정할 수 있었습니다.모든 서비스 다시 설치타다의 Kubernetes 리소스는 Helm 차트로 관리되고 있어서 기존 차트를 거의 그대로 설치할 수 있었습니다. 사용자에게 직접적인 영향을 덜 주는 워커 서비스를 먼저 설치해서 제대로 동작하는 것을 확인한 뒤, 마지막으로 프론트엔드 서비스를 설치하였습니다.트래픽을 새 클러스터로 보내기타다의 모든 트래픽은 NLB로 들어온 뒤 NGINX를 거쳐 다시 적절한 Pod에 라우팅됩니다. 그러므로 타다의 모든 도메인은 NLB를 가리키고 있습니다.타다는 Route 53을 DNS 서버로 사용합니다. Route 53에는 가중치 기반 DNS 레코드를 설정할 수 있습니다. 이를 이용하여 일부 트래픽만 새 클러스터의 NLB로 보낼 수 있습니다. 처음에는 아주 적은 트래픽만 새 클러스터로 보내다가 문제 없이 작동하는 것을 확인한 다음 조금씩 트래픽을 늘려나갔습니다.DNS 가중치 설정으로 일부 트래픽만 새 클러스터의 NLB로 보낼 수 있습니다.DNS 설정에서 이전 클러스터로 가는 레코드를 완전히 제거한 뒤에도, DNS 캐시 등의 이유로 일부 클라이언트가 이전 클러스터에 접속할 수도 있습니다. 따라서, 이전 클러스터 NLB에 새 클러스터의 노드들을 붙여서 아직 DNS를 따라오지 못한 클라이언트들의 요청을 처리하였습니다.이전 클러스터 제거가장 신나면서 조심해야 하는 작업입니다. 먼저 이전 클러스터로 트래픽이 전혀 들어오지 않는 것을 확인하였습니다. 그 다음에는 Terraform에서 이전 클러스터 리소스에 대한 참조를 제거한 뒤, terraform destroy 명령으로 이전 클러스터와 관련된 리소스를 한번에 삭제할 수 있었습니다.맺음말Kubernetes는 깔끔한 추상화를 통해 컨테이너 기반 배포를 간단하게 만들어주지만, 직접 클러스터를 관리해야 하는 부담이 있었습니다. Amazon EKS는 이러한 부담을 많이 덜어주는 좋은 서비스입니다. 앞으로 EKS의 무궁한 발전을 기원합니다.VCNC에는 오랫동안 쌓아온 AWS 인프라 운영 경험이 있습니다. 타다에서는 그동안의 경험과 비교적 최근에 시작한 프로젝트의 이점을 살려 컨테이너, Infrastructure as Code 등 업계 표준의 인프라 관리 방법론을 적극 도입하려고 노력하고 있습니다. 앞으로도 이에 관해 기술 블로그에 더 자세히 공유할 계획이니 기대해주세요. 또한 저희와 함께 안정적인 서비스를 만들어나갈 좋은 분들을 기다리고 있으니 VCNC 채용에도 많은 관심 부탁드립니다.
조회수 1172

AWS Batch 사용하기

OverviewAWS Batch는 배치 컴퓨팅 작업을 효율적으로 실행할 수 있게 도와줍니다. 배치 작업량과 리소스 요청을 기반으로 최적의 리소스 수량 및 인스턴스 유형을 동적으로 프로비져닝합니다. AWS Batch에서는 별도의 관리가 필요 없기 때문에 문제 해결에 집중할 수 있습니다. 별도의 추가 비용은 없습니다. 배치 작업을 저장 또는 실행할 목적으로 생성된 AWS 리소스(인스턴스 등)에 대해서만 비용을 지불하면 됩니다. 이번 포스팅에서는 간단한 튜토리얼로 AWS Batch 사용 방법을 크게 11개의 Step으로 알아보겠습니다. 이렇게 진행하겠습니다.AWS에서 제공하는 Dockerfile, fetch&run 스크립트 및 myjob.sh 다운로드Dockerfile를 이용하여 fetch&run 스크립트를 포함한 Docker 이미지 생성생성된 Docker 이미지를 ECR(Amazon Elastic Container Registry)로 푸쉬간단한 샘플 스크립트(myjob.sh)를 S3에 업로드IAM에 S3를 접속 할 수 있는 ECS Task role 등록Compute environments 생성Job queues 생성ECR을 이용하여 Job definition 생성Submit job을 통해 S3에 저장된 작업 스크립트(myjob.sh)를 실행하기결과 확인 STEP1. AWS에서 제공하는 Dockerfile, fetch&run 스크립트 및 myjob.sh 다운로드AWS Batch helpers페이지에 접속합니다.    2. /fetch-and-run/에서 Dockerfile, fetchandrun.sh, myjob.sh 다운로드합니다.STEP2. Dockerfile을 이용하여 fetch&run 스크립트를 포함한 Docker 이미지 생성Dockerfile을 이용해서 Docker 이미지를 빌드합니다.잠시 Dockerfile의 내용을 살펴보겠습니다.FROM amazonlinux:latestDocker 공식 Repository에 있는 amazonlinux 의 lastest 버젼으로 빌드RUN yum -y install which unzip aws-cliRUN을 통해 이미지 빌드 시에 yum -y install which unzip aws-cli를 실행ADD fetch_and_run.sh /usr/local/bin/fetch_and_run.shADD를 통해 Dockerfile과 같은 디렉토리에 있는 fetch_and_run.sh를 /usr/local/bin/fetch_and_run.sh에 복사 WORKDIR /tmp컨테이너가 동작할 때 /tmp를 기본 디렉토리로 설정USER nobody컨테이너 실행 시 기본 유저 설정 ENTRYPOINT [“/usr/local/bin/fetch_and_run.sh”]컨테이너 실행 시 /usr/local/bin/fetch_and_run.sh를 call shell에 docker 명령을 통해 이미지 생성shell : docker build -t fetch_and_run . 실행하면 아래와 같은 결과가 출력됩니다.[ec2-user@AWS_BRANDI_STG fetch-and-run]$ docker build -t fetch_and_run . Sending build context to Docker daemon 8.192kB Step 1/6 : FROM amazonlinux:latest latest: Pulling from library/amazonlinux 4b92325dc37b: Pull complete Digest: sha256:9ee13e494b762db41b9db92a200f6784b78da5ac3b0f974fb1c38feb7f636474 Status: Downloaded newer image for amazonlinux:latest ---> 81bb3e78db3d Step 2/6 : RUN yum -y install which unzip aws-cli ---> Running in 1f5293a2294d Loaded plugins: ovl, priorities Resolving Dependencies --> Running transaction check ---> Package aws-cli.noarch 0:1.14.9-1.48.amzn1 will be installed --> Processing Dependency: python27-jmespath = 0.9.2 for package: aws-cli-1.14.9-1.48.amzn1.noarch --> Processing Dependency: python27-botocore = 1.8.13 for package: aws-cli-1.14.9-1.48.amzn1.noarch --> Processing Dependency: python27-rsa >= 3.1.2-4.7 for package: aws-cli-1.14.9-1.48.amzn1.noarch --> Processing Dependency: python27-futures >= 2.2.0 for package: aws-cli-1.14.9-1.48.amzn1.noarch --> Processing Dependency: python27-docutils >= 0.10 for package: aws-cli-1.14.9-1.48.amzn1.noarch --> Processing Dependency: python27-colorama >= 0.2.5 for package: aws-cli-1.14.9-1.48.amzn1.noarch --> Processing Dependency: python27-PyYAML >= 3.10 for package: aws-cli-1.14.9-1.48.amzn1.noarch --> Processing Dependency: groff for package: aws-cli-1.14.9-1.48.amzn1.noarch --> Processing Dependency: /etc/mime.types for package: aws-cli-1.14.9-1.48.amzn1.noarch ---> Package unzip.x86_64 0:6.0-4.10.amzn1 will be installed ---> Package which.x86_64 0:2.19-6.10.amzn1 will be installed --> Running transaction check ---> Package groff.x86_64 0:1.22.2-8.11.amzn1 will be installed --> Processing Dependency: groff-base = 1.22.2-8.11.amzn1 for package: groff-1.22.2-8.11.amzn1.x86_64 ---> Package mailcap.noarch 0:2.1.31-2.7.amzn1 will be installed ---> Package python27-PyYAML.x86_64 0:3.10-3.10.amzn1 will be installed --> Processing Dependency: libyaml-0.so.2()(64bit) for package: python27-PyYAML-3.10-3.10.amzn1.x86_64 ---> Package python27-botocore.noarch 0:1.8.13-1.66.amzn1 will be installed --> Processing Dependency: python27-dateutil >= 2.1 for package: python27-botocore-1.8.13-1.66.amzn1.noarch ---> Package python27-colorama.noarch 0:0.2.5-1.7.amzn1 will be installed ---> Package python27-docutils.noarch 0:0.11-1.15.amzn1 will be installed --> Processing Dependency: python27-imaging for package: python27-docutils-0.11-1.15.amzn1.noarch ---> Package python27-futures.noarch 0:3.0.3-1.3.amzn1 will be installed ---> Package python27-jmespath.noarch 0:0.9.2-1.12.amzn1 will be installed --> Processing Dependency: python27-ply >= 3.4 for package: python27-jmespath-0.9.2-1.12.amzn1.noarch ---> Package python27-rsa.noarch 0:3.4.1-1.8.amzn1 will be installed --> Processing Dependency: python27-pyasn1 >= 0.1.3 for package: python27-rsa-3.4.1-1.8.amzn1.noarch --> Processing Dependency: python27-setuptools for package: python27-rsa-3.4.1-1.8.amzn1.noarch --> Running transaction check ---> Package groff-base.x86_64 0:1.22.2-8.11.amzn1 will be installed ---> Package libyaml.x86_64 0:0.1.6-6.7.amzn1 will be installed ---> Package python27-dateutil.noarch 0:2.1-1.3.amzn1 will be installed --> Processing Dependency: python27-six for package: python27-dateutil-2.1-1.3.amzn1.noarch ---> Package python27-imaging.x86_64 0:1.1.6-19.9.amzn1 will be installed --> Processing Dependency: libjpeg.so.62(LIBJPEG_6.2)(64bit) for package: python27-imaging-1.1.6-19.9.amzn1.x86_64 --> Processing Dependency: libjpeg.so.62()(64bit) for package: python27-imaging-1.1.6-19.9.amzn1.x86_64 --> Processing Dependency: libfreetype.so.6()(64bit) for package: python27-imaging-1.1.6-19.9.amzn1.x86_64 ---> Package python27-ply.noarch 0:3.4-3.12.amzn1 will be installed ---> Package python27-pyasn1.noarch 0:0.1.7-2.9.amzn1 will be installed ---> Package python27-setuptools.noarch 0:36.2.7-1.33.amzn1 will be installed --> Processing Dependency: python27-backports-ssl_match_hostname for package: python27-setuptools-36.2.7-1.33.amzn1.noarch --> Running transaction check ---> Package freetype.x86_64 0:2.3.11-15.14.amzn1 will be installed ---> Package libjpeg-turbo.x86_64 0:1.2.90-5.14.amzn1 will be installed ---> Package python27-backports-ssl_match_hostname.noarch 0:3.4.0.2-1.12.amzn1 will be installed --> Processing Dependency: python27-backports for package: python27-backports-ssl_match_hostname-3.4.0.2-1.12.amzn1.noarch ---> Package python27-six.noarch 0:1.8.0-1.23.amzn1 will be installed --> Running transaction check ---> Package python27-backports.x86_64 0:1.0-3.14.amzn1 will be installed --> Finished Dependency Resolution Dependencies Resolved ================================================================================ Package                              Arch   Version            Repository                                                                           Size ================================================================================ Installing:  aws-cli                              noarch 1.14.9-1.48.amzn1  amzn-main 1.2 M  unzip                                x86_64 6.0-4.10.amzn1     amzn-main 201 k  which                                x86_64 2.19-6.10.amzn1    amzn-main  41 k  Installing for dependencies:  freetype                             x86_64 2.3.11-15.14.amzn1 amzn-main 398 k  groff                                x86_64 1.22.2-8.11.amzn1  amzn-main 1.3 M  groff-base                           x86_64 1.22.2-8.11.amzn1  amzn-main 1.1 M  libjpeg-turbo                        x86_64 1.2.90-5.14.amzn1  amzn-main 144 k  libyaml                              x86_64 0.1.6-6.7.amzn1    amzn-main  59 k  mailcap                              noarch 2.1.31-2.7.amzn1   amzn-main  27 k  python27-PyYAML                      x86_64 3.10-3.10.amzn1    amzn-main 186 k  python27-backports                   x86_64 1.0-3.14.amzn1     amzn-main 5.0 k  python27-backports-ssl_match_hostname                                       noarch 3.4.0.2-1.12.amzn1 amzn-main  12 k  python27-botocore                    noarch 1.8.13-1.66.amzn1  amzn-main 4.1 M  python27-colorama                    noarch 0.2.5-1.7.amzn1    amzn-main  23 k  python27-dateutil                    noarch 2.1-1.3.amzn1      amzn-main  92 k  python27-docutils                    noarch 0.11-1.15.amzn1    amzn-main 1.9 M  python27-futures                     noarch 3.0.3-1.3.amzn1    amzn-main  30 k  python27-imaging                     x86_64 1.1.6-19.9.amzn1   amzn-main 428 k  python27-jmespath                    noarch 0.9.2-1.12.amzn1   amzn-main  46 k  python27-ply                         noarch 3.4-3.12.amzn1     amzn-main 158 k  python27-pyasn1                      noarch 0.1.7-2.9.amzn1    amzn-main 112 k  python27-rsa                         noarch 3.4.1-1.8.amzn1    amzn-main  80 k  python27-setuptools                  noarch 36.2.7-1.33.amzn1  amzn-main 672 k  python27-six                         noarch 1.8.0-1.23.amzn1   amzn-main  31 k Transaction Summary ================================================================================ Install 3 Packages (+21 Dependent packages) Total download size: 12 M Installed size: 51 M Downloading packages: -------------------------------------------------------------------------------- Total 1.0 MB/s | 12 MB 00:12 Running transaction check Running transaction test Transaction test succeeded  Running transaction   Installing : python27-backports-1.0-3.14.amzn1.x86_64                    1/24   Installing : python27-backports-ssl_match_hostname-3.4.0.2-1.12.amzn1    2/24   Installing : python27-setuptools-36.2.7-1.33.amzn1.noarch                3/24   Installing : python27-colorama-0.2.5-1.7.amzn1.noarch                    4/24   Installing : freetype-2.3.11-15.14.amzn1.x86_64                          5/24   Installing : libyaml-0.1.6-6.7.amzn1.x86_64                              6/24   Installing : python27-PyYAML-3.10-3.10.amzn1.x86_64                      7/24   Installing : mailcap-2.1.31-2.7.amzn1.noarch                             8/24   Installing : python27-ply-3.4-3.12.amzn1.noarch                          9/24   Installing : python27-jmespath-0.9.2-1.12.amzn1.noarch                  10/24   Installing : python27-futures-3.0.3-1.3.amzn1.noarch                    11/24   Installing : python27-six-1.8.0-1.23.amzn1.noarch                       12/24   Installing : python27-dateutil-2.1-1.3.amzn1.noarch                     13/24   Installing : groff-base-1.22.2-8.11.amzn1.x86_64                        14/24   Installing : groff-1.22.2-8.11.amzn1.x86_64                             15/24   Installing : python27-pyasn1-0.1.7-2.9.amzn1.noarch                     16/24   Installing : python27-rsa-3.4.1-1.8.amzn1.noarch                        17/24   Installing : libjpeg-turbo-1.2.90-5.14.amzn1.x86_64                     18/24   Installing : python27-imaging-1.1.6-19.9.amzn1.x86_64                   19/24   Installing : python27-docutils-0.11-1.15.amzn1.noarch                   20/24   Installing : python27-botocore-1.8.13-1.66.amzn1.noarch                 21/24   Installing : aws-cli-1.14.9-1.48.amzn1.noarch                           22/24   Installing : which-2.19-6.10.amzn1.x86_64                               23/24   Installing : unzip-6.0-4.10.amzn1.x86_64                                24/24   Verifying  : libjpeg-turbo-1.2.90-5.14.amzn1.x86_64                      1/24   Verifying  : groff-1.22.2-8.11.amzn1.x86_64                              2/24   Verifying  : unzip-6.0-4.10.amzn1.x86_64                                 3/24   Verifying  : python27-pyasn1-0.1.7-2.9.amzn1.noarch                      4/24   Verifying  : groff-base-1.22.2-8.11.amzn1.x86_64                         5/24   Verifying  : aws-cli-1.14.9-1.48.amzn1.noarch                            6/24   Verifying  : python27-six-1.8.0-1.23.amzn1.noarch                        7/24   Verifying  : python27-dateutil-2.1-1.3.amzn1.noarch                      8/24   Verifying  : python27-docutils-0.11-1.15.amzn1.noarch                    9/24   Verifying  : python27-PyYAML-3.10-3.10.amzn1.x86_64                     10/24   Verifying  : python27-botocore-1.8.13-1.66.amzn1.noarch                 11/24   Verifying  : python27-futures-3.0.3-1.3.amzn1.noarch                    12/24   Verifying  : python27-ply-3.4-3.12.amzn1.noarch                         13/24   Verifying  : python27-jmespath-0.9.2-1.12.amzn1.noarch                  14/24   Verifying  : mailcap-2.1.31-2.7.amzn1.noarch                            15/24   Verifying  : python27-backports-ssl_match_hostname-3.4.0.2-1.12.amzn1   16/24   Verifying  : libyaml-0.1.6-6.7.amzn1.x86_64                             17/24   Verifying  : python27-rsa-3.4.1-1.8.amzn1.noarch                        18/24   Verifying  : freetype-2.3.11-15.14.amzn1.x86_64                         19/24   Verifying  : python27-colorama-0.2.5-1.7.amzn1.noarch                   20/24   Verifying  : python27-setuptools-36.2.7-1.33.amzn1.noarch               21/24   Verifying  : which-2.19-6.10.amzn1.x86_64                               22/24   Verifying  : python27-imaging-1.1.6-19.9.amzn1.x86_64                   23/24   Verifying  : python27-backports-1.0-3.14.amzn1.x86_64                   24/24 Installed:   aws-cli.noarch 0:1.14.9-1.48.amzn1        unzip.x86_64 0:6.0-4.10.amzn1   which.x86_64 0:2.19-6.10.amzn1   Dependency Installed:   freetype.x86_64 0:2.3.11-15.14.amzn1   groff.x86_64 0:1.22.2-8.11.amzn1   groff-base.x86_64 0:1.22.2-8.11.amzn1   libjpeg-turbo.x86_64 0:1.2.90-5.14.amzn1   libyaml.x86_64 0:0.1.6-6.7.amzn1   mailcap.noarch 0:2.1.31-2.7.amzn1   python27-PyYAML.x86_64 0:3.10-3.10.amzn1   python27-backports.x86_64 0:1.0-3.14.amzn1   python27-backports-ssl_match_hostname.noarch 0:3.4.0.2-1.12.amzn1   python27-botocore.noarch 0:1.8.13-1.66.amzn1   python27-colorama.noarch 0:0.2.5-1.7.amzn1   python27-dateutil.noarch 0:2.1-1.3.amzn1   python27-docutils.noarch 0:0.11-1.15.amzn1   python27-futures.noarch 0:3.0.3-1.3.amzn1   python27-imaging.x86_64 0:1.1.6-19.9.amzn1   python27-jmespath.noarch 0:0.9.2-1.12.amzn1   python27-ply.noarch 0:3.4-3.12.amzn1   python27-pyasn1.noarch 0:0.1.7-2.9.amzn1   python27-rsa.noarch 0:3.4.1-1.8.amzn1   python27-setuptools.noarch 0:36.2.7-1.33.amzn1   python27-six.noarch 0:1.8.0-1.23.amzn1   Complete! Removing intermediate container 1f5293a2294d  ---> 5502efa481ce Step 3/6 : ADD fetch_and_run.sh /usr/local/bin/fetch_and_run.sh  ---> 1b69173e586f Step 4/6 : WORKDIR /tmp Removing intermediate container a69678c65ee7  ---> 8a560dd25401 Step 5/6 : USER nobody  ---> Running in e063ac6e6fdb Removing intermediate container e063ac6e6fdb  ---> e5872fd44234 Step 6/6 : ENTRYPOINT ["/usr/local/bin/fetch_and_run.sh"]  ---> Running in e25af9aa5fdc Removing intermediate container e25af9aa5fdc  ---> dfca872de0be Successfully built dfca872de0be Successfully tagged awsbatch-fetch_and_run:latest docker images 명령으로 새로운 로컬 repository를 확인할 수 있습니다.shell : docker images [ec2-user@AWS_BRANDI_STG fetch-and-run]$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE fetch_and_run latest dfca872de0be 2 minutes ago 253MB amazonlinux              latest              81bb3e78db3d        2 weeks ago         165MB STEP3. ECR에서 repository 생성아래는 ECR 초기 화면입니다.fetch_and_run이란 이름으로 Repository 생성합니다. 3. Repository 생성이 완료되었습니다.STEP4. ECR로 빌드된 이미지를 pushECR에 docker login후 빌드된 Docker 이미지에 태그합니다. shell : aws ecr get-login --no-include-email --region ap-northeast-2 빌드된 docker 이미지에 태그하세요.shell : docker tag fetch_and_run:latest 000000000000.dkr.ecr.ap-northeast-2.amazonaws.com/fetch_and_run:latest 태그된 docker 이미지를 ECR에 push합니다.shell: docker push 000000000000.dkr.ecr.ap-northeast-2.amazonaws.com/fetch_and_rrun:latest 아래는 ECR fetch_and_run Repository에 푸쉬된 Docker 이미지입니다.STEP5. 간단한 샘플 스크립트(myjob.sh)를 S3에 업로드아래는 간단한 myjob.sh 스크립트입니다.#!/bin/bash date echo "Args: $@" env echo "This is my simple test job!." echo "jobId: $AWS_BATCH_JOB_ID" sleep $1 date echo "bye bye!!" 위의 myjob.sh를 S3에 업로드합니다.shell : aws s3 cp myjob.sh s3:///myjob.sh STEP6. IAM에 S3를 접속할 수 있는 ECS Task role 등록Role 등록 화면에서 Elastic Container Service 선택 후, Elastic Container Service Task를 선택합니다.AmazonS3ReadOnlyAccess Policy를 선택합니다.아래 이미지는 Role에 등록 하기 전 리뷰 화면입니다.Role에 AmazonS3ReadOnlyAccess가 등록된 것을 확인합니다.STEP7. Compute environments 생성AWS Batch 콘솔에서 Compute environments를 선택하고, Create environment 선택합니다.Compute environment type은 Managed와 Unmanaged 두 가지를 선택할 수 있습니다. Managed는 AWS에서 요구사항에 맞게 자원을 관리해주는 것이고, Unmanaged는 직접 자원을 관리해야 합니다. 여기서는 Managed를 선택하겠습니다.Compute environment name을 입력합니다.Service Role을 선택합니다. 기존 Role을 사용하거나 새로운 Role을 생성할 수 있습니다. 새 Role을 생성하면 필수 역할 (AWSBatchServiceRole)이 생성됩니다.Instnace Role을 선택합니다. 기존 Role을 사용하거나 새로운 Role을 생성할 수 있습니다. 새 Role을 생성하면 필수 역할(ecsInstanceRole)이 생성됩니다.EC2 key pair에서 기존 EC2 key pair를 선택합니다. 이 key pair를 사용하여 SSH로 인스턴스에 접속할 수 있지만 이번 글의 예제에서는 선택하지 않겠습니다.Configure your compute resources Provisioning Model은 On-Demand와 Spot이 있습니다. 차이점은 Amazon EC2 스팟 인스턴스를 참고해주세요. 여기서는 On-Demand를 선택합니다.Allowed instance types에서는 시작 인스턴스 유형을 선택합니다. optimal을 선택하면 Job queue의 요구에 맞는 인스턴스 유형을 (최신 C, M, R 인스턴스 패밀리 중) 자동으로 선택합니다. 여기서는 optimal을 선택하겠습니다.Minimum vCPUs는 Job queue 요구와 상관없이 Compute environments에 유지할 vCPU 최소 개수입니다. 0을 입력해주세요.Desired vCPUs는 Compute environment에서 시작할 EC2 vCPU 개수입니다. Job queue 요구가 증가하면 필요한 vCPU를 Maximum vCPUs까지 늘리고 요구가 감소하면 vCPU 수를 Minimum vCPUs까지 줄이고 인스턴스를 제거합니다. 0을 입력해주세요.Maximum vCPUs는 Job queue 요구와 상관없이 Compute environments에서 확장할 수 있는 EC2 vCPU 최대 개수입니다. 여기서는 256을 입력합니다.Enable user-specified Ami ID는 사용자 지정 AMI를 사용하는 옵션입니다. 여기서는 사용하지 않겠습니다.Networking VPC Id 인스턴스를 시작할 VPC를 선택합니다.Subnet을 선택합니다.Security groups를 선택합니다.그리고 EC2 tags를 지정하여 생성된 인스턴스가 이름을 가질 수 있게 합니다. Key : Name, Value : AWS Batch InstanceCreate을 클릭해 Compute environment를 생성합니다.아래 이미지는 생성된 Compute environment입니다.STEP8. Job queues 생성AWS Batch 콘솔에서 Job queues - Create queue를 선택합니다.Queue name을 입력합니다.Priority는 Job queue의 우선순위를 입력합니다. 우선순위가 1인 작업은 우선순위가 5인 작업보다 먼저 일정이 예약됩니다. 여기서는 5를 입력하겠습니다.Enable Job queue가 체크되어 있어야 job을 등록할 수 있습니다.Select a compute environment에서 Job queue와 연결될 Compute environment을 선택합니다. 최대 3개의 Compute environment를 선택할 수 있습니다.생성된 Job queue, Status가 VALID면 사용 가능합니다.STEP9. ECR을 이용하여 Job definition 생성AWS Batch 콘솔에서 Job definitions - Create를 선택합니다.Job definition name을 입력하고 이전 작업에서 만들 IAM Role을 선택하세요, 그리고 ECR Repository URI를 입력합니다. 000000000000.dkr.ecr.ap-northeast-2.amazonaws.com/fetch_and_runCommand 필드는 비워둡시다.vCPUs는 컨테이너를 위해 예약할 vCPU의 수, Memory(Mib)는 컨테이너에 제공할 메모리의 제한, Job attempts는 작업이 실패할 경우 다시 시도하는 최대 횟수, Execution timeout은 실행 제한 시간, Ulimits는 컨테이너에 사용할 사용자 제한 값입니다. 여기서는 vCPUs는 1, Memory(MiB)는 512, Job Attempts는 1로 설정, Execution timeout은 기본값인 100 그리고 Limits는 설정하지 않습니다.vCPUs: 컨테이너를 위해 예약할 vCPU의 개수Memory(Mib): 컨테이너에 제공할 메모리의 제한Jop attempts: 작업이 실패할 경우 다시 시도하는 최대 횟수Execution timeout: 실행 제한 시간Ulimits: 컨테이너에 사용할 사용자 제한 값User는 기본값인 nobody로 선택 후, Create job definition을 선택합니다.Job definitions에 Job definition이 생성된 것을 확인할 수 있습니다.STEP10. Submit job을 통해 S3에 저장된 작업 스크립트(myjob.sh)를 실행하기AWS Batch 콘솔에서 Jobs를 선택합니다. Job을 실행할 Queue를 선택하고 Submit job을 선택합니다.Job run-time1)Job name을 입력합니다.2)Job definition을 선택합니다.3)실행될 Job queue를 선택합니다.Environment Job Type을 선택하는 부분에서는 Single을 선택합니다. Array 작업에 대한 자세한 내용은 어레이 작업 페이지를 참고해주세요.Job depends on은 선택하지 않습니다.자세한 내용은 작업 종속성 페이지를 참고해주세요.Environment Command에서 컨테이너에 전달할 명령을 입력합니다. 여기서는 [“myjob.sh”, “30”] 를 입력해주세요. vCPUs, Memory, Job attempts와 Execution timeout은 job definition에 설정된 값을 가져옵니다. 이 Job에 대한 설정도 가능합니다.Parameters를 통해 job을 제출할 때 기본 작업 정의 파라미터를 재정의 할 수 있습니다. Parameters에 대한 자세한 내용은 작업 정의 파라미터 페이지를 참고해주세요.Environment variables는 job의 컨테이너에 환경 변수를 지정할 수 있습니다. 여기서 주의할 점은 Key를 AWS_BATCH로 시작하면 안 된다는 것입니다. AWS Batch에 예약된 변수입니다.Key=BATCH_FILE_TYPE, Value=script Key=BATCH_FILE_S3_URL, Value=s3:///myjob.shSubmit job을 선택합니다.Job이 Submitted 된 화면입니다.Dashboard를 보시면 Runnable 상태로 대기 중인 것을 확인할 수 있습니다.STEP11. 결과 확인CloudWatch > Log Groups > /aws/batch/job에서 실행 로그를 확인할 수 있습니다.Conclusion간단한 튜토리얼로 AWS Batch를 설정하고 실행하는 방법을 알아봤습니다.(참 쉽죠?) 다음 글에서는 AWS Batch의 Array 또는 Job depends on등의 확장된 기능들을 살펴보겠습니다. 참고1) AWS Batch – 쉽고 효율적인 배치 컴퓨팅 기능 – AWS2) AWS Batch 시작하기 - AWS Batch3) Amazon ECR의 도커 기본 사항 - Amazon ECR글윤석호 이사 | 브랜디 [email protected]브랜디, 오직 예쁜 옷만#브랜디 #개발문화 #개발팀 #업무환경 #인사이트 #경험공유
조회수 855

로봇 택시가 산업 지형을 바꾼다

로봇 택시가 산업 지형을 바꾼다"자율 주행 전기차의 등장으로 유가가 배럴당 25달러까지 떨어지고, 새로운 세계 질서가 도래할 것이다."'에너지 혁명 2030' 의 저자로 2015년 한국을 방문한 적 있는 토니 세바 스탠포드대 교수(RethinkX의 공동 설립자)가 최근 미국 CNBC와 인터뷰에서 "기름 수요가 2020년~2021년 사이 1백만 배럴로 꼭지를 찍은 뒤 10년 내(2030년경)로 70만 배럴까지 줄어들면서 유가가 하락세를 면치 못할 것”이라며 이같이 예견했다.점차 많은 사람들이 공유경제의 축으로 자율 주행 전기차를 사용하게 되면서 ▽오일 회사는 생존이 어렵게 되고 ▽심해, 세일가스업체와 정유 파이프라인 회사들도 문을 닫게 될 것이라는 게 그의 예측이다.차량도 소유의 대상에서 서비스의 대상, 이른바 TAAS (transport as a service) 로 바뀐다. 차량을 더 이상 구입하지 않고, 편리하게 앱으로 로봇 택시를 호출해 이용하면 그만이다. 자율 주행 전기차의 가격도 싸지면서, 전기차 이용이 소유에 비해 10배 정도 저렴해질 것이라는 것.  경제학자인 그의 섬뜩한 전망은 계속된다. 급속한 기술의 진보로 인해 값비싼 정유회사나, 적응력이 떨어지는 카 메이커(의 주식)가 매력이 없어지며, 차량과 관련된 직업 중에서 차 딜러도 2024년까지 사라질 것이라는 예상이다.뿐만 아니라, 주차공간의 80% 이상이 쓸모없게 되고, (자동차)보험의 비용도 급격하게 떨어지기 때문에 보험회사도 설 땅이 좁아진다는 것.이 같은 그의 전망이 혼자만의 견해는 아니지만,  다른 사람들은 이런 변화에 훨씬 많은 시간이 걸리고, 그렇게 극적이지도 않을 거라고 내다본다.반대로 그는 차량 관련 지출이 줄면서 가계 소비가 늘어나 경제성장을 촉진할 것이라고 예상했다. 아울러 차세대 차의 개발과 관련된 차 운영체제, 컴퓨터 플랫폼, 배터리, 지도 소프트웨어 회사들을 눈여겨 보라고 조언했다.세바 교수의  유가 하락 전망이  결코 급진적인 것은 아니다.  유가는 WTI(서부 텍사스중질유)기준으로 2016년 2월에  배럴당 20달러대 중반까지 급락한 바 있다.  6월 14일 현재는  40달러대 중반에 머물러 있다.다만, 차량이 소유의 대상에서 이용 서비스의 대상으로 바뀐다든지, 차 딜러가 사라진다든지 하는 등의 혁신적이거나 과격한 전망이 실현될 지는 두고 볼 일이다.참조 : 다음은 토니 세바 교수가 참여한 화제의 보고서 ‘Rethinking transportation 2020-2030’ 원문 링크https://static1.squarespace.com/static/585c3439be65942f022bbf9b/t/591a2e4be6f2e1c13df930c5/1494888038959/RethinkX+Report_051517.pdf
조회수 967

주니어 개발자가 외칩니다, "Hello, System Architecture!"

Overview주니어 개발자는 시스템 아키텍처(System Architecture) 또는 시스템 디자인(System Design)이라는 단어에 덜컥 겁부터 먹습니다. 지금 진행하고 있는 개발에만 집중하다 보니 큰 그림을 놓치고 있는 게 아닐까 란 생각이 들었죠. 조금 더 큰 그림을 보고자 공부를 시작했습니다. 문득 같은 생각을 하는 주니어 개발자 분들도 많을 것 같다고 생각했어요. 그래서 이번 글은 시스템 아키텍처에 ㅇ_ㅇ? 뀨? 하는 표정을 짓는 주니어 개발자들을 위해 썼습니다.상상의 나래: 가상의 패션 e커머스상상의 나래를 펼쳐봅시다. 패션 e커머스 서비스를 이용하는 김유저 씨가 구매한 옷이 마음에 들어 상품 리뷰를 남기고 싶어한다고요.김유저 씨는 본인의 착용 사진과 텍스트 리뷰를 작성하고 ‘리뷰 등록하기’ 버튼에 엔터를 탁! 누를 겁니다. 그런데 말이죠. 김유저 씨는 요청하고 싶은 웹서버의 IP 주소를 모르기 때문에 요청을 보낼 수가 없습니다.내 정체를 알려줘: DNS (Domain Name System)그래서, DNS(Domain Name System)에게 물어봅니다. 서버의 도메인 이름으로부터 해당 서버의 IP 주소를 알려주는 것이 바로 DNS입니다. 도메인 이름에 대한 질의를 하고, 만일 해당 도메인 이름이 DNS에 ‘A Record’ 형태로 등록이 되어 있다면 도메인 이름에 해당하는 IP 주소를 응답으로 돌려줍니다.서비스에서 자체 DNS 시스템을 가지고 있을 수 있습니다. 예를 들어 Route 53, Cloud Flare같은 서비스가 있습니다. 그렇다면 또 한 가지 의문이 생깁니다. 왜 서비스는 시스템적 부담을 안고서 자체 DNS 서버를 구축하고 있는 걸까요? 그 이유로 두 가지를 꼽을 수 있습니다.첫 번째로는 신뢰도가 높습니다. 직접 DNS Record를 관리 및 운영하기 때문입니다. 두 번째로는 보안이 우수합니다. 만약 공개하고 싶지 않은 IP 주소, 예를 들어 Database IP 주소 같은 건 공개하지 않습니다. 1)작업장소: Web Server이제 웹서버의 IP 주소를 알았으니 통신을 시도합니다. 웹서버는 웹서비스에서 필요로 하는 다양한 요청과 그에 대한 응답을 제공합니다. 클라이언트가 리뷰에 대한 사진과 텍스트를 등록하고 싶다면 웹서버에게 등록하라는 요청을 보내야 합니다.웹서버에서 요청을 받으면 사용자가 요구한 대로 사진과 텍스트를 등록하고, 그에 대한 결과 정보를 응답으로 보내줄 것입니다. 웹서버 내부에서는 그 과정에 필요한 연산을 수행합니다. 서버 개발자는 이 연산에 대한 코드를 작성하고요.센스가 없는 서버:API (Application Programing Interface)서버는 사람이 아닙니다. 센스나 재치가 없죠. 미리 정의되지 않은 요청은 대응하지 못합니다. (어버버버버 퉤! Error 404!) 그래서 약속한 요청을 보내면 약속한 방식으로 응답해줄게라고 명세를 제공합니다.약속한 요청으로 데이터를 보내면 원하는 요청에서 데이터를 정제해 잘 처리했는지, 또는 처리된 데이터를 약속한 방식(예를 들어, JSON 방식)으로 내보내죠. 웹서버는 정의된 API에 맞춰 요청과 응답을 합니다.그런데 웹서버가 수많은 요청을 받고 응답하면 과부하가 일어날 수도 있습니다. 사용자 수가 어마어마한 규모로 늘어나서 서버가 펑! 하고 터진다면, 김유저 씨는 서비스를 더 이상 이용할 수 없을 겁니다. 이용하고 싶지도 않을 겁니다!따라서, 서버가 감당하는 요청을 나누기 위해 같은 역할을 하는 서버 장비 수를 늘릴 수도 있습니다. 그러면 요청이 각기 다른 웹서버 장비에 분산되어 한 번에 감당할 수 있는 요청 수가 더욱 많아집니다.이 구역의 매니저는 나야: Load Balancer그림처럼 서버가 4대 존재하는 상황이라면, 서버 4대에 일을 적절히 분배해주는 역할이 필요합니다. 그것이 로드 밸런서(Load Balancer)입니다. 로드 밸런서가 서버에게 일을 나누는 방법론은 여러 가지가 있습니다.Random: 랜덤으로 분배하기Least loaded: 가장 적은 양의 작업을 처리하고 있는 서버에게 요청을 할당하기Round Robin: 순서를 정하여 돌아가며 작업 분배하기많이 쓰는 로드 밸런서의 종류는 Layer 4, Layer 7을 꼽을 수 있습니다.Layer 4 Load Balancer: 데이터의 내용을 보지 않고 IP주소 및 TCP/UDP 정보에 따라 단순히 분배를 해줍니다.Layer 7 Load Balancer: 서버가 하는 역할이 분리되어 있는 환경에서 데이터의 내용을 보고 각기 맞는 역할을 하는 서버에게 분배를 해줍니다.로드 밸런서는 클라이언트가 요청을 보내야 할 서버를 골라야 하는 부담을 덜어주며, 로드 밸런서에게 할당된 vIP (가상 IP)로 요청을 보내기만 하면 로드 밸런서에서 알아서 작업을 나눠줍니다. 서버에서는 적절한 로드 밸런서를 사용하면 들어오는 요청이 여러 장비에 분산되어 처리량이 늘어나고 응답 시간이 줄어드는 효과를 기대할 수 있습니다. 컨텐츠 저장소: CDN(Content Delivery Network)이제 웹서버가 클라이언트의 요청에 의해 웹페이지에 대한 응답 결과를 돌려줬습니다. 이때 클라이언트의 화면에 렌더링해야 하는 수많은 이미지가 필요합니다. 이 이미지들을 웹서버가 전부 주려면 데이터의 용량이 너무 크고, 무거워서 서버가 헥헥거리죠. (서버가 죽으면 어떻게 될까요? 클라이언트님이 경쟁사로 환승하겠죠.. 안 돼요..) 따라서 웹서버는 직접 이미지를 주는 대신 CDN(Content Delivery Network)에게 요청하라고 이야기합니다. CDN은 일반적으로 용량이 큰 컨텐츠 데이터(이미지, 비디오, 자바스크립트 라이브러리 등)를 빠른 속도로 제공하기 위해 사용자와 가까운 곳에 분산되어 있는 데이터 저장 서버입니다. 클라이언트는 용량이 큰 컨텐츠 데이터를 가까운 CDN에 요청해 멀리 있는 웹서버에서 직접 받는 것보다 빠르게 받을 수 있습니다. CDN이 동작하는 방식에는 크게 Push CDN, Pull CDN이 있습니다. Push CDN: 서버에서 컨텐츠가 업로드되거나, 변경되었을 때 모두 반영하는 방식 Pull CDN: 클라이언트가 요청할 때마다 컨텐츠가 CDN에 새로 저장되는 방식 두 방식 모두 장단점이 있습니다. Push CDN은 모든 컨텐츠를 갖고 있기에 웹서버에 요청할 일이 없지만 유지하는데 필요한 용량과 비용이 많이 필요하겠죠? Pull CDN은 클라이언트가 요청한 컨텐츠가 있으면 바로 응답하지만 그렇지 않을 땐 데이터를 웹서버로부터 가져와야 하기 때문에 서버에 요청하는 부담이 존재합니다. 컨텐츠명은 그대로인데 내용만 변경되었다면 인지하지 못하고 옛버전의 컨텐츠를 제공하죠. 그래서 Pull CDN에 들어가는 컨텐츠는 TTL(Time To Live)이 적용됩니다. TTL이란 유통기한이라고 생각하면 쉽습니다. 일정시간이 지나면 해당 데이터가 삭제되는 것이죠. 이런 방식이 적용된다면 Pull CDN의 최대 단점을 보완할 수 있습니다. 이렇게 보완이 되면 수정된 데이터에 대해서도 대응이 가능하며 서버의 용량 즉, 비용적 부담이 해소될 겁니다.소중한 내 데이터: Database서비스를 제공하다 보면 클라이언트의 소중한 정보, 이력, 상품 가격, 상품 정보 등 다양한 데이터를 저장하고, 또 제공합니다. 하지만 수많은 데이터를 웹서버에 전부 저장하고 사용하기엔 데이터의 양이 너무 많아 저장 공간도 부족하고, 데이터를 원하는 모양에 맞게 정제하기가 어렵습니다. 그래서 데이터를 저장하는 데이터베이스 서버가 따로 존재합니다.민감한 정보를 다루는 데이터베이스는 ACID라는 성질을 만족해야 하는데요.Atomicity(원자성): 데이터베이스에 적용되는 명령이 중간만 실행되지 않고 완전히 성공하거나 완전히 실패해야 한다는 것을 의미합니다. 반만 적용된 명령이 있다면 헷갈리겠죠.Consistency(일관성): 데이터베이스가 수행한 명령이 일관적으로 반영되어 있어야 한다는 의미입니다. 예를 들어 계좌에 돈을 입금했는데 잔고에 반영되지 않는다면 당황스러울 겁니다.Isolation(고립성): 데이터베이스가 수행하는 명령 도중 다른 명령이 끼어들지 못한다는 것을 의미합니다.Durability(지속성): 성공적으로 수행한 명령은 영원히 그 이후 상태로 남아있어야 한다는 걸 의미합니다. 갑자기 하루 뒤에 명령이 취소되거나 이전 상태로 롤백되면 안 됩니다. Replication (복제 / 이중화)큰 시스템에서는 똑같은 데이터베이스가 여럿 존재한다고 하는데요. 그렇다면 왜 비용적인 부담을 안으면서까지 복제 데이터베이스를 구축해놓는 걸까요? 만약에 데이터베이스가 정상적으로 동작하지 않는다면 클라이언트의 데이터를 변경하지 못하며, 클라이언트가 원하는 정보를 제공하지 못하는 불상사가 일어나게 됩니다. 글로만 써도 벌써 땀이 납니다. 그러므로 복제해놓은 데이터베이스를 얼른 마스터로 등업해 데이터 흐름에 차질이 없도록 대비해야 합니다.만약 하나의 데이터베이스가 어떤 일을 수행할 때 다른 요청들은 계속 기다려야 합니다. 그렇다면 데이터를 변경하는 데이터베이스는 하나, 읽기만 하는 데이터베이스는 여러 대가 존재해도 되지 않을까요? 바로 여기서 Master-Slave의 개념이 탄생합니다.master-slave-replicaMaster-Slave Replica (a.k.a 주인-노예)요청을 분산하기 위해서 데이터베이스를 늘리다 보면 master-slave 토픽이 등장합니다.Mater: CRUD(Create, Read, Update, Delete)가 모두 가능Slave: R(Read)만 가능Master가 데이터를 변경할 동안 읽기에 대한 요청은 Slave에게 보내집니다. 그렇게 하면 읽기 요청은 분산되어 훨씬 더 수월하고 빠른 속도로 데이터 처리가 가능할 것입니다. 만약 Master가 변경된다면 아래 계급인 Slave, Replica 데이터베이스에게도 이 정보를 전해야 합니다. 다시 말해, 자신에게 들어온 요청(Query)을 동일하게 보내 빠른 시간 안에 동기화를 시켜주죠. 하지만 동기화도 시간이 걸리는 작업이므로 무한대로 Slave Replica를 늘려 확장하기는 어렵습니다.Master-Master Replica의문이 하나 생길 겁니다. “여러 대의 Master를 두어서 변경도 가능하고, 읽기도 가능하게 하면 되지 않을까?”앞서 언급했듯이 같은 데이터의 변경 가능한 데이터베이스는 하나여야 할 것입니다. 동시에 같은 데이터를 변경했을 때 갈등을 해소하기 위한 방법론은 존재하지만, 그 방식이 복잡하고 오래 걸립니다. 안정성도 낮아지고, 효율도 떨어집니다. 그래서 Master-Slave 아키텍처를 선호하는 것이죠.Sharding그러면 같은 데이터베이스 테이블을 동시에 변경하는 건 불가능한 걸까요? 그것을 해소하기 위해 샤딩(Sharding)이라는 방법론을 사용합니다. 샤딩된 테이블은 개념적으론 하나의 테이블처럼 보이지만 사실 그 내용물이 쪼개져 있습니다. 쪼개는 방법은 여러 가지 선택할 수 있습니다만, 분명한 건 겹치는 데이터 없이 쪼갠다는 것입니다. 그래서 같은 테이블이어도 쪼개져 있다면 그 테이블에 동시에 접근해 데이터를 변경할 수 있는 것이죠.이외에 서비스별, 기능별로 쪼개어 데이터베이스를 관리하는 Federation 등 많은 데이터베이스 디자인 방법론이 존재합니다.시스템 아키텍처가 가지고 있어야 할 최소본 아키텍처요점: 시스템 아키텍쳐에서 고려해야 할 성질이렇게 간단한 시스템 아키텍처의 면면을 살펴봤습니다. 시스템 개발자라면 시스템을 디자인하면서 반드시 고려해야 할 성질들을 만날 텐데요. 위에서 소개한 내용들 역시 아래의 성질들을 충족하기 위해 탄생했다고 볼 수 있습니다.Scalability (확장성): 10만 명의 요청을 처리할 수 있는 시스템과 1000만 명의 요청을 처리할 수 있는 시스템은 다릅니다. 확장성을 고려한 시스템은 앞으로 클라이언트 수가 늘어났을 때 무리 없이 모든 요청을 처리할 수 있을 겁니다.Performance (성능): 속도와 정확성을 말합니다. 요청한 내용을 정확하고 빠르게 돌려주어야 합니다.Latency (응답 시간): 모든 요청은 클라이언트가 불편해하지 않을 정도로 빠른 시간 안에 돌려주어야 합니다.Throughput (처리량): 같은 시간 안에 더욱 많은 요청을 처리한다면 좋은 시스템입니다.Availability (접근성): 사용자가 언제든지 시스템에 요청을 보내서 응답을 받을 수 있어야 합니다. 비록 서버 장비 한두 대가 문제가 생겨 제 기능을 하지 못하더라도 사용자는 그 사실을 몰라야 합니다.Consistency (일관성): 사용자가 서버에 보낸 요청이 올바르게 반영되어야 하고, 일정한 결과를 돌려주어야 합니다. 요청을 보낼 때마다 불규칙한 결과를 돌려준다면 믿을 수 없는 서비스가 될 것입니다.결론발로 그렸나 싶을 정도의 그림과 기나긴 글을 마무리 지으며주니어 개발자로서 시스템 아키텍처를 공부하면서 느낀 점이 있다면 시스템에 대한 완벽한 대응은 없으며, 모두 장단점이 존재한다는 것입니다. (이것을 보통 trade-off라고 표현합니다.)하지만 설계하는 서비스를 잘 알고 서비스에서 무게를 둬야 할 부분을 파악한다면, 그에 맞는 시스템을 설계하고 디자인할 수 있을 겁니다. 김유저 씨도 만족시킬 수 있을 거고요. 꼬박 이틀을 밤새워서 쓴 글이 아직 시스템 아키텍처를 두려워하는 다른 주니어 개발자분들에게 도움이 되었으면 합니다. 이번에는 시스템에서 아주 기초적인 부분을 공부했으니 다음 글에선 MSA(MicroService Architecture)를 씹어봅시다! 겁이 나고 무서워도 외쳐보세요. “Hello, System Architecture!”이 세상 모든 주니어 개발자분들, 퐈잇팅입니다.참고1) 추가적인 이점에 대하여: 웹서버에서 요청을 보낼 때 database 도메인 네임으로 보낼 경우, 멀리 있는 공인 DNS 서버 (예를 들면 google public DNS server: 8.8.8.8)에 물어오는 것보다 자체 DNS 서버에 물어오는 것이 훨씬 더 빠른 속도로 응답을 받아올 수 있습니다.출처GitHub - donnemartin/system-design-primer: Learn how to design large-scale systems. Prep for the system design interview. Includes Anki flashcards.글오연주 사원 | R&D 개발2팀[email protected]브랜디, 오직 예쁜 옷만#브랜디 #개발자 #개발팀 #인사이트 #경험공유 #주니어개발자
조회수 2157

디너의여왕 탐구 생활_인터뷰2. 개발팀

안녕하세요 :)오늘은 "디너의여왕 탐구생활"개발팀 편을 들고 왔습니다.개발팀 열일 현장입니다.무슨 뜻인지 모를 단어들이컴퓨터에 가득가득하네요!이제 그들과 인터뷰를 진행하면서본격적으로 파헤쳐 보도록 하겠습니다!!!오늘 인터뷰는 개발팀의 3인가디님, 월리님, 펭돌이님과인터뷰를 진행해보겠습니다 :-)첫번째 인터뷰는개발팀 가디님과 진행하겠습니다.Q. 현재 담당하고 계신직무에 대해 소개 부탁드려요. A. 저는 디너의여왕에서데이터 수집과Elasticsearch와 관련된검색시스템을 담당하고 있습니다.  Q. 어떤 동기를 갖고해당 직무에 지원하게 되었나요? A. 개인 프로젝트로기본적인 검색엔진 시스템을구축해 본 적이 있었는데,해당 경험을 살릴 수 있는소중한 기회라 생각해서해당 직무에 지원하게 되었습니다.Q. 해당 직무에 필요한 역량이 있다면무엇일까요?  A. 검색 시스템의전체적인 흐름을 아는 것이아무래도 업무를 수행하는데 도움이 됩니다.그리고 관련된 자료가 한국어로는 흔하지 않기 때문에필요한 자료들을 잘 찾을 수 있는스킬이 필요할 것 같습니다.Q. 해당 직무에서 일할 때 사용하는자신만의 스킬, 노하우가 있다면 무엇인가요? A. 직무와 관련된 자료는아무래도 영문이 많은데다행히 제가 익숙한 일본어로도양질의 자료가 있어서자료를 얻는데 도움이 되고 있습니다.Q. 해당 직무에서 일하면서 즐거웠던 적,힘들었던 적이 있다면 언제일까요?  검색과 관련된 기능은 Elasticsearch에서많은 것을 처리해 주기는 하지만여전히 개발자가 직접 처리해 주어야 하는작업들이 있습니다.다소 지루하게 느껴질 수 있는 부분이지만시행착오를 겪으면서조금씩 개선이 되는 시스템을 보면서보람을 느낄 수 있었습니다.두 번째 인터뷰는개발팀 월리님과 진행하겠습니다.Q. 현재 담당하고 계신 직무에 대해소개 부탁드려요.  디너의여왕 웹 프론트엔드 개발을맡고있습니다.Q. 어떤 동기를 갖고해당 직무에 지원하게 되었나요?디자인을 직접 코딩해서나오는 표현이 재밌어서 시작했는데마침 타이밍 맞게 여기에 기회가 생겨서요.Q. 해당 직무에 필요한 역량이 있다면 무엇일까요?  기본적인 html/ css/ javascript에 대한기본적인 이해가 일단 필요하고요,프론트엔드 분야가 일반적으로가장 노출이 많이 되는 부분이다 보니일반적으로 개발만 하는 것보다는UX/UI에 대한 고민하는 자세가가장 중요한 것 같습니다.  Q. 해당 직무에서 일할 때 사용하는 자신만의 스킬, 노하우가 있다면 무엇인가요?  저도 부족한데 뭐…코딩은 왕도가 없습니다.일단 많이 뜯어고쳐보고또 삽질도 많이 해봐야 한다고 생각합니다.  그러다 보면 자연스럽게 익혀져서나만의 노하우가 생긴다고 보면 됩니다!Q. 해당 직무에서 일하면서 즐거웠던 적,힘들었던 적이 있다면 언제일까요?  프론트엔드 개발자로서내가 만든 코드가실제 서비스에 나온다는 것 자체가보람찬 일입니다.힘든 건 묻지 마세요Q. 마지막으로, 디너의여왕이 될지원자들에게 한 마디 부탁드려요. 어솨요 반가버요 ヽ(‘ ∇‘ )ノ세 번째 인터뷰입니다.개발팀 펭돌이님과 함께 진행하겠습니다!Q. 현재 담당하고 계신직무에 대해 소개 부탁드려요.  A. 안녕하세요.저는 디너의여왕에서 사용되는웹 서비스 백엔드를 개발하고 있어요.  Q. 어떤 동기를 갖고 해당 직무에지원하게 되었나요?  A. 실시간 트래픽이 높은 웹 서비스를개발해보고 싶은 욕심이 있었어요.트래픽이 높으면 신경 써야 할 것들이여러 가지가 있는데그것 또한 경험이 되리라고 생각했습니다.  또, 과거에잠시 블로그를 운영했던 적이 있었는데그 덕분에,  SNS 블로그 마케팅이라는세일즈 프로모션에도 관심이 많았어요.Q. 해당 직무에 필요한 역량이 있다면무엇일까요?  A. 한 가지 이상의 서버에서 사용되는프로그래밍 언어를 다룰 줄 알아야 합니다. 또 데이터를 수집하고,가공하는 등의 기술에 대해서도응용력이 좋아야 합니다.  그 외에도 다양한 요구 사항들이동시다발적으로 발생할 수가 있으니우선순위에 따라업무를 순서대로 처리할 수 있는 능력이중요한 것 같아요.Q. 해당 직무에서 일할 때 사용하는자신만의 스킬, 노하우가 있다면무엇인가요?  A. 저는 최대한 오픈 소스,검색을 활용하는 편이에요.  오픈 소스 같은 경우에는여러 포럼, 저장소 등에서 검색해보는 것이중요하고,검색 같은 경우에는적절한 키워드 (영어 의문문 how to ~)를이용하여 검색하면웬만한 지식들은 구글에 나와 있습니다.Q. 해당 직무에서 일하면서 즐거웠던 적,힘들었던 적이 있다면 언제일까요?  A. 갑작스럽고 치명적인 오류 등에 의해서갑자기 바빠지거나,예상치 못한 오류 때문에업무에 지장이 생기는 경우가가장 스트레스를 많이 받았던 것 같아요.최대한 그런 일들이 발생하지 않도록예방해요.집을 짓는다고 가정하면초석부터 탄탄히 짓는 것이죠.즐거운 일은아무래도 예상외로 술술 풀려나갈 때가장 보람찬 것 같아요.Q. 개발 업무의 매력은 어떤 것이 있을까요? A. 개발 업무는인터넷이라는 가상의 공간에서무언가를 창조하고,사람들에게 보여주는 매력이 있는 것 같아요.  또, 만들어진 결과물로 인해서누군가의 인생을좌우할 수 있을 것만 같아요.이런 게 매력이 아닐까요? Q. 마지막으로,디너의여왕이 될 지원자들에게한 마디 부탁드려요. A. 디너의 여왕은단순한 음식점 소개 웹 사이트가 아닌,푸드 플랫폼을 위한다양한 기술들이 집약되어 있습니다.단순히 포스트를 올리고,보여주는 것이 아닌어떻게 하면 효율적인 마케팅 효과를 불러올 수 있는 것인지 수집하고 가공하는복잡한 기술들이 집약되어 있습니다.  빅데이터 등의 IT 패러다임에관심이 있으시다면서로 win-win할 수 있는 기회가 될 것 같아요.이상으로 인터뷰를 마치겠습니다 :-)디너의여왕 탐구생활 다음 편은누구와 함께 하게 될까요?#디너의여왕 #개발팀 #팀원소개 #팀원인터뷰 #기업문화 #조직문화
조회수 3179

사물인터넷(IOT) 란? 

안녕하세요?크몽(www.kmong.com) 개발자SEAN입니다.오늘은 요즘 말이 많이 나오고있는 IT용어중에서 사물인터넷(IOT)에 대해서 적어 봅니다. 위키피디아의 사물인터넷의 정의는 '사물 인터넷(Internet of Things, 약어로 IoT)은 각종 사물에 센서와 통신 기능을 내장하여 인터넷에 연결하는 기술을 의미한다. 여기서 사물이란 가전제품, 모바일 장비, 웨어러블 컴퓨터 등 다양한 임베디드 시스템이 된다. 사물 인터넷에 연결되는 사물들은 자신을 구별할 수 있는 유일한 아이피를 가지고 인터넷으로 연결되어야 하며, 외부 환경으로부터의 데이터 취득을 위해 센서를 내장할 수 있다.모든 사물이 해킹의 대상이 될 수 있어 사물 인터넷의 발달과 보안의 발달은 함께 갈 수밖에 없는 구조이다.'라고 정의가 되어있습니다.예를 들자면 아침에 집에서 알람이 울리면 그와 동시에 토스트기계가 반응하여 저절로 빵이 구워진다든지 집을 나서기 직전 문앞에서 오늘의 날씨를 알려준다든지, 모든 전자기기에 접목을 시킬수있습니다. 또다른 예를 들자면 카페의자에 센서를 달아서 카페마다 자리가 몇자리 남았는지 몇명이 있는지 등을 파악하여 굳이 찾아가지 않아도 내가 쉽게 자리가 있는 카페를 찾을 수 있습니다.  사물인터넷은 매우 좋지만 쉽게 대중화 되지 못하는 점은 위의 정의와 같이 보안에 매우 취약합니다.예를 들어 위의 카페의 정보를 잘못 보이도록하여 그 카페에 못가게 한다든지, 집안의 기계를 다른사람이 조종을 한다든지의 개인 프라이버시 침해가 발생 할 수있다는 것이겠지요. 그리고 또다른 문제점으로는 비용이 많이 든다는 겁니다. 이 점도 무시를 할 수없겠지요. 조그마한 장비라도 여기저기 붙여야하고 그 기기를 연결도 시켜야하고 쉬운 문제는 아닐 듯합니다.언젠가는 대중화 되는 날이 있겠지요?저도 기대해봅니다.이상 크몽 개발자 SEAN이었습니다.#크몽 #개발자 #개발팀 #팀원소개 #기업문화 #조직문화
조회수 97

바로고 사내소식 런치앤런 Scalable team with DevOps

barogo바로고사 내 소 식대한민국#배송 #배달바로고가 함께 달립니다.뼈가 되고 살이 되는외부인사 초청 강연Scalable team with DevOps바로고 복지의 일환으로스타트업 엔지니어 박훈 님을 모시고외부인사 초청 강연이 진행되었습니다.박훈 님의 강연이 시작되었습니다.2018년 1월 31일에 진행된바로고 외부 인사 초청 강연의 생생한 현장을 소개합니다.박훈 님을 모시고 진행된 이번 초청 강연은미니 세미나 형식으로 진행되었습니다.데브옵스(DeOp) 전략을 통해소프트웨어 개발 과정을 좀 더 지속적이고 민첩하게 진행하며개발담당자와 운영담당자가 함께 소통하며협력하는 자리가 되길 기대합니다.뼈가 되고 살이 되는 시간개발자의 고민1. 우리 팀은 사람은 많은데 왜 이렇게 느릴까?2. 왜 사람들은 테스트를 덜 작성할까?3. 왜 API 호환성이 자꾸 고장(incompatubel) 나는 걸까?4. 배포 하나 하기가 왜 이렇게 힘들까?5. 데이터에 기반을 둬 결정을 내리려면 뭐가 더 필요할까?6. 왜 에러는 우리팀보다 사용자가 먼저 찾아낼까?평소 박훈 님께서 개발을 하시며고민하던 부분은 함께 공유하며문제를 해결하고자 다양한 이야기를 나누는 시간이 되었습니다.배고픔을 잊은 그대들의 열정에 박수를 _짝짝짝DevOps를 실제로 사내에서 어떻게 적용하고 있는지열정적으로 발표해주시는 박훈 님경험과 노하우를 공유하며함께 솔루션을 찾아가는 과정이정말 뼈가 되고 살이 되는 시간이 되었습니다.그가 스타트업 정글에서 살아남은 방법(중략)단순히 개발뿐만 아니라지식의 전달, 배포, 문서화 등모든 측면에 있어서scalable 한 팀이 되어야만 한다_!우리의 소통은 계속 됩니다.발표가 끝난 뒤보다 집중적으로 사례를 분석했습니다.DevOps가 잘 정착되면보다 고객에 집중할 수 있다는 점을 강조하였습니다.Solution = System + Culture1. 새로운 것을 좋아하는 사람도 있지만, 싫어하는 사람도 있을 수 있다. 2. 도구가 아니라 풀려는 문제에 집중하자.3. 도구뿐만 아니라 문화(CULTURE)를 가져오자.박훈님_ 수고하셨습니다_!항상 발전하고 진화하는 소프트웨어의 흐름데브옵스를 통해 개발자와 정보 기술 전문가 간의소통과 협업을 통해더 나은 개발 환경, 문화를 만들어가길기대합니다_!바로고 x 본도시락세미나를 마치고 즐거운 점심시간런치앤런의 진짜 시작이라고 할까요?^_*너무나 열띤 토론으로 인해우리는 배가 고팠습니다.런치앤런선정 메뉴를바로고가 배달하는 '본도시락'[바로고 x 본도시락]https://blog.naver.com/barogo_info/2211915027002018년 첫 외부인사 초청 강연박훈님께 감사드립니다.다음에도뼈가 되고 살이 되는알찬 내용으로 찾아가는 런치앤런이 되겠습니다.감사합니다.^___^배송의 가치를 만들어가는바로고barogo-[바로고 공식 홈페이지]https://goo.gl/jKB7LA
조회수 2108

블로그 운영 방법에서 엿보는 VCNC의 개발문화

VCNC에서 엔지니어링 블로그를 시작하고 벌써 새로운 해를 맞이하였습니다. 그동안 여러 글을 통해 VCNC 개발팀의 이야기를 들려드렸습니다. 이번에는 엔지니어링 블로그 자체를 주제로 글을 적어보고자 합니다. 저희는 워드프레스나 텀블러와 같은 일반적인 블로깅 도구나 서비스를 사용하지 않고 조금은 개발자스럽다고 할 수 있는 특이한 방법으로 엔지니어링 블로그를 운영하고 있습니다. 이 글에서는 VCNC 개발팀이 엔지니어링 블로그를 운영하기 위해 이용하는 방법들을 소개하고자 합니다. 그리고 블로그를 운영하기 위해 방법을 다루는 중간중간에 개발팀의 문화와 일하는 방식들에 대해서도 간략하게나마 이야기해보고자 합니다.블로그에 사용하는 기술들Jekyll: Jekyll은 블로그에 특화된 정적 사이트 생성기입니다. GitHub의 Co-founder 중 한 명인 Tom Preston-Werner가 만들었으며 Ruby로 작성되어 있습니다. Markdown을 이용하여 글을 작성하면 Liquid 템플릿 엔진을 통해 정적인 HTML 파일들을 만들어 줍니다. VCNC 엔지니어링 블로그는 워드프레스같은 블로깅 도구를 사용하지 않고 Jekyll을 사용하고 있습니다.Bootstrap: 블로그 테마는 트위터에서 만든 프론트엔드 프레임워크인 Bootstrap을 이용하여 직접 작성되었습니다. Bootstrap에서 제공하는 다양한 기능들을 가져다 써서 블로그를 쉽게 만들기 위해 이용하였습니다. 덕분에 큰 공을 들이지 않고도 Responsive Web Design을 적용할 수 있었습니다.S3: S3는 AWS에서 제공되는 클라우드 스토리지 서비스로서 높은 가용성을 보장합니다. 일반적으로 파일을 저장하는 데 사용되지만, 정적인 HTML을 업로드하여 사이트를 호스팅하는데 사용할 수도 있습니다. 아마존의 CTO인 Werner Vogels 또한 자신의 블로그를 S3에서 호스팅하고 있습니다. VCNC Engineering Blog도 Jekyll로 만들어진 HTML 파일들을 아마존의 S3에 업로드 하여 운영됩니다. 일단 S3에 올려두면 운영적인 부분에 대한 부담이 많이 사라지기 때문에 S3에 올리기로 하였습니다.CloudFront: 브라우저에서 웹페이지가 보이는 속도를 빠르게 하려고 아마존의 CDN서비스인 CloudFront를 이용합니다. CDN을 이용하면 HTML파일들이 전 세계 곳곳에 있는 Edge 서버에 캐싱 되어 방문자들이 가장 가까운 Edge를 통해 사이트를 로딩하도록 할 수 있습니다. 특히 CloudFront에 한국 Edge가 생긴 이후에는 한국에서의 응답속도가 매우 좋아졌습니다.s3cmd: s3cmd는 S3를 위한 커맨드 라인 도구입니다. 파일들을 업로드하거나 다운로드 받는 등 S3를 위해 다양한 명령어를 제공합니다. 저희는 블로그 글을 s3로 업로드하여 배포하기 위해 s3cmd를 사용합니다. 배포 스크립트를 실행하는 것만으로 s3업로드와 CloudFront invalidation이 자동으로 이루어지므로 배포 비용을 크게 줄일 수 있었습니다.htmlcompressor: 정적 파일들이나 블로그 글 페이지들을 s3에 배포할 때에는 whitespace 등을 제거하기 위해 htmlcompressor를 사용합니다. 또한 Google Closure Compiler를 이용하여 javascript의 길이도 줄이고 있습니다. 실제로 서버가 내려줘야 할 데이터의 크기가 줄어들게 되므로 로딩속도를 조금 더 빠르게 할 수 있습니다.블로그 관리 방법앞서 소개해 드린 기술들 외에도 블로그 글을 관리하기 위해 다소 독특한 방법을 사용합니다. 개발팀의 여러 팀원이 블로그에 올릴 주제를 결정하고 서로의 의견을 교환하기 위해 여러 가지 도구를 이용하는데 이를 소개하고자 합니다. 이 도구들은 개발팀이 일할 때에도 활용되고 있습니다.글감 관리를 위해 JIRA를 사용하다.JIRA는 Atlassian에서 만든 이슈 관리 및 프로젝트 관리 도구입니다. VCNC 개발팀에서는 비트윈과 관련된 다양한 프로젝트들의 이슈 관리를 위해 JIRA를 적극적으로 활용하고 있습니다. 제품에 대한 요구사항이 생기면 일단 백로그에 넣어 두고, 3주에 한 번씩 있는 스프린트 회의에서 요구사항에 대한 우선순위를 결정합니다. 그 후 개발자가 직접 개발 기간을 산정한 후에, 스프린트에 포함할지를 결정합니다. 이렇게 개발팀이 개발에 집중할 수 있는 환경을 가질 수 있도록 하며, 제품의 전체적인 방향성을 잃지 않고 모두가 같은 방향을 향해 달릴 수 있도록 하고 있습니다.VCNC 개발팀이 스프린트에 등록된 이슈를 얼마나 빨리 해결해 나가고 있는지 보여주는 JIRA의 차트.조금만 생각해보시면 어느 부분이 스프린트의 시작이고 어느 부분이 끝 부분인지 아실 수 있습니다.위와 같은 프로젝트 관리를 위한 일반적인 용도 외에도 엔지니어링 블로그 글 관리를 위해 JIRA를 사용하고 있습니다. JIRA에 엔지니어링 블로그 글감을 위한 프로젝트를 만들어 두고 블로그 글에 대한 아이디어가 생각나면 이슈로 등록할 수 있게 하고 있습니다. 누구나 글감 이슈를 등록할 수 있으며 필요한 경우에는 다른 사람에게 글감 이슈를 할당할 수도 있습니다. 일단 글감이 등록되면 엔지니어링 블로그에 쓰면 좋을지 어떤 내용이 포함되면 좋을지 댓글을 통해 토론하기도 합니다. 글을 작성하기 시작하면 해당 이슈를 진행 중으로 바꾸고, 리뷰 후, 글이 발행되면 이슈를 해결한 것으로 표시하는 식으로 JIRA를 이용합니다. 누구나 글감을 제안할 수 있게 하고, 이에 대해 팀원들과 토론을 하여 더 좋은 글을 쓸 수 있도록 돕기 위해 JIRA를 활용하고 있습니다.JIRA에 등록된 블로그 글 주제들 중 아직 쓰여지지 않은 것들을 보여주는 이슈들.아직 제안 단계인 것도 있지만, 많은 주제들이 블로그 글로 발행되길 기다리고 있습니다.글 리뷰를 위해 Pull-request를 이용하다.Stash는 Attlassian에서 만든 Git저장소 관리 도구입니다. GitHub Enterprise와 유사한 기능들을 제공합니다. Jekyll로 블로그를 운영하는 경우 이미지를 제외한 대부분 콘텐츠는 평문(Plain text)으로 관리 할 수 있게 됩니다. 따라서 VCNC 개발팀이 가장 자주 사용하는 도구 중 하나인 Git을 이용하면 별다른 시스템의 도움 없이도 모든 변경 내역과 누가 변경을 했는지 이력을 완벽하게 보존할 수 있습니다. 저희는 이런 이유로 Git을 이용하여 작성된 글에 대한 변경 이력을 관리하고 있습니다.또한 Stash에서는 GitHub와 같은 Pull request 기능을 제공합니다. Pull request는 자신이 작성한 코드를 다른 사람에게 리뷰하고 메인 브랜치에 머지해 달라고 요청할 수 있는 기능입니다. 저희는 Pull request를 활용하여 상호간 코드 리뷰를 하고 있습니다. 코드 리뷰를 통해 실수를 줄이고 개발자 간 의견 교환을 통해 더 좋은 코드를 작성하며 서로 간 코드에 대해 더 잘 이해하도록 노력하고 있습니다. 새로운 개발자가 코드를 상세히 모른다 해도 좀 더 적극적으로 코드를 짤 수 있고, 업무에 더 빨리 적응하는데에도 도움이 됩니다.어떤 블로그 글에 대해 리뷰를 하면서 코멘트로 의견을 교환하고 있습니다.코드 리뷰 또한 비슷한 방법을 통해 이루어지고 있습니다.업무상 코드 리뷰 뿐만 아니라 새로운 블로그 글을 리뷰하기 위해 Pull request를 활용하고 있습니다. 어떤 개발자가 글을 작성하기 위해서 가장 먼저 하는 것은 블로그를 관리하는 Git 리포지터리에서 새로운 브랜치를 따는 것입니다. 해당 브랜치에서 글을 작성하고 작성한 후에는 새로운 글 내용을 push한 후 master 브랜치로 Pull request를 날립니다. 이때 리뷰어로 등록된 사람과 그 외 개발자들은 내용에 대한 의견이나 첨삭을 댓글로 달 수 있습니다. 충분한 리뷰를 통해 발행이 확정된 글은 블로그 관리자에 의해 master 브랜치에 머지 되고 비로소 발행 준비가 끝납니다.스크립트를 통한 블로그 글 발행 자동화와 보안준비가 끝난 새로운 블로그 글을 발행하기 위해서는 일련의 작업이 필요합니다. Jekyll을 이용해 정적 파일들을 만든 후, htmlcompressor 통해 정적 파일들을 압축해야 합니다. 이렇게 압축된 정적 파일들을 S3에 업로드 하고, CloudFront에 Invalidation 요청을 날리고, 구글 웹 마스터 도구에 핑을 날립니다. 이런 과정들을 s3cmd와 Rakefile을 이용하여 스크립트를 실행하는 것만으로 자동으로 이루어지도록 하였습니다. VCNC 개발팀은 여러 가지 업무 들을 자동화시키기 위해 노력하고 있습니다.또한, s3에 사용하는 AWS Credential은 IAM을 이용하여 블로그를 호스팅하는 s3 버킷과 CloudFront에 대한 접근 권한만 있는 키를 발급하여 사용하고 있습니다. 비트윈은 특히 커플들이 사용하는 서비스라 보안에 민감합니다. 실제 비트윈을 개발하는데에도 보안에 많은 신경을 쓰고 있으며, 이런 점은 엔지니어링 블로그 운영하는데에도 묻어나오고 있습니다.맺음말VCNC 개발팀은 엔지니어링 블로그를 관리하고 운영하기 위해 다소 독특한 방법을 사용합니다. 이 방법은 개발팀이 일하는 방법과 문화에서 큰 영향을 받았습니다. JIRA를 통한 이슈 관리 및 스프린트, Pull request를 이용한 상호간 코드 리뷰 등은 이제 VCNC 개발팀의 문화에 녹아들어 가장 효율적으로 일할 수 있는 방법이 되었습니다. 개발팀을 꾸려나가면서 여러가지 시행 착오를 겪어 왔지만, 시행 착오에 대한 반성과 여러가지 개선 시도를 통해 계속해서 더 좋은 방법을 찾아나가며 지금과 같은 개발 문화가 만들어졌습니다. 그동안 그래 왔듯이 앞으로 더 많은 개선을 통해 꾸준히 좋은 방법을 찾아 나갈 것입니다.네 그렇습니다. 결론은 저희와 함께 고민하면서 더 좋은 개발문화를 만들어나갈 개발자를 구하고 있다는 것입니다.저희는 언제나 타다 및 비트윈 서비스를 함께 만들며 기술적인 문제를 함께 풀어나갈 능력있는 개발자를 모시고 있습니다. 언제든 부담없이 [email protected]로 이메일을 주시기 바랍니다!
조회수 2230

안드로이드와 자동화 툴

모바일은 플랫폼의 생태계와 규모에 비해 개발자들이 처리해야 할 것이 매우 많습니다.서버나 타 플랫폼들 또한 개발자들의 영역이 많지만 그 영역들이 세분화되고 전문화되어 가고 있습니다. 데이터베이스, 백엔드, 프론트웨어, 인프라, DevOps 와 같이 점점 분야별로 심화되고 독립성을 갖추어 가고 있습니다.하지만 모바일은 각 플랫폼의 개발자들이 전체적인 아키텍쳐, 프론트, 내부용 데이터베이스, 리소스 관리, 배포 등이 해당 플랫폼의 소수의 개발자들에게 광범위하게 공존합니다. 다양한 분야가 전문화되기엔 변화가 잦고 규모가 점 형태로 구성이 된 경우가 많기 때문입니다.그렇기 때문에 반복적이고 불필요하게 비용이 소모되는 작업일수록 자동화 해서 최대한 코드 작성 본연에 업무에 집중할 수 있도록 환경을 구성하는 것이 중요합니다.토스랩 안드로이드 팀은 2015년 초부터 조금씩 자동화 환경을 구성하여 현재는 아래와 같습니다.다국어 문자 관리 자동화이미지 관리 자동화CI다국어 문자 리소스 자동화1. 다국어 글로벌 담당자의 원본 문서토스랩은 다국어 지원을 위해 글로벌 번역 문서를 관리하고 있습니다. 문서는 Google Drive 를 통해서 관리되고 있으며 기획/개발 파트에서 다국어 지원을 위한 리소스를 기입하면 각 언어의 담당자들이 해당 언어를 번역하고 있습니다.구성은 아래와 같습니다ABCDEFGH영어한국어일본어중국어-간체중국어-번체웹키ios 키안드로이드 키2. 기존 작업기존에는 해당 언어의 번역 데이터를 추가하기 위해 개발 파트에서 수동으로 각 언어의 리소스 파일에 추가하는 형태로 진행하였습니다.이러한 작업의 단점은 언어별 리소스 파일에 키-값 형태의 문자 리소스를 추가하는 작업을 반복적으로 해야 한다는 것입니다. 또한 반영이 된 후에 수정된 문자에 대해서 반영하기가 매우 어렵고 실수도 빈번하게 발생합니다.이러한 가능성을 최소화 하기 위해 자동으로 문자 리소스를 갱신하는 작업을 진행하였습니다.3. 안드로이드 파트를 위한 별도 필터 파일 추가|A|B|C|D|E|F| |—-|—-|—-|—-|—-|—-| |영어|한국어|일본어|중국어-간체|중국어-번체|안드로이드 키|가급적 원본 파일에 대한 조작을 피하기 위해 안드로이드용으로 Read-Only SpreadSheet 를 별도로 생성하였습니다.해당 작업을 위해 Google SpreadSheet Script 를 사용하였습니다.4. 자동화 툴 작업자동화 툴의 역할은 크게 3가지였습니다.안드로이드용 필터 파일을 다운로드한다.Spread-sheet를 분석해서 다국어용 자료구조로 변환한다.다국어용 자료구조를 XML 파일로 변경한다.툴은 Python 스크립트로 작업하였습니다.5. Gradle Task 로 추가별도의 Python 파일을 실행해도 되지만 Gradle Task 로 추가하여 Android Studio 에서도 Task 를 실행할 수 있도록 하였습니다.개발팀에서 안드로이드 키를 원본 문서에 추가한 후 Gradle Task 실행하면 바로 반영되도록 하였습니다. 기존의 방식과 가장 큰 차이점은 Merge 시 충돌 이슈에 대해서 더이상 관여하지 않아도 된다는 것입니다. 가장 최근 시점을 기준으로 자동화 Task 를 실행하면 모든 리소스가 최신화되기 때문에 충돌이 난다하더라도 무시하고 새로 Task 를 실행함으로써 충돌에 의한 이슈를 완전히 배제하고 작업할 수 있다는 장점이 생겼습니다.더 나아가 현재는 Android 용 리소스 Key를 기획 팀에서 기획시 적용하도록 하기로 현재 논의되고 있습니다. 이러한 논의가 반영된다면 더이상 리소스 관리에 있어서 개발파트에서 관리 할 필요가 없어지므로 다국어 리소스에 반영해야할 리소스 또한 최소화 될 것이라 기대하고 있습니다.이미지 리소스 자동화1. 기존 작업앱에 사용되는 디자인 리소스는 이슈 트래커와 JANDI 의 디자인 토픽을 통해서 전달 받아 작업을 하였습니다.이런 작업 형태는 이미지 관리가 분산 될 뿐만 아니라 일관성 있는 전달 방식이 아니기 때문에 누락건이 언제든지 존재할 수 있습니다.그래서 디자인 리소스에 대한 관리를 디자인 팀이 주도적으로 하며 개발팀에서는 빠르고 편하게 이미지를 전달 받을 수 있도록 하기 위해 자동화 툴을 만들었습니다.2. 개선 작업토스랩의 디자인 팀에서 사용하는 저장소는 권한에 따라 접근이 가능하도록 API 를 제공하고 있습니다. Read-Only 권한을 부여받은 후 API 를 통하여 이미지를 다운로드하도록 툴을 구성하였습니다.툴은 Python 스크립트로 구성하였습니다.3. Gradle Task 로 추가문자 리소스와 마찬가지로 별도로 Gradle 로 툴을 이용할 수 있도록 하기 위해 별도의 Task 를 정의하여 사용하도록 하였습니다.자동화된 리소스의 관리문자와 이미지를 자동화로 관리한다 하더라도 개발자가 필요에 따라 임의로 추가/수정하는 리소스가 존재 할 수 있습니다.이를테면 다운로드한 이미지 리소스를 활용한 Selector-Drawable 과 같은 것들입니다.이에 따라 자동화 처리된 리소스들은 별도의 관리를 위해 추가적으로 ResourceSet 을 만들었습니다. android { // ...중략 sourceSets { main.res.srcDirs += ${별도의_리소스_경로} } } 이러한 방식을 통해서 자동화된 리소스와 추가적한 리소스를 분리하여 발생할 수 있는 문제를 최소화 하였습니다.지속적 통합 (Continuous Integration, CI)자동화와 관련되어서 결코 빠질 수 없는 내용입니다. 빌드, 테스트, 배포, 리포팅에 이르기까지 이 모든 과정에 있어서 자동화 되지 않았다면 상상하기 어려운 작업들입니다.토스랩에서는 Jenkins 를 활용하여 빌드-테스트-리포팅을 하고 있습니다.1. 빌드 대상빌드의 의미는 최소한 컴파일 오류가 발생하지 않는 코드들이 최종 상태로 관리되고 있음을 의미합니다. 그러기 때문에 언제나 중앙 저장소에 반영되었거나 반영될 예정의 소스들은 항상 빌드 대상이라고 볼 수 있습니다.안드로이드 팀은 내부적으로 빌드 대상이 되는 브랜치를 아래와 같이 정의하였습니다.개발된 이슈가 최종적으로 반영된 브랜치 (develop)Github 에서 코드에 변경이 발생하면 이를 Jenkins 로 통보하여 해당 브랜치를 빌드합니다.개발 브랜치에 반영을 위해 코드리뷰 중인 브랜치 (features, fixes)Github 에 새로운 Pull-Request 가 발생하면 Jenkins 로 통보하여 해당 브랜치를 빌드합니다.테스트와 리포팅은 이 시점부터 발생한다고 볼 수 있습니다.2. 빌드빌드를 하는 과정에 기본적인 정적 분석을 사용하고 있습니다. 코드의 Convention 이나 복잡도 등을 측정하고 이를 분석하여 수정할 부분을 파악하기 위해서입니다.3. 테스트안드로이드팀은 작년 중순까지 Robolectric 이라는 Test Framework 을 사용하였으나 여러가지 이슈로 인하여 현재는 Android Test Support Library 를 사용하고 있습니다. ATSL 은 에뮬레이터를 필요로 하기 때문에 Jenkins 서버에 에뮬레이터를 구동하여 Test-Bed 를 구성하였습니다.빌드 과정에서 정적 분석이 완료되면 테스트 코드를 동작 시킵니다.테스트 된 결과는 JUnit Test Report 와 Jacoco Coverage Report 를 받고 있습니다.4. 결과 리포트빌드, 테스트 결과는 Jenkins 에서 별도로 관리되고 있지만 모든 동작들은 자동화 되어 관리되기 때문에 별도의 장치가 없다면 알아채기 어렵습니다.좀 더 빠른 피드백을 받기 위해 JANDI-Webhook 기능을 이용하여 결과 리포팅을 바로 받아 확인 할 수 있도록 하였습니다. 또한 Github Pull-Request 화면에서 Build-Status 연동하여 코드리뷰 하는 과정에서 잠재적 오류를 찾을 수 있도록 하였습니다.※ 빌드된 결과물의 배포는 내부적인 정책으로 현재는 하지 않고 있습니다만, 현재 가용 가능한 리소스 안에서 해결 방안을 찾고 있습니다.총평자동화의 가장 큰 목적은 반복적이지만 시간을 소요하기엔 가치가 떨어지는 작업을 단순화 하기 위함이었습니다. 여기서 오는 가장 큰 의미는 관리에 소요되는 시간을 최소화함으로써 생산성을 향상 시켰다는 데에 있습니다.특히 다국어 리소스와 이미지 리소스를 자동화 하기 위한 작업은 소요된 시간이 극히 미미하지만 그 효과는 매우 긍정적이라 할 수 있습니다.CI 는 초기 설정뿐만 아니라 관리가 매우 어려운 작업입니다. 해당 시스템을 총체적으로 알고 있다는 가정에서 해야 하며 정책적으로 규정해야 하는 것들도 있습니다. 하지만 결과물 그 자체에 대한 관리를 위해서는 없어서는 안되는 도구이며 정적분석과 자동화 테스트 등 다양한 효과를 얻을 수 있기 때문에 많은 개발자들에게 권장하고 싶습니다.#토스랩 #잔디 #JANDI #개발 #효율 #자동화툴 #업무환경
조회수 2063

칸반(Kanban) 5개월 사용 후기

사실 개발 방법론이라는 것을 7개월 전만 해도 귓등으로 듣고 그게 왜 필요한지도 알지 못했던 것이 사실입니다. 부끄럽지만 애자일이 수많은 프로그래밍 언어중 하나인줄 알았죠.10개월 전만해도 우리 팀은 저를 포함해서 3명에 불과했고 모든 것은 메신저와 구글 드라이브로 일을 처리했습니다. 기억력이 좋지않지만 머릿속에서 각 팀원들이 언제까지 뭘하고 다음엔 무엇을 언제까지 해야겠다라는 것이 그려질 정도로 적은 숫자였죠. 개발방법론이 필요한 이유가 없으니 무관심한 것은 당연했습니다. 이 글을 읽으시는 분들 중에 아마 7개월 전의 저와 같은 생각을 하신 분이 있을지도 모르겠네요.지금 우리 팀은 11명으로 늘어났고(그중에 소프트웨어 개발팀만 7명) 그들 하나하나를 마이크로 매니징하기에는 저라는 인간이 너무나 머리가 아팠습니다. 그래서 도입한 것이 애자일 개발방법론이었는데 애자일은 비록 실패로 끝났지만 거기서 많은 교훈을 얻고 칸반으로 전환하는 원동력이 되었습니다.우리 팀은 애자일 개발선언 중에서도 "계획을 따르기보단 변화에 대응하기"라는 선언을 굉장히 맘에 들어했는데, 그 이유는 애자일 도입이전 우리의 상황이 그랬기 때문이었습니다. 매일매일 고객의 요구는 들어오고 경영진과의 대화에서 매일매일 우선순위가 바뀌고, 그에 따라 하던 작업이 마무리되지 않으면 브랜치를 새로 파서 다른 작업을 하고 미완성된 코드는 늘어났으며 그에 따라 불평불만도 늘어났습니다.여러 애자일 개발방법론 중에서도 우리가 선택했던 것은 eXtreme Programming(XP)이었는데, 우리에게 스크럼과 같은 1달간의 스프린트는 너무 길다, 2주간의 이터레이션(Iteration)으로 구성된 XP가 좋다라는 것이었습니다.우리는 스크럼 보드를 준비했고 거기에 포스트잇을 붙여가면서 아침마다 스크럼 회의를 했으며, 기록을 남기기위해 레드마인을 사용하였습니다.eXtreme Programming Flow Chart간단하게 왜 실패했는지 이유를 들어볼게요.1. 배포 계획(Release Plan)을 수립하기 힘들다물론 계획자체를 만들기 힘들다는 것이 아닙니다. 배포 계획을 만들어도 그대로 지켜지지 않았습니다. 큰 틀로 배포 계획을 만들고 작은 틀로 반복 계획(Iteration Plan)을 세우는 것이 목표였는데, 수립을 해봤자 절대 지켜지지 않았습니다. 우리와 같은 작은 스타트업의 작은 팀은 시장의 요구사항이라는 급류에 이리저리 쓸려 매일매일 계획과는 다른 일을 하고 있었거든요. 리팩토링할 시간은 커녕 테스트 코드를 짤 시간조차 없었습니다.(핑계일수도 있지만요)거짓말이 아니고 단 한번도 계획대로 되지 않았습니다.2. 팀원들의 시간 예측 능력 부족애자일은 팀원들이 시간 예측을 굉장히 잘한다는 가정하에 잘 돌아가는 방법론입니다. 모두가 함께 한자리에 모여 복잡도를 논의하고 그에 따른 프로젝트의 시간 예측을 하고 함께 번다운 차트(Burn-down chart)를 그리며 하하호호 잘 나아가야 하는데, 우리 팀은 그렇지 않았습니다. 물론 실력부족이라고 탓할 수도 있겠지만 실제로 스크럼 보드에 예측시간 8시간이라고 적어놓고 4시간정도만 지나면 다른 문제가 터지거나 다른 기능을 개발해야하는 둥 제대로 지켜지지 않았을 뿐더러 그런 방해요소가 없다고 하더라고 8시간보다 더 많이 걸리거나 더 적게 걸리기도 했습니다.예측시간을 측정하기 힘든 마이너한 이유중에 하나는, 스파이크 솔루션(Spike solution)를 개발하는데 얼마나 걸리는지 예측하지 못한 탓도 있었는데 이 세상에 없는 솔루션을 개발하는데 있어 이전의 경험만으로는 턱없이 부족했습니다.이런 이유들 때문에 우리는 XP를 버릴 수 밖에 없었습니다. 계획보다는 변화에 적응하자!라는 원대한 목표가 있었지만 애자일 개발방법론은 우리가 닥친 미친듯한 변화를 감당하기에는 벅찼습니다. 우리는 스크럼 보드를 점점 멀리하기 시작했고 다시 구글 드라이브로 돌아갔습니다.저는 구글 문서(Google Docs)에 우리가 해야할 요구사항을 적었습니다. 우선순위가 높은 일일 수록 상단에 두었습니다. 그 오른쪽에는 일을 해야할 사람의 이름을 적었습니다. 그렇게 적고 문서를 공유하면 팀원들은 그 문서를 보고 그 순서대로 일을 진행하였습니다. 일을 진행하다가 생기는 의문점은 급한 일일 경우 구두로 전달하고 급하지 않을 경우에는 메신저 또는 문서의 빈공간을 활용하여 적었습니다.완료된 요구사항은 취소선을 긋고 옅은 글씨로 처리하여 해야 할일과 완벽히 구분되도록 하였으며 한 사람당 해당 시간에 하나의 일만 처리하도록 규칙을 세웠습니다. 보류되는 일은 보류 섹션으로 할일을 옮기고 보류가 되는 이유를 적도록 했습니다. 혼자 해결하기 힘들경우 회의를 통하여 함께 해결할 수 있는 자리를 마련했구요.그런식으로 우리는 배포 시기를 최대한 맞추려고 노력했고 이상하게도 XP를 버리고 구글 문서로 갈아타니 일이 더욱 수월해져서 이제는 생각보다 일이 빨리 끝나는 것이었습니다. 그리고 더욱 놀라운 일은 지금까지 우리가 했던 방식이 칸반과 유사하다는 것이었습니다.저는 바로 칸반 보드를 도입했고 이에따라 애자일에서 배운 규칙/정신과 칸반의 장점을 혼합하여 우리 팀만의 칸반보드를 완성하였습니다. 현재 우리가 쓰고 있는 칸반 보드는 Kanboard의 오픈소스를 그대로 사용하고 있습니다.1. 활발한 커뮤니케이션을 토대로 개발한다. 절대 혼자 일하지 않는다- 지속적으로 팀의 동의(Team agreement)를 구한다.- Knoledge island를 탈출하라(자신이 알고있는 지식이 전부가 아니다).- 코드 병목현상(Code bottleneck)을 탈출하라. Collective ownership을 발동하라.2. 한 번에 한개의 일만 처리하라. 보류하는 일은 최소로 하라칸반의 핵심으로 한 번에 한개의 일만 처리하도록 합니다. 개발자의 뇌는 하나도 손은 두개이고 손가락은 열개이므로 한 번에 하나의 일만 처리해야 합니다. 한 개의 일이 끝나지 않으면 다음 일을 진행하지 않는 것을 규칙으로 합니다.3. 가능하다면 예측시간을 적는 습관을 들인다개발완료시간을 정확히 예측하는 것은 개발자들에게 정말 중요한 능력중에 하나입니다. 신제품을 시장에 빨리 내놓을 수록 피드백을 빨리 받을 수 있으며, 고객으로부터의 소중한 피드백은 개선된 다음 버전을 위한 초석이 되기 때문입니다. 사업적으로 성공하고 싶다면 예측시간을 꼭 적는 습관을 들여 자신이 정해진 시간 동안 얼마만큼의 일을 할 수 있는지 예측하는 일이 큰 도움이 됩니다.4. 더 좋은 방법이 있다면 기존의 방법을 과감히 버린다저의 철학과도 일치하는 이야기인데요, 우리 팀과 회사가 함께 좋아질 수 있는 방법을 발견한다면 과감히 현재의 방법을 버리고 새로운 방법을 시도한다라는 우리 팀만의 맹세입니다. 앞으로 항상 발전하겠다는 의지를 가지고 잠시 손을 놓고 한발짝 물러서서 비판적인 자세로 모든 것을 바라보는 시간을 가지는 것도 혁신의 첫발짝이라고 생각합니다.지금까지 우리 팀이 꾀한 겉으로 보기에 가장 큰 혁신은 기존의 속도가 느리고 사용하기 불편했던 솔루션을 과감히 버리고 새로운 서버와 새로운 언어로 전환하면서 마이그레이션 및 새로운 형태의 최적화된 솔루션을 구축했다는 것입니다.(물론 내부적으로 가장 큰 혁신은 기존의 방법을 버릴 수도 있다라는 생각을 가졌다는 것이지요)현재 저는 팀 매니저로서 User story(요구사항정의서) 관리, Release plan(배포 계획서), 와이어프레임을 포함한 기획서 등 최소한의 문서만 관리하고 있으며, 팀원들 또한 이 시스템에 만족하며 아직까지는 판단하기 이르지만 굉장히 좋은 방법인것 같습니다.5개월간 칸반을 사용하면서 팀원들로부터 받은 피드백은 다음과 같습니다.1. 매일 아침 15분씩 하는 스크럼 회의는 새로운 기능 또는 새로운 프로젝트를 진행할 때는 굉장히 유용하지만, 디버깅 또는 테스팅 기간에는 시간낭비다.이 말을 한 팀원의 말에 따르면, 우리 팀은 데이터베이스를 관리하는 사람, API를 만드는 사람 등등 각자의 역할이 확실히 나누어져 있는데 새로운 기능을 개발할때는 여러사람과 소통해야하는 경우가 많고 개발 스펙이 달라지거나(작게는 함수이름 변경 등) 여러 변수들이 작용할 수 있으므로 짧게 자주만나는 것이 좋다고 말했습니다.2. 회의도 시간낭비다- 회의는 가급적 개최하지 않고 가능하다면 1:1 구두로 해결한다.- 급한일이 아닐경우에는 이메일/메신저를 활용하도록 한다.3. 칸반 보드에 보류 칼럼, 테스팅 칼럼을 나눈다보류 칼럼과 테스팅 칼럼을 나누어 적어 어떤 할일이 보류되었으며 어떤 할일이 테스팅 중인이 확실히 하도록 했습니다. 이는 테스팅을 하는데 오래걸리는 기능들이 있으며 테스팅을 하는 동안 다른 기능을 개발할 수도 있다는 것이 큰 이유였습니다.우선 순위가 바뀌었을 때 할 일을 잠시동안 놓아둘 칼럼이 없다는 것이 보류 칼럼이 존재하는 가장 큰 이유였습니다. 그러나 보류 칼럼에 놓을 수 있는 할 일의 수는 개인당 1개로 제한하여 2개 이상의 보류하는 일이 없도록하여 경각심을 갖도록 하였습니다.앞으로의 계획은 전에 언급했던 와비파커(Warby Parker)의 기술팀이 도입한 와블스(Warbles) 시스템을 적용해보는 것입니다. 우리 팀이 어떻게 바뀔지 정말 기대가 됩니다.#비주얼캠프 #인사이트 #경험공유 #조언 #개발자 #개발팀
조회수 1433

코인원 마이페이지가 더욱 더 새로워졌습니다 :) - 유저플로우셀 팀터뷰

웹서비스에서 나만의 서비스 이용내역과 개인정보를 확인할 수 있는 공간을 ‘마이페이지'라고 하죠. 유저들은 마이페이지를 통해 나의 상태를 체크하며 해당 서비스에 좀 더 애착을 갖기도 합니다. 이번에 코인원 마이페이지도 더욱 더 새로워지면서 애정이 가득해졌다는 유저들의 제보가 속속 들어오고 있어요!오늘은 코인원 마이페이지를 새롭게 탄생시킨 유저플로우셀 예은님, 정유님, 현진님, 종헌님과 함께 마이페이지의 모든 것을 파헤쳐보겠습니다.코인원 유저플로우셀은 트레이딩 영역을 제외한 전반적인 서비스 영역을 담당하고 있습니다. 각 서비스에 대한 유저 경로 동선을 만들고 서비스를 제공하며, 누구나 거래를 하고 싶은 코인원을 만들고 있답니다. :-)Q. 안녕하세요, 유저플로우셀 여러분. 자기소개와 함께 현재 업무를 소개해주세요!예은 : 유저플로우셀에서 서비스 기획자로 일하고 있는 지예은입니다. 저는 코인원 유저들이 겪는 문제상황과 UX트렌드 분석을 통해 기존의 서비스를 개선하고 고도화하고 있어요.정유 : 프로덕트 디자이너로 일하고 있는 이정유입니다. 유저플로우셀은 유저와 거래소를 이어주는 모든 페이지를 담당하고 있어요. 저는 기획자들과 함께 유저의 니즈를 페이지에 UI(User Interface)적으로 어떻게 반영할지 고민하고, 이를 디자인 시스템에 녹여 시각적 일관성을 전달합니다.  현진 : 프론트엔드 개발자로 불철주야 개발 중인 박현진입니다. 프론트엔드는 한마디로 코인원 프로덕트에서 실제로 유저들에게 보여지는 웹화면이에요. 저는 유저들에게 보이는 영역을 책임지며 프로그래밍하고 있습니다.종헌 : 웹 API를 담당하고 있는 백엔드 개발자 김종헌입니다. 프론트엔드가 유저에게 보이는 영역을 담당한다면, 저는 보이지 않는 곳인 백엔드에서 입출금 서비스, 거래기록, 개인정보 등 코인원의 다양한 서비스와 유저를 연결하고 있어요.Q. 이번에 마이페이지 개선이 대대적으로 진행되었습니다. 어떤 계기와 방향성으로 개선하게 되었나요?예은 :  마이페이지 개선은 유저의 고충을 파악하기 위한 코인원 고객센터 인터뷰에서 시작되었습니다. 거래소 이용에 필요한 인증, 계정 보안에 대한 관리가 익숙하지 않은 유저들의 ‘페인 포인트(Pain Point)’를 발견했거든요. 서비스 기획자, 디자이너, 개발자가 함께 모여 UI나 정보로 사용자에게 도움을 주고 CS비용을 최소화 할 수 있는 방법을 고민하기 시작했습니다. 우선, ‘마이페이지'는 코인원 서비스를 이용하는 유저 개개인을 챙겨주는 공간이라고 생각합니다. 이번 개선 과정에서 가장 중점을 둔 부분도 ‘고객을 챙겨주는 마이페이지' 경험을 전달하는 것이었어요. 이렇게 설정된 방향성에 따라 유저들의 상태별로 필요한 상황을 안내하도록 구성했습니다. 한마디로 ‘유저 맞춤형 마이페이지’로 진화한겁니다!▲ 더욱 더 새로워진 코인원 마이페이지정유 : 이전의 마이페이지는 엉켜있는 플로우로 인해, 유저가 어떤 상태인지, 어떤 인증과정을 거치고 있는지 인지하기가 힘들었습니다. 목적을 달성하기 위해 마이페이지에 접속했지만 목적 달성을 끝마칠 수 없었죠. 먼저 흩어져 있는 기능, 정보, 구조들을 그룹핑하며 플로우를 개선하는 작업을 시작했어요. 아이데이션 과정을 거치면서 마이페이지를 ‘내 서랍, 내 방' 등 나만의 정체성을 확인할 수 있는 키워드로 정의했습니다. 그리고 키워드를 확장시켜 ‘나의 데이터'를 한 눈에 관리할 수 있는 대시보드 형태의 디자인을 지향하게 되었어요. 결과적으로 현재 마이페이지에는 나의활동, 개인정보관리, 인증단계 총 3 개의 탭으로 위계를 설정했습니다. :D▲ 코인원 거래소 인증단계가 훨씬 간편해졌습니다!Q. 기술적으로는 어떤 변화가 있었을까요?현진 : 마이페이지를 포함해서 코인원 웹 프로덕트에 기술부채(Technical Debt)가 조금씩 쌓여 있었어요. 이 부분을 덜어내기 위해 마이페이지를 개선하면서 ‘기획/디자인/개발’ 삼박자로 변화를 주는 리빌딩(Re-building)을 진행했습니다. 덕분에 기술적으로 관리 포인트가 많이 줄었어요. 이제는 웹 유지/보수가 좀 더 용이하게 되었답니다.종헌 : 그 동안 코인원 웹은 하나의 비대한 서비스로 운영되었습니다. 하나의 서비스가 덩치가 점점 커지다 보니 개발자가 서비스 로직을 온전히 이해하기 어려웠어요. 웹을 유지하고 보수하거나, 새로운 기능을 추가하는 것도 쉽지 않았습니다. 그래서 하나의 비대한 서비스를 여러 개의 작은 서비스로 나누는 작업인 리빌딩을 진행했어요. 여러 작은 서비스로 분리하고 책임 영역을 나누면서 서비스 로직에 대해 제대로 이해하고 체계적으로 코드를 작성할 수 있게 되었습니다.    Q. 마이페이지 개선 전과 후, 달라진 점을 말씀해주세요.예은 : 코인원 마이페이지는 이전보다 유저들에게 더욱 친근하게 다가가고 있습니다. 마이페이지의 콘텐츠가 유저의 상태에 맞춰 변화하며, 유저마다 다음 인증 과정이나 활동 내역을 다르게 안내합니다. 유저가 기능을 먼저 찾지 않아도, 마이페이지가 길을 찾아주는 가이드의 형태를 띄고 있어요.또한 인증단계 별로 수수료나 회원등급이 달라지는데, 유저들이 하나하나 가이드를 보며 찾아볼 수는 없다고 생각해요. 한눈에 자신의 상태를 파악할 수 있도록 UI를 활용하는 것이 중요한 부분이죠. 마이페이지의 개선된 UI로 유저가 코인원의 서비스 정책을 한층 더 깊게 이해하는데 도움이 되었으면 해요.정유 : 유저가 코인원 프로덕트와의 관계성을 인지할 수 있는 디테일들이 추가되었습니다. 가장 대표적인 예시로는 ‘코인원과 함께한 지 000일째 입니다.’라는 문구가 있겠네요. 코인원 유저들에게 ‘챙겨준다'라는 느낌을 전달하기 위해 정말 많은 회의와 아이데이션을 거쳤습니다. 그 과정 중 나왔던 아이디어인데 이번에 반영하게 되었어요. ‘제품’보다는 ‘서비스'로서 느껴질 수 있도록, 대화하는 느낌을 잘 살려주는 포인트이기에 매우 뿌듯했죠.▲ 심...심쿵....!!!!!현진 : 개발자 입장에서 바라봤을 때, 페이지 애니메이션이 가장 좋았어요. 페이지 애니메이션은 웹페이지가 다른 웹페이지로 이동할 때 발생하는 애니메이션을 말합니다. ‘툭' 하고 넘어가는 것이 아니라 ‘sha~(?)’ 하게 넘어가는 느낌이라고 할까요. 페이지와 페이지 사이가 하나의 관계성을 가지고 넘어가게 됩니다. 유저들은 ‘암호화폐 거래소에서 마이페이지에 이런 디테일한 부분까지 신경쓰고 있구나’를 느낄 수 있을거에요. 또한 에러메시지, 경고메시지와 같은 피드백 인터랙션도 정교해졌어요. 사용자와 교감할 수 있는 쪽에 코인원만의 감성이 잘 버무려졌습니다.종헌 : 이전의 코인원 프로필 서비스는 사용빈도가 높지는 않았어요. 그라바타(Gravatar)라는 외부서비스를 사용했는데, 이것을 사용하지 않는 유저들에게 친숙하지 않았거든요. 이제는 코인원에서 프로필 이미지를 정해두고 원하는 이미지로 클릭해서 쉽게 변경할 수 있게 설정했어요. 참고로 프로필 이미지를 설정하는 것이 보안측면에서도 좋습니다. 예를 들어, 은행에서는 프로필 이미지를 설정하면 바로 내가 사용하는 계정인지 아닌지를 알 수 있어요. 코인원에서도 프로필 이미지를 설정하면 내가 가입한 계정인지 아닌지 식별이 가능합니다.▲ 프로필 사진 설정 기능도 많이 이용해주세요 :)Q. 마이페이지의 개선 작업 과정에서 많은 고민이 있으셨을 것 같아요. 가장 중점적으로 생각했던 부분이 있었나요?정유 : 가장 중점이 되었던 부분은 서비스를 이용하는 유저 개개인의 상태를 반영하는거였어요. 유저별로 동일한 정보가 아닌 맞춤형 정보를 제공하기 때문에 한 페이지 안에 들어가는 정보의 위계가 상태값에 따라 계속 변하는 것이 관건이었습니다. 예를 들어, 마이페이지에는 나의 정보를 업데이트하기 위한 많은 버튼들이 들어갑니다. 그럼 유저 케이스별로 중요한 정보를 바꿔보면서 어떤 버튼이 가장 위계가 높은지 고민하고 계산해요. 이러한 과정을 거치면서 유저의 상태값을 쉽게 알려주고 변경할 수 있는 디자인이 완성되었습니다. 예은 : 기존부터 유저 인터뷰를 진행하며 ①신규 유저 ②타사 이용 유저 ③거래소 이용에 문제를 겪고 있는 유저 ④코인원을 오래 이용해준 고마운 유저 케이스까지 다양한 상황에 놓여있는 유저들에게 만족스러운 UX 경험을 드리기 위해 고민해왔습니다. 특히 운영지원셀과 코인원 고객센터 CS로 인입되는 주요 인터뷰들을 중점적으로 수집하여 인증과정에 문제가 되는 것들을 모아서 개선회의를 해왔어요. 이외에 마케팅, 프로덕트쪽도 함께 서비스를 제공하는 공급자 입장에서의 니즈도 취합해 마이페이지에 반영할 수 있었습니다.▲ (절대 설정샷 아니에요) 훈훈하게 회의중인 유저플로우셀!Q. 혹시 개선된 마이페이지를 이용한 코인원 고객들의 후기도 있었나요?예은 : 개선된 마이페이지로 바뀐 지 얼마되지 않아, 유저의 피드백을 직접적으로 접하지는 못했어요. 대신 정량적인 부분에서 여러 수치들이 올라간 것을 확인할 수 있었습니다. 대략적으로 재방문자의 UV(Unique Visitor)수가 개선 전과 대비해서 약 70%정도 크게 증가했습니다. 이전에는 회원가입을 끝마치고 인증과정 중에 페이지를 이탈한 유저도 보였지만, 개선된 후에는 마이페이지 탭 이용빈도가 크게 올라갔습니다. 마이페이지가 좀 더 원활한 거래소 서비스 이용을 위한 가이드 역할을 해주길 기대하면서, 지속적으로 니즈를 관찰하고 개선해 나갈 예정입니다.Q. 마이페이지 이외에도 기억에 남는 유저플로우셀의 프로젝트가 있나요?예은 : 코인원의 수익현황을 한 눈에 볼 수 있는 자산탭이 기억에 남아요. 그 동안 코인원 유저들이 수익률을 확인할 수 있는 기능을 많이 요청했었는데, 팀원들이 함께 고민하여 새로 개편한 기능이라서 그 의미가 컸어요.정유 : 저는 실질적으로 프로젝트에 돌입하기 전에 진행했던 코인원 유저 인터뷰가 가장 기억에 남아요. 인터뷰 내용이 개선점으로 가득찰 줄 알았는데, 응원의 목소리를 전달해주셨거든요. 더 열심히 UI 디자인을 해야겠다는 의욕을 불타오르게 해주었어요!현진 : 코인원 웹프로덕트를 사용하시는 분들이 눈치 채셨는지 모르겠지만, 마이페이지 이전부터 진행해왔던 리빌딩 프로젝트(랜딩, 거래소, 프로차트, 코인원 톡 등)들이 기억에 남아요. 사실 마이페이지 이전 리빌딩 프로젝트들은 기술적으로만 접근하다보니 우여곡절이 많았어요. 그래도 마이페이지 리빌딩은 업무적으로도 많이 배우고, 기술 뿐만 아니라 전체적으로 변화한 것이 보여 저 또한 성장하는 시간이었습니다.종헌 : 이외에도 유저플로우셀은 UX개선을 여러 프로젝트와 함께 진행하고 있습니다. 정신없긴 하지만 개발요소도 새롭고 다이나믹한 것이 많아서 즐겁게 하고 있습니다!▲ 화기애애하게 UI 시안을 보고 있는(?) 유저플로우셀Q. 코인원에서 디자이너 그리고 개발자로 일하는 큰 장점은 무엇인가요?예은 : 코인원에선 셀마다 다른 직무의 인원들이 빠르게 소통하여 의사결정하는 목적조직 형태로 일합니다. 중간중간 기획리뷰, 디자인리뷰 과정을 거치면서 더 꼼꼼하게 일하고, 다른 직무에 계신 분들의 작업도 공유하고 있어요. 거래소에서 일어날 수 있는 다양한 문제 상황을 긴밀하게 대응하고 있죠.정유 : 현재 코인원은 ‘셀(Cell)’이라는 목적조직 형태입니다. PM, 개발자, 디자이너가 한 조직에 속하다보니 Output 나오는 속도가 매우 좋아졌습니다. 또한 여러 직군이 함께 팀웍을 맞추다보니 서비스를 다양한 각도에서 바라볼 수 있고, 이는 디자이너로서 서비스 이해도를 높이는데 굉장히 좋은 환경이라고 생각해요.  종헌 : 코인원은 개발자도 기획 단계부터 적극적으로 참여하여 프로젝트를 설계하고 있습니다. 이로 인해 개발을 하다 예기치 않은 변수가 생기는 일이 거의 발생하지 않아요. 또한 정기적으로 회고를 하며 프로세스의 문제점을 도출해내고, 개선을 위해 다양한 시도를 해볼 수 있다는 것도 장점입니다. 현진 : 현재 코인원 기술본부는 트렌디한 기술을 곳곳에 사용하고 있어요. 기술에 민감하게 반응하는 프론트엔드 개발자분이 코인원에 온다면 기술적으로 매우 만족하실거에요. Q. 앞으로 이루고 싶은 목표는 무엇인가요?예은 : 암호화폐 거래소는 UX를 기획하기에 매우 도전적인 분야입니다. 블록체인 기술이 곳곳에서 화제가 되고 있지만, 아직 업계의 워딩이나 사용에서의 유저 친화적 성숙도가 높지 않은것 같아요. 앞으로의 목표는 누구나 쉽게 거래할 수 있는 암호화폐 거래소를 만드는 것입니다. 점점 더 발전하는 코인원의 모습을 많이 기대해주세요!정유 : 코인원 UI에는 아직 블록체인 공급자적 시선이 많이 담겨있어요. 예를들어, 개발자가 아니면 이해하기 어려운 용어나 UI가 남아있는 부분이 있거든요. 이를 디자인적으로 해소하고 싶습니다. 유저가 갖고 있는 암호화폐 거래 장벽을 낮추고, 코인원의 가치가 잘 반영된 프로덕트를 만드는 것이 목표에요. 종헌 : 코인원에서는 트레이딩 이외에도 여러가지 서비스들을 유저에게 제공하는 다양한 시도를 하고 있어요. 저는 다양한 서비스들을 연결하면서 서비스의 안전장치를 견고하게 쌓아올리고 싶네요. 장애 발생에도 끄떡없는 안정적인 코인원을 유저에게 선보이고 싶습니다.현진 : 대한민국에서 적어도 사용성 1위 암호화폐 거래소를 만들거에요. 유저플로우셀에서 마이페이지 이후에도 많은 프로젝트를 준비하고 있거든요. 매주(?) UX가 점차적으로 개선되는 코인원 거래소의 모습을 확인할 수 있을 거에요. 마지막으로 꼭 하고싶은 말이 있는데, 코인원에 많은 개발자분들이 지원해주셨으면 좋겠어요. 아직 업계에 부정적인 인식이 강하지만, 블록체인이 발전하는 과정을 보며 점차 해소될거라고 믿어요. 기술적으로 발전할 가능성이 무궁무진한 곳이니 기술적인 욕심을 채우고 싶은 분들, 함께 성장하고 싶으신 분들 코인원으로 오세요!▲ 코인원 유저플로우셀 많이 기대해주세요!무엇보다도 긍정적인 에너지로 가득찼던 유저플로우셀의 인터뷰를 들어봤어요.코인원 마이페이지에 큰 변화를 가져온 활기찬 에너지, 다들 느끼셨나요?마이페이지 이후에도 다양한 프로젝트를 준비하고 있는 유저플로우셀. 곧 코인원 웹 거래소를 사용하면서 UX적으로 편리한 사용성을 경험할 수 있을겁니다.끝으로, 특별한 문화를 경험할 기회! 코인원 채용에 함께하는 것도 잊지 마세요 :-)
조회수 980

비트윈 시스템 아키텍처

VCNC는 커플을 위한 모바일 앱 비트윈을 서비스하고 있습니다. 비트윈은 사진, 메모, 채팅, 기념일 등 다양한 기능을 제공하며, 오픈 베타 테스트를 시작한 2011년 11월부터 현재까지 연인 간의 소통을 돕고 있습니다. 그동안 비트윈 시스템 아키텍처에는 많은 변화가 있었으며 다양한 결정을 하였습니다. 비트윈 아키텍처를 발전시키면서 배우게 된 여러 가지 노하우를 정리하여 공유해보고자 합니다. 그리고 저희가 앞으로 나아갈 방향을 소개하려 합니다.소프트웨어 스택Java: 비트윈 API서버는 Java로 작성되어 있습니다. 이는 처음 비트윈 서버를 만들기 시작할 때, 서버 개발자가 가장 빨리 개발해낼 수 있는 언어로 프로그래밍을 시작했기 때문입니다. 지금도 자바를 가장 잘 다루는 서버 개발자가 많으므로 여전히 유효한 선택입니다.Netty: 대부분의 API는 HTTP로 호출되며, 채팅은 모바일 네트워크상에서의 전송 속도를 위해 TCP상에서 프로토콜을 구현했습니다. 두 가지 모두 Netty를 통해 사용자 요청을 처리합니다. Netty를 선택한 것은 뛰어난 성능과 서비스 구현 시 Thrift 서비스를 통해 HTTP와 TCP 프로토콜을 한 번에 구현하기 쉽다는 점 때문이었습니다.Thrift: API서버의 모든 서비스는 Thrift 서비스로 구현됩니다. 따라서 TCP뿐만 아니라 HTTP 또한 Thrift 인터페이스를 사용합니다. HTTP를 굳이 Thrift서비스로 구현한 이유는, TCP로 메세징 전송 시 똑같은 서비스를 그대로 사용하기 위함이었습니다. 덕분에 빠른 채팅 구현 시, 이미 구현된 서비스들을 그대로 사용할 수 있었습니다. 또한, 채팅 패킷들은 패킷 경량화를 위해 snappy로 압축하여 송수신합니다. 모바일 네트워크상에서는 패킷이 작아질수록 속도 향상에 크게 도움이 됩니다.HBase: 비트윈의 대부분 트랜젝션은 채팅에서 일어납니다. 수많은 메시지 트랜젝션을 처리하기 위해 HBase를 선택했으며, 당시 서버 개발자가 가장 익숙한 데이터베이스가 HBase였습니다. 서비스 초기부터 확장성을 고려했어야 했는데, RDBMS에서 확장성에 대해 생각하는 것보다는 당장 익숙한 HBase를 선택하고 운영하면서 나오는 문제들은 차차 해결하였습니다.ZooKeeper: 커플들을 여러 서버에 밸런싱하고 이 정보를 여러 서버에서 공유하기 위해 ZooKeeper를 이용합니다. Netflix에서 공개한 오픈 소스인 Curator를 이용하여 접근합니다.AWS비트윈은 AWS의 Tokyo리전에서 운영되고 있습니다. 처음에는 네트워크 및 성능상의 이유로 국내 IDC를 고려하기도 했으나 개발자들이 IDC 운영 경험이 거의 없는 것과, IDC의 실질적인 TCO가 높다는 문제로 클라우드 서비스를 이용하기로 하였습니다. 당시 클라우드 서비스 중에 가장 안정적이라고 생각했던 AWS 를 사용하기로 결정했었고, 지금도 계속 사용하고 있습니다.EC2: 비트윈의 여러 부가적인 서비스를 위해 다양한 종류의 인스턴스를 사용 중이지만, 메인 서비스를 운용하기 위해서는 c1.xlarge와 m2.4xlarge 인스턴스를 여러 대 사용하고 있습니다.API 서버: HTTP 파싱이나 이미지 리시아징등의 연산이 이 서버에서 일어납니다. 이 연산들은 CPU 가 가장 중요한 리소스이기 때문에, c1.xlarge를 사용하기로 했습니다.Database 서버: HDFS 데이터 노드와 HBase 리전 서버들이 떠있습니다. 여러 번의 테스트를 통해 IO가 병목임을 확인하였고, 따라서 모든 데이터를 최대한 메모리에 올리는 것이 가장 저렴한 설정이라는 것을 확인하였습니다. 이런 이유 때문에 68.4GB의 메모리를 가진 m2.4xlarge를 Database 서버로 사용하고 있습니다.EBS: 처음에는 HBase상 데이터를 모두 EBS에 저장하였습니다. 하지만 일정 시간 동안 EBS의 Latency가 갑자기 증가하는 등의 불안정한 경우가 자주 발생하여 개선 방법이 필요했는데, 데이터를 ephemeral storage에만 저장하기에는 안정성이 확인되지 않은 상태였습니다. 위의 두 가지 문제를 동시에 해결하기 위해서 HDFS multiple-rack 설정을 통해서 두 개의 복제본은 ephemeral storage에 저장하고 다른 하나의 복제본은 PIOPS EBS에 저장되도록 구성하여 EBS의 문제점들로부터의 영향을 최소화하였습니다.S3: 사용자들이 올리는 사진들은 s3에 저장됩니다. 사진의 s3키는 추측이 불가능하도록 랜덤하게 만들어집니다. 어차피 하나의 사진은 두 명밖에 받아가지 않고 클라이언트 로컬에 캐싱되기 때문에 CloudFront를 사용하지는 않습니다.ELB: HTTP는 사용자 요청의 분산과 SSL적용을 위해 ELB를 사용합니다. TCP는 TLS를 위해 ELB를 사용합니다. SSL/TLS 부분은 모두 AWS의 ELB를 이용하는데, 이는 API서버의 SSL/TLS처리에 대한 부담을 덜어주기 위함입니다.CloudWatch: 각 통신사와 리전에서 비트윈 서버로의 네트워크 상태와 서버 내의 요청 처리 시간 등의 메트릭을 CloudWatch로 모니터링 하고 있습니다. 따라서 네트워크 상태나 서버에 문제가 생긴 경우, 이메일 등을 통해 즉각 알게 되어, 문제 상황에 바로 대응하고 있습니다. Netflix의 Servo를 이용하여 모니터링 됩니다.현재의 아키텍처처음 클로즈드 베타 테스트때에는 사용자 수가 정해져 있었기 때문에 하나의 인스턴스로 운영되었습니다. 하지만 처음부터 인스턴스 숫자를 늘리는 것만으로도 서비스 규모를 쉽게 확장할 수 있는 아키텍쳐를 만들기 위한 고민을 하였습니다. 오픈 베타 이후에는 발생하는 트래픽에 필요한 만큼 여러 대의 유연하게 서버를 운영하였고, 현재 채팅은 TCP 위에서 구현한 프로토콜을 이용하여 서비스하고 있습니다.HTTP 요청은 하나의 ELB를 통해 여러 서버로 분산됩니다. 일반적인 ELB+HTTP 아키텍처와 동일합니다.채팅은 TCP 연결을 맺게 되는데, 각 커플은 특정 API 서버로 샤딩되어 특정 커플에 대한 요청을 하나의 서버가 담당합니다. 비트윈에서는 커플이 샤딩의 단위가 됩니다.이를 통해, 채팅 대화 내용 입력 중인지 여부와 같이 굉장히 빈번하게 값이 바뀌는 정보를 인메모리 캐싱할 수 있게 됩니다. 이런 정보는 휘발성이고 매우 자주 바뀌는 정보이므로, HBase에 저장하는 것은 매우 비효율적입니다.Consistent Hashing을 이용하여 커플을 각 서버에 샤딩합니다. 이는 서버가 추가되거나 줄어들 때, 리밸런싱되면서 서버간 이동되는 커플들의 수를 최소화 하기 위함입니다.클라이언트는 샤딩 정보를 바탕으로 특정 서버로 TCP연결을 맺게 되는데, 이를 위해 각 서버에 ELB가 하나씩 붙습니다. 어떤 서버로 연결을 맺어야 할지는 HTTP 혹은 TCP 프로토콜을 통해 알게 됩니다.Consistent Hashing을 위한 정보는 ZooKeeper를 통해 여러 서버간 공유됩니다. 이를 통해 서버의 수가 늘어나거나 줄어들게 되는 경우, 각 서버는 자신이 담당해야 하는 샤딩에 대한 변경 정보에 대해 즉각 알게 됩니다.이런 아키텍처의 단점은 다음과 같습니다.클라이언트가 자신이 어떤 서버로 붙어야 하는지 알아야 하기 때문에 프로토콜 및 아키텍처 복잡성이 높습니다.서버가 늘어나는 경우, 순식간에 많은 사용자 연결이 맺어지게 됩니다. 따라서 새로 추가되는 ELB는 Warm-up이 필요로 하며 이 때문에 Auto-Scale이 쉽지 않습니다.HBase에 Write연산시, 여러 서버로 복제가 일어나기 때문에, HA을 위한 Multi-AZ 구성을 하기가 어렵습니다.한정된 자원으로 동작 가능한 서버를 빨리 만들어내기 위해 이처럼 디자인하였습니다.미래의 아키텍처현재 아키텍처에 단점을 보완하기 위한 해결 방법을 생각해보았습니다.Haeinsa는 HBase상에서 트렌젝션을 제공하기 위해 개발 중인 프로젝트입니다. 구현 완료 후, 기능 테스트를 통과하였고, 퍼포먼스 테스트를 진행하고 있습니다. HBase상에서 트렌젝션이 가능하게 되면, 좀 더 복잡한 기능들을 빠르게 개발할 수 있습니다. 서비스에 곧 적용될 예정입니다.Multitier Architecture를 통해 클라이언트와 서버 간에 프로토콜을 단순화시킬 수 있습니다. 이 부분은 개발 초기부터 생각하던 부분인데, 그동안 개발을 하지 못하고 있다가, 지금은 구현을 시작하고 있습니다. 커플은 특정 Application 서버에서 담당하게 되므로, 인메모리 캐싱이 가능하게 됩니다. 클라이언트는 무조건 하나의 ELB만 바라보고 요청을 보내게 되고, Presentation 서버가 사용자 요청을 올바른 Application 서버로 릴레이 하게 됩니다.Multitier Architecture를 도입하면, 더 이상 ELB Warm-up이 필요하지 않게 되므로, Auto-Scale이 가능하게 되며, 좀 더 쉬운 배포가 가능하게 됩니다.Rocky는 API 서버의 Auto-Failover와 커플에 대한 샤딩을 직접 처리하는 기능을 가진 프로젝트입니다. 현재 설계가 어느 정도 진행되어 개발 중에 있습니다. 알람이 왔을 때 서버 팀이 마음을 놓고 편히 잠을 잘 수 있는 역할을 합니다.기본적인 것은 위에서 언급한 구조와 동일하지만 몇 가지 기능이 설정을 추가하면 Multi-AZ 구성이 가능합니다.특정 커플에 대한 모든 정보는 하나의 HBase Row에 담기게 됩니다.HBase의 특정 리전에 문제가 생긴 경우, 일정 시간이 지나면 자동으로 복구되긴 하지만 잠시 동안 시스템 전체에 문제가 생기가 됩니다. 이에 대해 Pinterest에서 Clustering보다는 Sharding이 더 낫다는 글을 쓰기도 했습니다. 이에 대한 해결책은 다음과 같습니다.원래는 Consistent Hashing을 사용하여 커플들을 Application 서버에 샤딩하였습니다. 하지만 이제는 HBase에서 Row를 각 리전에 수동으로 할당하고, 같은 리전에 할당된 Row에 저장된 커플들은 같은 Application 서버에 할당하도록 합니다.이 경우에, 같은 커플들을 담당하는 Application 서버와 HBase 리전 서버는 물리적으로 같은 머신에 둡니다.이렇게 구성 하는 경우, 특정 HBase 리전이나 Application 서버에 대한 장애는 특정 샤드에 국한되게 됩니다. 이와 같이 하나의 머신에 APP과 DB를 같이 두는 구성은 구글에서도 사용하는 방법입니다.이와 같이 구성하는 경우, Multi-AZ 구성이 가능하게 됩니다.AWS에서 같은 리전에서 서로 다른 Zone간 통신은 대략 2~3ms 정도 걸린다고 합니다.Presentation의 경우, 비동기식으로 동작하기 때문에 다른 리전으로 요청을 보내도 부담이 되지 않습니다.HBase에서 Write가 일어나면 여러 복제본을 만들게 됩니다. 하나의 사용자 요청에 대해 Write가 여러번 일어나기 때문에 HBase연산의 경우에는 서로 다른 Zone간 Latency가 부담으로 작용됩니다. Haeinsa가 적용되면, 한 트렌젝션에 대해서 연산을 Batch로 전송하기 때문에 AZ간 Latency 부담이 적습니다.저희는 언제나 타다 및 비트윈 서비스를 함께 만들며 기술적인 문제를 함께 풀어나갈 능력있는 개발자를 모시고 있습니다. 언제든 부담없이 [email protected]로 이메일을 주시기 바랍니다!

기업문화 엿볼 때, 더팀스

로그인

/