본문 바로가기

Server Story..../Windows Server

쿼리의 응답속도가 갑자기 느려지는 경우


 

쿼리의 응답속도가 갑자기 느려지는 경우

평상시에는 이상이 없었는데 어느 날 갑자기 쿼리의 응답속도가 느려지는 경우를 아마 한번쯤은 경험했을 겁니다. 그런 경우 원인은 어떤 것이었나요? 해결은 어떻게 하셨나요? 물론 같은 시간 대에 백업 작업이나 배치 작업이 실행되고 있었다면 당연히 성능상에 영향이 있었을 겁니다. 이런 간단한 경우는 어떻게 해결하면 될까요? 업무량이 많은 시간대에 백업 작업이 실행된다는 것은 아무래도 효율적이지 못하니까 스케줄을 조정해 주는 것도 하나의 방법일 겁니다. 그런데, 그 시간대에 어떤 배치작업이 업무상 반드시 실행되어야 한다면 어떻게 하겠습니까? 만약 SQL Server가 CPU 4개가 작동하는 4-Way 시스템이라고 가정해 보겠습니다.

그렇다면 CPU의“max degree of parallelism”옵션을 4보다 작은 값으로 조정하여 비용이 많이 소모되는 작업을 한다 할지라도 해당 작업이 모든 CPU를 점유하지 않도록 하는 것도 하나의 방법이 될 수 있을 겁니다. 또는 해당 배치를 튜닝하여 부하를 줄이는 것도 방법이 될 수 있습니다.

그러나, 현재 상황은 그와 같은 일이 없다고 가정한 경우입니다.

갑자기 느려진 쿼리를 실행하는 프로세스 외에 이렇다 할 만한 대형 작업이 없는 경우라면 어떻게 해결해야 할까요?

다시, DETECT 방법을 이용해서 점검해보도록 하겠습니다.

첫 번째 Discover 단계는 쿼리의 응답속도가 갑자기 느려졌다는 것을 인지한 상황입니다.

두 번째 Explore 단계는 이와 같은 상황을 보다 명확히 정의해야 하는 작업 입니다. 갑자기 느려지기 전에 어떤 일이 있었는지를 점검해 보도록 하겠습니다. 스케줄을 조사해보니 대량의 배치가 돌아서 상당한 양의 데이터가 새롭게 로딩되었습니다. 월말 배치가 실행되었다는 가정입니다. 약 5천만 행이 있던 테이블에 1천만 행 정도가 추가 되었습니다. 이러한 정보를 바탕으로 다음 단계로 넘어갑니다.

세 번째 단계인 Track down possible approach 단계와 네 번째 단계인 Execute the most likely approach 단계를 통해서 원인이 될 수 있는 사항들을 추측해 보고, 원인이 될 수 있는 각 CASE 별로 가능한 해결방법을 모색해 보도록 하겠습니다.

대략 다음과 같은 사항들이 원일일 가능성이 높다고 할 수 있습니다. 이제 다음의 각 CASE를 통해서 원인을 분석하고 해결점을 도출해 보도록 하겠습니다.

1. 대량의 데이터가 로딩된 후 통계정보가 최신으로 업데이트 되지 않았거나 적절한 샘플링이 되지 않아 실행계획이 적절하지 않다.
2. 인덱스의 단편화가 심하게 발생되어 있다.
3. 현재 작업이 다른 프로세스에 의해 블로킹 당하고 있다.
4. 로그 파일의 파일 증가 설정값이 적절하지 않다.
5. 데이터 파일의 파일 증가 설정값이 적절하지 않다.
6. 현재 작업을 수행하는데 필요한 공간이 tempdb에 충분하게 확보되어 있지 않다.
7. 사용중인 디스크의 사용률이 100%에 근접해 있다.
8. 비정상적인 병렬 작업이 수행된다.
9. 바이러스등에 감염되어 서버의 상태가 불안정하다.
10. 기타 원인

CASE 1. 통계정보가 최신으로 업데이트 되지 않았거나 적절한 샘플링이 되지 않아 실행
              계획이 적절하지 않은 경우
SQL Server는 데이터베이스 옵션으로 통계페이지가 생성되지 않은 경우 자동으로 통계를 생성하고, 자동으로 통계를 최신 상태로 업데이트를 해주는 옵션이 있으며 이것은 기본적으로 활성화되어 있습니다. 그렇지만 대량의 데이터가 로드된 후 즉시 다시 사용하고자 하는 경우 등에는 자동으로 업데이트가 되지 않아서 옵티마이저의 실행계획이 비효율적으로 작성되는 경우가 종종 발생합니다. 따라서, 다음과 같이 통계페이지의 최신 여부와 쿼리의 검색조건으로 지정된 컬럼의 통계페이지가 적절하게 유지 관리되고 있는지 확인해야 합니다.
DBCC SHOW_STATISTICS (테이블_이름, 인덱스_이름)
이와 같은 결과가 출력되는 해당 인덱스에 통계페이지가 생성되지 않은 경우입니다.
통계를 업데이트 한 후 다시 DBCC SHOW_STATISTICS를 실행하면 다음과 같은 결과를 확인할 수 있습니다.
UPDATE STATISTICS 테이블_이름 인덱스_이름
①번이 최근에 통계 정보가 업데이트된 일자입니다.
①번으로 표시된 부분인 updated 항목이 데이터가 대량으로 로딩된 것이 반영된 시점인지 확인해서 통계 정보를 최신으로 유지해야 합니다.

뿐만 아니라 SQL Server는 통계의 분포도를 기록할 때 해당 값(STEP)을 200개 밖에 저장할 수 없고 통계를 수집하는 샘플링 비율에 따라 적정한 분포 정보를 유지하지 못해서 유효한 통계 정보를 생성할 수 없는 경우도 발생할 수 있습니다.

이럴 때는 옵티마이저가 유효한 실행계획을 생성할 수 있도록 샘플링 비율을 적절하게 조정해서 수동으로 통계페이지를 업데이트해야 합니다. 또한 인위적으로 분포의 스텝 값을 지정할 수 없으므로 쿼리에서 최적의 실행계획을 유도하는 옵티마이저 힌트를 사용해야만 하는 경우도 있습니다.

②번으로 표시된 부분이 나타내는 값은 일종의 버그입니다. density는 1보다 작아야 합니다.
위와 같이 잘못된 density 값이 표시될 때에는 WITH FULLSCAN 옵션으로 통계를 업데이트 해야 정상적인 값이 표시됩니다.

<통계 정보의 density 버그 참조 사이트>

http://support.microsoft.com/default.aspx?scid=kb;en-us;299518

통계 정보의 업데이트는 비용 기반 옵티마이저에게 있어서 성능상 가장 중요한 요소 중 하나입니다. 대량의 배치 작업 후에는 반드시 적절한 샘플링 옵션을 지정하여 수동으로 업데이트해야 합니다.
CASE 2. 인덱스의 단편화가 심하게 발생 된 경우
인덱스의 단편화는 넓은 범위의 값을 검색할 때 성능상의 문제를 야기하게 됩니다. 인덱스는 구조상 다음 페이지 주소와 이전 페이지 주소를 저장하는 이중 링크로 구성되어 있으며 다음 페이지를 읽기 위해서는 링크의 정보를 따라 순차적으로 이동하게 됩니다. 따 라서, 특정 범위의 데이터를 포함하고 있는 페이지들이 순서대로 정렬되어 있지 않고 뒤죽 박죽 넓게 퍼져서 단편화가 심하게 발생되었다면 그렇지 않은 경우와 비교하면 모니터링 되는 페이지의 I/O는 동일해도 처리 속도는 느려지게 됩니다.
위와 같은 경우 특정범위 값을 카운트 하는데 약 30초가 걸렸습니다. 이것이 정상적인지를 확인하기 위해 단편화 정도를 점검해 보겠습니다. 단편화 정보를 확인하기 위해 DBCC SHOWCONTIG 명령어를 사용합니다. 테이블의 단편화를 조사해서 다음과 같은 결과를 얻었습니다.
DBCC SHOWCONTIG ( 테이블_이름 , 인덱스_이름 )

테이블: 'tb_m_mmodel_cost_act_Past' (165575628); 인덱스 ID: 1,
데이터베이스 ID: 10
TABLE 수준 스캔이 수행되었습니다.
- 스캔한 페이지................................: 1888100
- 스캔한 익스텐트..............................: 244450
- 전환된 익스텐트..............................: 671143
- 익스텐트 당 평균 페이지 수........................: 7.7
- 스캔 밀도[최적:실제].......: 35.17% [236013:671144]
- 논리 스캔 조각화 상태 ..................: 2.35%
- 익스텐트 스캔 조각화 상태 ...................: 35.57%
- 페이지 당 사용 가능한 평균 바이트 수.....................: 76.7


위에서 실행된 결과를 확인하면, 해당 테이블의 클러스터드 인덱스는 총 1,888,100 개의 페이지로 구성되었고, 페이지 링크를 따라 검색한 결과 익스텐트 전환을 671,143번 실행했습니다. 익스텐트는 8개의 페이지로 구성되어 있으므로 1,888,100개의 페이지라면 1,888,100/8=236,013개의 익스텐트로 구성되고 익스텐트 전환도 236,012번 실행해야 최적인데 익스텐트 전환을 671,143번 했으므로 마치 71,144개의 익스텐트를 가지고 있는 상태와 유사하다고 할 수 있습니다. DBCC DBREINDEX 명령어로 인덱스를 재구성하여 압축한 뒤 다시 단편화 정도를 검사한 결과가 다음과 같습니다.

TABLE 수준 스캔이 수행되었습니다.
- 스캔한 페이지................................: 1888097
- 스캔한 익스텐트..............................: 240140
- 전환된 익스텐트..............................: 240139
- 익스텐트 당 평균 페이지 수........................: 7.9
- 스캔 밀도[최적:실제].......: 98.28% [236013:240140]
- 논리 스캔 조각화 상태 ..................: 0.42%
- 익스텐트 스캔 조각화 상태 ...................: 0.11%
- 페이지 당 사용 가능한 평균 바이트 수.....................: 76.7
- 평균 페이지 밀도(전체).....................: 99.05%


기존에 비해 페이지도 몇 개 감소하고 익스텐트도 완벽하지는 않지만 거의 최적화가 되었습니다. 이와 같이 단편화를 제거한 후 다시 범위 검색 쿼리를 실행하면 다음과 같이 검색속도가 1/2로 상당히 단축되었음을 확인할 수 있습니다. 이와 같이 인덱스 재구성 작업은 단편화를 제거함으로써 검색 속도를 향상시킬 뿐만 아니라 저장공간도 효율적으로 관리할 수 있도록 해 줍니다. 물론, 인덱스를 재구성하는 동안 통계 정보는 100% 샘플링의 비율로 업데이트 되었습니다.
CASE 3. 현재 작업이 다른 프로세스에 의해 블로킹 당하고 있는 경우
현재 실행중인 쿼리가 다른 프로세스가 먼저 걸어놓은 잠금 때문에 대기하고 있는 상태일 수도 있습니다. SQL Server의 기본 잠금 대기 시간은 무한대로 설정되어 있기 때문에 먼저 잠금 을 걸어놓은 프로세스가 종료될 때까지 기다리기 때문에 응답이 지연되는 문제가 발생합니다.

이와 같은 상태를 점검하기 위해서는 sp_who2 시스템 저장 프로시저를 실행해서 BlkBy 컬럼의 값을 확인하거나 sp_lock 시스템 저장 프로시저 등으로 모니터링하는 것도 좋은 방법이고 SQL Server DBA 가이드에서 설명하고 있는 sp_blocker_pss80 저장 프로시저를 사용하는 것도 효율적인 방법입니다. sp_blocker_pss80 저장 프로시저는 아래의 명령을 모두 실행한 결과를 일목요연하게 모니터링할 수 있도록 해 줍니다.

① EXEC sp_who2 (master.dbo.sysprocess 의 정보)
② EXEC sp_lock (master.dbo.syslockinfo 의 정보)
③ DBCC SQLPERF(WAITSTATS)
④ DBCC INPUTBUFFER

다음의 사이트에서 스크립트 소스를 복사하여 사용하기 바랍니다.

<sp_blocker_pss80 저장 프로시저소스 코드 참조 사이트>

http://support.microsoft.com/default.aspx?scid=kb;en-us;271509

<SP_BLOCKER_PSS80 저장 프로시저 실행 결과>
위의 그림은 sp_blocker_pss80 저장 프로시저의 실행 결과 창입니다.

①번 부분에서는 현재 SPID 53은 SPID 52에 의해 블로킹을 당하고 있어 대기하고 있는 상 태임을 보여 주고 있습니다. ②번 부분에서는 SPID 53은 인덱스 키(010086470766)에 공유 잠금(Shared Lock)을 걸기 위해 대기하고 있음을 나타내고 있습니다. ③번 부분은 DBCC SQLPERF(WAITSTATS)의 실행 결과로서 각 잠금의 요청 별로 대기 시간을 나타냅니다.

④번 부분은 DBCC INPUTBUFFER의 실행 결과이며 잠금을 걸고 있거나 블로킹을 당하고 있는 SPID가 실행중인 쿼리 문을 확인해 줍니다.
CASE 4. log file의 설정 값이 적절하지 않은 경우
트랜잭션 로그 파일은 트랜잭션을 시작하기 위해서 그리고, 트랜잭션 로그를 기록하여 트랜잭션의 ACID 속성을 보장하기 위해서 반드시 충분한 공간을 확보하고 있어야 합니다.

트랜잭션 로그가 더 이상 기록될 공간이 없게 되면 아래와 같은 오류 메시지가 반환되고 더 이상의 트랜잭션의 실행은 불가능하게 됩니다.

오류: 9002, 심각도: 17, 상태: 2
'%.*ls' 데이터베이스의 로그 파일이 꽉 찼습니다.


이러한 상황이 발생하지 않도록 DBA는 로그 파일을 적절한 크기로 관리해야 합니다. 뿐만 아니라 로그 파일의 자동 증가 설정을 통해 미처 DBA가 예상하지 못한 경우에 대비해야 합니다. 자동증가 설정이 부적절하면 쿼리의 응답속도가 갑자기 느려지는 현상이 발생할 수 있습니다.

처음 가정에서 대량의 배치가 실행된 직후 라는 가정을 하였습니다. 대량의 변경작업이 수행 되었으므로 당연히 많은 로그 파일 공간을 사용했을 것입니다. 먼저 다음 구문으로 로그 파일의 공간 사용 정보를 확인합니다.
DBCC SQLPERF(LOGSPACE)
만약, 로그 파일의 사용률이 100%에 달했다면 파일증가 속성에 지정된 임계값의 크기로 확장하는 시간 동안 DML이나 DDL과 같은 쿼리의 실행은 대기 상태에 있게 됩니다. 이럴 때 확장 크기가 너무 크다면 확장하는 시간 동안, 너무 작다면 너무 빈번하게 확장을 시도하게 되어 두 경우 모두 쿼리가 대기하게 되므로 응답속도가 느려지는 결과를 초래하게 됩니다.

실제로 DBA의 실수로 로그 파일 증가 속성을 1MB로 지정해놓고 대형 인덱스를 재구성하여 약 1시간 정도면 종료 되어야 하는 작업이 10시간이 넘게 수행되는 경우도 목격하였고, 대형의 배치작업을 수행하다가 트랜잭션 로그 파일이 있는 디스크에 충분한 공간이 있음에도 불구하고 로그가 가득 찼다는 9002 오류를 유발하고 전체 작업이 롤백되는 현상도 목격 하였습니다. 이와 같이 로그 파일의 사용률과 로그 파일의 확장 속성의 지정 여부도 쿼리의 응답속도에 영향을 미칠 수 있으므로 DBA는 항상 로그 파일의 사용률을 모니터링하고 미리 미리 충분한 로그 파일의 공간을 확보해야 합니다.

참고로 다음과 같은 구문으로 Wide-Ultra SCSI3/10,000 RPM의 RAID 1 환경에서 약 200MB를 확장하는데 약 14초 정도가 소요되었습니다.
특히나 대형 테이블의 인덱스 생성 / 재구성 작업이나 대량의 배치작업을 위해서는 대형의 로그 파일이 필요하므로 이와 관련해서는 대용량 작업에서 발생할 수 있는 문제 부분에서 다루도록 하겠습니다.

<트랜잭션 로그 참조 사이트>

http://support.microsoft.com/default.aspx?scid=kb;ko;317375

CASE 5. data file의 설정 값이 적절하지 않은 경우
CASE 4의 경우를 이해하였다면 굳이 추가적인 설명이 필요하지는 않습니다. 단순 SELECT 의 경우라면 데이터 파일에서 추가 공간을 할당 받을 필요가 없지만 DML 작업인 경우에는 데이터 파일의 공간을 필요로 하므로 파일의 사용률과 증가 속성이 중요한 요소가 됩니다.

참고로 다음과 같은 구문을 통해서 로그 파일을 테스트한 동일한 환경에서 500MB의 데이 터 파일을 확장하는 테스트를 한 경우 약 29초의 시간이 소요되었습니다. 따라서, DBA는 자 동 증가 옵션의 설정에 의지해서 데이터 파일과 로그 파일을 방치하게 되면 SQL Server의 응답 속도가 느려지는 문제가 발생하게 됩니다.
CASE 6. 현재 작업에 충분한 tempdb의 공간이 없는 경우
tempdb는 정렬(sort), 그룹핑(group by), 커서 사용, 임시테이블 및 테이블 변수 사용, JOIN 작업, SORT_IN_TEMPDB 옵션을 사용한 인덱스 생성, 데이터베이스의 복구 작업 등에서 사용됩니다. 따라서, 이와 같은 작업을 위해서는 반드시 충분한 tempdb의 공간이 확보되어야 하며, 다중의 사용자가 tempdb를 사용한다면 tempdb의 위치나 파일의 개수, 사이즈 등을 충분히 고려하여 구성하여야 합니다. 즉, DML 작업이 아니더라도 쿼리는 tempdb의 공간을 필요로 할 수 있기 때문에 DBA는 항상 tempdb의 상황을 모니터링하고 관리해야 합니다. tempdb의 공간 사용 정보는 sp_tempdbspace 시스템 저장 프로시저를 통해서 확인 합니다.
tempdb의 I/O 경합을 줄이기 위해서는 SMP 서버의 경우 해당 CPU 개수만큼의 데이터 파일을 동일한 사이즈로 생성할 것을 권장합니다. 그럴 경우 각 CPU를 점유하고 있는 스레드들이 각각 다른 tempdb 데이터 파일을 액세스하므로 I/O의 경합을 줄일 수 있습니다. 뿐만 아니라 추적 플래그 T1118을 사용하면 tempdb가 익스텐트를 할당할 때 다중의 세그먼트가 사용하는 혼합(Mixed) 익스텐트를 할당하지 않고 유니폼(Uniform) 익스텐트만을 할당하므로 추가적으로 IO의 경합을 감소시킬 수 있습니다. 단, T1118 추적 플래그는 SQL Server 7.0에서는 사용을 삼가합니다.

<tempdb 성능 관련 참조 사이트>

http://support.microsoft.com/kb/328551

CASE 7. 사용중인 디스크의 사용률이 100%에 근접한 경우
하드디스크의 경우 사용률이 전체 공간대비 약 85% 대에 이르면 불필요한 큐잉(queuing)을 유발할 수 있습니다. 따라서, 데이터의 증가에 대한 사이징을 미리 하셔서 매년 사업계획을 작성할 때 반드시 예산을 확보해야 합니다.
CASE 8. 비정상적인 parallel 작업이 수행 되는 경우
앞에서 다룬 SQL Server와 연결이 되지 않는 경우의 CASE 4 에서 다루었던 부분이기도 합니다. 마이크로소프트의 기술 문서에서 확인하면 다양한 경우에 스레드가 과도하게 할당되어 느려지거나 추가적인 스레드 할당을 하지 못하고 17884 오류를 발생하는 경우가 있습니다. 필자의 판단이지만 Hyper-Threading을 지원하는 SMP 서버에서 통계 페이지를 업데이트 하는 과정이나 대량의 DML작업에서도 비정상적으로 스레드의 개수를 늘리는 경우가 모니터링 되곤 합니다. 이런 경우에는 스레드의 개수가“max worker threads”옵션의 현재 구성 값에 도달해서 장시간 대기하다가 교착상태로 종결되는 경우도 있고, 교착상태를 발생시키지 않고 응답속도만 느려지는 경우도 있습니다. 비정상적으로 스레드의 개수가 늘어나는 현상을 모니터링 하기 위해서는“max worker threads”를 충분한 개수로 조정해야 가능합니다. 사용자 connection의 정보는 성능 모니터의 SQL Server : General Statistics : User connections 카운터를 통해서 모니터링 할 수 있고, 활성화된 스레드의 정보는 다음과 같은 쿼리로 증가하는 상황을 확인할 수 있습니다.
<5초마다 sp_who2 저장 프로시저를 실행하는 쿼리>
<대량의 INSERT 작업 중 과도하게 THREAD를 확장해가는 초기 단계>
좌측의 표는 8개의 CPU를 가진 서버가 INSERT 작업을 실행하면서 과도하게 스레드를 할당 하는 초기 단계를 sp_who2 시스템 저장 프로시저를 통해서 모니터링한 결과입니다. 이와 같은 경우 마이크로소프트가 제공하는 핫픽스를 설치하여 해결되는지 여부를 확인합니다. 핫픽 스로 해결되지 않을 경우 임시적이기는 하지만“max degree of parallelism”서버 옵션을 물리적인 CPU 의 개수 -1 정도의 값을 설정하는 방법도 고려합니다. 상당기간이 흐른 현재까지 동일한 문제가 재발하고 있지 않습니다. 쿼리에서 OPTION (MAXDOP n ) 절을 사용하는 방법도 확인해보도록 합니다.
CASE 9. 바이러스 등에 감염되어 서버의 상태가 불안정한 경우
시스템이 바이러스에 감염된 경우에는 시스템 자체에 과부하가 걸려서 이상 현상을 나타내기도 하며 SQL Server 웜 바이러스 같은 바이러스 공격을 받는 경우에 쿼리의 응답속도가 느려지는 현상이 생기기도 합니다. 따라서, 윈도우즈 서버나, SQL Server의 보안 패치는 테스트 후 즉시, 서비스 팩도 테스트 실시 후 빠른 시간 내에 반영하도록 권장합니다. 뿐만 아니라 서버용 바이러스 백신을 설치하고 정기적으로 검사함으로써 서버를 더욱 안전하고 정상적인 상태로 유지할 수 있습니다. 단, SQL Server에 바이러스 백신을 설치하고 검사하는 작업의 결과가 예상하지 못한 오류를 발생하거나 SQL Server에 치명적인 결과를 초래할 수도 있습니다.
<바이러스에 감염된 경우>
따라서, 바이러스 백신 프로그램이 SQL Server에 적합한 것인지를 다음의 사이트에서 확인하고 해당 백신 판매업체와 충분히 상담하여야 합니다.

http://www.microsoft.com/security/partners/antivirus.asp

또한, SQL Server에서 바이러스 감염 여부를 검사할 때 발생할 수 있는 문제에 대해서도 사전 검토가 필요합니다. 다음의 사이트에서 SQL Server에서 바이러스를 검사하는 경우 발생할 수 있는 문제와 주의사항에 대해 설명하고 있습니다.

http://support.microsoft.com/?kbid=309422

시스템이 바이러스에 감염된 경우 외에도 설치된 응용 프로그램이나 하드웨어 드라이버 등의 문제가 운영체제를 불안정하게 하거나 많은 리소스를 사용하여 시스템 전체를 느리게 할 수도 있습니다. 이런 경우 문제가 되는 응용 프로그램이나 하드웨어 드라이버 등을 중심으로 점검하고, 정확한 진단과 해결이 어려운 경우에는 다음의 사이트를 참조하여 메모리 덤프를 생성해서 마이크로소프트 기술지원센터에 문의합니다.

<메모리 덤프 생성 참조 사이트>

http://support.microsoft.com/default.aspx?scid=kb;ko;244139

쿼리의 응답속도가 갑자기 느려지는 아홉 가지 경우를 살펴보았습니다. 지금까지 살펴본 이유 외에도 여러 가지가 쿼리의 응답속도가 갑자기 느려지는 원인이 될 수도 있습니다. 위에서 나열한 여러 가지 경우들 중에서 원인과 해결방법을 찾았더라도 반드시 나머지의 경우도 점검을 하도록 합니다. 여러 가지 문제가 복합적으로 작용해 원인이 될 수도 있고 지금은 장애의 원인으로 나타나지는 않았지만 어느 정도 지금의 상태가 지속된다면 또 다시 갑자기 쿼리의 응답속도가 느려지는 상황을 유발할 가능성이 잠재되어 있을 수도 있기 때문입니다.

다섯 번째 단계인 Check for Success를 수행하셨다면 마지막으로 Tie up loose ends 단계를 실시함으로써 확실한 마무리를 해야 합니다. 다시 한번 미비한 점은 없는지 살펴 보고 인터넷으로 관련 자료를 수집해 여러분이 처리한 해결방법과 비교해 보는 것도 좋은 방법입니다. 끝으로 조치한 사항에 대해서 다음과 같이 오류 발생 일지를 작성하고 일지의“주의 및 확인사항”항목에 기록된 대로 수시로 관련 자료의 유무를 확인한다면 아주 깔끔한 마무리라 할 수 있습니다.