지난 3월 중순부터 약 한 달간 해커랭크에 있는 SQL practice를 정주행했다. 발단은 ‘코딩 테스트를 해커랭크로 내는 회사들도 있다’는 얘기를 들어서였다.

결과적으로는 입문/초급에서 중급으로의 언저리를 맴돌던 실력이 확 늘었다고 느끼는 계기가 되었다. 무엇을 할 수 있는지와 함께 어떻게 접근하는지를 보는 게 코딩테스트라면, 그 ‘어떻게’를 짧은 시간에 밀도있게 트레이닝하는 기회였다.

해커랭크의 SQL Practice 구성

총 58개의 Practice로 이루어져 있다. 난이도는 Easy/Medium/Hard로 나뉜다.

  • Basic Select
    Easy(20)

  • Advanced Select
    Easy(1) - Medium(4)

  • Aggregation
    Easy(14) - Medium(3)

  • Basic Join
    Easy(3) - Medium(5)

  • Advanced Join
    Medium(3) - Hard(2)

  • Alternative Queries
    Easy(2) - Medium(1)


학습 방법

1차 정주행

일반적인 방법으로 문제를 풀어갔다. 지문을 읽고, 필요한 조건을 아래와 같이 뽑았다.

  • 최종적으로 리포트에 포함시킬 Column들 (SELECT)
  • 정렬 순서 (ORDER BY)
  • 제한 조건 (WHERE, JOIN ON) 그리고는 순차적으로 테이블을 어떻게 뽑아갈 것인지, 백지를 펼쳐놓고 그려가면서 접근했다.

몇 번의 디버깅으로 쉽게 패스한 문제는 그냥 두고, 꽤 시간이 걸려서 풀고 오류를 많이 범했던 문제 위주로 Github에 정리했다. 올바른 쿼리와 시행착오 쿼리를 모두 남기고, 새로 알게된 건 사소해도 Lesson & Learned으로 정리했다.
사실 1차에선 일단 문제를 해결하는 데 초점을 뒀었다. 쿼리를 짜면서도 때로는 뭔가 비효율적이라는 느낌을 떨칠 수 없었다.

2차 정주행

Github에 정리했던 문제들만 다시 풀어본 뒤, 전에 짰던 쿼리와 비교해 보았다. Easy 레벨은 둘이 서로 일치하기도 했지만 JOIN이 많아지고 제약조건이 복잡해질수록 기존 쿼리에 문제가 많았다. 리팩토링이라는 말을 이럴 때 써도 되는지 모르겠지만 아무튼 쿼리 효율과 가독성을 고려해 개선하는 작업을 했다.

이 과정에서 아래의 글을 번역하면서 개념을 확실히 잡았다.
[번역] 데이터 분석을 위한 SQL 쿼리 효율
[번역] WHERE이나 ON을 이용해 필터링하기


얻은 것

1. 심리적 자신감

MECE하게 구성된 Practice들을 통해 다양한 상황과 문법을 다뤄보고 나니, 아는 것과 모르는 것을 구분할 수 있게 되었다. 채용면접 후기에 보면 ‘코딩테스트는 해커랭크로 나왔고, 평소에 좀 해보신 분이라면 무리없이 풀 수 있는 수준이었다’는 얘기를 본 적이 있다. 전에는 코딩테스트에 대해 막연한 두려움이 있었는데, 이젠 뭐가 주어져도 어떻게든 해볼 수 있겠다는 자신감이 생겼다.

2. 새로 알게된 개념과 함수들

  • 사용자 정의 세션 변수(User Defined Session Variable) 사용하기
  • REGEXP(), DATEDIFF()
  • SELECT에 집계함수가 들어가면, 테이블 전체가 full-group-by 됨
  • ORDER BYSELECT하기 전 테이블에 적용됨. 즉, 비용이 많이 든다.

3. 머리로만 알았던 개념을 몸에 익힘

  • 교육 컨텐츠는 보통 아래와 같은 순서로 학습시킨다.
    특정 함수 —> 이것의 기능 –> 구체적 사용법
    하지만 실제로 응용할 줄 아는 수준이 위해서는 반대의 트레이닝이 반드시 필요하다.
    상황과 목표 –> 필요한 기능 —> 특정 함수
    나에게 해커랭크는 후자를 경험하는 좋은 기회가 되었다.
  • 특히 그동안 INNER JOIN만 주로 사용하다가, 상황과 필요에 따라 LEFT JOIN, CROSS JOIN을 써보고 그 개념을 몸으로 이해하게 되었다.

4. 반복적인 실수 파악

집계함수를 쓰는 경우 테이블 전체가 full-group-by 된다는 걸 알게 되었다. 가장 많이 맞닥뜨린 에러였다.

5. 코딩스타일 확립

짧은 시간에 많고 다양한 쿼리를 짜다 보니, 자연스럽게 코딩스타일이 확립되지 않은 부분들이 드러났다. 또한 2차 정주행할 때 내가 짠 쿼리인데도 알아보기 힘들어서 가독성을 높이는 쪽으로 개선했다.

아쉬운 점

1. 언어 장벽

영문 컨텐츠이다 보니 아무래도 학습 효율은 조금 떨어진다. 문제에 제시된 제약조건을 잘못 이해해 엉뚱하게 쿼리를 짜는 경우가 가끔 있었다.

2. 일부 컨텐츠의 퀄리티

문제 설명 자체가 모호하거나 부정확한 Practice가 몇 개 있었다. 영 안풀리면 Discussion 게시판을 봤는데, 많은 사람들이 이런 이슈를 제기한 경우에는 굳이 애써서 풀지 않았다.


그럼에도 좋은 해커랭크의 장점

1. 다양한 케이스를 다뤄보게 된다.

해커랭크를 하기 전 2개의 데이터셋을 로컬 MySQL에 업로드하고 이런저런 쿼리를 짜봤었다. 겨우 2개라서 좀 그렇지만, 아직 보는 눈이 없어서 그런지 ‘분석해보고 싶을만큼 군침도는’ + ‘RDB 형태의’ + ‘가급적 raw한 상태인’ 데이터셋을 찾기가 무척 어려웠다. 그렇다 보니 분석 과정에서 사용하는 스킬에도 한계가 있었다.
하지만 해커랭크를 풀면 기본적으로 알아야 할 다양한 내용들을 다루게 된다. 문제를 풀면서도 잘 구성된 커리큘럼이라는 느낌이 들었다.

2. 게미피케이션 요소

올바른 결과를 출력해서 ‘Congratulations!’가 떴을 때의 희열이 있다. 문제를 풀 때마다 10~30점의 점수를 받고, 총점을 기반으로 Rank가 매겨졌다. 이거 올리는 재미로 초반엔 며칠 밤을 달렸다. 다만 지금은 이 랭킹시스템이 코인 제도로 바뀌었다. 내가 모든 Practice를 마칠 무렵에 일어난 일이라 그나마 다행이다.


향후 계획

실무형 쿼리 짜보기

사실은 중후반쯤 달리고 있을 때 <데이터 분석을 위한 SQL 레시피>가 출간된 걸 알게 되었다. 변찌님의 적극 추천에 묻지도 따지지도 않고 샀더니, 이건…진짜 보물이다. 우선 3장~6장만 훑어보는 걸 목표로 예제 하나하나씩 쿼리 짜보고 있다. 뒷부분은 난이도가 좀 있고, 어떤 곳에서 어떤 직무를 하게 될지에 따라 필요성이 달라져서 일단 보류해둔다. 앞부분만 확실히 숙지해도 훨씬 자신있게 면접과 코딩테스트에 임할 수 있을 듯하다.

3차 정주행

전에 Coursera에서 Data Science 코스 들을 때, 같은 과제를 놓고 다른 사람과 코드를 비교해보면 공부가 많이 된다는 걸 느꼈다. 해커랭크에는 각 Practice별로 Discussion 게시판이 있다. 여기 올라온 쿼리를 보면서 비교/분석해보고 Lesson & Learned를 정리해 볼 예정이다. 이건 급한 건 아니니, 1일커밋 소재가 부족할 때 기분전환으로 해보면 좋을 듯하다.