<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>truly_flower</title>
        <link>https://velog.io/</link>
        <description>개발자를 꿈꾸는..</description>
        <lastBuildDate>Mon, 15 Jul 2024 17:33:43 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>truly_flower</title>
            <url>https://velog.velcdn.com/images/truly_flower/profile/843db9f5-2973-470c-ab8d-4b7435e1c657/image.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. truly_flower. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/truly_flower" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[기상청 정보 가져오기]]></title>
            <link>https://velog.io/@truly_flower/%EA%B8%B0%EC%83%81%EC%B2%AD-%EC%A0%95%EB%B3%B4-%EA%B0%80%EC%A0%B8%EC%98%A4%EA%B8%B0</link>
            <guid>https://velog.io/@truly_flower/%EA%B8%B0%EC%83%81%EC%B2%AD-%EC%A0%95%EB%B3%B4-%EA%B0%80%EC%A0%B8%EC%98%A4%EA%B8%B0</guid>
            <pubDate>Mon, 15 Jul 2024 17:33:43 GMT</pubDate>
            <description><![CDATA[<p><a href="https://docs.google.com/spreadsheets/d/1VMWI4pDMg0KlAKEx2lwF9Rux8Z7VOBEA/edit?usp=sharing&amp;ouid=100662855295101405651&amp;rtpof=true&amp;sd=true">격자x, 격자 y 관련 파일 </a>
위도경도를 격자x,y로 바꾸는 방법이 따로 있음 (여기에 언급하지는 않음)</p>
<ul>
<li>API키를 받을때는 인코딩된 키를 써야한다~
<img src="https://velog.velcdn.com/images/truly_flower/post/78f29b9a-7805-4a78-8ec3-107a3223c11f/image.png" alt=""></li>
</ul>
<h2 id="1-단기-예보-조회서비스">1. 단기 예보 조회서비스</h2>
<h3 id="getultrasrtncst----초단기실황조회-아래-항목명을-로-이어서-써주면-됨">getUltraSrtNcst    초단기실황조회 (아래 항목명을 &amp;로 이어서 써주면 됨)</h3>
<p><img src="https://velog.velcdn.com/images/truly_flower/post/4a804ceb-6382-41ec-9c3d-d16beb674e4b/image.png" alt=""></p>
<blockquote>
<p>예시 url</p>
<pre><code class="language-py">http://apis.data.go.kr/1360000/VilageFcstInfoService_2.0/
getUltraSrtNcst?
serviceKey=인증키&amp;numOfRows=한페이지에 몇열 보여줄건지&amp;pageNo=1&amp;dataType=json
&amp;base_date=00000000&amp;base_time=0600&amp;nx=격자x&amp;ny=격자y (위도 경도 아님.)</code></pre>
</blockquote>
<blockquote>
<p>예시 데이터</p>
<pre><code class="language-html">{
  &quot;response&quot;: {
    &quot;header&quot;: {
      &quot;resultCode&quot;: &quot;00&quot;,
      &quot;resultMsg&quot;: &quot;NORMAL_SERVICE&quot;
    },
    &quot;body&quot;: {
      &quot;dataType&quot;: &quot;JSON&quot;,
      &quot;items&quot;: {
        &quot;item&quot;: [
          {
            &quot;baseDate&quot;: &quot;20240715&quot;,
            &quot;baseTime&quot;: &quot;0600&quot;,
            &quot;category&quot;: &quot;PTY&quot;,
            &quot;nx&quot;: 60,
            &quot;ny&quot;: 127,
            &quot;obsrValue&quot;: &quot;0&quot;
          },
          {
            &quot;baseDate&quot;: &quot;20240715&quot;,
            &quot;baseTime&quot;: &quot;0600&quot;,
            &quot;category&quot;: &quot;REH&quot;,
            &quot;nx&quot;: 60,
            &quot;ny&quot;: 127,
            &quot;obsrValue&quot;: &quot;71&quot;
          },
          {
            &quot;baseDate&quot;: &quot;20240715&quot;,
            &quot;baseTime&quot;: &quot;0600&quot;,
            &quot;category&quot;: &quot;RN1&quot;,
            &quot;nx&quot;: 60,
            &quot;ny&quot;: 127,
            &quot;obsrValue&quot;: &quot;0&quot;
          },
          {
            &quot;baseDate&quot;: &quot;20240715&quot;,
            &quot;baseTime&quot;: &quot;0600&quot;,
            &quot;category&quot;: &quot;T1H&quot;,
            &quot;nx&quot;: 60,
            &quot;ny&quot;: 127,
            &quot;obsrValue&quot;: &quot;25&quot;
          },
          {
            &quot;baseDate&quot;: &quot;20240715&quot;,
            &quot;baseTime&quot;: &quot;0600&quot;,
            &quot;category&quot;: &quot;UUU&quot;,
            &quot;nx&quot;: 60,
            &quot;ny&quot;: 127,
            &quot;obsrValue&quot;: &quot;-2.4&quot;
          },
          {
            &quot;baseDate&quot;: &quot;20240715&quot;,
            &quot;baseTime&quot;: &quot;0600&quot;,
            &quot;category&quot;: &quot;VEC&quot;,
            &quot;nx&quot;: 60,
            &quot;ny&quot;: 127,
            &quot;obsrValue&quot;: &quot;70&quot;
          },
          {
            &quot;baseDate&quot;: &quot;20240715&quot;,
            &quot;baseTime&quot;: &quot;0600&quot;,
            &quot;category&quot;: &quot;VVV&quot;,
            &quot;nx&quot;: 60,
            &quot;ny&quot;: 127,
            &quot;obsrValue&quot;: &quot;-0.8&quot;
          },
          {
            &quot;baseDate&quot;: &quot;20240715&quot;,
            &quot;baseTime&quot;: &quot;0600&quot;,
            &quot;category&quot;: &quot;WSD&quot;,
            &quot;nx&quot;: 60,
            &quot;ny&quot;: 127,
            &quot;obsrValue&quot;: &quot;2.7&quot;
          }
        ]
      },
      &quot;pageNo&quot;: 1,
      &quot;numOfRows&quot;: 30,
      &quot;totalCount&quot;: 8
    }
  }
}</code></pre>
</blockquote>
<p><img src="https://velog.velcdn.com/images/truly_flower/post/b17a0829-dd29-4a8f-a454-e572a79fac10/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/truly_flower/post/256a74de-1d3e-48fe-8d19-1572585a399d/image.png" alt=""></p>
<h3 id="getultrasrtfcst----초단기예보조회">getUltraSrtFcst    초단기예보조회</h3>
<p><img src="https://velog.velcdn.com/images/truly_flower/post/8f300db6-cebc-44e8-9c2f-5ba72ff6845e/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/truly_flower/post/7f0365de-8b20-41d2-a669-314ad6a7420c/image.png" alt=""></p>
<h3 id="getvilagefcst----단기예보조회">getVilageFcst    단기예보조회</h3>
<p><img src="https://velog.velcdn.com/images/truly_flower/post/bc7552c4-97dc-4f6b-a4f3-9b14b8841cdb/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/truly_flower/post/d7e8a0b4-2e53-4dbf-976a-aa42ebe61eba/image.png" alt=""></p>
<h3 id="getfcstversion----예보버전조회">getFcstVersion    예보버전조회</h3>
]]></description>
        </item>
        <item>
            <title><![CDATA[중요한 DAG 파라미터 VS Task 파라미터]]></title>
            <link>https://velog.io/@truly_flower/%EC%A4%91%EC%9A%94%ED%95%9C-DAG-%ED%8C%8C%EB%9D%BC%EB%AF%B8%ED%84%B0-VS-Task-%ED%8C%8C%EB%9D%BC%EB%AF%B8%ED%84%B0</link>
            <guid>https://velog.io/@truly_flower/%EC%A4%91%EC%9A%94%ED%95%9C-DAG-%ED%8C%8C%EB%9D%BC%EB%AF%B8%ED%84%B0-VS-Task-%ED%8C%8C%EB%9D%BC%EB%AF%B8%ED%84%B0</guid>
            <pubDate>Mon, 17 Jun 2024 02:54:20 GMT</pubDate>
            <description><![CDATA[<h4 id="max-active-runs">max active runs</h4>
<p>백필할떄 중요.
만약 이전 데이터에 문제가 생겨서 1년치의 데이터를 백필해야된다
근데 만약 이게 1로 설정되어있다면 한번에 1개의 dag만 돌아가서
매우 오래걸림
but 한번에 30개로 해놓으면 훨씬 금방됨</p>
<h4 id="max-active-tasks">max active tasks</h4>
<p><code>~~~ &gt;&gt; ~~~ &gt;&gt; ~~~&gt;&gt;</code>
이런식으로 되어있으면 어차피 하나 실행되고 다음 태스크 실행되고 하니까 상관없음
근데 만약 동시에 실행되는 태스크가 있다면 설정해 주는 파라미터</p>
<p>full refresh vs incremental update</p>
<p>full refresh : 백필 상관없음. 왜냐하면 할때마다 다 다시불러오기 때문
incremental update : 반대</p>
<hr>
<p>catch up 참고
<a href="https://magpienote.tistory.com/236">https://magpienote.tistory.com/236</a></p>
<hr>
<p>autocommit 참고
<a href="https://velog.io/@seovalue/autocommit%EC%9D%B4-%EB%8F%84%EB%8C%80%EC%B2%B4-%EB%AD%94%EB%8D%B0">https://velog.io/@seovalue/autocommit%EC%9D%B4-%EB%8F%84%EB%8C%80%EC%B2%B4-%EB%AD%94%EB%8D%B0</a></p>
<hr>
<p><img src="https://velog.velcdn.com/images/truly_flower/post/1a1b473c-687e-4477-b984-fda42121b58d/image.png" alt=""></p>
<p>비긴 ~ 커밋 사이에 에러가 발생하면 try except 구문이므로 except로 가서 에러를 출력한 뒤, 롤백 (비긴 전 상태) 해주는 코드 = 데이터 정합성 보장</p>
<p><a href="https://stricky.tistory.com/133">https://stricky.tistory.com/133</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[맥북 삼성 프린터 연결]]></title>
            <link>https://velog.io/@truly_flower/%EB%A7%A5%EB%B6%81-%EC%82%BC%EC%84%B1-%ED%94%84%EB%A6%B0%ED%84%B0-%EC%97%B0%EA%B2%B0</link>
            <guid>https://velog.io/@truly_flower/%EB%A7%A5%EB%B6%81-%EC%82%BC%EC%84%B1-%ED%94%84%EB%A6%B0%ED%84%B0-%EC%97%B0%EA%B2%B0</guid>
            <pubDate>Mon, 17 Jun 2024 02:50:40 GMT</pubDate>
            <description><![CDATA[<p><a href="https://support.apple.com/ko-kr/106385">https://support.apple.com/ko-kr/106385</a>
여기서 HP드라이버 다운로드</p>
<p>프린터 추가 누르기</p>
<p><a href="https://m.blog.naver.com/bgfkjy1000/221990103554">https://m.blog.naver.com/bgfkjy1000/221990103554</a></p>
<p>이분 블로그에 나온대로 하면됨</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[도커 이미지 생성]]></title>
            <link>https://velog.io/@truly_flower/%EB%8F%84%EC%BB%A4-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EC%83%9D%EC%84%B1</link>
            <guid>https://velog.io/@truly_flower/%EB%8F%84%EC%BB%A4-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EC%83%9D%EC%84%B1</guid>
            <pubDate>Mon, 03 Jun 2024 08:42:31 GMT</pubDate>
            <description><![CDATA[<p>도커 이미지 생성하는 법
docker build -t tag
이렇게 이름 정해서 생성 가능</p>
<p>docker image의 구성요소
from - 기본 os, 환경
run - 설치
환경설정변수 - env, arg
이 이미지의 버전이 뭐고 작성자가 누군지,,,등등 메타 데이터
docker image ls로 볼 수 이씀</p>
<p>docker image를 registry 에서 다운받는다 = docker pull
내가 업로드 = doker push
(깃헙이랑 비슷)</p>
<p>docker hub.com에 회원가입 하기!
여기에 ~~리포지토리 만들고, 그 밑에 이미지를 저장하는 것.</p>
<p>사람들이 많이 사용하는 소프트웨어는 official image가 있음.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[도커]]></title>
            <link>https://velog.io/@truly_flower/%EB%8F%84%EC%BB%A4</link>
            <guid>https://velog.io/@truly_flower/%EB%8F%84%EC%BB%A4</guid>
            <pubDate>Mon, 03 Jun 2024 08:08:38 GMT</pubDate>
            <description><![CDATA[<h4 id="내-컴퓨터-환경을-그대로-패키징해서-다른-이에게-줄-수-있다면">내 컴퓨터 환경을 그대로 패키징해서 다른 이에게 줄 수 있다면?</h4>
<p>도커의 목표 : 소프트웨어를 일관되게 빌드하고 실행하고 배포</p>
<p>Docker Image : 이렇게 독립적으로 완전하게 만들어진 패키지
Docker Container : 이 도커 이미지를 독립된 환경에서 실행한 것
도커 이미지를 빌드한다고 많이 얘기함
<img src="https://velog.velcdn.com/images/truly_flower/post/34274801-090e-4c10-8a7c-c4b1564a0496/image.png" alt="">
보통 도커 레지스트리에 도커 이미지를 올려서 다른사람들이 그걸 다운받아서 씀</p>
<p>VM보다는 light weight함.
VM은 각각의 Operating System을 갖고 있기 때문
ex) EC2
<img src="https://velog.velcdn.com/images/truly_flower/post/8a54fe43-b71a-4027-bd9f-0f9aefd78ec0/image.png" alt="">
<img src="https://velog.velcdn.com/images/truly_flower/post/49179480-c3cb-4578-a256-25999a90f968/image.png" alt="">
도커가 나온이후로 VM사용이 많이 줄었음</p>
<p>리눅스 기반은 다 돌아감
<img src="https://velog.velcdn.com/images/truly_flower/post/47dca9cc-5cee-45fb-96a7-2470a7528536/image.png" alt="">
컨테이너의 장단점
<img src="https://velog.velcdn.com/images/truly_flower/post/4994eb36-842a-4902-b6e7-fca684649bf4/image.png" alt=""></p>
<p>많은 수의 도커 컨테이너를 관리하는것이 쿠버네티스</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[에어플로 오퍼레이터]]></title>
            <link>https://velog.io/@truly_flower/%EC%97%90%EC%96%B4%ED%94%8C%EB%A1%9C-%EC%98%A4%ED%8D%BC%EB%A0%88%EC%9D%B4%ED%84%B0</link>
            <guid>https://velog.io/@truly_flower/%EC%97%90%EC%96%B4%ED%94%8C%EB%A1%9C-%EC%98%A4%ED%8D%BC%EB%A0%88%EC%9D%B4%ED%84%B0</guid>
            <pubDate>Mon, 03 Jun 2024 07:55:49 GMT</pubDate>
            <description><![CDATA[<p>AirFlow에서 Task
DAG을 구성하는 작업 단위를 Task라고 하며, DAG이 수행할 작업들을 의미한다.
하나 또는 여러 개의 Task를 연결해서 DAG을 생성하며, Task에는 Operator, Sensor, Hook이 있다.</p>
<p>Task는 Bash, Python을 포함해서 다양한 작업을 수행할 수 있다.
<a href="https://airflow.apache.org/docs/apache-airflow/2.2.3/operators-and-hooks-ref.html">이 사이트</a>를 참고한다.</p>
<p>또한 잘 알려진 서비스나 오픈소스 백엔드에 대한 작업을 수행할 수 있도록 다양한 Providers Package를 제공한다.
<a href="https://airflow.apache.org/docs/apache-airflow-providers/index.html">이 사이트</a>를 참고한다.</p>
<p>Providers Package의 경우 pip를 사용해서 설치 가능하다.
<a href="https://airflow.apache.org/docs/apache-airflow-providers/installing-from-pypi.html">이 기술 문서</a>를 참고한다.</p>
<p>Operator
Operator는 task를 어떻게 실행시킬지를 나타낸다.
하나의 워크플로우 안에서 하나의 테스크를 나타낸다.
Sensor와 Hook도 있지만 일반적으로 Operator를 대부분 사용한다.</p>
<p>Operator는 Action Operator와 Transfer Operator로 구분된다.
Action Operator는 작업을 수행하거나 다른 시스템에 작업을 수행하도록 지시한다.
Transfer Operator는 특정 시스템에서 다른 시스템으로 데이터를 이동시킨다.</p>
<p>AirFlow에서 제공하는 기본 Operator의 종류는 Bash와 Python을 포함해서 상당히 많다.</p>
<pre><code>Submodules
airflow.operators.bash
airflow.operators.bash_operator
airflow.operators.branch
airflow.operators.branch_operator
airflow.operators.check_operator
airflow.operators.dagrun_operator
airflow.operators.datetime
airflow.operators.docker_operator
airflow.operators.druid_check_operator
airflow.operators.dummy
airflow.operators.dummy_operator
airflow.operators.email
airflow.operators.email_operator
airflow.operators.gcs_to_s3
airflow.operators.generic_transfer
airflow.operators.google_api_to_s3_transfer
airflow.operators.hive_operator
airflow.operators.hive_stats_operator
airflow.operators.hive_to_druid
airflow.operators.hive_to_mysql
airflow.operators.hive_to_samba_operator
airflow.operators.http_operator
airflow.operators.jdbc_operator
airflow.operators.latest_only
airflow.operators.latest_only_operator
airflow.operators.mssql_operator
airflow.operators.mssql_to_hive
airflow.operators.mysql_operator
airflow.operators.mysql_to_hive
airflow.operators.oracle_operator
airflow.operators.papermill_operator
airflow.operators.pig_operator
airflow.operators.postgres_operator
airflow.operators.presto_check_operator
airflow.operators.presto_to_mysql
airflow.operators.python
airflow.operators.python_operator
airflow.operators.redshift_to_s3_operator
airflow.operators.s3_file_transform_operator
airflow.operators.s3_to_hive_operator
airflow.operators.s3_to_redshift_operator
airflow.operators.slack_operator
airflow.operators.sql
airflow.operators.sql_branch_operator
airflow.operators.sqlite_operator
airflow.operators.subdag
airflow.operators.subdag_operator
airflow.operators.trigger_dagrun
airflow.operators.weekday</code></pre><p>참고로 _operator로 끝나는 Operator들은 대부분 Defrecated 되었다.
대신 이름에서 _operator를 제외한 Operator를 사용하면 된다.</p>
<p>Operator에 공통적으로 <strong>kwargs</strong>라는 Keyword Arguments 를 전달하는 부분이 있다.
해당 부분은 DAG을 정의할 때 정의했던 default_args가 전달된다고 이해하면 된다.</p>
<p>자세한 내용은 아래 포스팅을 참고한다.</p>
<p>managed airflow </p>
<ul>
<li>MWAA : aws가 관리해줄게- 관리비쌈 : 한달 50만원</li>
<li>GCP - 구글이 관리해줄게</li>
</ul>
<p>데이터 인프라
RDS - raw data: 데이터레이크 - 복제 - 가공 - 데이터웨어하우스에 저장 - 레드시프트
airflow 를 이용해 db를 클론하고
스파크를 통해 production DB의 데이터를 DL로 복제한다
production db는 S3</p>
<p>airflow를 써보기만 했구나...
라고만 생각이 들지 않도록</p>
<p>airflow를 써봤다 = 공식문서를 봤다.
airflow의 흐름을 알고 있다 = 오픈소스를 보고 어떤 흐름으로 흘러가는지 안다.
airflow 공식문서를 정리해서 책을 내면 잘 팔릴듯 ㅋㅋ</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[crud]]></title>
            <link>https://velog.io/@truly_flower/crud-0tp3va9v</link>
            <guid>https://velog.io/@truly_flower/crud-0tp3va9v</guid>
            <pubDate>Mon, 03 Jun 2024 07:55:43 GMT</pubDate>
            <description><![CDATA[<p>cerat read
update delete</p>
<p>serialize
모델 데이터를
jason으로 바꾸는거.</p>
<p>deserialize
그 반대</p>
<p><img src="https://velog.velcdn.com/images/truly_flower/post/5b51d079-dbee-4f6b-ab76-64b1076c2c9b/image.png" alt="">
<img src="https://velog.velcdn.com/images/truly_flower/post/f4ad03c0-48f1-45ab-8b9f-6ea35e32920d/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[간단한 ETL 작성]]></title>
            <link>https://velog.io/@truly_flower/%EA%B0%84%EB%8B%A8%ED%95%9C-ETL-%EC%9E%91%EC%84%B1</link>
            <guid>https://velog.io/@truly_flower/%EA%B0%84%EB%8B%A8%ED%95%9C-ETL-%EC%9E%91%EC%84%B1</guid>
            <pubDate>Mon, 03 Jun 2024 07:55:35 GMT</pubDate>
            <description><![CDATA[<p>에어플로에서는 dag라고 부름
a. DAG (Directed Acyclic Graph)
단어 뜻 그대로 순환하지 않는 그래프, DAG(대그)라고 부름
반복이나 순환을 허용하지 않음
순차적으로 작업(task)이 이루어지며, 순환 실행을 방지하기 때문에 매우 중요함
→ 논리적 오류는 교착상태(deadlock)로 이어짐</p>
<p>extract
transform (너무 크면 spark같은 빅데이터 프레임워크를 쓰기도 함)
load </p>
<p>묶어서 하나의 task가 되기도,
각각이 하나의 task가 되기도 함.</p>
<p>웹상에 존재하는 이름 성별 csv파일을 redshift에 있는 테이블로 복사하는데,
name열을 pirmary key로 지정할 것임.
하지만 데이터 웨어하우스에서는 primary key 로 지정한다고 해서 uniqeness가 지켜지는 것이 아님.
따라서 그것을 데이터 엔지니어가 책임져야 함.</p>
<h4 id="파이썬으로-extract-transform-load-함수를-구성할-것">파이썬으로 extract, transform, load 함수를 구성할 것</h4>
<p><img src="https://velog.velcdn.com/images/truly_flower/post/1beb0ce2-08c0-4fd2-b520-be7f755afe10/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[다음 프로젝트는]]></title>
            <link>https://velog.io/@truly_flower/%EB%8B%A4%EC%9D%8C-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EB%8A%94</link>
            <guid>https://velog.io/@truly_flower/%EB%8B%A4%EC%9D%8C-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8%EB%8A%94</guid>
            <pubDate>Tue, 28 May 2024 02:35:11 GMT</pubDate>
            <description><![CDATA[<p>파케이로 저장해보기. (처리속도가 얼마나 증가하는지 궁금)
트랜잭션(transaction)이란 &quot;쪼갤 수 없는 업무 처리의 최소 단위&quot;를 말한다.
begin, end= commit으로 하나의 트랜젝션 만들어보기</p>
<p>만약 roll back - 비긴 이전으로 돌아감
<img src="https://velog.velcdn.com/images/truly_flower/post/bbcf7e19-51ef-45ec-954b-770bd4e5b124/image.png" alt="">
<img src="https://velog.velcdn.com/images/truly_flower/post/eaec9c0e-dcf2-49c6-baca-25c325ba8dfc/image.png" alt="">
이건 개인 선호도 차이
<br/>
try execpt 할 때 except 뒤에 슬랙으로 알리든 하는 기능을 넣어야 함.
아니면 계속 모르고 넘어가게 됨.
따라서 raise를 써주면 fail하기 때문에 airflow가 알 수 있게됨.
fail했을때 이메일을 보낸다거나 슬랙으로 알린다거나 하도록 하게 하면 됨.</p>
<p><br/><br/><br/><br/><br/><br/><br/></p>
<h2 id="에어플로-설치">에어플로 설치</h2>
<p>가장 좋은 방법 : 사양이 좋은 EC2서버를 만들고 그안에 다커 엔진을 설치한 다음에 다커 컨테이너 형태로 에어플로를 실행하는게 가장 좋은 방법(팀프로젝트 할 땐 이렇게 해야 할 것)</p>
<p>리눅스 이해하기
● 우분투 (ubuntu): 리눅스 타입 중의 하나. 다른 타입은 데비안, 레드햇, 페도라,
...
● ssh: 리눅스 혹은 유닉스 서버에 로그인해주는 프로그램 (터미널)
○ private key와 public key를 사용
● sudo: 보통 슈퍼유저로서 프로그램을 구동할 수 있도록 하는 프로그램이다.
● apt-get: 우분투/데비안 계열의 리눅스에서 프로그램 설치/삭제를 관리해주는
프로그램
○ apt-get update, apt-get install
● su: substitue user의 약자로 현재 사용 중인 사용자 계정을 로그아웃하지 않고
다른 사용자의 권한을 얻을 때 사용한다
● vi: 텍스트 에디터. <a href="https://withcoding.com/112">https://withcoding.com/112</a></p>
<p><br/><br/><br/><br/></p>
<ol>
<li><p>도커 엔진 맥북에 설치 :  맥에서는 4GB가 필요
<img src="https://velog.velcdn.com/images/truly_flower/post/e4d6857f-37db-4e89-af1a-eec6180b8a67/image.png" alt=""></p>
</li>
<li><p>airflow 도커 이미지 다운
●먼저 터미널 프로그램을 실행하고 적당한 폴더로 이동
●airflow-setup Github repo를 클론
○ git clone <a href="https://github.com/keeyong/airflow-setup.git">https://github.com/keeyong/airflow-setup.git</a>
● airflow-setup 폴더로 이동하고 
○ cd airflow-setup
●2.5.1 이미지 관련 yml 파일 다운로드
○ curl -LfO &#39;<a href="https://airflow.apache.org/docs/apache-airflow/2.5.1/docker-compose.yaml&#39;">https://airflow.apache.org/docs/apache-airflow/2.5.1/docker-compose.yaml&#39;</a>
● 이미지 다운로드
○docker-compose -f docker-compose.yaml pull</p>
</li>
</ol>
<ol start="3">
<li><p>그 이미지를 도커 컨테이너 안으로 실행을 시킨 다음
● 컨테이너 실행
○ docker-compose -f docker-compose.yaml up</p>
</li>
<li><p>그게 다 잘되면 airflow 웹서버가 뜰거고, 그거를 웹 브라우저를 통해 access 해보는 형태로 데모를 실행해 볼것.
● <a href="http://localhost:8080%EC%9C%BC%EB%A1%9C">http://localhost:8080으로</a> 웹 UI 로그인
○airflow:airflow 사용</p>
</li>
</ol>
<p><img src="https://velog.velcdn.com/images/truly_flower/post/1ac2e304-8fab-446f-8a07-18223a78c501/image.png" alt=""></p>
<p>아래는 DAG객체 만든 예시
(한기용)</p>
<pre><code class="language-py">from airflow import DAG
dag = DAG(
&quot;dag_v1&quot;, #DAG이름
start_date = datetime(2020,8,7,hour = 0 ,minute = 00),
schedule = &quot;0****&quot;, #얘도 한시간에 한번임.모든 0분마다 한번씩 시작이 됨.
tags = [&quot;example&quot;],
catchup = False ,
#아까 공통 세팅 정해준거 넣기
defalut_args = defalut_args
)</code></pre>
<p>(다른 블로그)</p>
<pre><code class="language-py">def task_failure_alert(context):
    print(f&quot;Task has failed, task_instance_key_str: {context[&#39;task_instance_key_str&#39;]}&quot;)

def dag_success_alert(context):
    print(f&quot;DAG has succeeded, run_id: {context[&#39;run_id&#39;]}&quot;)

with DAG(
    dag_id=&quot;example_callback&quot;,
    schedule=None,
    start_date=pendulum.datetime(2021, 1, 1, tz=&quot;UTC&quot;), #시작날짜
    dagrun_timeout=datetime.timedelta(minutes=60),
    catchup=False,
    on_success_callback=dag_success_alert, #성공했을 때
    on_failure_callback=task_failure_alert, #실패했을 때
    tags=[&quot;example&quot;],
)</code></pre>
<p>schedule = None : 나는 주기적으로 실행 안할겨. 다른 DAG가 끝났을 때 trigger 할겨
schedule = @once : 나는 주기적으로 실행 안할겨. 다른 DAG가 끝났을 때 trigger 할거
schedule = @hourly : 매 시 0분
schedule = @daily : 매일 0시 0분
schedule = @weekly : 매 주 ...
schedule = @monthly
schedule = @yearly</p>
<p>catchup 
실행 안된 날짜에 대해서 매 시간마다 이 dag를 실행하려고 함.
catchup=False 하면
start date과 지금 날짜의 갭에 대해서 아무런 행동을 하지 않음
특히 dag가 Full refresh라면 과거 2년치에 대해 실행하나
지금 한번 실행하나 그 결과가 똑같기 때문에 꼭 False로 설정해줘야 함
incremental한거 아니면 다 False로 설정 할 것.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[데이터 파이프라인 만들때 주의점]]></title>
            <link>https://velog.io/@truly_flower/%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%8C%8C%EC%9D%B4%ED%94%84%EB%9D%BC%EC%9D%B8-%EB%A7%8C%EB%93%A4%EB%95%8C-%EC%A3%BC%EC%9D%98%EC%A0%90</link>
            <guid>https://velog.io/@truly_flower/%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%8C%8C%EC%9D%B4%ED%94%84%EB%9D%BC%EC%9D%B8-%EB%A7%8C%EB%93%A4%EB%95%8C-%EC%A3%BC%EC%9D%98%EC%A0%90</guid>
            <pubDate>Mon, 20 May 2024 08:33:49 GMT</pubDate>
            <description><![CDATA[<p>이상과 현실간의 괴리</p>
<ul>
<li>내가 만든 데이터 파이라인은 문제없이 동작할 것이고, 관리하는 것은 어렵지 않을 것이다.</li>
</ul>
<p>현실 : 버그 , 데이터 소스 상의 이유 What if data sources are not available or change its data format, 데이터 파이프라인들 간의 의존도에 이해도 부족</p>
<p>만약에 어떤 테이블의 열을 업데이트하거나 이름을 바꿨다면 그 뒷단의 파이프라인이 모두 변경되어야 하기 때문에 문제가 생김...(장고 하면서 경험해봤다ㅠㅠ)</p>
<h4 id="best-practices">Best practices</h4>
<ol>
<li><p>가능하면 데이터를 통채로 복사해서 테이블 만들기 (Full refresh)
문제가 생겨도 해결 방법이 간단.
이게 어느시점부터는 불가능할텐데, 그럼 incremental update를 해야함<br/>
소스를 봤을 떄 하루에 한번 업데이트를 하는 파이프라인이라면,
어제 하루 업데이트 된것만 DW에 저장
효율성은 올라가지만, operation이 복잡해짐
만약 하루씩 데이터가 올라가는데, 어떤날 데이터가 안올라갔다 = 빵꾸생김
과거 데이터가 바꼈다 = 다 다시 읽어와야 함. 코드를 바꿔야 함
이런 복잡도가 생김.따라서 가능하면 full refresh를 해라.
언제 그럼? - 이 데이터를 하루에 한번 업데이트를 해야한다? - full refresh를 하는데 12시간이 걸린다면 대략 정오쯤 데이터가 다 카피됨. 그래도 문제 없으면 full 쓰고, 적어도 오전 9시부터는 해야한다 = incremental refresh해야함.</p>
</li>
<li><p>멱등성을 보장해야함. Idempotency
몇번을 실행하나 결과가 동일해야함.
내가10번 실행하면 10번 중복이 된다 ? = 멱등성이 깨진 것.</p>
</li>
<li><p>백필이 쉬워야 함.
실패한걸 다시 채우는게 쉬워야 함.</p>
</li>
<li><p>데이터 파이프라인의 입력과 출력을 명확히 하고 문서화
비즈니스 오너 명시 - 누가 요청했는지 (필요 없으면 지우고 해야하니까)
데이터 리니지 (A라는 테이블이 뒷단에서 어떻게 소비되는지) 명확히 있어야 스키마를 바꾸면 누가 영향을 받는지 알게 됨. 이걸 이해하지 못하면 온갖 종류의 사고 발생</p>
</li>
<li><p>주기적으로 쓸모 없는 데이터들을 삭제
지난 90일동안 사용되지 않은것 등등.. 유데미에서는 쿼터에 한번정도 주기적으로 했다고 함.</p>
</li>
<li><p>데이터 파이프라인의 실패는 당연시 여기고, 그 사고 보고서를 잘 써야함.
사고 원인을 이해하고, 이를 방지하기 위한 액션 아이템들의 실행이 중요해짐.
사고의 정도를 보고 기술부채를 갚아야 할지..말지..</p>
</li>
<li><p>중요 데이터 파이프라인의 입력과 출력을 체크하기
입력 레코드 수와 출력 레코드 수가 몇개인지 체크하는 것부터 시작됨.
써머리 테이블을 만들어내고 primary key 가 존재한다면 primary key uniqueness가 보장되는지 체크하는 것이 필요함.
중복 레코드 체크</p>
</li>
</ol>
<p>장고 업데이트 사항 - 1. full refresh를 페이지 누를때마다 하지 말것.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[데이터 파이프라인 ]]></title>
            <link>https://velog.io/@truly_flower/%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%8C%8C%EC%9D%B4%ED%94%84%EB%9D%BC%EC%9D%B8</link>
            <guid>https://velog.io/@truly_flower/%EB%8D%B0%EC%9D%B4%ED%84%B0-%ED%8C%8C%EC%9D%B4%ED%94%84%EB%9D%BC%EC%9D%B8</guid>
            <pubDate>Mon, 20 May 2024 08:12:12 GMT</pubDate>
            <description><![CDATA[<p>써드파티
서드파티(Third Party)의 사전적 정의는 &#39;제3자&#39;를 뜻해요. IT업계에서 서드파티는 어떠한 분야에서 처음 개발하거나 원천기술을 가지고 있는 게 아닌, 원천기술과 호환되는 상품을 출시하거나 해당 기술을 이용한 파생상품을 생산하는 회사를 말해요. 즉 제3자로서의 역할을 하는 거죠.</p>
<p><strong>ETL</strong> 데이터 카피해서 데이터 웨어하우스로 집어넣기 (데이터 엔지니어가 수행) : 누군가 요청해서 하는것
ex) &quot; 페이스북 광고 데이터를 갖고와주세요 &quot;라는 요청을 수행. ( 보통 데엔은 어떻게 사용해야 되는지 모름)</p>
<p><strong>ELT</strong> 그걸 갖고 분석하기 쉽게 요약(조금 더 추상화되고 요약된 - 데이터 분석가가 수행)
데이터 크기에 따라 DW보다 DL의 정보를 바탕으로 하는 경우가 더 많음.</p>
<p>*<em>데이터 웨어하우스와 데이터 레이크의 차이는..?
*</em></p>
<p>데이터 레이크는 훨씬 몇배는 더 스케일이 큰 데이터 웨어하우스라고 보면 됨.
딱히 큰 기능 없어도 되고, 로그파일처럼 비구조화 된 데이터를 저장하는 데도 별 부담이 없음
원본 데이터를 건들지 않고 원본 그대로 복제 해놓는 경우가 많음.</p>
<p>데이터 웨어하우스는 관계형 데이터베이스이기 때문에
비구조화된건 어려움
보존기한이 있는 구조화된 데이터를 저장하고 &quot;처리&quot;하는 스토리지.
보통 BI툴들(룩커, 태블로, 수퍼셋)은 데이터 웨어하우스를 백엔드로 사용함.
<strong><em>실제로는</em></strong>
DL중 의미있는거만 가공해서 DW로 옮김</p>
<p>EX) 넷플리스
굉장히 많은 데이타 소스가 있음 (사용자 access 로그 같은 정보들 - 중요하지만 비구조화되어있음)
S3같은 data lake에 저장함
이걸 Spark, Athena같은 빅데이터 프로세싱 프레임워크를 사용해서
sql기반으로 프로세싱해서 정제해서 의미있는경우만 DataWarehouse 에 저장</p>
<p>데이터 파이프라인의 정의: 데이터를 소스로부터 목적지로 복사하는 작업 
보통 python or 스칼라 or SQL을 통해 이루어짐
대부분 목적지가 데이터 웨어하우스.</p>
<p><img src="https://velog.velcdn.com/images/truly_flower/post/9e33d9d1-2096-4a99-8504-32410c154f4f/image.png" alt=""></p>
<h4 id="데이터-파이프라인-종류-1---보통-데이터-엔지니어가-함">데이터 파이프라인 종류 1 - 보통 데이터 엔지니어가 함</h4>
<p>외부나 내부 데이터 소스에서 데이터를 읽어서(보통 api를 통하게 됨)
적당한 데이터 포맷 변환 후 (데이터 크기가 커지면 파이썬으로 불가. Spark 등이 필요해짐)
데이터 웨어하우스에 로드 </p>
<h4 id="데이터-파이프라인-종류-2---데이터-분석가가-함--애널리틱-엔지니어dbt데이터-빌드-툴">데이터 파이프라인 종류 2 - 데이터 분석가가 함 + 애널리틱 엔지니어(<a href="https://mjs1995.tistory.com/263">DBT</a>)데이터 빌드 툴</h4>
<ul>
<li>DW또는 DL에서 읽어서 다시 DW에 쓰는 ETL</li>
<li>raw data를 읽어서 리포트 형태나 써머리 형태의 테이블을 다시 만드는 용도</li>
<li>ab테스트 결과 분석</li>
</ul>
<p>데이터 엔지니어 관점에서는 어떻게 데이터 분석가들이 편하게 할 수 있는 환경을 만들어주느냐가 관건</p>
<h4 id="데이터-파이프라인-종류-3">데이터 파이프라인 종류 3</h4>
<p>DW로부터 데이터를 읽어 다른 스토리지(많은 경우 프로덕션 환경)으로 쓰는 ETL</p>
<ul>
<li>써머리 정보가 프로덕션 환경에서 성능 이유로 필요한 경우</li>
<li>혹은 머신러닝 모델에서 필요한 피쳐들을 미리 계산해두는 경우</li>
</ul>
<p>예를 들어서 너무 많은 사용자가 몰려서 좋아요를 누른다 - 하나하나 몰릴때마다 계산하면 부하가 심해져 문제가 생김
이때 유데미는 Mysql 이용
참고
<a href="https://devlog-wjdrbs96.tistory.com/374">https://devlog-wjdrbs96.tistory.com/374</a>
<a href="https://youtu.be/brYCFFWA_6M?si=3eH3JGyJ1vgJNUsA">https://youtu.be/brYCFFWA_6M?si=3eH3JGyJ1vgJNUsA</a> - 중학생도 k 학교대전에서 이용!
클라이언트가 몇 초 간격으로 유저가 클릭한 횟수를 카운팅해서 서버에게 전송하고 서버에서 매크로인지 확인하고, 정상 범위 내에 있으면 redis에 업데이트
redis에서 몇 시간당으로 DB에 업데이트 하는 구조 </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[한국은행 api 가져오기]]></title>
            <link>https://velog.io/@truly_flower/%ED%95%9C%EA%B5%AD%EC%9D%80%ED%96%89-api-%EA%B0%80%EC%A0%B8%EC%98%A4%EA%B8%B0</link>
            <guid>https://velog.io/@truly_flower/%ED%95%9C%EA%B5%AD%EC%9D%80%ED%96%89-api-%EA%B0%80%EC%A0%B8%EC%98%A4%EA%B8%B0</guid>
            <pubDate>Wed, 15 May 2024 14:18:11 GMT</pubDate>
            <description><![CDATA[<ol>
<li><p>화면 오른쪽 상단 인증키 신청 클릭
<img src="https://velog.velcdn.com/images/truly_flower/post/09c61613-96ac-4a9c-b412-19a53d6ff07b/image.png" alt=""></p>
</li>
<li><p>본인인증 후 이메일 확인</p>
</li>
<li><p>목록확인(코드)</p>
</li>
<li><p>상세목록 조회 안내서 다운로드</p>
</li>
<li><p>나는 환율 전체 나라 데이터를 1일치씩만 다운받고싶었고, 파이썬 for문을 이용해 csv파일로 저장</p>
</li>
</ol>
<pre><code class="language-py">import requests
import pandas as pd
from datetime import datetime, timedelta
import json


api_code =&#39;발급받은 코드를 쓰세요&#39;
c = &#39;731Y001&#39; #통계코드 확인 (나는 환율코드)

#먼저 list를 확인해준다.
response_list = requests.get(f&#39;http://ecos.bok.or.kr/api/StatisticItemList/{api_code}/json/kr/1/100/{c}/&#39;)
</code></pre>
<p>저장 함수를 짜줬다.</p>
<pre><code class="language-py">def save1(response,start_day,end_day):
    if response.status_code == 200:
        data = response.json()
        df = pd.json_normalize(data[&#39;StatisticSearch&#39;][&#39;row&#39;])
        it = data[&#39;StatisticSearch&#39;][&#39;row&#39;][0][&#39;ITEM_NAME1&#39;][2:]
        df.to_csv( it + start_day + end_day + &#39;.csv&#39;, index=False)
    else:    
        print(&#39;error:&#39;, response.status_code)</code></pre>
<p>각각 따로따로 있는 나라들을 하나씩 저장해줬다.</p>
<pre><code class="language-py">#52개국
for i in range(0,52):
    codd = &#39;&#39;
    if i &lt; 9:
        codd = &#39;000000&#39; + str(i+1)
    else :
        codd = &#39;00000&#39; + str(i+1)

    if response_list.status_code == 200:
        data = response_list.json()
        sorted_list = sorted(data[&#39;StatisticItemList&#39;][&#39;row&#39;], key=lambda x: int(x[&quot;ITEM_CODE&quot;])) #나라 코드 오름차순으로 정렬
        file_name = sorted_list[i][&#39;ITEM_NAME&#39;]
        cycle = sorted_list[i][&#39;CYCLE&#39;]
        end_day = sorted_list[i][&#39;END_TIME&#39;]
        end_day_int = datetime(int(end_day[:4]), int(end_day[4:6]), int(end_day[6:]))
        start_day_int = end_day_int - timedelta(days=0)
        start_day = start_day_int.strftime(&#39;%Y%m%d&#39;)
        print(sorted_list[i][&#39;ITEM_CODE&#39;])
        print(file_name)
        print(cycle)
        print(end_day)
        print(start_day) #오류 확인용 프린트
        response = requests.get(f&#39;http://ecos.bok.or.kr/api/StatisticSearch/{api_code}/json/kr/1/100/{c}/{cycle}/{start_day}/{end_day}/{codd}/?/?/?&#39;)#물음표는 채우니까 오류나서 그냥 그대로 냅둠
        data = response.json()
        print(json.dumps(data, indent=4, ensure_ascii=False)) #그냥 json으로 보니까 눈아파서 ..ㅎㅎ
        save1(response,start_day,end_day)

    else:
        print(&#39;error:&#39;, response_list.status_code)</code></pre>
<p>그렇게 52개의 csv파일이 생성되었다.
원래는 한 나라당 날짜별로 2024-05-01 , 1000원, 2024-05-02, 2000원 ,,,이런식으로 저장이 되어있다.
근데 나는 한 나라당 딱 한개씩만 필요했다..
그리고 모든 나라가 다 필요했다.....(superset에서 map을 그리고 싶었기 때문)</p>
<p>그래서 이 52개 파일을 S3에 올리고,
redshift에서 한 테이블(country_exchange_rate)에 다 저장할거다
그럼 52개의 레코드(행)이 생긴다.</p>
<p>그 전에 각 나라별 ISO코드를 다른 csv파일로 저장했다.( gpt로 찾아서 저장함 .)
그리고 나라별로 붙여진 숫자코드를 붙여줬고
얘는 다른 테이블로 저장 (country_code)</p>
<p>그리고 나라별 숫자코드 열로 country_code테이블과 country_exchange_rate테이블을 조인할것임..</p>
<pre><code class="language-sql">--코랩에서 진행.
%load_ext sql
!pip install ipython-sql==0.4.1
!pip install SQLAlchemy==1.4.47</code></pre>
<pre><code class="language-sql">--연결
%sql postgresql://{id}:{pw}@{~~~redshift-serverless.amazonaws.com}:5439/데이터베이스이름</code></pre>
<pre><code class="language-sql">%%sql
CREATE SCHEMA raw_data;</code></pre>
<p>52개 데이터의 모든 열이 똑같았기 때문에, 버킷에 폴더를 만들어줘서 그 폴더 내부의 모든 파일을 모두 한 테이블에 저장하는 sql문을 짠 것.</p>
<pre><code class="language-sql">%%sql

DROP TABLE IF EXISTS country_exchange_rate;
DROP TABLE IF EXISTS raw_data.country_exchange_rate;

CREATE TABLE raw_data.country_exchange_rate (
    STAT_CODE varchar(256),
    STAT_NAME varchar(256),
    ITEM_CODE1 float,
    ITEM_NAME1 varchar(256),
    ITEM_CODE2 float,
    ITEM_NAME2 varchar(256),
    ITEM_CODE3 float,
    ITEM_NAME3 varchar(256),
    ITEM_CODE4 float,
    ITEM_NAME4 varchar(256),
    UNIT_NAME varchar(256),
    WGT float,
    TIME DATE,
    DATA_VALUE float
);

COPY raw_data.country_exchange_rate
FROM &#39;s3://kor-financial-market/exchange_rate/pythontest/&#39;
IAM_ROLE &#39;~~~~~~~~~~&#39;
CSV
IGNOREHEADER 1
DATEFORMAT &#39;auto&#39;;</code></pre>
<p>근데 2001년도 이런식으로 가장 최신 데이터가 한참 전 데이터라면, 그 나라는 이제 그 돈을 안 쓰고 있는것이다. 
처음엔 NULL값이 들어있어서 UPDATE함수로 채워줬지만, 다시 확인해보니 그러면 중복 값이 되어버리는 것이다.
그래서 DELETE로 그 국가들은 없애주었다.(대부분 본인 나라 돈 쓰다가 유로로 바뀐 케이스+중국,홍콩)</p>
<p>이후 iso를 담은 테이블 하나 더 생성</p>
<pre><code class="language-sql">%%sql 
CREATE TABLE raw_data.country_code (
  code_name varchar(256),
  code_num float,
  country_name varchar(256),
  ISO varchar(256)
);

COPY raw_data.country_code
FROM &#39;s3://kor-financial-market/exchange_rate/exchange_rate_code.csv&#39;
credentials &#39;~~~~~~~~~~~&#39;
delimiter &#39;,&#39; dateformat &#39;auto&#39; timeformat &#39;auto&#39; IGNOREHEADER 1 removequotes;</code></pre>
<p>이제 preset에서 sql lab에 들어간다..</p>
<pre><code class="language-sql">SELECT
  b.code_num,
  b.country_name,
  b.iso,
  a.time,
  a.data_value
FROM
  raw_data.country_exchange_rate AS a
JOIN
  raw_data.country_code AS b ON a.item_code1 = b.code_num</code></pre>
<p>이렇게 간단하게 조인완성!
<img src="https://velog.velcdn.com/images/truly_flower/post/bdc61ee9-8650-41a2-8a3b-14743fd5c70f/image.png" alt="">
그럼 이 테이블로 지도를 만들면!!!
<img src="https://velog.velcdn.com/images/truly_flower/post/533720f6-0bda-4681-b31d-75d9e4da11dc/image.png" alt="">
동그라미가 클 수록 비싼 나라다 ㅋㅋㅋ</p>
<p>한국은행에서 주요 나라 데이터들만 제공해줬기 때문에, 모든 나라의 데이터가 없다.
따라서 내일은 크롤링을 통해 모든 나라의 데이터를 긁어와서 채우는 것이 목표!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[@Override]]></title>
            <link>https://velog.io/@truly_flower/Override</link>
            <guid>https://velog.io/@truly_flower/Override</guid>
            <pubDate>Fri, 03 May 2024 05:42:10 GMT</pubDate>
            <description><![CDATA[<p>상속(extends)이란 상위 클래스에 있는 변수 메소드 등을 전부다 가져와서 쓸수 있게 만드는 것이다. </p>
<p>말그대로 우리 현대사회에서 부모가 가진 부동산 재화(변수) 그리고 권력(메소드)
<br>
이렇게 우리는 반복되는 코드는 그냥 부모의 것을 상속받아서 쓸 경우 편하게 사용 가능하다. </p>
<p>여기서 생각해야하는 점은 부모에게 상속 받은 메소드들 중에서 3가지가 있다면 한가지 Method는 내맘에 들지않는다.</p>
<p>즉 코드가 다르다는 뜻이다.</p>
<p>이럴때 @Override 한다고 즉 재정의해서 </p>
<p>내가 원하는대로 코딩을 가능하게 만드는 것이다.</p>
<p>즉 비유적으로 표현하면 아버지의 물건을 그대로 쓰지 않고 자기입맛에 맞게 고치기위해서 먼저 나이거 고칠게</p>
<p>라고 Java에게 가르쳐주는 것이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[document db 차이점]]></title>
            <link>https://velog.io/@truly_flower/document-db-%EC%B0%A8%EC%9D%B4%EC%A0%90</link>
            <guid>https://velog.io/@truly_flower/document-db-%EC%B0%A8%EC%9D%B4%EC%A0%90</guid>
            <pubDate>Tue, 30 Apr 2024 05:41:22 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/truly_flower/post/1afa6e22-2e48-4552-98b8-76d2f25704ff/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[API 와 Endpoint ]]></title>
            <link>https://velog.io/@truly_flower/API-%EC%99%80-Endpoint</link>
            <guid>https://velog.io/@truly_flower/API-%EC%99%80-Endpoint</guid>
            <pubDate>Mon, 22 Apr 2024 07:17:24 GMT</pubDate>
            <description><![CDATA[<p>하지만 URI URL 두 가지가 있는지 모르고 이 두가지를 하나로 혼용해 &quot;인터넷 주소잖아&quot; 라고 생각하는게 일반적입니다.</p>
<p>크게 문제는 없지만 이 둘의 차이점이 존재합니다.</p>
<p><img src="https://velog.velcdn.com/images/truly_flower/post/feb9a416-4b54-4ab3-8215-03397b3998da/image.png" alt=""></p>
<p>사진을 통해 간단히 보자면 URI가 가장 큰 개념으로 URI의 하위 개념으로 URL과 URN을 포함하고있습니다.</p>
<p>이번 포스팅에선 URI와 URL,URN 각 개념과 차이점에 대해 알아보려합니다.</p>
<p>먼저 URL의 구조 부터 알아야 하기 때문에 URL 부터 설명해보겠습니다.</p>
<p>URL ( Uniform Resource Locator ) - 통합 자원 지시자
URL은 우리가 가장 흔히 보는 것으로</p>
<p>URL은 Resource의 정확한 위치 정보(파일의 위치)를 나타냅니다.</p>
<p>URL을 통해 Resource가 어디에 있는지 어떻게 접근할 수 있는 지 알 수 있습니다.</p>
<p>URL 예시
<a href="https://www.naver.com/">https://www.naver.com/</a> - 네이버의 URL</p>
<p><a href="https://search.shopping.naver.com/best/today?rankedDate=20220922">https://search.shopping.naver.com/best/today?rankedDate=20220922</a> - 네이버 쇼핑의 오늘의 베스트 카테고리 URL</p>
<p><a href="https://www.youtube.com/feed/subscriptions">https://www.youtube.com/feed/subscriptions</a> - 유튜브의 구독한 목록 URL</p>
<h2 id="url의-구조">URL의 구조</h2>
<p>다음과 같은 URL이 있다하고 이 URL을 부분별로 나누어 하나씩 살펴보겠습니다.</p>
<p><code>https://hstory0208.tistory:3000/category?category=network&amp;page=5#url차이</code></p>
<p><img src="https://velog.velcdn.com/images/truly_flower/post/07a9ee87-02e0-4d4e-8add-57757b237404/image.png" alt=""></p>
<p>URN ( Uniform Resource Name ) - 통합 자원 이름
Resource의 위치와 상관없이 식별 가능한 고유한 이름 역할을 합니다.</p>
<p>URN은 이름이 변하지 않는한, 리소스 위치가 변경되더라도 문제없이 동작합니다.</p>
<p>즉, 리소스 위치와 상관없이 이름만으로 식별할 수 있다는 개념입니다.</p>
<p>URN은 URL의 한계로 인해 생긴 것으로 아직까진 URL이 대중화가 되어 채택되지 못했습니다.</p>
<h2 id="url의-한계란-">URL의 한계란 ?</h2>
<p>리소스의 위치를 옮기면 해당 URL을 더 이상 사용할 수 없는것.</p>
<p>만약, 구글 검색에 노출된 hstory0208.tistory.com/10 이라는 링크가 있다고 가정해봅시다.
이 주소를 바꾸고 싶어 hstory0208.tistory.com/network/10 으로 주소를 바꾼다면
다른 사람이 기존에 노출된 링크(hstory0208.tistory.com/10)에 접속 시 주소가 바뀌었기 때문에 해당 페이지는 찾을 수가 없게되는것입니다.
이게 바로 URL의 한계 입니다. </p>
<p>URI ( Uniform Resource Identifier ) - 통합 자원 식별자
자원의 위치뿐만 아니라 자원에 대한 고유 식별자로서 URL을 의미를 포함합니다.</p>
<p>URI의 존재는 인터넷에서 요구되는 기본조건으로써 인터넷 프로토콜에 항상 붙어다니며,</p>
<p>URI의 하위 개념으로 URL,과 URN이 있습니다.</p>
<h2 id="uri와-url-구분하기">URI와 URL 구분하기</h2>
<p>URI와 URL를 쉽게 구분하는 방법은</p>
<p>URI 는 통합 자원 식별자로 주소에 식별자가 있으면 URI</p>
<p>URL은 리소스 주소를 나타내므로 리소스 위치까지만 나타내면 URL 입니다.</p>
<p>다음 예시를 통해 비교하며 이해해봅시다.</p>
<p><a href="https://hstory0208.tistory.com/category">https://hstory0208.tistory.com/category</a>
hstory0208.tistory.com 에서 category 라는 경로를 나타냅니다.</p>
<p>category는 리소스의 실제 위치이므로 이 주소는 URL 입니다.</p>
<p><a href="https://hstory0208.tistory.com/category/12">https://hstory0208.tistory.com/category/12</a>
hstory0208.tistory.com 에서 category 라는 자원의 경로를 나타내는 부분까진 URL 이지만</p>
<h3 id="12-는-식별자-이므로-httpshstory0208tistorycomcategory-url을-포함한-uri라고-할-수-있습니다">/12 는 식별자 이므로 <a href="https://hstory0208.tistory.com/category">https://hstory0208.tistory.com/category</a> URL을 포함한 URI라고 할 수 있습니다.</h3>
<p><a href="https://hstory0208.tistory.com/category?page=12">https://hstory0208.tistory.com/category?page=12</a>
위와 마찬가지로 <a href="https://hstory0208.tistory.com/category">https://hstory0208.tistory.com/category</a> 까지는 자원의 실제 위치를 나타내기 때문에 URL이고,</p>
<p>뒤의 query ( ?page=12 ) 가 붙었으므로 <a href="https://hstory0208.tistory.com/category">https://hstory0208.tistory.com/category</a> URL을 포함한 URI 입니다.</p>
<hr>
<p>API 와 Endpoint의 차이 한 줄 정리</p>
<p>​</p>
<p>API가 두 시스템(어플리케이션)이 상호작용할 수 있게 하는 프로토콜의 총집합이라면,</p>
<p>ENDPOINT는 API가 서버에서 리소스에 접근할 수 있도록 가능하게 하는 URL이라 할 수 있겠다.</p>
<ol>
<li>Endpoint, 엔드포인트</li>
</ol>
<p>An endpoint is simply one end of a communication channel.</p>
<p>(stackoverflow)</p>
<p>​</p>
<p>​</p>
<p>커뮤니케이션 채널의 한 쪽 끝.</p>
<p>서비스를 이용할 때 사용하는 커뮤니케이션 채널의 한쪽 끝에 해당하는 URI.</p>
<p>이번에 api를 활용 할 때 , end point라고 적혀있고
url이 적혀있어서 뭔가 궁금했었다.</p>
<p>API는 Application Programming Interface의 약자로, 응용 프로그램 프로그래밍 인터페이스.
프로그램 혹은 시스템 간의 통신하는 창구, 즉</p>
<p>프로그램들이 서로 상호작용하는 것을 도와주는 매개체라 할 수 있다.
<img src="https://velog.velcdn.com/images/truly_flower/post/2246fbbf-0817-4d46-aea7-c1b6a4d59ed5/image.png" alt=""></p>
<p>점원은 손님에게 메뉴를 알려주고, 주방에 주문받은 요리를 요청하고, 그다음 주방에서 완성된 요리를 손님께 다시 전달. API는 여기서 점원과 같은 역할을 한다.</p>
<p>​</p>
<p>API는 손님(프로그램)이 주문할 수 있게 메뉴(명령 목록)를 정리하고,</p>
<p>주문(명령)을 받으면 요리사(응용프로그램)와 상호작용하여 요청된 메뉴(명령에 대한 값)를 전달한다.</p>
<p>​</p>
<p> API는 프로그램들이 서로 상호작용하는 것을 도와주는 매개체로 볼 수 있겠다.</p>
<p>​</p>
<p>이제.. API가 뭔지 대충은 감이 오니까 더 자세히 알아보자!</p>
<blockquote>
</blockquote>
<ol>
<li>API는 서버와 데이터베이스에 대한 출입구 역할을 한다.</li>
</ol>
<p>: 데이터베이스에는 소중한 정보들이 저장된다. 그렇기에 모든 사람들이 이 데이터베이스에 접근할 수 있어서는 안 된다. API는 이를 방지하기 위해 사람들이 가진 서버와 데이터베이스에 대한 출입구 역할을 하며, 허용된 사람들에게만 접근성을 부여해 준다.</p>
<p>​</p>
<blockquote>
</blockquote>
<ol start="2">
<li>API는 애플리케이션과 기기가 원활하게 통신할 수 있도록 한다.</li>
</ol>
<p>: 여기서 애플리케이션이란 우리가 흔히 알고 있는 스마트폰 앱이나 프로그램을 말한다.</p>
<p>API는 애플리케이션과 기기가 데이터를 원활히 주고받을 수 있도록 돕는 역할을 한다.</p>
<p>​</p>
<blockquote>
</blockquote>
<ol start="3">
<li>API는 모든 접속을 표준화한다.</li>
</ol>
<p>API는 모든 접속을 표준화하기 때문에 기계/ 운영체제 등과 상관없이 누구나 동일한 액세스를 얻을 수 있다. 쉽게 말해, API는 범용 플러그처럼 작동한다고 볼 수 있겠다.</p>
<p>API는 작은 단위로 응용프로그램에서 사용할 수 있도록</p>
<p>OS나 프로그래밍 언어가 제공하는 기능을 사용/제어할 수 있게 하는 인터페이스를 의미하기도 한다. (날씨 api는 이건 아니다)</p>
<p>​</p>
<p>자바를 예로 들자면 JDK 1.8에서 추가된 Stream API 가 있다.</p>
<p>여기서의 스트림은 파일 I/O에서 사용되는 스트림과는 다르다. 스트림은 데이터 소스를 추상화하고, 데이터를 다루는데 자주 사용되는 메서드들을 정의해 놓았다. 데이터 소스를 추상화하였다는 것은 데이터 소스가 무엇이든 같은 방식으로 다룰 수 있게 되었다는 것과, 코드의 재사용성이 높아진다는 것을 의미한다.</p>
<p>​</p>
<p>여기서 Stream이라는 기능을 사용하기 위해 제공된 명세를, API라고 할 수 있다.</p>
<p>(명세에 대해서 이해가 잘되지 않는다면, 자바의 Interface 개념을 생각해 보면 좋을 듯하다)</p>
<p>​</p>
<p>API에 대한 간단한 설명을 뒤로하고, 이번 글의 주제인 엔드포인트를 이해하기 위해 웹에서 사용하는 API에 대해 알아보자.</p>
<p>​</p>
<p>​
3. 웹 API</p>
<p>웹 API는 웹 애플리케이션 개발에서 다른 서비스에 요청을 보내고 응답을 받기 위해 정의된 명세를 일컫는다.</p>
<p>예를 들어 블로그 API를 이용하면, 블로그에 접속하지 않고도 다른 방법으로 글을 올릴 수 있다.</p>
<p>그 외에 우체국의 우편번호 API, 구글과 네이버의 지도 API 등 유용한 API들이 많으므로, 요즘은 홈페이지 구축이나 추가 개편 시 따로 추가로 개발하지 않고 이런 오픈 API를 가져와 사용하는 추세다.</p>
<p>​</p>
<p>한마디로 서비스 간의 요청과 응답을 위한 명세로 정리할 수 있겠는데,</p>
<p>글 초반부에서 참고한 stackoverflow의 내용과 연결점이 있다.</p>
<p>엔드포인트는 서비스를 사용 가능하도록 하는 서비스에서 제공하는 커뮤니케이션 채널의 한쪽 끝.</p>
<p>즉 요청을 받아 응답을 제공하는 서비스를 사용할 수 있는 지점을 의미한다.</p>
<p>​</p>
<p>예를 들어 지하철 최단 거리 경로를 제공하는 웹 서비스가 있다고 하자.</p>
<p>이 서비스를 이용하는 사용자는 출발역과 도착역을 설정하고 최단 경로를 찾는 버튼을 누른다.</p>
<p>이때 최단 거리 경로를 구하는 서비스를 이용하기 위한 요청이 향하는 URI가, 엔드포인트이다.</p>
<p>​</p>
<p>이 웹 서비스는 유효한 형태로 엔드포인트에 요청이 전달되었을 경우 사용자가 알 필요 없는 서비스 내부 로직을 실행하고 응답을 반환한다.</p>
<p>​</p>
<p>​
3. API vs Endpoint</p>
<p>결국 API가 두 시스템(어플리케이션)이 상호작용(소통) 할 수 있게 하는 프로토콜의 총집합이라면,</p>
<p>ENDPOINT는 API가 서버에서 리소스에 접근할 수 있도록 가능하게 하는 URL이라 할 수 있겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[데이터 엔지니어 프로젝트 4일차 회고]]></title>
            <link>https://velog.io/@truly_flower/%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%97%94%EC%A7%80%EB%8B%88%EC%96%B4-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-4%EC%9D%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@truly_flower/%EB%8D%B0%EC%9D%B4%ED%84%B0-%EC%97%94%EC%A7%80%EB%8B%88%EC%96%B4-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-4%EC%9D%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Thu, 18 Apr 2024 01:22:19 GMT</pubDate>
            <description><![CDATA[<h1 id="한-것">한 것</h1>
<h3 id="1-장고-사용법에-익숙해-졌다br">1. 장고 사용법에 익숙해 졌다.<br></h3>
<p>1) 모델
처음에 model.py를 잘못 만졌다가, 계속 오류가 났었다.
이제 모델을 건들기 전에 
마이그레이션 기록들을 살펴 본 뒤,
테이블까지 살펴보고, 테이블 내부 형태까지 살펴본 뒤에
삭제, 추가 하는 습관이 생겼다.
근데 아직도 이름바꾸기는 조금 어렵다..ㅎ
그 사이에 sqlite3의 사용법도 익히게 되었다.
그리고 오류가 생기면 대체로 테이블이 없다, 테이블이 없다... 테이블이 이미 있다...
이런 오류였기 때문에
sqlite로 바로 테이블 생성하고 삭제하고 하는것 까지 익숙해졌다.
새로운 필드를 만들 땐, 이전 데이터들에 없는 값을 채워주기 위해 디폴트 값을 정의해야한다.<br>
2) 장고의 구조 이해
장고는 프로젝트 라는 거대한 틀이 있고, 그 내부에 여러 앱들을 추가하는 구조로 이루어진다.
한 앱은 한 폴더로 이루어져있고, 그 폴더 내부에는 여러가지 파이썬 파일들이 구성되어 있다.
만약에 필요한 함수가 크다면 새로운 파일을 만들어서 함수를 저장한 뒤,
다른곳에서 그 함수를 쓰면(from .파일이름 import 함수이름들 해야 쓸 수 있음)
함수가 그대로 작동한다!
그리고 뷰가 가장 중요하다고 느꼈던게, 
url.py에서 path를 작성 할 때, 뷰에서 어떤 함수를 작동하도록 해라~하고 쓰기 때문이다!그럼 그 path로 이동했을 때, 그 작동한 화면을 볼 수 있다<br></p>
<h3 id="2-cli-사용법에-익숙해졌다br">2. CLI 사용법에 익숙해졌다.<br></h3>
<p>1) 가상환경 설치
가상환경이 뭔지부터 몰라서 찾아보니 굉장히 쉽게 설명해주신분이 계셨다..
가상환경이라는게 애초에 다른 버전의 프로그램을 돌리기 위해 있는 것이였다!
마침 나는 파이썬3 .12가 안되고 3.11에서만 무언가가 되기때문에 이걸 3.11로 설치했어야 됐고
이 설명을 보며 아 ~~그래서 그렇구나 라고 잘 이해하게 되었다.
문제는
가상환경을 설치하면서 이게 어디에 설치되고, 어디에 설치해야하고, 어느 폴더로 가야하며
설치된건 어디에있고 삭제는 왜 또 맘대로 안되며...ㅋㅋㅋ
:wq 이거부터 ㅜㅜ
아직 배워야 할 게 많지만 이제 무섭지는 않다!
(처음엔 진짜 뭔지 몰라서 인터넷에 나와있는 $표시부터 다 따라 쳤었다..)<br>
2) 파일이동<br>
3) 폴더 위치 찾기 
cmd option c 하면 파일 위치가 복사된다.<br>
4) 환경변수 이해 
python3 -&gt; python 만 쳐도 나오도록 함</p>
<h3 id="3-오류-읽는-법에-익숙해졌다">3. 오류 읽는 법에 익숙해졌다.</h3>
<p>이번에 우리는 완전 생 초보들만 모여서 진행한 조였다.
그래서 좋았던 점도, 단점도 있었지만 그래서 바닥부터 크게 된 것같다..(feat 오류지옥)</p>
<h3 id="4-인공지능-활용에-익숙해-졌다br">4. 인공지능 활용에 익숙해 졌다.<br></h3>
<p>이번에 우리가 한 것은 과거 데이터와, 오늘 데이터를 비교하는 프로젝트였다.
그런데, 과거 데이터와 오늘의 데이터 저장 형식이 다르게 되어 있다는 것이 굉장한 골칫덩이였다.
근데 그거보다 더 큰 골치는 시간을 제대로 입력해 주지 않으면 데이터를 받아오지 못한다는 사실이였다(데이터가 계속 업데이트 되기 때문)
또한 데이터를 받아와서 저장하는 것도 문제고, 이 데이터를 어떤 방식으로 저장해야될지도 사실 엄청 고민했었다.
다들 초보이기 때문에 쉽게 꺼내 쓸 수 있는 데이터 형식이 되었으면 좋겠다고 생각했기 때문이다.</p>
<p>여기서 url을 업데이트 시간을 반영해서 조정하는 것도 할 줄 알게 되었고,</p>
<p>데이터를 받아서 데이터베이스에 저장하는것도 굉장히 어려웠고... 흐엉 ㅜㅜ
정말 아침에 일어나자마자부터 딱 자기전까지 코딩생각만 머릿속에 뺑글뺑글 돌아갔다.
왜냐하면 내가 제시한 아이디어였고,
데이터가 저장되지 않으면 절대 이 프로젝트는 완성될 수 없기 때문에
내 역할이 가장 초반에 탄탄히 다져져야 했기 때문이다. 그래서 부담감도 엄청났다..
그와중에 아침에 일어나서 매일 아침운동도 했다 ㅋㅋㅋㅋㅋ
아침운동이 하루종일 집중할 수 있게 해주는 키포인트이기도 했기 때문이다.</p>
<p>그리고 처음에는 인코딩 키, 디코딩 키도 어떻게 해야할 지 몰라 엄청 버벅였다
심지어 둘 다 나와있는데도 뭔가 다를 줄 알고
인코딩키를 디코딩하는 프로그램을 돌려 디코딩했더니
엥? 똑같이 나오네 ? 하면서 익혀갔다 ㅋㅋㅋㅋ
사람들도 날씨를 과거 데이터를 받아와서 비교하는 프로젝트는 잘 하지 않는다는 것을 알았다..
그런 자료가 별로 없어서 나는 과거 데이터를 비교하는 프로젝트를 해보고 싶었는데,
그게 오히려 독이 된 것이다..(왜냠 나는 초보초보초보니깐 ..흑)</p>
<p>그래도 어찌저찌 구조를 잘 공부했는데(오류지옥에서 살아남으며 저절로 공부함..ㅎㅎ)
이 오류를 분석 할 때 인공지능이 큰 도움이 되었다.
오류를 입력하면 오류를 해석해 주는 것 뿐만 아니라 어떤 문제인지 설명도 해주기 때문이다.
대신 그것을 알아먹는 것은 그 사람 몫이고,
인공지능이 코드를 잘 짜주진 못한다.(질문이나 짤 구조같은것을 잘 적어주면 될지도..근데 나는 지금은 내가 짜는게 편하다..)</p>
<p>하지만 ;같은걸 잘 못 친 사소한 오류나 
source venv/bin/activate라고 쳐야하는데 
python3 venv/bin/activate라고 쳤거나 
하는 것을 잘 잡아주어서, 이제 진짜 코드를 잘 짜는 것이 중요하게 됐고
쓸데없는 곳에서 하는 시간낭비가 매우매우매우 줄어들었다는 것을 체감하게 되었다.</p>
<p>필자는 코파일럿과, gpt4(남친찬스<del>~</del>&gt;&lt;) 를 둘 다 쓰는데,
아무래도 둘 다 있는게 좋은 것 같다.ㅋㅋㅋㅋㅋㅋㅋㅋ</p>
<p>그 차이는 써본 사람만이 알 것이다 ㅋㅋㅋ</p>
<h3 id="5-html--javascript-사용법을-어느정도-알게-되었다">5. HTML , Javascript 사용법을 어느정도 알게 되었다.</h3>
<p>근데 정말 어느 정도이지, 막 잘 하고 그런건 아니다.</p>
<h3 id="6-깃허브의-브랜치-포크-충돌해결에-익숙해졌다">6. 깃허브의 브랜치, 포크, 충돌해결에 익숙해졌다.</h3>
<h3 id="7-팀-프로젝트의-전체-그림이-머릿속에-있냐-없냐가-얼마나-큰-차이를-불러오는-지-알게-되었다">7. 팀 프로젝트의 전체 그림이 머릿속에 있냐 없냐가 얼마나 큰 차이를 불러오는 지 알게 되었다.</h3>
<p>월요일 화요일은 다들 깃에 익숙해지고, 장고에 익숙해 지는 시간이였던 것같다.
그리고 화요일 저녁때 만나보니 다들 어느정도 기능을 완성 하신 것 같아
다음날 작업 하다가 전체적으로 어떤 기능을 구현해야 하는지 알려드렸다.
(아무래도 내가 낸 주제로 작업하다보니 내가 확실하게 말씀드려야 다들 진행하기 쉬울 것 같았다)
<img src="https://velog.velcdn.com/images/truly_flower/post/e63c24af-36ad-4752-a2d0-81bde9e616e9/image.png" alt="">
(저 스프레드 시트 정리는 또 인공지능의 힘을 빌렸따! 받아오는 API가 두 곳에서 받아오는데, 지역 저장 형태가 하나는 위도 경도로 되어있고, 하나는 지역번호로 되어있어서, 지역 번호별로 위도 경도를 구분해내는데 gpt를 썼다 ㅎㅎ 노가다로 할뻔)
<img src="https://velog.velcdn.com/images/truly_flower/post/2eca46b4-3898-41a6-a7c2-4a4e9334303b/image.png" alt="">
이런식으로 전체적으로 구성을 짜드렸고
그리고나서 저녁에 만나서 얘기해보니 훨씬 효율이 올라간 게 느껴졌고 연결할 부분들이 보였다.
심지어 그 자리에서 연결 부분을 해결 하기도 했다.</p>
<h3 id="8-팀회의의-중요성을-느꼈다">8. 팀회의의 중요성을 느꼈다.</h3>
<p>우리팀은 매일 5시에 회의를 한다. 그러면 다들 어느정도 완성했는지 보이기 시작하는데,
이 완성한 부분을 깃허브에 올린 버전들을 살펴보면서 아 이걸 어디다 어떻게 써야되는구나가 보이고
그러면 내 부분도 완성하기 쉬워진다!
팀원들이 어디까지 완성했는지가 보이면 나도 속도를 내야 한다는 생각이 들게 되고
밤을 새더라도 완성시켜서
어느정도 합을 맞출 수 있게 된다.</p>
<h3 id="9-협업의-힘을-느꼈다">9. 협업의 힘을 느꼈다.</h3>
<p>나랑 같이 백엔드를 맡은 팀원이 계셨는데, 그분이 내가 고민하면서 엄청 길게 짤 뻔했던 코드를 if continue 를 이용해서 짧게 짜주셨다!
보면서 
&#39;아 내가 생각하지 못했던 부분을 다른사람이 볼 수 있고
이래서 협업을 하는구나.&#39;
라고 크게 느꼈다!! 그분은 내가 코드를 이미 잘 짜놔서 자기는 숟가락 얹은 것 밖에 없다고 했지만 진짜 나는 저런 한 줄이 너무너무 크게 느껴졌다!
아직 프론트랑 백이 이어지는 작업을 하지 못했지만, 그건 다른 팀원이 맡아주셨고, 이제 데이터 쌓는 것은 잘 되기 때문에 그부분을 나도 맡아서 도와드릴 것 같다.</p>
<p>그리고 팀장님께서는 깃허브 관리를 맡아주셨는데 굉장히 잘 해주시고,
다들 첨 하다보니 깃허브를 다루지 못하는 팀원들이 많았는데 굉장히 친절하게 잘 알려주신것 같아 보였다.
그리고 각자가 한 프로젝트가 잘 굴러가는지 계속 확인해주신 덕분에
뭔가 순조롭게 굴러갈 수 있었던 것 같다.</p>
<h3 id="10-각자-맡은-역할을-열심히-해준-팀원들께-고마움을-느꼈다">10. 각자 맡은 역할을 열심히 해준 팀원들께 고마움을 느꼈다.</h3>
<p>다들 어렵고 포기하고 싶은 순간도 있었을 텐데 포기하지 않고 계속 하고있는 팀원들을 보면서
나도 포기하고싶은 순간에 포기하지 않고 내가 맡은 기능을 구현해 낼 수 있었던 것같다.</p>
<h1 id="하고싶은-것">하고싶은 것</h1>
<h3 id="1-테이블끼리-연결-관계를-만들고-싶다">1. 테이블끼리 연결 관계를 만들고 싶다.</h3>
<p>1) 참조
이번 프로젝트에서는 테이블끼리 서로 참조하도록 만들지 못했다.
다음번엔 이 참조 부분을 제대로 공부해서 연결관계를 만들고 싶다.
목 금 이렇게 이틀 기간이 남은 상태에서 테이블을 또 잘못 건드렸다가 프로젝트를 망치고 싶지 않아서,</p>
<h3 id="2-프론트를-꾸며보고-싶다">2. 프론트를 꾸며보고 싶다.</h3>
<ul>
<li>4번과 이어진다.
4/24 - 프론트를 꾸몄다! 프론트 구조에 대해 알게되었다.<h3 id="3-다른-많은-기능들도-써보고-싶다">3. 다른 많은 기능들도 써보고 싶다.</h3>
</li>
</ul>
<p>나는 이렇게 하기 위해선 잘 만든 다른 프로젝트를 한번 면밀히 분석해 봐야 할 필요가 있다고 생각한다. 그래서 이번 프로젝트를 끝내고 , 다른 프로젝트를 살펴 본 뒤, 한번 테이블 관계같은 것을 수정해서 보완해 볼 생각이다.</p>
<h3 id="4-자바-스크립트랑-html을-더-공부해보고-싶다">4. 자바 스크립트랑 HTML을 더 공부해보고 싶다.</h3>
<p>아무래도 이번이 첫 프로젝트고 다음 프로젝트 때는 더 많은 기능을 구현한 결과물을 내보고 싶기 때문에 JS와HTML에 대해 더 깊게 공부하고 다음 프로젝트 전까지 혼자 토이프로젝트를 진행해보면서 공부해 볼 것 같다. 
아무래도 코딩을 공부하는 것에는 프로젝트를 직접 해보는 것 만큼 크게 공부되는게 없는 것 같다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[팀프로젝트 1일차 4/15 월]]></title>
            <link>https://velog.io/@truly_flower/%ED%8C%80%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-1%EC%9D%BC%EC%B0%A8-415-%EC%9B%94</link>
            <guid>https://velog.io/@truly_flower/%ED%8C%80%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-1%EC%9D%BC%EC%B0%A8-415-%EC%9B%94</guid>
            <pubDate>Tue, 16 Apr 2024 05:21:03 GMT</pubDate>
            <description><![CDATA[<ol>
<li>깃허브 공동 프로젝트 시작</li>
</ol>
<p>1) 초대 - 이메일로 들어가서 확인 눌러야 오류가 안남
2) 포크 - 포크 후 풀 리퀘스트 까지 확인</p>
<ol start="2">
<li><p>브랜치 만들어서 올리기(안그러면 충돌생김)</p>
</li>
<li><p>장고의 이해, view와 url model의 관계 ,api 이해</p>
</li>
<li><p>table의 삭제, table 있는지 확인(sqlite3로 오류 잡아내기)</p>
</li>
</ol>
<p>4/16 화</p>
<ol start="5">
<li>table 이름 바꾸기</li>
<li>api 불러와서 table에 저장하기</li>
</ol>
<p>오늘 할일 - 다대다 관계 정리 url 두개에서 받아온 정보를 한 테이블에 저장하기</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[팀 프로젝트 0일차]]></title>
            <link>https://velog.io/@truly_flower/%ED%8C%80-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-0%EC%9D%BC%EC%B0%A8</link>
            <guid>https://velog.io/@truly_flower/%ED%8C%80-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-0%EC%9D%BC%EC%B0%A8</guid>
            <pubDate>Mon, 15 Apr 2024 04:30:17 GMT</pubDate>
            <description><![CDATA[<p>회의 일정잡기</p>
<ol>
<li>구글 스프레드 시트를 활용해서 회의 일정을 잡음</li>
<li>다음날 저녁 8시 회의 시작</li>
</ol>
<p>회의</p>
<ol>
<li>주제 정하기 (투표)</li>
<li>팀장 정하기 (사다리 타기)</li>
<li>대략적인 역할 정하기</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[csrf_token]]></title>
            <link>https://velog.io/@truly_flower/csrftoken</link>
            <guid>https://velog.io/@truly_flower/csrftoken</guid>
            <pubDate>Thu, 11 Apr 2024 05:27:55 GMT</pubDate>
            <description><![CDATA[<p>CSRF Attack (Cross Site Request Fogery Attack)
csrf 공격은, 위해한 웹사이트가 POST와 같은 액션을 사용할 때, 인증된 사용자의 인증정보를 무단으로 사용하는 것을 말한다.
이 때문에 사용자는 자신이 의도하지 않은 요청을 하게 된다.</p>
<p>예를 들어, 공격자가 사이트의 게시물에 어떤 사이트의 API를 이용하여 조작된 HTML을 만들면, 인증된 사용자가 그것을 사용하여 자신은 의도치 않았던 행위를 하는 것이다.</p>
<p>CSRF Token
django는 csrf 공격을 막기 위해 csrf token을 사용한다. 사용자가 post 요청이 있는 template을 요청하면, 장고는 cookie에 secret을 보내고, hidden form의 필드 &#39;csrfmiddlewaretoken&#39;에는 serect + mask 한 정보를 랜더링한다.</p>
<p>사용자가 post를 하면, 쿠키와 함께 csrfmiddlewaretoken이 함께 날아간다. django는 이것을 프로세싱하여 쿠키의 serect과 csrfmiddlewaretoken의 프로세싱된 값이 같은지 확인하는 것이다.</p>
<p>같다면 다음 middleware로 진행하고 그렇지 않다면 403에러를 띄우게 된다.</p>
<p>csrf_token이 post의 data 필드값에 필요하기 때문에 django의 서버가 직접 랜더링한 html만이 유효하게 되어 csrf 공격을 막을 수 있게된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[crud]]></title>
            <link>https://velog.io/@truly_flower/crud</link>
            <guid>https://velog.io/@truly_flower/crud</guid>
            <pubDate>Mon, 08 Apr 2024 06:29:08 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/truly_flower/post/34843865-ad0c-4c16-84f5-01b68087e9c4/image.png" alt=""></p>
]]></description>
        </item>
    </channel>
</rss>