출근 40일차

·2022년 10월 21일
2

회사이야기

목록 보기
40/118

오늘은 실제로 코드를 작성한 것보다는 뭐랄까 딴짓을 하는 시간이 길었다.

왜냐하면........택배사 추가 연동은 거의 완료가 됐고
작업한 코드로 물건을 회사로 주문을 해봐야해서 여러가지 사항을 기다리고 있다.

그래서 주소 검색엔진에 조금 더 힘을 실어서 작업을 해봤다.

주소 검색엔진의 아키텍처

이름이 거창한데, 걍 플로우(?)느낌에 가깝다.

  1. 다운로드 받은 모든 주소정보를 로그스태시를 통해서 엘라스틱 서치에 집어넣는다.
  2. 한달단위로 갱신되는 정보를 다운로드받아 AWS 람다에 넣어준다.
  3. 갱신 정보 추가 + 업데이트

딱 3단계로 분리가 되는데, 여기서 문제가 있었다(ㅠㅠ)

그게 뭐냐면 로그스태시로 txt 파일을 어떻게 넣어야할지 감이 안잡히더라

csv파일은 제대로 지원하는 것 같은데, txt 파일은 어떻게 해야할지 모르겠고

제일 중요한 것은 필드를.....언제 그걸 다 지정하고 앉아있어(....)
그래서 이 부분을 자동화를 해야해서 그것에 대한 코드를 짜는게 좀 오래 걸릴 것 같다.

  1. 우체국 사이트에서 파일을 다운로드 받는다(이건 수제로 해야함)
  2. txt 파일을 utf8 + csv 파일로 변환시킨다.
  3. 로그스태시가 달려있는 람다에 던진다.
  4. 람다는 파일 속의 모든 필드를 확인하여 엘라스틱서치에 넣는다.

정도가 조금 더 깊은 정보가 담겨있다.

여기서 먼저 확인을 해야하는 부분이 있었는데, 바로 유사도 쿼리를 어떻게 짜느냐에 대한 부분이였다.

그래서 도커컴포즈 속에서 해당 테스트를 해보려고 했는데...?

어, 로컬DB에 있는 정보를 도커 컴포즈의 DB와 어떻게 직결시키지?

이것저것 자료를 다 봤는데 제대로 돌아가는게 하나도 없어가지고(....)
걍 파일 뽑아서 직접 꽂아봤더니 타입이 안맞더라 (와 날짜가 varchar로 들어가던데?)

심지어 한번에 600만개 쌓여있는거 파일로 뽑으려고 했더니 디비버가 메모리 터져가지고 뻗음ㅋㅋㅋㅋㅋ

그래서 어떻게 했냐면.....

version: '3.7'

services:
  database:
    image: mysql:latest
    environment:
      MYSQL_DATABASE: 'root'
      MYSQL_ROOT_PASSWORD: 'root'
    ports:
      - 3308:3306
    volumes:
      - /Users/Downloads/zipcode_DB/경기도.txt:/var/lib/1.txt
      - /Users/Downloads/zipcode_DB/경상남도.txt:/var/lib/2.txt
      - /Users/Downloads/zipcode_DB/경상북도.txt:/var/lib/3.txt
      - /Users/Downloads/zipcode_DB/광주광역시.txt:/var/lib/4.txt
      - /Users/Downloads/zipcode_DB/대구광역시.txt:/var/lib/5.txt
      - /Users/Downloads/zipcode_DB/대전광역시.txt:/var/lib/6.txt
      - /Users/Downloads/zipcode_DB/부산광역시.txt:/var/lib/7.txt
      - /Users/Downloads/zipcode_DB/서울특별시.txt:/var/lib/8.txt
      - /Users/Downloads/zipcode_DB/세종특별자치시.txt:/var/lib/9.txt
      - /Users/Downloads/zipcode_DB/울산광역시.txt:/var/lib/10.txt
      - /Users/Downloads/zipcode_DB/인천광역시.txt:/var/lib/11.txt
      - /Users/Downloads/zipcode_DB/전라남도.txt:/var/lib/12.txt
      - /Users/Downloads/zipcode_DB/전라북도.txt:/var/lib/13.txt
      - /Users/Downloads/zipcode_DB/제주특별자치도.txt:/var/lib/14.txt
      - /Users/Downloads/zipcode_DB/충청남도.txt:/var/lib/15.txt
      - /Users/Downloads/zipcode_DB/충청북도.txt:/var/lib/16.txt

걍 볼륨에 냅다 꽂아버렸다^^

사실 이런 방식도 있긴 했는데, 적용이 잘 안됐다.

    volumes:
      - /usr/local/var/mysql/address/seoul.ibd:/var/mysql/root/seoul.ibd

이게 무슨 방식이냐면, 데이터베이스에 들어가있는 실제 정보가 .ibd의 형식으로 로컬에 저장되어있다.

그래서 해당 정보를 도커 내부에 직접 꽂아버리는 방식이였는데.... 많은 엄지를 받은 글임에도 불구하고 나는 안되더라..ㅠㅠ

그래서 편법을 썼다. 걍 직접 냅다 꽂고 내가 고치자고!

테이블을 조금 고쳤다, 시간 정보가 필요했음 (...)

CREATE TABLE address ( 
`ZIP_NO` VARCHAR(5) NULL COMMENT '우편번호',
`SIDO` VARCHAR(20) NULL COMMENT '시도',
`SIDO_ENG` VARCHAR(40) NULL COMMENT '시도(영문)',
`SIGUNGU` VARCHAR(20) NULL COMMENT '시군구',
`SIGUNGU_ENG` VARCHAR(40) NULL COMMENT '시군구(영문)',
`EUPMYUN` VARCHAR(20) NULL COMMENT '읍면',
`EUPMYUN_ENG` VARCHAR(40) NULL COMMENT '읍면(영문)',
`DORO_CD` VARCHAR(12) NULL COMMENT '도로명코드',
`DORO` VARCHAR(80) NULL COMMENT '도로명',
`DORO_ENG` VARCHAR(80) NULL COMMENT '도로명(영문)',
`UNDERGROUND_YN` CHAR(1) NULL COMMENT '지하여부',
`BUILD_NO1` DECIMAL(5,0) NULL COMMENT '건물번호본번',
`BUILD_NO2` DECIMAL(5,0) NULL COMMENT '건물번호부번',
`BUILD_NO_MANAGE_NO` VARCHAR(25) NULL COMMENT '건물관리번호',
`DARYANG_NM` VARCHAR(40) NULL COMMENT '다량배달처명',
`BUILD_NM` VARCHAR(200) NULL COMMENT '시군구용건물명',
`DONG_CD` VARCHAR(10) NULL COMMENT '법정동코드',
`DONG_NM` VARCHAR(20) NULL COMMENT '법정동명',
`RI` VARCHAR(20) NULL COMMENT '리명',
`H_DONG_NM` VARCHAR(40) NULL COMMENT '행정동명',
`SAN_YN` VARCHAR(1) NULL COMMENT '산여부',
`ZIBUN1` DECIMAL(4,0) NULL COMMENT '지번본번',
`EUPMYUN_DONG_SN` VARCHAR(2) NULL COMMENT '읍면동일련번호',
`ZIBUN2` DECIMAL(4,0) NULL COMMENT '지번부번' ,
`ZIP_NO_OLD` VARCHAR(4) NULL COMMENT '구우편번호' ,
`ZIP_SN` VARCHAR(2) NULL COMMENT '우편일련번호',
`CREATED_AT` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP,
`UPDATE_AT` datetime(6) NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ) 
ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 AUTO_INCREMENT=1;

그리고 내가 어제는 깜빡했는데, 데이터 로드를 쓰려면 설정값이 필요하다.

  1. mysql --local_infile=1 -u root -p
  2. set global local_infile=true;

내가 보기에는 위에꺼만 해도 충분한데 (일회성으로 제한 푸는거라) 가끔 안되길래 걍 둘 다 치고 하고 있다ㅎㅎ..ㅎㅎ

저렇게 허용을 안하면 SQL ERROR 3948번 [42000] 에러가 발생한다.

아무튼 테이블을 생성해놓고, 이제 값을 넣어주면 된다!

(대신 도커 내부에서 넣어줘야한다. 이렇게 쓸꺼니까)

데이터 로드 할 때 썼던 SQL

LOAD DATA LOCAL INFILE "/var/lib/16.txt" INTO TABLE address CHARACTER SET 'UTF8MB4' FIELDS TERMINATED BY '|' OPTIONALLY ENCLOSED BY '"' LINES TERMINATED BY '\n' IGNORE 1 LINES
(@ZIP_NO, @SIDO, @SIDO_ENG, @SIGUNGU, @SIGUNGU_ENG,
@EUPMYUN, @EUPMYUN_ENG,
@DORO_CD, @DORO, @DORO_ENG,
@UNDERGROUND_YN, @BUILD_NO1, @BUILD_NO2,
@BUILD_NO_MANAGE_NO, @DARYANG_NM,@BUILD_NM,
@DONG_CD, @DONG_NM,@RI, @H_DONG_NM, @SAN_YN,
@ZIBUN1, @EUPMYUN_DONG_SN, @ZIBUN2, @ZIP_NO_OLD, @ZIP_SN)
SET
ZIP_NO = NULLIF(@ZIP_NO,'0'),
SIDO = NULLIF(@SIDO,'0'),
SIDO_ENG = NULLIF(@SIDO_ENG,'0'),
SIGUNGU = NULLIF(@SIGUNGU,'0'),
SIGUNGU_ENG = NULLIF(@SIGUNGU_ENG,'0'),
EUPMYUN = NULLIF(@EUPMYUN,'0'),
EUPMYUN_ENG = NULLIF(@EUPMYUN_ENG,'0'),
DORO_CD = NULLIF(@DORO_CD,'0'),
DORO = NULLIF(@DORO,'0'),
DORO_ENG = NULLIF(@DORO_ENG,'0'),
UNDERGROUND_YN = NULLIF(@UNDERGROUND_YN,'0'),
BUILD_NO1 = NULLIF(@BUILD_NO1,'0'),
BUILD_NO2 = NULLIF(@BUILD_NO2,'0'),
BUILD_NO_MANAGE_NO = NULLIF(@BUILD_NO_MANAGE_NO,'0'),
DARYANG_NM = NULLIF(@DARYANG_NM,'0'),
BUILD_NM = NULLIF(@BUILD_NM,'0'),
DONG_CD = NULLIF(@DONG_CD,'0'),
DONG_NM = NULLIF(@DONG_NM,'0'),
RI = NULLIF(@RI,'0'),
H_DONG_NM = NULLIF(@H_DONG_NM,'0'),
SAN_YN = NULLIF(@SAN_YN,'0'),
ZIBUN1 = NULLIF(@ZIBUN1,'0'),
EUPMYUN_DONG_SN = NULLIF(@EUPMYUN_DONG_SN,'0'),
ZIBUN2 = NULLIF(@ZIBUN2,'0'),
ZIP_NO_OLD = NULLIF(@ZIP_NO_OLD,'0'),
ZIP_SN  = NULLIF(@ZIP_SN,'0');

크게 달라진 것은 없고, 내가 명시해놓은 도커 볼륨의 절대경로와 테이블을 한개로 써보기로 했다.

이제 로그스태시에 던질 준비가 완료 됐으니까, 서버작업을 진행해야한다.

주소는 한달마다 변경하는데, PK가 있다!

엘라스틱서치에 도큐먼트ID를 한개로 쓰면, 정보가 업데이트 될 때 덮어쓰기를 할 수 있다.

정확하게 말하면 지웠다가 새로 생성하는거라 효율이 개노답(...)이긴 하지만.

그렇지만 10번의 건물관리번호를 도큐먼트ID로 사용하면 한달단위로 수정되는 값이 들어가더라도 큰 문제가 없을 것 같더라!

제법 해피해졌다 :>

prisma? 함 써보자!

현재 ELK 테스트를 위하여 아예 프로젝트를 하나 새로 뺐다.

다른 팀원분들도 ELK에 관심도가 제법 있었고 prisma라던가 graphql에 관심을 보이시길래

걍 내가 검색엔진 작업하는거 서버로 빼가지고 써보고싶은 스택 다 붙여본다음에 다같이 장난감처럼 가지고 놀아보는게 목표다!

근데 프리즈마가 너무 편하다...

  • npx prisma init
    • 시작을 하려면 해당 명령어를 사용한다. 그럼 파일이 뿅 하고 나온다.
  • npx prisma db pull instead
    • 이 명령어를 쓰면 DB의 테이블 정보를 알아서 다 긁어온다.

  • npx prisma studio
    • 이거쓰면 그냥 데이터베이스를 GUI로 볼 수 있다.

진짜 흠.... 너무 좋은데? 라는 생각이 들었다.

그리고 현재 우리 프로덕션과 데브의 데이터 정의방식이 동일한데,
enum을 제대로 지원을 안하는지 한번 땡겨봤는데 타입이 다 작살나있더라?
그래서 이 부분은 좀 찾아봐야할 것 같다.

아무튼 그래서 주말동안 작업해야하는 것들이 대충 윤곽이 보인다.

  1. 서버 API 작업, 프레임워크는 NestJS를 사용하고 버전은 9.0.0대를 쓸 것이다.
  2. REST API가 아닌 GraphQL를 사용할 예정이고
  3. DB는 MySQL, ORM은 prisma로 진행한다.
  4. ELK는 7.17버전을 사용할 예정.
  5. 한글 분석기인 Nori를 엘라스틱서치에 달아줘야한다.
  6. 커스텀 템플릿 쓸꺼라 템플릿도 작성해야하고
  7. 로그스태시 conf 파일도 작성
  8. 엘라스틱서치의 자세한 값도 좀 찾아서 집어넣으면 좋겠다

지금 걱정인 것은, 엘라스틱서치를 도커컴포즈로 옵션들을 다양하게 먹여야하는데
이거 좀 많이 헤멜 것 같아서 걱정이긴하다(...)

그리고 서버, DB, ELK 다섯개를 한번에 다 올릴건데 노트북 뻗진 않겠지??

상황보고 젤 무거운 키바나를 빼던가 해야겠다;


오늘부터 트위터에서 주니어탤런트쇼를 진행자로 참가하게 됐는데 음...
역시 긴장이 아예 안될 순 없더라...

그래서 좀 아쉬웠다.
나왔던 내용들이 좋은게 많아서 나중에 한번 돌려듣고 가능하다면 정리해서 올려봐야겠다.

profile
물류 서비스 Backend Software Developer

0개의 댓글