이 글은 개발자가 아닌 주변 지인들로부터, 현업에서 엑셀로 데이터를 처리하다가 여러가지 한계점을 느끼고 데이터 베이스를 배우고자 하는 니즈가 있다는 것을 알게 되어, 이와 비슷한 경험을 겪은 사람들을 위해 작성된 글입니다.

따라서 추가적으로 질문이나 요청사항이 있다면 이 글에 댓글 등의 방법으로 피드백을 남겨주시면 글에 내용을 추가하거나 추가 글을 작성하도록 하겠습니다.

------------------------------------------------------------------

엑셀 vs 스프레드 시트

일단 용어에 대해 살짝 명확하게 하고 가자면, 스프레드시트와 엑셀은 의미에 있어서 차이가 있습니다. 스프레드시트는 표 형식으로 데이터를 처리할 수 있는 컴퓨터 프로그램을 뜻합니다. 엑셀은 마이크로소프트라는 회사에서 만든 스프레드 시트 프로그램의 상표명이라고 볼 수 있죠. 마치 스프레드 시트와 엑셀의 관계는 유리테이프와 스카치테이프, 고체풀과 딱풀, 라면과 삼양라면, 햄버거와 불고기버거의 관계라고 볼 수 있습니다. 엑셀외에도 한컴오피스에서 만든 한셀이라는 프로그램도 스프레드시트 프로그램 중 하나입니다. 엑셀이 제일 유명한 스프레드 시트 프로그램이니, 앞으로는 편의상 엑셀이라고 칭하겠습니다.

 

엑셀을 왜 쓸까요?

엑셀은 표 형식으로 데이터를 처리하는 스프레드시트 프로그램입니다. 따라서 표 형식으로 나타내면 편리한 데이터들을 처리하기 위해서 씁니다.

CRUD 데이터 처리

여기서 데이터 처리라는 것은 데이터 쓰기, 읽기, 바꾸기, 지우기와 같은 동작들인데, 이 용어들을 영어로 표현하면 Create, Read, Update, Delete인데 이 단어들의 앞글자를 따면 CRUD가 됩니다. 이 CRUD는 컴퓨터 프로그램에서 데이터를 처리할때 가장 기본이 되는 4가지 동작들입니다. 엑셀은 이 4가지 동작이 다 손쉽게 가능합니다.

Create를 할 때에는 엑셀의 빈 셀에 값을 쓰면 되고, Read는 해당 셀을 클릭해서 데이터를 확인해볼 수 있습니다. 검색이 필요한 경우 Ctrl + F를 눌러서 검색이 가능합니다. Update(수정)가 필요할때는 셀을 클릭해서 새로운 값을 입력하거나, F2를 누른 뒤 값을 변경하면 됩니다. Delete(삭제)는 해당 셀을 클릭한 뒤 키보드 delete 키를 누르면 됩니다.

다소 복잡한 데이터 처리

데이터 정렬이 필요할때에는, 칼럼 이름에 필터를 건 뒤, 오름차순 혹은 내림차순으로 정렬하기를 누르면 쉽게 정렬이 됩니다. 그 외에도 평균값을 구하거나, 총합을 구하거나, 순위를 구하거나 등의 다소 복잡한 데이터 연산이 필요한 경우 엑셀에 내장된 함수들을 이용해서 계산을 할 수 있습니다.

 

데이터베이스는 뭘까요?

사전적인 의미로는 여러사람들이 공유하여 사용할 목적으로 체계화하여 통합 및 관리하는 데이터 집합이라고 합니다. 데이터를 쉽게 잘 다룰 수 있도록 잘 해놓은 데이터 덩어리라고 보면 된다. 사실 기본적인 내용들은 엑셀과 다를 바 없는 것이, 똑같이 데이터를 다루고, CRUD 연산도 당연히 잘 됩니다.

Database vs DBMS(Database management system)

여기서 데이터베이스(Database)와 DBMS(Database Management System)의 차이를 살짝 짚고 넘어갑시다. 데이터베이스는 데이터들 모여있는 것, 데이터 그 자체를 의미하고, DBMS는 데이터 베이스를 처리하는 컴퓨터 프로그램입니다.

눈치채었을 수 있겠지만, 이제 언급할 것들은 사실 데이터베이스가 아닌 DBMS의 특징들이라고 볼 수 있습니다. 그냥 데이터베이스는 추상적인 개념들이고, DBMS는 우리가 당장 실무에서 써먹을 수 있는 녀석들이니 말입니다.

 

엑셀 vs 데이터베이스(DBMS)?

엑셀과 데이터베이스의 장단점을 매우 간단하게 비교하면 이렇습니다. 엑셀이 배우기는 훨씬 쉽고 직관적입니다. 데이터베이스는 익히고 사용하는데 지식이 더 많이 필요하고 어렵습니다. 

대신 데이터베이스는 엑셀보다 더 좋은 성능과 기능들을 가지고 있습니다. 여기서 더 좋은 성능이라 함은, 엑셀의 경우 데이터가 몇 만개 정도만 되어도 컴퓨터가 버벅이고 느려지고 처리가 힘들어질 수 있으며, 데이터 개수의 제한이 명확하지만 데이터베이스의 경우는 그 보다 더 많은 개수의 데이터도 쉽고 빠르게 처리할 수 있습니다. 또한 엑셀에서 처리하는 것 보다 더 복잡할 수 있는 연산들을 처리할 수 있습니다.

그리고 엑셀의 경우 남과 데이터를 공유하려면, 엑셀파일을 저장한 뒤, 이 파일을 이메일 등을 통해서 공유를 해야 하는데, 데이터베이스의 경우 실시간으로 데이터 편집한 부분을 반영시켜서 남과 동시에 작업이 가능합니다.

구분 엑셀(스프레드시트) 데이터베이스(DBMS)
장점 직관적, 익히기 쉽다 사용 시 쿼리 언어에 능숙해야함
데이터 모델링 시 지식과 숙련도 필요
단점 많은 데이터 처리시 느려짐(저성능)
다소 복잡한 내용 처리 어려움
동시작업 불가능
많은 데이터 쉽게 처리(고성능)
복잡한 처리 가능
동시작업 가능

뭐 쉽게 생각하면, 데이터베이스가 익히기는 어렵지만 엑셀에서 할 수 있는 것들 대부분을 다 할 수 있고 성능도 더 좋고 강력합니다. 하지만 데이터 베이스를 잘 쓰기 위해서는 데이터베이스용 쿼리 언어인 SQL을 사용할 줄 알아야 하고, 데이터 모델링에 대한 지식과 숙련도도 필요합니다.

실제 소프트웨어 회사에서 데이터베이스의 성능을 극대화까지 끌어내기 위해서, 이러한 SQL 쿼리 작성과 데이터 모델링만 전문적으로 행하는 DBA라는 직무가 따로 있을 정도로 깊게 들어가면 매우 어려운 영역입니다.

하지만 그렇게까지 복잡하지 않은 데이터들을 처리할때에는 가볍게 공부해서 시도해볼 수 도 있을 것 같습니다.

References

ko.wikipedia.org/wiki/%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4

www.oppadu.com/%EC%97%91%EC%85%80-vs-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-%EC%B0%A8%EC%9D%B4%EC%A0%90-1%ED%83%84/

www.oppadu.com/%EC%97%91%EC%85%80-%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%B2%A0%EC%9D%B4%EC%8A%A4-%EC%B0%A8%EC%9D%B4%EC%A0%90-%EB%B9%84%EA%B5%90/

opentutorials.org/course/3162/19527

https://www.datacamp.com/community/tutorials/role-underscore-python

 

Role of Underscore(_) in Python

In this tutorial, you're going to learn about the uses of underscore(_) in python.

www.datacamp.com

이 글은 위 글의 번역 및 정리 글입니다.

 

파이썬관련 찾아볼 일이 있어서 보다가 언더바에 대한 내용들이 있어서 한번 정리합니다.

파이썬 개발자들 중 많은사람들이 파이썬에서 언더바의 역할에 대해 잘 모르는데, 이를 이용해서 코드 생산성을 늘릴 수 있습니다. 이번기회에 한번 알아봅시다.

for _ in range(100)
__init__(self)
_ = 2

만약 당신이 파이썬 개발자라면, 위와 같은 파이썬 코드들을 본 적이 있을 것입니다.

위에서 _는 각각 다른 조건에서 특별한 의미를 갖습니다.

 

일단 6개의 다른 용도가 있는데 차근차근 알아봅시다.

  1. 인터프리터에서의 사용
  2. 무시하는 값
  3. 루프에서 사용
  4. 숫자값의 분리
  5. 명명용
    1. 앞에 하나가 쓰이는 경우
    2. 뒤에 하나가 쓰이는 경우
    3. 앞에 두개가 쓰이는 경우
    4. 앞 뒤로 두개씩 쓰이는 경우

이제 예제들과 함께 알아봅시다.

 

1. 인터프리터에서 사용

파이썬 인터프리터에서 가장 마지막 표현식의 결과값을 자동적으로 "_"라는 변수에 저장합니다. 물론 여기 저장된 값을 다른데다가 저장할 수 있습니다.

일반적인 값처럼 쓸 수 있습니다.

>>> 5 + 4
9
>>> _
9
>>> _ + 6
15
>>> _
15
>>> a = _
>>> a
15

위와 같이 동작하는걸 볼 수 있습니다.

2. 무시하는 값

언더바는 무시하는 값으로도 쓰일 수 있습니다. 해당 값을 unpack하기 싫다면, 그냥 _에다가 할당하면 됩니다.

## 값을 버립니다.
a, _, b = (1, 2, 3) # a = 1, b = 3, _에 2가 할당됩니다.
print(a, b)

## 여러개 값 버리기
## *(변수) 는 unpack할때, 여러개의 값을 하나의 변수에 저장할때 쓰입니다.
## 이는 확장된 Unpacking이라고 불리며,Python 3.x 버전에서만 가능합니다.
a, *_, b = (7, 6, 5, 4, 3, 2, 1)
print(a, b)

테스트를 해보니, _에다가 할당하면 _도 일반 변수처럼 쓰이고, 1번처럼 Last expression을 저장하지 않게 됩니다. del _를 통해 해당 변수를 삭제하면 1번때처럼 Last expression을 저장하게 됩니다.

 

3. 루프에서 사용

for 루프를 돌 때 사용할 수 있습니다. 아래처럼 쓰는 것도 하나의 방법이 됩니다.

## _를 이용해서 루프를 돕니다.
for _ in range(5):
    print(_)

## 리스트 순회를 _를 이용해서 합니다.
## _ 를 일반 변수처럼 사용할 수 있습니다.
languages = ["Python", "JS", "PHP", "Java"]
for _ in languages:
    print(_)

_ = 5
while _ < 10:
    print(_, end = ' ') # 'end'의 기본값은 '\n'인데 이걸 변경해줍니다.
    _ += 1

실행결과는 예상한 것과 같게 아래처럼 나옵니다.

0
1
2
3
4
Python
JS
PHP
Java
5 6 7 8 9

4. 숫자값의 구분

숫자값이 길다면, 자릿수 구분을 위해 _를 중간중간에 넣어줄 수 있습니다.

이진수값이나 16진수, 8진수 값도 동일하게 적용할 수 있습니다.

## 여러 숫자 표현법
## 아래 값들이 정확한지 확인하기위해 int 함수를 써 볼수도 있습니다.
million = 1_000_000
binary = 0b_0010
octa = 0o_64
hexa = 0x_23_ab

print(million)
print(binary)
print(octa)
print(hexa)

실행 결과는 아래와 같습니다.

1000000
2
52
9131

5. 언더바를 포함한 변수명들

 변수, 함수, 클래스 명 등에 언더바가 사용될 수 있습니다.

  • 앞에 하나의 언더바 _variable
  • 뒤에 하나의 언더바 variable_
  • 앞에 둘의 언더바 __variable
  • 앞과 뒤에 두개의 언더바 __variable__

5.1 앞의 하나의 언더바

앞에 하나의 언더바로 시작하는 이름은, 내부 사용용입니다(internal use only). 일단 예시부터 봅시다.

class Test:

    def __init__(self):
        self.name = "datacamp"
        self._num = 7

obj = Test()
print(obj.name)
print(obj._num)

위 코드를 실행하면 아래처럼 됩니다.

datacamp
7

변수명 앞에 _를 하나 붙였다고 해서, 해당 변수를 접근하지 못하게 되진 않습니다. 하지만 모듈을 import해서 쓰는 경우 효과가 발생합니다.

아래와 같은 코드를 한번 확인해봅시다.

## filename:- my_functions.py

def func():
    return "datacamp"

def _private_func():
    return 7

이제 my_functions.py를 가져오기 위해 import 구문을 써보자. 파이썬은 언더바 하나로 시작한 이름들은 import하지 않는다.

>>> from my_functions import *
>>> func()
'datacamp'
>>> _private_func()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name '_private_func' is not defined

위의 코드 결과를 보다시피, _로 시작한 _private_func는 찾지를 못한다.

위와 같은 에러를 방지하기 위해, from module import *가 아닌 모듈 자체를 import를 해보자. 

>>> import my_functions
>>> my_functions.func()
'datacamp'
>>> my_functions._private_func()
7

앞에 _ 1개로 시작한 이름은 내부 사용 전용이라는 뜻이다.

5.2 뒤의 하나의 언더바

가끔 파이썬 키워드에 해당하는 이름으로 변수명, 함수명, 클래스명으로 쓰고 싶을때가 있을 수 있다. 이럴때 이 방법이 유용하다. 마지막 부분에 언더바를 하나 추가함으로써 파이썬의 기본 키워드들과 충돌하는거를 방지할 수 있다.

>>> def function(class):
  File "<stdin>", line 1
    def function(class):
                 ^
SyntaxError: invalid syntax
>>> def function(class_):
...     pass
...
>>>

마지막에 하나의 언더바를 추가하는 명명법은 파이썬 키워드와 겹치는 경우를 방지하고 싶을때이다.

5.3 앞의 두개의 언더바

앞에 두개의 언더바로 시작하는 명명법은 name mangling이다. mangle은 짓이기다라는 뜻인데, 알아보기 힘든 모양으로 만든다라는 의미로 볼 수 있겠다.

앞에 두개의 언더바로 시작하는 명명법은 파이썬 인터프리터에게 해당 서브클래스의 attribute 이름을 바꾸어서 이름 충돌이 나지 않게 하라고 말하는 것이다. 서브클래스 이야기가 나온걸로 봐서 상속하는 경우와 관련이 있는 것 같다.

 

일단 예시를 보자.

class Sample():

    def __init__(self):
        self.a = 1
        self._b = 2
        self.__c = 3
obj1 = Sample()
dir(obj1)

dir한 결과는 아래와 같이 나온다.

['_Sample__c',
 '__class__',
 '__delattr__',
 '__dict__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__gt__',
 '__hash__',
 '__init__',
 '__init_subclass__',
 '__le__',
 '__lt__',
 '__module__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 '__weakref__',
 '_b',
 'a']

dir함수는 클래스 객체의 모든 attribute들을 리턴해준다. 선언한 변수들을 dir 리턴값 중에서 한번 찾아보자.

a와 _b는 잘 보인다. 맨 마지막에 있다. _b는 내부 사용용으로만 쓰인다.

Sample클래스에 분명히 __c라는 맴버변수를 선언했는데, __c는 없고 대신 _Sample__c라는 값이 있다.

이것이 name mangline이다. 나중에 다른 클래스가 Sample이라는 클래스를 상속할때, 그 클래스에서 이 변수를 override하는 걸 방지해준다.

 

다른 클래스를 만들어서 Sample이라는 클래스를 상속해보자.

class SecondClass(Sample):

    def __init__(self):
        super().__init__()
        self.a = "overridden"
        self._b = "overridden"
        self.__c = "overridden"
obj2 = SecondClass()
print(obj2.a)
print(obj2._b)
print(obj2.__c)

상속을 한 뒤, 초기화를 하는 과정에서 Sample의 맴버변수들에 값을 다 대입하고 있다.

overridden
overridden



---------------------------------------------------------------------------

AttributeError                            Traceback (most recent call last)

<ipython-input-2-4bf6884fbd34> in <module>()
      9 print(obj2.a)
     10 print(obj2._b)
---> 11 print(obj2.__c)


AttributeError: 'SecondClass' object has no attribute '__c'

__c를 찾지 못해서 에러가 발생했다. name mangline때문에 obj2.__c가 아닌 obj2.__SecondClass__c로 바뀌었다. obj2._SecondClass__c를 한번 출력해보자.

print(obj2._SecondClass__c)
overridden

편의상 결과도 같이 썼다.

그러면 _Sample__c는 어떻게 되었는지 한번 보자.

print(obj1._Sample__c)
3

mangle 된 이름으로 잘 있다.

 

맴버함수(메소드)를 이용해서 mangle 된 두개의 언더바로 시작하는 변수를 접근할 수 있다. 예시를 보자.

class SimpleClass:

    def __init__(self):
        self.__datacamp = "Excellent"

    def get_datacamp(self):
        return self.__datacamp

obj = SimpleClass()
print(obj.get_datacamp()) ## "Excellent"를 출력한다. __datacamp에 해당하는 값이다.
print(obj.__datacamp)     ## 여기서 에러가 발생한다. 변수 이름이 바뀐다.

메소드(getter, setter)안에서는 잘 접근을 한다. 하지만 외부에서 멤버 변수로 직접 접근하려고 하면 에러가 난다.

 

언더바 2개로 시작하는 명명법은 변수뿐만 아니라 메소드 이름에도 적용이 가능하다. 예시를 보자.

class SimpleClass:

    def __datacamp(self):
        return "datacamp"

    def call_datacamp(self):
        return self.__datacamp()

obj = SimpleClass()
print(obj.call_datacamp()) ## __datacamp()의 리턴값과 같다.
print(obj.__datacamp())    ## 여기선 에러가 난다.

__로 시작한 함수는 안에서만 호출이 되는 용도라고 보면 될 것 같다.

다른 객체지향 언어에서 private access modifier(접근 지정자)의 역할이라고 보면 될 것 같다.

 

다른 예시를 한번 보자.

_SimpleClass__name = "datacamp"

class SimpleClass:

    def return_name(self):
        return __name

obj = SimpleClass()
print(obj.return_name()) ## "datacamp"를 출력하게 된다.

위와 같은 코드도 정상적으로 동작을 한다.

 

좀 특이한 방식의 개념이다.

5.4 앞뒤로 2개의 언더바

파이썬에서 앞뒤로 2개의 언더바로 둘러쌓인 명명법을 본 적이 있을 것이다. 이녀석들은 매직 메소드(magic method) 혹은 dunder 메소드라고 불린다.

class Sample():

    def __init__(self):
        self.__num__ = 7

obj = Sample()
obj.__num__

이 명명방식을 변수 이름으로 사용할 경우 변수명 충돌이 일어날 수 있기 때문에 가급적 삼가하는게 좋다.

dunder method에서 dunder는 double under(score)를 뜻하며, 보통 연산자 오버로딩을 할 때 많이 사용한다고 한다.

매직 메소드는 __init__, __add__, __len__, __repr__등이 있다.

 

__init__메소드는 생성자라고 보면된다. 호출없이 초기화할때 호출되는 함수이며, 클래스의 인스턴스가 생성될때, 실행되게 된다.

 

__repr__ 메소드는 해당 클래스를 출력하고자 할때 내부적으로 호출되는 메소드라고 보면 된다. 자바로 치면 toString() 함수와 유사하다고 볼 수 있겠다.

References

https://www.geeksforgeeks.org/dunder-magic-methods-python/

어쩌다 보니 환경 구축만 계속 여러번 하게 되는 듯 하다.

회사 리눅스 컴이 맛가서 밀고 다시 설치하고, 집컴와서 vm에 Ubuntu 깔고 다시 설치하고 등등... 그냥 이렇게 된 김에 한번 싹 정리하자.

 

Linux에서 포너블 문제풀이든 할 환경을 싹 구축해보자.

사실 그렇게 복잡하진 않다.

Virtualbox에 Ubuntu 18.04 설치

이 과정은 뭐 대충 다 아실거라 생각한다. Virtualbox 설치하고, Ubuntu 18.04 iso 다운받아서, 대충 머신만든 뒤, iso넣어서 부팅하면 아래 처럼 나온다.

Live CD로 플레이하는게 있고, 설치하는게 있는데 당연 설치이다. 언어랑 키보드는 English(US)고르고 그냥 계속 Continue누르면 된다.

Normal install이라고 되있는데 Minimal install으로 바꿔서 했다.

기본 옵션으로 간다.

스왑 알아서 박는다는데 걍 Continue로 간다.

어디있냐는데 Seoul 그대로 간다. 타임존이랑 apt repository 때문에 물어보는거일듯 함.

유저명이랑 패스워드 정하라는데, 어차피 vm안에 놈이니 대충정하자. 좀 기다린다

이제 설치가 다 된거다.

 

virtualbox extension 설치

설치를 하고 나면 화면이 굉장히 작고 host랑 클립보드 공유가 안되는 걸 알 수 있다.

extension을 설치해줘야한다.

게스트 확장 CD 이미지 삽입을 누르면, vbox내에 guest extension 설치 파일이 있는 이미지가 CD로 들어간것처럼 된다

실행하고 안애 파일을 설치시켜주면 된다.

비밀번호를 치면 알아서 설치가 된다.

이제 재부팅을 해주자. 이제 vbox 윈도우를 전체화면을 하면 안에 화면도 꽉차게 된다. 꿀!

 

클립보드 공유도 설정을 해주자.

우분투 화면잠금 해제

Settings -> Privacy -> Screen Lock을 Off해주면 된다.

우분투 sleep mode 해제

Power saving에 never 해준다.

pwntools 설치

일단 python3부터 설치를 해야 한다. 그리고 python3-pwntools를 설치를 하면 된다.

$ sudo apt update && sudo apt install -y python3 python3-dev python3-pip git && pip3 install --upgrade git+https://github.com/arthaud/python3-pwntools.git

 

잘 설치되었는지 한번 확인해보자.

별 다른 에러가 없는거보니, 잘 된 것 같다.

 

gef 설치

$ sh -c "$(curl -fsSL http://gef.blah.cat/sh)"

 

(curl을 미리 설치해야 한다)

 

잘 된다. 사실 뭐 별것없다. 쓰고나니 다 간단하기만 했네

vscode 설치

text editor로 vscode를 깔아보자.

공홈가서 deb 파일을 받은 뒤

$ sudo dpkg -i vscode.deb 하면 된다.

 

References

https://github.com/hugsy/gef

https://github.com/arthaud/python3-pwntools

+ Recent posts