<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>HEisSHAM</title>
        <link>https://velog.io/</link>
        <description>우당탕탕 개발자</description>
        <lastBuildDate>Fri, 16 Jun 2023 08:43:50 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>HEisSHAM</title>
            <url>https://velog.velcdn.com/images/he_sham/profile/d05cd963-4879-4562-9d3d-cf1dea5d8646/image.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. HEisSHAM. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/he_sham" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[AWS 배포 (1) (Docker + Nestjs)]]></title>
            <link>https://velog.io/@he_sham/AWS-%EB%B0%B0%ED%8F%AC-1-Docker-Nestjs</link>
            <guid>https://velog.io/@he_sham/AWS-%EB%B0%B0%ED%8F%AC-1-Docker-Nestjs</guid>
            <pubDate>Fri, 16 Jun 2023 08:43:50 GMT</pubDate>
            <description><![CDATA[<p>이전에 코캠에서는 GCP로 배포를 배웠는데, 실무에서는 AWS도 많이 사용되는 것 같아서
이번 사이드 프로젝트는 AWS로 배포를 해보았다.</p>
<hr>


<h2 id="1-계정-생성">1. 계정 생성</h2>
<p>GCP에서 무료 크레딧을 주는 것과 유사하게 AWS에서는 프리티어가 있다.
1년간, 속도나 용량을 프리티어 기준에만 맞추면 계속 사용할 수 있다.</p>
<p>줄어드는 크레딧보고 조마조마하는 GCP보다 AWS가 사이드 프로젝트 용으로 합리적인 듯?</p>
<hr>

<h2 id="2-지역-변경">2. 지역 변경</h2>
<p><img src="https://velog.velcdn.com/images/he_sham/post/3162126d-a0f6-46b1-9195-3a2fd95fa794/image.png" alt=""></p>
<p>우측 상단을 보면 지역을 변경할 수 있다.</p>
<p>처음에는 미국 오하이오로 설정이 되어있었는데, 
굳이 미국 오하이오 컴퓨터를 빌려서 배포 할 이유가 없으니 서울로 변경.</p>
<hr>

<h2 id="3-인스턴스-생성-ec2">3. 인스턴스 생성 (EC2)</h2>
<p>좌측 상단 서비스 메뉴를 눌러서 EC2 탭으로 들어간다.
GCP와 유사하게 인스턴스를 생성할 수 있다.</p>
<p>배포 할 컴퓨터를 한대 빌리는 것으로 생각하면 된다.</p>
<h4 id="1-인스턴스-시작">1) 인스턴스 시작</h4>
<p><img src="https://velog.velcdn.com/images/he_sham/post/ffdb6cf3-b40d-412b-8e67-30576f6692a7/image.png" alt=""></p>
<h4 id="2-ami-인스턴스의-소프트웨어-세팅">2) AMI (인스턴스의 소프트웨어 세팅)</h4>
<p><img src="https://velog.velcdn.com/images/he_sham/post/e61e25da-0915-41d1-a910-70050bdea5d6/image.png" alt=""></p>
<p>이름을 정해주고, 어떤 운영체제를 사용할지 정한다.
익숙한 Ubuntu로 진행.</p>
<p>다만 하단의 이 부분은 프리 티어가 사용 가능한 것으로 골라야 한다.</p>
<p><img src="https://velog.velcdn.com/images/he_sham/post/558e60cc-ee98-4adb-a0a7-34e66d6400e8/image.png" alt=""></p>
<p>인스턴스 유형도 프리티어 사용 가능한 것으로 설정.</p>
<p><img src="https://velog.velcdn.com/images/he_sham/post/1951a65f-ddad-42f4-9ab7-848e36f0f08a/image.png" alt=""></p>
<h4 id="3-키페어-인스턴스에-접근할-수-있는-권한을-가지는-파일">3) 키페어 (인스턴스에 접근할 수 있는 권한을 가지는 파일)</h4>
<p>키페어가 있어야만 인스턴스에 접속이 가능하다.
우리는 키페어가 없으니 일단 생성.</p>
<p><img src="https://velog.velcdn.com/images/he_sham/post/7b24af02-7757-4975-a08a-2a259d6661be/image.png" alt=""></p>
<p>이름을 정해주고,
RSA + .PEM파일 형식 그대로 생성
이 형식이 터미널에서 접속하기 편하더라.</p>
<p><img src="https://velog.velcdn.com/images/he_sham/post/0e0c1521-d43f-4da0-91b1-135201c243d2/image.png" alt=""></p>
<p>키페어는 Desktop이나 찾기 좋은 위치에 두는게 좋다.
코드가 들어있는 폴더에는 두지 않는 것이 좋다. 혹시 Git에 올라가면 난리가 나기 때문.</p>
<h4 id="4-기타-설정">4) 기타 설정</h4>
<p><img src="https://velog.velcdn.com/images/he_sham/post/e7455786-91ce-4dba-a38e-34a3e3e2efee/image.png" alt=""></p>
<p>위 세팅은 손댈 것이 없다. 그대로 생성.</p>
<hr>

<h2 id="4-ec2-접속">4. EC2 접속</h2>
<p>시작을 누르면 이렇게 생성이 되어있다.
<img src="https://velog.velcdn.com/images/he_sham/post/f3e33a11-cd7b-4d26-9d94-c253c1f307f2/image.png" alt=""></p>
<p>이 부분이 접속 가능한 도메인이 된다.</p>
<p><img src="https://velog.velcdn.com/images/he_sham/post/4c8e5175-d0da-47ee-b091-20d5a407cef1/image.png" alt=""></p>
<h4 id="1-연결">1) 연결</h4>
<p>우측 상단에 연결을 누른다.</p>
<p><img src="https://velog.velcdn.com/images/he_sham/post/dd2953ab-93ff-4145-9099-76a243262e57/image.png" alt=""></p>
<p>위와 같은 창이 뜨는데, 우리가 만든 키파일은 SSH 클라이언트 방식으로 접속이 가능하다.</p>
<p>** 이하는 맥북 기준</p>
<p><img src="https://velog.velcdn.com/images/he_sham/post/3c55b242-1feb-4f83-b21f-92aaae5a3199/image.png" alt=""></p>
<p>터미널을 열어서 위 부분을 붙여넣기 하면된다.</p>
<p><img src="https://velog.velcdn.com/images/he_sham/post/30262efb-a2b4-42db-ba8c-afcb068babb4/image.png" alt=""></p>
<p>이런 에러가 뜬다면?</p>
<p>키파일이 있는 위치에 가서 다시 실행해야 한다.
이래서 키파일 위치가 중요하다.</p>
<p><img src="https://velog.velcdn.com/images/he_sham/post/8f840fd8-59c4-4c20-a7e2-108047db2461/image.png" alt=""></p>
<p>위와 같이 뜬다면 잘 접속이 된 것.</p>
<hr>

<h2 id="5-docker-설치-및-명령어">5. Docker 설치 및 명령어</h2>
<p>우선 배포 컴퓨터에 접속을 했는데, 아무것도 설치가 되어 있지 않다.
우리는 도커로 배포 예정이니, 설치를 진행한다.</p>
<p><code>sudo apt update</code> : 패키지 업데이트
<br></p>
<p><code>sudo apt install docker</code>: 도커 설치
<code>docker --version</code>: 도커 버전 확인하여 설치 여부 체크
<code>sudo usermod -aG docker ${USER}</code>: 해당 명령어 사용하여 docker 사용 시 sudo없이 가능하도록 설정
<br></p>
<p><code>sudo apt install git</code>: git clone을 위해 git도 설치
<code>git clone ~~~</code> : 배포 할 코드를 git clone을 통해 인스턴스에 설치</p>
<br>

<p>git clone 받은 파일로 들어가서 
<code>docker compose build</code>  + <code>docker compose up</code> 실행</p>
<p>이러면 아마 높은 확률로 에러가 뜬다.
내 경우에는 git ignore된 .env파일이 clone되지 않았기 때문이다.</p>
<p>바로 env파일 생성하기.</p>
<p><code>vi .env.docker</code> : vi는 해당 폴더에 파일을 생성하거나 접근할 수 있다.
<code>i</code> i를 누르면 insert로 모드가 변경되어 추가나 변경이 가능하다.
내 env파일을 복사 붙여넣기한 후 <code>esc</code>로 나간 후, <code>:wq</code> 를 통해 저장후 종료.</p>
<br>

<p>다시 <code>docker compose up</code>을 실행 !
서버가 켜지는데 성공했다.
swagger 페이지로 확인.</p>
<p><img src="https://velog.velcdn.com/images/he_sham/post/5090d7ab-7e53-4056-8ee7-fd9059bd80bc/image.png" alt=""></p>
<p>사실 아직 빼먹은 것이 있다.
DB연결을 안했다.</p>
<p>AWS RDS서비스로 DB도 연결할 수 있는데, 
너무 길어져서 그건 다음 게시글로 넘겨야겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[NEST] Nest 기본 - 2
]]></title>
            <link>https://velog.io/@he_sham/NEST-Nest-%EA%B8%B0%EB%B3%B8-2</link>
            <guid>https://velog.io/@he_sham/NEST-Nest-%EA%B8%B0%EB%B3%B8-2</guid>
            <pubDate>Sun, 28 May 2023 05:43:50 GMT</pubDate>
            <description><![CDATA[<h3 id="1-pipe">1. PIPE</h3>
<p>PIPE란?
클라이언트에서 요청을 보낼 때, 
메소드 호출 직전에 올바른 요청인지 아닌지 걸러주는 단계</p>
<hr>

<h4 id="사용법-3가지">사용법 3가지</h4>
<ul>
<li><p>Handler
@UsePipes()를 사용하여 이하의 모든 파라미터에 적용시키기</p>
</li>
<li><p>Parameter
ParameterPipe는 파라미터 안에 들어가서 해당 파라미터에만 적용</p>
</li>
</ul>
<ul>
<li>Gloabal
main.ts에 app.useGlobalPipes(GlobalPipes)를 삽입하여
모든 서비스에 적용가능</li>
</ul>
<hr>

<pre><code class="language-ts">사용예시 

** pipe.ts
import { ArgumentMetadata, PipeTransform } from &quot;@nestjs/common&quot;;

export class BoardStatusValidationPipe implements PipeTransform {
  transform(value: any, metadata: ArgumentMetadata) {
    return value;
  }
}


** controller.ts
 @Patch(&quot;/:id/status&quot;)
  updateBoardStatus(
    @Param(&quot;id&quot;) id: string,
    @Body(&quot;status&quot;, BoardStatusValidationPipe) status: BoardStatus
  ) {
    return this.updateBoardStatus(id, status);
  }
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[NEST] Nest 기본]]></title>
            <link>https://velog.io/@he_sham/NEST-Nest-%EA%B8%B0%EB%B3%B8</link>
            <guid>https://velog.io/@he_sham/NEST-Nest-%EA%B8%B0%EB%B3%B8</guid>
            <pubDate>Thu, 25 May 2023 03:37:38 GMT</pubDate>
            <description><![CDATA[<p>사이드 프로젝트를 시작하며, 간만에 다시 Nest를 사용하며 복습한 내용을 적어보자.</p>
<h3 id="1-nestjs-설치">1. Nest.js 설치</h3>
<pre><code>npm install -g @nestjs/cli

||

yarn add @nestjs/cli</code></pre><h3 id="2-프로젝트-생성">2. 프로젝트 생성</h3>
<pre><code>nest new 프로젝트명 (생성을 원하는 위치에서)</code></pre><p><img src="https://velog.velcdn.com/images/he_sham/post/824b14c8-eaf8-437f-b05b-c0c19f64794d/image.png" alt=""></p>
<ul>
<li>Main.ts : 프로젝트의 시작점</li>
</ul>
<h3 id="3-기본-처리-로직">3. 기본 처리 로직</h3>
<pre><code>1. 브라우저의 요청 (REQ), ex) localhost:3000
2. Controller에서 해당 앤드포인트를 받아서 Services에서 로직 실행 
3. Service에서 해당 로직 리턴값을 다시 Controller로
4. 브라우저에 반응 (RES)</code></pre><h3 id="4-controller">4. Controller</h3>
<pre><code>** 들어오는 요청을 받아서 Service로 보내고 Service에서 받은 값을 반환한다.
REQ, RES 담당자로 보면 된다.
@Controller로 정의하여 사용
</code></pre><h3 id="5-service">5. Service</h3>
<pre><code>** 비즈니스 로직을 작성하는 곳
@Injectable 을 통해 다른 곳에서도 사용 가능하게 함
</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[스프링] 라이브러리]]></title>
            <link>https://velog.io/@he_sham/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC</link>
            <guid>https://velog.io/@he_sham/%EC%8A%A4%ED%94%84%EB%A7%81-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC</guid>
            <pubDate>Thu, 06 Apr 2023 07:43:09 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/he_sham/post/97667902-f7ce-4c09-8457-2479a005ca70/image.png" alt=""></p>
<p>start.spring.io 에서 프로젝트를 생성할 때, 필요한 라이브러리를 간편하게 불러올 수 있다.</p>
<p>내가 지금까지 이해한 바로는, node에서 
라이브러리를 yarn add + import를 편리하게 하는 것과 같은 것으로 보인다.</p>
<p><img src="https://velog.velcdn.com/images/he_sham/post/bf2ac53d-306a-449d-a31c-a7ac87a40fc7/image.png" alt=""></p>
<p>흥미로운 사실은, 프로젝트 생성 시 내가 지정한 라이브러리에 의존관계 있는 라이브러리가
알아서 추가된다는 점이다. 아직 각 라이브러리가 뭔지 모르겠는데 일단 엄청 많다.</p>
<hr>

<h2 id="알아둘만한-라이브러리">알아둘만한 라이브러리</h2>
<h4 id="spring-boot-starter">spring-boot-starter</h4>
<ul>
<li>tomcat : 톰캣, 스프링 서버</li>
<li>webMVC : 기본 MVC 패턴 형태</li>
</ul>
<p><code>MVC란? Model + View + Controller 로 프로젝트 구성 시 용도에 맞게 나눔</code></p>
<ul>
<li>spring-boot-starter-thymeleaf : html로 보여주는 라이브러리</li>
<li>spring-core : 기본 필수 라이브러리</li>
<li>spring-boot-starter-logging 의 logback + slf4j : 로그 관련 표준 라이브러리</li>
</ul>
<h4 id="spring-boot-starter-test-코트-테스트-관련">spring-boot-starter-test (코트 테스트 관련)</h4>
<ul>
<li>junit : 테스트 프레임 워크</li>
<li>mockito</li>
<li>assertj</li>
<li>spring-test : 테스트 지원</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JS/자바스크립트] 프로그래머스 - 2016년]]></title>
            <link>https://velog.io/@he_sham/JS%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-2016%EB%85%84</link>
            <guid>https://velog.io/@he_sham/JS%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-2016%EB%85%84</guid>
            <pubDate>Mon, 13 Feb 2023 10:22:06 GMT</pubDate>
            <description><![CDATA[<h2 id="문제">문제</h2>
<pre><code class="language-ts">2016년 1월 1일은 금요일입니다.
2016년 `a`월 `b`일은 무슨 요일일까요?

두 수 `a` ,`b`를 입력받아 2016년 `a`월 `b`일이 무슨 요일인지 리턴하는 함수, solution을 완성하세요.

요일의 이름은 일요일부터 토요일까지 각각 SUN,MON,TUE,WED,THU,FRI,SAT 입니다. 
예를 들어 a=5, b=24라면 5월 24일은 화요일이므로 문자열 &quot;TUE&quot;를 반환하세요.

2016년은 윤년입니다.
2016년 a월 b일은 실제로 있는 날입니다. (13월 26일이나 2월 45일같은 날짜는 주어지지 않습니다)</code></pre>
<h2 id="풀이">풀이</h2>
<pre><code class="language-ts">const month = {
    1: 31,
    2: 29,
    3: 31,
    4: 30,
    5: 31,
    6: 30,
    7: 31,
    8: 31,
    9: 30,
    10: 31,
    11: 30,
    12: 31
 } 

  let day = [&quot;FRI&quot;, &quot;SAT&quot;, &quot;SUN&quot;, &quot;MON&quot;, &quot;TUE&quot;, &quot;WED&quot;, &quot;THU&quot;] 
 //Month와 Day를 선언

  function solution(a, b) {
    let answer = 0;
    for (let i = 1; i&lt;a; i++) {
        answer += month [i]}  // 위에 선언한 Month에서 해당 달까지 지난 달을 모두 담는다.
    answer += ( b - 1)         // 마지막 달의 일수 (b)를 더한다. 1일부터 시작하므로 1을 빼야됨
    answer = day[answer % 7] 
    // answer에 1월 1일부터 지난 모든 day의 합이 쌓인다. 7![](https://velog.velcdn.com/images/he_sham/post/cda6df56-e632-41fd-a7b1-fa10cf155d00/image.png)
로 나누어 요일을 구함.
    return answer    
}

</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JS/자바스크립트] 프로그래머스 - 한 번만 등록한 문자]]></title>
            <link>https://velog.io/@he_sham/JS%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%ED%95%9C-%EB%B2%88%EB%A7%8C-%EB%93%B1%EB%A1%9D%ED%95%9C-%EB%AC%B8%EC%9E%90</link>
            <guid>https://velog.io/@he_sham/JS%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%ED%95%9C-%EB%B2%88%EB%A7%8C-%EB%93%B1%EB%A1%9D%ED%95%9C-%EB%AC%B8%EC%9E%90</guid>
            <pubDate>Mon, 13 Feb 2023 09:03:41 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/he_sham/post/1f5e118f-cbb2-4399-b3b1-fb0edd33b468/image.png" alt=""></p>
<h2 id="문제">문제</h2>
<pre><code class="language-ts">한 번만 등장한 문자

문자열 `s`가 매개변수로 주어집니다. 
`s`에서 한 번만 등장하는 문자를 사전 순으로 정렬한 문자열을 return 하도록 
solution 함수를 완성해보세요. 
한 번만 등장하는 문자가 없을 경우 빈 문자열을 return 합니다.</code></pre>
<p><img src="https://velog.velcdn.com/images/he_sham/post/284344b2-7316-43e6-a4e8-09a8ba909dba/image.56" alt=""></p>
<h2 id="풀이">풀이</h2>
<pre><code class="language-ts">
function solution(s) {

    let answer = &#39;&#39;

    let arr = s.split(&#39;&#39;).sort() // 문자열을 배열로 바꿔서 알파벳 순으로 정렬

    for(let i = 0; i&lt;arr.length; i++) {
        if(arr[i] != arr[i+1] &amp;&amp; arr[i] != arr[i-1]) {
            answer = answer + String(arr[i]) }
      // 앞뒤로 같은 문자가 없을 경우에 answer에 String 변환하여 담기
    }
    return answer
}</code></pre>
<h2 id="흠">흠...</h2>
<p>for문 하나썼는데 풀이 시간이 굉장히 길다. 다른 사람의 풀이를 살펴보자
<img src="https://velog.velcdn.com/images/he_sham/post/6ebd44c8-6949-4def-9900-9af2572d50d9/image.49" alt=""></p>
<pre><code class="language-ts">// 처음에 보고 이게 뭔 소리지? 생각이 들었다.
// 이 풀이를 사용하니 3.24ms 걸리던 테스트 1번이 0.08ms로 줄었다.

function solution(s) {

    let res = [];

    for (let c of s) 
    if (s.indexOf(c) === s.lastIndexOf(c)) res.push(c);

      // indexOf는 중복된 값이 있어도 가장 첫 index 번호를 가져온다.
      // lastIndexOf는 중복된 값이 있을 경우 가장 마지막 index 번호를 가져온다.
      // 그러므로 indexOf === lastIndexOf 일 경우는 중복된 값이 없다는 소리

    return res.sort().join(&#39;&#39;);
      // 중복되지 않은 값만 배열에 담아서 string 변환
}</code></pre>
<p>프로그래머스 다른문제 풀이 최상단을 보면 항상 기상천외한 풀이가 있다.
정답만 통과하는게 아니라 효율적으로 풀도록 노력해야겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JS/자바스크립트] 프로그래머스 - 진료 순서 정하기]]></title>
            <link>https://velog.io/@he_sham/JS%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%A7%84%EB%A3%8C-%EC%88%9C%EC%84%9C-%EC%A0%95%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@he_sham/JS%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-%EC%A7%84%EB%A3%8C-%EC%88%9C%EC%84%9C-%EC%A0%95%ED%95%98%EA%B8%B0</guid>
            <pubDate>Mon, 13 Feb 2023 08:26:46 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/he_sham/post/60599745-8aa9-4660-be69-24cbc6f4efa5/image.png" alt=""></p>
<h2 id="문제">문제</h2>
<pre><code class="language-js">외과의사 머쓱이는 응급실에 온 환자의 응급도를 기준으로 진료 순서를 정하려고 합니다. 
정수 배열 `emergency` 가 매개변수로 주어질 때 
응급도가 높은 순서대로 진료 순서를 정한 배열을 return 하도록 solution 함수를 완성해주세요.</code></pre>
<p><img src="https://velog.velcdn.com/images/he_sham/post/354283a8-e061-4ea4-8556-2bcc74cb74d6/image.07" alt=""></p>
<h2 id="풀이">풀이</h2>
<pre><code class="language-js">function solution(emergency) {
    let arr = emergency.slice().sort((a,b) =&gt; (b-a))  
    //응급 순서로 정렬
    // slice를 하지 않으면 원본이 변경된다.
    // slice()를 사용하면 원본은 별경하지 않고 얕은 복사 가능하다.
    let answer = emergency.map(e =&gt; arr.indexOf(e)+1)
    // map으로 arr의 index 값 + 1 을 부여
    return answer
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JS/자바스크립트] 프로그래머스 - k의 개수]]></title>
            <link>https://velog.io/@he_sham/JS%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-k%EC%9D%98-%EA%B0%9C%EC%88%98</link>
            <guid>https://velog.io/@he_sham/JS%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-k%EC%9D%98-%EA%B0%9C%EC%88%98</guid>
            <pubDate>Mon, 13 Feb 2023 08:07:28 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/he_sham/post/dffc626a-b6bb-4243-bd00-9a31c44b11d8/image.png" alt=""></p>
<h2 id="문제">문제</h2>
<pre><code class="language-js">1부터 13까지의 수에서, 1은 1, 10, 11, 12, 13 이렇게 총 6번 등장합니다.
정수 i, j, k가 매개변수로 주어질 때, 
i부터 j까지 k가 몇 번 등장하는지 return 하도록 solution 함수를 완성해주세요.</code></pre>
<p><img src="https://velog.velcdn.com/images/he_sham/post/ceb26529-0e9c-455c-a0a9-bc6fab8aac68/image.53" alt=""></p>
<h2 id="풀이">풀이</h2>
<pre><code class="language-js">function solution(i, j, k) {

    let arr = []
    let arr2 = []
    let answer = 0;

    for(let a=i; a&lt;=j; a++) {                //i 와 j 사이의 수를 가져오기
            arr.push(String(a).split(&#39;&#39;)) // 문자로 변환 + 자릿수별로 쪼개서 가져오기
            arr2 = arr[arr.length-1]      // i와 j 사이의 모든 수는 배열의 마지막 값
              for(let b = 0; b&lt;arr2.length; b++) { 
                                           // k와 같은 숫자 찾아서 answer에 담기
            if(arr2[b] === String(k)) answer ++
            }
    }
    return answer
}</code></pre>
<h2 id="흠">흠..</h2>
<p><img src="https://velog.velcdn.com/images/he_sham/post/aeb47555-cf39-43c0-88d0-ee9928f5f3f2/image.55" alt=""></p>
<p>시간이 너무 많이 걸리는 것 같아서 다른 사람의 풀이를 알아보자</p>
<pre><code class="language-js">function solution(i, j, k) {
    let a =&#39;&#39;;
    for(i; i&lt;=j; i++){a += i}
    return a.split(k).length-1;
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백앤드] ACID]]></title>
            <link>https://velog.io/@he_sham/%EB%B0%B1%EC%95%A4%EB%93%9C-ACID</link>
            <guid>https://velog.io/@he_sham/%EB%B0%B1%EC%95%A4%EB%93%9C-ACID</guid>
            <pubDate>Fri, 23 Dec 2022 12:32:58 GMT</pubDate>
            <description><![CDATA[<h2 id="acid">ACID</h2>
<blockquote>
<p>Transaction 을 정의하는 4가지 속성</p>
</blockquote>
<ul>
<li>A(Atomicity) : 원자성 → 안전성 보장을 위해 가져야 할 성질 중의 하나로 트랜잭션과 관련된 작업들이 부분적으로 실행되다가 중단되지 않는 것을 보장하는 능력.
모두 성공할 것 아니면 모두 실패하게 만드는 것
(DB의 오염을 막기 위함).</li>
<li>C(Consistency) : 일관성 → 트랜잭션이 실행을 성공적으로 완료하면 언제나 일관성 있는 데이터베이스 상태로 유지하는 것.
똑같은 쿼리를 조회할 때마다 동일한 결과값이 나타나야하는 것.
수정과 삭제로 인해 결과값이 달라지는 것은 당연함.</li>
<li>I(Isolation) : 격리성 → 트랜잭션을 수행 시 다른 트랜잭션의 연산 작업이 끼어들지 못하도록 보장하는 것.
사람의 요청을 처리하는 동안 B사람의 요청은 잠시 기다리는 것</li>
<li>D(Durability) : 지속성 → 성공적으로 수행된 트랜잭션에 대한 로그가 남아야하는 성질로 런타임 오류나 시스템 오류가 발생하더라도, 해당 기록은 영구적이어야 하는 것.
성공하여 commit이 되었으면 서버를 다시 켜도 그 데이터는 그대로 유지가 되어야 되는 것.</li>
</ul>
<h2 id="isolation-level">Isolation-level</h2>
<p>Transaction의 격리 수준</p>
<blockquote>
<p>READ UNCOMMITTED
READ COMMITTED
REPEATABLE READ
SERIALIZABLE
<em><strong>(*아래 단계로 내려갈수록 안전해지는 반면 성능이 느려짐)</strong></em></p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/he_sham/post/35db203a-653a-4236-bdf8-f815ca11fac6/image.png" alt=""></p>
<blockquote>
<p>Dirty Read : 트랜잭션이 작업이 완료되지 않았는데도 다른 트랜잭션에서 볼 수 있게 되는 현상
NON REPEATABLE READ : 동일한 결과값이 나타나지 않을 때 나타나는 현상</p>
</blockquote>
<ul>
<li>한 트랜잭션 내에서 같은 쿼리를 두번 수행할 때, 그 사이에 다른 트랜잭션이 값을 수정 또는 삭제함으로써 두 쿼리가 상이하게 나타나는 현상 =&gt; 동일한 쿼리를 요청하면 매번 동일한 결과값이 나타나야 함.</li>
</ul>
<h2 id="1단계--read-uncommitted">1단계 : READ UNCOMMITTED</h2>
<p>각 트랜잭션에서의 변경 내용이 COMMIT이나 ROLLBACK 여부에 상관 없이 다른 트랜잭션에서 값을 읽을 수 있음 =&gt; commit 되지 않는 데이터들을 조회할 수 있으나, 정합성에 문제가 많은 격리 수준이기 때문에 사용하지 않는 것을 권장!</p>
<h2 id="2단계--read-committed">2단계 : READ COMMITTED</h2>
<p>RDB(관계형 데이터베이스)에서 대부분 기본적으로 사용되고 있는 격리 수준
Dirty Read 발생 X
실제 테이블 값을 가져오는 것이 아니라 Undo 영역에 백업된 레코드에서 값을 가져옴</p>
<h2 id="3단계--repeatable-read">3단계 : REPEATABLE READ</h2>
<p>RDB(관계형 데이터베이스)에서 대부분 기본적으로 사용되고 있는 격리 수준</p>
<p>MySQL에서는 트랜잭션마다 트랜잭션 ID를 부여하여 트랜잭션 ID보다 작은 트랜잭션 번호에서 변경한 것만 읽게됨</p>
<p>Undo 공간에 백업해두고 실제 레코드 값을 변경</p>
<p>백업된 데이터는 불필요하다고 판단하는 시점에 주기적으로 삭제
Undo에 백업된 레코드가 많아지면 MySQL 서버의 처리 성능이 떨어질 수 있음
=&gt; 이러한 변경방식은 MVCC(Multi Version Concurrency Control)라고 부름</p>
<p>PHANTOM READ : 종종 다른 트랜잭션에서 수행한 변경 작업에 의해 레코드가 보였다가 안 보였다가 하는 현상</p>
<h2 id="4단계--serializable">4단계 : SERIALIZABLE</h2>
<p> async findAll() {
    const queryRunner = await this.connection.createQueryRunner();
    await queryRunner.connect();
    await queryRunner.startTransaction(&#39;SERIALIZABLE&#39;);
    try {
      // 조회시 락을 걸고 조회함으로써, 다른 쿼리에서 조회 못하게 막음(대기시킴) =&gt; Select ~ For Update
      const payment = await queryRunner.manager.find(Payment, {
        //PHANTOM READ 가 발생하지 않기 위해서 lock을 걸어줌 
        lock: { mode: &#39;pessimistic_write&#39; },
      });
      console.log(payment);</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Git workflow]]></title>
            <link>https://velog.io/@he_sham/Git-workflow</link>
            <guid>https://velog.io/@he_sham/Git-workflow</guid>
            <pubDate>Fri, 23 Dec 2022 12:29:56 GMT</pubDate>
            <description><![CDATA[<h1 id="git-workflow">Git Workflow</h1>
<blockquote>
<p>여기서 더 나아가서 dev 브랜치에서 기능별로 feature 브랜치를 빼서 개발하고 기능 개발이 완료되면 dev 브랜치에 합칩니다.</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/he_sham/post/30665b3f-8fe3-49a1-bca7-1f690e430194/image.png" alt=""></p>
<ul>
<li><p>hotfix 브랜치
hot-fix 브랜치는 말 그래도 긴급하게 에러를 고치기 위해 만드는 브랜치입니다. 이 브랜치는 master 브랜치에서 바로 만들어서 프로덕션에서 생긴 이슈를 고치고 master 브랜치로 합쳐서 배포할 수 있도록 합니다.</p>
</li>
<li><p>release 브랜치
release 브랜치는 dev 브랜치에서 생성합니다. dev 브랜치에서 feature 브랜치들을 만들어서 기능들을 모두 개발하고 합칩니다. 그 다음에 dev 브랜치에서 release 브랜치를 생성하고, 프로덕션을 출시하기 위해서 필요한 코드들만 덧붙이도록 합니다. 그후 master 브랜치에 합칩니다. 또한 dev 브랜치에서는 release 브랜치를 합쳐서 최신 버전으로 유지합니다.</p>
</li>
<li><p>Git Fork Workflow - Forking Repository
위의 브랜치를 이용한 과정들은 한 개의 저장소에서 이루어지는 것입니다. Git Fork Workflow는 저장소를 fork(복제) 해서 협업하는 작업 과정을 말합니다.</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[회고]]></title>
            <link>https://velog.io/@he_sham/%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@he_sham/%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Fri, 23 Dec 2022 12:19:09 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>29세의 (만나이) 8주 부트캠프 회고</p>
</blockquote>
<ol>
<li><p>올해 8월 회사를 관뒀다.
여러가지 이유가 있지만, 적성에 맞지 않는 것 같다는 생각이 있었다.
본인만 열심히하면 무한히 자기 발전이 가능한 개발자가 해보고 싶었다.</p>
<p><em>어? 근데 지금와서 생각해보면 열심히 해서 발전안하는 직업이있나?</em></p>
<br>
</li>
<li><p>쿨하게 사표를 낼때만 해도 나는 내가 똑똑한줄 알았다.
사실 <em>&#39;나는 이과형 머리가 아닐까?&#39;</em> 이런 자신감을 갖고 있었다.</p>
</li>
</ol>
<br>

<ol start="3">
<li><p>아니더라 베이스캠프가 열리자마자 나는 그냥 문과형머리였다.
아래는 실제로 내가 베이스캠프 1주차때 작성한 if문이다.</p>
<p>같은 조 동료가 들여쓰기 저딴식으로 하지 말라고 말했는데도 
똥고집을 부렸다.</p>
<p><em>&quot;제가 보기엔 이게 더 가시성이 좋은데요?&quot;</em></p>
</li>
</ol>
<pre><code class="language-ts">if
(a&gt;2000)
{return true}</code></pre>
<br>

<ol start="4">
<li><p>베이스캠프 3주차 js 강의를 듣다가 벽을 느꼈다.
선생님이 우다다다 로직을 세우는데 이해가 하나도 가지 않았다.</p>
<p><em>&quot;지난주 css 도형 옮기기는 재밌었는데.. 프엔할걸 그랬나?&quot;</em>
_ - 프론트엔드가 도형만 옮기는 줄 알았던 사람_</p>
</li>
</ol>
<br>


<ol start="5">
<li>오프라인 부트캠프가 개강했다.
전반적인 정규 수업을 듣는 내 느낌은 이랬다.<blockquote>
<p>1교시 = 사칙연산
2교시 = 사칙연산
3교시 = 사칙연산을 이용하여 자동차 만들기
과제 = 수업시간에 배운것을 바탕으로 로켓발사하기</p>
</blockquote>
</li>
</ol>
<br>

<ol start="6">
<li><p>평생 접하지 않은 내용이 너무 많아서 쉽지가 않았다. 
매일 머리 싸매고 과제를 했고, 주변 도움을 받지 않으려고 했으나
아무리 검색해도 혼자 해결하는게 쉽지가 않더라.</p>
<p>주변 도움을 많이 받았다. 같은 반 사람들은 다 좋은 사람들이었다.
 꼭 도와줘서 좋은건 아니고 사람들이 다 순둥순둥했다.</p>
</li>
</ol>
<br>

<ol start="7">
<li>8주간 캠프 생활을 하면서 과제만  겨우겨우 따라가다보니
사실 내가 성장하고 있다는 느낌을 받지 못했다.
수업을 들을때는 다 이해가가는데 막상 내 코드를 치려고 하면 막막했다.</li>
</ol>
<p><img src="https://velog.velcdn.com/images/he_sham/post/1f5c4a36-7fd2-4d5a-8c9e-a96a29d434a1/image.jpeg" alt=""></p>
<ol start="8">
<li><p>실력이 느는건지 가물가물하던 와중에 놀랍게도 나는 성장하고 있었다.
어느날 알고리즘 테스트에서 무려 4개중 2개를 맞았다.</p>
<p>반타작하고 호들갑이라고 할 수 있지만, 
과거에 들여쓰기도 못하던 내가 문제를 해결하는게 대견했다</p>
<p>꼭 못하는 애들이 더 유난인 것처럼, 1개맞은사람 0개맞은사람을 놀렸다.</p>
<br>


</li>
</ol>
<ol start="9">
<li><p>수업 강의도 계속 돌려보니, 
수업시간에 따라치느라 듣지 못했던 내용이 많더라.</p>
<p>반복해서 완두쌤의 강의를 들으니 로직이 어느정도 이해가 가기 시작했다.
내가 치는 코드가 무슨 의미인지, 어떻게 로직을 짜야하는지
희미하지만 개념이 잡히는 느낌이 들었다. 
(아직 응용하라고 하면 머릿속 하얘짐)</p>
<br>

</li>
</ol>
<ol start="10">
<li>8주차를 보내며 내가 만든 사이트도 배포했고,
사실 아무 기능 없는 graphql 사이트지만 
가끔씩 <a href="https://yogiya.shop/graphql">yogiya.shop</a>을 들어가서, 내가 낳은 API들을 보면 기분이 좋아진다.</li>
</ol>
<br>

<ol start="11">
<li><p>다음주에는 팀프로젝트가 시작된다. 걱정이 많다.
모든 조에 백앤드가 3명씩 들어가 있는데, 
우리조에는 나를 포함하여 2명이다. (왜?)
다른 한명도 똑똑이가 아니기 때문에, 큰 고난이 예상된다.</p>
<p>하지만 기회가 아닐까?
잘하는 사람 등에 업혀서 가는 것보다, 
영차영차 머리깨지면서 기어가면 실력이 늘 것이라고 생각하고 있다.</p>
<p>프론트에서 요청하는 것은 밤을 새서라도 들어줄 심산이다. </p>
</li>
</ol>
<br>

<p>아직은 블로그 제목처럼 우당탕탕 굴러가고 있으나, 돌이켜보면 성장하고 있다.
팀프로젝트 잘 끝내고 다시 회고 작성하러 오겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[웹] SSL, HTTPS]]></title>
            <link>https://velog.io/@he_sham/%EC%9B%B9-SSL-HTTPS</link>
            <guid>https://velog.io/@he_sham/%EC%9B%B9-SSL-HTTPS</guid>
            <pubDate>Fri, 23 Dec 2022 11:25:00 GMT</pubDate>
            <description><![CDATA[<h1 id="ssl이란">SSL이란?</h1>
<p><img src="https://velog.velcdn.com/images/he_sham/post/03f2c17f-e63d-4fea-b12a-cfd974e5361e/image.png" alt=""></p>
<blockquote>
<p>암호기반 프로토콜이며, SSL이 적용된 웹사이트는 URL이
HTTP 에서 <strong>HTTPS</strong>로 변경이 된다. (추가된 S는 보안의 Secure을 뜻한다.)</p>
</blockquote>
<h1 id="ssl-작동원리">SSL 작동원리?</h1>
<blockquote>
<ul>
<li>기본적으로 웹에서 전송되는 데이터를 자동으로 암호화하여, 해커가 데이터를
가로채더라도 해독이 불가능한 암호를 보도록 만든다.</li>
</ul>
</blockquote>
<ul>
<li>추가로 &quot;핸드셰이크(악수)&quot;라는 기능을 통한 인증프로세스로
두 장치의 ID를 확인한다</li>
</ul>
<blockquote>
<h4 id="핸드셰이크">핸드셰이크</h4>
<p>통신을하는 브라우저와 웹서버 사이에서 암호화 통신을 하도록,
<strong>신분을 확인하고 필요한 정보를 주고 받는 과정이다.</strong>
흡사 악수와 비슷하여 핸드셰이크라는 이름이 붙게 되었다.</p>
</blockquote>
<h1 id="ssl--tls-사용-이유">SSL / TLS 사용 이유?</h1>
<blockquote>
<p>SSL은 TLS의 전신이다. 1999년에 이름이 업데이트 되었으며, 동일한 개념임.</p>
</blockquote>
<blockquote>
<p>신용카드 정보나, 개인정보가 수없이 오고 가는 웹 사이트 상에서 보안의 필요성은
당연히 대두 되었으며, 해커들이 정보를 빼가도 고객의 정보가 유출되지 않도록
SSL/TLS 암호화를 사용하게 되었다.</p>
</blockquote>
<hr>

<h1 id="http--https">HTTP &amp; HTTPS</h1>
<p>HTTP의 개념은 아래와 같다</p>
<blockquote>
<h3 id="http-hyper-text-transfer-protocol">HTTP (Hyper Text Transfer Protocol)</h3>
<p>웹 사이트와 서버 사이에서 주고받는 언어(HTML)로 작성된 프로토콜</p>
</blockquote>
<ul>
<li>프로토콜 : 인터넷상에서의 통신을 주고받을때 적용되는 규약</li>
<li>HTML: 웹 사이트의 기본이 되는 언어로, 브라우저를 통해 읽을 수 있음.</li>
<li>Request를 보낼 때마다 Response를 받는 원리이다.</li>
<li>이 이유로 기존의 요청은 기억하지 못하는 stateless 개념이다.</li>
<li>위 문제를 해결하기 위해, 세션/DB 등으로 상태를 저장하게 되었다.</li>
</ul>
<p>위 개념에 S(Secure, 보안)이 추가 된 것으로,
말그대로 SSL인증을 추가한 HTTP이며 더욱 보안이 철저한 프로토콜이라고 볼 수 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백앤드] CI / CD]]></title>
            <link>https://velog.io/@he_sham/%EB%B0%B1%EC%95%A4%EB%93%9C-CI-CD</link>
            <guid>https://velog.io/@he_sham/%EB%B0%B1%EC%95%A4%EB%93%9C-CI-CD</guid>
            <pubDate>Fri, 23 Dec 2022 00:48:23 GMT</pubDate>
            <description><![CDATA[<h1 id="ci--cd">CI / CD</h1>
<p>개발과 배포를 자동으로 진행해주는 서비스이다.</p>
<blockquote>
<p>CI/CD를 정확히 나누면 아래와 같으며,
CI = Continuous Integration (통합)
CD = Continous Deployment (배포)</p>
</blockquote>
<p>CI/CD에 대표적인 서비스는 아래와 같다.</p>
<ul>
<li>Jenkins (서비스 규모가 클 경우 사용) ( + 추가라이브 많음)</li>
<li>GithubActions (서비스 규모가 작을 경우 용이)</li>
<li>AWS (CodePipeline) - AWS로 통일하고 싶을 경우</li>
<li>GCP (CloudBuild) - GCP로 통일하고 싶을 경우</li>
</ul>
<hr>

<h2 id="gcp---cloudbuild">GCP - CloudBuild</h2>
<p>GCP에서 제공하는 cloud build 서비스 로직은 아래와 같다.</p>
<ol>
<li>Vscode 상에서 cloudbuild.yaml 파일을 만들어서 git에 push!</li>
<li>Github에 설정을 해두고, 자동으로 GCP로 넘어가도록 설정하기.</li>
<li>GCP 컴퓨터 안에서 소스코드 실행 및 docker build, push 등등</li>
<li>구글 레지스토리에 이미지 자동 업데이트 + 자동 업데이트 배포</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백앤드] 서버리스란?]]></title>
            <link>https://velog.io/@he_sham/%EB%B0%B1%EC%95%A4%EB%93%9C-%EC%84%9C%EB%B2%84%EB%A6%AC%EC%8A%A4%EB%9E%80</link>
            <guid>https://velog.io/@he_sham/%EB%B0%B1%EC%95%A4%EB%93%9C-%EC%84%9C%EB%B2%84%EB%A6%AC%EC%8A%A4%EB%9E%80</guid>
            <pubDate>Fri, 23 Dec 2022 00:41:33 GMT</pubDate>
            <description><![CDATA[<h1 id="서버리스">서버리스</h1>
<blockquote>
<p>서버리스는 말 그대로 서버가 없다는 뜻이다.
Cloud를 통해 API 단위로 배포를 진행한다.</p>
</blockquote>
<h1 id="서버리스를-왜-쓰나요">서버리스를 왜 쓰나요?</h1>
<blockquote>
<p>실제로 서버를 구입하면 24시간동안 서버가 돌아가므로,
비용이 발생한다.</p>
</blockquote>
<blockquote>
<p>하지만 서버리스 서비스는 함수가 실행될때만 비용이 부과되고,
초기 비용이 적으므로 비용 절감에 큰 효과가 있다.</p>
</blockquote>
<h1 id="아니-그렇게-좋은데-왜-안쓰나요">아니 그렇게 좋은데 왜 안쓰나요?</h1>
<blockquote>
<p>서버리스 서비스에는 고질적인 문제가 있는데,
Cold Start라는 문제이다. 
서버리스는 요청이 들어올때만 서버가 돌아가기 때문에, 컴퓨터를
구동하는데 약 5초정도의 시간이 걸린다.
서버에 지속적으로 요청하지 않으면, 다시 서버가 off 되므로
이용하는 사용자들은 계속 Cold Start를 통한 지연을 겪게된다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백앤드] 방화벽 & VPC]]></title>
            <link>https://velog.io/@he_sham/%EB%B0%B1%EC%95%A4%EB%93%9C-%EB%B0%A9%ED%99%94%EB%B2%BD-VPC</link>
            <guid>https://velog.io/@he_sham/%EB%B0%B1%EC%95%A4%EB%93%9C-%EB%B0%A9%ED%99%94%EB%B2%BD-VPC</guid>
            <pubDate>Fri, 23 Dec 2022 00:31:27 GMT</pubDate>
            <description><![CDATA[<h1 id="방화벽">방화벽?</h1>
<p>불이 번지지 않도록 내리는 벽이기도하고
PC에 바이러스가 들어오지 않도록 방화벽을 설정하기도 했다.</p>
<p>방화벽은 정확히 무엇일까?</p>
<p>위키에서의 정의는 아래와 같다.</p>
<blockquote>
<p>방화벽은 미리 정의된 보안 규칙에 기반한, 
들어오고 나가는 네트워크 트래픽을 모니터링하고 제어하는 
네트워크 보안 시스템이다.
방화벽은 일반적으로 신뢰할 수 있는 내부 네트워크, 
신뢰할 수 없는 외부 네트워크(예: 인터넷) 간의 장벽을 구성한다.</p>
</blockquote>
<p>다른 네트워크에서, 신뢰가 가지않는 네트워크에서 오는 접근을
차단하는 역할을 한다.</p>
<p>말만 들어보면 방화벽은 항상 유지하는게 좋아보이지만,
배포시에 방화벽이 설정되어 있으면 내 사이트에 접근이 차단되므로
해제하는 작업도 필요하다.</p>
<p>GCP로 배포를 진행하고 방화벽을 해재하고 내가 열어둔 3000번 포트를 연결하여 주었다.</p>
<p><img src="https://velog.velcdn.com/images/he_sham/post/ed0ec42c-d8b1-44d7-90e7-21dbcab791e9/image.png" alt=""></p>
<hr>

<h1 id="vpc">VPC</h1>
<p>Virtual Private Cloud 의 약자.</p>
<p>가상의 네트워크 클라우드를 사용한다는 소리이다.</p>
<p>GCP에서  아래와 같이 설정하여 docker를 올려보았다.
<img src="https://velog.velcdn.com/images/he_sham/post/ca92cbb0-71c7-4a06-8b7e-02f1b211e44c/image.png" alt=""></p>
<p>0.0.0.0/0은 모든 IP를 허용한다는 뜻</p>
<p><img src="https://velog.velcdn.com/images/he_sham/post/e8b1f83d-9f5a-43a9-86b1-1d9ce8cd870a/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/he_sham/post/95bf842c-5f75-4fc5-b904-ef4e4772d1e3/image.png" alt=""></p>
<p>그 뒤 GCP-SQL에서 IP를 얻은 뒤,</p>
<p><img src="https://velog.velcdn.com/images/he_sham/post/9e02e513-471b-40ac-b102-74b8e05a2dc4/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/he_sham/post/592c534c-23b4-4495-9d20-5540d6fe5316/image.png" alt=""></p>
<p>app.module의 호스트에 연결해주고 다시 배포를 진행하면 DB로도 접근이 가능하였다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[백앤드] TDD란?]]></title>
            <link>https://velog.io/@he_sham/%EB%B0%B1%EC%95%A4%EB%93%9C-TDD%EB%9E%80</link>
            <guid>https://velog.io/@he_sham/%EB%B0%B1%EC%95%A4%EB%93%9C-TDD%EB%9E%80</guid>
            <pubDate>Fri, 23 Dec 2022 00:14:11 GMT</pubDate>
            <description><![CDATA[<h1 id="tdd">TDD</h1>
<p>위키에는 아래와 같이 TDD를 정의하고 있다.</p>
<blockquote>
<p>테스트 주도 개발(Test-driven development TDD)은 
매우 짧은 개발 사이클을 반복하는 소프트웨어 개발 프로세스 중 하나이다. 
개발자는 먼저 요구사항을 검증하는 자동화된 테스트 케이스를 작성한다. 그런 후에, 그 테스트 케이스를 통과하기 위한 최소한의 코드를 생성한다. 마지막으로 작성한 코드를 표준에 맞도록 리팩토링한다.</p>
</blockquote>
<p>말만 들으면 테스트코드를 짜놓고 코드를 짜맞추는거 같아서
이상하게 들릴 수 있으나,</p>
<p>현실적으로 개발을 하다보면 시간이 부족하여 테스트를 미처 끝내지 못하고
배포하는 경우가 많다고한다.</p>
<p>이에 테스트 코드를 미리 짜놓고 개발하는 것이 현실적으로 안전하다고도
볼 수 있다.</p>
<h1 id="tdd의-장단점">TDD의 장단점</h1>
<blockquote>
<p>장점</p>
</blockquote>
<ul>
<li>테스트 코드를 짜다보면 설계를 구체적으로 할 수 있다.</li>
<li>배포 전 오류 검사가 용이하며, 디버깅 시간을 단축시킨다.</li>
<li>코드를 읽을 때, 테스트 코드에는 모든 기능이 모여있어,<pre><code> 해당 코드를 읽고 서비스를 쉽게 이해할 수 있다.</code></pre></li>
</ul>
<blockquote>
<p>단점</p>
</blockquote>
<ul>
<li>테스트 코드 작성에 너무 많은 시간을 소모할 수 있다.</li>
<li>서비스 개발 전에 테스트 코드를 짜기 때문에, 테스트 코드가 완벽하지 않을 수 있다.</li>
</ul>
<p>회사를 들어가면 내규에 맞게 개발을 따라가게 될 것이지만,
개인적으로는 서비스의 구체성이 자주 변하는 스타트업의 경우에는
TDD개발이 부적합하다고 느껴진다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[정규표현식 - 이메일 & 전화번호 표현]]></title>
            <link>https://velog.io/@he_sham/%EC%A0%95%EA%B7%9C%ED%91%9C%ED%98%84%EC%8B%9D-%EC%9D%B4%EB%A9%94%EC%9D%BC-%EC%A0%84%ED%99%94%EB%B2%88%ED%98%B8-%ED%91%9C%ED%98%84</link>
            <guid>https://velog.io/@he_sham/%EC%A0%95%EA%B7%9C%ED%91%9C%ED%98%84%EC%8B%9D-%EC%9D%B4%EB%A9%94%EC%9D%BC-%EC%A0%84%ED%99%94%EB%B2%88%ED%98%B8-%ED%91%9C%ED%98%84</guid>
            <pubDate>Thu, 22 Dec 2022 07:52:04 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>정규표현식은 기본적으로 <code>/      /</code> 안에 작성한다.</p>
</blockquote>
<blockquote>
<ul>
<li>\w : 모든 문자를 1개를 칭한다.</li>
</ul>
</blockquote>
<ul>
<li>2개가 하고싶다면?    \w{2}</li>
<li>1개 이상이 하고 싶다면?  \w+</li>
<li>0개 이상이 하고 싶다면?  \w*</li>
</ul>
<p>이메일 양식을 정규 표현식으로 표현한다면?</p>
<blockquote>
<p>/\w+@\w+.\w+/ 
하지만 위와 같이 작성하면 온점(.) 자리에 콤마(,)가 들어와도
true를 반환한다.
왜냐? 정규표현식에서 온점(.)은 &quot;모든 것&quot;을 의미한다.</p>
</blockquote>
<blockquote>
<p>*<em>/\w+@\w+.\w+/ *</em>
위와 같이 작성하면 온점 본연의 성질을 잃어버리고 text로 변경됨.</p>
</blockquote>
<hr>

<p>숫자의 경우 아래와 같이 표현한다.</p>
<blockquote>
<p>\d : 모든 숫자 1개
\d{3} : 모든 숫자 3개
\d{3,4) : 모든 숫자 3개 혹은 4개</p>
</blockquote>
<p>위를 이용하여 핸드폰 번호를 표현한다면?</p>
<blockquote>
<p><strong>/^\d{3}-\d{3,4}-\d{4}$/</strong></p>
</blockquote>
<p>정규 표현식은 시작(^)과 끝($)을 표현해줘야 초과된 값을 제외하여 true를
반환한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[자바스크립트] 이미지 업로드 프로세스]]></title>
            <link>https://velog.io/@he_sham/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EC%97%85%EB%A1%9C%EB%93%9C-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4</link>
            <guid>https://velog.io/@he_sham/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EC%97%85%EB%A1%9C%EB%93%9C-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4</guid>
            <pubDate>Thu, 22 Dec 2022 02:38:33 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/he_sham/post/8db0c976-368b-438c-9052-14a01f57a193/image.jpeg" alt=""></p>
<h1 id="이미지-업로드">이미지 업로드</h1>
<p>이미지를 웹에 업로드하는 기본적인 로직은 아래와 같다.</p>
<blockquote>
<ol>
<li>브라우저에서 사용자가 업로드할 이미지 파일을 선택합니다.</li>
<li>브라우저에서 선택된 파일을 변수에 저장합니다. 
변수에 담긴 내용을 <strong><code>파일 객체</code></strong>라고 하며 파일 사이즈 등 파일에 대한 정보를 담고 있습니다.</li>
<li>이제 브라우저에서는 파일 객체를 백엔드 서버에 
업로드 요청을 합니다.
이를 위해 백엔드 서버에서는 파일 업로드를 하는 
API를 제작 및 구현 해놓아야 한다.</li>
<li>백엔드 서버에서는 API를 통해 받은 파일을 DB에 저장 시 <code>BLOB</code>타입으로 저장</li>
</ol>
</blockquote>
<p>구현한 코드는 아래와 같다.</p>
<pre><code class="language-ts">**Service
@Injectable()
export class FilesService {
  async upload({ files }: IFilesServiceUpload): Promise&lt;string[]&gt; {
    const waitedFiles = await Promise.all(files);

    // 1. 파일을 클라우드 스토리지에 저장하는 로직

    // 1-1) 스토리지 셋팅하기
    const bucket = &#39;yoyoyo&#39;;
    const storage = new Storage({
      projectId: &#39;polar-scene-370203&#39;,
      keyFilename: &#39;gcp-file-storage.json&#39;,
    }).bucket(bucket);

    // 1-2) 스토리지에 파일 올리기
    const results = await Promise.all(
      waitedFiles.map(
        (el) =&gt;
          new Promise&lt;string&gt;((resolve, reject) =&gt; {
            const fname = `${getToday()}/${uuidv4}/origin/${el.filename}`;

            el.createReadStream()
              .pipe(storage.file(el.filename).createWriteStream())
              .on(&#39;finish&#39;, () =&gt; resolve(`${bucket}/${fname}`))
              .on(&#39;error&#39;, () =&gt; reject(&#39;실패&#39;));
          }),
      ),
    );

    // 2. 다운로드URL 브라우저에 돌려주기
    return results;
  }
}</code></pre>
<p>콘솔로 받아오는 값을 찍어서 지정된 규칙대로 GCP 상에 저장하였다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[웹] CORS란?]]></title>
            <link>https://velog.io/@he_sham/%EC%9B%B9-CORS%EB%9E%80</link>
            <guid>https://velog.io/@he_sham/%EC%9B%B9-CORS%EB%9E%80</guid>
            <pubDate>Thu, 22 Dec 2022 02:26:38 GMT</pubDate>
            <description><![CDATA[<h1 id="what-cors-is">what CORS is</h1>
<blockquote>
<p>브라우저에서는 보안을 이유로 cross-origin HTTP 요청을 제한한다. 그래서 HTTP- HTTPS 사이에서 cross-origin 요청을 하려면 서버의 동의가 필요하다.
만약 서버가 동의한다면 브라우저에서는 요청을 허락하고, 
동의하지 않는다면 브라우저에서 거절합니다.
이 매커니즘을 CORS 라고 부른다.</p>
</blockquote>
<hr>

<h1 id="cors-동작-원리">CORS 동작 원리</h1>
<p>다른 출처의 리소스를 요청할 때 HTTP 프로토콜을 사용하여 요청을 보내게 되는데, 이때 브라우저는 요청헤더에 Origin이라는 필드에 요청을 보내는 출처를 함께 담아서 보낸다.</p>
<p>하지만 동작 원리를 조금 더 깊게 들어가면 CORS 요청은 다음과 같이
세 가지 유형으로 나눠서 생각해볼 수 있다.</p>
<p><code>Simple Request</code>
MDN에서 &quot;단순요청&quot;은 아래와 같이 정의한다.</p>
<p>단순요청은 예비 요청(Prefilght)을 보내지 않고 바로 서버에 본 요청을 한 후, 서버가 이에 대한 응답의 헤더에 Access-Control-Allow-Origin과 같은 같을 보내주면 브라우저가 CORS정책 위반여부를 검사하는 방식이다.</p>
<p>단순요청은 아래의 조건을 만족해야 된다.</p>
<ul>
<li><p>요청의 메소드는 GET, HEAD, POST 중 하나여야 한다.</p>
</li>
<li><p>유저 에이전트가 자동으로 설정한 헤더외에, 
수동으로 설정할 수 있는 헤더는 Fetch 명세에서 
 &quot;CORS-safelisted request-header&quot;로 정의한 헤더만 사용할 수 있다.</p>
</li>
</ul>
<blockquote>
<p>위와 같은 조건을 만족하는 단순 요청은 안전한 요청으로 취급되며, 프리플라이트 요청이 필요 없이 단 한 번의 요청만을 전송한다. </p>
</blockquote>
<p><code>Prefilght Request</code></p>
<p>프리플라이트 요청의 특징은 다음과 같다.</p>
<blockquote>
<ul>
<li>메소드로 OPTIONS를 사용한다.</li>
</ul>
</blockquote>
<ul>
<li>Origin 헤더에 자신의 Origin을 설정한다.</li>
<li>Access-Control-Request-Method 헤더에 
실제 요청에 사용할 메소드를 설정한다.</li>
<li>Access-Control-Request-Headers 헤더에 
실제 요청에 사용할 헤더들을 설정한다.</li>
</ul>
<p>서버는 이러한 프리플라이트 요청에 대해 다음과 같은 특징을 가진 응답을 제공해야 한다.</p>
<blockquote>
<ul>
<li>Access-Control-Allow-Origin 헤더에 허용되는 Origin들의 목록 혹은 와일드카드(*)를 설정한다.</li>
</ul>
</blockquote>
<ul>
<li>Access-Control-Allow-Methods 헤더에 허용되는 메소드들의 목록 혹은 와일드카드(*)를 설정한다.</li>
<li>Access-Control-Allow-Headers 헤더에 허용되는 헤더들의 목록 혹은 와일드카드(*)를 설정한다.</li>
<li>Access-Control-Max-Age 헤더에 해당 프리플라이트 요청이 브라우저에 캐시 될 수 있는 시간을 초 단위로 설정한다.</li>
</ul>
<p>이러한 응답을 받고 나면 브라우저는 이 응답의 정보를 자신이 전송한 요청의 정보와 비교하여 실제 요청의 안전성을 검사한다.
만약 이 안전성 검사에 통과하게 된다면, 그때서야 실제 요청을 서버에게 보낸다.<img src="https://velog.velcdn.com/images/he_sham/post/e0ba03bc-c5f7-4d78-9785-fd16bc6eba51/image.jpeg" alt=""></p>
<hr>]]></description>
        </item>
        <item>
            <title><![CDATA[[자바스크립트] DB Schema & ERD]]></title>
            <link>https://velog.io/@he_sham/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-DB-Schema-ERD</link>
            <guid>https://velog.io/@he_sham/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-DB-Schema-ERD</guid>
            <pubDate>Wed, 21 Dec 2022 11:11:41 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/he_sham/post/146ab64b-202c-44c1-a2d7-32017e80dcb2/image.jpeg" alt="">
<img src="https://velog.velcdn.com/images/he_sham/post/5b2e07b0-caeb-4b3c-b3ff-9a921154be13/image.jpeg" alt="">
<img src="https://velog.velcdn.com/images/he_sham/post/b73c1e7e-72c1-4f33-8d60-c0f6d68d27e2/image.jpeg" alt=""></p>
<h1 id="스키마란">스키마란</h1>
<blockquote>
<p>데이터베이스 어떻게 설계할지에 대한 계획 
구조와 제약 조건을 정하는 것이다.</p>
</blockquote>
<h2 id="db-스키마">DB 스키마</h2>
<p>당연히 DB 스키마는 
데이터베이스에서 자료의 구조, 자료의 표현 방법, 자료 간의 관계를 형식 언어로 정의한 구조이다.</p>
<p>스키마는 기본적으로 3가지의 종류로 나뉘는데, 아래와 같다.</p>
<ul>
<li><p>외부 스키마(External Schema) : 프로그래머나 사용자의 입장에서 데이터베이스의 모습으로 조직의 일부분을 정의한 것</p>
</li>
<li><p>개념 스키마(Conceptual Schema) : 모든 응용 시스템과 사용자들이 필요로하는 데이터를 통합한 조직 전체의 데이터베이스 구조를 논리적으로 정의한 것</p>
</li>
<li><p>내부 스키마(Internal Schema) : 전체 데이터베이스의 물리적 저장 형태를 기술하는 것</p>
</li>
</ul>
<hr>

<h1 id="erd">ERD</h1>
<blockquote>
<p>테이블간의 관계를 설명해주는 다이어그램이다. 
이를 통해 프로젝트에서 사용되는 DB 의 구조를 한눈에 파악할 수 있으며, API를 효율적으로 작성하기 위한 그림이므로,
프로젝트 작업시, 선행적으로 작성해야 하는 부분이다.</p>
</blockquote>
<p>아래와 같이 각 그룹들을 연결하여 관계를 표현한다.
<img src="https://velog.velcdn.com/images/he_sham/post/1999a951-5006-472b-bc03-b48e29cbca20/image.png" alt="">
내가 첫 프로젝트로 작성한 ERD 예시는 아래와 같다.</p>
<p><img src="https://velog.velcdn.com/images/he_sham/post/8dc31f9c-102c-4c5d-a6ef-73f8adc15e50/image.png" alt=""></p>
]]></description>
        </item>
    </channel>
</rss>