217 lines
18 KiB
Markdown
217 lines
18 KiB
Markdown
# 구현 TODO
|
||
|
||
최종 수정일: 2026-08-18
|
||
|
||
완료한 작업은 체크하고, 설정값이나 URL이 바뀌면 관련 문서도 함께 갱신합니다.
|
||
|
||
## 0. 사전 조사
|
||
|
||
- [x] [Codex] 프로젝트 문서 상시 동기화 규칙을 `AGENTS.md`에 추가
|
||
- [x] [Codex] 로컬 저장소 및 작업 대상 확인
|
||
- [x] [Codex] `design/` 페이지 구성과 반복 구조 검토
|
||
- [x] [Codex] 공개 화면과 관리자 화면의 모바일 문제 확인
|
||
- [x] [Codex] 브라우저 저장소 및 클라이언트 인증 문제 확인
|
||
- [x] [Codex] Cafe24 호스팅 상품, PHP, MariaDB, 보안 설정 확인
|
||
- [x] [Codex] 도메인 이전 상태, 네임서버 위임, DNS 장애 상태 확인
|
||
- [x] [사용자] 연결할 도메인을 `gtsit.co.kr`로 최종 확인
|
||
|
||
## 1. 임시 페이지 배포
|
||
|
||
- [x] [Codex] 외부 리소스 없는 `public/index.html` 제작
|
||
- [x] [Codex] 데스크톱 화면 확인
|
||
- [x] [Codex] 390px 모바일 화면 및 가로 넘침 확인
|
||
- [x] [Codex] 로컬 검증 서버 종료
|
||
- [x] [사용자] Cafe24 SSH 인증키 다운로드
|
||
- [x] [Codex] 인증키를 `.secrets/`로 이동, 파일 권한 제한, Git 제외
|
||
- [x] [사용자] Cafe24 `FTP/Shell 접속설정`에서 SSH key 로그인 재적용
|
||
- [x] [사용자] `인증키 재발급` 없이 현재 등록된 SSH 인증키 다시 다운로드
|
||
- [x] [Codex] 새 키 지문 확인, 권한 제한, `.secrets/` 보관
|
||
- [x] [Codex] SSH/SFTP 접속 및 실제 웹 루트 확인
|
||
- [x] [Codex] 서버 기존 파일 목록 확인
|
||
- [x] [Codex] 기존 Cafe24 안내 파일 백업
|
||
- [x] [Codex] 임시 페이지 업로드
|
||
- [x] [Codex] `gts0201.mycafe24.com` HTTPS 200 및 파일 일치 확인
|
||
- [x] [Codex] 실제 브라우저에서 임시 페이지와 가로 넘침 확인
|
||
- [x] [Codex] 임시 페이지 상단 로고와 하단 저작권을 `(주)지티에스정보통신`으로 변경 및 재배포
|
||
- [ ] [사용자] 다운로드 폴더의 인증키 복사본 정리 여부 결정
|
||
|
||
진행 메모: 2026-08-04 새로 다운로드한 키의 지문이 기존 키와 다른 것을 확인했고 새 키로 SSH 접속에 성공했습니다. 실제 홈은 `/home/hosting_users/gts0201`, 웹 루트는 `www`입니다. 기존 `hosting_index.html`은 `hosting_index.html.backup-20260804`로 보존했고, `public/index.html`을 `www/index.html`로 배포했습니다. 기본 도메인 HTTPS 200, 로컬·운영 파일 SHA-256 일치, 브라우저 렌더링 및 1280px 가로 넘침 없음까지 확인했습니다.
|
||
|
||
## 2. 사용자 도메인 연결
|
||
|
||
- [x] [공동] Cafe24의 연결 대상 호스팅 `gts0201`과 도메인 `gtsit.co.kr` 재확인
|
||
- [x] [Codex] 사용자 승인 후 호스팅에 도메인 연결
|
||
- [x] [Codex] 루트 도메인 A 레코드 `112.175.85.162` 응답 확인
|
||
- [x] [Codex] `www`가 루트 도메인을 거쳐 같은 서버로 연결되는지 확인
|
||
- [x] [Codex] 로컬 및 Google Public DNS에서 기존 `SERVFAIL` 해소 확인
|
||
- [ ] [Codex] Cloudflare DNS를 포함한 전체 전파 완료 확인
|
||
- [x] [공동] 대표 주소를 `https://gtsit.co.kr`로 결정
|
||
- [x] [Codex] Cafe24 대표 도메인을 `gtsit.co.kr`로 변경
|
||
- [x] [Codex] HTTP 및 `www`를 대표 HTTPS 주소로 영구 리디렉션
|
||
- [ ] [Codex] 기본 Cafe24 도메인의 운영 노출 정책 결정 및 적용
|
||
|
||
진행 메모: 2026-08-04 Cafe24 대표 도메인을 `gtsit.co.kr`로 변경했습니다. 변경 직후 외부 요청에서 `http://gtsit.co.kr`과 `https://www.gtsit.co.kr`은 `https://gtsit.co.kr`로 301 응답하고, 대표 HTTPS 주소는 200 응답하는 것을 재확인했습니다. Cafe24 자가진단은 같은 시각 서버 연결 및 SSL 오류를 표시했지만 실제 공개 접속과 TLS 검증은 정상이라 진단 표시 불일치로 기록합니다.
|
||
|
||
## 3. HTTPS 설정
|
||
|
||
- [ ] [Codex] 도메인 DNS 전체 전파 확인
|
||
- [x] [Codex] 도메인 연결 직후 HTTP 응답 및 배포 파일 일치 확인
|
||
- [x] [Codex] Cafe24 SSL Basic 신청 가능 상태와 비용 확인
|
||
- [x] [사용자] SSL 발급 및 설치 완료
|
||
- [x] [Codex] 루트 및 `www` 인증서 적용 확인
|
||
- [x] [Codex] HTTP에서 HTTPS로 301 리디렉션
|
||
- [x] [Codex] `www`에서 루트 HTTPS 주소로 301 리디렉션
|
||
- [x] [Codex] 혼합 콘텐츠와 인증서 체인 QA
|
||
|
||
진행 메모: 2026-08-04 Let’s Encrypt 인증서가 루트와 `www`에 적용됐습니다. 인증서 유효기간은 2026-08-04~2026-11-02이며, HTTP와 `www`는 `https://gtsit.co.kr`로 301 리디렉션됩니다.
|
||
|
||
## 4. MariaDB 설정
|
||
|
||
- [x] [Codex] DB 주소 `localhost`, 계정 `gts0201`, 포트 `3306`, MariaDB `10.6.5` 확인
|
||
- [x] [Codex] PHP 8.4의 PDO MySQL 및 mysqli 확장 사용 가능 여부 확인
|
||
- [x] [Codex] PHP 기본 문자셋 UTF-8 및 시간대 `Asia/Seoul` 확인
|
||
- [x] [사용자] 기존 DB 비밀번호를 로컬 비밀 설정에 입력
|
||
- [x] [사용자] DB 비밀번호를 `.secrets/db.env`에 직접 저장
|
||
- [x] [Codex] DB 접속 설정을 서버 웹 루트 밖에 배치하고 권한 `600` 적용
|
||
|
||
- [x] [Codex] DB 비밀번호와 설정 파일의 Git 제외 확인
|
||
- [x] [Codex] 비밀번호 인증 연결 테스트 및 임시 진단 파일 제거
|
||
- [x] [Codex] 빈 DB 기본값을 `utf8mb4`와 `utf8mb4_unicode_ci`로 변경
|
||
- [x] [Codex] `database/schema.sql` 초안 작성
|
||
- [x] [Codex] 관리자, 게시글, 이미지, 문의, 사이트 설정 테이블 생성
|
||
- [x] [Codex] 초기 관리자 계정의 안전한 생성 절차 마련
|
||
- [x] [사용자] 초기 관리자 아이디 `gts0201` 확정
|
||
- [ ] [사용자] 1회용 등록 URL에서 관리자 비밀번호 직접 설정
|
||
- [ ] [Codex] 백업 및 복구 절차 검증
|
||
|
||
진행 메모: 2026-08-04 웹 진단으로 PHP 8.4.21p1, PDO 드라이버 `mysql`, `mysqli`, `mbstring`, `openssl`, `fileinfo`, 업로드 100MB, 메모리 256MB를 확인했습니다. MariaDB 10.6.17 비밀번호 인증에 성공했고, 테이블 0개인 빈 DB의 기본값을 `utf8mb4`와 `utf8mb4_unicode_ci`로 변경했습니다. 서버 접속 설정은 웹 루트 밖의 `.gtsit-db.env`에 권한 600으로 저장했으며 모든 임시 웹 파일은 삭제했습니다.
|
||
|
||
관리자 등록 메모: 초기 아이디는 `gts0201`입니다. 비밀번호는 채팅이나 저장소에 남기지 않고 24시간 유효한 1회용 URL에서 사용자가 직접 입력합니다. 계정 생성 후 서버의 등록 토큰 파일은 자동 삭제됩니다.
|
||
|
||
## 5. 디자인 구현 전 확정
|
||
|
||
- [x] [Codex] 공개·관리자 전체 디자인 구조 검토
|
||
- [x] [Codex] 접수번호와 비밀번호를 사용한 웹 답변 조회 흐름 구현
|
||
- [ ] [사용자] 회사 정보와 대외 표시 실적 수치 최종 확인
|
||
- [x] [사용자] 대표 이메일 `gts0201@naver.com` 확인
|
||
- [x] [사용자] 주소 `서울시 송파구 정의로7길 13, B동 오피스 1020호` 확인
|
||
- [x] [사용자] 공개·관리자 전체 회사명을 `(주)지티에스정보통신`으로 통일
|
||
- [x] [Codex] `GTS` 글자 기반 워드마크 로고 이미지 생성 및 공개·관리자·임시 페이지 적용
|
||
- [x] [Codex] HTML 템플릿의 네트워크 시공 이미지를 최적화해 메인 비주얼에 적용
|
||
- [x] [Codex] 기존 사이트 백업의 실제 시공 이미지 4장으로 메인 자동 슬라이드 구현
|
||
- [x] [Codex] 기존 사이트의 LAN·무선·키폰·CCTV 글을 재구성한 공개 게시글 5건 등록
|
||
- [x] [사용자] 푸터 전화번호 연결 제거 및 플로팅 전화상담 아이콘 적용
|
||
- [x] [Codex] 네이버 지도 API 연동 방식 및 공식 등록 요건 확인
|
||
- [x] [사용자] NAVER Cloud Maps Application 생성, Dynamic Map 선택, 웹 URL `http://gtsit.co.kr` 등록
|
||
- [x] [사용자] Maps Client ID 전달·등록, Client Secret은 전달하지 않음
|
||
- [x] [Codex] 오시는 길 지도·회사 마커·네이버 지도 열기 fallback 구현
|
||
- [x] [Codex] 지도 SDK 요소 높이 안정화 및 사용자 정의 전체화면 컨트롤 적용
|
||
- [x] [Codex] 지도 내부 컨트롤보다 전화상담 플로팅 버튼이 위에 표시되도록 스태킹 순서 보정
|
||
- [x] [Codex] 지도 드래그·키보드 이동 차단 및 마커 중심 확대·축소 고정
|
||
- [x] [Codex] 핀치·휠·더블클릭/탭 줌 차단 및 주소 중심 확대·축소 컨트롤만 허용
|
||
- [x] [사용자] 기존 사이트 백업의 실제 시공 이미지 원본 전달
|
||
- [ ] [사용자] 최신 시공 이미지 추가 전달
|
||
- [x] [Codex] 관리자 인증·세션·접근 통제 방식 확정
|
||
- [x] [Codex] 모바일 헤더와 관리자 모바일 목록 구조 설계
|
||
- [x] [Codex] 2026 개인정보보호위원회 작성지침 기반 개인정보 수집·이용 고지 및 개인정보처리방침 확정
|
||
- [x] [Codex] 공통 PHP 템플릿과 MariaDB 기반 구현 구조 확정
|
||
|
||
## 6. 공통 마크업 및 기반 구축
|
||
|
||
- [x] [Codex] 디자인 토큰과 공통 CSS 정리
|
||
- [x] [Codex] 공통 헤더, 내비게이션, 푸터 템플릿화
|
||
- [x] [Codex] 모바일 공개 헤더 구조 구현
|
||
- [x] [Codex] 관리자 목록 모바일 카드 구조 구현
|
||
- [x] [Codex] 공통 버튼, 입력 필드, 표, 상태 UI 정리
|
||
- [x] [Codex] 접근 가능한 포커스, 오류, 빈 상태 정의
|
||
- [x] [Codex] PHP 라우팅 및 오류 페이지 구성
|
||
|
||
## 7. 공개 페이지 구현
|
||
|
||
- [x] [Codex] 홈 구현
|
||
- [x] [Codex] 게시글 목록 및 페이지네이션 구현
|
||
- [x] [Codex] 게시글 상세 동적 템플릿 구현
|
||
- [x] [Codex] 주제별 공개 게시글과 대표 이미지 데이터 반영
|
||
- [x] [Codex] 대표 이미지 없는 게시글의 브랜드형 임시 썸네일 적용
|
||
- [x] [Codex] 메인 서비스 카드의 네트워크·키폰·CCTV·유지보수 고정 아이콘 구현
|
||
- [x] [Codex] 메인 서비스 카드 아이콘 테스트 경로 배포 및 시각 QA
|
||
- [x] [Codex] 문의 작성 및 서버 검증 구현
|
||
- [x] [Codex] 문의 이메일 도메인 선택·직접입력 전환 적용
|
||
- [x] [Codex] 단일 연락처 필드의 휴대전화·지역번호·대표번호 자동 형식 적용
|
||
- [x] [Codex] 문의 입력 안내 제거·placeholder 대비·드롭다운 꺾쇠 여백 조정
|
||
- [x] [Codex] 문의 조회 및 본인 확인 구현
|
||
- [x] [Codex] 숫자 4자리 조회 PIN과 접수번호별 5회 실패·15분 잠금 적용
|
||
- [x] [Codex] 개인정보 수집·이용 요약 고지와 최종 개인정보처리방침 적용
|
||
- [x] [Codex] 공개 페이지 반응형 QA
|
||
|
||
## 8. 관리자 구현
|
||
|
||
- [x] [Codex] 서버 세션 기반 관리자 로그인 구현
|
||
- [x] [Codex] 클라이언트 코드의 기존 관리자 인증값 제거
|
||
- [x] [Codex] 대시보드 구현
|
||
- [x] [Codex] 게시글 목록, 작성, 수정, 소프트 삭제 구현
|
||
- [x] [Codex] 신규·기존 게시글 URL을 `post-글번호` 형식으로 자동 생성하고 이전 주소 301 연결
|
||
- [x] [Codex] 관리자 글 목록에서 초안·공개 글의 인증된 실제 화면 미리보기 구현
|
||
- [x] [Codex] 이미지 업로드 검증 구현
|
||
- [x] [Codex] 테스트 경로에 대표 이미지 최대 6장 슬라이드와 본문 이미지 최대 10장 배치 기능 구현
|
||
- [x] [Codex] 다중·본문 이미지가 있는 글의 테스트 기간 공개 차단과 전용 초안 미리보기 구성
|
||
- [x] [Codex] 관리자 본문 입력을 텍스트 문단·이미지 전용 블록 편집 UI로 개선
|
||
- [x] [Codex] 블록 이동·삭제·대체 텍스트와 안전한 내부 토큰 직렬화 구현
|
||
- [x] [Codex] 글쓰기 화면에서 저장 전 제목·본문·대표 이미지·본문 이미지 즉시 미리보기 구현
|
||
- [x] [Codex] 테스트 base path가 등록 본문 이미지의 JavaScript 미리보기 경로에 누락되는 문제 수정
|
||
- [ ] [공동] 테스트 초안의 슬라이드·본문 이미지 UI 검토 및 수정사항 확정
|
||
- [ ] [Codex] 승인된 다중·본문 이미지 기능 운영 코드 반영
|
||
- [x] [Codex] 문의 목록, 상세, 처리 상태 및 공개 답변 구현
|
||
- [x] [Codex] 회사 및 사이트 설정 구현
|
||
- [x] [Codex] CSRF, 세션 만료, 로그인 시도 제한, 권한 검증 적용
|
||
- [x] [사용자] GA4 표준 속성과 `gtsit.co.kr` 웹 데이터 스트림 생성
|
||
- [x] [Codex] 운영 공개 페이지에 통계 동의 기반 Google 태그 적용, 관리자·테스트 경로 제외
|
||
- [x] [사용자] Analytics Data API 서비스 계정 생성과 GA4 뷰어 권한 부여
|
||
- [x] [Codex] GA4 Data API 연동과 15분 서버 캐시 구현
|
||
- [x] [Codex] 관리자 대시보드 방문자·페이지뷰·유입경로·인기 페이지 UI 구현
|
||
- [x] [Codex] GA4 전문 용어를 최근 접속자·30일 방문자·페이지 열람 수·사이트 방문 횟수로 쉽게 표시
|
||
- [x] [Codex] GA4 측정 시작일 이후 전체 방문자 지표 추가
|
||
- [x] [공동] 테스트 관리자 대시보드의 데스크톱 UI 확인
|
||
- [ ] [공동] 관리자 대시보드 모바일 UI 확인
|
||
- [ ] [Codex] 문의 제출 전환 이벤트와 전환 지표 추가
|
||
|
||
GA4 진행 메모: 2026-08-12 계정 `(주)지티에스정보통신`, 속성 ID `549573245`, 운영 웹 스트림 ID `15422491033`, 측정 ID `G-92XBR314YD`를 생성했습니다. 선택 동의 전에는 Google 스크립트를 로드하지 않고, 테스트·관리자 경로는 측정하지 않습니다. 운영 동의 후 GA4 실시간 활성 사용자 1명을 확인했습니다.
|
||
|
||
GA4 관리자 연동 메모: 2026-08-13 Google Cloud 프로젝트 `gtsit-ga4-dashboard-20260812`에서 Analytics Data API를 활성화하고 서비스 계정 `gtsit-ga4-reader@gtsit-ga4-dashboard-20260812.iam.gserviceaccount.com`에 GA4 속성 `뷰어` 권한만 부여했습니다. 서버 측 OAuth와 Data API 실제 조회에서 사용자·페이지뷰·세션 데이터 응답을 확인했고, 집계 결과는 웹 루트 밖에 15분간 권한 600으로 캐시합니다. 테스트 관리자 화면의 최종 시각 QA 후 운영에 반영합니다.
|
||
|
||
운영 반영 메모: 2026-08-13 현재 저장소의 공개·관리자 실행 코드, 번호형 게시글 URL, 문의·개인정보 화면, 관리자 글쓰기 개선, GA4 대시보드와 공개 에셋을 운영에 반영했습니다. 서버 기존 파일은 `/home/hosting_users/gts0201/.deploy-backup-20260813-current-work`에 앱·웹 아카이브로 보관했습니다. 운영 PHP 문법, GA4 Data API 실제 조회, 비밀키·캐시 권한 600, 주요 공개 경로와 에셋 200, 관리자 비로그인 302, 게시글 200과 이전 주소 301, 홈·문의·네이버 지도 렌더링을 확인했습니다.
|
||
|
||
## 9. 운영 설정 및 출시
|
||
|
||
- [x] [Codex] 운영 루트를 유지한 채 `/site-preview-7c2a91f4` 테스트 라우팅 배포
|
||
- [x] [Codex] 테스트 경로 검색엔진 차단 및 세션 쿠키 경로 격리
|
||
- [ ] [Codex] 만료 문의 파기 명령의 정기 실행 일정 등록
|
||
- [ ] [공동] ModSecurity와 실제 기능 호환성 QA
|
||
- [ ] [공동] PHP 안티웹쉘 활성화 여부 결정 및 QA
|
||
- [x] [Codex] 업로드 디렉터리 PHP 실행 차단 설정 작성
|
||
- [ ] [사용자] 하드 용량 및 트래픽 알림 수신처 결정
|
||
- [ ] [공동] 용량 및 트래픽 알림 활성화
|
||
- [ ] [공동] GA4 통계 쿠키 동의 문구와 개인정보처리방침 국외 처리 항목 최종 검토
|
||
- [x] [공동] 검색 봇 차단 정책과 공개 시점 결정
|
||
- [x] [Codex] 공개 페이지 허용·관리자와 비공개 문의 조회 차단 `robots.txt` 배포
|
||
- [x] [Codex] 공개 페이지와 게시글 6건 `sitemap.xml` 배포
|
||
- [ ] [사용자] 대표 메일 서비스 결정
|
||
- [ ] [공동] Cafe24 백업 외 별도 외부 백업 위치 결정
|
||
- [ ] [Codex] 운영 QA 전체 실행
|
||
- [x] [공동] 임시 페이지를 본 사이트로 전환
|
||
- [ ] [Codex] 출시 후 DNS, HTTPS, 오류 로그, 문의 흐름 재확인
|
||
|
||
진행 메모: 2026-08-04 기존 임시 안내 페이지는 `https://gtsit.co.kr/`에 유지하고 본 사이트 테스트 빌드를 `https://gtsit.co.kr/site-preview-7c2a91f4/`에 배포했습니다. 테스트 경로는 `X-Robots-Tag`와 HTML robots 메타로 색인을 차단하며, 세션 쿠키 경로도 테스트 경로로 제한합니다.
|
||
|
||
지도 연동 메모: 2026-08-05 Client ID `0xuekem2qn`을 `ncpKeyId`로 등록했습니다. 고정된 회사 위치는 주소 변환 API를 매번 호출하지 않고 확인된 위·경도로 표시하며, `Dynamic Map`만으로 회사 마커를 렌더링합니다. 지도 SDK 로드·인증 실패 시에도 주소와 네이버 지도 검색 링크를 유지합니다.
|
||
|
||
운영 오픈 메모: 2026-08-10 기존 임시 페이지와 루트 설정을 `.deploy-backup-20260810-production-open`에 보존하고 `https://gtsit.co.kr`을 본 사이트로 전환했습니다. 운영 앱은 웹 루트 밖의 `gtsit-app-20260810`, 공개 파일은 `www`에 배치했습니다. 주요 공개 경로·게시글 6건·에셋·지도·관리자 로그인·HTTPS 리디렉션·업로드 PHP 실행 차단을 확인했습니다. 일반 GET은 정상이나 `HEAD` 요청을 라우터가 404로 처리하는 호환성 항목은 로직 변경 승인 후 보완합니다. 최초 커밋 `dbb35d3`은 생성했으며 원격 저장소 HTTPS 인증 정보가 없어 push는 사용자 인증 후 재시도합니다.
|
||
|
||
게시글 미디어 테스트 메모: 2026-08-10 운영과 테스트가 같은 DB를 사용하므로 스키마는 변경하지 않고 `post_images.caption` 내부 표식으로 대표·본문 이미지를 구분했습니다. `/site-preview-7c2a91f4/admin/posts/15/preview`에 테스트 전용 초안을 구성했으며, 대표 3장 자동 슬라이드와 본문 2장 위치 배치를 확인했습니다. 다중 또는 본문 이미지가 있는 글은 운영 반영 전까지 `draft` 저장만 허용하며 운영 앱 파일은 변경하지 않았습니다.
|
||
|
||
본문 블록 편집기 메모: 2026-08-10 범용 WYSIWYG와 임의 HTML 저장을 사용하지 않고 테스트 관리자에 텍스트 문단·이미지 블록 편집기를 적용했습니다. 관리 화면은 내부 `[[image:번호]]`를 숨기고 실제 이미지 카드로 보여주며, 저장 직전에만 기존 일반 텍스트 형식으로 변환합니다. 이미지 위치 토큰은 서버에서 숫자 범위·중복·본문 1회 배치·실제 이미지 연결 여부를 재검증합니다.
|
||
|
||
작성 화면 미리보기 메모: 2026-08-10 테스트 관리자 편집 화면에 저장 전 내용을 즉시 확인하는 모달을 추가했습니다. 현재 입력 중인 제목·분류·작성자·문단과 기존/신규 대표 이미지·본문 이미지를 브라우저 DOM으로만 구성하며, 미리보기를 열거나 대표 이미지 썸네일을 전환해도 데이터베이스에는 저장하지 않습니다.
|
||
|
||
게시글 URL 자동 생성 메모: 2026-08-10 새 글 저장 시 DB가 발급한 게시글 번호를 기준으로 `post-16`, `post-17`처럼 slug를 자동 생성하도록 변경했습니다. 기존 1~15번 글도 `post-1`~`post-15`로 통일하고 종전 주소는 새 주소로 301 이동하도록 보존하며, 작성·수정 화면에서는 URL을 직접 입력하지 않습니다.
|