스토리 홈

인터뷰

피드

뉴스

조회수 1873

더 빠른 Android App Build

Android App Build의 변화Android App 개발에서 빌드는 올해 중순을 기점으로 큰 변화를 가져왔습니다.Ant 에서 Gradle 로… Eclipse 에서 Android Studio 로…Android Studio 는 JetBrains 사의 IntelliJ 의 Community 버전을 커스터마이징한 것입니다.Gradle 은 Ant 의 빌드 기능 에 Maven 의 의존성 관리 기능이 접목된 빌드 툴입니다. 그만큼 제공하는 기능이 다양하며 동시에 의존성에 대한 문제도 함께 해결이 되었습니다.큰 변화는 장점과 단점 모두를 가져왔습니다. 대표적인 장점은 기존에 Eclipse 에서는 한계가 있었던 Plugin 기능이 더욱더 다양해졌다는 것입니다. 반면 갑작스럽게 바뀐 IDE 와 빌드툴은 여전히 큰 장벽으로 존재하고 있습니다.특히 Gradle 의 성능 문제는 줄곧 거론되었습니다. Eclipse 에서는 빠르게 빌드되던 것이 Gradle 기반으로 전환되면서 적게는 2배에서 5배 이상 오래 소요되는 문제를 가져오게 되었습니다.그러한 문제는 토스랩의 안드로이드 팀도 빗겨갈순 없었습니다.코딩-빌드-실행이라는 반복적인 패턴에서 빌드에 소요되는 시간이 개발의 흐름을 끊게 되는 상황에서 이를 개선하는 것은 필수적인 요소였습니다.이 포스팅은 그동안 잔디의 안드로이드 팀이 빌드 속도를 개선하기 위해 노력했던 흔적들의 모음입니다.New Android App Build System1. Bazel (Google)본디 Android 만을 위한 빌드는 아니고 iOS 까지 빌드 할 수 있는 통합 빌드 시스템이라고 보시면 됩니다. Google 의 빌드 시스템인 Blaze 에서 파생된 빌드 프로젝트로 현재 베타로 등록, 진행되고 있습니다.2. Buck (Facebook)Bazel 보다는 좀 더 다양한 언어를 지원하기 위한 프로젝트로 보여집니다. 실제로 Go, Rust 등 다양한 언어를 지원하는 빌드 툴이라고 생각하시면 됩니다.3. Pants (Twitter, FourSquare, Square)3개의 회사가 협동해서 만든 빌드 툴입니다.특이점은 Bazel 만 Mobile Platform 을 위해 개량된 빌드 툴이고 2개는 좀 더 다양한 빌드 환경을 제공한다는 것입니다.Build 시스템의 성능들1. Bazel| —-| 출처 : Bazel(http://bazel.io/docs/mobile-install.html)|구글의 자료에 의하면 기존에 비해 4배~10배 의 성능 향상이 있다고 합니다.2. Buck|**Gradle**|**Buck**| | ----|----|----|----| clean build|31s|6s|5x| incremental build|13s|1.7s|7.5x| no-op build|3s|0.2s|15x| clean install|7.2s|7.2s|1x| incremental install|7.2s|1.5s|4.8x| 출처: Buck (https://buckbuild.com/article/exopackage.html)Gradle 과 비교Gradle 팀에서는 Bazel 에 대해서 2015년 3월 포스팅에 아래와 같이 평하였습니다.Gradle 팀이 꼽은 Bazel 의 단점Bazel 은 구글의 특화 되어 있으며 쉽게 빌드 할 수 있을만큼 고수준 상태가 아니다확장성이 떨어진다.성능은 의존성이 해결된 이후의 문제이다.*nix 환경(Mac, 유닉스, 리눅스를 지칭)에서만 가능하다. 아직 많은 엔터프라이즈 툴들이 .Net 기반이다.(51%)플러그인을 위한 생태계가 구성되어 있지 않다.결론각각의 빌드 시스템들이 제공해주는 정보에 따르면 새로운 빌드 시스템은 큰 차이를 보여주는 빌드 환경을 제공해줍니다. 하지만 그런 이점에도 불구하고 잘 알려지지 않은 이유는 설정에 큰 어려움이 있기 때문입니다. Gradle 과 Android Plugin 에서 제공해주던 것을 직접 스크립트로 작성을 해야하며 각각의 의존성에 대해서도 직접적으로 명시를 해줘야 하기 때문에 정교하고 어려운 작업입니다. 또한 개별적으로 Plugin 을 제공하지 않아 Crash Report 를 위한 툴이나 Build 과정에서 추가적인 작업들이 필요한 경우에도 별도의 작업을 필요로 합니다.이러한 어려움에 기존의 Gradle 에서 새로운 빌드 환경으로의 전환은 쉽지 않으며 끊임없는 도전이 될 것입니다.그래서 잔디의 안드로이드 팀이 선택한 것은 Gradle 에서 성능 극대화 하기 입니다.Gradle 의 성능 개선하기1. Gradle 의 최신화$> vi $project/gradle/wrapper/gradle-wrapper.properties distributionUrl=https\://services.gradle.org/distributions/gradle-2.9-all.zip2. Android Gradle Plugin 최신화buildscrpt { dependencies { classpath 'com.android.tools.build:gradle:1.5.0' } }3. 최소 지원 기기 설정하기android { productFlavors { dev { minSdkVersion 21 } prod { minSdkVersion 14 } } }minSdkVersion 을 LOLLIPOP 으로 설정하게 되면 Build 하는 과정에서 큰 부분이 생략이 되고 특히 MultiDex 를 설정한 프로젝트에서 더 큰 효과를 보실 수 있습니다. Android 는 컴파일 및 패키징과정에서 Class to Dex 와 Merge Dex 을 거치게 됩니다. 이때 하지만 LOLLIPOP 부터는 art 기반이기때문에 Merge Dex 과정이 생략되기에 빌드 성능이 크게 개선됩니다. 단, API 21을 바라보기때문에 lint 나 개발 과정에서 API 특화 대응이 되질 않을 수 있습니다. 유의해서 API 를 사용해주세요.4. Gradle 속성 추가$> vi $project/gradle.properties org.gradle.daemon=true org.gradle.parallel=true org.gradle.jvmargs=-Xmx768m5. DexOption 추가android { dexOptions { incremental true } }※incremental 은 잠재적 오류가 있을 수 있으니 조심해서 사용하라고 합니다. (참고링크)빌드 성능 비교빌드 환경 : MacBook Pro Retina 2012 (i7 2.3Ghz, 8GB Ram)|**변경 전**|**변경 후**| | ----|----|----|----| SingleDex clean build|57s|47s|1.2x| SingleDex incremental build|16.3s|9.6s|1.7x| MultiDex clean build|71s|71s|1x| MultiDex incremental build|48s|17.6s|2.7x| Incremental Build 를 보면 Single Dex, Multi Dex 모두에서 주목할만큼 성능 향상이 있습니다. 개발 과정에서는 Incremental Build 가 대다수의 빌드임을 감안한다면 Gradle 옵션을 수정이 개발 과정에서도 충분히 좋은 성능을 얻을 수 있음을 알 수 있습니다.코딩-빌드-실행을 반복해야하는 패턴에서 최대한 코딩과 테스트에 집중할 수 있는 환경을 만들기 위해 했던 많은 시도들이 다른 안드로이드 개발자분들에게 큰 도움이 되었으면 합니다.#토스랩 #잔디 #JANDI #개발 #개발자 #개발팀 #모바일 #안드로이드 #Android #꿀팁
조회수 1169

AWS CodeCommit. 배포 자동화 환경 만들기(브랜치별 Pipeline 구성)

편집자 주: 함께 보면 좋아요!애플리케이션 개발부터 배포까지, AWS CodeStarCodeStar + Lambda + SAM으로 테스트 환경 구축하기AWS Lambda + API Gateway로 API 만들어보자목차1. CodeStar 프로젝트 생성2. 템플릿 선택3. 프로젝트 정보 입력4. 프로젝트 생성 및 자동 배포 확인5. CodeCommit 접속6. staging 브랜치 생성7. index.py 수정 및 Commit8. 람다 실행 권한 변경9. 스택 생성 및 템플릿 소스 복사10. 템플릿 소스 붙여넣기 및 S3 버킷 URL 생성11. staging 브랜치용 CloudFormation 스택 생성(1)12. staging 브랜치용 CloudFormation 스택 생성(2)13. 파이프라인 설정14. AWS CodeCommit 연결15. CodeBuild16. CodeDeploy17. staging 브랜치용 파이프라인 생성 및 자동 릴리즈18. 작업 그룹 추가19. 파이프라인 실행 및 배포20. API Gateway 접속 및 엔드포인트 확인21. index.py 배포 확인OverviewAWS는 유용한 서비스를 많이 제공하지만, 이것들을 조합하고 사용하는 건 꽤나 번거롭습니다. CodeStar는 이런 고충을 해결해주고자 등장한 서비스입니다. 버전 관리(CodeCommit)부터 빌드(CodeBuild)와 배포(CodeDeploy), 모니터링(CloudWatch)까지 한 번에 프로젝트를 구성해줍니다. 여기서 한 발 더 나아가 브랜치(master, staging)마다 자동으로 빌드, 배포되도록 구성했습니다. 이 포스팅에서는 AWS CodeCommit과 AWS Lambda(Python)을 사용했습니다. 물론 다른 스택을 사용해도 괜찮습니다.Practice1.CodeStar 프로젝트를 생성하겠습니다. CodeStar로 접속해 프로젝트를 생성합니다. CodeStar를 처음 사용한다면 서비스 역할을 생성하라는 창부터 나옵니다. 역할을 생성하고 진행합니다.2.왼쪽 필터에서 웹 서비스, Python, AWS Lambda를 클릭하고 프로젝트 템플릿을 선택합니다.3.프로젝트 정보를 입력하고 AWS CodeCommit을 선택, 프로젝트를 생성합니다. 코드편집 도구설정은 건너뜁니다. 나중에 다시 설정할 수 있습니다.4.조금 기다리면 프로젝트가 생성됩니다. 오른쪽 아래의 엔드포인트로 접속하면 자동으로 생성되는 예제 프로젝트가 잘 배포된 것을 볼 수 있습니다. 클릭 몇 번으로 자동 빌드, 배포에 모니터링까지 가능한 프로젝트가 구성되었으니 이제 staging 브랜치를 생성하여 똑같이 구성하겠습니다.5.먼저 브랜치를 생성하겠습니다. CodeCommit에 접속해 왼쪽의 브랜치 메뉴를 클릭하면 아래와 같이 master 브랜치가 생성된 것을 볼 수 있습니다.6.브랜치 생성을 클릭해 브랜치 이름은 staging, 다음으로부터의 브랜치는 master를 선택합니다.7.생성된 staging 브랜치를 클릭하면 파일 리스트가 보입니다. master 브랜치와 결과 페이지를 구별하기 위해 index.py 파일을 임의로 수정하겠습니다. index.py > 편집을 클릭해 output 문자열을 수정하고 Commit합니다.8.CodeStar는 CloudFormation 서비스로 인프라 리소스를 관리합니다. CloudFormation은 ‘스택’이라는 개념을 사용해 설정을 구성하고 있습니다. 지금은 master 브랜치의 template.yml 파일을 사용해 master 브랜치용 스택이 생성되어 있는 상태입니다.문제는 여기에 기본적으로 람다(lambda) 실행 역할이 구성되어 있는데, 이 역할의 리소스 접근 권한은 master 브랜치 람다로 한정되어 있다는 것입니다.1)이 글에서는 staging용 람다 실행 권한을 별도로 생성하는 방법으로 문제를 해결했습니다. staging 브랜치의 template.yml 파일을 열어 Resources: LambdaExecutionRole: Properties: RoleName을 임의의 값으로 수정합니다. 저는 뒤에 ‘-staging’을 붙였습니다.9.CloudFormation 스택도 따로 생성합니다. AWS CloudFormation에 접속하면 기본적으로 생성된 스택을 볼 수 있습니다. 기존의 스택 템플릿에서 조금만 수정해 스택을 생성하면 되니 템플릿을 복사해오겠습니다.awscodestar-testproject-lambda를 클릭해 오른쪽의 ‘Designer에서 템플릿 보기/편집’을 클릭하면 템플릿 소스를 볼 수 있습니다. 가장 아래의 템플릿 탭이 클릭되어 있는지 확인하고 그대로 복사합니다.10.다시 CloudFormation으로 돌아와 템플릿 디자인 버튼을 클릭하고 복사한 소스를 붙여 넣습니다. 여기서 마찬가지로 Resources: LambdaExecutionRole: Properties: RoleName을 조금 전의 이름과 같게 수정하고 저장합니다. 템플릿 언어를 YAML로 바꾸고 수정하면 보기 편합니다.Amazon S3 버킷에 저장하면 템플릿 파일이 S3 버킷에 저장되며 S3 버킷 URL이 생성됩니다. 잘 복사해둡니다. 템플릿 디자이너는 이제 닫아도 됩니다11.CloudFormation 창에서 스택 생성을 클릭해 Amazon S3 템플릿 URL에 복사한 URL을 입력합니다. 이후의 내용은 스택 이름만 다르게 하고, 나머지는 기본적으로 생성된 스택 정보와 동일하게 입력합니다. 기존에 생성한 스택 정보는 스택 상세 페이지 오른쪽의 스택 업데이트를 클릭하면 볼 수 있습니다.생성 페이지 마지막의 ‘AWS CloudFormation에서 사용자 지정 이름을 갖는 IAM 리소스를 생성할 수 있음을 승인합니다’를 체크하고 생성을 클릭합니다.12.staging 브랜치용 CloudFormation 스택이 생성되었습니다. 이 스택을 사용해 staging 브랜치용 파이프라인을 생성하겠습니다.13.CodePipeline으로 접속해 파이프라인 생성을 클릭하면 설정창으로 이동하는데, 아래 이미지와 같이 입력합니다.CodeStar프로젝트가 생성되며 IAM 역할과 S3 버킷이 자동 생성되는데, 동일한 역할과 버킷으로 설정하면 됩니다. 파이프라인 이름만 임의로 다르게 넣어줍니다.14.AWS CodeCommit을 연결해야 합니다. 아래와 같이 자동 생성된 리포지토리를 선택하고 미리 생성한 staging 브랜치를 연결합니다.15.CodeBuild를 알아보겠습니다. 기본 파이프라인에서 자동 생성된 프로젝트를 선택하고 다음을 클릭합니다.16.새 창을 열어 기존에 생성된 파이프라인 상세 페이지로 접속합니다. 편집을 클릭하고 Deploy 스테이지 편집을 클릭, GenerateChangeSet 편집 버튼을 클릭하면 설정값이 보입니다. 이 값을 참고해 다음 스텝을 아래와 같이 진행하면 됩니다.앞서 생성했던 staging 브랜치 파이프라인용 스택을 연결하고, 세트 이름을 임의로 다르게 넣습니다. ‘템플릿’과 ‘템플릿 구성 - 선택 사항’ 설정값도 다르니 주의합니다.17.다음으로 진행하면 staging 브랜치용 파이프라인이 생성되어 자동으로 릴리즈되고 있는 것을 볼 수 있습니다.18.여기서 master 파이프라인과 동일하게 Deploy 스테이지의 GenerateChangeSet 아래에 작업 그룹을 하나 추가해야 합니다. 마찬가지로 master 파이프라인을 참고해 작성힙니다. 작업이름, 새로 생성한 스택, staging용으로 임의 작성했던 세트 이름을 넣습니다.19.저장 후, 변경사항 릴리스를 클릭하면 파이프라인이 실행됩니다. 잠시 기다리면 완료와 함께 배포작업까지 이뤄집니다.20.모든 작업이 끝났습니다! 제대로 구성되었는지 엔드포인트로 접속해 확인해보겠습니다. AWS API Gateway로 접속해 staging 브랜치용 API Gateway를 클릭합니다.21.왼쪽의 스테이지 메뉴를 클릭하면 엔드포인트 URL을 볼 수 있습니다. 이 URL로 접속하면 위에서 편집한 staging 브랜치의 index.py가 배포된 것을 볼 수 있습니다. master 브랜치의 엔드포인트로도 접속해서 비교해보세요.ConclusionAWS의 서비스들은 강력하고 다양합니다. 그 수가 많아져 이제는 전부 다루기는커녕 나열하기도 어려울 정도입니다. 아마존에서도 이런 고충을 알기 때문에 여러 서비스를 묶어 간편하게 세팅하는 CodeStar를 제공하는 게 아닌가 싶습니다. 수가 많은 만큼 각각의 서비스를 정확히 이해하고 적절히 이용해 오버엔지니어링을 피하는 게 중요하겠습니다.참고1) IAM - 역할 - Permission boundary에서 확인 가능합니다글양정훈 사원 | R&D 개발3팀[email protected]브랜디, 오직 예쁜 옷만
조회수 6143

[SQL 데이터분석] 증감율 구하는 간단한 방법

sql에서는 = 등호가 비교연산자로 사용됩니다.대신 := 이렇게 콜론(:)과 등호(=)를 같이 쓰면 대입연산자로 쓸 수 있어요.select @prev := users.id // @prev 라는 임시변수에 users.id 값을 넣어라. from users가입일자로 사용자수를 구해보면, 아래처럼 가입일로 group_by 를 해서 구하죠.select date(created_at) as '가입일' , count(1) as '가입자수' from users group by 1 order by 1 desc;// 가입일 | 가입자수 // --------------------------- // 2017-08-02 100 // 2017-08-01 50그럼 전일 대비 증감율을 구하려면 어떻게 할까요?select date(created_at) as '가입일' , @prev as '전일 가입자수' , (count(1) - @prev) / @prev as '증감율' , @prev := count(1) as '가입자수' from users group by 1 order by 1 desc;// 가입일 | 전일 가입자수 | 증감율 | 가입자수 // -------------------------------------------------------- // 2017-08-02 50 1.0 100 // 2017-08-01 50 0 50증감율을 계산하는 count(1) / @prev까지는 @prev 에 전일 가입자수가 저장되어 있구요.@prev := count(1) 에서 당일 가입자수로 할당이 됩니다.저는 := 이 연산자를 알기 전엔 self-join 형태로 증감율을 구했는데데이터를 가오는 속도는 := 이 연산자가 훨씬 빠른것 같습니다.다음엔 self-join 으로 증감율을 구하는 법도 한 번 올려볼께요.#티엘엑스 #TLX #개발 #개발팀 #개발자 #꿀팁 #인사이트 #조언
조회수 6893

BPM, RPA 그리고 Process Mining(프로세스마이닝)

새로운 IT 기술의 등장과 기업 환경의 변화로 새로운 과학 경영 기법들이 비즈니스 유행어처럼 등장하고 사라지지만 그 가운데서도 변하지 않는 것이 있다면 프로세스 개선과 관련된 대한 끊임없는 노력과 관심일 것입니다.프로세스 마이닝은 이벤트 로그를 기반으로 비즈니스 프로세스를 분석할 수 있는 프로세스 관리 기술입니다. 정보 시스템에서 기록한 이벤트 로그에 포함된 패턴 및 세부 정보를 식별하기 위해 별도의 분석 알고리즘이 이벤트 로그 데이터에 적용됩니다. 프로세스 마이닝은 프로세스의 효율성과 이해를 향상시키는 것을 목표로 하며, “자동화된 비즈니스 프로세스 발견” ABPD (Automated Business Process Discovery)이라는 좀 더 일반화된 명칭으로 불리기도 합니다.이러한 프로세스 마이닝은 어디서 갑자기 나온 개념은 아니고 기존 비즈니스 프로세스 관리 기법에 대한 연구와 데이터 분석 기술이 합쳐져서 나온 산물이기에 “비즈니스 프로세스”와 관련된 기술들을 살펴보고 프로세스 마이닝과의 연관성을 찾아보고자 합니다.BPM (Business Process Management)프로세스 마이닝은 일반적으로 BPM과 데이터 마이닝이 겹치는 중간 영역에 위치합니다.BPM은 비즈니스 프로세스를 발견, 모델링, 분석, 측정, 개선, 최적화 및 자동화하기 위해 다양한 방법을 사용하는 운영 관리 기법을 의미하며, 프로세스를 관리하여 기업 성과를 향상시키는 데 중점을 둡니다. 좁은 의미에서 BPM은 업무 프로세스를 사전에 모델링하고, 설계된 프로세스 대로 업무 결제, 승인, 구매 등의 업무 등이 자동화되어 흘러갈 수 있도록 도와주는 IT 시스템을 지칭하기도 합니다..BPM은 Top-Down 방식으로 프로세스 모델을 그려서, 해당 프로세스 모델 대로 업무를 수행하도록 강제하는 방식이라면 프로세스 마이닝은 이미 수행된 업무로부터 프로세스 모델을 도출하는 Bottom-up 방식을 따릅니다.  하지만 점점 복잡해져 가는 기업 업무 활동을 BPM처럼 중앙 집권적 방식으로 모든 것을 통제하기에는 한계가 있습니다.  BPM의 통제를 벗어난 다양한 여러 시스템을 업무 관점에서 통합적으로 관리하고 모니터링하기 위해서는 개별 시스템은 그대로 두고 이로부터 쏟아져 나오는 로그를 통해 프로세스를 관리하는 분권적 방식이 BPM의 한계를 보완하는 역할을 합니다. RPA (Robot Process Automation)로봇 프로세스 자동화 (RPA)는 소프트웨어 로봇 또는 AI (인공 지능) 작업자의 개념을 기반으로 하는 사무 자동화 기술의 새로운 형태입니다.소프트웨어 '로봇'은 컴퓨터 시스템의 사용자 인터페이스와 상호 작용하는 인간의 행동을 복제하는 소프트웨어 응용 프로그램입니다. 예를 들어, ERP 시스템에 데이터 입력을 실행하거나 실제로 비즈니스 프로세스를 수행하는 것이 소프트웨어 로봇의 일반적인 활동이 될 것입니다. 소프트웨어 로봇은 사람과 동일한 방식으로 사용자 인터페이스(UI)에서 작동합니다. 이것은 기존에 애플리케이션 프로그래밍 인터페이스(API)에 기반한 전통적 형태의 IT 통합과 크게 다릅니다. 즉, 사용자 인터페이스의 데이터 아키텍처 계층을 기반으로 한 기계 간(machine-to-machine) 통신 형태를 취합니다.앞서 언급한 BPM이 프로세스 개선을 위해 프로세스 자체를 재설계하고 변경하려는 방식이라면 RPA는 사람이 하던 현재 방식을 그대로 모방하여 소프트웨어로 대체하여 자동화하는 방식입니다. 이러한 RPA가 업무에 더 많이 적용될 수록 더 많은 시스템 로그가 나올 것이고 이에 대한 성과 분석과 모니터링이 필요해질 것입니다. 프로세스 마이닝은 RPA 도입 전 초기 단계에 전체 프로세스를 분석하여 RPA가 적용될 만한 구간을 식별하여 타당성을 검증하고, RPA 도입 이후의 전후 비교를 통해 지속적으로 업무 효율성을 측정할 수 있는 방법을 제공합니다.앞서 살펴본 것처럼 BPM, RPA, Process Mining 이 세 가지는 서로의 영역을 다투는 것이 아니라 상호 보완적인 존재로 볼 수 있습니다.프로세스 마이닝은 “프로세스”와 관련된 다양한 시스템과 활동들에 대해서 데이터에 근거한 현재 프로세스의 모델링 및 성과 측정 방법을 제공합니다. 이를 통해 과거 혹은 신규 프로세스 혁신 기법들과 맞물려 해당 시스템 및 방법론이 성공적으로 수행될 수 있도록 자동화된 “업무 조언자” 역할을 수행하게 됩니다. [참고 자료]https://en.wikipedia.org/wiki/Business_process_managementhttps://en.wikipedia.org/wiki/Robotic_process_automationhttps://www.minit.io/blog/robotic-process-automation-and-process-mininghttps://medium.com/towards-data-science/unleash-the-value-of-process-mining-4e3b5af4e9d8http://www.cdevworkflow.com/bpm-life-cycle/https://www.uipath.com/blog/the-robotic-process-automation-infographic#퍼즐데이터 #개발팀 #개발자 #개발후기 #인사이트
조회수 1599

코인원코어 엔진, PM과 개발자가 직접 답해드립니다!

‘코인원코어 엔진을 탑재하고 새로운 심장을 품게 된 코인원.’오늘은 차세대 엔진 프로젝트 ‘랩터TF’ 구성원들과 함께 엔진을 탑재하기까지의 비하인드 스토리와 코인원에서 일하는 이유에 대해 들어보려고 합니다.차세대 엔진 프로젝트는 코인원 크루의 치열했던 고민과 협업의 결과물입니다. 짧게 주어진 시간 동안 출산을 경험한 크루, 공휴일을 반납하고 개근상을 탄 크루 등 여러 에피소드를 남기고 무사히 서비스를 오픈할 수 있었습니다. 이 모든 것은 크루들의 헌신과 열정이 모여 이룰 수 있었던 성과였어요.'랩터TF'를 성공적으로 이끈 랩터 5총사. 지금 바로 이들이 만들어낸 성공 스토리를 공개합니다.Q. 안녕하세요, 자기소개와 함께 현재 하고 계신 일을 소개해주세요!요한 : 이번 랩터 프로젝트 PM과 더불어 블록체인셀에서 Cell Owner (이하 ‘CO’)로 이중생활(?) 하고 있는 조요한입니다. 블록체인셀에서는 주로 암호화폐 자산 입출금을 위한 지갑을 개발하고, 코인원에 블록체인 기술을 연구하고 적용하고 있습니다!자현 : QA셀의 CO 겸 Release Manager를 맡은 구자현입니다. (저도 이중생활을 하네요!) QA셀은 SW테스팅을 통해 코인원 서비스의 품질 경쟁력을 확보하는 것을 목표로 하고 있어요. 그리고 서비스 일정에 차질이 없도록, 전사 배포 프로세스와 일정을 관리합니다.지훈 : 모바일셀의 백엔드 개발자로 일하고 있는 김지훈입니다. 백엔드 개발자에 대해 간략하게 말씀드리면, ‘눈에 보이지 않는 부분을 개발한다.’라고 말씀드릴 수 있겠네요. 저는 코인원 모바일 애플리케이션의 백엔드 API 서버를 담당하고 있습니다. 은호 : 트레이딩셀의 백엔드 개발자 이은호입니다. 지훈님이 모바일 쪽이라면, 저는 웹 영역에서 ‘보이지 않는 손’의 역할을 맡고 있습니다. 서버 뒷단의 작업을 통해 코인원 유저가 안정적이며 신속하게 거래를 할 수 있는 환경을 제공하고 있고요. 랩터 프로젝트에서는 주로 매칭엔진 API 개발을 담당했습니다.허민 : 플랫폼셀의 시스템 엔지니어 허민입니다. 코인원을 지탱하는 인프라 플랫폼의 아키텍처 설계부터 구축과 운영까지 통합적으로 담당하고 있습니다. 특히 이번 랩터 프로젝트가 안정적으로 운영될 수 있도록 서비스 구성부터 많은 정성을 기울였습니다.Q. 차세대 엔진 프로젝트에 왜 랩터라는 별칭이 붙게 되었나요?요한 : 새로운 엔진으로 교체한 이후에 유저들이 서비스적으로 크게 체감할 수 있는 부분은 아무래도 속도일 겁니다. 요새 제 첫째아들이 동물도감에 푹 빠져있어요. 동물도감에서는 지구상에서 가장 빠른 동물로 ‘랩터'라는 공룡을 지칭하고 있습니다. 엔진교체로 거래 속도가 빨라지는 것을 가장 잘 표현할 수 있는 단어라 생각되어 이렇게 별명을 붙여보았어요. 자현 : 저도 랩터 별칭 때문에 찾아본 것이 또 하나 있어요. 전투기 중에서도 가장 빠른 기종을 ‘랩터'라고 하더라고요. 랩터 전투기는 신기술의 집합체이며 아주 정밀하게 만들어졌다고 하네요. 새롭게 교체된 엔진을 가장 잘 표현하는 것 같아 TF원으로서 맴이 아주 뿌-듯합니다!Q. 코인원의 새로운 차세대 엔진 ‘코인원코어'에 대한 자세한 설명 부탁드릴게요.요한 : 코인원코어는 초당 300만 건 이상의 거래 체결 처리가 가능한 고성능 엔진입니다. 수백 대의 서버로 수평 확장이 가능한 분산시스템을 갖추고 있어요. 서비스 중단 없이 거래 엔진을 확장할 수 있고, 신규 암호화폐 상장도 가능합니다. 또한 예상치 못한 장애 상황에서도 별도의 점검 없이 실시간으로 대응할 수 있습니다.코인원은 2014년에 출발해 4년이라는 적지 않은 시간 동안 거래소를 운영하면서 발생한 한계점들을 해결할 솔루션이 필요했어요. 이에 코인원의 다년간 거래소 운영 경험과 서버 엔진 전문기업 아이펀팩토리의 대규모 분산처리 기술이 융합된 거래엔진을 탄생시켰습니다.※ 코인원코어에 관한 자세한 설명은 (https://coinonecore.com/)에서 확인할 수 있습니다!▲화기애애하게 회의중(?)인 랩터TF 크루들!Q. 코인원이 새로운 엔진을 장착하기 이전과 이후, 무엇이 달라졌나요?은호 : 먼저, 시스템 확장성 부분에 대해 말씀드릴게요. 이전에는 상장되어 있는 암호화폐의 개수가 늘어날수록 시스템에 많은 부하가 발생했어요. 시스템을 수평 확장할 수 없는 구조적 한계를 지니고 있었죠. 기존 자원을 더 높은 사양의 자원으로 업그레이드하여 시스템의 부하를 해결했었는데, 이는 매우 높은 유지 비용을 요구하고 확장성 측면에서 한계점이 명확했어요.이제는 코인원코어 엔진을 새롭게 탑재하면서 이러한 부분들을 해결했습니다. 무한히 확장할 수 있는 병렬구조의 아키텍처를 구성했고, 더 많은 암호화폐를 상장해도 끄떡없는 코인원이 되었어요.고가용성과 장애 극복 측면에서 보자면, 모든 서버가 이중화 요건을 만족하여 단일 장애점(Single Point of Failure : SPOF)없는 안정적인 아키텍처로 구성되었습니다. 예상치 못한 장애 상황에서도 별도의 점검 없이 실시간 대응이 가능해 더 안정적인 거래소 운영을 할 수 있습니다.요한 : 이어서 성능에 관한 부분입니다. 거래체결량이 이전보다 100배 이상 향상되었습니다. 암호화폐 거래소 운영에 있어 안정적인 서버 운영은 가장 중요한 요소로 꼽히고 있어요. 특히 거래 서버의 경우 단시간에 수많은 요청을 처리해야 하는데, 코인원 코어는 초당 300만 건 이상 체결 처리를 합니다. 이는 증권사 수준 이상의 체결 엔진 성능이라 말씀드릴 수 있습니다.Q. 이번 코인원코어에 새롭게 적용된 기술적 특징이 있다면?허민 : 한국의 ‘Amazon EKS (Kubernetes Management Service)’가 오픈하고 나서, 가장 빠르게 도입한 회사가 코인원일겁니다. 대부분의 작업을 코드화 한 후, GUI 화면에서 반복적으로 작업하느라 속도가 나지 않던 부분들을 개선하게 되었고요. Kubernetes를 구축하면서 대부분의 서비스를 도커 컨테이너로 전환시키고 서비스들을 마이크로화 했습니다. 이제는 각각의 서비스 배포를 분리해서 업데이트 할 때, 다른 서비스에는 영향을 주지 않도록 시스템을 설계했어요. 개발한 서비스를 안정적이면서도 손쉽게 배포할 수 있고, 문제가 발생했을 때는 빠르게 복구가 가능하게 되었답니다.지훈 : 모바일쪽에서는 이번에 랩터 프로젝트를 하게 되면서 기존 베이스 코드를 리팩토링 한 부분이 절반정도 됩니다. 좀 더 효율적으로 프레임워크를 쓸 수 있도록 리팩토링 작업이 많이 들어갔고요. 많은 성능 향상을 기대하고 있어요!은호 : 앞서 요한님께도 말씀해주셨지만, 코인원코어의 가장 큰 특징은 세계적인 증권 거래엔진을 상회하는 체결성능과 이를 뒷받침하는 안정성이라고 생각해요. 백엔드 개발자 입장에서 성능과 안정성이라는 두가지 품질 요건은 대부분의 상황에서 Trade-off 관계에 놓이게 되는 아키텍처 요건이거든요. 한가지 요건을 달성하게 되면 다른 한가지 요건은 어느정도 희생을 감수할 수 밖에 없습니다. 그러나 코인원코어는 두 마리 토끼를 모두 포기하지 않았어요.초당 300만건이상의 주문을 체결할 수 있는 성능을 제공함과 동시에 장애 발생 상황에서도 단 한 건의 주문 누락 없이 서버가 복구되고 대체됩니다. 이 모든 과정이 전략적으로 자동화 되어 고객의 자산을 보다 더 안전하게 지킬 수 있게 되었어요. 코인원과 코인원코어의 뛰어난 기술력으로 이뤄낸 성과라 자부합니다.▲늦은 시간까지 열정적으로 진행되었던 '랩터TF'▲랩터 TF의 파워업을 위한 영양제와 야식 또한 빠질 수 없겠죠? ;)Q. 코인원 크루로 일하시면서 가장 큰 장점은 무엇인가요?요한 : 직무에 상관없이 자유롭게 소통하는 코인원 크루의 모습이 좋습니다. 코인원에서는 PM, 개발자, 디자이너가 모여 데일리 스탠드업 미팅, 회고 등 원활하게 소통하는 문화가 잘 구축되어 있습니다. 일하면서 좋을 때도 있지만 때론 힘든 부분들도 있을 거에요. 이에 대해 코인원 크루는 서로 투명하게 소통하고 피드백을 건네며 함께 성장합니다.지훈 : 코인원 입사 후에 개발 시간을 그래프로 나타내보았어요. 제 고향인 모바일셀보다 랩터 프로젝트에서 보낸 시간이 더 많더라고요. 랩터 프로젝트를 하면서 느낀 것 중, 코인원 크루는 자부심과 일에 임하는 태도가 남다르다는 것입니다. 저 또한 다른 크루분들의 열정적인 모습을 보고 다시 불태우게 되더라고요. 앞으로 코인원에서 새롭고 재미난 개발작업들을 많이 할 것 같아요.은호 : 코인원이라는 공간은 혼자가 아닌 모두가 함께 만들어나가는 공간이라는 것을 느끼고 있어요. 코인원에서 일하면서 함께 도전하고 성취하려는 크루들의 마인드가 무척 좋습니다. 더불어 모두가 거리낌 없이 새로운 기술을 받아들이려고 하는 스타트업 정신을 잘 가지고 있다는 것이 큰 장점이라고 생각해요. 새로운 기술을 이곳저곳 적용해보면서 시행착오를 겪어야 하는 개발자에게 있어서 가장 중요한 부분입니다. 허민 : 코인원은 이전에 몸담았던 다른 산업군의 회사들보다 훨씬 스펙타클한 곳이에요. 저는 그동안 새로움에 대한 갈증이 매우 컸어요. 시스템 엔지니어의 특성상 기존 서비스를 안정적으로 운영하면서 새로운 기술을 도입하는 부분에는 어려움이 많았거든요. 현재는 다양한 인프라 환경과 블록체인 기술에 관해 공부하고 도전해 볼 수 있는 제 모습이 좋습니다. 그리고 코인원의 크루분들도 새로운 기술에 대해 적극적으로 수용하려 하고, 회사 차원에서도 투자도 많이 이뤄져 뿌듯하네요!자현 : 코인원은 책임감으로 똘똘 뭉친 좋은 사람들이 모여있는 곳이에요. 빠듯한 일정 속에 고생하신 분들이 정말 많습니다. 힘들다고 하기 전에 먼저 알고 서로 응원해주는 모습들이 보기 좋아요. 그렇기 때문에 더욱 힘을내서 랩터 프로젝트를 할 수 있었고요. 또한 새로운 기술에 대해 회사 차원에서 끓임 없이 지원 해줍니다. 저 또한 QA 엔지니어로서 새로운 툴들을 찾아보고 활용할 수 있도록 노력하고 있죠! ▲크루 여러분, 정말 고생 많으셨습니다 :-)Q. 앞으로 코인원에서 이루고 싶은 목표가 있다면?요한 : 블록체인셀의 CO로서 좀 더 안정적인 무중단 입출금 플랫폼을 구축하고 운영하고 싶어요. 아직 블록체인과 암호화폐 생태계가 기술적 관점을 요구할 때가 많아, 일반 유저들이 이해하는데 상당히 어려움을 겪고 있습니다. 저는 유저가 쉽고 편리하게 이용할 수 있는 서비스를 만들고 싶습니다. 마지막으로, 유망한 블록체인 프로젝트들을 더 많이 코인원에 상장하고 싶네요!자현 : QA는 SW제품의 품질을 높이기 위해 개발 전 단계에 걸쳐 코인원의 품질을 체계적으로 잡아가는 조직입니다. 테스팅을 통해 결함을 조기 발견하고 제품 품질을 높여 유저가 서비스를 이용하는 데 문제가 없도록 하고 있어요. 현재 코인원 서비스가 놀이터 수준이라면 고도화된 서비스로 유저들이 즐길 수 있는 놀이동산이 되었으면 좋겠습니다. 코인원 놀이동산에 모여 많은 분이 다양한 서비스를 즐길 수 있으면 좋겠네요!지훈 : 제가 코인원에 입사한 지 얼마 되지 않아, 전체적인 개발을 이해하는데 조금은 감이 오지 않았던 때가 있었습니다. 그래서 특히 랩터TF에 감사해요. 하드코어 심화 속성(?) 수업으로 코인원에 대한 모든 것을 숙지할 수 있게 해주었거든요. 이제는 모바일셀의 백엔드 개발자로서 새로운 서비스나 기능을 많이 개발하고 싶어요. (P.S. 모바일 개발에 대한 A to Z까지 크루분들에게 알려드릴 수 있도록 하겠습니다.)은호 : 개발자의 자아실현 실천법 중에 ‘기여’라는 방법이 있습니다. 개발자는 누구나 오픈 소스 커뮤니티의 도움을 받아 개발을 해왔고, 앞으로도 하고 있을 거에요. 저는 제 멘토와도 같은 오픈소스 커뮤니티에 기여하는 것을 소소하게 목표로 삼고 있어요. 오픈소스 프로젝트를 기획하고, 관심있는 프로젝트에 더 큰 기여를 해 제가 받았던 도움들을 보답하고 싶네요. 이러한 기여의 방법은 저의 개발 커리어로서도 명예이고, 제가 속한 조직에 더 큰 선순환을 불러일으킬거에요.허민 : IT업계 중에서 좋은 개발문화가 회자되는 곳으로 넷플릭스와 페이스북을 꼽습니다. 이들의 경우,  좋은 아이디어나 유저의 요구사항을 빠르게 적용해서 서비스에 반영하고 있어요. 이러한 실행속도는 안정적인 플랫폼이 뒷받침되기에 가능하다고 생각합니다. 코인원 또한 지속적으로 플랫폼을 개선해 나갈 생각이고, 이러한 개발문화를 스며들게 하는것이 제 목표라고 할 수 있겠네요.Q. 코인원에 합류할 예비 PM 그리고 개발자분들에게 한 말씀 부탁드려요!요한 : 코인원은 크루들에게 많은 오너십을 부여하고 있어요. 자신이 맡은 Product에 많은 역할과 권한을 갖는 것을 좋아하고 블록체인을 좋아한다면 코인원으로 오세요! 자현 : 책임감이 강한 분이 오셨으면 좋겠어요. 최소한 자신이 구현한 것에 대해서 끝까지 책임질 수 있는, 마지막 실행단계까지 끝까지 확인할 수 있는 분이었으면 좋겠네요. 모두가 편해지는 개발 월드를 위해!지훈 : 아무래도 금융 쪽에 서비스를 하다 보니까 머리가 좋으신 분들이 정말 많이 지원하실 것 같아요! 아, 추가로 테스트코드를 같이 작성하시는 분이 오시면 정말 좋을 것 같네요!은호 : 자신의 결과물에 자부심과 책임감이 있는 크루가 함께했으면 좋겠습니다! (진지,궁서체입니다.) 허민 : 수평적인 협업을 하고 싶으신 분! 같이의 가치를 소중히 여기시는 분! 어려운 문제가 앞에 있어도 즐기면서 넘어갈 수 있는 분들! 창의적이면서도 효율적으로 일하고 싶으시다면 저희와 함께해요!▲수줍게 웃음짓고 계신 랩터TF 인터뷰이들!지금까지 랩터TF 크루들의 이야기를 들어봤습니다.인터뷰 내내 엔진 서비스를 개발했을 때의 열정이 고스란히 전해졌어요. 함께 서비스를 만들고 성장하면서 서로의 신뢰가 더 두터워졌다는 코인원 크루들. 이러한 믿음 안에서 불가능한 일도 가능하게 만든 힘을 엿볼 수 있었습니다.앞으로 코인원은 더 빠르고, 더 안전하고, 더 단단해진 서비스로 여러분들을 찾아뵐 예정입니다. 엔진 프로젝트를 시작점으로 최고의 서비스를 만들어나가는 이들의 모습이 기대됩니다!끝으로, 특별한 개발문화를 경험할 기회! 코인원 채용에 함께하는 것도 잊지 마세요 :-)
조회수 2962

Apache Spark에서 컬럼 기반 저장 포맷 Parquet(파케이) 제대로 활용하기 - VCNC Engineering Blog

VCNC에서는 데이터 분석을 위해 다양한 로그를 수집, 처리하는데 대부분은 JSON 형식의 로그 파일을 그대로 압축하여 저장해두고 Apache Spark으로 처리하고 있었습니다. 이렇게 Raw data를 바로 처리하는 방식은 ETL을 통해 데이터를 전처리하여 두는 방식과 비교하면 데이터 관리비용에서 큰 장점이 있지만, 매번 불필요하게 많은 양의 데이터를 읽어들여 처리해야 하는 아쉬움도 있었습니다.이러한 아쉬움을 해결하기 위해 여러 논의 중 데이터 저장 포맷을 Parquet로 바꿔보면 여러가지 장점이 있겠다는 의견이 나왔고, 마침 Spark에서 Parquet를 잘 지원하기 때문에 저장 포맷 변경 작업을 하게 되었습니다. 결론부터 말하자면 74%의 저장 용량 이득, 10~30배의 처리 성능 이득을 얻었고 성공적인 작업이라고 평가하지만 그 과정은 간단하지만은 않았습니다. 그 과정과 이를 통해 깨달은 점을 이 글을 통해 공유해 봅니다.Parquet(파케이)에 대해Parquet(파케이)는 나무조각을 붙여넣은 마룻바닥이라는 뜻을 가지고 있습니다. 데이터를 나무조각처럼 차곡차곡 정리해서 저장한다는 의도로 지은 이름이 아닐까 생각합니다.Parquet을 구글에서 검색하면 이와 같은 마룻바닥 사진들이 많이 나옵니다.빅데이터 처리는 보통 많은 시간과 비용이 들어가므로 압축률을 높이거나, 데이터를 효율적으로 정리해서 처리하는 데이터의 크기를 1/2 혹은 1/3로 줄일 수 있다면 이는 매우 큰 이득입니다. 데이터를 이렇게 극적으로 줄일 수 있는 아이디어 중 하나가 컬럼 기반 포맷입니다. 컬럼 기반 포맷은 같은 종류의 데이터가 모여있으므로 압축률이 더 높고, 일부 컬럼만 읽어 들일 수 있어 처리량을 줄일 수 있습니다.https://www.slideshare.net/larsgeorge/parquet-data-io-philadelphia-2013Parquet(파케이)는 하둡 생태계의 어느 프로젝트에서나 사용할 수 있는 효율적인 컬럼 기반 스토리지를 표방하고 있습니다. Twitter의 “Julien Le Dem” 와 Impala 프로젝트 Lead였던 Cloudera의 “Nong Li”가 힘을 합쳐 개발한 프로젝트로 현재는 많은 프로젝트에서 Parquet를 지원하고 컬럼 기반 포맷의 업계 표준에 가깝습니다.Parquet를 적용해보니 Apache Spark에서는, 그리고 수많은 하둡 생태계의 프로젝트들에서는 Parquet를 잘 지원합니다.val data = spark.read.parquet("PATH") data.write.parquet("PATH") Spark에서는 이런 식으로 손쉽게 parquet 파일을 읽고, 쓸 수가 있습니다. 데이터를 분석하기 전에 원본이라고 할 수 있는 gzipped text json을 읽어서 Parquet 로 저장해두고 (gzipped json은 S3에서 glacier로 이동시켜버리고), 이후에는 Parquet에서 데이터를 읽어서 처리하는 것 만으로도 저장용량과 I/O 면에서 어느 정도의 이득을 얻을 수 있었습니다. 하지만 테스트 결과 저장용량에서의 이득이 gz 23 GB 에서 Parquet 18GB 로 1/3 정도의 저장용량을 기대했던 만큼의 개선이 이루어지지는 않았습니다.Parquet Deep Dive상황을 파악하기 위해 조금 더 조사를 해보기로 하였습니다. Parquet의 포맷 스팩은 Parquet 프로젝트에서 관리되고 있고, 이의 구체적인 구현체로 parquet-mr 이나 parquet-cpp 프로젝트 등에서 스펙을 구현하고 있습니다. 그리고 특별한 경우에는 Spark에서는 Spark 내부에 구현된 VectorizedParquetRecordReader 에서 Parquet 파일을 처리하기도 합니다.파일 포맷이 바뀌거나 기능이 추가되는 경우에는 쿼리엔진에서도 이를 잘 적용해주어야 합니다. 하지만 안타깝게도 Spark은 parquet-mr 1.10 버전이 나온 시점에도 1.8 버전의 오래된 버전의 parquet-mr 코드를 사용하고 있습니다. (아마 다음 릴리즈(2.4.0)에는 1.10 버전이 적용될 것으로 보이지만)Parquet 의 메인 개발자 중에는 Impala 프로젝트의 lead도 있기 때문에, Impala에는 비교적 빠르게 변경사항이 반영되는 것에 비하면 대조적입니다. 모든 프로젝트들이 실시간적으로 유기적으로 업데이트되는 것은 힘든 일이기 때문에 어느 정도는 받아들여야겠지만, 우리가 원하는 Parquet의 장점을 취하기 위해서는 여러 가지 옵션을 조정하거나 직접 수정을 해야 합니다.VCNC 데이터팀에서는 저장 용량과 I/O 성능을 최적화하기 위하여 Parquet의Dictionary encoding (String들을 압축할 때 dictionary를 만들어서 압축하는 방식, 길고 반복되는 String이 많다면 좋은 압축률을 기대할 수 있습니다)Column pruning (필요한 컬럼만을 읽어 들이는 기법)Predicate pushdown, row group skipping (predicate, 즉 필터를 데이터를 읽어 들인 후 적용하는 것이 아니라 저장소 레벨에서 적용하는 기법)과 같은 기능들을 사용하기를 원했고, 이를 위해 여러 조사를 진행하였습니다.저장용량 줄이기102GB의 JSON 포맷 로그를 text그대로 gzip으로 압축하면 23GB가 됩니다. dictionary encoding이 잘 적용되도록 적절한 옵션 설정을 통해 Parquet로 저장하면 6GB로, 기존 압축방식보다 저장 용량을 74%나 줄일 수 있었습니다.val ndjsonDF = spark.read.schema(_schema).json("s3a://ndjson-bucket/2018/04/05") ndjsonDF. sort("userId", "objectType", "action"). coalesce(20). write. options(Map( ("compression", "gzip"), ("parquet.enable.dictionary", "true"), ("parquet.block.size", s"${32 * 1024 * 1024}"), ("parquet.page.size", s"${2 * 1024 * 1024}"), ("parquet.dictionary.page.size", s"${8 * 1024 * 1024}"), )). parquet("s3a://parquet-bucket/2018/04/05") 비트윈의 로그 데이터는 ID가 노출되지 않도록 익명화하면서 8ptza2HqTs6ZSpvmcR7Jww 와 같이 길어지기에 이러한 항목들이 dictionary encoding을 통해 효과적으로 압축되리라 기대할 수 있었고, Parquet에서는 dictionary encoding이 기본이기에 압축률 개선에 상당히 기대하고 있었습니다.하지만 parquet-mr 의 구현에서는 dictionary의 크기가 어느 정도 커지면 그 순간부터 dictionary encoding을 쓰지 않고 plain encoding으로 fallback하게 되어 있었습니다. 비트윈에서 나온 로그들은 수많은 동시접속 사용자들의 ID 갯수가 많기 때문에 dictionary의 크기가 상당히 커지는 상태였고, 결국 dictionary encoding을 사용하지 못해 압축 효율이 좋지 못한 상태였습니다.이를 해결하기 위해, parquet.block.size를 default 값인 128MB에서 32MB로 줄이고 parquet.dictionary.page.size를 default 값 1MB에서 8MB 로 늘려서 ID가 dictionary encoding으로만 잘 저장될 수 있도록 만들었습니다.처리속도 올리기저장용량이 줄어든 것으로도 네트워크 I/O가 줄어들기 때문에 처리 속도가 상당히 올라갑니다. 하지만 컬럼 기반 저장소의 장점을 온전하게 활용하기 위해서 column pruning, predicate pushdown들이 제대로 작동하는지 점검하고 싶었습니다.소스코드를 확인하고 몇 가지 테스트를 해 본 결과, Spark에서는 Parquet의 top level field에서의 column pruning은 지원하지만 nested field들에 대해서는 column pruning을 지원하지 않았습니다. 비트윈 로그에서는 nested field들을 많이 사용하고 있었기에 약간 아쉬웠으나 top level field에서의 column pruning 만으로도 어느 정도 만족스러웠고 로그의 구조도 그대로 사용할 예정입니다.Predicate pushdown도 실행시간에 크게 영향을 줄 거라 예상했습니다. 그런데 Spark 2.2.1기준으로 column pruning의 경우와 비슷하게, top level field에 대해서만 predicate pushdown이 작동하는 것을 확인할 수 있었습니다. 이는 성능에 큰 영향을 미치기에, predicate 로 자주 사용하는 column들을 top level 로 끌어올려 저장하는 작업을 하게 되었습니다. 여기에 추가로 parquet.string.min-max-statistics 옵션을 손보고 나서야 드디어 10~30배 정도의 성능 향상을 볼 수 있었습니다.매일 15분 정도 걸리던 "의심스러운 로그인 사용자" 탐지 쿼리가 30여초만에 끝나고, cs처리를 위해 한 사람의 로그만 볼 때 5분 정도 걸리던 쿼리가 30여초만에 처리되게 되었습니다.못다 한 이야기parquet.string.min-max-statistics 옵션과 row group skipping에 관해.Parquet 같은 포맷 입장에서 string 혹은 binary 필드의 순서를 판단하기는 어렵습니다. 예를 들어 글자 á 와 e 가 있을 때 어느 쪽이 더 작다고 할까요? 사전 편찬자라면 á가 더 작다고 볼 것이고, byte 표현을 보면 á는 162이고 e는 101이라 e가 더 작습니다. Parquet 같은 저장 포맷 입장에서는 binary 필드가 있다는 사실만 알고 있고, 그 필드에 무엇이 저장될지, 예를 들어 á와 e가 저장되는지, 이미지의 blob가 저장되는지는 알 수 없습니다. 그러니 순서를 어떻게 정해야 할지는 더더구나 알 수 없습니다.그래서 Parquet 내부적으로 컬럼의 min-max 값을 저장해 둘 때, 1.x 버전에서는 임의로 byte sequence를 UNSINGED 숫자로 해석해 그 컬럼의 min-max 값을 정해 저장했습니다. 이후에 이를 개선하기 위해 Ryan Blue가 PARQUET-686에서 parquet-format에 SORT_ORDER를 저장할 수 있도록 했습니다.여기에서 문제는 이전 버전과의 호환성입니다. SORT_ORDER가 없던 시절의 Parquet 파일을 읽으려 할 때, min-max 값을 사용해 row group skipping이 일어나면 query 엔진에서 올바르지 않은 결과가 나올 수 있으니, binary 필드의 min-max 값을 parquet-mr 에서 아예 반환하지 않게 되어있습니다.하지만 이는 우리가 원하는 동작이 아닙니다. 여기에 parquet.string.min-max-statistics option을 true로 설정하면, 이전처럼 binary필드의 min-max값을 리턴하게 되고 rowgroup skipping이 작동하여 쿼리 성능을 크게 올릴 수 있습니다.마치며Spark과 Parquet 모두 많은 사람이 사랑하는 훌륭한 오픈소스 프로젝트입니다. 또한 별다른 설정이나 튜닝 없이 기본 설정만으로도 잘 돌아가는 편이기 때문에 더더욱 많은 사람이 애용하는 프로젝트이기도 합니다.하지만 오픈소스는 완전하지 않습니다. 좋은 엔지니어링 팀이라면 단지 남들이 많이 쓰는 오픈소스 프로젝트들을 조합해서 사용하는 것에서 그치지 않고 핵심 원리와 내부 구조를 연구해가며 올바르게 활용해야 한다고 생각합니다. 기술의 올바른 활용을 위해 비트윈 데이터팀은 오늘도 노력하고 있습니다.
조회수 2815

우아한 설계의 첫걸음, ES7의 decorator

하루가 멀다 하고 신기술이 쏟아지는 요즘 자바스크립트 또한 계속해서 새로운 모습으로 바뀌고 있습니다. ECMAScript 2015(이하 ES6)에 새롭게 등장한 Arrow function, Class, Generator 등이 그중 하나라 할 수 있습니다. 오늘은 ECMAScript 2016(이하 ES7)에서 새롭게 제안된 Decorator에 대해 알아보려 합니다.Decorator란?ES7 스펙 명세(링크)에는 Decorator를 아래와 같이 설명하고 있습니다.선언된 클래스와 그 프로퍼티들을 디자인 시간에 변경할 수 있는 편리한 문법위 문장만 봐서는 도대체 Decorator가 어떤 역할을 하는지 감이 오지 않습니다. 백문이 불여일견이라고 예제를 통해 Decorator를 어떻게 활용할 수 있는지 알아보겠습니다. 아래 코드는 Decorator를 이용해 설계한 클래스 코드의 일부입니다.@withSuperEngine class Car {     ...   @readOnly  manufacturer = 'ZOYI'   ... } 클래스와 클래스의 프로퍼티가 어떤 성질을 가지고 있는지 한눈에 보이시나요? Car는 슈퍼 엔진을 가지고 있고 manufacturer는 변경할 수 없는 값이라는 것을 소설을 읽는 것처럼 쉽게 이해할 수 있습니다. 이처럼 Decorator를 이용하면 코드를 우아하게 작성할 수 있습니다. 그렇다면 어떻게 Decorator를 정의하고 사용할 수 있을까요?Decorator는 최종적으로 채택된 스펙이 아니기 때문에 babel과 함께 사용해야 합니다. babel 설정은 링크에서 확인할 수 있습니다.Decorator의 선언 및 사용방법Decorator는 사실 함수입니다. 함수를 선언한 뒤 ‘@’ 키워드를 이용해 선언된 함수를 Decorator로 사용할 수 있습니다. @withSuperEngine, @readonly, @say.hello, @hello(...) 등이 사용 가능한 Decorator의 호출 형태입니다. Decorator는 클래스를 꾸밀지, 클래스의 프로퍼티를 꾸밀지에 따라 선언하는 방법이 달라집니다.클래스 프로퍼티의 Decorator먼저 클래스 프로퍼티의 Decorator를 정의하고 사용하는 방법에 대해 알아보겠습니다. 이 경우에는 프로퍼티의 descriptor를 인자로 받아 새로운 descriptor를 반환하는 형태를 가집니다. (descriptor에서 설정할 수 있는 여러 값은 링크를 확인해주세요.)그럼 이제 readonly 역할을 하는 Decorator를 작성하고 테스트를 해 보도록 하겠습니다.function readonly(target, property, descriptor) {     descriptor.writable = false   return descriptor } class Car {     @readonly   manufacturer = 'ZOYI' } const myCar = new Car()   myCar.manufacturer = ‘JOY’ // 새로운 값을 할당하려고 한다면 에러가 납니다. 또 다른 예제로 클래스의 프로퍼티를 열거할 때 열거 대상에서 제외하는 Decorator를 작성해 보겠습니다.function nonenumerable(target, property, descriptor) {     descriptor.enumerable = false   return descriptor } class Car {     @nonenumerable  acceleration = 10 manufacturer = 'ZOYI' } const myCar = new Car()   for (let key in myCar) {     console.log(key)  // manufacturer 만 출력이 된다. acceleration는 열거 대상에서 제외된다. } 단 몇 줄만으로 우리는 클래스의 프로퍼티를 읽기 전용으로 만든다던지 열거 대상에서 제외했습니다. 참 편리하지 않나요? Decorator의 활용은 여기서 끝나지 않습니다. 메모이제이션을 하는 메서드를 만들수 있고 클래스에 자동으로 바인드된 메서드로 만들 수도 있습니다.Decorator는 제안된 지 얼마 안 됐지만 많은 사람들이 활발히 연구 중입니다. github에는 지금도 계속해서 Decorator에 관련된 라이브러리들이 올라오고 있습니다. 그중 core-decorators.js는 미리 정의된 유용한 Decorator 패키지를 제공합니다.클래스의 Decorator클래스의 Decorator는 타겟 클래스의 생성자를 인자로 받습니다. 사용자는 인자로 받은 생성자를 입맛에 맞게 바꾼 뒤 반환을 해 주면 됩니다.function setAnimalSound(sound) {     return (target) => {     target.prototype.sound = sound     return target   } } @setAnimalSound('oink') class Pig {     say() {     return this.sound   } } @setAnimalSound('quack') class Duck {     say() {     return this.sound   } } const pig = new Pig()   console.log(pig.say()) // ‘oink’ 출력 const duck = new Duck()   console.log(duck.say()) // ‘quack’ 출력 위 코드처럼 오리나 돼지의 울음소리를 클래스 내부에서 정의하지 않고 클래스 Decorator를 사용해서 정의할 수 있습니다.(사실 이런 코드는 설계 관점에서 봤을 때 바람직하지 않지만 Decorator를 사용할 수 있는 여러 방법 중에 하나라고 봐주시면 감사하겠습니다.)클래스 Decorator는 클래스의 생성자를 바꾸는 것에 국한되지 않고 완전히 다른 클래스의 생성자로 바꿔치기도 할 수 있습니다. 아래 코드는 그 예제를 보여줍니다.function withBus(target) {     return class Bus {     say() {       return 'I am bus'     }   } } @withBus class Car {     say() {     return 'I am car'   } } const car = new Car()   console.log(car.say()) // ‘I am bus’ 출력 이런 구현 방식은 특정 상황에서 클래스 자체를 하이재킹 함으로써 전통적인 분기문 예외 처리가 아닌 보편적인 프로그래밍을 할 수 있게 도와줍니다.클래스 Decorator는 Cross-Cutting-Concern(전체 설계에서 빈번하게 나오는 관심사를 쉽게 모듈화 시키지 못하는 상황)이나 React에서 컴포넌트 하이재킹을 쉽게 해결해줄 수 있는 방법을 제공합니다. 이런 상황을 어떻게 효율적으로 처리하는지에 대해서는 Decorator를 소개하는 글의 취지에 맞지 않아 다음에 연재할 글에서 다룰 예정입니다.마무리이상으로 ES7에 새롭게 제안된 클래스 및 클래스 프로퍼티에 사용할 수 있는 Decorator에 대해서 알아봤습니다. Decorator는 Java, Python과 같은 언어에서 이미 존재하는 문법이기 때문에 이런 설계가 기존에 없던 새로운 방법은 아닙니다. 하지만 오랫동안 ES5에 머물던 자바스크립트가 ES6, ES7 그리고 최근에는 ES8까지 빠르게 변하고 있는 스펙 속에 다른 언어의 장점을 품는 것은 그 자체로 상당히 도전적인 변화라 생각합니다. Decorator 문법은 클래스와 그 파라미터를 꾸밀 수 있는 것에 멈추지 않고 함수의 파라미터에도 꾸밀 수 있게 드래프트 버전이 나온 상태입니다. 자바스크립트에서 Decorator를 이용한 우아한 설계가 어디까지 발전할 수 있는지, 그리고 향후 자바스크립트의 행보가 기대됩니다.#조이코퍼레이션 #개발자 #개발팀 #인사이트 #경험공유 #일지
조회수 1056

ASIHTTPRequest를 대체하는 iOS 네트워킹 라이브러리 2가지

ASIHTTPRequest는 iOS 개발자들 사이에서 가장 많이 이용되는 네트워킹 라이브러리인데, 간결한 인터페이스와 개선된 성능으로 인기를 끌었습니다. Github의 Objective-C Most Watched Overall에서도 2위 자리를 현재도 유지하고 있는 것을 보면 이 라이브러리가 얼마나 오랜 시간 동안 iOS 개발자들에게 사랑받았는지는 쉽게 알 수 있습니다.[request release];하지만 애석하게도, 이 라이브러리는 작년 9월에 제작 종료가 선언되었습니다. 6개월 이상 된 소식이지만 하도 오랜 시간 동안 쓰여와서 소개된 곳이 많다보니 제작 종료 소식이 많이 안 퍼지고 있는 듯합니다.여러 가지 이유가 있겠지만, 제작자는 제작 종료 선언 글을 통해 “내부가 너무 복잡해졌고, 수 년에 걸쳐 누적된 몇 가지 아키텍처 선택이 프로젝트를 유지 보수하기 어렵게 만들었다.”라고 제작 종료 선언의 이유에 대해 고백하고 있습니다.부지런히 갈아탈 준비를 해두세요.제작 종료가 선언된 라이브러리인 만큼 가능하면 새로운 라이브러리로 갈아타시는 것이 좋습니다. iOS 개발환경은 1년 단위로 빠르게 성장하고 있는데, 당장 최근 iOS5 개발환경만 해도 block 문법 기반의 API 패러다임, ARC 지원들이 현행 라이브러리들의 필수 요소처럼 굳어져 가고 있습니다. 이에 맞추어 따라갈 수 있는 라이브러리들을 쓰는 것이 장기적인 개발 환경 개선에 도움이 될 것입니다.어떤 대안이 있나?ASIHTTPRequest 라이브러리 개발자는 여러 가지 대안을 소개했지만, 저는 2가지 정도로 간추려서 추천하고자 합니다. 하나는 AFNetworking이며, 하나는 MKNetworkKit입니다.AFNetworkingAFNetworking은 최근 Facebook에 인수된 Gowalla에서 NSURLConnection, NSOperation 등의 기본 Foundation framework 위에 구현된 네트워킹 라이브러리입니다.현재 ASIHTTPRequest의 대안으로 가장 빠르게 성장하고 있는 라이브러리인데, 그 이유는 유명 애플리케이션 개발사의 개발자들이 유지하고 있는 프로젝트이면서, 꽤 명쾌한 API를 제공하고 있습니다. 기본적인 block 기반의 API 구성 외로도, SDWebImage와 같은 라이브러리에서 볼 수 있는 이미지 다운로드 헬퍼도 제공하고 있어 매우 편리합니다.자세한 사용법은 AFNetworking Github 저장소에서 확인할 수 있습니다.MKNetworkKitASIHTTPRequest는 편리한 API를 제공해주는 것으로 많은 사용자에게 사랑받았지만, 기본 NSURLConnection, NSOperation 으로 낼 수 없는 높은 퍼포먼스 또한 그의 강점이었습니다. MKNetworkKit은, ASIHTTPRequest의 아키텍처와 AFNetworking의 인터페이스를 동시에 지향하고자 하는 라이브러리입니다. 그 외에도 아래와 같은 기능들을 추가로 겸비합니다.전체 앱에 대한 single queue 관리자동 queue 크기 조절캐싱과 복구 기능비슷한 request를 하나의 처리로 수행Full ARC support아주 멋진 목표를 가지고 진행되고 있는 프로젝트이며 개발 진척도 상당히 빠른 속도로 진행 중이지만, 아직 자잘한 버그가 많다는 것이 단점입니다. 네트워킹 라이브러리는 애플리케이션 단위에선 상당히 저 수준에 있는 만큼, 이 문제는 치명적일 수 있습니다. 그래서 상업용 프로젝트에 바로 이용하기보다는 실험적인 프로젝트에서 써보면서 지켜보는 것을 추천합니다.마무리하며iOS 애플리케이션 개발 환경에서 네트워킹 라이브러리의 선택은 개발 속도와 애플리케이션 퍼포먼스에서 아주 중요한 위치에 속합니다. ASIHTTPRequest는 그 중 가장 많이 쓰였지만, 개발 종료를 선언했기 때문에 대안 라이브러리를 준비하시는 것이 좋습니다.AFNetworking은 편리하게 쓸 수 있는 API를 NSURLConnection, NSOperation 위에 구현하였으며, 믿을 수 있을 만큼 성숙하여 현재 새 프로젝트에 바로 도입하기 좋습니다. MKNetworkKit은 아직 개발이 한창 더 진행되어야 하지만 API 디자인과 개선된 퍼포먼스, ARC 지원 등 보다 미래지향적인 목표를 하고 있으므로 장기적으로 지켜볼 가치가 있습니다.이 외에도 추천하는 라이브러리가 있다면 공유해봅시다.#스포카 #개발 #개발팀 #개발자 #개발팁 #꿀팁 #인사이트 #조언
조회수 1012

만땅에서 스푼까지 함께 달려온 찰스를 소개합니다

스푼을 만드는 사람들 여덟 번째 이야기마이쿤의 초창기 멤버 중 한 명인 'Charles' 를 인터뷰해보았다.그래서, 영어 유치원은 보내셨나요?https://brunch.co.kr/@mirr5510/17내가(Sunny) 처음 마이쿤에 입사하게 된 계기는 바로 Neil(대표)의 브런치 글과 마이쿤 관련 인터넷 기사를 읽고 나서였다. 많은 글 둘 중에 가장 궁금하고 특이하다고 생각했던 글이 바로 '영어 유치원' 보내자 였다.영어 유치원 보내자? 무슨 말이지? 하고 클릭해서 읽어보았다. 스푼 라디오라는 서비스 전 '만땅'이라는 배터리 공유 서비스를 시작할 때 첫 팀 빌딩에 관한 이야기였다. 닐의 주변 지인, 학교 후배들에게 함께 서비스를 만들자고 제안했을 때 유부남 팀원들에게 이렇게 말씀하셨다고 한다."우리, 아이들 영어 유치원 보내자"즉, 그만큼 잘하자. 우리 같이해서 성공하자라는 의미로 이렇게 말씀을 하신 것 같다. 그래서 찰스를 인터뷰할 때 가장 먼저 물어본 질문이었다. 그래서 아이들 영어 유치원은 보내셨는지 말이다.찰스 특징: 모자 좋아함"하하하.. 이미 저희 아이들은 많이 커서 유치원은 벌써 졸업했어요. 이제 테드랑 빅터의 차례가 아닐까 싶네요"찰스가 가장 좋아하는 맥주 'Charles' 당신이 궁금합니다.Q. 본인을 한 마디로 표현한다면?'동네형 또는 오빠' 저는 어색한 걸 싫어하고, 친화력이 좋은 편이기도 하고요. 사람들과의 편한 관계를 좋아해요. 그래서 먼저 보통 말을 먼저 잘 거는 편이에요"Q. 찰스도 혹시 딸 바보세요?"네, 저는 딸 바보예요. 아빠들은 딸 바보가 된다는 건 사실인가 봐요. 딸은 일단 아들과는 정말 달라요. 되게 예쁘고요.. 되게 애교가 많고요..(이때 눈이 반짝반짝하셨습니다) 아들은 보통 엄마를 찾던데, 딸은 항상 아빠를 찾더라고요. 아! 그리고 자다가도 아빠 들어오는 소리 들리면 나와서 뽀뽀해주고 다시 자러 가요. 6살인데 아빠한테 잔소리도 하고요. 마지막으로 하나만 더 자랑해도 돼요? 오늘 5일 만에 딸 얼굴을 봤는데 (안 자고 있을 때) 아빠가 엄~청 보고 싶었다면서 일주일치 뽀뽀를 엄청 많이 해줬답니다.. 이래서 다들 딸 바보가 되나 봐요."Q. 밀가루를 정말 좋아하신다고 들었습니다 feat. 코젤 다크"제 생각에 저는 탄수화물 중독자인 것 같습니다. 탄수화물을 정말 좋아해요. 특히나 칼국수를 정말 좋아하는데요. 맑은 거 말고 찐한 국물의 칼국수 있잖아요. 그거 너무 맛있어요. 제가 추천하고 싶은 칼국수집은, 논현동 영동시장에 있는 이름이 기억이 안 나는데.. 거기 진짜 칼국수 진짜 맛있습니다."P.S: 테드가 옆에서 조용히 슬랙으로 보내주셨습니다. 바로 이 칼국수 집이라네요. '손국시' https://m.blog.naver.com/PostView.nhn?blogId=rldudal0070&logNo=220165610372&proxyReferer=https://www.google.com/당신의 회사생활이 궁금합니다Q. 마이쿤의 초장기 멤버가 되신 계기를 더 알고 싶어요"저는 마이쿤에 입사하게 된 계기가 제 인생에서 가장 큰 결정이었어요. 저는 이 전 회사에서 9년 4개월 정도 근무를 했었어요. 그러던 어느 날 Neil이 회사에 놀러 오라고 하더라고요? 그래서 놀러 갔더니 보니까 이미 Yong 도 함께 일하고 있었고, 갑자기 닐이 사업 기획서를 보여주는 거예요. 이런저런 이야기 함께 나누다가 함께 일을 하자고 제안을 하더라고요. 정말 고민 많았어요. 마침 그때 제가 이직을 생각할 때였거든요. 그렇게 고민하고 와이프와 함께 의논을 했는데 고맙게도 와이프가 저를 믿어주고 응원해주었어요. 그리고 이런 생각을 했어요. "어차피 이직할 거라면 한 번 밑바닥에서 도전해보자!" 그리고 제 손으로 서비스를 함께 만들 수 있다는 것이 가장 큰 메리트이었고요. 드디어 내가 원하는 일을 하게 되었구나 생각했었죠. 무엇보다 서비스가 잘되면 우리 아이들에게 더 나은 미래와 경험을 줄 수 있다고 믿었고요. 무엇보다 잘 되지 않아도 살아가면서 나에게 정말 좋은 경험으로 남아 미래에 발판이 될 것이라고 생각했어요. 그렇게 저는 마이쿤의 초창기 멤버가 되었어요. 무엇보다 서비스에 대한 아이디어와 매력도가 높다고 느꼈고, 닐이 "영어 유치원 보내자!"라는 말에 혹했죠"Q. 첫 서비스를 실패했을 때 떠나지 않고 남았던 이유는?"제가 처음에 입사를 하자마자 와이프가 둘째를 임신한 걸 알게 되었어요. 근데 정말 너무 바빠서 집에도 못 들어가고 일을 했었어요. 가장으로서 남편으로서도 잘하고 싶었고, 일도 잘하고 싶었는데 마음처럼 쉽지가 않더라고요. 경제적으로 힘든 부분도 있었지만, 저는 이대로 이 팀이 헤어지기엔 너무나도 아쉬워서 남는 선택을 했어요. 저희 정말 열심히 했거든요. 진짜 정말 열심히 했는데 이대로 서비스가 잘 되지 않았다는 게 아쉬웠고, 이 일로 이 팀이 해체되는 게 너무 싫었어요. 그때 우리는 모두 정말 열심히 했지만 잘하진 못했었어요. 어떻게 가야 하는지 방향도 몰랐어요. 그래서 더욱 아쉬웠죠. 팀이 해체된다 할지 언정 후회 없이 헤어지고 싶었어요. 근데 저뿐만 아니라, 모든 사람들이 동의를 했어요. 우리 이번엔 열심히 하지 말고 '잘' 하자라고. 그리고 저는 외벌이에 유부남이라 팀원들이 저를 많이 배려해줬었죠. 와이프에게 가장 고마운 점이 그때 와이프가 그랬어요. "떠날 때 떠나더라도 후회 없이 해"이 말이 정말 큰 힘이 됐던 것 같아요. 와이프에게 많이 미안하고 고맙습니다."Q. 6년 동안 함께 해올 수 있었던 원동력은?"저는 정말로 솔직하게 여태 마이쿤에서 다른 곳으로 이직을 해야겠다는 생각을 해본 적이 없어요. 첫 번째 서비스가 망하고도 자발적으로 남은 이유도 이 팀과 함께 후회 없이 가고 싶다는 마음 때문이었어요. 저는 아직도 제가 성장하고 많이 배우고 있고, 배워야 한다고 생각하거든요. 어떠한 사람들과 일하느냐가 정말 중요한 것 같아요. 무엇보다 함께 시작하여 함께 실패하고 또다시 함께 일어났다는 점과 성장했다는 점이 기쁘고 뿌듯하고 더 큰 책임감을 느끼게 해 주거든요. 하지만 언젠가 제가 회사에 도움이 되지 않는 날이 온다면 그때는 스스로 떠날 생각입니다 (웃음)"Q. 리더로서의 삶은 어떤가요?"팀에 동료가 많아지게 되고 각각 다른 성격의 동료들이 생겨났어요. 각자 다들 일을 열심하 하고 잘하지만 팀으로서 하나가 되어 한 마음으로 커 나가는 건 다른 문제라고 생각해요. 각자의 개성을 살릴 수 있는 방법이 있을까? 내가 어떻게 하면 좋은 리더가 되어 후배들을 이끌어 줄 수 있을까? 하고 고민도 많이 해보고, 함께 이야기도 해보기도 하고요. 진심을 담아서 늘 말을 해요. 제 진심이 닿아야 팀원들도 저를 더 잘 따라 줄 테니까요. 면담을 통해서 불편한 것들을 해소해주려고도 노력하고 무엇보다 저도 그 들에게 많이 배우고 있어요. 아무리 신입이라도 해도 제가 생각하지 못한 부분을 배울 수 있거든요. 각자 살아온 환경과 경험이 다르고 본인이 잘하는 것들은 다 제 각각 다르니까요. 그래서 많이 노력하고 배우려는 리더가 되려고 노력 중입니다."Q. 새로운 서비스가 성장하면서 변한 게 있다면?Sunny 曰: "지난 만 5년 동안 마이쿤의 실패 그리고 재 도전 및 성장 과정을 모두 봐오셨잖아요. 뭐가 가장 많이 달라졌을까요? 정말 많은 것들이 변했겠지만요."Charles 曰: "저는 일단 스푼이라는 서비스가 성장하면서 좋아진 점이 정말 많아진 것 같아요. 그중 가장 큰 건 회사에 점점 더 전문적이고 실력 있는 분들이 입사하셨다는 겁니다. 물론 분위기는 예전하고 같을 수 없겠지요. 그때와 지금의 인원 차가 크니까요.분위기나 문화를 그때가 똑같이 유지를 한다는 건 불가능하다고 생각해요. 서비스의 규모에 맞게 함께 성장해 나가야 하니까요. 다양한 사람과 다양한 시선으로 보고 느껴야 회사 서비스가 더 성장할 수 있거든요. 그리고 서비스가 성장해야 우리 모두에게 좋은 일인 것이고요. 새로 입사하신 분들은 굉장히 능력자가 많으세요. 그분들에게 많이 배우려고 하고 있고 있고요"찰스가 좋아하는 진라면 + 파송송 + 계란탁 당신의 사생활이 궁금합니다Q. 좋은 아빠란 어떤 아빠라고 생각하세요?"내가 생각하는 좋은 아빠란?처음에는 애들과 재미있게 잘 놀아주면 그것만으로도 좋은 아빠라고 생각을 했었어요. 알고 보니 그것만으로는 부족하더라고요. 잘 놀아주는 것은 기본이고, 아이의 시선에서 세상을 바라봐 주고, 아이와 눈높이를 맞춰 주는 자세를 가져야 하고 제일 중요한 것은 아이의 마음을 공감해줘야 한다고 생각합니다. 이렇게 해야 정말 좋은 아빠가 아닐까?라고 생각합니다. 잘 놀아주는 것은 누구보다 잘한다고 생각합니다만 아직까지도 아이의 마음을 공감해주는 부분에서는  많이 부족합니다. 저도 모르게 아이를 혼내고, 반성하고 이 패턴이 반복이에요. 한때는 뱃속에 있을 때는 건강하기만을 원했는데, 막상 세상에 나와보니 어쩔 수 없나 봅니다."Q. 자녀분들이 개발자를 꿈꾼다면 추천하시나요?“개발자는 굉장히 매력적인 직업입니다.누구나 개발자가 될 수 있고, 즐길 수 있는 지금의 문화라면 저는 아이들에게 개발자가 되는 것을 추천해주고 싶어요. 성취감이라는 걸 얻을 수 있는 직업이기에, 그런 걸 느껴보게 해주고 싶기도 하고요.나의 재능으로 나를 포함한 누군가의 삶이 달라질 수 있는 경험은 좋은 경험이라고 생각해요. 무엇보다 개발자는 스스로 만들고 싶어 하는 욕구가 있는데요. 내가 개발한 서비스나 상품을 누군가가 사용하고 좋은 피드백을 준다면 정말 보람찬 일이거든요. 물론 부정적인 피드백을 받으면 상실감을 느낄 수도 있지만, 그 과정에서 또 성장해나갈 수 있기 때문에!”Q. 나중에 개발해 보고 싶은 서비스가 있나요?"있어요. 라면 서비스요. 저는 라면을 정말 좋아하거든요, 라면 중에서도 진라면을 가장 좋아하는데 진라면에 파 넣고 마늘 넣고 콩나물 넣고! 끓여먹으면 전 일주일 내내 먹을 수 있습니다. 그래서 '우리 함께라면'이라는 라면 서비스를 해보고 싶어요. 라면에 특화된 서비스죠. 제가 그래서 예전에 회사에서 사람들 한 명 한 명한테 혹시 라면 일주일 내내 먹을 수 있냐고 물어보기도 했었어요."Q. 만약 개발을 하지 않았더라면 지금 뭐하시고 계셨을 거 같으세요?"글쎄요. 저는 원래 사실 개발자가 되려던 마음은 없었어요. 군대 제대하고 우연히 한 번 해볼까? 했는데 시작하게 되어 업이 되었네요. 저는 아마 개발자가 아니라면 지금 공무원? 하지 않았을까 싶어요. 원래 저의 옛날 성향은 뭔가 모나지 않고, 평범한 사람이었거든요. 이렇게 큰 도전을 하기 전까지는요"당신이 마이쿤에서 우리와 함께 일해야 하는 이유는요저희는 정말 많은 실패와 역경을 거쳐왔고, 쓰러질 때마다 '함께' 일어났습니다. 이제서야말로 정말 본격적으로 성장하기 위해 달려야 하는 시점이에요.  해야 할 것도 정말 많고요. 회사와 서비스가 성장하는 경험을 할 수 있다는 것은 어디서 돈 주고도 못할 경험이라고 생각합니다. 지금 이 기회에 저희와 같은 배를 타신다면, 개개인이 노력한 만큼 서비스 성장에 기여하실 수 있고 본인 스스로도 성장하는데 많은 도움이 될 것이라고 생각해요. 이미 성장한 곳에서 경험을 하는 것도 분명 가치 있는 일이지만, 나 스스로가 성장에 기여할 수 있는 회사의 구성원이 될 수 있는 건 흔한 일이 아니라고 생각합니다.서비스 플랫폼 팀원들이 Charles를 한마디로 표현한다면?Kyu 曰:  '동네형' - 사실은 동네 아저씨에 더 가깝지만 마치 동네 형인 듯 다가와주는 사람.Sam 曰:  '장군님' - 어디서 자꾸 전리품(티셔츠, 스티커 등 )을 가지고 오신다.P.S 저희 어머님께서 NewRelic 티셔츠 편하다고 너무 좋아하십니다.Mark 曰:  '언니' - 가끔 삐지시는 거 같지만 언제나 잘 챙겨준다.
조회수 1197

EOS Token 생성과 발행, 전송

이번시간에는 배포한 Contract를 통해 Token 발행과 전송을 해보겠습니다. 이를 위한 준비는 아래 2미디엄 글을 참조해주세요EOS Smart Contract 를 위한 준비EOS Smart Contract 배포먼저 저번 시간에 배포한 token 발행 abi 를 확인해 보겠습니다.$ cleos get abi hexlanthenryget abiabi를 확인하다보면 actions 라는 항목에 총 3개의 action이 있음을 확인할 수 있습니다. 이 3개의 name이 실행할 수 있는 action입니다. token발행은 create action을 통해 진행할 수 있습니다.Token 생성$ cleos push action hexlanthenry create '["hexlanthenry", "10000000000.0000 HEX"]' -p hexlanthenrycreate action 실행 결과create action 을 통해 ‘HEX’ 토큰을 100억개 생성했습니다. create 라는 action의 인자는 account_name(hexlanthenry), maximum_supply(10000000000.0000 HEX) 입니다. 즉 첫번째 인자는 토큰의 발행자를 나타내며, 두번째 인자는 토큰의 최대 수량을 나타냅니다.이 인자가 어떻게 들어가는지는 abi 의 struct 를 확인하면 알 수 있습니다.abi의 create structparameter 1 : account_name type— issuerparameter 2 : asset type — maximum_supply+ 저번 강의에서 공지한데로 다음 포스팅에서는 abi가 무엇을 뜻하는지, 이를 통해 어떻게 action을 실행할 수 있는지 알아보도록 하겠습니다.Token 발행생성과 발행 이 2개의 개념이 헷갈릴 수 있습니다. create action을 통한 생성은 최대 발행량을 결정 하는 것이며, issue action 은 토큰을 유통 시키는 것입니다.create : token 생성과 동시에 최대 발행량 결정issue : token 의 유통따라서 issue action을 통해 이전에 생성한 HEX token을 발행해보겠습니다.$ cleos push action hexlanthenry issue '["hexlanthenry", "10000.0000 HEX", "initial issue"]' -p hexlanthenryissue contract 실행 결과issue action 역시 data로 어떤 인자가 들어가는지는 abi를 통해 확인 가능합니다.abi의 issue structparameter 1 : account_name type — toparameter 2 : asset type — quantityparameter 3 : string type — memomemo 는 transfer 가 어떤 목적인지에 대해 설명해주는 인자 입니다. 생략해도 되는 값으로, 원하시면 parameter 개수를 유지하는 선에서 empty string을 넣으시면 됩니다. memo를 어떻게 쓰면 유용한지에 대해서도 다른 포스팅에 담도록 하겠습니다.issue가 잘 실행 되었는지 확인해 보겠습니다.$ cleos get currency balance hexlanthenry hexlanthenry저는 issue 를 4번 수행한 후 balance 를 체크 했기 때문에 총 40000개의 HEX token이 존재하는 것을 확인 할 수 있습니다.hexlanthenry 의 HEX token개수예외사항1create 하지 않은 token을 issue 할 경우해당 symbol 이 존재하지 않음예외사항2생성한 token 수보다 많은 양을 issue 할 경우maximum supply를 초과함Token transfer마지막으로 token을 다른 계정에 전송 해보도록 하겠습니다. 다른계정에 token을 보내야 하기 때문에 계정을 생성하거나 존재하고 있는 계정을 사용하시면 됩니다.아래 명령으로 hexlanthenry 계정이 babylion1234 계정으로 10000개의 HEX 토큰을 보냅니다.$ cleos push action hexlanthenry transfer '["hexlanthenry", "babylion1234", "10000.0000 HEX", "first"]' -p hexlanthenrytransfer 실행결과transfer 시 들어가는 data에 대해서도 abi를 확인해보겠습니다. 다른 action보다 많은 인자를 필요로 합니다. [“hexlanthenry”, “babylion1234”, “10000.0000 HEX”, “first”]abi의 transfer structparameter 1 : account_name type — fromparameter 2 : account_name type — toparameter 3 : asset type — quantityparameter 4 : string type — memo실제로 babylion1234 계정을 확인해 보면, 방금 배포한 HEX token을 보유하고있는 것을 확인할 수 있습니다.babylion1234의 HEX 보유이번 포스팅에서는 token을 생성과 발행 그리고 전송을 다뤄봤습니다. EOS는 Ethereum 과 달리 토큰 발행을 매우 쉽게 진행할 수 있습니다. 이 두 dapp의 차이에 대해서도 포스팅을 하고 싶으나 우선 다음 포스팅에서는 contract 개발의 기초를 다루도록 하겠습니다.감사합니다.#헥슬란트 #HEXLANT #블록체인 #개발자 #개발팀 #기술기업 #기술중심
조회수 254

컴공생의 AI 스쿨 필기 노트 ③ K-평균 군집화

AI 스쿨 3주차에서는 K-means clustering(K 평균 군집화)에 대해 배웠어요. 이에 대해서 간략하게 정리해볼게요.K-means clustering클러스터링이란 군집화를 의미하는데요, K-means clustering은 비슷한 데이터끼리 묶어주는 머신 러닝 기법이에요. K-means clustering은 비지도학습(Unsupervised learning)의 일종이에요. 비지도 학습이란 데이터와 각각의 데이터가 무엇인지를 설명해주는 라벨이 없는 학습을 말해요. 따라서 우리는 주어진 데이터들을 가장 잘 설명하는 클러스터를 찾아 데이터를 분류할 수 있어요. 아래는 데이터를 2개의 클래스로 군집화한 것을 잘 나타내주는 그래프에요.K-means는 클러스터 내부에 속한 데이터들이 서로 가깝다고 정의해요. 그렇다면 같은 클러스터에 속한 데이터들은 서로 가까이 근접해 있겠죠? K-means는 클러스터의 중심으로부터 가까운 데이터들을 찾아서 묶어주는 알고리즘이에요. 데이터들은 가장 가까운 내부 거리를 가지는 클러스터를 고르게 되는데, 이를 위해서 각각의 클러스터는 중심(프로토타입)이 존재하고 각각의 데이터가 그 중심과 얼마나 가까운지를 Cost로 정의해요.위의 식은 같은 클러스터에 속하는 각각의 점들로부터 그 클러스터의 평균(프로토타입)과의 거리의 합을 제곱한 함수에요. - N : 데이터의 개수- K : 클러스터의 개수- uk : k 번째 클러스터의 중심(프로토타입)- rnk : n 번째 데이터가 k 번째 클러스터에 속하면 1, 속하지 않는다면 0을 가지는 이진 변수우리는 위 식에서 rnk, uk를 구해야 해요. 이때 반드시 잊지 말아야 하는 조건은 각 데이터가 한 개의 클러스터에 할당이 되어야 한다는 것이에요.K-means 알고리즘K-means algorithm을 구하는 방법은 아래와 같이 크게 2단계로 나누어져요. 먼저 uk에 랜덤 값을 사용하여 임의의 초깃값을 설정해요.1. Expectationuk를 고정시키면서 J를 최소화하는  rnk값을 지정해야 하는데,  rnk은 모든 데이터 n에 대해 각각 모든 클러스터 중에서 xn- uk가 가장 작은 클러스터에 할당해요.2. Maximization새롭게 얻어진 rnk를 고정하고 uk는 k 번째 클러스터의 mean을 계산해요. 두 값이 적당한 범위 내로 수렴할 때까지 계산을 반복해요, 위의 두 단계를 각각 E(expectation) 단계와 M(maximization) 단계라 하고, 이 두 단계를 합쳐서 EM 알고리즘이라고 해요.알고리즘 코드로 나타내기그럼 K-means algorithm을 코드로 어떻게 나타내는지 살펴볼게요!Step1. 데이터 만들기np.random.seed(42)digits = load_digits()  data = scale(digits.data)n_samples, n_features = data.shapen_digits = len(np.unique(digits.target))labels = digits.targetx_train, x_test, y_train, y_test = train_test_split(data, labels, test_size=0.25, random_state=42) - digits = load_digits(): load_digits 함수를 사용하면 data와 target이 반환되는데 이 데이터를 scale 함수를 사용하여 전처리해요.- data.shape을 사용하면 n_samples에는 1797, n_feature에는 64가 할당돼요.- n_digits에는 digits의 target의 중복된 값을 제외한 개수를 할당해요.- train_test_split() 함수를 이용하여 train_set과 test_set을 랜덤 시드를 42를 가지는 75:25의 비율로 나눠요.Step2. KMeans model 만들기sklearn 라이브러리를 사용하면 KMeans model을 아주 쉽게 구현할 수 있어요.kmeans = KMeans(init='k-means++', n_clusters=10, random_state=42)clusters = kmeans.fit_predict(x_train)- KMeans 함수를 이용하여 모형은 k-means++를 가지고, cluster는 10개를 가지며 랜덤 시드는 42를 가지는 K-means clustering을 만들어요.- x_train 데이터 셋을 중심으로 클러스터의 중심을 계산하고 각 샘플에 대한 클러스터의 인덱스를 예측할 수 있도록 fit_predict()를 사용해요.Step3. K-means clustering 결과 출력print('Clusters: ', clusters)위와 같이 출력하면 아래와 같은 결과가 나와요.Clusters: [1 3 2 ... 6 6 0]]그래프를 출력하면 아래와 같은 결과를 볼 수 있어요!이번 수업에 배운 K-means clustering의 개념은 1주차와 2주차 수업의 개념에 비해 어렵지 않았던 것 같아요. 이해하기에 큰 문제는 없었지만 코드로 직접 짜려고 하니 막히는 부분이 있어서 고생을 좀 했어요. 저는 과제를 하다가 에러가 나면 구글링을 통해서 에러를 해결하거나 도저히 못하겠다 싶으면 도움 요청을 해요. 목요일에는 조교분들께서 Multiple Regression에 대해 숙명여대에서 수업을 진행해주셨는데요. 1, 2주차에 배운 내용을 복습하고 3주차 수업에서 짧게 살펴본 Multiclassification을 더 자세히 알려주셔서 본 수업 때 이해가 되지 않았던 부분이 해결이 되었습니다! 목요일 수업은 정식 수업이 아닌 보충수업이었기 때문에 소수의 사람들이 강의에 참여했는데요. 시간이 된다면 참석을 꼭 해주시면 굉장히 큰 도움이 될 것 같아요. * 이 글은 AI스쿨 - 인공지능 R&D 실무자 양성과정 3주차 수업에 대해 수강생 최유진님이 작성하신 수업 후기입니다.
조회수 3346

코인원 개발자는 어떻게 일할까?

코인원의 파이콘 한국 2018 참여기 그 두번째 이야기!코인원의 핵심, 코인원의 자랑 ‘코인원 개발자’들에 대한 이야기를 나눠보려 합니다.지금의 코인원이 있을 수 있는 이유는 바로 더 좋은 프로덕트를 만들어내기 위해 치열하게 고민하는 개발 크루들의 노력이 있었기 때문입니다.코인원은 지난 파이콘 한국 2018 ‘열린공간(Open Speak Talking)’ 세션에 참여했습니다. 이 시간을 통해 그동안 코인원 개발 크루들이 축적한 지식과 경험 그리고 노하우를 공유했어요. 파이콘이 개발자들을 위한 행사인만큼, 코인원의 개발문화와 환경, 채용 원칙에 대한 심도깊은 이야기가 오고갔답니다.그래서 예고했던대로 코인원 개발자들의 ‘Mini Interview’를 통해 개발 크루들은 기술본부를 어떻게 만들어나가고 있는지 자세히 알려드릴게요 :-)'파이콘 한국 2018' 후기 1탄 현장스케치▼코인원X'파이콘 한국 2018' 현장스케치!파이썬 개발자들의 즐거운 축제, ‘파이콘 한국 2018’이 지난 19일 성황리에 막을 내렸습니다. 이번 행사...blog.naver.com지난 8월 19일 진행된 파이콘 열린공간 현장, Open Speak Talking!진우님(CTO)을 집중 심문하고 있는 피플팀 수장 대경님코인원 기술본부는 어떻게 구성되어 있나요?진우님(CTO) : 안녕하세요, 코인원 CTO(Chief Technical Officer, 최고기술책임자) 이진우 입니다. 현재 코인원 기술본부는 총 8개의 팀으로 이루어져 있는데요. Core팀, Web팀, API팀, APP팀, QA팀, SRE팀, 데이터팀, 기술연구팀으로 나뉘어진답니다. 코인원 기술본부는 사용자에게 편리한 서비스를 제공하기 위해 프로덕트를 만들어나가고 있어요. 먼저, 사용자에게 직접적으로 보여지는 화면인 프론트엔드를 책임지는 ‘Web팀과 APP팀’ 그리고 사용자에게 보이지 않지만 시스템의 안쪽에서 수행되는 백엔드를 책임지며 프론트엔드에서 필요로하는 결과를 제공하는 ‘Core팀, API팀, QA팀, SRE팀, 데이터팀, 기술연구팀’이 인터렉티브하게 일하고 있습니다.저희는 암호화폐 거래소 코인원을 더욱 더 잘 구축하고, 개선하고, 안전하게 운영하는 것을 목표로 삼고 있어요. 또한 개발 뿐만 아니라, 지속적인 블록체인 연구를 통해 거래소에 최신 기술 트렌드를 반영할 수 있도록 항상 고민하죠.파이콘의 질문왕, 웹팀의 경화님 :)저 멍때리는거 아니에요, OST에 집중하고 있는거에요. (feat. 새로찬가로찬님)눈감은거아니에요, 뜬거에요. (feat. 킹갓제너럴대현님)코인원 개발자들은 어떻게 일하나요?경화님 (Web developer) : 코인원 개발자들은 서로 어떤 업무를 하고 있는지 눈으로 트래킹 할 수 있고, 투명하게 업무를 공유할 수 있는 개발환경을 만들고 있어요. 저희는 협업툴로 Jira와 Confluence를 사용하고 있습니다. 협업툴로 업무의 효율성을 높이면서 새로운 개발업무에 집중하는데 많은 도움이 되고 있어요. 또한 협업툴 이외에도 새로운 기술 도입에 긍정적이라 자기주도하에 여러가지 기술을 실무에 적용해볼 수 있다는 점이 매력적이죠.새로찬님 (Engineer) : 주어진 요구사항에 맞게 그대로 개발하기 보다는 요구사항의 필요성에 대해 공감하고 더 좋은 방향으로 만들 수 있도록 기획, 디자인, 개발 모든 단계에서 능동적으로 의견을 제시합니다. 기술본부에서는 빠르게 변화하는 시장상황에 맞추기 위해 매일 아침마다 PM, 개발자, 디자이너가 모여 *데일리스크럼을 진행하는데요, 서로의 Task나 Project 진행상황을 공유하고 최고의 프로덕트를 사용자에게 전달하기 위해 노력하고 있어요. *데일리스크럼이란? 정해진 시간에 개발크루들이 모여서 어제 했던 일과 오늘의 할 일 등을 공유하고, 다른 개발 크루들이 이야기하는 업무현황을 들으면서 내가 기여할 수 있는 부분과 이슈를 빠르게 파악할 수 있는 자리에요! 대현님 (Engineer) : 서비스를 만드는데 있어 주도적으로 그리고 적극적으로 개발업무를 수행합니다. 예를 들어, 코인원 Live Service에서 Manual하게 처리하고 있었던 이슈들을 자동화하는 프로젝트가 있었는데요. 수동으로 해결할 수 있는 부분이지만, 이를 서비스 기획자분들과 연계해 Task로 만들어 해결방안을 얻을 수 있었습니다. 또한 여기서 그치는게 아니라, 계속해서 코인원 사용자들을 위해 필요한 기능들을 추가하는 프로젝트에 참여하면서 많은 재미를 느꼈죠.왼쪽부터 파이콘의 나이스걸 (윤정님), 개발자 (희수님), ddddeveloper (선우님)개발본부의 공식포즈, 쁘쁘브브브이 종헌님 ㅇ_ㅇV코인원 개발자가 되면 어떤 점들이 좋나요?희수님 (Engineer) : 이전에 경험하지 못했던 거래소 프로덕트를 만들어볼 수 있다는 점이 정말 좋습니다. 저는 원래 암호화폐와 핀테크에 관심이 많았는데요. 코인원에서 거래소 프로덕트를 직접 만들면서 관심 분야에 대해서도 더 많이 알게 되고, 또 이런 서비스를 개발할 때 중요한 것이 무엇인지 고민해보면서 배워가는 것이 정말 많아요. 제가 코인원 합류 이전에 개발한 프로덕트들과는 성향이 많이 달라서 더 재미를 느끼고 있어요!종헌님 (Web developer) : 함께 일하는 모든 개발자 분들이 더 효율적인 개발 프로세스를 만들기 위해 치열하게 고민하는 것을 보면서 매일 놀라고 있어요. 서비스를 개발하며 느끼는 문제점을 도출하면서 치열하게 토론하고, 그 문제들을 해결하기 위한 아이디어들을 직접 시도해 볼 수 있어서 좋아요. 일을 더 효율적으로, 즐겁게 할 수 있는 환경을 만드는 과정이 코인원만의 애자일을 만들어나가는 것 같아 더 열정적으로 일할 수 있는 것 같습니다.선우님 (Web developer) : 많은 사용자들이 직접 이용하는 서비스를 만드는 개발자로서 다양한 문제 상황을 직면하고 해결해 나가며 보고 배우는게 많습니다. 또 코인원 기술본부는 여느 코인원 조직처럼 언제든 자신의 의견을 자유롭게 이야기하는 분위기가 형성돼있어요. 특히 하나의 프로젝트가 끝나면 회고(Retro)를 진행하는데, 프로젝트의 진행과정, 이슈, 결과물을 공유하면서 저 자신을 성장시켜나갈 수 있는 요소들이 많습니다.안녕하세요, 코인원 신입개발자 (a.k.a CTO) 입니다. (인사성 밝음밝음)“코인원에서는 어떤개발자를 원하나요?진우님 (CTO) : 블록체인을 좋아하고, 개발을 좋아하시는 분이라면 언제든지 환영입니다. 코인원 개발 크루들을 생각했을 때 ‘몰입’이라는 단어가 가장 먼저 떠오르는데요. 모두가 마니아적이고 덕후기질이 있어, 자기주도적으로 업무를 하고 적극적으로 개발할 것들을 찾고 실행합니다.  앞으로 코인원 개발 크루로 합류하실 분들 또한, 적극적으로 아이디어를 내고, 그 아이디어를 실현할 수 있도록 프로젝트를 리딩할 수 있는 분이었으면 해요. 물론 개발하는데 있어서는 누구보다 신중한 자세가 필요하겠죠? 누구보다도 내가 짠 개발코드를 꼼꼼하게 검토하고, 표용력이 있어 좋은 아이디어에는 귀 기울일 줄 아는 분들이셨으면 좋겠습니다. 참고로 Node.js, Python, Spring, C#, AngularJS를 업무에 많이 활용하고 있답니다.개발을 사랑하시는 분! 블록체인을 함께 탐험할 준비가 되신 분! 코인원 개발자 채용에 많은 관심 부탁 드립니다.코인원 개발자 채용에 많은 관심 부탁드립니다 :-)지금까지 미니 인터뷰를 통해 코인원 개발 크루들의 이야기를 들어봤습니다:) 블록체인이라는 새로운 기술 영역에서 매일매일 즐겁게 도전하고 있는 코인원 개발팀에 합류하고 싶은 분들은 현재 코인원 개발자 채용이 진행되고 있으니 지금 바로 확인해주세요!#코인원 #블록체인 #기술기업 #암호화폐 #스타트업인사이트 #기업문화 #조직문화 #팀원소개 #인터뷰

기업문화 엿볼 때, 더팀스

로그인

/