# 1
2022년 01월 15일 현재, 나는 개발자다.
더 정확하게 말하면 파이썬이라는 프로그래밍 언어를 기반으로 데이터 수집 크롤러를 만드는 6개월 차 신입 개발자다.
올해로 32살, 늦은 나이에 개발이라는 업을 시작하고 6개월이나 지났지만 아직도 모니터 2개가 세팅된 사무실 책상에 앉아 개발을 하고 있는 내 모습이 가끔 낯설다.. 왠지 안 어울리는 것 같다는 생각도 든다.
왜 갑자기 개발자가 되기로 마음먹었나?라는 질문에 대한 나름 이유가 있었고 이걸 위해 나는 내 팔자에도 없었던 개발자라는 직업을 갖게 되었다.
그리고 개발자가 되려고 결심한 순간부터 개발자로 취직한 지금까지 모든 사건이 2021년 한 해에만 이루어진 일이었다. 이제 2022년 새해를 맞이하여, 불과 2주 전에 지나간 다시 오지 않을 2021년을 기념하며 나의 개발자 도전기의 모든 사건이 담겨있는 2021년을 회고해보려 한다.
# 2
2021년 1월, 나는 공장 노동자였다.
지난해(2021년) 초까지, 나는 경북 구미에서 스마트폰 모듈을 만드는 공장에서 일했다.
격주로 바뀌는 주/야간 근무환경과 하루 12시간이라는 지루한 공장생활이었다.
내가 공장 노동자가 된 이유는 2020년, 큰 꿈을 안고 도전했던 창업 실패로 모든 걸 잃고 더 이상 잃을 게 없을 때, 나에겐 선택권이 별로 없었다. 그래서 이미 폐인이 된 나를 일으켜 세우고 죽지 않기 위해 밥과 숙소를 제공하는 공장으로 무작정 들어갔다.
공장에서의 생활은 그리 나쁘지는 않았다. 월세, 휴대폰 비, 대출 연체 걱정이 사라졌고, 오히려 하루 12시간 격주로 바뀌는 주/야간 패턴으로 인해 잠과 일을 반복하다 보니 내 통장 잔고는 늘어나고 있었다.
하지만 통장 잔고는 늘어날지언정, 내 마음은 언제나 공허했다.
IT 분야에 매료되어 무작정 서울로 달려가 고군분투하며 고난과 성장을 반복하며 키워간 나의 꿈, 나의 미래가 점점 나에게 멀어지면서 희미하게 보였고, 이제는 다른 세상의 이야기 같이 느껴졌다.
그래서 쉬는 날마다 엄청난 공허함을 느꼈다. 공장 동료들과 미친 듯이 술도 마셔보고, 공장 기숙사에 있는 동안 동기부여 영상과 자기 계발서를 미친 듯이 보아도 공허함은 채워지질 않았다.
그러던 어느 휴일 날, 습기 가득 찬 공장 기숙사에 쳐 박혀 있자니 너무 답답해서 기숙사 주변을 일단 걷기 시작했다.
내가 좋아하는 음악을 들으며 아무 생각 없이 걷고 또 걷다 보니, 근심과 걱정이 조금씩 사라지는 기분이었고, 과거를 회상하며 내가 했던 선택과 행동에 대해 돌아볼 수 있게 되었다.
그렇게 쉬는 날마다 해가 저물어가는 시간 때 기어 나와 목적지를 정해두지 않은 채, 다리에 힘이 풀릴 때까지 구미 도시 전체를 배회하며 걷고 또 걸었다.
계속 걷고 또 걷다 보니 조금씩 내 안의 부정적인 생각들과 공허함을 조금씩 떨쳐내기 시작했고, 걷기를 시작한 지 2개월쯤 되던 어느 날, 만약 공장을 그만두면 무엇을 해야 할까를 고민하기 시작했다.
과거, 나는 많은 사람들에게 가치를 제공하는 영향력 있는 IT 서비스를 만들고 회사를 세우는 게 꿈이었다. (사실 ‘었다’가 아니고 여전히 그렇다.)
그래서 IT 분야를 지식을 공부하기 위해 무작정 서울에 올라와서 교육원을 다녔고, IT 사업을 배우기 위해 사물인터넷 회사 사업부로 취업해서 나름의 성과와 커리어 그리고 많은 경험을 쌓은 후, IT 서비스를 기획하고 친구와 창업을 도전했다. 그리고 1차 도전은 처참하게 실패로 끝이 났고 창업 이후 너무 힘든 시기를 보냈다.
단지 한 번의 실패였고, 창업 기간도 그리 길지 않았다. 사실 지금 생각하면 이렇게 힘들 필요도 없었는데 그때 당시엔 세상이 무너지는 기분이었다.
구미 시내를 걸으며 생각했다. 나는 왜 한 번의 작은 실패로 이렇게 까지 무너졌을까?
그 당시 많은 걸 잃고 방황하다 나 자신을 조금 내려놓다 보니 조금은 나를 제삼자의 입장에서 바라볼 수 있게 된 것 같다. 그 당시, 나는 실패에 대한 리스크를 전혀 생각하지 않았고, 실패했을 때를 대비한 물질적/정신적 준비가 전혀 되어 있지 않았다.
결국, 실패했고 나는 다음이 없었다. 그저 한 번의 도전에 내 모든 걸 걸고 있었다.
나는 안전장치 없이 아슬아슬하게 외줄 타기를 하고 있었다. 그리고 중심을 잃은 순간 바닥으로 추락했다.
그래서 생각했다. 다시 한번 도전할 기회가 주어진다면 나는 무엇을 해야 할까?
내가 만들고자 했던 것은 IT 서비스이다. 그래서 나는 IT 분야의 기획/제안/마케팅/영업/사업화 역량을 키워왔다. 마음만 먹으면 언제든지 내가 만들고 싶은 서비스가 생기면 즉시 사업 스케치를 할 수 있다.
하지만 IT 서비스라는 것은 결국 구현되어야 한다. 아무리 좋은 아이디어와 기획이 나온다고 해도, 서비스를 구현할 수 있는 역량이 없으면 의미가 없다.
설령 아무리 좋은 아이디어와 기획이라고 생각해도 시장에서 외면받을 수 있고 여러 번 실패할 가능성이 있다. (아니, 평생 실패만 하다가 끝날 수도 있다. 시장은 냉혹하다.)
그렇기 때문에 실패를 지속할 수 있어야 한다. 그리고 실패했을 때 리스크 관리할 수 있는 고정 수입이 있어야 한다.
일을 하면서 서비스를 만들 수 있는 기술을 배우고 지속적으로 실패하면서 시도할 수 있는 일은..
바로 개발자가 되는 것이었다.
프로토타입 정도로 만들 수 있는 능력을 키운다면 일을 하면서 자투리 시간에 내가 원하는 서비스를 만들고 언제든지 시장의 반응을 보면서 실패했을 때 다음을 기약할 수 있다.
2021년 1월에, 구미 대교 인근 낙동강 산책로를 걸으며 개발자가 되기로 마음먹었다.
내가 원하는 서비스는 방대한 데이터를 수집/가공하여 사람들에게 가치 있는 정보를 제공하고 싶다는 추상적인 꿈을 토대로 데이터 사이언스 분야에서 가장 많이 쓰이는 파이썬이라는 언어로 선택했다.
# 3
2021년 2월, 개발자가 되기 위해 공장 생활을 정리하고 나의 고향 금당도로 향했다.
내 고향 금당도 앞바다 일출 풍경
나의 고향 금당도는 완도군의 부속 섬 중 하나이다.
대한민국 지도를 켜고 남쪽 끝 부분을 보다 보면 여러 점들 가운데 하나가 보이는데 그곳이 금당도이다.
광활한 우주도 작은 점으로부터 시작되었듯이 내 인생의 시작점도 이 작은 점에서 시작되었다. 내 인생의 시작점으로 다시 돌아가는 발걸음이 그리 가볍지는 않았다.
서울에서 성공하고 돌아오겠다고 자신 있게 말하고 떠났지만 5년 후, 나는 빈털터리에, 생기를 잃은 좀비 같은 모습으로 다시 돌아왔다. 안 그래도 마른 체형이었던 나는 창업 실패 이후 폐인 생활과 공장생활을 하면서 10키로 이상이 빠져서 뼈만 앙상하게 남은 좀비 같았다.
이런 몰골에 풀이 죽어있는 모습으로 돌아온 나를 본 부모님 심정은 오죽했을까. 하지만 부모님은 이런 모습으로 돌아온 나에게 아무 말도 하지 않으셨다.
고향집에 오자마자 엄마가 차려준 밥을 풀이 죽은 채, 먹고 있는 나의 모습을 조용히 지켜보고 있는 엄마의 눈에서 슬픔을 느낄 수 있었지만 나는 애써 외면했다. 정말 죄송스럽고 할 말은 많았지만 그냥 더 좋은 일자리를 얻기 위해 잠시 준비하러 내려왔으니 걱정 말라는 말만 남긴 채, 남은 밥을 마저 먹고 방으로 들어갔다.
그리곤 다짐했다. 독하게 공부하고, 프로그래밍 언어를 독학해서 반드시 개발자가 되겠노라.
나는 파이썬 관련 서적 3개를 사 왔는데, 1) 파이썬 기본 문법 및 기초 관련 책, 2) 증권 데이터 분석 책이었으며, 다른 하나는 3) 파이썬 언어를 기반으로 웹 사이트를 쉽고 빠르게 구축할 수 있게 도와주는 장고(Django) 프레임워크 책이었다.
고향에 가져간 데이터 분석과 웹사이트 개발 관련 책(파이썬 기초 책은 기억이 안 난다..)
내 계획은 파이썬 기본 문법을 숙지하고, 데이터 분석 기술을 습득한 뒤, 증권 데이터를 수집하고 분석한 정보를 웹사이트에 표출할 수 있는 수준까지 학습하는 것이었다.
금당도에 돌아온 다음날부터 파이썬 기본 문법을 공부하기 시작했다.
파이썬이라는 언어를 독학해야 했지만 그나마 내가 가진 이점은 오랜 기간 IT 분야에 몸담은 경험이 있기 때문에 IT 서비스 및 시스템에 대한 기본 개념과 이해도가 있었으며, IT 분야로 내 인생 목표를 설정하던 20대 중반, IT 배경지식을 배우기 위해 국비지원 개발자 양성 교육원을 다녔던 경험이 있어서 프로그래밍 기본 배경지식을 어느 정도 알고 있었다.
하지만 국비지원 교육원을 수료한 이후 개발자의 길로 가지 않고 IT 사업분야 쪽으로 진로를 선택했기 때문에 프로그래밍 기본 문법 및 배경지식이 희미하게 머릿속에 남아있을 뿐이었다.
그나마 IT 분야에 접점이 전혀 없는 일반인보다 출발선이 조금 앞서 있을 뿐,
결국 기초부터 다시 시작해야 했다.
프로그래밍에는 수많은 언어가 존재한다.
그중 나는 파이썬을 선택하게 되었지만 예전 국비지원 교육원에서 배웠던 자바 언어와 처음 프로그래밍을 공부할 때 학습해야 하는 구성이 거의 동일했다.
데이터를 담는 변수의 개념,
수많은 데이터의 종류를 분류하고 효과적으로 처리하기 위한 자료형,
자료형에 담긴 데이터들을 원하는 조건에 맞게 순차적으로 뽑아 쓰기 위한 반복문,
자료 조건이 참과 거짓 여부에 따라 연산과, 특정 기능을 수행하기 위한 조건문,
데이터 가공, 연산 등 특정 기능을 수행하기 위한 함수,
특정 기능을 수행하는 여러 함수들이 모여 하나의 큰 작업 흐름을 정의하기 위한 클래스,
그리고 각 언어가 지향하는 방법론,
내가 생각하기에 모든 언어가 지향하는 방법론에 따라 조금 구성이 바뀔 수는 있어도 적어도, 내가 공부했던 자바와 파이썬이라는 언어의 프로그래밍 기초 구성은 이러했다.
다른 언어도 프로그래밍 기초를 공부할 때 대부분이 위의 범주로 구성되지 않을까 싶다.
이래서 프로그램 언어 1개를 깊게 공부하면 다른 언어는 비교적 쉽게 습득할 수 있다는 말이 나오는 것 같다.
어쨌든 나는 파이썬스러운(?) 기초 문법을 익히기 시작했다.
전에 자바를 조금 접해봐서 그런 것인지, 아니면 파이썬이 초보자가 배우기 쉬운 언어라서 그런 건지, 이유는 잘 모르겠지만 파이선 기초 문법을 이해하는데 2주도 안 걸렸던 것 같다.
아버지는 고향에서 한평생 어업을 하셨고 현재 문어 잡는 일을 하신다.
나는 고향에 내려가 아버지를 도와 문어잡이 하면서 프로그래밍 공부를 병행했다.
문어잡이는 극한직업(?)에서 나왔을 만큼 굉장히 육체적으로 힘든 일이다. 하지만 대부분의 바닷일이 그렇듯 한번 나갈 때는 엄청 고된 일이지만 쉬는 날이 많다는 장점이 있었다.
왜냐하면 바닷일은 물때라는 것이 있어서 물살이 강할 때는 나가지 않고, 물살이 약한 시점에 바다에 나가서 그물과 줄을 끌어올린다. (업종마다 다르긴 함)
물의 세기가 1 물부터 14 물까지 있다고 가정할 때 숫자가 올라갈수록 물살이 강하다는 의미이다.
보통 문어 잡이를 나가는 시점은 1 물부터~5 물까지이고 나머지는 바다에 던져놓고 기다리는 시기이기 때문에 나머지 물살이 강한 시점은 그물이나 줄 손질 같은 잔업을 한다.
아버지는 내가 취직 준비를 해야 한다는 걸 알았기 때문에 나를 배려해서 잔업은 시키지 않으셨다. 아버지의 배려 덕에 14일 중 5일 정도만 바다에 나가서 일하고 나머지는 프로그래밍 공부에 집중했다.
사실, 새벽부터 배를 타고 문어를 잡는 10시간 동안에도 프로그래밍 학습을 놓지 않았었다.
문어 통발이 연결된 줄을 다 끌어올리고 새로운 줄을 끌어올리기 위해 이동하는 시간 동안 넓은 바다를 보며 프로그래머가 되어있는 나를 상상했고, 문어 통발을 올리기 위해 줄을 쉬지 않고 끌어올리는 기계를 보며, 반복문을 떠올렸으며, 배 위에 가지런히 쌓여있는 문어통발을 보며 자료형을 떠올렸다.
내가 학습한 프로그래밍 기초 지식을 문어 잡이 작업에 대입해가면서 프로그래밍 기초 지식에 대한 이해도를 한층 끌어올리기 위해 노력했다.
문어를 잡는 시간과 잡지 않는 시간 모두 나는 프로그래머가 되기 위한 학습을 하고 있었던 것이다. 그만큼 개발자가 된다는 것은 나에게 간절했고, 다시 일어설 수 있는 희망 한줄기 같은 꿈이었다. 그렇기 때문에 독하게 마음먹고 준비할 수 있었던 것 같다.
프로그래밍 기초 문법을 숙지하고 본격적으로 데이터 분석 기술을 공부하기 시작했다.
최근 빅데이터와 인공지능 기술이 대두되며 파이썬 인기도 나날이 높아지고 있다. 파이썬은 직관적이고 간결한 문법으로 일반인도 쉽게 배울 수 있다는 특징뿐만 아니라 데이터 수집부터 전처리, 모델링, 시각화 등에 필요한 라이브러리(기능)를 모두 갖추고 있어서 데이터 사이언스 분야에 최적화된 언어로 평가되고 있다.
나는 크롤링 기술을 활용해서 증권 데이터를 수집/저장하고 확보된 데이터를 가공하여 다양한 증권 데이터 분석 기법을 적용하여 증권시장의 흐름을 예측하고 자동으로 매매할 수 있는 서비스 및 시스템을 만들어보기로 했다.
증권 데이터 분석 공부는 김 황후님의 ‘파이썬 증권 데이터 분석’이라는 책을 통해 공부를 하기 시작했다.
네이버 증권에서 몇 년치 국내 주식 시세를 수집하기 위해 ‘뷰티풀 수프(Beautiful Soup)와 리퀘스츠(Requests)’라는 라이브러리 사용했고, 수집된 내가 원하는 형식의 데이터로 가공하고 시각화하기 위해 ‘판다스/맷플롭립’라는 라이브러리들을 사용했으며, 이외 유명한 경제학자들이 만든 유명한 분석 알고리즘을 적용하여 자동으로 주식을 매매할 수 있는 여러 기능을 숙지하고 구현할 수 있었다.
이 책을 통해 여러 증권 데이터 분석 기술을 학습하는데 한 달 정도 걸렸다.
책에 있는 예제를 그대로 따라 하면서 공부한 수준이지만 비슷한 기능을 반복적으로 사용하는 것이 많았기에 여러 데이터 분석 라이브러리 사용이 익숙해지기 시작했던 것 같다.
이렇게 이 책 한 권을 한 달간 공부하다 보니 증권 데이터 분석과 자동매매 시스템을 간단한 수준으로 구현할 수 있었다.
하지만 문제는 증권 데이터 분석 결과 및 자동매매 시스템이 동작하는 과정에서 생긴 결과물들이 터미널에 못생기게 표출된다는 점이다. 나 혼자 사용하는 프로그램이면 상관없지만 나는 이걸 누구나 쉽게 이용할 수 있는 서비스 형태로 만들고 싶었다.
그래서 터미널에서 아름답지 못하게 동작하는 데이터 분석과 자동매매 프로그램을 웹 서비스 형태로 만들기 위해 웹사이트 만드는 방법을 공부하기 시작했다.
데이터 분석 기능은 파이썬 언어가 최적화되어있고 내가 공부하면서 만든 것들도 다 파이썬 언어 기반이기 때문에 파이썬 언어로 웹사이트를 만들고 연동해야 호환성이 좋을 것 같았다.
데이터 분석 책으로 주식 데이터 분석 및 자동매매 시스템을 구현함
그래서 파이썬 언어를 기반으로 가장 널리 쓰이는 웹 프레임워크인 장고(Django)를 선택하게 되었고
장고를 활용한 웹사이트 개발을 공부하기 시작했다.
장고를 공부하기 위해 구입한 책은 이성용/김태곤님의 ‘(만들면서 배우는 웹 개발 A to Z) 장고+부스트랩 파이썬 웹 개발의 정석’이었다.
이 책을 통해 클라이언트와 서버 간의 관계 및 웹 개발 시작 전 필요한 기초 지식부터 장고의 핵심 디자인 패턴(MTV)을 활용하여 블로그를 웹사이트를 만드는 과정에서 웹의 기본인 CRUD(Create, Read, Update, Delete)를 습득하고 화면 디자인을 예쁘고 실용적으로 만드는 방법뿐만 아니라 로그인 기능, 댓글 기능, 검색 기능, 깃허브로 소스 관리 등 웹사이트 제작에 필요한 여러 유용한 요소들을 학습할 수 있었고 나만의 웹사이트를 전 세계에 배포하는 과정까지 총 600페이지 분량으로 알차게 구성된 책이었다.
책에 나온 설명을 잘 따라가면서 책에 나온 예제 소스 코드를 그대로 따라 치면 그럴듯한 웹사이트 하나를 만들 수 있을 정도로 어렵지 않았지만 예제를 따라 치는 것에서 그치지 않고 책에서 설명하는 모든 내용을 이해할 수준이 될 때까지 읽고 또 읽으며 천천히 공부해 나갔다.
그 이유는 책에서는 책에서 나온 예제 소스는 블로그 웹사이트를 만들기 위한 소스코드였으나, 나는 데이터 분석 프로그램과 웹사이트를 연동하여 증권 데이터 분석 결과를 웹사이트 상에서 표출하려고 했기 때문에 웹사이트에 필요한 기본 기능을 충분히 숙지한 뒤 내가 원하는 사이트를 만들 수 있으려면 웹사이트 구축에 필요한 기본 기능을 제대로 이해하고 있을 필요가 있었다.
책을 통해 간단한 블로그 웹사이트를 만드는 데 성공하고 난 뒤, 지금까지 배운 것을 토대로 책에서는 제공하지 않았지만 스스로 게시판 기능을 만들어보기도 했는데 블로그 기능보다 훨씬 단순한 형태의 기능이었지만 역시 가이드 없이 기능 구현하는 것이 쉽지 않았다. 그래도 결국 일주일 만에 게시판 기능을 완성할 수 있었고, 이때 웹 사이트 개발에 대한 이해도가 많이 올라갔던 것 같다.
장고(Django)로 구현한 나만의 웹 사이트
파이썬 기초부터~ 데이터 분석과 웹사이트 구축까지 공부하는데 2달 정도 걸렸던 것 같다.
중간중간 문어잡이 하면서 쌓인 피로 때문에 공부를 제대로 못한 날이 몇 번 있었지만 그래도 2달간 열심히 공부한 덕분에 파이썬 데이터 분석 프로그램과 블로그/게시판 기능을 갖춘 간단한 웹사이트를 만들 수 있게 되었고 이는 나만의 포트폴리오가 하나 만들어졌다는 의미이기도 했다.
개발자 전직 준비를 위해 고향에 약 3~4개월 머물렀는데 2개월 동안은 파이썬 문법 숙지, 파이썬 데이터 분석 및 웹사이트 제작을 위한 기술을 공부하였고 남은 1~2개월 동안은 지금까지 배운 내용을 토대로 나만의 웹 서비스를 기획하고 구현하는데 집중하였다.
내가 마지막 한 달 동안 만든 웹사이트는 ‘증권/금융 데이터 분석 및 투자 정보 공유 웹사이트’였다.
데이버 분석 결과를 웹사이트와 연동하여 표출한 화면
이 웹 사이트는 네이버 증권에서 제공하는 국내 주식 시세 데이터를 매일 수집/분석하여 분석 결과를 웹사이트에서 제공하는 웹사이트다. 증권 데이터 분석 결과물뿐만 아니라 기본적인 웹사이트와 동일하게 로그인, 게시판, 블로그 등 다양한 편의 기능도 추가할 수 있도록 고안하였다.
나는 개인적으로 파이썬이라는 언어를 처음 시작할 때부터 웹사이트 제작까지 보다 내가 원하는 서비스를 기획하고 구현한 마지막 한 달이라는 시간 동안 프로그래밍 실력과 이해도가 급격히 상승했던 것 같다. 책과 인터넷 강의라는 가이드가 있을 때와는 차원이 다르게 만드는데 애를 먹었다.
100만 건이 넘는 증권 데이터를 화면에 표출하려다가 화면이 다운되는 상황을 맞이하기도 했고, 증권 데이터를 보여줄 화면 레이아웃이 자꾸 원하는 대로 만들어지지 않아 며칠을 고생한 적도 있고, 기존 증권 데이터 수집용 DB와 웹사이트 전용 DB가 달라서 멀티 DB 환경을 구축하기 위한 환경설정을 몰라서 엄청 헤매는 등 수많은 예외상황과 오류를 경험하고 이를 해결하는 과정에서 웹과 프로그래밍 언어에 대한 이해도가 확 올라가는 듯한 기분이 들었다. 여러 가지 시행착오와 우여곡절 끝에, 내가 원하는 기능이 구현된 나만의 웹사이트가 완성되었다.
# 4
2021년 05월, 개발자라는 새로운 커리어에 첫 도전장을 내밀기 위해 고향을 떠나,
전남 광주에 사는 친동생 집으로 갔다.
개발자로 취업하기 위해서는 입사 지원을 하기 위한 이력서와 포트폴리오가 필요했다.
내가 목표로 하는 지역은 서울/경기 지역이었고, 동생 집에 머무는 동안 이력서와 포트폴리오를 만들고 원하는 회사에 입사 지원한 후 서울에 무작정 올라가려는 계획이었다.
개발자가 되기 위한 취업준비를 해본 경험이 없어서 처음에 어떻게 이력서를 작성해야 할지 막막했다. 그리고 막상 IT 기획/제안/마케팅/영업 등 사업 분야에서 쌓아 올린 커리어와 경험은 많았지만 개발 분야의 이력은 단 1줄도 쓸게 없었다. IT 분야에 오래 몸담았을 뿐, 개발자 채용에 나의 예전 경험은 크게 메리트가 없었다.
개발자 이력서와 포트폴리오 작성하는 방법을 유튜브나 인터넷 검색을 통해 아무리 찾아보아도 거의 비슷한 내용이었고, 그들이 말하는 방식대로 이력서 작성한다면 나는 쓸 내용이 별로 없었다.
최근 IT 직종의 수요가 많고 인기가 높아진 탓에 개발자를 준비하는 취준생들도 많을 테고, 그들과 비슷한 양식으로 이력서를 작성한다면 나는 그들에 비해 경쟁력이 전혀 없어 보였다.
내가 원하는 기술을 배우기 위해 학원에 가서 체계적으로 배운 것도 아니고, 혼자 고향에서 주먹구구식으로 독학으로 공부했기 때문에 프로젝트를 같이 진행할 사람도 없던 탓에, 팀 사이드 프로젝트를 해본 경험도 없었고, 개발 관련 자격증도 하나도 없는 상태였다.
이대로 취업 전선에 뛰어든다면 나는 면접관을 만나보지도 못하고 쓰러질게 뻔했다.
그래서 고민을 한참 하다가 한 가지 결론에 이르렀다. 내가 내세울 수 있는 포트폴리오는 고향에서 독하게 공부하며 만들었던 데이터 분석 및 주식 정보공유 사이트였다.
나는 이것 하나로 승부를 봐야 했고 다른 선택지가 없었다.
내가 파이썬 개발자로서 갖춘 기술 스택과 데이터 분석 그리고 웹에 대한 이해는 이 포트폴리오에 모두 담겨있었고 이것 말고 다른 걸로 자신 있게 설명할 자신도 없었다.
그렇기에 내가 자신 있게 명중시킬 수 있는 이 총알 하나로 내 모든 걸 걸기로 했다.
회사에서는 당연하게도 소규모라도 여러 개의 프로젝트 경험이 있는 인재를 선호한다. 또한 인사담당자 입장에서는 하루에도 수십~수백 개의 이력서를 검토해야 하기 때문에 여러 프로젝트의 핵심만 간결하게 서술해주길 원할 것도 안 봐도 뻔했다.
열심히 기술을 습득하고 다양한 프로젝트 경험을 한 데다, 이걸 포트폴리오에 간결하게 서술하고 심지어 스토리까지 더해져 감동까지 있는 그런 인재의 이력서와 포트폴리오.. 완벽하지 않은가?
하지만 안타깝게도 개발자로서 ‘나’란 사람은 인사담당자가 좋아할 만한 그 어느 것도 갖추지 못했다.
나도 사람인지라 불안한 마음에 유튜브와 인터넷 검색을 통해 여러 개발자 취업 케이스 및 이력서/포트폴리오를 작성법을 찾아보았지만 불안감만 더 증폭될 뿐이었다. “더 준비해야 하나?”라는 생각까지 했다.
하지만 나는 더 물러설 곳도 없었다.
만약 물러선다면 또다시 문어를 잡으며 더 많은 포트폴리오를 만들어낼 뿐이었다.
그래서 그냥 내가 가진 이 총알(포트폴리오)에 나의 스토리, 그리고 내가 아는 모든 것을 쏟아내기로 했다.
비록, 하나밖에 없었던 허술한 내 첫 포트폴리오였지만 그 순간만 큼은 진심이었기에 나는 흔들리지 않고 포트폴리오 문서를 작성해 나갔다.
하나밖에 없는 이 포트폴리오에 내가 이만큼 알고 있다는 것을 어필하기 위해 포트폴리오를 만들기 시작한 시점부터 완성되기까지 모든 순간과 과정을 되돌아보고 곱씹으며 써 내려갔다. 그러다 보니 완성된 포트폴리오는 파워포인트(PPT)로 100장이 넘어가고 있었다.
솔직히 이건 너무 과한 것 같아서 줄이고 줄여서 결국 약 65장 분량이 나왔다.
단 하나의 포트폴리오가 65장 분량이라면, 그 어느 인사담당자가 다 보겠는가?
하지만 나는 더 이상 포트폴리오를 수정하지 않았다.
가독성 없이 마냥 길기만 한 허술한 포트폴리오일 수도 있지만 이 포트폴리오는 나의 2번째 도약과 희망이 담긴 포트폴리오였고, 나의 고뇌와 결의가 담겨있으며 지금까지의 나의 여정과 스토리가 고스란히 담긴 포트폴리오였다.
누가 뭐라고 하든, 나는 이 포트폴리오를 나의 혼이 담겼다는 뜻에서 ‘영혼의 포트폴리오’라고 정의했다.
많은 사람들이 개발자로 취업을 하기 위한 준비는 이렇게 해야 하고 이력서는 이렇게 작성하고 포트폴리오는 저렇게 작성해야 하며, 이런 기술 스택과 이런 것을 준비해야 한다고 말한다.
심지어 나를 지지하는 주변 지인들까지 내 포트폴리오 분량과 준비 상태를 보고 취업하기 힘들 수도 있겠다는 피드백을 주기도 했다.
이미 오랜 기간 동안 시장(개발 및 취업)에서 만들어진 정형화된 방법과 형식들이 존재했다.
정형화된 형식과 방법을 잘 따르면 따를수록 취업확률도 높아진다는 사실도 인정한다.
하지만 나는 이미 예전부터 사회나 시장이 규정한 기준들과 방법을 잘 따르지 않았다.
그로 인해 나는 남들 다 가지고 있던 대학교 졸업장도, IT 개발 시장에서 취업에 도움이 되는 그 어떤 자격증과 경험도 없었다.
이런 상태에서 이미 정형화된 방법과 형식 그리고 기준을 따라 이력서나 포트폴리오를 아무리 예쁘게 잘 정리한다고 한들, 이미 기준에 부합한 준비된 자들과 경쟁 상대조차 못됐다.
그렇다면 나는 내가 원하는 직업을 얻기 위해 나를 뽑아 주는 사람에게 보여줄 수 있는 경쟁력은 무엇이란 말인가?
오랜 시간 고민하였고 결국, 고민 끝에 내린 결론은 “나라는 사람을 보여주자”였다.
내가 작성한 단 하나의 포트폴리오 내용 안에는 이 포트폴리오 왜 만들게 되었는지와 개발자가 되려는 이유도 담겨있고, 내가 가진 기술을 설명할 유일한 결과물이었기 때문에 기능과 화면 하나하나 디테일하게 서술했으며 심지어 쓸데없이 장황하게 늘어놓기도 했다. 마지막 장에는 개발자로서 새로운 커리어를 시작하려는 나의 각오와 다짐까지 적었다.
어떻게 보면 정말 미련한 전략이지만 또 다른 관점에서 보면 쥐뿔도 없는 놈이 걸 수 있는 유일한 승부수이자 경쟁력이었다.
정형화된 완벽함이 아닌 나만의 스타일과 색이 담긴 특이함으로 승부를 보기로 했다.
‘개발자로서 역량은 한참 부족하지만 그 누구보다 개발자에 대한 열망과 간절함이 있고 나를 뽑아준다면 누구보다 열심히 잘할 자신 있다. 나를 뽑은걸 후회하지 않을 것이다.’라는 식의 나의 간절함과 희망을 이 포트폴리오에 담으려 했던 것 같다.
누군가는 사회적 잣대가 아닌 온전히 ‘나’라는 인간 자체를 봐주는 사람이 있겠지 라는 나의 헛된 바람과 희망사항일 뿐일 수도 있었다.
그냥 내가 추구하는 방식과 방법이 옳다고 믿기로 마음먹었다.
또다시 나를 믿어보기로 결심했고 포트폴리오를 완성하고 바로 다음날부터 개발자로 취업 준비생스럽지 못한(?) 나만의 이력서와 포트폴리오를 가지고 본격적으로 취업 전선에 뛰어들어 나를 필요로 하는 회사를 찾아다니기 시작했다.
동생집에서 완성한 파워포인트 65page 분량의 영혼의 포트폴리오
지금까지 많은 경험과 허튼짓을 반복하며 나름 다사다난했던 인생을 살아오면서 깨달은 한 가지 사실이 있다.
그것은 바로 “누가 봐도 헛된 믿음일지라도, 그 믿음이 무엇이건 간에, 믿음의 힘은 강력하다는 것과 믿음이 있는 자는 없는 자와 비교도 할 수 없을 정도로 큰 힘을 발휘한다"는 사실이다.
그 믿음의 주체와 대상이 내가 될 수도 있고, 신이 될 수도 있고, 이념이 될 수도 있다.
믿음의 대상의 옳고 그름을 떠나, ‘믿음’에는 사람을 움직이는, 그리고 움직이게 하는 힘이 있다.
쥐뿔도 없는 내가, 지금까지 원하는 것을 할 수 있게 하고 작지만 작은 성취들을 이뤄낸 것도 ‘나는 할 수 있다’라는 나 자신에 대한 믿음이 있었기 때문인 것 같다.
이러한 믿음은 계속해서 나를 움직이게 하였고 고난과 절망을 견디게 해 주었다. 그리고 내 처지와 능력에 도저히 엄두 나질 않는 일을 도전할 수 있는 원동력이 되었다.
물론 스펙, 학벌, 돈, 자격증, 처세술 등 여러 가지 사회적 기준을 무시하며 살아온 혹독한 대가를 치르기도 했지만 결국 나에 대한 믿음이 절망에서 다시 일어설 수 있게 해 주었다.
(어느 정도 사회적인 기준도 따르는 것을 권장한다. 이걸 모두 무시한 채 살다가는 나중에 큰 대가를 치르게 된다.. 나도 다시는 못 일어날 뻔했었다.)
믿음이란 참으로 추상적인 개념이다.
그리고 ‘믿음’에는 실체가 없다. 보이지도, 잡히지도, 존재하지도 않는다.
하지만 내가 생각엔 믿음에 실체가 없는 것이 아닌, 실체가 믿음으로 만들어지는 게 아닌가 싶다.
지금 주위를 둘러봐도 이전에는 모두 없었던 것들이다. 노트북, 자동차, 냉장고, 책상 등등
이전에 없었던 것들이었지만 인간의 상상력과 믿음이 이 세상 모든 것들을 창조해냈다고 생각한다.
내가 되고 싶은 모습이 될 수 있다고 믿으면 곧 그 모습은 실체를 보일 것이고,
내가 갖고 싶은 것을 가질 수 있다고 믿으면 곧 그것은 내 앞에 실체로 나타날 것이다.
나는 개발자가 될 수 있다고 믿었다. 그리고 입사 지원을 시작한 지 2달도 채 안되어 원하는 기술을 배울 수 있는 회사에 개발자로 취업에 성공했다.
내가 다른 개발자 취준생들보다 뛰어나다고 생각하는가? 아니다.
기술적인 지식이나 실력, 스펙, 취업 준비 서류가 대부분의 취준생들이 평균적으로 나보다 높은 수준이었다.
나는 단지 나를 믿었고, 내가 믿는 것에 집중하고 행동했을 뿐이었다.
그리고 개발자가 되기 위한 6개월 여정 끝에 개발자가 되었다. 단지 이것뿐이다.
내가 개발자로 취업한 첫 직장은 IT 유통업을 영위하는 중견기업의 연구소였다.
연구소에서 운영하는 서비스 중 이커머스 분야에서 다양한 마켓 셀러들에게 판매 관리부터 상품 매출을 끌어올릴 수 있는 유용한 상품 정보 등 제공하는 서비스가 있었고 나는 이 팀에 합류하게 되었다.
마켓 셀러들에게 유용한 정보를 제공할 수 있으려면 셀러들의 판매 정보와 다양한 마켓의 상품정보를 수집하여야 한다.
나의 임무는 다양한 마켓 정보를 실시간으로 수집하는 크롤러 시스템을 만들고 유지보수하는 일이었다.
크롤러 시스템은 데이터 사이언스 분야에서 가장 널리 쓰이는 파이썬 언어를 기반으로 개발되고 있었고, 나는 파이썬 개발자로 크롤러를 만드는 것이 나의 첫 개발자 커리어의 시작이었다.
솔직히 취업 준비하는 2개월에 대한 자세한 설명 없이 취업 준비 후 개발자가 되었다는 정도만 말했는데 개발자로 취업하는 과정에서 운도 조금 따라준 것도 사실이지만 그래도 나름, 많은 고뇌와 고충이 있었고, 열심히 준비하기도 했다. 그리고 정말 내가 배우고자 하는 기술을 요구하는 수많은 회사에 입사지원을 했고 회사 5곳 정도 면접 보았고 최종적으로 3곳에서 합격 통보를 받게 되었다.
그리고 합격통보를 받은 3곳 중 연봉을 가장 적게 제시한 지금의 회사를 선택하게 되었다.
그 이유는 명확했다.
최종 합격받은 회사 중 2곳은 나의 이전 커리어(기획/제안/영업/마케팅/사업)에만 관심이 있었고, 면접 내내 개발 관련 질문보다 IT 사업 관련 질문을 더 많이 했으며, 노골적으로 기획 및 사업 쪽 일도 병행해서 할 수 있느냐라는 질문을 받기도 했다.
하지만 남은 1곳(지금의 회사)은 달랐다. 나의 전 커리어를 크게 신경 쓰지 않았고 오로지 개발자로서의 역량과 마음가짐에 대한 질문을 주로 하였다. 또한 내가 입사하게 되면 배우게 될 기술에 대해 자세히 설명해 주었고, 이것 외엔 다른 건 바라지 않는다고 하였다.
다른 2곳에 비해 연봉은 500~700 만원 정도 낮았다. 하나 나에겐 1초의 망설임도 없었다.
내가 배우고 싶은 기술을 배울 수 있고 개발 일을 집중할 수 있는 환경을 보장하는 회사에 입사하기로 결정하였다.
# 5
2021년 06월 21일, 개발자라는 새로운 커리어를 시작하게 된 날이다.
자, 이제부터 시작이다. 나의 새로운 도약을 위한 도전이~!
입사 전부터 개발자라는 직업을 가지는 동안 내가 얻고자 하는 기술적 목표는 명확했다.
개발자가 되기 전에 세웠던 목표였기에 현업을 경험하며 더 알아갈수록 더 세부적인 목표가 추가될 수도 있거나 방향이 조금 달라질 수는 있으나 앞으로도 크게 벗어나지 않을 듯하다.
왜냐하면 이 목표로 인해 개발자의 길을 선택했으니까..
내가 IT 분야에서 이루고자 하는 최종 목표는 세상 사람들에게 가치 있는 정보를 제공하는 서비스 혹은 시스템으로 다소 추상적이긴 하나 어떤 유형의 서비스를 만들지는 앞으로 고민해야 할 과업이고, 우선적으로 내가 개발자로 있을 동안에 이루고자 하는 목표는 2가지이다.
첫 번째는 가치 있는 정보를 제공하려면 세상에 존재하는 어떤 데이터든 수집할 수 있는 데이터 수집 기술을 습득하는 것이다. 21세기 대부분의 데이터는 웹상에서 얻을 수 있기에 세상 모든 데이터란 웹에서 표출되는 모든 데이터를 수집한다는 의미이다.
두 번째는 내가 수집한 데이터를 가공하여 가치 있는 정보를 전 세계 어느 누구나 볼 수 있도록 서비스 형태로 만들 수 있는 기술을 습득하는 것이다. 서비스란 웹이 될 수도 있고 응용 애플리케이션이 될 수도 있는 등 다양한 형태로 구현될 수는 있으나 전 세계 어느 누구나 이용될 수 있으려면 가장 적합한 것이 웹이라고 판단되기에 기본적인 웹 서비스 형태로 프로토타입을 만들고 배포할 수 있을 정도의 기술을 습득하는 것이다.
이 말은 화면으로 보이는 프론트 영역, 화면 뒷단에서 비즈니스 로직 및 데이터를 처리하는 백엔드 영역, 데이터를 저장하는 DB 영역, 그리고 원활한 배포 운영 그리고 서비스 관리 효율을 높여주는 데브옵스 영역 등을 포함하는 것이다.
지금은 첫 번째 목표를 이루기 위한 여정을 시작한 샘이다.
# 6
입사 후 3개월(2021년 7월~9월), 크롤링의 이해
이미지 출처 : https://jovian.ai/
현재 웹상에 있는 데이터를 수집하는 기술인 크롤링(Crawling) 기술을 배우고 개발하는 중이고 운이 좋게도 6개월이라는 짧은 기간 동안 나름 회사에서 운영하는 여러 크롤러(Crawler) 시스템 개발 및 유지보수를 해본 덕택에 다양한 크롤링 시스템 구조를 경험했고 크롤링 업무에 널리 쓰이는 최신 라이브러리 기반의 최신 방식의 크롤러와 예전 방식의 레거시 크롤러를 다 경험해보기도 했다.
입사 3개월 차 까지는 나에게 부족한 파이썬 문법을 보완하기 위한 공부를 하면서 회사에서 운영 중인 크롤러 시스템 구조 파악과 여러 크롤링 기술을 익히는 동시에 회사에서 요구하는 업무를 수행하는데 집중했었다.
입사 3개월 차로 접어들자, 어느 정도 크롤러 시스템 구조가 눈에 보이기 시작하였고 각 시스템에 적용된 크롤링 기술에 대한 장단점이 보이기 시작하였다.
크롤링(crawling)이란 인터넷에서 표출되는 웹 페이지를 그대로 가져와서 데이터를 추출하는 행위이며,
이러한 행위를 하는 소프트웨어를 크롤러(Crawler)라고 부른다.
오늘날, 우리가 필요로 하는 정보를 습득할 때 대부분 인터넷을 활용한다.
개인 컴퓨터가 상용화되기 시작하고 전 세계 사람들이 인터넷으로 연결되어 정보의 공유가 활발해지면서 하루에도 상상을 초월하는 양질의 정보가 인터넷상에서 쏟아져 나오고 있다.
작은 노트북 한대만 있으면 세상의 모든 도서관의 지식을 접할 수 있는 세상에 살고 있으며, 이 세상에 존재하는 모든 지식은 인터넷을 통해 대부분 얻을 수 있게 되었다.
허나, 하루에 생산되는 글로벌 데이터 전송량이 20조 비트라고 한다는 IBM의 추정치를 보더라도 오늘날 컴퓨터 기술의 발달에 따라 우리는 엄청난 정보를 쉽게 얻을 수 있지만 반대로 불필요한 정보의 홍수 속에 노출되어 있다는 뜻이기도 하다.
이러한 정보의 홍수 속에서 사람들이 필요로 하는 가치 있는 정보를 제공하기 위해 크롤러가 필요한 것이다.
정보의 홍수 속에서 특정 분야의 웹 공간에서 원하는 데이터만 콕 집어서 수집하고 이를 가공하여 사람들에게 가치 있는 정보와 편의를 제공하는 것,
이것의 시작이 바로 데이터 수집이고, 이것이 바로 크롤러의 존재 이유인 듯하다.
데이터를 수집하는 크롤러를 개발하는데 기본적으로 알아야 할 개념은 월드와이드 웹(Word-Wide-Web)
그리고 웹의 기본인 서버와 클라이언트 간의 관계를 이해하는 것이다.
월드 와이드 웹은 인터넷을 통해 전 세계 컴퓨터가 연결되어 정보를 공유할 수 있는 거미줄(Web)처럼 엮이고 연결되는 공간을 뜻한다.
예시) 서버와 클라이언트의 관계
우리가 인터넷 주소를 입력할 때 쓰는 'www'가 바로 word-wide-web의 약자이다.
그리고 우리는 이를 간단하게 웹(Web)이라고 부른다.
웹의 출현은 정보통신기술의 비약적인 발전을 불러왔고 현대 사회의 경제와 산업 구조 그리고 우리의 일상을 완전히 바꿔버릴 만큼의 엄청난 패러다임이었다.
우리가 인터넷을 통해 어떠한 정보를 얻고자 할 때 먼저 컴퓨터 바탕화면의 크롬이나 익스플로러 등의 브라우저 아이콘을 더블 클릭하고 인터넷 주소창에 주소를 입력하여 특정 웹사이트에 접속하거나 네이버/구글 등의 검색 엔진을 통해 검색 결과를 통해 정보를 얻는다.
크롬과 같은 웹 브라우저의 역할은 단순 인터넷상의 여러 정보를 얻기 위한 편의, 즉 쉽게 접속하고 검색하고 볼 수 있는 기능 등을 제공하는 역할을 한다.
브라우저 주소창에 URL('www.naver.com')을 검색했을 때 네이버에서 개발한 웹사이트 화면을 볼 수 있다. 대부분의 웹사이트의 구성은 상단에 메뉴가 있고, 로그인이 있고, 중간에 메뉴를 클릭했을 때 나오는 콘텐츠 및 게시판과 블로그 형식의 정보들로 구성되어 있다.
우리가 문서를 작성할 때 한글 혹은 PPT로 정해진 양식에 맞춰서 작성하듯이, 인터넷상의 수많은 회사(사이트)에서 제공하는 정보를 보기 좋게 웹상에 표출할 수 있도록 문서 형식을 하나로 통일하자고 약속한 것이 바로 HTML(Hypertext Markup Language)이다.
html 형식의 태그
우리가 보는 모든 웹사이트의 화면은 HTML 형식 기반의 문서라고 생각하면 된다.
브라우저를 통해 특정 주소(www.naver.com)를 입력하는 것은 네이버라는 회사에게 네이버 문서를 요청하는 행위이다. 주소가 잘못되지 않았다면 네이버는 해당 요청 주소에 맞는 화면 혹은 문서(html)를 응답할 것이고, 우리는 네이버 메인화면을 보게 된다. 이것이 서버와 클라이언트의 관계의 기본이다.
서버와 클라이언트의 개념과 동작 구조를 깊게 파고들면 무수히도 많고 어려운 기술을 만나게 되기 때문에 깊게 파고들지는 않겠다.
네이버 사이트 화면에서 뉴스 메뉴와 특정 뉴스를 클릭하여 뉴스를 것과 같이, 웹 화면에서 뉴스 정보를 요청하는 쪽(브라우저)을 클라이언트라 부르고 클라이언트에서 요청한 뉴스 정보를 응답하는 쪽(네이버)을 서버라고 부른다. 우리는 클라이언트와 서버 간 요청과 응답이라는 두 가지 과정을 통해 원하는 인터넷(웹) 상의 정보를 얻게 되는 것이다.
이렇게 웹과 서버/클라이언트의 개념을 주저리주저리 설명하는 이유는 내가 현재 하고 있는 크롤링 작업과 크롤러 개발 업무에 매우 중요한 요소이기 때문이다.
크롤링(Crawling)은 이처럼 웹(Web) 페이지에 표시된 데이터를 추출하는 작업이며, 웹상에 존재하는 거의 모든 웹 페이지는 HTML이라는 구조적인 문서 형태로 제작되었기 때문에 크롤러는 이런 HTML 문서를 구문 분석(파싱) 하여 데이터를 얻어내는 소프트웨어 시스템이다.
여러분이 한글과 PPT와 같은 문서 작업을 할 때에도 제목, 내용, 날짜, 표 등 정해진 양식에 맞게 작성할 때가 많을 것이다. HTML도 위 문서작업과 동일하게 구조적인 문서 형태로 웹문서(사이트)를 제작(개발)하며, HTML은 태그(tag)로 문서 형태를 구분한다.
그렇기 때문에 특정 웹사이트의 정보를 추출하기 위해서는 웹 정보제공자(서버)에게 요청하여 얻은 웹문서(사이트, HTML)의 태그 정보를 기반으로 내가 원하는 데이터를 찾고 추출하게 될 수 있는 것이다.
이것이 크롤링이 데이터를 추출하는 작업 방식이다.
# 7
크롤링 분야에서 가장 많이 쓰이는 대표적인 크롤링 기술들
*내가 회사에서 일하는 동안 배우고 직접 사용한 것만 설명
크롤링 분야에서 널리 쓰이는 3가지 대표적인 라이브러리(https://www.bestproxyreviews.com)
파이썬이라는 언어는 데이터 사이언스 분야에서 최적의 언어로 평가되고 있다. 파이썬은 문법이 간단하며 직관적이라서 일반인도 쉽게 배울 수 있을 뿐만 아니라, 데이터 수집/전처리/모델링/시각화/AI-학습 등 데이터 과학에서 필요한 다양하고 강력한 라이브러리를 제공하고 있기 때문이다.
이처럼 데이터 수집 업무를 수행하는 크롤링 분야의 선두주자 또한 파이썬이라는 의견이 지배적이다.
컴퓨터 프로그래밍에 익숙하지 않은 데이터 과학 및 통계분야 종사자와 비전공자들도 쉽게 사용할 수 있는 크롤링 라이브러리들이 많이 생겨나고 급격히 발달하고 있다.
현재 많은 크롤링 관련 라이브러리들이 존재하지만 내가 아는 한, 이 분야에서 널리 쓰이는 크롤링 라이브러리를 꼽자면 뷰티풀 수프(Beautifulsoup), 셀레니움(Selenium), 스크래피(Scrapy) 이 3가지가 대표적이다.
나는 운이 좋게도 입사하고 6개월 간 뷰티풀 수프와 셀레니움을 사용한 크롤러를 개발해보았다. 스크래피 또한 강력한 크롤링 라이브러리라는 의견이 많아 추후 따로 공부해서 개인 프로젝트를 진행하면서 적용해볼 예정이지만 아직 내가 사용해본 경험이 없어서 자세한 언급은 하지 않겠다.
1. 뷰티풀 수프(Beautiful Soup)
뷰티풀 수프(Beautiful Soup)HTML과 XML 문서의 구문을 분석(파싱)해서 데이터를 추출하는 라이브러리이다.
장점은 배우기 쉽고 데이터 추출이 빠르다는 점이다.
뷰티풀 수프는 HTML 및 XML 문서를 가져오는 웹 요청 기능을 제공하지 않기 때문에 Requests, urlib와 같은 웹 요청 보내는 라이브러리와 함께 사용하여야 한다.
웹 요청 후 응답 받은 HTML 및 XML 문서의 구문 분석(파싱)을 위해 lxml, html.parser 등 외부 파서가 필요하다.
웹 요청 URL을 통해 응답받은 WEB 문서를 파싱해서 데이터를 추출하기 때문에 Ajax와 javascript로 구현된 동적 웹 페이지 데이터를 수집하는데 많은 어려움이 있다.
2. 셀레니움(Selenium)
selenium(셀레니움)
초기 웹 자동화 테스트(버튼 클릭, 스크롤조작 등)를 하기 위한 프레임워크로 설계되었지만 현재 크롤링으로 널리 쓰이고 있는 강력한 라이브러리이다.
웹 드라이버를 통해 웹 브라우저를 실제로 띄워서 사람이 웹 사이트에 접속해서 할 수 있는 모든 행동 및 절차를 자동으로 구현할 수 있으며, 실제 보여지는 웹 페이지의 모든 데이터를 가져올 수 있고 디버깅 또한 매우 직관적이다.
셀레늄은 클릭, 스크롤 조작 등의 액션 기능을 사용하여 데이터를 추출할 수 있기 때문에 Ajax 및 javascript 렌더링을 통해 생성되는 데이터를 손쉽게 가져올 수 있다.
나는 뷰티풀 수프와 셀레니움을 활용하여 쇼핑몰 베스트 상품 크롤러, 오픈 마켓 셀러들의 다양한 판매/매출 정보 크롤러 등 다양한 크롤러를 개발해 보았고,
현재 내가 내린 결론은 정적인 웹페이지와 크롤링 작업이 단순하고 규모가 작은 프로젝트에는 뷰티풀 수프가 적합하지만 크롤링이 필요한 데이터 종류가 많고 작업이 다소 복잡하고 큰 규모의 프로젝트에 사용되는 크롤러 개발을 할 경우, 셀레니움이 더 적합하다고 판단된다.
크롤링 작업은 단순 속도가 빠르다고 다가 아니다 속도가 빠르다는 건 특정 웹 서버에 요청을 빠르게 날림으로써 서버에 더 많은 부하를 주는 것을 의미하므로 크롤링 대상이 되는 회사가 영위하는 사업에 영향을 주지 않는 정도로 크롤링 작업을 수행 하는 것도 고려해야한다.
또한 크롤링 작업에는 무수히도 많은 예외상황과 문제점이 발생하는데 이런 문제를 빠르고 효과적으로 해결하면서 원하는 데이터의 무결성을 지키며 정확하게 수집하는 것이 무엇보다 중요하다고 생각한다.
항상 속도를 문제 삼는 경우가 종종 있는데, 이는 멀티 프로세스 및 병렬 처리 기법을 활용하면 일정 부분을 개선할 수도 있다. 각 라이브러리들의 고유한 장단점이 분명히 존재하기 때문에, 이게 좋다 저게 좋다는 논쟁은 별로 의미가 없는 것 같다. 크롤링 작업을 수행할 라이브러리를 선택할 때 프로젝트 및 서비스의 규모와 요구사항을 정확하게 파악하고 이에 적합한 라이브러리를 선택하는 것이 현명하다.
(결국 다 써보고 경험하는 것이 최고이기 때문에 빠른 시일 내에 내가 아직 경험하지 못한 스크래피(Scrapy)를 공부하고 적용해 나갈 예정이다.)
이처럼 6개월 동안 크롤링 작업에 유용하게 쓰이는 대표 라이브러리 2개를 활용하여 크롤러 개발에 참여했었다. 하지만 모든 시스템이 그러하듯, 강력한 라이브러리를 많이 알고 잘 활용한다고 해서 시스템 성능이 좋아지지는 않는다. 물론 좋은 라이브러리를 사용하면 특정 기능 한에서 삽질의 과정을 줄이고 성능을 높여줄 수는 있으나, 시스템 전체에 대한 성능을 보장하진 않는다.
크롤러라고 해서 예외는 아니다. 현재 내가 근무 중인 회사의 크롤러는 여러 개 있는데 모두 널리 쓰이는 대표적인 크롤러 라이브러리를 활용하고 있다. 비슷한 유형의 데이터를 수집하는 데도 어떤 크롤러는 수집 속도도 빠르고 문제가 많이 발생하지 않지만 어떤 크롤러는 수집 속도가 느릴뿐더러 많은 문제가 발생하였다.
이 차이는 전체적인 시스템 구성과 구조의 차이였으며, 개발자 경험치의 차이이기도 했다.
크롤러 시스템 또한 단순 데이터를 수집하고 저장하는 기능이 다가 아니다. 어떻게 보면 핵심 기능이기도 하지만 정작 전체 시스템에서 차지하는 코드 양은 매우 미비할 뿐이다.
크롤러 시스템은 로그인, 2차 인증, 타입 별 데이터 수집, 수집된 데이터 가공, 데이터베이스 적재 등 여러 가지 구성요소와 기능이 순차적으로 처리되어야 한다.
더군다나 모든 작업은 자동으로 스케줄러에 의해 설정된 시간에 동작하여야 하고 그 시간대에 내/외부(크롤링 대상 사이트) 요인으로 인한 문제가 하나라도 발생하면 크롤러는 동작을 멈추게 된다.
내가 위에 언급한 크롤러 시스템 기능은 주요 기능만 나열했을 뿐이고 이외에 무수히도 많은 요소들이 녹아져서 모든 요소들이 상호작용하며 한 치의 실수 없이 동작해야 하는 것이다.
나는 운이 좋은 건지, 나쁜 건지 회사 크롤러를 개발했던 기존 담당자들이 모두 퇴사하는 바람에 졸지에 회사 서비스 플랫폼에서 필요한 모든 크롤러 시스템을 맡게 되는 상황에 처했고 기존 전임자들이 만든 문서나 소스코드를 뒤져가며 회사 크롤러 개발 히스토리를 알게 되고 크롤러의 구조를 들여다볼 수 있는 기회가 생겼다.
그리고 모든 크롤러들이 동작하고 끝나는 시간을 체크하고 수집한 데이터가 잘 들어왔는지 확인하는 일을 해야 했기 때문에 이 과정에서 각 크롤러의 성능과 문제점을 파악할 수 있게 되었다.
정말 회사에서 운영되는 모든 크롤러 시스템은 파이썬 언어로 만들어졌지만 모든 크롤러의 구조와 코드 방식이 너무나도 달랐다.
각 크롤러 시스템의 구조와 동작 방식뿐만 아니라 성능과 문제 발생 빈도 또한 너무나도 차이가 심했다.
회사가 왜 이런 선택을 했는지 나름 사정은 있겠지만 아직도 이해가 잘 안 되는 것 중 하나가 초기 회사 서비스에 크롤러를 도입하자는 의견이 나오고 신입 파이썬 개발자 2명을 뽑아서 그들에게 크롤러 개발을 지시했다고 한다.
그래서 초기 크롤러는 신입 파이썬 개발자 2명이 수년간 중심을 잡아 줄 사수도 없이 신입 두 명이 시행착오를 거치며 만들어지게 되었고 회사가 운영하는 서비스 고객의 다양한 니즈에 따라 여러 크롤링이 추가 개발하게 되었다고 한다. 크롤러의 종류가 많아지면서 관리 요소들이 늘어나는데 모래 위의 성벽을 짓는 듯이 주먹구구식으로 개발된 크롤러는 당연히 문제도 많았고 그로 인해 과도한 업무와 위에서 문제 해결 요구가 빗발치는 압박을 견디다 못해 2명이 동시에 퇴사를 했고 그 이후 팀장급 관리자가 크롤러 파트를 맡아 기존 크롤러를 리팩토링 하기도 했고 새로운 크롤러를 개발하기도 했다고 한다.
이런 히스토리를 거쳐 현재 회사 서비스를 위해 운영 중인 크롤러들이 개발된 것이다.
여러 크롤러 중에서 중요도가 상대적으로 낮은 작업을 하는 크롤러의 경우, 개발 초기 2명의 신입 개발자가 만든 크롤러를 그대로 사용했기 때문에 초기 크롤러의 구조를 볼 수 있었고 나머지 팀장급 개발자가 다른 크롤러를 새로 리팩토링한 크롤러와 처음부터 새로 만든 크롤러까지 모든 크롤러의 구조와 방식을 두루두루 파악하고 학습할 수 있었다.
솔직히 나에게 처음부터 크롤러를 만들어보라고 지시한다면 초기 2명의 파이썬 신입 개발자가 개발한 크롤러만큼도 만들 자신은 없다. 이 크롤러도 역시 그들의 2~3년간의 시행착오와 경험치가 녹아 있었기 때문이다.
하지만 팀장급 개발자가 만든 크롤러와는 상대적으로 성능도 떨어지고 비효율적으로 동작하고 있었다.
여기서 한 가지 느꼈다.
개발자란 개개인의 능력과 자질에 따라 성장과 발전 속도는 다를 수 있지만 오랜 개발 경험과 다양한 문제 해결을 통해 얻은 경험은 무시할 수 없다는 사실을..
짬은 무시 못함..
팀장급 개발자의 경우 수많은 프로젝트와 시스템을 개발하면서 배운 여러 기술과 방법 그리고 시스템이 동작하는 과정에서 발생할 가능성이 있는 문제점을 미리 예측하여 문제를 사전에 예방하고 여러 예외를 처리하는 코드를 크롤러를 초기 설계할 때부터 반영한 듯 보였다.
이러한 경험치는 코드 퀄리티에서 보이고 전체적인 구조에서도 확실한 차이를 보였다.
추후 내가 맡게 될 때에도 크롤러의 에러 및 문제 발생빈도와 수집 속도에서도 큰 차이를 보이기도 했다.
효율적이고 높은 성능을 자랑하는 시스템을 만들기 위한 방법은 무수히도 많을뿐더러 아직 6개월 차가 감히 이런 것을 논한다는 건 다소 우스꽝스럽지만 그래도 나름 6개월 동안 크롤러를 개발하면서 시니어 개발자와 주니어 개발자가 개발한 각기 다른 크롤러 시스템 구조와 방식을 파악하고 학습하는 과정에서 배운 효율적인 시스템을 개발하기 위해 필요한 것들을 정리한 내용을 공유하려고 한다.
사실 효율적인 시스템을 만드는 것은 무수히도 많은 방법론이 존재할 것이고 고차원적인 알고리즘이 필요할 수도 있지만, 나는 아직 구조적인 개선을 위한 방법론과 고차원적인 알고리즘 등을 논할 수준이 못될뿐더러 내가 현재 유일하게 경험한 것이 회사에서 운영되는 여러 크롤러 시스템의 코드이기 때문에 크롤러 개발자의 시선에서 여러 코드 구조를 분석하며 느낀 효율적인 시스템을 만드는 코드는 무엇인가? 에 대해 정리한 내용이라는 점만 참고해주길 바란다.
# 8
(내가 6개월간 배운) 좋은 시스템과 좋은 서비스 구조를 만들기 위한 나만의 코딩 방법
*수많은 개발자분들께 욕먹을 각오하고 한 글자 적어보겠습니다ㅋㅋ
내가 생각하는 개발자란 코딩을 통해 무언가를 만드는 사람이다.
대부분의 개발자가 만드는 무언가는 회사나 고객이 필요로 하는 응용 프로그램 혹은 서비스이다.
코딩이란 쉽게 말해서 컴퓨터에게 작업흐름을 지시하거나 소통하는 것을 말한다.
한국사람이 미국 사람과 소통하려면 영어를 배워야 하듯이, 개발자가 컴퓨터와 소통하려면 컴퓨터가 이해하는 언어로 소통해야 한다. 이런 이유로 프로그래밍 언어가 생겼고 프로그래밍 언어로 작성된 프로그램을 컴퓨터가 이해할 수 있는 기계어로 번역되어 프로그램이 실행되는 것이다.
인간의 경우 개떡 같이 작업을 지시해도 유도리 있는 사람이라면 찰떡 같이 알아듣고 유연하게 업무를 수행할 수도 있지만, 컴퓨터는 정해진 규칙과 문법에 의해 개발자가 만든 작업 지시 내역 및 작업흐름을 그대로 순차적으로 해석해서 실행하기 때문에 문법적인 한치의 실수도 용납되지 않는다.
이러한 '이유로 컴퓨터는 거짓말을 하지 않는다'는 유명한 말이 생겨나기도 했다.
코딩을 개떡같이 하면 개떡 같은 결과가 나오는 것이고 찰떡같이 하면 찰떡같은 결과가 나오는 것은 당연한 일이다. 이처럼 컴퓨터는 유도리가 없고, 거짓말을 못한다. 개발자가 지시한 그대로를 실행하고 동작한다. 그렇기 때문에 개발자의 전체적인 구조 설계 및 코딩 역량에 의해 프로그램의 성능 및 효율이 좌우되는 것이다.
개발자의 코딩 실력이 효율적인 프로그램을 만드는데 굉장히 중요한 건 사실이지만 그보다 제일 먼저 중요한 요소는 개발자가 구현해야 하는 프로그램 작업에 대한 이해이다. 앞서 말했듯이 개발자는 회사나 고객이 필요로 하는 무언가를 만들어내는 사람이다.
1. 회사나 고객이 원하는 요구사항을 충분히 숙지하고 이해한 다음 프로그래밍을 시작하는 것이 좋다.
어떤 일을 하든지 커뮤니케이션 능력은 중요하다.
한 가지 예로, 만약 이 커머스 쪽 사업을 하고 있는 회사에서 자신들의 고객에게 최근 잘 팔리는 상품을 분석해서 제공하고 싶어서 여러 쇼핑몰의 베스트 상품 100개씩만 매일 수집하는 프로그램을 만들어달라고 했는데 개발자는 회사의 요구사항과 의도를 잘못 이해하고 여러 쇼핑몰의 상품 전체를 수집하는 프로그램을 만들었다고 가정해보자.
쇼핑몰마다 베스트 상품의 개수가 보통 100개이고, 한 페이지에 상품을 모두 표출해주는데, 고객이 원하는 요구사항을 잘 파악했다면 어렵지 않게 다양한 쇼핑몰 베스트 상품 정보를 수집하는 프로그램을 만들 수 있을 것이다. 하지만 쇼핑몰의 모든 상품을 수집한다면 1개의 쇼핑몰마다 수만~수십만의 상품을 수집해야 할 것이고, 모든 카테고리를 타고 들어가서 페이지를 하나하나 넘겨가는 기능까지 구현해야 하기 때문에 엄청난 삽질의 시간을 보낼 것이다. (생각보다 쉽지 않은 기능이다..)
전자의 경우, 크게 힘을 들이지 않고 손쉽게 구현할 수 있어서 프로그램을 빨리 만들어서 보여주면 회사에 칭찬을 받겠지만 후자의 경우는 아무리 열심히 밤새워가며 프로그램 개발을 했을지라도 분명 회사로부터 욕만 바가지로 먹을 가능성이 크다. 이 처럼 개발자는 코딩 실력 이전에 제일 먼저 고객이 원하는 요구사항을 충분히 숙지하고 이해한 다음 코딩을 시작해야 하는 게 제일 중요하다고 생각한다. 그렇기 때문에 고객의 요구사항과 해결해야 하는 문제를 잘 파악하기 위해서 지녀야 할 능력은 커뮤니케이션 스킬이다.
대화 불능의 사람은 아무리 똑똑하고 코딩 실력이 좋다할지라도 고객이 원하는 것을 만들어 낼 수가 없다.
고객이 가진 문제점과 요구사항을 제대로 파악하려 하지 않고 이해를 못 하고 있는데 무얼 만들겠는가?
그리고 커뮤니케이션 능력이 뛰어난 개발자는 고객의 문제를 정확하게 파악하고 이해할 수 있기 때문에 문제 해결 능력 또한 좋을 수밖에 없다.
2. 고객의 문제와 요구사항을 충분히 숙지했다면, 프로그램으로 구현하기 전 충분히 생각하고 구상한 뒤 구조를 설계해야 한다.
프로젝트 담당자 또는 고객과의 미팅을 통해 자신이 만들어야 할 서비스 및 기능을 명확히 인지 했다면 이제는 구현만 남아있겠지만 무작정 코딩을 시작하는 건 좋지 않은 방법인 것 같다.
오랜 경험과 노하우를 가진 시니어 개발자들의 경우 이미 머릿속에 구조, 작업 흐름, 예외 상황 등이 그려지겠지만 나와 같은 신입 개발자라면 더더욱 무작정 부딪히는 방법은 피해야 하는 것 같다.
'시작이 반'이라는 말이 있지만 무작정 시작하는 건 반이 아니라 -50% 보다 더 퇴보할 수도 있다.
대부분의 신입 개발자가 회사에 입사하면 전임자들이 개발했던 기존 소스를 받아서 기존 소스를 수정하거나 참고하여 유지보수 혹은 확장하는 개발업무를 수행한다.
그리고 무작정 그 코드를 쭉~ 훑어보고 수정이 필요하다고 예상되는 기능에 손을 대기 시작한다.
신기한 것이 개발이라는 것이 어떻게든 삽질에 삽질을 거듭하다 보면 원하는 대로 동작은 한다.
만약 기존 시스템을 유지보수만 하는 업무라면 괜찮을 수도 있지만 새로운 기능 및 시스템을 개발해야 한다면 얘기가 달라진다. 예를 들어, 어떤 회사가 네이버 쇼핑몰 데이터를 수집 하하여 서비스를 하고 있는 회사가 있다고 가정할 때, 갑자기 회사에서 기존 네이버 쇼핑몰 크롤러 소스코드를 참고해서 쿠팡 쇼핑몰 크롤러도 확장 개발하라는 업무지시를 받았다면 어떻게 될까?
대부분이 기존 네이버 크롤러 소스를 복사 + 붙여 넣기 해서 쿠팡 쇼핑몰 크롤러로 이름을 변경하고 삽질의 삽질을 또 반복하며 어떻게든 동작하게만 구현할 것이다.
이렇게 되면 시스템 성능이 어떻게 될까?
분명 데이터 수집이라는 작업은 동일하지만 네이버 쇼핑몰과 쿠팡 쇼핑몰의 사이트 구조, 정책, 제공하는 데이터 포맷, 화면 위치 등이 다르기 때문에 기존 소스에서 필요했지만 쿠팡 크롤러를 만들 때 불필요한 기능들이 존재할 것이고, 수정해야 할 기능이 있을 것이며, 필요에 따라 새로 만들어야 하는 기능도 있을 것이다.
아마 새로 만들어야 할 쿠팡 쇼핑몰의 데이터 크롤러는 불필요한 기능과 요소들이 다 들어있을 가능성이 크다.
그리고 네이버 크롤러와 쿠팡 크롤러 소스에서 대부분의 기능과 코드의 중복이 발생한다.
(왜냐하면 네이버 크롤러 소스를 그대로 복사 + 붙여 넣기 해서 쿠팡 크롤러를 구현했기 때문이다.)
이것이 2개 쇼핑몰이면 크게 문제가 되지 않겠지만, 만약 100개의 쇼핑몰을 확장해야 된다면?
하나의 공통 기능을 모듈화 해서 재활용하면 될 것을 가지고, 100개의 복붙으로 인한 중복 코드를 양산하게 된다. 그리고 처음부터 복붙 한 소스를 가지고 구현할 때 어쩌면 처음부터 만드는 것보다 더 많은 시행착오와 시간이 소요될 수도 있다.
시간이 지남에 따라, 서비스 유지보수 및 개발을 위해 수많은 개발자들이 거쳐갈 것이고 기존 소스에서 또 다른 코드들이 추가되게 될 것이고, 불필요한 소스들이 난무하는 악순환이 반복되다가 기능은 동작 하지만 점점 의도를 알 수 없는 난해하고 복잡한 구조와 코드로 변질되기 시작할 것이다.
결국, 유지보수를 어렵게 하여 생산성을 저하시키고 새롭게 투입된 인력은 고사하고, 기존 유지 보수했던 인력들 조차 문제 해결과 유지보수 시간에만 막대한 비용이 들어가고 기술 부채가 쌓이기 시작하면서 해당 기능이 망하거나, 회사 입장에서 막대한 금전적 손실을 떠 앉게 될 가능성이 크다.
이러한 이유로 새롭게 무언갈 만들어야 하거나, 기존 소스를 가지고 추가적인 개발을 해야 할 경우라도 무작정 개발하기보다 자신이 구현해야 할 대상의 세부적인 기능을 나누고 이 기능의 작업 흐름을 충분히 생각하고 구상한 뒤에 전체적인 구조가 머릿속으로 그려지기 시작할 때 코딩을 시작하는 게 좋은 것 같다.
이런 식으로 코딩을 시작하게 되면 기존 소스가 아무리 복잡하더라도 어느 정도 이 기능은 이 업무를 위한 기능이구나 라는 정도의 힌트를 얻을 수 있고 전체적인 소스 구조를 손쉽게 파악할 수 있게 될 것이다.
그리고 기존 소스의 구조와 세부 기능을 파악하고 기존 소스를 참고해서 다른 '사이트' 혹은 '분야'로 확장하는 일을 하더라도 새로운 사이트에 대한 업무 흐름을 파악하게 될 것이고 기존 사이트의 업무 흐름과 비교하게 됨으로써 기존 소스에서 재활용할 기능, 수정할 기능, 불필요한 기능, 새롭게 만들어야 할 기능이 명확해지면서 공통 기능은 모듈화 해서 재사용하여 중복 코드가 사라지고 불필요한 기능은 사용하지 않을 것이다.
또한 기능 하나하나에 대한 이해와 쓰임새를 명확하게 파악하고 있기 때문에 문제나 에러를 만나더라도 시행착오와 삽질의 시간이 줄어들 것이다.
위 설명은 내가 유일하게 경험한 크롤러 시스템 개발이라는 한 분야에 국한되긴 했지만 그래도 6개월간 나름 기존 소스를 수정하면서 다른 크롤러를 만들어보기도 했고, 제로 베이스에서 처음부터 크롤러를 만들어보기도 했고, 현재 운영되고 있는 크롤러들을 유지보수를 하는 과정과 경험을 토대로 느낀 점을 설명한 것이고 섣불리 판단하기 다소 조심스럽긴 하지만 다른 분야에서도 충분히 적용 가능한 방법이라고 생각한다.
나는 새로운 크롤러를 확장/개발하라는 작업 지시가 내려올 경우 절대로 비슷한 업무의 기존 크롤러 소스를 복붙 해서 사용하지 않는다. 더 스트레스받고 오래 걸릴 것을 알고 있기 때문이다. 새롭게 확장해야 할 사이트를 방문해서 데이터를 수집하는 과정과 위치를 정확하게 파악하고 이를 노트에 정리한다.
예를 들어 네이버 뉴스에 가서 검색 키워드를 입력해서 나온 1년 치 뉴스들을 전부 수집하는 크롤러를 개발하라는 지시가 있을 경우 실제로 네이버 뉴스를 들어가서 검색하고 옵션을 설정하는 등의 작업을 직접 체험해본다.
네이버에서 특정 키워드로 뉴스를 검색해서 1년 치를 보려면, 우선 인터넷을 켜고 네이버 뉴스 사이트를 들어가고, 검색 옵션에서 기간을 선택한 후 원하는 키워드를 입력해서 검색 버튼을 누르면 해당 키워드에 관련된 뉴스 결과 리스트들이 쭉~ 나온다. 이렇게 나온 결과를 1page 부터 마지막 page까지 클릭하면서 데이터를 수집해야 한다.
그리고 이러한 작업 흐름을 쪼개서 작성한다.
① 네이버 뉴스 웹 사이트 들어가기
② 검색 옵션 설정하기
③ 검색 키워드 입력하기
④ 검색 버튼 누르기
⑤ 페이지당 뉴스 결과 데이터 수집하기
⑥ 다음 페이지로 넘어가기
⑦ (다음 페이지가 존재하지 않을 시) 3번 업무부터 다시 시작하기
⑧ (모든 키워드 검색이 끝나면) 프로그램 종료하기
이렇게 작성한 다음, 위 내용을 함수 형태로 다시 정리한다.
① open_naver_news (url)
② set_search_option (options)
③ input_search_keyword (keyword[current_index])
④ click_search_button (search_button_xpath)
⑤ scrape_articles_per_page (article_page_xpath)
⑥ click_next_button (next_button_xpath)
⑦ if next_button == null : input_search_keyword (keyword[current_index] )
⑧ if naver_keyword[last_index] < current_index : finish
위 예시로 정리된 함수들은 실제로 내가 쉬는 날 재미 삼아 만들어본 뉴스 크롤러 구현 과정 중 일부이다.
작업 절차를 간략하게 나열한 다음 함수명을 곰곰이 생각하여 정리하고 난 후 실제로 함수를 구현한다.
저 함수 이름에도 알 수 있듯이 누구든 저 함수명만 보더라도 무슨 작업을 하는 기능인지 파악할 수 있어야 한다. 그리고 실제로 프로그래밍으로 저 함수를 먼저 구현한다. 함수를 구현할 때 함수 이름에서 명시한 기능 외에 다른 기능은 되도록 추가하지 않고 하나의 함수는 되도록 하나의 기능만 처리하도록 구현한다. 그러고 나서 실제로 내가 분리한 함수를 순차적으로 실행해보면서 기능을 추가하거나 수정하는 작업을 반복한다.
위 작업에서 다양한 예외 상황이 발생하는데, 그중 한 가지만 예를 들면, 특정 키워드로 1년 치 뉴스를 검색하면 수십 페이지 이상의 뉴스 결과가 나오기도 하고 뉴스 결과가 하나도 없는 이슈가 발생하고 프로그램은 찾는 정보가 없다는 에러 메시지와 함께 크롤러 동작이 중간에 멈춘다.
이럴 때는 해당 이슈에 연관된 함수 내부 혹은 새로 함수를 만들어서 조건문과 반복문을 통해 페이지당 뉴스 정보를 수집하다가 검색 페이지에 뉴스가 존재하지 않으면 다음 작업으로 넘어가게끔 처리하면 된다.
위 함수들을 초기에는 별개로 만들었지만 이것 또한 업무 흐름에 따라 여러 함수를 하나의 함수 안에 합쳐서 처리해야 할 상황이 생긴다.
예를 들어, 1) 키워드를 입력/검색하고 → 2) 페이지별 뉴스 정보를 모두 수집한 후 → 또다시 다른 키워드를 입력하고 해당 키워드로 검색한 뉴스 정보를 수집해야 하는 등 똑같은 작업을 반복해야 하는 이런 상황이라면 키워드 입력 함수 + 검색 버튼 함수 + 뉴스 정보 수집 함수 + 다음 페이지 클릭 함수를 하나의 함수로 묶어서 조건문과 반복문을 통해 작업이 처리될 수 있게 해야 하는 등 여러 가지 고려하지 못한 상황이 생길 때는 그 상황에 맞게 다시 함수를 정의하고 수정하면 된다.
이런 식으로 코딩하게 되면 정말 클린하고 누가 봐도 쉽게 이해할 수 있는 소스코드가 완성된다.
(나만의 착각일 수도..ㅠㅠ)
정말 단순한 크롤러지만 네이버 뉴스에서 원하는 키워드를 검색해서 뉴스정보를 수집할 수 있는 크롤러가 정상적으로 동작한다면 구글 뉴스도 수집하고 싶은 생각이 들 수밖에 없다. 이때, 네이버 뉴스 크롤러를 활용해서 구글 뉴스 크롤러로 확장하는 건 정말 쉽고 빠르게 확장이 가능하다. 내가 네이버 뉴스 크롤러를 3일 정도 고민하면서 만들었지만 구글 뉴스 크롤러로 확장하는 건 하루도 안 걸렸던 것 같다. 왜냐하면 위에 정리한 작업흐름을 정확하게 이해하고 있었기 때문에 구글 뉴스와 네이버 뉴스의 작업흐름의 차이점만 파악한다면 확장하는 건 일도 아니다.
3. 확장성이 용이하고 중복 코드를 최소화하기 위한 공통 기능 모듈화를 고려하면서 코딩을 하는 것이 좋다.
앞서 설명했던 내용들을 요약하자면, 자신이 구현해야 할 개발 업무 흐름을 정확하게 이해하고 코딩하기 전 충분한 생각하고 구상하여 구조적 설계를 어느 정도 정리한 다음 코딩을 하는 것을 추천한다는 내용이었다.
본문에서는 명확하게 언급은 안 했지만 이러한 과정 속에서 아래 2가지로 요약할 수 있다.
이해하기 쉬운 코드를 위한 함수 및 변수 네이밍을 직관적으로 지어야 한다.
가독성이 좋은 코드를 위한 하나의 함수는 하나의 기능에 충실하도록 만들고 되도록 짧은 코드로 짠다.
위의 내용처럼 이전 설명은 이해하기 쉽고 가독성이 좋은 코드에 관한 설명에 가까웠고 이런 원칙을 지켰을 경우 다른 개발자가 투입되더라도 빠르게 이해하고 활용할 수 있기 때문에 코드 해독 시간이 줄어들고 문제가 생겼을 때 유지보수 시간을 절약할 수 있는 장점이 있다.
이제부터는 설명할 (3번 : 확장성을 위한 공동 기능 모듈화) 내용은 시스템 및 서비스 효율과 성능에 큰 이점이 작용할 수 있다고 생각되는 내용이다.
먼저 여기서 말하는 확장성이란 비즈니스 요구에 맞게 (IT) 시스템 혹은 서비스에 필요한 기능을 추가하거나 서비스(도메인) 대상이 바뀔 때 전체 시스템에 영향을 주지 않고 신속하게 대응할 수 있도록 구조적인 설계가 되어 있는지에 대한 것이다.
간혹 서비스를 운영하다가 고객들의 니즈 혹은 회사의 필요에 의해 새로운 기능을 추가해야 할 상황이 생긴다. 기존 시스템에서 새로운 기능을 추가할 때 기존 시스템의 상당 부분을 건드리지 않고도 기능을 추가/확장할 수 있도록 노력해야 한다.
작은 기능 하나를 추가하는데 수많은 에러와 문제가 발생하거나 핵심 코어를 변경해야 한다면 기존에 잘 동작하던 기능들도 에러가 발생할 가능성이 크고 작은 기능 추가 하나 때문에 전체를 뜯어고쳐야 할 수도 있다.
그렇기 때문에 각각의 기능이 상호 연결되어 있되, 너무 의존적이지 않고 확장이 필요할 때 정말 불가피한 경우를 제외하곤 핵심 코어에 영향을 주지 않고 작은 부분만 수정해도 확장이 가능한 구조가 확장성이 좋은 시스템 구조라고 생각한다.
내가 아직 확장성이 용이한 시스템 구조를 위한 개발을 말할 수준은 아니지만 그래도 현재 노력 중에 있으므로 위 네이버 크롤러를 만들어보고 추가적으로, 구글 뉴스 크롤러 확장을 시도하며 적용했던 부분들을 공유하겠다.
나만의 코드 철학을 담긴 크롤러 개발을 연습하기 위해 크롤링 대상을 찾던 중 자동으로 원하는 키워드를 입력하고 검색해서 나온 뉴스 정보를 수집하는 크롤러를 만들어 보고 싶다는 생각을 했다.
그래서 국내에서 가장 많은 언론사 뉴스 정보를 제공하고 국내에서 뉴스 볼 때 가장 많이 이용할 것 같다고 생각되는 네이버 뉴스를 크롤링하기로 결정했다.
그래서 우선적으로 위에서 설명한 것처럼 네이버 뉴스를 확인하는 흐름을 정리하였고 이를 기능 단위로 쪼개서 함수 네이밍을 정리하였고 각 기능을 구현하기 시작했다. 네이버 뉴스에서 원하는 옵션을 선택하고 원하는 키워드를 입력하고 검색해서 모든 뉴스 정보를 수집하는 업무의 흐름은 아래와 같다.
① 네이버 뉴스 접속
② 검색 옵션 설정(기간, 정렬)
③ 키워드 입력
④ 검색 버튼 클릭
⑤ 스크롤 최대로 내리기(다음 페이지 누르기 위함)
⑥ 뉴스 정보 수집(현재 페이지)
⑦ 다음 페이지 버튼 클릭
⑧ (6), (7)번 작업 반복
⑨ (마지막 페이지 수집 완료 후) 스크롤 최대로 올리기(다음 키워드 입력을 위함)
⑩ 다음 키워드 입력
⑪ 검색 버튼 클릭
⑫ 스크롤 최대로 내리기(다음 페이지 누르기 위함)
⑬ (6), (7)번 작업 반복
⑭ (마지막 페이지 수집 완료 후) 스크롤 최대로 올리기(다음 키워드 입력을 위함)
⑮ (더 이상 키워드가 없을 시) 프로그램 종료
세부적으로 따지면 더 많이 있지만 네이버 뉴스에서 원하는 키워드를 입력해서 뉴스 정보를 모두 수집하는 주요 작업 흐름은 위와 같다. 위 흐름대로 함수명을 결정하고 기능 하나하나 구현하여 결국 자동으로 원하는 뉴스 정보를 크롤링하는 크롤러를 완성했다. 키워드를 여러 개 추가해도 문제없이 잘 동작했다.
이제 네이버 뉴스가 뿐만 아니라 구글 뉴스도 확장하고 싶어졌다. 그래서 구글 뉴스를 확장하기 위해 첫 번째로 네이버 뉴스와 동일하게 구글에서 키워드를 검색해서 뉴스 정보를 확인하는 업무를 파악했다.
다행히도 구글 뉴스에서 원하는 키워드를 입력해서 검색을 하고 표출되는 뉴스 정보가 거의 동일했다.
다만, 다른 점은 옵션을 설정하는 방식이 네이버와 구글이 조금 달랐다. 하지만 검색 옵션 설정이라는 업무 특성과 본질을 같았다.
그래서 기존 파일 하나로 정의했던 네이버 뉴스 크롤러 파일을 3개로 나누었다.
※ 파일명.py 확장자는 파이썬 파일이라는 의미이다.
① crawler.py → 완전 공통 기능
② base_crawler.py → 부분 공통 기능
③ news_crawler.py → 각 사이트 별 고유 기능
첫 번째 crawler.py는 구글과 네이버 뉴스의 크롤링 작업에 필요한 기능이 절대 바뀌지 않는 것들이다. 예를 들어 키워드 입력, 검색 버튼 클릭, 스크롤 내리기/올리기, 검색/다음 버튼 클릭 등이 있다. 다른 뉴스 사이트를 확장하더라도 변경 없이 사용 가능한 함수들이다.
crawler.py 소스코드 중 일부
두 번째 base_crawler.py는 구글과 네이버 뉴스 크롤링 작업에서 부분적으로 달라져야 하는 것들이다.
예를 들어 구글과 네이버 뉴스의 작업 흐름 중 검색 옵션 설정하는 부분이었다.
이렇게 부분적으로 달라지는 기능은 공통 기능을 정의한 crawler에서 함수 선언은 하되, 추상 메서드로 남겨놓고 base_crawler에서 구현하도록 한다. 쉽게 구글 옵션 방식과 네이버 옵션 방식이라고 가정할 때 base_crawler에서 구현할 때 만약에 인자 값이 구글이라면 구글 방식의 옵션 함수를 호출하고, 인자 값이 네이버 방식이라면 네이버 옵션 방식 함수를 호출하면 된다.
base.py 소스코드 중 일부
그리고 마지막 세 번째 news_crawler.py는 네이버 뉴스와 구글 뉴스에서만 존재하는 고유한 기능과 옵션 값들을 정의하는 곳이다. 우선 base_crawler를 상속받은 다음 네이버와 구글에서만 존재하는 고유한 기능과 인자 값을 정의한다. 모든 사이트에서 고유한 것이라면 모든 사이트마다 다를 수밖에 없는 URL, 옵션 정보 그리고 크롤링을 하기 위해 필요한 html 정보 등에 해당된다. 셀레늄에서는 사이트의 데이터를 추출하거나 클릭 등의 이벤트를 할 때 해당 화면의 html 경로를 통해 찾아서 작업을 수행하는데 이를 xpath라고 부른다. 모든 사이트의 xpath가 다르므로 이건 고유한 값이기 때문에 news_crawler에서 사이트에서 필요한 xpath를 정의하는 것이다.
news_crawler.py 소스코드 중 일부
정리하자면 네이버 구글뿐만 아니라 다른 뉴스 사이트를 확장할 때 기능 수정 없이 공통적으로 사용할 수 있는 함수는 crawler.py에 정의하고, 부분적으로 수정해야 하는 것들, 예를 들어 구글 뉴스와 다음 뉴스의 방식이 동일하고, 야후 뉴스와 네이버 뉴스는 다른 방식일 경우 부분적으로 달라지는 부분이기 때문에 이런 기능들은 base_crawler에 정의한다. 그리고 모든 사이트에서 고유한 기능과 값은 news_crawler에서 각 뉴스 사이트별 클래스로 만들어서 고유한 기능과 값을 정의한다.
위 방식으로 크롤러를 개발한 결과, 확장성이 용이하고 중복 코드를 줄일 수 있었다.
이런 방식으로 다른 뉴스 사이트를 확장한다면, crawler.py와 base_crawler.py는 거의 손댈 일이 없고 news_crawler.py에서 클래스를 하나 만든 다음 url, xpath와 같이 고유한 값들만 설정해주고 만약 다른 뉴스 사이트에서만 존재하는 공통 기능이 존재할 경우, news_cralwer.py에 해당 기능만 추가하면 손쉽게 확장이 가능할 것이다.
이런 식의 구조로 코딩을 할 경우, 손쉽게 기능 및 사이트 확장이 가능하고, 중복으로 사용되는 함수가 없어진다. 이 구조만 조금 파악하면 새로운 인력이 들어와서 다른 사이트를 확장하게 될 때 news_crawler.py만 조금 수정하는 것만으로도 새로운 크롤러를 개발할 수 있게 된다.
네이버와 구글 뉴스 크롤러가 동작하면서 뉴스 정보를 수집하는 중..
중복 코드가 없어지기 때문에 시스템 성능이 빠를 수밖에 없고, 코드량이 현저히 줄어들기 때문에 처음 보는 사람도 빠르게 코드 분석이 가능해진다. 그리고 코어(crawler)를 손댈 필요가 없어져서 확장하는데 리스크가 줄어들고 빠르게 확장이 가능해져서 유지보수와 개발에 필요한 인건비를 많이 줄일 수 있다.
지금 네이버와 구글 2가지 사이트만으로 예시를 들어서 다소 신빙성이 없어 보이긴 하지만 내가 회사에서 쇼핑몰 정보 수집 크롤러를 확장할 때 이런 구조로 처음 3개 정도 쇼핑몰을 확장할 때 공통 기능인 줄 알았던 것이 부분 공통 기능으로 바뀌는 경우도 있었고 특정 사이트에서만 존재하는 고유한 기능인 줄 알았더니 다른 몰 확장 때도 있어서 부분 공통기능으로 다시 옮길 때도 있었다.
하지만 10개 정도를 확장해보니 코어와 부분 공통기능을 수정할 일이 거의 없어졌다. 왜냐하면 레퍼런스가 많아질수록 공통기능과 부분 공통기능은 견고해지고 다들 비슷한 비즈니스 형태를 띠기 때문에 예외적인 기능이나 상황이 줄어들기 시작했다.
이것이 내가 6개월 간 배운 효율적인 시스템 구조를 위한 코딩 방식이다.
아직 한참 부족하고 아무것도 모르는 신입이기 때문에 이것이 옳은 방법인지 그리고 적절하게 설명했는지 모르겠으나, 적어도 내가 6개월간 일하면서 배우고 느낀 그대로를 써내려 간 것만은 확실하다. 몇 년 뒤에 이 글을 보고 왜 저랬나 싶을 수도 있지만 아마 웃을 수 있을 것 같다는 생각이 든다. 무식하면 용감해지듯이, 아무것도 모르는 신입이기 때문에 감히 이런 내용을 자신 있게 설명할 수 있지 않을까 싶다.
이상, 여기까지가 공장 노동자에서 개발자 되기까지의 고군분투 스토리와 6개월간 개발 일을 하면서 배우고 느낀 점을 그대로 담은 2021년 회고록이다.