스프레드시트 appscript이용하여 데이터저장하기

최지웅·2025년 3월 23일
0

gcs

목록 보기
22/78

목적

프리토타입을 이용하여 사용자 이메일 정보를 수집하려고 한다.

기존에 내가 해본 방법은 java spring boots를 javac으로 만들어 aws ec2에 올리고 h2 db에 저장하는 방식이었는데, 현 상황에서는 이 정보를 수집하기 위해 db가 필요하지도 않고 aws운영 비용도 부담해야하기에 적절하지 않다고 판단했다.
고로 이메일 정도를 저장할 수 있는 다른 가벼운 방법을 찾아보던 중, 스프레드 시트의 확장 프로그램인 app script를 이용해 post 요청만으로 추가할 수 있다는 방법을 알게 되었다.

문제

하지만 현재 기능 구현이 제대로 되지 않는 문제에 봉착했기에 오늘 그 디버깅을 진행해보려고 한다.

코드

우선 아래는 스프레트 시트에 데이터를 추가해주는 app script이다.

function doPost(e) {
  try {
    // ✅ 명확하게 스프레드시트 ID 설정
    const sheet = SpreadsheetApp.openById('~~~~~~~~~').getSheetByName('시트1');

    const params = JSON.parse(e.postData.contents);
    const email = params.email;

    if (!email || !validateEmail(email)) {
      throw new Error("유효하지 않은 이메일 형식입니다.");
    }

    // ✅ 스프레드시트에 데이터 추가
    sheet.appendRow([new Date(), email]);

    // ✅ 응답 반환
    const result = {
      status: "success",
      email: email
    };

    return ContentService
      .createTextOutput(JSON.stringify(result))
      .setMimeType(ContentService.MimeType.JSON);

  } catch (error) {
    Logger.log(error);
    return ContentService
      .createTextOutput(JSON.stringify({ status: "error", message: error.message }))
      .setMimeType(ContentService.MimeType.JSON);
  }
}

// ✅ 이메일 유효성 검사 함수
function validateEmail(email) {
  const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
  return regex.test(email);
}

아래는 웹 페이지에서 버튼 이벤트 시 post요청하는 script부분이다

<script>
        const fadeInElements = document.querySelectorAll('.fade-in');
		const slideInLeftElements = document.querySelectorAll('.slide-in-left');
		const slideInRightElements = document.querySelectorAll('.slide-in-right');

		const observer = new IntersectionObserver((entries) => {
			entries.forEach(entry => {
				if (entry.isIntersecting) {
					entry.target.classList.add('active');
					observer.unobserve(entry.target);
				}
			});
		}, {
			threshold: 0.2
		});

		fadeInElements.forEach(element => {
			observer.observe(element);
		});

		slideInLeftElements.forEach(element => {
			observer.observe(element);
		});

		slideInRightElements.forEach(element => {
			observer.observe(element);
		});

		const submitEmail = async (event) => {
			event.preventDefault();

			const email = document.getElementById('email').value;
			if (!email) {
				alert('이메일을 입력해주세요.');
				return;
			}

			try {
				const response = await fetch('https://script.google.com/macros/s/~~~~~~~~~~~~/exec', {
					method: 'POST',
					mode: 'cors', // ✅ CORS 설정 추가
					headers: {
						'Content-Type': 'application/json'
					},
					body: JSON.stringify({ email })
				});

				if (!response.ok) {
					throw new Error(`HTTP 오류! 상태 코드: ${response.status}`);
				}

				const result = await response.json();
				if (result.status === "success") {
					alert(`이메일이 등록되었습니다: ${result.email}`); // ✅ 템플릿 리터럴 사용 수정
				} else {
					alert(`등록 실패: ${result.message}`);
				}
			} catch (error) {
				console.error('전송 오류:', error);
				alert('서버에 연결할 수 없습니다. 배포 상태 및 URL을 확인해주세요.');
			}
		};
    </script>

현재 문제 사항은 html에서 버튼 누를 시 제대로 요청은 보내지는 듯 하나, 스프레드 시트에 추가가 안된다.

디버깅

1차적으로 로그를 직접 찍어보려고 한다. 표시한 두 메시지 모두 접근 가능했다.


2차적으로 로그를 찍어보았는데 표시한 두 메시지 모두 접근 불가능했다.


GPT가 제안한 해결 방법은 다음과 같다.

  • Apps Script의 엑세스 권한 문제
  • Script 수정

첫번째로 html Script를 수정해보자. 버튼을 await가 아닌 onclick=이벤트로 설정하고 아래와 같이 수정하였다.

const submitEmail = async (event) => {
		event.preventDefault();

		const email = document.getElementById('email').value;
		if (!email) {
			alert('이메일을 입력해주세요.');
			return;
		}

		try {
			alert("send request");
			const response = await fetch('https://script.google.com/macros/s/~~~~~~~~~~~~~/exec', {
				method: 'POST',
				//mode: 'cors', // ✅ CORS 설정 추가
				headers: {
					'Content-Type': 'application/json'
				},
				body: JSON.stringify({ email })
			});

			alert("get response"); // ✅ 여기까지 오면 응답이 정상적으로 온 상태

			if (!response.ok) {
				throw new Error(`HTTP 오류! 상태 코드: ${response.status}`);
			}

			const result = await response.json();
			if (result.status === "success") {
				alert(`이메일이 등록되었습니다: ${result.email}`); // ✅ 템플릿 리터럴 사용 수정
			} else {
				alert(`등록 실패: ${result.message}`);
			}
		} catch (error) {
			console.error('전송 오류:', error);
			alert('서버에 연결할 수 없습니다. 배포 상태 및 URL을 확인해주세요.');
		}
	};



까지 도달했음을 알 수 있었다.


다시 GPT에게 자문을 구해보자.

  • 배포 상태의 문제일 가능성이 크다!

배포 상태를 변경해보았다.


둘 다 여전히 작동이 안된다.


https://3d-yeju.tistory.com/105
를 참고했는데도 똑같다..



수정후도 같다.



구글 시트 API 추가


해결 완료

ajax 로 reqeust를 보내고 헤더 script에 jquery를 추가하였다.

    $(document).ready(function() {
        $('#contactForm').on('submit', function(event) {
            event.preventDefault();

            // 입력 값 가져오기
            var name = $('#name').val();
            var email = $('#email').val();
            var message = $('#message').val();

            console.log(name, email, message);

            $.ajax({
                type: "POST",
                url: "https://script.google.com/macros/s/~~~~~~~/exec",
                data: {
                    "이름": name,
                    "이메일": email,
                    "문의사항": message
                },
                success: function(response) {
                    alert('사전예약이 성공적으로 접수되었습니다.');
                    $('#contactForm')[0].reset(); // 폼 초기화
                },
                error: function(err) {
                    alert('오류가 발생했습니다. 다시 시도해주세요.');
                    console.log(err);
                }
            });
        });
    });

	<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.6.4/jquery.min.js"></script>

그리고 추가적으로 구글 애널리틱스 연동하여 클릭율 조회.

profile
이제 4학년!!!

0개의 댓글