<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>seobi-97.log</title>
        <link>https://velog.io/</link>
        <description>즐겁게 코딩 ૮₍ •̀ᴥ•́ ₎ა</description>
        <lastBuildDate>Thu, 28 Aug 2025 10:06:53 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>seobi-97.log</title>
            <url>https://velog.velcdn.com/images/seobi-97/profile/c51cd94f-5ce9-411f-b013-6781ed9c91b3/image.jpg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. seobi-97.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/seobi-97" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[✨SIPE 네 번째 사담콘 참가 후기!✨]]></title>
            <link>https://velog.io/@seobi-97/SIPE-%EB%84%A4-%EB%B2%88%EC%A7%B8-%EC%82%AC%EB%8B%B4%EC%BD%98-%EC%B0%B8%EA%B0%80-%ED%9B%84%EA%B8%B0</link>
            <guid>https://velog.io/@seobi-97/SIPE-%EB%84%A4-%EB%B2%88%EC%A7%B8-%EC%82%AC%EB%8B%B4%EC%BD%98-%EC%B0%B8%EA%B0%80-%ED%9B%84%EA%B8%B0</guid>
            <pubDate>Thu, 28 Aug 2025 10:06:53 GMT</pubDate>
            <description><![CDATA[<p><img src="https://velog.velcdn.com/images/seobi-97/post/a3430e36-3ce5-4a2e-a2ba-9849d8b755e5/image.png" alt=""></p>
<h2 id="sipe-네-번째-사담콘-참석-후기">SIPE 네 번째 사담콘 참석 후기</h2>
<p>얼마 전, <em>SIPE(SHARING INSIGHTS with PEOPLE EVERYDAY)</em>에서 진행한 사담콘에 다녀왔습니다.
너무 재밌게 보고 정리도 할 겸, 참가한 제 경험을 공유해보려고합니다!</p>
<h2 id="1-sipe란">1. SIPE란?</h2>
<p>SIPE는 Sharing Insights with People Everyday의 약자로, 단순히 프로젝트 완성에만 초점에 둔 게 아니라, 다양한 교류 활동을 통해 성장하는데 초점인 IT 동아리입니다.
주요 활동으로는 크게 세 가지가 있다해요!</p>
<ul>
<li>정규 미션
한 기수에 2번의 정규 미션을 진행한다. 자유롭게 팀을 구성하여 원하는 개발, 공부에 대한 미션을 수행한다.</li>
<li>사이프챗
개발, 커리어, 이직, 주식, 부업 등 다양한 대화 주제를 가지고 소통하는 시간이다. 다른 사람의 경험을 재미나게 들을 수 있는 시간인 거 같아요.</li>
<li>사담콘
현직 개발자, 디자이너, PM의 실제 업무에서 많이 고민을 했던 기술, 커리어에 대한 이야기를 나누는 컨퍼런스이다. 해당 사담콘은 사이퍼뿐 아니라 외부 인원들도 신청을 통해 참가할 수 있다.</li>
</ul>
<blockquote>
<p>사이프 공식 사이트를 활용하여 적었습니다.
자세한 소개와 활동은 <a href="https://sipe.team/">https://sipe.team/</a> 에서 확인할 수 있습니다!</p>
</blockquote>
<h2 id="2-사담콘-참가">2. 사담콘 참가</h2>
<p>이번 사담콘은 공덕역 프론트원에서 열렸습니다.
부트캠프에서 알게 되어 꾸준히 연락하는 친구가 “우리 동아리에서 컨퍼런스를 열어! 부담없이 한번 들어봐!”라고 권유해줘서 참석하게 됐습니다.
미리 준비한 QR코드로 빠르게 입장했고, 홀에는 간단한 과자와 음료가 준비되어 있었습니다. 중간에 당 떨어질 때 방문하기 딱 좋은..
무겁고 진지한 분위기로 생각했지만, 생각보다 훨씬 활기찼고 참여자도 많았어요!
포스트잇에 인스타 아이디나 번호를 적어 랜덤으로 교환해서 ‘커피챗’ 상대를 찾는 이벤트도 있었어요. 저는 망설이다 기회를 놓쳤습니다..!
<img src="https://velog.velcdn.com/images/seobi-97/post/982a5629-e9d0-456b-b58e-2634bd7ad600/image.jpeg" width="50%"/></p>
<h3 id="발표-세션">발표 세션</h3>
<p><img src="https://velog.velcdn.com/images/seobi-97/post/c9710c83-ae2a-435a-8fdb-1fae2cf9ee08/image.png" alt=""></p>
<p>발표는 백엔드, AI, PM, 개발 유튜버 등 다양한 분야에서 종사하는 분들이 준비하셨어요.
처음에는 “프론트엔드 얘기 아니면 잘 이해 못하고 흥미도 떨어지지 않을까” 걱정했는데, 발표자분들이 다양한 사람이 모일 걸 예상하고 눈높이에 맞는 설명과 비유를 곁들여서 고민을 공감하며 재밌게 들을 수 있었습니다.</p>
<p>특히 인상 깊었던 내용들은</p>
<ul>
<li>경품 이벤트 분산락 문제 해결 시도</li>
<li>AI의 환각(hallucination)과 안정성/비용/응답속도 이슈</li>
<li>개발 유튜버의 성장 과정</li>
<li>패키지를 잘 분리하려다보니 배보다 배꼽이 더 커진 경험담!</li>
</ul>
<p>저는 첫 세션부터 노트북을 펴고 메모할 만큼 몰입해서 들었습니다.
<img src="https://velog.velcdn.com/images/seobi-97/post/d535fcbd-abeb-40d3-bbf7-7578a8b85927/image.jpeg" width="50%"/></p>
<h3 id="네트워킹-시간">네트워킹 시간</h3>
<p>대학생 때 이후로 오랜만에 발표를 오래 듣다보니 예상치 못한 체력 이슈가 있었습니다. 살짝 정신이 혼미해질때쯤 쉬는 시간이 주어졌어요
홀에서 친구와 함께 돌아다니며 많은 개발자 분들과 인사를 나눌 수 있었습니다. “같은 분야네요!”, “저는 이런 분야 관심있어요!” 하면서 대화도 하고, 처음 본 분들과 인생네컷도 찍는 진귀한(?) 경험도 했습니다!
<img src="https://velog.velcdn.com/images/seobi-97/post/d5304e6f-dd2a-4b18-a217-23f4aa9a5afe/image.jpg" width="50%"/>
그리고 정말 놀랐던 건, 제 대학 한 학번 뒤 동기가 동아리 1기부터 활동하고 있었다는 겁니다.
한번 마주치기도 힘든데 최근에 세 번이나 우연히 마주치다니..꼭 밥 한 끼 해야겠네요.</p>
<h2 id="마무리">마무리</h2>
<p align=center><img src="https://velog.velcdn.com/images/seobi-97/post/03cfa5fe-c5fd-450c-9e25-457a02126cbd/image.jpeg" width="50%"/></p>

<p>행사 마지막에는 경품 추첨이 있었습니다. 개발 서적, 사이프 굿즈가 걸려있었는데 역시 똥손인 저는 바로 광탈! 친구는 책에 당첨됐습니다.</p>
<h2 id="느낀-점">느낀 점</h2>
<p>저는 커뮤니티 활동 경험도 많지 않고, 제 실력이 뛰어나다고 생각하지 않아서 사실 걱정이 많았습니다. “과연 내가 대화를 잘할 수 있을까? 다른 사람 얘기를 잘 이해할 수 있을까..?</p>
<p>하지만 괜한 걱정을 한 거 같아요! 발표는 이해하기 쉽게 준비되어 있었고, 참가자분들도 먼저 인사해주시고 편하게 이야기를 나눌 수 있었어요.
이번 경험 덕분에 앞으로는 더 많은 사람들과 개발, 커리어, 취미 등 다양한 주제로 얘기를 나누고 싶다는 생각을 했습니다.</p>
<p>벌써 다음 사담콘이 기대됩니다!🙌</p>
<blockquote>
<p>추후에 아래 유튜브 계정으로 사담콘 영상이 업로드 된다고 합니다!
<a href="https://www.youtube.com/@sipe_team/videos">https://www.youtube.com/@sipe_team/videos</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[A text node cannot be a child of a <View>.]]></title>
            <link>https://velog.io/@seobi-97/A-text-node-cannot-be-a-child-of-a-View</link>
            <guid>https://velog.io/@seobi-97/A-text-node-cannot-be-a-child-of-a-View</guid>
            <pubDate>Mon, 10 Mar 2025 06:29:20 GMT</pubDate>
            <description><![CDATA[<p>React Native를 이용해 운동 예약 앱을 만들던 도중 <strong>A text node cannot be a child of a View.</strong> 에러를 발견했다.
 대충 에러 내용을 보면 View의 자식 노드로 있는 text에 문제가 있는것으로 보인다.</p>
<p> 회원가입 페이지인데, 글자 수가 2글자 이하거나 정규식이 맞지 않을때 경고 메세지를 보여주려했다.</p>
<blockquote>
<pre><code>&lt;View style={[styles.container, colorScheme === &#39;dark&#39; &amp;&amp; styles.darkContainer]}&gt;
            &lt;Text style={[styles.title, colorScheme === &#39;dark&#39; &amp;&amp; styles.darkText]}&gt;회원가입&lt;/Text&gt;
            &lt;TextInput
                style={[styles.input, colorScheme === &#39;dark&#39; &amp;&amp; styles.darkInput]}
                placeholder=&quot;이름&quot;
                value={formData.name}
                onChangeText={text =&gt; handleChange(&#39;name&#39;, text)}
            /&gt;
            &lt;TextInput
                style={[styles.input, colorScheme === &#39;dark&#39; &amp;&amp; styles.darkInput]}
                placeholder=&quot;이메일&quot;
                value={formData.email}
                onChangeText={text =&gt; handleChange(&#39;email&#39;, text)}
            /&gt;
            &lt;TextInput
                style={[styles.input, colorScheme === &#39;dark&#39; &amp;&amp; styles.darkInput]}
                placeholder=&quot;비밀번호&quot;
                value={formData.password}
                onChangeText={text =&gt; handleChange(&#39;password&#39;, text)}
                secureTextEntry
            /&gt;
            {errors.name &amp;&amp; &lt;Text style={styles.errorText}&gt;{errors.name}&lt;/Text&gt;}
            {errors.email &amp;&amp; &lt;Text style={styles.errorText}&gt;{errors.email}&lt;/Text&gt;}
            {errors.password &amp;&amp; &lt;Text style={styles.errorText}&gt;{errors.password}&lt;/Text&gt;}
            &lt;Button title=&quot;회원가입&quot; onPress={handleSignup} /&gt;
        &lt;/View&gt;</code></pre></blockquote>
<pre><code>
하지만 해당 에러 구문에서 에러가 발생하였다.
원래 코드의 문제점은 errors.name이 빈 문자열일 경우 false를 반환하지만, JavaScript에서는 false도 하나의 값으로 인식하여 렌더링을 시도한다는 점이다. 따라서 View에서는 false값을 직접적으로 가질 수 없기 때문에 에러가 발생하는것이다.

따라서 아래와 같은 코드로 수정하였다.</code></pre><p>{errors.name ? <Text style={styles.errorText}>{errors.name}</Text> : null}
{errors.email ? <Text style={styles.errorText}>{errors.email}</Text> : null}
{errors.password ? <Text style={styles.errorText}>{errors.password}</Text> : null}</p>
<p>```</p>
<p>null값일 경우 렌더링을 하지 않기 때문에, 에러가 발생하지 않는다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Spring Boot + Kotlin] MariaDB 설치 및 연동하기]]></title>
            <link>https://velog.io/@seobi-97/Spring-Boot-Kotlin-MariaDB-%EC%84%A4%EC%B9%98-%EB%B0%8F-%EC%97%B0%EB%8F%99%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@seobi-97/Spring-Boot-Kotlin-MariaDB-%EC%84%A4%EC%B9%98-%EB%B0%8F-%EC%97%B0%EB%8F%99%ED%95%98%EA%B8%B0</guid>
            <pubDate>Fri, 28 Jun 2024 08:36:52 GMT</pubDate>
            <description><![CDATA[<p>리눅스 서버에 MariaDB를 설치하고, 설치된 MariaDB을 연동하는 방법에 대해 알아보겠다.</p>
<h2 id="mariadb-설치">MariaDB 설치</h2>
<pre><code>// 설치
sudo apt-get update
sudo apt-get install mariadb-server</code></pre><p>설치 과정중에 비밀번호 설정이 뜰 것이다.</p>
<pre><code>Enter current password for root(enter for none):</code></pre><pre><code>// 서비스 시작 및 확인
sudo systemctl start mariadb
sudo systemctl enable mariadb
sudo systemctl status mariadb</code></pre><p><code>sudo systemctl status mariadb</code>를 확인했을때 별 다른 에러메시지가 없다면 정상적으로 실행된 것이다.</p>
<p>아래 여러 항목에 대해서 묻는데 원하는 취향에 따라 설정해주면 된다.</p>
<pre><code>// 패스워드 입력
// 초기에 설정한 패스워드를 입력해주었다.
New password:
Re-enter new password:

// anonymous 계정을 삭제하겠습니까?
Remove anonymous users?

// 원격으로 root 로그인을 허용하지 않습니까?
Disallow root login remotely?

// test database를 삭제하겠습니까?
Remove test database and access to it?

// 지금 권한 테이블을 다시 로드하시겠습니까?
Reload privilege tables now?</code></pre><p>아래 명령어로 mariaDB에 접속이 가능하다.</p>
<pre><code>sudo mysql -u root -p</code></pre><h2 id="mariadb-연동하기">MariaDB 연동하기</h2>
<ol>
<li>먼저 <code>build.gradle.kts</code> 파일을 설정해준다.<pre><code>plugins {
 id(&quot;org.springframework.boot&quot;) version &quot;3.3.1&quot;
 id(&quot;io.spring.dependency-management&quot;) version &quot;1.1.5&quot;
 kotlin(&quot;plugin.jpa&quot;) version &quot;1.9.24&quot;
 kotlin(&quot;jvm&quot;) version &quot;1.9.24&quot;
 kotlin(&quot;plugin.spring&quot;) version &quot;1.9.24&quot;
}
</code></pre></li>
</ol>
<p>group = &quot;com.example&quot;
version = &quot;0.0.1-SNAPSHOT&quot;</p>
<p>java {
    toolchain {
        languageVersion = JavaLanguageVersion.of(17)
    }
}</p>
<p>repositories {
    mavenCentral()
}</p>
<p>dependencies {
    implementation(&quot;org.springframework.boot:spring-boot-starter-data-jpa&quot;)
    implementation(&quot;org.springframework.boot:spring-boot-starter-mustache&quot;)
    implementation(&quot;org.springframework.boot:spring-boot-starter-web&quot;)
    implementation(&quot;com.fasterxml.jackson.module:jackson-module-kotlin&quot;)
    implementation(&quot;org.jetbrains.kotlin:kotlin-reflect&quot;)
    implementation(&quot;io.github.cdimascio:dotenv-kotlin:6.2.2&quot;)
    implementation(&quot;org.mariadb.jdbc:mariadb-java-client&quot;)
    developmentOnly(&quot;org.springframework.boot:spring-boot-devtools&quot;)
    testImplementation(&quot;org.springframework.boot:spring-boot-starter-test&quot;)
    testImplementation(&quot;org.jetbrains.kotlin:kotlin-test-junit5&quot;)
    runtimeOnly(&quot;org.mariadb.jdbc:mariadb-java-client&quot;)
    testRuntimeOnly(&quot;org.junit.platform:junit-platform-launcher&quot;)
}</p>
<p>kotlin {
    compilerOptions {
        freeCompilerArgs.addAll(&quot;-Xjsr305=strict&quot;)
    }
}</p>
<p>tasks.withType<Test> {
    useJUnitPlatform()
}</p>
<pre><code>2. 데이터베이스 설정
`application.yml`이나 `application.properties`를 작성한다.
</code></pre><p>// application.properties</p>
<p>spring.application.name=kotlin_crud
spring.datasource.url=jdbc:mariadb://localhost/crud
spring.datasource.username=${DB_USERNAME}
spring.datasource.password=${DB_PASSWORD}
spring.datasource.driver-class-name=org.mariadb.jdbc.Driver</p>
<p>spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MariaDB106Dialect</p>
<p>```
<code>ddl-auto</code>는 DDL(Data Definition Language)을 자동으로 작성하여 테이블을 생성하거나 수정해주는 속성이다. </p>
<p><code>show-sql</code>은 콘솔로그로 sql문을 확인할 수 있다.</p>
<p><code>format_sql</code>은 sql문을 포맷팅해서 보기 편하게 만들어준다.</p>
<p>서버의 데이터베이스를 사용한다면, <code>localhost</code>에 서버 주소를 입력하면 된다.
<code>localhost</code>뒤에는 사용할 데이터베이스 이름을 넣어주면 된다.
서버 주소, 데이터베이스 유저 이름, 패스워드는 노출될 수도 있기에 환경 변수로 사용하였다.</p>
<p>이제 애플리케이션을 실행하면 MariaDB와 연동된 Spring Boot를 사용할 수 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Spring Boot + Kotlin] Kotlin project 생성하기 ]]></title>
            <link>https://velog.io/@seobi-97/Spring-Boot-Kotlin-project-%EC%83%9D%EC%84%B1%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@seobi-97/Spring-Boot-Kotlin-project-%EC%83%9D%EC%84%B1%ED%95%98%EA%B8%B0</guid>
            <pubDate>Wed, 26 Jun 2024 07:42:15 GMT</pubDate>
            <description><![CDATA[<h2 id="1-intellij-idea-설치">1. IntelliJ IDEA 설치</h2>
<p>IntelliJ IDEA를 이용하여 프로젝트를 설정한다.
아래 사이트에서 다운로드 가능하고, 계정이 따로 없을 경우 30일 체험판 또는 무료 버전을 다운받고, 학생 계정이 있으면 확인하여 등록을 해주면 된다.
(<a href="https://www.jetbrains.com/ko-kr/idea/">https://www.jetbrains.com/ko-kr/idea/</a>)
<img src="https://velog.velcdn.com/images/seobi-97/post/d979b189-d872-41c9-9659-f414479c4658/image.png" alt=""></p>
<h2 id="2-jdk-설치">2. JDK 설치</h2>
<p><img src="https://velog.velcdn.com/images/seobi-97/post/142c1143-8f9b-4ac3-a957-6db2ba85a312/image.png" alt=""></p>
<p>리눅스 서버에 설치된 버전과 맞추기 위해 jdk-17 버전을 다운받았다.
개발환경에 맞는 버전을 선택해서 다운받으면 된다.
(<a href="https://www.oracle.com/kr/java/technologies/downloads/#java17">https://www.oracle.com/kr/java/technologies/downloads/#java17</a>)</p>
<h2 id="3-프로젝트-생성하기">3. 프로젝트 생성하기</h2>
<p><img src="https://velog.velcdn.com/images/seobi-97/post/550445bd-7b38-4fa5-9c04-0e92766e5919/image.png" alt="">
처음 안내 페이지에서 생성해도 되고, 상단 메뉴바에 File-&gt;New-&gt;Project를 선택해도 된다.
JDK는 아까 설치했던 17버전을 선택해줬다.</p>
<h2 id="4-dependecies-선택하기">4. Dependecies 선택하기</h2>
<p><img src="https://velog.velcdn.com/images/seobi-97/post/6cf86d56-17ca-4de5-a2a5-a5e4fd8720ba/image.png" alt=""></p>
<p><a href="https://spring.io/guides/tutorials/spring-boot-kotlin">공식문서</a>에 따르면, 5개의 dependencies를 선택하라고 나와있다.
나는 mariaDB를 사용할 예정이기에, H2 Database 대신 MariaDB Driver를 선택해줬다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[PostgreSQL vs MySQL]]></title>
            <link>https://velog.io/@seobi-97/PostgreSQL-vs-MySQL</link>
            <guid>https://velog.io/@seobi-97/PostgreSQL-vs-MySQL</guid>
            <pubDate>Wed, 26 Jun 2024 02:15:43 GMT</pubDate>
            <description><![CDATA[<h2 id="개요">개요</h2>
<p>대학교 수업 시간에 Database, MySQL에 대해 다뤄봤지만, 기억이 나지 않을뿐더러 너무 오래된 내용이었다. 지금까지 프론트엔드에 대해서만 공부를 하고 백엔드에 대해 지식이 많이 부족한 상태이다. 백엔드 공부의 필요성을 느끼고 차근차근 공부중이다.</p>
<p>Oracle, MySQL, Redis, MongoDB 등 다양한 Database에 들어봤지만, 그 중 PostgreSQL, MySQL에 대해 다뤄볼 예정이다.</p>
<h2 id="postgresql이란">PostgreSQL이란?</h2>
<blockquote>
<p>객체 관계형 데이터 베이스 관리 시스템(ORDBMS)이다.</p>
</blockquote>
<p>PostgreSQL은 JSON, XML등 다양한 데이터 타입을 지원하며, 고급 인덱싱 기능, 복잡한 쿼리 최적화, MVCC 등을 제공한다. 
따라서 복잡한 대용량 데이터 작업에 강점이 있다.
데이터 유형, 확장성, 동시성 및 데이터 무결성에 있어 유연성이 더 뛰어나다.</p>
<h3 id="mvccmulti-version-concurrency-control">MVCC(Multi-Version Concurrency Control)</h3>
<p>데이터베이스 관리 시스템에서 동시성 제어를 위해 사용하는 기법 중 하나이다.
MVCC는 데이터베이스의 각 레코드에 여러 버전을 저장한다. 각 트랜잭션은 레코드의 특정 버전을 참조한다. 이로 인해 읽기 작업이 쓰기 작업을 방해하지 않으며, 쓰기 작업도 다른 트랜잭션의 읽기작업을 방해하지 않는다. </p>
<h2 id="mysql이란">MySQL이란?</h2>
<blockquote>
<p>오픈 소스 관계형 데이터베이스 관리 시스템(RDBMS)이다.</p>
</blockquote>
<p>관계형 데이터베이스는 테이블 형태로 데이터를 저장하며, 테이블은 행과 열로 구성되어 있다.
주로 웹 어플리케이션에 사용되며, 사용의 용이성과 속도, 안정성이 뛰어나다는 특징이 있다.</p>
<h2 id="postgresql-vs-mysql">PostgreSQL vs MySQL</h2>
<p>위에서 각각의 특징은 살펴보았고, 어떤 데이터 베이스를 선택해야할까?
우선 PostgreSQL은 읽기-쓰기 작업, 대규모 데이터 세트 및 복잡한 쿼리를 관리하는데 선호되고, MySQL은 읽기 성능에 강점을 갖고 있다. 따라서 어느 한쪽이 좋다고 단정짓기는 어렵다. 오래된 자료이긴 하지만 속도 또한 단정짓기 어렵다. <a href="https://wskills.blogspot.com/2007/01/postgresql-vs-mysql-benchmark.html">Windows Skills</a>는 MySQL이 더 빠르다했고, <a href="https://benchw.sourceforge.net/benchw_results_open3.html">Benchw</a>은 PostgreSQL이 더 빠르다고 말했다. </p>
<h2 id="결론">결론</h2>
<p>데이터베이스 디자인, 하드웨어 환경, 사용목적에 따라 적절한 데이터베이스를 선택해야한다. 또한 두 시스템 간의 SQL문법, 데이터 타입이 약간 다르다고 하니 이것 또한 고려해봐야할 것이다.</p>
<hr>
<h2 id="참고링크">참고링크</h2>
<p><a href="https://www.integrate.io/ko/blog/postgresql-vs-mysql-which-one-is-better-for-your-use-case-ko/">PostgreSQL, MySQL 속도 비교</a>
<a href="https://f-lab.kr/insight/mysql-vs-postgresql">MySQL과 PostgreSQL의 차이점 및 선택 가이드</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[React 이미지, 글꼴 최적화]]></title>
            <link>https://velog.io/@seobi-97/React-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EA%B8%80%EA%BC%B4-%EC%B5%9C%EC%A0%81%ED%99%94</link>
            <guid>https://velog.io/@seobi-97/React-%EC%9D%B4%EB%AF%B8%EC%A7%80-%EA%B8%80%EA%BC%B4-%EC%B5%9C%EC%A0%81%ED%99%94</guid>
            <pubDate>Wed, 24 Apr 2024 05:02:28 GMT</pubDate>
            <description><![CDATA[<h2 id="문제-발생">문제 발생</h2>
<p>회사 홈페이지 리뉴얼 작업중에 문제가 발생했다.
큰 문제는 아니지만 이미지, 글꼴 로드에 많은 소요시간이 발생한다는 점이다.
이로 인해 첫 페이지 진입 시, 이미지가 매우 늦게 보이고 글꼴도 처음에는 일반 글씨였다가 나중에 적용하려던 글씨로 바뀌었다.
홈페이지를 방문하는 사람들에게 매우 불편한 요소로 생각이 되었고, 이를 최적화를 통해 개선해야겠다고 마음먹었다.</p>
<p>아래 사이트를 통해 성능 문제를 진단하였다. 역시 성능이 좋지 않다는 평가를 받았다.
<a href="https://pagespeed.web.dev/">https://pagespeed.web.dev/</a>
<img src="https://velog.velcdn.com/images/seobi-97/post/3e396eab-4ca6-4c46-9020-964de0e0d787/image.png" alt="">
<img src="https://velog.velcdn.com/images/seobi-97/post/42815525-6d85-4b8c-920f-7d5cb83e1d5a/image.png" alt=""></p>
<h2 id="이미지-최적화">이미지 최적화</h2>
<p>이미지 폴더에 들어가 이미지를 하나하나 확인하였다.
페이지에서 사용하는 규격은 훨씬 작은데 사진의 규격은 너무도 컸다.
또한 .jpg, .png 파일을 .webp으로 바꿔줬다.
.webp은 뛰어난 무손실 및 손실 압축을 제공 하는 최신 이미지 파일 포멧으로 모든 경우는 아니지만 대부분의 경우 더 가벼운 용량을 갖는다.
<a href="https://squoosh.app/">해당 사이트</a>를 통해 .webp으로 이미지 변환 작업을 해주었다. 사이즈 또한 변경하였다.
<img src="https://velog.velcdn.com/images/seobi-97/post/99e7ee30-4f31-4926-9800-4a6a08b83bdb/image.png" alt=""><img src="https://velog.velcdn.com/images/seobi-97/post/e224bdaa-aae2-45d1-9e64-bee2429e11ae/image.png" alt=""></p>
<p>모든 사진의 용량을 줄이고, 해당 규격에 맞게만 적용하여도 아래와 같이 성능이 많이 향상된 것을 느낄 수 있다.
<img src="https://velog.velcdn.com/images/seobi-97/post/19b78087-7378-48ec-b4a4-67f0e738f58e/image.png" alt="">
<img src="https://velog.velcdn.com/images/seobi-97/post/0941ebbe-b342-483c-bb52-49d6ff2bdc8b/image.png" alt=""></p>
<h2 id="글꼴-최적화">글꼴 최적화</h2>
<p>리뉴얼 사이트에서는 pretendard 글꼴을 사용한다. 글꼴을 다운받다보니 .ttf, .otf, .woff가 보였다. 처음에 적용한 것은 .otf였다. 글꼴 또한 성능 평가에서 좋지 못했기 때문에 .woff를 적용해보기로 했다.</p>
<h3 id="otf-ttf-woff">OTF, TTF, WOFF</h3>
<p>우선 OTF와 TTF의 차이점은 포멧 방식이다. OTF는 오픈 타입(Open Type Font)이고, TTF는 트루 타입(True Type Font)이다. OTF가 TTF보다 더 많은 정보를 바탕으로 섬세한 작업을 하며 일반 환경에서는 큰 차이가 없지만, 고해상도에서는 차이가 있다.
WOFF는 압축된 파일이라 다운이나 웹 페이지에서 사용이 용이하다는 장점이 있다.</p>
<h3 id="성능-비교">성능 비교</h3>
<p>.woff 파일을 적용하여 테스트를 진행했는데 큰 차이를 느끼지 못했다. 여러 이미지들과 함께 글꼴을 불러오다보니 차이를 느끼지 못한 것 같다. 또한 성능 비교를 하면서 생각이 든게 Pretendard에 Light, Bold, Regular, Medium 4개를 다 사용할 필요가 있냐는 거다. 4개의 글꼴 파일을 다 불러오다보니 성능이 저하될 수 밖에 없었다. 따라서 2개의 글꼴 파일만 사용하고 나머지는 font-weight를 통해 적절히 변경하기로 하였다.</p>
<h3 id="preload">Preload</h3>
<p>글꼴 최적화 방법 중 preload라는 것을 발견하였고, 해당 방법으로 테스트하였다. 하지만 preload도 어쨌든 load를 해야한다. 4개의 글꼴을 모두 preload를 하게 되면 첫 페이지를 띄우는 시간이 엄청 증가할 것이다. 따라서 2개의 글꼴을 사용하고 처음 화면에 사용되는 글꼴만 preload를 해주었다.
.html파일에서 head 태그 안에 입력해주었다.</p>
<pre><code>&lt;link
    rel=&quot;preload&quot;
    type=&quot;font/woff&quot;
    as=&quot;font&quot;
    href=&quot;/src/assets/fonts/pretendard/Pretendard-Medium.woff&quot;
    crossorigin
/&gt;</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[Organization Repository에 Github label 커스텀 적용하기+ 템플릿 생성하기]]></title>
            <link>https://velog.io/@seobi-97/Organization-Repository%EC%97%90-Github-label-%EC%BB%A4%EC%8A%A4%ED%85%80-%EC%A0%81%EC%9A%A9%ED%95%98%EA%B8%B0-%ED%85%9C%ED%94%8C%EB%A6%BF-%EC%83%9D%EC%84%B1%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@seobi-97/Organization-Repository%EC%97%90-Github-label-%EC%BB%A4%EC%8A%A4%ED%85%80-%EC%A0%81%EC%9A%A9%ED%95%98%EA%B8%B0-%ED%85%9C%ED%94%8C%EB%A6%BF-%EC%83%9D%EC%84%B1%ED%95%98%EA%B8%B0</guid>
            <pubDate>Fri, 24 Nov 2023 07:54:37 GMT</pubDate>
            <description><![CDATA[<p>이번 프로젝트에 Issues와 Pull requests를 좀 더 체계적으로 관리하고,  템플릿을 만들어 편리하게 이용도 하고 이쁘게 꾸미고 싶었다.</p>
<h1 id="github-label-커스텀-적용하기">Github label 커스텀 적용하기</h1>
<p>구글에서 Github issue template을 검색하는 도중 label 간편하게 커스텀 할 수 있는 <a href="https://github.com/Financial-Times/github-label-sync">github-label-sync</a>라는 라이브러리를 발견했다.</p>
<p>Github에서 Issues에 들어가면, 기본적으로 label 9개가 주어진다.
하지만 이 라이브러리를 사용하면 이렇게 더 이쁘고 아이콘으로 한눈에 확인하기 편하다.
<img src="https://velog.velcdn.com/images/seobi-97/post/ca698abc-b524-447b-8cb6-c8f0fe95996e/image.png" alt=""></p>
<h2 id="1-labelsjson">1. labels.json</h2>
<p>자신이 원하는 경로에 labels.json 파일을 만든다.
label의 <code>name</code>, <code>color</code>, <code>description</code>, <code>aliases</code> 를 정의할 수 있다.</p>
<pre><code>[
  {
    &quot;name&quot;: &quot;⚙ Setting&quot;,
    &quot;color&quot;: &quot;e3dede&quot;,
    &quot;description&quot;: &quot;개발 환경 세팅&quot;
  },
  {
    &quot;name&quot;: &quot;✨ Feature&quot;,
    &quot;color&quot;: &quot;a2eeef&quot;,
    &quot;description&quot;: &quot;기능 개발&quot;
  },
  {
    &quot;name&quot;: &quot;🌏 Deploy&quot;,
    &quot;color&quot;: &quot;C2E0C6&quot;,
    &quot;description&quot;: &quot;배포 관련&quot;
  },
  {
    &quot;name&quot;: &quot;🎨 Html&amp;css&quot;,
    &quot;color&quot;: &quot;FEF2C0&quot;,
    &quot;description&quot;: &quot;마크업 &amp; 스타일링&quot;
  },
  {
    &quot;name&quot;: &quot;🐞 BugFix&quot;,
    &quot;color&quot;: &quot;d73a4a&quot;,
    &quot;description&quot;: &quot;Something isn&#39;t working&quot;
  },
  {
    &quot;name&quot;: &quot;💻 CrossBrowsing&quot;,
    &quot;color&quot;: &quot;C5DEF5&quot;,
    &quot;description&quot;: &quot;브라우저 호환성&quot;
  },
  {
    &quot;name&quot;: &quot;📃 Docs&quot;,
    &quot;color&quot;: &quot;1D76DB&quot;,
    &quot;description&quot;: &quot;문서 작성 및 수정 (README.md 등)&quot;
  },
  {
    &quot;name&quot;: &quot;📬 API&quot;,
    &quot;color&quot;: &quot;D4C5F9&quot;,
    &quot;description&quot;: &quot;서버 API 통신&quot;
  },
  {
    &quot;name&quot;: &quot;🔨 Refactor&quot;,
    &quot;color&quot;: &quot;f29a4e&quot;,
    &quot;description&quot;: &quot;코드 리팩토링&quot;
  },
  {
    &quot;name&quot;: &quot;🙋‍♂️ Question&quot;,
    &quot;color&quot;: &quot;9ED447&quot;,
    &quot;description&quot;: &quot;Further information is requested&quot;
  },
  {
    &quot;name&quot;: &quot;🥰 Accessibility&quot;,
    &quot;color&quot;: &quot;facfcf&quot;,
    &quot;description&quot;: &quot;웹접근성 관련&quot;
  },
  {
    &quot;name&quot;: &quot;✅ Test&quot;,
    &quot;color&quot;: &quot;ccffc4&quot;,
    &quot;description&quot;: &quot;test 관련(storybook, jest...)&quot;
  }
]</code></pre><h2 id="2-access-token-발급하기">2. Access-token 발급하기</h2>
<p><a href="https://github.com/">github</a> 사이트에 로그인을 한 후, 자신의 계정에서 Settings-&gt;Developer Settings에 들어간다.
Personal access tokens에 들어가 토큰을 발급받는다. 토큰값은 <code>ghp</code>로 시작하고 나중에 따로 확인하기 어려울 수 있으므로, 다른 곳에 복사해두길 바란다.</p>
<h2 id="3-github-label-sync-설치">3. github-label-sync 설치</h2>
<p>터미널에 명령어를 입력해 <a href="https://github.com/Financial-Times/github-label-sync">github-label-sync</a> 라이브러리를 설치한다.
나는 mac 권한 설정 때문에, 앞에 <code>sudo</code>을 추가로 입력했다.</p>
<pre><code>npm install -g github-label-sync</code></pre><h2 id="4-label을-레포지토리에-적용">4. label을 레포지토리에 적용</h2>
<p>아래는 github-label-sync의 명령어 가이드이다.</p>
<pre><code>Usage: github-label-sync [options] &lt;repository&gt;

Options:

  -h, --help                  output usage information
  -V, --version               output the version number
  -a, --access-token &lt;token&gt;  a GitHub access token (also settable with a GITHUB_ACCESS_TOKEN environment variable)
  -l, --labels &lt;path&gt;         the path or URL to look for the label configuration in. Default: labels.json
  -d, --dry-run               calculate the required label changes but do not apply them
  -A, --allow-added-labels    allow additional labels in the repo, and don&#39;t delete them</code></pre><p>보통은 아래와 같이 입력한다. 하지만 나는 Organization Repository에 적용해야 했기에 사용자 계정 이름 대신 Organization을 넣었다.</p>
<pre><code>github-label-sync --access-token token --labels ./labels.json 사용자 계정 이름/저장소 이름</code></pre><h1 id="github-issues-template-만들기">Github issues template 만들기</h1>
<p>Issues template을 만들어두면 이슈를 생성할 때, 시간을 절약할 수 있고 형식이 갖춰질 수 있다.</p>
<h2 id="1-템플릿-생성하기">1. 템플릿 생성하기</h2>
<p>해당 레포지토리 Settings에 들어간다.
General탭에서 내리다보면 <code>Set up templates</code>라는 초록색 버튼이 있다.
<code>Bug report</code>, <code>Feature request</code>, <code>Custom template</code> 세 가지 유형이 존재하는데, 나는 <code>Custom template</code>를 선택했다.</p>
<h2 id="2-자유롭게-템플릿-편집하기">2. 자유롭게 템플릿 편집하기</h2>
<p>해당 템플릿의 연필 모양 아이콘을 클릭한다.
원하는 이슈 제목과 템플릿 설명, 템플릿 내용을 입력한다.
나는 아래와 같이 입력했다.</p>
<pre><code>## Description
{ 업무에 대한 요약 및 설명 }

&lt;br/&gt;

## CheckList

{ 작업 체크리스트 }
- [ ] 리스트 1
- [ ] 리스트 2

&lt;br/&gt;

## ETC
{ 기타 내용, 의존성있는 작업 }</code></pre><p>짜잔 완성됐다.
앞으로 이슈를 작성할 때 해당 템플릿을 사용할 수 있고, 안에 내용만 직접 작성해주면 된다.
<img src="https://velog.velcdn.com/images/seobi-97/post/d3fa4f31-b5cd-4f0d-a975-f026bc6994d8/image.png" alt=""></p>
<h1 id="출처">출처</h1>
<blockquote>
<p><a href="https://www.thegeekdiary.com/github-label-sync-command-examples/">&quot;github-label-sync&quot; 명령 예</a>
<a href="https://velog.io/@rimo09/Github-github-label-%ED%95%9C%EB%B2%88%EC%97%90-%EC%A0%81%EC%9A%A9%ED%95%98%EA%B8%B0">[Github] github label 한번에 적용하기</a>
<a href="https://velog.io/@sasha1107/%EA%B9%83%ED%97%88%EB%B8%8C-%EC%9D%B4%EC%8A%88-%ED%85%9C%ED%94%8C%EB%A6%BF-%EC%83%9D%EC%84%B1%ED%95%98%EA%B8%B0">깃허브 이슈 템플릿 생성하기</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[Organization Repository를 vercel+git actions로 무료 배포하기]]></title>
            <link>https://velog.io/@seobi-97/Organization-Repository%EB%A5%BC-vercelgit-actions%EB%A1%9C-%EB%AC%B4%EB%A3%8C-%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@seobi-97/Organization-Repository%EB%A5%BC-vercelgit-actions%EB%A1%9C-%EB%AC%B4%EB%A3%8C-%EB%B0%B0%ED%8F%AC%ED%95%98%EA%B8%B0</guid>
            <pubDate>Thu, 23 Nov 2023 07:56:55 GMT</pubDate>
            <description><![CDATA[<p>팀 프로젝트를 진행하는데 프론트쪽을 미리 배포를 하고 진행을 하려고 했다.
여러가지 방법으로 배포가 가능하지만 비교적으로 편리한 <a href="https://vercel.com/">Vercel</a>을 이용하기로 했다.</p>
<h2 id="github-repositories-불러오기">Github Repositories 불러오기</h2>
<p>Vercel 페이지를 들어가서 로그인을 하면 이 페이지가 보일 것이다. 다른 페이지가 보인다면 Add new...을 클릭 후 드롭다운 메뉴 중에 project 클릭하면 이 화면이 나타날 것이다.</p>
<p><img src="https://velog.velcdn.com/images/seobi-97/post/aee867ad-d6cd-4e3d-a5c0-9702a954895e/image.png" alt="">
개인 프로젝트, 레포지토리를 불러오려면 그냥 검색을 해서 import 버튼을 클릭하면 된다. 하지만 나는 Organization에 있는 레포지토리를 불러오려했기에 Add Github Account를 클릭하여 불러왔다.
Organization owner면 상관없는데, 일반 Member일 경우 owner에게 메일이 가서 따로 승인을 받아야했다.
<img src="https://velog.velcdn.com/images/seobi-97/post/e653ca19-9235-4344-94d1-bbcc60690a61/image.png" alt=""></p>
<p>이후 팀 이름, 프로젝트 이름, 도메인 등을 설정해주고 deploy를 눌러준다. 다른 블로그를 봤을때 바로 배포가 됐는데 나는 아무 반응이 없어서 안된줄 알았다. 그래서 계속 시도를 하니 이미 존재하는 프로젝트라고 나와서 개인 페이지로 돌아가봤는데 프로젝트가 만들어져있었다. 아직 배포된 상태는 아니였고, master branch에 push를 하니까 배포가 시작되었다.</p>
<p>정상적으로 배포가 되었지만 문제가 하나 있었다.
Pro요금제가 적용된다는 점..!
아쉽게도 평가판에서만 가능하고, 이후에는 요금을 따로 지불해야했다.</p>
<p>그래서 다른 방법이 없을까? 고민을 하다가 바로 좋은 <a href="https://velog.io/@rmaomina/organization-vercel-hobby-deploy">블로그</a>를 발견했다.</p>
<p>블로그의 내용을 간단하게 설명하자면, 내 개인 레포지토리를 만들고 vercel과 연동을 한다. 그리고 배포하고 싶은 Organization 레포지토리에 Git Actions를 적용하여 내 개인 레포지토리로 push하여 그 내용이 배포가 되는것이다.</p>
<h2 id="배포-작업을-위해-해야할-일">배포 작업을 위해 해야할 일</h2>
<ol>
<li><p>개인 레포지토리를 생성해준다.(public)</p>
</li>
<li><p>vercel에 개인 레포지토리를 연동한다.</p>
</li>
<li><p>Organization 레포지토리 루트 경로로 <code>build.sh</code> 파일을 생성해준다.
<code>[team-repo-name]</code>을 모두 지우고 Organization 레포지토리 이름을 입력해준다. </p>
<p> #!/bin/sh
 cd ../
 mkdir output
 cp -R ./[team-repo-name]/* ./output
 cp -R ./output ./[team-repo-name]/</p>
</li>
<li><p>Organization 레포지토리에 secret 변수를 등록해준다.
<code>EMAIL</code>에는 Github 계정 이메일을, <code>AUTO_ACTIONS</code>에는 개인 계정에서 발급받은 token값을 넣어준다. token값을 만들때는 repo 권한을 선택해주고, 다시 확인하기 어려울 수 있으므로 다른 곳에 복사해두길 바란다. token값은 <code>ghp_</code>가 들어가는 값이다.
<img src="https://velog.velcdn.com/images/seobi-97/post/63dfd8e6-86de-4729-a5d5-4d73f7e42156/image.png" alt=""></p>
</li>
<li><p>GitHub Actions 활성화 &amp; 워크플로우 생성</p>
<pre><code> name: git push into another repo to deploy to vercel

 on:
       push:
         branches: [master]

 jobs:
       build:
         runs-on: ubuntu-latest
         container: pandoc/latex
         steps:
               - uses: actions/checkout@v2
               - name: Install mustache (to update the date)
             run: apk add ruby &amp;&amp; gem install mustache
               - name: creates output
             run: sh ./build.sh
               - name: Pushes to another repository
             id: push_directory
             uses: cpina/github-action-push-to-another-repository@main
             env:
                   API_TOKEN_GITHUB: ${{ secrets.AUTO_ACTIONS }}
             with:
                   source-directory: &quot;output&quot;
                   destination-github-username: &quot;your-github-name&quot;
                   destination-repository-name: &quot;your-project-name&quot;
                   user-email: ${{ secrets.EMAIL }}
                   commit-message: ${{ github.event.commits[0].message }}
                   target-branch: main
               - name: Test get variable exported by push-to-another-repository
             run: echo $DESTINATION_CLONED_DIRECTORY</code></pre></li>
</ol>
<p>Organization 레포지토리에서 push하는 branch가 master이기 때문에 바꿔줬다. 하지만 아래 target-branch는 개인 레포지토리의 main branch이기 때문에 main으로 설정했다.</p>
<p>처음 생성할땐 actions/checkout@v2으로 작성했는데 현재 2024년 11월 기준 <a href="https://github.com/actions/checkout">최신 버전</a>은 v4이다.</p>
<p>아까 secret 변수로 등록했던 token값과 Email을 불러와주고, <code>your-github-name</code> <code>your-project-name</code>에 해당 값을 넣어준다.</p>
<p>나는 이 파일을 Github 사이트에서 Actions -&gt; New workflow를 통해서 생성했다. 생성하고 Actions에 들어가면 작동하고 있는지 확인이 가능하다.</p>
<p>성공적으로 작동이 된다면 개인 레포지토리로 파일들이 잘 옮겨졌는지, vercel에 제대로 배포가 되었는지 확인해보자!</p>
<p>우선 나는 배포를 잘 확인했지만, 프로젝트를 진행하면서도 계속 확인해야겠다.
끝!</p>
<blockquote>
<h3 id="출처">출처</h3>
<p><a href="https://velog.io/@rmaomina/organization-vercel-hobby-deploy">GitHub Organization 프로젝트를 vercel 무료로 연동하기 (+git actions)</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[Backbone.js란 무엇일까?]]></title>
            <link>https://velog.io/@seobi-97/Backbone.js</link>
            <guid>https://velog.io/@seobi-97/Backbone.js</guid>
            <pubDate>Tue, 24 Oct 2023 00:58:35 GMT</pubDate>
            <description><![CDATA[<h2 id="backbonejs란">Backbone.js란?</h2>
<blockquote>
<p>Backbone is a library, not a framework, and plays well with others. - backbonejs.org</p>
</blockquote>
<p>Backbone은 프론트엔드 자바스크립트 코드의 틀을 만드는데 도움을 주는 경량 자바스크립트 라이브러리이다.
프레임워크와 라이브러리의 차이는 제어 흐름을 누가 가지냐의 차이이다.
프레임워크는 프레임워크가, 라이브러리는 사용자가 가지고 있다.</p>
<p>Backbone은 틀을 만드는데 도움이 되는 메서드를 제공해주지만 틀을 만드는건 순전히 개발자의 몫이다.
틀을 제시하기 때문에 프레임워크라고 하는 사람도 있다.</p>
<h2 id="backbone의-특징">Backbone의 특징?</h2>
<p>Backbone의 특징은 아래와 같다.</p>
<ul>
<li>MVC 패턴을 따르게 도와준다. MVC 패턴과 유사하지만, 컨트롤러 기능이 뷰에 포함된다.
데이터를 모델로 표현하여 생성, 검증, 삭제 및 서버에 저장할 수 있다.</li>
<li>라이브러리라서 확장성이 좋다. 꼭 따라야할 규칙이 minimal하면서 RESTful API를 잘 지원하다보니 다른 프레임워크에도 잘 녹아들 수 있다. 따라서 임베디드 위젯부터 대형 웹 애플리케이션까지 사용 가능하다.</li>
<li>경량이기 때문에 네트워크가 느린 경우에도 충분히 사용할 수 있으며 학습에 시간이 적게 걸린다.</li>
</ul>
<h2 id="backbone을-사용해야-할-경우">Backbone을 사용해야 할 경우</h2>
<ol>
<li><p>서버에 대한 HTTP 요청을 줄여야하는 경우
 Backbone 같은 MVC 프레임워크는 대게 모든 스크립트, 스타일시트가 포함된 묶음을 한 번 다운로드하고 필요사항을 마크업하고 나서, 백그라운드에 추가적으로 필요한 작업을 수행하는식으로 동작한다. 그래서 SPA를 만드는데 유용하다.</p>
</li>
<li><p>복잡한 UI 설계를 단순화해야할 경우
 Backbone은 하나의 view를 이용해서 요청된 모델을 공유하는 여러 개의 sub-view를 관리할 수 있다.</p>
</li>
<li><p>스파게티 코드를 피하고 싶은 경우
 Backbone은 개발자가 비즈니스 모델과 인터페이스를 분리하게끔 도와준다. Model과 View간에 event-driven communication을 할 수 있도록 설계되어있기 때문이다.</p>
</li>
</ol>
<h2 id="모델과-뷰">모델과 뷰</h2>
<p><img src="https://velog.velcdn.com/images/seobi-97/post/56d857b6-3d69-476c-a6e9-bc91061df92b/image.png" alt=""></p>
<p>모델은 데이터 속성의 내부 테이블을 관리하고 데이터가 수정되면 변경 이벤트를 트리거한다. 모델을 일반적으로 지원 데이터베이스가 있는 REST API인 지속성 레이어를 사용하여 데이터 동기화를 처리한다.</p>
<p>뷰는 사용자 인터페이스의 원자 덩어리이다. 특정 모델 또는 여러 모델의 데이터를 렌더링하는 경우가 많지만, 뷰는 독립된 데이터 없는 UI 덩어리일 수도 있다. 모델은 일반적으로 뷰를 인식하지 않아야한다. 대신 뷰는 모델의 변경 이벤트를 수신하고 적절하게 다시 반응하거나 다시 렌더링한다.</p>
<h2 id="컬렉션">컬렉션</h2>
<p><img src="https://velog.velcdn.com/images/seobi-97/post/20d9d7b7-4754-48f4-8db8-a052142b4553/image.png" alt="">
컬렉션은 관련 모델 그룹을 처리하고, 새 모델을 서버에 로드 및 저장하고, 모델 목록에 대한 집계 또는 계산을 수행하기 위한 도우미 기능을 제공하는데 도움이 된다. 자체 이벤트외에도 컬렉션은 컬렉션 내의 모델에 발생하는 모든 이벤트를 프록시하여 컬렉션의 모든 모델에 발생할 수 있는 모든 변경 사항을 한 곳에서 수신할 수 있다.</p>
<blockquote>
<p>출처
<a href="https://backbonejs.org/#Getting-started">https://backbonejs.org/#Getting-started</a>
<a href="https://humblego.tistory.com/14">https://humblego.tistory.com/14</a></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[메인 프로젝트 회고]]></title>
            <link>https://velog.io/@seobi-97/%EB%A9%94%EC%9D%B8-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@seobi-97/%EB%A9%94%EC%9D%B8-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Wed, 02 Aug 2023 14:46:44 GMT</pubDate>
            <description><![CDATA[<p>조금 늦은 회고 시작~~
7월 27일 데모데이가 끝나고 일주일 간 푹 쉬었다.
바로 회고를 작성해야했는데 미루다가 이제 적어본다.
코드와 기술에 대해서는 따로 다루고 이번 회고에서는 프로젝트를 하면서 도움이 되었던 활동에 대해서 이야기를 해보겠다.
(주의!) 사진이 아주 많을 예정!
<img src="https://velog.velcdn.com/images/seobi-97/post/cc570b72-8e60-401e-9a7b-d1768230427b/image.png" alt="">
데모데이 부스에 모인 우리 팀원들!
팀장이라 처음이라 어리숙한 부분이 많았는데 다들 한달 간 정말 고생 많았다.</p>
<h2 id="매일-아침-스크럼">매일 아침 스크럼</h2>
<p><img src="https://velog.velcdn.com/images/seobi-97/post/9a5966b8-4808-41a6-aa4c-6f7e1d370cdf/image.png" alt="">
<img src="https://velog.velcdn.com/images/seobi-97/post/d787481a-bdba-4884-b052-fa25fef4c75d/image.png" alt=""></p>
<p>아무도 빠짐없이 정말 잘 지켜졌던 것 중에 하나이다. 프로젝트에 대해 소통하는 것에 많은 도움이 되었다. 간단하게 작업 상황에 대해 적고 한명씩 돌아가면서 발표를 하고, 그에 대해 궁금한 점들을 자유롭게 질문하고 답하였다. 자신의 작업을 신경쓰느라 다른 사람들의 진행 상황에 대해 무지하거나 놓칠 수 있는 부분이 있는데, 매일 같이 진행하다보니 그런 부분은 없었다.</p>
<h2 id="다양한-문서-작업">다양한 문서 작업</h2>
<p><img src="https://velog.velcdn.com/images/seobi-97/post/ce491536-d02f-43f5-9390-7a6deea6bce9/image.png" alt=""></p>
<p>혼자 프로젝트를 진행할때는 한번도 작성해보지 않았다. 이런 걸 작성해야 한다고도 못 느꼈다. 하지만 이번에 작성을 해보면서 문서 작업도 상당히 중요하다고 느꼈다. 개발자인 우리를 위해서, 사용자들을 위해서 중요하다 생각한다. 초기에 기획했던 것과 얼만큼 적합한가? 개발 중 API명세서를 참고해서 개발을 하기 등 많은 도움이 되었다. 문서 작성에도 거의 일주일이란 시간을 들여 열심히 작업했었다.</p>
<h2 id="멘토링">멘토링</h2>
<p><img src="https://velog.velcdn.com/images/seobi-97/post/a3138cbc-4dc8-4cce-b976-49099e0288e8/image.png" alt="">
처음 멘토님과 개발 기술 스택에 관해 얘기를 나눴을때다. 이때는 사실 좀 어지러웠다. 마치 기술면접 현장에 있는 듯한 느낌이었다. 하지만 이 스택을 왜 사용해야 하는지에 대해 더 명확하게 판단할 수 있는 시간이었다. 남들이 많이 쓰니까, 요즘 뜨는 기술이니까 그냥 선택 부분도 많았기 때문이다. 그래서 필요한 부분만 가져다 썼다.
<img src="https://velog.velcdn.com/images/seobi-97/post/6599229f-28bc-4890-ab92-24b6ea181462/image.png" alt="">
한달 중 4번의 멘토링이 이루어졌는데 프로젝트에 관해서, 개발자로 성장하는거에 관해서 모두 도움이 많이 되었다. 좋은 개발자로 성장하기 바라는 멘토님이 좋은 말씀을 많이 해주셨다. hoc패턴 공부와 AccessToken을 쿠키에 저장해 관리하는 법은 나중에 꼭 공부해 적용시켜야겠다.
클린 코드라는 책은 꼭 읽어볼거다!</p>
<h2 id="마지막으로">마지막으로</h2>
<p>한달 간 9시부터 18시까지 회의 및 작업한다는 일은 정말 쉽지 않았다. 스트레스도 많이 받고, 살도 많이 찌는 기간이었다. 하지만 끝나고 보니 너무 뿌듯하고 많은 것을 배웠다고 생각한다. 또한 AccessToken 쿠키로 저장 및 관리, 다크 모드, 비디오 추가 등 다양한 기능을 더 추가하고 싶은 욕심이 있다. 우선 아래 배포 링크를 올려놨으니 음악을 감상하고 싶은 분들은 한번 들어가보셔도 좋을 것 같다!
<img src="https://velog.velcdn.com/images/seobi-97/post/8bdad544-1b7c-40a3-af7d-05effda6c255/image.png" alt=""></p>
<p><a href="https://on.petpil.site">https://on.petpil.site</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Pre-Project 회고]]></title>
            <link>https://velog.io/@seobi-97/Pre-Project-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@seobi-97/Pre-Project-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Tue, 27 Jun 2023 05:28:14 GMT</pubDate>
            <description><![CDATA[<p>드디어 Pre-Project가 끝났다.
프로젝트 하나가 끝났다는 기쁨과 Main-Project가 바로 앞에 있다는 절망감이 공존한다.
프로젝트를 하면서 내가 아직 많이 부족하구나 느꼈다.
그동안 프로젝트 경험도 해봤고, 전공자이기 때문에 자신감이 있었는데 생각만큼 잘 해내지 못한거 같다.</p>
<p><img src="https://velog.velcdn.com/images/seobi-97/post/9f9c1788-924b-4694-8db1-34ab9add28fe/image.PNG" alt=""></p>
<h2 id="git-이슈">Git 이슈</h2>
<p>제일 아찔한 순간이 아닐까싶다.
한번은 Pull Request를 Main으로 날렸는데 모르고 merge를 해버렸다.
그래서 원래 팀 계획은 모두 작업을 완료하고 dev브랜치에서 main브랜치로 옮기고 배포하기였다. 하지만 이 일을 계기로 중간중간 main브랜치로 올리는 형식으로 바꼈다. 파일들이 날라간 건 아니여서 다행이다.</p>
<p>한번은 dev에서 새로운 브랜치를 생성하고 작업한 다음 commit 메시지만 작성했다. 그리고 팀 레포 dev내용을 개인 레포 dev에 pull을 하고 작업하던 브랜치에서 merge했다. 마지막으로 다시 작업하고 바뀐 내용들을 commit하고 push를 했는데 처음 작성한 commit 메시지가 다 재커밋 되는 상황이 벌어졌다. 거의 100개...ㄷㄷ 당황하고 되돌려보려했지만 이미 pr후 merge까지 완료라 바꿀 수는 없었다. 이번에도 마찬가지로 파일들이 날라간 건 아니여서 다행이었다.</p>
<h2 id="테스트-이슈">테스트 이슈</h2>
<p>처음부터 더미 데이터를 잘 구성하고 남겨놨어야 되는데, 일찍 제거를 해버려서 문제였다. 내가 맡은 답변부분이 로그인, 질문 생성부터 타고 넘어오는 부분이여서 앞부분이 완벽하게 작성된 상태여야 작업을 하기 편한 상황이다. 하지만 우리는 동시에 작업을 진행하고 있었고, 이런 부분을 미리 대비를 했어야했다.</p>
<p>또한 내 노트북에는 인텔리제이가 있고, 서버를 한번 실행시켰을때 잘 작동되길래 이걸 계속 pull하면서 이용해야지라는 생각이 있었다. 하지만 백엔드분들도 계속 작업중이고 그에 맞는 작업 환경 변화도 있을것이다. 그래서 편하게 localhost로 서버를 실행시키려는 생각도 실패했다. 몸이 편하려고하니 벌 받았다. 그래서 계속 pull할때 마다 오류가 자주 떴다. 이렇게 실행이 안될때마다 백엔드 분에게 요청해서 해결하길 반복했다. 이 시간이 생각보다 너무 많이 쓰였다.</p>
<h2 id="코로나-이슈">코로나 이슈</h2>
<p>프로젝트 중간에 갑자기 목이 아프고 감기기운이 있길래
전날 저녁에 괜히 선풍기를 틀고 잤나했다. 하지만 3일동안 낫지 않아서 자가키트를 검사했더니 양성이 나왔다.
그동안 눈도 가렵고, 긁으면 다래끼처럼 부어서 약을 잘 못 처방 받았나했는데 눈병을 동반한 신종 코로나였다. 이름도 아르크투루스이다. 그리스 고대학자 이름 같다.
이틀은 열나고 좀 아팠고, 일찍 회복해서 다행이었다.</p>
<h2 id="마지막-느낀점">마지막 느낀점</h2>
<p>그래도 다른분들과 작업을 하면서 많은 것을 느꼈다. 소통하는 법, 작업량 관리 및 공유 등등..
다음 Main-Project에서는 작업전에 좀 더 계획을 세부적으로 잘 짜보고 실행에 옮겨야겠다.
<strong>아자아자 화이팅!</strong>
<img src="https://velog.velcdn.com/images/seobi-97/post/d47d8185-40ef-4422-9440-da6e8611729c/image.PNG" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CORS & Proxy]]></title>
            <link>https://velog.io/@seobi-97/CORS-Proxy</link>
            <guid>https://velog.io/@seobi-97/CORS-Proxy</guid>
            <pubDate>Wed, 07 Jun 2023 06:51:04 GMT</pubDate>
            <description><![CDATA[<h2 id="cors">Cors</h2>
<h3 id="cors란">Cors란?</h3>
<blockquote>
<p><strong>Cors란?</strong></p>
</blockquote>
<p>교차 출처 리소스 공유(Cross-Origin Resource Sharing, CORS)는 추가 HTTP 헤더를 사용하여, 한 출처에서 실행 중인 웹 애플리케이션이 다른 출처의 선택한 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제입니다.</p>
<h3 id="출처">출처</h3>
<blockquote>
<p>웹 콘텐츠의 출처(origin)는 접근할 때 사용하는 URL의 스킴(프로토콜), 호스트(도메인), 포트로 정의됩니다. 두 객체의 스킴, 호스트, 포트가 모두 일치하는 경우 같은 출처를 가졌다고 말합니다.
일부 작업은 동일 출처 콘텐츠로 제한되나, CORS를 통해 제한을 해제할 수 있습니다.</p>
</blockquote>
<h2 id="proxy">Proxy</h2>
<h3 id="proxy란">Proxy란?</h3>
<blockquote>
<p>프록시(Proxy)는 &quot;대리&quot;의 의미로, 인터넷과 관련해서 쓰이는 경우, 특히 내부 네트워크에서 인터넷 접속을 할 때에, 빠른 액세스나 안전한 통신등을 확보하기 위한 중계서버를 &quot;프록시 서버&quot;라고 일컫는다. 클라이언트와 Web서버의 중간에 위치하고 있어, 대신 통신을 받아 주는 것이 프록시 서버이다. </p>
</blockquote>
<h3 id="proxy-적용-전-흐름">Proxy 적용 전 흐름</h3>
<p><img src="https://velog.velcdn.com/images/seobi-97/post/4331cb66-6194-421c-ae5f-7219be42f5dc/image.png" alt="">
위의 그림은 proxy를 적용해 브라우저를 속이기 전 흐름입니다. 프론트엔드, 즉 여러분이 개발한 React 앱에서 브라우저 쪽으로 요청을 보냅니다. 그러면 브라우저는 백엔드, 즉 서버 쪽으로 리소스를 요청하게 됩니다. 이때 접근 권한이 있는지, 즉 출처가 같은지 확인하는데 이때 백엔드 서버는 정상적으로 200 OK 응답을 브라우저에게 보냅니다. 마지막으로 브라우저는 받은 리소스 및 응답과 함께 출처가 같은지 아닌지 확인하게 되는데, 이때 출처가 다르다면 응답을 파기(CORS Error) 하고, 출처가 같다면 응답을 파기하지 않고 다시 프론트엔드 쪽으로 응답을 보내주는 것입니다.</p>
<h3 id="proxy-적용-후-흐름">Proxy 적용 후 흐름</h3>
<p><img src="https://velog.velcdn.com/images/seobi-97/post/39fb097d-2251-4c34-89a8-6a0b911e1444/image.png" alt="">
위의 그림은 proxy를 적용해 브라우저를 속인 후 흐름입니다. React 앱에서 브라우저를 통해 API를 요청할 때, proxy를 통해 백엔드 서버로 요청을 우회하여 보내게 됩니다. 그러면 백엔드 서버는 응답을 React 앱으로 보내고, React 앱은 받은 응답을 백엔드 서버 대신 브라우저에게 전달합니다. 이렇게 되면 출처가 같아지기 때문에 브라우저는 이 사실을 눈치채지 못하고 허용하게 됩니다.</p>
<h3 id="proxy를-설정해-http-통신하기">Proxy를 설정해 HTTP 통신하기</h3>
<h4 id="webpack-dev-server-proxy">webpack dev server proxy</h4>
<p>webpack dev server의 proxy를 사용하게 되면, 브라우저 API를 요청할 때 백엔드 서버에 직접적으로 요청을 하지 않고, 현재 개발서버의 주소로 우회 요청을 하게 됩니다. 그러면 웹팩 개발 서버에서 해당 요청을 받아 그대로 백엔드 서버로 전달하고, 백엔드 서버에서 응답한 내용을 다시 브라우저 쪽으로 반환합니다.</p>
<pre><code>//package.json
//보통 맨 밑에 작성한다.
...
&quot;browserslist&quot;: {
    &quot;production&quot;: [
      &quot;&gt;0.2%&quot;,
      &quot;not dead&quot;,
      &quot;not op_mini all&quot;
    ],
    &quot;development&quot;: [
      &quot;last 1 chrome version&quot;,
      &quot;last 1 firefox version&quot;,
      &quot;last 1 safari version&quot;
    ]
  },
    &quot;proxy&quot; : &quot;우회할 API 주소&quot;
}</code></pre><p>그리고 기존의 fetch, 혹은 axios를 통해 요청하던 부분에서 도메인 부분을 제거합니다.</p>
<pre><code>export async function getAllfetch() {

    const response = await fetch(&#39;우회할 api주소/params&#39;);
    .then(() =&gt; {
            ...
        })
}

export async function getAllfetch() {

    const response = await fetch(&#39;/params&#39;);
    .then(() =&gt; {
            ...
        })
}</code></pre><h4 id="react-proxy-사용법">React Proxy 사용법</h4>
<p>우선 http-proxy-middleware 라이브러리 설치한다.</p>
<p><code>npm install http-proxy-middleware --save</code></p>
<p>그 이후 src폴더 안에 setupProxy.js 파일을 생성하고, 설치한 라이브러리를 불러온 후, 아래와 같이 작성한다.</p>
<pre><code>const { createProxyMiddleware } = require(&#39;http-proxy-middleware&#39;);

module.exports = function(app) {
  app.use(
    &#39;/api&#39;, //proxy가 필요한 path prameter를 입력합니다.
    createProxyMiddleware({
      target: &#39;http://localhost:5000&#39;, //타겟이 되는 api url를 입력합니다.
      changeOrigin: true, //대상 서버 구성에 따라 호스트 헤더가 변경되도록 설정하는 부분입니다.
    })
  );
};</code></pre><p>또한 위와 동일하게 기존 fetch, axios를 통해 요청하던 부분에서 도메인 부분을 제거한다.</p>
<pre><code>export async function getAllfetch() {

    const response = await fetch(&#39;우회할 api주소/params&#39;);
    .then(() =&gt; {
            ...
        })
}

export async function getAllfetch() {

    const response = await fetch(&#39;/params&#39;);
    .then(() =&gt; {
            ...
        })
}</code></pre><h4 id="오류">오류</h4>
<p>작업을 하다보니
<code>Uncaught (in promise) SyntaxError: Unexpected token &#39;&lt;&#39;, &quot;&lt;!DOCTYPE &quot;... is not valid JSON</code>
이런 오류가 발생하였다.</p>
<p><a href="https://stackoverflow.com/questions/37269808/react-js-uncaught-in-promise-syntaxerror-unexpected-token-in-json-at-posit">스택오버플로우</a>, <a href="https://xionwcfm.tistory.com/340">블로그</a>에서 찾아보니 노드 버전이나 여러 요인으로 인해 프록시 서버가 정상적으로 동작하지 않는다는 것이였다.</p>
<p>직접 노드 버전을 다운그레이드 하거나 <code>.env</code>파일을 생성한 후
<code>DANGEROUSLY_DISABLE_HOST_CHECK=true</code>을 작성해주면 해결이 되었다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[TypeScript 문법(열거형, 타입 별칭, 타입 추론, 클래스)]]></title>
            <link>https://velog.io/@seobi-97/TypeScript-%EB%AC%B8%EB%B2%95%EC%97%B4%EA%B1%B0%ED%98%95-%ED%83%80%EC%9E%85-%EB%B3%84%EC%B9%AD-%ED%83%80%EC%9E%85-%EC%B6%94%EB%A1%A0-%ED%81%B4%EB%9E%98%EC%8A%A4</link>
            <guid>https://velog.io/@seobi-97/TypeScript-%EB%AC%B8%EB%B2%95%EC%97%B4%EA%B1%B0%ED%98%95-%ED%83%80%EC%9E%85-%EB%B3%84%EC%B9%AD-%ED%83%80%EC%9E%85-%EC%B6%94%EB%A1%A0-%ED%81%B4%EB%9E%98%EC%8A%A4</guid>
            <pubDate>Wed, 31 May 2023 07:50:11 GMT</pubDate>
            <description><![CDATA[<h2 id="열거형">열거형</h2>
<p>TypeScript에서 열거형은 다음과 같은 형태로 정의한다.</p>
<pre><code>enum Color {
  Red,
  Green,
  Blue,
}</code></pre><p>Color라는 열거형을 정의하고 있다. 열거형의 값은 <code>Red</code>,<code>Green</code>,<code>Blue</code> 세 개입니다.</p>
<h3 id="숫자형-열거형enum">숫자형 열거형(Enum)</h3>
<p>열거형은 숫자형과 문자열형, 혹은 이 둘의 조합으로 정의될 수 있다. 디폴트 값으로 숫자형을 사용하며, 각 값은 자동으로 0부터 시작하여 1씩 증가한다. 그러나 수동으로 값을 지정할 수도 있다.</p>
<pre><code>enum Color {
  Red = 1,
  Green = 2,
  Blue = 4,
}</code></pre><p>열거형의 값에 대해 산술 연산을 수행할 수도 있다.</p>
<pre><code>enum Color {
  Red = 1,
  Green = 2,
  Blue = 4,
}

let c: Color = Color.Green;
let greenValue: number = Color.Green;
let blueValue: number = Color.Blue;

console.log(c);          // 출력: 2
console.log(greenValue);  // 출력: 2
console.log(blueValue);   // 출력: 4</code></pre><p>열거형은 일반적으로 상수값을 대신하여 사용되므로, 타입스크립트에서는 열거형이 많이 사용됩니다. 열거형은 코드를 더욱 가독성 높게 만들어주고, 오타와 같은 실수를 방지해 줍니다.</p>
<h3 id="문자형-열거형enum">문자형 열거형(Enum)</h3>
<p>문자형 열거형은 앞에서 살펴본 숫자형 열거형과 개념적으로는 거의 비슷합니다. 문자형 열거형은 열거형의 값을 전부 다 특정 문자 또는 다른 열거형 값으로 초기화해야 합니다.</p>
<pre><code>enum Direction {
  Up = &quot;UP&quot;,
  Down = &quot;DOWN&quot;,
  Left = &quot;LEFT&quot;,
  Right = &quot;RIGHT&quot;,
}

let myDirection: Direction = Direction.Up;
console.log(myDirection); // 출력: &quot;UP&quot;</code></pre><p>문자형 열거형에는 숫자형 열거형과는 다르게 auto-incrementing이 없습니다. 대신 디버깅을 할 때 숫자형 열거형의 값은 가끔 불명확하게 나올 때가 있지만 문자형 열거형은 항상 명확한 값이 나와 읽기 편합니다.</p>
<p>예를 들어, HTTP 요청 방식을 나타내는 열거형을 정의할 수 있다.</p>
<pre><code>enum HttpMethod {
  Get = &quot;GET&quot;,
  Post = &quot;POST&quot;,
  Put = &quot;PUT&quot;,
  Delete = &quot;DELETE&quot;,
}

function makeRequest(url: string, method: HttpMethod) {
  // ...
}

makeRequest(&quot;/api/data&quot;, HttpMethod.Post);</code></pre><p>위 코드에서는 HTTP 요청 방식을 나타내는 <code>HttpMethod</code> 열거형을 정의하고 있습니다. <code>makeRequest</code> 함수는 URL과 HTTP 요청 방식을 인자로 받습니다. HTTP 요청 방식을 지정할 때는 <code>HttpMethod.Post</code>와 같이 열거형 값을 사용합니다.</p>
<p>이렇게 열거형을 사용하면 오타와 같은 실수를 방지할 수 있으며, 코드의 가독성과 안정성을 높일 수 있습니다.</p>
<h3 id="역-매핑reverse-mappings">역 매핑(Reverse mappings)</h3>
<p>역 매핑은 숫자형 열거형에만 존재하는 특징입니다. 열거형의 키(<code>key</code>)로 값(<code>value</code>)을 얻을 수 있고 값(<code>value</code>)으로 키(<code>key</code>)를 얻을 수도 있습니다.</p>
<pre><code>enum Enum {
    A
}
let a = Enum.A;
let nameOfA = Enum[a]; // &quot;A&quot;</code></pre><p>위와 같이 열거형의 키로 값을 얻을 수 있지만, 값으로도 열거형의 키를 얻을 수 있습니다. 이는 숫자형 열거형에만 존재하며, 문자형 열거형에서는 존재하지 않는 특징입니다.</p>
<h2 id="타입-별칭type-aliases">타입 별칭(Type Aliases)</h2>
<blockquote>
<p><strong>타입 별칭(Type Aliases)이란?</strong></p>
</blockquote>
<p>타입의 새로운 이름을 만드는 것이다.
이는 새로운 이름으로 기존의 타입을 참조하는 것을 의미한다.
타입 별칭을 이용하여 타입의 새로운 이름을 만들 때 키워드 <code>type</code>을 사용하여 작성한다.</p>
<p>예시를 통해 살펴보자.</p>
<pre><code>type MyString = string;

let str1: string = &#39;hello!&#39;;

// string 타입처럼 사용할 수 있습니다.
let str2: MyString = &#39;hello world!&#39;;</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[TypeScript 프로젝트 환경 구성하기]]></title>
            <link>https://velog.io/@seobi-97/TypeScript-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%ED%99%98%EA%B2%BD-%EA%B5%AC%EC%84%B1%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@seobi-97/TypeScript-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%ED%99%98%EA%B2%BD-%EA%B5%AC%EC%84%B1%ED%95%98%EA%B8%B0</guid>
            <pubDate>Tue, 30 May 2023 07:53:16 GMT</pubDate>
            <description><![CDATA[<h2 id="typescript-프로젝트-환경-구성하기">TypeScript 프로젝트 환경 구성하기</h2>
<ol>
<li>TypeScript를 적용하기 전, 먼저 프로젝트 폴더 하나를 생성하자.<pre><code>mkdir (폴더명)
cd (폴더명)</code></pre></li>
</ol>
<p>터미널에서 생성해줘도 되고, 직접 폴더를 만들어도 된다.</p>
<ol start="2">
<li><p>프로젝트 폴더를 생성했으면 프로젝트 폴더 안으로 이동하여, <code>npm init -y</code>명령어를 실행해 새로운 프로젝트를 초기화한다.</p>
</li>
<li><p>이제 프로젝트 내부에서 npm을 사용할 준비가 되었으므로, 이제 TypeScript를 설치한다.</p>
<pre><code>npm install typescript --save-dev</code></pre></li>
<li><p>프로젝트 루트 디렉토리에 <code>tsconfig.json</code>파일을 생성한다.
 그리고 아래 코드를 붙여준다.</p>
<pre><code>//tsconfig.json
//compilerOptions 내의 속성은 자유롭게 커스텀 할 수 있습니다.
{
&quot;compilerOptions&quot;: {
 &quot;target&quot;: &quot;es6&quot;,
 &quot;module&quot;: &quot;commonjs&quot;,
 &quot;sourceMap&quot;: true,
 &quot;outDir&quot;: &quot;./dist&quot;
},
&quot;include&quot;: [
 &quot;src/**/*&quot;
]
}
</code></pre></li>
<li><p>이제 <code>src</code>폴더 밑에 TypeScript언어로 된 파일을 작성할 수 있습니다.</p>
</li>
</ol>
<h3 id="typescript-eslint와-prettier-설정하기">TypeScript ESLint와 Prettier 설정하기</h3>
<p>TypeScript는 2020년까지만 TSLint를 지원하고, 이후부터는 typescript-eslint를 사용해야 합니다. 만일 TypeScript 프로젝트에서 ESLint나 Prettier를 사용하고 싶다면, 아래의 안내를 따릅니다.</p>
<ol>
<li>VSCode 에디터를 사용할 것이므로, 확장 프로그램인 ESLint를 설치합니다.
<img src="https://velog.velcdn.com/images/seobi-97/post/9c544a4f-f316-4c61-9ed2-dbb7e94f1e4b/image.png" alt=""></li>
<li>그리고 VSCode 에디터에 다음 설정을 적용합니다.
윈도우는 <code>ctrl+shift+p</code>, 맥은 <code>cmd+shift+p</code>
<code>Preference: Open User Settings (JSON)</code> 입력한다.<pre><code>{
// ... 
&quot;editor.codeActionsOnSave&quot;: {
   &quot;source.fixAll.eslint&quot;: true
},
&quot;eslint.alwaysShowStatus&quot;: true,
&quot;eslint.workingDirectories&quot;: [
   {&quot;mode&quot;: &quot;auto&quot;}
],
&quot;eslint.validate&quot;: [
   &quot;javascript&quot;,
   &quot;typescript&quot;
],
}</code></pre>위의 내용은 사용자 설정에 넣어야 하며, 기존에 설치한 확장 프로그램들이 있다면 안이 채워져 있을 수 있습니다. 채워져 있다면 그 밑에 바로 내용을 넣어주시면 됩니다.</li>
</ol>
<ol start="3">
<li><p>마지막으로 VSCode 에디터 설정 중 format on save가 설정되어 있는지 확인합니다. 되어 있다면 설정을 해제합니다.</p>
</li>
<li><p>확장 프로그램 ESLint, Prettier을 설치한다.</p>
</li>
<li><p>몇 가지 프리셋과 라이브러리를 설치한다.</p>
<pre><code>npm i -D @babel/core @babel/preset-env @babel/preset-typescript @typescript-eslint/eslint-plugin @typescript-eslint/parser eslint prettier eslint-plugin-prettier</code></pre></li>
</ol>
<ol start="6">
<li>프로젝트 폴더 밑에 <code>.eslintrc.js</code> 파일을 만들고 이하 내용을 붙여 넣습니다.<pre><code>module.exports = {
root: true,
env: {
 browser: true,
 node: true,
 jest: true,
},
extends: [
 &#39;plugin:@typescript-eslint/eslint-recommended&#39;,
 &#39;plugin:@typescript-eslint/recommended&#39;,
],
plugins: [&#39;prettier&#39;, &#39;@typescript-eslint&#39;],
rules: {
 &#39;prettier/prettier&#39;: [
   &#39;error&#39;,
   {
     singleQuote: true,
     tabWidth: 2,
     printWidth: 80,
     bracketSpacing: true,
     arrowParens: &#39;avoid&#39;,
   },
 ],
 &#39;@typescript-eslint/no-explicit-any&#39;: &#39;off&#39;,
 &#39;@typescript-eslint/explicit-function-return-type&#39;: &#39;off&#39;,
 &#39;prefer-const&#39;: &#39;off&#39;,
},
parserOptions: {
 parser: &#39;@typescript-eslint/parser&#39;,
},
};</code></pre></li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[TypeScript란?]]></title>
            <link>https://velog.io/@seobi-97/TypeScript%EB%9E%80</link>
            <guid>https://velog.io/@seobi-97/TypeScript%EB%9E%80</guid>
            <pubDate>Tue, 30 May 2023 07:37:17 GMT</pubDate>
            <description><![CDATA[<h2 id="typescript란">TypeScript란?</h2>
<blockquote>
<p><strong>TypeScript란?</strong></p>
</blockquote>
<p>자바스크립트의 슈퍼셋인 오픈소스 프로그래밍 언어이다.
마이크로소프트에서 개발, 유지하고 있으며 엄격한 문법을 지원한다.
타입스크립트에서 자신이 원하는 타입을 정의하고 프로그래밍을 하면 자바스크립트로 컴파일되어 실행할 수 있다.</p>
<h3 id="typescript의-장점">TypeScript의 장점</h3>
<p>TypeScript를 꼭 써야하는 이유가 있을까?
그 이유가 있다면 무엇일까?</p>
<h4 id="1-에러-예방">1. 에러 예방</h4>
<p>타입스크립트는 타입을 부여하기 때문에 코드 작성 시에 알맞지 않은 타입을 넣거나, 혹은 타입을 넣지 않았을 경우 사전에 IDE에서 오류라고 경고를 준다.
<img src="https://velog.velcdn.com/images/seobi-97/post/d83895bd-b60b-44f5-abf6-38a0db9e0507/image.png" alt="">
이것은 사전에 오류를 디버깅 할 수 있고 나중에 디버깅하는 시간을 줄여줘 생산적인 측면에서 효과적이다.</p>
<h4 id="2-실행-속도">2. 실행 속도</h4>
<p>타입스크립트는 개발자가 코드를 작성하면서 직접 오류를 체크해 수정을 하기도 하고, 타입을 미리 결정하기 때문에 기계가 할 일을 덜어 실행 속도가 매우 빠르다.</p>
<h4 id="3-안정성--협업용이성">3. 안정성 &amp; 협업용이성</h4>
<p>자바스크립트로만 코드를 작성하게 되면 나중에 같이 협업하는 사람이나 다른 사람이 코드를 읽을 경우 모든 변수의 타입을 짐작하기는 쉽지 않다. 자기 자신 또한 나중에 코드를 보게 될때 바로 알아내기 쉽지 않을 것이다.</p>
<p>하지만 타입스크립트는 타입을 명시할 수 있고 컴파일 시 오류를 찾기 때문에 보다 안정적이다.</p>
<h4 id="4-슈퍼셋">4. 슈퍼셋</h4>
<p>타입스크립트는 자바스크립트의 슈퍼셋, 즉 자바스크립트의 +알파이다.</p>
<p>자바스크립트와의 100%호환이 되고, 그 이외에도 클래스, 인터페이스 등 객체향 프로그래밍 패턴을 제공한다.</p>
<h3 id="typescript의-단점">TypeScript의 단점</h3>
<h4 id="1-초기-세팅">1. 초기 세팅</h4>
<p>자바스크립트에 비해 초기 세팅이 까다롭다.</p>
<h4 id="2-새로운-언어">2. 새로운 언어</h4>
<p>자바스크립트를 이용할 줄 아는 개발자라도 새로운 언어를 따로 배워 적용해야한다.</p>
<h4 id="3-더-많은-코드-작성">3. 더 많은 코드 작성</h4>
<p>타입스크립트는 타입을 일일이 명시해줘야 하기 때문에 자바스크립트보다 더 많은 코드를 작성해야한다.</p>
<h2 id="느낀점">느낀점</h2>
<p>공부를 새로 해야한다는 단점이 있지만, 자바스크립트보다 타입스크립트를 선호하는 추세기도 하고 장점들을 살펴보니 쓸 이유가 충분하다!
타스 공부 화이팅~!</p>
<br>

<p>출처: <a href="https://fomaios.tistory.com/entry/TS-%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8TypeScript%EB%9E%80">https://fomaios.tistory.com/entry/TS-%ED%83%80%EC%9E%85%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8TypeScript%EB%9E%80</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Section 3 회고]]></title>
            <link>https://velog.io/@seobi-97/Section-3-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@seobi-97/Section-3-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Tue, 09 May 2023 06:22:10 GMT</pubDate>
            <description><![CDATA[<h2 id="저번-회고록-리뷰">저번 회고록 리뷰</h2>
<p>원래 하루에 계획을 머릿속으로만 생각하고 진행하는 편이었다.
파워 P 답게 할 수 있는거 좀  하고 나머지는 나중에 해야지라는 마인드로 넘겨왔는데, 그게 쌓이고 쌓이다보니 진짜 많아졌다.
이제는 진짜 체계적으로 해야겠다는 생각이 들었다.
그렇다고 직접 어디에 기록하는 건 귀찮아서 Todo앱을 깔아 하루하루 공부, 운동 계획을 세우고 지켜나가는 중이다!</p>
<h2 id="목표-상기하기">목표 상기하기</h2>
<blockquote>
<ul>
<li>일주일 계획을 세우고 지키는 체계적인 공부</li>
</ul>
</blockquote>
<ul>
<li>질문이 들어왔을때, 바로 대답할 수 있는 깊은 언어 지식 보유</li>
<li>건강한 몸 상태 유지</li>
</ul>
<h2 id="keep-problem-작성하기">Keep, Problem 작성하기</h2>
<h3 id="keep">Keep</h3>
<blockquote>
<ul>
<li>새로 알게 된 사이트, 정보 노션 및 블로그에 기록하기</li>
</ul>
</blockquote>
<ul>
<li>일주일 2~3회 러닝 및 마라톤 참가(빵빵런, JTBC 마라톤 추천!)</li>
</ul>
<h3 id="problem">Problem</h3>
<blockquote>
<ul>
<li>집중력을 좀 더 기르자!</li>
</ul>
</blockquote>
<ul>
<li>좀 더 우선순위를 확실하게 정하고 그에 맞게 공부하자.</li>
</ul>
<h2 id="try-작성하기">Try 작성하기</h2>
<blockquote>
<ul>
<li>빨리 해버리고 쉬자는 마인드 장착하기(매우매우 어려움)</li>
</ul>
</blockquote>
<ul>
<li>새로 알게 된 내용을 나만의 생각으로 블로그 작성하기</li>
<li>채용공고 수시 확인하기</li>
</ul>
<h2 id="우선순위">우선순위</h2>
<blockquote>
<ul>
<li>우선 기본 과제에 충실하자.</li>
</ul>
</blockquote>
<ul>
<li>스터디 공부 및 기록</li>
<li>개인 공부</li>
</ul>
<h2 id="마무리">마무리</h2>
<p>전체적으로 살펴보니 더 나아진 점도 있었고, 더 나빠진 점도 있었다.
나빠진 점을 빠르게 파악해서 인정하고 고치려고 노력해보자!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Section3 기술면접]]></title>
            <link>https://velog.io/@seobi-97/Section3-%EA%B8%B0%EC%88%A0%EB%A9%B4%EC%A0%91</link>
            <guid>https://velog.io/@seobi-97/Section3-%EA%B8%B0%EC%88%A0%EB%A9%B4%EC%A0%91</guid>
            <pubDate>Tue, 09 May 2023 05:39:40 GMT</pubDate>
            <description><![CDATA[<h3 id="재귀"><strong>재귀</strong></h3>
<ul>
<li>재귀를 활용하기 좋은 상황은 언제인지 예시를 들어 설명해 주세요.</li>
</ul>
<pre><code>재귀 함수란, 함수에서 자기 자신을 다시 호출해 작업을 수행하는 방식이다.
재귀함수를 이용하는 이유로는 변수의 사용을 줄여주고, 큰 문제를 작은 문제로 분할하여 
쉽게 풀 수 있다는 점이다.
가장 대표적인 예로 팩토리얼이 있다.
for문이나 while문을 사용하는 것보다 재귀 함수로 작성하는 것이 더 자연스럽다.</code></pre><h3 id="uiux"><strong>UI/UX</strong></h3>
<ul>
<li>UI, UX의 개념과 두 개념의 관계에 대해서 설명해 주세요.</li>
</ul>
<h3 id="custom-component"><strong>Custom Component</strong></h3>
<ul>
<li>Styled Components를 사용해 보면서 느낀 장점을 이야기해 주세요.<pre><code>우선 컴포넌트마다 css파일을 만드는 것은 아주 귀찮은 일이다. 
그렇다고 하나의 css파일로 작성하기엔 뭐가 어디서 쓰인 지 파악하기가 어려워진다.
하지만 Styled-Components를 사용하면 하나의 JS 파일안에서 CSS를 작성할 수 있다.
이는 코드를 한눈에 보기도 편하고, 원하는 스타일링을 하기도 좋다.</code></pre></li>
<li>useRef가 필요한 상황을 예시를 들어 설명해 주세요.<pre><code>JavaScript를 사용할 때는 getElementById, querySelector 같은 DOM Selector 
함수를 사용해서 DOM 을 선택한다.
React에서도 특정 DOM을 선택할 일이 발생하는데, 그 때 ref를 사용한다.
그 중 함수형 컴포넌트에서 useRef라는 Hook함수를 사용한다.
예시로 들자면, 모달 창을 만들 때 바깥 부분을 클릭 시 모달 창이 닫히는 기능을
useRef로 구현할 수 있다.</code></pre></li>
</ul>
<h3 id="redux"><strong>Redux</strong></h3>
<ul>
<li>상태관리 라이브러리의 필요성에 대해서 설명해 주세요.<pre><code>간단한 프로젝트의 경우 state &amp; props로 상태값을 관리할 수 있다.
하지만 프로젝트 규모가 커지고 props 전달하는 컴포넌트가 많아지면, 데이터 흐름을 
예측하기 어려울 뿐만 아니라 컴포넌트를 순수 함수로 유지하기 힘들어진다.
이 문제는 상태 관리 라이브러리를 사용하면 해결할 수 있다.</code></pre></li>
<li>Redux의 주요 개념들과 연결 관계를 설명해 주세요.<pre><code>Redux는 크게 Action, Dispatch, Store, Reducer로 구성된다.
</code></pre></li>
</ul>
<p>Action은 state의 변화에 대한 내용을 말한다. type은 필수 구성 요소이고, payload는
필요 시 작성한다.
Dispatch는 Reducer로 Action을 전달해 주는 함수이다.
Reducer는 Dispatch에게서 전달받은 Action 객체의 type 값에 따라서 상태를 변경시키는
함수이다.
Store는 상태가 관리되는 오직 하나뿐인 저장소의 역할을 한다. Redux 앱의 state가 
저장되어 있는 공간이다.</p>
<ol>
<li>상태가 변경되는 이벤트가 발생하면, 변경될 상태에 관한 Action 객체가 발생한다.</li>
<li>Action 객체는 Dispatch 함수의 인자로 전달된다.</li>
<li>Dispatch 함수는 받아온 객체를 Reducer 함수로 전달한다.</li>
<li>Reducer 함수는 Action 객체의 값을 확인하고, Store의 상태를 변경한다.</li>
<li>상태가 변경되면 리렌더링이 발생한다.<pre><code></code></pre></li>
</ol>
<h3 id="웹-표준--웹-접근성"><strong>웹 표준 &amp; 웹 접근성</strong></h3>
<ul>
<li>Semantic HTML의 필요성을 예시를 들어 설명해 주세요.</li>
</ul>
<h3 id="네트워크-심화"><strong>네트워크 심화</strong></h3>
<ul>
<li>IP 프로토콜의 한계에 대해서 설명해 주세요.</li>
<li>HTTP 프로토콜의 특징에 대해 설명해 주세요.</li>
</ul>
<h3 id="인증--보안"><strong>인증 / 보안</strong></h3>
<ul>
<li>Cookie의 MaxAge, Expires 옵션이 무엇인지, 설정하지 않으면 어떻게 되는지 설명해 주세요.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[웹 표준과 웹 접근성]]></title>
            <link>https://velog.io/@seobi-97/%EC%9B%B9-%ED%91%9C%EC%A4%80%EA%B3%BC-%EC%9B%B9-%EC%A0%91%EA%B7%BC%EC%84%B1</link>
            <guid>https://velog.io/@seobi-97/%EC%9B%B9-%ED%91%9C%EC%A4%80%EA%B3%BC-%EC%9B%B9-%EC%A0%91%EA%B7%BC%EC%84%B1</guid>
            <pubDate>Fri, 28 Apr 2023 00:42:48 GMT</pubDate>
            <description><![CDATA[<h2 id="웹이란">웹이란?</h2>
<blockquote>
<p>문서, 이미지, 영상 등 다양한 정보를 여러 사람들과 공유할 수 있는 공간</p>
</blockquote>
<h2 id="웹의-특징">웹의 특징</h2>
<blockquote>
</blockquote>
<p>인터넷 상에서 텍스트나 그림, 소리, 영상 등과 같은 멀티미디어 정보를 하이퍼텍스트 방식으로 연결하여 제공한다.
책처럼 순서대로 정보에 접근하는 방식이 아니라, 링크를 통해 사용자가 원하는 순서에 따라 정보를 얻을 수 있다.</p>
<h2 id="웹-표준">웹 표준</h2>
<blockquote>
<p>웹 표준이란 W3C에서 권고하는 웹에서 표준적으로 사용되는 기술이나 규칙을 의미한다. 현재 크롬,엣지,사파리,오페라,파이어폭스 등 최신 웹 브라우저들은 모두 웹 표준을 지원한다.</p>
</blockquote>
<h3 id="웹-표준의-장점">웹 표준의 장점</h3>
<ol>
<li>유지 보수의 용이성<blockquote>
<p>웹 표준으로 HTML, CSS, JavaScript 등의 사용 방법을 정리하기 이전에는 구조, 표현, 동작이 뒤섞인 코드도 많았다. 하지만 웹 표준으로 각 영역이 분리되면서 유지 보수가 용이해졌고, 코드가 경량화되면서 트래픽이 감소하는 효과도 생겼다.</p>
</blockquote>
</li>
<li>웹 호환성 확보<blockquote>
<p>웹 표준을 준수하여 개발하면, 웹 브라우저의 종류나 버전, 운영 체제나 사용 기기 종류에 상관없이 항상 동일한 결과가 나오도록 할 수 있다.</p>
</blockquote>
</li>
<li>검색 효율성 증대<blockquote>
<p>웹 표준에 맞춰 웹 사이트를 작성하는 것만으로도 검색 엔진에서 더 높은 우선순위로 노출될 수 있다.</p>
</blockquote>
</li>
<li>웹 접근성 향상<blockquote>
<p>모든 환경과 사용자에 맞춰서 웹 개발하는 것은 쉽지 않다. 웹 표준에 맞춰 개발하는 것만으로도 이러한 문제를 해결할 수 있다.</p>
</blockquote>
</li>
</ol>
<h2 id="웹-접근성">웹 접근성</h2>
<blockquote>
<p>웹 접근성이란, 일반적으로 장애인, 고령자 등이 웹 사이트에서 제공하는 정보에 비장애인과 동등하게 접근하고 이해할 수 있도록 보장하는 것을 뜻한다.</p>
</blockquote>
<h3 id="웹-접근성을-갖추면-얻을-수-있는-효과">웹 접근성을 갖추면 얻을 수 있는 효과</h3>
<ol>
<li>사용자층 확대<blockquote>
<p>웹 접근성을 확보하면 일반인뿐만 아니라 장애인, 고령자 등 정보 소외 계층도 웹 사이트를 자유롭게 이용할 수 있다.</p>
</blockquote>
</li>
<li>다양한 환경 지원<blockquote>
<p>웹 접근성을 향상 시키면 다양한 환경, 다양한 기기에서 자유롭게 사용할 수 있게 되어 서비스의 사용 범위가 확대된다.</p>
</blockquote>
</li>
<li>사회적 이미지 향상<blockquote>
<p>기업이 정보 소외 계층을 위한 사회 공헌 및 복지 향상에 힘쓰고 있음을 보여줄 수 있다.</p>
</blockquote>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[Node.js란?]]></title>
            <link>https://velog.io/@seobi-97/Node.js%EB%9E%80</link>
            <guid>https://velog.io/@seobi-97/Node.js%EB%9E%80</guid>
            <pubDate>Tue, 25 Apr 2023 09:26:32 GMT</pubDate>
            <description><![CDATA[<h2 id="nodejs란">Node.js란?</h2>
<hr>
<blockquote>
<p>공식사이트를 참고하면
Node.js란? Chrome V8 JavaScript엔진으로 빌드된 JavaScript 런타임이다. Node.js는 이벤트 기반, 논 블로킹 I/O모델을 사용해 가볍고 효율적입니다. Node.js의 패키지 생태계인 npm은 세계에서 가장 큰 오픈 소스 라이브러리 생태계이기도 합니다.</p>
</blockquote>
<h3 id="nodejs의-주요-특징">Node.js의 주요 특징</h3>
<hr>
<ol>
<li>자바스크립트 언어 사용</li>
</ol>
<ul>
<li>자바스크립트를 사용할 줄 아는 개발자들에게는 러닝커브가 낮다.</li>
<li>또한 자바스크립트로 백엔드 로직까지 개발할 수 있다는 장점으로 점유율이 높아지고 있다.</li>
</ul>
<ol start="2">
<li>빠른 속도</li>
</ol>
<ul>
<li>구글에서 개발한 자바스크립트 엔진을 사용하기 때문에 빠른 속도를 자랑한다.</li>
</ul>
<ol start="3">
<li>이벤트 기반 비동기 방식(Non-Blocking)</li>
</ol>
<ul>
<li>Node.js에서는 모든 API가 비동기 방식이므로, 호출 후 응답을 기다리지 않고 다른 API를 호출한다.</li>
<li>이전에 호출했던 API의 응답이 오면 이벤트 루프가 확인하여 처리한다.</li>
</ul>
<ol start="4">
<li>단일 쓰레드</li>
</ol>
<ul>
<li>복잡한 비동기 I/O 응용 프로그램을 싱글 스레드 JavaScript로 작성하여 결과물의 실행 속도와 개발 편의성 측면에서 좋다는 것이 Node.js의 근간을 이루는 개념이며, CPU의 높은 연산력을 요구하는 프로그램을 Node.js로 짜면 좋지 않은 성능이 나온다.</li>
</ul>
<h3 id="장점">장점</h3>
<ol>
<li>자바스크립트 언어를 동일하게 사용해서 새로운 언어를 습득하지 않고도 서버기술을 빨리 개발/응용할 수 있다.</li>
<li>개발이 빠르고 쉽다.</li>
<li>Non-blocking I/O와 단일 스레드 이벤트 루프를 통한 높은 처리 성능</li>
<li>이벤트 기반 비동기 방식이라 서버 무리가 적다.</li>
<li>npm을 통한 다양한 모듈 제공<h3 id="단점">단점</h3>
</li>
<li>이벤트 기반 비동기 방식이라 서버단 로직이 복잡한 경우 콜백함수의 늪에 빠질 수 있다.</li>
<li>단일 스레드이기 때문에 하나의 작업 자체가 많이 걸리는 웹서비스에는 어울리지 않는다.</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[React+Redux를 이용한 count 증가, 감소]]></title>
            <link>https://velog.io/@seobi-97/Redux%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-count-%EC%A6%9D%EA%B0%80-%EA%B0%90%EC%86%8C</link>
            <guid>https://velog.io/@seobi-97/Redux%EB%A5%BC-%EC%9D%B4%EC%9A%A9%ED%95%9C-count-%EC%A6%9D%EA%B0%80-%EA%B0%90%EC%86%8C</guid>
            <pubDate>Mon, 24 Apr 2023 16:03:55 GMT</pubDate>
            <description><![CDATA[<p>Redux란 상태 관리 라이브러리를 이용해 count를 증가, 감소시켜보겠다.</p>
<p>src폴더 내에 <code>Actions</code>,<code>Reducers</code>, <code>Store</code> 폴더 세 개를 만들어준다.</p>
<h2 id="actions">Actions</h2>
<p>Action폴더 내에 <code>index.js</code>파일을 만든다.</p>
<h3 id="indexjs">index.js</h3>
<pre><code>// action type 정의
export const INCREASE = &#39;INCREASE&#39;;
export const DECREASE = &#39;DECREASE&#39;;

// action 생성 함수 정의
export const increase = () =&gt; {
  return {
    type: INCREASE,
  };
};

export const decrease = () =&gt; {
  return {
    type: DECREASE,
  };
};
</code></pre><h2 id="reducers">Reducers</h2>
<h3 id="indexjs-1">index.js</h3>
<pre><code>import { initialState } from &#39;./initialState.js&#39;;
import { INCREASE, DECREASE, increase, decrease } from &#39;../Actions&#39;;

//상태에 변화를 일으키는 함수
//첫 번째 파라미터는 현재 상태이고, 두 번째 파라미터는 액션 객체이다.
export const counterReducer = (state = initialState, action) =&gt; {
  switch (action.type) {
    case INCREASE:
      return state + 1;
    case DECREASE:
      return state - 1;
    case &#39;SET_NUMBER&#39;:
      return action.payload;
    default:
      return state;
  }
};
</code></pre><h3 id="initialstatejs">initialState.js</h3>
<pre><code>//초기 상태 정의
export const initialState = 1;
</code></pre><h2 id="store">Store</h2>
<h3 id="indexjs-2">index.js</h3>
<pre><code>import { legacy_createStore as createStore } from &#39;redux&#39;;
import { counterReducer } from &#39;../Reducers&#39;;
//Store 생성
export const store = createStore(counterReducer);
</code></pre><h2 id="appjs">App.js</h2>
<pre><code>import React from &#39;react&#39;;
import &#39;./style.css&#39;;
import { useSelector, useDispatch } from &#39;react-redux&#39;;
import { increase, decrease } from &#39;./Actions&#39;;

export default function App() {
  const state = useSelector((state) =&gt; state);
  const dispatch = useDispatch();
  const plusNum = () =&gt; {
    dispatch(increase());
  };

  const minusNum = () =&gt; {
    dispatch(decrease());
  };

  return (
    &lt;div className=&quot;container&quot;&gt;
      &lt;h1&gt;{`Count: ${state}`}&lt;/h1&gt;
      &lt;div&gt;
        &lt;button className=&quot;plusBtn&quot; onClick={plusNum}&gt;
          +
        &lt;/button&gt;
        &lt;button className=&quot;minusBtn&quot; onClick={minusNum}&gt;
          -
        &lt;/button&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  );
}
</code></pre><h2 id="indexjs-3">index.js</h2>
<pre><code>import React from &#39;react&#39;;
import { createRoot } from &#39;react-dom/client&#39;;
import App from &#39;./App&#39;;
import { Provider } from &#39;react-redux&#39;;
import { store } from &#39;./Store&#39;;

const rootElement = document.getElementById(&#39;root&#39;);
const root = createRoot(rootElement);

root.render(
  &lt;Provider store={store}&gt;
    &lt;App /&gt;
  &lt;/Provider&gt;
);
</code></pre><h2 id="전체적인-흐름">전체적인 흐름</h2>
<ol>
<li><code>+</code> 버튼을 클릭하면, <code>plusNum</code>함수가 실행된다.</li>
<li><code>dispatch</code>에서 액션 생성자를 사용해서 Reducer를 호출한다.</li>
<li><code>action.type</code>이 <code>INCREASE</code>이므로 <code>state+1</code>를 return하게 된다.</li>
<li><code>useSelector</code>를 이용해 가져온 <code>state</code>값은 2가 되어 출력된다.</li>
</ol>
<h2 id="코드-확인">코드 확인</h2>
<p><a href="https://stackblitz.com/edit/react-c3said?file=src/App.js">https://stackblitz.com/edit/react-c3said?file=src/App.js</a></p>
]]></description>
        </item>
    </channel>
</rss>