Skip to content
isdnetworks
Go back

소스에서 거꾸로 스키마를 그렸다

인계받은 시스템에 DB 문서가 없었다. 테이블이 140개였다.

Table of contents

Open Table of contents

상황 — 문서가 없었다

DESC 로 표를 하나씩 볼 수는 있었다.

tb_enroll
  enr_no     int
  st_no      int
  cs_no      int
  st_cd      char(2)
  reg_dt     datetime

st_nost_cd 가 무엇인지 몰랐다.

st_nost_cd 가 접두사는 같은데 하나는 번호고 하나는 코드였다. 컬럼 이름만으로는 무엇을 담는 자리인지 알 수 없는 것이 대부분이었다.

검증 — 코드에서 찾았다

tb_enroll 을 다루는 코드를 grep 으로 찾았다.

$enroll = [
    'st_no' => $student->no,
    'cs_no' => $course->no,
    'st_cd' => 'AP',   // 승인 대기
];

st_no 는 수강생 번호이고 st_cd 는 상태 코드였다.

$student->no'AP' 가 각각 다른 성격이었다. 값의 종류도 모아 봤다.

$ grep -rn "st_cd" --include=*.php app/ | grep -o "'[A-Z]\{2\}'" | sort -u
'AP'
'CF'
'CN'
'DN'

APCFCNDN 이 나왔고 문맥에서 뜻을 찾았다.

대응 — 화면에서 찾은 실제 뜻

코드로 안 나오는 것은 화면 쪽 statusLabel 에서 봤다.

$statusLabel = ['AP' => '승인대기', 'CF' => '수강중', 'CN' => '취소', 'DN' => '수료'];

DN 은 완료가 아니라 수료였다.

코드만 보면 짐작이고 화면을 봐야 실제 뜻이 나온다. 화면에도 안 나오는 컬럼은 모르는 것으로 적어 뒀는데 억지로 짐작해 적으면 그것이 나중에 잘못된 근거가 된다.

전체 흐름 — 관계 찾기와 확인

외래키가 하나도 없어서 관계가 안 보였다.

$ grep -rnE "join .*tb_[a-z_]+ .* on" --include=*.php app/ | grep -oE "on [a-z_.]+ *= *[a-z_.]+" | sort -u

조인 조건을 모으니 관계가 그려졌다.

tb_enroll.st_no  = tb_student.st_no
tb_enroll.cs_no  = tb_course.cs_no
tb_course.ct_no  = tb_category.ct_no

코드에서 JOIN 하는 것이 실제 관계이고 문서에 있을 관계보다 정확하다.

찾은 관계가 맞는지 데이터로 확인했다.

SELECT COUNT(*) FROM tb_enroll e
LEFT JOIN tb_student s ON e.st_no = s.st_no
WHERE s.st_no IS NULL;
412

tb_student 에 대응이 없는 것이 412건 남아 있었다.

관계는 맞는데 데이터가 깨져 있는 것이었다. 지워진 수강생의 수강 기록이 남은 것이라 그 사실까지 문서에 함께 적었다.

결과 — 문서로 만든 것

그려 낸 것을 표 하나로 정리했다.

[tb_enroll] 수강 신청

  enr_no  int       수강신청 번호   PK, 자동 증가
  st_no   int       수강생 번호     → tb_student.st_no (FK 없음)
  cs_no   int       과정 번호       → tb_course.cs_no (FK 없음)
  st_cd   char(2)   상태            AP/CF/CN/DN
  reg_dt  datetime  신청일시

상태 코드
  AP 승인대기 / CF 수강중 / CN 취소 / DN 수료

주의
  외래키가 없어 대응하지 않는 st_no 가 412건 있다 (2019-06 기준)
  st_no 와 st_cd 는 접두사가 같지만 다른 것을 가리킨다

주의 항목이 가장 쓸모 있었다.

컬럼 이름과 타입은 DESC 로 바로 볼 수 있지만 이런 것은 조사하지 않으면 안 나온다. 다음 사람이 같은 데서 헷갈리지 않게 하는 것이 그 항목이었다.

판단 기준 — 그리는 순서

tb_ 로 시작하는 140개를 다 그리는 데는 오래 걸린다.

1. 자주 건드리는 것 (코드에서 참조 횟수)
2. 관계의 중심에 있는 것 (조인에 자주 나오는 것)
3. 나머지

참조 횟수는 grep 으로 세어서 정했다.

$ grep -rohE "tb_[a-z_]+" --include=*.php app/ | sort | uniq -c | sort -rn | head -20

상위 20개가 참조의 대부분이라 그것부터 그렸다.

두 달에 걸쳐 60개를 그렸고 나머지는 필요해질 때 그리기로 미뤘다. 전부 하려고 들면 끝나기 전에 앞부분이 이미 낡는다.

정리


Share this post on:

Previous Post
등록은 롤백되고 수정은 안 된다
Next Post
외부 시스템의 성공 응답을 그대로 믿지 않게 된 이유