<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>wrld_worthy.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Thu, 20 Jun 2024 08:48:17 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <copyright>Copyright (C) 2019. wrld_worthy.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/wrld_worthy" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[Study] OS 1-1장]]></title>
            <link>https://velog.io/@wrld_worthy/Study-OS-1-1%EC%9E%A5</link>
            <guid>https://velog.io/@wrld_worthy/Study-OS-1-1%EC%9E%A5</guid>
            <pubDate>Thu, 20 Jun 2024 08:48:17 GMT</pubDate>
            <description><![CDATA[<h1 id="운영체제">운영체제</h1>
<h2 id="1-운영체제가-하는-일">1. 운영체제가 하는 일</h2>
<p>컴퓨터 시스템은 대개 4가지 구성요소 하드웨어, 운영체제, 응용 프로그램, 사용자로 구분할 수 있다.</p>
<p><strong>하드웨어</strong>는 말 그대로 장치들을 일컫는다. 중앙 처리 장치(CPU), 메모리 및 입/출력(I/O) 장치로 구성되어있다.</p>
<p><strong>응용 프로그램</strong>은 컴파일러, 웹 브로우저, 워드 프로세서 등등 사용자의 계산 문제를 해결하기 위해 이들 자원이 어떻게 사용될지를 정의하는 것들이다.</p>
<p><strong>운영체제</strong>는 다양한 사용자들을 위해 다양한 응용 프로그램 간의 하드웨어 사용을 제어하고 조정하는데, 그 자체로는 유용한 기능을 수행하지 못한다. 단순히 다른 프로그램이 유용한 작업을 할 수 있는 환경을 제공하는 것이다.</p>
<p>관점에 따른 목적, 기능이 다르고 하는 역할이 매우 다양하다.</p>
<h3 id="user-view">User View</h3>
<p>컴퓨터에 대한 사용자의 관점은 사용되는 인터페이스에 따라 달라진다.
ex) 랩톱, 데스크톱
이러한 시스템들은 한 사용자가 자원을 독점하도록 설계되었고, 목표는 사용자가 수행하는 작업을 최대화 하는 것이다. 이러한 경우에는 운영체제가 <strong>사용의 용이성</strong>을 위해 설계되고 성능에 약간 신경을 자원의 이용에는 전혀 신경을 쓰지 않는다.</p>
<h3 id="system-view">System View</h3>
<p>운영체제는 하드웨어와 가장 밀접하게 연관된 프로그램이다.</p>
<p>따라서 운영체제를 자원 할당자로 볼 수 있다.</p>
<p>컴퓨터 시스템은 문제를 해결하기 위해 요구되는 여러 가지 자원들, 즉 CPU 시간, 메모리 공간, 저장장치 공간, 입/출력 장치 등을 가진다.</p>
<p>운영체제는 자원에 대해 서로 상충할 수도 있는 많은 요청이 있으므로, 효율적의고 공정하게 운영할 수 있도록 어느 요청에 자원을 할당할지를 결정해야한다.</p>
<p>다소 다른 관점은 입/출력 장치와 사용자 프로그램ㅇ르 제어할 필요성을 강조한다. 
즉 제어 프로그램으로써의 역할을 가지는 것이다. </p>
<p>제어 프로그램은 컴퓨터의 부적절한 사용을 방지하기 위해 사용자 프로그램의 수행을 제어한다.</p>
<p>운영체제는 자원 할당자, 제어 프로그램의 역할들을 맡는다.</p>
<p>이렇게 운영체제는 관점마다 고려할 점과, 역할, 목적이 다르게 작동하기 때문에</p>
<p>적합한 정의는 없다. 다만 유용한 컴퓨팅 시스템을 만드는 문제를 해결하기 위한 합리적인 방법을 제공하기 때문에 존재하며 매우 중요한 시스템이라는 것이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Study] Operating System Concepts 공부 시작]]></title>
            <link>https://velog.io/@wrld_worthy/Study-Operating-System-Concepts-%EA%B3%B5%EB%B6%80-%EC%8B%9C%EC%9E%91</link>
            <guid>https://velog.io/@wrld_worthy/Study-Operating-System-Concepts-%EA%B3%B5%EB%B6%80-%EC%8B%9C%EC%9E%91</guid>
            <pubDate>Thu, 20 Jun 2024 08:05:36 GMT</pubDate>
            <description><![CDATA[<h1 id="운영체제-cs공부-시작">운영체제 CS공부 시작</h1>
<p>컴퓨터 전공을 하면서 대학을 다녔지만</p>
<p>공부보다는 게임과 노는게 중요했던 시기를 보냈다.</p>
<p>취업을 준비하면서 CS관한 지식은 항상 부족했고</p>
<p>국비지원과 부트캠프를 다녀봤지만 CS학습을 병행하고 이해하기에는 시간과 학습량 또한 부족했다.</p>
<p>추가적인 학습이 반드시 필요하다고 생각했고 책을 구매하여 학습하기로 했다.</p>
<p>준비한 책은 공룡책으로 유명한 Operating System Concepts이다.</p>
<p>영문버전으로 보기에는 나의 무능함이...</p>
<p>한글 번역판으로 준비해봤다.</p>
<p>아마 평생 가져가면서 잊어서 보고 잊기 전에보고 생각 날 때마다 또 볼 예정인 책이다.</p>
<p>이제부터 공부를 시작해보자.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[나만무] 2주차 회고/ 트러블 슈팅]]></title>
            <link>https://velog.io/@wrld_worthy/%EB%82%98%EB%A7%8C%EB%AC%B4-2%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0-%ED%8A%B8%EB%9F%AC%EB%B8%94-%EC%8A%88%ED%8C%85</link>
            <guid>https://velog.io/@wrld_worthy/%EB%82%98%EB%A7%8C%EB%AC%B4-2%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0-%ED%8A%B8%EB%9F%AC%EB%B8%94-%EC%8A%88%ED%8C%85</guid>
            <pubDate>Tue, 23 Jan 2024 17:32:09 GMT</pubDate>
            <description><![CDATA[<h1 id="회고">회고</h1>
<p>우리 팀은 Motion Tetris를 주제로 선정하였고 필요한 스택이나, 요구사항을 분석하며 정리하기 시작했다.</p>
<p>각자 역할을 맡았고 우리 팀은 총 4명으로</p>
<p>2명의 프론트엔드 2명의 백엔드로 나뉘었다.</p>
<p>물론 공식적으로 역할군을 나눴지만</p>
<p>프로젝트를 진행하는데 한쪽이 먼저 끝난다면 바로 남은 쪽으로 뛰어들기로 정했기 때문에</p>
<p>정확한 선은 없고 같이 진행하는 식이 될 것같다.</p>
<p>일단 1차적으로 선정한 기술 스택이다.</p>
<h2 id="front-end">front-End</h2>
<ol>
<li>TypeScript</li>
<li>React</li>
<li>Redux</li>
<li>PoseNet API</li>
<li>Nginx</li>
<li>Canvas
위 스택드을 가지고 진행할 것 같다.</li>
</ol>
<p>아마 필요에 따른 다른 스택들이 증가될 가능성이 매우 높다.</p>
<h2 id="back-end">Back-End</h2>
<ol>
<li>Nest.js</li>
<li>TypeScript</li>
<li>WebRTC</li>
<li>Redis</li>
<li>Mysql</li>
</ol>
<h2 id="공통">공통</h2>
<ul>
<li>Docker</li>
</ul>
<p>정도로 진행될 것 같다.
TypeORM 정도 당장 추가할 생각은 있고 물론 마찬가지로</p>
<p>추후에 필요에 따른 스택 변화 가능성이 다분하다.</p>
<p>드디어 제대로 시작이 될 것 같아서 기대가 되었다.</p>
<p>그리고 멘토님이 배정되었다.</p>
<p>서버 관련 직종에 종사하시는 현업자이셨고,</p>
<p>백엔드를 지원하고 있는 나의 입장에서는 매우 좋은 기회가 될 것 같다.</p>
<p>매주 화 목 2일 오전 10시에 함께 회의를 진행하기로 했고, </p>
<p>Notion을 통하여 진행 상황이나 계획, 목표, API 문서 등을 관리하기로 하여</p>
<p>Notion에서 모든 것을 기록하고 있다.</p>
<p>이번 한 주 동안 기본적인 API 구현과 화면 구현을 목표로 삼았고</p>
<p>나는 Lobby Server 구현을 담당하였다.</p>
<p>게임 로비 서버를 구현하는게 처음이라 어떻게 구현할지 모르고 검색해도 잘 나오진 않았다.</p>
<p>우리는 진짜 게임서버가 아니고 웹 게임으로 구현을 하다고니 많이 다르기도하고 막 다른 것 같지 않기도 하고</p>
<p>잘 모르겠다... </p>
<p>일단 진행하다보니 CRUD처럼 구현을 하고 있는 me....</p>
<p>Docker도 처음 사용하게 되어서 익숙하지 않아 버벅이며 진행이 느린 me...</p>
<p>역시 처음 사용은 많은 에러를 불러 일으킨다고 생각하고 있었는데, 역시는 역시였다.</p>
<p>바로 에러를 만나 하루 종일 시간을 날려먹었다</p>
<h1 id="docker-container-ip">Docker Container IP</h1>
<p>우리는 개발 환경을 로컬보다는 </p>
<p>배포했을 때, 만날 에러를 최대한 줄이기 위해서 <strong>Docker</strong>를 사용하여 환경을 구축하기로 했다.</p>
<p>팀원 각자 로컬에서 docker ubuntu 이미지를 다운받아서 </p>
<p>컨테이너를 생성하고 환경을 구축 후 작업을 진행했다.</p>
<p>나는 NestJS 서버를 생성하고, redis도 이미지를 다운받아 컨테이너를 생성하여 서버를 열었따. </p>
<p>그 후 redis와의 통신 확인을 위해서 API를 적당히 구현하고 redis와의 통신 테스트를 진행했다.</p>
<p>Redis 서버와 통신을 하기 위해서 콘솔로 ping을 날려보니 pong이라는 응답이 잘 오는 것을 확인했고, </p>
<p>nest서버에서 요청을 날려보았다.</p>
<p><img src="https://velog.velcdn.com/images/wrld_worthy/post/efa83089-5572-4cce-b5c1-ee5e94a81c62/image.png" alt=""></p>
<p>하루 종일 이상태였다.</p>
<p>0.0.0.0 host를 localhost로 바인딩도 해보고,</p>
<p>포트 포워딩이 안되어 있나 싶어서 확인도 해보고</p>
<p>정상으로 보여도 다시 포워딩을 진행하고 연결해보았다.</p>
<p>역시나 안된다.</p>
<p>다른 포트로도 해보았다.</p>
<p>역시 안된다.</p>
<p>재부팅, 이미지 삭제, 재설치 다해봤다.</p>
<p>역시... Nope</p>
<p>더 이상 뭘 해봐야 할지 모르겠던 나는</p>
<p>docker container의 Inspect를 뒤지기 시작했다.</p>
<p>역시...</p>
<p>새로운 것을 사용하거나 배울때에는 내부적인 것을 빠르게 캐치하는게 중요한 것 같다.</p>
<p>사진으로 확인해보자</p>
<p><img src="https://velog.velcdn.com/images/wrld_worthy/post/a902b3cf-808f-4835-85cf-5b54783289e4/image.png" alt=""></p>
<p>하... container의 IPAddress가 따로 존재했다.</p>
<p>나는 단지 nest서버를 열어놓은 컨테이너는 ubuntu 이미지로 생성했을 때에는</p>
<p>localhost로 요청을 보내고 응답을 받을 수 있었는데,</p>
<p>redise 컨테이너는 아니었다.</p>
<p>Docker의 Docs를 전부 찾아보고 완벽히 공부한 것은 아니지만</p>
<blockquote>
<p>Docker는 기본적으로 컨테이너의 개념으로 독립적인 어플리케이션 환경을 제공한다.
따라서 localhost나 127.0.0.1 자기 자신을 가리키는 Host는 말 그대로 컨테이너의 자신을 가리키는 호스트를 뜻하며 Docker에서 모든 container에 독립적인 환경, 주소, 설정 값 등을 제공한다.</p>
</blockquote>
<p>nest서버에서 localhost:6379(redis port번호 : 6379)로 요청을 보낸 것은 그냥 자신 컨테이너의 6379 port로 요청을 보기만 하고 있던 것이다.</p>
<p>그럼 왜 ubuntu 컨테이너에 있는 nestjs는 왜 요청을 받을 수 있었을까?</p>
<p>그것은 로컬 환경의 3000번 포트가 ubuntu 컨테이너와 포워딩이 되어있기 때문이었다.</p>
<p>정말 좀만 공부하고 진행했다면 하루를 날리지 않았을 에러이다...</p>
<p>Docs란 정말 중요한 문서이며 꼭 필요하고 세세하게 꼼꼼히 확인해야만 한다는 것을 깊게 느낄 수 있었다.</p>
<p><img src="https://velog.velcdn.com/images/wrld_worthy/post/2883be99-e793-4952-86be-8f9f5afd4fd0/image.png" alt="">
기존에 host에 localhost라고 적었던 것을 컨테이너의 주소로 바꿔서 실행해보았다.</p>
<p><img src="https://velog.velcdn.com/images/wrld_worthy/post/5971197b-a9ce-488f-85bf-b0a3dc66ac48/image.png" alt=""></p>
<p>AppModule이 성공적으로 실행된 것을 확인할 수 있었고</p>
<p>요청도 아주 잘 된다...</p>
<p>많은 것을 배운 트러블 슈팅 아닌 트러블 슈팅이었다.</p>
<p>그리고 Docker를 사용해보니 상당히 환경이 깔끔해지고 편리함, 쾌적함을 좀 느낄 수 있었다...</p>
<p>아직 깊게 사용해보진 않았지만 맘에 들어서 따로 Docker에 대한 공부를 진행해볼까 한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[나만무] 1주차 회고]]></title>
            <link>https://velog.io/@wrld_worthy/%EB%82%98%EB%A7%8C%EB%AC%B4-1%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</link>
            <guid>https://velog.io/@wrld_worthy/%EB%82%98%EB%A7%8C%EB%AC%B4-1%EC%A3%BC%EC%B0%A8-%ED%9A%8C%EA%B3%A0</guid>
            <pubDate>Thu, 18 Jan 2024 15:53:42 GMT</pubDate>
            <description><![CDATA[<h1 id="나만무-1주차-회고">나만무 1주차 회고.</h1>
<p>주제를 정하는게 너무 힘들었던 한 주였다.</p>
<p>내가 너무 어렵게 생각했는지 주제 의견을 제대로 못 냈다.</p>
<p>그래서 그런지 팀원들에게 점점 미안해지고,</p>
<p>팀원들의 의견이나 방향 제시하는데 있어서 소극적으로 임하게 되었다.</p>
<p>어찌 되었건 피드백이라도 열심히 했어야 했지 않나? 생각이 들었고 프로젝트를 시작하게 되면 더욱 열심히 해보자고 마음을 먹게 되었다.</p>
<p>우리 팀은 주제가 대충 5가지로 좁혀졌다.</p>
<p><strong>1. 티켓팅 플랫폼</strong></p>
<ul>
<li>단순히 티케팅을 하는 사이트가 아니었다. 약간 사업성에 가까운 아이디어 였음.</li>
</ul>
<p><strong>2. OP.GG와 비슷한 플랫폼...?</strong></p>
<ul>
<li>무엇인지 팀원들도 정확히 이름을 정의하지는 못했다. 그래서인지 코치님께 설명하는데 애매하게 했던 것 같다.</li>
</ul>
<p><strong>3. Clash of Clan + Coding을 합친 Clash of Coding 게임</strong></p>
<ul>
<li>문제를 풀면 병사가 나와서 상대 진영과 싸우게 되는 게임이다.
재미있을 것 같아서 다들 좋아했는데, 생각해보니 발표부터 시연까지 7분이내에 끝내야만 한다...
코딩 문제는 5분안에..? (흠...)
일단 코치님들의 반응은 괜찮으면서도 단점도 많이 보여서 피드백을 많이 받은 주제였던 것 같다.</li>
</ul>
<p><strong>4. dor.gg?</strong></p>
<ul>
<li>dor.gg라는 사이트가 존재했다. 쇼츠처럼 게임 영상을 캡쳐하여 올리면서 SNS와 비슷한 사이트였다.
Desktop App으로 만들어서 discord와 영상 녹화, 편집이 가능한 앱을 만들자는 아이디어이다.
기술적으로 챌린지 범벅이고 너무 어려울 것 같아서 제대로 할 자신이 없었다.</li>
</ul>
<p><strong>5. Motion Tetris</strong></p>
<ul>
<li>모션을 인식하여 테트리스 게임을 하는 아이디어이다.
아무래도 모션으로 게임을 해야하기 때문에 웃기고 나름 챌린지한 부분들이 많았을 것같아서
다른 팀에서도 좋은 의견을 많이 받았다.</li>
</ul>
<hr>
<p>뭐라도 정해져서 정말 다행이었다.</p>
<p>다른 팀들은 좀 일찍 정해져서 아키텍쳐와 기본 기능들을 구현하고 있는거 보면 우리팀은 초반에 진행이 참 느리구나 라는 생각이 강하게 </p>
<p>들어서 맘이 좀 급해졌었다.</p>
<p>주제를 빠르게 정리하여 코치님들께 피드백을 받아가면서 수정해 나갔다.</p>
<p>간단한 시연 영상을 편집하면서 발표 ppt 자료도 준비하면서 영상 편집 경험이 있으신 팀원분이 기가막히게 잘 만들어 주셔서 일이 수월하고 </p>
<p>안정적으로 진행 되었던 것 같다.</p>
<p>생각해보면 딱히 급한 상황도 아니었는데, 이상하게 주변팀이 빠르게 치고 나가다보니 마음이 급했던 것같다.</p>
<p>앞으로의 나만의 무기 프로젝트 진행하는 시기가 기대가 된다.</p>
<hr>
<p>ppt 발표를 끝내고 우리 팀은</p>
<p><strong>Motion Tetris</strong> 게임을 만들기로 했다.</p>
<p>기본적으로 Web Game으로 게임성이 짙지는 않아서 괜찮은 것 같다.</p>
<p>(게임 프로그래밍을 할 생각인 아직 없기 때문에 더욱 좋은 것 같음.)</p>
<p>간단하게 PoseNet이라는 Motion을 인식하는 AI API를 사용해서</p>
<p>html로 블럭을 움직이거나 테트리스 블럭을 쌓아보는 테스트를 걸쳤는데,</p>
<p>모션 인식이 애매하고 포즈 인식이 많아질수록 여러 동작을 맘대로 막 인식해버리는 바람에</p>
<p>내가 예상한 결과에 도달하지 못하고 이상한 결과만 나오게 되었다.</p>
<p>모션 인식의 정의나 정교함을 좀 더 커스터마이징 할 수 있는 방식을 생각해야겠다.</p>
<p>플레이 자체도 상당히 어렵고 절대 쉽지 않았다.</p>
<p>좀 더 다양한 효과나 게임 플레이를 단순화하면서 재밋게 할 요소들을 생각해내야 할 것 같다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[TypeScript] 타입 스크립트를 왜 쓸까?]]></title>
            <link>https://velog.io/@wrld_worthy/TypeScript-%ED%83%80%EC%9E%85-%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EB%A5%BC-%EC%99%9C-%EC%93%B8%EA%B9%8C</link>
            <guid>https://velog.io/@wrld_worthy/TypeScript-%ED%83%80%EC%9E%85-%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EB%A5%BC-%EC%99%9C-%EC%93%B8%EA%B9%8C</guid>
            <pubDate>Fri, 12 Jan 2024 05:12:52 GMT</pubDate>
            <description><![CDATA[<h1 id="타입스크립트">타입스크립트</h1>
<p><strong>JavaScript</strong>는 일반적으로 <code>Interpreted</code> 또는 <code>Just-In-Time</code>(JIT)언어로 분류되는데 전통적인 컴파일 언어와 다르게 작동 된다.</p>
<ul>
<li><strong>인터프리터 언어</strong><ul>
<li>자바스크립트 코드는 보통 브라우저 또는 Node.js와 같은 환경에서 직접 실행되고 이러한 환경에서 자바스크립트 인터프리터는 스크립트를 읽고, 실시간으로 기계어로 번역하며 실행한다.<br></li>
</ul>
</li>
<li><strong>JIT</strong><ul>
<li>현대의 많은 자바스크립트 엔진(V8)은 JIT 컴파일 방식을 사용한다. 이 방식은 자바스크립트 코드가 실행될 때, 엔진이 스크립트 일부를 기계어로 컴파일하고 즉시 실행한다. 일반적인 전통 인터프리트 방식보다 훨씬 빠른 실행 속도를 자랑한다.</li>
</ul>
</li>
</ul>
<p>때문에 일반적으로 사용하기에 언어가 쉽고 실행도 쉬워 입문용 언어로 많이 사용한다.
하지만 내부 동작을 이해하고 사용하기에는 쉬운 언어라고 생각은 들지 않는다.</p>
<h2 id="js의-단점">JS의 단점</h2>
<ol>
<li><strong>동적 타입 바인딩</strong>
 JS는 변수에 타입을 지정해주지 않고 <code>let</code>, <code>const</code>와 같은 변수 선언 키워드를 사용하여 선언한다. 그럼 변수의 타입은 어떻게 지정되는가?
 -&gt; <strong>바로 실행 시점에 결정된다.</strong><br>
 이로 인해서 타입 관련 에러 버그들이 발생하기 쉽고, 실제로 빈번히 발생한다.
 때문에 <strong>대규모 프로젝트에서</strong> 이러한 버그를 추적하기 어려울 수 있다. <br></li>
<li><strong>규모의 확장성</strong>
 큰 규모의 프로젝트나 많은 개발자가 참여하는 프로젝트에서 위와같은 특징과 JS의 구조는 <strong>코드 유지보수</strong>를 어렵게 만든다. <br>

</li>
</ol>
<p>다른 특징도 존재하는데 예시를 보자</p>
<ol>
<li><strong>변수에 값을 넣지 않으면 <code>undefined</code>값을 할당한다.</strong><pre><code class="language-js">const add = (num1, num2) =&gt; {
return num1+num2
}</code></pre>
위와 같은 함수가 있다.
함수를 실행할 때,</li>
</ol>
<p><img src="https://velog.velcdn.com/images/wrld_worthy/post/ca29666b-0aef-4f66-a2f1-a52d0089d850/image.png" alt="">
이렇게 실행을 한다면
에러가 발생할까?</p>
<p>정답은 발생하지 않는다.
<img src="https://velog.velcdn.com/images/wrld_worthy/post/b37b24e4-c67d-4d6f-81a8-e68986603ab3/image.png" alt=""></p>
<p>이처럼 정상적으로 실행된느 것을 볼 수 있다.
적어도 3번째 실행은 6의 결과 값을 기대하고 사용한 것일 수 있다.
이런식으로 에러 발생지점을 알 수 없고 직접 찾아야만 하며
함수의 매개변수에 인자값을 주지 않더라도 자바스크립트는 <code>undefined</code>라는 값을 할당함으로써 에러를 발생시키지 않는다.</p>
<ol start="2">
<li><strong>자동 형변환</strong>
undefined를 자동하더라도 적어도 연산을 수행할 때에는 잘 못된 값이 있으면 에러가 발생하기 마련이다.
하지만 자바스크립트는 undefined를 자동으로 NaN이라는 데이터로 형변환을 하여 에러가 발생하지 않는다.
다른 예시로 1+&#39;2&#39;는 12라는 string 값을 얻게 된다.</li>
</ol>
<h2 id="typescript">TypeScript</h2>
<p>JS는 위와 같은 특징으로 인해 대규모 프로젝트나 개발자가 많은 프로젝트에서는 진행하거나 유지보수 하는데 있어서 매우 힘들다는 점이 있다.</p>
<p><strong>TypeScript</strong>를 도입하면 위와 같은 문제들을 해결할 수 있다.</p>
<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>좋음 (다양한 편집기 및 도구 지원)</td>
<td>매우 좋음 (자바스크립트의 도구에 추가적인 타입 체크 및 자동 완성 기능)</td>
</tr>
<tr>
<td>브라우저 호환성</td>
<td>바로 실행 가능</td>
<td>컴파일 후 자바스크립트로 변환되어 실행</td>
</tr>
<tr>
<td>사용 사례</td>
<td>웹 개발, 서버 사이드 스크립트, 프론트엔드/백엔드 개발</td>
<td>대규모 애플리케이션, 엔터프라이즈급 개발, 프론트엔드/백엔드 개발</td>
</tr>
</tbody></table>
<p>위의 자바스크립트에서의 함수 실행을 같은 케이스로 봐보자.
<img src="https://velog.velcdn.com/images/wrld_worthy/post/a2aea610-27f3-4c9f-8b1c-f59d7928fd93/image.png" alt=""></p>
<p>*.js --&gt; *.ts로 바꿔주기만해도 일단 함수 매개변수 부분에서 에러가 난 것을 확인할 수 있었다.</p>
<p>기존에는</p>
<ol>
<li>런타임에서 확인할 수 있음.</li>
<li>직접 에러를 찾아야 한다.</li>
</ol>
<p>였지만 타입 스크립트를 사용한다면
실행 전에 내가 고려한, 예상한 상황에 맞지 않을 경우에는 잘못된 코드를 확인할 수 있다.</p>
<p>물론 자바스크립트와 같이 1+&#39;2&#39;와 같은 데이터 자체의 자동 형변환이나 그런 것들은 차이점이 없다.</p>
<p>자바 스크립트는 동적인 언어라면 타입스크립트는 정적인 언어가 되어 최대한 예상한 상황이 만들어지도록 도와주며 남들이 보더라도 내가 사용한 변수나 함수들이 어떠한 값을 리턴하며 내가 만들려던 흐름이 어떠한 것인지 더 이해가 쉽게 해준다.</p>
<p>이러한 점을 보더라도 타입스크립트의 사용 가치는 확실한 것같다.</p>
<h1 id="내-생각">내 생각</h1>
<p>예전 오래된 언어들을 보면 대부분이 정적언어인 것같다.
아마 지나친 정적언어로 뭔가 타입리스한 언어들을 선호하게 되고 만든 것 같은데,
기존 개개인의 일보다 팀 프로젝트들이 많아지고 협업을 진행하면서 어려운 점들이 많아지고 요즘은 오픈 소스들도 많고 남들 코드를 보는 시간이 더 많아지는 시대에 동적 언어의 불편한 점들이 점점 더 많아져 타입스크립트 와 같은 정적 타입 언어가 만들어진게 아닌가 싶다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] async, await]]></title>
            <link>https://velog.io/@wrld_worthy/JavaScript-async-await</link>
            <guid>https://velog.io/@wrld_worthy/JavaScript-async-await</guid>
            <pubDate>Tue, 02 Jan 2024 14:58:28 GMT</pubDate>
            <description><![CDATA[<p>async와 await은 자바스크립트에 가장 최근 도입된 비동기 처리 방식인 콜백 함수와 프로스미스의 단점을 보완했으며 가독성 높은 코드를 작성할 수 있다.</p>
<p>async는 함수 앞에 붙이는 키워드로 이 함수는 asynchronous라는 의미이다.</p>
<p>어떤 함수인지 쉽게 유추가 가능하다.</p>
<p>async, await 함수는 기본적으로 Promise 객체를 다룬다.</p>
<p>asnyc는 Promise 객체를 반환하고 await은 Promise 객체를 사용할 수 있도록 해준다.</p>
<pre><code class="language-js">// async 사용 예시
const test = async ()=&gt;{
    return &quot;hi&quot;; 
}
console.log(test());</code></pre>
<p><img src="https://velog.velcdn.com/images/wrld_worthy/post/9dcbd0d6-6e4e-403e-8c28-ab06d417f471/image.png" alt=""></p>
<p>hi를 출력하는게 아닌 Promise 객체로 감싸진 형태로 넘어온 hi를 볼 수 있다.</p>
<p>이렇게 async 함수는 Promise 객체를 반환하는 것을 확인 할 수 있다.</p>
<pre><code class="language-js">// await 사용 예시
const test = async ()=&gt; {
    return &quot;hi&quot;;
}

const test2 = async()=&gt;{
    const sayHi = await test(); 
    console.log(sayHi);
}

console.log(test2())</code></pre>
<p><img src="https://velog.velcdn.com/images/wrld_worthy/post/e811eb7e-67ff-4496-a41a-6b20b65bf079/image.png" alt=""></p>
<p>await은 Promise 객체인 test 함수의 실행이 끝나기를 기다린다. 출력 결과에 Promise 객체가 있는 것은 console.log(test2())의 결과 값이고 역시 async 함수는 Promise 객체를 반환하는 것을 다시 볼 수 었다.</p>
<blockquote>
<p><strong>실행 결과가 뭔가 이상하다??</strong>
원래라면 hi가 먼저 나오고 promise 객체가 나와야한다. 하지만 반대로 나왔다... 왜 일까?
이게 바로 앞에서 봤던 비동기 처리의 결과인 것이다!!</p>
</blockquote>
<p>await을 좀 더 체감할 만한 다른 예시를 봐보자!!</p>
<pre><code class="language-js">const waitOneSecond = (msg) =&gt; {
  return new Promise((resolve,_)=&gt;{
    setTimeout(()=&gt;resolve(`${msg}`),1000);
  });
}

const countOneToTen = async () =&gt; {
  for (let x of [...Array(10).keys()]){
    let result = await waitOneSecond(`${x+1}초 대기중 ...`);
    console.log(result);
  }
  console.log(&quot;완료&quot;);
}

countOneToTen();</code></pre>
<p><img src="https://velog.velcdn.com/images/wrld_worthy/post/4d925a16-85f8-4dc9-8b4f-a5e35913c298/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Javacript] 비동기 처리하기 Callback, Promise]]></title>
            <link>https://velog.io/@wrld_worthy/Javacript-%EB%B9%84%EB%8F%99%EA%B8%B0-%EC%B2%98%EB%A6%AC%ED%95%98%EA%B8%B0-Callback-Promise</link>
            <guid>https://velog.io/@wrld_worthy/Javacript-%EB%B9%84%EB%8F%99%EA%B8%B0-%EC%B2%98%EB%A6%AC%ED%95%98%EA%B8%B0-Callback-Promise</guid>
            <pubDate>Tue, 02 Jan 2024 14:40:20 GMT</pubDate>
            <description><![CDATA[<h1 id="1-비동기">1. 비동기</h1>
<p><strong>동기 Synchronous</strong> 프로그래밍에서 작업은 차례로 실행되며 이전 작업이 끝날 때까지 중단할 수 없다. 모든 작업은 이전 작업의 실핼이 완료될 때까지 기다려야만 한다. </p>
<p>반면, <strong>비동기 Asynchronous</strong> 프로그래밍에서는 임의의 순서로 똔느 동시에 작업이 실행될 수 있다.</p>
<p>자바스크립트는 런타임(Node.js)에서 싱글 스레드로 작동한다. 싱글 스레드로 동작 한다는 것은 한번에 하나의 작업만 처리한다는 뜻이다. 그럼 동기 프로그램으로 동작한다면 실행이 완료될 때까지는 매우 긴 시간이 걸리게되고 매우 비효율적으로 동작하게 될 것이다. </p>
<p><strong>어떻게 효율적으로 처리해야 할 까?</strong>
비동기 처리를 하면된다. 비동기처리는 이전 작업이 끝나지 않아도 다른 작업을 수행 할 수 있게 해준다.</p>
<p>비동기로 처리하기 위해서는 Callback, Promise, asyn, await 방법을 사용하면 자바스크립트에서 비동기로 처리가 가능하다.</p>
<ul>
<li>Callback func : 함수 파라미터로 함수를 전달하며, 비동기 처리가 끝났을 때 전달된 함수를 실행한다. 골백은 가독성이 좋지 못하여 유지보수 및 디버깅이 힘들다는 단점이 있다.<br></li>
<li>Promise 객체 : 콜백 대신 사용할 수 있는 방법으로 비동기 작업이 완료되면 결과를 반환하는 객체이다. 프로미스 객체는 상태를 가지고 있으며 처음에는 대기였다가 작업이 완료되면 성공 또는 실패 상태가 된다. 상태에 따라서 then, catch메서드를 사용하여 처리할 수 있다.<br></li>
<li>async, await : 어싱크 어웨이트는 프로미스를 사용하는 비동기 작업을 동기적으로 처리하는 것처럼 코드를 작성할 수 있게 해준다. async가 붙어있는 함수를 실행할 때 await 키워드를 사용하여 비동기 작업이 완료될 때까지 기다릴 수 있다. asyn와 await 두 키워드는 반드시 붙어 다닌다. async인 함수에만 await을 사용할 수 있다.</li>
</ul>
<h1 id="2-callback-function">2. Callback function</h1>
<p>비동기는 현재 코드의 실행 결과를 받지 않고 이후 코드를 수행하는 기법이다. 컴퓨팅 자원을 효율적으로 사용하는 기법이긴 하자민 정확한 순서를 지켜 수행해야 하는지를 고려해서 처리해야한다.</p>
<p>비동기 코드를 순서대로 싱행하는 가장 일반적인 방안으로 콜백이 있다. 콜백은 실행 가능한 함수를 인자로 전달하여, 특정 상황이 발생할 때 호출되게 하는 방식이다. </p>
<p>콜백은 현실 세계에서도 발견할 수 있는데, 커피숍에 가서 점원에게 커피를 먼저 주문하고 다른 것을 하고 있으면, 커피 제조가 끝난 후에 손님을 호출(callback)하는 상황으로 콜백을 볼 수 있다.</p>
<p>콜백 함수를 작성해 보자.</p>
<pre><code class="language-js">const DB = []

// 회원 가입 API 함수
// 콜백이 3중으로 중첩된 함수
function register(user) {
  return saveDB(user, function(user){
   return sendEmail(user, function(user){
     return getResult(user);
   });
  });
}

// DB에 저장후 콜백 실행
function saveDB(user, callback){
  DB.push(user);
  console.log(`save ${user.name} to DB`);
  return callback(user);
}

// 이메일 발송 로그만 남기는 코드 실행 후 콜백
function sendEmail(user, callback){
  console.log(`email to ${user.email}`);
  return callback(user);
}

// 결과를 반환하는 함수
function getResult(user){
  return `success register ${user.name}`;
}

const result = register({ email:&quot;andy@test.com&quot;, password: &quot;1234&quot;, name: &quot;andy&quot;});
console.log(result);</code></pre>
<p>3단계로 회원 가입 API를 실행하는 1. register함수는 2.saveDB, 3.sendEamil, 4. getResult 함수를 각각 차례로 호출하여 콜백을 사용했다.</p>
<p>여기서 보장하는 것은 함수의 실행 순서이다. </p>
<p>결과
<img src="https://velog.velcdn.com/images/wrld_worthy/post/ee02ec3d-75e8-480c-8c5b-3a6a7c0050b3/image.png" alt=""></p>
<p>예상한 순서대로 잘 작동하는 것을 볼 수 있따. 하지만 매우 간단한 코드 인데도 콜백을 사용하니 코드가 매우 복잡해보여 가독성이 금방 매우 떨어지는 것을 볼 수 있다.</p>
<p>콜백을 3번만 사용해도 tab이 3번을 사용해야한다. 좀 더 복잡하고 무거운 프로그램을 만들어야 한다면? 10단, 20단 콜백문을 볼 수 있을지도 모른다.</p>
<p>그렇다면 지금은 짧아서 괜찮더라도 점점 알아보기가 힘든 상황이 된다. 심지어 콜백에 에러가 발생한다면? 찾기는 매우 힘들 것이다. 생각도 하기 싫다.</p>
<p>이러한 문제를 해결하기 위해서 <strong>Promise 객체</strong>가 2015년 ES6 버전에서 등장했다.</p>
<h1 id="promise-객체">Promise 객체</h1>
<p><code>Promise</code>객체는 자바스크립트에서 비동기 실행을 동기화하는 구문으로 사용한다. Promise의 뜻인 약속을 떠올리면 프로미스 개념을 이해하기 좀 쉽다.</p>
<p>현실 세계에서 약속은 미래에 어떤 것을 할 거라고 정하는 것이다. 약속은 이행, 거절, 대기 세가지 상태를 가질 수 있다.</p>
<p>자바스크립트에서 &#39;이 코드는 어느 시점에서 실행할 거야&#39;라고 약속하는 객체로 Promise를 사용한다.</p>
<p>Promise는 각각 이행, 거절, 대기 세가지 상태를 가질 수 있다. Promise는 객체로 new 연산자로 인스턴스 생성이 가능하다.</p>
<p><img src="https://velog.velcdn.com/images/wrld_worthy/post/9c51417d-89f4-433f-af1d-26ad4a2455f4/image.png" alt=""></p>
<p>Promise 객체가 생성되면 대기 (pending)상태가 된다. resolve()함수가 실행되면 이행으로 변경되고
실패해 reject()함수가 실행되면 거절로 변한다.</p>
<pre><code class="language-js">const DB = []

// DB에 저장후 콜백 실행
function saveDB(user, callback){
  const oldDBSize = DB.length;
  DB.push(user);
  console.log(`save ${user.name} to DB`);
  return new Promise((resolve, reject)=&gt;{ // 콜백 대신 Promise 객체 반환
    if (DB.length &gt; oldDBSize){
      resolve(user)    // 성공 시 유저 정보 반환
    } else {
      reject(new Error(&quot;Save DB Error!&quot;)); // 실패 시 에러처리
    }
  });
}

// 이메일 발송 로그만 남기는 코드 실행 후 콜백
function sendEmail(user, callback){
  console.log(`email to ${user.email}`);
  return new Promise((resolve)=&gt;{ // Promise 객체 반환, 실패 처리 없음
    resolve(user);
  });
}

// 결과를 반환하는 함수
function getResult(user){
  return new Promise((resolve, reject)=&gt;{
    resolve(`success register ${user.name}`);
  });
}

function registerByPromise(user){
  //비동기 호출이지만 순서를 지켜서 실행
  const result = svaeDB(user).then(sendEmail).then(getResult);
  // 아직 완료되지 않아서 지연(pending)상태이다.

  console.log(result);
  return result
}

const myUser = { email:&quot;andy@test.com&quot;, password: &quot;1234&quot;, name: &quot;andy&quot;};
const result = registerByPromise(myuser);
result.then(console.log);</code></pre>
<p>결과</p>
<p><img src="https://velog.velcdn.com/images/wrld_worthy/post/b081fdb8-2bc1-4cc3-a0e3-98b535045891/image.png" alt=""></p>
<p>각각의 함수에 있던 콜백 함수를 Promise 객체로 바꿨다. Promise는 객체이므로 new 생성자로 생성할 수 있고 그 안에 resolve, reject 함수가 있다.</p>
<p>성공하면 resolve를 실패하면 reject를 실행시킨다. 또한 Promise는 then(promise) 메서드가 있어서 비동기 호출이지만 Promise1.then(Promise2).then(Promise3) 이런 식으로 순서대로 호출할 수 있다.</p>
<p>then은 Promise 객체에만 사용할 수 있다.</p>
<p>then의 사용법</p>
<pre><code class="language-js">then(onFulfilled)
then(onFulfilled, onRejected)

then(
  value=&gt;{/*Fulfilled handler*/},
  reason=&gt;{/*rejection handler*/}
)</code></pre>
<p>then은 성공했을 때, catch는 주로 실패했을 때 사용하지만
then의 파라미터를 잘 이요하면 2번째 파라미터에 실패시의 처리를 해줄 수 있다.</p>
<h2 id="동시에-여러-promise-객체-호출하기">동시에 여러 Promise 객체 호출하기.</h2>
<p>동시에 여러 Promise 객체를 호출해 결괏값을 받고 싶을 때는 어떻게 해야할까??</p>
<p><code>Promise.all([Promise1, Promise2, ...])</code>처럼 사용하면 된다.</p>
<p>그러면 나열된 순서 상관없이 동시에 실행할 수 있다. 결과 값은 배열로 반환된다.</p>
<pre><code class="language-js">// 위 코드 그대로...

const myUser = { email:...}
allResult = Promise.all([saveDB(myUser), sendEmail(myUser), getResult(myUser)]);
allResult.then(console.log);</code></pre>
<p>결과</p>
<p><img src="https://velog.velcdn.com/images/wrld_worthy/post/c1fdd878-4679-4799-a15c-99ab4e0e66f3/image.png" alt=""></p>
<p>이와 같은 배열의 결과 값을 얻을 수 있다.</p>
<br>

<h2 id="promise-예외-처리">Promise 예외 처리</h2>
<p>saveDB() 함수의 로직을 약간 변경해서 에러를 발생시켜보자.</p>
<pre><code class="language-js">const DB = []

// DB에 저장후 콜백 실행
function saveDB(user, callback){
  const oldDBSize = DB.length+1; // 이 부분 수정하여 에러발생
  DB.push(user);
  console.log(`save ${user.name} to DB`);
  return new Promise((resolve, reject)=&gt;{ // 콜백 대신 Promise 객체 반환
    if (DB.length &gt; oldDBSize){
      resolve(user)    // 성공 시 유저 정보 반환
    } else {
      reject(new Error(&quot;Save DB Error!&quot;)); // 실패 시 에러처리
    }
  });
}

// 이메일 발송 로그만 남기는 코드 실행 후 콜백
function sendEmail(user, callback){
  console.log(`email to ${user.email}`);
  return new Promise((resolve)=&gt;{ // Promise 객체 반환, 실패 처리 없음
    resolve(user);
  });
}

// 결과를 반환하는 함수
function getResult(user){
  return new Promise((resolve, reject)=&gt;{
    resolve(`success register ${user.name}`);
  });
}

function registerByPromise(user){
  //비동기 호출이지만 순서를 지켜서 실행
  const result = svaeDB(user).then(sendEmail).then(getResult);
  // 아직 완료되지 않아서 지연(pending)상태이다.

  console.log(result);
  return result
}

const myUser = { email:&quot;andy@test.com&quot;, password: &quot;1234&quot;, name: &quot;andy&quot;};
const result = registerByPromise(myuser);
result.then(console.log);</code></pre>
<p>DB.length보다 oldDBSize의 크기가 커야한다고 명시했는데, 일부러 oldDBSize를 더 크게 해주면 Promise 로직이 실패하게 된다.
<img src="https://velog.velcdn.com/images/wrld_worthy/post/5fd2951b-940a-46b1-bddc-9c3ea377de2f/image.png" alt=""></p>
<pre><code class="language-js">function registerByPromise(user){
  //비동기 호출이지만 순서를 지켜서 실행
  const result = saveDB(user)
      .then(sendEmail)
      .then(getResult)
      .catch(error=&gt;new Error(error));
  // 아직 완료되지 않아서 지연(pending)상태이다.
  console.log(result);
  return result
}</code></pre>
<p>위와 같이 수정해주면
<img src="https://velog.velcdn.com/images/wrld_worthy/post/86700a5c-9f47-4149-b007-68ed514e7c8b/image.png" alt=""></p>
<p>좀 다르고 보기 쉬운 에러를 얻을 수 있다.</p>
<p><strong>finally</strong> 메서드도 봐보자.</p>
<p>finally 메서드는 비동기 처리의 성공, 실패 여부와 상관 없이 마지막에 실행해주는 메서드다.</p>
<pre><code class="language-js">function registerByPromise(user){
  //비동기 호출이지만 순서를 지켜서 실행
  const result = saveDB(user)
    .then(sendEmail)
    .then(getResult)
    .catch(error=&gt;new Error(error))
    .finally(()=&gt; console.log(&quot;완료&quot;));
  // 아직 완료되지 않아서 지연(pending)상태이다.
  console.log(result);
  return result
}</code></pre>
<p>위와 같이 수정해주면</p>
<p><img src="https://velog.velcdn.com/images/wrld_worthy/post/0131cc20-688f-478b-a486-f730313dd3ab/image.png" alt=""></p>
<p>완료가 잘 찍혀있는 것을 확인할 수 있다.</p>
<h2 id="promise의-문제점">Promise의 문제점</h2>
<p>자바스크립트에서 비동기 처리를 하는 데 사용하는 Promise 객체는 콜백보다는 확실히 편리하다.</p>
<p>하지만 then()과 catch() 함수를 연결하는 체이닝 방식을 사용하기가 만만하지는 않다. 거기에 더 복잡한 로직을 추가하고 예외 처리까지 해야되는 상호아이라면 더욱 힘들어진다.</p>
<p>이상적으로 깔끔한 코드를 작성할 수는 있겠지만 그런 코드는 실전에서는 보기가 힘들다.</p>
<p>실전은 더욱 복잡하고 까다로운 로직을 수행해야하는 경우가 많기 때문이다.</p>
<p>Promise는 콜백보다는 깔끔하지만 잘못 사용될 수 있는 여지가 남아있따.</p>
<ol>
<li>프로미스의 then 함수에 성공 시와 실패 시 처리할 함수를 둘 다 넘기는 경우.
둘다 넘기면 프로미스는 장식에 불과하고 기존 콜백 함수에 결과와 에러를 동시에 넘기는 형태와 다를 바가 없다.<br></li>
<li>프로미스를 중첩해서 사용하는 경우이다. 콜백에는 익숙한데 프로미스에 익숙하지 않은 때 이런 실수를 많이 한다.</li>
</ol>
<p>이러한 문제를 해결하기 위해서 async, await이 만들어 졌다!!</p>
<p>다음에 알아보자.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Node.js] NPM,  Yarn]]></title>
            <link>https://velog.io/@wrld_worthy/Node.js-NPM-Yarn</link>
            <guid>https://velog.io/@wrld_worthy/Node.js-NPM-Yarn</guid>
            <pubDate>Tue, 02 Jan 2024 10:20:27 GMT</pubDate>
            <description><![CDATA[<h1 id="npm">NPM</h1>
<p><strong>NPM</strong>은 자바스클비트용 패키지 매니저이다. 유저가 만든 패키지를 등록하는 저장소를 의미하기도 하고, CLI를 의미하기도 한다. Node.js를 설치할 때 함께 설치된다.</p>
<p>NPM은 세상에서 가장 많은 수의 패키지가 등록되어 있고, Java의 메이븐, .NET의 NuGet, Python, PyPI, PHP, Ruby를 모두 합친 것보다 압도적으로 많은 패키지들이 등록되어 있다.
<img src="https://velog.velcdn.com/images/wrld_worthy/post/5477713d-34de-4dc7-9260-587c9155b9ac/image.png" alt=""></p>
<p>NPM은 <code>Node Package Manager</code>를 줄인 말로 프로젝트에 필요한 의존성 패키지를 고나리하는 프로그램이다. </p>
<p>의존성 패키지는 해당 프로젝트를 실행하는데 꼭 필요한 라이브러리와 모듈을 말한다.</p>
<p>예를 들어서 express 서버는 express 라이브러리에 의존성이 있기 때문에 express 없이는 동작하지 않는다. </p>
<p>npm은 이런 의존성 패키지를 잘 관리하기 위해서 만들어졌다. 단순하게 의존성 패키지 리스트만 잘 관리하면 될 것같지만 npm은 이보다 더 많은 기능을 제공한다.</p>
<h2 id="package-module">Package/ Module</h2>
<p>Node.js에서 <strong>Package</strong>는 package.json으로 정의한 파일 또는 디렉터리를 의미한다.
패키지에는 반드시 package.json이 포함되어야하고, 여기에 정의된 모두가 패키지가 될 수 있다.</p>
<ol>
<li>Package.json 파일이 있는 디렉토리</li>
<li>1번을 압축한 파일</li>
<li>2번을 내려받을 수 있는 URL주소</li>
<li>3번 정보를 가지고 npm 저장소에 <code>&lt;패키지명&gt;@&lt;버전&gt;</code>으로 등록된 것</li>
<li>4번을 가리키는 <code>&lt;패키지명&gt;@&lt;태그&gt;</code></li>
<li>&lt;패키지명&gt;만 있는 경우 5번에서 latest 태그를 가리킴</li>
<li>1번을 결과로 주는 git URL</li>
</ol>
<p>결과적으로 package.json으로 정의한 코드 뭉치가 바로 패키지이다.</p>
<hr>
<p><strong>Module</strong>은 <code>node_modules</code> 디렉토리 아래에 있는 파일 또는 디렉토리를 말한다.
node_modules에 있는 파일이라 디렉토리는 require()함수로 읽을 수 있다.</p>
<blockquote>
<p><strong>Node.js는 commonJS이다.</strong>
<br>
CommonJS는 브라우저 뿐아니라 서버 애플리케이션에서도 모듈 기능을 제공하기 위해 나온 모듈 규약으로, ES6가 나오기 전에 많이 사용되었고, 특히 <strong>Node.js는 CommonJS가 기본 값</strong>으로 사용되고 있다.
ES module은 ES6의 자바스크립트 모듈의 표준이다. 패키지를 임포트할 때 CommonJS는 require()함수로, ES module(ESM)은 import로 임포트한다.
package.json에서 type 속성을 module로 설정하면 ESM을 사용할 수 있다.
Node.js에서 ESM을 사용하면 프론트엔드의 코드를 백엔드에서도 쉽게 가져가 사용할 수 있다는 장점이 있다.</p>
</blockquote>
<p>node_modules 디렉토리에는 <code>npm install</code>로 설치한 패키지들이 저장된다. 즉 모든 패키지는 모듈이고 설치한다면 node_modules에 모여있다.</p>
<p>또한 npm에 등록되어 있지 않더라도 패키지 포멧만 맞다면 npm install로 설치를할 수 있다.</p>
<p>패키지로 만들면 npm 레지스트리에 등록할 수 있고, 패키지로 만든 코드들은 간단하게 다른 곳에서 설치해 사용이 가능하므로 사설 npm 레지스트리에 공통으로 사용하는 패키지를 배포해서 사용하기도 한다.</p>
<h2 id="npm-문제점">npm 문제점</h2>
<p>사실 require() 함수를 사용할 때 단순히 현재 디렉토리의 node_modules만 읽는 것은 아니다.</p>
<p>module.pahts에 있는 경로를 따라서 모듈을 찾는다.</p>
<pre><code class="language-sh">mkdir sample-package
cd sample-package
node

# 아래는 Node.js의 REPL이다.
&gt; module.paths</code></pre>
<p>임시 sample-package라는 폴더를 생성하여 node에서 module.paths를 확인해 보았다.
<img src="https://velog.velcdn.com/images/wrld_worthy/post/44d18903-9faf-4253-85fd-b2be57cc5568/image.png" alt=""></p>
<p>새로 생성한 폴더에는 어떠한 파일도 존재하지 않지만</p>
<p><img src="https://velog.velcdn.com/images/wrld_worthy/post/1a5c8d93-4a7f-4f0a-9ed2-c5f9c0ecf318/image.png" alt="">
출력 결과는 다르다.</p>
<p>무언가 있는 것처럼 나온다. </p>
<blockquote>
<h3 id="왜-이러는-것일까"><strong>왜 이러는 것일까??</strong></h3>
<p>이 출력 결과는 있는 폴더를 나타내는게 아니라, <code>node_modules가 있을 것이라고 가정한 path들이다.</code> 즉, 있지도 않는 디렉토리들을 상위 디렉토리에 있는 패키지를 계속 타고 올라가면서 node_modules를 확인하는 것이다. 이런 방식은 굉장히 많은 I/O를 발생시킨다.
때문에 require()가 무거워지는 원인이 된다. 
이런 문제점을 해결한 <strong>yarn</strong> 프로젝트가 존재한다.</p>
</blockquote>
<h2 id="packagejson-파일-만들기">package.json 파일 만들기</h2>
<p>package.json이 패키지들의 정보들을 담고 있는데, 이런 파일은 어떻게 생성이 가능할까?</p>
<p>일단 쉬운 방법은 직접 작석하는 것이있다. 하지만 오타나 무언가 문제가 발생할 확률이 매우매우 높다. </p>
<p>그래서 다른 방법은 npm install을 하여 필요한 패키지를 설치하는 것이다. 그럼 자동적으로 package.json과 외에 필요한 파일들을 생성하고 패키지들의 정보를 기록한다.</p>
<p>하지만 위와 같은 방식보다는 최종적으로 <code>npm init -y</code>를 사용하여 생성하는 것이 가장 권장된 방식이다.</p>
<p>위의 명령어를 사용하여 생성하면 기본적인 내용을 작성하여 파일을 생성해준다.</p>
<p>-y 옵션을 사용하지 않고 직접 입력하면 내용을 변경할 수 있다.</p>
<p>생성한 package.json의 내용은</p>
<pre><code class="language-json">{
    &quot;name&quot;: &quot;sample-package&quot;,
    &quot;version&quot;: &quot;1.0.0&quot;,
    &quot;description&quot;:&quot;&quot;,
    &quot;main&quot;:&quot; &quot;index.js&quot;,
    &quot;scripts&quot;: {
          &quot;test&quot;: &quot;echo \&quot;Error: no test specified\&quot; &amp;&amp; exit 1&quot;
    },
    &quot;keywords&quot;: [],
    &quot;author&quot;: &quot;&quot;,
    &quot;license&quot;: &quot;ISC&quot;
}</code></pre>
<p>위와 같다. </p>
<p>이렇게 디렉터리를 만드록 package.json을 만들면 설정은 끝이다.</p>
<pre><code class="language-js">// sample-package/index.js
console.log(&quot;require로 부르면 호출됩니다.&quot;);

module.exports = {
  add: (a,b) =&gt; a + b,
  sub: (a,b) =&gt; a - b,
  multi: (a,b) =&gt; a * b,
  div: (a,b) =&gt; a / b
}</code></pre>
<p>require() 함수로 모듈을 읽을 때 파일을 위에서부터 읽기 때문에 conosle.log를 먼저 실행 할 것이다. module.exports는 require를 사용해 불러왔을 때 반환하는 객체이다.</p>
<pre><code class="language-sh"># 현재 위치는 sample-package의 상위 폴더이다.
$ mkdir sample-test
$ cd sample-test
$ npm install ../sample-package</code></pre>
<p>sample-package를 설치한 후</p>
<pre><code class="language-js">// smaple-test/index.js

const calc = require(&quot;sample-package&quot;);

const a = 17;
const b = 3;

console.log(&quot;a + b = &quot;, calc.add(a,b));
console.log(&quot;a - b = &quot;, calc.sub(a,b));
console.log(&quot;a * b = &quot;, calc.multi(a,b));
console.log(&quot;a / b = &quot;, calc.div(a,b));</code></pre>
<p>하면 결과는</p>
<pre><code>require로 부르면 호출됩니다.
a + b = 20
a - b = 14
a * b = 51
a / b = 5.66666666666667</code></pre><p>와 같은 결과를 얻을 수 있다.</p>
<h2 id="package-설치-업데이트-삭제">Package 설치, 업데이트, 삭제</h2>
<h3 id="설치">설치</h3>
<p><code>npm install</code> 명령어로 패키지 설치를 진행할 수 있다.</p>
<ul>
<li><code>npm install</code> [&lt;@패키지 스코프(네임스페이스)&gt;/]&lt;패키지 명&gt;@&lt;tag/version/version range&gt;</li>
<li><code>npm i</code></li>
<li><code>npm add</code></li>
</ul>
<blockquote>
<p><strong>설치 옵션</strong></p>
</blockquote>
<ul>
<li>-D, -save-dev : devDependencies에 의존성 설정 추가</li>
<li>-P, -save-prod : dependencies에 의존성 설정 추가, 기본 값 코통은 사용하지 않음</li>
<li>-g, -global : 프로젝트 디렉토리가 아닌 node가 설치되어 있는 디렉터리의 [node_modules]에 의존성 패키지 설치</li>
</ul>
<p>-g 옵션으로 설치한 node_modules 데릭토리는 <code>npm root -g</code>명령으로 찾을 수 있다. -g 옵션으로 설치하려면 관리자 권한이 필요할 수도 있음.</p>
<blockquote>
<p><strong>패키지의 정보가 담긴 package.json</strong>을 받았는데 실질적으로 node_modules에 설치가 안되어 있을 때!!
<code>npm install</code> 명령으로 package.json에 있는 패키지들을 설치할 수 있다.</p>
</blockquote>
<p>그리고 package.json만으로 설치가 진행된다고 생각하기 쉽겠지만 사실은
package.json이 없이 package-lock.json 파일만 잇어도 설치가 된다.
<code>패키지 잠금</code> 부분에서 살펴보자.</p>
<h3 id="업데이트">업데이트</h3>
<ul>
<li>`npm update [-g] [패키지명1, 패키지명 2, ...]</li>
<li><code>npm up</code></li>
<li><code>npm upgrade</code></li>
<li>g 옵션은 install과 마찬가지로 node가 설치되어 있는 디렉토리의 의존성 패키지를 업데이트할 때 사용한다.</li>
</ul>
<h3 id="설치-패키지-확인하기">설치 패키지 확인하기</h3>
<ul>
<li><code>npm ls [@스코프/] 패키지명</code></li>
<li><code>npm list</code></li>
<li><code>npm la</code></li>
<li><code>npm ll</code></li>
</ul>
<h3 id="삭제">삭제</h3>
<ul>
<li><code>npm uninstall</code> [@스코프/] 패키지명[@버전] [-S| -D| -O]</li>
<li><code>npm remove</code></li>
<li><code>npm rm</code></li>
<li><code>npm r</code></li>
<li><code>npm un</code></li>
<li><code>npm unlink</code></li>
</ul>
<p>예시</p>
<pre><code class="language-sh">$ npm uninstall express --save
$ npm uninstall @types/react
$ npm uinstall jest --save-dev
$ npm uninstall plugin --save-optaional</code></pre>
<h2 id="npx">NPX</h2>
<p>npm은 명령어를 지정해 실행하는 스크립트 기능도 제공한다. 스크립트 기능은 앱 시작, 중지, 빌드, 배포, 테스트 등의 명령어를 터미널에 매번 입력하지 않고 package.json에 정의함으로써 조금 더 간편한 명령어를 실행하는 기능이다. 보통 스크립트는 [node_modules] 디렉토리 아래에 설치된 패키지에 있기 때문에 경로를 지정해야 하지만 npx를 이요하면 경로를 지정하지 않고 간편하게 사용할 수 있다.</p>
<h3 id="npm-스크립트-파일을-정의하기">npm 스크립트 파일을 정의하기</h3>
<p>Node.js 프로젝트의 package.json에는 scripts 항목이 존재한다. scripts에 등록된 항목들은 npm run 명령으로 실행할 수 있다.</p>
<pre><code class="language-sh"># sample-test의 상위 폴데어 test-scripts폴더를 생성한다.
$ mkdir test-scripts
$ cd test-scripts</code></pre>
<pre><code class="language-json">// npx 테스트용 package.json
{
    &quot;name&quot;: &quot;test-scripts&quot;,
    &quot;version&quot;: &quot;1.0.0&quot;,
      &quot;scripts&quot;: {
      &quot;hello&quot;: &quot;echo &#39;hello Node.js&#39;&quot;
    }
}</code></pre>
<p>참고로 json에는 주석을 달 수 없다. <code>//</code>는 임시로 그냥 적은 것이다.</p>
<p>터미널에서 실행해보자</p>
<pre><code class="language-sh">$ npm run hello
&gt; test-scripts@1.0.0 hello
&gt; echo &#39;hello Node.js&#39;

hello Node.js</code></pre>
<p>scripts에 hello로 등록된 명령이 실행된다. 이렇게 npm을 사용해 package.json의 scripts에 선언되어 있는 스크립트들을 실행할 수 있따.</p>
<blockquote>
<p>scripts에 정의하는 명령 중에 run 없이 사용할 수 있는 명령어</p>
</blockquote>
<ul>
<li>start</li>
<li>stop</li>
<li>test</li>
<li>restart</li>
</ul>
<pre><code class="language-json">{
    &quot;name&quot;: &quot;test-scripts&quot;,
    &quot;version&quot;: &quot;1.0.0&quot;,
      &quot;scripts&quot;: {
      &quot;hello&quot;: &quot;echo &#39;hello Node.js&#39;&quot;
      &quot;test&quot;: &quot;ehco &#39;test Node.js&#39;&quot;, // npm test
      &quot;start&quot;: &quot;ehco &#39;start Node.js&#39;&quot;, // npm start
      &quot;stop&quot;: &quot;ehco &#39;stop Node.js&#39;&quot;, // npm stop
      &quot;restart&quot;: &quot;ehco &#39;restart Node.js&#39;&quot;, // npm restart
    }
}</code></pre>
<h3 id="npx로-prettier-실행하기">npx로 prettier 실행하기</h3>
<p>NPX는 Node package eXecute의 약자로 Node 패키지 실행자라고도 한다.
Node.js 패키지는 대부분 프로젝트에 임포트해서 사용하지만 개발할 때는 프로젝트 실행, 관리, 테스트 등에 명령형 패키지를 다수 사용한다. 대표적으로 prettier, eslint, jest같은 포매팅, 문법 검사, 단위 테스트 도구들이 있다. 이렇나 패키지들을 실행하려면 <code>node_modules/.bin/{패키지명}</code> 경로로 명령어를 실행해야 한다. npx를 사용하면 <code>npx {패키지명}</code>처럼 경로를 생략해 실행할 수 있다.</p>
<pre><code class="language-sh"># test-npx 폴더 생성
$ mkdir test-npx
$ npm install prettier</code></pre>
<pre><code class="language-json">{
    &quot;name&quot;: &quot;prettier&quot;,
    &quot;version&quot;: &quot;2.5.1&quot;,
      &quot;description&quot;: &quot;Prettier is an opinionated code formatter&quot;,
      &quot;bin&quot;: &quot;./bin-prettier.js&quot;, // npx로 실행하는 명령어의 경로 지정
  // 생략...
}</code></pre>
<p>prettier 프로젝트의 package.json에 있는 bin 설정이 바로 npx 명령어에서 실행하는 파일이다.</p>
<p>다음과 같이 index.js파일을 생성하여 작성해보자.</p>
<pre><code class="language-js">function getRandomInt(
    min,
    max)/*주석도 포매팅 해준다*/
{
      return Math.floor(
      Math.random()
      * (max - min)) + min;
}

console.log(
  getRandomInt
  (10,20));</code></pre>
<p>터미널에서 npx 명령어로 prettier를 실행해보자</p>
<pre><code class="language-sh">
$ npx prettier index.js
$ npx prettier -w index.js
// npx prettier index.js 결과
function getRandomInt(min, max){
    /*주석도 포매팅해줍니다*/
    return Math.floor(Math.random() * (max - min)) + min;
}

console.log(getRandomInt(10, 20));

//npx prettier -w index.js의 결과
index.js 33ms</code></pre>
<p>npm prettier index.js를 실행해 index.js를 포매팅한 결과를 출력한다.
<strong>이때 포매팅이 index.js에 반영 되지는 않는다. -w 옵션을 추가해 실행하면 포매팅된 코드가 index.js 파일에 반영이 된다.</strong></p>
<p>같은 포매팅을 사용해야 가독성이 높아지고 파일 저장 시 혹은 저장소에 커밋이나 푸시하기 전에 자동으로 적용되도록 하면 유용하게 사용할 수 있다.</p>
<h2 id="yarn">yarn</h2>
<p>지금까지는 npm만 보았다. npm을 사용한 패키지 관리가 편해보이면서 쉽진 않을 것이다.
npm은 용량 문제, 패키지 내려받는 속도 문제, 보안 문제를 가지고 있다. 이를 신경 쓰지 않는다면 매우 편하겠지만 간과할 수 없는 일이다.</p>
<p>여러문제가 있는 npm의 node_modules를 사용하지 않고 다른 방법으로 패키지를 관리할 수 있는 방법 yarn은 이렇나 문제들을 해결할 목적으로 페이스북에서 만든 패키지 관리 프로그램이다.</p>
<p><strong>yarn</strong>은 버전 1과 yarn berry라고 부르는 버전 2가 있다.
버전 1은 npm과 거의 유사하며 패키지 설치가 조금 더 빠른 정도인데,
버전 2는 PnP(Plug n Play) 전력을 사용하여 node_modules를 사용하지 않고 의존성 패키지를 관리한다.</p>
<p>PnP 전략은 패키지를 적절한 위치에 꽂으면 바로 실행 하도록 단순화하는 데 있다.</p>
<p>이를 위해서 node_modules 디렉토리를 사용하지 않고, 의존성 찾기는 <code>.pnp.cjs</code>에 정리하고, 실제 의존성 패키지 파일은 압축 파일의 형태로 <code>.yarn 디렉토리</code> 아래에 <code>cache 디렉토리</code>에 저장한다.</p>
<p>cache 디렉토리 안에는 트리구조가아닌 끌어올림(hoisting)되어 평평하게 저장된다.</p>
<p>PnP 전략을 사용해 의존성 패키지를 코드 저장소에 바로 저장하면, 당연한 말이지만 추후에 서버 배포시 패키지 설치를 하지 않아도 된다. 이것을 제로 인스톨(Zero Install)이라고 한다.</p>
<p>제로 인스톨을 하면, 서버에 소스 코드를 배포할 때 패키지도 같이 설치가 된다. 그러면 패키지 설치 시점에 따라 버전이 달라져서 버그가 발생하는 일도 없어진다.</p>
<p>PnP를 사용함으로써 얻는 이점이 또 하나 있는데, 그것은 서버의 기동 속도가 빨라진다는 것이다.</p>
<p>애플리케이션이 동작하면 require로 불러오는 의존성 패키지가 어디있는지 불러오는 과정이 있는데, PnP를 사용하는 yarn2는 기동할 때 의존성 패키지를 찾는데 파일 시스템을 순회할 필요가 없기 때문에 그 시간만큼 빨리 기동할 수 있다.</p>
<h3 id="yarn-실습">yarn 실습</h3>
<pre><code class="language-sh"># test-yarn 폴더를 생성한다
$ mkdir test-yarn
$ cd test-yarn
$ corepack enable    # corepack 활성화. Linux/ Mac에서 permission이뜨면  sudo로 실행 해주자.
$ yarn init -2    # yarn 2버전 초기화</code></pre>
<p><strong>corepack</strong>은 Node.js 프로젝트에서 npm 이외의 패키지 매니저를 사용하는 기능이다.
yarn과 pnpm을 지원한다.</p>
<blockquote>
<p><strong>혹시 corepack 활성화 하는 과정이 에러가 발생한다면?</strong>
Node.js 버전이 낮아서 그럴 가능성이 높다.
<code>npm i -g corepack</code>
명령으로 corepack을 설치한 후 진행하면 된다.</p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/wrld_worthy/post/1b5a8bb9-a717-45bd-9edc-67339c1731c5/image.png" alt=""></p>
<p>README.md, package.json, yarn.lock, .pnp.cjs, .yarn, .git 등등 파일이 생성된 것을 확인할 수 있다.</p>
<blockquote>
<h3 id="npm과-yarn-명렁어"><strong>npm과 yarn 명렁어</strong></h3>
<table>
<thead>
<tr>
<th>명령어</th>
<th>npm</th>
<th>yarn</th>
</tr>
</thead>
<tbody><tr>
<td>의존성 설치</td>
<td>npm install</td>
<td>yarn</td>
</tr>
<tr>
<td>패키지 설치</td>
<td>npm install 패키지명</td>
<td>yarn add 패키지명</td>
</tr>
<tr>
<td>개발용 패키지 설치</td>
<td>npm install --save-dev 패키지명</td>
<td>yarn add -dev 패키지명</td>
</tr>
<tr>
<td>패키지 업데이트</td>
<td>npm update</td>
<td>yarn upgrade</td>
</tr>
<tr>
<td>패키지 삭제</td>
<td>npm uninstall 패키지명</td>
<td>yarn remove 패키지명</td>
</tr>
<tr>
<td>프로젝트 초기화</td>
<td>npm init</td>
<td>yarn init</td>
</tr>
<tr>
<td>스크립트 실행</td>
<td>npm run</td>
<td>yarn run</td>
</tr>
<tr>
<td>bin 패키지 실행</td>
<td>npm 패키지 명령어</td>
<td>yarn 패키지 명령어</td>
</tr>
</tbody></table>
</blockquote>
<p>yarn을 사용하여  chalck 패키지를 설치해보자.</p>
<pre><code class="language-sh">$ yarn add chalk</code></pre>
<p><img src="https://velog.velcdn.com/images/wrld_worthy/post/5ce041f2-882b-46fe-907b-5a207068968b/image.png" alt="">
<img src="https://velog.velcdn.com/images/wrld_worthy/post/14153c20-d655-497a-bd78-cbd9b2f39b0a/image.png" alt=""></p>
<p>package.json이 업데이트가 되고, .yarn 아래의 cache 디렉토리에 chalk 패키지의 압축 파일이 추가될 것이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] Node.js Express]]></title>
            <link>https://velog.io/@wrld_worthy/JavaScript-Node.js-Express</link>
            <guid>https://velog.io/@wrld_worthy/JavaScript-Node.js-Express</guid>
            <pubDate>Mon, 01 Jan 2024 11:19:49 GMT</pubDate>
            <description><![CDATA[<h1 id="express">Express</h1>
<p>Express는 기본 라이브러리가 아니기 때문에 설치가 필요하다.
Node.js와 같이 설치되는 npm 패키지 메니저로 설치하면 된다.</p>
<pre><code class="language-sh">$ npm install express</code></pre>
<h1 id="간단한-서버-만들기">간단한 서버 만들기</h1>
<p>localhost:3000으로 서버를 열어서 hello express를 응답하는 서버를 만들어 보자.
express를 설치한 폴더에서 js파일을 생성해준 뒤에</p>
<pre><code class="language-js">const express = require(&quot;express&quot;);
const app = express();

const port = 3000;

app.get(&quot;/&quot;, (req,res)=&gt;{    // &quot;/&quot; 요청시 콜백 함수 실행
  res.set({&quot;Content-type&quot;: &quot;text/plain; charset=utf-8&quot;});
  res.end(&quot;hello express&quot;);
});

app.listen(port, ()=&gt;{ // 서버 듣기 상태
  console.log(`START SERVER : use ${port}`);
});</code></pre>
<p>이제 실행하고 브라우저를 켜서 <code>localhost:3000</code>으로 접속해보자.</p>
<p><img src="https://velog.velcdn.com/images/wrld_worthy/post/737d7520-7ef1-4801-8975-ff7cd1514afc/image.png" alt=""></p>
<p>이와 같은 화면을 확인할 수 있다.</p>
<h1 id="api-서버-만들기">API 서버 만들기</h1>
<p>DB가 없기 때문이 휘발성 데이터로 저장하여 API로 POST와 Delete를 해보자.</p>
<pre><code class="language-js">const express = require(&quot;express&quot;);
const app = express();
let posts = [];
const port = 3000;

app.use(express.json());
app.use(express.urlencoded({extended: true}));

app.get(&quot;/&quot;,(req,res)=&gt;{
    res.json(posts);
});

app.post(&quot;/posts&quot;,(req,res)=&gt;{
    const {title, name, text} = req.body;

    posts.push({id:posts.length + 1, title, name, text, craetedDt: Date()});
    res.json({title, name, text});
});

app.delete(&quot;/posts/:id&quot;,(req,res)=&gt;{
    const id = req.params.id;   // app.delete에 설정한 path 정보에서 id값을 가져옴.
    const filteredPosts = posts.filter((post)=&gt; post.id !== +id); // 글 삭제.
    const isLenthChanged = posts.length !== filteredPosts.length; // 삭제 확인
    posts = filteredPosts;
    if(isLenthChanged){
        res.json(&quot;OK&quot;);
        return;
    }

    res.json(&quot;NOT CHANGED&quot;);
})

app.listen(port, ()=&gt;{ // 서버 듣기 상태
  console.log(`START SERVER : use ${port}`);
});</code></pre>
<p>위와 같이 서버를 실행하고 curl로 요청을 보내보자.</p>
<pre><code class="language-sh">$curl localhost:3000</code></pre>
<p><img src="https://velog.velcdn.com/images/wrld_worthy/post/f222ea76-4dd6-4e4b-a4f4-c03be3dc9fe8/image.png" alt=""></p>
<p>처음에 그냥 요청을 보내면 posts는 빈배열이기 때문에 []만 응답하게 된다.
post요청으로 배열에 값을 넣어보자</p>
<pre><code class="language-sh">$ curl -X POST -H &quot;Content-type: application/x-www-form-urlencoded&quot; -d &quot;title=제목1&amp;name=testman&amp;text=테스트 중&quot; http://localhost:3000/posts</code></pre>
<p><img src="https://velog.velcdn.com/images/wrld_worthy/post/721ed20c-5be6-4756-9e2c-4e7b4a5d7258/image.png" alt=""></p>
<p>데이터가 배열에 들어간게 확인이 된다.</p>
<pre><code class="language-sh">$curl localhost:3000</code></pre>
<p>다시 확인해보자
<img src="https://velog.velcdn.com/images/wrld_worthy/post/a7ac3b5a-fdad-4708-a067-6fa34e358c2f/image.png" alt="">
값이 잘 들어가 있고 응답이 잘 왔다.</p>
<p>이제 삭제해 보자</p>
<pre><code class="language-sh">$ curl -X DELETE localhost:3000/post/1</code></pre>
<p><img src="https://velog.velcdn.com/images/wrld_worthy/post/12893f66-a2e7-4428-8abd-c516afa751eb/image.png" alt="">
이미 삭제한 id로 삭제를 다시 요청했더니 <code>NOT CHANGED를 응답 받았다.</code></p>
<p>다시 조회해보니
<img src="blob:https://velog.io/80d769c0-fe21-47ac-8c70-a5b8394c4e6c" alt="업로드중..">
빈 배열로 응답받았다. 성공적으로 삭제된 것을 확인할 수 있었다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScipt] Node.js 이벤트 기반 아키텍처]]></title>
            <link>https://velog.io/@wrld_worthy/JavaScipt-Node.js-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EA%B8%B0%EB%B0%98-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98</link>
            <guid>https://velog.io/@wrld_worthy/JavaScipt-Node.js-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EA%B8%B0%EB%B0%98-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98</guid>
            <pubDate>Mon, 01 Jan 2024 07:44:52 GMT</pubDate>
            <description><![CDATA[<h1 id="이벤트-기반-아키텍처">이벤트 기반 아키텍처</h1>
<p>Node.js처럼 싱글 스레드로 요청을 처리하는 서버가 있다면, 한 번에 하나를 처리하는 서버에 0.1초가 걸리는 요청이 100개가 들어온다면 마지막에 요청한 사람은 10초를 기다려야만 응답을 받을 수 있다.</p>
<p>멀티 스레드를 지원하는 언어라면 스레드를 100개 만들어서 동시에 처리할 수 있지만 싱글 스레드인 <code>자바스크립트는 싱글 스레드이기 때문에 불가능하다.</code></p>
<p><strong>그럼 어떻게 동시에 처리를 할 수 있을까??</strong></p>
<p>방법은 이벤트 기반 아키텍처를 사용하는 것이다.</p>
<p>콜 스택에 쌓인 작업을 다른 곳에서 처리한 다음 처리가 완료되엇을 대 알림을 받으면 스레드가 하나라도 빠르게 처리할 수 있다.</p>
<p>예를 들면 커피숍 카운터에서 주문을 완료하면 주문은 제조를 하는 직원에게 건네진다.</p>
<p>카운터는 커피가 나올 때까지 기다리지 않고 다음 고객의 주문을 받는다. </p>
<p>진동 벨을 받은 고객은 진동 벨이 울릴 때까지 대기했다가 울리면 주문 음료를 받아가는 것이다. </p>
<p>이때 줄을 섰던 순서와 다르게 빠르게 제조된 음료가 먼저 나올 수 있다.</p>
<p>이런 원리가 이벤트 기반 아키텍처이다.</p>
<pre><code class="language-javascript">console.log(&quot;1&quot;);
setTimeout(()=&gt;console.log(2),1000);
console.log(&quot;3&quot;);</code></pre>
<p>결과</p>
<pre><code>1
3
(1초 후)
2</code></pre><p>흐름은
console.log(&quot;1&quot;)이 콜 스택에 쌓인 후 바로 1을 출력하며 빠져나가고</p>
<p>setTimeout(()=&gt;console.log(&quot;2&quot;),1000)이 콜 스택에 쌓인다.</p>
<p>setTimeout(()=&gt;console.log(&quot;2&quot;),1000)은 Node.js의 API로 실행되고</p>
<p>지정된 시간 만큼 대기한다.</p>
<p>대기하는 동안 console.log(&quot;3&quot;)이 실행되어 콜 스택에 쌓이고 3을 출력하면서 빠져나간다.</p>
<p>1초 후 setTimeout(()=&gt;console.log(&quot;2&quot;),1000)는 이벤트 루프의 태스크 큐에 추가되고 이벤트 루프의 각 단계를 진행하며 콜 스택에 나중에 다시 추가된다.</p>
<p>콜백함수를 실행하면서 콜 스택을 빠져나간다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] Node.js 환경 설정 (MAC)]]></title>
            <link>https://velog.io/@wrld_worthy/JavaScript-Node.js-%ED%99%98%EA%B2%BD-%EC%84%A4%EC%A0%95-MAC</link>
            <guid>https://velog.io/@wrld_worthy/JavaScript-Node.js-%ED%99%98%EA%B2%BD-%EC%84%A4%EC%A0%95-MAC</guid>
            <pubDate>Mon, 01 Jan 2024 03:36:41 GMT</pubDate>
            <description><![CDATA[<h1 id="nodejs-환경-설정">Node.js 환경 설정</h1>
<h2 id="공식-사이트-접속">공식 사이트 접속</h2>
<ol>
<li><a href="https://nodejs.org">Node.js 공식 사이트</a>에 접속한다.</li>
<li>LTS(Long Term Stability) 버전으로 설치 파일을 내려받는다.
<img src="https://velog.velcdn.com/images/wrld_worthy/post/d0cb1f64-6474-44b1-a5e4-11039ae02b23/image.png" alt=""></li>
<li>설치한다.</li>
<li>설치 후 terminal에서
<img src="https://velog.velcdn.com/images/wrld_worthy/post/83e03055-e094-4643-b84c-05eebf78caf2/image.png" alt=""><pre><code class="language-sh">$ node --version</code></pre>
명령어로 version이 확인이 된다면 성공적으로 설치가 완료된 것이다.
( 이전에 설치한 버전이 있기 때문에 따로 설치하지는 않았다. )</li>
</ol>
<h2 id="git-설치">Git 설치</h2>
<p>git은 컴퓨터 파일의 변경 사항을 추적하고 사용자 간의 공동 작업을 조율하는 분산 버전 관리 시스템이다.</p>
<p><a href="https://git-scm.com">Git 공식 사이트</a>에 접속하여 OS에 맞는 버튼을 눌러서 공식 사이트에서 유도하는 대로 설치를 진행하면 끝이다.</p>
<p>window는 과정이 좀 긴 것을 알고 있는데, mac은 brew가 설치되어 있다면 brew를 통해서 설치만하면 된다.</p>
<p>귀찮다면</p>
<pre><code class="language-sh">$ brew install git</code></pre>
<p>으로 설치하면 된다.</p>
<h2 id="vscode-설치">vsCode 설치</h2>
<p><a href="https://visualstudio.com">VisualStudio</a>에 접속하여 OS에 맞는 설치파일을 다운로드 후 설치만 해주면 된다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JavaScript] Node.js]]></title>
            <link>https://velog.io/@wrld_worthy/JavaScript-Node.js</link>
            <guid>https://velog.io/@wrld_worthy/JavaScript-Node.js</guid>
            <pubDate>Mon, 01 Jan 2024 02:44:16 GMT</pubDate>
            <description><![CDATA[<h1 id="javascript">Javascript</h1>
<p>자바 스크립트는 기본적으로 VC(VsCode)를 설치하면 사용할 수 있다.</p>
<p>각 종 Extensions는 검색해보는게 하나하나 더 정확하고 좋을 것이다.</p>
<h1 id="nodejs">Node.js</h1>
<p><strong>Node.js</strong>의 정의는 공식 사이트에 정의되어 있다.</p>
<blockquote>
<p>Node.js®는 오픈 소스, 크로스 플랫폼 자바스크립트 런타임 환경입니다.</p>
</blockquote>
<p>말 그대로 JavaScript를 사용하면서 노드를 통해 다양한 JS 애플리케이션을 실행할 수 </p>
<p>있도록 런타임을 제공하는 것이다.</p>
<blockquote>
<p>Node.js의 기본적인 목적은 JavaScirpt의 단일 언어의 사용 목적을 확장하며, 브라우저만이 아닌 높은 성능의 <strong>서버 사이드 애플리케이션</strong>을 쉽게 구축하기 위함에 있다.</p>
</blockquote>
<h2 id="특징">특징</h2>
<ul>
<li>Node.js는 JS를 브라우저만이 아닌 서버에서도 사용할 수 있도록 만들어진 런타임 프로그램이다.</li>
<li>Node.js는 V8 JS 엔진 위에서 동작한다.</li>
<li>런타임이다.</li>
<li>Node.js는 웹 서버와 같이 확장성 있는 네트워크 프로그램을 제작하기 위해 만들어졌다.</li>
</ul>
<p>Node.js는 V8 JavaScript 엔진을 사용하는데, 이 엔진은 구글 크롬 브라우저에서 </p>
<p>사용되는 엔진이지만</p>
<p>브라우저 밖의 환경에서도 사용할 수 있도록하며</p>
<p>이 때문에 브라우저의 보안 제약 사항이 적용되지 않고 사용할 수 있다.</p>
<p>일반 적으로는 JavaScript로 파일을 읽거나 쓸 수 없는데, </p>
<p>그 이유는 <code>JavaScript는 기본적으로 브라우저에서 구동되기 때문이다.</code></p>
<p>Node.js는 이러한 제한적인 환경을 브라우저 밖에서 런타임을 제공함으로써 언어의 범위를 확장시켜 </p>
<p>컴퓨터 시스템에 접근이 가능하도록 하여 서버 사이드 애플리케이션을 쉽게 구축할 수 있다.</p>
<p>Node.js는 다양한 라이브러리를 제공하여 아파치 톰캣 등 별도의 처리 과정이 없이 웹서버 동작이 가능하다.(ex: HTTP)</p>
<p><strong>이벤트 기반</strong>
Node.js는 이벤트 기반, 논 블록킹 I/O를 구현하고 있다.
미리 지정해둔 이벤트가 발생했을 시에 콜백함수를 사용하여 처리하고, 다음 이벤트가 발생할 때까지 대기한다.</p>
<p><strong>이벤트 루프</strong>
이벤트 루프는 여러 이벤트가 동시에 발생했을 때, 어떤 순서로 콜백함수를 호출할지 이벤트 루프가 판단한다.</p>
<p>노드는 이벤트가 종료될 때까지 이벤트 처리를 위한 작업을 반복한다.</p>
<p><strong>논 블록킹 I/O</strong>
작업에는 동시에 실행될 수 있는 작업, 동시에 실행될 수 없는 작업 2가지가 있다.
예시로 파일 시스템에 접근, 네트워크를 통한 요청 작업은 I/O의 일종으로,
이러한 작업을 할 때에는 비동기 방식으로 Non-Blocking으로 처리한다.
<strong>비동기</strong>는 이전 작업이 완료될 때까지 대기하지 않고 동시에 작업을 수행하는 것.
<strong>동기</strong>는 이전 작업이 끝나야만 다음 작업을 수행할 수 있는 것이다.
함수 호출시 당장 실행하는 것이 아니라, 어느 곳에 쌓아서 요청을 동시에 처리하고 요청이 완료된 스택을 사용하여 순서대로 처리한다는 뜻이다.
( blocking, non-blocking, synchronous, asynchronous 의 관계가 좀 헷갈리는데 따로 포스팅 하겠다. )</p>
<p><strong>싱글 스레드</strong>
위의 모든 것들과 관련이 되어있다. 바로 싱글 스레드이다.
Node.js는 싱글 스레드이기 때문에 위와 같은 처리가 필요한 것이다.</p>
<p>Node.js는 실글 스레드, 논 블로킹 모델로 싱글 스레드가 혼자서 모든 일들을 처리하지만 요청 순서가아닌 논 블로킹 방식으로 이전 작업이 완료될 때까지 대기하지 않고 다음 작업을 수행한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[PintOS] Project3 Virtual Memory]]></title>
            <link>https://velog.io/@wrld_worthy/PintOS-Project3-Virtual-Memory</link>
            <guid>https://velog.io/@wrld_worthy/PintOS-Project3-Virtual-Memory</guid>
            <pubDate>Wed, 27 Dec 2023 12:07:18 GMT</pubDate>
            <description><![CDATA[<h1 id="1-pg_round_downva">1. pg_round_down(va)</h1>
<p>가상 주소를 해당 주소가 속한 페이지의 시작 주소로 내림하는 기능을 수행한다. 예를 들어, 4KB 페이지 크기를 가정할 때, 주소 0x12345는 0x12000으로 내림된다.</p>
<p>페이지 폴트가 발생하거나, 스택 영역의 주소가 있는 페이지에 접근하려고 할 때, 그 주소는 page의 주소가 아닌 잘못된 주소를 가리키고 있을 가능성이 있다. 그래서 page의 시작 주소로 맞춰주기 위해서 사용하면 된다.</p>
<h1 id="2-check_address">2. check_address</h1>
<p><img src="https://velog.velcdn.com/images/wrld_worthy/post/dd735b5a-e635-4636-bfce-1474b734215f/image.png" alt=""></p>
<p>기존 check_address는 포인터가 가리키는 주소가 사용자 영역인지 확인하고, 페이지가 있는지 확인하여 
exit(-1)을 실행하도록 하는 함수였다.</p>
<p>하지만 project3에서는 page_fault_handler를 구현하면서 page가 없는 경우 page를 할당해줘야 하기 때문에, 무조건 프로세스를 종료하는 조건문을 수정해줘야한다.
<img src="https://velog.velcdn.com/images/wrld_worthy/post/8939c2f2-f317-48f5-89b6-17a51b58888b/image.png" alt=""></p>
<p>페이지의 유무를 판단해야하는 시스템 콜의 경우에는</p>
<pre><code class="language-c">void check_page(void* addr){
    if (pml4_get_page(thread_current()-&gt;pml4, addr) == NULL) {
        exit(-1);
    }
}</code></pre>
<p>함수를 따로 만들어서 추가해주었다.</p>
<p>하지만 userprog 테스트 부분에서 대부분이 통과가 되지 않는 현상이 생기는데,</p>
<pre><code class="language-c">static void page_fault(struct intr_frame* f){

    ...code

    not_present = (f-&gt;error_code &amp; PF_P) == 0;
    write = (f-&gt;error_code &amp; PF_W) != 0;
    user = (f-&gt;error_code &amp; PF_U) != 0;

    //exit(-1);

#ifdef VM
    ...</code></pre>
<p>page fault가 발생 했을 때 exception에서 무조건 exit(-1)을 하던 것을 지워서 발생했던 거였다.</p>
<p><img src="https://velog.velcdn.com/images/wrld_worthy/post/2a775cd5-5048-4155-8ef3-40b9e6bfcb89/image.png" alt="">
이 처럼 exit(-1)을 vm이 아닐 때 사용하도록 처리를 했다.</p>
<h1 id="3-exec-read-테스트-케이스-passing">3. exec, read 테스트 케이스 passing</h1>
<p><img src="https://velog.velcdn.com/images/wrld_worthy/post/70f472bc-2fd0-4fa0-bb2b-4db4c0f777f7/image.png" alt="">
기존 코드이다. project2에서는 문제 없이 테스트를 통과 했었다.
하지만 project3에 넘어오면서 
<img src="https://velog.velcdn.com/images/wrld_worthy/post/8970007c-900e-4d82-b720-0ce02801b123/image.png" alt="">
안되는 케이스들이 발생하기 시작했는데, read나 fork 부분에서 발생하는 문제였다.</p>
<p>원인을 파악하기 전에 팀원 분의 조언을 얻어서 코드를 수정했다.</p>
<p><img src="https://velog.velcdn.com/images/wrld_worthy/post/4a0cf2b1-f4e5-467f-ade7-97b9d1268d73/image.png" alt="">
일단 원인은 위와 같은 상황이 었다.
argv[4]에 예측할 수 없는 다른 값이 있을 수 있어서 그런 것같다.
NULL넣어서 해결할 수 있었다.
<img src="https://velog.velcdn.com/images/wrld_worthy/post/c6862072-b58c-495d-8912-ad81f37ceaf6/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[CS] Lazy Loading]]></title>
            <link>https://velog.io/@wrld_worthy/CS-Lazy-Loading</link>
            <guid>https://velog.io/@wrld_worthy/CS-Lazy-Loading</guid>
            <pubDate>Fri, 15 Dec 2023 07:30:10 GMT</pubDate>
            <description><![CDATA[<h1 id="lazy-loading">Lazy Loading</h1>
<p><strong>Lazy Loading</strong>은 프로그램이 실제로 필요로 하는 데이터나 코드를 메모리에 로드하는 것을 필요한 순간까지 지연시키는 방식을 말한다. 시스템의 메모리 사용을 최적화하고, 전반적인 성능 향상을 가저온다.</p>
<h2 id="특징">특징</h2>
<ol>
<li><strong>지연된 페이지 로딩</strong>: 프로그램이 시작할 때, 몯느 코드나 데이터를 메모리에 즉시 로드하지 않는다.
대신 해당 코드나 데이터에 접근하는 순간에만 해당 부분을 메모리에 로드한다.<br></li>
<li><strong>효율적인 메모리 사용</strong>: 필요하지 않은 부분은 메모리에 로드되지 않으므로, 전체적인 메모리 사용량을 줄일 수 있다. 이는 특히 메모리가 제한적인 시스템에서 유용하다.<br></li>
<li><strong>페이지 폴트를 통한 로딩</strong>: 프로그램이 아직 메모리에 로드되지 않은 주소를 참조하면 페이지 폴트가 발생하고, 이를 처리하는 과정에서 필요한 페이지가 메모리에 로드된다.<br></li>
<li><strong>성능 최적화</strong>: 초기 로딩 시간이 단축되고, 사용되지 않는 코드나 데이터에 대한 메모리 낭비를 방지한다.</li>
</ol>
<h2 id="방식">방식</h2>
<ol>
<li><strong>프로그램 실행</strong>: 프로그램이 실행되면, 운영체제는 해당 프로그램의 실행 파일을 분석하고, 필요한 메모리 구조를 설정한다.<br></li>
<li><strong>페이지 테이블 설정</strong>: 초기 페이지 테이블 설정 시, 실제 메모리에 존재하지 않는 페이지들은 <code>Not Present</code>상태로 표시.<br></li>
<li><strong>메모리 접근 시도</strong>: 프로그램이 특정 메모리 주소에 접ㄱ느하려고 할 때, 해당 주소가 메모리에 존재하지 않으면 페이지 폴트가 발생한다.<br></li>
<li><strong>페이지 폴트 처리</strong>: 운영체제는 페이지 폴트를 처리하기 위해 필요한 페이지를 디스크에서 찾아 메모리에 로드하고, 페이지 테이블을 업데이한다.<br></li>
<li><strong>프로세스 재개</strong>: 페이지 로딩이 완료되면, 프로세스는 중단된 시점부터 실행을 재개한다.</li>
</ol>
<h2 id="장단점">장단점</h2>
<h3 id="장점">장점</h3>
<ul>
<li>메모리 사용량 감소</li>
<li>초기 프로그램 로딩 시간 단축</li>
<li>전체 시스템 성능 향상</li>
</ul>
<h3 id="단점">단점</h3>
<ul>
<li>페이지 폴트 처리로 인한 오버헤드 발생 가능성이 높아짐</li>
<li>프로그램 실행 중 메모리 로딩으로 인한 지연 발생 가능성이 높아짐</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[CS] Translation Lookaside Buffer(TLB)]]></title>
            <link>https://velog.io/@wrld_worthy/CS-Translation-Lookaside-BufferTLB</link>
            <guid>https://velog.io/@wrld_worthy/CS-Translation-Lookaside-BufferTLB</guid>
            <pubDate>Fri, 15 Dec 2023 07:04:07 GMT</pubDate>
            <description><![CDATA[<h1 id="tlb">TLB</h1>
<p><strong>TLB</strong>는 컴퓨터 시스템의 가상 메모리 관리에서 중요한 역할을 하는 캐시의 한 형태이다. 가장 최근에 사용된 가상 주소와 그에 해당하는 물리적 주소 매핑을 저장하여, 가상 주소를 물리적 주소로 변환하는 과정의 효율성을 높인다. 일종의 캐싱과 같다.</p>
<h2 id="기능">기능</h2>
<p><strong>주소 변환 가속화</strong>
TLB는 가상 주소를 물리적 주소로 변환하는 과정을 가속화한다. 페이지 테이블을 매번 조회하는 대신, TLB는 최근에 사용된 주소 변환을 빠르게 제공한다.
<strong>효율적인 메모리 접근</strong>
TLB를 사용함으로써 메모리 접근 시간이 단축되고, 시스템의 전반적ㅇ니 성능이 향상된다.
<strong>페이지 테이블 오버헤드 감소</strong>
TLB는 페이지 테이블 접근 횟수를 줄여, 페이지 테이블로 인한 오버헤드를 감소시킨다.</p>
<h2 id="원리">원리</h2>
<ol>
<li><strong>TLB</strong> 조회:프로세스가 메모리에 접근할 때, 시스템은 먼저 TLB에서 해당 가상 주소의 매핑을 조회한다.</li>
<li><strong>히트와 미스</strong>: TLB미스가 발생하면, 시스템은 페이지 테이블을 조회하여 필요한 주소 변환을 수행하낟. 이후, 이 매핑은 TLB에 저장되어 향후 접근을 가속화한다.</li>
<li><strong>TLB업데이트</strong>: TLB는 제한된 크기를 가지므로, 새로운 주소 매핑이 추가될 때 오래된 매핑을 교체한다.</li>
</ol>
<h2 id="중요성">중요성</h2>
<ul>
<li>TLB는 메모리 접근 시간을 크게 줄여주는 중요한 요소이다. 특히, 페이지 테이블이 여러 레벨로 구성된 복잡한 시스템에서 TLB의 역할은 더욱 중요하다.</li>
<li>TLB는 시스템의 성능에 직접적ㅇ니 영향을 미치므로, TLB의 크기와 관리 전략은 시스템 설꼐에서 중요한 고려 사항이다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[CS] Page Replacement Policy]]></title>
            <link>https://velog.io/@wrld_worthy/CS-Page-Replacement-Policy</link>
            <guid>https://velog.io/@wrld_worthy/CS-Page-Replacement-Policy</guid>
            <pubDate>Fri, 15 Dec 2023 04:55:10 GMT</pubDate>
            <description><![CDATA[<p>프로세스가 메모리에 접근하려고 할 때, 운영 체제제는 가상 메모리 주소를 사용하여 이루어진다. 하지만 실제 메모리는 물리 메모리 주소에 로드되어 있기 때문에 가상 주소는 물리 주소로 변환되어야 한다.
MMU에서 가상 메모리 페이지 테이블을 사용하여 가상 주소와 매핑된 실제 물리 메모리 주소로 변환하여 접근할 수 있게 해준다.
이때 <code>요청된 가상 주소가 해당 페이지 테이블 엔트리에 없거나</code>, <code>물리적 메모리에 없고 스왑 영역에 있거나</code>, <code>아직 할당되지 않은 메모리 영역을 가리키고 있을 때</code> <strong>페이지 폴트가 발생</strong>하게 되고, 페이지를 교체하여 처리해야한다면 어떤 페이지 프레임을 선택하여 교체를 해야한다. 이때 사용하는 정책이다.</p>
<h1 id="페이지-교체-정책">페이지 교체 정책</h1>
<p><strong>페이지 교체 정책</strong>은 컴퓨터 시스템의 가상 메모리 관리에서 중요한 부분이다. 이 정책은 시스템의 물리적 메모리가 가득 찼을 때, 어떤 페이지를 제거하고 새 페이지를 로드할지 결정하는 방법을 제공한다. 효율적인 페이지 교체 정책은 시스템의 전반적인 성능과 응답 시간에 큰 영향을 미친다.</p>
<h2 id="정책">정책</h2>
<ol>
<li><strong>FIFO</strong><ul>
<li>가장 오래전에 메모리에 로드된 페이지를 제거한다.</li>
<li>구현이 간단하지만, 자주 사용되는 페이지가 제거될 수 있다는 단점이 있다.</li>
</ul>
</li>
<li><strong>LRU(Least Recently Used)</strong><ul>
<li>가장 오랫동안 사용하지 않았던 데이터는 앞으로도 사용할 확률이 적다는 생각으로 만들어졌다.</li>
<li>시간 지역성(temporal locality)성질 고려(최근에 참조된 페이지가 가까운 미래에 다시 참조될 가능성이 높은 성질)</li>
<li>가장 오랫동안 사용되지 않은 페이지를 제거한다.</li>
<li>최근 사용 패턴을 반영하여 효율적이지만, 구현이 복잡하고 오버헤드가 발생할 수 있다.</li>
<li>프로세스가 주기억장치에 접근할때마다 참조된 페이지 시간을 기록해야 하므로 막대한 오버헤드가 발생</li>
</ul>
</li>
<li><strong>LFU(Least Frequently Used)</strong><ul>
<li>사용 빈도가 가장 낮은 페이지를 제거한다.</li>
<li>사용 빈도를 기반으로 하지만, 초기에 자주 사용된 페이지가 장기적으로 불필요해질 때 비효율적일 수 있다.</li>
<li>가장 최근에 불러온 페이지가 교체될 수 있음, 구현 더 복잡, 막대한 오버헤드 발생.</li>
</ul>
</li>
<li><strong>Optimal Page Replacement</strong><ul>
<li>미래에 가장 오랫동안 사용되지 않을 페이지를 제거한다.</li>
<li>이론적으로최적이지만, 실제 시스템에서는 미래의 사용 패턴을 예측할 수 없어서 구현이 불가능하다.</li>
</ul>
</li>
<li><strong>Clock Alogorithm</strong><ul>
<li>FIFO와 유사하지만 각 페이지에 사용 비트를 두어 최근 사용 여부를 체크한다.</li>
<li>사용 비트가 설정된 페이지는 한 번의 기회를 더 받고, 사용 비트가 클리어도니 페이지가 교체 대상이 된다.</li>
</ul>
</li>
<li><strong>Random Replacement</strong><ul>
<li>제거할 페이지를 무작위로 선택한다.</li>
<li>구현이 매우 간단하지만, 성능을 예측하기 어렵다.</li>
</ul>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[CS]  가상메모리 Page]]></title>
            <link>https://velog.io/@wrld_worthy/CS-%EA%B0%80%EC%83%81%EB%A9%94%EB%AA%A8%EB%A6%AC-Page</link>
            <guid>https://velog.io/@wrld_worthy/CS-%EA%B0%80%EC%83%81%EB%A9%94%EB%AA%A8%EB%A6%AC-Page</guid>
            <pubDate>Fri, 15 Dec 2023 02:32:56 GMT</pubDate>
            <description><![CDATA[<h1 id="page">Page</h1>
<p><strong>Page</strong>는 가상 메모리 시스템에서 사용되는 기본 단위로, 메모리는 여러 페이지로 나뉜다. 각 페이지는 일반적으로 몇 킬로바이트(KB) 크기를 가지며, 가상 주소 공간을 물리적 메모리에 매핑하는데 사용된다.</p>
<p>페이지는 프로그램이 메모리에 접근할 때 사용되는 <strong>추상화된 개념</strong>으로, 프로그램은 <strong>연속적인 가상 메모리 주소</strong>를 사용하지만, <strong>실제 물리적 메모리는 불연속적일 수 있다.</strong></p>
<h2 id="사용하는-이유">사용하는 이유</h2>
<ol>
<li><strong>메모리 관리의 효율성</strong>: 페이지를 사용하면 메모리 관리가 더 효율적이게 된다. 프로그램은 필요한 메모리만 사용할 수 있으며, 전체 메모리 공간을 연속적으로 할당할 필요가 없다.<br></li>
<li><strong>프로세스 간 메모리 격리</strong>: 각 프로세스는 독립적인 가상 주소 공간을 가지는데, 한 프로세스의 메모리 접근이 다른 프로세스에 영향을 미치지 않는다.<br></li>
<li><strong>스왑 아웃</strong> /  <strong>스왑 인</strong>: 시스템 메모리가 부족할 때, 사용되지 않는 페이지를 디스크로 옮기고(<code>스왑 아웃</code>)
필요할 때 다시 메모리로 가져올 수 있다.(<code>스왑 인</code>)</li>
</ol>
<h2 id="단점">단점</h2>
<ol>
<li><strong>페이지 폴트 오버헤드</strong>: 메모리에 없는 페이지에 접근하려 할 때 페이지 폴트가 발생할 수 있다.</li>
<li><strong>페이지 테이블 관리</strong>: 페이지 테이블을 관리하는 데 추가적인 메모리와 처리 시간을 요한다.</li>
</ol>
<h2 id="예시">예시</h2>
<p><strong>운영 체제의 메모리 관리</strong>: 대부분의 현대 운영 체제는 페이지 기반의 가상 메모리 시스템을 사용한다. 이를 통해 프로세스는 물리적 메모리의 한계를 넘어서는 메모리를 사용할 수 있다.</p>
<p><strong>스왑 공간</strong>: Linux와 같른 운영 체제는 디스크에 스왑 공간을 할당하여, 사용되지 않는 페이지를 저장한다. 이는 시스템 메모리가 부족할 때 매우 유용하다.</p>
<h2 id="page-종류">Page 종류</h2>
<p><strong>페이지</strong>는 가상 메모리 시스템에서 다양한 역할을 수행하는데, 종류에 따라 다른 역할을 수행한다.</p>
<ol>
<li><strong>일반 페이지</strong><ul>
<li>대부분 프로그램 데이터와 코드가 저장되는 표준 페이지이다.</li>
<li>이 페이지들은 프로그램의 실행 중에 메모리가 로드되고, 필요에 따라 디스크로 스왑된다.</li>
</ul>
</li>
<li><strong>공유 페이지</strong><ul>
<li>여러 프로세스에 의해 공유되는 페이지이다.</li>
<li>예를들어, 동일한 라이브러리나 실행 파일으 사용하는 여러 프로세스가 메모리 상의 같은 페이지를 공유할 수 있다.</li>
</ul>
</li>
<li><strong>스왑 페이지</strong><ul>
<li>물리적 메모리가 부족할 때, 사용되지 않는 페이지를 디스크의 스왑 공간에 저장하는데 사용되는 페이지.</li>
<li>필요할 때 다시 메모리로 로드 될 수 있다.</li>
</ul>
</li>
<li><strong>커널 페이지</strong><ul>
<li>운영 체제의 커널에 의해 사용된느 페이지.</li>
<li>이 페이지들은 시스템의 핵심 기능ㅇ르 수행, 일반 사용자 프로세스와 분리되어 관리된다.</li>
</ul>
</li>
<li><strong>페이지 테이블 페이지</strong><ul>
<li>가상 주솔르 물리적으로 매핑하는데 사용되는 페이지 테이블 자체가 저장되는 페이지이다.</li>
<li>시스템의 핵심 기능을 수행하며, MMU에 의해 사용 관리된다.</li>
</ul>
</li>
<li><strong>제로 페이지</strong><ul>
<li>초기화된 데이터를 포함하지 않는, 즉 모든 비트가 0으로 설정된 페이지이다.</li>
<li>새로운 메모리 할당 시, 빠르게 초기화된 페이지를 제공하기 위해 사용된다.</li>
</ul>
</li>
<li><strong>Anonymous Page</strong></li>
<li><strong>file-backed Page</strong></li>
</ol>
<h1 id="anonymous-page">Anonymous Page</h1>
<p><strong>Anonymous Page</strong>는 파일 시스템의 어떠 파일과도 연결되지 않은 메모리 페이지이다. 이 페이지는 프로세스의 실행 중에 동적으로 생성된다. 특정 파일이나, 초기화된 데이터 소스와 연결이 되어있지 않다.</p>
<p>주로 스택이나 힙과 같은 동적 메모리 영역에 사용되며, 프로그램이 실행중에 변수를 할당하거나 메모리를 동적으로 할당할 때 사용된다.</p>
<p>대부분의 운영 체제는 새로운 Anonymous Page를 0또는 다른 기본 값으로 초기화한다.
메모리가 부족할 때는 이 페이지를 디스크의 스왑 영역으로 이동시킬 수 있다.</p>
<h1 id="file-backed-page">File-Backed Page</h1>
<p><strong>file-backed Page</strong>는 파일 시스템상의 특정 파일과 직접적으로 연결된 메모리 페이지이며, 디스크 상의 파일의 내용을 반영한다.</p>
<p>파일 매핑된 메모리, 공유 라이브러리, 실행 파일의 코드 영역 등에 사용되며, mmap() 시스템 호출을 사용하여 파일을 메모리에 매핑할 때 생성된다.</p>
<p>파일 전체 내용을 메모리에 즉시 로드하는 대신, 필요한 부분만 페이지 단위로 로드되고,
페이지는 스왑 아웃될 수 있고 변경된 경우 원본 파일에 변경 사항이 다시 기록될 수 있다.</p>
<h1 id="anonymous-page-file-backed-page-차이점">Anonymous Page/ File-Backed Page 차이점</h1>
<ul>
<li><strong>데이터 소스</strong>: Anonymous Page는 파일과 연결되어 있지 않고, Fil-Backed Page는 특정 파일과 연결된다.</li>
<li><strong>생성 방식</strong>: Anonymous Page는 동적 메모리 할당과 같은 프로세스의 내부 작업에 의해 생성되는 반면, File_Backed Page는 파일 매핑을 통해 생성된다.</li>
<li><strong>스왑 아웃 동작</strong>: Anonymous Page는 스왑 아웃 시 디스크의 스왑 공간에 입시로 저장되지만, File-Backed Page는 원본 파일에 변경 사항이 기록될 수 있다.</li>
</ul>
<h1 id="유사한-방법">유사한 방법</h1>
<h2 id="세그멘테이션segmentation">세그멘테이션(Segmentation)</h2>
<p><strong>세그멘테이션</strong>은 컴퓨터 메모리 관리에 사용된는 주용한 개념으로, 메모리를 의미있는 단위인 <code>세그먼트</code>로 나누는 방식을 말한다. 세그멘테이션은 프로그램의 다양한 부분들(ex:코드, 데이터, 스택)을 서로 다른 세그먼트로 분리하여 관리한다.</p>
<h3 id="특징">특징</h3>
<ol>
<li><strong>가변 크기의 세그먼트</strong>: 각 세그먼트는 가변적인 크기를 가질 수 있으며, 프로그램의 특정 논리적 단위(함수, 배열, 객체 등)에 해당한다.<br></li>
<li><strong>세그먼트 테이블</strong>: 시스템은 각 세그먼트의 시작 주소와 길이를 저장하는 세그먼트 테이블을 유지한다. 이 테이블은 가상 주소를 물리적 주소로 변환하는데 사용된다.<br></li>
<li><strong>논리적 주소 공간</strong>: 세그멘테이션은 논리적 주소 공간을 사용한다. 논리적 주소는 세그먼트 번호와 세그먼트 내 오프셋으로 구성되어있다.</li>
</ol>
<h3 id="page와-차이">Page와 차이</h3>
<p><strong>메모리 블록의 크기</strong>: 페이지는 고정 크기로 분할되어 있고, 세그먼트는 가변의 크기를 가진다.
<strong>메모리 관리 방식</strong>: 페이지는 투명한 메모리 관리를 제공하는 반면, 세그먼트는 프로그램의 논리적 구조를 반영한다. 
=&gt; 페이지는 고정된 메모리를 할당하면서 메모리 관리의 복잡성을 숨기고, 프로그램에게 단순화된 연속적인 가상 메모리 공간을 제공하며, 세그먼트는 프로그램의 논리적 구조를 메모리에 반영하는데 유리하기 때문이다.</p>
<p><strong>단편화의 종류</strong>: 페이지는 내부 단편화의 문제를 가지고 있고, 세그먼트는 외부 단편화의 문제를 가질 수 있다. 페이지는 고정적인 메모리를 쪼개서 관리하고, 세그먼트는 가변적인 필요한 만큼 메모리를 사용하기 때문.</p>
<h1 id="page-table">Page Table</h1>
<p>페이지 테이블은 컴퓨터 시스템의 가상 메모리 관리에서 핵심적인 역할을 하는 데이터 구조이며,
가상 주소를 물리적 주소로 매핑하는데 사용된다. 각 프로세스는 자신만의 페이지 테이블을 가지고 있으며, 이를 통해 운영 체제는 프로세스의 가상 메모리 공간을 물리적 메모리에 매핑한다.</p>
<h2 id="페이지-테이블의-기능">페이지 테이블의 기능</h2>
<p><strong>주소 변환</strong>: 페이지 테이블은 프로세스가 사용하는 가상 주소를 실제 물리적 메모리 주소로 변환하는데 사용된다.</p>
<p><strong>메모리 보호</strong>: 페이지 테이블을 통해 특정 메모리 영역에 대한 접근 권한(rwx)을 설정할 수 있다. 이를 통해 운영 체제는 프로세스가 허용되지 않은 메모리 영역에 접근하느 ㄴ것을 방지할 수 있다.</p>
<p><strong>메모리 공유</strong>: 다른 프로세스와 메모리 영역(ex:  공유 라이브러리)을 공유할 때 페이지 테이블을 사용하여 공유를 관리한다.</p>
<h2 id="구조">구조</h2>
<ul>
<li><strong>페이지 테이블 엔트리</strong>(PTE): 페이지 테이블은 여러 페이지 테이블 엔트리로 구성된다. 각 PTE는 가상 페이지와 연결된 물리적 페이지의 정보를 포함한다.<br></li>
<li><strong>프레임 번호</strong>: 각 PTE는 해당 가상 페이지가 매핑된 물리적 메모리의 프레임(페이지)번호를 보함한다.<br></li>
<li><strong>플래그</strong>: PTE에 접근 권한, 수정 여부, 사용 여부 등을 나타내는 플래그가 포함될 수 있다.</li>
</ul>
<h2 id="관리">관리</h2>
<ul>
<li><strong>메모리 관리 유닛(MMU)</strong>: CPU에 내장된 MMU는 페이지 테이블을 사용하여 가상 주소를 무릴적 주소로 변환한다.<br></li>
<li><strong>페이지 테이블 위치</strong>: 페이지 테이블은 일반적으로 메인 메모리에 저장되며, 현재 활성화된 페이지 테이블의 기준 주소는 특변한 레지스터에 저장된다.<br></li>
<li><strong>멀티 레벨 페이지 테이블(MLPT)</strong>: 대규모 가상 주소 공간을 관리하기 위해, 현대의 시스템은 종종 멀티 레벨 페이지 테이블 구조를 사용한다. 페이지 테이블 자체가 여러 레벨로 나뉘어져 있는 구조이다.</li>
</ul>
<h1 id="page-fault">Page Fault</h1>
<p><strong>페이지 폴트</strong>는 가상 메모리 시스템에서 발생하는 이벤트로 매우 중요한 역할을 한다.
프로세스가 접근하려는 페이지가 현재 물리적인 메모리에 존재하지 않을 때 발생하는데, 좀 더 자세한 원인을 확인해보자.</p>
<h2 id="원인">원인</h2>
<ol>
<li><strong>비할당 메모리 접근</strong>: 프로세스가 아직 할당되지 않은 메모리 영역에 접근할 때 발생한다.<br></li>
<li><strong>스왑 아웃 페이지 접근</strong>: 프로세스가 필요한 페이지가 디스크 스왑 영역에 있고, 현재 물리적 메모리에 로드되어 있지 않을 때 발생한다.<br></li>
<li><strong>페이지 보호 위반</strong>: 프로세스가 접근 권한이 없는 페이지(ex: 쓰기 급지된 페이지, 컬널 영역...)에 접근하려고 할 때 발생한다.</li>
</ol>
<h2 id="페이지-폴트-처리">페이지 폴트 처리</h2>
<ol>
<li><strong>인터럽트</strong>: 페이지 폴트가 발생하면, 운영 체제는 페이지 폴트 인터럽트를 처리하는 루틴을 실행한다.<br></li>
<li><strong>페이지 폴트 원인 분석</strong>: 운영 체제는 위와 같은 원인이 존재하는지 페이지 폴트의 원인을 파악한다.<br></li>
<li><strong>페이지 로딩 또는 생성</strong>: 필요한 페이지가 디스크에 잇다면, 운영 체제는 해당 페이지를 물리적 메모리에 로드한다. 페이지가 아직 생성되지 않았다면, 운영체제는 새로운 페이지를 할당하고 초기화한다.<br></li>
<li><strong>페이지 테이블 업데이트</strong>: 페이지가 메모리에 로드되면, 페이지 테이블이 업데이트되어 새로운 페이지 매핑이 반연된다.<br></li>
<li><strong>프로세스 재개</strong>: 페이지 로딩이 완료되면, 프로세스는 중단된 지점부터 실행을 재개한다.</li>
</ol>
<h2 id="페이지-폴트의-영향">페이지 폴트의 영향</h2>
<ul>
<li><strong>성능저하</strong>: 페이지 폴트 처리는 시간이 소요되고 디스크I/O가 필요한 경우 특히 성능에 영향을 줄 수 있다. 때문에 디스크 스왑 인/아웃을 자주 할 수록 성능은 더욱 급격히 떨어진다.</li>
<li><strong>시스템 효율성</strong>: 적절한 페이지 교체 알고리즘과 스왑 전략을 사용하면, 페이지 폴트의 영향을 최소화하고 시스템의 전반적인 효율성을 높일 수 있다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[CS] Register, Memory, cache]]></title>
            <link>https://velog.io/@wrld_worthy/CS-Register-Memory-cache</link>
            <guid>https://velog.io/@wrld_worthy/CS-Register-Memory-cache</guid>
            <pubDate>Tue, 05 Dec 2023 05:45:39 GMT</pubDate>
            <description><![CDATA[<h1 id="memory">Memory</h1>
<ul>
<li>프로그램, 데이터, 운영 체제 등을 저장하는데 사용된다. 메모리는 실행 중인 프로그램의 코드와 필요한 데이터를 저장하고 있다.</li>
<li>보편적으로 메모리하면 RAM을 뜻하며, ROM(읽기 전용 메모리), 보조 기억장치(HDD,SDD 등)이 포함된다.</li>
<li>CPU의 레지스터보다는 상당히 낮은 속도를 보이지만, 더 많은 데이터를 저장할 수 있다.</li>
</ul>
<p>이 정도만 알아보고
<a href="https://velog.io/@wrld_worthy/CS-%EB%A9%94%EB%AA%A8%EB%A6%AC">메모리</a>에서 좀 더 자세히 볼 수 있다.</p>
<h1 id="register">Register</h1>
<p>컴퓨터의 프로세서(CPU) 내에서 데이터를 보관하는 아주 빠른 기억 장치로, 일반적으로 그냥 레지스터라 불리며 프로세서 레지스터라고 불리기도 한다. 주로 현재 계산을 수행중인 값을 저장하는데 사용된다.
대부분의 현대 프로세서는 메인 메모리에서 레지스터로 데이터를 옮겨와 데이터를 처리한 후, 그 내용을 다시 레지스터에서 메인 메모리로 저장하는 로드 - 스토어 설계를 사용하고 있다.
레지스터는 메모리 계층의 최상위에 위치하며, 가장 빠른 속도로 접근 가능한 메모리이다.</p>
<h2 id="위치-속도">위치, 속도</h2>
<p>레지스터는 CPU 내부에 위치하며, 컴퓨터 시스템에서 가장 빠른 데이터 접근 속도를 제공한다.
프로그램 실행 중에 필요한 데이터와 명령어를 즉시 사용할 수 있게 함.</p>
<h2 id="역할">역할</h2>
<ol>
<li><strong>데이터 처리</strong>
CPU 가 실행 중인 프로그램의 연산을 처리하기 위해, 레지스터는 필요한 데이터를 저장하고, 연산 결과를 임시로 보관한다.<br></li>
<li><strong>명령어 실행</strong>
CPU는 실행할 명령어를 레지스터에 저장하고, 명령어에 따라 다른 레지스터에 저장된 데이터를 사용한다.<br></li>
<li><strong>프로그램 흐름 제어</strong>
프로그램 카운터와 같은 특수 목적 레지스터는 실행 중인 프로그램의 현재 위치를 추적하고, 다음에 수행할 명령어의 주소를 가리킨다.<br></li>
<li><strong>상태 표시</strong>
상태 레지스턴느 현재 CPU의 상태를 나타내는 플래그를 포함하여, 연산의 결과나 CPU의 상태를 나타낸다.</li>
</ol>
<h2 id="용량">용량</h2>
<p>레지스터의 크기는 보통 32비트나 64비트와 같이 CPU의 아키텍처에 따라 다르다. 레지스터의 용량은 메우 제한적이며, 큰 데이터를 저장하기에는 매우 부적합하다.</p>
<p>32비트에서 64비트의 CPU 아키텍쳐가 만들어 졌을 때, 새로운 아키텍쳐를 설계하기 보단 기존에 사용하던 방식들이 많은 보급이 이루어졌기 때문에 버리고 새로 만들기에는 비용이 많이 들며, 많은 문제점들을 일으킬 수 있기 때문에 32비트의 구조에서 Extend 형식으로 설계 되었다. 때문에 64비트에서의 레지스터는 32비트에서의 레지스터들을 내부에 가지고 있다.</p>
<h2 id="구성">구성</h2>
<ul>
<li><strong>PC(프로그램 계수기)</strong> : 다음에 실행할 명령어(instruction)의 주소를 가지고 있다.</li>
<li><strong>IR(명령어 레지스터)</strong> : 현재 수행 중인 명령어를 가지고 있다.</li>
<li><strong>MAR(메모리 주소 레지스터)</strong> : 메모리로부터 읽어오거나 메모리에 쓰기 위한 주소를 가지고 있다.</li>
<li><strong>MBR(메모리 버퍼 레지스터)</strong> : 메모리로부터 읽어온 데이터 또는 메모리에 써야할 데이터를 가지고 있다.</li>
<li><strong>I/O AR(입출력 주소 레지스터)</strong> : 입출력 장치에 따른 입출력 모듈의 주소를 가지고 있다.</li>
<li><strong>I/O BR(입출력 버퍼 레지스터)</strong> : 입출력 모듈과 프로세서 간의 데이터 교환을 위해 사용된다.</li>
</ul>
<h2 id="목적">목적</h2>
<p>일반적으로 레지스터는 일반 목적 레지스터와, 특수 목적 레지스터 2가지로 나뉜다.
<img src="blob:https://velog.io/3aa967e9-2a24-41d3-bdd1-9db801413776" alt="업로드중.."></p>
<h3 id="일반-목적-레지스터">일반 목적 레지스터</h3>
<p>일반 목적 레지스터는 다양한 데이터 처리 작업에 사용된다.</p>
<ul>
<li><strong>RAX, RBX, RCX, RDX (64bit)</strong>
주로 데이터 연산과 저장에 사용된다.</li>
<li><strong>RSI, RDI</strong>
스택 관리에 사용된다.</li>
<li>R8,9,10,...,15
다양한 다목적 용도로 활용된다.</li>
</ul>
<h3 id="특수-목적-레지스터">특수 목적 레지스터</h3>
<p>특정 기능만을 위해 설계된 레지스터들로 CPU의 제어와 상태 관리에 주로 사용된다.</p>
<ul>
<li><strong>PC(Program Counter) 또는 IP(Instruction Pointer)</strong>
다음에 실행할 명령어의 주소를 저장한다. PC나 IP는 레지스터가 아닌 레지스터의 구성 중 하나를 뜻하는데, RIP 레지스터가 수행함.<br></li>
<li><strong>Instruction Register(IR)</strong>
현재 실행 중인 명령어를 저장한다.<br></li>
<li><strong>Status Register/ Flag Register(ex: FLAGS, EFLAGS, RFLAGS)</strong>
CPU의 상태 플래그( 제로 플래그, 오버플로 플래그 등)을 저장한다.<br></li>
<li><strong>RSP</strong>
현재 스택의 상단을 가리킨다.<br></li>
<li><strong>RBP</strong>
스택 프레임의 기준점을 가리킨다.<br></li>
<li><strong>세크먼트 레지스터</strong>
메모리 세그먼트의 시작 주소를 저장하고 관리한다. 주로 메모리 관리에 사용된다.<br></li>
<li><strong>컨트롤 레지스터</strong>
시스템의 상태와 제어를 위한 레지스터<br>

</li>
</ul>
<h1 id="cache">cache</h1>
<p>캐시는 데이터나 값을 미리 복사해 놓는 임시 장소로 쓰인다.
캐시의 접근 시간에 비해 원래 데이터에 접근하는 시간이 오래 걸리는 경우 중앙 처리 장치(CPU)와 메모리 사이의 속도 차이를 줄이기 위해, 값을 다시 계산하는 시간을 절약하고 싶은 경우에 사용되는 고속 데이터 저장소이다. 캐시의 주요 목적은 데이터와 명령어를 빠르게 접근할 수 있게 함으로써 전체 시스템의 성능을 향상시키는 것이다.</p>
<h2 id="특징">특징</h2>
<ol>
<li><strong>고속 접근</strong>
캐시는 CPU와 메모리 사이에 위치하여, CPU가 필요한 데이터와 명령어를 빠르게 접근할 수 있도록 해준다.</li>
<li><strong>임시 저장서</strong>
자주 사용되는 데이터나, 연산 결과 값, 명령어를 저장하여 CPU 가 메인 메모리에 접근하는 횟수를 줄여준다.</li>
</ol>
<h2 id="작동-원리">작동 원리</h2>
<ul>
<li><strong>로컬리티 원칙</strong>
캐시는 시간적 지역성과 공간적 지역성의 원칙을 활용한다. 이는 프로그램이 특정 데이터나 명령어를 한 번 사용하면 곧 다시 사용할 가능성이 높다는 것을 의미한다.</li>
<li><strong>캐시 적중과 캐시 미스</strong>
CPU가 데이터를 요청햇을 때 캐시에 해당 데이터가 있으면 <code>캐시 적중</code> 없으면 <code>캐시 미스</code>라고 한다.
캐시 미스가 발생하면 데이터는 메인 메모리에서 가져와 캐시에 저장된다.</li>
</ul>
<h2 id="캐시와-레지스터의-차이">캐시와 레지스터의 차이</h2>
<p>레지스터에 들어오는 데이터는 처리되기 위해서 들어오는 것이고 저장되기 위해서 들어오는 것이 아니다.
즉, 레지스터는 데이터 처리를 위한 구성요소로써 CPU의 필수 구성 요소지만 캐시는 CPU를 개선하고 돕기위한 저장을 위한 요소로 CPU의 보조 구성요소이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[CS] User mode, Kernel mode]]></title>
            <link>https://velog.io/@wrld_worthy/CS-User-mode-Kernel-mode</link>
            <guid>https://velog.io/@wrld_worthy/CS-User-mode-Kernel-mode</guid>
            <pubDate>Tue, 05 Dec 2023 02:51:24 GMT</pubDate>
            <description><![CDATA[<p>운영체제에는 사용자 모드(User mode)와 커널 모드(Kernel mode) 두 모드로 나뉜다.
<strong>왜 모드(mode)가 나눠져 있을까??</strong></p>
<ol>
<li><p>보안성</p>
<ul>
<li>사용자 모드와 커널 모드의 분리는 시스템의 보안성을 위함이다. 악의적인 소프트웨어가 시스템의 핵심 부분에 접근하는 것을 방지해야하기 때문이다. 이러한 보안성은 컴퓨터 시스템에서는 매우 중요한 요소로, 권한을 분리해주는 것이 좋다. 프로세스간의 메모리의 간섭을 막는 이유 또한 같은 이유이다.</li>
</ul>
</li>
<li><p>안정성</p>
<ul>
<li>각 프로그램은 독립된 메모리 공간에서 실행되므로, 한 프로그램의 실패가 다른 프로그램이나 운영 체제 전체에 영향을 미치지 않게 하기 위함. 
ex) 시스템 콜과 같은 시스템 내부에 접근할 수 있는 권한을 사용하지 못하게 함.</li>
</ul>
</li>
<li><p>효율성</p>
<ul>
<li>운영 체제는 모드를 효율적으로 전환하며 자원을 효과적으로 관리할 수 있다.</li>
</ul>
</li>
<li><p>자원 관리</p>
<ul>
<li>커널 모드는 시스템 자원을 관리, 사용자 모드는 애플리케이션 영역을 관리하며 서비스를 제공한다.</li>
</ul>
</li>
<li><p>시스템 호출</p>
<ul>
<li>사용자 모드 애플리케이션은 시스템 호출을 통해 필요한 시스템 자원을 안전하게 요청하고 사용할 수 있다. 이는 커널 모드와 사용자 모드 간의 중요한 이터페이스 역할을 한다.</li>
</ul>
</li>
</ol>
<h1 id="사용자-모드-user-mode">사용자 모드, User mode</h1>
<ul>
<li>이 모드에서는 일반 애플리케이션영역으로 프로그램들이 실행되는 영역이다. 흔히 우리가 코딩을하여 실행하면 이 영역에서 실행된다.</li>
<li>실행되는 모든 프로그램은 제한된 메모리 영역과 자원만을 사용할 수 있다.</li>
<li>하드웨어에 직접적으로 접근할 수 없고, 시스템 자원을 사용하기 위해서는 운영 체제가 제공하는 인터페이스를 사용해야한다. ex) 시스템 콜 등.</li>
</ul>
<h2 id="역할">역할</h2>
<ul>
<li>사용자 모드 영역에서 실행되는 애플리케이션은 서로의 메모리 영역에 접근할 수 없고, 서로를 격리한다. 이는 시스템의 안정성과 보안성을 향상시킨다.</li>
<li>애플리케이션의 오류나 충돌은 해당 어플리케이션에만 영향을 미치고, 시스템 전체에는 영향을 주지 않는다.</li>
</ul>
<h2 id="자원-접근">자원 접근</h2>
<ul>
<li>애플리케이션은 커널 모드의 기능을 필요로 할 때에는, 시스템 호출(System call)을 사용한다.</li>
<li>시스템 호출을 통해 운영 체제는 요청을 받고, 필요한 작업을 커널 모드에서 수행한 후 결과 값만을 반환한다.</li>
</ul>
<br>

<h1 id="커널-모드-kernel-mode">커널 모드, kernel mode</h1>
<ul>
<li>커널 모드는 운영 체제의 핵심 부분이 실행되는 영역이다.</li>
<li>이 영역에서는 시스템의 모든 자원고 메모리에 대한 완전한 접근 권한이 있다.</li>
<li>하드웨어와 직접적으로 상호 작용하는 작업, 메모리 관리, 프로세스 관리, 입 출력 관리 등을 수행하는 영역이다.</li>
</ul>
<h2 id="역할-1">역할</h2>
<ul>
<li>커널 모드에서 실행된느 코드는 시스템에서 매우 큰 영향을 미칠 수 있으므로, 보안이 주요하다.</li>
<li>일반적으로 사용자가 직접 커널 모드에서 코드를 실행할 수 없게 하며, 시스템 호출만을 통해 운영 체제가 제공하는 인터페이스를 사용하게 하여 제어한다.</li>
</ul>
<h2 id="위험성">위험성</h2>
<ul>
<li>커널 모드에서의 오류나 잘못된 접근은 시스템 전체의 안정성을 위협할 수 있다.</li>
</ul>
<p><img src="blob:https://velog.io/299c8f9b-58c0-4bfc-a6ee-f36e7384d6a7" alt="업로드중.."></p>
<h1 id="mode-switching">Mode Switching</h1>
<ul>
<li>프로세스가 사용자 모드에서 커널 모드로 전환하는 것은 일반적으로 시스템 호출을 통해 이루어진다.
ex) 파일을 읽기 위해서는 <code>read</code>라는 시스템 호출을 사용하여, 사용자모드에서 커널 모드로 전환이 이루어진다.</li>
<li>작업이 완료된 후, 시스템은 다시 사용자 보드로 전환하여 프로세스 제어권을 반환한다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[CS] Process, Thread]]></title>
            <link>https://velog.io/@wrld_worthy/CS-Process-Thread</link>
            <guid>https://velog.io/@wrld_worthy/CS-Process-Thread</guid>
            <pubDate>Thu, 23 Nov 2023 14:06:23 GMT</pubDate>
            <description><![CDATA[<h1 id="process">Process</h1>
<p>프로세스(Process)는 프로그램을 실행하면, 운영체제는 해당 프로글매의 실행 파일(ex:exe파일)을 메모리에 로드한다. 이때 프로세스를 생성하여 메모리를 할당한다.</p>
<br>

<h2 id="process-의미">Process 의미</h2>
<ul>
<li>컴퓨터에서 실행중인 프로그램</li>
<li>프로그램의 인스턴스로 독립적인 객체이며, 고유한 프로세스 식별자(PID)가 할당된다.</li>
<li>운영체제로부터 자원을 할당받는 작업의 단위이다.</li>
</ul>
<br>

<h2 id="process-특징">Process 특징</h2>
<ul>
<li>프로그램의 코드, 데이터, 스택, 힙 영역 드을 포함한 메모리 공간을 할당 받음.</li>
<li>자신만의 주소 공간을 가지고 있어, 프로세스 간 메모리 충돌을 방지한다.</li>
<li>다른 프로세스의 메모리에 접근할 수 없다.</li>
<li>기본적으로 프로세스당 1개 이상의 스레드를 생성할 수 있다.</li>
<li>프로세스가 다른 프로세스의 자원에 접근하려면 프로세스 간의 통신이 이루어져야한다.
(프로세스 간의 통신:IPC, inter-process-communication)</li>
</ul>
<h2 id="실행">실행</h2>
<ul>
<li>프로세스는 운영 체제의 스케줄러에 의해 CPU 시간을 할당받고 실행된다.</li>
</ul>
<br>

<h1 id="thread">Thread</h1>
<p>스레드(Thread)는 프로세스 내에서 실행되는 가장 작은 실행 단위로, 프로그램 코드의 실행 흐름이다. 스레드는 프로세스의 자원과 메모리 공간(힙, 전역 변수 등)을 공유하며, 각각 독립적ㅇ니 실행 경로와 스택을 가진다.</p>
<h2 id="thread-의미">Thread 의미</h2>
<ul>
<li>프로세스 내에서 병렬로 실행되는 작업의 단위, 프로세스 내에서 실행되는 가장 작은 단위.</li>
<li>프로세스의 자원(메모리, 파일 핸들 등)을 공유하지만, 각 스레드는 독립적인 스택과 프로그램 카운터를 가진다.</li>
<li>멀티 스레딩을 통해 하나의 프로세스 내에서 여러 작업을 동시에 수행 할 수 있다.</li>
</ul>
<h2 id="thread-특징">Thread 특징</h2>
<ul>
<li>프로세스 내 자원 공유, 스레드는 프로세스의 메모리(힙, 전역변수 등)와 자원을 공유하여 효율적인 자원 사용이 가능하다.</li>
<li>독립적 실행 경로, 각 스레드는 독립적인 실행 으름을 가지며, 자신만의 스택을 통해 함수 호출과 로컬 변수를 관리한다.</li>
<li>경량 프로세스, 스레드는 프로세스보다 생성 비용과 Context Switching비용이 낮다.</li>
<li>동기화 필요, 공유 자원에 대한 접근을 관리하기 위한 동기화 메커니즘이 필요하다.(ex: 세마포어, 뮤텍스)</li>
</ul>
<h2 id="실행-1">실행</h2>
<ul>
<li>스레드는 프로세스 내에서 운영 체제의 스케줄러에 의해 독립적으로 CPU시간을 할당받아 실행된다.</li>
<li>멀티 코어 프로세서에서는 여러 스레드가 동시에 다른 코어에서 실행될 수 있어 병렬 처리의 이점을 제공한다.</li>
</ul>
<h2 id="멀티-프로세스-멀티-스레드">멀티 프로세스, 멀티 스레드</h2>
<h3 id="멀티-프로세스">멀티 프로세스</h3>
<p>멀티 프로세스는 여러 프로세스가 동시에 실행되는 방식으로, 각 프로세스가 독립적으로 메모리와 자원을 사용한다. 멀티 프로세스는 환경에서는 각 프로세스가 서로 다른 작업을 수행할 수 있다.
]</p>
<h4 id="멀티-프로세스-성질">멀티 프로세스 성질</h4>
<ul>
<li>독립적인 실행 환경, 각 프로세스는 독립적인 메모리 공간과 자원을 가진다.</li>
<li>안정성, 한 프로세스의 실패가 다른 프로세스에 영향을 미치지 않아 시스템의 전체적인 안정성이 높음</li>
<li>프로세스 간 통신(IPC)이 필요, 서로 다른 메모리 공간을 가지므로, 프로세스 간 통신에는 특별한 메커니즘을 필요로 한다.</li>
</ul>
<h4 id="멀티-프로세스-특징">멀티 프로세스 특징</h4>
<ul>
<li>자원의 독립성: 프로세스는 독립적인 메모리, 자원을 가짐</li>
<li>오버헤드: 프로세스 간 컨텍스트 스위칭과 자원 관리에 더 많은 시스템 오버헤드 발생할 수 있다.</li>
<li>데이터 고융와 통신 복잡성: 프로세스 간 데이터 공유와 통신이 복잡하고 오버헤드가 크다.</li>
</ul>
<br>

<h3 id="멀티-스레드">멀티 스레드</h3>
<p>멀티 스레드는 하나의 프로세스 내에서 여러 스레드가 동시에 실행되는 방식이다. 스레드들은 프로세스의 자원과 메모리를 공유하면서 작업을 수행한다.</p>
<h4 id="멀티-스레드-성질">멀티 스레드 성질</h4>
<ul>
<li>자원 공동일한 프로세스 내의 스레드들은 메모리와 자원을 공유한다.</li>
<li>효율적인 자원 사용, 자원을 공유하기 때문에 멀티 프로세스보다 효율적인 자원 사용이 가능하다.</li>
<li>반응성 향상: 하난의 스레드가 대기 상태일 때 다른 스레드가 작업을 계속 수행할 수 있어, 응용 프로그램의 반응성이 좋아진다.</li>
</ul>
<h4 id="멀티-스레드-특징">멀티 스레드 특징</h4>
<ul>
<li>경량 프로세스, 스레드는 프로세스보다 가볍고 빠르며, 컨텍스트 스위칭 비용이 낮다.</li>
<li>동기화 문제, 공유 자원에 대한 접근을 관리하기 위한 동기화가 필요하다.</li>
<li>스레드 간의 자원 공유는 전역 변수(데이터 세그먼트)를 이용하므로 충돌이 발생할 수 있다.</li>
<li>오류와 예외 처리의 복잡성, 한 스레드의 실패가 전체 프로세스의 영향을 줄 수 있다.</li>
</ul>
<h2 id="멀티-프로세스와-멀티-스레드의-차이">멀티 프로세스와 멀티 스레드의 차이</h2>
<ul>
<li>자원의 공유: 멀티 프로세스는 각각 독립된 메모리 공간을 가지지만, 멀티 스레드는 프로세스의 자원을 공유한다.</li>
<li>오버헤드와 효율성: 멀티 프로세스는 간 컨테긋트 스위칭으로 인한 오버헤드가 크지만, 멀티 스레드는 더 효율적인 자원 사용과 빠른 컨텍스트 스위칭이 가능하다.</li>
<li>안정성과 격리성: 멀티 프로세스는 프로세스 간 격리로 인해 안전성이 높지만, 멀티 스레드는 하나의 스레드에 문제가 생기면 전체 프로세스에 영향을 줄 수 있다.</li>
<li>통신과 데이터 공유: 멀티 프로세스는 IPC를 통해 데이터를 교환하지만 복잡하고 오버헤드가 크며, 멀티 스레드는 프로세스 내에서 자원을 공유하기 때문에 통신이 더 간단하고 효율적이다.</li>
</ul>
<h1 id="멀티-프로세스-보다-멀티-스레드를-사용한다">멀티 프로세스 보다 멀티 스레드를 사용한다.</h1>
<p>멀티 프로세스가 먼저 개발되어 초기에 적용이 되었고, 후에 멀티 프로세스의 단점을 극복하기 위해서 멀티 스레드를 채택하여 적용됐다.</p>
<p>단점</p>
<ul>
<li>고비용의 컨텍스트 스위칭</li>
<li>자원 사용의 비효율성</li>
</ul>
<h2 id="멀티-프로세스로-할-수-있는-작업들을-하나의-프로세스에서-멀티-스레드로-작업하는-이유">멀티 프로세스로 할 수 있는 작업들을 하나의 프로세스에서 멀티 스레드로 작업하는 이유</h2>
<ol>
<li>자원의 효율성 증대</li>
</ol>
<ul>
<li>멀티 프로세스로 실행되는 작업을 멀티 스레드로 실행할 경우, 프로세스를 생성하여 자원을 할당하는 시스템 콜이 줄어들어 자원을 효율적으로 관리할 수 있다.</li>
<li><blockquote>
<p>프로세스 간의 Context Switching시 단순히 CPU 레지스터 교체 뿐만 아니라 RAM과 CPU 사이의 캐쉬 메모리에 대한 데이터까지 초기화되므로 오버헤드가 크기 때문</p>
<br></blockquote>
</li>
<li>스레드는 프로세스 내의 메모리를 공유하기 때문에 독립적인 프로세스와 달리 스레드 간 데이터를 주고 받는 것이 간단해지고 시스템 자원 소모가 줄어들게 된다.</li>
</ul>
<br>

<ol start="2">
<li>처리 비용 감소 및 응답 시간 단축</li>
</ol>
<ul>
<li>프로세스 간의 통신(IPC)보다 스레드 간의 통신의 비용이 적으므로 작업들 간의 통신의 부담이 줄어든다.
–&gt; 스레드는 Stack 영역을 제외한 모든 메모리를 공유하기 때문<br></li>
<li>프로세스 간의 전환 속도보다 스레드 간의 전환 속도가 빠르다.
–&gt; Context Switching시 스레드는 Stack 영역만 처리하기 때문</li>
</ul>
]]></description>
        </item>
    </channel>
</rss>