<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>h_ani99.log</title>
        <link>https://velog.io/</link>
        <description>매일 성장하는 개발자</description>
        <lastBuildDate>Tue, 10 Feb 2026 12:58:51 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>h_ani99.log</title>
            <url>https://velog.velcdn.com/images/h_ani99/profile/9f1e4375-d8ea-4d46-8e3f-7a8d0774a4e6/social_profile.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. h_ani99.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/h_ani99" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[[HTTP 웹 기본 지식 #2] URI]]></title>
            <link>https://velog.io/@h_ani99/HTTP-%EC%9B%B9-%EA%B8%B0%EB%B3%B8-%EC%A7%80%EC%8B%9D-2-URI</link>
            <guid>https://velog.io/@h_ani99/HTTP-%EC%9B%B9-%EA%B8%B0%EB%B3%B8-%EC%A7%80%EC%8B%9D-2-URI</guid>
            <pubDate>Tue, 10 Feb 2026 12:58:51 GMT</pubDate>
            <description><![CDATA[<p>URI와 웹 브라우저 요청 흐름에 대해서 알아보고 HTTP의 기본적인 개념들을 살펴보도록 하자.</p>
<h3 id="1-uri-uniform-resource-identifier">1. URI (Uniform Resource Identifier)</h3>
<ul>
<li><strong>U</strong>niform : 리소스 식별하는 통일된 방식</li>
<li><strong>R</strong>esource : 자원,URI로 식별할 수 있는 모든 것(제한 없음)</li>
<li><strong>I</strong>dentifier : 다른 항목과 구분하는데 필요한 정보</li>
</ul>
<blockquote>
<p><strong>❓리소스</strong>
리소스란 URI로 식별할 수 있는 모든 것을 말한다.
예를 들어 웹브라우저에 있는 html이나 파일 같은 것뿐만 아니라 실시간 교통정보 등
우리가 구분할 수 있는 모든 것이 리소스라고 이해하면 된다.</p>
</blockquote>
<p><strong>통합 자원 식별자(URI)</strong>는 인터넷에 있는 자원을 나타내는 유일한 주소이다.
URI는 로케이터(<strong>L</strong>ocator),이름(<strong>N</strong>ame)또는 둘다 추가로 분류될 수 있다. ➡️ URL 과 URN
<img src="https://velog.velcdn.com/images/h_ani99/post/56d7b7d9-375a-472d-8bef-b639b6d9a323/image.png" alt="">
URI 라는 가장 큰 개념이 URL과 URN을 포함한다.</p>
<ul>
<li><p>URL(Uniform Resource Locator)</p>
<ul>
<li>네트워크 상에서 자원이 어디 있는지를 알려주기 위한 규약</li>
<li>리소스가 있는 위치를 지정</li>
<li>쉽게 말해, 웹 페이지를 찾기 위한 주소</li>
</ul>
</li>
<li><p>URN(Uniform Resource Name)</p>
<ul>
<li>urn:scheme 을 사용하는 URI를 위한 역사적인 이름이다.</li>
<li>URN은 영속적이고, 위치에 독립적인 자원을 위한 지시자로 사용하기 위해 정의되었다.</li>
<li>리소스에 이름을 부여</li>
<li>리소스가 이름에 매핑되어 결과가 나오게 되어야 하는데 이름을 부여하면 거의 찾기가 힘들다.</li>
<li>URN 이름만으로 실제 리소스를 찾을 수 있는 방법이 보편화 되지 않음</li>
<li>그래서 거의 URL만 사용한다.</li>
</ul>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/h_ani99/post/c871f7c8-feee-4f15-8541-2cf1732ca5bd/image.png" alt=""></p>
<p>URL과 URN의 형태는 위의 이미지와 같다.</p>
<h4 id="☝️-url-전체-문법">☝️ URL 전체 문법</h4>
<ul>
<li>scheme://[userinfo@]host[:port][/path][?query][#fragment]</li>
<li><a href="https://www.google.com:443/search?q=hello&amp;hl=ko">https://www.google.com:443/search?q=hello&amp;hl=ko</a></li>
</ul>
<ul>
<li>프로토콜(https)</li>
<li>호스트명(<a href="http://www.google.com">www.google.com</a>)</li>
<li>포트 번호(443)</li>
<li>path(/search) : 경로</li>
<li>쿼리 파라미터(q=hello&amp;hl=ko)</li>
</ul>
<h4 id="1️⃣-스키마">1️⃣ 스키마</h4>
<ul>
<li><strong>scheme:</strong>//[userinfo@]host[:port][/path][?query][#fragment]</li>
<li><strong>https:</strong>//<a href="http://www.google.com:443/search?q=hello&amp;hl=ko">www.google.com:443/search?q=hello&amp;hl=ko</a></li>
</ul>
<ul>
<li>주로 프로토콜 사용</li>
<li>프로토콜 : 어떤 방식으로 자원에 접근할 것인가 하는 클라이언트와 서버 간의 약속과 규칙(http,https)</li>
<li>http는 80포트, https는 443 포트를 주로 사용, 포트는 생략 가능</li>
<li>https는 http에 강력한 보안이 적용된 것(HTTP Secure)</li>
</ul>
<h4 id="2️⃣-userinfo">2️⃣ Userinfo</h4>
<ul>
<li>scheme://<strong>[userinfo@]</strong>host[:port][/path][?query][#fragment]</li>
<li><a href="https://www.google.com:443/search?q=hello&amp;hl=ko">https://www.google.com:443/search?q=hello&amp;hl=ko</a></li>
</ul>
<ul>
<li>URL에 사용자정보를 포함해서 인증해야 될 때 사용</li>
<li>거의 사용하지 않음</li>
</ul>
<h4 id="3️⃣-host">3️⃣ Host</h4>
<ul>
<li>scheme://[userinfo@]<strong>host</strong>[:port][/path][?query][#fragment]</li>
<li>https:// <strong><a href="http://www.google.com">www.google.com</a></strong>:443/search?q=hello&amp;hl=ko</li>
</ul>
<ul>
<li>호스트명</li>
<li>도메인명 또는 IP주소를 직접 사용가능하다.<h4 id="4️⃣-port">4️⃣ Port</h4>
</li>
<li>scheme://[userinfo@]host[:port][/path][?query][#fragment]</li>
<li><a href="https://www.google.com">https://www.google.com</a>: <strong>443</strong>/search?q=hello&amp;hl=ko</li>
</ul>
<ul>
<li>포트(PORT)</li>
<li>접속 포트</li>
<li>일반적으로 생략, 생략시 http는 80, https는 443</li>
</ul>
<h4 id="5️⃣-path">5️⃣ Path</h4>
<ul>
<li>scheme://[userinfo@]host[:port]<strong>[/path]</strong>[?query][#fragment]</li>
<li><a href="https://www.google.com:443">https://www.google.com:443</a> /<strong>search</strong>?q=hello&amp;hl=ko</li>
</ul>
<ul>
<li>리소스 경로(path)</li>
<li>보통 계층적 구조로 되어있음</li>
<li>Ex<ul>
<li>/home/file1.jpg</li>
<li>/members</li>
<li>/members/100 (컬렉션에서 하위에 100번이라는 아이디를 가진 회원 조회)</li>
</ul>
</li>
</ul>
<h4 id="6️⃣-쿼리">6️⃣ 쿼리</h4>
<ul>
<li>scheme://[userinfo@]host[:port][/path]<strong>[?query]</strong>[#fragment]</li>
<li><a href="https://www.google.com:443/search">https://www.google.com:443/search</a>? <strong>q=hello&amp;hl=ko</strong></li>
</ul>
<ul>
<li>key = value 형태로 데이터가 들어간다.</li>
<li>? 로 구문이 시작하고 &amp;로 파라미터를 계속 추가할 수 있다.<ul>
<li>keyA=valueA&amp;keyB=valueB</li>
</ul>
</li>
<li>query parameter,query string등으로 불림, 웹서버에 제공하는 파라미터,문자 형태</li>
</ul>
<hr>
<p> 글에 포함된 모든 내용과 자료는 김영한님의 모든 개발자를 위한 HTTP 웹 기본 지식 강의를 듣고 정리했습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[HTTP 웹 기본 지식 #1] 인터넷 네트워크]]></title>
            <link>https://velog.io/@h_ani99/HTTP-%EC%9B%B9-%EA%B8%B0%EB%B3%B8-%EC%A7%80%EC%8B%9D-1-%EC%9D%B8%ED%84%B0%EB%84%B7-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC</link>
            <guid>https://velog.io/@h_ani99/HTTP-%EC%9B%B9-%EA%B8%B0%EB%B3%B8-%EC%A7%80%EC%8B%9D-1-%EC%9D%B8%ED%84%B0%EB%84%B7-%EB%84%A4%ED%8A%B8%EC%9B%8C%ED%81%AC</guid>
            <pubDate>Thu, 05 Feb 2026 08:10:38 GMT</pubDate>
            <description><![CDATA[<p>인터넷이 어떤 식으로 인터넷 상에서 통신이 일어나는지 보기 위해
<strong>IP , TCP , UDP , PORT , DNS</strong> 에 대해서 알아보도록 하자</p>
<h3 id="0-개요---인터넷-통신">0. 개요 - 인터넷 통신</h3>
<p>인터넷 상에서 컴퓨터 둘은 어떻게 통신할까?
컴퓨터 두 대가 바로 옆에 붙어있다면 케이블을 연결해서 통신할 수 있을 것이다.
하지만 두 컴퓨터가 멀리 떨어져 있다면?
<img src="https://velog.velcdn.com/images/h_ani99/post/b6fc0814-efa5-4da0-965c-675a1863ee67/image.png" alt=""></p>
<p>두 컴퓨터가 통신하기 위해서는 케이블과 위성혹은 수많은 중간 노드라고 하는
이 서버들을 거쳐서 메세지가 안전하게 넘어가야 한다.
이런 복잡한 상황속에서 어떤 규칙으로 메세지가 안전하게 도착을 할 수 있을까?</p>
<h3 id="1-ip인터넷-프로토콜">1. IP(인터넷 프로토콜)</h3>
<p>복잡한 인터넷망에서 내 컴퓨터에서 다른 서버로 요청을 보내기 위해서는 IP 주소가 필요하다.</p>
<p><img src="https://velog.velcdn.com/images/h_ani99/post/4a1c939c-27a6-42e5-984a-82ae04159338/image.png" alt=""></p>
<p>예를 들어 클라이언트인 내 컴퓨터의 IP주소를 100.100.100.1이라고 하고
메세지를 보내야 되는 상대방의 컴퓨터인 서버의 IP주소를 200.200.200.2 라고 하자.</p>
<h4 id="인터넷-프로토콜-역할">인터넷 프로토콜 역할</h4>
<ul>
<li>지정한 IP 주소(IP Address)에 데이터 전달</li>
<li>패킷(Packet)이라는 통신 단위로 데이터 전달</li>
</ul>
<br/>

<p><strong>패킷</strong>
<img src="https://velog.velcdn.com/images/h_ani99/post/14fa79b7-6f36-4173-a935-811d6312a8a1/image.png" alt=""></p>
<p>패킷에 전송 데이터와 함께 출발지 IP,목적지 IP 등을 넣어 데이터를 전송한다.
(패킷의 의미는 데이터 덩어리,전송하는 데이터의 단위정도 라고 생각하면 된다.)</p>
<p><img src="https://velog.velcdn.com/images/h_ani99/post/44d77769-b2be-4c6c-b9f5-6e1ab8a1288e/image.png" alt=""></p>
<p>인터넷망은 IP프로토콜에 의해서 서버들이 규약을 따르고 있기 때문에
IP주소를 보고 출발지와 목적지를 이해를 할 수 있다.
결국 이 규약과 IP주소를 통해 우리가 원하는 목적지에 데이터를 정확히 전달할 수 있다.</p>
<h4 id="ip-프로토콜의-한계">IP 프로토콜의 한계</h4>
<ul>
<li><p>비연결성</p>
<ul>
<li>패킷을 받을 대상이 없거나 서비스 불능 상태여도 패킷을 전송한다.</li>
<li>ex) 내가 친구한테 메시지를 보내려고 하는데 친구 컴퓨터가 꺼져있는 경우 ➡️ 그래도 보냄</li>
</ul>
</li>
<li><p>비신뢰성</p>
<ul>
<li>중간에 패킷이 사라져도 어쩔 수 없다.</li>
<li>패킷이 순서대로 도착하지 않을 수도 있다.</li>
</ul>
</li>
<li><p>프로그램 구분</p>
<ul>
<li>같은 IP를 사용하는 서버에서 통신하는 애플리케이션이 둘 이상이면?</li>
</ul>
</li>
</ul>
<p>IP프로토콜을 통해서 출발지 주소와 목적지 주소는 확인할 수 있지만
이런 문제는 어떻게 해결할 수 있을까?</p>
<h3 id="2-tcp--udp">2. TCP / UDP</h3>
<p>IP프로토콜에서 발생했던 수많은 문제들을 TCP 프로토콜을 통해 해결할 수 있다.
<img src="https://velog.velcdn.com/images/h_ani99/post/16200e5f-0257-4b13-85fd-a1f9b7aa3376/image.png" alt="">
우리가 미국에 있는 친구한테 Hello,world!라는 메세지를 전송을 하고 싶다고 가정을 해보자.
처음으로 메세지를 생성하여 소켓 라이브러리를 통해 전달한다.
소켓 라이브러리를 통해 OS계층에 메세지를 넘기면 메세지 데이터가 포함된 TCP 정보를 생성한다.
또 TCP 정보 밖에다가 IP와 관련된 정보(위에서 말한 IP주소 등)를 추가하여 IP패킷을 생성한다.
<img src="https://velog.velcdn.com/images/h_ani99/post/0889a928-22dc-4879-bf68-4b6f18cccafb/image.png" alt=""></p>
<p>TCP 세그먼트(TCP 데이터)에는 우선 우리가 전송하려는 전송 데이터를 포함하고
출발지 PORT,목적지 PORT,전송 제어,순서,검증 정보 등이 들어간다.
이를 통해 IP만으로 해결이 안 됐던 순서 제어 문제들이 해결된다.</p>
<h4 id="tcp-특징">TCP 특징</h4>
<p>전송 제어 프로토콜 (Transmission Control Protocol)</p>
<ul>
<li>연결 지향 - TCP 3 way handshake(가상 연결)</li>
<li>데이터 전달 보증 (데이터 유실 여부를 알 수 있다.)</li>
<li>순서 보장</li>
<li>신뢰할 수 있는 프로토콜</li>
<li>현재는 대부분 TCP 사용</li>
</ul>
<h4 id="tcp-3-way-handshake">TCP 3 way handshake</h4>
<p><img src="https://velog.velcdn.com/images/h_ani99/post/8d38ea7a-2f0f-4916-bd70-9ab4d28910a6/image.png" alt="">
** SYN : 연결 요청 / ACK : 요청을 잘 받았다는 확인** </p>
<ol>
<li>클라이언트에서 서버로 요청을 보낼때 먼저 SYN(Synchronizer)이라는 요청 메세지를 보낸다.</li>
<li>서버에서 싱크를 받게되면 ACK(Acknowledge)라는 확인 메세지와 SYN를 보낸다.</li>
<li>클라이언트가 서버에서 보낸 메세지를 받게 되면 다시 서버에 ACK를 보낸다.</li>
<li>3번의 메시지를 주고 받으면서 연결이 안정적으로 성립된다.<br/>
➡️ 서버(상대방)가 꺼져있으면 SYN(요청)을 보내도 ACK(확인)가 돌아오지 않아 데이터 전송을 하지 않음.
(비연결성 해결)
➡️ 데이터를 보낼때마다 상대방은 데이터를 받으면 ACK(확인)를 돌려준다.(비신뢰성 해결)
➡️ 데이터를 보낼때 시퀀스를 함께 보내 데이터 순서를 보장한다.
(데이터 순서가 안맞으면 안맞는 부분부터 재전송)</li>
</ol>
<h4 id="udp-특징">UDP 특징</h4>
<p>사용자 데이터그램 프로토콜(User Datagram Protocol)</p>
<ul>
<li>하얀 도화지에 비유(기능이 거의 없음)</li>
<li>연결지향 - TCP 3 way handshake X</li>
<li>데이터 전달 보증 X</li>
<li>순서 보장 X</li>
<li>데이터 잔달 및 순서가 보장되지 않지만,단순하고 빠름</li>
<li>정리<ul>
<li>IP와 거의 같다. + PORT + 체크섬 정도만 추가</li>
<li>애플리케이션에서 추가 작업 필요</li>
</ul>
</li>
</ul>
<p><strong>체크섬</strong>: 데이터가 전송 중에 손상되었는지 확인하는 숫자값</p>
<h3 id="3-port">3. PORT</h3>
<h4 id="한번에-둘-이상-연결해야-하면">한번에 둘 이상 연결해야 하면?</h4>
<p>내가 컴퓨터로 게임도 하고 화상통화도 하고 웹 브라우저에서 유튜브를 틀게 되면
한번에 클라이언트 PC가 여러개의 서버와 통신해야 한다.
요청을 보내면 응답은 IP패킷들로 날아올텐데 IP패킷에는 목적지 주소가 있기 때문에
정확히 내 PC에 도착할 것이다.
하지만 각 응답들이 어떤 애플리케이션으로 가야하는지 어떻게 알 수 있을까?
<img src="https://velog.velcdn.com/images/h_ani99/post/fe57a3f5-cbfb-4218-b94d-ff652b87c468/image.png" alt="">
TCP / IP  패킷을 다시 한번 보자.
TCP 세그먼트 안에는 출발지 PORT와 목적지 PORT가 있다.
IP주소로 목적지를 찾게 되면 PORT번호로 우리는 정확한 애플리케이션을 찾을 수 있다.
쉽게 말하면 IP주소는 내가 사는 아파트 주소(XX아파트), PORT번호는 동,호수(101동 202호)이다.
<img src="https://velog.velcdn.com/images/h_ani99/post/8736f518-cf00-4bbf-8fc1-c9a05d101226/image.png" alt="">
이와 같이 같은 PC내에서 서로 다른 PORT번호로 어떤 애플리케이션이 응답을 받을 지 정할 수 있다!</p>
<h4 id="port">PORT</h4>
<ul>
<li>0 ~ 65535 할당 가능</li>
<li>0 ~ 1023 : 잘 알려진 포트 , 사용하지 않는 것이 좋음<ul>
<li>FTP - 20,21</li>
<li>TELNET - 23</li>
<li>HTTP - 80</li>
<li>HTTPS - 443</li>
</ul>
</li>
</ul>
<h3 id="4-dnsdomain-name-system">4. DNS(Domain Name System)</h3>
<p><strong>IP는 기억하기 어렵다.</strong>
<strong>IP는 변경될 수 있다.</strong></p>
<h4 id="dns도메인-네임-시스템">DNS(도메인 네임 시스템)</h4>
<ul>
<li>전화번호부</li>
<li>도메인 명을 IP주소로 변환해준다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/h_ani99/post/c724b51b-90a9-460a-9173-0929740debdf/image.png" alt=""></p>
<p>도메인 이름을 사서 등록을 하게 되면 해당 도메인의 IP주소 요청을 보내면 IP주소를 반환해준다.
IP주소가 바뀌어도 해당 도메인의 IP를 DNS서버 상에서 변경을 하면 문제없이 접근을 할 수 있다.</p>
<br/>

<p><strong>⭐정리</strong></p>
<ul>
<li>인터넷 통신 : 복잡한 인터넷 망에서 컴퓨터끼리 어떻게 통신할까?</li>
<li>IP : IP프로토콜을 통해 서로 통신을 할 수 있지만 한계가 있다.</li>
<li>TCP , UDP : IP의 한계를 TCP가 해결해준다.</li>
<li>PORT : IP주소는 아파트 주소 , PORT 번호는 정확한 동,호수.</li>
<li>DNS : IP주소의 변동성을 해결해주는 도메인 네임 시스템</li>
</ul>
<hr>
<p> 글에 포함된 모든 내용과 자료는 김영한님의 모든 개발자를 위한 HTTP 웹 기본 지식 강의를 듣고 정리했습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ 김영한 스프링 핵심 원리 #2 ] 싱글톤 컨테이너]]></title>
            <link>https://velog.io/@h_ani99/%EA%B9%80%EC%98%81%ED%95%9C-%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-2-%EC%8B%B1%EA%B8%80%ED%86%A4-%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88</link>
            <guid>https://velog.io/@h_ani99/%EA%B9%80%EC%98%81%ED%95%9C-%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-2-%EC%8B%B1%EA%B8%80%ED%86%A4-%EC%BB%A8%ED%85%8C%EC%9D%B4%EB%84%88</guid>
            <pubDate>Mon, 02 Feb 2026 05:58:47 GMT</pubDate>
            <description><![CDATA[<h3 id="0-싱글톤-패턴이란">0. 싱글톤 패턴이란?</h3>
<p>싱글톤 패턴이란
객체 인스턴스가 현재 나의 JVM에 딱 하나만 있어야 되는 패턴을 말한다.</p>
<h3 id="1-웹-애플리케이션과-싱글톤">1. 웹 애플리케이션과 싱글톤</h3>
<ul>
<li>스프링은 태생이 기업용 온라인 서비스 기술을 지원하기 위해 탄생했다.</li>
<li>대부분의 스프링 애플리케이션은 웹 애플리케이션이다. 물론 웹이 아닌 애플리케이션 개발도
얼마든지 할 수 있다.</li>
<li>웹 애플리케이션은 보통 여러 고객이 동시에 요청을 한다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/h_ani99/post/62ced3e8-2701-4d4d-af73-c8bf500a36f3/image.png" alt=""></p>
<p>위 그림과 같이 클라이언트 3명에게서 동시에 멤버서비스로 요청이 들어왔다고 생각해보자.</p>
<p><img src="https://velog.velcdn.com/images/h_ani99/post/afc44d01-f9b0-4ece-8ebc-4398de5e414c/image.png" alt="">
같은 요청이 동시에 3번오면 위 코드의 경우 요청마다 멤버서비스 임플 객체를 반환한다.
결국 3번의 요청동안 3번의 객체가 생성되는 것이다.</p>
<h4 id="🚨문제점">🚨문제점?</h4>
<ul>
<li>웹 애플리케이션은 고객이 계속 요청을 하는 애플리케이션이다.</li>
<li>고객 트래픽이 초당 100이 나오면 초당 100개 객체가 생성되고 소멸된다!
➡️ 메모리 낭비가 심하다.</li>
<li>해결방안은 해당 객체가 딱 1개만 생성되고, 공유하도록 설계해야 한다!
➡️ 싱글톤 패턴</li>
</ul>
<h3 id="2-싱글톤-패턴">2. 싱글톤 패턴</h3>
<ul>
<li><p>클래스의 인스턴스가 딱 1개만 생성되는 것을 보장하는 디자인 패턴이다.</p>
</li>
<li><p>그래서 객체 인스턴스를 2개 이상 생성하지 못하도록 막아야 한다.</p>
<ul>
<li>private 생성자를 사용해서 외부에서 임의로 new 키워드를 사용하지 못하도록 만들어야한다.</li>
</ul>
<p><img src="https://velog.velcdn.com/images/h_ani99/post/561d5255-626e-4122-bd67-5fda502f9372/image.png" alt=""></p>
</li>
</ul>
<ol>
<li>static 영역에 객체 instance를 미리 하나 생성해서 올려둔다.</li>
<li>이 객체 인스턴스가 필요하면 오직 <code>getInstance()</code> 메서드를 통해서만 조회할 수 있다.
이 메서드를 호출하면 항상 같은 인스턴스를 반환한다.</li>
<li>딱 1개의 객체 인스턴스만 존재해야 하므로, 생성자를 privatge으로 막아서 혹시라도
외부에서 new 키워드로 객체 인스턴스가 생성되는 것을 막는다.</li>
</ol>
<p><img src="https://velog.velcdn.com/images/h_ani99/post/bd76af00-02cf-4a57-ba33-cecd9155f2cd/image.png" alt="">
<img src="https://velog.velcdn.com/images/h_ani99/post/731a812e-07e4-43da-b488-f3d61bf589f3/image.png" alt=""></p>
<p>테스트를 해보니 서비스를 2번 호출했지만 같은 객체가 호출되는 것을 확인할 수 있다.
싱글톤 패턴을 적용하면 고객의 요청이 올 때 마다 객체를 생성하는 것이 아니라, 
이미 만들어진 객체를 공유해서 효율적으로 사용할 수 있다. 
하지만 싱글톤 패턴은 다음과 같은 수 많은 문제점들을 가지고 있다.</p>
<h4 id="🚨-싱글톤-패턴-문제점">🚨 싱글톤 패턴 문제점</h4>
<ul>
<li>싱글톤 패턴을 구현하는 코드 자체가 많이 들어간다.</li>
<li>의존관계상 클라이언트가 구체 클래스에 의존한다. ➡️ DIP를 위반한다.</li>
<li>클라이언트가 구체 클래스에 의존해서 OCP 원칙을 위반할 가능성이 높다.</li>
<li>테스트하기 어렵다.</li>
<li>내부 속성을 변경하거나 초기화 하기 어렵다.</li>
<li>private 생성자로 자식 클래스를 만들기 어렵다.</li>
<li>결론적으로 유연성이 떨어진다.</li>
<li>안티패턴으로 불리기도 한다.</li>
</ul>
<h3 id="3-싱글톤-컨테이너">3. 싱글톤 컨테이너</h3>
<p>스프링 컨테이너는 싱글톤 패턴의 문제점을 해결하면서 , 
객체 인스턴스를 싱글톤(1개만 생성)으로 관리한다.</p>
<h4 id="싱글톤-컨테이너">싱글톤 컨테이너</h4>
<ul>
<li>스프링 컨테이너는 싱글톤 패턴을 적용하지 않아도, 객체 인스턴스를 싱글톤으로 관리한다.</li>
<li>스프링 컨테이너는 싱글톤 컨테이너 역할을 한다. 
이렇게 싱글톤 객체를 생성하고 관리하는 기능을 싱글톤 레지스트리라고 한다.</li>
<li>스프링 컨테이너의 이런 기능 덕분에 싱글톤 패턴의 모든 단점을 해결하면서 객체를 싱글톤으로 유지할 수 있다.</li>
</ul>
<h3 id="4-싱글톤-방식의-주의점">4. 싱글톤 방식의 주의점</h3>
<ul>
<li>싱글톤 패턴이든, 스프링 같은 싱글톤 컨테이너를 사용하든 , 객체 인스턴스를 하나만
생성해서 공유하는 싱글톤 방식은 여러 클라이언트가 하나의 같은 객체 인스터스를 공유하기 때문에
싱글톤 객체는 상태를 유지(stateful)하게 설계하면 안된다.</li>
<li>무상태(stateless)로 설계해야 한다.<ul>
<li>특정 클라이언트에 의존적인 필드가 있으면 안된다.</li>
<li>특정 클라이언트가 값을 변경할 수 있는 필드가 있으면 안된다!</li>
<li>가급적 읽기만 가능해야 한다.</li>
<li>필드 대신에 자바에서 공유되지 않는, 지역변수,파라미터,ThreadLocal 등을 사용해야 한다.</li>
</ul>
</li>
</ul>
<p><strong>상태를 유지할 경우 발생하는 문제점 예시</strong>
<img src="https://velog.velcdn.com/images/h_ani99/post/6d989515-a531-4e8a-88e9-339bbe94fd92/image.png" alt="">
<strong>상태를 유지할 경우 발생하는 문제점 예시</strong>
<img src="https://velog.velcdn.com/images/h_ani99/post/fb3b15ac-daa0-411d-8ff5-979927b3c740/image.png" alt=""></p>
<ul>
<li>ThreadA가 사용자A를 호출하고 ThreadB가 사용자B 코드를 호출한다 가정하자.</li>
<li><code>StatefulService</code>의 <code>price</code>필드는 공유되는 필드인데, 특정 클라이언트가 값을 변경한다.</li>
<li>사용자A의 주문금액은 10,000원이 되어야 하는데, 20,000원 이라는 결과가 나왔다.</li>
<li>공유필드는 조심해야 한다! 스프링 빈은 항상 무상태(stateless)로 설계하자.</li>
</ul>
<hr>
<p>글에 포함된 모든 내용과 자료는 김영한님의 스프링 핵심 원리-기본편 강의를 듣고 정리했습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[ 김영한 스프링 핵심 원리 #1 ] 객체 지향 설계와 스프링]]></title>
            <link>https://velog.io/@h_ani99/%EA%B9%80%EC%98%81%ED%95%9C-%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-1-%EA%B0%9D%EC%B2%B4-%EC%A7%80%ED%96%A5-%EC%84%A4%EA%B3%84%EC%99%80-%EC%8A%A4%ED%94%84%EB%A7%81</link>
            <guid>https://velog.io/@h_ani99/%EA%B9%80%EC%98%81%ED%95%9C-%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-1-%EA%B0%9D%EC%B2%B4-%EC%A7%80%ED%96%A5-%EC%84%A4%EA%B3%84%EC%99%80-%EC%8A%A4%ED%94%84%EB%A7%81</guid>
            <pubDate>Mon, 02 Feb 2026 05:48:14 GMT</pubDate>
            <description><![CDATA[<h3 id="1-자바-진영의-추운-겨울과-스프링의-탄생-❄️">1. 자바 진영의 추운 겨울과 스프링의 탄생 ❄️</h3>
<p>2000년대 초반에 자바 진영의 표준 기술 중 최고봉인 <strong>EJB(enterprise java beans)</strong>라는 게 있었다. 
지금으로 치자면 스프링과 JPA 등을 몽땅 합쳐놓은 종합선물 세트였다.</p>
<p>많은 회사에서 사용했고 글로벌하게 사용되어 레퍼런스 또한 넘쳐났다.
트랜잭션 관리와 서버 분산 관리에도 굉장히 용이했다.
또한 EJB는 엔티티 빈이라는 ORM 기술 또한 지원을 해주었다.</p>
<p><strong>그러나!!</strong> 이 듣기 좋은 기술에도 단점은 확실히 존재했다.</p>
<p>요즘 우리는 개발을 하기 위해 스프링을 사용한다고 하면 대부분 무료로 사용한다.
하지만 당시 EJB를 제대로 구성하기 위해서는 수천만원짜리 서버들도 필요했다.
또한 굉장히 복잡했다.</p>
<p>EJB가 제공하는 인터페이스를 모두 구현하고 EJB에 의존적으로 개발해야 된다.
EJB가 제공하는 엔티티 빈 기술 조차도 그 수준이 너무 낮았으며 EJB를 사용하여 개발을 하게 되면 코드가 너무 지저분해졌다.</p>
<p>이후, <strong>로드 존슨</strong>이라는 개발자가 EJB를 비판하면서 EJB를 대체하며 훨씬 더 단순하고 좋은 방법으로 개발할 수 있다라는 것을 주제로 해서 책을 쓰고 코드를 풀게 된다.
또한 <strong>Gavin King</strong>이 엔티티 빈 기술을 대신할 수 있는 <strong>하이버네이트</strong>를 개발하게 된다.</p>
<p>사람들은 EJB의 엔티티 빈을 사용하지 않고, 당시 ORM 기술을 대부분 하이버네이트를 사용할 정도로 많은 인기를 끌었다.
EJB의 사용률이 너무 저조하자 자바 표준을 논의하고 만드는 곳에서 개빈 킹을 데려와 <strong>JPA</strong>를 만들어낸다.</p>
<p><img src="https://velog.velcdn.com/images/h_ani99/post/c1731a63-fa54-4771-b423-17ab35980eb6/image.png" alt=""></p>
<hr>
<h3 id="2-스프링이란-🌱">2. 스프링이란? 🌱</h3>
<ul>
<li><strong>스프링 생태계</strong></li>
</ul>
<p><img src="https://velog.velcdn.com/images/h_ani99/post/8c35b395-0a3e-4815-81c9-115540f948cd/image.png" alt=""></p>
<p>스프링은 특정한 하나가 아니라 여러가지 기술들의 모음이다.
스프링의 가장 핵심이 되는 <strong>스프링 프레임워크</strong>와 여러 스프링 기술들을 편리하게 사용할 수 있도록 도와주는 <strong>스프링 부트</strong> 그리고 스프링 데이터, 세션, 시큐리티, 레스트 독스, 배치 등등 있다.</p>
<ul>
<li><strong>스프링 데이터:</strong> 데이터의 등록, 수정, 삭제, 조회, CRUD는 RDBMS, NoSQL 모두 비슷하기 때문에 이를 굉장히 편리하게 사용할 수 있도록 도와주는 기술이다. (현재 제일 많이 쓰이는 것은 JPA이다.)</li>
<li><strong>스프링 세션:</strong> 세션 기능을 편리하게 사용할 수 있도록 지원한다.</li>
<li><strong>스프링 시큐리티:</strong> 보안과 관련된 기능들을 편리하게 사용할 수 있는 기술이다.</li>
<li><strong>스프링 Rest Docs:</strong> API 문서화를 편리하게 해줄 수 있도록 지원한다.</li>
<li><strong>스프링 배치는:</strong> 배치 처리에 특화된 기술을 제공한다.</li>
<li><strong>스프링 클라우드는:</strong> 클라우드 기술에 특화된 기술을 제공한다.</li>
</ul>
<br>

<p><strong><code>스프링 프레임워크</code></strong></p>
<p>스프링 프레임워크 안에는 첫번째 핵심 기술 스프링의 DI, 컨테이너, AOP, 이벤트, 디지털 등등, 스프링의 모든 라이브러리를 활용하는 스프링의 가장 핵심 중의 핵심이라고 할 수 있는 핵심 기술이 있다.
Spring MVC, 웹플렉스 같은 웹 기술들이 있다.
DB에 접근하는 데이터베이스 트랜잭션이나 JDBC ORM등을 지원하는 데이터 접근 기술과 관련된 부분이 있다. 또한 기술을 통합하거나 테스트와 관련된 부분과 언어 지원과 관련된 부분들을 통합해서 <strong>Spring Framework</strong>라고 한다.</p>
<p>최근에는 스프링 프레임워크의 기술들을 편리하게 사용할 수 있는 <strong>스프링 부트</strong>라는 것을 통해서 스프링 프레임워크를 사용한다.</p>
<br>

<p><strong><code>스프링 부트</code></strong></p>
<p>스프링 부트는 스프링을 굉장히 편리하게 사용할 수 있도록 지원하는 기술이다.</p>
<ul>
<li><strong>스프링 부트의 장점?</strong><ol>
<li>단독으로 실행할 수 있는 Spring 애플리케이션을 쉽게 생성할 수 있다.</li>
<li>Tomcat같은 웹서버를 내장해서 별도의 웹서버를 설치하지 않아도 된다.</li>
<li>손쉬운 빌드 구성을 위한 스타터 의존성 제공을 한다.</li>
<li>유명한 메이저 라이브러리들은 궁합과 조합이 잘 맞는지 스프링이 다 테스트하고 버전까지 지정을 해서 다운로드 받을 수 있다.</li>
</ol>
</li>
</ul>
<blockquote>
<p>⚠️ 스프링 부트는 스프링 프레임워크와 별도로 사용할 수 있는게 아니다. 스프링 부트는 여러 기술들을 편리하게 사용할 수 있도록 해주는 기능들을 제공해준다.
스프링 부트는 스프링 프레임워크와 다른 기능들도 필요하면 같이 사용하는 것이지 스프링 부트만으로 뭔가 돌아갈 수 있는 프로젝트는 아니다.</p>
</blockquote>
<br>

<p><strong><code>스프링이란?</code></strong></p>
<p>스프링이라는 단어는 애매한 단어이다.
문맥에 따라 다르지만 좁혀서 얘기하자면 핵심 중에 핵심인 <strong>스프링 빈을 관리하는 DI 컨테이너 기술</strong>이다. 스프링 프레임워크 자체를 말하기도 한다.</p>
<p><strong><code>스프링을 왜 만들게 되었을까?</code></strong></p>
<p><strong>스프링의 핵심은 객체지향 언어가 가진 강력한 특징을 살려내는 프레임워크이다.</strong>
스프링은 좋은 객체지향 어플리케이션을 개발할 수 있도록 개발자들을 도와주는 프레임워크이다.
EJB 사용할 당시에는 객체지향이 가진 장점을 모두 잃어버린 채 EJB에 의존적으로 개발을 할 수 밖에 없었다.</p>
<hr>
<h3 id="3-좋은-객체-지향-프로그래밍이란-🧩">3. 좋은 객체 지향 프로그래밍이란? 🧩</h3>
<p><strong>객체 지향 프로그래밍의 특징</strong></p>
<ul>
<li>추상화</li>
<li>캡슐화</li>
<li>상속</li>
<li><strong>다형성</strong></li>
</ul>
<p>객체 지향 프로그래밍에서는 프로그램이 각각의 객체들의 모임으로 이루어져있고 객체는 서로 메시지를 주고받고 데이터를 처리하며 협력한다.
또한 유연하고 변경이 용이하여 대규모 소프트웨어 개발에 많이 사용이 된다.</p>
<p><strong>유연하다는 것이 무슨 의미일까?</strong>
(레고 블록을 조립하듯이, 키보드 마우스를 새로운 키보드 마우스로 갈아 끼우듯이, 컴퓨터 부품을 갈아 끼우듯이)
컴포넌트를 쉽고 유연하게 변경하면서 개발할 수 있는 방법이다.
궁극의 유연함과 궁극의 변경이 용이함이 바로 객체지향의 핵심인 <strong>다형성</strong>이다.</p>
<br>

<p><strong><code>다형성?</code></strong></p>
<p>다형성을 설명하기 앞서 세상을 역할과 역할을 행하는 행위(구현)를 세상으로 구분하면 역할이 인터페이스이고 구현이 실제 인터페이스를 구현한 객체라고 생각해보자.</p>
<p><strong>1. 운전자와 자동차 예시</strong></p>
<p><img src="https://velog.velcdn.com/images/h_ani99/post/dab717ca-9415-48c2-9436-62617182c97c/image.png" alt=""></p>
<p>운전자와 자동차 예시를 보면 운전자라는 역할이 있고 자동차라는 역할이 있다.
우리는 자동차가 K3이든 아반떼이든 테슬라이든 상관없이 운전을 할 수 있다.(운전면허만 있다면)
자동차가 바뀌어도 자동차란 역할에 대한 구현만 바뀌었을 뿐 그 역할은 바뀌지 않았기 때문이다.
운전자는 자동차의 역할에 대해서만 의존하고 있다.
따라서 자동차가 바뀐다 하더라도 운전자(클라이언트)에게는 영향을 주지 않는다.
이처럼 운전자(클라이언트)에게 영향을 주지 않고도 계속적으로 새로운 구현(새로운 자동차)를 제공할 수 있는 것이다.</p>
<p><strong>2. 로미오와 줄리엣 예시</strong></p>
<p><img src="https://velog.velcdn.com/images/h_ani99/post/dce42fbe-ac9c-453d-a3e4-88a4ee3baced/image.png" alt=""></p>
<p>로미오와 줄리엣 공연 예시를 보면 로미오라는 역할이 있고 줄리엣이라는 역할이 있다.
이 역할들은 여러 배우들이 연기가 가능하다. 역할과 구현을 나눴기때문에 변경 가능한 대체 가능성이 생긴다.(유연하고 변경에 용이하다.)
로미오가 클라이언트고 줄리엣이 서버가 된다고 가정해보자.
여기서 줄리엣이라는 구현이 바뀐다고 해서 로미오 역할에 영향을 주지 않는다.
이것이 바로 유연하고 변경이 용이하다는 것이다.</p>
<p><strong>- 정리</strong></p>
<p>역할과 구현으로 구분하면 세상이 단순해지고, 유연해지며 변경도 편리해진다.</p>
<ul>
<li><strong>장점</strong><ul>
<li>클라이언트 는 대상의 역할(인터페이스)만 알면 된다. (ex. 로미오 역할은 대본에서의 줄리엣 역할만 알면된다. 김태희가 할지 송혜교가 할지, 역할의 구현체에 대한 것은 몰라도 된다.)</li>
<li>클라이언트 는 구현 대상의 자세한 내부 구조를 몰라도 된다.</li>
<li>클라이언트 는 구현 대상의 내부 구조가 변경되어 영향을 받지 않는다.</li>
<li>클라이언트 는 구현 대상 자체를 변경해도(ex. K3 -&gt; 테슬라) 영향을 받지 않는다.</li>
</ul>
</li>
</ul>
<hr>
<p><strong>자바 언어에서의 역할과 구현을 분리</strong></p>
<ul>
<li><strong>자바 언어의 다형성을 활용</strong><ul>
<li>역할 = 인터페이스</li>
<li>구현 = 인터페이스를 구현한 클래스, 구현 객체</li>
</ul>
</li>
<li>객체를 설계할 때 역할과 구현을 명확히 분리해서 설계를 한다.</li>
<li>객체를 설계시 역할(인터페이스)를 먼저 부여하고, 그 역할을 수행하는 구현 객체를 만든다.</li>
</ul>
<p><strong>객체의 협력이라는 관계부터 생각</strong></p>
<ul>
<li>혼자 있는 객체는 없다.</li>
<li>클라이언트 : 요청 , 서버 : 응답</li>
<li>수 많은 객체 클라이언트와 객체 서버는 서로 협력 관계를 가진다.<ul>
<li>개념이 커지면 여러 서버끼리,시스템끼리 요청을 주고 받을 수 있다.</li>
</ul>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/h_ani99/post/49c220f5-74ed-4c2e-ac36-8268a6899f20/image.png" alt=""></p>
<pre><code>* 클라이언트가 서버에 요청을 할 수 도 있고 동시에 서버가 될 수도 있다.
* 클라이언트가 서버에 요청을 하고 서버는 클라이언트가 돼서 다른 서버들에 요청할 수 있다.</code></pre><br>

<p><strong>자바 언어의 다형성</strong></p>
<p><img src="https://velog.velcdn.com/images/h_ani99/post/900593ad-7292-472e-8967-d30e289453d7/image.png" alt=""></p>
<p><strong>다형성의 본질</strong></p>
<ul>
<li>인터페이스를 구현한 객체 인스턴스를 실행 시점에 유연하게 변경할 수 있다.</li>
<li>다형성의 본질을 이해하려면 협력이라는 객체 사이의 관계에서 시작해야함</li>
<li><strong>클라이언트를 변경하지 않고, 서버의 구현 기능을 유연하게 변경할 수 있다.</strong></li>
</ul>
<h4 id="정리">정리</h4>
<ul>
<li>실세계의 역할과 구현이라는 편리한 컨셉을 다형성을 통해 객체 세상으로 가져올 수 있음</li>
<li>유연하고 변경이 용이하다.</li>
<li>확장 가능한 설계</li>
<li>클라이언트에 영향을 주지 않는 변경 가능</li>
<li>인터페이스를 안정적으로 잘 설계하는 것이 중요</li>
</ul>
<h4 id="한계">한계</h4>
<ul>
<li>역할(인터페이스)자체가 변하면, 클라이언트, 서버 모두에 큰 변경이 발생한다.</li>
<li>자동차를 비행기로 변경해야 한다면?</li>
<li>대본 자체가 변경된다면?</li>
<li><strong>인터페이스를 안정적으로 잘 설계하는 것이 중요하다!!</strong></li>
</ul>
<h3 id="4-좋은-객체-지향-설계의-5가지-원칙solid">4. 좋은 객체 지향 설계의 5가지 원칙(SOLID)</h3>
<p>좋은 객체 지향 설계의 5가지 원칙인 솔리드에 대해서 알아보자.</p>
<h4 id="solid란">SOLID란?</h4>
<p>클린코드로 유명한 로버트 마틴이 좋은 객체 지향 설계의 5가지 원칙을 정리한 것</p>
<blockquote>
<ul>
<li>SRP : 단일 책임 원칙(Single responsibility principle)</li>
</ul>
</blockquote>
<ul>
<li>OCP : 개방-폐쇄 원칙(Open/closed principle)</li>
<li>LSP : 리스코프 치환 원칙(Liskov substitution principle)</li>
<li>ISP : 인터페이스 분리 원칙(Integerface segregation principle)</li>
<li>DIP : 의존관계 역전 원칙(Dependency inversion principle)</li>
</ul>
<p>5가지 원칙의 앞글자를 따서 SOLID라고 말한다.</p>
<p>1) SRP 단일 책임 원칙(Single responsibility principle)</p>
<ul>
<li><p>한 클래스는 하나의 책임만 가져야 한다.</p>
</li>
<li><p>하나의 책임이라는 것은 모호하다.</p>
<ul>
<li>클 수 있고 , 작을 수 있다.</li>
<li>문맥과 상황에 따라 다르다.</li>
</ul>
</li>
<li><p>중요한 기준은 변경이다. 변경이 있을 때 파급 효과가 적으면 단일 책임 원칙을 잘 따른것이다.
예)  UI 변경 , 객체의 생성과 사용을 분리</p>
<p>우리가 계층이 잘 나누어져 있고 범위를 적절하게 잘 조절하는 것이 단일 책임 원칙을 지키는 것이다.
변경이 있을 때 딱 하나의 클래스나 하나의 지점만 고치면 그게 단일 책임 원칙을 잘 따르는 것이다.</p>
</li>
</ul>
<p>2) OCP 개방-폐쇄 원칙(Open/closed principle)</p>
<ul>
<li>가장 중요한 원칙</li>
<li>소프트웨어 요소는 확장에는 열려 있으나 변경에는 닫혀 있어야 한다.</li>
<li>이런 거짓말 같은 말이? 기능 확장을 하려면 코드가 변경이 돼야 하는 것 아닌가?</li>
<li>다형성을 활용해보자.</li>
<li>인터페이스를 구현한 새로운 클래스를 하나 만들어서 새로운 기능을 구현</li>
<li>역할과 구현의 분리를 생각해보자.</li>
</ul>
<p>🚨 OCP 개방-폐쇄 원칙 문제점</p>
<ul>
<li><p>아래의 멤버서비스 클래스는 직접 구현 클래스를 선택 하고 있다.
<img src="https://velog.velcdn.com/images/h_ani99/post/487a3833-f960-4e15-a1bc-4aac7e088370/image.png" alt=""></p>
<ul>
<li>MemberRepository m = new MemoryMemberRepository() // 기존 코드</li>
<li>MemberRepository m = new JdbcMemberRepository()  // 변경 콛,</li>
</ul>
</li>
<li><p>구현 객체를 변경하려면 클라이언트 코드를 변경해야 한다.</p>
</li>
<li><p>분명 다형성을 사용했지만 OCP 원칙을 지킬 수 없다.</p>
</li>
<li><p>이 문제를 어떻게 해결해야 하나?</p>
</li>
<li><p>객체를 생성하고, 연관관계를 맺어주는 별도의 조립,설정자가 필요하다
⭐이 별도의 조립,설정자를 Spring이 해결해준다.</p>
</li>
</ul>
<p>3) LSP 리스코프 치환 원칙(Liskov substitution principle)</p>
<ul>
<li>프로그램 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 
바꿀 수 있어야 한다.</li>
<li>다형성에서 하위 클래스는 인터페이스 규약을 다 지켜야 한다는 것,
다형성을 지원하기 위한 원칙 , 인터페이스를 구현한 구현체는 믿고 사용하려면,
이 원칙이 필요하다.</li>
<li>단순히 컴파일에 성공한느 것을 넘어서는 이야기</li>
<li>예 ) 자동차 인터페이스의 엑셀은 앞으로 가라는 기능 , 뒤로 가게 구현하면 LSP 위반,
느리더라도 앞으로 가야한다.</li>
</ul>
<p>4) ISP 인터페이스 분리 원칙(Integerface segregation principle)</p>
<ul>
<li>특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 낫다.</li>
<li>자동차 인터페이스 -&gt; 운전 인터페이스 , 정비 인터페이스로 분리</li>
<li>사용자 클라이언트 -&gt; 운전자 클라이언트, 정비사 클라이언트로 분리</li>
<li>분리하면 정비 인터페이스 자체가 변해도 운전자 클라이언트에 영향을 주지 않음</li>
<li>인터페이스가 명확해지고 , 대체 가능성이 높아진다.</li>
</ul>
<p>5) DIP 의존관계 역전 원칙(Dependency inversion principle)</p>
<ul>
<li>프로그래머는 &quot;추상화에 의존해야지, 구체화에 의존하면 안된다.&quot;
의존성 주입은 이 원칙을 따르는 방법 중 하나이다.</li>
<li>쉽게 이야기 해서 구현 클래스에 의존하지 말고 , 인터페이스에 의존하라는 뜻</li>
<li>앞에서 이야기한 <strong>역할(Role)에 의존하게 해야 한다는 것과 같다.</strong>
객체 세상도 클라이언트가 인터페이스에 의존해야 유연하게 구현체를 변경할 수 있다!
구현체에 의존하게 되면 변경이 아주 어려워진다.</li>
<li>예 ) K3 운전자가 자동차 역할에 대해서만 알면 되지 K3자체에 대해서 디테일하게 알 필요가 없다.<br/>

</li>
</ul>
<p>☝️정리</p>
<ul>
<li>객체 지향의 핵심은 다형성</li>
<li>다형성 만으로는 쉽게 부품을 갈아 끼우듯이 개발할 수 없다.</li>
<li>다형성 만으로는 구현 객체를 변경할 때 클라이언트 코드도 함께 변경된다.</li>
<li>다형성 만으로는 OCP , DIP를 지킬 수 없다.</li>
<li>뭔가 더 필요하다.</li>
</ul>
<h3 id="5-객체-지향-설계와-스프링">5. 객체 지향 설계와 스프링</h3>
<h4 id="다시-스프링으로">다시 스프링으로</h4>
<p>스프링 이야기에 객체 지향 이야기가 왜 나오는가?</p>
<ul>
<li><p>스프링은 다음 기술로 다형성 + OCP,DIP를 가능하게 지원해주는 기술이다.</p>
<ul>
<li><p>DI(Dependency Injection) : 의존관계, 의존성 주입</p>
</li>
<li><p>DI 컨테이너 제공 : 자바 객체들을 컨테이너 안에 넣어주고 안에서 의존관계를 
서로 연결해주고 주입해주는 기능을 제공</p>
</li>
<li><p><strong>클라이언트 코드의 변경 없이 기능 확장</strong></p>
</li>
<li><p>쉽게 부품을 교체하듯이 개발</p>
</li>
</ul>
<p>😫 스프링이 없던 시절?</p>
<ul>
<li><p>옛날 어떤 개발자가 좋은 객체 지향 개발을 하려고 OCP,DIP 원칙을 지키면서
개발을 해보니, 너무 할일이 많았다. 배보다 배꼽이 크다.그래서 프레임 워크로 만들어버림</p>
</li>
<li><p>순수하게 자바로 OCP,DIP 원칙들을 지키면서 개발을 해보면, 결국 스프링 프레임워크를 만들게 된다. (더 정확히는 DI컨테이너)</p>
</li>
<li><p>DI 개념은 말로 설명해도 이해가 잘 안된다. 코드로 짜봐야 필요성을 알게 된다!</p>
</li>
</ul>
</li>
</ul>
<p> ☝️정리</p>
<ul>
<li>모든 설계에 역할과 구현을 분리하자</li>
<li>자동차,공연의 예를 떠올려보자.</li>
<li>애플리케이션 설계도 공연을 설계 하듯이 배역만 만들어두고, 배우는 언제든지 유연하게
변경할 수 있도록 만드는 것이 좋은 객체 지향 설계다.</li>
<li>이상적으로는 모든 설계에 인터페이스를 부여하자</li>
</ul>
<hr>
<p>글에 포함된 모든 내용과 자료는 김영한님의 스프링 핵심 원리-기본편 강의를 듣고 정리했습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[JSONB란 무엇인가?]]></title>
            <link>https://velog.io/@h_ani99/JSONB%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80</link>
            <guid>https://velog.io/@h_ani99/JSONB%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80</guid>
            <pubDate>Thu, 15 Jan 2026 10:03:02 GMT</pubDate>
            <description><![CDATA[<h1 id="📦-jsonb란-무엇인가">📦 JSONB란 무엇인가?</h1>
<p>PostgreSQL을 사용하다 보면 컬럼 타입으로<br><code>JSON</code>과 <code>JSONB</code>가 따로 존재하는 걸 보게 된다.</p>
<p>처음에는<br>“JSON이면 JSON이지, 왜 B가 붙은 게 따로 있지?”<br>라는 생각이 들었고,<br>실제로는 대부분 <code>JSONB</code>를 사용한다고 해서 정리해보게 되었다.</p>
<hr>
<h2 id="jsonb-한-줄로-정리하면">JSONB 한 줄로 정리하면</h2>
<p><strong>JSONB는 JSON 데이터를 이진(Binary) 형태로 저장하는 PostgreSQL의 데이터 타입이다.</strong></p>
<p>JSONB는 단순히 JSON 문자열을 저장하는 것이 아니라,<br>PostgreSQL이 내부적으로 파싱해서 <strong>구조화된 형태로 저장</strong>한다.</p>
<hr>
<h2 id="json과-jsonb의-차이">JSON과 JSONB의 차이</h2>
<p>PostgreSQL에는 <code>JSON</code>과 <code>JSONB</code> 두 가지 타입이 있다.</p>
<table>
<thead>
<tr>
<th>구분</th>
<th>JSON</th>
<th>JSONB</th>
</tr>
</thead>
<tbody><tr>
<td>저장 방식</td>
<td>문자열 그대로 저장</td>
<td>이진(Binary) 형태로 저장</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>
<hr>
<h2 id="jsonb는-왜-더-많이-쓰일까">JSONB는 왜 더 많이 쓰일까?</h2>
<p>JSONB는 데이터를 저장할 때 한 번 파싱해서<br>이진 형태로 저장한다.</p>
<p>그래서:</p>
<ul>
<li>특정 키 값 조회가 빠르고</li>
<li>인덱스를 사용할 수 있고</li>
<li>연산에 유리하다</li>
</ul>
<p>반면 JSON 타입은<br>문자열 그대로 저장되기 때문에<br>조회할 때마다 파싱이 필요하다.</p>
<hr>
<h2 id="jsonb-사용-예시">JSONB 사용 예시</h2>
<p>JSONB 컬럼을 가진 테이블 예시다.</p>
<pre><code>CREATE TABLE orders (
    id SERIAL,
    info JSONB
);</code></pre><p>데이터를 JSON 형태로 저장할 수 있다.</p>
<pre><code>INSERT INTO orders (info)
VALUES (&#39;{&quot;product&quot;: &quot;book&quot;, &quot;price&quot;: 10000}&#39;);</code></pre><p>JSONB 내부 값 조회도 가능하다.</p>
<pre><code>SELECT info-&gt;&gt;&#39;product&#39;
FROM orders;</code></pre><p>이렇게 JSON 구조 안의 값에 바로 접근할 수 있다.</p>
<hr>
<h2 id="jsonb는-언제-사용하면-좋을까">JSONB는 언제 사용하면 좋을까?</h2>
<p>JSONB는 다음과 같은 경우에 유용하다.</p>
<ul>
<li>구조가 자주 바뀌는 데이터</li>
<li>외부 API 응답을 그대로 저장해야 하는 경우</li>
<li>설정 정보나 옵션 값 저장</li>
<li>모든 필드를 컬럼으로 만들기 애매한 경우</li>
</ul>
<p>예를 들면:</p>
<ul>
<li>결제 정보</li>
<li>로그 데이터</li>
<li>사용자 설정 값</li>
</ul>
<hr>
<h2 id="jsonb를-사용할-때-주의할-점">JSONB를 사용할 때 주의할 점</h2>
<p>JSONB가 편리하다고 해서<br>모든 데이터를 JSONB로 저장하는 것은 좋지 않다.</p>
<ul>
<li>자주 조회되는 값</li>
<li>정형화된 데이터</li>
<li>관계가 중요한 데이터</li>
</ul>
<p>이런 경우에는<br>일반 컬럼으로 분리하는 것이 더 좋다.</p>
<p>JSONB는 <strong>보조적인 용도</strong>로 사용하는 게 적절하다.</p>
<hr>
<h2 id="정리해보면">정리해보면</h2>
<p>JSONB는 PostgreSQL에서<br><strong>유연한 구조의 데이터를 효율적으로 저장하고 조회할 수 있는 데이터 타입</strong>이다.</p>
<p>구조가 자주 바뀌거나<br>모든 필드를 컬럼으로 만들기 애매한 경우에<br>특히 강점을 가진다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[PostGIS란 무엇인가?]]></title>
            <link>https://velog.io/@h_ani99/PostGIS%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80</link>
            <guid>https://velog.io/@h_ani99/PostGIS%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80</guid>
            <pubDate>Thu, 15 Jan 2026 10:01:09 GMT</pubDate>
            <description><![CDATA[<h1 id="📍-postgis란-무엇인가">📍 PostGIS란 무엇인가?</h1>
<p>PostgreSQL을 공부하다 보면 <code>PostGIS</code>라는 단어를 한 번쯤 보게 된다.<br>처음에는 “GIS? 공간 데이터?” 같은 말들이 나오는데,<br>막상 정확히 어떤 역할을 하는지 감이 잘 안 왔다.</p>
<p>그래서 PostGIS가 무엇인지,<br>어디에 쓰이는지 간단하게 정리해보려고 한다.</p>
<hr>
<h2 id="postgis-한-줄로-정리하면">PostGIS 한 줄로 정리하면</h2>
<p><strong>PostGIS는 PostgreSQL에서 공간 데이터를 다룰 수 있게 해주는 확장 기능이다.</strong></p>
<p>PostgreSQL은 기본적으로 숫자나 문자열 같은 일반적인 데이터는 잘 다룬다.<br>하지만 좌표, 거리, 위치 같은 <strong>공간 정보</strong>를 처리하기에는 한계가 있다.</p>
<p>이때 사용하는 것이 PostGIS다.</p>
<hr>
<h2 id="postgis는-왜-필요한가">PostGIS는 왜 필요한가?</h2>
<p>예를 들어 이런 상황을 생각해볼 수 있다.</p>
<ul>
<li>두 지점 사이의 거리 계산</li>
<li>특정 위치에서 반경 3km 안에 있는 데이터 조회</li>
<li>어떤 좌표가 특정 영역 안에 포함되는지 확인</li>
</ul>
<p>이런 작업을 일반 SQL로 처리하려면 쿼리가 굉장히 복잡해진다.<br>PostGIS는 이런 공간 연산을 <strong>함수 형태로 쉽게 제공</strong>해준다.</p>
<hr>
<h2 id="postgis는-지도에서-공간-데이터를-어떻게-다룰까">PostGIS는 지도에서 공간 데이터를 어떻게 다룰까?</h2>
<p>지도 서비스에서 가장 기본이 되는 정보는 <strong>위치 좌표</strong>다.<br>보통 위도(latitude)와 경도(longitude) 형태로 표현된다.</p>
<p>PostGIS는 이런 좌표를 단순한 숫자가 아니라<br><strong>공간 객체(Geometry)</strong>로 저장하고 처리한다.</p>
<p>예를 들면:</p>
<ul>
<li>하나의 위치는 <code>Point</code></li>
<li>도로는 <code>Line</code></li>
<li>특정 지역 범위는 <code>Polygon</code></li>
</ul>
<p>같은 형태로 표현된다.</p>
<p>이렇게 저장된 공간 데이터는<br>“거리”, “포함 여부”, “겹침 여부” 같은 공간 연산이 가능해진다.</p>
<hr>
<h2 id="지도에서-자주-사용하는-공간-연산-예시">지도에서 자주 사용하는 공간 연산 예시</h2>
<h3 id="두-위치-사이의-거리-계산">두 위치 사이의 거리 계산</h3>
<pre><code>SELECT ST_Distance(
    ST_Point(127.0, 37.5),
    ST_Point(127.1, 37.6)
);</code></pre><p>두 좌표 사이의 거리를 계산할 수 있다.<br>배달 서비스에서 “가장 가까운 가게 찾기” 같은 기능에 사용된다.</p>
<hr>
<h3 id="특정-반경-안에-있는-데이터-조회">특정 반경 안에 있는 데이터 조회</h3>
<ul>
<li>현재 위치 기준 반경 1km 이내 매장 조회</li>
<li>특정 지역 안에 포함된 데이터 검색</li>
</ul>
<p>이런 기능들도 PostGIS의 공간 함수로 처리할 수 있다.</p>
<hr>
<h2 id="postgis로-다룰-수-있는-데이터">PostGIS로 다룰 수 있는 데이터</h2>
<p>PostGIS를 사용하면 다음과 같은 공간 데이터를 다룰 수 있다.</p>
<ul>
<li>위도, 경도 좌표</li>
<li>점(Point), 선(Line), 면(Polygon)</li>
<li>거리, 면적</li>
<li>위치 관계(포함, 교차 등)</li>
</ul>
<p>그래서 보통 아래와 같은 서비스에서 많이 사용된다.</p>
<ul>
<li>지도 서비스</li>
<li>배달 앱</li>
<li>위치 기반 추천 서비스</li>
</ul>
<hr>
<h2 id="postgis는-기본-기능이-아니다">PostGIS는 기본 기능이 아니다</h2>
<p>중요한 점은 <strong>PostGIS는 PostgreSQL의 기본 기능이 아니라 확장(extension)</strong>이라는 것이다.</p>
<p>즉,</p>
<ul>
<li>PostgreSQL 설치만으로는 사용할 수 없고</li>
<li>PostGIS를 따로 설치하고 활성화해야 한다</li>
</ul>
<p>일반적인 CRUD 위주의 서비스라면<br>굳이 PostGIS를 사용할 필요는 없다.</p>
<hr>
<h2 id="언제-사용하면-좋을까">언제 사용하면 좋을까?</h2>
<p>PostGIS는 다음과 같은 경우에 적합하다.</p>
<ul>
<li>위치 정보가 핵심인 서비스</li>
<li>거리 계산이나 반경 검색이 필요한 경우</li>
<li>지도 기반 기능이 필요한 경우</li>
</ul>
<p>반대로,<br>단순한 게시판이나 회원 관리 서비스라면<br>굳이 사용할 이유는 없다.</p>
<hr>
<h2 id="정리해보면">정리해보면</h2>
<p>PostGIS는 PostgreSQL에서<br><strong>좌표, 거리, 위치 같은 공간 데이터를 효율적으로 다룰 수 있게 해주는 확장 기능</strong>이다.</p>
<p>지도 서비스에서 사용하는<br>“거리 계산”, “반경 검색”, “영역 포함 여부” 같은 기능을<br>DB 레벨에서 처리할 수 있다는 점이 가장 큰 특징이다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[🐘 PostgreSQL이란 무엇인가?]]></title>
            <link>https://velog.io/@h_ani99/PostgreSQL%EC%9D%B4%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80</link>
            <guid>https://velog.io/@h_ani99/PostgreSQL%EC%9D%B4%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80</guid>
            <pubDate>Thu, 15 Jan 2026 09:52:48 GMT</pubDate>
            <description><![CDATA[<h2 id="🤔-왜-postgresql을-정리하게-됐나">🤔 왜 PostgreSQL을 정리하게 됐나</h2>
<p>Spring 프로젝트를 진행하면서 데이터베이스로 PostgreSQL을 사용하게 되었는데,<br>막상 사용하다 보니 <strong>“PostgreSQL이 정확히 뭐지?”</strong>라는 질문에 명확하게 답하기가 어려웠다.<br>그래서 PostgreSQL의 개념과 특징을 간단하게 정리해보려고 한다.</p>
<hr>
<h2 id="📌-postgresql-한-줄-정의">📌 PostgreSQL 한 줄 정의</h2>
<blockquote>
<p><strong>PostgreSQL은 오픈소스 객체-관계형 데이터베이스 관리 시스템(ORDBMS)이다.</strong></p>
</blockquote>
<hr>
<h2 id="🧩-postgresql이란">🧩 PostgreSQL이란?</h2>
<p>PostgreSQL은 데이터를 <strong>테이블 형태로 저장하고 관리하는 관계형 데이터베이스(RDBMS)</strong>이면서,<br>객체 개념까지 확장한 <strong>객체-관계형 데이터베이스(ORDBMS)</strong>이다.</p>
<ul>
<li>오픈소스</li>
<li>무료 사용 가능</li>
<li>대규모 서비스에서도 안정적으로 사용 가능</li>
</ul>
<hr>
<h2 id="🏗️-postgresql의-주요-특징">🏗️ PostgreSQL의 주요 특징</h2>
<h3 id="1️⃣-오픈소스--무료">1️⃣ 오픈소스 &amp; 무료</h3>
<ul>
<li>라이선스 비용 없음  </li>
<li>커스터마이징 가능  </li>
<li>커뮤니티가 활발함</li>
</ul>
<hr>
<h3 id="2️⃣-표준-sql을-잘-지원">2️⃣ 표준 SQL을 잘 지원</h3>
<p>PostgreSQL은 SQL 표준을 충실히 따르는 DB 중 하나다.</p>
<p>예시:</p>
<pre><code>SELECT * FROM member WHERE id = 1;</code></pre><p>기본적인 SQL 문법은 다른 DB(MySQL, Oracle 등)와 거의 동일하다.</p>
<hr>
<h3 id="3️⃣-강력한-확장성">3️⃣ 강력한 확장성</h3>
<p>PostgreSQL은 <strong>확장 기능(extension)</strong>을 통해 기능을 추가할 수 있다.</p>
<p>대표적인 예:</p>
<ul>
<li>PostGIS: 공간 데이터(지도, 좌표) 처리</li>
<li>사용자 정의 함수, 타입 추가 가능</li>
</ul>
<hr>
<h3 id="4️⃣-트랜잭션과-무결성-보장">4️⃣ 트랜잭션과 무결성 보장</h3>
<p>PostgreSQL은 <strong>ACID 트랜잭션</strong>을 완벽하게 지원한다.</p>
<ul>
<li>데이터 정합성 보장  </li>
<li>장애 상황에서도 안정적인 복구 가능</li>
</ul>
<hr>
<h3 id="5️⃣-다양한-데이터-타입-지원">5️⃣ 다양한 데이터 타입 지원</h3>
<p>기본적인 타입 외에도 다양한 타입을 지원한다.</p>
<ul>
<li>JSON / JSONB  </li>
<li>배열(Array)  </li>
<li>UUID  </li>
<li>사용자 정의 타입</li>
</ul>
<p>복잡한 데이터 구조를 다루기 좋다.</p>
<hr>
<h2 id="🆚-postgresql-vs-mysql-간단-비교">🆚 PostgreSQL vs MySQL (간단 비교)</h2>
<table>
<thead>
<tr>
<th>항목</th>
<th>PostgreSQL</th>
<th>MySQL</th>
</tr>
</thead>
<tbody><tr>
<td>라이선스</td>
<td>오픈소스</td>
<td>오픈소스</td>
</tr>
<tr>
<td>SQL 표준</td>
<td>매우 충실</td>
<td>비교적 단순</td>
</tr>
<tr>
<td>확장성</td>
<td>매우 강력</td>
<td>제한적</td>
</tr>
<tr>
<td>복잡한 쿼리</td>
<td>강점</td>
<td>상대적으로 약함</td>
</tr>
</tbody></table>
<p>👉 복잡한 쿼리, 확장성, 데이터 무결성이 중요하면 PostgreSQL이 많이 선택된다.</p>
<hr>
<h2 id="🧠-postgresql을-언제-쓰면-좋을까">🧠 PostgreSQL을 언제 쓰면 좋을까?</h2>
<ul>
<li>데이터 무결성이 중요한 서비스  </li>
<li>복잡한 쿼리나 통계 처리가 필요한 경우  </li>
<li>JSON, 공간 데이터 등 다양한 데이터 타입을 사용하는 경우  </li>
<li>장기적으로 확장 가능한 구조가 필요한 경우</li>
</ul>
<hr>
<h2 id="⚠️-처음-사용할-때-헷갈렸던-점">⚠️ 처음 사용할 때 헷갈렸던 점</h2>
<ul>
<li><code>schema</code> 개념이 익숙하지 않았다  </li>
<li>기본 DB인 <code>postgres</code>와 실제 사용하는 DB의 차이를 몰랐다  </li>
<li>권한 설정이 MySQL보다 조금 까다롭게 느껴졌다</li>
</ul>
<p>👉 하지만 구조를 이해하고 나니 오히려 명확하게 느껴졌다.</p>
<hr>
<h2 id="✅-한-줄-요약">✅ 한 줄 요약</h2>
<blockquote>
<p><strong>PostgreSQL은 안정성, 확장성, 표준 SQL 지원이 강력한 오픈소스 객체-관계형 데이터베이스이다.</strong></p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[Spring-Plus 트러블 슈팅]]></title>
            <link>https://velog.io/@h_ani99/Spring-Plus-%ED%8A%B8%EB%9F%AC%EB%B8%94-%EC%8A%88%ED%8C%85</link>
            <guid>https://velog.io/@h_ani99/Spring-Plus-%ED%8A%B8%EB%9F%AC%EB%B8%94-%EC%8A%88%ED%8C%85</guid>
            <pubDate>Fri, 21 Mar 2025 04:49:36 GMT</pubDate>
            <description><![CDATA[<h2 id="querydsl-사용-시-qclass-생성-문제">QueryDSL 사용 시 QClass 생성 문제</h2>
<p>프로젝트를 진행 하는 과정에서 QueryDs을 사용해서 일정 조회 기능을 구현하는 과정에서
QClass가 생성이 안되는 문제가 발생하였다.</p>
<p><img src="https://velog.velcdn.com/images/h_ani99/post/19583eb9-7379-4dd7-af3f-537a9bb4a140/image.png" alt="">
의존성을 추가하고 빌드를 하여도 QueryDSL 의존성 추가가 안되는 모습이다.
의존성 추가가 안되니 당연히 QClass도 자동으로 생성이 안되고 있었다.</p>
<pre><code>  // QueryDSL
    implementation &#39;com.querydsl:querydsl-jpa:5.0.0:jakarta&#39;
    annotationProcessor &quot;com.querydsl:querydsl-apt:${dependencyManagement.importedProperties[&#39;querydsl.version&#39;]}:jakarta&quot;
    annotationProcessor &quot;jakarta.annotation:jakarta.annotation-api&quot;
    annotationProcessor &quot;jakarta.persistence:jakarta.persistence-api&quot;</code></pre><br/>

<p>다음과 같이 의존성을 추가하고 빌드를 하니 </p>
<p><img src="https://velog.velcdn.com/images/h_ani99/post/186a7407-ab74-48e3-9bac-065f2a3ea28e/image.png" alt=""><img src="https://velog.velcdn.com/images/h_ani99/post/d06bc9bf-f849-4035-a60d-510abdb27703/image.png" alt=""></p>
<p>문제없이 의존성 추가가 됐고 QClass도 생성이 잘 되어있는 것을 확인할 수 있었다.
<br/>
<br/></p>
<h2 id="aws를-이용한-배포-문제">AWS를 이용한 배포 문제</h2>
]]></description>
        </item>
        <item>
            <title><![CDATA[스프링 JPA로 일정 관리 앱 만들기]]></title>
            <link>https://velog.io/@h_ani99/%EC%8A%A4%ED%94%84%EB%A7%81-JPA%EB%A1%9C-%EC%9D%BC%EC%A0%95-%EA%B4%80%EB%A6%AC-%EC%95%B1-%EB%A7%8C%EB%93%A4%EA%B8%B0</link>
            <guid>https://velog.io/@h_ani99/%EC%8A%A4%ED%94%84%EB%A7%81-JPA%EB%A1%9C-%EC%9D%BC%EC%A0%95-%EA%B4%80%EB%A6%AC-%EC%95%B1-%EB%A7%8C%EB%93%A4%EA%B8%B0</guid>
            <pubDate>Thu, 13 Feb 2025 02:16:28 GMT</pubDate>
            <description><![CDATA[<p>스프링 JPA를 사용해서 일정 관리 프로젝트를 진행하였다.</p>
<h2 id="필수-과제">필수 과제</h2>
<h3 id="lv-1-일정-crud">Lv 1. 일정 CRUD</h3>
<p>일정 관리에는 작성 유저명,할일 제목,할일 내용,작성일,수정일이 필요하다.
작성일과 수정일은 강의에서 배운 내용대로 BaseEntity클래스를 작성하여
이를 상속받아 공통적으로 관리했다.</p>
<h3 id="lv-2-유저-crud">Lv 2. 유저 CRUD</h3>
<p>유저 관리에는 유저명,이메일,작성일,수정일이 필요하다.
작성일과 수정일은 마찬가지로 BaseEntity를 상속받아 공통적으로 관리한다.</p>
<h3 id="lv-3-회원가입">Lv 3. 회원가입</h3>
<p>회원가입을 하기 위해서는 이름,이메일,비밀번호를 작성해야한다.
이때 이메일은 unique해야 하며 비밀번호는 데이터베이스에 저장될 때
암호화되어 저장되어야 한다.
이 조건들은 도전과제에서 구현한다.</p>
<h3 id="lv-4-로그인">Lv 4. 로그인</h3>
<p>로그인은 세션을 활용해 구현한다.
사용자는 자신의 이메일과 비밀번호를 입력하여 로그인에 성공하면
세션을 발급받게 되고 이는 게시물과 댓글을 작성,삭제,수정할 때
발급받은 세션이 자동으로 넘어가 권한을 확인한다.(인가)</p>
<h2 id="도전과제">도전과제</h2>
<h3 id="lv-5-다양한-예외처리-적용하기">Lv 5. 다양한 예외처리 적용하기</h3>
<p>Validation을 활용해 예외처리를 하였다.
찾아보니 우선 요청을 보낼 RequestDto에서 조건을 설정해줘야 했다.
@NotBlank 어노테이션을 사용하여 필수적으로 입력값을 작성하도록 하였고
@Email 어노테이션을 통해 이메일 형식을 검증했다.</p>
<p>RequestDto에서 어노테이션을 붙인다고 끝나는게 아니라 controller에서
이 예외들을 처리해줘야 했다.
이 부분이 익숙하지 않았지만 구글링을 통해 해결할 수 있었다.</p>
<h3 id="lv-6-비밀번호-암호화">Lv 6. 비밀번호 암호화</h3>
<p>사용자가 회원가입을 하게 되면 사용자 정보가 데이터베이스에 저장된다.
하지만 이때 사용자의 비밀번호는 암호화 되지 않은 상태로 그대로 저장되게 된다.
이는 이후에 보안상 큰 문제를 초래할 수 있다.
이를 방지하고자 사용자의 비밀번호는 반드시 암호화하여 저장되어야 한다.
비밀번호 암호화는 PasswordEncoder를 사용하여 암호화한다.
<br/></p>
<pre><code>implementation &#39;at.favre.lib:bcrypt:0.10.2&#39;</code></pre><p>build.gradle 에 다음과 같은 의존성을 추가한다.</p>
<pre><code>import at.favre.lib.crypto.bcrypt.BCrypt;
import org.springframework.stereotype.Component;

@Component
public class PasswordEncoder {

    public String encode(String rawPassword) {
        return BCrypt.withDefaults().hashToString(BCrypt.MIN_COST, rawPassword.toCharArray());
    }

    public boolean matches(String rawPassword, String encodedPassword) {
        BCrypt.Result result = BCrypt.verifyer().verify(rawPassword.toCharArray(), encodedPassword);
        return result.verified;
    }
}</code></pre><p>config 패키지에 다음과 같이 코드를 작성하면 
비밀번호는 암호화되어 데이터베이스에 저장된다.</p>
<h3 id="lv-7-댓글-crud">Lv 7. 댓글 CRUD</h3>
<p>사용자는 생성된 일정에 댓글을 작성할 수 있다.
댓글은 댓글내용,작성일,수정일,유저 고유 식별자, 일정 고유 식별자가 필요하다.
댓글에 유저와 일정 정보가 포함되도록 하기 위해서
사용자와 일정에 다대일 연관관계를 설정하였다.</p>
<h3 id="어려웠던-점이나-느낀점">어려웠던 점이나 느낀점</h3>
<p>이번 과제를 진행하면서 JPA의 동작을 더 잘 이해할 수 있게 되었다.
기본적인 CRUD구현은 이제 쉽게 할 수 있게 되었다.
대댓글 기능을 이전에 구현해본적이 있어 이번에도 대댓글 기능을 구현하려고 했으나
시간 관계상 구현하지 못했다.
대댓글 기능을 구현하기 위해서는 대댓글(자식 댓글)은 상위댓글(부모 댓글)의 id가 필요하다.
이후에 대댓글 기능도 추가해봐야겠다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[키오스크 과제 트러블 슈팅]]></title>
            <link>https://velog.io/@h_ani99/%ED%82%A4%EC%98%A4%EC%8A%A4%ED%81%AC-%EA%B3%BC%EC%A0%9C-%ED%8A%B8%EB%9F%AC%EB%B8%94-%EC%8A%88%ED%8C%85</link>
            <guid>https://velog.io/@h_ani99/%ED%82%A4%EC%98%A4%EC%8A%A4%ED%81%AC-%EA%B3%BC%EC%A0%9C-%ED%8A%B8%EB%9F%AC%EB%B8%94-%EC%8A%88%ED%8C%85</guid>
            <pubDate>Mon, 20 Jan 2025 02:40:10 GMT</pubDate>
            <description><![CDATA[<p>이번에는 햄버거,디저트,음료를 주문하는 키오스크 과제를 진행해보았다.</p>
<h3 id="lv1-기본적인-키오스크를-프로그래밍">LV1 기본적인 키오스크를 프로그래밍</h3>
<p>Scanner를 활용하여 조건문,반복문을 통해
종료버튼을 누르기 전까지 제시된 햄버거 메뉴를 고른다.</p>
<h3 id="lv2-객체-지향-설계를-적용해-햄버거-메뉴를-클래스로-관리">LV2 객체 지향 설계를 적용해 햄버거 메뉴를 클래스로 관리</h3>
<p>햄버거 메뉴를 MenuItem클래스로 관리한다.
List를 활용하여 여러 메뉴들을 관리한다.</p>
<h3 id="lv3-객체-지향-설계를-적용해-순서-제어를-클래스로-관리">LV3 객체 지향 설계를 적용해 순서 제어를 클래스로 관리</h3>
<p>Kiosk클래스를 통해 프로그램 제어를 관리한다.
Kiosk클래스 내에서 사용자의 입력을 처리하고 메뉴를 관리한다.
유효하지 않은 입력에 대한 예외도 처리한다.</p>
<h3 id="lv4-음식-메뉴와-주문-내역을-클래스-기반으로-관리">LV4 음식 메뉴와 주문 내역을 클래스 기반으로 관리</h3>
<p>버거,음료,디저트를 관리하기 위해 별도의 클래스를 작성하고
각각의 클래스들은 MenuItem을 상속받는다.
버거,음료,디저트 클래스는 각각의 클래스의 용도에 맞는 최소한의
필드만 정의해두고 공통적인 필드는 MenuItem에 정의한다.</p>
<h3 id="lv5-캡슐화-적용하기">LV5 캡슐화 적용하기</h3>
<p>Getter,Setter 메서드를 사용해 데이터를 관리하고 접근지정자를 사용하여 캡슐화를
적용한다.</p>
<p>LV5까지 진행과정에서는 매우 순조롭게 진행이 되었다.
버거,음료,디저트에서 공통적인 기능들을 묶어 MenuItem클래스에 정의하니
코드가 훨씬 더 간결해지고 유지보수도 용이해졌다.</p>
<h3 id="도전과제">도전과제</h3>
<p>도전 과제에서는 장바구니 기능과 구매하기 기능을 추가하고
마지막에는 총 가격에서 할인까지 적용해야한다.</p>
<p>우선 할인정보를 관리하기 위해 따로 Enum클래스를 작성하여
할인 대상과 할인율을 관리했다.</p>
<p>Kiosk클래스에서 장바구니를 구현하기 위해 MenuItem타입의 리스트를 정의하였다.
이를 통해 MenuItem타입의 메뉴들(버거,디저트,음료)들을 저장할 수 있었다.</p>
<p>각각의 로직들은 모두 Kiosk내에서 별도의 메서드로 작성하였다.</p>
<p>이번 과제에서는 데이터의 흐름을 천천히 생각해보고 순서대로 진행해보니
어려운 부분이 없었다.
프로그램 내에서 데이터의 흐름,제어를 그려보고 이를 토대로 코드를 작성해보는 좋은 경험이 되었다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[CH2 계산기 과제 구현 트러블슈팅]]></title>
            <link>https://velog.io/@h_ani99/CH2-%EA%B3%84%EC%82%B0%EA%B8%B0-%EA%B3%BC%EC%A0%9C-%EA%B5%AC%ED%98%84-%ED%8A%B8%EB%9F%AC%EB%B8%94%EC%8A%88%ED%8C%85</link>
            <guid>https://velog.io/@h_ani99/CH2-%EA%B3%84%EC%82%B0%EA%B8%B0-%EA%B3%BC%EC%A0%9C-%EA%B5%AC%ED%98%84-%ED%8A%B8%EB%9F%AC%EB%B8%94%EC%8A%88%ED%8C%85</guid>
            <pubDate>Thu, 09 Jan 2025 05:52:45 GMT</pubDate>
            <description><![CDATA[<p><strong>구현 코드 깃허브 주소</strong>
<a href="https://github.com/kim-hani/CalculatorProject/tree/main">https://github.com/kim-hani/CalculatorProject/tree/main</a></p>
<p>Lv1과 Lv2는 간단한 구현이라 큰 어려움없이 진행되었다.
Lv3에서는 제네릭타입과 스트림,람다를 적용해야되는데 
익숙하지 않은 부분이라 어려움이 있었다.</p>
<p>3개의 패키지에 나눠서 과제를 진행했다.
<img src="https://velog.velcdn.com/images/h_ani99/post/bb290bd0-82a9-4a09-8ad7-163080251fe1/image.png" alt=""></p>
<p>Calculator1 -&gt; Lv1 구현
Calculator2 -&gt; Lv2 구현
Calculator3 -&gt; Lv3 구현
와 같이 패키지를 구분했다.</p>
<p>트러블 슈팅에 대한 내용은 Lv3, Calculator3 패키지에 있는 내용으로 다뤘다.
<br/></p>
<hr>
<h3 id="배경">배경</h3>
<p>ArithmeticCalculator 클래스를 설계하면서, Integer와 Double을 동시에 
처리하기 위해 제네릭 타입을 도입했다. 문제는 여기서 발생했다.
제네릭은 타입의 <strong><em>유연성을 확보</em></strong>해주지만 그 만큼 <strong><em>제약사항이 많아진다.</em></strong>
구현 과정에서 제네릭 타입의** 숫자 연산과 타입캐스팅 문제**를 발견했다.
<br/></p>
<hr>
<h3 id="발단">발단</h3>
<p><strong>1. 제네릭 타입 간 연산 불가</strong> 
제네릭 타입 변수에는 모든 타입이 올 수 있기때문에 특정 타입에만 제공하는
메서드나 기능을 사용할 수 없다.
이러한 이유로 제네릭 타입 간 +,-,/,*와 같은 사칙연산을 사용하려고 하면
오류가 발생하였다.</p>
<p><strong>2. 타입 캐스팅 문제</strong> 
클래스를 제네릭으로 선언하고 클래스 내의 메소드내에서도 제네릭을 제대로 활용해보고싶어
모든 메서드의 리턴타입,매개 변수들을 제네릭 타입으로 작성하려고 했다.
이를 위해서는 제네릭 타입 T를 Double또는 Integer로 캐스팅을 해야 하지만
제네릭에서는 이를 자동으로 처리해주지 않는다.
이러한 과정에서 코드가 복잡해지고 오류가 많아지는 문제가 발생했다.
<br/></p>
<hr>
<h3 id="전개">전개</h3>
<p><strong>1. extends Number로 타입 제한</strong> 
제네릭 타입 간 연산이 불가한 문제를 해결하기 위해 제네릭 클래스를 선언할때</p>
<pre><code>public class ArithmeticCalculator&lt;T extends Number&gt;{
    // 클래스 내용
 }</code></pre><p>와 같이 extends Number를 사용하여 T가 Integer와 Double과 같은 Number타입만
사용할 수 있도록 타입 제한을 하였다.
이를 통해 doubleValue()와 같은 메서드 사용이 가능했고 제네릭 타입을 숫자로
활용할 수 있었다.
T를 doubleValue()메소드로 타입 변환을 하여 연산을 수행하였고
OperatorType 에서 Enum을 사용하여 사칙연산을 처리했다.</p>
<hr>
<h3 id="위기">위기</h3>
<p>제네릭 타입 간 연산은 어렵지 않게 해결했다.
이제 제네릭 타입을 클래스 내의 메소드 내에서도 적극 활용해보려고 했다.
연산 결과를 저장하는 result부터 제네릭 타입으로 선언하였다.</p>
<pre><code>private ArrayList&lt;T&gt; result = new ArrayList&lt;&gt;();</code></pre><p>이후 모든 메소드의 반환타입,매개변수들을 제네릭 타입 T로 바꾸었다.
모든 코드에 에러가 발생하였다.
제네릭은 T를 자동으로 Double,Integer로 변환해주는 기능이 없어
우선 T를 Double,Integer와 같은 타입정보를 명시적으로 전달하거나
변환 로직을 따로 구현해야 했었다.
변환 로직을 따로 구현하려고 했지만 이는 코드를 굉장히 복잡하게 만들었다.
<br/></p>
<hr>
<h3 id="절정">절정</h3>
<p>변환 로직을 따로 구현하는 것은 유지보수,성능,가독성,비용면에서 너무 비효율적이라는 
판단 하에 근본적인 해결 방안으로 접근했다.
result를 Double타입으로 제한하고 메서드의 반환 타입,매개변수를 Double로 명시하였다.
실제로 두 개의 숫자와 연산자를 매핑시켜 결과를 반환하는 calculate메서드에서는
매개변수로 받는 두 개의 숫자는 제네릭 타입으로 받게하였다.
제네릭 타입으로 받은 후 doubleValue() 메소드를 사용하여 double값으로 변환했다.</p>
<pre><code> public double calculate(T n1,String op,T n2){
        OperatorType operator = OperatorType.fromOperator(op);
        double total = operator.apply(n1.doubleValue(),n2.doubleValue());
        result.add(total);
        return total;
    }</code></pre><p>연산은 항상 double로 수행하지만 입력값은 다양한 숫자 타입을 받을 수 있도록 설계하여
제네릭 타입의 장점도 살렸다.</p>
<hr>
<h3 id="결말">결말</h3>
<p><strong>제네릭 타입 간 연산 불가</strong>는 extends Number를 사용하여 타입 제한을 하여
해결하였지만 클래스 내 메소드에서 제네릭을 활용하는 부분에서 
많은 어려움을 겪었다.
메소드에서 반환타입 및 매개변수들을 모두 제네릭 타입을 사용하려고 시도했지만
이를 해결하기 위해서는 제네릭 타입을 변환해주는 로직을 따로 구현해야 했다.
이는 코드를 너무 복잡하게 만들어 가독성도 안좋아지고
비용,성능,유지보수 측면에서도 비효율적이었다.
따라서 대부분의 메소드에서 타입을 명시적으로 작성했지만 
calculate메소드 에서는 매개변수로 제네릭 타입을 받아 
제네릭 타입의 장점도 활용하였다.
이를 통해 간결하고 유지보수하기도 좋은 코드가 작성되었다.<br/>
코드를 작성할 때 우리는 항상 더 좋은 코드를 작성하고싶은 욕심이 생기지만
때로는 그러한 욕심이 비효율적인 코드를 만들 수 있다는 것을 이해하게 되었다.
산의 정상에서 조금 더 나아가면 오르막길이 아닌 내리막길이듯 
내가 작성한 코드가 최적의 상태일수도 있다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[12/31(화) TIL ]]></title>
            <link>https://velog.io/@h_ani99/1231%ED%99%94-TIL</link>
            <guid>https://velog.io/@h_ani99/1231%ED%99%94-TIL</guid>
            <pubDate>Tue, 31 Dec 2024 11:22:59 GMT</pubDate>
            <description><![CDATA[<h2 id="i-jvm">I. JVM</h2>
<p><strong>JVM</strong>은 Java Virtual Machine의 준말로 자바 가상 머신을 줄여부르는 용어이다.
우리가 작성하는 자바 소스코드(.java)는 CPU가 인식하지 못하므로 기계어로 컴파일을 해주어야 한다.
자바에서는 자바 컴파일러가 소스코드를 자바 바이트 코드(.class)로 변환하면 JVM이라는 가상 머신에서는 이 바이트코드를 알맞는 기계어로 해석하여 
<strong>자바를 OS에 종속받지 않고 독립적으로 CPU에서 인식,실행 할 수 있도록 해준다.</strong> 
즉 JVM은 실행환경에 영향받지 않고 JVM만 있으면 어디서든지 Java를 실행할 수 있다.
즉, JVM은 JAVA와 OS사이의 중개인과 같은 역할을 하는 셈이다.</p>
<h4 id="자바가-컴파일되어-실행되는-과정">자바가 컴파일되어 실행되는 과정</h4>
<ol>
<li>소스코드(.java)파일 작성</li>
<li>자바 컴파일러가 소스 코드를 바이트 코드로 변환</li>
<li>바이트 코드는 .class 확장자를 가진 파일로 저장</li>
<li>자바 실행 환경(JRE)에서 클래스 로더가 .class파일을 JVM 메모리에 로드</li>
<li>클래스 로더가 필요한 .class파일을 메모리에 적재한다.</li>
<li>이후 검증과 실행을 걸쳐 결과가 출력 된다.</li>
</ol>
<h2 id="2-기본타입과-참조-타입">2. 기본타입과 참조 타입</h2>
<blockquote>
<p>기본 타입</p>
</blockquote>
<ul>
<li>실제 값을 저장하는 공간으로 Stack영역에 저장된다.</li>
<li>기본값이 있기 때문에 null이 없다.</li>
<li>메소드 매개변수로 값을 넘겨줘도 원본값은 바뀌지 않는다.</li>
</ul>
<blockquote>
<p>참조형 타입</p>
</blockquote>
<ul>
<li>객체의 주소값을 참조하는 타입으로 배열,열거,클래스,인터페이스 등을 말한다.</li>
<li>기본형 타입을 제외한 모든 자료형은 참조형 타입임</li>
<li>빈 객체를 의미하는 null이 있을 수 있다.</li>
<li>기본자료형은 Stack에 실제 데이터값이 저장되지만 
참조자료형은 Heap에 실제 데이터값이 저장되고  Stack에는 힙 메모리의 위치값이
저장된다.</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[12/30(월) TIL]]></title>
            <link>https://velog.io/@h_ani99/1230%EC%9B%94-TIL</link>
            <guid>https://velog.io/@h_ani99/1230%EC%9B%94-TIL</guid>
            <pubDate>Mon, 30 Dec 2024 11:09:27 GMT</pubDate>
            <description><![CDATA[<h1 id="14조-코딩벌레">14조 코딩벌레</h1>
<hr>
<p><strong>1.  우리들의 1 주</strong></p>
<ul>
<li><p>우리가 한 것</p>
<ul>
<li>프로젝트 : 간단한 팀 소개 페이지 만들기</li>
<li>HTML,CSS,JS,git을 사용하여 간단한 웹 페이지를 구현</li>
</ul>
</li>
<li><p>느낀점</p>
<ul>
<li><p>김한이
짧은 시간동안 프로젝트를 진행했지만 팀원분들이 너무나 열정적이고 참여도가 높아
굉장히 재밌고 편안하게 프로젝트를 진행했습니다.
시간이 많이 없어 많은 부분을 생각하지 못하고 프로젝트를 진행한 것 같아
다음에는 좀 여유있게 더 많은 부분을 생각하며 프로젝트를 진행하고 싶습니다.<br><br></p>
</li>
<li><p>김정호<br></p>
<p>긴 과정의 첫 주차에 개념을 배우기 보다 간단한 프로젝트를 하다 보니 이 과정에 어느 정도 적응이  된 것 같습니다. <br>그리고 팀원분들이 적극적으로 프로젝트에 임하다보니 저 긴장감을  지게 된 것 같습니다. <br>강의 수강과 프로젝트를 동시에 하다보니 정신이 없었고 프로젝트에 큰  기여를 못한 것 같습니다. 다음에는 좀 더 지식을 쌓은 상태에서 프로젝트에 참여하고 싶습니다.    </p>
<br></li>
<li><p>박수진<br></p>
<p>  저희 코딩벌레 팀원분들은 프로젝트 기간동안 각자 맡은 역할을 충실히 이행하였고, 서로를 존중하고 배려하며 소통하였습니다. 짧은 기간이었지만 훌륭한 팀원분들을 만나 좋은 경험을 쌓을 수 있었습니다. 이번에 기획과 디자인 역할을 맡았는데 다음 프로젝트에서는 개발을 좀 더 중점적으로 해보고 싶습니다.<br></p>
</li>
<li><p>홍수경<br></p>
<p>  팀 프로젝트 경험도 부족하고, 웹 관련 코딩 지식도 부족한 상황에서 첫 주차에 프로젝트를 하는 것이 처음에는 겁이 많이 났었습니다. 하지만 팀원분들의 적극적인 참여와 소통에 용기를 얻게 되었고, 좋은 결과물을 냈던 것 같습니다.
  아쉬웠던 부분은 일정을 제대로 계획하지 못하여 시간에 쫓기며 개발을 하게 되었는데 다음에 팀 프로젝트를 하게 되면 일정을 체계적으로 계획하여 시간적 여유를 두고 개발을 하고 싶습니다.</p>
  <br></li>
<li><p>권은서
팀 프로젝트 경험을 쌓기 위해 들어온 내일배움캠프였는데, 시작부터 그런 프로젝트 경험을 얻을 수 있어 좋았습니다. 기획부터 시작해 역할을 분담하고, 서로 부족한 부분을 채우는 점이 큰 도움이 되었습니다. 프로젝트를 하면서 기능을 구현하다 보니 욕심이 생겼고, 더 좋은 기능을 보여주고 싶다는 생각으로 임했습니다. 단순히 보여주는 것이 화려한 것보다 사용자들이 편리하게 사용할 수 있도록 하고 싶었습니다. 하지만 그 부분을 신경 쓰지 못한 것 같아서 아쉬움이 있습니다. 다음 프로젝트는 사용자 관점에서 편리성에 중점을 둔 프로젝트를 하고 싶습니다. 그렇다고 디자인을 놓치고 싶지는 않다는 욕심도 같이 있습니다.</p>
</li>
</ul>
</li>
</ul>
<ol start="2">
<li><p>Keep</p>
<ul>
<li>디자인 및 기능 구현 부분에 대한 질문이나 의견에 대한 소통이 굉장히 원할하게 진행되었습니다.</li>
<li>모든 팀원분들이 열정적으로 참여했습니다.</li>
<li>모르는 부분,부족한 부분은 팀원들 간 서로 보완해주었습니다.</li>
<li>프로젝트를 시작하기 전에 진행 방향, 기획을 충분히 하고 프로젝트에 착수했습니다.</li>
</ul>
</li>
<li><p>Problem</p>
<ul>
<li><p>문제</p>
<ol>
<li>실행환경마다 홈페이지 화면이 제대로 나오기도 하고 사진이 잘려서 나오기도 함</li>
<li>프로젝트를 진행하며 git을 통한 협업이 부족했음<br><br></li>
</ol>
</li>
<li><p>원인<br></p>
<p>   1 :  html에 style.css를 추가적으로 적용해서 잘리는 문제가 발생함.<br></p>
<p>   2 : 프로젝트 규모가 작아 git으로 굳이 협업 시도를 하지 않음.<br></p>
</li>
<li><p>해결방안</p>
<p><br>  1 : 반응형 웹 사이트로 구성하여 모든 화면에서 개발자의 의도를 보여줄 수 있음.</p>
<p><br>  2 : 작은 규모의 프로젝트라고 하더라도 git을 사용해봐야 겠다고 느낌.</p>
</li>
</ul>
</li>
</ol>
<ol start="4">
<li><p>Try</p>
<ol>
<li><p>html,css,js에 대한 지식이 부족하여 좀 더 공부해보기.</p>
<ol>
<li>git을 많이 써보고 익숙해져보기</li>
<li>상호 간 코드 리뷰도 하며 소통을 충분히 하여 같이 성장하기.</li>
<li>해당 기술의 공식 문서를 참고해보기.</li>
</ol>
</li>
</ol>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[12/27(금) TIL]]></title>
            <link>https://velog.io/@h_ani99/1227%EA%B8%88-TIL</link>
            <guid>https://velog.io/@h_ani99/1227%EA%B8%88-TIL</guid>
            <pubDate>Fri, 27 Dec 2024 05:07:45 GMT</pubDate>
            <description><![CDATA[<h2 id="람다-표현식">람다 표현식</h2>
<p>람다 표현식은 Java 8 에 추가된 기능으로
매개변수를 받아서 값을 반환하는 짧은 코드 블록이다.
람다 표현식을 사용하면 간결하고 가독성 높은 코드를 작성할 수 있으며,
함수형 프로그래밍의 핵심 요소로 , 함수형 인터페이스와 함께 사용된다.</p>
<h2 id="람다의-기본적인-형태">람다의 기본적인 형태</h2>
<ol>
<li>매개변수가 없는 람다식<pre><code>() -&gt; {표현식
</code></pre></li>
</ol>
<p>Runnable r = () -&gt; { System.out.println(&quot;Hello, Lambda!&quot;); };</p>
<pre><code>&lt;br/&gt;


2. 하나의 매개변수가 있는 람다식</code></pre><p>(매개변수) -&gt; {표현식}</p>
<p>Consumer<String> printer = message -&gt; System.out.println(message);</p>
<pre><code>&lt;br/&gt;


3. 여러개의 매개변수가 있는 람다식</code></pre><p>(매개변수1, 매개변수2) -&gt; {표현식}</p>
<p>BiFunction&lt;Integer, Integer, Integer&gt; add = (a, b) -&gt; a + b;</p>
<pre><code>&lt;br/&gt;


4. 반환값이 있는 경우</code></pre><p>(매개변수) -&gt; { return value;}</p>
<p>// return 생략 가능
Function&lt;Integer, Integer&gt; square = x -&gt; x * x;</p>
<pre><code>&lt;br/&gt;


5. 단일식의 경우 중괄호 생략 가능</code></pre><p>Predicate<Integer> isPositive = n -&gt; n &gt; 0;</p>
<pre><code>&lt;br/&gt;

## 예시

1. 리스트의 요소 출력</code></pre><p>import java.util.ArrayList;</p>
<p>public class Main {
    public static void main(String[] args) {
        ArrayList<Integer> numbers = new ArrayList&lt;&gt;();
        numbers.add(5);
        numbers.add(2);
        numbers.add(3);</p>
<pre><code>    numbers.forEach(n -&gt; System.out.println(n));
}</code></pre><p>}</p>
<pre><code>
2. 두 수의 합 계산</code></pre><p>import java.util.function.BiFunction;</p>
<p>public class Main {
    public static void main(String[] args) {
        BiFunction&lt;Integer, Integer, Integer&gt; add = (a, b) -&gt; a + b;
        System.out.println(add.apply(5, 10)); // 출력: 15
    }
}</p>
<pre><code>
3. 조건에 따른 필터링</code></pre><p>import java.util.function.Predicate;</p>
<p>public class Main {
    public static void main(String[] args) {
        Predicate<Integer> isEven = n -&gt; n % 2 == 0;</p>
<pre><code>    System.out.println(isEven.test(4)); // true
    System.out.println(isEven.test(5)); // false
}</code></pre><p>}</p>
<pre><code>&lt;br/&gt;&lt;br/&gt;

## 반환값과 타입 추론
1. 타입 추론 
- 자바 컴파일러는 람다 표현식의 컨텍스트를 참조하여 매개변수와 반환값의 타입을 추론한다.</code></pre><p>Function&lt;Integer, Integer&gt; square = x -&gt; x * x; // 매개변수 x의 타입은 Integer로 추론</p>
<pre><code>
2. 반환값:
- 반환값이 있는 경우 , return 키워드는 선택 사항.
- 단일 문장이라면 return과 중괄호 {} 생략 가능하다.</code></pre><p>// 반환값 있음 (return 생략)
Function&lt;String, Integer&gt; length = str -&gt; str.length();</p>
<p>// 반환값 있음 (return 명시)
Function&lt;Integer, String&gt; evenOdd = n -&gt; {
    if (n % 2 == 0) return &quot;Even&quot;;
    else return &quot;Odd&quot;;
};</p>
<pre><code>&lt;br/&gt;&lt;br/&gt;

## 함수형 인터페이스란?
- 단 하나의 추상 메서드를 가지는 인터페이스
- 자바에서 람다 표현식은 반드시 함수형 인터페이스와 함께 사용된다.
- @FunctionalInterface 어노테이션을 사용하여 명시 가능
</code></pre><p>@FunctionalInterface
interface MyFunc {
    void apply(int x, int y); // 단일 추상 메서드
}</p>
<p>public class Main {
    public static void main(String[] args) {
        // 람다 표현식으로 함수형 인터페이스 구현
        MyFunc add = (a, b) -&gt; { System.out.println(a + b); };</p>
<pre><code>    // apply 메서드 호출
    add.apply(5, 10); // 출력: 15
}</code></pre><p>}</p>
<pre><code>&lt;br/&gt;
자바 내장 함수형 인터페이스
&lt;br/&gt;

| **인터페이스**  | **설명**                 | **메서드**      | **예시 람다 형태**                |
|----------------|--------------------------|----------------|-----------------------------------|
| `Consumer&lt;T&gt;`  | 매개변수를 받아 소비(출력 등) | `accept(T t)`  | `(n) -&gt; System.out.println(n)`  |
| `Function&lt;T, R&gt;` | 입력값을 받아 반환값을 생성  | `apply(T t)`   | `(x) -&gt; x * x`                  |
| `Predicate&lt;T&gt;` | 입력값을 평가(참/거짓 반환)   | `test(T t)`    | `(x) -&gt; x &gt; 10`                 |
| `Supplier&lt;T&gt;`  | 값을 반환                  | `get()`        | `() -&gt; &quot;Hello&quot;`                 |

</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[12/26(목) TIL]]></title>
            <link>https://velog.io/@h_ani99/1226%EB%AA%A9-TIL</link>
            <guid>https://velog.io/@h_ani99/1226%EB%AA%A9-TIL</guid>
            <pubDate>Thu, 26 Dec 2024 11:09:31 GMT</pubDate>
            <description><![CDATA[<h2 id="스프링과-스프링의-차이">스프링과 스프링의 차이</h2>
<p><strong>차이점1. 구성의 차이</strong></p>
<p>스프링은 애플리케이션 개발에 필요한 환경을 수동으로 구성하고 정의해야됨</p>
<p>스프링 부트는 스프링 코어와 스프링 MVC의 모든 기능을 자동으로 로드
<br/><br/></p>
<p><strong>차이점2. 내장WAS의 유무</strong></p>
<p>스프링 부트는 WAS(Wep Apllication Server)를 자체적으로 가지고 있다.</p>
<p>jar 파일만 만들면 별도로 WAS를 설정하지 않아도 애플리케이션을 실행할 수 있다.
<br/><br/></p>
<h2 id="제어의-역전ioc과-의존성-주입di">제어의 역전(IoC)과 의존성 주입(DI)</h2>
<br/>

<h2 id="제어의-역전inversion-of-control">제어의 역전(Inversion of Control)</h2>
<ul>
<li><p>제어의 역전은 프로그램의 흐름 제어 권한을 개발자가 아닌 프레임워크 또는 
컨테이너가 담당하는 것을 의미</p>
</li>
<li><p>객체를 생성하고 의존성을 설정하는 작업은 개발자가 수행했지만
IoC에서는 컨테이너가 이 역할을 수행한다.</p>
</li>
<li><p>다른 객체를 직접 생성하거나 제어하는 것이 아니라 외부에서 관리하는 객체를 가져와 사용하는 것</p>
</li>
<li><p>전통적인 방식</p>
</li>
</ul>
<pre><code class="language-java">public class Service {
    private Repository repository;

    public Service() {
        this.repository = new Repository(); // 직접 객체 생성
    }
}</code></pre>
<ul>
<li>IoC 방식</li>
</ul>
<pre><code class="language-java">public class Service {
    private Repository repository;

    public Service(Repository repository) {
        this.repository = repository; // 외부에서 주입
    }
}</code></pre>
<ul>
<li>장점<ul>
<li>객체 간의 결합도가 낮아져 코드의 유연성과 재사용성이 높아진다.</li>
<li>테스트와 유지보수가 쉬워짐</li>
<li>개발자가 핵심 로직에 집중할 수 있음<br/>

</li>
</ul>
</li>
</ul>
<h2 id="의존성-주입">의존성 주입</h2>
<ul>
<li><p>제어의 역전을 구현하기 위해 사용하는 방법</p>
</li>
<li><p>의존성 주입은 객체가 의존하는 객체를 외부에서 주입받는 방식</p>
</li>
<li><p>DI의 유형</p>
</li>
</ul>
<ol>
<li>생성자 주입</li>
</ol>
<pre><code class="language-java">public class Service {
    private Repository repository;

    public Service(Repository repository) {
        this.repository = repository;
    }
}</code></pre>
<ol start="2">
<li>세터 주입</li>
</ol>
<pre><code class="language-java">public class Service{
    private Repository repository;

    public void setRepository(Repository repository){
        this.repository = repository;
}</code></pre>
<ol start="3">
<li>필드 주입</li>
</ol>
<pre><code class="language-java">public class Service{
    @Autowired
    private Repository repository;
}</code></pre>
<p><br/><br/></p>
<h2 id="서블릿">서블릿</h2>
<h3 id="서블릿이란">서블릿이란?</h3>
<p>Java 기반의 웹 애플리케이션에서 클라이언트 요청(주로 HTTP요청)을 처리하고</p>
<p>응답을 생성하기 위해 사용되는 서버 측 컴포넌트</p>
<h2 id="서블릿의-주요-동작-원리">서블릿의 주요 동작 원리</h2>
<ol>
<li>클라이언트의 HTTP 요청이 서블릿 컨테이너에 전달됨</li>
<li>서블릿 컨테이너는 요청을 분석하여 적절한 서블릿 인스턴스를 생성하거나 
기존 인스턴스를 사용</li>
<li>서블릿이 요청을 처리하고 응답을 생성하여 클라이언트에게 반환
<br/><br/></li>
</ol>
<h2 id="컨테이너">컨테이너</h2>
<p>웹 컴포넌트를 관리하고 실행하는 소프트웨어</p>
<h2 id="컨테이너의-주요-역할"><strong>컨테이너의 주요 역할</strong></h2>
<p>컨테이너는 다음과 같은 역할을 수행합니다:</p>
<h3 id="1-웹-컴포넌트-관리">1. <strong>웹 컴포넌트 관리</strong></h3>
<ul>
<li>서블릿, JSP, 필터(Filter) 등의 생명 주기를 관리합니다.</li>
<li>컴포넌트 생성, 초기화, 요청 처리, 소멸까지 전 과정을 제어합니다.</li>
</ul>
<h3 id="2-요청-응답-처리">2. <strong>요청-응답 처리</strong></h3>
<ul>
<li>클라이언트의 HTTP 요청을 분석하고 적절한 서블릿이나 JSP로 전달합니다.</li>
<li>서블릿/JSP에서 생성된 응답 데이터를 클라이언트로 반환합니다.</li>
</ul>
<h3 id="3-http-프로토콜-지원">3. <strong>HTTP 프로토콜 지원</strong></h3>
<ul>
<li>HTTP 요청/응답 처리, 세션 관리, 쿠키 처리 등을 제공합니다.</li>
<li>HTTP 1.1, HTTPS 등 다양한 프로토콜을 지원합니다.</li>
</ul>
<h3 id="4-구성-및-배포-지원">4. <strong>구성 및 배포 지원</strong></h3>
<ul>
<li>웹 애플리케이션을 쉽게 배포하고 실행할 수 있는 환경을 제공합니다.</li>
<li><code>web.xml</code>(배포 설명자) 또는 어노테이션 기반 설정을 통해 컴포넌트를 구성할 수 있습니다.</li>
</ul>
<h3 id="5-보안-관리">5. <strong>보안 관리</strong></h3>
<ul>
<li>인증(Authentication)과 권한 부여(Authorization)를 처리합니다.</li>
<li>SSL/TLS 같은 보안 프로토콜을 지원하며, URL 기반 접근 제어를 제공합니다.</li>
</ul>
<h3 id="6-스레드-관리">6. <strong>스레드 관리</strong></h3>
<ul>
<li>클라이언트의 요청마다 스레드를 생성하거나 풀링하여 동시에 여러 요청을 처리합니다.</li>
</ul>
<h3 id="7-리소스-관리">7. <strong>리소스 관리</strong></h3>
<ul>
<li>데이터베이스 연결 풀 관리, 파일 접근, 전역 리소스 접근 등을 처리합니다.</li>
</ul>
<p><br/><br/></p>
<h2 id="스프링-부트-계층">스프링 부트 계층</h2>
<br/>

<h3 id="프레젠테이션-계층">프레젠테이션 계층</h3>
<p>HTTP요청을 받고 이 요청을 비즈니스 계층으로 전송하는 역할을 한다.</p>
<p>컨트롤러가 대표적인 프레젠테이션 계층</p>
<hr>
<h3 id="비즈니스-계층">비즈니스 계층</h3>
<p>모든 비즈니스 로직을 처리한다.</p>
<p>서비스를 만들기 위한 로직을 처리</p>
<p>서비스가 비즈니스 계층 역할</p>
<hr>
<h3 id="퍼시스턴스-계층">퍼시스턴스 계층</h3>
<p>모든 데이터베이스 관련 로직을 처리한다.</p>
<p>리포지토리가 퍼시스턴스 계층의 역할을 한다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[12/24(화) 회고록]]></title>
            <link>https://velog.io/@h_ani99/1224%ED%99%94-%ED%9A%8C%EA%B3%A0%EB%A1%9D</link>
            <guid>https://velog.io/@h_ani99/1224%ED%99%94-%ED%9A%8C%EA%B3%A0%EB%A1%9D</guid>
            <pubDate>Tue, 24 Dec 2024 12:22:19 GMT</pubDate>
            <description><![CDATA[<p>오늘 공부한 내용을 두서 없이 작성해보겠다.
JS와 스프링을 공부했는데 기초에 가까운 내용을 공부해서 아직까지는 
서로 연관성도 없고 공부글이라기 보다는
개인적인 일기에 가까운 듯하다.</p>
<h3 id="js자바스크립트란">JS(자바스크립트)란?</h3>
<p>프로그래밍 언어 중 하나로 웹 페이지의 동적인 기능을 구현하기 위해 사용된다.</p>
<p>자바스크립트는 웹 브라우저에서 실행되는 클라이언트 사이드 언어이다.</p>
<p>소스코드를 한줄 한줄 읽어나가는 형식인 인터프리터 방식으로 실행된다.</p>
<p>자바스크립트는 프론트엔드 , 백엔드 둘 다 개발이 가능하며 </p>
<p>IOS, 안드로이드 등 다양한 분야에서 널리 사용되고 있다.</p>
<p><strong>JavaScript 사용 방법</strong></p>
<ol>
<li>내부 스크립트</li>
</ol>
<p>내부스크립트는 HTML문서의 &lt;script&amp;gt 태그 안에 JS코드를 직접 작성하는 방식이다.</p>
<p>&lt;script&amp;gt 태그를 &lt;html&gt; 파일의 &lt;head&amp;gt또는 &lt;body&amp;gt안에 작성한다.</p>
<p>주로 간단한 테스트 코드 작성에 사용한다.</p>
<pre><code>
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;내부 스크립트 예제&lt;/title&gt;

&lt;/head&gt;
&lt;body&gt;
     &lt;script&gt;
        function greet() {
            alert(&quot;Hello, 내부 스크립트!&quot;);
        }
    &lt;/script&gt;

&lt;/body&gt;
&lt;/html&gt;
</code></pre><ol start="2">
<li>외부 스크립트</li>
</ol>
<p>자바스크립트 파일을 HTML과 별개인 .js 확장자의 파일로 저장한 후 불러온다.</p>
<p>HTML내에서 &lt;script&amp;gt의 src속성으로 HTML문서 위치의 기준 파일 경로를 입력해준다.</p>
<pre><code>&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
    &lt;meta charset=&quot;UTF-8&quot;&gt;
    &lt;meta name=&quot;viewport&quot; content=&quot;width=device-width, initial-scale=1.0&quot;&gt;
    &lt;title&gt;외부 스크립트 예제&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
        &lt;script src=&quot;script.js&quot;&gt;&lt;/script&gt;
    &lt;button onclick=&quot;greet()&quot;&gt;Click Me&lt;/button&gt;
&lt;/body&gt;
&lt;/html&gt;
</code></pre><p><strong>JS의 기초문법1</strong></p>
<ul>
<li>3가지 변수 선언 방법</li>
</ul>
<p>JavaScript에는 변수를 선언하는 3가지의 키워드가 있다.</p>
<p><strong>1. var</strong></p>
<p>최신 코드에서는 거의 사용하지 않으며 , let과 const로 대체된다.</p>
<p>변수가 선언된 함수 내부에서만 유효하며</p>
<p>같은 이름의 변수를 다시 선언할 수 있다.</p>
<p>변수가 선언되기 전에 해당 변수에 접근할 수 있지만 , 그 값은 undefined로 </p>
<p>초기화된다.</p>
<pre><code>function exampleVar() {
    if (true) {
        var x = 10; // var는 블록 스코프를 무시
    }
    console.log(x); // 10
}
exampleVar();

var a = 5;
var a = 10; // 중복 선언 가능
console.log(a); // 10
</code></pre><br/>


<p><strong>2. let</strong></p>
<p>변수가 선언된 블록(<code>{  }</code>) 내부에서만 유효하다.</p>
<p>함수와 블록 모두에서 사용할 수 있다.</p>
<p>같은 이름으로 변수를 다시 선언할 수 없다.</p>
<p>선언 전에 변수를 사용하려고 하면 참조 오류가 발생한다.</p>
<pre><code>function exampleLet() {
    if (true) {
        let x = 10; // let은 블록 스코프를 따름
        console.log(x); // 10
    }
    // console.log(x); // 변수 x는 블록 외부에서 유효하지 않음
}
exampleLet();

let a = 5;
// let a = 10; // 이미 선언되어 에러가 남
</code></pre><br/>

<p><strong>3. const</strong></p>
<p>한번 값을 할당하면 재할당이 불가능하다.</p>
<p>let과 동일하게 블록 (<code>{  }</code>) 내부에서만 유효하다.</p>
<p>초기화 후  변경이 불가능하지만</p>
<p>객체 혹은 배열의 속성은 수정이 가능하다.</p>
<p>선언 전에 사용하려고 하면 참조 오류가 발생한다.</p>
<pre><code>function exampleLet() {
    if (true) {
        let x = 10; // let은 블록 스코프를 따름
        console.log(x); // 10
    }
    // console.log(x); // 변수 x는 블록 외부에서 유효하지 않음
}
exampleLet();

let a = 5;
// let a = 10; // 이미 선언되어 에러가 남
</code></pre><br/>

<h3 id="스프링-하기-전-알아야-할-지식들">스프링 하기 전 알아야 할 지식들</h3>
<p>스프링을 배우기 전에 알아야 할 기본적인 지식들을 소개하겠다.</p>
<h3 id="클라이언트">클라이언트</h3>
<p>서버로 요청하는 모든 프로그램</p>
<h3 id="서버">서버</h3>
<p>클라이언트의 요청을 받아 처리하는 주체</p>
<h3 id="데이터베이스">데이터베이스</h3>
<p>데이터를 한 군데에 모아놓고 여러 사람이 사용할 목적으로 관리하는 데이터 저장소</p>
<h3 id="rdb">RDB</h3>
<p>Relational Database의 약자</p>
<p>관계형 데이터베이스</p>
<p>데이터를 행과 열로 이루어진 테이블로 관리하며 기본키를 사용해 각 행을 식별함</p>
<p>테이블 간에 관계도 지을 수 있다.</p>
<h3 id="nosql">NoSQL</h3>
<p>RDB는 저장,질의,수정,삭제가 용이하나 성능을 올리는게 쉽지않음</p>
<p>데이터베이스의 성능을 올리기 위해서는 머신의 성능을 좋게하는 스케일 업 혹은</p>
<p>머신을 여러 대로 분리하는 스케일 아웃이라는 것이 필요함</p>
<p>스케일 아웃은 데이터베이스의 분산이 필요 → 트랜잭션을 사용하면 성능이 떨어짐</p>
<ul>
<li><p>트랜잭션이란?
데이터베이스의 상태를 변화시키기 위한 작업의 단위
모든 작업이 성공적으로 완료되거나 하나라도 실패하면 전체 작업이 취소 되어야 함
다음의 조건을 만족해야한다.</p>
</li>
<li><p>원자성
  트랜잭션 내의 모든 작업이 전부 성공하거나 전부 실패해야함</p>
</li>
<li><p>일관성</p>
<p>   실행되기 전과 후의 일관성이 데이터베이스의 보장되어야함</p>
</li>
<li><p>고립성
  동시에 여러 트랜잭션이 실행될때 독립적으로 실행되는 것처럼 보장되어야 함</p>
</li>
<li><p>지속성
  성공적으로 완료되면 그 결과는 영구적으로 반영되어야 함</p>
</li>
</ul>
<h3 id="ip--port">IP &amp; Port</h3>
<p>IP : 서버의 주소</p>
<p>Port : 해당 서버의 특정 서비스 주소</p>
<h3 id="라이브러리와-프레임워크">라이브러리와 프레임워크</h3>
<p><strong>라이브러리</strong> </p>
<p>→ 애플리케이션 개발에 필요한 기능인 클래스,함수 등을 모아놓은 코드의 모음</p>
<p><strong>프레임워크</strong></p>
<p>→ 소프트웨어 개발을 수월하게 하기 위한 소프트웨어 개발환경</p>
<p><strong>즉, 프레임워크는 애플리케이션을 개발할 때 전체적인 구조를 잡기 위해 사용하는 것이고</strong></p>
<p><strong>라이브러리는 애플리케이션을 개발을 하는 과정에서 필요한 기능을 구현하기 위해 사용</strong></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[12/23 회고록(TIL)]]></title>
            <link>https://velog.io/@h_ani99/1223-%ED%9A%8C%EA%B3%A0%EB%A1%9DTIL</link>
            <guid>https://velog.io/@h_ani99/1223-%ED%9A%8C%EA%B3%A0%EB%A1%9DTIL</guid>
            <pubDate>Mon, 23 Dec 2024 12:06:32 GMT</pubDate>
            <description><![CDATA[<h3 id="1-html-css--js">1. HTML ,CSS , JS</h3>
<p>HTML,CSS,JS로 홈페이지를 만드는 것은 익숙하지 않아 당황스러웠다.
간단하게 정리해보자면</p>
<p>HTML : 웹사이트의 틀을 잡는데 사용한다.
CSS :  HTML로 틀을 잡았다면 디자인을 하는데 사용한다.
JS : 기능 구현을 하는데 사용한다.</p>
<ul>
<li><p>HTML의 요소들</p>
<ul>
<li>head<ul>
<li>HTML문서의 헤더 부분</li>
<li>head의 내용은 페이지에 표시되지 않음</li>
<li>메타데이터 및 문서 전체 타이틀을 표현하기 위한 <title>이 들어간다.</li>
</ul>
</li>
<li>body<ul>
<li>HTML 문서의 본체</li>
<li>사용자가 직접 보는 컨텐츠가 들어간다.</li>
<li>텍스트,이미지,동영상,버튼,링크 등 포함가능</li>
</ul>
</li>
<li>div<ul>
<li>콘텐츠를 묶어 그룹화 한다.<br/>

</li>
</ul>
</li>
</ul>
<ul>
<li>간단한 HTML 문서
<img src="https://velog.velcdn.com/images/h_ani99/post/ed84000f-df6f-41eb-9f5b-f29ac701efe4/image.png" alt=""></li>
</ul>
<p>해당 HTML은 head와 body로만 구성된 아주 간단한 문서이다.</p>
<p>html 태그로 문서의 시작과 끝을 알려주고</p>
<p>head에 메타데이터와 스타일을 추가한다.</p>
<p>style은 HTML 내에서 CSS를 정의하는 것으로 .mytitle클래스에 스타일을 지정할 수 있다.</p>
<p>body에서는 div로 구역을 나누고 ID,PW를 입력할 수 있는 입력창과</p>
<p>로그인하기 버튼이 추가되어 있다.</p>
<p>여기서 사용된 대부분의 코드는 외워서 사용하는 것이 아니라 필요할때마다 </p>
<p>서칭해서 사용하는 것이다.</p>
</li>
</ul>
<h3 id="2-git과-github">2. Git과 GitHub</h3>
<h4 id="git이란">Git이란?</h4>
<p>  코드 변경점 기록</p>
<p>버전(형상) 관리 도구</p>
<p>소프트웨어의 변경사항을 체계적으로 추적하고 통제하는 것</p>
<h4 id="github">GitHub?</h4>
<p>  온라인 백업 , 공유 , 협업을 하는 온라인 코드 저장소</p>
<br/>

<h4 id="git-필수-명령어">Git 필수 명령어</h4>
<ol>
<li>git init : 새로운  Git 저장소 초기화<ul>
<li>프로젝트 시작 전 딱 한번만 입력하면 됨</li>
<li>여러번 입력해도 문제가 되진 않음</li>
<li>정확한 프로젝트 폴더(경로)에서 입력해야 함</li>
<li>입력하면 .git이라는 폴더가 생김 이때부터 코드 변경을 git에서 추적<br/>

</li>
</ul>
</li>
</ol>
<ol start="2">
<li><p>git add , git commit</p>
<ul>
<li>git add index.gtml<ul>
<li>git commit -m “첫 번째 코드 작성”</li>
</ul>
</li>
<li>저장 명령어가 2개인 이유<ul>
<li>add는 저장할 파일을 지정 (Staging area에 들어감)</li>
<li>commit 실제로 저장 (실제로 repository에 들어감)</li>
<li>gid add. : 모든 변경 파일 추가</li>
</ul>
</li>
</ul>
<br/>
</li>
<li><p>git status : 저장 여부 확인하는 명령어</p>
<ul>
<li>붉은 색 : 변경은 있지만 커밋을 안함</li>
</ul>
</li>
<li><p>git log : 저장 내역을 확인하는 명령어</p>
</li>
<li><p>git push : 추가로 수정된 코드 github에 반영</p>
<ul>
<li>git push origin 브랜치명</li>
</ul>
</li>
<li><p>git clone : 분기를 만든다. 코드를 통째로 가져오기</p>
<ul>
<li>Code를 눌러서 주소 전달</li>
<li>코드를 작성할 폴더를 만들고</li>
<li>git clone github주소  . 명령어 → . 붙여야됨</li>
</ul>
</li>
<li><p>git pull : 충돌 방지 git pull 로 먼저 당겨오고 push해야됨(변경사항을 미리 가져오기)</p>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[MinMax알고리즘을 이용한 TicTacToe]]></title>
            <link>https://velog.io/@h_ani99/MinMax%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-TicTacToe</link>
            <guid>https://velog.io/@h_ani99/MinMax%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98%EC%9D%84-%EC%9D%B4%EC%9A%A9%ED%95%9C-TicTacToe</guid>
            <pubDate>Mon, 25 Sep 2023 17:33:12 GMT</pubDate>
            <description><![CDATA[<p>Tic-Tac-Toe 게임은 3*3 게임판에 두 명의 플레이어가</p>
<p>X와 O를 번갈아 두면서 3개의 동일한 무늬의 직선을 만들게 되는 쪽이</p>
<p>승자가 되는 게임이다.</p>
<p>이제 이 Tic-Tac-Toe 게임을 MinMax 알고리즘을 통해 </p>
<p>구현하는 방법을 알아보도록 하자.</p>
<h2 id="1-minmax-알고리즘">1. MinMax 알고리즘</h2>
<p>MinMax 알고리즘이란 최대 최소 전략을 사용하여 틱택토,오목,체스,바둑 등과 같은</p>
<p>턴제 게임과 같은 프로그램에서 최선의 의사결정을 하는데 사용되는 알고리즘이다.</p>
<p>상대방과 차례를 주고받는 게임에서는 우리는 상대방의 수를 예측하고</p>
<p>그 수를 기반으로 다음 수를 생각하는 것이 승리할 수 있는 가장 좋은 </p>
<p>방법일 것이다.</p>
<p>MinMax 알고리즘의 핵심이 바로 이것이다.</p>
<p>이런 턴제 게임에서 상대방이 최선의 수를 택한다는 가정하에 다음 수를 </p>
<p>예측하는 것이다.</p>
<p>상대방의 최선의 수(상대방에게 유리해지는 수)는 나의 입장에서는 최악의 </p>
<p>수이기 때문에 </p>
<h4 id="상대방의-최선의-수를-두더라도-이에-대응하여-최소한의-손실을-보는-것">&#39;<strong>상대방의 최선의 수를 두더라도 이에 대응하여 최소한의 손실을 보는 것</strong>&#39;</h4>
<p>이것이 MinMax 알고리즘의 궁극적인 목표라 할 수 있다.</p>
<p>그렇다면 MinMax 알고리즘은 어떤 방식으로 구현이 될까?</p>
<p>게임트리는 가능한 선택지들을 트리의 노드로 만들고 각각의 노드들로부터</p>
<p>또 가능한 자식 노드들이 이어지는 트리이다.</p>
<p>다음 그림과 같이 루트로부터 가능한 경우의 수들이 노드로 생성되고</p>
<p>거기서 또 파생되어서 트리가 만들어진다.</p>
<p><img src="https://velog.velcdn.com/images/h_ani99/post/ebeb40e7-0ae1-4576-aa45-88b9a3b7692f/image.png" alt=""></p>
<p>나의 차례에서는 가장 좋은 수(max)를 선택하고 상대방의 차례에서는 </p>
<p>나에게 최악의 수(min,즉 상대방에게 최선의 수)를 선택하게 된다.</p>
<h2 id="2-tic-tac-toe-구현">2. Tic-Tac-Toe 구현</h2>
<p>Tic-Tac-Toe 게임의 규칙은 다음과 같다.</p>
<ol>
<li><p>A와 B가 차례대로 번갈아가면서 수를 둔다.</p>
</li>
<li><p>Max가 선공을 가져간다. (선공은 항상 X로 시작한다.)</p>
</li>
<li><p>같은 무늬의 직선( 수직선 , 수평선 , 대각선 )을 먼저 완성하는 쪽이 승리.</p>
</li>
<li><p>제로썸 게임이다. (승자와 패자가 나뉜다.)</p>
</li>
</ol>
<p>MinMax 알고리즘을 사용하기에 플레이어들은 최선의 수를 선택한다는 가정하에</p>
<p>게임을 진행한다.</p>
<p><img src="https://velog.velcdn.com/images/h_ani99/post/1c87c6af-faae-4456-b09f-487a38c3abf7/image.png" alt=""></p>
<p>Max가 항상 X로 시작하며 후공인 Min은 O이다.</p>
<p>그림과 같이 가능한 모든 경우의 수들을 그려보며 </p>
<p>가장 아래 노드까지 탐색하며 모든 수들을 평가한다.</p>
<p>모든 경우의 수들을 평가하며 측정값을 계산한다.</p>
<p>Max가 이기는 경우 측정값은 +1 이다.
Min이 이기는 경우 측정값은 -1 이다.
비기는 경우는 0이 된다.</p>
<p><img src="https://velog.velcdn.com/images/h_ani99/post/026995cb-d71c-43bf-b334-b2494518c270/image.png" alt=""></p>
<p>Max는 항상 큰 값을 택하고 Min은 작은 값을 택한다.</p>
<p>Min은 3과 5를 비교하여 3을 택하고 2와 9를 비교하여 2를 택한다.</p>
<p>Max는 3과 2를 비교하여 3을 택한다.</p>
<p>이런 식으로 모든 수들을 비교하여 항상 최선의 수를 두도록 한다.</p>
<h2 id="3-tic-tac-toe-구현-코드">3. Tic-Tac-Toe 구현 코드</h2>
<p>Tic-Tac-Toe는 제로섬 게임이기때문에 비겼을 경우에는</p>
<p>선공을 하는 X가 이기는 것으로 구현하였다.</p>
<p>개발환경은 vsCode를 사용하였고 언어는 파이썬으로 구현했다.
<img src="https://velog.velcdn.com/images/h_ani99/post/eaa79c94-2d75-4b6e-be90-fc8bd1b02662/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/h_ani99/post/1387aa4e-941d-47fd-9acc-3d11f1c81151/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/h_ani99/post/d0b3a1f1-08cd-46ed-8fcd-aa5257cf24e0/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/h_ani99/post/c88f0b0a-7e7f-424a-81a0-a7689e9ad79e/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/h_ani99/post/0e7c3270-1c7c-49f1-8aa1-fef8919a3e87/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/h_ani99/post/af980a27-8143-43e4-97a3-e0bd5d2ca548/image.png" alt="">
<img src="https://velog.velcdn.com/images/h_ani99/post/e6258336-a7ca-4f57-9255-f5eaa5a77279/image.png" alt="">
<img src="https://velog.velcdn.com/images/h_ani99/post/9513cac6-16c2-4fef-a9e1-576bd9161439/image.png" alt="">
<img src="https://velog.velcdn.com/images/h_ani99/post/2f62cafa-fa91-439b-98d9-c5a3e593e6c2/image.png" alt=""></p>
<h2 id="참고">참고</h2>
<p><a href="https://ddddewang.tistory.com/entry/MINMAX-%EB%AF%B8%EB%8B%88%EB%A7%A5%EC%8A%A4-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98-%EC%86%8C%EA%B0%9C">미니맥스 알고리즘 소개</a>
<a href="https://aboutnlp.tistory.com/18">https://aboutnlp.tistory.com/18</a>
<a href="https://kau-algorithm.tistory.com/7">휴리스틱 알고리즘</a>
<a href="https://going-to-end.tistory.com/entry/Minimax-algorithm-%EB%AF%B8%EB%8B%88%EB%A7%A5%EC%8A%A4-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98">https://going-to-end.tistory.com/entry/Minimax-algorithm-%EB%AF%B8%EB%8B%88%EB%A7%A5%EC%8A%A4-%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98</a>
<a href="https://lordofkangs.tistory.com/204">https://lordofkangs.tistory.com/204</a>
<a href="https://ssollacc.tistory.com/43">https://ssollacc.tistory.com/43</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[WebGL 개요 및 실습]]></title>
            <link>https://velog.io/@h_ani99/WebGL-%EA%B0%9C%EC%9A%94-%EB%B0%8F-%EC%8B%A4%EC%8A%B5</link>
            <guid>https://velog.io/@h_ani99/WebGL-%EA%B0%9C%EC%9A%94-%EB%B0%8F-%EC%8B%A4%EC%8A%B5</guid>
            <pubDate>Sat, 23 Sep 2023 13:15:54 GMT</pubDate>
            <description><![CDATA[<h2 id="1-opengl이란">1. OpenGL이란?</h2>
<p>OpenGL : Open Graphics Library
컴퓨터 그래픽스를 위한 교차 플랫폼 2D 및 3D 그래픽 라이브러리다.</p>
<p>GPU를 이용하여 하드웨어 가속화를 통해 렌더링을 해
2D,3D 그래픽을 표현한다.</p>
<p>OpenGL의 성능은 CPU 보다는 GPU가 좌우하는데 그 이유가 무엇일까?</p>
<p>위에서 GPU를 이용한 하드웨어 가속화를 통해 그래픽을 표현한다고 했다.
하드웨어 가속이란 CPU가 작업을 처리하는 것이 아니라 해당 작업에 
최적화된 하드웨어(GPU)에게 작업을 맡겨 처리하는 것이다.
때문에 CPU가 직접 작업을 처리하는 것이 아니고 GPU가 처리하기때문에
성능은 CPU보다 GPU가 좌우한다.</p>
<p>우리는 OpenGL을 통해 정점을 픽셀로 변환을 할 수 있게된다.</p>
<blockquote>
<p>용어 정리</p>
</blockquote>
<p><strong>Vertex(정점)</strong>
 &nbsp;&nbsp;3차원 개체의 가장자리의 결합을 형성하는 점
 &nbsp;&nbsp;즉 , 3차원 도형을 구성하는 하나의 점</p>
<blockquote>
</blockquote>
<p> <strong>Pixel</strong>
&nbsp;&nbsp; 렌더링 후 모니터 속 이미지 혹은 비디오를 표현하는 점</p>
<h3 id="그래픽스-파이프라인">그래픽스 파이프라인</h3>
<p><img src="https://velog.velcdn.com/images/h_ani99/post/672efbae-7f88-4e49-9b3a-e975736d4aba/image.png" alt=""></p>
<p>그래픽스 파이프라인이란 3차원의 도형 혹은 이미지를 2차원 래스터 이미지로 표현하기 위한 단계적 방법을 말한다.
그 단계는 위의 그림과 같다.</p>
<p><strong>-Vertex Processer</strong>
 &nbsp;&nbsp;이 단계에서는 좌표 체계를 변환한다.
 &nbsp;&nbsp;3D도형을 2D형태로 모니터에 표현하기 위해 좌표를 변환시키는 작업을 한다.</p>
<p><strong>-Clipper and primitive assembler</strong>
&nbsp;&nbsp; 이 단계에서는 먼저 primitive assembler를 거친다.
 &nbsp;&nbsp;Vertex Processer를 통과한 좌표 정보를 바탕으로
 &nbsp;&nbsp;line,Polygon,Curve,Surface 등 어떻게 표현을 할 지 결정이 되고
 &nbsp;&nbsp;이러한 정보를 바탕으로 vertex가 수집된다.</p>
<p> &nbsp;&nbsp;Clipper에서는 Viewer에게 보이는 부분만 남기고 보이지 않는 부분은 
 &nbsp;&nbsp;처리하는 작업을 한다.
<img src="https://velog.velcdn.com/images/h_ani99/post/bef54607-5253-449d-b659-71292335785f/image.png" alt="">
 &nbsp;&nbsp;위 그림처럼 우리는 현실세계에서 전체를 볼 수 없는것과 마찬가지로
 &nbsp;&nbsp;가상카메라또한 객체의 일부밖에 볼 수 없기때문에 보이지 않는 부분은
 &nbsp;&nbsp;처리해주는 것이다.</p>
<p><strong>- Rasterizer</strong>
 &nbsp;&nbsp;위의 단계를 모두 거치고 제거되지 않은 점들에게는 color가 할당된다. Rasterizer는 각 개체의 color와 depth정보를 부여하여
 실제 화면이 보이게 한다.
<strong>- Fragment Processor</strong>
 &nbsp;&nbsp;이 단계에서는 최종적으로 표현되는 객체에 대한 정보를 구현하고 최종적으로 처리한다.
  &nbsp;&nbsp;각 pixel에 대한 복합적인 정보를 계산하고 결정하며 다양한 정보를 처리한다.</p>
<h2 id="2-webgl이란">2. WebGL이란?</h2>
<p>&nbsp;Web Graphics Library의 약자로 웹 기반의 그래픽 라이브러리이며
&nbsp;&nbsp;로우 레벨 JavaScript API이다.
&nbsp;&nbsp;WebGL은 플러그인의 사용없이 3차원 컴퓨터 그래픽스 API를 제공하는
&nbsp;&nbsp;캔버스 HTML 요소의 일부분이다.
&nbsp;&nbsp;OPenGL ES 2.0을 기반으로 하고 3차원 그래픽을 사용하기 위한
&nbsp;&nbsp;프로그래밍 인터페이스를 제공한다.</p>
<h3 id="렌더링과-캔버스">렌더링과 캔버스</h3>
<p>&nbsp;렌더링이란 3차원 공간에 객체를 2차원 화면인 하나의 장면에 바꾸어 표현하는 &nbsp;것으로 물체의 외형에 재질,조명 등의 외부 정보를 추가해
&nbsp;&nbsp;사실감있는 이미지로 표현하는 방법이다.
&nbsp;&nbsp;캔버스는 자바스크립트를 이용해서 그래픽을 그릴 수 있는 쉽고 
&nbsp;&nbsp;강력한 여러 옵션을 제공하는데 우리가 그림을 그릴 종이라고 이해하면 된다.</p>
<h3 id="셰이더란">셰이더란?</h3>
<p>&nbsp;셰이더란 3D 컴퓨터 그래픽에서 최정적으로 화면에 출력하는 
&nbsp;&nbsp;픽셀의 색을 정해주는 함수이다.
&nbsp;&nbsp;즉 셰이더는 화면에 출력할 객체의 색의 색조와 명암 등을 결정해준다.
&nbsp;&nbsp;WebGL에서는 셰이더 프로그램을 사용하여 클라이언트 시스템에 그래픽
&nbsp;&nbsp;요소를 그리는데 필요한 모든 프로그램을 작성한다.
&nbsp;&nbsp;셰이더는 GPU용 프로그램이며 정점 셰이더와 프래그먼트 셰이더, 두 가지 유형이 &nbsp;있다.</p>
<ul>
<li><p><strong>정점 셰이더(Vertex Shader)</strong>
모든 정점에서 호출되는 프로그램 코드로 각 모델링의 3D정점 위치들을 
카메라가 바라보는 화면 위치로 변환한다.
정점 변환,텍스처 좌표 생성,텍스처 좌표 변환,조명,색상 재료 적용 등을 할 수 있다.</p>
</li>
<li><p><strong>프래그먼트 셰이더(Fragment Shader)</strong>
메쉬는 여러 삼각형으로 구성되며 각 삼각형의 표면을 프래그먼트라고 한다.프래그먼트 셰이더는 모든 프로그먼트의 픽셀에서 실행되는 코드로
모든 픽셀의 최종 색상을 계산한다.</p>
<h3 id="용어-정리">용어 정리</h3>
</li>
<li><p><strong>정점(vertex)</strong>
&nbsp;3차원 개체의 가장자리의 결합을 형성하는 점
&nbsp;즉 , 3차원 도형을 구성하는 하나의 점</p>
</li>
<li><p><strong>인덱스(index)</strong>
인덱스는 정점을 식별하는 숫자값이다.
인덱스를 이용하여 WebGL의 메쉬를 그리는데 사용된다.</p>
</li>
<li><p><strong>버퍼(buffer)</strong>
데이터를 가지고 있는 WebGL의 메모리 영역</p>
</li>
<li><p><strong>메쉬(mesh)</strong>
polygon들이 모인 하나의 3차원 객체
메시는 vertices,edges,faces들이 필요하며
메시의 정점들만 메모리에 저장한다.</p>
</li>
</ul>
<h2 id="3-webgl-프로그래밍-실습">3. WebGL 프로그래밍 실습</h2>
<p><img src="https://velog.velcdn.com/images/h_ani99/post/9d6561af-ed13-447c-8c84-3b7fe24afa79/image.png" alt="">
<img src="https://velog.velcdn.com/images/h_ani99/post/5ca09f86-4ecb-41b7-80f9-eee5d059dd08/image.png" alt="">
<img src="https://velog.velcdn.com/images/h_ani99/post/b509d5f2-4926-4fa1-b073-cd35ccce716a/image.png" alt=""></p>
<p>위의 js코드를 html과 연결하여 실행한다.</p>
<p><img src="https://velog.velcdn.com/images/h_ani99/post/1a1e4831-6789-49a5-8a3d-d848581bf432/image.png" alt="">
<img src="https://velog.velcdn.com/images/h_ani99/post/3ddf9a61-ec17-420d-bdf0-4d84b6c99c6e/image.png" alt="">
결과화면은 다음과 같다.
<img src="https://velog.velcdn.com/images/h_ani99/post/b7afd404-4054-428f-ac93-3f5d5c01d242/image.png" alt=""></p>
<h2 id="참고">참고</h2>
<p><a href="https://code-masterjung.tistory.com/110">https://code-masterjung.tistory.com/110</a>
<a href="https://zzaps.tistory.com/99">https://zzaps.tistory.com/99</a>
<a href="https://velog.io/@0hyo/WebGL%EC%9D%B4%EB%9E%80">https://velog.io/@0hyo/WebGL%EC%9D%B4%EB%9E%80</a>
<a href="https://medium.com/@su_bak/opengl-%EC%9D%B4%EB%9E%80-ad19cf68c948">https://medium.com/@su_bak/opengl-%EC%9D%B4%EB%9E%80-ad19cf68c948</a>
<a href="https://zamezzz.tistory.com/13">https://zamezzz.tistory.com/13</a>
<a href="https://ko.wikipedia.org/wiki/OpenGL#">https://ko.wikipedia.org/wiki/OpenGL#</a>
<a href="https://ko.wikipedia.org/wiki/WebGL">https://ko.wikipedia.org/wiki/WebGL</a>
<a href="https://parodev.tistory.com/30">https://parodev.tistory.com/30</a>
<a href="https://parksh86.tistory.com/168">https://parksh86.tistory.com/168</a>
<a href="https://post.naver.com/viewer/postView.naver?volumeNo=35507555">https://post.naver.com/viewer/postView.naver?volumeNo=35507555</a>
<a href="https://hoanart.tistory.com/entry/Mesh%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C">https://hoanart.tistory.com/entry/Mesh%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%BC%EA%B9%8C</a>
<a href="https://rito15.github.io/posts/unity-shader-concept/">https://rito15.github.io/posts/unity-shader-concept/</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[JAVA] 패키지]]></title>
            <link>https://velog.io/@h_ani99/JAVA-%ED%8C%A8%ED%82%A4%EC%A7%80</link>
            <guid>https://velog.io/@h_ani99/JAVA-%ED%8C%A8%ED%82%A4%EC%A7%80</guid>
            <pubDate>Tue, 16 Aug 2022 13:14:02 GMT</pubDate>
            <description><![CDATA[<h2 id="ⅰ-package와-import">Ⅰ. package와 import</h2>
<h3 id="1-패키지">1. 패키지</h3>
<ul>
<li><p>패키지란 비슷한 목적으로 생성된 클래스 파일들을 모아 둔 폴더를 의미</p>
<ul>
<li>클래스를 체계적으로 관리할 수 있음</li>
</ul>
</li>
<li><p>1개의 프로젝트에 1개또는 여러개의 패키지를 생성 할 수 있다.
패키지를 아예 생성하지 않아도 문법적으로 문제 없다.</p>
</li>
<li><p>패키지가 다르면 클래스가 저장되는 경로가 분리돼 클래스명의 충돌을
방지해준다.</p>
</li>
<li><p>패키지가 있을 때는 소스크도의 첫번째 줄에 반드시 &#39;package 패키지명&#39;을 
명시해줘야함</p>
</li>
</ul>
<p><img src="https://velog.velcdn.com/images/h_ani99/post/0b2dd631-eb88-47d3-9b40-73672740f2e7/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/h_ani99/post/a76af20a-3587-4856-aa7f-46e49334a1f1/image.png" alt=""></p>
<p><strong>패키지 이름 규칙</strong></p>
<ul>
<li>숫자로 시작하거나 &#39;_&#39; 와 &#39;$&#39;를 제외한 특수문자 사용 불가</li>
<li>java로 시작하는 패키지 금지 (자바 표쥰 API에서만 사용)</li>
<li>int,static 등 자바 표준어 사용 불가</li>
<li>소문자로만 작성하는 것이 관례</li>
</ul>
<p>패키지 사용으로 클래스명의 충돌을 방지 할 수 있다고 했다.
여러 회사가 협업해 프로젝트를 진행하게 되면 클래스명이 중복될 수 있다.
이런 경우 클래스들을 통합하게 되면 문제가 발생할 수 있다.
하지만 서로 다른 패키지를 쓴다면 충돌 문제는 발생하지 않는다.
패키지명의 중복을 피하기 위해서 일반적으로 패키지명에는 
회사의 URL 주소를 사용한다. (URL 주소는 이미 유일한 값임을 보장받은 상태임)</p>
<h3 id="2-임포트">2. 임포트</h3>
<ul>
<li><p>다른 패키지 내의 클래스를 사용하기 위한 문법 요소</p>
</li>
<li><p>소스 코드상 패키지 구문 다음 줄에 위치함</p>
</li>
</ul>
<p>동일한 패키지 내의 클래스들은 자유롭게 사용 할 수 있지만 다른 패키지의 클래스들을 사용하고자 할때는 제약이 따른다.
다른 패키지의 클래스를 사용하는 방법은 크게 2가지로 나뉜다.
<br/>
<strong>방법 1</strong>)** 클래스의 풀네임 사용**</p>
<p>같은 패키지의 클래스들은 객체를 생성할 때 클래스명으로만 객체를 생성했다.</p>
<p>하지만 다른 패키지의 클래스들을 사용할 때는 
<strong>&#39;패키지명.클래스명&#39;</strong>을 명시해야한다.</p>
<p>또한 다른 패키지에서 클래스를 사용하기 위해서는 반드시 해당 클래스는
<strong>public class</strong> 로 선언되어야 한다.
<img src="https://velog.velcdn.com/images/h_ani99/post/e24ddd30-af44-48d3-9d26-9d6aaa535376/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/h_ani99/post/8fda88de-6f14-464d-bd9c-ea5714c787b1/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/h_ani99/post/afd601d1-39f5-44ec-9147-1b79d7720502/image.png" alt="">
위의 예시에서는 pack이라는 상위패키지 밑에 두개의 하위패키지 example1과
example2가 존재한다. 
이렇게 상위패키지의 하위패키지의 클래스를 사용하기 위해서는
<strong>&#39;상위패키지명.하위패키지명.클래스명&#39;</strong>을 명시해줘야 한다.
pack.example1 패키지의 클래스를 사용하기 위해 public class로 정의하였고 pack.example2 패키지에서 클래스의 풀네임을 사용하여 객체를 생성했다.
<br/>
<strong>방법 2) 임포트 사용</strong></p>
<p>&#39;import 패키지명.클래스명&#39; 을 표기하면 해당 패키지의 클래스를 사용할 수 있다.
패키지 내의 모든 클래스를 임포트하고 싶다면 &#39;import 패키지명.*&#39; 과 같이 표기하면 된다.
단,이때 임포트되는 클래스는 public class로 선언된 클래스이다.</p>
<p><img src="https://velog.velcdn.com/images/h_ani99/post/3be7610e-3e97-47f0-b5e3-58708f7e8b1e/image.png" alt="">
위와 같이 packimport라는 패키지 내에 public class로 정의된 두 개의 A,B 클래스가 있고 각각은 다음과 같이 정의되어 있다.
<img src="https://velog.velcdn.com/images/h_ani99/post/8f581f0f-b075-41a6-9034-362f5bca9439/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/h_ani99/post/98dba732-f9a9-42ff-a57a-5d862e3f1699/image.png" alt="">
이때 클래스 A만 임포트하는 경우와 한번에 두개의 클래스를 모두 임포트하는 경우를 보면 다음과 같다.
<img src="https://velog.velcdn.com/images/h_ani99/post/d364ba0e-903d-42a5-98c7-8308706c6def/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/h_ani99/post/7fbe2e65-62c8-4109-8654-8d1d80d93024/image.png" alt=""></p>
<p>다른 패키지의 클래스를 사용할 수 있는 2가지의 방법을 살펴보았는데
서로 다른 패키지를 모두 임포트한 상태에서 이름이 같은 클래스를 사용하는 상황.
즉, import abc.A 와 import bcd.A 를 사용한다고 생각해보면
당연히 사용할 수 없다.
이럴때는 방법1을 사용해야한다.
<img src="https://velog.velcdn.com/images/h_ani99/post/d499a81c-e927-4d13-b4ab-b7bc6e9f4c22/image.png" alt=""></p>
<p>또한 다음과 같이 packimport 안에 lowpack이라는 하위패키지가 존재할때,
packimport패키지를 *기호를 사용하여 임포트한다고해서 lowpack의 클래스까지 임포트 되는것이 아니라 A,B클래스만 임포트된다.</p>
<h2 id="ⅱ-클래스패스">Ⅱ. 클래스패스</h2>
<h3 id="1-클래스-패스란">1. 클래스 패스란?</h3>
<p>클래스패스란 클래스를 찾기위한 경로이다. JVM이 프로그램을 실행할 때 
클래스 파일을 찾는 데 기준이 되는 파일 경로를 말한다.
소스 코드(.java)를 컴파일하게 되면 소스 코드는 
바이트 코드(자바 가상 머신이 이해할 수 있는 코드/ .class)로 변환된다.
 java runtime(java 또는 jre)으로 이 .class 파일에 포함된 명령을 실행하려면, 이 파일을 찾을 수 있어야 한다. .class 파일을 찾을 때, classpath에 지정된 경로를 사용한다.</p>
<p>classpath는 .class 파일이 포함된 디렉토리와 파일을 콜론(;)으로 구분한 목록이다.</p>
<p>이 classpath 를 지정하기 위한 두 가지 방법이 있다.</p>
<ul>
<li>CLASSPATH 환경 변수 사용</li>
<li>java runtime에 -classpath 옵션 사용</li>
</ul>
<h3 id="2-classpath-환경-변수-사용">2. CLASSPATH 환경 변수 사용</h3>
<p>시스템 속성에서 환경 변수를 통해 지정 가능하다.</p>
<p><img src="https://velog.velcdn.com/images/h_ani99/post/0e611f6a-55b6-4b5a-b233-d96f1c6928d2/image.png" alt=""></p>
<p><img src="https://velog.velcdn.com/images/h_ani99/post/3e34dc97-da35-4648-8fa9-7ecfbdb8e99c/image.png" alt=""></p>
<p>JVM이 시작될 때 JVM의 클래스 로더는 이 환경 변수를 호출한다. 
환경 변수에 설정되어 있는 디렉토리가 호출되면 해당 디렉토리에 있는 클래스들을 
먼저 JVM에 로드한다.
따라서 CLASSPATH 환경 변수에는 필스 클래스들이 위치한 디렉토리를 등록하도록 한다.</p>
<h3 id="3-java-runtime에--classpath-옵션-사용">3. java runtime에 -classpath 옵션 사용</h3>
<p>-classpath는 컴파일러가 컴파일러가 컴파일 하기 위해서 필요로 하는 참조할 클래스 파일들을 찾기 위해서 컴파일 시 파일 경로를 지정해주는 옵션이다.
-cp라고 써도 된다.</p>
<p>예컨데,
Hello.java 파일이 C:\Java 디렉토리에 존재하고,
필요한 클래스 파일들이 C:\Java\Engclasses 에 위치한다면
javac -classpath CL\Java\EngClasses C:\Java\Hello.java로 해주면 된다.</p>
<p>만약 참조할 클래스 파일들이 그 외의 다른 디렉터리, 그리고 현 디렉토리에도 존재한다면,
 javac -classpath .;C:\Java\Engclasses;C;\Java\Korclasses C:\Java\Hello.java</p>
<p>로 해주면 된다.
위와 같이 세미콜론으로 구분해줄 수 있다.
(.은 현 디렉토리, ..은 현 디렉토리에서 상위 디렉토리를 의미한다.)</p>
<h2 id="ⅲ-접근-지정자">Ⅲ. 접근 지정자</h2>
<p>접근 지정자는 말 그대로 클래스,필드,메서드,생성자 등에 접근 범위를 지정해주는 문법 요소이다.
접근 지정자는 멤버와 생성자에 붙어 있을 때와 클래스 자체에 붙어 있을 때를 
나누어 생각해야 한다.</p>
<h3 id="1-멤버-및-생성자의-접근-지정자">1) 멤버 및 생성자의 접근 지정자</h3>
<p>멤버 및 생성자에는 
<strong>public, protected, default(또는 package), private</strong> 라는 4가지 종류의 접근 지정자를 사용 할 수 있다.</p>
<blockquote>
</blockquote>
<p>public : 동일 패키지의 모든 클래스 + 다른 패키지의 모든 클래스에서 사용 가능
protected : 동일 패키지의 모든 클래스 + 다른 패키지의 자식 클래스에서 사용가능
default : 동일 패키지의 모든 클래스에서 사용 가능
private : 동일 클래스에서만 사용 가능</p>
<p><img src="https://velog.velcdn.com/images/h_ani99/post/0de6ae0b-a875-4c7c-a756-8ac9c0f21775/image.png" alt=""></p>
<h3 id="2-클래스의-접근-지정자">2) 클래스의 접근 지정자</h3>
<p>클래스에는 public 혹은 default 접근 지정자만 사용 가능하다.
위의 import 부분에서 public class로만 선언된 클래스만 임포트가 가능하다고 했다.</p>
<p>즉, public 으로 선언된 클래스만 다른 패키지에서 임포트하여 사용가능하고 
default지정자가 붙은 클래스는 다른 패키지에서 임포트가 불가능하다.</p>
<p>또한 클래스의 생성자를 직접 정의하지 않았을때 컴파일러가 자동으로 추가해주는데 이때 자동으로 추가되는 생성자의 접근 지정자는
클래스의 접근 지정자에 따라 결정된다.</p>
<p>클래스가 public이면 자동으로 추가되는 생성자의 접근 지정자도 public이며 
클래스가 default이면 자동으로 추가되는 생성자의 접근 지정자도 default 이다.</p>
<p>생성자를 직접 정의할때는 클래스의 접근 지정자와 다르게 접근 지정자를 지정할 수 있다.</p>
<h2 id="참고자료">참고자료</h2>
<p>Do it! 자바 완전 정복</p>
<p><a href="https://scshim.tistory.com/221">https://scshim.tistory.com/221</a></p>
<p><a href="https://doozi0316.tistory.com/entry/JAVA-7%EC%A3%BC%EC%B0%A8-%ED%8C%A8%ED%82%A4%EC%A7%80-package-import-classpath">https://doozi0316.tistory.com/entry/JAVA-7%EC%A3%BC%EC%B0%A8-%ED%8C%A8%ED%82%A4%EC%A7%80-package-import-classpath</a></p>
<p><a href="https://kils-log-of-develop.tistory.com/430#%ED%81%B4%EB%9E%98%EC%8A%A4%ED%8C%A8%EC%8A%A4">https://kils-log-of-develop.tistory.com/430#%ED%81%B4%EB%9E%98%EC%8A%A4%ED%8C%A8%EC%8A%A4</a></p>
<p><a href="https://effectivesquid.tistory.com/entry/%EC%9E%90%EB%B0%94-%ED%81%B4%EB%9E%98%EC%8A%A4%ED%8C%A8%EC%8A%A4classpath%EB%9E%80">https://effectivesquid.tistory.com/entry/%EC%9E%90%EB%B0%94-%ED%81%B4%EB%9E%98%EC%8A%A4%ED%8C%A8%EC%8A%A4classpath%EB%9E%80</a></p>
<p><a href="https://velog.io/@codename_hee/JAVA-%EC%8A%A4%ED%84%B0%EB%94%94-5%EC%A3%BC%EC%B0%A8-%ED%81%B4%EB%9E%98%EC%8A%A4">https://velog.io/@codename_hee/JAVA-%EC%8A%A4%ED%84%B0%EB%94%94-5%EC%A3%BC%EC%B0%A8-%ED%81%B4%EB%9E%98%EC%8A%A4</a></p>
]]></description>
        </item>
    </channel>
</rss>