<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>sh_j225.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Thu, 14 Sep 2023 11:38:07 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>sh_j225.log</title>
            <url>https://velog.velcdn.com/images/sh_j225/profile/14416700-371e-472c-b275-916c07d2f808/image.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. sh_j225.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/sh_j225" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[데이터로부터 동적 좌석 레이아웃 그리기]]></title>
            <link>https://velog.io/@sh_j225/%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%A1%9C%EB%B6%80%ED%84%B0-%EB%8F%99%EC%A0%81-%EC%A2%8C%EC%84%9D-%EB%A0%88%EC%9D%B4%EC%95%84%EC%9B%83-%EA%B7%B8%EB%A6%AC%EA%B8%B0</link>
            <guid>https://velog.io/@sh_j225/%EB%8D%B0%EC%9D%B4%ED%84%B0%EB%A1%9C%EB%B6%80%ED%84%B0-%EB%8F%99%EC%A0%81-%EC%A2%8C%EC%84%9D-%EB%A0%88%EC%9D%B4%EC%95%84%EC%9B%83-%EA%B7%B8%EB%A6%AC%EA%B8%B0</guid>
            <pubDate>Thu, 14 Sep 2023 11:38:07 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/sh_j225/post/64bf2fa3-ece1-4205-98a9-c55c4fdfcfd3/image.png" alt=""></p>
<h2 id="반복문을-사용한-동적-생성">반복문을 사용한 동적 생성</h2>
<h4 id="1-주어진-seatshape-2차원-배열의-각-요소를-순회하여-행과-열을-기반으로-좌석-레이아웃을-구성한다">1. 주어진 seatShape (2차원 배열)의 각 요소를 순회하여 행과 열을 기반으로 좌석 레이아웃을 구성한다.</h4>
<h4 id="2-외부-for-반복문은-행row을-처리하고-내부-for-반복문은-열column을-처리한다">2. 외부 for 반복문은 행(row)을 처리하고, 내부 for 반복문은 열(column)을 처리한다.</h4>
<h2 id="html-요소-동적-생성">HTML 요소 동적 생성</h2>
<h4 id="1-각-행에-대한-div-요소를-생성하고-row라는-클래스-이름을-부여한다">1. 각 행에 대한 div 요소를 생성하고, &#39;row&#39;라는 클래스 이름을 부여한다.</h4>
<h4 id="2-이를-통해-각-행을-시각적으로-구분할-수-있다">2. 이를 통해 각 행을 시각적으로 구분할 수 있다.</h4>
<h2 id="데이터에서-좌석-정보-찾기">데이터에서 좌석 정보 찾기</h2>
<h4 id="1-seatdataseatsfind를-사용하여-현재-행과-열에-해당하는-좌석-정보를-찾는다">1. seatData.seats.find(...)를 사용하여 현재 행과 열에 해당하는 좌석 정보를 찾는다.</h4>
<h4 id="2seatdata는-api나-다른-데이터-소스로부터-가져온-좌석에-관한-정보를-담고-있다">2.seatData는 API나 다른 데이터 소스로부터 가져온 좌석에 관한 정보를 담고 있다.</h4>
<h2 id="좌석-정보를-기반으로-좌석-요소-설정">좌석 정보를 기반으로 좌석 요소 설정</h2>
<h4 id="1-seatinfo를-사용하여-각-좌석의-상태예약-가능-예약-불가-등와-관련된-클래스를-설정한다">1. seatInfo를 사용하여 각 좌석의 상태(예약 가능, 예약 불가 등)와 관련된 클래스를 설정한다.</h4>
<h4 id="2-각-좌석에-대한-추가-정보예-좌석-번호도-이를-기반으로-설정한다">2. 각 좌석에 대한 추가 정보(예: 좌석 번호)도 이를 기반으로 설정한다.</h4>
<h2 id="결론">결론:</h2>
<p>데이터 기반으로 동적 웹 요소를 생성하고 조작하는 방법을 통해, 실시간으로 변화하는 정보를 웹 페이지에 반영할 수 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[MongoDB vs MySQL - 어떤 것을 선택해야 할까?]]></title>
            <link>https://velog.io/@sh_j225/MongoDB-vs-MySQL-%EC%96%B4%EB%96%A4-%EA%B2%83%EC%9D%84-%EC%84%A0%ED%83%9D%ED%95%B4%EC%95%BC-%ED%95%A0%EA%B9%8C</link>
            <guid>https://velog.io/@sh_j225/MongoDB-vs-MySQL-%EC%96%B4%EB%96%A4-%EA%B2%83%EC%9D%84-%EC%84%A0%ED%83%9D%ED%95%B4%EC%95%BC-%ED%95%A0%EA%B9%8C</guid>
            <pubDate>Thu, 07 Sep 2023 00:37:54 GMT</pubDate>
            <description><![CDATA[<p>오늘, 우리는 두 대표적인 데이터베이스, MongoDB와 MySQL에 대해 깊게 토론해 보았다. 각 데이터베이스의 특성과 장단점을 비교해 보면서 어떤 상황에서 어떤 데이터베이스를 선택하는 것이 좋은지에 대한 인사이트를 얻을 수 있었다.</p>
<h3 id="mongodb-nosql">MongoDB (NoSQL)</h3>
<h4 id="장점">장점:</h4>
<p>유연한 스키마: 데이터 모델을 유연하게 조정할 수 있어, 빠르게 변화하는 데이터 요구사항에 잘 대응할 수 있다.
확장성: 대량의 데이터와 트래픽을 처리하기 위해 수평적으로 확장이 가능하다.
JSON 형태의 데이터 저장: 개발자들이 친숙한 JSON 형태로 데이터를 저장하고 조회할 수 있어 개발이 편리하다.</p>
<h4 id="단점">단점:</h4>
<p>정규화가 없음: 중복 데이터가 발생할 수 있으며, 데이터 무결성을 유지하는 것이 어려울 수 있다.
트랜잭션의 제한: 복잡한 트랜잭션 처리가 제한적일 수 있다.</p>
<h3 id="mysql-rdbms">MySQL (RDBMS)</h3>
<h4 id="장점-1">장점:</h4>
<p>데이터 무결성: 정규화 덕분에 데이터의 중복을 방지하고 무결성을 유지할 수 있다.
복잡한 쿼리: JOIN 연산 등 복잡한 쿼리를 사용하여 다양한 방식으로 데이터를 조회할 수 있다.
검증된 안정성: 오랜 시간 동안 많은 조직에서 사용되어 안정성과 성능이 검증되었다.</p>
<h4 id="단점-1">단점:</h4>
<p>수직 확장: 대규모의 데이터와 트래픽을 처리하기 위해선 주로 수직적으로 확장해야 하며, 이는 비용이 많이 든다.
유연성 부족: 스키마 변경이 번거롭고 시간이 오래 걸릴 수 있다.
결론:
데이터베이스 선택은 프로젝트의 요구사항과 특성에 따라 달라진다.</p>
<p>MongoDB는 빠르게 변화하는 스타트업 환경, 대규모 데이터를 다루는 시스템, 개발 속도를 중요시하는 프로젝트에 적합하다.
반면, MySQL은 데이터 무결성이 중요한 금융, 의료 분야, 복잡한 쿼리가 필요한 분석 시스템 등에 적합하다.</p>
<h3 id="오늘의-질의-응답😎">오늘의 질의 응답😎</h3>
<h4 id="get-post의-개념과-함께-데이터-흐름에-대해서-설명해주세요">GET, POST의 개념과 함께 데이터 흐름에 대해서 설명해주세요.</h4>
<p>나의 답변 😄
GET 메서드는 정보를 요청할 때 사용하는 방식으로, 주로 URL을 통해 데이터를 전송하며, 검색 결과나 웹 페이지 조회에 사용됩니다. POST 메서드는 데이터를 서버로 제출할 때 사용하는 방식으로, 데이터는 HTTP 본문(body)에 숨겨져 전송되며, 로그인, 회원가입, 민감한 정보 전송 등에 사용됩니다.
데이터 흐름은 간단히 클라이언트에서 요청을 보내고, 서버에서 요청을 처리한 뒤 응답을 받는 것으로 이루어집니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[NestJS 백엔드와 클라이언트 사이드 연동]]></title>
            <link>https://velog.io/@sh_j225/NestJS-%EB%B0%B1%EC%97%94%EB%93%9C%EC%99%80-%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8-%EC%82%AC%EC%9D%B4%EB%93%9C-%EC%97%B0%EB%8F%99</link>
            <guid>https://velog.io/@sh_j225/NestJS-%EB%B0%B1%EC%97%94%EB%93%9C%EC%99%80-%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8-%EC%82%AC%EC%9D%B4%EB%93%9C-%EC%97%B0%EB%8F%99</guid>
            <pubDate>Tue, 05 Sep 2023 10:40:32 GMT</pubDate>
            <description><![CDATA[<h3 id="1-문제-상황">1. 문제 상황:</h3>
<p>클라이언트 사이드에서 require를 사용하면서 문제가 발생하였다.
이를 해결하기 위해 require를 사용하는 로직을 백엔드로 이동시키는 방안을 모색하였다.</p>
<h3 id="2-백엔드-수정">2. 백엔드 수정:</h3>
<p>NestJS와 TypeORM을 사용하여 백엔드를 구성하였다.
좌석 정보를 MongoDB에서 가져오고, MySQL에서 좌석의 상세 정보를 관리하도록 구현하였다.</p>
<h3 id="3-프론트엔드-수정">3. 프론트엔드 수정:</h3>
<p>fetch를 사용하여 NestJS 백엔드에서 좌석 정보를 가져온다.
가져온 좌석 정보는 2차원 배열 형태로 반환되며, 이를 활용하여 화면에 좌석을 동적으로 그리는 기능을 구현하였다.</p>
<h3 id="4-핵심-포인트">4. 핵심 포인트:</h3>
<p>클라이언트 사이드에서는 require를 사용할 수 없으므로, 이러한 로직은 백엔드로 이동시켜야 한다.
NestJS에서 제공하는 데코레이터와 TypeORM을 활용하면, 백엔드 로직을 효율적으로 구성할 수 있다.
프론트엔드에서는 fetch를 사용하여 백엔드와 통신하며, 반환된 데이터를 활용하여 원하는 UI를 동적으로 생성할 수 있다.</p>
<h3 id="오늘의-질의-응답😎">오늘의 질의 응답😎</h3>
<h4 id="orm을-사용하면서-쿼리가-복잡해지는-경우에는-어떻게-해결하는게-좋을까요">ORM을 사용하면서 쿼리가 복잡해지는 경우에는 어떻게 해결하는게 좋을까요?</h4>
<p>나의 답변 😄</p>
<ol>
<li><p>Query Builder 활용: ORM이 제공하는 Query Builder를 사용하여 복잡한 쿼리를 프로그래밍적으로 작성할 수 있습니다. 이는 SQL 문법에 익숙하지 않은 개발자에게도 쿼리 작성을 간편하게 만들어줍니다.</p>
</li>
<li><p>메소드 분리: 복잡한 쿼리를 하나의 메소드에 집중하지 말고, 관련된 로직을 여러 개의 메소드로 나눠 작성하면 코드의 가독성이 향상됩니다.</p>
</li>
<li><p>최적화: ORM이 자동 생성하는 쿼리를 분석하고 최적화해야 합니다. 데이터베이스 인덱스를 관리하거나 EXPLAIN을 사용하여 쿼리 실행 계획을 분석하여 성능을 개선할 수 있습니다.</p>
</li>
<li><p>Raw 쿼리 활용: 특히 복잡한 쿼리의 경우, ORM을 통하지 않고 직접 SQL 쿼리를 작성할 수 있습니다. 이를 통해 성능을 향상시킬 수 있지만, 보안과 ORM의 이점을 유지하는 것이 중요합니다.</p>
</li>
<li><p>인덱스 관리: 데이터베이스의 필드에 인덱스를 추가하여 쿼리 성능을 최적화할 수 있습니다. 이는 ORM이 자동으로 생성해주지 않는 경우 수동으로 관리해야 합니다.</p>
</li>
<li><p>캐싱 활용: 자주 사용되는 복잡한 쿼리의 결과를 캐싱하여 데이터베이스 부하를 줄일 수 있습니다. ORM의 캐싱 기능을 활용하거나 외부 캐싱 라이브러리를 사용할 수 있습니다.</p>
</li>
<li><p>디버깅 및 튜닝: 쿼리가 복잡할 경우, 디버깅을 통해 문제를 식별하고 개선하는 과정이 필요합니다. 또한 ORM의 튜닝 기능을 사용하여 성능을 모니터링하고 최적화할 수 있습니다.</p>
</li>
</ol>
<p>종합적으로, 복잡한 쿼리를 다루는데 있어서 Query Builder, 메소드 분리, 최적화, Raw 쿼리, 인덱스 관리, 캐싱, 디버깅 등 다양한 접근법을 조합하여 사용하는 것이 좋습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[NestJS에서 Stopwatch 모듈 구현하기]]></title>
            <link>https://velog.io/@sh_j225/NestJS%EC%97%90%EC%84%9C-Stopwatch-%EB%AA%A8%EB%93%88-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@sh_j225/NestJS%EC%97%90%EC%84%9C-Stopwatch-%EB%AA%A8%EB%93%88-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</guid>
            <pubDate>Mon, 04 Sep 2023 12:17:24 GMT</pubDate>
            <description><![CDATA[<ol>
<li>Stopwatch 모듈 생성
먼저, Stopwatch 모듈을 생성합니다. Nest CLI를 사용하거나 수동으로 모듈을 생성할 수 있습니다.</li>
</ol>
<pre><code>nest generate module stopwatch</code></pre><ol start="2">
<li>Stopwatch Entity 생성
스톱워치 데이터를 저장하기 위한 Entity를 생성합니다. 이 Entity는 시작 시간, 종료 시간 및 대상 시간(초)을 포함합니다.</li>
</ol>
<pre><code>import { Entity, PrimaryGeneratedColumn, Column, ManyToOne } from &#39;typeorm&#39;;
import { User } from &#39;./user.entity&#39;;

@Entity()
export class Stopwatch {
  @PrimaryGeneratedColumn()
  id: number;

  @Column({ type: &#39;timestamp&#39;, default: () =&gt; &#39;CURRENT_TIMESTAMP&#39; })
  startTime: Date;

  @Column({ type: &#39;timestamp&#39;, default: null, nullable: true })
  endTime: Date;

  @Column({ type: &#39;integer&#39; })
  targetSeconds: number;

  @ManyToOne(() =&gt; User, (user) =&gt; user.stopwatches)
  user: User;
}
</code></pre><ol start="3">
<li>Stopwatch Service 및 Controller 생성
Stopwatch 서비스와 컨트롤러를 생성합니다. 서비스는 스톱워치 생성 및 종료를 처리하고, 컨트롤러는 API 엔드포인트를 노출합니다.</li>
</ol>
<h4 id="stopwatchservice">StopwatchService</h4>
<pre><code>import { Injectable, NotFoundException } from &#39;@nestjs/common&#39;;
import { InjectRepository } from &#39;@nestjs/typeorm&#39;;
import { Repository } from &#39;typeorm&#39;;
import { Stopwatch } from &#39;../entity/stopwatch.entity&#39;;
import { User } from &#39;../entity/user.entity&#39;;

@Injectable()
export class StopwatchService {
  constructor(
    @InjectRepository(Stopwatch)
    private stopwatchRepository: Repository&lt;Stopwatch&gt;,
  ) {}

  async createStopwatch(userId: number, targetSeconds: number): Promise&lt;Stopwatch&gt; {
    const stopwatch = new Stopwatch();
    stopwatch.user = { id: userId } as User;
    stopwatch.targetSeconds = targetSeconds;
    return await this.stopwatchRepository.save(stopwatch);
  }

  async endStopwatch(stopwatchId: number): Promise&lt;Stopwatch&gt; {
    const stopwatch = await this.stopwatchRepository.findOne(stopwatchId);
    if (!stopwatch) {
      throw new NotFoundException(&#39;Stopwatch not found&#39;);
    }

    stopwatch.endTime = new Date();
    return await this.stopwatchRepository.save(stopwatch);
  }
}
</code></pre><h4 id="stopwatchcontroller">StopwatchController</h4>
<pre><code>import { Controller, Post, Param } from &#39;@nestjs/common&#39;;
import { StopwatchService } from &#39;./stopwatch.service&#39;;

@Controller(&#39;stopwatches&#39;)
export class StopwatchController {
  constructor(private readonly stopwatchService: StopwatchService) {}

  @Post(&#39;:userId/start/:targetSeconds&#39;)
  async startStopwatch(
    @Param(&#39;userId&#39;) userId: number,
    @Param(&#39;targetSeconds&#39;) targetSeconds: number,
  ) {
    return this.stopwatchService.createStopwatch(userId, targetSeconds);
  }

  @Post(&#39;:stopwatchId/end&#39;)
  async endStopwatch(@Param(&#39;stopwatchId&#39;) stopwatchId: number) {
    return this.stopwatchService.endStopwatch(stopwatchId);
  }
}</code></pre><ol start="4">
<li>AppModule에 StopwatchModule 추가
앞서 생성한 Stopwatch 모듈을 AppModule에 추가합니다. 이렇게 하면 StopwatchService와 관련된 의존성이 AppModule에서 해결됩니다.</li>
</ol>
<pre><code>import { Module } from &#39;@nestjs/common&#39;;
import { TypeOrmModule } from &#39;@nestjs/typeorm&#39;;
import { StopwatchModule } from &#39;./stopwatch/stopwatch.module&#39;; // Stopwatch 모듈 추가
// ...

@Module({
  imports: [
    ConfigModule.forRoot({ isGlobal: true }),
    TypeOrmModule.forRootAsync({
      imports: [ConfigModule],
      useClass: TypeOrmConfigService,
      inject: [ConfigService],
    }),
    JwtModule.registerAsync({
      imports: [ConfigModule],
      useClass: JwtConfigService,
      inject: [ConfigService],
    }),
    MulterModule.register({
      // ...
    }),
    PostModule,
    ToDoModule,
    GroupModule,
    RoomModule,
    SeatModule,
    CardModule,
    UserModule,
    PaymentModule,
    ChatModule,
    StopwatchModule, // Stopwatch 모듈 추가
  ],
  controllers: [AppController, PaymentController, StopwatchController],
  providers: [
    AppService,
    S3Service,
    UploadService,
    PaymentService,
    PaymentGateway,
    MyLogger,
    Logger,
    StopwatchService,
  ],
})
export class AppModule implements NestModule {
  configure(consumer: MiddlewareConsumer) {
    consumer.apply(LoggerMiddleware).forRoutes(&#39;*&#39;);
  }
}
</code></pre><h3 id="오늘의-질의-응답😎">오늘의 질의 응답😎</h3>
<h4 id="대용량-트래픽-발생-시-어떻게-대응해야-하나요">대용량 트래픽 발생 시 어떻게 대응해야 하나요?</h4>
<p>나의 답변 😄
ORM을 사용할 때 복잡한 쿼리 처리에 대한 해결책은 다음과 같습니다. QueryBuilder로 가독성을 높이고, 필요한 경우 Raw SQL을 활용합니다. 데이터베이스 인덱스 최적화를 통해 쿼리 성능을 향상하고, 자주 사용되는 쿼리 결과를 캐싱하여 데이터베이스 부하를 줄입니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[발표자료준비]]></title>
            <link>https://velog.io/@sh_j225/%EB%B0%9C%ED%91%9C%EC%9E%90%EB%A3%8C%EC%A4%80%EB%B9%84</link>
            <guid>https://velog.io/@sh_j225/%EB%B0%9C%ED%91%9C%EC%9E%90%EB%A3%8C%EC%A4%80%EB%B9%84</guid>
            <pubDate>Fri, 01 Sep 2023 11:19:00 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/sh_j225/post/cead88cc-cd5a-451e-8f88-dca9a5591b95/image.png" alt=""></p>
<p><a href="https://pacific-peace-393.notion.site/4-01ca9aac4b8c4421a14b6ada00716bd2?pvs=4">https://pacific-peace-393.notion.site/4-01ca9aac4b8c4421a14b6ada00716bd2?pvs=4</a></p>
<h3 id="오늘의-질의-응답😎">오늘의 질의 응답😎</h3>
<h4 id="대용량-트래픽-발생-시-어떻게-대응해야-하나요">대용량 트래픽 발생 시 어떻게 대응해야 하나요?</h4>
<p>나의 답변 😄</p>
<p>대용량 트래픽 대응 방법은 다음과 같습니다:</p>
<ol>
<li><p>로드 밸런싱: 트래픽을 여러 서버로 분산하여 부하를 분담합니다. 이로써 서버 과부하를 예방하고 안정적인 서비스를 유지합니다.</p>
</li>
<li><p>캐싱: 빈번한 요청 결과를 캐시에 저장하고, 이후 동일한 요청에 대한 응답을 캐시에서 제공합니다. 이는 응답 시간을 단축시키고 서버 부하를 줄입니다.</p>
</li>
<li><p>수평 확장: 서버 수를 추가하여 처리 능력을 확장합니다. 트래픽 증가에 따라 서버를 더 늘려서 대응합니다.</p>
</li>
<li><p>CDN 사용: Content Delivery Network을 활용하여 정적 자원(이미지, CSS, JavaScript 등)을 빠르게 제공합니다. 이는 대역폭을 절약하고 응답 시간을 최적화합니다.</p>
</li>
<li><p>비동기 처리: 비동기 방식으로 비즈니스 로직을 처리합니다. 이로써 서버는 요청을 받고 결과를 기다리는 동안 다른 작업을 수행할 수 있으며, 응답 시간을 최소화합니다.</p>
</li>
<li><p>DB 최적화: 데이터베이스 쿼리 튜닝, 인덱스 최적화, 데이터 샤딩 등을 통해 데이터베이스 부하를 최소화합니다. 이는 데이터 관련 작업의 성능을 향상시키고 서버 안정성을 높입니다.</p>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[웹 스탑워치 기능 구현하기]]></title>
            <link>https://velog.io/@sh_j225/%EC%9B%B9-%EC%8A%A4%ED%83%91%EC%9B%8C%EC%B9%98-%EA%B8%B0%EB%8A%A5-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@sh_j225/%EC%9B%B9-%EC%8A%A4%ED%83%91%EC%9B%8C%EC%B9%98-%EA%B8%B0%EB%8A%A5-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</guid>
            <pubDate>Thu, 31 Aug 2023 12:10:31 GMT</pubDate>
            <description><![CDATA[<p> HTML, CSS, JavaScript를 사용하여 목표 시간을 설정하고 스탑워치를 시작하며 정지시키는 기능을 구현해보았다.</p>
<ol>
<li><p>설정 버튼과 목표 시간 입력
먼저, 페이지에는 스탑워치와 관련된 요소들이 포함되어 있습니다. 설정 버튼을 클릭하면 사용자가 목표 시간(시간과 분)을 입력할 수 있도록 프롬프트 창이 뜨도록 설정했습니다. 사용자가 유효한 시간을 입력하면 목표 시간이 화면에 표시되고, 스탑워치가 작동합니다.</p>
</li>
<li><p>스탑워치 기능 구현
스탑워치는 setInterval 함수를 사용하여 1초마다 시간을 업데이트하는 방식으로 구현했습니다. 스탑워치가 시작되면 현재 시간을 기준으로 경과 시간을 계산하고, 이를 화면에 업데이트합니다. 목표 시간이 다 되면 스탑워치가 정지되고 알림 창이 뜨도록 설정했습니다.</p>
</li>
<li><p>멈춤 및 다시 시작 기능
스탑워치를 멈추고 다시 시작하면 정지한 시점부터 다시 시간이 흐르도록 구현했습니다. 멈춘 시간을 저장하여 다시 시작할 때 경과된 시간을 계산해 화면에 업데이트합니다.</p>
</li>
</ol>
<p>이렇게 웹 스탑워치 기능을 구현하면 사용자들은 목표 시간을 설정하고 스탑워치를 통해 시간을 관리할 수 있습니다.</p>
<pre><code>document.addEventListener(&#39;DOMContentLoaded&#39;, () =&gt; {
  let totalHours = 0;
  let totalMinutes = 0;
  let isRunning = false;
  let intervalId = null;
  let pausedTime = 0;

  const goalText = document.getElementById(&#39;goalText&#39;);
  const currentTimeDisplay = document.getElementById(&#39;currentTimeDisplay&#39;);
  const gauge = document.getElementById(&#39;gauge&#39;);
  const formSettingButton = document.querySelector(&#39;.form-setting&#39;);

  formSettingButton.addEventListener(&#39;click&#39;, () =&gt; {
    const userHours = parseInt(
      prompt(&#39;목표 시간(시)을 입력하세요:&#39;, totalHours),
    );
    const userMinutes = parseInt(
      prompt(&#39;목표 시간(분)을 입력하세요:&#39;, totalMinutes),
    );

    if (!isNaN(userHours) &amp;&amp; !isNaN(userMinutes)) {
      totalHours = userHours;
      totalMinutes = userMinutes;

      goalText.textContent = `목표시간: ${totalHours}시간 ${totalMinutes}분`;
      currentTimeDisplay.textContent = `0시간 0분 0초`;

      const gaugeWidth = ((totalHours * 60 + totalMinutes) / (60 * 24)) * 100; // 하루는 1440분
      gauge.style.width = `${gaugeWidth}%`;

      isRunning = true;
      startCountdown(totalHours * 3600 + totalMinutes * 60 - pausedTime);
    } else {
      alert(&#39;유효한 숫자를 입력하세요.&#39;);
    }
  });

  function startCountdown(totalSeconds) {
    let currentTime = totalSeconds;
    intervalId = setInterval(() =&gt; {
      if (currentTime &lt;= 0) {
        clearInterval(intervalId);
        alert(&#39;목표 시간이 다 되었습니다.&#39;);
        return;
      }

      currentTime--;

      const hours = Math.floor(currentTime / 3600);
      const remainingMinutes = Math.floor((currentTime % 3600) / 60);
      const seconds = currentTime % 60;

      currentTimeDisplay.textContent = `${hours}시간 ${remainingMinutes}분 ${seconds}초`;
    }, 1000);
  }
});</code></pre><h3 id="오늘의-질의-응답😎">오늘의 질의 응답😎</h3>
<h4 id="객체지향-프로그래밍이란-무엇이고-어떻게-활용할-수-있나요">객체지향 프로그래밍이란 무엇이고 어떻게 활용할 수 있나요?</h4>
<p>나의 답변 😄</p>
<p>객체지향 프로그래밍은 현실 세계의 객체를 프로그램 내 객체로 표현하며, 데이터와 메서드를 함께 묶어 캡슐화하여 유지보수성과 재사용성을 높이는 프로그래밍 패러다임입니다. 상속과 다형성을 통해 코드 중복을 줄이고 유연한 설계를 가능케 하며, 모듈화와 협업에 용이하며 대규모 프로젝트에서도 활용됩니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[저장과 표현에 관한 컴퓨터 사이언스]]></title>
            <link>https://velog.io/@sh_j225/%EC%A0%80%EC%9E%A5%EA%B3%BC-%ED%91%9C%ED%98%84%EC%97%90-%EA%B4%80%ED%95%9C-%EC%BB%B4%ED%93%A8%ED%84%B0-%EC%82%AC%EC%9D%B4%EC%96%B8%EC%8A%A4</link>
            <guid>https://velog.io/@sh_j225/%EC%A0%80%EC%9E%A5%EA%B3%BC-%ED%91%9C%ED%98%84%EC%97%90-%EA%B4%80%ED%95%9C-%EC%BB%B4%ED%93%A8%ED%84%B0-%EC%82%AC%EC%9D%B4%EC%96%B8%EC%8A%A4</guid>
            <pubDate>Wed, 30 Aug 2023 10:41:18 GMT</pubDate>
            <description><![CDATA[<p> 데이터는 컴퓨터 시스템에서 처리되고 조작되어 결과를 얻기 위해 저장되어야 하며, 이에 필요한 구조와 방법들이 존재합니다. </p>
<p>1) 데이터 표현 방식:</p>
<ol>
<li><p>이진 표현: 컴퓨터는 모든 데이터를 이진(binary) 형태로 표현합니다. 모든 정보는 0과 1로 표현되며, 비트(bit) 단위로 조합되어 숫자, 문자, 이미지 등의 데이터가 표현됩니다.</p>
</li>
<li><p>비트와 바이트: 비트는 0 또는 1을 나타내는 최소 단위이고, 8개의 비트가 모여 바이트(byte)를 형성합니다.
2) 정수 표현:</p>
</li>
<li><p>부호 없는 정수: 숫자의 크기만을 나타내며, 이진수로 직접 표현합니다.</p>
</li>
<li><p>부호 있는 정수: 부호 비트를 사용하여 양수와 음수를 표현합니다. 2의 보수 표현은 음수의 덧셈과 같은 연산을 간단하게 처리할 수 있도록 도와줍니다.</p>
</li>
</ol>
<p>3) 부동 소수점 표현:</p>
<p>실수는 부동 소수점 방식으로 표현됩니다. IEEE 754 표준은 32비트와 64비트 형식으로 실수를 저장하는 방식을 규정합니다.</p>
<p>4) 문자 표현:</p>
<ol>
<li>문자 집합(Character Set): 문자를 숫자로 매핑한 표입니다. ASCII, Unicode 등이 대표적입니다.</li>
<li>문자 인코딩(Character Encoding): 문자를 이진수로 변환하는 방식입니다. UTF-8, UTF-16 등이 널리 사용됩니다.</li>
</ol>
<p>5) 배열과 구조체:</p>
<p>데이터를 보다 복잡한 형태로 구성하기 위해 배열과 구조체를 사용합니다. 배열은 동일한 타입의 데이터를 순차적으로 저장하며, 구조체는 서로 다른 타입의 데이터를 묶어 하나의 단위로 만듭니다.</p>
<p>6)파일과 데이터베이스:</p>
<p>파일 시스템은 데이터를 파일로 저장하고 조직하는 방식입니다. 파일은 이름, 위치 및 크기 등의 정보와 함께 디스크에 저장됩니다.
데이터베이스는 구조화된 데이터의 집합을 관리하는 시스템입니다. SQL 데이터베이스나 NoSQL 데이터베이스 등 다양한 형태가 있습니다.</p>
<h3 id="오늘의-질의-응답😎">오늘의 질의 응답😎</h3>
<h4 id="di-ioc에-대해-설명해주세요">DI, IoC에 대해 설명해주세요.</h4>
<p>나의 답변 😄</p>
<p>DI (Dependency Injection)와 IoC (Inversion of Control)는 소프트웨어 디자인 패턴으로, 객체 간의 결합도를 낮추고 유지보수성을 향상시키는 데 목적이 있습니다.</p>
<ol>
<li><p>DI (Dependency Injection): DI는 객체들 간의 의존성을 외부에서 주입하는 패턴입니다. 이로써 코드의 유연성과 테스트 용이성이 증가하며, 객체가 필요한 의존성을 직접 생성하는 것이 아니라 외부로부터 주입받게 됩니다.</p>
</li>
<li><p>IoC (Inversion of Control): IoC는 제어의 역전을 의미하며, 소프트웨어 컴포넌트들의 제어 흐름을 역전시키는 패턴입니다. 일반적으로 프레임워크나 컨테이너가 객체의 라이프사이클을 관리하고 생성, 의존성 주입 등을 처리하며, 개발자는 이를 통해 컴포넌트를 더 집중적으로 개발할 수 있습니다.</p>
</li>
</ol>
<p>간단히 말해, DI와 IoC는 객체 간 의존성과 제어 흐름을 역전시킴으로써 코드의 유지보수성과 확장성을 높이는 디자인 패턴입니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[오늘 내가 배운 것 - 2023년 8월 28일]]></title>
            <link>https://velog.io/@sh_j225/%EC%98%A4%EB%8A%98-%EB%82%B4%EA%B0%80-%EB%B0%B0%EC%9A%B4-%EA%B2%83-2023%EB%85%84-8%EC%9B%94-28%EC%9D%BC</link>
            <guid>https://velog.io/@sh_j225/%EC%98%A4%EB%8A%98-%EB%82%B4%EA%B0%80-%EB%B0%B0%EC%9A%B4-%EA%B2%83-2023%EB%85%84-8%EC%9B%94-28%EC%9D%BC</guid>
            <pubDate>Tue, 29 Aug 2023 11:45:20 GMT</pubDate>
            <description><![CDATA[<blockquote>
<h3 id="모달-창에서-동적-콘텐츠-관리하기">모달 창에서 동적 콘텐츠 관리하기</h3>
<p>오늘은 웹 페이지에서 카드를 클릭하면 모달 창이 열리고 해당 카드의 세부 정보가 모달 내에 표시되는 기능을 구현해보았습니다. 이를 위해서는 JavaScript를 사용하여 동적으로 요소를 조작하고 화면에 표시해야 했습니다.</p>
</blockquote>
<pre><code>// 카드 클릭 시 모달 열기
const cardTitles = document.querySelectorAll(&#39;.card-title&#39;);
cardTitles.forEach((cardTitle) =&gt; {
  cardTitle.addEventListener(&#39;click&#39;, () =&gt; {
    const modalTitle = document.querySelector(&#39;.cardModal-title&#39;);
    const modalDescription = document.querySelector(&#39;.cardModal-description&#39;);
    const cardModal = document.getElementById(&#39;cardModal&#39;);

    // 선택된 카드의 정보를 모달에 채워넣고 모달 열기
    modalTitle.innerText = title;
    modalDescription.innerText = card.desc;
    cardModal.style.display = &#39;block&#39;;
  });
});</code></pre><blockquote>
<h3 id="드롭다운-메뉴-유지-상태-설정하기">드롭다운 메뉴 유지 상태 설정하기</h3>
<p>드롭다운 메뉴를 클릭한 후에도 마우스 커서의 움직임에 상관없이 메뉴가 열린 상태로 유지되도록 개선해보았습니다.</p>
</blockquote>
<pre><code>// 드롭다운 메뉴 클릭 이벤트 처리
let isDropdownVisible = false;
dropbtn.addEventListener(&#39;click&#39;, () =&gt; {
  isDropdownVisible = !isDropdownVisible;
  dropdown.classList.toggle(&#39;show&#39;, isDropdownVisible);
});</code></pre><blockquote>
<h3 id="날짜-정보-포맷팅하기">날짜 정보 포맷팅하기</h3>
<p>날짜 데이터에서 필요한 년, 월, 일 정보만 추출하여 표시하는 방법을 알아보았습니다.</p>
</blockquote>
<pre><code> const startdate = groupData.startDate;
      const enddate = groupData.endDate;
      const Startdate = startdate.split(&#39;T&#39;)[0];
      const Enddate = enddate.split(&#39;T&#39;)[0]; 


      groupNameElement.innerText = groupName;
      TeamRoleElement.innerText = TeamRole;
      StartDateElement.innerText = Startdate;
      EndDateElement.innerText = Enddate;

</code></pre><h3 id="오늘의-질의-응답😎">오늘의 질의 응답😎</h3>
<h4 id="http-https-차이점에-대해-설명해주세요">http, https 차이점에 대해 설명해주세요.</h4>
<p>나의 답변 😄</p>
<p>HTTP(Hypertext Transfer Protocol)와 HTTPS(Hypertext Transfer Protocol Secure)는 둘 다 데이터 통신을 위한 프로토콜입니다.</p>
<p>HTTP는 데이터를 암호화하지 않고 전송하기 때문에 보안에 취약할 수 있습니다. 반면에 HTTPS는 보안 소켓 계층(SSL) 또는 전송 계층 보안(TLS) 프로토콜을 사용하여 데이터를 암호화하고 전송합니다. 이로써 사용자의 개인 정보와 민감한 데이터가 외부의 눈에 노출되지 않도록 보호됩니다.</p>
<p>HTTPS는 웹사이트의 신뢰성과 안전성을 강화하며 데이터 탈취나 변조를 예방합니다. 이러한 이유로 현대 웹 개발에서는 보안을 강화하기 위해 HTTPS를 사용하는 것이 권장됩니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[NestJS와 Socket.IO를 활용한 실시간 채팅 서버 구축하기]]></title>
            <link>https://velog.io/@sh_j225/NestJS%EC%99%80-Socket.IO%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%9C-%EC%8B%A4%EC%8B%9C%EA%B0%84-%EC%B1%84%ED%8C%85-%EC%84%9C%EB%B2%84-%EA%B5%AC%EC%B6%95%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@sh_j225/NestJS%EC%99%80-Socket.IO%EB%A5%BC-%ED%99%9C%EC%9A%A9%ED%95%9C-%EC%8B%A4%EC%8B%9C%EA%B0%84-%EC%B1%84%ED%8C%85-%EC%84%9C%EB%B2%84-%EA%B5%AC%EC%B6%95%ED%95%98%EA%B8%B0</guid>
            <pubDate>Mon, 28 Aug 2023 10:11:19 GMT</pubDate>
            <description><![CDATA[<h3 id="nestjs와-mongodb-연동하기">NestJS와 MongoDB 연동하기</h3>
<p>NestJS와 MongoDB를 연동하여 데이터를 저장하고 관리할 수 있는 환경을 구축해보겠습니다. MongoDB는 NoSQL 데이터베이스로서 JSON 형식의 데이터를 저장하며, NestJS에서는 TypeORM을 통해 MongoDB와 손쉽게 연동할 수 있습니다.</p>
<pre><code>import { TypeOrmModuleOptions } from &#39;@nestjs/typeorm&#39;;

export const typeOrmConfig: TypeOrmModuleOptions = {
  type: &#39;mongodb&#39;,
  host: &#39;localhost&#39;,
  port: 27017,
  database: &#39;chat_app&#39;,
  entities: [__dirname + &#39;/../**/*.entity{.ts,.js}&#39;],
  synchronize: true,
};
</code></pre><h3 id="채팅-서버-구축하기">채팅 서버 구축하기</h3>
<p>Socket.IO를 사용하여 실시간 채팅 서버를 구축해봅시다. NestJS에서는 @nestjs/websockets 모듈을 사용하여 쉽게 WebSocket 기능을 구현할 수 있습니다.</p>
<pre><code>
import { WebSocketGateway, WebSocketServer, SubscribeMessage } from &#39;@nestjs/websockets&#39;;
import { Server, Socket } from &#39;socket.io&#39;;

@WebSocketGateway()
export class ChatGateway {
  @WebSocketServer()
  server: Server;

  @SubscribeMessage(&#39;chatMessage&#39;)
  handleChatMessage(client: Socket, data: { message: string }): void {
    this.server.emit(&#39;chatMessage&#39;, {
      user: client.id,
      message: data.message,
      timestamp: new Date(),
    });
  }
}</code></pre><h3 id="결제-시스템-구축하기">결제 시스템 구축하기</h3>
<p>또한, 결제 시스템을 트랜잭션과 소켓을 활용하여 구축해봅시다. NestJS에서는 @nestjs/typeorm 모듈의 @Transaction() 데코레이터와 @TransactionManager() 데코레이터를 사용하여 트랜잭션을 간편하게 처리할 수 있습니다.</p>
<pre><code>import { Controller, Post, Body, HttpCode, HttpStatus } from &#39;@nestjs/common&#39;;
import { PaymentService } from &#39;./payment.service&#39;;
import { PaymentDto } from &#39;../dto/payment/payment.dto&#39;;
import { Transaction, TransactionManager } from &#39;typeorm&#39;;

@Controller(&#39;payments&#39;)
export class PaymentController {
  constructor(private readonly paymentService: PaymentService) {}

  @Post()
  @HttpCode(HttpStatus.CREATED)
  @Transaction() // 트랜잭션 시작
  async createPayment(
    @TransactionManager() manager: EntityManager,
    @Body() paymentDto: PaymentDto,
  ): Promise&lt;void&gt; {
    await this.paymentService.createPayment(manager, paymentDto);
    // API 로직 추가
  }
}
</code></pre><h3 id="오늘의-질의-응답😎">오늘의 질의 응답😎</h3>
<h4 id="tcpudp에-대해서-설명해주세요">TCP/UDP에 대해서 설명해주세요.</h4>
<p>나의 답변 😄</p>
<p>TCP는 신뢰성 있는 데이터 전송을 위한 연결 지향 프로토콜로, 순서와 손실을 관리하여 안정적인 통신을 제공합니다. 3-way 핸드쉐이킹으로 연결 설정하고 4-way 핸드쉐이킹으로 연결을 해제합니다. 파일 전송, 이메일, 웹 브라우징과 같은 신뢰성 필요한 서비스에 사용됩니다.</p>
<p>UDP는 비연결성 프로토콜로, 데이터의 신뢰성을 보장하지 않고 빠른 데이터 전송을 지향합니다. 데이터 순서와 손실이 발생할 수 있지만 연결 설정 과정이 없어 더 빠른 전송이 가능합니다. 실시간 반응성이 필요한 스트리밍, 온라인 게임 등에 사용됩니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CS)프로세스 생명주기와 프로세스 메모리]]></title>
            <link>https://velog.io/@sh_j225/CS%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4-%EC%83%9D%EB%AA%85%EC%A3%BC%EA%B8%B0%EC%99%80-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4-%EB%A9%94%EB%AA%A8%EB%A6%AC</link>
            <guid>https://velog.io/@sh_j225/CS%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4-%EC%83%9D%EB%AA%85%EC%A3%BC%EA%B8%B0%EC%99%80-%ED%94%84%EB%A1%9C%EC%84%B8%EC%8A%A4-%EB%A9%94%EB%AA%A8%EB%A6%AC</guid>
            <pubDate>Fri, 25 Aug 2023 14:13:25 GMT</pubDate>
            <description><![CDATA[<h4 id="1-프로세스">1. 프로세스:</h4>
<p>프로세스는 실행 중인 프로그램을 메모리에 적재하여 실행하는 작업 단위입니다.</p>
<h4 id="2-프로세스-생명주기">2. 프로세스 생명주기:</h4>
<p>프로세스는 신규 -&gt; 준비 -&gt; 수행 -&gt; 대기 -&gt; 종료의 생명주기를 가지며, 각 단계는 프로세스의 상태를 나타냅니다.</p>
<h4 id="3-pcb-process-control-block">3. PCB (Process Control Block):</h4>
<p>프로세스의 실행 정보와 상태 정보를 저장하는 자료구조로, PID(프로세스 식별자), PC(프로그램 카운터), 레지스터 상태, MMU(메모리 관리 유닛) 정보 등을 포함합니다.</p>
<h4 id="4-대기-큐-queue">4. 대기 큐 (Queue):</h4>
<p>작업 큐, 준비 큐, 디바이스 큐 등의 큐는 프로세스나 작업들을 관리하기 위한 자료구조입니다.</p>
<h4 id="5-스케줄러-scheduler">5. 스케줄러 (Scheduler):</h4>
<p>작업 스케줄러, CPU 스케줄러, 디바이스 스케줄러 등은 프로세스나 작업들의 실행 순서를 관리하는 역할을 합니다.</p>
<h4 id="6-스와핑-swapping">6. 스와핑 (Swapping):</h4>
<p>메모리에 올라간 프로세스 중 필요 없는 것을 디스크로 내리고, 필요한 것을 다시 메모리로 올리는 작업을 말합니다.</p>
<h4 id="7-컨텍스트-스위칭-context-switching">7. 컨텍스트 스위칭 (Context Switching):</h4>
<p>현재 실행 중인 프로세스의 상태를 PCB에 저장하고 다음 실행할 프로세스의 정보를 읽어와 전환하는 작업입니다.</p>
<h4 id="8-디스패처-dispatcher">8. 디스패처 (Dispatcher):</h4>
<p>컨텍스트 스위칭에 필요한 정보를 PCB에서 추출하거나 저장하는 역할을 수행하는 컴퓨터 프로그램입니다.</p>
<h4 id="9-cpu-시간-공유-시스템">9. CPU 시간 공유 시스템:</h4>
<p>대부분의 운영 체제에서 여러 프로세스나 스레드가 CPU를 나눠서 사용할 수 있도록 관리하는 시스템입니다.</p>
<h4 id="10-프로세스-메모리-공간">10. 프로세스 메모리 공간:</h4>
<p>프로세스 주소 공간은 코드, 데이터, 스택, 힙 등으로 구성되어 있습니다.</p>
<h4 id="11-커널">11. 커널:</h4>
<p>운영 체제의 핵심 부분으로 하드웨어와 프로세스 간의 인터페이스를 제공하며 시스템 리소스를 관리합니다.</p>
<h4 id="12-pcb-process-control-block">12. PCB (Process Control Block):</h4>
<p>프로세스의 실행 정보와 상태 정보를 저장하는 자료구조로, 운영 체제 내부에 존재합니다.</p>
<h3 id="오늘의-질의-응답😎">오늘의 질의 응답😎</h3>
<h4 id="쿠키와-세션의-차이점을-설명해주세요">쿠키와 세션의 차이점을 설명해주세요.</h4>
<p>나의 답변 😄</p>
<p>쿠키는 클라이언트 브라우저에 저장되는 작은 데이터 조각으로 주로 로그인 상태 유지 등에 사용되며 보안에 취약합니다. 세션은 서버에 사용자 상태를 저장하며 더 높은 보안성을 제공하나 브라우저 종료 시 종료됩니다. 쿠키는 클라이언트 측에, 세션은 서버 측에 저장되며 용량, 보안성, 유효 기간 등에서 차이가 있습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[사용자 로그인 정보를 가져와서 채팅 애플리케이션에 적용하는 방법]]></title>
            <link>https://velog.io/@sh_j225/%EC%82%AC%EC%9A%A9%EC%9E%90-%EB%A1%9C%EA%B7%B8%EC%9D%B8-%EC%A0%95%EB%B3%B4%EB%A5%BC-%EA%B0%80%EC%A0%B8%EC%99%80%EC%84%9C-%EC%B1%84%ED%8C%85-%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98%EC%97%90-%EC%A0%81%EC%9A%A9%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95</link>
            <guid>https://velog.io/@sh_j225/%EC%82%AC%EC%9A%A9%EC%9E%90-%EB%A1%9C%EA%B7%B8%EC%9D%B8-%EC%A0%95%EB%B3%B4%EB%A5%BC-%EA%B0%80%EC%A0%B8%EC%99%80%EC%84%9C-%EC%B1%84%ED%8C%85-%EC%95%A0%ED%94%8C%EB%A6%AC%EC%BC%80%EC%9D%B4%EC%85%98%EC%97%90-%EC%A0%81%EC%9A%A9%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95</guid>
            <pubDate>Thu, 24 Aug 2023 11:00:40 GMT</pubDate>
            <description><![CDATA[<h3 id="백엔드-구현">백엔드 구현</h3>
<ol>
<li>NestJS를 사용하여 UserController를 생성하고, 로그인을 처리하는 login 메서드가 구현합니다.</li>
<li>로그인이 성공하면 인증 토큰을 쿠키에 저장하여 응답합니다.<h3 id="프론트엔드-구현">프론트엔드 구현</h3>
</li>
<li>Axios를 사용하여 백엔드의 로그인 API를 호출합니다.</li>
<li>받아온 토큰을 쿠키에 저장합니다.</li>
<li>Socket.IO를 사용하여 소켓 연결을 수립합니다.</li>
<li>토큰을 이용하여 백엔드 API에서 사용자 정보를 요청합니다.</li>
<li>사용자 정보를 소켓을 통해 채팅 애플리케이션에 적용합니다.</li>
</ol>
<h3 id="프론트엔드-예시">프론트엔드 예시</h3>
<pre><code>import axios from &#39;axios&#39;;
import io from &#39;socket.io-client&#39;;

const loginData = {
  email: &#39;user@example.com&#39;,
  password: &#39;password&#39;,
};

axios.post(&#39;api_endpoint&#39;, loginData)
  .then(response =&gt; {
    const authorization = response.data;
    document.cookie = `Authorization=Bearer ${authorization}; path=/;`;

    const socket = io();

    axios.get(&#39;api_endpoint&#39;, {
      headers: {
        Authorization: `Bearer ${authorization}`,
      },
    })
    .then(response =&gt; {
      const user = response.data;
      const userName = user.name;

      socket.emit(&#39;setUserName&#39;, userName);

      // 나머지 채팅 애플리케이션 코드
    })
    .catch(error =&gt; {
      console.error(&#39;Error fetching user data:&#39;, error);
    });
  })
  .catch(error =&gt; {
    console.error(&#39;Error logging in:&#39;, error);
  });</code></pre><h3 id="오늘의-질의-응답😎">오늘의 질의 응답😎</h3>
<h4 id="브라우저의-작동방식에-대해서-설명해주세요">브라우저의 작동방식에 대해서 설명해주세요.</h4>
<p>나의 답변 😄</p>
<p>브라우저는 사용자가 URL을 입력하거나 링크를 클릭하면 서버에 데이터 요청을 보내고, 받은 HTML, CSS, JavaScript 파일을 해석하여 화면에 웹 페이지를 표시합니다. 이를 위해 렌더링 엔진이 HTML을 파싱하고, DOM과 CSSOM을 생성하여 화면을 구성합니다. JavaScript는 동적 기능을 추가하며, 이벤트 처리와 상호작용을 관리합니다. 페이지 업데이트나 사용자 입력에 따라 과정을 반복하며 웹 페이지를 구성하고 보여줍니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[클라이언트와 서버 간의 WebSocket 통신에서 CORS 문제 해결하기]]></title>
            <link>https://velog.io/@sh_j225/%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8%EC%99%80-%EC%84%9C%EB%B2%84-%EA%B0%84%EC%9D%98-WebSocket-%ED%86%B5%EC%8B%A0%EC%97%90%EC%84%9C-CORS-%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@sh_j225/%ED%81%B4%EB%9D%BC%EC%9D%B4%EC%96%B8%ED%8A%B8%EC%99%80-%EC%84%9C%EB%B2%84-%EA%B0%84%EC%9D%98-WebSocket-%ED%86%B5%EC%8B%A0%EC%97%90%EC%84%9C-CORS-%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0%ED%95%98%EA%B8%B0</guid>
            <pubDate>Wed, 23 Aug 2023 11:02:54 GMT</pubDate>
            <description><![CDATA[<h2 id="문제-클라이언트와-서버-간의-websocket-통신-시-cors-정책으로-인한-접근-문제가-발생하는-상황">문제: 클라이언트와 서버 간의 WebSocket 통신 시 CORS 정책으로 인한 접근 문제가 발생하는 상황.</h2>
<h3 id="해결-단계">해결 단계:</h3>
<h4 id="1-서버-cors-설정-확인">1. 서버 CORS 설정 확인</h4>
<p>NestJS 애플리케이션에서 app.enableCors()를 사용하여 CORS를 설정.
origin에 클라이언트 도메인 주소를 추가하고 credentials: true로 설정.</p>
<h4 id="2-클라이언트-cors-설정">2. 클라이언트 CORS 설정</h4>
<p>클라이언트 측에서 io() 호출 시 withCredentials: true를 설정하여 CORS 요청을 허용.</p>
<h4 id="3소켓-경로-확인">3.소켓 경로 확인</h4>
<p>클라이언트에서 소켓 연결 시 사용하는 경로와 서버에서 해당 경로를 제대로 처리할 수 있는지 확인.</p>
<h4 id="4서버-및-클라이언트-포트-일치-확인">4.서버 및 클라이언트 포트 일치 확인</h4>
<p>서버와 클라이언트가 같은 포트에서 실행 중인지 확인.</p>
<h4 id="5socketio-버전-호환성">5.socket.io 버전 호환성</h4>
<p>서버와 클라이언트 양쪽에서 socket.io 버전이 호환되는지 확인.</p>
<h4 id="6브라우저-개발자-도구-활용">6.브라우저 개발자 도구 활용</h4>
<p>브라우저 개발자 도구의 콘솔 및 네트워크 탭을 확인하여 자세한 오류 메시지와 네트워크 요청을 분석.</p>
<h4 id="7서버-로그-확인">7.서버 로그 확인</h4>
<p>서버에서 발생하는 로그를 확인하여 요청과 응답을 추적하며 문제 해결.</p>
<h3 id="오늘의-질의-응답😎">오늘의 질의 응답😎</h3>
<h4 id="corscross-origin-resource-sharing에-대해-설명해주세요">CORS(Cross Origin Resource Sharing)에 대해 설명해주세요.</h4>
<p>나의 답변 😄</p>
<p>CORS는 웹 애플리케이션이 한 도메인에서 다른 도메인으로 리소스를 요청할 때 발생하는 보안 정책입니다. 웹 브라우저는 이 정책을 통해 악의적인 요청을 방지하고 사용자 데이터를 보안하는 역할을 합니다. 웹 페이지는 동일 출처 정책에 따라 같은 도메인에서만 요청을 보낼 수 있습니다. 하지만 지금의 다양한 도메인 간의 상호작용을 위해 CORS가 도입되었습니다. 서버는 특정 도메인으로부터의 요청을 허용하기 위해 HTTP 헤더를 사용하며, 이를 통해 클라이언트와 서버 간의 안전한 통신이 이루어집니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TypeScript와 Nest.js로 실시간 채팅 구현하기]]></title>
            <link>https://velog.io/@sh_j225/TypeScript%EC%99%80-Nest.js%EB%A1%9C-%EC%8B%A4%EC%8B%9C%EA%B0%84-%EC%B1%84%ED%8C%85-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@sh_j225/TypeScript%EC%99%80-Nest.js%EB%A1%9C-%EC%8B%A4%EC%8B%9C%EA%B0%84-%EC%B1%84%ED%8C%85-%EA%B5%AC%ED%98%84%ED%95%98%EA%B8%B0</guid>
            <pubDate>Tue, 22 Aug 2023 12:51:52 GMT</pubDate>
            <description><![CDATA[<h4 id="1-프로젝트-설정-및-설치">1. 프로젝트 설정 및 설치</h4>
<p>먼저 새로운 Nest.js 프로젝트를 생성하고, Socket.io를 설치합니다.</p>
<pre><code> Nest.js 프로젝트 생성
 nest new real-time-chat-app</code></pre><pre><code> Socket.io 설치
 npm install --save @nestjs/platform-socket.io @nestjs/websockets socket.io</code></pre><h4 id="2-websocket-모듈-생성">2. WebSocket 모듈 생성</h4>
<p>Nest.js에서 WebSocket을 사용하기 위해 WebSocketsModule을 생성하고 설정합니다.</p>
<pre><code>import { Module } from &#39;@nestjs/common&#39;;
import { WebSocketsModule } from &#39;./websockets/websockets.module&#39;;

@Module({
  imports: [WebSocketsModule],
})
export class AppModule {}</code></pre><hr>
<pre><code>import { Module } from &#39;@nestjs/common&#39;;
import { WebSocketsGateway } from &#39;./websockets.gateway&#39;;

@Module({
  providers: [WebSocketsGateway],
})
export class WebSocketsModule {}</code></pre><h4 id="3-websocket-gateway-생성">3. WebSocket Gateway 생성</h4>
<p>WebSocket Gateway를 생성하여 실시간 통신을 처리합니다.</p>
<pre><code>import {
  WebSocketGateway,
  WebSocketServer,
  SubscribeMessage,
  OnGatewayConnection,
  OnGatewayDisconnect,
} from &#39;@nestjs/websockets&#39;;
import { Server, Socket } from &#39;socket.io&#39;;

@WebSocketGateway()
export class WebSocketsGateway implements OnGatewayConnection, OnGatewayDisconnect {
  @WebSocketServer()
  server: Server;

  async handleConnection(client: Socket) {
    // 클라이언트 연결 시 처리
  }

  async handleDisconnect(client: Socket) {
    // 클라이언트 연결 종료 시 처리
  }

  @SubscribeMessage(&#39;chat&#39;)
  handleMessage(client: Socket, message: string) {
    // 클라이언트로부터 메시지 수신 처리
    this.server.emit(&#39;chat&#39;, message); // 모든 클라이언트에 메시지 전달
  }
}
</code></pre><h4 id="4-클라이언트-측-구현">4. 클라이언트 측 구현</h4>
<p>클라이언트 측에서도 Socket.io를 사용하여 실시간 채팅을 구현합니다.</p>
<pre><code> const socket = io(); // Socket.io 연결

    const chatDiv = document.getElementById(&#39;chat&#39;);
    const input = document.createElement(&#39;input&#39;);
    const button = document.createElement(&#39;button&#39;);
    button.textContent = &#39;전송&#39;;

    button.addEventListener(&#39;click&#39;, () =&gt; {
      const message = input.value;
      socket.emit(&#39;chat&#39;, message); // 서버로 메시지 전송
      input.value = &#39;&#39;;
    });

    socket.on(&#39;chat&#39;, (message) =&gt; {
      const messageDiv = document.createElement(&#39;div&#39;);
      messageDiv.textContent = message;
      chatDiv.appendChild(messageDiv);
    });

    chatDiv.appendChild(input);
    chatDiv.appendChild(button);</code></pre><h4 id="이와-같이-typescript와-nestjs를-활용하여-실시간-채팅을-구현할-수-있습니다-websocket-gateway를-사용하여-서버-측에서-클라이언트로-메시지를-전달하고-클라이언트-측에서도-socketio를-이용하여-실시간으로-메시지를-주고받을-수-있습니다">이와 같이 TypeScript와 Nest.js를 활용하여 실시간 채팅을 구현할 수 있습니다. WebSocket Gateway를 사용하여 서버 측에서 클라이언트로 메시지를 전달하고, 클라이언트 측에서도 Socket.io를 이용하여 실시간으로 메시지를 주고받을 수 있습니다.</h4>
<h3 id="오늘의-질의-응답😎">오늘의 질의 응답😎</h3>
<h4 id="http-메서드에-대해-설명해주세요">HTTP 메서드에 대해 설명해주세요.</h4>
<p>나의 답변 😄</p>
<p>HTTP 메서드는 웹 서버와 클라이언트 사이의 통신에서 사용되는 요청 유형을 나타내며, 주로 다음과 같은 네 가지 메서드가 있습니다. 
GET, 주로 데이터 조회에 사용되고, 정보를 서버로부터 가져오기 위한 요청입니다.
POST, 서버에 새로운 데이터를 생성하기 위한 요청입니다. 주로 데이터 생성 또는 업데이트에 활용됩니다.
PUT, 서버의 데이터를 수정하기 위한 요청입니다. 주로 데이터 갱신에 사용되며, 전체 데이터를 업데이트합니다. 
DELETE, 서버의 데이터를 삭제하기 위한 요청입니다. 해당 데이터를 삭제하도록 서버에 요청합니다.
이러한 HTTP 메서드들은 각각 명확한 목적과 작업을 나타내며, 웹 애플리케이션 개발 및 API 디자인에서 적절하게 활용됩니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[NestJS에서 모듈 간 의존성 관리하기]]></title>
            <link>https://velog.io/@sh_j225/NestJS%EC%97%90%EC%84%9C-%EB%AA%A8%EB%93%88-%EA%B0%84-%EC%9D%98%EC%A1%B4%EC%84%B1-%EA%B4%80%EB%A6%AC%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@sh_j225/NestJS%EC%97%90%EC%84%9C-%EB%AA%A8%EB%93%88-%EA%B0%84-%EC%9D%98%EC%A1%B4%EC%84%B1-%EA%B4%80%EB%A6%AC%ED%95%98%EA%B8%B0</guid>
            <pubDate>Mon, 21 Aug 2023 12:39:45 GMT</pubDate>
            <description><![CDATA[<h2 id="nestjs에서-모듈-간-의존성-관리하기">NestJS에서 모듈 간 의존성 관리하기</h2>
<p>NestJS 애플리케이션을 개발하면서 모듈 간의 의존성 관리는 중요한 부분이다. 모듈 간의 의존성을 올바르게 설정하지 않으면 런타임 중에 주입해야 하는 서비스나 레포지토리를 찾지 못해 애플리케이션이 시작되지 않을 수 있다.</p>
<h4 id="문제-상황">문제 상황</h4>
<p>NestJS 프로젝트에서 TodoService와 CardService를 각각 별도의 모듈에서 구현하고자 했다. TodoService에서는 TodoRepository를 주입받아 사용하고, CardService에서는 CardRepository와 함께 TodoRepository도 주입받아야 했다.</p>
<h4 id="해결-방법">해결 방법</h4>
<p>TodoService에서 TodoRepository와 CardRepository를 주입받기 위해 CardModule에서 TodoRepository도 함께 import했다.</p>
<pre><code>@Module({
  imports: [TypeOrmModule.forFeature([Card, Todo]), forwardRef(() =&gt; ToDoModule)],
})
export class CardModule {}</code></pre><h4 id="1-todoservice에서-cardrepository와-todorepository를-함께-주입받을-수-있게-되었다">1. TodoService에서 CardRepository와 TodoRepository를 함께 주입받을 수 있게 되었다.</h4>
<pre><code>@Injectable()
export class TodoService {
  constructor(
    @InjectRepository(Todo)
    private readonly todoRepository: Repository&lt;Todo&gt;,
    @InjectRepository(Card)
    private readonly cardRepository: Repository&lt;Card&gt;,
  ) {}
}</code></pre><h4 id="2-constructor에-의존성을-주입하니-todoservice에서-todorepository와-cardrepository를-올바르게-주입받아-사용할-수-있게-되었다">2. constructor에 의존성을 주입하니 TodoService에서 TodoRepository와 CardRepository를 올바르게 주입받아 사용할 수 있게 되었다.</h4>
<h2 id="결론">결론</h2>
<p>NestJS 애플리케이션에서 모듈 간의 의존성을 올바르게 관리하는 것은 중요한 작업이다. 위의 예시를 통해 모듈 간의 의존성 설정 방법을 이해할 수 있었다. 애플리케이션의 규모가 커질수록 의존성 관리는 더욱 중요한 요소가 되며, NestJS의 강력한 기능을 활용하여 모듈을 구성하고 의존성을 관리하는 방법을 숙지하는 것이 필요할 것 이다.</p>
<h3 id="오늘의-질의-응답😎">오늘의 질의 응답😎</h3>
<h4 id="primary-key-foreign-key에-대해-설명해주세요">Primary Key, Foreign Key에 대해 설명해주세요.</h4>
<p>나의 답변 😄</p>
<p>Primary Key(기본 키)는 RDBMS 테이블에서 각 레코드를 고유하게 식별하는 열로, 중복과 무결성을 보장합니다. Foreign Key(외래 키)는 다른 테이블의 Primary Key와 연결되는 열로, 관계를 형성하여 데이터 간 참조를 구현하며 데이터 일관성을 유지하고 관리합니다. Foreign Key는 참조된 테이블의 Primary Key와 일치해야 하며, 이를 통해 테이블 간의 관계를 설정할 수 있습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[외래키 오류]]></title>
            <link>https://velog.io/@sh_j225/%EC%99%B8%EB%9E%98%ED%82%A4-%EC%98%A4%EB%A5%98</link>
            <guid>https://velog.io/@sh_j225/%EC%99%B8%EB%9E%98%ED%82%A4-%EC%98%A4%EB%A5%98</guid>
            <pubDate>Fri, 18 Aug 2023 11:03:19 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/sh_j225/post/c158eead-5930-4903-a8b7-a303161b6a22/image.png" alt=""></p>
<p>이 오류는 외래 키 제약 조건이 실패했을 때 발생하는 것입니다. card 테이블에서 todoId 열이 외래 키로 설정되어 있으며, 이 열은 todo 테이블의 todoId 열을 참조해야 합니다. 따라서 card 테이블에 데이터를 추가하거나 업데이트할 때 todoId의 값이 todo 테이블에 존재하는 유효한 값이어야 합니다.</p>
<h4 id="이-오류가-발생하는-이유는">이 오류가 발생하는 이유는</h4>
<ol>
<li>새로운 카드를 생성하거나 업데이트할 때 todoId 값을 잘못 설정한 경우</li>
<li>card 테이블과 todo 테이블 간에 데이터 불일치가 있는 경우 
(예: todoId가 todo 테이블에 존재하지 않는 값인 경우)</li>
<li>todo 테이블과 card 테이블이 동일한 데이터베이스에 있지 않는 경우</li>
</ol>
<h4 id="해결-방법">해결 방법:</h4>
<p>CardController의 createCard() 메서드와 updateCard() 메서드에서 createCardDto.todoId 값을 올바르게 설정하고, 해당 todoId 값이 실제로 todo 테이블에 존재하는지 확인.
card 테이블과 todo 테이블 간의 외래 키 제약 조건을 확인하여 데이터 일치성을 유지.
todo 테이블과 card 테이블이 동일한 데이터베이스에 있는지 확인하고, 올바른 연결을 사용하고 있는지 확인.
데이터베이스의 외래 키 관계와 연결이 올바른지 확인하고, 데이터를 추가하거나 업데이트할 때 todoId 값을 제대로 설정하는지 확인.</p>
<p><img src="https://velog.velcdn.com/images/sh_j225/post/35295710-ae59-46db-83fe-59207c43d372/image.png" alt=""></p>
<h4 id="cardentity의-관계를-재설정하여-오류-해결">card.entity의 관계를 재설정하여 오류 해결.</h4>
<h3 id="오늘의-질의-응답😎">오늘의 질의 응답😎</h3>
<h4 id="rdbms의-정규화에-대해-설명해주세요">RDBMS의 정규화에 대해 설명해주세요.</h4>
<p>나의 답변 😄</p>
<p>정규화는 RDBMS에서 데이터를 효율적으로 저장하고 관리하기 위해 사용되는 과정입니다. 데이터 중복과 이상 현상을 최소화하여 데이터 일관성과 무결성을 유지하고, 1NF부터 5NF까지의 정규형을 따라 데이터를 분해하며, 이로써 중복을 제거하고 연결된 테이블 간의 관계를 명확하게 정의하여 데이터베이스의 구조를 최적화하는 역할을 합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TypeORM: TypeScript와 JavaScript를 위한 객체 관계 매핑(ORM) 라이브러리]]></title>
            <link>https://velog.io/@sh_j225/TypeORM-TypeScript%EC%99%80-JavaScript%EB%A5%BC-%EC%9C%84%ED%95%9C-%EA%B0%9D%EC%B2%B4-%EA%B4%80%EA%B3%84-%EB%A7%A4%ED%95%91ORM-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC</link>
            <guid>https://velog.io/@sh_j225/TypeORM-TypeScript%EC%99%80-JavaScript%EB%A5%BC-%EC%9C%84%ED%95%9C-%EA%B0%9D%EC%B2%B4-%EA%B4%80%EA%B3%84-%EB%A7%A4%ED%95%91ORM-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC</guid>
            <pubDate>Thu, 17 Aug 2023 10:54:06 GMT</pubDate>
            <description><![CDATA[<h2 id="typeorm-typescript와-javascript를-위한-객체-관계-매핑orm-라이브러리">TypeORM: TypeScript와 JavaScript를 위한 객체 관계 매핑(ORM) 라이브러리</h2>
<p>TypeORM은 데이터베이스와 상호작용하는 데 도움이 되는 강력한 라이브러리로, TypeScript와 JavaScript 프로젝트에서 사용할 수 있다. ORM은 객체 지향 프로그래밍과 데이터베이스 간의 간극을 줄여주며, 데이터베이스의 테이블과 애플리케이션의 클래스를 매핑함으로써 개발자들이 더 효율적으로 데이터를 다룰 수 있게 한다.</p>
<h3 id="typeorm의-주요-특징">TypeORM의 주요 특징</h3>
<h4 id="1-객체-지향적-모델링-데이터베이스-테이블을-typescript-클래스로-정의할-수-있습니다-이는-데이터의-구조를-직관적으로-표현하며-코드의-가독성과-유지보수성을-높일-수-있다">1. 객체 지향적 모델링: 데이터베이스 테이블을 TypeScript 클래스로 정의할 수 있습니다. 이는 데이터의 구조를 직관적으로 표현하며, 코드의 가독성과 유지보수성을 높일 수 있다.</h4>
<h4 id="2매우-다양한-데이터베이스-지원-typeorm은-postgresql-mysql-sqlite-mssql-등-다양한-데이터베이스-시스템과-호환된다">2.매우 다양한 데이터베이스 지원: TypeORM은 PostgreSQL, MySQL, SQLite, MSSQL 등 다양한 데이터베이스 시스템과 호환된다.</h4>
<h4 id="3-마이그레이션-관리-데이터베이스-스키마를-변경할-때-생기는-문제를-해결하기-위해-typeorm은-마이그레이션을-지원한다-데이터베이스-스키마를-버전-관리하고-업데이트하는-프로세스를-간편하게-만들어준다">3. 마이그레이션 관리: 데이터베이스 스키마를 변경할 때 생기는 문제를 해결하기 위해 TypeORM은 마이그레이션을 지원한다. 데이터베이스 스키마를 버전 관리하고 업데이트하는 프로세스를 간편하게 만들어준다.</h4>
<h4 id="4-쿼리-언어-지원-typeorm은-데이터베이스-쿼리를-직접-작성하는-것-외에도-쿼리-빌더를-제공하여-보다-효율적으로-데이터를-가져올-수-있다">4. 쿼리 언어 지원: TypeORM은 데이터베이스 쿼리를 직접 작성하는 것 외에도 쿼리 빌더를 제공하여 보다 효율적으로 데이터를 가져올 수 있다.</h4>
<h4 id="5-유지보수성-향상-객체-지향적-모델링과-마이그레이션-지원으로-데이터베이스-스키마-변경-시-발생하는-문제를-최소화하며-코드-유지보수를-용이하다">5. 유지보수성 향상: 객체 지향적 모델링과 마이그레이션 지원으로 데이터베이스 스키마 변경 시 발생하는 문제를 최소화하며, 코드 유지보수를 용이하다.</h4>
<h4 id="6-생산성-향상-클래스-기반의-데이터베이스-모델을-사용하면서-생산성이-향상된다-crudcreate-read-update-delete-작업을-좀-더-직관적으로-수행할-수-있다">6. 생산성 향상: 클래스 기반의 데이터베이스 모델을 사용하면서 생산성이 향상된다. CRUD(Create, Read, Update, Delete) 작업을 좀 더 직관적으로 수행할 수 있다.</h4>
<h4 id="7-유연한-데이터베이스-선택-다양한-데이터베이스-시스템과-호환되므로-프로젝트의-요구에-맞게-데이터베이스를-선택하여-이용할-수-있다">7. 유연한 데이터베이스 선택: 다양한 데이터베이스 시스템과 호환되므로 프로젝트의 요구에 맞게 데이터베이스를 선택하여 이용할 수 있다.</h4>
<blockquote>
<p>TypeORM은 TypeScript와 JavaScript 프로젝트에서 데이터베이스 작업을 더욱 효율적으로 처리하기 위한 강력한 도구다. ORM의 이점을 활용하여 코드의 가독성과 유지보수성을 향상시키며, 데이터베이스와의 상호작용을 간소화할 수 있다.</p>
</blockquote>
<h2 id="오늘의-질의-응답😎">오늘의 질의 응답😎</h2>
<h3 id="mvc-패턴에-대해서-설명해주세요">mvc 패턴에 대해서 설명해주세요.</h3>
<p>나의 답변 😄</p>
<p>MVC 패턴은 소프트웨어 디자인 패턴 중 하나로, 소프트웨어를 세 가지 주요 부분으로 분리하는 방법입니다. 모델은 데이터와 비즈니스 로직을 관리하며, 뷰는 사용자 인터페이스를 담당하고, 컨트롤러는 모델과 뷰 간의 상호작용을 관리합니다. 이렇게 분리된 구성은 코드의 재사용성과 유지보수성을 높여 원활한 코드관리에 용이합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Nest.js를 알아보자]]></title>
            <link>https://velog.io/@sh_j225/Nest.js%EB%A5%BC-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90</link>
            <guid>https://velog.io/@sh_j225/Nest.js%EB%A5%BC-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90</guid>
            <pubDate>Wed, 16 Aug 2023 11:45:36 GMT</pubDate>
            <description><![CDATA[<p>Nest.js는 Node.js 기반의 서버 사이드 애플리케이션을 개발하기 위한 프레임워크로, TypeScript를 활용한 모듈, 아키텍처와 간결한 코드 작성을 제공하는 Node.js 프레임워크로, 효율적이고 확장 가능한 서버 애플리케이션을 개발할 때 유용한 도구다.</p>
<blockquote>
<h3 id="1-모듈-아키텍처-nestjs는-모듈-기반-아키텍처를-채택하여-코드의-모듈화와-재사용성을-높이고-의존성을-관리할-수-있게-해준다">1. 모듈 아키텍처: Nest.js는 모듈 기반 아키텍처를 채택하여 코드의 모듈화와 재사용성을 높이고 의존성을 관리할 수 있게 해준다.</h3>
</blockquote>
<blockquote>
<h3 id="2-decorator-사용-typescript의-데코레이터를-활용하여-간결하고-직관적인-코드-작성이-가능하다-이를-통해-의존성-주입-및-미들웨어-사용-등이-용이해지는-장점이-있다">2. Decorator 사용: TypeScript의 데코레이터를 활용하여 간결하고 직관적인 코드 작성이 가능하다. 이를 통해 의존성 주입 및 미들웨어 사용 등이 용이해지는 장점이 있다.</h3>
</blockquote>
<blockquote>
<h3 id="3-의존성-주입-의존성-주입패턴을-적극적으로-활용하여-모듈-간의-결합도를-줄이고-테스트-용이성을-높일-수-있다">3. 의존성 주입: 의존성 주입패턴을 적극적으로 활용하여 모듈 간의 결합도를 줄이고 테스트 용이성을 높일 수 있다.</h3>
</blockquote>
<blockquote>
<h3 id="4강력한-cli-nest-cli를-통해-프로젝트-구조-생성-모듈컨트롤러서비스-생성-등을-간단하게-수행할-수-있다">4.강력한 CLI: Nest CLI를 통해 프로젝트 구조 생성, 모듈/컨트롤러/서비스 생성 등을 간단하게 수행할 수 있다.</h3>
</blockquote>
<blockquote>
<h3 id="5-express-및-fastify-지원-express-또는-fastify와-같은-웹-프레임워크를-내부적으로-사용할-수-있어-선택한-웹-서버에-대한-유연성을-제공할-수-있다">5. Express 및 Fastify 지원: Express 또는 Fastify와 같은 웹 프레임워크를 내부적으로 사용할 수 있어, 선택한 웹 서버에 대한 유연성을 제공할 수 있다.</h3>
</blockquote>
<blockquote>
<h3 id="6-middleware와-파이프-미들웨어와-파이프를-통해-요청-및-응답-데이터를-가공하거나-검증하는-로직을-구현하기에-용이하다">6. Middleware와 파이프: 미들웨어와 파이프를 통해 요청 및 응답 데이터를 가공하거나 검증하는 로직을 구현하기에 용이하다.</h3>
</blockquote>
<blockquote>
<h3 id="7-exception-필터와-인터셉터-예외-처리와-요청-인터셉트를-지원하여-에러-처리와-로깅을-효율적으로-관리할-수-있다">7. Exception 필터와 인터셉터: 예외 처리와 요청 인터셉트를 지원하여 에러 처리와 로깅을 효율적으로 관리할 수 있다.</h3>
</blockquote>
<blockquote>
<h3 id="8-typescript-지원-typescript를-기본-언어로-사용하며-정적-타입-체크와-강력한-개발-도구를-제공하여-개발-생산성을-높일-수-있다">8. TypeScript 지원: TypeScript를 기본 언어로 사용하며, 정적 타입 체크와 강력한 개발 도구를 제공하여 개발 생산성을 높일 수 있다.</h3>
</blockquote>
<blockquote>
<h3 id="9-구조적-일관성-모듈-아키텍처와-데코레이터를-통해-코드의-구조적-일관성을-유지하면서-유연한-애플리케이션을-구축할-수-있다">9. 구조적 일관성: 모듈 아키텍처와 데코레이터를 통해 코드의 구조적 일관성을 유지하면서 유연한 애플리케이션을 구축할 수 있다.</h3>
</blockquote>
<blockquote>
<h3 id="10-테스트-용이성-의존성-주입과-모듈화된-코드로-인해-단위-테스트-및-통합-테스트를-용이하게-수행할-수-있다">10. 테스트 용이성: 의존성 주입과 모듈화된 코드로 인해 단위 테스트 및 통합 테스트를 용이하게 수행할 수 있다.</h3>
</blockquote>
<blockquote>
<h3 id="11-확장성-모듈-기반-아키텍처와-미들웨어-인터셉터를-통해-애플리케이션을-쉽게-확장하고-변경할-수-있다">11. 확장성: 모듈 기반 아키텍처와 미들웨어, 인터셉터를 통해 애플리케이션을 쉽게 확장하고 변경할 수 있다.</h3>
</blockquote>
<blockquote>
<h3 id="12-커뮤니티와-생태계-활발한-커뮤니티와-다양한-패키지-라이브러리-등을-활용하여-개발을-지원받을-수-있다">12. 커뮤니티와 생태계: 활발한 커뮤니티와 다양한 패키지, 라이브러리 등을 활용하여 개발을 지원받을 수 있다.</h3>
</blockquote>
<h2 id="오늘의-질의-응답😎">오늘의 질의 응답😎</h2>
<h3 id="nosql과-rdbms의-특징과-차이점에-대해서-장-단점을-들어-설명해주세요">NoSQL과 RDBMS의 특징과 차이점에 대해서 장, 단점을 들어 설명해주세요.</h3>
<p>나의 답변 😄</p>
<p> RDBMS는 정형 데이터를 테이블 형식으로 관리하여 데이터의 일관성과 무결성을 보장합니다. 강력한 SQL 쿼리로 복잡한 질의와 분석을 수행할 수 있지만, 대용량 데이터 처리와 확장에 제약이 있습니다. 데이터의 구조를 미리 정의해야 하고, 스키마 변화가 제한적입니다. 그에 반해 NoSQL은 다양한 데이터 유형과 비정형 데이터를 처리하며, 데이터 유연성과 확장성을 강조합니다. 분산 처리로 대용량 데이터 처리가 용이하나 ACID 특성을 모두 만족하지 않고 일관성 제어가 어려울 수 있습니다. 쿼리 언어가 표준화되지 않아 복잡한 쿼리에 제한이 있을 수 있습니다. RDBMS와 NoSQL은 각자의 강점과 제약으로 선택은 데이터 특성, 처리 방식, 요구 사항에 따라 달라집니다. 정형 데이터와 복잡한 질의에선 RDBMS가, 다양한 데이터 유형과 확장성에선 NoSQL이 유용할 수 있습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[프로젝트 완료! ]]></title>
            <link>https://velog.io/@sh_j225/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%99%84%EB%A3%8C</link>
            <guid>https://velog.io/@sh_j225/%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%99%84%EB%A3%8C</guid>
            <pubDate>Fri, 11 Aug 2023 12:02:49 GMT</pubDate>
            <description><![CDATA[<p><a href="https://gleaming-harp-2af.notion.site/9-9-9-691e5aa238994e2293bb8bb37971cb80">https://gleaming-harp-2af.notion.site/9-9-9-691e5aa238994e2293bb8bb37971cb80</a></p>
<p>링크로 대체!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[git fork 조심하자!]]></title>
            <link>https://velog.io/@sh_j225/git-fork-%EC%A1%B0%EC%8B%AC%ED%95%98%EC%9E%90</link>
            <guid>https://velog.io/@sh_j225/git-fork-%EC%A1%B0%EC%8B%AC%ED%95%98%EC%9E%90</guid>
            <pubDate>Wed, 09 Aug 2023 13:03:50 GMT</pubDate>
            <description><![CDATA[<p>&quot;Git fork&quot;는 프로젝트의 소스 코드를 원본 저장소에서 분기하여 복사하는 작업을 의미한다. 기본적으로 Git fork는 협업 및 기여를 위한 목적으로 사용되며, 오픈 소스 프로젝트에 기여하거나 자체적으로 수정한 버전을 유지하고 싶을 때 유용하다. 하지만 때로는 Git fork를 사용하는 것이 적합하지 않을 수 있는 상황도 있다</p>
<h4 id="프로젝트의-개발-방향을-따르고-싶은-경우">프로젝트의 개발 방향을 따르고 싶은 경우:</h4>
<p>원본 프로젝트의 개발 방향과 목표를 따라가야 하는 상황에서는 fork하지 않고 원본 저장소를 직접 사용하는 것이 더 나을 수 있다. Fork를 사용하면 프로젝트가 독립적으로 발전하며, 원본 프로젝트의 업데이트를 받아들이기 어려울 수 있다.</p>
<h4 id="프로젝트를-다시-병합할-필요가-있는-경우">프로젝트를 다시 병합할 필요가 있는 경우:</h4>
<p>원본 프로젝트의 업데이트를 받고 수정한 내용을 다시 원본 프로젝트로 병합하려면 fork 대신 브랜치를 사용하는 것이 더 적절할 수 있다. Fork를 사용하면 원본 저장소와 분리되어 병합 작업이 더 복잡해질 수 있다.</p>
<h4 id="프로젝트의-독립성을-유지하고-싶은-경우">프로젝트의 독립성을 유지하고 싶은 경우:</h4>
<p>프로젝트를 fork하면 원본 저장소와 완전히 독립된 저장소가 생성된다. 이는 일부 상황에서는 좋을 수 있지만, 프로젝트 간의 연계성을 유지하거나 원본 프로젝트의 기능을 유지하려는 목적으로는 부적합할 수 있다.</p>
<h4 id="프로젝트를-오픈-소스로-공개하고-싶은-경우">프로젝트를 오픈 소스로 공개하고 싶은 경우:</h4>
<p>프로젝트를 fork하여 자체적으로 수정하고 관리하면, 해당 프로젝트는 기존 원본과 다른 독립적인 엔티티로써 존재하게 된다. 프로젝트를 오픈 소스로 공개하고 다른 개발자들과 협업하려면, fork 대신 원본 저장소에서 직접 작업하거나, pull request를 통해 기여하는 것이 더 좋을 수 있다.</p>
<p>따라서 상황에 따라 Git fork를 사용할지 여부를 신중하게 결정하는 것이 중요하고, Fork의 목적과 장단점을 고려하여 프로젝트를 효과적으로 관리하고 개발하는 습관을 만들어보자.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[VS Code] project tree - 파일 트리 구조 자동 생성]]></title>
            <link>https://velog.io/@sh_j225/VS-Code-project-tree-%ED%8C%8C%EC%9D%BC-%ED%8A%B8%EB%A6%AC-%EA%B5%AC%EC%A1%B0-%EC%9E%90%EB%8F%99-%EC%83%9D%EC%84%B1</link>
            <guid>https://velog.io/@sh_j225/VS-Code-project-tree-%ED%8C%8C%EC%9D%BC-%ED%8A%B8%EB%A6%AC-%EA%B5%AC%EC%A1%B0-%EC%9E%90%EB%8F%99-%EC%83%9D%EC%84%B1</guid>
            <pubDate>Mon, 07 Aug 2023 13:37:59 GMT</pubDate>
            <description><![CDATA[<p>VS Code(Visual Studio Code)는 Microsoft에서 개발한 무료이며 경량화된 텍스트 편집기이자 통합 개발 환경(IDE)이다. VS Code는 다양한 프로그래밍 언어와 프레임워크를 지원하며, 확장성이 뛰어나서 사용자들이 원하는 기능을 추가할 수 있다.</p>
<p>&quot;Project Tree&quot;라는 용어는 일반적으로 프로젝트의 디렉토리 구조와 파일을 시각적으로 표시하는 기능을 의미한다. </p>
<h4 id="프로젝트-폴더-열기-vs-code를-실행하고-메뉴에서-파일file--폴더-열기open-folder를-선택하여-프로젝트-폴더를-연다">프로젝트 폴더 열기: VS Code를 실행하고 메뉴에서 &quot;파일(File)&quot; &gt; &quot;폴더 열기(Open Folder)&quot;를 선택하여 프로젝트 폴더를 연다.</h4>
<h4 id="사이드바-탐색기-사용-왼쪽-사이드바의-탐색기explorer-아이콘을-클릭하거나-cmd--shift--e-mac-키보드-단축키를-사용하여-탐색기를-연다">사이드바 탐색기 사용: 왼쪽 사이드바의 탐색기(Explorer) 아이콘을 클릭하거나 Cmd + Shift + E (Mac) 키보드 단축키를 사용하여 탐색기를 연다.</h4>
<h4 id="폴더-및-파일-표시-탐색기에서는-열려있는-프로젝트의-폴더-및-파일을-표시한다-프로젝트-내의-폴더를-확장하고-파일을-선택하여-내용을-확인할-수-있다">폴더 및 파일 표시: 탐색기에서는 열려있는 프로젝트의 폴더 및 파일을 표시한다. 프로젝트 내의 폴더를 확장하고 파일을 선택하여 내용을 확인할 수 있다.</h4>
<h4 id="확장-기능extensions-설치-프로젝트-트리에-더-많은-정보나-기능을-추가하려면-확장-기능을-설치하여-사용하면-된다-예를-들어-project-manager와-같은-확장-기능을-설치하면-여러-프로젝트를-관리하고-빠르게-전환할-수-있다">확장 기능(Extensions) 설치: 프로젝트 트리에 더 많은 정보나 기능을 추가하려면 확장 기능을 설치하여 사용하면 된다. 예를 들어, &quot;Project Manager&quot;와 같은 확장 기능을 설치하면 여러 프로젝트를 관리하고 빠르게 전환할 수 있다.</h4>
<h4 id="작업-공간workspace-설정-작업-공간을-설정하여-특정-프로젝트와-관련된-설정-확장-기능-등을-따로-관리할-수-있다-파일file--작업-공간-저장workspace-save-as을-선택하여-작업-공간을-만들고-설정을-저장할-수-있다">작업 공간(Workspace) 설정: 작업 공간을 설정하여 특정 프로젝트와 관련된 설정, 확장 기능 등을 따로 관리할 수 있다. &quot;파일(File)&quot; &gt; &quot;작업 공간 저장(Workspace Save As)&quot;을 선택하여 작업 공간을 만들고 설정을 저장할 수 있다.</h4>
<h4 id="파일-및-폴더-생성-탐색기에서-마우스-오른쪽-버튼을-클릭하거나-cmd--n-mac-키보드-단축키를-사용하여-새-파일이나-폴더를-생성할-수-있다">파일 및 폴더 생성: 탐색기에서 마우스 오른쪽 버튼을 클릭하거나 Cmd + N (Mac) 키보드 단축키를 사용하여 새 파일이나 폴더를 생성할 수 있다.</h4>
<h4 id="파일-탐색-및-편집-탐색기에서-파일을-더블-클릭하여-편집하거나-오른쪽-버튼을-클릭하여-파일을-탐색하고-다양한-작업을-수행할-수-있다">파일 탐색 및 편집: 탐색기에서 파일을 더블 클릭하여 편집하거나, 오른쪽 버튼을 클릭하여 파일을 탐색하고 다양한 작업을 수행할 수 있다.</h4>
<p>이렇게 하면 VS Code 내에서 프로젝트 트리를 관리하고 작업할 수 있다.</p>
]]></description>
        </item>
    </channel>
</rss>