# data[].attributes.attachment_link.title
발표사진_쉽게 배우는 모바일 앱개발

# data[].attributes.attachment_link.title
최종 과제물.pptx

# data[].attributes.body
2023027610_노현우_발표자료

# data[].attributes.attachment_link.title
2023027610_노현우_기말발표자료

# data[].attributes.attachment_link.title
프차피티 디자인 김예은

# data[].attributes.attachment_link.title
쉽게배우는모바일앱개발_16주차

# data[].attributes.headline
최지훈 6/10 데이터베이스

# data[].attributes.subject
최지훈 6/10 데이터베이스

# data[].attributes.body
// 변수 선언 ====================================================================

// DB, Table 데이터 담을 변수

var DB_Date, Table_Data;

// 받아오는 파라미터 담을 변수

var p;

// 되돌려주는 변수

var result, msg, value;

// value 배열 변수

var arrvalue;

// 통신 함수 ====================================================================

// 유니티에서 Post 호출됨

function doPost(e)

{

  // 파라미터 받기

  p = e.parameter;



  // reg 체크

  if(!regCheck(p.DB_Name) ||!regCheck(p.Table_Name) || !regCheck(p.API_Name) || !regCheck(p.Value))

    return ContentService.createTextOutput("");



  // value 값 -> 배열

  valueToArray(p.Value);

  // DB 경로 재설정

  DB_Date, Table_Data = null;

  switch(p.DB_Name)

  {

    // 시트 파일 이름 = 주소 대입

    case "mydb": DB_Date = SpreadsheetApp.openById("1ndrIhJkom50zQDss1G8A_tFM0g_TzLkUoXtHlYXNBf4");

      // 시트 이름 = 시트 번호 대입

      switch(p.Table_Name)

      {

        case "Auth": Table_Data = DB_Date.getSheets()[0];

          break;

      }

      break;

  }

  //DB 경로 에러

  if(!DB_Date || !Table_Data)

  {

    setResult("ERROR", "DB경로가 올바르지 않습니다.");

    return;

  }



  // 알맞은 API 실행

  switch(p.API_Name)

  {

    case "Create": Create(); break;

    case "Read": Read(); break;

    case "Update": Update(); break;

    case "Delete": Delete(); break;



    default :

      setResult("ERROR", "호출한 API가 없습니다.");

      return;

      break;

  }

  // 유니티로 결과 돌려주기

  return response();

}

// 유니티로 결과 돌려주기

function response()

{

  var json = {};

  // 어떤 DB 인지

  json.GSDB = p.DB_Name;

  // 어떤 Table 인지

  json.GStable = p.Table_Name;

  // 어떤 API 인지

  json.GSAPI = p.API_Name;

  // 수행 결과

  json.result = result;

  // 수행 메시지

  json.msg = msg;

  // 반환 값

  json.value = value;

  // json 형태로 담기

  jsonData = JSON.stringify(json);

  // 유니티로 전달

  return ContentService.createTextOutput(jsonData);

}

// 기능 함수 ====================================================================

// 수행 결과, 메시지 입력 함수

function setResult(_result, _msg)

{

  result = _result;

  msg = _msg;

}

// value 값 -> 배열

function valueToArray(val)

{

  const str = val;

  arrvalue = str.split("|");

  if(arrvalue.lenght < 2) arrvalue = val;

}

// reg 체크 함수

function regCheck(val)

{

  var regExp = /[\{\}\[\]\/?.,;"\)*~`!^\-+<>@\#$%&\\\=\(\'\"]/gi;

  if(regExp.test(val)) return false;

  else return true;

}

// API ====================================================================

// Create

function Create()

{

  // key 체크

  if(arrvalue[0] == "​"){

    setResult("ERROR", "키가 없습니다");

    return;

  }

  // key 중복 체크

  var cell = Table_Data.getRange(2, 1, Table_Data.getLastRow() - 1, 1).getValues();

  if(cell.some(row => row == arrvalue[0]))

  {

    setResult("ERROR", "이미 존재하는 키입니다");

    return;

  }

  // Create_Start-------------------------

  Table_Data.appendRow([arrvalue[0],arrvalue[1],arrvalue[2]]);

  setResult("OK", "main1의 " + arrvalue + "값 저장 완료");

  // Create_End-------------------------

}

// Read

function Read()

{

  // key 체크

  if(arrvalue[0] == "​"){

    setResult("ERROR", "키가 없습니다");

    return;

  }

  // key 중복 체크

  var cell = Table_Data.getRange(2, 1, Table_Data.getLastRow() - 1, 1).getValues();

  if(!cell.some(row => row == arrvalue[0]))

  {

    setResult("ERROR", "선택한 키값이 없습니다");

    return;

  }

  else

  {

    // Read_Start-------------------------

    for(i = 0; i < cell.length; i++)

    {

      if(cell[i][0] == arrvalue[0])

      {

        value = arrvalue[0] + "|";

        value += Table_Data.getRange(i+2, 2).getValues() + "|";

        value += Table_Data.getRange(i+2, 3).getValues();

        setResult("OK", "main1의 " + arrvalue + "값 읽기 완료");

        return;

      }

    }

    // Read_End-------------------------

  }

}

// Update

function Update()

{

  // key 체크

  if(arrvalue[0] == "​"){

    setResult("ERROR", "키가 없습니다");

    return;

  }

  // key 중복 체크

  var cell = Table_Data.getRange(2, 1, Table_Data.getLastRow() - 1, 1).getValues();

  if(!cell.some(row => row == arrvalue[0]))

  {

    setResult("ERROR", "선택한 키값이 없습니다");

    return;

  }

  else

  {

    // Update_Start-------------------------

    for(i = 0; i < cell.length; i++)

    {

      if(cell[i][0] == arrvalue[0])

      {

        Table_Data.getRange(i+2, 2).setValue(arrvalue[1]);

        Table_Data.getRange(i+2, 3).setValue(arrvalue[2]);

        setResult("OK", "main1의 " + arrvalue + "값 업데이트 완료");

        return;

      }

    }

    // Ypdate_End-------------------------

  }

}

// Delete

function Delete()

{

  // key 체크

  if(arrvalue[0] == "​"){

    setResult("ERROR", "키가 없습니다");

    return;

  }

  // key 중복 체크

  var cell = Table_Data.getRange(2, 1, Table_Data.getLastRow() - 1, 1).getValues();

  if(!cell.some(row => row == arrvalue[0]))

  {

    setResult("ERROR", "선택한 키값이 없습니다");

    return;

  }

  else

  {

    // Delete_Start-------------------------

    for(i = 0; i < cell.length; i++)

    {

      if(cell[i][0] == arrvalue[0])

      {

        Table_Data.deleteRow(i+2);

        setResult("OK", "main1의 " + arrvalue + "값 삭제 완료");

        return;

      }

    }

    // Delete_End-------------------------

  }

}



}

# data[].attributes.body
// 변수 선언 ====================================================================

// DB, Table 데이터 담을 변수

var DB_Date, Table_Data;

// 받아오는 파라미터 담을 변수

var p;

// 되돌려주는 변수

var result, msg, value;

// value 배열 변수

var arrvalue;

// 통신 함수 ====================================================================

// 유니티에서 Post 호출됨

function doPost(e)

{

// 파라미터 받기

p = e.parameter;

// reg 체크

if(!regCheck(p.DB_Name) ||!regCheck(p.Table_Name) || !regCheck(p.API_Name) || !regCheck(p.Value))

return ContentService.createTextOutput("");

// value 값 -> 배열

valueToArray(p.Value);

// DB 경로 재설정

DB_Date, Table_Data = null;

switch(p.DB_Name)

{

// 시트 파일 이름 = 주소 대입

case "#DBNAME#": DB_Date = SpreadsheetApp.openById("#DBID#");

// 시트 이름 = 시트 번호 대입

switch(p.Table_Name)

{

case "#TABLENAME#": Table_Data = DB_Date.getSheets()[0];

break;

}

break;

}

//DB 경로 에러

if(!DB_Date || !Table_Data)

{

setResult("ERROR", "DB경로가 올바르지 않습니다.");

return;

}

// 알맞은 API 실행

switch(p.API_Name)

{

case "Create": Create(); break;

case "Read": Read(); break;

case "Update": Update(); break;

case "Delete": Delete(); break;

default :

setResult("ERROR", "호출한 API가 없습니다.");

return;

break;

}

// 유니티로 결과 돌려주기

return response();

}

// 유니티로 결과 돌려주기

function response()

{

var json = {};

// 어떤 DB 인지

json.GSDB = p.DB_Name;

// 어떤 Table 인지

json.GStable = p.Table_Name;

// 어떤 API 인지

json.GSAPI = p.API_Name;

// 수행 결과

json.result = result;

// 수행 메시지

json.msg = msg;

// 반환 값

json.value = value;

// json 형태로 담기

jsonData = JSON.stringify(json);

// 유니티로 전달

return ContentService.createTextOutput(jsonData);

}

// 기능 함수 ====================================================================

// 수행 결과, 메시지 입력 함수

function setResult(_result, _msg)

{

result = _result;

msg = _msg;

}

// value 값 -> 배열

function valueToArray(val)

{

const str = val;

arrvalue = str.split("|");

if(arrvalue.lenght < 2) arrvalue = val;

}

// reg 체크 함수

function regCheck(val)

{

var regExp = /[\{\}\[\]\/?.,;"\)*~`!^\-+<>@\#$%&\\\=\(\'\"]/gi;

if(regExp.test(val)) return false;

else return true;

}

// API ====================================================================

// Create

function Create()

{

// key 체크

if(arrvalue[0] == "​"){

setResult("ERROR", "키가 없습니다");

return;

}

// key 중복 체크

var cell = Table_Data.getRange(2, 1, Table_Data.getLastRow() - 1, 1).getValues();

if(cell.some(row => row == arrvalue[0]))

{

setResult("ERROR", "이미 존재하는 키입니다");

return;

}

// Create_Start-------------------------

Table_Data.appendRow([arrvalue[0],arrvalue[1],arrvalue[2]]);

setResult("OK", "main1의 " + arrvalue + "값 저장 완료");

// Create_End-------------------------

}

// Read

function Read()

{

// key 체크

if(arrvalue[0] == "​"){

setResult("ERROR", "키가 없습니다");

return;

}

// key 중복 체크

var cell = Table_Data.getRange(2, 1, Table_Data.getLastRow() - 1, 1).getValues();

if(!cell.some(row => row == arrvalue[0]))

{

setResult("ERROR", "선택한 키값이 없습니다");

return;

}

else

{

// Read_Start-------------------------

for(i = 0; i < cell.length; i++)

{

if(cell[i][0] == arrvalue[0])

{

value = arrvalue[0] + "|";

value += Table_Data.getRange(i+2, 2).getValues() + "|";

value += Table_Data.getRange(i+2, 3).getValues();

setResult("OK", "main1의 " + arrvalue + "값 읽기 완료");

return;

}

}

// Read_End-------------------------

}

}

// Update

function Update()

{

// key 체크

if(arrvalue[0] == "​"){

setResult("ERROR", "키가 없습니다");

return;

}

// key 중복 체크

var cell = Table_Data.getRange(2, 1, Table_Data.getLastRow() - 1, 1).getValues();

if(!cell.some(row => row == arrvalue[0]))

{

setResult("ERROR", "선택한 키값이 없습니다");

return;

}

else

{

// Update_Start-------------------------

for(i = 0; i < cell.length; i++)

{

if(cell[i][0] == arrvalue[0])

{

Table_Data.getRange(i+2, 2).setValue(arrvalue[1]);

Table_Data.getRange(i+2, 3).setValue(arrvalue[2]);

setResult("OK", "main1의 " + arrvalue + "값 업데이트 완료");

return;

}

}

// Ypdate_End-------------------------

}

}

// Delete

function Delete()

{

// key 체크

if(arrvalue[0] == "​"){

setResult("ERROR", "키가 없습니다");

return;

}

// key 중복 체크

var cell = Table_Data.getRange(2, 1, Table_Data.getLastRow() - 1, 1).getValues();

if(!cell.some(row => row == arrvalue[0]))

{

setResult("ERROR", "선택한 키값이 없습니다");

return;

}

else

{

// Delete_Start-------------------------

for(i = 0; i < cell.length; i++)

{

if(cell[i][0] == arrvalue[0])

{

Table_Data.deleteRow(i+2);

setResult("OK", "main1의 " + arrvalue + "값 삭제 완료");

return;

}

}

// Delete_End-------------------------

}

}

# data[].attributes.headline
12차시 유니티 프로젝트

# data[].attributes.subject
12차시 유니티 프로젝트

# data[].attributes.body
// 스프레드 시트 파일, 스프레드 시트 번호, 로그 시트 번호
var sheetId, sheet;
// 파라미터 담을 변수
var p;
// 되돌려줄 변수
var result, msg, value;
var arrvalue;

// 유니티에서 Post 호출됨
function doPost(e)
{
  // 파라미터 받기
  p = e.parameter;

  // reg 체크
  if(!regCheck(p.order)  || !regCheck(p.value))
    return ContentService.createTextOutput("");

  // value 값 -> 배열
  valueToArray(p.value);

  // DB 경로 재설정
  sheetId, sheet, logSheet = null;
  switch(p.sheetID)
  {
    case "SleepAppAPI": // 앱 스크립트 명
      sheetId = SpreadsheetApp.openById("1-4aEOY6NGv7ZLnO6luoqxX9RDP8oDIfAXxpmH1mWxUA"); //주소 대입
      // 시트 이름 = 시트 번호 대입
      switch(p.sheetNAME)
      {
        case "Auth": //Sheet 이름 넣기
          sheet = sheetId.getSheets()[0];
          break;
      }
      break;
  }

  //DB 경로 에러
  if(!sheetId || !sheet)
  {
    setResult("ERROR", "DB경로가 올바르지 않습니다.");
    return;
  }

  // 알맞은 API 실행
  switch(p.order)
  {
    case "main1Create":  main1Create(); break;
    case "main1Read":  main1Read(); break;
    case "main1Update":  main1Update(); break;
    case "main1Delete":  main1Delete(); break;

    default :
      setResult("ERROR", "호출한 API가 없습니다.");
      return;
      break;
  }

  // 유니티로 결과 돌려주기
  return response();
}


// 유니티로 결과 돌려주기
function response()
{
  var json = {};
  // 어떤 DB 인지
  json.sheetID = p.sheetID;
  json.sheetNAME = p.sheetNAME;
  // 어떤 API 인지
  json.order = p.order;
  // 수행 결과
  json.result = result;
  // 수행 메시지
  json.msg = msg;
  // 결과 값
  json.value = value;

  jsonData = JSON.stringify(json);

  // 유니티로 돌려주기
  return ContentService.createTextOutput(jsonData);
}






// 수행 결과, 메시지 입력 함수
function setResult(_result, _msg)
{
  result = _result;
  msg = _msg;
}

// value 값 -> 배열
function valueToArray(val)
{
  const str = val;
  arrvalue = str.split("|");

  if(arrvalue.lenght < 2) arrvalue = val;
}

// reg 체크 함수
function regCheck(val)
{
  var regExp = /[\{\}\[\]\/?.,;"\)*~`!^\-+<>@\#$%&\\\=\(\'\"]/gi;

  if(regExp.test(val)) return false;
  else return true;
}








// Create
function main1Create()
{
  // key 체크
  if(arrvalue[0] == "​"){
    setResult("ERROR", "키가 없습니다");
    return;
  }
  // key 중복 체크
  var cell = sheet.getRange(2, 1, sheet.getLastRow() - 1, 1).getValues();
  if(cell.some(row => row == arrvalue[0]))
  {
    setResult("ERROR", "이미 존재하는 키입니다");
    return;
  }
  // Create
  sheet.appendRow([arrvalue[0],arrvalue[1],arrvalue[2]]); //column이 늘어날수록 array를 늘려줘야한다.
  setResult("OK", "main1의 " + arrvalue + "값 저장 완료");
}


// Read
function main1Read()
{
  // key 체크
  if(arrvalue[0] == "​"){
    setResult("ERROR", "키가 없습니다");
    return;
  }
  // key 중복 체크
  var cell = sheet.getRange(2, 1, sheet.getLastRow() - 1, 1).getValues();
  if(cell.some(row => row == arrvalue[0]))
  {
    // Update
    for(i = 0; i < cell.length; i++)
    {
      if(cell[i][0] == arrvalue[0])
      {
        value = arrvalue[0] + "|";
        value += sheet.getRange(i+2, 2).getValues() + "|";
        value += sheet.getRange(i+2, 3).getValues();

        setResult("OK", "main1의 " + arrvalue + "값 읽기 완료");
        return;
      }
    }
  }
  else
  {
    setResult("ERROR", "선택한 키값이 없습니다");
    return;
  }
}

// Update
function main1Update()
{
  // key 체크
  if(arrvalue[0] == "​"){
    setResult("ERROR", "키가 없습니다");
    return;
  }
  // key 중복 체크
  var cell = sheet.getRange(2, 1, sheet.getLastRow() - 1, 1).getValues();
  if(cell.some(row => row == arrvalue[0]))
  {
    // Update
    for(i = 0; i < cell.length; i++)
    {
      if(cell[i][0] == arrvalue[0])
      {
        sheet.getRange(i+2, 2).setValue(arrvalue[1]);
        sheet.getRange(i+2, 3).setValue(arrvalue[2]);
        setResult("OK", "main1의 " + arrvalue + "값 업데이트 완료");
        return;
      }
    }
  }
  else
  {
    setResult("ERROR", "선택한 키값이 없습니다");
    return;
  }
}

// Delete
function main1Delete()
{
  // key 체크
  if(arrvalue[0] == "​"){
    setResult("ERROR", "키가 없습니다");
    return;
  }
  // key 중복 체크
  var cell = sheet.getRange(2, 1, sheet.getLastRow() - 1, 1).getValues();
  if(cell.some(row => row == arrvalue[0]))
  {
    // Delete
    for(i = 0; i < cell.length; i++)
    {
      if(cell[i][0] == arrvalue[0])
      {
        sheet.deleteRow(i+2);
        setResult("OK", "main1의 " + arrvalue + "값 삭제 완료");
        return;
      }
    }
  }
  else
  {
    setResult("ERROR", "선택한 키값이 없습니다");
    return;
  }
}

# data[].attributes.attachment_link.title
쉽게배우는모바일앱개발_12주차

# data[].attributes.body
1. Google Sheets 만들기 (DB공간)

a. DB 크기에 맞춰 열 삭제 (ex : 3개면 D~Z 삭제)

b. DB 크기에 맞춰 행 삭제

c. 1행에 는 열 이름 적어주기

d. 1행 1열은 무조건 key 값

e. 따라서 데이터는 2열 부터 들어감

f. 2열에는 샘플 데이터 넣어주기

g. 위와같이 테이블 개수에 맞게 sheet 늘려주기

2. Google Apps Script 만들기 (API)

a. Google Sheets 에서 확장프로그램 -> Apps Script 선택

b. 제공된 내용 복사 (Script폴더 안에 txt 파일)

c. 코드 28번째 줄 Google Sheets 아이디 교체 (Google Sheets 의 URL 중간 "spreadsheets/d/@@@/edit#gid=0" 에서 @@@ 부분이 ID)

d. 베포 -> 새 베포 -> 유형 -> 웹앱 -> 엑세스 권환이 있는 사용자 -> 모든 사용자 -> 베포

e. 베포 시 URL 복사

3. Unity 사용하기 (GSDBManager)

a. Hierarchy 에 GSDBManager 빈 오브젝트 생성후 컴포넌트 추가

b. URL에 Google Apps Script 베포 URL 추가

4. Unity 사용하기 (GSDBCustom)

a. 이벤트를 태울 오브젝트의 컴포넌트로 추가 (버튼)

b. GSM 에 GSDBManager 연결

c. ID 에 Google Sheets 이름 넣기

d. NAME 에 Sheet 이름 넣기

e. API 에 api함수 이름 넣기

f. Value 배열에 들어가는 값 개수만큼 늘려서 값 추가 (TValue -> TMPText 연결, SValue -> 기본값 적어두기)

g. Viewtmp 에 출력할 인자만큼 배열 개수 을려서 TMPText 연결

h. End() 안에 호출 끝났을때 실행할 함수 연결

5. Google Apps Script 수정하기

a. case ID 매칭 및 추가

b. case NAME 매칭 및 추가

c. case API 매칭 및 추가

d. Create

sheet.appendRow([arrvalue[0],arrvalue[1],arrvalue[2]]);

에서 arrvalue[0] 은 4-f Value 개수만큼

e. Read

value = arrvalue[0] + "|";

value += sheet.getRange(i+2, 2).getValues() + "|";

value += sheet.getRange(i+2, 3).getValues();

에서 sheet.getRange(i+2, 2).getValues() 은 4-g Viewtmp 개수만큼 추가

f. Update

sheet.getRange(i+2, 2).setValue(arrvalue[1]);

sheet.getRange(i+2, 3).setValue(arrvalue[2]);

에서 sheet.getRange(i+2, 3).setValue(arrvalue[2]) 은 4-f Value 개수만큼

g. Delete

없음

# data[].attributes.body
ON CLICK > NO FUCTION > GSDBCustom > callManager

# data[].attributes.body
배포관리로 가기 -->웹앱 url 복사 -->UNITY 창에서 manager 에 넣기

# data[].attributes.body
1. Unity 씬에 Canvas 추가해야함 : 프로젝트 창에서 "Create" -> "UI" -> "Canvas"를 선택하거나, Hierarchy 창에서 마우스 우클릭 후 "UI" -> "Canvas"를 선택하여 캔버스 생성하기

2. 캔버스에 버튼 추가: Hierarchy 창에서 "Create" -> "UI" -> "Button"을 선택하거나, 캔버스 내부에서 우클릭 후 "UI" -> "Button"을 선택하여 버튼 생성하기

3. 버튼 복사해서 사용하기 control C / CONTROL V

4. 생성된 버튼을 선택하고, Inspector 창에서 버튼의 속성 수정할 수 있으니까 텍스트 작성하기

# data[].attributes.body
DB (데이터베이스):

데이터베이스는 데이터를 구조화하여 저장하고 관리하는 시스템입니다. 주로 구조화된 쿼리 언어(SQL)를 사용하여 데이터를 조작하고 접근할 수 있습니다.

API (Application Programming Interface):

API는 응용 프로그램 간의 통신을 위한 인터페이스로, 서로 다른 소프트웨어 시스템이 상호 작용할 수 있도록 합니다. API는 일련의 규칙과 프로토콜을 제공하여 응용 프로그램이 서로 통신하고 데이터를 공유할 수 있도록 합니다.

Client (클라이언트):

클라이언트는 서비스를 제공하는 서버로부터 데이터나 서비스를 요청하는 사용자 또는 사용자의 소프트웨어를 가리킵니다. 웹에서는 클라이언트가 웹 브라우저일 수 있으며, 모바일 앱이나 데스크톱 애플리케이션도 클라이언트가 될 수 있습니다. 클라이언트는 서버로부터 데이터를 요청하고 응답을 받아 사용자에게 보여주는 역할을 합니다.

# data[].attributes.attachment_link.description
Draw ERD with your team members. All states are shared in real time. And it's FREE. Database modeling tool.

# data[].attributes.attachment_link.readable_text
// 변수 선언 ====================================================================

// DB, Table 데이터 담을 변수
var DB_Date, Table_Data;
// 받아오는 파라미터 담을 변수
var p;
// 되돌려주는 변수
var result, msg, value;
// value 배열 변수
var arrvalue;






// 통신 함수 ====================================================================

// 유니티에서 Post 호출됨
function doPost(e) 
{
  // 파라미터 받기
  p = e.parameter;
  
  // reg 체크
  if(!regCheck(p.DB_Name) ||!regCheck(p.Table_Name) || !regCheck(p.API_Name) || !regCheck(p.Value))
    return ContentService.createTextOutput("");
  
  // value 값 -> 배열
  valueToArray(p.Value);

  // DB 경로 재설정
  sheetId, sheet = null;
  switch(p.DB_Name)
  {
    // 시트 파일 이름 = 주소 대입
    case "#DBNAME#": DB_Date = SpreadsheetApp.openById("#DBID#");
      // 시트 이름 = 시트 번호 대입
      switch(p.Table_Name)
      {
        case "#TABLENAME#": Table_Data = DB_Date.getSheets()[0];
          break;
      }
      break;
  }

  //DB 경로 에러
  if(!DB_Date || !Table_Data)
  {
    setResult("ERROR", "DB경로가 올바르지 않습니다.");
    return;
  }
    
  // 알맞은 API 실행
  switch(p.API_Name)
  {
    case "Create": Create(); break;
    case "Read": Read(); break;
    case "Update": Update(); break;
    case "Delete": Delete(); break;
    
    default :
      setResult("ERROR", "호출한 API가 없습니다.");
      return;
      break;
  }

  // 유니티로 결과 돌려주기
  return response();
}


// 유니티로 결과 돌려주기
function response()
{
  var json = {};
  // 어떤 DB 인지
  json.GSDB = p.DB_Name;
  // 어떤 Table 인지
  json.GStable = p.Table_Name;
  // 어떤 API 인지
  json.GSAPI = p.API_Name;
  // 수행 결과
  json.result = result;
  // 수행 메시지
  json.msg = msg;
  // 반환 값
  json.value = value;
  // json 형태로 담기
  jsonData = JSON.stringify(json);
  // 유니티로 전달
  return ContentService.createTextOutput(jsonData);
}








// 기능 함수 ====================================================================

// 수행 결과, 메시지 입력 함수
function setResult(_result, _msg)
{
  result = _result;
  msg = _msg;
}

// value 값 -> 배열
function valueToArray(val)
{
  const str = val;
  arrvalue = str.split("|");

  if(arrvalue.lenght < 2) arrvalue = val;
}

// reg 체크 함수
function regCheck(val)
{
  var regExp = /[\{\}\[\]\/?.,;"\)*~`!^\-+<>@\#$%&\\\=\(\'\"]/gi;

  if(regExp.test(val)) return false;
  else return true;
}






// API ====================================================================
// Create
function Create()
{
  // key 체크
  if(arrvalue[0] == "​"){
    setResult("ERROR", "키가 없습니다");
    return;
  }
  // key 중복 체크
  var cell = Table_Data.getRange(2, 1, Table_Data.getLastRow() - 1, 1).getValues();
  if(cell.some(row => row == arrvalue[0])) 
  {
    setResult("ERROR", "이미 존재하는 키입니다");
    return;
  }
  // Create_Start-------------------------
  Table_Data.appendRow([arrvalue[0],arrvalue[1],arrvalue[2]]);
  setResult("OK", "main1의 " + arrvalue + "값 저장 완료");
  // Create_End-------------------------
}


// Read
function Read()
{
  // key 체크
  if(arrvalue[0] == "​"){
    setResult("ERROR", "키가 없습니다");
    return;
  }
  // key 중복 체크
  var cell = Table_Data.getRange(2, 1, Table_Data.getLastRow() - 1, 1).getValues();
  if(!cell.some(row => row == arrvalue[0])) 
  {
    setResult("ERROR", "선택한 키값이 없습니다");
    return;
  }
  else
  {
    // Read_Start-------------------------
    for(i = 0; i < cell.length; i++)
    {
      if(cell[i][0] == arrvalue[0])
      {
        value = arrvalue[0] + "|";
        value += Table_Data.getRange(i+2, 2).getValues() + "|";
        value += Table_Data.getRange(i+2, 3).getValues();

        setResult("OK", "main1의 " + arrvalue + "값 읽기 완료");
        return;
      }
    }
    // Read_End-------------------------
  }
}

// Update
function Update()
{
  // key 체크
  if(arrvalue[0] == "​"){
    setResult("ERROR", "키가 없습니다");
    return;
  }
  // key 중복 체크
  var cell = Table_Data.getRange(2, 1, Table_Data.getLastRow() - 1, 1).getValues();
  if(!cell.some(row => row == arrvalue[0])) 
  {
    setResult("ERROR", "선택한 키값이 없습니다");
    return;
  }
  else
  {
    // Update_Start-------------------------
    for(i = 0; i < cell.length; i++)
    {
      if(cell[i][0] == arrvalue[0])
      {
        Table_Data.getRange(i+2, 2).setValue(arrvalue[1]);
        Table_Data.getRange(i+2, 3).setValue(arrvalue[2]);
        setResult("OK", "main1의 " + arrvalue + "값 업데이트 완료");
        return;
      }
    }
    // Ypdate_End-------------------------
  }
}

// Delete
function Delete()
{
  // key 체크
  if(arrvalue[0] == "​"){
    setResult("ERROR", "키가 없습니다");
    return;
  }
  // key 중복 체크
  var cell = Table_Data.getRange(2, 1, Table_Data.getLastRow() - 1, 1).getValues();
  if(!cell.some(row => row == arrvalue[0])) 
  {
    setResult("ERROR", "선택한 키값이 없습니다");
    return;
  }
  else
  {
    // Delete_Start-------------------------
    for(i = 0; i < cell.length; i++)
    {
      if(cell[i][0] == arrvalue[0])
      {
        Table_Data.deleteRow(i+2);
        setResult("OK", "main1의 " + arrvalue + "값 삭제 완료");
        return;
      }
    }
    // Delete_End-------------------------
  }
}










# data[].attributes.attachment_link.title
이용찬 창업실무_쉽게배우는모바일앱개발 중간 보고서

# data[].attributes.body
https://www.figma.com/file/lcjN6TzDbXWLbqEEFRAjWf/Week6?type=design&node-id=0%3A1&mode=design&t=19zx0F5NtDBPtzzO-1

# data[].attributes.attachment_link.title
중간보고서

# data[].attributes.attachment_link.title
과제 발표 동료 피드백 _평가점수만 (1)

# data[].attributes.body
중간보고서 과제 제출합니다!

# data[].attributes.attachment_link.title
창업실무중간보고서_HAIRS 이석우

# data[].attributes.attachment_link.readable_text
CSS에서는 transition 속성과 animation 속성을 사용하여 easing 함수를 지정할 수 있습니다.

CSS에서, 이 함수는 @keyframes 를 사용하여 구현할 수 있습니다.:

크기

위치

불투명도

PostCSS의 easing 함수는 이 사이트에서 transition 정보를 가져오는 postcss-easings 라는 플러그인이 있어 구현하기 간편합니다.

이 PostCSS 구현은 컴파일 시 CSS로 구현된 코드로 변환됩니다.

아쉽게도 현재 함수는 PostCSS로 지정할 수 없습니다. 대신, @keyframes 로 구현할 수 있으니 위를 확인해보세요.

.block {
	background: linear-gradient(
		to bottom,
		#1473e6,
		,
		#247b5e
	);
}

아래에 있는 코드는 TypeScript로 작성된 Easing 함수입니다. 변수 x는 0 (움직임의 시작)에서 1 (움직임의 끝) 사이의 움직임 진척도입니다.

아래에 있는 코드는 TypeScript로 작성된 Easing 함수입니다. 변수 x는 0 (움직임의 시작)에서 1 (움직임의 끝) 사이의 움직임 진척도입니다.

# data[].attributes.attachment_link.description
실제 사물들은 일정한 속도로 이동하지 않고, 즉시 시작하거나 즉시 멈추지도 않습니다. Easing 함수는 실제 사물들 같이, 이동 속도를 지정하여 움직임을 좀 더 자연스럽도록 만듭니다. 이 페이지에서는 여러분이 알맞은 easing 함수를 고를 수 있도록 도와드립니다.

# data[].attributes.attachment_link.readable_text
Thanks for using Shapes2D, a Unity asset for easily creating art assets in the Unity editor. You can use Shapes2D for creating PNG sprites, prototyping, game jams, UI, effects and more!

Shapes2D is available in the Unity asset store.

Extremely easy to use

Shapes can act as sprites or Unity GUI objects

Convert to Sprite button can turn shapes into a .PNG with one click

Multiple layered shapes can be collapsed into a single .PNG

Works with Unity GUI masking

Shapes can optionally be used procedurally at runtime (see Performance), meaning:

Shapes can be scaled up without becoming pixellated

Shapes can be modified/animated at runtime using the Scripting API

Base shape types are:

Circles/Ellipses (with settings for donuts, arcs, pies and wedges)

Paths (made of quadratic Bézier curves, up to 32 segments, optionally fill closed areas)

Polygons (convex or concave, up to 64 vertices)

Rectangles (and rounded rectangles)

Triangles

Customizations include:

Outlines

Blur

Gradient fills

Texture fills

Pattern fills (grids, stripes & checkerboard)

After importing Shapes2D, go to GameObject->Shapes2D and choose one of the template Shapes. Once your Shape is created, you can tweak its various options from the Shape component in the Inspector.

In the Shape component, sizes are typically specified in world units and outlines will keep the same thickness no matter how they are scaled.

Unity GUI

To use Shapes2D with canvas game objects, just add a Shape component to them. In Unity, canvases may be scaled quite a lot to fit your screen, depending on your settings. That means the scale of units may be very different than when dealing with sprites (canvases do use world units, which is why they appear so huge in the editor, but they are scaled down by Unity at runtime to overlay your screen). So, you may have to scale values (like outline size) up quite a lot to get the same effect in a UI component as with a sprite.

Anti-Aliasing

If you set blur to 0, Shapes2D will add resolution-independent anti-aliasing to Shapes so that they will look smooth regardless of scaling - essentially it is just modifying the blur value on the fly as you scale in and out. If you set blur to some value greater than 0, then blur is specified in world units and will stay fixed.

Sorting

Shapes can act like sprites or UI components, and will obey the same sorting rules. For sprite-based Shapes, use the attached SpriteRenderer component to specify the sorting layer and order. For UI components, the parent canvas has sorting options and the children will render in the order they appear in the hierarchy.

Convert to Sprite

To convert a Shape component to a sprite, press the "Convert to Sprite" button in the Shape component in the inspector. A PNG asset will be created in a folder called /Assets/Resources/Shapes2D Sprites , and the object will be converted into a SpriteRenderer or Image, depending on the object. Any active child Shapes will also be combined into the PNG, allowing you to create complex layered Shapes. To revert the sprite conversion, either use Unity's Undo function or just re-enable the Shape component and any child Shapes.

If you convert your Shapes to sprites, then Shapes2D has no impact on the performance of your game.

However, before converting to sprite, Shapes are rendered on the fly using shaders, which is why they look so smooth when scaled up and can be changed at runtime via scripting. For simple Shapes like rectangles that isn't such a big deal, but for complex shape types like polygons and paths it can be really expensive. Lots of math has to be done for each pixel, so the size of the Shape on the screen matters.

To make things worse, Shapes do not batch and require one Material per Shape. Changing any Shape properties via scripting causes properties to be re-sent to the GPU which is also a performance hit. Mobile in particular does not have very good performance, depending on what you're doing.

Nevertheless, using the included Stress Test demo I am able to get 1000+ non-complex Shapes on-screen at once at 60fps on my MacBook Pro. Dynamically modifying Shape properties at runtime is slower, and I get about 500+ Shapes running at 60fps. On mobile, performance is much worse and I recommend testing on all target platforms before attempting to use Shapes2D procedurally. You should be able to get away with small numbers of non-complex shapes.

If performance becomes an issue, a good workflow is to rapidly create Shapes when prototyping and then either "Convert to Sprite" or replace them with artist-created assets later. You should test on each of your supported platforms and decide if you can afford to use a procedural Shape or if you should replace prototype Shapes with sprites (or perhaps an animated mesh, for certain types of effects).

Path Performance

Paths (even line paths) are the most expensive Shape type for performance, and I recommend always converting them to sprites unless you are very sure your target platform can handle it. The more segments you use, the more expensive rendering will be. If you do need dynamic procedural curves or paths at runtime, you might want to look into a vector solution which would convert your paths into a much more performance-friendly mesh. There are other assets on the Unity Asset Store for that!

On mobile, performance for paths is very bad - convert them to sprites first!

Polygon Optimization

Polygon Shapes have an additional "optimized" rendering mode which can be selected via a checkbox in the Unity Component Inspector.

Optimized polygons:

Are about as fast as the other Shape types, even on mobile

Are slow if you want to update their vertices dynamically via code (and slow to Instantiate)

Will render fine for most polygons but will show rendering artifacts if vertices are too close to each other, if vertices are too close to polygon edges, or if polygon edges intersect each other

Non-optimized polygons:

Are slow in general, and slower the more vertices you have

Are very slow on mobile

Can have their vertices updated quickly

Should always render correctly

If you intend to Convert to Sprite anyway, go ahead and leave your polygons non-optimized so you don't have to worry about rendering issues.

Shapes2D has been tested on OSX, Windows, iOS, Android and WebGL. For polygons and paths with high numbers of vertices, Shapes2D shaders may not compile for the , meaning you should not target that platform if you intend to use complex shapes procedurally (converting to sprite is fine because the shaders aren't required at runtime). If you notice any problems with Shapes not appearing or appearing wrong, please let me know!

To modify Shapes from code, you can do things like this:

etc...

If you want to modify a Shape's attributes from your method, you may need to add a call to shape.ComputeAndApply() to prevent a flicker of the Shape's initial attributes on the first frame.

See below for customizable settings.

API Documentation
The Shape Component UserProps (customizable settings)

# data[].attributes.attachment_link.title
Shapes2D for Unity - Shapes2D 1.3 documentation

# data[].attributes.attachment_link.description
Thanks for using Shapes2D, a Unity asset for easily creating art assets in the Unity editor. You can use Shapes2D for creating PNG sprites, prototyping, game jams, UI, effects and more! Shapes2D is available in the Unity asset store.

# data[].attributes.body
icon

icons8

iconify

mockUp

Artboard Mockup

# data[].attributes.attachment_link.description
상업용 무료한글폰트 사이트

# data[].attributes.attachment_link.readable_text
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class ScenesChanger : MonoBehaviour
{
    public void ChangeScenes(int i){
        switch (i){
            case 1 :
            SceneManager.LoadScene("01. Main");
            break;
            case 2 :
            SceneManager.LoadScene("02. Text (TMP)");
            break;
            case 3 :
            SceneManager.LoadScene("03. Imag");
            break;
            case 4 :
            SceneManager.LoadScene("04. Image_UI");
            break;
            case 5 :
            SceneManager.LoadScene("05. Buttom");
            break;
            case 6 :
            SceneManager.LoadScene("06. InputField (TMP)");
            break;
            case 7 :
            SceneManager.LoadScene("07. Toggle & Dropdown");
            break;
            case 8 :
            SceneManager.LoadScene("08. Slider");
            break;
            case 9 :
            SceneManager.LoadScene("09. Scroll View");
            break;
            
        }
    }
}

# data[].attributes.attachment_link.title
쉽게배우는모바일앱개발_5주차_최종 자료_업로드 

# data[].attributes.body
3/18 아이디어 초안

# data[].attributes.attachment_link.title
다이어리&할일앱 만들기 7차시 최종본

# data[].attributes.body
1)이름: 김정우

2)수강 선택 이유 : 100세 시대에 대비해서 제2, 제3의 직업을 만들고 싶습니다.

3)개발하고 싶은 모바일 앱 영역 : 1인 가구를 위한 레시피 앱

4)나를 소개하는 이미지 : 자유의 여신상, 자유롭고 싶어서

# data[].attributes.body
이름: 박보영

수강 선택 이유: 이커머스 관련 플랫폼 비즈니스 창업에 관심 있어서

개발하고 싶은 모바일 앱: 당일 판매되지 않으면 폐기되어야 하는 음식들을 저렴한 가격에 판매하는 B2C 플랫폼, 레터링 케이크 오더/딜리버리 플랫폼, 냉장고 속 음식들의 유통기한을 트래킹해주는 앱, 대중교통 내릴때쯤 깨워주는 알람 서비스 등

나를 소개하는 이미지: Infp & Entp

# data[].attributes.attachment_link.title
모바일앱개발 나의 관심 영역 발표

# data[].attributes.attachment_link.title
체리라이프 앱이 가져야 할 기능 소개

# data[].attributes.attachment_link.title
전지완_쉽게배우는 앱개발

# data[].attributes.headline
이름: 정원웅수강선택이유: 

# data[].attributes.body
이름: 정원웅

수강선택이유: 앱 개발을 해본적이 없어서

개발하고 싶은 모바일 앱: 킥보드 통합 앱, 위치 추적이 더 확실하게 가능하고 동기부여해주는 러닝앱

나를 소개하는 이미지...ㅣ..

# data[].attributes.attachment_link.title
킥보드 통합 앱 - 정원웅

# data[].attributes.attachment_link.title
모바일 앱 동향_고도연

# data[].attributes.attachment_link.title
쉽게배우는모바일앱개발_강민서_3주차발표

# data[].attributes.body
김예은

수강 선택 이유: 직접 내가 원하는 앱을 개발해보는 경험을 해보고 싶어서 선택하게 되었습니다.

개발하고 싶은 모바일 앱 영역: 차별화 된 단어장(강제성과 접근성을 높여 효과적인 암기가 가능한 단어장)

나를 소개하는 이미지: 마음 먹은 건 다 하는 사람(이 되고 싶다.)

# data[].attributes.body
1) 이름: 강민서

2) 수강 선택 이유: 작년에 웹 기반으로 영어 단어 학습 프로그램을 개발하는 스타트업에서 풀스택 개발자로 약 10개월 정도 일했던 적이 있습니다. 그 과정에서 웹 기반 어플리케이션의 여러 장점들을 경험했으나, 반대로 브라우저나 기타 환경 등에 따른 제약이 많다는 점을 느끼게 되었습니다. 이에 웹 기반이 아닌 유니티, 자바 등을 이용한 앱 개발을 배워보고 싶었습니다.

3) 개발해보고 싶은 모바일 앱 영역: 단순히 축구를 하는 영상을 촬영함으로써 활동량, 플레이 스타일 등에 대한 분석이나 슈팅, 패스 등의 자세에 대한 피드백을 해줄 수 있는 어플리케이션

4) 나를 소개하는 이미지: 인간 ENTP

# data[].attributes.body
3조 임해원

# data[].attributes.attachment_link.title
내가 개발하고 싶은 앱

# data[].attributes.attachment_link.title
앱개발 동향 탐색 ppt

# data[].attributes.headline
서지현-발표자료(수정)

# data[].attributes.subject
서지현-발표자료(수정)

# data[].attributes.attachment_link.title
서지현_모바일앱동향조사

# data[].attributes.body
이름 : 임해원

수강 선택 이유 : 앱 개발의 기초를 알고 싶어서

개발하고 싶은 모바일 앱 영역 : 식품정보 종합앱

나를 소개하는 이미지 : 아직 어떤 것을 하고 살아갈지 정한 것이 없어서 백지와 같은 상태이기 때문에

# data[].attributes.body
이름 : 고도연

수강선택 이유 : 서비스를 기획하고 제작하기까지의 일련의 과정을 직접 해보고 싶어서, 이 과정을 통해 내가 관심있는 분야가 무엇인지 가닥을 잡고 싶어서

개발하고 싶은 모바일 앱 영역 : 환경/사회문제 등에 개인이 관심을 갖고 실천할 수 있도록 동기부여를 하는 앱

나를 소개하는 이미지 : 말하는 감자가 되고싶어요

# data[].attributes.body
3/18 (월) 발표자료

# data[].attributes.body
1.이름:최지훈

2.수강 선택 이유: 학과에서 배우는 내용 이외의 실무경험을 쌓아 보고 싶었고 아직 뚜렷하게 하고 싶어하는것이 없어 진로를 보다 더 구체적으로 그려보고 싶어 수강신청하였습니다

3.개발하고 싶은 모바일 앱

다이어리&할일 기록과 알림 앱 (rpg형식의 본인이 설정한 목표들 또는 할일을 마무리한다면 본인이 설정한 기간과 중요도를 고려하여 앱 내 재화를 지급하여 앱 상점에서 물품을 사 앱 내의 캐릭터를 키우거나 방을 꾸미는등의 보상 시스템이 존재하는 앱)

4.나를 소개하는 이미지

한국인 남자 직장인 캐릭터

# data[].attributes.attachment_link.title
한국인 남자 직장인 캐릭터

# data[].attributes.body
1) 이름 : 오서윤 
2) 수강 선택 이유 : 
어플리케이션을 직접 만들어보는 과정을 수업을 통해 미리 경험해보고 싶었다. 
앱은 내가 가진 이상을 현실로 구현할 수 있는 여러 실무적인 방법들 중 가장 접근성이 높고 친근한 도구라고 생각한다.
꼭 배워보고 싶었다!
3) 개발하고 싶은 모바일 앱영역
지식컨텐츠 어플/ 책큐레이션어플
4) 나를 소개하는 이미지 검색해서 업로드
책과 사람을 좋아하는 enfp 

# data[].attributes.body
1) 이름 : 이용찬

2) 수강 선택 이유 : 큰 부 및 가치를 만들기 위해서는 사업이나 창업을 해야한다는 것을 알게 되었고 친구와 토론하며 사업아이템을 만들고 사업계획서를 작성하던 와중에 해당 수업을 알게 되었다. 친구와 계획한 사업은 모바일앱을 반드시 필요로 하여 수업을 통해 모바일앱 개발에 대해 알게되면 도움이 될 것 같아 수강하게 되었다. 또한 반드시 지금 계획하고 있는 사업이 아니더라도 모바일앱 개발에 대한 이해는 앞으로 어떤 사업을 하든 많은 도움이 될 것이라 기대하여 선택하게 되었다.

3) 개발하고 싶은 모바일 앱 영역

(게임앱, 소통앱, 정보탐색앱 등 만들어보고 싶은 것은 많지만 현재 친구랑 계획하고 있는 사업에 필요한 앱을 기준으로 설명하려고 한다.)

기본 기능 : 할인 상품을 다양한 곳에서 올리면 그것의 가격 및 할인율과 판매 위치를 소비자에게 알려준다. 맵에 소비자의 현재 위치를 파악하여 가까운 곳에 어떤 할인상품이 있는지 정보를 제공해준다.

추가 기능 : 소비자의 과거 소비 패턴을 알고리즘적으로 분석하여 소비자가 선호할 만한 상품을 추천해준다.

4) 나를 소개하는 이미지 : 내가 추구하는 가치와 나만의 개성을 세상에 보여주고 결합하여 내가 원하는 세상을 만들어가고 싶기 때문에 이에 어울리는 놀이공원 이미지를 선택했다.