UiPath 개발 중 직접 겪었던 문제와 해결 방식을 정리하는 문서입니다.
단순 문법 정리가 아니라, 문제 상황 → 내가 적용한 해결 방식 → 주의한 점 → 정리한 기준 순서로 계속 업데이트합니다.


문서 기준

  • UiPath Studio 기준
  • VB.NET 표현식 기준
  • Windows 환경의 UI 자동화 기준
  • Excel, Browser, Mail 자동화 포함
  • 프로젝트 환경, 패키지 버전, Studio 버전에 따라 액티비티 이름이나 옵션 위치는 다를 수 있음

공개 글 작성 기준

이 글은 공개 블로그용이므로 실제 운영 정보는 일반화해서 작성한다.

- 실제 업무 시스템명 → "업무 시스템", "대상 시스템"으로 표현
- 실제 URL, IP, 도메인 → example.com 또는 <도메인> 형태로 표현
- 계정명, 서버명, PC명 → <계정명>, <서버명>, <Robot PC> 형태로 표현
- 내부 패키지 경로 → <로컬 패키지 경로>, <내부 패키지 저장소>로 표현
- 방화벽 허용 정보 → 출발지, 목적지, 프로토콜, 포트, 용도 기준으로 일반화
- RDP 세션 명령어 → 실제 세션 ID, 계정명 없이 템플릿 형태로 작성

보안 관련 내용을 무조건 제외하기보다는, 실제 환경을 특정할 수 있는 값만 제거하고 구조와 판단 기준은 남긴다.


1. 문자열을 콤마 기준으로 나누고 Trim까지 처리하기

문제 상황

콤마로 구분된 문자열을 배열로 나누고 싶었다.
단순히 Split만 하면 값 앞뒤에 공백이 남는 문제가 있었다.

예시 문자열:

" A, B , C "

원하는 결과:

{"A", "B", "C"}

내가 적용한 방식

strText.Split(","c).Select(Function(x) x.Trim()).ToArray()

List 타입으로 받아야 할 때는 마지막만 ToList()로 바꿨다.

strText.Split(","c).Select(Function(x) x.Trim()).ToList()

정리한 기준

문자열을 나누기만 한다 → Split
나눈 뒤 각 항목을 가공한다 → Split + Select
배열로 사용한다 → ToArray()
List로 사용한다 → ToList()

Select는 반드시 필요한 것은 아니다.
하지만 나눈 값마다 Trim, Replace, ToUpper 같은 후처리가 필요하면 Select를 쓰는 게 맞다.


2. 줄바꿈 기준으로 문자열 배열 만들기

문제 상황

여러 줄 텍스트를 줄 단위로 나눠 배열로 만들 필요가 있었다.

예시:

A
B
C

원하는 결과:

{"A", "B", "C"}

내가 적용한 방식

Windows 줄바꿈만 고려하면 아래 방식으로 충분하다.

strText.Split({Environment.NewLine}, StringSplitOptions.RemoveEmptyEntries)

다만 외부에서 가져온 텍스트는 줄바꿈 형식이 섞일 수 있어서, 실무에서는 아래 방식이 더 안전했다.

strText.Split({vbCrLf, vbLf}, StringSplitOptions.RemoveEmptyEntries)

각 줄의 앞뒤 공백까지 제거해야 하면 다음처럼 처리했다.

strText.Split({vbCrLf, vbLf}, StringSplitOptions.RemoveEmptyEntries).
    Select(Function(x) x.Trim()).
    ToArray()

정리한 기준

줄바꿈 형식이 확실하다 → Environment.NewLine
외부 텍스트라 줄바꿈이 섞일 수 있다 → vbCrLf, vbLf 모두 처리
빈 줄 제거가 필요하다 → RemoveEmptyEntries
각 줄 공백 제거가 필요하다 → Select + Trim

3. 정규식으로 인증번호 6자리 추출하기

문제 상황

문자열 안에서 "인증번호:" 뒤에 오는 6자리 숫자만 추출해야 했다.

예시:

인증번호: 123456

원하는 결과:

123456

내가 적용한 방식

System.Text.RegularExpressions.Regex.Match(strText, "인증번호:\s*(\d{6})").Groups(1).Value

더 안전하게 처리한 방식

실제 자동화에서는 매칭 실패 가능성도 있기 때문에 Success를 확인하는 방식이 더 안전하다.

Dim match = System.Text.RegularExpressions.Regex.Match(strText, "인증번호:\s*(\d{6})")

If match.Success Then
    strCode = match.Groups(1).Value
Else
    Throw New Exception("인증번호 6자리를 찾을 수 없습니다.")
End If

정리한 기준

패턴이 반드시 있다고 확신한다 → Match().Groups(1).Value
패턴이 없을 수도 있다 → Match.Success 확인 후 처리
실패 시 업무 오류로 봐야 한다 → Throw

4. 숫자 + 공백으로 시작하는 문자열 확인하기

문제 상황

텍스트가 아래처럼 숫자와 공백으로 시작하는지 확인할 필요가 있었다.

1 항목명

내가 적용한 방식

System.Text.RegularExpressions.Regex.IsMatch(strText, "^\d+\s")

정리

^     문자열 시작
\d+   숫자 1개 이상
\s    공백 1개

이 패턴은 목록형 텍스트를 구분할 때 유용했다.


5. Array와 List 선택 기준

문제 상황

UiPath에서 Array를 써야 할지, List를 써야 할지 헷갈렸다.

내가 정리한 기준

개수가 고정되어 있다 → Array
실행 중 계속 추가하거나 제거한다 → List

String Array 기본값

New String() {}

String List 기본값

New List(Of String)()

List에 값 추가

listData.Add("값")

List 개수 확인

listData.Count

List 마지막 값 가져오기

listData.Last()

단, 리스트가 비어 있으면 Last()에서 예외가 발생한다.
그래서 실제로는 아래처럼 방어 조건을 넣었다.

If(listData.Count > 0, listData.Last(), "")

정리한 기준

처음부터 값 목록이 정해져 있다 → Array
반복 중 값을 계속 쌓는다 → List
마지막 값을 가져온다 → Last()
비어 있을 수 있다 → Count 체크 후 Last()

6. List 중복 제거하기

문제 상황

List(Of String)에서 중복 값을 제거해야 했다.
처음에는 Python의 set 같은 타입을 찾았지만, VB.NET에서는 Distinct()를 쓰는 방식이 일반적이었다.

내가 적용한 방식

listData.Distinct().ToList()

대소문자를 무시해야 할 때는 아래처럼 처리했다.

listData.Distinct(StringComparer.OrdinalIgnoreCase).ToList()

주의한 점

Distinct()는 중복 제거용으로 사용하고, 결과 순서가 중요하면 이후에 명시적으로 정렬하는 편이 안전하다.

listData.Distinct().OrderBy(Function(x) x).ToList()

정리한 기준

중복 제거만 필요하다 → Distinct()
결과를 List로 계속 사용한다 → Distinct().ToList()
대소문자를 같은 값으로 본다 → StringComparer.OrdinalIgnoreCase
결과 순서도 중요하다 → OrderBy 추가

7. List끼리 비교하기

문제 상황

두 개의 List가 같은 값을 가지고 있는지 비교해야 했다.

순서까지 같아야 하는 경우

listA.SequenceEqual(listB)

예시:

{"A", "B", "C"}
{"A", "B", "C"}

결과:

True

하지만 아래처럼 순서가 다르면 False다.

{"A", "B", "C"}
{"C", "B", "A"}

순서는 상관없고 구성과 개수만 같으면 되는 경우

listA.OrderBy(Function(x) x).SequenceEqual(listB.OrderBy(Function(x) x))

이 방식은 중복 개수까지 비교한다.

예시:

{"A", "A", "B"}
{"A", "B", "B"}

결과:

False

중복을 무시하고 값 종류만 비교하는 경우

listA.Distinct().OrderBy(Function(x) x).
    SequenceEqual(listB.Distinct().OrderBy(Function(x) x))

정리한 기준

순서까지 같아야 한다 → SequenceEqual
순서는 무시하지만 중복 개수는 비교한다 → OrderBy 후 SequenceEqual
중복 자체를 무시한다 → Distinct 후 OrderBy 후 SequenceEqual

8. Throw 밑에 Return을 넣을 필요가 있는가

문제 상황

하위 Workflow에서 Throw로 예외를 발생시키고, 상위 Workflow에서 Try-Catch로 잡는 구조였다.
이때 Throw 아래에 Return을 넣어야 하는지 헷갈렸다.

내가 정리한 결론

대부분 필요 없다.

Throw
Return

Throw가 실행되면 예외가 발생하고 현재 흐름은 중단된다.
따라서 바로 아래의 Return은 실행되지 않는다.

정리한 기준

정상적으로 현재 Workflow를 끝낸다 → Return
실패를 상위 Workflow에 알린다 → Throw
반복문만 빠져나간다 → Break

예외 상황인데 Return으로 조용히 종료하면 상위 Workflow에서는 정상 종료처럼 보일 수 있다.
운영 자동화에서는 실패를 숨기는 구조가 더 위험하다.


9. For Each 안에서 Break와 Return 구분하기

문제 상황

For Each 반복 도중 특정 조건에서 멈춰야 했다.
이때 Break를 써야 할지, Return을 써야 할지 구분이 필요했다.

내가 정리한 기준

Break는 현재 반복문만 빠져나간다.

For Each
    조건 만족
    Break
Next

아래 로직 계속 실행

Return은 현재 Workflow 자체를 종료한다.

For Each
    조건 만족
    Return
Next

아래 로직 실행 안 됨

실무 기준

반복만 멈추고 다음 로직은 계속한다 → Break
현재 Workflow를 정상 종료한다 → Return
실패 상황을 상위에 알린다 → Throw

10. 중첩 If를 Guard Clause 방식으로 정리하기

문제 상황

조건이 여러 개 있고, 중간에 하나라도 실패하면 예외로 중단해야 했다.
처음에는 If 안에 If가 계속 들어가는 구조가 되었다.

If 조건1 Then
    If 조건2 Then
        If 조건3 Then
            처리
        End If
    End If
End If

내가 적용한 방식

실패 조건을 먼저 검사하고, 실패하면 바로 Throw했다.

If Not 조건1 Then
    Throw New Exception("조건1 실패")
End If

If Not 조건2 Then
    Throw New Exception("조건2 실패")
End If

If Not 조건3 Then
    Throw New Exception("조건3 실패")
End If

' 정상 처리

효과

실패 조건이 위에 모인다
정상 로직이 깊게 들어가지 않는다
예외 메시지를 명확히 남기기 쉽다
유지보수가 쉬워진다

RPA에서 적용하기 좋은 상황

로그인 여부 확인
필수 데이터 존재 여부 확인
조회 결과 존재 여부 확인
화면 상태 확인
파일 존재 여부 확인
권한 여부 확인

11. DataTable은 In으로 넘겨도 내부 수정이 외부에 반영된다

문제 상황

String, Integer 같은 값은 하위 Workflow에 In으로 넘기고 내부에서 바꿔도 외부 값이 바뀌지 않았다.
그런데 DataTableIn으로 넘겼는데도 내부에서 수정한 내용이 외부에 반영됐다.

원인

DataTable은 참조 타입이다.
하위 Workflow로 객체의 참조가 전달되기 때문에, 같은 객체의 내부 내용을 수정하면 외부에서도 변경된 내용이 보인다.

예시:

dtData.Rows.Add(...)

또는:

dtData.Rows(0)("Status") = "완료"

주의한 점

아래처럼 새 객체를 다시 할당하는 것은 다르다.

dtData = New DataTable()

이 경우 외부 변수가 자동으로 새 DataTable을 바라보지는 않는다.
외부에도 새 객체를 전달해야 한다면 Out 또는 In/Out 인수를 써야 한다.

정리한 기준

DataTable 내부 행/컬럼/값을 수정한다 → In으로도 외부 반영 가능
DataTable 변수에 새 객체를 할당한다 → Out 또는 In/Out 필요

12. String은 참조 타입인데 왜 값처럼 보이는가

문제 상황

VB.NET에서 String은 참조 타입이라고 알고 있었다.
그런데 UiPath Workflow에서 StringIn으로 넘기고 내부에서 값을 바꿔도 외부 값은 바뀌지 않았다.

원인

문자열은 불변 객체다.
즉, 기존 문자열 자체를 수정하는 것이 아니라 변경 결과로 새 문자열을 만든다.

예시:

strText = strText.Replace("A", "B")

이 코드는 기존 문자열을 직접 수정하는 것이 아니다.
Replace 결과로 새 문자열을 만들고, 그 새 문자열을 strText 변수에 다시 할당하는 구조다.

정리한 기준

String 값을 하위 Workflow에서 바꾸고 외부에도 반영해야 한다 → Out 또는 In/Out
String을 읽기만 한다 → In
String은 참조 타입이지만 불변 객체라 값처럼 다루는 편이 안전하다

13. 클래식 UI 자동화와 모던 UI 자동화의 차이

문제 상황

클래식 액티비티에서는 Browser 변수를 사용했는데, 모던 UI 자동화에서는 같은 방식이 잘 맞지 않았다.

내가 정리한 차이

클래식 방식은 보통 아래 액티비티 중심으로 구성된다.

Open Browser
Attach Browser
Classic Click
Classic Type Into

이 구조에서는 Browser 타입 변수를 직접 다루는 방식이 자연스럽다.

반면 모던 방식은 아래 구조를 중심으로 사용한다.

Use Application/Browser
Check App State
Modern Click
Modern Type Into
Table Extraction

모던에서는 Browser 변수를 직접 넘겨가며 제어하기보다, Use Application/Browser Scope 안에서 대상 애플리케이션을 잡고 처리하는 방식이 더 자연스럽다.

정리한 기준

기존 Browser 변수 기반 구조다 → 클래식 중심으로 유지
Use Application/Browser, Check App State, Modern Table Extraction을 쓴다 → 모던 중심으로 구성
한 흐름에서 섞어야 한다 → Scope 경계와 셀렉터 기준을 명확히 분리

클래식과 모던을 섞는 것이 불가능한 것은 아니다.
다만 유지보수 난이도가 올라가므로, 한 업무 흐름 안에서는 가능하면 한 방식을 기준으로 잡는 편이 낫다.


14. URL에 sessionId 같은 동적 값이 있을 때 셀렉터 처리하기

문제 상황

URL에 매번 바뀌는 값이 들어가서 셀렉터가 불안정해졌다.

예시:

https://example.com/search?sessionId=ABC123&page=1

sessionId 값은 실행마다 바뀔 수 있으므로 셀렉터에 그대로 넣으면 다음 실행에서 깨질 가능성이 있다.

내가 적용한 방식

동적으로 바뀌는 부분은 와일드카드로 처리했다.

<html app='chrome.exe' url='https://example.com/search?sessionId=*&amp;page=1' />

page 값도 바뀌면 다음처럼 처리할 수 있다.

<html app='chrome.exe' url='https://example.com/search?sessionId=*&amp;page=*' />

주의한 점

셀렉터는 XML 형식이므로 URL의 &는 그대로 쓰지 않고 &amp;로 작성해야 한다.

잘못된 표현: &
올바른 표현: &amp;

정리한 기준

sessionId, token, timestamp처럼 매번 바뀐다 → 와일드카드 처리
업무적으로 의미 있는 값이다 → 필요한 경우만 유지
URL 전체가 불안정하다 → url 속성 의존도를 낮추고 다른 속성 검토

15. 특정 UI 엘리먼트 개수 확인하기

문제 상황

화면에 특정 엘리먼트가 몇 개 있는지 확인해야 했다.

내가 적용한 방식

Find Children 계열 액티비티로 조건에 맞는 자식 엘리먼트를 찾고, 결과 개수를 확인했다.

결과 변수가 List나 배열이면 다음처럼 확인할 수 있다.

uiElements.Count

결과가 IEnumerable(Of UiElement) 형태라면 아래처럼 쓰는 편이 안전하다.

uiElements.Count()

또는 List로 변환해서 확인한다.

uiElements.ToList().Count

주의한 점

부모 엘리먼트 범위를 잘 잡는 것이 핵심이었다.

부모 범위가 너무 넓다 → 불필요한 요소까지 잡힌다
부모 범위가 너무 좁다 → 원하는 요소가 누락된다

정리한 기준

목록, 테이블, 반복 UI 개수 확인 → Find Children
개수가 예상보다 많다 → 부모 범위가 너무 넓은지 확인
개수가 0이다 → 로딩, iframe, 셀렉터 조건 확인
화면 로딩이 느리다 → Element Exists 또는 Check App State 후 Count

16. “입력 내용이 화면 경계를 벗어납니다” 오류

문제 상황

UiPath 실행 중 아래 오류가 발생했다.

입력 내용이 화면 경계를 벗어나므로 UI 엘리먼트에 보낼 수 없습니다.

내가 확인한 원인

이 오류는 단순히 입력값이 잘못됐다는 의미가 아니었다.
대부분 화면 상태나 UI 렌더링 문제와 관련이 있었다.

가능성이 높았던 원인은 다음이다.

대상 엘리먼트가 화면 밖에 있음
창이 최소화되어 있음
브라우저 또는 프로그램이 비활성 상태임
해상도 또는 배율이 다름
셀렉터는 잡혔지만 실제 좌표가 비정상임
스크롤이 필요한 위치에 대상이 있음
원격 세션 상태가 UI 자동화에 적합하지 않음

내가 적용한 대응

1. 창을 Maximize 처리
2. 대상 창 Activate
3. 필요한 경우 Scroll Into View
4. Element Exists 또는 Check App State로 대상 확인
5. 입력 방식 변경 검토
6. 운영 PC의 해상도와 배율 확인
7. 원격 세션 종료 방식 확인

정리한 기준

개발 PC에서는 되는데 운영 PC에서 실패한다 → 해상도, 배율, 화면 상태 확인
가끔 실패한다 → 로딩 대기, Activate, Scroll 처리 추가
항상 실패한다 → 셀렉터 또는 대상 컨트롤 상태 확인
원격 접속 종료 후 실패한다 → 세션 유지 방식 확인

17. Excel COM 오류: RPC_E_DISCONNECTED

문제 상황

Excel 자동화 중 아래 오류가 발생했다.

호출된 개체가 해당 클라이언트로부터 연결이 끊겼습니다.
HRESULT: 0x80010108 (RPC_E_DISCONNECTED)

내가 본 원인

이 오류는 UiPath와 Excel 사이의 연결이 불안정해졌을 때 발생했다.
특히 Copy/Paste 작업이 많거나 Excel Scope 구조가 복잡할 때 더 자주 나타났다.

가능한 원인은 다음으로 정리했다.

Excel 프로세스 비정상 상태
파일 잠김
Excel 창 응답 없음
Copy/Paste 작업이 너무 빠르게 이어짐
Use Excel File 범위가 복잡함
클립보드 사용 중 충돌

내가 적용한 방향

가능하면 화면 기반 Copy/Paste를 줄이고 DataTable 기반 처리로 바꿨다.

Read Range
Write Range
Append Range
DataTable 조작
Workbook 기반 처리

정리한 기준

대량 데이터 복사/붙여넣기 중 오류 → DataTable 방식 검토
간헐적 오류 → Delay, Save/Close 순서, Scope 정리
항상 같은 위치에서 오류 → 파일 잠금, 시트 보호, 범위 문제 확인
운영 PC에서만 오류 → Office 버전, 권한, 실행 환경 확인

18. 패키지 의존성 오류

문제 상황

다른 PC에서 가져온 UiPath 프로젝트를 열었더니 패키지 의존성 오류가 발생했다.
패키지 복구를 눌러도 제한된 네트워크 환경에서는 복구가 되지 않았다.

내가 확인한 항목

project.json의 dependencies
Studio의 Manage Packages 설정
로컬 패키지 경로
기존 개발 PC의 패키지 캐시
사내 라이브러리 패키지 존재 여부
패키지 소스 우선순위

내가 적용한 방식

실제 내부 경로나 저장소 정보는 공개하지 않고, 해결 흐름만 정리하면 다음과 같다.

1. 기존 개발 PC에서 필요한 패키지 파일 확인
2. 대상 PC에서 참조 가능한 로컬 패키지 경로 구성
3. Studio 패키지 소스에 로컬 경로 추가
4. project.json의 dependencies와 실제 패키지 버전 확인
5. Restore 재시도

정리한 기준

인터넷이 가능한 개발 환경 → 공식 피드에서 Restore 가능
제한된 네트워크 환경 → 로컬 패키지 또는 내부 패키지 저장소 필요
프로젝트만 복사했다 → 패키지 누락 가능성 높음
사내 라이브러리를 쓴다 → 해당 라이브러리 패키지도 같이 이관 필요
패키지 버전이 다르다 → project.json 기준으로 맞춰야 함

19. 방화벽 제한 환경에서 UiPath 패키지 복구가 안 될 때

문제 상황

UiPath 프로젝트를 열었을 때 패키지 복구가 필요했지만, 네트워크 제한 때문에 패키지를 다운로드하지 못했다.
처음에는 단순히 “인터넷이 안 된다” 정도로 봤지만, 실제로는 Studio, Robot, Orchestrator, 패키지 피드 간 통신 경로를 구분해서 봐야 했다.

내가 정리한 확인 방식

방화벽 요청은 단순히 “열어주세요”가 아니라 아래 항목으로 정리하는 게 좋았다.

구분작성 예시
출발지<개발 PC>, <Robot PC>
목적지<Orchestrator URL>, <패키지 피드 URL>, <Automation Cloud 관련 URL>
프로토콜HTTPS
포트443
용도Studio 로그인, 패키지 복구, Robot-Orchestrator 통신, 라이선스 확인 등
대상 프로그램UiPath Studio, UiPath Robot
비고프록시, 인증서 검사, 내부망 정책 확인 필요

내가 적용한 표현 방식

공개 글에서는 실제 도메인이나 내부 URL을 쓰지 않고 아래처럼 일반화한다.

출발지: <개발 PC 또는 Robot PC>
목적지: <UiPath Orchestrator 또는 패키지 피드>
프로토콜: HTTPS
포트: TCP 443
용도: 패키지 복구, Robot 연결, Studio 로그인

방화벽 이슈를 의심한 기준

Studio에서 패키지 Restore가 실패한다
Manage Packages에서 피드 목록은 보이지만 다운로드가 실패한다
개발 PC에서는 되는데 운영 PC에서는 안 된다
Robot이 Orchestrator에 연결되지 않는다
로그인 또는 라이선스 확인 단계에서 실패한다

내가 정리한 대응 방향

1. 패키지 복구 실패인지, Orchestrator 연결 실패인지 구분
2. Studio PC와 Robot PC의 네트워크 정책이 같은지 확인
3. 공식 피드 사용인지 내부 패키지 저장소 사용인지 확인
4. 폐쇄망이면 로컬 패키지 또는 내부 패키지 저장소 방식 검토
5. 방화벽 요청 시 출발지, 목적지, 포트, 용도를 명확히 정리

정리한 기준

패키지 다운로드만 실패한다 → 패키지 피드 접근 확인
Robot 연결만 실패한다 → Orchestrator 접근 확인
Studio 로그인만 실패한다 → 인증/라이선스 관련 통신 확인
개발 PC만 정상이다 → 운영 PC의 방화벽, 프록시, 인증서 정책 확인
폐쇄망이다 → 외부 다운로드 전제 구조를 버리고 로컬 패키지 전략 필요

방화벽 관련 내용은 보안상 삭제할 것이 아니라, 실제 도메인과 내부 경로를 제거하고 통신 구조 중심으로 일반화해서 정리하는 것이 적절하다.


20. 짧은 주기 스케줄에서 중복 실행 방지하기

문제 상황

짧은 주기로 스케줄을 실행하려고 했는데, 이전 Job이 아직 실행 중일 때 다음 Job이 또 쌓이면 문제가 될 수 있었다.

내가 정리한 방향

Orchestrator Trigger 설정에서 중복 실행 관련 옵션을 먼저 확인했다.
추가로 프로세스 내부에서도 2차 방어를 두는 구조가 안전하다고 판단했다.

내부 방어 구조

Start
  - 실행 중 여부 확인
  - 실행 중이면 종료
  - 실행 중이 아니면 실행 상태 설정

Process
  - 실제 업무 처리

Finally
  - 실행 상태 해제

정리한 기준

짧은 주기로 Trigger 실행 → 중복 실행 방지 필수
한 번에 하나만 돌아야 하는 업무 → Trigger 설정 + 내부 실행 상태 체크
비정상 종료 가능성이 있다 → 실행 상태 해제 기준 필요

공개 글에서는 구체적인 Orchestrator Tenant명, Folder명, Robot명은 쓰지 않는 편이 안전하다.
대신 “중복 실행 방지 옵션”과 “프로세스 내부 실행 상태 체크”라는 구조를 설명하면 된다.


21. Queue와 단순 반복 처리의 차이

문제 상황

Queue가 단순히 List를 반복하는 것과 무엇이 다른지 헷갈렸다.

내가 정리한 차이

Queue는 단순 반복문이 아니다.
Orchestrator에서 처리 건을 상태로 관리하는 구조다.

대표적으로 아래와 같은 상태 흐름을 가진다.

New
In Progress
Successful
Failed
Retried
Abandoned
Deleted

상태 종류는 UiPath 버전과 설정에 따라 표현이 달라질 수 있으므로, 글에서는 “대표적으로”라고 표현하는 것이 안전하다.

Queue가 적합한 경우

처리 대상이 건 단위로 명확함
실패 건을 재처리해야 함
성공/실패 상태를 Orchestrator에서 보고해야 함
여러 Robot이 나눠 처리할 수 있음
트랜잭션 단위 로그가 중요함

Queue가 과할 수 있는 경우

웹사이트에서 실시간으로 조회함
조회 결과가 없으면 바로 종료함
Input 데이터가 사전에 쌓여 있지 않음
단순 상태 확인성 프로세스임
건별 재처리 필요성이 낮음

정리한 기준

건별 상태 관리가 필요하다 → Queue
재처리와 Retry가 중요하다 → Queue
단순 조회 후 있으면 처리, 없으면 종료 → While 반복 구조 검토
결과만 취합하면 된다 → Queue가 과할 수 있음

22. REFramework를 무조건 Queue 구조로 볼 필요는 없다

문제 상황

REFramework를 사용하려고 했지만, Input 데이터가 Queue에 미리 쌓여 있는 구조가 아니었다.
웹에서 실시간으로 조회한 뒤, 처리할 건이 있으면 진행하고 없으면 종료하는 업무였다.

내가 정리한 구조

기본 REFramework 구조는 다음과 같다.

Init
Get Transaction Data
Process Transaction
End Process

하지만 모든 업무가 Queue 기반에 맞는 것은 아니다.

실시간 조회형 업무는 아래 구조가 더 자연스러웠다.

Init
  - 브라우저 실행
  - 로그인
  - 설정 로딩

Process
  - 처리 대상 조회
  - 없으면 종료
  - 있으면 반복 처리

End
  - 로그아웃
  - 브라우저 종료
  - 결과 정리

처리할 건이 없는데 후속 시스템까지 접근하면 실패 지점만 늘어난다.
그래서 초반에 처리 대상 존재 여부를 먼저 판단하는 방식으로 정리했다.

정리한 기준

처리 건이 Queue에 쌓여 있다 → 기본 REFramework 구조 적합
처리 건을 웹에서 실시간 조회한다 → Process 안의 While 반복 검토
건이 없으면 바로 끝난다 → 초반 조회 후 종료
후속 시스템 접근이 조건부다 → 사전 조건 검증 후 접근

23. RDP 세션 종료 후 UI 자동화가 실패할 때

문제 상황

원격 환경에서 UiPath를 실행할 때, RDP 접속을 종료한 뒤 UI 자동화가 실패하는 경우가 있었다.
특히 화면 클릭, 입력, 엘리먼트 인식 같은 작업은 원격 세션 상태에 영향을 받았다.

내가 확인한 원인

UI 자동화는 실제 화면 상태에 의존하는 경우가 많다.
따라서 원격 세션을 그냥 닫거나 화면이 잠기면 아래 문제가 생길 수 있다.

화면 렌더링 중단
해상도 변경
창 비활성화
엘리먼트 좌표 계산 오류
입력 대상이 화면 밖으로 인식됨

내가 정리한 대응 방식

운영 환경에서는 가능하면 Unattended Robot 구성을 우선 검토한다.
불가피하게 원격 세션 기반으로 실행해야 한다면, RDP 세션 종료 방식도 운영 절차에 포함해야 한다.

일반적으로 확인할 항목은 다음과 같다.

1. Robot 실행 계정으로 정상 로그인되어 있는가
2. 실행 중 화면 잠금이 발생하지 않는가
3. 해상도와 배율이 고정되어 있는가
4. RDP 종료 후에도 UI 자동화가 가능한 상태로 세션이 유지되는가
5. 관리자 권한이 필요한 명령을 쓰고 있지는 않은가
6. 작업 스케줄러 실행 계정과 실제 로그인 계정이 일치하는가

세션 전환 명령어를 일반화해서 표현하면

실제 계정명이나 세션 ID를 공개하지 않고, 개념만 정리하면 아래와 같다.

query user <계정명>

현재 접속된 사용자 세션 정보를 확인한다.

tscon <세션ID> /dest:console

특정 RDP 세션을 콘솔 세션으로 전환한다.

배치 파일 형태로 만들 경우에는 실제 환경의 query user 출력 형식에 맞춰 세션 ID 위치를 파싱해야 한다.

@echo off
for /f "skip=1 tokens=<세션ID_토큰위치>" %%s in ('query user <계정명>') do (
    %windir%\System32\tscon.exe %%s /dest:console
)

주의한 점

query user 출력 형식은 환경마다 다를 수 있다.
따라서 tokens=3 같은 값이 항상 맞는 것은 아니다.

또한 tscon은 관리자 권한이 필요할 수 있다.
운영 환경에서는 보안 정책과 계정 권한 정책을 먼저 확인해야 한다.

정리한 기준

운영 자동화다 → Unattended Robot 구성이 우선
RDP 종료 후 실패한다 → 세션 종료 방식 확인
CMD 수동 실행은 되는데 BAT는 실패한다 → 권한, 계정, 세션 ID 파싱 확인
tokens 값이 맞지 않는다 → query user 출력 결과 기준으로 조정
관리자 권한이 필요하다 → 운영 정책에 맞게 승인된 방식으로 처리

RDP 관련 내용도 무조건 숨길 필요는 없다.
다만 실제 계정명, 서버명, 세션 ID, 내부 접속 방식은 제거하고, “원격 세션 상태가 UI 자동화에 영향을 준다”는 구조 중심으로 작성하는 것이 안전하다.


24. 운영 PC 환경에서 확인한 항목

문제 상황

개발 PC에서는 정상 동작했지만 운영 PC 또는 원격 환경에서는 UI 자동화가 실패하는 경우가 있었다.

내가 확인한 항목

해상도 고정 여부
디스플레이 배율
절전 모드 여부
화면 잠금 정책
브라우저 업데이트 영향
UiPath 브라우저 확장 프로그램 설치 여부
Windows 업데이트 후 재부팅 영향
Robot 실행 계정 권한
다운로드/임시 폴더 접근 권한
Office 버전
Outlook 프로필 설정
원격 세션 종료 방식

정리한 기준

UI 자동화가 간헐적으로 실패한다 → 해상도, 배율, 화면 잠금 확인
브라우저 셀렉터가 갑자기 깨진다 → 브라우저 업데이트 영향 확인
운영 시간 중 실패한다 → 재부팅 또는 세션 상태 확인
Excel/Outlook 오류가 난다 → Office 버전, 프로필, 권한 확인
원격 환경에서만 실패한다 → RDP 세션 상태와 실행 계정 확인

운영 PC 문제는 소스 코드 문제가 아니라 실행 환경 문제인 경우가 많았다.
따라서 개발 완료 후에는 운영 PC 기준으로 별도 점검표를 두는 것이 좋다.


25. HTML 메일 서식이 깨질 때

문제 상황

UiPath에서 HTML 메일을 작성해 보냈는데, Outlook에서 테이블 서식이 깨지는 경우가 있었다.

내가 확인한 원인

메일 클라이언트는 일반 브라우저처럼 HTML/CSS를 완전하게 처리하지 않는다.
특히 <style> 태그나 복잡한 CSS는 클라이언트에 따라 다르게 보일 수 있다.

내가 적용한 방식

중요한 스타일은 인라인으로 넣었다.

<table style='width:800px; border-collapse:collapse;'>
    <tr>
        <td style='border:1px solid #999; padding:4px;'></td>
    </tr>
</table>

VB.NET 문자열 안에서 HTML을 만들 때는 큰따옴표보다 작은따옴표를 쓰는 편이 편했다.

<td style='padding:4px;'></td>

동적으로 행을 추가할 때는 새로 생성되는 모든 td에 스타일을 직접 넣었다.

strRows = strRows &
"<tr>" &
"<td style='border:1px solid #999; padding:4px;'>" & value1 & "</td>" &
"<td style='border:1px solid #999; padding:4px;'>" & value2 & "</td>" &
"</tr>"

정리한 기준

메일 서식이 깨진다 → 인라인 CSS 우선
브라우저에서는 정상인데 Outlook에서 깨진다 → 메일 클라이언트 CSS 제한 의심
동적 테이블 일부만 깨진다 → 생성된 td/tr에 스타일 누락 확인
HTML이 텍스트로 보인다 → HTML Body 옵션 확인

26. 최종 판단 기준 요약

문자열과 컬렉션

문자열을 나누기만 한다 → Split
나눈 뒤 각 항목을 가공한다 → Split + Select
계속 추가할 데이터다 → Array보다 List
List 개수 확인 → Count
List 마지막 값 → Last(), 단 Count 체크 필요
중복 제거 → Distinct
순서까지 비교 → SequenceEqual
순서 무시 비교 → OrderBy 후 SequenceEqual
중복 무시 비교 → Distinct 후 OrderBy 후 SequenceEqual

Workflow 흐름 제어

정상 종료 → Return
실패를 상위에 전달 → Throw
반복문만 탈출 → Break
Throw 아래 Return → 대부분 불필요
중첩 If가 깊다 → Guard Clause로 분리

변수와 인수

String을 하위에서 바꾸고 외부에도 반영 → Out 또는 In/Out
DataTable 내부 내용 수정 → In으로도 반영 가능
DataTable 새 객체 할당 → Out 또는 In/Out 필요
String은 참조 타입이지만 불변 객체 → 값처럼 다루는 편이 안전

UI 자동화

동적 URL → 와일드카드 처리
URL 셀렉터의 & → &amp;로 작성
브라우저 변수 중심 → 클래식 방식
Use Application/Browser 중심 → 모던 방식
엘리먼트 개수 확인 → 부모 범위와 로딩 상태 확인
화면 경계 오류 → 해상도, 배율, Activate, Scroll 확인
셀렉터 불안정 → 동적 속성 제거, 안정 속성 위주로 재구성
원격 환경 실패 → 세션 상태와 화면 렌더링 확인

Excel 자동화

Excel COM 오류 → Excel 프로세스/파일 잠금/Scope 구조 확인
Copy/Paste 불안정 → DataTable 기반 처리 검토
간헐적 오류 → Delay, Save/Close 순서, Scope 단순화
운영 PC에서만 실패 → Office 버전, 권한, 실행 환경 확인

패키지와 네트워크

패키지 Restore 실패 → 패키지 소스와 버전 확인
제한된 네트워크 환경 → 로컬 패키지 또는 내부 패키지 저장소 필요
방화벽 요청 → 출발지, 목적지, 프로토콜, 포트, 용도 기준으로 정리
Robot 연결 실패 → Orchestrator 접근 확인
개발 PC만 정상 → 운영 PC의 네트워크, 프록시, 인증서 정책 확인

Queue와 REFramework

건별 상태 관리 필요 → Queue
실패 건 재처리 필요 → Queue
단순 실시간 조회 후 있으면 처리 → While 반복 검토
REFramework 사용 → Transaction 단위부터 정의
처리 대상이 없으면 후속 시스템 접근 불필요

운영 환경

UI 자동화 운영 PC → 해상도, 배율, 절전, 잠금 정책 확인
브라우저 자동화 → 브라우저 업데이트 영향 확인
스케줄 실행 → 중복 실행 방지 필요
RDP 종료 후 실패 → 세션 유지 방식 확인
Attended를 Unattended처럼 사용 → 운영 리스크 큼

마무리

UiPath 개발에서 자주 발생하는 문제는 대부분 다음 범주로 정리된다.

1. VB.NET 표현식과 데이터 타입 이해 부족
2. Workflow 흐름 제어와 예외 처리 기준 부족
3. UI 자동화 셀렉터와 화면 상태 문제
4. Excel, Outlook, Browser 같은 외부 애플리케이션 의존성
5. 패키지, 방화벽, 운영 환경 차이
6. Queue, REFramework, Trigger 설계 판단 문제
7. 원격 세션과 화면 렌더링 문제

RPA는 개발 PC에서 한 번 성공했다고 끝나는 작업이 아니다.
운영 환경에서 반복 실행되기 때문에, 작은 변수 타입 하나나 셀렉터 조건 하나도 장애 원인이 될 수 있다.

그래서 트러블슈팅은 단순히 “이렇게 하면 됨”으로 끝내기보다 아래 형식으로 정리하는 것이 좋다.

문제 상황
내가 적용한 해결 방식
주의한 점
정리한 기준

이 문서는 그런 기준으로 계속 업데이트한다.

profile
슬로우스타터 개발자 일지

0개의 댓글