스토리 홈

인터뷰

피드

뉴스

조회수 1659

HBase 설정 최적화하기 - VCNC Engineering Blog

커플 필수 앱 비트윈은 여러 종류의 오픈 소스를 기반으로 이루어져 있습니다. 그 중 하나는 HBase라는 NoSQL 데이터베이스입니다. VCNC에서는 HBase를 비트윈 서비스의 메인 데이터베이스로써 사용하고 있으며, 또한 데이터 분석을 위한 DW 서버로도 사용하고 있습니다.그동안 두 개의 HBase Cluster 모두 최적화를 위해서 여러 가지 설정을 테스트했고 노하우를 공유해 보고자 합니다. 아랫은 저희가 HBase를 실제로 저희 서비스에 적용하여 운영하면서 최적화한 시스템 구성과 설정들을 정리한 것입니다. HBase를 OLTP/OLAP 목적으로 사용하고자 하는 분들에게 도움이 되었으면 좋겠습니다. 아래 구성을 최적화하기 위해서 했던 오랜 기간의 삽질기는 언젠가 따로 포스팅 하도록 하겠습니다.HBaseHBase는 Google이 2006년에 발표한 BigTable이라는 NoSQL 데이터베이스의 아키텍처를 그대로 따르고 있습니다. HBase는 뛰어난 Horizontal Scalability를 가지는 Distributed DB로써, Column-oriented store model을 가지고 있습니다. 사용량이 늘어남에 따라서 Regionserver만 추가해주면 자연스럽게 Scale-out이 되는 구조를 가지고 있습니다. 또한, Hadoop 특유의 Sequential read/write를 최대한 활용해서 Random access를 줄임으로 Disk를 효율적으로 사용한다는 점을 특징으로 합니다. 이 때문에 HBase는 보통의 RDBMS와는 다르게 Disk IO가 병목이 되기보다는 CPU나 RAM 용량이 병목이 되는 경우가 많습니다.HBase는 많은 회사가 데이터 분석을 하는 데 활용하고 있으며, NHN Line과 Facebook messenger 등의 메신저 서비스에서 Storage로 사용하고 있습니다.시스템 구성저희는 Cloudera에서 제공하는 HBase 0.92.1-cdh4.1.2 release를 사용하고 있으며, Storage layer로 Hadoop 2.0.0-cdh4.1.2를 사용하고 있습니다. 또한, Between의 데이터베이스로 사용하기 위해서 여러 대의 AWS EC2의 m2.4xlarge 인스턴스에 HDFS Datanode / HBase Regionserver를 deploy 하였습니다. 이는 m2.4xlarge의 큰 메모리(68.4GB)를 최대한 활용해서 Disk IO를 회피하고 많은 Cache hit이 나게 하기 위함입니다.또한 Highly-Available를 위해서 Quorum Journaling node를 활용한 Active-standby namenode를 구성했으며, Zookeeper Cluster와 HBase Master도 여러 대로 구성하여 Datastore layer에서 SPOF를 전부 제거하였습니다. HA cluster를 구성하는 과정도 후에 포스팅 하도록 하겠습니다.HDFS 최적화 설정dfs.datanode.handler.countHDFS에서 외부 요청을 처리하는 데 사용할 Thread의 개수를 정하기 위한 설정입니다. 기본값은 3인데 저희는 100으로 해 놓고 사용하고 있습니다.dfs.replicationHDFS 레벨에서 각각의 데이터가 몇 개의 독립된 인스턴스에 복사될 것 인가를 나타내는 값입니다. 저희는 이 값을 기본값인 3으로 해 놓고 있습니다. 이 값을 높이면 Redundancy가 높아져서 데이터 손실에 대해서 더 안전해지지만, Write 속도가 떨어지게 됩니다.dfs.datanode.max.transfer.threads하나의 Datanode에서 동시에 서비스 가능한 block 개수 제한을 나타냅니다.과거에는 dfs.datanode.max.xcievers라는 이름의 설정이었습니다.기본값은 256인데, 저희는 4096으로 바꿨습니다.ipc.server.tcpnodelay / ipc.client.tcpnodelaytcpnodelay 설정입니다. tcp no delay 설정은 TCP/IP network에서 작은 크기의 패킷들을 모아서 보냄으로써 TCP 패킷의 overhead를 절약하고자 하는 Nagle's algorithm을 끄는 것을 의미합니다. 기본으로 두 값이 모두 false로 설정되어 있어 Nagle's algorithm이 활성화되어 있습니다. Latency가 중요한 OLTP 용도로 HBase를 사용하시면 true로 바꿔서 tcpnodelay 설정을 켜는 것이 유리합니다.HBase 최적화 설정hbase.regionserver.handler.countRegionserver에서 외부로부터 오는 요청을 처리하기 위해서 사용할 Thread의 개수를 정의하기 위한 설정입니다. 기본값은 10인데 보통 너무 작은 값입니다. HBase 설정 사이트에서는 너무 큰 값이면 좋지 않다고 얘기하고 있지만, 테스트 결과 m2.4xlarge (26ECU) 에서 200개 Thread까지는 성능 하락이 없는 것으로 나타났습니다. (더 큰 값에 관해서 확인해 보지는 않았습니다.)저희는 이 값을 10에서 100으로 올린 후에 약 2배의 Throughput 향상을 얻을 수 있었습니다.hfile.block.cache.sizeHBase 의 block 들을 cache 하는데 전체 Heap 영역의 얼마를 할당한 것인지를 나타냅니다. 저희 서비스는 Read가 Write보다 훨씬 많아서 (Write가 전체의 약 3%) Cache hit ratio가 전체 성능에 큰 영향을 미칩니다.HBase 에서는 5분에 한 번 log 파일에 LruBlockCache (HBase 의 Read Cache) 가 얼마 만큼의 메모리를 사용하고 있고, Cache hit ratio가 얼마인지 표시를 해줍니다. 이 값을 참조하셔서 최적화에 사용하실 수 있습니다.저희는 이 값을 0.5로 설정해 놓고 사용하고 있습니다. (50%)hbase.regionserver.global.memstore.lowerLimit / hbase.regionserver.global.memstore.upperLimit이 두 개의 설정은 HBase에서 Write 한 값들을 메모리에 캐쉬하고 있는 memstore가 Heap 영역의 얼마만큼을 할당받을지를 나타냅니다. 이 값이 너무 작으면 메모리에 들고 있을 수 있는 Write의 양이 한정되기 때문에 디스크로 잦은 flush가 일어나게 됩니다. 반대로 너무 크면 GC에 문제가 있을 수 있으며 Read Cache로 할당할 수 있는 메모리를 낭비하는 것이기 때문에 좋지 않습니다.lowerLimit와 upperLimit의 두 가지 설정이 있는데, 두 개의 설정이 약간 다른 뜻입니다.만약 memstore 크기의 합이 lowerLimit에 도달하게 되면, Regionserver에서는 memstore들에 대해서 'soft'하게 flush 명령을 내리게 됩니다. 크기가 큰 memstore 부터 디스크에 쓰이게 되며, 이 작업이 일어나는 동안 새로운 Write가 memstore에 쓰일 수 있습니다.하지만 memstore 크기의 합이 upperLimit에 도달하게 되면, Regionserver는 memstore들에 대한 추가적인 Write를 막는 'hard'한 flush 명령을 내리게 됩니다. 즉, 해당 Regionserver이 잠시 동안 Write 요청을 거부하게 되는 것입니다. 보통 lowerLimit에 도달하면 memstore의 크기가 줄어들기 때문에 upperLimit까지 도달하는 경우는 잘 없지만, write-heavy 환경에서 Regionserver가 OOM으로 죽는 경우를 방지하기 위해서 hard limit가 존재하는 것으로 보입니다.hfile.block.cache.size와 hbase.regionserver.global.memstore.upperLimit의 합이 0.8 (80%)를 넘을 수 없게 되어 있습니다. 이는 아마 read cache 와 memstore의 크기의 합이 전체 Heap 영역 중 대부분을 차지해 버리면 HBase의 다른 구성 요소들이 충분한 메모리를 할당받을 수 없기 때문인 듯합니다.저희는 이 두 개의 설정 값을 각각 0.2, 0.3으로 해 놓았습니다. (20%, 30%)ipc.client.tcpnodelay / ipc.server.tcpnodelay / hbase.ipc.client.tcpnodelayHDFS의 tcpnodelay 와 비슷한 설정입니다. 기본값은 전부 false입니다.이 설정을 true로 하기 전에는 Get/Put 99%, 99.9% Latency가 40ms 와 80ms 근처에 모이는 현상을 발견할 수 있었습니다. 전체 요청의 매우 작은 부분이었지만, 평균 Get Latency가 1~2ms 내외이기 때문에 99%, 99.9% tail이 평균 Latency에 큰 영향을 미쳤습니다.이 설정을 전부 true로 바꾼 후에 평균 Latency가 절반으로 하락했습니다.Heap memory / GC 설정저희는 m2.4xlarge가 제공하는 메모리 (68.4GB)의 상당 부분을 HBase의 Read/Write cache에 할당하였습니다. 이는 보통 사용하는 Java Heap 공간보다 훨씬 큰 크기이며 심각한 Stop-the-world GC 문제를 일으킬 수 있기 때문에, 저희는 이 문제를 피하고자 여러 가지 설정을 실험하였습니다.STW GC time을 줄이기 위해서 Concurrent-Mark-and-sweep GC를 사용했습니다.HBase 0.92에서부터 기본값으로 설정된 Memstore-Local Allocation Buffer (MSLAB) 을 사용했습니다. hbase.hregion.memstore.mslab.enabled = true #(default)hbase-env.sh 파일을 다음과 같이 설정했습니다. HBASE_HEAPSIZE = 61440 #(60GB) HBASE_OPTS = "-XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=70 -verbose:gc -XX:+PrintGCDetails -XX:+PrintGCDateStamps"GC log를 Python script로 Parsing해서 STW GC 시간을 관찰하고 있습니다. 지금까지 0.2초 이상의 STW GC는 한 번도 발생하지 않았습니다.그 밖에 도움이 될 만한 설정들hbase.hregion.majorcompactionHBase는 하나의 Region에 대해서 여러 개의 StoreFile을 가질 수 있습니다. 그리고 주기적으로 성능 향상을 위해서 이 파일들을 모아서 하나의 더 큰 파일로 합치는 과정을 진행하게 됩니다. 그리고 이 과정은 많은 CPU usage와 Disk IO를 동반합니다. 그리고 이때 반응 속도가 다소 떨어지게 됩니다. 따라서 반응 속도가 중요한 경우에는, 이 Major compaction을 off-peak 시간대를 정해서 manual 하게 진행하시는 것이 좋습니다.저희는 사용자의 수가 상대적으로 적은 새벽 시간대에 crontab 이 실행시키는 script가 돌면서 전체 Region에 대해서 하나하나 Major Compaction이 진행되도록 하였습니다.기본값은 86,400,000 (ms)로 되어 있는데, 이 값을 0으로 바꾸시면 주기적인 Major Compaction이 돌지 않게 할 수 있습니다.hbase.hregion.max.filesizeHBase는 하나의 Region이 크기가 특정 값 이상이 되면 자동으로 2개의 Region으로 split을 시킵니다. Region의 개수가 많지 않을 때는 큰 문제가 없지만, 계속해서 데이터가 쌓이게 되면 필요 이상으로 Region 수가 많아지는 문제를 나을 수 있습니다. Region 수가 너무 많아지면 지나친 Disk IO가 생기는 문제를 비롯한 여러 가지 안 좋은 점이 있을 수 있기 때문에, split 역시 manual 하게 하는 것이 좋습니다. 그렇다고 Table의 Region 수가 너무 적으면 Write 속도가 떨어지거나 Hot Region 문제가 생길 수 있기 때문에 좋지 않습니다.HBase 0.92.1 에서는 기본값이 1073741824(1GB)로 되어 있는데, 저희는 이 값을 10737418240(10GB)로 늘인 후에 manual 하게 split을 하여 Region의 개수를 조정하고 있습니다.hbase.hregion.memstore.block.multipliermemstore의 전체 크기가 multiplier * flush size보다 크면 추가적인 Write를 막고 flush가 끝날때까지 해당 memstore는 block 됩니다.기본값은 2인데, 저희는 8로 늘려놓고 사용하고 있습니다.dfs.datanode.balance.bandwidthPerSec부수적인 설정이지만, HDFS의 Datanode간의 load balancing이 일어나는 속도를 제한하는 설정입니다. 기본값은 1MB/sec로 되어 있지만, 계속해서 Datanode를 추가하거나 제거하는 경우에는 기본값으로는 너무 느릴 때가 있습니다. 저희는 10MB/sec 정도로 늘려서 사용하고 있습니다.dfs.namenode.heartbeat.recheck-intervalHDFS namenode에만 해당되는 설정입니다.Datanode가 응답이 없는 경우에 얼마 후에 Hadoop cluster로부터 제거할 것인지를 나타내는 값입니다.실제로 응답이 없는 Datanode가 떨어져 나가기까지는 10번의 heartbeat가 연속해서 실패하고 2번의 recheck역시 실패해야 합니다. Heartbeat interval이 기본값인 3초라고 하면, 30초 + 2 * recheck-interval 후에 문제가 있는 Datanode가 제거되는 것입니다.기본값이 5분으로 되어 있는데, fail-over가 늦어지기 때문에 사용하기에는 너무 큰 값입니다. 저희는 문제가 있는 Datanode가 1분 후에 떨어져 나갈 수 있도록 이 값을 15,000 (ms) 으로 잡았습니다.Read short-circuitRegionServer가 로컬 Datanode로부터 block을 읽어올 때 Datanode를 통하지 않고 Disk로부터 바로 읽어올 수 있게 하는 설정입니다.데이터의 양이 많아서 Cache hit이 낮아 데이터 대부분을 디스크에서 읽어와야 할 때 효율적입니다. Cache hit에 실패하는 Read의 Throughput이 대략 2배로 좋아지는 것을 확인할 수 있습니다. OLAP용 HBase에는 매우 중요한 설정이 될 수 있습니다.하지만 HBase 0.92.1-cdh4.0.1까지는 일부 Region이 checksum에 실패하면서 Major compaction이 되지 않는 버그가 있었습니다. 현재 이 문제가 해결되었는지 확실하지 않기 때문에 확인되기 전에는 쓰는 것을 추천하지는 않습니다.설정하는 방법은 다음과 같습니다. dfs.client.read.shortcircuit = true #(hdfs-site.xml) dfs.block.local-path-access.user = hbase #(hdfs-site.xml) dfs.datanode.data.dir.perm = 775 #(hdfs-site.xml) dfs.client.read.shortcircuit = true #(hbase-site.xml)Bloom filterBloom filter의 작동방식에 대해 시각적으로 잘 표현된 데모 페이지HBase는 Log-structured-merge tree를 사용하는데, 하나의 Region에 대해서 여러 개의 파일에 서로 다른 version의 값들이 저장되어 있을 수 있습니다. Bloom filter는 이때 모든 파일을 디스크에서 읽어들이지 않고 원하는 값이 저장된 파일만 읽어들일 수 있게 함으로써 Read 속도를 빠르게 만들 수 있습니다.Table 단위로 Bloom filter를 설정해줄 수 있습니다.ROW와 ROWCOL의 두 가지 옵션이 있는데, 전자는 Row key로만 filter를 만드는 것이고, 후자는 Row+Column key로 filter를 만드는 것입니다. Table Schema에 따라 더 적합한 설정이 다를 수 있습니다.저희는 데이터 대부분이 메모리에 Cache 되고 하나의 Region에 대해서 여러 개의 StoreFile이 생기기 전에 compaction을 통해서 하나의 큰 파일로 합치는 작업을 진행하기 때문에, 해당 설정을 사용하지 않고 있습니다.결론지금까지 저희가 비트윈을 운영하면서 얻은 경험을 토대로 HBase 최적화 설정법을 정리하였습니다. 하지만 위의 구성은 어디까지나 비트윈 서비스에 최적화되어 있는 설정이며, HBase의 사용 목적에 따라서 달라질 수 있음을 말씀드리고 싶습니다. 그래서 단순히 설정값을 나열하기보다는 해당 설정이 어떤 기능을 하는 것인지 저희가 아는 한도 내에서 설명드리려고 하였습니다. 위의 글에서 궁금한 점이나 잘못된 부분이 있으면 언제든지 답글로 달아주시길 바랍니다. 감사합니다.
조회수 2232

시간을 줄여주는 CodeStar 사용 팁

편집자 주: 함께 보면 좋아요!애플리케이션 개발부터 배포까지, AWS CodeStarOverview: 작성 환경AWS CodeStar를 사용하면 애플리케이션의 서버, 언어 , 형상관리, 배포, 빌드까지 한꺼번에 관리할 수 있습니다. AWS를 사용하는 개발자라면 꼭 필요한 도구이기도 합니다. 이번 글에서는 CodeStar를 초기 설정할 때의 도움이 될 내용들을 소개하겠습니다.-서비스: AWS CodeStar-템플릿: Python Webservice, AWS Lambda목차파라미터 바인딩람다 환경변수 설정람다 레이어 설정xray 모니터링 설정람다 함수명 설정Global 섹션로컬 개발환경에서의 SAM 실행CodeStar 프로젝트 생성 후CodeStar로 프로젝트를 생성하면 소스코드와 배포를 위한 Code 시리즈 리소스들이 함께 만들어집니다. CodeCommit, CodeBuild, CodePipeline 등이 있습니다. 우선 기본으로 구축된 파이프라인부터 살펴보겠습니다.CodeCommit 리포지토리의 마스터 브랜치 코드를 변경하면 CodeBuild와 CloudFormaton 서비스를 통해 빌드, 테스트, 배포를 진행할 수 있게 설정되어 있습니다. 생성된 리포지토리의 template.yml 파일을 이용하면 프로젝트 리소스도 관리할 수 있는데, 특히 template.yml을 통해 CloudFormation으로 관리하는 리소스까지도 관리가 가능합니다.기본으로 생성된 template.yml 파일을 자세히 살펴보겠습니다.AWSTemplateFormatVersion: 2010-09-09 Transform: - AWS::Serverless-2016-10-31 - AWS::CodeStar Parameters: ProjectId: Type: String Description: CodeStar projectId used to associate new resources to team members CodeDeployRole: Type: String Description: IAM role to allow AWS CodeDeploy to manage deployment of AWS Lambda functions Stage: Type: String Description: The name for a project pipeline stage, such as Staging or Prod, for which resources are provisioned and deployed. Default: '' Globals: Function: AutoPublishAlias: live DeploymentPreference: Enabled: true Type: Canary10Percent5Minutes Role: !Ref CodeDeployRole Resources: HelloWorld: Type: AWS::Serverless::Function Properties: Handler: index.handler Runtime: python3.7 Role: Fn::GetAtt: - LambdaExecutionRole - Arn Events: GetEvent: Type: Api Properties: Path: / Method: get PostEvent: Type: Api Properties: Path: / Method: post LambdaExecutionRole: Description: Creating service role in IAM for AWS Lambda Type: AWS::IAM::Role Properties: RoleName: !Sub 'CodeStar-${ProjectId}-Execution${Stage}' AssumeRolePolicyDocument: Statement: - Effect: Allow Principal: Service: [lambda.amazonaws.com] Action: sts:AssumeRole Path: / ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole PermissionsBoundary: !Sub 'arn:${AWS::Partition}:iam::${AWS::AccountId}:policy/CodeStar_${ProjectId}_PermissionsBoundary' 파라미터 바인딩Parameters 섹션에서는 ProjectId, CodeDeployRole, Stage 등 템플릿에서 사용할 파라미터를 지정할 수 있습니다. yml 파일 안에서는 ${ProjectId} 와 같이 사용할 수 있고, CodePipeline 환경에서 파라미터를 전달할 수 있습니다.CodePipeline → Deploy → GenerateChangeSet → Advanced → Parameter overrides람다 환경변수 설정람다 함수에서 사용할 환경변수를 설정할 수 있습니다. 아래와 같이 람다 환경변수 TZ(timezone)를 지정하면 실행 환경의 표준 시간대 설정이 가능합니다.Resources: HelloWorld: Type: AWS::Serverless::Function Properties: Environment: Variables: TZ: 'Asia/Seoul' 람다 레이어 설정람다 레이어를 적용하면 패키지 관리가 훨씬 편리해집니다. 함수의 패키지 크기가 3MB를 넘지 않으면 콘솔에서 코드를 직접 확인 및 수정할 수 있습니다. 람다 레이어는 zip 파일로 관리되고, /opt 폴더에 압축 해제되며 생성됩니다.람다는 250MB의 제한이 있습니다. 만약 레이어를 사용해 분리하더라도 람다함수패키지와 람다 레이어의 합으로 걸려있으므로 크기 제약에서 벗어날 수는 없습니다.Resources: HelloWorld: Type: AWS::Serverless::Function Properties: Layers: - arn:aws:lambda:{region}:{id}:layer:{layer-name}:{version} xray 모니터링 설정Tracing Property를 이용하면 람다 함수의 Enable active tracing 설정을 할 수 있습니다. CloudFormation 템플릿 메뉴얼엔 TracingConfig로 안내하고 있어도 빌드에 실패하여 확인해보니 SAM 템플릿의 AWS::Serverless::Function 의 스펙에선 Tracing으로 안내되고 있는 걸 볼 수 있었습니다.Resources: HelloWorld: Type: AWS::Serverless::Function Properties: Tracing: Active 람다 함수명 설정람다 함수는 기본적으로 아래와 같은 이름을 부여합니다.awscodestar-{brandi-test(프로젝트명)}-lambda-{HelloWorld(template함수ID)}-{NZ6YXLZ8XD0O(RANDOM_ID)}만약 함수 간의 호출이 필요할 때는 아래와 같이 함수 이름의 지정도 가능합니다.Resources: HelloWorld: Type: AWS::Serverless::Function Properties: FunctionName: !Sub '${ProjectId}-HelloWorld-${Stage}' Global 섹션Global 섹션을 이용하면 리소스마다 동일하게 적용할 항목들을 관리할 수 있습니다.Globals: Function: Runtime: python3.6 Environment: Variables: TZ: 'Asia/Seoul' VpcConfig: SubnetIds: - subnet-a1111111 - subnet-b2222222 SecurityGroupIds: - sg-c2222222 로컬 개발환경에서의 SAM 실행API Gateway 환경 실행sam local start-api 람다 함수 직접 실행echo ‘{}’ | sam local invoke —parameter-values=‘ParameterKey=ProjectId,ParameterValue=brandi-test’ HelloWorld Conclusion지금까지 CodeStar 초기 설정에 도움이 될 내용들을 살펴봤습니다. 강력한 기능들과 함께 업무를 진행한다면 조금이라도 더 나은 개발 환경을 구축할 수 있을 거라 생각합니다.글이상근 실장 | R&D DO실[email protected]브랜디, 오직 예쁜 옷만
조회수 2305

(개발자)가 !(개발자)와 일하는 방법

 이 포스트는 제가 개발팀에게 했던 세미나를 정리한 것입니다. 개발자와 기획자, 개발자와 디자이너 사이에 의사소통에 대해서 얘기하는 글이 너무나 많습니다. 디자이너(기획자)가 개발자와 일하기 위해 알아야하는 최소한의 개발 용어, 기획자와 개발자가 절대 하지 말아야 할 말들 등등 재밌는 포스트들이 인터넷에 떠돌고 여러 담당자들의 공감과 비판을 사고 있지요. 언제 이야기해도 농담을 주고 받으며 할 수 있는 좋은 주제인 것 같습니다. 그러나 그런 글들은 해당 개발자 또는 기획자가 쓴 글이기 때문에 바이어스가 걸리기 마련이지요. 우스갯소리로 넘기기에는 껄끄럽고 진지하게 받아들이기에도 껄끄럽죠. 왜 이런 말들이 이렇게 많이 나올까요? 왜냐하면 실제로 그들이 대화하는 방식이 너무나 다르고 서로가 하는 일을 이해하기 힘들기 때문입니다. 서로간에 말이 정말 잘 통했다면 그럴 일이 없겠지요. 심지어 화성에서 온 개발자 금성에서 온 기획자라는 말이 한 때 많이 나돌아 다녔지요.UI/UX도 모르면서...결국 게시판 만들라는 거잖아요이런걸 기획서라고 써오다니...아니 그걸 다 된다고 하면 어떡해요이거 하나 바꾸는게 그렇게 어려운가요?언제까지 가능한지만 얘기해주세요여기서는 되는데 우리는 왜 안되나요?개발 공부 할거에요! 공감 하시나요? 저는 개발자이지만 한번 기획자의 입장에서 왜 그렇게 할 수 밖에 없었는지 핑계를 대보겠습니다. 도대체 기획자는 저딴 방구인지 말인지 모를 말들을 할까요? 와이컴비네이터의 폴 그래햄의 유명한 에세에인 Do things that don’t scale의 한국어 요약본입니다. 영어가 싫고 1분1초가 아까운 여러분을 위해서 준비했습니다 :) 읽어보시면 스타트업에서 처음부터 규모가 큰 작업을 하거나 그것을 자동화하는 일이 얼마나 위험한 일인지 간접적으로 느끼실 수 있을것 같아요. 그 중에 일부만 발췌하여 말씀드리면1. 모집 : 사람들은 많은 선택권을 가지고 있기 때문에 우리 제품을 써야할 필요가 없음그들을 선택하려면 빠른 프로토타입이 필요하고 요구사항에 맞춰 변화할 필요가 있음2. 황홀감 : 모든 유저들에게 황홀한 수준의 경험을 제공해야하는데 엔지니어 교육과정중에 유저 만족에 기울어야한다는 내용이 없어서 생각하기 힘듬3. Meraki : 하드웨어 벤처의 경우 수동으로 기계를 생산/조립하면서 기존에는 알지못했던 핵심 요인들을 발견할 수 있음4. 수동 : 초기에는 소프트웨어가 할일을 사람이 직접하는게 좋을 수도 있음.수동으로 해결하다가 해결책을 자동화하는 것은 확실한 고객을 확보할 수 있지만, 처음부터 자동화된 해결책으로 아무런 문제도 해결하지 못한다면 확실한 실패로 이어짐5. 대형 : 처음부터 큰 스케일로 일을 벌인다고해서 성공으로 이어지는 건 아님. 수동을 싫어하기 때문에 크게 일을 벌리는 것은 큰 실패로 이어짐.큰 버그가 아니고 시장 진입 타이밍이 중요하다면 바로 출시할 수도 있다 이 중에서도 저는 4번의 수동이라는 덕목을 가장 중요하게 생각합니다. 개발자라는 족속들이 수동을 굉장히 싫어하는 경우가 많습니다. 수동은 쿨하지 않거든요. 그래서 모든 것을 자동화시키려고 하죠. 자동은 쿨하니까요. 어떤 포털사이트의 랜딩 페이지를 개발해야하는 프로젝트가 생겼다고 예를 들어봅시다. 개발자는 생각합니다.매일매일 갱신되는 랜딩페이지를 만들자. 좋아요와 댓글이 많은 글들을 최신순으로 정렬하여 보여주는데 매일 자정에 랜딩 페이지가 새로운 내용으로 갱신되는게 좋겠다. 이미 한번 게시되었던 글은 다시는 게시되지 않도록 구성해야겠군. 좋아요와 댓글의 가중치는 1:2 정도가 좋겠지? 이렇게 랜딩 페이지를 하나 구성하는데 엄청난 노력과 시간을 투자합니다. 기획자 또는 마케터는 왜 이렇게 일이 오래걸리는지 답답해하죠. 빨리 출시해서 고객들의 반응을 보고 싶은데 개발이 늦어지니까요. 사실 고객들은 포털 사이트의 메인 컨텐츠가 자동으로 구성되던 수동으로 구성되던 관심이 없어요. 그건 기획자 또한 마찬가지지요. 그들에게 어떤 컨텐츠를 보여줘야 좋아할까 고민하지요. 심지어 그전에 랜딩 페이지라는 기능이 유효한지 증명되지도 않았지요. 실제로 이전에 제가 만들었던 시크릿차트라는 서비스에서 병원의 랭킹을 계산하여 유저들에게 보여주는 기능을 만들 때도 비슷한 일이 있었습니다. 병원 랭킹 기능이란 각 병원이 언급된 블로그와 카페 글을 스크레이핑하여 몇 개인지 세고 데이터베이스를 쌓고 블로그와 카페 글이 많은 순서대로 정렬하여 보여주는 기능입니다. 처음에 저도 욕심이 생기는 겁니다. 검색 포털의 API를 이용하여 스크레이핑 봇을 만들고 데이터베이스를 구축해주는 프로그램을 만들고 싶었습니다. 그 프로그램을 만드는데는 테스팅까지 약 1주일이라는 시간이 꼬박 들겠지요. 그래도 굉장히 쿨하고 재밌어 보였습니다. 그러나 그 욕망을 꾹 참고 수동으로 세서 데이터베이스를 구축하기로 결심합니다. 검색 포털에서 검색하여 나온 숫자를 눈으로 직접 보고 데이터베이스에 직접 접근하여 수동으로 입력하는 방식입니다. 저는 기획자와 다른 개발자에게도 입력하는 것을 도와달라고 협조를 요청했습니다. 그렇게 2일만에 우리는 데이터베이스를 구축했고 빠르게 배포하여 고객의 반응을 살폈습니다. 고객의 반응을 살펴보던 기획자들은 그 기능이 정말 잘 작동하고 고객들이 좋아한다는 것을 증명해냈고 저는 그제서야 API를 이용하여 모든 것을 자동화했지요. 우리는 자동화의 욕심을 버려야합니다. 물론 시간과 비용, 효율을 따져서 해야겠지요. 효율을 따지는 것은 여러분이 더욱 능숙하실거라고 생각합니다. 우선은 간단한 예로 비개발자들이 왜 요상한 말과 행동을 하는지 알아보았습니다. 그러면 개발자인 우리는 그들에게 어떻게 이야기해야할까요? 어떻게 해야 싸우지 않고 일할 수 있을까요? 애자일 개발방법론 중에 하나인 익스트림 프로그래밍에서도 이야기하듯이 지식 섬 현상(Islands of Knowledge)은 굉장히 위험한 요소입니다. 서로가 이해하는 것이 다르기때문에 계속적인 커뮤니케이션을 통해 지식 섬을 없애야합니다. 저는 그 지식섬을 없애기 위한 실질적인 방법을 소개하려고 해요.조카에게 설명하듯이1. 훈민정음 아시겠지만 개발 용어는 절대 금지입니다. 정말로 필요한 경우가 아니면 절대 개발 용어를 쓰지마세요.2. ABC 제목만 보면 훈민정음 룰과 반대되는 내용인 것 같죠? 예를 들어서 설명할게요. 태그 기능을 만든다고 합시다. 그런데 거기서 기획서에 나오지 않은 허점을 우리는 발견했습니다. 손가락을 이리저리써가며 태그가 여러개가 되었을 때 꼬이는 현상을 설명하려 하지마세요. 태그A, 태그B, 태그C 이렇게 설명하세요, 또는 "가나다"도 좋겠군요.3. 연필 & 종이 미팅을 할때 무조건 연필과 종이를 챙겨가세요. 그리고 말보다는 그림을 그려가며 설명하세요. 종이를 아끼지 말고 최대한 자세하게요. 또는 미리 정리한 문서를 준비해가세요. 문서를 보면서 설명하면 빼먹지않고 더 잘 설명할 수 있지요.4. 메타포를 사용하라 익스트림 프로그래밍에도 나오듯이 시스템 전체 또는 기능 전체를 하나의 메타포로 정의하여 설명하는 방법입니다. 현재 제가 만들고있는 IoT 관제 솔루션의 뒷면에는 기획자 또는 디자이너가 절대 이해하지 못할 프로토콜이라고 불리는 부분이 있습니다. 우리는 프로토콜을 어떻게 개발자가 아닌 사람에게 설명해야 할까요? 저는 커피머신을 메타포로 사용하여 설명하겠습니다. 우리는 제품으로부터 raw data라는 가공되지 않은 커피빈을 받습니다. 그냥 겉으로만 보면 어떤 유용한 데이터를 가지고 있는지 전혀 모르죠. 커피빈을 볶고 갈아서 사람이 마실만한 에스프레소를 만듭니다. 거기에 우유, 크림, 초콜릿 등을 더해서 다른 사용자가 좋아할 만한 또다른 커피도 만들 수 있겠죠. 데이터베이스를 모르는 사람들이 보는 깔끔한 그래프가 나오는 화면은 아메리카노, 라떼 등으로 비유할 수 있겠군요. 정말 조카에게 설명하듯이 쉽게 친절하게 설명하시면 됩니다. 그럼 다음으로 여기서 한발짝 더 나아가서 심화학습을 해보죠. 우리는 개발자로서 비개발자인 그들에게 어떻게 해주면 더 좋을까요?1. 기획의도를 이해하기 왜 이렇게 기획했는지 이해하면 좋습니다. 유저의 요구사항이 무엇이고 왜 그런 요구를 했는지 Back-log를 알면 개발이 더 쉬울 뿐만 아니라 빠르게 배포할 수 있을지도 모릅니다. 예를 들어 배포 30분전에 버그가 발견되었습니다. 개발자는 "헉, 버그다."이러면서 열심히 고치겠지요. 그러면서 기획자에게 배포를 내일해도 되냐고 물어봅니다. 기획자는 안된다고 하고 또 싸우겠죠. 만약 기획의도를 이해한다면 이 싸움이 필요하지 않을지도 모릅니다. 해당 기능을 작동시키는데 있어서 크리티컬한 것이 아니면 서비스를 우선 배포하고 이 후에 고쳐도 되겠지요. 또는, 마케팅이나 시장은 타이밍이 중요하기 때문에 기능 구현의 우선순위를 기획자가 잡아줄 수도 있습니다.2. 프로토타입을 빠르게 개발자는 코드로 이야기합니다. 그러나 비개발자는 이해 못합니다. 움직이는 프로토타입은 고객뿐만 아니라 동료의 이해도를 드라마틱하게 높일 수 있지요.3. 계속해서 점검받기 점검받는다고 그들의 아래에 있는 것이 아닙니다. 우리는 프로젝트를 완수하기 위해 각자 다른 역할을 수행하고 있는 동등한 존재임을 잊지맙시다. 개발자는 비개발자에게 계속해서 움직이는 프로토타입을 보여주고 피드백 받으면서 지식의 섬을 없애나가야 합니다. 고객들이 원하는대로, 기획자들이 기획한대로, 디자이너 디자인한대로 구현하는 것이 프로젝트에서는 무엇보다도 중요하니까요.4. 데드라인은 꼭 지키기 데드라인을 지키는 것은 개발자와 비개발자간에 신뢰관계를 높이는 방법 중에 개발자가 할 수 있는 가장 효과적인 방법입니다. 또한 고객과도 마찬가지죠. 약속을 지키지 못하는 회사의 제품을 사가는 사람은 없습니다.  우리는 서로에 대해 너무 조금만을 알고 있습니다. 그래서 서로의 입장을 모르고 문제가 생기기 마련이지요. 당연히 서로에 대해 자세히 알 필요는 없지요. 우리팀에서 프로젝트를 망치고 싶어하는 사람은 없습니다. 그러나 상황이, 그리고 오해가 프로젝트를 망치게 하지요. 그리고 누구나 똥을 쌉니다. 서로 부족한 점이 있으니 부족한 점을 욕하기보다는 부족한 부분을 채우기위해 영역을 넓혀가는 건 어떨까요? 저건 내 일이 아니니 알아서 되겠지라는 태도보다는 다 같이 고민하며 빈 공간을 채우는 편이 좋다고 생각합니다. 서로를 비난하면서 프로젝트를 할 것인가, 서로를 이해하는 마음가짐으로 즐겁게 프로젝트를 할 것인가... 선택은 당신의 손에 달렸지요.#비주얼캠프 #인사이트 #경험공유 #조언 #개발자 #개발팀 #협업 #팀워크
조회수 1159

테이블이냐, 컬렉션이냐, 그것이 문제로다!(KOR)

편집자 주 외래어 표기법에 따르면 ‘원어에서 띄어 쓴 말은 띄어 쓴 대로 한글 표기를 하되, 붙여 쓸 수도 있다.’고 규정하고 있다.(제3장 제1절 영어의 표기, 제10항과, 컴퓨터 전문어, 전기 전문어 등) 즉 ‘원칙’과 ‘허용’이 모두 가능하다는 의미다. 이를 바탕으로 여러 표기 용례를 참고한 결과, TableView는 ‘테이블뷰(원칙)’로 표기해야 하나, 본문에서는 독자의 가독성을 높이기 위해 ‘테이블 뷰(허용)’로 표기한다. 응용하여, CollectionView는 ‘컬렉션 뷰’로, TableViewCell은 ‘테이블 뷰 셀’ 등으로 띄어 쓴다. Overview앱에서 데이터를 사용자에게 보여줄 땐 여러 가지의 모습으로 나타납니다. 설정 앱처럼 목록으로 보여줄 때도 있고, 사진 앱처럼 그리드(grid) 형식으로 보여줄 때도 있습니다. 이처럼 데이터를 보여줄 때 많이 사용되는 뷰는 테이블 뷰(UITableView) 또는 컬렉션 뷰(UICollectionView)입니다. 각자 특징이 있기 때문에 앱의 성격에 따라 적절한 뷰를 사용해야 합니다. 왜냐하면 목록을 보여주는 디자인을 바꿀 때, 다시 개발해야 하는 수고를 덜 수 있기 때문입니다. 이번 글에선 각각의 뷰를 간략하게 알아보겠습니다. 목록 형식의 설정 앱과 그리드 형식의 사진 앱 스크린샷테이블 뷰(UITableView)단일 열에 배열된 행을 사용해 데이터를 표시하는 뷰입니다. 수직 스크롤만 가능하며, 테이블의 개별 항목을 구성하는 셀은 테이블 뷰 셀(UITableViewCell) 객체입니다. 테이블 뷰는 이 객체들을 이용해 테이블에 표시되는 행을 그립니다. 여러 행은 하나의 섹션 안에 구성될 수 있으며, 각 섹션은 헤더(header)와 푸터(footer)를 가질 수 있습니다. 섹션과 행은 인덱스 번호로 구별하는데, 번호는 0부터 시작합니다. 테이블 뷰는 plain과 grouped 스타일 중 한 가지의 스타일을 가질 수 있습니다. Plain 스타일은 보통 목록 스타일입니다. 섹션의 헤더와 푸터는 섹션 분리기(inline separators)로 표시되고 스크롤을 할 때 해당 섹션 안에 있는 콘텐츠 위에 나타납니다. Grouped 스타일은 시각적으로 뚜렷한 행 그룹을 표시하는 섹션이 있습니다. 섹션의 헤더와 푸터는 콘텐츠 위에 나타나지 않습니다. 아래와 같은 사진을 보시면 확연히 차이를 볼 수 있습니다. plain 스타일의 연락처 앱과 grouped 스타일의 설정 앱테이블 뷰의 많은 메소드들은 인덱스패스(NSIndexPath) 객체를 매개변수 또는 리턴 값으로 사용합니다. 테이블 뷰는 해당하는 행의 색인 인덱스와 섹션 인덱스 값을 가져올 수 있게 인덱스패스의 범주를 선언합니다. 또한 색인 인덱스와 섹션 인덱스 값을 가지고 인덱스패스를 만들 수 있습니다. 특히 여러 섹션이 있는 테이블 뷰는 섹션 인덱스 값이 반드시 있어야 행의 인덱스 번호로 구별할 수 있습니다.override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> AttractionTableViewCell {         // Table view cells are reused and should be dequeued using a cell identifier.         let cellIdentifier = "AttractionTableViewCell"              guard let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as? AttractionTableViewCell else {             fatalError("The dequeued cell is not an instance of AttractionTableViewCell.")         }                 let attraction = attractions[indexPath.row]                 cell.attractionLabel.text = "\(indexPath.row). \(attraction.nameWithDescription)"         cell.attractionImage.image = attraction.photo                 cell.attractionImage.tag = indexPath.row                 attraction.indexPath = indexPath                 ...                 return cell     } 위의 코드는 데이터 소스(data source) 메소드로, 테이블 뷰의 특정한 위치에 셀을 추가합니다. 다시 말해, 이 메소드는 테이블 뷰가 ‘표시할 새로운 셀이 필요할 때마다’ 특정 행에 노출할 정보가 있는 셀을 만들고 리턴하는 걸 말합니다. 매개변수로 필요한 셀 객체의 행을 가리키는 indexPath 값을 전달합니다. 그리고 indexPath의 row 값을 이용해서 attraction이라는 배열 인덱스로 활용하고, 셀에 표시할 정보들을 설정합니다. 여기서 attraction 배열은 관광 명소들의 정보들이 담고 있는 배열인데, 1행은 첫 번째로 저장한 관광 명소, 2행은 두 번째로 저장한 관광 명소 등 순서대로 설정하도록 indexPath.row 값을 이용하는 것입니다. indexPath의 row 값과 배열의 인덱스 값은 0부터 시작하기 때문입니다. 해당 예제는 섹션이 1인 경우이기 때문에 섹션 인덱스 값이 없지만, 섹션이 여러 개 있다면 반드시 섹션 인덱스 값을 이용해서 설정해야 합니다.테이블 뷰 객체는 데이터 소스(data source)와 델리게이트(delegate)가 필요합니다. 데이터 소스는 UITableViewDataSource 프로토콜을 구현해야 하고, 델리게이트는 UITableViewDelegate 프로토콜을 구현해야합니다. 데이터 소스는 테이블 뷰가 테이블을 만들 때 필요한 정보를 제공하고 테이블의 행이 추가, 삭제 또는 재정렬할 때 데이터 모델을 관리합니다. 델리게이트는 화면에 보이는 모습과 행동을 담당합니다. 예를 들어 표시할 행의 수, 사용자가 특정 행을 터치했을 때, 행의 재정렬 등과 같은 것입니다.override func numberOfSections(in tableView: UITableView) -> Int {         // #warning Incomplete implementation, return the number of sections         return 1     }      override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {         // #warning Incomplete implementation, return the number of rows         return attractions.count     } 위의 두 소스는 데이터 소스가 필수적으로 구현해야 하는 메소드입니다. 하나는 섹션의 개수를 리턴하고, 또 하나는 한 섹션 안에 있는 행의 개수를 리턴합니다.테이블 뷰는 수정 모드에서 행을 추가, 삭제, 재정렬할 수 있습니다. 각 행은 테이블 뷰 셀에 연관된 editingStyle에 따라서 추가, 삭제, 재정렬을 할 수 있는데, 예를 들어 editingStyle이 insert라면 추가하는 메소드를 실행하고, delete면 삭제하는 메소드를 실행합니다. 행의 showsReorderControl 속성이 true라면, 재정렬하는 메소드를 실행할 수 있습니다.// Override to support editing the table view.     override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {         if editingStyle == .delete {             // Delete the row from the data source             ...                 // delete rows and attractions and reload datas             attractions.remove(at: indexPath.row)             tableView.deleteRows(at: [indexPath], with: .middle)             tableView.reloadData()         } else if editingStyle == .insert {             // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view         }     } 위 소스는 editingStyle이 delete일 때 셀을 삭제하고 테이블 뷰를 다시 로드하는 기능을 구현한 것입니다.테이블 뷰를 만드는 가장 쉽고 권장하는 방법은 바로 스토리보드에서 테이블뷰컨트롤러(UITableViewController)를 이용해서 만드는 겁니다. 런타임에 테이블뷰컨트롤러는 테이블 뷰를 만들고 델리게이트와 데이터 소스를 자기 자신으로 할당합니다.컬렉션 뷰(UICollectionView)컬렉션 뷰는 테이블 뷰에서 할 수 있는 모든 것을 할 수 있습니다. 섹션을 가질 수 있고, 인덱스패스 값을 이용해서 셀을 구별합니다. 이 셀들은 컬렉션 뷰 셀(UICollectionViewCell)의 서브 클래스이며 데이터 소스(UICollectionViewDataSource)와 델리게이트(UICollectionViewDelegate)가 필요합니다. 셀을 추가, 삭제, 재정렬하는 기능도 구현할 수 있습니다. 그렇다면 컬렉션 뷰와 테이블 뷰를 구분하는 특징은 무엇일까요? 바로 레이아웃입니다. 컬렉션 뷰는 여러 개의 열과 행으로 셀을 표현할 수 있습니다. 예를 들어, 그리드(grid) 형태로 아이템의 목록을 보여줄 수 있습니다. 그래서 수직 스크롤뿐만 아니라 수평 스크롤도 할 수 있습니다.스토리보드에서 디자인한 테이블 뷰 셀과 컬렉션 뷰 셀위 스크린샷에서 테이블 뷰와 컬렉션 뷰의 가장 큰 차이는 바로 셀입니다. 테이블 뷰에서는 하나의 열에 여러 행을 표시하는 형식이기 때문에, 셀의 모습을 행에 맞춰서 디자인합니다. 하지만 컬렉션 뷰는 열과 행을 만들 수 있기 때문에, 꼭 행의 모습이 아니더라도 다양한 모습으로 셀을 디자인할 수 있습니다. 컬렉션 뷰 셀의 가장 큰 특징이기도 하죠. 위처럼 셀을 디자인하고 앱을 실행하면 아래의 화면이 나타납니다.테이블 뷰와 컬렉션 뷰의 앱 화면 차이또한 컬렉션 뷰는 레이아웃 객체가 있습니다. 기존에 제공하는 flow layout을 사용해도 괜찮지만, 본인이 원하는 레이아웃 모양을 custom layout을 만들어서 사용합니다. 이를 담당하는 프로토콜은 UICollectionViewDelegateFlowLayout 입니다.func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {         let fullWidth = collectionView.frame.size.width - (self.CGFLOAT_INSET_WIDTH * 3) - (self.CGFLOAT_ITEMSPACING * 3)         let width = fullWidth/3         return CGSize(width: width, height: width + self.CGFLOAT_HEIGHT_ATTRACTIONCELL_DEFAULT)     }         func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {         return UIEdgeInsetsMake(self.CGFLOAT_LINESPACING_VERTICAL, self.CGFLOAT_INSET_WIDTH, self.CGFLOAT_LINESPACING_VERTICAL, self.CGFLOAT_INSET_WIDTH)     } 위 소스에서 collectionView(:layout:sizeForItemAt:) 메소드는 해당하는 셀의 사이즈를 설정하고, collectionView(:layout:insetForSectionAt:) 메소드는 섹션 안에 margin을 설정합니다.여러 모양의 셀을 이루어 하나의 뷰 화면을 구현할 수도 있습니다. 섹션마다 셀을 만들어 각각 다른 모습의 셀을 설정하고, 한 화면에 다양한 모습의 셀을 가진 뷰를 만드는 것입니다. 예를 들어, 헤더, 메뉴, 본문, 푸터 각각 셀을 만들어서 원하는 모양으로 만들고, 하나의 뷰 컨트롤러에 셀을 조합해서 한 화면에 나타나게 할 수 있습니다. 이 방법을 사용하면 자주 사용하는 셀을 재활용할 수 있습니다. 똑같은 헤더와 푸터 셀을 여러 번 만들지 않고 기존의 셀을 재활용하면 시간도 절약하고, 훨씬 깔끔한 소스를 만들 수 있을 겁니다.브랜디 앱 스크린샷 일부위의 스크린샷처럼 여러 화면에서 보여줘야 할 똑같은 뷰가 있을 때, 셀 xib 파일을 만들고 컬렉션 뷰에서 셀을 섹션별로 설정 및 사용하면 재활용하기 좋습니다.Conclusion지금까지 테이블 뷰와 컬렉션 뷰의 특징들을 살펴봤습니다. 한마디로 정리하면 테이블 뷰는 가장 간단한 목록을 만들 수 있습니다. 컬렉션 뷰는 다양한 모습의 목록으로 커스터마이징(Customizing)할 수 있습니다.그렇다면 우리는 어떤 것을 선택해야 할까요? 구현할 목록이 얼마나 복잡한지에 따라 선택은 달라집니다. 테이블 뷰는 간단하고 보편적인 목록을 만듭니다. 반면에 컬렉션 뷰는 특정한 모습의 목록을 만들 수 있습니다. 그래서 테이블 뷰는 목록이 간단하고 디자인 변경이 없을 때만 사용하길 권장합니다. 하지만 나중에 디자인이 바뀔 수도 있다면 컬렉션 뷰를 사용하는게 더 좋겠죠.Simple is the best! 간단하게 구현할 수 있는 건 테이블 뷰를 사용합시다. 테이블 뷰에서 구현하기 힘들다면 컬렉션 뷰를 이용해 개성 있는 목록을 마음껏 만들어봅시다!참고UITableView - UIKit | Apple Developer DocumentationUICollectionView - UIKit | Apple Developer Documentation 글김주희 사원 | R&D 개발1팀[email protected]브랜디, 오직 예쁜 옷만#브랜디 #개발문화 #개발팀 #업무환경 #인사이트 #경험공유
조회수 1612

2017 NDC 리뷰) 크립돈 퓨처 미디어와 하츠네미쿠

 이번글은 덕력이 솟구친다는!!!은 아니고요(진짜 아니에요), 혹시 "하츠네 미쿠"라는 캐릭터를 보신 적 있으신가요?하츠네 미쿠! 설마 처음보는 분들이 계신가요?? 출처: https://ec.crypton.co.jp/pages/prod/vocaloid하츠네 미쿠는 VOCALOID(보컬로이드)로서, 간단히 설명하면, 야마하에서 만든 음성 엔진입니다(자세한 내용은 링크를 확인!). 해당 엔진을 기반(자세히는 VOCALOID2인데... 아, 저는 잘 몰라요 진짜예요...)을 기반으로 크립톤 퓨처 미디어사가 아티스트를 만들고, 이를 지적 재산권(이하 IP라고 하겠습니다)으로 창출해 낸 사례입니다! 해당 세션은 이 보컬로이드가 성공할 수 있게 된, 창작자들에게 프로그램 번들 시디를 팔던, 크립톤 퓨처 미디어사가 새로운 미디어와 아트의 중심에 설 수 있게 된 이유를 들을 수 있게 된 좋은 시간이었습니다. 앞으론 말이 매우 딱딱하니 이점 히해해 주세요~! 시작하겠습니다!씨디파는 회사가 인터넷 시대를 맞이하며 겪게 된 위기, 그리고 해결방안. 앞서 말씀드렸든, 크립톤 퓨처 미디어(이하 크립톤이라고 하겠습니다)는 창작자들을 위한 서비스(또는 프로그램)를 번들 또는 디스크 형식으로 판매하는 회사였습니다. 그리고 새로운 세대로 들어서면서, 해당 사업이 사양되고 있고(디스크 판매> 콘텐츠 다운로드의 변화), 특히 음악 제작 서비스의 경우, 작은 시장의 규모 때문에 비즈니스에 대한 한계를 느끼고, 새로운 사업 영역을 펼쳐나가기 위해 방향 모색하기 시작했다고 합니다. 그리고 크립톤이 생각할 수 있는 "자사가 가장 잘할 수 있는 것"을 생각해 보았을 때, "소리"라는 콘텐츠를 방점으로 서비스를 응용해 나가면서 스팩트럼을 넓히자!라는 생각을 했다고 합니다. 그래서 시작한 것이 바로, 보컬로이드!라는 것이었죠.보컬 합성 기술(보컬로이드) + IP의 도입은 처음부터 성공적이진 않았습니다. 처음 크립톤은 야마하의 보컬로이드 기술을 기반, Leon과 Lola라는 소프트웨어를 제작,  당사에서 유통을 시작했을 때에는, 타깃 유저를 잡는데 실패해 매출에 전혀 도움이 되지 않았다고 합니다(아래 사진을 보면 왠지 알 거 같...)첫 보컬로이드 레온과 로라입니다..... 음... 입술이 매력적 이네요.... 출처: http://vocaloid.wikia.com/wiki/Forever_(Zero-G_song) 그 이유는 해당 서비스를 사용할 것이라고 타게팅한 아티스트들의 경우, 목소리에 관해 리얼함을 추구하는 데, 해당 소프트웨어는 하드웨어로 조정하는 음과 음성들이 리얼함이 다소 떨어져 전혀 니즈가 없었던 것이죠.그래서 트립톤은"해당 서비스를 진짜 사용하는 유저들은 어떤 사람들 일까?"에 대한 고려를 기반으로,"메이코"라는 일본어로 노래하는 보컬로이드를 제작, 흥미를 끌 수 있도록 캐릭터를 모티브로 하는 커버 디자인 작업 시작(안드로이드 아니 보컬로이드 이니깐요!)이제는 버전 쓰리가 된 메이코! (출처:http://vocaloid.wikia.com/wiki/MEIKO) 첫 출시 당시, 거부감도 있었지만, 당시 KPI 목표인 500개를 훌쩍 넘어 3,000개의 판매 성공을 거뒀고, 성공의 요인은 패키징 디자인과 단순한 아티스트뿐만이 아닌, 다양한 콘텐츠에 관심을 가지는 다양한 유저들을 유저들을 이끌 수 있는 요소들이 있어서 라고 판단하였다고 합니다. (서비스를 사용할 것이다 라는 사용자의 경험에 대한 고려를 더 많이 한 포인트라고 생각되는 부분이지요!)메이코 이후 드디어 그분을 만들어 내는 것을 준비합니다.크립톤은 이때부터 정말로 사용자들이 무엇을 원하는가에 대한 생각을 많이 한 것 같다고 보이는 포인트입니다. 메이코의 등장 이후, "하츠네 미쿠"라는 캐릭터 산업으로 만들어 내는 것을 준비합니다. 그리고 해당 캐릭터를 하나의 "사업전략"으로 생각해 낸 이유는 메이코의 KPI달성도 있겠지만, "사람의 목소리와 극히 다른 목소리로 노래를 부르게 된다면, 이상하지 않을까?라는 부분을 오히려 역으로 기획, "인간이 아닌 다른 안드로이드가 하는 노래"라는 새로운 존재로서 IP를 만들어 버린 것이죠!또,  캐릭터를 기반으로 다양한 성격을 가질 수 있도록 "성우"라는 시스템을 집어넣어 "특별한 존재"라는 특징 성을 추가하였고, 기존의 보컬로이드는 "인간의 가수를 대체하는 것"이었으나, 하츠네 미쿠는 "안드로이드 가 부르는 진짜 보컬로이드"라는 접근을 통해 새로운 존재를 만들고, 메이코 디자인을 기반으로, "아이돌 라이즈 된 새로운 사이버 가수"를 만든 것이죠!아아.... 이제 고인이 되신 사이버 가수 아담... (http://beautinaru.tistory.com/196 또한, 해당 콘텐츠를 기반으로 음악을 만들었던 유저들에게 레트로 한 마크들을 집어넣어서 예전에는 이랬었지 라는 향수를 불러일으키고, 해당 콘텐츠를 기반으로 다시 작업을 할 동기를 줄 수 있도록 유저들의 의견을 듣고 반영하는 일들을 굉장히 많이 했다고 합니다!그리고 하츠네 미쿠의 진정한 아이덴티티를 생성합니다. 그것은 바로 Chain of Co-creation!!!하츠네 미쿠가 이렇게 성장할 수 있었던 이유는 저는 하나만 꼽으라 라고 한다면 이쁘잖아요! 가아니라... "확산 가능 여부"에 대한 많은 고려가 있었기에 가능했다고 생각합니다.인터넷 덕분에 음악 등을 만드는 사람들이 쉽게 업로드하고 공유할 수 있는 많은 플랫폼들이 생성되는 현실.덕이 많은 분들이 공유를 통해 자아실현을 하는 공감대를 형성할 수 있는 움직임이 확산.콘텐츠가 콘텐츠를 만들고 퍼져나가는 순기능적인 부분들이 늘어나는 현상들을 확인하고,2차 3차 저작물을 통한 확산> Chain of co-creation의 순선환 적인 기능들이 생겨나는 것이죠!! 그리고 그런 상황을 기반으로, 궁극적으론,모든 사람들이 제작자가 될 수 있는 현실 상황을 받아들이고,제작할 수는 있지만,  저작에 관련한 법률 등에서 막히는 상황을 막기 위해, 창작자들의 창작활동을 돕고, 실제 업로드된 콘텐츠를 기반으로, 실제 사업이 일어날 수 있는 방향으로 전개합니다!그리고 수익화를 통해서 창작자들이 창작활동 = 수익활동이 될 수 있도록 플랫폼 화를 추진한 것이죠!그래서 처음 하츠네 미쿠가 나온 2007년부터 10년이 지난 지금까지도 "보컬로이드"의 선두 주자로 전 세계적으로 콘서트를 다니며 성공적인 투어를 하고 있습니다.투어는 계속된다. (출처: http://mikuexpo.com/) 저는 하츠네 미쿠가 단지 덕후들의 승리라고 요만큼도 생각하지 않습니다.하츠네 미쿠를 성장시킬 수 있었던 건 "우리가 제공하는 서비스가 어떤 유저들에게 더 많은 강점이 있고, 해당 유저들은 어떤 행동을 통해서 자아를 성찰할 수 있을까? 그리고 해당 행동을 통해 유저가 얻는 궁극적인 이익들이 잇을까?"를 생각했던, 크립톤의 유저를 생각하는, 유저의 직접적인 경험을 서비스에 반영하려고 하는 강한 의지가 해당 서비스를 성공시킬 수 있게 한 요인이라고 생각해요. 그런 의미에서 저에겐 정말로 뜻깊고 즐거웠던 세션이었습니다!P.S.: 이제 슬슬 NDC2017 영상들이 올라오기 시작하네요! 관심 있는 분들은 https://ndc.nexon.com/main에서 확인해 보세요~오늘도 긴 글 읽어주셔서 감사합니다! 다소 글이 엉망진창이라도 이해해 주세요! #코인원 #블록체인 #기술기업 #암호화폐 #스타트업인사이트
조회수 2609

DevOps, 그 문화에 대해서...

개발 방법론이나 소프트웨어 개발과 관련된 은빛 탄환과도 같은 뉘앙스를 풍기는 접근법은 수없이 많았다. 이제는 최고의 화두로 떠오른 DevOps에 대해서 삐딱한 아키텍트의 생각으로 끄적거려 보자.주변에 DevOps를 지향하는 개발회사들이 많다. 그리고, DevOps를 무슨 완전체인 것처럼 소개하는 칼럼이나 글들도 많다. 그렇다면, DevOps의 정체는 무엇이며, 우리 회사, 우리 개발팀이나 운영팀은 그런 준비가 되어 있는 것인지에 대해서 생각해봐야 한다.사람들은 정말 DevOps가 어떤 의미이기에 사람들이 궁금해하고 있는 것일까?, 그리고. 과연 정말 내가 속한 조직과 팀이 DevOps를 지향할 수 있을까? DevOps에 대해서 삐딱한 아키텍트가 생각해보는 것이 이번 칼럼의 목적이다.DevOps는 모든 팀, 모든 회사, 모든 곳에 사용되는 만병통치약이 아니다.DevOps는 새로운 개념인가?Culture와 movement에 대해서 먼저 이야기를 시작하는 것이 맞을 듯하다. Culture는 어떤 한 국가나 집단의 문화와 같은 것을 의미한다. 그리고, movement는 어떤 움직임을 의미하는 것으로 여기서 사용되는 의미로는 사람들이 조직적으로 어떤 것을 벌리는 운동을 의미한다.일반적으로 문화란 어떤 옷, 음악, 형태를 가진 조형물 등을 포괄하는 것으로 무형, 유형의 것을 모두 포함하는 것이 문화라고 할 수 있다.그리고, 이러한 문화는 해당 문명과 조직, 사회의 모든 것을 표현하고 있는 것이며, 그것에 대비하여 문화라는 형태를 통해서 표현한다. 그래서, 소프트웨어 개발의 조직이나 기업에서도 자체적인 개발자 문화라는 것이 존재하고 있다. 이는, 일반적으로 각 회사별로 그 형태나 상황, 사람들의 모습, 역사적인 배경과 발전과정을 통하고, 어떤 사람들이 그 조직을 거쳐갔느냐에 따라서 많은 부분에 있어서, 개발자들의 문화는 매우 다르다고 할 수 있다.이처럼, 개발자 문화의 영향으로 소프트웨어 개발 방법론과 같은 무형의 것부터, 실제 산출물, 개발 소스와 같은 실제 눈에 보이는 것까지 개발자 문화란 눈에 보이는 것과 눈에 보이지 않는 것을 모두 포함한다고 할 수 있다.이런 개발자 문화를 언급하기 전에, 개발자들의 운동과 운동을 위한 선언과 같은 것에 대해서 알아보자. 그중에서도 movement를 먼저 살펴보자. 개발자들 커뮤니티와 개발자들의 요즘 철학적인 움직임은 ‘요구사항’ 변동에 대해서 이제 관대한 생각을 가지기 시작했다고 볼 수 있다.어차피, 요동치는 요구사항에 대해서 ‘완결된 요구사항’이 나올 것이라고 기대하지 않고, 요구사항은 사랑하는 애인의 변덕스러운 마음이라는 생각을 가지기 시작한 것이 DevOps의 원칙적인 기본 생각의 변화라고 먼저 이야기를 하고 싶다.이제, 개발자들은 요동치는 사람들의 마음이나 사회적인 변덕을 소프트웨어로 반영하는 것을 매우 당연스럽고 자연스러운 과정이라고 인지하기 시작한 것이라고 볼 수 있다. 이처럼 기본적으로 요구사항이 변덕스러운 기획자나 고객의 마음이 당연한 것이라고 생각한다면, 오히려, 더 행복한 개발이 가능하도록 기준이나 계획을 잡을 수 있는 것 아닐까?이것이 DevOps의 개념 전환의 기본적인 개념이라고 볼 수 있다. 오히려. 처음부터 요구사항이 잘 정해졌고, 더 이상 변하지 않을 것이라고 거짓말을 하고 있는 기획자와 고객들의 마음속에 변덕스러운 변화에 대해서 이제는 관대한 개발자가 되려는 마음을 가진 것이라고 생각할 수 있다고 소프트웨어 개발자들은 이해하기 시작한 것이다.DevOps는 이러한 마음가짐의 변화와 movement가 먼저 필요하다. 기존의 개발 방법론이나 개발 문화에서 정의하려고 하였던, 뜬구름 잡는 ‘요구사항 명세’는 어차피 불가능한 것이니까, 그 부분을 매우 관대하게 받아들이고자 변화의 마음을 가지게 된 것이라고 생각한다. 그래서, 실제 고객을 만족시키는 요리사의 마음에다가 고객의 마음을 좀 더 가까이에서 이야기를 나눌 수 있는 웨이터의 마음을 가지고 시작해야 한다고 설명하는 것이 더 현명할 수 있다.이러한 변화의 요소에는 다음과 같은 개발자들이 두려워하는 몇 가지 요소들에 대해서 이제는 정말 명확하게 이야기할 수 있기 때문에 DevOps는 가능하다고 생각한다.DevOps의 내면에 깔려 있는 소프트웨어 개발자들의 두려움을 먼저 알아야 DevOps의 기본적인 원칙에 좀 더 접근할 수 있다. 그것은 다음에 나열된 내용들은 일반적으로 소프트웨어 개발자들이 어려워하는 것들이다.1.  소프트웨어를 솔루션 형태의 디자인으로 만드는 것은 정말 어렵다개발자들은 솔루션을 만들고 그것을 디자인하고 설계, 구현한다는 것은 정말 어려운 것이라고 인지하기 시작하였다. 솔루션을 만들고, 어떤 문제를 해결한다는 것은 정말 험난하고 고된 일이라고 이미 인지하였다.2.  테스트 케이스를 작성한다는 것은 정말 어렵다수많은 사용자의 환경을 인지하고, 그것에 대응하는 완벽한 테스트는 불가능하다는 것 또한 개발자들은 인지하였다. 그리고, 그 테스트를 만들기 위해서 쥐어뜯었던 머리카락과 수많은 시간들에 대해서 완전이란 불가능하다는 것을 인지한 것이다.3.  개발 관련 문서작성 또한 매우 어려운 것이다개발자들 간에 상호 소통하기 위한 문서의 작성과 다이어그램과 모델을 만든다는 것 또한 정말 어려운 일이다. 또한, 그것을 표준이나 변화해가는 기술적인 요청과 반영 내용을 모두 담는다는 것은 정말 어려운 일이라고 인지하였다.4.  개발자 자신이 동의하지 않는 기능 구현을 허구 헌 날 해야 한다는 것간혹이 아니라, 상당 부분 발생하는 동의하지 않는, 쓸모없다고 생각하는 기능 구현에 매달리고 있는 현실에 대해서 이제는 약간은 무덤덤하게 대응할 수 있는 개발자들의 마음가짐은 정말 관해하게 변화하였다.5.  다른 사람이 작성한 코드를 다루는 것인 매우 당연하다는 것생각 이상으로 다른 사람의 코드와 프레임워크에 가두어진 상태로 프로그래밍을 해야 한다는 것에 대해서 학교에서는 가르치지 않았다는 것을 매우 두려워하고, 원망한다. 타인이 만들어 놓은 코드에 대해서 읽는 방법에 대해서 가르쳐 주지 않은 교수님이 원망스러울 뿐이다.6.  고객과 같이 비전문가와 커뮤니케이션해야 한다는 것비전문가와 소통하는 방법에 대해서 아무도 가르쳐주지 않았다. 사실은 그들과 소통하고 그들을 설득하는 것이 최선의 방법인데, 왜? 그들과 소통하는 방법은 학교에서 가르치고 있지 않는가? 혹시. 교수님들도 그것을 포기한 것 아닌가 하는 의심이 든다? 그러한 마음이 생기기 시작하였고, 과거의 방법론이나 공학에 대해서 의심을 하기 시작하였다.7.  업무 완료에 필요한 시간 예측은 필수가 되었다는 것기능 단위의 시간 예측과 일정에 대해서 ‘감’이 필요하다는 것은 실제 현업에 나와서야 만 가능하다는 것을 이야기해준 선배와 교수가 없었다는 점도 실제 현업의 초기에 어려움을 느끼는 부분들이다.8.  업무의 우선순위와 작업 할당이 애매하다는 것도대체 누가 결정하는가? 그 순서에 대해서 아무도 모른다.9.  이름을 만들고, 이름과 의미를 부여한다는 것은 매우 어렵다는 것그냥, X, Y, I, j, k를 부여하면 안 된다고 하는데, 생각 이상으로 붙여야 할 이름과 규칙들이 너무도 많다.이처럼, 소프트웨어 개발이 어려워지고 두려워지는 개발자들보다 더 어려운 것도 있다는 사실을 소프트웨어 개발자들은 경험으로 터득한다. 그것은 다음과 같은 상황이다. 그리고, 해결책도 없다는 점이다.위의 두려운 상황은 ‘단단한 마음’으로 이겨낼 수 있지만, 정마로, 다음의 상황들은 가능하면 소프트웨어 개발자들이 피하고 싶어 진다. 하지만, 우리가 지금 당장, 어제, 그리고 내일도 만날 수 있는 상황이다.1.  무능력한 경영진의 삽질2.  멍청한 동료 개발자의 어설픈 코드3.  특정 기술이 무슨 이유에서 쓰이는지도 모르고 강제로 배우거나 사용해야 하는 것4.  재미있어 시작한 개발일이 정말 반복적인 작업에 의해서 재미없어졌을 때5.  이제 쏟아지는 버그를 만나게 되었을 때하지만 가장 두려운 상황의 최고봉은 역시, ‘개발자는 고객과 대화를 나누는 것이 가장 두렵다’라는 것이 정답일 것이다. 그리고, 두려운 것은 동료와의 커뮤니케이션과 소통이다. 아마도, 이러한 고객과 동료들 사이에 있다면, 개발자는 당연한 것이지만. ‘개발하는 것이 행복하지 않다’라고 느끼는 것은 매우 당연할 것이다.여기서. DevOps는 출발한다.이렇게 ‘개발하지 않는 것이 불행한 개발일’을 하지 않게 하기 위한 일종의 movement라고 생각하면 된다.아이러니 하지만, 이러한 불행을 해결할 가장 좋은 방법은 행복의 최소 조건이나 개발자가 원하는 개발환경의 최소 조건을 만족하면 된다. 그것은 바로 자원(resource)이 충분한 환경을 만들면 가능하다. ‘돈’이 넉넉하면 부수적으로 대부분 따라오는 것들이다.하지만, 실제 개발일을 이런 환경에서 할 수 있는 방법은, ‘취미’로 개발일을 하는 경우에만 100% 만족할 수 있을 것이다. 취미는 최종 개발완룐일을 언제든지 뒤로 미룰 수 있기 때문에 ‘무한정의 리소스’를 투입할 수 있는 유일한 방법일 것이다.DevOps는 개발자가 행복하게 소프트웨어를 개발할 수 있는 환경을 만드는 것이 목표이다. 과거의 개발 방법론이나 문화, 운동들이 대부분 ‘소프트웨어 품질’을 위해서 개개인의 시간과 개개인의 능력 차이를 무시하고 진행되었다면, DevOps는 그 우선순위의 가장 높은 개념으로 ‘개발자의 행복’을 우선순위 위에 둔다.결론적으로 ‘개발자가 행복’하다면,자연스럽게 소프트웨어의 ‘품질’은 올라간다는 개념이다.물론, ‘행복’이 아니라, ‘시간 낭비’라는 단어와 ‘물자와 자원 낭비’라는 결코, 개발자는 행복하지 않을 것이다. 대부분의 개발자들은 ‘시간과 자원의 낭비’를 가장 싫어한다. DevOps는 기본적으로 개발자들을 신뢰해야 형성된다.DevOps는 소프트웨어 개발과 운영, 서비스의 효율적인 환경을 만들기 위해서 노력하는 개발 문화로써 간단하게 줄여서 설명하자면. ‘소비자, 사용자들의 서비스의 요구사항을 가장 빠르고 단순화하여 대응할 수 있는 신속한 서비스 지원 형태. 그리고, 그것을 지원하고 유지시켜주는 소프트웨어 개발 문화’라고 이야기할 수 있다. 그래서 Development / Operations를 합친 말이라고 본다.물론, 이렇게 만들어진 환경은 당연하지만 개발자를 ‘행복’하게 할 것이다.DevOps는 빠르고, 단순화, 신속함이라는 서비스 형태를 지향한다. 그리고, 그것을 지원하고 유지시켜주는 소프트웨어 개발 문화를 지향하고 있다. 실제, DevOps를 구현했다고 평가를 받고 있는 Netflix와 Flickr 등의 개발 성과물들은 정말 놀라울 정도로 효과적이다.1만 개 이상의 AWS 인스턴스를 불과 10여 명의 DevOps팀이 운영하고, 초당 4만 장 이상의 업로드 부하를 버티고. 자동화된 상태에서 하루 10회 이상의 배포본이 반영되는 매우 효과적인 개발과 운영이 접목된 환경을 만들어 낸다는 사실에 개발자 문화의 최신화 경향을 만들어 냈다.이렇든 엄청난 효율과 고속의 처리를 만들어 낸 것은 어떤 이유 때문에 가능한 것이었을까? 그리고, 이러한 DevOps의 성과물들은 일반적인 IT기업에서도 얻을 수 있는 환경일까? 가장 먼저 DevOps의 장점을 몇 가지 정리하고 넘어가자.DevOps의 장점을 서술한다면 다음의 3가지로 선언할 수 있다.1.  최소 인원으로의 개발과 운영이 가능한 환경을 지향한다2.  서비스의 배포와 운영이 자유롭고, 서비스가 매우 신속하고 빠르게 운영된다.3.  개발의 배포가 자동화되며, 그에 따라 고품질 서비스를 지향한다.자, 그렇다면. 가장 중요한 것은 이러한 DevOps는 내가 속한 조직에서 만들 수 있는 문화와 개발형 태인가? 대부분의 개발 조직에서는 이러한 것에 대해서 가장 궁금할 것이다. 결론부터 이야기하자면 DevOps가 가동되고, 개발 조직의 문화가 되려면 다음의 두 가지가 필수이다.1.  소프트웨어를 잘 만들어내는 개발자2.  잘 동작하도록 운영하는 운영자그리고, 이러한 두 가지의 조건을 만족시키기 위한 기본적인 환경적인 구성이 필요하다. 그것은 가장 먼저 소프트웨어 품질을 관리하는 제대로 된 품질관리 조직이 있어야 하며, 개발 조직이 빠르게 소프트웨어를 개발, 빌드, 테스트, 배포, 운영하게 할 수 있는 사이클을 신속하게 진행할 수 있는 개발환경을 갖추고 있어야 하고 업무 프로세스를 정의하고, 각 조직 간의 역할을 조율하는 프로세스들이 매우 자연스럽게 자동화되어지고 효율적으로 운영되고 있어야 한다. 그래야, ‘소프트웨어를 잘 만들어내는 개발자’와 ‘잘 동작하도록 운영하는 운용자’가 만들어지게 되고, 그 역할과 방법론이 효율적으로 가동되는 DevOps는 가동된다.DevOps의 원칙그렇다면, 이러한 DevOps을 세팅하고 구입하기 위해서 조직이 필요로 하는 비용적인 측면은 어떤 것들이 있을 것인지 가볍게 살펴보자. DevOps는 매우 큰 비용을 요구하는 것은 아니다. 다만, 그 비용이라는 것이 전반적으로 투자된 비용을 의미하는 것이지, 단기간에 투입되어 얻어지는 효과는 아니라는 점에 주목해야 한다.가장 먼저, 개발자들은 기능 개발과 결함의 수정 등의 변화를 얼마나 자주 일으키고 있는지 체크하고 이를 관리하거나, 관리할 수 있는 포인트를 개발자들에게 제공하고 있는가? 하는 측면이 가장 먼저라고 할 수 있다.두 번째는 운영자가 실제 서비스의 안전성과 성능의 향상을 위하여 취해지는 시스템 아키텍처 적인 변화에 대해서 얼마나 두려워하고 있으며, 이를 얼마나 수치화하여 관리하고있는지, 그리고. 그 선택을 할 수 있는지가 DevOps에 가장 중요한 측면이기도 하다.세 번째는 이러한 개발집단과 운영 집단에서 선택과 운영, 개발의 우선순위 등을 고르고 선택할 수 있는 ‘권한과 책임’이 주어지고 있느냐 하는 점이다.네 번째는 큰 조직, 큰 기업, 큰 프로세스의 운영 시에는 이러한 DevOps와 같은 콘셉트는 운영하기 매우 어렵다. 그러므로, 개발과 운영환경의 구분과 절차. 권한과 릴리즈 절차와 규칙 등에 대해서 얼마나 세분화하고 있는지, 그리고. 일에 대해서 얼마나 작은 규모로 산정하고 산출하고 있는지에 대해서도 정의되어야 한다.아쉽게도 DevOps를 구현하고 싶지만, 착각하고 있는 개발자 조직의 경우의 사례를 살펴보면 다음과 같은 실제 일들이 벌어진다고 볼 수 있다.1.  사용하지도 않는 기능을 도출하고, 이를 위하여 시간과 비용을 낭비하고 있는 경우2.  개발 후 버그를 찾기 위해서 테스트를 하고 있다고 프로세스를 정형화하는 일이다. 실제 DevOps를 지향하는 개발 조직의 경우에는 내부적으로 개발 단계에서 충분하게 품질을 고려하여 디자인되고 개발을 진행하려 노력한다.3.  예측을 위한 투자를 많이 하고 있는가?라는 질문에 소극적인 경우이다. 대부분은 그나마. 사건 발생 시에 빠르게 대처할 수 있는 환경이라고 가능한 구축하라고 권하는 경우가 태반이다.4.  소프트웨어 공학을 잘 못 받아들여 정말 중요한 지표에 집중해야 하는데, 너무 많은 지표를 도출하기 위하여 삽질을 하는 경우가 대표적인 착각되어진 개발 조직의 경우라고 볼 수 있다.DevOps을 좁게 보는 진정한 장점DevOps는 ‘잦은 배포’를 수행하면서, 잦은 릴리즈를 수행하고, 잦은 릴리즈를 통해서 위험을 하향 균등화 시키는 것이 주목적이라고 작게 정의할 수 있기도 하다. 그래서, 애자일과도 아주 잘 맞는다. TimeBox를 2주로 맞추거나 1.5주로 맞추고 배포를 진행하는 경우도 빈번하게 필자는 상황을 참조한다.하지만, 이러한 DevOps를 구현하는 데 있어서는 다음과 같은 최소한의 필요충분 요건이 필요하다.1.  잦은 개발과 버그 픽스가 가능한 개발자 환경을 구현하라2.  공유 소스 코드 버전 관리시스템도 없다면, 이러한 환경을 구성한 다는 것은 거의 불가능하지 않겠는가?3.  빌드, 테스트, 배포 단계를 자동화하기 위하여 얼마나 노력하고 있는가?4.  수작업의 실수와 반복을 어떻게 최소화하기 위해서 노력하는가?5.  개발 조직과 운영조직의 협업을 위하여 빈번한 커뮤니케이션 소통 비용을 지불하고 있는가?이러한 최소한의 필요충분조건을 만족한다면, 개발 조직은 다음과 같은 최소한의 목표를 이루기 위해서 준비를 한다고 볼 수 있다.1.  개발과 품질관리, 운영을 교집합적으로 운영하기 위한 방법을 터득하였고, 그것을 개발 조직에 내재화하기 위하여 노력 중이다.2.  신뢰성, 보안성, 개발과 배포 사이클을 보다 더 빠르게 개선하기 위해서 배포, 테스트, 세부 기능 개발, 릴리즈 관리를 목표로 조직이 운영 중이다.3.  툴이 아니라, 문화와 일하는 방법에 대한 경험을 더 우선적으로 하고 있다.DevOps의 가장 중요한 원칙위에서 이야기한 필요조건과 환경에 대한 것이 준비가 된다면, 다음과 같은 DevOps의 원칙을 실현할 준비가 된 것이다. 그 원칙을 살펴보자1.  주요 기능에 집중하고 있는가?2.  품질을 내재화하기 위하여 노력하고 있는가?3.  개발에 필요한 지식을 창출하기 위해서 과학적으로 접근하고 있는가?4.  완벽한 명세서를 만들기 위한 비용보다, 명쾌한 협업을 중시하여 커뮤니케이션 비용을 지출하고 있는가?5.  가능한 한 빨리 개발하기 위해서 시도하고 있는가?6.  사람을 존중하는 개발자 문화를 만들고 있는가?7.  최적화를 위한 방안을 고안하는데 회의나 토론을 아까워하지 않고 있으며, 그것에 대해서 투자를 아낌없이 하고 있는가?이러한 과정은 DevOps에 대해서 실현하기 위해서 노력하는 행위와 절차라고 볼 수 있다. 가능하다면 DevOps의 성숙도 모델에 대한 설명과 실제 우리가 그러한 모델을 통해서 개발 조직에 DevOps의 사상을 표현할 수 있는지에 대해서 설명할 기회가 곧 다가올 것으로 기대해본다.물론, 기술적 부채에 대해서도 한 번 거론한 다음에 그 이야기를 이야기하도록 하겠다.DevOps는 애자일과 마찬가지로 선언이고 문화에 해당한다. 즐거운 개발을 지향하고 있다면 소프트웨어 품질은 매우 당연하게 좋아진다. 행복한 개발자가 훌륭한 소프트웨어를 만든다는 것을 잊지 말자. 그것이 DevOps의 시작이며, 출발이다.
조회수 998

비트윈 시스템 아키텍처

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]로 이메일을 주시기 바랍니다!
조회수 8827

AWS Lambda에서 메모리 설정값과 CPU 파워의 관계

안녕하세요. 데이블 백엔드 개발팀 최형주입니다.이번에 말씀드릴 내용은 서버 없는 컴퓨팅(Serverless Computing)의 널리 사용되는 AWS(Amazon Web Service)의 Lambda에 대한 내용입니다. AWS Lambda는 메모리 설정값에 따라 CPU 파워가 결정되는데, 그 메모리 설정값에 따라 CPU 파워가 어떻게 변화하는지에 대한 실험 내용을 설명하겠습니다. 처음에 AWS Lambda가 무엇인지 간략하게 소개를 하고 왜 이번 실험을 하게 되는지 배경 설명을 드릴 것입니다. 그다음 메모리 설정값에 따른 CPU 파워는 어떻게 결정되는지를 규명하고 마지막으로 이번 포스트를 간략히 요약겠습니다.목차1. AWS Lambda란?2. 실험배경3. 메모리 설정값과 CPU 파워의 관계4. 요약AWS Lambda란?AWS Lamba의 웹사이트AWS Lambda는 이벤트에 응답하여 코드를 실행하고 자동으로 기본 컴퓨팅 리소스를 관리하는 서버 없는 컴퓨팅 서비스입니다. 즉 코드를 업로드 하기만 하면 높은 가용성과 확장성을 보장하는 Lambda 플랫폼에서 코드를 실행합니다.AWS Lambda를 사용의 장점은 서버관리 불필요(Serverless), 지속적인 조정(Scaling), 밀리 초 단위의 측정 및 과금(Demand-based Pricing)입니다. 즉 서버를 프로비저닝(Provisioning)하거나 관리할 필요 없이 AWS Lambda에서 코드를 자동으로 실행하기 때문에 코드를 작성하고 AWS Lambda에 업로드하기만 하면 됩니다. 또한, 각 트리거에 대한 응답으로 코드를 실행하여 애플리케이션을 자동으로 확장하거나 축소합니다. 즉 코드는 병렬로 실행되고 각 트리거는 개별적으로 처리되어 정확히 워크로드(Workload) 규모에 맞게 조정됩니다. 과금 방식은 100밀리 초 단위로 코드가 실행되는 시간 및 코드가 트리거 되는 회수를 기준으로 요금이 부과됩니다. 코드가 실행되지 않을 때는 요금이 부과되지 않습니다.실험 배경AWS Lambda의 과금은 요청 요금과 컴퓨팅 요금의 합으로 계산됩니다. 요청 요금은 Lambda 함수를 호출한 총 요청 수에 대해 요금을 부과하고, 컴퓨팅 요금은 사용자가 업로드한 코드를 실행한 시간을 계산하여 100ms당 요금을 부과합니다. 컴퓨팅 요금은 사용자가 설정한 메모리 크기에 선형 비례하여 다르게 부과됩니다. 예를 들어 128MB 메모리에서는 100ms당 0.000000208$이고 256MB는 128MB의 약 두 배인 0.000000417$입니다. 그리고 512MB에서는 256MB의 두 배인 0.000000834$입니다. 또한, 더 큰 메모리를 사용할수록 더 큰 CPU 파워를 제공합니다.가장 큰 메모리 설정값을 사용하면 좋겠지만, 비용적인 측면을 고려해볼 때 사용자 입장에서의 사용 목적은 AWS Lambda로부터 최소한의 요금으로 최대한의 계산 효율을 뽑아내는 것입니다. 이 목적을 달성하기 위해서는 Lambda 함수를 실행할 때 메모리의 크기와 CPU의 파워(코어 수, 연산능력)를 명확하게 규명할 수 있어야 합니다. 메모리 크기는 사용자가 설정할 수 있습니다. 하지만 아쉽게도 아마존에서는 CPU 용량은 설정한 메모리 크기에 비례하여 결정된다고만 설명되어 있고 어느 정도의 성능을 가졌는지 명시하지 않고 있습니다.하지만 데이블의 백엔드 개발팀에서, 실험을 통하여 AWS Lambda에서 메모리 설정값에 따라 CPU 파워가 어떻게 변하는지 규명해냈습니다. 이제 그것을 이 포스팅을 통해 설명해 드리고자합니다.메모리 설정값과 CPU 파워의 관계"설정한 메모리 크기와 CPU 파워는 지수적 감쇠 관계(Exponential Decay)를 보인다"앞서 "CPU 파워는 메모리 설정한 값에 비례하여 증가한다”라고 했습니다. "그러면 어느 정도로 어떻게 비례하는가?”, “당연히 선형관계 아닌가?"라는 질문이 자연스럽게 나올 것입니다. 저희는 이 질문에 대답하기 위해 각 메모리 설정값별로 100만 번의 덧셈연산을 하여 각 설정 별 처리시간을 계산해 보았습니다. 다음 [그림 1]은 100만 번의 덧셈 연산을 했을 때 처리시간을 나타낸 그래프입니다. X축은 할당한 메모리의 크기를 나타내고 Y축은 처리시간을 초 단위로 측정한 것입니다. 보시는 바와 같이 처리시간은 메모리 크기에 따라 지수적으로 감소함을 알 수 있었습니다. 그러므로 AWS Lambda에서는 설정한 메모리 크기와 CPU 파워는 지수적 감쇠 관계(Exponential Decay)를 보인다고 결론을 내릴 수 있습니다. 예를 들면 현재 설정한 메모리보다 2배 높은 CPU 파워를 사용하고 싶으면 2배로 큰 메모리 용량을 설정해야 합니다.[그림 1] 메모리 설정값에 따른 처리시간필요로 하는 메모리 크기와 사용하는 응용에 따라 다르겠지만, 일반적으로 메모리의 크기에 상관없이 사용하는 비용이 거의 같다고 얘기할 수 있습니다. [그림 2]는 앞서 100만 번 덧셈 연산을 1만 번 호출했을 때의 각 메모리 설정값 별 요금을 나타낸 것입니다. X축은 설정한 메모리 크기이고 Y축은 각 메모리 설정값 별 요금입니다. 보시는 바와 같이 분포가 급격히 변하지 않고 대체로 균일한 것을 알 수 있습니다.[그림 2] 메모리 설정값에 따른 요금하지만 프로그램의 실행 시간은 단순히 CPU 파워로만으로 처리 시간이 결정되지 않기 때문에 다양한 요인을 검토해야 합니다. 알고리즘의 시간복잡도, 메모리의 크기와 접근 횟수, 네트워크 비용 등 다양한 것들이 처리 시간에 영향을 미치기 때문에 단순히 메모리 설정값을 늘려서 사용하는 방법은 옳지 못합니다. 그러므로 위 자료를 참고 용도로만 사용하셔서 하고자 하는 목적에 맞게 가장 최적의 메모리 설정값을 설정하시면 됩니다.요약AWS Lambda는 대표적인 서버 없는 컴퓨팅 서비스입니다. AWS Lambda에서 뛰어난 가성비를 얻고자 할 때는 각 설정값에 따라 제공하는 자원을 예측할 수 있어야 합니다. 여러 설정값 중 가장 성능에 큰 영향을 미치는 것은 사용하고자 하는 메모리 크기인데 이 크기에 따라 CPU 파워가 결정됩니다. 하지만 각 메모리 설정값에 따른 CPU 파워 정보를 아마존에서 제공해 주지 않고 있으므로 실험을 통해서 확인하였습니다. 실험 결과 설정한 메모리 크기와 CPU 파워는 지수적 감쇠 관계(Exponential Decay)를 규명했습니다. 이 규명은 단순한 프로그램에서만 확인한 것이기 때문에 최고의 효율을 가지는 AWS Lambda를 사용하기 위해서는 그 밖의 다양한 것들을 고려하여 설정해야 합니다.  기타머신 성능 및 정보- 사용하는 CPU는 Intel(R) Xeon(R) CPU E5-2666 v3 @ 2.90GHz, 코어의 개수는 2개, 그리고 캐시의 크기는 25600 KB 임(사용하는 Microcode는 바뀔 수 있음)- 메모리는 약 3.67GB를 가짐실험에 사용한 Lambda 함수import osimport multiprocessingimport timeimport subprocessdef lambda_handler(event, context):mem_bytes = os.sysconf('SC_PAGE_SIZE') * os.sysconf('SC_PHYS_PAGES')mem_gib = mem_bytes/(1024.**3)num_cores = multiprocessing.cpu_count()#start_time = time.time()print subprocess.check_output ('vmstat -s', shell=True)sum = 0for i in range(1000000):sum += iif sum 000 == 0:print subprocess.check_output ('vmstat -s', shell=True)print subprocess.check_output ('vmstat -s', shell=True)hostname = subprocess.check_output ('hostname', shell=True)cpuinfo = subprocess.check_output ('cat /proc/cpuinfo', shell=True)meminfo = subprocess.check_output('cat /proc/meminfo', shell = True)print hostnameprint '--------------------------------------------------------------\n\n'print 'CPU Information'print cpuinfoprint '--------------------------------------------------------------\n\n'print 'Memory Information'print meminfoprint '\n\n\n\n'참고 자료https://aws.amazon.com/ko/lambda/details/#데이블 #개발 #개발자 #인사이트 #꿀팁 #AWS #조언
조회수 1549

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

 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 개발팀의 문화에 녹아들어 가장 효율적으로 일할 수 있는 방법이 되었습니다. 개발팀을 꾸려나가면서 여러가지 시행 착오를 겪어 왔지만, 시행 착오에 대한 반성과 여러가지 개선 시도를 통해 계속해서 더 좋은 방법을 찾아나가며 지금과 같은 개발 문화가 만들어졌습니다. 그동안 그래 왔듯이 앞으로 더 많은 개선을 통해 꾸준히 좋은 방법을 찾아 나갈 것입니다.네 그렇습니다. 결론은 저희와 함께 고민하면서 더 좋은 개발문화를 만들어나갈 개발자를 구하고 있다는 것입니다.
조회수 2058

출시의 기록 - #1 랜딩페이지

이 글은 "친구끼리 쓰는 라이브 스트리밍 앱, 라이비오(LIVEO)"의 앱 출시 과정을 담는 글입니다. 어디까지나 현재 겪고 있는 과정을 기록하는 것으로, 최선의 방법이 아닐 수도 있으니 더 좋은 방법이 있다면 언제든지 소개 부탁드립니다.앱을 출시하게 되면서 가장 먼저 준비하게 되는 것 중에 하나. 웹사이트이다.지난 사업인 위제너레이션이나 오드리씨 모두 웹 사이트 자체가 중심이 되는 사업이었기에, 팀 내에 웹 개발자가 있었고 직접 사이트 제작을 건드려야 할 일은 따로 없었다.그러나 라이비오라는 앱 서비스를 준비하게 되면서, 팀 내 개발자들은 앱 서비스 개발에 바쁘고 웹 사이트는 기본적인 소개의 역할만 담당하면 되기 때문에, 직접 사이트를 만들게 되었다.이렇게 가장 기본적인 소개의 역할만을 담당하는 한 페이지짜리 웹 사이트를Promotional Landing Page, 혹은 랜딩 페이지라고 줄여서 부른다.우리는 총 세 가지 과정을 거쳐 웹 사이트를 만들어왔는데, 순서대로 아래와 같다.[1] 시중에 떠도는 HTML5 템플릿을 활용해 앱 개발자분께 부탁하여 간단하게 직접 만들었다[2] IMXPRS 라는 서비스를 이용하여 직접 만들었다[3] Instapage 라는 서비스를 이용하여 직접 만들었다결론만 말하자면 IMXPRS 는 내가 어떻게 알았는지 모르지만 완전 비추인 서비스이다.직접 만드는 것도 돈은 들지 않지만 그 때 그 때 커스텀이 안되기 때문에 불편하다.알아본 결과 랜딩페이지 제작으로는 주로 wix(바로가기) 나 Instapage(바로가기)를 추천하는데, 두 서비스가 유사하지만 개인적으로 Instapage 의 디자인이 더 마음에 들어서 선택하게 되었다.*wix의 경우 한글 버전이 있고, 이후 결제를 붙이는 것이 좀 더 용이하다고 알고있다.각각의 템플릿과 기능을 보고 적절한 것으로 선택하면 될 것이다.Instapage 사용 경험의 경우 개인적으로 10점 만점에 9.5점을 줄 정도로 아주 높다.당연히 직접 개발하는 것 만큼이야 커스텀이 안되겠지만, 매우 쉽게, 꽤 높은 수준으로 커스텀이 가능하다.예를 들어, 애초에 사용한 템플릿은 위의 템플릿이었는데, 아래와 같이 커스텀했다                                                  애초의 템플릿                                                   최종 결과물거의 다른 모습임을 알 수 있는데 그만큼 커스텀이 정말 쉽다는 뜻이다.- 기본적인 디자인은 모두 템플릿에서 제공하며- 핵심이 되는 Headline 및 본문 글꼴을 수정할 수 있고- 원하는 이미지 등을 손쉽게 원하는 위치에 삽입하고, 요소를 원하는 위치에 원하는 크기로 넣는다- 배경 사진 또한 유료 사진을 즉석에서 보고 어울리는 것을 쉽게 결제할 수 있다- 모바일 페이지도 자동 생성되며 별도로 변경할 수 있다(!)이러한 기능들 덕택에 개발자나 디자이너가 아니더라도, 30분~1시간만에 어느 정도 수준의 랜딩페이지를 손쉽게 완성할 수 있다.가장 마음에 들었던 부분은 외부 서비스와의 연계인데, 특히 이메일 주소를 받는 등의 추가기능이 필요한 경우 Integration 탭에서 정말 쉽게 넣을 수 있다. (라이비오의 경우 현재 이메일 주소를 받는 부분은 Mailchimp 라는 타 서비스와 연결되어있다.)                        Edit > Integration 탭에 가면 볼 수 있는 수많은 서비스들향후에는 좀 더 공식 사이트스러운 것들이 필요하겠지만, 초반 몇 달간 사용하기에 손색이 없는 서비스라고 생각한다. 일정 기간동안 무료로 제공되며, 향후 이용료를 낸다. (위의 사이트 수준이면 월 $29 정도)완성된 홈페이지: http://liveo.me랜딩 페이지는 이 정도로 하고, 이후 스마트 앱 배너를 추가할 계획이다.모바일로 랜딩페이지에 접속하면 앱 설치로 유도하는 배너이다.이 부분은 SDK 연동 등도 필요해서 개발자분들의 바쁨이 조금 잦아들면 출시 직전이나 직후에 넣으려고 한다. 관련 서비스는 branch.io 등이 있다.                                Smart App Banner 사례: 맨 위에 저거...사실 처음에는 랜딩 페이지(Promotional Landing Page)니, 스마트 앱 배너(Smart App Banner)니 하는 용어 자체를 몰라서 관련 서비스를 찾기가 어려웠다. 하지만 일단 용어를 알고나니 관련하여 이용할만한 좋은 서비스들이 많았다.혹시 앱 출시를 처음 해 보는 팀이 있다면 앱 출시 마케팅 자체에 대한 조사를 먼저 하고 큰 그림을 그려둔 후 가지를 쳐가며 준비하기를 추천한다. 개인적으로 어떤 부분을 모르는지, 어떤 부분을 알아야 할지를 알 수 있어 훨씬 수월했던 것 같다.하나 하나 완성된 모습으로 채워가는 과정이 왠지 괴롭고도(?) 재미있다.앞으로 소셜미디어와 프레스킷을 만들어가는 과정도 담아보기로 한다.+ 여담: 배경색 선정은 페이스북 '포토샵 완전정복' 디자이너 그룹의 힘을 빌었다.  투표의 힘!정말 많은 분들이 투표에 참여해주셨고 그 중 아는 언니가 준 의견 덕분에 지금의 검은 색상 옵션을 추가하게 되었다.사실 내가 처음 밀었던 색상은 아래의 보라색이었고 우리 팀도 대표님 제외하고 모두 보라색을 택했다 ㅋㅋㅋ 그러나 디자이너들의 의견은 가차없이,검은색 > 민트색 > 보라색 이었다.역시 기술만 있는 나에게 디자이너의 안목을 기르기란 끝없는 과제이다.이 글은 "친구끼리 쓰는 라이브 스트리밍 앱, 라이비오(LIVEO)"의 앱 출시 과정을 담는 글입니다. 어디까지나 현재 겪고 있는 과정을 기록하는 것으로, 최선의 방법이 아닐 수도 있으니 더 좋은 방법이 있다면 언제든지 소개 부탁드립니다.#라이비오 #경험공유 #출시 #업무프로세스 #인사이트
조회수 1138

개발자의 경력관리란?

경력이 아닌 업력이 되는 단계에 이르러야 가능한 것 아닌가 합니다.대부분의 경력은 '어느 회사의 누구'라는 표현에서 만들어진 것이 아닙니다.진정한 경력의 결과는 '자신의 이름'이 곧 브랜드화 되는 것입니다.매우 당연하게,하루 이틀, 한 두해 한다고 해서 얻어지는 것이 아닙니다."10년 경력!"10년 이상 한 분야나 하나의 도메인, 하나의 테크, 하나의 경력, 하나의 경험을 꾸준하게 파고들었을 때에 얻어지고, 그러는 경험속에서 인사이트, 통찰력이 생기게 됩니다.물론. 그래서, 20대에도 명성을 얻을 수 있는 '경력관리'가 가능하다고 이야기합니다.(실제 얻은 사람을 많이 봤습니다. 그들은 10대에 시작했죠. )회사의 테두리 내에서 얻을 수 있는 '경력'은 '경험'일뿐입니다.자신의 이름을 중심으로 기술할 수 있을 때에 '경력'이라고 이야기할 수 있습니다.개발자라면...글을 써서도 얻을 수 있고,강연을 해서도 얻을 수 있고,GitHub에 오픈소스를 공개하면서도 얻을 수 있습니다.현재 30대와 그 이전의 개발자라면...10대와 20대도 똑같습니다.40대, 50대 이후를 준비하세요.반복적인 일, 똑같은 일, 회사의 프로세스의 하나인 일만 하는 '사람'이라면...그냥, 그 회사의 톱니바퀴가 되는 것입니다.대부분 '경력관리'가 잘 안됩니다.앞으로 50대 이후에도 '브랜드'를 얻을 사람이 되려면...자신의 '경력'관리를 잘 해야 얻을 수 있습니다.나중에 닭 튀기거나 치킨 배달할 것이 아니라면...관리를 잘해야 합니다.경력관리가 가능하려면 어떤 회사를 찾아야 할까요.다음을 기억하세요.1. 구루급 개발자가 있는 회사를 찾으세요.2. 자신이 주도적으로 무언가를 만들 수 있는 권한과 책임을 줄 수 있는 회사를 찾으세요.3. 커뮤니티나 외부 강연, 외부 오픈소스 개발 행사에 적극 참여할 수 있는 기회를 주는 회사를 찾으세요.4. 반복적인 업무와 정체된 마켓에서만 반복적으로 서비스를 하는 회사는 회피하세요.5. 우리 도메인은 원래 이래, 이 일은 원래 이래... 이런 식으로 이야기하는 '상급자'가 있는 회사를 피하세요.6. 쉽게 설명할 수 있도록 준비하고, 리뷰를 할 수 있는 기회와 시간이 주어지는 회사를 찾으세요.그리고, 마지막으로...비전은 누가 주거나 만들어 주지 않습니다.결국, 자기 자신이 찾아야 하는데...이것도, 주변에 이야기가 통하는 '구루급 개발자'가 있어야 그나마 방향성을 찾기 좋습니다.혼자 고민하거나,주변에 비슷한 사람들끼리 고민해봐야 답이 안 나옵니다.꼭, 기억하세요!'구루급 개발자'와 상의하세요.그분들은 실패와 성공, 포기와 단념, 선택과 집중에 대해서 알고 있답니다.퇴근시간이라면..구루급 개발자에게 치맥 한잔 하자고 하세요!
조회수 2759

Good Developer 2 | 커뮤니케이션 잘하는 개발자가 되는 방법

프로그래머와 개발자는 다르다.커뮤니케이션에 대한 이야기를 하기 전에 프로그래머와 개발자의 차이에 대해 명확히 하려 한다. 먼저 프로그래머는 컴퓨터를 이용해서 프로그램을 만들거나 수정하는 일을 하는 사람이다. 프리랜서로 일하면서 외주 프로젝트를 맡거나 학교 과제를 하면서 프로그래밍을 하는 사람들 모두 프로그래머라 할 수 있겠다.반면, 개발자는 회사나 조직에 소속이 돼서 다른 사람들과 함께 일하면서 개발을 사는 사람이다. 즉 어딘가에 소속이 돼서 규칙이나 규율 혹은 그 조직의 원칙을 가지고 일을 한다면 개발자로 볼 수 있는 것이다. 정리해 보자면 모든 개발자는 프로그래머지만 모든 프로그래머는 개발자는 아니다. 프로그래머와 개발자를 굳이 나누어서 말하는 이유는 개발자에게는 커뮤니케이션 능력이 절대적으로 필요하기 때문이다. 이와 관련해 아주 적절한 비유를 소개하려고 한다. 이 비유는 칼럼니스트 임백준 님의 '개발자의 생명은 커뮤니케이션 능력'에서 가져왔다.(이 글도 아주 좋으니 읽어보는 것을 추천)비유를 해보자면 이렇다. 프로그래머나 해커는 강호를 떠돌면서 혼자서 행동하는 무사라고 한다면 개발자는 군대에 소속되어 있는 정규군이다. 칼럼에서는 정확이 이렇게 표현한다.외톨이 무사에게 생명은 칼 솜씨고 정규군의 생명은 규칙과 규율이다.칼 솜씨는 코딩 실력이 되겠고, 규칙과 규율은 다른 사람과의 커뮤니케이션 능력이라 볼 수 있겠다. 이것이 개발자에게 있어 코딩 실력이 중요하지 않다는 것은 아니다. 코딩 실력은 기본이요. 커뮤니케이션 능력도 반드시 필수적이라는 뜻이다. 군대에 속해서 전투를 치르기 위해서는 기본적인 전투능력이 필요하다. 즉, 개발자는 자기가 맡은 프로그래밍 업무를 성공적으로 수행할 수 있는 능력을 가져야 하고 이것 은 기본이다!좋은 개발자가 되기 위한 첫 번째 방법, '소통'많은 시니어 개발자들이나 개발 관련된 직종에서 오래 근무한 사람들이 가장 많이 하는 말 중 하나가 바로 커뮤니케이션에 대한 이야기다.  개발자를 뽑을 때 중요한 것이 커뮤니케이션 능력이라고 한다. 커뮤니케이션이 원활하지 않아 개발 업무에 차질이 생기는 일이 다반사며 원활한 커뮤니케이션은 막혔던 문제를 훨씬 더 빠른 속도로 풀릴 수 있게끔 만든다.그럼 구체적으로 좋은 커뮤니케이션을 하기 위해 어떻게 해야 하는지 알아보자. 한 번쯤 들어봤을 이야기들이긴 하지만 구체적인 실행방안들을 추가해서 실제 기업이나 조직에서 바로 적용할 수 있도록 했다.건설적인 대화를 하라!너무나 당연한 말이지만, 이 말이 얼마나 업무 현장에서 지켜지고 있는지는 의문이다. 먼저 건설적인 대화의 방법들을 살펴보기 전에 어떤 대화들이 건설적인 대화가 아닌지를 살펴보자. 그리고 그것을 어떻게 건설적인 대화로 바꿀 것인지 말할 것이다.(1) 대화가 끝났어도 명확한 합의점이나 결과, action item, 해결책이 나오지 않았다.- > 이 문제는 두 가지 이유에서 비롯된다. 첫 번째는 대화의 목적(대화를 하는 이유)이나 목표(해결하고자 하는 것)가 불문명해서 대화가 어느 방향을 전개되야 하는지 갈피를 못 잡기 때문이다. 그리고 두 번째는 대화가 끝난 후 테스크로 전환하는 일을 하지 않은 것이다.==> 대화의 목적과 목표를 분명히 하라! 이야기를 시작할 때는 목적과 목표를 분명히 하라. '우리 지금 이 문제를 해결하기 위해 이야기하는 거죠?' '이 문제를 어떻게 처리할지에 대해 이야기해 봐요.' 일차원적일 수도 있겠지만 이렇게 직접적으로 이야기하는 것이 원활한 커뮤니케이션을 하는데 더 효과적이다. 목적과 목표를 정하지 않고 이야기를 하게 되면 이야기가 중간에 표류할 공산이 크다.==> 대화가 끝난 후에는 반드시 대화에서 얻어낸 결과물들을 테스크로 전환하고 각자에게 배분하라! 업무적 성격의 대화인 경우 문제 해결에 대한 이야기일 가능성이 크다. 이때 액션 아이템이나 합의점이 도출되지 않았다면 건설적인 대화가 이루어지지 않은 것이다. 업무 관련 일이 아닐 경우, 단순 아이디어 회의일 경우에는 대화하면서 나온 아이디어를 적고 문서화시켜야 한다. 그래야 나중에 '너 그때 이렇게 말했잖아!' 하면서 싸우는 일이 없다. 결론이나 결과가 없는 대화는 나중에 그 문제로 인해 다시 대화하게 될 가능성이 크다. 그리고 그것은 곧 리소스의 낭비다.(2) 논쟁을 하다 삼천포로 빠지고, 논쟁이 논쟁을 위한 논쟁으로 변질된다.-> 대화를 하다 보면 항상 좋게 좋게만 흘러가는 것이 아니다. 또 원활한 커뮤니케이션이 의견 충돌이 없는 소통을 의미하는 것도 아니다. 의견이 충돌하되 그것을 건설적이고 긍정적인 방향으로 풀어내는 것이 커뮤니케이션 능력이다. 이 케이스는 목적과 목표의 설정이 제대로 이루어지지 않아서이기도 하지만 대화를 하는데 있어서 서로가 명확히 해야 할 부분을 하지 않아서이기도 하다.==> 논쟁의 지점을 분명히 하라! 특히, 논쟁 지점이 여러 가지라면 뒤죽박죽 이 얘기 저 얘기 다 하면서 시간 소모를 할 공산이 크다. 건설적인 논쟁을 위해서는 우리가 어떤 포인트 때문에 논쟁을 하는지 서로 동의하는 부분은 무엇이고 동의하지 않는 부분은 무엇인지 명확히 해야 한다. ==> 용어를 분명히 하라! 서로 쓰는 용어의 의미가 달라서 논쟁이 되는 경우도 많다. 같은 문제를 바라봐도 다르게 말할 수 있고, 다른 문제를 이야기하는데 같은 용어를 통해 이야기할 수 있다. 원활한 커뮤니케이션의 기본은 용어 통일, 논의의 통일이다. 같은 수준에서 이야기할 때 비로소 원활한 소통을 할 수 있다.커뮤니케이션에 있어서 핵심은 '당신'이다.물론, 커뮤니케이션은 쌍방의 문제다. 내가 문제일수도 있고 상대방이 문제일 수도 있다. 하지만, 원활한 커뮤니케이션에 있어서 상대방을 바꾸는 것은 매우 어렵지만, 나를 바꾸는 것은 상대방을 바꾸는 것보다는 수월하다. 그리고 진정으로 커뮤니케이션을 잘하는 사람은 커뮤니케이션을 못하는 사람과도 '잘' 하는 사람이다. 커뮤니케이션을 잘하는 개발자로 인정받고 싶다면 그 누구와도 잘 할 준비가 되어 있어야 한다.그럼 어떻게 바뀌어야 커뮤니케이션을 잘 할 수 있게 되는지 세 가지 조건을 통해서 알아보자.(1) 자신과 상대방의 커뮤니케이션 스타일을 파악한다.서로 누구의 잘못이라기보다는 방식의 차이 때문에 싸우는 경우가 다반사다. 말투, 어투, 말하는 방식, 시기 등 자신의 스타일을 모르고 상대방의 스타일을 이해하지 못할 때 커뮤니케이션은 막혀버린다. 가장 좋은 것은 글로 적어보는 것이다. 나는 이렇고 상대방은 이렇다. 직접적으로 적어본다면 보다 커뮤니케이션 스타일을 이해하기 쉬워진다. 그리고 커뮤니케이션 스타일을 이해하는 것만으로도 커뮤니케이션을 할 때 많은 도움이 된다.(2) 상대방이 당신에게 망설임 없이 커뮤니케이션할 수 있게 하라!어떤 사람과는 커뮤니케이션 시작 자체를 하기가 어려운 사람들이 있다. 바쁘거나 시작하면 논의가 이루어지지 않거나 많은 조건들이 있을 것이다. 특히, 이 부분에 대해서는 스스로를 돌아보기가 매우 힘들다. 이때는 딱 두 가지의 것을 확인하면 된다.첫 번째로는 주변에 커뮤니케이션하기 망설여지는 상대를 찾아보라. 그리고 그 사람과는 왜 커뮤니케이션이 망설여지는지 생각해 보고 나를 돌아보면 된다. 타산지석(他山之石)이라 했던가. 혹시 내가 커뮤니케이션이 망설여지는 사람이 아닌지 다른 사람을 통해 되돌아보자.두 번째로는 다른 사람에게 솔직하게 물어보는 것이다. 이 방법이 사실 제일 중요하다. 내가 커뮤니케이션에 있어서 부족한 점은 없는지 상대방에게 물어보는 것이 가장 효과적인 방법이다. 물론, 솔직한 말을 듣는 것이 처음에는 두렵고 상처가 될 수도 있다. 하지만, 이것은 당신을 가장 성장시켜줄 대화 중 하나다. 동료만큼 당신과 커뮤니케이션을 많이 하는 사람도 없을 테니 바로 옆자리의 동료에게 자신의 커뮤니케이션에 있어서 부족한 점을 솔직히 말해달라고 부탁하라!(3) 동료와 친밀한 관계를 형성하고 공감하는 것은 중요하다.여기 회사 동료와 친할수록 일의 효율이 올라간다는 연구결과가 있다. 커뮤니케이션의 기본은 열린 마음이다. 그리고 마음은 상대방에게 호의가 있을 때 더 쉽게 열린다. 좋은 커뮤니케이션을 위해서라면 사전에 좋은 관계를 형성하는 것도 중요하다. 좋은 관계와 좋은 커뮤니케이션은 서로 밀접한 상관관계가 있다.대화가 커뮤니케이션의 전부가 아니다.대화만으로 모든 커뮤니케이션을 할 수는 없다. 효율적이지도 않고 물리적으로 불가능한 상황이 있을 수도 있다. 원활한 커뮤니케이션을 위해서라면 적절한 도구의 사용이 필요하다. 즉, 협업 툴을 효과적으로 사용하여 자신이 하고 있는 일들을 상대방에게 알려주고 상대방의 업무를 파악하려고 노력하라!도구의 사용은 커뮤니케이션에 사용하는 비용을 엄청나게 절감해 준다. 자신이 커뮤니케이션에 자신이 없고 언변이 부족하다 생각한다면 도구를 잘 쓰는 방식으로 커뮤니케이션 능력을 향상시킬 수 있다. 지금까지 위에서 언급한 것들은 쉽게 바뀔 수 있는 것들이 아니다. 왜냐하면 지금까지 몸에 체화된 자신만의 대화 방식을 바꾸는 것이기 때문이다. 하지만 커뮤니케이션 도구의 사용은 프로그램이다. 프로그램은 사용법을 배우면 된다.예를 들어, ASANA라는 협업 툴로 자신과 동료의 업무를 리스트화하고 체크할 수 있다. 또는, 구글 캘린더에 자신의 스케줄을 올려서 일정을 공유할 수 있다. 협업 툴을 이용하면 일의 진행사항들을 쉽게 공유하고 상대방의 일정을 파악할 수 있다. 그리고 이런 정보의 공유는 원활한 커뮤니케이션의 기본이다. 이런 도구들을 통해 커뮤니케이션이 부족한 사람들도 충분히 좋은 '커뮤니케이터'가 될 수 있다.커뮤니케이션도 실력이다.다시 처음으로 돌아가 커뮤니케이션의 필요성에 대해 다시 강조하려고 한다. 어떤 사람은 개발자의 핵심은 개발 능력이고 커뮤니케이션은 잘하면 좋은 것이라 생각한다. 위에서도 언급했지만, 개발자는 떠돌이 무사나 용병이 아니다. 조직에 소속되어 있는 개발자라면 소통하고 커뮤니케이션을 하는 능력이 핵심이다.그래서 개발자가 되려는 사람들에 항상 하는 말 중 하나가 다른 사람과 함께한 협업 프로젝트를 해보라는 것이다. 함께 프로젝트를 하는 경험은 프로그래밍 능력을 향상시킬 뿐만 아니라 어떻게 함께 개발하는지에 대해 많은 고민을 할 수 있게 해준다. 단순히 프로그래머가 되려면 코딩 실력에만 집중하라! 그러나, 다른 사람들과 함께 개발을 하는 개발자를 지향한다면 반드시 커뮤니케이션 역량도 향상시켜라!Good Developer 두 번째는 커뮤니케이션에 대해서 다루었다. 다음 Good Developer 는 나쁜 개발자에 대해서 알아볼 것이다.

기업문화 엿볼 때, 더팀스

로그인

/