<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>intwocave&#039;s Diary</title>
	<atom:link href="https://intwocave.com/feed/" rel="self" type="application/rss+xml" />
	<link>https://intwocave.com</link>
	<description>intwocave&#039;s Diary</description>
	<lastBuildDate>Wed, 14 Jan 2026 09:32:45 +0000</lastBuildDate>
	<language>ko-KR</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://intwocave.com/wp-content/uploads/2024/04/cave-1-150x150.png</url>
	<title>intwocave&#039;s Diary</title>
	<link>https://intwocave.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>고급 프로젝트 &#060;CODI-IT&gt; 개별 개발 리포트</title>
		<link>https://intwocave.com/417/</link>
					<comments>https://intwocave.com/417/#comments</comments>
		
		<dc:creator><![CDATA[intwocave]]></dc:creator>
		<pubDate>Wed, 14 Jan 2026 09:31:59 +0000</pubDate>
				<category><![CDATA[코드잇]]></category>
		<guid isPermaLink="false">https://intwocave.com/?p=417</guid>

					<description><![CDATA[1. 프로젝트 개요 본 프로젝트는 패션 이커머스 플랫폼의 웹 서비스 개발과 구축을 목표로 하였습니다. 기본적으로 오픈마켓 형태의 시스템을 갖으며, 판매자와 구매자 두 역할로 나뉩니다. 판매자는 자신만의 상점을 개설하고 상품을 등록, 관리할 수 있으며, 구매자는 상품을 구매하고 리뷰를 작성하는 등의 역할을 수행합니다. 프로젝트를 진행하면서 주로 문의(Inquiry)와 리뷰(Review 작성) API 서비스 로직 작성 및 CI/CD 파이프라인 구축을 [&#8230;]]]></description>
										<content:encoded><![CDATA[
<h1 class="wp-block-heading"><strong>1. 프로젝트 개요</strong></h1>



<p>본 프로젝트는 패션 이커머스 플랫폼의 웹 서비스 개발과 구축을 목표로 하였습니다. 기본적으로 오픈마켓 형태의 시스템을 갖으며, 판매자와 구매자 두 역할로 나뉩니다. 판매자는 자신만의 상점을 개설하고 상품을 등록, 관리할 수 있으며, 구매자는 상품을 구매하고 리뷰를 작성하는 등의 역할을 수행합니다.</p>



<p>프로젝트를 진행하면서 주로 문의(Inquiry)와 리뷰(Review 작성) API 서비스 로직 작성 및 CI/CD 파이프라인 구축을 담당하였으며, 가독성 및 유지보수성이 좋은 코드 품질 유지을 위해 노력했습니다.</p>



<ul class="wp-block-list">
<li><strong>프로젝트명</strong>: CODI-IT</li>



<li><strong>기간</strong>: 2025년 12월 1일(기획) ~ 2026년 1월 13일(최종 발표)</li>



<li><strong>담당 역할</strong>:
<ul class="wp-block-list">
<li><strong>핵심 백엔드 로직 일부</strong>: 리뷰(Review) 및 문의(Inquiry) 시스템 전담 개발</li>



<li><strong>데브옵스</strong>: Docker 컨테이너화 및 GitHub Actions 기반 CI/CD 파이프라인 구축</li>



<li><strong>DB 설계</strong>: Prisma Schema 설계 및 마이그레이션 관리</li>
</ul>
</li>



<li><strong>참조</strong>
<ul class="wp-block-list">
<li><strong>GitHub Repository</strong>: <a href="https://github.com/kokooa/nb04-CODIIT-team3">https://github.com/kokooa/nb04-CODIIT-team3<span class="fa fa-rocket external-icon anchor-icon"></span></a></li>
</ul>
</li>
</ul>



<div style="height:40px" aria-hidden="true" class="wp-block-spacer"></div>



<h1 class="wp-block-heading">2. 기술 스택</h1>



<ul class="wp-block-list">
<li><strong>언어 및 프레임워크</strong>: TypeScript, Node.js, Express.js</li>



<li><strong>DBMS / ORM</strong>: AWS RDS, PostgreSQL, Prisma ORM</li>



<li><strong>Infrastructure</strong>: Docker, Docker Compose, Nginx</li>



<li><strong>CI/CD</strong>: GitHub Actions, GHCR, AWS EC2</li>



<li><strong>Tooling</strong>: Prettier, ESLint</li>
</ul>



<div style="height:40px" aria-hidden="true" class="wp-block-spacer"></div>



<h1 class="wp-block-heading">3. 핵심 구현 기능</h1>



<h6 class="wp-block-heading">리뷰 시스템</h6>



<p>단순한 CRUD를 넘어, 데이터 무결성과 비즈니스 로직의 정합성을 최우선으로 구현했습니다.</p>



<ul class="wp-block-list">
<li><strong>구매 검증 로직</strong>: <code>fetchOrderItem</code>을 통해 실제 상품을 구매한 유저만 리뷰를 작성할 수 있도록 검증하여 가짜 리뷰를 원천 차단</li>



<li><strong>중복 방지</strong>: checkReviewExists 로직을 통해 주문 상품 하나당 하나의 리뷰만 작성되도록 제한, 데이터 중복을 방지</li>



<li><strong>권한 제어</strong>: 본인의 주문 내역에 대해서만 접근 가능하도록 Service 계층에서 철저한 권한 검증(Authorization)을 수행</li>
</ul>



<pre class="wp-block-code javascript"><code><span class="fz-12px">export const createReview = async (
  params: CreateReviewParamsDto,
): Promise&lt;CreateReviewResponseDto&gt; =&gt; {
  const { productId, userId, data } = params;

  <strong><span class="marker-blue">// 주문 내역 유효성 검사 (구매 여부 및 본인 확인)</span></strong>
  const orderItem = await reviewRepository.<strong>fetchOrderItem</strong>(data.orderItemId);

  if (!orderItem) {
    throw new HttpError('주문 내역을 찾을 수 없습니다.', 404);
  }
  if (orderItem.productId !== productId) {
    throw new HttpError('해당 상품에 대한 주문 내역이 아닙니다.', 400);
  }
  if (orderItem.order.userId !== userId) {
    throw new HttpError(
      '본인의 주문 내역에 대해서만 리뷰를 작성할 수 있습니다.',
      403,
    );
  }

<strong>  <span class="marker-red">// 중복 리뷰 검사</span></strong>
  const reviewExists = await reviewRepository.<strong>checkReviewExists</strong>(
    data.orderItemId,
  );
  if (reviewExists) {
    throw new HttpError('이미 해당 주문 내역에 대한 리뷰를 작성했습니다.', 409);
  }

  // 리뷰 작성
  const createdReview = await reviewRepository.createReview(params);

  if (!createdReview) {
    throw new HttpError('리뷰 작성에 실패했습니다.', 500);
  }

  return createdReview;
};</span></code></pre>



<h6 class="wp-block-heading">문의 시스템</h6>



<p>구매자와 판매자 간의 원활한 소통을 위해 보안(비밀글)과 알림 기능이 결합된 문의 시스템을 구축했습니다.</p>



<ul class="wp-block-list">
<li><strong>비밀글 로직</strong>: <code>isSecret</code> 플래그를 도입하여, 작성자와 해당 스토어 판매자 외에는 내용을 볼 수 없도록 Row-Level Security에 준하는 로직을 애플리케이션 레벨에서 구현</li>



<li><strong>판매자 답변 및 알림 연동</strong>: 판매자가 답변을 등록하면, 즉시 <code>NotificationService</code>와 연동하여 구매자에게 알림이 발송되는 이벤트 기반 설계를 적용</li>



<li><strong>원자적 트랜잭션 처리</strong>: 문의 답변 등록 시 Prisma 트랜잭션을 적용하여, 답변 생성과 문의 상태 변경(답변완료) 두 가지 작업이 반드시 동시에 성공하거나 실패하도록 보장</li>



<li><strong>쿼리 최적화</strong>: <code>include</code> 대신 중첩 <code>select</code> 방식을 채택하여, 연관된 테이블에서 불필요한 필드는 제외하고 필요한 데이터만 조회함으로써 DB 부하를 줄이고 응답 속도를 개선</li>
</ul>



<h6 class="wp-block-heading">CI/CD &amp; Docker</h6>



<p>개발 생산성 향상과 안정적인 배포를 위해 CI/CD 환경을 구축하였습니다.</p>



<ul class="wp-block-list">
<li><strong>Docker Multi-stage Build</strong>: builder 스테이지와 production 스테이지를 분리하여, 빌드 도구를 제외한 경량화된 프로덕션 이미지를 생성 (용량 최적화)</li>



<li><strong>GitHub Actions CI/CD</strong>: 
<ul class="wp-block-list">
<li><strong>CI</strong>: GitHub에서 Push 이벤트 살생 시 Formatting → Type Check → Build 과정을 자동화하여 코드 품질을 일관되게 보장</li>



<li><strong>CD</strong>: Docker 이미지를 빌드하여 GHCR에 푸시하고, EC2 서버에서 <code>docker-compose</code>를 통해 자동 배포를 구현</li>
</ul>
</li>
</ul>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<h1 class="wp-block-heading">4. 기술적 성과 및 문제 해결</h1>



<h6 class="wp-block-heading">서비스 계층 분리를 통한 유지보수성 향상</h6>



<ul class="wp-block-list">
<li><strong>문제</strong>: 컨트롤러에 비즈니스 로직이 집중될 경우, 코드 중복과 테스트 어려움 발생 우려</li>



<li><strong>해결</strong>: 3-Layer Architecture (Controller &#8211; Service &#8211; Repository)를 엄격히 적용
<ul class="wp-block-list">
<li>Repository는 Prisma를 사용한 순수 DB 접근만 담당 (<code>fetchReviewDetailById</code> 등)</li>



<li>Service는 비즈니스 검증 로직만 담당 (<code>validateUser, checkSecretAccess</code> 등)</li>
</ul>
</li>



<li>성과: 코드의 책임이 명확해져 팀원들이 내 코드를 참조하기 쉬워졌으며, 유지보수가 용이한 구조를 완성</li>
</ul>



<h6 class="wp-block-heading">DTO를 활용한 타입 안정성 확보</h6>



<ul class="wp-block-list">
<li><strong>성과</strong>: <code>ReviewDetailParamsDto</code>, <code>CreateInquiryParamsDto</code> 등 명확한 DTO를 정의하여, 프론트엔드에서 넘어오는 데이터의 타입을 런타임 이전에 컴파일 타임에서 보장받아 런타임 에러를 획기적으로 경감</li>
</ul>



<h6 class="wp-block-heading">인프라 구축으로 팀 개발 효율 증대</h6>



<ul class="wp-block-list">
<li><strong>성과</strong>: 로컬에서는 <code>docker-compose</code>로 DB와 앱을 한 번에 실행하고, 배포 시에는 GitHub Actions가 자동으로 수행되게 함으로써 팀원들이 배포가 아닌 개발에만 집중할 수 있는 환경을 제공</li>
</ul>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<h1 class="wp-block-heading">5. 코드 품질 및 협업</h1>



<ul class="wp-block-list">
<li><strong>일관된 에러 처리</strong>: HttpError 클래스를 공통으로 사용하여, 여러 HTTP Status Code를 의미론적으로 정확하게 반환하도록 구현</li>



<li><strong>Prettier &amp; Linting</strong>: CI 파이프라인에 프맷팅 체크를 강제하여, 5명의 팀원이 작성한 코드가 마치 한 명이 작성한 것처럼 일관된 스타일을 유지하도록 함</li>
</ul>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<h1 class="wp-block-heading">6. 향후 개선 사항</h1>



<ul class="wp-block-list">
<li><strong>테스트 코드 커버리지</strong>: 현재 CI 파이프라인에 <code>npm test</code> 단계가 주석 처리되어 있는데, 향후 Jest 등을 활용한 Unit Test를 추가하여 비즈니스 로직의 안정성을 더욱 강화하고 싶습니다.</li>



<li><strong>트랜잭션 관리 고도화</strong>: 현재는 단일 모델 업데이트가 주를 이루지만, 추후 &#8216;리뷰 작성 시 포인트 적립&#8217;과 같이 두 개 이상의 테이블을 동시에 수정해야 할 경우 Prisma의 Interactive Transactions를 적용하여 데이터 정합성을 더욱 견고히 할 예정입니다.</li>



<li><strong>캐싱 도입</strong>: 리뷰 조회가 빈번한 인기 상품의 경우, Redis 등 인-메모리 캐싱 시스템을 도입하여 조회 성능을 최적화할 여지가 있습니다.</li>



<li><strong>무중단 배포 도입</strong>: 현재 CI/CD 파이프라인에서 배포를 자동화하고는 있지만, 새롭게 Pull 받은 이미지로 갱신하기 위해 <code>docker-compose</code>로 실행 중인 컨테이너를 단순히 <code>restart</code>하고 있습니다. 추후 Rolling, Blue/Green, Canary 등의 아키텍처를 도입하여 무중단 배포를 구현하고 싶습니다.</li>
</ul>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<h1 class="wp-block-heading">7. 프로젝트 회고</h1>



<p>이번 프로젝트에서 리뷰와 문의, 그리고 CI/CD라는 핵심 도메인을 설계부터 구현까지 주도적으로 수행하며, 데이터의 흐름과 무결성을 지키는 백엔드 개발의 책임감을 배울 수 있었습니다. 특히 Docker와 GitHub Actions를 통한 CI/CD 파이프라인 도입은 이번 프로젝트에서 처음 시도해본 것인데, 이를 직접 구축하여 팀 전체의 개발 사이클을 효율화시킨 경함은 큰 자산이 되었습니다.</p>



<p>그러나 팀원 간 커뮤니케이션이 좀 더 활발하게 이루어졌더라면, 전체 개발 일정의 단축과 추가 기능 도입까지 이룰 수 있었을 것이라는 아쉬움도 남습니다.</p>



<p>이번 프로젝트는 비즈니스 로직 구현 능력과 인프라 핸들링 능력을 동시에 배우고 익힐 수 있었던 뜻깊은 시간이었습니다.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://intwocave.com/417/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>위클리 페이퍼 18주차 정리</title>
		<link>https://intwocave.com/413/</link>
					<comments>https://intwocave.com/413/#respond</comments>
		
		<dc:creator><![CDATA[intwocave]]></dc:creator>
		<pubDate>Sun, 09 Nov 2025 15:44:03 +0000</pubDate>
				<category><![CDATA[코드잇]]></category>
		<guid isPermaLink="false">https://intwocave.com/?p=413</guid>

					<description><![CDATA[Q1. 1:1 관계를 만드는 방법에 대해 SQL 문법으로 설명해 주세요. 개념 1:1 관계는 테이블 A의 레코드 하나가 테이블 B의 레코드 하나와만 정확히 매칭되는 관계다. (예: User와 UserProfile) 가장 일반적인 구현 방법은 두 테이블이 동일한 기본 키(Primary Key)를 공유하도록 하거나, 한 테이블의 외래 키(Foreign Key)에 UNIQUE 제약 조건을 추가하는 것이다. 더 명확한 방법은 두 테이블이 동일한 [&#8230;]]]></description>
										<content:encoded><![CDATA[
<h3 class="wp-block-heading">Q1. 1:1 관계를 만드는 방법에 대해 SQL 문법으로 설명해 주세요.</h3>



<h6 class="wp-block-heading">개념</h6>



<p>1:1 관계는 테이블 A의 레코드 하나가 테이블 B의 레코드 하나와만 정확히 매칭되는 관계다. (예: <code>User</code>와 <code>UserProfile</code>)</p>



<p>가장 일반적인 구현 방법은 <strong>두 테이블이 동일한 기본 키(Primary Key)를 공유</strong>하도록 하거나, 한 테이블의 <strong>외래 키(Foreign Key)에 <code>UNIQUE</code> 제약 조건을 추가</strong>하는 것이다.</p>



<p>더 명확한 방법은 두 테이블이 동일한 PK를 공유하는 것이다.</p>



<p><strong>예시: <code>Users</code> 테이블과 <code>UserProfiles</code> 테이블</strong></p>



<p>1. 먼저, 기준이 되는 <code>Users</code> 테이블을 만든다.</p>



<ol start="1" class="wp-block-list"></ol>



<pre class="wp-block-code"><code>CREATE TABLE Users (
    user_id INT PRIMARY KEY,
    username VARCHAR(100) NOT NULL UNIQUE
    -- 기타 사용자 기본 정보
);</code></pre>



<p>2. 다음으로, <code>UserProfiles</code> 테이블을 만들 때 <code>user_id</code>를 <code>Users</code> 테이블의 <code>user_id</code>를 참조하는 <code><strong>FOREIGN KEY</strong></code>이면서 동시에 <code>UserProfiles</code> 테이블의 <code><strong>PRIMARY KEY</strong></code>로 지정한다.</p>



<pre class="wp-block-code"><code>CREATE TABLE UserProfiles (
    user_id INT PRIMARY KEY,  -- 이 테이블의 PK이자
    full_name VARCHAR(100),
    bio TEXT,

    -- Users 테이블의 user_id를 참조하는 FK 설정
    FOREIGN KEY (user_id) REFERENCES Users(user_id)
);</code></pre>



<p><strong>핵심:</strong> <code>UserProfiles</code>의 <code>user_id</code>가 <code>PRIMARY KEY</code>이므로 <strong>반드시 고유(Unique)</strong>해야 한다. 동시에 <code>Users</code> 테이블을 참조하는 <code>FOREIGN KEY</code>이기도 하므로, <code>Users</code> 테이블에 존재하는 <code>user_id</code>만 가질 수 있다. 이 두 가지 제약 조건이 결합되어 1:1 관계가 완성된다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading">Q2. M:N 관계를 만드는 방법에 대해 SQL 문법으로 설명해 주세요.</h3>



<h6 class="wp-block-heading">개념</h6>



<p>M:N 관계는 테이블 A의 레코드 하나가 테이블 B의 여러 레코드와 관계를 맺을 수 있고, 그 반대도 마찬가지인 관계다. (예: <code>Students</code>와 <code>Courses</code>)</p>



<p>M:N 관계는 두 테이블만으로는 직접 구현할 수 없으며, 두 테이블을 연결하는 <strong>중간 테이블(Junction Table 또는 Mapping Table)</strong>이 반드시 필요하다.</p>



<p><strong>예시: <code>Students</code> 테이블과 <code>Courses</code> 테이블</strong></p>



<p>1. <code>Students</code> 테이블을 만든다.</p>



<pre class="wp-block-code"><code>CREATE TABLE Students (
    student_id INT PRIMARY KEY,
    student_name VARCHAR(100) NOT NULL
);</code></pre>



<p>2. <code>Courses</code> 테이블을 만든다.</p>



<pre class="wp-block-code"><code>CREATE TABLE Courses (
    course_id INT PRIMARY KEY,
    course_name VARCHAR(100) NOT NULL
);</code></pre>



<p>3. 두 테이블을 연결할 중간 테이블 <code>Enrollments</code> (수강신청)를 만든다. 이 테이블은 두 테이블의 PK를 각각 FK로 받는다.</p>



<pre class="wp-block-code"><code>CREATE TABLE Enrollments (
    student_id INT,
    course_id INT,

    -- 두 컬럼을 조합하여 복합 기본 키(Composite Primary Key)로 설정
    PRIMARY KEY (student_id, course_id),

    -- Students 테이블을 참조하는 FK
    FOREIGN KEY (student_id) REFERENCES Students(student_id),

    -- Courses 테이블을 참조하는 FK
    FOREIGN KEY (course_id) REFERENCES Courses(course_id)
);</code></pre>



<p><strong>핵심:</strong> <code>Enrollments</code> 테이블은 어떤 학생(<code>student_id</code>)이 어떤 과목(<code>course_id</code>)을 수강하는지 매핑한다. <code>(student_id, course_id)</code> 조합 자체가 <code>PRIMARY KEY</code>이므로 &#8220;한 학생이 동일한 과목을 여러 번&#8221; 등록하는 중복을 방지한다.</p>



<ul class="wp-block-list">
<li>한 학생(Student)은 여러 <code>Enrollments</code> 레코드를 가질 수 있다. (여러 과목 수강)</li>



<li>한 과목(Course)도 여러 <code>Enrollments</code> 레코드를 가질 수 있다. (여러 학생이 수강)</li>
</ul>
]]></content:encoded>
					
					<wfw:commentRss>https://intwocave.com/413/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>위클리 페이퍼 17주차 정리</title>
		<link>https://intwocave.com/392/</link>
					<comments>https://intwocave.com/392/#respond</comments>
		
		<dc:creator><![CDATA[intwocave]]></dc:creator>
		<pubDate>Sun, 02 Nov 2025 18:19:29 +0000</pubDate>
				<category><![CDATA[코드잇]]></category>
		<guid isPermaLink="false">https://intwocave.com/?p=392</guid>

					<description><![CDATA[Q1. 관계형 데이터베이스에서 무결성이 무엇인지 설명해 주세요. 개념 관계형 데이터베이스에서 무결성은 데이터베이스 내의 데이터가 항상 정확하고, 일관되며, 유효한 상태를 유지하도록 보장하는 성질을 말한다. 즉, 데이터베이스에 결점이 없는 상태, 신뢰할 수 있는 데이터만 저장되도록 하는 규칙이자 제약 조건이다. 데이터 무결성이 중요한 이유는 사용자가 데이터를 신뢰하고 이를 바탕으로 올바른 결정을 내릴 수 있게 하기 때문이다. 데이터베이스는 여러 [&#8230;]]]></description>
										<content:encoded><![CDATA[
<h3 class="wp-block-heading"><strong>Q1.</strong> 관계형 데이터베이스에서 무결성이 무엇인지 설명해 주세요.</h3>



<h6 class="wp-block-heading">개념</h6>



<p>관계형 데이터베이스에서 <strong>무결성</strong>은 데이터베이스 내의 데이터가 항상 <strong>정확</strong>하고, <strong>일관</strong>되며, <strong>유효</strong>한 상태를 유지하도록 보장하는 성질을 말한다. 즉, 데이터베이스에 <strong>결점이 없는 상태</strong>, 신뢰할 수 있는 데이터만 저장되도록 하는 규칙이자 제약 조건이다.</p>



<p>데이터 무결성이 중요한 이유는 사용자가 데이터를 신뢰하고 이를 바탕으로 올바른 결정을 내릴 수 있게 하기 때문이다.</p>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<p>데이터베이스는 여러 가지 제약 조건을 통해 무결성을 강제한다.</p>



<ul class="wp-block-list">
<li><strong>개체 무결성 (Entity Integrity):</strong>
<ul class="wp-block-list">
<li>테이블의 모든 행(row)이 고유하게 식별되어야 한다는 규칙.</li>



<li>이를 위해 <strong>기본 키(Primary Key, PK)</strong>를 사용하며, 기본 키로 지정된 열은 <strong>NULL 값을 가질 수 없고 항상 고유한 값</strong>을 가져야 함.</li>
</ul>
</li>



<li><strong>참조 무결성 (Referential Integrity):</strong>
<ul class="wp-block-list">
<li>두 테이블 간의 관계가 항상 일관성을 유지하도록 보장하는 규칙.</li>



<li><strong>외래 키(Foreign Key, FK)</strong>를 사용하여 구현. 외래 키는 한 테이블의 열이 다른 테이블의 기본 키를 참조할 때, 이 외래 키의 값은 참조하는 테이블의 기본 키 값이거나 NULL이어야 함.</li>



<li>예를 들어, &#8216;주문&#8217; 테이블의 &#8216;고객ID&#8217;는 반드시 &#8216;고객&#8217; 테이블에 존재하는 &#8216;고객ID&#8217;여야 하며, 존재하지 않는 고객의 주문을 생성할 수 없음.</li>
</ul>
</li>



<li><strong>도메인 무결성 (Domain Integrity):</strong>
<ul class="wp-block-list">
<li>테이블의 특정 열(column)에 입력될 수 있는 값의 범위를 제한하는 규칙.</li>



<li>데이터 타입(예: 숫자, 문자열), 허용되는 값의 범위(예: &#8216;성별&#8217; 열에는 &#8216;남&#8217; 또는 &#8216;여&#8217;만 가능), 또는 형식을 지정하여 데이터가 유효한 범위 내에 있도록 보장.</li>
</ul>
</li>



<li><strong>사용자 정의 무결성 (User-Defined Integrity):</strong>
<ul class="wp-block-list">
<li>위의 세 가지 유형 외에, 특정 비즈니스 논리나 규칙을 데이터베이스에 적용.</li>



<li>예를 들어, &#8216;월급&#8217; 열의 값은 항상 0보다 커야 한다는 규칙 등을 설정할 수 있음.</li>
</ul>
</li>
</ul>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><strong>Q2.</strong> 관계형 데이터베이스에서 마이그레이션이란 무엇인지 설명해 주세요.</h3>



<h6 class="wp-block-heading">개념</h6>



<p><strong>마이그레이션</strong>은 데이터를 한 시스템에서 다른 시스템으로 이전하거나 이동하는 전체 과정을 의미한다. 데이터베이스의 맥락에서는 기존 데이터베이스 시스템을 새로운 시스템으로 옮기거나 업그레이드하는 작업을 말한다.</p>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<h6 class="wp-block-heading">마이그레이션의 주요 목적</h6>



<ul class="wp-block-list">
<li><strong>시스템 업그레이드:</strong> 오래된(legacy) 데이터베이스 시스템을 더 새롭고 성능이 좋은 시스템으로 교체할 때 (예: 구버전 MySQL에서 최신 버전 PostgreSQL로 이전)</li>



<li><strong>클라우드 이전:</strong> 기업 내부 서버(On-premise)에서 운영하던 데이터베이스를 AWS, Google Cloud, Azure 등 클라우드 환경으로 이전할 때</li>



<li><strong>비용 절감:</strong> 라이선스 비용이 비싼 상용 데이터베이스에서 오픈소스 데이터베이스로 전환하여 운영 비용을 줄이고자 할 때</li>



<li><strong>데이터 통합:</strong> 여러 곳에 흩어져 있던 데이터베이스를 하나의 중앙 데이터베이스로 통합할 때</li>
</ul>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<h6 class="wp-block-heading">마이그레이션 과정</h6>



<p>데이터 마이그레이션은 단순히 데이터를 복사-붙여넣기 하는 작업이 아니며, 데이터 손실이나 서비스 중단을 최소화하기 위해 다음과 같은 체계적인 계획과 절차가 필요하다.</p>



<ol start="1" class="wp-block-list">
<li><strong>계획 및 평가:</strong> 현재 시스템을 분석하고, 새로운 시스템의 요구사항을 정의하며, 마이그레이션 전략(일시 중단 후 전체 이전 vs. 단계적 이전)을 수립.</li>



<li><strong>데이터 추출 및 변환:</strong> 기존 시스템에서 데이터를 추출하고, 새로운 시스템의 구조(스키마)에 맞게 데이터를 변환하거나 정제.</li>



<li><strong>테스트:</strong> 실제 데이터의 일부를 이용해 마이그레이션 테스트를 수행하여 데이터가 정확하게 옮겨지는지, 성능에 문제는 없는지 검증.</li>



<li><strong>실행:</strong> 계획된 절차에 따라 실제 데이터 마이그레이션을 실행.</li>



<li><strong>검증:</strong> 마이그레이션 완료 후, 모든 데이터가 누락되거나 변형되지 않았는지 최종적으로 확인하고 검증.</li>
</ol>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://intwocave.com/392/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>중급 프로젝트 &#060;Dear Carmate&gt; 개별 개발 리포트</title>
		<link>https://intwocave.com/379/</link>
					<comments>https://intwocave.com/379/#respond</comments>
		
		<dc:creator><![CDATA[intwocave]]></dc:creator>
		<pubDate>Wed, 29 Oct 2025 10:26:41 +0000</pubDate>
				<category><![CDATA[코드잇]]></category>
		<guid isPermaLink="false">https://intwocave.com/?p=379</guid>

					<description><![CDATA[1. 서론 본 프로젝트는 중고차 계약 관리 서비스 개발로, 고객사의 관리자가 차량 및 고객의 계약과 계약서를 쉽고 효율적으로 관리할 수 있는 서비스 제공을 목표로 하였다. 팀 단위로 진행되었으며, 이 프로젝트에서 난 계약서 파일의 업로드 및 다운로드, 계약 목록을 조회하는 API, 그리고 등록된 계약들에 대한 통계를 산출하여 도표로 표시해 주는 대시보드 API의 개발을 담당하였다. 2. 개인 [&#8230;]]]></description>
										<content:encoded><![CDATA[
<h6 class="wp-block-heading">1. 서론</h6>



<p>본 프로젝트는 중고차 계약 관리 서비스 개발로, 고객사의 관리자가 차량 및 고객의 계약과 계약서를 쉽고 효율적으로 관리할 수 있는 서비스 제공을 목표로 하였다. 팀 단위로 진행되었으며, 이 프로젝트에서 난 계약서 파일의 업로드 및 다운로드, 계약 목록을 조회하는 API, 그리고 등록된 계약들에 대한 통계를 산출하여 도표로 표시해 주는 대시보드 API의 개발을 담당하였다.</p>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<h6 class="wp-block-heading">2. 개인 담당 파트 및 역할</h6>



<p><strong>계약 목록 조회</strong></p>



<ul class="wp-block-list">
<li>등록된 계약 목록을 DB로부터 가져온 후, API 명세에 맞게 가공하여 반환</li>



<li>페이지네이션 가능</li>



<li>계약서명, 담당자명으로 검색 가능</li>
</ul>



<p><strong>계약서 파일 업로드</strong> <strong>및 등록</strong></p>



<ul class="wp-block-list">
<li>유효한 확장자(jpg, png, pdf)의 파일만 업로드 가능</li>



<li>업로드 파일 개수, 용량 제한</li>



<li>계약서가 등록될 경우 고객에게 자동으로 계약서가 첨부된 이메일 발송</li>
</ul>



<p><strong>계약서 파일 다운로드</strong></p>



<ul class="wp-block-list">
<li>업로드 된 계약서 파일 중 일부 혹은 전체를 일괄 다운로드 가능</li>
</ul>



<p><strong>대시보드를 위한 통계</strong> <strong>데이터</strong></p>



<ul class="wp-block-list">
<li>이달의 매출, 진행 중인 계약 수, 성사된 계약 수를 표시</li>



<li>차량타입별 계약수, 차량타입별 매출액을 표시</li>



<li>저장된 계약 및 차량 데이터 등을 DB 집계 함수를 통해 계산 및 가공하여 반환</li>
</ul>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<h6 class="wp-block-heading">3. 진행 과정</h6>



<ol class="wp-block-list">
<li>팀원 간 역할과 책임 정의, 일정 조율, 컨벤션 결정</li>



<li>DB 스키마 설계</li>



<li>레이어드 아키텍처 설계 패턴을 적용하여 각 역할에 해당하는 기능 개발</li>



<li>리팩토링 및 버그 수정, 테스트</li>



<li>코드 품질관리 및 배포</li>



<li>프로젝트 마무리 후 발표</li>
</ol>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<h6 class="wp-block-heading">4. 배운 점</h6>



<p><strong>코드 리뷰 및 피드백의 중요성</strong></p>



<ul class="wp-block-list">
<li>초급 프로젝트에서도 느꼈지만, 프로젝트 진행 및 개발에 있어서 코드 리뷰 및 피드백은 더 나은 개발자가 되기 위해 너무나도 중요한 과정이다. 이번 중급 프로젝트에서는 Github의 Issue와 Pull Request가 이전 프로젝트보다 더 활발히 등록되었는데, 작성한 코드에 대한 문제점이나 개선점, 혹은 발견된 오류에 대해 어떻게 해결하면 될지 예시 코드를 제안받는 등 구글 검색이나 AI를 통한 배움과는 다른 맛이 있었다. 특히나 &#8216;프로젝트 완수&#8217;라는 공동의 목표를 갖고 있는 사람들이기에 열정을 갖고 개발에 임할 수 있었다.</li>
</ul>



<p><strong>Pre-commit Hook의 중요성</strong></p>



<ul class="wp-block-list">
<li>팀원 중 한 분이 프로젝트 초기 계획 된계에서 Husky와 Vitest를 이용하여 Pre-commit 단계에서 코드의 유효성을 검증하고, 단위 및 통합 테스트를 자동화하여 커밋 후에 발생할 수 있는 오류를 미연에 방지할 수 있도록 컨벤션을 구성하였다. <code>git commit</code> 커맨드를 실행하면 커밋 메시지 창이 뜨던 초급 프로젝트 때와는 다르게 미리 설정해 둔 테스트가 실행되는 것이 다소 어색했지만, 코드의 유효성을 검증한 다음 브랜치에 최종 병합되어 나중의 수고를 덜어주는 아주 중요한 역할을 하였다. </li>
</ul>



<p><strong>테스트의 중요성</strong></p>



<ul class="wp-block-list">
<li>위에서 언급한 Pre-commit Hook의 Task에 있었던 테스트는 Vitest라는 패키지를 활용하여 이뤄졌는데, 단위(Unit) 테스트, 통합(Integration) 테스트, 그리고 엔드투엔드(E2E) 테스트로 규모별로 나누어 진행하였다. 그중 엔드투엔드 테스트는 전체 애플리케이션의 처음부터 끝까지의 사용자 시나리오를 검증하는 테스트인데, 시간은 좀 걸리지만 앱 전체를 검증해주기에 사용자 경험을 향상시키고 잠재적인 문제를 조기에 발견하여 개발 효율성을 높이는 장점이 있다. 초급 프로젝트에서는 이런 테스트 도구를 전혀 사용하지 않고 개발자가 일일이 테스트를 했기 때문에, 버그를 발견하고 수정하기까지 시간이 오래 걸렸다.</li>
</ul>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<h6 class="wp-block-heading">5. 개선점</h6>



<p><strong>컨테이너화</strong></p>



<ul class="wp-block-list">
<li>팀원 중 한 분이 백엔드 서버를 Docker로 컨테이너화하여 배포 과정을 단순화하자고 제안하셨고, 실제 도커 설정 파일을 작성하고 도커 이미지까지 생성하긴 했다. 그러나 발표까지 시간이 촉박했기에 Docker를 충분히 활용하지 못했고, 아직 컨테이너 사용 경험이 별로 없어서 여러가지로 미숙했다. 개발을 마치고 서버에 배포하는 과정에서 환경변수의 설정이나 패키지 설치 등, 여러가지로 신경써야 할 부분이 많다. 그러나 컨테이너를 사용한다면 이러한 수고를 덜 수 있을 것이다.</li>
</ul>



<p><strong>타입 안정성</strong></p>



<ul class="wp-block-list">
<li>초급 프로젝트에서는 타입 안정성이 없는 JavaScript를 사용하였지만, 이번 프로젝트에선 TypeScript를 사용하였다. 타입 안정성을 위한 여러 가지 기능을 지원하는 TypeScript를 십분 활용하기 위해 Type, Interface 등을 최대한 많이 활용하려고 애썼으나, 타입과 인터페이스를 정의하고 DTO를 작성하는 것은 꽤나 수고로운 작업이었고, 결국 충분히 활용하지 못했다고 생각한다. 타입을 정의하는 것이 수고스러운 작업일지라도 JavaScript 대신 TypeScript가 현업에서 주류로 사용된다는 것을 보면 타입 안정성이 주는 장점은 내가 생각하는 것보다 훨씬 클 것이므로, 다음 프로젝트에서는 이를 유념하고 타입 안정성에 신경을 써야 할 것이다.</li>
</ul>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<h6 class="wp-block-heading">6. 결론</h6>



<p>이번 팀 프로젝트는 타입스크립트를 사용한 첫 프로젝트인데, 사실 타입을 사용한다는 점을 제외하면 초급 프로젝트와 난이도는 큰 차이가 없다고 느꼈다.</p>



<p>그러나 좋은 팀을 만난 덕분에 여러가지를 배웠고, 발표 또한 성공리에 마무리할 수 있었다.</p>



<p>이번 프로젝트를 진행하면서 느낀 점 중 하나는, &#8216;팀 프로젝트&#8217;에 &#8216;팀&#8217;이 들어가는 이유는 팀원들끼리 서로 협력하고 돕기 때문이란 것이다. 당연한 말처럼 들리지만, 팀 프로젝트를 더 팀 프로젝트처럼 진행하기 위해서는 소통과 협력이 꼭 필요하고, 만약 그렇지 않다면 개인전과 크게 다르지 않다고 생각한다.</p>



<p>그렇기에 이번 프로젝트는 팀 프로젝트가 무엇인지 다시 생각하게 되는 좋은 경험이었다.</p>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://intwocave.com/379/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>위클리 페이퍼 10주차 정리</title>
		<link>https://intwocave.com/375/</link>
					<comments>https://intwocave.com/375/#respond</comments>
		
		<dc:creator><![CDATA[intwocave]]></dc:creator>
		<pubDate>Sun, 14 Sep 2025 18:58:42 +0000</pubDate>
				<category><![CDATA[코드잇]]></category>
		<guid isPermaLink="false">https://intwocave.com/?p=375</guid>

					<description><![CDATA[Q1. 세션 기반 인증에 대해 설명해 주세요. 개념 세션 기반 인증이란, 서버가 사용자의 로그인 상태를 세션(session)이라는 형태로 서버 메모리나 DB(i.e. Redis)에 저장하고, 클라이언트는 세션을 식별하는 세션 ID를 쿠키로 받아 요청마다 서버에 보낸다. 서버는 이 세션 ID를 확인해 사용자를 식별하는 인증 방식이다. 흐름 장점 단점 Q2. 토큰 기반 인증에 대해 설명해 주세요. 개념 서버가 인증 성공 [&#8230;]]]></description>
										<content:encoded><![CDATA[
<h3 class="wp-block-heading"><strong>Q1.</strong> 세션 기반 인증에 대해 설명해 주세요.</h3>



<h6 class="wp-block-heading">개념</h6>



<p><strong>세션 기반 인증</strong>이란, 서버가 <strong>사용자의 로그인 상태</strong>를 <strong>세션(session)이라는 형태</strong>로 서버 <strong>메모리나 DB</strong>(i.e. Redis)에 저장하고, 클라이언트는 세션을 식별하는 <strong>세션 ID</strong>를 쿠키로 받아 요청마다 서버에 보낸다.</p>



<p>서버는 이 세션 ID를 확인해 사용자를 식별하는 인증 방식이다.</p>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<h6 class="wp-block-heading">흐름</h6>



<ol class="wp-block-list">
<li>사용자가 ID/PW로 <strong>로그인</strong></li>



<li>서버는 <strong>세션 저장소에 사용자 정보를 기록</strong>하고, <strong>세션 ID를 생성</strong></li>



<li>세션 ID를 클라이언트에게 쿠키로 전달</li>



<li>클라이언트는 이후 <strong>요청마다 이 쿠키를 서버로 전송</strong></li>



<li>서버는 세션 저장소에서 <strong>세션 ID를 확인하고 사용자 인증</strong> 처리</li>
</ol>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<h6 class="wp-block-heading">장점</h6>



<ul class="wp-block-list">
<li><strong>구현이 간단</strong>하고 오래된 웹 프레임워크에서 기본 지원</li>



<li><strong>서버가 상태를 관리</strong>하므로 유저 정보 저장이 용이</li>
</ul>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<h6 class="wp-block-heading">단점</h6>



<ul class="wp-block-list">
<li>서버가 모든 세션을 기억해야 하므로 <strong>확장성 문제</strong> 발생 (특히 서버가 여러 대일 경우 세션 공유 필요)</li>



<li>모바일 앱이나 외부 API 연동에는 부적합</li>



<li>쿠키 기반이라 <strong>CSRF 취약 가능성</strong> 있음</li>
</ul>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><strong>Q2.</strong> 토큰 기반 인증에 대해 설명해 주세요.</h3>



<h6 class="wp-block-heading">개념</h6>



<p><strong>서버가 인증 성공 시 토큰을 발급</strong>하고, 클라이언트는 이후 요청마다 이 토큰을 <strong>Authorization Bearer 헤더</strong>에 담아 전송한다.</p>



<p>서버는 <strong>토큰 자체를 검증</strong>하여 사용자를 식별하고, 서버에 별도의 <strong>상태 저장이 필요 없다</strong>.</p>



<h6 class="wp-block-heading">흐름</h6>



<ol class="wp-block-list">
<li>사용자가 로그인 요청</li>



<li>서버가 사용자 <strong>검증 후 JWT 같은 토큰 생성</strong></li>



<li><strong>클라이언트는 토큰을 저장</strong> (쿠키, localStorage 등)</li>



<li>이후 요청 시 <strong>Authorization 헤더에 토큰 첨부</strong></li>



<li>서버는 <strong>토큰의</strong> <strong>유효성을 검증</strong> (서명/만료 시간 확인) 후 요청 처리</li>
</ol>



<h6 class="wp-block-heading">장점</h6>



<ul class="wp-block-list">
<li><strong>Stateless</strong>: 서버가 세션 상태를 저장하지 않아도 됨 (확장성과 분산 환경에서 유리)</li>



<li>모바일 앱, SPA, API 인증에 적합</li>



<li>인증 + 권한 부여까지 쉽게 처리 가능</li>
</ul>



<h6 class="wp-block-heading">단점</h6>



<ul class="wp-block-list">
<li>토큰이 탈취되면 만료될 때까지 무조건 유효 (서버가 강제로 무효화하기 어려움)</li>



<li>토큰이 길어질 수 있어 네트워크 트래픽 증가</li>



<li>구현 난이도가 세션보다 살짝 높음</li>
</ul>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://intwocave.com/375/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>위클리 페이퍼 9주차 정리</title>
		<link>https://intwocave.com/369/</link>
					<comments>https://intwocave.com/369/#respond</comments>
		
		<dc:creator><![CDATA[intwocave]]></dc:creator>
		<pubDate>Sun, 07 Sep 2025 17:58:51 +0000</pubDate>
				<category><![CDATA[코드잇]]></category>
		<guid isPermaLink="false">https://intwocave.com/?p=369</guid>

					<description><![CDATA[Q1. Express.js에서 미들웨어란 무엇인지 설명해 주세요. Express.js에서 미들웨어란, 요청(request)과 응답(response) 사이에서 동작하는 함수를 의미한다. 즉, 클라이언트 → 서버로 들어온 요청을 처리하는 과정에서, 중간에 거쳐가는 처리 단계라고 생각하면 쉽다. 미들웨어의 특징 Q2. 백엔드 서버에서 이미지 업로드를 구현하는 다양한 방식에 대해 설명해 주세요. 백엔드 서버에서 이미지 업로드를 구현하는 방식은 프로젝트의 요구사항(성능, 확장성, 비용, 보안 등)에 따라 달라지며, [&#8230;]]]></description>
										<content:encoded><![CDATA[
<h3 class="wp-block-heading"><strong>Q1.</strong> Express.js에서 미들웨어란 무엇인지 설명해 주세요.</h3>



<p>Express.js에서 미들웨어란, <strong>요청(request)과 응답(response) 사이에서 동작하는 함수</strong>를 의미한다.</p>



<p>즉, 클라이언트 → 서버로 들어온 요청을 처리하는 과정에서, <strong>중간에 거쳐가는 처리 단계</strong>라고 생각하면 쉽다.</p>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<h6 class="wp-block-heading"><strong><span class="fz-18px"><span class="fz-24px">미들웨어의 특징</span></span></strong></h6>



<ul class="wp-block-list">
<li>일반적으로 <strong>req, res, next</strong>라는 세 개의 인자를 갖으며, 다음과 같이 구성된다.</li>
</ul>



<pre class="wp-block-code"><code>function myMiddleware(req, res, next) {
  console.log("Middleware 실행됨");
  next(); // 다음 미들웨어로 제어를 넘김
}</code></pre>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<ul class="wp-block-list">
<li>요청 → 응답 과정에서 여러 개의 미들웨어를 <strong>체인 형태로 연결</strong>할 수 있다.</li>
</ul>



<pre class="wp-block-code"><code>const router = express.Router();
router.get(middleware1, middleware2, controller);</code></pre>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<ul class="wp-block-list">
<li>요청(req) 가공, 인증/인가, 로그, 에러 핸들링(err 인자 필요), 정적 파일 제공 등 여러가지 역할을 수행할 수 있다.</li>
</ul>



<pre class="wp-block-code"><code>import express from "express";
const app = express();

// 1. 로깅 미들웨어
function logger(req, res, next) {
  console.log(`${req.method} ${req.url}`);
  next(); // 다음으로 제어 넘기기
}

// 2. 인증 미들웨어
function auth(req, res, next) {
  if (!req.headers.authorization) {
    return res.status(401).json({ message: "Unauthorized" });
  }
  next();
}

// 3. 라우터
app.get("/profile", auth, (req, res) =&gt; {
  res.json({ message: "Welcome to profile!" });
});

// 전역 미들웨어 등록
app.use(logger);

// 에러 핸들링 미들웨어 (4개의 인자 필요!)
app.use((err, req, res, next) =&gt; {
  console.error(err.stack);
  res.status(500).json({ message: "Something broke!" });
});

app.listen(3000, () =&gt; console.log("Server running..."));</code></pre>



<div style="height:100px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<h3 class="wp-block-heading"><strong>Q2.</strong> 백엔드 서버에서 이미지 업로드를 구현하는 다양한 방식에 대해 설명해 주세요.</h3>



<p>백엔드 서버에서 이미지 업로드를 구현하는 방식은 프로젝트의 요구사항(성능, 확장성, 비용, 보안 등)에 따라 달라지며, 크게 나누면 <strong>저장 위치(로컬 vs 외부)와 전송 방식</strong>에 따라 여러 전략이 있다.</p>



<h6 class="wp-block-heading">1. 로컬 저장소(Local Storage)에 저장</h6>



<p>가장 단순한 방식으로, 클라이언트가 업로드한 이미지를 <strong>서버의 파일시스템에 저장</strong>하는 방법이다. 구현 방법은 다음과 같다.</p>



<ul class="wp-block-list">
<li><strong>Multer</strong> 같은 라이브러리를 이용해 <strong>multipart/form-data</strong> 요청을 파싱</li>



<li>dest 또는 diskStorage 옵션을 이용해 서버 디스크에 저장</li>



<li>DB에는 <strong>이미지 파일 경로(Path)</strong>만 저장</li>
</ul>



<pre class="wp-block-code"><code>import multer from "multer";
const upload = multer({ dest: "uploads/" });

app.post("/upload", upload.single("image"), (req, res) =&gt; {
  res.json({ file: req.file });
});</code></pre>



<p>간단하고 빠르게 구현 가능한 장점이 있으나, <strong>서버 확장(스케일 아웃) 시 이미지 동기화 문제</strong>가 발생할 수 있으며, 서버 <strong>디스크 용량에 의존</strong>한다는 단점이 있다.</p>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<h6 class="wp-block-heading">2. 데이터베이스에 BLOB(Binary Large Object) 형태로 저장</h6>



<p>이미지를 <strong>DB 칼럼에 직접 저장</strong>하는 방식이며, 구현 방법은 다음과 같다.</p>



<ul class="wp-block-list">
<li>이미지 파일을 Buffer 형태로 받아 DB 칼럼(bytea, BLOB)에 저장</li>



<li>Prisma ORM으로 다음과 같이 표현할 수 있다.</li>
</ul>



<pre class="wp-block-code"><code>await prisma.image.create({
  data: {
    filename: req.file.originalname,
    data: req.file.buffer, // Buffer 형태로 DB에 저장
  }
});</code></pre>



<p>DB 백업/복구만으로 파일 일관성을 보장할 수 있으나, 성능 저하가 발생할 수 있고 DB 용량에 부담되는 점, 그리고 <strong>대규모 서비스엔 비효율적</strong>이라는 단점이 있다.</p>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<h6 class="wp-block-heading">3. 외부 클라우드 스토리지에 저장</h6>



<p>이미지를 서버가 아니라 <strong>클라우드 스토리지에 저장</strong>하는 방식으로, 제공 서비스로는 AWS S3, Google Cloud Storage, Azure Blob Storage 등이 있다.</p>



<p>방식 1, 2에서는 클라이언트 → 서버로 데이터가 전송된다. 그러나 이 방식에서는 일반적으로 서버가 <strong>사전 서명 URL(Presigned URL)을 발급</strong>하고, <strong>클라이언트 → 클라우드 스토리지로 바로 전송</strong>되도록 하여 <strong>서버에 부담이 적다</strong>는 특징이 있다.</p>



<p>AWS S3 서비스를 예로 들면 다음과 같다.</p>



<pre class="wp-block-code"><code>import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";

const s3 = new S3Client({ region: "ap-northeast-2" });

async function uploadToS3(file) {
  const command = new PutObjectCommand({
    Bucket: "my-bucket",
    Key: file.originalname,
    Body: file.buffer,
    ContentType: file.mimetype,
  });
  await s3.send(command);
}</code></pre>



<p>이 방식은 <strong>확장성이 뛰어나고 CDN 연계가 용이</strong>하지만, <strong>클라우드 사용 비용이 발생</strong>하고 <strong>초기 설정이 복잡</strong>하다는 단점이 있다.</p>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<p>이외에도 업로드된 이미지를 <strong>CDN(Content Delivery Network)을 통해 배포</strong>하는 방법, <strong>대용량 파일 업르도 시 Chunk 단위로 나누어 업로드</strong>하는 방식, 이미지 데이터를 <strong>Base64 문자열로 변환하여 JSON body에 담아 전송</strong>하는 방법 등이 있다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>위 업로드 방식들 중 어느 방식을 쓰는 게 좋을지는, 진행하는 <strong>프로젝트의 규모나 목적</strong>에 따라 달라지는데, 간단히 정리하면 다음과 같다.</p>



<ul class="wp-block-list">
<li><strong>개인 프로젝트 / 소규모 서비스</strong> → 로컬 저장소 + DB에 경로 저장</li>



<li><strong>중소 규모 / 여러 서버 운영</strong> → AWS S3 같은 외부 스토리지</li>



<li><strong>대규모 글로벌 서비스</strong> → S3 + CDN + Presigned URL 방식</li>



<li><strong>보안이 중요한 서비스</strong> → Presigned URL + 인증 미들웨어</li>
</ul>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://intwocave.com/369/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>초급 프로젝트 &#060;SEVEN&gt; 개별 개발 리포트</title>
		<link>https://intwocave.com/362/</link>
					<comments>https://intwocave.com/362/#respond</comments>
		
		<dc:creator><![CDATA[intwocave]]></dc:creator>
		<pubDate>Mon, 01 Sep 2025 08:55:36 +0000</pubDate>
				<category><![CDATA[코드잇]]></category>
		<guid isPermaLink="false">https://intwocave.com/?p=362</guid>

					<description><![CDATA[1. 서론 본 프로젝트는 사용자로 하여금 함께 운동하고, 그 기록을 공유하여 사용자 간 열정과 성취감을 나누도록 하며, 커뮤니티를 형성하여 함께 소통하고 유대감을 쌓는 웹 기반 운동 기록 소셜 네트워크 서비스의 제공을 목표로 하였다. 팀 단위로 진행되었으며, 본인은 운동 기록에 대한 순위 반환, 이미지 업로드 API의 개발과 전체적인 코드 리팩토링을 담당하였다. 2. 개인 담당 파트 및 [&#8230;]]]></description>
										<content:encoded><![CDATA[
<h6 class="wp-block-heading"><span class="fz-24px"><span class="fz-32px">1. 서론</span></span></h6>



<p>본 프로젝트는 사용자로 하여금 함께 운동하고, 그 기록을 공유하여 사용자 간 열정과 성취감을 나누도록 하며, 커뮤니티를 형성하여 함께 소통하고 유대감을 쌓는 웹 기반 운동 기록 소셜 네트워크 서비스의 제공을 목표로 하였다. 팀 단위로 진행되었으며, 본인은 운동 기록에 대한 순위 반환, 이미지 업로드 API의 개발과 전체적인 코드 리팩토링을 담당하였다.</p>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<h6 class="wp-block-heading"><span class="fz-32px">2. 개인 담당 파트 및 역할</span></h6>



<p><span class="fz-28px"><span class="fz-24px"><span class="bold">운동 기록 순위 조회</span></span></span></p>



<ul class="wp-block-list">
<li>특정 그룹에 속하는 운동 기록을 운동 시간을 기준으로 정렬하여 반환</li>



<li>duration(weekly 및 monthly) 쿼리 스트링을 받아 기간별 순위 조회 구현</li>
</ul>



<p><strong><span class="fz-28px"><span class="fz-24px">이미지 업로드 기능</span></span></strong></p>



<ul class="wp-block-list">
<li>Multer 라이브러리를 통해 서버의 로컬 저장소에 이미지 파일 업로드 구현</li>



<li>업로드된 이미지에 대한 메타데이터를 DB에 저장</li>



<li>정적으로 접근 가능한 이미지 URL을 반환</li>
</ul>



<p><strong><span class="fz-24px">코드 리팩토링</span></strong></p>



<ul class="wp-block-list">
<li>프로젝트 중반까지 네이밍 컨벤션, 코드 스타일, 클래스 기반 설계 등이 제대로 이루어지지 않는 문제 발견</li>



<li>전체적인 소스 코드를 통틀어 리팩토링을 진행하였고, 네이밍 컨벤션을 kebab-case로 통일, 각 모듈을 Class-based로 통일</li>
</ul>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<h6 class="wp-block-heading"><span class="fz-32px">3. 개발 과정</span></h6>



<ol class="wp-block-list">
<li>팀원 간 역할과 책임 정의</li>



<li>Prisma ORM의 DB Scheme 설계</li>



<li>디렉토리 구조 설계 (router &#8211; controller &#8211; service &#8211; repository)</li>



<li>기능 개발</li>



<li>코드 리팩토링</li>



<li>README 작성</li>



<li>프로젝트 마무리 후 발표</li>
</ol>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<h6 class="wp-block-heading"><span class="fz-32px">4</span><span class="fz-32px">. 배운 점</span></h6>



<p><strong><span class="fz-24px">코드 리뷰의 중요성</span></strong></p>



<ul class="wp-block-list">
<li>팀 프로젝트로 협업하는 과정에서 PR을 등록하고, 변경 사항에 대해 코드 리뷰를 받았다. 팀원 분께서 정말 세세하고 꼼꼼한 부분까지 자세하게 코드 리뷰를 해 주셨는데, 해당 리뷰를 보고 개선 사항을 코드에 반영할 때마다 더 나은 코드가 무엇인지에 대해 고민하고 학습하는 좋은 기회가 되었다.</li>
</ul>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<p><strong><span class="fz-24px">코드 아키텍처의 중요성</span></strong></p>



<ul class="wp-block-list">
<li>프로젝트 진행 초반에 디렉토리 및 파일 구조와 소스 코드를 어떻게 작성할지에 대해 고민하는 과정에서 멘토님의 도움을 받아 &lt;Router &#8211; Controller &#8211; Service &#8211; Repository>의 네 단계로 구성하기로 했다. 디자인 패턴에서 자주 접할 수 있는 MVC 구조와 비교하면 Model과 Controller 사이에 Service가 하나 더 생긴 꼴인데, 비즈니스 로직과 Repository를 분리하는 것으로 더 깔끔하고 명확하면서 유지보수에 용이할 것이라는 생각을 직접 코드를 작성하면서 체감할 수 있었다.</li>
</ul>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<p><strong><span class="fz-24px">리팩토링의 중요성</span></strong></p>



<ul class="wp-block-list">
<li>프로젝트 중반에 멘토링을 진행했는데, 소스 코드에 전체적으로 리팩토링이 필요하다는 조언을 받았다. 코드 리팩토링을 내가 담당하게 되었는데, 비록 리팩토링이 완벽하게 되진 않았더라도 생각보다 어렵지 않게 진행할 수 있었다. 지금 생각해보니 그 이유는 API 명세서에 객체지향 설계를 도입하라는 요구사항이 있었고, 다행히도 나는 초반부터 객체지향 설계를 고려해서 코드를 작성했기에 다른 코드들도 같은 방식으로 변환하는 데 큰 어려움이 없었다.</li>



<li>또한 Prisma 인스턴스 또는 다양한 계층의 클래스 인스턴스가 각자 코드에서 생성되는 것이 기능 확장 및 유지보수성 측면에서 좋지 않을 것이라 생각했는데, 같은 부분을 우려한 팀원분과 협력하여 각 계층의 모듈을 index.js에 모으고, 각 index.js를 하나의 container.js에서 불러와 의존성 주입 패턴을 적용했다.</li>
</ul>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<h6 class="wp-block-heading"><span class="fz-32px">5. 개선점</span></h6>



<p><strong><span class="fz-24px">글로벌 에러 핸들러</span></strong></p>



<ul class="wp-block-list">
<li>팀원 각자가 기능별 개발을 담당하다 보니, 공통적으로 오류가 발생하는 부분에 대해 글로벌 에러 핸들러를 적용할 여지가 있었다. 부분적으로 글로벌 에러 핸들러를 적용하긴 했지만, 더 깔끔하고 가독성 좋게 코드를 리팩토링할 수 있었다. 그러나 그러지 못한 점이 아쉽다.</li>
</ul>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<h6 class="wp-block-heading"><span class="fz-32px">6</span><span class="fz-32px">. 결론</span></h6>



<p>이번 팀 프로젝트는 Git과 Github을 활용한 사실상 첫 협업이었기에 감회가 깊다.</p>



<p>처음 프로젝트를 시작할 때의 역할 분담과 스키마 설계 과정을 지나고부터는 어느 정도 원활하게 개발이 진행되었지만, 개발 도중 발생했던 팀원과의 미스커뮤니케이션이나 각종 에러, Git 경험 미숙으로 인한 커밋 충돌, 코드 리팩토링, 그리고 프론트엔드에서의 작동 확인에 애를 먹었다. </p>



<p>그러나 지나고 보면, 진행 과정에서 애먹었던 부분을 해결하는 과정에서 문제해결 능력을 기를 수 있었고, 몰랐던 부분을 충분히 익히는 기회가 되었다.</p>



<p>만약 나중에 같은 문제와 직면했을 때 큰 수고를 들이지 않고 해결할 수 있을 것이라는 자신감이 생겼으며, 지속적인 팀 프로젝트 경험을 통해 더 큰 문제와 맞딱드리고, 해결해보고 싶다는 생각마저 드는 귀중한 경험이었다.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://intwocave.com/362/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>위클리 페이퍼 8주차 정리</title>
		<link>https://intwocave.com/360/</link>
					<comments>https://intwocave.com/360/#respond</comments>
		
		<dc:creator><![CDATA[intwocave]]></dc:creator>
		<pubDate>Sun, 31 Aug 2025 18:29:00 +0000</pubDate>
				<category><![CDATA[코드잇]]></category>
		<guid isPermaLink="false">https://intwocave.com/?p=360</guid>

					<description><![CDATA[Q1. 웹 서비스에서 관계형 데이터베이스를 사용하는 이유 중 하나를 설명해 주세요. 데이터의 무결성과 일관성을 보장할 수 있기 때문입니다. 관계형 데이터베이스(RDB)는 ACID 특성(Atomicity, Consistency, Isolation, Durability)을 제공해서, 여러 사용자가 동시에 데이터를 읽고 쓰더라도 데이터가 깨지거나 충돌하지 않도록 관리해 줍니다. 예를 들어 은행 계좌 이체처럼 중요한 트랜잭션이 발생하는 상황에서도 정확하게 데이터를 유지할 수 있습니다. Q2. Primary Key와 [&#8230;]]]></description>
										<content:encoded><![CDATA[
<h3 class="wp-block-heading"><strong>Q1.</strong> 웹 서비스에서 관계형 데이터베이스를 사용하는 이유 중 하나를 설명해 주세요.</h3>



<p>데이터의 <strong><span class="marker">무결성</span></strong>과 <strong><span class="marker-blue">일관성</span></strong>을 보장할 수 있기 때문입니다.</p>



<p>관계형 데이터베이스(RDB)는 <strong><span class="marker">ACID 특성(Atomicity, Consistency, Isolation, Durability)을 제공</span></strong>해서, 여러 사용자가 동시에 데이터를 읽고 쓰더라도 데이터가 깨지거나 충돌하지 않도록 관리해 줍니다. 예를 들어 은행 계좌 이체처럼 중요한 트랜잭션이 발생하는 상황에서도 정확하게 데이터를 유지할 수 있습니다.</p>



<div style="height:100px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><strong>Q2.</strong> Primary Key와 Foreign Key에 대해 설명해 주세요.</h3>



<ul class="wp-block-list">
<li><strong>Primary Key (기본 키)</strong>
<ul class="wp-block-list">
<li>테이블에서 각 행(row)을 고유하게 식별하기 위해 사용되는 컬럼(또는 컬럼 조합).</li>



<li><code><strong>NULL</strong></code> 값을 가질 수 없고, 중복될 수 없음.</li>



<li>예: <code><strong>User</strong></code> 테이블의 <code><strong>user_id</strong></code></li>
</ul>
</li>



<li><strong>Foreign Key (외래 키)</strong>
<ul class="wp-block-list">
<li>다른 테이블의 Primary Key를 참조하는 키.</li>



<li>두 테이블 간 <strong>관계(relationship)</strong> 를 표현하고 데이터의 <strong>참조 무결성</strong>을 보장함.</li>



<li>예: <code><strong>Post</strong></code> 테이블의 <code><strong>user_id</strong></code> → <code><strong>User</strong>.<strong>user_id</strong></code> 참조</li>
</ul>
</li>
</ul>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://intwocave.com/360/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>위클리 페이퍼 5주차 정리</title>
		<link>https://intwocave.com/350/</link>
					<comments>https://intwocave.com/350/#comments</comments>
		
		<dc:creator><![CDATA[intwocave]]></dc:creator>
		<pubDate>Sun, 10 Aug 2025 19:03:08 +0000</pubDate>
				<category><![CDATA[코드잇]]></category>
		<guid isPermaLink="false">https://intwocave.com/?p=350</guid>

					<description><![CDATA[Q1. 프로세스와 스레드에 대해 설명해 주세요. 1. 프로세스란 프로세스는 간단하게 말하면, 실행 중인 프로그램입니다. 컴퓨터에서 프로그램을 실행한다는 것은 운영체제가 프로그램을 메인 메모리(RAM; Random Access Memory)에 로드하고 실행한다는 것을 의미하는데, 프로세스는 프로그램이 실행되면 생성됩니다. 각각의 프로세스는 독립적인 메모리 공간을 가지는데, 각 영역은 다음과 같습니다. 각 프로세스는 할당받은 메모리를 따로 쓰는데, 프로세스 간 통신(IPC; Inter-Process Communication)을 위해 [&#8230;]]]></description>
										<content:encoded><![CDATA[
<h3 class="wp-block-heading"> <strong>Q1.</strong> 프로세스와 스레드에 대해 설명해 주세요.</h3>



<h6 class="wp-block-heading">1. 프로세스란</h6>



<p>프로세스는 간단하게 말하면, <strong><span class="marker">실행 중인 프로그램</span></strong>입니다.</p>



<p>컴퓨터에서 프로그램을 실행한다는 것은 운영체제가 프로그램을 메인 메모리(RAM; Random Access Memory)에 로드하고 실행한다는 것을 의미하는데, <strong><span class="marker-red">프로세스는 프로그램이 실행되면 생성</span></strong>됩니다.</p>



<p>각각의 프로세스는 <strong><span class="marker-blue">독립적인 메모리 공간</span></strong>을 가지는데, 각 영역은 다음과 같습니다.</p>



<ul class="wp-block-list">
<li><strong>Code</strong>: 컴파일을 통해 변환된 기계어가 저장되는 공간</li>



<li><strong>Data</strong>: 전역 변수나 static 변수 등의 데이터가 저장되는 공간</li>



<li><strong>Heap</strong>: malloc 등으로 동적 할당된 메모리가 저장되는 공간</li>



<li><strong>Stack</strong>: 함수 호출, 지역 변수, 리턴값 등의 데이터가 저장되는 공간</li>
</ul>



<p>각 <strong><span class="marker">프로세스는 할당받은 메모리를 따로 쓰는데</span></strong>, <strong><span class="marker-blue">프로세스 간 통신(IPC; Inter-Process Communication)</span></strong>을 위해 공유 메모리(스레드), 파이프, 메시지 큐 등의 방법을 사용합니다.</p>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<h6 class="wp-block-heading">2. 스레드란</h6>



<p>스레드는 <strong><span class="marker">프로세스 안에서 실행되는 작은 실행 단위</span></strong>입니다.</p>



<p>하나의 프로세스 안에는 <strong><span class="marker-red">최소 한 개의 스레드가 존재</span></strong>하며, 두 개 이상의 스레드가 한 프로세스 안에 있을 수도 있습니다.</p>



<p>두 개 이상의 스레드가 존재하는 경우 스레드들은 프로세스의 <span class="marker-blue"><strong>Code, Data, Heap 메모리 영역을 공유</strong></span>하지만, <span class="marker"><strong>Stack 영역은 스레드별로 각각</strong></span> 가집니다.</p>



<p>같은 메모리 공간을 공유하는 만큼 스레드들은 본인이 속한 프로세스의 <strong><span class="marker-red"><span class="marker-blue">데이터를 서로 빠르게 주고받을 수 있지만</span></span></strong>, <strong><span class="marker"><span class="marker-red">동시에 하나의 자원에 접근하려고 하면 문제</span></span></strong>가 생길 수 있습니다. 이를 <strong><span class="marker">경쟁 상태(race condition)</span></strong>라고 합니다.</p>



<div style="height:100px" aria-hidden="true" class="wp-block-spacer"></div>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<div style="height:100px" aria-hidden="true" class="wp-block-spacer"></div>



<h3 class="wp-block-heading"><strong>Q2.</strong> 프레임워크와 라이브러리의 차이에 대해 설명해 주세요.</h3>



<h6 class="wp-block-heading">1. 라이브러리</h6>



<p>라이브러리는 <strong><span class="marker">특정 기능</span></strong> 및 역할을 하면서, 필요할 때 가져다 사용할 수 있는 코드의 모음이라고 할 수 있습니다.</p>



<p>즉, 프로그래머가 <strong><span class="marker-blue">프로그램의 흐름을 직접 제어하기 위해 사용하는 도구 모음</span></strong> 같은 느낌인데, 정리하면 다음과 같습니다.</p>



<ul class="wp-block-list">
<li>필요할 때 프로그래머가 불러와서 쓰는 도구 모음</li>



<li>프로그램의 흐름을 직접 제어하기 위해 사용</li>



<li>라이브러리는 단순히 기능을 제공</li>
</ul>



<div style="height:30px" aria-hidden="true" class="wp-block-spacer"></div>



<h6 class="wp-block-heading">2. 프레임워크</h6>



<p>프레임워크는 <strong><span class="marker">프로그램의 기본 구조와 흐름을 제공</span></strong>하며, 그 <strong><span class="marker-blue">규칙과 틀 안에서 프로그래머가 코드를 작성하는 방식</span></strong>입니다.</p>



<p>즉, 프로그램의 <strong><span class="marker">전반적인 제어권이 프레임워크</span></strong>에 있고, 프로그래머는 그 구조에 맞춰 <strong><span class="marker-blue">필요한 부분만 구현</span></strong>하는 느낌인데, 정리하면 다음과 같습니다.</p>



<ul class="wp-block-list">
<li>정해진 구조와 흐름 안에서 코드를 작성</li>



<li>프로그램의 흐름 제어권이 프레임워크에 있음</li>



<li>프레임워크가 필요한 시점에 프로그래머의 코드를 호출</li>
</ul>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://intwocave.com/350/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
		<item>
		<title>위클리 페이퍼 3주차 정리</title>
		<link>https://intwocave.com/336/</link>
					<comments>https://intwocave.com/336/#comments</comments>
		
		<dc:creator><![CDATA[intwocave]]></dc:creator>
		<pubDate>Sun, 27 Jul 2025 17:08:05 +0000</pubDate>
				<category><![CDATA[코드잇]]></category>
		<guid isPermaLink="false">https://intwocave.com/?p=336</guid>

					<description><![CDATA[Q1. 자바스크립트에서 모듈을 사용하는 이유에 대해 설명해 주세요. A1. 본래 웹 브라우저에서 사용되던 자바스크립트를 V8 엔진을 통해 브라우저 밖에서 범용적으로 사용되기 시작했는데, 초기 자바스크립트엔 모듈화가 어려웠기 때문에 한 파일에 모든 변수와 상수, 그리고 함수들을 작성하기엔 가독성과 유지보수성이 떨어지는 문제가 있었습니다. 따라서 C/C++에서 include 키워드를 사용하여 분리되어 있는 외부 코드나 기능을 불러오듯이, 자바스크립트에서도 모듈을 도입하여 이를 [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p><strong>Q1.</strong> 자바스크립트에서 <strong><span class="marker">모듈을 사용하는 이유</span></strong>에 대해 설명해 주세요.</p>



<p><strong>A1.</strong> 본래 웹 브라우저에서 사용되던 자바스크립트를 V8 엔진을 통해 브라우저 밖에서 범용적으로 사용되기 시작했는데, 초기 자바스크립트엔 모듈화가 어려웠기 때문에 한 파일에 모든 변수와 상수, 그리고 함수들을 작성하기엔 <strong><span class="marker-red">가독성과 유지보수성이 떨어지는 문제</span></strong>가 있었습니다.</p>



<p>따라서 C/C++에서 include 키워드를 사용하여 분리되어 있는 외부 코드나 기능을 불러오듯이, 자바스크립트에서도 <strong><span class="marker-blue">모듈을 도입하여 이를 해결</span></strong>하고자 하였습니다.</p>



<p>자바스크립트의 모듈화 명세를 만든 여러 그룹 중 하나인 <strong><span class="marker">CommonJS가 Node.js의 표준으로 채택</span></strong>되면서 널리 사용되기 시작했고, Node.js에서 모듈을 불러오기 위해 사용하는 require 키워드가 바로 CommonJS에서 모듈화를 구현하기 위한 방법입니다.</p>



<p>지금은 <strong><span class="marker-blue">ECMAScript 2015에 의해 점차 대체</span></strong>되어 import 키워드가 모듈을 불러오기 위한 표준 키워드가 되었지만, Node.js 프로젝트에서는 여전히 널리 쓰이는 방식입니다.</p>



<p>간단히 정리하면, <strong><span class="marker-red">자바스크립트에서 모듈을 사용하는 이유는 가독성과 유지보수성, 그리고 코드 재사용성을 높이기 위함</span></strong>입니다.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p><strong>Q2.</strong> Fetch API와 비교했을 때 <strong><span class="marker">Axios를 사용하면 좋은 점</span></strong>을 설명해 주세요.</p>



<p><strong>A2.</strong> 우선, Fetch API는 Axios보다 나중에 나온 자바스크립트 내장 API입니다.</p>



<p>반대로 말하면 Axios는 Fetch API가 나오기 전부터 꾸준히 사용되어 왔다고 할 수 있는데, 덕분에 많은 프로젝트에 사용되어 Axios는 <strong><span class="marker-blue">신뢰성이 검증된 라이브러리</span></strong>입니다.</p>



<p>또한, Axios는 <strong><span class="marker"><span class="marker-red">Fetch API 대비 편리한 기능을 제공</span></span></strong>합니다. 예를 들어서, Axios에서는 JSON을 자동으로 시리얼라이즈 및 파싱해주는 기능이 있습니다. Fetch API에서는 response.json()처럼 별도의 파싱 메서드를 사용해야 하지만, Axios는 자동으로 처리해 줍니다.</p>



<p>이외에도 요청을 취소하는 기능, Fetch API보다 더 나은 에러 처리 등 Axios가 더 좋은 점이 많으며, 이는 현업에서 Fetch API보다 Axios를 더 선호하는 이유가 되기도 합니다.</p>



<p></p>
]]></content:encoded>
					
					<wfw:commentRss>https://intwocave.com/336/feed/</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
	</channel>
</rss>
