애플리케이션 성능·품질 분석과 최적화
성능 테스트와 품질분석 도구를 구분하고 프로그램의 동작을 유지하며 병목과 불필요한 연산을 줄인다.
비기능 테스트와 성능 지표
비기능 테스트는 성능·신뢰성·사용성·보안성처럼 시스템의 품질을 확인한다. 요구사항은 ‘빠르다’보다 ‘동시 사용자 500명에서 평균 응답시간 2초 이하’처럼 관측 조건과 기준을 함께 정한다.
| 지표 | 의미 |
|---|---|
| 응답시간 | 요청부터 응답 완료까지의 시간 |
| 처리량 | 단위 시간에 처리한 요청·작업 수 |
| 오류율 | 전체 요청 중 실패한 비율 |
| 자원 사용률 | CPU·메모리·디스크·네트워크의 사용 정도 |
응답시간만 낮아도 오류가 많거나 자원 한계를 넘으면 요구 품질을 충족했다고 볼 수 없다. 사용성은 대상 사용자의 과업 성공률·오류·소요 시간·만족도 등으로 평가한다.
성능 테스트 유형과 환경
| 유형 | 확인할 내용 |
|---|---|
| 부하 | 예상되는 정상 부하에서 성능 목표 충족 여부 |
| 스트레스 | 한계를 넘는 부하에서의 실패와 복구 |
| 스파이크 | 짧은 시간의 급격한 부하 증가에 대한 반응 |
| 내구성 | 장시간 실행 중 누수·성능 저하 |
| 용량 | 처리 가능한 사용자·데이터·작업 규모 |
운영체제·DBMS·설정·서버 사양과 데이터 양·분포를 기록한다. 정상값·경계값·오류값을 준비하고 테스트 간 상태를 격리한다. 일시적인 재시도 통과만으로 간헐적 결함이 해결됐다고 판단하지 않는다.
확인 테스트와 회귀 테스트
확인 테스트는 보고된 결함이 수정되었는지 다시 확인한다. 회귀 테스트는 변경으로 기존 기능에 새로운 오류가 생겼는지 확인한다. 영향 범위에는 변경 모듈뿐 아니라 직접·간접 호출 관계, 공통 기능과 인터페이스도 포함한다.
소스코드 품질분석 도구
| 분석 | 방식과 예 |
|---|---|
| 정적 분석 | 실행하지 않고 코드 규칙 위반·결함 후보를 조사. Checkstyle, PMD 등 |
| 동적 분석 | 실행 중 메모리·자원·동작을 조사. Valgrind의 Memcheck 등 |
| 프로파일링 | 실행시간·호출 횟수 등을 계측하여 병목 구간을 조사 |
프로파일의 자체 시간(self time)은 함수 자신의 실행시간이며, 포함 시간은 하위 함수 호출까지 포함한다. 부모와 자식의 포함 시간을 더하면 중복 계산할 수 있다. 초기화되지 않은 변수 사용과 도달 불가능한 코드는 소스 검토에서 확인할 대표 항목이다.
동작을 보존하는 코드 최적화
| 기법 | 적용 조건 |
|---|---|
| 공통 부분식 제거 | 피연산자가 바뀌지 않는 구간의 같은 계산을 재사용 |
| 루프 불변식 이동 | 반복 중 값이 바뀌지 않고 부작용이 없는 계산을 밖으로 이동 |
| 강도 감소 | 같은 결과를 내는 더 저렴한 연산으로 대체 |
| 불필요한 코드 제거 | 실행되지 않거나 결과에 영향이 없는 코드를 제거 |
| 자료구조·알고리즘 개선 | 전체 입력과 처리량에 맞춰 시간·공간 비용을 줄임 |
리팩터링은 관찰 가능한 동작을 유지하면서 내부 구조를 개선하는 작업이다. 업무 규칙이나 오류 정책을 바꾸는 기능 변경과 구분한다. 최적화에서도 반환값·예외·부작용을 보존해야 한다. 정수 나눗셈의 버림이나 단락 평가의 순서를 무시하면 결과가 달라질 수 있다.
반복 조회에 캐시를 쓰면 결과를 결정하는 입력을 키에 포함하고 원본 변경 시 갱신·무효화한다. 전처리 비용과 추가 메모리도 함께 고려한다. 한 구간만 개선하면 나머지 구간의 시간은 남으므로 전체 개선량을 다시 계산·측정한다.