<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>ldu_95.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Sat, 23 Sep 2023 05:36:32 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>ldu_95.log</title>
            <url>https://images.velog.io/images/ldu_95/profile/f8a48f58-c20d-4976-b39e-3435d8559c95/52775482.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. ldu_95.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/ldu_95" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Azure VM에서, redis 연결 하기]]></title>
            <link>https://velog.io/@ldu_95/Azure-VM%EC%97%90%EC%84%9C-redis-%EC%97%B0%EA%B2%B0-%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@ldu_95/Azure-VM%EC%97%90%EC%84%9C-redis-%EC%97%B0%EA%B2%B0-%ED%95%98%EA%B8%B0</guid>
            <pubDate>Sat, 23 Sep 2023 05:36:32 GMT</pubDate>
            <description><![CDATA[<p>이번에 일하게된 회사에서는 Azure를 쓴다.</p>
<p>AWS 밖에 안써봐서 생소했지만, 서비스가 다 거기서 거기지 뭐....</p>
<p>프로젝트 구성을 위해, 간단하게 서버를 만들고, 해당 서버에 mysql, redis 를 연결해야했다.</p>
<p><img src="https://velog.velcdn.com/images/ldu_95/post/4f660f4d-b95c-4d64-9712-9802bc1ae908/image.png" alt="">
db Connection Pool 구성</p>
<p><img src="https://velog.velcdn.com/images/ldu_95/post/2329aa02-bdde-4155-a0cf-f8e4c9abeafc/image.png" alt=""></p>
<p>redis 구성</p>
<p>로컬에서 테스트할땐 HOST는 localhost, PORT는 각각 기본 포트인 3306, 6379로 사용했고, 연결 완료 후 테스트까지 잘 완료했다.</p>
<hr>
<p>이후 배포환경에 azure mysql, redis에서 설정된 host와 port로 바꿔주고 실행을 시켰다</p>
<p><img src="https://velog.velcdn.com/images/ldu_95/post/76fe42e6-043a-4eb1-a321-7d788fd63b3e/image.png" alt=""></p>
<p>이런 에러가 발생했다.....</p>
<p>에러 발생지점도 나오지 않고 덜렁 저렇게 코드만...</p>
<p>구글링 결과 tcp 연결 에러로 나온다(타임 아웃과 유사한건가??)</p>
<hr>
<h3 id="예상-원인">예상 원인</h3>
<ol>
<li><p>mysql 연결 에러. 
구글링 했을때 tcp 연결 실패 에러 케이스가 대부분 mysql이었다.
로컬 mysql workbench 에서 ssh연결로 연결했을 때 정상적으로 접속이 되었었고. vm 상에서 <code>mysql -h blahblah -P 3306 -p</code>로 연결했을 떄도 정상적으로 접속이 가능했다. </p>
</li>
<li><p>redis 연결 에러.(범인)
```redis-cli -h blahblah -p 6379`` 명령어로 로컬 환경에서도 연결이 안됐었고, vm에서도 연결이 안됐었다.</p>
</li>
</ol>
<p>azure cache for redis 서비스에서 확인해보니</p>
<p><img src="https://velog.velcdn.com/images/ldu_95/post/df001512-37b8-43e8-8324-d4684093bed0/image.png" alt=""></p>
<p>이런 옵션이.......켜져있었다.....</p>
<p><a href="https://learn.microsoft.com/ko-kr/azure/azure-cache-for-redis/cache-nodejs-get-started">https://learn.microsoft.com/ko-kr/azure/azure-cache-for-redis/cache-nodejs-get-started</a></p>
<p>azure 공식 문서에서 알아보니 redis 접속 시, password 옵션으로 access_key가 필요하다는걸 알았다.</p>
<p><img src="https://velog.velcdn.com/images/ldu_95/post/5494a6bd-9369-46f1-9936-855eced89fe4/image.png" alt=""></p>
<p>access_key를 REDIS_PASSWORD라는 환경 변수에 할당해주고 vm에서 실행을 시켰다!!</p>
<hr>
<p>동작하지 않는다....... 
30분 가량 삽질하다가.... azure 공식 문서에서 답을 찾았다</p>
<p><img src="https://velog.velcdn.com/images/ldu_95/post/d222f908-5567-4f0b-94e1-fd7f9f377880/image.png" alt=""></p>
<p>프로토콜이.... redis가 아닌.... rediss로 되어야했다......... s......</p>
<hr>
<p><img src="https://velog.velcdn.com/images/ldu_95/post/fb18606e-ef59-49da-aa7e-762a7160fe67/image.png" alt=""></p>
<p>개발 환경에 맞춰 실행할 수 있도록 REDIS_PROTOCOL이라는 환경 변수를 만들어주었고 실행시켰더니.. 정상 작동 된다...</p>
<p>결론 : 공식 문서를 잘 읽자.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[final project -day4 ~ day5-]]></title>
            <link>https://velog.io/@ldu_95/final-project-day4-day5-</link>
            <guid>https://velog.io/@ldu_95/final-project-day4-day5-</guid>
            <pubDate>Mon, 19 Jun 2023 04:33:47 GMT</pubDate>
            <description><![CDATA[<h2 id="진행한-것들">진행한 것들</h2>
<hr>
<ul>
<li>AWS 리소스 아키텍처 다이어그램 수정</li>
<li>AWS 리소스 아키텍처 다이어그램 피드백</li>
<li>AWS 리소스 아키텍처 다이어그램 피드백 후 수정</li>
</ul>
<h3 id="--aws-리소스-아키텍처-다이어그램-수정--피드백">- AWS 리소스 아키텍처 다이어그램 수정 &amp; 피드백</h3>
<hr>
<p><img src="https://velog.velcdn.com/images/ldu_95/post/0400f0df-dd2c-4e18-8ef6-0a2b16fdf7af/image.png" alt=""></p>
<p>기존 REST API는 SNS topic발행만 하게하고 Lambda에서 모든 기능이 실행된다고 생각하고 구상했었다....</p>
<p>Lambda와 rds가 통신하기도 하고, 다시 봐도 이해하기 힘든 로직이긴 하다. 너무 기능 분리에 몰두했다보다.</p>
<h3 id="aws-리소스-아키텍처-다이어그램-피드백-후-수정">AWS 리소스 아키텍처 다이어그램 피드백 후 수정</h3>
<hr>
<p><img src="https://velog.velcdn.com/images/ldu_95/post/29b6847a-ebf9-4ff3-92d8-56c283203589/image.png" alt=""></p>
<p>피드백 후 분리된 도메인 내에서 처리가 가능한 기능들은 웹 서버에서 처리하고, 각 도메인 간에 상호 작용이 필요한 부분만 <code>SNS -&gt; SQS -&gt; Lambda -&gt; 웹 서버</code> 구조로 처리하게 만들었다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[final project -day3-]]></title>
            <link>https://velog.io/@ldu_95/final-project-day3-</link>
            <guid>https://velog.io/@ldu_95/final-project-day3-</guid>
            <pubDate>Wed, 14 Jun 2023 13:13:57 GMT</pubDate>
            <description><![CDATA[<h2 id="오늘-진행한-것들">오늘 진행한 것들</h2>
<hr>
<ul>
<li>AWS 리소스 아키텍처 다이어그램 작성</li>
</ul>
<h3 id="aws-리소스-아키텍처-다이어그램">AWS 리소스 아키텍처 다이어그램</h3>
<p><img src="https://velog.velcdn.com/images/ldu_95/post/7e636dd4-aff6-4b0d-bb55-cb5ad1a633a3/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[final project -day2-]]></title>
            <link>https://velog.io/@ldu_95/final-project-day2-</link>
            <guid>https://velog.io/@ldu_95/final-project-day2-</guid>
            <pubDate>Tue, 13 Jun 2023 15:24:28 GMT</pubDate>
            <description><![CDATA[<h2 id="오늘-진행한-것들">오늘 진행한 것들</h2>
<hr>
<ul>
<li>이벤트 스토밍 결과(DDD 구현) 피드백 받기</li>
<li>피드백 후 수정</li>
<li>API 명세서 작성</li>
<li>ERD 작성</li>
</ul>
<h3 id="이벤트-스토밍-결과-및-기능·인프라-요구사항-피드백">이벤트 스토밍 결과 및 기능·인프라 요구사항 피드백</h3>
<hr>
<p>이전에 작성했었던 이벤트 스토밍 결과
<img src="https://velog.velcdn.com/images/ldu_95/post/a11e279e-d86f-4fb8-a213-d7b20990d2f7/image.png" alt=""></p>
<h3 id="피드백">피드백</h3>
<ol>
<li>이벤트 스토밍</li>
</ol>
<p>우리가 작성했던 것들은 DDD라 보기 힘들다. DDD는 조직구조를 반영한다. (ERD랑은 다릅니다)</p>
<ul>
<li>애그리거트가 없다</li>
<li>조직단위 바운디드 컨텍스트가 아니다<ul>
<li>바운디드 컨텍스트라면 배송관리팀, 결제관리팀, 제품관리팀, 시스템관리팀 으로 나누어져있어야 하는 것</li>
</ul>
</li>
</ul>
<ol start="2">
<li>기능·인프라 요구사항 피드백</li>
</ol>
<p>기능·인프라 요구사항들이 너무 방대하다. 주어진 기안 내에 다 하지 못할 뿐더러, 현재 상황에선 손도 못댈 것들이 많다. (PG모듈 같은 것들...)</p>
<p><strong>수정된 DDD</strong>
<img src="https://velog.velcdn.com/images/ldu_95/post/b018e673-45aa-4003-a18b-18d820020588/image.png" alt=""></p>
<p><strong>수정된 기능 요구사항</strong></p>
<ul>
<li>판매자가 크라우드펀딩 제품을 오픈하고 펀딩을 받는다</li>
<li>후원자가 프로젝트에 일정 금액을 펀딩한다</li>
<li>목표 금액이 달성되면, 해당 프로젝트는 성공으로 간주한다 (판매자가 제품을 만들고 배송하는 것은 부차적인 것)</li>
</ul>
<p><strong>수정된 인프라 요구사항</strong></p>
<ul>
<li><p>컨테이너 베이스 구현</p>
</li>
<li><p>데이터베이스를 쓰는데, 목적에 맞게 선정이 필요</p>
<ul>
<li>프로젝트 CRUD: 어떤 종류의 데이터베이스를 써도 상관이 없음</li>
<li>결제 -&gt; 결제 시도 및 결과와 관련한 이벤트 로그가 항상 있어야 한다. (후원자의 트랜잭션, 프로젝트에 쌓인 트랜잭션이 일치할 수 있도록, 최종적 일관성만 확보되면 됨)<ul>
<li>mq가 로그 저장소의 역할도 하니까 고려해보시면 좋을 듯하다</li>
<li>바로 결제시스템을 연결하기보다는 (강결합 x), 일종의 사이버머니(포인트)가 트랜잭션 상에서 왔다갔다 하는게 구현도 편하고, 테스트도 편하고, 컨셉 증명도 편하다. (확장성에도 좋음)</li>
</ul>
</li>
</ul>
</li>
<li><p>가용성 </p>
<ul>
<li>가장 빈번한 트래픽 발생은 어디서 발생할까?: 상품 후원 -&gt; 결제 쪽 데이터베이스에 가용성 확보 전략을 마련해야 할듯하다.</li>
<li>API Server도 이중화 시키고 로드밸런서는 붙여야할듯.</li>
</ul>
</li>
<li><p>보안부분은 아키텍쳐 회의때 진행하기로함.</p>
</li>
<li><p>모니터링</p>
<ul>
<li>무엇을 모니터링할 것인가?<ul>
<li>프로젝트 별 후원 상태</li>
<li>결제 시도 시 실패가 어디에서 발생하는지</li>
<li>4xx 5xx 에러</li>
</ul>
</li>
</ul>
</li>
</ul>
<p><strong>그 외</strong></p>
<ul>
<li>결제는 필연적으로 외부 시스템과 연동이 되어야 하는 것<ul>
<li>트랜잭션 기록은 항상 실패에 대비해 구현해야 하고</li>
<li>외부 시스템의 의존성 문제도 생각해야 한다.</li>
</ul>
</li>
</ul>
<h3 id=""></h3>
<hr>
<p>기존에 생각하고 작성했던 부분들(DDD)에 대한 개념정리가 확실하지 않았었다.
사실 아직도 잘 모르겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[final project -day1-]]></title>
            <link>https://velog.io/@ldu_95/final-project-day1-</link>
            <guid>https://velog.io/@ldu_95/final-project-day1-</guid>
            <pubDate>Mon, 12 Jun 2023 16:10:03 GMT</pubDate>
            <description><![CDATA[<p>코드스테이츠 final project</p>
<h2 id="프로젝트-개요">프로젝트 개요</h2>
<hr>
<h3 id="achievment-goals">Achievment Goals</h3>
<ul>
<li>실무와 가까운 클라우드 아키텍처를 구현할 수 있다(팀)</li>
<li>실무의 커뮤니케이션과 흡사하게 롤플레잉을 통해 의뢰인으로부터 자세한 요구사항을 이끌어낼 수 있다.(팀/개인)</li>
<li>낮선 기술스택과 요구사항에 대해서 스스로 학습하여 적용할 수 있다.(개인)</li>
<li>클라우드 아키텍처에 대한 그림을 그리고 설명할 수 있다. (팀)</li>
<li>구현의 디테일에 대한 질문을 받을 때 답변할 수 있다.(개인)</li>
</ul>
<h3 id="요구사항-구체화">요구사항 구체화</h3>
<hr>
<p>우리 팀이 진행하는 시나리오는 <strong>자유주제 - 컨테이너 기반 시스템</strong>이었다.
간단한 3티어 혹은 2티어 아키텍처를 시스템이 컨테이너 환경에서 실행될 수 있게 하는 인프라를 구현해야한다.</p>
<h3 id="기능-요구사항">기능 요구사항</h3>
<hr>
<ul>
<li>최소 1개의 CRUD 기능을 가진 자유로운 시스템 구성</li>
<li>로직 티어와 데이터 티어는 구분되어야 한다.</li>
</ul>
<h3 id="인프라-요구사항">인프라 요구사항</h3>
<hr>
<ul>
<li>사용되는 애플리케이션들은 <strong>컨테이너</strong>로 구동되어야한다.</li>
<li>시스템 전반에 <strong>가용성</strong>, <strong>내결함성</strong>, <strong>확장성</strong>, <strong>보안성</strong>이 고려된 서비스들이 포함되어야 한다.</li>
<li>하나 이상의 컴퓨팅 유닛에 대한 <strong>CI/CD 파이프라인</strong>이 구성되어야 한다.</li>
<li>시스템 메트릭 또는 저장된 데이터에 대한 하나 이상의 <strong>시각화된 모니터링 시스템</strong>이 구축되어야 한다.</li>
</ul>
<h1 id="오늘-진행한-것들">오늘 진행한 것들</h1>
<hr>
<ul>
<li>진행 시나리오 설정</li>
<li>팀 규칙 결정</li>
<li>프로젝트 유저 스토리 작성</li>
<li>DDD 이벤트 스토밍(진행 중)</li>
</ul>
<h2 id="진행-시나리오--클라우드-펀딩-플랫폼">진행 시나리오 : 클라우드 펀딩 플랫폼</h2>
<hr>
<p>제품 아이디어 기획으로 크라우드 펀딩을 진행하는 예전의 와디즈와 유사하게 진행 중.</p>
<h3 id="기능-요구사항-1">기능 요구사항</h3>
<hr>
<ul>
<li>사용자 등록 및 프로필 관리: 사용자는 플랫폼에 가입하고 프로필을 설정할 수 있어야 합니다.</li>
<li>프로젝트 생성 및 관리: 사용자는 프로젝트를 생성하고 관리할 수 있어야 합니다. 프로젝트에는 제목, 설명, 목표 금액, 기간 등의 정보가 포함될 수 있어야 합니다.</li>
<li>펀딩 및 결제: 사용자는 프로젝트에 펀딩을 할 수 있어야 합니다. 결제는 안전한 방법으로 이루어져야 하며, 다양한 결제 수단을 지원해야 합니다.</li>
<li>프로젝트 업데이트: 프로젝트 창작자는 프로젝트 진행 상황을 업데이트하고 후원자에게 공유할 수 있어야 합니다.</li>
<li>리워드 관리: 프로젝트 창작자는 펀딩에 대한 보답으로 리워드를 제공할 수 있어야 합니다. 사용자는 리워드를 선택하고 받을 수 있어야 합니다.</li>
<li>커뮤니케이션 기능: 창작자와 후원자 사이의 소통을 위한 커뮤니케이션 기능이 필요합니다. 채팅, 댓글, 메시지 등의 기능을 포함할 수 있습니다.</li>
<li>검색 및 탐색 기능: 사용자는 다양한 프로젝트를 검색하고 탐색할 수 있어야 합니다. 카테고리, 인기 프로젝트, 추천 프로젝트 등의 기준으로 프로젝트를 필터링할 수 있어야 합니다.</li>
</ul>
<h3 id="인프라-요구사항-1">인프라 요구사항</h3>
<hr>
<ul>
<li>컨테이너 오케스트레이션 플랫폼: 컨테이너 기반 시스템을 구축하기 위해 Kubernetes, Docker Swarm 등의 컨테이너 오케스트레이션 플랫폼을 사용할 수 있습니다.</li>
<li>데이터베이스: 사용자 정보, 이벤트 정보, 주문 내역 등을 저장하기 위한 데이터베이스가 필요합니다. 관계형 데이터베이스(예: MySQL, PostgreSQL)나 NoSQL 데이터베이스(예: MongoDB, Cassandra)를 선택할 수 있습니다.</li>
<li>웹 서버: 사용자 인터페이스를 제공하기 위한 웹 서버가 필요합니다. Nginx, Apache 등의 웹 서버를 사용할 수 있습니다.</li>
<li>보안: 사용자 정보와 결제 정보를 보호하기 위해 SSL 인증서를 사용하는 HTTPS 통신과 데이터 암호화를 구현해야 합니다.</li>
<li>결제 게이트웨이: 다양한 결제 수단을 지원하기 위해 결제 게이트웨이(예: Stripe, PayPal)를 통합해야 합니다.(보류)</li>
<li>이메일 서비스: 티켓 구매 확인, 알림 등을 위해 이메일 서비스를 사용해야 합니다.</li>
<li>파일 저장소: 이벤트 사진, 티켓 디자인 등의 파일을 저장하고 관리하기 위한 파일 저장소가 필요합니다. AWS S3, Google Cloud Storage 등의 클라우드 기반 파일 저장소를 사용할 수 있습니다.</li>
<li>모니터링 및 로깅: 시스템의 상태를 모니터링하고 로그를 기록하기 위한 모니터링 및 로깅 시스템을 구축해야 합니다. Prometheus, ELK 스택(Elasticsearch, Logstash, Kibana) 등을 사용할 수 있습니다.</li>
</ul>
<h2 id="프로젝트-유저-스토리">프로젝트 유저 스토리</h2>
<hr>
<h3 id="유저">유저</h3>
<hr>
<ul>
<li>서비스 사용자가 서비스를 이용하기 위해 회원 가입버튼을 누다.</li>
<li>서비스 사용자가 서비스를 이용하기위해 로그인버튼을 누른다.</li>
<li>서비스 사용자가 비밀번호를 바꾸기위해 비밀번호 리셋버튼을 누다.</li>
<li>서비스 사용자가 아이디를 찾기위해 이메일을 검색한다(회원 가입시 이메일 작성)</li>
<li>서비스 사용자가 더이상 서비스를 사용하지않기위해 로그아웃버튼을 누른다.</li>
<li>서비스 사용자가 더이상 서비스를 사용하지않기위해 회원탈퇴버튼을 누른다.</li>
<li>서비스 사용자가 회원 정보 변경을 위해 회원정보수정 버튼을 누른다.(유저 페이지)</li>
</ul>
<h3 id="아이디어상품">아이디어(상품)</h3>
<hr>
<ul>
<li>서비스 사용자가 관심있는 아이디어상품을 기억하기위해 즐겨찾기 아이콘을 누른다.</li>
<li>서비스 사용자가 원하는 아이디어 상품을 찾기위해 원하는 아이디어 상품 카테고리/아이디어상품 이름 등을 검색한다. (-&gt; 아이디어 이름, 제작상태랑 후원상태 포함)</li>
<li>서비스 사용자(판매자)가 아이디어 상품을 팔기 위한 후원 받기 위해 아이디어 상품을 생성버튼을 누른다.(등록을 할 때 기입, 카테고리로 나눈 걸 기입)</li>
<li>서비스 사용자가(판매자)가 아이디어 상품 수정을 하기위해 아이디어 상품수정버튼을 누른다 </li>
<li>서비스 사용자가(판매자)가 아이디어 상품을 더이상 후원을받지 않기 위해 아이디어 상품삭제버튼을 누른다.</li>
<li>서비스 사용자가(구매자)가 원하는 아이디어상품의 판매자와 커뮤니케이션 하기위해 댓글을 입력한다.</li>
</ul>
<h3 id="후원">후원</h3>
<hr>
<ul>
<li>서비스 사용자가(구매자)가 원하는 상품을 사기위해 후원버튼을 누른다.</li>
<li>서비스 사용자가(구매자)가 상품을 더이상 사지 않기위해 후원취소버튼을 누른다.</li>
</ul>
<h3 id="결제">결제</h3>
<hr>
<ul>
<li>서비스 사용자(구매자)가 후원을 하기위해 결제방법을 선택한다. (결제방법 생각해보기)</li>
<li>서비스 사용자(구매자)가 카드결제하기위해 카드정보를 입력한다.</li>
<li>서비스 사용자(구매자)가 무통장입금을 하기위해 입금할 은행을 선택한다.</li>
<li>관리자가 구매자의 무통장 입금을 위해 은행정보를 화면에 보여준다..?</li>
</ul>
<h3 id="notification">Notification</h3>
<hr>
<ul>
<li>시스템 상에서 실패한 후원케이스를 구매자에게  알리기위해 후원실패 알림 보낸다.</li>
<li>시스템 상에서 후원한 상품 출고를 알려주기 위해 알림문자를 보낸다..?</li>
<li>시스템 상에서 결제완료확인을 위해 구매자에게 결제완료 이메일을 전송한다.</li>
<li>시스템상에서 결제 실패를 구매자에게 알리기 위해 결제실패 알림 이메일을 전송한다.</li>
<li>시스템상에서 구매자로부터 구매확정을 받기위해 구매확정 알림 이메일 전송한다.</li>
<li>판매자는 상품 출고를 배송업체에게 알리기위해 출고준비 버튼을 누른다.</li>
<li>시스템상에서 판매자가 아이디어를 수정할 시 아이디어상품 구매자에게 수정, 삭제되었다고 알림</li>
</ul>
<h2 id="이벤트-스토밍진행-중">이벤트 스토밍(진행 중)</h2>
<hr>
<p><img src="https://velog.velcdn.com/images/ldu_95/post/19a22c7b-1004-4edd-b397-d7262bf241dd/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Terraform 연습(1)]]></title>
            <link>https://velog.io/@ldu_95/Terraform%EC%97%B0%EC%8A%B5</link>
            <guid>https://velog.io/@ldu_95/Terraform%EC%97%B0%EC%8A%B5</guid>
            <pubDate>Sat, 10 Jun 2023 12:04:33 GMT</pubDate>
            <description><![CDATA[<p>테라폼 홈페이지의 <a href="https://registry.terraform.io/providers/hashicorp/local/latest/docs">Local Provider</a>, <a href="https://registry.terraform.io/providers/hashicorp/aws/latest/docs">AWS provider</a>를 이용해 실습.</p>
<p><img src="https://velog.velcdn.com/images/ldu_95/post/bc6b4073-1ddd-4982-9cb3-a88ad92da988/image.png" alt=""></p>
<h3 id="terraform-init">terraform init</h3>
<p>터미널에서 <code>terraform init</code>명령어를 실행한다.</p>
<p>명령어를 실행하면 <code>.terraform</code>이라는 폴더와 <code>.terraform.lock.hcl</code>이라는 파일이 생성된다.</p>
<p><code>.terraform</code>폴더는 main.tf파일에 명시된 프로바이더나 모듈들의 데이터를 다운로드 받아 보관한다.</p>
<p><code>.terraform.lock.hcl</code>파일은 팀에서 협업을 하거나 CI/CD 파이프라인을 구성할때 필요하다. 해당 워크스페이스에서 사용하는 프로바이더를 확인하고, 버전과 해시를 확인하여 다른 개발자들과 환경을 동일하게 유지하기 위해 사용한다.</p>
<h3 id="로컬-프로바이더-생성">로컬 프로바이더 생성</h3>
<hr>
<p>로컬 프로바이더는 주어진 컨텐츠로 로컬 환경에 파일을 생성한다.</p>
<p><code>main.tf</code>파일을 생성 후 공식 문서 우측 상단에 <strong>USE PROVIDER</strong>를 클릭해 provider 블록을 복사해준다.</p>
<pre><code class="language-tf">terraform {
  required_providers {
    local = {
      source  = &quot;hashicorp/local&quot;
      version = &quot;2.4.0&quot;
    }
  }
}

provider &quot;local&quot; {
  # Configuration options
}</code></pre>
<p>여기서 terraform block은 여러 provider를 사용하거나 특정 버전의 terraform을 요구하는 설정에서 유용하다.</p>
<p>terraform block으로 provider에 대한 정보를 지정하지 않으면 terraform은 기본적으로 최신 버전의 provider를 사용한다.
하지만 최신 버전의 provider는 항상 기존 terraform 코드와 호환되는 것은 아니다. provider의 새 버전에서는 종종 기능이 변경되거나 삭제되기도 하며, 이러한 경우 기존의 terraform 코드가 예상대로 작동하지 않을 수 있다. </p>
<p>그리고 terraform block에 require_providers 블록을 사용하면 terraform 코드의 이식성이 향상된다. 즉 다른 사람이나 다른 시스템에서 해당 코드를 실행할 때 동일한 provider 버전을 사용하도록 상제함으로써 일관성을 보장할 수 있다.</p>
<h3 id="resource">Resource</h3>
<hr>
<p>리소스는 프로바이더를 통해 관리할 수 있는 인프라 리소스이다. 데이터를 쓰는 용도로 사용된다.</p>
<ol>
<li>로컬 파일 리소스 생성<pre><code class="language-tf">resource &quot;local_file&quot; &quot;foo&quot; {
filename = &quot;${path.module}/foo.txt&quot;
content = &quot;hello world!&quot;
}
# 현재 폴더에 &quot;hello world!&quot;라는 내용을 가진 foo.txt파일을 생성하는 코드이다.</code></pre>
</li>
</ol>
<p>위 코드에서 사용된 <code>${}</code>는 terrform에서 inter polation 이라는 문법이다.
문자열 내부에 hcl에서 제공하는 변수나 컨텍스트에 접근하여 값을 가져오기 위함이다.</p>
<p><code>path.module</code>은 해당 파일이 위치한 디렉토리 경로이다.</p>
<ol start="2">
<li>변경 사항 확인
<code>terraform plan</code> 명령어로 내가 작성한 tf파일이 어떤 변경사항을 불러 일으키는지 확인할 수 있다.</li>
</ol>
<blockquote>
<p>Plan: 1 to add, 0 to change, 0 to destroy.</p>
</blockquote>
<p>마지막 출력문으로 어떤 리소스가 추가, 변경, 삭제되었는지 확인할 수 있다.</p>
<ol start="3">
<li>변경 사항 적용
<code>terraform apply</code> 명령어로 변경사항을 적용시킬 수 있다.</li>
</ol>
<p>명령어 실행 후 <code>foo.txt</code>파일과 <code>terraform.tfstate</code>파일이 생성되었다.</p>
<p><code>terraform.tfstate</code>파일은 테라폼 상태 파일이라고 볼 수 있는데, 현재 리소스의 상태를 기록하고 있다.
<code>terraform.tfstate</code>파일을 통해 main.tf를 수정하고 변경할 때 diff 결과를 명확하게 확인할 수 있다.</p>
<h3 id="data-source">Data Source</h3>
<hr>
<p>데이터 소스 리소스를 관리할때 데이터를 참조해야할때 사용한다. 데이터를 읽는 용도로 사용된다.</p>
<p>데이터 소스는 리소스와 다르게 <code>data</code>라는 지시어로 사용된다.</p>
<pre><code class="language-tf">data &quot;local_file&quot; &quot;bar&quot; {
  filename = &quot;${path.module}/bar.txt&quot;
}</code></pre>
<p>위 코드를 작성 후 <code>terraform plan</code>명령어를 실행하면 bar.txt 파일이 없다는 에러가 출력된다.
Data Source는 워크스페이스의 리소스를 사용하기 때문이다.</p>
<pre><code class="language-tf">data &quot;local_file&quot; &quot;foo_value&quot; {
  filename = &quot;${path.module}/foo.txt&quot;
}</code></pre>
<p>올바르게 코드를 작성하고 <code>terraform plan</code> -&gt; <code>terraform apply</code>를 통해 변경사항을 적용시켜 준다. (diff가 없을 것이다)
읽어들인 Data Source는 output 이라는 지시어로 출력할 수 있다.</p>
<pre><code class="language-tf">output &quot;file_foo&quot; {
  value = data.local_file.foo_value
}</code></pre>
<p>tf apply를 해보면, 인프라 상에 변경사항은 없지만, 아래와 같이 Output 섹션에 결과값이 출력된 것을 볼 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/ldu_95/post/8832443a-6191-41f1-bb4d-ea1f8d264bd1/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[모니터링의 목표와 측정 항목]]></title>
            <link>https://velog.io/@ldu_95/%EB%AA%A8%EB%8B%88%ED%84%B0%EB%A7%81%EC%9D%98-%EB%AA%A9%ED%91%9C%EC%99%80-%EC%B8%A1%EC%A0%95-%ED%95%AD%EB%AA%A9</link>
            <guid>https://velog.io/@ldu_95/%EB%AA%A8%EB%8B%88%ED%84%B0%EB%A7%81%EC%9D%98-%EB%AA%A9%ED%91%9C%EC%99%80-%EC%B8%A1%EC%A0%95-%ED%95%AD%EB%AA%A9</guid>
            <pubDate>Thu, 01 Jun 2023 03:25:16 GMT</pubDate>
            <description><![CDATA[<p>CI/CD 파이프라인의 마지막 Stage는 운영이다. 서비스에 생길 수 있는 현황을 파악하고 문제를 모니터링하는 과정으로 대표될 수 있다. 그렇다면 어떤 지표를 수집하고, 어떤 메트릭을 기준으로 삼아야 할까?</p>
<p><img src="https://velog.velcdn.com/images/ldu_95/post/5ce54a86-592c-4cec-aabe-92f4a8a820a4/image.png" alt=""></p>
<blockquote>
<h3 id="메트릭이란">메트릭이란?</h3>
<p>메트릭은 시간에 따라 측정한 결과값이다. 보다 넓은 의미로는 비즈니스 개념을 나타내는 수치 측정을 의미하기도 한다.
</br>
예를 들어, 시간당 CPU 사용률, 연간 순매출과 같이 시간이라는 차원이 함께 적용되어야 한다. 시간이 다른 차원을 기준으로 삼을 수도 있다.</p>
</blockquote>
<h2 id="모니터링의-목표">모니터링의 목표</h2>
<hr>
<p>모니터링을 통해 얻는 것은 다음과 같다.</p>
<ol>
<li>시간을 기준으로 측정되는 주요 메트릭을 최소화하여 고가용성을 달성</li>
<li>사용량을 추적하여, 배포에 앞서 세운 가설을 검증하고 개선</li>
</ol>
<h3 id="구글이-이야기-하는-모니터링의-목표">구글이 이야기 하는 모니터링의 목표</h3>
<hr>
<ul>
<li>장기적인 트렌드 분석<ul>
<li>DB가 얼마만큼의 용량을 차지하며, 얼마나 빨리 용량이 증가하는가?</li>
<li>DAU는 얼마나 빨리 증가하는가?</li>
</ul>
</li>
<li>시간의 경과 및 실험 그룹 간의 비교<ul>
<li>어떤 DB를 썼을때 쿼리가 빠른가?</li>
<li>캐시용 노드를 추가했을 때, 캐시 적중룔이 얼마나 향상되는가?</li>
<li>지난주보다 사이트가 얼마나 느려졌는가?</li>
</ul>
</li>
<li>경고<ul>
<li>인프라의 어떤 부분이 고장 났는가? 혹은 고장 날 수 있는가?</li>
</ul>
</li>
</ul>
<h3 id="측정-메트릭">측정 메트릭</h3>
<hr>
<ul>
<li>캐시 사용률</li>
<li>CPU, Memory</li>
<li>인스턴스의 개수</li>
<li>연결 유지</li>
</ul>
<p>주요 메트릭은 노드에 따라 다르게 측정할 수 있다.</p>
<ul>
<li>단일 노드일 경우 리눅스를 통해 측정할 수 있다.</li>
<li>클러스터 형태일 경우 AWS, Azure, GCP의 콘솔을 통해 이미 제공되고 있는 경우가 많다.
</br></br></br></br><h2 id="모니터링-구분">모니터링 구분</h2>
</li>
</ul>
<hr>
<p>어떠한 서비스가 제대로 작동되는지 확인하려면, 서비스 또는 시스템과 관련한 모든 변수들을 모니터링해야 한다.</p>
<p>하지만 모든 메트릭을 실시간으로 보는 것은 불가능할뿐더러, 너무 많은 메트릭을 모니터링하다 보면, 정말 중요한 신호를 발견하기도 어렵다.</p>
<p>따라서 모니터링을 할 때에는 단계를 구분해서 계층적으로 할 필요가 있다.</p>
<h3 id="블랙박스-모니터링과-화이트박스-모니터링">블랙박스 모니터링과 화이트박스 모니터링</h3>
<hr>
<p>블랙박스와 화이트박스의 구분은 박스를 기준으로 관찰자가 밖에서 바라보느냐, 안에서 바라보느냐의 차이이다. 박스는 애플리케이션이 될 수도 있고, 쿠버네티스 시스템이 될 수도 있다.</p>
<p>블랙박스 모니터링은 CPU/메모리/스토리지 등 인프라 수준의 모니터링에 유용하다. 쿠버네티스 시스템의 경우, 클러스터 정상 작동여부 등 쿠버네티스 컴포넌트 그 자체를 모니터링하는 것도 블랙박스 모니터링에 해당한다. 그러나, 애플리케이션이 왜 오류를 내는지는 알 수 없다.</p>
<p>화이트박스 모니터링은 시스템 내부의 측정 기준에 따라 모니터링하는 것을 의미한다. 예를 들면, HTTP 요청, 500 에러의 발생 횟수, 레이턴시 등이 이에 해당한다. 단순히 현상만 바라보는 것이 아닌, 현상이 발생한 근거를 알 수 있는 모니터링 방식이다.</p>
<h3 id="계층에-따른-모니터링-구분">계층에 따른 모니터링 구분</h3>
<hr>
<p>논리적인 리소스의 집합이 하나의 상위 계층을 만든다. 오케스트레이션 툴이나, AWS의 서비스가 제공하는 계층을 이해하면, 어떤 것을 모니터링해야 하는지 보다 쉽게 파악이 가능하다.</p>
<ul>
<li>쿠버네티스<ul>
<li>노드 &gt; 클러스터 컴포넌트 &gt; 파드</li>
</ul>
</li>
<li>ECS<ul>
<li>클러스터 &gt; 서비스 &gt; 태스크</li>
</ul>
</li>
<li>EC2: 인스턴스에 대한 메트릭만 볼 수 있다.</li>
<li>Lambda: 함수에 대한 메트릭만 볼 수 있다.</li>
</ul>
<h3 id="proxy-서버의-메트릭">Proxy 서버의 메트릭</h3>
<hr>
<p>애플리케이션 서버의 압단에 캐시 서버 혹은 인증서버, 로드 밸런서와 같은 Proxy 서버가 존재한다면, 이는 애플리케이션 서버와는 별도로 모니터링해야 한다. 애플리케이션 서버가 각 노드의 컴퓨팅 자원을 모니터링하는 데에 중점을 뒀다면, Proxy 서버, 그중에서도 HTTP 라우팅을 다루고 있는 서버는 요청 그 자체와 연관된 메트릭을 위주로 모니터링해야 gksek.</p>
<p>HTTP 요청/응답 관련 모니터링 대상은 쿠버네티스의 경우 <strong>인그레스</strong>, AWS 생태계에서는 ALB를 중점으로 보아야 한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Section3 회고]]></title>
            <link>https://velog.io/@ldu_95/Section3-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@ldu_95/Section3-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Tue, 30 May 2023 16:44:58 GMT</pubDate>
            <description><![CDATA[<h2 id="프로젝트의-목표">프로젝트의 목표</h2>
<hr>
<ul>
<li>AWS 클라우드 환경을 기반으로 하는 느슨하게 연결된(loosely coupled) 애플리케이션 아키택처에 대한 이해</li>
<li>SNS, SQS, DQL에 대한 이해</li>
<li>Publisher-Subscriber 패턴과 Producer-Consumer 패턴에 대한 이해</li>
<li>MSA에 대한 이해</li>
</ul>
<h3 id="issues">Issues</h3>
<hr>
<h4 id="1-lambda-함수로-넘어오는-event객체-이해-부족">1. Lambda 함수로 넘어오는 event객체 이해 부족</h4>
<p>Event 객체에서, http 요청으로 받은 body에서 MessageAttributes를 가져오려는데 body에 MessageAttributes가 없다는 에러가 나왔다.</p>
<pre><code class="language-js">const consumer = async (event) =&gt; {

  console.log(event)
  const record = event.Records[0]
  console.log(&#39;body,&#39;,record.body)
  // point 1
  // 여기까진 나옴
  const {MessageAttributes} = record.body
  //에러 발생.
  console.log(&#39;body,&#39;,record.body)
  console.log(&#39;MessageAttributes,&#39;,MessageAttributes)
  const {MessageAttributeProductId} = MessageAttributes
  console.log(&#39;MessageAttributeProductId&#39;,MessageAttributeProductId)
  const sku = getValue(MessageAttributeProductId)    

};</code></pre>
<p>point 부분에서 record.body의 객체에서 내가 필요로 하는 MessageAttributes가 있었지만, 계속 찾을 수 없다는 에러를 뱉어내고 있었다.</p>
<h4 id="해결">해결</h4>
<p>record.body의 값</p>
<pre><code class="language-js">{
    &quot;Type&quot;: &quot;Notification&quot;,
    &quot;MessageId&quot;: &quot;xxxxx-xxxx-xxxx-xxxx-xxxxx&quot;,
    &quot;TopicArn&quot;: &quot;arn:aws:sns:ap-northeast-2:BlahBlah:BlahBlahBlahBlah&quot;,
    &quot;Subject&quot;: &quot;도너츠 재고 부족&quot;,
    &quot;Message&quot;: &quot;도너츠 재고가 없습니다. 제품을 생산해주세요! \n메시지 작성 시각: Thu May 25 2023 06:26:57 GMT+0000 (Coordinated Universal Time)&quot;,
    &quot;Timestamp&quot;: &quot;2023-05-25T06:26:57.595Z&quot;,
    &quot;SignatureVersion&quot;: &quot;1&quot;,
    &quot;Signature&quot;: &quot;BlahBlahBlahBlahBlahBlahBlahBlahBlahBlahBlahBlahBlahBlahBlahBlahBlahBlah&quot;,
    &quot;SigningCertURL&quot;: &quot;https://sns.ap-northeast-2.amazonaws.com/SimpleNotificationService-BlahBlahBlahBlahBlahBlahBlahBlahBlahBlah.pem&quot;,
    &quot;UnsubscribeURL&quot;: &quot;https://sns.ap-northeast-2.amazonaws.com/?Action=Unsubscribe&amp;SubscriptionArn=aBlahBlahBlahBlahBlahBlahBlahBlah&quot;,
    &quot;MessageAttributes&quot;: {
        &quot;MessageAttributeProductId&quot;: {
            &quot;Type&quot;: &quot;String&quot;,
            &quot;Value&quot;: &quot;CP-502101&quot;
        },
        &quot;MessageAttributeFactoryId&quot;: {
            &quot;Type&quot;: &quot;String&quot;,
            &quot;Value&quot;: &quot;xxxxx-xxxx-xxxx-xxxx-xxxxxxxx&quot;
        }
    }
}</code></pre>
<p>위 값처럼 JSON 객체가 직렬화 되어있었다.</p>
<pre><code class="language-js">
  const record = event.Records[0]
  const {MessageAttributes} = JSON.parse(record.body)
  const {MessageAttributeProductId} = MessageAttributes
  const sku = getValue(MessageAttributeProductId)    </code></pre>
<p><strong>JSON.parse(record.body)</strong> 를 사용하여 해결하였다.</p>
<h4 id="2-lambda-권한-문제">2. Lambda 권한 문제</h4>
<p>serverless.yml 작성 후 serverless deploy로 배포 시도 중 lambda에서 </p>
<ul>
<li>SQS ReceiveMessage</li>
<li>SQS DeleteMessage</li>
<li>SQS GetQueueAttributes </li>
</ul>
<p>관련 권한이 없어 생성하지 못하는 에러가 발생.</p>
<h4 id="해결-1">해결</h4>
<p>IAM -&gt; 역할 -&gt; 생성하려는 LambdaRole -&gt; 권한 추가</p>
<pre><code> &quot;sqs:ReceiveMessage&quot;,
 &quot;sqs:DeleteMessage&quot;,
 &quot;sqs:GetQueueAttributes&quot;</code></pre><p>위 권한 추가 후 정상실행.</p>
<h3 id="배운-점">배운 점</h3>
<p>에러 핸들링으로 배운 점은 아니지만 </p>
<ul>
<li>MSA로 아키텍쳐 구성할때 도메인은 SQS를 기준으로 나눈다.</li>
<li>SQS를 써야하는 이유는 영속성 즉, 느슨한 연결을 위한 연결다리의 역할과 메시지가 전달되는 다음 리소스에 에러가 발생해도 이전 리소스에서 전달받은 메시지를 SQS가 가지고 있어 내구성 있는 서비스를 구성할 수 있다.</li>
<li>Publisher-Subscriber 패턴과 Producer-Consumer 패턴에 대한 이해<ul>
<li>(API-Gateway -&gt; SNS(Publisher))(Producer) -&gt; SQS(Subscriber) -&gt; Lambda(Consumer)</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[쿠버네티스 (1)]]></title>
            <link>https://velog.io/@ldu_95/%EC%BF%A0%EB%B2%84%EB%84%A4%ED%8B%B0%EC%8A%A4-1</link>
            <guid>https://velog.io/@ldu_95/%EC%BF%A0%EB%B2%84%EB%84%A4%ED%8B%B0%EC%8A%A4-1</guid>
            <pubDate>Sun, 21 May 2023 07:59:50 GMT</pubDate>
            <description><![CDATA[<p>쿠버네티스는 다량의 컨테이너를 하나의 물리적인 서버에 배치하여 이를 사용하듯 관리해주는 역할을 한다.</p>
<p>쿠버네티스의 영역은 크게 노드를 하나로 묶는 클러스터를 관리하는 Control Plane 영역과 흩어져 있는 각 노드를 관리하는 노드 영역으로 나눌 수 있다.</p>
<p>K8s라고도 한다.</p>
<h2 id="k8s-클러스터-설계-원칙">K8s 클러스터 설계 원칙</h2>
<p>K8s 클러스터가 갖춰야 할 특성은 다음과 같다.</p>
<ul>
<li>보안성: 최신 보안 모범 사례를 따라야 한다.</li>
<li>사용 편이성: 몇 가지 간단한 며 ㅇ령으로 작동할 수 있어야 한다.</li>
<li>확장 가능성: 하나의 제공업체만을 선호해서는 안 되고 구성 파일을 통해 사용자 정의를 할 수 있어야 한다.</li>
</ul>
<h2 id="k8s-구성-요소">K8s 구성 요소</h2>
<p>작동 중인 K8s 배포를 클러스터라고 한다. K8s 클러스터는 Control Plane과 Node 2개 부분으로 시각화할 수 있다. 
각 노드 자체는 Linux환경이며 물리 또는 가상 머신일 수 있다. </p>
<p><img src="https://velog.velcdn.com/images/ldu_95/post/09b68955-45b5-42a2-9e4d-dd3e59a96244/image.png" alt=""></p>
<h3 id="control-plane">Control Plane</h3>
<p>Control Plane는 클러스터에 관한 결정을 내리고 클러스터 이벤트를 감지하며 반응한다. Control Plane은 클러스터 내 어떠한 머신에서라도 동작할 수 있다.</p>
<h4 id="component">Component</h4>
<ul>
<li><p>kube-apiserver: K8s의 모든 컴포넌트의 통신을 담당한다.</p>
</li>
<li><p>etcd: 모든 클러스터 데이터를 담는 K8s 뒷단의 저장소로 사용되는 키-밸류 저장소이다.</p>
</li>
<li><p>kube-scheduler: 노드가 배정되지 않은 새로 생성된 파드를 감지하고, 실행할 노드를 선택하는 컴포넌트이다.</p>
</li>
<li><p>kube-controller-manager: 컨트롤러를 구동하는 컴포넌트이다. 종류로는 노드 컨트롤러, 레플리케이션 컨트롤러, 엔드포인트 컨트롤러, 서비드 어카운트, 토큰 컨트롤러 등이 있다.</p>
</li>
</ul>
<h3 id="node">Node</h3>
<p>K8s클러스터는 컨테이너화된 애플리케이션을 실행하는 Node라는 워커 머신의 집합이다.</p>
<p>워커 노드는 애플리케이션의 구성요소인 Pod를 호스트한다.</p>
<pre><code class="language-bash">minikube start --nodes=3</code></pre>
<p>위 명령어를 통해 여러개의 노드를 구성할 수 있다.</p>
<p>여러 개의 노드를 만들면, 첫 번째는 master, 나머지 두 개의 노드는 worker 노드로 구성된다. 
여러 개의 노드를 구성할 경우, 워커 노드에는 실제로 실행되는 애플리케이션을 배치하며, 마스터 노드는 클러스터 관리 그 자체에 집중하게 한다.</p>
<h4 id="component-1">Component</h4>
<ul>
<li><p>kubelet: 클러스터의 각 노드에서 실행되는 에이전트이다. kubelet은 파드에서 컨테이너가 확실하게 동작하도록 관리한다.</p>
</li>
<li><p>kube-proxy: 클러스터의 각 노드에서 실행되는 네트워크 프록시로, K8s 서비스 개념의 구현부이다. 또한 노드의 네트워크 규칙을 유지, 관리한다. 이 네트워크 규칙이 내부 네트워크 세션이나 클러스터 바깥에서 Pod로 네트워크 통신을 할 수 있도록 해준다.</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Terraform]]></title>
            <link>https://velog.io/@ldu_95/Terraform</link>
            <guid>https://velog.io/@ldu_95/Terraform</guid>
            <pubDate>Sat, 13 May 2023 08:48:47 GMT</pubDate>
            <description><![CDATA[<p><a href="https://seay0.github.io/Infrastructure-as-Code-TIL/">IaC</a> 도구를 사용하면 GUI를 통하지 않고 구성 파일을 사용하여 를 안전하고 일관되며 반복 가능한 방식으로 빌드, 변경 및 관리할 수 있게 해준다.</p>
<p>Terraform은 IaC 도구이며, 이 도구를 사용하면 사람이 읽기 쉬운 선언적 구성 파일에서 리소스와 인프라를 정의할 수 있으며 인프라의 라이프사이클을 관리할 수 있다.</p>
<h3 id="terraform의-장점">Terraform의 장점</h3>
<ul>
<li>여러 클라우드 플랫폼에서 인프라를 관리할 수 있다.</li>
<li>사람이 읽기 쉬운 구성 언어를 사용하면 인프라 코드를 빠르게 작성할 수 있다.</li>
<li>Terraform의 state를 사용하여 배포 상태에서 리소스 변경 내용을 추적할 수 있습니다</li>
<li>configuration을 버전 관리 시스템에 커밋하여 인프라에 대한 협업을 안전하게 진행할 수 있습니다</li>
</ul>
<h3 id="terraform의-특징">Terraform의 특징</h3>
<h3 id="모든-인프라-관리">모든 인프라 관리</h3>
<p>Terraform의 프로바이더는 Terraform이 API를 통해 클라우드 플래솦ㅁ이나 다른 서비스와 상호 작용할 수 있게 해준다.
이미 사용 중인 플랫폼이나 서비스에 대한 프로바이더는 Terraform레지스트리에서 찾아볼 수 있다(AWS, Azure, GCP...).</p>
<hr>
<h3 id="배포-워크플로우-표준화">배포 워크플로우 표준화</h3>
<p>프로바이더는 인프라 개별 단위를 정의한다(EC2, VPC...). 서로 다른 프로바이더의 리소스를 모듈이라고 불리는 재사용 가능한 Terraform구성으로 조합할 수 있고, 일관된 언어와 워크플로우를 관리할 수 있다.</p>
<p>Terraform의 구성 언어는 선언적으로, 인프라의 원하는 최종 state를 설명해주고, 절차적 프로그래밍 언어와 다르게 단계별 지시사항을 요구하지 않는다.</p>
<p>Terraform 프로바이더는 리소스 간 의존성을 자동으로 계산해서 올바른 순서로 생성하거나 제거할 수 있게 해준다.</p>
<p><img src="https://velog.velcdn.com/images/ldu_95/post/9c480dd6-5f43-44ed-8ed0-ff1bf325ed73/image.png" alt=""></p>
<h4 id="테라폼의-배포-워크-플로우">테라폼의 배포 워크 플로우</h4>
<ul>
<li>scope - 프로젝트에 필요한 인프라 파악.</li>
<li>author - 인프라 구송 작성.</li>
<li>initialize - 인프라 관리를 위해 Terraform 플러그인(프로바이더)을 설치.</li>
<li>plan - Terraform이 변경될 내용을 미리 살펴본다.</br>
</li>
</ul>
<hr>
<h3 id="인프라-추적">인프라 추적</h3>
<ul>
<li>Terraform은 state 파일에서 실제 인프라를 추적한다. </li>
<li>Terraform은 state 파일을 사용하여 구성에 맞게 인프라에 적용할 변경 사항을 결정한다.</br>
</li>
</ul>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[프로그래머스 - 영어 끝말잇기]]></title>
            <link>https://velog.io/@ldu_95/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%98%81%EC%96%B4-%EB%81%9D%EB%A7%90%EC%9E%87%EA%B8%B0</link>
            <guid>https://velog.io/@ldu_95/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%98%81%EC%96%B4-%EB%81%9D%EB%A7%90%EC%9E%87%EA%B8%B0</guid>
            <pubDate>Mon, 08 May 2023 15:54:54 GMT</pubDate>
            <description><![CDATA[<h3 id="1-설계-로직">1. 설계 로직</h3>
<ul>
<li><p>사용된 단어를 담는 배열(usedWords)과, 직전 단어를 (beforeWord)담을 변수를 선언</p>
</li>
<li><p>문자를 담은 배열을 순회하며 이전에 사용된 단어들과 직전 단어를 비교.</p>
<ol>
<li>첫 번째 단어일 경우 usedWords에 단어를 추가하고, beforeWord에 단어를 할당한다.<ol start="2">
<li>현재 단어가 usedWords에 있고, 현재 단어의 첫 번째 알파벳과 직전 단어의 마지막 알파벳이 일치하지 않을 경우(끝말잇기 실패), [실패한 사람의 번호, 차례]를 담는 배열을 반환한다.</li>
</ol>
</li>
</ol>
<ul>
<li>실행 횟수 % n -&gt; 실패한 사람의 번호, 0일시 n<ul>
<li>math.ceil(실행 횟수/n) -&gt; 차례</li>
</ul>
</li>
</ul>
<ol start="3">
<li>현재 단어가 usedWords에 없고 현재 단어의 첫 번째 알파벳과 직전 단어의 마지막 알파벳이 일치할 경우(끝말잇기 성공), usedWords에 현재 단어를 추가하고, beforeWord에 현재를 할당한다.</li>
</ol>
</li>
</ul>
<h3 id="2-코드">2. 코드</h3>
<pre><code class="language-python">import math
def solution(n, words):
    usedWords = []
    beforeWord =&quot;&quot;
    index = 0

    while 1:        
        if index==0:
            usedWords.append(words[index])
            beforeWord =words[index]  
            index = index+1
            continue
        elif len(words) == index:
            return [0,0]


        curWord = words[index]   
        if usedWords.count(curWord)!=0 or beforeWord[-1] !=curWord[0]:       
            cnt = index+1
            num = n if cnt%n ==0 else cnt%n
            turn = math.ceil(cnt/n)            
            return [num,turn]
        else:
            usedWords.append(curWord)
            beforeWord =curWord
            index = index+1


    return                          </code></pre>
<h3 id="3-후기">3. 후기</h3>
<p>처음 python으로 풀어본 알고리즘이라 전체적으로 미숙했던 부분이 많았던 것 같다. </p>
<p>익숙해지는 과정이 필요하다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[YAML]]></title>
            <link>https://velog.io/@ldu_95/YAML</link>
            <guid>https://velog.io/@ldu_95/YAML</guid>
            <pubDate>Sun, 30 Apr 2023 15:56:59 GMT</pubDate>
            <description><![CDATA[<p>YAML은 구조를 가진 데이터 표현 양식의 한 종류이다.</p>
<p>YAML은 최근 들어 많이 활용되고 있는 데이터 형식이며, 사람이 읽고 이해하기 쉬운 형태를 가지고 있다.</p>
<p>확장자는 .yml 또는 .yaml을 사용한다.</p>
<h2 id="yaml-문법">YAML 문법</h2>
<hr>
<h3 id="데이터-정의">데이터 정의</h3>
<p>YAML은 기본적으로 데이터를 정의할 때, key:value형태로 데이터를 정의한다.</p>
<p>이때 <code>:</code> 뒤에는 키와 값을 구분하기 위해 반드시 공백문자가 있어야 한다.</p>
<p>데이터 타입으로는 <code>Number</code>, <code>String</code>, <code>Boolean</code>이 있으며, 문자열에 <code>\n</code>, <code>@</code> 등의 특수 문자가 포함된 경우에만 <code>&quot; &quot;</code>를 사용하여 작성한다.</p>
<pre><code class="language-yml">#주석
Name: DongWook
Age: </code></pre>
<h3 id="arraylists">Array/Lists</h3>
<p>배열이나 리스트의 구조를 표현할땐 <code>-</code>를 사용한다.
<code>-</code>는 배열의 한 요소를 가리킨다.</p>
<pre><code class="language-yml">Fruits:
    - Orange
    - Apple
    - Banana
Vegetables:
    - Carrot
    - Lettuce</code></pre>
<pre><code class="language-js">{
    Fruits : [&quot;Orange&quot;,&quot;Apple&quot;,&quot;Banana&quot;],
    Vegetables:[&quot;Carrot&quot;,&quot;Lettuce&quot;]
}</code></pre>
<h3 id="dictionary-map">Dictionary/ Map</h3>
<p>계층 구조를 표현하고 싶은 경우, 기본적으로 2칸 혹은 4칸의 들여 쓰기를 사용한다. 들여 쓰기를 사용할 때, 각 아이템에 대해서 꼭 같은 수의 공백문자를 사용하여 들여 쓰기를 해야 한다.</p>
<pre><code class="language-yml">Fruits:
    Name: Pear
    Quantitiy: 5
    Origin: Naju
Vegetables:
    Name: Garic
    Quantitiy: 3
    Origin: Uiseong</code></pre>
<h3 id="multi-lines">Multi-lines</h3>
<p>값으로 여러 행의 문장을 작성할 때 <code>\n</code>,<code>&gt;</code>,<code>|</code>을 사용한다.</p>
<pre><code class="language-yml">     example: &quot;this is multiline string \n and this is nextline \n and nextline \n&quot;</code></pre>
<p><code>&gt;</code> 문자는 한 줄을 모두 비웠을 때만 줄 바꿈으로 인식을 하고, 그냥 줄 바꿈을 할 때에는 공백문자로 인식한다.</p>
<pre><code class="language-yaml">example: &gt;
    this is multiline string
    and this is nextline
    and next

example2: &gt;
  this is multiline string 

  and this is nextline 

  and nextline</code></pre>
<p><code>|</code> 문자는 모든 줄 바꿈을 인식하며, 마지막 문장의 끝도 마찬가지로 줄 바꿈으로 인식한다.</p>
<pre><code class="language-yml">example1: |
  this is multiline string 
  and this is nextline 
  and nextline</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[IaC, 형상 관리, 이미지 빌드]]></title>
            <link>https://velog.io/@ldu_95/IaC</link>
            <guid>https://velog.io/@ldu_95/IaC</guid>
            <pubDate>Sun, 30 Apr 2023 14:32:37 GMT</pubDate>
            <description><![CDATA[<h3 id="iacinfrastructure-as-code">IaC(Infrastructure as Code)</h3>
<p>네트워크, 로드밸런서, 저장소, 서버 등의 인프라 자원을 수동 술정이 아닌 코드를 이용하여 프로비저닝하고 관리하는 것</p>
<p>대표적인 IaC 도구로 Terraform, CloudFormation, Pulumi, Azure Arm Template 등이 있다.</p>
<h3 id="형상-관리configuration-management">형상 관리(Configuration Management)</h3>
<hr>
<p>서버 운영체제 상에 필요한 소프트웨어를 설치하고 원하는 설정으로 관리하는 것, CaC(Configuration as Code)라고도 불림</p>
<h3 id="이미지-빌드image-build">이미지 빌드(Image Build)</h3>
<hr>
<p>AWS EC2, VMware, VirtualBox, Docker 등 여러 플랫폼에서 재사용 가능한 머신 이미지를 빌드하는 것
대표적인 이미지 빌더로 패커(Packer), AWS EC2 Image Builder 등이 있음.</p>
<h2 id="코드로-관리한다는-것-as-code">코드로 관리한다는 것(... as Code)</h2>
<hr>
<ul>
<li><h3 id="사람이-수동으로-처리하는-것을-코드로-작성하여-관리">사람이 수동으로 처리하는 것을 코드로 작성하여 관리</h3>
<ul>
<li>휴먼 에러 방지</li>
<li>재사용성</li>
<li>일관성</li>
</ul>
</li>
<li><h3 id="소프트웨어-개발처럼-git과-같은-버전-관리-시스템vcs-활용-가능">소프트웨어 개발처럼 Git과 같은 버전 관리 시스템(VCS) 활용 가능</h3>
<ul>
<li>코드 리뷰 가능</li>
<li>변경내용 추적 가능</li>
<li>버전 관리</li>
<li>협업</li>
</ul>
</li>
</ul>
<p>코드가 어떻게 관리되느냐에 따라 <strong>선언형 설정(Declartive Configuration)과 절차형 설정(Imperative Configuration)</strong>으로 분류할 수 있다.</p>
<h3 id="선언형-설정">선언형 설정</h3>
<p>선언형 설정에서는, 우리가 워나는 시스템의 최종 상태에 대해 &#39;선언&#39;한다. 이를 통해, 시스템은 최종 상태를 달성하는 데 필요한 단계를 자체적으로 결정하고 수행할 수 있다.</p>
<p>선언형 설정은 코드의 명확성과 유지 관리 용이성을 높이며, 사이드 이펙트를 최소화하는 데 효과적이다.</p>
<p>Terraform, Kubernetes, Ansible이 이에 해당한다.</p>
<h3 id="절차형-설정">절차형 설정</h3>
<p>시스템에게 상태를 변경하는 방법에 대한 명령을 &#39;지시&#39;한다. 이 경우, 명확한 단계와 절차를 제공해야하며, &quot;어떻게&quot;이러한 상태를 달성할 것인지를 지시한다. 절차형 설정은 세부적인 제어와 특정 동작에 대한 완전한 통제를 가능하게 한다.</p>
<p>Shell scripts, Python, JavaScript 등의 일반적인 프로그래밍 언어들, Chef와 Puppet과 같은 관리 도구들이 이에 해당한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CDN]]></title>
            <link>https://velog.io/@ldu_95/CDN</link>
            <guid>https://velog.io/@ldu_95/CDN</guid>
            <pubDate>Sat, 22 Apr 2023 12:57:56 GMT</pubDate>
            <description><![CDATA[<h3 id="content-delivery-networkcdn">Content Delivery Network(CDN)</h3>
<p>컨텐츠를 좀더 빠르고 효율적으로 제공하기 위해 등장한 서비스</p>
<hr>
<h3 id="cdn의-특징">CDN의 특징</h3>
<ul>
<li>원복을 복사하여 저장할 여러개의 캐시 서버로 구성</li>
<li>컨텐츠를 요청받은 경우 데이터를 전달하기 가장 유리한 캐시 서버에서 관련 콘텐츠를 제공한다.<ul>
<li>제공할 컨텐츠를 가지고 있으며 위치상으로 가장 가까운 캐시 서버가 우선순위를 가짐.</li>
</ul>
</li>
</ul>
<hr>
<h3 id="컨텐츠-종류">컨텐츠 종류</h3>
<h4 id="정적-컨텐츠">정적 컨텐츠</h4>
<p>내용이 거의 변하지 않는 컨텐츠</p>
<ol>
<li>HTML 파일, 동영상과 같은 컨텐츠.</li>
<li>변화가 없는 컨텐츠.</li>
<li>개인화되지 않은 대중적인 컨텐츠.</li>
</ol>
<p>위와 같은 컨텐츠들은 CDN의 캐시 서버에 저장하기 적합하다.</p>
<h4 id="동적-컨텐츠">동적 컨텐츠</h4>
<p>접속할때 마다 내용이 바뀌거나 사용자 마다 다른 내용을 보여주는 컨텐츠.</p>
<ol>
<li>위치, IP주소, 사용시간 관련 컨텐츠.</li>
<li>사용자가 접근할때 마다 내용이 달라지는 컨텐츠.</li>
<li>카드 번호, 전화번호등 개인화된 정보 관련 컨텐츠.</li>
</ol>
<p>컨텐츠가 바뀔때 마다 캐시 서버에 바뀐 컨텐츠가 전파되어야 함</p>
<hr>
<h3 id="cdn의-이점">CDN의 이점</h3>
<p>1.DDoS공격에 대해 어느정도 대응이 가능<br>    &nbsp;&nbsp;&nbsp;&nbsp;- 지리적으로 가까운 다른 서버에서 컨텐츠 제공</p>
<p>2.로딩속도 감소로 인한 사용자 경험 향상
3.트래픽 분산으로 인한 트래픽 관련 비용 절감.
    &nbsp;&nbsp;&nbsp;&nbsp;- 서버 분산으로 지역에 맞게 서버의 성능과 인터넷의 성능을 낮춘다 해도 무리 없이 서비스 제공 가능.
    &nbsp;&nbsp;&nbsp;&nbsp;- 외국에 있는 사용자들의 로딩 시간을 단축가능.</p>
<hr>
<h3 id="네트워크-구성-방법">네트워크 구성 방법</h3>
<h4 id="scattered방식">Scattered방식</h4>
<ol>
<li>세계 곳곳에 최대한 많은 캐시 서버를 제공.    </li>
<li>낮은 수용량의 데이터 센터 및 캐시 서버.</li>
<li>매우 높은 관리비용 및 사용자 요금.</li>
<li>연결 수요가 적은 지역 대상으로 적절한 방식.</li>
</ol>
<h4 id="consolidated방식">Consolidated방식</h4>
<ol>
<li>다수의 고성능 서버로 통합하여 운용하는 방식</li>
<li>응답시간 증가. 하지만 관리 및 유지 비용이 낮아짐.</li>
<li>연결 수요가 많은 지역 대상으로 적절한 방식.</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[NoSQL]]></title>
            <link>https://velog.io/@ldu_95/NoSQL</link>
            <guid>https://velog.io/@ldu_95/NoSQL</guid>
            <pubDate>Fri, 30 Jul 2021 04:32:46 GMT</pubDate>
            <description><![CDATA[<h1 id="nosql이란">NoSQL이란?</h1>
<p>NoSQL 은 매우 넓은 범위에서 사용하는 용어로, 관계형 테이블의 방법을 사용하지 않는 데이터 저장소를 
뜻한다.</p>
<p>NoSQL 데이터를 행과 열이 아닌, 체계적인 방식으로 저장한다. </p>
<h2 id="엇떨때-사용">엇떨때 사용?</h2>
<ol>
<li>비구조적인 대용량의 데이터를 저장하는 경우</li>
</ol>
<ul>
<li>NoSQL 데이터베이스는 관계에 중점을 둔 SQL 데이터베이스보다 자유로운 형태로 데이터를 저장할 수 있으므로 필요에 따라 새로운 데이터 유형을 추가할 수 있다.</li>
<li>SW 개발에 정형화되지 않은 많은 양의 데이터가 필요할 경우, NoSQL이 효율적일 수 있다.
(비정형 데이터 저장에 효율적)</li>
</ul>
<ol start="2">
<li><p>클라우드 컴퓨팅 및 저장공간을 최대한 활용하는 경우
NoSQL 데이터베이스는 데이터베이스를 클라우드 기반으로 쉽게 분리 할 수 있도록 지원하며,
저장공간을 효율적으로 사용한다. 
시스템이 커지면서 DB를 증설해야 하는 시점이 오면, SQL 데이터베이스에서는 수직적 확장의 형태로 DB를 증설한다.
수직적으로 확장된 DB는 관리가 어려워질 수 있는데에 반해, NoSQL은 수평적 확장의 형태로 증설하므로, 이론상 무한대로 서버를 계속 분산시켜 DB를 증설할 수 있다.</p>
</li>
<li><p>빠르게 서비스를 구축하고 데이터 구조를 자주 업데이트 하는 경우
NoSQL 데이터베이스의 경우 스키마를 미리 준비할 필요가 없어서, 개발을 빠르게 해야하는 경우에 매우 적합하다.</p>
</li>
</ol>
<blockquote>
<p>ACID 를 지켜야 할땐  RDB 아니면 NoSQL을 쓰자</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[렉시컬 스코프, 클로저]]></title>
            <link>https://velog.io/@ldu_95/%EB%A0%89%EC%8B%9C%EC%BB%AC-%EC%8A%A4%EC%BD%94%ED%94%84-%ED%81%B4%EB%A1%9C%EC%A0%80</link>
            <guid>https://velog.io/@ldu_95/%EB%A0%89%EC%8B%9C%EC%BB%AC-%EC%8A%A4%EC%BD%94%ED%94%84-%ED%81%B4%EB%A1%9C%EC%A0%80</guid>
            <pubDate>Fri, 16 Jul 2021 14:22:02 GMT</pubDate>
            <description><![CDATA[<h2 id="렉시컬-스코프란">렉시컬 스코프란?</h2>
<p>렉시컬 스코프는 JS의 특별한 개념이 아니라 스코프를 결정하는 방법론? 중 하나이다.</p>
<ol>
<li>식별자를 어디서 호출하였는지에 따라 상위 스코프를 결정하는 방법.</li>
<li>식별자를 어디서 선언하였는지에 따라 상위 스코프를 결정하는 방법.</li>
</ol>
<p>첫 번째 방식을 동적 스코프(Dynamic scope)라 하고,
두 번째 방식을 렉시컬 스코프(Lexical scope) 또는 정적 스코프(Static scope)라 한다.</p>
<p>JS를 비롯한 대부분의 프로그래밍 언어는 두 번째 방식을 따른다고 한다.</p>
<p>JS는 렉시컬 스코프를 따르므로 함수를 선언한 시점에 상위 스코프가 결정된다.
함수를 어디에서 호출하였는지는 스코프 결정에 아무런 의미를 주지 않는다.</p>
<pre><code class="language-js">let name = &#39;이동욱&#39;;

function a() {
  let name = &#39;이동훅&#39;
  bar();
}

function b() {
  console.log(x);
}

a(); // ?
b(); // ?
</code></pre>
<p>위 예제 코드의 실행 결과는 어떻게 될까?</p>
<pre><code class="language-js">a() // 이동욱
b() // 이동욱</code></pre>
<p>둘 다 같은 이동욱
즉, 전역 스코프의 name 변수를 참조하여 출력한다.</p>
<h2 id="클로저">클로저</h2>
<p>클로저 역시 JS 고유의 개념이 아니라 함수를 일급 객체로 취급하는 함수형 프로그래밍 언어에서 사용되는 중요한 특성이다.</p>
<p>MDN 은 클로저에대해 아래와 같이 정의한다.</p>
<blockquote>
<p>클로저는 함수와 함수가 선언된 어휘적 환경(Lexical environment)의 조합이다. 클로저를 이해하려면 자바스크립트가 어떻게 변수의 유효범위를 지정하는지(Lexical scoping)를 먼저 이해해야 한다.</p>
</blockquote>
<p>머선 말인지 모르겠다.. 예제로 한번 살펴보자.</p>
<pre><code class="language-js">let name= &#39;이동욱&#39;

const outer=()=&gt;{
    let name =&#39;이동훅&#39;
    const inner=()=&gt;{console.log(name)}
    return inner
}

let inner = outer() 
inner()// &#39;이동욱&#39;</code></pre>
<p>위 에제에서 outer는 내부함수 inner를 반환하고 생을 마감했다.
즉, 함수 outer는 실행된 이후 콜스택에서 제거되었으므로 함수 outer의 name 또한 더이상 유효하지 않게 되어 변수 name에 접근할 수 있는 방법은 없을듯하다</p>
<p>하지만 위 코드의 실행 결과는 변수 name값인 &#39;이동욱&#39; 이다.</p>
<p>이처럼 자신을 포함하고 있는 외부함수보다 내부함수가 더 오래 유지되는 경우, 외부 함수 밖에서 내부함수가 호출되더라도 외부함수의 지역변수에 접근할 수 있는 함수를 클로저라고 부른다.</p>
<p>다시 MDN 정의를 살펴보자.</p>
<blockquote>
<p>클로저는 <a href="A">함수</a>와 <a href="B">함수가 선언된 어휘적 환경(Lexical environment)</a>의 조합이다. </p>
</blockquote>
<p>위 정의에서 &quot;함수&quot;A 는 반환된 내부함수를 의미하고, &quot;함수가 선언된 어휘적 환경&quot;B는 내부 함수가 선언됐을 때의 스코프를 의미한다.
즉, 클로저는 <strong>반환된 내부함수가 자신이 선언됐을 떄의 환경(Lexical environment)인 스코프를 기억하여 자신이 선언됐을 때의 스코프 밖에서 호출되어도 그 스코프에 접근할 수 있는 함수</strong>를 말한다.</p>
<p>조금 더 간단히 하면 <strong>클로저는 자신이 생성될 때의 스코프를 기억하는 함수</strong> 라고 할 수 있다</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[스코프]]></title>
            <link>https://velog.io/@ldu_95/%EC%8A%A4%EC%BD%94%ED%94%84</link>
            <guid>https://velog.io/@ldu_95/%EC%8A%A4%EC%BD%94%ED%94%84</guid>
            <pubDate>Sun, 11 Jul 2021 06:36:01 GMT</pubDate>
            <description><![CDATA[<p>스코프(Scope , 유효범위)는 JS 에서만 쓰이는 개념이 아닌 모든 프로그래밍 언어의 기본적인 개념으로 확실한 이해가 필요하다.</p>
<p>*<em>스코프는 참조 대상 식별자(identifier, 변수, 함수의 이름과 같이 어떠한 대상을 다른 대상과 구분하여 식별할 수 있는 유일한 이름)를 찾아내기 위한 규칙이다.
*</em></p>
<pre><code class="language-js"> let name = &#39;이동욱&#39;

const a=()=&gt;{
  let name= &#39;이동훅&#39;
  console.log(name)
  {
      let name =&#39;이동훅훅&#39;
    console.log(name)
  }
}

a() 
//이동훅훅
//이동훅
console.log(name) //이동욱</code></pre>
<p>이름이 같은 변수 name이 중복 선언되었다. 전역에서 변수 name을 참조할 때, 그리고 함수 foo내부에서 변수 name을 참조할 때 이름이 중복된 2개의 변수를 JS는 엇덕혜 식별하는 것일까?</p>
<p>프로그래밍은 변수를 선언하고 값을 할당하며 변수를 참조하는 기본적인 기능을 제공하며 이것으로 프로그램의 상태를 관리할 수 있다. 변수는 전역, 함수 내부, 코드 블록에 선언하며 코드 블록이나 함수는 중첩될 수 있다. 식별자는 자신이 어디에 선언됐는지에 의해 자신이 유효한 범위를 갖는다.</p>
<p>위 코드에서 전역에 선언된 변수 name은 어디에든 참조할 수 있다. 하지만 함수 a내에서 선언된 변수 name는 함수 a내부에서만 참조할 수 있고 함수 외부에서는 참조할 수 없다.
이러한 규칙을 스코프라고 한다.</p>
<h3 id="스코프의-구분">스코프의 구분</h3>
<p> JS의 스코프에대해서 알아보자</p>
<h4 id="전역-스코프global-scope">전역 스코프(Global Scope)</h4>
<p>전역에 변수를 선언하면 이 변수는 어디서든지 참조할 수 있는 전역 스코프를 갖는 전역 변수가 된다.
var로 선언한 전역변수는 Browser-side 에서 window 객체의 프로퍼티 , Server-side 에서는 global 객체의 프로퍼티가 된다. (let, const는 아님) </p>
<h4 id="지역-스코프local-scope">지역 스코프(Local Scope)</h4>
<p>JS는 함수 레벨 스코프를 사용했지만 ES6로 넘어오면서 변수 선언시  let과 const를 권장하면서 사용하면서 블록 레벨 스코프가 되었다 해도 무방하다.(사견임)</p>
<p>함수 내에 존재하는 함수인 내부 함수의 경우를 살펴보자</p>
<pre><code class="language-js">let name = &#39;이동욱&#39;

const outer =()=&gt; {
  let name = &#39;이동훅&#39;
  console.log(name);

  const inner=() =&gt;{  // 내부함수
    console.log(name); // ?
  }

  inner();
}
outer();
console.log(name); // ?</code></pre>
<p>내부함수는 자신을 포함하고 있는 외부함수의 변수에 접근할 수 있다.</p>
<p>함수 inner에서 참조하는 변수 name은 outer에서 선언된 지역변수이다.
이는 실행 컨텍스트의 스코프 체인에 의해 참조 순위에서 전역변수 name이 뒤로 밀렸기 때문</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[JS 숫자 알고리즘]]></title>
            <link>https://velog.io/@ldu_95/JS-%EC%88%AB%EC%9E%90-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98</link>
            <guid>https://velog.io/@ldu_95/JS-%EC%88%AB%EC%9E%90-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98</guid>
            <pubDate>Sun, 04 Jul 2021 18:33:43 GMT</pubDate>
            <description><![CDATA[<p>숫자가 소수인지 판단하는 알고리즘은 수자와 관련된 가장 많이 논의된 알고리즘 중 하나라고 한다.
이를 한번 살펴보자.</p>
<h2 id="소수-테스트">소수 테스트</h2>
<p>숫자가 소수인지 알아보는 방법은 숫자 n을 2부터 n-1까지의 수로 나눠 나머지가 0인지 확인하면 된다.</p>
<pre><code>const isPrime=(n)=&gt;{
    if(n&lt;=1){
        return false
    }

    // 2부터 n-1까지의 수로 나눈다.
    for(let i =2 ; i&lt;n;i++){
        if(n%i===0){
            return false
        }
    }

    return true
}</code></pre><p>위의 코드의 시간 복잡도는 O(n)이다. 0부터 n까지의 모든 수를 확인하기 때문이다.</p>
<p>위의 알고리즘 수행 방식에서 패턴을 찾아 알고리즘을 더 빠르게 만들 수 있을까?</p>
<p>우선 2의 배수는 무시해도 된다. 하지만 이뿐만 아니라 최적화 가능한 부분이 더 있다.</p>
<p>우선 소수를 나열해보면</p>
<p><code>2,3,5,7,11,13,17,19,23,29 ...</code></p>
<p>알아차리기 힘들 수도 있지만 2와 3을 제외하고는 모든 소수는 6k +- 1의 형태를 지닌다.
여기서 k는 정수다.</p>
<p><code>5 =(6-1), 7 = (6+1) , 11 = (2*6 -1) ...</code></p>
<p>또한 n이 소수인지 알아보기 위해 반복문을 n의 제곱근까지만 확인해보면 된다. n의 제곱근이 소수가 아니면 n은 수학 정의에 의해 소수가 아니기 때문이다.</p>
<pre><code>const isPrime = (n)=&gt;{
    if(n &lt;= 1 ) return false
    if(n &lt;=3 ) return true

    //입력된 수가 2 또는 3인 경우 아래 반복문에서 
    //다섯 개의 숫자를 건너뛸 수 있다.

    if(n%2 ===0 || n%3===0) return false

    for(let i =5;i*i&lt;=n; i +=6){ 
        //i*i &lt;=n 인 이유는 제곱근이기 때문
        if(n%i===0 || n%(i+2)===0){
            return false
        }

    }

    return true;
}</code></pre><p>위의 개선된 알고리즘의 시간복잡도는 O(sqrt(n)) 이다. 시간을 상당히 줄인다.</p>
<h3 id="소인수분해">소인수분해</h3>
<p>또 다른 유용하 알고리즘으로 어떤 숫자의 소인수분해를 구하는 것이 있다. 소수는 암호화와 해싱의 기반이 되고 소인수분해는 주어진 숫자를 만들기 위해 어떤 소수들이 곱해져야 하는지 구하는 과정이다.</p>
<pre><code>const primeFactors=(n)=&gt;{
    // n이 2로 나눠진다면 나눠질 수 있는 수만큼 2가 출력된다.
    while(n%2 ==0){
        console.log(2)
        n /= 2
    }

    //이 지점에서 부터 n은 홀수이다.
    //따라서 수를 두 개씩 증가시킬 수 있다.
    //3부터 n의 제곱근까지 반복한다.
    for(let i =3; i*i &lt;=n ; i = i+2){
        while(n%i ==0){
            console.log(i)
            n /=i
        }
    }

    //n이 2보다 큰 소수인 경우를 처리하기 위한 조건문이다.
    if(n&gt;2){
        console.log(n)
    }
}

primeFactors(10) -&gt; &#39;2&#39;와 &#39;5&#39;를 출력한다.</code></pre><h3 id="무작위-수-생성기">무작위 수 생성기</h3>
<p>무작위 수 생성은 어떤 조건이 어떤 식으로 동작하는지 확인하는 데 있어 중요하다.
JS에는 수자를 생성하기 위한 내장 함수인 Math.random()이 있다.</p>
<p>Math.random()은 0과 1 사이의 부동소수점을 반환한다.</p>
<p>무작위 정수나 1보다 큰 무작위 수를 얻는 방법은
Math.random()에 범위를 곱하면 된다.</p>
<pre><code>Math.random()*100  // 0부터 100까지의 부동소수점
Math.random()* 25+5 // 5부터 30까지의 부동소수점
Math.random()*10-100 // -100부터 -90까지의 부동소수점</code></pre><p>무작위 정수를 얻기 위해서는 Math.floor(), Math.round(),Math.ceil()을 사용해 부동소수점을 정수로 만들면 된다.</p>
<pre><code>Math.floor(Math.random()*100)  // 0부터 99까지의 정수
Math.round(Math.random()* 25+5) // 5부터 30까지의 정수
Math.ceil(Math.random()*10-100) // -100부터 -90까지의 정수</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[JS 숫자]]></title>
            <link>https://velog.io/@ldu_95/JS-%EC%88%AB%EC%9E%90</link>
            <guid>https://velog.io/@ldu_95/JS-%EC%88%AB%EC%9E%90</guid>
            <pubDate>Sun, 04 Jul 2021 09:34:40 GMT</pubDate>
            <description><![CDATA[<p>프로그래밍 언어에서 숫자 연산 덕분에 숫자 값을 계산할 수 있다.
JS의 숫자 연산에는 다음과 같은 것들이 있다.</p>
<ul>
<li><code>+</code> : 덧셈</li>
<li><code>-</code> : 뺄셈</li>
<li><code>/</code> : 나눗셈</li>
<li><code>*</code> : 곱셈</li>
<li><code>%</code> : 나머지 연산</li>
</ul>
<p>위의 연산자들은 다른 프로그래밍 언어에서도 일반적으로 사용되며 JS에 한정된 것은 아니다.</p>
<p>JS는 숫자에 대해 부호 (1비트), 지수(11비트), 소수(52비트) 총 64비트로 이루어진 부동소수점 표현을 사용한다. (JS가 모든 숫자를 나타낼 때 부동소수점을 사용한다... 정로도만 이해하자)</p>
<h1 id="js-숫자-객체">JS 숫자 객체</h1>
<p>JS가 모든 숫자를 나타낼 때 부동소수점을 사용하기 떄문에 정수 나눗셈은 소용이 없다.</p>
<p>JAVA와 같은 프로그래밍 언어에서 정수 나눗셈의 결과는 해당 나누기의 몫이다.</p>
<pre><code>    JAVA : 5/4 === 1
    JS   : 5/4 ===1.25</code></pre><p>자바에서는 명시적으로 데이터 형식을 선언해야 하기 때문이다. 
ex) int , float  ...</p>
<p>따라서 결과는 부동 소수점이 될 수 없다.</p>
<h2 id="정수-내림-반올림-올림">정수 내림, 반올림, 올림</h2>
<p>JS에서 정수 나눗셈을 하길 원한다면 다음 중 하나를 사용해야 한다.</p>
<pre><code>Math.floor - 가장 가까운 정수로 내림한다.
Math.round - 가장 가까운 정수로 반올림한다.
Math.ceil  - 가장 가까운 정수로 올림한다.</code></pre><h2 id="numberepsilon">Number.EPSILON</h2>
<p>Number.EPSILON은 두 개의 표현 가능한 숫자 사이의 가장 작은 간격을 반환한다.
이는 부동소수점 근사치를 활용해 분수가 제대로 표현되지 않는 문제를 해결하는 데 유용하다.</p>
<pre><code>function numberEquals(x,y){
    return Math.abs(x-y) &lt; Number.EPSILON
 }

 numberEquals(0.1 + 0.2 ,0.3); true

 // JS에서는 십진분수로 인해 소수점 연산을 정확하게 표현할 수 없다.
 ex) 0.1+0.2 === 0.3 //false
     0.1+0.11 ===0.12 //false</code></pre><h2 id="최대치">최대치</h2>
<h3 id="numbermax_safe_integer">Number.MAX_SAFE_INTEGER</h3>
<p>Number.MAX_SAFE_INTEGER는 가장 큰 정수를 반환한다.</p>
<p><code>Number.MAX_SAFE_INTEGER+1 ===Number.MAX_SAFE_INTEGER + 2 //true</code></p>
<p>위의 코드에서 두 수는 더 이상 커질 수 없기 때문에 true를 반환한다.
하지만 위의 코드를 부동소수점과 같이 사ㅇㅇ하면 제대로 동작하지 않으면 결과는 false이다.</p>
<p><code>Number.MAX_SAFE_INTEGER +1.111 ===Number.MAX_SAFE_INTEGER +2.022 //false</code></p>
<h3 id="numbermax_value">Number.MAX_VALUE</h3>
<p>Number.MAX_VALUE는 가능한 가장 큰 부동 소수점을 반환한다.</p>
<p>Number.MAX_VALUE는 1.7976931348623157e +308 라고한다
(뭔지는 모르겠다)</p>
<pre><code>Number.MAX_VALUE +1 === Number.MAX_VALUE +2       //true
Number.MAX_VALUE +1.111 ===Number.MAX_VALUE+2.022 //true</code></pre><p>Number.MAX_SAFE_INTEGER 와는 다르게 부동소수점에 대해서도 잘 동작한다.</p>
<h2 id="최소치">최소치</h2>
<h3 id="numbermin_safe_integer">Number.MIN_SAFE_INTEGER</h3>
<p>Number.MIN_SAFE_INTEGER는 가장 작은 정수를 반환한다.</p>
<p>Number.MIN_SAFE_INTEGER는 -9007199254740991이다.</p>
<p><code>Number.MIN_SAFE_INTEGER -1 === Number.MIN_SAFE_INTEGER -2 //true</code></p>
<p>위의 코드에서 두 수가 더 이상 작아질 수 없기 때문에 true를 반환한다.
하지만 역시 부동소수점과 함께 사용하면 제대로 동작하지 않는다.</p>
<h3 id="numbermin_value">Number.MIN_VALUE</h3>
<p>Number.MIN_VALUE는 JavaScript에서 표현할 수 있는, 0에 가장 가깝지만 음수는 아닌 수이다.
Number.MIN_VALUE는 5e-324 이다.</p>
<h2 id="무한">무한</h2>
<p>Number.MAX_VALUE 보다 큰 유일한 것은 Infinity 이고 Number.MIN_SAFE_INTEGER보다 작은 유일한 것은 -Infinity이다.</p>
<h2 id="크기-순서">크기 순서</h2>
<pre><code>-Infinity &lt; Number.MIN_SAFE_INTERGER &lt; 0 &lt; Number.MIN_VALUE &lt; Number.MAX_SAFE_INTEGER &lt; Number.MAX_VALUE &lt; Infinity </code></pre><p>위의 코드와 같이 JS 숫자의 크기를 가장 작은 것(왼쪽)부터 가장 큰 것(오른쪽) 순으로 요약했다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[URL , URI]]></title>
            <link>https://velog.io/@ldu_95/URL-URI</link>
            <guid>https://velog.io/@ldu_95/URL-URI</guid>
            <pubDate>Thu, 24 Jun 2021 09:37:59 GMT</pubDate>
            <description><![CDATA[<h2 id="url">URL</h2>
<p>URL 은 Uniform Resource Locator의 줄임말로, 네트워크 상에서 웹 페이지, 이미지, 동영상 등의 파일이 위치한 정보를 나타낸다.</p>
<h2 id="uri">URI</h2>
<p>URI 는 Uniform Resource Identifier의 줄임말로, 일반적으로 URL의 기본 요소에 더해 query, bookmark를 포함한다.</p>
<p>query는 웹 서버에 보는 추가적인 질문이다.</p>
<p>URI 는 URL을 포함하는 상위 새념이다. 따라서 &#39;URL은 URI이다&#39; 는 참이고, &#39;URI는 URL이다는&#39; 거짓이다.</p>
<h3 id="url--uri-구성-요소">URL , URI 구성 요소</h3>
<ul>
<li>scheme : 통신 프로토콜이다.<ul>
<li><code>file://</code>, <code>http://</code>, <code>https://</code> </li>
</ul>
</li>
<li>hosts  : 웹 페이지, 이미지, 동영상 등의 파일이 위치한 웹 서버, 도메인 또는 IP이다.<ul>
<li><code>192.168.1.1</code>,<code>www.naver.com</code></li>
</ul>
</li>
<li>port   : 웹 서버에 접속하기 위한 통로이다.<ul>
<li><code>:80</code>, <code>:8080</code>, <code>:3000</code></li>
</ul>
</li>
<li>url-path : 웹 서버의 루트 디렉토리로부터 웹 페이지, 이미지, 동영상 등의 파일 위치까지의 경로를 나타낸다<ul>
<li><code>/search</code>, <code>/User/username/Desktop</code></li>
</ul>
</li>
<li>query    : 웹 서버에 전달하는 추가 질문이다.<ul>
<li><code>name=이동욱</code>,<code>q=JavaScript</code></li>
</ul>
</li>
</ul>
]]></description>
        </item>
    </channel>
</rss>