<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>kimy_j_.log</title>
        <link>https://velog.io/</link>
        <description>나만의 방식을 찾아가는 신입신입 개발자 </description>
        <lastBuildDate>Fri, 01 Sep 2023 07:35:46 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>kimy_j_.log</title>
            <url>https://velog.velcdn.com/images/kimy_j_/profile/835b3b76-822f-42ec-92a3-5f92b49fddfb/image.jpeg</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. kimy_j_.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/kimy_j_" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[HTTP 웹 기본 지식]]></title>
            <link>https://velog.io/@kimy_j_/HTTP-%EC%9B%B9-%EA%B8%B0%EB%B3%B8-%EC%A7%80%EC%8B%9D</link>
            <guid>https://velog.io/@kimy_j_/HTTP-%EC%9B%B9-%EA%B8%B0%EB%B3%B8-%EC%A7%80%EC%8B%9D</guid>
            <pubDate>Fri, 01 Sep 2023 07:35:46 GMT</pubDate>
            <description><![CDATA[<p><strong>IP(Internet Protocol)</strong></p>
<ul>
<li>지정한 IP주소에 데이터 전달 </li>
<li>패킷 이라는 통신 단위로 데이터 전달 </li>
</ul>
<p>*<em>단점 *</em></p>
<ul>
<li>패킷을 받을 대상이 없거나 서비스 불능 상태여도 패킷 전송 </li>
<li>비신뢰성 </li>
<li>같은 IP를 사용하는 서버에서 통신하는 애플리케이션이 둘 이상이면 구분 하기 어려움 </li>
</ul>
<p>*<em>TCP(Transmission Control Protocol) *</em></p>
<ul>
<li>연결 지향 TCP2 way handshake (가상 연결 - 노드가 정해지는 것은 아님) </li>
<li>데이터 전달 보증 </li>
<li>순서 보장 </li>
<li>IP의 단점을 거의 보안 하였다 </li>
<li>대신 개발자가 최적화를 위해 기능 재조립하기에는 알맞지 않음 완성형에 가깝기 때문에</li>
</ul>
<p><strong>UDP(User Datagram Protocol)</strong></p>
<ul>
<li>IP와 거의 비슷 </li>
<li>차이점은 PORT 체크섬 정도가 추가 </li>
<li>데이터 전달의 순서가 보장되지 않지만 단순하고 빠름 </li>
<li>*<em>TCP가 재조립하기 어렵다면 UDP는 하얀 도화지 같아서 최적화 하기 위해 재조립하기 알맞다 *</em></li>
</ul>
<p>*<em>DNS(Domain Name System) *</em></p>
<ul>
<li>도메인 명을 IP주소로 변환해준다 </li>
</ul>
<p><img src="https://velog.velcdn.com/images/kimy_j_/post/99e6f307-d31e-43ed-86da-f204ca4c8eb8/image.png" alt="">
*<em>URL - 위치, URN - 이름 *</em>
*위치는 변할 수 있지만 이름은 변할 수 없다 </p>
<p>*URN 이름만으로 실제 리소스를 찾을 수 있는 방법이 보편화 되지 않음 </p>
<p><strong>URI(Uniform Resource Identifier)</strong></p>
<blockquote>
<p>Uniform - 리소스 식별하는 통일된 방식
Resource - 자원 URI로 식별할 수 있는 모든 것 (제한 없음)
Identifier - 다른 항목과 구분하는데 필요한 정보</p>
</blockquote>
<blockquote>
<p>*<em>Stateful , stateless 차이 *</em>
상태 유지 : 중간에 다른 점원으로 바뀌면 안된다 
(중간에 다른 점원으로 바뀔 때 산태 정보를 다른 점원에게 미리 알려줘야 한다 
무상태 : 중간에 다른 점원으로 바뀌어도 된다 
갑자기 고객이 증가해도 점원을 대거 투입할 수 있다 
갑자기 클라이언트 요텅이 증가해도 서버를 대거 투입할 수 있다 
무상태는 응답 서버를 쉽게 바꿀 수 있다 -&gt; 무한한 서버 증설 가능 </p>
</blockquote>
<p>Stateful은 서버가 상태를 유지하기 때문에 중간에 서버가 바뀌면 안됨 
stateless은 서버가 상태를 가지고 있기보다는 클라이언트 쪽에서 가지고 있어 대량의 서버가 투입이 되도 상관이 없다 
*<em>상태유지는 최소한만 사용 *</em></p>
<p>리소스 작성 시 
예 ) 멤버 조회 -&gt; members(O) selectMember(X)
리소스만 작성하고 행위는 http메소드로 처리해야한다 </p>
<p><strong>HTTP 메서드 종류</strong></p>
<p>GET - 리소스 조회 , 메시지 바디를 이용해서 데이터를 전달할 수 있지만 지원하지 않는 곳이 많아 권장하지 않음 
POST - 요청 데이터 처리 , 메시지 바디를 통해 서버로 요청 데이터 전달 
PUT - 리소스를 대체 , 클라리언트가 리소스 위치를 알고 URI 지정 
PATCH - 리소스 부분 변경 
DELETE - 리소스 삭제 </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[RDBMS]]></title>
            <link>https://velog.io/@kimy_j_/RDBMS</link>
            <guid>https://velog.io/@kimy_j_/RDBMS</guid>
            <pubDate>Wed, 02 Aug 2023 05:29:18 GMT</pubDate>
            <description><![CDATA[<p>데이터 베이스 
-&gt; 구조화된 데이터들의 집합 
관계형 데이터 베이스 
-&gt; 데이터들을 2차원 배열과 같은 테이블에 저장하고 관리
-&gt; 관계형 데이터에서는 반드시 Primary Key 가 존재해야 한다</p>
<p>식별자
-&gt; 하나의 레코드를 고유하게 구분할 수 있는 것으로 하나의 컬럼 또는 여러 개의 컬럼이 모여 <strong>Primary Key</strong>를 구성한다 </p>
<p><strong>어떤 컬럼을 주식별자로 설정 할 것인가</strong>
-&gt; 고객들이 제공한 데이터로는 주로 주식별자로 설정하지 않는다 ( 데이터 오류가 있을 수 있기 때문에 )</p>
<p>decimal - 실수 컬럼 자료형 (실수의 오차범위가 가장 적음 화폐 단위에 사용하기 좋음)
-money의 자료형이 따로 있지만 오차범위 때문에 decimal를 더 사용한다 </p>
<p>char 와 Varchar 차이
char은 할당 된 메모리의 크기 만큼 한 컬럼당 다 부여되지만 varchar은 메모리 할당이 가변이기 때문에 메모리 활용에 더 효과적임 </p>
<p>uniqueidentifier 
NEWID() 함수를 사용해서 유니크한 아이디를 준다 </p>
<p>유니코드 ( 다국어의 데이터를 저장 할 때 사용 )
앞의 n을 붙인다 </p>
<p>Primary Key 설계
고려사항 
-유일하고 모든 레코드에 not null일 수 있는 컬럼을 찾는다 
-후보 식별자가 없는 셩우 임의의 식별자를 만들어 부여한다 </p>
<p>pk의 데이터 타입 결정
-레코드의 발생 가능한 최대 수를 예측한다
예) 처리해야 하는 대상이 대략 몇 개정도 되는가?
-단순하게 생각하고 의미를 부여하는 것은 대량의 데이터를 관리하기에는 불리할 수 있다 </p>
<h3 id="1m-의-관계">1:M 의 관계</h3>
<blockquote>
<p>한쪽이 관계를 맺은 쪽의 여러 객체를 갖는 것을 의미한다 </p>
</blockquote>
<p>외래키(foreign key) : 부모 테이블에 있는 동일 컬럼 자식 테이블에는 여러개의 데이터가 존재 할 수 있지만 부모 테이블에는 딱 한 개만 존재가 가능하다 
설정 방법 </p>
<blockquote>
<p> -- 외래키 설정
    FOREIGN KEY (컬럼명) REFERENCES 부모테이블명(컬럼명)
    -- 이미 생성된 자식 테이블에 외래키 추가
ALTER TABLE 자식 테이블명
ADD FOREIGN KEY (컬럼명) REFERENCES 부모테이블명(컬럼명);</p>
</blockquote>
<p>*<em>테이블에 외래키를 설정해주면 부모 테이블에 없는 primarykey의 데이터를 자식 테이블에 넣을 수 없다 
*</em></p>
<p>외래키는 Not Null 지키자 ( 제대로 된 통계수치를 알 수 없다 ) </p>
<p>자식 테이블에 부모 테이블의 primarykey 데이터가 존재하면 부모 테이블의 데이터를 삭제 할 수 없다 </p>
<h3 id="1m-재귀적-관계">1:M 재귀적 관계</h3>
<p>예) 회사 -&gt; 부서 -&gt; 부서2</p>
<p>테이블 안에 외래키를 만들어준다 </p>
<h3 id="mn-의-관계">M:N 의 관계</h3>
<blockquote>
<p>두 테이블에 관계가 전혀 없다면 중간에 비즈니스를 설명하는 테이블이 만들어 질 수 있다 </p>
</blockquote>
<p>주어 목적어 동사가 확실하게 나오는 테이블은 잘 설계된 테이블이라 할 수 있다 ( 해석이 잘 되는 테이블 ) </p>
<blockquote>
<p>서고 테이블 (서고id-PK) 
서가 테이블 (서가id-PK) (서고id-PK FK) - 상속형(엄격)
<strong>-&gt; 서가 테이블 컬럼에 null을 허용하지 않기 때문에 데이터가 들어올 때 절대적으로 서가 서고가 같이 들어와야 할 때에는 상속형을 사용해주면 된다</strong> 
단점 : 상속을 받을 때 마다 pk가 늘어나기 때문에 데이터 삽입시 상다히 엄격해질 수 있다 
서고 테이블 (서고id-PK) 
서가 테이블 (서가seq-PK) (서가id) (서고id-FK) - 독립형
*<em>-&gt; 서가 테이블에 null을 허용하기 때문에 서가 서고가 동시에 데이터가 들어오지 않아도 문제가 없을 때 사용해준다  *</em>
단점 : 데이터 관련 에러가 발생 할 수 있음 </p>
</blockquote>
<ul>
<li>자식 테이블이 되지 않는 테이블은 해당 데이터에 기준이 될 수 있는지 고민해보자 (참조만 되는 테이블) - select만 되는 절대적인 테이블 </li>
<li>pk에 의미를 주지 말자 ( 예 : 반id - pk 반이름 반이름 컬럼을 따로 줘서 확장성을 키우자 )</li>
<li>TB - 테이블 접두어를 붙이자 </li>
</ul>
<p>update 테이블명 set 컬럼명 = cast(컬럼명 as varchar) + &#39;삽입 할 문자&#39;
-&gt; 반이름(반id = 3 , 반이름 = 3반) 을 한 번에 수정 할 수 있는 쿼리문 </p>
<ul>
<li><p>서로 상관관계가 있을 때에는 부모없는 자식을 만들 수 없다 ( 만약 부모의 데이터를 삭제해야한다면 상태를 나타내는 컬럼을 추가해준다 ) </p>
</li>
<li><p>회원 테이블에 상태를 나타내는 컬럼이 없으면 탈퇴시 데이터를 삭제해줘야 하는데 이미 그 회원과 상관관계를 맺은 데이터가 있다면 그 데이터는 부모 없는 자식이 된다 그러므로 삭제는 지양하고 상태 컬럼으로 유지와 탈퇴를 분간하면 된다 </p>
</li>
<li><p>null을 허용하지만 유니크한 데이터를 줘야 한다면 pk말고 유니크를 지정해주자 </p>
</li>
<li><p>설계시 다향한 변수또한 생각을 해야한다 </p>
</li>
</ul>
<blockquote>
<p>성정 (varchar(1000)) 
국어 90#수학90#영어40 
프로그래밍시 파밍하여 데이터 추출 
--지양 하는 방법 join하여 데이터 확인이 불가능하다 </p>
</blockquote>
<p><img src="https://velog.velcdn.com/images/kimy_j_/post/90685c23-9d96-4ccc-b1c0-132c6ec18370/image.png" alt="">
학교 성적관리 테이블 예시 </p>
<h3 id="11-관계">1:1 관계</h3>
<blockquote>
<p>어느 쪽 당사자의 입장에서 상대를 보더라도 반드시 단 하나씩 관계를 가지는 것을 말한다 </p>
</blockquote>
<p>예 ) 책 정보 테이블과 책 위치 테이블을 만든다 1:1 
책의 구분 컬럼을 테이블로 따로 만들어 데이터 삽입시 에러를 줄인다 </p>
<h3 id="정규화">정규화</h3>
<p>*<em>데이터 모델링에서 제일 중요한 것은 무결성을 보장하는 것 *</em></p>
<blockquote>
<p>*<em>Anomaly 란 *</em>
데이터의 이상 현상 
중복때문에 anomaly가 발생 ( 의도하지 않은 이상 현상 발생 가능 ) 
update deltet insert 에서 발생 할 수 있음</p>
</blockquote>
<p>1 정규화 
-&gt; 데이터 중복을 제거하기 위한 테이블 분할 </p>
<p>2 정규화
-&gt; 두 개 이상으로 구성된 PK 에서 발생한다 식별자 일부에 종속되는 어트리뷰트는 제거해야 한다 
-&gt; 상품명은 삼품 코드에만 종속되고 주문번호와는 관계 없음 
-&gt; 상품명을 따로 테이블로 만들어 줌 </p>
<p>3 정규화 
-&gt; 식별자 이외의 속성간에 종속 관계가 존재하면 안 된다 
-&gt; 종속 관계가 있으면 중복 값이 생긴다 
-&gt; 이행 종속 관계를 분해하는 것 </p>
<blockquote>
<p>1정규화</p>
</blockquote>
<ul>
<li>모든 속성은 반드시 하나의 값을 가져야 한다</li>
<li>값이라는 것은 원자성을 가져야 한다 즉 더 이상 쪼갤 수 없는 하나의 값만을 가져야 한다 </li>
</ul>
<p>대상 </p>
<ul>
<li>다가 속성이 사용된 릴레이션 
<img src="https://velog.velcdn.com/images/kimy_j_/post/21caea55-9b5c-4d5f-aab2-25ce8ba5f145/image.png" alt=""></li>
</ul>
<ul>
<li><p>복합 속성이 사용된 릴레이션
<img src="https://velog.velcdn.com/images/kimy_j_/post/715ec380-4091-4faa-bfd1-77e513b89697/image.png" alt=""></p>
</li>
<li><p>유사한 속성이 반복된 릴레이션</p>
</li>
<li><p>중첩 릴레이션</p>
</li>
<li><p>동일 속성이 여러 릴레이션에 사용된 경우</p>
</li>
</ul>
<blockquote>
<p>2정규화 </p>
</blockquote>
<ul>
<li>두 개 이상으로 구성된 pk에서 발생 </li>
<li>r의 모든 속성이 후보 식별자 전체에 종속 </li>
<li>일반 속성이 후보 식별자 전체에 종속 </li>
<li>일반 속성이 후보 식별자 전체에 종속되지 않고 일부에 종속된다면 2정규형 아님</li>
<li>따라서 2정규형이기 위해서는 모든 비 식별자 속성은 후보 식별자 속성에 완전함수 종속돼야 한다 </li>
</ul>
<blockquote>
<p>3정규화</p>
</blockquote>
<ul>
<li>식별자가 아닌 일반 속성 간에는 종속성이 존재하지 않는다 </li>
<li>3정규형의 대상이 되는 속성을 이행 종속 속성이라고 함</li>
</ul>
<p>*<em>db는 중복이 발생하지 않게 관계성을 잘 설계해야한다 *</em></p>
<blockquote>
<p>역정규화 </p>
</blockquote>
<ul>
<li>효율을 위해서 정규화된 결과의 일부를 수정하여 중복을 허용</li>
<li>정규화되지 않은 상태에서 중복을 허용하는 것과는 다름</li>
<li>대부분 join시 발생되는 엄청난 계산량을 해결하기 위해서 사용</li>
</ul>
<p>테이블 설계의 마지막은 튜닝이다 </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[객체지향 ]]></title>
            <link>https://velog.io/@kimy_j_/%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5</link>
            <guid>https://velog.io/@kimy_j_/%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5</guid>
            <pubDate>Sun, 23 Jul 2023 02:23:20 GMT</pubDate>
            <description><![CDATA[<p>객체의 핵심 -&gt; 기능 제공 
객체는 제공하는 기능으로 정의 
-내부적으로 가진 필드(데이터)로 정의하지 않음 
예 회원 객체 -&gt; 암호 변경하기기능, 차단 여부 확인 하기 기능 </p>
<p>메서드를 이용해서 기능 명세  ( 이름, 파라미터, 결과 )
객체와 객체는 기능을 사용해서 연결 ( 상호 작용 )
기능 사용 = 메서드 호출 </p>
<p>객체와 객체 상호 작용 : 메시지를 주고 받는다고 표현 
-메서드를 호출하는 메시지, 리턴하는 메시지, 익셉션 메시지</p>
<p>기능이 없고 단순한 데이터만 다루는 클래스는 객체보다는 데이터에 더 가깝다 (구조체-c)</p>
<p>전체적으로 이해했을 때 기능을 사용하는 곳과 기능을 작성하는 곳을 정확하게 분리하여 수정을 최소화 하는 과정</p>
<h3 id="캡슐화">캡슐화</h3>
<blockquote>
<p>데이터 + 관련 기능 묶기 
객체가 기능을 어떻게 구현했는지는 외부에 감추는 것 
구현에 사용된 데이터의 상세 내용을 외부에 감춤 
정보은닉 의미 포함
외부에 영향 없이 객체 내부 구현 변경 가능 
요구사항이 변경이 될 때 코드 수정을 최소하 할 수 있음 </p>
</blockquote>
<p>규칙 </p>
<ul>
<li>데이터 달라 하지 말고 해달라고 하기 </li>
<li>메서드에서 생성한 객체의 메서드만 호출 </li>
<li>파라미터로 받은 객체의 메서드만 호출</li>
<li>필드로 참조하는 객체의 메서드만 호출</li>
</ul>
<p>정리 
-&gt; 기능의 구현을 외부에 감춤
-&gt; 캡슐화를 통해 기능을 사용하는 코드에 영향을 주지 않고 (또는 최소화) 내부 구현을 변경할 수 있는 유연함 </p>
<h3 id="추상화">추상화</h3>
<blockquote>
<p>여러 모습을 갖는 것
객체지향에서는 한 객체가 여러 타입을 갖는 것 
즉 한 객체가 여러 타입의 기능을 제공
타입 상속으로 다형성 구현
하위 타입은 상위 타입도 됨 </p>
</blockquote>
<p>추상화 -&gt; 제이터나 프로세스 등을 의미가 비슷한 개념이나 의미 있는 표현으로 정의하는 과정</p>
<p>두 가지 방식의 추상화
특정한 성질 , 공통 성질 (일반화)</p>
<p>타입 추상화
여러 구현 클래스를 대표하는 상위 타입 도출
흔히 인터페이스 타입으로 추상화
추상화 타입과 구현은 타입 상속으로 연결</p>
<p>-&gt; 추상 타입은 구현을 감춤 </p>
<p>추상화는 변경이나 확장시에 시도하는 것이 좋다 </p>
<p>*<em>상속을 통한 기능 재사용의 단점 *</em></p>
<ul>
<li>상위 클래스 변경이 어려움 </li>
<li>상속 오용 </li>
</ul>
<p><strong>단점 해결 방법</strong>
-&gt; 조립 
여러 객체를 묶어서 더 복잡한 기능을 제공
보통 필드로 다른 객체를 탐조하는 방식으로 조립 또는 객체를 필요 시점에 생성/구함 </p>
<p>기능은 곧 책임 
분라한 각 기능을 알맞게 분배 </p>
<ul>
<li>패턴 적용</li>
<li>계산분리</li>
<li>연동분리</li>
<li>조건 분기는 추상화 </li>
</ul>
<p>의존 
기능 구현을 위해 다른 구성 요소를 사용하는 것 
의존의 예 : 객체 생성, 메소드호출, 데이터 사용</p>
<p>의존은 변경이 전파될 가능성을 의미
의존하는 대상이 바뀌면 바뀔 가능성이 높아짐
예 : 호출하는 메서드의 파라미터가 변경
예 : 호출하는 메소드가 발생할 수 있는 익셉션 타입이 추가 </p>
<p>순환의존 (위험)
변경 연쇄 전파 가능성</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[이중 for 문의 시간 복잡도 (프로그래머스)]]></title>
            <link>https://velog.io/@kimy_j_/%EC%9D%B4%EC%A4%91-for-%EB%AC%B8%EC%9D%98-%EC%8B%9C%EA%B0%84-%EB%B3%B5%EC%9E%A1%EB%8F%84-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4</link>
            <guid>https://velog.io/@kimy_j_/%EC%9D%B4%EC%A4%91-for-%EB%AC%B8%EC%9D%98-%EC%8B%9C%EA%B0%84-%EB%B3%B5%EC%9E%A1%EB%8F%84-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4</guid>
            <pubDate>Tue, 13 Jun 2023 07:25:53 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>프로그래머스 알고리즘을 푸는 중 시간 복잡도에 걸렸다 문제를 풀면서 알고리즘을 세우는 방식도 쉽지 않지만 시간계산을 하여 가장 효율적인 알고리즘을 세우는 것도 많은 연습과 공부의 필요성을 느꼈다 </p>
</blockquote>
<pre><code>package Lv_1;

public class Solution3 {

    public static void main(String[] args) { // 기사단원의 문제

        long startTime = System.currentTimeMillis();

        // 메소드 호출 및 처리
        solution(200000,100,100);

        long endTime = System.currentTimeMillis();
        long executionTime = (endTime - startTime) / 1000;
        System.out.println(&quot;처리 시간: &quot; + executionTime + &quot; 초&quot;);

    }
        public static int solution(int number, int limit, int power) {
            int answer = 0;
            int[] arr = new int[number];

            for(int i=1; i&lt;=number; i++){
//                 for(int j=1; j&lt;=i; j++){ // 처음에 시도했던 약수 구하는 알고리즘
//                     if(i%j == 0){
//                         arr[i-1] += 1;
//                     }
//                 }
                for(int j=1; j*j&lt;=i; j++){ // 타임오버로 인한 수정 number 를
                // 200000 으로 설정하여 비교하였을 때 대략 23초 차이가 난다
                    if(j * j == i){
                        arr[i-1]++;
                    }else if(i%j == 0){
                        arr[i-1] += 2;
                    }
                }

            }

            for(int i=0; i&lt;arr.length; i++){

                if(arr[i] &lt;= limit){
                    answer += arr[i];
                }else {
                    answer += power;
                }

            }

            return answer;
        }


}</code></pre><p>만약 100의 약수를 구한다고 가정하였을 때 1 , 2 , 3 , ..... , 100 번 까지 for문을 반복해야한다 적은 숫자에서는 가능하지만 만번을 반복하게 되면 10초 이상이 걸리기 때문에 굉장히 비효율적이다 그러기에 구글링을 통해 알게된 알고리즘 방식이 100에 루트를 씌운 만큼만 반복 / x의 약수 y가 있다면 x/y가 무조건 존재한다는 원리를 이용해 훨씬 효율적인 알고리즘을 만들 수 있었다 </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Spring Security ]]></title>
            <link>https://velog.io/@kimy_j_/Spring-Security</link>
            <guid>https://velog.io/@kimy_j_/Spring-Security</guid>
            <pubDate>Sat, 29 Apr 2023 10:51:46 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>최근 개인 프로젝트를 진행하며 시큐리티를 적용시켜 로그인 기능을 구현하고 싶단 생각이 들어 무작정 구글링을 통해 적용시켰지만 아직 동작원리에 대해 정확히 이해하지 못 한 느낌이 들어 따로 정리해보기로 했다 </p>
</blockquote>
<h3 id="스프링">스프링</h3>
<p>이란 스프링 기반의 애플리케이션 보안을 담당하는 하위 개념의 프레임워크이다 간단하게 말해 애플리케이션의 <strong>인증 인가</strong>를 담당하는 역할이다 </p>
<h4 id="여기서-인증과-인가는-무엇인가">여기서 인증과 인가는 무엇인가?</h4>
<p>인증(Authentication) -&gt; 유저가 실제 사이트의 유저가 맞는지 식별하는 과정 
인가(Authorization) -&gt; 특정 리소스에 접근이 가능한지 확인</p>
<p>_Security는 필터흐름으로 처리된다 _</p>
<blockquote>
<p>Client (request) → Filter → DispatcherServlet → Interceptor → Controller
(실제로 Interceptor가 Controller로 요청을 위임하는 것은 아님, Interceptor를 거쳐서 가는 것)</p>
</blockquote>
<p>여기서 필터와 인터셉터 둘 다 요청과 응답을 가로채는 역할을 한다 반대로 차이점은 필터는 DispatcherServlet 이전에 처리가 되고 인터셉터는 DispatcherServlet에서 Controller로 가기 전에 처리가 된다는 차이가 있다 
<img src="https://velog.velcdn.com/images/kimy_j_/post/0519bb3b-e0f9-4202-9502-f1ecad369d31/image.png" alt="">
&lt; 필터의 위치와 인터셉터의 위치 사진 참고 &gt;</p>
<p><img src="https://velog.velcdn.com/images/kimy_j_/post/760ad9d6-77f7-4099-8f42-2a90f74fad9c/image.png" alt="">
위에 사진은 시큐리티의 동작방식에 관한 사진이다 </p>
<ol>
<li>유저가 id/pass 를 입력하여 요청을 보낸다 </li>
<li>AuthenticationFilter가 요청을 가로채고 요청받은 유저의 정보로 UsernamePasswordAuthentication Token을 생성한다 </li>
<li>AuthenticationManager의 구현체인 ProviderManager에 토큰을 전달하여 등록된 AuthenticationProvider들을 조회하여 인증을 요구한다 </li>
<li>UserDeatialServeice에서 요청 받은 유저의 정보를 DB에 연결하여 확인한다 </li>
<li>유저의 정보가 있으면UserDetails을 만들어 session을 생성한다 </li>
<li>인증이 성공된 정보를 Authentication객체를 생성하여AuthenticatuonManager -&gt; AuthenticationFilter로 이동시키고</li>
<li>최종적으로 SecurityContextHolder에 사용자 정보가 담긴 Authentication객체를 저장시킨다 </li>
</ol>
<p>참고
<a href="https://velog.io/@soyeon207/SpringBoot-%EC%8A%A4%ED%94%84%EB%A7%81-%EC%8B%9C%ED%81%90%EB%A6%AC%ED%8B%B0%EB%9E%80">https://velog.io/@soyeon207/SpringBoot-%EC%8A%A4%ED%94%84%EB%A7%81-%EC%8B%9C%ED%81%90%EB%A6%AC%ED%8B%B0%EB%9E%80</a>
<a href="https://dev-coco.tistory.com/174">https://dev-coco.tistory.com/174</a>
<a href="https://emgc.tistory.com/108">https://emgc.tistory.com/108</a>
<a href="https://mangkyu.tistory.com/173">https://mangkyu.tistory.com/173</a></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[JDK 삭제하기 / 재설치 / 환경변수 설정]]></title>
            <link>https://velog.io/@kimy_j_/JDK-%EC%82%AD%EC%A0%9C%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@kimy_j_/JDK-%EC%82%AD%EC%A0%9C%ED%95%98%EA%B8%B0</guid>
            <pubDate>Thu, 27 Apr 2023 04:55:58 GMT</pubDate>
            <description><![CDATA[<h2 id="jdk-삭제">jdk 삭제</h2>
<p>터미널 창에 해당 명령어를 입력해준다 </p>
<p><strong>/usr/libexec/java_home -V</strong></p>
<p>입력 후 나오는 자바 버전들이 있을 것이다 삭제 할 버전의 위치를 복사해준다</p>
<p>*<em>sudo rm -rf 위치 붙여넣기 *</em></p>
<p>이렇게 명령어를 입력해주면 정상적으로 삭제가 완료된다 </p>
<h2 id="jdk-brew을-통하여-재설치">jdk brew을 통하여 재설치</h2>
<p><strong>brew update</strong>
최신 버전으로 업데이트를 시켜준다 </p>
<p><strong>brew tap adoptopenjdk/openjdk</strong>
adoptopenjdk/openjdk 레포지토리를 사용할 수 있도록 추가</p>
<p><strong>brew search jdk</strong>
현재 사용 가능한 버전을 검색한다 </p>
<p><strong>brew install --cask adoptopenjdk11</strong> (원하는 자바 버전을 작성)
원하는 jdk 버전을 저장 한다 </p>
<p>설치가 완료되면 <strong>java -version</strong> 으로 설치가 정상적으로 되었는지 확인해주면 된다 </p>
<h2 id="환경변수">환경변수</h2>
<p><strong>/usr/libexec/java_home -V</strong>
위의 명령어를 통해 jdk 위치를 복사한다 </p>
<p><strong>cd /Library/Java/JavaVirtualMachines</strong></p>
<p><strong>vi ~/.bash_profile</strong>
편집기를 열어준다 </p>
<p>export JAVA_HOME= 위치 붙여넣기
export PATH=&dollar;{PATH}:$JAVA_HOME/binJAVA_HOME= 위치 붙여넣기 </p>
<p>해당 두 줄을 작성해주고:wq 를 통해 나온다 </p>
<p><strong>source ~/.bash_profile</strong>
작성한 줄을 환경변수 설정을 해준다 </p>
<p><strong>echo $PATH</strong>
환경변수가 잘 등록이 되었는지 확인한다 </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[C언어 시작하기]]></title>
            <link>https://velog.io/@kimy_j_/C%EC%96%B8%EC%96%B4-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@kimy_j_/C%EC%96%B8%EC%96%B4-%EC%8B%9C%EC%9E%91%ED%95%98%EA%B8%B0</guid>
            <pubDate>Thu, 13 Apr 2023 10:37:23 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p><strong>c언어의 특징</strong></p>
</blockquote>
<ul>
<li>논리적이며 구조적인 시스템 프로그래밍 언어이다</li>
<li>하드웨어 제어가 가능하다 </li>
<li>프로그램 이식성이 높다</li>
<li>간력한 문법 표현으로 함축적인 프로그램 작성이 용이하다</li>
<li>저급 언어 특성을 가진 고급 언어이다</li>
</ul>
<h4 id="c언어로-작성된-프로그램은-총-3단계를-걸쳐-완성이된다">c언어로 작성된 프로그램은 총 3단계를 걸쳐 완성이된다</h4>
<ol>
<li>코딩 </li>
</ol>
<ul>
<li>소스파일을 작성한다(.c 라는 확장자를 가지게 된다 )</li>
</ul>
<ol start="2">
<li>컴파일 </li>
</ol>
<ul>
<li>작성된 코드를 기계어로 해석 할 수 있게 컴파일 시킨다 여기서 바로 기계어로 해석이 되는 것이 아니라 중간단계인 <strong>목적파일</strong>이 만들어지고 .obj라는 확장자를 가지게 된다 목적파일 하나로는 큰 의미를 두지 못 하고 라이브러리와 연결이 되어 하나의 프로그램이 되었을 때 의미를 가지게 된다 </li>
</ul>
<ol start="3">
<li>링커</li>
</ol>
<ul>
<li>여기서 목적파일과 라이브러리 파일과 연결하여 실행파일을 만들어내는 도구가 <strong>링커</strong>이다 컴파일러는 대부분 링커 기능까지 제공하고 있다 이 링커 과정이 끝나면 .exe라는 확장자를 가진 실행 파일이 생성된다 </li>
</ul>
<pre><code>#include &lt;stdio.h&gt; // 라이브러리 가져오기

int main(void) // 반환값을 void로 지정해도 되지만 그렇게 되면 정상종료가 안 될수 있기
//때문에 int로 지정한 후 retrun 값을 0을 반환하여 정상적으로 종료가 되었음을 나타내는 것이 
//좋다 
{
    printf(&quot;hello c \n&quot;);
    return 0;
}</code></pre><p>참고문서 
C프로그래밍 (김형근 곽덕훈 정재화 공저)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[thymeleaf layout 적용 시키기 (수정)]]></title>
            <link>https://velog.io/@kimy_j_/thymeleaf-layout-%EC%A0%81%EC%9A%A9-%EC%8B%9C%ED%82%A4%EA%B8%B0</link>
            <guid>https://velog.io/@kimy_j_/thymeleaf-layout-%EC%A0%81%EC%9A%A9-%EC%8B%9C%ED%82%A4%EA%B8%B0</guid>
            <pubDate>Wed, 29 Mar 2023 09:24:19 GMT</pubDate>
            <description><![CDATA[<p>예전 프로젝트는 jsp파일에 include 를 하여 레이아웃을 적용시켰지만 스프링부트 + thymeleaf 을 사용하면 tomcat을 별도로 설치 할 필요도 없고 jar로 빌드 시킬 수 있기때문에 이번 프로젝트는 jsp파일이 아닌 thymeleaf 를 사용하기위해 수정하였다 </p>
<ol>
<li><p>layout 라이브러리 추가해주기 </p>
<pre><code>implementation &#39;nz.net.ultraq.thymeleaf:thymeleaf-layout-dialect&#39;</code></pre></li>
<li><p>application.properties 파일에 추가해주기 </p>
<pre><code>spring.thymeleaf.enabled=true
spring.thymeleaf.cache=false
spring.thymeleaf.check-template-location=true
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html</code></pre></li>
<li><p>main.html 파일에 소스추가 </p>
<pre><code>&lt;html lang=&quot;en&quot;
   xmlns:th=&quot;http://www.thymeleaf.org&quot;
   xmlns:layout=&quot;http://www.ultraq.net.nz/thymeleaf/layout&quot;&gt;</code></pre></li>
<li><p>layout.html 파일에 이름 추가해주기 </p>
<pre><code>&lt;html lang=&quot;en&quot;
   xmlns:th=&quot;http://www.thymeleaf.org&quot;
   th:fragment=&quot;SideContent&quot;&gt;</code></pre></li>
<li><p>main.html 파일에 layout 페이지 추가해주기 </p>
<pre><code>&lt;th:block th:replace=&quot;/layout/sideContent :: SideContent&quot;&gt;&lt;/th:block&gt; //기존 </code></pre><pre><code>&lt;th:block th:replace=&quot;/layout/sideContent :: SideContent&quot;&gt;&lt;/th:block&gt; //수정</code></pre><p>인텔리제이에서 실행 할 때는 정상적으로 실행이 됐지만 터미널을 통해 빌드했을 때 오류가 나왔다 검색해보니 경로의 문제여서 경로를 수정하니 제대로 실행이 되었다 휴!ㅜ
참고 : <a href="https://adjh54.tistory.com/75">https://adjh54.tistory.com/75</a></p>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[warning: an illegal reflective access operation has occurred 에러 해결 ]]></title>
            <link>https://velog.io/@kimy_j_/warning-an-illegal-reflective-access-operation-has-occurred-%EC%97%90%EB%9F%AC-%ED%95%B4%EA%B2%B0</link>
            <guid>https://velog.io/@kimy_j_/warning-an-illegal-reflective-access-operation-has-occurred-%EC%97%90%EB%9F%AC-%ED%95%B4%EA%B2%B0</guid>
            <pubDate>Sat, 25 Mar 2023 14:29:21 GMT</pubDate>
            <description><![CDATA[<pre><code>WARNING: An illegal reflective access operation has occurred
WARNING: // 파일경로가 읽혔음 
WARNING: Please consider reporting this to the maintainers of org.apache.poi.util.DocumentHelper
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release</code></pre><p>검색해봤을 때 찾은건 스프링부트와 자바의 버전이 맞지 않아서 나오는 오류였다 </p>
<p>기존 스프링부트 2.7.10 + 자바 11 버전에서 스프링부트 2.7.10 + 자바 16 버전으로 바꾸니 해결되었다 </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[spring Gradle myBatis 연동 방법]]></title>
            <link>https://velog.io/@kimy_j_/spring-Gradle-myBatis-%EC%97%B0%EB%8F%99-%EB%B0%A9%EB%B2%95</link>
            <guid>https://velog.io/@kimy_j_/spring-Gradle-myBatis-%EC%97%B0%EB%8F%99-%EB%B0%A9%EB%B2%95</guid>
            <pubDate>Tue, 21 Mar 2023 06:44:26 GMT</pubDate>
            <description><![CDATA[<p>mybatis를 사용하기 위해선 의존성을 먼저 추가해줘야 한다 </p>
<p><strong>build.gradle</strong> 파일에 추가해준다 </p>
<blockquote>
<p>implementation group: &#39;org.mybatis.spring.boot&#39;, name: &#39;mybatis-spring-boot-starter&#39;, version: &#39;3.0.0&#39;
implementation &#39;org.mariadb.jdbc:mariadb-java-client&#39; // mariadb로 데이터 연동을 할 것 </p>
</blockquote>
<p>다음에 <strong>application.prorerties</strong> 파일에 데이터 정보와 mybatis를 연결해준다 </p>
<blockquote>
<p>spring.datasource.driverClassName=org.mariadb.jdbc.Driver
spring.datasource.url=jdbc:mariadb://localhost:3306/
spring.datasource.username= user 명
spring.datasource.password= 패스워드 
mybatis.type-aliases-package= mapper 파일이 들어가있는 패키지 경로 
mybatis.mapper-locations= mapper.xml파일이 들어가있는 경로 </p>
</blockquote>
<p>후에 main -&gt; resources -&gt; 이 위치에 경로를 추가해준다 </p>
<p><img src="https://velog.velcdn.com/images/kimy_j_/post/786c44fd-ec29-4d6d-b742-bbc728c593ff/image.png" alt=""></p>
<p>*<em>mybatis -&gt; mapper -&gt; 파일명.xml *</em></p>
<p>xml 파일에 sql문을 작성해준다 </p>
<pre><code>&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; ?&gt;
&lt;!DOCTYPE mapper PUBLIC &quot;-//mybatis.org//DTD Mapper 3.0//EN&quot; &quot;http://mybatis.org/dtd/mybatis-3-mapper.dtd&quot;&gt;

&lt;mapper namespace=&quot;com.example.Pets.mapper.NowTest&quot;&gt;
//namespace 는 인터페이스 경로로 잡아준다  
&lt;select id=&quot;NowTest&quot; resultType=&quot;String&quot;&gt;
    select now()
&lt;/select&gt;
&lt;/mapper&gt;
// 만약 resultType 을 DTO객체로 할 경우 DTO의 클래스이름 포함 경로까지 다 작성해줘야 함 </code></pre><p>예전 프로젝트에는 config파일을 별도로 작성하여 mappig작업을 하였지만 config파일 없이 인터페이스로만 연결해보려고 한다 </p>
<pre><code>@Repository
@Mapper // 어노테이션 추가 
public interface NowTest {

    String NowTest(); // 메소드명과 xml파일에 작성한 sql문의 id와 일치해야한다 
}</code></pre><p>인터페이스까지 만들어졌으면 controller service를 생성하여 테스트하면 정상적으로 데이터연동까지 되는 모습을 확인할 수 있다 </p>
<p><strong>인터페이스 테스트 코드 작성</strong> </p>
<pre><code>package com.example.Pets.Test;

import com.example.Pets.mapper.NowTest;
import org.junit.jupiter.api.Test;
import org.junit.runner.RunWith;
import org.mybatis.spring.boot.test.autoconfigure.MybatisTest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.test.context.junit4.SpringRunner;


@MybatisTest
@RunWith(SpringRunner.class)
@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
public class batisTest {

    @Autowired
    NowTest test;


    @Test
    void test(){
        System.out.println(&quot;NowTest 메소드 테스트 = &quot; + test.NowTest());
    }
}</code></pre><p>++ 참고: 테스트 코드에서 데이터 삽입시에는 자동 롤백이 설정되어 있다 
커밋하기 위해서는 @Commit 어노테이션을 추가해줘야 함 </p>
]]></description>
        </item>
        <item>
            <title><![CDATA[객체지향 개발 5가지 원리의 핵심 SOLID ]]></title>
            <link>https://velog.io/@kimy_j_/%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5-%EA%B0%9C%EB%B0%9C-5%EA%B0%80%EC%A7%80-%EC%9B%90%EB%A6%AC%EC%9D%98-%ED%95%B5%EC%8B%AC-SOLID</link>
            <guid>https://velog.io/@kimy_j_/%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5-%EA%B0%9C%EB%B0%9C-5%EA%B0%80%EC%A7%80-%EC%9B%90%EB%A6%AC%EC%9D%98-%ED%95%B5%EC%8B%AC-SOLID</guid>
            <pubDate>Wed, 01 Mar 2023 10:25:59 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>SOLID 란 객체지향 프로그래밍의 5가지 설계 원칙 장점으로 코드의 변경이 용이하고, 유지보수와 확장이 쉬운 소프트웨어를 개발하는데 도움이 되는 것으로 알려져있다 </p>
</blockquote>
<ol>
<li><p>단일 책임의 원칙 <strong>SRP</strong>(Single Responsibility Principle)
하나의 클래스는 하나의 책임만을 가져야 한다</p>
</li>
<li><p>개방 폐쇄 원칙 <strong>OCP</strong>(Open-Closed Principle)
소프트웨어 요소는 확장에는 열려있으나 변경에는 닫혀있어야 한다 
기존의 코드를 변경하지 않고 기능 추가, 수정 할 수 있도록 설계가 가능해야 한다 </p>
</li>
<li><p>리스코프 치환 원칙 <strong>LSP</strong>(Liskov Substisution Principle)
객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다
다향성에서 하위 클래스는 인터페이스 규약을 다 지켜야 한다는 것</p>
</li>
<li><p>인터페이스 분리 원칙 <strong>ISP</strong>(Interface Segregation Principle)
특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 낫다 
인터페이스가 면확해지고, 대체 가능성이 높아진다 </p>
</li>
<li><p>의존성 역전 원칙 <strong>DIP</strong>(Dependency Inversion Principle)
구체화에 의존하면 안되고 추상화에 의존해야 한다 </p>
</li>
</ol>
<p>참고 </p>
<ul>
<li><a href="https://ip99202.github.io/posts/SOLID/">https://ip99202.github.io/posts/SOLID/</a></li>
<li><a href="https://mangkyu.tistory.com/194">https://mangkyu.tistory.com/194</a></li>
<li><a href="https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/">https://www.inflearn.com/course/스프링-핵심-원리-기본편/</a></li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[intelliJ 로 스프링 프로젝트 생성과 빌드]]></title>
            <link>https://velog.io/@kimy_j_/intelliJ-%EB%A1%9C-%EC%8A%A4%ED%94%84%EB%A7%81-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%83%9D%EC%84%B1</link>
            <guid>https://velog.io/@kimy_j_/intelliJ-%EB%A1%9C-%EC%8A%A4%ED%94%84%EB%A7%81-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EC%83%9D%EC%84%B1</guid>
            <pubDate>Wed, 01 Feb 2023 14:59:07 GMT</pubDate>
            <description><![CDATA[<h4 id="스프링-프로젝트-생성">스프링 프로젝트 생성</h4>
<ol>
<li><a href="https://start.spring.io">https://start.spring.io</a> (스프링 부트 기반 프로젝트 생성해주는 사이트) 들어가기 
Gradle 버전을 많이 사용하는 추세 </li>
<li>Spring Web Thymeleaf (html 만들어 주는 거) Dependencies 추가 </li>
<li>인텔리제이에서 프로젝트 import (build.gradle 파일을 열어주면 된다)</li>
</ol>
<h4 id="프로젝트-실행-할-때-gradle를-거치고-실행되면-실행속도가-다소-느릴-수-있음-이럴-때-해줘야-하는-설정">프로젝트 실행 할 때 gradle를 거치고 실행되면 실행속도가 다소 느릴 수 있음 이럴 때 해줘야 하는 설정</h4>
<ol>
<li>설정에 들어가 Gradle로 들어간다 </li>
<li>Build and run using , Run tests using 를 IntelliJ IDEA로 설정해준다 </li>
</ol>
<p>*<em>핵심 라이브러리 *</em></p>
<p>Gradle은 의존관계가 있는 라이브러리를 함께 다운로드 한다.</p>
<p>스프링 부트 라이브러리
• spring-boot-starter-web
-&gt;• spring-boot-starter-tomcat: 톰캣 (웹서버)
-&gt;• spring-webmvc: 스프링 웹 MVC
• spring-boot-starter-thymeleaf: 타임리프 템플릿 엔진(View)
• spring-boot-starter(공통): 스프링 부트 + 스프링 코어 + 로깅
• spring-boot
-&gt;• spring-core
• spring-boot-starter-logging
-&gt;• logback, sIf4; (이 조합으로 많이 사용됨) </p>
<p>테스트 라이브러리
• spring-boot-starter-test
-&gt;• junit: 테스트 프레임워크
-&gt;• mockito: 목 라이브러리
-&gt;• assert;: 테스트 코드를 좀 더 편하게 작성하게 도와주는 라이브러리
-&gt;-&gt;spring-test: 스프링 통합 테스트 지원</p>
<p>시작 페이지는 static에서 index파일을 찾는다 </p>
<p>spring-boot-devtools 라이브러리를 추가하면 html 파일을 컴파일만 해주면 재시작 없이 view파일 변경이 가능하다 
컴파일 방법 : 메뉴build -&gt; Recompile</p>
<h3 id="build">Build</h3>
<p>콘솔로 이동 </p>
<ol>
<li>./gradlew build // 빌드 파일을 만든다 </li>
<li>cd build/libs </li>
<li>java -jar [jar파일 이름]</li>
</ol>
<p>*프로젝트가 제대로 실행이 안될시에는 프로젝트 파일로 이동후 
./gradlew clean  // 빌드 파일 삭제 
./gradlew clean build // 빌드 파일 삭제 후 재생성 </p>
<p>ctrl + Z : 프로젝트 정지
ctrl + C : 프로젝트 종료</p>
<p>++ springboot + jsp 로 빌드 할 경우 jsp파일을 jar에서 읽어오지 못 함 이럴 땐 war로 변경해줘야함 빌드 방법은 동일하다 </p>
<p>둘 중 하나 추가 </p>
<pre><code>plugins {
    id &#39;org.springframework.boot&#39; version &#39;2.3.4.RELEASE&#39;
    id &#39;io.spring.dependency-management&#39; version &#39;1.0.10.RELEASE&#39;
    id &quot;com.ewerk.gradle.plugins.querydsl&quot; version &quot;1.0.10&quot;
    id &#39;java&#39;
    id &#39;war&#39; // 추가 1
}
   OR
group = &#39;com.example&#39;
version = &#39;0.0.1-SNAPSHOT&#39;
apply plugin: &#39;war&#39; // 추가 2 </code></pre><sapn style="color:gray">
참고 :
인프런 강의 '스프링 입문 - 코드로 배우는 스프링 부트, 웹 MVC, DB 접근 기술' 
https://hye0-log.tistory.com/28

]]></description>
        </item>
        <item>
            <title><![CDATA[쓰레드 Thread]]></title>
            <link>https://velog.io/@kimy_j_/%EC%93%B0%EB%A0%88%EB%93%9C-Thread</link>
            <guid>https://velog.io/@kimy_j_/%EC%93%B0%EB%A0%88%EB%93%9C-Thread</guid>
            <pubDate>Thu, 12 Jan 2023 18:30:59 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>프로세스(실행 중인 프로그램)의 자원을 이용해서 실제로 작업을 수행하는 것이 바로 쓰레드이고 둘 이상의 쓰레드를 가진 프로세스를 멀티쓰레드 프로세스 라고 한다
프로세스를 하나 더 만드는 것보다 쓰레드를 하나더 생성하는 것이 적은 비용이 든다 </p>
</blockquote>
<p><strong>멀티 쓰레드의 장점</strong></p>
<ul>
<li>CPU의 사용률을 향상시킨다 </li>
<li>자율을 보다 효울적으로 사용할 수 있다</li>
<li>사용자에 대한 응답성이 향상된다 </li>
<li>작업이 분리되어 코드가 간결해진다 </li>
</ul>
<h4 id="쓰레드-구현-방법-2가지">쓰레드 구현 방법 2가지</h4>
<pre><code>class MyThread extends Thread{
    public void run(){} // Thread클래스의 run()을 오버라이딩
}</code></pre><pre><code>class MyThread2 implements Runnable{
    public void run(){} // Runnable인터페이스의 run()을 구현
}
</code></pre><blockquote>
<p>MyThread th1 = new MyThread(); // 클래스를 상속받은 쓰레드 생성 
Runnable run  = new MyThread2(); 
Thread th2 = new Thread(run); // 인터페이스를 상속받은 쓰레드 생성</p>
</blockquote>
<p>쓰레드를 실행 시킬 땐 start()메소드를 사용해주면 된다 run()메소드를 호출 할 시에는 일반 메소드 호출과 같다 </p>
<p>start()메소드 실행 순서 </p>
<ol>
<li>main메소드에서 쓰레드의 start() 호출 </li>
<li>start()는 새로운 쓰레드를 생성하고, 끄레드가 작업하는데 사용될 호출스택을 생성한다</li>
<li>새로 생성된 호출스택에 run()이 호출되어, 쓰레드가 독립된 공간에서 작업을 수행한다</li>
<li>이제는 호출스택이 2개이므로 스케줄러가 정한 순서에 의해서 번갈아 가면서 실행된다 </li>
</ol>
<h4 id="쓰레드의-실행상태">쓰레드의 실행상태</h4>
<p> <strong>NEW</strong> 쓰레드가 생성되고 아직 start()가 호출되지 않은 상태
 <strong>RUNNABLE</strong> 실행 중 또는 실행 가능한 상태
 <strong>BLICKED</strong> 동기화블럭에 의해서 일시정지된 상태(lock이 풀릴 때까지 기다리는 상태)
 <strong>WAITING</strong> <strong>TIMED_WAITING</strong> 쓰레드의 작어비 종료되지는 않았지만 실행가능하지 않은(unrunable) 일시정지상태 TIMED_WAITING은 일시정지시간이 지정된 경우를 의미 
 <strong>TERMINATED</strong> 쓰레드의 작업이 종료된 상태 </p>
<h4 id="쓰레드의-동기화">쓰레드의 동기화</h4>
<blockquote>
<p>한 쓰레드가 진행중인 작업을 다른 쓰레드가 간섭하지 못하게 막는 것 </p>
</blockquote>
<pre><code>public synchronized void calcSun(){
 // 임계영역
}</code></pre><pre><code>public void calcSun(){
    synchronized(객체의 참조변수){
        // 임계영역
    }
}</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[열거형 enum ]]></title>
            <link>https://velog.io/@kimy_j_/%EC%97%B4%EA%B1%B0%ED%98%95-enum</link>
            <guid>https://velog.io/@kimy_j_/%EC%97%B4%EA%B1%B0%ED%98%95-enum</guid>
            <pubDate>Tue, 10 Jan 2023 08:22:51 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>여러개의 상수를 관리할 때 편리하게 선언하는 방식이다 
enum 열겨형 이름 { 상수명1, 상수명2 }</p>
</blockquote>
<p>enum Direction { EAST, SOUTH, WEST, NORTH }</p>
<p>사용법 &gt;&gt;</p>
<pre><code>class Unit{
    Direction dir; // 열거형 인스턴스 변수를 선언 

    void init(){
        dir = Direction.EAST;
    }
}</code></pre><p>열거형 상수간의 비교는 &#39;==&#39;를 사용 할 수 있다 하지만 비교연산자 &#39;&gt;&#39; , &#39;&lt;&#39; 는 사용이 불가능하다 대신 compartTO()는 사용이 가능함 </p>
<p>dir == Direction.EAST 가능 
dir &gt; Direction.EAST 불가능 
dir.compareTo(Direction.WEST) &gt; 0 가능 </p>
<blockquote>
<p>열거형 메소드 종류 
Class<E> getDeclaringClass() 열거형의 Class객체를 반환한다 
  String name() 열거형 상수의 이름을 문자열로 반환한다 
  int ordinam() 열거형 상수가 정의된 순서를 반환한다 (0부터) 값과는 무관, 단순히 순서만 지정됨 
  T valueOf(Class<T> enumType, String name) 지정된 열거형에서 name과 일치하는 열거형 상수를 반환한다 </p>
</blockquote>
<h3 id="열거형의-멤버-추가하기">열거형의 멤버 추가하기</h3>
<pre><code>enum Direction{
  EAST(1) , SOUTH(5) , WEST(-1) , NORTH(10); 
  private final int value; // 열거형의 상수값을 저장하기 위해 final로 하는 것이 좋다 
  Direction(int value) {this.value = value; } // 접근 제어자 private가 디폴트 열거형 생성자는 외부에서 호출 불가능
  public int getValue() {return value;}
  }</code></pre>]]></description>
        </item>
        <item>
            <title><![CDATA[제네릭 Generics ]]></title>
            <link>https://velog.io/@kimy_j_/%EC%A0%9C%EB%84%A4%EB%A6%AD-Generics</link>
            <guid>https://velog.io/@kimy_j_/%EC%A0%9C%EB%84%A4%EB%A6%AD-Generics</guid>
            <pubDate>Tue, 10 Jan 2023 08:09:02 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>컴파일시에 타입체크를 해주는 기능을 한다 
장점 1. 타입 안정성을 제공한다
장점 2. 타입체크와 형변환을 생략할 수 있으므로 코드가 간결해 진다 </p>
</blockquote>
<p>컴파일 체크시 한계가 있어 안정성으로 생긴것이 제네릭이다 제네릭을 사용하면 런타임에서 생길 에러를 컴파일 때 잡을 수 있다 그러므로 코드를 즉각적으로 수정이 가능하게 된다 (jdk1.5 부터 생겼음)</p>
<h4 id="제네릭의-용어">제네릭의 용어</h4>
<blockquote>
<p>class Box&lt;T&gt; {}
Box&lt;t&gt;  -- 제네릭 클래스 T의 box 또는 T box 라고 읽는다<br>T -- 타입 변수 또는 타입 매개변수 (T는 타입 문자)
Box -- 원시 타입(raw type)</p>
</blockquote>
<p>ArrayList&lt;Product&gt; list = new ArrayList&lt;Product&gt;(); 타입 일치 
ArrayList&lt;Product&gt; list = new ArrayList&lt;Tv&gt;(); 타입 불일치 </p>
<ul>
<li>상속 관계에 있어도 타입은 무조건 일치시켜줘야함 </li>
<li>상속 관계에 있는 객체를 삽입하는 것은 가능</li>
</ul>
<p>  <strong>list.add(new Product()); 가능
  list.add(new Tv()); Product를 상속 받았기 때문에 가능
  list.add(new Audio()); Product를 상속 받았기 때문에 가능</strong></p>
<h3 id="제네릭과-extends">제네릭과 extends</h3>
<blockquote>
<p>class FruitBox &lt;T extends Fruit&gt; {
      // Fruit의 자손만 타입으로 지정가능 
 } 
<spna style="color:red"> 만일 클래스가 안라 인처페이스를 구현해야 한다는 제약이 필요하다면, 이때도 &#39;extends&#39;를 사요한다. &#39;implements&#39;를 사용하지 않는다는점에 주의하자 </span></p>
</blockquote>
<h3 id="제네릭의-제약">제네릭의 제약</h3>
<blockquote>
<ol>
<li>static 멤버에 타입변수 T를 사용할 수 없다 </li>
</ol>
<p>-T는 인스턴스 변수로 간주되기 때문에 안됨 
2. 지네릭 타입의 배열을 생성하는 것도 혀용되지 않는다 
-T[] itemArr; 가능 
-T[] itemArr = new T(); // new 연산자 사용 불가능 </p>
</blockquote>
<h3 id="와일드-카드">와일드 카드</h3>
<blockquote>
<p>&lt;? extends T&gt;  - 와일드 카드의 상한 제한 T와 그 자손들만 가능 
&lt;? super T&gt; - 와일드 카든의 하한 제한 T와 그 조상들마 가능
&lt;?&gt; - 제한 없음 모든 타입이 가능 &lt;? extends Object&gt; 와 동일함 </p>
</blockquote>
<p>static Juice make Juice (FriutBox&lt;? extends fruit&gt; box){
// fruit를 상속받은 객체의 타입만 지정해줄 수 있음 
}</p>
<h3 id="제네릭-메소드">제네릭 메소드</h3>
<blockquote>
<p>메서드의 선언부에 제네릭 타입이 선언된 메서드를 제네릭메서드라고 한다 
static &lt;T&gt; void sort(List&lt;T&gt; list, Comparator&lt;? super T&gt; c)</p>
</blockquote>
<p>제네릭 클래스에 정의도니 타입 매개변수가 T이고 제네릭 메서드에 정의된 타입 매개변수가 T이어도 이 둘은 전혀 별개의 것이다 같은 타입 문자 T를 사용해도 같은 것이 나이러는 것에 주의해야 한다 </p>
<p>static &lt;T extends Fruit&gt; Juice makeJuice(FruitBox&lt;T&gt; box){
 ///.....
}
호출시 &gt;&gt;
Juicer.&lt;Fruit&gt;makeJuice(fruitBox);</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Comparator Comparable]]></title>
            <link>https://velog.io/@kimy_j_/Comparator-Comparable</link>
            <guid>https://velog.io/@kimy_j_/Comparator-Comparable</guid>
            <pubDate>Mon, 09 Jan 2023 06:51:44 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>컬렉션 인터페이스를 사용할 때 정렬기준을 사용할 때가 있다 이 때 사용하는 인터페이스가 Comparator Comparable이 있다 int로 값을 반환하는데 객체가 값으면 0 비교하는 값보다 작으면 음수, 크면 양수로 반환한다 </p>
</blockquote>
<p>import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;</p>
<p>public class Ex100 {</p>
<pre><code>public static void main(String[] args) {

    ArrayList list = new ArrayList();
    list.add(new score(80 , &quot;fjie&quot;));
    list.add(new score(20 , &quot;sdfs&quot;));
    list.add(new score(180 , &quot;wre&quot;));
    list.add(new score(90 , &quot;dfsf&quot;));
    list.add(new score(30 , &quot;grgeg&quot;));

    Collections.sort(list); 

    Iterator it = list.iterator();

    System.out.println(&quot;======스코어 순위======&quot;);
    while(it.hasNext()) {
        System.out.println(it.next());
    }

}</code></pre><p>}</p>
<p>class score implements Comparable{</p>
<pre><code>int score;
String id;

public score(int score, String id) {
    super();
    this.score = score;
    this.id = id;
}

public int getScore() {
    return score;
}
public void setScore(int score) {
    this.score = score;
}
public String getId() {
    return id;
}
public void setId(String id) {
    this.id = id;
}
@Override
public String toString() {
    return id + &quot;님 스코어 : &quot; + score;
}

@Override
public int compareTo(Object o) { // 내림차순 구현
    score s = (score) o;
    return s.score - score;
    // return score - s.score; 오름차순
}</code></pre><p>}</p>
<blockquote>
<p>======스코어 순위======
wre님 스코어 : 180
dfsf님 스코어 : 90
fjie님 스코어 : 80
grgeg님 스코어 : 30
sdfs님 스코어 : 20</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[컬렉션 프레임워크 (2)]]></title>
            <link>https://velog.io/@kimy_j_/%EC%BB%AC%EB%A0%89%EC%85%98-%ED%94%84%EB%A0%88%EC%9E%84%EC%9B%8C%ED%81%AC-2</link>
            <guid>https://velog.io/@kimy_j_/%EC%BB%AC%EB%A0%89%EC%85%98-%ED%94%84%EB%A0%88%EC%9E%84%EC%9B%8C%ED%81%AC-2</guid>
            <pubDate>Thu, 05 Jan 2023 20:41:53 GMT</pubDate>
            <description><![CDATA[<h3 id="iterator--listiteator">Iterator , ListIteator</h3>
<blockquote>
<p>컬레션 프레임워크에서는 컬렉션의 저장된 요소들을 읽어오는 방법을 표준화하였다 
컬렉션에 저장된 데이터를 접근하는데 사용되는 인터페이스 종류
iterator - 컬렉션에 저장된 요소를 접근하는데 사용되는 인터페이스(단방향)
Listiterator - iterator에 양방향 조회기능 추가 (List를 구현한 경우에만 사용 가능)</p>
</blockquote>
<p>컬렉션 종류마다 구조가 다르므로, 데이터를 읽어오는 구조가 다르다 이 때 다른 종류마다의 데이터를 읽을 때 이처럼 표준화가 되어있다면 코드변경에 유리하다</p>
<pre><code>List list = new ArrayList(); // 다른 컬렉션으로 변경할 때는 이 부분만 고치면 된다
Iterator it = list.iterator();

while(it.hasNext()){ // hasNext()로 읽어올 요소가 있는지 확인한다 
System.out.println(it.next()) // 다음 요소를 읽어옴 
}</code></pre><p>ArrayList list = new ArrayList();
Collections co = new ArrayList();</p>
<p>컬렉션을 참조변수로 가지게 되면 다른 배열로 사용할 때 코드 전체를 확인하지 않고 new 연산자만 교체해주면 사용이 가능하다(코드 수정에 용이) 만약 참조변수를 ArrayList로 가지게 된다면 ArrayList에만 사용가능한 메소드들을 모두 교체해줘야하는 번거로움이 생긴다 Collections에 공통된 메소드들만 사용할 시에는 두 번째 형식으로 객체 생성하는 것이 더 좋은 방법이다 </p>
<p>*<em>Map에 iterator 사용하기 *</em></p>
<blockquote>
<p>Map map = new HashMap();
Iterator it = map.entrySet().iterator();</p>
</blockquote>
<p>Map인터페이스는 컬렉션을 상속받지 않았기 때문에 Set의 entrySet()와 함께 사용해야 한다 </p>
<h3 id="comparator--comparable">Comparator , Comparable</h3>
<blockquote>
<p>정렬기준을 제공해주는 인터페이스 
comparable - 기본 정렬기준을 구현하는데 사용
commparable - 기본 정렬기준 외에 다른 기분으로 정렬하고자 할 때 사용 </p>
</blockquote>
<h3 id="hashset">HashSet</h3>
<blockquote>
<p>Set 인터페이스를 구현한 가장 대표적인 컬렉션이며 Set의 특징처럼 순서가 없고, 중복을 허용하지 않는다 </p>
</blockquote>
<pre><code>HashSet set = new HashSet();
set.add(new Person(&quot;David , 10));
set.add(new Person(&quot;David , 10));</code></pre><p>위에 처럼 공통의 값이 들어간 객체가 있을시에 equals , hashConde 메소드를 오버라이딩을 해줘야만 같은 값으로 인식하여 하나만 추가가 된다 만약 오버라이딩이 안 되어있다면 둘 다 배열에 추가되니 오버라이딩을 꼭 기억하자</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[컬렉션 프레임워크 (1)]]></title>
            <link>https://velog.io/@kimy_j_/%EC%BB%AC%EB%A0%89%EC%85%98-%ED%94%84%EB%A0%88%EC%9E%84%EC%9B%8C%ED%81%AC-1</link>
            <guid>https://velog.io/@kimy_j_/%EC%BB%AC%EB%A0%89%EC%85%98-%ED%94%84%EB%A0%88%EC%9E%84%EC%9B%8C%ED%81%AC-1</guid>
            <pubDate>Wed, 04 Jan 2023 13:18:45 GMT</pubDate>
            <description><![CDATA[<h4 id="컬렉션-프레임워크란">컬렉션 프레임워크란</h4>
<p>데이터를 저장하는 클래스들을 표준화한 설계 
컬렉션을 다루기 위한 표준화된 프로그램 방식 컬렉션을 쉽고 편리하게 다룰 수 있는 다양한 클래스를 제공한다 </p>
<p>핵심 인터페이스의 종류 </p>
<blockquote>
<p>List -&gt; 순서가 있는 데이터의 집합 데이터의 중복을 허용한다 
Set -&gt; 순서를 유지하지 않는 데이터의 집합 데이커의 중복을 허용하지 않는다 
Map -&gt; key , value 로 이루어져 있으며 , 순서는 유지되지 않는다 키는 중복을 허용하지 않고, 값을 중복을 허용한다 </p>
</blockquote>
<p>실제 사용을 할 때에는 각 인터페이스의 주특징을 파악하여 그에 맞는 인터페이스를 사용하는 것이 좋다 </p>
<h4 id="list-중-arraylist">List 중 ArrayList</h4>
<blockquote>
<p>데이터의 저장순서가 저장이되고 중복 값을 허용한다 저장방식은 배열의 순서대로 저장이 되며 배열에 더 이상 저장할 공간이 없으면 큰 새로운 배열을 생성해서 기존의 배열에 저장된 내용을 새로운 배열로 복사한 다음에 저장된다 
ArrayList array = new ArrayList();</p>
</blockquote>
<p>기본형은 저장할 수 없음 대신 outoboxing를 통하여 Integer로 형변환 시켜 객채로 저장한다 </p>
<p>remove 사용시 주의 할 점 </p>
<ol>
<li>remove(1) -     인덱스 1번이 삭제됨 </li>
<li>remove(new Integer(1)) - 값이 1인 공간이 삭제됨 </li>
</ol>
<p>ArrayList의 삭제 방식 </p>
<ol>
<li>삭제할 데이터의 아래에 있는 데이터를 한 칸씩 위로 복사해서 삭제할 데이터를 덮어쓴다 </li>
<li>데이터가 모두 한 칸씪 위로 이동하였으므로 마지막 데이터는 null로 변경해야 한다 </li>
<li>데이터가 삭제되어 데이터의 개수(size)가 줄었으므로 size의 값을 1 감소시킨다 </li>
</ol>
<p>-&gt;List 삭제 for문 사용할 때 0부터 시작이 아닌 마지막 객체부터 시작하면 복사단계 없이 더 빠르고 정확한 삭제가 가능하다  </p>
<h4 id="list-중-linkedlist">List 중 LinkedList</h4>
<blockquote>
<p>크기를 변경 할 수 없고, 데이터의 추가 삭제의 시간이 오래걸리는 배열의 단점을 보안하고자 LinkedList라는 자료구조가 나왔고 배열은 모든 데이터가 연속적으로 존재하지만 링크드 리스트는 불연속적으로 존재하는 데이터를 서로 연결한 형태로 구성되어있다 </p>
</blockquote>
<p>LinkedList의 삭제와 추가 </p>
<p>데이터 삭제는 간단하다 삭제하고자 하는 요소의 이전요소가 삭제하고자 하는 요소의 다음요소를 참조하도록 변경하기만 하면 된다 단 하나의 참조만 변경하면 삭제가 이루어지는 것이다 배열처럼 데이터를 이동하기 우해 복하는 과정이 없기 때문에 처리속도가 매우 빠르다 </p>
<p>새로운 데이터를 추가할 때는 새로운 요소를 생성한 다음 추가하고자 하는 위치의 이전 요소의 참조를 새로운 요소에 대한 참조로 변경해주고, 새로운 요소가 그 다음 요소를 참조하도록 변경하기만 하면 되므로 처리속도가 매우 빠르다 </p>
<h4 id="다루고자-하는-데이터의-개수가-변하지-않는-경우라면-arraylist가-최사으이-선택이-되겠지만-데이터-개수의-변경이-잦다면-linkedlist를-사용하는-것이-더-나은-선택이-될-것이다">다루고자 하는 데이터의 개수가 변하지 않는 경우라면 ArrayList가 최사으이 선택이 되겠지만, 데이터 개수의 변경이 잦다면 LinkedList를 사용하는 것이 더 나은 선택이 될 것이다</h4>
<h3 id="stack-queue">Stack Queue</h3>
<blockquote>
<p>Stack은 push(저장) pop(추출)로 이루어진 LIFO(Last In First Out) 구조로 되어있는 클래스이고 마지막에 저장된 것을 먼저 꺼내는 형식으로 되어있다 
Queue은 offer(저장) poll(추출)로 이루어진 FIFO(First In First Out) 구조로 되어있는 인터페이스이고 제일 먼저 저장한 것을 제일 먼저 꺼내는 형식으로 되어있다 </p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[Calendar, SimpleDateFormat,Date]]></title>
            <link>https://velog.io/@kimy_j_/Calendar-SimpleDateFormatDate</link>
            <guid>https://velog.io/@kimy_j_/Calendar-SimpleDateFormatDate</guid>
            <pubDate>Sun, 01 Jan 2023 08:05:17 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>Calendar은 추상클래스이기 때문에 객체 생성이 불가능 하다 
Calendar cal = Calendar.getInstance(); 로 사용 </p>
</blockquote>
<pre><code>        Calendar cal = Calendar.getInstance();

        int year = cal.get(Calendar.YEAR);
        int month = cal.get(Calendar.MONTH); // (0~11)
        int day = cal.get(Calendar.DATE);

        System.out.println(year + &quot;년&quot; + month+1 + &quot;월&quot; + day+ &quot;일&quot;);</code></pre><blockquote>
<p>2023년01월1일</p>
</blockquote>
<p>*<em>Date 와 Calendar 의 형변환 *</em></p>
<ul>
<li>Calendar to Date 
Calendar cal = Calendar.getInstance();
Date d = new Date(cal.getTimeInMillis()); // Date(long date)</li>
<li>Date to Calendar
Date d = new Date();
Calendar cal = Calendar.getInstance();
cal.setTime(d)</li>
</ul>
<h4 id="simpledateformat">SimpleDateFormat</h4>
<p>Date today = new Date();
SimpleDateFormat df = new SimpleDateFormat(&quot;yyyy-MM-dd&quot;);</p>
<p>String result = df.format(today);
// 오늘 날짜를 yyyy-MM-dd 형태로 반환한다 </p>
<pre><code>try{
Data d = df.parse(&quot;2023-01-01&quot;); // SimpleDateFormat에 parse는 문자열을 Date로 형변환 해준다
System.out.println(df.format(d));
}catch(Exception e){
}</code></pre><blockquote>
<p>2023-01-01</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[String 클래스 와 StringBuffer 클래스]]></title>
            <link>https://velog.io/@kimy_j_/String-%ED%81%B4%EB%9E%98%EC%8A%A4-%EC%99%80-StringBuffer-%ED%81%B4%EB%9E%98%EC%8A%A4</link>
            <guid>https://velog.io/@kimy_j_/String-%ED%81%B4%EB%9E%98%EC%8A%A4-%EC%99%80-StringBuffer-%ED%81%B4%EB%9E%98%EC%8A%A4</guid>
            <pubDate>Thu, 29 Dec 2022 07:58:04 GMT</pubDate>
            <description><![CDATA[<blockquote>
<p>String 클래스에는 문자열을 저장하기 위해서 문자형 배열 참조변수(char[]) value를 인스턴스 변수로 정의해놓고 있다. 인스턴스 생성 시 생성자의 매개변수로 입력받는 문자열은 이 인스턴스변수에 문자열 배열(char[])로 저장되는 것이다</p>
</blockquote>
<p><span style="color:gray">문자열 간의 결합이나 추출 등 문자열을 다루는 작업이 많이 필요한 경우에는 String 클래스 대신 StringBuffer클래스를 사용하는 것이 좋다 StringBuffer인스턴스에 저장도니 문자열은 변경이 가능하므로 하나의 StringBuffer인스턴스로도 문자열을 다루는 것이 가능하다</span></p>
<p>문자열은 new 연산자를 통하여 메모리 할당이 되기 때문에 == 로 비교하기 보단 equals()로 비교해야 한다 </p>
<p>String str = &quot;a&quot;;
String str2 = &quot;a&quot;; // 문자열 리터럴이 존재할 시 재사용을 한다 
String str = new String(&quot;a&quot;);
String str2 = new String(&quot;a&quot;); // 재사용 하지 않는다 그러므로 == 로 비교하게 되면 주소가 달라 false 가 출력이 된다 </p>
<h4 id="int-to-string">int to String</h4>
<p>int i = 1;
String num = i + &quot;&quot;; 
String num = String.valueOf(i); // 더 빠름 </p>
<h4 id="string-to-int">String to int</h4>
<p>int i = Integer.paseInt(&quot;100&quot;);
int i = Integer.valueOf(&quot;100&quot;);
int i = Integer.valueOf(&quot;100&quot; , 10); // 여기서 10은 10진수를 의미 
int i = Integer.valueOf(&quot;100&quot;.trim()); // 양쪽에 공백이 있으면 예외가 발생 할 수 있기 때문에 trim()메소드를 습관적으로 사용하기도 한다 </p>
<h3 id="stringbuffer">StringBuffer</h3>
<ul>
<li>String 클래스는 변경이 불가능 하지만 buffer은 문자열 편집이 가능하다 </li>
<li>buffer은 비교 할 때 toString()으로 변환후 비교해줘야 한다 (equals()를 오버라이딩 하지 않아서 == 로 비교됨 String은 오버라이딩이 되어있다)</li>
</ul>
<blockquote>
<p>StringBuffer str = new StringBuffer(&quot;문자&quot;);
StringBuffer str = new StringBuffer(정수); // 크기 지정도 가능 </p>
</blockquote>
<h3 id="stringbuilder">StringBuilder</h3>
<p>buffer와 사용방법은 똑같다 buffer에 동기화만 빠진거라 생각하면 된다 </p>
]]></description>
        </item>
    </channel>
</rss>