소개
home

객체(Object)의 key와 value 활용하기

태그
스크립트
구글시트
Object
for
Logger
log
array
getSheetByName
MailApp
sendEmail
if
else
샘플링크
https://docs.google.com/spreadsheets/d/1Ralu7pbakyAlimek1IfSUYRrQ8bMqRSNIZk00TWzjYE/edit?usp=sharing
난이도
☆☆
4 more properties

목적

스프레드시트에서 사용하는 객체(Object)에 대해 설명하고, 메일을 전송하는 상황에서 객체를 어떻게 활용할 수 있는지 알아 보겠습니다.
"메일 전송하기" 페이지에서 다룬 시트를 사용하기 때문에, 메일 전송 스크립트에 대해 이해가 안 되는 부분이 있으신 경우, 해당 페이지의 포스팅을 먼저 보시고 본 페이지로 넘어 오시는 것을 권장드립니다.

예제 1 - 객체 기본 문법, 임의의 key 에 할당된 value 호출하기

sendEmails 라는 이름의 함수 아래로 임의의 이름을 가지는 함수를 다음과 같이 추가합니다.
예시에서 사용된 함수명은 learn 입니다.
예제 1 코드
function learn(){ var info = { name: "이진수", gender: "남성", eyecolor: "검정색", age: "28" }; Logger.log(info["name"]); }
JavaScript
스크립트
learn 함수가 실행되도록 설정한 다음, 위의 자바스크립트를 실행했을 때 실행 로그에 아래 이미지와 같은 결과가 출력됩니다.
스크립트 결과
예제 1 코드에서 6번째 줄의 코드 중, name 부분을 아래와 같이 다른 값으로 대체하면 실행 로그에 출력되는 결과가 달라집니다.
Logger.log(info["gender"]);
JavaScript
스크립트
스크립트 결과
실행 로그의 출력 값이 "남성" 으로 출력됩니다.
Logger.log(info["eyecolor"]);
JavaScript
스크립트
스크립트 결과
실행 로그의 출력 값이 "검정색" 으로 출력됩니다.
Logger.log(info["age"]);
JavaScript
스크립트
스크립트 결과
실행 로그의 출력 값이 "28" 로 출력됩니다.

예제 2-1 - 객체에서 key 값 호출하기

스크립트 코드를 한 번만 실행하여 info 변수로 담은 객체의 모든 key 값을 호출해 보겠습니다.
예제 2-1 코드
function learn(){ var info = { name: "이진수", gender: "남성", eyecolor: "검정색", age: "28" }; for(var key in info){ Logger.log(key); } }
JavaScript
스크립트
for(var key in info) : 반복문을 사용하여 info 변수로 지정한 객체 내에서 각 항목의 콜론(:) 의 좌측에 있는 모든 값을 변수 key 에 지정합니다.
스크립트 결과

예제 2-2 - 객체에서 key 값과 value 값 동시에 호출하기

객체에서 콜론(:) 기준으로 왼쪽 값과 오른쪽 값을 동시에 출력해 보겠습니다.
function learn(){ var info = { name: "이진수", gender: "남성", eyecolor: "검정색", age: "28" }; for(var [key,value] in info){ Logger.log(key); Logger.log(value); } }
JavaScript
스크립트
스크립트 결과
스크립트 실행에는 오류가 생기지 않았지만, 출력 결과에서 문제가 생깁니다.
실행 로그를 보면 각 객체의 key 값의 앞 두 글자씩만 순서대로 출력됩니다.
이는 코딩 자체의 문제라기보다는 2021년 8월 6일 기준 구글의 스크립트편집기가 사용하는 V8 자바스크립트 엔진이 새 버전으로 적용된 상태이므로, 새 버전에서 사용하는 문법에 맞지 않아 다음의 기본 문법 버전 반복문이 제대로 실행되지 않는 것입니다.
for(var [key,value] in info){
JavaScript
스크립트 코드 중 문제가 된 부분
새로운 V8 자바스크립트 엔진에서 사용하는 문법에 맞는 코드는 아래와 같으며, 이와 같은 이유로, 객체의 key 값과 value 값을 동시에 받는 반복문을 작성할 경우 아래와 같은 문법으로 작성하는 것을 권장드립니다.
for (let [key, value] of Object.entries(info)) {
JavaScript
수정이 적용된 코드 형태
수정을 적용할 코드로 스크립트를 실행해 보겠습니다.
function learn(){ var info = { name: "이진수", gender: "남성", eyecolor: "검정색", age: "28" }; for (let [key, value] of Object.entries(info)) { Logger.log(key); Logger.log(value); } }
JavaScript
스크립트 (코드 픽스)
예제 2-2 코드 결과물
스크립트 결과
이미지와 같이 정상적으로 key 값과 value 값이 출력됨을 확인할 수 있습니다.

예제 3 - value가 배열의 데이터로 저장된 객체의 key와 value 활용하기

배열로 구성된 데이터를 value 로 담아 key에 저장할 수 있습니다. 그 key에 할당된 데이터를 실행 로그에 호출해 보겠습니다.
function learn(){ var info = { name: "이진수", gender: "남성", eyecolor: "검정색", age: "28", favcolors: ["#000000", "#ff3366", "#000cff"] }; Logger.log(info["favcolors"]); }
JavaScript
스크립트
스크립트 결과
예제 3 코드에서 배열 내에 입력된 데이터들은 기본적으로 순서를 나타내는 다음 숫자값을 가지고 있습니다.
"#000000" : [0] - 첫 번째 순서
"#ff3366" : [1] - 두 번째 순서
"#000cff" : [2] - 세 번째 순서
따라서 배열의 두 번째 데이터인 #ff3366 이라는 value 값을 실행 로그에 호출하기 위해서는 아래와 같이 코드를 작성하여 스크립트를 실행하면 됩니다.
function learn(){ var info = { name: "이진수", gender: "남성", eyecolor: "검정색", age: "28", favcolors: ["#000000", "#ff3366", "#000cff"] }; Logger.log(info["favcolors"][1]); }
JavaScript
스크립트
스크립트 결과

예제 4 - value가 객체의 데이터로 저장된 객체의 key와 value 활용하기

객체로 구성된 데이터를 value 로 담아 key에 저장할 수 있습니다. 그 key에 할당된 데이터를 실행 로그에 호출해 보겠습니다.
function learn(){ var info = { name: "이진수", gender: "남성", eyecolor: "검정색", age: "28", favcolors: ["#000000", "#ff3366", "#000cff"], address: {street: "별내중앙로 26", city: "남양주시", zipcode: 12113} }; Logger.log(info["address"]["city"]); }
JavaScript
스크립트
예시로, address 라는 key에 저장된 객체 데이터 내에 있는
city 키에 할당하는 value 를 호출하길 원한다고 가정하겠습니다.
스크립트 결과
이미지처럼 city 키에 저장된 "남양주시" value 가 호출됩니다.

예제 5 - 객체를 활용하여 메일 전송 폼 개선하기

지금까지 배운 객체 문법을 활용하여, 메일 전송 스크립트를 개선해 봅시다.
시트 편집
연락처 시트의 변경 사항:
날짜 값을 표시하는 D 열을 추가했고, D2 셀, D3 셀에 당일 날짜의 결과값을 반환하는 함수인 today() 함수를 추가했습니다.
메일 전송 내용 시트의 변경 사항 :
2번째 줄에 {data} 라는 날짜값을 출력하는 변수 데이터를 추가했습니다.
스크립트편집기 편집
예제 5 코드 - sendEmails() 함수 (수정 전)
function sendEmails(){ SpreadsheetApp.getActiveSpreadsheet().getSheetByName("연락처").activate(); var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); var lr = ss.getLastRow(); var templateText = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("메일 전송 내용").getRange(1, 1).getValue(); var quotaLeft = MailApp.getRemainingDailyQuota(); Logger.log(quotaLeft); if((lr-1) > quotaLeft){ Browser.msgBox("현재 고객님의 오늘 메일 전송 잔여량은 " + quotaLeft + " 회이며, " + (lr-1) + " 개의 메일을 보내려고 시도하셨습니다. 이메일이 전송되지 않았습니다."); } else { for (var i=2;i<=lr;i++){ var currentEmail = ss.getRange(i, 1).getValue(); var currentName = ss.getRange(i, 2).getValue(); var currentClassTitle = ss.getRange(i, 3).getValue(); var messageBody = templateText.replace("{name}",currentName).replace("{title}",currentClassTitle); var subjectLine = "다음 클래스로 등록된 이메일로 전송되었습니다 : " + currentClassTitle + " 클래스"; MailApp.sendEmail(currentEmail, subjectLine, messageBody); } // 반복문 종료 } // else 문 종료. }
JavaScript
예제 5 코드 - sendEmails() 함수 (수정 후)
function sendEmails(){ SpreadsheetApp.getActiveSpreadsheet().getSheetByName("연락처").activate(); var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); var lr = ss.getLastRow(); var templateText = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("메일 전송 내용").getRange(1, 1).getValue(); var quotaLeft = MailApp.getRemainingDailyQuota(); Logger.log(quotaLeft); if((lr-1) > quotaLeft){ Browser.msgBox("현재 고객님의 오늘 메일 전송 잔여량은 " + quotaLeft + " 회이며, " + (lr-1) + " 개의 메일을 보내려고 시도하셨습니다. 이메일이 전송되지 않았습니다."); } else { for (var i=2;i<=lr;i++){ var currentEmail = ss.getRange(i, 1).getValue(); var currentName = ss.getRange(i, 2).getValue(); var currentClassTitle = ss.getRange(i, 3).getValue(); var currentDate = ss.getRange(i, 4).getDisplayValue(); var infomation = { name: currentName, title: currentClassTitle, date: currentDate }; var messageBody = templateEngine(infomation, templateText); Logger.log(messageBody); var subjectLine = "다음 클래스로 등록된 이메일로 전송되었습니다 : " + currentClassTitle + " 클래스"; MailApp.sendEmail(currentEmail, subjectLine, messageBody); } // 반복문 종료 } // else 문 종료. }
JavaScript
수정된 내역.
8번째 줄의 다음 코드 위에 있는 공백 줄을 제거했습니다.
var templateText = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("메일 전송 내용").getRange(1, 1).getValue();
JavaScript
조건문에서 else 문의 내부 코드가 수정되었습니다.
1.
i행 4열의 데이터 입력값을 "시트에 표시된 셀의 데이터 형태로" 받는 변수 currentDate 추가.
var currentDate = ss.getRange(i, 4).getDisplayValue();
JavaScript
i가 2부터 시작하기 때문에 D2 셀부터 시작해서 아래로 데이터가 마지막으로 입력된 셀까지의 모든 셀의 데이터를 받되, 시트의 셀에 표시된 형태로 데이터를 받습니다.
getValue() 함수가 아니라 getDisplaValue() 함수가 기재되었다는 점에 유의하세요.
2.
시트의 이름, 클래스, 날짜 데이터값을 각각 name, title, date 키에 담은 객체 데이터로 받는 변수 information 추가.
var infomation = { name: currentName, title: currentClassTitle, date: currentDate };
JavaScript
3.
변수 messageBody 를 다음과 같이 수정.
수정 전
var messageBody = templateText.replace("{name}",currentName).replace("{title}",currentClassTitle);
JavaScript
기존 변수는 "메일 전송 내용" 시트의 1행 1열 데이터에서 {name} 부분을 "연락처" 시트의 B2 셀부터 아래로 마지막으로 데이터가 입력된 셀까지의 모든 셀의 데이터로 대치하고, {title} 부분을 "연락처" 시트의 C2 셀부터 아래로 마지막으로 데이터가 입력된 셀까지의 모든 셀의 데이터로 대치하는 함수였습니다.
수정 후
var messageBody = templateEngine(infomation, templateText);
JavaScript
새로 수정된 버전은 templateEngine 이라는 함수에서 첫 번째 인수값을 information 변수로, 두 번째 인수값을 templateText 변수로 받도록 변경하는 함수입니다.
예제 5 코드 - templateEngine(obj, templateText) 함수
function templateEngine(obj, templateText){ var messageBody = templateText; for (let [key, value] of Object.entries(obj)) { messageBody = messageBody.replace("{"+ key +"}",value); } return messageBody; }
JavaScript
추가된 예제 5 코드 상세 정보
첫 번째 인수값을 obj, 두 번째 인수값을 templateText 로 받는 함수가 생성되었습니다.
이 함수는 "메일 전송 내용" 시트의 1행 1열 데이터를 변수 messageBody 로 지정하며, obj 라는 이름의 객체에 key, value 값이 존재하는 동안 반복적으로 수행합니다.
sendEmails() 함수 기준으로, {name} 값을 "연락처" 시트의 이름 데이터에 해당하는 value로, {title} 값을 "연락처" 시트의 클래스 데이터에 해당하는 value로, {date} 값을 "연락처" 시트의 날짜 데이터에 해당하는 value로 변경하는 작업을 반복하고, 반복하여 수행된 결과를 변수 messageBody 로 도로 대입하는 함수입니다.
원래 obj 라는 값은 이 함수에서 임의로 지정한 함수이기 때문에 그냥 sendEmails() 함수 스크립트를 실행할 경우 문제가 생기지만, sendEmails() 함수 내에 다음 코드로 인해 인수값이 대치되므로 정상적으로 실행됩니다.
var messageBody = templateEngine(infomation, templateText);
JavaScript
이 작업이 "연락처" 시트의 데이터 값이 존재하는 동안 반복해서 수행하는 코드 안에 있기 때문에 "연락처" 시트에 존재하는 모든 메일 주소로 메일이 전송되는 것입니다.
실행 결과는 다음과 같습니다.
스크립트 결과 (실행 로그)
Logger.log(quotaLeft); 스크립트로 인해 실행 로그의 2번째 칸에 일일 메일 전송 가능 잔여 횟수를 뜻하는 100.0 값이 출력되었습니다.
반복문 내부의 Logger.log(messageBody); 스크립트로 인해 실행 로그의 3번째 칸에 다음 내용이 출력되었습니다.
빨간 텍스트 : "메일 전송 내용" 시트에서 {name} 이 대치된 결과값.
노랑 텍스트 : "메일 전송 내용" 시트에서 {title} 이 대치된 결과값.
초록 텍스트 : "메일 전송 내용" 시트에서 {date} 이 대치된 결과값.
안녕하세요, 이진수1. 이 메일은 앱디자인, 캐릭터박스 클래스로 등록된 귀하께 202197일 화요일 에 전송된 이메일입니다. 구글 앱 스크립트는 유용한 기능들이 많이 있습니다. 여러분들도 한 번 시도해 보시기 바랍니다.
JavaScript
이 내용을 담은 메일이 "다음 클래스로 등록된 이메일로 전송되었습니다 : 앱디자인, 캐릭터박스 클래스" 라는 구문을 제목으로 지정하여 jinsoo@appdesign.co.kr 주소와 jinsoo@characterbox.co.kr 주소로 각각 1개씩 전송되었습니다.
반복문 내부의 Logger.log(messageBody); 스크립트로 인해 실행 로그의 4번째 칸에 다음 내용이 출력되었습니다.
빨간 텍스트 : "메일 전송 내용" 시트에서 {name} 이 대치된 결과값.
노랑 텍스트 : "메일 전송 내용" 시트에서 {title} 이 대치된 결과값.
초록 텍스트 : "메일 전송 내용" 시트에서 {date} 이 대치된 결과값.
안녕하세요, 이진수2. 이 메일은 오토오피스 클래스로 등록된 귀하께 202197일 화요일 에 전송된 이메일입니다. 구글 앱 스크립트는 유용한 기능들이 많이 있습니다. 여러분들도 한 번 시도해 보시기 바랍니다.
JavaScript
이 내용을 담은 메일이 "다음 클래스로 등록된 이메일로 전송되었습니다 : 오토오피스 클래스" 라는 구문을 제목으로 지정하여 jinsoo@autooffice.co.kr 주소로 1개가 전송되었습니다.

관련 포스팅