인턴 채용 메일 자동화 사례 - Power Automate 활용기 2탄 (다중 인원 처리 구현기)

📌 소개 (Introduction)

무엇을 시도했나?

지난 번 Power Automate 자동화 후, 하나의 채용 요청 메일 본문에 두 명 이상의 채용 대상자가 포함되는 경우에는 한 명만 Excel에 자동 기재되는 현상을 발견했습니다. 이에 따라 Apply to Each 를 사용하여 다중 인원도 Excel에 자동 기재될 수 있도록 플로우 수정 작업을 하였습니다.

🛠️ 진행 방법 (Methodology)

사용한 도구

  • Microsoft Power Automate: 워크플로우 엔진

  • Genspark AI: 파싱 로직 설계 및 디버깅


1단계: 문제 진단

초기 플로우 (ver1)

📧 트리거: 새 메일 도착
  ↓
📝 변수 초기화 (var_메일본문)
  ↓
🧹 HTML 태그 제거 (4단계)
  ↓
🔤 데이터 추출 (15개 변수)
  - var_성명: @last(split(..., '채용 대상자'))  ← 문제!
  ↓
✅ Excel 행 추가 (1회만)

문제: last(split(..., '채용 대상자'))로 마지막 사람만 추출


2단계: 다중 인원 처리 구현

수정된 플로우 (ver2 - 최종)

📧 트리거: 새 메일 도착
   조건: 제목 포함 '채용' + 발신자 8명 중 1명
  ↓
🧹 HTML_태그_제거 (5단계)
  ↓
✂️ 채용대상자별_분할
  @split(outputs('HTML_태그_제거5'), '채용 대상자')
  → [0]="", [1]="홍길동\n...", [2]="김철수\n..."
  ↓
🔁 각_인원_처리 (Apply to each)
  @skip(outputs('채용대상자별_분할'), 1)
    ↓
    📊 현재인원_성명
    📊 현재인원_이메일
    📊 현재인원_핸드폰번호
    📊 현재인원_채용기간 → 입사일/퇴사일
    📊 현재인원_프로젝트명
    📊 현재인원_계정발급여부 → 계정생성대상
    📊 현재인원_발신인이메일
...
    ↓
    🔍 테이블_조회 → 필터_배열 → 소속_추출
    ↓
    ✅ 테이블에_행_추가
    ↓
    🔀 조건 (성공/실패 메일)

핵심 코드 1: 트리거 설정에 제목 필터 추가("채용"을 포함하는 경우만 작동)

개선 이유: 불필요한 메일(예: 계정 문의, 일반 공지) 필터링 → 오작동 방지

핵심 코드 2: HTML 태그 제거 5단계

// HTML_태그_제거5
@replace(
  replace(
    replace(
      replace(
        replace(
          outputs('HTML_태그_제거4'),
          'color', 
          ''
        ),
        'currentcolor',
        ''
      ),
      'rgb',
      ''
    ),
    '(',
    ''
  ),
  ')',
  ''
)

3단계: 데이터 추출 로직 (최종 버전)

1️⃣ 성명

// 현재인원_성명 (Compose)
@trim(split(item(), decodeUriComponent('%0A'))[0])

로직: 각 인원 섹션의 첫 줄 = 이름

2️⃣ 이메일 (HTML 잔여물 제거)

// 현재인원_이메일 (Compose)
@trim(
  replace(
    replace(
      replace(
        replace(
          replace(
            split(
              split(item(), '대상자 이메일 주소')[1],
              decodeUriComponent('%0A')
            )[0],
            '대상자 이메일 주소',
            ''
          ),
          '15,108,189',  // ← HTML 잔여물
          ''
        ),
        ',',
        ''
      ),
      ' ',
      ''
    ),
    decodeUriComponent('%0A'),
    ''
  )
)

개선 포인트: 15,108,189 같은 HTML 색상 코드 잔여물 제거

3️⃣ 핸드폰번호 (substring 방식)

// 현재인원_핸드폰번호 (Compose)
@replace(
  replace(
    replace(
      substring(
        split(
          split(item(), '대상자 연락처')[1],
          decodeUriComponent('%0A')
        )[0],
        sub(
          length(
            split(
              split(item(), '대상자 연락처')[1],
              decodeUriComponent('%0A')
            )[0]
          ),
          13
        ),
        13
      ),
      ',',
      ''
    ),
    ' ',
    ''
  ),
  '15108189',
  ''
)

로직:

  1. '대상자 연락처' 이후 첫 줄 추출

  2. 해당 줄의 끝에서 13자리 (010-1234-5678 형식)

  3. 쉼표, 공백, HTML 잔여물 제거

4️⃣ 채용기간 (current 제거)

// 현재인원_채용기간 (Compose)
@trim(
  replace(
    replace(
      replace(
        split(
          split(item(), '채용 기간')[1],
          decodeUriComponent('%0A')
        )[0],
        '채용 기간',
        ''
      ),
      'current',  // ← HTML 속성 'currentcolor' 잔여물
      ''
    ),
    ' ',
    ' '
  )
)

// 현재인원_입사일
@trim(first(split(outputs('현재인원_채용기간'), '~')))

// 현재인원_퇴사일
@trim(last(split(outputs('현재인원_채용기간'), '~')))

5️⃣ 계정발급여부 (고정 라인 인덱스)

// 현재인원_계정발급여부
@trim(
  last(
    split(
      split(item(), decodeUriComponent('%0A'))[11],  // ← 12번째 줄 고정
      ' '
    )
  )
)

// 현재인원_계정생성대상
@if(
  or(
    equals(toLower(trim(outputs('현재인원_계정발급여부'))), 'yes'),
    equals(toLower(trim(outputs('현재인원_계정발급여부'))), 'y'),
    equals(toLower(trim(outputs('현재인원_계정발급여부'))), 'n')
  ),
  if(
    equals(toLower(trim(outputs('현재인원_계정발급여부'))), 'n'),
    'X',
    '필요'
  ),
  'X'
)

특이사항:

  • 키워드 검색 대신 고정 인덱스 [11] 사용

  • 이유: 실제 메일 포맷이 일관되게 12번째 줄에 위치

6️⃣ 소속 추출 (외부 테이블 조회)

// 현재인원_발신인이메일
@triggerOutputs()?['body/from']

// 테이블에_있는_행_나열

// 필터_배열 (Query)
@equals(
  item()?['담당자 메일'],
  outputs('현재인원_발신인이메일')
)

// 현재인원_소속추출
@if(
  greater(length(body('필터_배열')), 0), 
  first(body('필터_배열'))?['관할조직'], 
  ''
)

4단계: 조건부 알림 (각 인원마다)

// 조건
@equals(outputs('테이블에_행_추가')?['statusCode'], 200)

// Yes: 성공_메일_보내기(V2)
To: 나의 메일
Subject: @{outputs('현재인원_소속추출')} @{outputs('현재인원_성명')}  인턴 시트에 입력 완료

// No: 실패_메일_보내기(V2)
Subject: 인턴 시트에 기재 실패
Body: 수기 입력 필요

📊 결과와 배운 점

핵심 학습

1. "substring은 끝에서 역산할 수 있다"

// 발견: 핸드폰번호가 "홍길동 010-1234-5678" 형식
// 해결: 끝에서 13자리만 추출
substring(text, length(text) - 13, 13)

배운 점: 앞쪽이 불규칙하면 뒤에서 거꾸로 추출

2. "고정 인덱스 vs 키워드: 상황 따라 선택"

// 일관성 있는 위치 → 고정 인덱스 OK
split(item(), '%0A')[11]  // 계정발급여부

// 위치 가변적 → 키워드 검색
split(item(), 'PM / 사번')[1]

3. "HTML 잔여물은 5단계 이상 제거 필요"

  • 15,108,189: RGB 색상 코드

  • current: currentcolor 속성 잔여

  • Outlook HTML = Word 기반 → 복잡함

4. "'채용' 제목 필터로 오작동 90% 감소"

Copy// Before: 모든 메일 처리 → 계정 문의, 일반 공지도 파싱 시도
// After: 제목에 '채용' 포함된 메일만
"subjectFilter": "채용"

시행착오

문제 1: "두 번째 사람 이메일에 HTML 태그"

  • 현상: color rgb(15,108,189) [email protected]

  • 원인: 두 번째 이메일에만 하이퍼링크 스타일

  • 해결: HTML_태그_제거5에서 'rgb' 제거 + 이메일 수식에 15,108,189 제거

문제 2: "핸드폰번호에 이름 포함"

  • 현상: 홍길동 010-1234-5678

  • 원인: 첫 단어 추출 → 이름까지 포함

  • 해결: substring으로 끝 13자리만

문제 3: "계정발급여부 추출 실패"

  • 현상: 빈 값 또는 다른 필드 값

  • 원인: 키워드 검색이 불안정

  • 해결: 고정 인덱스 [11] 사용 (메일 포맷 일관성 확인 후)



💬 마치며

3가지 핵심 교훈:

  1. 예외 케이스가 완성도를 결정

    • HTML 잔여물, 다중 인원, 빈 값 처리 = 90% 시간 소요

  2. 도구 이해보다 패턴 이해

    • substring(끝에서 역산), 고정 인덱스 vs 키워드, 5단계 HTML 제거

1
1개의 답글

뉴스레터 무료 구독

👉 이 게시글도 읽어보세요