[DE프젝]첫 번째 회고

포동동·2023년 1월 31일
0

[유튜브 프로젝트]

목록 보기
1/13
post-thumbnail

✒ 프로젝트 개요

12월부터 참여하게 된 팀 프로젝트가 있어 그 과정을 기록하려 한다. 내가 참여한 프로젝트는 실제로 서비스로 출시를 목표로 하는 팀이고, 각 분야의 미들 이상급 분들과 주니어가 섞인 성장형+실무형 프로젝트다.

프로젝트는 유튜브 데이터를 수집 후 AI 학습시켜 서비스 유저에게 가치있는 정보 전달을 하는 서비스이다(더 자세한 내용은 아직 출시전이라 쓰는 것을 삼가겠다😶)

나는 여기서 데이터 엔지니어로 참여하게 되었고, 주로 크롤링 자동화와 DB 구축을 맡았다. 그리고 그 과정을 약 한 달 반 진행한 지금 시점에서 잠시 스스로 점검을 위해 기록해두려 한다.



⚙ DE로서의 업무

나는 크게 아래와 같은 일을 담당하였다.

  • 크롤링
    • 유튜브 채널/비디오 데이터 크롤링
    • 네이버 및 각종 포털의 연관검색어 크롤링
    • 파이썬 병렬처리를 위한 ray 도입
  • DB
    • Elasticsearch 도입
    • ES로 ETL 파이프라인 구축
    • AI팀 업무를 위한 DB 매핑
    • AI팀 업무를 위한 간단한 성과 로직 구축

사실 12월 한 달 동안은 거의 크롤링 업무를 주로 했다. 크롤링을 해본 적이 거의 없어 기존 다른 팀원이 짜놓은 코드를 이해하는 데만 2주가 걸렸다. 그리고 회사에서도 동시에 scrapy로 크롤링 하는 업무를 맡아 12월은 크롤링의 달이었다😂 그 뒤 드디어 팀 프로젝트다운 일들을 해나갔고 1월 초부터 ES를 건들일 여유가 생겼다. DB 선정 전에는 SQLAlchemy를 배워서 써보려 했지만 ES로 전환하기로 했기 때문에 따로 포스팅 해두겠다.

사진과 같이 그래도 계속해서 프로젝트를 놓지 않고 커밋을 해왔다는 것에 위로를 하며 업무 진행 중 어려웠던 점들을 적어보겠다.

1. bs4와 selenium

  • parser -> 참고링크
  • bs4에서는 find/find_all 혹은 select_one/select (select가 css 외에도 다양한 선택자를 가지고 하위 경로를 직접 지정할 수 있기 때문에 용이)
  • selenium에서는 find_element(By.) -> 문법에 주의 공식문서
  • CSS_SELECTOR와 XPATH를 적절히 잘 섞자. 하나로만 하면 꽝 나는 경우가 너무 많았다.

2. 병렬처리

병렬처리. 꼭 필요했다. 하루에 크롤링해야 하는 데이터가 3천만건이었다. cpu는 최대 12개를 쓸 수 있는 상황이었고, 기존에는 multiprocessing을 이용해서 크롤링 하였지만 나눠놓은 프로세스 중 한 개의 데이터가 크롤링이 끝나지 않으면 다른 프로세스들이 대기해야 하는 상황이 생겼고, 이러면 멀티프로세싱을 나눠놓은 효과를 극대화할 수 없다고 생각해서 다른 방법을 찾다가 ray를 알게되었다. 이를 위한 포스팅 또한 따로 정리하고 여기에는 소스코드만 남겨두겠다.

다만, ray를 쓰면서 문제점이 있었는데, 크롤링한 데이터를 한 번에 엘라스틱에 넣으려고 하면 자꾸 네트워크쪽 문제가 생기는 것이다. 아직 그 쪽 지식이 부족해 정확한 원인은 모르겠으나, 아마 ray 내에서 db에 접속이 중복되면 에러를 일으키는 것 같았다. ray 커뮤니티 내에서 답변을 찾아본 결과, 크롤링 하는 함수와 db에 접속하는 함수를 구분하기로 했고, 이를 통해 해결했다.

만약 크롤링 코드가 안정적이라면 한 번에 다 모아서 bulk update를 해보고 싶다.

import ray

@ray.remote
def crawling() :
	...
    return save
    
def connect_to_db() :
	...
    return 
    
if __name__ == "__main__" :  

    num_cpus = 12
    ray.init(num_cpus=num_cpus, ignore_reinit_error=True)
    results = [crawling.remote(row[0], row[1]) for idx, row in li.iterrows()]

    while len(results):
    	done_id, results = ray.wait(results)
        save = ray.get(done_id[0])
        connect_to_db(save)
        
    print("All process done.")

3. Elasticsearch

ES는 개인적으로 꼭 공부해보고 싶은 스킬이기 때문에 더 자세한 것은 다른 시리즈에서 다룰 예정이다. 엘라스틱을 공부하면서 샤드, 파티션, 인덱스, 노드 등등 다양한 걸 공부했고 이건 꼭 강의를 추가로 수강하고 더 공부해서 정리해둘 필요가 있을 것 같다.

  • es 적재 코드
try :
      es = Elasticsearch("http://localhost:9200")
      index_name = "인덱스 이름"

      # 인덱스 있으면 pass (있는데 만들면 에러)
      if es.indices.exists(index=index_name):
         pass

      else :
            with open('매핑.json', 'r') as f:
                mapping = json.load(f)
                es.indices.create(index=index_name, body=mapping)

     # data insert
     doc = {
            """
            필드로 넣을 데이터
            """
           }
     es.index(index=index_name, id="설정 해줘도 되고 안 해줘도 되고", document=doc)

except OSError:
      print("Error: Failed to create database table.")
  • ES에 적재할 때는 꼭 try except를 써서 예외처리를 해주자. 병렬처리를 해서 insert 할 경우, 동시 접속하면 접속이 거부된다.
  • 성능 최적화를 위해 참고할 블로그 : https://brunch.co.kr/@alden/37

4. 데이터 모델링

데이터 모델링이 사실 최근 작업 중에서 꽂혀있는 작업이었다. 프로젝트 합류 전 이미 테이블 설계가 끝나있었기 때문에 내가 크게 손 볼 것은 없었지만, 엘라스틱이라는 db의 특성이나 ai와의 협업을 생각했을 때 인덱스를 나누거나 필드를 정의할 게 많았기 때문에 고민하면서 참 재밌었던 것 같다. 이에 대한 포스팅 또한 나중에 자세하게 다뤄보기로 하겠다.



🌓 중간 회고

회사가 워낙 자유로워 개인 프로젝트를 하는 것이 크게 어렵지 않았던 것은 사실이다. 그러나 정작 걱정해야했던 것은 회사가 아니라 나 자신이었다. 주니어로서 성장하고 싶어 참여한 프로젝트에서 정작 내가 한 것은 크롤링 공부밖에 없었다. 사실 이건 회사에서의 업무와도 연관되었기에 큰 이득이었던 것은 사실이다.

하지만, 내가 원했던 것은 이게 아니었다. 나는 DB에 대해 좀 더 자세하게 공부하고 싶었고, 처음에 MySQL을 사용한다고 했을 때 DB 최적화나 쿼리 튜닝 같은 업무를 기대했다. 그 뒤, 스케일의 문제로 ES로 넘어갔을 때도 NoSQL을, 게다가 그렇게 핫하다는 ELK 스택을 써볼 수 있다는 기대감이 있었다. 프로젝트는 예상대로 흘러갔지만, 그 기대에 못 미치게 된 것은 나 자신 때문이었다. 오랜만에 한 취업에, 각종 스트레스에, 주중 출근을 핑계로 쉬고싶은 욕망이 넘치는 주말까지 나의 기분을 들쑥날쑥 하게 만드는 것들을 컨트롤 하지 못 했다.

그렇게 감정에 휘둘리고 나면 항상 자책감이 몰려왔다. "아 이거 했어야 했는데"보다는 "아 할 수 있었는데"라는 스스로의 능력과 스케줄을 알고 나서 오는 아쉬움 같은 것이었다. 그래서 침착하게 일주일을 돌아보니 나는 루틴대로 살아야 에너지가 나는 사람이었다. 아침 기상시간부터 강아지 산책까지 정해진 루틴대로 하루를 끝마쳤을 때 비로소 나는 나만의 개인 일정을 할 에너지를 얻는 사람이었다.

그래서 깨달은 그 순간부터 루틴을 웬만하면 지키려고 노력했다. 그러자, 일상 곳곳에 프로젝트에 조금씩이나마 집중할 수 있는 시간이 났고, 그 시간에 에너지를 얻어서, 이동시간에 구상을 하고, 집에 와서 구글링과 실험을 할 수 있었다.

이제서야, 내가 개발자로서 어떤 사람이고 어떻게 학습해야 하는지 조금 감이 잡힌 느낌이 들었다. 회사 업무가 널널한 것을 이용해 나는 더 많은 스킬을 배우기보다 나라는 개발자가 어떤 성향인지 파악하는 시간이었다. 많은 스킬을 배우는 것은 입사 후 지난 두 달간 어쨌는지 몰라도, 우선 어떤 성향인지는 파악했으니 그걸로 됐다.

크롤링 작업이 끝난 후부터가 DE는 진짜라고 시작한다. ES 성능도, 후에 사용할 Kibana도 공부해서 프로젝트를 잘 마무리 할 예정이다.

profile
완료주의

0개의 댓글