# QA 체크리스트

최종 수정일: 2026-08-10

기능 구현 시 해당 섹션을 복사하거나 항목을 추가해 계속 확장합니다. 민감정보가 포함된 화면 캡처와 로그는 저장소에 넣지 않습니다.

## 실행 기록 템플릿

| 항목 | 기록 |
| --- | --- |
| 실행일 | YYYY-MM-DD |
| 담당자 |  |
| 환경 | 로컬 / Cafe24 기본 도메인 / 운영 도메인 |
| URL |  |
| 브라우저·기기 |  |
| 배포 버전 |  |
| 결과 | 통과 / 조건부 통과 / 실패 |
| 증빙 | 안전한 스크린샷 또는 이슈 링크 |

## 1. 임시 페이지

- [x] 로컬에서 HTML 정상 표시
- [x] 외부 CSS, 폰트, 이미지 의존성 없음
- [x] 390px 모바일에서 가로 스크롤 없음
- [x] 전화 링크의 번호와 표시 문구 확인
- [x] 검색엔진 `noindex, nofollow` 적용
- [x] Cafe24 기본 도메인에서 HTTPS 200 응답
- [x] 운영 도메인에서 로컬 원본과 동일한 콘텐츠 표시
- [x] Cafe24 기본 도메인 HTTPS에서 보안 경고 없음
- [x] 로고와 저작권에 `(주)지티에스정보통신` 표시
- [ ] 모바일 실기기에서 전화 링크 동작

## 2. 배포 및 서버

- [x] 현재 등록된 SSH 인증키를 다시 내려받아 로컬 키 지문 비교
- [x] 서버에 등록된 키로 SSH 로그인 성공
- [x] 실제 웹 루트와 업로드 경로 확인
- [x] 기존 파일 백업 후 배포
- [ ] 디렉터리 목록 노출 차단
- [ ] 불필요한 설정, 백업, 로그 파일의 웹 접근 차단
- [ ] 404 및 500 오류 응답 확인
- [x] 임시 `index.html` 파일 권한 `640` 적용
- [x] 웹 루트에 `Options -Indexes` 적용
- [ ] 배포 후 오류 로그에 신규 치명 오류 없음

테스트 배포 기록: 2026-08-04 `https://gtsit.co.kr/site-preview-7c2a91f4/`에 본 사이트를 별도 라우팅했습니다. 홈·블로그·문의·개인정보·문의 조회·관리자 로그인은 200, 비로그인 관리자 경로는 테스트 경로의 로그인으로 302, 없는 경로는 404를 반환했습니다. CSS·JavaScript 에셋 4종은 모두 200이며 기존 운영 루트 임시 페이지도 200과 기존 문구를 유지합니다.

운영 오픈 기록: 2026-08-10 `https://gtsit.co.kr` 운영 루트를 본 사이트로 전환했습니다. 홈·블로그·문의·개인정보와 공개 게시글 6건은 GET 200, 없는 경로는 404, 비로그인 관리자는 `/admin/login`으로 이동했습니다. 공개 canonical에서 테스트 경로가 제거되고 공개 화면에는 robots 차단이 없으며 관리자 화면은 `noindex,nofollow,noarchive`를 유지합니다. 홈 1280px에서 메인 이미지 4장·서비스 아이콘 4개·최신 글 3개와 가로 넘침 없음을 확인했고, 문의 지도는 `ready`·프레임 300px·지도 298px·타일 27개·전체화면 버튼 표시 상태입니다. 운영 업로드 경로의 임시 PHP 파일 요청은 403으로 차단됐고 검사 파일은 즉시 삭제했습니다.

회사 정보 반영 기록: 2026-08-04 대표 이메일과 주소를 `site_settings` 및 애플리케이션 기본값에 반영했습니다. 테스트 문의 페이지에서 새 주소, 푸터에서 새 이메일·주소가 표시되고 이전 값이 남아 있지 않은 것을 확인했습니다.

회사명 통일 기록: 2026-08-04 공개 헤더·푸터·메타데이터, 관리자 콘솔, 게시글 작성자 기본값과 기존 초안 9건, 운영 루트 임시 페이지를 `(주)지티에스정보통신`으로 통일했습니다. 실제 응답 3개 화면에서 이전 표기 0건, 새 표기 16건을 확인했고 360·390·1440px에서 가로 넘침이 없었습니다.

푸터·플로팅 버튼 기록: 2026-08-04 푸터의 전화번호를 일반 텍스트로 변경해 `tel:` 링크 0건을 확인했습니다. 플로팅 전화상담 버튼은 전화기 SVG 아이콘, 대표번호 `tel:` 링크와 접근성 이름을 유지하며 실제 Chrome 렌더링을 확인했습니다.

브랜드 로고 적용 기록: 2026-08-04 도식형 심볼을 `GTS` 글자 기반 워드마크로 교체해 `public/assets/images/company-logo-v3.png`로 적용했습니다. 공개 헤더·푸터, 관리자 헤더·로그인·초기 설정, 운영 임시 페이지에서 512×237 투명 PNG 로드를 확인했습니다. 테스트 경로 1280px와 390px에서 헤더 로고를 64×29.6px로 표시했으며 회사명·메뉴 겹침과 가로 넘침이 없었습니다.

메인 이미지 적용 기록: 2026-08-05 HTML 템플릿 자산 `design/assets/hero-network.png`를 1200×675, 151KB JPEG로 최적화해 메인 비주얼에 적용했습니다. CSS 캐시 갱신 버전을 추가했고 테스트 사이트에서 1280px·390px 모두 이미지 로드, `cover` 크롭, 가로 넘침 없음을 확인했습니다. 원본은 템플릿 제공 이미지이므로 실제 회사 시공 사진이 확보되면 동일 영역에서 교체합니다.

메인 슬라이드·콘텐츠 이관 기록: 2026-08-05 기존 사이트 백업의 실제 시공 사진 4장을 1200×900 JPEG로 최적화해 5초 자동 슬라이드로 교체했습니다. 1280px에서 첫 번째에서 두 번째 사진으로 자동 전환되고, 390px에서 컨트롤 한 줄 표시와 가로 넘침 없음을 확인했습니다. LAN·옥외 무선·키폰·CCTV·통신 랙 관리 게시글 5건을 공개해 기존 공개 글을 포함한 카드 6건, 대표 이미지, 상세 본문 4개 문단과 페이지 메타데이터를 확인했습니다.

네이버 지도 연동 기록: 2026-08-05 `https://gtsit.co.kr/site-preview-7c2a91f4/contact`에서 Client ID와 허용 URL 인증, 지도 `ready` 상태, `(주)지티에스정보통신` 마커, 네이버 지도 검색 링크를 확인했습니다. 주소 변환 API는 활성화하지 않고 확인된 고정 좌표로 `Dynamic Map`만 사용합니다. Client Secret은 전달받거나 저장하지 않았으며, SDK 실패 상태에서도 주소와 외부 지도 링크가 유지됩니다.

지도 표시·전체화면 수정 기록: 2026-08-05 NAVER SDK가 지도 요소의 위치 속성을 덮어써 내부 높이가 0px이 된 원인을 수정했습니다. 일반 상태에서 프레임 300px·지도 298px·타일 이미지 27개·마커 1개를 확인했습니다. 사용자 정의 전체화면 아이콘으로 720px 확장 후 298px 복귀와 마커 유지를 검증했고, 390px에서도 지도 298px와 가로 넘침 없음을 확인했습니다. 정상 상태의 외부 텍스트 링크는 숨기고 실패 시 fallback으로 유지합니다.

블로그 임시 썸네일 기록: 2026-08-05 공개 글 6건 중 실제 대표 이미지 5건은 기존 사진을 유지하고, 이미지가 없는 1건에는 `GTS` 브랜드 플레이스홀더가 표시되는 것을 확인했습니다. 1280px에서 카드 행 높이 정렬과 가로 넘침 없음, 390px에서 카드 358px·플레이스홀더 356×199px 및 가로 넘침 없음을 확인했습니다.

문의 입력 편의 기록: 2026-08-05 이메일 아이디 `11111`과 `naver.com` 선택 시 전송용 값 `11111@naver.com`, `직접입력` 선택 시 전체 주소 `hello@company.co.kr`이 유지되는 것을 확인했습니다. 연락처 숫자 `01011111111`은 `010-1111-1111`로 자동 변환됐습니다. 실제 문의는 생성하지 않았으며 390px에서 이메일 필드 312px와 가로 넘침 없음을 확인했습니다.

문의 입력 시각 보정 기록: 2026-08-05 연락처 자동 하이픈 안내 문구와 연결된 `aria-describedby`를 제거했습니다. 연락처 placeholder는 `14px`·`rgb(161, 161, 170)`, 이메일 아이디 placeholder는 `13px`·`rgb(176, 179, 186)`로 확인했습니다. 이메일 도메인·문의 유형 드롭다운은 우측 여백 `14px`, 내부 우측 여백 `42px`로 조정했으며 390px 화면에서 이메일 아이디 `155px`, 도메인 `132px`, 가로 넘침 없음을 확인했습니다.

연락처·조회 PIN 기록: 2026-08-05 단일 연락처 필드에서 `010-1234-5678`, `02-123-4567`, `02-1234-5678`, `031-123-4567`, `031-1234-5678`, `1588-1234`, `070-1234-5678`, `0507-1234-5678` 자동 형식을 확인했습니다. 문자와 기호가 섞인 조회 PIN 입력은 숫자 4자리만 남았으며, 실제 QA 문의를 생성해 올바른 PIN 조회 성공과 잘못된 PIN 5회 후 15분 잠금을 확인한 뒤 테스트 문의를 완전 삭제했습니다.

개인정보처리방침 기록: 2026-08-05 개인정보보호위원회 「개인정보 처리방침 작성지침(2026.4.)」과 개인정보 포털의 수집·이용 동의 양식을 기준으로 처리 목적·항목·법적 근거·보유기간·제3자 제공·Cafe24 위탁·파기·권리 행사·안전조치·세션 쿠키·담당부서·권익침해 구제·시행일을 반영했습니다. 문의 폼에도 목적·필수/선택 항목·보유기간·동의 거부 불이익을 직접 표시했습니다.

서비스 카드 아이콘 기록: 2026-08-10 네트워크·키폰·CCTV·유지보수 카드에 항목별 인라인 SVG 아이콘을 고정 UI 자산으로 배포했습니다. 테스트 경로에서 아이콘 4개와 각 SVG 존재, 48×48px 컨테이너와 26×26px 아이콘, 항목별 배경·선 색상, 중앙 정렬, CSS 버전 `20260805-11`, 1280px 화면의 가로 넘침 없음을 확인했습니다. 운영 루트 임시 페이지는 기존 상태로 HTTP 200 응답을 유지합니다.

파기 명령 기록: 2026-08-05 `bin/purge-inquiries.php`를 Cafe24 PHP 8.4와 MariaDB에서 실행해 만료 대상 0건으로 정상 종료했습니다. 현재 뉴아우토반 일반형은 Cafe24 공식 안내상 cron 미지원 상품이고 서버에도 `crontab` 명령이 없어, 정기 실행 등록은 외부 스케줄러 또는 호스팅 상품 변경 시 진행합니다.

진행 기록: 2026-08-04 새 키로 SSH 로그인 성공. 웹 루트 `/home/hosting_users/gts0201/www`, 기존 안내 파일 백업, 임시 페이지 배포 완료. `https://gts0201.mycafe24.com` HTTPS 200, 운영·로컬 파일 SHA-256 일치, 브라우저 1280px에서 가로 넘침 없음 확인.

## 3. 도메인 및 DNS

- [x] 연결 도메인 `gtsit.co.kr` 철자와 소유 계정 확인
- [x] 루트 도메인의 A 레코드가 호스팅 서버 `112.175.85.162`를 가리킴
- [x] `www` 도메인이 루트 도메인을 거쳐 같은 서버를 가리킴
- [x] 로컬 및 Google Public DNS에서 `SERVFAIL` 해소
- [ ] 여러 공개 DNS에서 결과 일치
- [x] Cafe24 대표 도메인이 `gtsit.co.kr`로 표시됨
- [x] HTTP와 `www`가 `https://gtsit.co.kr`로 301 리디렉션
- [ ] `HEAD` 요청이 공개 GET 경로와 같은 상태 코드 반환
- [ ] 기존 메일 사용 시 MX 및 TXT 레코드 보존 확인

진단 참고: 2026-08-04 Cafe24 자가진단은 서버 연결 및 SSL 오류를 표시했으나, 외부 HTTP/HTTPS 요청과 인증서 검증은 정상입니다. Cafe24 진단 결과만 근거로 장애 처리하지 않고 실제 응답을 함께 확인합니다.

## 4. HTTPS

- [x] SSL Basic 신청 가능 도메인과 최초 1회 설치비 11,000원 확인
- [x] 루트와 `www` 인증서의 도메인 일치
- [x] 인증서 유효기간 2026-08-04~2026-11-02 확인
- [x] HTTP 요청이 HTTPS로 한 번만 리디렉션
- [x] `www` 요청이 대표 루트 주소로 한 번만 리디렉션
- [x] 임시 페이지 혼합 콘텐츠 없음
- [x] 루트와 `www`에서 인증서 경고 없이 HTTPS 200 응답
- [ ] 세션 쿠키에 `Secure`, `HttpOnly`, 적절한 `SameSite` 적용

## 5. 데이터베이스

- [x] MariaDB 10.6.5 클라이언트와 `localhost:3306` 접속정보 확인
- [x] PHP PDO MySQL 및 mysqli 확장 확인

- [x] PHP UTF-8 및 `Asia/Seoul` 기본값 확인
- [x] 비밀번호 없는 DB 접근 차단 확인
- [x] 비밀번호 인증 DB 연결 확인
- [x] DB 기본 문자셋 `utf8mb4` 및 `utf8mb4_unicode_ci` 적용
- [x] DB 설정 파일의 웹 루트 외부 배치와 권한 `600` 확인
- [x] 임시 DB 진단 및 설정 파일 제거 확인
- [ ] `utf8mb4` 한글 및 이모지 저장·조회
- [ ] 서버 시간과 화면 표시 시간 일치
- [ ] 모든 쿼리에 파라미터 바인딩 적용
- [ ] DB 오류에 접속정보 또는 SQL 원문 미노출
- [ ] 외부 MySQL 접속 차단 유지
- [ ] 백업 생성 및 복원 테스트
- [ ] 삭제 또는 익명화 정책 동작 확인

진행 기록: 2026-08-04 `admins`, `posts`, `post_images`, `inquiries`, `site_settings` 테이블 생성 및 전체 테이블 `utf8mb4_unicode_ci` 적용 확인.

## 6. 디자인 구현 필수 QA

- [x] 비로그인 상태에서 관리자 및 글 관리 URL이 로그인 화면으로 302 이동
- [x] 관리자 비밀번호 및 인증 판정 로직이 HTML·JavaScript에 노출되지 않음
- [x] 문의와 게시글이 브라우저 저장소가 아닌 MariaDB에 저장됨
- [x] 360px 이상 공개 화면에서 가로 스크롤 없음
- [ ] 모바일 관리자 목록이 카드 또는 접근 가능한 표 형태로 표시됨
- [x] 문의 필수값, 형식, 글자 수, 동의 여부의 서버 검증
- [x] 개인정보 수집 항목·목적·보유기간·거부 안내 표시
- [ ] 블로그 카드와 주요 탐색 요소를 키보드로 이용 가능
- [x] 페이지별 title, description, canonical, Open Graph 적용
- [x] 업로드 이미지 형식·용량·크기 검증 및 대체 텍스트 제공

## 7. 공통 UI 및 접근성

- [x] 360px, 390px, 768px, 1024px, 1440px 레이아웃 확인
- [x] 가로 스크롤과 콘텐츠 잘림 없음
- [ ] 키보드만으로 모든 조작 가능
- [ ] 포커스 표시가 명확함
- [x] 제목 구조가 논리적이고 페이지당 `h1`이 명확함
- [x] 입력 요소에 연결된 레이블 존재
- [ ] 오류 메시지를 색상 외의 방법으로 전달
- [ ] 이미지 대체 텍스트 적절성 확인
- [ ] 모달 사용 시 포커스 이동과 복귀 확인
- [ ] 확대 200%에서도 주요 기능 사용 가능

## 8. 공개 페이지

- [x] 홈의 주요 링크와 CTA 동작
- [x] 홈 서비스 카드 4종의 항목별 고정 아이콘 표시
- [x] 대표 이미지 없는 게시글 카드에 브랜드형 임시 썸네일 표시
- [x] 문의 이메일 도메인 선택·직접입력 전환 동작
- [x] 문의 연락처의 휴대전화·지역번호·대표번호별 자동 형식 적용
- [x] 문의 입력 placeholder 대비와 드롭다운 꺾쇠 여백
- [ ] 게시글 목록의 정렬과 페이지네이션 동작
- [ ] 게시글 상세의 줄바꿈, 이미지, 이전·다음 글 동작
- [x] 존재하지 않는 게시글에 404 응답
- [x] 문의 필수값과 형식 검증
- [x] 중복 제출 방지
- [ ] 문의 조회번호 발급과 안내
- [ ] 올바른 조회정보로 문의 확인
- [ ] 틀린 조회정보로 개인정보 노출 없음
- [ ] 성공, 오류, 빈 상태 문구 확인

## 9. 관리자

- [x] 로그인 전 관리자 URL 접근 차단
- [ ] 올바른 계정 로그인과 로그아웃 동작
- [x] 관리자 초기 등록 URL의 토큰 없는 접근 404, 유효 토큰 교환 302, 등록 폼 200
- [x] 관리자 초기 등록의 약한 비밀번호 422 거부
- [ ] 반복 로그인 실패 제한
- [ ] 세션 만료 후 재인증 요구
- [ ] 게시글 작성, 수정, 삭제, 공개 상태 동작
- [ ] 관리자 목록의 검색, 필터, 페이지네이션 동작
- [ ] 문의 목록, 상세, 처리 상태 변경 동작
- [ ] 모바일 표와 조작 버튼의 잘림 없음
- [x] 관리자 변경 작업에 CSRF 방어 적용
- [x] 일반 사용자가 관리자 경로를 호출할 수 없음

진행 기록: 2026-08-04 공식 PHP 8.4 컨테이너와 Cafe24 PHP 8.4에서 전체 PHP 문법 통과. 로컬 주요 경로 `/`, `/blog`, `/contact`, `/privacy`, `/inquiry/lookup`, `/admin/login` 200, 비로그인 `/admin`, `/admin/posts` 302, 없는 경로 404 확인. 문의 CSRF 누락 403 및 빈 필수값 제출 422 확인. Cafe24가 비표준 419를 500으로 변환하는 것을 확인해 표준 403으로 조정했습니다.

추가 기록: 2026-08-04 시스템 Chrome으로 공개 주요 6개 경로를 360·390·768·1024·1440px에서 재검수했습니다. 모든 조합에서 HTTP 200, 가로 넘침 없음, 페이지당 `h1` 1개, 누락된 폼 레이블 0개를 확인했습니다. 모바일 문의 화면에서 고정 전화 버튼이 입력 영역을 가리던 문제는 640px 이하에서 버튼을 숨기도록 수정 후 재검수를 통과했습니다.

## 10. 파일 업로드

- [x] 허용 확장자와 MIME만 업로드 가능
- [x] 최대 용량 초과 차단 및 안내
- [x] 실행 가능한 파일 업로드 차단
- [x] 서버에서 안전한 파일명으로 변경
- [x] 동일 이름 파일 충돌 없음
- [ ] 이미지 메타데이터와 방향 처리 확인
- [ ] 삭제된 게시글의 파일 정리 정책 확인
- [x] 업로드 경로에서 PHP 실행 불가 확인

진행 기록: 2026-08-04 Cafe24 테스트 경로의 업로드 폴더에 무해한 PHP 검사 파일을 잠시 배치해 HTTP 403과 미실행을 확인한 뒤 즉시 삭제했습니다.

## 11. 보안 및 개인정보

- [ ] HTML과 스크립트 입력의 XSS 방어
- [ ] SQL 삽입 입력 방어
- [x] 관리자 비밀번호와 문의 조회 PIN 해시 저장
- [x] HTML, JavaScript, 로그에 비밀번호 없음
- [x] 오류 화면에 서버 경로와 스택 정보 없음
- [x] 개인정보 동의 내용과 수집 항목 일치
- [x] 개인정보 보관기간·종료일 기록·완전 삭제 명령 구현
- [ ] 만료 문의 완전 삭제 명령의 정기 실행 등록
- [ ] 보안 헤더 적용 여부 확인
- [ ] ModSecurity와 UploadGuard 오탐 없음

## 12. 검색, 성능 및 운영

- [x] 임시 페이지 종료 후 공개 화면 `noindex` 제거 확인
- [x] 테스트 경로 `X-Robots-Tag`와 robots 메타 색인 차단
- [x] 페이지별 고유 제목과 설명 적용
- [x] canonical과 대표 도메인 일치
- [x] `robots.txt`와 사이트맵 정책 확인
- [ ] 이미지 크기와 지연 로딩 적절성 확인
- [ ] 모바일 저속 환경에서 주요 콘텐츠 표시
- [ ] 용량 및 트래픽 알림 동작 확인
- [ ] 일일 백업과 외부 백업 성공 확인
- [ ] 장애 시 임시 페이지로 되돌리는 절차 확인

## 13. 네이버 지도

- [x] Dynamic Map Client ID 및 허용 웹 서비스 URL 일치
- [x] 회사 주소 좌표와 마커 위치 일치
- [x] 지도 SDK 적용 후 실제 지도 요소 높이와 타일 표시
- [x] 사용자 정의 전체화면 아이콘 열기·종료 및 지도 크기 복구
- [ ] 데스크톱·모바일 지도 확대·축소 및 스크롤 충돌 없음
- [x] 지도 API 로드 실패 시 주소와 네이버 지도 링크 유지
- [x] Client Secret이 HTML·JavaScript·저장소에 포함되지 않음
- [ ] API 이용 한도와 임계치 알림 설정

## 이슈 기록 템플릿

```md
### QA-000 제목

- 환경:
- URL:
- 재현 절차:
  1.
  2.
- 기대 결과:
- 실제 결과:
- 심각도: Blocker / Critical / Major / Minor
- 증빙:
- 상태: Open / Fixed / Retest / Closed
```
