뒤로가기뒤로가기

데일리 랩스

캠퍼스론을 위한 데이터 정형화 프로젝트 vol.1

에러를 마주하는 매 순간의 이슈

데일리펀딩

 

?인턴을 시작한 지 어느덧 두 달이 넘어갔다. 오늘은 그동안 공부한 내용들과 분석한 내용을 바탕으로 '캠퍼스론을 위한 데이터 정형화 프로젝트'에서 진행하고 있는 내용에 대해서 이야기해 보려고한다.


개발일지1

우선 어떤 특정한 주제를 정해서 그 내용에 대해서만 데이터를 수집하는 것이 아니라, 해당 유저의 다양한 정보들을 최대한 많이 가져오는 것으로 진행해 보라고 하셔서 유저의 모든 게시글, 댓글과 관련한 정보들을 스크래핑 해왔다. 이 데이터들을 DB에 저장하기 위해서 ERdiagram을 작성했고, 이에 맞추어 우리의 서버에서 저장할 수 있도록 했다.

 

[ ERDiagram 설계 ]

가장 기본적인 데이터에 해당하는 테이블은 4개가 있다. 우리 서비스의 유저와, 해당 유저의 인스타그램계정 정보, 게시글 정보, 댓글 정보를 저장하는 테이블이다. 각각 데이터에 대한 ID값을 키값으로 가지고 있지만 한 명의 유저가 여러 개의 인스타그램 계정을 보유할 수도 있기 때문에 instagram 테이블은 Auto Increment 속성을 가지는 정수형 ID를 키값으로 갖도록 설계했다.

instagram_[ ]_count에 해당하는 테이블은 게시글과 댓글에 따른 좋아요 수와 게시글의 개수, 게시글에 따른 댓글의 수의 추이를 저장하는 테이블이다. 변동 추이를 활용해서 데이터를 정형화할 수도 있기 때문이다. 원래 time과 count 컬럼을 이용해서 복합키로 설정하려고 했는데, Auto increment 속성을 가지는 기본 키를 설정했다. (사실 typeORM으로 entity를 선언하는데 타임스탬프 타입의 변수가 기본 키로 설정이 안되어서 우회했다 ?)

해시태그에 대해서는 이미 존재하는 해시태그가 계속 추가되지 않도록 하기 위해서 해시태그만 저장하는 테이블을 만들고, 게시글과 해시태그를 매칭하는 테이블, 댓글과 해시태그를 매칭하는 테이블을 만들었다. 원래는 instagram_content_hashtag와 instagram_comment_hashtag를 하나의 테이블에 넣고 게시물인지, 댓글인지를 구분해 주는 컬럼을 넣으려고 했으나 댓글과 게시글의 ID 값의 길이가 달라서 구분했다.

 

[ MySQL RDS ]

xuzy님과 함께 진행 중이기에 MySQL을 로컬로 사용할 수가 없었다. 따라서 AWS의 RDS를 활용해서 클라우드에서 DB를 운영하기로 했다. 한글 인코딩을 위해서 파라미터 그룹의 인코딩 관련 파라미터의 값을 UTR-8로 지정하고, 이 파라미터 그룹을 DB에 적용했다. 이후 접속 권한을 설정하기 위해 인바운드 규칙과 VPC 보안그룹 등을 설정하고 각각의 개념에 대해서 공부했다. 이후 우리의 프로젝트에서 이 RDS의 인스턴스에 접근해서 데이터를 저장할 수 있도록 했다.

 

[ typeORM을 이용한 데이터 저장 ]

NestJS 강의를 들을 때에는 몽고DB를 이용한 실습만 해봐서 관계형 DB인 Mysql을 이용할 때에는 어떻게 저장하는지 구글링과 공식 문서를 보고 학습하며 진행했다. 처음에 스크래핑을 진행할 때 TypeScript에서 직접 스크래핑도 해오고, 저장해야겠다고 했으나 레퍼런스 부족으로 인해 파이썬으로 변경한 경험이 있기에,, 이번에는 레퍼런스가 많은 방식으로 DB에 저장해야겠다고 생각했다. NestJS와 MySQL을 연결할 때 TypeORM을 가장 많이 사용하는 것 같고 레퍼런스도 많아서 이로 결정하고 연동을 시작했다.

관계형 DB를 ORM을 활용해서 진행한 적은 처음이라 새롭게 알게 된 개념이 있었다. 바로 Synchronize 속성인데 이 속성을 true로 지정하면, 서버를 켤 때마다 엔터티를 DB와 동기화한다. 엔터티에 열을 추가하거나 새 엔터티를 만들어 새 테이블을 만드는 등 서버가 시작되면 DB가 자동으로 업데이트된다. 각각의 속성을 이해하지 못하고 우선 프로젝트에 적용하고 일부 엔터티에 대해서만 실습을 진행하다가 MySQL에서 다이어그램을 켰을 때, 이전에 직접 쿼리문으로 생성해둔 테이블들이 사라져서 꽤나 당황했었다. ? 하지만 이후에 설계에서 빠뜨린 부분이 생겨 수정을 진행해야 할 때마다 이 속성을 아주 잘 활용했고,, 없었으면 어쩔뻔했나 싶었다,,ㅎㅎ


개발일지2

매 순간 에러를 마주하는 만큼 매 순간이 이슈이지만, 최근에 꽤나 오랜 시간 동안 해결하지 못했던 이슈에 대해서 정리해 보려고 한다.

 

⚠️문제 발생

서비스에서 댓글을 저장하도록 하고 나니 아래의 에러가 계속 발생했다. 데이터베이스에 저장되는 댓글 데이터에 대해서도 저장되는 값의 개수가 불규칙했다.

 

⁉ 원인 찾기

instagram_commment 테이블의 경우 자기 자신 테이블의 다른 값을 참조하는 컬럼이 존재한다. parentsID 컬럼이 replyID를 참조하는데, 그러기 위해서는 praentsID에 담는 값이 replyID에 저장이 되어있어야 한다. 위의 에러에서 말하는 내용이 이 내용이다.

( 댓글의 경우 parentsID가 null 값이고, 대댓글의 경우 parentsID에 댓글의 replyID를 저장한다. )

 

? 시도1

따라서 다시 로직을 점검해 보았다. 먼저 파이썬 코드에서 json형식으로 값을 서버로 넘겨주고, 서버에서는 이 json형태의 값을 DB에 저장한다. 이때 댓글과 대댓글은 json에서 하나의 배열에 담겨서 넘어간다. 따라서 댓글, 대댓글 순서로 DB에 저장되기 위해서는 배열에 담길 때도 그 순서가 지켜져야 한다. 이를 점검했을 때는 정확한 순서대로 값이 담겨있었다.

 

? 시도2

그렇다면 서버에서 DB에 저장될 때 값이 정확한 순서대로 저장이 되지 않는 건가 싶어서 서버 코드를 점검해 보았다.

댓글과 대댓글을 담고 있는 배열에서 값을 저장하는 반복문에서 DB가 저장을 완료하고 리턴을 하는 것이 아니고 저장을 시도한 뒤 완료되지 않은 채 다음 반복문이 실행되는 것이 아닐까 싶었다. await을 활용했기 때문에 typeORM의 문제일까 싶었으나 다른 데이터는 await가 잘 작동하기 때문에 이것이 원인은 아니었다.

 

? 해결

결국 원인은 문법에 있었다..

동기와 비동기가 문제일 것 같다는 생각에 다다른 뒤에는 빠르게 해결할 수 있었다? 문제는 반복문 자체였다. forEach함수를 통해서 배열의 값을 꺼내와 각각의 데이터를 DB에 저장했는데, forEach함수는 비동기 처리가 이루어지지 않기 때문이었다. map과 forEach와 같은 메서드는 콜백 함수가 비동기라 할지라도 그것의 처리결과를 기다려 주지 않고 병렬로 돌면서 콜백 함수를 실행하기만 한다고 한다. ? 따라서 forEach문을 for...of 문으로 변경한 뒤 순차적으로 저장을 할 수 있게 되었다.

 

 

오늘의 주저리주저리

세배의 법칙은 언제나 들어맞는 것 같다? 스크래핑과 DB 설계, 저장, 데이터 저장 후 정형화까지 원래는 이번 주에 끝내는 것을 목표로 하고 있었는데 매일매일 마주하는 새로운 오류들과 이슈들 때문에 생각보다 오래 걸리고 있다ㅜㅜ 지금도 새로운 이슈와 싸우고 있는데 얼른 이 오류와 문제를 해결하고 다음 단계로 넘어가고 싶다. 그래도 해결할 때의 쾌감이 있기 때문에 계속 힘내서 진행할 수 있는 것 같다. 앞으로도 이 뿌듯함과 쾌감을 느끼기 위해 매일매일 힘내서 남은 인턴 기간을 알차게 보내고 싶다?

 

우리는 매일 금융의 각을 넓혀가는
데일리언입니다.

데일리언과 함께하기 >