Introduction
안녕하세요, codedbyjst입니다.
앞으로 이어지는 글들을 통해 개발 중 이루어졌던 선택들을 꺼내볼 건데요,
일단 기존 db단에 어떤 문제점이 있었는지 이야기 해 보도록 할게요.
기존엔 어땠나요?(SQLite)
일단 전 포스트에서 밝혔듯, 기존엔 django 프레임워크를 기반으로 작성되었다고 말씀 드렸었죠?
일단 초기 db단은 어떻게 설정되어 있었는지 알아보도록 하죠.
django는 기본 db로 SQLite를 이용합니다.
sqlite의 특징이라면, 부가기능이라곤 없는 정말 가볍고 단순한 db랍니다.
기본값인 것도 있고, 그냥 파일 하나만 옮기면 db 전체가 옮겨지니 테스트할때도 편합니다.
또 DB를 직접 확인하고 싶을때 볼 수 있는 gui 프로그램도 있구요.(물론 예쁘진 않습니다만..)
그래서 별 다른 걱정 없이 sqlite로 작업을 진행중.. 결국 와야 하는 순간이 오고 맙니다.
database is locked
db설정을 완료한 후 python 코드로 db 갱신을 테스트하는 중이었는데, 위의 에러가 뜨면서 갑자기 멈춰버리는 겁니다.
아니, 이게 무슨 버그지? 난 db 건든적이 없는데?
라는 생각을 갖고 해결을 위해 stackoverflow을 돌아다니던 중, 공식 문서를 확인하라는 조언을 보아 공식 문서를 확인해보게 됩니다.
중점만 요약하자면,
sqlite는 태생 자체가 정말 '가벼운' db입니다.
기본적인 crud 작업이 가능하지만, 만약 '동시에' 여러개의 작업을 요청하면 어떻게 될까요?
기타 db들은 동시성을 처리함에 있어서 여러가지 효율적인 방법을 이용합니다.
이 과정 속에서 동시성에 문제가 생기지 않도록, db는 자체적으로 lock을 걸었다 풀게 되는데요.
타 db들은 이러한 처리에 유연하게(효율적이고 안전하게 자원을 이용하여) 대처할 준비가 되어 있어서 괜찮지만,
정말 심플한 구조로 되어 있는 sqlite는 이러한 것에 대비가 되어 있지 않습니다.(설계 의도에 따른 결과입니다!)
제 db updater는 db의 빠른 갱신을 위해 multiprocessing(병렬 처리)을 이용하고 있었습니다.
따라서 위의 문제에 대해 sqlite의 한계점에 봉착한 것입니다.
또한, 병렬 처리를 사용하고 있지 않았다고 해도, db updater의 처리속도는 매우 빠르기 때문에 과도한 대기시간으로 인해 db updater나 sqlite단에서 결국 timeout error가 날 수밖에 없는 상황이었습니다.
이를 해결하기 위해선...
1. timeout을 억지로 늘리고 병렬 처리를 포기한다
-> 갱신이 느려져서 유저가 불편해함. 또, 애초에 서버 처리능력은 늘 일관되지 않을 수 있는데 어느 정도 timeout을 설정할 것인가?
2. db를 바꾼다.
-> 새로 db를 배워야한다.
의 선택지가 있었고, 당연히 후자를 선택할 수 밖에 없었습니다. 애초에 이게 django측에서 추천한 방법이기도 했구요.
바꾸는건 확정이고, 뭐로 바꾸지?
그렇다면 django가 지원하는 db에는 어떤 것들이 있는지 살펴봐야겠네요.
django는 아래와 같은 db들을 지원합니다.
숙련된 개발자라면 각각의 특성을 알고(아니면 사실 거의 비슷함을 알고) 적절하게 선택하겠지만, 저에게는 좀 많이 어려웠습니다.
그러니까 우선 기존에 하던 것처럼, 어떤 걸 가장 많이 쓰는지 참조했습니다.
흠, 우선 가장 많이 쓰이는건 mysql이네요.
조금 더 찾아보니 mysql에 대한 칭찬 일색입니다. 현장에서도 많이 쓰인다구 하구요.
그렇다면 mysql로 결정일까요?
mysql로 마음이 기울던 중, 개발중에 느꼈던 요구사항을 하나 떠올리게 됩니다.
'db에 배열을 넣을 수는 없나?'
DB에 배열을...넣어?
모든 관계형 DB는 기본적으로 위와 같은 구조를 갖고 있습니다.
각각의 row에 대해 column에 맞는 값들이 들어가 있죠.
따라서 db에 위와 같은 데이터를 저장할 때엔, 새로운 row(2017,삼성전자,30000000)를 넣어주면 됩니다.
그런데 생각해보니, 회사명 데이터가 과도하게 중복되어진 것처럼 보이는 겁니다. 매번 중복된 회사명 데이터를 row에 넣어줘야 하니깐요.
또 나중에 db단에서 데이터를 꺼낼 때에도 어차피 '특정 년도'의 데이터를 불러오기보단 '특정 회사'의 데이터를 일괄적으로 불러오게 되니, 회사명을 primary key로 해서 불러오는게 더 쉽고 효율적이지 않나? 싶었구요.
일단 이런 식으로 저장하기 위해서는 db단에서의 지원이 필수 불가결입니다. 일단 지원해야 하던지 하죠.
다만 뒤에 설명하겠지만, 여러 이유들로 인해 관계형 db는 기본적으론 배열필드를 제공하지 않습니다.
하지만 그렇다고 못 하는 건 아니죠!
PostgreSQL라면 가능합니다!
django는 postgresql 전용으로 ArrayField를 제공합니다.
Arrayfield가 있으면, 어떠한 꼼수 없이 제가 원하던 방식으로 개발할 수 있게 됩니다!
그리고 또 하나, postgresql의 엄청난 장점인 pgadmin도 있었구요.
pgadmin은 postgresql의 관리 gui 소프트웨어입니다. db를 관리할때 많이 보게 될거에요.(콘솔보단 gui가 낫죠.)
정말 예쁘지 않나요? mysql도 workbench라는 관리 gui가 있긴 한데...
postgres의 저 이쁜 관리 콘솔에 이미 현혹되버린 저는 이미 마음을 굳혀 버렸습니다.
근데 그럼 왜 mysql로 바꿨나요?
좋은 질문입니다. 그렇게 코끼리, 아니 postgresql이 좋았다면 왜 db를 옮길때 mysql로 바꿨을까요?
이를 설명하기 위해선 위에 전 더이상 위에 말씀드린 arrayfiled와 같은 방식을 채용하지 않았다는 것부터 말씀 드려야 겠네요. 어째서일까요?
효율성으로 인한 비효율성
위와 같은 방식은 회사명의 중복은 해결해주지만, 다른 비효율성을 불러 일으킵니다.
예를 들어, 한 특정 년도의 데이터만을 수정하려 한다면 기존 데이터를 어딘가에 잠시 저장하고, 수정한 값을 해당 데이터에 집어 넣은 후 다시 db에 넣어줘야 합니다. 기존에는 그냥 한 줄만 골라 수정하면 됬을 텐데 말이죠.
또, 데이터를 집어넣을때 관계형 db는 무결성을 유지하기 위해 type checking(int필드에 제대로 된 int값이 들어왔는지)을 진행하는데, 이런 작업때 비효율적이구요.
그리고, 특정 년도의 data를 나중에 필요로 하면 어떻게 해야 할까요? 연도 배열을 확인해서 특정 년도의 index를 확인하고, 해당 index를 이용해서 영업이익 배열에서 값을 찾아야 할 겁니다. 필요없는 과도한 양의 데이터를 받아오는건 덤이구요.
혹시나 연도 배열과 영업이익 배열의 길이가 다른데 눈치채지 못했다? 언젠가는 해당 자료를 사용할 때 문제가 터질 겁니다.
사실, 위와 같은 방식으로 구현하는게 얻는 게 더 많겠다 싶다면 db 자체를 관계형 db가 아닌 nosql쪽을 쓰는게 더 나을 겁니다. 하지만 그럴 바에야 약간의 비효율성을 감내하는게 낫겠더라구요.(기본적으론 관계형 db가 저에겐 더 유리했기 때문에 이것때문에 또 nosql로 갈 수는 없었습니다.)
왜 MySQL인가요?
위에서도 나왔지만, mysql말고도 관계형 db는 많습니다.
당장 그냥 arrayfield기능을 쓰지 않고 postgresql을 그대로 쓰면 새로 배울 필요도 없었구요.
그런데 왜 굳이 바꿨을까요?
1. 개발자 풀이 큽니다.
위에서도 말씀드렸듯, 개발자들이 가장 많이 사용하는 db입니다.
가장 많이 사용하는 툴이라는건,
수많은 관련 자료들이 즐비하다는 의미고(모르면 stackoverflow가 살려준다는 의미입니다),
이는 신입 개발자인 저에게는 매우 중요한 요소입니다.
앞으로 취업하게 될 기업에서(취업이란게 오긴 하는건지 모르겠습니다만...) 사용하고 있을 툴일 가능성이 높다는 의미이기도 하구요.
또, 오랫동안 사랑받은 툴이기에 안정성 역시 충분히 검증되었다고 볼 수 있습니다.
2. 무료입니다.
💸
바로 이게 mysql이 여기까지 성장하게 된 원동력이라고 생각합니다.
사실 최고급 data(신용카드 데이터, 개인정보 등)을 다루는 기업은 oracle db를 주력으로 이용합니다.
다만 oracle db는 기업에서 상당한 비용을 지불해야 사용할 수 있는 고급 db이며, 개인이 감당할 용도로 만들어진 툴이 아닙니다.
그렇다면 mysql은 어떨까요?
mysql은 무료입니다.
상업적 이용은 유료여서 oracle사에게(사실 mysql도 oracle사의 상품이긴 합니다!) 라이센스 비용을 지불해야 합니다만,
여기서의 상업적 이용이란 아예 커스텀 버전의 mysql을 판매하거나 할 때의 이야기이고, 기본적으로 이용하는것은 완전히 무료입니다.
사실 postgresql을 선택할때 '상업적 이용은 유료라고? 아이고... 그냥 다른거 써야겠다' 했었는데, 그냥 이용하는건 무료더라구요.
걱정하지 않으셔도 됩니다!
Conclusion
결국, 돌고 돌아 mysql의 품으로 돌아왔습니다.
꽤 긴 여정이었지만, 결국 '마땅히 따라야 했던 방법'으로 돌아온 것 같기도 하고,
해당 과정들을 거쳐오면서 db에 대한 이해력도 많이 늘어났으니 돌아보자면 좋은 경험이었다고 할 수 있겠네요.
postgresql은 점점 성장하는 중인 db입니다.
결국 mysql로 돌아오긴 했지만, postgresql은 상당히 개발자 친화적인 sql문도 제공하여 개발하기에도 더 편할 수 있습니다. pgadmin같은건... 진짜 치트키 아닌가 싶을 정도로 잘 만들었구요.
다만 안전성은 조금 떨어지는지, 제가 사용하는 pgadmin은 ssh 터널링이 재부팅하고 나면 제대로 안 작동하는 버그가 있긴 하네요. 언젠가는 패치되겠죠.
비교하자면, mysql은 상대적으로 매우 안정적입니다. 툴도 포함해서요.
많은 사람들이 여전히 mysql을 쓰는 이유이기도 하겠죠. 저도 신뢰도 있는 db가 필요하다면 일단 mysql부터 고려할 듯 합니다. 물론 극한의 안전성이 필요하다면 oracle db를 써야겠지만요.
앞으로는 nosql도 한 번 사용해보고 싶네요.
제가 작업했던 db는 관계형 db의 장점이 더 커서 관계형 db로 진행했습니다만, 막상 많은 책들에서 MongoDB같은 nosql을 쓰니까, 나도 한번 써보곤 싶다...라고 생각하고 있습니다.
여튼, 유익한 시간이었습니다!
긴 글 읽어주셔서 감사드리고, 다음 개발일지에서 뵙겠습니다!
'돈복사닷컴 > 개발일지' 카테고리의 다른 글
갈아엎어! django에서 react로 (2) | 2022.01.18 |
---|---|
돈복사닷컴, 새롭게 돌아왔습니다! (0) | 2022.01.15 |