today.log

액셀로 전달받은 데이터를 테이블에 저장하기

dextto™ 2020. 5. 12. 22:35

모두싸인은 GetSiteControl이라는 도구를 적극 사용한다. 회사 내에서는 '겟사콘'이라고 부르고 있다. 한 예로 이렇게 생겼다. 

개발자가 아닌 운영 직군의 사람도 간단 설정 메뉴를 통해 다양한 형식의 팝업을 띄울 수 있다. 큰 기능 배포를 위해 홈페이지 상단에 배포 일정을 띄울 때도 사용한다.

따로 개발 리소스를 투입하지 않고 꽤 괜찮은 UI를 가진 화면을 뚝딱 만들어 낼 수 있는 좋은 도구다.

 

모두싸인에 처음 가입하고 간단한 설문조사를 하면 1달 동안 프리미엄 요금제로 무료 사용할 수 있도록 해 준다.

그런데 이 때 입력 받는 항목에 전화번호가 없어서 영업에 잘 활용하지 못했다. 도입하고 싶다고 먼저 연락을 했던 고객에게도 메일로만 회신을 해야 해서 대응이 느린 경우도 있다. 그래서 이번에 설문항목에 전화번호를 선택 항목으로 넣기로 했다.

 

작업을 마치고 나서 기존에 위와 같은 겟사콘 설문으로 쌓아놓은 데이터를 새로 추가한 필드에 채워 넣어주기로 했다. 

서론이 길었는데, 이 과정을 하면서 겪었던 과정을 풀어 보자.

 


마이그레이션을 위해 전달받은 겟사콘 데이터는 액셀이었다. 

이중에서 색깔로 칠해진 데이터를 User 테이블에 새로 추가된 phone_number, funnel, search_word 필드에 넣어줘야 한다.

 

방법1: mysql 쿼리를 짜서 처리하기

일단 액셀을 csv 파일로 저장한다.

csv로 변환하는 이유는 mysql 명령어로 csv파일에서 테이블에 집어 넣을 수 있기 때문이다.

  • 열을 추가된 필드만 남기고 삭제한다.
  • 첫번째 행은 지운다
  • csv로 저장한다.

이런 식으로 된다.

임시 테이블을 만든다.

데이터베이스가 실행되고 있는 도커 컨테이너 안에 들어가서 mysql을 실행한 후 아래 명령어를 넣으면 된다.

use UserService;
create table UserService.GetSiteControl
(
    date         varchar(20) null,
    phone_number varchar(30) null,
    funnel1      varchar(30) null,
    funnel2      varchar(30) null,
    search_word  varchar(30) null,
    user_id      varchar(40) null
);

csv에 있는 데이터를 임시 테이블에 넣는다.

이 과정에서 production DB에 직접 접근해서 하기는 위험하니까 DB툴을 이용하기로 한다. 일단 로컬 DB에 넣고 복사+붙여넣으면 되겠다.

 

mysql 도커 컨테이너를 확인한다.

docker ps

해당 컨테이너로 csv 파일을 복사한다.

docker cp {local_file_path} {container_id}:{docker_path}
ex) docker cp /Users/dexter/Downloads/stage.csv bfa9f3559e82:/

도커 안으로 들어간다.

docker exec -it {container_id} bash

로컬 mysql docker에 들어가서 csv파일 데이터를 테이블에 집어넣는 명령어는 다음과 같다.

LOAD DATA INFILE '{file_path}' INTO TABLE {table_name} FIELDS TERMINATED BY "{delimeter}";
ex) LOAD DATA INFILE '/stage.csv' INTO TABLE GetSiteControl FIELDS TERMINATED BY ",";

그런데 처음에 위 명령어를 실행하면 이런 에러가 난다.

The MySQL server is running with the --secure-file-priv option so it cannot execute this statement

mysql 설정을 바꿔준다.

vi /etc/mysql/my.cnf
마지막에 아래 내용을 넣고 저장.
[mysqld]
secure-file-priv=""

이 과정에서 vi가 없다면 설치해 준다.

apt-get update apt-get install vim

mysql을 재시작한다.

service mysql restart

다시 LOAD DATA를 한다.

잘 들어갔다.

production의 데이터베이스에도 위에서 처럼 같은 임시 테이블을 만든 후, 로컬에 있는 데이터를 복사해서 붙여넣자.

이제 임시 테이블(GetSiteControl)에서 User 테이블로 필요한 데이터를 옮기는 쿼리를 수행하면 끝!

UPDATE UserService.User as User INNER JOIN UserService.GetSiteControl as GSC
ON User.id = GSC.user_id
SET
    User.surveyPhoneNumber = GSC.phone_number,
    User.surveyFunnel = concat(GSC.funnel1, '/', GSC.funnel2),
    User.surveySearchWord = GSC.search_word;

방법2: 액셀을 읽어서 백엔드에서 제공하는 API로 호출

방법1로 해피하게 끝났으면 좋았을 텐데, 한가지 문제가 있었다. 겟사콘을 작성할 때 유효성을 검증해 줄 수가 없다.

입력받는 전화번호 란에 숫자, +, - 문자 같이 실제 전화번호를 구성하는 문자들로만 입력받게 할 수가 없다. 

실제 데이터에도 그랬다.

 

전화번호 전처리를 쿼리로 작성하기는 힘들어서 xslx 라이브러리를 이용한 코드를 작성했다.

결국 데이터 입력은 백엔드에서 제공하고 있던 API를 호출했다. 문제는 대량의 호출을 해야 하는데 과연 잘 될 것인가...


결국은 2가지 방법을 섞어서 쓰는 것으로..

가만히 생각해 보니 액셀 파일 데이터를 직접 업데이트 하면 된다. 방법2에서 작성해둔 전화번호 전처리 코드를 이용해서 액셀 시트의 값을 업데이트 한 후 저장했다. 그리고 방법1로 임시 테이블에 넣은 후 쿼리 수행. 

 

왜 처음에 이 생각을 못했지?

반응형