작성일·마지막 확인: 2026-08-29

고객사별 폴더를 눈으로 찾아 열 때는 회사 이름이 조금 달라도 사람이 알아서 뜻을 맞춘다. 하지만 자동화에 같은 방식을 맡기면 이야기가 달라진다. 정식명, 줄임말, 지점명처럼 보이는 표현이 각각 다른 폴더를 가리키기 시작하면, 그럴듯한 추측이 곧 잘못된 파일 읽기로 이어질 수 있다. 제가 레지스트리를 두는 이유는 이름을 멋지게 정리하기 위해서가 아니라 입력한 이름이 정확히 어느 작업 공간을 뜻하는지 기계적으로 결정하고, 결정할 수 없으면 멈추게 하기 위해서다.

이 글이 필요한 사람

Windows PC에서 여러 거래처나 프로젝트의 원고, 이미지, 상태표를 나누어 관리하면서 CSV 정도의 가벼운 형식으로 자동화를 시작하려는 1인 운영자에게 맞춘 글이다. 대규모 고객관리 시스템을 대신하려는 설계가 아니다. 고객 수가 많지 않더라도 비슷한 상호가 있거나, Telegram 같은 짧은 메시지로 작업 대상을 지정하거나, AI 에이전트가 폴더를 찾아야 한다면 먼저 적용할 만하다.

문제는 폴더 수보다 이름의 불일치다

한 회사를 부르는 말은 하나가 아닐 수 있다. 계약서의 정식명과 작업자가 쓰는 줄임말이 다르고, 대화에서는 지역명만 붙여 부르기도 한다. 이때 프로그램이 문자열이 가장 비슷한 항목을 자동 선택하도록 만들면 편해 보이지만, 실제 쓰기·게시 작업에서는 위험하다. 이름을 잘못 골라도 문법 오류가 나지 않기 때문이다. 파일은 정상적으로 열리고 결과도 생성되므로 발견이 늦어진다.

그래서 저는 현재 상태 자체와 고객을 찾는 색인을 분리해 생각한다. 레지스트리는 “누구인가”와 “어디를 조회해야 하는가”만 연결한다. 이번 달 원고 단계, 승인 여부, 게시 예정일처럼 자주 바뀌는 값은 각 고객의 상태파일에 둔다. 하나의 CSV에 모든 정보를 몰아넣지 않으면 별칭을 고치다가 진행상태를 건드리는 일도 피할 수 있다.

기준 환경

  • Windows PC와 고객사별 작업 폴더
  • UTF-8로 저장한 CSV 레지스트리
  • 작업 루트를 기준으로 한 상대경로
  • 레지스트리를 먼저 조회한 뒤 상태파일을 읽는 스크립트 또는 에이전트

공개 글에서는 실제 사용자명이나 드라이브 전체 경로를 쓰지 않는다. 아래 값은 구조를 설명하기 위한 가상 예시이며 실행 결과나 실제 고객 정보가 아니다.

1단계: 변하지 않는 ID를 먼저 만든다

화면에 보이는 회사명을 파일 연결의 기준으로 삼지 않는다. 상호는 바뀔 수 있고 같은 이름이 생길 수도 있다. 내부 식별자인 client_id를 만들고, 영문 소문자·숫자·밑줄처럼 파일과 코드에서 다루기 쉬운 문자만 허용한다. ID에 전화번호, 담당자명, 사업자번호 같은 개인정보를 넣지 않는 것도 중요하다.

client_id,client_name,aliases,status_path,active
client_a,예시 스튜디오,예시|스튜디오A,data/client_a/status.csv,true
client_b,샘플 연구소,샘플랩|연구소B,data/client_b/status.csv,true

client_name은 사람이 확인할 표시명, aliases는 허용한 별칭 목록, status_path는 승인된 작업 루트 아래의 상대경로다. active는 종료된 고객을 검색 대상에서 제외할 때 쓸 수 있다. 열을 더하기 전에 그 값이 고객 식별에 필요한지, 상태파일에 둘 값인지 먼저 나눈다.

2단계: CSV 저장 규칙을 고정한다

Excel로 열었다가 다시 저장하면 인코딩, 줄바꿈, 따옴표 처리가 달라질 수 있다. 회사명에 쉼표가 들어갈 가능성이 있다면 CSV 표준에 맞게 필드를 따옴표로 감싸는 라이브러리를 사용한다. 별칭 구분자는 회사명에 잘 등장하지 않는 문자 하나로 정하고, 앞뒤 공백을 제거한 뒤 저장한다. 단, 대소문자 통일이나 공백 제거가 두 고객을 같은 값으로 만들 수 있으므로 정규화 뒤의 중복도 검사해야 한다.

3단계: 조회는 세 가지 결과만 허용한다

  1. 정확히 한 건 일치: ID, 표시명, 상대경로를 반환한다.
  2. 일치 없음: 임의 선택 없이 “대상을 찾지 못함”으로 끝낸다.
  3. 두 건 이상 일치: 후보의 표시명과 ID만 보여주고 사용자의 선택을 기다린다.

별칭의 부분 일치나 편집거리 기반 추천은 조회 보조로만 쓸 수 있다. 추천을 곧 선택으로 취급하지 않는다. 특히 외부 게시, 삭제, 덮어쓰기 단계에서는 반드시 내부 ID로 대상을 다시 고정한다. 입력 메시지의 원문만 다음 단계까지 끌고 가면 중간에 이름 해석이 달라질 수 있다.

4단계: 상대경로가 작업 루트를 벗어나지 못하게 한다

status_path가 상대경로라고 해서 저절로 안전한 것은 아니다. ..를 포함한 값이나 링크를 따라가면 승인된 루트 밖으로 이동할 수 있다. 프로그램은 작업 루트와 상대경로를 결합해 정규화한 최종 경로가 여전히 작업 루트 안인지 확인해야 한다. 파일 존재 여부와 확장자도 읽기 전에 검사한다. 이 검증이 실패하면 새 파일을 추측해 만들지 말고 레지스트리 오류로 보고한다.

5단계: 읽기 전용 조회부터 연결한다

처음부터 “고객 이름을 말하면 게시까지 완료”로 묶지 않는다. 먼저 이름을 받아 ID와 상태파일 위치만 보여주는 읽기 전용 명령을 만든다. 다음으로 상태 요약을 읽게 하고, 쓰기는 별도 승인 단계로 남긴다. 자동화가 참조한 레지스트리 행과 최종 ID를 실행 기록에 남기면, 나중에 어떤 기준으로 대상을 선택했는지 확인하기 쉽다. 기록에도 전체 로컬 경로나 개인정보는 남기지 않는다.

실무 예시: 짧은 요청을 안전하게 해석하기

예를 들어 사용자가 “예시 이번 달 상태 보여줘”라고 보냈다고 하자. 이것은 실행 사실이 아니라 흐름을 설명하기 위한 예시다. 프로그램은 먼저 예시를 정규화한 뒤 client_name과 별칭에서 찾는다. 한 행만 일치하면 client_a로 대상을 고정하고, 작업 루트 안에 있는지 확인한 data/client_a/status.csv를 읽는다. 두 행이 일치한다면 상태파일을 하나라도 열기 전에 후보 선택을 요청해야 한다. “아마 자주 쓰는 고객일 것”이라는 기억은 선택 근거가 아니다.

제가 피하는 나쁜 접근

  • 폴더명을 부분 검색해 첫 번째 결과를 자동 선택하는 방식
  • 한 고객의 별칭을 다른 고객에게도 중복 등록하는 방식
  • 현재 진행상태까지 레지스트리 한 칸에 자유문장으로 쌓는 방식
  • 로컬 절대경로와 Windows 사용자명을 채팅 보고에 그대로 출력하는 방식
  • 레지스트리 파일이 없을 때 비슷한 폴더를 찾아 계속 진행하는 방식

이런 접근은 데모에서는 빠르게 보이지만 실패가 조용하다. 특히 “명령이 성공했다”는 메시지는 올바른 고객을 선택했다는 증거가 아니다. 최종 ID와 읽은 상태의 고객 ID가 같은지 다시 대조해야 한다.

검증 체크리스트

  • 정식명과 등록된 모든 별칭이 각각 정확히 한 ID를 찾는가
  • 존재하지 않는 이름에서는 파일을 열지 않고 중단하는가
  • 중복 별칭에서는 후보만 제시하고 자동 선택하지 않는가
  • 비활성 고객이 기본 검색 결과에서 제외되는가
  • .., 절대경로, 허용하지 않은 확장자를 거부하는가
  • CSV의 한글, 쉼표, 따옴표, 줄바꿈이 저장 후에도 유지되는가
  • 상태파일 내부의 고객 ID와 선택한 ID가 일치하는가
  • 보고 메시지와 로그에 실제 로컬 전체 경로가 노출되지 않는가

보안과 개인정보 주의

레지스트리에는 업무 연결에 필요한 최소 정보만 둔다. 개인 전화번호, 환자명, 계정 비밀번호, API 키는 넣지 않는다. 파일의 백업본과 휴지통 사본도 원본과 같은 보안 범위로 다뤄야 한다. 공유용 예시를 만들 때는 이름만 가리는 데서 끝내지 말고 경로, 메모, 파일 메타데이터에 식별 정보가 남지 않았는지 확인한다. CSV를 스프레드시트에서 열 때 수식으로 해석될 수 있는 외부 입력도 주의해야 한다.

함께 읽을 작업 노트

대상 식별 뒤에 실제 변경을 붙이기 전에는 AI 자동화에서 사람이 반드시 승인해야 하는 작업을 먼저 정리하는 편이 좋다. 전체 자동화 범위를 고르는 단계라면 AI 업무자동화를 시작하기 전에 정리할 것도 이어서 볼 수 있다.