스토리 홈

인터뷰

피드

뉴스

조회수 2237

사운들리 코드 품질 관리 이야기

안녕하세요 "사운들리"입니다 :)오늘은 사운들리의 코드 품질 관리에 대해 이야기 해보려 합니다.몇몇 개발자에게는 지루하고 악몽같은 이야기일 수 있겠네요.제 경우에는 예전에는 이런 품질이라는 단어를 멀리했지만 결국 제가 작성한 코드에 발목을 많이 잡히다 보니, 자연스레 관심을 갖게 되었습니다.일단, 어떤 소프트웨어가 좋은 품질의 소프트웨어일까요?좋은 품질이란? 책에 나올법한 내용을 보면, 아래와 같은 항목을 토대로 소프트웨어 품질을 판단한다고 합니다.ISO/IEC 9126 : Software engineering - Product qualityFunctionality: 명시된 요구사항을 잘 충족했는지Reliability: 명시된 조건과 시간 아래에서 일정 성능을 유지 하는지Usability: 사용하기 위해 어느정도의 노력과 자원이 필요한지Efficiency: 소모 자원과 성능간의 효율Maintainability: 수정하기 위해 어느정도의 노력이 필요한지Portability: 다른 환경에서도 사용 할수 있는지출처: https://en.wikipedia.org/wiki/ISO/IEC_9126 뭔가 복잡해 보이지만, 결국 개발자라면 위의 항목은 누구나 추구하게 되는 가치라고 생각 합니다.그런데 말입니다. 이런 좋은 내용을 마음 속으로만 간직한 채 코드를 작성하면 정말 좋은 소프트웨어를 만들 수 있을까요? 저는 객관적인 방법으로 코드를 평가한다면 좋은 피드백이 될 것이라고 생각합니다. (물론 이 성적표를 남에게 보여주는 것과는 다른 문제에요 ㅎㅎ)어떻게 품질을 체크하는가 소프트웨어의 품질을 체크하는 데에 다양한 방법과 툴이 제시되고 있는데요, 저는 크게 두 가지로 분류 해보겠습니다.유저 입장의 품질: 유저의 요구사항에 맞는 소프트웨어인지 체크개발자 입장의 품질: 내가 지금 이 코드를 의도한 대로 잘 작성하고 있는지 체크 유저 입장의 품질은 언급하지 않아도 중요함을 누구나 알고 있습니다. 이 부분이 만족이 되지 않으면 제품이 아니죠! 그래서 저는 개발자 입장에서 스스로 챙길수 있는 품질을 사운들리는 어떻게 챙겨보고 있는 지 이야기 해보도록 하겠습니다. 실은 제가 개발자 입니다 ㅎㅎ사운들리 개발자의 코드는 아래와 같이 흘러갑니다.<그림1> 사운들리 코드 개발상의 품질 관리 순서도간단히 각 항목을 훑어 보겠습니다.Local Machine 각자 갖고 있는 맥북으로, 다양한 IDE를 사용해 코딩합니다. 그리고 git 을 이용해 commit 하고, github 에 push 하죠.Github push 된 수정사항은 pull request 를 통해 동료에게 알려집니다. 이후 코드리뷰를 통해 merge 하게 됩니다. 코드리뷰는 많은 사람들에 의해 그 중요성이 부각되고 있습니다. 사운들리는 같은 모듈을 만드는 개발자끼리, 그리고 다른 모듈에 영향을 주는 코드일 경우에는 해당 모듈의 개발자도 리뷰를 합니다. 코드리뷰를 통해 다른 사람이 어떤 기능을 작성했는지 보고, 오류도 찾고, 더 좋은 방법이 있으면 공유도 하고, 칭찬도 하고, 훈수도 두고 합니다. 참고로 사운들리는 git-flow 정책에 따라 git branch를 운영하고 있습니다.Jenkins  Github 에 commit 이 등록되면 Jenkins 는 자동으로 빌드를 시작 합니다. Jenkins 는 단순 빌드 성공 실패를 떠나서, 코드 품질에 대한 몇가지 report 를 발생 시킵니다. 아래에서 좀더 자세히 다뤄보겠습니다.SonarQube Jenkins 에서 빌드하면서 SonarQube 에 포함된 분석 기능을 사용하게 됩니다.그렇다면, 코드 품질의 지표는 무엇일까요?Jenkins가 발생시키는 레포트를 통해서 알 수 있는 내용은 아래와 같습니다.코딩 스타일 체크 결과: 작성된 코드가 미리 정의된 코딩 스타일에 맞게 작성되어 있는지?Unit Test 결과: 유닛 테스트 결과 (당연히 전부 pass 해야겠죠)Test code coverage 결과: 테스트 코드가 전체 코드의 몇 % 를 커버 하고 있는지 (우리의 최종목표는.. 60%.. 덜덜덜)정적 분석 결과: 코드를 실행하지는 않지만, 코드 그 자체에서 발생할 수 있는 결함을 찾아줍니다. 이 네 가지 레포트는 객관적 수치를 나타내주기 때문에 일종의 코드 품질 지표로 삼을 수 있습니다. 물론 이 지표만 잘 관리 했다고 해서 좋은 코드를 작성했다고 말할 수는 없습니다. 다만 좋은 코드를 작성하기 위한 기초 중의 기초라고 볼 수 있겠죠 :)품질 체크를 위한 툴(tool)은 개발 언어에 따라 다를 수 있습니다. 사운들리에서는 다양한 언어로 소프트웨어가 작성되어 있습니다. 따라서 언어마다 위의 결과를 얻기 위해서 서로 다른 툴을 사용하고 있습니다. AndroidJavaJavascriptC/C++코딩 스타일checkstylecheckstyle jshintcppcheckUnit testjunitjunitmochagoogletestCode coveragejacococoberturamocha-covgcov정적 분석sonarqubesonarqube sonarqubecppcheck 각 개발자는 위의 네 가지 결과를 얻기 위해서 빌드 시스템에 툴을 포함하여 개발하고 있습니다. 제가 주로 개발하고 있는 java 언어에 해당하는 툴들을 좀 더 자세히 살펴보겠습니다.checkstyle코딩 스타일을 체크 해줍니다. xml 파일로 미리 정의 되어있고요. 매번 빌드할때마다 스타일이 틀린것을 지적해 줍니다.코딩 스타일은 중요합니다. 같이 개발하는 개발자와 코딩 스타일이 같다면 마치 내가 작성한 코드처럼 쉽게 읽을 수 있죠.junitjunit 은 자바 유닛 테스트 프레임워크 입니다. 유닛 테스트 코드를 편하게 작성하게 해주고, 쉽게 테스트 결과를 볼 수 있습니다.유닛 테스트 코드를 작성하면 내가 작성한 모듈을 작은 단위로 테스트 해서, 작은 로직에서 발생하는 시시콜콜한 문제를 방지 할 수 있습니다. 테스트 코드를 작성해서 검증한 부분은 스스로도 신뢰가 갑니다.기능 수정간에 유닛 테스트에서 fail 이 나는 경우가 발생하는데, 모르는 사이에 다른 모듈에 영향을 준 것을 알게 됩니다. 다른 모듈에 모르고 영향을 주게 되면 뒷처리가 어려워지잖아요~coberturacode coverage 를 계산해 주는 툴입니다.유닛 테스트 코드가 실행되면, 작성된 코드의 각 부분을 실행하게 됩니다. cobertura 는 이때 각 코드의 어느부분이 실행되었는지 확인해서 통계를 내줍니다.주로 line coverage / branch coverage 두 지표를 보는데요, line coverage 는 해당 라인이 한번이라도 실행 되면 check 되고, branch coverage 는 각 라인에 있는 조건문을 다 따로 check 합니다. 당연히 branch coverage 를 달성하는게 어렵겠죠?sonarqube소나큐브는 다양한 plug-in 을 통해서 정적 분석을 하고, 시각화를 해주는 툴입니다.사운들리는 주로 정적 분석 용도로만 소나큐브를 사용하고 있습니다. (지원하는 plug-in 을 보면 젠킨스와 기능이 겹치는 부분이 있습니다.)정적분석으로 실제 문제가 되는 부분을 찾는 경우도 있고, minor 한 부분에 대한 지적을 하는 경우도 있습니다. 그러나 이런 minor 한 부분도 꼼꼼하게 잘 챙겨야 좋은 개발자가 된다고 믿고 있습니다.마치며 여기까지 사운들리의 코드 품질 관리에 대해 이야기 해보았습니다. 품질 관리를 해보신 분은 아시겠지만, 이런 툴을 쓰다보면 항상 행복하게 코드 품질을 관리할 수는 없습니다. 매달 세워놓은 목표를 달성하기 위해서 뼈를 깎는 노력으로 테스트 코드를 작성해야 되고, 당장 기능 수정해서 배포해야 되는데, 작성해 둔 테스트 케이스가 Fail 되어 말썽을 부릴 수도 있습니다. 그렇지만 객관적 기준으로 코드 품질을 관리하다보면 어느샌가 큰 노력없이 좋은 코드를 작성하는 개발자가 되지 않을까 생각해 봅니다. 코드 졸면서 막 짜도 style warning 0건/ 정적분석 오류없음 / 테스트 코드 기본 탑재 뭐 이런 개발자 말입니다 ㅎㅎ 다른 개발자분들은 어떻게 자신이 작성한 코드의 품질을 관리하고 있는지 궁금하네요.알고 계신 좋은 방법이 있다면 언제든지 공유 부탁드리겠습니다~!#사운들리 #개발자 #개발 #인사이트 #조언 #개발후기 #후기
조회수 2758

우아한 설계의 첫걸음, 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를 이용한 우아한 설계가 어디까지 발전할 수 있는지, 그리고 향후 자바스크립트의 행보가 기대됩니다.#조이코퍼레이션 #개발자 #개발팀 #인사이트 #경험공유 #일지
조회수 10787

Next.js 튜토리얼 6편: 서버 사이드

* 이 글은 Next.js의 공식 튜토리얼을 번역한 글입니다.** 오역 및 오탈자가 있을 수 있습니다. 발견하시면 제보해주세요!목차1편: 시작하기 2편: 페이지 이동 3편: 공유 컴포넌트4편: 동적 페이지 5편: 라우트 마스킹6편: 서버 사이드 - 현재 글7편: 데이터 가져오기8편: 컴포넌트 스타일링9편: 배포하기개요이전 편에서는 깔끔한 URL를 생성하는 방법에 대해 배웠습니다. 기본적으로 다음과 같이 생긴 URL를 가질 수 있습니다: http://localhost:3000/p/my-blog-post하지만 이 URL은 클라이언트 사이드 이동 시에만 동작합니다. 페이지를 새로고침하면 404 페이지가 표시됩니다.페이지 디렉토리에 p/my-blog-post를 부르는 실제 페이지가 없기 때문입니다.Next.js 커스텀 서버 API를 이용하여 쉽게 해결할 수 있습니다. 어떻게 구현할 수 있는지 살펴봅시다.설치이번 장에서는 간단한 Next.js 애플리케이션이 필요합니다. 다음의 샘플 애플리케이션을 다운받아주세요:아래의 명령어로 실행시킬 수 있습니다:이제 http://localhost:3000로 이동하여 애플리케이션에 접근할 수 있습니다.커스텀 서버 생성하기Express를 사용하여 애플리케이션의 커스텀 서버를 생성할 예정입니다. 간단합니다.먼저 애플리케이션에 Express를 추가해주세요:npm install —save express애플리케이션에 server.js 파일을 생성하고 다음과 같이 작성해주세요:npm dev 스크립트를 수정해주세요:이제 npm run dev 명령어로 애플리케이션을 다시 실행시켜주세요.어떤 일이 일어날까요?- 깔끔한 URL을 지원하는 서버 사이드를 추가할 것이다.- 애플리케이션이 동작하지만 서버 사이드의 깔끔한 URL은 동작하지 않는다.- "Express와 Next.js은 함께 동작할 수 없습니다"라는 에러가 발생할 것이다.- "Next.js 커스텀 서버는 프로덕션에서만 동작합니다"라는 에러가 발생할 것이다.커스텀 라우트 생성하기경험했다시피 구현한 커스텀 서버가 "next" 바이너리 명령어와 비슷하기 때문에 이전과 비슷하게 동작합니다.블로그 포스트 URL과 매치되는 커스텀 라우트를 추가해봅시다.새로운 라우트가 있는 server.js는 다음과 같습니다:다음의 코드를 살펴봅시다:단순히 기존 "/post" 페이지에 커스텀 라우트를 매핑했습니다. 또한 쿼리 매개 변수도 매핑했습니다.이게 끝입니다.애플리케이션을 다시 실행시키고 다음 페이지로 이동해주세요:http://localhost:3000/p/hello-nextjs더이상 404 페이지가 보이지 않습니다. 이제 실제 페이지를 볼 수 있습니다.하지만 작은 문제가 있습니다. 뭔지 아시나요?- 아무런 문제가 없다.- 클라이언트 사이드에서 랜더링된 제목과 서버 사이드에서 랜더링된 제목이 다르다.- 서버 사이드에서 랜더링된 페이지는 콘솔에 에러를 발생시킨다.- 클라이언트 사이드에서 랜더링된 페이지는 콘솔에 에러를 발생시킨다.URL에 있는 정보/post 페이지는 쿼리 문자열 파라미터 title을 통해 제목을 가져옵니다. 클라이언트 사이드 라우팅에서는 쉽게 URL 마스킹을 통해 적당한 값을 전달할 수 있습니다. (Link의 as prop을 통해)서버 라우트에서는 URL에 있는 블로그 포스트 ID만을 가지기 때문에 제목이 없습니다. 이 경우 ID를 서버 사이드 쿼리 문자열 파라미터로 설정합니다.다음과 같은 라우트 정의를 볼 수 있습니다:문제가 발생하지만 실제로는 ID를 사용하여 클라이언트와 서버 모두 서버에서 데이터를 가져오므로 이는 별로 문제가 되지 않습니다.그래서 ID만 필요합니다.마무리Next.js의 커스텀 서버 API를 사용한 라우트를 간단히 구현해보았습니다. 깔끔한 URL을 지원하는 서버 사이드를 추가했습니다. 원하는 대로 여러 라우트를 구현할 수 있습니다.Express를 사용하는 것에 국한되지 않습니다. 원하는 Node.js 서버 프레임워크를 사용할 수 있습니다. 커스텀 서버 API에 대한 Next.js 문서를 볼 수 있습니다.#트레바리 #개발자 #안드로이드 #앱개발 #Next.js #백엔드 #인사이트 #경험공유
조회수 1265

A씨의 일주일

스포카 개발팀 문성원입니다. 오늘은 스포카 개발팀의 가공의 개발자 A씨의 일주일을 통해, 스포카 개발팀에서는 일주일간의 개발 일정을 어떻게 진행하는지 살펴보겠습니다. 평소 스타트업(Startup) 개발팀의 문화에 관심이 있으셨던 분들에게 도움이 되길 바랍니다.월요일오전 10시, A씨는 평소보다 조금 일찍 사무실에 도착했습니다. 매주 월요일은 스포카 전체 미팅이 있는 날이기 때문이죠. 한 주간 각자 진행한 것을 토대로 이번 주에 진행할 일을 대외적으로 공표하는 이 회의에 앞서, 스포카 개발팀은 따로 미팅을 잠깐 가집니다. 그동안 지난 주 개발 사항, 이번 주 구현 목록 등을 트렐로(Trello)를 통해 정리한 뒤, 이를 전체 미팅에서 공유합니다. A씨는 지난 주에 미쳐 다 구현하지 못했던 서버의 몇 가지 기능과 클라이언트 신버전 배포 준비를 하게 되었습니다.정신없이 회의 하고 났더니 벌써 점심시간입니다. 늘 가던 근처 식당에서 즐겁게 점심을 먹고 사무실로 올라온 A씨는 막간을 이용해 간밤에 올라온 스포카 개발 블로그의 원고를 검토합니다. 몇 가지 오탈자와 맞춤법을 지적한 뒤 모두가 지루해할 월요일 오후 1~2시경에 공개하는 것이 목표입니다.올라간 블로그 글을 확인한 뒤에, A씨는 구현해야 할 서버 기능을 살펴보기로 했습니다. 생각보단 많긴 하지만 일주일 안에는 어떻게든 끝낼 수도 있을 것 같은 분량이네요. 우선 트렐로에 올라온 카드의 명세를 토대로 작업해야 할 내용을 체크리스트(Check List)로 정리합니다. 그다음은 모두가 짐작하시듯이 열심히 일합니다. A씨는 프로니까요.어느덧 저녁 시간이 다 되었습니다. 특별히 일이 없는 이상 야근은 하지 않는 주의인 A씨지만, 오늘만큼은 저녁을 먹고 조금 더 남아있기로 합니다. 팀 내에서 진행하고 있는 스터디 때문이죠. 혼자서 읽기는 까다로웠던 책을 다 같이 읽어보니 조금은 이해가 더 되는 느낌이 드네요.화요일A씨는 오전에 작업하던 중 이상한 점을 발견합니다. 구현하기로 한 기능이 기존 기능과 모순이 되기 때문이죠. 이걸 어떻게 해결할까 고민하던 A씨는 다행히 사무실에 남아있던 엔에이블러(Enabler)팀원들과 간단하게 미팅을 합니다. 문제를 설명하고 명세를 다시 확인한 A씨는 작성한 회의록과 함께 배포합니다. 트렐로의 해당 카드에도 첨부하여 나중에 다시 볼 수 있게 하는 것은 기본입니다.뜻하지 않은 문제 때문에 오전을 날려서 기분이 나빠진 A씨지만, 다행히 좋아하는 스파게티를 먹고 기운을 내기로 했습니다. 사무실에 올라와 인터넷 뉴스와 페이스북을 잠시 보던 A씨는 암묵적으로만 정해진 점심시간이 끝나자 바로 작업을 시작합니다. A씨는 프로니까요.그런데 문제가 있습니다. 오전에 배포한 회의록을 읽어 본 다른 팀원들이 이건 다른 문제의 원인이 될 수 있다고 합니다. A씨는 새 기능 추가가 단순히 로직이 아니라 클라이언트 UI를 포함한 대규모 변경이 필요하다는 것을 깨닫습니다. A씨는 새 기능에 대한 대략적인 스케치를 발사믹 목업(Balsamiq Mockup)으로 마친 뒤 이를 다시 배포합니다. 또한, 관련된 카드에 설명도 잊지 않습니다.수요일매주 수요일 오전에 스포카 개발팀은 짧은 미팅을 합니다. 금주의 진행사항 중 변경사항이나 도움이 필요한 내용을 공유하는 자리인데요. 여기서 A씨는 어제 일을 다시 정리해서 이야기하고, 일정이 지연될 수 있음을 전달합니다. A씨에게 할당된 카드 일부를 다음 주로 미루거나, 좀 한가한 사람에게 나눠주는 형식으로 짐을 던 A씨였지만, 여전히 큰일이 되어버린 기능 변경은 무거운 짐입니다.이런 대량의 작업 때문에 고민하던 A씨에게 같은 팀 B씨가 어떤 라이브러리를 소개해줍니다. A씨는 처음 보는 라이브러리인지라 B씨가 전담해서 가르쳐주는 모양이 되었지만, 생각보다 문제 해결에 큰 도움이 될 것 같습니다. 마침 다음 주에 개발 블로그에 글을 써야 할 당번이 된 A씨는 그 라이브러리에 대해 좀 더 공부해서 쓰기로 정합니다.B씨의 도움 덕에 진행 속도가 붙은 A씨는, 금주 업무 중 하나였던 클라이언트 새 버전의 테스트를 내일부터 진행하기 위해 페이스북이나 인터넷 뉴스도 보지 않은 채 열심히 일합니다. 이런 A씨의 프로다운 모습에 하늘도 감탄했는지, 퇴근 시간인 7시 전에 작업을 끝낸 A씨는 구현된 기능들을 테스트 해 보고 팀의 다른 개발자와 공유하기 위해 github에 만들어진 스포카 서버 코드 저장소에 푸시(Push)합니다.목요일구글 플레이(Google Play)는 하루 정도면 배포가 되니 다행이지만 애플 앱스토어(Apple App Store)는 일주일 정도의 심사기간이 있기 때문에 거절(Reject)당하지 않게 철저히 준비해야 합니다. 그래서 어느 때보다 A씨는 날카로운 눈매로 클라이언트를 점검합니다. 아니나 다를까 메뉴를 이동하다 보니 화면 구성이 흐트러지는 버그가 발견되었습니다. 하지만 프로답게 A씨는 당황하지 않고 재현 조건을 확인한 뒤, 클라이언트 담당자인 C씨에게 알려줍니다. “클라이언트 관련한 버그를 찾았는데, 트렐로를 확인해보세요.”라구요. QA(Quality Assurance) 업무 역시 스포카 개발팀은 직접 처리합니다.밖에 비가 오는지라 피자를 시켜먹은 뒤, 자리에 앉아 잠깐 쉬고 있던 A씨에게 D씨가 다가와서는, “어제 푸시한 소스를 내려받다(Pull)가 충돌(Conflict)이 났는데, 어떻게 병합(Merge)해야 할지 모르겠네요.” 라며 묻습니다. A씨는 D씨와 충돌이 난 소스를 함께 검토하고 문제가 발생하지 않게끔 조정한 뒤 이를 다시 푸시해서 상황을 종료합니다.이러는 사이 C씨가 A씨가 말한 버그를 고쳤다며 다시 확인해보라고 트렐로의 관련 카드를 “테스트” 리스트로 옮깁니다. A씨는 재현된 상황에서 문제 없이 동작하는 것을 확인하고 카드를 “완료” 리스트로 다시 옮깁니다. 이제 클라이언트 앱을 심의 신청하고 어제 구현한 서버 쪽 코드의 개선사항이 있는지 살펴봅니다. 서버는 클라이언트가 앱스토어나 플레이에 준비되는 것을 확인한 뒤, DotCloud에서 제공하는 배포 스크립트를 통해 손쉽게 버전업할 수 있기 때문에 시간이 좀 남아 있습니다. 현재로선 특별히 더 손댈 부분이 없다는 걸 확인한 A씨는 오늘도 즐겁게 퇴근합니다.금요일월요일과 마찬가지로 오늘도 A씨는 평소보다 조금 서둘러서 사무실에 도착했습니다. 오늘은 사내 전체적으로 한 주간 있었던 업무 내용을 간략하게 보고하는 자리가 있습니다. A씨는 이번 주에 맡은 서버 개발이 이러저러해서 이렇고 저렇게 바뀌었다고 설명한 뒤, 앱스토어에 신청되었다는 사실을 공지합니다. 전체 보고가 끝난 뒤엔 개발팀은 따로 남아서 약간 자세하게 금주 작업을 공유하면서 트렐로의 “완료” 상태에 있는 카드들을 정리하는 시간을 갖습니다.점심을 먹고 나서, 이번 주에 더는 급한 일정이 없다는 것을 확인한 A씨는 개발 블로그에 쓸 글을 정리하기 시작합니다. 수요일에 B씨가 알려 준 라이브러리의 사용 방법은 대강 배웠지만, 그것을 남에게 설명할 수 있을 만큼 자세히 알지는 못했기 때문에 A씨는 한동안 공식 문서와 예제 코드들과 씨름합니다. 그래도 어느새 옆에서 거들기 시작한 B씨 덕에 글은 생각보다 순조롭게 마무리되었습니다. 이제 다음 주 월요일까지 퇴고해서 블로그에 공개하기만 하면 되죠.생각보다 오늘 업무를 끝낸 A씨는 친구들과 약속이 있는 홍대로 가기 위해, 7시 정시에 사무실을 떠납니다.#스포카 #개발 #개발자 #개발팀 #개발자의일주일 #개발자의일상 #인사이트 #경험공유
조회수 1429

PyCon2017 첫번째날 후기

아침에 느지막이 일어났다. 어제 회사일로 피곤하기도 했지만 왠지 컨디션이 좋은 상태로 발표를 하러 가야지!라는 생각 때문에 깼던 잠을 다시 청했던것 같다. 일어나 아침식사를 하고 아이 둘과 와이프를 두고 집을 나섰다. 작년 파이콘에는 참가해서 티셔츠만 받고 아이들과 함께 그 옆에 있는 유아교육전을 갔었기에 이번에는 한참 전부터 와이프에게 양해를 구해둔 터였다.코엑스에 도착해서 파이콘 행사장으로 가까이 가면 갈수록 백팩을 메고, 면바지를 입고, 영어 글자가 쓰인 티셔츠를 입은 사람의 비율이 높아지는 것으로 보아 내가 제대로 찾아가고 있구나 라는 생각이 들었다.                                               늦게 왔더니 한산하다.지난번에는 입구에서 에코백과 가방을 나눠줬던 것 같은데 이번에는 2층에서 나눠준다고 한다. 1층이 아무래도 복잡해지니 그런 것 같기도 하고, 2층에서 열리는 이벤트들에도 좀 더 관심을 가져줬으면 하는 것 같기도 하다. 우선 스피커 옷을 받고 싶어서 (솔직히 입고 다니고 싶어서) 2층에 있는 스피커방에 들어갔다.                         허락 받지 않고 사진찍기가 좀 그래서 옆방을 찍었다.첫 번째 키노트는 놓쳤지만 두 번째 키노트는 꼭 듣고 싶었기에 간단히 인사만 하고 티셔츠를 들고 나왔다. (외국에서 오신 연사분과 영어로 대화를 나누고 있어서 자리를 피한것은 아니다.) 나가는 길에 보니 영코더(초등학교 5학년 부터 고등학생 까지 파이썬 교육을 하는 프로그램)을 진행하고 있었다. 의미있는 시도를 하고 있다는 생각이 들었다.                          이 친구들 2년 뒤에 나보다 잘할지도 모른다.키노트 발표장에 갔더니 아웃사이더님이 뒤에 서 게셨다. 지난 파이콘 때 뵙고 이번에 다시 뵈었으니 파이콘이 사람들을 이어주는 역할을 하는구나 싶었다.키노트에서는 현우 님의 노잼, 빅잼 발표 분석 이야기를 들을 수 있었다. 그리고 발표를 통해 괜히 이것저것 알려줘야만 할 것 같아 발표가 부담스러워지는 것 같다는 이야기를 들었다. 나 또한 뭔가 하나라도 지식을 전달해야 한다는 압박감을 느끼고 있었던 터라 현우 님의 키노트 발표를 듣고 나니 좀 더 오늘을 즐겨야겠다는 생각이 들었다.                                              오늘은 재미있었습니다!현우님 키노트를 듣고 같은 시간(1시)에 발표를 하시는 경업님과 이한님 그리고 내일 발표이신 대명님, 파이콘 준비위원회를 하고 계신 연태님과 함께 식사를 하러 갔다. 가는 길에 두숟갈 스터디를 함께 하고 계신 현주님과 희진 님도 함께했다. 사실 이번에는 발표자도 티켓을 사야 한다고 해서 조금 삐져 있었는데 양일 점심 쿠폰을 주신다고 해서 삐진 마음이 눈 녹듯이 사라졌다.                                                  부담 부담식사를 하고 발표를 할 101방으로 들어가 봤다. 아직 아무도 없는 방이라 그런지 괜히 긴장감이 더 생기는 느낌이다. 발표 자료를 열어 처음부터 끝까지를 한번 넘겨 보고 다시 닫았다. 처음에는 가장 첫 발표라 불만이었는데 생각해보니 발표를 빨리 마치고 즐기는 게 훨씬 좋겠다는 생각이 들었다. 발표 자료를 다듬을까 하다가 집중이 되지 않아 밖으로 나갔다. “열린 공간” 현황판에 충동적으로 포스트잇을 하나 붙이고 왔다. 어차피 발표는 나중에 온라인으로도 볼 수 있으니까 사람들과 이야기를 나눠 봐야 겠다 싶었다. (내 발표에는 사람이 많이 왔으면 하면서도, 다른 사람의 발표는 온라인으로 보겠다는 이기적인 생각이라니..)                                            진짜 궁금하긴 합니다다시 발표장으로 돌아왔다. 왠지 모르는 분들은 괜찮은데 아는 분들이 발표장에 와 계시니 괜히 더 불안하다. 다른 분들은 발표자료에 짤방도 많이 넣으셨던데.. 나는 짤방도 없는 노잼 발표인데.. 어찌해야 하나. 하지만 시간은 다가오고 발표를 시작했다.                                            얼굴이 반짝 반짝리허설을 할 때 22분 정도 시간이 걸렸던 터라 조금 당겨서 진행을 했더니 발표를 거의 20분에 맞춰서 끝냈다. 그 뒤에 몇몇 분이 오셔서 질문을 해주셨다. 어리버리 대답을 한 것 같다. 여하튼 내 발표를 찾아오신 분들께 도움이 되었기를. 그리고 앞으로 좀 더 정확한 계산을 하시기를.대단히 발표 준비를 많이 하지도 못하면서 마음에 부담만 쌓아두고 있는 상황이었는데, 발표가 끝나니 아주 홀가분한 마음이 되었다. 발표장을 나가서 이제 부스를 돌아보기 시작했다. 매해 참여해 주고 계신 스마트스터디도 보이고 (정말 안 받고 싶은 ‘기술부채’도 받고 말았다.) 쿠팡, 레진 등 친숙한 회사들이 많이 보였다. 내년에는 우리 회사도 돈을 많이 벌어 여기에 부스를 내고 재미있는 이벤트를 하면 좋겠다는 생각이 들었다.부스를 돌아다니다가 이제 파이콘의 명물이 된 내 이름 찾기를 시작했다. 이름을 찾기가 쉽지가 않다. 매년 참여자가 늘어나서 올해는 거의 2000명에 다다른다고 하니 파이썬 커뮤니티의 성장이 놀랍다. 10년 전에 파이썬을 쓸 때에는 그리고 첫 번째 한국 파이콘이 열릴 때만 해도 꽤 마이너 한 느낌이었는데, 이제 주류가 된 것 같아 내 마음이 다 뿌듯하다. (그리고 내 밥줄이 이어질 수 있는 것 같아 역시 기쁘다)                                          어디 한 번 찾아보시라다음으로는 박영우님의 "Django admin site를 커스텀하여 적극적으로 활용하기” 발표를 들으러 갔다. (짧은 발표를 좋아한다.) 알고 있었던 것도 있었지만 커스텀이 가능한지 몰랐던 것들도 있어서 몇 개의 기능들을 킵해 두었다. 역시 컨퍼런스에 오면 내게 필요한 ‘새로운 것’에 대한 실마리를 주워가는 재미가 있다.                                     익숙하다고 생각했지만 모르는 것이 많다4시가 되어 OST(Open Space Talk)를 하기로 한 208B 방으로 조금 일찍 갔다. 주제가 뭐였는지는 잘 모르겠는데 주식 투자, Tensor Flow, 비트코인, 머신러닝 등등의 이야기들이 오가고 있었다. 4시가 되어 내가 정한 주제에 대해 관심 있는 사람들이 모였다. 괜히 모일 사람도 없는데 큰방을 잡은 것이 아닐까 하고 생각하고 있었는데, 생각보다 많은 분들이 오셨다.각 회사들이 어떤 도구를 사용하는지 설문조사도 해보고, 또 어떤 개발 방법론을 사용하는지, 코드 리뷰, QA는 어떻게 하고 있는지에 대한 이야기를 나눴다. 다양한 회사에서 다양한 일을 하는 사람들이 모여 있다 보니 생각보다 꽤 재미있게 논의가 진행되었다. 사실 내가 뭔가 말을 많이 해야 할 줄 알았는데, 이야기하고 싶은 분들이 많이 있어서 진행을 하는 역할만 하면 되었다. 마지막으로는 “우리 회사에서 잘 사용하고 있어서 다른 회사에도 추천해 주고 싶은 것”을 주제로 몇 가지 추천을 받은 것도 재미가 있었다.                                  열심히 오간 대화를 적어두긴 했다5시에 OST를 마치고는 바로 집으로 돌아왔다. 오늘 저녁에 아이들을 잘 돌보고 집 청소도 열심히 해두어야 내일 파이콘에 참여할 수 있기 때문이다. 기대된다. 내일의 파이콘도.그리고 정말 감사드린다. 파이콘을 준비해주시고 운영해주고 계신 많은 분들께.                                                   #8퍼센트 #에잇퍼센트 #이벤트 #참가후기 #파이콘 #개발자 #개발 #파이썬 #Python #Pycon
조회수 2489

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의 시작이며, 출발이다.
조회수 1706

잔디 팀에서 가장 자유로운 영혼을 가진 그녀! 고객 경험(CX)팀의 Soo를 만나다

맛있는 인터뷰: 고객 경험(Customer Experience) 매니저 Soo ▲ 점심엔 역시 맥주 한 잔이죠? 알코올과 함께 하는 맛있는 인터뷰 먼저 인터뷰를 제안해 온 사람은 처음이다. 본인 소개를 부탁한다Soo(이하 ‘S’): 반갑다! 잔디 팀에서 고객 경험: CX(Customer Experience) 업무를 담당하고 있는 Soo라고 한다. 고객 응대뿐 만 아니라 서비스 번역이나 비즈니스 팀에서 사용되는 제품 메뉴얼 작성, 영상 작업 등 고객 경험에 연관된 다양한 업무를 수행하고 있다. 하는 일이 꽤 많은 것 같은데?S: 잔디 팀원이라면 당연히 이 정도는! 타이 음식은 오랜만이다. 이 곳을 오게 된 이유가 있다면?S: 우리가 온 곳은 망고플레이트에서도 평이 좋은 태국 음식점 ‘알로이 타이(Aloy Thai)‘다. 개인적으로 동남아 음식을 너무 좋아한다. 미국에 있을 때 먹었던 쌀국수 맛이 늘 그리웠는데.. 수소문 끝에 알아낸 인생 맛집이다. 선릉역 2번 출구에서 도보 5분 거리에 있다. 정확한 주소는 서울시 강남구 대치동 8… 잠깐! 광고비를 받은 건가? 맛있는 인터뷰는 원칙적으로 협찬을 금지하고 있다S: 무슨 소리. 인생 맛집이라 이렇게라도 알리고 싶었다. 아님 말고..S: ..^^ 음식과 함께 술을 주문한 인터뷰이는 Soo가 처음이다S: 평소 술을 즐기는 편이다. 하지만 오해하지 않았으면 좋겠다. 술을 좋아하는 거지 잘 마시는 건 아니다. 가끔 집에서 혼술하는 것도 좋아한다. 술 말고 좋아하는 건?S: 게임을 좋아한다. 미국에 있을 때는 집에서 혼자 농구게임을 엄청 많이 했고, 친구들과 철권을 즐겼다. 한국에서는 롤을 무척이나 많이 했다. 아침부터 새벽까지 랭겜을 돌리곤 했다. 티어가…?S: 그것은 비밀이다. (웃음) 술, 게임, 쌀국수까지. Soo의 미국 생활이 진심 궁금하다S: 남들과 크게 다르지 않다. 중학교를 제외한 학창 시절을 모두 미국에서 보냈다. 한국에서 이렇게 오래 지내보는 건 처음이다. 잔디 팀에 조인하면서 한국 생활을 시작한 격인데 처음엔 무척 낯설었다. 2년 지난 지금은 꽤 괜찮아졌다. ▲ 미국에 있을 당시의 Soo 모습. 왼쪽에서 화사하게 웃고 있는 사람이 Soo다.어떻게 잔디 팀을 알고 지원했는지 궁금하다S: 대기업에서 인턴을 해보니 수직적인 기업 문화가 맞지 않았다. 때마침 지인에게 잔디 팀을 추천 받게 되어 입사하게 되었다. 스타트업은 뭔가 열정이 넘치다 못해 폭발하는 사람만 가는 곳이라 생각했는데, 지금은 그 ‘스타트업’ 중 한 곳에서 일하고 있다. 묘한 감정이 든다. (웃음) 잔디 팀의 업무 문화는 마음에 드는가?S: 잔디 팀에서 일하면서 가장 좋은 점은 내 직무에서 풀어야 할 숙제를 스스로 한다는 점이다. 개인적으로 가장 재미있고 신나는 경험이다. 너무 교과서적인 대답이다. 신박한 답변을 원한다S: 역으로 질문하고 싶다. 잔디 팀의 업무 문화가 마음에 드는가? 소중한 말씀 감사합니다..S: ^^ 주말에는 무엇을 하고 지내는가?S: 보통 술을 마신다. (웃음) 아니면 집에서 영화를 본다. 뭔가 #술 #알코올 #혼술 #집스타그램 해시태그를 붙여야 할 것 같은 인터뷰다. 다른 이야기를 해보자!S: 언제든지! 잔디 표지모델은 어떻게 하게 되었는지?S: Product 팀의 DL이 부탁해서 촬영하게 되었다. 사진을 본 내 친구들이 이게 뭐냐며 비웃었던 게 가장 기억에 남는다. DL이 보정을 해준다고 했는데 실제로는 목주름만 보정해줬다. 뭔가 슬펐다. ▲ 잔디 홍보 자료에 자주 등장한 Soo 일하는 자리를 보면 아기자기한 물건들이 많다. 애착이 가는 물건이 있다면?S: 내가 기르고 있는 식물이다. 귀엽기도 하고, 물만 줘도 조용히 잘 자라는 녀석들이 기특하다. 펫을 기른다는 기분으로 정성스레 기르고 있다. 이름도 지어주었다. 이름이?S: 밝힐 수 없다. 맛있는 인터뷰를 통해 공개하기엔 부적절한 이름이다. (웃음) 대학교에서 신문방송학을 전공했다고 들었다. 전공과 무관한 고객 경험 업무를 하게 된 계기가?S: 고객 응대만을 하는 CS(Customer Service)가 아니라 총체적인 ‘고객 경험’에 참여하는 CX 라는 점이 끌렸다. 제품과 고객을 잇는 브릿지 역할을 한다는 점이 매력적이었고, 잔디를 이용할 때 퍼널(Funnel) 최전방에서 가장 먼저 접하는 사람이 나라는 점도 흥미로웠다. 그리고 주 전공인 영상 제작 업무도 CX 일을 하며 할 수 있어 좋았다. 업무를 하다 보면 재미있는 에피소드가 있을 것 같다S: 연령대가 높은 사용자 중 생각보다 컴퓨터 사용법을 잘 모르는 경우를 종종 볼 수 있다. 그럼에도 불구하고 최근 많은 이슈가 되고 있는 협업 트렌드를 배우고자 열심히 노력하는 모습이 너무 인상적이었다. 더욱 더 도와주고 싶다는 생각이 자연스레 들 정도다. 협업툴에 대한 요구가 많아졌음을 직감하는지?S: 협업툴에 대한 요구도 많아졌지만 그보다 더 피부에 와닿는 변화는 고객의 인식이 확연히 바뀌었다는 점이다. 처음 CX 업무를 시작했을 때 접한 잔디 사용자들은 돈을 주고 서비스를 사용한다는 개념을 생소하게 여겼다. 반면 지금은 다르다. 최근 잔디 도입을 문의하는 고객 대다수는 서비스 요금부터 문의한다. 잔디 도입 문의 어디에 하는 게 효과적인가?S: 잔디 웹사이트 우측 하단에 있는 파란색 버튼을 클릭하거나 도입 문의 폼을 남기면 CX팀과 세일즈 팀이 바로 도움을 드린다. ▲ 인형과 식물이 가득한 Soo의 업무 공간잔디 팀에서 배운 점이 있다면?S: 사람과 소통하는 방법을 가장 많이 배웠다. 아무래도 한국 문화에 익숙하지 않아 ‘한국식 소통 방법’이 낯설었는데 사회 생활을 통해 자연스레 학습할 수 있어 좋았다. 잔디 팀에서의 경험 덕분에 자신감이 생겼다. 다른 곳에 간다고 해도 잘 할 수 있을 것 같다. 첫 직장으로서 잔디 팀의 생활이 만족스럽다는 걸로 들린다S: 물론이다. (웃음) 정말인가?S: 물론이다. 건배나 하자. 태국 음식엔 역시 맥주가 짱이다. (웃음) 어떤 꿈을 가졌는지 궁금하다S: 사실 무엇을 해야할 지 정한 건 없다. 막연하지만 나만의 것을 해보고 싶다. 사무실에 앉아서 일하는 것보단 무언가 발로 뛰며 성취하는 경험을 해보고 싶다. 이전 인터뷰이였던 잔디 HR 담당자 Amy의 질문이다. 자신의 인생에서 가장 행복했던 순간은?S: 행복했던 순간이 너무 많아 한 가지만 고르기 힘들다. 뭔가 성취감을 느꼈을 때 행복을 느끼는 것 같다. 그 외에는 맥주 한잔하면서 집에서 뒹굴뒹굴할 때가 행복하다. 일상의 소소한 것에서 느끼는 즐거움이 진짜 행복은 아닐지 생각해본다. 다음 인터뷰이를 위한 질문을 부탁한다S: 올해 꼭 이루고 싶은 목표는? ▲ 술과 음식으로 점철된 맛있는 인터뷰가 열린 선릉역 맛집 ‘알로이 타이’마지막 질문이다. 왜 맛있는 인터뷰가 하고 싶었는지?S: 잔디 팀과 함께 한 시간이 어언 2년이다. 팀의 일원으로서 잔디 이름을 가진 어딘가에 내 흔적을 남기고 싶었다. 맛있는 인터뷰가 그 흔적으로 적합하다고 생각하는가?S: 물론이다. 맛있는 인터뷰를 보면 그간 잔디 팀과 함께 했던, 그리고 함께 한 멤버들의 모습을 꺼내볼 수 있다. 일종의 추억 보관함이라고 해야할까? 내 이야기도 잔디 팀의 누군가에게 추억이 될 거라 생각해 내 이름을 꼭 남기고 싶었다. 인터뷰 해줘서 너무 고맙다. (웃음) #토스랩 #잔디 #JANDI #팀원소개 #인터뷰 #기업문화 #조직문화 #팀원자랑
조회수 844

비트윈의 HBase 스키마 해부 - VCNC Engineering Blog

비트윈에서는 HBase를 메인 데이터베이스로 이용하고 있습니다. 유저 및 커플에 대한 정보와 커플들이 주고받은 메시지, 업로드한 사진 정보, 메모, 기념일, 캘린더 등 서비스에서 만들어지는 다양한 데이터를 HBase에 저장합니다. HBase는 일반적인 NoSQL과 마찬가지로 스키마를 미리 정의하지 않습니다. 대신 주어진 API를 이용해 데이터를 넣기만 하면 그대로 저장되는 성질을 가지고 있습니다. 이런 점은 데이터의 구조가 바뀔 때 별다른 스키마 변경이 필요 없다는 등의 장점으로 설명되곤 하지만, 개발을 쉽게 하기 위해서는 데이터를 저장하는데 어느 정도의 규칙이 필요합니다. 이 글에서는 비트윈이 데이터를 어떤 구조로 HBase에 저장하고 있는지에 대해서 이야기해 보고자 합니다.비트윈에서 HBase에 데이터를 저장하는 방법Thrift를 이용해 데이터 저장: Apache Thrift는 자체적으로 정의된 문법을 통해 데이터 구조를 정의하고 이를 직렬화/역직렬화 시킬 수 있는 기능을 제공합니다. 비트윈에서는 서버와 클라이언트가 통신하기 위해 Thrift를 이용할 뿐만 아니라 HBase에 저장할 데이터를 정의하고 데이터 저장 시 직렬화를 위해 Thrift를 이용합니다.하나의 Row에 여러 Column을 트리 형태로 저장: HBase는 Column-Oriented NoSQL로 분류되며 하나의 Row에 많은 수의 Column을 저장할 수 있습니다. 비트윈에서는 Column Qualifier를 잘 정의하여 한 Row에 여러 Column을 논리적으로 트리 형태로 저장하고 있습니다.추상화된 라이브러리를 통해 데이터에 접근: 비트윈에서는 HBase 클라이언트 라이브러리를 직접 사용하는 것이 아니라 이를 래핑한 Datastore라는 라이브러리를 구현하여 이를 이용해 HBase의 데이터에 접근합니다. GAE의 Datastore와 인터페이스가 유사하며 실제 저장된 데이터들을 부모-자식 관계로 접근할 수 있게 해줍니다.트랜잭션을 걸고 데이터에 접근: HBase는 일반적인 NoSQL과 마찬가지로 트랜잭션을 제공하지 않지만 비트윈에서는 자체적으로 제작한 트랜잭션 라이브러리인 Haeinsa를 이용하여 Multi-Row ACID 트랜잭션을 걸고 있습니다. Haeinsa 덕분에 성능 하락 없이도 데이터 무결성을 유지하고 있습니다.Secondary Index를 직접 구현: HBase에서는 데이터를 Row Key와 Column Qualifier를 사전식 순서(lexicographical order)로 정렬하여 저장하며 정렬 순서대로 Scan을 하거나 바로 임의 접근할 수 있습니다. 하지만 비트윈의 어떤 데이터들은 하나의 Key로 정렬되는 것으로는 충분하지 않고 Secondary Index가 필요한 경우가 있는데, HBase는 이런 기능을 제공하지 않고 있습니다. 비트윈에서는 Datastore 라이브러리에 구현한 Trigger을 이용하여 매우 간단한 형태의 Secondary Index를 만들었습니다.비트윈 HBase 데이터 구조 해부페이스북의 메시징 시스템에 관해 소개된 글이나, GAE의 Datastore에 저장되는 구조를 설명한 글을 통해 HBase에 어떤 구조로 데이터를 저장할지 아이디어를 얻을 수 있습니다. 비트윈에서는 이 글과는 약간 다른 방법으로 HBase에 데이터를 저장합니다. 이에 대해 자세히 알아보겠습니다.전반적인 구조비트윈에서는 데이터를 종류별로 테이블에 나누어 저장하고 있습니다. 커플과 관련된 정보는 커플 테이블에, 유저에 대한 정보는 유저 테이블에 나누어 저장합니다.각 객체와 관련된 정보는 각각의 HBase 테이블에 저장됩니다.또한, 관련된 데이터를 하나의 Row에 모아 저장합니다. 특정 커플과 관련된 사진, 메모, 사진과 메모에 달린 댓글, 기념일 등의 데이터는 해당 커플과 관련된 하나의 Row에 저장됩니다. Haeinsa를 위한 Lock Column Family를 제외하면, 데이터를 저장하기 위한 용도로는 단 하나의 Column Family만 만들어 사용하고 있습니다.각 객체의 정보와 자식 객체들은 같은 Row에 저장됩니다.또한, 데이터는 기본적으로 하나의 Column Family에 저장됩니다.이렇게 한 테이블에 같은 종류의 데이터를 모아 저장하게 되면 Region Split하는 것이 쉬워집니다. HBase는 특정 테이블을 연속된 Row들의 집합인 Region으로 나누고 이 Region들을 여러 Region 서버에 할당하는 방식으로 부하를 분산합니다. 테이블을 Region으로 나눌 때 각 Region이 받는 부하를 고려해야 하므로 각 Row가 받는 부하가 전체적으로 공평해야 Region Split 정책을 세우기가 쉽습니다. 비트윈의 경우 커플과 관련된 데이터인 사진이나 메모를 올리는 것보다는 유저와 관련된 데이터인 메시지를 추가하는 트래픽이 훨씬 많은데, 한 테이블에 커플 Row와 유저 Row가 섞여 있다면 각 Row가 받는 부하가 천차만별이 되어 Region Split 정책을 세우기가 복잡해집니다. RegionSplitPolicy를 구현하여 Region Split 정책을 잘 정의한다면 가능은 하지만 좀 더 쉬운 방법을 택했습니다.또한, 한 Row에 관련된 정보를 모아서 저장하면 성능상 이점이 있습니다. 기본적으로 한 커플에 대한 데이터들은 하나의 클라이언트 요청을 처리하는 동안 함께 접근되는 경우가 많습니다. HBase는 같은 Row에 대한 연산을 묶어 한 번에 실행시킬 수 있으므로 이 점을 잘 이용하면 성능상 이득을 얻을 수 있습니다. 비트윈의 데이터 구조처럼 특정 Row에 수많은 Column이 저장되고 같은 Row의 Column들에 함께 접근하는 경우가 많도록 설계되어 있다면 성능 향상을 기대할 수 있습니다. 특히 Haeinsa는 한 트랜잭션에 같은 Row에 대한 연산은 커밋시 한 번의 RPC로 묶어 처리하므로 RPC에 드는 비용을 최소화합니다. 실제 비트윈에서 가장 많이 일어나는 연산인 메시지 추가 연산은 그냥 HBase API를 이용하여 구현하는 것보다 Haeinsa Transaction API를 이용해 구현하는 것이 오히려 성능이 좋습니다.Column Qualifier의 구조비트윈은 커플들이 올린 사진 정보들을 저장하며, 또 사진들에 달리는 댓글 정보들도 저장합니다. 한 커플을 Root라고 생각하고 커플 밑에 달린 사진들을 커플의 자식 데이터, 또 사진 밑에 달린 댓글들을 사진의 자식 데이터라고 생각한다면, 비트윈의 데이터들을 논리적으로 트리 형태로 생각할 수 있습니다. 비트윈 개발팀은 Column Qualifier를 잘 정의하여 실제로 HBase에 저장할 때에도 데이터가 트리 형태로 저장되도록 설계하였습니다. 이렇게 트리 형태로 저장하기 위한 Key구조에 대해 자세히 알아보겠습니다.Column Qualifier를 설계할 때 성능을 위해 몇 가지 사항들을 고려해야 합니다. HBase에서는 한 Row에 여러 Column이 들어갈 수 있으며 Column들은 Column Qualifier로 정렬되어 저장됩니다. ColumnRangeFilter를 이용하면 Column에 대해 정렬 순서로 Scan연산이 가능합니다. 이 때 원하는 데이터를 순서대로 읽어야 하는 경우가 있는데 이를 위해 Scan시, 최대한 Sequential Read를 할 수 있도록 설계해야 합니다. 또한, HBase에서 데이터를 읽어올 때, 실제로 데이터를 읽어오는 단위인 Block에 대해 캐시를 하는데 이를 Block Cache라고 합니다. 실제로 같이 접근하는 경우가 빈번한 데이터들이 최대한 근접한 곳에 저장되도록 설계해야 Block Cache의 도움을 받을 수 있습니다.비트윈에서는 특정 커플의 사진이나 이벤트를 가져오는 등의 특정 타입으로 자식 데이터를 Scan해야하는 경우가 많습니다. 따라서 특정 타입의 데이터를 연속하게 저장하여 최대한 Sequential Read가 일어나도록 해야 합니다. 이 때문에 Column Qualifier가 가리키는 데이터의 타입을 맨 앞에 배치하여 같은 타입의 자식 데이터들끼리 연속하여 저장되도록 하였습니다. 만약 가리키는 데이터의 타입과 아이디가 Parent 정보 이후에 붙게 되면 사진 사이사이에 각 사진의 댓글 데이터가 끼어 저장됩니다. 이렇게 되면 사진들에 대한 데이터를 Scan시, 중간중간 저장된 댓글 데이터들 때문에 완벽한 Sequential Read가 일어나지 않게 되어 비효율적입니다.이렇게 특정 타입의 자식들을 연속하게 모아 저장하는 묶음을 컬렉션이라고 합니다. 컬렉션에는 컬렉션에 저장된 자식들의 개수나 새로운 자식을 추가할 때 발급할 아이디 등을 저장하는 Metadata가 있습니다. 이 Metadata도 특정 Column에 저장되므로 Metadata를 위한 Column Qualifier가 존재합니다. 이를 위해 Column Qualifier에는 Column Qualifier가 자칭하는 데이터가 Metadata인지 표현하는 필드가 있는데, 특이하게도 메타데이터임을 나타내는 값이 1이 아니라 0입니다. 이는 Metadata가 컬렉션의 맨 앞쪽에 위치하도록 하기 위함입니다. 컬렉션을 읽을 때 보통 맨 앞에서부터 읽는 경우가 많고, 동시에 Metadata에도 접근하는 경우가 많은데, 이 데이터가 인접하게 저장되어 있도록 하여 Block Cache 적중이 최대한 일어나도록 한 것입니다.Datastore 인터페이스비트윈에서는 이와 같은 데이터 구조에 접근하기 위해 Datastore라는 라이브러리를 구현하여 이를 이용하고 있습니다. HBase API를 그대로 이용하는 것보다 좀 더 쉽게 데이터에 접근할 수 있습니다. GAE의 Datastore와 같은 이름인데, 실제 인터페이스도 매우 유사합니다. 이 라이브러리의 인터페이스에 대해 간단히 알아보겠습니다.Key는 Datastore에서 HBase에 저장된 특정 데이터를 지칭하기 위한 클래스입니다. 논리적으로 트리 형태로 저장된 데이터 구조를 위해 부모 자식 관계를 이용하여 만들어 집니다.Key parentKey = new Key(MType.T_RELATIONSHIP, relId); Key photoKey = new Key(parentKey, MType.T_PHOTO, photoId); // 특정 커플 밑에 달린 사진에 대한 키 Datastore는 Key를 이용해 Row Key와 Column Qualifier를 만들어 낼 수 있습니다. Datastore는 이 정보를 바탕으로 HBase에 새로운 데이터를 저장하거나 저장된 데이터에 접근할 수 있는 메서드를 제공합니다. 아래 코드에서 MUser 클래스는 Thrift로 정의하여 자동 생성된 클래스이며, Datastore에서는 이 객체를 직렬화 하여 HBase에 저장합니다.MUser user = new MUser(); user.setNickname("Alice"); user.setGender(Gender.FEMALE); user.setStatus("Hello World!"); Key userKey = new Key(MType.T_USER, userId); getDatastore().put(userKey, user); user = getDatastore().get(userKey); getDatastore().delete(userKey); 또한, Datastore는 Key를 범위로 하여 Scan연산이 할 수 있도록 인터페이스를 제공합니다. Java에서 제공하는 Try-with-resource문을 이용하여 ResultScanner를 반드시 닫을 수 있도록 하고 있습니다. 내부적으로 일단 특정 크기만큼 배치로 가져오고 더 필요한 경우 더 가져오는 식으로 구현되어 있습니다.try (CloseableIterable> entries = getDatastore().subSibling(fromKey, fromInclusive, toKey, toInclusive)) { for (KeyValue entry : entries) { // do something } } Secondary Index 구현 방법HBase는 데이터를 Row Key나 Column Qualifier로 정렬하여 저장합니다. 이 순서로만 Sequential Read를 할 수 있으며 Key값을 통해 특정 데이터를 바로 임의 접근할 수 있습니다. 비트윈에서는 특정 달에 해당하는 이벤트들을 읽어오거나 특정 날짜의 사진들의 리스트를 조회하는 등 id 순서가 아니라 특정 값을 가지는 데이터를 순서대로 접근해야 하는 경우가 있습니다. 이럴 때에도 효율적으로 데이터에 접근하기 위해서는 id로 정렬된 것 외에 특정 값으로 데이터를 정렬할 수 있어야 합니다. 하지만 HBase에서는 이와 같은 Secondary Index 같은 기능을 제공하지 않습니다. 비트윈 개발팀은 이에 굴하지 않고 Secondary Index를 간단한 방법으로 구현하여 사용하고 있습니다.구현을 간단히 하기 위해 Secondary Index를 다른 데이터들과 마찬가지로 특정 타입의 데이터로 취급하여 구현하였습니다. 따라서 Index에 대해서도 Column Qualifier가 발급되며, 이때, Index에 해당하는 id를 잘 정의하여 원하는 순서의 Index를 만듭니다. 이런 식으로 원하는 순서로 데이터를 정렬하여 저장할 수 있으며 이 인덱스를 통해 특정 필드의 값의 순서대로 데이터를 조회하거나 특정 값을 가지는 데이터에 바로 임의 접근할 수 있습니다. 또한, Index에 실제 데이터를 그대로 복사하여 저장하여 Clustered Index처럼 동작하도록 하거나, Reference만 저장하여 Non-Clustered Index와 같이 동작하게 할 수도 있습니다. Datastore 라이브러리에는 특정 데이터가 추가, 삭제, 수정할 때 특정 코드를 실행할 수 있도록 Trigger 기능이 구현되어 있는데, 이를 통해 Index를 업데이트합니다. 데이터의 변경하는 연산과 Index를 업데이트하는 연산이 하나의 Haeinsa 트랜잭션을 통해 원자적으로 일어나므로 데이터의 무결성이 보장됩니다.못다 한 이야기각 테이블의 특정 Row의 Column들에 대한 Column Qualifier외에도 Row에 대한 Row Key를 정의 해야 합니다. 비트윈에서는 각 Row가 표현하는 Root객체에 대한 아이디를 그대로 Row Key로 이용합니다. 새로운 Root객체가 추가될 때 발급되는 아이디는 랜덤하게 생성하여 객체가 여러 Region 서버에 잘 분산될 수 있도록 하였습니다. 만약 Row Key를 연속하게 발급한다면 특정 Region 서버로 연산이 몰리게 되어 성능 확장에 어려움이 생길 수 있습니다.데이터를 저장할 때 Thrift를 이용하고 있는데, Thrift 때문에 생기는 문제가 있습니다. 비트윈에서 서버를 업데이트할 때 서비스 중지 시간을 최소화하기 위해 롤링 업데이트를 합니다. Thrift 객체에 새로운 필드가 생기는 경우, 롤링 업데이트 중간에는 일부 서버에만 새로운 Thift가 적용되어 있을 수 있습니다. 업데이트된 서버가 새로운 필드에 값을 넣어 저장했는데, 아직 업데이트가 안 된 서버가 이 데이터를 읽은 후 데이터를 다시 저장한다면 새로운 필드에 저장된 값이 사라지게 됩니다. Google Protocol Buffer의 경우, 다시 직렬화 할 때 정의되지 않은 필드도 처리해주기 때문에 문제가 없지만, Thrift의 경우에는 그렇지 않습니다. 비트윈에서는 새로운 Thrift를 적용한 과거 버전의 서버를 먼저 배포한 후, 업데이트된 서버를 다시 롤링 업데이트를 하는 식으로 이 문제를 해결하고 있습니다.
조회수 2583

WHATAP Python APM 이야기...

백엔드 서비스로 Python을 사용한다면 만나게될 상황을보다 쉽게 해결하기 위한 와탭의 Python APM, 개발하게 된 이유입니다.파이썬은 배우기 쉽고, 어디서나 실행되는 언어라고 이야기되며, 인기도 높습니다. 생각보다 많은 곳에서 배울 수 있으며, 혼자 배우기도 좋습니다. 그런데, 이 규모가 확대되어서 스타트업의 경우에 Python을 사용하여 백엔드 서비스를 개발하는 경우를 찾는 것이 어렵지 않습니다. 또는, 수학적인 알고리즘이거나 ML(머신러닝)과 같은 영역이거나 블록체인등에서 Python을 사용하여 API geteway나 broker를 사용하는 경우에 한정한 상황을 고려하고 있습니다.Python으로 백엔드 서비스를 만들 때에는 성능과 설계 부분에 대해서 많은 걱정을 하게 됩니다. 이런 상황을 만나게되는 개발자는 여러가지 문제를 만나게 됩니다. 그 문제에 와탭은 집중합니다.!와탭은 백엔드 서비스를 Python으로 개발시에 만나게 되는 상황을 가장 최우선으로 생각하게 되었습니다.Python으로 '설계', '개발'되고 '테스트'된 후에 '배포'되는 상황에서 서비스의 불완전함과 속도상의 문제, 리소스의 불협화음등을 '유지보수'하는 단계를 '성능 튜닝'이라고 정의하고, 이를 고려한 상황을 보다 단순화하는 것이라고 생각하게 되었습니다. 이를 어떻게 처리하느냐가 와탭 Python의 핵심 가치라고 생각하였습니다.----- 이 부분은 Python korea 페이스북에서 '배권한'님이 지적하신 내용을 기반으로 일부 첨언되었습니다.----- python native 개발자들에게는 불필요한 설명에 해당됩니다.파이썬은 분명, 읽기 쉽고 사용하기 쉬운 것은 장점이며, 라즈베리파이 위에서 동작되는 기민함은 정말 매력적입니다. <- 원래 문장.(* 현재에는 jvm도 동작합니다. 하지만, 작고 기민하게 다양한 IoT 디바이스에서 폭넓게 활용되는 것은 파이썬의 장점은 분명하지 않나 합니다. 이 부분에 대한 지적이 있어서 첨언합니다. )내부 구성상 비동기식으로 쓰레딩이 아니라, 단일 이벤트 루프를 사용하는 비동기식 작성은 매우 효과적입니다. <- 원래 문장.(* 이 부분도 asyncio나 gevent등에 대한 이야기이고, CPython의 언어 구현상 GIL때문에 쓰레드가 비효율적이라는 이야기를 거론하고 싶었으나, 일반적으로 파이썬에 대한 언어를 사용할때에 대부분 사용하는 이유가 단일 이벤트 루프기반의 비동기식 작성이 매우 일반적으로 사용되기 때문에, 이렇게 서술되었습니다. 하지만, 이런 설명은 백엔드로 Python을 사용하는 경우에 대부분의 프레임웍들에서 처리되고 있기 때문에 서술이 불분명하다는 지적이 있었습니다. 당연, 백엔드 서비스를 개발할때에 사용되는 wsgi interface등에 맞추어서 서술되는 경우에는 이런 설명이 무의미합니다.다만, 이렇게 서술한 이유는 Java를 기반으로 APM이 개발되어졌기 때문에 이 부분에 대한 서술이나 설명이 필요하다고 생각한 저의 과도한 설명이 되겠습니다.이 부분은 Python Native개발자들에게는 불필요한 설명이 되겠습니다. 하지만, 백엔드 서비스를 개발하면서 만나게될 환경에서는 이 부분에 대한 이해가 어느정도 필요하다고 생각되어 서술된 내용이라고 생각해주시면 감사하겠습니다. )----------------------------------------------------------------------------------------------------------------------이 방식은 복잡한 자원 경쟁이나 교착상태를 발생하지 않게 되며, 기본 코딩과 유지보수를 정말 수월하게 만들어 줍니다. 그만큼 일관성이 높은 수학 알고리즘을 구현하는데 매우 적합합니다. 하지만, 냉정하게, 비즈니스 로직이나 분기가 많은 업무 로직에 적합한 언어는 아닙니다.하지만, 수학적 알고리즘 기반의 주요 모듈 위에 데이터베이스가 일부 필요하고, 웹서비스의 형태로 가동되는 구조라면 파이썬은 매우 훌륭한 선택이 되고 있으며, 생각보다 많이 사용됩니다.그런 이유 중의 하나는 파이썬의 멀티패러다임 구성과 같은 구성에서는 자바에서처럼 굳이 프린트를 위해서 객체지향 클래스를 만들 필요 없이 간단한 함수형 스타일도 가능하게 구성이 됩니다. ( 자바 8에서는 이런 함수 기능도 추가되었습니다. )단순한 구조와 방식 때문에 파이썬 개발은 요즘처럼 ML이나 AI 등의 기술적 요소들이 많이 사용되는 환경에서는 매우 효과적입니다. 백엔드 파이썬 개발이 많이 보이게 되는 이유이기도 하죠.또한, 파이썬 개발의 단점이라고 지적되던 문제들도 현재에는 실행 속도 문제는 사실상 큰 문제가 되지 않는 상황입니다. 일례로, 파이파이(PyPY)로 실행된 파이썬 코드는 웬만한 수준의 C 코드보다 빠르게 동작합니다.굳이 더 지적하자면, 모바일 컴퓨팅과 브라우저에 따른 웹 애플리케이션 클라이언트는 굳이 파이썬으로 작성할 필요성을 느끼지 못한다고 이야기하는 정도입니다.하지만, 이런 파이썬 개발에 가장 큰 문제가 있습니다.테스팅 없이는 동작하기 어렵고,실제 동작 환경에서만 등장하는 오류의 발생파이썬의 특성상 동적 입력 형태에 따르는 더 많은 테스팅을 필요로 하고 있으며, 실제 실행시간에만 나타나는 오류를 찾는 것이 가장 큰 문제가 있습니다. 이 부분은 수많은 파이썬 개발자들을 괴롭히고 있습니다.( 단편적으로 파이썬 개발환경이 매우 고도화되어있지 않으며, 파이썬으로 백엔드 서비스를 만들 것이라고 예측하지 못한 점도 있을 것입니다. 앞으로 파이썬 개발이 더 고도화 되기를 기원합니다. )이 가장 큰 문제를 잡기 위해서와탭은 집중하였습니다.파이썬 백엔드 개발 시의 문제 해결!물론, Python도 디버깅에 대한 지원 유틸리티가 존재합니다.pdb라는 파이썬 디버깅 모듈을 통해서 Step over/Step into, 중단점(breakpoint) 설정, 콜 스택 검사, 소스 리스팅, 변수 치환 등을 할 수 있습니다.‘Phthon -m pdb 파이썬 파일. py’의 형태로 디버그 동작 화면에서 세부적인 동작을 트레이스 해보는 방식을 사용하거나, pdb모듈을 import 한 후에 pdb.set_trace()를 중단하고 싶은 부분에 넣어서 사용하는 방식도 사용됩니다. 또한, 디버그 세션을 사용하는 방식이며, PDB를 사용하여 디버깅하는 방식들도 흔하게 사용됩니다.PyCharm, PTVS, Spyder 등의 IDE를 사용해서 디버깅을 하는 방법은 전통적인 개발환경과 동일하게 사용할 수 있습니다.하지만, 이 방식들은 백엔드 서비스에는 맞지 않게 되며 개발자들은 백엔드 서비스 동작시에 디버그 추적을 위한 로그를 거는 방식을 흔하게 사용하게 됩니다. ( 너무도 전통적인 방식이죠. )정말 백엔드로 파이썬을 사용하고 있다면, 오류 추적이나 동작 메커니즘을 추적한다는 것은 매우 귀찮고 번거로운 작업이 됩니다.만들어지는 파이썬의 모든 파일에 해당 로그를 넣었다가 빼었다가, 배포의 오류를 만나는 상황까지 매우 번거로운 작업들이 끊임없이 반복되게 됩니다. 이런 상황들을 추적하기 위한 APM의 추적 기능들을 찾게 됩니다.또한, Python의 특징상 수학 알고리즘으로 구성된 API 중개인의 형태를 취할 경우에 DB에 대한 접근을 위한 ORM에서의 추적과 외부 웹 호출들이 뒤섞이게 되면서 오류 추적은 매우 짜증스러운 단계로 진화되게 됩니다.Python으로 백엔드 개발을 하게 되면만나게 되는 매우 짜증스러운 상황이죠.그래서, 와탭의 Python APM은 이 문제에 집중하기 위해서 와탭 고유의 문제 해결 방식을 그대로  아키텍처로 적용하여서 개발시에 편하고 빠르게 성능을 추적할 수 있도록 제작되었습니다. Python 백엔드 개발을 위한 최선의 방향을 제시합니다.Python개발자는 와탭의 APM을 설치하면 매우 손쉽게 웹 트랜잭션의 단계, 에러 추적, 클래스 추적, DB의 형태 및 Slow Query추적, 외부 호출 메커니즘의 구성 등을 설치 이후부터 빠르게 추적할 수 있으며, 개발자의 실수이거나 다른 외부 호출의 문제, DB와의 관계 등을 빠르게 잡아낼 수 있습니다.에러를 추적하기 위한 로그를 동작한다던지, 실환경시에 배포를 다시 한다던가 하는 귀찮은 작업을 모두 제거하는 것뿐만 아니라, 매우 통계적으로 의미 있는 와탭의 트랜잭션 추적 메커니즘을 사용할 수 있게 됩니다.파이썬을 기반으로 백엔드를 구성하는 곳이라면,와탭 APM은 매우 의미 있는 결과를 도출할 수 있습니다.와탭 Python의 세부적인 기능을 조금 더 상세하게 설명드리겠습니다.가장 먼저, 실시간 트랜잭션 모니터링!5초 주기로 트랜잭션을 수집하는 와탭의 방식은 서버의 부하를 최소화하면서 가장 의미 있는 데이터들을 수집하고 데이터 기반으로 오류와 트랜잭션을 빠르게 추적할 수 있게 합니다.파이썬 개발 시의 동작성을 체크하기 위한 와탭만의 고유의 진행 중인 트랜잭션 실시간 모니터링 기능인 아크 이퀄라이져와 동작된 웹 트랜잭션의 종료시간을 기준으로 시각화하여 동작된 트랜잭션의 상황을 한눈에 파악할 수 있습니다.와탭 Python APM위의 그림을 보면, Active Transaction으로 불리는 원형( 아크 이퀄라이져라 함 )으로 실제 동작중인 트랜잭션의 개수와 동작속도 등을 체크할 수 있으며, Hitmap을 통해서 종료된 트랜잭션의 속도를 시각화하여 볼 수 있습니다. 이 두 개의 시각화 만으로도 느린 트랜잭션을 추적 관리할 수 있습니다.Python 트랜잭션 추적 및 분석개발자는 단지 APM을 동작시켰을 뿐이지만, postgreSQL 데이터베이스에 연결하고 SQL문장을 주고받는 부분들을 하나의 시각화된 관점으로 나열해서 확인할 수 있습니다.각각의 동작 시간을 추적하는 것은 물론이고, 이 내용은 ORM으로 매핑된 상태에서도 SQL의 동작 순서대로 시각화되기 때문에 순서가 꼬이거나 문제가 발생되는 부분들을 손쉽게 찾아볼 수 있게 합니다.이외에도 와탭 APM( Java, Node, PHP 등의 모든 APM)에 기본적으로 제공되는 트랜잭션 추적 모듈 이외에도 사용자가 원하는 모듈 추적에 대한 기능들을 플러그인 형태로 정의할 수 있습니다. 더 복잡한 추적을 위해서 와탭의 고유기능을 추가적을 확대 사용이 가능합니다.WHATAP_HOME 의 plugin.json파일에 적절한 내용을 수정하여 특정 모듈의 데이터를 추적할 수 있습니다. 특정 모듈의 데이터를 추적하거나, 사용자 별로 원하는 모듈을 추적할 수 있습니다.*사용 안내:•[module_name]: 추적하고자 하는 대상의 모듈 명. import 하는 모듈 명 이기도 하다.•[class_name]: 추적하고자 하는 대상의 클래스 명. 없다면 ‘’(empty string)으로 사용한다.•[def_name]: 추적하고자 하는 대상이다.•args_indexes: 추적하고자 하는 대상의 아규먼트 인덱스. 여러 개일 경우 , 로 구분한다.•kwargs: 추적하고자 하는 대상의 키워드 명. 여러 개일 경우 , 로 구분한다.Plugin 기능 사용위의 예제에서는 Plugin과 SQL update문장의 순차적인 실행,세부 Plugin 설정에서 사용자의 모듈명, 추적 클래스 명, 추적대상과 아규먼트 인덱스, 키워드 등을 추적할 수 있습니다.*사용 예:plugin.json{"[module_name]": {      "class_name": "[class_name]",      "def_name": "[def_name]",      "args_indexes": ", ",      "kwargs": ", "},"httplib2": {      "class_name": "Http",      "def_name": "request",      "args_indexes": "1",      "kwargs": "method"},"faker.providers.address": {      "class_name": "Provider",      "def_name": "street_address",      "args_indexes": "",      "kwargs": ""}}두 번째, 데이터베이스를 매핑한 ORM과 SQL의 순서와 속도, Slow Query!매우 당연하게 파이썬을 기반으로 백엔드 개발을 할 경우에 데이터베이스를 사용하게 되며, 이에 대한 Slow Query와 관련된 추적하는 것이 개발자에게 필요하게 됩니다. 향후, RDS기반을 사용하게 되면 Query추적은 대부분의 데이터베이스 처리에 기본이 될 것입니다.현재 지원되고 있는 mysql / postgresql에 대하여 SQL Query, Fetch Count, SQL Query수행 시간을 수집합니다.Python개발 시에 RDBMS(관계형 데이터베이스 관리 시스템)를 선택하면 거의 항상 ORM(객체 관계 매핑) 라이브러리를 함께 사용하게 됩니다.특히, 파이썬에서는 이런 ORM라이브러리가 다양하고 사용하기 쉽기 때문에, 매우 흔하게 사용하고 있습니다.ORM의 장점으로는 쿼리를 생성하거나 추상화하는 대신, 데이터 베이스 시스템에 대한 접근을 쉽게 할 수 있는 장점이 있습니다. 다만, 이러한 장점 때문에 실제 만들어진 쿼리가 어떠하고 쿼리 수행 시간이 얼마나 걸리는지에 대해서는 추적이 어렵다는 점이 있습니다.이처럼, 파이썬의 특징상 ORM(객체 관계 매핑) 라이브러리를 사용할 경우에 추상화된 쿼리가 어떻게 동작하고, 실제 어떤 상황으로 발생 및 동작되는지를 한눈에 파악할 수 있게 합니다.ORM으로 매핑된 SQL의 순차적인 동작 상태 파악그리고, 세 번째. 외부 호출 추적파이썬 백엔드 개발 시에 사용되는 외부 호출(request/httplib2)등의 외부 호출과 관련된 호출 정보 및 수행 시간 등을 수집합니다.외부 호출을 사용하는 경우에는 각각의 호출에 대한 지연시간에 대해서 세밀하게 추적해야 하므로, 이와 관련된 에러와 지연시간 등을 추적하는 것은 매우 중요한 개발 시의 관점입니다.Python 외부 호출 추적마지막 중요 관점 네 번째는, 튜닝을 위한 다양한 프로파일 데이터의 제공을 이야기할 수 있습니다.와탭의 파이썬 에이전트는 위에서 나열되는 성능 저하를 위한 요소들의 전체적인 관점에서 수집하고 그 데이터들을 시각화할 수 있습니다.데이터베이스를 효율적으로 사용하고 있는지, 사용하는 ORM툴과 매핑과의 관계, 쿼리와 쿼리의 수행 시간과 상태에 대한 추적, 외부 호출시간과 각각의 지연되는 외부 호출과의 관계와 순서 등이 전체적으로 백엔드로 개발되는 Python의 성능 튜닝에 영향을 주게 되는 것이죠.그 이외에도 전체적으로 백엔드 서비스의 TPS, 응답 시간, 서비스 리소스 사용량과 어떤 에러가 발생되고 있는지를 알 수 있습니다.서비스 사용자가 사용하는 상세한 정보들을 프로파 일릉 함으로써 이들의 연관관계를 한분에 파악하게 해줍니다. 와탭에서 관리되는 프로파일 정보는 - 트랜잭션, SQL Query, 외부 HTTP호출, Error, User Agent, Client IP 등의 상관관계들입니다.그리고, 덤으로... Python이 설치 운영되는 전체적인 패키지의 버전을 한눈에 파악할 수 있는 것은 너무도 당연한 기능입니다.설치된 Python 패키지 확인그리고, 와탭의 DNA를 그대로 이어받은 APM이기 때문에, 기본적인 APM의 기능들을 대부분 담고 있습니다. 처음 와탭 APM을 접하시는 분들을 위해서 간단하게 설명드리면 다음과 같습니다.CUBE 메뉴는 시간을 기점으로 와탭 Python APM이 설치된 이후부터 현재까지의 모든 상황들을 추적 관찰할 수 있습니다. 주말에 오류 간 난 상황이라던지, 특정 오류의 발생 시점을 알고 있는 경우에 빠르게 해당 문제가 발생한 위치나 SQL 등을 추적할 수 있습니다.상세한 일간, 주간, 월간 리포트나 MAU 등을 추적할 수 있는 리포트 기능들은 와탭만이 가지고 있는 장점에 해당됩니다.Python으로 백엔드 웹서비스를 개발하고 계시다면, WHATAP Python APM은 개발과 운용을 매우 풍요롭고 빠르게 해줍니다.파이썬 백엔드 서비스 개발자라면 와탭 APM!
조회수 1837

더 빠른 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 #꿀팁
조회수 4527

Elasticsearch로 느린 쿼리 분석하기

응당 인덱스가 있으리라 생각한 칼럼에 인덱스가 없고 인덱스를 걸자마자 응답속도가 평균 10배 가까이 좋아지는 모습을 지켜보니 여러 생각이 들더라. 통계와 지표가 제공되는 곳은 주기적으로 검토하고 문제가 커지기 전에 손을 쓰는데 그렇지 않은 곳이 문제이다. 주기적으로 Slow query 로그를 훑어볼 수는 있다. 하지만 특정 시점에 일부 로그만 훑어봐서는 엉뚱한 문제를 해결하기 일쑤다. 예를 들어 1초짜리 쿼리보다 10초짜리 쿼리가 문제라고 생각하기 쉽지만 이 1초짜리 쿼리를 10초짜리 쿼리보다 1000배 많이 실행한다면 이야기가 달라진다. 요는 느린 쿼리를 지속적으로 수집하고 통계를 낼 필요가 있다는 것이다.이러한 모니터링 도구를 어떻게 구현할까? 우리 손에 있는 도구를 검토하는 일부터 시작했다.통계분석은 MySQL 또는 Elasticsearch 를 쓰면 된다.Elasticsearch를 쓴다면 Kibana를 이용해 시각화하기 편하다.느린 쿼리 로그를 Elasticsearch에 보내는 일은 Fluentd를 쓰면 된다.그러니까 Fluentd, Elasticsearch, Kibana 조합이라면 데이터를 눈으로 보고 문제를 해결하기 좋을 것이다. 그렇다면 어떻게 구현할 것인가?우선 RDS에서 느린 쿼리를 뽑아서 Fluentd에 보내는 방법을 찾아야 한다.Fluentd를 이용해 Elasticsearch에 데이터를 보내는 건 쉬우니 대시보드만 잘 구성하면 끝!문제는 RDS에서 느린 쿼리를 뽑아서 Fluentd에 보내는 것인데 크게 두 가지 방법이 있다. RDS 설정에 따라 느린 쿼리 로그를 테이블 또는 파일에 저장할 수 있는데 이에 따라 구체적인 구현방법이 달라진다. 하지만 기본적으로는 동일한 과정을 거치는데 대충 이런 식이다.느린 쿼리 로그를 읽는다.같은 쿼리라도 매개변수 값이 다를 수 있으므로 mysql_slow_log_parser 또는 pt-query-digest 같은 도구를 사용해 쿼리를 일반화한다.Fluentd를 통해 해당 로그를 ES로 보낸다.새로 추가된 로그만 읽어서 다시 ES로 보낸다.이와 관련해서는 AWS RDS Mysql SlowQuery monitoring on Kibana using Logstash 등의 글이 잘 설명한다.다행히 테이블에 저장한 로그를 읽어들이는 Fluentd 플러그인을 구하기는 쉽다. 변형체가 많은데 대부분은 kenjiskywalker/fluent-plugin-rds-slowlog에서 파생됐다. 파일에 저장한 로그의 경우는 in_rds_mysqlslowlog_stream.rb를 써서 처리하면 된다. 우리는 테이블에 저장하기 때문에 전자를 선택했다.이쯤 조사를 마치고 나니 진행방향은 매우 명확하다. 적당히 잘 만든 Fluentd 플러그인을 골라서 적용한 후에 ES에 대시보드를 만들면 된다. 물론 우리는 Kubernetes 위에 모니터링 도구를 띄워야 하니 Dockerize할 필요도 있다. 이쯤에서 또다시 구글링을 하니 무시무시한 게 나온다. inokappa/rds-slowquery-log-demo는 방금 설명한 모든 과정을 하나로 정리해서 제공한다. Docker로 만든 Fluentd와 ES 대시보드 설정을 한데 묶어놓았다. 거기에 파일 로그, 테이블 로그 둘 다 예제로 제공한다. 덕분에 일이 쉽게 끝날 줄 알았다. 하지만!개발한지 꽤 시간이 지난 지라 최신 버전의 Fluentd와 ES에서 계속 문제를 일으켰다. 문제점에 대해 구구절절 설명할 생각은 없고 DailyHotel/rds-slowquery-log-demo를 참고해서 적용하면 된다는 점만 이야기하고자 한다. 일어로 된 README 파일은 구글 번역기를 돌리면 적당히 읽을만해진다.삽질을 약간만 하면 아래와 같이 간지!나는 대시보드를 얻을 수 있으니 해볼만 할 것이다.참! DailyHotel/rds-slowquery-log-demo는 테이블 로그인 경우만 테스트했으니 파일 로그를 사용하는 경우라면 이 점을 주의해야 한다.더 읽을거리Collecting and Analying Slow Query Logs for MySQLRDS(MySQL) のスロークエリを EFK スタック + Docker で出来るだけ手軽に可視化する考察(2)〜 log_output: FILE の場合 〜#데일리 #데일리호텔 #개발 #개발자 #개발팀 #Elasticsearch #엘라스틱서치 #꿀팁 #도입후기 #일지
조회수 1445

박문수 이야기

출근 첫날 이효진 대표님으로부터 입사 지원 메일을 하나 전달받았다. 이력서를 살펴보니 컴퓨터를 전공하지도 않았고, 현재 개발을 하고 있지도 않았지만 개발자로 일하고 싶다고 적혀 있었다. 개발을 할 수만 있다면 인턴부터 시작해도 좋다고 말했다. 남들이 부러워하는 삼성에 다니고 있는데 어떤 이유로 개발자가 되고 싶어 할까? 궁금한 마음에 한 번 만나보기로 했다. (뽑을 생각은 없었다)첫인상은 그냥 수수한 시골 청년이었다. 나도 입사한 지 얼마 안 되어 회사 주위 식당을 몰라 그냥 눈에 띄는 식당으로 들어갔다. (생각해 보니 그 식당을 그 이후로는 한 번도 가지 않았다) 지난 회사에서 어떤 일들을 했고, 왜 개발에 대한 목마름을 느꼈는지를 들었다. 개발자가 되기 위해 어떤 것들을 포기할 수 있는가에 대한 각오도 들었다.나는 앞으로 일 년 동안 인턴 월급을 받아야 할지 모른다고 이야기했다. 정말 열심히 하지 않으면 그저 그런 개발자가 되어 인생이 꼬일지도 모른다고 경고했다. 그런데도 흔쾌히 도전해보고 싶다고 말했고, 나는 배움의 기회를 제공하겠다는 약속을 했다. 좋은 대학을 나와 어렵게 얻은 직장을 포기하고 다시 새로운 길을 선택하려는 용기를 높이 샀다. 입사일은 3주 뒤로 정했다. 파이썬 책과 웹 프로그래밍 기본 책을 던져주고 모두 읽어 오라고 했다.입사 후 정신없이 3주가 지나고 문수님이 입사를 했다. 첫날 개발 환경을 셋업 하는 것을 도와주었다. 나에게는 너무나도 자연스러운 많은 것들이 그에게는 생소한 것이고 설명을 해야 했다. 문수님이 이해할 수 있는 간단한 것만 설명하고 나머지는 더 크면 알게 된다고 설명을 미루었다.(첫날 전체를 대상으로 자기소개를 하는 문수님. 우리 회사에는 입사자가 전체를 대상으로 자기소개를 하는 문화가 있다. 이 문화의 유래에 대해서는 다시 한 번 이야기해 보겠다.)내가 모든 것을 알려 줄 수는 없으니 코세라 수업을 같이 들어 보자고 이야기했다. 내 기준으로는 너무 쉬운 강의였지만 나는 회사 내에서 공부하는 분위기를 만들어 가고 싶었고 문수님께는 회사에서 필요한 기술 스택을 맛보는 기회가 될 수 있으리라 생각했다. (현재 시점으로 3달째 코세라 강의를 이어서 듣고 있다.)첫 강의인 HTML5를 들으면서 간단한 버그 수정부터 문수님께 요청을 하기 시작했다. 오자를 고치거나 박스의 위치를 조정하는 일부터 시작했다. 입사하고 3일이 지나서 첫 번째 배포를 했다. 처음이 어려웠을 뿐 간단한 수정을 하는 것에는 일주일이면 충분했다. 그때부터는 git과 git flow를 알려주기 시작했다. 착한 신입은 마음이 열려 있어서 불만 없이 모든 것을 따라 했다. 어느 정도 이해를 했는지는 알 수가 없다. 하지만 프로그래밍을 배우는 길에는 머리보다 손이 먼저 익히는 것들도 많다.3주가 지난 시점에는 첫 번째 데모를 전체 앞에서 보였다. (우리는 스크럼을 하고 있어서 매번 스크럼이 끝나는 날에 개발자가 스스로 자신이 개발한 것을 전 직원 앞에서 데모를 보인다.) 지금은 잠깐 문을 닫은 채권 거래소에서 채권 판매자가 손쉽게 채권을 팔 수 있는 기능이었다. 그것을 만들기 위해 일주일 넘게 꽁꽁 머리를 싸매고 있었고, 결국은 결과물을 내놓았다.(첫 번째 데모를 보이는 문수님. 긴장한 모습이 느껴진다. 데모를 마치고 다들 뜨거운 박수를 보내주었다)내가 만들면 2시간이면 끝났을 기능이라 일주일간 고생하는 것을 옆에서 지켜보는 것은 상당한 인내를 필요로 했다. 하지만 최대한 혼자만의 힘으로 첫 번째 과제를 해내기를 원했기에 최소한의 도움만을 주었다.이제 문수님이 입사한 지 만 3개월이 되었다. 그동안 많은 변화가 있었다. 회사에서 조그마한(점점 커지고 있다) 수정/기능들은 대부분 맡아 주고 있기에 다른 개발자들은 좀 더 어려운 문제를 풀 수 있게 되었다. 처음에는 코드 리뷰를 온라인으로 할 수가 없었다. 옆에 앉아서 어떤 부분을 어떻게 고쳐야 하는지를 구체적으로 알려 주어야 했고, 이해하지 못하면 관련된 지식을 얻을 방법을 알려 주어야 했기 때문이다. 하지만 이제 github의 PR을 보고 코멘트를 다는 것 만으로 코드를 적절히 수정할 수 있게 되었다. 얼마 전에는 하루에 1억이 넘는 이체를 하는 내부 시스템을 80% 이상 만들기도 했다. (내가 뼈대는 잡아 주기는 했다.)개발자라 부를 수 있는 기준이 따로 있겠냐만은 나는 이제 그를 개발자라 부를 수 있을 것 같다. 아마도 오늘의 문수님에게는 “개발자 박문수 님”이 가장 듣고 싶은 호칭이 아닐까 생각한다.  마지막으로 전공하지도 않았고, 첫 직장과도 관련 없는 새로운 도전을 하는 문수님의 용기에 박수를 보낸다. 내게 말하지는 않았지만 수많은 주위의 걱정과 우려를 이겨내기 위해 최선을 다하고 있으리라 생각한다. 나는 앞으로 그에게 “문수님은 지금 어디로 가고 있나요?"를 종종 물어봄으로 내 역할을 해야겠다.8퍼센트는 멋진 저희 팀과 함께 할 분들을 찾고 있습니다. 특히 저보다 개발을 잘 하시는 시니어 개발자, 그리고 3년 뒤에는 저 보다 잘하게 되실 주니어 개발자는 제가 모시러 갑니다. hr@8percent.kr로 연락 주세요.박문수 님이 이체 시스템 개발을 할 때 Toss의 이체 대행 API를 사용했습니다. 정말 간편합니다. 관련 개발을 하시는 분들은 사용해 보세요.#8퍼센트 #에잇퍼센트 #채용 #채용후기 #개발자 #개발자채용 #인턴 #인턴채용 #스타트업CTO

기업문화 엿볼 때, 더팀스

로그인

/