← 문제 해결 기록

회사 업무 · 팀 협업 · 2026.06 - 현재

CRM 청구·인력 관리와 제품 이관

청구·인력 관리의 규칙을 구현하고, 제품 이관의 완료 기준을 실행과 저장까지 넓혔습니다.

개요

기간
2026.06 - 현재
참여 형태
회사 업무 · 팀 협업
담당
담당 기능 구현·검증
목적
계약에서 정한 청구 스케줄과 인력 계획을 업무 화면·상태 전이·저장 조건으로 관리하고, 제품을 신버전 DB 환경으로 옮기는 것
대상
청구와 인력 계획을 관리하는 업무 사용자
사용 기술
Java · React · PostgreSQL
회사에서 청구·인력 관리 기능의 구현과 검증을 맡고 있습니다. 팀이 제시한 청구 스케줄과 인력 계획 요구를 업무 화면·상태 전이·저장 조건으로 구체화했습니다. 발행 상태, 배정 기간, 역할, 공수처럼 서로 연결된 규칙을 다룹니다.화면의 읽기 전용 처리에만 기대지 않고, 생성·월 이동·수정에서 같은 서버 규칙을 적용하도록 정리했습니다. 청구 저장 경로를 일원화하고, 종료한 계획의 이력을 보존하며 중복 호출을 구분했습니다. 조회 허용 조건을 검토할 때도 편리한 기본값보다 확인 가능한 권한을 기준으로 판단했습니다.제품 이관에서는 데이터가 옮겨졌다는 사실과 사용자가 실행·저장할 수 있다는 사실을 구분했습니다. DB 정의부터 API, 화면, 실행, 저장 후 재조회까지 단계별로 확인하고 기존 업무 데이터의 보존도 점검했습니다. 구현에는 AI 도구를 활용했고, 제 기여는 요구를 서버 조건으로 정리한 판단과 담당 경로의 검증입니다.

구현 기능과 기술 선택

  • 청구 스케줄·발행 워크플로우 (발행 전 미리보기, 전자세금계산서 발행)
  • 인력 배정 보드 (기간·역할·공수 관리)
  • MariaDB → PostgreSQL 제품 이관과 단계별 검증
  • 청구 스케줄·발행 워크플로우와 인력 배정 보드 구현, 상태·기간·역할·공수 검증을 서버 저장 경로에 공통 적용
  • 청구 저장 경로 일원화, 종료 계획의 이력 보존과 중복 종료 요청의 구분 처리
  • MariaDB 기준 패치의 PostgreSQL 비호환 4종(NOT NULL 제약, 전용 타입, 숫자 컬럼의 빈 문자열, 날짜 함수) 보정
서버 저장 경로의 공통 검증
화면의 읽기 전용 처리는 생성·월 이동·수정 경로마다 규칙이 달라질 수 있어, 저장 경로에 같은 조건을 두었습니다.
표준 SQL과 플랫폼 표준 함수
PostgreSQL 전용 문법으로 우회하면 다른 DB에서 다시 깨지므로, 플랫폼 표준 날짜 함수와 CAST 구문을 유지했습니다.
React 컴포넌트의 설정 분리
같은 보드를 여러 화면에서 쓰며 파일 복사가 늘었습니다. 화면마다 달라지는 값만 폼 설정으로 옮기고, 데이터를 바꾸는 기능은 설정에서 명시적으로 켠 경우에만 동작하게 했습니다.

트러블슈팅

청구·인력 관리의 규칙을 서버에 옮기기

문제 상황

청구 발행 상태와 인력 배정의 기간·역할·공수는 서로 연결된 규칙입니다. 화면에서 입력을 막아도 생성·월 이동·수정 경로마다 저장 로직이 달라, 같은 데이터가 경로에 따라 다른 규칙으로 저장될 수 있었습니다. 청구에는 별도 쓰기 경로와 폴백 경로까지 있었습니다.

해결 과정

화면의 읽기 전용 처리만으로는 경로가 늘 때마다 규칙이 달라질 수 있었습니다. 그래서 화면은 안내만 하고, 최종 판단은 서버 저장 경로 한 곳에서 하도록 바꿨습니다. 인력 생성·월 이동·공수 수정에 같은 조건을 적용하고 청구의 별도 쓰기·폴백 경로는 없앴습니다. 종료한 계획은 삭제하는 대신 완료 상태로 남겨 이력을 보존했고, 이미 종료된 계획의 재요청은 따로 구분했습니다.

결과

어느 경로로 저장해도 같은 규칙을 따르고, 종료한 계획은 이력으로 남습니다. 변경은 담당 코드와 업무 기록으로 확인했습니다.

본인 기여: 주어진 요구를 서버의 조건과 저장 정책으로 구체화하고 담당 구현·검증에 참여했습니다. 구현에는 AI 보조를 활용했습니다.

조회 허용 조건과 정상 동작을 함께 검증하기

문제 상황

업무 조회의 허용 범위를 결정할 때 권한 정보가 명확하지 않은 경우를 어떻게 처리할지 기준이 필요했습니다. 단순히 예외가 발생하지 않도록 만드는 것만으로는 올바른 조회 범위를 설명할 수 없었습니다.

해결 과정

권한 정보가 확인되지 않았을 때 허용 범위를 넓히는 편의적 기본값을 기각했습니다. 담당 조회 조건을 수정하고 격리 환경에서 차단해야 하는 입력과 정상 권한의 입력을 함께 실행했습니다. 적용·원복·재적용을 대조해 조건 변경의 영향을 확인했습니다.

결과

격리 환경의 담당 조회에서 허용되지 않은 입력의 차단과 정상 권한의 조회 유지를 확인했습니다. 이 결과는 확인한 경로와 환경에 한정됩니다. 추가 조회 조건 검토와 운영 화면 회귀는 후속 범위로 남겼습니다.

이관 완료를 데이터 존재로 판단하지 않기

문제 상황

제품 버전과 적용 환경이 바뀌면 데이터가 존재해도 화면·연계·저장 동작이 이어진다고 볼 수 없었습니다. 업무·관계 데이터의 매핑과 다른 제품팀의 기능 적용 지원에서 단계별 완료 기준이 필요했습니다.

해결 과정

담당 데이터와 관계를 ID 기준으로 연결하고, DB 정의 → API → 화면 → 실행 → 저장 후 재조회 순서로 확인했습니다. 기존 업무 데이터의 행 해시를 대조하고 재실행 절차를 정리했습니다. 다른 팀이 적용을 재현할 수 있도록 확인 순서와 남은 조건을 공유했습니다.

결과

담당 이관·패치와 단계별 실행 확인을 기록했고, 확인한 기존 데이터의 보존을 점검했습니다. 일부 연계의 형식 호환성과 AI 기능의 운영 전환 승인은 남아 있었습니다. 개발 환경의 실행 확인과 전체 운영 이관 완료를 별도 상태로 관리했습니다.

본인 범위: 담당 데이터 매핑·검증 및 다른 제품팀의 적용 지원. 전체 제품 전환의 단독 주도 성과로 표현하지 않습니다.

MariaDB에서 통과하던 패치가 PostgreSQL에서 막히는 네 가지

문제 상황

제품을 MariaDB에서 PostgreSQL로 옮기면서 구버전에서 만든 패치를 적용하자 INSERT와 테이블 생성이 연이어 거부됐습니다. MariaDB가 관대하게 받아 주던 값을 PostgreSQL은 엄격하게 거부했고, 원인이 제각각이었습니다.

해결 과정

거부된 사례를 네 유형으로 나눠 유형마다 기준을 정했습니다. 멀티테넌시 키가 빠진 NOT NULL 위반은 공통 데이터와 테넌트 데이터를 구분해 값을 채웠고, MEDIUMTEXT·VARCHAR2·CLOB 같은 전용 타입은 PostgreSQL 타입으로 바꿨습니다. 숫자 컬럼의 빈 문자열은 일괄 NULL로 바꾸면 원래 0이던 데이터의 합계·평균·'= 0' 조건 결과가 달라져, 원래 0이던 값은 0으로, 미입력은 NULL로 나눴습니다. 날짜 함수는 PostgreSQL 전용 문법으로 우회하면 다른 DB에서 다시 깨지므로, 전용 함수 대신 플랫폼 표준 날짜 함수와 CAST를 유지했습니다.

결과

보정한 패치를 다시 적용해 정상 반영을 확인했습니다. 네 유형과 보정 방법을 확인 순서로 정리해 사내에 공유했고, 이후 다른 팀원의 이관 기록에서 이 정리를 참조했습니다.

주의한 점: 빈 값을 일괄 NULL로 바꾸면 원래 0이던 데이터의 합계·평균·'= 0' 조건 결과가 달라집니다.

결과와 성과

  • 이관 완료 기준을 DB 정의 → API → 화면 → 실행 → 저장 후 재조회 5단계로 확장, 행 해시 대조로 기존 데이터 보존 확인
  • PostgreSQL 비호환 유형과 보정 방법을 정리해 사내 공유, 이후 다른 팀원의 이관 기록에서 참조
  • 조회 허용 조건을 격리 환경에서 차단 입력과 정상 입력 모두 실행해 검증 (적용·원복·재적용 대조)

회고

배운 점
데이터가 옮겨졌다는 사실과 사용자가 실행·저장할 수 있다는 사실이 다르다는 점을 배웠습니다. 완료 기준을 단계로 나누자 남은 조건을 숨기지 않고 관리할 수 있었습니다.
아쉬운 점
일부 회귀 검사가 소스 문자열 검사에 머물렀고, 통합 검증 문서에 실패·미판정 항목이 남아 있습니다. 금액 파싱 함수는 세 파일에 중복돼 있고 실패 시 0을 반환합니다.
보완 계획
실제 WAS에서 실행하는 통합 검사로 바꾸고, 금액 파싱을 공통 함수로 합쳐 실패가 드러나게 하는 것이 다음 정리 대상입니다.