<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>ssssm</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Fri, 17 Apr 2026 21:43:33 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <copyright>Copyright (C) 2019. ssssm. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/smin_0820" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[정처기 프로그래밍 언어]]></title>
            <link>https://velog.io/@smin_0820/%EC%A0%95%EC%B2%98%EA%B8%B0-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%EC%96%B8%EC%96%B4</link>
            <guid>https://velog.io/@smin_0820/%EC%A0%95%EC%B2%98%EA%B8%B0-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%EC%96%B8%EC%96%B4</guid>
            <pubDate>Fri, 17 Apr 2026 21:43:33 GMT</pubDate>
            <description><![CDATA[<h1 id="c언어">C언어</h1>
<h3 id="변수명-작성-규칙">변수명 작성 규칙</h3>
<blockquote>
<p>영문자 또는 언더바(_)로 시작해야 한다
공백은 포함 불가
맨 앞에 숫자 불가</p>
</blockquote>
<h3 id="출력-함수--입력-함수">출력 함수 / 입력 함수</h3>
<blockquote>
<p>putchar() : 화면에 한 개의 문자를 출력
puts() : 화면에 문자열을 출력</p>
<p>getchar() : 키보드를 통해 한 개의 문자 입력 받음
gets() : 키보드를 통해 문자열 입력 받음</p>
</blockquote>
<h3 id="출력-변환-문자">출력 변환 문자</h3>
<table>
<thead>
<tr>
<th>구분</th>
<th>설명</th>
<th>사용 예</th>
<th>출력값</th>
</tr>
</thead>
<tbody><tr>
<td>%d</td>
<td>10진수</td>
<td>printf(&quot;%d&quot;, 10);</td>
<td>10</td>
</tr>
<tr>
<td>%o</td>
<td>8진수</td>
<td>printf(&quot;%o&quot;, 10);</td>
<td>12</td>
</tr>
<tr>
<td>%x</td>
<td>16진수</td>
<td>printf(&quot;%x&quot;, 10);</td>
<td>a</td>
</tr>
<tr>
<td>%X</td>
<td>16진수 (대문자)</td>
<td>printf(&quot;%x&quot;, 10);</td>
<td>A</td>
</tr>
<tr>
<td>%f</td>
<td>실수</td>
<td>printf(&quot;%f&quot;, 1.3);</td>
<td>1.300000</td>
</tr>
<tr>
<td>%c</td>
<td>문자1개</td>
<td>printf(&quot;%c&quot;, &#39;A&#39;);</td>
<td>A</td>
</tr>
<tr>
<td>%s</td>
<td>문자열</td>
<td>printf(&quot;%s&quot;, &quot;abcde&quot;);</td>
<td>abcde</td>
</tr>
</tbody></table>
<h3 id="진법-변환">진법 변환</h3>
<p>10진수 -&gt; 2진수
2진수 -&gt; 8진수
2진수 -&gt; 16진수</p>
<h3 id="언어별-참-거짓-출력">언어별 참, 거짓 출력</h3>
<table>
<thead>
<tr>
<th>언어</th>
<th>참</th>
<th>거짓</th>
</tr>
</thead>
<tbody><tr>
<td>C언어</td>
<td>1</td>
<td>0</td>
</tr>
<tr>
<td>Java</td>
<td>true</td>
<td>false</td>
</tr>
<tr>
<td>Python</td>
<td>True</td>
<td>False</td>
</tr>
</tbody></table>
<h3 id="아스키-코드">아스키 코드</h3>
<blockquote>
<p>A : 65
a : 97
&#39;0&#39; : 48</p>
</blockquote>
<h3 id="stringh-문자열-함수">&lt;string.h&gt; 문자열 함수</h3>
<blockquote>
<p>strlen() : 문자열의 길이 반환</p>
</blockquote>
<p>strcpy() : 문자열을 다른 문자열로 복사
strncpy() : 문자열을 지정한 길이만큼 복사</p>
<blockquote>
</blockquote>
<p>strcat() : 문자열을 다른 문자열에 이어 붙인다
strncat() : 지정된 길이 만큼 문자열을 이어 붙인다</p>
<blockquote>
</blockquote>
<p>strcmp() : 두 문자열 비교, 0(같다), 양수(&gt;), 음수(&lt;)
strncmp() : 지정된 길이 만큼 두 문자열을 비교</p>
<blockquote>
</blockquote>
<p>strchr() : 문자열에서 특정 문자의 첫 번째 위치를 찾는다
strrchr() : 문자열에서 특정 문자의 마지막 위치를 찾는다</p>
<blockquote>
</blockquote>
<p>strstr() : 문자열에서 특정 문자열의 첫 번째 위치를 찾는다</p>
<h3 id="mathh-수학-함수">&lt;math.h&gt; 수학 함수</h3>
<blockquote>
<p>sqrt() : 제곱근 반환
pow() : 거듭제곱 반환
abs() : 정수의 절대값 반환</p>
</blockquote>
<p>ceil() : 올림
floor() : 내림
round() : 가장 가까운 정수로 반올림</p>
<h3 id="기타-함수">기타 함수</h3>
<blockquote>
<p>stoi() / stof() : 문자열을 정수 / 실수로 변환</p>
</blockquote>
<h1 id="python">Python</h1>
<h3 id="문자열-변환-메서드">문자열 변환 메서드</h3>
<blockquote>
<p>capitalize() : 맨 첫 글자만 대문자로 변환
title() : 영단들의 첫 글자 모두 대문자로 변환
strip() : 문자열 양 끝 공백 제거</p>
</blockquote>
<h3 id="문자열-검색-및-확인-메서드">문자열 검색 및 확인 메서드</h3>
<blockquote>
<p>find(sub) : 특정 문자열이 처음 나타난 위치 반환
index(sub) : 특정 문자열의 위치 반환</p>
</blockquote>
<h3 id="set">Set</h3>
<blockquote>
<p>union(set) : 합집합
intersection(set) : 교집합
difference(set) : 차집합</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[정처기 나머지]]></title>
            <link>https://velog.io/@smin_0820/%EC%A0%95%EC%B2%98%EA%B8%B0-%EB%82%98%EB%A8%B8%EC%A7%80</link>
            <guid>https://velog.io/@smin_0820/%EC%A0%95%EC%B2%98%EA%B8%B0-%EB%82%98%EB%A8%B8%EC%A7%80</guid>
            <pubDate>Fri, 17 Apr 2026 21:43:24 GMT</pubDate>
            <description><![CDATA[<h2 id="e-r-다이어그램-기호">E-R 다이어그램 기호</h2>
<blockquote>
<p>사각형 - 개체 Entity =&gt; 테이블명
마름모 - 관계 Relationship
타원 - 속성 Attribute
밑줄 타원 - 기본키 속성
이중 타원 - 복합 속성</p>
</blockquote>
<h2 id="용어">용어</h2>
<blockquote>
<ul>
<li>SSO
한번의 로그인으로 다른 사이트들을 자동으로 접속</li>
</ul>
</blockquote>
<ul>
<li>OAuth
다른 애플리케이션을 통해 로그인  ex)카카오, 네이버 </li>
</ul>
<h2 id="arq">ARQ</h2>
<p>정지-대기 (Stop-and-Wait) ARQ: 하나의 프레임을 보내고 확인(ACK/NAK)을 받을 때까지 기다립니다.
Go-Back-N ARQ: 오류가 발생한 프레임부터 모두 재전송합니다.
선택적 재전송 (Selective Repeat) ARQ: 오류가 발생한 프레임만 선별하여 재전송합니다.</p>
<h2 id="3a">3A</h2>
<p>인증 (Authentication): &quot;당신이 누구인지 증명하세요.&quot; (신분증과 탑승권 확인)
권한 부여 (Authorization): &quot;당신이 할 수 있는 일은 여기까지입니다.&quot; (비즈니스석 티켓 소지자는 비즈니스 라운지 이용 가능)
계정 관리 (Accounting): &quot;당신이 한 모든 일을 기록합니다.&quot; (면세점 구매 내역, 출입국 기록)</p>
<h2 id="악성-코드-종류">악성 코드 종류</h2>
<p>바이러스 :    프로그램 변형 감염, 자가 복제, 네트워크 자율 전파 안함
웜 :    네트워크 자율 전파, 자가 복제, 이메일/공유 폴더/P2P 전파
트로이 목마 : 정상 프로그램 위장, 악성 루틴 포함, 자가 복제 안함, 파일 감염 안함
랜섬웨어 : 파일 암호화, 몸값 요구, 데이터 인질, 복구 불가능
스파이웨어 : 정보 수집, 개인정보 유출, 키로거, 사용자 모르게 설치</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[5정처기 - 보안]]></title>
            <link>https://velog.io/@smin_0820/5%EC%A0%95%EC%B2%98%EA%B8%B0-%EB%B3%B4%EC%95%88</link>
            <guid>https://velog.io/@smin_0820/5%EC%A0%95%EC%B2%98%EA%B8%B0-%EB%B3%B4%EC%95%88</guid>
            <pubDate>Fri, 17 Apr 2026 21:37:21 GMT</pubDate>
            <description><![CDATA[<h1 id="공격-유형">공격 유형</h1>
<h2 id="dos-vs-ddos">DOS vs DDOS</h2>
<blockquote>
<p>DOS는 시스템의 리소스를 과도하게 사용하여 사용자가 정상적인 서비스를 이용하지 못하도록 만드는 공격</p>
</blockquote>
<p>접속 요청을 엄청 많이 보내서 다른 사용자가 들어가지도 못하게 하는 것. 
규모가 작고 막기 위해 공격 IP 차단만 하면된다.</p>
<blockquote>
<p>DDOS는 여러 분산된 시스템에 공격하기 때문에 규모도 매우 크고 공격의 출처를 찾기 어렵기 때문에 막기 어렵다</p>
</blockquote>
<h2 id="dos-공격-종류">DOS 공격 종류</h2>
<p>Land Attack : 출발지와 목적지 주소 동일
Smurf Attack : 출발지 IP를 공격 대상의 IP로 위조 후, 네트워크 내 모든 장치를 ICMP Echo 요청을 보내는 방식
Tear drop : 데이터를 조각내서 보낸 후, 수신 시스템에서 힘들게 조립 시 과부하
Ping of Death : 최대 크기 패킷보다 더 큰 패킷 전송으로 공격
SYN Flooding : 다수의 SYN(연결 요청) 패킷을 보내지만, 이후의 ACK(응답) 패킷을 보내지 않음
UDP Flooding : 특정 포트로 무작위로 전송하는 공격</p>
<h2 id="네트워크-공격-종류">네트워크 공격 종류</h2>
<blockquote>
<p>패스워드 크래킹
저장된 비밀번호를 알아내기 위해 사용되는 모든 기술</p>
<blockquote>
<p>사전 크래킹 : 사람들이 자주 사용하는 단어, 유출된 비밀번호를 통해 알아내는 방법
무차별 크래킹 : 하나씩 무식하게 입력
패스워드 하이브리드 공격 : 단어, 특수문자, 숫자 조합
레인보우 테이블 공격 : 해시 함수 탈취후 거꾸로 추적</p>
</blockquote>
</blockquote>
<blockquote>
<p>스푸핑 : 스푸핑은 &#39;속이다&#39;라는 뜻으로, 공격자가 자신의 신원을 위장하여 시스템에 접근
스니핑 : 데이터 패킷을 몰래 엿보는 행위
세션 하이재킹 : 정상적인 세션을 가로채서 공격자가 인증된 사용자로 위장</p>
</blockquote>
<hr>
<h1 id="암호-알고리즘">암호 알고리즘</h1>
<blockquote>
<p>대칭키 암호화 알고리즘</p>
</blockquote>
<p>암호화와 복호화에 동일한 키 사용</p>
<blockquote>
<blockquote>
<p>블록 암호화
DES : 최초의 표준 / 길이가 짧아 보안에 취약 / IBM 개발
AES : 현존 가장 안전하고 널리 쓰임
SEED : 최초 국내 대칭키 알고리즘 / ARIA로 대체
IDEA : 초기 블록 암호화 / 스위스 개발
Skipjack : 전화기 적용 / NSA 개발</p>
</blockquote>
<blockquote>
<p>스트림 암호화
데이터를 비트 단위로 순차적 암호화 / RC4</p>
</blockquote>
</blockquote>
<blockquote>
<p>비대칭키(공개키) 암호화 알고리즘</p>
</blockquote>
<p>암호화 키와 복호화 키를 분리하여 사용</p>
<blockquote>
<blockquote>
<p>디피-헬만 : 최초 공개키 암호화 알고리즘 / 이산 로그
RSA : 소인수분해 기반 / 가장 대중적
ECC : RSA 대안</p>
</blockquote>
</blockquote>
<blockquote>
<p>해시 암호화 알고리즘</p>
</blockquote>
<p>단방향 함수 / 복호화 불가능</p>
<blockquote>
<blockquote>
<p>MD5, SHA-1 : 충돌 취약 / 더 이상 사용 X
SHA-2 : 가장 널리 사용</p>
</blockquote>
</blockquote>
<hr>
<h1 id="보안-기능">보안 기능</h1>
<h2 id="서버-접근-통제">서버 접근 통제</h2>
<p>임의적 접근 통제 DAC : 개인용, 소규모</p>
<p>강제적 접근 통제 MAC : 군사, 정부, 높은 보안</p>
<p>역할 기반 접근 통제 RBAC : 대부분 기업, 클라우드</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[4정처기 - SW 설계 과목]]></title>
            <link>https://velog.io/@smin_0820/4%EC%A0%95%EC%B2%98%EA%B8%B0-SW-%EC%84%A4%EA%B3%84-%EA%B3%BC%EB%AA%A9</link>
            <guid>https://velog.io/@smin_0820/4%EC%A0%95%EC%B2%98%EA%B8%B0-SW-%EC%84%A4%EA%B3%84-%EA%B3%BC%EB%AA%A9</guid>
            <pubDate>Fri, 17 Apr 2026 21:37:15 GMT</pubDate>
            <description><![CDATA[<h1 id="앱-설계">앱 설계</h1>
<h2 id="디자인-패턴">디자인 패턴</h2>
<blockquote>
<p>생성 패턴 5</p>
</blockquote>
<p>암기 법 : 싱글 팩토리 빌드 프로토스 앱</p>
<table>
<thead>
<tr>
<th>패턴</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>Singleton</td>
<td>인스턴스 하나임을 보장</td>
</tr>
<tr>
<td>Factory Method</td>
<td>객체 생성을 서브클래스에 위임</td>
</tr>
<tr>
<td>Builder</td>
<td>동일한 생성 절차, 다양한 결과 표현</td>
</tr>
<tr>
<td>Prototype</td>
<td>기존 객체 복사</td>
</tr>
<tr>
<td>Abstract Method</td>
<td>구체적인 클래스에 의존하지 않고 생성</td>
</tr>
</tbody></table>
<blockquote>
<p>구조 패턴 7</p>
</blockquote>
<p>암기 법 : 브플어오르는 퍼프 어데있나?</p>
<table>
<thead>
<tr>
<th>패턴</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>Adapter</td>
<td>호환</td>
</tr>
<tr>
<td>Decorator</td>
<td>조합을 통해 동적 기능 추가</td>
</tr>
<tr>
<td>Facade</td>
<td>단순화된 통합 인터페이스 제공</td>
</tr>
<tr>
<td>Proxy</td>
<td>대리 객체 제공</td>
</tr>
<tr>
<td>Bridge</td>
<td>추상부과 구현부 분리</td>
</tr>
<tr>
<td>Flyweight</td>
<td>재사용, 메모리 절약</td>
</tr>
<tr>
<td>Composite</td>
<td>객체를 트리구조로 구성</td>
</tr>
</tbody></table>
<blockquote>
<p>행위 패턴 11</p>
</blockquote>
<table>
<thead>
<tr>
<th>패턴</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>Chain of Responsibility</td>
<td>처리 불가 시 다음 객체로 전달</td>
</tr>
<tr>
<td>Command</td>
<td>요청을 캡슐화, 취소/로그 저장 등 지원</td>
</tr>
<tr>
<td>Interpreter</td>
<td>언어 문장 해석</td>
</tr>
<tr>
<td>Iterator</td>
<td>순차 접근</td>
</tr>
<tr>
<td>Mediator</td>
<td>중재자 객체</td>
</tr>
<tr>
<td>Memento</td>
<td>상태 저장, 이전 상태 복원</td>
</tr>
<tr>
<td>Observer</td>
<td>상태 변화 관찰</td>
</tr>
<tr>
<td>State</td>
<td>상태 전이 표현</td>
</tr>
<tr>
<td>Strategy</td>
<td>알고리즘 교체</td>
</tr>
<tr>
<td>Template Method</td>
<td>알고리즘을 상위에서 정의하고, 하위에서 세부 구현</td>
</tr>
<tr>
<td>Visitor</td>
<td>구조 변경 없이 새로운 연산 추가, 개방-폐쇄 원칙 실현</td>
</tr>
</tbody></table>
<h2 id="결합도-coupling">결합도 Coupling</h2>
<blockquote>
<p>자료 결합도 (Data) : 값 전달
스탬프 결합도 (Stamp) : 배열, 오브젝트 전달
제어 결합도 (Control) : 제어 요소 전달
외부 결합도 (External) : 외부에서 데이터 참조 / 외부 변수 참조
공통 결합도 (Common) : 전역변수 이용
내용 결합도 (Content) : 다른 모듈의 변수/기능 이용</p>
</blockquote>
<h2 id="응집도-cohesion">응집도 Cohesion</h2>
<blockquote>
<p>기능적 응집도 (Functional) : 단일 목적 사용
순차적 응집도 (Sequential) : 출력값을 입력값으로 사용
통신적 응집도 (Communication) : 동일한 입력값과 출력값 사용
절차적 응집도 (Procedual) : 순차적으로 수행
시간적 응집도 (Temporal) : 특정 시간에 처리
논리적 응집도 (Logical) : 유사한 성격
우연적 응집도 (Coincidental) : 연관 없는 경우</p>
</blockquote>
<h2 id="객체지향-설계-원칙-solid">객체지향 설계 원칙 SOLID</h2>
<blockquote>
<p>단일 책임 원칙 - Single Responsibility Principle : 하나의 클래스는 하나의 책임만 가진다
개방-폐쇄 원친 - Open-closed Principle : 확장에는 열려있는 수정에는 닫혀있어야 한다
리스코프 치환 원치 - Liskov Substitution Principle : 부모 클래스 인스턴스를 자식 클래스 인스턴스로 대체해도 정상적으로 동작
인터페이스 분리 원칙 - Interface Segregation Principle : 사용하지 않은 인터페이스 의존관계 X
의존성 역전 원칙 - Dependency Inversion Principle : 구체적인 클래스보다 추상화에 의존</p>
</blockquote>
<h2 id="럼바우">럼바우</h2>
<table>
<thead>
<tr>
<th>용어</th>
<th>키워드</th>
</tr>
</thead>
<tbody><tr>
<td>객체 / 정보 모델링 Obejct</td>
<td>객체 간의 관계 정의 / E-R 다이어그램 / 객체 다이어그램</td>
</tr>
<tr>
<td>동적 모델링 Dynamic</td>
<td>상태 다이어그램</td>
</tr>
<tr>
<td>기능 모델링 Functional</td>
<td>DFD 자료 흐름도</td>
</tr>
</tbody></table>
<hr>
<h1 id="요구사항">요구사항</h1>
<h2 id="uml-다이어그램">UML 다이어그램</h2>
<p>구조 다이어그램 : 클래스 다이어그램, 패키지 다이어그램</p>
<p>행위 다이어그램 : 유스케이스 다이어그램</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[3정처기 - SW 개발 과목]]></title>
            <link>https://velog.io/@smin_0820/3%EC%A0%95%EC%B2%98%EA%B8%B0-SW-%EA%B0%9C%EB%B0%9C-%EA%B3%BC%EB%AA%A9</link>
            <guid>https://velog.io/@smin_0820/3%EC%A0%95%EC%B2%98%EA%B8%B0-SW-%EA%B0%9C%EB%B0%9C-%EA%B3%BC%EB%AA%A9</guid>
            <pubDate>Fri, 17 Apr 2026 21:37:05 GMT</pubDate>
            <description><![CDATA[<h1 id="테스트">테스트</h1>
<h2 id="테스트-커버리지">테스트 커버리지</h2>
<blockquote>
<p>구문 커버리지 : 구문에 대해 한번 이상 수행
조건 커버리지 : 개별 조건식 / x &gt; 0
결정 커버리지 === 분기 : 결정 포인트 내의 모든 분기문에 대해 수행 / if(x &gt; 0 &amp;&amp; y &lt; 15)
조건/결정 커버리지 : 개별 조건식과 결정 포인트 모두 T/F가 나와야 함
변경 조건/결정 커버리지 : 개별 조건식이 결정 전체 결과에 영향을 주는지 확인
다중 조건 커버리지 : 모든 가능한 조합 100 만족</p>
</blockquote>
<h2 id="블랙박스-테스트-기법">블랙박스 테스트 기법</h2>
<blockquote>
<p>화이트박스 테스트 : 소스코드 (개발자 위주 테스트)
블랙박스 테스트 : 기능 (사용자 위주 테스트)</p>
<ol>
<li>동등 분할 기법(Equivalance Partitioning Testing) : 입력 데이터를 여러 구간으로 나누고, 각 구간의 대표값으로 테스트 케이스 구성하여 검사</li>
<li>경계값 분석 기법(Boundary Value Analysis) : 경계값 중심으로 테스트 진행</li>
<li>원인-효과 그래프 검사(Cause-Effect Graphing Test) : 입력 데이터가 출력값에 미치는 영향을 분석해서 가장 효율적인 케이스 선정</li>
<li>오류 예측 검사(Error Guessing) : 테스터의 직관으로 오류를 찾아내는 기법</li>
<li>비교 검사(Comparison Testing) : 여러 프로그램으로 돌려서 동일한 결과가 나오는지 테스트</li>
<li>상태 전이 검사(State Transition Testing) : 다른 상태로 전이되는 경우의 수를 모두 테스트</li>
</ol>
</blockquote>
<h2 id="테스트-레벨">테스트 레벨</h2>
<p>소프트웨어 개발 과정에서 테스트가 수행되는 단계
<img src="https://velog.velcdn.com/images/smin_0820/post/40a9269c-8a64-41b3-86d9-893c4fe5ce5e/image.png" alt=""></p>
<blockquote>
<p>통합 테스트
상향식 : 드라이버
하향식 : 스텁</p>
</blockquote>
<blockquote>
<p>인수 테스트
알파 : 개발자
베타 : 사용자</p>
</blockquote>
<h2 id="테스트-케이스-구성요소">테스트 케이스 구성요소</h2>
<ol>
<li>식별자 ID</li>
<li>테스트 항목</li>
<li>테스트 조건</li>
<li>테스트 데이터</li>
<li>예상 결과</li>
</ol>
<hr>
<h1 id="인터페이스">인터페이스</h1>
<h2 id="인터페이스-보안">인터페이스 보안</h2>
<h2 id="eai">EAI</h2>
<p>기업내 다양한 애플리케이션을 통합</p>
<ul>
<li>Point-to-Point
미들웨어 없이 직접 애플리케이션끼리 연결</li>
<li>Hub &amp; Spoke
중앙 허브를 통해 중앙 집중적으로 연결 (데이터 전송 보장 / 확장 용이)</li>
<li>Message Bus
미들웨어를 사용해 애플리케이션 간 메세지 전달하는 방식 (확장성 / 대용량 처리 가능)</li>
<li>Hybrid
내부 - Hub &amp; Spoke / 외부 - Message Bus</li>
</ul>
<h2 id="인터페이스-통신-기술-4가지">인터페이스 통신 기술 4가지</h2>
<p>클라이언트와 서버가 데이터를 주고받기 위해 사용하는 다양한 통신 기술</p>
<p>AJAX</p>
<ul>
<li>XMLHttpRequest 객체를 사용하여 서버에 요청보내고 응답 받음</li>
<li>페이지 새로고침 없이 백그라운드에서 서버와 데이터를 비동기적으로 교환하여 동적으로 화면 갱신</li>
</ul>
<p>Fetch API</p>
<ul>
<li>XMLHttpRequest 객체를 대체하는 현대 브라우저 내장 API</li>
<li>Promise 기반으로 설계되어 코드 가독성이 높음</li>
<li>현재 웹 표준으로 자리잡아 AJAX보다 더 많이 사용</li>
</ul>
<p>WebSockets</p>
<ul>
<li>클라이언트와 서버 간에 양방향 실시간 통신을 지원하는 프로토콜</li>
<li>한번 연결 수립되면 계속 유지되어 데이터 교환이 자유로움</li>
<li>지연 시간이 매우 낮아서, 채팅, 온라인 게임, 주식 시세 알림 등 사용됨</li>
</ul>
<p>GraphQL</p>
<ul>
<li>API를 위한 쿼리 언어이자, REST 아키텍처의 대안</li>
<li>클라이언트가 필요한 데이터의 구조를 직접 요청하여 불필요한 데이터 전송이 없음</li>
<li>한번에 여러 종류의 데이터 요청 가능, 강력한 타입 기반 시스템</li>
</ul>
<h2 id="데이터-표현-형식">데이터 표현 형식</h2>
<p>시스템 간 데이터를 교환할 때 약속된 형식이 필요함. 대표 3개 데이터 형식</p>
<p>JSON</p>
<ul>
<li>자바스크립트 객체 기반, 사람이 읽기 쉬운 텍스트 기반 데이터 교환 방식</li>
<li>key-value 구조, 웹 환경, 특히 REST API에서 주로 사용</li>
</ul>
<p>XML</p>
<ul>
<li>&lt;&gt;를 사용하여 데이터 구조를 계층적으로 표현하는 마크업 언어</li>
<li>트리구조로 확장성에 용이하고 복잡한 데이터 표현에 용이</li>
<li>과거 웹 서비스 SOAP에서 사용</li>
</ul>
<p>YAML</p>
<ul>
<li>사람이 읽고 쓰기 편한 것에 중점을 둔 데이터 직렬화 형식</li>
<li>주석( #)을 사용하여 설명 추가 가능</li>
</ul>
<h2 id="웹-서비스-인터페이스-방식">웹 서비스 인터페이스 방식</h2>
<p>웹 서비스는 서로 다른 시스템이 인터넷을 통해 상호작용하는 방식</p>
<p>SOAP</p>
<ul>
<li>HTTP, SMTP 등 위에서 XML 기반의 메시지를 교환하여 원격 프로시저를 호출하는, 매우 엄격한 규칙을 가진 프로토콜</li>
</ul>
<p>REST</p>
<ul>
<li>URI를 통해 자원을 식별하고, HTTP 메서드를 통해 해당 자원에 대한 행위를 표현하는 원칙을 기반으로 하는 소프트웨어 아키텍처 스타일</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[2정처기 - 네트워크/OS]]></title>
            <link>https://velog.io/@smin_0820/2%EC%A0%95%EC%B2%98%EA%B8%B0-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%ACOS</link>
            <guid>https://velog.io/@smin_0820/2%EC%A0%95%EC%B2%98%EA%B8%B0-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%ACOS</guid>
            <pubDate>Fri, 17 Apr 2026 21:36:56 GMT</pubDate>
            <description><![CDATA[<h1 id="메모리-프로세스">메모리, 프로세스</h1>
<h2 id="메모리-페이지-교체-알고리즘">메모리 페이지 교체 알고리즘</h2>
<p>목표 : 페이지 부재를 최소화해서 시스템 성능 향상</p>
<table>
<thead>
<tr>
<th>페이지 교체 알고리즘</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>FIFO (First in, First out)</td>
<td>가장 먼저 들어온 페이지를 가장 먼저 내보내는 방식</td>
</tr>
<tr>
<td>LRU (Least Recently Used)</td>
<td>가장 오랫동안 사용되지 않은 페이지를 교체</td>
</tr>
<tr>
<td>LFU (Least Frequently Used)</td>
<td>참조 횟수가 가장 적은 페이지를 교체</td>
</tr>
</tbody></table>
<h2 id="프로세스-스케줄링-알고리즘">프로세스 스케줄링 알고리즘</h2>
<p>컴퓨터는 동시에 여러 프로세스를 처리해야 한다. 이때 어떤 프로세스에 CPU를 할당할지 결정하는 것이 프로세스 스케줄링. 프로세스 스케줄링을 통해 사용자 시간을 단축한다.</p>
<ul>
<li>비선점형 : 프로세스가 CPU를 할당 받으면, 종료되거나 입출력 작업을 위해 스스로 반납할 때까지 다른 프로세스에 CPU 빼앗길 수 없다.</li>
<li>선점형 : 운영체제가 필요하다고 판단하면, 실행중인 프로세스를 중단시키고 강제로 다른 프로세스에 CPU 할당 가능.</li>
</ul>
<table>
<thead>
<tr>
<th>비선점형</th>
<th>선점형</th>
</tr>
</thead>
<tbody><tr>
<td>FCFS(도착 순서대로 할당)</td>
<td>Round Robin</td>
</tr>
<tr>
<td>SJF(실행 시간 짧은 프로세스에 할당, 비선점형/선점형 둘 다 가능</td>
<td>SRT(선점형 SJF)</td>
</tr>
<tr>
<td>HRN (실행시간+대기시간) / 실행시간</td>
<td></td>
</tr>
<tr>
<td>기한부</td>
<td></td>
</tr>
<tr>
<td>우선순위</td>
<td></td>
</tr>
</tbody></table>
<h1 id="네트워크-7계층">네트워크 7계층</h1>
<h2 id="라우팅-프로토콜">라우팅 프로토콜</h2>
<p>라우팅(Routing)은 네트워크에서 데이터 패킷을 출발지에서 목적지까지 전달할 때, 최적의 경로를 결정하는 과정이다</p>
<table>
<thead>
<tr>
<th>라우팅, 프로토콜 종류</th>
<th>핵심 키워드</th>
</tr>
</thead>
<tbody><tr>
<td>정적 라우팅</td>
<td>고정된 경로 사용</td>
</tr>
<tr>
<td>동적 라우팅</td>
<td>동적으로 경로 변경</td>
</tr>
<tr>
<td>내부 라우팅 프로토콜(IGP)</td>
<td>같은 네트워크 내</td>
</tr>
<tr>
<td>외부 라우팅 프로토콜(EGP)</td>
<td>다른 네트워크 간</td>
</tr>
<tr>
<td>RIP</td>
<td>거리 벡터 알고리즘 / 벨만-포드 알고리즘 / 최대 15홉</td>
</tr>
<tr>
<td>OSPF</td>
<td>링크 상태 알고리즘 / 다익스트라 알고리즘 / 최소 경로 비용</td>
</tr>
<tr>
<td>BGP</td>
<td>경로 벡터 알고리즘</td>
</tr>
</tbody></table>
<h2 id="네트워크-계층-프로토콜">네트워크 계층 프로토콜</h2>
<table>
<thead>
<tr>
<th>기술/프로토콜</th>
<th>주요 기능</th>
<th>특징</th>
</tr>
</thead>
<tbody><tr>
<td>IP ( Internet Protocol )</td>
<td>데이터그램의 주소 지정 및 경로 설정</td>
<td>비연결성, 비신뢰성</td>
</tr>
<tr>
<td>ARP</td>
<td>IP주소 -&gt; MAC주소 변환</td>
<td></td>
</tr>
<tr>
<td>RARP</td>
<td>MAC주소 -&gt; IP주소 변환</td>
<td></td>
</tr>
<tr>
<td>ICMP ( Internet Control Message Protocol )</td>
<td>오류 보고 및 네트워크 상태 진단</td>
<td>IP에 의존하여 동작, 제어 메시지 전송</td>
</tr>
<tr>
<td>IGMP (Internet Group Management Protocol)</td>
<td>멀티캐스트 그룹 관리</td>
<td>특정 그룹에만 데이터 전송 및 대역폭 강화</td>
</tr>
<tr>
<td>라우팅 프로토콜</td>
<td>최적의 데이터 전송 경로 탐색</td>
<td>RIP, OSPF, BGP</td>
</tr>
<tr>
<td>NAT</td>
<td>사설IP주소를 공인IP주소로 변환</td>
<td>IP주소 절약, 내부 네트워크 보안 강화</td>
</tr>
</tbody></table>
<h2 id="네트워크-전송-방식">네트워크 전송 방식</h2>
<p>네트워크에서 데이터를 전송하는 두 가지 주요 방식
<img src="https://velog.velcdn.com/images/smin_0820/post/77158271-eb40-4272-ac86-e315d73642e3/image.png" alt=""></p>
<table>
<thead>
<tr>
<th>교환 방식</th>
<th>전송 단위</th>
</tr>
</thead>
<tbody><tr>
<td>패킷 교환방식</td>
<td>패킷</td>
</tr>
<tr>
<td>서킷 교환방식</td>
<td>비트 스트림</td>
</tr>
</tbody></table>
<hr>
<table>
<thead>
<tr>
<th>구분</th>
<th>비연결형 (데이터그램)</th>
<th>연결형 (가상회선)</th>
</tr>
</thead>
<tbody><tr>
<td>연결 설정</td>
<td>불필요</td>
<td>필요</td>
</tr>
<tr>
<td>패킷 독립성</td>
<td>독립적</td>
<td>종속적</td>
</tr>
<tr>
<td>경로 결정</td>
<td>패킷마다 다름</td>
<td>고정 경로</td>
</tr>
<tr>
<td>순서 보장</td>
<td>보장 안됨</td>
<td>보장됨</td>
</tr>
<tr>
<td>대표 프로토콜</td>
<td>IP, UDP</td>
<td>TCP, ATM, X.25</td>
</tr>
</tbody></table>
<ul>
<li>네트워크계층 : IP(비연결), X.25(연결)</li>
<li>전송계층 : UCP(비연결), TCP(연결)</li>
</ul>
<h1 id="shell-script">shell script</h1>
<h2 id="unix-기본-명령어">unix 기본 명령어</h2>
<table>
<thead>
<tr>
<th>기능</th>
<th>명령어</th>
</tr>
</thead>
<tbody><tr>
<td>현재 작업 디렉토리 경로 출력</td>
<td>pwd</td>
</tr>
<tr>
<td>디렉토리 내용 출력</td>
<td>ls</td>
</tr>
<tr>
<td>디렉토리 이동</td>
<td>cd</td>
</tr>
<tr>
<td>파일/디렉토리 복사</td>
<td>cp</td>
</tr>
<tr>
<td>파일/디렉토리 이동 또는 이름 변경</td>
<td>mv</td>
</tr>
<tr>
<td>파일/디렉토리 삭제</td>
<td>rm</td>
</tr>
<tr>
<td>디렉토리 생성</td>
<td>mkdir</td>
</tr>
<tr>
<td>빈 디렉토리 삭제</td>
<td>rmdir</td>
</tr>
<tr>
<td>파일 내용 출력</td>
<td>cat</td>
</tr>
<tr>
<td>파일 권한 변경</td>
<td>chmod</td>
</tr>
<tr>
<td>파일 소유자 변경</td>
<td>chown</td>
</tr>
<tr>
<td>패턴 검색</td>
<td>grep</td>
</tr>
<tr>
<td>파일 검색</td>
<td>find</td>
</tr>
<tr>
<td>프로세스 목록 조회</td>
<td>ps</td>
</tr>
<tr>
<td>프로세스 종료</td>
<td>kill</td>
</tr>
</tbody></table>
<h2 id="chmod">chmod</h2>
<p>chmod 777 파일명</p>
<p>소유자 - 그룹 - 그 외</p>
<p>4 읽기 - 2 쓰기 - 1 실행</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[1정처기 - DB]]></title>
            <link>https://velog.io/@smin_0820/1%EC%A0%95%EC%B2%98%EA%B8%B0-DB</link>
            <guid>https://velog.io/@smin_0820/1%EC%A0%95%EC%B2%98%EA%B8%B0-DB</guid>
            <pubDate>Fri, 17 Apr 2026 21:36:49 GMT</pubDate>
            <description><![CDATA[<h1 id="sql">SQL</h1>
<p>관계형 데이터베이스 RDBMS를 위해 설계된 프로그래밍 언어</p>
<h2 id="정의-조작-제어-정의어">정의, 조작, 제어 정의어</h2>
<table>
<thead>
<tr>
<th>유형</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>정의어 DDL</td>
<td>CREATE / DROP / ALTER / TRUNCATE</td>
</tr>
<tr>
<td>조작의 DML</td>
<td>INSERT / UPDATE / DELETE / SELECT</td>
</tr>
<tr>
<td>데이터 제어어 DCL</td>
<td>GRANT / REVOKE</td>
</tr>
<tr>
<td>트랜잭션 제어어 TCL</td>
<td>COMMIT / ROLLBACK / SAVEPOINT</td>
</tr>
</tbody></table>
<h3 id="정의어-ddl">정의어 DDL</h3>
<pre><code class="language-sql">// 예제 1 테이블 생성
CREATE TABLE 테이블명
    컬럼명 데이터타입 [제약조건]
    name varchar(30) [제약조건]
                    NOT NULL : null    입력 불가
                    UNIQUE : 중복값 불가
                    PRIMARY KEY : 기본키 설정
                    CHECK : 검증 CHECK IN (&#39;M, &#39;F&#39;)
                    DEFAULT : 기본값 지정

// 예제 2 가상 테이블 생성
CREATE VIEW 뷰명
AS
SELECT 컬럼1, 컬럼2 FROM 테이블명;

// 예제 3 인덱스 생성
CREATE INDEX 인덱스명 ON 테이블명(컬럼명);
</code></pre>
<pre><code class="language-sql">// 예제 1 컬럼 추가
ALTER TABLE 테이블명
ADD (컬럼명 데이터타입 [제약조건]);

// 예제 2 컬럼 수정
ALTER TABLE 테이블명
MODIFY (컬럼명 데이터타입 [제약조건]);

// 예제 3 컬럼 삭제
ALTER TABLE 테이블명
DROP COLUMN 컬럼명;

// 예제 4 컬럼명 수정
ALTER TABLE 테이블명
RENAME 기존 컬럼명 TO 새컬럼명;</code></pre>
<pre><code class="language-sql">DROP TABLE 테이블명;
TRUNCATE TABLE 테이블명;</code></pre>
<h3 id="조작어-dml">조작어 DML</h3>
<pre><code class="language-sql">// 컬럼명을 지정하여 INSERT
INSERT INTO student(name, major, age)
VALUES(&#39;Kim&#39;, &#39;컴퓨터공학&#39;, 25);

// 다른 테이블 조회 후 그 결과를 INSERT
INSERT INTO student_backup(name, major, age)
SELECT name, major, age
FROM student
WHERE major = &#39;컴퓨터공학&#39;;

// UPDATE
UPDATE 테이블명
SET 컬럼명
WHERE 조건;

// DELETE
DELETE FROM 테이블명
WHERE 조건;

// UNION, UNION ALL, INTERSECT, EXCEPT</code></pre>
<h3 id="데이터-제어어-dcl">데이터 제어어 DCL</h3>
<pre><code class="language-sql">// userA에게 Student 테이블의 조회 권한 부여
GRANT SELECT ON Student 
TO userA;

// userA에게 Student 테이블의 조회, 삽입 권한 부여
GRANT SELECT, INSERT ON Student
TO userA;

// 다른 사용자에게 권한을 재부여
마지막에 WITH GRANT OPTION;

// userA의 조회 권한 회수
REVOKE SELECT ON Student FROM userA;</code></pre>
<h3 id="null-문제">NULL 문제</h3>
<pre><code class="language-sql">COUNT(컬럼명) : NULL 제외
DISTINCT : NULL 포함
집계함수 : 무시하고 계산에서 제외
GROUP BY : NULL 끼리 그룹핑 가능
WHERE 절 : NULL 비교 불가라서 제외</code></pre>
<h3 id="join">JOIN</h3>
<pre><code class="language-sql">// INNER JOIN
교집합

// NATURAL JOIN
자연스럽게 JOIN, 공통 컬럼 1개

// FULL OUTER JOIN
먼저 INNER JOIN 후 교집합 없는 컬럼은 NULL로 채움

// LEFT OUTER JOIN, RIGHT OUTER JOIN
먼저 INNER JOIN 후 왼쪽만, 오른쪽만

// CROSS JOIN
테이블 X 테이블</code></pre>
<h2 id="트랜잭션-acid">트랜잭션 ACID</h2>
<p>원자성 Atomicity : 트랜잭션 연산 모두 실행 or 하나도 실행 X
일관성 Consistency : 트랜잭션 실행 후 일관된 데이터베이스 유지
고립성 Isolation : 하나 트랜잭션 실행중 끼어들 수 없음
지속성 Durability : 성공된 트랜잭션은 영구적으로 데이터베이스에 저장</p>
<h1 id="논리-db-설계">논리 DB 설계</h1>
<h2 id="관계-데이터-모델-구성요소">관계 데이터 모델 구성요소</h2>
<blockquote>
<p>Relation : 행과 열로 구성된 2차원 테이블
Tupple : 행, 레코드
Attibute : 열, 데이터 필드
Cardinality : 튜플의 수
Degree : 속성의 수</p>
</blockquote>
<blockquote>
<p>Schema : 데이터베이스의 구조와 제약조건 명세
Instance : 릴레이션에 들어있는 데이터 집합
Domain : 속성들이 가질 수 있는 값의 범위</p>
</blockquote>
<h2 id="데이터베이스-스키마-3단계-구조">데이터베이스 스키마 3단계 구조</h2>
<p>외부 스키마</p>
<ul>
<li>사용자나 개발자 관점</li>
</ul>
<p>개념 스키마</p>
<ul>
<li>데이터베이스의 전체적인 논리구조</li>
</ul>
<p>내부 스키마</p>
<ul>
<li>물리적 저장 장치 관점</li>
</ul>
<blockquote>
<p>데이터 독립성</p>
</blockquote>
<ul>
<li>논리적 독립성 : 테이블 구조(개념 스키마)가 바뀌어도, 기존 사용자 뷰(외부 스키마)는 그대로 유지</li>
<li>물리적 독립성 : 저장 방식(내부 스키마)이 바뀌어도, 개념 스키마는 영향 받지 않음</li>
</ul>
<h2 id="요개논물">요개논물</h2>
<h3 id="데이터-모델-3가지-구성요소">데이터 모델 3가지 구성요소</h3>
<p>구조 : 데이터베이스에 표현될 객체 타입, 데이터 타입, 객체들 간의 관계 정의
연산 : 데이터를 조작하고 검색하는 방법에 대한 명세
제약조건 : 일관성 있는 데이터를 유지하기 위한 논리적인 제약사항</p>
<h3 id="데이터베이스-설계-4단계">데이터베이스 설계 4단계</h3>
<table>
<thead>
<tr>
<th>단계</th>
<th>핵심활동</th>
<th>산출물</th>
</tr>
</thead>
<tbody><tr>
<td>요구사항 분석</td>
<td>사용자의 요구사항 수집하고 분석</td>
<td>요구사항 명세서</td>
</tr>
<tr>
<td>개념적 설계</td>
<td>현실세계를 추상적인 개념 모델로 표현</td>
<td>개념적 스키마 / E-R 다이어그램</td>
</tr>
<tr>
<td>논리적 설계</td>
<td>DBMS가 지원하는 논리적 모델로 변환</td>
<td>논리적 스키마 / 테이블 명세서</td>
</tr>
<tr>
<td>물리적 설계</td>
<td>실제 저장장치에 맞는 물리적 구조 설계</td>
<td>물리적 스키마 / 테이블 정의서</td>
</tr>
</tbody></table>
<h1 id="물리-db-설계">물리 DB 설계</h1>
<h3 id="이상현상-발생---함수적-종속-바탕으로-정규화-진행">(이상현상) 발생 -&gt; (함수적 종속) 바탕으로 (정규화) 진행</h3>
<h2 id="이상현상">이상현상</h2>
<blockquote>
<p>삽입이상 : 새로운 튜플 추가 시 불필요한 데이터 발생 + 무결성 위반
삭제이상 : 기존 튜플 삭제 시 연쇄 삭제 발생
갱신이상 : 속성값 변경 시 정보 모순 발생</p>
</blockquote>
<h2 id="함수적-종속">함수적 종속</h2>
<table>
<thead>
<tr>
<th>유형</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>완전 함수 종속(Full Functional Dependency)</td>
<td>기본키 전체에 대해서만 종속</td>
</tr>
<tr>
<td>부분 함수 종속(Partial Functional Dependency)</td>
<td>기본키 일부 속성에 종속되는 경우</td>
</tr>
<tr>
<td>이행 함수 종속(Transitive Functional Dependency)</td>
<td>A-&gt;B / B-&gt;C / A-&gt;C가 성립하는 관계</td>
</tr>
</tbody></table>
<blockquote>
<p>같은 의미
한 릴레이션에서 속성A값이 속성B값을 유일하게 결정
속성B은 속성A에 함수적으로 종속된다
A -&gt; B</p>
</blockquote>
<h2 id="정규화">정규화</h2>
<blockquote>
<p>제1정규형(1NF) : 모든 속성 값이 원자값
제2정규형(2NF) : 부분 함수 종속 제거
제3정규형(3NF) : 이행적 함수 종속 제거
BCNF : 결정자 / 후보키
제4정규형(4NF) : 다치 종속 제거
제5정규형(5NF) : 조인 종속 제거</p>
</blockquote>
<ul>
<li>반정규화
성능향상이나 개발의 편의성을 위해 의도적으로 중복을 허용</li>
</ul>
<h2 id="키">키</h2>
<p>슈퍼키 : 튜플을 유일하게 식별할 수 있는 속성 집합
후보키 : 튜플을 유일하게 식별하면서 최소한의 속성으로 구성된 키
대체키 : 기본키로 선택되지 못한 나머지 후보키
기본키 : 후보키 중 선택된 단 하나의 키</p>
<p>외래키 : 다른 테이블 기본키를 참조</p>
<h2 id="데이터베이스-무결성">데이터베이스 무결성</h2>
<table>
<thead>
<tr>
<th>구분</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>개체 무결성</td>
<td>기본키는 NULL값을 가질 수 없으며, 릴레이션에서 유일해야 한다</td>
</tr>
<tr>
<td>참조 무결성</td>
<td>외래키 값은 참조 릴레이션의 기본키 값이거나 NULL이어야 한다</td>
</tr>
<tr>
<td>도메인(속성) 무결성</td>
<td>속성값은 정해진 도메인 범위에 속해야 한다</td>
</tr>
</tbody></table>
<h2 id="스토리지">스토리지</h2>
<p>여러개의 물리적인 디스크를 하나의 논리적인 디스크처럼 사용하는 기술</p>
<p>주요 목적 : 성능 향상, 안전성 확보</p>
<blockquote>
<p>스트라이핑 : 데이터를 여러 디스크에 분산 저장하여 동시에 읽고 쓸 수 있게 함. 성능 향상
미러링 : 동일한 데이터를 두 개 이상의 디스크에 복제 저장. 안전성 향상
패리티 : 데이터의 오류를 검출하고 복구하기 위한 추가 정보.</p>
</blockquote>
<table>
<thead>
<tr>
<th>RAID 레벨</th>
<th>기술</th>
<th>패리티    최소 디스크</th>
<th>장애 허용</th>
<th>저장 효율</th>
</tr>
</thead>
<tbody><tr>
<td>0</td>
<td>스트라이핑</td>
<td>2</td>
<td>불가</td>
<td>100%</td>
</tr>
<tr>
<td>1</td>
<td>미러링</td>
<td>2</td>
<td>1개</td>
<td>50%</td>
</tr>
<tr>
<td>5</td>
<td>스트라이핑 + 분산 패리티</td>
<td>3</td>
<td>1개</td>
<td>(n-1)/n</td>
</tr>
<tr>
<td>6</td>
<td>스트라이핑 + 이중 패리티</td>
<td>4</td>
<td>2개</td>
<td>(n-2)/n</td>
</tr>
<tr>
<td>10</td>
<td>미러링 + 스트라이핑</td>
<td>4</td>
<td>쌍 당 1개</td>
<td>50%</td>
</tr>
</tbody></table>
]]></description>
        </item>
        <item>
            <title><![CDATA[Zustand selector가 객체를 반환할 때 발생한 무한 렌더링 문제 해결 (useShallow 적용)]]></title>
            <link>https://velog.io/@smin_0820/Zustand-selector%EA%B0%80-%EA%B0%9D%EC%B2%B4%EB%A5%BC-%EB%B0%98%ED%99%98%ED%95%A0-%EB%95%8C-%EB%B0%9C%EC%83%9D%ED%95%9C-%EB%AC%B4%ED%95%9C-%EB%A0%8C%EB%8D%94%EB%A7%81-%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0-useShallow-%EC%A0%81%EC%9A%A9</link>
            <guid>https://velog.io/@smin_0820/Zustand-selector%EA%B0%80-%EA%B0%9D%EC%B2%B4%EB%A5%BC-%EB%B0%98%ED%99%98%ED%95%A0-%EB%95%8C-%EB%B0%9C%EC%83%9D%ED%95%9C-%EB%AC%B4%ED%95%9C-%EB%A0%8C%EB%8D%94%EB%A7%81-%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0-useShallow-%EC%A0%81%EC%9A%A9</guid>
            <pubDate>Tue, 10 Feb 2026 00:08:22 GMT</pubDate>
            <description><![CDATA[<h1 id="1문제-상황--progress-로직-리펙토링-중-무한-랜더링-발생">1.문제 상황 : Progress 로직 리펙토링 중 무한 랜더링 발생</h1>
<p>스쿼드 에디터에서 진행 상태(포메이션 선택, 선수 11명 배치, 제목 입력, 감독 이미지, 메모 입력)를 표시하는 <code>SquadEditorProgress 컴포넌트</code>를 구현하면서, 여러 컴포넌트에서 중복으로 계산하던 로직을 하나의 훅으로 통합하려고 했다.</p>
<p>기존에는 각 컴포넌트에서 직접 조건을 계산하고 있었는데, 유지보수성을 높이기 위해 Zustand 스토어에 다음과 같은 파생 상태 훅을 추가했다.</p>
<ul>
<li>useSquadProgress() : 진행 상태 계산</li>
<li>useCanSaveSquad() : 저장 가능 여부 계산</li>
</ul>
<p>즉, UI는 표시만 담당하고, 실제 조건 계산은 스토어 훅에서 관리하도록 구조를 정리하는 것이 목적이었다.</p>
<h1 id="2발생한-에러">2.발생한 에러</h1>
<p><img src="https://velog.velcdn.com/images/smin_0820/post/dc366ccd-22c8-4334-b8e4-5b93351d634a/image.png" alt="">
리팩토링 이후 아래 에러가 발생했다.</p>
<ul>
<li>The result of getSnapshot should be cached to avoid an infinite loop</li>
<li>Maximum update depth exceeded</li>
</ul>
<p>즉, 렌더링이 반복되는 무한 업데이트 루프가 발생한 상황이었다.</p>
<h1 id="3원인-분석">3.원인 분석</h1>
<p>문제의 원인은 Zustand Selector가 객체를 반환하는 방식이었다.</p>
<pre><code class="language-typescript">export const useSquadProgress = () =&gt;
  useSquadEditorStore((s) =&gt; {
    return {
      filledCount,
      hasFormation,
      isAllPlayersFilled,
      hasTitle,
      hasCoachImage,
      hasMemo,
      isMemoValid,
    };
  });</code></pre>
<p>이 코드에서는 렌더링될 때마다 새로운 객체<code>{...}</code>가 생성된다.
값이 동일하더라도 객체의 참조(reference)는 매번 달라지기 때문에 Zustand는 &quot;상태가 변경된 것&quot;으로 판단하게 된다.</p>
<p>그 결과 snapshot이 계속 변경되고 React가 업데이트를 반복하면서 Maximum update depth exceeded 에러가 발생했다.</p>
<h1 id="4해결-방법">4.해결 방법</h1>
<p>selector 결과를 안정화하기 위해 Zustand의 <code>useShallow</code>를 적용했다.</p>
<pre><code class="language-ts">import { useShallow } from &quot;zustand/react/shallow&quot;;

export const useSquadProgress = () =&gt;
  useSquadEditorStore(
    useShallow((s) =&gt; {
      return {
        filledCount,
        hasFormation,
        isAllPlayersFilled,
        hasTitle,
        hasCoachImage,
        hasMemo,
        isMemoValid,
      };
    }),
  );</code></pre>
<p>useShallow는 이전 selector의 결과와 현재 결과를 비교(shallow compare)하여 실제 값이 동일하면 동일한 snapshot으로 처리해준다.</p>
<p>이렇게 하면 selector가 새 객체를 반환하더라도 값이 같으면 업데이트가 발생하지 않기 때문에 무한 루프가 해결된다.</p>
<h1 id="5-추가-고민--useshallow로-객체를-반환하는-방식-vs-selector를-모두-쪼개는-방식">5. 추가 고민 : useShallow로 객체를 반환하는 방식 vs selector를 모두 쪼개는 방식</h1>
<p>문제를 해결한 뒤 자연스럽게 또 하나의 고민이 생겼다.</p>
<blockquote>
<p>selector에서 여러 값을 묶어서 <code>useShallow</code>로 반환하는 방식이 좋은가, 아니면 selector를 모두 분리해서 각각 가져오는 방식이 더 좋은가?</p>
</blockquote>
<p>두 방식은 모두 실무에서 사용되지만, 관점별로 장단점이 분명히 존재한다.</p>
<h3 id="useshallow로-객체-1개-반환-묶음-selector">useShallow로 &quot;객체 1개&quot; 반환 (묶음 selector)</h3>
<p>장점</p>
<ul>
<li>&quot;진행도에 필요한 값&quot; 묶음으로 코드를 읽기 쉽다</li>
<li>훅이 1개니까 컴포넌트 상단이 깔끔하다</li>
</ul>
<p>단점</p>
<ul>
<li>묶음 중 하나만 바뀌어도 “전체 묶음” 비교가 발생하고 컴포넌트가 갱신됨.</li>
</ul>
<h3 id="selector를-모두-쪼개서-분리">selector를 “모두 쪼개서” 분리</h3>
<p>장점</p>
<ul>
<li>UI가 실제로 사용하는 값만 구독하니까 변화 범위가 작아짐</li>
</ul>
<p>단점</p>
<ul>
<li>훅 호출이 여러 줄로 늘어남</li>
</ul>
<h1 id="6-결론">6. 결론</h1>
<p>Zustand에서는 selector를 무조건 쪼개거나 무조건 묶는 것보다,
상태는 분리하고 의미적으로 함께 사용되는 파생 상태만 useShallow로 묶는 혼합형 패턴이 실무적으로 가장 효율적이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[폰트 최적화]]></title>
            <link>https://velog.io/@smin_0820/%ED%8F%B0%ED%8A%B8-%EC%B5%9C%EC%A0%81%ED%99%94</link>
            <guid>https://velog.io/@smin_0820/%ED%8F%B0%ED%8A%B8-%EC%B5%9C%EC%A0%81%ED%99%94</guid>
            <pubDate>Tue, 13 May 2025 00:13:32 GMT</pubDate>
            <description><![CDATA[<h1 id="용어-설명">용어 설명</h1>
<p><img src="https://velog.velcdn.com/images/smin_0820/post/c8e01b7e-f3b9-477a-8f3e-543670ff6adf/image.png" alt=""></p>
<h2 id="foit-flash-of-invisible-text">FOIT (flash of invisible text)</h2>
<p>FOIT는 폰트가 완전히 다운로드될 때까지 화면에서 텍스트를 숨기는 방식을 의미합니다. 사용자는 폰트가 로딩되는 동안 텍스트를 볼 수 없으며, 폰트 다운로드가 끝난 후에야 텍스트가 노출됩니다. 이 방식의 단점은 폰트 로딩이 지연될 경우, 사용자에게 불편함을 줄 수 있다는 것입니다.</p>
<h2 id="fout-flash-of-unstyled-text">FOUT (flash of unstyled text)</h2>
<p>FOUT는 폰트가 다운로드되기 전까지 시스템 기본 폰트를 먼저 노출하고, 폰트 로딩이 완료된 후 지정된 웹 폰트로 교체하는 방식을 말합니다. 이 방식은 사용자가 콘텐츠를 바로 볼 수 있지만, 중간에 폰트가 바뀌면서 깜빡임 현상이 발생할 수 있습니다.</p>
<h1 id="css의-font-display-속성">CSS의 font-display 속성</h1>
<p>CSS에서는 이러한 폰트 로딩 방식을 제어하기 위한 <code>font-display</code> 속성을 제공합니다. 주요 값과 특징은 다음과 같습니다:</p>
<ul>
<li><strong>swap (FOUT)</strong><ul>
<li>기본 폰트를 먼저 보여주고, 웹 폰트 다운로드가 끝나면 교체합니다.</li>
<li>콘텐츠 접근성을 최우선으로 합니다.</li>
</ul>
</li>
<li><strong>block (FOIT)</strong><ul>
<li>최대 3초까지 웹 폰트 로딩을 기다리며, 이 시간 내에 로딩되지 않으면 기본 폰트를 표시합니다.</li>
</ul>
</li>
<li><strong>fallback (FOIT)</strong><ul>
<li>약 0.1초 동안 기다린 후, 웹 폰트가 3초 이내에 로딩되지 않으면 기본 폰트를 노출합니다.</li>
<li>폰트 다운로드 결과와 무관하게 기본 폰트를 먼저 노출하는 시간이 짧아 사용자 경험에 비교적 좋습니다.</li>
<li>한번 로딩된 폰트는 캐싱되어 재방문 시 빠르게 로딩됩니다.</li>
</ul>
</li>
<li><strong>optional (FOIT)</strong><ul>
<li>fallback과 유사하지만, 웹 폰트 로딩 시간이 길어지면 브라우저가 다운로드 연결을 취소할 수도 있습니다.</li>
<li>자주 사용하는 폰트의 경우 캐시를 활용해 빠른 로딩을 지원합니다.</li>
</ul>
</li>
</ul>
<p>이러한 방식들을 상황과 사용자의 요구사항에 맞게 선택하여 웹사이트의 성능과 사용자 경험을 최적화할 수 있습니다.</p>
<h1 id="실제-프로젝트에서-폰트-로딩-방식-테스트하기">실제 프로젝트에서 폰트 로딩 방식 테스트하기</h1>
<p>다음과 같은 방법으로 자신의 프로젝트에서 실제로 폰트 로딩 방식을 테스트할 수 있습니다.</p>
<h2 id="테스트-환경-설정-방법">테스트 환경 설정 방법</h2>
<ol>
<li><strong>SCSS 파일에서 설정하기</strong><ul>
<li>프로젝트의 <code>scss/font.scss</code> 파일에서 원하는 폰트에 대해 <code>font-display</code> 속성을 설정합니다.</li>
</ul>
</li>
</ol>
<pre><code class="language-scss">{
    font-family: &#39;NanumGothic&#39;;
  src: 
      url(&quot;../assets/fonts/NanumGothic.woff2&quot;) format(&quot;woff2&quot;),
      url(&quot;../assets/fonts/NanumGothic.woff&quot;) format(&quot;woff&quot;);
  // font-display: swap;
  // font-display: block;
  // font-display: fallback;
  // font-display: optional;
}</code></pre>
<ol>
<li><strong>브라우저에서 테스트하기</strong><ul>
<li>프로젝트를 실행한 후 브라우저에서 F12를 눌러 개발자 도구를 엽니다.</li>
<li><strong>네트워크 탭(Network Tab)</strong> 에서 <strong>캐시 중지(Disable Cache)</strong> 옵션을 체크하여 매번 폰트를 새로 다운로드 받도록 설정합니다.</li>
<li>필터 창에서 <strong>글꼴(Font)</strong>을 선택하여 웹 폰트 로딩 상태를 쉽게 관찰할 수 있습니다.</li>
</ul>
</li>
</ol>
<p>이 과정을 통해 선택한 <code>font-display</code> 방식에 따라 폰트 로딩 시 웹사이트가 어떻게 반응하는지 직관적으로 확인할 수 있습니다.</p>
<p><img src="https://velog.velcdn.com/images/smin_0820/post/35aa3aa2-d7da-473a-ae6c-df4931cbc73d/image.png" alt=""></p>
<h1 id="폰트-용량-줄이기-subset">폰트 용량 줄이기 (Subset)</h1>
<p>폰트 최적화의 기본은 용량을 줄이는 것입니다. 웹 폰트의 용량을 줄이면 로딩 속도와 사용자 경험이 개선됩니다. 다음과 같은 방법으로 폰트 용량을 효율적으로 줄일 수 있습니다.</p>
<h2 id="폰트-subset-만들기"><strong>폰트 Subset 만들기</strong></h2>
<ol>
<li><a href="https://namu.wiki/w/%EC%99%84%EC%84%B1%ED%98%95/%ED%95%9C%EA%B8%80%20%EB%AA%A9%EB%A1%9D/KS%20X%201001">KS X 1001 문자표</a>에서 필요한 글자를 추립니다.</li>
<li>원하는 폰트를 업로드하고 변환할 문자(아래 내용을 charaters에 복사 후 붙여 넣어 주세요)를 입력하여 subset 폰트로 변환합니다.</li>
<li>변환이 완료되면 demo 파일을 클릭해 변환된 폰트 형태를 확인할 수 있습니다.</li>
<li>subset된 woff, woff2 파일을 프로젝트의 fonts 폴더로 옮기고 폰트명을 지정합니다.</li>
</ol>
<p>가 각 간 갇 갈 갉 갊 감 갑 값 갓 갔 강 갖 갗 같 갚 갛 개 객 갠 갤 갬 갭 갯 갰 갱 갸 갹 갼 걀 걋 걍 걔 걘 걜 거 걱 건 걷 걸 걺 검 겁 것 겄 겅 겆 겉 겊 겋 게 겐 겔 겜 겝 겟 겠 겡 겨 격 겪 견 겯 결 겸 겹 겻 겼 경 곁 계 곈 곌 곕 곗 고 곡 곤 곧 골 곪 곬 곯 곰 곱 곳 공 곶 과 곽 관 괄 괆 괌 괍 괏 광 괘 괜 괠 괩 괬 괭 괴 괵 괸 괼 굄 굅 굇 굉 교 굔 굘 굡 굣 구 국 군 굳 굴 굵 굶 굻 굼 굽 굿 궁 궂 궈 궉 권 궐 궜 궝 궤 궷 귀 귁 귄 귈 귐 귑 귓 규 균 귤 그 극 근 귿 글 긁 금 급 긋 긍 긔 기 긱 긴 긷 길 긺 김 깁 깃 깅 깆 깊 까 깍 깎 깐 깔 깖 깜 깝 깟 깠 깡 깥 깨 깩 깬 깰 깸 깹 깻 깼 깽 꺄 꺅 꺌 꺼 꺽 꺾 껀 껄 껌 껍 껏 껐 껑 께 껙 껜 껨 껫 껭 껴 껸 껼 꼇 꼈 꼍 꼐 꼬 꼭 꼰 꼲 꼴 꼼 꼽 꼿 꽁 꽂 꽃 꽈 꽉 꽐 꽜 꽝 꽤 꽥 꽹 꾀 꾄 꾈 꾐 꾑 꾕 꾜 꾸 꾹 꾼 꿀 꿇 꿈 꿉 꿋 꿍 꿎 꿔 꿜 꿨 꿩 꿰 꿱 꿴 꿸 뀀 뀁 뀄 뀌 뀐 뀔 뀜 뀝 뀨 끄 끅 끈 끊 끌 끎 끓 끔 끕 끗 끙 끝 끼 끽 낀 낄 낌 낍 낏 낑 나 낙 낚 난 낟 날 낡 낢 남 납 낫 났 낭 낮 낯 낱 낳 내 낵 낸 낼 냄 냅 냇 냈 냉 냐 냑 냔 냘 냠 냥 너 넉 넋 넌 널 넒 넓 넘 넙 넛 넜 넝 넣 네 넥 넨 넬 넴 넵 넷 넸 넹 녀 녁 년 녈 념 녑 녔 녕 녘 녜 녠 노 녹 논 놀 놂 놈 놉 놋 농 높 놓 놔 놘 놜 놨 뇌 뇐 뇔 뇜 뇝 뇟 뇨 뇩 뇬 뇰 뇹 뇻 뇽 누 눅 눈 눋 눌 눔 눕 눗 눙 눠 눴 눼 뉘 뉜 뉠 뉨 뉩 뉴 뉵 뉼 늄 늅 늉 느 늑 는 늘 늙 늚 늠 늡 늣 능 늦 늪 늬 늰 늴 니 닉 닌 닐 닒 님 닙 닛 닝 닢 다 닥 닦 단 닫 달 닭 닮 닯 닳 담 답 닷 닸 당 닺 닻 닿 대 댁 댄 댈 댐 댑 댓 댔 댕 댜 더 덕 덖 던 덛 덜 덞 덟 덤 덥 덧 덩 덫 덮 데 덱 덴 델 뎀 뎁 뎃 뎄 뎅 뎌 뎐 뎔 뎠 뎡 뎨 뎬 도 독 돈 돋 돌 돎 돐 돔 돕 돗 동 돛 돝 돠 돤 돨 돼 됐 되 된 될 됨 됩 됫 됴 두 둑 둔 둘 둠 둡 둣 둥 둬 뒀 뒈 뒝 뒤 뒨 뒬 뒵 뒷 뒹 듀 듄 듈 듐 듕 드 득 든 듣 들 듦 듬 듭 듯 등 듸 디 딕 딘 딛 딜 딤 딥 딧 딨 딩 딪 따 딱 딴 딸 땀 땁 땃 땄 땅 땋 때 땍 땐 땔 땜 땝 땟 땠 땡 떠 떡 떤 떨 떪 떫 떰 떱 떳 떴 떵 떻 떼 떽 뗀 뗄 뗌 뗍 뗏 뗐 뗑 뗘 뗬 또 똑 똔 똘 똥 똬 똴 뙈 뙤 뙨 뚜 뚝 뚠 뚤 뚫 뚬 뚱 뛔 뛰 뛴 뛸 뜀 뜁 뜅 뜨 뜩 뜬 뜯 뜰 뜸 뜹 뜻 띄 띈 띌 띔 띕 띠 띤 띨 띰 띱 띳 띵 라 락 란 랄 람 랍 랏 랐 랑 랒 랖 랗 래 랙 랜 랠 램 랩 랫 랬 랭 랴 략 랸 럇 량 러 럭 런 럴 럼 럽 럿 렀 렁 렇 레 렉 렌 렐 렘 렙 렛 렝 려 력 련 렬 렴 렵 렷 렸 령 례 롄 롑 롓 로 록 론 롤 롬 롭 롯 롱 롸 롼 뢍 뢨 뢰 뢴 뢸 룀 룁 룃 룅 료 룐 룔 룝 룟 룡 루 룩 룬 룰 룸 룹 룻 룽 뤄 뤘 뤠 뤼 뤽 륀 륄 륌 륏 륑 류 륙 륜 률 륨 륩 륫 륭 르 륵 른 를 름 릅 릇 릉 릊 릍 릎 리 릭 린 릴 림 립 릿 링 마 막 만 많 맏 말 맑 맒 맘 맙 맛 망 맞 맡 맣 매 맥 맨 맬 맴 맵 맷 맸 맹 맺 먀 먁 먈 먕 머 먹 먼 멀 멂 멈 멉 멋 멍 멎 멓 메 멕 멘 멜 멤 멥 멧 멨 멩 며 멱 면 멸 몃 몄 명 몇 몌 모 목 몫 몬 몰 몲 몸 몹 못 몽 뫄 뫈 뫘 뫙 뫼 묀 묄 묍 묏 묑 묘 묜 묠 묩 묫 무 묵 묶 문 묻 물 묽 묾 뭄 뭅 뭇 뭉 뭍 뭏 뭐 뭔 뭘 뭡 뭣 뭬 뮈 뮌 뮐 뮤 뮨 뮬 뮴 뮷 므 믄 믈 믐 믓 미 믹 민 믿 밀 밂 밈 밉 밋 밌 밍 및 밑 바 박 밖 밗 반 받 발 밝 밞 밟 밤 밥 밧 방 밭 배 백 밴 밸 뱀 뱁 뱃 뱄 뱅 뱉 뱌 뱍 뱐 뱝 버 벅 번 벋 벌 벎 범 법 벗 벙 벚 베 벡 벤 벧 벨 벰 벱 벳 벴 벵 벼 벽 변 별 볍 볏 볐 병 볕 볘 볜 보 복 볶 본 볼 봄 봅 봇 봉 봐 봔 봤 봬 뵀 뵈 뵉 뵌 뵐 뵘 뵙 뵤 뵨 부 북 분 붇 불 붉 붊 붐 붑 붓 붕 붙 붚 붜 붤 붰 붸 뷔 뷕 뷘 뷜 뷩 뷰 뷴 뷸 븀 븃 븅 브 븍 븐 블 븜 븝 븟 비 빅 빈 빌 빎 빔 빕 빗 빙 빚 빛 빠 빡 빤 빨 빪 빰 빱 빳 빴 빵 빻 빼 빽 뺀 뺄 뺌 뺍 뺏 뺐 뺑 뺘 뺙 뺨 뻐 뻑 뻔 뻗 뻘 뻠 뻣 뻤 뻥 뻬 뼁 뼈 뼉 뼘 뼙 뼛 뼜 뼝 뽀 뽁 뽄 뽈 뽐 뽑 뽕 뾔 뾰 뿅 뿌 뿍 뿐 뿔 뿜 뿟 뿡 쀼 쁑 쁘 쁜 쁠 쁨 쁩 삐 삑 삔 삘 삠 삡 삣 삥 사 삭 삯 산 삳 살 삵 삶 삼 삽 삿 샀 상 샅 새 색 샌 샐 샘 샙 샛 샜 생 샤 샥 샨 샬 샴 샵 샷 샹 섀 섄 섈 섐 섕 서 석 섞 섟 선 섣 설 섦 섧 섬 섭 섯 섰 성 섶 세 섹 센 셀 셈 셉 셋 셌 셍 셔 셕 션 셜 셤 셥 셧 셨 셩 셰 셴 셸 솅 소 속 솎 손 솔 솖 솜 솝 솟 송 솥 솨 솩 솬 솰 솽 쇄 쇈 쇌 쇔 쇗 쇘 쇠 쇤 쇨 쇰 쇱 쇳 쇼 쇽 숀 숄 숌 숍 숏 숑 수 숙 순 숟 술 숨 숩 숫 숭 숯 숱 숲 숴 쉈 쉐 쉑 쉔 쉘 쉠 쉥 쉬 쉭 쉰 쉴 쉼 쉽 쉿 슁 슈 슉 슐 슘 슛 슝 스 슥 슨 슬 슭 슴 습 슷 승 시 식 신 싣 실 싫 심 십 싯 싱 싶 싸 싹 싻 싼 쌀 쌈 쌉 쌌 쌍 쌓 쌔 쌕 쌘 쌜 쌤 쌥 쌨 쌩 썅 써 썩 썬 썰 썲 썸 썹 썼 썽 쎄 쎈 쎌 쏀 쏘 쏙 쏜 쏟 쏠 쏢 쏨 쏩 쏭 쏴 쏵 쏸 쐈 쐐 쐤 쐬 쐰 쐴 쐼 쐽 쑈 쑤 쑥 쑨 쑬 쑴 쑵 쑹 쒀 쒔 쒜 쒸 쒼 쓩 쓰 쓱 쓴 쓸 쓺 쓿 씀 씁 씌 씐 씔 씜 씨 씩 씬 씰 씸 씹 씻 씽 아 악 안 앉 않 알 앍 앎 앓 암 압 앗 았 앙 앝 앞 애 액 앤 앨 앰 앱 앳 앴 앵 야 약 얀 얄 얇 얌 얍 얏 양 얕 얗 얘 얜 얠 얩 어 억 언 얹 얻 얼 얽 얾 엄 업 없 엇 었 엉 엊 엌 엎 에 엑 엔 엘 엠 엡 엣 엥 여 역 엮 연 열 엶 엷 염 엽 엾 엿 였 영 옅 옆 옇 예 옌 옐 옘 옙 옛 옜 오 옥 온 올 옭 옮 옰 옳 옴 옵 옷 옹 옻 와 왁 완 왈 왐 왑 왓 왔 왕 왜 왝 왠 왬 왯 왱 외 왹 왼 욀 욈 욉 욋 욍 요 욕 욘 욜 욤 욥 욧 용 우 욱 운 울 욹 욺 움 웁 웃 웅 워 웍 원 월 웜 웝 웠 웡 웨 웩 웬 웰 웸 웹 웽 위 윅 윈 윌 윔 윕 윗 윙 유 육 윤 율 윰 윱 윳 융 윷 으 윽 은 을 읊 음 읍 읏 응 읒 읓 읔 읕 읖 읗 의 읜 읠 읨 읫 이 익 인 일 읽 읾 잃 임 입 잇 있 잉 잊 잎 자 작 잔 잖 잗 잘 잚 잠 잡 잣 잤 장 잦 재 잭 잰 잴 잼 잽 잿 쟀 쟁 쟈 쟉 쟌 쟎 쟐 쟘 쟝 쟤 쟨 쟬 저 적 전 절 젊 점 접 젓 정 젖 제 젝 젠 젤 젬 젭 젯 젱 져 젼 졀 졈 졉 졌 졍 졔 조 족 존 졸 졺 좀 좁 좃 종 좆 좇 좋 좌 좍 좔 좝 좟 좡 좨 좼 좽 죄 죈 죌 죔 죕 죗 죙 죠 죡 죤 죵 주 죽 준 줄 줅 줆 줌 줍 줏 중 줘 줬 줴 쥐 쥑 쥔 쥘 쥠 쥡 쥣 쥬 쥰 쥴 쥼 즈 즉 즌 즐 즘 즙 즛 증 지 직 진 짇 질 짊 짐 집 짓 징 짖 짙 짚 짜 짝 짠 짢 짤 짧 짬 짭 짯 짰 짱 째 짹 짼 쨀 쨈 쨉 쨋 쨌 쨍 쨔 쨘 쨩 쩌 쩍 쩐 쩔 쩜 쩝 쩟 쩠 쩡 쩨 쩽 쪄 쪘 쪼 쪽 쫀 쫄 쫌 쫍 쫏 쫑 쫓 쫘 쫙 쫠 쫬 쫴 쬈 쬐 쬔 쬘 쬠 쬡 쭁 쭈 쭉 쭌 쭐 쭘 쭙 쭝 쭤 쭸 쭹 쮜 쮸 쯔 쯤 쯧 쯩 찌 찍 찐 찔 찜 찝 찡 찢 찧 차 착 찬 찮 찰 참 찹 찻 찼 창 찾 채 책 챈 챌 챔 챕 챗 챘 챙 챠 챤 챦 챨 챰 챵 처 척 천 철 첨 첩 첫 첬 청 체 첵 첸 첼 쳄 쳅 쳇 쳉 쳐 쳔 쳤 쳬 쳰 촁 초 촉 촌 촐 촘 촙 촛 총 촤 촨 촬 촹 최 쵠 쵤 쵬 쵭 쵯 쵱 쵸 춈 추 축 춘 출 춤 춥 춧 충 춰 췄 췌 췐 취 췬 췰 췸 췹 췻 췽 츄 츈 츌 츔 츙 츠 측 츤 츨 츰 츱 츳 층 치 칙 친 칟 칠 칡 침 칩 칫 칭 카 칵 칸 칼 캄 캅 캇 캉 캐 캑 캔 캘 캠 캡 캣 캤 캥 캬 캭 컁 커 컥 컨 컫 컬 컴 컵 컷 컸 컹 케 켁 켄 켈 켐 켑 켓 켕 켜 켠 켤 켬 켭 켯 켰 켱 켸 코 콕 콘 콜 콤 콥 콧 콩 콰 콱 콴 콸 쾀 쾅 쾌 쾡 쾨 쾰 쿄 쿠 쿡 쿤 쿨 쿰 쿱 쿳 쿵 쿼 퀀 퀄 퀑 퀘 퀭 퀴 퀵 퀸 퀼 큄 큅 큇 큉 큐 큔 큘 큠 크 큭 큰 클 큼 큽 킁 키 킥 킨 킬 킴 킵 킷 킹 타 탁 탄 탈 탉 탐 탑 탓 탔 탕 태 택 탠 탤 탬 탭 탯 탰 탱 탸 턍 터 턱 턴 털 턺 텀 텁 텃 텄 텅 테 텍 텐 텔 템 텝 텟 텡 텨 텬 텼 톄 톈 토 톡 톤 톨 톰 톱 톳 통 톺 톼 퇀 퇘 퇴 퇸 툇 툉 툐 투 툭 툰 툴 툼 툽 툿 퉁 퉈 퉜 퉤 튀 튁 튄 튈 튐 튑 튕 튜 튠 튤 튬 튱 트 특 튼 튿 틀 틂 틈 틉 틋 틔 틘 틜 틤 틥 티 틱 틴 틸 팀 팁 팃 팅 파 팍 팎 판 팔 팖 팜 팝 팟 팠 팡 팥 패 팩 팬 팰 팸 팹 팻 팼 팽 퍄 퍅 퍼 퍽 펀 펄 펌 펍 펏 펐 펑 페 펙 펜 펠 펨 펩 펫 펭 펴 편 펼 폄 폅 폈 평 폐 폘 폡 폣 포 폭 폰 폴 폼 폽 폿 퐁 퐈 퐝 푀 푄 표 푠 푤 푭 푯 푸 푹 푼 푿 풀 풂 품 풉 풋 풍 풔 풩 퓌 퓐 퓔 퓜 퓟 퓨 퓬 퓰 퓸 퓻 퓽 프 픈 플 픔 픕 픗 피 픽 핀 필 핌 핍 핏 핑 하 학 한 할 핥 함 합 핫 항 해 핵 핸 핼 햄 햅 햇 했 행 햐 향 허 헉 헌 헐 헒 험 헙 헛 헝 헤 헥 헨 헬 헴 헵 헷 헹 혀 혁 현 혈 혐 협 혓 혔 형 혜 혠 혤 혭 호 혹 혼 홀 홅 홈 홉 홋 홍 홑 화 확 환 활 홧 황 홰 홱 홴 횃 횅 회 획 횐 횔 횝 횟 횡 효 횬 횰 횹 횻 후 훅 훈 훌 훑 훔 훗 훙 훠 훤 훨 훰 훵 훼 훽 휀 휄 휑 휘 휙 휜 휠 휨 휩 휫 휭 휴 휵 휸 휼 흄 흇 흉 흐 흑 흔 흖 흗 흘 흙 흠 흡 흣 흥 흩 희 흰 흴 흼 흽 힁 히 힉 힌 힐 힘 힙 힛 힝
abcdefghijklmnopqrstuvwxyz
ABCDEFGHIJKLMNOPQRSTUVWXYZ
! @ # $ % ^ &amp; * ( ) _ - + = { } [ ] : ; &quot; &#39; &lt; &gt; , . ? / | \ ~ `
0123456789</p>
<p><img src="https://velog.velcdn.com/images/smin_0820/post/4974bc6d-96f5-439d-a7df-92e048a5ee71/image.png" alt=""></p>
<pre><code class="language-scss">url(&quot;../assets/fonts/**subset-**NanumGothic.woff2&quot;) format(&quot;woff2&quot;),
url(&quot;../assets/fonts/**subset-**NanumGothic.woff&quot;) format(&quot;woff&quot;);</code></pre>
<h3 id="befor">Befor</h3>
<p><img src="https://velog.velcdn.com/images/smin_0820/post/e3c70285-e56d-4c41-b11b-303f8d230497/image.png" alt=""></p>
<h3 id="after"><strong>After</strong></h3>
<p><img src="https://velog.velcdn.com/images/smin_0820/post/19f3631a-3093-455a-b843-e3a1db0c4e93/image.png" alt=""></p>
<p>기존의 폰트 파일이 예를 들어 1.7MB였다면, subset을 통해 약 1/4 수준까지 용량을 줄일 수 있습니다. 이렇게 줄어든 용량은 브라우저가 다운로드해야 하는 리소스를 감소시키며, 결과적으로 웹사이트의 로딩 속도와 사용자 경험을 크게 개선합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[이미지 최적화 2가지 방법 (Squoosh, Cloudinary)]]></title>
            <link>https://velog.io/@smin_0820/%EC%9D%B4%EB%AF%B8%EC%A7%80-%EC%B5%9C%EC%A0%81%ED%99%94-2%EA%B0%80%EC%A7%80-%EB%B0%A9%EB%B2%95-Squoosh-Cloudinary</link>
            <guid>https://velog.io/@smin_0820/%EC%9D%B4%EB%AF%B8%EC%A7%80-%EC%B5%9C%EC%A0%81%ED%99%94-2%EA%B0%80%EC%A7%80-%EB%B0%A9%EB%B2%95-Squoosh-Cloudinary</guid>
            <pubDate>Tue, 13 May 2025 00:09:31 GMT</pubDate>
            <description><![CDATA[<p>웹사이트를 만들면서 누구나 한 번쯤 마주치는 문제가 바로 이미지 최적화입니다. 이번에 진행한 프로젝트에서도 Lighthouse 성능 검사를 해봤더니 이미지가 JPG 형식이라서 성능 점수가 생각보다 좋지 않았어요. 이미지는 웹사이트의 성능과 사용자 경험에 정말 큰 영향을 미치기 때문에 제대로 최적화하는 것이 중요합니다.</p>
<p>오늘은 제가 프로젝트에서 직접 써보고 효과를 봤던 두 가지 이미지 최적화 방법인 <strong>Squoosh</strong>와 <strong>Cloudinary</strong>에 대해 소개해 보겠습니다.</p>
<p><img src="https://velog.velcdn.com/images/smin_0820/post/ed264c68-df29-49d5-93cb-22c1766908c4/image.png" alt=""></p>
<h1 id="squoosh로-jpg-→-webp-변환하기">Squoosh로 JPG → Webp 변환하기</h1>
<p>구글에서 만든 이미지 최적화 웹 애플리케이션 <strong>Squoosh</strong>입니다. JPG 이미지는 용량이 크고 압축률이 낮아서 로딩 속도가 느려질 수 있습니다. 이럴 때 WebP 형식으로 바꾸면 같은 품질이라도 훨씬 작은 용량으로 이미지를 사용할 수 있습니다.</p>
<p>Squoosh는 설치할 필요도 없고 그냥 웹에서 바로 드래그 앤 드롭만 하면 이미지를 손쉽게 WebP로 바꿀 수 있습니다.</p>
<p><a href="https://squoosh.app/">https://squoosh.app/</a></p>
<p><img src="https://velog.velcdn.com/images/smin_0820/post/bd68273b-096e-4b48-81ad-b694b569a87a/image.png" alt=""></p>
<h1 id="cloudinary로-이미지-관리하기"><strong>Cloudinary로 이미지 관리하기</strong></h1>
<p>다음은 이미지 CDN 서비스 <strong>Cloudinary</strong>입니다. Cloudinary는 단순히 이미지를 관리하는 것을 넘어, 이미지를 자동으로 최적화하고 글로벌 CDN을 통해 빠르게 전달해주는 서비스입니다.</p>
<p>저는 Cloudinary를 써보고 정말 편하다고 느꼈던 게, URL만 살짝 수정해주는 것으로 이미지의 포맷, 품질, 크기까지 간단히 조정할 수 있다는 점이었습니다.</p>
<p><a href="https://cloudinary.com/">https://cloudinary.com/</a></p>
<p>프로젝트에서 저는 이미지를 이렇게 React 컴포넌트로 구현했습니다.</p>
<pre><code class="language-tsx">&lt;img
  src={generateImageUrl({
    filename: src,
    format: &#39;jpg&#39;,
    option: &#39;w_240,h_240,q_auto,c_fill&#39;,
  })}
  alt=&quot;이미지&quot;
/&gt;</code></pre>
<p>그리고 URL을 생성해주는 함수는 이렇게 만들었어요.</p>
<pre><code class="language-tsx">export default function generateImageUrl({
  filename,
  format,
  option = &#39;q_auto,c_fill&#39;,
}: {
  filename: string
  format: &#39;jpg&#39; | &#39;webp&#39;
  option?: string
}) {
  return `https://res.cloudinary.com/dcyd8uzlr/image/upload/${option}/v1743141438/${format}/${filename}.${format}`
}</code></pre>
<h3 id="마치며">마치며</h3>
<p>이미지 최적화를 잘하면 사용자 경험과 성능을 동시에 높일 수 있습니다. 저도 이번 프로젝트에서 이 두 가지 방법을 써보고 Lighthouse 점수가 크게 올라갔어요. 여러분도 Squoosh와 Cloudinary를 꼭 활용해서 보다 빠르고 쾌적한 웹사이트를 만들어 보세요!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[React에서 페이지 이동 시 스크롤이 초기화되지 않는 문제 해결하기]]></title>
            <link>https://velog.io/@smin_0820/React%EC%97%90%EC%84%9C-%ED%8E%98%EC%9D%B4%EC%A7%80-%EC%9D%B4%EB%8F%99-%EC%8B%9C-%EC%8A%A4%ED%81%AC%EB%A1%A4%EC%9D%B4-%EC%B4%88%EA%B8%B0%ED%99%94%EB%90%98%EC%A7%80-%EC%95%8A%EB%8A%94-%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@smin_0820/React%EC%97%90%EC%84%9C-%ED%8E%98%EC%9D%B4%EC%A7%80-%EC%9D%B4%EB%8F%99-%EC%8B%9C-%EC%8A%A4%ED%81%AC%EB%A1%A4%EC%9D%B4-%EC%B4%88%EA%B8%B0%ED%99%94%EB%90%98%EC%A7%80-%EC%95%8A%EB%8A%94-%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0%ED%95%98%EA%B8%B0</guid>
            <pubDate>Tue, 29 Apr 2025 08:40:31 GMT</pubDate>
            <description><![CDATA[<h1 id="문제-상황">문제 상황</h1>
<p>리액트로 만든 카드 리스트 페이지에서 A 카드를 클릭해 상세 페이지로 이동하고, 스크롤을 내렸다.</p>
<p>이후 <strong>뒤로가기</strong>를 누르면 카드 리스트로 돌아오는데, <strong>스크롤이 내려간 상태가 그대로</strong> 유지되었다.</p>
<p>다른 카드를 클릭해도 여전히 스크롤이 내려간 위치에서 열리는 문제가 발생했다.</p>
<h1 id="원인">원인</h1>
<p>리액트 같은 SPA(Single Page Application)에서는 <strong>페이지 전환 시 브라우저를 새로고침하지 않고</strong>, 내부적으로 컴포넌트만 바꿔끼운다.</p>
<p>그래서 브라우저는 이전 페이지의 스크롤 위치를 <strong>기억하고 복원</strong>하는 기본 동작을 수행한다.</p>
<p>즉, 페이지 이동 시 스크롤을 수동으로 초기화하지 않으면,</p>
<p><strong>이전 스크롤 위치가 그대로 남게 된다.</strong></p>
<h1 id="해결-방법">해결 방법</h1>
<p><code>ScrollToTop</code>이라는 별도의 컴포넌트를 만들어서, <strong>페이지(pathname)가 바뀔 때마다 스크롤을 맨 위로 이동</strong>시킨다.</p>
<p>ScrollToTop 컴포넌트는 다음과 같이 만들었다.</p>
<pre><code class="language-tsx">// components/ScrollToTop.tsx
import { useEffect } from &#39;react&#39;;
import { useLocation } from &#39;react-router-dom&#39;;

export default function ScrollToTop() {
  const { pathname } = useLocation();

  useEffect(() =&gt; {
    window.scrollTo(0, 0);
  }, [pathname]);

  return null;
}</code></pre>
<p>그리고 <code>App.tsx</code> 파일에서 <code>BrowserRouter</code> 내부에 <code>&lt;ScrollToTop /&gt;</code>을 추가한다.</p>
<pre><code class="language-tsx">import ScrollToTop from &#39;./components/ScrollToTop&#39;;

function App() {
  return (
    &lt;BrowserRouter&gt;
      &lt;ScrollToTop /&gt;
      &lt;Routes&gt;
        {/* Routes 정의 */}
      &lt;/Routes&gt;
    &lt;/BrowserRouter&gt;
  );
}</code></pre>
<h1 id="마무리">마무리</h1>
<p>SPA에서는 페이지 이동을 부드럽게 처리하지만, 그만큼 스크롤이나 상태 관리도 신경 써야 한다.</p>
<p>ScrollToTop처럼 작은 디테일을 잡아주는 것도 사용자 경험(UX)을 높이는 좋은 방법이다!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[날짜 포맷팅 라이브러리 (date-fns)]]></title>
            <link>https://velog.io/@smin_0820/%EB%82%A0%EC%A7%9C-%ED%8F%AC%EB%A7%B7%ED%8C%85-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-date-fns</link>
            <guid>https://velog.io/@smin_0820/%EB%82%A0%EC%A7%9C-%ED%8F%AC%EB%A7%B7%ED%8C%85-%EB%9D%BC%EC%9D%B4%EB%B8%8C%EB%9F%AC%EB%A6%AC-date-fns</guid>
            <pubDate>Thu, 03 Apr 2025 06:37:56 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/smin_0820/post/fbff8a98-5ebd-4c0e-80da-8a0d91d71284/image.png" alt="">
최근에 토이 프로젝트를 진행하면서 날짜 데이터를 사용자에게 보여줘야 하는 부분이 생겼다. 처음에는 JavaScript의 기본 <code>Date</code> 객체를 사용하려 했지만, 날짜 포맷팅과 로케일 지원이 번거로웠다. 그래서 좀 더 편리한 방법을 찾다 보니 <code>date-fns</code>, <code>moment.js</code>, <code>Day.js</code> 같은 라이브러리를 알게 되었다. 검색을 통해 각 라이브러리의 장단점을 비교한 후, 모듈화와 성능 면에서 장점이 있는 <code>date-fns</code>를 선택하게 되었다.</p>
<h1 id="date-fns-란">date-fns 란?</h1>
<hr>
<p><code>date-fns</code>는 JavaScript의 날짜 및 시간 처리를 쉽게 할 수 있도록 도와주는 경량 라이브러리이다. 함수형 스타일을 기반으로 설계되어 있으며, 필요한 기능만 가져와서 사용할 수 있어 번들 크기를 줄이는 데 유리하다.</p>
<h3 id="특징">특징</h3>
<ul>
<li><strong>함수형 스타일</strong>: OOP 방식이 아닌 개별 함수로 제공됨</li>
<li><strong>모듈화</strong>: 필요한 기능만 가져와서 사용 가능 <code>import { format } from &#39;date-fns&#39;</code></li>
<li><strong>로케일 지원</strong>: 다국어 날짜 포맷팅 가능</li>
<li><strong>타임존 처리 가능</strong> <code>date-fns-tz</code> 패키지를 추가하면 지원</li>
</ul>
<h1 id="사용-방법">사용 방법</h1>
<hr>
<h3 id="1️⃣-설치">1️⃣ <strong>설치</strong></h3>
<pre><code class="language-bash">yarn add date-fns</code></pre>
<h3 id="2️⃣-날짜-포맷팅-format">2️⃣ <strong>날짜 포맷팅 (format)</strong></h3>
<pre><code class="language-tsx">import { format } from &quot;date-fns&quot;;

const date = new Date(2025, 2, 9); // 2025년 3월 9일
console.log(format(date, &quot;yyyy-MM-dd&quot;)); // &quot;2025-03-09&quot;
console.log(format(date, &quot;PPPP&quot;));       // &quot;Sunday, March 9th, 2025&quot;</code></pre>
<h3 id="3️⃣-날짜-계산-add-sub">3️⃣ <strong>날짜 계산 (add, sub)</strong></h3>
<pre><code class="language-tsx">import { addDays, subMonths } from &quot;date-fns&quot;;

const today = new Date();
console.log(addDays(today, 10));   // 오늘 날짜에서 10일 뒤
console.log(subMonths(today, 2));  // 오늘 날짜에서 2달 전</code></pre>
<h3 id="4️⃣-날짜-비교-isbefore-isafter">4️⃣ <strong>날짜 비교 (isBefore, isAfter)</strong></h3>
<pre><code class="language-tsx">import { isBefore, isAfter } from &quot;date-fns&quot;;

const date1 = new Date(2025, 2, 9);
const date2 = new Date(2025, 5, 15);

console.log(isBefore(date1, date2)); // true (date1이 더 이전 날짜)
console.log(isAfter(date1, date2));  // false</code></pre>
<h3 id="5️⃣-로케일locale-지원">5️⃣ <strong>로케일(Locale) 지원</strong></h3>
<pre><code class="language-tsx">import { format } from &quot;date-fns&quot;;
import { ko, enUS } from &quot;date-fns/locale&quot;;

const date = new Date(2025, 2, 9);

console.log(format(date, &quot;PPPP&quot;, { locale: ko }));   // &quot;2025년 3월 9일 일요일&quot;
console.log(format(date, &quot;PPPP&quot;, { locale: enUS })); // &quot;Sunday, March 9th, 2025&quot;</code></pre>
<h3 id="6️⃣-시간-차이-계산-differenceindays-differenceinhours">6️⃣ <strong>시간 차이 계산 (differenceInDays, differenceInHours)</strong></h3>
<pre><code class="language-tsx">import { differenceInDays, differenceInHours } from &quot;date-fns&quot;;

const start = new Date(2025, 2, 1);
const end = new Date(2025, 2, 9);

console.log(differenceInDays(end, start));  // 8일 차이
console.log(differenceInHours(end, start)); // 192시간 차이</code></pre>
<h1 id="date-fns-momentjs-dayjs-비교"><strong>date-fns, moment.js, Day.js 비교</strong></h1>
<hr>
<table>
<thead>
<tr>
<th>라이브러리</th>
<th>크기</th>
<th>모듈화</th>
<th>성능</th>
<th>유지보수 상태</th>
<th>사용 방식</th>
</tr>
</thead>
<tbody><tr>
<td><strong>moment.js</strong></td>
<td>🚨 큼 (200KB+)</td>
<td>❌ 없음</td>
<td>🐌 느림</td>
<td>⚠️ 유지보수 중단(Deprecated)</td>
<td>OOP 스타일(객체 기반)</td>
</tr>
<tr>
<td><strong>Day.js</strong></td>
<td>✅ 작음 (2KB)</td>
<td>❌ 없음</td>
<td>🚀 빠름</td>
<td>✅ 유지보수 중</td>
<td>moment.js와 유사한 API</td>
</tr>
<tr>
<td><strong>date-fns</strong></td>
<td>✅ 작음 (24KB)</td>
<td>✅ 있음</td>
<td>🚀 빠름</td>
<td>✅ 유지보수 중</td>
<td>함수형 스타일 (필요한 것만 가져오기)</td>
</tr>
</tbody></table>
<h3 id="핵심-비교">핵심 비교</h3>
<ul>
<li><strong>moment.js</strong>는 한때 가장 많이 쓰였지만, <strong>크기가 크고, 성능이 떨어지며, 유지보수가 중단됨</strong></li>
<li><strong>Day.js</strong>는 moment.js와 API가 거의 동일하지만, <strong>더 가벼운 크기와 좋은 성능을 제공함</strong></li>
<li><strong>date-fns</strong>는 <strong>모듈화가 가능하고 함수형 스타일</strong>이라 유지보수에 유리함</li>
</ul>
<h1 id="어떤-라이브러리를-선택하는-것이-좋을까"><strong>어떤 라이브러리를 선택하는 것이 좋을까?</strong></h1>
<hr>
<ul>
<li><strong>새로운 프로젝트</strong>: <code>date-fns</code> 또는 <code>Day.js</code> 추천</li>
<li><strong>moment.js를 사용 중이라면?</strong> <code>Day.js</code>로 마이그레이션 고려</li>
<li><strong>함수형 스타일이 필요하면?</strong> <code>date-fns</code>가 적합</li>
<li><strong>최대한 가벼운 라이브러리가 필요하면?</strong> <code>Day.js</code> 선택</li>
</ul>
<p><code>date-fns</code>, <code>moment.js</code>, <code>Day.js</code>는 각각 장단점이 있지만, <strong>moment.js는 더 이상 추천되지 않으며, date-fns 또는 Day.js 중에서 선택하는 것이 좋다</strong>. 프로젝트의 특성에 맞게 적절한 라이브러리를 선택하면 날짜 처리가 훨씬 수월해질 것이다.</p>
<h1 id="참고-자료">참고 자료</h1>
<hr>
<p><a href="https://github.com/date-fns/date-fns?tab=readme-ov-file">https://github.com/date-fns/date-fns?tab=readme-ov-file</a></p>
<p><a href="https://date-fns.org/">https://date-fns.org/</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[폰트 적용 방법 2가지]]></title>
            <link>https://velog.io/@smin_0820/%ED%8F%B0%ED%8A%B8-%EC%A0%81%EC%9A%A9-%EB%B0%A9%EB%B2%95-2%EA%B0%80%EC%A7%80</link>
            <guid>https://velog.io/@smin_0820/%ED%8F%B0%ED%8A%B8-%EC%A0%81%EC%9A%A9-%EB%B0%A9%EB%B2%95-2%EA%B0%80%EC%A7%80</guid>
            <pubDate>Wed, 02 Apr 2025 05:54:14 GMT</pubDate>
            <description><![CDATA[<p>웹 프로젝트에서 폰트는 디자인과 가독성을 결정하는 중요한 요소입니다. 이번 글에서는 <strong>웹 폰트 서비스</strong>를 이용하는 방법과 <strong>직접 폰트를 다운로드하여 적용하는 방법</strong>을 비교해 보겠습니다.</p>
<h1 id="웹-폰트-서비스를-이용하는-방법-naver-font">웹 폰트 서비스를 이용하는 방법 (Naver font)</h1>
<hr>
<h3 id="1-사이트-접속">1. 사이트 접속</h3>
<p>먼저 네이버 한글 폰트 사이트에 접속합니다. <a href="https://hangeul.naver.com/">https://hangeul.naver.com/</a></p>
<h3 id="2-원하는-폰트-찾기">2. 원하는 폰트 찾기</h3>
<p>사이트에서 다양한 폰트를 미리 보기로 확인한 후 원하는 폰트를 선택합니다.</p>
<p><img src="https://velog.velcdn.com/images/smin_0820/post/ed97f461-70ac-403f-b4a2-f2b6dc6a9de5/image.png" alt=""></p>
<h3 id="3-웹-폰트-url을-가져오기">3. 웹 폰트 url을 가져오기</h3>
<p>선택한 폰트의 웹 폰트 URL을 복사합니다.</p>
<p><img src="https://velog.velcdn.com/images/smin_0820/post/0f9cbcd9-f5d1-4562-98fa-7985369d5dd5/image.png" alt=""></p>
<h3 id="4-프로젝트에-적용하">4. 프로젝트에 적용하</h3>
<p><strong>1️⃣ HTML에서 폰트 불러오기</strong></p>
<pre><code class="language-html">   &lt;link href=&quot;https://hangeul.pstatic.net/hangeul_static/css/nanum-gothic.css&quot; rel=&quot;stylesheet&quot;&gt;
   &lt;title&gt;React App&lt;/title&gt;
</code></pre>
<p>이 코드를 <strong>public 폴더의 <code>index.html</code> 파일</strong>에서 <code>&lt;title&gt;</code> 태그 위에 추가합니다.</p>
<p><strong>2️⃣ CSS에서 폰트 적용하기</strong></p>
<p><img src="https://velog.velcdn.com/images/smin_0820/post/61d739d5-322f-407c-86b6-823b6da96869/image.png" alt=""></p>
<pre><code class="language-scss">body {
    font-family: &#39;NanumGothic&#39;;
}</code></pre>
<p>✅ <strong>장점:</strong></p>
<ul>
<li>폰트 추가, 제거, 관리가 쉽다.</li>
<li>외부에서 제공하는 최신 폰트를 바로 적용할 수 있다.</li>
</ul>
<p>❌ <strong>단점:</strong></p>
<ul>
<li>외부 서비스에 의존해야 한다.</li>
<li>폰트를 불러오는 속도가 느려질 수 있으며, 초기 로딩 속도에 영향을 줄 수 있다.</li>
</ul>
<h1 id="폰트-다운로드하고-css를-적용하는-방법">폰트 다운로드하고 css를 적용하는 방법</h1>
<hr>
<p>외부 서비스에 의존하지 않고, 직접 폰트를 관리하는 방법도 있습니다. 이 방식은 폰트 로딩 속도를 최적화할 수 있다는 장점이 있습니다.</p>
<h3 id="1-마음에-드는-폰트를-다운-받는다-왼쪽-하단-다운-버튼-클릭">1. 마음에 드는 폰트를 다운 받는다. (왼쪽 하단 다운 버튼 클릭)</h3>
<p><img src="https://velog.velcdn.com/images/smin_0820/post/a2566bdd-e04a-4e87-8917-2eed6a408cc8/image.png" alt=""></p>
<h3 id="2-사이트-접속">2. 사이트 접속.</h3>
<p>WOFF/WOFF2 형식은 웹에서 최적화된 폰트 파일 형식입니다. 변환을 위해 아래 사이트를 이용할 수 있습니다.    <a href="https://cloudconvert.com/">https://cloudconvert.com/</a> </p>
<p>변환 후 <strong>WOFF/WOFF2 파일을 다운로드</strong>합니다.</p>
<p><img src="https://velog.velcdn.com/images/smin_0820/post/99c44fd6-9167-4ae9-ba29-2a67d9594bd2/image.png" alt=""></p>
<h3 id="3-프로젝트에-적용하기">3. <strong>프로젝트에 적용하기</strong></h3>
<p><strong>1️⃣ 폰트 파일 저장하기</strong></p>
<p>변환된 폰트 파일을 프로젝트 내 <strong><code>src/assets/fonts/</code> 폴더</strong>에 저장합니다.</p>
<p><img src="https://velog.velcdn.com/images/smin_0820/post/b122c294-c97b-4907-89ba-69c57a6d271f/image.png" alt=""></p>
<p><strong>2️⃣ <code>font.scss</code> 파일 생성 및 적용</strong></p>
<p>프로젝트의 <code>scss</code> 폴더에 <code>font.scss</code> 파일을 만들고 다음 내용을 추가합니다.</p>
<pre><code class="language-scss">@font-face {
    font-family: &#39;NanumGothic&#39;;
    src: 
        url(&quot;../assets/fonts/NanumGothic.woff2&quot;) format(&quot;woff2&quot;),
        url(&quot;../assets/fonts/NanumGothic.woff&quot;) format(&quot;woff&quot;)
}</code></pre>
<p><strong>3️⃣ <code>global.scss</code>에서 불러오기</strong></p>
<pre><code class="language-scss">@import url(&quot;./font.scss&quot;);

body {
    font-family: &#39;NanumGothic&#39;;
}</code></pre>
<p>✅ <strong>장점:</strong></p>
<ul>
<li>외부 서비스에 의존하지 않으므로 안정적이다.</li>
<li>로딩 속도가 빠르고 최적화할 수 있다.</li>
</ul>
<p>❌ <strong>단점:</strong></p>
<ul>
<li><p>폰트 파일을 직접 관리해야 한다.</p>
</li>
<li><p>폰트 업데이트 시 수동으로 변경해야 한다.</p>
<p><strong>결론:</strong></p>
</li>
<li><p>빠르게 프로젝트를 진행하고 싶다면 <strong>웹 폰트 서비스</strong>를 이용하는 것이 좋습니다.</p>
</li>
<li><p>성능 최적화가 중요하다면 <strong>직접 폰트를 다운로드</strong>하여 적용하는 것이 더 나은 선택이 될 수 있습니다.</p>
</li>
</ul>
<p>프로젝트 상황에 맞게 적절한 방법을 선택하세요!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Tailwind 주요 개념 실습]]></title>
            <link>https://velog.io/@smin_0820/Tailwind-%EC%A3%BC%EC%9A%94-%EA%B0%9C%EB%85%90-%EC%8B%A4%EC%8A%B5</link>
            <guid>https://velog.io/@smin_0820/Tailwind-%EC%A3%BC%EC%9A%94-%EA%B0%9C%EB%85%90-%EC%8B%A4%EC%8A%B5</guid>
            <pubDate>Sun, 23 Mar 2025 05:55:21 GMT</pubDate>
            <description><![CDATA[<h1 id="tailwind-css란">Tailwind CSS란?</h1>
<hr>
<p>CSS 프레임워크. 미리 정의된 클래스를 사용하여 HTML 스타일을 쉽게 적용할 수 있음</p>
<ul>
<li><strong>클래스 기반</strong> : Utility-first라는 개념하에 클래스 이름으로 스타일링 가능. HTML와 CSS를 분리를 최소화하여 재사용성을 높임.</li>
<li><strong>커스텀 설정</strong> : tailwind.config.js 파일을 통해 사용자 정의 스타일 및 구성 제공</li>
<li>일관된 디자인 : 미리 정의된 클래스로 일관성 있는 디자인 구현 가능</li>
<li><strong>반응형 스타일링</strong> : 미디어 크기에 맞는 반응형 디자인을 지원하며, 클래스 접두사로 편리하게 제어 가능</li>
<li><strong>풍부한 자료</strong> : 거대한 커뮤니티와 풍부한 자료, 그리고 Tailwind를 이용한 여러가지 컴포넌트들</li>
</ul>
<p>[장점]</p>
<p>빠른 개발, 커스터마이징, 재사용성, 반응형 디자인 간편하게 구현 가능</p>
<p>[단점]</p>
<p>점점 클래스가 복잡해지고 파일 크기가 커짐, 초기 학습 비용 많이 들어감</p>
<h1 id="nextjs에서-tailwind-css-사용하기">Next.js에서 Tailwind CSS 사용하기</h1>
<hr>
<ol>
<li><strong>yarn으로 Tailwind CSS 설치 후, Tailwind CSS 구성  파일 생성을 위해 tailwindcss init 커맨드 입력</strong></li>
</ol>
<pre><code class="language-bash">yarn add -D tailwindcss postcss autoprefixer
npx tailwindcss init -p</code></pre>
<ol>
<li><strong>PostCSS 설정 파일에 Tailwind 추가</strong></li>
</ol>
<pre><code class="language-tsx">module.exports = {
    plugins: {
        tailwindcss: {},
        autoprefixer: {},
    }
}</code></pre>
<ol>
<li><strong>TailwindCSS 적용할 템플릿 파일 경로를 tailwind.config.js 설정 파일에 명시</strong></li>
</ol>
<pre><code class="language-tsx">module.exports = {
    content: [
        &#39;./src/pages/**/*.{js, jsx, ts, tsx, mdx}&#39;,
        &#39;./src/components/**/*.{js, ts, jsx, tsx, mdx}&#39;,
    ],
    theme: {
        extend: {},
    },
    plugins: [],
}</code></pre>
<ol>
<li><strong>Tailwind CSS를 사용하기 위한 CSS 파일을 생성하고 tailwindcss를 import한다.</strong></li>
</ol>
<pre><code class="language-tsx">/* globals.css */
@tailwind base;
@tailwind components;
@tailwind utilities;</code></pre>
<ol>
<li><strong>프로젝트를 시작하고, tailwind 클래스를 적용한다</strong></li>
</ol>
<h1 id="핵심-개념">핵심 개념</h1>
<hr>
<p>Tailwind CSS 공식 도큐 참고 <a href="https://tailwindcss.com/docs/styling-with-utility-classes">https://tailwindcss.com/docs/styling-with-utility-classes</a></p>
<ul>
<li>Utility-First Fundamentals (유틸리티-퍼스트 기본 원칙)</li>
<li>Hover, focus, and Other states (호버 및 포커스 다른 상태 처리)</li>
<li>Responsive design (반응형 디자인)</li>
<li>Dark mode (다크 모드)</li>
<li>Reusing Styles (스타일 재사용)</li>
<li>Adding Custom Styles (커스텀 스타일 추가)</li>
<li>Function &amp; Directives (함수 및 디렉티브)</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Next.js Script 란]]></title>
            <link>https://velog.io/@smin_0820/Next.js-Script-%EB%9E%80</link>
            <guid>https://velog.io/@smin_0820/Next.js-Script-%EB%9E%80</guid>
            <pubDate>Thu, 13 Mar 2025 08:45:55 GMT</pubDate>
            <description><![CDATA[<h1 id="nextjs-script-컴포넌트란">Next.js Script 컴포넌트란?</h1>
<hr>
<ul>
<li><p>서버 및 클라이언트에서 자바스크립트 코드를 실행하고 데이터를 초기화하는데 사용되는 개념이다.</p>
<p>  (서버측과 클라이언트측에서 둘 다 실행될 수 있음으로 SSR, CSR 모두 사용 가능)</p>
</li>
<li><p>해당 컴포넌트를 사용하면 서버에서 데이터를 미리 가져와 클라이언트로 전달하거나, 클라이언트 측에서 라우팅 또는 페이지 진입 시 특정 작업을 수행할  수 있다.</p>
</li>
</ul>
<h3 id="기능1-서버-사이드-데이터-로딩">[기능1] 서버 사이드 데이터 로딩</h3>
<p>페이지가 서버에서 처음 렌더링 될 때 데이터를 가져와 초기화하는데 사용. 예를 들어, getServerSide props 와 함께 사용해서 서버 사이드 데이터 로딩을 처리할 수 있다.</p>
<h3 id="기능2-클라이언트-사이드-데이터-로딩">[기능2] 클라이언트 사이드 데이터 로딩</h3>
<p>페이지가 클라이언트에서 로딩될 때 특정 작업 수행하도록 설정할 수 있다. 이를 통해 페이지 진입 시 데이터를 가져오거나 이벤트 핸들러 등을 등록 할 수 있다.</p>
<h1 id="nextjs-script-컴포넌트-주요-속성">Next.js Script 컴포넌트 주요 속성</h1>
<hr>
<p>Next.js에서 스크립트, 외부 스크립트 로드하는데 실행이되고, 다양한 속성을 제공해서 스크립트의 동작을 개발자가 조절할 수 있다.</p>
<table>
<thead>
<tr>
<th>속성명(props)</th>
<th>설명</th>
<th>예시</th>
</tr>
</thead>
<tbody><tr>
<td>src</td>
<td>로드할 스크립트 파일 경로 지정</td>
<td>src=”<a href="http://example.com/script%E2%80%9D">http://example.com/script”</a></td>
</tr>
<tr>
<td>strategy</td>
<td>스크립트 로드 전략 설정(언제 로드/ 실행하는지)</td>
<td>strategy=”lazyOnload”</td>
</tr>
<tr>
<td>onLoad</td>
<td>스크립트가 로드되면 실행할 함숫 지정</td>
<td>onLoad={onLoadFunc}</td>
</tr>
<tr>
<td>onReady</td>
<td>스크립트가 준비되면 실행할 함수 지정</td>
<td>onReady={onReadyFunc}</td>
</tr>
<tr>
<td>onError</td>
<td>스크립트 로드 중에 오류가 발생했을 때 실행할 함수 지정</td>
<td>onError={onErrorFunc}</td>
</tr>
</tbody></table>
<h2 id="strategy의-4가지-다른-전략">strategy의 4가지 다른 전략</h2>
<p><code>afterInteractive (기본값)</code> : 스크립트가 페이지 상호 작용 가능한 상태 이후에 로드 되고 실행. 예를 들어, 페이지가 로드되고 사용자가 상호작용 할 수 있는 상태가 될 때.</p>
<p><code>beforeInteractive</code> : 스크립트가 페이지가 상호 작용 가능한 이전에 로드되고 실행 (페이지가 초기 렌더링 시 필요한 스크립트들을 로드하고 해당 스크립트가 준비되면 페이지가 상호작용 가능한 상태로 전환이 된다.</p>
<p><code>lazyOnLoad</code> : 스크립트가 페이지가 완전히 로드된 후에 로드되고 실행 (페이지 초기 로드 성능 향상, 필요한 스크립트 나중에 로드하기 때문에 초기 페이지 로딩 시간 단축 가능)</p>
<p>worker : 백그라운드 워커 스크립트를 로드하고 실행하는데 사용</p>
<h1 id="참고-자료">참고 자료</h1>
<hr>
<p><a href="https://nextjs.org/docs/app/api-reference/components/script#optional-props">https://nextjs.org/docs/app/api-reference/components/script#optional-props</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Next.js의 라우팅 설명]]></title>
            <link>https://velog.io/@smin_0820/Next.js%EC%9D%98-%EB%9D%BC%EC%9A%B0%ED%8C%85-%EC%84%A4%EB%AA%85</link>
            <guid>https://velog.io/@smin_0820/Next.js%EC%9D%98-%EB%9D%BC%EC%9A%B0%ED%8C%85-%EC%84%A4%EB%AA%85</guid>
            <pubDate>Mon, 10 Mar 2025 01:52:25 GMT</pubDate>
            <description><![CDATA[<h1 id="nextjs-라우팅이란">Next.js 라우팅이란?</h1>
<hr>
<ul>
<li>Next.js는 파일 시스템 기반의 라우팅인 <code>Pages Routers</code> 을 제공한다.</li>
</ul>
<h3 id="pages-라우팅">Pages 라우팅</h3>
<p>파일을 <code>Pages</code> 라는 폴더 안에 생성하면, 자동으로 라우팅이 적용된다.</p>
<p>pages/faqs/index.ts 파일    ⇒    “/faqs” 라는 경로로 자동으로 라우팅이 적용 (따로 라우팅을 적용X 세팅 X)</p>
<h3 id="동적-라우팅">동적 라우팅</h3>
<p>URL 경로에서 변수를 추출하고 동적 데이터를 처리할 수 있도록 함</p>
<p>/blog/[slug].js 파일에서 [slug] 부분은 동적 변수로 취급</p>
<h3 id="link-컴포넌트">Link 컴포넌트</h3>
<p>페이지 간 내부 네비게이션을 쉽게 구현할 수 있는 Link 컴포넌트 제공</p>
<h3 id="userouter-훅">useRouter 훅</h3>
<p>현재 라우트와 관련된 정보들을 가져오고, 페이지 내에서 동적으로 라우팅 조작 가능</p>
<h1 id="pages-routes-파일-기반-라우팅">Pages Routes (파일 기반 라우팅)</h1>
<hr>
<ul>
<li>Next.js는 ‘파일 시스템 기반 라우팅’을 기본적으로 제공함</li>
<li>프로젝트의 /pages 디렉토리 내부에 생성된 파일 구조와 URL 경로를 일치 시켜 자동으로 라우팅 됨</li>
<li>따라서, 별도의 라우팅 설정이 필요하지 않다</li>
</ul>
<p><img src="https://velog.velcdn.com/images/smin_0820/post/4df964e3-7551-457f-bff0-8a7c8f7fb756/image.png" alt=""></p>
<h3 id="indexjs">/index.js</h3>
<p>: 기본 root 페이지로 매핑되어 <a href="http://example.com/">http://example.com/</a> 로 접급할 수 있음</p>
<h3 id="aboutjs">/about.js</h3>
<p>: /about 경로로 매핑되어 <a href="http://example.com/about">http://example.com/about</a> 로 접근할 수 있음</p>
<h3 id="contacttestjs">/contact/test.js</h3>
<p>: /contact/test 경로로 매핑되어 <a href="http://exmaple.com/contact/test">http://exmaple.com/contact/test</a> 로 접근할 수 있음</p>
<h1 id="dynamic-routes-동적-라우팅">Dynamic Routes (동적 라우팅)</h1>
<hr>
<ul>
<li>동적 라우팅을 사용하면 URL에서 변수를 추출하고 동적 데이터를 처리할 수 있다.</li>
<li>가장 기본적인 ‘파일 시스템’ 을 사용해서 동적 라우팅을 처리할 수 있다. 이를 위해서 파일 및 디렉토리 이름을 [name].js or [id].js 와 같이 <strong>대괄호</strong>로 묶어야 한다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/smin_0820/post/ceb7608d-c7fd-4e8f-9214-9dfd80272f60/image.png" alt=""></p>
<h1 id="nextjs-link-컴포넌트">Next.js Link 컴포넌트</h1>
<hr>
<ul>
<li>next의 link 컴포넌트는 내부 네비게이션을 만들 떄 사용되며, 페이지 간의 이동을 쉽게 처리할 수 있게 해준다.</li>
<li>SPA와 비슷하게 클라이언트 사이드 라우팅을 가능하게 한다. 따라서 Link 컴포넌트로 만든 링크를 클릭했을 때 페이지는 새로고침 되지 않고 클라이언트 사이드 라우팅이 굉장히 자연스럽게 넘어가게 된다.</li>
</ul>
<h1 id="nextjs-userouter-훅">Next.js useRouter 훅</h1>
<hr>
<ul>
<li>현재 라우트 정보를 가져오고, 페이지 내에서 동적 라우팅을 제어하는데 사용됨</li>
</ul>
<p><img src="https://velog.velcdn.com/images/smin_0820/post/51acbb1d-050c-45dd-80fa-a496073585f5/image.png" alt=""></p>
<h3 id="속성">속성</h3>
<p><code>router.push</code> : 새로운 경로로 이동 (히스토리 쌓임)</p>
<p><code>router.replace</code> : 현재 페이지를 새로운 경로로 대체 (브라우저의 히스토리 스택을 수정하지 않고 교체 가능)</p>
<p><code>router.back</code> : 뒤로가기</p>
<p><code>router.reload</code> : 현재 페이지 다시 로드 (새로고침)</p>
<p><code>pathname</code> : 현재 페이지 경로</p>
<p><code>locale</code> : 현재 페이지 언어 local 정보</p>
<p><code>basePath</code> : 여러 속성 정보를 통해서 현재 페이지의 라우터 확인 가능</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Next.js의 Data Fetching]]></title>
            <link>https://velog.io/@smin_0820/Next.js%EC%9D%98-Data-Fetching</link>
            <guid>https://velog.io/@smin_0820/Next.js%EC%9D%98-Data-Fetching</guid>
            <pubDate>Mon, 10 Mar 2025 01:49:39 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/smin_0820/post/303c04a7-c905-44ce-bece-d996037c7023/image.png" alt=""></p>
<h1 id="data-fetching-이란">Data Fetching 이란?</h1>
<hr>
<p>데이터 페칭 (Data Fetching) : 웹 애플리케이션에서 데이터를 가져오는 프로세스</p>
<p>Next.js는 다양한 방법의 데이터 페칭 방법이 존재</p>
<ul>
<li>서버에서 데이터를 가져와 페이지를 렌더링</li>
<li>클라이언트 측에서 데이터를 가져와 동적으로 페이지를 업데이트</li>
</ul>
<h1 id="종류">종류</h1>
<hr>
<p>Next.js는 페이지에 필요한 데이터를 효율적으로 가져오는 방법을 선택하고 사용자에게 최상의 경험을 제공하는데 활용할 수 있습니다.</p>
<p><code>getStaticProps</code></p>
<p><strong>빌드 시점</strong>에 페이지에 필요한 데이터를 불러오는 함수. (주로 정적인 사이트에서 사용) </p>
<p>예시) 제품 목록, FAQ 목록</p>
<p><code>getStaticPaths</code></p>
<p>동적 경로를 사용할 때, 필요한 경로의 목록을 동적으로 생성하는 함수입니다. (getStaticProps 함수와 함께 사용)</p>
<p>예시) 블로그 게시물 상세 페이지, 제품 디테일 페이지</p>
<p><code>getServerSideProps</code></p>
<p>매 요청마다 서버에서 필요한 데이터를 가져올 수 있게 하는 함수 (항상 최신 데이터 제공, SSR에서 사용)</p>
<p>예시) 검색 결과 페이지</p>
<p><code>API Routes</code></p>
<p>Next.js에서 엔드포인트를 생성, 사용하여 데이터를 가져오는 방법 (API 라우트를 통해서 서버와 클라이언트간 데이터를 주고 받을 수 있음)</p>
<p>예시) 데이터 등록, 처리, 로그인</p>
<h1 id="getstaticprops">getStaticProps</h1>
<hr>
<p>정적 페이지 생성을 위한 데이터를 가져오는 사전 렌더링 함수. 런타임이 아니라, 빌드 타임에서만 실행되기 때문에 변동이 거의 없는 데이터 대상으로만 적용하는게 좋다</p>
<ul>
<li>빌드 타임에 getStaticProps로 생성한 props를 가지고 페이지를 사전에 렌더링 함</li>
<li>예를 들어, 거의 변동이 없는 블로그 글 또는 FAQ 글 목록을 가져올 때 사용됨</li>
</ul>
<pre><code class="language-tsx">export async function getStaticProps() {
    const posts = await fetchPosts(); // 데이터 가져오기 함수
    return {
        props: {
            posts,
        },
    };
}</code></pre>
<h1 id="getstaticpaths">getStaticPaths</h1>
<hr>
<p>동적 경로를 위한 정적 경로 생성하는 사전 렌더링 함수.</p>
<ul>
<li>동적으로 생성되는 페이지를 사전 렌더링할 때 사용</li>
<li>예를 들어, 하나의 FAQ 데이터 (id: 1)가 존재한다고 했을 때, faqs/1 라는 경로를 빌드 타임에 미리 사전 렌더링 할 수 있음</li>
</ul>
<pre><code class="language-tsx">export async function getStaticPaths() {
    const posts = await fetchDynamicPaths(); // 동적 경로 생성 함수
    return {
        paths, 
        fallback: false, // 없는 경로는 404 페이지로 처리
    };
}</code></pre>
<h1 id="getserversideprops">getServerSideProps</h1>
<hr>
<p>서버 사이드 렌더링을 위한 데이터 가져오기 함수</p>
<ul>
<li>매 요청 마다 데이터를 서버에서 가져옴</li>
<li>예를 들어, 자주 업데이트 되는 posts 데이터들을 외부 API로 부터 fetch해서 사전 렌더링을 하고 싶을 때 사용</li>
</ul>
<pre><code class="language-tsx">export async function getServerSideProps() {
    const posts = await fetchData(); // 서버에서 데이터 가져오기
    return {
        props: {
            data,
        }
    };
}</code></pre>
]]></description>
        </item>
        <item>
            <title><![CDATA[package.json파일의 Dependencies VS devDependencies]]></title>
            <link>https://velog.io/@smin_0820/package.json-%ED%8C%8C%EC%9D%BC%EC%9D%98-Dependencies-VS-devDependencies</link>
            <guid>https://velog.io/@smin_0820/package.json-%ED%8C%8C%EC%9D%BC%EC%9D%98-Dependencies-VS-devDependencies</guid>
            <pubDate>Wed, 05 Mar 2025 05:20:04 GMT</pubDate>
            <description><![CDATA[<p>패키지 매니저(npm, yarn)를 사용하여 라이브러리를 설치하면 <code>package.json</code> 파일이 생성된다.</p>
<p>이 파일을 열어보면 <code>dependencies</code>와 <code>devDependencies</code>라는 두 가지 주요 항목을 확인할 수 있다.</p>
<h1 id="dependencies-란">dependencies 란?</h1>
<hr>
<pre><code class="language-bash">npm install [라이브러리명]
yarn add [라이브러리명]</code></pre>
<p>위와 같은 명령어를 통해 설치된 라이브러리는 <code>dependencies</code>에 추가된다.</p>
<p><code>dependencies</code>에는 애플리케이션의 동작에 직접적으로 영향을 미치며, 배포 시에도 필요한 라이브러리들이 포함된다.</p>
<p>즉, <strong>프로덕션 환경에서도 사용되는 필수 라이브러리</strong>가 <code>dependencies</code>에 들어간다고 보면 된다.</p>
<p>예를 들어, React 프로젝트에서는 <code>react</code>, <code>react-dom</code>과 같은 라이브러리들이 <code>dependencies</code>에 포함된다.</p>
<h1 id="devdependencies-란">devDependencies 란?</h1>
<hr>
<pre><code class="language-bash">npm install 라이브러리명 --save-dev
npm install 라이브러리명 -D </code></pre>
<p>위와 같은 명령어로 설치된 라이브러리는 <code>devDependencies</code>에 추가된다.</p>
<p><code>devDependencies</code>는 <strong>애플리케이션의 동작과 직접적인 연관은 없지만, 개발 과정에서 필요한 라이브러리</strong>들을 포함한다.</p>
<p>예를 들어, 코드 품질을 개선하는 <code>eslint</code>, 코드 스타일을 정리해 주는 <code>prettier</code> 등은 실제 애플리케이션 로직과 무관하므로 <code>devDependencies</code>에 포함하는 것이 일반적이다.</p>
<h1 id="devdependencies의-장점">devDependencies의 장점</h1>
<hr>
<ul>
<li>배포 시 포함되지 않으므로 <strong>최종 결과물의 크기가 줄어들고, 로딩 속도가 빨라진다</strong>.</li>
<li>불필요한 패키지가 제거되면서 <strong>빌드 시간이 단축</strong>된다.</li>
</ul>
<p>따라서 <strong>직접적인 관련이 없는 라이브러리는 <code>devDependencies</code>에 포함하는 것이 좋다</strong>.</p>
<h1 id="참고-자료">참고 자료</h1>
<hr>
<p><a href="https://pusha.tistory.com/entry/devDependencies-vs-Dependencies-%EB%B9%84%EA%B5%90">https://pusha.tistory.com/entry/devDependencies-vs-Dependencies-비교</a>
<a href="https://www.codeit.kr/community/questions/UXVlc3Rpb246NjBlNmQwN2I2ZjU1NDAxYWEyNzAyYjE1">https://www.codeit.kr/community/questions/UXVlc3Rpb246NjBlNmQwN2I2ZjU1NDAxYWEyNzAyYjE1</a>
<a href="https://80000coding.oopy.io/fb570d89-1874-424c-b0d2-5cf2bada3867">https://80000coding.oopy.io/fb570d89-1874-424c-b0d2-5cf2bada3867</a>
<a href="https://velog.io/@remon/dependencies-%EC%99%80-devDependencies-%EC%B0%A8%EC%9D%B4">https://velog.io/@remon/dependencies-와-devDependencies-차이</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Next.js에 대해 알아보자]]></title>
            <link>https://velog.io/@smin_0820/Next.js%EC%97%90-%EB%8C%80%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90</link>
            <guid>https://velog.io/@smin_0820/Next.js%EC%97%90-%EB%8C%80%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90</guid>
            <pubDate>Tue, 25 Feb 2025 02:26:48 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/smin_0820/post/6f1079bc-0eb4-4b87-b657-ae2f6c8dc6be/image.png" alt=""></p>
<p>NextJS를 사용한 강의를 듣기 전에 NextJs에 사전에 공부하고, 공부한 내용을 정리할 계획이다.</p>
<h1 id="nextjs란">NextJS란?</h1>
<hr>
<p>Next.JS는 Vercel에서 개발한 React기반 프레임워크로, 빠른 성능과 SEO 최적화를 위해 서버 사이드 렌더링(SSR) 및 정적 사이트 생성 (SSG) 등을 지원한다.</p>
<p><strong>사전 렌더링 (Pre-Rendering)</strong></p>
<ul>
<li>각 페이지들을 사전에 미리 HTML 문서로 생성해서 가지고 있음</li>
</ul>
<p><strong>서버 사이드 렌더링 (SSR)</strong></p>
<ul>
<li>페이지를 서버에서 렌더링하여 초기 로딩 속도를 향상</li>
</ul>
<p><strong>정적 사이트 생성 (SSG)</strong></p>
<ul>
<li>빌드 시점엣 페이지를 사전 렌더링하여 성능을 향상</li>
</ul>
<p><strong>Incremental Static Regeneraton (ISR)</strong></p>
<ul>
<li>동적으로 사전 렌더링할 수 있는 중간 솔루션을 제공</li>
</ul>
<p><strong>SEO 최적화</strong></p>
<ul>
<li>검색 엔진 최적화를 위한 메타 태그, 제목 태그 등을 손쉽게 설정</li>
</ul>
<p><strong>파일 기반 네비게이션</strong></p>
<ul>
<li>폴더의 경로에 따라 페이지의 경로가 설정되어 구축이 빠르고 관리가 편리</li>
<li>pages/about.js ⇒ “/about” 경로와 연결됨</li>
</ul>
<h1 id="csr이란">CSR이란?</h1>
<hr>
<p>클라이언트 측에서 페이지 렌더링을 수행하는 방식</p>
<ul>
<li>사용자의 브라우저에서 Javascript를 사용하여 페이지를 동적으로 생성</li>
<li>따라서 처음에 서버는 빈 HTML 페이지만 제공하고, 이후 데이터와 페이지를 렌더링하는 역할은 클라이언트가 수행</li>
</ul>
<ol>
<li>사용자가 새로운 사이트 요청</li>
<li>서버에서는 빈 HTML 파일 제공 (화면 X, 상호작용 X)</li>
<li>브라우저가 JS 파일 다운로드 (아직도 화면 X, 상호작용 X)</li>
<li>다운로드한 이후에 브라우저가 JS 실행하면 (화면 O, 상호작용 O)</li>
</ol>
<h1 id="csr-장단점">CSR 장단점</h1>
<hr>
<ul>
<li>주로 웹 애플리케이션에서 클라이언트 측 라우팅 및 상호작용이 많은 경우에 사용</li>
<li>SPA, 대시보드 및 관리 패널, 소셜 미디어 플랫폼, 라이브 스트리밍 및 실시간 업데이트 서비스</li>
<li>React, Vue, Angular와 같은 프레임워크, 라이브러리에서 주로 사용된다</li>
</ul>
<p>[장점]</p>
<p><strong>상호작용성</strong> : 클라이언트에서 페이지를 렌더링을 하므로 사용자와의 상호작용 매우 빠름.</p>
<p><strong>서부 부하 감소</strong> : 서버는 초기에 HTML만 제공하고 이후에는 클라이언트에서 데이터를 로드하고 모든것을 작업하기 때문에 서버 부하 감소한다는 장점이 있음.</p>
<p><strong>자연스러운 앱 경험</strong> : SPA로 구현되는 경우가 많은데, 이는 자연스러운 앱과 유사한 경험을 제공</p>
<p>[단점]</p>
<p><strong>SEO 어려움</strong> : CSR은 초기에 HTML에 콘텐츠가 없으므로 검색 엔진 최적화를 구현하기 어려움.</p>
<p>그외</p>
<ul>
<li>초기 로딩 후 콘텐츠 표시까지 로딩 시간 문제</li>
<li>CSR에서 페이지가 많이 복잡하고 데이터 양이 큰 경우 초기 로딩 or 페이지 전환 시 성능 문제 발생할 수도 있음 (특히 느린 네트워크애서 두드러짐)</li>
</ul>
<h1 id="ssr이란">SSR이란?</h1>
<hr>
<p>서버에서 페이지를 미리 생성한 뒤, 사용자에게 페이지를 렌더링을 하는 방식</p>
<ul>
<li>사용자가 페이지에 접속할 때 서버에세 미리 HTML을 생성하고 클라이언트로 보냄</li>
<li>사용자에게 초기 내용을 빠르게 표시하고 검색 엔진 최적화(SEO)를 개선하는데 도움을 줌</li>
</ul>
<ol>
<li>사용자가 새로운 사이트 요청</li>
<li>서버에서 미리 생성된 HTML 파일 제공 (화면 O, 상호작용 X)</li>
<li>브라우저가 JS 파일 다운로드 (화면 O, 상호작용 X)</li>
<li>브라우저가 JS 실행 (화면 O, 상호작용 O)</li>
</ol>
<h1 id="ssr-장단점">SSR 장단점</h1>
<hr>
<ul>
<li>주로 동적 콘텐츠를 포함하고 있는 웹 애플리케이션에 적합</li>
<li>실시간으로 콘텐츠가 업데이트되는 뉴스 웹 사이트, 블로그, 전자 상거래 플랫폼에 적합</li>
</ul>
<p>[장점]</p>
<p><strong>SEO 최적화</strong> : SSR 된 페이지들을 검색 엔진에 쉽게 색인화 가능.</p>
<p><strong>초기 로딩 속도 개선</strong> : 사용자에게 초기 콘텐츠를 더 빠르게 표시할 수 있음.</p>
<p><strong>데이터 최신화</strong> : 매 요청마다 최신 데이터를 가져올 수 있음</p>
<p>[단점]</p>
<p><strong>서버 부하</strong> : 매 요청마다 서버에서 페이지를 가져오면 서버 자원을 많이 사용할 수 있음</p>
<p><strong>느린 네트워크 연결 시</strong> : 서버에서 HTML 생성해서 가져오는데, 느린 네트워크의 영향을 받으면 초기 로딩 속도가 느려질 수 있음.</p>
<h1 id="마지막으로-ssg-알아보기">마지막으로 SSG 알아보기</h1>
<hr>
<p>Static Site Generation는 페이지를 사전에 빌드 시점에서 생성하고 정적 파일로 제공하는 방식</p>
<ul>
<li><p>기본적으로, Next.js는 SSG 방식으로 데이터를 페칭함.</p>
</li>
<li><p>초기 로딩 속도가 빠르고, SEO가 우수</p>
</li>
<li><p>미리 빌드된 페이지를 제공하기 때문에 서버 부하가 적음</p>
</li>
<li><p>하지만, 정적 데이터를 사용하므로 동적 콘텐츠에는 제한이 있음</p>
<pre><code>     ex) 주로 블로그, 포트폴리오 웹 사이트, 회사 홈페이지 등 정적인 사이트에 사용</code></pre></li>
</ul>
<p>[장점] 빠른 초기 로딩 속도, SEO 우수, 서버 부하 적음</p>
<p>[단점] 동적 데이터 제한, 업데이트된 데이터에 대한 재빌드 필요</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[브라우저의 렌더링 방식]]></title>
            <link>https://velog.io/@smin_0820/%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80%EC%9D%98-%EB%A0%8C%EB%8D%94%EB%A7%81-%EB%B0%A9%EC%8B%9D</link>
            <guid>https://velog.io/@smin_0820/%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80%EC%9D%98-%EB%A0%8C%EB%8D%94%EB%A7%81-%EB%B0%A9%EC%8B%9D</guid>
            <pubDate>Wed, 19 Feb 2025 07:32:18 GMT</pubDate>
            <description><![CDATA[<h3 id="✅-원리를-알아야-하는-이유">✅ 원리를 알아야 하는 이유</h3>
<p>내가 의도한대로 코드를 실행시키려면 브라우저가 어떻게 렌더링 되는지 파악해야 더 <strong>효율적</strong>인 코드를 작성할 수 있다.</p>
<h3 id="✅-파싱-렌더링">✅ 파싱? 렌더링?</h3>
<p><strong>[파싱]</strong></p>
<p>프로그래밍 언어의 문법에 맞게 작성된 텍스트 문서를 읽고 실행하기 위해 텍스트 문자의 문자열을 분해하고 구조를 생성하는 과정</p>
<p><strong>[렌더링]</strong></p>
<p>HTML, CSS, JS로 작성된 문서를 파싱하여 브라우저에 시각적으로 출력하는 것.</p>
<h3 id="✅-요청과-응답">✅ 요청과 응답</h3>
<p><img src="https://velog.velcdn.com/images/smin_0820/post/ee1fd183-4cfc-44db-8e1f-f72be62e1009/image.png" alt=""></p>
<p>브라우저에서 <a href="http://www.XXXXXX.com%EB%A5%BC">www.XXXXXX.com를</a> 입력 후 엔터를 치면 오른쪽 사진과 같이 순서대로 진행된다. 브라우저에서 서버로 부터 HTML 파일 요청하고 해당 파일 응답받고, CSS 파일도 요청→ 응답, JS도 동일하게 진행된다. (DNS를 통해 IP주소를 파악하는 등 더 많은 내용이 있지만 이번 글에서는 생략하고 심화 버전에서 추가로 더 작성할 계획이다)</p>
<h3 id="✅-렌더링-순서">✅ 렌더링 순서</h3>
<h3 id="1-html-파싱-dom-생성">1. HTML 파싱 DOM 생성</h3>
<ol>
<li>서버는 브라우저가 요청한 HTML 파일을 읽고 메모리에 저장한 다음, 바이트로 변환 후 바이트로 응답한다.</li>
<li>바이트 형태로 응답 받은 브라우저는 HTML 파일에 <code>&lt;meta charset=”UTF-8”&gt;</code>  지정해 둔 인코딩 방식을 확인하고 문자열로 변환한다.</li>
<li>문자열로 변환된 HTML 문서를 읽고 토큰으로 분해한다. (최소 단위)</li>
<li>토큰들을 객체로 변환하여 노드를 생성한다. 노드는 이후에 DOM을 이루는 하나의 단위이며, 노드들이 모여서 DOM 트리가 구성된다. </li>
</ol>
<p><img src="https://velog.velcdn.com/images/smin_0820/post/b8e9a759-e982-4a0b-8714-1f27acd222c2/image.png" alt=""></p>
<p>브라우저가 DOM 트리를 생성할 때 link와 img 태그를 만나게 되면, 해당 태그 안에 명시되어 있는 리소스를 다운로드 받는다.</p>
<p>그리고 DOM 트리 렌더링 과정에서 script 태그를 만나게 된다면 브라우저는 DOM 생성을 중단하고 script 태그 안에 있는 자바스크립트 코드를 해석하게 된다.</p>
<h3 id="2-css-파싱-cssom-생성">2. CSS 파싱 CSSOM 생성</h3>
<ol>
<li>한 줄씩 순차적으로 파싱하여 DOM을 생성한다. 이때, 중간에 CSS를 로드하는 link, style 태그를 만나면 DOM 생성을 일시 중단한다.</li>
<li>그 후 DOM을 만드는 것 처럼 CSS 파일을 서버에 요청, 응답받는 과정을 HTML과 동일한 과정을 거쳐 CSSOM을 생성한다. 이후 CSS 파싱이 완료되면 마저 HTML 파싱이 중단된 시점으로 돌아가 다시 HTML을 파싱한다.</li>
</ol>
<h3 id="3-랜더render-tree-트리-생성">3. 랜더(Render Tree) 트리 생성</h3>
<ol>
<li>생성된 DOM 트리와 CSSOM 트리가 합쳐서 랜더 트리를 생성하게 된다.</li>
</ol>
<h3 id="4-레이아웃-단계">4. 레이아웃 단계</h3>
<ol>
<li>앞서 랜더 트리의 각 요소의 위치와 크기를 계산하여 정확한 배치를 수행한다.</li>
</ol>
<p>이 때 중요한 것은 display: none 과 같은 속성이 적용된 요소는 랜더 트리에 포함되지 않는다.</p>
<p><img src="https://velog.velcdn.com/images/smin_0820/post/ae222aca-6b9c-4c91-b4eb-b2385411e5f6/image.png" alt=""></p>
<h3 id="5-페인트-단계">5. 페인트 단계</h3>
<ol>
<li>브라우저가 렌더링된 요소들을 화면에 그리는 단계. CSS 스타일링, 배경, 그림자 등을 고려해서 여러 계층으로 구성된 렌더링 요소들을 하나의 이미지로 합치는 과정이다.</li>
</ol>
<p>이 과정은 사용자의 환경, 컴퓨터 사양, 브라우저 종류에 따라 속도가 다르므로 개발자는 최적화하여 사용자 경험을 개선해야 한다.</p>
<h3 id="✅-리플로우-현상-리페인트-현상">✅ 리플로우 현상, 리페인트 현상</h3>
<p><strong>[리플로우]</strong> </p>
<p>CSS 수정으로 인해 화면에 보이는 Layout이 변경된다면 브라우저는 렌더 트리를 다시 생성하고 레이아웃→페인트→ Composite→화면을 사용자들에게 다시 렌더링하는 현상.</p>
<p><img src="https://velog.velcdn.com/images/smin_0820/post/759125d2-f02f-4ea4-bc2e-466095fe178b/image.png" alt=""></p>
<p><strong>[리페인트]</strong> </p>
<p>레이아웃 단계에서 변경이 없다면 레이아웃 단계를 건너뛰고 페인트,Composite, 화면 렌더링을 하게된다.</p>
<p><img src="https://velog.velcdn.com/images/smin_0820/post/a09ae941-0ed2-4d15-b548-b055ba0a5b27/image.png" alt=""></p>
<h3 id="✅-웹-사이트-성능-좋게-하려면">✅ 웹 사이트 성능 좋게 하려면?</h3>
<h3 id="1-애니메이션-구현-시-transform-opacity-사용">1. 애니메이션 구현 시 transform, opacity 사용</h3>
<p>transform, opacity 속성을 사용해도 DOM 트리를 변경되지 않게 설계되어 있다. 그렇기 때문에 리플로우, 리페인트를 생략 되고 브라우저가 화면을 쾌적하게 렌더링을 할 수 있게 된다.</p>
<h3 id="2-css-및-javascript-최적화">2. CSS 및 JavaScript 최적화</h3>
<p>css코드와 js코드가 지나치게 복잡하거나, 파일 크기가 크면 렌더링 성능을 저하시키는 원인이 된다. 그래서 코드를 압축하고, 중복 또는 불필요한 코드를 제거하고, JS코드를 지연 로딩하거나 비동기 로딩을 이용하여 페이지 로딩 시간을 최적화 필요가 있다.</p>
<h3 id="3-외부에서-가져오는-횟수-줄이기">3. 외부에서 가져오는 횟수 줄이기</h3>
<h3 id="4-이미지--최적화">4. 이미지  최적화</h3>
<p>Lazy Loading 기술을 이용하는 등 페이지 스크롤링에 따라 이미지를 로딩하는 방식을 채택한다.</p>
<h3 id="참고-자료">참고 자료</h3>
<p><a href="https://www.youtube.com/watch?v=z1Jj7Xg-TkU">https://www.youtube.com/watch?v=z1Jj7Xg-TkU</a></p>
<p><a href="https://oliviakim.tistory.com/80#%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%20%ED%8C%8C%EC%8B%B1%EA%B3%BC%20%EC%8B%A4%ED%96%89-1">https://oliviakim.tistory.com/80#자바스크립트 파싱과 실행-1</a></p>
<p><a href="https://opendeveloper.tistory.com/entry/FrontEnd-%EC%A7%80%EC%8B%9D%EB%B8%8C%EB%9D%BC%EC%9A%B0%EC%A0%80-%EB%A0%8C%EB%8D%94%EB%A7%81-%EC%9B%90%EB%A6%AC%EC%99%80-%EC%88%9C%EC%84%9C%EC%84%B1%EB%8A%A5-%EC%B5%9C%EC%A0%81%ED%99%94-%EA%B3%A0%EB%A0%A4%EC%82%AC%ED%95%AD">https://opendeveloper.tistory.com/entry/FrontEnd-지식브라우저-렌더링-원리와-순서성능-최적화-고려사항</a></p>
<p><a href="https://www.youtube.com/watch?v=Mqh13dNI8jc">https://www.youtube.com/watch?v=Mqh13dNI8jc</a></p>
<p><a href="https://www.reason-to-code.com/blog/why-do-they-ask-about-browser-rendering/">https://www.reason-to-code.com/blog/why-do-they-ask-about-browser-rendering/</a></p>
]]></description>
        </item>
    </channel>
</rss>