<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>jn2o_o2.log</title>
        <link>https://velog.io/</link>
        <description>https://github.com/jennaaaaaaaaa</description>
        <lastBuildDate>Thu, 16 May 2024 08:09:56 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>jn2o_o2.log</title>
            <url>https://velog.velcdn.com/images/jn2o_o2/profile/09eaabec-0639-48fa-b053-8f5deed12575/image.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. jn2o_o2.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/jn2o_o2" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[2024-05-16[TIL]]]></title>
            <link>https://velog.io/@jn2o_o2/2024-05-16TIL</link>
            <guid>https://velog.io/@jn2o_o2/2024-05-16TIL</guid>
            <pubDate>Thu, 16 May 2024 08:09:56 GMT</pubDate>
            <description><![CDATA[<p>초기 벨로그 글엔 생각도 조금씩 작성했었는데 글이 정리되어 보이지 않아서 그냥 노트 처럼 쓰기 시작했어요.
그치만 개발자가 되기 위해선 본인만의 생각도 중요하는 걸 깨달았기에 정리가 안되있어보여도 글을 잘 쓰지 못 하더라도 써보려고 합니다 :) 쓰다보면 좋아지겠..죠?</p>
<br>

<p>테크 블로그글을 읽고..</p>
<h2 id="당근-마켓-서버-개발자의-api-설계">당근 마켓 서버 개발자의 API 설계</h2>
<p>오늘 당근마켓 개발자가 쓴 블로그를 보게되었습니다.
저는 당연히 design-first 접근 방식으로 설계 해야되는 줄 알고 그렇게 설계를 해왔었습니다.
api 설계 할 때 명세를 먼저 작성하는게 &#39;design-first 접근 방식&#39;이라고 용어가 있는지도 처음 알았습니다.</p>
<p>저는 프로젝트 개발 경험을 했었을 때 처음엔 당연히 그렇게 해야되는 줄 알고 노션을 사용해 API명세서를 작성했었어요</p>
<ol>
<li>팀노션에 API 명세 페이지를 만든다</li>
<li>API 명세를 작성한다</li>
<li>클라이언트에선 앞서 작성된 API를 임시로 사용한다</li>
<li>서버에서 API를 작성하고 완성된 API를 클라이언트에게 공유해 해당 API를 사용한다</li>
</ol>
<p>대체적으로 위 처럼 진행되었는데 마지막 프로젝트 때 노션으로 API 설계시 수정된 API 명세를 다시 작성해줘야하는 번거로움과 API가 완성된줄 알았는데 수정되었을 때 정신이 없어 클라이언트에게 수정된 사실을 알리지 못 한 문제가 있었어요. 그래서 마지막 프로젝트, 좀 나중에 적용되긴 했지만 swagger를 사용해봤습니다.</p>
<h3 id="새로-알게된-oas">새로 알게된 OAS</h3>
<p>OpenAPI Specification 이라는 HTTP API를 정의하고 문서화하는 언어를 새롭게 알게되었어요
이걸로 API 명세를 작성하면 API 문서와 프로그래밍 언어의 코드를 자동으로 생성해준다는데 자세한건 사용해봐야 될거 같습니다</p>
<h4 id="oas-장점">OAS 장점</h4>
<ol>
<li>yaml 또는 json으로 API 명세를 작성해 수동으로 요청 응답을 작성하지 않아도 된다.</li>
<li>제안하는 규격이 있어 일관된 형식으로 API를 작성할 수 있다.</li>
<li>별도 저장소에서 관리해 찾기 쉽다.</li>
<li>최신성이 보장된다.</li>
</ol>
<h3 id="느낀점">느낀점</h3>
<p>솔직히 이때까지 프로젝트들을 진행하면서 API 명세가 중요하다는 걸 알고는 있었지만 주어진 기간내에 부족한 실력으로 개발을 하려니 API에 대해 진지하게 짚고 넘어간적이 없었습니다 체계적이고 확실하게 관리를 해야되는구나 하고 다시한번 깨닫게 되면 글이였습니다.</p>
</br>

<p><a href="https://medium.com/daangn/%EC%BB%A4%EB%AE%A4%EB%8B%88%ED%8B%B0%EC%8B%A4-api-design-first-%EC%A0%91%EA%B7%BC%EB%B0%A9%EC%8B%9D-%EC%A0%95%EC%B0%A9%EA%B8%B0-cecca0a37c05">당근 개발자 하이드님 글</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[2024-03-19]]></title>
            <link>https://velog.io/@jn2o_o2/2024-03-19</link>
            <guid>https://velog.io/@jn2o_o2/2024-03-19</guid>
            <pubDate>Tue, 19 Mar 2024 12:55:01 GMT</pubDate>
            <description><![CDATA[<h1 id="req-객체의-다양한-속성과-메서드">REQ 객체의 다양한 속성과 메서드</h1>
<h3 id="reqmethod">req.method</h3>
<ul>
<li>HTTP 요청의 메서드:  &quot;GET&quot;, &quot;POST&quot;, &quot;PUT&quot;, &quot;DELETE&quot; 등</li>
<li>클라이언트가 어떤 데이터를 가져오기 위해 GET 요청을 보냈다면, req.method는 &quot;GET&quot;을 반환</li>
</ul>
<h3 id="reqoriginalurl">req.originalUrl</h3>
<ul>
<li>요청된 URL의 전체 경로</li>
<li>클라이언트가 <a href="http://example.com/api/users?name=John">http://example.com/api/users?name=John</a> 으로 요청을 보냈다면, req.originalUrl은 /api/users?name=John을 반환</li>
</ul>
<h3 id="reqheaders">req.headers</h3>
<ul>
<li>Content-Type, Authorization (예: 토큰), User-Agent 등 클라이언트가 보낸 모든 HTTP 헤더를 포함</li>
</ul>
<h3 id="reqip">req.ip</h3>
<ul>
<li>실제 사용자의 IP를 얻기 위해서는 프록시 또는 로드 밸런서 설정에 따라 req.headers[&#39;x-forwarded-for&#39;] 또는 유사한 헤더를 확인</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[2024-02-01[TIL]]]></title>
            <link>https://velog.io/@jn2o_o2/2024-02-01</link>
            <guid>https://velog.io/@jn2o_o2/2024-02-01</guid>
            <pubDate>Thu, 01 Feb 2024 11:13:28 GMT</pubDate>
            <description><![CDATA[<h1 id="hoisting">Hoisting</h1>
<hr>
<h2 id="hoisting이란">hoisting이란?</h2>
<ul>
<li>호이스팅은 코드가 실행하기 전 변수,함수선언이 해당 <strong>scope</strong>의 최상단으로 끌어 올려진 것 같은 현상을 말합니다 자바스크립트코드가 실행되기 전 함수와 변수선언이 먼저 스캔되고  <strong>lexical environment</strong>라는 자바스크립트 데이터 내 메모리에 추가됩니다 따라서 변수, 함수를 선언시 호이스팅되서 코드 내에 선언되기 이전부터 사용 할 수 있습니다.</li>
</ul>
</br>

<h3 id="scope란">scope란?</h3>
<hr>
<ul>
<li>globalScope<ul>
<li>전역에 선언되어있어 어느곳에서든지 해당 변수에 접근할 수 있다</li>
</ul>
</li>
<li>localScope<ul>
<li>해당 지역(함수)에서만 접근할 수 있다<pre><code class="language-javascript">var a = 1; // 전역 스코프
function print() { // 지역(함수) 스코프
var a = 111;
console.log(a);
}
print();
console.log(a)</code></pre>
</br>

</li>
</ul>
</li>
</ul>
<h3 id="lexical-environment란">lexical environment란?</h3>
<hr>
<ul>
<li>identifier-variable 이렇게 매핑 정보를 가지고 있는 데이터 구조 입니다<ul>
<li>identifierdms 변수, 함수의 이름을 가리키며, variable은 실제 객체 또는 원시값을 가르킵니다.<pre><code class="language-javascript">  LexicalEnvironment = {
   Identifier:  &lt;value&gt;,
   Identifier:  &lt;function object&gt;
  }</code></pre>
</li>
</ul>
</li>
</ul>
<p>참고
<a href="https://medium.com/@su_bak/javascript-%EC%8A%A4%EC%BD%94%ED%94%84-scope-%EB%9E%80-bc761cba1023">스코프관련 블로그</a>
<a href="https://velog.io/@rkio/Javascript-%ED%98%B8%EC%9D%B4%EC%8A%A4%ED%8C%85hoisting%EC%97%90-%EB%8C%80%ED%95%98%EC%97%AC#%EC%B0%B8%EA%B3%A0-%EC%9E%90%EB%A3%8C">hoisting관련 블로그</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[2024-01-23[TIL]]]></title>
            <link>https://velog.io/@jn2o_o2/2024-01-23TIL</link>
            <guid>https://velog.io/@jn2o_o2/2024-01-23TIL</guid>
            <pubDate>Mon, 22 Jan 2024 15:30:14 GMT</pubDate>
            <description><![CDATA[<h1 id="nodemailer">Nodemailer</h1>
<p>: node.js 환경에서 이메일을 쉽게 보낼 수 있도록 도와주는 모듈</p>
<ol>
<li>nodemailer 설치<pre><code class="language-shell">yarn add nodemailer</code></pre>
</li>
<li>smtpTransport 객체<pre><code class="language-javascript">let smtpTransport = nodemailer.createTransport({
service: &#39;gmail&#39;,
auth: {
 user: &#39;your-email@gmail.com&#39;,
 pass: &#39;your-password&#39;
},
tls: {
   rejectUnauthorized: false, //서버의 SSL 인증서를 검증할지 여부를 결정(보안)
}
});</code></pre>
</li>
<li>mailOptions 설정( 보내는 사람, 받는 사람, 제목, 본문 등 지정)<pre><code class="language-javascript">let mailOptions = {
from: &#39;your-email@gmail.com&#39;,
to: &#39;receiver-email@example.com&#39;,
subject: &#39;Hello&#39;,
text: &#39;Hello world!&#39;
};
</code></pre>
</li>
</ol>
<pre><code>
4. 설정한 transporter, mailOptions을 사용해 이메일 보내기
```javascript
smtpTransport.sendMail(mailOptions, function(error, info){
  if (error) {
    console.log(error);
  } else {
    console.log(&#39;Email sent: &#39; + info.response);
  }
  smtpTransport.close();
});</code></pre><h3 id="aws-ses-적용해보기">aws ses 적용해보기</h3>
<ol>
<li><p>aws-sdk 설치</p>
<pre><code class="language-shell">yarn add aws-sdk</code></pre>
</li>
<li><p>aws ses 사용 설정 및 nodemailer 이메일 전송객체 생성</p>
<pre><code class="language-javascript">AWS.config.update({
accessKeyId: process.env.AWS_SES_ACCESS_KEY,
secretAccessKey: process.env.AWS_SES_SECRET_KEY,
region: process.env.AWS_SES_REGION,
});
</code></pre>
</li>
</ol>
<p>const sesMailer = nodemailer.createTransport({
   SES: new AWS.SES({
      apiVersion: &#39;2010-12-01&#39;,
   }),
});</p>
<pre><code>+ nodemailer의 createTransport 메서드를 사용해 aws ses 설정해서 sendMail 메서드를 통해 이메일을 보낼 수 있다
+ new AWS.SES({ apiVersion: &#39;2010-12-01&#39; })는 AWS SES 서비스 객체를 생성하는 부분이다

3. mailOptions 설정( 보내는 사람, 받는 사람, 제목, 본문 등 지정)
```javascript
let mailOptions = {
  from: &#39;your-email@gmail.com&#39;,
  to: &#39;receiver-email@example.com&#39;,
  subject: &#39;Hello&#39;,
  text: &#39;Hello world!&#39;
};</code></pre><ol start="4">
<li>설정한 transporter, mailOptions을 사용해 이메일 보내기<pre><code class="language-javascript">sesMailer.sendMail(mailOptions, function(error, info){
if (error) {
 console.log(error);
} else {
 console.log(&#39;Email sent: &#39; + info.response);
}
smtpTransport.close();
});</code></pre>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[2024-01-22[TIL]]]></title>
            <link>https://velog.io/@jn2o_o2/2024-01-22TIL</link>
            <guid>https://velog.io/@jn2o_o2/2024-01-22TIL</guid>
            <pubDate>Mon, 22 Jan 2024 14:32:22 GMT</pubDate>
            <description><![CDATA[<h1 id="인스턴스-생성-방식">인스턴스 생성 방식</h1>
<pre><code class="language-javascript">class SomeClass {
    constructor(postsService) {
        this.postsService = postsService;
    }
}</code></pre>
<p>위 코드는 의존성 주입(Dependency Injection, DI) 패턴을 사용한다
의존성 주입(Dependency Injection, DI)이란, 클래스가 필요로 하는 서비스나 객체를 외부에서 주입받는 패턴을 말한다
클래스가 필요로 하는 의존성을 직접 생성하지 않고 외부에서 주입받아 사용하는 방식이다
코드의 테스트와 재사용성을 향상시킬 수 있다</p>
<pre><code class="language-javascript">service = new Service();</code></pre>
<p>위 코드는 Service 라는 클래스의 인스턴스를 직접 생성한다
의존성 주입을 사용하지 않으므로 테스트와 재사용성 측면에서는 단점이지만, 간단한 애플리케이션에서는 더 직관적일 수 있다.</p>
<p>참고
<a href="https://charming-kyu.tistory.com/17">https://charming-kyu.tistory.com/17</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[2024-01-19[TIL]]]></title>
            <link>https://velog.io/@jn2o_o2/2024-01-19TIL</link>
            <guid>https://velog.io/@jn2o_o2/2024-01-19TIL</guid>
            <pubDate>Fri, 19 Jan 2024 00:53:25 GMT</pubDate>
            <description><![CDATA[<blockquote>
</blockquote>
<h1 id="for문-사용하는-경우">for문 사용하는 경우</h1>
<ul>
<li>for문은 글로벌 변수값이 for문 안에서만 사용가능하다</li>
<li>일반적으로 배열의 모든 원소에 대해 동일한 작업을 수행할 때 유용하며, 반복 횟수가 미리 정해져 있을 때 사용한다<h1 id="while문-사용하는-경우">while문 사용하는 경우</h1>
</li>
<li>while문은 글로벌 변수값이 안에서도 밖에서도 사용가능하다 (값이 달라짐)</li>
<li>반복 횟수가 미리 정해져 있지 않고, 각 반복마다 수행하는 작업이 달라질 수 있는 경우에는 while문이 더 적합하다</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[2024-01-15[TIL]]]></title>
            <link>https://velog.io/@jn2o_o2/%EC%86%8C%ED%94%84%ED%8A%B8%EC%82%AD%EC%A0%9C%EC%9D%98-%EC%9E%A5%EC%A0%90%EA%B3%BC-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%AC%B4%EA%B2%B0%EC%84%B1%EC%9D%B4%EB%9E%80</link>
            <guid>https://velog.io/@jn2o_o2/%EC%86%8C%ED%94%84%ED%8A%B8%EC%82%AD%EC%A0%9C%EC%9D%98-%EC%9E%A5%EC%A0%90%EA%B3%BC-%EB%8D%B0%EC%9D%B4%ED%84%B0-%EB%AC%B4%EA%B2%B0%EC%84%B1%EC%9D%B4%EB%9E%80</guid>
            <pubDate>Mon, 15 Jan 2024 05:02:47 GMT</pubDate>
            <description><![CDATA[<h1 id="soft-delete">Soft Delete</h1>
<h3 id="장점">장점</h3>
<ul>
<li><p>데이터 복구 용이: 실제 데이터를 삭제하는 대신, &#39;삭제됨&#39; 상태로 표시만 변경되기 때문에 필요할 경우 쉽게 복구 가능, 실수로 데이터를 삭제하더라도 복구 할 수 있다.</p>
</li>
<li><p>데이터 무결성 유지: 데이터 간의 관계를 유지하면서도 삭제 작업을 처리 가능, 완전히 삭제하는 대신 &#39;삭제됨&#39; 상태로 만들면 데이터 간의 참조 관계를 유지
=&gt; 데이터 무결성을 보장하는 데 도움</p>
</li>
<li><p>데이터 분석에 유용: 삭제된 데이터까지 포함하여 전체 데이터를 분석하는 데 유용,
(ex; 특정 기간 동안 사용자의 활동 패턴, 상품의 구매 이력 등을 분석할 때, 소프트 삭제를 통해 삭제된 데이터까지 고려하면 더 정확한 분석 결과를 얻을 수 있다.)</p>
</li>
<li><p>법적/규제적 요구사항 충족: 소프트 삭제를 통해 일부 산업/국가에서는 특정 데이터를 일정 기간 동안 보존하는 것이 법적으로 필요로 하는 요구사항을 충족할 수 있음</p>
</li>
<li><p>시스템 안정성 향상: 소프트 삭제를 사용하면 데이터 삭제로 인해 일부 기능이 제대로 작동하지 않는 문제를 방지할 수 있습니다.</p>
</li>
</ul>
</br>

<h3 id="단점">단점</h3>
<ul>
<li>필요하지 않은 데이터가 시스템 내에 계속 남아있게 되는 단점</li>
</ul>
</br>

<h1 id="데이터-무결성data-integrity">데이터 무결성(Data Integrity)</h1>
<p>: 데이터의 정확성, 일관성, 유효성을 보장하는 것으로 데이터베이스에서 데이터 무결성을 보장하는 것은 중요한 요소로, 이를 통해 데이터의 신뢰성을 유지하고 데이터 관리 오류를 최소화할 수 있다.</p>
<ul>
<li><p>개체 무결성(Entity Integrity): 각 행이 고유하게 식별될 수 있도록 보장하는 것 즉, 테이블의 기본 키 값은 고유하고 NULL 값을 가질 수 없다.</p>
</li>
<li><p>참조 무결성(Referential Integrity): 외래 키를 사용하여 두 테이블 간의 관계를 설정할 때, 참조 무결성을 보장, 이는 <em>외래 키 값이 반드시 참조하는 테이블의 기본 키 값과 일치하거나 NULL이어야 함을 의미</em>, 이를 통해 잘못된 데이터가 데이터베이스에 들어가는 것을 방지</p>
</li>
<li><p>도메인 무결성(Domain Integrity): 특정 필드에 입력될 수 있는 값의 범위를 제한, 예를 들어, <em>나이 필드에는 음수가 들어갈 수 없고, 이메일 필드는 특정 형식을 따라야 한다는 것</em> 이 도메인 무결성의 예시</p>
</li>
<li><p>사용자 정의 무결성(User-Defined Integrity): 비즈니스 규칙에 따라 정의되는 무결성, 예를 들어, 한 회사에서는 &#39;고객이 주문을 하려면 먼저 회원가입을 해야 한다&#39;는 규칙이 사용자 정의 무결성</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[2024-01-08[TIL]]]></title>
            <link>https://velog.io/@jn2o_o2/2024-01-08TIL</link>
            <guid>https://velog.io/@jn2o_o2/2024-01-08TIL</guid>
            <pubDate>Mon, 08 Jan 2024 07:59:01 GMT</pubDate>
            <description><![CDATA[<h1 id="softdelete--harddelete">softDelete &amp; hardDelete</h1>
<h2 id="soft-delete와-hard-deletecascade-delete의-차이점">Soft Delete와 Hard Delete(Cascade Delete)의 차이점</h2>
<h4 id="soft-delete-실제로-데이터를-db에서-삭제하는-것이-아니라-삭제된-것처럼-보이게-하는-방법">Soft Delete: 실제로 데이터를 DB에서 삭제하는 것이 아니라, 삭제된 것처럼 보이게 하는 방법</h4>
<ul>
<li>일반적으로 &#39;isDeleted&#39; 나 &#39;deletedAt&#39; 같은 필드를 추가하여, 이 필드를 통해 데이터가 삭제된 것처럼 처리, 실제 데이터는 그대로 남아 있기 때문에, 필요한 경우 복구가 가능</li>
<li>사용자가 실수로 데이터를 삭제한 경우나, 삭제된 데이터의 히스토리를 유지해야 하는 경우, 데이터를 &quot;삭제&quot;하고 싶을 때 사용</li>
<li>데이터의 무결성을 유지<h4 id="hard-deletecascade-delete-해당-데이터와-관련된-모든-참조를-함께-삭제해-데이터를-db에서-완전히-삭제하는-방법">Hard Delete(Cascade Delete): 해당 데이터와 관련된 모든 참조를 함께 삭제해 데이터를 DB에서 완전히 삭제하는 방법</h4>
</li>
<li>cascade를 사용</li>
<li>데이터를 완전히 제거해야 하거나, 데이터 저장 공간을 확보해야 하는 경우, 데이터가 다른 테이블과 복잡하게 연결되어 있고, 이 데이터를 삭제하면 연결된 모든 데이터를 함께 삭제해야 하는 경우에 사용</li>
</ul>
<p><code>두 방식을 동시에 사용하는 것도 가능하다. 예를 들어, 일반적인 삭제 작업에는 Soft Delete를 사용하고, 특정 조건을 만족하는 데이터는 Hard Delete를 사용하는 방식있다.</code></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[2024-01-07[WIL]]]></title>
            <link>https://velog.io/@jn2o_o2/2024-01-07WIL</link>
            <guid>https://velog.io/@jn2o_o2/2024-01-07WIL</guid>
            <pubDate>Sun, 07 Jan 2024 11:37:41 GMT</pubDate>
            <description><![CDATA[<h1 id="nosql--sql">NOSQL &amp; SQL</h1>
<h2 id="sqlstructured-query-language">SQL(Structured Query Language)</h2>
<p>:SQL(Structured Query Language)은 관계형 데이터베이스에 정보를 저장하고 처리하기 위한 프로그래밍 언어</p>
<ul>
<li><p>관계형데이터베이스는 정보를 표 형식으로 저장하며, 행과 열은 다양한 데이터 속성과 데이터 값 간의 다양한 관계를 나타낸다(테이블 형식으로 데이터를 저장하며, 각 테이블은 고유한 데이터 필드(열) 세트를 가진다. 테이블 간에는 관계를 설정할 수 있으며, 이를 통해 복잡한 쿼리와 분석을 수행할 수 있다)</p>
</li>
<li><p>구조화된 쿼리 언어(SQL)를 사용: SQL을 사용하면 강력한 쿼리를 작성할 수 있고 데이터 조작 및 정의 언어를 포함한 많은 기능을 제공한다.</p>
</li>
<li><p>스키마 기반: 데이터는 테이블에 미리 정의된 스키마에 따라 저장된다. 스키마는 데이터의 구조(데이터 타입, 값의 유무 등)를 정의한다.</p>
</li>
<li><p>ACID 트랜잭션: SQL 데이터베이스는 원자성(Atomicity), 일관성(Consistency), 고립성(Isolation), 지속성(Durability)을 보장하는 ACID 트랜잭션을 지원한다.</p>
</li>
</ul>
<h2 id="nosqlnot-only-sql">NOSQL(Not Only SQL)</h2>
<p>:NoSQL(Not Only SQL)은 테이블을 사용하여 데이터를 저장하지 않는 비관계형 데이터베이스</p>
<p><code>NoSQL 데이터베이스는 대규모 데이터 집합을 저장하고 분석하는 데 유용하며, 키-값 쌍, 넓은 열, 그래프 또는 문서와 같이 다양한 데이터 모델을 지원한다</code></p>
<ul>
<li>스키마 없음: NoSQL 데이터베이스는 유연한 데이터 모델을 지원하므로, 애플리케이션의 요구 사항에 따라 데이터를 저장하고 검색할 수 있다.</li>
<li>수평적 확장성: NoSQL 데이터베이스는 데이터를 여러 서버에 분산시키는 데 효과적이다. 이로 인해 데이터베이스는 많은 양의 트래픽과 데이터를 처리할 수 있다.</li>
<li>BASE 트랜잭션: NoSQL 데이터베이스는 일반적으로 ACID 트랜잭션 대신 BASE(Basically Available, Soft state, Eventually consistent) 트랜잭션을 지원한다.</li>
</ul>
<p>정형화된 데이터와 복잡한 쿼리를 다루는 경우 SQL이 적합할 수 있으며, 대규모의 비정형 데이터를 다루는 경우 NoSQL이 더 적합할 수 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[2024-01-06[TIL]]]></title>
            <link>https://velog.io/@jn2o_o2/2024-01-06TIL</link>
            <guid>https://velog.io/@jn2o_o2/2024-01-06TIL</guid>
            <pubDate>Sat, 06 Jan 2024 02:23:27 GMT</pubDate>
            <description><![CDATA[<h1 id="prisma-schema와-database">prisma schema와 database</h1>
</br>

<ul>
<li>Prisma 스키마에서 우리가 정의하는 모델과 필드 이름은, 우리가 Node.js 코드 상에서 데이터베이스를 다룰 때 사용하는 이름</li>
<li>데이터베이스의 컬럼 이름은 보통 스네이크 케이스(snake_case)를 사용하는데 반해, JavaScript나 TypeScript에서는 카멜 케이스(camelCase)를 주로 사용</li>
<li>데이터베이스의 구조나 이름이 변경되더라도 Prisma 스키마의 이름을 그대로 유지하기 때문에 @map과 @@map으로 컬럼명과 데이터베이스명을 스키마에서 사용하는 컬럼명과 테이블명을 다르게 해주는게 좋다(데이터베이스의 변경사항이 코드에 미치는 영향을 최소화)</li>
<li>코드와 데이터베이스 사이의 독립성을 유지하면서 이름 규칙의 일관성을 유지할 수 있다는 장점으로 컬럼명이나 테이블명을 스키마나 데이터베이스에서 똑같이 사용한다 해도 @map이나 @@map을 사용하는게 좋다</li>
</ul>
<pre><code>@map(&#39;데이터베이스에서 사용될 컬럼명&#39;)
@@map(&#39;데이터베이스에서 사용될 테이블명&#39;)</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[2023-01-04[TIL]]]></title>
            <link>https://velog.io/@jn2o_o2/2023-01-00TIL</link>
            <guid>https://velog.io/@jn2o_o2/2023-01-00TIL</guid>
            <pubDate>Thu, 04 Jan 2024 13:28:00 GMT</pubDate>
            <description><![CDATA[<h1 id="aws-s3-적용하기">AWS S3 적용하기</h1>
<h3 id="aws에서-s3-버킷-생성-후-코드-적용하기">aws에서 s3 버킷 생성 후 코드 적용하기</h3>
<p>&quot;@aws-sdk/client-s3&quot;: &quot;^3.484.0&quot;, 이 모듈을 깔면 
아래 에러가 난다</p>
<pre><code>TypeError: this.client.send is not a function
    at Upload.__uploadUsingPut</code></pre><p>안깔고 없애면 아래 에러가 뜨고</p>
<pre><code>Error: Cannot find module &#39;@aws-sdk/client-s3’</code></pre><blockquote>
<p>@aws-sdk/client-s3 이 모듈은 지워야 했었고 모듈 버전 호환 문제로 aws-sdk랑 multer-s3랑 버전이 2든 3이든 같아야된다고 해서 yarn add <a href="mailto:multer-s3@2.10.0">multer-s3@2.10.0</a> 해줌</p>
</blockquote>
</br>

<p><strong>버킷 이름이나 그 외 키 설정 등이 안 맞으면 생기는 오류</strong></p>
<pre><code>NoSuchBucket: The specified bucket does not exist</code></pre></br>

<p><strong>aws s3 버킷에서 객체 소유권에 acl활성화 시켜주지 않아서 생기는 오류</strong></p>
<pre><code>AccessControlListNotSupported: The bucket does not allow ACLs
    at Request.extractError </code></pre></br>

<h3 id="aws-iam-설정">AWS IAM 설정</h3>
<p>IAM 이란 Identity and Access Management의 약자로 , AWS 리소스에 대한 액세스를 안전하게 제어할 수 있는 웹 서비스다.
IAM을 사용하여 리소스를 사용하도록 인증(로그인) 및 권한 부여(권한 있음)된 대상을 제어한다.
</br></p>
<p>참고
<a href="https://github.com/anacronw/multer-s3#readme">https://github.com/anacronw/multer-s3#readme</a>
<a href="https://whitemackerel.tistory.com/50">https://whitemackerel.tistory.com/50</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[2024-01-01[WIL]]]></title>
            <link>https://velog.io/@jn2o_o2/2024-01-01WIL</link>
            <guid>https://velog.io/@jn2o_o2/2024-01-01WIL</guid>
            <pubDate>Mon, 01 Jan 2024 07:01:12 GMT</pubDate>
            <description><![CDATA[<h1 id="express-middleware">EXPRESS MIDDLEWARE</h1>
<h2 id="express란">express란?</h2>
<p>: Node.js로 서버를 빠르고 간편하게 만들 수 있게 도와주는 웹 프레임워크입니다</p>
<h3 id="장점">장점</h3>
<ul>
<li><p>웹 애플리케이션에 필요한 라우팅 기능을 간결하고 유연하게 제공합니다. HTTP 메서드(GET, POST, PUT, DELETE 등)와 URL 경로에 따라 요청을 효과적으로 처리할 수 있습니다.</p>
</li>
<li><p>middleware: 미들웨어 기능을 통해 요청과 응답 사이의 중간 처리 과정을 사용자가 원하는 대로 조작하거나 확장할 수 있습니다. 이는 애플리케이션의 기능을 모듈화하고 재사용하는데 매우 유용합니다.</p>
</li>
<li><p>Template engine: 다양한 템플릿 엔진을 지원하여 서버 사이드에서 HTML을 동적으로 생성하고 클라이언트에게 전달할 수 있습니다.</p>
</li>
<li><p>error handling: 미들웨어를 이용한 오류 핸들링 기능을 제공합니다</p>
</li>
</ul>
<h2 id="middleware">middleware</h2>
<p>: 클라이언트로부터 받은 요청에 대한 응답을 하기 전 중간에서 목적에 맞는 특정 작업을 수행하는 함수들을 말합니다</p>
<ul>
<li>다음 미들웨어 함수에 대한 엑세스는 next 함수를 이용해서 다음 미들웨어로 현재 요청을 점길 수 있습니다</li>
<li>req, res, next를 매개변수로 가지는 함수로써 app.use나 app.get, app.post로 쓰인다 (에러 처리 미들웨어는err, req, res, next)<pre><code class="language-javascript">app.use(
  morgan(&#39;dev&#39;),
  express.static(&#39;/&#39;, path.join(__dirname, &#39;public&#39;)),
  express.json(),
  express.urlencoded({ extended: false }),
  cookieParser(process.env.COOKIE_SECRET)
);</code></pre>
위 미들웨어들은 내부적으로 next를 호출하므로 연달아 쓸 수 있다.</li>
</ul>
<p><del>express 미들웨어 패키지 종류 검색해보기</del></p>
<p>참고
<a href="https://inpa.tistory.com/entry/EXPRESS-%F0%9F%93%9A-%EB%AF%B8%EB%93%A4%EC%9B%A8%EC%96%B4-%F0%9F%92%AF-%EC%9D%B4%ED%95%B4-%EC%A0%95%EB%A6%AC#%E2%9A%A0%EF%B8%8F_%EB%87%8C%EC%A0%95%EC%A7%80_%EB%8B%B9%ED%95%98%EA%B8%B0%EC%A0%84%EC%9D%98_%EC%98%88%EB%B0%A9%EC%A7%80%EC%8B%9D">https://inpa.tistory.com/entry/EXPRESS-%F0%9F%93%9A-%EB%AF%B8%EB%93%A4%EC%9B%A8%EC%96%B4-%F0%9F%92%AF-%EC%9D%B4%ED%95%B4-%EC%A0%95%EB%A6%AC#%E2%9A%A0%EF%B8%8F_%EB%87%8C%EC%A0%95%EC%A7%80_%EB%8B%B9%ED%95%98%EA%B8%B0%EC%A0%84%EC%9D%98_%EC%98%88%EB%B0%A9%EC%A7%80%EC%8B%9D</a></p>
<h1 id="restful">RESTFUL</h1>
<p>:웹 서비스의 설계 방식 중 하나로, REST(REpresentational State Transfer) 설계 원칙을 따르는 것을 의미합니다. </p>
<h2 id="rest">REST</h2>
<p>: HTTP URL을 통해 자원을 명시하고 HTTP Method를 통해 명시한 자원에 대한 CRUD를 적용합니다. </p>
<h3 id="특징">특징</h3>
<ul>
<li>클라이언트-서버 구조(Client-server architectur): 클라이언트와 서버는 서로 독립적이며, 각각의 역할이 분리되어 있습니다. 이를 통해 클라이언트와 서버는 각자의 개발을 독립적으로 진행할 수 있습니다.</li>
<li>무상태성(Stateless): 각 요청은 서버에 저장된 이전 요청과는 독립적입니다. 즉, 각 요청이 서버에 필요한 모든 정보를 포함하고 있어야 합니다.</li>
<li>캐시 가능(Cacheable): 클라이언트는 응답을 캐시할 수 있어야 합니다. 이를 통해 네트워크 부하를 줄이고 성능을 향상시킬 수 있습니다.</li>
<li>계층화된 시스템(Layered System): 클라이언트는 네트워크 아키텍처의 여러 계층을 알 필요가 없습니다. 중간 계층(예: 로드 밸런서)이 존재하더라도, 클라이언트는 서버와 직접 통신하는 것처럼 요청을 보낼 수 있습니다.</li>
<li>Uniform Interface: REST는 일관된 인터페이스를 통해 자원을 조작합니다. 이는 HTTP 표준 메서드(GET, POST, PUT, DELETE 등)를 사용하고, 자원을 식별하는 URL, 자원의 표현(예: JSON, XML)을 사용합니다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[2023-12-29[TIL]]]></title>
            <link>https://velog.io/@jn2o_o2/2023-12-29TIL</link>
            <guid>https://velog.io/@jn2o_o2/2023-12-29TIL</guid>
            <pubDate>Fri, 29 Dec 2023 02:09:02 GMT</pubDate>
            <description><![CDATA[<h1 id="배포-과정">배포 과정</h1>
<p>리눅스 시스템에서는 1024 이하의 포트를 사용하려면 관리자 권한이 필요하므로, 특이사항이 없다면 <strong>2000 이상의 포트 번호를 사용</strong></p>
<p>프로젝트를 만든 후, 깃에 연결해서 올리는 방법은 다음과 같다. (<code>.gitignore</code>를 추가하는 것을 잊지말기)</p>
<ol>
<li>git init</li>
<li>git remote add origin &lt;github 페이지에 나오는 주소&gt;</li>
<li>git에 프로젝트 올려주기</li>
<li>aws ec2 인스턴스 생성(키페어는 한번 발급 받았으면 새로 발급받지 않아도됨)</li>
<li>git bash로 ec2 접속하기 (ssh -i 받은키페어를끌어다놓기 ubuntu@AWS에적힌내아이피)</li>
<li>node.js 설치</li>
<li>git clone https주소 후 <strong>프로젝트 생성된 폴더로 위치 이동</strong></li>
<li>yarn을 사용하기 위해, 전역으로 yarn을 설치</li>
<li>원격 저장소로 부터 가져온 프로젝트의 의존성 및 패키지를 설치</li>
<li>프로젝트를 실행</li>
<li>pm2를 활용한 node 무중단 서비스 사용</li>
</ol>
<h1 id="ssh-설정">ssh 설정</h1>
<pre><code class="language-jsx">Host *
  AddKeysToAgent yes
  UseKeychain yes
  IdentityFile ~/.ssh/id_ed25519</code></pre>
<p><code>Host *</code>: 이 설정이 모든 호스트(<code>*</code>로 표시)에 적용되어야 함을 나타냅니다. ⇒ github</p>
<p><code>AddKeysToAgent yes</code>: ssh-agent에 키를 자동으로 추가하도록 설정. ssh-agent는 사용자 대신 개인 키를 보관하고, 원격 호스트에 대한 인증 요청을 처리하는 프로그램</p>
<p><code>UseKeychain yes</code>: macOS에서만 사용되며, 시스템 키체인에 비밀번호를 저장하도록 설정</p>
<p><code>IdentityFile ~/.ssh/id_ed25519</code>: 사용할 개인 키의 위치를 지정</p>
<ol>
<li><p>새로운 SSH 키를 생성</p>
<pre><code class="language-jsx">ssh-keygen -t ed25519 -C &quot;your_email@example.com&quot;</code></pre>
</li>
<li><p>SSH key 생성 여부 확인하기</p>
</li>
</ol>
<pre><code class="language-jsx">ls -al ~/.ssh</code></pre>
<p>~/.ssh/id_ed25519 와 ~/.ssh/id_ed25519.pub 파일이 생성됨</p>
</br>

<h1 id="우분투에-환경변수-설정하기">우분투에 환경변수 설정하기</h1>
<p>환경변수를 설정하는 방법에 대해 설명하겠습니다. 여기서는 <code>DATABASE_URL</code> 환경변수를 예로 들겠습니다.</p>
<h2 id="환경변수-설정-방법">환경변수 설정 방법</h2>
<ol>
<li><p>우분투 서버에 로그인합니다.</p>
</li>
<li><p>사용자의 bash 프로필 파일인 <code>~/.bashrc</code>을 연다. 이 파일에 환경 변수를 추가할 것입니다.</p>
<pre><code class="language-bash"> nano ~/.bashrc</code></pre>
</li>
<li><p><code>~/.bashrc</code> 파일의 맨 아래에 원하는 환경 변수를 추가합니다.</p>
<pre><code class="language-bash"> export DATABASE_URL=your_database_url</code></pre>
</li>
<li><p>변경사항을 저장하고 편집기를 종료합니다.</p>
</li>
<li><p>변경사항을 적용하기 위해 터미널을 재시작하거나 아래의 명령어를 실행합니다.</p>
<pre><code class="language-bash"> source ~/.bashrc</code></pre>
</li>
<li><p><code>echo $DATABASE_URL</code> 명령을 실행해서 환경 변수가 제대로 설정되었는지 확인합니다.</p>
</li>
</ol>
<blockquote>
<p>이 방법은 사용자의 bash 세션마다 환경 변수가 설정되기 때문에, 서버가 재시작되거나 사용자가 로그아웃하면 환경 변수 설정이 사라집니다.</p>
</blockquote>
<hr>
<p><strong>참고:</strong> 서버 전체에서 사용할 환경 변수를 설정하려면 <code>/etc/environment</code> 파일에 환경 변수를 추가할 수 있습니다. 이 파일에 환경 변수를 추가하는 방법은 <code>~/.bashrc</code> 파일에 환경 변수를 추가하는 방법과 동일합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[2023-12-28[TIL]]]></title>
            <link>https://velog.io/@jn2o_o2/2023-12-28TIL</link>
            <guid>https://velog.io/@jn2o_o2/2023-12-28TIL</guid>
            <pubDate>Thu, 28 Dec 2023 13:32:13 GMT</pubDate>
            <description><![CDATA[<h1 id="mongodb">MongoDB</h1>
<p>비관계형 데이터베이스 - NonRelationalDatabase(NoSQL):</p>
<ul>
<li>데이터 형식이 공정되어 있지 않고 유연하게 확장 가능</li>
<li>데이터가 JSON형태로 저장</li>
<li>복잡한 데이터 구조 쉽게 저장할 수 있는 장점
  -&gt; 대용량 데이터를 쉽게 처리</li>
<li>데이터베이스 서버의 확장을 쉽게 늘리고 줄이기 가능
  -&gt; 서버 부하가 늘어나도 빠르게 대응</br>

</li>
</ul>
<h3 id="mongoose를-통해서-데이터를-삽입하면-__v--필드가-생김--버전키기본값은-0"><strong>mongoose를 통해서 데이터를 삽입하면 &#39;__v &#39; 필드가 생김 =&gt; 버전키(기본값은 0)</strong></h3>
</br>

<p><strong>삭제방법(versionKey: false)</strong></p>
<pre><code class="language-javascript">const Schema = new Schema({
   title: { type: String, required: true},
   content: { type: Date, default: Date.now },
   status: { type: String, default: &quot;active&quot; }
},{
   versionKey: false
});
</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[2023-12-27[TIL]]]></title>
            <link>https://velog.io/@jn2o_o2/2023-12-00TIL-sdt8esae</link>
            <guid>https://velog.io/@jn2o_o2/2023-12-00TIL-sdt8esae</guid>
            <pubDate>Wed, 27 Dec 2023 06:09:57 GMT</pubDate>
            <description><![CDATA[<h1 id="reqquery">req.query</h1>
<p>url의 물음표 이후에 오는 key=value 형태의 파라미터로 전달
ex) /search?keyword=apple&amp;page=1 =&gt; keyword와 page는 key이고, apple과 1은 value이며 &#39;&amp;&#39; 기호로 여러개의 쿼리 매개변수를 구분</p>
<h1 id="param-query">param, query</h1>
<p><strong>req.params</strong></p>
<ul>
<li>일반적으로 동적인 부분에 대한 데이터를 가져올 때 사용</li>
<li>users/:id에서 :id는 개별 사용자의 id값을 나타내며 주로 하나의 값을 가져오는데 사용</li>
</ul>
<p><strong>req.query</strong></p>
<ul>
<li>Key=value 형태로 URL에 여러개의 매개변수와 그 값을 전달할 때 사용</li>
<li>필터링, 정렬, 페이지네이션 과 같은 다양한 옵션 적용 시 사용</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[2023-12-26[TIL]]]></title>
            <link>https://velog.io/@jn2o_o2/2023-12-26TIL</link>
            <guid>https://velog.io/@jn2o_o2/2023-12-26TIL</guid>
            <pubDate>Tue, 26 Dec 2023 13:02:43 GMT</pubDate>
            <description><![CDATA[<h1 id="깃허브-ssh-키-생성-이유">깃허브 ssh 키 생성 이유</h1>
<ul>
<li><p>ssh를 이용하면 깃허브에 접속할 때마다 사용자 이름과 비밀번호를 입력하지 않아도 되며, ssh키는 개인키와 공개키의 쌍으로 이루어져 있어 보안성이 높음</p>
</li>
<li><p>깃허브를 이용할 때 사용의 편의성과 보안성을 높이기 위한 것
(다만, 리눅스와 같은 터미널 환경에서 ssh키를 생성하고 관리하는데 사용되는 명령어가 잘 구비되어 있어 잘 사용됨)</p>
</li>
</ul>
</br>

<h1 id="git-init">git init</h1>
<p>: 새로운 git 저장소를 초기화 하는데 사용되는 명령어</p>
<ul>
<li><p>이미 초기화된 git 저장소에서 작업하는 경우 git init명령을 사용할 필요없음</p>
</li>
<li><p>git clone 명령을 사용하여 원격 저장소를 로컬에 복제하는 경우도 이미 git 저장소가 초기화되어 있기 때문에 git init 할 필요없음</p>
</li>
<li><p>아직 git 관리 하에 있지 않는 프로젝트들을 git으로 관리하려는 경우 해당 디렉토리에서 git init명령을 실행하여 git 저장소를 초기화 해야함</p>
</li>
</ul>
<p>따라서 git init 명령의 사용 여부는 작업 상황에 따라 다름</p>
</br>

<h1 id="git-clone과-remote-차이">git clone과 remote 차이</h1>
<ul>
<li>git clone<ul>
<li>원격 저장소의 모든 내용(파일, 커밋 히스토리 등)을 복제하여 새로운 로컬 저장소를 생성할 때 사용</li>
<li>모든 내용들이 로컬에 복제 되고 원격 저장소가 자동으로 origin이라는 이름으로 remote에 등록 됨</li>
</ul>
</li>
<li>git remote<ul>
<li>기존 로컬 git 저장소를 연결할 때 사용</li>
<li>이미 git init으로 초기화된 로컬 git 저장소를 원격 저장소로 연결하는 경우</li>
</ul>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[2023-12-24[WIL]]]></title>
            <link>https://velog.io/@jn2o_o2/2023-12-24WIL</link>
            <guid>https://velog.io/@jn2o_o2/2023-12-24WIL</guid>
            <pubDate>Sun, 24 Dec 2023 14:22:12 GMT</pubDate>
            <description><![CDATA[<h1 id="페어프로그래밍-경험">페어프로그래밍 경험</h1>
<p>진도가 안 맞는 이유로 네비게이터만 진행한게 아쉬웠고 팀원들이 잘 할 수도 있도록 이끌어주는 일이 쉬운게 아니라는걸 깨달았다</p>
<h1 id="향상방안">향상방안</h1>
<p>알고리즘문제 꾸준히 풀면서 오답노트 작성하기</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[2023-12-22[TIL]]]></title>
            <link>https://velog.io/@jn2o_o2/2023-12-22TIL</link>
            <guid>https://velog.io/@jn2o_o2/2023-12-22TIL</guid>
            <pubDate>Fri, 22 Dec 2023 07:45:19 GMT</pubDate>
            <description><![CDATA[<h1 id="algorithm">ALGORITHM</h1>
<p><strong>문제)</strong>
// 문자열 s에는 공백으로 구분된 숫자들이 저장되어 있습니다.
// 현지는 s에 나타나는 숫자 중 소수의 최대값과
// 소수가 아닌 수의 최소값을 찾아
// 이를 &quot;(최소값) (최대값)&quot;형태의 문자열을 반환하는 함수, solution을 완성하려고 합니다.</p>
<p>// 예를들어 s가 &quot;2 3 4 5&quot;라면 &quot;4 5&quot;를 리턴하고, &quot;15 3 10 9 7 8&quot;라면 &quot;8 7&quot;을 리턴하면 됩니다.</p>
<p>// - s에는 둘 이상의 정수가 공백으로 구분되어 있습니다.
// - 문자열에는 소수가 한개 이상 섞여 있습니다.
// - 문자열에는 소수가 아닌 수가 한개 이상 섞여 있습니다.
// - 음수는 없습니다.</p>
<p><strong>혼자 생각한 풀이과정</strong></p>
<pre><code class="language-javascript">// 소수란: 1과 자기 자신만을 약수로 가지는 수
// 소수임을 증명하는 계산법: 
// i를 아직 쓸수 없기에 nums의 길이만큼 돌리고 그 안에서 빈 배열을 선언한 배열의 길이만큼 반복 해주면서
// 중접으로 다음 for 반복문을 아래처럼 이용한다(i=&gt; j)
//for문으로 i= 2부터 (1과 자기 자신만을 이라고 했으니 1은 당연히 나눠지는, 계산을 조금이라도 덜 하기 위해?..)
// i가 해당숫자보다 작을 때까지 반복 하면서 해당숫자 나누기 i를 했을 때 나머지가 0이 되는 수가 있다면
//  그 해당 숫자는 소수가 아니다
// 소수인 수 배열과 소수가 아닌 수의 빈 배열을 선언해두고 차곡차곡 넣는다
//  소수인 수 들 중 최대값과 소수가 아닌 수의 최소값을 반환

 function solution(s){
      let nums = s.split(&#39; &#39;).map(Number)
     let isPrime = []
     let notPrime = []
     for( let i = 0; i &lt; nums.length; i++){
         for (let j = 2; j &lt; nums[i]/2; j++){
             if(nums[i]%j === 0){
                 notPrime.push(nums[i])
             } else {
                 isPrime.push(nums[i])
             }
         }
     }
     console.log(&quot;isPrime&quot;, isPrime)
     console.log(&quot;notPrime&quot;, notPrime)

     let answer = 0

     return answer

 }
let s=&quot;97 75 88 99 95 92 73&quot;;
console.log(solution(s))

// let s=&quot;97 75 88 99 95 92 73&quot;; //&quot;75 97&quot;
// let s=&quot;15 3 10 9 7 8&quot;; &quot;8 7&quot; 
// let s=&quot;2 3 4 5&quot;; &quot;4 5&quot;</code></pre>
</br>

<p><strong>생각 못 한 부분</strong></p>
<pre><code class="language-javascript">// for 안에서 push(nums[i])를 해주면 반복하고 있는 중이라 돌아가는 만큼 push에 찍히게 됨
// if 안에서 소수가 아닌지만 체크해주고 멈춰서 if문을 빠져나오게 한 뒤 맨안쪽 for문도 빠져나와
// 첫번째 for문 안에 있는 if문으로 들어간다 isPrimeCheck가 false로 저장되면 notPrime으로 들어갈것// 
// isPrimeCheck에서 기본초기값을 true로 해두고 if에 조건이 맞는 nums[i]에 대해 isPrimeCheck = false면
// // break로 if문과 두번째 for문을 빠져나오게 된다 첫번째 for문에서 isPrimeCheck가 true가 아니라서 notPrime으로 push된다
function solution(s){
    let nums = s.split(&#39; &#39;).map(Number)
    let isPrime = []
    let notPrime = []
    for( let i = 0; i &lt; nums.length; i++){
        let isPrimeCheck = true;
        for (let j = 2; j &lt;= nums[i]/2; j++){
            if(nums[i]%j === 0){
                isPrimeCheck = false
                break;
            }
        }
        // 1은 소수가 아니라서?
        if(isPrimeCheck &amp;&amp; nums[i] &gt; 1){
            isPrime.push(nums[i])
        } else {
            notPrime.push(nums[i])
        }
    }

    // console.log(&quot;isPrime&quot;, isPrime)
    // console.log(&quot;notPrime&quot;, notPrime)

    let max = Math.max(...isPrime)
    let min = Math.min(...notPrime)

    // console.log(&quot;max&quot;, max);
    // console.log(&quot;min&quot;, min);

    let answer = `${min} ${max}`

    return answer

}
let s=&quot;2 3 4 5&quot;;
console.log(solution(s))


// let s=&quot;97 75 88 99 95 92 73&quot;; //&quot;75 97&quot;
// let s=&quot;15 3 10 9 7 8&quot;; &quot;8 7&quot; 
// let s=&quot;2 3 4 5&quot;; &quot;4 5&quot;</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[2023-12-20[TIL]]]></title>
            <link>https://velog.io/@jn2o_o2/2023-12-20TIL</link>
            <guid>https://velog.io/@jn2o_o2/2023-12-20TIL</guid>
            <pubDate>Wed, 20 Dec 2023 08:36:33 GMT</pubDate>
            <description><![CDATA[<h1 id="algorithm">ALGORITHM</h1>
<p><strong>문자열 내림차순 배치</strong></p>
<pre><code class="language-JAVASCRIPT">function solution(s) {
    var answer = &#39;&#39;;

    // answer.sort((a, b) =&gt; a-b) :이런식으로 정렬하는건 숫자만 가능 
    //문자는 sort()로 유니코드 값을 기준으로 정렬

    //join은 새로운 문자열을 반환하지만 원래의 배열을 변경하지 않기 때문에 그 결과를 변수에 다시 할당해야함
    // answer = s.split(&#39;&#39;)
    // answer.sort().reverse().join(&#39;&#39;)
    // 그래서 아래 처럼 answer를 재할당해줄 때 join을 해줬음
    // 재할당하지 않으면?? join이 안됨

    answer = s.split(&#39;&#39;).sort().reverse().join(&#39;&#39;)
    return answer;
}

console.log(solution(&quot;Zbcdefg&quot;));</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[2023-12-19[TIL]]]></title>
            <link>https://velog.io/@jn2o_o2/2023-12-19TIL-qm69yte7</link>
            <guid>https://velog.io/@jn2o_o2/2023-12-19TIL-qm69yte7</guid>
            <pubDate>Tue, 19 Dec 2023 01:27:44 GMT</pubDate>
            <description><![CDATA[<h1 id="algorithm">ALGORITHM</h1>
<p><strong>콜라츠 추측 여러가지 풀이법</strong></p>
<pre><code class="language-javascript">//&lt;방법1&gt;
function collatz(num) {
    var answer = 0;
    while(num !=1 &amp;&amp; answer !=500){
        num%2==0 ? num = num/2 : num = num*3 +1;
    answer++;
  }
    return num == 1 ? answer : -1;
}

//&lt;방법2&gt;
function solution(num) {
    var count = 0;

    while (count &lt; 500) {
        if (num === 1) {
            return count;
        }
        count ++;
        num = num % 2 === 0 ? num /2 : num *3 +1;
    }

    return -1;
}

//&lt;방법3&gt;
function collatz(num,count = 0) {
    return num == 1 ? (count &gt;= 500 ? -1 : count) : collatz(num % 2 == 0 ? num / 2 : num * 3 + 1,++count);
}</code></pre>
]]></description>
        </item>
    </channel>
</rss>