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

# data[].attributes.attachment_link.title
아이들나라 - 아이를 키우는 독서 앱 - Apps on Google Play

# data[].attributes.attachment_link.description
A children-only content platform that leads from reading to learning

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

2) 수강 선택 이유 : 개발자분들과 원활하게 소통하는 법을 배우고 싶어서 직접 과정에 참여해봐야겠다고 생각함

3) 개발하고 싶은 모바일 앱 영역 : 정보전달형 앱서비스 (카테고리 특화)

4) 나를 소개하는 이미지 : 미니언즈 BOB, 영어이름이 bob이고 ENFP적인 느낌이 보여

# data[].attributes.body
1. 이름: 황윤서

2. 수강 선택 이유: 지적재산권 하나 잘뽑아서 평생 놀고 먹으며 살고 싶다는 욕망과, 평소하고 싶은 컨텐츠 기획을 할 수 있다는 것, 그리고 문과로서의 진로적합성을 살리고자 게임 개발팀 프로젝트 매니저라는 직종을 희망하게 됨. 게임 개발에 대해 깊게는 아니더라도 어느정도는 알아야한다 느껴, 이번 강의를 초석으로 개발 업무를 이해해나가고자 함.

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

1) 기프티콘 자동 저장기

기프티콘을 이미지로 저장하면, 자동으로 어플에 카테고리별 모아주는 어플. 메세지, 카카오톡 등으로 이미지를 저장하면 해당 기프티콘 이미지를 인식하여 자동으로 폴더에 정리해줄 수있게음 하는 것

2) 포켓몬고 +토스 주변 장소 포인트 주는 걸 결합한 위치 기반 ar게임. 근데 이제 IP를 곁들인.

3) 역사 드라마 영화 전달 전달앱

4. 나를 소개하는 이미지: 포켓몬 만든 사람의 사진인데, 나도 포켓몬 같은 거 만들어서 평생 놀고 먹는 부를 쌓고자 해서.

# data[].attributes.headline
신예림_PPT 업데이트

# data[].attributes.subject
신예림_PPT 업데이트

# data[].attributes.body
2. 수강선택이유 : 비교적 쉽게 게임 또는 앱 개발이 가능한 유니티에 흥미가 생겨서

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

(1) 소셜링기반 스케쥴 관리 서비스 : 나와 비슷한 목표를 가진 사람들과 소통하고 갓생을 살 수 있도록 도와주는 어플

(2) 스토리텔링이 가능한 지도 : 내가 가본 곳, 의미있는 장소를 찍으면 그와 관련된 내용을 보여주는 간단한 어플

4. 나를소개하는이미지검색해서업로드 : 여러 장소들을 지나며 다양한 사람들을 만날 수 있게 해주는 기차가 제 삶의 지향점을 잘 보여줍니다!!

# data[].attributes.body
이름: 이선민

수강 선택 이유: 플랫폼 및 앱 개발에 관심이 생겨서

개발하고싶은 모바일 앱 영역: 냉장고 관리 어플리케이션

사진 선택 이유: 바다를 부유하는 해파리처럼 나른하게 인생을 살아가기 때문

# data[].attributes.body
1)이름:전지완

2)수강선택이유: 취미로라도 내 앱을 만들고 싶음

3)개발하고싶은모바일앱영역: 팬 커뮤니티

4)나를소개하는이미지검색해서업로드

DALL-E 에게" 투자를 좋아하는 20대 대학생 그림을 그려줘"

# data[].attributes.attachment_link.title
DALL·E 2024-03-11 18.28.23 - A 20-something college student who loves investing is sitting at a desk in their dorm room, surrounded by financial books and a laptop open to stock m

# data[].attributes.body
1) 이름 : 박진수

2) 수강 선택 이유 : 유니티 사용법을 배워보고자 해당 과목을 선택하게 됨. 조그마한 프로젝트를 진행하면서, 유니티로 어떤 기능을 구현 할 수 있을지 알아보고 싶음.

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

유저들이 한꺼번에 많이 몰릴 수 있는 단순한 로직의 킬링 타임용 앱.

4) 나를 소개하는 이미지: 석유찾는 것 처럼 대박을 내고 싶다.

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

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

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

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

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

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

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

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

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

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

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

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

4.나를 소개하는 이미지

한국인 남자 직장인 캐릭터

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

# data[].attributes.body
1) 이름 : 서현우

2) 수강 선택 이유 : 앱개발 툴을 다뤄보고 사업을 구상하여 관련된 앱을 만들어 보고싶었음(경험하는 것이 중요하다 생각)

3) 개발해보고 싶은 모바일 앱 영역 : 일렉기타 정보제공 및 교육 앱

튜닝, 메트로놈 뿐만아니라 휴대폰에 저장된 음악파일을 박자, 키조절, 악보추출하며, 기타용품구매, 강좌등을 제시할 수 있는 앱

4) 나를 소개하는 이미지 : 기타치고 공연을 좋아하는 20대의 이미지

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

# data[].attributes.body
1. 김예은

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

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

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

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

# 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
체리라이프 앱이 가져야 할 기능 소개

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

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

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

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

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

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

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

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

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

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

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

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

# 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.body
icon

1. icons8

2. iconify

mockUp

1. Artboard Mockup

# 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.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.body
중간보고서 과제 제출합니다!

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

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

# 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.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.body
1. DB (데이터베이스):

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

2. API (Application Programming Interface):

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

3. 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.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
배포관리로 가기 -->웹앱 url 복사 -->UNITY 창에서 manager 에 넣기

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

# 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.attachment_link.title
쉽게배우는모바일앱개발_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.headline
12차시 유니티 프로젝트

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

# 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.attachment_link.title
쉽게배우는모바일앱개발_16주차

# 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.attachment_link.title
프차피티 디자인 김예은