<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>ss_g.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Sun, 12 Jan 2025 13:52:19 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>ss_g.log</title>
            <url>https://velog.velcdn.com/images/ss_g/profile/6831e09b-1b5a-4ad4-947d-caa9298bc550/social_profile.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. ss_g.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/ss_g" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[HTTP, REST, HTTP Status Code, 쿠키&세션]]></title>
            <link>https://velog.io/@ss_g/HTTP-REST-HTTP-Status-Code-%EC%BF%A0%ED%82%A4%EC%84%B8%EC%85%98</link>
            <guid>https://velog.io/@ss_g/HTTP-REST-HTTP-Status-Code-%EC%BF%A0%ED%82%A4%EC%84%B8%EC%85%98</guid>
            <pubDate>Sun, 12 Jan 2025 13:52:19 GMT</pubDate>
            <description><![CDATA[<h4 id="http">HTTP</h4>
<p>HTTP(Hypertext Transfer Protocol) : 클라이언트와 서버 간 통신 프로토콜로 클라이언트가 요청(Request) 을 보내면 서버가 응답(Response) 을 보냄</p>
<ul>
<li><p>요청(Request)</p>
<ul>
<li>클라이언트가 서버에 데이터를 요청하는 메시지</li>
<li>HTTP 메서드 : 요청 의도를 나타냄(GET, POST, PUT, DELETE)</li>
<li>URL : 요청 대상의 리소스 주소</li>
<li>헤더(Header) : 요청정보(인코딩, 인증 등)</li>
<li>본문(Body) : 추가적인 데이터</li>
</ul>
</li>
<li><p>응답(Response)</p>
<ul>
<li>서버가 요청에 대해 반환하는 메시지</li>
<li>상태코드 : 요청 결과를 나타내는 숫자 코드(200, 400, 500 등등)</li>
<li>헤더(Header) : 응답 메타데이터</li>
<li>본문(Body) : 요청한 데이터나 메시지</li>
</ul>
</li>
</ul>
<ul>
<li>HTTP 와 HTTPS 의 차이<ul>
<li>HTTP : 텍스트 기반 프로토콜로 암호화되지 않은 데이터 전송</li>
<li>HTTPS : 보안을 강화한 HTTP 로 SSL/TLS 를 사용해 데이터 암호화</li>
</ul>
</li>
</ul>
<h4 id="http-상태-코드">HTTP 상태 코드</h4>
<ol>
<li>1xx (정보)<ul>
<li>요청 수신 완료. 프로세스 계속 진행</li>
</ul>
</li>
</ol>
<table>
<thead>
<tr>
<th>상태 코드</th>
<th>이름</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>100</td>
<td>Continue</td>
<td>요청의 시작 부분이 받아들여졌으며 클라이언트는 계속 이어서 보내야 함</td>
</tr>
<tr>
<td></td>
<td></td>
<td>이미 요청을 완료한 경우에는 무시해도 됨</td>
</tr>
<tr>
<td>101</td>
<td>Switching Protocol</td>
<td>요청 헤더의 Update 필드 중 하나로 서버가 프로토콜을 변경함</td>
</tr>
<tr>
<td>102</td>
<td>Processing</td>
<td>서버가 요청을 수신하고 이를 처리하고 있으나 제대로 된 응답을 알려줄 수 없음</td>
</tr>
</tbody></table>
<ol start="2">
<li>2xx (성공)<ul>
<li>요청 성공적으로 처리됨</li>
</ul>
</li>
</ol>
<table>
<thead>
<tr>
<th>상태 코드</th>
<th>이름</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>200</td>
<td>OK</td>
<td>요청을 정상적으로 처리함</td>
</tr>
<tr>
<td>201</td>
<td>Created</td>
<td>성공적으로 생성에 대한 요청을 받았으며 서버가 새 리소스를 작성함 (대개 POST, PUT일 때)</td>
</tr>
<tr>
<td>202</td>
<td>Accepted</td>
<td>요청을 접수했지만 아직 처리하지 않음 (요청은 적절했음)</td>
</tr>
<tr>
<td>203</td>
<td>Non-Authoritative Information</td>
<td>요청을 성공적으로 처리했지만 다른 소스에서 수신된 정보를 제공함, 검증이 되지 않은 상태</td>
</tr>
<tr>
<td>204</td>
<td>No Content</td>
<td>서버가 요청을 성공적으로 처리했지만 제공할 컨텐츠는 없음</td>
</tr>
<tr>
<td>205</td>
<td>Reset Content</td>
<td>서버가 요청을 성공적으로 처리했지만 새로운 내용을 확인해야 함을 알려줌 (새로고침 등)</td>
</tr>
<tr>
<td>206</td>
<td>Partial Content</td>
<td>서버가 GET 요청의 일부만 성공적으로 처리함</td>
</tr>
<tr>
<td></td>
<td></td>
<td>- Content-Range와 Date 헤더를 반드시 포함</td>
</tr>
<tr>
<td>207</td>
<td>Multi Status</td>
<td>여러 개의 리소스가 여러 status code를 갖고 있는 상황에서 적절한 정보 전달</td>
</tr>
<tr>
<td>208</td>
<td>Already Reported</td>
<td>DAV에서 사용</td>
</tr>
</tbody></table>
<ol start="3">
<li>3xx (리다이렉션)<ul>
<li>클라이언트의 요청에 대해 적절한 리다이렉션을 제공하거나 대안 응답 제공</li>
</ul>
</li>
</ol>
<table>
<thead>
<tr>
<th>상태 코드</th>
<th>이름</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>300</td>
<td>Multiple Choice</td>
<td>클라이언트가 동시에 여러 응답이 가능한 요청을 보냈을 경우 클라이언트의 선택지를 반환</td>
</tr>
<tr>
<td>301</td>
<td>Moved Permanently</td>
<td>요청한 리소스의 URI가 변경됨 -&gt; 변경된 URI에 대한 정보와 함께 응답</td>
</tr>
<tr>
<td>302</td>
<td>Found</td>
<td>요청한 리소스의 URI가 일시적으로 변경된 것이므로 원래 요청했던 URI로 요청해야 함</td>
</tr>
<tr>
<td>303</td>
<td>See Other</td>
<td>클라이언트가 요청한 작업을 하기 위해서는 다른 URI에서 얻어야 할 때 클라이언트에게 줌</td>
</tr>
<tr>
<td>304</td>
<td>Not Modified</td>
<td>이전의 요청과 비교하여 달라진 것이 없음 (캐시를 목적으로 사용됨)</td>
</tr>
<tr>
<td>305</td>
<td>Use Proxy</td>
<td>proxy를 통해 요청되어야 함</td>
</tr>
<tr>
<td>306</td>
<td>Unused</td>
<td>지금은 사용하지 않는 코드 -&gt; 추후 사용을 위해 예약되어 있음</td>
</tr>
<tr>
<td>307</td>
<td>Temporary Redirect</td>
<td>302와 동일하나 클라이언트가 보낸 HTTP 메소드도 변경하면 안됨</td>
</tr>
<tr>
<td>308</td>
<td>Permanent Redirect</td>
<td>요청한 리소스가 영구적으로 다른 URI에 위치하고 있음, 301과 동일하나 HTTP 메소드도 변경하지 말 것</td>
</tr>
</tbody></table>
<ol start="4">
<li>4xx (클라이언트 에러)<ul>
<li>클라이언트의 잘못된 요청</li>
</ul>
</li>
</ol>
<table>
<thead>
<tr>
<th>상태 코드</th>
<th>이름</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>400</td>
<td>Bad Request</td>
<td>잘못된 문법으로 요청을 보내고 있어 서버가 이해할 수 없음</td>
</tr>
<tr>
<td>401</td>
<td>Unauthorized</td>
<td>요청을 위해 권한 인증이 필요함 (예: 토큰이 없음)</td>
</tr>
<tr>
<td>402</td>
<td>Payment Required</td>
<td>결제 시스템을 위해 만들어졌으나 현재는 사용하지 않음</td>
</tr>
<tr>
<td>403</td>
<td>Forbidden</td>
<td>클라이언트가 요청한 컨텐츠에 대해 접근할 권리가 없음 (신원 인증은 되었지만 권한은 없음)</td>
</tr>
<tr>
<td>404</td>
<td>Not Found</td>
<td>요청한 URI를 찾을 수 없음</td>
</tr>
<tr>
<td>405</td>
<td>Method Not Allowed</td>
<td>클라이언트가 보낸 메소드가 해당 URI에서 지원하지 않음</td>
</tr>
<tr>
<td>406</td>
<td>Not Acceptable</td>
<td>클라이언트의 요청에 대해 응답할만한 컨텐츠가 없음</td>
</tr>
<tr>
<td>407</td>
<td>Proxy Authentication Required</td>
<td>401과 동일하나, proxy를 통해 인증해야 함</td>
</tr>
<tr>
<td>408</td>
<td>Request Timeout</td>
<td>요청에 응답하는 시간이 오래 걸려 요청을 끊음 (보내지 않고 끊을 때도 있음)</td>
</tr>
<tr>
<td>409</td>
<td>Conflict</td>
<td>클라이언트의 요청이 서버의 상태와 충돌이 발생할 수 있음</td>
</tr>
<tr>
<td>410</td>
<td>Gone</td>
<td>요청한 URI가 더 이상 사용되지 않고 사라졌음</td>
</tr>
<tr>
<td>411</td>
<td>Length Required</td>
<td>요청 헤더에 Content-length가 포함되어야 함</td>
</tr>
<tr>
<td>412</td>
<td>Precondition Failed</td>
<td>요청 헤더의 조건이 서버의 조건에 적절하지 않음</td>
</tr>
<tr>
<td>413</td>
<td>Payload Too Large</td>
<td>요청 payload가 서버에서 정의한 최대 크기보다 큼</td>
</tr>
<tr>
<td>414</td>
<td>URI Too Long</td>
<td>요청된 URI가 너무 길어서 처리할 수 없음</td>
</tr>
<tr>
<td>415</td>
<td>Unsupported Media Type</td>
<td>서버가 지원하지 않는 미디어 포맷을 요청함</td>
</tr>
<tr>
<td>416</td>
<td>Requested Range Not Satisfiable</td>
<td>요청 헤더에 있는 Range 필드가 잘못됨</td>
</tr>
<tr>
<td>417</td>
<td>Expectation Failed</td>
<td>요청 헤더에 있는 Expect 필드가 적절하지 않음</td>
</tr>
<tr>
<td>418</td>
<td>I&#39;m a teapot</td>
<td>서버는 티팟이므로 커피 내리기를 거절했음</td>
</tr>
<tr>
<td>421</td>
<td>Misdirected Request</td>
<td>요청이 응답을 생성할 수 없는 서버로 지정됨</td>
</tr>
<tr>
<td>422</td>
<td>Unprocessable Entity</td>
<td>문법 오류로 인하여 처리할 수 없음</td>
</tr>
<tr>
<td>423</td>
<td>Locked</td>
<td>요청한 리소스는 접근하는 것이 잠겨있음</td>
</tr>
<tr>
<td>424</td>
<td>Failed Dependency</td>
<td>이전 요청이 실패했기 때문에 현재의 요청도 실패했음</td>
</tr>
<tr>
<td>425</td>
<td>Too Early</td>
<td>서버가 재생될 수 있는 요청을 처리하는 것을 원치 않음</td>
</tr>
<tr>
<td>426</td>
<td>Upgrade Required</td>
<td>현재 요청한 프로토콜에 대한 처리는 거절함, 다른 프로토콜로 업그레이드를 하면 처리 가능</td>
</tr>
<tr>
<td>428</td>
<td>Precondition Required</td>
<td>필수 전제 조건 헤더가 누락됨</td>
</tr>
<tr>
<td>429</td>
<td>Too Many Requests</td>
<td>클라이언트가 한정된 시간에 너무 많은 요청을 보냄</td>
</tr>
<tr>
<td>431</td>
<td>Request Header Fields Too Large</td>
<td>요청한 헤더 필드가 너무 커서 처리할 수 없음, 헤더 필드를 줄여서 다시 요청해야 함</td>
</tr>
<tr>
<td>451</td>
<td>Unavailable For Legal Reasons</td>
<td>클라이언트가 요청한 것은 정부에 의해 검열된 불법적인 리소스임</td>
</tr>
</tbody></table>
<ol start="5">
<li>5xx (서버 에러)<ul>
<li>클라이언트의 정상 요청에 대해 서버 문제로 인해 응답 불가</li>
</ul>
</li>
</ol>
<table>
<thead>
<tr>
<th>상태 코드</th>
<th>이름</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>500</td>
<td>Internal Server Error</td>
<td>서버의 문제로 응답할 수 없음</td>
</tr>
<tr>
<td>501</td>
<td>Not Implemented</td>
<td>서버가 지원하지 않는 새로운 메소드를 사용하여 요청함</td>
</tr>
<tr>
<td></td>
<td></td>
<td>클라이언트 요청에 대해 서버가 수행할 수 있는 기능이 없음</td>
</tr>
<tr>
<td>502</td>
<td>Bad Gateway</td>
<td>서버 위의 서버에서 오류가 발생, proxy나 gateway 등에서 응답함</td>
</tr>
<tr>
<td>503</td>
<td>Service Unavailable</td>
<td>현재 서버가 일시적으로 사용이 불가함</td>
</tr>
<tr>
<td></td>
<td></td>
<td>일반적으로 유지보수로 인해 중단되거나 과부하가 걸린 서버임</td>
</tr>
<tr>
<td>504</td>
<td>Gateway Timeout</td>
<td>서버가 다른 서버로 요청을 보냈으나 delay가 발생하여 처리가 불가능함</td>
</tr>
<tr>
<td>505</td>
<td>HTTP Version Not Supported</td>
<td>서버가 지원하지 않거나 적절하지 않은 프로토콜로 요청을 함</td>
</tr>
<tr>
<td>506</td>
<td>Variant Also Negotiates</td>
<td>서버에 내부 구성 오류가 있음</td>
</tr>
<tr>
<td>507</td>
<td>Insufficient Storage</td>
<td>서버에 내부 구성 오류가 있음</td>
</tr>
<tr>
<td>508</td>
<td>Loop Detected</td>
<td>요청을 처리하는 동안 무한 루프를 감지함</td>
</tr>
<tr>
<td>510</td>
<td>Not Extended</td>
<td>서버가 처리하기 위해서는 요청을 더 확장해야 함</td>
</tr>
<tr>
<td>511</td>
<td>Network Authentication Required</td>
<td>클라이언트가 네트워크 액세스를 얻으려면 인증이 필요함</td>
</tr>
</tbody></table>
<h4 id="rest-와-restful">REST 와 RESTful</h4>
<ul>
<li><p>REST(REpresentational State Transfer) 는 어떤 자원에 대해 CRUD 연산 수행시 URI(Resource)로 행위(GET, POST 등의 Method)을 사용해 요청을 보내는데, 이때 특정 형태(JSON, XML 등등) 으로 표현됨</p>
</li>
<li><p>RESTful 은 REST 의 원칙을 준수하는 시스템 혹은 API 를 의미하며 아래와 같은 특성을 지님</p>
</li>
</ul>
<ol>
<li><strong>리소스 URL 설계</strong> : URL 은 명확하고 간결해야 하며 자원을 명시적으로 나타내야함 ex) GET /users, GET/users/ssg</li>
<li><strong>HTTP 메서드 사용</strong> : CRUD 작업을 HTTP 메서드로 한다</li>
<li><strong>무상태성(Stateless)</strong> : 클라이언트의 context 를 서버에 저장하지 않고, 서버는 각각의 요청을 별개의 것으로 인식 및 처리함</li>
<li><strong>HTTP 상태 코드 활용</strong> ex) 200 요청 성공이나 400, 500 등</li>
</ol>
<h4 id="쿠키cookie">쿠키(Cookie)</h4>
<p>쿠키는 사용자의 컴퓨터에 저장하는 작은 텍스트 파일로 유효시간 지정 가능하며 클라이언트 상태 정보를 로컬에 저장했다 참조함 </p>
<ul>
<li>장점</li>
</ul>
<ol>
<li>클라이언트쪽 저장으로 서버 부하의 감소</li>
<li>간단한 데이터 저장 및 전송 가능</li>
</ol>
<ul>
<li>단점</li>
</ul>
<ol>
<li>클라이언트가 데이터 수정 가능하므로 신뢰성 떨어짐</li>
<li>브라우저에 의존하고, 쿠키의 크기와 개수 제한이 있음</li>
</ol>
<h4 id="세션session">세션(Session)</h4>
<p>세션은 서버에 저장되는 데이터 저장소로 유출되면 안될 데이터를 주로 저장함.</p>
<ul>
<li>세션 프로세스</li>
</ul>
<ol>
<li>클라이언트가 서버 접속시 세션 ID 를 발급하면</li>
<li>서버에서 클라이언트로 발급해준 세션 ID 를 쿠키를 이용해 전송하고</li>
<li>이후 재접속 시 쿠키에 저장된 세션 ID 를 서버에 전달하면</li>
<li>서버는 요청 헤더에 쿠키 정보로 클라이언트를 판별함</li>
</ol>
<p><strong>세션과 쿠키의 차이</strong></p>
<table>
<thead>
<tr>
<th>구분</th>
<th>쿠키(Cookie)</th>
<th>세션(Session)</th>
</tr>
</thead>
<tbody><tr>
<td>저장 위치</td>
<td>클라이언트(브라우저)</td>
<td>서버</td>
</tr>
<tr>
<td>수명</td>
<td>브라우저 종료 시 삭제(세션 쿠키) 또는 만료 시간 설정</td>
<td>브라우저 종료 또는 세션 만료 시간 경과 시 삭제</td>
</tr>
<tr>
<td>보안</td>
<td>클라이언트가 수정 가능(XSS 취약성)</td>
<td>서버에서 관리하므로 클라이언트가 수정 불가</td>
</tr>
<tr>
<td>데이터 크기 제한</td>
<td>제한적(4KB)</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>
<br>
<br>
<br>
<br>
<br>
<br>
<br>

<p>참조(HTTP Status Code) : <a href="https://hocheon.tistory.com/68">https://hocheon.tistory.com/68</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[예외처리에 대해 알아보자]]></title>
            <link>https://velog.io/@ss_g/%EC%98%88%EC%99%B8%EC%B2%98%EB%A6%AC%EC%97%90-%EB%8C%80%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90</link>
            <guid>https://velog.io/@ss_g/%EC%98%88%EC%99%B8%EC%B2%98%EB%A6%AC%EC%97%90-%EB%8C%80%ED%95%B4-%EC%95%8C%EC%95%84%EB%B3%B4%EC%9E%90</guid>
            <pubDate>Sun, 12 Jan 2025 12:59:12 GMT</pubDate>
            <description><![CDATA[<h3 id="예외-처리를-보기-전에-알아둘-기본-개념">예외 처리를 보기 전에 알아둘 기본 개념</h3>
<h4 id="객체지향-프로그래밍object-oriented-programming">객체지향 프로그래밍(Object-Oriented Programming)</h4>
<p>객체지향 프로그래밍(OOP)란? : 절차지향적 프로그래밍이 아닌 객체의 관점에서 프로그래밍을 하는 방법. 객체를 중심으로 프로그램을 설계, 개발함</p>
<ul>
<li>OOP 의 주요 원칙</li>
</ul>
<ol>
<li>SRP(Single Responsibility Principle)<ul>
<li>클래스는 단 하나는 책임만 가져야 함</li>
</ul>
</li>
<li>OCP(Open/Closed Principle)<ul>
<li>클래스는 확장에는 열려 있어야 하고, 수정에는 닫혀 있어야 함</li>
</ul>
</li>
<li>LSP(Liskov Substitution Principle)<ul>
<li>자식 클래스는 부모 클래스와 교체 가능해야 함</li>
</ul>
</li>
<li>ISP(Interface Segregation Principle)<ul>
<li>클라이언트는 자신이 사용하지 않는 메서드에 의존하지 않아야 함</li>
</ul>
</li>
<li>DIP(Dependency Inversion Principle)<ul>
<li>고수준 모듈은 저수준 모듈에 의존하지 않고, 둘 다 추상화에 의존해야 함</li>
</ul>
</li>
</ol>
<ul>
<li>OOP 의 장점</li>
</ul>
<ol>
<li>코드 재사용성 증가</li>
<li>유지보수의 용이</li>
<li>코드 확장성 높아짐</li>
<li>시스템을 단순화한 설계가 가능</li>
</ol>
<ul>
<li>OOP 의 단점</li>
</ul>
<ol>
<li>설계의 복잡도 증가 가능</li>
<li>설계 방향에 따라 코드가 무거워질 가능성 있음</li>
<li>작은 프로젝트에 적합하지 않을 수 있음</li>
</ol>
<ul>
<li>주요 개념</li>
</ul>
<ol>
<li><p>클래스(Class)</p>
<ul>
<li><p>객체를 만들기 위한 설계도</p>
</li>
<li><p>속성(데이터, 변수)과 메서드(기능, 함수)를 포함</p>
<pre><code>class Car {
public $color;
public $brand;

public function drive() {
  echo &quot;Driving the car!&quot;;
  }
}</code></pre></li>
</ul>
</li>
<li><p>객체(Object)</p>
<ul>
<li>클래스를 인스턴스화해서 만들어진 구체적인 사물 또는 개념</li>
<li>클래스의 속성과 메서드를 실제로 사용할 수 있는 형태<pre><code>$car = new Car();
$car-&gt;color = &quot;Red&quot;;
echo $car-&gt;color; // 출력: Red
$car-&gt;drive(); // 출력: Driving the car!</code></pre></li>
</ul>
</li>
<li><p>캡슐화(Encapsulation)</p>
<ul>
<li>객체의 속성과 메서드를 하나의 단위로 묶어 외부에서의 접근을 제한하는 것</li>
<li>주로 접근 제한자(public, protected, private) 사용</li>
</ul>
</li>
<li><p>상속(Inheritance)</p>
<ul>
<li><p>이미 정의된 클래스를 기반으로 새로운 클래스를 생성해서 기존 클래스의 속성과 메서드를 물려받는것</p>
</li>
<li><p>코드의 재사용성을 높이고 계층 구조를 만듦</p>
<pre><code>class Vehicle {
public $type;

public function move() {
  echo &quot;Moving!&quot;;
  }
}

class Car extends Vehicle {
  public $brand;
}</code></pre></li>
</ul>
</li>
<li><p>다형성(Polymorphism)</p>
<ul>
<li>같은 이름의 메서드를 사용하지만, 다른 기능을 하는 것</li>
<li>오버라이딩(Overriding) : 부모 클래스의 메서드를 자식 클래스에서 재정의</li>
</ul>
</li>
<li><p>추상화(Abstraction)</p>
<ul>
<li>불필요한 구현 세부사항을 숨기고 필요 기능만 외부에 제공함</li>
<li>추상 클래스와 인터페이스를 사용</li>
</ul>
</li>
</ol>
<hr>

<h3 id="예외-처리-예외-처리-계층과-종류">예외 처리, 예외 처리 계층과 종류</h3>
<h4 id="예외처리">예외처리</h4>
<p>예외처리란? : 객체 지향 프로그래밍(OOP)에서 오류 상황을 처리하는 방법중 하나. 예외처리를 통해 프로그램이 예상치 못한 상황을 제어하고 적절한 대응을 할 수 있음</p>
<ul>
<li><p>예외(Exception)
예외는 프로그램의 실행 중 발생하는 에러나 상황을 나타내는 객체. 일반적으로 코드 실행 중에 발생하는 오류를 처리하기 위해 사용.
예외는 특정한 예외 클래스로 표현되고, 예외 클래스는 예외 발생 시 정보를 담고 있는 속성과 예외 처리를 위한 메서드를 가지고 있음.</p>
</li>
<li><p>예외 처리 방법
try-catch 문을 사용해 구현. 
try 블록 내에서 예외가 발생할 수 있는 코드를 실행하고, catch 블록에서 예외를 처리하는 방식
예외 발생 시 try 블록의 실행이 중단되고, 해당 예외를 처리할 수 있는 catch 블록이 실행됨.
여러 개의 catch 블록을 사용하면 다양한 예외를 처리할 수 있음. 예외 클래스의 계층 구조를 활용해서 상위 예외 클래스부터 하위 예외 클래스로 처리 가능</p>
</li>
<li><p>예외 계층 구조
PHP 에서 예외 처리 계층은 아래와 같음.</p>
<blockquote>
<p><strong>Throwable</strong> -&gt; <strong>Exception</strong> &amp; <strong>Error</strong> -&gt; <strong>각각의 세부 클래스</strong>(RuntimeException, LoginException 혹은 TypeError, ParseError 등등)</p>
</blockquote>
</li>
</ul>
<h4 id="throwable">Throwable</h4>
<ul>
<li>PHP 예외 처리의 최상위 인터페이스. 모든 예외와 오류 객체는 해당 인터페이스를 구현함.</li>
<li>Exception 과 Error 는 Throwable 의 주요 구현체.</li>
</ul>
<pre><code>try {
    throw new Error(&quot;에러 출력&quot;);
} catch (Throwable $t) {
    echo &quot;출력 : &quot; . $t-&gt;getMessage();
}</code></pre><ul>
<li>Throwable 을 통해 객체 지향적 예외 처리가 가능함.</li>
<li>Throwable 에서 제공하는 메서드로는 이런 것들이 있음.<pre><code>$t-&gt;getMessage() // 예외 혹은 에러의 메시지 반환
 $t-&gt;getCode() // 예외 혹은 에러의 코드(정수)를 반환
 $t-&gt;getFile() // 예외 혹은 에러가 발생한 파일 경로 반환
 $t-&gt;getLine() // 예외 혹은 에러가 발생한 파일 라인 번호 반환
 $t-&gt;getTrace() // 예외 혹은 에러의 스택 트레이스를 배열 형태 반환
 $t-&gt;getTraceAsString() // 예외 혹은 에러의 스택 트레이스를 문자열 형태 반환
 $t-&gt;__toString() // 예외 혹은 에러 객체를 문자열로 표현</code></pre></li>
</ul>
<h4 id="exception">Exception</h4>
<ul>
<li><p>Exception 클래스는 Throwable 에서 정의된 메서드 getMessage(), getCode() 등을 상속받아 사용 가능.</p>
</li>
<li><p>애플리케이션 실행 중에 발생하는 예외를 다루고 있는데, Error 는 치명적인 오류인데 반해 Exception 은 복구가 가능한 오류를 나타냄</p>
</li>
<li><p>Exception 클래스는 크게 LogicException 과 RuntimeException 이 있고 하위 클래스를 가진 계층 구조</p>
<pre><code>// Exception 의 대표적인 클래스들 계층 구조
Exception
├── LogicException
│   ├── BadMethodCallException
│   ├── DomainException
│   ├── InvalidArgumentException
│   ├── LengthException
│   └── OutOfBoundsException
├── RuntimeException
    ├── OutOfRangeException
    ├── OverflowException
    ├── UnderflowException
    └── UnexpectedValueException</code></pre></li>
<li><p>Exception 클래스를 확장하면 사용자 정의 예외 클래스를 생성할 수 있음</p>
</li>
<li><p>Exception 클래스의 생성자</p>
<pre><code>__construct(string $message = &quot;&quot;, int $code = 0, ?Throwable $previous = null)</code></pre><p>  $message : 예외 메시지로 기본값은 빈 문자열
  $code : 예외 코드(정수)로 기본값은 0
  $previous : 이전 예외를 연결할 때 사용</p>
</li>
<li><p>예외 처리 키워드로는 try, catch, finally, throw 가 있음</p>
<ul>
<li>try : 예외 발생 가능성 있는 코드 실행 블럭</li>
<li>catch : 발생한 예외 처리 블럭</li>
<li>finally : 예외 발생 여부와 상관없이 실행되는 블럭</li>
<li>throw : 예외를 명시적으로 발생</li>
</ul>
</li>
<li><p>예외 체인(Previous Exception)을 사용해 여러 예외를 연결할 수 있음</p>
<pre><code>try {
    try {
        throw new Exception(&quot;첫번째 예외&quot;);
    } catch (Exception $e) {
        throw new Exception(&quot;두번째 예외&quot;, 0, $e);
    }
} catch (Exception $e) {
    echo &quot;Msg: &quot; . $e-&gt;getMessage() . &quot;\n&quot;;
    echo &quot;Previous: &quot; . $e-&gt;getPrevious()-&gt;getMessage();
}</code></pre></li>
</ul>
<h4 id="error">Error</h4>
<ul>
<li><p>Exception 과 동일하게 Throwable 의 구현체이기 때문에 Throwable 의 메서드들을 사용 가능함</p>
</li>
<li><p>Error 클래스는 치명적인 오류를 객체로 처리할 수 있도록 제공되는 클래스라는 차이점이 있고 PHP 엔진에서 자동으로 발생하는 오류임. 나머지는 Exception 과 유사함</p>
</li>
<li><p>Exception 과 동일한 생성자 형태를 가지고 있음</p>
</li>
<li><p>Error 의 주요 하위 클래스</p>
<pre><code>Throwable
└── Error
    ├── TypeError
    ├── ParseError
    ├── ArithmeticError
    │   └── DivisionByZeroError
    └── AssertionError</code></pre></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[공부한 것들]]></title>
            <link>https://velog.io/@ss_g/cdh10w1f</link>
            <guid>https://velog.io/@ss_g/cdh10w1f</guid>
            <pubDate>Sat, 11 Jan 2025 11:31:10 GMT</pubDate>
            <description><![CDATA[<h3 id="질문-리뷰">질문 리뷰</h3>
<h3 id="q-파이썬과-자바는-인터프리터-컴파일-컴파일과-런타임">Q. 파이썬과 자바는 인터프리터? 컴파일? (컴파일과 런타임)</h3>
<p>기계어(Machine Language) : CPU 가 직접 이해할 수 있는 0 과 1 로 구성된 이진 코드
어셈블리어(Assembly Language) : 기계어에 대한 프로그래밍 저급 언어로 기계어와 1:1 매핑됨</p>
<p><strong>사람이 쓰는 개발언어를 기계어로 번역해주는 것이 컴파일러(Compiler) 와 인터프리터(Interpreter)</strong></p>
<p><strong>컴파일러(Compiler)</strong> : 고급 프로그래밍 언어로 작성된 프로그램 소스 코드 전체를 스캔해서 이를 모두 기계어로 한번에 번역해서 실행파일을 생성</p>
<ul>
<li>C++, Java, Kotlin 등에서 컴파일러 사용<ul>
<li>장점</li>
<li>초기 스캔은 오래 걸리나, 한번 스캔을 마치고 나면 실행파일을 만들어두고 계속 사용하기 때문에 실행 속도는 인터프리터보다 빠름</li>
<li>오류 메시지 생성시 전체 코드를 검사한 후 오류 메시지를 생성하기에 실행 전 오류를 발견할 수 있음</li>
<li>배포 시 소스코드가 아닌 실행 파일을 제공하기 때문에 소스코드가 노출되지 않아 보안성이 높음</li>
<li>생성된 실행파일은 컴파일된 환경과 무관하게 독립적으로 실행이 가능함</li>
<li>단점</li>
<li>소스가 길고 복잡해질수록 초기 스캔시간 및 컴파일 시간이 길어짐</li>
<li>기계어로 번역시 오브젝트 코드(Object Code) 파일을 만드는데, 이를 다시 묶어서 하나의 실행 파일로 만드는 링킹(Linking) 작업을 해야함.
그러므로 인터프리터보다 많은 메모리를 사용함</li>
</ul>
</li>
</ul>
<p><strong>인터프리터(Interpreter)</strong> : 고급 프로그래밍 언어로 작성된 프로그램 소스 코드를 한 줄씩 읽고 즉시 실행</p>
<ul>
<li>Python, JavaScript, Ruby 등이 인터프리터 언어</li>
<li>장점<ul>
<li>코드를 한 줄씩 실행하기 때문에, 에러를 빠르게 찾고 수정할 수 있으며, 코드 변경시 빌드 과정이 따로 필요 없어 테스트 및 개발 속도가 빠른편</li>
<li>링킹 과정을 거치지 않기 때문에 메모리 효율이 좋음</li>
<li>소스 코드만 있다면 다양한 플랫폼에서 실행 가능</li>
</ul>
</li>
<li>단점<ul>
<li>매번 코드를 한 문장씩 읽고 번역하고 실행하는 과정을 거치기 때문에 컴파일러에 비해 실행 속도가 느림</li>
<li>모든 소스를 사전에 검사하지 않기 때문에 런타임 도중에만 발견되는 오류를 미리 확인할 수 없음</li>
</ul>
</li>
</ul>
<p><strong>런타임(Runtime)</strong> : 특정 프로그램이 실제로 실행되는 동안의 동작
특정 프로그램이 필요로 하는 시스템 자원(RAM, 시스템 변수, 환경변수 등) 을 할당받고 실제로 시스템 자원을 사용해 어떠한 처리를 하는 동작
<strong>런타임 환경(Runtime Environment)</strong> : 애플리케이션이 OS 의 시스템 자원(RAM, 시스템 변수, 환경변수 등) 에 액세스 할 수 있도록 해주는 실행 환경</p>
<h3 id="q-i-와-i-는-같은-자료형인가">Q. i 와 I 는 같은 자료형인가?</h3>
<p>자료형은 같게 저장할 수 있으나 각 자료형 별 저장된 값이 상이할 수 있음</p>
<ul>
<li>i 와 I 를 자료형 별로 저장시</li>
</ul>
<ol>
<li>char : 기본 문자 자료형 그대로 저장</li>
<li>String : 문자나 문자열 저장</li>
<li>int, byte, short, long : ASCII/유니코드 값으로 저장</li>
<li>Character : 래퍼 클래스로 저장</li>
<li>float, double : ASCII/유니코드 값을 부동소수점으로 변환해서 저장<h3 id="q-객체자료형의-특징">Q. 객체자료형의 특징</h3>
<h3 id="q-call-by-value-와-call-by-reference">Q. Call By Value 와 Call By Reference</h3>
Call By Value(값에 의한 호출)</li>
</ol>
<ul>
<li>함수가 인수로 전달받은 값을 복사하여 처리하는 방식</li>
<li>변수가 가진 값을 복사하여 전달하므로 원본 값은 변경되지 않음. 값의 불변성(Immutability) 을 유지하는데 용이</li>
<li>실제 인수는 다른 메모리 위치에 생성됨</li>
</ul>
<p>Call By Reference(참조에 의한 호출)</p>
<ul>
<li>값의 주소를 참조해서 직접 값에 영향을 주는 방식</li>
<li>변수 값을 변경하면, 호출한 쪽에서 해당 변수의 값이 변경됨.
이는 전달되는 값이 변수의 주소이므로, 변수의 값을 변경하면 해당 주소에 저장된 값이 변경되기 때문</li>
<li>실제 인수는 같은 메모리 위치에 생성됨</li>
<li>Call By Reference 에서 기존 값이 영향 받는 단점을 보완할 수 있는 방법으로 깊은 복사(Deep Copy) 를 이용하는 방법이 있음.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/ss_g/post/ba946e1e-11a5-4ea2-8555-873740d75365/image.png" alt=""></p>
<h3 id="q-깊은복사와-얕은복사">Q. 깊은복사와 얕은복사</h3>
<ul>
<li><p>깊은 복사(Deep Copy) </p>
<ul>
<li>실제 값 복사</li>
<li>객체의 모든 필드를 복사해서 새로운 객체를 생성함. 객체의 상태를 완전히 복제할 때 사용</li>
<li>메모리를 많이 사용하고, 복사 과정에서 성능 저하 발생할 수 있음</li>
</ul>
</li>
<li><p>얕은 복사(Shallow Copy)    </p>
<ul>
<li>주소 값 복사</li>
<li>객체의 참조 주소만 복사하여 새로운 객체를 생성함. 객체의 참조 주소만 복사하기 때문에 원본 객체와 복사된 객체가 동일한 데이터를 참조</li>
<li>메모리를 적게 사용하고, 성능이 뛰어남. 하지만 참조된 데이터를 변경하면 원본 데이터에도 영향을 끼침</li>
</ul>
</li>
</ul>
<table>
<thead>
<tr>
<th><strong>특징</strong></th>
<th><strong>얕은 복사 (Shallow Copy)</strong></th>
<th><strong>깊은 복사 (Deep Copy)</strong></th>
</tr>
</thead>
<tbody><tr>
<td><strong>복사 방식</strong></td>
<td>1차 데이터만 복사, 참조 데이터는 주소 복사</td>
<td>모든 데이터와 참조 데이터까지 재귀적으로 복사</td>
</tr>
<tr>
<td><strong>원본과의 독립성</strong></td>
<td>복사본과 원본이 참조 데이터 공유</td>
<td>복사본과 원본이 완전히 독립적</td>
</tr>
<tr>
<td><strong>수행 속도</strong></td>
<td>상대적으로 빠름</td>
<td>상대적으로 느림</td>
</tr>
<tr>
<td><strong>메모리 사용량</strong></td>
<td>원본과 공유하므로 적음</td>
<td>복제된 데이터를 저장하므로 많음</td>
</tr>
<tr>
<td><strong>데이터 변경 영향</strong></td>
<td>참조 데이터 변경 시 원본에 영향</td>
<td>복사본 변경 시 원본에 영향 없음</td>
</tr>
</tbody></table>
<br>
<hr>


<h3 id="과제">과제</h3>
<br>

<h3 id="기초-단계-질문기본-개념">기초 단계 질문(기본 개념)</h3>
<h3 id="q-자료형이란-무엇이며-왜-필요한가요">Q. 자료형이란 무엇이며, 왜 필요한가요?</h3>
<p>자료형(Data Type) : 데이터를 구성하고 관리하는 기본 개념으로, 데이터의 크기, 형식, 해석 방식을 정의.</p>
<p><strong>자료형의 필요&amp;중요 이유</strong></p>
<ol>
<li><p>데이터, 메모리 관리</p>
<ul>
<li>자료형은 데이터의 크기와 형식을 정의하는데, 이때 자료형을 명시함으로서 프로그램이 데이터를 메모리에 효율적으로 저장 및 관리할 수 있음</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>
<h3 id="q-정적-타입과-동적-타입의-차이점은-무엇인가요">Q. 정적 타입과 동적 타입의 차이점은 무엇인가요?</h3>
<table>
<thead>
<tr>
<th><strong>특징</strong></th>
<th><strong>정적 타입</strong></th>
<th><strong>동적 타입</strong></th>
</tr>
</thead>
<tbody><tr>
<td><strong>타입 결정 시점</strong></td>
<td>컴파일 시점</td>
<td>런타임 시점</td>
</tr>
<tr>
<td><strong>자료형 선언</strong></td>
<td>명시적으로 선언하거나 컴파일러가 추론</td>
<td>선언 필요 없음</td>
</tr>
<tr>
<td><strong>타입 검사</strong></td>
<td>컴파일러가 타입을 검사</td>
<td>런타임에 인터프리터가 타입을 검사</td>
</tr>
<tr>
<td><strong>유연성</strong></td>
<td>낮음</td>
<td>높음</td>
</tr>
<tr>
<td><strong>오류 탐지 시점</strong></td>
<td>컴파일 단계에서 오류를 탐지</td>
<td>런타임에서 오류를 탐지</td>
</tr>
<tr>
<td><strong>주요 언어</strong></td>
<td>C, C++, Java, TypeScript, Go</td>
<td>Python, JavaScript, Ruby, PHP</td>
</tr>
<tr>
<td><strong>성능</strong></td>
<td>일반적으로 빠름</td>
<td>상대적으로 느릴 수 있음</td>
</tr>
</tbody></table>
<h3 id="q-기본-데이터-타입primitive-types-과-참조-타입reference-types-의-차이는-무엇인가요">Q. 기본 데이터 타입(primitive types) 과 참조 타입(reference types) 의 차이는 무엇인가요?</h3>
<p><strong>기본 데이터 타입(primitive types)</strong> : 기본적인 데이터 구조로 값 자체를 메모리에 저장하기에 크기가 고정되어 있음</p>
<p><strong>참조 타입(reference types)</strong> : 실제 데이터는 메모리의 다른 위치에 저장되고, 변수는 해당 데이터의 참조(주소)를 저장함. 주로 객체, 배열, 함수 등의 복잡한 데이터 구조를 다룸</p>
<table>
<thead>
<tr>
<th><strong>특징</strong></th>
<th><strong>Primitive Types</strong></th>
<th><strong>Reference Types</strong></th>
</tr>
</thead>
<tbody><tr>
<td><strong>저장 방식</strong></td>
<td>값 자체를 저장</td>
<td>값의 메모리 주소를 저장</td>
</tr>
<tr>
<td><strong>메모리 할당</strong></td>
<td>스택(Stack)</td>
<td>힙(Heap)에 데이터 저장, 스택에는 참조 저장</td>
</tr>
<tr>
<td><strong>크기</strong></td>
<td>고정 크기</td>
<td>크기가 동적</td>
</tr>
<tr>
<td><strong>값 복사</strong></td>
<td>값을 복사 (독립적)</td>
<td>참조를 복사 (공유됨)</td>
</tr>
<tr>
<td><strong>변경 가능성</strong></td>
<td>대부분 불변</td>
<td>대부분 변경 가능</td>
</tr>
<tr>
<td><strong>성능</strong></td>
<td>빠름</td>
<td>참조를 따라가야 하므로 상대적으로 느릴 수 있음</td>
</tr>
<tr>
<td><strong>주요 예시</strong></td>
<td>숫자, 문자, 불리언 등</td>
<td>객체, 배열, 리스트, 함수 등</td>
</tr>
</tbody></table>
<h3 id="q-타입변환">Q. 타입변환</h3>
<p><strong>타입변환</strong> : 하나의 데이터 타입을 다른 데이터 타입으로 변환하는 과정으로 서로 다른 데이터 타입 간의 연산이나 호환성을 위해 사용함</p>
<p><strong>명시적 형변환(Explicit Conversion)</strong></p>
<ul>
<li>정의<ul>
<li>개발자가 명시적으로 변환 함수 혹은 캐스팅 연산자를 사용해 데이터 타입 변환을 요청</li>
<li>타입 캐스팅(Type Casting)으로 불림</li>
</ul>
</li>
<li>특징<ul>
<li>개발자의 명확한 의도 파악 가능</li>
<li>변환 과정에서 데이터 손실 발생 가능</li>
</ul>
</li>
</ul>
<p><strong>묵시적 형변환(Implicit Conversion)</strong></p>
<ul>
<li>정의<ul>
<li>컴파일러나 인터프리터가 자동으로 데이터 타입을 변환하는 방식</li>
</ul>
</li>
<li>특징<ul>
<li>개발자가 직접 변환 코드를 작성하지 않음</li>
<li>시스템이 변환해도 된다고 판단하는 경우 변환을 자동으로 수행함</li>
<li>데이터 손실이 일어나지 않음</li>
</ul>
</li>
</ul>
<p><strong>주의사항</strong></p>
<ul>
<li>묵시적 변환시에는 자동변환되어 예상치 못한 결과값이 도출될 수 있음</li>
<li>명시적 변환 시 데이터의 크기나 범위가 다를 경우 데이터 손실이 일어날 수 있음</li>
</ul>
<h3 id="q-묵시적-형변환과-명시적-형변환의-차이점은-무엇인가요">Q. 묵시적 형변환과 명시적 형변환의 차이점은 무엇인가요?</h3>
<table>
<thead>
<tr>
<th><strong>특징</strong></th>
<th><strong>명시적 변환 (Explicit Conversion)</strong></th>
<th><strong>묵시적 변환 (Implicit Conversion)</strong></th>
</tr>
</thead>
<tbody><tr>
<td><strong>변환 요청 주체</strong></td>
<td>개발자가 명시적으로 요청</td>
<td>컴파일러나 인터프리터가 자동 수행</td>
</tr>
<tr>
<td><strong>코드 가독성</strong></td>
<td>변환 과정이 명확히 드러남</td>
<td>변환 과정이 코드에 드러나지 않음</td>
</tr>
<tr>
<td><strong>데이터 손실 가능성</strong></td>
<td>발생할 수 있음</td>
<td>안전한 변환만 수행</td>
</tr>
<tr>
<td><strong>사용 용이성</strong></td>
<td>변환 함수나 캐스팅 연산자를 명시적으로 사용해야 함</td>
<td>추가 코드 작성 없이 자동 변환</td>
</tr>
<tr>
<td><strong>변환 방향</strong></td>
<td>데이터 크기와 무관하게 변환 가능</td>
<td>작은 크기/범위 → 큰 크기/범위로만 변환</td>
</tr>
</tbody></table>
<h3 id="q-형변환-시-발생할-수-있는-데이터-손실은-어떤-경우에-일어나나요">Q. 형변환 시 발생할 수 있는 데이터 손실은 어떤 경우에 일어나나요?</h3>
<p><img src="https://velog.velcdn.com/images/ss_g/post/3334edb4-155d-4451-b08d-46dc95d5d94d/image.png" alt=""></p>
<p>*long 은 8byte float 는 4byte 인데 왜 long-&gt;float 가 가능한지?
-&gt; 일반적으로 메모리 설계상 정수 타입보다 실수 타입이 더 크게 되어있기 때문
*char 타입은 문자 자료형이지만, 아스키 코드 숫자를 저장하기에 사실상 정수형 타입으로 볼 수 있음</p>
<p><strong>범위 초과</strong>
오버플로(Overflow) / 언더플로(Underflow)
    큰 자료형에서 작은 자료형으로 변환 시(ex long-&gt;int) 표현 범위를 벗어나는 부분은 잘리거나 왜곡된 값으로 변환될 수 있음</p>
<p><strong>크기 축소 변환</strong>
크기 축소 변환 : 큰 범위(크기) 의 데이터 타입에서 작은 범위(크기) 의 데이터 타입으로 변환시 일부 데이터가 잘리거나 왜곡될 수 있음</p>
<p>ex) 큰 정수형 -&gt; 작은 정수형 변환 시 데이터가 잘리거나 왜곡 되어 예상치 못한 데이터 발생(long-&gt;short) 에서 long 데이터가 short 로 담을 수 없는 경우</p>
<p><strong>정밀도 손실</strong>
정밀도 손실 : 데이터 변환 시 원래 값의 정밀도가 유지되지 못할 수 있음</p>
<p>ex) 실수-&gt;정수 변환 시 소수점 이하가 잘려나가고 부동소수점 연산(float-&gt;double, double-&gt;float) 에서 반올림 오차 발생 가능</p>
<br>
<br>

<h3 id="중급-단계-질문메모리와-자료형">중급 단계 질문(메모리와 자료형</h3>
<h3 id="q-각-자료형이-메모리에서-어떻게-저장되나요">Q. 각 자료형이 메모리에서 어떻게 저장되나요?</h3>
<p><strong>메모리 구조</strong></p>
<ul>
<li><p>코드 영역 (Text Segment)</p>
<ul>
<li>실행할 프로그램의 코드가 저장.</li>
<li>보통 읽기 전용.</li>
</ul>
</li>
<li><p>데이터 영역 (Data Segment)</p>
<ul>
<li>전역 변수와 정적 변수(static variables)가 저장.</li>
<li>프로그램이 종료될 때까지 유지.</li>
</ul>
</li>
<li><p>힙 영역 (Heap)</p>
<ul>
<li>동적 메모리 할당에 사용.</li>
<li>런타임에 필요에 따라 크기가 증가하거나 감소.</li>
</ul>
</li>
<li><p>스택 영역 (Stack)</p>
<ul>
<li>함수 호출 시 사용되는 지역 변수와 매개변수가 저장.</li>
<li>LIFO(Last In, First Out) 구조로 빠르게 접근.</li>
</ul>
</li>
</ul>
<p><strong>기본 자료형(Primitive Types) 저장 방식</strong></p>
<ul>
<li>특징<ul>
<li>메모리에 값을 직접 저장</li>
<li>보통 크기가 고정되어 있음</li>
</ul>
</li>
</ul>
<ul>
<li>저장 흐름</li>
</ul>
<ol>
<li><p>int</p>
<ul>
<li>정수는 2진수로 변환되어 메모리에 저장됨
  int a = 10; -&gt; 10을 2진수 00000000 00000000 00000000 00001010 로 변환 후 <strong>메모리에 4바이트 크기로 저장</strong></li>
</ul>
</li>
<li><p>float, double</p>
<ul>
<li>부동소수점 표현방식(IEEE 754 표준)을 사용
  float a = 1.23; -&gt; 1.23을 부동소수점 형식으로 변환 후 <strong>메모리에 4바이트 크기로 저장</strong></li>
</ul>
</li>
<li><p>char</p>
<ul>
<li>문자 하나를 저장하며 ASCII 혹은 Unicode 로 변환
  char a = &#39;A&#39;; -&gt; A 를 ASCII 값 65로 변환 후 <strong>메모리에 1바이트 크기로 저장</strong></li>
</ul>
</li>
<li><p>boolean</p>
<ul>
<li>참 또는 거짓 값을 <strong>메모리에 1비트 혹은 1바이트를 사용하여 저장</strong></li>
</ul>
</li>
</ol>
<p><strong>참조 자료형(Reference Types) 저장 방식</strong></p>
<ul>
<li>특징<ul>
<li>값 자체가 아니라 <strong>값의 메모리 주소(참조)</strong>를 저장</li>
<li>실제 데이터는 Heap 영역에 저장되고, 참조 변수는 Stack 영역에 저장</li>
</ul>
</li>
</ul>
<ol>
<li><p>Object</p>
<ul>
<li><p>객체 생성시 데이터는 힙 영역에 저장되고, 변수는 해당 객체의 메모리 주소를 저장함</p>
<pre><code>class Example {
    int x = 10;
}

Example obj = new Example();</code></pre><p>obj 는 스택에 생성되고, 힙에 생성된 객체 Example 의 메모리 주소를 가지게 됨</p>
</li>
</ul>
</li>
<li><p>Array</p>
<ul>
<li>힙 영역에 저장되며, 스택에는 배열의 참조가 저장됨<pre><code>int[] array = {1,2,3};</code></pre>array 는 스택에 저장되고, 배열 데이터 [1,2,3] 은 힙에 저장</li>
</ul>
</li>
<li><p>String</p>
<ul>
<li>문자열은 힙에 저장되지만, 같은 값을 가진 문자열은 메모리 방지를 줄이기 위해 <strong>문자열 상수 풀(String Pool)</strong>에 저장되기도 함</li>
</ul>
</li>
</ol>
<br>

<table>
<thead>
<tr>
<th><strong>자료형</strong></th>
<th><strong>저장 위치</strong></th>
<th><strong>저장 내용</strong></th>
</tr>
</thead>
<tbody><tr>
<td><strong>Primitive</strong></td>
<td>스택</td>
<td>값 자체 (예: int, float, char)</td>
</tr>
<tr>
<td><strong>Reference</strong></td>
<td>스택 &amp; 힙</td>
<td>스택에 참조(주소), 힙에 실제 데이터 저장</td>
</tr>
<tr>
<td><strong>전역 변수</strong></td>
<td>데이터 영역</td>
<td>프로그램 실행 동안 지속</td>
</tr>
<tr>
<td><strong>동적 할당</strong></td>
<td>힙</td>
<td>힙에 데이터 저장, 스택에 참조 저장</td>
</tr>
<tr>
<td><strong>코드</strong></td>
<td>코드 영역</td>
<td>실행할 명령어 저장</td>
</tr>
</tbody></table>
<h3 id="q-문자열이-메모리에-저장되는-방식은-어떻게-다른가요">Q. 문자열이 메모리에 저장되는 방식은 어떻게 다른가요?</h3>
<ul>
<li>문자열의 특징</li>
</ul>
<ol>
<li><p>Immutable(불변성)</p>
<ul>
<li>Java 에서는 문자열은 불변이므로 문자열 생성 이후 내용 변경 불가능. 
새로운 문자열이 만들어지면 기존 문자열 수정이 아닌 새로운 객체 생성</li>
</ul>
</li>
<li><p>String Pool 사용</p>
<ul>
<li><p>Java 는 문자열 상수 풀(String Pool) 이라는 특별한 메모리 영역을 사용해서 문자열의 중복 생성을 방지하고 메모리 사용량을 최적화함</p>
<pre><code>String str1 = &quot;Hello&quot;;
String str2 = &quot;Hello&quot;;  // str1과 동일한 문자열 참조
</code></pre></li>
</ul>
</li>
</ol>
<ul>
<li>문자열 저장 방식</li>
</ul>
<ol>
<li>new 연산자 이용<ul>
<li>값의 중복 여부에 상관없이 힙 영역에 인스턴스가 생성됨.</li>
</ul>
</li>
<li>문자열 리터럴 생성<ul>
<li>리터럴 방식으로 저장시 힙 메모리 안의 String Pool 에 값을 저장함. 이후 똑같은 문자열을 저장하려고 하면 앞서 만들어둔 인스턴스의 주소값을 참조함
<img src="https://velog.velcdn.com/images/ss_g/post/2e5de486-bf95-4f43-9f68-6e69346df925/image.png" alt=""></li>
</ul>
</li>
</ol>
<h3 id="q-포인터와-참조의-차이점은-무엇인가요">Q. 포인터와 참조의 차이점은 무엇인가요?</h3>
<p><strong>포인터(Pointer)</strong></p>
<ul>
<li>메모리 주소 저장 변수</li>
<li>변수나 객체의 메모리 주소를 직접 조작 가능</li>
</ul>
<p><strong>참조(Reference)</strong></p>
<ul>
<li>변수나 객체에 대한 별칭(alias)</li>
<li>참조 사용시 변수 자체처럼 동작하지만, 실제로는 원본 데이터를 참조함</li>
<li>직접 주소를 조작하지 않음</li>
</ul>
<table>
<thead>
<tr>
<th><strong>특징</strong></th>
<th><strong>포인터 (Pointer)</strong></th>
<th><strong>참조 (Reference)</strong></th>
</tr>
</thead>
<tbody><tr>
<td><strong>메모리 주소</strong></td>
<td>메모리 주소를 저장</td>
<td>별칭(alias)로, 내부적으로 주소를 사용</td>
</tr>
<tr>
<td><strong>NULL 가능성</strong></td>
<td>NULL 값을 가질 수 있음</td>
<td>NULL을 가질 수 없음 (항상 유효해야 함)</td>
</tr>
<tr>
<td><strong>선언 및 초기화</strong></td>
<td>선언 후 초기화하지 않아도 됨</td>
<td>선언과 동시에 초기화가 필요</td>
</tr>
<tr>
<td><strong>재할당 가능 여부</strong></td>
<td>다른 주소를 가리키도록 변경 가능</td>
<td>초기화 이후 다른 객체를 참조할 수 없음</td>
</tr>
<tr>
<td><strong>연산 가능 여부</strong></td>
<td>주소를 기반으로 산술 연산 가능</td>
<td>직접 연산 불가</td>
</tr>
<tr>
<td><strong>사용 목적</strong></td>
<td>메모리 주소의 직접 조작, 동적 메모리 관리</td>
<td>변수나 객체에 대한 간편하고 안전한 접근</td>
</tr>
</tbody></table>
<h3 id="q-배열과-컬렉션">Q. 배열과 컬렉션</h3>
<p><strong>배열(Array)</strong></p>
<ul>
<li>동일한 타입의 요소를 연속적인 메모리 공간에 저장하는 고정 크기의 데이터구조</li>
<li>인덱스를 사용하여 요소에 접근하고, 인덱스는 0부터 시작함</li>
<li>특징</li>
</ul>
<ol>
<li>고정 크기 : 배열 크기는 선언 시점에 고정되고, 실행중 변경 불가</li>
<li>단일 타입 저장 : 동일한 데이터 타입의 요소만 저장 가능</li>
<li>인덱스를 통한 접근 : 인덱스를 통해 O(1) 시간 복잡도로 접근 가능</li>
<li>연속된 메모리 공간 사용 : 메모리에 연속적으로 저장되어있기에 데이터 처리 속도가 빠름</li>
</ol>
<p><strong>컬렉션(Collection)</strong></p>
<ul>
<li>객체의 그룹을 저장하고 조작하기 위한 데이터 구조로, 배열보다 유연함</li>
<li>크기가 동적이고, 다양한 데이터 타입의 요소를 저장할 수 있는 구조 제공</li>
<li>특징</li>
</ul>
<ol>
<li>동적 크기 : 컬렉션은 데이터의 추가/삭제에 따라 크기가 자동으로 조정됨</li>
<li>다양한 데이터 타입 : 대부분의 컬렉션은 여러 데이터 타입의 객체를 저장 가능</li>
<li>데이터 추가, 삭제, 검색, 정렬, 필터링 등의 기능 제공</li>
<li>List, Set, Map 등의 인터페이스와 그 구현체 ArrayList, HashSet, HashMap 이 제공됨</li>
<li>비연속적 메모리 할당 : 요소가 반드시 연속된 메모리 공간에 저장되지 않아도 됨</li>
</ol>
<table>
<thead>
<tr>
<th><strong>특징</strong></th>
<th><strong>배열 (Array)</strong></th>
<th><strong>컬렉션 (Collection)</strong></th>
</tr>
</thead>
<tbody><tr>
<td><strong>크기</strong></td>
<td>고정 크기</td>
<td>동적 크기</td>
</tr>
<tr>
<td><strong>데이터 타입</strong></td>
<td>동일한 데이터 타입의 요소만 저장 가능</td>
<td>다양한 데이터 타입의 객체 저장 가능</td>
</tr>
<tr>
<td><strong>메모리 구조</strong></td>
<td>연속된 메모리 공간에 저장</td>
<td>비연속적인 메모리 공간에 저장 가능</td>
</tr>
<tr>
<td><strong>기능성</strong></td>
<td>제한적 (추가/삭제/정렬 등의 기능 없음)</td>
<td>추가, 삭제, 검색, 정렬 등 고급 기능 제공</td>
</tr>
<tr>
<td><strong>성능</strong></td>
<td>빠름 (특히 인덱스 기반 접근)</td>
<td>성능은 구현체에 따라 다름 (HashMap 등은 빠름)</td>
</tr>
<tr>
<td><strong>사용 목적</strong></td>
<td>고정된 크기의 단순 데이터 저장</td>
<td>동적으로 크기가 변하는 데이터 저장 및 관리</td>
</tr>
<tr>
<td><strong>사용 예</strong></td>
<td>정수 배열, 문자 배열 등</td>
<td>리스트, 셋, 맵 등</td>
</tr>
</tbody></table>
<table>
<thead>
<tr>
<th><strong>사용 상황</strong></th>
<th><strong>배열 (Array)</strong></th>
<th><strong>컬렉션 (Collection)</strong></th>
</tr>
</thead>
<tbody><tr>
<td><strong>데이터 크기가 고정</strong></td>
<td>배열이 적합</td>
<td>불필요하게 메모리를 낭비할 수 있음</td>
</tr>
<tr>
<td><strong>데이터 크기가 유동적</strong></td>
<td>부적합</td>
<td>크기가 동적으로 조정되는 컬렉션이 적합</td>
</tr>
<tr>
<td><strong>단순 데이터 저장 및 접근</strong></td>
<td>배열이 적합</td>
<td>컬렉션의 오버헤드가 불필요</td>
</tr>
<tr>
<td><strong>데이터 추가, 삭제, 정렬, 검색 등의 작업 필요</strong></td>
<td>구현하기 어려움</td>
<td>컬렉션이 적합 (이미 기능이 구현되어 있음)</td>
</tr>
<tr>
<td><strong>성능이 매우 중요한 경우 (고정 크기)</strong></td>
<td>배열이 적합 (연속된 메모리, 인덱스 접근 빠름)</td>
<td>컬렉션은 약간의 성능 오버헤드가 발생 가능</td>
</tr>
</tbody></table>
<h3 id="q-정적-배열과-동적-배열의-차이점은-무엇인가요">Q. 정적 배열과 동적 배열의 차이점은 무엇인가요?</h3>
<p><strong>정적 배열(Static Array)</strong></p>
<ul>
<li>컴파일 시점에 크기가 고정되는 배열로 메모리가 Stack 또는 데이터 영역에 할당됨</li>
<li>특징</li>
</ul>
<ol>
<li>고정된 크기 : 배열의 크기가 선언 시점에 정해지며, 실행중 변경 불가능</li>
<li>빠른 접근 속도 : 메모리가 연속적으로 할당되기 때문에 인덱스 기반 접근 속도가 빠름 </li>
<li>스택 메모리 사용 : 지역 변수로 선언된 정적 배열은 스택 메모리를 사용하기에 관리가 간단하지만 크기가 큰 배열은 메모리 부족 문제를 야기할 수 있음</li>
<li>크기가 고정되어 있어 데이터 크기가 가변적인 경우 유연성이 떨어짐</li>
</ol>
<p><strong>정적 배열(Dynamic Array)</strong></p>
<ul>
<li>런타임 시점에 크기가 결정되며, 필요에 따라 크기 조정 가능. 메모리가 Heap 영역에 할당됨</li>
<li>특징</li>
</ul>
<ol>
<li>크기 조정 가능 : 실행중 배열의 크기를 조정할 수 있어 유연성이 높음</li>
<li>힙 메모리 사용 : 메모리가 힙에 동적으로 할당되므로, 더 큰 크기의 배열 처리 가능</li>
<li>메모리 관리 필요 : 동적으로 할당된 메모리는 명시적으로 해제하는 등의 관리를 하지 않으면 메모리 누수 발생 가능</li>
<li>추가 오버헤드 : 크기를 변경하는 경우 기존 데이터 복사 및 새로운 메모리 할당으로 인해 오버헤드 발생 가능</li>
</ol>
<table>
<thead>
<tr>
<th><strong>특징</strong></th>
<th><strong>정적 배열 (Static Array)</strong></th>
<th><strong>동적 배열 (Dynamic Array)</strong></th>
</tr>
</thead>
<tbody><tr>
<td><strong>크기 결정 시점</strong></td>
<td>컴파일 시점</td>
<td>런타임 시점</td>
</tr>
<tr>
<td><strong>메모리 할당 위치</strong></td>
<td>스택(Stack) 또는 데이터 영역</td>
<td>힙(Heap)</td>
</tr>
<tr>
<td><strong>크기 조정</strong></td>
<td>불가능</td>
<td>가능</td>
</tr>
<tr>
<td><strong>성능</strong></td>
<td>빠름 (메모리가 연속적으로 할당됨)</td>
<td>약간 느림 (동적 메모리 할당 및 복사 필요)</td>
</tr>
<tr>
<td><strong>메모리 관리</strong></td>
<td>자동 (스택 메모리는 함수 종료 시 해제됨)</td>
<td>명시적으로 해제해야 함 (delete 또는 free)</td>
</tr>
<tr>
<td><strong>유연성</strong></td>
<td>낮음</td>
<td>높음</td>
</tr>
</tbody></table>
<h3 id="q-arraylist-와-linkedlist-의-성능-차이는-어떻게-되나요">Q. ArrayList 와 LinkedList 의 성능 차이는 어떻게 되나요?</h3>
<p><strong>ArrayList</strong></p>
<ul>
<li>배열 기반의 List 구현체로 내부적으로 동적 배열을 사용해서 데이터를 저장</li>
<li>초기 용량 초과시 새로운 배열을 생성하고 기존 데이터를 복사해서 저장</li>
<li>인덱스를 사용해서 요소에 접근하기 때문에 요소 접근 속도 빠름.</li>
<li>요소 추가, 삭제 시 배열 크기가 조정되므로 빈번한 요소 추가와 삭제 발생은 성능이 저하될 수 있음</li>
<li>사용 사례</li>
</ul>
<ol>
<li>인덱스를 통한 접근이 가능할 때</li>
<li>삽입/삭제 동작이 적고 읽기 위주의 작업이 많을 때</li>
<li>메모리 효율이 중요할 경우 : 배열 기반이므로 메모리 오버헤드가 적기 때문</li>
</ol>
<p><strong>LinkedList</strong></p>
<ul>
<li>연결 리스트 기반의 List 구현체로 각 요소가 이전 요소와 다음 요소의 참조를 가지고 있음</li>
<li>요소 추가, 삭제시 참조만 변경하면 되기에 해당 동작시 성능이 우수함</li>
<li>사용 사례</li>
</ul>
<ol>
<li>삽입/삭제가 빈번할 때</li>
<li>데이터 크기가 동적으로 변할 때</li>
<li>메모리 효율이 크게 중요하지 않을 때</li>
</ol>
<p><strong>ArrayList 와 LinkedList 의 차이</strong></p>
<table>
<thead>
<tr>
<th><strong>특징</strong></th>
<th><strong>ArrayList</strong></th>
<th><strong>LinkedList</strong></th>
</tr>
</thead>
<tbody><tr>
<td><strong>내부 구현 방식</strong></td>
<td>동적 배열</td>
<td>이중 연결 리스트</td>
</tr>
<tr>
<td><strong>데이터 저장 방식</strong></td>
<td>연속된 메모리 블록</td>
<td>분리된 노드(각 노드는 데이터와 참조를 포함)</td>
</tr>
<tr>
<td><strong>인덱스 접근 속도</strong></td>
<td>빠름 (O(1), 배열 인덱스 접근)</td>
<td>느림 (O(n), 순차적으로 노드 탐색 필요)</td>
</tr>
<tr>
<td><strong>삽입/삭제 (중간 위치)</strong></td>
<td>느림 (O(n), 요소 이동 필요)</td>
<td>빠름 (O(1), 노드 참조만 변경)</td>
</tr>
<tr>
<td><strong>삽입/삭제 (끝 위치)</strong></td>
<td>빠름 (O(1), 크기 초과 시 O(n))</td>
<td>빠름 (O(1))</td>
</tr>
<tr>
<td><strong>메모리 사용량</strong></td>
<td>적음 (배열 기반, 추가 메모리 오버헤드 적음)</td>
<td>많음 (노드별 추가 참조 필드 및 메모리 할당)</td>
</tr>
</tbody></table>
<br>

<p><strong>두 List의 성능 차이</strong></p>
<table>
<thead>
<tr>
<th><strong>연산</strong></th>
<th><strong>ArrayList</strong></th>
<th><strong>LinkedList</strong></th>
</tr>
</thead>
<tbody><tr>
<td><strong>인덱스 접근</strong></td>
<td>빠름 (O(1))</td>
<td>느림 (O(n))</td>
</tr>
<tr>
<td><strong>삽입 (끝)</strong></td>
<td>빠름 (O(1), 동적 확장 시 O(n))</td>
<td>빠름 (O(1))</td>
</tr>
<tr>
<td><strong>삽입 (중간)</strong></td>
<td>느림 (O(n))</td>
<td>느림 (O(n), 탐색 포함)</td>
</tr>
<tr>
<td><strong>삭제 (끝)</strong></td>
<td>빠름 (O(1))</td>
<td>빠름 (O(1))</td>
</tr>
<tr>
<td><strong>삭제 (중간)</strong></td>
<td>느림 (O(n))</td>
<td>느림 (O(n), 탐색 포함)</td>
</tr>
<tr>
<td><strong>메모리 효율성</strong></td>
<td>높음</td>
<td>낮음</td>
</tr>
</tbody></table>
<h3 id="q-제네릭스를-사용하는-이유는-무엇인가요">Q. 제네릭스를 사용하는 이유는 무엇인가요?</h3>
<p><strong>제네릭스(Generics)</strong></p>
<ul>
<li>Java 에서 타입을 일반화하는 방법으로 클래스, 메서드, 인터페이스에서 사용할 타입을 런타임이 아니라 컴파일 시점에 지정할 수 있도록 지원함.</li>
<li>데이터 타입을 파라미터화 하는 방식</li>
<li>제네릭스를 사용하면 특정 타입에 종속되지 않고, 다양한 타입을 지원하는 클래스나 메서드를 정의할 수 있음</li>
</ul>
<pre><code>ArrayList&lt;String&gt; list = new ArrayList&lt;&gt;();</code></pre><p>&lt;&gt; 가 제네릭스</p>
<table>
<thead>
<tr>
<th><strong>타입</strong></th>
<th><strong>설명</strong></th>
</tr>
</thead>
<tbody><tr>
<td><strong><code>&lt;T&gt;</code></strong></td>
<td>타입(Type)</td>
</tr>
<tr>
<td><strong><code>&lt;E&gt;</code></strong></td>
<td>요소(Element), ex) <code>List&lt;E&gt;</code></td>
</tr>
<tr>
<td><strong><code>&lt;K&gt;</code></strong></td>
<td>키(Key), ex) <code>Map&lt;K, V&gt;</code></td>
</tr>
<tr>
<td><strong><code>&lt;V&gt;</code></strong></td>
<td>리턴 값 또는 매핑된 값(Value), ex) <code>Map&lt;K, V&gt;</code></td>
</tr>
<tr>
<td><strong><code>&lt;N&gt;</code></strong></td>
<td>숫자(Number)</td>
</tr>
<tr>
<td><strong><code>&lt;S, U, V&gt;</code></strong></td>
<td>2번째, 3번째, 4번째에 선언된 타입</td>
</tr>
</tbody></table>
<ul>
<li>제네릭스 사용이유</li>
</ul>
<ol>
<li>타입 안정성 제공
 -컴파일 시점에 타입을 확인하여 타입 오류를 방지할 수 있고, 잘못된 타입 사용으로 인한 런타임 에러를 줄일 수 있음 </li>
<li>타입 캐스팅 제거<ul>
<li>제네릭스를 사용하면 명시적 타입 캐스팅이 필요 없어 코드 가독성과 유지보수성을 높일 수 있음 <pre><code>//제네릭스 없을 때
ArrayList list = new ArrayList(); // Raw 타입
list.add(&quot;Hello&quot;);
String str = (String) list.get(0); // 명시적 캐스팅 필요</code></pre><pre><code>//제네릭스 사용할 때
ArrayList&lt;String&gt; list = new ArrayList&lt;&gt;();
list.add(&quot;Hello&quot;);
String str = list.get(0); // 캐스팅 필요 없음</code></pre></li>
</ul>
</li>
<li>코드 재사용성 증가, 가독성 향상<ul>
<li>하나의 클래스나 메서드로 다양한 데이터 타입 처리 가능</li>
</ul>
</li>
</ol>
<br>
<br>

<h3 id="고급-단계-질문최적화와-성능">고급 단계 질문(최적화와 성능)</h3>
<h3 id="q-박싱boxing-과-언박싱unboxing-이-성능에-미치는-영향은-무엇인가요">Q. 박싱(Boxing) 과 언박싱(Unboxing) 이 성능에 미치는 영향은 무엇인가요?</h3>
<p><strong>래퍼 클래스(Wrapper Class)</strong></p>
<ul>
<li>기본 데이터 타입을 객체로 다룰수 있도록 제공되는 클래스</li>
</ul>
<table>
<thead>
<tr>
<th><strong>기본 타입</strong></th>
<th><strong>래퍼 클래스</strong></th>
</tr>
</thead>
<tbody><tr>
<td><code>byte</code></td>
<td><code>Byte</code></td>
</tr>
<tr>
<td><code>short</code></td>
<td><code>Short</code></td>
</tr>
<tr>
<td><code>int</code></td>
<td><code>Integer</code></td>
</tr>
<tr>
<td><code>long</code></td>
<td><code>Long</code></td>
</tr>
<tr>
<td><code>float</code></td>
<td><code>Float</code></td>
</tr>
<tr>
<td><code>double</code></td>
<td><code>Double</code></td>
</tr>
<tr>
<td><code>char</code></td>
<td><code>Character</code></td>
</tr>
<tr>
<td><code>boolean</code></td>
<td><code>Boolean</code></td>
</tr>
</tbody></table>
<br>

<p>**가비지 컬렉션(Garbage Collection)</p>
<ul>
<li>더 이상 사용되지 않는 객체(메모리)를 자동으로 식별하여 회수하고, 메모리 누수를 방지해 프로그램의 효율성을 유지하는 메모리 관리 방식</li>
<li>특징</li>
</ul>
<ol>
<li>자동 메모리 관리 : GC 가 더 이상 참조되지 않는 객체를 자동으로 회수해 메모리를 정리함</li>
<li>힙 메모리 관리 : GC 가 주로 Heap 메모리를 관리하며 동적으로 생성된 객체를 추적함</li>
<li>객체의 생명주기 관리 : 객체가 사용중인지, 더 이상 접근 불가한지 여부를 확인함</li>
<li>백그라운드에서 동작 : GC 는 JVM 이 자동으로 관리하며 프로그램 실행중에 백그라운드에서 작동함</li>
</ol>
<p><strong>박싱(Boxing)</strong></p>
<ul>
<li>기본 타입(Primitive Type) 데이터를 래퍼 클래스(Wrapper Class) 로 변환하는 과정
ex) int -&gt; integer, double -&gt; Double</li>
</ul>
<pre><code>int a = 10;
Integer boxed = Integer.valueOf(a); // 박싱
</code></pre><p><strong>언박싱(Unboxing)</strong></p>
<ul>
<li>래퍼 클래스 데이터를 기본 타입으로 변환하는 과정
ex) integer -&gt; int, Double -&gt; double</li>
</ul>
<pre><code>Integer boxed = 20;
int unboxed = boxed.intValue(); // 언박싱
</code></pre><p>** 오토박싱, 오토언박싱**</p>
<pre><code>int a = 10;
Integer boxed = a;    // 오토박싱
int unboxed = boxed;  // 오토언박싱</code></pre><p><strong>박싱과 언박싱이 성능에 미치는 영향</strong></p>
<ul>
<li>박싱과 언박싱의 성능 오버헤드</li>
</ul>
<ol>
<li>추가메모리 할당<ul>
<li>박싱 시 새로운 래퍼 객체 생성되는데, 추가적인 메모리 사용과 힙 할당을 필요로 하기에 성능에 영향을 미침</li>
</ul>
</li>
<li>객체관리<ul>
<li>박싱된 객체는 Heap 에 저장되며 가비지 컬렉션(Garbage Collection) 의 부담이 증가할 수 있음
(특히 많은 박싱/언박싱 연산이 발생하면 GC 횟수가 늘어나 성능저하 초래가능)</li>
</ul>
</li>
<li>메서드 호출 비용<ul>
<li>언박싱 과정에서 래퍼 클래스의 메서드가 호출되고, 이또한 성능에 영향을 미칠 수 있음</li>
</ul>
</li>
</ol>
<ul>
<li>반복 연산에서의 영향<ul>
<li>반복문에서의 많은 박싱, 언박싱이 일어나면 성능저하가 많이 발생할 수 있음</li>
</ul>
</li>
<li>메모리 사용의 영향<ul>
<li>기본 타입은 스택 메모리에 저장되어 메모리 사용량이 적지만,
박싱된 래퍼 클래스는 Heap 메모리에 저장되어 추가적인 오버헤드가 발생함</li>
</ul>
</li>
</ul>
<p><strong>박싱/언박싱 사용시 주의할점</strong></p>
<ol>
<li>성능에 민감한 작업에는 남용 금지 : 계산량이 많은 작업의 경우 박싱/언박싱으로 인해 성능저하 발생 가능</li>
<li>제네릭과 래퍼 클래스의 조합 : 제네릭 사용시 박싱/언박싱이 자동 발생하므로 성능에 영향을 미칠 수 있음을 인지해야함</li>
</ol>
<h3 id="q-불변-객체immutable-objects-를-사용하는-이유와-장단점은-무엇인가요">Q. 불변 객체(Immutable Objects) 를 사용하는 이유와 장단점은 무엇인가요?</h3>
<p><strong>불변 객체(Immutable Objects)</strong></p>
<ul>
<li>생성된 이후 상태를 변경할 수 없는 객체를 의미</li>
<li>특징</li>
</ul>
<ol>
<li>상태 변경 불가<ul>
<li>생성된 객체의 내부 상태가 변경되지 않음. 변경하려면 새로운 객체를 생성해야함</li>
</ul>
</li>
<li>스레드 안전성<ul>
<li>불변 객체는 변경되지 않기 때문에 멀티스레드 환경에서 동기화 없이 안전하게 사용 가능</li>
</ul>
</li>
<li>참조 투명성<ul>
<li>동일한 입력 값에 대해 항상 동일한 결과 반환</li>
</ul>
</li>
<li>캐싱 가능<ul>
<li>동일한 값의 불변 객체는 캐싱하여 재사용 가능</li>
</ul>
</li>
</ol>
<p><strong>사용 이유</strong></p>
<ol>
<li>안전성 : 멀티스레드 환경에서 동기화 없이도 안전하게 공유 가능</li>
<li>변경 불가 : 객체 상태가 변경되지 않아 예상하지 못한 부작용을 방지</li>
<li>캐싱 가능 : 동일한 값을 가진 객체를 재사용할 수 있어 메모리와 성능 최적화</li>
<li>디버깅 용이 : 객체의 상태가 변하지 않으므로 추적과 디버깅이 쉬움</li>
</ol>
<table>
<thead>
<tr>
<th><strong>장점</strong></th>
<th><strong>단점</strong></th>
</tr>
</thead>
<tbody><tr>
<td><strong>안전성</strong></td>
<td>변경되지 않으므로 스레드 간 안전하게 공유 가능.</td>
</tr>
<tr>
<td><strong>예측 가능성</strong></td>
<td>상태 변경이 불가능하므로 코드의 동작이 예측 가능.</td>
</tr>
<tr>
<td><strong>변경 추적</strong></td>
<td>상태가 변경되지 않아 디버깅과 문제 원인 추적이 쉬움.</td>
</tr>
<tr>
<td><strong>성능 최적화</strong></td>
<td>캐싱 및 공유를 통해 동일한 객체를 재사용 가능.</td>
</tr>
</tbody></table>
<h3 id="q-메모리-누수를-방지하기-위한-자료형-사용-전략은-어떻게-되나요">Q. 메모리 누수를 방지하기 위한 자료형 사용 전략은 어떻게 되나요?</h3>
<ol>
<li>불필요한 참조 제거<ul>
<li>객체를 더 이상 사용하지 않을 때, 해당 객체에 대한 참조를 명시적으로 제거함</li>
</ul>
</li>
<li>약한 참조 사용<ul>
<li>약한 참조를 사용해 가비지 컬렉션이 객체를 회수할 수 있도록 함. WeakReference 와 SoftReference 클래스를 사용하면 약한 참조 구현 가능</li>
</ul>
</li>
<li>불변 객체 사용<ul>
<li>불변 객체는 상태가 변경되지 않으므로 참조로 인해 메모리가 유지되는 문제가 줄어듬</li>
</ul>
</li>
<li>정적 필드와 싱글톤 관리<ul>
<li>정적 필드나 싱글톤 객체 관리시 사용하지 않는 데이터를 명시적으로 제거하거나 필요에 따라 동적으로 재할당함. 이때 정적 참조가 지속되면 객체가 GC 대상에서 제외되므로 주의해야함</li>
</ul>
</li>
<li>이벤트 리스너와 콜백 관리<ul>
<li>이벤트 리스너와 콜백 객체 등록시 약한 참조를 사용하거나 명시적으로 해제하여 메모리 누수를 방지함</li>
</ul>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[JAVA 스프링 배치 개념 및 php 로 만든 간단 예제]]></title>
            <link>https://velog.io/@ss_g/JAVA-%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B0%B0%EC%B9%98-%EA%B0%9C%EB%85%90-%EB%B0%8F-php-%EB%A1%9C-%EB%A7%8C%EB%93%A0-%EA%B0%84%EB%8B%A8-%EC%98%88%EC%A0%9C</link>
            <guid>https://velog.io/@ss_g/JAVA-%EC%8A%A4%ED%94%84%EB%A7%81-%EB%B0%B0%EC%B9%98-%EA%B0%9C%EB%85%90-%EB%B0%8F-php-%EB%A1%9C-%EB%A7%8C%EB%93%A0-%EA%B0%84%EB%8B%A8-%EC%98%88%EC%A0%9C</guid>
            <pubDate>Sat, 11 Jan 2025 09:08:05 GMT</pubDate>
            <description><![CDATA[<p>Spring Batch 는 로깅/추적, 트랜잭션 관리, 작업 처리 통계, 작업 재시작, 건너뛰기, 리소스 관리 등 대용량 레코드 처리 기능을 제공
또한 최적화 및 파티셔닝 기술을 통해 대용량, 고성능 배치 작업을 가능하게 하는 서비스나 기능을 제공
배치가 실패하여 작업을 재시작한다면 실패한 지점부터 실행하게됨</p>
<p>Spring Batch 용어</p>
<p><strong>Job</strong>
배치 처리 과정을 하나의 단위로 만들어 놓은 객체. Job은 특정 작업을 정의하고, 실행 단위로 구분할 수 있는 가장 큰 논리적 배치 작업의 집합이다. 하나의 Job은 여러 Step으로 구성될 수 있으며, 각각의 Step은 순차적으로 실행되거나 조건에 따라 실행될 수 있다. Job은 주로 비즈니스 로직에 따라 데이터 처리의 흐름을 정의하는 데 사용된다.</p>
<p><strong>JobInstance</strong>
Job의 실행 단위를 나타내는 객체. Job을 실행시키면 하나의 JobInstance가 생성된다. 즉, 같은 Job이라도 실행할 때마다 새로운 JobInstance가 생성되며, JobParameters에 따라 구별된다. JobInstance는 동일한 JobDefinition(Job의 논리적 정의)에 대해 실행된 결과를 나타내며, 재시작 가능한 배치 작업을 관리하는 데 중요한 역할을 한다.</p>
<p><strong>JobParameters</strong>
JobInstance를 구분하기 위한 용도로, Job 실행 시 외부에서 받는 파라미터를 가진 객체. JobParameters는 JobInstance를 고유하게 식별하기 위해 사용되며, 예를 들어 날짜, 시간, ID 등의 값을 포함할 수 있다. JobParameters가 다르면 새로운 JobInstance가 생성되며, 동일한 JobParameters를 사용하면 이미 실행된 JobInstance가 재시작될 수 있다.</p>
<p><strong>JobExecution</strong>
JobInstance의 실행 시도에 대한 정보를 담고 있는 객체. JobExecution은 실행 상태, 시작 시간, 종료 시간, 생성 시간 등 실행 관련 메타데이터를 포함하며, Job의 성공 또는 실패 여부를 나타낸다. JobExecution은 Job이 실행될 때마다 새로 생성되며, 하나의 JobInstance는 여러 개의 JobExecution을 가질 수 있다(재시작이 가능하기 때문).</p>
<p><strong>Step</strong>
Job의 배치 처리 과정을 정의하고, 순차적인 단계를 캡슐화한 객체. Step은 Job의 실제 일괄 처리를 제어하는 모든 정보를 담고 있으며, Reader, Processor, Writer의 조합으로 작업을 처리한다. 하나의 Job은 최소 하나 이상의 Step을 가져야 하며, 각 Step은 독립적으로 실행될 수 있다. Step은 실행 순서와 의존성을 설정할 수 있으며, 비즈니스 로직을 모듈화하여 효율적으로 관리할 수 있다.</p>
<p><strong>StepExecution</strong>
JobExecution과 동일하게 Step의 실행 시도를 나타내는 객체. StepExecution은 실행 상태, 처리된 데이터 개수, 실패 여부 등의 실행 정보를 포함하며, Step이 실제로 실행될 때 생성된다. Job이 여러 Step으로 구성된 경우, 이전 Step이 실패하면 다음 Step은 실행되지 않으며, 이 경우 해당 StepExecution은 생성되지 않는다.</p>
<p><strong>ExecutionContext</strong>
Job에서 데이터를 공유할 수 있는 데이터 저장소 역할을 하는 객체. ExecutionContext는 JobExecutionContext와 StepExecutionContext 두 종류로 나뉘며, 데이터를 각 실행 범위에서 공유하거나 보존하는 데 사용된다.</p>
<ul>
<li>JobExecutionContext: JobExecution 범위에서 데이터를 공유하며, Commit 시점에 저장된다.</li>
<li>StepExecutionContext: StepExecution 범위에서 데이터를 공유하며, Step 실행 중간에도 저장될 수 있다. ExecutionContext를 사용하면 Step 간 데이터를 공유할 수 있으며, Job이 실패했을 경우 마지막 실행 값을 복원하여 작업을 재개할 수 있다.</li>
</ul>
<p><strong>JobRepository</strong>
스프링 배치의 모든 배치 처리 정보를 저장하고 관리하는 매커니즘. Job 실행 시 JobRepository는 JobExecution과 StepExecution 객체를 생성하고, 실행 정보와 상태를 저장하거나 조회하여 사용한다. JobRepository는 데이터베이스에 메타데이터를 저장하며, 배치 작업의 상태를 지속적으로 관리하여 재시작 및 복구 기능을 지원한다.</p>
<p><strong>JobLauncher</strong>
Job과 JobParameters를 사용하여 Job을 실행하는 객체. JobLauncher는 Job 실행의 시작점을 제공하며, 배치 작업을 프로그래밍적으로 트리거하거나 관리할 수 있다. 주로 Spring Scheduler 또는 Rest API 호출과 결합하여 사용된다.</p>
<p><strong>ItemReader</strong>
Step에서 데이터를 읽어오는 역할을 담당하는 인터페이스. ItemReader는 데이터베이스, 파일, 큐 등 다양한 소스에서 데이터를 읽어오도록 구현될 수 있다. Spring Batch는 다양한 기본 Reader 구현체를 제공하며, 커스텀 Reader를 작성하여 특정 데이터 소스를 처리할 수도 있다.</p>
<p><strong>ItemWriter</strong>
Step에서 처리된 데이터를 쓰는 데 사용되는 인터페이스. ItemWriter는 결과 데이터를 데이터베이스에 삽입하거나 업데이트하거나, 파일에 저장하거나, 메시지 큐로 전송하는 등 다양한 작업을 수행할 수 있다. Spring Batch는 기본적으로 여러 Writer 구현체를 제공하며, 데이터를 Chunk 단위로 묶어서 처리한다.</p>
<p><strong>ItemProcessor</strong>
ItemReader에서 읽어온 데이터를 처리하는 역할을 담당하는 인터페이스. ItemProcessor는 데이터를 필터링하거나 변환하는 작업을 수행하며, 처리된 데이터를 ItemWriter로 전달한다. ItemProcessor는 배치 작업에서 필수 요소는 아니지만, 데이터를 가공하거나 정제할 필요가 있을 때 유용하게 사용된다.</p>
<p><strong>Tasklet</strong>
단일작업 수행하는 구성요소
작업의 비즈니스 로직을 처리하고 작업이 끝나면 RepeatStatus.FINISHED 또는 RepeatStatus.CONTINUABLE 을 반환
일반적으로 단순 초기화 작업 및 한번만 실행되고 종료되는 작업에 사용</p>
<h3 id="php-로-만든-간단-예제">PHP 로 만든 간단 예제</h3>
<p>호출부</p>
<pre><code>$data = [
    &quot;data&quot; =&gt; [
        &quot;aa-01-0001&quot;, &quot;aa-01-0002&quot;, &quot;aa-01-0003&quot;, &quot;aa-01-0004&quot;, &quot;aa-01-0005&quot;,
        &quot;aa-01-0006&quot;, &quot;aa-01-0007&quot;, &quot;aa-01-0008&quot;, &quot;aa-01-0009&quot;, &quot;aa-01-0010&quot;,
        &quot;bb-01-0011&quot;, &quot;bb-01-0012&quot;, &quot;bb-01-0013&quot;, &quot;bb-01-0014&quot;, &quot;bb-01-0015&quot;,
        &quot;bb-01-0016&quot;, &quot;bb-01-0017&quot;, &quot;bb-01-0018&quot;, &quot;bb-01-0019&quot;, &quot;bb-01-0020&quot;,
        &quot;aa-01-0021&quot;, &quot;aa-02-0022&quot;, &quot;aa-03-0023&quot;, &quot;aa-04-0024&quot;, &quot;aa-05-0025&quot;,
        &quot;aa-06-0026&quot;, &quot;aa-07-0027&quot;, &quot;aa-08-0028&quot;, &quot;aa-09-0029&quot;, &quot;aa-10-0030&quot;
    ]
];

require_once &#39;경로 어쩌고저쩌고/batch.php&#39;;
$batchProcessor = new Batch(10, $data);

$batchProcessor-&gt;Job();</code></pre><br>

<p>배치가 실행되는 클래스</p>
<pre><code>&lt;?php

/*
서버에서 크론탭으로 배치 파일 호출할때
0 * * * * /myServer/bin/php /modules/chatbot/theme/default-desktop/adm/batch.php
*/
class batch
{
    private $_chunkSize;
    private $_data;
    private $_logFile = &#39;batch_log.txt&#39;;
    private $_currentTime;
    private $_refinedData = [];

    public function __construct($chunkSize, $data)
    {
        $this-&gt;_chunkSize = $chunkSize;
        $this-&gt;_data = $data;
        $this-&gt;_currentTime = date(&#39;Y-m-d H:i:s&#39;);
    }

    public function Job()
    {
        // 배치 Job 이 돌 때 로그 쌓음
        $this-&gt;_initJobStep();

        // 데이터 정제 Step
        $this-&gt;_dataSetStep();
    }

    private function _initJobStep()
    {
        file_put_contents($this-&gt;_logFile, &quot;Batch executed at: $this-&gt;_currentTime\n&quot;, FILE_APPEND);
        file_put_contents($this-&gt;_logFile, &quot;Request Data : $this-&gt;_data\n&quot;, FILE_APPEND);
    }

    private function _dataSetStep()
    {
        // itemReader 는 데이터가 생성자에서 들어왔기 때문에 추가하지 않았음

        // processor
        $this-&gt;_process();

        // writer
        $this-&gt;_write();
    }

    private function _process()
    {
        $chunks = array_chunk($this-&gt;_data[&#39;data&#39;], $this-&gt;_chunkSize);

        foreach ($chunks as $index =&gt; $chunk) {
            $this-&gt;_processChunk($chunk);
        }
    }

    private function _processChunk($chunk)
    {
        foreach ($chunk as $item) {
            $this-&gt;_refinedData[] = $this-&gt;_refineData($item);
        }
    }

    private function _refineData($item)
    {
        $parts= explode(&#39;-&#39;, $item);

        return [
            &#39;name&#39; =&gt; $parts[0] ?? null,
            &#39;type&#39; =&gt; $parts[1] ?? null,
            &#39;code&#39; =&gt; $parts[2] ?? null,
        ];
    }

    private function _write()
    {
        $sql = &quot;INSERT INTO test_batch 어쩌고저쩌고&quot;;
        //쿼리 실행으로 db 삽입
    }

}



</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[[CS]자료형]]></title>
            <link>https://velog.io/@ss_g/CS%EC%9E%90%EB%A3%8C%ED%98%95</link>
            <guid>https://velog.io/@ss_g/CS%EC%9E%90%EB%A3%8C%ED%98%95</guid>
            <pubDate>Sun, 15 Dec 2024 13:02:25 GMT</pubDate>
            <description><![CDATA[<h2 id="초심으로-돌아가서-자료형을-공부하면서-연관되는-개념까지-싸그리-학습해보자">초심으로 돌아가서 자료형을 공부하면서 연관되는 개념까지 싸그리 학습해보자</h2>
<br>
<hr>

<h4 id="자료형">자료형</h4>
<p>자료형(Data Type) : 데이터를 구성하고 관리하는 기본 개념으로, 데이터의 크기, 형식, 해석 방식을 정의한다.</p>
<h4 id="자료형의-분류">자료형의 분류</h4>
<p><strong>원시자료형(Primitive Types)</strong> : 데이터 표현의 가장 기본적인 형태</p>
<ul>
<li>정수형(Integer Types)<ul>
<li>정수를 저장하는 자료형</li>
<li>값의 범위는 비트 수와 부호(sign)의 유무에 따라 달라진다.</li>
</ul>
</li>
</ul>
<pre><code>* byte : 1 byte
* int : 2byte
* short : 4byte
* long : 8byte</code></pre><blockquote>
<ul>
<li>부호 ? <ul>
<li>숫자의 양수(Positive) 또는 음수(Negative) 여부를 나타내는 개념</li>
<li>가장 왼쪽의 비트(최상위 비트)를 부호 비트(Sign Bit)로 사용한다.</li>
<li>0 이 양수(Positive)</li>
<li>1 이 음수(Negative)<br>
</li>
</ul>
</li>
</ul>
</blockquote>
<ul>
<li><p>비트 ?</p>
<ul>
<li>비트(Binary Digit)는 컴퓨터에서 데이터를 표현하는 가장 작은 단위.</li>
<li>0 또는 1 두 가지 상태만 가질 수 있음(0 = OFF, 1 = ON)</li>
<li>컴퓨터는 모든 데이터를 2진수로 처리하고, 각각의 비트는 2진법의 자리값을 나타낸다. 모든 데이터(숫자, 문자, 이미지 등)는 비트의 조합으로 표현된다.<br>
* 바이트 ?</li>
<li>8비트로 구성된 데이터 저장 단위로 2⁸ = 256개의 값(0<del>255 or -128</del>127)을 표현 가능하다.<br>
* 인코딩 디코딩 ?</li>
<li>인코딩(Encoding) : 데이터를 다른 형식으로 변환하는 과정으로 문자 인코딩의 경우 텍스트 데이터를 숫자로 변환해서 컴퓨터가 저장하고 처리할 수 있도록 한다.<ul>
<li>디코딩(Decoding) : 인코딩된 데이터를 원래의 형식으로 복원하는 과정으로 이진수, 압축파일, 암호화된 데이터 등 컴퓨터가 처리 가능한 데이터를 사람이 읽을 수 있는 형태로 되돌리는 작업* 문자 인코딩 ?</li>
</ul>
</li>
<li>컴퓨터가 문자를 숫자로 변환해서 저장하고 처리하기 위한 인코딩 체계.<br></li>
</ul>
</li>
<li><p>문자 인코딩 ?</p>
<ul>
<li>ASCII(American Standard Code for Information Interchange) : 미국 표준 문자 인코딩 체계로, 주로 영어 알파벳, 숫자, 특수 문자 등을 포함함. 초창기 문자 인코딩 방식</li>
<li>Unicode : 모든 언어와 문자를 표현할 수 있도록 설계된 국제 표준 문자 인코딩 체계</li>
<li>인코딩 방식으로는 EUC-KR, UTF-8, UTF-16, UTF-32 등이 있음</li>
</ul>
</li>
<li><p>실수형(Floating-Point Types)</p>
<ul>
<li>소수점을 포함하는 숫자를 표현</li>
<li>float(Single Precision) : 32비트<ul>
<li>double(Double Precision) : 64비트</li>
</ul>
</li>
</ul>
<br>
</li>
<li><p>문자형(Character Types)</p>
<ul>
<li>단일 문자를 표현. ASCII 혹은 Unicode 사용</li>
<li>ASCII : 1 Byte</li>
<li>Unicode : 2 Byte<br>
</li>
</ul>
</li>
<li><p>논리형(Boolean Type)</p>
<ul>
<li>true or false 두 가지 상태만 표현
보통 1 Bit</li>
</ul>
</li>
</ul>
<br>

<p>// Java
<strong>참조 자료형(Reference Type)</strong> : 기본 자료형을 조합하거나 확장해서 더 복잡한 데이터를 표현하는 자료형</p>
<ul>
<li>배열(Array)<ul>
<li>동일한 자료형의 데이터 집합을 순차적으로 저장한 자료형
고정된 크기를 가지고, 각 요소는 인덱스를 통해 접근함.
메모리에 연속적으로 저장되고, 모든 요소가 같은 자료형이어야 함.</li>
</ul>
</li>
<li>클래스(Class)<ul>
<li>객체 지향 프로그래밍(Object-Oriented Programming) 에서 속성과 메서드를 포함하는 사용자 정의 자료형
데이터를 캡슐화하고 메서드를 통해 조작함.
객체를 생성해서 실제 데이터를 저장하고 사용할 수 있음.</li>
</ul>
</li>
</ul>
<p>*<em>자료형 설계의 한계 *</em></p>
<pre><code>1. 값의 범위 제한 : 오버플로우 또는 언더플로우 발생 가능
2. 실수 표현에서의 오차 : 부동소수점 연산에서 근사값으로 인해 오차가 발생 가능
3. 타입 변환 문제 : 서로 다른 타입 간의 변환시에 정밀도가 손실됨
4. Null 값의 문제 : 참조타입에서 Null 값으로 인해 NullPointerException 과 같은 런타임 에러 발생 가능
5. 메모리 비효율 : 실제 데이터 크기에 비해 메모리를 낭비할 수 있음</code></pre><p><strong>오버플로우</strong> : 데이터가 표현할 수 있는 최대값을 초과했을 때 발생하는 현상
<strong>언더플로우</strong> : 데이터가 표현할 수 있는 최소값보다 더 작은 값으로 감소할때 발생</p>
<br>
<hr>

<h4 id="컴퓨터-메모리">컴퓨터 메모리</h4>
<p><strong>코드</strong>
실행할 프로그램의 코드가 저장되는 영역으로 텍스트 영역이라고 불림.
CPU 가 코드 영역에 저장된 명령어를 하나씩 가져가서 처리함</p>
<p><strong>데이터 영역</strong>
프로그램의 전역 변수와 정적(static) 변수가 저장되는 영역
데이터 영역은 프로그램의 시작과 함께 할당되고 프로그램이 종료되면 소멸함.</p>
<p><strong>스택 영역</strong> 
정적 메모리 영역. 함수 호출, 지역 변수 관리 등에 사용함.
push 동작으로 데이터를 저장, pop 동작으로 데이터를 인출하는 LIFO(Last In, First Out) 원칙으로 데이터를 관리함.
고정 크기이고, 빠른 메모리 할당과 해제가 특징임.
스택의 크기는 제한적이며, 이를 초과하면 스택 오버플로우가 발생할 수 있음</p>
<ul>
<li>스택 오버플로우(Stack Overflow) : 함수의 재귀 호출이 무한히 반복되면 해당 프로그램이 스택 오버플로우에 의해 종료됨
재귀 호출에 의한 스택 프레임이 점차 쌓이게 되다가 스택의 공간보다 더 큰 데이터가 push 되면 프로그램은 에러를 발생하고 강제종료 시킴.</li>
</ul>
<p><strong>힙 영역</strong>
동적 메모리 영역. 런타임시 크기가 동적으로 결정되는 데이터를 저장.
비정렬(non-ordered) 메모리 구조로, 메모리 할당과 해제가 스택보다 느림
가변 크기의 데이터와 객체를 저장함.
사용자가 직접 관리할 수 있다는 장점이 있으나, 동시에 관리를 해야 한다는 까다로움 또한 있음.
힙 영역은 메모리의 낮은 주소에서 높은 주소 방향으로 할당됨
힙 메모리를 잘 관리하지 못하면 프로그램에 메모리 누수(Memory Leak)가 발생할 수 있음.</p>
<ul>
<li>가비지 컬렉션(Garbage Collection)
힙 영역에서 동적으로 할당했던 메모리 영역 중 필요가 없어진 메모리 영역을 주기적으로 삭제하는 프로세스
Java 는 JVM 에 탑재된 가비지 컬렉터가 메모리 관리를 대신 해줌</li>
</ul>
<br>
<hr>

<h4 id="자료구조">자료구조</h4>
<p><strong>자료구조(Data Structure)</strong>
    - 데이터를 효율적으로 저장, 관리, 처리하기 위한 구조적 방식으로 데이터를 논리적이고 체계적으로 조직화해서 작업을 효율적으로 수행할 수 있게 도움.</p>
<p><strong>자료구조 특징</strong></p>
<ul>
<li>효율성 : 데이터의 삽입, 삭제, 검색, 정렬 등의 상황또는 문제에 알맞은 자료구조 사용시 처리 효율이 증가</li>
<li>조직화 : 자료구조는 데이터를 논리적 또는 물리적으로 구조화해서 저장함. 이러한 데이터의 관계와 배치를 정의해서 효율적으로 접근하고 처리할 수 있음.</li>
<li>자료의 추상화(Abstraction) : 복잡한 시스템의 세부적인 구현을 숨기고, 필요한 핵심 개념 혹은 기능만을 노출해서 단순화하는 과정
간결성, 재사용성, 유지보수 면에서 우수함<br>

</li>
</ul>
<p><strong>자료구조 분류</strong></p>
<p><strong>단순구조(Simple Structure)</strong>
가장 기본적이고 간단한 형태의 자료구조. 데이터의 구조적 관계가 없는 개별적인 데이터 항목을 처리하는데 사용
    - 정수(Integer), 실수(Floating Poing), 문자(Character), 문자열(String), 논리(Boolean) 등</p>
<p><strong>선형구조(Linear Structure)</strong>
데이터가 순차적으로 배치되는 자료구조. 데이터가 메모리에 연속적이거나 논리적으로 연결되어 있고, 각 요소는 이전 요소와 다음 요소에 대한 관계를 가짐. 데이터가 특정 순서로 접근되거나 처리될 때 사용</p>
<ol>
<li>배열(Array)</li>
</ol>
<ul>
<li>데이터가 메모리에 연속적으로 저장되는 자료구조.</li>
<li>특징<ul>
<li>고정 크기 : 선언시 크기가 고정됨.</li>
<li>연속적인 메모리 : 배열 요소는 메모리상에 연속적으로 배치됨. 인덱스를 사용하면 O(1) 시간 복잡도로 특정 요소에 접근 가능</li>
<li>자료형 동일 : 배열에 저장되는 모든 요소는 동일한 자료형이어야 함.</li>
<li>순차 접근 : 배열 요소는 인덱스를 사용해 순차적 또는 랜덤으로 접근 가능함.</li>
</ul>
</li>
</ul>
<ol start="2">
<li>연결 리스트(Linked List)</li>
</ol>
<ul>
<li>각 노드(Node) 들이 데이터와 포인터를 가지고 논리적으로 연결된 구조</li>
<li>특징<ul>
<li>포인터로 다음 노드를 찾을 수 있음.</li>
<li>크기가 동적으로 변경 가능</li>
<li>데이터 접근은 순차적이고, 삽입/삭제 동작이 빠름</li>
</ul>
</li>
<li>종류<ul>
<li>단일 연결 리스트(Singly Linked List) : 한방향 연결</li>
<li>이중 연결 리스트(Doubly Linked List) : 양방향 연결</li>
<li>원형 연결 리스트(Circular Linked List) : 마지막 노드가 첫번째 노드를 가리킴</li>
</ul>
</li>
</ul>
<ol start="3">
<li>스택(Stack)</li>
</ol>
<ul>
<li>한쪽 끝에서만 데이터를 넣고 뺄 수 있는 LIFO(Last In First Out) 원칙에 따라 동작하는 선형구조</li>
<li>동작<ol>
<li>push : 스택에 데이터를 추가하는 연산. 스택의 맨 위에 데이터 삽입</li>
<li>pop : 스택에서 데이터를 제거하는 연산. 스택의 맨 위에서 데이터를 삭제하고 반환</li>
<li>peek or top : 스택의 맨 위에 있는 데이터를 반환. 스택에서 제거하지는 않음</li>
<li>isEmpty : 스택이 비어있는지 확인하는 연산</li>
<li>size : 스택에 저장된 데이터의 개수 반환</li>
</ol>
</li>
</ul>
<ol start="4">
<li>큐(Queue)</li>
</ol>
<ul>
<li>양쪽 끝에서만 삽입, 삭제가 일어나는 FIFO(First In First Out) 원칙에 따라 동작하는 자료구조. 리어(rear) 에서 삽입, 프론트(front) 에서 삭제<ul>
<li>중간 항목에 접근하기 어렵고, 특정 항목을 찾기 위해 큐를 선형적으로 탐색해야 하기에 큐의 크기에 탐색 시간이 비례함.</li>
</ul>
</li>
<li>동작<ol>
<li>enqueue(item) : 큐의 리어(rear)에 item 삽입하는 연산</li>
<li>dequeue() : 큐의 프론트(front)에서 항목을 삭제하고 반환하는 연산</li>
<li>isEmpty() : 큐가 비어있는지 확인하는 연산</li>
<li>size() : 큐의 현재 크기를 반환</li>
<li>peek() : 큐의 프론트(front)에 위치한 항목 반환. 큐에서 삭제하지는 않음</li>
</ol>
</li>
</ul>
<p><strong>비선형구조</strong>
데이터가 계층적이거나 복잡한 연결 관계를 가지는 자료구조. 데이터간의 관계를 명확히 표현하거나 복잡한 문제를 효율적으로 해결하는데 사용됨.</p>
<ol>
<li>트리(Tree)</li>
</ol>
<ul>
<li>계층적 관계를 가지는 비선형 자료구조. 노드(Node) 와 간선(Edge) 로 구성됨</li>
<li>종류<ol>
<li>일반 트리(General Tree) : 각 노드가 여러 자식을 가질 수 있는 트리</li>
<li>이진 트리(Binary Tree) : 각 노드의 차수가 2 이하인 트리</li>
<li>이진 탐색 트리(Binary Search Tree, BST) : 순서화된 이진 트리로 노드의 왼쪽 자식은 부모의 값보다 작은 값을 가져야 하며, 노드의 오른쪽 자식은 부모의 값보다 큰 값을 가져야 함.
외에도 모든 노드가 자식을 하나만 가지는 편향 트리(skew tree), 데이터베이스 인덱싱을 구현하는데 사용하는 AVL tree, B-tree, B+tree, 사전 저장에 사용되는 tries, Heap 등이 있음</li>
</ol>
</li>
</ul>
<ol start="2">
<li>그래프(Graph)</li>
</ol>
<ul>
<li>연결되어있는 원소간의 관계를 표현한 비선형 자료구조.
연결할 객체를 나타내는 정점(Vertex)과 객체를 연결하는 간선(Edge)의 집합으로 구성
G=(V, E) 로 정의하는데, V 는 정점의 집합, E 는 간선들의 집합을 의미</li>
<li>용어
  차수(Degree) : 정점에 부속되어 있는 간선의 수
  -진입차수(in-degree) : 정점을 머리로 하는 간선의 수
  -진출차수(out-degree) : 정점을 꼬리로 하는 간선의 수
  경로(Path) : 정점 Vi 에서 Vj 까지 간선으로 연결된 정점을 순서대로 나열한 리스트
  경로 길이(Path Length) : 경로를 구성하는 간선의 수
  사이클(Cycle) : 단순 경로 중에서 경로의 시작 정점과 마지막 정점이 같은 경로</li>
<li>종류<ol>
<li>방향 그래프(Directed Graph) : 간선이 방향을 가리키는 그래프</li>
<li>무방향 그래프(Undirected Graph) : 두 정점을 연결하는 간선에 방향이 없는 그래프</li>
<li>가중 그래프(Weighted Graph) : 간선에 가중치가 할당된 그래프</li>
<li>순환 그래프(Cyclic Graph) : 순환 경로가 존재하는 그래프</li>
<li>비순환 그래프(Acyclic Graph) : 순환 경로가 없는 그래프</li>
<li>연결 그래프(Connected Graph) : 모든 노드가 서로 연결된 그래프</li>
<li>비연결 그래프(Disconnected Graph) : 일부 노드가 연결되지 않은 그래프</li>
<li>이분 그래프(Bipartite Graph) : 노드를 두 개의 독립적인 집합으로 나눌 수 있는 그래프</li>
</ol>
</li>
</ul>
<ol start="3">
<li>해시(Hash) &amp; 해시 테이블(Hash Table)
(해시는 데이터를 특정 값으로 매핑하는 알고리즘 또는 데이터 매핑 방법)</li>
</ol>
<ul>
<li>효율적인 검색과 삽입 연산을 위해 설계된 자료구조
키-값 쌍의 데이터를 저장하는데 사용되고, 각 키는 해시 함수를 통해 고유 인덱스로 변환되어 배열 내에 저장됨
데이터를 저장할 버킷(Bucket) 또는 슬롯(Slot)으로 구성
<em>해싱(Hashing) : 해시 함수를 통해 데이터를 특정 값으로 매핑하는 과정</em></li>
<li>해시함수(Hash Function)<ul>
<li>임의의 데이터를 고정된 길이의 값으로 리턴해주는 함수</li>
</ul>
</li>
<li>해시충돌(collision)과 해결방법 : 두 개 이상의 데이터가 같은 해시 값을 가지는 상황<ul>
<li>체이닝(Chaining) : 충돌이 발생한 데이터를 연결 리스트로 저장</li>
<li>오픈 어드레싱(Open Addressing) : 충돌시 빈 슬롯을 찾아 데이터를 저장</li>
</ul>
</li>
</ul>
<ol start="4">
<li>집합(Set)</li>
</ol>
<ul>
<li>중복을 허용하지 않는 데이터 구조로 Array 나 List 처럼 순열 자료구조(collection)이지만 set은 비순차적으로 순서의 개념이 존재하지 않음.</li>
<li>특징<ul>
<li>순서가 없기에 삽입 순서대로 저장되지 않음</li>
<li>수정 가능(mutable)</li>
<li>동일 값 여러번 삽입 불가능. 동일 값 여러번 삽입 시 하나의 값만 저장</li>
</ul>
</li>
</ul>
<br>
<hr>

<h4 id="시간복잡도와-공간복잡도">시간복잡도와 공간복잡도</h4>
<ul>
<li><p>복잡도(complexity)
알고리즘의 성능, 효율성을 나타내는 척도
각 알고리즘이 주어진 특정 크기의 입력(n) 을 기준으로 수행시간(연산) 혹은 사용공간이 얼마나 되는지 객관적으로 비교할 수 있는 기준을 제시</p>
<ul>
<li>점근적 표기법 3가지</li>
</ul>
<ol>
<li>최상의 경우 : 오메가 표기법(Big-Ω)</li>
<li>평균의 경우 : 세타 표기법(Big-θ)</li>
<li>최악의 경우 : 빅오 표기법(Big-O)
주로 최악의 경우인 빅오 표기법으로 복잡도를 표기</li>
</ol>
</li>
</ul>
<p><strong>시간복잡도(Time complexity)</strong> 
입력값 크기(input size) 에 따라 실행되는데 걸리는 시간의 증가율을 나타내는 척도. 알고리즘의 효율성을 평가하는 중요 개념
수행시간은 실행환경에 따라 다르게 측정되기 때문에 기본 연산의 실행 횟수로 수행 시간을 평가함.</p>
<ul>
<li>빅오 표기법<ul>
<li>O(1)상수시간 : 입력 크기에 상관없이 일정한 시간이 걸리는 알고리즘. ex) 배열의 특정 인덱스 접근</li>
<li>O(log n)로그시간 : 입력 크기가 커질수록 처리시간이 log(지수 함수의 역함수)만큼 짧아지는 알고리즘 ex) 이진탐색(Binary Search)</li>
<li>O(n)선형시간 : 입력 데이터의 크기에 비례해 처리 시간이 증가하는 알고리즘 ex) 배열의 순차 검색(Linear Search)</li>
<li>O(n log n)로그선형시간 : 데이터가 많아질수록 처리시간이 log 배 만큼 더 늘어나는 알고리즘 ex)병합 정렬(Merge Sort), 퀵 정렬(Quick Sort)</li>
<li>O(n²)이차시간 : 데이터가 많아질수록 처리시간이 급수적으로 늘어나는 알고리즘 ex)버블 정렬(Bubble Sort), 삽입 정렬</li>
<li>O(2^n)지수시간 : 데이터가 많아질수록 처리시간이 기하급수적으로 늘어나는 알고리즘. 재귀가 역기능을 할 경우도 해당 ex) 피보나치 수열(재귀 구현)</li>
</ul>
</li>
</ul>
<blockquote>
<p>O(1) &lt; O(log n) &lt; O(nlog n) &lt; O(n²) &lt; O(2ⁿ)
좌에서 우 순서로 갈수록 효율성이 떨어짐</p>
</blockquote>
<p><strong>공간복잡도</strong> 
알고리즘이 실행되는 동안 사용하는 메모리의 양을 측정하는 척도</p>
<ul>
<li>구성요소</li>
</ul>
<ol>
<li>고정 공간(Fixed Part)<ul>
<li>알고리즘의 입력 크기와 상관없이 항상 일정하게 사용하는 공간</li>
<li>ex) 상수, 변수, 프로그램 실행에 필요한 기본 메모리 등</li>
<li>크기 : 상수 O(1)</li>
</ul>
</li>
<li>가변 공간(Variable Part)<ul>
<li>입력 크기(n) 에 따라 증가하거나 감소하는 공간</li>
<li>ex) 배열, 리스트, 동적 데이터 구조</li>
<li>크기 : O(n), O(n²) 등</li>
</ul>
</li>
<li>재귀 또는 호출 스택 공간(Recursion/Function Call Stack Space)<ul>
<li>재귀함수 호출시 사용하는 메모리</li>
<li>재귀 깊이에 따라 메모리 사용량 달라짐<ul>
<li>크기 : 함수 호출 횟수 X 호출당 메모리 사용량</li>
</ul>
</li>
</ul>
</li>
</ol>
<ul>
<li>공간복잡도 최적화<ul>
<li>중복 데이터 줄이기 위해 메모리를 공유하고, 재귀 대신 반복을 사용. 효율적인 데이터 구조 선택 등으로 최적화</li>
</ul>
</li>
</ul>
<br>
<hr>

<p><strong>거품정렬(Bubble Sort)</strong></p>
<blockquote>
<p>서로 인접한 두 원소의 대소를 비교하고, 조건에 맞지 않다면 자리를 교환하며 정렬하는 알고리즘</p>
</blockquote>
<p>거품 정렬은 선택 정렬과 유사한 알고리즘.</p>
<p><strong>정렬 방법</strong></p>
<ol>
<li>1회전에 첫 번째 원소와 두 번째 원소를, 두 번째 원소와 세 번째 원소를... 이런 식으로 마지막 -1 번째 원소와 마지막 원소를 비교하며 조건에 맞지 않는다면 서로 교환.</li>
<li>1회전을 수행하고 나면 가장 큰 원소가 맨 뒤로 이동하므로 2회전에서는 맨 끝에 있는 원소는 정렬에서 제외되고, 2회전을 수행하고 나면 끝에서 두 번째 원소까지는 정렬에서 제외됨. 이렇게 정렬을 1회전 수행할 때마다 정렬에서 제외되는 데이터가 하나씩 늘어남.</li>
</ol>
<p><strong>Java Code</strong></p>
<pre><code>void bubbleSort(int[] arr) {
    int temp = 0;
    for(int i = 0; i &lt; arr.length; i++) {       // 1.
        for(int j= 1 ; j &lt; arr.length-i; j++) { // 2.
            if(arr[j-1] &gt; arr[j]) {             // 3.
                // swap(arr[j-1], arr[j])
                temp = arr[j-1];
                arr[j-1] = arr[j];
                arr[j] = temp;
            }
        }
    }
}</code></pre><ol>
<li>i는 제외될 원소의 갯수를 의미한다. 1회전이 끝난 후 배열의 마지막 위치에는 가장 큰 원소가 위치하기 때문에 하나씩 증가시켜준다.</li>
<li>원소를 비교할 index를 뽑는 반복문으로 j는 현재 원소를 가리키고, j-1은 이전 원소를 가리키게 되므로, j는 1부터 시작한다.</li>
<li>현재 가리키고 있는 두 원소의 대소를 비교한다, 해당 코드는 오름차순 정렬이므로 현재 원소보다 이전 원소가 더 크다면 이전 원소가 뒤로 가야하므로 서로 자리를 교환해준다.</li>
</ol>
<p><img src="https://velog.velcdn.com/images/ss_g/post/de22b18a-025b-49fd-9996-d751c1e0de9a/image.gif" alt=""></p>
<p><strong>시간복잡도</strong></p>
<blockquote>
<p>(n-1) + (n-2) + (n-3) + ..... + 2 + 1 =&gt; n(n-1) / 2
이므로 O(n^2)이다</p>
</blockquote>
<p>Bubble Sort는 정렬이 돼있던 안돼있던, 2개의 원소를 비교하기 때문에 최선, 평균, 푀악의 경우 모두 시간 복잡도가 동일하다.</p>
<p><strong>공간복잡도</strong>
주어진 배열 안에서 교환(swap)을 통해 정렬이 수행되므로 O(n)이다.</p>
<p><strong>장점</strong> </p>
<ul>
<li>구현이 간단하고, 소스코드가 직관적</li>
<li>정렬하고자 하는 배열 안에서 교환하는 방식이므로, 다른 메모리 공간을 필요로 하지 않는다. =&gt; 제자리 정렬(in-place sorting)</li>
<li>안전 정렬(stable Sort)이다.</li>
</ul>
<p><strong>단점</strong></p>
<ul>
<li>시간복잡도가 최악, 최선, 평균 모두 O(n^2)으로, 굉장히 비효율적이다.</li>
<li>정렬 돼있지 않은 원소가 정렬 됐을때의 자리로 가기 위해서, 교환 연산(swap)이 많이 일어나게 된다.</li>
</ul>
<br>
<hr>

<p><strong>선택 정렬(Selection Sort)</strong></p>
<blockquote>
<p>해당 순서에 원소를 넣을 위치는 이미 정해져 있고, 어떤 원소를 넣을지 선택하는 알고리즘</p>
</blockquote>
<p>선택 정렬은 거품 정렬과 유사한 알고리즘.</p>
<p><strong>정렬방법</strong></p>
<ol>
<li>주어진 배열 중에 최소값을 찾는다.</li>
<li>그 값을 맨 앞에 위치한 값과 교체한다.(pass)</li>
<li>맨 처음 위치를 뺀 나머지 배열을 같은 방법으로 교체한다.</li>
</ol>
<p><strong>Java Code</strong></p>
<pre><code>void selectionSort(int[] arr) {
    int indexMin, temp;
    for (int i = 0; i &lt; arr.length-1; i++) {        // 1.
        indexMin = i;
        for (int j = i + 1; j &lt; arr.length; j++) {  // 2.
            if (arr[j] &lt; arr[indexMin]) {           // 3.
                indexMin = j;
            }
        }
        // 4. swap(arr[indexMin], arr[i])
        temp = arr[indexMin];
        arr[indexMin] = arr[i];
        arr[i] = temp;
  }
}</code></pre><ol>
<li>위치(index)를 선택해준다.</li>
<li>i + 1 번째 원소부터 선택한 위치(index)의 값과 비교를 시작한다.</li>
<li>오름차순이므로 현재 선택한 자리에 있는 값보다 순회하고 있는 값이 작다면, 위치(index)를 갱신해준다.</li>
<li>&#39;2&#39;번 반복문이 끝난 뒤에는 indexMin에 &#39;1&#39;번에서 선택한 위치(index)에 들어가야하는 값의 위치(index)를 갖고 있으므로 서로 교환(swap)해준다.</li>
</ol>
<p><img src="https://velog.velcdn.com/images/ss_g/post/b2f08066-6e32-41c1-a9fe-1bc6d98a1755/image.gif" alt=""></p>
<p><strong>시간복잡도</strong></p>
<p>데이터의 개수가 n개라고 했을 때,</p>
<ul>
<li>첫 번째 회전에서의 비교횟수 = 1 ~ (n-1) =&gt; n-1</li>
<li>두 번째 회전에서의 비교횟수 : 2 ~ (n-1) =&gt; n-2
...</li>
</ul>
<blockquote>
<p>(n-1) + (n+2) + .... + 2 + 1 =&gt; n(n-1) / 2</p>
</blockquote>
<p>비교하는 것이 상수 시간에 이루어진다는 가정 아래, n개의 주어진 배열을 정렬하는데 O(n^2) 만큼의 시간이 걸린다. 최선, 평균, 최악의 경우 시간복잡도는 O(n^2) 으로 동일하다.</p>
<p><strong>공간복잡도</strong></p>
<p>주어진 배열 안에서 교환(swap)을 통해 정렬이 수행되므로 O(n) 이다.</p>
<p><strong>장점</strong></p>
<ul>
<li>Bubble Sort와 마찬가지로 알고리즘이 단순하다.</li>
<li>정렬을 위한 비교 횟수는 많지만, Bubble Sort에 비해 실제로 교환하는 횟수는 적기 때문에 많은 교환이 일어나야 하는 자료상태에서 비교적 효율적이다.</li>
<li>Bubble Sort와 마찬가지로 정렬하고자 하는 배열 안에서 교환하는 방식이므로, 다른 메모리 공간을 필요로 하지 않는다. =&gt; 제자리 정렬(in-place sorting)</li>
</ul>
<p><strong>단점</strong></p>
<ul>
<li>시간복잡도가 O(n^2)으로 비효율적이다.</li>
<li>불안정 정렬(Unstable Sort)이다.</li>
</ul>
<br>
<hr>

<p><strong>병합정렬</strong></p>
<blockquote>
<p>주어진 배열을 작은 단위로 나누고, 정렬된 부분 배열들을 병합해서 최종적으로 정렬하는 방식 </p>
</blockquote>
<p><strong>작동원리</strong> </p>
<ol>
<li>분할(Divide)<ul>
<li>배열을 반으로 나누어 재귀적으로 작게 분할</li>
<li>분할을 계속해서 배열이 길이 1이 될 때까지 반복</li>
</ul>
</li>
<li>정복(Conquer)<ul>
<li>길이 1인 배열은 이미 정렬된 상태이므로, 두 배열을 병합하여 정렬</li>
</ul>
</li>
<li>병합(Merge)<ul>
<li>두 개의 정렬된 배열을 합쳐 하나의 정렬된 배열로 만듦</li>
</ul>
</li>
</ol>
<p><strong>시간복잡도</strong></p>
<p>분할단계 : 배열의 크기를 계속 반으로 나눔 -&gt; O(log n)
병합단계 : 각 단계에서 모든 요소를 병합 -&gt; O(n)</p>
<p>병합정렬의 시간복잡도는 O(n log n)</p>
<p>n 개의 요소가 있을때 n 이 2의 k 제곱이라면 밑이 2인 로그를 취했을때, k만큼 반복해야 크기가 1인 배열로 분할 가능
그리고 다시 합칠때 각 요소들을 비교해서 정렬하며 병합하기 때문에 비교연산도 시간복잡도에 포함</p>
<br>
<hr>

<p><strong>퀵정렬</strong></p>
<p>분할정복(Divide adn Conquer) 알고리즘의 종류로 배열의 한 요소를 기준(pivot)으로 삼아 작은 값과 큰 값을 나누어 정렬하는 방식
추가 메모리가 거의 필요하지 않음(제자리정렬)</p>
<p><strong>작동원리</strong></p>
<ol>
<li>분할(Divide)<ul>
<li>배열에서 하나의 요소를 기준(pivot)으로 선택</li>
<li>기준보다 작은 요소는 왼쪽, 큰 요소는 오른쪽에 위치</li>
</ul>
</li>
<li>정복(Conquer)<ul>
<li>왼쪽과 오른쪽 부분에 대해 재귀적으로 퀵 정렬 수행</li>
</ul>
</li>
<li>결합(Combine)<ul>
<li>재귀적으로 정렬된 부분 배열들을 합침(이때 병합 과정은 없음)</li>
</ul>
</li>
</ol>
<p><strong>시간복잡도</strong>
이미 정렬된 배열에서 첫 요소를 피벗으로 선택했을 때 -&gt; O(n²)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[자바스크립트에서 문자열을 감쌀 때 무엇을 사용하면 좋을까? & JSON 이란?]]></title>
            <link>https://velog.io/@ss_g/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EC%97%90%EC%84%9C-%EB%AC%B8%EC%9E%90%EC%97%B4%EC%9D%84-%EA%B0%90%EC%8C%80-%EB%95%8C-%EB%AC%B4%EC%97%87%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%98%EB%A9%B4-%EC%A2%8B%EC%9D%84%EA%B9%8C-JSON-%EC%9D%B4%EB%9E%80</link>
            <guid>https://velog.io/@ss_g/%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EC%97%90%EC%84%9C-%EB%AC%B8%EC%9E%90%EC%97%B4%EC%9D%84-%EA%B0%90%EC%8C%80-%EB%95%8C-%EB%AC%B4%EC%97%87%EC%9D%84-%EC%82%AC%EC%9A%A9%ED%95%98%EB%A9%B4-%EC%A2%8B%EC%9D%84%EA%B9%8C-JSON-%EC%9D%B4%EB%9E%80</guid>
            <pubDate>Mon, 20 May 2024 09:34:43 GMT</pubDate>
            <description><![CDATA[<p>싱글 쿼테이션(&#39;&#39;), 더블 쿼테이션(&quot;&quot;), 백틱(``) 중 어떤걸 사용하면 좋을까?</p>
<h3 id="더블-쿼테이션-사용을-권장주관적임">더블 쿼테이션 사용을 권장(주관적임)</h3>
<ul>
<li>그 이유는? JSON 이 더블 쿼테이션으로 이름/값 쌍을 감싸고 있기 때문.
보통 JS 는 JSON으로 파싱하는 경우가 많이 생기는데, 싱글 쿼테이션 사용시 JSON.parse 시에 문제가 발생할 수 있다.</li>
</ul>
<h3 id="다른-언어들에서는">다른 언어들에서는?</h3>
<ul>
<li>SQL 에서는 싱글 쿼테이션은 string이나 문자열 표현시 사용, 더블 쿼테이션은 식별자나 객체 이름 표현시 사용한다.</li>
<li>JAVA 에서는 싱글 쿼테이션은 character 표현시 사용, 더블 쿼테이션은 string 표현시 사용한다.</li>
</ul>
<h3 id="그렇다면-사용에-표준이-있나">그렇다면 사용에 표준이 있나?</h3>
<p>ECMA-262 표준문서에서는 예제코드 및 프로토타입 함수를 정의할 때 더블 쿼테이션을 사용하고 있다.
하지만 구글의 사내 코드 컨벤션은 싱글 쿼테이션이라고 한다.
그만큼 선호도의 차이일 뿐 무엇을 사용하던지 큰 문제는 없다고 하는데, 그렇다면 JSON 을 자주 사용하는 자바스크립트에서는 더블 쿼테이션을 사용하는 게 유리하지 않을까?</p>
<h3 id="스택오버플로우에서도-더블-쿼테이션-사용이-바람직하다고주관적인-의견">스택오버플로우에서도 더블 쿼테이션 사용이 바람직하다고..(주관적인 의견)</h3>
<p>네 가지 이유로 더블 쿼테이션을 사용하는 게 바람직하다고 주장한다.</p>
<ol>
<li>영어에서의 더블 쿼테이션은 인용된 텍스트의 구절을 식별하기 위해 사용하고, 싱글 쿼테이션은 구어적 의미를 나타낸다. 기존 언어와 일관성을 유지하는 것이 합리적이다.</li>
<li>더블 쿼테이션 사용시 I&#39;m Kim 과 같은 문자열에서 apostrophes 를 escape 처리하지 않아도 된다.</li>
<li>더블 쿼테이션은 다른 많은 언어들에서 문자열을 의미하는 것이 일반적이다. JAVA나 C와 같은 언어들에서는 문자열이 더블 쿼테이션을 의미하고, 싱글 쿼테이션은 다른 기능을 가지는 경우가 있다.</li>
<li>JSON 의 표기법은 더블 쿼테이션이다.</li>
</ol>
<p>이러한 이유로 더블 쿼테이션이 유리하다고 말한다.
무엇을 쓰던 상관은 없다고 하지만, 찾아본 내용을 종합했을 때 사내 혹은 프로젝트 컨벤션이 싱글 쿼테이션을 지향하는 것이 아니라면 굳이 사용할 필요가 있을까 생각이 든다. 물론 shift + &#39; 를 누르기가 귀찮긴 하지만..</p>
<hr>

<h3 id="json-은-뭔데">JSON 은 뭔데?</h3>
<p>JSON(Javascript Object Notation) 은 key/value 객체 형태의 경량 데이터 교환 형식이다. JS 를 포함한 여러 언어에서 범용적으로 사용한다.</p>
<p>JSON.stringify : 객체를 JSON 으로 변환(직렬화)
JSON.parse : JSON 을 객체로 변환(역직렬화)</p>
<p>** 직렬화 : 외부의 시스템에서 사용할 수 있도록 바이트 형태로 데이터를 변환하는 기술. 코드 내의 객체나, 해시테이블, 딕셔너리 등을 JSON으로 변환하는 것을 의미한다.</p>
<p>** 역직렬화 : 외부 시스템의 바이트 형태의 데이터를 객체나 해시테이블, 딕셔너리 등으로 변환하는 것을 의미한다.</p>
<h4 id="js와-json-객체의-차이점">JS와 JSON 객체의 차이점</h4>
<p>JS 객체</p>
<ol>
<li>키에 따옴표 없어도 가능 -&gt; {key:&quot;value&quot;}</li>
<li>문자열 값에 작은 따옴표 사용 가능 -&gt; {&quot;key&quot;:&#39;value&#39;}</li>
<li>키-값 사이에 공백 사용 가능 -&gt; {&quot;key&quot; : &quot;value&quot;}</li>
<li>키-값 쌍 사이에 공백 사용 가능 -&gt; {&quot;key&quot;:&quot;value&quot;, a=1}</li>
</ol>
<p>JSON 객체</p>
<ol>
<li>키,값에 무조건 더블 쿼테이션 -&gt; {&quot;key&quot;:&quot;value&quot;}</li>
<li>키-값 사이에 공백 사용 불가능 -&gt; {&quot;key&quot;:&quot;value&quot;}</li>
<li>키-값 쌍 사이에 공백 사용 불가능 -&gt; {&quot;key&quot;:&quot;value&quot;,a=1}</li>
</ol>
<h3 id="json-의-특징">JSON 의 특징</h3>
<ul>
<li>간결하고 가독성이 좋다.
JSON은 텍스트 기반 형식이므로 사람이 읽고 쓰기 쉬우며, 간단하고 가독성이 좋다.</li>
<li>키-값 쌍 형태
JSON 은 키, 값, 사이의 쌍으로 데이터를 표현한다. 키-값 쌍은 객체의 형태로 표현되며, {}로 둘러싸여 있다.</li>
<li>데이터 타입 지원
JSON 은 다양한 데이터 타입을 지원한다. 문자열, 숫자, 불리언, 배열, 객체, null 을 표현할 수 있다.</li>
<li>중첩 구조
JSON 객체 내에서 다른 JSON 객체를 중첩하여 사용할 수 있고, 배열을 사용해서 여러 값을 저장할 수 있다.</li>
<li>언어 독립적
JSON은 언어 독립적인 형식이므로 다양한 프로그래밍 언어 간에 데이터를 교환하는 데 사용할 수 있다.</li>
<li>웹 API 통신
웹 애플리케이션에서 서버와의 통신에 JSON을 주로 사용한다. 서버에서 클라이언트로, 혹은 클라이언트에서 서버로 데이터를 보낼 때 JSON 형식을 사용한다.</li>
</ul>
<p>참고
<a href="https://stackoverflow.com/questions/242813/are-double-and-single-quotes-interchangeable-in-javascript">https://stackoverflow.com/questions/242813/are-double-and-single-quotes-interchangeable-in-javascript</a>
<a href="https://www.json.org/json-en.html">https://www.json.org/json-en.html</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[이번주 회고, git rebase 가 무엇인가]]></title>
            <link>https://velog.io/@ss_g/%EC%9D%B4%EB%B2%88%EC%A3%BC-%ED%9A%8C%EA%B3%A0-git-rebase-%EA%B0%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80</link>
            <guid>https://velog.io/@ss_g/%EC%9D%B4%EB%B2%88%EC%A3%BC-%ED%9A%8C%EA%B3%A0-git-rebase-%EA%B0%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80</guid>
            <pubDate>Sun, 19 May 2024 14:56:14 GMT</pubDate>
            <description><![CDATA[<h3 id="이번주-미흡했던-점">이번주 미흡했던 점</h3>
<p>1) 클라이언트, 서버쪽까지는 금방 끝냈는데 콜봇에 프로세스 적용할 때 방향성을 잘못 잡았다. 생각했던 방향성에 대해 미리 여쭤보고 진행했으면 개발기간을 줄일 수 있었는데 굳이 안해도 되는 작업 방식을 고수해서 개발기간을 길게 가져갔다.</p>
<ul>
<li>curl을 사용했던 이유 : 기존에 작업한 프로세스를 활용해야 하지 않을까 라는 생각이었다. 활용해야겠다는 생각은 했으나, 단순히 require_once 만 해서 사용하면 된다는 생각까지는 하지 못했다. 그래서 curl 을 사용해서 api를 호출해야 겠다는 판단을 했고, 그렇게 작업했다. 하지만 서버단에서 같은 서버의 api 를 굳이 호출할 필요는 없다. 그냥 그 프로세스를 require 해서 활용하기만 하면 되는데 짧은 생각이었다.</li>
</ul>
<p>-&gt; 앞으로 조금 더 적극적인 소통을 할 수 있도록 노력해야 한다. 내가 하려는 방향성에 대해 미리 컨펌을 받자. 컨펌을 받으면 잘못된 생각을 작업 전에 고칠 수 있고, 올바른 방향으로의 개발을 진행 할 수 있다. 또한 모르겠으면 잡고 고민하기보단 바로 여쭤보고 피드백을 받자
<br>
2) 과장님께서 방향성을 제시해주셨으나, 그게 아닌 다른 방법으로 진행했다. 내 나름대로의 생각은 그 방법보다 내가 작업한 방법이 금방 끝낼 수 있다고 생각했다. 이미 해당 이슈로 워킹데이를 많이 소모했기 때문에 빠르게 끝내야 한다는 생각에 그렇게 작업했으나, 최적의 방법은 아니었다. 빠르게 끝내는 것도 중요하지만 나중에 추가 공수가 들어가지 않으려면 최적의 방법으로 진행하는 것도 중요하다.</p>
<p>-&gt; 1 과 비슷한 개선사항. 주관을 가지는 것이 잘못된 것은 아니겠으나, 옳고 그름을 좀 더 명확히 판단할 수 있도록 하자.
<br>
3) 실서버에 굳이 테스트해보지 않아도 되는 것을 반영했다. 로컬서버에서는 확인이 잘 됐지만, 실서버(콜봇 프로세스)에서 여전히 에러가 발생하는 것을 확인하기 위해 실서버에 업로드를 했다. 이로 인해 서비스가 잠시 마비되는 경험을 했다. 이런 상황을 만들어서는 안된다.</p>
<p>-&gt; 항상 실서버에 접근할 때는 최대한 보수적일 수 있도록 하자. 분기처리를 확실히 하고, 잠시 올렸다 롤백하는건 괜찮겠지 라는 안일한 생각은 버리자. 나에게는 잠시일 수 있으나 같은 부분을 보고 있는 타인에게는 영문 모를 버그일 수도 있다.
<br>
4) 게을렀다. 모르는 것에 대해 공부할 수 있었으나, 겉핥기 식으로만 봤고 해당 내용에 대한 개념을 제대로 숙지하지 못했다.
-&gt; 모르는 내용에 대해서는 적극적으로 학습할 수 있도록 하고, 학습에 게으르지 말자. 그리고 뭔가 공부를 할 때 얕게 보지 말고 해당 내용에 대해 깊게 파고들 수 있도록 하자.
<br></p>
<hr>

<h3 id="require과-include의-차이">require과 include의 차이</h3>
<p>require : 해당 파일을 찾지 못하거나 오류가 발생하면 fatal error를 발생시키고 스크립트 실행을 중단한다. 포함하려는 파일이 해당 프로세스(애플리케이션)실행에 필수적일 때 사용한다. 즉 좀 더 strict 한 방식이다. </p>
<p>include : 파일을 찾지 못하거나 오류가 발생하면 경고를 발생시키지만, 스크립트의 실행은 계속된다. 포함하는 파일이 필수적이지 않을때 사용한다. 즉 flexible 하기 때문에 사용을 지양하는 것이 좋다.</p>
<p>그렇다면 once는 뭐지?</p>
<ul>
<li>동일한 파일이 여러 번 포함되지 않도록 한다. 동일한 파일이 여러 번 포함되어 발생할 수 있는 중복 정의 오류를 방지할 수 있다.</li>
</ul>
<hr>

<h3 id="git-rebase-는-무엇인가">git rebase 는 무엇인가</h3>
<ul>
<li>브랜치를 병합하는 데 사용하는 명령어. 브랜치의 기반을 다른 커밋으로 이동시켜서 히스토리를 재작성하는 기능으로, 커밋 히스토리를 깔끔하게 유지할 수 있다. 이를 활용하면 프로젝트의 커밋 히스토리를 명확하고 가독성있게 유지할 수 있다.<br>
ex) A브랜치에서 B브랜치를 파서 작업을 하는 경우에, A브랜치에 타인이 커밋을 추가하는 경우
![](https://velog.velcdn.com/images/ss_g/post/eb41c878-7b07-4a02-bc26-eb318fb5c5cf/image.png)
이 때 merge를 시도하면 conflict이 나게 될 것이다.
A브랜치에서는 추가 커밋이 올라간 상황인데 B브랜치에서는 추가된 커밋이 없이 B브랜치에서 쌓은 커밋만 존재하기 때문이다.
이때 사용할 수 있는 것이 rebase.
rebase 하면 A브랜치의 Head에 맞춰 B브랜치에서 쌓은 커밋들이 쌓이게 된다.![](https://velog.velcdn.com/images/ss_g/post/42794acc-2b94-41ae-9b0d-49e053c2ec31/image.png)

</li>
</ul>
<blockquote>
<p>쉽게 생각하면 현재 브랜치는 rebase하려는 브랜치의 최상단 라인으로 맞춰진다</p>
</blockquote>
<p>만약 feature 브랜치가 main 브랜치로부터 생성이 된 이후, main 브랜치에 변경사항이 추가된 경우에 feature 브랜치를 main 브랜치의 최신상태로 업데이트를 진행해야 할 때</p>
<pre><code>git checkout feature
git rebase main</code></pre><p>이렇게 하면 feature 브랜치는 main 브랜치의 최신 커밋(Head)로 이동된다. 여러 라인으로 작업되다가 하나의 라인으로 rebase 된다고 이해하면 된다.</p>
<ul>
<li>merge 와 rebase 의 차이점
merge 나 rebase 는 브랜치간 내용을 합치기 위한 방법이고, 두 방법의 최종 내용 또한 같지만 히스토리의 차이가 있다.</li>
</ul>
<pre><code>- merge : merge 는 브랜치를 통합하는 것이다. 두 브랜치를 병합할 때 새로운 병합 커밋을 생성한다. 
다른 브랜치에서 여태까지의 커밋 내용을 하나의 merge commit으로 합치기 때문에 히스토리를 추적하기에 어려움이 있어 히스토리가 복잡해질 수 있다. </code></pre><ul>
<li>rebase : 병합 커밋 없이 히스토리를 재작성하기 때문에 깔끔하고 선형적인 히스토리를 유지할 수 있다. 즉 과거 커밋 기록을 보기 쉽다. 
rebase 를 잘 활용하면 프로젝트의 커밋 히스토리를 명확하고 이해하기 쉽게 관리할 수 있다.
다만 히스토리를 재작성하기 때문에 공유된 브랜치(main 등과 같은)에서는 rebase 하지 않아야 한다. 공유된 브랜치에서 rebase 할 시 히스토리가 바뀌면서 충돌이 발생할 수 있기 때문이다.</li>
</ul>
<ul>
<li><p>rebase 주의 사항
  rebase 중 충돌이 발생시
1) 충돌 파일을 수동으로 수정하고 git add 시켜서 수정 내용을 추가시킨다.
2) git rebase --continue 명령어로 rebase를 계속해서 진행한다.</p>
<p>충돌 해결이 복잡하거나 rebase를 중단하고 싶을 시 git rebase --abort 명령어를 사용해 rebase를 중단할 수 있다.</p>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[백엔드 로드맵 따라가기 - How Browers Work]]></title>
            <link>https://velog.io/@ss_g/%EB%B0%B1%EC%97%94%EB%93%9C-%EB%A1%9C%EB%93%9C%EB%A7%B5-%EB%94%B0%EB%9D%BC%EA%B0%80%EA%B8%B0-How-Browers-Work</link>
            <guid>https://velog.io/@ss_g/%EB%B0%B1%EC%97%94%EB%93%9C-%EB%A1%9C%EB%93%9C%EB%A7%B5-%EB%94%B0%EB%9D%BC%EA%B0%80%EA%B8%B0-How-Browers-Work</guid>
            <pubDate>Sun, 28 Apr 2024 04:21:38 GMT</pubDate>
            <description><![CDATA[<p>브라우저 작동 방식</p>
<p>웹브라우저가 웹서버에 웹페이지 요청을 하면 웹서버는 웹페이지에 응답을 한다.
서버가 브라우저에게 전달한 응답인 HTML 문서를 브라우저는 읽어들이고 해석한 후 사용자에게 보여준다.
HTML 및 CSS 를 해석하는 구체적인 내용들은 모두 W3C, World Side Web Consortium 에 의해 관리되고 유지된다. </p>
<p>웹 브라우저 구조와 렌더링 엔진
<img src="https://velog.velcdn.com/images/ss_g/post/cf03ba01-34f8-411c-9e5f-20e847956219/image.png" alt=""></p>
<p>주소창, 버튼 등을 포함한 User Interface, UI와 렌더링 엔진 사이에서 중간 매체 역할을 수행하는 브라우저 엔진, 웹서버로부터 응답 받은 내용을 UI 상에 나타내주는 렌더링 엔진, 웹서버와 통신이 가능하게 하는 네트워크, UI 구동이 가능하게 하는 UI 백엔드, 자바스크립트 코드를 파싱하고 실행하는 자바스크립트 해석기, 쿠키와 같은 로컬 데이터를 저장하는 데이터 스토리지로 구성된다.</p>
<p>이중 가장 핵심적인 역할을 담당하는 렌더링 엔진의 경우 사용자가 요청해서 웹서버가 응답한 HTML 문서를 HTML 과 CSS로 파싱해서 화면을 구성한다. 렌더링 엔진은 여러 개의 인스턴스를 한 번에 구동할 수 있다. 서로 다른 브라우저는 기본적으로 다른 렌더링 엔진을 사용한다. Trident, Gecko, Webkit 등등..
렌더링 엔진은 웹서버로부터 전달받은 HTML 문서를 맨 처음 네트워크 레이어에서 불러온다.</p>
<p>렌더링 엔진 작동 방식
렌더링 엔진은 웹서버로부터 전달받은 HTML 문서를 맨 처음 네트워크 레이어에서 불러온다. 그리고 아래와 같은 기본적인 Flow를 거친다.</p>
<ol>
<li>HTML 파싱 후 DOM 트리 만들기</li>
<li>렌더 트리 만들기</li>
<li>렌더 트리 레이아웃 만들기</li>
<li>렌더 트리 페인팅
<img src="https://velog.velcdn.com/images/ss_g/post/7e6fe743-d98e-4728-ae83-a2a86a25414c/image.png" alt=""></li>
</ol>
<ol>
<li><p>HTML 파싱 후 DOM 트리 만들기
렌더링 엔진은 우선 네트워크 레이어를 통해 전달받은 HTML 문서(source code)를 파싱하여 각 요소들을 DOM Tree(Contents Tree)의 각 DOM 노드들로 전환한다. DOM이란 Document object model의 준말로 마크업 형태의 HTML 문서를 오브젝트 모델의 형태로 바꿔놓은 것이다.</p>
</li>
<li><p>렌더 트리 만들기
HTML 문서들을 파싱하여 DOM Tree를 구성한 후, 렌더링 엔진은 CSS/Style 데이터를 파싱하고 그 스타일 데이터들로 렌더 트리를 만든다. DOM 트리가 웹 상에 나타날 내용을 구성한다면 렌더 트리는 시각적 요소, 어떻게 나타날지 그 스타일을 지정한다. 렌더트리는 색상, 차원 등 시각적 지침들을 담은 정사각형들로 구성된다. 그 정사각형들은 스크린에 맞는 순서대로 정렬되어야 한다.</p>
</li>
</ol>
<p>렌더 트리 각각의 정사각형에 해당하는 Renderer 들은 DOM 트리 요소들에 적용되지만 1:1 관계가 성립되는 것은 아니다. 시각적이지 않은 DOM 요소들은 렌더 트리에 삽입될 수 없다. head 태그 안의 요소들은 화면에 나타나는 값을 포함하지 않는다. 따라서 그 어떤 Renderer도 적용될 수 없다. 어떤 렌더러들은 DOM 노드에 적용될 수 있으나 꼭 트리와 같은 위계에 속할 필요는 없다.</p>
<p><img src="https://velog.velcdn.com/images/ss_g/post/16feee2c-fe38-41b7-9231-e923c999390e/image.png" alt=""></p>
<ol start="3">
<li><p>렌더트리 레이아웃 만들기
레이아웃을 만든다는 것은 각 노드들에게 스크린의 어느 공간에 위치해야 할지 각각의 값(Positionm, size)을 부여하는 것을 의미한다.</p>
</li>
<li><p>렌더 트리 페인팅
렌더 트리가 만들어져 레이아웃이 구성되었다면, UI 백엔드가 동작하여 각 노드들을 정해진 스타일 및 위치값대로 화면세 배치한다.
더 나은 UX를 위해, 렌더링 엔진은 각 콘텐츠를 가능한한 빨리 스크린에 띄워야 한다. 따라서 모든 HTML 요소들을 렌더링 엔진으로 넣어서 한번에 출력하는 것이 아니라, 일부 콘텐츠는 먼저 트리 과정을 거쳐 스크린에 나타나고, 그 와중에 웹의 다른 요소들은 네트워크를 통해 렌더링 엔진으로 읽어들어 오는 순차적인 방식으로 입출력이 진행된다.</p>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[백엔드 로드맵 따라가기 - Everything you need to know about HTTP]]></title>
            <link>https://velog.io/@ss_g/%EB%B0%B1%EC%97%94%EB%93%9C-%EB%A1%9C%EB%93%9C%EB%A7%B5-%EB%94%B0%EB%9D%BC%EA%B0%80%EA%B8%B0-Everything-you-need-to-know-about-HTTP-n6grayxj</link>
            <guid>https://velog.io/@ss_g/%EB%B0%B1%EC%97%94%EB%93%9C-%EB%A1%9C%EB%93%9C%EB%A7%B5-%EB%94%B0%EB%9D%BC%EA%B0%80%EA%B8%B0-Everything-you-need-to-know-about-HTTP-n6grayxj</guid>
            <pubDate>Sun, 28 Apr 2024 04:19:44 GMT</pubDate>
            <description><![CDATA[<p>HTTP란 무엇인가?
HTTP(HyperText Transfer Protocol)는 World Wide Web의 기초이며 하이퍼텍스트 링크를 사용하여 웹페이지를 로드하는데 사용된다. HTTP는 네트워크로 연결된 장치 간에 정보를 전송하도록 설계된 애플리케이션 계층 프로토콜이며 네트워크 프로토콜 스택의 다른 계층 위에서 실행된다. HTTP를 통한 일반적인 흐름에는 시스템이 서버에 요청한 후 응답 메시지를 보내는 것이 포함된다.</p>
<p>HTTP 요청 종류
HTTP 요청은 웹 브라우저와 같은 인터넷 통신 플랫폼이 웹 사이트를 로드하는 데 필요한 정보를 요청하는 방식이다.
인터넷을 통해 이루어진 각 HTTP 요청은 다양한 유형의 정보를 전달하는 일련의 인코딩된 데이터를 전달한다. 일반적인 HTTP 요청에는 다음이 포함된다.</p>
<ol>
<li>HTTP 버전 유형</li>
<li>URL</li>
<li>HTTP메소드</li>
<li>HTTP 요청헤어</li>
<li>선택적 HTTP 본문</li>
</ol>
<p>HTTP 메소드란?
HTTP 동사라고도 하는 HTTP 메서드는 쿼리된 서버에서 HTTP 요청이 기대하는 작업을 나타낸다. 예를 들어, 가장 일반적인 메소두 두가지중 GET 요청은 정보가 반환되기를 기대하는 반면 POST 요청은 일반적으로 클라이언트가 웹 서버에 정보를 제출하고 있음을 나타낸다.</p>
<p>HTTP 요청 헤더란?
HTTP 헤더에는 키-쌍 값으로 저장된 텍스트 정보가 포함되어 있으며 모든 HTTP 요청에 포함된다. 이러한 헤더는 클라이언트가 사용하는 브라우저, 요청되는 데이터 등 핵심 정보를 전달한다.</p>
<p>HTTP 요청 본문에는 어떤 것들이 있나?
요청 본문은 요청이 전송하는 정보의 ‘본문’을 포함하는 부분이다. HTTP 요청의 본문에는 사용자 이름, 비밀번호 또는 양식에 입력된 기타 데이터 등 웹 서버에 제출되는 모든 정보가 포함된다.</p>
<p>HTTP 응답에는 무엇이 들어있나?
HTTP 응답은 웹 클라이언트가 HTTP 요청에 대한 응답으로 인터넷 서버로부터 수신하는 것이다 이러한 응답은 HTTP 요청에서 요청한 내용을 기반으로 정보를 전달한다.
일반적으로 HTTP 응답에는 1. HTTP 상태코드, 2. HTTP 응답헤더, 3. 선텍적 HTTP 본문 이 포함된다</p>
<p>HTTP 상태 코드란?
HTTP 상태 코드는 HTTP 요청이 성공적으로 완료되었는지 여부를 나타내는 데 가장 자주 사용되는 3자리 코드이다. 상태 코드는 다음 5개의 블록으로 구분된다</p>
<ol>
<li>1xx 정보</li>
<li>2xx 성공</li>
<li>3xx 리디렉션</li>
<li>xx 클라이언트 오류</li>
<li>5xx 서버 오류</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[백엔드 로드맵 따라가기 - How does the Internet work?]]></title>
            <link>https://velog.io/@ss_g/%EB%B0%B1%EC%97%94%EB%93%9C-%EB%A1%9C%EB%93%9C%EB%A7%B5-%EB%94%B0%EB%9D%BC%EA%B0%80%EA%B8%B0-How-does-the-Internet-work</link>
            <guid>https://velog.io/@ss_g/%EB%B0%B1%EC%97%94%EB%93%9C-%EB%A1%9C%EB%93%9C%EB%A7%B5-%EB%94%B0%EB%9D%BC%EA%B0%80%EA%B8%B0-How-does-the-Internet-work</guid>
            <pubDate>Sun, 28 Apr 2024 04:19:02 GMT</pubDate>
            <description><![CDATA[<ol>
<li><p>인터넷 소개
인터넷은 네트워크의 네트워크
네트워크는 뭐지? 서로 연결된 컴퓨터 또는 기타 장치의 그룹
ex) 집에 나의 컴퓨터와 장치의 네트워크가 있고, 옆집에도 비슷한 장치 네트워크가 있다면 이러한 모든 네트워크는 함께 연결되면 인터넷을 형성한다.</p>
</li>
<li><p>인터넷 작동 방식 : 개요
인터넷의 핵심은 서로 다른 장치와 시스템 간의 트래픽 전달을 담당하는 상호 연결된 라우터의 글로벌 네트워크이다.
인터넷을 통해 데이터를 보내면 데이터는 작은 패킷으로 나뉘어 장치에서 라우터로 전송된다.
라우터는 패킷을 검사하여 목적지를 향한 경로의 다음 라우터로 전달하고, 이 프로세스는 패킷이 최종 목적지에 도달할 때까지 계속된다.</p>
</li>
</ol>
<ul>
<li>패킷은 뭐지? <ul>
<li>네트워크를 통해 전송되는 형식화된 데이터 덩어리. 네트워크 패킷의 주요 컴포넌트는 사용자 데이터와 제어 정보이다. 사용자 데이터는 payload 로 알려져 있고, 제어정보는 payload를 전달하기 위한 정보이다.</li>
</ul>
</li>
</ul>
<p>패킷이 올바르게 전송되고 수신되도록 하기 위해 인터넷은 IP(인터넷 프로토콜) 및 TCP(전송 제어 프로토콜)를 포함한 다양한 프로토콜을 사용한다. IP는 패킷을 올바른 대상으로 라우팅하는 역할을 담당하고, TCP는 패킷이 올바른 순서로 안정적으로 전송되도록 보장한다.</p>
<ul>
<li>프로토콜은 뭐지?<ul>
<li>컴퓨터나 원거리 통신 장비 사이에서 메시지를 주고 받는 양식과 규칙의 체계. 즉 통신 규약 및 약속이다.
기본 요소 3가지
구문(Syntax) : 전송하고자 하는 데이터의 형식(Format), 부호화(Coding), 신호레벨(Signal Level) 등을 규정
의미(Semantics) : 두 기기 간의 효율적이고 정확한 정보 전송을 위한 협조 사항과 오류 관리를 위한 제어 정보를 규정
시간(Timing) : 두 기기 간의 통신 속도, 메시지의 순서 제어 등을 규정
프로토콜의 종류
<img src="https://velog.velcdn.com/images/ss_g/post/7d185d97-a9fd-4642-94a8-b66d4100b494/image.png" alt=""></li>
</ul>
</li>
</ul>
<ul>
<li>IP와 TCP에 대한 정확한 개념은 뭐지?<ul>
<li>IP : 인터넷에 연결되어 있는 모든 장치들(컴퓨터, 서버 장비, 휴대폰 등)을 식별할 수 있도록 각가의 장비에 부여되는 고유 주소
IP 주소는 IPv4, IPv6 두 가지 종류가 있으며, 일반적으로 IP주소라 하면 IPv4를 말한다.
IPv4는 IP version 4의 약자로 전 세계적으로 사용된 첫 번째 인터넷 프로토콜로서, 주소는 32비트 방식으로, 8비트씩 4자리로 되어 있으며 각 자리는 온점으로 구분한다.
ex) 111.11.11.11
IPv4는 0~2^32(약 42억 9천)개의 주소를 가질 수 있는데, 세계적으로 사용중인 IP 갯수가 급증하면서 주소가 고갈될 위기에 처해있다. 이를 해결하기 위해 나온 것이 IPv6
IPv6는 IPv4의 주소체계를 128비트 크기로 확장한 차세대 인터넷 프로토콜 주소이다. 16비트씩 8자리로 각 자리는 콜론으로 구분한다.
ex) 2001:0DB8:1000:0000:0000:0000:1111:2222
네트워크 속도, 보안적인 부분 뿐만 아니라 여러 면에서 뛰어나지만 기존의 주소체계를 변경하는데 비용이 많이 든다.</li>
</ul>
</li>
</ul>
<p>이러한 핵심 프로토콜 외에도 DNS(Domain Name System), HTTP(HyperText Transfer Protocol) 및 보안 프로토콜을 포함하여 인터넷을 통한 통신 및 데이터 교환을 가능하게 하는 데 사용되는 다양한 기술 및 프로토콜이 있다.</p>
<ol start="3">
<li>기본 개념 및 용어
인터넷을 이해하기 위해 알아야 할 몇 가지 기본 개념과 용어</li>
</ol>
<ul>
<li>패킷(Packet) : 인터넷을 통해 전송되는 작은 데이터 단위</li>
<li>라우터 : 서로 다른 네트워크 간에 데이터 패킷을 전달하는 장치</li>
<li>IP 주소 : 네트워크의 각 장치에 할당된 고유 식별자로, 데이터를 올바른 대상으로 라우팅하는 데 사용됨</li>
<li>도메인 이름 : google.com 과 같이 웹사이트를 식별하는 데 사용되는 사람이 읽을 수 있는 이름</li>
<li>DNS : 도메인 이름 시스템은 도메인 이름을 IP 주소로 변환하는 역할을 담당</li>
<li>HTTP : 하이퍼텍스트 전송 프로토콜은 클라이언트와 서버간에 데이터를 전송하는 데 사용됨</li>
<li>HTTPS : 클라이언트와 서버 간의 보안 통신을 제공하는 데 사용되는 암호화된 HTTP 버전</li>
<li>SSL/TSL : SSL(Secure Sockets Layer) 및 전송 계층 보안(Transport Layer Security) 프로토콜은 인터넷을 통한 보안 통신을 제공하는 데 사용</li>
</ul>
<ol start="4">
<li><p>인터넷에서 프로토콜의 역할
프로토콜은 인터넷을 통한 통신 및 데이터 교환을 가능하게 하는 데 중요한 역할을 한다. 프로토콜은 장치와 시스템 간에 정보가 교환되는 방식을 정의하는 일련의 규칙 및 표준이다.
인터넷 프로토콜(IP), 전송 제어 프로토콜(TCP), 사용자 데이터그램 프로토콜(UDP), 도메인 이름 시스템(DNS) 등을 포함하여 인터넷 통신에 사용되는 다양한 프로토콜이 있다.
IP는 데이터 패킷을 올바른 대상으로 라우팅하는 역할을 하며, TCP와 UDP는 패킷이 안정적이고 효율적으로 전송되도록 보장한다. DNS는 도메인 이름을 IP 주소로 변환하는 데 사용되고, HTTP는 클라이언트와 서버 간에 데이터를 전송하는 데 사용된다.
표준화된 프로토콜을 사용하는 주요 이점 중 하나는 다양한 제조업체 및 공급업체으이 장치와 시스템이 서로 원활하게 통신할 수 있다는 것이다.</p>
</li>
<li><p>IP 주소 및 도메인 이름 이해
IP 주소와 도메인 이름은 모두 인터넷 작업 시 이해해야 할 중요한 개념이다.
IP 주소는 네트워크의 각 장치에 할당된 고유 식별자이다. 이는 데이터를 올바를 대상으로 라우팅하여 정보가 의도한 수신자에게 전송되도록 하는 데 사용된다. IP 주소는 일반적으로 1111.111.1.1과 같이 마침표로 구분된 일련의 4개 숫자료 표시된다.
반면, 도메인 이름은 웹사이트와 기타 인터넷 리소스를 식별하는 데 사용되는 사람이 읽을 수 있는 이름이다. 일반적으로 두 개 이상의 부분으로 구성되며 마침표로 구분된다. 
ex) google.com은 도메인 이름이며, 도메인 이름은 DNS(Damain Name System)를 사용하여 IP 주소로 변환된다.
DNS는 도메인 이름을 IP 주소로 변환하는 역할을 하는 인터넷 인프라의 중요한 부분으로 웹 브라우저에 도메인 이름을 입력하면 컴퓨터는 DNS 서버에 DNS 쿼리를 보내고, DNS 서버는 해당 IP 주소를 반환한다. 그러면 컴퓨터는 해당 IP 주소를 사용하여 요청한 웹 사이트나 기타 리소스에 연결한다.</p>
</li>
<li><p>HTTP 및 HTTPS 소개
HTTP와 HTTPS 는 인터넷 기반 애플리케이션 및 서비스에서 가장 일반적으로 사용되는 두 가지 프로토콜이다.
HTTP 는 클라이언트와 서버간에 데이터를 전송하는 데 사용되는 프로토콜이다. 웹사이트를 방문하면 웹 브라우저는 서버에 HTTP 요청을 보내 요청한 웹페이지나 기타 리소스를 요청한다. 그런 다음 서버는 요청된 데이터가 포함된 HTTP 응답을 클라이언트에 다시 보낸다.
HTTPS 는 SSL/TLS 암호화를 사용하여 클라이언트와 서버 간에 전송되는 데이터를 암호화하는 보다 안전한 HTTP 버전이다. 이는 추가 보안 계층을 제공하여 로그인 자격 증명, 결제 정보 및 기타 데이터와 같은 민감한 정보를 보호하는 데 도움이 된다.</p>
</li>
<li><p>TCP/IP를 사용하여 애플리케이션 구축
TCP/IP(전송 제어 프로토콜/인터넷 프로토콜)는 대부분의 인터넷 기반 응용 프로그램 및 서비스에서 사용되는 기본 통신 프로토콜이다. 이는 서로 다른 장치에서 실행되는 애플리케이션 간에 안정적이고 순서적이며 오류가 확인된 데이터 전달을 제공한다.
TCP/IP 로 애플리케이션을 구축할 때 이해해야 할 몇 가지 주요 개념이 있다.</p>
</li>
</ol>
<ul>
<li>포트 : 포트는 장치에서 실행 중인 애플리케이션이나 서비스를 식별하는데 사용된다. 각 애플리케이션이나 서비스에는 고유한 포트 번호가 할당되어 데이터가 올바른 대상으로 전송될 수 있다.</li>
<li>소켓 : 소켓은 IP 주소와 포트 번호의 조합으로, 통신을 위한 특정 끝점을 나타낸다. 소켓은 장치 간 연결을 설정하고 애플리케이션 간에 데이터를 전송하는 데 사용된다.</li>
<li>연결 : 두 장치가 서로 통신하려고 할 때 두 소켓 사이에 연결이 설정된다. 연결 설정 프로세스 중에 장치는 최대 세그먼트 크기 및 창 크기와 같은 다양한 매개변수를 협상하여 연결을 통해 데이터가 전송되는 방식을 결정한다.</li>
<li>데이터 전송 : 연결이 설정되면 각 장치에서 실행되는 애플리케이션 간에 데이터를 전송할 수 있다. 데이터는 일반적으로 세그먼트로 전송되며, 각 세그먼트에는 안정적인 전달을 보장하기 위해 시퀀스 번호와 이타 메타데이터가 포함된다.
TCP/IP 를 사용하여 애플리케이션을 구축할 때 애플리케이션이 적절한 포트, 소켓 및 연결과 함께 작동하도록 설계되었는지 확인해야 한다. 또한 HTTP, FTP, SMTP등 TCP/IP에 일반적으로 사용되는 다양한 프로토콜과 표준에 대해 잘 알고 있어야한다, 효과적이고 확장 가능하며 안전한 인터넷 기반 애플리케이션과 서비스를 구축하려면 이러한 개념과 프로토콜을 이해하는 것이 필수적이다.</li>
<li>FTP에 대한 정확한 개념은 뭐지?<ul>
<li>File Transfer Protocol의 약자로 TCP/IP 네트워크상에서 컴퓨터들이 파일을 교환하기위한 통신 규약.
하나의 호스트에서 다른 호스트로 파일을 복사하기 위해 사용한다.</li>
</ul>
</li>
<li>SMPT에 대한 정확한 개념은 뭐지?<ul>
<li>Simple Mail Transfer Protocol의 약자로 인터넷을 통해 이메일 메시지를 보내고 받는 데 사용되는 통신 프로토콜.</li>
</ul>
</li>
</ul>
<ol start="8">
<li><p>SSL/TLS 로 인터넷 통신 보안
SSL/TSL는 인터넷을 통해 전송되는 데이터를 암호화하는데 사용되는 프로토콜이다. 일반적으로 웹 브라우저, 이메일 클라이언트, 파일 전송 프로그램과 같은 애플리케이션에 보안 연결을 제공하는 데 사용된다.
SSL/TLS를 사용하여 인터넷 통신을 보호할 때 이해해야 할 몇 가지 주요개념
인증서 : SSL/TLS 인증서는 클라이언트와 서버 간의 신뢰를 구축하는 데 사용된다. 여기에는 서버의 신원에 대한 정보가 포함되어 있으며 신뢰성을 확인하게 위해 신뢰할 수 있는 제 3자(인증기관)의 서명을 받는다.
핸드셰이크 : SSL/TLS 핸드셰이크 프로세스 중에 클라이언트와 서버는 보안 연결을 위한 암호화 알고리즘 및 기타 매개변수를 협상하기 위해 정보를 교환한다.
암호화 : 보안 연결이 설정되면 합의된 알고리즘을 사용하여 데이터가 암호화되며 클라이언트와 서버 간에 안전하게 전송될 수 있다.
인터넷 기반 애플리케이션 및 서비스를 구축할 때 SSL/TLS 의 작동 방식을 이해하고 로그인 자격 증명, 결제 정보, 기타 개인 데이터와 같은 민감한 데이터를 전송할 때 애플리케이션이 SSL/TLS를 사용하도록 설계되었는지 확인하는 것이 중요하다. 또한 서버에 대해 유효한 SSL/TLS 인증서를 획득 및 유지하고 SSL/TLS 연결 구성 및 보안을 위한 모범 사례를 따르고 있는지 확인해야 한다. 이렇게 하면 사용자 데이터를 보호하고 인터넷을 통한 애플리케이션 통신의 무결성과 기밀성을 보장할 수 있다.</p>
</li>
<li><p>결론</p>
</li>
</ol>
<ul>
<li>인터넷은 데이터를 교환하기 위해 표준 통신 프로토콜 세트를 사용하는 상호 연결된 컴퓨터의 글로벌 네트워크이다.</li>
<li>인터넷은 IP 및 TCP와 같은 표준화된 프로토콜을 사용하여 장치와 컴퓨터 시스템을 함께 연결함으로써 작동한다.</li>
<li>인터넷을 핵심은 서로 다른 장치와 시스템 간에 트래픽을 전달하는 상호 연결된 라우터의 글로벌 네트워크이다.</li>
<li>숙지해야 할 기본 개념과 용어에는 패킷. 라우터, IP, 도메인, DNS, HTTP, HTTPS 및 SSL/TLS 등이 있다.</li>
<li>프로토콜은 인터넷을 통한 통신 및 데이터 교환을 가능하게 하는 데 중요한 역할을 하며, 다양한 제조업체 및 공급업체의 장치와 시스템이 원활하게 통신할 수 있도록 해준다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[UML 다이어그램]]></title>
            <link>https://velog.io/@ss_g/UML-%EB%8B%A4%EC%9D%B4%EC%96%B4%EA%B7%B8%EB%9E%A8</link>
            <guid>https://velog.io/@ss_g/UML-%EB%8B%A4%EC%9D%B4%EC%96%B4%EA%B7%B8%EB%9E%A8</guid>
            <pubDate>Fri, 09 Feb 2024 09:43:36 GMT</pubDate>
            <description><![CDATA[<h3 id="정보처리기사-공부">정보처리기사 공부</h3>
<br>

<h4 id="uml-다이어그램">UML 다이어그램</h4>
<p>UML(Unified Modeling Language) : 소프트웨어 시스템을 개발하는 과정에서 산출물의 명세화, 시각화, 문서화할 때 사용하는 모델링 언어로, 하나의 시스템을 표현하기 위한 표준적인 방법 제공을 위해 만들어졌다.</p>
<p>1) Class Diagram(클래스 다이어그램)</p>
<p>시스템에서 사용되는 객체 타입을 정의하는 다이어그램. 객체 지향 시스템에서 공통적으로 많이 쓰이는 다이어그램으로, 프로그램 코드로 바로 변환이 가능하다는 장점이 있다. 클래스는 이름, 속성, 연산으로 구성되고 모델 요소와 클래스 간의 관계를 여러 모양의 화살표와 선으로 표현한다.
<img src="https://velog.velcdn.com/images/ss_g/post/c42002f5-6491-4da7-9718-1650dbbcf956/image.png" alt=""></p>
<p>2) Use Case Diagram(유즈케이스 다이어그램)</p>
<p>시스템과 사용자의 상호작용을 다이어그램으로 표현한 UML 다이어그램. 사용자가 시스템 내부 기능 중 어떤 기능을 사용 가능한지 나타내기 때문에, 고객과 개발자의 요구사항 관련 의견을 조율할 수 있다. 사용자와 시스템 사이의 관계를 나타내는 다이어그램이다.
<img src="https://velog.velcdn.com/images/ss_g/post/a06680cd-9c81-42df-833e-a33304b183d5/image.png" alt=""></p>
<p>3) Package Diagram(패키지 다이어그램)</p>
<p>클래스와 같이 여러 모델 요소를 그룹화하여 표현하는 UML 다이어그램. 서로 다른 패키지들 사이 의존관계를 표현한다. 패키지는 여러 클래스들로 구성된 묶음을 말하고, 의존 관계는 하나의 패키지가 다른 패키지를 사용하는 관계이다.
<img src="https://velog.velcdn.com/images/ss_g/post/538f3aef-40a0-4f2f-940b-c2a23002836f/image.png" alt=""></p>
<p>4) Statechart Diagram(상태 다이어그램)</p>
<p>객체가 가지는 모든 가능한 상태를 표현한 UML 다이어그램. 진입 조건, 탈출 조건, 상태 전이에 필요한 사건 등 자세한 상황을 표현한다. 설계 단계에서 객체가 동적 행동을 어떻게 하는지 표현하는데 쓰인다.
<img src="https://velog.velcdn.com/images/ss_g/post/5081c432-027e-42fc-90cd-db9a449b208c/image.png" alt=""></p>
<p>5) Activity Diagram(액티비티 다이어그램)</p>
<p>객체가 로직이나 조건에 따라 처리되는 흐름을 순서에 따라 정의한 UML 다이어그램. 무언가를 하고 있는 상태를 활동이라 하고, 시작 상태와 종료 상태, 선택점과 전이 등 클래스의 관계와 생명 주기나 관계를 표현한다.
<img src="https://velog.velcdn.com/images/ss_g/post/738ff1b8-71f0-4683-ae84-148fa3ae3ee8/image.png" alt=""></p>
<p>6) Component Diagram(컴포넌트 다이어그램)</p>
<p>시스템을 구성하는 요소들의 조직과 종속성을 보여준다. 클래스 다이어그램과 비슷한데, 둘 다 의존성이 있고 일반화가 가능하다. 정해진 인터페이스를 실현 가능하기도 하다. 단, 클래스는 논리적인 추상화에 가까운 반면 컴포넌트는 물리적 요소를 나타낸다. 클래스는 속성과 오퍼레이션을 직접 가지지만, 컴포넌트는 자신의 인터페이스를 통해 접근 가능한 오퍼레이션만 가질 수 있다.
<img src="https://velog.velcdn.com/images/ss_g/post/2f989a67-8f20-497b-b173-3c8aa095e930/image.png" alt=""></p>
<p>7) Sequence Diagram(순차 다이어그램)</p>
<p>객체들끼리 주고 받는 메세지의 순서를 시간의 흐름에 따라 보여주는 다이어그램이다. 일반적으로 화면 요구사항과 클래스 다이어그램 기반으로 작성된다. 1. 객체 간의 관계, 메시지의 시간적 순서 강조 표현과 2. useCase 시나리오를 시간과 순서에 따라 묘사 및 도식화하고 3. 복잡한 시나리오나 실시간 명세 표현, 메시지의 명시적인 순서 표현하는 특징이 있다.
<img src="https://velog.velcdn.com/images/ss_g/post/d4214833-1560-43f9-8c1d-03d53c41f184/image.png" alt=""></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Bubble Sort / Selection Sort]]></title>
            <link>https://velog.io/@ss_g/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EA%B3%B5%EB%B6%80</link>
            <guid>https://velog.io/@ss_g/%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EA%B3%B5%EB%B6%80</guid>
            <pubDate>Sat, 27 Jan 2024 06:50:14 GMT</pubDate>
            <description><![CDATA[<h2 id="거품정렬bubble-sort">거품정렬(Bubble Sort)</h2>
<blockquote>
<p>서로 인접한 두 원소의 대소를 비교하고, 조건에 맞지 않다면 자리를 교환하며 정렬하는 알고리즘</p>
</blockquote>
<p>거품 정렬은 선택 정렬과 유사한 알고리즘이다.</p>
<h4 id="정렬-방법">정렬 방법</h4>
<ol>
<li>1회전에 첫 번째 원소와 두 번째 원소를, 두 번째 원소와 세 번째 원소를... 이런 식으로 마지막 -1 번째 원소와 마지막 원소를 비교하며 조건에 맞지 않는다면 서로 교환한다.</li>
<li>1회전을 수행하고 나면 가장 큰 원소가 맨 뒤로 이동하므로 2회전에서는 맨 끝에 있는 원소는 정렬에서 제외되고, 2회전을 수행하고 나면 끝에서 두 번째 원소까지는 정렬에서 제외된다. 이렇게 정렬을 1회전 수행할 때마다 정렬에서 제외되는 데이터가 하나씩 늘어난다.</li>
</ol>
<h4 id="java-code">Java Code</h4>
<pre><code>void bubbleSort(int[] arr) {
    int temp = 0;
    for(int i = 0; i &lt; arr.length; i++) {       // 1.
        for(int j= 1 ; j &lt; arr.length-i; j++) { // 2.
            if(arr[j-1] &gt; arr[j]) {             // 3.
                // swap(arr[j-1], arr[j])
                temp = arr[j-1];
                arr[j-1] = arr[j];
                arr[j] = temp;
            }
        }
    }
}</code></pre><ol>
<li>i는 제외될 원소의 갯수를 의미한다. 1회전이 끝난 후 배열의 마지막 위치에는 가장 큰 원소가 위치하기 때문에 하나씩 증가시켜준다.</li>
<li>원소를 비교할 index를 뽑는 반복문으로 j는 현재 원소를 가리키고, j-1은 이전 원소를 가리키게 되므로, j는 1부터 시작한다.</li>
<li>현재 가리키고 있는 두 원소의 대소를 비교한다, 해당 코드는 오름차순 정렬이므로 현재 원소보다 이전 원소가 더 크다면 이전 원소가 뒤로 가야하므로 서로 자리를 교환해준다.</li>
</ol>
<p><img src="https://velog.velcdn.com/images/ss_g/post/de22b18a-025b-49fd-9996-d751c1e0de9a/image.gif" alt=""></p>
<h4 id="시간복잡도">시간복잡도</h4>
<blockquote>
<p>(n-1) + (n-2) + (n-3) + ..... + 2 + 1 =&gt; n(n-1) / 2
이므로 O(n^2)이다</p>
</blockquote>
<p>Bubble Sort는 정렬이 돼있던 안돼있던, 2개의 원소를 비교하기 때문에 최선, 평균, 푀악의 경우 모두 시간 복잡도가 동일하다.</p>
<h4 id="공간복잡도">공간복잡도</h4>
<p>주어진 배열 안에서 교환(swap)을 통해 정렬이 수행되므로 O(n)이다.</p>
<h4 id="장점">장점</h4>
<ul>
<li>구현이 간단하고, 소스코드가 직관적</li>
<li>정렬하고자 하는 배열 안에서 교환하는 방식이므로, 다른 메모리 공간을 필요로 하지 않는다. =&gt; 제자리 정렬(in-place sorting)</li>
<li>안전 정렬(stable Sort)이다.</li>
</ul>
<h4 id="단점">단점</h4>
<ul>
<li>시간복잡도가 최악, 최선, 평균 모두 O(n^2)으로, 굉장히 비효율적이다.</li>
<li>정렬 돼있지 않은 원소가 정렬 됐을때의 자리로 가기 위해서, 교환 연산(swap)이 많이 일어나게 된다.</li>
</ul>
<br>
<hr>

<h2 id="선택-정렬selection-sort">선택 정렬(Selection Sort)</h2>
<blockquote>
<p>해당 순서에 원소를 넣을 위치는 이미 정해져 있고, 어떤 원소를 넣을지 선택하는 알고리즘</p>
</blockquote>
<p>선택 정렬은 거품 정렬과 유사한 알고리즘이다.</p>
<h4 id="정렬방법">정렬방법</h4>
<ol>
<li>주어진 배열 중에 최소값을 찾는다.</li>
<li>그 값을 맨 앞에 위치한 값과 교체한다.(pass)</li>
<li>맨 처음 위치를 뺀 나머지 배열을 같은 방법으로 교체한다.</li>
</ol>
<h4 id="java-code-1">Java Code</h4>
<pre><code>void selectionSort(int[] arr) {
    int indexMin, temp;
    for (int i = 0; i &lt; arr.length-1; i++) {        // 1.
        indexMin = i;
        for (int j = i + 1; j &lt; arr.length; j++) {  // 2.
            if (arr[j] &lt; arr[indexMin]) {           // 3.
                indexMin = j;
            }
        }
        // 4. swap(arr[indexMin], arr[i])
        temp = arr[indexMin];
        arr[indexMin] = arr[i];
        arr[i] = temp;
  }
}</code></pre><ol>
<li>위치(index)를 선택해준다.</li>
<li>i + 1 번째 원소부터 선택한 위치(index)의 값과 비교를 시작한다.</li>
<li>오름차순이므로 현재 선택한 자리에 있는 값보다 순회하고 있는 값이 작다면, 위치(index)를 갱신해준다.</li>
<li>&#39;2&#39;번 반복문이 끝난 뒤에는 indexMin에 &#39;1&#39;번에서 선택한 위치(index)에 들어가야하는 값의 위치(index)를 갖고 있으므로 서로 교환(swap)해준다.</li>
</ol>
<p><img src="https://velog.velcdn.com/images/ss_g/post/b2f08066-6e32-41c1-a9fe-1bc6d98a1755/image.gif" alt=""></p>
<h4 id="시간복잡도-1">시간복잡도</h4>
<p>데이터의 개수가 n개라고 했을 때,</p>
<ul>
<li>첫 번째 회전에서의 비교횟수 = 1 ~ (n-1) =&gt; n-1</li>
<li>두 번째 회전에서의 비교횟수 : 2 ~ (n-1) =&gt; n-2
...</li>
</ul>
<blockquote>
<p>(n-1) + (n+2) + .... + 2 + 1 =&gt; n(n-1) / 2</p>
</blockquote>
<p>비교하는 것이 상수 시간에 이루어진다는 가정 아래, n개의 주어진 배열을 정렬하는데 O(n^2) 만큼의 시간이 걸린다. 최선, 평균, 최악의 경우 시간복잡도는 O(n^2) 으로 동일하다.</p>
<h4 id="공간복잡도-1">공간복잡도</h4>
<p>주어진 배열 안에서 교환(swap)을 통해 정렬이 수행되므로 O(n) 이다.</p>
<h4 id="장점-1">장점</h4>
<ul>
<li>Bubble Sort와 마찬가지로 알고리즘이 단순하다.</li>
<li>정렬을 위한 비교 횟수는 많지만, Bubble Sort에 비해 실제로 교환하는 횟수는 적기 때문에 많은 교환이 일어나야 하는 자료상태에서 비교적 효율적이다.</li>
<li>Bubble Sort와 마찬가지로 정렬하고자 하는 배열 안에서 교환하는 방식이므로, 다른 메모리 공간을 필요로 하지 않는다. =&gt; 제자리 정렬(in-place sorting)</li>
</ul>
<h4 id="단점-1">단점</h4>
<ul>
<li>시간복잡도가 O(n^2)으로 비효율적이다.</li>
<li>불안정 정렬(Unstable Sort)이다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[db connection, connection pool]]></title>
            <link>https://velog.io/@ss_g/db-connection-connection-pool</link>
            <guid>https://velog.io/@ss_g/db-connection-connection-pool</guid>
            <pubDate>Tue, 16 Jan 2024 08:44:02 GMT</pubDate>
            <description><![CDATA[<p>회사에서 기존에 진행하던 프로젝트를 리뉴얼하는 작업을 하게 되어 개발환경을 설정하고 리뉴얼을 막 시작했는데, Dbeaver에서 해당 프로젝트의 개발서버 db가 접속이 되지 않는 이슈가 발생했다.</p>
<pre><code>fatal: remaining connection slots are reserved for non-replication superuser connections</code></pre><p>라는 에러코드였고, 이는 슈퍼유저 연결용을 제외한 커넥션 슬롯이 가득 찼다는 의미였다.
처음엔 내가 수정할 수 있는 문제인줄 알고 찾아보면서 db 설정도 확인해보고 했으나, 회사 db 관리는 서버를 관리 하시는 분이 총괄 하시는 게 생각나 확인 요청 드려서 해결했다. 
그러나 찾아보면서 알게 된 내용을 정리해두면 좋을 것 같아 작성한다.</p>
<h3 id="스프링부트-db-커넥션과-커넥션-풀">스프링부트 DB 커넥션과 커넥션 풀</h3>
<p>자바에서는 JDBC(Java Database Connectivity)라는 데이터베이스에 좁속할 수 있도록 하는 API가 있다. JDBC는 데이터베이스에서 자료를 쿼리하거나 업데이트하는 방법을 제공한다.</p>
<h4 id="db-connection">DB Connection</h4>
<p>DB를 사용하기 위해 DB와 애플리케이션간 통신할 수 있는 수단으로, DB Connection에는 Database Driver와 Database 연결 정보를 담은 URL이 필요하다.</p>
<h4 id="connection-pool">Connection Pool</h4>
<p>웹 컨테이너(WAS)가 실행되면서 일정량의 Connection 객체를 미리 만들어서 pool에 저장했다가, 클라이언트 요청이 오면 Connection 객체를 빌려주고 해당 객체의 임무가 완료되었을 때 다시 Connection 객체를 반납받아 pool에 저장하는 프로그래밍 기법이다.</p>
<h4 id="해결방법">해결방법</h4>
<p>나는 직접 db를 수정할 권한이 없었기 때문에 요청해서 해결했지만, 보통 이런 문제에서는 Connection Pool을 늘려주는 방법을 자주 사용하는 것으로 보였다. 다만 Connection Pool의 권장 크기는 아래와 같이 정의하고 있다.</p>
<pre><code>1 connections = ((core_count) * 2) + effective_spindle_count)</code></pre><hr>

<h3 id="프로젝트-db변경">프로젝트 DB변경</h3>
<p>위의 문제를 해결하자마자 바로 해당 프로젝트의 db를 마이그레이션 해서 새로운 접속 정보를 주셨다. 여태까지는 연결되어 있는 프로젝트만 받아서 작업하다가 새로 연결하게 되어 스프링 환경에서 연결 방법을 찾아보고 수정했다.</p>
<h4 id="해결방법-1">해결방법</h4>
<p>새로운 db도 같은 DBMS를 사용하고 있었기 때문에 기존 설정파일은 건들 것이 없었고, local과 dev의 yml 파일에 db 정보만 변경 후 재빌드 하면 됐다. 
생각보다 간단해서 새로 db를 연결하는 방법에 대해서도 찾아보았는데, 처음에 build.gradle에 사용할 DBMS와 관련된 것만 설정하고 db 접속정보를 그대로 yml에 넣으면 그대로 사용할 수 있는 것을 알 수 있었다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[자바 공부 시작 전 궁금한 용어들 정리]]></title>
            <link>https://velog.io/@ss_g/%EC%9E%90%EB%B0%94-%EA%B3%B5%EB%B6%80-%EC%8B%9C%EC%9E%91-%EC%A0%84-%EA%B6%81%EA%B8%88%ED%95%9C-%EC%9A%A9%EC%96%B4%EB%93%A4-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@ss_g/%EC%9E%90%EB%B0%94-%EA%B3%B5%EB%B6%80-%EC%8B%9C%EC%9E%91-%EC%A0%84-%EA%B6%81%EA%B8%88%ED%95%9C-%EC%9A%A9%EC%96%B4%EB%93%A4-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Thu, 23 Nov 2023 07:04:32 GMT</pubDate>
            <description><![CDATA[<p>JDK : 프로그램을 실행하는 자바 플랫폼 구성요소.
JRE : JVM을 생성하는 디스크 상의 부분</p>
<p>JDK는 개발자들이 JVM과 JRE에 의해 실행되고 구동될 수 있는 자바 프로그램을 생성할 수 있게 해준다.</p>
<p>JDK와 JRE의 차이점은 JDK는 자바 기반 소프트웨어를 개발하기 위한 도구들로 이루어진 패키지인 반면, JRE는 자바 코드를 실행하기 위한 도구들로 구성된 패키지다.</p>
<br>
<br>
트랜잭션 : 기능 처리의 최소 단위로, 하나의 기능은 여러 가지 소작업들로 구성될 수 있다. 최소 단위란 것은 이 소작업들을 분리할 수 없으며, 전체를 하나로 본다는 개념이다. 트랜잭션은 소작업들이 모두 성공하거나 모두 실패해야 한다.]]></description>
        </item>
        <item>
            <title><![CDATA[라라벨-RESTful API]]></title>
            <link>https://velog.io/@ss_g/%EB%9D%BC%EB%9D%BC%EB%B2%A8-RESTful-API</link>
            <guid>https://velog.io/@ss_g/%EB%9D%BC%EB%9D%BC%EB%B2%A8-RESTful-API</guid>
            <pubDate>Fri, 19 May 2023 09:06:51 GMT</pubDate>
            <description><![CDATA[<h3 id="라라벨에서-api를-작성하는-방법에-대해-알아보는-내용">라라벨에서 API를 작성하는 방법에 대해 알아보는 내용.</h3>
<h4 id="restful-api란">RESTful API란?</h4>
<p>REST(Represntational State Transfer) API란 SPA(SIngle Page Application) 또는 기타 클라이언트에서 데이터를 요청하고 처리 및 가공할 수 있도록 서버에 리소스를 요청하는 방법 중 하나이며, 클라이언트는 REST API가 구현된 서버에 요청하면 JSON(Javascript Object Notation) 으로 처리하는 것이 일반적이다.
기존에는 XML도 사용했지만 이제는 JSON으로만 반환하는 경우가 많아 라라벨에서도 JSON을 반환하는 것을 주력으로 한다.
클라이언트의 요청에 따른 응답으로 JSON이라는 포맷을 빌려서 리소스를 묘사(Representational)하여 현재의 상태(State)를 클라이언트에 전달(Transfer)한다. 여기서 상태라함은 현재 리소스의 현황이라고 이해하는 것이 쉽다. 
REST API는 표준이 아닌 API 아키텍처 스타일이다. 따라서 꼭 지켜야 하는 의무는 아니지만 통상적으로 권장되는 스타일 가이드가 존재하는데 이러한 스타일 가이드를 잘 지켜서 ful하게 만드는 것이 RESTful API이다.</p>
<h4 id="uri">URI</h4>
<p>RESTful API에는 권장되는 몇 가지 URI 규칙이 존재한다. 이는 서비스마다 다를 수 있지만, URI는 해당 API가 RESTful한지 평가하는 가장 기본이 되는 요소이다.
<img src="https://velog.velcdn.com/images/ss_g/post/7e39577e-f0be-4532-b9c5-270d7b4f0876/image.png" alt="">
중첩된 리소스를 포함할 때는 GET /blogs/hello-world/posts/1고 같이 표현할 수 있고, blogs와 같이 복수형으로 쓰인 부분은 컬렉션(Collection) posts/{post}와 같이 표현하며, URL 파라미터로 쓰이는 부분은 Document라는 용어를 사용한다.</p>
<h4 id="http-메서드">HTTP 메서드</h4>
<p>HTTP 메서드를 REST API 스타일 가이드에 따라 사용하는 것은 URI 규칙과 마찬가지로 가장 중요시되는 규칙 중 하나라고 볼 수 있다. 대표적으로 자원을 요청하는 GET, 생성하는 POST, 수정하는 PUT/PATCH, 삭제하는 DELETE가 있다.</p>
<h4 id="http-header">HTTP HEADER</h4>
<p>헤더 설정은 필수는 아니지만 리소스의 위치를 표현하는 Content-Location, application/json과 같이 자원표현 포맷을 의미하는 Content-type, 그리고 너무 잦은 리소스 요청으로 Too many Re-quests와 함께 첨부하는 Retry-After가 있다.</p>
<h4 id="httml-상태코드">HTTML 상태코드</h4>
<p>RESTful 하지 않은 API의 경우 상태코드는 200을 던지는데 정작 JSON에 포함된 staues에는 다른 코드를 표현하는 경우가 있다.
200번대 상태코드는 요청에 대한 성공, 400번대는 서버 에러를 제외한 에러, 500번대는 서버 에러를 의미한다.
<img src="https://velog.velcdn.com/images/ss_g/post/59fbe7df-9133-4578-bbc1-2cbc531d145a/image.png" alt=""></p>
<h4 id="hateoas">HATEOAS</h4>
<p>HATEOAS(Hypermedia as the Engine of Application State)는 응답을 던질 때 프론트엔드에서 해당 자원과 관련된 정보도 알 수 있도록 각종 하이퍼미디어, 즉, Links를 첨부하자는 이야기다. </p>
<h4 id="버저닝">버저닝</h4>
<p>API 버저닝은 URL, Accept, Accept-version을 사용하는 버저닝 방법이 있다.
버저닝 같은 경우 일반적으로 웹 어플리케이션과는 별개로 API 프로젝트로 분리하여 깃 브랜치로 관리하는 것이 더 나은 방법이다.
<img src="https://velog.velcdn.com/images/ss_g/post/34156b5e-5ff0-451d-b1bf-7bd10c5ba0c1/image.png" alt=""></p>
<h4 id="라라벨-생텀">라라벨 생텀</h4>
<p>RESTful API는 무상태(Stateless)를 기본으로 간주한다. 상태가 없다는 뜻은 서버에 사용자가 상태를 유지하기 위한 세션과 데이터가 없다는 뜻이고, 클라이언트에서는 세션 쿠기가 아니라 API토큰을 가지고 있다는 뜻이다. API 토큰을 사용하면 세션과 쿠키를 기반으로 관리되는 것이 아니므로 클라이언트가 꼭 웹 브라우저가 아니더라도 사용자의 인증을 처리할 수 있다.
라라벨 생텀은 가벼운 API 토큰 기반 인증을 제공하여, 사용자가 스스로 API 토큰을 만들고 관리할 수 있도록 처리할 수 있다.
설치법으로는 Laravel 10.x 프로젝트라면 기본적으로 설치가 포함되어 있다. 설치되어 있지 않다면 conposer를 통해 설치할 수 있다.</p>
<pre><code>$ composer require laravel/sanctum</code></pre><h4 id="jwtjson-web-token인증">JWT(Json Web Token)인증</h4>
<p>JWT는 라라벨 생텀처럼 토큰을 사용하고 RESTful API와 같은 무상태 환경에서 사용되며, 헤더 또한 Authorization을 사용하는데 PAT(Personal Access Token)인 라라벨 생텀의 토큰과는 다른 점이 있다.
JWT를 사용할 때는 personal_access_tokens 같은 별도의 테이블이 존재하지 않는다. 즉, 서버에 저장하는 않는다. 
JWT는 토큰에서 정보를 자체적으로 가지고 있는 자기포함(Self-Contained)라는 특성을 가지고 있다. 토큰이 자체적으로 정보를 가지고 있다는 것은 저장하고 있는 정보가 많으면 토큰이 커질 수도 있다는 것을 의미하고, 서버의 부담을 줄여주는 것과 동시에 토큰에서 자체적인 보안 요소를 탑재하고 있음을 의미한다. JWT의 구조는 Header, Payload, Signature로 구성된다. 
Header에는 JWT에서 사용할 타입과 해시 알고리즘의 종류가 담겨있다.
Payload는 서버에서 첨부한 사용자의 정보와 데이터가 담겨있다. 즉, 데이터 자체는 암호화되거나 보호되지 않고 외부에 노출되어 있다.
Siganature에는 Header, Payload를 Base64 URL-safe Encode한 이후 Header에 명시된 해시함수를 적용하고 Secret Key로 서명한 전자서명이 담겨있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[라라벨]]></title>
            <link>https://velog.io/@ss_g/%EB%9D%BC%EB%9D%BC%EB%B2%A8</link>
            <guid>https://velog.io/@ss_g/%EB%9D%BC%EB%9D%BC%EB%B2%A8</guid>
            <pubDate>Fri, 19 May 2023 08:18:04 GMT</pubDate>
            <description><![CDATA[<h4 id="모델">모델</h4>
<p>사용자에게 나타내고자 하는 데이터로서, 코드상으로는 하나의 데이터베이스 테이블에 대해 클래스로 매핑한 것을 의미한다.</p>
<h4 id="모델-팩토리">모델 팩토리</h4>
<p>라라벨에서는 모델을 사용해 더미 데이터를 생성하는 모델 팩토리와 이것으로 생성된 더미 데이터를 데이터베이스에 심는 시딩기능을 제공한다.
모델 팩토리는 데이터를 생성해주고 시더는 생성된 데이터를 가지고 데이터베이스에 심는다. 모델 팩토리를 사용하면 모델 생성시 더미 데이터가 채워진 상태로 생성할 수도 있는데, 실질적으로 작성할 코드는 더미 데이터가 어떻게 채워질지를 정의하는 것이라고 볼 수 있다. 이렇게 정의한 모델 팩토리는 일반적으로 시더에서 호출된다.</p>
<h4 id="시딩">시딩</h4>
<p>시더를 만들기 위해서는 다음의 명령어를 사용한다.</p>
<pre><code>$ php artisan make:seeder UserSeeder</code></pre><h4 id="엘로퀀드-orm">엘로퀀드 ORM</h4>
<p>엘로퀀트는 모델을 통해 사용할 수 있고, 일부 추가된 메서드가 있는 것을 제외하곤 쿼리빌더 또한 가지고 있어서 쿼리빌더도 사용할 수 있다. 엘로퀀트는 모델을 통회 조회하므로 엘로퀀트 컬렉션의 각 요소는 모델이다.</p>
<h4 id="블레이드-템플릿">블레이드 템플릿</h4>
<p>블레이드 템플릿의 기본적인 내용들과 자주 사용되는 디렉티브인 @yield, @section, @show, @parent 등이 있다. 블레이드 템플릿은 다른 템플릿들처럼 레이아웃을 별도로 구성하는 것이 가능하고, 그러한 레이아웃을 다른 템플릿이 상속받아서 구성할 수 있다. 이러한 레이아웃을 사용하게 되면 자연스럽게 코드의 중복이 제거됨으로 유지보수하기 좋다.
@extend 는 자식템플릿에서 레이아웃을 지정할 때 사용한다.
@yield 는 자식에서 섹션을 지정하여 내용을 채워 넣어주기 위해 사용한다.
@show 는 자식에서 @section~@endsection으로 지정하지 않고도 렌더링된다.</p>
<h4 id="라우팅--컨트롤러">라우팅 &amp; 컨트롤러</h4>
<p>라우팅은 프론트 컨트롤러를 지나 라우터와 미들웨어를 거쳐 컨트롤러에 도달하도록 만들어준다. 컨트롤러는 어플리케이션의 주요 로직이 담겨있다. 즉 라우팅은 사용자가 입력한 URL과 그에 해당하는 컨트롤러를 매핑하는 일이라고 볼 수 있다.
라우팅을 위한 라우트들은 routes 디렉터리에 있다.</p>
<h4 id="미들웨어">미들웨어</h4>
<p>로그인으로 예를 들었을때 게시글을 작성하는 페이지에서 User가 로그인해야만 로직을 수행하고, 그렇지 않으면 로그인 페이지로 리다이렉트시키고 싶은 경우 미들웨어를 사용하게 되면 간단하게 이런 반복적인 작업을 분리하여 컨트롤러에 요청이 도달하기 전에 처리할 수 있다.
<img src="https://velog.velcdn.com/images/ss_g/post/b916c224-9053-4810-8176-f4b23dccbccd/image.png" alt=""></p>
<h4 id="oauth2">OAuth2</h4>
<p>OAuth2는 JWT처럼 토큰을 기반으로 움직이지만 둘은 상당히 다르다. JWT는 토큰에 자체적으로 정보를 가지고 있는 반면 OAuth2는 그 자체로는 아무런 정보도 가지고 있지 않다. 다음은 OAuth2 인증 절차이다.</p>
<ol>
<li>로그인 페이지에서 특정 사이트로 로그인하기 클릭.</li>
<li>특정 사이트에 이미 로그인이 되어 있는 경우, 인증 버튼 누르기, 로그인이 안된 경우 로그인 먼저 진행</li>
<li>인증이 완료되고 나면 다시 어플리케이션으로 돌아온 뒤 로그인 완료
<img src="https://velog.velcdn.com/images/ss_g/post/29c0fdb4-35cd-4c92-a499-1ad00dec6622/image.png" alt=""></li>
</ol>
<p>OAuth2의 인증방식으로는 Code Grant, Password Credentials, Client Credential, Implicit이 있다. 주로 많이 사용되는 방식은 Code Grant이다.
Code Grant 방식에는 Code, Access Token, Refresh Token, Explire, Authentication, Authorization등의 개념이 있다.</p>
<h4 id="큐">큐</h4>
<p>라라벨의 큐는 데이터베이 큐를 포함한 Redis, Amazon SQS 같은 서비스를 사용함에 있어서도 일관된API를 제공하므로 백그라운드에서 어떠한 큐 서비스를 사용하는지도 코드에 있어서는 크게 문제되지 않는다.
큐는 Job, Batch 등 관련된 내용이 상당히 많다. </p>
<h4 id="큐-워커">큐 워커</h4>
<p>큐는 기본적으로 별도의 프로세스에서 동작하기 때문에 큐 커넥션 드라이버에서 지정한 큐 서비스에 기록된 작업들을 가져와서 처리하는 프로세스가 별도로 필요한게 라라벨에서는 큐 워커가 내장되어 있다.</p>
<pre><code>$ php artisan Queue:work</code></pre><p>queue:work는 부팅된 어플리케이션의 상태를 메모리에 저장하므로 코드가 업데이트된 경우 상태를 즉각적으로 반영할 수 없다. 그래서 다시 반영하려면 큐 워커를 다시 시작해야 하는데, 이떄 queue:listen을 사용할 수도 있다.
기본 큐 대기열은 queue.connections.database,queue 설정에 따라 default인데, 이메일을 보내는 큐를 emails 라는 이름을 가진 대기열에 작업 배치할 것이라고 가정했을때 다음과 같이 사용할 수 있다.</p>
<pre><code>vagrant@homestead:~/code$ php artisan queue:listen --queue=emails, default</code></pre><p>큐 워커를 한 개만 쓰면 100개의 알림을 보내는 데에도 많은 시간이 소요되기 때문에 큐 워커를 여러 개 띄워서 병렬로 처리하는 것도 가능하다. 큐 워커 프로세스를 다중으로 띄우면 알아서 큐 대기열에 있는 큐들을 분산하여 처리할 수 있어서 메일, 알림, 이벤트 리스너를 빠르게 처리해서 사용자에게 알릴 수 있다.</p>
<h4 id="라라벨-호라이즌">라라벨 호라이즌</h4>
<p>라라벨 호라이즌은 큐를 Redis를 기반으로 사용할때 볼 수 있는 큐를 위한 모니터링 대시보드이며 큐 처리량과 실패한 큐 등을 볼 수 있다. </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[라라벨 - 아키텍처]]></title>
            <link>https://velog.io/@ss_g/%EB%9D%BC%EB%9D%BC%EB%B2%A8-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98</link>
            <guid>https://velog.io/@ss_g/%EB%9D%BC%EB%9D%BC%EB%B2%A8-%EC%95%84%ED%82%A4%ED%85%8D%EC%B2%98</guid>
            <pubDate>Fri, 19 May 2023 06:15:43 GMT</pubDate>
            <description><![CDATA[<h3 id="아키텍처">아키텍처</h3>
<h4 id="21-mvcmodel-view-controller">2.1 MVC(Model, View, Controller)</h4>
<p>라라벨은 기본적으로 MVC로 구성되어있다. </p>
<p>MVC 구조의 동작흐름
<img src="https://velog.velcdn.com/images/ss_g/post/ccd84ac8-645c-48ed-9aa5-32a4fa5e2eac/image.png" alt=""></p>
<h4 id="211-모델">2.1.1 모델</h4>
<p>모델(Model)은 사용자에게 보여줄 데이터를 의미. 데이터는 일반적으로 데이터베이스에 담겨있다.
라라벨 프레임워크 내부에서는 데이터베이스 테이블에 대해 하나의 클래스로 표현하고 각 컬럼또한 프로퍼티로 매핑되어있다. 모델에 있는 프로퍼티를 조작하고 데이터베이스와 관련된 메서드를 호출해서 데이터를 동기화하는 것으로 데이터베이스의 내용이 변하도록 할 수 있다.</p>
<p>라라벨에서는 엘로퀀트(Eloquent)라는 이름을 가진 ORM(Object Relational Mapping)을 사용한다면 SQL을 하드코드하지 않더라도 간단하게 데이터베이스 테이블에 접근하여 내용을 추가하거나 수정하고 조회할 수 있게 된다. 데이터 바인딩과 같은 부분은 라라벨이 알아서 처리한다.</p>
<pre><code>$pdo = new PDO(...);

$sth = $pdo-&gt;prepare(&quot;SELECT * FROM users&quot;);

if($sth-&gt;execute()){
    users = [];

    while ($user = $sth-&gt;fetchObject()){
        array_push($users, $user);
    }
}</code></pre><p>라라벨을 사용하지 않고 PHP 내장 클래스중 하나인 PDO(PHP Data Object)레이어를 통해 쿼리를 준비한 다음, 실행하고 결과를 하나씩 가져와 배열에 넣는다. 쿼리를 준비하는 과정에는 SQL Injection 공격 방지를 위한 문자열 처리도 포함된다. PDO는 PHP에서 데이터베이스의 종류와 상관없이 동일한 인터페이스로 데이터베이스를 조작할 수 있는 레이어이며 모던 PHP에서 데이터베이스에 연결하기 위한 기본 개념중 하나다. 
하지만 엘로퀀트 ORM을 사용하여 조회하면 아래와 같이 간결하게 처리될 수 있다.</p>
<pre><code>$users = User::all();</code></pre><p>User 모델에서 all()메서드를 마치 정적 메서드를 호출하는 것처럼 사용한 것을 볼 수 있는데, PHP의 언어 기능 중 하나인 매직 메서드에서 _callStatic()을 참조하면 확인할 수 있다.</p>
<h4 id="212-뷰">2.1.2 뷰</h4>
<p>뷰(View)는 사용자 인터페이스(UI)를 통해 HTTP요청을 다른 로직에 전달하거나, 컨트롤러에서 반환되어 사용자에게 응답한다. 응답으로 반환된 뷰는 렌더링되어서 사용자에게 보여지는데, 라라벨에서는 블레이드(Blade)라는 전용 템플릿을 사용한다. 
블레이드 템플릿이 가지는 주요 기능 중 하나는 레이아웃 템플릿을 상속하거나 컴포넌트와 슬롯 등의 개념을 사용하여 마크업을 구성할 수 있다는 것이다. </p>
<h4 id="213-컨트롤러">2.1.3 컨트롤러</h4>
<p>컨트롤러(Controller)에는 어플리케이션의 주요 로직이 담겨있다, 컨트롤러가 아닌 레이어드 아키텍처에 따라 서비스 레이어에 비즈니스 로직을 두는 경우가 더 많기는 하지만, 계층을 나누지 않는다면 컨트롤러에서 처리하게 된다. 컨트롤러는 사용자가 요청하면 라우터와 미들웨어를 거쳐 도달하게 되는데, 주로 모델을 생성하거나 갱신하게 되고 이후 뷰를 응답으로 반환하거나 다른 페이지로 리다이렉트, XML, JSON 등의 포맷으로 변환된 데이터를 반환하게 된다. </p>
<p>사용자가 HTTP요청을 하고 라우터를 통해 컨트롤러에 도달하는 과정
<img src="https://velog.velcdn.com/images/ss_g/post/033c722b-59ed-4015-8e20-54da67b808fa/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/ss_g/post/df0fec59-e59f-4f7e-8fe5-34f95d19fdb1/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/ss_g/post/7dfb5b26-3327-489d-a6aa-3d5c5d58f919/image.png" alt=""></p>
<h4 id="22-컨테이너">2.2 컨테이너</h4>
<p>라라벨의 서비스 컨테이너는 IoC(Inversion of Control) 컨테이너, 어플레케이션 컨테이너 등 여러 이름을 가지고 있다. 컨테이너에 대해 알아보려면 먼저 의존성 주입에 대한 이해가 선행되어야 한다.</p>
<h4 id="221-의존성-주입">2.2.1 의존성 주입</h4>
<p>의존성 주입은 생성자, 메서드, 세터에 파라미터를 통해 외부에서 구체 클래스 또는 인터페이스를 충족하는 객체를 넣는 것이다. 의존성이란 어떤 기능이 제대로 동작하기 위해서는 다른 기능에 의존하는 것이 필요함을 말하는데, 의존성을 외부에서 주입하지 않고 비즈니스 로직 내부에서 객체를 직접 생성하면 클래스간 결합도가 크게 증가하여 유연성이 떨어지게 된다.</p>
<h4 id="222-서비스-컨테이너">2.2.2 서비스 컨테이너</h4>
<p>라라벨의 서비스 컨테이너는 IoC 컨테이너로서 의존성을 외부에서 주입해서 해결해준다, IoC는 비즈니스 로직에서 의존성을 직접 제어하지 않고 컨테이너에 의해 외부로부터 주입하는 것으로 제어의 주체를 로직이 아닌 외부의 영역에서 하도록 만드는 것이다. 따라서 컨테이너는 객체의 생성 방법을 알고 있으며, 이를 대신해주고 필요한 곳에 주입해준다.
비즈니스 로직에서 어떠한 객체를 컨테이너에 요구하면 객체를 적절하게 생성해서 넘겨주게 되는데, 이를 의존성 해결이라 한다. 
라라벨에서는 컨테이너를 통해 이를 명시적으로 객체를 생성해서 주입하지 않고도 서비스 컨테이너가 컨트롤러 등에서 타입힌트만 해주면 자동으로 의존성이 해결된다. 이를 오토 와이어링(Auto Wiring) 기능이라고 한다.</p>
<h4 id="23-서비스-프로바이더">2.3 서비스 프로바이더</h4>
<p>서비스 프로바이더는 라라벨 어플리케이션에 기능을 제공하기 위해 사용된다. 어플리케이션을 시작하기 위한 부트스트래핑이 진행되면서 발생하는 중요한 과정 중 하나는 서비스 프로바이더를 등록하고 부팅시키는 일이다.
기본적으로 라라벨 프레임워크 템플릿이 가지고 있는 서비스 프로바이더들음 app/Providers에 존재하며 AppSerciveProcider, RouteServiceProvider 등이 위치하고 있다.</p>
<h4 id="231-부트스트래핑">2.3.1 부트스트래핑</h4>
<p>서비스 프로바이더가 등록되고 부팅되는 부트스트래핑 과정</p>
<p><img src="https://velog.velcdn.com/images/ss_g/post/71075452-b83b-4813-8052-91bd7c1c15f4/image.png" alt=""></p>
<h4 id="232-지연된-서비스-프로바이더">2.3.2. 지연된 서비스 프로바이더</h4>
<p>지연된 서비스 프로바이더란 단순하게 서비스 프로바이더에 바인딩만을 등록하는 단순한 케이스의 경우, 의존성 해결을 위해 사용될 때까지 등록을 지연할 수 있는 프로바이더를 말한다. 어플리케이션을 부트스트래핑할 때 모든 요청에 대해 서비스 프로바이더를 로드해놓는 것이 아니라 해당 의존성 해결이 필요한 경우에만 서비스 프로바이더를 로드하고 등록하도록 할 수 있다.</p>
<h4 id="24-파사드">2.4 파사드</h4>
<p>라라벨의 파사드(Facades) 기능은 세션과 큐와 같은 라라벨의 기능들을 사용하기 위해 거쳐야하는 복잡한 절차를 간편하게 사용할 수 있도록 정적 메서드의 형태로 제공하는 라라벨의 기능 중 하나다. 
파사드는 이름이 길고 기억하기 어려우며 사용하기에도 번거로운 구체 클래스 또는 인터페이스에 대해 정적 프록시 역할을 한다.
<img src="https://velog.velcdn.com/images/ss_g/post/47523dbb-f4f4-4cac-a133-8b108d854975/image.png" alt=""></p>
<h4 id="241-실시간-파사드">2.4.1 실시간 파사드</h4>
<p>라라벨에는 실시간 파사드라는 기능이 있다. 실시간 파사드는 직접 파사드 클래스를 상속받아서 만들지 않더라도 그저 네임스페이스에 Facades만 붙이면 사용할 수 있는 기능을 제공한다.</p>
<pre><code>use Facades\App\Contracts\Publisher;

class Podcast extends Model
{
    public function publish()
    {
        Publisher::publish($this);
    }
}</code></pre><p>이처럼 실시간 파사드를 사용하면 Illuminate\Support\Facades\Facade를 상속받아 파사드 클래스를 만들지 않더라도 간편하게 사용할 수 있다.</p>
<h4 id="25-헬퍼함수">2.5 헬퍼함수</h4>
<p>헬퍼함수는 특별한 것이 아니라 일반적인 함수이다. 단지, 라라벨에서 이 함수들의 이름을 지칭하는 것이 헬퍼이고, 귀찮은 작업들을 간단하게 할 수 있도록 도와준다. 라라벨에는 많은 헬퍼 함수가 존재하고 있다. 공식문서를 참고하면 확인이 가능하다.</p>
<h4 id="26-laravel-contracts">2.6 Laravel Contracts</h4>
<p>Contracts는 라라벨 프레임워크에서 단순히 인터페이스를 의미한다. 서비스 컨테이너의 바인딩에 따라 인터페이스를 컨테이너에 요청하면 구체 클래스를 던진다. 이러한 인터페이스를 타입힌트에 사용하여 의존성을 주입함으로써 사용하는 것이 가능하다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[DOMContentLoaded와  window.onload]]></title>
            <link>https://velog.io/@ss_g/DOMContentLoaded%EC%99%80-window.onload</link>
            <guid>https://velog.io/@ss_g/DOMContentLoaded%EC%99%80-window.onload</guid>
            <pubDate>Tue, 18 Apr 2023 09:16:33 GMT</pubDate>
            <description><![CDATA[<h2 id="html보다-script가-위에-있을-때-정상적으로-동작하지-않는-문제가-발생">html보다 script가 위에 있을 때 정상적으로 동작하지 않는 문제가 발생</h2>
<p>평소에 작성하던 대로 html 위에 script를 선언해서 함수나 eventHandler를 사용하고 있었다. 하지만 함수는 사용이 되나 eventHandler가 정상적으로 동작하지 않았고 이유를 찾아보던 중 html 요소들이 로드되기 전에 실행이 될 가능성이 있기 때문이라는 것을 알게되어 이 문제를 해결하기 위한 방법을 찾아보게 되었다.</p>
<ol>
<li><p>스크립트를 html 요소 맨 아래(body태그의 맨 아래)에 배치한다.</p>
<p> --&gt; 이 방법으로는 바로 해결이 되었다.</p>
</li>
<li><p>DOMContentLoaded 이벤트 사용
 --&gt; 이 방법으로는 해결되지 않았다. 그래서 DOMContentLoaded와 비슷한 것을 찾아보게 되었고 window.onload라는 것이 있다는 것을 알게 되었다.</p>
</li>
</ol>
<h3 id="domcontentloaded">DOMContentLoaded</h3>
<ul>
<li>웹페이지가 로드되고 파싱된 후에 발생하는 이벤트. HTML 문서의 모든 요소가 파싱 되었지만, 이미지나 스타일시트등 외부리소스는 비동기적으로 로드해서 완전히 로드되지 않았을 때 발생한다. HTML 문서가 준비되면 바로 발생하는 이벤트이다. 즉 window.onload보다 빨리 로드되고 렌더링될 수 있다.</li>
</ul>
<h3 id="windowonload">window.onload</h3>
<ul>
<li>웹페이지의 모든 자원이 로드 되어야만 발생한다. 즉, 페이지의 모든 요소가 다운로드되고 렌더링 되어야 이벤트가 발생한다. 그래서 window.onload가 실행되기까지는 상대적으로 오래 걸릴 수 있다.</li>
</ul>
<h3 id="결론">결론</h3>
<ul>
<li>페이지 초기화에 필요한 스크립트는 DOMContentLoaded 에서 실행하고, 추가적인 작업이나 리소스를 로드해야 할 경우에는 window.onload 에서 실행한다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[JS onKeypress, onKeyup, onKeydown 이벤트]]></title>
            <link>https://velog.io/@ss_g/JS-onKeypress-onKeyup-onKeydown-%EC%9D%B4%EB%B2%A4%ED%8A%B8</link>
            <guid>https://velog.io/@ss_g/JS-onKeypress-onKeyup-onKeydown-%EC%9D%B4%EB%B2%A4%ED%8A%B8</guid>
            <pubDate>Tue, 11 Apr 2023 09:19:41 GMT</pubDate>
            <description><![CDATA[<p>onKey 이벤트 : 폼 관련 태그들만 사용함.(포커스를 가지는 태그에만 적용 가능)</p>
<h3 id="onkeydown">onKeydown</h3>
<ul>
<li>KeyCode 값 </li>
<li>키보드의 키를 눌렀을 때 발생</li>
<li>문자, 숫자, Ctrl, Alt, Shift, F1~F12, Scroll Lock, Pause, Enter 등등 인식 가능</li>
<li>한/영, Print Screen 인식 불가능<h3 id="onkeyup">onKeyup</h3>
</li>
<li>keyCode 값</li>
<li>키보드의 키를 눌렀다가 뗄 때 발생</li>
<li>문자, 숫자, Ctrl, Alt, Shift, F1~F12, Scroll Lock, Pause, Enter 등등 인식 가능</li>
<li>한/영, Print Screen 인식 불가능</li>
</ul>
<h3 id="onkeypress">onKeyPress</h3>
<ul>
<li>ASCII 값</li>
<li>키보드의 키를 눌렀을 때 발생</li>
<li>ASCII 값이기 때문에 shift, ctrl, backspace, tab, 한/영키 등등 인식 불가</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[SQL CTE와 WITH RECURSIVE]]></title>
            <link>https://velog.io/@ss_g/SQL-CTE%EC%99%80-WITH-RECURSIVE</link>
            <guid>https://velog.io/@ss_g/SQL-CTE%EC%99%80-WITH-RECURSIVE</guid>
            <pubDate>Tue, 11 Apr 2023 09:05:00 GMT</pubDate>
            <description><![CDATA[<h2 id="ctecommon-table-expressions">CTE(Common Table Expressions)</h2>
<p>SQL 쿼리에서 임시적으로 사용할 수 있는 이름을 가진 쿼리 결과 세트 즉, CTE는 다른 쿼리에서 참조할 수 있는 일시적인 테이블이다.</p>
<p>CTE는 WITH 키워드를 사용하여 정의된다. WITH 절 다음에는 CTE 이름과 CTE에 사용될 SELECT 문이 온다. SELECT 문에서 CTE 이름을 사용해 CTE의 결과를 참조할 수 있다.</p>
<p>CTE와 비교할 대상으로 VIEW가 있다. VIEW 는 만들기 위해서는 권한이 필요하고 사전에 정의를 해야한다. 하지만 CTE는 권한이 필요 없고 하나의 쿼리문이 끝날 때까지만 지속되는 일회성 테이블이다.</p>
<p>CTE에는 재귀적 CTE와 비재귀적 CTE가 있다.</p>
<h3 id="재귀적-cte">재귀적 CTE</h3>
<p>최초 CTE가 반복적으로 실행되어, 전체 결과 집합을 얻을 때까지 데이터의 하위 집합을 반환하는 CTE이다.</p>
<p>재귀적 CTE를 참조하는 쿼리를 재귀 쿼리라고 하며,
재귀 쿼리의 일반적인 용도는 계층적 데이터를 반환하는 것이다.</p>
<h3 id="재귀적-cte의-구조">재귀적 CTE의 구조</h3>
<p>T-SQL의 재귀적 CTE 구조는 다른 프로그래밍 언어의 재귀 루틴과 아주 흡사하지만.
다른 언어의 재귀 루틴은 스칼라 값을 반환하는 것이 비해, 재귀적 CTE는 여러 행을 반환할 수 있다.</p>
<p>재귀적 CTE는 다음 세 가지 요소로 구성된다.</p>
<p>1) 루틴의 호출</p>
<p>재귀적 CTE의 첫 번째 호출은 UNION ALL, UNION, EXCEPT 또는 INTERSECT 연산자로 조인된
하나 이상의 CTE_query_definitions로 구성된다. </p>
<p>이러한 쿼리 정의는 CTE 구조의 기본 결과 집합을 형성하기 때문에 앵커(Anchor) 멤버(AM)라고 한다.</p>
<p>CTE_query_definitions는 CTE 자체를 참조하지 않는 경우 앵커 멤버로 간주된다.</p>
<p>모든 앵커 멤버 쿼리 정의를 첫 번째 재귀 멤버 정의 앞에 배치하고,
UNION ALL 연산자를 사용하여 마지막 앵커 멤버를 첫 번째 재귀 멤버와 조인해야 한다. </p>
<p>2) 루틴의 재귀 호출</p>
<p>재귀 호출에는 CTE 자체를 참조하는 UNION ALL 연산자로 JOIN(조인)된 하나 이상의 CTE_query_definitions가 포함된다.
(JOIN에 대해선 차후 자세히 별도의 문서로 작성하겠다)</p>
<p>이러한 쿼리 정의를 재귀(Recursive) 멤버(RM)라고 한다.</p>
<p>3) 종료 확인</p>
<p>종료 확인은 암시적으로 수행되며, 이전 호출에서 반환되는 행이 없을 때 재귀가 중지된다.</p>
<h3 id="cte-장점-">CTE 장점 :</h3>
<ul>
<li>쿼리를 더욱 가독성있게 만들 수 있다.</li>
<li>하나의 복잡한 쿼리를 여러 개의 작은 쿼리로 분할할 수 있다.</li>
<li>같은 CTE를 여러 번 참조하더라도 데이터베이스가 해당 CTE를 한 번만 계산하므로 성능상의 이점이 있을 수 있다.</li>
</ul>
<BR>


<h2 id="with-recursive">WITH RECURSIVE</h2>
<p>CTE에서 재귀적으로 쿼리를 실행할 수 있는 구문 중 하나.</p>
<pre><code>WITH RECURSIVE cte_name (column_list) AS (
  -- non-recursive term
  SELECT ...
  UNION
  -- recursive term
  SELECT ...
  FROM cte_name
  WHERE ...
)
SELECT ...
FROM cte_name;</code></pre><p>WITH RECURSIVE 는 두 개의 부분으로 구성된다. 첫 번째 부분은 재귀적으로 실행되지 않는 초기 쿼리 부분(non-recursive term), 두 번째 부분은 재귀적으로 실행되는 쿼리 부분(recursive term).</p>
<p>recursive term은 다음과 같은 구조를 가진다.</p>
<pre><code>SELECT ...
FROM cte_name
WHERE ...</code></pre><p>recursive term 에서는 CTE의 이름을 참조하고 WHERE 절에서는 재귀 종료 조건을 정의한다.</p>
<p>위 코드에서 CTE의 이름은 cte_name으로 정의했고, column_list는 CTE에서 반환할 열의 이름과 데이터 유형을 정의한다. SELECT 문에서 반환하는 열의 이름과 데이터 유형이 column_list와 일치해야 한다.</p>
<p>WITH RECURSIVE를 사용하면 재귀적으로 쿼리를 실행할 수 있으며, 재귀적으로 실행되는 쿼리에서는 CTE의 이름을 참조한다. 재귀적으로 실행되는 쿼리는 non-recursive term에서 반환한 결과와 recursive term에서 반환한 결과를 결합한 결과를 반환한다.</p>
]]></description>
        </item>
    </channel>
</rss>