데이블(Dable)

데이블은 “아시아에서 빠른 속도로 성장하고 있는 국내 1위 콘텐츠 디스커버리 플랫폼”이라고 합니다.

데이블의 기술팀은 네이버, 엔씨소프트, SK플래닛 출신으로 구성되어 있고, 개인화, 머신러닝, 광고주 효율을 위한 자동 최적화 등에 소프트웨어 엔지니어링을 펼치고 있습니다.

다른 조직에서는 주로 콘텐츠 보관 용도로 작성하는 노션(https://www.notion.so/)을 일감 관리를 위한 이슈 트래커로 활용하고 있는 점이 눈에 띄었습니다. 노션 홈페이지에도 칸반 보드 소개가 나와 있긴 하지만, 팀이 아니라 전사적으로 사용하는 곳은 처음이었습니다.

Dable Notion screenshot

과제

데이블은 미디엄 블로그(https://medium.com/dableblog) 등을 통해 데이블의 서비스 소식을 알리고 있습니다. 복수의 미디엄 계정에 국가별, 분류별로 다양한 글들이 올라오는데, 여러 국가의 각 운영팀이 글을 작성하고 있는 것으로 보입니다.

글을 관리하고 모니터링하기 위해 미디엄에 올라오는 포스팅을 관찰하여, 대시보드에 표시하는 방법을 고려하고 있고, 이를 위해 미디엄에 새 글이 올라오거나 글이 지워진 경우에 데이터베이스에 기록하는 Node.js 스크립트를 작성해줄 것을 요청받았습니다.

MySQL 데이터베이스 기준의 테이블 스키마를 전달받았으며, 이를 바탕으로 어떤 조건으로 어떻게 남길 것인가를 얘기하며 작업을 시작하였습니다.

해결 과정

약간의 자바스크립트 작성 경험이 있었지만, 대부분 웹 브라우저에서 작동될 것을 전제로 하는 환경에서의 작업이었던 터라, Node.js 생태계에서의 코드 작성은 어쩐지 낯설었습니다.

Node.js 뿐만 아닌 다양한 환경의 자바스크립트 라이브러리들이 패키지 매니저로 쓰고 있는 npm(https://npmjs.com)에는 정말로 많은 패키지가 등록되어있어, 어떤 것을 골라 작업할 것인가를 고민하는 것부터가 시작이었습니다.

mysql

일단 MySQL 데이터베이스와 값을 주고받기 위해 관련 라이브러리부터 검색해보았는데, 다음의 두 라이브러리가 가장 많이 사용되고 있어 둘 중 하나를 골라야 했습니다.

mysql2는 기존에 MySQL-Native로 불리던 라이브러리의 후속 버전이라고 합니다. 어떤 차이가 있는 지 오래 사용해본 사람이 아니라면 알 수 없으므로 https://npmcompare.com/compare/mysql,mysql2 등의 단순한 수치 비교 페이지를 참고하여, 더 많은 사용자를 가진 mysql을 골랐습니다.

feedparser

미디엄은 https://medium.com/feed/{username}으로 접속하면 Atom 형식의 최근 글 목록을 내려줍니다. 이런 형식을 해석해서 자바스크립트 개체로 만들어주는 피드 라이브러리도 정말 다양합니다.

그중 가장 사용이 간편해 보이는 feedparser를 선택했으며, 이 라이브러리를 Promise를 지원하도록 감싼 feedparser-promised를 사용했습니다.

feedparser는 URL을 직접 받아 바로 HTTP 요청까지 해서 해석해주므로 사용자는 거의 아무것도 하지 않고, 다음과 같은 간단한 코드로 피드를 읽어올 수 있습니다.

feedparser.parse(url).then((posts) => {
    // Handle posts
});

yargs

기존 시스템과 독립적으로 작동되는 커맨드라인 인터페이스를 갖춘 스크립트로 작성해달라는 요청을 받았으므로, 일단 Node.js에서 제공하는 process.argv 값을 통해 입력값을 직접 다루려다, 파이썬에서도 argparse 등을 이용해 편리하게 작업했던 기억을 떠올려 npm에서 검색해보았습니다.

검색 결과로 가장 먼저 나오는 것은 args 라이브러리지만, 이쪽 생태계에서 가장 널리 사용되는 라이브러리는 yargs인 것으로 보입니다. 여러 예제 코드를 참고하여 요청받은 입력값을 처리할 수 있도록 하였습니다.

// Provide command line interface via yargs
argv.command('$0 <username> <category> <country>', 'Get feed from Medium blog and upsert into MySQL', (yargs) => {
  yargs.positional('username', {
    describe: 'Medium username',
    type: 'string'
  }),
  yargs.positional('category', {
    describe: 'Category name',
    type: 'string'
  }),
  yargs.positional('country', {
    describe: '2-bytes country code',
    type: 'string'
  });
}, (argv) => {
  main(argv.username, argv.category, argv.country);
})
.help('h')
.alias('h', 'help')
.argv;

위와 같은 라이브러리를 통해 미디엄 블로그의 피드를 읽어, 데이터베이스에 저장된 값과 비교하여 없는 항목에 대해서 새로 저장하는 간단한 스크립트를 비교적 빠른 시간 안에 작성할 수 있었습니다.

다만, 지워진 글에 대해서는 피드만 이용해서는 명확하게 확인할 수 없어, 사전 협의하여 해당 내용은 작업하지 않고 생략하였습니다.

추가 작업

기본 작업을 마치고 남은 오후 시간에는 원래 요청받았던 파이썬의 테스트와 관련된 이야기를 나누었습니다. 원래는 데이블에 있는 파이썬 코드들에 대한 테스트 계획을 세우고, 작업자들과 함께 테스트를 작성하여 CI를 적용하는 것이 목표였지만, 당일 여건이 여의치 않아 파이썬 테스트와 주변 생태계에 대한 전반적인 소개와 데모를 진행하였습니다.

몇 년 전에 작성했던 슬라이드 자료를 이용하여 파이썬의 테스트에 대해 간략하게 소개하였습니다.

더 알아보기

  • i18next

  • shields.io

    • 프로젝트 소개, README.md 등에 활용할 수 있는 배지 이미지를 제공합니다.
    • 테스트, 커버리지, 펀딩 등 다양한 분야의 배지를 SVG, PNG 형식으로 제공해줍니다.
  • setup.py test command deprecated

    • 예전에는 파이썬 패키지의 테스트를 setup.py에 함께 저장하였는데, 테스트를 tox에서 진행하는 것이 대중화되어 테스트와 관련된 내용을 setup.py에서 제거하고 있습니다.
    • tox를 통해 여러 환경을 테스트하는 경우 예전에는 detox를 통해 병렬로 테스트를 진행할 수 있었으나, tox병렬 모드를 자체 지원하는 것으로 대체되었습니다.
    • 테스트에서만 필요한 패키지 의존성을 기존에는 setup.pytests_require 항목에 기입하였으나, 이 또한 tox.ini에서 관리하는 것으로 대신할 수 있습니다.
    • 예제: django-summernote의 setup.py에서 테스트 항목을 제거한 커밋
  • 데이블 피어 보너스 제도

    • 데이블은 고마운 직원에게 다른 직원이 보너스를 쏴줄 수 있는 피어 보너스(Peer bonus) 제도를 운용하고 있다는 점이 흥미로웠습니다. 그리고 그 내역을 모두가 볼 수 있도록 공개한 것이 인상적이었습니다. Dable Peer Bonus screenshot
    • 그 외에도 매주 목요일 재택근무, 그리고 추가로 연 10일간 원하는 곳에서 선택적으로 원격근무하는 제도가 눈에 띄었습니다. 데이블에 대한 자세한 안내는 아랫글들을 참고해보세요.

영상