seminar/레거시 서비스PHP프로파일링.md 추가
This commit is contained in:
@@ -0,0 +1,262 @@
|
|||||||
|
# 장헌 7개 서비스 PHP·SQL 프로파일링 세미나
|
||||||
|
|
||||||
|
대상: A팀 기술회의
|
||||||
|
측정일: 2026-07-31
|
||||||
|
환경: 정상 환경과 분리한 `jang-profile`, PHP 8.4.23, Xdebug 3.5.3,
|
||||||
|
MySQL 8.4 Performance Schema
|
||||||
|
|
||||||
|
## 1. 오늘 확인할 질문
|
||||||
|
|
||||||
|
1. 화면이 열린다는 사실과 기능이 정상이라는 사실을 어떻게 구분하는가?
|
||||||
|
2. 평균 응답시간 뒤에 숨은 느린 PHP 함수와 SQL을 측정하는가?
|
||||||
|
3. 권한차단·외부의존·데이터부재를 실제 실패와 구분하는가?
|
||||||
|
4. 쓰기 테스트 후 DB와 합성 데이터가 원상태인지 확인하는가?
|
||||||
|
5. 양 팀이 배포 전후 동일한 측정 기준을 사용할 수 있는가?
|
||||||
|
|
||||||
|
발표 메모:
|
||||||
|
|
||||||
|
> 이번 결과는 단순 화면 캡처가 아닙니다. 계정, 서비스, 메뉴, 기능,
|
||||||
|
> DB 변화, PHP 함수와 SQL을 서로 연결해 본 결과입니다.
|
||||||
|
|
||||||
|
## 2. 측정 환경과 안전장치
|
||||||
|
|
||||||
|
- 정상 환경: `jang-p12-auto-r10`, `127.0.0.1:18091`
|
||||||
|
- 프로파일 환경: `jang-profile`, `127.0.0.1:18092`
|
||||||
|
- 별도 웹·DB·세션·첨부파일·로그·프로파일 볼륨 사용
|
||||||
|
- 원본 DB를 읽기 전용 덤프로 복제
|
||||||
|
- 원본과 복제본 모두 DB 객체 462개, 뷰 13개
|
||||||
|
- 평상시 Xdebug 비활성, 지정 트리거 요청만 프로파일링
|
||||||
|
- 정상 환경과 프로파일 환경 모두 최종 `healthy`
|
||||||
|
|
||||||
|
발표 메모:
|
||||||
|
|
||||||
|
> 운영과 비슷한 데이터를 사용하되 테스트 쓰기는 복제 DB에만
|
||||||
|
> 발생하도록 분리했습니다. 프로파일러는 모든 요청에 켜지 않았습니다.
|
||||||
|
|
||||||
|
## 3. 계정·서비스·메뉴·기능 범위
|
||||||
|
|
||||||
|
| 측정 축 | 실행 수 | 결과 |
|
||||||
|
| --- | ---: | --- |
|
||||||
|
| 7계정 × 7서비스 대표 접근 | 49 | 정상 46, 권한차단 3 |
|
||||||
|
| 승인 역할 × 실제 메뉴 조회 | 135 | 정상 128, 의존 6, 데이터부재 1 |
|
||||||
|
| 서비스별 쓰기·권한·DB정리 | 7시나리오×2회 | 14/14 통과 |
|
||||||
|
| 전체 통합 매트릭스 | 191행 | 실패 0 |
|
||||||
|
|
||||||
|
주의:
|
||||||
|
|
||||||
|
- 7계정으로 135개 메뉴를 각각 실행한 945건 완전 교차 검사는 아니다.
|
||||||
|
- 49개 대표 접근으로 계정의 서비스 진입을 확인했다.
|
||||||
|
- 135개 메뉴는 서비스별 승인 역할로 확인했다.
|
||||||
|
- 메뉴별 타 역할 권한은 추가 확인 범위다.
|
||||||
|
|
||||||
|
발표 메모:
|
||||||
|
|
||||||
|
> 숫자를 부풀리지 않기 위해 대표 접근과 메뉴 탐색을 분리했습니다.
|
||||||
|
> 현재 확정 가능한 범위와 아직 측정하지 않은 범위를 같은 표에 둡니다.
|
||||||
|
|
||||||
|
## 4. 결과 분류
|
||||||
|
|
||||||
|
| 분류 | 건수 | 의미 |
|
||||||
|
| --- | ---: | --- |
|
||||||
|
| 정상 | 181 | 기대한 인증·조회·쓰기 경계·정리 통과 |
|
||||||
|
| 권한차단 | 3 | 비인사 역할의 인사관리 로그인 거부 |
|
||||||
|
| 외부 라이브러리 의존 | 3 | jspreadsheet, Google Maps, Summernote |
|
||||||
|
| 부모 실행문맥 의존 | 3 | 부모 프레임·선행 화면 없이 단독 실행 불가 |
|
||||||
|
| 데이터부재 | 1 | 선행 선택 전 빈 출하 목록 |
|
||||||
|
| 실패 | 0 | HTTP·기능 실패 없음 |
|
||||||
|
|
||||||
|
발표 메모:
|
||||||
|
|
||||||
|
> 권한이 막힌 것을 실패라고 세지 않았고, 데이터가 없는 화면도
|
||||||
|
> 프로그램 오류와 분리했습니다. 부모 프레임이 필요한 화면 역시
|
||||||
|
> 외부 장애와 구분했습니다.
|
||||||
|
|
||||||
|
## 5. 기능별 DB 변경 전후
|
||||||
|
|
||||||
|
- 인트라넷 일정 합성 등록·권한차단·삭제: 잔여 0
|
||||||
|
- 공장 공통코드 합성 등록·수정·삭제: 잔여 0
|
||||||
|
- 인사 탄력근무 합성 등록·수정·삭제: 잔여 0
|
||||||
|
- 사업 기초코드 합성 등록·수정·삭제: 잔여 0
|
||||||
|
- 회계 계정코드 합성 등록·수정·삭제: 잔여 0
|
||||||
|
- 가상야적장 익명 쓰기 차단: 핵심 DB 행 수 불변
|
||||||
|
- 터치스크린 쓰기·배치 7개 진입점 차단: DB 스냅샷 불변
|
||||||
|
|
||||||
|
발표 메모:
|
||||||
|
|
||||||
|
> 쓰기 성공만 확인한 것이 아니라 테스트 종료 후 잔여와 핵심 테이블
|
||||||
|
> 불변까지 확인했습니다. 운영 데이터를 흉내 낸 값은 남기지 않았습니다.
|
||||||
|
|
||||||
|
## 6. 서비스별 대표 응답시간
|
||||||
|
|
||||||
|
워밍업 2회 후 일반 요청 5회의 로컬 단일 요청 결과:
|
||||||
|
|
||||||
|
| 서비스 | p50 | p95 | 최대 |
|
||||||
|
| --- | ---: | ---: | ---: |
|
||||||
|
| intranet | 4.627ms | 5.882ms | 5.882ms |
|
||||||
|
| factory_mng | 11.087ms | 11.850ms | 11.850ms |
|
||||||
|
| person_mng | 3.202ms | 3.789ms | 3.789ms |
|
||||||
|
| projt_mng | 13.893ms | 14.488ms | 14.488ms |
|
||||||
|
| account | 4.830ms | 5.262ms | 5.262ms |
|
||||||
|
| virtual_yard | 16.632ms | 18.006ms | 18.006ms |
|
||||||
|
| factory_board | 11.730ms | 12.777ms | 12.777ms |
|
||||||
|
|
||||||
|
해석:
|
||||||
|
|
||||||
|
- 현재 대표 화면에서 절대 응답시간은 짧다.
|
||||||
|
- 브라우저 전체 렌더링, 외부 자원, 대량 동시성 결과와 동일하지 않다.
|
||||||
|
- 표본이 작으므로 운영 SLA나 용량 결론으로 사용하지 않는다.
|
||||||
|
|
||||||
|
## 7. Xdebug 측정 방식과 오버헤드
|
||||||
|
|
||||||
|
- 서비스별 일반 요청 5회
|
||||||
|
- 서비스별 Xdebug 요청 3회
|
||||||
|
- 고유 Cachegrind 21개
|
||||||
|
- 파일명에 마이크로초 `%u`를 사용해 덮어쓰기 방지
|
||||||
|
|
||||||
|
| 서비스 | 일반 p50 | 프로파일 중앙값 | 관측 배수 |
|
||||||
|
| --- | ---: | ---: | ---: |
|
||||||
|
| intranet | 4.627ms | 5.108ms | 1.104x |
|
||||||
|
| factory_mng | 11.087ms | 11.320ms | 1.021x |
|
||||||
|
| person_mng | 3.202ms | 3.505ms | 1.095x |
|
||||||
|
| projt_mng | 13.893ms | 14.766ms | 1.063x |
|
||||||
|
| account | 4.830ms | 4.997ms | 1.035x |
|
||||||
|
| virtual_yard | 16.632ms | 16.547ms | 0.995x |
|
||||||
|
| factory_board | 11.730ms | 11.675ms | 0.995x |
|
||||||
|
|
||||||
|
발표 메모:
|
||||||
|
|
||||||
|
> 1배 미만은 프로파일러가 성능을 높였다는 뜻이 아니라 작은 표본의
|
||||||
|
> 변동입니다. Cachegrind의 함수 순위에는 사용할 수 있지만 운영
|
||||||
|
> 오버헤드 결론에는 더 많은 반복이 필요합니다.
|
||||||
|
|
||||||
|
## 8. 느린 PHP 함수 Top
|
||||||
|
|
||||||
|
서비스별 프로파일 3회 합계 self time:
|
||||||
|
|
||||||
|
| 순위 | 서비스 | 함수 | self time |
|
||||||
|
| ---: | --- | --- | ---: |
|
||||||
|
| 1 | virtual_yard | `mysqli_real_connect` | 22.412ms |
|
||||||
|
| 2 | projt_mng | `mysqli_query` | 13.118ms |
|
||||||
|
| 3 | factory_mng | `mysqli_query` | 9.878ms |
|
||||||
|
| 4 | projt_mng | `mysqli_real_connect` | 7.223ms |
|
||||||
|
| 5 | factory_mng | `mysqli_real_connect` | 6.309ms |
|
||||||
|
| 6 | virtual_yard | `mysqli_set_charset` | 4.391ms |
|
||||||
|
| 7 | account | `mysqli_real_connect` | 2.753ms |
|
||||||
|
| 8 | projt_mng | Smarty compiled process | 2.103ms |
|
||||||
|
|
||||||
|
해석:
|
||||||
|
|
||||||
|
- 대표 요청에서는 DB 연결·쿼리 비용이 우선 관찰 대상이다.
|
||||||
|
- 그다음은 Smarty 컴파일 결과 처리와 렌더링이다.
|
||||||
|
- 지속 연결 적용 여부는 효과뿐 아니라 세션·장애 복구를 함께 검증해야 한다.
|
||||||
|
|
||||||
|
## 9. 느린 SQL Top
|
||||||
|
|
||||||
|
Performance Schema digest 초기화 후 7개 대표 화면을 5회 반복:
|
||||||
|
|
||||||
|
| 순위 | 유형 | 호출 | 총시간 | 평균 | 최대 | 검사행 |
|
||||||
|
| ---: | --- | ---: | ---: | ---: | ---: | ---: |
|
||||||
|
| 1 | 근태 집계 | 155 | 45.939ms | 0.296ms | 0.422ms | 18,755 |
|
||||||
|
| 2 | 출퇴근 조회 | 155 | 22.894ms | 0.148ms | 0.227ms | 0 |
|
||||||
|
| 3 | 팝업 공지 조회 | 5 | 17.613ms | 3.523ms | 3.924ms | 12,925 |
|
||||||
|
| 4 | 가상야적장 상태 조회 | 5 | 13.174ms | 2.635ms | 2.898ms | 9,980 |
|
||||||
|
| 5 | 시스템 설정 조회 | 15 | 11.158ms | 0.744ms | 0.904ms | 10,185 |
|
||||||
|
|
||||||
|
관찰:
|
||||||
|
|
||||||
|
- 팝업 공지와 가상야적장 상태 조회는 각 5회 모두 no-index가 기록됐다.
|
||||||
|
- 근태 집계는 절대시간은 짧지만 호출 155회와 no-index 155회다.
|
||||||
|
- 즉시 인덱스를 추가하지 않고 `EXPLAIN`과 데이터 증가 조건을 확인한다.
|
||||||
|
|
||||||
|
## 10. 발견 후 보정한 PHP 경고
|
||||||
|
|
||||||
|
- 관리자 계정의 사업관리 홈에서만 재현
|
||||||
|
- 비활성 화면이 HTML 주석 안에 있었지만 Smarty는 내부 변수를 컴파일
|
||||||
|
- `Undefined array key` 18건
|
||||||
|
- 연쇄 null 속성 접근 18건
|
||||||
|
- 합계 36건, HTTP 응답은 200
|
||||||
|
|
||||||
|
보정:
|
||||||
|
|
||||||
|
- 공통 홈 렌더링 전에 비활성 화면 변수의 빈 기본값을 지정
|
||||||
|
- 문서 조회 함수에도 조회 결과 0건 기본값을 지정
|
||||||
|
- 사업관리 7계정 재검사: 7/7 HTTP 200, PHP Warning 0
|
||||||
|
- 7개 서비스 대표 회귀: 7/7 HTTP 200, PHP 오류 0
|
||||||
|
|
||||||
|
판정: 즉시 수정 완료, 프로파일 환경 검증 완료
|
||||||
|
|
||||||
|
## 11. 조치 분류
|
||||||
|
|
||||||
|
### 즉시 수정
|
||||||
|
|
||||||
|
- 현재 확인된 HTTP·기능 실패는 0건
|
||||||
|
- 사업관리 관리자 조건 Warning 36건 보정 및 회귀 완료
|
||||||
|
|
||||||
|
### 추가 확인
|
||||||
|
|
||||||
|
- 공지·가상야적장 SQL 실행계획과 복합 인덱스 후보
|
||||||
|
- 근태 쿼리 155회 호출의 중복 제거 가능성
|
||||||
|
- jspreadsheet·Google Maps·Summernote 로딩 정책
|
||||||
|
- 부모 프레임 의존 화면의 실제 메뉴 진입 검사
|
||||||
|
- 데이터부재 화면의 합성 기준 데이터
|
||||||
|
- 메뉴별 타 역할 권한 완전 교차가 필요한 범위
|
||||||
|
|
||||||
|
### 현행 유지
|
||||||
|
|
||||||
|
- 46개 정상 계정·서비스 대표 접근
|
||||||
|
- 128개 정상 메뉴 조회
|
||||||
|
- 14회 쓰기·권한·정리 결과
|
||||||
|
- 정상 환경에서 Xdebug 비활성 정책
|
||||||
|
|
||||||
|
## 12. A팀에 묻는 비교 질문
|
||||||
|
|
||||||
|
1. 서비스별 p50·p95·p99와 최대를 측정하는가?
|
||||||
|
2. 워밍업, 데이터 조건, 반복 횟수, 동시성을 고정하는가?
|
||||||
|
3. PHP 함수별 self·inclusive time과 호출 횟수를 보는가?
|
||||||
|
4. SQL digest별 총·평균·최대시간과 rows examined를 보는가?
|
||||||
|
5. no-index와 임시 디스크 테이블을 배포 전후 비교하는가?
|
||||||
|
6. OPcache hit/miss와 메모리 고갈을 감시하는가?
|
||||||
|
7. 계정×서비스×메뉴×기능 권한표가 있는가?
|
||||||
|
8. 쓰기 테스트 전후 DB 변화와 합성 잔여 0을 확인하는가?
|
||||||
|
9. 권한차단·외부의존·데이터부재를 실패와 구분하는가?
|
||||||
|
10. 프로파일 산출물의 크기 제한·보관·폐기 기준이 있는가?
|
||||||
|
11. 운영에서 프로파일러를 활성화할 때 승인과 종료 조건이 있는가?
|
||||||
|
12. 양 팀이 같은 시나리오로 배포 전후 회귀 비교할 수 있는가?
|
||||||
|
|
||||||
|
## 13. 회의에서 합의할 제안
|
||||||
|
|
||||||
|
- 공통 결과 분류 코드와 증적 형식
|
||||||
|
- 대표 시나리오·테스트 계정·합성 데이터 규칙
|
||||||
|
- p50·p95·p99·최대와 SQL digest 기본 항목
|
||||||
|
- PHP·SQL Top N 산출 기준
|
||||||
|
- 프로파일러 운영 활성화 금지 또는 승인 절차
|
||||||
|
- 합성 데이터 접두어와 종료 후 잔여 0 원칙
|
||||||
|
- 배포 전후 동일 시나리오 비교와 결과 보관 기간
|
||||||
|
|
||||||
|
## 14. 결론
|
||||||
|
|
||||||
|
- 7개 서비스는 현재 대표 접근·조회·쓰기 경계에서 실제 실패 0건이다.
|
||||||
|
- 권한차단·의존·데이터부재를 실패와 분리했다.
|
||||||
|
- DB 변경 후 합성 잔여 0 또는 스냅샷 불변을 확인했다.
|
||||||
|
- PHP 병목 후보는 DB 연결·쿼리와 Smarty 렌더링이다.
|
||||||
|
- SQL 확장 위험 후보는 팝업 공지, 가상야적장, 반복 근태 집계다.
|
||||||
|
- 다음 기술 작업은 SQL `EXPLAIN` 비교와 의존 화면 실제 진입 검증이다.
|
||||||
|
|
||||||
|
발표 마무리:
|
||||||
|
|
||||||
|
> A팀이 이미 같은 항목을 측정하고 있다면 도구 이름보다 결과 형식을
|
||||||
|
> 맞추는 것이 중요합니다. 측정하지 않는 항목이 있다면 이번 장헌
|
||||||
|
> 매트릭스와 프로파일 결과를 공통 출발점으로 제안합니다.
|
||||||
|
|
||||||
|
## 증적 위치
|
||||||
|
|
||||||
|
- 통합 매트릭스:
|
||||||
|
`docs/evidence/p12/uat/2026-07-31_account-service-menu-function-matrix.csv`
|
||||||
|
- 응답시간:
|
||||||
|
`data/test-artifacts/profile-20260731-unique/seven-service-profile/`
|
||||||
|
- PHP 함수:
|
||||||
|
`data/test-artifacts/profile-20260731-unique/cachegrind-analysis/`
|
||||||
|
- SQL digest:
|
||||||
|
`data/test-artifacts/profile-20260731-unique/sql-analysis/digest-top.tsv`
|
||||||
|
- 진행 관리:
|
||||||
|
`new-pc-development-setup-stabilization.md`
|
||||||
Reference in New Issue
Block a user