포트폴리오 사이트나 회사 소개 홈페이지를 보면 하단에 contact us라고 적혀있는 연락하기 폼을 많이 보았을 것 같아요.
메일 주소에 mailto를 사용하면 구현은 가능하지만 컴퓨터 메일 앱이 켜지면서 직접 보내는 형태이기 때문에 서드파티 앱을 한번 거쳐야 하기 때문에 사용자 경험이 그리 좋아 보이진 않았기에 페이지 내에서만 해결하려고 했습니다.
기능을 찾아보던 중, EmailJS는 월 200건만 무료로 보낼 수 있기에 다른 방법을 찾아보던 중 google에서 제공하는 기능을 사용해보고자 합니다!
- 백엔드(db) 없이 프론트엔드로만 구현
- 각 정보를 입력하고 submit 버튼을 누르면 스프레드시트에 데이터 저장 및 지정한 메일로 메일이감
- form 액션으로 요청하는 것이 아닌 fetch, axios 등 데이터 를 사용하여 구현.
로직을 간단하게 정리해 보자면
메일을 보내고 스프레드시트에 데이터가 저장되는 것은 스프레드시트 내의 스크립트가 처리하고, next.js 내에서는 fetch를 사용하여 해당 스프레드시트 스크립트에 데이터 저장을 요청을 합니다.
1 . sample spreadsheet 복사
https://docs.google.com/spreadsheets/d/1Bn4m6iA_Xch1zzhNvo_6CoQWqOAgwwkOWJKC-phHx2Q/copy
Google 계정에 로그인 -> "사본 만들기" 클릭
데이터를 쌓고, 메일을 보내는 스크립트가 있는 스프레드시트 샘플을 복사한다고 생각하면 됩니다.
2. Apps Script 열어, TO_ADDRESS를 설정
1. 확장프로그램 > Apps Script 열기
2. 상단에 있는 var TO_ADDRESS = "example~@" 의 주석을 풀고 본인의 이메일로 지정 후 저장
3. 해당 스프레드 시트의 스크립트를 웹 앱으로 배포
1. 배포 > 새배포 클릭
2. 아무 설명 써넣고 배포하기
❗️액세스 권한이 있는 사용자 = 모든 사용자로 설정해 주어야 스크립트에 요청을 할 수 있습니다.
3. 본인 메일 계정으로 액세스 승인
이때, 권한 인증에 관련 경고 문구(Google hasn’t verified this app)가 나오는데
하단에 Advanced를 누르고 Go to html contact form sendEmail(unsafe)를 누르고 Allow를 선택합니다.
4. 웹 앱 Url 복사하기
4. form html 만들기
<form
id="submit-to-google-sheet"
className="flex flex-col space-y-4"
onSubmit={handleContact}
autoComplete="off"
>
<input className="hidden" name="time" value={setCurrentTime()} /> // 생략가능
<input
className="w-full h-10 flex items-center px-3 rounded-4 border"
name="name"
placeholder="name"
required
/>
<input
className="w-full h-10 flex items-center px-3 rounded-4 border"
name="email"
placeholder="email"
required
/>
<input
className="w-full h-40 flex p-3 rounded-4 border"
name="message"
placeholder="message"
required
/>
<button
className="w-full h-10 flex items-center justify-center rounded-4 bg-green-950 text-white"
type="submit"
>
SUBMIT
</button>
</form>
❗️input의 name은 본인의 스프레드 시트의 컬럼네임과 일치해야 합니다.
form 제출하기를 누르면 리다이렉트가 되어 결괏값을 받는 것이 아닌, handleContact 함수에서 처리하기 위해 위와 같이 짰습니다.
5. fetch로 웹앱 url에 데이터 보내기
const handleContact = (event: any) => {
event.preventDefault();
const scriptURL =
'https://script.google.com/macros/s/AKfycbw1UELQfnH~~~~~;' //본인 시트의 웹앱 url
const form = document.getElementById(
'submit-to-google-sheet'
) as HTMLFormElement;
fetch(scriptURL, { method: 'POST', body: new FormData(form) })
.then(response => {
console.log('Success!', response);
form.reset(); // 보내는 값이 성공값이면, form data reset
})
.catch(error => console.error('Error!', error.message));
};
* 현재시간 저장함수 (한국시간)
const setCurrentTime = () => {
const TIME_ZONE = 1000 * 60 * 60 * 9;
const resultTime = new Date(new Date().getTime() + TIME_ZONE)
.toISOString()
.replace('T', ' ')
.slice(0, -5);
return String(resultTime);
};
6. 결과
submit 버튼을 누르면 시간텀을 두고 성공값이 옵니다.
성공값이 온다면 본인이 지정한 메일과 스프레드 시트에도 쌓이게 됩니다.
Timestamp값은 form에서 보내는 값이 아닌, 스프레드시트 스크립트에서 저장하는 값으로 한국표준시간으로 저장되지 않습니다. 스크립트 내에서도 new date() 값을 저장하는데 왜 9시간 차이가 아니라 8시간 차이가 나는지 몰라서 저는 new Date에 9시간을 더한 값을 form에 따로 hidden값으로 보내어 저장하도록 하였습니다. 왜 8시간이 차이가 나는지 아시는 분 있음 답변 부탁드리겠습니다 🥺
'Web > React & Next.js' 카테고리의 다른 글
React | Next.js 환경에서 나이스(PASS) 신원인증 구현하기 (0) | 2023.11.05 |
---|---|
React | Kakao Map Api를 사용하여 주소로 지도 그리기 (0) | 2023.05.14 |
Next.js 에서 Next/Image를 사용하여 이미지 처리하기 (0) | 2023.02.16 |
Next.js | Next.js + Styled-Components 초기 세팅 (next 13) (0) | 2023.02.14 |
Next.js | Next.js + typescript 초기 세팅 (next 13) (0) | 2023.02.14 |