호라이즌앱스 로고
← 기술 노트

프로그램 외주 맡기기 전에 정할 것, 누가 무엇을 볼 수 있나

임균영조회 —

그날 아침 계약관리 시스템에 팀별 조직도 화면을 올렸습니다. 이어서 팀장이 자기 팀원의 계약을 열어 볼 수 있는 권한도 배포했습니다.

그날 안에 둘 다 걷어냈습니다. 만든 지 몇 시간 만이었습니다.

시점한 일
오전팀별 조직도 화면 배포
오전팀장 계약 열람 권한 배포
같은 날현업 확정: 팀 없음, 전원 지사장 직할
같은 날팀장 권한 테이블·트리거·보안 분기 삭제 배포

코드는 테스트를 통과했고 운영 화면에서도 제대로 돌았습니다. 빠진 것은 개발 전에 들었어야 할 한 문장이었습니다.

처음 업무 프로그램을 외주로 맡기는 분은 보통 화면 목록과 기능 목록부터 준비하십니다. 그 목록보다 먼저 답해 둘 질문이 있습니다. 누가 무엇을 볼 수 있느냐는 질문입니다.

오전에 올린 팀장 열람

보험대리점(GA) 지사의 계약관리 시스템이었습니다. 설계사마다 맡은 계약과 고객이 있고, 지사 관리자는 전체를 봅니다.

데이터에는 설계사마다 팀 이름이 적혀 있었습니다. 저는 그 팀을 최상위 단위로 삼아 임직원 화면을 팀별 카드로 바꿨습니다.

인원이 많은 팀은 카드가 지나치게 길어져서 처음 8명만 보이고 나머지는 펼치게 했습니다. 데스크톱과 휴대폰 폭 390px 화면을 직접 캡처해 확인했습니다.

이어서 팀장 권한을 붙였습니다. 팀장은 같은 팀 재직자의 계약과 그 계약에 연결된 고객만 볼 수 있게 했습니다.

팀장 관계는 별도 테이블에 명시했습니다. 팀장이 퇴사하거나 팀을 옮기면 DB 트리거가 그 관계를 바로 지웁니다.

데이터베이스의 행 단위 보안 규칙에도 팀장 예외를 넣었습니다. 앱이 조회를 잘못 짜더라도 DB가 한 번 더 막는 구조입니다.

격리된 테스트 DB에 가짜 팀과 계약을 만들어 돌려 봤습니다. 같은 팀 계약은 1행, 다른 팀 계약은 0행이 나왔습니다.

팀장을 퇴사 처리하자 팀장 관계는 0건, 볼 수 있는 계약도 0행이 됐습니다. 운영 배포 뒤 화면 콘솔 오류도 0건이었습니다.

같은 날 확정된 한 문장

같은 날 지사 실무 책임자와 메신저로 담당자 구조를 두고 긴 논의가 오갔습니다. 거기서 확정된 내용은 "팀 없음, 전원 지사장 직할, 남의 계약은 안 본다"였습니다.

팀 이름은 데이터에만 남아 있었고 실제 조직에는 팀장이 없었습니다. 오전에 만든 기능은 존재하지 않는 역할을 위한 기능이 됐습니다.

그래서 팀장 테이블과 트리거를 지우고, 행 단위 보안의 팀장 분기를 삭제했습니다. 앱 조회 함수의 팀장 분기와 계약 목록의 팀 필터도 걷어냈습니다.

임직원 화면은 원래의 목록으로 돌렸습니다.

데이터에 적힌 팀 이름대로 묶었던 카드와 팀장 열람이, 현업의 한 문장이 내려오자 지사장 직할 한 줄 목록으로 풀립니다. 각 설계사는 본인 계약만 봅니다.

삭제는 마이그레이션 하나와 코드 몇 곳으로 끝났습니다. 아까운 건 그 앞의 몇 시간이었습니다. 설계하고 검증하고 배포한 시간이 그대로 지워졌습니다.

담당자는 누구인가

그날 논의에서는 팀보다 더 큰 것이 정해졌습니다. 계약의 담당자가 누구냐는 문제였습니다.

답은 그 계약을 처음 모집한 설계사였습니다. 그 설계사가 퇴사해도 담당자는 바뀌지 않고, 지사장에게 넘어가지도 않습니다.

바뀌는 건 새로 체결하는 계약의 담당자뿐입니다. 수금 담당이라는 개념은 아예 없다는 답도 받았습니다.

저는 그때까지 수금 담당이 따로 있다고 짐작하고 있었습니다. 근거는 기존 데이터의 컬럼 이름이었습니다.

'수금 담당'이라는 이름의 칸에 실제로는 처음 모집한 설계사가 들어 있었습니다. '원모집자' 칸은 전부 비어 있었습니다.

데이터를 옮겨 넣던 프로그램이 원모집자 칸을 채우지 않았고, 그 역할을 수금 담당 칸이 대신하고 있던 겁니다. 컬럼 이름과 실제 값이 뒤틀려 있었습니다.

다행히 동작은 맞았습니다. 퇴사 처리나 주인 잃은 계약을 나누는 로직이 그 칸을 바꾸지 않았습니다.

고칠 코드가 거의 없다는 것은 코드를 먼저 읽어 확인했습니다.

계약서 문구와 실제 입금일

급식 납품업체에는 대시보드를 운영해 드리면서 서버 운영비를 제가 매달 청구합니다. 그 청구 규칙에서도 비슷한 일을 겪었습니다.

서버 운영비 계약서에는 "매월 말일까지 입금한다"고 적혀 있었습니다. 실제 관행은 전월분 명세서를 매월 1일에 발행하고 그달 10일까지 받는 방식이었습니다.

고객 요청으로 조건이 바뀌었는데 계약서는 예전 문구 그대로였습니다. 저는 명세서 자동 발송을 되살리면서 계약서 조항을 기준으로 코드를 짰습니다.

첫 자동 발송 명세서에는 "9월분, 입금 기한 9월 30일"이 찍혀 나갔습니다. 맞는 값은 "8월분, 기한 9월 10일"이었습니다.

같은 날 코드를 관행에 맞춰 고쳐 배포하고 정정본을 다시 보냈습니다.

출처적힌 조건
계약서 조항매월 말일까지 입금
실제 나간 명세서전월분, 1일 발행, 10일 기한

맞는 답은 지난달까지 실제로 나간 명세서 PDF와 대시보드 코드 한 줄에 이미 있었습니다. 저는 가장 권위 있어 보이는 문서 하나만 정본으로 골랐습니다.

돈이 오가는 규칙은 최근 실제로 오간 내역 한두 건과 함께 알려 주세요. 명세서 PDF 한 장만 있어도 계약서 문구와 관행이 다른지 개발 전에 보입니다.

그 파일은 어디서 왔나

원본 파일을 넘길 때는 출처도 같이 적어 주시는 편이 좋습니다. 직원이 손으로 쌓은 엑셀인지, 어떤 시스템에서 내려받은 파일인지에 따라 확인할 것이 다릅니다.

내려받은 파일은 그 시스템이 정한 형식을 따르므로 형식 함정을 먼저 봅니다. 손으로 만든 파일은 사람마다 칸을 쓰는 법이 달라서, 같은 칸에 다른 뜻이 섞였는지를 먼저 봅니다.

앞 절의 뒤틀린 컬럼은 데이터를 옮겨 넣던 프로그램에서 생겼습니다. 어느 프로그램이 옮겼는지까지 한 줄 적어 주시면 그런 칸부터 확인합니다.

롤백 뒤 남은 권한

팀장 분기를 지운 뒤에는 권한이 '본인 담당만'으로 돌아갔는지 다시 봐야 했습니다. 설계사 역할의 시험 계정으로 운영 화면에 들어가 확인했습니다.

담당 설계사가 넷인 고객에서는 본인 담당 1건만 보였고, 계약 목록 2,524건도 전부 그 설계사의 것이었습니다. 이렇게 역할 계정으로 검수하는 방법은 외주 검수 글에서 당일 검수표와 함께 다룹니다.

의뢰 전 준비물

이 시스템에는 같은 날 개발자와 현업 책임자가 비동기로 묻고 답하는 확인 창구도 만들었습니다. 확인할 것 5건을 올렸고 4건에 답이 왔습니다.

그중 하나가 "실적과 화면 표시는 납입보험료 기준"이라는 답이었습니다. 이 한 줄로 수정보험료를 먼저 쓰던 계산을 세 곳에서 고쳤습니다.

질문이 개발 중에 생기는 건 막을 수 없습니다. 다만 아래 준비물이 미리 있으면 질문마다 누가 답할지가 미리 정해집니다.

준비물이 글에서 관련된 장면
역할별 열람 범위 표없는 팀장 역할을 만들었다가 같은 날 삭제
지금 쓰는 원본 파일 한 벌컬럼 이름과 실제 값의 뒤틀림을 뒤늦게 발견
그 파일의 출처옮겨 넣던 프로그램이 원모집자 칸을 비워 둠
돈 규칙의 실제 관행명세서가 한 달 어긋나 정정본 발송
퇴사·이관 같은 예외 3건담당자 이관 여부를 개발 도중에 확정
최종 결정할 사람 한 명실무 책임자와의 논의 한 번으로 담당자 구조 확정

열람 범위 표는 이 정도 모양이면 충분합니다. 위 계약관리 시스템을 예로 든 모양입니다.

역할볼 수 있는 데이터서명 계약서 PDF
설계사본인이 처음 모집한 계약과 그 고객본인 담당 계약만 열람
관리자지사 전체 계약과 고객열람, 업로드
팀장이 조직에는 없는 역할없음

마지막 줄처럼 '없는 역할'을 적어 두는 것도 의미가 있습니다. 개발자가 데이터를 보고 역할을 지어낼 여지를 미리 닫아 줍니다.

예외는 실제로 있었던 일로 적어 주세요. "설계사가 퇴사하면 그 사람 계약은 누가 맡나요?"에 지금 어떻게 처리하고 있는지 한 줄씩이면 됩니다.

이 표를 혼자 채우기 막막하다면 업무 시스템 도입 교육에서 우리 회사 업무 흐름을 그려 요구사항 표로 옮기는 과정을 직접 해 볼 수 있습니다.

표를 반쯤 채운 상태라도 제작 상담에 붙여 보내 주시면, 빈칸마다 개발 전에 물어야 할 질문으로 바꿔 드립니다.

이어서 읽기