프로젝트에 들어가면 자연어 처리를 너무 아무렇지 않게 요구하는 케이스들이 있다.

그러나 우리가 쓸 수 있는 리소스나 알고리즘, 모델은 보통 자연어 처리를 지원할 정도가 되지 않는다.

이때 간단한 대안으로 제시할 수 있는 것이 레벤슈타인 알고리즘이다.

 

레벤슈타인 알고리즘은 각 String을 2차원 배열로 분리해 글자 차이를 계산해주는 방식이고

패키지로 배포가 되어있다. [UipathTeam.String.Acitivities]

https://hoony-gunputer.tistory.com/entry/%EB%A0%88%EB%B2%A4%EC%8A%88%ED%83%80%EC%9D%B8-%EA%B1%B0%EB%A6%AC%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%B4%EC%84%9C-%EB%91%90-%EB%AC%B8%EC%9E%A5-%EB%B9%84%EA%B5%90%ED%95%98%EA%B8%B0

 

레벤슈타인 거리를 이용해서 두 문장 비교하기

레벤슈타인 거리를 이용해서 두 문장 비교하기 레벤슈타인 거리는 독일의 레벤슈타인이라는 사람이 고안한 알고리즘이다. 레벤슈타인 거리란 두개의 문장을 2차원 배열로 나타내어서 각 문장

hoony-gunputer.tistory.com

 

보통 해당 사업이 조회하려는 사업이 맞나 같은 것들을 판단해서 공고를 보내주거나 하는 형태로 쓰이고

일치율은 테스트를 통해 조정을 하여 제시하길 바란다. (일반적으로는 40% 내외이나 사안의 유의성에 따라 편차는 클 수 있음.)

기존 크롬에서는 특정 폴더에 캐시 관련해 모두 저장되었기 때문에 아래의 shell script가 먹혔다.

현재 크롬은 이곳저곳 캐시를 흩뿌려 놓고 있어서 2가지 방법이 주로 쓰인다.

1) 캐시를 저장하는 폴더를 지정해서 실행

2) 브라우저를 띄워서 캐시 삭제 창 띄우고 삭제 클릭

1의 경우 browser를 파이썬 같은 걸로 띄울 때 파라미터를 주는 방식이다. 아예 캐시가 저장될 파라미터를 실행할 때 주고 그 폴더를 삭제하는 방식으로 캐시를 삭제한다. 다만 uipath에서는 이렇게 하려면 open browser 대신 start process로 실행 후 attach하는 방식이 되기 때문에 범용적으로 쓰기 어렵다.

2의 경우 브라우저를 open browser로 아무 주소로나 띄운 후, send hot key로 ctrl + shift + del 을 눌러 삭제 버튼을 누르고 대기해주는 방식이다. front로 진행하기 때문에 적절한 retry scope 및 확인 체크를 해주는 것을 추천한다.

 

캐시때문에 간간히 로그인 세션 등이 꼬일 때가 있기 때문에 프레임워크에 포함시키면 좋은 스크립트.

Cache.bat으로 만들어서 실행시키는 게 가장 무난해 보임

Invoke Power Shell 을 쓸 때, IsScript 체크 / TypeArgument 는 String으로 설정되어 있는지 체크.

+ 2022.05.13 : 크롬에 적용해보니 세션이 안 없어지길래 살펴보니 Network라는 폴더로 쿠키의 위치가 바뀌었음

=> Network 폴더 추가함

+ 기본적으로 크롬의 새로운 프로필(Default가 아닌 프로필)의 경우엔 그 경로도 포함해줘야 함

 

/******************************************* Powershell script *****************************

 

"-------------------"
Write-Host -ForegroundColor Green "SECTION 1: Getting the list of users"
"-------------------"
# Write Information to the screen
Write-Host -ForegroundColor yellow "Exporting the list of users to c:\users\%username%\users.csv"
# List the users in c:\users and export to the local profile for calling later
dir C:\Users | select Name | Export-Csv -Path C:\users\$env:USERNAME\users.csv -NoTypeInformation
$list=Test-Path C:\users\$env:USERNAME\users.csv
""
#########################
"-------------------"
Write-Host -ForegroundColor Green "SECTION 2: Beginning Script..."
"-------------------"
if ($list) {
    "-------------------"
    #Clear Mozilla Firefox Cache
    Write-Host -ForegroundColor Green "SECTION 3: Clearing Mozilla Firefox Caches"
    "-------------------"
    Write-Host -ForegroundColor yellow "Clearing Mozilla caches"
    Write-Host -ForegroundColor cyan
    Import-CSV -Path C:\users\$env:USERNAME\users.csv -Header Name | foreach {
            Remove-Item -path C:\Users\$($_.Name)\AppData\Local\Mozilla\Firefox\Profiles\*.default\cache\* -Recurse -Force -EA SilentlyContinue -Verbose
            Remove-Item -path C:\Users\$($_.Name)\AppData\Local\Mozilla\Firefox\Profiles\*.default\cache\*.* -Recurse -Force -EA SilentlyContinue -Verbose
     Remove-Item -path C:\Users\$($_.Name)\AppData\Local\Mozilla\Firefox\Profiles\*.default\cache2\entries\*.* -Recurse -Force -EA SilentlyContinue -Verbose
            Remove-Item -path C:\Users\$($_.Name)\AppData\Local\Mozilla\Firefox\Profiles\*.default\thumbnails\* -Recurse -Force -EA SilentlyContinue -Verbose
            Remove-Item -path C:\Users\$($_.Name)\AppData\Local\Mozilla\Firefox\Profiles\*.default\cookies.sqlite -Recurse -Force -EA SilentlyContinue -Verbose
            Remove-Item -path C:\Users\$($_.Name)\AppData\Local\Mozilla\Firefox\Profiles\*.default\webappsstore.sqlite -Recurse -Force -EA SilentlyContinue -Verbose
            Remove-Item -path C:\Users\$($_.Name)\AppData\Local\Mozilla\Firefox\Profiles\*.default\chromeappsstore.sqlite -Recurse -Force -EA SilentlyContinue -Verbose
            }
    Write-Host -ForegroundColor yellow "Clearing Mozilla caches"
    Write-Host -ForegroundColor yellow "Done..."
    ""
    "-------------------"
    # Clear Google Chrome 
    Write-Host -ForegroundColor Green "SECTION 4: Clearing Google Chrome Caches"
    "-------------------"
    Write-Host -ForegroundColor yellow "Clearing Google caches"
    Write-Host -ForegroundColor cyan
    Import-CSV -Path C:\users\$env:USERNAME\users.csv -Header Name | foreach {
            Remove-Item -path "C:\Users\$($_.Name)\AppData\Local\Google\Chrome\User Data\Default\Cache\*" -Recurse -Force -EA SilentlyContinue -Verbose
Remove-Item -path "C:\Users\$($_.Name)\AppData\Local\Google\Chrome\User Data\Default\Cache2\entries\*" -Recurse -Force -EA SilentlyContinue -Verbose
            Remove-Item -path "C:\Users\$($_.Name)\AppData\Local\Google\Chrome\User Data\Default\Cookies" -Recurse -Force -EA SilentlyContinue -Verbose
            Remove-Item -path "C:\Users\$($_.Name)\AppData\Local\Google\Chrome\User Data\Default\Media Cache" -Recurse -Force -EA SilentlyContinue -Verbose
            Remove-Item -path "C:\Users\$($_.Name)\AppData\Local\Google\Chrome\User Data\Default\Cookies-Journal" -Recurse -Force -EA SilentlyContinue -Verbose
           Remove-Item -path "C:\Users\$($_.Name)\AppData\Local\Google\Chrome\User Data\Default\Sessions\*" -Recurse -Force -EA SilentlyContinue -Verbose
           Remove-Item -path "C:\Users\$($_.Name)\AppData\Local\Google\Chrome\User Data\Default\Session Storage\*" -Recurse -Force -EA SilentlyContinue -Verbose
           Remove-Item -path "C:\Users\$($_.Name)\AppData\Local\Google\Chrome\User Data\Default\Network\*" -Recurse -Force -EA SilentlyContinue -Verbose
            # Comment out the following line to remove the Chrome Write Font Cache too.
            # Remove-Item -path "C:\Users\$($_.Name)\AppData\Local\Google\Chrome\User Data\Default\ChromeDWriteFontCache" -Recurse -Force -EA SilentlyContinue -Verbose
            }

    Write-Host -ForegroundColor yellow "Done..."
    ""
    "-------------------"
    # Clear Internet Explorer
    Write-Host -ForegroundColor Green "SECTION 5: Clearing Internet Explorer Caches"
     "-------------------"
    Write-Host -ForegroundColor yellow "Clearing Google caches"
    Write-Host -ForegroundColor cyan
    Import-CSV -Path C:\users\$env:USERNAME\users.csv | foreach {
            Remove-Item -path "C:\Users\$($_.Name)\AppData\Local\Microsoft\Windows\Temporary Internet Files\*" -Recurse -Force -EA SilentlyContinue -Verbose
    Remove-Item -path "C:\Users\$($_.Name)\AppData\Local\Microsoft\Windows\WER\*" -Recurse -Force -EA SilentlyContinue -Verbose
    Remove-Item -path "C:\Users\$($_.Name)\AppData\Local\Temp\*" -Recurse -Force -EA SilentlyContinue -Verbose
    Remove-Item -path "C:\Windows\Temp\*" -Recurse -Force -EA SilentlyContinue -Verbose
    Remove-Item -path "C:\`$recycle.bin\" -Recurse -Force -EA SilentlyContinue -Verbose
            }

    Write-Host -ForegroundColor yellow "Done..."
    ""
    Write-Host -ForegroundColor Green "All Tasks Done!"
    } else {
Write-Host -ForegroundColor Yellow "Session Cancelled"
}

20.4에서 Uipath 오케스트레이터의 인증서 교체 시

인증서 Config 매핑이 자동으로 되지 않아 수동으로 매핑하고

권한을 부여해야 한다고 함.

 

 

+ 특정 버전 이상에서는 자체 발급 인증서로 인증되지 않아 IT팀에 따로 요청하여 인증서를 받기도 했음

보통 이 경우는 jsp 등으로 로컬의 서비스 프로그램을 실행시키고자 했을 때 발생한다.

이때 IE로 하면 실행이 되는데 크롬에서 하면 실행이 안 되면서 CORS Policy가 뜬다면 다음과 같은 옵션을 Disable로 변경해주면 된다.

chrome://flags/#block-insecure-private-network-requests

 

크롬에서는 기본적으로 CORS 정책을 지키지 않았을 때, 보안이 되지 않은 Context로 인식하고 막게끔 설정되어 있다.

IE는 그것이 약하기 때문에(그래서 일반 유저 입장에선 크롬이 훨씬 보안이 좋다) 그런 검사없이 실행시키므로 사내 레거시 프로그램을 실행하는 데 더 유리하다.

 

내 경우는 고객사에서 가급적 크롬으로 진행하기를 원해서 크롬 기준으로 개발을 했으나

그룹웨어에서 이 프로그램을 트리거링 하면서 CORS 정책을 풀어주는 코드를 삭제했기 때문에

RPA 소스 수정없이 크롬에서 문제를 해결하는 것을 찾아보다 발견했다.

 

보안이 약해지는 것이기 때문에 확인하고 풀길 바란다.

아직까진 라이선스가 비싸서 보통 대형 사이트가 아니고선 쓸 일이 없지만,

쓰고 싶은 경우는 많은, 없으면 거의 이미지 인식으로 개발을 이어나가야만 하는 Connector의 사용법을 정리한다.

 

 

1. Attach Window로 창을 잡고 정의해야 함

- 포괄 Recorder는 아니기 때문에 Xplatform인 창을 잡고 Window 객체를 가져와 셀렉터와 함께 할당해 주어야 한다.

- 이런 특성 때문에 팝업 형태가 뜨는 경우 Attach를 풀고 다시 창을 Assign 해주어야 한다.

- 물론 다시 팝업에서 벗어나 원래 창을 컨트롤 하려는 경우 새롭게 Assign 해야 한다. (Single Session인 것으로 보임)

 

2. Get 종류는 Focusing을 포함

- Uipath의 UiElement 선택기처럼 Delay 후 선택 같은 게 없다.

- 드롭다운 같은 경우 Delay가 없기 때문에, 따로 선택할 수가 없어 클릭이 불가능하다.

- 그래도 Get List Item Position 같은 것을 쓰면 Focusing하여 선택하는 것이 가능하다.

- 다만 Click으로 Select되는 게 아니기 때문에 그걸 트리거로 다른 Dropdown이 새로 로딩되는 형태라면 변수가 생긴다.

- 그 경우엔 Focusing하고 화살표를 아래로 내리면서 Text나 Value가 원하는 값인지 체크하면서 진행하는 것이 좋다.

- 라디오 버튼의 경우에도 Get으로 선택할 수 있다.

- 다만 *같은 건 쓸 수 없다. 정확한 값을 입력해야만 한다.

 

3. Get Text는 Value와 Text 두 종류로 가져올 수 있음

 

4. Assign 바로 다음 오는 Connector Activity는 뻑나는 케이스가 꽤 있음. Delay로 해결되진 않고 Retry를 해야 함. 혹은 Focus Out 해야  잡히는 케이스도 있으므로 Assign뒤에 Alt+tab을 넣어주면 잘 잡힘(추정하기로는 Selector를 인식할 때 ::~~~ 형태로 잡히게 되면 인식이 안 되는데 그것을 Focus Out하여 Init하는 게 아닌가 하는 중. ::~~~ 형태로 잡히는 이유에 대해서는 ToBeSoft에서도 잘 모르겠다는 답변)

 

5. Grid Hard Click이 필요한 경우

Grid의 Cell에는 포커싱으로는 트리거가 안 되는 케이스들이 많다.

그렇게 Hard Click이 필요한 경우는 Get Cell Position으로 좌표를 가져온 후 Selector 없는 Click의 Position을 잡아주어야 한다. (이때 가져온 좌표값은 pPosition 변수에 있다고 치자)

Top-Left로 설정 후 X좌표는 Cint(pPositon.Left)+Cint(pPosition.Width/2),

Y좌표는 Cint(pPosition.Top)+Cint(pPosition.Height/2)로 설정하면 된다.

다만 최신판 기준으로 이는 Maximize된 창 기준이기 때문에 꼭 작업하기 전에 maximize하길 추천한다.

[Maximize는 Window에 대해 Assign한 다음 Maximize를 쓰면 됨]

 

각 시스템별로 Data Export를 하는 것을 받아보면 여러가지 형태가 있다.

xls, xlsx, csv, txt 등등 각 서버마다 DB최적화를 위해서든, 사용자 편의를 위해서든 데이터를 주는 방식이 다르다.

혹은 OCR로 데이터를 읽었더니 Structured Text가 생기고 이를 의미단위로 나누어 처리해야 되는 케이스들이 생긴다.

 

RPA로 이런 데이터를 다루기 위해서, 특히 DataTable에 넣기 위해서는 다음과 같은 방법이 있다.

 

1. Generate Data Table

 - OCR의 구조화된 텍스트를 읽기 위한 방식이지만 Amazon같이 txt로 뱉어주는 곳에서 유용하게 쓸 수 있다.

 - 규칙적으로 나누다보니 변칙적인 데이터가 있는 경우(구분자나 문법에 관련된 문자열이 데이터 자체에 포함된 경우) 문제가 생길 수 있다.

 - 일반적으로 chr(34)를 Replace하고 Input에 넣어야 잘 작동한다.

 - 특이한 데이터의 경우 Environment.NewLine(chr(10)+chr(13))이 아닌 Chr(10)으로 row가 나뉘거나, 이상한 Tab으로 컬럼이 나뉘기도 한다.[이럴 땐 그 탭을 복사해서 컬럼 구분자로 넣어줘야 함]

 - 일률적이지 않을 수 있으므로 잘 구조화된 텍스트가 아니라면 다른 방법을 먼저 시도하길 권한다. [웬만해선 CSV 체크를 하면 잘 되긴 한다.]

2. Ctrl+a 후 엑셀에 붙이기

 - 가장 원시적인 방법일 수 있으나 갓셀은 굉장히 이를 잘 인식해준다.

 - 특이한 데이터의 경우 붙일 때 Ctrl+Alt+v 로 붙이고 유니코드 텍스트 등을 선택해야 잘 인식된다.

 - 이 작업을 여러번 반복해야 하는 경우, 간헐적으로 키가 씹혀서 붙이는 Starting Cell에 v만 입력되기도 하므로 주의

 

 

이런 케이스가 아주 많이 일어나진 않는다.

Data Scraping 등이 안 되는지 체크해보고 위를 시도해 보도록 하자.

RPA를 개발하다 보면 생각보다 환경 이슈 중 윈도우 권한 관련 이슈가 많이 발생한다.

대부분의 실행, UI인식 문제는 권한 문제부터 훑어볼 정도로 흔한 문제이다.

 

다만 관리자로 실행하는 경우 Uipath를 실행하는 데 있어 애로사항이 많다.

특히 구성상 uipath를 관리자 권한으로 실행시켜야 하는데 환경에 따라 이렇게 설정하면

Machine 설정 인식이 안 되는 케이스가 있다.

따라서 최대한 실행 앱의 권한을 기본 User로 맞춰주거나 기본 User의 권한을 올려서 부여해줘야 한다.

관리자 권한으로 인한 증상은 보통 다음과 같다.

1. Ui Element 인식 불가[Xplatform, OZ Viewer 같은 내부 그리드 구성앱이 아닌데 세부 인식이 되지 않고 통으로 잡힘]

2. 관리자 권한 실행 메세지가 발생[Uipath에서 알려주는 게 일반적이고 간혹 앱 자체에서 띄우기도 함]

3. 특정환경에서만 앱의 특정기능 혹은 시작 시 알 수 없는 에러 발생[이런 경우 보통 현업 PC에서는 잘된다고 함]

4. 이벤트 뷰어에서 관련된 에러가 떠있음[응용프로그램 혹은 보안쪽에 로그가 있음]

 

i) 필수는 아니지만 기본적으로 관리자 권한으로 실행되도록 체크된 경우

앱의 실행파일의 속성에서 관리자 권한으로 실행될 수 있는 옵션들을 찾아 Uncheck 시켜주자

그럼에도 안 된다면,

C:\Windows\System32\cmd.exe /min /c "set __COMPAT_LAYER=RUNASINVOKER && start "" "실행할 파일 경로"

Start process 액티비티로 cmd.exe까지는 프로그램 경로, 그 뒤는 Parameter로 주면 됨.

[헥사 에디터를 이용하는 방법도 있으니 필요하다면 검색 "실행파일로부터 관리자 권한을 제거하는 방법"]

ii) 파일 및 폴더 권한이 필요한 경우

추정되는 폴더루트에 User의 권한이 적정수준으로 부여돼 있는지 체크

우클릭 속성 - 보안탭에서 User 선택 후 확인

iii) 레지스트리 권한이 필요한 경우

드물게 이런 케이스들이 있다. 앱에서 로컬 레지스트리에 해당 프로그램의 권한 유저값을 변경하는 등의 행위로 보안 처리를 해놨는데 윈도우 업데이트 등으로 일반 유저의 레지스트리 편집 권한이 없어진 경우이다.

이 경우 레지스트리 편집기의 폴더를 우클릭하면 마찬 가지로 권한 부여가 가능하다.

 

 

+ UAC(사용자 계정 컨트롤) 관련 팁

- 로컬 보안 정책을 실행

- 로컬 정책 - 보안 옵션 - 사용자 계정 컨트롤 : 관리 승인 모드에서 모든 관리자 실행 => 사용 안 함

[단, 보안 관련해서 담당자와 상의할 것을 추천함. 출처가 불분명한 앱들이 실행할 수 있도록 열어주는 것이기 때문]

 

일반적으로 소스품질에서 Exception과 로깅이 차지하는 비중은 대단히 높다.

특히 비지니스 측면에서 고객만족도와 매우 연관성이 크다.

따라서 exception의 구분과 컨트롤은 프로 개발자라면 비지니스 로직만큼 공을 들여야 한다.

 

소스가 컴파일되고 순서대로 실행되는 과정에서 예외로 처리되는 것은 크게 2가지로 나뉘게 된다.

1) 인식불가 및 예상하지 못한 오류

 - System Exception

2) 인식 및 예상가능한 오류

 - Application Exception

 - Business Rule Exception

 

개념적으로 System Exception은 폭넓은 의미 / 좁은 의미를 가진다.

폭넓은 의미로는 모든 소스에서의 Exception의 의미이고 좁은 의미에서는 예상하지 못한 모든 Exception이다.

 

여기서 하나 짚고 넘어가야 할 부분은 '인식 및 예상 가능하다'는 말의 의미이다.

RPA에서 인식 및 예상 가능하다는 의미는 고의로 예외로 처리한다는 뜻이다.

인식 및 예상가능한 에러는 Throw하지 않으면 에러가 나지 않고 진행될 수도 있으나

데이터 정합성에 문제가 생기거나 이후 프로세스에서 문제가 발생하는 에러이다.

 

Application Exception은 특정 시스템이 점검 등의 이유로 접속되지 않는 것을 어떤 특정값으로 확인할 수 있는 경우, 세션이 나가면 작업이 불가능해 고의로 에러를 내고 새롭게 시도를 해야 되는 경우 등에 쓸 수 있다.

Application Exception은 일반적으로는 적극적으로 쓰이지는 않는다. 대부분의 경우 예상하기 어렵기도 하거니와 그런 에러가 나면 Retry 할 수 있게끔만 만들어 놓으면 되기 때문이다. 다만 프레임워크 구조상 System Exception중 Exception Message를 구체적으로 가져갈 필요가 있는 경우는 자주 쓰기도 한다.

[Exception의 Try Catch 처리가 시퀀스 단위가 아니라 Business Logic 단위로 되어있는 경우, 안쪽에서 Exception이 발생하면 해당 Xaml의 인수값의 전달이 실패하는 특성때문에 그렇다. 개인적으로는 이런 프레임워크는 로깅 관리가 어렵다는 점 때문에 선호하지 않지만, 그런 경우 일부러 안쪽에서 Catch에서 메세지를 담아 Throw 하는 경우가 있다.]

 

Business Rule Exception은 프로세스상 정합성이 맞지 않는 경우의 예외이다.

Business Exception은 소스상 오류는 아니나 데이터 정합성이 맞지 않는다든가, 프로세스 정합성이 맞지 않아 미리 인식하고 종료해야 하는 경우 많이 쓰인다.

보통 재시도를 하지 않고 끝내기 때문에, 전체 재시도 하는 로직이라면 필히 Catch의 BusinessRule Exception란에 Break를 넣어주자.

 

이 개념을 알고 Sequence단위 FrameWork를 보면 훨씬 이해가 잘 된다.

+ Recent posts