Files
gtsit/docs/architecture.md
2026-08-18 10:53:58 +09:00

16 KiB
Raw Blame History

GTSIT 사이트 설계안

최종 수정일: 2026-08-18

1. 구축 목표

  • 회사와 서비스를 명확히 소개하는 반응형 웹사이트 구축
  • 게시글과 문의를 운영자가 관리할 수 있는 관리자 기능 제공
  • Cafe24 웹호스팅의 PHP 및 MariaDB 환경에 맞춘 단순하고 유지보수 가능한 구성
  • 비밀번호와 문의 내용 등 민감정보를 브라우저 저장소가 아닌 서버에서 안전하게 처리

2. 확인된 운영 환경

항목 확인 내용 후속 작업
호스팅 계정 gts0201 인증 정보는 문서에 저장하지 않음
상품 뉴아우토반호스팅 일반형 현재 용량으로 초기 운영 가능
웹 환경 PHP 8.4 배포 전 필수 PHP 확장 확인
DB 환경 MariaDB 10.6.17, localhost:3306, 계정 gts0201 utf8mb4_unicode_ci, 스키마 생성 대기
서버 IP 112.175.85.162 DNS 생성 후 실제 응답과 대조
기본 도메인 gts0201.mycafe24.com 연결 도메인으로 유지, 운영 노출 정책 결정 대기
대표 도메인 gtsit.co.kr 2026-08-04 Cafe24 대표 도메인 변경 완료
대표 이메일 gts0201@naver.com 공개 화면 및 문의 안내에 사용
회사 주소 서울시 송파구 정의로7길 13, B동 오피스 1020호 공개 화면 사업자 정보에 사용
네임서버 Cafe24 네임서버 위임 확인 호스팅 연결 후 DNS 레코드 생성 확인
현재 DNS 루트·www112.175.85.162로 연결, 공개 DNS 전파 중 Cloudflare DNS 전파 재확인
SSL Lets Encrypt 적용, 루트·www 포함 자동 갱신 상태 지속 확인
웹 방화벽 ModSecurity 사용 적용 후 기능 오탐 점검
UploadGuard 사용 파일 업로드 기능과 호환성 점검
SSH/SFTP RSA 4096 인증키, 만료일 2026-09-03 새 다운로드 키로 접속 성공
서버 홈·웹 루트 /home/hosting_users/gts0201, www 임시 페이지 배포 완료
PHP 안티웹쉘 미사용 본 사이트 배포 전 활성화 검토
외부 MySQL 접속 차단 서버 내부 PHP에서만 DB 사용 권장

3. 페이지 구조

공개 페이지

경로 역할 주요 구성
/ 회사 소개, 핵심 서비스, 최신 게시글, 문의 유도
/blog 게시글 목록 검색 또는 분류, 목록, 페이지네이션
/blog/{slug} 게시글 상세 제목, 본문, 이미지, 작성일, 이전·다음 글
/contact 문의 접수 작성자 정보, 문의 내용, 개인정보 동의
/inquiry/lookup 문의 확인 접수번호와 숫자 4자리 조회 PIN을 통한 본인 확인

관리자 페이지

경로 역할 주요 구성
/admin/login 관리자 인증 서버 세션 기반 로그인
/admin 대시보드 게시글 및 문의 요약
/admin/posts 게시글 관리 목록, 상태 변경, 수정, 삭제
/admin/posts/new 게시글 작성 제목, 본문, 대표 이미지, 공개 상태
/admin/posts/{id}/edit 게시글 수정 기존 데이터 편집
/admin/inquiries 문의 관리 목록, 검색, 처리 상태
/admin/inquiries/{id} 문의 상세 내용 확인, 답변 메모, 상태 변경
/admin/company 회사 정보 연락처와 사이트 공통 정보 관리

4. 권장 기술 구성

  • 서버: PHP 8.4
  • 데이터베이스: MariaDB 10.6.17, PDO MySQL과 prepared statement 사용
  • 화면: 서버 렌더링 HTML, CSS, 필요한 범위의 경량 JavaScript
  • 인증: PHP 세션, password_hash()password_verify() 사용
  • URL: Apache rewrite 사용 가능 여부 확인 후 의미 있는 경로 적용
  • 설정: DB 접속값을 공개 디렉터리 밖의 환경별 설정 파일로 분리

확인된 웹 PHP 환경은 PHP 8.4.21p1, UTF-8, Asia/Seoul, PDO MySQL, mysqli, mbstring, OpenSSL, fileinfo, 업로드 최대 100MB, 메모리 256MB입니다. DB 접속 설정은 서버 웹 루트 밖의 .gtsit-db.env에 권한 600으로 저장합니다.

Cafe24의 실제 웹 루트는 /home/hosting_users/gts0201/www로 확인했습니다. PHP 확장은 본 사이트 개발 단계에서 확정합니다. 아래 구조는 공유호스팅 권한 범위에 맞춰 조정합니다.

app/
  Controllers/
  Repositories/
  Views/
config/
database/
  schema.sql
docs/
public/
  assets/
  uploads/
  index.php
storage/
  logs/

초기 임시 배포는 현재의 public/index.html 단일 파일을 유지합니다. 본 사이트는 public/index.php 프런트 컨트롤러와 공통 PHP 뷰로 구현하며, 운영 전환 시 Apache가 index.php를 우선 사용합니다.

5. 데이터 모델 초안

테이블 목적 핵심 데이터
admins 관리자 계정 로그인 ID, 비밀번호 해시, 상태, 마지막 로그인
posts 게시글 제목, slug, 본문, 공개 상태, 작성·수정일
post_images 게시글 이미지 게시글 ID, 파일 경로, 대체 텍스트, 정렬값
inquiries 고객 문의 접수번호, 작성자, 연락처, 내용, 조회 PIN 해시, 처리 상태, 조회 실패·잠금, 종료일
site_settings 회사 및 공통 설정 설정 키, 값, 수정일

2026-08-04 초기 스키마를 MariaDB에 적용했습니다. admins, posts, post_images, inquiries, site_settings 5개 테이블은 모두 utf8mb4_unicode_ci를 사용합니다. 문의는 접수번호와 숫자 4자리 조회 PIN의 해시로 공개 답변을 조회합니다. 2026-08-05 접수번호별 조회 실패 횟수와 잠금 시각, 처리 종료일을 추가했으며 5회 실패 시 15분 동안 해당 접수번호의 조회를 제한합니다.

5-1. 현재 구현 구조

app/
  Auth/AdminAuth.php
  Repositories/
  Support/helpers.php
  Views/
bin/create-admin.php
config/
database/schema.sql
public/
  assets/css/
  assets/images/company-logo-v3.png
  assets/js/
  index.html
  index.php
  • 공개 페이지: 서버 렌더링, 페이지별 title·description·canonical·Open Graph 적용
  • 브랜드 로고: 투명 배경 GTS 워드마크 PNG를 이미지로 사용하고, 법인명은 정확한 표기와 접근성을 위해 HTML 텍스트로 분리
  • 서비스 아이콘: 네트워크·키폰·CCTV·유지보수 항목에 대응하는 인라인 SVG를 고정 UI 자산으로 관리하며 관리자 입력 대상에서 제외
  • 메인 비주얼: 기존 사이트 백업의 실제 시공 이미지 4장을 public/assets/images/field/에 1200×900 JPEG로 최적화해 5초 간격 자동 슬라이드로 표시
  • 슬라이드 접근성: 이전·다음·직접 선택·일시정지 제공, 포인터·키보드 조작 중 자동 전환 정지, prefers-reduced-motion 환경 자동재생 중지
  • 이전 콘텐츠 이관: LAN·옥외 무선·키폰·CCTV·통신 랙 관리 5개 주제를 현재 표현으로 재구성하고 database/seed-legacy-content.sql로 멱등 반영
  • 문의: 이메일은 아이디와 주요 도메인을 조합하고 직접입력에서만 전체 주소 작성, 연락처는 단일 필드에서 휴대전화·서울·기타 지역번호·대표번호·인터넷전화·안심번호 형식으로 자동 변환
  • 문의 보안: 서버 필수값 검증, CSRF, 20초 중복 방지, 숫자 4자리 조회 PIN 해시, 세션 및 접수번호별 조회 실패 제한
  • 개인정보: 2026 개인정보보호위원회 작성지침을 기준으로 처리 목적·항목·법적 근거·보유기간·제3자 제공·위탁·파기·권리 행사·안전조치·세션 쿠키·담당부서·시행일을 공개
  • 개인정보 파기: 문의가 closed로 전환된 시각을 기록하고 1년이 지난 문의를 bin/purge-inquiries.php로 데이터베이스에서 완전 삭제
  • 파기 실행 환경: 현재 뉴아우토반 공유 웹호스팅은 cron을 지원하지 않아 정리 명령을 수동 실행할 수 있도록 배포했으며, 외부 스케줄러 또는 지원 상품 전환 시 정기 실행 등록 필요
  • 관리자: 서버 세션, 비밀번호 해시, 계정별 잠금, 세션 단위 시도 제한, 모든 하위 경로 인증 선행
  • 방문 통계: 무료 GA4 표준 속성으로 운영 공개 페이지만 측정하고 관리자·테스트 경로 제외, Analytics Data API는 서버의 읽기 전용 서비스 계정과 15분 캐시를 통해 관리자 대시보드에 집계값만 제공
  • 통계 개인정보 경계: 문의 이름·연락처·이메일·본문과 관리자 식별정보는 GA4 이벤트에 포함하지 않고, 통계 쿠키 동의 전에는 Analytics 저장을 비활성화
  • GA4 식별자: 계정 (주)지티에스정보통신, 속성 ID 549573245, 운영 웹 스트림 ID 15422491033, 측정 ID G-92XBR314YD
  • 통계 동의 흐름: 최초 선택 전 Google 태그 미로딩, 허용 시 운영 호스트에서만 측정, 거부·철회 시 Analytics 저장 거부와 회사 도메인 _ga 쿠키 삭제 시도, 광고 저장·Google 신호·광고 개인화는 항상 비활성화
  • 관리자 통계: Google Cloud 프로젝트 gtsit-ga4-dashboard-20260812의 전용 서비스 계정에 GA4 속성 뷰어 권한만 부여하고, 서버에서 Analytics Data API를 조회해 15분간 비공개 파일 캐시
  • GA4 키 보관: JSON 개인키는 Git과 웹 루트 밖의 앱 .secrets/에 권한 600으로 보관하며 브라우저 HTML·JavaScript·로그에 포함하지 않음
  • 통계 장애 대응: API 오류 시 마지막 정상 캐시를 표시하고, 캐시도 없을 때는 관리자 화면에 일반 안내만 표시해 자격 증명·API 오류 세부 정보 비노출
  • 전체 방문자 기준: GA4 측정 시작일 2026-08-12부터 오늘까지의 totalUsers를 표시하며 이전 방문 기록은 포함하지 않음
  • 초기 관리자: 24시간 유효한 토큰을 세션으로 교환한 뒤 비밀번호를 직접 설정하며, 생성 즉시 토큰 파일 삭제
  • 게시글: 신규·기존 slug는 DB 게시글 번호 기반 post-{id} 자동 생성, 종전 slug는 정적 별칭을 통한 301 이동, 분류, 초안·공개 상태, 소프트 삭제 기반
  • 대표 이미지: JPG·PNG·WebP, 8MB, 6000px 제한, MIME 재검증, 임의 파일명, 대체 텍스트 적용
  • 게시글 미디어 실험: 테스트 경로에서 대표 이미지 최대 6장 슬라이드와 본문 이미지 최대 10장을 지원하고, 본문은 독립 줄의 [[image:번호]] 토큰 위치에 안전하게 렌더링
  • 관리자 본문 편집: 범용 HTML 에디터 대신 textarea 문단과 이미지 카드만 제공하는 전용 블록 UI 사용, 위·아래 이동과 삭제 후 기존 텍스트·토큰 형식으로 직렬화
  • 작성 화면 미리보기: 저장 전 폼 상태와 선택 파일의 브라우저 임시 URL을 모달에 안전한 DOM API로 렌더링하며, 미리보기 조작은 서버 요청이나 DB 저장을 발생시키지 않음
  • 본문 보안 경계: 임의 HTML·contenteditable·innerHTML을 사용하지 않고 텍스트는 기존 출력 이스케이프, 이미지는 서버 검증 파일과 DB 연결 정보만 렌더링
  • 운영 호환성: 공유 DB 스키마 변경 없이 post_images.caption@gtsit:gallery, @gtsit:inline:번호 내부 표식과 정렬순서를 사용하며, 운영 코드가 항상 첫 대표 이미지를 선택하도록 유지
  • 실험 공개 제한: 다중 대표 이미지 또는 본문 이미지가 포함된 게시글은 운영 반영 승인 전까지 초안으로만 저장
  • 이미지 없는 게시글 카드: 글을 숨기지 않고 GTS 로고와 카테고리 색상을 사용한 16:9 브랜드 플레이스홀더 표시, 대표 이미지 등록 시 실제 이미지 우선
  • 회사 정보: 관리자 화면에서 연락처·주소·사업자 정보를 DB 설정값으로 관리
  • 오시는 길: NAVER Cloud Dynamic Map으로 주소 기반 지도와 회사 마커 표시, API 오류 시 네이버 지도 검색 링크 제공
  • 운영 사이트: https://gtsit.co.kr에서 본 사이트 공개, 애플리케이션은 웹 루트 밖의 gtsit-app-20260810에 배치
  • 이전 테스트 경로: /site-preview-7c2a91f4, 운영 전환 후 비교·복구용으로 유지하며 검색엔진 색인 차단

6. 디자인 구현 전 수정 원칙

  • 19개 HTML 시안의 공통 헤더, 푸터, 내비게이션을 공통 뷰로 통합
  • 게시글 상세 페이지를 개별 정적 파일이 아닌 하나의 동적 템플릿으로 통합
  • 공개 화면의 모바일 헤더 가로 넘침 수정
  • 관리자 게시글 목록의 모바일 조작 영역 잘림 수정
  • localStorage 기반 게시글과 문의 데이터를 MariaDB로 이전
  • 클라이언트 코드에 포함된 관리자 인증값 제거
  • 문의 등록 시 접수번호와 조회 PIN 해시를 서버에 저장하고 접수번호별 시도 제한을 적용한 조회 절차 구현
  • 업로드 파일의 확장자, MIME, 용량, 저장 파일명을 서버에서 검증

7. 보안 원칙

  • 모든 운영 페이지 HTTPS 강제
  • 관리자 로그인 시도 제한과 세션 쿠키 보안 옵션 적용
  • CSRF 토큰, 출력 이스케이프, SQL 파라미터 바인딩 적용
  • 비밀번호와 개인키를 저장소, 로그, HTML, JavaScript에 포함하지 않음
  • 업로드 디렉터리에서 PHP 실행 차단
  • 관리자 경로에 검색엔진 차단 및 필요 시 추가 접근 제한 적용
  • Cafe24 일일 백업과 별도의 외부 백업 병행

8. 배포 순서

  1. SSH/SFTP 개인키 준비 및 서버 접속 확인
  2. 기존 웹 루트 파일 확인 및 백업
  3. 임시 index.html 업로드
  4. gts0201.mycafe24.com에서 응답 및 모바일 화면 확인
  5. 확정한 사용자 도메인을 호스팅에 연결
  6. 루트 도메인과 www DNS 응답 확인
  7. 무료 SSL 신청, 발급, HTTPS 리디렉션 확인
  8. MariaDB 접속 확인 및 최소 권한 구성
  9. 본 사이트 스키마와 애플리케이션 배포
  10. 보안, 백업, 알림, 최종 회귀 QA

2026-08-10 운영 루트를 본 사이트로 전환했습니다. 웹 루트에는 공개 에셋·업로드 디렉터리·운영 진입 파일만 두고, PHP 애플리케이션은 웹 루트 밖에 배치합니다. 이전 테스트 경로는 비교·복구용으로 유지하며 경로 접두사와 검색엔진 차단 설정을 유지합니다.

9. 미확정 의사결정

현재 대표 주소는 https://gtsit.co.kr입니다. Cafe24 대표 도메인도 gtsit.co.kr로 변경했으며, HTTP와 www 요청은 public/.htaccess에서 대표 주소로 301 리디렉션합니다. 2026-08-04 확인한 Lets Encrypt 인증서는 루트와 www를 포함하며 2026-11-02까지 유효합니다.

  • 회사 대표 메일을 Cafe24 메일로 사용할지 외부 메일 서비스를 사용할지 결정
  • 관리자 계정 수와 권한 구분 필요 여부 확정
  • 게시글 분류, 검색, 임시저장, 예약발행 필요 여부 확정

10. 네이버 지도 연동

  • NAVER Cloud Platform의 Maps Application에서 Dynamic Map 선택
  • Web 서비스 URL은 공식 형식에 맞춰 http://gtsit.co.kr 등록(HTTP·HTTPS 구분 없음, www 제외)
  • 브라우저 지도 로더에는 Client ID를 ncpKeyId로 사용
  • Client Secret은 프런트엔드, 저장소, HTML에 포함하지 않음
  • 고정 회사 위치는 확인된 위도 37.48524, 경도 127.11478을 사용해 Dynamic Map만 호출하고, 별도 Geocoding 상품과 일일 주소 변환 호출은 사용하지 않음
  • 주소 표시는 서울시 송파구 정의로7길 13, B동 오피스 1020호, 네이버 지도 검색은 건물 주소를 기준으로 연결
  • 지도 SDK가 컨테이너 위치 속성을 덮어써도 높이가 유지되도록 지도 요소에 height: 100% 적용
  • NAVER 기본 컨트롤에 전체화면이 없으므로 Fullscreen API 기반 사용자 정의 아이콘을 지도 안에 제공하고, 미지원 환경에서는 네이버 지도 새 창 열기로 대체
  • 정상 지도 상태에서는 별도 텍스트 링크를 숨기고, API 로드 실패 또는 JavaScript 비활성 환경에서만 주소가 지정된 네이버 지도 링크 제공