<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>dev-dk.log</title>
        <link>https://velog.io/</link>
        <description>끊임없이 도전하고, 실패에서 배우는 백엔드 개발자입니다.</description>
        <lastBuildDate>Sun, 28 Apr 2024 14:49:30 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>dev-dk.log</title>
            <url>https://velog.velcdn.com/images/dukov-dev/profile/f4d941b2-d0a4-4506-82d1-409501dbfd7c/image.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. dev-dk.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/dukov-dev" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[OAuth 이해하기]]></title>
            <link>https://velog.io/@dukov-dev/About-OAuth</link>
            <guid>https://velog.io/@dukov-dev/About-OAuth</guid>
            <pubDate>Sun, 28 Apr 2024 14:49:30 GMT</pubDate>
            <description><![CDATA[<h2 id="oauth란">OAuth란?</h2>
<p>OAuth(Open Authorization)는 사용자가 로그인 자격 증명을 타사 애플리케이션과 공유하지 않으면서도, 타사 애플리케이션에게 다른 서비스에 존재하는 사용자의 리소스에 대한 액세스 권한을 제한적으로 부여할 수 있도록 하는 표준 인가(Authorization) 프로토콜입니다.</p>
<p>여기서 로그인 자격 증명이라고 하는것은 보통 ID, PW 등이 될 것이고, 타사 애플리케이션은 일반적인 웹 애플리케이션을 이야기합니다. 또한 다른 서비스에 존재하는 사용자 리소스란 보통 구글, 네이버, 페이스북 등이 보유한 사용자 정보를 말합니다.</p>
<p>OAuth를 사용하면 사용자로부터 ID나 PW 등 민감정보를 받을 필요 없이 구글, 네이버, 페이스북 등에 등록된 사용자 정보를 이용해 서비스를 제공 할 수 있습니다.</p>
<p>OAuth는 인증(Authentication) 보다는 인가(Authorization) 프로토콜에 가깝습니다. 사용자의 신원을 확인하는 것이 아니라 사용자가 리소스에 대한 액세스 권한을 부여했는지 확인합니다. </p>
<p>OAuth는 종합적인 인증 및 권한 부여 솔루션을 제공하기 위해 OpenID Connect와 같은 인증 프로토콜과 함께 사용되는 경우가 많습니다.</p>
<h3 id="oauth의-구성-요소">OAuth의 구성 요소:</h3>
<ul>
<li><p><strong>리소스 소유자(Resource Owner)</strong>: 일반적으로 데이터를 소유한 사용자입니다.</p>
</li>
<li><p><strong>클라이언트(Client)</strong>: 사용자 데이터에 대한 액세스를 요청하는 타사 애플리케이션입니다.</p>
</li>
<li><p><strong>리소스 서버(Resource Server)</strong>: 리소스 소유자의 데이터를 보호하고, 호스팅하는 서버입니다.</p>
</li>
<li><p><strong>권한 부여 서버(Authorization Server)</strong>: 리소스 소유자를 인증하고, 클라이언트에 토큰을 발급하는 서버입니다.</p>
</li>
</ul>
<hr>
<h2 id="oauth를-사용하는-이유">OAuth를 사용하는 이유</h2>
<h3 id="보안">보안</h3>
<p>OAuth는 기존 방식에 비해 더욱 안전하게 사용자를 인증하고 권한을 부여하는 방법입니다. 타사 애플리케이션과 비밀번호를 공유할 필요가 없으므로 피싱 공격과 비밀번호 도용의 위험이 줄어듭니다.</p>
<ul>
<li><p><strong>비밀번호 보호</strong>: OAuth를 사용하면 사용자가 타사 애플리케이션과 비밀번호를 공유할 필요가 없으므로 비밀번호 도용 및 피싱 공격의 위험이 줄어듭니다.</p>
</li>
<li><p><strong>제한적인 접근 권한</strong>: OAuth를 사용하면 타사 애플리케이션에게 제한적으로 사용자의 리소스에 대한 액세스 권한을 부여할 수 있어 민감한 정보에 대한 무단 액세스 위험을 줄일 수 있습니다.</p>
</li>
<li><p><strong>안전한 토큰 교환</strong>: OAuth는 보안 토큰 교환 메커니즘을 사용하여 클라이언트와 권한 부여 서버 간에 액세스 토큰이 안전하게 교환되도록 합니다.</p>
</li>
</ul>
<h3 id="편리함">편리함</h3>
<p>OAuth를 이용하면 애플리케이션 사용자가 새 계정을 만들 필요가 없습니다. </p>
<p>사용자는 애플리케이션에게 리소스에 대한 액세스 권한을 부여하는데 동의하는 것 만으로 애플리케이션을 이용할 수 있기 때문에 매끄러운 사용자 경험을 제공하는 데 큰 도움이 됩니다.</p>
<ul>
<li><p><strong>싱글 사인 온(SSO)</strong>: 사용자는 단일 로그인 자격 증명으로 여러 애플리케이션에 액세스할 수 있게 됩니다.</p>
</li>
<li><p><strong>비밀번호 피로감 감소</strong>: 사용자가 여러 개의 비밀번호를 기억할 필요가 없으므로 비밀번호 피로도를 줄여줍니다.</p>
</li>
<li><p><strong>매끄러운 사용자 경험</strong>: 사용자가 클릭 한 번으로 리소스에 대한 액세스 권한을 부여할 수 있도록 하여 매끄러운 사용자 환경을 제공합니다.</p>
</li>
</ul>
<h3 id="유연함">유연함</h3>
<p>OAuth를 사용하면 개발자는 여러 서비스와 상호 작용할 수 있는 애플리케이션을 구축하여 보다 포괄적이고 통합된 사용자 경험을 제공할 수 있습니다.</p>
<ul>
<li><strong>다중 서비스 통합</strong>: OAuth를 사용하면 개발자가 여러 서비스를 단일 애플리케이션에 통합하여 보다 포괄적인 사용자 경험을 제공할 수 있습니다.</li>
<li><strong>넓은 생태계</strong>: OAuth는 개발자가 애플리케이션에서 OAuth를 구현하는 데 사용할 수 있는 많은 라이브러리와 프레임워크를 갖춘 대규모의 활발한 생태계를 갖추고 있습니다.</li>
</ul>
<hr>
<h2 id="oauth-사용하기">OAuth 사용하기</h2>
<h3 id="oauth의-작동-방식">OAuth의 작동 방식</h3>
<ol>
<li><p><strong>클라이언트 등록</strong>: 클라이언트(타사 애플리케이션)가 권한 부여 서버에 등록하고 Client ID, Client Secret을 받아옵니다.</p>
</li>
<li><p><strong>인증 요청</strong>: 클라이언트가 사용자를 권한 부여 서버로 리디렉션하여 리소스에 대한 액세스를 요청합니다.</p>
</li>
<li><p><strong>사용자 인증</strong>: 사용자가 로그인 자격 증명을 사용하여 권한 부여 서버에 인증합니다.</p>
</li>
<li><p><strong>권한 부여</strong>: 사용자가 리소스에 대한 액세스 권한을 승인하고 권한 부여 서버가 권한 부여 코드를 사용하여 사용자를 클라이언트로 리디렉션합니다.</p>
</li>
<li><p><strong>액세스 토큰 요청</strong>: 클라이언트가 권한 부여 코드를 사용하여 권한 부여 서버에 액세스 토큰을 요청합니다.</p>
</li>
<li><p><strong>액세스 토큰 응답</strong>: 권한 부여 서버는 액세스 토큰으로 응답하며, 클라이언트는 이 토큰을 사용하여 사용자의 리소스에 액세스합니다.</p>
</li>
</ol>
<h3 id="oauth-스코프">OAuth 스코프</h3>
<p>OAuth 스코프는 클라이언트에 액세스 권한이 있는 특정 리소스 및 작업을 정의합니다. </p>
<p>스코프는 클라이언트가 사용자의 리소스에 액세스할 수 있는 범위를 제한하는 데 사용됩니다.</p>
<ul>
<li><p><strong>스코프 유형</strong>: 스코프에는 읽기 전용과 읽기-쓰기의 두 가지 유형이 있습니다. 읽기 전용 스코프는 클라이언트가 사용자의 리소스를 읽을 수 있도록 허용하고, 읽기-쓰기 스코프는 클라이언트가 사용자의 리소스를 읽고 쓸 수 있도록 허용합니다.</p>
</li>
<li><p><strong>스코프 유효성 검사</strong>: 권한 부여 서버는 클라이언트가 요청한 스코프의 유효성을 검사하여 사용자가 요청된 리소스에 대한 액세스 권한을 클라이언트에게 부여했는지 확인합니다.</p>
</li>
</ul>
<h3 id="oauth-토큰">OAuth 토큰</h3>
<p>OAuth 토큰은 클라이언트를 인증하고 권한을 부여하는 데 사용됩니다. 토큰에는 두 가지 유형이 있습니다:</p>
<ul>
<li><strong>액세스 토큰</strong>: 사용자의 리소스에 액세스하는 데 사용되는 수명이 짧은 토큰입니다. 액세스 토큰은 일반적으로 짧은 시간 동안 유효합니다.</li>
<li><strong>리프레시 토큰</strong>: 기존 토큰이 만료될 때 새 액세스 토큰을 받는 데 사용되는 수명이 긴 토큰입니다. 리프레시 토큰은 일반적으로 더 긴 기간 동안 유효합니다.</li>
</ul>
<h3 id="oauth-구현하기">OAuth 구현하기</h3>
<p>개발자는 서비스 제공업체 또는 타사 라이브러리에서 제공하는 라이브러리 및 프레임워크를 사용하여 OAuth를 구현할 수 있습니다. 예를 들어, JavaScript용 Facebook SDK는 Facebook 인증을 위한 OAuth를 간단하게 구현할 수 있는 방법을 제공합니다.</p>
<ul>
<li><p><strong>OAuth 라이브러리</strong>: 많은 서비스 제공업체가 널리 사용되는 프로그래밍 언어용 OAuth 라이브러리를 제공하므로 애플리케이션에서 OAuth를 쉽게 구현할 수 있습니다.</p>
</li>
<li><p><strong>타사 라이브러리</strong>: OAuth.io와 같은 타사 라이브러리는 여러 서비스 제공업체에서 OAuth를 간단하게 구현할 수 있는 방법을 제공합니다.</p>
</li>
</ul>
<hr>
<h2 id="결론">결론</h2>
<p>OAuth는 안전하고 편리한 사용자 인증 및 권한 부여 방법을 제공하여 개발자가 보다 통합적이고 포괄적인 애플리케이션을 구축할 수 있도록 지원합니다. </p>
<p>개발자는 OAuth 흐름, 범위 및 토큰을 이해함으로써 애플리케이션에서 OAuth를 구현하고 더 나은 사용자 경험을 제공할 수 있습니다.</p>
<h2 id="resources">Resources</h2>
<blockquote>
<p><a href="https://tools.ietf.org/html/rfc6749">OAuth 2.0 Specification</a>
<a href="https://www.oauth.com/oauth2-servers/">OAuth 2.0 Tutorial</a>
<a href="https://developers.facebook.com/docs/javascript">Facebook SDK for JavaScript</a>
<a href="https://oauth.io/">OAuth.io</a>
<a href="https://inpa.tistory.com/entry/WEB-%F0%9F%93%9A-OAuth-20-%EA%B0%9C%EB%85%90-%F0%9F%92%AF-%EC%A0%95%EB%A6%AC">WEB-📚-OAuth-20-개념-💯-정리 [Inpa Dev 👨‍💻:티스토리]</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[Swagger Editor로 API 명세서 작성하기]]></title>
            <link>https://velog.io/@dukov-dev/api-specification-with-swagger</link>
            <guid>https://velog.io/@dukov-dev/api-specification-with-swagger</guid>
            <pubDate>Thu, 11 Apr 2024 17:58:23 GMT</pubDate>
            <description><![CDATA[<p>웹 개발에 있어서 명확한 API 명세서 작성은 필수적입니다. API 명세서를 잘 작성해두면 이후 프로젝트에서 효율적인 협업이 가능하며, 시간을 절약할 수 있고, 더 좋은 서비스를 만들 수 있습니다.</p>
<p>이번 포스트에서는 API 명세서를 작성하는 도구 중 하나인 Swagger를 소개합니다. Swagger는 OpenAPI specification을 기반으로 RESTful API를 디자인하고, 문서화하기 위한 도구입니다.</p>
<blockquote>
<p><strong>What is OpenAPI?</strong>
The OpenAPI Specification provides a formal standard for describing HTTP APIs.
This allows people to understand how an API works, generate client code, create tests, apply design standards, and much, much more.<br>
OpenAPI specification은 HTTP API를 설명하기 위한 공식 표준을 제공합니다.
이를 통해 사람들은 API의 작동 방식을 이해하고, 클라이언트 코드를 생성하고, 테스트를 만들고, 디자인 표준을 적용하는 등 다양한 작업을 수행할 수 있습니다.
<a href="https://www.openapis.org/">- OpenAPI 소개</a></p>
</blockquote>
<p>이제부터 Swagger가 무엇인지, 어떻게 사용하는지 알아보도록 하겠습니다.</p>
<hr>
<h2 id="swagger란">Swagger란?</h2>
<p>Swagger는 RESTful 웹 서비스를 설계, 구축, 문서화할 수 있도록 설계된 오픈소스 프레임워크입니다. Swagger는 RESTful API에 대해 언어 독립적이고, 표준화된 인터페이스를 제공하므로 Swagger로 작성된 API 명세서는 API의 기능을 쉽게 이해하는데 도움을 줄 수 있습니다.</p>
<p>Swagger는 API 명세서 작성을 위해 다음과 같은 여러가지 도구를 제공합니다:</p>
<ul>
<li><p><strong>Swagger UI</strong>: API 명세서를 정적 컨텐츠로 브라우저에서 열람할 수 있도록 하는 툴입니다. API 테스트도 가능합니다.</p>
</li>
<li><p><strong>Swagger Editor</strong>: 웹 기반 API 명세서 작성 에디터입니다. JSON, YAML 포맷으로 간편하게 API 명세서를 작성할 수 있습니다.</p>
</li>
<li><p><strong>Swagger Codegen</strong>: 서버 스텁, 클라이언트 라이브러리 및 API 문서를 자동으로 생성하는 도구입니다.</p>
</li>
<li><p><strong>Swagger Inspector</strong>: 개발자가 API를 테스트하여 기능을 검증하고, 기존 API에 대한 명세서 작성을 돕는 툴입니다.</p>
</li>
</ul>
<p>이번 포스트에서는 가장 간단하게 API 명세서를 작성할 수 있는 Swagger Editor를 이용해 API 명세서를 작성하겠습니다.</p>
<hr>
<h2 id="swagger-editor를-사용해-api-명세서-작성하기">Swagger Editor를 사용해 API 명세서 작성하기</h2>
<h3 id="swagger-editor-접속하기">Swagger Editor 접속하기</h3>
<p><a href="https://editor.swagger.io/">Swagger Editor</a>에 접속하면 다음과 같은 화면을 볼 수 있습니다.
<img src="https://velog.velcdn.com/images/dukov-dev/post/0fd878e2-39c6-46ab-9e38-c4b0e1fba053/image.png" alt=""></p>
<p>화면의 왼쪽에서 JSON 또는 YAML을 사용해서 코드를 작성하면 오른쪽에서 결과를 실시간으로 확인할 수 있습니다.</p>
<p>이제 Swagger Editor에서 기본으로 제공되는 샘플 코드를 뜯어보며 API 명세서 작성법을 알아보겠습니다.</p>
<h3 id="기본-정보-정의하기">기본 정보 정의하기</h3>
<pre><code class="language-YAML">openapi: 3.0.3
info:
  title: Swagger Petstore - OpenAPI 3.0
  description: |-
    This is a sample Pet Store Server based on the OpenAPI 3.0 specification.  
    You can find out more about Swagger ...
  termsOfService: http://swagger.io/terms/
  contact:
    email: apiteam@swagger.io
  license:
    name: Apache 2.0
    url: http://www.apache.org/licenses/LICENSE-2.0.html
  version: 1.0.11
externalDocs:
  description: Find out more about Swagger
  url: http://swagger.io
servers:
  - url: https://petstore3.swagger.io/api/v3
tags:
  - name: pet
    description: Everything about your Pets
    externalDocs:
      description: Find out more
      url: http://swagger.io
  - name: store
    description: Access to Petstore orders
    externalDocs:
      description: Find out more about our store
      url: http://swagger.io
  - name: user
    description: Operations about user</code></pre>
<ul>
<li><code>openapi</code>: OpenAPI specification 버전을 명시합니다.</li>
<li><code>info</code>: <code>title</code>, <code>description</code> 등 해당 API 명세서의 각종 정보들을 명시하는 부분입니다.</li>
<li><code>servers</code>: API에 접근 가능한 URL을 나열합니다.</li>
<li><code>tags</code>: 여러 개의 태그 개체가 포함된 목록입니다. 각 태그 객체에는 일반적으로 <code>name</code>, <code>description</code> 등이 포함됩니다.</li>
</ul>
<h3 id="api-엔드포인트-http-메서드-정의하기">API 엔드포인트, HTTP 메서드 정의하기</h3>
<pre><code class="language-YAML">paths:
  /pet:
    put:
      tags:
        - pet
      summary: Update an existing pet
      description: Update an existing pet by Id
      operationId: updatePet
      requestBody:
        description: Update an existent pet in the store
        content:
          application/json:
            schema:
              $ref: &#39;#/components/schemas/Pet&#39;
          application/xml:
            schema:
              $ref: &#39;#/components/schemas/Pet&#39;
          application/x-www-form-urlencoded:
            schema:
              $ref: &#39;#/components/schemas/Pet&#39;
        required: true
      responses:
        &#39;200&#39;:
          description: Successful operation
          content:
            application/json:
              schema:
                $ref: &#39;#/components/schemas/Pet&#39;          
            application/xml:
              schema:
                $ref: &#39;#/components/schemas/Pet&#39;
        &#39;400&#39;:
          description: Invalid ID supplied
        &#39;404&#39;:
          description: Pet not found
        &#39;422&#39;:
          description: Validation exception
      security:
        - petstore_auth:
            - write:pets
            - read:pets</code></pre>
<ul>
<li><code>paths</code>: API 엔드포인트, HTTP 메소드를 명시합니다. 위의 코드 스니펫에서는 엔드포인트로 /pet, HTTP 메서드로 PUT을 사용했습니다.</li>
<li><code>requestBody</code>: requestBody를 정의합니다. <code>description</code>, <code>content</code> 등이 정의되며, <code>schema</code>를 따로 정의하여 참조하는 방식으로 사용할 수 있습니다.</li>
<li><code>responses</code>: HTTP 응답 코드와 설명을 명시합니다.</li>
</ul>
<h3 id="컴포넌트-및-스키마-추가하기">컴포넌트 및 스키마 추가하기</h3>
<p>재사용 가능한 컴포넌트, 스키마를 추가하여 API 명세서를 작성할때 유용하게 사용할 수 있습니다.</p>
<pre><code class="language-YAML">components:
  schemas:
    Pet:
      required:
        - name
        - photoUrls
      type: object
      properties:
        id:
          type: integer
          format: int64
          example: 10
        name:
          type: string
          example: doggie
        category:
          $ref: &#39;#/components/schemas/Category&#39;
        photoUrls:
          type: array
          xml:
            wrapped: true
          items:
            type: string
            xml:
              name: photoUrl
        tags:
          type: array
          xml:
            wrapped: true
          items:
            $ref: &#39;#/components/schemas/Tag&#39;
        status:
          type: string
          description: pet status in the store
          enum:
            - available
            - pending
            - sold
      xml:
        name: pet</code></pre>
<p>위의 코드 스니펫은 Pet 객체를 스키마의 형태로 정의합니다.</p>
<p>샘플 API 명세서에서는 여기에 정의된 스키마를 참조해서 <code>requestBody</code>, <code>responses</code> 부분의 예시를 제공합니다.</p>
<ul>
<li><code>properties</code>: 해당 객체가 어떤 속성을 갖는지 명시합니다. 여기에서는 <code>id</code>, <code>name</code>, <code>category</code>, <code>photoUrls</code> 등이 포함됩니다.</li>
</ul>
<p>지금까지 살펴본 샘플 YAML 코드로 생성되는 API 명세서는 다음과 같습니다.
<img src="https://velog.velcdn.com/images/dukov-dev/post/85150468-cd7b-4c69-bd6d-6e47ee4004ce/image.png" alt=""></p>
<hr>
<h2 id="결론">결론</h2>
<p>지금까지 Swagger Editor를 사용한 API 명세서 작성에 대해 알아보았습니다. </p>
<p>Swagger Editor를 사용하면 간편하게 API 명세서를 작성할 수 있고, JSON이나 YAML 파일로 저장할 수 있어서 버전관리가 용이하다는 장점이 있습니다.</p>
<blockquote>
<h2 id="references">References</h2>
<p><a href="https://www.openapis.org/">OpenAPI 공식 페이지</a>
<a href="https://gruuuuu.github.io/programming/openapi/">OpenAPI 란? (feat. Swagger)</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[웹 인증(Authentication)을 위한 쿠키, 세션, 그리고 JWT 이해하기]]></title>
            <link>https://velog.io/@dukov-dev/introduction-cookie-session-jwt</link>
            <guid>https://velog.io/@dukov-dev/introduction-cookie-session-jwt</guid>
            <pubDate>Fri, 05 Apr 2024 03:55:15 GMT</pubDate>
            <description><![CDATA[<p>웹 개발에 있어서 사용자 세션과 인증 관리는 안전하고 효율적인 애플리케이션을 만드는데 있어 필수적입니다. </p>
<p>이번 포스트에서는 인증 및 세션 관리에서 중요한 역할을 하는 세 가지 기본 개념인 쿠키(Cookies), 세션(Sessions), JWT에 대해 알아보도록 하겠습니다.</p>
<hr>
<h2 id="쿠키-cookie란">쿠키 (Cookie)란?</h2>
<blockquote>
<p>HTTP 쿠키(웹 쿠키, 브라우저 쿠키)는 서버가 사용자의 웹 브라우저에 전송하는 작은 데이터 조각입니다. 
브라우저는 그 데이터 조각들을 저장해 놓았다가, 동일한 서버에 재 요청 시 저장된 데이터를 함께 전송합니다. 
쿠키는 두 요청이 동일한 브라우저에서 들어왔는지 아닌지를 판단할 때 주로 사용합니다. 
이를 이용하면 사용자의 로그인 상태를 유지할 수 있습니다. 상태가 없는(stateless) HTTP 프로토콜에서 상태 정보를 기억시켜주기 때문입니다.
<a href="https://developer.mozilla.org/ko/docs/Web/HTTP/Cookies">- MDN: HTTP 쿠키</a></p>
</blockquote>
<p><strong>쿠키 (Cookie)</strong>는 웹사이트가 상태 저장 정보(예: 온라인 상점의 장바구니에 추가된 품목)를 기억하거나 사용자의 검색 활동(특정 버튼 클릭, 로그인 또는 과거에 방문한 페이지 기록 등)을 기록하기 위해 만들어졌습니다.</p>
<p>우리는 쿠키를 이름, 주소, 비밀번호, 결제 카드 번호 등 사용자가 이전에 양식 필드에 입력한 정보를 기억하는 용도로 사용할 수 있고, 웹 인증을 구현하는 용도로 사용할 수도 있습니다.</p>
<h3 id="쿠키의-종류">쿠키의 종류</h3>
<ol>
<li><p><strong>세션 쿠키</strong>: 임시 쿠키라고도 하는 세션 쿠키는 사용자가 웹사이트를 방문하는 동안 사용자의 브라우저에 일시적으로 생성됩니다. 세션 쿠키는 사용자가 브라우저를 닫으면 삭제됩니다.</p>
</li>
<li><p><strong>영구 쿠키</strong>: 영구 쿠키 또는 저장 쿠키라고도 하는 영구 쿠키는 사용자의 브라우저에 저장되며 설정된 만료일까지 유효합니다(만료일 전에 사용자가 삭제하지 않는 한). 영구 쿠키는 웹 서핑 행동이나 특정 웹사이트에 대한 사용자 기본 설정 등 사용자에 대한 식별 정보를 수집하는 데 사용됩니다.</p>
</li>
</ol>
<h3 id="쿠키와-보안">쿠키와 보안</h3>
<p>쿠키는 사용자 행동을 추적하고 분석하는 데 사용될 수 있습니다. 따라서 쿠키를 사용할 때 개인정보 보호 및 보안에 주의해야 합니다. </p>
<p>많은 웹 브라우저에서는 사용자가 쿠키 기본 설정을 관리하여 특정 사이트의 쿠키를 제한하거나 차단할 수 있습니다. </p>
<p>또한 유럽연합의 일반 데이터 보호 규정(GDPR) 및 기타 개인정보 보호법에 따라 웹사이트는 쿠키를 배치하기 전에 사용자의 동의를 얻어야 합니다.</p>
<p>요새 해외 사이트 등에 접속할 때 쿠키 동의 요청 팝업이 뜨는 것도 GDPR을 준수하기 위함이라고 합니다.</p>
<h3 id="세션-없이-쿠키만-단독-사용하는-경우">세션 없이 쿠키만 단독 사용하는 경우</h3>
<p>일반적으로 쿠키로만 웹 인증을 구현하는 것은 보안에 매우 취약하기 때문에 권장되지 않습니다.</p>
<p>그럼에도 불구하고 쿠키만 단독으로 사용하는 경우들이 있는데, 다음과 같습니다:</p>
<ul>
<li><p><strong>사용자 설정 저장</strong>: 민감정보가 아닌 단순 사용자 설정(테마, 언어 등) 등을 쿠키에 저장하는 경우.</p>
</li>
<li><p><strong>클라이언트 사이드 트래킹</strong>: 서버의 개입 없이 사용자의 활동을 추적하고자 하는 경우 쿠키를 사용합니다.</p>
</li>
<li><p><strong>JWT 등 인증 토큰을 담는 경우</strong>: 토큰을 쿠키에 담아서 사용하는 경우 세션 없이 웹 인증을 구현할 수 있습니다.</p>
</li>
</ul>
<hr>
<h2 id="세션-session이란">세션 (Session)이란?</h2>
<p><strong>세션 (Session)</strong>은 사용자 또는 브라우저 세션과 관련된 정보의 서버 측 저장소입니다. </p>
<p>웹 서버는 세션을 사용해 여러 HTTP 요청에 걸쳐 상태를 저장할 수 있습니다. </p>
<p>쿠키와 달리, 세션 데이터는 각 HTTP 요청과 함께 전송되지 않아 데이터 전송량을 줄이고 보안을 높입니다.</p>
<p>세션 데이터는 애플리케이션의 확장성과 보안 요구 사항에 따라 메모리 내 저장소(Redis 등), 데이터베이스, 또는 파일 시스템 등 다양한 방식으로 저장됩니다.</p>
<h3 id="세션의-작동-방식">세션의 작동 방식</h3>
<p>사용자가 웹 애플리케이션에 접속하면 서버는 해당 사용자의 세션에 대한 고유 세션 식별자(세션 ID)를 생성합니다. </p>
<p>이 세션 ID는 일반적으로 쿠키 형태로 클라이언트의 브라우저로 전송되며, 이후 요청이 있을 때마다 서버로 다시 전송됩니다. </p>
<p>이를 통해 서버는 세션 ID를 기반으로 저장된 세션 데이터를 검색하여 요청 사이에 사용자의 상태나 활동을 효과적으로 기억할 수 있습니다.</p>
<h3 id="세션의-특징">세션의 특징</h3>
<ol>
<li><p><strong>상태 관리</strong>: 세션은 여러 HTTP 요청에 걸쳐 사용자 상태를 보존하는 방법을 제공하며, 이는 stateless한 HTTP 프로토콜에서 개인화된 사용자 경험을 만들고, 인증을 구현할 수 있게 합니다.</p>
</li>
<li><p><strong>보안</strong>: 세션 데이터는 서버에 저장되므로 민감한 정보가 클라이언트의 브라우저에 노출되지 않습니다. 따라서 세션은 쿠키만 단독으로 사용하는 것에 비해 보안 측면에서 더 안전합니다.</p>
</li>
<li><p><strong>유연성</strong>: 세션은 다양한 데이터 유형과 구조를 저장할 수 있으므로 사용자 인증, 장바구니, 사용자 기본 설정 등 다양한 요구사항에 따라 다양하게 활용할 수 있습니다.</p>
</li>
</ol>
<h3 id="세션의-종류">세션의 종류</h3>
<ol>
<li><p><strong>임시 세션</strong>: 이러한 세션은 일시적이며 일반적으로 사용자 브라우저 세션의 수명에 연결됩니다. 브라우저를 닫으면 삭제됩니다.</p>
</li>
<li><p><strong>영구 세션</strong>: 이러한 세션은 서버 또는 데이터베이스에 보다 영구적으로 저장되며 미리 정의된 만료 시간에 따라 여러 브라우저 세션에 걸쳐 지속될 수 있습니다.</p>
</li>
</ol>
<h3 id="세션-관리-방법">세션 관리 방법</h3>
<p>PHP, Ruby on Rails, Django(Python), Express(Node.js) 등의 웹 개발 프레임워크와 언어는 세션 관리를 기본적으로 지원하여 세션을 만들고 관리하는 프로세스를 간소화합니다.</p>
<p>Express 환경에서는 express-session 모듈을 사용하면 간편하게 세션을 만들고, 관리할 수 있습니다.</p>
<h3 id="세션과-보안">세션과 보안</h3>
<p>세션은 클라이언트 측 쿠키보다 더 안전하지만 세션 하이재킹 같은 취약점이 없는 것은 아닙니다. </p>
<p>따라서 세션 보안을 위해 세션 만료기간 설정, HTTP 전용 쿠키 사용 등 조치가 필요합니다.</p>
<hr>
<h2 id="쿠키와-세션으로-인증-구현하기">쿠키와 세션으로 인증 구현하기</h2>
<p>쿠키와 세션을 함께 사용하는 것은 사용자 인증을 관리하는 일반적이고 효과적인 방법입니다.</p>
<p>일반적으로 서버는 로그인 성공 시 사용자의 세션을 생성하고, 사용자의 브라우저에 세션ID가 담긴 쿠키를 저장한 다음, 이후 요청때마다 사용자의 쿠키를 확인하여 사용자의 세션 데이터를 검색하는 프로세스를 거칩니다. </p>
<p>이렇게 쿠키와 세션을 사용해 인증을 구현하면 사용자가 다시 로그인하지 않아도 서버는 여러 요청에 걸쳐 사용자를 인식할 수 있습니다.</p>
<h3 id="인증-구현-과정">인증 구현 과정</h3>
<h4 id="1-유저-로그인">1. 유저 로그인</h4>
<p>사용자가 로그인 자격 증명(일반적으로 사용자 이름과 비밀번호)을 제출하면 서버는 DB에 저장된 사용자 데이터와 비교하여 자격 증명을 확인합니다.</p>
<h4 id="2-세션-생성하기">2. 세션 생성하기</h4>
<p>로그인에 성공하면 서버가 새 세션을 생성합니다. 세션 데이터에는 사용자의 ID, 역할, 기본 설정 등 사용자의 세션과 관련된 모든 것이 포함될 수 있습니다.</p>
<p>세션 데이터는 메모리, 데이터베이스, 세션 스토어, 세션 관리 서비스 등을 통해 서버에 저장됩니다.</p>
<h4 id="3-쿠키-전송하기">3. 쿠키 전송하기</h4>
<p>서버는 세션 ID를 쿠키에 담아서 클라이언트의 브라우저에 전송합니다. 이 쿠키는 이후 브라우저의 모든 요청에 포함됩니다.</p>
<p>쿠키가 HTTPS를 통해서만 전송되도록 하려면 응답 헤더의 Set-Cookie 부분에 <code>Secure</code> 속성을 추가합니다.</p>
<p>클라이언트 측 스크립트가 쿠키에 액세스하지 못하도록 하여 크로스 사이트 스크립팅(XSS) 공격에 대한 보안을 강화하려면 응답 헤더의 Set-Cookie 부분에 <code>HttpOnly</code> 속성을 추가합니다.</p>
<h4 id="4-세션-유지하기">4. 세션 유지하기</h4>
<p>세션 ID 쿠키가 설정되면 이후 클라이언트 브라우저의 각 요청에 이 쿠키가 포함됩니다. </p>
<p>서버는 쿠키에서 세션 ID를 읽고 해당 세션 데이터를 조회하여 사용자의 인증 상태 및 권한을 확인합니다.</p>
<h4 id="5-만료된-세션-처리하기">5. 만료된 세션 처리하기</h4>
<p>보안상의 이유로 세션에는 만료시간이 설정되어야 합니다.</p>
<p>세션이 만료되면 서버에서 세션 데이터가 삭제되고, 해당 세션 ID가 담긴 쿠키는 더 이상 유효하지 않게됩니다. </p>
<hr>
<h2 id="jwt-json-web-tokens란">JWT (JSON Web Tokens)란?</h2>
<blockquote>
<p>JSON 웹 토큰(JWT)은 당사자 간에 정보를 JSON 객체로 안전하게 전송하기 위한 간결하고 독립적인 방법을 정의하는 개방형 표준(RFC 7519)입니다. 이 정보는 디지털 서명이 되어 있기 때문에 검증되고 신뢰할 수 있습니다. JWT는 비밀(HMAC 알고리즘 사용) 또는 RSA 또는 ECDSA를 사용하는 공개/개인 키 쌍을 사용하여 서명할 수 있습니다.
<a href="https://jwt.io/introduction">- jwt.io: JWT 소개</a></p>
</blockquote>
<p><strong>JWT (JSON Web Token)</strong>는 쿠키와 세션을 사용하는 전통적인 인증 방식과 달리, 사용자 인증 정보를 JSON 포맷으로 안전하게 전송할 수 있는 토큰 기반의 인증 방식입니다. </p>
<p>JWT는 헤더, 페이로드, 그리고 서명의 세 부분으로 구성됩니다. </p>
<p>헤더는 토큰의 타입과 사용된 해싱 알고리즘에 대한 정보를 담고 있습니다.</p>
<p>페이로드에는 실제 전송하고자 하는 데이터(예: 사용자의 정보)가 포함됩니다. </p>
<p>마지막으로, 서명은 토큰이 변조되지 않았음을 검증하기 위해 사용됩니다.</p>
<h3 id="jwt의-작동-방식">JWT의 작동 방식</h3>
<p>JWT는 헤더, 페이로드, 서명의 세 부분으로 구성됩니다. 각 부분은 점(.)으로 구분됩니다.</p>
<ol>
<li><p><strong>헤더 (Header)</strong>: 헤더는 일반적으로 두 부분으로 구성됩니다. 토큰의 유형(JWT)과 사용 중인 서명 알고리즘(예: HMAC SHA256 또는 RSA)입니다.</p>
</li>
<li><p><strong>페이로드 (Payload)</strong>: 페이로드에는 클레임(Claim)이 포함됩니다. 클레임은 사용자와 추가 메타데이터에 대한 정보입니다. 클레임에는 등록 클레임, 공개 클레임, 비공개 클레임의 세 가지 유형이 있습니다.</p>
</li>
<li><p><strong>서명 (Signature)</strong>: 서명 부분을 만들려면 인코딩된 헤더, 인코딩된 페이로드, 비밀 키, 헤더에 지정된 알고리즘을 가져와서 서명해야 합니다.</p>
</li>
</ol>
<p>예를 들어 서버는 &#39;관리자 권한으로 로그인함&#39;이라는 클레임이 있는 토큰을 생성하여 클라이언트에 제공할 수 있습니다. </p>
<p>그러면 클라이언트는 이 토큰을 서버에 전송하는 것 만으로도 자신이 관리자로 로그인했음을 증명할 수 있습니다. </p>
<p>서버는 토큰의 서명을 확인해서 유효성을 검증하고, 페이로드의 클레임을 이용해 사용자를 인증합니다.</p>
<p>JWT는 보통 응답 헤더에 포함되거나 쿠키에 담겨서 전송됩니다.</p>
<h3 id="jwt-클레임의-유형">JWT 클레임의 유형</h3>
<ul>
<li><p><strong>등록된 클레임</strong>: 필수 사항은 아니지만 권장되는 미리 정의된 클레임 세트입니다. 여기에는 iss(발행자), exp(만료 시간), sub(대상) 등이 포함됩니다.</p>
</li>
<li><p><strong>공개 클레임</strong>: JWT를 발행하는 사람이 마음대로 정의할 수 있습니다. 충돌을 방지하려면 URI 형식으로 정의하는게 좋습니다.</p>
</li>
<li><p><strong>비공개 클레임</strong>: 비공개 클레임은 사용하기로 동의한 당사자 간에 정보를 공유하기 위해 만든 사용자 지정 클레임입니다.</p>
</li>
</ul>
<h3 id="jwt의-장점">JWT의 장점</h3>
<ol>
<li><p><strong>컴팩트함</strong>: JWT는 URL, POST 매개변수 또는 HTTP 헤더 내부를 통해 전송할 수 있습니다. 또한 JWT는 크기가 작기 때문에 성능면에서 이점을 가져갈 수 있습니다.</p>
</li>
<li><p><strong>많은 정보를 포함</strong>: 페이로드에는 사용자에 대한 모든 필수 정보가 포함되어 있기 때문에 사용이 용이합니다.</p>
</li>
<li><p><strong>사용 편의성</strong>: 다양한 라이브러리와 도구가 JWT를 지원하므로 웹, 데스크톱 및 모바일 애플리케이션에서 쉽게 구현할 수 있습니다.</p>
</li>
<li><p><strong>교차 도메인 인증 용이</strong>: CORS(교차 출처 리소스 공유) 및 교차 도메인 인증을 용이하게 합니다.</p>
</li>
</ol>
<h3 id="jwt의-단점">JWT의 단점</h3>
<ol>
<li><p><strong>저장상의 문제</strong>: 일단 발급된 JWT는 만료되기 전에는 무효화할 수 없습니다. XSS 또는 CSRF 공격을 방지하기 위해 안전하게 저장해야 합니다.</p>
</li>
<li><p><strong>확장 문제</strong>: 서버에 세션 상태가 없으므로 애플리케이션에서 로그아웃을 추적해야 하는 경우 서버에서 따로 로직을 구현해야 합니다.</p>
</li>
<li><p><strong>보안 문제</strong>: JWT 페이로드의 정보는 인코딩되어 있지만 암호화되어 있지 않으므로 가로챌 경우 쉽게 해독할 수 있습니다. 민감한 정보는 JWT에 저장해서는 안 됩니다. 또한 시크릿 키가 유출되거나 탈취 당하지 않도록 해야합니다.</p>
</li>
</ol>
<hr>
<h2 id="언제-어떤-방식을-사용해야-할까">언제, 어떤 방식을 사용해야 할까?</h2>
<h3 id="쿠키-세션-방식이-적합한-경우">쿠키-세션 방식이 적합한 경우</h3>
<ul>
<li><strong>대부분의 일반적인 경우</strong>: 전통적인 방식이며 보안 측면에서 검증된 방법이기 때문에, JWT를 꼭 써야하는 상황이 아닐 때는 쿠키-세션 방식을 고려하는 것이 좋습니다.</li>
</ul>
<h3 id="jwt-방식이-적합한-경우">JWT 방식이 적합한 경우</h3>
<ul>
<li><p><strong>단일 페이지 애플리케이션(SPA) 및 모바일 애플리케이션</strong>: JWT는 클라이언트 애플리케이션이 다른 서버나 도메인에 API 요청을 해야 하는 경우 사용하기 좋습니다.</p>
</li>
<li><p><strong>확장성이 뛰어난 어플리케이션</strong>: JWT는 서버 측 세션 저장소가 필요하지 않으므로 많은 수의 사용자가 예상되는 애플리케이션에 더 확장성이 뛰어납니다.</p>
</li>
<li><p><strong>교차 도메인 인증이 필요한 경우</strong>: 애플리케이션에 여러 도메인이 포함되어 있고 이러한 도메인에서 사용자 세션을 유지 관리해야 하는 경우 JWT는 쿠키-세션 방식보다 유연하며 사용하기 편합니다. (예: MSA 등)</p>
</li>
</ul>
<h3 id="결론">결론</h3>
<p>쿠키-세션 방식과 JWT는 웹 인증을 구현할때 매우 유용한 도구로 쓸 수 있습니다. </p>
<p>모든 상황에서 무조건 좋은 방식은 없으며, 확장성, 도메인 간 인증의 필요성, 개발 중인 애플리케이션의 유형 등 애플리케이션의 요구 사항에 따라 적합한 방식을 잘 선택해서 사용해야 합니다.</p>
<hr>
<blockquote>
<h2 id="references">References</h2>
<p><a href="https://developer.mozilla.org/ko/docs/Web/HTTP/Cookies">MDN: HTTP 쿠키</a>
<a href="https://jwt.io/introduction">jwt.io: JWT 소개</a>
<a href="https://youtu.be/XXseiON9CV0?si=nZw-Gsq8CCxx-3Sb">코딩애플: JWT 대충 쓰면 님들 코딩인생 끝남</a>
<a href="https://youtu.be/GhrvZ5nUWNg?si=2s3-Qe718bJvST53">Valentin Despa: Difference between cookies, session and tokens</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[월간 회고] 24년 3월의 기록]]></title>
            <link>https://velog.io/@dukov-dev/monthly-retrospect-2024-march</link>
            <guid>https://velog.io/@dukov-dev/monthly-retrospect-2024-march</guid>
            <pubDate>Sun, 31 Mar 2024 18:37:35 GMT</pubDate>
            <description><![CDATA[<h1 id="🤷🏻♂️이번-달은-어떻게-보냈나">🤷🏻‍♂️이번 달은 어떻게 보냈나?</h1>
<h2 id="💻데브코스-강의-수강">💻데브코스 강의 수강</h2>
<p>2월부터 데브코스 <strong>타입스크립트로 함께하는 웹 풀 사이클 개발(React, Node.js) 2기</strong>에 참여중이다.</p>
<p>매일 온라인 강의를 들어야 하기 때문에 평일 낮에는 항상 강의를 듣고, 강의 내용을 내가 원하는대로 변형해서 코드를 작성해 Github에 push하는게 이번달의 주 일과였다. (잔디심기는 중대사항이니까🌿)</p>
<p>이번달은 npm, express 기초와 API 작성 등을 배웠다. 강의 시간 자체도 짧았고, 주제를 깊게 다루지도 않아서 좀 아쉬움이 남는다.</p>
<p>5월부터 프론트엔드 파트 강의가 시작되는걸로 알고 있다. 배울게 많을 것 같아서 기대된다.</p>
<h2 id="👨🏻🏫매주-복습발표">👨🏻‍🏫매주 복습발표</h2>
<p>지금은 데브코스에서 두 번째 스프린트가 진행중이다. 그리고 매 스프린트마다 새로 배정되는 팀에서 팀원들끼리 매주 날짜를 정해서 복습발표 및 주간회고 공유를 진행한다.</p>
<p>우리팀은 금요일 오전에 슬랙에 모여서 복습발표 허들을 진행한다. 각자 한 주 동안 배운것 중에 인상 깊은 주제를 가져와서 발표하고, 질문과 답변이 오고간다. 이 과정에서 정말 배우는게 많다. 강의보다 복습발표에서 얻어가는게 훨씬 많다는 생각이 들 정도다.</p>
<p>또한 발표할때마다 항상 아쉬움이 남는다. 복습발표를 준비하며 블로그에 복습내용을 정리할 때는 내가 이 주제에 대해 잘 알고있는 것만 같고, 어떤 질문이 들어와도 답변할 수 있다는 근거 없는 자신감이 든다. 하지만 막상 발표를 진행하다보면 내가 횡설수설 하고 있다는 것이 느껴지고, 이 주제에 대해서 내가 얼마나 무지한지 깨닫게 된다. 하지만 그 아쉬움을 발판삼아 매번 더 나은 발표를 할 수 있도록 노력하고 있다.</p>
<h2 id="🔥말해보카-141일-연속-출석">🔥말해보카 141일 연속 출석!</h2>
<p><img src="https://velog.velcdn.com/images/dukov-dev/post/2f9b89ba-86b1-49b4-9125-b17f446e4479/image.png" alt="">
3월에도 하루도 빠짐없이 말해보카로 영어 공부했다. 하루에 한 시간 정도 부담없이 영어 공부하기에 참 좋은 앱이라고 생각한다.</p>
<p>이제 다시 그랜드마스터 리그에 진입했고, 4월 첫째주가 끝나면 5번째 환생을 하게 될 것 같다.</p>
<p>근 1년간 영어 공부를 한 결과 GPT와 영어로 채팅하는것도 어느정도 익숙해졌고, 특히 노래의 영어가사가 이제는 잘 들린다.</p>
<h2 id="🔥듀오링고-66일-연속-출석">🔥듀오링고 66일 연속 출석!</h2>
<p><img src="https://velog.velcdn.com/images/dukov-dev/post/98f92c6c-6591-41cd-a8af-8c143dab5251/image.png" alt="">
1월 말부터 듀오링고로 일본어 공부도 하는 중이다. 처음에는 그냥 취미삼아 시작했는데, 어느샌가 하루 루틴에 떡하니 자리잡아서 매일 한 시간씩 투자하게 되었다.</p>
<p>듀오링고에서는 한국어로 일본어를 공부하는 것은 지원하지 않기 때문에, 영어로 일본어를 공부해야한다. 그래서 영어, 일본어 공부를 한꺼번에 하는 기분이 들어서 좀 이득인것 같다.😹</p>
<h2 id="🏊🏻♂️꾸준히-수영하기">🏊🏻‍♂️꾸준히 수영하기</h2>
<p><img src="https://velog.velcdn.com/images/dukov-dev/post/ee835149-874e-459c-b263-a983491d0ba5/image.png" alt="">
작년 6월부터 수영을 시작했으니 이제 1년이 다 되어가고, 수영을 못하던 나는 어느새 상급반에서 수영하고 있다.</p>
<p>작년에 SeSAC 과정을 시작하기 전까지만 해도 주5일 개근이었으나... 이제는 듬성듬성 운동하게 됐다.😿</p>
<p>3월 첫째주, 둘째주는 워치를 안차고 수영해서 운동기록이 안됐는데 한 3~4일 정도 수영하러 갔던 것 같다.</p>
<p>4월은 매주 3일 이상 수영하는걸 목표로 해야겠다.</p>
<h2 id="👨🏻🔧ango-프론트엔드-백엔드-통신-문제-해결">👨🏻‍🔧ANGO 프론트엔드-백엔드 통신 문제 해결</h2>
<p>나는 작년 10월부터 올해 2월까지 SeSAC 성동캠퍼스에서 자바스크립트 풀스택 개발 과정에 참여했다.</p>
<p>과정 마무리로 최종 팀프로젝트를 진행했고, 우리팀은 지하철 탑승칸 추천 서비스인 <strong>ANGO</strong>를 배포해서 지금도 서비스중이다.</p>
<p>기존 배포 환경은 다음과 같았다:</p>
<ul>
<li>React app: netlify</li>
<li>Express server: EC2, EC2 load balancer, Docker</li>
<li>Database: RDS</li>
</ul>
<p>처음 배포하고 프로젝트 발표할때까지만 해도 아무런 문제가 없었으나... 백엔드 서버 및 DB를 아무 생각없이 배포한게 문제의 시작이었다.</p>
<p>AWS는 올해 2월부터 할당된 모든 IPv4 주소에 대해 시간당 0.005 달러를 부과하도록 요금 정책을 바꿨다. (Free tier EC2 제외)</p>
<p>나는 https 통신을 위해 EC2 로드 밸런서를 생성해 EC2 인스턴스와 연결했다. RDS의 public access도 열어둔 상태였다. 이 경우 EC2 로드 밸런서, RDS 인스턴스에 각각 IPv4 주소가 할당되기 때문에 시간당 0.01달러가 과금된다. 한달 750시간으로 계산하면 7.5달러, 세금까지 8.25달러로 현재 환율기준 11,000원 정도 과금된다.</p>
<p>고작 한달 11,000원 갖고 호들갑이냐?😾 할 수도 있겠지만... 아무것도 안해도 매달 지불해야하는 요금이고, 배포환경만 개선하면 얼마든지 불필요한 과금을 막을 수 있겠다는 생각이 들어서 배포환경을 다음과 같이 변경하게 되었다:</p>
<ul>
<li>React app: Amplify</li>
<li>Express server: EC2, Docker</li>
<li>Database: RDS</li>
<li>CDN: Cloudfront</li>
</ul>
<p>EC2를 Cloudfront와 연결해서 서버가 https 통신을 할 수 있도록 했고, RDS는 인스턴스를 삭제하고 public access를 disable로 설정해서 IPv4 주소가 할당되지 않도록 했다. 물론 이 경우 EC2 인스턴스와 RDS 인스턴스가 VPC 내부에서 통신할수 있도록 설정해야한다.</p>
<p>이렇게 배포환경을 구성하면 더 이상 AWS에서 요금이 청구되는 일은 없다.</p>
<p>하지만 이번엔 프론트엔드-백엔드 간 통신에 문제가 생겼다. React app에서 아무리 서버로 axios 요청을 보내도 콘솔에는 에러만 출력될 뿐이었다. postman으로 서버와 통신하는건 전혀 문제가 없었기 때문에 머리털이 다 빠져버릴 지경이었다.😿</p>
<p>며칠간의 삽질 후... Cloudfront가 CDN이라는걸 드디어 알게 되었고, response를 캐싱하며, 헤더·쿠키·쿼리스트링 등 다방면에서 통신에 관여한다는 사실을 알게 되었다. 프론트엔드-백엔드 간 통신이 되지 않던 이유는 origin, 즉 EC2 서버로 요청이 갈 때 Cloudfront가 중간에서 헤더·쿠키·쿼리스트링 등을 어떻게 처리할지 설정해두지 않아서였다. Cloudfront 배포의 동작 설정에 들어가서 요청의 모든 헤더·쿠키·쿼리스트링 전송을 허용했고, 지금은 문제가 해결되었다. (아직 쿠키는 해결안된건 비밀)</p>
<p>이 문제를 해결하는 과정에서 SOP, CORS, CDN 등에 대해서 많이 배웠다. 나중에 더 깊게 공부해서 복습발표 주제로 써먹을 생각이다.😸</p>
<hr>
<h1 id="💭이번-달-회고">💭이번 달 회고</h1>
<h2 id="😸좋았던-것-liked">😸좋았던 것 (Liked)</h2>
<ul>
<li><p><strong>복습 발표</strong>
위에서 말했듯이 새로운걸 많이 배울 수 있는 좋은 시간이다.
또한 온라인으로만 진행되는 데브코스에서 팀원들과 이런저런 이야기도 하고, 정보공유도 하는 시간이기 때문에 유익하고 보람차다!</p>
</li>
<li><p><strong>포스트 새싹</strong>
포스트 새싹은 SeSAC 과정 수료생을 대상으로 멘토링을 제공해주는 프로그램이다.
내 경우는 SeSAC 과정에 워낙 만족하기도 했고, 강사님이 정말 대단한 분이기 때문에 공고 뜨자마자 바로 프로그램에 지원했다.
줌을 이용해 강사님께 멘토링을 받았는데 ANGO 코드 리뷰, 개인프로젝트 주제 선정, 서적 추천 등 많은 부분에서 도움을 받았다.
정말 감사하고 좋은 경험이었다. 박수현 강사님 감사합니다!👍🏻</p>
</li>
<li><p><strong>새싹 글로벌 취업연계 신청</strong>
이번에 SeSAC에서 과정 수료생을 대상으로 미국 취업을 도와주는 프로그램을 새로 진행중이다.
비록 J-1 비자를 발급받고 미국에서 최대 1년간 인턴십을 진행하는 프로그램이지만, 나는 원래 해외취업에 관심이 많았고 지금이 해외에 진출하기에 적기라고 판단해서 신청서를 작성했다.
인턴십 진행중에 회사 도움으로 H1B 등 비자로 전환돼서 더 오래 일할 수 있으면 좋겠다 하고 희망회로를 열심히 돌리는 중이다.</p>
</li>
<li><p><strong>블로그 작성 시작</strong>
복습발표 자료 작성용으로 velog를 시작했다.
막상 시작해보니 블로그를 왜 쓰는건지 알게 되었다. 
마크다운 문법이 익숙해졌고, 머리속의 생각을 정리해서 기록하는 용도로 정말 유용한 것 같다.
그리고 참고용으로 이런저런 블로그 포스트를 보는 재미가 쏠쏠하다. 
지금 내 브라우저의 북마크바에는 <strong>velog</strong>와 <strong>요즘IT</strong>가 당당하게 한 자리씩 차지하게 되었다.</p>
</li>
</ul>
<h2 id="🤔배웠던-것-learned">🤔배웠던 것 (Learned)</h2>
<ul>
<li><p><strong>npm, Express 기초</strong></p>
</li>
<li><p><strong><a href="https://velog.io/@dukov-dev/JavaScript-%EB%AA%A8%EB%93%88-CJS-vs-ESM">CJS vs ESM</a></strong>
왜 아직도 옛날에 쓰던 CJS를 사용하는 사람들이 있는지 궁금해서 공부하고 기록했다.</p>
</li>
<li><p><strong><a href="https://velog.io/@dukov-dev/Map-and-Object">Map vs Object</a></strong>
Key-value pair를 저장할때 Object만 사용했는데, Map은 왜 있는건지 궁금해서 공부하고 기록했다.</p>
</li>
<li><p><strong><a href="https://velog.io/@dukov-dev/javascript-string-object">JavaScript의 데이터 타입</a></strong>
JS에서 문자열(String)은 객체(Object)인지 궁금해서 공부하고 기록했다.</p>
</li>
<li><p><strong>HTTP 메서드 탐구</strong>
복습발표에서 팀원분이 HTTP 메서드 관련 강의를 듣고, 요점만 정리해서 발표해 주셨는데 정말 유익했다.</p>
</li>
<li><p><strong>JavaScript 이벤트루프</strong>
이것도 복습발표때 팀원분이 JS 이벤트루프에 관한 좋은 영상을 공유해주셔서, 이벤트루프의 구성과 작동방식에 대해 배울 수 있었다.</p>
<h2 id="🫠부족했던-것-lacked">🫠부족했던 것 (Lacked)</h2>
</li>
<li><p><strong>일찍 기상하기</strong>
목표는 항상 9시 기상이지만... 눈 떠보면 언제나 10시나 11시다.</p>
</li>
<li><p><strong>클린코드 못 읽은것</strong>
이유는 모르겠지만 항상 시간이 부족하다. 지난주에 도서관에서 클린코드 책을 빌려왔는데 아직 반도 못 읽었다.<br>이번 주 안으로 다 읽는게 목표다.</p>
</li>
<li><p><strong>React 공부</strong>
프론트엔드, 특히 React에 대해서는 내가 아는것이 없다. 그래서 틈틈이 React를 공부해야겠다고 생각했는데 결국 하나도 못했다.😿</p>
<h2 id="🤩바라는-것-longed-for">🤩바라는 것 (Longed for)</h2>
</li>
<li><p><strong>두 번째 스프린트도 무사히 마무리하기</strong></p>
</li>
<li><p><strong>개발관련 책 한권 더 읽기</strong>
무슨 책을 읽을지 아직 정하지는 않았지만 아마 Node.js 교과서가 될 듯 하다.</p>
</li>
<li><p><strong>Udemy JS 강의 수강하기</strong></p>
</li>
<li><p><strong>개인프로젝트 설계 완료 및 구현 시작</strong>
후보군에 있는 개인프로젝트 주제 중 하나를 선정해서 설계하고, 구현 시작할 생각이다.</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[JavaScript에서 문자열(String)은 객체(Object)인가?]]></title>
            <link>https://velog.io/@dukov-dev/javascript-string-object</link>
            <guid>https://velog.io/@dukov-dev/javascript-string-object</guid>
            <pubDate>Thu, 28 Mar 2024 15:34:14 GMT</pubDate>
            <description><![CDATA[<p>데브코스 Node.js 강의를 듣던 중 강사님이 JS에서는 문자열도 객체라는 말씀을 하셨습니다.</p>
<p>JS에서 문자열은 원시 데이터 타입인걸로 알고있었는데 좀 혼란스럽더라구요.</p>
<p>그래서 문자열이 객체인지 궁금해져서 이것저것 좀 찾아본 결과를 정리했습니다.</p>
<hr>
<h2 id="1-js의-데이터-타입-종류">1. JS의 데이터 타입 종류</h2>
<p>JavaScript에서 데이터 타입은 크게 <strong>원시 데이터 타입</strong>과 <strong>객체 데이터 타입</strong>의 두가지로 나뉩니다.</p>
<h3 id="원시-데이터-타입primitive-data-types">원시 데이터 타입(Primitive Data Types)</h3>
<ul>
<li><strong>String</strong>: 텍스트 데이터를 표현하기 위한 타입입니다. 예: <code>&quot;Hello, World!&quot;</code></li>
<li><strong>Number</strong>: 숫자를 표현하는 타입으로, 정수와 실수 구분 없이 하나의 숫자 타입만 존재합니다. 예: <code>42</code>, <code>3.14</code></li>
<li><strong>BigInt</strong>: 매우 큰 정수를 표현하기 위한 타입입니다. 예: <code>9007199254740991n</code></li>
<li><strong>Boolean</strong>: 논리적인 값인 <code>true</code>와 <code>false</code>를 나타냅니다.</li>
<li><strong>Undefined</strong>: 값이 할당되지 않은 변수의 초기값입니다.</li>
<li><strong>Null</strong>: &#39;값이 없음&#39;을 의도적으로 표현하기 위한 타입입니다.</li>
<li><strong>Symbol</strong>: 고유하고 변경 불가능한 데이터 타입으로, 주로 객체 속성의 키로 사용됩니다.</li>
</ul>
<h3 id="객체-데이터-타입object-data-types">객체 데이터 타입(Object Data Types)</h3>
<ul>
<li><strong>Object</strong>: 키와 값의 집합체로, 다양한 데이터 타입을 포함할 수 있습니다. 예: <code>{ name: &quot;Alice&quot;, age: 30 }</code></li>
<li><strong>Array</strong>: 배열은 특별한 유형의 객체로, 순서가 있는 데이터의 집합을 다루기 위해 설계되었습니다. 예: <code>[1, 2, 3]</code></li>
<li><strong>Function</strong>: 함수는 일급 객체로, 기본적으로 다른 객체와 같은 방식으로 취급됩니다.</li>
</ul>
<h2 id="2-우리가-원시-데이터-타입을-객체-데이터-타입처럼-사용-할-수-있는-이유">2. 우리가 원시 데이터 타입을 객체 데이터 타입처럼 사용 할 수 있는 이유</h2>
<p>그런데 우리는 JavaScript에서 원시 데이터 타입인 문자열에 대해 <code>.length</code>나 <code>.toUpperCase()</code>와 같은 프로퍼티와 메소드를 사용할 수 있습니다.</p>
<p>이는 마치 원시 데이터 타입이 객체처럼 동작하는 것처럼 보이게 합니다.</p>
<pre><code class="language-javascript">let myString = &quot;hello&quot;;
console.log(myString.toUpperCase()); // &quot;HELLO&quot;</code></pre>
<p>이렇게 원시 데이터 타입을 객체처럼 사용할 수 있는 이유는 JavaScript 엔진이 자동으로 원시 값을 해당하는 래퍼 객체로 임시 변환하기 때문입니다.</p>
<p>다른 원시 데이터 타입인 <code>Number</code>, <code>Boolean</code>, <code>BigInt</code>, <code>Symbol</code> 등도 사용자가 프로퍼티나 메소드를 사용할 때 동일한 과정을 거칩니다.</p>
<h2 id="3-래퍼-객체-wrapper-object">3. 래퍼 객체 (Wrapper Object)</h2>
<p>원시 값에 대해 객체처럼 메서드를 호출하거나 속성에 접근하려고 할 때, 자바스크립트 엔진은 자동으로 해당 원시 값을 래퍼 객체로 변환합니다. </p>
<p>예를 들어, 문자열 원시 타입에 대한 래퍼 객체는 <code>String</code> 객체입니다. </p>
<p>다른 원시 데이터 타입도 각각 <code>Number</code>, <code>Boolean</code>, <code>BigInt</code>, <code>Symbol</code> 등의 래퍼 객체를 가집니다.</p>
<p>원시 데이터 타입을 객체처럼 사용할 때 임시적으로 사용된 래퍼 객체는 재사용 되지 않으며, 사용 후 가비지 컬렉터에 의해 자동으로 메모리에서 제거됩니다.</p>
<h2 id="4-결론">4. 결론</h2>
<p>결론적으로, JavaScript에서 문자열은 기본적으로 원시 데이터 타입이며, 객체가 아닙니다. </p>
<p>그러나 JavaScript의 유연성 덕분에, 이 원시 타입은 필요한 경우 객체처럼 다루어질 수 있습니다. </p>
<p>이는 내부적으로 JavaScript 엔진에 의해 래퍼 객체를 통해 이루어지는 일시적인 변환이며, 실제로 문자열이 객체 데이터 타입으로 변하는 것은 아닙니다. </p>
<p><strong>따라서 JS에서 문자열(String)은 본질적으로 객체가 아니라 원시 데이터 타입이라는 것을 알 수 있었습니다.</strong></p>
<h2 id="5-references">5. References</h2>
<blockquote>
<p><a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Data_structures">https://developer.mozilla.org/ko/docs/Web/JavaScript/Data_structures</a>
<a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/String#string_coercion">https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/String#string_coercion</a>
<a href="https://developer-talk.tistory.com/69">https://developer-talk.tistory.com/69</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[JavaScript: Key-value pair 저장할때 Map과 Object 중 어떤 걸 사용해야 할까?]]></title>
            <link>https://velog.io/@dukov-dev/Map-and-Object</link>
            <guid>https://velog.io/@dukov-dev/Map-and-Object</guid>
            <pubDate>Fri, 22 Mar 2024 00:59:39 GMT</pubDate>
            <description><![CDATA[<p>JavaScript 개발을 하면서 데이터를 저장하고 관리해야 할 때, 많은 개발자들이 <code>Map</code>과 <code>Object</code> 사이에서 선택해야 하는 상황에 직면합니다. 이 두 타입은 유사해 보이지만, 성능, 기능, 사용 방법에서 중요한 차이점을 가지고 있습니다. 이번 포스트에서는 <code>Map</code>과 <code>Object</code>의 주요 차이점과 각각의 사용 사례를 살펴보겠습니다.</p>
<hr>
<h2 id="map">Map</h2>
<p><code>Map</code> 객체는 키-값 쌍을 저장하기 위한 컬렉션입니다. <code>Map</code>은 다음과 같은 특징을 가집니다:</p>
<ul>
<li><strong>빈번한 삽입/삭제에서 뛰어난 성능</strong>: <code>Map</code>은 내부적으로 최적화된 데이터 구조를 사용하여 빈번한 삽입 및 삭제 작업에서 뛰어난 성능을 제공합니다.</li>
<li><strong>순서 유지</strong>: <code>Map</code>은 삽입된 순서대로 키-값 쌍을 저장합니다.</li>
<li><strong>다양한 키 타입</strong>: 문자열, 객체, 함수, 배열 등 다양한 타입의 값을 키로 사용할 수 있습니다.</li>
<li><strong>얕은 복사와 깊은 복사 지원</strong>: 생성자를 통한 얕은 복사와 <code>structuredClone</code> 메소드를 사용한 깊은 복사가 가능합니다.</li>
<li><strong><code>Object.fromEntries</code>메소드로 Object로 변환 용이</strong>: <code>Map</code>을 간단히 객체로 변환할 수 있습니다.</li>
</ul>
<h3 id="사용-사례">사용 사례</h3>
<ul>
<li>키의 순서가 중요한 상황</li>
<li>다양한 타입의 키를 사용해야 하는 경우</li>
<li>빈번한 데이터의 삽입과 삭제가 이루어지는 경우</li>
</ul>
<h2 id="object">Object</h2>
<p><code>Object</code>는 JavaScript의 기본적인 데이터 타입 중 하나로, 키-값 쌍을 저장하는데 사용됩니다. <code>Object</code>는 다음과  같은 특징을 가집니다:</p>
<ul>
<li><strong>기본 생성 시 할당되는 키-값 쌍</strong>: 객체를 생성할 때 몇 가지 내장 프로퍼티와 메소드가 포함될 수 있으며, 이는 버그를 유발 할 수 있습니다.</li>
<li><strong>키 타입 제한</strong>: 키는 문자열 또는 심볼만 가능합니다.</li>
<li><strong>JSON 변환 용이</strong>: <code>JSON.stringify</code> 메소드를 사용해서 쉽게 JSON 문자열로 변환할 수 있습니다.</li>
</ul>
<h3 id="사용-사례-1">사용 사례</h3>
<ul>
<li>복잡한 데이터 구조보다는 단순한 데이터를 저장할 때</li>
<li>데이터를 JSON으로 변환할 필요가 있을 때</li>
<li>ES6 이전의 코드와의 호환성이 필요할 때</li>
</ul>
<h2 id="기타-고려사항">기타 고려사항</h2>
<ul>
<li>성능: 실제 성능은 사용 사례나 어플리케이션 환경에 따라 다를 수 있습니다.</li>
<li>메모리 사용: 대규모 데이터를 다룰 때, <code>Map</code>과 <code>Object</code>는 메모리 사용량이 다를 수 있습니다. 일반적으로 Map이 더 효율적인 데이터 구조를 제공합니다.</li>
<li>호환성: <code>Map</code>은 ES6에서 도입되었으므로, 구형 브라우저나 환경에서는 폴리필(Polyfill)을 사용해야 할 수도 있습니다.</li>
</ul>
<hr>
<h2 id="결론">결론</h2>
<p><code>Map</code>과 <code>Object</code>는 JavaScript에서 데이터를 저장하고 관리하는 데 사용될 수 있지만, 각각의 특성과 성능 차이를 이해하는 것이 중요합니다. <code>Map</code>은 더 복잡한 데이터 구조를 효율적으로 다루는 데 적합한 반면, <code>Object</code>는 더 단순하고 전통적인 데이터 저장 방식을 제공합니다.</p>
<p><code>Map</code>과 <code>Object</code>의 특성을 잘 알고 있으면 Key-value pair를 저장할때 어떤 것을 사용할지 선택하는데 큰 도움이 될것입니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[JavaScript 모듈 - CJS vs ESM]]></title>
            <link>https://velog.io/@dukov-dev/JavaScript-CJS-vs-ESM</link>
            <guid>https://velog.io/@dukov-dev/JavaScript-CJS-vs-ESM</guid>
            <pubDate>Sat, 16 Mar 2024 15:42:10 GMT</pubDate>
            <description><![CDATA[<p>많은 JS 강의에서 CJS 방식을 사용하는 걸 보고 왜 아직도 이걸 사용하는 걸까? 하는 궁금증이 생겨서 이것저것 찾아보고, 관련 내용을 정리했습니다.</p>
<h2 id="cjs-commonjs">CJS (CommonJS)</h2>
<ul>
<li><strong>사용법:</strong> <code>exports</code> ~ <code>require</code></li>
<li><strong>로딩 방식:</strong> <code>require</code> 호출은 <strong>동기적(synchronous)</strong>; 모듈 로딩이 끝날 때까지 코드는 <strong>블록(block)</strong> 됨</li>
<li><strong>특징:</strong><ul>
<li><code>__filename</code>, <code>__dirname</code> 이 미리 정의되어 있어서 바로 사용할 수 있음</li>
<li>파일을 로딩해서 바로 사용 가능</li>
</ul>
</li>
<li><strong>만들어진 이유:</strong> Node.js에서 Server-Side JavaScript를 사용하기 위해 만들어짐</li>
</ul>
<hr>
<h2 id="esm-ecmascript-modules">ESM (ECMAScript Modules)</h2>
<ul>
<li><strong>사용법:</strong> <code>export</code> ~ <code>import</code></li>
<li><strong>로딩 방식:</strong> <strong>비동기적(asynchronous) 로딩</strong>; CJS보다 상대적으로 performance 측면에서 이득이 있을 수 있음</li>
<li><strong>특징:</strong><ul>
<li><code>__filename</code>, <code>__dirname</code> 미리 정의되어 있지 않음 -&gt; <code>url</code>, <code>path</code> 모듈 사용해 정의 필요</li>
<li>모듈이 아닌 일반 파일을 코드 내에서 로딩하고자 하는 경우 <code>module</code> 모듈을 사용해야 함 </li>
</ul>
</li>
<li><strong>만들어진 이유:</strong> Client-side, Server-side에서 통일된 모듈 시스템을 사용하기 위해 디자인 되었으며 ES6 부터 도입됨</li>
</ul>
<hr>
<h2 id="cjs를-여전히-사용하는-이유">CJS를 여전히 사용하는 이유</h2>
<ol>
<li><strong>레거시 CJS 코드를 ESM으로 바꾸는 비용</strong> 부담이 존재</li>
<li>여전히 <strong>CJS 방식만을 지원하는 툴과 라이브러리</strong>가 존재</li>
</ol>
<hr>
<h2 id="현황-및-추세">현황 및 추세</h2>
<ul>
<li>웹팩(Webpack), bundler, 라이브러리 등이 ESM으로 작성되는 추세</li>
<li>ESM에서는 CJS 모듈을 <code>import</code> 가능하지만, 역은 불가능함 </li>
<li>JS 생태계의 발전을 위해 <strong>ESM 사용을 지지하는 여론</strong>이 많음</li>
</ul>
]]></description>
        </item>
    </channel>
</rss>