1. Insert 하는 방식

Druid의 Insert는 spec과 raw data에 관한 JSON을 서버와 통신하며 이뤄진다.

JSON에는 데이터 JSON이 담긴 위치와 granularity, segment, dimension spec 등이 저장된다.

https://druid.apache.org/docs//0.15.1-incubating/ingestion/ingestion-spec.html

 

Druid | Ingestion Spec

Table of Contents <!-- ~ Licensed to the Apache Software Foundation (ASF) under one ~ or more contributor license agreements. See the NOTICE file ~ distributed with this work for additional information ~ regarding copyright ownership. The ASF licenses this

druid.apache.org

raw data는 new line으로 구분된 json이다. [다른 형태로도 가능하게 해놨는지는 잘 모르겠다]

spec에 관한 json과 raw data json이 준비됐다면,

curl -X 'POST' -H 'Content-Type:application/json' -d @{spec에관한JSON경로} http://{druid주소 및 포트}/druid/indexer/v1/task

형태로 insert 할 수 있다.

 

 

2. Delete 하는 방식

TSDB류의 특성상 DELETE는 까다로운 편이다

일단 __time의 Interval을 지정해 row를 unused로 mark해 주어야 한다.

curl -X 'POST' -H 'Content-Type:application/json' -d '{ "interval" : "1990-01-03T00:00:00.000Z/2222-02-09T00:00:00.000Z" }' http://{druid주소 및 포트}/druid/coordinator/v1/datasources/{datasource 이름}/markUnused

이렇게 하면 interval에 속하는 row들이 unused로 마크되고,

 

Datasource - Actions에서 Delete 가능하게 바뀐다.

1. Druid에 Load

Data를 가져와서(Extract) 가공(Transform)한 후 Druid에 올린다(Load). [전형적인 ETL]

드루이드에 올릴 때는 json으로 input source 및 dataSchema에 대한 정보를 적어주고 api로 전송한다.

curl -X 'POST' -H 'Content-Type:application/json' -d @{spec에관한JSON경로[Datasource에 관한 내용도 포함되어 있음]} http://{druid주소}/druid/indexer/v1/task

 

2. Airflow 자동화

Airflow는 Metadata와 설정된 DAG들을 참고하여 Scheduler가 Worker에 일을 시키는 구조를 지닌 워크플로우 관리 플랫폼이다.

Airflow Architecture

일반적으로 파이썬을 통해 ETL을 자동화 구성한다면,

DAG를 설정하는 소스를 Scheduler에 등록하고 Worker에 소스를 Deploy해서 쓴다. [각주:1]

3. 전체적인 자동화 ETL 구조

Superset까지 포함한 대략적인 구조도

1) scheduler가 cron으로 정해진 시간대에 worker한테 정해진 DAG를 실행시킨다.

2) worker는 Datasource에 가서 쿼리를 날리거나 수집하는 형태로 정해진 데이터를 받는다

3) worker에서 가공하여 Druid로 보낸다.

4) Druid는 Superset에 연계되어 데이터 시각화 및 통계를 제공한다.

  1. Worker와 Scheduler 및 Metadata DB는 각자 분리해 구성하는 것이 합리적으로 보인다. Worker들을 여러 대 관리해야 Airflow의 효율이 더 좋기 때문이다. 또한 한 Device로 scheduler에 Worker까지 구성하면 시스템이 확장될수록 scheduler의 기능적 제약이 있을 수도 있다. [본문으로]

1. DataScraping이란?

다른 툴 대비 Uipath의 강력한 장점 중 하나다.

'웹크롤링' 생산성을 비약적으로 높여주는 액티비티다.

(**modern 기준 extract structured data)

 

규칙성이 있는 2개의 Element만 찍어주면 자동으로 규칙성을 찾아 화면의 데이터를 datatable로 담아온다.

사용법은 굉장히 간단하게 돼있다.

첫번째 element를 클릭하고 다음 element를 클릭하면 UI의 구조적 규칙성을 찾아 알아서 구성해준다.

(**modern 기준으로는 하나만 찍고 특성을 골라도 되는 것처럼 보임)

이것이 가능한 이유는 UI요소들의 배치가 일반적으로는 구조적 규칙성을 띄기 때문이다.

 

사용법은 이렇다. (Legacy Template 기준. modern도 방식은 거의 비슷하나 use app browser로 생성된다는 차이가 있음.)

1. 첫번째 Element 선택(Get info of ui by UI Explorer)

2. 두번째 Element 선택(Get info of ui by UI Explorer)

3.규칙성 찾음(구조적 규칙성[웹이라면 X-path])

4.특정 Selector 기준으로 규칙성에 따라 Get Data

 

2. 기준 Selector와 Metadata 조정의 필요성

다만 다음과 같은 경우에 대응이 어렵다.

A. 광고유무, 특정 트리거 유무에 따라 구조가 달라지는 경우

B. 기준이 되어야 할 요소가 화면상 특정 요소에 가려져 있는 경우

 

A는 데이터를 가져오는 기전을 생각하면 너무나 자명한 결과다.

심지어 구조적으로 같으면 해당 컬럼에 그 데이터를 넣기 때문에 잘못 가져올 수 있는 위험도 있다.

따라서 케이스에 대한 정확한 파악이 있어야 한다.

대부분 기준 selector를 잘 찾아야 해결이 된다.

필요하다면 Find Children 같은 액티비티를 이용해 동적인 기준을 잡아야 한다.

 

B는 구조상 DIV가 Wrapping 돼있어 구조를 따로 파고 들어가지 않는 이상 선택이 어려운 경우다.

기준 요소를 다시 잡는 것은 어렵지 않으나 바뀐 기준에 따라 변경된 MetaData는 새롭게 수정해줘야 한다.

 

 

3. Data Scraping MetaData의 조정

MetaData는 기준으로 잡힌 Selector에서 어떻게 데이터를 가져올지 구조를 열거한 XML 데이터다.

row 태그 : 1줄의 기준을 어디로 잡을지를 정한다.

column 태그 : 가져오는 컬럼을 정한다. 속성 exact를 1로 하면 그 구조가 안 맞는 경우 안 가져온다. 0으로 하면 없을 때, 구조가 비슷한 것을 가져온다.

name 속성 : name은 기본적으로 가져오는 컬럼명이다. 같은 구조에서 다른 attr을 가져오고 싶다면, name2='다른이름' 식으로 적어주고 해당하는 attr을 attr2='속성명'으로 적어주면 된다.

attr 속성 : metadata 구조에 해당하는 타겟으로부터 얻고자 하는 속성.

 

예시를 보자.

<extract>
	<row exact='1'>
		<webctrl tag='div' />
		<webctrl tag='article' idx='1' />
	</row>
	<column exact='1' name='예시1' attr='text' name2='예시3' attr='src'>
		<webctrl tag='div' />
		<webctrl tag='article' idx='1' />
		<webctrl tag='section' idx='1' />
		<webctrl tag='h3' idx='1' />
		<webctrl tag='span' idx='1' />
	</column>
	<column exact='1' name='예시2' attr='text'>
		<webctrl tag='div' />
		<webctrl tag='article' idx='1' />
		<webctrl tag='section' idx='2' />
		<webctrl tag='div' idx='1' />
	</column>
 </extract>

예상 결과값

dtData = ["예시1", "예시3", "예시2"

"test1", "src값", "test2222"

"test11", "src값", "test222222"]

이때 row의 첫줄 div는 기준 셀렉터의 아래 div태그를 의미한다.

기준 셀렉터 기준으로 아래에 div - article이라는 태그가 있으면 그 기준을 하나의 행 기준으로 보겠다는 의미다.

예시1 컬럼을 보면 row에 해당하는 기준 아래에

section이라는 태그, h3 태그, span 태그의 text를 가져온다.

예시2 컬럼은 row에 해당하는 기준 아래 section이라는 태그 중 2번째, 그리고 div 태그의 text값을 가져온다.

예시3 컬럼은 예시1과 같은 구조에서 src값을 가져온다.

 

 

이를 지정하기 위해선 기준 Selector의 Xpath나 Fullpath를 알아야 한다.[각주:1]

/html/body/div[2]/div[1]/div[2]/div[2]/div/div[2]/div/div/div[2]/div[2]/section/div[1]/div[1]/article/section[1]/h3/span

위에 예시를 보면 파란색 글씨가 기준 셀렉터로 잡힌 곳, 빨간색으로 표시된 곳이 row이고

그 아래에 어떤 구조의 태그로 들어가느냐를 row를 포함해서 적어주면 된다.

 

 

사용상 주의점

- 기본이 Continue On Error로 돼있기 때문에 데이터가 들어가지 않거나 selector를 못 잡아도 그냥 넘어간다.

- 기준이 되는 요소가 틀 형태로 먼저 뜨고 로딩 이후 데이터가 뿌려진다면 Retry Scope으로 row 수나 nothing 여부를 체크해야 한다.[각주:2]

- 경우에 따라 metadata 자체가 조건에 맞춰 변화해야 할 수도 있다. 가령 랜덤으로 광고가 뜨면서 구조가 바뀐다든가 하는 경우도 많다. 또는 안정적인 셀렉터가 자동으로 잡히는 셀렉터의 상위 구조에 있을 수 있다.

- 버그같아 보이는데, 추출 column이 여러 개 일때, 앞선 태그가 없으면, 그 뒤의 정보들의 구조가 맞더라도 데이터가 안 들어오는 경우가 있다. 재밌는 점은 메타데이터에 쓰인 순서를 변경하면 해결되기도 한다는 것. 가령 price1, price2, price3으로 크롤링 했는데 price1의 구조가 비어있는 경우 price2, price3, price1 형태로 바꾸면 잘 된다. 그럼 price2가 없는 경우 같은 현상이 일어나지 않을까 했는데, 그건 잘 가져왔다. 왜 그러는지 가늠이 잘 안 되지만 안 되면 순서를 바꿔보자. 아마도 metadata의 추출 과정에서 True/False 순서에 영향을 받는 거 아닐까 추정만 하는 중.

  1. 브라우저 개발자 도구에서 element를 찾아 우클릭하면 copy 가능하다. [본문으로]
  2. 기준 요소만 뜨면 데이터를 가져오려고 하기 때문이다. 데이터를 기다리지 않는다. [본문으로]

History

초기에는 Click Stream을 기록하기 위한 수단으로서 활용되었음

기존 관계형DB가 아닌 TSDB와 거의 비슷한 개념임

가능한 Group by 조합에 모두 Index를 부과하여 퍼포먼스를 제고하는 방식

다만 TSDB와는 달리 통계량을 뽑아내는 것에 대해 퍼포먼스를 높이도록 조직됨

기존에 이런 방식으로 작동하는 OLAB이 있었으나 솔루션 가격이 매우 비쌌음

그러던 중 Imply Data라는 곳에서 자신들의 기술력을 알리기 위해 OLAB 기반으로 개발하여

아파치 재단을 통해 오픈소스로 출범시켜 버림[각주:1]

이후 에어비엔비에서 드루이드를 기반한 솔루션을 개발한 것이 Superset임

초기 Superset은 연결할 수 있는 Database로 드루이드만 지원됐으나,

지금은 Postgre, Mysql 등 다양한 DB와 Connection 할 수 있게 발전함

특징

Druid와 비슷한 TSDB로 Click House, SnowFlake, BigQuery(구글), RedShift(아마존)가 있음

다만 TSDB와는 달리 Join하기가 어려움

따라서 Join하지 않아도 되는 큰 테이블을 만들어 처리하는 것이 편리

오픈소스이기 때문에 시스템이 안정적이진 않음[각주:2]

Superset은 문자형 컬럼, 숫자형 컬럼으로 나뉨

숫자형 컬럼을 Dimension으로 선택하면 새로운 통계량을 그래프로 쉽게 나타낼 수 있음

데이터를 요청자 스스로 조정하여 Group-by graph를 얻는 데 용이함

 

개발

ETL을 통해 Database에 올림

Ingestion은 Job History가 나오고 Query탭을 통해 업로드한 Data를 확인할 수 있음

보통 Dictionary로 데이터를 저장하고 JSON 형태로 Transform함

TS 기반이면서 실시간성을 띌 수 있게 조직되었기 때문에 데이터 분할 term에 대한 segment가 존재함[각주:3]

가령 Hour segment라면 1시 1분에 올리고 1시 59분에 올리면 덮어쓰기가 됨

Data Update가 어려운 TSDB 특성상 Segment 단위를 통째로 다시 올려야 제대로 업데이트가 됨

기준 데이터에서 컬럼을 삭제하면 바로 적용되어 제대로 출력되지 않음

컬럼을 추가하는 경우 'Sync Columns From Source'를 눌러 새로고침함

  1. 이로인해 OLAB의 가격이 급락하며 어떤 분야든 데이터 분석 시대가 도래했다는 후문 [본문으로]
  2. 불안정한데도 Druid의 유지비용이 다른 솔루션들에 비해 저렴한 편은 아니라고 함 [본문으로]
  3. 이를 Granularity라고 한다. 작은 양을 짧게 자주한다면 fine-grained 반대로 큰 양을 가끔한다면 coarse-grained라고 한다. Granularity는 이 두 개념의 합집합 정도로 생각할 수 있다. [본문으로]

DB연결 시 DSN으로 세팅하는 게 편하긴 하지만

Credential 변경 시 Device마다 각각 들어가서 바꿔줘야 한다.

그래서 규모가 커질 수록 Connection String을 설정해 Asset과 연동되도록 하는 것이 편하다.

 

"Driver={ODBC Driver 이름};Server=서버IP;Port=포트번호;Database=DB이름;Uid=아이디;Pwd=패스워드;"

 

ODBC는 일단 적절한 버전을 깔도록 하자. [보통 RPA에서는 32비트로 연결되므로 5점대 버전이 안정적이다]

ODBC 설정에 들어가서 '추가'를 누르면 다음과 같이 뜬다.

 

ODBC 선택창

여기서 뜨는 '이름'을 Driver에 적어주자.

-----------------------------------------------------------------------------------------

혹시나 DB 종류가 다른 경우, 가령 오라클이면

Oracle ODBC를 깔고 Oracle ODBC connection string을 쳐서 찾아보면 된다.

다만 Driver name은 웬만해선 지정해줘야 돌아가니 체크

굉장히 드문 경우지만 IP Block 등을 막기 위해서 RPA 과제 진행 중 Proxy를 사용하는 케이스가 있다.

그 경우 지금 VPN이 돌고 있는지 아닌지를 알기 위해 기존 원래 공인 IP를 확인하고

특정 시점에 공인 IP를 확인하는 로직이 필요하다.

 

네이버에 '내 아이피 찾기' 이런 식으로 쳐도 나오지만,

RPA에서 가장 부담이 적은 방법은

Invoke Power shell에서 "(Invoke-WebRequest ifconfig.me/ip).Content.Trim()"를 실행하는 것이다.

기본 Text Command를 하드 코딩하는 경우의 설정

 

output은 Collection 객체이고 하나의 요소가 Return 된다. (= 공인 IP 주소)

 

 

오개념이 좀 있을 수 있지만 대략적인 느낌만 참고 바랍니다.

+ 기억을 다시 되돌려보니 트리거를 걸 때 specific robots를 체크하면 environment를 굳이 바꾸지 않아도 됐던 거 같은데

단톡 질문하신 분 참고해 보세요~

자주 헷갈려서 남겨둔다.

Try~Catch~Finally에서 Catch 에러가 나면 xaml의 Error Handler로 가게 된다.

따라서 Finally 구문은 실행되지 않는다.

Try에서 Terminate Workflow를 쓰면 바로 이렇게 되게 할 수 있다.

[Catch문도 안 탐]

일반적으로 다른 언어에서도 Catch문에서 에러가 나면 Finally는 실행되지 않고 에러로 처리된다.

다만 파이썬은 Finally가 실행된다. [각주:1]

  1. 이래서 Finally를 금지하는 경우도 있다. [본문으로]

+ Recent posts