index.php 에서만 문의 등록 폼이 안되는 이유

🙏SIR UI/UX 디자인 의뢰(~7/31)
index.php 에서만 문의 등록 폼이 안되는 이유

QA

index.php 에서만 문의 등록 폼이 안되는 이유

본문

안녕하세요. 오랜만에 문의 남깁니다.

 

제가 사이트를 하나 만들어 보고 있는데요

 

index 페이지와 렌딩 페이지가 있을때

동일한 상담문의 폼을 그대로 복붙해도

 

렌딩 페이지에서는 정상적으로 문의 게시글이 작성되고,

index 페이지에서는 상담문의 성공 얼럿이 뜨지만 문의 게시글이 작성되지 않습니다.

 

아래는 해당 코드입니다.

 


<div class="custom-main-banner">
    <div class="banner-container">
        <div class="banner-left">
            <h2>온라인 상담 신청</h2>
            <form id="consultForm" action="제 도메인 주소/bbs/write_update.php" method="post">
                <input type="hidden" name="bo_table" value="tl_qa">
                <input type="hidden" name="wr_id" value="">
                <input type="hidden" name="sca" value="">
                <input type="hidden" name="w" value="">
                <input type="hidden" name="html" value="html1">
                <!-- CSRF 방지를 위한 토큰 추가 -->
                <input type="hidden" name="token" value="<?php echo get_write_token('tl_qa'); ?>">
                
                <div class="form-group">
                    <label for="name"></label>
                    <input type="text" id="name" name="wr_name" placeholder="이름" required />
                    <input type="hidden" name="wr_subject" id="wr_subject_hidden" />
                </div>
                <div class="form-group">
                    <label for="phone"></label>
                    <input type="tel" id="phone" name="wr_content" placeholder="‘-’ 없이 숫자만 입력" pattern="[0-9]{11,14}" required />
                </div>
                <div class="form-group">
                    <label for="selectCategory"></label>
                    <select id="selectCategory" name="consult_type">
                        <option value="상담신청">상담신청</option>
                        <option value="상품1">상품1</option>
                        <option value="상품2">상품2</option>
                        <option value="상품3">상품3</option>
                        <option value="상품4">상품4</option>
                        <option value="상품5">상품5</option>
                    </select>
                </div>
                <div class="form-check">
                    <input type="checkbox" id="agree" checked />
                    <label for="agree">개인정보 수집 및 이용 동의 <a href="#" id="openModal">자세히보기</a></label>
                </div>
                <button class="btn-submit blue" type="submit">빠른 상담</button>
            </form>
            <!-- 개인정보 수집 모달 -->
            <div class="memo__modal" id="privacyModal" style="display: none;">
                <div class="memo-modal__inner">
                    <div class="memo-modal__close" id="closeModal">닫기</div>
                    <div class="memo-modal__txt">
                        <h3>개인(신용)정보의 수집,이용에 관한사항</h3>
                        <p>[개인정보보호법] 및 [신용정보의 이용 및 보호에 관한 법률]에 따라 아래와 같은 내용으로 본인의 개인정보 수집·이용에 동의합니다.</p>
                       기타 개인정보 내용
                    </div>
                </div>
            </div>
        </div>
        <div class="banner-right">
            <div class="banner-card">
                <span class="card-label">상품1</span>
                <h3>상품1</h3>
                <p>어쩌고저쩌고</p>
                <div class="card-image"><img src="<?=G5_THEME_URL?>/img/cnimg.png" alt="상품1"></div>
                <a href="/theme/sample03/html/렌딩.php" class="goto-button">바로가기</a>
            </div>
            <div class="banner-card">
                <span class="card-label">상품1</span>
                <h3>상품1</h3>
                <p>어쩌고저쩌고</p>
                <div class="card-image"><img src="<?=G5_THEME_URL?>/img/cnimg.png" alt="상품1"></div>
                <a href="/theme/sample03/html/렌딩.php" class="goto-button">바로가기</a>
            </div>
            <div class="banner-card">
                <span class="card-label">상품1</span>
                <h3>상품1</h3>
                <p>어쩌고저쩌고</p>
                <div class="card-image"><img src="<?=G5_THEME_URL?>/img/cnimg.png" alt="상품1"></div>
                <a href="/theme/sample03/html/렌딩.php" class="goto-button">바로가기</a>
            </div>
            <div class="banner-card">
                <span class="card-label">상품1</span>
                <h3>상품1</h3>
                <p>어쩌고저쩌고</p>
                <div class="card-image"><img src="<?=G5_THEME_URL?>/img/cnimg.png" alt="상품1"></div>
                <a href="/theme/sample03/html/렌딩.php" class="goto-button">바로가기</a>
            </div>
            <div class="banner-card">
                <span class="card-label">상품1</span>
                <h3>상품1</h3>
                <p>어쩌고저쩌고</p>
                <div class="card-image"><img src="<?=G5_THEME_URL?>/img/cnimg.png" alt="상품1"></div>
                <a href="/theme/sample03/html/렌딩.php" class="goto-button">바로가기</a>
            </div>
        </div>
    </div>
</div>
 
<script>
// 오류 로그 저장 함수
function saveErrorLog(data) {
    const timestamp = new Date().toISOString();
    const logEntry = { 
        timestamp, 
        sessionId: document.cookie.match(/PHPSESSID=([^;]+)/)?.[1] || 'none',
        referer: window.location.href,
        cookies: document.cookie,
        ...data 
    };
    let logs = JSON.parse(localStorage.getItem('ormErrors') || '[]');
    logs.push(logEntry);
    localStorage.setItem('ormErrors', JSON.stringify(logs));
    console.log('Error log saved:', logEntry);
}
document.getElementById('consultForm').addEventListener('submit', function(e) {
    e.preventDefault(); // Prevent default form submission
    const form = e.target;
    const name = document.getElementById('name').value.trim();
    const phone = document.getElementById('phone').value.trim();
    const consultTypeElement = form.querySelector('select[name="consult_type"]');
    const consultType = consultTypeElement ? consultTypeElement.value : '상담신청';
    const agree = document.getElementById('agree').checked;
    // 1. Name validation: Korean characters, 2-5 letters
    const namePattern = /^[가-힣]{2,5}$/;
    const invalidNamePattern = /^(?:[ㄱ-ㅎㅏ-ㅣ]+)$/;
    const repeatedCharPattern = /^(.)\1+$/;
    if (!namePattern.test(name)) {
        alert("이름은 2~5글자 한글로 입력해 주세요.");
        return;
    }
    if (invalidNamePattern.test(name) || repeatedCharPattern.test(name)) {
        alert("이름을 확인해 주세요.");
        return;
    }
    // 2. Phone validation: 11-14 digits (aligned with cancer.txt)
    const phonePattern = /^[0-9]{11,14}$/;
    if (!phonePattern.test(phone)) {
        alert("연락처는 11~14자리 숫자만 입력해 주세요.");
        return;
    }
    if (!agree) {
        alert("개인정보 수집 및 이용에 동의해야 상담이 가능합니다.");
        return;
    }
    // 3. Construct post content with consult type
    const currentPageUrl = window.location.href;
    const postContent = `상담신청: ${consultType}<br>이름: ${name}<br>연락처: ${phone}<br>신청페이지: ${currentPageUrl}`;
    // Debugging: Log post content and form fields
    console.log("postContent:", postContent);
    console.log("Form fields:", {
        bo_table: form.querySelector('input[name="bo_table"]').value,
        wr_name: name,
        wr_content: postContent,
        wr_subject: name + " 님의 상담 요청",
        consult_type: consultType
    });
    // Set subject and content
    const subjectHidden = document.getElementById('wr_subject_hidden');
    if (subjectHidden) {
        subjectHidden.value = name + " 님의 상담 요청";
    }
    const phoneInput = document.getElementById('phone');
    if (phoneInput) {
        phoneInput.value = postContent;
    }
    // Debugging: Log FormData
    const formData = new FormData(form);
    for (let [key, value] of formData.entries()) {
        console.log(`FormData: ${key} = ${value}`);
    }
    // AJAX request
    fetch(form.action, {
        method: 'POST',
        body: formData
    })
    .then(response => {
        // Debugging: Log response status and headers
        console.log("Response status:", response.status, response.statusText);
        console.log("Response headers:", [...response.headers.entries()]);
        if (!response.ok) {
            throw new Error(`HTTP error! Status: ${response.status} ${response.statusText}`);
        }
        return response.text();
    })
    .then(responseText => {
        // Debugging: Log response text
        console.log("Response text:", responseText);
        // Use cancer.txt's success condition
        if (responseText.includes("location.replace") || responseText.includes("onclick=")) {
            alert("상담 신청이 완료되었습니다.");
            form.reset();
        } else {
            alert("전송에 실패했습니다. 다시 시도해 주세요.");
            console.error("Unexpected response:", responseText);
        }
    })
    .catch(error => {
        console.error("Fetch error:", error);
        alert("서버 오류가 발생했습니다: " + error.message);
    });
});
// Modal open/close (integrated from cancer.txt and index_n.txt)
document.getElementById('openModal').addEventListener('click', function(e) {
    e.preventDefault();
    document.getElementById('privacyModal').style.display = 'flex';
});
document.getElementById('closeModal').addEventListener('click', function() {
    document.getElementById('privacyModal').style.display = 'none';
});
// index_n.txt's existing banner slider and modal script
document.addEventListener('DOMContentLoaded', function() {
    const bannerRight = document.querySelector('.banner-right');
    let isDown = false;
    let startX;
    let scrollLeft;
    let autoScroll;
    // Drag functionality
    bannerRight.addEventListener('mousedown', (e) => {
        isDown = true;
        bannerRight.classList.add('active');
        startX = e.pageX - bannerRight.offsetLeft;
        scrollLeft = bannerRight.scrollLeft;
        clearInterval(autoScroll);
        bannerRight.style.scrollBehavior = 'auto';
    });
    bannerRight.addEventListener('mouseleave', () => {
        isDown = false;
        bannerRight.classList.remove('active');
        bannerRight.style.scrollBehavior = 'smooth';
        startAutoScroll();
    });
    bannerRight.addEventListener('mouseup', () => {
        isDown = false;
        bannerRight.classList.remove('active');
        bannerRight.style.scrollBehavior = 'smooth';
        startAutoScroll();
    });
    bannerRight.addEventListener('mousemove', (e) => {
        if (!isDown) return;
        e.preventDefault();
        const x = e.pageX - bannerRight.offsetLeft;
        const walk = (x - startX) * 2;
        bannerRight.scrollLeft = scrollLeft - walk;
    });
    // Touch functionality
    bannerRight.addEventListener('touchstart', (e) => {
        isDown = true;
        startX = e.touches[0].pageX - bannerRight.offsetLeft;
        scrollLeft = bannerRight.scrollLeft;
        clearInterval(autoScroll);
        bannerRight.style.scrollBehavior = 'auto';
    });
    bannerRight.addEventListener('touchend', () => {
        isDown = false;
        bannerRight.style.scrollBehavior = 'smooth';
        startAutoScroll();
    });
    bannerRight.addEventListener('touchmove', (e) => {
        if (!isDown) return;
        const x = e.touches[0].pageX - bannerRight.offsetLeft;
        const walk = (x - startX) * 2;
        bannerRight.scrollLeft = scrollLeft - walk;
    });
    // Auto-scroll functionality
    function startAutoScroll() {
        clearInterval(autoScroll);
        autoScroll = setInterval(() => {
            const cardWidth = window.innerWidth <= 768 ? 200 + 20 : 250 + 20;
            const maxScroll = bannerRight.scrollWidth - bannerRight.clientWidth;
            if (bannerRight.scrollLeft + cardWidth >= maxScroll) {
                setTimeout(() => {
                    bannerRight.style.scrollBehavior = 'auto';
                    bannerRight.scrollLeft = 0;
                    bannerRight.style.scrollBehavior = 'smooth';
                }, 500);
            } else {
                bannerRight.scrollLeft += cardWidth;
            }
        }, 2000);
    }
    bannerRight.style.scrollBehavior = 'smooth';
    startAutoScroll();
});
</script>

 

조언 부탁드립니다ㅠㅠ

그누5 버전은 가장 최신이고 

서버 환경은 UTF-8 (PHP8.4, mariadb-10.x) 입니다.

 

이 질문에 댓글 쓰기 :

답변 4

https://sir.kr/g5_skin/60030

좋은 자료 알려주셔서 감사합니다!

아직 정확한 원인은 못찾았는데 이 자료로 설치 후 테스트해보다가
테이블명만 다른 게시글로 변경했는데 잘 작동하네요;;

다른 렌딩페이지에서는 기존대로 tl_qa 테이블로 잘 쌓이고
메인은 다른 테이블명으로 수정하니까 되네요;;;

도움 주셔서 감사합니다!

ai로 한건가요?? 

암튼 저거 개발자도구 켜서 네트워크로 확인해보세요

에러 로그로 내용이 잘 들어가는데 페이로드 문제 없는지 그리고 응답이나 시작점 눌러서 json 출력 잘되는지 꼼꼼히 확인해보세요

index 에 common 파일 인클루드 되어있나요?

아래 3개중에 하나일것 같은데 확인한번 해보세요

 

PHP 토큰 미처리    index.html → index.php로 변경 + common.php 포함
JS 값 누락    wr_subject, wr_content가 정상적으로 세팅되는지 확인
응답만 받음    fetch 응답 확인 + 서버단 POST값 수신 여부 확인

답변을 작성하시기 전에 로그인 해주세요.
전체 128,859 | RSS
QA 내용 검색

회원로그인

(주)에스아이알소프트 / 대표:홍석명 / (06211) 서울특별시 강남구 역삼동 707-34 한신인터밸리24 서관 1404호 / E-Mail: admin@sir.kr
사업자등록번호: 217-81-36347 / 통신판매업신고번호:2014-서울강남-02098호 / 개인정보보호책임자:김민섭(minsup@sir.kr)
© SIRSOFT