<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>eeeasy-code.log</title>
        <link>https://velog.io/</link>
        <description>쉽고 즐겁게 개발합시다.</description>
        <lastBuildDate>Mon, 28 Oct 2024 13:04:29 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>eeeasy-code.log</title>
            <url>https://images.velog.io/images/eeeasy-code/profile/83fe773a-1219-437e-9b57-2187ce57fa3a/27FA1497-A432-40FA-9A12-38356FE7AD34.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. eeeasy-code.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/eeeasy-code" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Temp Title]]></title>
            <link>https://velog.io/@eeeasy-code/Temp-Title</link>
            <guid>https://velog.io/@eeeasy-code/Temp-Title</guid>
            <pubDate>Mon, 28 Oct 2024 13:04:29 GMT</pubDate>
            <description><![CDATA[<p>Temp Body</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[github-action + slack으로 서버 헬스체크하기]]></title>
            <link>https://velog.io/@eeeasy-code/github-action%EC%9C%BC%EB%A1%9C-%EC%84%9C%EB%B2%84-%ED%97%AC%EC%8A%A4%EC%B2%B4%ED%81%AC%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@eeeasy-code/github-action%EC%9C%BC%EB%A1%9C-%EC%84%9C%EB%B2%84-%ED%97%AC%EC%8A%A4%EC%B2%B4%ED%81%AC%ED%95%98%EA%B8%B0</guid>
            <pubDate>Wed, 27 Dec 2023 14:31:02 GMT</pubDate>
            <description><![CDATA[<p>이번에 진행한 프로젝트에서 나는 CloudType을 사용하여 NestJS 기반 서버를 무료로 배포하였다. 무료로 서버를 배포할 수 있다는 것이 정말 큰 장점이었지만, CloudType의 무료 티어의 경우 <strong>연속 실행 제한</strong>이 걸려 매일 오전 3~9시 사이 프리티어로 구동 중인 서비스는 자동으로 중지 상태로 변경되는 문제가 존재한다.</p>
<p><img src="https://velog.velcdn.com/images/eeeasy-code/post/227fe906-018a-41b5-92e3-25f37f0a37c8/image.png" alt=""></p>
<p>사실, 정지되는 것은 문제가 되지 않았다. 웹 사이트에 접속하는 사용자의 수도 많지 않았고, 오전 3~9시 사이에 접속하는 사용자는 더욱 낮을 것이라고 판단했기 때문이다. 그럼에도 일단 언제 중지될지 모르는 서버와 꺼져있는 서버를 재가동시키는 것을 깜빡하는 경우에 소중한 사용자의 데이터가 저장되지 못하는 일이 발생했다. 프로젝트 배포에서 가장 중요했던 사용자의 구매량과 버튼 클릭 수를 DB 서버에 저장하고 있었기에 이는 우리에게 나름 크리티컬한 문제가 되었다.</p>
<h2 id="대응-방안">대응 방안</h2>
<p>일단 초기 대응 방안은 그저 9시 이후에 CloudType 프로젝트 관리창에서 꺼져있는 나의 서버를 다시 켰다. 그런데 가끔 9시 이후에도 잘 켜져있다가 이후에 꺼지는 경우도 있었던 것으로 기억한다. 그래서, 언제꺼질지 몰라 지속적으로 확인했었다. 이는 너무 귀찮기도 했고 짜증나기도 했다. 그렇게 점점 서버 재가동을 놓치는 시간이 많아졌고, 서버는 잠들어 있는 시간이 더 길어졌다.</p>
<p>문제를 해결하기 위해, 아이디어를 구상해 보았다.</p>
<blockquote>
<ol>
<li>서버 중단 시, 내부 로직에 중단되기 직전 메일 등의 알림 기능을 구현</li>
<li>프론트엔드 단에서 서버의 응답이 정상적으로 오지않을 경우를 확인</li>
<li>헬스체크 서버를 구현 후 배포하여 주기적으로 확인</li>
</ol>
</blockquote>
<p>내 머리 속에 든 생각은 총 3가지였다. 우선 첫 번째 아이디어를 진행보았다. 서버 내부 메인 로직에 아래와 같은 코드를 넣어 서버가 다운될 시점에 로그 파일을 남길 수 있도록 진행했다.</p>
<pre><code>process.on(&#39;exit&#39;, code =&gt; {
  console.log(code)
  logger.log({
    level: &#39;error&#39;,
    message: &#39;exit&#39;
  })
})

process.on(&#39;SIGINT&#39;, code =&gt; {
  console.log(code)
  logger.log({
    level: &#39;error&#39;,
    message: &#39;sigint&#39;
  })
})</code></pre><p>하지만, 서버가 중단되고 재가동 후 확인해본 결과 로그 파일은 생성되지 않았다. 그 원인에 대해 아직도 명확한 해답을 찾지는 못했지만 스스로 생각해본 결과 배포 시스템이 중단되는 것과 내부 로직은 관련이 없고, AWS처럼 시스템 중단 시 발생하는 이벤트가 존재할텐데 이를 활용해야 할 것 같다는 생각이 들었다. CloudType 공식문서에는 따로 나와있는 내용이 없었다.</p>
<p>두 번째 아이디어는 프론트엔드 단에서 내가 배포한 서버의 API를 호출했을 때, 응답이 정상적으로 오지않고 500 등의 에러를 응답할 경우에 알림을 보내는 기능을 생각해봤다. 사실 이 아이디어도 나름 깔끔하고 좋다고 생각했지만, 프론트엔드 개발자 분께서 본인의 코드를 건드는 것을 별로 좋아하지 않았고 그래서 일단 내가 스스로 해결해보려 노력해봤다.</p>
<p>마지막 아이디어를 지금 채택해 사용 중인데, 초기에 생각했던 것은 헬스체크 서버에 기존 서버의 헬스체크 Api를 스케줄링하는 기능을 구현해 배포하려고 했다. 생각해보니 그럼 서버가 두 개나 띄워져있는 것인데 이는 낭비라고 생각이 들었다. 그래서 찾은 방법이 ** Github Action으로 헬스 체크**하는 것이었다. Github Action으로 스케줄링을 걸어놓고 특정 시간에 한 번씩 서버의 상태를 확인하고, 이를 Slack으로 알림을 전송하는 것을 생각했다.</p>
<h2 id="github-action으로-헬스체크">Github Action으로 헬스체크</h2>
<p>github action에 등록한 헬스체크 기능을 코드로 먼저 보겠다.</p>
<pre><code>name: health check

on:
  # 스케줄링을 설정함 / 매분마다 한 번씩 이벤트를 트리거함
  schedule:
    - cron: &#39;*/1 * * * *&#39;
  # workflow_dispath는 수동으로 이벤트를 트리거할 수 있도록 해주는 것을 의미함
  workflow_dispatch:

jobs:
  healthcheck:
    runs-on: ubuntu-latest
    steps:
      # 지정한 서버에 대해 헬스 체크 진행
      - name: Release API Health Check
        uses: jtalk/url-health-check-action@v3
        with:
          github_token: ${{ secrets.GHP_TOKEN }}
          url: ${{ secrets.RELEASE_URI }}
          max-attempts: 3 # 시도 횟수
          retry-delay: 1s # 시도 간격

      # 트리거된 이벤트의 내용을 slack으로 전달
      - name: action-slack
        uses: 8398a7/action-slack@v3
        with:
          status: ${{ job.status }}
          github_token: ${{ secrets.GHP_TOKEN }}
          author_name: Github Action Health Check
          fields: repo,message,commit,action,eventName,ref,workflow,job,took # 보낼 정보들
        env:
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEB_HOOK_URL }}
        if: always() # 특정 조건에 상관없이 항상 실행
</code></pre><p>작성된 github action의 healthCheck 플로우는 다음과 같다. 이 후, slack의 incoming-webhook을 등록하여 진행하면 문제없이 서버의 healthCheck 기능이 정상적으로 작동된다. 덕분에 서버가 중단된 경우 Slack을 통해 알림을 받을 수 있게 되었고, 귀찮게 내가 한번씩 접속해서 서버가 중단되었는지 확인하지 않아도 알 수 있게 되어 너무 편하다.</p>
<table>
<thead>
<tr>
<th>서버 정상 작동</th>
<th>서버 중단 시</th>
</tr>
</thead>
<tbody><tr>
<td><img src="https://velog.velcdn.com/images/eeeasy-code/post/2ff2fd43-d7ec-4cb7-98b4-1618a3ac1b7b/image.png" alt=""></td>
<td><img src="https://velog.velcdn.com/images/eeeasy-code/post/0db7fdfe-7582-4679-bd0c-eb87353f6925/image.png" alt=""></td>
</tr>
</tbody></table>
<p><img src="https://velog.velcdn.com/images/eeeasy-code/post/81ed5cf4-526b-4085-98c3-9d4c04d9a76e/image.png" alt=""></p>
<h2 id="발생한-문제들">발생한 문제들</h2>
<ol>
<li>Github Action에서 발생하는 <code>"Resource not accessible by integration"</code> 문제 발생 -&gt; github token을 넣어주면 해결 가능</li>
<li><code>"The process '/usr/bin/git' failed with exit code 1"</code> 문제 발생 -&gt; healthCheck할 서버의 url이 정상적인 응답을 보내는지 확인 후 설정 </li>
<li>schedule의 cron을 1분마다 한 번으로 지정했는데, 지정한대로 스케줄링이 되지않고 10분 내외의 간격으로 이벤트가 트리거되는 문제 발생 -&gt; 해결중</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[Koyeb에 NodeJS(Express) 서버 배포하기]]></title>
            <link>https://velog.io/@eeeasy-code/Koyeb%EC%97%90-NodeJSExpress-%EC%84%9C%EB%B2%84-%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@eeeasy-code/Koyeb%EC%97%90-NodeJSExpress-%EC%84%9C%EB%B2%84-%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B8%B0</guid>
            <pubDate>Tue, 19 Dec 2023 09:27:52 GMT</pubDate>
            <description><![CDATA[<p>최근 프로젝트에서 백오피스를 만들게 되었는데, <strong>React</strong>로 Front 구현, <strong>NodeJS(Express)</strong>로 서버 개발을 진행하게 되었다. 백오피스 환경은 전부 무료 클라우드를 사용하고 싶어, React는 Netlify로 배포를 진행했고 NodeJS는 Koyeb로 배포를 진행했다. React는 성공적으로 배포가 되었지만, NodeJS는 배포 과정에서 에러를 계속 뱉어냈다. </p>
<h1 id="nodejs-배포">NodeJS 배포</h1>
<p>Koyeb에서 지원하는 배포 방식에는 크게 두 가지가 있다.</p>
<pre><code>1. GitHub Repository를 통한 배포
2. Docker를 통한 배포</code></pre><h2 id="github-repository-배포">GitHub Repository 배포</h2>
<p>나는 처음에 GitHub Repository를 통해 배포를 시도했다. 배포를 시켜놓고 잠깐 볼 일을 보고오니 에러가 발생해 있었다.
<img src="https://velog.velcdn.com/images/eeeasy-code/post/2c8da60d-73d4-47ae-9a7a-4bf8d0ce4db9/image.png" alt=""></p>
<p>무슨 문제로 에러가 발생했는지 확인하기 위해서 로그를 확인했다. 
<img src="https://velog.velcdn.com/images/eeeasy-code/post/e59e0b62-954b-4bb8-ac31-c9dad982c4cd/image.png" alt=""></p>
<p>확인 결과, node_modules를 찾지 못해 발생한 에러였다. 기존 런타임 command를 <code> npm start</code>로만 지정해주어 발생한 것으로, <code> npm install; npm start</code>를 입력하면 정상적으로 배포가 수행된다.
<img src="https://velog.velcdn.com/images/eeeasy-code/post/090f718f-2025-4efb-8633-0836d00834ea/image.png" alt=""></p>
<h2 id="docker-배포">Docker 배포</h2>
<p>GitHub로 배포를 하고나니 시간이 어느정도 여유가 생겨서 Docker Image로 배포하는 방법도 궁금해졌다. 클라우드에 배포를 진행할 때 거의 대부분 github repository로만 배포하다보니까 다른 배포 방식은 어떻게 진행되는지 알아보고자 docker로도 배포를 해보았다. </p>
<h3 id="docker-배포-flow">Docker 배포 flow</h3>
<pre><code>1. Dockerfile을 통해 NodeJS 서버를 이미지로 변환
2. 생성된 이미지를 Docker Repository에 push
3. Docker Repository 주소를 사용하여 클라우드에 배포</code></pre><p>Docker로 배포하게 되면 위와같은 flow로 진행된다. Docker에 대한 기본적인 지식과 학습이 선행되어야 매끄럽게 진행될 것 같다. </p>
<p><strong>[Dockerfile]</strong></p>
<pre><code>FROM node:20

WORKDIR &quot;/app&quot;

COPY ./package*.json ./

RUN npm install

COPY . .

EXPOSE 3000

CMD [&quot;npm&quot;, &quot;start&quot;]</code></pre><p>Dockerfile은 위와 같은 형태로 작성했다.</p>
<p>이후, <code>docker build .</code> 명령어로 이미지를 빌드하고 나의 docker repository에 push하면 된다.</p>
<p><img src="https://velog.velcdn.com/images/eeeasy-code/post/63aa54f4-8afe-4719-884a-1d72ea448fc3/image.png" alt=""></p>
<p>마지막으로 koyeb 배포 설정에서 docker-repository 주소를 입력 후 배포하면 된다.
<img src="https://velog.velcdn.com/images/eeeasy-code/post/8147f915-c502-4a48-866a-7c37dd1ebd75/image.png" alt=""></p>
<h1 id="trouble-shooting">Trouble Shooting</h1>
<p>배포 과정에서 많은 에러들을 맞이하게 되었는데, 이에 대한 해결 과정은 따로 링크를 걸어둘 예정이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[DTO는 무엇인가]]></title>
            <link>https://velog.io/@eeeasy-code/NestJS-DTOData-Transfer-Object</link>
            <guid>https://velog.io/@eeeasy-code/NestJS-DTOData-Transfer-Object</guid>
            <pubDate>Sat, 16 Dec 2023 14:06:27 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/eeeasy-code/post/a3ff36a4-c37d-422b-88e6-5c1e04a44c89/image.png" alt=""></p>
<p>NestJS, SpringBoot 등의 프레임워크를 사용할 때마다 DTO를 사용했었다. DTO가 무엇인지, 왜 사용해야하는지 등에 대한 고민은 뒤로하고 항상 다 사용하니까 나도 따라 사용했다. 그렇다면 <strong>DTO란 무엇이고, 왜 사용해야할까?</strong></p>
<h1 id="dto-data-transfer-object">DTO (Data Transfer Object)</h1>
<blockquote>
<p>In the field of programming a data transfer object (DTO) is an object that carries data between processes. - Wiki</p>
</blockquote>
<p>위키백과에서 말하는 DTO는 ** 프로세스 간 데이터를 전달하는 객체 *<em>라고 정의되어 있다. 이 뜻을 다시 내 입맛대로 재정의해보자. *</em> DTO는 순수하게 데이터를 전송하기 위해 사용하는 객체이며, 서버 - 서버, 서버 - 클라이언트 간 데이터 전송에 사용된다. **
<img src="https://velog.velcdn.com/images/eeeasy-code/post/70898211-208e-42bb-8284-acc0715d1ad4/image.png" alt="">
사진 출처 : </p>
<p>직접 API를 개발하다보면 특히, express 등의 프레임워크를 사용하여 개발을 하면 DTO의 존재에 대해서 알지 못한채 개발을 하게 된다. 그냥 Controller 단에서 body 객체를 받아 변수에 저장하면 끝이니까. 나도 그렇게 사용했었고 NestJS나 SpringBoot를 사용하면서 DTO를 왜 굳이 사용해야 하나 싶기도 했다. 그래서, 왜 사용하는지는 알고 내가 사용해야 덜 찝찝하고 귀찮게 설계하는 것에 대한 이유가 생길 것 같았다. </p>
<h2 id="dto의-사용-이유">DTO의 사용 이유</h2>
<blockquote>
<ol>
<li>DTO와 Entity의 분리</li>
<li>효율적인 Validation 가능</li>
<li>reqeust, response 시 필요 데이터만 전송해 효율성 증가</li>
</ol>
</blockquote>
<p><img src="https://velog.velcdn.com/images/eeeasy-code/post/6b71a773-328f-4a74-997b-48966e1924a2/image.png" alt=""></p>
<p>일단 내가 사용하면서 느낀 이유와 여러 문서에서 찾은 DTO의 사용 이유를 크게 3가지로 정리해보았다. 각각의 내용을 조금 면밀하게 다루어보자.</p>
<h3 id="dto와-entity의-분리">DTO와 Entity의 분리</h3>
<p>DTO와 Entity를 분리한다는 것은 DB Layer와 View Layer의 역할을 분리한다는 것으로 받아들일 수 있다. 
Entity는 실제 Table과 매핑되어 있는데, 비즈니스 요구사항에서 가장 자주 변경되는 View Layer에서 Entity를 사용할 경우 Entity를 그 요구에 맞게 계속 변경하는 것은 바람직하지 않다. 그 이유로는 Entity 클래스가 변경되면 다른 클래스에도 영향을 미치게 되기 때문이다. </p>
<p>또, DTO 대신 Entity를 사용하게되면 Entity의 구조가 외부에 노출될 수 있는데 이는 보안적으로 문제가 될 수 있다. 그래서 DTO를 사용함으로써 Entity 내부 구현을 캡슐화할 수 있다.</p>
<h3 id="효율적인-validation-가능">효율적인 Validation 가능</h3>
<p>사실 Validation은 Entity에서도 수행할 수 있다. 그렇지만, 서버 내부 로직을 타기 전, DTO에서 먼저 Data에 대한 Validation을 수행하게 된다면 성능적인 측면에서 더 효율적이다. 그렇다고 해서, DTO에서만 Validation을 수행하는 것은 바람직하지 않다. Validation은 서버로 Data를 전달하기 전, Front 단에서도 진행되어야 하고, DTO, Entity 클래스에서도 전부 진행되는 것이 가장 안전하다. </p>
<h3 id="필요-데이터만-전송">필요 데이터만 전송</h3>
<p>여러 API에서 요구하는 데이터는 각각 다르고, reqeust/response에서 필요한 데이터도 다를 수 있다. 이런 경우, Entity를 통해 데이터를 전송하게 되면 사용하지 않는 데이터까지 전부 보내게 되는데, 이는 효율적이지 못하고 아까 말했듯 Entity 구조를 외부에 노출하게 된다. 
DTO를 사용함으로써, 다양한 API 형태에 맞추어 필요한 데이터만 전송하여 전송 속도를 개선하고 효율성을 높일 수 있다.</p>
<h1 id="결론">결론</h1>
<p>DTO를 왜 사용해야 하는지, 어떤 식으로 사용이 되는지 등에 대해서 알 수 있었다. 사실 최근 진행한 프로젝트에서 DTO 설계를 하다가 정말 포기할 뻔 했었는데, Entity를 직접 사용하게 되었을 때 나중에 생길 기술 부채를 생각해보면 DTO 설계에 든 비용이 훨씬 값싸다고 판단이 되었다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[NestJS + MySQL + CloudType으로 배포하기]]></title>
            <link>https://velog.io/@eeeasy-code/NestJS-MySQL-CloudType%EC%9C%BC%EB%A1%9C-%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@eeeasy-code/NestJS-MySQL-CloudType%EC%9C%BC%EB%A1%9C-%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B8%B0</guid>
            <pubDate>Thu, 14 Dec 2023 14:25:05 GMT</pubDate>
            <description><![CDATA[<h1 id="개요">개요</h1>
<p>학교에서 진행하고 있는 창업 프로젝트에서 서버 개발자로 프로젝트를 진행한지 일주일 정도된 것 같다. 1차 서비스 배포가 얼마 남지 않은 시점에 참여하게 되어 빠른 시간 내에 개발을 진행해야 했다. </p>
<h2 id="tech-spec">Tech Spec.</h2>
<p>사용된 개발 환경은 다음과 같다.</p>
<blockquote>
<p>Node - v20.10.0
Flamework - NestJS
DB - MySQL
Cloud - CloudType</p>
</blockquote>
<p>빠른 생산성을 위해 프레임워크 선정에 express도 고려해봤지만 실제 서비스 배포 이후, 지속적으로 유지보수나 확장이 필요했고 개발자가 추가 투입되었을 경우, 어느정도 일관된 구조가 필요할 것이라 판단했기에 NestJS를 선정했다. 
<img src="https://velog.velcdn.com/images/eeeasy-code/post/139b687d-599a-4c29-8585-9818194029b4/image.png" alt=""></p>
<h1 id="cloudtype으로-배포">CloudType으로 배포</h1>
<p>CloudType은 학교에서 팀프로젝트를 진행했을 때, 우연히 알게된 플랫폼이다. 무료이면서 빠르게 배포를 진행하고 싶어 찾게 되었는데 UI든 환경설정이든 내가 사용해본 플랫폼 중 가장 편하고 좋은 것 같아 채택하게 되었다. </p>
<h2 id="nestjs-배포">NestJS 배포</h2>
<p><img src="https://velog.velcdn.com/images/eeeasy-code/post/82d9f35f-3fe2-427d-b0eb-4580a24eb0ea/image.png" alt=""></p>
<p>CloudType에서 제공하는 공식 문서를 보고 배포를 진행하니 수월하게 배포할 수 있었다. 다만 배포 환경에서의 package.json의 Script를 잘못 설정했더니 runtime error가 엄청나게 쏟아져 나왔다. 
<img src="https://velog.velcdn.com/images/eeeasy-code/post/606498a6-eee8-45c4-a515-37306b9dcb98/image.png" alt=""></p>
<ol>
<li><p>DB 접속 오류
DB를 기존에 local 환경에서 사용했기 때문에 당연히 오류가 발생할 수 밖에 없었다. 그래서 NestJS를 배포하기 전, CloudType에서 같은 프로젝트 내에 MariaDB를 배포한 뒤 연동하였다. </p>
</li>
<li><p>Script 설정
prod 환경의 script에서 build path를 잘못입력해 발생한 오류가 존재했다. dist/main -&gt; build/main으로 변경해주니 문제없이 실행되었다.</p>
</li>
<li><p>npm run 설정
npm run 설정을 prod 환경으로 지정하지 않아 오류가 발생했다. cloudType Script 설정에서 num run 관련된 내용을 변경해주었다. 
<img src="https://velog.velcdn.com/images/eeeasy-code/post/ccea42e7-61c6-4bc7-8f3d-aa0dacc0a903/image.png" alt=""></p>
</li>
</ol>
<h2 id="mariadb-배포">MariaDB 배포</h2>
<p><img src="https://velog.velcdn.com/images/eeeasy-code/post/fea8b309-47eb-4f93-880d-34ab828a92b2/image.png" alt=""></p>
<p>CloudType에 존재하는 템플릿으로 클릭 몇 번만 하면 손쉽게 배포할 수 있었다. 배포 이후, 생성된 도메인을 통해 MySQL Workbench로 접속하여 DB, Table을 생성한 뒤 서버에 Post 요청을 하니 데이터가 잘 저장되는 것을 확인할 수 있었다.</p>
<h1 id="추후-작업내용">추후 작업내용</h1>
<p>일단 기본적으로 추가되는 기능에 대한 것들을 개발할 예정이고, 사실 서버를 빠르게 배포한다는 핑계로 구조 설계나 기본 로깅 설정 등을 많이 스킵하거나 대충 개발을 하였다. 이 부분들을 개선하기 위해 리팩토링을 진행할 예정이다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[NestJS VS Express]]></title>
            <link>https://velog.io/@eeeasy-code/NestJS-VS-Express</link>
            <guid>https://velog.io/@eeeasy-code/NestJS-VS-Express</guid>
            <pubDate>Sun, 03 Dec 2023 08:05:00 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/eeeasy-code/post/16eb0909-b00b-447f-8820-5213e8664bb0/image.png" alt="">
최근에 나는 학교 프로젝트로 Express 프레임워크를 사용한 서버 개발을 진행했다. 과거에 회사에 있을때는 nestJS 기반으로 프로젝트를 개발했었는데, 그때는 그저 Express보다 nestJS가 더 좋다는 이유만으로 사용했다.
둘 다 사용해본 지금 시점에 두 프레임워크 간 장단점을 이야기해보려 한다. </p>
<h1 id="express">Express?</h1>
<p>Express는 웹 및 모바일 애플리케이션을 위한 일련의 강력한 기능을 제공하는 간결하고 유연한 Node.js 웹 애플리케이션 프레임워크이다.
Node.js의 표준 웹서버 프레임워크로 불려질 만큼 많은 곳에서 사용하고있다.</p>
<p>Express의 특징으로는 다음과 같다.</p>
<pre><code>- 가장 보편적으로 사용되어 많은 생태계가 구축되어있음
- 타입스크립트의 사용이 가능하지만 각종 세팅 과정이 복잡해짐
- 웹서버를 빠르게 구현하기 위해 적합하며 개발에대한 자유도가 높음</code></pre><p>실제 프로젝트에 사용해본 결과 SpringBoot나 NestJS에 비해 초기 설정이나 개발 과정에서의 자유도가 굉장히 높다는 것을 체감했다. 앞서말한 NestJS와 같은 프레임워크는 정해진 구조가 존재하기에 이 부분을 맞춰주어야 설계하기 쉬워진다. 이 부분은 설계과정이 쉽고 빨라진다는 장점도 있지만, 개발자 입맛대로 작성하기 어렵다는 단점도 존재한다. </p>
<h1 id="nestjs">NestJS?</h1>
<p>NestJS는 Node.js에 기반을 둔 웹 API 프레임워크로써 Express 또는 Fastify 프레임워크를 래핑하여 동작한다.
NestJS는 데이터베이스, ORM, 설정, 유효성 검사 등 수많은 기능을 기본 제공한다. 또 필요한 라이브러리를 쉽게 설치 (npm, yarn 등)하여 기능을 확장할 수 있는 Node.js의 장점을 그대로 가지고 있다.
또, 모듈/컴포넌트 기반으로 프로그램을 작성해 코드 재사용성을 높일 수 있다.
프로그래밍 언어로는 타입스크립트를 기본으로 사용해 타입스크립트가 가진 타입시스템의 장점을 누릴 수 있다.</p>
<p>NestJS의 특징으로는 다음과 같다.</p>
<pre><code>- 안정성
NestJS는 타입스트립트 언어를 채택함. 
타입스크립트는 타입을 지정하여 개발자 또는 시스템이 코드를 읽고 디버깅 하는 데 자바스크립트의 실수 및 버그를 사전에 잡아줘 개발 시 발생할 수 있는 이슈를 미연에 방지할 수 있음

- 확장성
NestJS는 모듈식 아키텍쳐를 사용하는데, 다른 라이브러리와 함께 사용할 수 있어 유연한 확장성을 제공함

- 캡슐화
객체지향프로그래밍의 특성중 하나가 캡슐화임. NestJS는 비슷한 기능을 하는 컨트롤러,서비스등을 묶어 module파일 내에서 모두 관리함

- 효율성
nestJS는 타입스크립트의 적극적인 도입, DI(Dependency Injection), Ioc(Inversion of Control), Module을 통한 구조화 등의 기술을 통해 생산적인 개발이 용이함</code></pre><p>NestJS를 사용하다가 SpringBoot로 Migration한 경험이 있는데, 이때 느낀 점은 NestJS가 SpringBoot의 개념을 녹여낸 것 같다는 것이었다. 데코레이터, DI, MVC 패턴 등을 사용하는 부분에서 느끼게 되었다. </p>
<h1 id="결론">결론</h1>
<p>Express는 나의 입맛대로 유연하게 개발을 할 수 있다는 장점이 있지만, 프로젝트의 규모가 커지거나 협업을 하는 과정에서 엄격하게 Convention을 맞추지 않으면 굉장히 어려울 것 같다는 생각이 든다. 그래서, 단기간에 빠르게 가벼운 웹 서버를 개발해야하는 상황이라면 Express 사용을 고려해보면 좋을 것 같다.
NestJS는 프레임워크에서 자체적으로 패턴과 같은 것들을 제공하기에 협업이나 대규모 프로젝트에서 사용하면 수월할 것 같다는 생각이 든다. 또한, ypescript 자체의 안정성과 확장성, OOP 개념의 도입, 효율성 등도 장점으로 존재한다. 다만, 그만큼 프레임워크에 대한 이해도가 높아야 할 것 같고, Express에 비해 커뮤니티가 상대적으로 작다보니 이 점도 고려해야할 것 같다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[동시에 같은 DB Table row 를 업데이트 하는 상황에는 어떻게 해결해야 할까?]]></title>
            <link>https://velog.io/@eeeasy-code/%EB%8F%99%EC%8B%9C%EC%97%90-%EA%B0%99%EC%9D%80-DB-Table-row-%EB%A5%BC-%EC%97%85%EB%8D%B0%EC%9D%B4%ED%8A%B8-%ED%95%98%EB%8A%94-%EC%83%81%ED%99%A9%EC%97%90%EB%8A%94-%EC%96%B4%EB%96%BB%EA%B2%8C-%ED%95%B4%EA%B2%B0%ED%95%B4%EC%95%BC-%ED%95%A0%EA%B9%8C</link>
            <guid>https://velog.io/@eeeasy-code/%EB%8F%99%EC%8B%9C%EC%97%90-%EA%B0%99%EC%9D%80-DB-Table-row-%EB%A5%BC-%EC%97%85%EB%8D%B0%EC%9D%B4%ED%8A%B8-%ED%95%98%EB%8A%94-%EC%83%81%ED%99%A9%EC%97%90%EB%8A%94-%EC%96%B4%EB%96%BB%EA%B2%8C-%ED%95%B4%EA%B2%B0%ED%95%B4%EC%95%BC-%ED%95%A0%EA%B9%8C</guid>
            <pubDate>Sun, 12 Nov 2023 13:10:29 GMT</pubDate>
            <description><![CDATA[<p>동시에 같은 DB 테이블 row를 업데이트 하는 상황은 <Strong>&quot;DB의 동시성 이슈&quot;</Strong>으로 생각해보면 좋을 것 같다. </p>
<h1 id="db의-동시성-이슈">DB의 동시성 이슈</h1>
<p><Strong>동시성</Strong>이란 여러 요청이 동시에 동일한 자원(Data)에 접근하고 수정하려는 것을 말한다. 이로 인해, 발생하게 되는 문제를 동시성 문제라고 한다. 동시성 문제로 Data의 무결성이 깨지고 의도하지 않은 결과를 반환하게 되는 문제들이 발생한다.</p>
<hr>

<h1 id="해결방안">해결방안</h1>
<p>해결방안에는 DB수준에서의 락, 프레임워크 or 언어 수준에서의 동기화 등이 존재한다. 여기서는 DB수준에서의 락에 대해 알아보려고 한다. </p>
<blockquote>
<ol>
<li>테이블의 row에 접근 시, Lock을 걸고 다른 Lock이 걸려있지 않는 경우에만 수정을 가능하게 함</li>
<li>수정할 때 내가 먼저 수정했음을 명시하여 다른 곳에서 동일한 조건으로 값을 수정할 수 없게 함</li>
</ol>
</blockquote>
<p>위처럼, 자원 경쟁에 대한 관점으로 두 가지의 방법을 생각해볼 수 있다. 이는 비관적 락과 낙관적 락을 나누는 기준이 된다.</p>
<hr>

<h2 id="비관적-락pessimistic-lock">비관적 락(Pessimistic Lock)</h2>
<p>현재 수정하려는 data가 언제든지 다른 요청에 의해 수정될 가능성을 고려하여 해당 data에 Lock을 거는 방식
트랜잭션이 시작될 때 Shared Lock 또는 Exclusive Lock을 걸고 시작한다. </p>
<ul>
<li><p><code><Strong>공유락 (Shared Lock)</Strong></code> : Read Lock이라고 하는 공유락은 트랜잭션이 읽기를 할 때 사용하는 락이며, 데이터를 읽기만 하기 때문에 같은 공유락끼리는 동시에 접근이 가능하지만, 쓰기 작업은 막는다.</p>
</li>
<li><p><code><Strong>베타락 (Exclusive Lock)</Strong></code> : Write Lock이라고 하는 배터락은, 데이터를 변경할 때 사용하는 락이다. 트랜잭션이 완료될 때까지 유지되며, 락이 끝나기 전까지 읽기/쓰기를 모두 막는다.</p>
</li>
</ul>
<h3 id="장점">장점</h3>
<ul>
<li>data의 무결성을 보존할 수 있다.</li>
<li>충돌 발생 미리 방지</li>
</ul>
<h3 id="단점">단점</h3>
<ul>
<li>Lock으로 인해 이후의 다른 요청은 대기 상태로 빠짐</li>
<li>기존 Lock의 트랜잭션이 commit/rollback으로 끝내면 이후 대기 요청을 실행</li>
</ul>
<hr>

<h2 id="낙관적-락optimistic-lock">낙관적 락(Optimistic Lock)</h2>
<p>자원에 락을 걸지 않고, 동시성 문제가 발생하면 그때 처리한다.
숫자/시간 컬럼을 만들어 수정 시 그 data를 증가/갱신함 -&gt; data 수정 시 컬럼을 비교하여 일치하는지 확인</p>
<ul>
<li><p>Version과 같은 <Strong>별도의 컬럼을 추가</Strong>하여 충돌 발생을 막는다.
Version -&gt; hashcode / timestamp 등을 사용하여 상태를 보고 충돌 확인함</p>
</li>
<li><p>충돌 발생 시, DB가 아닌 애플리케이션 단에서 처리를 한다.
낙관적 락은 UPDATE에 실패해도 자동으로 예외를 던지지 않고, 단순히 0개의 row를 업데이트한다.
따라서 이때 여러 작업이 묶은 트랜잭션 요청 실패 시,<Strong>우리가 직접 롤백 처리</Strong>를 해줘야 한다.</p>
</li>
</ul>
<h3 id="장점-1">장점</h3>
<ul>
<li>구현하기 용이함</li>
<li>지속적인 락으로 인한 성능저하를 막을 수 있음</li>
</ul>
<h3 id="단점-1">단점</h3>
<ul>
<li>Version Conflict 시, 처리해야 할 외부 요인이 존재함</li>
</ul>
<hr>

<h2 id="성능-비교">성능 비교</h2>
<blockquote>
<p><Strong>비관적 락 &lt; 낙관적 락 </Strong></p>
</blockquote>
<ul>
<li>낙관적 락은 트랜잭션이 필요하지 않기 때문에 성능적으로 우수함</li>
<li>비관적 락은 데이터 자체에 락을 걸기 때문에 동시성이 떨어져 성능 저하가 발생하며, 서로의 자원이 필요할 경우에는 교착상태가 발생할 가능성 존재</li>
</ul>
<blockquote>
<p><Strong>충돌이 많이 발생하는 환경</Strong></p>
</blockquote>
<p>충돌 발생 시, 비관적 락은 트랜잭션을 롤백하면 끝남. 하지만 낙관적 락은 까다로운 수동 롤백 처리와 성능 측면에서도 Update를 한번씩 더 해줘야 하기 떄문에, 성능 저하가 발생할 수 있음</p>
<p><Strong> 데이터의 무결성 + 데이터의 충돌이 많이 발생할 것 같은 경우 -&gt; 비관적 락
데이터 충돌이 적을 것 같은 경우 + 조회 작업이 많아 동시 접근 성능이 중요 -&gt; 낙관적 락 </Strong></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[프레임워크 선정 기준]]></title>
            <link>https://velog.io/@eeeasy-code/%ED%94%84%EB%A0%88%EC%9E%84%EC%9B%8C%ED%81%AC-%EC%84%A0%EC%A0%95-%EA%B8%B0%EC%A4%80</link>
            <guid>https://velog.io/@eeeasy-code/%ED%94%84%EB%A0%88%EC%9E%84%EC%9B%8C%ED%81%AC-%EC%84%A0%EC%A0%95-%EA%B8%B0%EC%A4%80</guid>
            <pubDate>Thu, 09 Nov 2023 15:29:17 GMT</pubDate>
            <description><![CDATA[<p>개발을 진행할 때, 내가 사용할 언어를 선택하고 <Strong>프레임워크</Strong>를 선택하게 된다. 나는 프레임워크가 무엇인지 이해하고 그 용도에 맞게 잘 선택한 것인지 스스로 의문점이 들어 정리를 할 필요가 있다고 판단했다.</p>
<h1 id="프레임워크-framework">프레임워크 (Framework)</h1>
<p><Strong>프레임워크</Strong> 란 &quot;소프트웨어의 구체적인 부분에 해당하는 설계와 구현을 재사용이 가능하게 만드는 일련의 협업화된 형태로 클래스와 라이브러리를 제공하는 것&quot; 라고 한다. </p>
<blockquote>
<p>바퀴를 다시 발명하지 마라 (Don&#39;t reinvent the wheel)</p>
</blockquote>
<p>프레임워크와 같은 개발을 편리하게 만들어주는 도구들은 위의 격언의 내용을 전부 내포하고 있지 않을까? 프레임워크는 우리가 서비스 개발에 더 집중할 수 있도록 도와주는 기본 뼈대라고 생각을 한다. 내가 개발을 하는데 A라는 기능이 필요하다면 A라는 기능을 구현하면 된다. 그러나, 이미 A를 누군가가 구현해 놓았다면 우리는 그 기능을 따로 구현하지 않고 사용하면 된다. 정말 편리하다. 
다시 정리하자면, 내가 목표하는 기능을 구현하기 위해 기본적인 뼈대와 부품을 가져다 쓰겠다는 것이다. </p>
<h2 id="장점">장점</h2>
<ol>
<li>효율성</li>
<li>품질 향상</li>
<li>유지 보수 용이</li>
</ol>
<h2 id="단점">단점</h2>
<ol>
<li>러닝커브가 급함</li>
<li>프레임워크 의도와 목적에 제약 사항</li>
</ol>
<h1 id="선정-기준">선정 기준</h1>
<blockquote>
<p>내가 구현하고자 하는 서비스의 목적, 특징</p>
</blockquote>
<p>대부분의 프레임워크가 제공하는 기본적인 기능들은 비슷하다. 언어와 사용방법이 조금씩 차이가 있을뿐 기능은 큰 차이가 없다. 다만, 프레임워크마다 특정 기능 구현에 포커스를 맞춰놓은 부분들이 있기에 이런 부분을 고려하여 선정해야 한다. </p>
<ol>
<li>본인이 사용할 수 있는 언어 고려</li>
<li>구현할 서비스의 목적과 특징 분석</li>
<li>기능을 검색해 봤을 때, 참고할만한 자료가 풍부한지 고려</li>
</ol>
<p>등등.. 많은 선정 기준이 있지만 내가 생각했을 때 대표적인 선정 기준은 위 3가지로 추려볼 수 있다.
특히 개발을 처음 시작했을 때, 1순위 선정 기준(언어 제외)은 난 아무것도 모르기 때문에, 참고할 수 있는 자료들이 많은 프레임워크를 선정하는 것이었다. 사용자가 적은 프레임워크나 참고 자료가 많지 않은 프레임워크로 개발을 했다가 프레임워크를 다시 선정하고 개발을 다시 시작한 경험이 있다..</p>
<h1 id="대표적인-프레임워크">대표적인 프레임워크</h1>
<h2 id="spring--java">Spring + Java</h2>
<p>
<img src="https://velog.velcdn.com/images/eeeasy-code/post/0c002b44-4a2c-4ac9-ac6e-2f26efc207a1/image.png" width="40%" height="30"/>
> 자바 플랫폼을 위한 오픈 소스 애플리케이션 프레임워크
전자정부 표준 프레임워크
대규모 트래픽 처리에 용이함
성능과 언정성 측면에서 우수함

<h2 id="express--jsts">Express + JS/TS</h2>
<p>
<img src="https://velog.velcdn.com/images/eeeasy-code/post/70b91a84-000f-4329-b23f-710bad2fc505/image.png" width="40%" height="30"/>
> Node.js를 위한 빠르고 개방적이고 간결한 웹 프레임워크
npm을 통한 간단한 설치
작고 간단한 서버 제작에 용이함
미들웨어 활용이 강조된 간단한 구조

<h2 id="django--python">Django + Python</h2>
<p>
<img src="https://velog.velcdn.com/images/eeeasy-code/post/9b408fe2-36bf-48c8-a50e-bd02fdbf9fab/image.png" width="40%" height="30"/>

<blockquote>
<p>Python 기반의 웹 프레임워크
강력한 라이브러리 지원
Full Stack 개발 가능
최소기능제품(MVP) 제작을 위해 곧바로 사용 가능함</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[검색창에 google.com을 입력하면 벌어지는 일]]></title>
            <link>https://velog.io/@eeeasy-code/%EA%B2%80%EC%83%89%EC%B0%BD%EC%97%90-google.com%EC%9D%84-%EC%9E%85%EB%A0%A5%ED%95%98%EB%A9%B4-%EB%B2%8C%EC%96%B4%EC%A7%80%EB%8A%94-%EC%9D%BC</link>
            <guid>https://velog.io/@eeeasy-code/%EA%B2%80%EC%83%89%EC%B0%BD%EC%97%90-google.com%EC%9D%84-%EC%9E%85%EB%A0%A5%ED%95%98%EB%A9%B4-%EB%B2%8C%EC%96%B4%EC%A7%80%EB%8A%94-%EC%9D%BC</guid>
            <pubDate>Wed, 08 Nov 2023 16:27:30 GMT</pubDate>
            <description><![CDATA[<p>우리가 아무 생각없이 구글에 접속을 하기 위해, 웹 브라우저에 <a href="http://www.google.com%EC%9D%84">www.google.com을</a> 검색한다. 그럼 내 PC의 화면에는 구글 페이지가 출력된다. 과연 우리가 입력하고 검색함과 동시에 그 뒤에서는 어떠한 일이 일어날까?</p>
<h1 id="간단하게-이해하는-동작-과정">간단하게 이해하는 동작 과정</h1>
<img src="https://velog.velcdn.com/images/eeeasy-code/post/e53d58f6-0ce3-41e0-bf2a-e017e91b21e2/image.png" width="100%" height="30">
기본적으로 클라이언트의 브라우저 검색창에 내가 알고있는 도메인 이름을 입력한다. 그리고 그 도메인 이름으로 DNS Server에 질의를 요청한다. DNS Server는 요청받은 도메인 이름에 맞는 IP 주소를 찾아 리턴해준다. 그럼 브라우저는 요청받은 IP주소로 접속한다.

<p>우리는 사람이다. 그리고, 우리가 사용하고 있는 PC는 기계이다. 우리가 입력하는 도메인 이름을 기계는 이해하지 못한다. 그럼 우리는 접속하고 싶은 서버에 대한 IP 주소를 전부 기억해야 하는가? 그럴 수 없기에 우리 인간은 사용하기 쉬운 문자열을 입력하여 그 문자열에 맞는 주소를 반환할 수 있는 서버를 만들어냈다. 그게 바로 <Strong> DNS Server </Strong>이다.</p>
<h1 id="더-알아야-할-내용들">더 알아야 할 내용들</h1>
<p>위의 설명은 엄청나게 쉽게 동작 과정들을 표현하였다. 하지만, 추가적으로 도메인의 형식, 형태나 DNS와 DNS Server 동작 과정, 각각의 통신 과정, 웹 브라우저에 표현되는 페이지의 랜더링 과정이나 브라우저 동작 과정 등 엄청나게 복잡한 내용들이 존재한다. 나는 이 내용들에 대해 다음 세션에 더 자세히 알아보고자 한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TCP vs UDP]]></title>
            <link>https://velog.io/@eeeasy-code/TCP-vs-UDP</link>
            <guid>https://velog.io/@eeeasy-code/TCP-vs-UDP</guid>
            <pubDate>Tue, 07 Nov 2023 14:58:01 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/eeeasy-code/post/91a1f8e7-8dd4-4870-a06b-6551ff4fa708/image.jpeg" alt=""></p>
<p>우선 TCP와 UDP가 무엇인지에 대해 전반적인 개념을 설명하려고 한다. 
TCP와 UDP는 OSI 7계층 중 <Strong>4계층(전송 계층)</Strong>에서 사용되는 프로토콜이다. <Strong>전송 계층</Strong>은 서로 다른 호스트에서 동작하는 애플리케이션 프로세스들 간의 논리적 통신(logical communication)을 제공한다. IP에 의해 전달되는 패킷의 오류를 검사하고 재전송 요구, 패킷의 목적지가 어떤 프로세스인지 등의 제어를 담당한다.</p>
<h1 id="tcp">TCP</h1>
<p>TCP(Transmisson Control Protocol): 전송 제어 프로토콜
TCP는 신뢰성 있는 데이터 전송을 지원하는 <Strong> 연결 지향형 </Strong> 프로토콜이다. 일반적으로 TCP는 IP와 함께 사용되는데, IP가 데이터 전송을 처리하면 TCP는 패킷의 추적 및 관리를 한다.</p>
<h2 id="tcp의-특징">TCP의 특징</h2>
<ul>
<li>연결형 서비스로 가상 회선 방식 제공</li>
<li>3-way Handshake 방식으로 연결, 4-way Handshake 방식으로 해제</li>
<li>흐름 제어 및 혼잡 제어 O</li>
<li>높은 신뢰성</li>
<li>데이터의 전송 순서 보장</li>
<li>느린 전송 속도</li>
</ul>
<blockquote>
<p><Strong>흐름 제어</Strong> -&gt; 송/수신 측 간 데이터 처리 속도 차이를 조절
<Strong>혼잡 제어</Strong> -&gt; 네트워크 내 패킷의 수가 넘치지 않게 방지</p>
</blockquote>
<h1 id="udp">UDP</h1>
<p>UDP(User Datagram Protocol): 사용자 데이터그램 프로토콜
UDP는 <Strong> 비연결형 </Strong>프로토콜로, 인터넷 상에서 데이터 송/수신에 대한 신호 절차를 거치지 않고 송신 측에서 일방적으로 데이터를 전달하는 통신 프로토콜이다. TCP와 달리 연결 설정을 하지 않으며, 혼잡 제어를 하지 않아 TCP보다 속도가 빠르다. 그러나, 데이터 송신에 대한 보장을 하지 않아 패킷 손실이 발생할 수 있다.</p>
<h2 id="udp의-특징">UDP의 특징</h2>
<ul>
<li>비연결형 서비스로 데이터그램 방식을 제공</li>
<li>비신뢰성</li>
<li>흐름 제어 및 혼잡 제어 X</li>
<li>낮은 신뢰성</li>
<li>빠른 속도</li>
<li>패킷 오버헤드가 적어 네트워크 부하 감소</li>
</ul>
<hr>

<h1 id="정리">정리</h1>
<p><img src="https://velog.velcdn.com/images/eeeasy-code/post/2c148e33-d071-4796-abef-2af678618ac6/image.png" alt=""></p>
<center>

<table>
<thead>
<tr>
<th align="center">TCP</th>
<th align="center">UDP</th>
</tr>
</thead>
<tbody><tr>
<td align="center">연결형 프로토콜</td>
<td align="center">비연결형 프로토콜</td>
</tr>
<tr>
<td align="center">데이터 경계를 구분하지 않음</td>
<td align="center">데이터의 경계를 구분함</td>
</tr>
<tr>
<td align="center">신뢰성있는 데이터 전송 (데이터 재전송 O)</td>
<td align="center">신뢰성없는 데이터 전송 (데이터 재전송 X)</td>
</tr>
<tr>
<td align="center">1:1 통신</td>
<td align="center">1:1, 1:N, N:M 통신</td>
</tr>
</tbody></table>
</center>]]></description>
        </item>
        <item>
            <title><![CDATA[Git Conflict 발생 해결책]]></title>
            <link>https://velog.io/@eeeasy-code/conflict-%EB%B0%9C%EC%83%9D-%EC%8B%9C-%EC%96%B4%EB%96%BB%EA%B2%8C-%ED%95%B4%EC%95%BC%ED%95%98%EB%82%98</link>
            <guid>https://velog.io/@eeeasy-code/conflict-%EB%B0%9C%EC%83%9D-%EC%8B%9C-%EC%96%B4%EB%96%BB%EA%B2%8C-%ED%95%B4%EC%95%BC%ED%95%98%EB%82%98</guid>
            <pubDate>Tue, 07 Nov 2023 08:14:43 GMT</pubDate>
            <description><![CDATA[<h1 id="conflict-시나리오">Conflict 시나리오</h1>
<ol>
<li><p>최근에 프로젝트를 진행하는 강의를 들으면서 수업 전 날, 미리 내 깃허브 레포에 수업에 필요한 코드를 push해놓고 프로젝트에서 사용하는 OS 내에서 내 레포를 pull해 코드를 사용했다. 
수업은 주에 한 번이라 전 주에 내가 로컬에 어떤 코드를 작성하고 수정했는지, 원격 레포에는 어떤 코드가 올라가 있는지 까먹게 되는데 아무 생각없이 pull을 시도하였다가 Conflict이 발생했다.</p>
</li>
<li><p>회사를 다니던 때에 개발 중인 서비스에 대한 계정 정보, Docker-compose 파일 등 내가 사용하기 편한 환경 설정을 로컬에 구성하여 개발을 진행했다. 하나의 feature에 대한 개발 작업이 완료되고 develop 브랜치와 merge를 하려 PR을 만들었는데, Conflict이 발생했다.</p>
</li>
</ol>
<p>이 외에도 git을 사용하는 환경에서는 나를 당황시키는 conflict이 정말 많이 발생할 것이다. 위 시나리오는 실제 내가 겪었던 사례 기반이다. </p>
<h1 id="해결-방안">해결 방안</h1>
<p>그렇다면 우리는 conflict이 발생했을 때 어떤 식으로 해결을 해야할까? </p>
<p>conflict이 발생했을 때 해결 방법은 매우 단순하다.</p>
<ol>
<li>진행된 merge 작업을 취소하고 원래 상태로 복귀</li>
<li>conflict이 발생한 지점을 확인한 뒤, 해결하고 merge를 완료 </li>
</ol>
<h2 id="1-진행된-merge-취소">1. 진행된 merge 취소</h2>
<p><code>git merge --abort</code> 를 실행하면 merge가 취소된다.</p>
<h2 id="2-conflict-해결-후-merge">2. conflict 해결 후 merge</h2>
<p><code>git status</code> 를 실행해보면 현재 conflict가 발생한 파일의 이름이 출력된다. 그럼 conflict가 발생한 파일을 찾아가보자.
<img src="https://velog.velcdn.com/images/eeeasy-code/post/f5dcd2dc-5de4-47d0-8513-b3c8aff73d9d/image.png" width="70%" height="30">
conflict가 발생한 지점이 보인다. </p>
<p>&lt;&lt;&lt;&lt;&lt;&lt;&lt; HEAD 부터 ======= 사이의 내용은 나의 로컬 환경 수정 사항들을 나타낸다. 이 수정 사항은 아직 원격 저장소에 반영되지 않은 상태이다.</p>
<ul>
<li>HEAD가 가리키던 (HEAD 표시가 있는 이유)</li>
<li>master 브랜치가 가리키던 최신 커밋에서의 파일 내용</li>
</ul>
<p>======= 부터 &gt;&gt;&gt;&gt;&gt;&gt;&gt; 사이에는 원격 저장소나 다른 브랜치의 수정 사항들을 나타낸다. </p>
<ul>
<li>premium 브랜치가 가리키던 최신 커밋에서의 파일 내용</li>
</ul>
<p>여기서 선택할 수 있는 옵션은 여러가지가 존재한다.</p>
<ol>
<li>Good morning을 사용할 것인가? (Good morning! 텍스트만 남겨놓고 나머지 부분 전부 삭제)</li>
<li>Good Afternoon을 사용할 것인가? (Good Afternoon~ 텍스트만 남겨놓고 나머지 부분 전부 삭제)</li>
<li>Good morning과 GoodAfternoon을 둘 다 사용할 것인가? (둘 다 남겨놓는다)</li>
<li>새로운 코드를 사용할 것인가? (충돌난 부분 전부 삭제 후 다시 새로운 코드 입력)</li>
</ol>
<p>이후, commit을 날려주고 merge를 진행하면 된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[S3 버킷 퍼블릭 액세스 설정]]></title>
            <link>https://velog.io/@eeeasy-code/S3-%EB%B2%84%ED%82%B7-%ED%8D%BC%EB%B8%94%EB%A6%AD-%EC%95%A1%EC%84%B8%EC%8A%A4-%EC%84%A4%EC%A0%95</link>
            <guid>https://velog.io/@eeeasy-code/S3-%EB%B2%84%ED%82%B7-%ED%8D%BC%EB%B8%94%EB%A6%AD-%EC%95%A1%EC%84%B8%EC%8A%A4-%EC%84%A4%EC%A0%95</guid>
            <pubDate>Mon, 06 Nov 2023 14:17:07 GMT</pubDate>
            <description><![CDATA[<p>S3 버킷을 생성하면 기본적으로 모든 퍼블릭 액세스에 대해 차단되어 있다. 이는 S3 버킷 정책의 기본 원칙이다. 그렇기에 S3 버킷을 퍼블릭하게 사용하기 위해서는 사용자가 S3 버킷 퍼블릭 액세스 설정을 해주어야 한다.</p>
<h1 id="기본-세팅">기본 세팅</h1>
<p>S3 퍼블릭 액세스에 대한 기본 세팅에 대해서 설명해보려고 한다.</p>
<h2 id="퍼블릭-액세스-차단-설정">퍼블릭 액세스 차단 설정</h2>
<p>버킷을 생성할 때, 버킷의 퍼블랙 액세스 차단을 설정할 수 있다. 우리는 버킷을 퍼블릭하게 사용할 것이기 때문에, 모든 퍼블랙 액세스 차단에 체크를 해제해준다.</p>
<table>
<thead>
<tr>
<th><img src="https://velog.velcdn.com/images/eeeasy-code/post/72bbddf1-c130-44df-9560-8d0e685523a7/image.png" alt=""></th>
<th><img src="https://velog.velcdn.com/images/eeeasy-code/post/ac97d3af-225d-459a-b3ed-91315feb2414/image.png" alt=""></th>
</tr>
</thead>
</table>
<blockquote>
<p><Strong>퍼블릭 액세스 차단</Strong></p>
</blockquote>
<ul>
<li>새 ACL을 통해 부여된 버킷 및 객체에 대한 퍼블릭 액세스 차단</li>
<li>임의의 ACL을 통해 부여된 버킷 및 객체에 대한 퍼블릭 액세스 차단</li>
<li>새 퍼블릭 버킷 또는 액세스 지점 정책을 통해 부여된 버킷 및 객체에 대한 퍼블릭 액세스 차단</li>
<li>임의의 퍼블릭 버킷 또는 액세스 지점 정책을 통해 부여된 버킷 및 객체에 대한 퍼블릭 및 교차 계정 액세스 차단</li>
</ul>
<h2 id="s3-권한-설정">S3 권한 설정</h2>
<h3 id="1-사용자를-생성하고-사용자의-버킷-액세스-권한을-관리하는-iam">1. 사용자를 생성하고 사용자의 버킷 액세스 권한을 관리하는 IAM</h3>
<h3 id="2-권한있는-사용자에-대해-개별-객체를-액세스-가능하게-만드는-acl">2. 권한있는 사용자에 대해 개별 객체를 액세스 가능하게 만드는 ACL</h3>
<h3 id="3-단일-s3-버킷-내-모든-객체에-대한-권한을-세부적으로-구성하는-버킷-정책">3. 단일 S3 버킷 내 모든 객체에 대한 권한을 세부적으로 구성하는 버킷 정책</h3>
<h3 id="4-임시-url을-사용하여-다른-사용자에게-임시-권한-액세스를-부여하는-쿼리-문자열-인증-pre-signed-url">4. 임시 URL을 사용하여 다른 사용자에게 임시 권한 액세스를 부여하는 쿼리 문자열 인증 (pre-signed URL)</h3>
]]></description>
        </item>
        <item>
            <title><![CDATA[정적 웹 사이트 호스팅]]></title>
            <link>https://velog.io/@eeeasy-code/%EC%A0%95%EC%A0%81-%EC%9B%B9-%EC%82%AC%EC%9D%B4%ED%8A%B8-%ED%98%B8%EC%8A%A4%ED%8C%85</link>
            <guid>https://velog.io/@eeeasy-code/%EC%A0%95%EC%A0%81-%EC%9B%B9-%EC%82%AC%EC%9D%B4%ED%8A%B8-%ED%98%B8%EC%8A%A4%ED%8C%85</guid>
            <pubDate>Mon, 06 Nov 2023 12:11:46 GMT</pubDate>
            <description><![CDATA[<p>정적 웹 사이트는 백엔드 처리 없이 static한 컨텐츠를 갖는다. 이러한 컨텐츠에는 HTML, CSS, JS, 이미지 등의 웹 사이트를 렌더링하는 데 필요한 모든 파일이 포함될 수 있다. </p>
<p><img src="https://velog.velcdn.com/images/eeeasy-code/post/222679ff-7f82-4b47-bae0-2630824d6bd6/image.png" alt=""></p>
<p>컨텐츠를 업로드하고 공개적인 액세스를 허용하여 AWS S3에 손쉽게 정적 웹 사이트를 호스팅할 수 있다. S3를 사용하면 서버가 따로 필요하지 않으며 웹 상 어디에서나 언제든지 원하는 양의 데이터를 저장하고 검색할 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/eeeasy-code/post/602772e0-a92b-4e52-bbe5-66b50a6f497c/image.png" alt=""></p>
<h1 id="aws-s3를-사용하여-정적-웹-사이트-호스팅">AWS S3를 사용하여 정적 웹 사이트 호스팅</h1>
<p>본 실습에서는 AWS S3 버킷에 static한 컨텐츠를 업로드하여 정적인 웹 사이트를 호스팅할 예정이다. </p>
<h2 id="s3-bucket-생성">S3 Bucket 생성</h2>
<p>S3 버킷 이름은 전 세계에서 유일한 이름을 사용해야 한다. 그리고 본인이 사용할 리전을 잘 맞추어 설정해준다. 
<img src="https://velog.velcdn.com/images/eeeasy-code/post/7c3b5411-5849-4362-bd03-45624153f38d/image.png" width="70%" height="30"></p>
<h2 id="bucket-퍼블릭-액세스-차단-설정">Bucket 퍼블릭 액세스 차단 설정</h2>
<p>버킷에 대한 퍼블릭 액세스는 기본적으로 차단된다. 정적 웹 사이트의 파일은 인터넷을 통해 액세스할 수 있어야 하므로, 퍼블릭 액세스를 허용해야 한다.
<img src="https://velog.velcdn.com/images/eeeasy-code/post/4f5983b2-ef6e-4db0-96c4-dfe8dff4a112/image.png" width="70%" height="30"></p>
<h2 id="생성된-bucket-확인">생성된 Bucket 확인</h2>
<p>위와 같은 설정을 잘 마쳤다면, 생성된 버킷을 아래와 같이 확인할 수 있을 것이다.
<img src="https://velog.velcdn.com/images/eeeasy-code/post/dbfad8f3-ae8f-46c0-a764-1b61a681823b/image.png" width="70%" height="30"></p>
<h2 id="정적-웹-사이트-호스팅-설정">정적 웹 사이트 호스팅 설정</h2>
<p>버킷의 속성 메뉴에 정적 웹 사이트 호스팅 설정이 있는데, 아래와 같이 설정을 진행해준다.
인덱스 문서와 오류 문서에는 예시에 나와있는 것과 같이 그대로 입력해 주어야 한다.
<img src="https://velog.velcdn.com/images/eeeasy-code/post/9e5f28df-55d4-4f07-99d9-ea2d539254e2/image.png" width="70%" height="30"></p>
<p>이후에 버킷에 html, css, js 등의 콘텐츠를 업로드해준다. 
<img src="https://velog.velcdn.com/images/eeeasy-code/post/c514cfd8-b686-450c-a7c0-bdcba2c3b87e/image.png" width="70%" height="30">
정적 웹 사이트 호스팅을 설정하면서 생성된 url을 통해 접속해본다. 현재 버킷 권한을 아직 구성하지 않았기 때문에 403 Forbidden 에러가 표시된다. 
<img src="https://velog.velcdn.com/images/eeeasy-code/post/96dd6af8-1d02-4d92-8729-d7ab10f549f9/image.png" width="70%" height="30"></p>
<h2 id="객체에-대한-액세스-활성화">객체에 대한 액세스 활성화</h2>
<p>AWS S3의 객체를 퍼블릭으로 설정할 수 있는 방법에는 두 가지가 존재한다.</p>
<ol>
<li>전체 버킷이나 버킷의 특정 디렉터리를 퍼블릭으로 설정하려면 <Strong>버킷 정책</Strong>을 사용한다.</li>
<li><Strong>액세스 제어 목록(ACL)</Strong>을 사용하여 버킷의 개별 객체를 퍼블릭으로 설정할 수도 있다.</li>
</ol>
<p>일반적으로 <i>개별 객체</i>를 퍼블릭으로 설정하면 실수로 다른 객체를 공개하는 일이 발생하지 않아 더 안전하다. 그러나 전체 버킷에 민감한 정보가 포함되지 않은 경우에는 <i>버킷 정책</i>을 사용해도 상관없다.</p>
<p>나는 본 실습에서 ACL을 사용하여 버킷의 개별 객체를 퍼블릭으로 설정하였다.
<img src="https://velog.velcdn.com/images/eeeasy-code/post/7174b848-27ff-4138-a7b1-d9b0f8dc3a2e/image.png" width="70%" height="30"></p>
<p>객체를 퍼블릭으로 설정한 이후에 정적 웹 사이트 url에 다시 접속해보자. 그럼 아래와 같이 퍼블릭으로 변경된 객체의 컨텐츠들이 적절하게 호스팅되어 표현되는 것을 확인할 수 있다.
<img src="https://velog.velcdn.com/images/eeeasy-code/post/bece6555-eb8f-4de2-9a58-15713f8e7ae2/image.png" width="70%" height="30"></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[배포 전략 종류 (롤링 / 블루 · 그린 / 카나리)]]></title>
            <link>https://velog.io/@eeeasy-code/%EB%B0%B0%ED%8F%AC-%EC%A0%84%EB%9E%B5-%EC%A2%85%EB%A5%98-%EB%A1%A4%EB%A7%81-%EB%B8%94%EB%A3%A8-%EA%B7%B8%EB%A6%B0-%EC%B9%B4%EB%82%98%EB%A6%AC</link>
            <guid>https://velog.io/@eeeasy-code/%EB%B0%B0%ED%8F%AC-%EC%A0%84%EB%9E%B5-%EC%A2%85%EB%A5%98-%EB%A1%A4%EB%A7%81-%EB%B8%94%EB%A3%A8-%EA%B7%B8%EB%A6%B0-%EC%B9%B4%EB%82%98%EB%A6%AC</guid>
            <pubDate>Sun, 05 Nov 2023 17:25:09 GMT</pubDate>
            <description><![CDATA[<h1 id="무중단-배포">무중단 배포</h1>
<p>무중단 배포란 <strong> 배포 중 서비스 기능이 멈추지 않고, 실제 사용자들이 정상적으로 서비스를 사용할 수 있는 기능</strong>을 제공하는 배포 방식이다.</p>
<p>MSA의 발전으로 서비스 별로 적절한 기술 스택과 소규모 배포를 가능하게 하여, Agile 프로세스를 통해 스프린트 단위로 기능을 유동적으로 개발할 수 있게 하고, docker를 통해 컨테이너 환경과 높은 이식성으로 안정적이고 빠른 배포 환경을 구축할 수 있게 된다.</p>
<p>무중단 배포는 공통점이 두 가지 존재한다.</p>
<h2 id="1-서버는-최소-두-개-이상-존재">1. 서버는 최소 두 개 이상 존재</h2>
<p><img src="https://velog.velcdn.com/images/eeeasy-code/post/4f1d6585-d7fc-4fd4-8785-c647b7b6d3ed/image.png" alt=""></p>
<p>서버를 배포하기 위해서는 결국에 잠깐이라도 서비스 중인 서버가 내려가고 다시 서버가 동작하는 시간 즉, downtime이 필요하기 때문에 절대 단일 서버로 무중단 배포 시스템을 구축할 수 없다.</p>
<h2 id="2-로드밸런서가-필요">2. 로드밸런서가 필요</h2>
<p><img src="https://velog.velcdn.com/images/eeeasy-code/post/13ceacda-a3d3-464e-a4a4-b5ae527b626c/image.gif" alt=""></p>
<p>먼저, 프론트엔드 단과 백엔드 단이 직접적으로 연결되어 있다고 보자. 무중단 배포를 위해, 프론트엔드 단에서는 모든 서버에 대한 각각의 IP를 알고 있어야하고 이 서버들 중 어떤 서버가 현재 사용 가능한지 찾아 그 서버에 요청을 날려야 한다. 또한, 트래팩에 대한 정보가 일괄적으로 관리되지 않아, 유동적인 트래픽 관리도 불가능해 배포 과정에서 서비스가 정상적으로 운영될 수 있는지 확인도 어렵다.</p>
<p>따라서 서버 앞 단에 로드밸런서를 둬서 클라이언트 요청을 받아서 처리하는 환경을 구성한다. </p>
<h1 id="배포-전략-종류">배포 전략 종류</h1>
<p>무중단 배포 이전의 모습은 서비스 중인 서버를 멈추고, 이 후에 새로운 버전을 배포하여 재가동하는 형태이다.
<img src="https://velog.velcdn.com/images/eeeasy-code/post/e8ef036c-0c77-4f94-8749-51ff293b2329/image.png" alt=""></p>
<p>무중단 배포 전략은 3가지가 있다. 각 전략은 호환성, 자원 효율성, 안정성 등의 측면에서 차별화된다.</p>
<h2 id="1-롤링-배포">1. 롤링 배포</h2>
<p><img src="https://velog.velcdn.com/images/eeeasy-code/post/86f5d3f2-74ea-4d87-81a9-ceded46c15d9/image.png" alt=""></p>
<p>롤링 배포는 기존 운영중인 서버 중 일부 단위만큼씩 새 버전으로 점진적으로 교체하는 방식이다. 하지만, 그 동안 가용 가능한 서버 자원이 줄어들기 때문에, 서버 자원이 충분한지 확실한 검증 하에 진행되어야 한다. 또한, 구 버전과 신 버전이 같이 서비스되기 때문에 호환성 검증도 필요하다. </p>
<blockquote>
<p><strong> 단점 </strong></p>
</blockquote>
<ul>
<li>구 버전과 신 버전의 호환성 확인 필요</li>
<li>배포동안 가용 가능한 서버 자원 감소</li>
</ul>
<h2 id="2-블루-·-그린-배포">2. 블루 · 그린 배포</h2>
<p><img src="https://velog.velcdn.com/images/eeeasy-code/post/9e2423a8-e073-49fd-b1cf-d1f36ff626e3/image.png" alt=""></p>
<p>기존 버전(블루)에 연결되어 있던 트래픽을 일괄적으로 신 버전(그린)으로 전환하는 배포 방식이다. 또한, 한꺼번에 모든 서비스를 전환하기 때문에, 신 버전이 정상적으로 동작하는지에 대한 테스트가 진행되어야 한다. 다만, 일반적인 배포 방식보다 서버 자원을 두 배로 유지해야 한다는 단점이 있다.</p>
<blockquote>
<p><strong>장점</strong></p>
</blockquote>
<ul>
<li>구 버전과 신 버전에 대한 호환성 확인이 필요없음</li>
<li>신 버전을 미리 배포하기 때문에, 실제와 동일한 환경에서 미리 테스트 가능<blockquote>
</blockquote>
<strong>단점</strong></li>
<li>서버 자원을 두 배로 유지해야 함</li>
<li>신 버전에 대한 테스트 선행 필요</li>
</ul>
<h2 id="3-카나리-배포">3. 카나리 배포</h2>
<p><img src="https://velog.velcdn.com/images/eeeasy-code/post/7d00aea6-e711-4cc0-966c-142da7d33d58/image.png" alt=""></p>
<p>카나리 배포는 롤링 배포와 블루-그린 배포를 합쳐놓은 배포 방식이다. 신 버전의 비율을 유동적으로 늘려가는 롤링 배포 + 실제 환경에서 미리 테스트 진행하는 블루-그린 배포
위험을 빠르게 감지할 수 있는 배포 전략으로, 지정한 서버 또는 특정 사용자에게만 배포했다가 정상적으로 작동하면 전체를 배포한다. 서버의 트래픽의 일부를 신 버전으로 분산시켜 오류 여부를 확인할 수 있다. 이런 전략은 A/B 테스트가 가능하며, 성능 모니터링에 유용하다. 트래픽을 분산시킬 때에는 라우팅을 랜덤하게 혹은 사용자로 분류 가능하다.</p>
<blockquote>
<p><strong>장점</strong></p>
</blockquote>
<ul>
<li>위험 상황 빠르게 감지</li>
<li>A/B 테스트로 활용 가능<blockquote>
</blockquote>
<strong>단점</strong></li>
<li>네트워크 트래픽 제어에 대한 부담</li>
</ul>
<p>A/B 테스트 -&gt; 대조군과 실험군으로 나누어 특정한 UI나 알고리즘의 효과를 비교하는 방법론</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[AWS 계정 기초 보안 설정]]></title>
            <link>https://velog.io/@eeeasy-code/AWS-%EA%B3%84%EC%A0%95-%EA%B8%B0%EC%B4%88-%EB%B3%B4%EC%95%88-%EC%84%A4%EC%A0%95</link>
            <guid>https://velog.io/@eeeasy-code/AWS-%EA%B3%84%EC%A0%95-%EA%B8%B0%EC%B4%88-%EB%B3%B4%EC%95%88-%EC%84%A4%EC%A0%95</guid>
            <pubDate>Fri, 03 Nov 2023 10:04:20 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/eeeasy-code/post/3b4ae564-694e-4e14-9bb5-7e141166c0ef/image.png" alt=""></p>
<h1 id="aws-계정-보안">AWS 계정 보안</h1>
<p>AWS 계정에서 루트 계정의 Access Key를 탈취하여 과금을 유도하거나 불법적인 행위를 인스턴스에서 실행하게 하는 등의 악성 행위가 발생할 수 있다. 이는, 개인에게 금전적으로 위협이 되거나 실제 서비스를 사용하고 있는 기업의 입장에서 엄청나게 큰 위험이다. </p>
<p>루트 계정의 자격이 필요한 작업이 몇가지 존재한다. 계정의 이름, 이메일 주소, 암호 변경, 결제/비용에 대한 IAM 액세스 활성화, 지원 플랜 변경/취소, S3 버킷의 일부 설정, 계정 해지 등의 작업은 루트 사용자 권한이 필요하다. 그 외에는 권한이 부여된 IAM 사용자 자격으로 모든 작업을 할 수 있습니다. 따라서, 루트 사용자에 대한 기본 보안 설정을 완료한 다음에는 적절한 자격을 부여한 IAM 사용자를 생성하고 주로 IAM 사용자로 모든 작업을 하는 것이 안전하다.</p>
<p>AWS 클라우드 서비스를 사용하기 위해 계정을 가입하고 가장 먼저해야 할 설정에 대해 알아보려 한다.</p>
<h1 id="aws-계정-기초-보안-설정">AWS 계정 기초 보안 설정</h1>
<h2 id="루트-사용자-mfa-설정">루트 사용자 MFA 설정</h2>
<p>루트 사용자 계정에 대한 MFA 설정이다.</p>
<h3 id="mfamulti-factor-authentication">MFA(Multi-Factor Authentication)</h3>
<p>MFA는 계정에 대한 2차 인증을 실시하는 것을 말한다. 이를 통해, 해킹의 위험에 대해 방지할 수 있다.
MFA를 활성화하면 사용자가 AWS 웹 사이트에 로그인할 때 계정과 암호뿐만 아니라 AWS MFA 디바이스의 6 자리 인증코드를 입력하게 된다.
이러한 다중 요소를 통해 AWS 계정 설정 및 리소스에 대한 보안을 높일 수 있다.
<img src="https://velog.velcdn.com/images/eeeasy-code/post/00c79240-e443-472b-b393-5672eeb474e4/image.png" alt="">
위와 같이 MFA 디바이스 관리에 대한 설정을 진행하면 된다.</p>
<h2 id="루트-사용자-access-key-삭제">루트 사용자 Access Key 삭제</h2>
<p>액세스 키는 아이디/패스워드 인증과 동일한 권한을 갖지만 AWS CLI, PowerShell용 도구, AWS SDK 또는 직접 AWS API 호출을 통해 AWS를 프로그래밍 방식으로 호출할 수 있도록 해준다. 반드시 필요한 용도이지만 액세스 키가 루트 사용자 권한으로 사용될 때는 그 용도 만큼이나 매우 강력해서 탈취되어 악용하면 광범위한 영역에서 피해를 줄 수 있다. 따라서, 특별한 이유가 없다면 루트 사용자 계정에는 반드시 액세스 키를 삭제하거나 비활성화되어 있어야 한다.</p>
<h2 id="iam-사용자-설정">IAM 사용자 설정</h2>
<p>루트 계정 · 사용자를 사용하지 않고, IAM 사용자나 그룹에 Admin 권한 등을 부여하여 관리한다. 이후, 조직의 특성에 맞게 IAM 사용자와 그룹에 적절한 권한을 부여하여 사용한다. 이때, 모든 권한은 &quot;최소 권한의 법칙&quot;을 따른다.
<br></p>
<hr>
어느 서비스를 사용하던 보안에 관한 설정은 항상 민감하게 반응하고 대응해야 한다. 특히나, 개인 정보와 같이 민감한 데이터를 사용하는 조직이라면 더더욱 보안에 대해 관심을 가져야 한다.]]></description>
        </item>
        <item>
            <title><![CDATA[IAM (AWS Identity & Access Management)]]></title>
            <link>https://velog.io/@eeeasy-code/IAM-AWS-Identity-Access-Management</link>
            <guid>https://velog.io/@eeeasy-code/IAM-AWS-Identity-Access-Management</guid>
            <pubDate>Fri, 03 Nov 2023 08:17:59 GMT</pubDate>
            <description><![CDATA[<h2 id="iam-구조">IAM 구조</h2>
<p><img src="https://velog.velcdn.com/images/eeeasy-code/post/ae67e461-23d0-4620-aa16-1e990a5116ef/image.png" alt=""></p>
<h2 id="실습-시나리오">실습 시나리오</h2>
<p><img src="https://velog.velcdn.com/images/eeeasy-code/post/5a250875-0d96-49c6-a4cf-1a73da762a36/image.png" alt=""></p>
<p>IAM 사용자(user-1, user-2, user-3)와 IAM 그룹(S3-Support, EC2-Support, EC2-Admin)을 생성 후, IAM 그룹과 권한을 맵핑하고 그룹에 사용자를 추가하여 실습을 진행하게 된다.</p>
<h3 id="iam-그룹">IAM 그룹</h3>
<p><img src="https://velog.velcdn.com/images/eeeasy-code/post/44b3a231-cef5-476a-b45b-221a9024fa53/image.png" alt="">
생성된 각 그룹에 사용자를 시나리오에 맞게 연결해준 뒤, 확인해보면 그룹에 사용자가 1로 등록되어 있는 것을 확인할 수 있다.</p>
<h3 id="생성된-ec2-admin-그룹">생성된 EC2-Admin 그룹</h3>
<p><img src="https://velog.velcdn.com/images/eeeasy-code/post/f0b54774-e7bd-4619-a84d-aea00cf610f1/image.png" alt=""></p>
<h3 id="ec2-admin-그룹에-맵핑되어-있는-정책">EC2-Admin 그룹에 맵핑되어 있는 정책</h3>
<p><img src="https://velog.velcdn.com/images/eeeasy-code/post/75774945-49f4-40e0-8443-0d95d1c5a1ff/image.png" alt=""></p>
<p>EC2-Admin 그룹에 맵핑되어 있는 정책이다.</p>
<h3 id="user-1-사용자">user-1 사용자</h3>
<p>IAM 대시보드에서 IAM 계정 로그인 URL을 브라우저에 입력하면, 아래와 같은 페이지로 로그인을 할 수 있다. 
<img src = "https://velog.velcdn.com/images/eeeasy-code/post/ecc47453-4b3e-45ec-94a5-aa380a0c520a/image.png" width = "30%"> </p>
<p>user-1 계정은 S3-Support 그룹에 속해있으므로, S3에 관련된 권한만 부여되어 있는 상황이다. 해당 계정으로 EC2 인스턴스 항목을 접근하게 되면 아래와 같이 권한 거부를 반환하는 것을 확인할 수 있다.
<img src="https://velog.velcdn.com/images/eeeasy-code/post/e9aecd41-8e56-49d1-a61a-5a041c0b8ef0/image.png" alt=""></p>
<h3 id="user-2-사용자">user-2 사용자</h3>
<p>user-1과 같이 user-2도 IAM 계정으로 로그인한다.
<img src = "https://velog.velcdn.com/images/eeeasy-code/post/7877cf91-8a11-4326-bc26-809f79250beb/image.png" width = "30%"> 
user-2 계정은 EC2-Support 그룹에 속해있으므로, EC2 인스턴스를 확인할 수 있다. EC2 메뉴에서 인스턴스를 클릭하게 되면 아래와 같이 인스턴스 항목에 대해 확인할 수 있다.
<img src="https://velog.velcdn.com/images/eeeasy-code/post/46a850c7-8abb-488e-8f00-6139e2b38e4e/image.png" alt="">
해당 계정의 권한에는 EC2 인스턴스에 대한 제어권이 허가되지 않았으므로, 아래와 같이 인스턴스를 중지하려고 할 경우 실패하는 것을 확인할 수 있다.
<img src="https://velog.velcdn.com/images/eeeasy-code/post/0cfe31bf-da99-4016-895c-9019f19833cd/image.png" alt=""></p>
<h3 id="user-3-사용자">user-3 사용자</h3>
<p>user-3도 로그인해준다.
<img src = "https://velog.velcdn.com/images/eeeasy-code/post/6a15f01f-17df-4757-bd95-ead994c8a7ba/image.png" width = "30%">
user-3 계정은 EC2-Admin 그룹에 속해있으므로, EC2 인스턴스에 대한 대부분의 권한을 가지고 있다. 그렇기 때문에, 아래와 같이 EC2 인스턴스 중지를 실행하였을 때 성공적으로 중지가 되는 것을 확인할 수 있다.
<img src="https://velog.velcdn.com/images/eeeasy-code/post/985ecbe7-413f-44e9-b138-15543f0a0b20/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CISC-S'23]]></title>
            <link>https://velog.io/@eeeasy-code/CISC-S23</link>
            <guid>https://velog.io/@eeeasy-code/CISC-S23</guid>
            <pubDate>Fri, 30 Jun 2023 17:33:51 GMT</pubDate>
            <description><![CDATA[<h3 id="처음써본-논문으로-학회-우수논문상까지-수상할-줄은-꿈에도-몰랐지">처음써본 논문으로 학회 우수논문상까지 수상할 줄은 꿈에도 몰랐지?</h3>
<p>5월초였나, 연구실에서 갑자기 나보고 논문을 써야한다고 했었다. 나는 그때가 기말고사 기간이기도 했고, 연구실에서 진행하고 있는 과제도 있었고? 또, 조교 활동도 매주 목,금,토 진행도 하고... 이번 학기 성적이 4.25를 넘지 못하면 학석사 연계 전형을 지원하지도 못하게 될 수 있다는 부담감이 컸다.. 
사실 논문을 쓰라고 했을 때, 난 진짜 못하겠다 이 말 밖에 안나왔다. 그래도, 내 담당 석사님의 열렬한 관심과 피드백 덕분에 어떻게든 title 부터 시작해서 본문을 작성하고... 결론까지 작성했다. </p>
<p><strong>그래서.. 결과는?</strong></p>
<img src = "https://velog.velcdn.com/images/eeeasy-code/post/3a0688f3-793f-4835-a198-477a44355c05/image.JPG" width = "65%" height = "30%" align='left'>
<img src = "https://velog.velcdn.com/images/eeeasy-code/post/5ec2e7b8-8761-46d3-919e-2f86cc70b86c/image.jpg" width = "35%" height = "30%" align='right'>

<p>짠..!
학회 우수논문상도 받았고, 무려 KISA의 취약점 신고포상제를 운영하셨던 분이 좌장님으로....
웃긴건 내 논문 주제가 국내외 버그바운티 운영 제도에 대한 문제점을 식별해서 해결방안을 제시하는 것인데, 공교롭게 KISA의 취약점 신고포상제에 대한 문제점을 주제로 잡았다는 거...
그래도, 좌장님께서 나의 의견을 긍정적으로 검토해 KISA에 직접 문의해보겠다고 하셨다..ㅎㅎ</p>
<p>아무튼 나의 첫 정보보호학회 학술대회는 이렇게 성공적으로 마무리할 수 있었다!!! </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[2022년 회고 & 2023년 목표]]></title>
            <link>https://velog.io/@eeeasy-code/2022%EB%85%84-%ED%9A%8C%EA%B3%A0-2023%EB%85%84-%EB%AA%A9%ED%91%9C</link>
            <guid>https://velog.io/@eeeasy-code/2022%EB%85%84-%ED%9A%8C%EA%B3%A0-2023%EB%85%84-%EB%AA%A9%ED%91%9C</guid>
            <pubDate>Fri, 13 Jan 2023 17:01:09 GMT</pubDate>
            <description><![CDATA[<p>2022년은 나에게 너무 다사다난한 해였다. 스타트업에 들어가서 백엔드 개발 업무를 담당했다. node.js 를 사용하다가 nestJS로 갈아타고, kotlin + spring boot로 정착했다. 그 뒤로는 AWS와 serverless framework 기반의 서비스를 제작했다. lambda 환경에서의 제약 조건이 많아, 아예 nestJS 기반의 서비스로 바꾼게 마지막 업무이다. 이런저런 일들로 인해 12월까지만 일을하고 그만두게 되었다. 
회사와 랩실, 학업까지 병행하다보니 번아웃이 정말 자주왔고, 모든 것을 포기하고 싶었다. 그렇게 랩실, 회사를 그만두었다. 또, 주변에 있던 많은 사람들을 잃게 되었다. 그럼에도 나를 믿어주고 응원해주는 사람이 있었고, 그 사람들을 위해 더 노력해야겠다는 동기부여를 받았다. 절대 놓치지 말자.</p>
<p>개발을 하면서 느낀 것은 배울 것이 굉장히 많고, 잘한다는 기준도 굉장히 추상적이라는 것을 느꼈다. 특히, 배워야 할 것이 많다는 것을 뼈져리게 느꼈는데, 예로 AWS 기술만 하여도 그 밑에 세부적인 기능들이 너무 많고 모르면 사용하는 것이나 효율적으로 다루는 것이 어렵다. 그래서 현재 위치에 만족하면 안되고, 계속 스스로를 발전시키려면 꾸준한 공부가 뒷받침 되어야 한다는 것을 느꼈다.</p>
<p>누구에게나 필요하고 도움이 되는 그런 사람이 되고 싶다. 모두가 좋아할 수는 없겠지만 다수가 좋아하고 무리의 분위기를 바꿀 수 있는 사람이 될 것이다. 포기하지 않고 정말 열심히 몰입하는 습관과 확언하는 습관을 꼭 갖고싶다.</p>
<h3 id="2022년에-내가-이루어낸-것">2022년에 내가 이루어낸 것</h3>
<ol>
<li>학업에 충실했던 나 (4.4/4.5) -&gt; 전공학점 4.5/4.5</li>
<li>개발 실무 경험 (Back-End 개발자로 1년)</li>
<li>힘든 상황에 나를 응원해 주는 사람을 남겨둔 것</li>
<li>운동하는 습관</li>
<li>힘들어도 도전하는 정신</li>
<li>전역</li>
</ol>
<h3 id="2023년에-이루고-싶은-것">2023년에 이루고 싶은 것</h3>
<p>&lt;생활&gt;</p>
<ol>
<li>명확한 나의 진로 &amp; 공부 방향성 잡기</li>
<li>모두가 좋아하는 사람되는 것</li>
<li>운동을 꾸준히 하는 것</li>
<li>높은 학점을 꾸준히 유지하는 것</li>
<li>포기하지 않는 습관</li>
<li>성장하기</li>
<li>확언하기 (내가 뱉은 말은 전부 지킬 것)</li>
</ol>
<p>&lt;개발&gt;</p>
<ol>
<li>알고리즘 &amp; 자료구조에 미쳐보기</li>
<li>나의 진로에 맞는 프로젝트 진행해보기 &amp; 책을 따라서 개인 프로젝트 진행</li>
<li>1일 1커밋</li>
<li>CS 지식을 천천히 쌓아가기</li>
<li>인프런 강의 열심히 듣기</li>
<li>블로그와 포트폴리오 열심히 작성하기</li>
</ol>
<p>아무쪼록 힘든 2022년을 나름 잘 보냈으니, 2023년은 나의 포텐셜을 터트릴 수 있는 그런 해가 되었으면 좋겠다.</p>
]]></description>
        </item>
    </channel>
</rss>