두다지 서버 개발자 양성 프로그램 Week 1


두다지에서 진행하는 서버 개발자 양성 프로그램 3기에 참여하게 되었다. 시간과 돈을 투자하여 좋은 멘토님에게 수업을 듣는 만큼 멘토님이 말씀하신 내용들을 기록하여 차후에 다시 학습을 함에 있어 내 자신을 remind 시키는데 도움이 되게끔 기록을 남긴다.


간단한 정렬 알고리즘의 구현과 코드 리뷰

멘토와 멘티들의 간단한 자기 소개 이후, 멘토님은 우리에게 Warming up 삼아 본인이 작성할 수 있는 정렬 알고리즘의 코드를 작성해보도록 시키셨다. 작성 언어의 경우, Python으로 통일. 평소 알고리즘에 큰 자신이 없는데다가, 누군가의 앞에서 코드를 작성해본 경험이 없었던 나는 알고리즘을 작성한 그 짧은 시간이 너무나도 길게 느껴졌다... Quick Sort 혹은 Merge Sort와 같이 내가 알고 있는 효율적 정렬 알고리즘을 구현해보고 싶었으나, 당장 Pseudo code를 보지 않고 작성할 수 있는 Bubble Sort와 Selection Sort를 작성하기로 하였고, 코드 작성 이후에는 멘토님의 코드 리뷰가 이어졌다.


버블정렬과 선택정렬의 구현

  1. Bubble Sort
a = [3,4,1,2,7,9,10]
size = len(a)

for j in range(size-1, 1, -1):
	for i in range(0, j):
		if a[i] > a[i+1]:
			tmp = a[i]
			a[i] = a[i+1]
			a[i+1] = tmp

  1. Selection Sort
b = [3,4,1,2,7,9,10]
size_b = len(b)

for i in range(0, size_b-1):
	tmp_min = b[-1]
	idx = -1

	for j in range(i, size_b-1):
		if b[j] < tmp_min:
			tmp_min = b[j]
			idx = j

	b[i], b[idx] = b[idx], b[i]

코드 리뷰

  1. 스타일의 준수
    • Python이 공식적으로 내놓은 스타일 가이드인 'PEP 8'를 준수하는 것이 가장 좋음
    • 80 Columns Rule: 한 Line에 80개 이상의 column이 들어가지 않도록 하는 것이 좋음
      • 한 화면에서 라인이 모두 보이는 것이 가장 이상적이기 때문
      • 위아래도 마찬가지로. 위아래가 너무 길어지면 Flattening 작업을 해주는 것이 바람직
      • 긴 문자열을 사용해야 하는 경우, 이례적 예외가 있을 수 있음
  2. Logic을 module화 하여 사용하는 습관 들이기
    • 실제 기술 면접과 같이 Interviewer 앞에서 손코드를 작성하는 자리가 아닌 이상, 위와 같은 코드는 가독성이 떨어짐
    • 코드의 Logic을 module화 하게 되면 가독성이 좋아질 뿐더러, 80 Columns Rule의 준수도 가능해짐
    • Module화 한 method들을 import하여 한 번에 같이 사용
    • Module화 하여 사용할 경우 적절한 'Exception Handilng'에 대한 고민도 같이 하게 됨
  3. static한 작성이 아닌 적절한 Unit test를 통한 코드의 작성
    • 반드시 완벽한 로직을 생각하고 난 후에 코드를 작성할 필요는 없음
    • assert와 pytest를 잘 활용하여 작성한 method가 올바르게 작동하는지 등의 Unit Test를 수행하며 작성하는 것이 좋은 접근 방법
    • +) 2번에서의 Module화는 Method 단위의 Test 또한 가능하게 해주는 장점이 있음
  4. Function(Method) Call과 관련한 성능 관련 이슈
# 좋은 예
count = len(array)
while i < count:
	~~~~~~~~~~~

# 안 좋은 예
while i < len(array):
	~~~~~~~~~~~~~~

위의 두 코드 중, 좌측의 코드가 변수 메모리를 하나 더 사용함에도 불구하고 성능면에서 더 효율적일 수 있음. 오른쪽 예의 코드와 같이 len() 함수를 반복적으로 사용하는 경우를 피할 수 있게 해주기 때문.


변수의 선언을 메모리의 낭비라고 생각하지 말고, 위의 예에서와 같이 자주 사용될 것 같은 값은 변수로 미리 만들어 재사용하는 것이 더 효율적


그렇다면 위의 내가 작성한 Selection Sort에서 최소 값 원소의 index를 찾는 안쪽 for문의 Logic을 method화 하면 어떨까?

# 기존에 작성한 코드

for i in range(0, size_b-1):
	tmp_min = b[-1]
	idx = -1

	for j in range(i, size_b-1):
		if b[j] < tmp_min:
			tmp_min = b[j]
			idx = j

	b[i], b[idx] = b[idx], b[i]

# method화 하여 호출한 코드

for i in range(0, size_b-1):
	idx = find_min_idx(b[i:])

	b[i], b[idx] = b[idx], b[i]

내가 작성한 코드의 경우, 함수 호출 없이 한 Logic 안에서 모든 연산이 이루어진다. 그러나, 두 번째와 같이 해당 영역 Logic을 method로 만들어 호출하게 되면 Stack 메모리에 분기(Jump) 명령어가 추가적으로 실행되어 값을 얻을 수 있게 된다. Heap 영역 연산에 비해 Stack 영역에서의 연산이 보다 더 저렴한 연산이라 할 지라도 이는 분명 성능면에서 손해를 가져올 수 있다.


그럼에도 아래와 같은 코드를 사용하는 것이 더 바람직하다고 할 수 있다. 그 이유는 method를 재호출하여 얻는 '코드의 가독성'이 method의 호출로 인해 생기는 '성능면의 손해'를 상쇄시키고도 남기 때문이다. 따라서 이렇다 할 큰 성능의 차이를 보이지 않을 것이라고 생각되는 Logic의 경우 멘토님이 말씀하신 바와 같이 아래의 코드 작성법을 사용하여 코드의 가독성을 택하는 것이 바람직하다.


cf. C언어 계열에서의 inline 함수가 존재하는 것도 이러한 이유에서 비롯된다. inline 함수를 사용하게 되면 가독성과 성능이라는 두 마리 토끼를 다 얻을 수 있다. 그러나 과도한 inline 함수의 사용은 Overhead의 증가로 이어지기 때문에 적절하게 사용하는 것이 중요


Learn Practical things

  1. vim
    • 멘토링 진행 전, Ubuntu를 설치해오라고 한 이유의 한 부분을 차지할 정도로 강력한 텍스트 편집기
    • 개발을 함에 있어 shortcut과 command만 잘 익히고 있으면, 마우스 사용으로 인한 시간과 동선의 낭비를 획기적으로 줄일 수 있음
    • 특별히 선호하지 않는 에디터가 있지 않는 이상 VS Code에 vim plug-in을 설치해서 사용하는 것이 괜찮은 선택
  2. git
    • 협업이 중시되는 전산직종에서 git을 다루는 것은 필수적
    • 능통하게 다룰 수준은 아니더라도, 기본적인 사용법은 모두 숙지하고 있어야 함
    • 생활코딩의 강좌 '지옥에서 온 git' 를 통해 학습하는 것을 추천
  3. Linux
    • 2000년대 초반까지만 해도 윈도우 기반의 서버와 리눅스 기반의 서버 모두 사용되었으나, 이제 99% 이상의 서버가 리눅스에서 작동
    • 클라이언트 개발자가 된다 하더라도 개발자가 리눅스 CLI(Terminal)를 접하지 않을 일은 전혀 없음
    • 따라서 Linux terminal 환경에서 코드를 작성해보고, 서버를 띄워보는 등의 경험을 하는 것은 필수적

프로그래밍 언어에 대한 멘토님의 고견

  • 언어 선택에 큰 고민을 하는 것은 효율적 고민이 아닐 수 있음. 잘 나가는 회사는 사용할 언어에 크게 제약을 두지 않음
  • 지금 유행하는 언어와 플랫폼이 언제 시장에서 도태될지 모르는 곳이 IT 시장. 따라서 우리는 변화하는 환경에서도 지속적으로 사용할 수 있는 지식을 갖추어야 하는데 그것이 바로 전산학과 관련된 기본 지식
  • 전산학에서 배우는 Computer Architecture, Data Structure, Algorithm 등은 10년 전에도 중요한 것이었고, 향후 10년 간도 중요할 것
  • 따라서, 전산학에 대한 기본기를 튼튼하게 갖추는 것을 최우선 목표로 삼는 것이 좋음. 전산학에 대한 이해도가 좋은 사람은 새로운 언어를 습득하는데에 있어 짧게는 6개월 길면 1년 정도의 시간만 투자하면 해당 언어로 원하는 프로그램을 작성할 수 있는 수준에 이를 수 있음. 즉, 전산학을 통해 배움에 대한 가성비를 갖출 수 있음
    • 멘토님의 Angular 이야기를 들으며 백기선님이 학습법과 관련하여 하신 이야기가 생각이 났다. 기본기를 갖추고, 두루두루 잘 할 수 있는 개발자가 되도록 노력하자!

  • 그럼 우리는 어떻게 해야할 것인가?
    1. 내가 사용(해야)하는 Main language와 생산성을 위한 Script language 최소 2개 언어를 다룰 수 있어야 함
      • 나의 경우, Data Engineering에 큰 부분을 차지하는 Hadoop eco-system이 모두 Java로 작성되어 있기 때문에 Java를 Main language로, 내가 생각한 것들을 바로 구현해볼 수 있는 생산성을 위한 Script language로는 Python을 가져가고자 함. 차후에는 Scala도 공부해보고 싶다.
    2. 두 언어를 사용하여 내가 원하는 서비스를 웹으로 구현(웹 사이트, 게시판 등)할 수 있을 정도로 웹 관련 지식도 갖추어야 함

다음 주 까지의 Assignment

  1. Hash Table 구현
  2. Priority Queue 구현


  • 우리가 아직까지 자료구조를 공부해야 하는 이유?
    • 우리가 구현할 서비스에 따라 Data를 대상으로 하는 연산의 종류가 다를 수 있음
      • 어떠한 서비스는 데이터의 조회를, 또 어떠한 서비스는 데이터의 추가를...
    • 따라서 해당 연산에 강점을 가지는 적합한 자료구조를 사용하는 것이 성능과 비용면에서 좋은 선택
    • 완벽한 Data Structure는 없다. 그러나 나의 서비스 환경에서의 최적 Data Structure는 존재한다.
  • 자료구조 교재 하나 택해서 다시 처음부터 끝까지 복습하기(교재는 크게 중요하지 않음)
  • 단순히 해당 자료구조를 구현해보고 그치는 것이 아니라 Python에 내장되어 있는 List, Dictionary 자료형과의 추가, 검색, 삭제 등의 연산 시간을 비교해보며, 왜 수행속도 면에 있어 차이가 있을까. 그 내부 동작에 대한 고민을 깊게 해보는 것이 나중에 큰 자산이 될 것


+ Recent posts