<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>기발.log</title>
        <link>https://velog.io/</link>
        <description>기발한 기발자</description>
        <lastBuildDate>Sat, 15 Apr 2023 14:01:28 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>기발.log</title>
            <url>https://images.velog.io/images/sonhm-code/profile/5732b656-4aca-4a79-a1af-34cc83e74332/social.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. 기발.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/sonhm-code" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[기획] 좋은 기획문서를 쓰기 위한 여정 . 고마워요 피그마❤️]]></title>
            <link>https://velog.io/@sonhm-code/%ED%94%BC%EA%B7%B8%EB%A7%88%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-%EA%B8%B0%ED%9A%8D%EB%AC%B8%EC%84%9C-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@sonhm-code/%ED%94%BC%EA%B7%B8%EB%A7%88%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-%EA%B8%B0%ED%9A%8D%EB%AC%B8%EC%84%9C-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Sat, 15 Apr 2023 14:01:28 GMT</pubDate>
            <description><![CDATA[<h1 id="기획문서-잔혹사">기획문서 잔혹사</h1>
<p>초기 스타트업에서 기획문서를 셋업하는 일은 매우 중요한 일이었다.
개발팀과 기획팀이 모두 만족할 수 있는 커뮤니케이션 방식을 만들기까지 몇번의 시행착오가 있었다.
이는 그 과정을 기록하기 위한 포스팅.</p>
<h2 id="시행착오1-문서-포맷이-중요한지-몰랐음">시행착오1. 문서 포맷이 중요한지 몰랐음.</h2>
<p>스타트업을 세팅할 때, 제품 기획서를 어떤 방식으로 정리해야 할지 고민했었다. 먼저 팀원들과 함께 검색을 시작했다.</p>
<p><img src="https://velog.velcdn.com/images/sonhm-code/post/c23f6abb-8fbb-4a67-ad3f-47ac967d8bea/image.jpg" alt="구글에 검색하면 나오는 결과">
구글에 검색해보면 서비스 기획서나 화면 설계서와 같은 문서를 작성하는 대중적인 포맷을 찾을 수 있다. 팀원들이 모두 활용할 수 있어 논의 없이 해당 방식으로 작업을 진행했다. 화면 우측에 있는 디스크립션 란을 확보해 최대한 많은 내용을 담으려고 했지만, 시행착오가 있었다.</p>
<p>화면을 기준으로 디스크립션을 작성하면 서비스 기획을 MICE하게 작성할 수 없다.
여기서 MICE는 기획문서를 작성하는 가장 이상적인 분류 방식이다. 부분의 합이 전체를 대변해야 하는 문서 관리 기준이다. 기획서에 중복된 내용이 작성되면 업데이트 누락이 생기고, 기획자와 개발자 간 커뮤니케이션 미스가 발생할 수 있다.</p>
<p>화면 설계서는 화면을 기준으로 디스크립션을 작성하기 때문에 동일 작동 원리에 대한 서비스 기획 내용이 중복으로 작성될 수밖에 없다. 화면 설계서를 기반으로 서비스 정책서를 작성하는 것은 좋은 대안이 되지 않는다.</p>
<p>그렇다면 기획문서를 어떤 기준으로 정리해야 할까?</p>
<p>API 작성 기준으로 작성하는 것으로 일단 진행했다. 모든 기능은 메소드 기준으로 분류되었다. 등록, 수정, 삭제, 조회의 4가지 메소드는 기능을 구현하는 최소한의 단위이고 중복되지 않는다고 판단했다. 또한 개발자 분들이 문서를 찾고 확인하기에 용이하다고 판단했다.</p>
<p>최소 단위를 메소드 단위로 나누어 작성하고, 노션의 롤업 기능을 활용하여 기획문서에 연결했다. 기획문서는 각각의 API와 연결되어 개발자와 기획자가 소통하기 쉬운 환경이 되었고, 특정 메소드에 맞는 정책 내용이 중복되지 않게 정리되어 개발 환경이 개선되었다는 평가를 받았다.</p>
<p><img src="https://velog.velcdn.com/images/sonhm-code/post/40affe95-5a5f-473d-8097-8c61ee54e7e4/image.png" alt="피그마 문서 정리형태">
피그마로 정리된 기획문서의 목록</p>
<p><img src="https://velog.velcdn.com/images/sonhm-code/post/79f6a8d4-c899-4872-81bd-edc508404774/image.png" alt="각각의 API로 구성된 기획문서">
기획문서는 개발자가 작성한 API와 연결되어 있다.</p>
<p><img src="https://velog.velcdn.com/images/sonhm-code/post/6d095a0c-dadb-4390-8d42-709a3faed1d2/image.png" alt="각각의 API 상세">
API 상세를 클릭하면 세부 파라미터 값과 정리내용들을 확인할 수 있다.</p>
<h2 id="시행착오2-기획문서-길면-개발자분들-안봄">시행착오2. 기획문서 길면 개발자분들 안봄.</h2>
<p>시간이 지나면서, 기획서에 디테일한 내용을 모두 담는 것이 좋다고 생각했던 때가 있었다. 하지만 기획 내용은 항상 업데이트 되고, 변경 이력이 많을수록 커뮤니케이션이 어려워진다. 그래서 디테일하게 문서를 작성하려고 애를 쓴 적이 있었다.</p>
<p>그러나 그 과정에서 한 가지 시행착오가 있었다.
기획서가 길게 작성되면 쓰는 사람도 보는 사람도 힘들어진다.
제가 글이 길면 잘 안 읽는데, 길게 쓰면 개발자분들도 알기 힘들겠다고 생각했던 것이 문제였다. 길면 안 보이는 법이니까.. </p>
<p>그래서 최소한의 내용으로 빠짐없이 기입할 수 있는 방법을 찾아보았다. 파이썬 및 스크립트 공부를 하면서 느낀 점은 결국 코드든 사용자 스토리든 모두 시퀀스를 기반으로 설계된다는 점이었다. &#39;상황 - 판단 - 결과&#39; 기본적인 시퀀스로 구동된다고 생각하니, 기획팀에서 녹이고자 하는 모든 서비스 정책과 비지니스 방향이 플로우차트 속에서 설명될 수 있었다.</p>
<p>그래서 우리 회사의 제품 기획서 방식은 플로우차트와 화면설계서를 기반으로 한 기획 형태로 정의 되었다. 이는 메소드 기준으로 작성되었고 개발자분들이 쉽게 접근할 수 있도록 구성하여, 개발하기 편한 환경에 도움이 되었다는 평가를 받았다.</p>
<p><img src="https://velog.velcdn.com/images/sonhm-code/post/fd0ee561-d57c-4343-8f57-ba2effbcc5fc/image.png" alt="플로우차트 기반의 기획서"></p>
<h2 id="시행착오3-기획문서는-수정할-수-밖에-없음">시행착오3. 기획문서는 수정할 수 밖에 없음.</h2>
<p>자주 수정해야 하는 문서라면, 작성 방법만큼 히스토리 아카이빙이 중요하다. 전통적인 양식의 화면 설계서 문서들은 한 단어만 변경해도 여러 페이지를 일일이 찾아 수정하거나 바꾸어 주어야 란다.
해당 이슈를 해결하기 위해 기획 문서 기술적으로는 MICE 방식의 기술법이 중요하지만, 툴적으로는 한 개의 수정사항에 영향을 받는 브랜치 기획 문서들이 수정과 동시에 누락 없이 함께 수정될 수 있는 환경이 조성되어야 한다.
이런 문제를 해결하기 위해 피그마의 메인 컴포넌트 기능을 활용하여 도입하였으며, 회사 자체적으로 피그마 기획 문서 정리 컨벤션을 만들었다.</p>
<p><img src="https://velog.velcdn.com/images/sonhm-code/post/2adacedc-bb75-4e48-aef7-719fc42aedcc/image.png" alt="메인 컴포넌트">
메인 컴포넌트로 관리되고 있는 피그마 파일들은 수정사항이 발생할 때마다 영향받는 모든 브랜치에서 함께 수정이 되며
이는 기획팀의 퍼포먼스와 직결되었다.</p>
<p>아울러 피그마의 히스토리 세이브 기능을 활용하여 문서 버전을 관리했다. 이는 매우 효율적이었다. 해당 히스토리를 쉽고 빠르게 저장할 수 있었고, 세이브 링크를 통해 언제든 과거 문서로 이동할 수 있었다. 툴을 적절히 활용하는 것만으로 문서의 신뢰도가 높아지고 문서 기반으로 업무를 볼 수 있는 환경이 조성되었다.
<img src="https://velog.velcdn.com/images/sonhm-code/post/d3bf847d-42cc-41f7-b41d-d2df55bb810f/image.png" alt="피그마 문서 버전관리 기능"></p>
<p>피그마의 문서는 간단한 요약과 함께 링크로 전달되어 관리되었다.
<img src="https://velog.velcdn.com/images/sonhm-code/post/07279155-9f3b-40e2-b096-acb32cf0aee4/image.png" alt="노션을 통한 히스토리 관리"></p>
<p>현재 우리 조직의 기획문서는 개발팀과 기획팀 함께 보고 수정하는 구조로 정착되었다. 앞으로도 갈 길이 멀지만 같은 문서를 보고 함께 편집하는 기조가 생긴 것 같아 나름 만족스럽다. 짧은 주기로 제품이 애자일되는 조직 문화를 갖추기 위해선 효율적이고 효과적인 문서관리 체계가 필요한데, 앞으로도 이 부분에 더욱 연구를 많이 해서 좋은 애자일 문화를 만드는 데 일조하고 싶다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[SQL] SELECT과 ORDER BY문으로 데이터 정렬하기]]></title>
            <link>https://velog.io/@sonhm-code/SQL-SELECT%EA%B3%BC-ORDER-BY%EB%AC%B8%EC%9C%BC%EB%A1%9C-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%A0%95%EB%A0%AC%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@sonhm-code/SQL-SELECT%EA%B3%BC-ORDER-BY%EB%AC%B8%EC%9C%BC%EB%A1%9C-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%A0%95%EB%A0%AC%ED%95%98%EA%B8%B0</guid>
            <pubDate>Fri, 24 Mar 2023 22:05:36 GMT</pubDate>
            <description><![CDATA[<h2 id="테이블-데이터-형태-파악하기">테이블 데이터 형태 파악하기</h2>
<p>데이터는 다음의 열과 레코드로 구성되어 있다.
<img src="https://images.velog.io/images/sonhm-code/post/95d9e650-522f-44ce-9f0b-dabfeb533d02/Untitled.png" alt="1"></p>
<h2 id="select를-이용해-원하는-열만-추출하기"><code>SELECT</code>를 이용해 원하는 열만 추출하기</h2>
<p>전체 열을 불러오고 싶다면 <code>SELECT</code> 뒤에 <code>*(스타)</code>를 사용한다.
<img src="https://images.velog.io/images/sonhm-code/post/a171c94e-05c5-4b86-89a4-0128d5a99911/Untitled2.png" alt="2"></p>
<p>일부 열을 불러오고 싶다면 <code>SELECT</code> 뒤에 <code>열 이름</code>(예: CustomerID)을 사용한다.
<img src="https://images.velog.io/images/sonhm-code/post/91595989-1391-48b2-803e-1898c541e495/Untitled3.png" alt="3"></p>
<p><code>SELECT</code> 뒤에 <code>열 위치</code>(예: 1)를 사용할 경우 오류가 난다.
<img src="https://images.velog.io/images/sonhm-code/post/a90280aa-3fa4-4b41-a252-1aa23500af28/Untitled4.png" alt="4"></p>
<h2 id="order-by"><code>ORDER BY</code></h2>
<p><code>ORDER BY</code> 뒤에 <code>열이름</code>을 사용하여 데이터를 정렬한 모습 
<img src="https://images.velog.io/images/sonhm-code/post/82fe1e57-a20f-4365-a1a2-24963b0c1417/Untitled5.png" alt="5"></p>
<p><code>ORDER BY</code> 뒤에 <code>열 위치</code>로 사용할 경우, <code>출력된 테이블</code>의 열 위치(1번째 열)를 참조하여 정렬해야 한다.
<img src="https://images.velog.io/images/sonhm-code/post/eb80a496-ec2e-459b-91bb-00fcd53d96e2/Untitled6.png" alt="6"></p>
<p><code>ORDER BY</code> 뒤에 <code>열 위치</code>로 사용할 경우, <code>출력된 테이블</code>의 2번째 열을 참조한 모습
<img src="https://images.velog.io/images/sonhm-code/post/bca37c81-d2ea-42b3-91fb-d2eafe9b93e9/Untitled7.png" alt="7"></p>
<h2 id="order-by-뒤에-열-이름을-활용하여-정렬하면-좋은-점"><code>ORDER BY</code> 뒤에 <code>열 이름</code>을 활용하여 정렬하면 좋은 점</h2>
<p><code>SELECT</code> 뒤에 선택되지 않은 열(예: <code>Country</code>)에 대해서도 정렬할 수 있다. 
<img src="https://images.velog.io/images/sonhm-code/post/02b42de6-5bf4-4c5e-96ef-390426c75a1c/Untitled8.png" alt="8"></p>
<h2 id="2개-이상의-열-정렬하기">2개 이상의 열 정렬하기</h2>
<p>정렬 우선순위를 정하여 오름내림차순 할 수 있다. <code>City</code>는 내림차순되었으며, 동일 <code>City</code> 내에서 <code>고객명단</code>은 오름차순되어 있는 것을 확인할 수 있다.
<img src="https://images.velog.io/images/sonhm-code/post/631b512f-2b7f-4684-be98-8b18d69e68c1/Untitled9.png" alt="9"></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[기획] 시퀀스 다이어그램]]></title>
            <link>https://velog.io/@sonhm-code/%EA%B8%B0%ED%9A%8D-%EC%8B%9C%ED%80%80%EC%8A%A4-%EB%8B%A4%EC%9D%B4%EC%96%B4%EA%B7%B8%EB%9E%A8</link>
            <guid>https://velog.io/@sonhm-code/%EA%B8%B0%ED%9A%8D-%EC%8B%9C%ED%80%80%EC%8A%A4-%EB%8B%A4%EC%9D%B4%EC%96%B4%EA%B7%B8%EB%9E%A8</guid>
            <pubDate>Tue, 17 May 2022 23:57:09 GMT</pubDate>
            <description><![CDATA[<h1 id="말-많은-기획서보다-시퀀스">말 많은 기획서보다 시퀀스</h1>
<p>시퀀스 다이어그램(Sequence Diagram)은 어떠한 순서로 어떤 객체들과 어떻게 생호작용했는지를 표현하는 다이어그램임.</p>
<p>시퀀스 다이어그램을 이용하면 API 등의 유즈케이스를 디테일하게 알 수 있음. 또한 메서드 콜, DB 조회, 타 시스템의 API 호출등 로직을 모델링할 수 있음. 그렇기 때문에 시나리오를 파악하기 좋음.</p>
<p>유지보수 측면이나 커뮤니케이션 측면에서 잘 작성한 시퀀스 다이어그램 하나가 수많은 기획서보다 나음.</p>
<h1 id="구조">구조</h1>
<h2 id="life-line">Life line</h2>
<p>모델링 되는 개개의 인스턴스임.
LifeLine은 네모박스와 점선으로 이루어져 있으며 네모박스는 Object 관점이라면 Class, Service 관점이라면 Component가 됨. 그리고 점선은 위에 아래로 내려올수록 시간이 경과됨을 의미.
<img src="https://velog.velcdn.com/images/sonhm-code/post/38b8b998-99d3-4a03-9a5e-788ab351bfed/image.png" alt=""></p>
<h2 id="activations">Activations</h2>
<p>Activations는 LifeLine의 인스턴스가 실제로 다른 인스턴스와 상호작용을 하며 활성화되어있는 것을 나타냄.
<img src="https://velog.velcdn.com/images/sonhm-code/post/8df13f33-efc4-42e2-9e6e-b7b9722f6a42/image.png" alt=""></p>
<h2 id="call-message">call message</h2>
<p>call message는 요청을 하는 메시지임.
메시지에 대해서 받은 인스턴스는 특정 작업을 진행함. 그리고 작업을 마무리하고 return message를 돌려줌. call message를 통해 호출할 때 호출이름(파라미터)의 형식을 가짐. 그리고 response에 대해서는 반환되는 값을 명시해주시면 됨. 아래 이미지는 DB 서비스에 selectPhoto를 실행시키며 파라미터로 id를 전달함. 그리고 DB의 작업 후 photo를 Batch 인스턴스에 return하는 모습을 나타낸 것임.
<img src="https://velog.velcdn.com/images/sonhm-code/post/dcc5fba7-d2f9-4c88-9b1d-0fabeb2567f7/image.png" alt=""></p>
<h2 id="async">async</h2>
<p>sync 메시지가 가득차있는 삼각형 화살표라면 async 메시지는 골격만 가지고 있는 화살표로 표시. 
<img src="https://velog.velcdn.com/images/sonhm-code/post/7f6e19bc-96f2-437a-8576-0d1413167a58/image.png" alt=""></p>
<h2 id="self--recursive">self &amp; recursive</h2>
<p>인스턴스간의 상호작용 뿐만 아니라 하나의 인스턴스에서 처리를 하는 방법도 종종있음. 이럴때는 self 메시지를 사용할 수 있음. self message는 본인의 lifeline으로 재귀 하는 화살표를 가지고 있음.
<img src="https://velog.velcdn.com/images/sonhm-code/post/6e85d61a-f4f9-4572-a3a4-34adea004ec9/image.png" alt=""></p>
<h2 id="흐름제어">흐름제어</h2>
<p>프로그램 로직을 구성하다 보면 반드시 작성하게 되는것이 if, for, while 등과 같은 흐름 제어 표현임. 
Sequence Diagram은 시간 순의 인스턴스간의 상호작용을 표현하기 때문에 흐름 제어 표현들이 필요 할 수 있음. 이때 사용하는 요소가 guard와 Sequence Fragments임.</p>
<h3 id="guard">guard</h3>
<p>단일 메시지에 대해서 조건을 명시할 수 있는 방법. 
guard는 메시지의 Text의 앞쪽에 []로 감싼 후 조건을 명시. 
만약 a라는 값이 0보다 커야한다고 한다면 [a&gt;0]으로 명시하면 좋음. 아래 이미지는 photo의 갯수를 불러오고 photo.size의 값이 0보다 크다면 putPhoto(photo)로 호출한다는 의미임. 만약 size가 0이라면 해당 메시지는 발생하지 않음.
<img src="https://velog.velcdn.com/images/sonhm-code/post/ea54720d-2951-4d9d-b629-37c3c3ac3c30/image.png" alt=""></p>
<h3 id="sequence-fragments">Sequence Fragments</h3>
<p>guard가 한 메시지에 대해서 조건을 명시했다면, sequnce fragments는 범위로 조건을 명시할 수 있음. 즉, 특정 부분에 대해서 일정 부분의 메시지를 반복하던지 조건을 명시하던지 할때는 sequence fragments가 명확할 수 있음.</p>
<h4 id="alt">Alt</h4>
<p>alternatives는 줄여서 alt. 
이 타입은 if / else 구문을 나타낼 수 있음.
아래는 alt를 이용한 if / else 구문임. 여기서도 if에 대해서 guard를 사용할 수 있음. guard를 보시면 id값이 짝수일 경우임. 즉 이 시퀀스 다이어그램은 id가 짝수이면 insertOdd 메시지를 보내고 그렇지 않다면 logging이라는 메시지를 보내는것을 알 수 있음.
<img src="https://velog.velcdn.com/images/sonhm-code/post/ceb531a3-a4eb-4d92-943f-88f2e525c25e/image.png" alt=""></p>
<h4 id="opt">Opt</h4>
<p>options는 opt로 표기. 
이 타입은 if 구문을 나타낼 수 있음. 아래는 opt를 이용한 if 구문임. guard는 sequence fragments에서도 적용할 수 있으며 이는 opt에서도 마찬가지임. 아래 예제에서는 guard로 photo.resolution이 1280이라면 Pixel을 조절한다고 되어있음.
<img src="https://velog.velcdn.com/images/sonhm-code/post/67c2540d-2f03-4300-b88c-0bea32ae4ab3/image.png" alt=""></p>
<h4 id="loop">Loop</h4>
<p>loop는 우리가 일반적으로 아는 for 또는 while과 같은 loop 구문을 나타낸 seqence fragments. 
사용법은 guard로 condition을 작성하며 seqnece fgragments 안에서 로직을 작성하면 됨.
<img src="https://velog.velcdn.com/images/sonhm-code/post/de68bb73-6d2b-40ba-b572-098d25b46444/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/sonhm-code/post/60f061a8-b5f6-4324-ab89-77c206d82bca/image.png" alt=""></p>
<p>출처 : <a href="https://sabarada.tistory.com/84">https://sabarada.tistory.com/84</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Apps Script] 매크로 기능을 이용하여 7일간 KPI 달성 로그 확보하기]]></title>
            <link>https://velog.io/@sonhm-code/Apps-Script-%EB%A7%A4%ED%81%AC%EB%A1%9C-%EA%B8%B0%EB%8A%A5%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%98%EC%97%AC-7%EC%9D%BC%EA%B0%84-KPI-%EB%8B%AC%EC%84%B1-%EB%A1%9C%EA%B7%B8-%ED%99%95%EB%B3%B4%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@sonhm-code/Apps-Script-%EB%A7%A4%ED%81%AC%EB%A1%9C-%EA%B8%B0%EB%8A%A5%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%98%EC%97%AC-7%EC%9D%BC%EA%B0%84-KPI-%EB%8B%AC%EC%84%B1-%EB%A1%9C%EA%B7%B8-%ED%99%95%EB%B3%B4%ED%95%98%EA%B8%B0</guid>
            <pubDate>Wed, 19 May 2021 01:55:51 GMT</pubDate>
            <description><![CDATA[<h2 id="결과">결과</h2>
<p>규정된 월 KPI 안에서 KPI 달성로그를 매주 파악한다.
<img src="https://images.velog.io/images/sonhm-code/post/9e26758b-07e9-4d9e-87c4-615f88653912/Animation1.gif" alt="결과값"></p>
<p>KPI 달성로그는 지정한 시트에서 매주 월요일 자정 로그를 남긴다.
<img src="https://images.velog.io/images/sonhm-code/post/85f70f31-da99-4617-9f37-72e14c67bd86/%EC%BA%A1%EC%B2%98.JPG" alt="결과값"></p>
<h2 id="코드">코드</h2>
<pre><code class="language-javascript">function weeklyTrigger() {
  &lt;!-- R11에 최근 7일간 KPI 값을 정리 --&gt;
  var sheetR11 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(&quot;R11&quot;);
  var sheetR11NumRows = sheetR11.getDataRange().getLastRow();
  var sheetKpi = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(&quot;KPI&quot;); 
  var sheetKpiNumRows = sheetKpi.getDataRange().getLastRow();
  &lt;!-- KPI 시트에 R11의 값을 넣음 --&gt;
  var backupKpi = sheetR11.getRange(3, 1,(sheetR11NumRows-2), 7).getValues();

  Logger.log(sheetR11NumRows);
  sheetKpi.getRange((sheetKpiNumRows+1), 2, (sheetR11NumRows-2), 7).setValues(backupKpi);
}</code></pre>
<h2 id="매크로-설정">매크로 설정</h2>
<p>다음과 같이 매크로 설정한다.
<img src="https://images.velog.io/images/sonhm-code/post/97ad3a64-4817-4210-b853-a9097e5e17ab/image.png" alt="매크로 설정"></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Notion] Asana의 My Tasks 기능 구현하기]]></title>
            <link>https://velog.io/@sonhm-code/Notion%EC%9D%98-%EC%88%98%EC%8B%9D%EC%9D%84-%ED%99%9C%EC%9A%A9%ED%95%98%EC%97%AC-Asana%EC%9D%98-My-Tasks-%EA%B8%B0%EB%8A%A5-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@sonhm-code/Notion%EC%9D%98-%EC%88%98%EC%8B%9D%EC%9D%84-%ED%99%9C%EC%9A%A9%ED%95%98%EC%97%AC-Asana%EC%9D%98-My-Tasks-%EA%B8%B0%EB%8A%A5-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</guid>
            <pubDate>Thu, 13 May 2021 13:30:04 GMT</pubDate>
            <description><![CDATA[<h2 id="내가-오늘-할-일을-알려주는-my-task">내가 오늘 할 일을 알려주는 My Task</h2>
<p>업무협업툴로써, 노션만한게 있을까 싶다.</p>
<p>하지만 팀 전체가 내가 만든 노션툴로 갈아타고, 본격적인 업무를 시작하고 보니까 몇몇의 아쉬운 점들이 눈에 띄었다.</p>
<p>몹시나 강력했던 아사나의 My Tasks
<img src="https://images.velog.io/images/sonhm-code/post/1f6a5181-f84a-486e-8768-5dc16dd45e41/Untitled-1_copy.jpg" alt="1"></p>
<p>그 중의 하나가 <code>아사나</code>에서 제공했던 강력한 기능인 <code>My Tasks</code> 였다.
<code>아사나</code>의 <code>My Tasks</code>는 나에게 할당된 모든 업무 중 오늘 진행 중인 업무를 필터링하여 보여준다.</p>
<blockquote>
<p>나에게 할당된 오늘 처리해야 할 일?</p>
</blockquote>
<p>여기서 <code>오늘 처리해야 할 일</code>은 다음의 의미를 지닌다.</p>
<ol>
<li><code>착수일</code>이 오늘인 업무</li>
<li>과거에 착수 시작하여 <code>오늘 진행 중</code>인 업무</li>
<li>마감일이 지났지만 아직 <code>완료가 되지 않은</code> 업무</li>
</ol>
<blockquote>
<p>내가 하고 싶은 일은 바로 이 My Tasks를 Notion에 옮기는 일이었다.</p>
</blockquote>
<p>작업을 하면서 예상치 못한 난관에 부딛혔는데, 문제는 다음과 같았다.
노션의 모든 필터는 date_range의 시작일을 기반으로 필터링을 하기 때문에 원하는 데이터를 추출할 수가 없었다.</p>
<p><img src="https://images.velog.io/images/sonhm-code/post/fa592617-2de0-4104-a8f9-a126d2f237bd/Untitled.png" alt="2"></p>
<h2 id="formula문을-활용한-노션의-my-tasks-생성과정">Formula문을 활용한 노션의 My Tasks 생성과정</h2>
<p>때문에, <code>착수일이 과거이지만 오늘 진행 중</code>인 나의 업무를 필터링하기 곤란한 상황이 발생한다.</p>
<p>대부분의 업무는 착수한 날 종료되지 않으므로, 노션의 기본 필터 기능만으로는 <code>아사나</code>의 <code>My Tasks</code>를 구현할 수 없었다.</p>
<p>이를 위해 노션의 Formula문을 활용해야 한다.</p>
<blockquote>
<p>and(day(start(prop(&quot;일정*&quot;))) &lt;= day(now()), day(end(prop(&quot;일정*&quot;))) &gt;= day(now()))</p>
</blockquote>
<p>아래는 start와 end 구문을 통해 마감일이 현재 시점보다 미래이고 착수일이 현재 시점보다 과거인 데이터를 추출한 화면이다.
<img src="https://images.velog.io/images/sonhm-code/post/5f5a729c-9562-4d69-9f68-dc044d921c16/Untitled%20(1).png" alt="3"></p>
<p>이를 통해 착수일이 과거에 시작되었지만 마감일이 도래하지 않은 업무를 오늘 업무로 True체크 할 수 있다.
<img src="https://images.velog.io/images/sonhm-code/post/9c85162e-aa75-44d7-9b89-eebaab4a3913/Untitled%20(2).png" alt="4"></p>
<p>하지만 이 산식에도 헛점이 있다.</p>
<p>마감일이 지났어도 미완료된 업무를 <code>My Tasks</code>에 리턴시킬 수 없다는 것인데, 이럴 경우 마감일이 지났지만 완료되지 않은 업무를 놓치게 된다. (팀 관리자 입장에서 큰 고민이 아닐 수 없다.)</p>
<p>이런 경우, <code>Formula</code>문과 노션에서 제공하는 <code>Filter</code>의 기능 조합으로 해결할 수 있다.</p>
<blockquote>
<p>or(and(day(start(prop(&quot;일정*&quot;))) &lt;= day(now()), day(end(prop(&quot;일정*&quot;))) &gt;= day(now())), prop(&quot;상태*&quot;) != &quot;완료&quot;)</p>
</blockquote>
<p>우선, 좀 전의 산식에서 상태가 &quot;완료&quot;가 아닌 모든 업무를 OR구문으로 계산한다.
<img src="https://images.velog.io/images/sonhm-code/post/9e2693a5-3487-4722-893b-508bb91c10ad/Untitled%20(3).png" alt="5"></p>
<p>착수가 시작되었지만 마감일이 오지 않은 업무와 완료상태가 되지 않은 모든 업무의 합집합이 TRUE 체크 되었다.
<img src="https://images.velog.io/images/sonhm-code/post/02c35ad4-36a6-40aa-b6e3-6239b10e3db1/Untitled%20(4).png" alt="6"></p>
<p>이 상태에서 테이블 필터링을 걸어준다.
<img src="https://images.velog.io/images/sonhm-code/post/56b99019-0738-4b2c-8eb0-9ca66ac83a27/Untitled%20(5).png" alt="7"></p>
<p>And 조건으로 다음과 같이 작업을 한다. 계산된 필드의 TRUE값 중에 상태가 완료가 아닌 업무를 필터링한다.
<img src="https://images.velog.io/images/sonhm-code/post/1cac2c76-b7c3-482b-883f-0632c883f2a9/Untitled%20(6).png" alt="8"></p>
<p>오늘 업무에 미완료한 모든 업무 및 오늘 진행되는 업무들이 성공적으로 나열되었다.
<img src="https://images.velog.io/images/sonhm-code/post/65666c66-ac6d-4ffd-98b5-75c2c7cebc26/KakaoTalk_20191219_213533496.jpg" alt="9"></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Sheets] IMPORTRANGE 함수 범위 불러오기 오류 해결하기]]></title>
            <link>https://velog.io/@sonhm-code/Sheets-IMPORTRANGE-%ED%95%A8%EC%88%98-%EB%B2%94%EC%9C%84-%EB%B6%88%EB%9F%AC%EC%98%A4%EA%B8%B0-%EC%98%A4%EB%A5%98-%ED%95%B4%EA%B2%B0%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@sonhm-code/Sheets-IMPORTRANGE-%ED%95%A8%EC%88%98-%EB%B2%94%EC%9C%84-%EB%B6%88%EB%9F%AC%EC%98%A4%EA%B8%B0-%EC%98%A4%EB%A5%98-%ED%95%B4%EA%B2%B0%ED%95%98%EA%B8%B0</guid>
            <pubDate>Thu, 13 May 2021 13:16:36 GMT</pubDate>
            <description><![CDATA[<p>활용도가 높은 Gsuite는 스타트업에게  큰 힘이 되지만, 간간히 오류를 일으키기에 고민이 될 때도 있다. importrange문은 논리적인 문제가 없을 때도 오류가 종종 생기곤 하는데, 이는 구글 내부의 문제로써 유저가 해결하기 어려운 부분이 있다.</p>
<blockquote>
<p>골치 아픈 importrange 오류</p>
</blockquote>
<p><img src="https://images.velog.io/images/sonhm-code/post/0dd15b0c-29a2-48c6-975e-d23ccfd736af/Untitled%20(1).png" alt="오류화면"></p>
<p>이럴 때 대응방법으로 활용하는 것이 IFERROR문과 IMPORT문의 조합이다.</p>
<p>B2가 참조할 시트의 스프레드시트의 URL주소이고, C3가 범위 문자열이라고 한다면 , 통상 다음의 방법으로 시트를 불러올 것이다.</p>
<blockquote>
<p>B2 : URL 주소
B3 : R7!$A$2:$A
IMPORTRANGE(B2,B3)</p>
</blockquote>
<p>하지만 여기서 오류가 발생할 확률이 생긴다. 범위 오류가 생기는 여러가지 이유 중 가장 큰 문제는 바로 범위 문자열의 대소문자 구분 이슈에서 온다.</p>
<p>따라서 <code>IFERROR</code>문을 활용해 에러가 날 경우, 대소문자를 모두 탐지하여 <code>IMPORT</code> 해올 수 있도록 쿼리를 짠다.</p>
<p>우선, 대소문자 경우의 수를 대비하여 참조 주소를 세팅해둔 후,</p>
<blockquote>
<p>B2 : URL 주소
B3 : R7!$A$2:$A
C3 : R7!$A$2:$a
D3 : R7!$a$2:$A
E3 : R7!$a$2:$a
F3 : r7!$A$2:$A
G3 : r7!$a$2:$A
H3 : r7!$A$2:$a
I3 : r7!$a$2:$a</p>
</blockquote>
<p><code>IFERROR</code>문으로 에러가 날 경우, IMPORT를 계속 수행할 수 있도록 쿼리를 짜준다.</p>
<p>원리는 내부 불러오기 에러가 발생한 경우, 시트 내에 강제적으로 다른 범위로 계산케 해주는 것이다.</p>
<p>1번에 오류로 멈춰있을 시트가 이렇게 되면 강제적으로 4번 연산이 되므로, 오류가 줄 확률이 많이 줄어든다.</p>
<blockquote>
<p>=
IFERROR(
IFERROR(
IFERROR(
IFERROR(
IFERROR(
IFERROR(
IFERROR(IMPORTRANGE(B2,B3),IMPORTRANGE(B2,C3)),
IMPORTRANGE(B2,D3)),IMPORTRANGE(B2,E3)),
IMPORTRANGE(B2,F3)),IMPORTRANGE(B2,G3)),
IMPORTRANGE(B2,H3)),IMPORTRANGE(B2,I3))</p>
</blockquote>
<p><del>해당 반복문이 모든 문제를 해결해주지 않지만, 가장 확실한 문제 해결 방법이다. ~</del> (업데이트 내용을 통해서 해결함)</p>
<h2 id="update-20-04-08">UPDATE (20-04-08)</h2>
<p>위의 방법으로 모든 문제가 해결되지 않았다. 다음의 문제가 해결되지 않은 이유를 살펴보니, 강제 반복계산이 수행되지 않고 있었다는 사실을 발견했다.</p>
<p>자동 반복계산을 수행케하기 위해서 다음의 방법을 시도해보았다.</p>
<ol>
<li>범위참조주소를 업데이트 시켜주는 쿼리를 짬으로써, 시트 계산 트리거가 발현할 수 있도록 함.
<img src="https://images.velog.io/images/sonhm-code/post/76307349-6cff-4dc9-9de1-9bc79329f1c0/Untitled%20(2).png" alt="1"></li>
</ol>
<ol start="2">
<li>파일 &gt; 스프레드시트 설정 &gt; 반복계산 사용으로 시트 내 반복 계산을 활성화함. (시트내 순확종속성 오류를 해결하기 위해 스프레드시트 설정의 반복계산을 허용)
<img src="https://images.velog.io/images/sonhm-code/post/ea6f096c-01a5-4d3f-adb1-b6f5d198a0b4/Untitled%20(3).png" alt="2"></li>
</ol>
<p>오류가 해결된 모습
<img src="https://images.velog.io/images/sonhm-code/post/93ceac21-159b-4d78-9976-34e119e525bc/Untitled%20(4).png" alt="3"></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Tableau] Weeknum을 Date형식으로 Convert하여 일자별 추이 구하기]]></title>
            <link>https://velog.io/@sonhm-code/Tableau-Weeknum%EC%9D%84-Date%ED%98%95%EC%8B%9D%EC%9C%BC%EB%A1%9C-Convert%ED%95%98%EC%97%AC-%EC%9D%BC%EC%9E%90%EB%B3%84-%EC%B6%94%EC%9D%B4-%EA%B5%AC%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@sonhm-code/Tableau-Weeknum%EC%9D%84-Date%ED%98%95%EC%8B%9D%EC%9C%BC%EB%A1%9C-Convert%ED%95%98%EC%97%AC-%EC%9D%BC%EC%9E%90%EB%B3%84-%EC%B6%94%EC%9D%B4-%EA%B5%AC%ED%95%98%EA%B8%B0</guid>
            <pubDate>Thu, 13 May 2021 13:08:45 GMT</pubDate>
            <description><![CDATA[<h2 id="결과물">결과물</h2>
<p>기간별 필터링을 적용하여 원하는 기간 기준으로 추이를 확인토록한 화면
<img src="https://images.velog.io/images/sonhm-code/post/5062cd04-f3bd-4b47-97cc-2bd6eda32947/gif.gif" alt="결과"></p>
<h3 id="date-자료형은-다양한-계층-구조를-지닌다">Date 자료형은 다양한 계층 구조를 지닌다.</h3>
<p>태블로에서는 Date형식을 다음과 같이 분류해준다.</p>
<blockquote>
<p>년 ⇒ 분기 ⇒ 월 ⇒ 일</p>
</blockquote>
<p>해당 방식은 동일 기간 내 데이터 자료를 다각도로 분석할 수 있도록 도와준다. 예를 들면, 분기별로 개괄적인 추이를 확인하고 특정 기간의 이슈를 월 혹은 일자별로 확인하는 식이다.</p>
<p>태블로의 Date형식 구조. 
<img src="https://images.velog.io/images/sonhm-code/post/3a3b08fd-685c-4280-8b07-a3011fcf5599/Untitled.png" alt="1"></p>
<p>몇가지 추가 작업이 필요하지만, 태블로의 Date 계층 구조는 구글스프레드시트에서도 구현할 수 있다.</p>
<p>구글 스프레드시트에서 기간별 효율 추이 그래프를 적용한 화면 
<img src="https://images.velog.io/images/sonhm-code/post/83cd973a-8999-4019-83f8-60d9cd252212/Untitled(1).png" alt="2"></p>
<p>구글 스프레드시트에서 주별, 월별, 일별 필터를 적용한 화면
<img src="https://images.velog.io/images/sonhm-code/post/3a611566-c5bc-4e82-9d18-fcf33a237c05/Untitled_(14).png" alt="3"></p>
<h3 id="spread-sheet의-디폴트-기간세트-system1">Spread Sheet의 디폴트 기간세트 SYSTEM1</h3>
<p>스프레드 시트에서 제공하는 Date형식 Formula는 다음과 같다.</p>
<ol>
<li>Weekday : 일자의 요일을 숫자형식으로 추출 (디폴트 일요일은 1)
<img src="https://images.velog.io/images/sonhm-code/post/939a89b8-3330-4d4c-a8ec-7b16f2123d60/Untitled%20(15).png" alt="4"></li>
<li>Weeknum : 일자별 형식을 주별 형식의 데이터로 변경</li>
</ol>
<ul>
<li>기본적으로 일-토 단위로 1주를 묶는 System1 방식의 주 카운팅 방법이 적용된다.</li>
<li>중복된다. (2019.01.01이 속한 주와 2020.01.01이 속한 주의 Weeknum은 1로 동일하다.)</li>
<li>12월 마지막 주와 이듬해 1월 첫째주는 같은 주간에 있어도 다른 Weeknum가 적용된다.</li>
</ul>
<p>2019.12.31은 Weeknum 53, 2020.01.01은 Weeknum 1이 적용된다.
<img src="https://images.velog.io/images/sonhm-code/post/dcb4e368-26b4-45fd-a784-992f5457eef6/Untitled%20(16).png" alt="5"></p>
<h3 id="weeknum형을-date형식으로-변환하는-과정">Weeknum형을 DATE형식으로 변환하는 과정</h3>
<p>구글 스프레드시트는 태블로와 달리, 통계로 활용하기 위해서 몇 가지 추가작업이 필요한데, 그 중 대표적인 처리가 인덱싱이다. </p>
<p>예를 들면, <code>2020.01.01</code>이 속한 주의 통계를 확인할 때, 구글 스프레드 시트의 <code>Weeknum 1</code>로 불러오면, 유저 입장에서 어떤 날의 정보인지 가늠하기 어렵다. 이럴 때 <code>Weeknum 1</code>을 <code>2020.01.01 ~ 2020.01.04</code>로 인덱싱해주는 작업이 필요하다.</p>
<p>모든 데이터는 가장 작은 단위에서부터 통계를 추출하므로, 원시 데이터로 일별 데이터를 가지고 있다고 가정하자.</p>
<p>일별데이터로 구성된 원시데이터 세트. 편의상, B칼럼에 두었다.
<img src="https://images.velog.io/images/sonhm-code/post/4cab767c-197b-4063-aaff-966228b84bfb/Untitled%20(17).png" alt="6"></p>
<p>인덱싱을 위해 유저가 식별하기 쉬운 명칭으로 일별 데이터를 가공한다. </p>
<p>일-토까지를 1주로 보기 때문에, 당해년도에 한해서 일별 데이터는 총 7개의 중복값을 지닌다.</p>
<blockquote>
<p>ARRAYFORMULA(
IF(B3:B=&quot;&quot;,&quot;&quot;, # B칼럼 중 존재하는 값만 계산한다.
CONCAT(CONCAT(TEXT(B3:B,&quot;YY&quot;),&quot;년 &quot;), # 계산할 일자의 년도를 한글화한다.
CONCAT(WEEKNUM(B3:B,1),&quot;주차&quot;) # 계산할 일자의 주차번호를 한글화한다.
)
)
)</p>
</blockquote>
<p>A:B 칼럼의 정보를 활용해서 C 칼럼에 Vlookup한다.
<img src="https://images.velog.io/images/sonhm-code/post/3fcc3b06-ea30-416f-87b7-37207b3f76d9/Untitled%20(18).png" alt="7"></p>
<p>칼럼명이 기간인 C칼럼에는 해당 주차의 시작일과 마감일을 보기 좋게 인덱싱할 예정이다.</p>
<p>한주는 7일이니, 마감일은 통상 시작일의 6일 후로 볼 수 있기에, 다음 코드를 생각할 수 있다.</p>
<blockquote>
<p>ARRAYFORMULA(
IF(B3:B=&quot;&quot;,&quot;&quot;,
CONCAT(
CONCAT(
TEXT(B3:B,&quot;YY-MM-DD(DDD)&quot;),&quot; ~ &quot;), #B칼럼의 시작일을 불러온다.
CONCAT(
TEXT(B3:B+6},&quot;YY-MM-DD(DDD)&quot;),&quot;&quot;)) #시작일에 6일을 더한 값을 마감일로 설정한다.
))</p>
</blockquote>
<p>하지만, 시작일이 무조건 일요일인 경우는 없으므로 다음의 작업을 추가해둔다.</p>
<blockquote>
<p>ARRAYFORMULA(
IF(B3:B=&quot;&quot;,&quot;&quot;,
CONCAT(
CONCAT(
TEXT({VLOOKUP(A3:A,A:B,2,0)+{1-WEEKDAY(VLOOKUP(A3:A,A:B,2,0))}},&quot;YY-MM-DD(DDD)&quot;),&quot; ~ &quot;), #B칼럼에서 시작일을 불러온다.
CONCAT(
TEXT({VLOOKUP(A3:A,A:B,2,0)+{7-WEEKDAY(VLOOKUP(A3:A,A:B,2,0))}},&quot;YY-MM-DD(DDD)&quot;),&quot;&quot;))
#B칼럼에서 불러온 시작일 정보를 계산해서 마감일을 맞춘다. (* 7-시작일의 요일값)
))</p>
</blockquote>
<p>여기서 7 - 시작일의 요일값으로 마감일을 계산한 이유는 다음과 같다.</p>
<p>기본적으로 일요일은 숫자 1이 할당된다.
<img src="https://images.velog.io/images/sonhm-code/post/a8ea1964-9160-491c-b5a7-78a7126d539a/Untitled%20(19).png" alt="8"></p>
<blockquote>
<p>마감일 = 시작일 + {7 - 시작일(요일값)}</p>
</blockquote>
<ol>
<li>모든 값은 일 - 토이며, 마감일은 무조건 토요일이다.</li>
<li>토요일(7)이 시작일인 경우, 마감일도 토요일(7)이므로 0의 값을 더한다.</li>
<li>일요일(1)이 시작일인 경우, 마감일인 토요일(7)까지 6의 값을 더한다.</li>
<li>수요일(4)이 시작일인 경우, 마감일인 토요일(7)까지 3의 값을 더한다.</li>
</ol>
<p>다음과 같이 시작일을 계산하여, 마감일 정보를 추출하였다.
<img src="https://images.velog.io/images/sonhm-code/post/63d3e9a2-7a51-4b3b-b0bc-80c5a82bd38c/Untitled%20(20).png" alt="9"></p>
<p>하지만, 여기서도 문제가 있다. 12.31이 속한 주와 01.01이 속한 주를 구별하지 못한다.
<img src="https://images.velog.io/images/sonhm-code/post/d5c53003-b748-4691-87a7-6df37a6ced54/Untitled%20(21).png" alt="10"></p>
<p>앞서 말한 바, 12월 마지막 주와 이듬해 1월 첫째주는 같은 주간에 있어도 다른 Weeknum가 적용된다. 이런 경우, Weeknum 구분 기준에 맞추어 12.31과 01.01이 같은 주에 포함되어 있어도, 분류해주어야 한다.</p>
<p>이를 위해서 다음의 Formula문이 적용된다.</p>
<blockquote>
<p>ARRAYFORMULA(
IF(B3:B=&quot;&quot;,&quot;&quot;,
IF(WEEKNUM(B3:B)=1, # 매해 1번째 주간인 경우,
CONCAT(
CONCAT(
TEXT({VLOOKUP(A3:A,A:B,2,0)},&quot;YY-MM-DD(DDD)&quot;),&quot; ~ &quot;),
CONCAT(
TEXT({VLOOKUP(A3:A,A:B,2,0)+{7-WEEKDAY(VLOOKUP(A3:A,A:B,2,0))}},&quot;YY-MM-DD(DDD)&quot;),&quot;&quot;)),# 시작일은 1월 1일로 리턴한다. 마감일은 1월 1일 시작일을 기준으로 계산한다.
IF(WEEKNUM(B3:B)=53, # 매해 53번째 주간인 경우, 53번째 주간은 마지막 주간이다.
CONCAT(
CONCAT(
TEXT({VLOOKUP(A3:A,A:B,2,0)+{1-WEEKDAY(VLOOKUP(A3:A,A:B,2,0))}},&quot;YY-MM-DD(DDD)&quot;),&quot; ~ &quot;),
CONCAT(
TEXT({VLOOKUP(A3:A,A:B,2,0)+
{COUNTIF(A:A,CONCAT(CONCAT(TEXT(B3:B,&quot;YY&quot;),&quot;년 &quot;),CONCAT(WEEKNUM(B3:B,1),&quot;주차&quot;)))-1}},&quot;YY-MM-DD(DDD)&quot;),&quot;&quot;)),# 시작일 이후 12월 31일까지 남은 일수를 시작일과 더해 마감일을 구한다.
CONCAT(
CONCAT(
TEXT({VLOOKUP(A3:A,A:B,2,0)+{1-WEEKDAY(VLOOKUP(A3:A,A:B,2,0))}},&quot;YY-MM-DD(DDD)&quot;),&quot; ~ &quot;),
CONCAT(
TEXT({VLOOKUP(A3:A,A:B,2,0)+{7-WEEKDAY(VLOOKUP(A3:A,A:B,2,0))}},&quot;YY-MM-DD(DDD)&quot;),&quot;&quot;))
))))</p>
</blockquote>
<p>Weeknum와 기간 인덱싱이 정확히 매핑되었다.
<img src="https://images.velog.io/images/sonhm-code/post/789f7cbd-3a0b-460e-9cc3-b9e7034cafd6/Untitled%20(22).png" alt="11"></p>
<p>태블로로 넘기면 주별 넘버를 통해 기간 정보가 정확히 인덱싱된 모습을 확인할 수 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[기획] Arrayformula문의 활용으로 린하게 데이터마트 구축하기]]></title>
            <link>https://velog.io/@sonhm-code/Sheets-Arrayformula%EB%AC%B8%EC%9D%98-%ED%99%9C%EC%9A%A9</link>
            <guid>https://velog.io/@sonhm-code/Sheets-Arrayformula%EB%AC%B8%EC%9D%98-%ED%99%9C%EC%9A%A9</guid>
            <pubDate>Thu, 13 May 2021 12:36:44 GMT</pubDate>
            <description><![CDATA[<p>실제 대행사에서 쓰는 데이터를 기반으로 만든 대시보드이다. 제작기간은 1~2일 남짓 걸렸다.</p>
<p>최대 2년간 모든 매체의 모든 소재별 데이터 조회가 무리없이 가능하다.
어떻게 가능할까? 바로 배열수식과 csv 그리고 구글시트에서 제공하는 importrange 수식 덕분이다.</p>
<h2 id="배열수식의-장점">배열수식의 장점</h2>
<p>수식에 사용되는 데이터들을 하나의 배열로 인식하여 결과값을 계산하는 방법을 배열수식이라고 한다. 
배열수식을 잘 활용할 수만 있다면, 무수히 많은 중첩함수를 하나의 산식만으로 해결할 수 있다. 당연히 시트의 계산속도는 현저히 빨라진다.</p>
<h3 id="배열수식의-한계">배열수식의 한계</h3>
<p>배열수식은 강력하지만 모든 formula문에서 적용 가능한 것은 아니다. 대표적인 예로 다중조건문에서 배열수식 적용이 불가능하다. 다중조건문을 적용할 수 없는 문제는 다음과 같이 해결할 수 있었다.</p>
<h2 id="arrayformula에서-ifs-쓰기">Arrayformula에서 Ifs 쓰기</h2>
<blockquote>
<p>보너스 120만원 이상 받으면 A+ 100만원 이상 받으면 A 나머지는 B 처리한다.</p>
</blockquote>
<p>배열함수를 안쓴다면, Ifs로 다음과 같이 해결이 가능하다.
<img src="https://images.velog.io/images/sonhm-code/post/fe0135b5-a616-48ea-9a37-995004f6f40d/Untitled%20(4).png" alt="1"></p>
<p>IFS문을 쓰기 위해선 IF문을 중첩해서 사용해야한다. 연산속도는 데이터양이 증가할수록 배열수식이 유리하다.
<img src="https://images.velog.io/images/sonhm-code/post/aeaa7add-587f-41b4-98c2-774c03d2afb0/Untitled%20(5).png" alt="2"></p>
<h2 id="arrayformula문에서의-문자조합">Arrayformula문에서의 문자조합</h2>
<p>3개 이상의 문자를 조합해야하는 경우, Arrayformula문에서 Concatenate문을 실행하면 원하는 값을 얻을 수 없다. 이런 경우 Concat을 이중 적용하여 원하는 3개 이상의 문자열을 조합해야 한다. 다음의 예제를 보자.</p>
<p>셀마다 개별 적용할 경우, Concatenate문으로 쉽게 조합할 수 있다.
<img src="https://images.velog.io/images/sonhm-code/post/9ddb2855-11a0-48a2-b249-82c7d9d3208e/Untitled%20(6).png" alt="1"></p>
<p>Arrayformula문에 Concatenate를 사용하면 범위 내 지정한 모든 텍스트의 조합값이 하나의 셀에 표기된다.
<img src="https://images.velog.io/images/sonhm-code/post/e17aa778-9dd5-46f8-a630-b060c60e2556/Untitled%20(7).png" alt="2"></p>
<p>Arrayformula문을 쓸 경우, Concat를 이중 적용하여, 각 셀별로 원하는 텍스트를 조합한다.
<img src="https://images.velog.io/images/sonhm-code/post/f536c9be-b8b3-46c2-b017-bf828a3f27e8/Untitled%20(8).png" alt="3"></p>
<h2 id="arrayformulaconcat문과-join문을-활용하여-csv파일-만들기">Arrayformula+Concat문과 Join문을 활용하여 CSV파일 만들기</h2>
<p>CSV는 몇 가지 필드를 쉼표(,)로 구분한 텍스트 데이터 및 텍스트 파일을 의미한다. 확장자는 .csv이며 MIME 형식은 text/csv이다. comma-separated variables라고도 한다.
쉼표로만 구분된 텍스트 형태인 CSV는 데이터분석을 위한 raw 파일로서 범용적이라는 장점이 있다.</p>
<h2 id="구글스프레드시트의-꽃-importrange">구글스프레드시트의 꽃 importrange</h2>
<p>엑셀에서 구글스프레드시트로 넘어가는 이유는 데이터 연동이 실시간으로 이루어진다는 점에 있다.</p>
<p>스키마 구조를 짜듯이 시트간 데이터 연동을 체계적으로 구축할 수 있다면, 제법 쓸만한 데이터분석툴로 활용할 수 있다.</p>
<p>광고분석을 실시간으로 할 수 있는 크리에이티브 통계, 최대 3년치의 데이터 분석이 가능하도록 설계했다.
<img src="https://images.velog.io/images/sonhm-code/post/faf27b97-b70d-4e81-8d48-9314929d7a89/KakaoTalk_20191229_012146731.gif" alt="결과물"></p>
<p>이 때 사용하는 주된 함수들이 바로 importrange이다.</p>
<pre><code>importrange(&quot;스프레드시트_url&quot;,&quot;범위_문자열&quot;) #지정된 시트의 셀범위를 가져온다.</code></pre><ol>
<li>스프레드시트_URL : 가져올 데이터가 있는 스프레드시트의 URL</li>
<li>범위_문자열 : 가져올 범위를 지정하는 형식&quot;[시트_이름!]범위&quot;(예: &quot;Sheet1!A2:B6&quot; 또는 &quot;A2:B6&quot;)의 문자열</li>
</ol>
<p>이전 예제로 썼던 데이터를 import하기로 한다.
<img src="https://images.velog.io/images/sonhm-code/post/82bd5513-197d-4bda-898d-1538849103e2/Untitled%20(9).png" alt="예시1">
해당 URL의 데이터를 불러왔다. 2시트간 연동된 데이터는 실시간으로 공유 및 반영된다.
<img src="https://images.velog.io/images/sonhm-code/post/d17c57a8-4367-4226-b1fc-23e07a9bf9f2/Untitled%20(10).png" alt="예시2"></p>
<h2 id="구글스프레드시트에서-csv파일">구글스프레드시트에서 CSV파일</h2>
<p>구글스프레드시트에서 <code>CSV</code>파일의 성격을 이용하면 보다 빠르고 강력한 데이터 분석이 가능하다.</p>
<p>첨부한 예제를 보면 알 수 있듯이, 쉽고 빠르게 연동이 가능하다.</p>
<p>하지만 예제는 21개의 데이터로만 이루어져있다. 실무에서는 셀 수 없이 많은 데이터의 분석이 필요하다.</p>
<p><code>importrange</code>함수의 부하는 불러오는 셀의 갯수와 관련이 있기 때문에 분석할 데이터의 양이 많아질수록 연동할 셀의 갯수가 많아지므로 시트가 무거워진다는 단점이 있다.</p>
<blockquote>
<p>총 21개의 data를 추출했다. 만약에 추출할 데이터가 1,000,000,000개가 넘는다면?</p>
</blockquote>
<p><img src="https://images.velog.io/images/sonhm-code/post/04edd663-d00f-4f7d-9ec6-1be611fe0572/Untitled%20(11).png" alt="예시3"></p>
<p>이럴 때 사용하는 것이 <code>Arrayformula</code>문과 <code>Concat</code>문 및 <code>Join</code>문이다.</p>
<p>구글스프레드시트는 셀 1개에 최대 30000개의 텍스트를 담을 수 있는데, 데이터 유형에 따라 최소 수개월에서 수년의 데이터를 구글스프레드시트의 1셀에 담을 수 있다.</p>
<p>셀 1개에 응축된 <code>CSV</code>형태의 데이터를 담고, 이를 <code>importrange</code>함수를 이용해 빠르게 연동시켜보자.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Python] 기초 연습 문제]]></title>
            <link>https://velog.io/@sonhm-code/Python-%EA%B8%B0%EC%B4%88-%EC%97%B0%EC%8A%B5-%EB%AC%B8%EC%A0%9C</link>
            <guid>https://velog.io/@sonhm-code/Python-%EA%B8%B0%EC%B4%88-%EC%97%B0%EC%8A%B5-%EB%AC%B8%EC%A0%9C</guid>
            <pubDate>Thu, 13 May 2021 12:33:04 GMT</pubDate>
            <description><![CDATA[<h2 id="key는-while-규정할-때의-규칙을-기억하는-것">Key는 <code>while</code> 규정할 때의 규칙을 기억하는 것</h2>
<ol>
<li><code>while</code> 시작점을 정의</li>
<li><code>while</code> 범위를 정의</li>
<li><code>while</code> 증가방식을 정의</li>
</ol>
<blockquote>
<p>근무시간을 주당 12시간으로 규정하고 있다. 12시간을 초과한 경우, 시간당급여를 30%로 더 지급한다. 주당 총 근무 시간과 시간당 급여를 입력받아 1주일 급여를 계산하는 프로그램을 작성하시오.</p>
</blockquote>
<pre><code class="language-python">working_hour = int(input(&#39;근무시간을 입력하시오: &#39;))
pay_per_hour = int(input(&#39;시급을 입력하시오: &#39;))
total_pay = working_hour * pay_per_hour

if working_hour &gt; 12:
     additional_pay = (working_hour - 12) * pay_per_hour * 0.3
     total_pay = total_pay + additional_pay
     print(int(total_pay))
else :
     print(int(total_pay))</code></pre>
<p><img src="https://images.velog.io/images/sonhm-code/post/1eb3334f-df9e-4d8c-8013-d09a4f168494/Untitled.png" alt="1"></p>
<blockquote>
<p>하나의 양의 정수를 입력받아서 그 수의 약수를 모두 출력하고 약수의 개수도 출력하시오.</p>
</blockquote>
<pre><code class="language-python">n = int(input(&#39;정수를 입력하시오: &#39;)) # (1)입력받는 정수 정의

a = 1 # (2)while문의 시작점 정의 a는 1부터 시작한다.
count = 0 
while a &lt;= n : # (3)while문의 a 범위 정의
    if n % a == 0 :
        print(a) 
        count += 1 
    a += 1 # (4) while문의 a 증가 방식 규정

print(n, &#39;의 약수의 개수&#39;, count)</code></pre>
<p><img src="https://images.velog.io/images/sonhm-code/post/7cb279ac-85a9-4944-b1eb-79b0f7806d8d/Untitled%20(1).png" alt="2">
<img src="https://images.velog.io/images/sonhm-code/post/97299d37-9002-4676-8d66-ab42e2da904e/Untitled%20(2).png" alt="3"></p>
<blockquote>
<p>다섯 개의 정수를 하나씩 받아서 그 정수들 중에서 가장 큰 값을 구하시오</p>
</blockquote>
<pre><code class="language-python">n = int(input(&#39;정수를 입력하시오: &#39;))
max = n #최초 입력받은 수가 가장 큰수라는 가정

loop_count = 1 # (1) while의 시작 정의
while loop_count &lt; 5: # (2)while의 범위 정의
    n = int(input(&#39;정수를 입력하시오: &#39;))
    if n &gt; max :
        max = n
    loop_count+=1 # (3)해당 코드 없을 경우, 무한루프 돈다. Loop_count가 1이니까

print(&#39;최대값은 &#39;,max)</code></pre>
<p><img src="https://images.velog.io/images/sonhm-code/post/10f401c5-5989-486b-a43a-620f7f99d012/Untitled%20(3).png" alt="4"></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Python] 서강대 강의 예제]]></title>
            <link>https://velog.io/@sonhm-code/Python-%EC%84%9C%EA%B0%95%EB%8C%80-%EA%B0%95%EC%9D%98-%EC%98%88%EC%A0%9C</link>
            <guid>https://velog.io/@sonhm-code/Python-%EC%84%9C%EA%B0%95%EB%8C%80-%EA%B0%95%EC%9D%98-%EC%98%88%EC%A0%9C</guid>
            <pubDate>Thu, 13 May 2021 12:24:10 GMT</pubDate>
            <description><![CDATA[<h2 id="range를-활용한-for문-예제">Range를 활용한 For문 예제</h2>
<p><img src="https://images.velog.io/images/sonhm-code/post/9806ab80-75d6-44b3-9ff9-20a83dd8fc95/Untitled.png" alt="문제1"></p>
<pre><code class="language-python"># 0-9 숫자를 출력하는 코드
for x in range(0,10):
    print(x, end=&quot; &quot;) #end=&quot; &quot;는 default인 char(10)을 br로 바꾸어주는 역할
print()

# 0-50 5의 배수로 출력하는 코드
for x in range(0,51,5):
    print(x, end=&quot; &quot;)
print()

# 10-1 역순으로 출력하는 코드
for x in range(10,0,-1):
    print(x, end=&quot; &quot;)
print()</code></pre>
<p><img src="https://images.velog.io/images/sonhm-code/post/90db2861-30d8-41f3-8d80-6283cdab647b/Untitled%20(1).png" alt="문제2"></p>
<pre><code class="language-python"># 5회에 걸쳐서 성적을 입력하기
score = []
for i in range(5):
  data = int(input(&quot;성적을 입력하세요 : &quot;))
  score.append(data)
print(&#39;입력한 성적 : &#39;,score)

# 최대값 및 최소값 추출하기
print(&#39;최고 성적 : &#39;,max(score))
print(&#39;최저 성적 : &#39;,min(score))

# 평균값 추출하기
avg = sum(score) / len(score)
print(&#39;평균 성적 : %.2f&#39; % avg) #소수점 2번째까지 실수형으로 추출하기</code></pre>
<p><img src="https://images.velog.io/images/sonhm-code/post/d19745eb-f375-420b-89a9-bb3972842b00/Untitled%20(2).png" alt="문제3"></p>
<pre><code class="language-python">#데이터를 Dict자료형으로 생성
score = {1:[80,90,86],
         2:[78,88,85],
         3:[85,85,92],
         4:[70,69,65],
         5:[90,95,100]
         }</code></pre>
<p>다음과 같은 형태의 dict 자료형이 생성된다.
<img src="https://images.velog.io/images/sonhm-code/post/33b7fc6c-3321-4344-9af7-a7c9f21c4b9a/Untitled%20(3).png" alt="예시"></p>
<pre><code class="language-python"># 개별 평균값 추출하기
for k,v in score.items(): #score dict를 [키,값]의 리스트로 추출
  print(k,&#39;번 : &#39;,sum(v)/len(v))</code></pre>
<p>items는 키와 값의 리스트를 생성한다. items는 dict자료형을 list 쌍으로 리턴한다.
<img src="https://images.velog.io/images/sonhm-code/post/4dde2299-b329-46be-bae8-6538026bfa3b/Untitled%20(4).png" alt="예시"></p>
<p>items는 dict자료형을 list 쌍으로 리턴한다.
<img src="https://images.velog.io/images/sonhm-code/post/f84b73a0-e71c-4e29-9dcc-3bacc7bb849e/Untitled%20(5).png" alt="예시"></p>
<h2 id="while-실습">While 실습</h2>
<p>2 - 9까지 구구단 값을 리턴
<img src="https://images.velog.io/images/sonhm-code/post/b001adb0-2fa6-413b-b433-47ec4634252b/Untitled.png" alt="구구단 만들기 예제"></p>
<pre><code class="language-python">#%% 구구단 만들기

dan = 2 #dan이라는 객체가 2부터 시작
while dan &lt;= 9 : # 9까지 반복한다. 2단부터 9단까지 반복
    n = 1 
    while n &lt;= 10: 
        value = dan * n #곱하기의 정의
        print(&#39;%3d&#39; %(value), end=&#39;&#39;) #출력하되, 스페이스 건너 배치
        n += 1 #n이 1씩 증가하여 10번째까지 외움
    print() #2단의 한 Row를 완성
    dan += 1 #9단까지 외움</code></pre>
<p>다음과 같이 결과값이 나온다.
<img src="https://images.velog.io/images/sonhm-code/post/059cbbb9-fe1f-4514-bdf4-4d94e8befb5a/Untitled%20(1).png" alt="결과"></p>
<h3 id="break와-continue의-이해">Break와 Continue의 이해</h3>
<p>Break는 While문을 나가버린다.
<img src="https://images.velog.io/images/sonhm-code/post/12de507e-0dd9-414a-9933-cfe0edbc1986/P8_while_.pdf_page_07.jpg" alt="3">
Continue는 조건에 맞는 경우, Skip하고 다음 반복 쿼리를 처리한다.
<img src="https://images.velog.io/images/sonhm-code/post/517148c6-308f-4e62-a20f-edf771135214/P8_while_.pdf_page_09.jpg" alt="4"></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Tableau] 측정값별로 필터링하여 데이터 분석]]></title>
            <link>https://velog.io/@sonhm-code/Tableau-%EC%B8%A1%EC%A0%95%EA%B0%92%EB%B3%84%EB%A1%9C-%ED%95%84%ED%84%B0%EB%A7%81%ED%95%98%EC%97%AC-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B6%84%EC%84%9D</link>
            <guid>https://velog.io/@sonhm-code/Tableau-%EC%B8%A1%EC%A0%95%EA%B0%92%EB%B3%84%EB%A1%9C-%ED%95%84%ED%84%B0%EB%A7%81%ED%95%98%EC%97%AC-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%B6%84%EC%84%9D</guid>
            <pubDate>Thu, 13 May 2021 12:04:24 GMT</pubDate>
            <description><![CDATA[<h2 id="결과">결과</h2>
<p><img src="https://images.velog.io/images/sonhm-code/post/d6cdba21-11ee-4041-9d15-4dd6d5be4b81/Animation.gif" alt="결과"></p>
<h2 id="측정값">측정값</h2>
<p>집계 가능한 숫자형 자료형 및 파생칼럼의 속성값들은 자동 측정값 항목으로 규정된다.</p>
<p>숫자형 자료형은 기본 칼럼 및 계산된 필드를 포함한다.</p>
<ol>
<li>숫자형 자료형 예시 : 노출, 클릭, CPC 등</li>
<li>파생칼럼의 속성값 예시 : 레코드 수의 합계 등</li>
</ol>
<p>앤티티를 통해 도출된 다양한 측정값
<img src="https://images.velog.io/images/sonhm-code/post/ee10dd2a-0135-4632-8901-82f00228e532/Untitled.png" alt="1"></p>
<h2 id="측정값을-필터값으로-지정할-수-있는-방법">측정값을 필터값으로 지정할 수 있는 방법</h2>
<p>워크시트 내 측정값을 필터로 적용한 모습
<img src="https://images.velog.io/images/sonhm-code/post/0ac0e893-81ba-4386-8a4e-558e786795b1/Untitled2.png" alt="2">
측정값의 가장 하단에 측정값 전체를 대변하는 값이 있다.
<img src="https://images.velog.io/images/sonhm-code/post/a4d7258f-0724-4861-bd45-71821d74beda/Untitled3.png" alt="3">
필터와 마크에 측정값을 배치
<img src="https://images.velog.io/images/sonhm-code/post/1c2bc68c-7760-408f-b7ba-8b9ff8fa221d/Untitled4.png" alt="4">
대시보드 &gt; 필터 &gt; 측정값 선택
<img src="https://images.velog.io/images/sonhm-code/post/e50dcce9-32f9-48cb-ac46-a43c05dccbef/Untitled5.png" alt="5"></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Tableau] 별도범례를 이용하여 측정값 개별 비주얼라이제이션하기]]></title>
            <link>https://velog.io/@sonhm-code/Tableau-%EB%B3%84%EB%8F%84%EB%B2%94%EB%A1%80%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%98%EC%97%AC-%EC%B8%A1%EC%A0%95%EA%B0%92-%EA%B0%9C%EB%B3%84-%EB%B9%84%EC%A3%BC%EC%96%BC%EB%9D%BC%EC%9D%B4%EC%A0%9C%EC%9D%B4%EC%85%98%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@sonhm-code/Tableau-%EB%B3%84%EB%8F%84%EB%B2%94%EB%A1%80%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%98%EC%97%AC-%EC%B8%A1%EC%A0%95%EA%B0%92-%EA%B0%9C%EB%B3%84-%EB%B9%84%EC%A3%BC%EC%96%BC%EB%9D%BC%EC%9D%B4%EC%A0%9C%EC%9D%B4%EC%85%98%ED%95%98%EA%B8%B0</guid>
            <pubDate>Thu, 13 May 2021 11:56:27 GMT</pubDate>
            <description><![CDATA[<h2 id="별도범례">별도범례</h2>
<p>태블로와 같은 BI 툴은 산재되어 있는 데이터를 알기 쉽게 시각화하기 위해 쓴다.</p>
<p>따라서 범례 및 필터의 활용이 무척 중요하다.</p>
<p>하지만 측정값 필터링과 같이 가변 변수의 범례 적용을 하다보면 애로사항에 빠질 경우가 종종 있다.</p>
<p>전체 측정값에 색상범례를 일괄 지정하면, 특정 측정값만 색상 구분이 된다.
<img src="https://images.velog.io/images/sonhm-code/post/92377d1d-0441-4ebf-9e90-aea92a81ae6f/Untitled.png" alt="1"></p>
<h2 id="왜-이런-결과가-나올까">왜 이런 결과가 나올까?</h2>
<p>범례 측정값이 다음과 같이 정의됨.
<img src="https://images.velog.io/images/sonhm-code/post/510961b9-9465-4dd4-b124-a5c7d3ba5118/Untitled2.png" alt="2"></p>
<blockquote>
<p>측정값별로 집계 범위가 상이하다.
전환율은 0 ~ 100 사이에 있다. (예 : 전환율 78%) 
지출은 0 ~ 5,000,000원 사이에 있을 수 있다. (예 : 5,000,000원)</p>
</blockquote>
<p>이렇게 측정값별로 상일한 값의 범위를 하나의 범례로 묶는다면 범례는 다음과 같이 지정된다.</p>
<blockquote>
<p>전환율은 0 ~ 100 사이에 있다. (예 : 전환율 78%)
지출은 0 ~ 5,000,000원 사이에 있을 수 있다. (예 : 5,000,000원)
측정값 전체 범례 : 0  ~ 5,000,000</p>
</blockquote>
<p>이러한 경우, 100%의 전환을 한 레코드는 0 ~ 5,000,000의 측정값 전체 범례 내에서 나쁜 지표로 평가받게 된다.</p>
<p>이러한 오류를 해결하기 위해서, 측정값별로 다음과 같이 범례가 개별 구분되어야 한다.</p>
<blockquote>
<p>전환율 범례 : 0 ~ 100
지출 범례 : 0 ~ 5,000,000 </p>
</blockquote>
<h2 id="해결방법">해결방법</h2>
<p>측정값이 다음과 같이 분할되어 범례 표기된다.
<img src="https://images.velog.io/images/sonhm-code/post/4b645f90-e107-4951-995c-f3786ca2b781/Untitled3.png" alt="3">
전체 범례로 지정된 모습
<img src="https://images.velog.io/images/sonhm-code/post/fdce76a4-53cd-44b4-9fe0-a68a349061e8/Untitled4.png" alt="4">
별도의 범례로 지정된 모습
<img src="https://images.velog.io/images/sonhm-code/post/c1d4ca87-4d3c-424b-b820-6de8c530a249/Untitled5.png" alt="5"></p>
<blockquote>
<p>별도범례는 전체범례와 달리 색상 편집을 개별적으로 진행해주어야 한다.</p>
</blockquote>
<p>별도범례는 전체범례와 달리 색상 편집을 개별적으로 진행해주어야 한다.
측정값 별로 별도 범례, 별도의 데이터 시각화가 이루어진 모습</p>
<p><img src="https://images.velog.io/images/sonhm-code/post/dcf1f1aa-8eb4-451c-94ed-9c25e20f2c56/Untitled6.png" alt="6"></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Tableau] 계산된 필드를 활용하여 범례 편집하기]]></title>
            <link>https://velog.io/@sonhm-code/Tableau-%EA%B3%84%EC%82%B0%EB%90%9C-%ED%95%84%EB%93%9C%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%98%EC%97%AC-%EB%B2%94%EB%A1%80-%ED%8E%B8%EC%A7%91%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@sonhm-code/Tableau-%EA%B3%84%EC%82%B0%EB%90%9C-%ED%95%84%EB%93%9C%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%98%EC%97%AC-%EB%B2%94%EB%A1%80-%ED%8E%B8%EC%A7%91%ED%95%98%EA%B8%B0</guid>
            <pubDate>Thu, 13 May 2021 11:49:49 GMT</pubDate>
            <description><![CDATA[<h2 id="태블로-범례의-한계">태블로 범례의 한계</h2>
<p>태블로에서 색상 범례 활용 시, 다중 색상에서 가운데 색상을 지정할 수 없다. 태블로에서 자동으로 추출되는 가운데 색상환은 바로 흰색이다. (색상의 조합이 흰색으로 가능 빛의 색상환을 활용한 것으로 보임.) 이런 경우, 다음의 사례에서 문제가 생긴다.</p>
<p>가운데 색상은 태블로에서 임의 지정된다.
<img src="https://images.velog.io/images/sonhm-code/post/4eb7ec4e-673b-40b8-833b-29e972481d29/Untitled.png" alt="1">
양쪽 색상을 바꾸어도 가운데 색상은 보통 흰색으로 치환된다.
<img src="https://images.velog.io/images/sonhm-code/post/f379d811-234f-4474-8ce8-235f00524454/Untitled2.png" alt="2"></p>
<blockquote>
<p>지출 대비 광고 신청수를 의미하는 신청단가는 낮을수록 좋다.
하지만, 0 이하인 - 가 된다면 고저와 상관없이 효율이 없다고 판단해야 한다.
이런 경우, 신청단가에 따라 다음과 같이 가치 판단해야 한다.
예: - 10,000원 &lt; 30,000원 &lt;10,000원</p>
</blockquote>
<p>다음과 같은 상황에서 기존 색상범례를 활용한다면</p>
<ul>
<li>10,000원 &lt; 10,000원 &lt; 30,000원 혹은 해당 데이터의 역순으로 범례구분을 시킬 수 밖에 없다.</li>
</ul>
<p>사실상, 가장 좋지 않은 마이너스 (-) 지표가 가장 잘 보이는 형태로 도출되는 태블로의 색상범례
<img src="https://images.velog.io/images/sonhm-code/post/15606edb-3d73-4ea6-8410-8ebd0420d5e1/Untitled3.png" alt="3"></p>
<p>물론, 색상편집의 시작과 끝 값을 조정하여 마이너스(-)값을 다른 색상으로 표기할 수 도 있겠지만, 이런 경우에도 가장 중요한 지표인 10,000원 데이터가 흰색으로 표기되어, 올바른 시각화라고 볼 수 없게 된다.</p>
<h2 id="계산된-필드를-범례에-활용하기">계산된 필드를 범례에 활용하기</h2>
<p>이런 경우, 다음과 같이 계산된 필드를 범례로 활용할 수 있다.</p>
<pre><code class="language-r">IF [신청단가] &lt; 0 THEN &#39; ~ 0원&#39; 
ELSEIF [신청단가] &lt; 25000 THEN &#39;0원 ~ 25,000원&#39; 
ELSEIF [신청단가] &lt; 35000 THEN &#39;25,000원 ~ 35,000원&#39; 
ELSEIF [신청단가] &lt; 50000 THEN &#39;35,000원 ~ 50,000원&#39; 
ELSE &#39;50,000원 ~ &#39; 
END</code></pre>
<p>계산된 필드에서 신청단가를 기준으로 IF문을 활용하여 값별로 구분
<img src="https://images.velog.io/images/sonhm-code/post/7300c899-ef92-4ee7-8a97-c0d5de070ebd/Untitled4.png" alt="4"></p>
<p>새로 추가된 계산된 측정값 (필드)
<img src="https://images.velog.io/images/sonhm-code/post/24c25222-85d1-42fd-9af3-d78cd9a2a2c7/Untitled5.png" alt="5"></p>
<p>신청단가(범례)로 계산한 측정값을 색상 마크로 활용하였다.
<img src="https://images.velog.io/images/sonhm-code/post/ab2ac011-25f0-443b-b1cc-47877bd141cf/Untitled6.png" alt="6"></p>
<p>색상 편집에서 범례별로 색상을 지정
<img src="https://images.velog.io/images/sonhm-code/post/f3544687-25a3-4834-b802-ad02bf2a5f4c/Untitled7.png" alt="7"></p>
<p>마이너스 값은 붉은색 나머지 값은 파란색-청록색에서 선택
<img src="https://images.velog.io/images/sonhm-code/post/d9cd516d-f3df-4469-9fc8-e14701e77115/Untitled8.png" alt="8"></p>
<p>마이너스 값(-)을 기준으로 붉은색, 나머지는 최소값을 기준으로 높은 평가를 매겼다.
<img src="https://images.velog.io/images/sonhm-code/post/35392e85-6e70-41e4-9dfa-e275f676ad59/Untitled9.png" alt="9"></p>
<h2 id="계산된-필드를-범례로-활용할-때의-한계">계산된 필드를 범례로 활용할 때의 한계</h2>
<p>계산된 필드로 텍스트 범례를 만들어서 활용할 경우, 다음과 같은 한계점이 있으니, 참고한다.
개별 범례를 활용할 수 없음.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Tableau] 누적 선 그래프 구하기]]></title>
            <link>https://velog.io/@sonhm-code/Tableau-%EB%88%84%EC%A0%81-%EC%84%A0-%EA%B7%B8%EB%9E%98%ED%94%84-%EA%B5%AC%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@sonhm-code/Tableau-%EB%88%84%EC%A0%81-%EC%84%A0-%EA%B7%B8%EB%9E%98%ED%94%84-%EA%B5%AC%ED%95%98%EA%B8%B0</guid>
            <pubDate>Thu, 13 May 2021 11:42:44 GMT</pubDate>
            <description><![CDATA[<h2 id="runnig_sum">runnig_sum</h2>
<p>태블로 테이블에서 제공하는 함수로, 누적 합계를 구하는 산식이다.
<img src="https://images.velog.io/images/sonhm-code/post/e7908b6a-5bb1-492e-871c-81e4da6cee3d/Untitled%20(36).png" alt="수식">
Running_sum을 활용하여 도출한 누적 예약수의 집계.
<img src="https://images.velog.io/images/sonhm-code/post/df76a85b-c847-433f-8a40-99b339854a82/Untitled.png.png" alt="누적값"></p>
<h2 id="total">Total</h2>
<p>누적예약율은 파티션 총 예약수에서 레코드에 따른 누적예약수의 비율을 의미하므로, 토탈함수를 사용하여 계산한다.
TOTAL은 집계함수에만 사용이 가능하다.
<img src="https://images.velog.io/images/sonhm-code/post/355283ba-2179-48ff-88c7-c229d095b342/Untitled.png" alt="total의 사용">
TOTAL함수는 파티션 내 호출된 레코드의 합산 금액을 계산한다.
<img src="https://images.velog.io/images/sonhm-code/post/8d029893-112b-4a6b-82e1-fa8952877af8/Untitled2.png" alt="누적값"></p>
<h2 id="워크시트의-반영">워크시트의 반영</h2>
<p>대응시간별 누적예약율을 선형 그래프로 시각화한다.
<img src="https://images.velog.io/images/sonhm-code/post/29cff9dc-1a2f-4866-9594-e2eff9a961a5/Untitled3.png" alt="예시1">
측정값을 워크시트 내 우측에 드래그하면 이중 그래프를 만들 수 있다.
<img src="https://images.velog.io/images/sonhm-code/post/5444805b-6578-48f6-bd0b-0c56021f73b5/Untitled4.png" alt="예시2">
두 범례를 조정해서 만들어주면 누적값을 기반으로 한 누적 선 그래프를 만들 수 있다. 예약의 60%는 대응시간 8시간 이내에 완성이 된다.
<img src="https://images.velog.io/images/sonhm-code/post/53a487c3-417b-4284-a0e5-a57171cc920b/Untitled5.png" alt="예시3"></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Tableau] UNION을 통해 스키마 통합하기]]></title>
            <link>https://velog.io/@sonhm-code/Tableau-UNION%EC%9D%84-%ED%86%B5%ED%95%B4-%EC%8A%A4%ED%82%A4%EB%A7%88-%ED%86%B5%ED%95%A9%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@sonhm-code/Tableau-UNION%EC%9D%84-%ED%86%B5%ED%95%B4-%EC%8A%A4%ED%82%A4%EB%A7%88-%ED%86%B5%ED%95%A9%ED%95%98%EA%B8%B0</guid>
            <pubDate>Thu, 13 May 2021 04:45:21 GMT</pubDate>
            <description><![CDATA[<p>구글 스프레드 시트와 태블로를 활용하면, 린하게 BI 툴을 확보할 수 있다.
데이터 더미를 구글 스프레드 시트에서 관리하기 위해서는 다양한 시트에 분산처리 해야 한다. 분산된 구글 데이터를 태블로에서 통합하여 보려면 유니온 처리를 해야한다.</p>
<h2 id="union">Union</h2>
<p>당연한 이야기이지만, 여러 테이블의 데이터를 하나의 테이블에 병합하려면 다음의 제한 조건이 필요하다.</p>
<ol>
<li>동일한 칼럼명으로 설계되어 있어야 한다.</li>
<li>동일한 데이터타입 이어야 한다. (str, int..)</li>
<li>동일한 제약조건이어야 한다. (not null)</li>
</ol>
<h2 id="프로세스">프로세스</h2>
<h3 id="빠른-연산을-위해-시트에서는-분산-처리">빠른 연산을 위해 시트에서는 분산 처리</h3>
<p>광고대행업의 경우, 파트너별로 광고운용 매체별로 데이터 더미가 크다. 이런 데이터 더미는 시트별로 분산 적재하는게 용이하다.</p>
<p><img src="https://images.velog.io/images/sonhm-code/post/7cd3ae17-3e44-4f6c-b0cf-362bd1d03f27/image.png" alt="파트너코드별 분산처리1"></p>
<p>A-1 파트너코드로 시트별로 분산처리되어 관리됨.
<img src="https://images.velog.io/images/sonhm-code/post/438a5075-fb26-4859-a7e6-577721ca3167/image.png" alt="파트너코드별 분산처리2"></p>
<h3 id="태블로에서-유니온">태블로에서 유니온</h3>
<p>태블로에서 제공하는 Union기능은 다음과 같다.
<img src="https://images.velog.io/images/sonhm-code/post/d8fc622a-23bd-447b-8c81-22c73d86d872/image.png" alt="태블로 유니온 기능">
어떤 조인을 취할지 정하면 유니언된 정보를 바탕으로 데이터가 통합된다.
<img src="https://images.velog.io/images/sonhm-code/post/169499eb-121f-4805-b221-d7eb98249b1f/1.JPG" alt="태블로 조인1">
조인된 모습
<img src="https://images.velog.io/images/sonhm-code/post/c4dc24bb-f055-47d8-896e-3edf61219e53/image.png" alt="태블로 조인2"></p>
<hr>
<h3 id="참고자료">참고자료</h3>
<p><a href="https://help.tableau.com/current/pro/desktop/ko-kr/union.htm">태블로 공식문서 : 데이터 유니온</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[
[함께하는 민대리 / 2017-2018] 함께하는FTA]]></title>
            <link>https://velog.io/@sonhm-code/%ED%95%A8%EA%BB%98%ED%95%98%EB%8A%94-%EB%AF%BC%EB%8C%80%EB%A6%AC-2017-2018-%ED%95%A8%EA%BB%98%ED%95%98%EB%8A%94FTA</link>
            <guid>https://velog.io/@sonhm-code/%ED%95%A8%EA%BB%98%ED%95%98%EB%8A%94-%EB%AF%BC%EB%8C%80%EB%A6%AC-2017-2018-%ED%95%A8%EA%BB%98%ED%95%98%EB%8A%94FTA</guid>
            <pubDate>Thu, 13 May 2021 03:51:44 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/sonhm-code/post/5668341a-8f35-4dce-889b-5918e7919d37/201812_C.png" alt="기고 잡지"></p>
<blockquote>
<p>처녀작이 2년을 함께 할 줄 몰랐네요. 그저 감사합니다.</p>
</blockquote>
<p>2017년부터 2년간 작업을 해온 &quot;함께하는 민대리&quot;이다. 정부기간지 작업은 주로 말하는 바가 명확하고, 설명해야 하는 지점이 많다는 특성이 있는데. 이를 쉽고 재미있게 표현하기 위해 그간 많은 공부를 해왔던 것 같다. 지면 특성 상, 과감한 컨셉보다 타깃층이 함께 공감할 수 있을만한 내용을 바탕으로 스토리를 풀어가고자 했는데. 결국, 30대와 40대 중년 직장인인 민대리와 오과장, 그리고 양과장이 그렇게 그려지게 되었다. 일상 속 에피소드를 바탕으로 국내 FTA정세를 표현하려고 했던 컨셉이었기에, 매번 공부하고 고민하는 작업의 반복이었다. FTA의 약자도 잘 모르고 시작했었는데 이제는 어느덧 무역용어도 꽤나 익숙해다.</p>
<p><img src="https://images.velog.io/images/sonhm-code/post/f185afc7-ccad-41e4-894d-15e33aad0185/%ED%95%A8%EA%BB%98%ED%95%98%EB%8A%94_%EB%AF%BC%EB%8C%80%EB%A6%AC-12%EC%9B%94_10%ED%99%94.jpg" alt="10화"></p>
<p>처녀작으로써, 부족한 점도 많았을텐데 2년이란 시간동안 감사하게도 연재할 수 있게 해준 관계자분들께 감사하다. 애틋하고 고마운 작품의 갈무리를 포트폴리오에 남긴다.</p>
<p><img src="https://images.velog.io/images/sonhm-code/post/294a634e-47c5-4688-929e-bc1ef5db60c1/%ED%95%A8%EA%BB%98%ED%95%98%EB%8A%94_%EB%AF%BC%EB%8C%80%EB%A6%AC_10%EC%9B%94_8%ED%99%94-B%EC%95%88.jpg" alt="8화"></p>
<p><img src="https://images.velog.io/images/sonhm-code/post/3a9d3c21-501f-4492-ab13-d5a210ade474/11%EC%9B%94_9%ED%99%94.jpg" alt="9화"></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[제1회 축산물 웹툰 공모전/2018] 아는만큼 보이는 맛-한식대첩편]]></title>
            <link>https://velog.io/@sonhm-code/%EC%A0%9C1%ED%9A%8C-%EC%B6%95%EC%82%B0%EB%AC%BC-%EC%9B%B9%ED%88%B0-%EA%B3%B5%EB%AA%A8%EC%A0%842018-%EC%95%84%EB%8A%94%EB%A7%8C%ED%81%BC-%EB%B3%B4%EC%9D%B4%EB%8A%94-%EB%A7%9B-%ED%95%9C%EC%8B%9D%EB%8C%80%EC%B2%A9%ED%8E%B8</link>
            <guid>https://velog.io/@sonhm-code/%EC%A0%9C1%ED%9A%8C-%EC%B6%95%EC%82%B0%EB%AC%BC-%EC%9B%B9%ED%88%B0-%EA%B3%B5%EB%AA%A8%EC%A0%842018-%EC%95%84%EB%8A%94%EB%A7%8C%ED%81%BC-%EB%B3%B4%EC%9D%B4%EB%8A%94-%EB%A7%9B-%ED%95%9C%EC%8B%9D%EB%8C%80%EC%B2%A9%ED%8E%B8</guid>
            <pubDate>Thu, 13 May 2021 03:47:59 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/sonhm-code/post/8334c72b-b75d-46f6-a4f9-cc1c2f81853b/1.jpg" alt="공고"></p>
<blockquote>
<p>제한된 컷수에서 빠르게 환경설정을 하는 방법</p>
</blockquote>
<p>제한된 양식에서 작화를 할 때, 가장 쉽게 빠지게 되는 오류는 바로 배경 설정에 있다. 초창기 작화 시점엔 특히 배경 설정에 애를 먹곤 했는데, 예를 들면 다음과 같다. 12컷 작화를 그려야 하는데 등장인물과 배경설명에만 4컷 이상을 할애하는 경우, 힘을 주어야하는 내용에 힘이 실리지 못하고, 기승전결이 급하게 마무리되는 결과를 낳곤한다.</p>
<p>때문에 만화의 첫컷은 매우 중요하다고 볼 수 있다. 잘 짜여진 첫컷은 제한된 지면의 수를 절약할 수 있고, 빠른 몰입을 돕기때문이다. 이러한 측면에서 첫컷은 작품콘티의 방점이라고 볼 수 있으며, 고도의 훈련이 필요한 작업이라고 생각이 든다. 앞으로 다양한 작화를 통해 첫컷에 대한 감각을 익히는 연습을 해나아갈 예정이다. </p>
<p><img src="https://images.velog.io/images/sonhm-code/post/cf280ed8-1fca-4efa-bfbd-e032d2174604/2.jpg" alt="출품내용"></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[제3회 해양콘텐츠 웹툰 공모전 최우수상/2018] 예원이와 바다]]></title>
            <link>https://velog.io/@sonhm-code/%EC%A0%9C3%ED%9A%8C-%ED%95%B4%EC%96%91%EC%BD%98%ED%85%90%EC%B8%A0-%EC%9B%B9%ED%88%B0-%EA%B3%B5%EB%AA%A8%EC%A0%84-%EC%B5%9C%EC%9A%B0%EC%88%98%EC%83%812018-%EC%98%88%EC%9B%90%EC%9D%B4%EC%99%80-%EB%B0%94%EB%8B%A4</link>
            <guid>https://velog.io/@sonhm-code/%EC%A0%9C3%ED%9A%8C-%ED%95%B4%EC%96%91%EC%BD%98%ED%85%90%EC%B8%A0-%EC%9B%B9%ED%88%B0-%EA%B3%B5%EB%AA%A8%EC%A0%84-%EC%B5%9C%EC%9A%B0%EC%88%98%EC%83%812018-%EC%98%88%EC%9B%90%EC%9D%B4%EC%99%80-%EB%B0%94%EB%8B%A4</guid>
            <pubDate>Thu, 13 May 2021 03:45:05 GMT</pubDate>
            <description><![CDATA[<p><img src="https://images.velog.io/images/sonhm-code/post/ca0bb1a0-e251-4c3b-8e91-baf01378577b/intro.jpg" alt="공지"></p>
<blockquote>
<p>작품에서 조카의 그림은 가장 중요한 소재입니다. 
당장 공감하기 어려운 소재일수록 순수한 소재의 활용이 중요하다고 생각했습니다.</p>
</blockquote>
<p>컷수 제한이 있는 공모전 작화의 경우, 짜임새 있게 콘티를 작성하는 일이 가장 중요하다고 생각한다. 해당 작화의 경우, ①해양생물의 이야기 ②해양생물 보전인식을 15컷 안에 담아야 했다. 제한된 컷 수 안에서 공감과 재미를 얻기 위해, 최적의 소재를 찾는 일에 가장 많은 시간을 기울였다.</p>
<p>제가 찾은 소재는 바로, 조카의 바다그림이었다. 동심이 서려있는 그림의 형태감은 해양생물을 역동적으로 표현하기 용이한 오브제였다고 생각한다. 또한, 어린아이의 순수한 걱정거리는 해양보전의 필요성에 대해 많은 이들의 공감을 얻기에 꽤나 유용한 소재였다고 판단된다. 해당 작화를 통해 제한된 컷수 안에서 적합한 오브제를 찾는 일이 무엇보다 중요하다는 사실을 배울 수 있었고, 공감을 유도하는 내용에서 순수한 소재의 활용이 큰 효과를 발휘한다는 가정을 세울 수 있었다.</p>
<p><img src="https://images.velog.io/images/sonhm-code/post/560ce54b-fe8a-4a4b-bc3a-ff6320f17593/%EC%86%90%ED%98%95%EB%AF%BC-%EC%98%88%EC%9B%90%EC%9D%B4%EC%9D%98_%EB%B0%94%EB%8B%A4.jpg" alt="출품내용"></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Apps Script] getValue로 값 읽기]]></title>
            <link>https://velog.io/@sonhm-code/Apps-Script-getValue%EB%A1%9C-%EA%B0%92-%EC%9D%BD%EA%B8%B0</link>
            <guid>https://velog.io/@sonhm-code/Apps-Script-getValue%EB%A1%9C-%EA%B0%92-%EC%9D%BD%EA%B8%B0</guid>
            <pubDate>Wed, 12 May 2021 07:08:33 GMT</pubDate>
            <description><![CDATA[<p>앱스스크립트는 자바스크립트 기반의 구글 시트 언어이다. 엑셀의 VBA와 같다. getValue를 이용하면 시트간 값을 부하없이 복사해올 수 있다. 앱스스크립트는 시트의 활용성을 극해화하기 위해 만들어진 언어이므로 활용 범위가 높아지면 높아질수록 시트의 생산성은 크게 증가한다. 잘 만들어진 시트 시스템은 적은 규모의 데이터 더미 정도는 쉽게 분석할 수 있으며, 며칠 안에 린하게 구축할 수 있다는 장점 또한 있다.</p>
<h2 id="결과">결과</h2>
<p>앱스스크립트를 잘 활용해도 시트 내에서 광고운영사 차원의 더미데이터를 다차원으로 분석할 수 있게 된다.
<img src="https://images.velog.io/images/sonhm-code/post/8b337bc8-62d4-4095-a152-208c6b1e4240/%EA%B5%AC%EA%B8%80%EC%8B%9C%ED%8A%B8.gif" alt="데이터분석 대시보드"></p>
<p>로그 확인을 통해 이슈를 수정할 수 있다.
<img src="https://images.velog.io/images/sonhm-code/post/dcff9394-fc99-44e3-853b-7a5cbf74645e/Untitled%20(3).png" alt="로그 화면"></p>
<h2 id="코드">코드</h2>
<pre><code class="language-javascript">function learnBasics() {

  var app = SpreadsheetApp;
  var ss = app.getActiveSpreadsheet();
  var activeSheet = ss.getActiveSheet();


  var temptText = activeSheet.getRange(4,1).getValue(); //활성 시트의 A4셀 값을 변수명 temptText에 가져온다.
  activeSheet.getRange(6,2).setValue(temptText); //temptText에 가져온 값을 B6셀에 붙혀넣는다.

}</code></pre>
<pre><code class="language-javascript">function myFunction() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheets()[0]; // Passing only two arguments returns a &quot;range&quot; with a single cell.
  var range = sheet.getRange(1, 1);
  var values = range.getValues();
  Logger.log(values[0][0]);
}</code></pre>
<hr>
<h3 id="참고자료">참고자료</h3>
<p><a href="https://developers.google.com/apps-script/reference/spreadsheet/sheet">apps script 공식문서 : class</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Apps Script] 시트id값을 활용하여 시트 내용 카피하기]]></title>
            <link>https://velog.io/@sonhm-code/Apps-Script-%EC%8B%9C%ED%8A%B8id%EA%B0%92%EC%9D%84-%ED%99%9C%EC%9A%A9%ED%95%98%EC%97%AC-%EC%8B%9C%ED%8A%B8-%EB%82%B4%EC%9A%A9-%EC%B9%B4%ED%94%BC%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@sonhm-code/Apps-Script-%EC%8B%9C%ED%8A%B8id%EA%B0%92%EC%9D%84-%ED%99%9C%EC%9A%A9%ED%95%98%EC%97%AC-%EC%8B%9C%ED%8A%B8-%EB%82%B4%EC%9A%A9-%EC%B9%B4%ED%94%BC%ED%95%98%EA%B8%B0</guid>
            <pubDate>Wed, 12 May 2021 06:23:43 GMT</pubDate>
            <description><![CDATA[<p>구글 스프레드 시트에서도 id값을 이용하면, 관계형 데이터 베이스처럼 활용할 수 있다. 보통 importrange 수식을 활용해서 구축하지만, copyto를 활용하면 복사한 값 자체가 동기화하여 시트의 부하를 줄일 수 있게 된다.</p>
<h2 id="결과">결과</h2>
<p>변경 전
<img src="https://images.velog.io/images/sonhm-code/post/4d42e3f8-c11c-443c-84e4-03c00a9be96d/Untitled%20(1).png" alt="변경 전">
변경 후
<img src="https://images.velog.io/images/sonhm-code/post/68fb3f80-ce47-442e-bb66-6edc15adbf65/Untitled.png" alt="변경 후"></p>
<h2 id="코드">코드</h2>
<pre><code class="language-javascript">function LearnBasics() {
  var source = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = source.getSheets()[1]; //2번째 탭을 복사할 시트로 지정
  var destination = SpreadsheetApp.openById(&#39;18surAZTrk4jTYb__pHCR3Gtgm3MtNOa5_6CR2g9PAes&#39;);
  sheet.copyTo(destination); //destination 변수에 복사할 시트를 copy &amp; paste
}</code></pre>
<h2 id="구글-문서의-id-값-찾는-방법">구글 문서의 id 값 찾는 방법</h2>
<p>Opens the spreadsheet with the given ID. A spreadsheet ID can be extracted from its URL. For example, the spreadsheet ID in the URL <a href="https://docs.google.com/spreadsheets/d/abc1234567/edit#gid=0">https://docs.google.com/spreadsheets/d/abc1234567/edit#gid=0</a> is &quot;abc1234567&quot;.</p>
<p><img src="https://images.velog.io/images/sonhm-code/post/10ebc2dc-a8ff-427c-b774-8d466ab6ddc7/Untitled%20(2).png" alt="시트 id 확인 방법">
구글스프레드시트의 id값을 파악하는 방법 : d/부터 다음 /까지가 구글스프레드 시트의 id값이다.</p>
<pre><code class="language-javascript">// The code below opens a spreadsheet using its ID and logs the name for it.
// Note that the spreadsheet is NOT physically opened on the client side.
// It is opened on the server only (for modification by the script).
var ss = SpreadsheetApp.openById(&quot;abc1234567&quot;);
Logger.log(ss.getName());</code></pre>
<hr>
<h3 id="참고자료">참고자료</h3>
<p><a href="https://developers.google.com/apps-script/reference/spreadsheet/spreadsheet-app">apps script 공식문서</a></p>
]]></description>
        </item>
    </channel>
</rss>