<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>grow up</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Mon, 09 Sep 2024 08:27:31 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>grow up</title>
            <url>https://velog.velcdn.com/images/xiu_8/profile/50807fb1-270c-4799-af29-867ea3e5599d/image.avif</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. grow up. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/xiu_8" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[AWS S3 CloudFront 배포후 AccessDenied 문제 해결하기]]></title>
            <link>https://velog.io/@xiu_8/s3-cloudfront-%EB%B0%B0%ED%8F%AC%ED%9B%84-AccessDenied-%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@xiu_8/s3-cloudfront-%EB%B0%B0%ED%8F%AC%ED%9B%84-AccessDenied-%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0%ED%95%98%EA%B8%B0</guid>
            <pubDate>Mon, 09 Sep 2024 08:27:31 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/xiu_8/post/8a012692-6f35-4087-bdc2-337da765212c/image.png" alt=""></p>
<p>s3와 cloud front 배포 후 403 forbidden AccessDenied 에러가 뜬다면 ? s3에서 접속을 했을 경우 퍼블릭 엑세스 권한을 허용해두지않으면  403 forbidden AccessDenied 에러가 뜨는 것은 정상이다. cloudfront로 제어가 목적이라면 그대로 두면된다. 문제는 cloudfront로 배포한 url에 접속시 뜨는  AccessDenied 에러인데, s3 정책 설정까지 모두 제대로 완료했을 경우에는 리전만 추가 등록해준다면 가볍게 해결할 수 있다.</p>
<p>cloudfront 접속 후 원본 &gt; 원본체크 &gt; 편집 순으로 접속한다.</p>
<p><img src="https://velog.velcdn.com/images/xiu_8/post/3b64706b-b903-481f-9685-b60e4a38dbed/image.png" alt=""></p>
<p>맨 하단에 Enable Origin Shield에 리전을 본인이 지정하고자하는 지역에 선택해 변경 사항을 저장한다.</p>
<p><img src="https://velog.velcdn.com/images/xiu_8/post/92851369-2c2b-4797-9e61-f3209db34778/image.png" alt=""></p>
<p>다른 설정이 빠진게 없다면 cloudfront 배포 주소로 정상 접속되는 것을 확인할 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/xiu_8/post/906e2e44-0fec-426d-86f9-29459ed07b2c/image.png" alt=""></p>
<ol>
<li><a href="https://velog.io/@xiu_8/%EA%B8%B0%EC%96%B5%ED%95%B4-%EA%B8%B0%EB%A1%9D%ED%95%B4-%ED%94%84%EB%A1%A0%ED%8A%B8-%EB%B0%B0%ED%8F%AC-AWS-S3-CloudFront%ED%9B%84-githubCICD%EA%B9%8C%EC%A7%80">AWS S3 CloudFront 배포하는 법</a></li>
<li><a href="https://velog.io/@xiu_8/github-action%EC%9C%BC%EB%A1%9C-cicd-feat.-aws-s3-cloudfront">Github Action CI/CD 적용하기</a></li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[Github Action으로 CI/CD (feat. AWS S3 CloudFront)]]></title>
            <link>https://velog.io/@xiu_8/github-action%EC%9C%BC%EB%A1%9C-cicd-feat.-aws-s3-cloudfront</link>
            <guid>https://velog.io/@xiu_8/github-action%EC%9C%BC%EB%A1%9C-cicd-feat.-aws-s3-cloudfront</guid>
            <pubDate>Mon, 09 Sep 2024 08:26:36 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>2024.09.09 기준 작성된 포스팅입니다.</p>
</blockquote>
<p>먼저 s3 cloudfront 배포방법이 알고싶다면 하단 포스팅을 참고할 수 있다.</p>
<ul>
<li><a href="https://velog.io/@xiu_8/%EA%B8%B0%EC%96%B5%ED%95%B4-%EA%B8%B0%EB%A1%9D%ED%95%B4-%ED%94%84%EB%A1%A0%ED%8A%B8-%EB%B0%B0%ED%8F%AC-AWS-S3-CloudFront%ED%9B%84-githubCICD%EA%B9%8C%EC%A7%80">s3 cloudfront 배포방법 알기</a></li>
<li><a href="https://devchaeyoung.tistory.com/entry/GitHub-Actions-Workflow-%EB%AA%85%EB%A0%B9%EC%96%B4-%EC%A0%95%EB%A6%AC">workflows 스크립트 명령어 정리</a></li>
</ul>
<p>개념과 함께 아는 것이아니라 순서대로 cicd를 적용하고 싶은 사람은 목차 중에 <code>순서대로 github cicd 준비하기</code>를 바로 참고하길 바란다.</p>
<h1 id="github-cicd">github-cicd</h1>
<p>먼저 아래는 작성한 전체 workflow.yml 파일이다.</p>
<pre><code class="language-yml">name: DEV CI

on:
  push:
    branches: [&quot;dev&quot;]
  pull_request:
    branches: [&quot;dev&quot;]

jobs:
  build:
    runs-on: ubuntu-latest

    strategy:
      matrix:
        node-version: [20.x]

    steps:
      - uses: actions/checkout@v4

      - name: Create dotenv file
        run: |
          touch .env
          echo &quot;VITE_BASE_URL=${{secrets.VITE_BASE_URL}}&quot; &gt;&gt; .env 
 # ... env 파일에 생성할 객체 echo 명령어로 추가하기        
          cat .env

      - name: Use Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
          cache: yarn # yarn으로 설정

      - name: Yarn install
        run: yarn

      - name: Yarn build
        run: yarn build

      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ${{ secrets.AWS_DEFAULT_REGION }}

      - name: Deploy to S3
        uses: jakejarvis/s3-sync-action@master
        with:
          args: --delete
        env:
          AWS_S3_BUCKET: ${{ secrets.DEV_AWS_S3_BUCKET_NAME }}
          SOURCE_DIR: &quot;dist&quot;

      - name: Invalidate CloudFront Cache
        run: aws cloudfront create-invalidation --distribution-id ${{ secrets.DEV_AWS_DISTRIBUTION_ID }} --paths &quot;/*&quot;
</code></pre>
<h2 id="workflows를-통해-할-수-있는-동작">workflows를 통해 할 수 있는 동작</h2>
<p>workflows 작성이 어색한 사람들은 해당 섹션을 가볍게 읽어보면 이해하는데 조금 도움이 될 것이다.</p>
<h4 id="1-특정-브랜치에-push가-일어났을-때-동작-지시하기--트리거-조건-설정">1. 특정 브랜치에 push가 일어났을 때 동작 지시하기( = 트리거 조건 설정)</h4>
<p>깃 브랜치별로 push가 일어났을 때 다른 동작을 수행하게 하려면 <code>on:</code> 명령어를 통해 동작이 일어날 브랜치를 지정할 수 있다. 해당 스크립트로 main 브랜치와 dev브랜치를 구분하여 배포나 테스트 작업에 구분을 둘 수 있다.
추가적인 스크립트로 매번 수동으로 하던 빌드 -&gt; 업로드 -&gt; 배포 -&gt; 캐싱 무효화 등등과 같은 작업들을 한번에 끝낼 수 있다.</p>
<h4 id="2-미리-작성해둔-aws-권한으로-번거로운-수동-aws-작업-줄이기">2. 미리 작성해둔 aws 권한으로 번거로운 수동 aws 작업 줄이기</h4>
<p>aws access key와 secret access key와 같이 노출되면 안되는 정보들은 미리 github secrets에 등록해둠으로써 보안을 강화할 수 있다. 이때 저장해둔 값들은 workflow에 미리 등록해둔 key를 이용해 불러와 사용할 수 있다. 이때 주로 저장되어 사용하는 값이 aws 권한 인증에 필요한 aws access key와 secret access key이다. 해당 작업은 상단에 작성된 전체 스크립트에 <code>Configure AWS Credentials</code> 부분에 해당한다.</p>
<h4 id="3-github-action으로-s3에-빌드파일-자동-업데이트하기">3. github action으로 s3에 빌드파일 자동 업데이트하기</h4>
<p><code>name</code> 스크립트로 구간별 동작을 지정할 수 있다. 이 때, 파일 빌드 작업일 경우 <code>jobs</code> 스크립트 안에 실행될 환경을 설정할 수 있다. 위 스크립트는 우분투 최신버전으로 동작하도록 작성되었다. 후에 순차적으로 strategy.matrix로 node버전을 설정,<code>uses-with</code> 스크립트로 배포파일 지정 등 동작을 지정해둘 수 있다. 마지막으로 <code>env</code>환경 변수에 aws bucket 이름을 지정해줌으로써 파일 업로드가 완료된다. 스크립트에 dist는 해당 스크립트의 프로젝트가 vite-react기준이라 build파일이 dist폴더내에 저장되었기 때문에, dist로 작성되었다.</p>
<h4 id="4-s3업로드-완료-후-cloudfront-캐싱-무효화하기">4. s3업로드 완료 후 cloudfront 캐싱 무효화하기</h4>
<p>cloudfront의 장점은 캐싱이 된다는 장점이 있지만, 새로 업데이트를 할 경우 수동으로 캐싱을 무효화해줘야한다. 이ㄸㅐ 할 작업을 workflow에 함께 작성할 수 있다. 아래 명령어를 참고하면 된다. AWS_DISTRIBUTION_ID에는 cloudfront id값을 git secret에 AWS_DISTRIBUTION_ID 변수명으로 작성해주면된다. </p>
<pre><code class="language-yml">      - name: Invalidate CloudFront Cache
        run: aws cloudfront create-invalidation --distribution-id ${{ secrets.AWS_DISTRIBUTION_ID }} --paths &quot;/*&quot;</code></pre>
<p><img src="https://velog.velcdn.com/images/xiu_8/post/c01ca2dc-d80c-475d-8821-57554a4abe19/image.png" alt=""></p>
<h1 id="순서대로-github-cicd-준비하기">순서대로 github cicd 준비하기</h1>
<p>이제 본론으로 들어가 순서대로 cicd를 적용해보자ㅏ.</p>
<p>순서를 간략하게 요약하면 아래와 같다.</p>
<ul>
<li>aws 권한 부여를 위한 aws access key 발급<ul>
<li>권한 부여 방법은 따로 IAM 계정을 생성해서 해도 되지만 이번 포스팅에는 access key를 직접적으로 활용하였다</li>
</ul>
</li>
<li>git secret 등록</li>
<li>workflows .yml 파일 작성</li>
</ul>
<h2 id="1-aws-access-key-발급">1. aws access key 발급</h2>
<p>aws에서 우측 상단에 아이디 탭을 누르고 <code>보안 자격 증명</code> 메뉴를 클릭한다.</p>
<p><img src="https://velog.velcdn.com/images/xiu_8/post/b9249466-941e-4f91-a30e-3685704009f1/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/xiu_8/post/41313a6e-0d2a-4bd4-afc8-03cc3c0ff0c8/image.png" alt=""></p>
<p>용도에 맞게 사용 사례를 선택한다.</p>
<p><img src="https://velog.velcdn.com/images/xiu_8/post/772e790f-caa1-4208-af81-23d8e6fb418f/image.png" alt=""></p>
<p>생성된 엑세스 키는 보안을 위해 따로 저장하지 않는 편이 좋으며, 생성시에 바로 깃허브 레포 secret에 등록하는 편이 좋다.</p>
<p><img src="https://velog.velcdn.com/images/xiu_8/post/0bd00453-76e8-499c-bab7-d570a5fa4d73/image.png" alt=""></p>
<h2 id="2-git-secret-추가">2. Git secret 추가</h2>
<p>발급받는 엑세스키워 시크릿 엑세스 키를 두고 아래 경로로 접속하여 새로 변수를 등록한다.</p>
<p><strong>접속 순서</strong> : cicd 적용할 레포 &gt; 설정 &gt; secrets and variables &gt; action &gt; new repository secret</p>
<p><img src="https://velog.velcdn.com/images/xiu_8/post/213f4ac2-52f5-4978-b5b1-f877f2fdea64/image.png" alt=""></p>
<p>아래와 같이 원하는 변수명으로 변경/등록 할 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/xiu_8/post/48ecece6-383a-4e9b-930d-492f51583b0a/image.png" alt=""></p>
<p>작성된 내용을 github내에서도 두번은 볼 수 없으니 혹시나 잊을까 걱정된다면 다로 메모해둬도 좋지만, 보안을 걱정한다면 주기적으로 엑세스키를 업데이트 하는 것도 방법이다!</p>
<p>cicd 등록시 저장할 변수 목록 ( s3 cloudfront로 배포했을 경우 )</p>
<ul>
<li>AWS_ACCESS_KEY_ID</li>
<li>AWS_SECRET_ACCESS_KEY</li>
<li>AWS_DEFAULT_REGION</li>
<li>AWS_DISTRIBUTION_ID</li>
<li>AWS_S3_BUCKET_NAME</li>
</ul>
<h2 id="3-workflows-yml-파일-작성">3. workflows .yml 파일 작성</h2>
<pre><code class="language-yml">name: MAIN CI

on:
  push:
    branches: [&quot;main&quot;]
  pull_request:
    branches: [&quot;main&quot;]

jobs:
  build:
    runs-on: ubuntu-latest

    strategy:
      matrix:
        node-version: [20.x]

    steps:
      - uses: actions/checkout@v4

      - name: Create dotenv file
        run: |
          touch .env
          echo &quot;VITE_BASE_URL=${{secrets.VITE_BASE_URL}}&quot; &gt;&gt; .env 
 # ... env 파일에 생성할 객체 echo 명령어로 추가하기        
          cat .env

      - name: Use Node.js ${{ matrix.node-version }}
        uses: actions/setup-node@v4
        with:
          node-version: ${{ matrix.node-version }}
          cache: yarn # yarn으로 설정

      - name: Yarn install
        run: yarn

      - name: Yarn build
        run: yarn build

      - name: Configure AWS Credentials
        uses: aws-actions/configure-aws-credentials@v4
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: ${{ secrets.AWS_DEFAULT_REGION }}

      - name: Deploy to S3
        uses: jakejarvis/s3-sync-action@master
        with:
          args: --delete
        env:
          AWS_S3_BUCKET: ${{ secrets.AWS_S3_BUCKET_NAME }}
          SOURCE_DIR: &quot;dist&quot;

      - name: Invalidate CloudFront Cache
        run: aws cloudfront create-invalidation --distribution-id ${{ secrets.AWS_DISTRIBUTION_ID }} --paths &quot;/*&quot;
</code></pre>
<p>위 코드가 동작하는 방식을 간략하게 작서하면 다음과 같다.</p>
<ul>
<li>main 브랜치에 push나 pull request가 일어날 시 아래 스크립트를 실행한다.</li>
<li>yarn을 이용해 필요한 package.json 파일을 다운받고, build를 진행한다. </li>
<li>aws 인증</li>
<li>s3에 기존에 저장된 파일들을 삭제 후 build된 파일이 있는 dist폴더를 지정된 s3버킷에 저장한다.</li>
<li>마지막으로 cloudfront에 있는 캐싱 무효화 작업을 실행한다.</li>
</ul>
<h2 id="4-마무리-잘-동작하는지-확인하기">4. 마무리 잘 동작하는지 확인하기</h2>
<p><img src="https://velog.velcdn.com/images/xiu_8/post/896ae689-e4c2-4a3b-a3d2-62d361617b83/image.png" alt=""></p>
<p>action 카테고리에 들어가면 잘 동작하는지 확인할 수 있다. 프로젝트 크기에따라 오래걸릴 수도 있으니 잠깐 다른 작업을 하고 있으면 된다.</p>
<p><img src="https://velog.velcdn.com/images/xiu_8/post/01572845-bb5e-4cf2-950f-df007c6d3e25/image.png" alt=""></p>
<p>디테일을 보려면 Show all jobs 버튼을 프로그램이 동작하는 것을 확인할 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/xiu_8/post/90d48737-2144-43c0-8117-7371194bcc4a/image.png" alt=""></p>
<p>모두 완료된 후 배포 url로 접속하여 업로드가 잘 되었는지 또는 workflows 마지막 단계인 캐싱 무효화가 잘되었는지 등을 통해 잘 동작이 되었는지 확인할 수 있다.</p>
<h3 id="참고">참고</h3>
<ul>
<li><a href="https://www.daleseo.com/github-actions-checkout/">GitHub Actions의 체크아웃(Checkout) 액션으로 코드 내려받기</a></li>
<li><a href="https://velog.io/@bluestragglr/Github-Action%EC%9C%BC%EB%A1%9C-%EB%B0%B0%ED%8F%AC-%EC%9E%90%EB%8F%99%ED%99%94%ED%95%98%EA%B8%B0#1-aws-iam-%EB%B0%9C%EA%B8%89">Github Action으로 배포 자동화하기</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[기억해 기록해 프론트 배포( AWS S3 CloudFront)]]></title>
            <link>https://velog.io/@xiu_8/%EA%B8%B0%EC%96%B5%ED%95%B4-%EA%B8%B0%EB%A1%9D%ED%95%B4-%ED%94%84%EB%A1%A0%ED%8A%B8-%EB%B0%B0%ED%8F%AC-AWS-S3-CloudFront%ED%9B%84-githubCICD%EA%B9%8C%EC%A7%80</link>
            <guid>https://velog.io/@xiu_8/%EA%B8%B0%EC%96%B5%ED%95%B4-%EA%B8%B0%EB%A1%9D%ED%95%B4-%ED%94%84%EB%A1%A0%ED%8A%B8-%EB%B0%B0%ED%8F%AC-AWS-S3-CloudFront%ED%9B%84-githubCICD%EA%B9%8C%EC%A7%80</guid>
            <pubDate>Tue, 27 Aug 2024 08:28:24 GMT</pubDate>
            <description><![CDATA[<p>이번에 aws 계정을 변경하면서 프론트서버를 재배포하게 되었다.
해야할 것들부터 정리해보자.</p>
<ul>
<li>지속적인 운영을 위한 프로덕트 서버 배포</li>
<li>서비스 운영에 관계없이 개발에 집중을 하기위한 개발 서버 배포</li>
<li>Rout53으로 가비아 연결하기</li>
</ul>
<p>빌드 파일 저장은 s3 스토리지를 이용한다. <code>왜 ?</code> 이전 기록 삭제하고 다시 빌드 올리기가 쉽기 때문이다.</p>
<h2 id="1-s3-버킷-생성">1. S3 버킷 생성</h2>
<p><img src="https://velog.velcdn.com/images/xiu_8/post/d19d2249-6cbe-468d-9587-ca6474829678/image.png" alt=""></p>
<p><code>버킷 만들기</code> 클릭</p>
<p>아래 화면에서 s3 버킷 쓰임에 따라 내용을 작성한 후 버킷을 생성한다.</p>
<ul>
<li><strong>버킷 이름</strong> : 해당 버킷이 어떤 역할을하는지 알아볼 수 있는 이름 작성한다.</li>
<li><strong>기존 버킷에서 설정 복사</strong> : 이전에 설정한 버킷과 같은 설정을 하고 싶다면 <code>버킷 선택</code>을 눌러 가져오고 싶은 설정의 버킷을 선택하여 세팅할 수 있다.</li>
<li><strong>객체 소유권</strong> : 다른 aws 계정에서 해당 버킷을 이용하게 할 경우 ACL 활성화를 하면 되지만 해당 버킷을 생성하고 있는 계정에서만 쓸 경우에는 비활성화를 선택하면 된다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/xiu_8/post/df63842d-dc02-4703-944b-b1af402c4b2c/image.png" alt=""></p>
<ul>
<li><strong>퍼블릭 엑세스 차단 설정</strong> : 바로 S3로 접속을 할 경우에는 <code>모든 퍼블릭 액세스 차단</code>을 해제한 후 아해 개별 설정을 해줘야하지만 현재는 cloudfront를 이용해 배포를 할 것이기 때문에 기본 값이 <code>모든 퍼블릭 액세스 차단</code>에 체크를해두면 된다. </li>
<li><strong>버킷 버전 관리</strong> : 해당 프로젝트는 실사용자가 있어 무분별한 기능 업데이트보다는 버전으로 관리될 예정이므로 혹시 모를 일을 대비해 버전 관리 <code>활성화</code>에 체크하였다. 딱히 버전관리가 필요없다면 <code>비활성화</code>에 체크하면 된다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/xiu_8/post/dfb599be-67cf-45f8-be63-21ab1252581f/image.png" alt=""></p>
<ul>
<li><strong>기본 암호화</strong> : 딱히 키별로 관리할 용도의 버킷이 아니기 때문에 기본값인 <code>SSE-S3</code>로 체크하였다.</li>
<li><strong>고급 설정 - 객체 잠금</strong>: 여러 명이 함께하는 프로젝트라면 객체잠금을 하겠지만, 현재 프론트가 혼자인 관계로 딱히 설정하지 않았다.</li>
</ul>
<p>여기까지하면 <code>버킷 만들기</code> 클릭.</p>
<p><img src="https://velog.velcdn.com/images/xiu_8/post/62c7509f-5917-4633-916e-884f3d712f3d/image.png" alt=""></p>
<p>개발서버는 앞에 dev, 운영서버는 product를 붙여 구분하였다.</p>
<p><img src="https://velog.velcdn.com/images/xiu_8/post/fcdbcae7-8483-4aec-8724-96e0c8f7324e/image.png" alt=""></p>
<p>s3 파일 업로드하는 방법은 간단하다. 업로드 부분에 파일을 드래그하거나 업로드 버튼을 눌러 추가하면 된다.</p>
<p><img src="https://velog.velcdn.com/images/xiu_8/post/d9fdfaca-f763-43ac-9742-8dce961dff5b/image.png" alt=""></p>
<p>s3만으로 정적 호스팅을 하려면 aws 속성 설정 &gt; 맨 하단의 정적 웹 사이트 호스팅 활성화를 켜면 된다.
cloudfront로 배포를 할 것이기 때문에 비활성화 상태로 둔다.</p>
<p><img src="https://velog.velcdn.com/images/xiu_8/post/e88c8f77-1517-49fa-9a76-4cf353f2f6fd/image.png" alt=""></p>
<p>인덱스 문서와 오류 문서 둘다 index.html로 설정한다.</p>
<h2 id="2-cloudfront-생성">2. cloudfront 생성</h2>
<p><img src="https://velog.velcdn.com/images/xiu_8/post/5ee28511-b651-4173-92a1-8066e64461a2/image.png" alt=""></p>
<p>생성된 s3버킷을 origin domain으로 두고 cloudfront를 생성한다.</p>
<p><img src="https://velog.velcdn.com/images/xiu_8/post/e27d34c0-677b-4eaf-954c-c8981a279f97/image.png" alt=""></p>
<p>나머지 설정들</p>
<p><img src="https://velog.velcdn.com/images/xiu_8/post/23264bbe-751e-4e92-a16d-d28de6335b3c/image.png" alt=""></p>
<ul>
<li>기본 캐시 동작은 본인 프로젝트에 맞춰 설정해주면 되는데 서버측과 얘기한 후 HTTP and HTTPS로 할지 Redirect HTTP to HTTPS할지 정하면 된다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/xiu_8/post/cf631f3c-2686-41c3-8af0-1ce75a36e240/image.png" alt="">
<img src="https://velog.velcdn.com/images/xiu_8/post/b003b73c-90d9-4f14-b6a7-358016e2ed68/image.png" alt=""></p>
<p>쭉 이미지를 따라 설정하다가 인증서 설정이 나오는데 </p>
<p><img src="https://velog.velcdn.com/images/xiu_8/post/cbb2bbfc-d74e-46f4-8c4f-efbf29b2e96f/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/xiu_8/post/ff0634a0-690d-49db-b567-5801c8c388ce/image.png" alt=""></p>
<p>마지막으로 <code>배포 생성</code> 누르면 cloudfront 생성 끝. 가비아나 구매한 url을 연결해주려면 생성 후 cname 등록을 해주어야한다.</p>
<p><img src="https://velog.velcdn.com/images/xiu_8/post/211dbaa7-7db3-4259-94e3-ed9e25ab2a08/image.png" alt=""></p>
<h2 id="3-s3-버킷-정책-수정하기">3. S3 버킷 정책 수정하기</h2>
<p><img src="https://velog.velcdn.com/images/xiu_8/post/225a715b-49bd-4a84-9197-be647a22ef77/image.png" alt=""></p>
<p>생성하고 난 후에 뜬 알림문의 <code>정책 복사</code> 후 s3 버킷 권한으로 이동한다.</p>
<p><img src="https://velog.velcdn.com/images/xiu_8/post/454b7d73-eae0-4c12-b374-d05f436f4e58/image.png" alt=""></p>
<p>아래 정책 부분에 복사한 정책을 붙여넣은 후 변경사항 저장을 눌러주자.</p>
<p><img src="https://velog.velcdn.com/images/xiu_8/post/70aa5e8d-c2ad-494d-8c9c-99186b824b8c/image.png" alt=""></p>
<p>다시 클라우드 프론트로 돌아와 배포 url을 확인하면 배포가 잘 되었는지 확인할 수 있다.</p>
<h3 id="오류-페이지-등록">오류 페이지 등록</h3>
<p>cloudfront에서 페이지를 접속했을 때 <code>403 Forbidden</code>이 뜰 경우 리다이렉트해줄 파일을 선택할 수 있다.</p>
<p><img src="https://velog.velcdn.com/images/xiu_8/post/e99ee486-c996-4f36-bd08-c6416a4514ac/image.png" alt=""></p>
<p>403으로 뜰 경우 index.html 기본 폴더로 리다이렉트되게 설정하였다.</p>
<p><img src="https://velog.velcdn.com/images/xiu_8/post/3a60e605-3194-4941-ae0d-a6f1ecb16de0/image.png" alt=""></p>
<h2 id="4-cname-등록하기">4. CNAME 등록하기</h2>
<p>미리 가비아에 구매해둔 도메인을 등록하기 위해 가비아 페이지에서 cname을 등록해주자. 등록해서 바로 적용되는 것이 아닌 짧게는 15분~1시간 길게는 하루 반나절 정도 걸리니, cloudfront 배포 후 바로 등록해주는 것이 좋다.</p>
<p><img src="https://velog.velcdn.com/images/xiu_8/post/1f91fc45-0647-4dac-b137-12ef7b205f27/image.png" alt=""></p>
<p>자세한 내용을 따로 먼저 s3 cloudfront 배포후 추가 포스팅 첨부예정이다.</p>
<h3 id="s3-버킷-정적-호스팅-활성화">S3 버킷 정적 호스팅 활성화</h3>
<p>S3 get Object 설정
<img src="https://velog.velcdn.com/images/xiu_8/post/bfac4cb4-9d62-473d-905f-2fe776f12219/image.png" alt=""></p>
<h2 id="rout53으로-cname-등록">Rout53으로 cname 등록</h2>
<p><img src="https://velog.velcdn.com/images/xiu_8/post/61d1f79c-a99a-46c2-a063-4760d2da3977/image.png" alt=""></p>
<h2 id="끝">끝</h2>
<h3 id="포스팅-참고-링크">포스팅 참고 링크</h3>
<ul>
<li><a href="https://velog.io/@kcj_dev96/S3Cloudfront%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%9C-%EC%A0%95%EC%A0%81-%EC%9B%B9-%EB%B0%B0%ED%8F%AC">cloudfront+s3 배포</a></li>
<li><a href="https://inpa.tistory.com/entry/AWS-%F0%9F%93%9A-S3-%EA%B0%9D%EC%B2%B4-%EC%95%94%ED%98%B8%ED%99%94-%EA%B8%B0%EB%8A%A5-%EC%A2%85%EB%A5%98-%EB%B0%8F-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0">inpa DEV 티스토리 : AWS-📚-S3-객체-암호화-기능-종류-및-사용하기</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[맥 터미널에서 VScode 실행하기(feat. zsh: command not found: code 에러까지)]]></title>
            <link>https://velog.io/@xiu_8/%EB%A7%A5-%ED%84%B0%EB%AF%B8%EB%84%90%EC%97%90%EC%84%9C-VScode-%EC%8B%A4%ED%96%89%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@xiu_8/%EB%A7%A5-%ED%84%B0%EB%AF%B8%EB%84%90%EC%97%90%EC%84%9C-VScode-%EC%8B%A4%ED%96%89%ED%95%98%EA%B8%B0</guid>
            <pubDate>Fri, 26 Jul 2024 04:39:29 GMT</pubDate>
            <description><![CDATA[<p>터미널에서 실행하고 싶은 프로젝트 폴더로 이동한 후에 <code>code .</code> 명령어를 이용하여 VS code를 실행할 수 있다.</p>
<h2 id="세팅해서-안되길래-게시글을-찾아본-경우">세팅해서 안되길래 게시글을 찾아본 경우</h2>
<p>만약 이미 <code>code .</code> 명령어 설정을 했는데 실행이 안되는 경우</p>
<pre><code class="language-bash">zsh: command not found: code</code></pre>
<p> 먼저 응용프로그램에 VS code가 설치가 잘 되어있는지 확인해본다. i cloud 사용자라면 그냥 다운로드 폴더 안에 VS code가 설치 되어 있을 수 있기때문에 아무리 세팅을 반복해도 컴퓨터를 껏다키면 적용되지 않는다. </p>
<h1 id="처음-세팅하는-경우">처음 세팅하는 경우</h1>
<p>터미널에서 <code>cmd + shift + p</code> 명령어로 설정 탭을 켠후 
<strong>PATH에 code 명령 설치</strong> 또는 <strong>Shell Command: Install &#39;code&#39; command in PATH</strong>를 검색하여 클릭해준다.
<img src="https://velog.velcdn.com/images/xiu_8/post/00c6cdb7-940d-4e61-9463-c66916772bf4/image.png" alt=""></p>
<p>이미 설정이 되어있는 경우는 
<img src="https://velog.velcdn.com/images/xiu_8/post/aafb69f4-e9a6-4206-b7b6-3c967f06ee34/image.png" alt="">
아래와 같은 창이 뜬다.</p>
<p>간혹 설정하고 난 후 맥을 껏다켜면 </p>
<blockquote>
<p>eacces: permission denied, unlink &#39;/usr/local/bin/code&#39;</p>
</blockquote>
<p>위와 같은 에러가 뜨는 경우가 있는데 그럴 경우엔 터미널에서 </p>
<pre><code class="language-bash">cd /usr/local/bin</code></pre>
<p>bin 파일에 이동한 후 이전에 설정된 code를 삭제시켜준 후 재 설정 가능하다.</p>
<pre><code>sudo rm -rf code
password: </code></pre><p>sudo명령어를 입력한 후에 설정된 비밀번호를 입력해주면 된다.</p>
<p>처음 방법대로 vs code에서 Shall 명령어로 <strong>PATH에 code 명령 설치</strong>하기를 클릭하면 정상적으로 세팅되는 것을 확인할 수 있다.</p>
<p>이렇게 했는데도 안되는 컴퓨터 재시동시 zsh: command not found: code 에러가 뜨는 경우에는 .zshrc 파일에 VS code 명령어를 실행할 수 있는 PATH설정을 export해준다.</p>
<pre><code class="language-bash">vim ~/.zshrc</code></pre>
<p>읽기 모드로 열리는 경우 <code>i</code>를 눌러 편집모드로 변경 후 아래 코드를 후에 본인이 알아볼 수 있는 주석과 함께 붙여 넣은 후 <code>esc</code> + <code>:wq</code> 명령어를 통해 저장후 나오기를 실행한다.</p>
<pre><code>export PATH=&quot;$PATH:/Applications/Visual Studio Code.app/Contents/Resources/app/bin&quot;</code></pre><p>재시동후 터미널에서 VS code로 열고싶은 파일로 이동하여 <code>code .</code> 명령어를 실행한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[husky 사용하는 이유]]></title>
            <link>https://velog.io/@xiu_8/husky-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0</link>
            <guid>https://velog.io/@xiu_8/husky-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-%EC%9D%B4%EC%9C%A0</guid>
            <pubDate>Wed, 24 Apr 2024 13:04:15 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/xiu_8/post/7f46ab79-1b26-4c59-a598-ec01f0782e96/image.png" alt=""></p>
<h2 id="husky를-도입하는-이유">husky를 도입하는 이유</h2>
<p>lint와 prerrier설정 때문에 husky를 도입함. 강한 안전장치가 필요.</p>
<h3 id="아래-이유를-방지하기-위함">아래 이유를 방지하기 위함.</h3>
<ol>
<li>누군가 vscode/settings.json 또는 CLI 세팅을 넣어주더라도 vscode를 사용하지 않는 팀원 존재.</li>
<li>기존 설정 파일을 변경</li>
<li>CLI에서 명령어를 입력을 빼먹는 경우</li>
</ol>
<h3 id="ide레벨이-아닌-프로젝트-레벨">IDE레벨이 아닌 프로젝트 레벨</h3>
<ul>
<li><p>IDE레벨이 아닌 프로젝트 레벨에서 기존에 설정한 룰이 무조건 적용되게 하기위함.</p>
</li>
<li><p>git커밋 시 eslint, prettier를 무조건 적용.</p>
</li>
<li><p>git hook precommit를 사용하려면 husky를 써야겠다 생각.</p>
<h2 id="git-hook만-이용하는게-아니라-왜-husky인가">git hook만 이용하는게 아니라 왜 husky인가?</h2>
<p>git hook만 사용할 경우 git/hooks/pre-commit 파일에서 스크립트를 작성해서 쓰면 됨. 하지만 직접 스크립트를 작성하는데 번거로움이 있음. hook파일은 <code>.git</code> 안에 있어 git이 추적을 하지않아, 개개인이 관리해줘야하는 번거로움을 방지하고자 husky를 많이 사용한다고함.</p>
</li>
<li><p>허스키와 같이쓰는 link-staged라이브러리  : lint를 전체 적용하지 않고 git stage된 그런 상태 안에서만 lint 검사를 하여 시간을 단축시킬 수 있는 파일.</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[네이버 클라우드로 vm 만들어서 nginx 올리기 1탄]]></title>
            <link>https://velog.io/@xiu_8/%EB%84%A4%EC%9D%B4%EB%B2%84-%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9C%EB%A1%9C-vm-%EB%A7%8C%EB%93%A4%EA%B8%B0-%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@xiu_8/%EB%84%A4%EC%9D%B4%EB%B2%84-%ED%81%B4%EB%9D%BC%EC%9A%B0%EB%93%9C%EB%A1%9C-vm-%EB%A7%8C%EB%93%A4%EA%B8%B0-%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B8%B0</guid>
            <pubDate>Fri, 05 Apr 2024 16:02:40 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>기록기록. vm 서버 만들기 부터 환경설정까지 과정을 기록한 포스팅입니다.
이번 포스팅의 요약은 vm 서버 사양이 너무 낮아 사이트 접속 지연 이슈가 생겼다는 결말입니다.</p>
</blockquote>
<p>용어 이해하고 네이버 클라우드에서 제공하는 가이드센터만 차근차근 읽어본다면 네이버 클라우드로 vm 만들기 짱 쉬워용.</p>
<h2 id="네이버-클라우드로-vm-서버-만드는-순서-요약">네이버 클라우드로 vm 서버 만드는 순서 요약</h2>
<p>VPC 생성 -&gt; subnet 생성 -&gt; Server 생성</p>
<p>네이버 콘솔에 왼측에 메뉴바 &gt; VPC &gt; VPC Management접속
<img src="https://velog.velcdn.com/images/xiu_8/post/05c4df77-633a-4b37-8086-01764843f9bb/image.png" alt=""></p>
<h2 id="vpc-생성">vpc 생성</h2>
<p><img src="https://velog.velcdn.com/images/xiu_8/post/66292150-2ef9-401c-8e7f-a1c6b8542d61/image.png" alt=""></p>
<ul>
<li>vpc 이름은 본인이 배포할 프로젝트 이름이나 test와같은 구분할 수 있는 이름을 입력해주기</li>
<li>ip주소 범위는 VPC에서 많이 사용되는 일반적인 IP범위인 10.0.0.0/16로 설정해준다. <code>10.0.0.0/16</code>는 총 65,536개의 IP 주소를 사용할 수 있다.</li>
<li>VPC 유형 선택은 일반적으로 독립적인 VPC를 생성할 경우는 NORMAL일 경우에 선택, Transit Gateway와 연결되는 VPC를 생성할 때는 TRANSIT을 선택해준다. Transit Gateway은 여러 VPC와 온-프레미스 네트워크를 연결하는 허브 역할을 한다. 간단한 사이드 프로젝트일 경우라면 NORMAL유형의 VPC 생성을 권장한다. TRANSIT 유형은 복잡한 네트워크 아키텍처를 구현할 때 사용된다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/xiu_8/post/c8acfb41-209e-4818-9904-c31715e6f285/image.png" alt="">
vpc를 만들고나면 상태가 <code>생성중</code>으로 보통 5~10분 정도 소요된다. 더 복잡한 네트워크 구성이거나 다른 작업이 병행되는 경우에는 더 오래걸릴 수도 있다.</p>
<h3 id="vpc생성-과정">vpc생성 과정</h3>
<ol>
<li>VPC메타데이터 및 구성 정보 생성</li>
<li>라우팅 테이블, 보안 그룹 등 관련 리소스 생성</li>
<li>네트워크 환경 설정 및 초기화</li>
<li>생성 상태 검사 및 완료 처리</li>
</ol>
<h2 id="subnet-생성">subnet 생성</h2>
<p><img src="https://velog.velcdn.com/images/xiu_8/post/995150cf-1387-4262-8a9c-5a8943750f68/image.png" alt="">
VPC &gt; subnet Management 접속
<img src="https://velog.velcdn.com/images/xiu_8/post/f6e8f00e-095c-45cc-b1c8-3c2fe6ed039f/image.png" alt="">
옵션 입력하기</p>
<ul>
<li>vpc란에 생성한 vpc 선택해주기</li>
<li>ip 주소 범위는 10.0.0.0/16으로 설정</li>
<li>Internet Gateway는 격리 된 공간에 인터넷을 허용할 건지의 여부로 이해했다. 공인 IP를 사용하려면 Public Subnet만 등록이 되므로 Public으로 선택하기 <del>잘못 이해한 거라면 댓글로 알려주세여</del></li>
<li>용도는 일반으로 선택<h3 id="용도-옵션-특징">용도 옵션 특징</h3>
</li>
<li>LoadBalancer 여러 대의 서버에 들어오는 트래픽을 분산 시켜주는 역할</li>
<li>Bare Metal Server 실제 물리적 서버를 사용하는 옵션</li>
<li>NAT Gateway 사설 네트워크에서 인터넷에 접근하기 위해 사용됨. 인터넷을 통한 외부 서비스에 접근해야 하는 경우, NAT 게이트웨이를 통해 내부 IP주소를 공용 IP주소로 변환하여 통신함. 주로 보안 및 네트워크 관리를 위해 사용.</li>
</ul>
<blockquote>
<p>VPC와 Subnet 생성이 끝났다면 본인에게 맞는 운영 체제를 선택해 서버를 생성할 수 있다.</p>
</blockquote>
<h2 id="서버-생성">서버 생성</h2>
<p>Server &gt; Server 
<img src="https://velog.velcdn.com/images/xiu_8/post/b450c70c-5efc-413e-85cf-8d9f672718f5/image.png" alt=""></p>
<p>무료 버전인 micro를 사용할 경우 linux운영체제를 선택해준다.
<img src="https://velog.velcdn.com/images/xiu_8/post/eb7a77b4-d042-44b2-80dc-3cb8b986d7f2/image.png" alt="">
결제 수단 등록일로부터 1년간 무료로 제공되므로, 요금제 선택에서 뜨는 월 요금은 무시해주기. 무료 버전은 1개 계정당 서버 1대만 생성 가능하다.
<img src="https://velog.velcdn.com/images/xiu_8/post/18f148df-54d2-4746-95ad-0180d1c53749/image.png" alt=""></p>
<ul>
<li>Network Interface 생성</li>
<li>물리 배치 그룹 미사용</li>
<li>반납 보호 설정
<img src="https://velog.velcdn.com/images/xiu_8/post/398103c5-e317-4c1b-90ac-ea34374f0aee/image.png" alt=""><h3 id="스토리지-설정">스토리지 설정</h3>
기본 크기 10GB로 둔다. 
<img src="https://velog.velcdn.com/images/xiu_8/post/550ec336-14df-4de0-a936-d2991c781b6e/image.png" alt="">
인증키 설정은 보유하고 있는 키가 있다면 보유중인 인증키를 사용하고 없다면 새로운 키를 생성해준다.
<img src="https://velog.velcdn.com/images/xiu_8/post/1ba6e111-815c-40ed-888d-dd51770b3c89/image.png" alt="">
(요렇게 다운받아짐)
<img src="https://velog.velcdn.com/images/xiu_8/post/e21977ef-be3c-43a9-83f2-7daa1eddb1c2/image.png" alt="">
네트워크 접속 
<img src="https://velog.velcdn.com/images/xiu_8/post/2c624296-5611-43ed-8355-57fe3b86e2f2/image.png" alt="">
마지막으로 Server&gt;ACG로 이동해서 ACG생성 해면 서버 완료 끝~<h3 id="acg란">ACG란?</h3>
</li>
<li>IP 기반 필터링 기능으로 서버로의 네트워크 접근을 관리하는 서비스</li>
<li>ACG에서 네트워크 접근 ip를 설정 할 수 있음</li>
<li>자주 사용하는 TCP, UDP, ICMP 외에도 다양한 프로토콜을 제어 및 관리</li>
</ul>
<blockquote>
<p>공인IP까지 등록해줘야 접속이 가능해용.</p>
</blockquote>
<ul>
<li>Server &gt; Public IP 이동</li>
<li>공인 IP신청</li>
<li>적용 서버 선택에 방금 생성한 서버를 선택해주고 최종확인까지 하면 끝!</li>
<li>서버 선택에 생성한 서버가 안뜬다면 서버 생성에 시간이 조금 소요되므로 잠시 기다렸다 공인 ip등록을 해준다.</li>
</ul>
<h2 id="네이버-클라우드-터미널-ssh로-vm-서버-접근하기">네이버 클라우드 터미널 ssh로 vm 서버 접근하기</h2>
<p>아래 명령어 본인 서버에 맞춰 입력하기</p>
<pre><code class="language-bash">ssh &lt;관리자 이름&gt;@&lt;공인 ip 주소&gt;</code></pre>
<p>위 형태로 입력하면되는데 처음 vm 서버에 접속할 시에는 대부분 서버 이름 기본값이 <code>root</code>로 돼있다.</p>
<p>확인하는 방법은 네이버 클라우드 콘솔에서 VPC &gt; Server &gt; Server 카테고리에서 확인할 서버를 선택한 후, 상단에 <code>서버 관리 및 설정 변경 &gt; 관리자 비밀번호 확인</code>에서 처음 vm 서버를 생성 시 등록한 pem 인증키 파일을 첨부해 서버 관리자 이름과 비밀번호를 확인할 수 있다. </p>
<blockquote>
<p>초기 서버 이름 확인</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/xiu_8/post/3780ef5e-c5d5-49a6-a166-32d2c65d3319/image.png" alt=""></p>
<p>터미널로 vm 접속하기
<img src="https://velog.velcdn.com/images/xiu_8/post/ff19264b-ba7c-424a-b3c6-7187cb6c958d/image.png" alt=""></p>
<p>터미널에 위와 같은 창이 뜨면 vm에 접속 성공.
<a href="https://www.ncloud.com/guideCenter/guide/36">네이버 클라우드 가이드센터 바로가기</a></p>
<p>비밀번호 변경 명령어</p>
<pre><code class="language-bash">passwd root</code></pre>
<h2 id="vm-서버-환경-설정">vm 서버 환경 설정</h2>
<p>각자 프로젝트에 맞는 환경설정을 해준다.</p>
<h3 id="nginx-설치">nginx 설치</h3>
<p>엑, 무료 버전을 쓰려고 일단 먼저 vm 서버를 만들었는데 네이버 클라우드에서 권장하는 이미지가 있었다. 무료버전으로 해도 조금 느려지는 거 말고 큰 차이 있겠냐 생각하며 그냥 만들어둔 서버에 nginx를 설치했다.</p>
<h4 id="패키지-업그레이드">패키지 업그레이드</h4>
<pre><code class="language-bash">~# dnf -y upgrade-minimal</code></pre>
<p><img src="https://velog.velcdn.com/images/xiu_8/post/d50e4091-afa2-46fe-8479-2ca1c3b6eb5b/image.png" alt="">
모지? 업그레이드가 어마어마하게 돼서 이게 micro 서버에서 괜찮은 건가 살짝 불안해졌지만, 어떻게든 되겠지 생각하고 그대로 진행했다.
<del>설치가 이렇게 오래 걸리는게  맞나?</del>
<img src="https://velog.velcdn.com/images/xiu_8/post/c94d295a-0694-4c95-aa42-ec81bbe22add/image.png" alt="">
업그레이드가 완료되면 nginx 설치준비하기.
nginx 최신버전을 설치하려면 epel-release 리포지토리 패키지가 필요한데, epel-release 리포지토리 패키지를 설치하기 위해서는 Extras 저장소 파일이 필요하다.</p>
<pre><code class="language-bash">vi /etc/yum.repos.d/Rocky-Extras.repo</code></pre>
<p> 파일을 확인했을 때, 아래 처럼 Extras 저장소 설정 파일이 있다면 다음단계로 넘어가면 된다. 그렇지 않다면 아래 내용으로 파일을 생성한다.
 <img src="https://velog.velcdn.com/images/xiu_8/post/aed8fdf1-0513-4496-b968-b18587e7f8cc/image.png" alt=""></p>
<h4 id="epel-저장소-패키지-설치">EPEL 저장소 패키지 설치</h4>
<pre><code class="language-bash">dnf -y install epel-release</code></pre>
<p><img src="https://velog.velcdn.com/images/xiu_8/post/a002e50a-7102-4787-a44c-2f724442aa26/image.png" alt=""></p>
<p>nginx 설치, 설치 후 버전 확인</p>
<pre><code class="language-bash">dnf -y install nginx
nginx -v</code></pre>
<p><img src="https://velog.velcdn.com/images/xiu_8/post/2fb56664-a58a-4e07-bac8-f9e35d419ed7/image.png" alt=""></p>
<p>다음으로 홈으로 사용할 디렉토리 생성 및 해당 디렉토리 소유권 설정을 해준다.</p>
<pre><code class="language-bash"># 테스트 사이트 홈 디렉토리 생성
mkdir -p /ncloud/data/www/nginx-test/

# 해당 디렉토리에 nginx에 권한 부여
chown -R nginx:nginx /ncloud/data/www/nginx-test

# nginx 샘플 페이지를 사이트 디렉토리로 복사
cp /usr/share/nginx/html/*.* /ncloud/data/www/nginx-test/

# 복사된 파일들 확인
ls -al /ncloud/data/www/nginx-test/</code></pre>
<p><img src="https://velog.velcdn.com/images/xiu_8/post/92c4d073-d197-4fe1-8875-53216566da4a/image.png" alt=""></p>
<p>디렉토리 파일 구조 확인</p>
<pre><code class="language-bash">tree -P *conf* /etc/nginx/</code></pre>
<p><img src="https://velog.velcdn.com/images/xiu_8/post/eb7931b4-4c1a-4c8a-8fcf-75f5c3825ec1/image.png" alt="">
기본 설정 파일</p>
<pre><code class="language-bash">vi /etc/nginx/nginx.conf</code></pre>
<p>nginx 실행</p>
<pre><code class="language-bash">systemctl enable nginx
systemctl start nginx
systemctl status nginx</code></pre>
<p><img src="https://velog.velcdn.com/images/xiu_8/post/26e30b61-37a3-422e-abc3-1f64a2b4920c/image.png" alt=""></p>
<p>nginx 실행 후 vm ip 주소로 접속했을 때 nginx 화면이 실행되면 끝난건데, 서버가 micro 버전이어서 그런지 접속하는데 로딩이 너무 오래걸린다.
한번 해봤으니, 하다 안되면 vm 날리고 다시 처음부터 만들면 된다.
<img src="https://velog.velcdn.com/images/xiu_8/post/e0ccbd5e-9c42-4a88-bf88-a8ae7b0e4909/image.png" alt=""></p>
<h3 id="참고링크">참고링크</h3>
<p><a href="https://docs.3rdeyesys.com/compute/ncloud-compute-lemp-nginx-install-setting-rocky-linux-guide.html">linux에 nginx 설치하기</a></p>
<p><a href="https://docs.rockylinux.org/guides/web/nginx-mainline/">How to Install the Latest Nginx on Rocky Linux</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[목표 직무 전환 기념 깃허브 꾸미기]]></title>
            <link>https://velog.io/@xiu_8/%EB%AA%A9%ED%91%9C-%EC%A7%81%EB%AC%B4-%EC%A0%84%ED%99%98-%EA%B8%B0%EB%85%90-%EA%B9%83%ED%97%88%EB%B8%8C-%EA%BE%B8%EB%AF%B8%EA%B8%B0</link>
            <guid>https://velog.io/@xiu_8/%EB%AA%A9%ED%91%9C-%EC%A7%81%EB%AC%B4-%EC%A0%84%ED%99%98-%EA%B8%B0%EB%85%90-%EA%B9%83%ED%97%88%EB%B8%8C-%EA%BE%B8%EB%AF%B8%EA%B8%B0</guid>
            <pubDate>Wed, 14 Feb 2024 04:15:19 GMT</pubDate>
            <description><![CDATA[<p>Header, Footer 코드 : <a href="https://github.com/kyechan99/capsule-render">https://github.com/kyechan99/capsule-render</a></p>
<p>Heade 쿼리로 바로 만들어주는 사이트 :<a href="https://capsule-render.vercel.app/">https://capsule-render.vercel.app/</a></p>
<p>깃허브 상태 코드 : <a href="https://github.com/anuraghazra/github-readme-stats">https://github.com/anuraghazra/github-readme-stats</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[디자인패턴2 팩토리, 전략, 옵저버 패턴]]></title>
            <link>https://velog.io/@xiu_8/%EB%94%94%EC%9E%90%EC%9D%B8%ED%8C%A8%ED%84%B42-%ED%8C%A9%ED%86%A0%EB%A6%AC-%EC%A0%84%EB%9E%B5-%EC%98%B5%EC%A0%80%EB%B2%84-%ED%8C%A8%ED%84%B4</link>
            <guid>https://velog.io/@xiu_8/%EB%94%94%EC%9E%90%EC%9D%B8%ED%8C%A8%ED%84%B42-%ED%8C%A9%ED%86%A0%EB%A6%AC-%EC%A0%84%EB%9E%B5-%EC%98%B5%EC%A0%80%EB%B2%84-%ED%8C%A8%ED%84%B4</guid>
            <pubDate>Sun, 14 Jan 2024 06:40:42 GMT</pubDate>
            <description><![CDATA[<h3 id="112-팩토리-패턴">1.1.2 팩토리 패턴</h3>
<p>factory 공장 패턴이란? 객체를 사용하는 코드에서 객체 생성 부분을 떼어내 추상화한 패턴이자 상속 관계에 있는 두 클래스에서 상위 클래스가 중요한 뼈대를 결정하고, 하위 클래스에서 객체 생성에 관한 구체적인 내용을 결정하는 패턴
= 공장(Factory) 클래스로 캡슐화 처리하여 대신 생성하게 하는 생성 디자인 패턴</p>
<ul>
<li>객체 생성 로직이 떼어져 있기 때문에 코드 리팩터링시 한 곳만 고칠 수 있어 유지 보수성이 증가하게된다.</li>
<li>각 재료 공장을 연상하기</li>
</ul>
<h4 id="자바스크립트의-팩토리-패턴">자바스크립트의 팩토리 패턴</h4>
<p><code>new Object()</code>로 구현 가능. 전달받은 값에 따라 다른 객체를 생성하며 인스턴스의 타입 등을 정함</p>
<pre><code class="language-javascript">class Latte {
  constructor() {
    this.name = &quot;latte&quot;;
  }
}

class Espresso {
  constructor() {
    this.name = &quot;Espresso&quot;;
  }
}

class LatteFactory {
  static createCoffee() {
    return new Latte()
  }
}
class EspressoFactory {
  static createCoffee() {
    return new Espresso()
  }
}

const factoryList = {LatteFactory,EspressoFactory}

class CoffeeFactory {
    static createCoffee(type) {
      const factory = factoryList[type]
      retrun factory.createCoffee()
  }
}

const main = ()=&gt;{
  // Doing order latte
  const coffee = CoffeeFactory.createCoffee(&quot;LatteFactory&quot;)
  // Calling coffee&#39;s name
  console.log(coffee.name) // latte
}
main()
</code></pre>
<h4 id="팩토리-메서드-패턴-흐름">팩토리 메서드 패턴 흐름</h4>
<p><img src="https://velog.velcdn.com/images/xiu_8/post/125c5e9a-6695-432f-90e5-f5976c49f7ac/image.png" alt=""></p>
<h4 id="패턴-사용-시기">패턴 사용 시기</h4>
<ul>
<li>클래스 생성과 사용의 처리 로직을 분리하여 결합도를 낮추고자 할때</li>
<li>코드가 동작해야 하는 객체의 유형과 종속성을 캡슐화를 통해 정보 은닉 처리 할 경우</li>
<li>라이브러리 혹은 프레임워크 사용자에게 구성 요소를 확장하는 방법을 제공하려는 경우</li>
<li>기존 객체를 재구성하는 대신 기존 객체를 재사용하여 리소스를 절약하고자 하는 경우</li>
</ul>
<h3 id="113-전략-패턴">1.1.3 전략 패턴</h3>
<p>전략 패턴(strategy pattern) = 정책 패턴(policy pattern)</p>
<ul>
<li>캡슐화한 알고리즘을 컨텍스트 안에서 바꿔주면서 상호 교체가 가능하게 만드는 패턴</li>
</ul>
<h4 id="passport의-전략-패턴">passport의 전략 패턴</h4>
<p>Node.js에서 인증 모듈을 구현할 때 쓰는 미들웨어 라이브러리</p>
<h3 id="114-옵저버-패텅">1.1.4 옵저버 패텅</h3>
<p>observer pattern은 주체가 어떤 객체의 상태 변화를 관찰하다가 상태 변화가 있ㅇㄹ 때마다 메서드 등을 통해 옵저버 목록에 있는 옵저버들에게 변화를 알려주는 디자인 패턴</p>
<ul>
<li>트위터가 옵저버 패턴(&quot;새로운 트윗을 옵저버들에게 알려준다&quot;)</li>
<li>주로 이벤트 기반 시스템에 사용하며 MVC 패턴에도 사용된다.</li>
</ul>
<h4 id="자바스크립트에서의-옵저버-패턴">자바스크립트에서의 옵저버 패턴</h4>
<p>프록시 객체를 통해 구현 가능</p>
<blockquote>
<p>프록시(proxy) 객체?
어떠한 대상의 기본적인 동작(속성 접근, 할당, 순회, 열거, 함수 호출 등)의 작업을 가로챌 수 있는 객체. 프록시 객체는 두 개의 매개변수를 가짐</p>
<ul>
<li>target :프록시할 대상</li>
<li>handler 프록시 객체의 target 동작을 가로채서 정의할 동작들이 정해져 있는 함수</li>
</ul>
</blockquote>
<p>프록시 객체를 이용한 옵저버 패턴</p>
<pre><code class="language-javascript">function createReactiveObject(target, callback) {
  const proxy = new Proxy(target, {
    set(obj, prop, value) {
      if (value !== obj[prop]) {
        const prev = obj[prop];
        obj[prop] = value;
        callback(`${prop}(이)가 [${prev}] &gt;&gt; [${value}]로 변경되었습니다.`);
      }
      return true;
    },
  });
  return proxy;
}
const a = {
  채영: &quot;솔로&quot;,
};
const b = createReactiveObject(a, console.log);
b.채영 = &quot;솔로&quot;;
b.채영 = &quot;커플&quot;;
// 채영(이)가 [솔로] &gt;&gt; [커플]로 변경되었습니다.</code></pre>
<h4 id="참고링크">참고링크</h4>
<p><a href="https://inpa.tistory.com/entry/GOF-%F0%9F%92%A0-%ED%8C%A9%ED%86%A0%EB%A6%AC-%EB%A9%94%EC%84%9C%EB%93%9CFactory-Method-%ED%8C%A8%ED%84%B4-%EC%A0%9C%EB%8C%80%EB%A1%9C-%EB%B0%B0%EC%9B%8C%EB%B3%B4%EC%9E%90">팩토리 메서드 패턴-완벽 마스터하기</a></p>
<ul>
<li>참고 서적 면접을 위한 CS 전공 지식 노트</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[
디자인 패턴1 싱글톤 패턴 ]]></title>
            <link>https://velog.io/@xiu_8/%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B41-%EC%8B%B1%EA%B8%80%ED%86%A4-%ED%8C%A8%ED%84%B4</link>
            <guid>https://velog.io/@xiu_8/%EB%94%94%EC%9E%90%EC%9D%B8-%ED%8C%A8%ED%84%B41-%EC%8B%B1%EA%B8%80%ED%86%A4-%ED%8C%A8%ED%84%B4</guid>
            <pubDate>Sun, 07 Jan 2024 09:06:23 GMT</pubDate>
            <description><![CDATA[<h2 id="11-디자인-패턴">1.1 디자인 패턴</h2>
<p>프로그램을 설계할 때 발생했던 문제점들을 객체 간의 상호 관계 등을 이용하여 해결할 수 있도록 하나의 &#39;규약&#39;형태로 만들어 놓은 것</p>
<h3 id="111-싱글톤-패턴">1.1.1 싱글톤 패턴</h3>
<ul>
<li>singlton pattern 하나의 클래스에 오직 하나의 인스턴스만 가지는 패턴</li>
<li>데이터 베이스 연결 모듈에 많이 사용</li>
<li>장점 : 해당 인스턴스를 다른 오듈들이 공유하며 사용하기 때문에 인스턴스를 생성할 때 드는 비용이 줄어든다.</li>
<li>단점: 의존성이 높아진다.</li>
</ul>
<h4 id="자바스크립트-싱글톤-패턴">자바스크립트 싱글톤 패턴</h4>
<p><a href="https://chaeoff.medium.com/singleton-pattern-%EC%8B%B1%EA%B8%80%ED%86%A4-%ED%8C%A8%ED%84%B4-1131fae052f5">예시 참고</a></p>
<pre><code class="language-javascript">// Singleton.js
let instance;

export default class Singleton {
  constructor(data = &quot;Initial data&quot;) {
    if (instance) {
      return instance;
    }
    this.data = data;
    instance = this;
  }

  getData() {
    return this.data;
  }

  setData(data) {
    this.data = data;
  }
}</code></pre>
<h4 id="데이터베이스-연결-모듈">데이터베이스 연결 모듈</h4>
<pre><code class="language-javascript">const URL = &quot;mongodb://localhost:27017/app&quot;;
const createConnection = url =&gt; ({ url: url });

class DB {
  constructor(url) {
    if (!DB.instance) {
      DB.instance = createConnection(url);
    }
    return DB.instance;
  }
  connect() {
    return this.instance;
  }
}

const a = new DB(URL);
const b = new DB(URL);

console.log(a === b); // true</code></pre>
<p>하나의 인스턴스 기반으로 a, b를 생성함으로 데이터베이스 연결에 관한 인스턴스 생성 비용을 아낄 수 있다.</p>
<h4 id="싱글톤-패턴의-단점">싱글톤 패턴의 단점</h4>
<ol>
<li>독립적인 인스턴스 생성의 어려움<blockquote>
<p>TDD(Test Driven Development)를 할 때 단위 테스트를 주로 하는데 단위 테스트는 테스트가 서로 독립적이어야 하며 테스트를 어떤 순서로든 실행할 수 있어야하는데 싱글톤 패턴은 독립적인 인스턴스를 만들기 어렵다.</p>
</blockquote>
</li>
<li>모듈 간의 의존성이 강함<blockquote>
<p>모듈 간의 결합을 강하게 만든다. 의존성 주입(DI, Dependency Injection)을 통해 모듈간의 결합을 조금 더 느슨하게 만들어 해결할 수 있다. * 의존성 주입을 종속성이라고도 한다.</p>
</blockquote>
</li>
</ol>
<h4 id="의존성-주입의-장점">의존성 주입의 장점</h4>
<p>모듈들을 쉽게 교체할 수 있는 구조가 되어 테스팅과 마이그레이션이 수월해진다. 구현 시 추상화 레이어를 넣고 이를 기반으로 구현체를 넣어 주기 때문에 애플리케이션 의존성 방향이 일관되고, 애플리케이션을 쉽게 추론할 수있다.</p>
<h4 id="의존성-주입의-단점">의존성 주입의 단점</h4>
<p>오듈들이 더욱더 분리되므로 클래스 수가 늘어나 복잡성이 증가될 수 있고 약간의 런타임 페널티가 발생.</p>
<h4 id="의존성-주입의-원칙">의존성 주입의 원칙</h4>
<ul>
<li>상위 도율은 하위 모듈에서 어떠한 것도 가져오지 않아야한다. 둘 다 추상화에 의존해야하며 추상화는 세부 사항에 의존하지 않아야한다.</li>
</ul>
<h4 id="추상화란">추상화란?</h4>
<p>프로그래밍에서 추상화란 복잡하고 불필요한 세부 사항을 숨겨 코드를 더 간단하고 읽기 쉽고 유지 관리하기 쉽게 만드는 프로세스.</p>
<ul>
<li><p>좋은 객체를 만드는 법, 설계를 잘하는 법을 추상화라고 생각하기</p>
</li>
<li><p>참고링크
<a href="https://anerim.tistory.com/78">객체 지향 프로그래밍 4가지 개념</a>
<a href="https://moony211.medium.com/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EC%9D%98-%EC%B6%94%EC%83%81%ED%99%94-%ED%95%A8%EC%88%98%EC%99%80-%EA%B3%A0%EC%B0%A8-%ED%95%A8%EC%88%98%EB%A1%9C-%EC%BD%94%EB%93%9C-%EA%B0%84%EC%86%8C%ED%99%94%ED%95%98%EA%B8%B0-163fd12ec645">자바스크립트의 추상화: 함수와 고차 함수로 코드 간소화하기</a></p>
</li>
<li><p>참고 서적 
<a href="https://www.yes24.com/Product/Goods/108887922?pid=123487&amp;cosemkid=go16505206189583564&amp;gad_source=1&amp;gclid=Cj0KCQiAtOmsBhCnARIsAGPa5yb8FbJTElg0c1gZPg3vfyh2445z2yh7zDqGaXplvMylmsF0RMQtdXIaAqiREALw_wcB">면접을 위한 CS 전공 지식 노트</a></p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[자바스크립트 filter 함수]]></title>
            <link>https://velog.io/@xiu_8/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-filter-%ED%95%A8%EC%88%98</link>
            <guid>https://velog.io/@xiu_8/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-filter-%ED%95%A8%EC%88%98</guid>
            <pubDate>Tue, 02 Jan 2024 04:57:57 GMT</pubDate>
            <description><![CDATA[<h2 id="filter-메서드-사용-형태">filter 메서드 사용 형태</h2>
<p><code>Array.filter(조건 함수)</code></p>
<ul>
<li>주어진 배열에서 제공된 함수에 의해 구현된 테스트를 통과한 요소로만 필터링한다.<pre><code class="language-javascript">const words = [&#39;spray&#39;, &#39;elite&#39;, &#39;exuberant&#39;, &#39;destruction&#39;, &#39;present&#39;];
</code></pre>
</li>
</ul>
<p>const result = words.filter((word) =&gt; word.length &gt; 6);</p>
<p>console.log(result);
// Expected output: Array [&quot;exuberant&quot;, &quot;destruction&quot;, &quot;present&quot;]</p>
<pre><code>filter함수의 매개변수
```javascript
filter(callbackFn)
filter(callbackFn, thisArg)</code></pre><h3 id="callbackfn">callbackFn</h3>
<p>배열의 각 요소에 대해 실행할 함수. 결과 배열에 요소를 유지하려면 참 값을 반환하고 그렇지 않으면 거짓 값을 반환한다.</p>
<ul>
<li>구성 인수 <code>element</code>(배열에서 처리 중인 현재 요소), <code>index</code>(배열에서 처리 중인 현재 요소의 인덱스), <code>array</code> (filter()가 호출된 배열)</li>
</ul>
<h3 id="thisarg">thisArg</h3>
<ul>
<li>callbackFn을 실행할 때 this 값으로 사용할 값, 순회 메서드</li>
</ul>
<blockquote>
<p>순회메서드</p>
<ul>
<li>많은 배열 메서드는 콜백 함수를 인수로 받는다. 콜백 함수는 배열의 각 요소에 대해 순차적으로 최대 한 번만 호출되며, 콜백 함수의 반환값은 메서드의 반환값을 결정하는 데 사용.</li>
<li>예시 : every(), filter(), find(), findIndex(), map(), flatMap(), forEach(), some() 등</li>
</ul>
</blockquote>
<h2 id="filter함수란">filter함수란?</h2>
<p> 얕은 복사본은 반환하는 복사, 순회 메서드로 배열의 각 요소에 대해 제공된 콜백함수를 한 번씩 호출하고, 콜백이 참 값을 반환하는 모든 값으로 새 배열을 구성한다. 콜백함수 테스트를 통과하지 못한 배열 요소는 새 배열에 포함되지 않는다.
 콜백함수는 값이 할당된 배열 인덱스에 대해서만 호출된다.</p>
<h3 id="사용-시-주의-사항">사용 시 주의 사항</h3>
<ul>
<li>callbackFn은 filter() 호출이 시작되었을 때 배열의 초기 length 값을 초과하여 추가된 요소는 방문하지 않는다.<ul>
<li>이미 방문한 인덱스를 변경해도 callbackFn이 해당 인덱스에 대해 다시 호출되지 않는다.</li>
<li>배열의 아직 방문하지 않은 기존 요소가 callbackFn에 의해 변경되는 경우, callbackFn에 전달된 값은 해당 요소가 방문될 당시의 값이 됩니다. delete된 요소는 방문하지 않는다.<h2 id="예시">예시</h2>
<pre><code class="language-javascript">function isBigEnough(value) {
return value &gt;= 10;
}
</code></pre>
</li>
</ul>
</li>
</ul>
<p>const filtered = [12, 5, 8, 130, 44].filter(isBigEnough);
// 필터링된 값은 [12, 130, 44]</p>
<p>```</p>
<ul>
<li>filter메서드는 복잡한 코드를 생성하는 경우가 많으므로 꼭 필요한 경우가 아니라면 사용 지양하기. </li>
</ul>
<p><a href="https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/filter">참고링크</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[url 유효성 검사에  정규 표현식 사용하기]]></title>
            <link>https://velog.io/@xiu_8/url-%EC%9C%A0%ED%9A%A8%EC%84%B1-%EA%B2%80%EC%82%AC%EC%97%90-%EC%A0%95%EA%B7%9C-%ED%91%9C%ED%98%84%EC%8B%9D-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0-93m986wq</link>
            <guid>https://velog.io/@xiu_8/url-%EC%9C%A0%ED%9A%A8%EC%84%B1-%EA%B2%80%EC%82%AC%EC%97%90-%EC%A0%95%EA%B7%9C-%ED%91%9C%ED%98%84%EC%8B%9D-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0-93m986wq</guid>
            <pubDate>Sat, 30 Dec 2023 03:35:45 GMT</pubDate>
            <description><![CDATA[<p>url 유효성 검사에  정규 표현식 사용하기
<img src="https://velog.velcdn.com/images/xiu_8/post/52a2d22f-1cab-42b4-807f-cc764fc49e15/image.png" alt=""></p>
<p>URL 유효성 검사는 웹 개발에서 중요한 부분 중 하나이다. 대부분의 경우, 정규표현식을 사용하여 간단한 유효성 검사를 수행할 수 있다. 그러나 정규표현식은 모든 상황을 다루지 못할 수 있으므로 사용자는 이 한계를 이해하고 추가적인 확인 방법을 고려해야 한다.</p>
<p> URL 유효성 검사에 제공된 정규식은 대부분의 경우에 효과적일 수 있지만, 유효한 URL의 모든 인스턴스를 캡처하지 못할 수도 있다는 점에 유의해야한다.P 주소가 포함된 웹 주소, 라틴 문자가 아닌 문자 또는 FTP와 같은 대체 프로토콜이 포함될 수 있다. </p>
<h2 id="url-유효성-검사를-위한-정규표현식">URL 유효성 검사를 위한 정규표현식</h2>
<p> URL 유효성 검사를 위한 간단한 정규표현식이다. 이 정규표현식은 대부분의 경우에 효과적일 수 있지만, 모든 상황을 다루지는 않는다. IP 주소, 라틴 문자가 아닌 문자, FTP와 같은 대체 프로토콜 등이 포함될 수 있다. 
<a href="https://new.atsit.in/8330/">참고</a></p>
<pre><code class="language-javascript">const urlRegex = /^(https?|ftp):\/\/(-\.)?([^\s\/?\.#-]+\.?)+(\/[^\s]*)?$/i;</code></pre>
<h2 id="정규표현식-한계">정규표현식 한계</h2>
<p>이 정규표현식은 일반적인 경우에는 효과적이지만, 모든 상황을 다루지는 못한다. 사용자는 이 한계를 이해하고, 추가적인 검사 방법을 사용하여 정확성을 보장해야 한다. 예를 들어, IP 주소가 포함된 웹 주소나 라틴 문자가 아닌 문자를 다루기 위해 추가적인 확인 로직이 필요할 수 있다.</p>
<h2 id="코드-예시">코드 예시</h2>
<pre><code class="language-javascript">function isValidURL(url) {
  const urlRegex = /^(https?|ftp):\/\/(-\.)?([^\s\/?\.#-]+\.?)+(\/[^\s]*)?$/i;
  return urlRegex.test(url);
}

// 사용 예시
const url1 = &quot;https://www.example.com&quot;;
const url2 = &quot;ftp://ftp.example.com&quot;;
const url3 = &quot;invalid-url&quot;;

console.log(isValidURL(url1)); // true
console.log(isValidURL(url2)); // true
console.log(isValidURL(url3)); // false</code></pre>
<h2 id="추가-확인-방법-활용하기">추가 확인 방법 활용하기</h2>
<p>정규표현식을 사용한 기본적인 검사 후에도 사용자는 추가적인 확인 방법을 활용하여 정확성을 높일 수 있다. 예를 들어, 네트워크 요청을 통해 실제로 해당 URL이 존재하는지 확인하거나, 더 엄격한 검사를 위해 서드파티 라이브러리를 사용할 수 있다.</p>
<p>자신만의 추가 확인 방법을 도입하여 보다 신뢰성 있는 URL 유효성 검사를 수행할 수 있다.</p>
<h3 id="다양한-url-매칭-방법들">다양한 url 매칭 방법들</h3>
<p> Exact, Simple, Starts, Ends, Contains, Regular Expression 매치
 <a href="https://forum.beusable.net/ko/post/1320">참고링크</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[url 유효성 검사에  정규 표현식 사용하기]]></title>
            <link>https://velog.io/@xiu_8/url-%EC%9C%A0%ED%9A%A8%EC%84%B1-%EA%B2%80%EC%82%AC%EC%97%90-%EC%A0%95%EA%B7%9C-%ED%91%9C%ED%98%84%EC%8B%9D-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0-g32av6ud</link>
            <guid>https://velog.io/@xiu_8/url-%EC%9C%A0%ED%9A%A8%EC%84%B1-%EA%B2%80%EC%82%AC%EC%97%90-%EC%A0%95%EA%B7%9C-%ED%91%9C%ED%98%84%EC%8B%9D-%EC%82%AC%EC%9A%A9%ED%95%98%EA%B8%B0-g32av6ud</guid>
            <pubDate>Sat, 30 Dec 2023 03:35:45 GMT</pubDate>
            <description><![CDATA[<p>url 유효성 검사에  정규 표현식 사용하기
<img src="https://velog.velcdn.com/images/xiu_8/post/52a2d22f-1cab-42b4-807f-cc764fc49e15/image.png" alt=""></p>
<p>URL 유효성 검사는 웹 개발에서 중요한 부분 중 하나이다. 대부분의 경우, 정규표현식을 사용하여 간단한 유효성 검사를 수행할 수 있다. 그러나 정규표현식은 모든 상황을 다루지 못할 수 있으므로 사용자는 이 한계를 이해하고 추가적인 확인 방법을 고려해야 한다.</p>
<p> URL 유효성 검사에 제공된 정규식은 대부분의 경우에 효과적일 수 있지만, 유효한 URL의 모든 인스턴스를 캡처하지 못할 수도 있다는 점에 유의해야한다.P 주소가 포함된 웹 주소, 라틴 문자가 아닌 문자 또는 FTP와 같은 대체 프로토콜이 포함될 수 있다. </p>
<h2 id="url-유효성-검사를-위한-정규표현식">URL 유효성 검사를 위한 정규표현식</h2>
<p> URL 유효성 검사를 위한 간단한 정규표현식이다. 이 정규표현식은 대부분의 경우에 효과적일 수 있지만, 모든 상황을 다루지는 않는다. IP 주소, 라틴 문자가 아닌 문자, FTP와 같은 대체 프로토콜 등이 포함될 수 있다. 
<a href="https://new.atsit.in/8330/">참고</a></p>
<pre><code class="language-javascript">const urlRegex = /^(https?|ftp):\/\/(-\.)?([^\s\/?\.#-]+\.?)+(\/[^\s]*)?$/i;</code></pre>
<h2 id="정규표현식-한계">정규표현식 한계</h2>
<p>이 정규표현식은 일반적인 경우에는 효과적이지만, 모든 상황을 다루지는 못한다. 사용자는 이 한계를 이해하고, 추가적인 검사 방법을 사용하여 정확성을 보장해야 한다. 예를 들어, IP 주소가 포함된 웹 주소나 라틴 문자가 아닌 문자를 다루기 위해 추가적인 확인 로직이 필요할 수 있다.</p>
<h2 id="코드-예시">코드 예시</h2>
<pre><code class="language-javascript">function isValidURL(url) {
  const urlRegex = /^(https?|ftp):\/\/(-\.)?([^\s\/?\.#-]+\.?)+(\/[^\s]*)?$/i;
  return urlRegex.test(url);
}

// 사용 예시
const url1 = &quot;https://www.example.com&quot;;
const url2 = &quot;ftp://ftp.example.com&quot;;
const url3 = &quot;invalid-url&quot;;

console.log(isValidURL(url1)); // true
console.log(isValidURL(url2)); // true
console.log(isValidURL(url3)); // false</code></pre>
<h2 id="추가-확인-방법-활용하기">추가 확인 방법 활용하기</h2>
<p>정규표현식을 사용한 기본적인 검사 후에도 사용자는 추가적인 확인 방법을 활용하여 정확성을 높일 수 있다. 예를 들어, 네트워크 요청을 통해 실제로 해당 URL이 존재하는지 확인하거나, 더 엄격한 검사를 위해 서드파티 라이브러리를 사용할 수 있다.</p>
<p>자신만의 추가 확인 방법을 도입하여 보다 신뢰성 있는 URL 유효성 검사를 수행할 수 있다.</p>
<h3 id="다양한-url-매칭-방법들">다양한 url 매칭 방법들</h3>
<p> Exact, Simple, Starts, Ends, Contains, Regular Expression 매치
 <a href="https://forum.beusable.net/ko/post/1320">참고링크</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[express+typescript 환경설정]]></title>
            <link>https://velog.io/@xiu_8/expresstypescript-%ED%99%98%EA%B2%BD%EC%84%A4%EC%A0%95</link>
            <guid>https://velog.io/@xiu_8/expresstypescript-%ED%99%98%EA%B2%BD%EC%84%A4%EC%A0%95</guid>
            <pubDate>Fri, 29 Dec 2023 13:08:36 GMT</pubDate>
            <description><![CDATA[<p><a href="https://dev.to/cristain/how-to-set-up-typescript-with-nodejs-and-express-2023-gf">참고 링크</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[협업하기 전 내가 읽었더라면 좋았을 책 - 함께 자라기 (김창준)]]></title>
            <link>https://velog.io/@xiu_8/%ED%98%91%EC%97%85%ED%95%98%EA%B8%B0-%EC%A0%84-%EB%82%B4%EA%B0%80-%EC%9D%BD%EC%97%88%EB%8D%94%EB%9D%BC%EB%A9%B4-%EC%A2%8B%EC%95%98%EC%9D%84-%EC%B1%85-%ED%95%A8%EA%BB%98-%EC%9E%90%EB%9D%BC%EA%B8%B0-%EA%B9%80%EC%B0%BD%EC%A4%80</link>
            <guid>https://velog.io/@xiu_8/%ED%98%91%EC%97%85%ED%95%98%EA%B8%B0-%EC%A0%84-%EB%82%B4%EA%B0%80-%EC%9D%BD%EC%97%88%EB%8D%94%EB%9D%BC%EB%A9%B4-%EC%A2%8B%EC%95%98%EC%9D%84-%EC%B1%85-%ED%95%A8%EA%BB%98-%EC%9E%90%EB%9D%BC%EA%B8%B0-%EA%B9%80%EC%B0%BD%EC%A4%80</guid>
            <pubDate>Sun, 24 Dec 2023 09:15:45 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>간단 독서 후기</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/xiu_8/post/87f829d4-ecea-4e25-a128-0019003a6d90/image.jpeg" alt=""></p>
<blockquote>
<p>함께 자라기, 애자일로 가는 길
저자 : 김창준
출판 : 인사이트 </p>
</blockquote>
<h1 id="책소개">책소개</h1>
<p>부트캠프 수료식날 코치님께 개발자라면 꼭 읽어보고 가졌으면 좋을 거 같은 태도가 담긴 책이라며 받은 책</p>
<ul>
<li>기술 관련 이야기보다는 개발자 뿐만 아니라 개인이 자기계발을 위해 가져야할 학습의 태도와 더 좋은 협업의 자세에 대한 수필.</li>
</ul>
<h1 id="책을-읽고">책을 읽고</h1>
<p> 협업하기 전에 이 책을 읽었더라면 더 좋았을 거 같다는 생각이 들었다. 자기 계발이나 스터디, 고객 커뮤니케이션 등등 많은 주제가 몇장에 걸쳐 쓰여있지만 가장 와닿았던 파트는 협업에 관한 이야기였다. 아직 주니어도 아닌 베이비인 내가 겪고 고민해오던 부분이 협업이기에 더 재밌게 읽었던 거 같다.
 더 일찍이 읽었으면 이전에 협업하며 겪었던 매 상황에 더 잘 대응하거나 더 좋은 방안으로 이끌어 냈을 수 있겠다는 생각이 들었다.
 협업을 처음 할 때의 우리는 협업에 대해 제대로 배워본 적이 없기 때문에 직접 부딪히며 일어나는 갈등이나 소통 방식에 대해 직접 겪고 고민하며 함께하는 사람들과의 규칙을 만들어간다. 이 책에서는 배운 적 없는 협업인 만큼 코드의 추상화나 대화하는 프로그래밍에 대해 언급하며 협업 방식에 대해 더 수련하고 고민해야한다고 말한다. 
 적극적이어야만 협업이 잘되는 것이 아니다. 성향과 기질에 따른 애자일 방식을 소개하며 설득을 통해 협업을 잘 이끌어 낼 수 있다는 여러 대화문 예시를 통해 소통 접근법에 대해 보여준다.
 이 책은 부트캠프가 끝나고 수료식날 코치님께 받게된 책인데 그때 주변에 만나는 사람마다 이 책을 소개하고 꼭 읽어라고 강추한다고 하셨다ㅏ 뒤늦게 쓰게된 독후감(?)이지만 왜 그렇게 강추하셨는지 읽어보며 알게되었다. 이전에 협업하며 했던 고민들이나 혼자 학습이나 스터디 등등으로 했던 고민들을 직간접적으로 해결할 수 있도록 이끌어준 책인 거 같다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[url만 변경했더니 우리 교수님 연봉이 뜨더라니까요??]]></title>
            <link>https://velog.io/@xiu_8/%EB%B0%B1%EC%97%94%EB%93%9C-%EB%B3%B4%EC%95%88%EC%9D%84-%EA%B0%95%ED%99%94%ED%95%98%EC%9E%90-%ED%95%9C%EA%B5%AD%EB%B0%A9%EC%86%A1%ED%86%B5%EC%8B%A0%EB%8C%80-%EA%B0%9C%EC%9D%B8%EC%A0%95%EB%B3%B4-%EC%9C%A0%EC%B6%9C-%EC%82%AC%EB%A1%80%EC%99%80-%EC%95%88%EC%A0%84%ED%95%9C-JWT-%EB%B0%8F-Passport-%ED%99%9C%EC%9A%A9</link>
            <guid>https://velog.io/@xiu_8/%EB%B0%B1%EC%97%94%EB%93%9C-%EB%B3%B4%EC%95%88%EC%9D%84-%EA%B0%95%ED%99%94%ED%95%98%EC%9E%90-%ED%95%9C%EA%B5%AD%EB%B0%A9%EC%86%A1%ED%86%B5%EC%8B%A0%EB%8C%80-%EA%B0%9C%EC%9D%B8%EC%A0%95%EB%B3%B4-%EC%9C%A0%EC%B6%9C-%EC%82%AC%EB%A1%80%EC%99%80-%EC%95%88%EC%A0%84%ED%95%9C-JWT-%EB%B0%8F-Passport-%ED%99%9C%EC%9A%A9</guid>
            <pubDate>Sun, 17 Dec 2023 07:49:30 GMT</pubDate>
            <description><![CDATA[<h1 id="jwt-및-passport">JWT 및 Passport</h1>
<p><a href="https://news.sbs.co.kr/news/endPage.do?news_id=N1007450687&amp;plink=ORI&amp;cooper=NAVER">요번 방송통신대학교 이슈</a></p>
<h2 id="이게-무슨-일이래">이게 무슨 일이래</h2>
<p><img src="https://velog.velcdn.com/images/xiu_8/post/65923916-e0dc-4994-bffe-d99514dde337/image.png" alt=""></p>
<p>한국방송통신대학교의 개인정보 유출 사건은 웹 개발의 보안 측면에서 주목받고 있는 사례 중 하나이다. 이 사건은 지난 13년 동안 지원자들의 민감한 정보가 URL을 통해 쉽게 노출되어 있었다는 점에서 주요한 보안 이슈로 부상했다.</p>
<p>이러한 보안 이슈가 발생한 원인 중 하나는 URL에 접수번호가 그대로 노출되어 있어, 사용자가 이를 변경함으로써 다른 지원자의 정보에 접근할 수 있었다. 이는 개발자들이 URL을 통해 민감한 정보를 전송하거나 저장할 때 취해야 할 보안 조치가 부족했음을 시사이다.</p>
<p>이번 글에서는 해당 보안 이슈가 왜 발생했는지에 대한 근본적인 이유를 살펴보고, 베이비 백엔드 개발자들이 이러한 상황을 예방하고 안전한 애플리케이션을 개발하는 데 어떤 조치를 취할 수 있는지에 대해 알아보자.</p>
<hr>
<p><strong>1. URL 보안 강화하기:</strong>
기사에서 언급된 것처럼 URL을 통해 다른 사용자의 정보에 쉽게 접근할 수 있는 취약점을 보완하기 위해 URL에 민감한 정보를 노출하지 않도록 주의해야 한다. JWT와 Passport를 통한 안전한 사용자 인증 시스템을 구현해보자.</p>
<hr>
<p><strong>2. JWT(JSON Web Token) 소개:</strong>
JWT를 활용하여 효과적이고 안전한 사용자 인증을 구현하는 방법에 대해 알아보자.</p>
<pre><code class="language-javascript">const jwt = require(&#39;jsonwebtoken&#39;);

const secretKey = &#39;yourSecretKey&#39;;

const user = { id: 123, username: &#39;example&#39; };

const token = jwt.sign(user, secretKey);</code></pre>
<hr>
<p><strong>3. Passport와의 통합:</strong>
Passport는 다양한 전략을 제공하며, 그 중에서도 JWT를 사용한 인증을 적용하는 방법에 대해 살펴보자.</p>
<pre><code class="language-javascript">const passport = require(&#39;passport&#39;);
const JwtStrategy = require(&#39;passport-jwt&#39;).Strategy;
const ExtractJwt = require(&#39;passport-jwt&#39;).ExtractJwt;

const opts = {
  jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(),
  secretOrKey: &#39;yourSecretKey&#39;,
};

passport.use(new JwtStrategy(opts, (jwt_payload, done) =&gt; {
  // 사용자 확인 및 처리 로직
}));</code></pre>
<hr>
<p><strong>4. Express 애플리케이션에 적용하기:</strong>
Express 애플리케이션에 Passport 및 JWT를 통합하여 안전한 사용자 인증을 구현하는 방법에 대해 알아보자.</p>
<pre><code class="language-javascript">const express = require(&#39;express&#39;);
const passport = require(&#39;passport&#39;);

const app = express();

// Passport 초기화
app.use(passport.initialize());

// Passport JWT 미들웨어 적용
app.get(&#39;/protected-route&#39;, passport.authenticate(&#39;jwt&#39;, { session: false }), (req, res) =&gt; {
  res.json({ message: &#39;You accessed a protected route!&#39; });
});</code></pre>
<hr>
<p><strong>5. 기타 보안 강화 방법:</strong>
이외에도 HTTPS 사용, 토큰 유효 기간 설정 등을 통해 웹 애플리케이션의 보안을 강화하는 방법에 대해 간략히 다룬다.</p>
<h3 id="마무리">마무리</h3>
<p>부트캠프에서 코치님들을 통해 이런 경우를 들어오곤 했지만 이번 사례는 정말 개발자가 시스템 자체를 관리를 안했구나 싶은 수준이지만 댓글을 보면서 너무 당연한게 없는 곳이 있구나하는 생각이 들었다.</p>
<hr>
<p><strong>참고 자료 및 레퍼런스:</strong></p>
<ul>
<li><a href="https://jwt.io/introduction/">JWT 공식 문서</a></li>
<li><a href="http://www.passportjs.org/">Passport.js Documentation</a></li>
<li><a href="https://www.npmjs.com/package/jsonwebtoken">jsonwebtoken Documentation</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[면접을 준비할때 생각하기 : 혼자 주저리 쓰는 글 + 면접 답변]]></title>
            <link>https://velog.io/@xiu_8/%EB%A9%B4%EC%A0%91%EC%9D%84-%EC%A4%80%EB%B9%84%ED%95%A0%EB%95%8C-%EC%83%9D%EA%B0%81%ED%95%98%EA%B8%B0-%ED%98%BC%EC%9E%90-%EC%A3%BC%EC%A0%80%EB%A6%AC-%EC%93%B0%EB%8A%94-%EA%B8%80-%EB%A9%B4%EC%A0%91-%EB%8B%B5%EB%B3%80</link>
            <guid>https://velog.io/@xiu_8/%EB%A9%B4%EC%A0%91%EC%9D%84-%EC%A4%80%EB%B9%84%ED%95%A0%EB%95%8C-%EC%83%9D%EA%B0%81%ED%95%98%EA%B8%B0-%ED%98%BC%EC%9E%90-%EC%A3%BC%EC%A0%80%EB%A6%AC-%EC%93%B0%EB%8A%94-%EA%B8%80-%EB%A9%B4%EC%A0%91-%EB%8B%B5%EB%B3%80</guid>
            <pubDate>Sun, 10 Dec 2023 13:14:19 GMT</pubDate>
            <description><![CDATA[<h1 id="모의-면접-후기">모의 면접 후기</h1>
<p>이번 엘리스 모의면접 특강에 면접자로 참여하면서 느낀점은 최대한 많이 이야기하면 좋지만, 제대로 말하지 못하면 차라리 제대로 말할 만큼만 외우고 꼬리질문을 하게 만드는 것이 조금 더 떨지않고 말하는데에 도움이 된다는 것이었다. 단순 CS관련 질문이 아니더라도 내가 개발공부를 하면서 겪은 일들은 꾸준히 기록 해두는 것도 면접때 이야기거리가 될 수 있다는 생각에 포스팅을 더 꾸준히 해야겠다는 생각이 들었다.</p>
<h1 id="면접-준비-내용">면접 준비 내용</h1>
<h2 id="1-session-기반-인증과-token-기반-인증의-차이는-무엇인가요">1. session 기반 인증과 token 기반 인증의 차이는 무엇인가요?</h2>
<ul>
<li><p>wiki 및 참고 링크</p>
<p>  <a href="https://hudi.blog/session-based-auth-vs-token-based-auth/">https://hudi.blog/session-based-auth-vs-token-based-auth/</a></p>
<p>  <a href="https://giron.tistory.com/137#:~:text=%EC%A3%BC%EC%9A%94%20%EC%B0%A8%EC%9D%B4%EC%A0%90%EC%9D%80%20%EC%84%B8%EC%85%98%20%EA%B8%B0%EB%B0%98,%EB%B0%A9%EB%B2%95%EC%9D%84%20%EA%B2%B0%EC%A0%95%ED%95%B4%EC%95%BC%20%ED%95%9C%EB%8B%A4">https://giron.tistory.com/137#:~:text=주요 차이점은 세션 기반,방법을 결정해야 한다</a>.</p>
</li>
<li><p>내 답안</p>
</li>
<li><p><em>요점*</em> :세션 기반 인증은 서버가 세부 사항을 저장하고 토큰 기반은 클라이언트가 토큰을 가지고 있는 형태입니다. 세션 방식은 쿠키를 날린다거나 세션 유효기간이 만료되면 재인증해야 하는 번거로움이 있지만 토큰 같은 경우는 탈취를 당하면 강제로 로그아웃 시키거나 만료시키는 방법이 없기 때문에 중복 로그인 관리가 민감한 금융앱, 구독 앱, 모바일 PC체크 같은 경우 세션을 사용해 주로 관리합니다.</p>
</li>
</ul>
<hr>
<p>주요 차이점은 세션 기반 인증은 서버가 세부 사항을 저장하고 토큰 기반은 클라이언트가 토큰을 가지고 있는 형태입니다. 토큰은 대역폭이 크기 때문에 저장해서 사용하는 것보단 대역폭이 작은 세션을 사용하는 편이 좋습니다. </p>
<p>세션 방식은 쿠키를 날린다거나 세션 유효기간이 만료되면 재인증해야 하는 번거로움이 있습니다. 이런 번거로움이 나쁜 것은 아니고 유저의 사용 환경상 웹은 어디서건 접속할 수 있고 본인만 사용하는 PC라는 것을 확인할 수 없기 때문에 적절한 시점에서 로그아웃을 해주는 보안상 안전을 위해 주로 사용됩니다.</p>
<p>앱 사용환경에서는 스마트폰은 자신의 것이라는 컨센서스가 있기 때문에 앱, 서버간 인증에서 매번 로그아웃을 하는 것은 보안 수준이 높아야하는 금융앱 같은 경우를 제외하고 유저에게 번거로운 방식일 수 있습니다.</p>
<p>토큰같은 경우는 탈취를 당하면 강제로 로그아웃 시키거나 만료시키는 방법이 없기 때문에 중복로그인 관리가 민감한 경우 (금융앱, 구독 앱, 모바일 PC체크)에는 세션을 사용해 관리하는게 좋습니다. 하지만 자주 ip가 바뀌는 회사에서 사용하는 서비스일 경우 세션 방식이 중복 로그인을 관리하기는 쉽지 않은 걸로 알고 있습니다.</p>
<h3 id="💡출제-의도">💡출제 의도</h3>
<ul>
<li>두 인증 방법의 차이를 얼마나 알고 있는지</li>
<li>어떠한 경우에 해당 인증 방법을 사용하는지를 알고 있는지</li>
<li>각 인증 방법의 장단점을 알고 있는지</li>
</ul>
<h2 id="2-js진영에서는-callback-hell-문제가-종종-발생합니다-이-문제를-해결하는-방법을-아시는-데로-말씀해주세요">2. JS진영에서는 callback hell 문제가 종종 발생합니다. 이 문제를 해결하는 방법을 아시는 데로 말씀해주세요.</h2>
<ul>
<li><p>wiki 및 참고 링크</p>
<p>  <a href="https://springfall.cc/article/2022-11/easy-promise-async-await">https://springfall.cc/article/2022-11/easy-promise-async-await</a></p>
<p>  <a href="https://ko.javascript.info/async-await">https://ko.javascript.info/async-await</a></p>
<p>  <a href="https://ryurim.tistory.com/137#:~:text=%EC%BD%9C%EB%B0%B1%20%EC%A7%80%EC%98%A5%EC%9D%80%20%EB%B9%84%EB%8F%99%EA%B8%B0%20%EC%B2%98%EB%A6%AC,%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94%20%EB%B0%A9%EB%B2%95%EC%9D%B4%20%EC%9E%88%EC%8A%B5%EB%8B%88%EB%8B%A4">https://ryurim.tistory.com/137#:~:text=콜백 지옥은 비동기 처리,사용하는 방법이 있습니다</a>.</p>
<p>  <a href="https://velog.io/@yangareum1818/JS-%EB%B9%84%EB%8F%99%EA%B8%B0-%EC%B2%98%EB%A6%AC-%EB%AA%A8%EB%93%A0-%EA%B2%83-%EC%BD%9C%EB%B0%B1%EC%A7%80%EC%98%A5%EC%9D%84-%ED%95%B4%EA%B2%B0%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95">https://velog.io/@yangareum1818/JS-비동기-처리-모든-것-콜백지옥을-해결하는-방법</a></p>
</li>
<li><p>내 답안 : </p>
<p>  callback hell은 비동기 작업의 흐름을 제어하지 못하기 때문에 콜백함수를 이용해 코드가 깊어지는 경우  비동기 작업을 효율적으로 해결하기 위한 방안으로 Promise와 async/await을 사용할 수 있습니다.
  Promise는 비동기 작업의 단위로 <code>new Promise(...)</code> 를 하는 순간 할당된 비동기 작업이 바로 시작됩니다. 비동기 작업의 특징은 언제 끝날지 모르기 때문에 일단 뒤에 함수들을 실행하는데, 비동기 함수의 성공 유무를 따라 작업결과를 뒷처리 함으로 callback hell에 대한 문제를 해결할 수 있습니다.</p>
</li>
</ul>
<h2 id="2-rest-api-설계시-고려해야하는-http메서드-get과-post의-차이는-무엇인가요">2. Rest API 설계시 고려해야하는 HTTP메서드 GET과 POST의 차이는 무엇인가요?</h2>
<ul>
<li>GET은 단순 정보를 요청하는 메서드고 POST는 정보를 제출하는 메서드란 점이 다릅니다. 조회나 검색과 같이 멱등성이 중요한 API인 경우는 GET을 사용하고, 리소스 변경이 필요한 경우는 POST를 주로 사용하지만, GET은 요청시 url에 노출이 되어 보안에는 취약하므로 보안에 예민한 정보 같은 경우는 POST를 주로 이용합니다. 또한 큰 데이터를 전송해야 할 경우 데이터의 길이제한이 없는 POST를 사용하는 것이 적절합니다.</li>
</ul>
<h3 id="💡출제-의도-1">💡출제 의도</h3>
<ul>
<li>callback hell에 대해서 알고 있는지</li>
<li>promise와 async/await의 필요성에 대해서 인지하고 있는지</li>
</ul>
<h2 id="3-멱등성이란-무엇이며-rest-api-http-method의-4가지-중-멱등성을-보장하는-method는-무엇인지-이유와-함께-설명해보세요">3. 멱등성이란 무엇이며, REST API HTTP method의 4가지 중 멱등성을 보장하는 method는 무엇인지 이유와 함께 설명해보세요.</h2>
<ul>
<li><p>알아야 할 wiki 및 참고 링크</p>
<ul>
<li>멱등법칙(冪等法則) 또는 멱등성(冪等性, 영어: idempotent)은 수학이나 전산학에서 연산의 한 성질을 나타내는 것으로, <strong>연산을 여러 번 적용하더라도 결과가 달라지지 않는 성질</strong>을 의미한다.</li>
<li><a href="https://june0122.github.io/2021/08/05/term-idempotent/">https://june0122.github.io/2021/08/05/term-idempotent/</a></li>
<li><a href="https://tecoble.techcourse.co.kr/post/2020-08-17-put-vs-patch/">https://tecoble.techcourse.co.kr/post/2020-08-17-put-vs-patch/</a></li>
</ul>
</li>
<li><p>내 답안 : </p>
<p>  멱등성은 동일한 요청을 한 번 보내는 것과 여러 번 연속으로 보내는 것이 같은 효과를 지니고 서버의 상태에서도 동일하게 남을 때, 해당 HTTP 메서드가 멱등성을 가졌다고 합니다. REST API method의 POST를 제외하고 GET, PUT, DELETE가 멱등성을 가집니다. 멱등성이 필요한 이유는 금융 관련 자동이체와 같은 결제 서비스를 이용할 때 중복 이체나 결제를 방지할 수 있기 때문에 안정적인 서비스 제공에 중요한 역할을 합니다.</p>
<hr>
<p>  POST는 새로운 데이터를 제출하므로 서버에 새로운 데이터(새로운 primary ID)가 추가된다고 볼 수 있으므로 멱등성이라 볼 수 없다.</p>
<p>  GET은 단순 조회 메서드 이므로 서버의 상태에 영향을 주지 않는다.</p>
<p>  PUT은 같은 primary ID에 같은 요청을 보냄으로 서버의 상태가 동일하게 남는다.</p>
<p>  DELETE는 한번 삭제후 같은 데이터를 재삭제 할 경우 응답은 404를 받게 되지만 멱등성은 서버 응답 기준이 아니라 상태를 기준으로 하기 때문에 멱등성을 가졌다고 볼 수 있다.</p>
</li>
</ul>
<h3 id="💡출제의도">💡출제의도</h3>
<ul>
<li>REST API에 대해 어느 정도 수준으로 알고 있는가</li>
<li>HTTP method들에 대해서 알고 있는가</li>
<li>멱등성이란 개념이 어떠한 상황에서 필요한지 알고 있는가</li>
</ul>
<h2 id="4-프로젝트-기간-중-직면했던-도전-과제와-그-과제를-어떻게-극복하셨는지-말씀-해주실-수-있으실까요">4. 프로젝트 기간 중 직면했던 도전 과제와 그 과제를 어떻게 극복하셨는지 말씀 해주실 수 있으실까요?</h2>
<ul>
<li><p>내 답안 : </p>
<p>  프로젝트 시 npm 에 올라와있는 passport-kakao 모듈을 이용하여 소셜 로그인을 구현하려 한 적이 있습니다. 해당 라이브러리로 카카오 API의 url scope를 이용해 email을 필수 동의 항목으로 받아오려하였지만 해당 라이브러리를 수정해서 적용하기 쉽지않아 프로젝트 내에서 kakao-passport를 직접 만들어 구현하였습니다. 하지만 생각과는 달리 email은 보안에 중요한 항목이라 kakao API 내에서 제한을 두고 있었고, 소셜 로그인 유저일 경우 email을 따로 입력할 수 있도록 로직을 변경하였습니다. 결론적으로 처음 생각했던 방법과는 다르게 회원 로그인 기능을 완료하였지만 kakao-passport 로직을 직접 구현해보면서 나에게 필요한 외부 라이브러리를  찾아 잘 활용하는 것도 중요하지만 나에게 맞지않는 부분이 있을 때 안되는 부분을 찾아 해당 라이브러리에 이슈를 올리거나 나에게 필요한 부분을 직접 구현하는 것에 자신감이 생긴 거 같습니다.</p>
</li>
</ul>
<h3 id="💡출제-의도-2">💡출제 의도</h3>
<ul>
<li>문제 해결, 트러블 슈팅, 성능 개선 등 경험에 대한 문제</li>
<li>위기 대처 능력이 있는지(위기를 회피하는 사람은 아닌지).</li>
<li>프로젝트를 경험하면서 겪었던 문제들을 어떻게 해결했는지.</li>
<li>현업에서 일할 때 어떠한 일을 맡겨도 해결해낼 사람인지(이를 통해 성장할 수 있는 사람인지)를 가늠하는 단골 문제.</li>
</ul>
<h2 id="5-n1-문제란-무엇이며-이를-해결하기-위한-방법은-무엇인가요">5. N+1 문제란 무엇이며 이를 해결하기 위한 방법은 무엇인가요?</h2>
<ul>
<li><p>wiki 및 참고링크</p>
<p>  <a href="https://incheol-jung.gitbook.io/docs/q-and-a/spring/n+1">https://incheol-jung.gitbook.io/docs/q-and-a/spring/n+1</a></p>
<p>  <a href="https://programmer93.tistory.com/83#:~:text=N%2B1%20%EB%AC%B8%EC%A0%9C%EB%A5%BC%20%ED%95%B4%EA%B2%B0,%EB%93%B1%EC%9D%98%20%EB%B0%A9%EB%B2%95%EC%9D%B4%20%EC%9E%88%EB%8B%A4.&amp;text=JPQL%EC%9D%84%20%EC%82%AC%EC%9A%A9%ED%95%98%EC%97%AC%20DB,%EB%AC%B8%EC%9D%84%20%EC%83%9D%EA%B0%81%ED%95%98%EB%A9%B4%20%EB%90%9C%EB%8B%A4.%20">https://programmer93.tistory.com/83#:~:text=N%2B1 문제를 해결,등의 방법이 있다.&amp;text=JPQL을 사용하여 DB,문을 생각하면 된다.</a> )</p>
<p>  <a href="https://velog.io/@jinyoungchoi95/JPA-%EB%AA%A8%EB%93%A0-N1-%EB%B0%9C%EC%83%9D-%EC%BC%80%EC%9D%B4%EC%8A%A4%EA%B3%BC-%ED%95%B4%EA%B2%B0%EC%B1%85#n1%EC%9D%B4-%EA%B7%BC%EB%8D%B0-%EB%AD%90%EC%A3%A0">https://velog.io/@jinyoungchoi95/JPA-모든-N1-발생-케이스과-해결책#n1이-근데-뭐죠</a></p>
<p>  <a href="https://well-balanced.medium.com/graphql%EC%97%90%EC%84%9C-n-1-%EC%BF%BC%EB%A6%AC-%EC%A0%90%EC%A7%84%EC%A0%81%EC%9C%BC%EB%A1%9C-%EA%B0%9C%EC%84%A0%ED%95%98%EA%B8%B0-d758e925cc19">https://well-balanced.medium.com/graphql에서-n-1-쿼리-점진적으로-개선하기-d758e925cc19</a></p>
<p>  <a href="https://jojoldu.tistory.com/457">https://jojoldu.tistory.com/457</a></p>
</li>
<li><p>내 답안 : </p>
<p>  N+1 쿼리 문제는 <strong>연관 관계에서 발생하는 이슈로 엔티티를 조회</strong>했을 때 조회된 데이터 개수(n)만큼 연관 관계의 조회 쿼리가 추가적으로 따라오는 현상으로 알고 있습니다. 지연 로딩의 경우 fetch join을 이용하면 쉽게 해결할 수 있지만 <strong>페이지네이션이나 2개 이상의 collection join</strong>에서 MultipleBagFetchException 예외 문제가 발생합니다.  모든 케이스들을 정확히 이해하고 있지는 않지만 DB쿼리 외에 GraphQL 등 에서 발생하는 N+1 문제를 이벤트 루프의 원리를 이용해 해결해주는 dataloader 라이브러리를 사용하여 해결할 수 있는 방안이 있다는 개념정도만 알고 있습니다.</p>
</li>
</ul>
<h3 id="💡출제-의도-3">💡출제 의도</h3>
<ul>
<li>웹 서비스 개발에서 자주 직면할 수 있는 DB 쿼리 문제인 본 문제에 대해 인지하고 있는가(DB에 대한 이해도 가늠)</li>
<li>DB 쿼리/업데이트 최적화는 고려하지 않고 어플리케이션 코드만 생각하는 사람인가를 체크하기 위함</li>
<li>N+1문제가 DB 쿼리 외의 기타 네트워크 요청에서도 발생할 수 있음을 알고 있는가(예: GraphQL, RESTful API 등)</li>
<li>네트워크 요청 자체가 전체적인 서비스에 얼마나 영향을 끼치는지 인지하고 있는가</li>
</ul>
<h2 id="6-wwwgooglecom을-브라우저에-입력했을-때-어떠한-일들이-일어나나요">6. <a href="http://www.google.com%EC%9D%84">www.google.com을</a> 브라우저에 입력했을 때 어떠한 일들이 일어나나요?</h2>
<p><img src="https://prod-files-secure.s3.us-west-2.amazonaws.com/9cf0bfbc-0cd5-4a8c-91bd-12d5ca133160/79017d7c-9e46-41c5-bfcc-54b5c922329d/Untitled.png" alt="Untitled"></p>
<ul>
<li><p>wiki 및 참고링크</p>
<p>  <a href="https://velog.io/@tnehd1998/%EC%A3%BC%EC%86%8C%EC%B0%BD%EC%97%90-www.google.com%EC%9D%84-%EC%9E%85%EB%A0%A5%ED%96%88%EC%9D%84-%EB%95%8C-%EC%9D%BC%EC%96%B4%EB%82%98%EB%8A%94-%EA%B3%BC%EC%A0%95#:~:text=1.%20www.google.com,%EC%99%80%20%ED%95%A8%EA%BB%98%20%EC%A0%84%EB%8B%AC%EC%9D%84%20%ED%95%A9%EB%8B%88%EB%8B%A4">https://velog.io/@tnehd1998/주소창에-www.google.com을-입력했을-때-일어나는-과정#:~:text=1. www.google.com,와 함께 전달을 합니다</a>.</p>
<p>  <a href="https://velog.io/@eassy/www.google.com%EC%9D%84-%EC%A3%BC%EC%86%8C%EC%B0%BD%EC%97%90%EC%84%9C-%EC%9E%85%EB%A0%A5%ED%95%98%EB%A9%B4-%EC%9D%BC%EC%96%B4%EB%82%98%EB%8A%94-%EC%9D%BC">https://velog.io/@eassy/www.google.com을-주소창에서-입력하면-일어나는-일</a></p>
</li>
<li><p>내 답안 :</p>
<p>  <strong>요약</strong> : DNS서버에 IP주소를 조회 → 해당 IP주소를 web server에 요청 → 해당 html 문서에 맞는 웹 페이지 작업 및 db 작업을 web server가 was에게 요청함. //TCP</p>
<p>  입력한 URL 주소 중, 도메인 이름에 해당하는 google.com을 DNS에 검색합니다.</p>
<p>  가장 가까운 DNS 서버에서 해당 도메인 이름에 해당하는 IP주소를 찾아 사용자가 입력한 URL 정보와 함께 전달합니다.</p>
<p>  전달 받은 IP 주소를 이용하여 웹 브라운저는 웹 서버에게 해당 사이트에 맞는 html 문서를 요청합니다.</p>
<p>  WAS와 데이터베이스에서 웹페이지 작업을 처리합니다. WAS에서의 작업 처리 결과들을 웹 서버로 전송하고, 웹 서버는 웹 브라우저에게 html 문서 결과를 전달합니다.</p>
<p>  Critical Rendering Path를 통해 웹 브라우저 화면에 웹 페이지 내용을 출력합니다.</p>
<p>  DOM 트리 , CSSOM 트리를 빌드합니다.</p>
<p>  Render Tree가 생성되고 Render Tree의 노드들에 대한 위치와 크기를 계산하는 단계로 Layout -&gt; 특정 액션과 이벤트에 따라 Reflow &amp; Repaint가 수행됩니다.</p>
<p>  레이아웃과 페인트를 수행하지않고 레이어의 합성만 실행시키는 단계로 Composition이 일어나고나면 <a href="http://www.google.com%EC%97%90">www.google.com에</a> 맞는 화면이 웹 브라우저에 출력됩니다.</p>
</li>
</ul>
<h3 id="💡출제-의도-4">💡출제 의도</h3>
<ul>
<li>브라우저-서버 간의 통신에 대해 얼마나 알고 있는지에 대한 열린 질문</li>
<li>네트워크에 대해 얼마나 알고 있는지 가늠이 가능한 문제이기도 하다.</li>
</ul>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[뻔한 REST API 정리]]></title>
            <link>https://velog.io/@xiu_8/%EB%BB%94%ED%95%9C-REST-API-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@xiu_8/%EB%BB%94%ED%95%9C-REST-API-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Tue, 28 Nov 2023 15:54:29 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/xiu_8/post/044886eb-8972-42a7-a5d5-94d0c5215135/image.png" alt=""></p>
<blockquote>
<p>API는 메뉴판이라고 생각하고 설계하자.</p>
</blockquote>
<h2 id="명확하고-일관된-api-설계하기--rest-api">명확하고 일관된 API 설계하기 : REST API</h2>
<p>REST는 Representational State Transfer 의 약어로 하이퍼 미디어를 전송하는 규칙!</p>
<h3 id="rest의-6-원칙과-제약">REST의 6 원칙과 제약</h3>
<p><a href="https://medium.com/tech-pentasecurity/restful-api-%EB%84%A4%EC%9D%B4%EB%B0%8D-7c81bdb9da63">조금 더 자세한 설명은 여기에</a></p>
<ol>
<li>uniform interface 일관성</li>
<li>client-server 구분</li>
<li>Stateless : 작업에 대한 요청의 상태 정보를 저장하거나 관리 하지 않는다. 요청끼리 서로 의존성이 있으면 안된다.</li>
<li>Cacheable  : 요청은 캐싱이 가능해야한다.</li>
<li>Layered System : 요청 하나는 최종 응답 전에 각 계층의 정보를 얻을 수 없도록 분리되어 계층화돼야된다.</li>
<li>Code on Demand : 서버는 유저에게 실행 가능한 코드를 보내줄 수 있다.</li>
</ol>
<h2 id="네이밍">네이밍</h2>
<p>엔드포인트일 경우 주로 동사형태로 네이밍을 하지만 restful URI(uniform resource identifier)의 경우 문서, 컬렉션, 스토어, 컨트롤 4가지 범주로 자원을 분류하여 어떤 범주에 속하는지에 따라 명사로 네이밍을 한다. </p>
<h3 id="그-외-추가">그 외 추가</h3>
<ul>
<li>URI 마지막에 <code>/</code>를 사용하지 않는다.</li>
<li><code>_</code>언더스코어 대신 <code>-</code> 하이픈을 사용해 가독성을 높인다.</li>
<li>소문자를 사용한다.</li>
<li>파일의 확장자는 사용하지 않는다.</li>
<li>CRUD 메서드를 사용하지 않는다.</li>
<li>자원의 필터링은 쿼리 파라미터를 사용한다.</li>
<li>한 API에서 하나의 정보만 요청하도록 한다.</li>
</ul>
<h2 id="api-종류">API 종류</h2>
<ul>
<li>public API </li>
<li>private API</li>
<li>Partner API</li>
</ul>
<blockquote>
<p>모든 프로그램은 API를 가질 수 있다.</p>
</blockquote>
<ul>
<li>Windows API : 윈도우 운영체제 기능들을 사용가능</li>
<li>Database 관리 프로그램 API : DB 입출력 기능들 사용가능</li>
<li>어떤 프로그램 API : 프로그램이 존재한다면 API도 존재. 어떤 프로그램(chatGPT, 파파고 등등)의 기능들을 사용 가능</li>
</ul>
<h2 id="api-판매하는-플랫폼">API 판매하는 플랫폼</h2>
<ul>
<li>네이버 클라우드와 같은 사이트에서 다양한 API를 무료 또는 구매하여 사용 할 수 있다.</li>
<li>APT 마켓 플레이스 &quot;<a href="https://rapidapi.com/rakuten_webservice/api/rakuten-marketplace-product-search">사이트 바로가기</a>&quot;와 같은 곳에서 내가 잘 만든 API를 판매할 수 있다.</li>
</ul>
<blockquote>
<p>API 만들어서 팔아보쟈구</p>
</blockquote>
<h2 id="참고글">참고글</h2>
<ul>
<li><a href="https://restfulapi.net/resource-naming/">https://restfulapi.net/resource-naming/</a></li>
<li><a href="https://medium.com/tech-pentasecurity/restful-api-%EB%84%A4%EC%9D%B4%EB%B0%8D-7c81bdb9da63">https://medium.com/tech-pentasecurity/restful-api-%EB%84%A4%EC%9D%B4%EB%B0%8D-7c81bdb9da63</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[HTTP Method 속성과 설계시 고려해야할 점]]></title>
            <link>https://velog.io/@xiu_8/HTTP-Method-%EC%86%8D%EC%84%B1%EA%B3%BC-%EC%84%A4%EA%B3%84%EC%8B%9C-%EA%B3%A0%EB%A0%A4%ED%95%B4%EC%95%BC%ED%95%A0-%EC%A0%90</link>
            <guid>https://velog.io/@xiu_8/HTTP-Method-%EC%86%8D%EC%84%B1%EA%B3%BC-%EC%84%A4%EA%B3%84%EC%8B%9C-%EA%B3%A0%EB%A0%A4%ED%95%B4%EC%95%BC%ED%95%A0-%EC%A0%90</guid>
            <pubDate>Tue, 28 Nov 2023 15:06:31 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>요점 정리 : 금융 관련 결제 같은 요청들은 멱등성이 보장되는 메서드들 꼭꼭 사용하기</p>
</blockquote>
<h1 id="순서">순서</h1>
<ul>
<li>멱등성이란?</li>
<li>멱등성이 필요한 이유</li>
<li>HTTP Method의 멱등성</li>
<li>설계시 고려해야할 점</li>
<li>참고사이트</li>
</ul>
<h2 id="멱등성이란">멱등성이란?</h2>
<p>HTTP 메소드의 속성 중에 하나인 멱등성은 여러 번 동일한 요청을 보냈을 때, 서버에 미치는 의도된 영향이 동일할 경우를 말한다. 예를 들어 Safe 요청인 GET, HEAD등과 함께 PUT, DELETE를 멱등한 HTTP 메소드라고 정의한다. DELETE는 요청 한번 보냈을 때 <code>DELETE -&gt; 200 OK</code> 응답 값이 오고 동일한 요청을 보낼 경우 에러 <code>DELETE-&gt; 404 NOT FOUND</code> 를 받지만 멱등성의 기준은 요청 응답 기준이 아닌 서버 기준임을 명시하자. PATCH 또한 리소스를 수정할 경우 기존 리소스에 응답을 추가하는 경우에도 사용될 수 있는데 이때, 호출 결과가 달라질 수 있으므로 멱등하다 할 수 없다.</p>
<h3 id="http-메소드-중-멱등한-메소드">HTTP 메소드 중 멱등한 메소드</h3>
<ul>
<li>GET, PUT, DELETE</li>
</ul>
<h2 id="http-메소드의-멱등성이-필요한-이유는-">HTTP 메소드의 멱등성이 필요한 이유는 ?</h2>
<h3 id="1-안전한-요청">1. 안전한 요청</h3>
<p>멱등한 메소드는 서버 상태를 변경하지 않고 리소스에 대한 정보를 요청하는 데 사용될 수 있다. 이는 해당 요청이 오류 또는 부작용을 발생시키지 않고 여러 번 호출될 수 있음을 의미한다. 예를 들어, HTTP의 GET 메소드는 멱등성을 가지고 있다.</p>
<h3 id="2-캐싱">2. 캐싱</h3>
<p>멱등한 메소드를 사용하면 캐싱이 더욱 효과적으로 이루어질 수 있다. 동일한 요청에 대한 응답은 항상 동일하므로 캐시된 응답을 재사용할 수 있다.</p>
<h3 id="3-병행-처리와-복구">3. 병행 처리와 복구</h3>
<p>멱등한 메소드는 여러 클라이언트에서 동시에 호출되더라도 예상된 결과를 얻을 수 있습니다. 이는 분산 환경에서 병행 처리를 쉽게 만들어주며, 시스템이 실패하거나 중단되더라도 안전하게 복구할 수 있도록 한다.</p>
<h3 id="4-사용자-경험-향상">4. 사용자 경험 향상</h3>
<p>멱등한 메소드를 사용하면 사용자 경험이 향상될 수 있다. 사용자가 &quot;새로 고침&quot; 버튼을 누르거나 다시 시도 버튼을 클릭하여 동일한 요청을 여러 번 시도해도 예상된 동일한 결과를 받을 수 있다.</p>
<h3 id="5-네트워크-문제-대응">5. 네트워크 문제 대응</h3>
<p>멱등한 메소드를 사용하면 네트워크 문제로 인해 요청이 중단되었을 때 다시 시도하는 것이 더 쉽다. 동일한 요청을 여러 번 시도해도 동일한 결과를 얻을 수 있기 때문이다.</p>
<h2 id="멱등성이-필요한-예시">멱등성이 필요한 예시</h2>
<h3 id="결제-시스템">결제 시스템</h3>
<p>결제 시스템에서 멱등성은 중요한 개념이다. 결제는 금전적인 거래이기 때문에 중복 결제나 잘못된 금액의 결제 등을 방지하기 위해 멱등성이 필요하다. </p>
<ol>
<li>중복 결제 방지</li>
</ol>
<ul>
<li>사용자가 결제 버튼을 눌렀을 때, 네트워크 문제 또는 다양한 이유로 인해 응답이 늦게 도착하거나 사용자 측에서 재시도를 했을 경우 중복 결제가 발생할 수 있다. 멱등성이 없는 경우에는 동일한 결제 요청이 여러 번 발생하면 여러 번의 결제가 이루어질 수 있다. 멱등성이 있는 결제 시스템에서는 동일한 결제 요청이 여러 번 수행되어도 결제가 한 번만 이루어진다.</li>
</ul>
<ol start="2">
<li>오류 복구</li>
</ol>
<ul>
<li>결제 시스템에서 오류가 발생했을 때, 사용자나 시스템이 다시 시도를 할 수 있다. 이때 멱등성이 있는 결제 시스템에서는 동일한 결제 요청을 여러 번 시도해도 동일한 결과를 얻을 수 있다. </li>
</ul>
<ol start="3">
<li>시스템 간 통신 문제 대응</li>
</ol>
<ul>
<li>결제 요청은 여러 시스템 간의 통신을 포함할 수 있다. 이때 통신 문제로 인해 요청이 중단되거나 응답이 손실될 수 있다. 멱등성이 있는 결제 시스템에서는 시스템 간 통신 문제로 인한 중복 결제를 방지할 수 있다.</li>
</ul>
<pre><code>#결제 요청 예시

http
Copy code
POST /payments
Content-Type: application/json

{
  &quot;amount&quot;: 50.00,
  &quot;card_number&quot;: &quot;1234-5678-9012-3456&quot;,
  &quot;expiry_date&quot;: &quot;12/24&quot;,
  &quot;cvv&quot;: &quot;123&quot;,
  &quot;order_id&quot;: &quot;abc123&quot;
}</code></pre><p>해당 결제 요청이 여러 번 수행되더라도 동일한 order_id에 대한 결제는 한 번만 이루어진다. 이는 멱등성을 통해 중복 결제를 방지하고 시스템의 안정성을 높이는 데 도움된다.</p>
<h3 id="추가적인-예시">추가적인 예시</h3>
<ul>
<li>자동 이체나 정기 결제 서비스 같이 사용자가 한번 등록한 이체나 결제 요청이 여러번 발생 할 수 있는데, 멱등성은 이러한 상황에서 중복 이체나 결제를 방지할 수 있게 안정적인 서비스 제공에 도움을 준다.</li>
<li>만약 매월 특정 날짜에 자동이체를 등록해둘 경우, 오류로 인해 여러번 요청이 되더라도 <code>transaction_id</code>에 대한 이체가 한 번만 이루어지게 해둘 수 있다.</li>
</ul>
<p>멱등성은 금융 거래와 같은 중요한 작업에서 특히 중요한 역할을 한다.</p>
<h2 id="get과-post의-차이와-설계시-고려할-점">GET과 POST의 차이와 설계시 고려할 점</h2>
<p>간단하게 차이점을 얘기하면 GET은 정보의 요청, POST는 정보의 제출로 볼 수 있다.</p>
<h3 id="get멱등성-o">GET(멱등성 O)</h3>
<ul>
<li>주로 쿼리스트링을 통해 데이터를 전송하며 url에 데이터가 노출이 됨으로 보안에 취약할 수 있으니 민감한 정보는 담지않는 것이 좋다. 또한 데이터의 길이 제한이 있다.</li>
<li>캐싱이 가능하고, 동일한 GET 요청에 대한 응답은 캐시에서 가져와 사용할 수 있다.<h3 id="post멱등성-x">POST(멱등성 X)</h3>
</li>
<li>주로 리소스를 생성하거나 업데이트할 때 사용된다. 요청은 바디에 데이터를 담아 전송한다. url에 데이터가 노출되지 않으므로 GET 보다는 보안에 우수하지만 특정 경우를 제외하고는 목적을 분명하게 사용하는 편이 좋다. 데이터의 길이 제한이 없다.</li>
<li>캐싱이 어렵기 때문에, 동일한 POST 요청의 응답은 캐시에서 가져오지 않는다.</li>
</ul>
<h3 id="설계시-고려할-점">설계시 고려할 점</h3>
<ol>
<li>보안</li>
</ol>
<ul>
<li>민감한 정보를 전송해야 하는 경우 POST를 사용하는 것이 좋다.</li>
</ul>
<ol start="2">
<li>데이터 길이</li>
</ol>
<ul>
<li>큰 데이터를 전송해야 할 경우 POST를 사용하는 것이 적절하다. GET은 URL 길이 제한이 있을 수 있다.</li>
</ul>
<ol start="3">
<li>멱등성</li>
</ol>
<ul>
<li>멱등성이 필요한 작업인지 고려하여 적절한 메소드를 선택한다.</li>
<li>조회나 검색과 같이 멱등성이 중요한 경우 GET을 사용하고, 리소스 변경이 필요한 경우에는 POST를 사용한다.</li>
<li>HTTP 메소드의 적절한 사용은 웹 애플리케이션의 안정성, 효율성, 보안성 등에 영향을 미치므로 주의 깊게 고려되어야 한다.</li>
</ul>
<ol start="4">
<li>캐싱</li>
</ol>
<ul>
<li>캐싱이 중요한 경우 GET을 사용하여 캐싱을 활용한다.</li>
</ul>
<ol start="5">
<li>RESTful 설계</li>
</ol>
<p>RESTful API를 설계할 때는 각 메소드의 의도에 맞게 사용해야 한다.
리소스의 조회는 GET, 생성은 POST와 같이 목적에 따라 메소드를 사용한다.</p>
<h2 id="참고-사이트">참고 사이트</h2>
<ul>
<li><a href="https://mangkyu.tistory.com/251">https://mangkyu.tistory.com/251</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[gitlab에서 github로 wiki까지 옮기는 법(feat. 잔디 심기까지!)]]></title>
            <link>https://velog.io/@xiu_8/gitlab%EC%97%90%EC%84%9C-github%EB%A1%9C-wiki%EA%B9%8C%EC%A7%80-%EC%98%AE%EA%B8%B0%EB%8A%94-%EB%B2%95feat.-%EC%9E%94%EB%94%94-%EC%8B%AC%EA%B8%B0%EA%B9%8C%EC%A7%80</link>
            <guid>https://velog.io/@xiu_8/gitlab%EC%97%90%EC%84%9C-github%EB%A1%9C-wiki%EA%B9%8C%EC%A7%80-%EC%98%AE%EA%B8%B0%EB%8A%94-%EB%B2%95feat.-%EC%9E%94%EB%94%94-%EC%8B%AC%EA%B8%B0%EA%B9%8C%EC%A7%80</guid>
            <pubDate>Tue, 28 Nov 2023 08:04:05 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>2024.09.09 기준
fatal: the remote end hung up unexpectedly 에러 발생 시 해결 방법 추가</p>
</blockquote>
<blockquote>
<p>옮길 repository는 github, 옮겨올 repository는 gitlab으로 명칭하였습니다.</p>
</blockquote>
<p>매번 옮겨올 때마다 찾아보기 귀찮아서 한번에 벨로그에 정리하였다.</p>
<h2 id="gitlab에서-github-개인-레포로-잔디-커밋-내역까지-가져오기">gitlab에서 github 개인 레포로 잔디, 커밋 내역까지 가져오기</h2>
<ul>
<li>먼저 깃허브에 저장소를 새로 만들어준 후 아래 명령어대로 입력하면 된다!<pre><code class="language-bash"># gitlab 커밋내역까지 clone 해오는 명령어
git clone --bare &lt;깃랩 레포 주소&gt;
</code></pre>
</li>
</ul>
<h1 id="clone해온-파일로-이동하기">clone해온 파일로 이동하기</h1>
<p>cd &lt;프로젝트명&gt;.git</p>
<h1 id="github로-옮기기">github로 옮기기</h1>
<p>git push --mirror &lt;깃허브 레포 주소&gt;</p>
<pre><code>
## gitlab에 wiki를 github 레포에 옮기기


- 마찬가지로 github내에 wiki를 생성해준 후 아래 명령어를 입력해준다.
```bash
# gitlab wiki 가져오기
git clone --mirror &lt;깃랩 레포 wiki 주소&gt;

# clone해온 wiki 파일로 이동하기
 cd &lt;프로젝트명&gt;.wiki.git

# github로 옮기기
git push --mirror &lt;깃허브 레포 wiki 주소&gt;</code></pre><h2 id="그-외-명령어-정리">그 외 명령어 정리</h2>
<pre><code class="language-bash"># 현재 프로젝트 파일에 연결된 repository 확인 
git remote -v

# 연결된 원격 레포 연결 해제
git remote remove origin

# 원격 레포 연결하기
git remote add origin &lt;연결할 원격 저장소 주소&gt;</code></pre>
<hr>
<h2 id="fatal-the-remote-end-hung-up-unexpectedly-에러-발생시-아래-포스팅-참고">fatal: the remote end hung up unexpectedly 에러 발생시 아래 포스팅 참고</h2>
<p><a href="https://devchaeyoung.tistory.com/entry/fatal-the-remote-end-hung-up-unexpectedly-%EC%98%A4%EB%A5%98-%ED%95%B4%EA%B2%B0">fatal: the remote end hung up unexpectedly 오류 해결
</a></p>
<h2 id="끝">끝</h2>
]]></description>
        </item>
        <item>
            <title><![CDATA[웹 동작 원리와 HTTP 프로토콜]]></title>
            <link>https://velog.io/@xiu_8/%EC%9B%B9-%EB%8F%99%EC%9E%91-%EC%9B%90%EB%A6%AC%EC%99%80-HTTP-%ED%94%84%EB%A1%9C%ED%86%A0%EC%BD%9C</link>
            <guid>https://velog.io/@xiu_8/%EC%9B%B9-%EB%8F%99%EC%9E%91-%EC%9B%90%EB%A6%AC%EC%99%80-HTTP-%ED%94%84%EB%A1%9C%ED%86%A0%EC%BD%9C</guid>
            <pubDate>Sun, 26 Nov 2023 14:47:03 GMT</pubDate>
            <description><![CDATA[<p>간단 개념 정리하기</p>
<h2 id="간단-동작-원리-정리">간단 동작 원리 정리</h2>
<h3 id="웹의-기본-구조">웹의 기본 구조</h3>
<ul>
<li>클라이언트 &lt;- 방화벽 -&gt; 웹서버 &lt;--&gt; WAS &lt;--&gt; DB 서버</li>
<li>방화벽 : http(s)://</li>
<li>웹서버 : <a href="http://www.velog.io">www.velog.io</a></li>
<li>WAS : /write?</li>
<li>DB서버: id=dajflkdj</li>
</ul>
<p>웹 서비스를 위한 서버측의 구성은 기본적으로 방화벽, 웹 서버 ,WAS(Web Application Server), DB서버로 구성된다.</p>
<h4 id="방화벽firewall">방화벽(Firewall)</h4>
<p>네트워크를 이용한 악의적인 공격으로부터 내부망과 내부 시스템을 보호하기 위한 보안 장비</p>
<h4 id="웹-서버web-server">웹 서버(Web Server)</h4>
<p>HTTP 프로토콜을 이용하여 웹 클라이언트의 요청을 처리하고 응답한다.
사용자의 요청에 빠르게 응답하며, 최적의 UI(화면 구성)를 제공하는 것을 목적으로 한다.</p>
<h4 id="웹-응용-서버was">웹 응용 서버(WAS)</h4>
<ul>
<li>웹 기반 서비스의 응용(Application) 역할을 담당한다.</li>
<li>웹 서버와 응용 서버를 분리하여 구성하므로, &#39;사용자 요청에 대한 응답에 최적화된 웹 서버&#39;의 장점과 &#39;복잡한 로직을 처리하고 기능의 확장에 유리한 응용 서버의 장점을 모두 제공하게 된다.<h4 id="db-서버">DB 서버</h4>
</li>
<li>서비스를 위한 주요 데이터, 사용자 데이터 등을 저장하고 관리한다.</li>
</ul>
<hr>
<h4 id="dns-domain-name-system-server">DNS (Domain Name System Server)</h4>
<p>url들의 이름과 IP 주소를 저장하고 있는 데이터 베이스로 웹 사이트를 위한 주소록이다. IP주소 대신 사용자가 사용하시 편하도록 주소를 매핑해주는 역할을 한다.</p>
<h4 id="tcpiptransmission-control-protocol-internet-protocol">TCP/IP(transmission Control Protocol/ Internet Protocol)</h4>
<p>데이터가 어떻게 웹을 건너 여행하는지 정의하는 통신 규약이다. 송신자가 수신자에게 IP주소를 사용해서 데이터를 전달하고 그 데이터가 제대로 갔는지 이야기 하는 것이다.</p>
<h3 id="웹-브라우저에-웹페이지가-표시되는-과정">웹 브라우저에 웹페이지가 표시되는 과정</h3>
<ul>
<li>사용자가 <code>velog.io/write?id=saflk</code>와 같은 url을 웹 브라우저의 주소창에 직접 입력하거나, 링크를 클릭한다.</li>
<li>DNS(Domain Name System) 조회(Query)를 통하여 url을 IP주소로 변환한다.</li>
<li>TCP의 3way-handshaking연결 방식으로 웹 서버에 연결하며, 일반적으로 80포트를 이용한다. HTTPS일 경우 443 포트를 이용하여 접속한다. ( 서버에 html문서 요청)</li>
<li>HTTP 프로토콜을 이용하여 웹 서버에 <code>/write?id=saflk</code>를 요청(req)한다. </li>
<li>/write는 서버에서 실행되는 기능으로, 관련 기능에 따라 WAS와 상호 연동한다. 이때, 필요한 경우 데이터베이스의 정보를 이용한다.</li>
<li>웹 서버는 최종 정보를 웹브라우저에 응답(Res)하고, 웹 브라우저는 전송 받는 내용을 표시한다.</li>
<li>TCP의 4way-handshaking 연결 종료 방식으로 웹 서버와의 연결을 종료한다.</li>
</ul>
<h3 id="dns-query의-목적">DNS Query의 목적</h3>
<p>DNS 서버들을 검색해서 해당 사이트의 IP주소를 찾는대있다.
IP 주소를 찾을 때까지 DNS서버에서 다른 DNS 서버를 오가며 에러가 날때까지 반복적으로 검색한다. = recursive search</p>
<h2 id="http-프로토콜">HTTP 프로토콜</h2>
<h3 id="http-요청-메소드req-method">HTTP 요청 메소드(Req Method)</h3>
<ul>
<li>⭐️GET : URL 형식으로 리소스(res)데이터를 요청한다.</li>
<li>⭐️HEAD : 리소르의 헤더(header) 정보를 요청하며, 서버는 응답 메시지로 본문(body)을 제외한 헤더 정보만 사용한다. </li>
<li>⭐️POST : HTTP 요청을 헤더와 바디로 구분하여 사용하고, 요청할 내용을 바디에 담아 서버에 전송한다. 주로 Form문을 사용한 ㄷ이터 전송에 사용한다.</li>
<li>PUT : 새로운 문서를 만들거나 기본 정보를 갱신하기 위해 사용한다.</li>
<li>DELETE : 웹의 리소스(파일)를 삭제하기 위해 사용한다.</li>
<li>CONNECT : 프록시(proxy)와 같은 중간 서버에 접속하기 위해 사용한다.</li>
<li>TRACE : 요청한 리소스가 수신되는 경로를 확인하기 위해 사용한다.</li>
<li>⭐️OPTIONS : 웹 서버가 제공하는 메소드를 확인하기 위해 사용한다.</li>
</ul>
<h3 id="http-응답과-상태코드">HTTP 응답과 상태코드</h3>
<ul>
<li>웹 클라이언트 요청에 대한 응답시 웹 서버는 HTTP 프로토콜의 버전, 웹 서버 정보, 상태 코드, 데이터 정보(Header 정보)등을 함께 전송한다.</li>
<li>HTTP 상태코드는 1XX(조건부 응답, 정보교환), 2XX(성공), 3XX(리다이렉션), 4XX(요청오류), 5XX(서버오류)로 구분된다.<h3 id="http-헤더-구조">HTTP 헤더 구조</h3>
</li>
<li>HTTP 프로토콜의 요청과 응답은 헤더(부가정보)와 바디(실제 데이터)로 구성된다.</li>
<li>HTTP의 헤더와 바디는 한 줄로 구분 된다.(개행 문자인 <code>\r\n</code>으로 구분)</li>
</ul>
<h2 id="참고자료">참고자료</h2>
<ul>
<li><a href="https://www.yes24.com/Product/Goods/116967738">https://www.yes24.com/Product/Goods/116967738</a></li>
<li><a href="https://zero-base.co.kr/event/media_BE_school_qna">https://zero-base.co.kr/event/media_BE_school_qna</a></li>
<li><a href="https://github.com/ksundong/backend-interview-question#CS-%EA%B4%80%EB%A0%A8-%EC%A7%80%EC%8B%9D">https://github.com/ksundong/backend-interview-question#CS-%EA%B4%80%EB%A0%A8-%EC%A7%80%EC%8B%9D</a></li>
<li><a href="https://velog.io/@eassy/www.google.com%EC%9D%84-%EC%A3%BC%EC%86%8C%EC%B0%BD%EC%97%90%EC%84%9C-%EC%9E%85%EB%A0%A5%ED%95%98%EB%A9%B4-%EC%9D%BC%EC%96%B4%EB%82%98%EB%8A%94-%EC%9D%BC">https://velog.io/@eassy/www.google.com%EC%9D%84-%EC%A3%BC%EC%86%8C%EC%B0%BD%EC%97%90%EC%84%9C-%EC%9E%85%EB%A0%A5%ED%95%98%EB%A9%B4-%EC%9D%BC%EC%96%B4%EB%82%98%EB%8A%94-%EC%9D%BC</a></li>
</ul>
]]></description>
        </item>
    </channel>
</rss>