<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>장장스</title>
    <link>https://zangzangs.tistory.com/</link>
    <description>킵고잉 !!</description>
    <language>ko</language>
    <pubDate>Fri, 8 May 2026 18:03:28 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>장장스</managingEditor>
    <image>
      <title>장장스</title>
      <url>https://tistory1.daumcdn.net/tistory/3765796/attach/77fe9ed37c6c40f7b6f0b4e4c7720225</url>
      <link>https://zangzangs.tistory.com</link>
    </image>
    <item>
      <title>[JPA] No converter found capable of converting from type [org.springframework.data.jpa.repository.query.AbstractJpaQuery$TupleConverter$TupleBackedMap] to type [com.web.blog.dto.post.PostidandviewcntWrapperclass] 오류</title>
      <link>https://zangzangs.tistory.com/181</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1064&quot; data-origin-height=&quot;513&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bz8DZD/btsm1Tw6D6l/Ad7kAyQxpMNsirFHDeBdCK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bz8DZD/btsm1Tw6D6l/Ad7kAyQxpMNsirFHDeBdCK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bz8DZD/btsm1Tw6D6l/Ad7kAyQxpMNsirFHDeBdCK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbz8DZD%2Fbtsm1Tw6D6l%2FAd7kAyQxpMNsirFHDeBdCK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1064&quot; height=&quot;513&quot; data-origin-width=&quot;1064&quot; data-origin-height=&quot;513&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;No&amp;nbsp;converter&amp;nbsp;found&amp;nbsp;capable&amp;nbsp;of&amp;nbsp;converting&amp;nbsp;from&amp;nbsp;type&amp;nbsp;[org.springframework.data.jpa.repository.query.AbstractJpaQuery$TupleConverter$TupleBackedMap]&amp;nbsp;to&amp;nbsp;type&amp;nbsp;[com.web.blog.dto.post.PostidandviewcntWrapperclass&lt;br /&gt;오류&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;안녕하세요? 장장스입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;오늘은 JPA 사용 도중 발생한 오류 처리 방법을 정리입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;JPQL 프로젝션에서 발생하는 문제&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;pre id=&quot;code_1690697845812&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;List&amp;lt;MemberDto&amp;gt; memberDtoList = em.createQuery(&quot;select MemberDto(m.username, m.age) from Member m&quot;, MemberDto.class)
                    .getResultList();&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;JPQL을 사용한 데이터 조회시 필요한 필드만 갖도록 VO를 만들어 사용하였습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1690697884729&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;No converter found capable of converting from type [org.springframework.data.jpa.repository.query.AbstractJpaQuery$TupleConverter$TupleBackedMap] to type [com.web.blog.dto.post.PostidandviewcntWrapperclass&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;그런데, 위와 같은 오류가 발생하였습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;해결방법 (new&amp;nbsp;jpql.domain.MemberDto)&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;pre id=&quot;code_1690697961001&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;List&amp;lt;MemberDto&amp;gt; memberDtoList = em.createQuery(&quot;select new jpql.domain.MemberDto(m.username, m.age) from Member m&quot;, MemberDto.class)
                    .getResultList();&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;JPQL 프로젝션시 객체 생성을 하도록 하면 됩니다. new 명령어를 사용하고 DTO의 패키지명까지 써주면 해결 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;(다른 방법이 있으면 추가 기록할 예정입니다~)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignCenter&quot; data-emoticon-type=&quot;niniz&quot; data-emoticon-name=&quot;012&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;잘못된 코드나 내용이 있다면 댓글을 남겨주세요. 즉시 수정하도록 하겠습니다! :)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>JPA</category>
      <category>jpa</category>
      <category>jpql</category>
      <category>프로젝션</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/181</guid>
      <comments>https://zangzangs.tistory.com/181#entry181comment</comments>
      <pubDate>Sun, 9 Jul 2023 15:18:34 +0900</pubDate>
    </item>
    <item>
      <title>[JPA] 공통 매핑 정보 @MappedSuperclass</title>
      <link>https://zangzangs.tistory.com/180</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1064&quot; data-origin-height=&quot;513&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/evfMMW/btsmSvqhYlm/wkqKDjcQVhoWv9mybxMpn1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/evfMMW/btsmSvqhYlm/wkqKDjcQVhoWv9mybxMpn1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/evfMMW/btsmSvqhYlm/wkqKDjcQVhoWv9mybxMpn1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FevfMMW%2FbtsmSvqhYlm%2FwkqKDjcQVhoWv9mybxMpn1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1064&quot; height=&quot;513&quot; data-origin-width=&quot;1064&quot; data-origin-height=&quot;513&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;[JPA] 공통 매핑 정보 @MappedSuperclass&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;안녕하세요? 장장스입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;오늘은 JPA에서 공통 매핑 정보를 편리하게 사용하는 @MappedSuperclass 에 대해 정리해보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;실무에서 공통으로 사용되는 칼럼들&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;실무에서 테이블을 만들 때 보통 &lt;b&gt;최초생성자와 생성시간, 최종수정자와 수정시간&lt;/b&gt;을 저장하는 칼럼들을 사용한다. 매번 반복되는 테이블 칼럼을 반복해서 사용하는 것은 개발자에게 꽤나 번거로운 일이 될 것이라 생각한다. JPA에는 이처럼 공통적으로 매핑되는 칼럼을 쉽게 사용할 수 있도록 @MappedSuperclass 어노테이션을 통해 기능을 제공합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;@MappedSuperclass&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;위에서 언급한 최초생성자와 생성시간, 최종수정자와 수정시간을 공통으로 작성할 수 있도록 BaseEntity라는 클래스를 만들어 사용할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;div style=&quot;color: #333333; text-align: start;&quot;&gt;
&lt;div style=&quot;background-color: #ffffff;&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre id=&quot;code_1688829267128&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@MappedSuperclass
@Getter @Setter
public abstract class BaseEntity {

    @Column(name = &quot;INSERT_MEMBER&quot;)
    private String createBy;
    private LocalDateTime createDate;
    @Column(name = &quot;UPDATE_MEMBER&quot;)
    private String lastModifiedBy;
    private LocalDateTime lastModifiedDate;

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000;&quot;&gt;위처럼 공통정보를 담은 BaseEntity 클래스를 상속하여 사용 할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1688829388736&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Entity
public class Member extends BaseEntity{
    ...
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;공통 매핑 정보를 담는 BaseEntity는 직접 생성해서 사용하지 않으므로 추상(abstract) 클래스를 사용을 권장합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;@MappedSuperclass를 사용한 BaseEntity는 엔티티로 사용할 수 없습니다. BaseEntity를 상속받은 자식 클래스는 매핑 정보만 제공하고 조회할 수 있습니다. (em.find(BaseEntity)는 되지 않습니다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;참고로 엔티티는 @Entity, @MappedSuperclass 가 선언된 클래스만 상속 받을 수 있습니다.&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Post&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;References&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.inflearn.com/course/ORM-JPA-Basic&quot;&gt;자바 ORM 표준 JPA 프로그래밍 - 기본편 [김영한]&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignCenter&quot; data-emoticon-type=&quot;niniz&quot; data-emoticon-name=&quot;012&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;잘못된 코드나 내용이 있다면 댓글을 남겨주세요. 즉시 수정하도록 하겠습니다! :)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>JPA</category>
      <category>@MappedSuperclass</category>
      <category>jpa</category>
      <category>공통 매핑</category>
      <category>상속</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/180</guid>
      <comments>https://zangzangs.tistory.com/180#entry180comment</comments>
      <pubDate>Sun, 9 Jul 2023 10:59:38 +0900</pubDate>
    </item>
    <item>
      <title>[JPA] 상속관계 맵핑 @Inheritance, @DiscriminatorColumn</title>
      <link>https://zangzangs.tistory.com/179</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1064&quot; data-origin-height=&quot;513&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/T17in/btslnfaGInB/MNU6v6Q9OnrCVK2emWPtJ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/T17in/btslnfaGInB/MNU6v6Q9OnrCVK2emWPtJ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/T17in/btslnfaGInB/MNU6v6Q9OnrCVK2emWPtJ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FT17in%2FbtslnfaGInB%2FMNU6v6Q9OnrCVK2emWPtJ0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1064&quot; height=&quot;513&quot; data-origin-width=&quot;1064&quot; data-origin-height=&quot;513&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;상속관계 맵핑 @Inheritance, @DiscriminatorColumn&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;안녕하세요? 장장스입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;JPA 상속관계 맵핑 @MappedSuperclass 에 대해 정리해보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;상속관계 맵핑&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;일반적인 관계형 데이터베이스는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;슈퍼타입 서브타입 관계라는 모델링 기법이 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;585&quot; data-origin-height=&quot;337&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bsEyWH/btslcD4H9cS/XOnbog1gHJOns5NaeKmuc1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bsEyWH/btslcD4H9cS/XOnbog1gHJOns5NaeKmuc1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bsEyWH/btslcD4H9cS/XOnbog1gHJOns5NaeKmuc1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbsEyWH%2FbtslcD4H9cS%2FXOnbog1gHJOns5NaeKmuc1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;585&quot; height=&quot;337&quot; data-origin-width=&quot;585&quot; data-origin-height=&quot;337&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;JPA에서는 슈퍼타입 서브타입 관계를 상속을 활용하여 구현할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;560&quot; data-origin-height=&quot;307&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BLRIP/btsljTFGNI3/Wlabu1nKOKXwWAm5M1CRok/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BLRIP/btsljTFGNI3/Wlabu1nKOKXwWAm5M1CRok/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BLRIP/btsljTFGNI3/Wlabu1nKOKXwWAm5M1CRok/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBLRIP%2FbtsljTFGNI3%2FWlabu1nKOKXwWAm5M1CRok%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;560&quot; height=&quot;307&quot; data-origin-width=&quot;560&quot; data-origin-height=&quot;307&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt; @Inheritance&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@Inheritance 어노테이션의 strategy 속성을 통해 전략을 선택 할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@DiscriminatorColumn 어노테이션은 부모 클래스에 선언합니다. 하위클래스를 구분하는 용도의 칼럼을 사용합니다. name 속성을 통해 이름을 설정할 수 있습니다. default 값은 DTYPE 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1687666955589&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Entity
@Getter @Setter
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
@DiscriminatorColumn
public abstract class Item {

    @Id @GeneratedValue
    private Long id;

    private String name;
    private int price;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;하위 클래스는 상위 클래스를 상속 받습니다. 이때 @DiscriminatorValue 어노테이션으로 엔티티를 저장할 때 슈퍼타입의 구분 칼럼에 저장할 값을 지정합니다. 선언하지 않으면 클래스 이름이 기본값으로 들어가게 됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1687672917974&quot; class=&quot;java&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Entity
@Getter @Setter
@DiscriminatorValue(value = &quot;A&quot;)
public class Album extends Item{
    private String artist;
}

@Entity
@Getter @Setter
@DiscriminatorValue(value = &quot;B&quot;)
public class Book extends Item{

    private String author;
    private String isbn;
}

@Entity
@Getter @Setter
@DiscriminatorValue(value = &quot;M&quot;)
public class Movie extends Item{
    private String director;
    private String actor;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;InheritanceType.JOINED 전략&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1362&quot; data-origin-height=&quot;414&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cV7zU9/btsldOLM9VB/BGVtMZ0Om7seQQ2kcLSrn0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cV7zU9/btsldOLM9VB/BGVtMZ0Om7seQQ2kcLSrn0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cV7zU9/btsldOLM9VB/BGVtMZ0Om7seQQ2kcLSrn0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcV7zU9%2FbtsldOLM9VB%2FBGVtMZ0Om7seQQ2kcLSrn0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1362&quot; height=&quot;414&quot; data-origin-width=&quot;1362&quot; data-origin-height=&quot;414&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;일반적인 정규화 된 방법으로 구현하는 전략입니다. @DiscriminatorColumn을 선언해야만 DTYPE 칼럼이 생성됩니다. 조인을 통해 어떤 하위 클래스인지 확인을 할 수 있으나 명확한 구분을 위해 DTYPE을 선언하는게 좋습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;다만, 조회시 조인을 많이사용하게 되고 쿼리가 복잡해질 수 있어 성능저하가 올 수 있습니다. 추가로 테이블에 데이터 저장시 INSERT SQL 2번 호출하게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;InheritanceType.SINGLE_TABLE 전략&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1120&quot; data-origin-height=&quot;401&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qAfgR/btslfejnvg1/72zKzwU5MQXXwPgbwjkk51/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qAfgR/btslfejnvg1/72zKzwU5MQXXwPgbwjkk51/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qAfgR/btslfejnvg1/72zKzwU5MQXXwPgbwjkk51/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqAfgR%2Fbtslfejnvg1%2F72zKzwU5MQXXwPgbwjkk51%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;251&quot; data-origin-width=&quot;1120&quot; data-origin-height=&quot;401&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;하나의 테이블에 모두 저장하고 DTYPE으로 구분하는 전략입니다. &lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;하나의 테이블에 모두 저장하기 때문에 DTYPE 없이는 구분을 할 수 없어&amp;nbsp;&lt;/span&gt;@&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;DiscriminatorColumn 을 선언하지 않아도 DTYPE칼럼이 생성됩니다. &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;INSERT SQL 1번만 호출하게 됩니다. 자식 엔티티가 매핑한 컬럼은 모두 null 사용을 하게 됩니다, 하나의 테이블에 모든 데이터를 저장하므로 테이블이 커질 수 있습니다. 때문에 상황에 따라서 조회 성능이 오히려 느려질 수 있습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;InheritanceType.TABLE_PER_CLASS 전략 &lt;span style=&quot;color: #ee2323;&quot;&gt;(비추천)&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1342&quot; data-origin-height=&quot;322&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SPnIf/btsldOLN5GP/bq3KmVPkXC7dhTByEhXpFK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SPnIf/btsldOLN5GP/bq3KmVPkXC7dhTByEhXpFK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SPnIf/btsldOLN5GP/bq3KmVPkXC7dhTByEhXpFK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSPnIf%2FbtsldOLN5GP%2Fbq3KmVPkXC7dhTByEhXpFK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1342&quot; height=&quot;322&quot; data-origin-width=&quot;1342&quot; data-origin-height=&quot;322&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt; JOINED 전략과 유사하지만 슈퍼타입(여기서는 Item) 칼럼들을 서브타입으로 내리는 전략입니다. 각각의 구현 클래스마다 테이블 생성 전략을 적용 할 수 있으며, NOT NULL 제약조건을 사용할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그러나, 여러 자식 테이블을 함께 조회하기 위해서는 UNION SQL 을 사용해야만 합니다. 때문에 SQL 조회 성능이 떨어지게 고 여러 자식 테이블을 통합해서 SQL을 사용하기가 어렵습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Post&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;References&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.inflearn.com/course/ORM-JPA-Basic&quot;&gt;자바 ORM 표준 JPA 프로그래밍 - 기본편 [김영한]&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignCenter&quot; data-emoticon-type=&quot;niniz&quot; data-emoticon-name=&quot;012&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;잘못된 코드나 내용이 있다면 댓글을 남겨주세요. 즉시 수정하도록 하겠습니다! :)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>JPA</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/179</guid>
      <comments>https://zangzangs.tistory.com/179#entry179comment</comments>
      <pubDate>Sun, 25 Jun 2023 15:03:54 +0900</pubDate>
    </item>
    <item>
      <title>[JPA] 단방향 양방향 연관관계와 다중성 #다대일 #일대다 #일대일 #다대다</title>
      <link>https://zangzangs.tistory.com/178</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1064&quot; data-origin-height=&quot;513&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLgolC/btsgCCKicwq/kd52GhkNbl99XC1uknCVP0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLgolC/btsgCCKicwq/kd52GhkNbl99XC1uknCVP0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLgolC/btsgCCKicwq/kd52GhkNbl99XC1uknCVP0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLgolC%2FbtsgCCKicwq%2Fkd52GhkNbl99XC1uknCVP0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1064&quot; height=&quot;513&quot; data-origin-width=&quot;1064&quot; data-origin-height=&quot;513&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;[JPA] 단방향&amp;nbsp;양방향&amp;nbsp;연관관계와&amp;nbsp;다중성&amp;nbsp;#다대일&amp;nbsp;#일대다&amp;nbsp;#일대일&amp;nbsp;#다대다&lt;/span&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;안녕하세요? 장장스입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;JPA는 &lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;자바 진영의 표준 ORM(&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;Object Relational Mapping)입니다. ORM에서 가장 중요한 것이 객체와 모델 사이의 관계를 정의하는 것입니다. 각 모델과의 연관 관계를 자바 코드로서 객체로 옮기는 것에 백퍼센트 정답은 없습니다. 구현하고자 하는 서비스의 도메인과 요구사항에 따라 적절하게 연관 관계를 정의해야 합니다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;단방향 관계, 양방향 관계&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1260&quot; data-origin-height=&quot;258&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Jpded/btsiBM3Hd5a/Qhbf5WP2k5JRNc52VraKIK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Jpded/btsiBM3Hd5a/Qhbf5WP2k5JRNc52VraKIK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Jpded/btsiBM3Hd5a/Qhbf5WP2k5JRNc52VraKIK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJpded%2FbtsiBM3Hd5a%2FQhbf5WP2k5JRNc52VraKIK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1260&quot; height=&quot;258&quot; data-origin-width=&quot;1260&quot; data-origin-height=&quot;258&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;데이터베이스에서 테이블과 조인할때, 외래키(FK)로 하나로 양쪽 테이블을 조인이 가능합니다. 때문에 데이터베이스에서 테이블과 다른 테이블에는 방향이 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;882&quot; data-origin-height=&quot;280&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/S1xnO/btsiBNuKcOs/BvEVSSomuBaD9wHMDRn8Nk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/S1xnO/btsiBNuKcOs/BvEVSSomuBaD9wHMDRn8Nk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/S1xnO/btsiBNuKcOs/BvEVSSomuBaD9wHMDRn8Nk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FS1xnO%2FbtsiBNuKcOs%2FBvEVSSomuBaD9wHMDRn8Nk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;662&quot; height=&quot;210&quot; data-origin-width=&quot;882&quot; data-origin-height=&quot;280&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;반면에 JPA에서는 객체(엔티티)를 통해 또다른 객체(엔티티)를 참조합니다. Orders 객체가  Customer 객체를 참조하기 위해 Customer 클래스를 필드로 가집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;위의 그림처럼 객체사이에서 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;한 객체만이 다른 객체를 참조하고 있으면 &lt;b&gt;단방&lt;span style=&quot;background-color: #f6e199;&quot;&gt;향&lt;/span&gt;&lt;/b&gt; 관계&lt;/span&gt;라고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;884&quot; data-origin-height=&quot;290&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uO5kg/btsivQeuE0K/kTWs8d6nCLZmmps9UfYUiK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uO5kg/btsivQeuE0K/kTWs8d6nCLZmmps9UfYUiK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uO5kg/btsivQeuE0K/kTWs8d6nCLZmmps9UfYUiK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuO5kg%2FbtsivQeuE0K%2FkTWs8d6nCLZmmps9UfYUiK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;580&quot; height=&quot;190&quot; data-origin-width=&quot;884&quot; data-origin-height=&quot;290&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;객체 사이에서 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;양쪽 객체가 서로를 참조하고 있으면 &lt;b&gt;양방향&lt;/b&gt; 관계&lt;/span&gt;라고 합니다. 양방향 관계를 정확히 말하면 객체가 서로를 단방향 관계로 참조하고 있는 것입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Orders -&amp;gt; Customer : &lt;b&gt;Orders.getCustomer()&lt;/b&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;b&gt;Customer -&amp;gt; Orders : &lt;/b&gt;Customer.getOrders()&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;여기까지 내용을 정리하며 문득 드는 의문이 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;데이터베이스처럼 양쪽 객체를 서로 참조하도록 하면 되지 않나?&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;실제로 양방향 관계로 객체끼리 서로 참조하게 해보면 문제가 매우 복잡해 지게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;예를 들어, 일반적인 비즈니스에서 회원 엔티티는 많은 엔티티와 연관 관계를 형성할 수 밖에 없습니다. 이러한 경우에 모든 객체(엔티티)를 양방향 관계로 연결하게 되면 수많은 참조 필드가 생기게 된다는 것을 예상할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;다른 문제로,객체가 서로를 참조하다보면 순환참조 문제가 발생할 수 있습니다. 때문에 toString(), lombok, JSON 생성 라이브러리를 사용할 때 주의를 기울여야 합니다. 컴파일 단계에서는 확인되지 않기 때문에 자칫하면 운영중에 큰 사고로 이어질 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;연관 관계의 주인&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이제 우리는 객체의 두 관계중 하나에 연관 관계의주인을 정해야 한다는 사실을 알았습니다. 어떤 객체에 연관 관계의 주인을 설정해야 할까요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;대부분은 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;외래키가 있는 곳을 연관 관계의 주인&lt;/b&gt;&lt;/span&gt;으로 정합니다. (어떤 예외 상황이 있는지는 알지 못하여 나중에 그런 상황이 발생하면 추가로 정리하겠습니다.) 연관 관계의 주인인 객체만이 외래키를&amp;nbsp; 등록하고 수정할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;연관 관계의 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;주인이 아닌 쪽은 읽기만 가능하며, mappedby 속성으로 주인을 지정&lt;/b&gt;&lt;/span&gt;할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1685863625300&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Entity
public class Customer {
    @Id
    @GeneratedValue
    @Column(name = &quot;customer_id&quot;)
    private Long id;

    private String name;

    @OneToMany(mappedBy = &quot;customer&quot;)
    private List&amp;lt;Orders&amp;gt; ordersList = new ArrayList&amp;lt;&amp;gt;(); 
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1685863644031&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Entity
public class Orders {

    @Id
    @GeneratedValue
    @Column(name = &quot;order_id&quot;)
    private Long id;

    @ManyToOne
    @JoinColumn(name = &quot;customer_id&quot;)
    private Customer customer;

    private LocalDateTime order_date;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;연관 관계 메서드&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;JPA는 객체 참조이기 때문에 연관 관계 주인과 주인이 아닌 객체에 모두 값을 입력해야 합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1685864136352&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Customer customer = new Customer();
customer.setName(&quot;장장스&quot;);
em.persist(customer); //INSERT

Orders order1 = new Orders();
order1.setCustomer(customer);
order1.setOrder_date(LocalDateTime.now());
em.persist(order1); //INSERT&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;위 코드를 실행시키고 나서 아래 코드를 출력하면 어떻게 될까요?&lt;/p&gt;
&lt;pre id=&quot;code_1685864293006&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;customer.getOrdersList().isEmpty();&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ee2323;&quot;&gt;&amp;nbsp;&lt;/span&gt;  ture 를 반환한다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;왜? ordersList가 비어있을까요? 데이터베이스와 달리 객체입니다. 연관관계의 주인인 customer객체에 ordersList에 별도로 order를 추가하도록 코드를 아래와 같이 수정해야 합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1685864449659&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Customer customer = new Customer();
customer.setName(&quot;장장스&quot;);
em.persist(customer); //INSERT

Orders order1 = new Orders();
order1.setCustomer(customer);
order1.setOrder_date(LocalDateTime.now());

customer.getOrdersList().add(order1); //연관 관계 주인에도 값을 추가한다.

em.persist(order1); //INSERT&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;위 코드처럼&amp;nbsp; order와 customer에 각각 값을 추가해야 하는데, 솔직히 불편하고 번거롭습니다. 이를 편리하게 하기 위한 방법으로&amp;nbsp;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;연관 관계 메서드&lt;/b&gt;&lt;/span&gt;를&amp;nbsp; 정의하여 사용할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1685864560158&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public void setCustomer(Customer customer) {
        this.customer = customer;
        customer.getOrdersList().add(this);
    }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;양방향 연관 관계에서는 &lt;b&gt;자바의 객체 상태를 고려해서 항상 양쪽에 값을 설정&lt;/b&gt;할 수 있도록 해야 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;다중성&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;JPA는 테이블의 관계를 정할 때는 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;데이터베이스 테이블 관계를 기준&lt;/b&gt;&lt;/span&gt;으로 정합니다. &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;JPA에서 제공하는 다중성 관계는 총 4가지 입니다.&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;◆&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;다대일&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&amp;larr;&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&amp;rarr; 일대다&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;◆&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;일대일&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&amp;larr;&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&amp;rarr; 일대일 (반대 동일)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;◆&lt;span&gt; &lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;다대 다&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&amp;larr;&lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&amp;rarr; 다대다 (반대 동일)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt; 다대일(N:1)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;가장 많이 사용하는 다중성 관계이다. &lt;b&gt;데이터베이스는 다대일에서 무조건 다 쪽에 외래키(FK)가 있다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #99cefa;&quot;&gt;&amp;nbsp;&lt;/span&gt; 다대일(N:1)의 단방향 관계&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1270&quot; data-origin-height=&quot;678&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ds2bg1/btskgHOJTv1/kTfjJHQzuRxwEKvXsPiQh0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ds2bg1/btskgHOJTv1/kTfjJHQzuRxwEKvXsPiQh0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ds2bg1/btskgHOJTv1/kTfjJHQzuRxwEKvXsPiQh0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fds2bg1%2FbtskgHOJTv1%2FkTfjJHQzuRxwEKvXsPiQh0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;267&quot; data-origin-width=&quot;1270&quot; data-origin-height=&quot;678&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;JPA로 넘어와서 먼저 다대일(N:1) 관계에서 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;다(N)&lt;/b&gt;&lt;/span&gt;인 객체에서 단순하게 &lt;b&gt;&lt;span style=&quot;background-color: #c1bef9;&quot;&gt;일(1)&lt;/span&gt;&lt;/b&gt;인 객체로 단방향 참조를 살펴보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;단방향 참조는, 테이블에 외래키가 있는 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;다(N)&lt;/b&gt;&lt;/span&gt;인 객체에서 &lt;span style=&quot;background-color: #c1bef9;&quot;&gt;&lt;b&gt;일(1)&lt;/b&gt;&lt;/span&gt;인 객체로 연관관계 매핑 하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;다(N) : Member&lt;/span&gt;&lt;/b&gt; &lt;b&gt;&lt;span style=&quot;background-color: #c1bef9;&quot;&gt;일(1) : Team&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;1. &lt;b&gt;@ManyToOne&lt;/b&gt;을 사용해서 다대일 관계를 매핑합니다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;2. &lt;b&gt;@JoinColumn&lt;/b&gt;&lt;span&gt;은&lt;/span&gt; &lt;span&gt;외래&lt;/span&gt; &lt;span&gt;키를&lt;/span&gt; &lt;span&gt;매핑할&lt;/span&gt; &lt;span&gt;때&lt;/span&gt; &lt;span&gt;사용한다&lt;/span&gt;. &lt;span&gt;매핑할&lt;/span&gt; &lt;span&gt;외래&lt;/span&gt; &lt;span&gt;키&lt;/span&gt; &lt;span&gt;이름은 name에 작성합니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1687069859227&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Entity
public class Member {
    //...
    @ManyToOne
    @JoinColumn(name = &quot;TEAM_ID&quot;)
    private Team team;
    //...
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #99cefa;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;다대일(N:1)의&lt;span&gt;&amp;nbsp;&lt;/span&gt;양방향 관계&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1258&quot; data-origin-height=&quot;694&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cHH4QM/btsklmoX7Km/WZG2FFUT8dlloWvUgtZcUK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cHH4QM/btsklmoX7Km/WZG2FFUT8dlloWvUgtZcUK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cHH4QM/btsklmoX7Km/WZG2FFUT8dlloWvUgtZcUK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcHH4QM%2FbtsklmoX7Km%2FWZG2FFUT8dlloWvUgtZcUK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;276&quot; data-origin-width=&quot;1258&quot; data-origin-height=&quot;694&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;단방향 관계에서 추가적으로 양방향 관계로 매핑할 때, &lt;span style=&quot;background-color: #c1bef9;&quot;&gt;&lt;b&gt;일(1)&lt;/b&gt;&lt;/span&gt;인 객체에서 단방향 매핑을 해주게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #c1bef9;&quot;&gt;&lt;b&gt;일(1)&lt;/b&gt;&lt;/span&gt;인 객체에서 단방향 매핑을 하는 것은 데이터베스상의 테이블에 영향을 전혀 주지 않습니다. 이미 다대일(N:1) 관계로&amp;nbsp;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;다(N)&lt;/b&gt;&lt;/span&gt;인 객체에서&amp;nbsp;&lt;b&gt;연관관계의&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;주인으로&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;b&gt;외래키를&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;관리&lt;/b&gt;하고  있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;다(N) : Member&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;text-align: start;&quot;&gt;&amp;nbsp;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;background-color: #c1bef9;&quot;&gt;일(1) : Team&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. &lt;b&gt;@OneToMany&lt;/b&gt; 어노테이션을 사용한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2. 연관관계의 주인이 아니므로, 어디에 매핑이 되었는지에 명시해주어야만 합니다. 아래 코드의 &lt;b&gt;mappedBy = &quot;team&quot;&lt;/b&gt;&amp;nbsp;은 Team 엔티티의 members 필드가 Member 엔티티의 team 필드에 의해 매핑 되었음을 의미합니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1687069480285&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Entity
public class Member {
    //...
    @ManyToOne
    @JoinColumn(name = &quot;TEAM_ID&quot;)   //외래 키가 있는 곳이 진짜 주인으로 정해라, Member.team
    private Team team;
    //...
}


@Entity
public class Team {
    //...
    @OneToMany(mappedBy = &quot;team&quot;) //읽기용 외래키로 mappedBy
    private List&amp;lt;Member&amp;gt; members = new ArrayList&amp;lt;&amp;gt;();
    //...
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt;&amp;nbsp;일대다(1:N)&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;일대다(1:N)는&amp;nbsp;&lt;span style=&quot;background-color: #c1bef9;&quot;&gt;&lt;b&gt;일(1)&lt;/b&gt;&lt;/span&gt; 연관관계의 주인을 갖는 관계입니다. 일(1) 객체에서 외래키를 관리하는 경우입니다. 보통 실무에서 사용을 권장하지는 않는다고 합니다. 예외적으로 일대다(1:N) 관계를 사용하는 경우가 있다고 하는데, 나중에 알게되면 추가적으로 포스팅하도록 하겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #99cefa;&quot;&gt;&amp;nbsp;&lt;/span&gt;&amp;nbsp;일대다(1:&lt;b&gt;N&lt;/b&gt;)의&amp;nbsp;단방향 관계&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1188&quot; data-origin-height=&quot;640&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nVdd9/btskgcVBiLP/EqHoGaI9x2HXlHPHHeScM1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nVdd9/btskgcVBiLP/EqHoGaI9x2HXlHPHHeScM1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nVdd9/btskgcVBiLP/EqHoGaI9x2HXlHPHHeScM1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnVdd9%2FbtskgcVBiLP%2FEqHoGaI9x2HXlHPHHeScM1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;269&quot; data-origin-width=&quot;1188&quot; data-origin-height=&quot;640&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #c1bef9;&quot;&gt;&lt;b&gt;일(1)&lt;/b&gt;&lt;/span&gt;인 객체가 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;다(N)&lt;/b&gt;&lt;/span&gt;인 객체를를 가지는데, &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;다(N)&lt;/b&gt;&lt;/span&gt; 인 객체에서는 &lt;span style=&quot;background-color: #c1bef9;&quot;&gt;&lt;b&gt;일(1)&lt;/b&gt;&lt;/span&gt;인 객체를 참조하지 않아도 된다라는 설계가 나올 수 있다. (객체지향적인 설계 관점에서 보면 충분이 나올 수 있는 경우라고 생각됩니다.)&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그러나 데이터베이스 테이블 관점에서 보면, 무조건 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;다(N)&lt;/b&gt;&lt;/span&gt;쪽에 외래키가 들어가게 됩니다. &lt;span style=&quot;background-color: #c1bef9;&quot;&gt;&lt;b&gt;일(1)&lt;/b&gt;&lt;/span&gt;인 객체에서 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;다(N)&lt;/b&gt;&lt;/span&gt;인 객체가 변경되면, 데이터베이스에서 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;다(N)&lt;/b&gt;&lt;/span&gt;&amp;nbsp;테이블에&amp;nbsp;업데이트&amp;nbsp;쿼리가 실행되어 버립니다. 실무에서는 여러 테이블이 복잡하게 얽히기 때문에 이러한 상황이 발생하면 유지보수가 어렵게 됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;테이블이 수십, 수백개 존재하는 실무에서는 매핑이나 설계는 명확해야 누구나 사용이 편리합니다. 가능하면 다대일 단방향 관계로 매핑하고, 필요할 경우 양방향 매핑을 통해서 해결하도록 합니다. &lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #c1bef9;&quot;&gt;일(1) : Team&amp;nbsp;&lt;/span&gt; &lt;span style=&quot;background-color: #c1bef9;&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;다(N) : Member&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;b&gt;@OneToMany와 @JoinColumn&lt;/b&gt;을 이용해서 일대다(1:N) 단방향 매핑을 한다. @JoinColumn을 꼭 사용해야만 하며, 사용하지 않으면 조인 테이블 방식을 사용합니다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1687071926656&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Entity
public class Team {
    //...
    @OneToMany
    @JoinColumn(name = &quot;TEAM_ID&quot;)
    private List&amp;lt;Member&amp;gt; members = new ArrayList&amp;lt;&amp;gt;();
    //...
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #99cefa;&quot;&gt;&amp;nbsp;&lt;/span&gt;&amp;nbsp;일대다(1:&lt;b&gt;N&lt;/b&gt;)의&amp;nbsp;양방향 관계&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;일대다(1:N) 양방향 관계 는 공식적으로는 존재하지 않습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;@ManyToOne과 @JoinColumn을 사용해서 연관관계를 매핑하면, 다대일(N:1) 단방향 매핑이 되어버린다. 그런데 반대쪽 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;일(1)&lt;/b&gt;&lt;/span&gt;인 객체에서 이미 일대다(1:N) 단방향 매핑이 설정되어있다. 이런 상황에서는 두 엔티티에서 모두 테이블의 외래키를 관리 하게 되는 상황이 벌어진다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이러한 상황을 막기 위해 insertable, updatable 속성값을 &lt;b&gt;FALSE&lt;/b&gt;로 설정하고 읽기 전용 필드로 사용해서 양방향 매핑처럼 사용하는 방법이다. &lt;/span&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;@JoinColumn(name = &quot;team_id&quot;, &lt;b&gt;insertable = &lt;span style=&quot;color: #ee2323;&quot;&gt;false&lt;/span&gt;, updatable = &lt;span style=&quot;color: #ee2323;&quot;&gt;false&lt;/span&gt;&lt;/b&gt;) . &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;text-align: start;&quot;&gt;insertable, updatable&amp;nbsp; 속성값을 false로 만들어&amp;nbsp;&lt;/span&gt;읽기 전용으로 사용하도록 할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;일대일(1:1)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;일대일(1:1) 관계는 반대도 일대일(1:1)로 동일합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #99cefa;&quot;&gt;&amp;nbsp;&lt;/span&gt; 일대일(1:1)의  단방향 관계&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;711&quot; data-origin-height=&quot;348&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Fk2aa/btslauANhSZ/nmeHCpKr8bYqznofB2iM51/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Fk2aa/btslauANhSZ/nmeHCpKr8bYqznofB2iM51/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Fk2aa/btslauANhSZ/nmeHCpKr8bYqznofB2iM51/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFk2aa%2FbtslauANhSZ%2FnmeHCpKr8bYqznofB2iM51%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;245&quot; data-origin-width=&quot;711&quot; data-origin-height=&quot;348&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;일대일 관계는 주 테이블, 대상 테이블 중에 외래키를 넣을 테이블을 선택 할 수 있습니다. 또한 외래 키에 유니크 제약조건이 추가되어야 일대일 관계가 됩니다.&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #99cefa;&quot;&gt;&amp;nbsp;&lt;/span&gt; 일대일(1:1)의 양방향 관계&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;722&quot; data-origin-height=&quot;362&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DSULS/btsk9iVa0Ra/KADySB1s1zhoRoo0oe1Auk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DSULS/btsk9iVa0Ra/KADySB1s1zhoRoo0oe1Auk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DSULS/btsk9iVa0Ra/KADySB1s1zhoRoo0oe1Auk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDSULS%2Fbtsk9iVa0Ra%2FKADySB1s1zhoRoo0oe1Auk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;251&quot; data-origin-width=&quot;722&quot; data-origin-height=&quot;362&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;다대일(N:1)처럼 &lt;b&gt;외래키가 있는 곳이 연관관계의 주인&lt;/b&gt;이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;@OneToOne 어노테이션으로 일대일(1:1) 단방향 관계를 매핑합니다. @JoinColumn을 사용합니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1687622096196&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Entity
public class Member {
   //...       
   @OneToOne
   @JoinColumn(name = &quot;locker_id&quot;)
   private Locker locker;
   //...
}

@Entity
public class Locker {
   //...       
   @OneToOne(mappedBy = &quot;locker&quot;)
   private Member member;
   //...
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;다대다(N:M)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;일반적인 관계형 데이터베이스에서는 정규화된 테이블 2개로 다대다(N:M)을 표현할 수 가 없어 중간에 연결 테이블을 추가해서 다대일, 일대다 관계로 풀어서 설계 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;JPA에서 객체는 컬렉션을 사용하여 다대다 관계를 풀어낼 수 있습니다. 그러나 개발을 하다보면 서비스가 커지고 요건이 추가되며, 중간 연결 테이블에 칼럼이 추가되며 데이터가 들어가야 하는 일이 생기기도 합니다. 이렇게 처리 하게 되면, 중간에 숨겨진 테이블로 인해, 예상치 못한 쿼리가 나가게 됩니다. 따라서 &lt;b&gt;다대다(N:M) 관계는 실무에서는 절대 지양&lt;/b&gt;해야 합니다. 다대일, 일대다 관계로 풀어서 사용하도록 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Post&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;References&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://www.inflearn.com/course/ORM-JPA-Basic&quot;&gt;자바 ORM 표준 JPA 프로그래밍 - 기본편 [김영한]&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignCenter&quot; data-emoticon-type=&quot;niniz&quot; data-emoticon-name=&quot;012&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;잘못된 코드나 내용이 있다면 댓글을 남겨주세요. 즉시 수정하도록 하겠습니다! :)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>JPA</category>
      <category>jpa</category>
      <category>다대다</category>
      <category>다대일</category>
      <category>단방향</category>
      <category>동시성</category>
      <category>양방향</category>
      <category>일대다</category>
      <category>일대일</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/178</guid>
      <comments>https://zangzangs.tistory.com/178#entry178comment</comments>
      <pubDate>Sun, 25 Jun 2023 01:16:25 +0900</pubDate>
    </item>
    <item>
      <title>[JPA] 기본키(PK) 매핑 전략 IDENTITY, SEQUENCE, TABLE, AUTO</title>
      <link>https://zangzangs.tistory.com/177</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1064&quot; data-origin-height=&quot;513&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cAO62r/btsfA31lWJa/e4Xe4vS9BG71rJMvZ1Xbu0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cAO62r/btsfA31lWJa/e4Xe4vS9BG71rJMvZ1Xbu0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cAO62r/btsfA31lWJa/e4Xe4vS9BG71rJMvZ1Xbu0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcAO62r%2FbtsfA31lWJa%2Fe4Xe4vS9BG71rJMvZ1Xbu0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1064&quot; height=&quot;513&quot; data-origin-width=&quot;1064&quot; data-origin-height=&quot;513&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;[JPA]&amp;nbsp;기본키(PK)&amp;nbsp;매핑&amp;nbsp;전략&amp;nbsp;&lt;/b&gt;&lt;/h2&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;GenerationType.&lt;b&gt;IDENTITY&lt;/b&gt;&lt;/h2&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;GenerationType.&lt;b&gt;SEQUENCE&lt;/b&gt;&lt;/h2&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;GenerationType.&lt;b&gt;TABLE&lt;/b&gt;&lt;/h2&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;GenerationType.&lt;b&gt;AUTO&lt;/b&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;안녕하세요? 장장스입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;오늘은 기본키(PK) 매핑 전략에 대해 정리해보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;기본키 맵핑 어노테이션&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;@Id&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;기본키를 사용자가 직접 할당하여 사용한다.&lt;/p&gt;
&lt;pre id=&quot;code_1684557442560&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Id
private String id;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;@GeneratedValue&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본키를 자동생성할때 사용한다.&lt;/p&gt;
&lt;pre id=&quot;code_1684558099983&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;기본키를 자동생성하는 @GeneratedValue 어노테이션은 4가지 전략이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;@GeneratedValue (strategy = GenerationType.&lt;span style=&quot;color: #006dd7;&quot;&gt;IDENTITY&lt;/span&gt;)&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;pre id=&quot;code_1684559882892&quot; class=&quot;less&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private String id;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;IDENTITY는 데이터베이스에 위임하는 전략이다. &lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;MySQL의 AUTO_INCREMENT와 같은 기능을 제공하는 &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;MySQL, PostgreSQL, SQL Server, DB2에서 사용할 수 있다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000; text-align: start;&quot;&gt;IDENTITY&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000; text-align: start;&quot;&gt;전략은&lt;/span&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;DB&lt;/span&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000; text-align: start;&quot;&gt;에&lt;/span&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000; text-align: start;&quot;&gt;적재&lt;/span&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000; text-align: start;&quot;&gt;되기&lt;/span&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000; text-align: start;&quot;&gt;전까지&lt;/span&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;PK&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000; text-align: start;&quot;&gt;값을&lt;/span&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000; text-align: start;&quot;&gt;알&lt;/span&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000; text-align: start;&quot;&gt;수&lt;/span&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000; text-align: start;&quot;&gt;없다&lt;/span&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000; text-align: start;&quot;&gt;. 예를 들어, &lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000; text-align: start;&quot;&gt;AUTO_INCREMENT는 데이터베이스에 INSERT SQL을 실행한 이후에 ID값을 알 수 있다. &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;JPA는 보통 트랜잭션 커밋 시점에 INSERT SQL을 실행한다. &lt;/span&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;JPA에서는 &lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;PK값이 없는 데이터는 영속성 컨텍스트에 올릴 수가 없다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt; 때문에, &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif; color: #000000; text-align: start;&quot;&gt;persist 메서드가 실행될때 &lt;/span&gt;바로 insert가 실행되고 key 값을 가져온다.&lt;/b&gt;&lt;/span&gt; JDBC 내부적으로 insert 시에 key값을 가져오게 되어 있어 약간의 리소스를 더 사용하게 된다는 단점이 존재한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;위와 같은 단점은, 개발할 때 크게 문제가 되지는 않는다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;b&gt;@GeneratedValue (strategy = GenerationType.&lt;span style=&quot;color: #006dd7;&quot;&gt; SEQUENCE&lt;/span&gt;)&lt;/b&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;pre id=&quot;code_1684559924120&quot; class=&quot;java&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE)
private Long id;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;SEQUENCE는 데이터베이스 시퀀스 오브젝트를 사용한다. 보통 &lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;ORACLE의 기본키 생성 전략으로 많이 사용한다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;시퀀스를 지정하지 않으면 기본 시퀀스 이름으로(ex.. hibernate_seq) 시퀀스 오브젝트를 생성하며, 직접 시퀀스 오브젝트를 설정하기 위해 @SequenceGenerator 어노테이션과 함께 사용한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1684560624121&quot; class=&quot;less&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@SequenceGenerator(
        name = &quot;ZZS_SEQ_GENERATOR&quot;,
        sequenceName = &quot;ZZS_SEQ&quot;, //매핑할 데이터베이스 시퀀스 이름
        initialValue = 1, allocationSize = 50)
public Class Zangzangs{

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = &quot;ZZS_SEQ_GENERATOR&quot;)
    private Long id;
    
    ...
    ...
    
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;SEQUENCE 전략을 생성할 때, int, long와 같은 원시타입(primitive type)은 0이 있어 사용을 추천하지 않는다.(기본키가 0부터 시작이 된다.) &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;보통&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; Integer, Long와 같은 래퍼 클래스를(wrapper class) 사용하며, Integer의 최대 크기가 21억밖에 안된다. &lt;s&gt;통장에 21억만 있으면 좋겠네..&lt;/s&gt; (MAU가 높은 규모의 회사이거나, 장기간 서비스가 이루어지면 21억은 금방 찰수도 있다.)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 요즘은 컴퓨터 성능이 좋아진&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;이유로 가능하면 무조건 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;Long 사용을 추천&lt;/b&gt;&lt;/span&gt;한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;@SequenceGenerator&lt;/b&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 170px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style13&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 20%; height: 20px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;속성&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 60%; height: 20px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;설명&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 20%; height: 20px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;기본값&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 20%; height: 20px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;name&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 60%; height: 20px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;식별자 생성 이름&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 20%; height: 20px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;필수&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 54px;&quot;&gt;
&lt;td style=&quot;width: 20%; height: 54px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;sequenceName&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 60%; height: 54px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;데이터베이스에 등록되어 있는 시퀀스 이름&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 20%; height: 54px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;hibernate_sequence&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 20%; height: 18px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;initialValue&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 60%; height: 18px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;DDL 생성 시에만 사용됨, 시퀀스 DDL을 생성할 때 처음 1 시작하는 수를 지정한다.&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 20%; height: 18px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;1&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 20%; height: 18px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;allocationSize&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 60%; height: 18px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;시퀀스 한번 호출에 증가하는 수&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;성능최적화에 사용되며 데이터베이스 시퀀스 값이 하나씩 증가하도록 설정되어 있으면 이 값을 반드시 1로 설정해야 한다.&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 20%; height: 18px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;50&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 20%; height: 18px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;catalog&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 60%; height: 18px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;데이터베이스 catalog&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 20%; height: 18px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 22px;&quot;&gt;
&lt;td style=&quot;width: 20%; height: 22px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;schema&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 60%; height: 22px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;데이터베이스 schema&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 20%; height: 22px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;b&gt;@GeneratedValue (strategy = GenerationType.&lt;span style=&quot;color: #006dd7;&quot;&gt;TABLE&lt;/span&gt;)&lt;/b&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;pre id=&quot;code_1684565164738&quot; class=&quot;less&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Id
@GeneratedValue(strategy = GenerationType.TABLE)
private Long id;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;TABLE은 키 생성용 테이블을 사용한다. 시퀀스 전략을 흉내내는 전략으로 모든 DB에서 사용이 가능하다는 장점이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;SEQUENCE 전략처럼 @TableGenerator 어노테이션이 필요하다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1684565278631&quot; class=&quot;less&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@TableGenerator(
        name= &quot;ZZS_SEQ_GENERATOR&quot;,
        table = &quot;MY_SEQUENCES&quot;,
        pkColumnValue = &quot;MEMBER_SEQ&quot;, allocationSize = 1)
public class Zangzangs{
   @Id
   @GeneratedValue(strategy = GenerationType.TABLE , generator = &quot;ZZS_SEQ_GENERATOR&quot;)
   private Long id;
   
   ...
   ...
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;다만, 시퀀스를 값 조회보다 테이블 조회하는 성능상의 단점이 커서 일반적으로 사용하지 않는다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;@TableGenerator&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 148px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style13&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 20%; height: 20px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;속성&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 60%; height: 20px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;설명&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 20%; height: 20px; text-align: center;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;기본값&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 20%; height: 18px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;name&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 60%; height: 18px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;식별자 생성 이름&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 20%; height: 18px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;필수&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 20%; height: 18px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;table&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 60%; height: 18px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;키생성 테이블명&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 20%; height: 18px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;hibernate_sequences&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 20%; height: 18px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;pkColumnName&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 60%; height: 18px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;시퀀스 칼럼명&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 20%; height: 18px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;sequence_name&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 20%; height: 18px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #efefef; color: #333333; text-align: start;&quot;&gt;pkColmnValue&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 60%; height: 18px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;키로 사용할 값 이름&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 20%; height: 18px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;엔티티 이름&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 20%; height: 20px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #efefef; color: #333333; text-align: start;&quot;&gt;valueColmnName&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 60%; height: 20px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;시퀀스 값 칼럼명&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 20%; height: 20px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;next_val&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 20%; height: 18px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;initialValue&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 60%; height: 18px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;초기 값, 마지막으로 생성된 값이 기준이다.&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 20%; height: 18px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;0&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 18px;&quot;&gt;
&lt;td style=&quot;width: 20%; height: 18px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;allocationSize&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 60%; height: 18px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;시퀀스 한 번에 호출에 증가하는 수&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;성능 최적화에 사용됨&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 20%; height: 18px;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;50&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 20%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;catalog&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 60%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;데이터베이스 catalog&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 20%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 20%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;schema&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 60%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;데이터베이스 schema&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 20%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 20%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;uniqueConstraints&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 60%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;b&gt;유니크 제약 조건을 지정한다.&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 20%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;b&gt;@GeneratedValue (strategy = GenerationType.&lt;span style=&quot;color: #006dd7;&quot;&gt;AUTO&lt;/span&gt;)&lt;/b&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt; AUTO는 데이터베이스 방언에 따라 자동 지정되며, strategy 속성의 디폴트 값이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;데이터베이스 방언에 따라&amp;nbsp;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;IDENTITY, &lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;SEQUENCE, &lt;/span&gt;&lt;/span&gt;TABLE 전략이 선택이 된다. 예를들어 오라클을 사용할 경우 &lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;SEQUENCE 전략이 선택된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;JPA 버전마다 AUTO 전략이 달라질 수 있으므로 확인 후에 사용해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Post&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://zangzangs.tistory.com/174&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2023.05.13 - [JPA] - [JPA] 영속성 컨텍스트(Persistence Context)와 주요 기능&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://zangzangs.tistory.com/175&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2023.05.14 - [JPA] - [JPA] 데이터베이스 스키마 자동 생성 옵션 (hibernate.hbm2ddl.auto)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://zangzangs.tistory.com/176&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2023.05.15 - [JPA] - [JPA] 필드와 컬럼 매핑 @Column, @Enumerated, @Temporal, @Lob&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;References&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a style=&quot;color: #0070d1;&quot; href=&quot;https://www.inflearn.com/course/ORM-JPA-Basic&quot;&gt;자바 ORM 표준 JPA 프로그래밍 - 기본편 [김영한]&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignCenter&quot; data-emoticon-type=&quot;niniz&quot; data-emoticon-name=&quot;012&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘못된 코드나 내용이 있다면 댓글을 남겨주세요. 즉시 수정하도록 하겠습니다! :)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>JPA</category>
      <category>Auto</category>
      <category>identity</category>
      <category>jpa</category>
      <category>sequence</category>
      <category>Table</category>
      <category>기본키</category>
      <category>생성전략</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/177</guid>
      <comments>https://zangzangs.tistory.com/177#entry177comment</comments>
      <pubDate>Sat, 20 May 2023 16:28:04 +0900</pubDate>
    </item>
    <item>
      <title>[JPA] 필드와 컬럼 매핑 @Column, @Enumerated, @Temporal, @Lob</title>
      <link>https://zangzangs.tistory.com/176</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1064&quot; data-origin-height=&quot;513&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ddb6NS/btsfeAl4mz4/iXkvjRK6MM20oNyfKPetq0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ddb6NS/btsfeAl4mz4/iXkvjRK6MM20oNyfKPetq0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ddb6NS/btsfeAl4mz4/iXkvjRK6MM20oNyfKPetq0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fddb6NS%2FbtsfeAl4mz4%2FiXkvjRK6MM20oNyfKPetq0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1064&quot; height=&quot;513&quot; data-origin-width=&quot;1064&quot; data-origin-height=&quot;513&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;[JPA] 필드와 컬럼 매핑&lt;br /&gt;@Column,&amp;nbsp;@Enumerated,&amp;nbsp;@Temporal,&amp;nbsp;@Lob,&amp;nbsp;@Transient&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;안녕하세요? 장장스입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;JPA 필드와 컬럼 매핑 어노테이션에 대해 정리하겠습니다.&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;@Column&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;테이블의 컬럼 정보와 매핑하는 어노테이션이다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 225px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style13&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 20%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;속성&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 60%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;설명&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 20%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;기본값&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 20%; height: 20px; text-align: left;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;name&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 60%; height: 20px; text-align: left;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;필드와 매핑할 테이블의 컬럼 이름&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 20%; height: 20px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;객체의 필드 이름&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 20%; height: 20px; text-align: left;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;insertable,&lt;br /&gt;updatable&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 60%; height: 20px; text-align: left;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;insertable, updatable&amp;nbsp;가능 여부&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 20%; height: 20px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;TRUE&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 20%; height: 17px; text-align: left;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;nullable (DDL) &lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 60%; height: 17px; text-align: left;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;null 값의 허용 여부를 설정한다. false로 설정하면 DDL 생성 시에 not null 제약조건이 붙는다. &lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 20%; height: 17px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 20%; height: 17px; text-align: left;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;unique (DDL) &lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 60%; height: 17px; text-align: left;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;@Table의 uniqueConstraints와 같지만 한 컬럼에 간단히 유니크 제 약조건을 걸 때 사용한다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 20%; height: 17px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 20%; height: 17px; text-align: left;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;columnDefinition &lt;br /&gt;(DDL)&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 60%; height: 17px; text-align: left;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;데이터베이스 컬럼 정보를 직접 줄 수 있다. ex) varchar(100) default &amp;lsquo;EMPTY'&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 20%; height: 17px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;필드의 자바 타입과 방언 정보를 사용해&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 34px;&quot;&gt;
&lt;td style=&quot;width: 20%; height: 34px; text-align: left;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;length&lt;br /&gt;(DDL)&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 60%; height: 34px; text-align: left;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;문자 길이 제약조건, String 타입에만 사용한다. &lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 20%; height: 34px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;255&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 80px;&quot;&gt;
&lt;td style=&quot;width: 20%; height: 80px; text-align: left;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;precision,&lt;br /&gt;scale (DDL)&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 60%; height: 80px; text-align: left;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;BigDecimal 타입에서 사용한다(BigInteger도 사용할 수 있다). &lt;br /&gt;precision은 소수점을 포함한 전체 자 릿수를, scale은 소수의 자릿수다. &lt;br /&gt;참고로 double, float 타입에는 적용되지 않는다. &lt;br /&gt;아주 큰 숫자나 정 밀한 소수를 다루어야 할 때만 사용한다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 20%; height: 80px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;precision=19, scale=2 &lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;@Temporal&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;날짜 타입 java.util.Date, java.util.Calendar 를 매핑할때 사용한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Java8 부터 지원하는 LocaDate, LocaDateTime은 최신 하이버네이트에서 자동으로 지원하기 때문에 생략 가능하다.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style13&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 20%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;속성&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 60%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;설명&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 20%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;기본값&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 20%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #000000;&quot;&gt;&lt;b&gt;value&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 60%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #000000;&quot;&gt;&lt;b&gt;-TemporalType.DATE&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #000000;&quot;&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp;날짜, 데이터베이스 date 타입과 매핑 &lt;br /&gt;&amp;nbsp; &amp;nbsp;(예: 2013&amp;ndash;10&amp;ndash;11)&lt;br /&gt;- TemporalType.TIME&lt;br /&gt;&amp;nbsp; &amp;nbsp;시간, 데이터베이스 time 타입과 매핑 &lt;br /&gt;&amp;nbsp; &amp;nbsp;(예: 11:11:11)&lt;br /&gt;- TemporalType.TIMESTAMP&lt;br /&gt;&amp;nbsp; &amp;nbsp;날짜와 시간, 데이터베이 스 timestamp 타입과 매핑&lt;br /&gt;&amp;nbsp; &amp;nbsp;(예: 2013&amp;ndash;10&amp;ndash;11 11:11:11)&lt;br /&gt;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 20%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;@Enumerated&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;자바 enum 타입을 매핑할 때 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;ORDINAL 옵션은 enum 순서를 저장하므로 enum 순서가 바뀌면 매우 위험해진다. 사용하지 않도록 하자.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style13&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 20%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;속성&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 60%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;설명&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 20%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;기본값&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 20%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #000000;&quot;&gt;&lt;b&gt;value&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 60%;&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light'; color: #000000;&quot;&gt;&lt;b&gt;- EnumType.ORDINAL&lt;br /&gt;&amp;nbsp; &amp;nbsp;enum 순서를 데이터베이스에 저장 &lt;br /&gt;- EnumType.STRING&lt;br /&gt;&amp;nbsp; &amp;nbsp;enum 이름을 데이터베이스에 저장&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 20%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;@Lob (BLOB, CLOB)&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;데이터베이스 BLOB, CLOB 타입과 매핑한다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;@Lob 어노테이션은 지정할 수 있는 속성이 없으며, 매핑하는 필드 타입에 따라 CLOB, BLOB을 매핑한다.&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;&lt;b&gt;CLOB: String, char[], java.sql.CLOB&amp;nbsp;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt; BLOB: byte[], java.sql. BLOB&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;@Transient&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;필드를 매핑하지 않을 때 사용하는 어노테이션이다. 데이터베이스에 저장하지 않으며, 조회하지도 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;주로 메모리상에서만 임시로 어떤 값을 보관하고 싶을 때 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Post&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;References&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a style=&quot;color: #0070d1;&quot; href=&quot;https://www.inflearn.com/course/ORM-JPA-Basic&quot;&gt;자바 ORM 표준 JPA 프로그래밍 - 기본편 [김영한]&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignCenter&quot; data-emoticon-type=&quot;niniz&quot; data-emoticon-name=&quot;012&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘못된 코드나 내용이 있다면 댓글을 남겨주세요. 즉시 수정하도록 하겠습니다! :)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>JPA</category>
      <category>@column</category>
      <category>@Enumerated</category>
      <category>@Lob</category>
      <category>@Temporal</category>
      <category>@Transien</category>
      <category>jpa</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/176</guid>
      <comments>https://zangzangs.tistory.com/176#entry176comment</comments>
      <pubDate>Mon, 15 May 2023 21:03:48 +0900</pubDate>
    </item>
    <item>
      <title>[JPA] 데이터베이스 스키마 자동 생성 옵션 (hibernate.hbm2ddl.auto)</title>
      <link>https://zangzangs.tistory.com/175</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1064&quot; data-origin-height=&quot;513&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/suxAp/btsfbyCw7eY/yz9ffp3xXSFe6FPPDEcXfK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/suxAp/btsfbyCw7eY/yz9ffp3xXSFe6FPPDEcXfK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/suxAp/btsfbyCw7eY/yz9ffp3xXSFe6FPPDEcXfK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsuxAp%2FbtsfbyCw7eY%2Fyz9ffp3xXSFe6FPPDEcXfK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1064&quot; height=&quot;513&quot; data-origin-width=&quot;1064&quot; data-origin-height=&quot;513&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;[JPA]&amp;nbsp;데이터베이스&amp;nbsp;스키마&amp;nbsp;자동&amp;nbsp;생성&amp;nbsp;옵션&amp;nbsp;(hibernate.hbm2ddl.auto)&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;안녕하세요? 장장스입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;데이터베이스 스키마 자동 생성&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;JPA는 애플리케이션 실행 시점에 테이블을 자동 생성 할 수 있는 기능을 제공한다.&lt;/p&gt;
&lt;pre id=&quot;code_1683971426997&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;!-- 필수 속성 --&amp;gt;
&amp;lt;property name=&quot;hibernate.dialect&quot; value=&quot;org.hibernate.dialect.H2Dialect&quot;/&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;데이터베이스 방언(dialect)을 설정하여 데이터베이스에 맞는 적절한 DDL을 생성 할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;스키마 자동 생성 hibernate.hbm2ddl.auto 속성&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;pre id=&quot;code_1683971528963&quot; class=&quot;html xml&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;property name=&quot;hibernate.hbm2ddl.auto&quot; value=&quot;create&quot; /&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 105px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style13&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 20%; height: 17px;&quot;&gt;&lt;b&gt;옵션&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 58%; height: 17px;&quot;&gt;&lt;b&gt;설명&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 20%; height: 17px;&quot;&gt;&lt;b&gt;create&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 80%; height: 17px;&quot;&gt;&lt;b&gt;기존테이블 삭제 후 다시 생성 (DROP + CREATE)&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 20%; height: 17px;&quot;&gt;&lt;b&gt;create-drop&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 80%; height: 17px;&quot;&gt;&lt;b&gt;create와 같으나 종료시점에 테이블 DROP&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 20%; height: 17px;&quot;&gt;&lt;b&gt;update&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 80%; height: 17px;&quot;&gt;&lt;b&gt;변경분만 반영(운영DB에는 사용하면 안됨)&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 20%; height: 17px;&quot;&gt;&lt;b&gt;validate&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 80%; height: 17px;&quot;&gt;&lt;b&gt;엔티티와 테이블이 정상 매핑되었는지만 확인&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 20%; height: 20px;&quot;&gt;&lt;b&gt;none&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 80%; height: 20px;&quot;&gt;&lt;b&gt;사용하지 않음&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;운영서버에서는 절대 create, create-drop, update 사용하면 안된다.&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;개발 초기 단계에서는 create 또는 update&amp;nbsp; &lt;br /&gt;개발 서버에서는 update 또는 validate&amp;nbsp; &lt;br /&gt;운영 서버와 스테이징에서는 validate 또는 none&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Post&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;References&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a style=&quot;color: #0070d1;&quot; href=&quot;https://www.inflearn.com/course/ORM-JPA-Basic&quot;&gt;자바 ORM 표준 JPA 프로그래밍 - 기본편 [김영한]&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignCenter&quot; data-emoticon-type=&quot;niniz&quot; data-emoticon-name=&quot;012&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘못된 코드나 내용이 있다면 댓글을 남겨주세요. 즉시 수정하도록 하겠습니다! :)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>JPA</category>
      <category>hibernate.hbm2ddl.auto</category>
      <category>jpa</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/175</guid>
      <comments>https://zangzangs.tistory.com/175#entry175comment</comments>
      <pubDate>Sun, 14 May 2023 00:34:46 +0900</pubDate>
    </item>
    <item>
      <title>[JPA] 영속성 컨텍스트(Persistence Context)와 주요 기능</title>
      <link>https://zangzangs.tistory.com/174</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1064&quot; data-origin-height=&quot;513&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dyxhCj/btsffuFnvCQ/6QX5cVNuK4Qc8RTtiV5kik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dyxhCj/btsffuFnvCQ/6QX5cVNuK4Qc8RTtiV5kik/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dyxhCj/btsffuFnvCQ/6QX5cVNuK4Qc8RTtiV5kik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdyxhCj%2FbtsffuFnvCQ%2F6QX5cVNuK4Qc8RTtiV5kik%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1064&quot; height=&quot;513&quot; data-origin-width=&quot;1064&quot; data-origin-height=&quot;513&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;[JPA] 영속성 컨텍스트(Persistence Context)와 주요 기능&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;안녕하세요? 장장스입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;오늘은 JPA 영속성 컨텍스트와 주요 기능에 대해 정리해보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;영속성 컨텍스트(Persistence Context)란?&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;JPA(Java Persistence API)에서 영속성 컨텍스트(Persistence Context)란 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;엔티티(Entity)를 영구 저장하는 환경&lt;/b&gt;&lt;/span&gt;을 말한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;여기서 엔티티(Entity)는 데이터베이스의 테이블에 대응하는 클래스로. JPA에서는 @Entity 어노테이션이 붙은 클래스를 엔티티라 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1683902307931&quot; class=&quot;java&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Entity
public abstract class Item{
    @Id @GeneratedValue
    @Column(name = &quot;ITEM_ID&quot;)
    private Long id;
    private String name;
    private int price;
    private int stockQuantity;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;엔티티&lt;b&gt;(Entity)&lt;span&gt; &lt;/span&gt;&lt;/b&gt;매니저&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;엔티티 매니저(Entity Manager)를 통해 영속성 컨텍스트에 접근할 수 있으며, 엔티티 매니저는 영속성 컨텍스트(Persistence Context)내에서 엔티티(Entity)를 관리한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1683902442798&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;EntityManagerFactory emf = Persistence.createEntityManagerFactory(&quot;emf&quot;);
EntityManager em = emf.createEntityManager();&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;데이터베이스의 데이터를 변경하는 모든 명령은 트랜잭션 안에서 이루어져야 한다. 엔티티 매니저로부터 트랜잭션을 얻을 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1683902449326&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;EntityTransaction tx = em.getTransaction();

tx.begin(); // 트랜잭션 시작
tx.commit(); // 트랜잭션 수행
tx.rollback(); // 작업에 문제 발생 시&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;924&quot; data-origin-height=&quot;576&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cmF2mn/btsfeh0H9AR/LshZZ1vrQZF4mVOu0NOTc0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cmF2mn/btsfeh0H9AR/LshZZ1vrQZF4mVOu0NOTc0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cmF2mn/btsfeh0H9AR/LshZZ1vrQZF4mVOu0NOTc0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcmF2mn%2Fbtsfeh0H9AR%2FLshZZ1vrQZF4mVOu0NOTc0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;657&quot; height=&quot;410&quot; data-origin-width=&quot;924&quot; data-origin-height=&quot;576&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;엔티티 매니저는 데이터베이스 연결이 필요한 시점에 커넥션 풀에서 커넥션(connection)을 얻어서 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;참고로, JPA의 구현체(hibernate) 는 EntityManagerFactory를 생성할 때 커넥션 풀을 생성한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;엔티티의 생명주기&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;984&quot; data-origin-height=&quot;778&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tJF0b/btse97ZmowQ/cBE5wlwaSdyTeyrgTUfsk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tJF0b/btse97ZmowQ/cBE5wlwaSdyTeyrgTUfsk1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tJF0b/btse97ZmowQ/cBE5wlwaSdyTeyrgTUfsk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtJF0b%2Fbtse97ZmowQ%2FcBE5wlwaSdyTeyrgTUfsk1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;570&quot; height=&quot;451&quot; data-origin-width=&quot;984&quot; data-origin-height=&quot;778&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #99cefa;&quot;&gt;&lt;b&gt;비영속(new/transient)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;영속성 컨텍스트와 상관 없이 단순히 객체를 생성한 상태를 말한다.&lt;/p&gt;
&lt;pre id=&quot;code_1683904209516&quot; class=&quot;ebnf&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Member member = new Member();&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1762&quot; data-origin-height=&quot;599&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Gg7LE/btse97kOAIQ/FXYFKpIapLQBKLVvabjQBK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Gg7LE/btse97kOAIQ/FXYFKpIapLQBKLVvabjQBK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Gg7LE/btse97kOAIQ/FXYFKpIapLQBKLVvabjQBK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGg7LE%2Fbtse97kOAIQ%2FFXYFKpIapLQBKLVvabjQBK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1762&quot; height=&quot;599&quot; data-origin-width=&quot;1762&quot; data-origin-height=&quot;599&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #99cefa;&quot;&gt;&lt;b&gt;영속(managed)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;position: absolute;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;영속성 컨텍스트에 영속된 상태를 말한다.&lt;/p&gt;
&lt;pre id=&quot;code_1683904188731&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;em.persist(member);&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1126&quot; data-origin-height=&quot;533&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/brKEhE/btsfgiksTOo/YpL2VqgZSy6ieHVBPLGxY1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/brKEhE/btsfgiksTOo/YpL2VqgZSy6ieHVBPLGxY1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/brKEhE/btsfgiksTOo/YpL2VqgZSy6ieHVBPLGxY1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbrKEhE%2FbtsfgiksTOo%2FYpL2VqgZSy6ieHVBPLGxY1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;556&quot; height=&quot;263&quot; data-origin-width=&quot;1126&quot; data-origin-height=&quot;533&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #99cefa;&quot;&gt;&lt;b&gt;준영속(detached)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;영속 상태의 엔티티가 영속성 컨텍스트에서 분리된 상태를 말한다.&lt;/p&gt;
&lt;pre id=&quot;code_1683904177151&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;em.detach(member); // 특정 엔티티를 준영속 상태로 전환
em.clear(); //영속성 컨텍스트 초기화
em.close(); //영속성 컨텍스트 종료&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;영속성 컨텍스트가 제공하는 기능을 사용하지 못하기 때문에 비영속 상태와 유사하다. 다만,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #333333; text-align: start;&quot;&gt;준영속 상태는&amp;nbsp; 영속 상태였을 때의 &lt;b&gt;식별자 값&lt;/b&gt;을 가지고 있다. &lt;/span&gt;준영속 상태를 다시 영속 시키려면 merge 메서드를 사용한다.&lt;/p&gt;
&lt;pre id=&quot;code_1683904678022&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;em.merge(member);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #99cefa;&quot;&gt;&lt;b&gt;삭제(removed)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;영속성 컨텍스트를 삭제한 상태를 말한다.&lt;/p&gt;
&lt;pre id=&quot;code_1683904166347&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;em.remove(member);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1차&amp;nbsp;캐시(First&amp;nbsp;Level&amp;nbsp;Cache)&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;영속성 컨텍스트의 가장 주요 기능은 캐시 기능을 제공하는 것이다. 1차 캐시는&amp;nbsp; 영속성 컨텍스트 내부에 존재하는 캐시로, 데이터베이스에서 데이터를 가져오는 것이 아닌 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;영속성 컨텍스트 내부에서 데이터를 가져오는 기능&lt;/b&gt;&lt;/span&gt;입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2492&quot; data-origin-height=&quot;652&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JtfNG/btsfbzg0h7P/sgjuf5bL0NMPciYkkBbkJ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JtfNG/btsfbzg0h7P/sgjuf5bL0NMPciYkkBbkJ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JtfNG/btsfbzg0h7P/sgjuf5bL0NMPciYkkBbkJ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJtfNG%2Fbtsfbzg0h7P%2Fsgjuf5bL0NMPciYkkBbkJ1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;2492&quot; height=&quot;652&quot; data-origin-width=&quot;2492&quot; data-origin-height=&quot;652&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;1차 캐시를 사용함으로서 성능상의 이점이 발생 하지만, 1차 캐시는 동일 트랜잭션 내에서만 유지되기 때문에 보통 성능상 큰 차이가 발생하지 않는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #99cefa;&quot;&gt;&lt;b&gt;동일성 보장&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;1차 캐시로 반복 가능한 읽기 등급의 트랜잭션 격리 수준을 데이터베이스가 아닌 애플리케이션 차원에서 제공한다. 따라서 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;자바의 컬렉션과 같이 동일 트랜잭션에서 엔티티의 동일성을 보장해준다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1683954892717&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Member a = em.find(Member.class, &quot;member1&quot;); 
Member b = em.find(Member.class, &quot;member1&quot;);
System.out.println(a == b); //동일성 비교 true&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;쓰기 지연(Write Behind)&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;쓰기 지연(Write Behind)은 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;트랜잭션을 커밋할 때까지 SQL 쿼리를 모아서 한번에 DB에 전달하는 방식&lt;/b&gt;&lt;/span&gt;을 말한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1683955608810&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 1.트랜잭션 시작
transaction.begin(); 

// 2. 엔티티 영속성 컨텍스트 등록
em.persist(memberA);
em.persist(memberB);
//---여기까지 INSERT SQL을 데이터베이스에 보내지 않는다.---

// 3. 트랜잭션 커밋 - 데이터베이스에 INSERT SQL을 보낸다.
transaction.commit();&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;853&quot; data-origin-height=&quot;994&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bhrQ7h/btsfdqKCe7Y/eA5SAw3IdLtg10gJ3zTk6K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bhrQ7h/btsfdqKCe7Y/eA5SAw3IdLtg10gJ3zTk6K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bhrQ7h/btsfdqKCe7Y/eA5SAw3IdLtg10gJ3zTk6K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbhrQ7h%2FbtsfdqKCe7Y%2FeA5SAw3IdLtg10gJ3zTk6K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;613&quot; height=&quot;714&quot; data-origin-width=&quot;853&quot; data-origin-height=&quot;994&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;em.persist()&lt;/b&gt;&lt;/span&gt;&amp;nbsp;메서드가 수행되면 다음과 같은 동작이 일어난다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; 1. 영속성 컨텍스트 1차 캐시에 저장&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; 2. 쓰기 지연 SQL 저장소에 INSERT SQL 을 생성하여 보관&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1114&quot; data-origin-height=&quot;678&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/chGqwd/btsfaNs5j7b/1rmBkLu9PhQjuo2xP5lrH1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/chGqwd/btsfaNs5j7b/1rmBkLu9PhQjuo2xP5lrH1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/chGqwd/btsfaNs5j7b/1rmBkLu9PhQjuo2xP5lrH1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FchGqwd%2FbtsfaNs5j7b%2F1rmBkLu9PhQjuo2xP5lrH1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;707&quot; height=&quot;430&quot; data-origin-width=&quot;1114&quot; data-origin-height=&quot;678&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;마지막으로 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;transaction.commit()&lt;/b&gt;&lt;/span&gt; or &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;em.flush()&lt;/b&gt;&lt;/span&gt;이 실행되면 쓰기 지연 SQL 저장소의 SQL들을 한꺼번에 데이터베이스로 날린다. 쓰기 지연은 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;일종의 버퍼링 기능으로 I/O 부하를 줄일 수 있다는 것이 장점&lt;/b&gt;&lt;/span&gt;이다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;다만, 너무 많은 I/O가 동시에 발생하면 DB에 부하를 줄 수도 있다. 하이버네이트에서는 최대 한번에 보낼 insert/update 사이즈를 설정하는 옵션을 제공한다.&lt;/p&gt;
&lt;pre id=&quot;code_1683956132558&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;property name=&quot;hibernate.jdbc.batch_size&quot; value=&quot;10&quot;/&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;변경 감지(Dirty Checking)&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;JPA는 엔티티가 변경되면 수정 메서드를 사용하지 않아도 자동으로 UPDATE 쿼리를 날리게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1683969225249&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 1.트랜잭션 시작
transaction.begin();

// 2.영속 엔티티 조회
Member memberA = em.find(Member.class, &quot;memberA&quot;);
// 3. 영속 엔티티 데이터 수정
memberA.setUsername(&quot;hi&quot;);
memberA.setAge(10);

// 3-1. em.update(member) 이런 코드가 있어야 하지 않을까?

// 4. 트랜잭션 커밋
transaction.commit();&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;마치 자바 컬렉션에 있는 값을 꺼내서 변경하면 컬렉션에 다시 저장하지 않아도 컬렉션의 값이 수정되어 있는 것과 동일하게 동작한다. 이러한 JPA의 변경 감지(Dirty Checking)는 영속성 컨텍스트와 밀접한 관련이 있다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1184&quot; data-origin-height=&quot;697&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DRO0P/btsftKgGBuP/Y0U3wKEk2s3Xn3LbBKILBK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DRO0P/btsftKgGBuP/Y0U3wKEk2s3Xn3LbBKILBK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DRO0P/btsftKgGBuP/Y0U3wKEk2s3Xn3LbBKILBK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDRO0P%2FbtsftKgGBuP%2FY0U3wKEk2s3Xn3LbBKILBK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;760&quot; height=&quot;447&quot; data-origin-width=&quot;1184&quot; data-origin-height=&quot;697&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;transaction.commit() 명령이 호출되기 전에&amp;nbsp; em.flush() 메서드가 호출된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #99cefa;&quot;&gt;&lt;b&gt;플러시(flush)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;플러시가 발생하면 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;영속성 컨텍스트에서는 최초 데이터 1차 캐시에 저장된 상태의 스냅샷과 현재 엔티티의 값을 비교&lt;/b&gt;&lt;/span&gt;하는 동작이 수행된다. 엔티티의 값이 변경이 된 경우라면 UPDATE 쿼리를 생성하여 SQL 쓰기 지연 저장소에 저장하고,&amp;nbsp; 데이터베이스에 쿼리를 보내게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;영속성 컨텍스트를 플러시 하는 방법은 총 3가지 이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&amp;nbsp; 1. 직접 flush() 호출&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&amp;nbsp; 2. transaction.commit()시 flush() 자동 호출&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&amp;nbsp; 3. JPQL 쿼리를 실행하게 되면 flush() 자동 호출&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;JPQL 쿼리 실행시 flush()가 자동으로 호출되는 이유는 무엇일까?&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;JPQL은 영속성 컨텍스트에 적용되는 것이 아니라 데이터베이스에 직접 쿼리를 날리게 된다. 영속성 컨텍스트에 있지만 flush() 되지 않은 객체를 찾는 쿼리를 날릴 경우 객체가 DB에 없어 조회되지 않기 때문에 JPQL 쿼리를 실행하게 되면 자동으로 flush()를 자동으로 호출하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Post&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;References&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.inflearn.com/course/ORM-JPA-Basic&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;자바 ORM 표준 JPA 프로그래밍 - 기본편 [김영한]&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignCenter&quot; data-emoticon-type=&quot;niniz&quot; data-emoticon-name=&quot;012&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘못된 코드나 내용이 있다면 댓글을 남겨주세요. 즉시 수정하도록 하겠습니다! :)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>JPA</category>
      <category>1차 캐시</category>
      <category>jpa</category>
      <category>변경 감지</category>
      <category>쓰기 지연</category>
      <category>플러쉬</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/174</guid>
      <comments>https://zangzangs.tistory.com/174#entry174comment</comments>
      <pubDate>Sat, 13 May 2023 00:02:29 +0900</pubDate>
    </item>
    <item>
      <title>스트림 활용하기, 중간연산과 최종연산 #filter #map #findAny #reduce</title>
      <link>https://zangzangs.tistory.com/172</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;스트림&amp;nbsp;활용하기,&amp;nbsp;중간연산과&amp;nbsp;최종연산&amp;nbsp;&lt;/b&gt;&lt;/h2&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;#filter #distinct&lt;/b&gt;&lt;/h2&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;#takeWhile #dropWhile #skip #limit&lt;/b&gt;&lt;/h2&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;#map #flatMap&lt;/b&gt;&lt;/h2&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;#anyMatch #allMatch #noneMatch&lt;/b&gt;&lt;/h2&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;#findAny #findFirst&lt;/b&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;안녕하세요? 장장스입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;오늘은 스트림 연산에 대해 정리해 보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1. 스트림 요소 필터링&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #99cefa;&quot;&gt;&lt;b&gt;filter 메서드&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1683436820870&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Stream&amp;lt;T&amp;gt; filter(Predicate&amp;lt;? super T&amp;gt; predicate);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;fillter 메서드는 프레디케이트(Predicate)를 인수로 받아서 프레디케이트와 일치하는 모든 요소를 포함하는 스트림을 반환한다.&lt;/p&gt;
&lt;pre id=&quot;code_1683437795916&quot; class=&quot;dart&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public static final List&amp;lt;Dish&amp;gt; menu = Arrays.asList(
      new Dish(&quot;pork&quot;, false, 800, Dish.Type.MEAT),
      new Dish(&quot;beef&quot;, false, 700, Dish.Type.MEAT),
      new Dish(&quot;chicken&quot;, false, 400, Dish.Type.MEAT),
      new Dish(&quot;french fries&quot;, true, 530, Dish.Type.OTHER),
      new Dish(&quot;rice&quot;, true, 350, Dish.Type.OTHER),
      new Dish(&quot;season fruit&quot;, true, 120, Dish.Type.OTHER),
      new Dish(&quot;pizza&quot;, true, 550, Dish.Type.OTHER),
      new Dish(&quot;prawns&quot;, false, 400, Dish.Type.FISH),
      new Dish(&quot;salmon&quot;, false, 450, Dish.Type.FISH)
  );&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;위와 같이 menu 리스트가 있을 때,&lt;/p&gt;
&lt;pre id=&quot;code_1683436949181&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;List&amp;lt;Dish&amp;gt; vegetarianMenu = menu.stream()
            .filter(Dish::isVegetarian)
            .collect(toList());

vegetarianMenu.forEach(System.out::println);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;isVegetarian 메서드는 Dish 인스턴스가 채소인지 확인하는 void-&amp;gt;boolean 형 메서드이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;출력 결과를 보면 다음과 같다.&lt;/p&gt;
&lt;pre id=&quot;code_1683436984013&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;french fries
rice
season fruit
pizza&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #99cefa;&quot;&gt;&lt;b&gt;distinct 메서드&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1683437547653&quot; class=&quot;abnf&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Stream&amp;lt;T&amp;gt; distinct();&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;distinct 메서드는 고유 요소를 필터링 하는 메서드이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;고유 여부는 스트림에서 만든 객체의 hashCode, equals로 결정이 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1683437655372&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;List&amp;lt;Integer&amp;gt; numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;위와 같이 numbers 리스트가 있을때,&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1683437659706&quot; class=&quot;java&quot; style=&quot;background-color: #f8f8f8; color: #383a42; text-align: start;&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;numbers.stream()
       .filter(i -&amp;gt; i % 2 == 0)
       .distinct()
       .forEach(System.out::println);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;짝수를 필터링하여 distinct 메서드를 실행하면, 다음과 같이 중복된 숫자가 제거 되어 출력된다.&lt;/p&gt;
&lt;pre id=&quot;code_1683437743338&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;2
4&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2. 스트림 슬라이싱&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;자바 9부터는 스트림의 요소를 선택할 수 있는 takeWhile, dropWhile 메서드를 지원한다.&lt;/p&gt;
&lt;pre id=&quot;code_1683439329150&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;List&amp;lt;Dish&amp;gt; specialMenu = Arrays.asList(
        new Dish(&quot;season fruit&quot;, true, 120, Dish.Type.OTHER),
        new Dish(&quot;prawns&quot;, false, 300, Dish.Type.FISH),
        new Dish(&quot;prawns and chips&quot;, false, 320, Dish.Type.FISH),
        new Dish(&quot;rice&quot;, true, 350, Dish.Type.OTHER),
        new Dish(&quot;chicken&quot;, false, 400, Dish.Type.MEAT),
        new Dish(&quot;french fries&quot;, true, 530, Dish.Type.OTHER)
        );&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;위와 같은 specialMenu 리스트가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #99cefa;&quot;&gt;&lt;b&gt;tak eWhile 메서드&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;takeWhile 메서드는 조건에 맞는 요소가 나왔을 때부터 반복 작업을 수행한다.&lt;/p&gt;
&lt;pre id=&quot;code_1683438226363&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;List&amp;lt;Dish&amp;gt; slicedMenu1 = specialMenu.stream()
                .takeWhile(dish -&amp;gt; dish.getCalories() &amp;lt; 320)
                .collect(toList());
                
slicedMenu1.forEach(System.out::println);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 출력 결과이다.&lt;/p&gt;
&lt;pre id=&quot;code_1683438308744&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;season fruit
prawns&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #99cefa;&quot;&gt;&lt;b&gt;dropWhile 메서드&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt; dropWhile 메서드는 takeWhile 의 정반대로 조건에 맞는 요소가 나올 때부터 반복작업을 수행한다.&lt;/p&gt;
&lt;pre id=&quot;code_1683439310051&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;List&amp;lt;Dish&amp;gt; slicedMenu2 = specialMenu.stream()
        .dropWhile(dish -&amp;gt; dish.getCalories() &amp;lt; 320)
        .collect(toList());
        
slicedMenu2.forEach(System.out::println);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 출력 결과이다.&lt;/p&gt;
&lt;pre id=&quot;code_1683438338161&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;prawns and chips
rice
chicken
french fries&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #99cefa;&quot;&gt;&lt;b&gt;limit 메서드&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;주어진 값 이하의 크기를 갖는 새로운 스트림을 반환한다.&lt;/p&gt;
&lt;pre id=&quot;code_1683439717052&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;List&amp;lt;Dish&amp;gt; dishesLimit3 = menu.stream()
                .filter(d -&amp;gt; d.getCalories() &amp;gt; 300)
                .limit(3)
                .collect(toList());

dishesLimit3.forEach(System.out::println);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;limit의 요소 3만큼 선택하여 리스트가 만들어진 것을 확인 할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1683439754302&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;pork
beef
chicken&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #99cefa;&quot;&gt;&lt;b&gt;skip 메서드&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;limit 메서드와 정반대로 처음 선택한 요소의 개수만큼을 제외한 스트림을 반환 할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1683439860952&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt; List&amp;lt;Dish&amp;gt; dishesSkip2 = menu.stream()
                .filter(d -&amp;gt; d.getCalories() &amp;gt; 300)
                .skip(2)
                .collect(toList());


dishesSkip2.forEach(System.out::println);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;처음 요소 2개를 제외한 모든 요소가 출력이 되는 것을 확인 할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1683439886786&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;chicken
french fries
rice
pizza
prawns
salmon&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3. 스트림 요소 매핑&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #99cefa;&quot;&gt;&lt;b&gt;map 메서드&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;스트림은 함수를 인수로 받는 map 메서드를 지원한다.&lt;/p&gt;
&lt;pre id=&quot;code_1683440363620&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;R&amp;gt; Stream&amp;lt;R&amp;gt; map(Function&amp;lt;? super T, ? extends R&amp;gt; mapper);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;인수로 제공된 함수는 각 요소에 적용되며 함수를 적용한 결과가 새로운 요소로 매핑된다.&lt;/p&gt;
&lt;pre id=&quot;code_1683440530582&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Function은 T-&amp;gt;R 함수형 인터페이스!&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1683440649697&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;List&amp;lt;String&amp;gt; words = Arrays.asList(&quot;Hello&quot;, &quot;World&quot;, &quot;Stream API&quot;, &quot;map&quot;);&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1683440644081&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;List&amp;lt;Integer&amp;gt; wordLengths = words.stream()
        .map(String::length)
        .collect(toList());

System.out.println(wordLengths);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;map 메서드에 인자로 들어간 length 함수의 반환값이  int 로 stream 요소의 값이 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;String에서 Integer로 매핑되는 것&lt;/b&gt;&lt;/span&gt;을 알 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1683440698564&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[5, 5, 10, 3]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #99cefa;&quot;&gt;&lt;b&gt;flatMap&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;flatMap 메서드는 배열을 스트림이 아니라 스트림의 콘텐츠로 매핑한다. 하나의 평면화된 스트림을 반환한다.&lt;/p&gt;
&lt;pre id=&quot;code_1683441902848&quot; class=&quot;reasonml&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;List&amp;lt;String&amp;gt; words = Arrays.asList(&quot;Hello&quot;, &quot;World&quot;, &quot;Stream API&quot;, &quot;map&quot;);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 문자열 배열에서 중복을 제외한 알파벳을 뽑아보자.&lt;/p&gt;
&lt;pre id=&quot;code_1683441887052&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;words.stream()
    .map(word -&amp;gt; word.split(&quot;&quot;))
    .flatMap(Arrays::stream)
    .distinct()
    .collect(toList());&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;flatMap 메서드는 문자열 배열(&lt;b&gt;String[]&lt;/b&gt;)을 하나의 평면화된 스트림으로 반환한다. 반환의 과정은 사진과 같다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1652&quot; data-origin-height=&quot;1014&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/loTbx/btsd6tuwagM/hv4UU8b08u4nG9gAHa6580/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/loTbx/btsd6tuwagM/hv4UU8b08u4nG9gAHa6580/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/loTbx/btsd6tuwagM/hv4UU8b08u4nG9gAHa6580/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FloTbx%2Fbtsd6tuwagM%2Fhv4UU8b08u4nG9gAHa6580%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;604&quot; height=&quot;371&quot; data-origin-width=&quot;1652&quot; data-origin-height=&quot;1014&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;4.스트림 요소 매칭&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #99cefa;&quot;&gt;&lt;b&gt;anyMatch 메서드&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;프레디케이트로 적어도 한 요소와 일치하는지 확인하는 메서드이다.&lt;/p&gt;
&lt;pre id=&quot;code_1683443634712&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;menu.stream()
    .anyMatch(Dish::isVegetarian);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #99cefa;&quot;&gt;&lt;b&gt;allMatch 메서드&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;스트림의 모든 요소가 주어진 프레디케이트와 일치하는지를 검사한다.&lt;/p&gt;
&lt;pre id=&quot;code_1683443683328&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;menu.stream()
    .allMatch(d -&amp;gt; d.getCalories() &amp;lt; 1000);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #99cefa;&quot;&gt;&lt;b&gt;noneMatch 메서드&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;allMatch 메서드와 정반대 연산을 수행한다. 스트림의 모든 요소가 일치하는 요소가 없는지 확인한다.&lt;/p&gt;
&lt;pre id=&quot;code_1683443700593&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;menu.stream()
    .noneMatch(d -&amp;gt; d.getCalories() &amp;gt;= 1000);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;5. 스트림 요소 검색&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #99cefa;&quot;&gt;&lt;b&gt;findAny 메서드&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;현재 스트림에서 임의의 요소를 반환한다. findAny 메서드를 다른 스트림연산과 연결해서 사용할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1683444003349&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;menu.stream()
    .filter(Dish::isVegetarian)
    .findAny();&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #99cefa;&quot;&gt;&lt;b&gt;findFirst 메서드&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size18&quot;&gt;리스트 또는 정렬된 연속된 데이터로부터 생성된 스트트림에서 논리적인 아이템 순서가 정해져 있을 수 있다. 이런 스트림에서 첫 번째 요소를 찾아 내는 메서드이다.&lt;/p&gt;
&lt;pre id=&quot;code_1683444033584&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;menu.stream()
    .filter(Dish::isVegetarian)
    .findFirst();&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;6. 리듀싱 (reduce)&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;스트림에서는 스트림의 모든 요소를 처리해서 값으로 도출하는 &lt;b&gt;리듀싱 연산&lt;/b&gt;을 지원한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #99cefa;&quot;&gt;&lt;b&gt;reduce 메서드&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;reduce 연산은 &lt;b&gt;초깃값&lt;/b&gt;과 &lt;b&gt;두요소를 조합해서 새로운 값을 만드는 BinaryOperator&amp;lt;T&amp;gt;&lt;/b&gt;를 2개의 인수로 갖는다.&lt;/p&gt;
&lt;pre id=&quot;code_1683444721010&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;List&amp;lt;Integer&amp;gt; numbers = Arrays.asList(3, 4, 5, 1, 2);&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1683444713412&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int sum = numbers.stream().reduce(0, (a, b) -&amp;gt; a + b);
System.out.println(sum);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;위 예제에서는 BinaryOperator 대신&amp;nbsp;람다 표현식 (a, b) -&amp;gt; a+b 를 사용했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;아래는 출력 결과이다.&lt;/p&gt;
&lt;pre id=&quot;code_1683444734777&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;15&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;reduce 연산은 스트림이 하나의 값이 될때까지 각 요소를 반복해서 조합한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #99cefa;&quot;&gt;&lt;b&gt;초깃값이 없는 reduce 메서드&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1683445009081&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Optional&amp;lt;Integer&amp;gt; min = numbers.stream().reduce((a,b) -&amp;gt; a+b);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이처럼 초깃값을 설정하지 않는 reduce도 있다. 여기서 주의할 점은 Optional을 반환하는 것이다. 예를 들어, 스트림에 아무 요소가 없는 경우 값을 반환 할 수 없다. 때문에 Optional을 감싸 값을 반환한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #99cefa;&quot;&gt;&lt;b&gt;reduce를 사용한 최댓값, 최솟값&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;reduce연산을 활용하여 최댓값과 최솟값을 연산 할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1683445178484&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Optional&amp;lt;Integer&amp;gt; min = numbers.stream().reduce(Integer::min);&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1683445191252&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Optional&amp;lt;Integer&amp;gt; min = numbers.stream().reduce(Integer::max);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Post&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-ke-size=&quot;size23&quot;&gt;&lt;a style=&quot;background-color: #e6f5ff; color: #0070d1; text-align: start;&quot; href=&quot;https://zangzangs.tistory.com/171&quot;&gt;[JAVA] - 자바 스트림 설명부터 사용하는 이유 파헤쳐보기 #JAVA #스트림&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot; href=&quot;https://zangzangs.tistory.com/170&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[JAVA] - 자바 람다 표현식 설명부터 사용법까지 완벽 정리 #JAVA #람다&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;References&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;모던 자바 인 액션&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignCenter&quot; data-emoticon-type=&quot;niniz&quot; data-emoticon-name=&quot;012&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘못된 코드나 내용이 있다면 댓글을 남겨주세요. 즉시 수정하도록 하겠습니다! :)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>JAVA</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/172</guid>
      <comments>https://zangzangs.tistory.com/172#entry172comment</comments>
      <pubDate>Sun, 26 Mar 2023 15:53:22 +0900</pubDate>
    </item>
    <item>
      <title>자바 스트림 설명부터 사용하는 이유 파헤쳐보기 #JAVA #스트림</title>
      <link>https://zangzangs.tistory.com/171</link>
      <description>&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;자바&amp;nbsp;스트림&amp;nbsp;설명부터&amp;nbsp;사용하는&amp;nbsp;이유&amp;nbsp;파헤쳐보기&amp;nbsp;#JAVA&amp;nbsp;#스트림&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;안녕하세요? 장장스입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;오늘은 자바 스트림에 대해서 정리해 보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;스트림(Stream)이란 무엇인가?&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;스트림(Stream)은 자바 8 API에 새로 추가된 기능이다. 스트림을 이용하면 선언형(더 간결하고 가독성이 좋도록)으로 컬렉션 데이터를 처리할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;※ JAVA Colletion Data의 상속구조&lt;/span&gt;&lt;br /&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bkSqoP/btrXo54Ecs5/SAyPANf79sPSLeMcQOZax0/img.png&quot; data-origin-width=&quot;598&quot; data-origin-height=&quot;366&quot; data-is-animation=&quot;false&quot; /&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;일단 스트림이 데이터 컬렉션 반복을 멋지게 처리하는 기능이라고 생각하자. 또한 스트림을 이용하면 멀티스레드 코드를 구현하지 않아도 데이터를 투명하게 병렬로 처리할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;예를 들어, Dish 클래스의 리스트 형태인(List&amp;lt;Dish&amp;gt;) menu 리스트가 있을 때, 저칼로리 순서대로 음식명을 추출하고자 한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1674976950706&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//1. low 칼로리 음식만 리스트로 추출한다.
List&amp;lt;Dish&amp;gt; lowCaloricDishes = new ArrayList&amp;lt;&amp;gt;();
for (Dish dish: menu){
    if (dish.getCalories() &amp;lt; 400) {
        lowCaloricDishes.add(dish);
    }
}

//2. low 칼로리 순서대로 음식을 정렬한다.
Collections.sort(lowCaloricDishes, new Comparator&amp;lt;Dish&amp;gt;() {
    @Override
    public int compare(Dish o1, Dish o2) {
        return Integer.compare(o1.getCalories(), o2.getCalories());
    }
});

//3. low 칼로리 음식의 이름만 리스트로 반환한다.
List&amp;lt;String&amp;gt; lowCaloricDishesName = new ArrayList&amp;lt;&amp;gt;();
for (Dish dish : lowCaloricDishes) {
    lowCaloricDishesName.add(dish.getName());
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;먼저 저칼로리의 음식을 리스트로 추출하기 위해 &lt;span style=&quot;color: #000000;&quot;&gt;lowCaloricDishes 리스트를 만들고&lt;/span&gt;, 칼로리 순서대로 정렬 후,&amp;nbsp; 음식 이름만을&amp;nbsp;&lt;span style=&quot;color: #000000;&quot;&gt;lowCaloricDishesName&lt;/span&gt; 리스트로 추출할 수 있다. 이때, &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;u&gt;중간에 데이터를 담기 위한&amp;nbsp;&lt;span style=&quot;color: #000000;&quot;&gt;lowCaloricDishes라는 &lt;b&gt;'가비지 변수'&lt;/b&gt;를 사용하게 된다.&lt;/span&gt;&lt;/u&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #9d9d9d;&quot;&gt;(코드가 매우 길고 보기가 좋지 않다..!)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;스트림을 이용하면 아래의 코드처럼 &lt;span style=&quot;color: #000000;&quot;&gt;lowCaloricDishesName리스트를 추출할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1674978051687&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;List&amp;lt;String&amp;gt; lowCaloricDishesName =
    menu.stream()
        .filter(d -&amp;gt; d.getCalories() &amp;lt; 400)
        .sorted(Comparator.comparing(Dish::getCalories))
        .map(d -&amp;gt; d.getName())
        .collect(Collectors.toList());&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;일반적인 명령형 프로그래밍의 for문을 사용할 때와 비교하면 확실히 스트림이 더 간결하고, 가독성이 좋아진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;그래서&amp;nbsp; 스트림(Stream)이 뭔데!&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;스트림(Stream)은 &lt;u&gt;&lt;b&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;데이터 처리 연산&lt;/span&gt;을 지원하도록 &lt;span style=&quot;background-color: #c1bef9;&quot;&gt;소스&lt;/span&gt;에서 추출된 &lt;span style=&quot;background-color: #99cefa;&quot;&gt;연속된 요소&lt;/span&gt;&lt;/b&gt;&lt;/u&gt;로 정의할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;데이터 처리 연산&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;스트림은 함수형 프로그래밍 언어에서 일반적으로 지원하는 연산과 데이터베이스와 비슷한 연산을 지원한다. 예를 들어 filter, map, reduce, find, match, sort 등으로 데이터를 조작할 수 있다. 스트림 연산은 데이터를 순차적으로 또는 병렬로 실행할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #c1bef9;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;소스&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;스트림은 컬렉션, 배열, I/O 자원 등의 데이터 제공 소스로부터 데이터를 소비한다. 정렬된 컬렌션으로 스트림을 생성하면 정렬이 그대로 유지된다. 즉, 리스트로 스트림을 만들면 스트림의 요소는 리스트의 요소와 같은 순서를 유지한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #99cefa;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;연속된 요소&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;컬렉션과 마찬가지로 스트림은 특정 요소 형식으로 이루어진 연속된 값 집합의 인터페이스를 제공한다. 컬렉션은 자료구조이므로 컬렉션에서는 시간과 공간의 복잡성과 관련된 요소 저장(ex: add) 및 접근(ex: get) 연산이 주를 이룬다. 반면, 스트림은 filter, map, sorted처럼 표현 계산식이 주를 이룬다. 정리하면, 컬렉션의 주제는 데이터이고, 스트림의 주제는 계산이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;스트림(Stream)의 특징&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;파이프 라이닝&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;부분의 스트림 연산은 스트림 연산끼리 연결해서 커다란 파이프 라인을 구성할 수 있도록 스트림 자신을 반환한다. 그 덕분에 &lt;b&gt;layziness(게으름)&lt;/b&gt;, &lt;b&gt;short-circuiting(쇼트서킷) 같은&lt;/b&gt; 최적화도 얻을 수 있다. 연산 파이프라인은 데이터 소스에 적용하는 데이터베이스 질의와 비슷하다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;layziness(게으름)은 최종연산이 실행되기 전까지 중간연산(filter, sorted, map, ..)이 실행되지 않는 것을 말한다.&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;short-circuiting(쇼트서킷)은 여러 개의 조건이 중첩된 상황에서 값이 결정 나면 더 이상 불필요한 실행을 하지 않도록 하여 실행 속도를 올리는 기법을&amp;nbsp; 말한다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;내부 반복&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;반복자를 이용해서 명시적으로 반복하는 컬렉션과 달리 스트림은 내부 반복을 지원한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;컬렉션과 스트림&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;데이터를 &lt;span style=&quot;background-color: #f6e199; color: #ee2323;&quot;&gt;&lt;b&gt;언제&lt;/b&gt;&lt;/span&gt; 계산하느냐가 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;컬렉션&lt;/span&gt;과 &lt;span style=&quot;background-color: #99cefa;&quot;&gt;스트림&lt;/span&gt;의 가장 큰 차이이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;컬렉션&lt;/span&gt;은 우리가 아는 DVD와 비슷하다. 영상 전체 데이터를 CD에 모두 담고 있다. &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;&lt;b&gt;컬렉션은 현재 자료구조가 포함하는 모든 값을 메모리에 저장하는 자료 구조다&lt;/b&gt;.&lt;/span&gt; 즉, 컬렉션의 모든 요소는 컬렉션에 추가하기 전에 계산되어야 한다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;반면, &lt;span style=&quot;background-color: #99cefa;&quot;&gt;스트림&lt;/span&gt;은 스트리밍 서비스와 비슷하다. 사용자가 필요로 하는 몇 부분만 미리 내려받는다. 스트림은 이론적으로 &lt;span style=&quot;background-color: #99cefa;&quot;&gt;&lt;b&gt;요청할 때만 요소를 계산하는 고정된 자료구조이다.&lt;/b&gt;&lt;/span&gt; 사용자가 요청하는 값만 추출하는 것이 스트림의 핵심이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;또 다른 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;컬렉션&lt;/span&gt;과 &lt;span style=&quot;background-color: #99cefa;&quot;&gt;스트림&lt;/span&gt;의 차이점은 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;&lt;b&gt;외부 반복&lt;/b&gt;&lt;/span&gt;과 &lt;span style=&quot;background-color: #99cefa;&quot;&gt;&lt;b&gt;내부 반복&lt;/b&gt;&lt;/span&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;컬렉션&lt;/span&gt;을 사용하려면 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;&lt;b&gt;사용자가 직접 요소를 반복(ex: for-each문)해야 하는데 이를 외부 반복이라 한다.&lt;/b&gt;&lt;/span&gt; 반면 &lt;span style=&quot;background-color: #99cefa;&quot;&gt;스트림&lt;/span&gt;은 &lt;b&gt;&lt;span style=&quot;background-color: #99cefa;&quot;&gt;반복을 알아서 처리하고 결과 스트림 값을 어딘가에 저장해 주는 내부 반복을 사용한다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;예제를 들어 조금 더 자세히 알아보자. &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;수학점수와 학년을 변수로 갖는 Score 리스트가 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1676788569689&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public static final List&amp;lt;Score&amp;gt; scores = Arrays.asList(
    new Score(100, GRADE.GRADE4)
    ,new Score(80, GRADE.GRADE1)
    ,new Score(17, GRADE.GRADE3)
    ,new Score(50, GRADE.GRADE4)
    ,new Score(28, GRADE.GRADE3)
    ,new Score(30, GRADE.GRADE2)
    ,new Score(98, GRADE.GRADE1)
    ,new Score(69, GRADE.GRADE4)
    ,new Score(87, GRADE.GRADE3)
    ,new Score(76, GRADE.GRADE2)
);

// Score 클래스 일부 소스코드
public static class Score{
    private int math;
    private GRADE grade;

    public Score(int math, GRADE grade) {
        this.math = math;
        this.grade=grade;
    }

    @Override
    public String toString() {
        return &quot;Score{&quot; +
                &quot;math=&quot; + math +
                &quot;, grade=&quot; + grade +
                '}';
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;List&amp;lt;Score&amp;gt; 에서 학년이 4학년인 학생들의 수학 점수를 추출하려고 한다. 스트림을 활용한 아래의 코드가 실행되면 출력이 어떻게 될까?&lt;/p&gt;
&lt;pre id=&quot;code_1676788396777&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;scores.stream()
    .filter(g -&amp;gt; {
        System.out.println(&quot;filter 연산 : &quot; + g.toString());
        return g.getGrade().equals(GRADE.GRADE4);
    })
    .map(m -&amp;gt; {
        System.out.println(&quot;map 연산  : &quot; + m.toString());
        return m.getMath();
    })
    .limit(2)
    .forEach(System.out::println);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;정답을 생각해 보면 4학년 학생의 수학점수 100, 50이 출력이 될 것이다. 그리고&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중간연산 filter, map의 print문을 한번 살펴보자. 출력 결과는 아래와 같다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1676789452113&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;filter 연산 : Score{math=100, grade=GRADE4}
map 연산  : Score{math=100, grade=GRADE4}
100
filter 연산 : Score{math=80, grade=GRADE1}
filter 연산 : Score{math=17, grade=GRADE3}
filter 연산 : Score{math=50, grade=GRADE4}
map 연산  : Score{math=50, grade=GRADE4}
50&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;List&amp;lt;Score&amp;gt;에는 10개의 데이터가 있었지만 모두 실행되지 않았다. 출력 내용을 하나씩 살펴보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;Score(100, GRADE.GRADE4)&lt;/b&gt;&lt;/span&gt;인 학생은 4학년에 해당되므로 중간연산 filter, map의 출력문이 실행되고, forEach문이 실행되었다.&lt;/p&gt;
&lt;pre id=&quot;code_1676790780890&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;filter 연산 : Score{math=100, grade=GRADE4}
map 연산  : Score{math=100, grade=GRADE4}
100&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;Score(80, GRADE.GRADE1)&lt;/b&gt;&lt;/span&gt;인 학생은 1학년이므로, filter의 출력문만 실행되었다.&lt;/p&gt;
&lt;pre id=&quot;code_1676790793769&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;filter 연산 : Score{math=80, grade=GRADE1}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;Score(17, GRADE.GRADE3)&lt;/b&gt;&lt;/span&gt;인 학생은 3학년이므로, filter의 출력문만 실행되었다.&lt;/p&gt;
&lt;pre id=&quot;code_1676790804853&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;filter 연산 : Score{math=17, grade=GRADE3}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Score(50, GRADE.GRADE4)인 학생은 4학년에 해당되므로 중간연산 filter, map의 출력문이 실행되고, forEach문이 실행되었다.&lt;/p&gt;
&lt;pre id=&quot;code_1676790814886&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;filter 연산 : Score{math=50, grade=GRADE4}
map 연산  : Score{math=50, grade=GRADE4}
50&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;그 이후의 데이터는 limit(2)를 만족하는 결과를 얻었기 때문에 연산이 수행되지 않았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;스트림 연산&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;스트림의 연산은 크게 &lt;b&gt;중간 연산&lt;/b&gt;과 &lt;b&gt;최종 연산&lt;/b&gt;으로 나눈다. 스트림은 왜 연산을 두 가지로 구분하는 것일까?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중간 연산&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;filter나 sorted 같은 중간 연산은 다른 스트림을 반환한다. 따라서 다양한 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;중간연산을 연결하여 질의를 만들 수 있다.(루프 퓨전[loop fusion]이라 한다)&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;중간 연산의 중요한 특징은 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;단말 연산을 스트림 파이프라인에 실행하기 전까지는 아무 연산도 수행하지 않는다는 것&lt;/b&gt;&lt;/span&gt;이다. 즉, 게으름(lazy) 특성을 같는다. 중간 연산을 합친 다음에 합쳐진 중간 연산을 최종 연산으로 한 번에 처리하기 때문이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;위에서 사용했던 예제 코드를 다시 살펴보자.&lt;/p&gt;
&lt;pre id=&quot;code_1676792444725&quot; class=&quot;reasonml&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;scores.stream()
    .filter(g -&amp;gt; {
        System.out.println(&quot;filter 연산 : &quot; + g.toString());
        return g.getGrade().equals(GRADE.GRADE4);
    })
    .map(m -&amp;gt; {
        System.out.println(&quot;map 연산  : &quot; + m.toString());
        return m.getMath();
    })
    .limit(2)
    .forEach(System.out::println);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;스트림의 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;게으름(&lt;b&gt;layziness&lt;/b&gt;)&lt;/b&gt; 특성 덕분에 List &amp;lt;score&amp;gt;의 개수는 10개이지만 단말연산 limit(2) 덕분에 처음 2개의 결과가 나올 때까지만 반복이 수행&lt;/span&gt;되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;중간 연산 filter, map이 서로 다른 연산이지만 한 과정으로 병합되어 수행되었는데, 이를 &lt;b&gt;루프 퓨전(loop fusion)&lt;/b&gt;이라 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;최종 연산&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;최종 연산은 스트림 파이프라인에서 결과를 도출한다. 보통 최종 연산에 의해 List, Integer, void 등 스트림 이외의 결과가 반환된다. 예제 코드의 파이프라인에서 forEach는 void를 반환하는 최종 연산이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Post&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://zangzangs.tistory.com/170&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;자바 람다 표현식 설명부터 사용법까지 완벽 정리 #JAVA #람다&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;References&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모던 자바 인 액션&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignCenter&quot; data-emoticon-type=&quot;niniz&quot; data-emoticon-name=&quot;012&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;잘못된 코드나 내용이 있다면 댓글을 남겨주세요. 즉시 수정하도록 하겠습니다! :)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>JAVA</category>
      <category>java</category>
      <category>stream</category>
      <category>게으름</category>
      <category>루프 퓨전</category>
      <category>쇼트서킷</category>
      <category>스트림</category>
      <category>자바</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/171</guid>
      <comments>https://zangzangs.tistory.com/171#entry171comment</comments>
      <pubDate>Sun, 29 Jan 2023 16:53:38 +0900</pubDate>
    </item>
    <item>
      <title>자바 람다 표현식 설명부터 사용법까지 완벽 정리  #JAVA #람다</title>
      <link>https://zangzangs.tistory.com/170</link>
      <description>&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자바&amp;nbsp;람다&amp;nbsp;표현식&amp;nbsp;설명부터&amp;nbsp;사용법까지&amp;nbsp;완벽&amp;nbsp;정리&amp;nbsp;&amp;nbsp;#JAVA&amp;nbsp;#람다&lt;/span&gt;&lt;/h2&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;안녕하세요? 장장스입니다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;오늘은 자바 8에 추가된 람다에 대해 정리하겠습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;람다란 무엇인가?&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;람다 표현식은 메서드로 전달할 수 있는 익명 함수를 단순화한 것이라고 할 수 있습니다. 람다 표현식에는 이름은 없지만, &lt;b&gt;파라미터 리스트, 바디, 반환 형식, 발생할 수 있는 예외 리스트&lt;/b&gt;를 가질 수 있습니다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;람다의 특징을 하나씩 살펴보면,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;▶ 익명&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;보통의 메서드와 달리 이름이 없으므로 익명이라 표현한다. 구현해야 할 코드가 줄어든다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;▶ 함수&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;람다는 메서드처럼 특정 클래스에 종속되지 않으므로 함수라고 부른다. 하지만 메서드처럼 파라미터 리스트, 바디, 반환 형식, 가능한 예외 리스트를 포함한다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;▶ 전달&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;람다 표현식을 메서드 인수로 전달하거나 변수로 저장할 수 있다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;▶ 간결성&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;익명 클래스처럼 많은 자질구레한 코드를 구현할 필요가 없다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;익명 클래스란?&lt;/b&gt; &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;말 그대로 이름이 없는 클래스로, &lt;b&gt;일시적으로 만들어서 사용되고 버려지는 클래스&lt;/b&gt;를 말한다. &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Comparator 클래스를 직접 구현하여 사용 하는 것을 예로 들 수 있다.&amp;nbsp; &lt;/span&gt;&lt;br /&gt;
&lt;pre id=&quot;code_1672671238374&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Comparator&amp;lt;Tiger&amp;gt; comparator = new Comparator&amp;lt;Tiger&amp;gt;() {
  @Override
  public int compare(Tiger t1, Tiger t2) {
    return Integer.compare(t1.getWeight(), t2.getWeight());
  }
};&lt;/code&gt;&lt;/pre&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;위의 익명 클래스를 이용한 코드를 람다를 사용하면 아래처럼 바꿀 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;Comparator&amp;lt;Tiger&amp;gt; byWeight = 
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(Tiger t1, Tiger t2) -&amp;gt; t1.getWeight() - t2.getWeight();&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;람다 표현식은 &lt;span style=&quot;background-color: #99cefa;&quot;&gt;&lt;b&gt;람다 파라미터&lt;/b&gt;&lt;/span&gt;, &lt;span style=&quot;background-color: #99cefa;&quot;&gt;&lt;b&gt;화살표&lt;/b&gt;&lt;/span&gt;, &lt;span style=&quot;background-color: #99cefa;&quot;&gt;&lt;b&gt;람다 바디&lt;/b&gt;&lt;/span&gt;로 구성된다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1768&quot; data-origin-height=&quot;436&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cJC21r/btrVAtzR6p9/CZsV2ALwlaqQ5qrhrwkooK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cJC21r/btrVAtzR6p9/CZsV2ALwlaqQ5qrhrwkooK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cJC21r/btrVAtzR6p9/CZsV2ALwlaqQ5qrhrwkooK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcJC21r%2FbtrVAtzR6p9%2FCZsV2ALwlaqQ5qrhrwkooK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;600&quot; height=&quot;436&quot; data-origin-width=&quot;1768&quot; data-origin-height=&quot;436&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;람다는 어디에 어떻게 쓰일까?&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그래서 람다 표현식은 &lt;u&gt;&lt;b&gt;어디에 어떻게 쓰는지에 대한 궁금증&lt;/b&gt;&lt;/u&gt;이 생긴다. 함수형 인터페이스라는 문맥에서 람다 표현식을 사용할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;함수형 인터페이스(Functional Interface)?&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;함수형 인터페이스(Functional Interface)&lt;/span&gt;는 정확히 하나의 추상 메서드를 지정하는 인터페이스다. 위에서 사용했던 Comparator도 자바 API의 함수형 인터페이스이다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;※&amp;nbsp;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;함수형 인터페이스&lt;/span&gt;는 &lt;b&gt;@FunctionalInterface&lt;/b&gt; 어노테이션을 사용해서 표기한다. &lt;br /&gt;&lt;span style=&quot;background-color: #fcfcfc;&quot;&gt;필수적으로 구현해야 하는 추상 메서드가 1개 있으며, &lt;/span&gt;&lt;b&gt;@FunctionalInterface&lt;/b&gt; 로 선언했지만 실제로 함수형 인터페이스가 아닌경우 컴파일 에러를 발생할 수 있다.&lt;br /&gt;&amp;nbsp;&lt;br /&gt;위에서 예시로 사용했던 함수형 인터페이스 &lt;span style=&quot;background-color: #fcfcfc;&quot;&gt;Comparator는&lt;/span&gt; 추상 메서드 &lt;span style=&quot;background-color: #fcfcfc;&quot;&gt;compare&lt;/span&gt;를 직접 구현하여야 한다. &lt;/span&gt;&lt;br /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1462&quot; data-origin-height=&quot;248&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cHbfCA/btrVI6Xrd1S/O3qYGGMn2a45mIyy0cqeO1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cHbfCA/btrVI6Xrd1S/O3qYGGMn2a45mIyy0cqeO1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cHbfCA/btrVI6Xrd1S/O3qYGGMn2a45mIyy0cqeO1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcHbfCA%2FbtrVI6Xrd1S%2FO3qYGGMn2a45mIyy0cqeO1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;119&quot; data-origin-width=&quot;1462&quot; data-origin-height=&quot;248&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;람다 표현식으로 함수형 인터페이스의 추상 메서드 구현을 직접하여 전달할 수 있으므로 전체 표현식을 &lt;b&gt;함수형 인터페이스의 인스턴스로 &lt;/b&gt;취급할 수 있다. (자바 문법으로는 함수형 인터페이스를 구현한 클래스의 인스턴스이다.) &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;함수 디스크립터(function descriptor)&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;람다 표현식의 시그니처를 서술하는 추상 메서드를 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;함수 디스크립터(function descriptor)&lt;/b&gt;&lt;/span&gt;라고 부른다. 람다 표현식의 시그니처는 함수형 인터페이스의 추상 메서드 시그니처와 동일하다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;예를 들어, Comparator 인터페이스의 메서드 compare가 &lt;span style=&quot;background-color: #99cefa;&quot;&gt;&lt;u&gt;&lt;b&gt;두개의 인수를 받아 int를 반환&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;하므로 Comparator 인터페이스는 &lt;span style=&quot;background-color: #99cefa;&quot;&gt;&lt;u&gt;&lt;b&gt;두개의 인수를 받아 int를 반환하는 시그니처&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;로 볼 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1462&quot; data-origin-height=&quot;248&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cHbfCA/btrVI6Xrd1S/O3qYGGMn2a45mIyy0cqeO1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cHbfCA/btrVI6Xrd1S/O3qYGGMn2a45mIyy0cqeO1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cHbfCA/btrVI6Xrd1S/O3qYGGMn2a45mIyy0cqeO1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcHbfCA%2FbtrVI6Xrd1S%2FO3qYGGMn2a45mIyy0cqeO1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;119&quot; data-origin-width=&quot;1462&quot; data-origin-height=&quot;248&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;다른 예로, Runnable 인터페이스의 추상 메서드 run은 &lt;span style=&quot;background-color: #99cefa;&quot;&gt;&lt;u&gt;&lt;b&gt;파라미터를 받지 않고 void를 반환&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;하므로 Runnable 인터페이스의 시그니처는 &lt;span style=&quot;background-color: #99cefa;&quot;&gt;&lt;u&gt;&lt;b&gt;파라미터를 받지 않고 void를 반환&lt;/b&gt;&lt;/u&gt;&lt;/span&gt; 하는 것으로 생각하면 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1492&quot; data-origin-height=&quot;254&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c1p8wp/btrVGZK4y1T/dyVK3ccTnaiu5ZV6gk7ff0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c1p8wp/btrVGZK4y1T/dyVK3ccTnaiu5ZV6gk7ff0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c1p8wp/btrVGZK4y1T/dyVK3ccTnaiu5ZV6gk7ff0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc1p8wp%2FbtrVGZK4y1T%2FdyVK3ccTnaiu5ZV6gk7ff0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;119&quot; data-origin-width=&quot;1492&quot; data-origin-height=&quot;254&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;확인된 예외(Exception)을 던지지 않는 함수형 인터페이스&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;메서드를 만들때 우리는 확인된 예외(Exception)를 던지는 일을 한다. 아래 예시를 보면, BufferedReader 클래스의 readLine 함수를 사용했을 때, IOException이 예상이 된다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public void printInputText() throws IOException {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;String s = bufferedReader.readLine();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;System.out.printf(&quot;inputText : %s&quot;, s);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;그러나 람다는 확인된 예외를 던지기 위해서는 확인된 예외를 선언하는 함수형 인터페이스를 직접 정의하거나, 람다를 try~catch문을 사용하여 감싸야한다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;1. 확인된 예외를 선언하는 함수형 인터페이스 정의&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;BufferedReader를 사용할 때 발생할 수 있는 IOException을 선언하는 함수형 인터페이스를 직접 정의하여 사용 할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@FunctionalInterface
public interface BufferedReaderProcessor{
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;String process(BufferedReader bufferedReader) throws IOException;
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;java&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;BufferedReaderProcessor bufferedReaderProcessor =
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;(BufferedReader bufferedReader) -&amp;gt; bufferedReader.readLine();

String s = bufferedReaderProcessor.process(new BufferedReader(new InputStreamReader(System.in)));&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;2. try~catch문으로 사용하여 감싸기&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;BufferedReader를 사용할 때 발생할 수 있는 IOException을 try~catch 문으로 감싼다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public void printInputText(){
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Function&amp;lt;BufferedReader, String&amp;gt; function = (BufferedReader br) -&amp;gt; {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;try {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return br.readLine();
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;} catch (IOException e) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;throw new RuntimeException(e);
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;};

&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;String s = function.apply(new BufferedReader(new InputStreamReader(System.in)));
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;System.out.printf(&quot;inputText : %s&quot;, s);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;자바8의 함수형 인터페이스&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;다양한 람다 표현식을 사용하려면 다양한 함수 디스크립터를 기술하는 함수형 인터페이스들이 필요하다. 자바 API는 다양한 함수형 인터페이스들을 제공한다.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-style=&quot;style9&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;background-color: #9feec3; color: #000000;&quot;&gt;&lt;b&gt;함수형 인터페이스&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;background-color: #9feec3; color: #000000;&quot;&gt;&lt;b&gt;함수 디스크립터&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;background-color: #9feec3; color: #000000;&quot;&gt;&lt;b&gt;기본형 특화&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Predicate&amp;lt;T&amp;gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;T -&amp;rsaquo; boolean&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;IntPredicate&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;LongPredicate&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;DoublePredicate&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Consumer&amp;lt;T&amp;gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;T -&amp;gt; void&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;IntConsumer&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;LongConsumer&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;DoubleConsumer&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Function&amp;lt;T&amp;gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;T -&amp;gt; R&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;IntFunction&amp;lt;R&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;IntToDoubleFunction&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;IntToLongFunction&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;LongFunction&amp;lt;R&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;LongToDoubleFunction&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;LongToIntFunction&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;DoubleFunction&amp;lt;R&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;DoubleToIntFunction&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;DoubleToLongFunction&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ToIntFunction&amp;lt;T&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ToLongFunction&amp;lt;T&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ToDoubleFunction&amp;lt;T&amp;gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Supplier&amp;lt;T&amp;gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;() -&amp;gt; T&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;BooleanSupplier&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;IntSupplier&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;LongSupplier&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;DoubleSupplier&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;UnaryOperator&amp;lt;T&amp;gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;T -&amp;gt; T&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;IntUnaryOperator&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;LongUnaryOperator&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;DoubleUnary0perator&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;BinaryOperator&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(T, T) -&amp;gt; T&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;IntBinaryOperator&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;LongBinaryOperator&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;DoubleBinary0perator&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;BiPredicate&amp;lt;L, R&amp;gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(L, R) -&amp;gt; boolean&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;BIConsumer&amp;lt;T, U&amp;gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(T, U) -&amp;gt; void&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ObjIntConsumer&amp;lt;T&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ObjLongConsumer&amp;lt;T&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ObjDoubleConsumer&amp;lt;T&amp;gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;BIFunction&amp;lt;T, U, R&amp;gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(T, U) -&amp;gt; R&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ToIntBiFunction&amp;lt;T, U&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ToLongBiFunction&amp;lt;T, U&amp;gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;ToDoubleBiFunction&amp;lt;T, U&amp;gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;람다로 함수형 인터페이스의 인스턴스는 어떻게 만드는 걸까?&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;람다 표현식은 함수형 인터페이스의 인스턴스를 만들 수 있다. 그러나 람다 표현식 자체에는 람다가 어떤 함수형 인터페이스를 구현하는지의 정보가 포함되어 있지 않다. 따라서 람다 표현식을 이해하려면 실제 함수형 인터페이스의 형식을 파악해야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;public void filterHeavyTiger(){
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;List&amp;lt;Tiger&amp;gt; heavierThen290kg = filter(tigers, (Tiger tiger) -&amp;gt; tiger.getWeight() &amp;gt; 290);
}

public static List&amp;lt;Tiger&amp;gt; filter(List&amp;lt;Tiger&amp;gt; tigers, Predicate&amp;lt;Tiger&amp;gt; predicate) {
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;return tigers.stream()
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .filter(predicate)
&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; .collect(Collectors.toList());
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;위 코드는 호랑이 몸무게가 290kg을 넘는 호랑이를 필터링 하기 위한 filterHeavyTiger 메서드이다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;(Tiger tiger) -&amp;gt; tiger.getWeight() &amp;gt; 290&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;여기에 사용된 람다는 어떻게 Predicate 함수형 인터페이스인 것을 확인 할 수 있었을까? &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;람다의 형식 검사&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;람다가 사용되는 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;콘텍스트(context)&lt;/b&gt;&lt;/span&gt;를 이용해서 람다의 형식을 추론할 수 있다. 어떤 콘텍스트에서 기대되는 람다 표현식을 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;대상 형식(target type)&lt;/b&gt;&lt;/span&gt;이라고 부른다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;(Tiger tiger) -&amp;gt; tiger.getWeight() &amp;gt; 290&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;위 코드의 형식검사의 과정을 살펴보면 아래와 같다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;1. &lt;/b&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;b&gt;람다가 사용된 콘텍스트는 무엇인가?&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- filter 메서드를 확인한다. &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;2. &lt;/b&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;b&gt;대상 형식을 확인한다.&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- 두 번째 파라미터가 Predicate&amp;lt;Tiger&amp;gt; 대상 형식을 기대한다. &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;3. &lt;/b&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;b&gt;대상 형식(Predicate&amp;lt;Tiger&amp;gt;)의 추상 메서드는 무엇인가?&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- Predicate&amp;lt;Tiger&amp;gt;는 test 추상 메서드를 정의하는 함수형 인터페이스이다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- 이해가 안가면 Predicate 인터페이스를 확인해 보자&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;4. &lt;/b&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;b&gt;Tiger를 인수로 받아 boolean을 반환하는 test 메서드다&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #99cefa;&quot;&gt;&lt;b&gt;.&lt;/b&gt;&lt;/span&gt; &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- test 메서드는 Tiger를 받아 boolean을 반환하는 함수 디스크립터를 묘사한다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;5. &lt;/b&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;b&gt;함수 디스크립터와 람다의 시그니처와 일치를 확인한다.&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;- 형식 검사가 완료 된다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;대상 형식(Target Type)이라는 특징 때문에 같은 람다 표현식이더라도 호환되는 추상 메서드를 가진 다른 함수형 인터페이스로 사용될 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;Callable&amp;lt;Integer&amp;gt; c&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; = () -&amp;gt; 7;&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;java&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;PrivilegedAction&amp;lt;Integer&amp;gt; p = () -&amp;gt; 7;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Callable과 PrivilegedAction는 파라미터를 받지 않고, 제네릭 형식 T를 반환하는 함수를 정의한다. 따라서 위 코드는 모두 유효한 코드이다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;형식 추론&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자바 컴파일러는 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;대상 형식(콘텍스트)을 이용해서 함수 디스크립터를 알 수 있으므로 컴파일러는 람다의 시그니처도 추론&lt;/b&gt;&lt;/span&gt;할 수 있다. 결과적으로 컴파일러는 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;람다 표현식의 파라미터 형식에 접근할 수 있으므로 람다 문법에서 이를 생략&lt;/b&gt;&lt;/span&gt;할 수 있다. 즉, 자바 컴파일러는 다음 처럼 람다 파라미터 형식을 추론할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;Comparator&amp;lt;Tiger&amp;gt; c1 = (Tiger t1, Tiger t2) -&amp;gt; t1.getWeight().compareTo(t2.getWeight());&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;java&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;Comparator&amp;lt;Tiger&amp;gt; c2 = (t1, t2) -&amp;gt; t1.getWeight().compareTo(t2.getWeight());&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;어떤 코드가 더 좋다라고는 할 수 없다. 상황에 따라 형식을 배제하는 것이 가독성을 향상 시킬 수도 있고, 떨어지게 할 수도 있다. 이는 개발자 스스로 어떤 코드가 가독성을 향상시킬 수 있을지 결정해야 한다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;람다의 제약&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;지금까지 람다 표현식 설명을 위해 사용한 코드들을 보면 람다 표현식은 인수를 자신의 바디 안에서만 사용했다. 하지만 람다 표현식에서는 익명 함수가 하는 것처럼 자유 변수를 활용할 수 있다. 이와 같은 동작을 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;람다 캡처링&lt;/b&gt;&lt;/span&gt;이라고 부른다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;int waitNumber = 102;
Runnable r = () -&amp;gt; System.out.println(waitNumber);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;위의 코드는 유효한 코드로 정상 동작한다. 그렇다면 다음 코드는 어떻게 될까?&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;int waitNumber = 102;
Runnable r = () -&amp;gt; System.out.println(waitNumber);
waitNumber = 500;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 코드는 컴파일 에러가 발생한다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1198&quot; data-origin-height=&quot;160&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cyvzLY/btrWdokAA8r/vt7AFxRHFMtaxKwOUSwSs1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cyvzLY/btrWdokAA8r/vt7AFxRHFMtaxKwOUSwSs1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cyvzLY/btrWdokAA8r/vt7AFxRHFMtaxKwOUSwSs1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcyvzLY%2FbtrWdokAA8r%2Fvt7AFxRHFMtaxKwOUSwSs1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;93&quot; data-origin-width=&quot;1198&quot; data-origin-height=&quot;160&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;람다 표현식에서 자유 변수에 제약이 있다. 람다는 인스턴스 변수와 정적 변수를 자유롭게 캡처할 수 있다. 하지만 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;지역 변수는 명시적으로 final로 선언 되어 있어야 하거나 실질적으로 final로 선언된 변수와 똑같이 사용&lt;/b&gt;&lt;/span&gt;되어야 한다. 즉, 람다 표현식은 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;한번만 할당할 수 있는 지역 변수를 캡처&lt;/b&gt;&lt;/span&gt;할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;람다에는 왜 이런 제약이 걸리는걸까?&lt;/b&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;자바에서 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;인스턴스 변수는 힙 메모리&lt;/span&gt;에 저장된다. 반면 &lt;span style=&quot;background-color: #c1bef9;&quot;&gt;지역 변수는 스택 메모리&lt;/span&gt;에 저장된다. &lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;람다가 스레드에서 실행되면 변수를 할당한 스레드가 사라져서 지역 변수의 할당이 해제되었는데도 람다를 실행하는 스레드에서는 해당 지역 변수에 접근하려 할 수 있다.&lt;/b&gt;&lt;/u&gt; 따라서 자바 구현에서는 원래 변수에 접근을 허용하지 않고 &lt;u&gt;&lt;b&gt;자유 지역 변수의 복사본을 제공&lt;/b&gt;&lt;/u&gt;한다. &lt;br /&gt;따라서 복사본의 값이 바뀌지 않아야 하므로 자유 지역 변수에는 한번만 값을 할당해야 한다는 제약이 생긴 것이다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;메서드 참조&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자바에는 메서드 참조 기능이 있다. 메서드 참조는 특정 메서드만을 호출하는 람다의 축약형이라고 생각할 수 있다. 예를 들어 람다가 '이 메서드를 직접 호출해' 라고 명령한다면 메서드를 어떻게 호출해야 하는지 설명을 참조하기보다는 메서드명을 직접 참조하는 것이 편리하다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이때 명시적으로 메서드명을 참조함으로써 가독성을 높일 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-type=&quot;codeblock&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;tigers.sort(Comparator.comparing(Tiger::getWeight));&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;메서드명 앞에 구분자 (&lt;b&gt;::&lt;/b&gt;)를 붙이는 방식으로 메서드 참조를 활용할 수 있다. 예를 들어 Tiger::getWeight는 Tiger 클래스에 정의된 메서드 참조다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;메서드 참조를 만드는 방법&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;메서드 참조는 세 가지 유형으로 구분할 수 있다.&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;1. 정적 메서드 참조&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;예를 들어, Integer의 parseInt 메서드는 Integer::parseInt로 표현할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1606&quot; data-origin-height=&quot;110&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dfr4nf/btrWg0Xpe06/UPTm3MUNlIwVABR73rTSg0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dfr4nf/btrWg0Xpe06/UPTm3MUNlIwVABR73rTSg0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dfr4nf/btrWg0Xpe06/UPTm3MUNlIwVABR73rTSg0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdfr4nf%2FbtrWg0Xpe06%2FUPTm3MUNlIwVABR73rTSg0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1606&quot; height=&quot;110&quot; data-origin-width=&quot;1606&quot; data-origin-height=&quot;110&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;2. 다양한 형식의 인스턴스 메서즈 참조&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;예를 들어, String의 length 메서드는 String::length로 표현할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1604&quot; data-origin-height=&quot;210&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfmSON/btrWcqpGwNn/g4CtDN2B9uvZ2ZqKAZuS01/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfmSON/btrWcqpGwNn/g4CtDN2B9uvZ2ZqKAZuS01/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfmSON/btrWcqpGwNn/g4CtDN2B9uvZ2ZqKAZuS01/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfmSON%2FbtrWcqpGwNn%2Fg4CtDN2B9uvZ2ZqKAZuS01%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1604&quot; height=&quot;210&quot; data-origin-width=&quot;1604&quot; data-origin-height=&quot;210&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;3. 기존 객체의 인스턴스 메서드 참조&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;예를 들어,&amp;nbsp; Tiger 객체를 할당 받은 tiger 인스턴스트에 getWeight 메서드가 있다면, tiger::getWeight 메서드로 사용할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1998&quot; data-origin-height=&quot;118&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZdkFU/btrWX5DwlqC/9j6aBrIzrHDzDjU2uZd0VK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZdkFU/btrWX5DwlqC/9j6aBrIzrHDzDjU2uZd0VK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZdkFU/btrWX5DwlqC/9j6aBrIzrHDzDjU2uZd0VK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZdkFU%2FbtrWX5DwlqC%2F9j6aBrIzrHDzDjU2uZd0VK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1998&quot; height=&quot;118&quot; data-origin-width=&quot;1998&quot; data-origin-height=&quot;118&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;생성자 참조&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;생성자(new) 또한 메서드 참조를 이용해서 만들 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;인수가 없는 생성자, Supplier의 () -&amp;gt; Tiger 와 같은 시그니처를 갖는 생성자가 있다고 가정하면, 아래와 같이 사용 할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1714&quot; data-origin-height=&quot;58&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/baYqu8/btrWRX7WTxS/dqmTSZ8mwmLU2VKJGfRYq0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/baYqu8/btrWRX7WTxS/dqmTSZ8mwmLU2VKJGfRYq0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/baYqu8/btrWRX7WTxS/dqmTSZ8mwmLU2VKJGfRYq0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbaYqu8%2FbtrWRX7WTxS%2FdqmTSZ8mwmLU2VKJGfRYq0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1714&quot; height=&quot;58&quot; data-origin-width=&quot;1714&quot; data-origin-height=&quot;58&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Post&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a style=&quot;font-family: -apple-system, BlinkMacSystemFont, 'Helvetica Neue', 'Apple SD Gothic Neo', Arial, sans-serif; letter-spacing: 0px;&quot; href=&quot;https://zangzangs.tistory.com/171&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;자바 스트림 설명부터 사용하는 이유 파헤쳐보기 #JAVA #스트림&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;References&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;모던 자바 인 액션&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;figure data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignCenter&quot; data-emoticon-type=&quot;niniz&quot; data-emoticon-name=&quot;012&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;잘못된 코드나 내용이 있다면 댓글을 남겨주세요. 즉시 수정하도록 하겠습니다! :)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>JAVA</category>
      <category>java</category>
      <category>Lambda</category>
      <category>람다</category>
      <category>모던자바인액션</category>
      <category>자바</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/170</guid>
      <comments>https://zangzangs.tistory.com/170#entry170comment</comments>
      <pubDate>Tue, 3 Jan 2023 00:20:25 +0900</pubDate>
    </item>
    <item>
      <title>[스프링 부트] 예외처리(Exception)  @ControllerAdvice @RestControllerAdvice @ExceptionHandler @ResponseStatus</title>
      <link>https://zangzangs.tistory.com/168</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;751&quot; data-origin-height=&quot;329&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgsYnw/btrtieJKgEO/ZPLNytFvqYaaXeElKY7iQk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgsYnw/btrtieJKgEO/ZPLNytFvqYaaXeElKY7iQk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgsYnw/btrtieJKgEO/ZPLNytFvqYaaXeElKY7iQk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgsYnw%2FbtrtieJKgEO%2FZPLNytFvqYaaXeElKY7iQk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;751&quot; height=&quot;329&quot; data-origin-width=&quot;751&quot; data-origin-height=&quot;329&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;[스프링 부트] 예외처리(Exception)&amp;nbsp;&amp;nbsp;&lt;/h2&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;@ControllerAdvice @RestControllerAdvice @ExceptionHandler @ResponseStatus&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;안녕하세요? 장장스입니다!&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;오늘은 스프링에서 '예외 처리를 어떻게 할 것인가'에 대한 포스팅을 하려고 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;코드를 작성하며 고민 되는 문제 중 하나가 어떻게 예외 처리를 해야 하는가 입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Exception In Java&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;647&quot; data-origin-height=&quot;593&quot;&gt;&lt;a href=&quot;https://www.manishsanger.com/java-exception-hierarchy/&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BNb5E/btrtajk25fA/Zv1TvZrEdCUHluk0s9bRkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBNb5E%2Fbtrtajk25fA%2FZv1TvZrEdCUHluk0s9bRkK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;647&quot; height=&quot;593&quot; data-origin-width=&quot;647&quot; data-origin-height=&quot;593&quot;/&gt;&lt;/a&gt;&lt;figcaption&gt;Java Exception Hierarchy&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;예외 계층 구조에서 볼 수 있듯이 Java에서 발생하는 오류는 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;Error&lt;/b&gt;&amp;nbsp;&lt;/span&gt;클래스와&amp;nbsp;&lt;span style=&quot;color: #009a87;&quot;&gt;&lt;b&gt;Exception&lt;/b&gt;&amp;nbsp;&lt;/span&gt;클래스로 나뉩니다. 모든 오류 및 예외는 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Throwable&lt;/b&gt;&amp;nbsp;&lt;/span&gt;클래스를 상위 클래스로 가집니다. &lt;b&gt;Throwable&lt;/b&gt;를 상속받은 하위 클래스의 인스턴스들은&lt;span&gt;&amp;nbsp;&lt;/span&gt;JVM 또는 Java throw 문에 의해 throw됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;그렇다면 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;Error&lt;/b&gt;&amp;nbsp;&lt;/span&gt;클래스와 &lt;b&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;Exception&lt;/span&gt; &lt;/b&gt;클래스의 차이는 무엇일까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;오류 (&lt;b&gt;Error)&lt;/b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;오류는 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;처리할 수 없는 심각한 오류를 나타내는 클래스&lt;/b&gt;&lt;/span&gt;입니다. 실행 중에 throw되었지만 catch되지 않은 오류에 대해 Error 또는 해당 하위 클래스에 대해 throw 절을 선언할 필요가 없습니다. 오류는 개발자가 처리 할 수 없는 경우입니다. 예를 들어, 프로그램 실행 도중 메모리 공간 부족으로 오류가 발생하는 경우 &lt;b&gt;개발자는 이를 제어 할 수 없습니다.&lt;/b&gt; 오류 클래스의 종류로는 OutOfMemoryError,&amp;nbsp; AssertionError, StackOverflowError, IOError, NoClassDefFoundError 등이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;&lt;b&gt;예외 (&lt;b&gt;Exception&lt;/b&gt;)&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;예외는 프로그램이 복구할 수 있고 응용 프로그램에서 개발자가 처리해야 하는 문제를 나타냅니다. 예외에는 두 가지 하위 유형이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span&gt;&lt;b&gt;1. Checked Exception&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;787&quot; data-origin-height=&quot;244&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cORN0U/btrs8AniH3Z/CNtUoavsmdIZ1cklUK85P0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cORN0U/btrs8AniH3Z/CNtUoavsmdIZ1cklUK85P0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cORN0U/btrs8AniH3Z/CNtUoavsmdIZ1cklUK85P0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcORN0U%2Fbtrs8AniH3Z%2FCNtUoavsmdIZ1cklUK85P0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;787&quot; height=&quot;244&quot; data-origin-width=&quot;787&quot; data-origin-height=&quot;244&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;코드를 작성하다 보면 위 사진처럼 빨간색 밑줄이 생기는 경우를 경험한 적이 있을 것입니다. 컴파일 타임에 확인되는 이러한 예외를 Checked Exception이라고 합니다. 개발자는 이러한 예외에 대한 처리를 해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span&gt;&lt;/span&gt;IOException, SQLException, FileNotFoundException, ClassNotFoundException, NoSuchMethodException 등이 Checked Exception에 해당합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2.Unchecked Exception&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Checked Exception과 달리 Unchecked Exception은 컴파일 타임에 확인 할 수 없습니다. 이러한 예외는 런타임에 발생합니다. 때문에 RunTimeException이라고 부르기도 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;개발자는 Unchecked Exception을 발견하거나 예상된다면 해당 예외에 대한 처리를 해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;NullPointerException, ArithmeticException, IllegalArgumentException, IndexOutOfBoundException 등이 Unchecked&amp;nbsp;Exception에 해당합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Unchecked Exception 처리&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;그렇다면 이러한 예외를 어떻게 처리할 수 있을까요? 회원가입을 예시로 들어보겠습니다. 다음과 같은 Member Entity가 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1644820587730&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import javax.persistence.*;

@Entity
public class Member {

    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(name = &quot;member_name&quot;, unique = true)
    private String name;

    private int age;

    protected Member() {
    }

    public Member(String name, int age) {
        this.name = name;
        this.age = age;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;'장장스'라는 이름으로 회원가입을 신청했습니다. 성공했습니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;회원 가입을 요청하면 MemberService의 saveMember 메서드로 회원 가입을 시도합니다.&lt;/p&gt;
&lt;pre id=&quot;code_1644821343283&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Service
@Transactional(readOnly = true)
public class MemberService {
    private final MemberRepository memberRepository;

    public MemberService(MemberRepository memberRepository) {
        this.memberRepository = memberRepository;
    }

    @Transactional
    public Long saveMember(MemberDto memberDto){
        duplicatedMemberByName(memberDto.getName());
        return memberRepository.save(memberDto.convertEntity());
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;며칠 뒤 또 다른 사람이 '장장스'라는 이름으로 회원가입을 시도했으나 에러가 발생했습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;863&quot; data-origin-height=&quot;56&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KQ0hs/btrtajrZb5A/1puvq8oqSV41XsVUBRMm50/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KQ0hs/btrtajrZb5A/1puvq8oqSV41XsVUBRMm50/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KQ0hs/btrtajrZb5A/1puvq8oqSV41XsVUBRMm50/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKQ0hs%2FbtrtajrZb5A%2F1puvq8oqSV41XsVUBRMm50%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;863&quot; height=&quot;56&quot; data-origin-width=&quot;863&quot; data-origin-height=&quot;56&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;회원 테이블을 확인해 보니 name 칼럼에 unique 제약 조건이 걸려 있습니다. 때문에 같은 이름으로 회원 가입을 시도하면 SQL관련된 Exception이 발생한 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이처럼 중복된 이름으로 가입을 하는 것은 런타임에 발생할 수 있는 예상되는 Unchecked Exception 입니다. 이처럼 예상되는 문제에 대해서는 개발자가 처리를 해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Exception 클래스 생성하기&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;※ 자세한 코드는 &lt;a href=&quot;https://github.com/ZANGZANGS/exceptionLab&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;Git&lt;/b&gt;&lt;/a&gt;을 참고해주세요 :)&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;먼저 RuntimeException을 상속받은 새로운 &lt;b&gt;DuplicatedMemberNameException&lt;/b&gt; 클래스를 생성합니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1644821216654&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class DuplicatedMemberNameException extends RuntimeException{
    public DuplicatedMemberNameException() {
        super(&quot;중복된 회원입니다&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;MemberService에 새로운 메서드를 추가합니다. findMemberByName 는 name을 기준으로 회원을 찾는 메서드 이고, DuplicatedMemberNameException 는 이름이 중복될 경우 DuplicatedMemberNameException 예외를 터뜨리는 메서드입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1644821382867&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Service
@Transactional(readOnly = true)
public class MemberService {
    
    ...생략

    public Optional&amp;lt;Member&amp;gt; findMemberByName(String name){
        return memberRepository.findByName(name);
    }

    private void duplicatedMemberByName(String name){
        if(findMemberByName(name).isPresent()){
            throw new DuplicatedMemberNameException();
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이제 같은 이름으로 가입을 진행하면 SQL 관련 Exception이 아니라 DuplicatedMemberNameException 예외가 터지게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;간단한 테스트 코드를 작성해서 확인해 볼 수 있습니다!&lt;/p&gt;
&lt;pre id=&quot;code_1644827565516&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@SpringBootTest
class MemberServiceTest {

    @Autowired
    private MemberService memberService;


    @Test
    @DisplayName(&quot;회원_중복_테스트&quot;)
    @Transactional
    void duplicatedUserTest(){
        // given
        String name = &quot;홍길동&quot;;
        int age = 15;
        MemberDto memberDto = new MemberDto(name, age);

        // when
        memberService.saveMember(memberDto);

        // then - 홍킬동 중복 가입 시도
        DuplicatedMemberNameException e = assertThrows(DuplicatedMemberNameException.class,
                () -&amp;gt; memberService.saveMember(memberDto));

        System.out.println(&quot;회원 중복 테스트&quot; + e.getMessage());
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;e.getMessage() 를 통해 DuplicatedMemberNameException에서 설정한 메시지를 확인 할 수 있게 되었네요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이렇게 예측되는 예외에 대해 새로운 코드를 작성했지만 하지만 결국 Exception이 발생하는 것은 똑같습니다. DuplicatedMemberNameException이 발생하면 문제가 되는 것은 동일하니까요. 사용자는 결국 에러 페이지를 만날 수 밖에 없습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;472&quot; data-origin-height=&quot;238&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qmKIg/btrtiepJE10/5DQ0FV1RkfIryLmma8sHCK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qmKIg/btrtiepJE10/5DQ0FV1RkfIryLmma8sHCK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qmKIg/btrtiepJE10/5DQ0FV1RkfIryLmma8sHCK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqmKIg%2FbtrtiepJE10%2F5DQ0FV1RkfIryLmma8sHCK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;472&quot; height=&quot;238&quot; data-origin-width=&quot;472&quot; data-origin-height=&quot;238&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;@ControllerAdvice 사용하기&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;@ExceptionHandler 어노테이션을 사용해서 컨트롤러에서 발생하는 예외를 처리 할 수 있다. 컨트롤러에서 발생하는 예외를 처리해주는 기능을 한다. @Controller, @Rest&lt;span style=&quot;color: #000000;&quot;&gt;Controller 모두 해당된다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1644829938849&quot; class=&quot;less&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@RestController
public class MemberController {

	...생략

    @PostMapping
    @ExceptionHandler(DuplicatedMemberNameException.class)
    public Object saveMember(@RequestBody MemberDto memberDto){
        return memberService.saveMember(memberDto);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;하지만 모든 컨트롤러마다 &lt;span style=&quot;color: #000000;&quot;&gt;@ExceptionHandler 을 선언한다면 관리가 복잡해지게 된다. &lt;/span&gt;&lt;/span&gt;@ControllerAdvice 는 &lt;span style=&quot;color: #000000;&quot;&gt;@Controller, @RestController가 적용된 Bean내에서 발생하는 예외&lt;/span&gt;를 처리할 수 있게 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;다음은 @RestController 를 처리하기 위해 작성한 ExceptionLabRestControllerAdvice 클래스이다.&lt;/p&gt;
&lt;pre id=&quot;code_1644830252522&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@RestControllerAdvice
public class ExceptionLabRestControllerAdvice {

    Logger logger = LoggerFactory.getLogger(ExceptionLabRestControllerAdvice.class);

	..생략

    @ExceptionHandler(DuplicatedMemberNameException.class)
    @ResponseStatus(HttpStatus.CONFLICT)
    public String duplicatedMemberNameExceptionHandler(DuplicatedMemberNameException e){
        logger.error(&quot;DuplicatedMemberNameException: {}&quot;, e.getMessage());
        return e.getMessage();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;@RestControllerAdvice 을 통해 예외 처리의 타겟을 어노테이션으로 할지, 패키지나 클래스로 설정할 수 있다.&lt;/p&gt;
&lt;pre class=&quot;coffeescript&quot;&gt;&lt;code&gt;@RestControllerAdvice(annotations = RestController.class)&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@RestControllerAdvice( basePackages = {&quot;com.example.package1&quot;,&quot;com.example.package2&quot;})&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;coffeescript&quot;&gt;&lt;code&gt;@RestControllerAdvice( basePackageClasses = MemberController.class)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;br /&gt;@&lt;span style=&quot;color: #000000;&quot;&gt;ExceptionHandler&lt;span&gt; 은 어떤 Exception을 처리할지 설정 할 수 있다. 만약 value값이 없다면(Exception 클래스를 지정하지 않는경우) 메서드의 입력 파라미터의 Exception을 처리한다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;추가로, 다음과 같이 여러개의 예외를 처리할 수 있습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1644830964784&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;  @ExceptionHandler({Exception1.class, Exception2.class})&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;@ResponseStatus 은 응답 Http 코드를 선언할 수 있다. 스프링에서 HttpStatus enum 클래스를 정의하고 있다. http 코드별 내용은 &lt;b&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/HTTP/Status&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;여기&lt;/a&gt;&lt;/b&gt;에서 확인 할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;PostMan 을 통해 확인하기&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;839&quot; data-origin-height=&quot;425&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b3vHgy/btrtifWzn6W/PZ4z9szrAPD82kDYDfZ4G0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b3vHgy/btrtifWzn6W/PZ4z9szrAPD82kDYDfZ4G0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b3vHgy/btrtifWzn6W/PZ4z9szrAPD82kDYDfZ4G0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb3vHgy%2FbtrtifWzn6W%2FPZ4z9szrAPD82kDYDfZ4G0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;839&quot; height=&quot;425&quot; data-origin-width=&quot;839&quot; data-origin-height=&quot;425&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;첫 회원 가입 요청은 당연히 성공할 겁니다. 회원번호(PK)를 반환한 것을 확인 할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;834&quot; data-origin-height=&quot;494&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bZuoPr/btrtiepOXJX/vuTcaIkDNm33bqNFyRYiDk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bZuoPr/btrtiepOXJX/vuTcaIkDNm33bqNFyRYiDk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bZuoPr/btrtiepOXJX/vuTcaIkDNm33bqNFyRYiDk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbZuoPr%2FbtrtiepOXJX%2FvuTcaIkDNm33bqNFyRYiDk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;834&quot; height=&quot;494&quot; data-origin-width=&quot;834&quot; data-origin-height=&quot;494&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;두 번째 요청은 회원 가입이 되지 않고, DuplicatedMemberNameException 클래스에 선언한 텍스트가 반환됨을 확인 할 수 있다. 서버에서 log도 정상적으로 출력 되는 것을 확인 할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1190&quot; data-origin-height=&quot;45&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bugNEM/btrtejkUL8M/kTDR8qAveT6N45g0gs6ed1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bugNEM/btrtejkUL8M/kTDR8qAveT6N45g0gs6ed1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bugNEM/btrtejkUL8M/kTDR8qAveT6N45g0gs6ed1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbugNEM%2FbtrtejkUL8M%2FkTDR8qAveT6N45g0gs6ed1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1190&quot; height=&quot;45&quot; data-origin-width=&quot;1190&quot; data-origin-height=&quot;45&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;※ 자세한 코드는&amp;nbsp;&lt;a href=&quot;https://github.com/ZANGZANGS/exceptionLab&quot;&gt;&lt;b&gt;Git&lt;/b&gt;&lt;/a&gt;을 참고해주세요 :)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Post&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;References&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.manishsanger.com/java-exception-hierarchy/&quot;&gt;https://www.manishsanger.com/java-exception-hierarchy/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.oracle.com/javase/8/docs/api/java/lang/Error&quot;&gt;https://docs.oracle.com/javase/8/docs/api/java/lang/Error&lt;/a&gt;&lt;a href=&quot;https://docs.oracle.com/javase/8/docs/api/java/lang/Error.html&quot;&gt;&amp;nbsp;.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.oracle.com/javase/8/docs/api/java/lang/Throwable.html&quot;&gt;https://docs.oracle.com/javase/8/docs/api/java/lang/Throwable.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://reakwon.tistory.com/155&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://reakwon.tistory.com/155&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://javachoi.tistory.com/253&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://javachoi.tistory.com/253&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignCenter&quot; data-emoticon-type=&quot;niniz&quot; data-emoticon-name=&quot;012&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘못된 코드나 내용이 있다면 댓글을 남겨주세요. 즉시 수정하도록 하겠습니다! :)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Spring Boot</category>
      <category>controlleradvice</category>
      <category>exception</category>
      <category>exceptionhandler</category>
      <category>java</category>
      <category>ResponseStatus</category>
      <category>springboot</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/168</guid>
      <comments>https://zangzangs.tistory.com/168#entry168comment</comments>
      <pubDate>Mon, 14 Feb 2022 14:16:49 +0900</pubDate>
    </item>
    <item>
      <title>[DB] 트랜잭션 격리수준 (Isolation Level)</title>
      <link>https://zangzangs.tistory.com/167</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;790&quot; data-origin-height=&quot;323&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/br4Mva/btrr7rqjXOQ/MfiMhNRJJU1Etcnl8PCeYk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/br4Mva/btrr7rqjXOQ/MfiMhNRJJU1Etcnl8PCeYk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/br4Mva/btrr7rqjXOQ/MfiMhNRJJU1Etcnl8PCeYk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbr4Mva%2Fbtrr7rqjXOQ%2FMfiMhNRJJU1Etcnl8PCeYk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;433&quot; height=&quot;177&quot; data-origin-width=&quot;790&quot; data-origin-height=&quot;323&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;트랜잭션 격리수준 (Isolation Level)&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;동시성(&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;Concurrency&lt;/span&gt;) 문제&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;실제 서비스에서는 많은 사용자가 동시 다발적으로 서버에 요청을 하게 되고 서버는 데이터베이스에 다시 트랜잭션을 요청하게 됩니다. 모든 요청을 순서대로 처리하게 된다면 &lt;b&gt;동시성(&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;Concurrency&lt;/span&gt;)&lt;/b&gt; 문제가 생길 것입니다. 반대로 &lt;b&gt;동시성&lt;/b&gt;을 보장하기 위해 모든 요청을 동시에 처리하려고 한다면 데이터의 값이 맞지 않는 &lt;b&gt;일관성(&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;Consistency&lt;/span&gt;) &lt;/b&gt;문제가 생기게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;343&quot; data-origin-height=&quot;228&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rrGfM/btrr2XwV99g/H9tjsQq98xAfPjvbRG6nZ1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rrGfM/btrr2XwV99g/H9tjsQq98xAfPjvbRG6nZ1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rrGfM/btrr2XwV99g/H9tjsQq98xAfPjvbRG6nZ1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrrGfM%2Fbtrr2XwV99g%2FH9tjsQq98xAfPjvbRG6nZ1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;343&quot; height=&quot;228&quot; data-origin-width=&quot;343&quot; data-origin-height=&quot;228&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Isolation 이 낮다면 발생하는 문제들&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;아래와 같은 회원 테이블이 있습니다. 이 테이블에 대한 트랜잭션이 동시에 일어나면 어떤 문제가 있을까&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 100px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style13&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 99.8836%; text-align: center; height: 20px;&quot; colspan=&quot;3&quot;&gt;&lt;b&gt;회원 테이블&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 24.9418%; text-align: center; height: 20px;&quot;&gt;&lt;b&gt;이름&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 24.9418%; text-align: center; height: 20px;&quot;&gt;&lt;b&gt;VARCHAR&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center; height: 20px;&quot;&gt;장장스&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 24.9418%; text-align: center; height: 20px;&quot;&gt;&lt;b&gt;잔액&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 24.9418%; text-align: center; height: 20px;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;BIGINT&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center; height: 20px;&quot;&gt;10000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 24.9418%; text-align: center; height: 20px;&quot;&gt;&lt;b&gt;등급&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 24.9418%; text-align: center; height: 20px;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;VARCHAR&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center; height: 20px;&quot;&gt;BRONZE&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 24.9418%; text-align: center; height: 20px;&quot;&gt;&lt;b&gt;지역&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 24.9418%; text-align: center; height: 20px;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;VARCHAR&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%; text-align: center; height: 20px;&quot;&gt;서울&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1) Dirty Read가 발생하는 경우&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;아직 커밋되지 않은 데이터를 수정하는 도중 다른 트랜잭션에서 READ를 허용할 때 발생한다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 100px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px; text-align: center;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;트랜잭션 (T1)&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px; text-align: center;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;트랜잭션 (T2)&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;SELECT 잔액 FROM 회원 테이블 &lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;WHERE 이름=장장스;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;UPDATE 회원 테이블 SET 잔액 = 9000&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;WHERE 이름=장장스;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;SELECT 잔액 FROM 회원 테이블&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;WHERE 이름=장장스;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;ROLLBACK;&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #c1bef9;&quot;&gt;&lt;b&gt;트랜잭션(T1)&lt;/b&gt;&lt;/span&gt;이 회원 테이블에 접근하여 잔액을 10,000에서 9,000으로 변경 했습니다. COMMIT을 하지 않았습니다. 그런데 다른 &lt;b&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;트랜잭션(T2)&lt;/span&gt;&lt;/b&gt;이 회원 테이블에 접근하여 잔액을 READ해 보니 9,000원 입니다. &lt;span style=&quot;background-color: #c1bef9;&quot;&gt;&lt;b&gt;트랜잭션(T1)&lt;/b&gt;&lt;/span&gt;은 수정사항을 COMMIT 하지 않고 &lt;b&gt;ROLLBACK&lt;/b&gt; 했습니다. 따라서 장장스의 잔액은 10,000원입니다. 그러나 &lt;b&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;트랜잭션(T2)&lt;/span&gt;&lt;/b&gt; 가 조회한 잔액은 9,000원으로 데이터가 다릅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2) Non-Repeatable Read가 발생하는 경우&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;트랜잭션 내에서 같은 내용의 쿼리가 반복해서 수행할 때,&amp;nbsp; 다른 트랜잭션이 값을 수정 또는 삭제함으로써 두 쿼리가 상이하게 나타나는 &lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;비 일관성(Consistency)이 발생한다&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 160px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;트랜잭션 (T1)&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;트랜잭션 (T2)&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;&lt;b&gt;SELECT 잔액 FROM 회원 테이블;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 40px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 40px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 40px;&quot;&gt;&lt;b&gt;UPDATE 회원 테이블 SET 잔액 = 5000&lt;/b&gt;&lt;br /&gt;&lt;b&gt;WHERE 이름=장장스;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;&lt;b&gt;COMMIT;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 40px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 40px;&quot;&gt;&lt;b&gt;IF 잔액 &amp;gt;= 10000&lt;/b&gt;&lt;br /&gt;&lt;b&gt;UPDATE 회원 테이블 SET 등급 = SILVER&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 40px;&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;&lt;b&gt;COMMIT;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #c1bef9;&quot;&gt;&lt;b&gt;트랜잭션(T1)&lt;/b&gt;&lt;/span&gt;이 회원 테이블을 READ하고 있었습니다. 이때 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;트랜잭션(T2)&lt;/b&gt;&lt;/span&gt;가 데이터에 접근하여 값을 변경(삭제) 후 COMMIT을 했습니다. &lt;span style=&quot;background-color: #c1bef9;&quot;&gt;&lt;b&gt;트랜잭션(T1)&lt;/b&gt;&lt;/span&gt;이 다시 해당 데이터를&amp;nbsp; READ 하려 하는데 데이터가 변경(삭제) 되어 찾을 수가 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3) Phantom Read&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;하나의 트랜잭션에서 일정범위의 레코드를 두 번 이상 읽을 때, 첫 번재 쿼리에서 없던 &lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;&lt;u&gt;유령 레코드&lt;/u&gt;&lt;/b&gt;&lt;/span&gt;가 두번째 쿼리에서 나타나는 현상을 발생한다.&lt;/span&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 160px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;트랜잭션 (T1)&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;트랜잭션 (T2)&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;&lt;b&gt;INSERT INTO 지역별 회원 테이블&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; SELECT 지역, COUNT(*)&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; FROM 회원 테이블 GROUP BY 지역;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;&lt;b&gt;INSERT INTO 회원 테이블(이름, 잔액, 등급, 지역)&lt;/b&gt;&lt;br /&gt;&lt;b&gt;VALUES('강건마', 500, 'BRONZE', '부산');&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;&lt;b&gt;COMMIT;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 60px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 60px;&quot;&gt;&lt;b&gt;INSERT INTO 등급별 회원 테이블&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; SELECT 등급, COUNT(*)&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; FROM 회원 테이블 GROUP BY 등급;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 60px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;&lt;b&gt;COMMIT;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #c1bef9;&quot;&gt;&lt;b&gt;트랜잭션(T1)&lt;/b&gt;&lt;/span&gt;이 지역별, 등급별 회원을 집계하는 도중 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;트랜잭션(T2)&lt;/b&gt;&lt;/span&gt;가 새로운 회원을 등록하게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;그 결과 지역별 회원 테이블과 등급별 회원 테이블의 총 인원수가 불일치하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;트랜잭션 격리수준 (Isolation Level)&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이처럼 동일성(&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;Concurrency&lt;/span&gt;)을 높이다 보면 일관성(&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;Consistency&lt;/span&gt;) 문제가 발생하는 것을 알 수 있습니다. 이러한 문제 해결을 위한 방법으로 트랜잭션 격리수준을 설정할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;[Level 0] &lt;span style=&quot;background-color: #99cefa;&quot;&gt;READ UNCOMMITTED&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;트랜잭션에서 처리 중인, 아직 커밋되지 않은 데이터를 다른 트랜잭션이 읽는 것을 허용&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Dirty Read, Non-Repeatable Read, Phantom Read&lt;/b&gt; 가 발생합니다.&lt;/li&gt;
&lt;li&gt;참고로 Oracle의 경우 Read Uncommitted 레벨은 지원하지 않습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;[Level 1] &lt;span style=&quot;background-color: #99cefa;&quot;&gt;READ COMMITTED&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;트랜잭션이 커밋되어 확정된 데이터만 읽는 것을 허용합니다.&lt;/li&gt;
&lt;li&gt;DB2, SQL Server, Sybase같이 대부분의 DBMS가 기본모드로 채택하고 있습니다. READ 경우 '공유 Lock'을 이용해서 구현합니다. 하나의 레코드를 읽을 때 Lock을 설정하고 해당 레코드를 빠져 나가는 순간 Lock 해제합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Dirty Read&lt;/b&gt; 를 방지할 수 있으나 &lt;b&gt;Non-Repeatable Read, Phantom Read&lt;/b&gt;는 발생합니다.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.oracle.com/cd/E15586_01/server.1111/e25789/consist.htm#CNCPT221&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;Oracle database 11g&lt;/b&gt;&lt;/a&gt;의 기본 Isolation level 입니다. Oracle database는 원본 레코드를 사용하지 않고 읽기 전용 데이터 셋을 (&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;read-consistent set of data&lt;/span&gt;)생성하여 사용합니다. 사용자가 데이터를 수정할 때면 COMMIT 이전까지의 변경사항을 &quot;Undo Segments&quot; 기록하는 방법으로 일관성을 보장합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;[Level 2] &lt;span style=&quot;background-color: #99cefa;&quot;&gt;REPEATABLE READ&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;선행 트랜잭션이 읽은 데이터는 트랜잭션이 종료될 때가지 다른 트랜잭션이 갱신하거나 삭제하지 못하도록 하여 같은 데이터를 두 번 쿼리했을 때 일관성 있는 결과를 리턴하도록 합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Dirty Read, &lt;b&gt;Non-Repeatable Read&lt;/b&gt;&lt;/b&gt;를 방지할 수 있으나&lt;span&gt; &lt;/span&gt;&lt;b&gt;Phantom Read&lt;/b&gt;는&amp;nbsp;발생합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;InnoDB &lt;/b&gt;스토리 엔진을 사용하는&lt;b&gt;&lt;a href=&quot;https://dev.mysql.com/doc/refman/8.0/en/innodb-transaction-isolation-levels.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;MySQL,&lt;/span&gt;&lt;/a&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt; &lt;/span&gt;&lt;a href=&quot;https://mariadb.com/kb/en/mariadb-transactions-and-isolation-levels-for-sql-server-users/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;MariaDB&lt;/span&gt;&lt;/a&gt;&lt;/b&gt;의 기본 Isolation level 입니다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;[Level 3] &lt;span style=&quot;background-color: #99cefa;&quot;&gt;SERIALIZABLE&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;선행 트랜잭션이 읽은 데이터를 다른 트랜잭션이 수정/삭제하지 못할 뿐만 아니라 중간에 새로운 레코드를 산입하지 못하도록 막아 완벽하게 읽기 일관성 모드를 제공합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Post&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-ke-size=&quot;size23&quot;&gt;&lt;a href=&quot;https://zangzangs.tistory.com/135&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2021.11.23 - [database/DB Concept] - [DB] 트랜잭션&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;References&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://armful-log.tistory.com/57&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://armful-log.tistory.com/57&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;http://wiki.gurubee.net/pages/viewpage.action?pageId=21200923&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;http://wiki.gurubee.net/pages/viewpage.action?pageId=21200923&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://dev.mysql.com/doc/refman/8.0/en/innodb-transaction-isolation-levels.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://dev.mysql.com/doc/refman/8.0/en/innodb-transaction-isolation-levels.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://mariadb.com/kb/en/mariadb-transactions-and-isolation-levels-for-sql-server-users/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://mariadb.com/kb/en/mariadb-transactions-and-isolation-levels-for-sql-server-users/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.oracle.com/cd/E15586_01/server.1111/e25789/consist.htm#CNCPT221&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://docs.oracle.com/cd/E15586_01/server.1111/e25789/consist.htm#CNCPT221&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignCenter&quot; data-emoticon-type=&quot;niniz&quot; data-emoticon-name=&quot;012&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘못된 코드나 내용이 있다면 댓글을 남겨주세요. 즉시 수정하도록 하겠습니다! :)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>database/DB Concept</category>
      <category>db</category>
      <category>Isolation Level</category>
      <category>데이터베이스</category>
      <category>트랜잭션</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/167</guid>
      <comments>https://zangzangs.tistory.com/167#entry167comment</comments>
      <pubDate>Mon, 31 Jan 2022 19:00:04 +0900</pubDate>
    </item>
    <item>
      <title>Logback이란? feat.SLF4J</title>
      <link>https://zangzangs.tistory.com/166</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;751&quot; data-origin-height=&quot;329&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cuMbv6/btrr1jteaIq/nvYkajPJNM6dKwkU9hLXr1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cuMbv6/btrr1jteaIq/nvYkajPJNM6dKwkU9hLXr1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cuMbv6/btrr1jteaIq/nvYkajPJNM6dKwkU9hLXr1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcuMbv6%2Fbtrr1jteaIq%2FnvYkajPJNM6dKwkU9hLXr1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;751&quot; height=&quot;329&quot; data-origin-width=&quot;751&quot; data-origin-height=&quot;329&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;Logback이란? feat.SLF4J&lt;/span&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Logback?&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;logback은 &lt;/span&gt;SLF4J의 구현체입니다. &lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;logback-core, logback-classic 및 logback-access의 세 가지 모듈로 구분됩니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Logger, Appenders and Layouts&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Logger클래스는 logback-classic 모듈의 일부입니다&lt;span&gt;&amp;nbsp;&lt;/span&gt;.&lt;span&gt;&amp;nbsp;&lt;/span&gt;반면에&lt;span&gt;&amp;nbsp;&lt;/span&gt;Appender및&lt;span&gt;&amp;nbsp;&lt;/span&gt;Layout인터페이스는 logback-core의 일부입니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;범용 모듈로서 logback-core에는 로거 개념이 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;▶Logger&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;Logger는 가능한 모든 로그 기록을 개발자가 선택한 일부 기준에 따라 분류된다고 가정합니다.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 160px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style13&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 40px;&quot;&gt;
&lt;td style=&quot;width: 14.2857%; height: 40px; text-align: center;&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;level&amp;nbsp;of&amp;nbsp;&lt;br /&gt;request&amp;nbsp;p&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 85.7142%; height: 40px; text-align: center;&quot; colspan=&quot;6&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;effective&amp;nbsp;level&amp;nbsp;q&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 14.2857%; height: 20px; text-align: center;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;TRACE&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;DEBUG&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;INFO&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;WARN&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;ERROR&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;OFF&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 14.2857%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;TRACE&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #008000;&quot;&gt;YES&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;NO&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;NO&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;NO&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;NO&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;NO&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 14.2857%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;DEBUG&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #008000;&quot;&gt;YES&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #008000;&quot;&gt;YES&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;NO&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;NO&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;NO&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;NO&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 14.2857%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;INFO&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #008000;&quot;&gt;YES&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #008000;&quot;&gt;YES&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #008000;&quot;&gt;YES&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;NO&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;NO&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;NO&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 14.2857%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;WARN&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #008000;&quot;&gt;YES&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #008000;&quot;&gt;YES&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #008000;&quot;&gt;YES&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #008000;&quot;&gt;YES&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;NO&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;NO&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 14.2857%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;ERROR&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #008000;&quot;&gt;YES&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #008000;&quot;&gt;YES&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #008000;&quot;&gt;YES&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #008000;&quot;&gt;YES&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #008000;&quot;&gt;YES&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 14.2857%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ff0000;&quot;&gt;NO&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;b&gt;▶&lt;/b&gt;Appender&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Logback은 로깅 이벤트를 작성하는 작업을 Appender 컴포넌트에 에 위임합니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;Appender는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://logback.qos.ch/xref/ch/qos/logback/core/Appender.html&quot;&gt;ch.qos.logback.core.Appender&lt;/a&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;인터페이스를 구현했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;ConsoleAppender&lt;/span&gt;, &lt;span style=&quot;background-color: #f6e199;&quot;&gt;FileAppender&lt;/span&gt;, &lt;span style=&quot;background-color: #f6e199;&quot;&gt;RollingFileAppender&lt;/span&gt; &lt;/b&gt;&amp;nbsp;3가지 대표적인 Appender를 제공합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;(참고로 SMTPAppender 와 같이 메일을 발송하는 Appender도 있습니다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;ConsoleAppender&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이름처럼 콘솔에 추가하거나 더 정확하게는&lt;span&gt;&amp;nbsp;&lt;/span&gt;System.out&lt;span&gt;&amp;nbsp;&lt;/span&gt;또는&lt;span&gt;&amp;nbsp;&lt;/span&gt;System.err&lt;span&gt; 를 이용하여 콘솔에 출력합니다.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 320px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style13&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 15%; text-align: center;&quot;&gt;&lt;span style=&quot;background-color: #6ed3d8; color: #ffffff;&quot;&gt;Property Name&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 10%; text-align: center;&quot;&gt;&lt;span style=&quot;background-color: #6ed3d8; color: #ffffff;&quot;&gt;Type&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 75%; text-align: center;&quot;&gt;&lt;span style=&quot;background-color: #6ed3d8; color: #ffffff;&quot;&gt;Description&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 15%; text-align: center;&quot;&gt;&lt;b&gt;encoder&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 10%; text-align: center;&quot;&gt;Encoder&lt;/td&gt;
&lt;td style=&quot;width: 75%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이벤트가 기본 에 기록되는 방식을 결정합니다. 보통 패턴을 사용합니다.&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 15%; text-align: center;&quot;&gt;&lt;b&gt;target&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 10%; text-align: center;&quot;&gt;String&lt;/td&gt;
&lt;td style=&quot;width: 75%;&quot;&gt;문자열을 System.out,&amp;nbsp;System.err로 출력합니다. 설정하지 않으면 default로&amp;nbsp;System.out으로 출력합니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 15%; text-align: center;&quot;&gt;&lt;b&gt;withJansi&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 10%; text-align: center;&quot;&gt;boolean&lt;/td&gt;
&lt;td style=&quot;width: 75%;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;default로 withJansi&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;span style=&quot;color: #000000;&quot;&gt;property를false로 설정합니다. &lt;span style=&quot;color: #000000;&quot;&gt;withJansi&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 가 true 일 경우 &lt;span style=&quot;color: #000000;&quot;&gt;NSI color code들을 윈도우 기계(?) 에게 제공합니다&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre id=&quot;code_1643551608615&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;configuration&amp;gt;
  &amp;lt;appender name=&quot;STDOUT&quot; class=&quot;ch.qos.logback.core.ConsoleAppender&quot;&amp;gt;
    &amp;lt;!-- encoders are assigned the type
         ch.qos.logback.classic.encoder.PatternLayoutEncoder by default --&amp;gt;
    &amp;lt;encoder&amp;gt;
      &amp;lt;pattern&amp;gt;%-4relative [%thread] %-5level %logger{35} - %msg %n&amp;lt;/pattern&amp;gt;
    &amp;lt;/encoder&amp;gt;
  &amp;lt;/appender&amp;gt;

  &amp;lt;root level=&quot;DEBUG&quot;&amp;gt;
    &amp;lt;appender-ref ref=&quot;STDOUT&quot; /&amp;gt;
  &amp;lt;/root&amp;gt;
&amp;lt;/configuration&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;FileAppender&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;로그 이벤트를 파일에 저장합니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;대상 파일은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;파일&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;옵션으로 지정됩니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;파일이 이미 존재하는 경우 추가&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;속성&lt;span&gt;&amp;nbsp;&lt;/span&gt;값에 따라 파일이 추가되거나 잘립니다 .&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 120px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style13&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 15%; text-align: center; height: 20px;&quot;&gt;&lt;b&gt;Property Name&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 10%; text-align: center; height: 20px;&quot;&gt;&lt;b&gt;Type&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 75%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;Description&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 40px;&quot;&gt;
&lt;td style=&quot;width: 15%; text-align: center; height: 40px;&quot;&gt;&lt;b&gt;append&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 10%; text-align: center; height: 40px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;boolean&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 75%; height: 40px;&quot;&gt;기존 파일에 로그를 이어서 기록하는 프로퍼티로 default는 true로 설정 되어있습니다. false이면 기존 파일이 잘립니다.&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 15%; text-align: center; height: 20px;&quot;&gt;&lt;b&gt;encoder&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 10%; text-align: center; height: 20px;&quot;&gt;Encoder&lt;/td&gt;
&lt;td style=&quot;width: 75%; height: 20px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이벤트가 기본 에 기록되는 방식을 결정합니다. 보통 패턴을 사용합니다.&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 15%; text-align: center; height: 20px;&quot;&gt;&lt;b&gt;file&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 10%; text-align: center; height: 20px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;String&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 75%; height: 20px;&quot;&gt;파일의 이름입니다. 파일이 없으면 파일을 생성합니다. 이때 파일의 경로 또한 설정해야 합니다. default 값은 없습니다.&lt;br /&gt;ex) ./log/error/error-${BY_DATE}.log&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 15%; text-align: center; height: 20px;&quot;&gt;&lt;b&gt;prudent&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 10%; text-align: center; height: 20px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;boolean&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 75%; height: 20px;&quot;&gt;default 값은 false 입니다. &lt;span style=&quot;background-color: #f9f9f9; color: #000000;&quot;&gt;prudent&lt;span&gt; 모드에서는 다른 서버에서 실행 중인 FileAppender가 있는 경우에도 지정된 파일에 안전하게 로그 이벤트를 기록합니다.&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;pre id=&quot;code_1643552566149&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;configuration&amp;gt;
  &amp;lt;appender name=&quot;FILE&quot; class=&quot;ch.qos.logback.core.FileAppender&quot;&amp;gt;
    &amp;lt;file&amp;gt;testFile.log&amp;lt;/file&amp;gt;
    &amp;lt;append&amp;gt;true&amp;lt;/append&amp;gt;
    &amp;lt;!-- set immediateFlush to false for much higher logging throughput --&amp;gt;
    &amp;lt;immediateFlush&amp;gt;true&amp;lt;/immediateFlush&amp;gt;
    &amp;lt;!-- encoders are assigned the type
         ch.qos.logback.classic.encoder.PatternLayoutEncoder by default --&amp;gt;
    &amp;lt;encoder&amp;gt;
      &amp;lt;pattern&amp;gt;%-4relative [%thread] %-5level %logger{35} - %msg%n&amp;lt;/pattern&amp;gt;
    &amp;lt;/encoder&amp;gt;
  &amp;lt;/appender&amp;gt;
        
  &amp;lt;root level=&quot;DEBUG&quot;&amp;gt;
    &amp;lt;appender-ref ref=&quot;FILE&quot; /&amp;gt;
  &amp;lt;/root&amp;gt;
&amp;lt;/configuration&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;RollingFileAppender&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;FileAppender에서 로그 파일을 '&lt;b&gt;롤오버&lt;/b&gt;'하는 기능으로&lt;span&gt;&amp;nbsp;&lt;/span&gt;확장 됩니다. &lt;b&gt;롤오버&lt;/b&gt;를 쉽게 설명하면 특정 조건을 달성하면 파일을 이동시키는 것이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;예를 들어, 용량이 2GB에 도달하거나, 로그 기록이 일주일이 되는 등&amp;nbsp;특정 조건이 충족되면 기록 대상을 다른 파일로 변경할 수 있습니다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 179px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style13&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;height: 20px; width: 15%; text-align: center;&quot;&gt;&lt;b&gt;Property&lt;/b&gt;&lt;br /&gt;&lt;b&gt;Name&amp;nbsp;&lt;br /&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 20px; width: 10%; text-align: center;&quot;&gt;&lt;b&gt;Type&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 20px; width: 75%; text-align: center;&quot;&gt;&lt;b&gt;Description&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;height: 20px; width: 15%; text-align: center;&quot;&gt;&lt;b&gt;&lt;b&gt;append&lt;/b&gt;&lt;br /&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 20px; width: 10%; text-align: center;&quot;&gt;boolean&lt;/td&gt;
&lt;td style=&quot;height: 20px; width: 75%; text-align: left;&quot;&gt;기존 파일에 로그를 이어서 기록하는 프로퍼티로 default는 true로 설정 되어있습니다. false이면 기존 파일이 잘립니다.&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;height: 20px; width: 15%; text-align: center;&quot;&gt;&lt;b&gt;encoder&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 20px; width: 10%; text-align: center;&quot;&gt;Encoder&lt;/td&gt;
&lt;td style=&quot;height: 20px; width: 75%; text-align: left;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이벤트가 기본 에 기록되는 방식을 결정합니다. 보통 패턴을 사용합니다.&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;height: 20px; width: 15%; text-align: center;&quot;&gt;&lt;b&gt;file&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 20px; width: 10%; text-align: center;&quot;&gt;String&lt;/td&gt;
&lt;td style=&quot;height: 20px; width: 75%; text-align: left;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이벤트가 기본 에 기록되는 방식을 결정합니다. 보통 패턴을 사용합니다.&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 40px;&quot;&gt;
&lt;td style=&quot;height: 40px; width: 15%; text-align: center;&quot;&gt;&lt;b&gt;rolling&lt;br /&gt;Policy&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 40px; width: 10%; text-align: center;&quot;&gt;Rolling&lt;br /&gt;Policy&lt;/td&gt;
&lt;td style=&quot;height: 40px; width: 75%; text-align: left;&quot;&gt;롤오버가 발생할 때의 동작을 지시하는 구성 요소입니다. 3가지 정책을 제공합니다.&lt;br /&gt;- TimeBasedRollingPolicy&lt;br /&gt;- Size and time based rolling policy&lt;br /&gt;- FixedWindowRollingPolicy&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 39px;&quot;&gt;
&lt;td style=&quot;height: 39px; width: 15%; text-align: center;&quot;&gt;&lt;b&gt;triggering&lt;br /&gt;Policy&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 39px; width: 10%; text-align: center;&quot;&gt;TriggeringPolicy&lt;/td&gt;
&lt;td style=&quot;height: 39px; width: 75%; text-align: left;&quot;&gt;롤오버를 활성화할 시기를 알려주는 요소입니다. SizeBasedTriggeringPolicy 정책 한 가지로 현재 활성 파일의 크기를 확인하여 롤오버를 트리거 합니다. maxFileSize 옵션만 가지고 있습니다.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 15%; text-align: center; height: 20px;&quot;&gt;&lt;b&gt;&lt;b&gt;prudent&lt;/b&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 10%; text-align: center; height: 20px;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;boolean&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 75%; text-align: left; height: 20px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;rolling Policy&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;TimeBasedRollingPolicy - 가장 인기 있는 정책입니다. 일별 또는 월별과 같이 시간을 기준으로 롤오버 합니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;
&lt;pre id=&quot;code_1643554758130&quot; class=&quot;dust&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;rollingPolicy class=&quot;ch.qos.logback.core.rolling.TimeBasedRollingPolicy&quot;&amp;gt;
    &amp;lt;!-- daily rollover --&amp;gt;
    &amp;lt;fileNamePattern&amp;gt;logFile.%d{yyyy-MM-dd}.log&amp;lt;/fileNamePattern&amp;gt;
    &amp;lt;!-- keep 30 days' worth of history capped at 3GB total size --&amp;gt;
    &amp;lt;maxHistory&amp;gt;30&amp;lt;/maxHistory&amp;gt;
    &amp;lt;totalSizeCap&amp;gt;3GB&amp;lt;/totalSizeCap&amp;gt;
&amp;lt;/rollingPolicy&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Size and time based rolling policy - 파일 크기와 날짜 기반으로 동작합니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;
&lt;pre id=&quot;code_1643554663513&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;rollingPolicy class=&quot;ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy&quot;&amp;gt;
    &amp;lt;!-- rollover daily --&amp;gt;
    &amp;lt;fileNamePattern&amp;gt;mylog-%d{yyyy-MM-dd}.%i.txt&amp;lt;/fileNamePattern&amp;gt;
    &amp;lt;!-- each file should be at most 100MB, keep 60 days worth of history, but at most 20GB --&amp;gt;
    &amp;lt;maxFileSize&amp;gt;100MB&amp;lt;/maxFileSize&amp;gt;    
    &amp;lt;maxHistory&amp;gt;60&amp;lt;/maxHistory&amp;gt;
    &amp;lt;totalSizeCap&amp;gt;20GB&amp;lt;/totalSizeCap&amp;gt;
&amp;lt;/rollingPolicy&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;FixedWindowRollingPolicy -&amp;nbsp; &lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;fixed window 알고리즘으로 동작합니다. 특정 인덱스를 넘기면 롤오버합니다.&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;
&lt;pre id=&quot;code_1643554566891&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;rollingPolicy class=&quot;ch.qos.logback.core.rolling.FixedWindowRollingPolicy&quot;&amp;gt;
    &amp;lt;fileNamePattern&amp;gt;tests.%i.log.zip&amp;lt;/fileNamePattern&amp;gt;
    &amp;lt;minIndex&amp;gt;1&amp;lt;/minIndex&amp;gt;
    &amp;lt;maxIndex&amp;gt;3&amp;lt;/maxIndex&amp;gt;
&amp;lt;/rollingPolicy&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;triggering Policy&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SizeBasedTriggeringPolicy - 특정 파일 사이즈를 넘어가면 롤오버하도록 트리거 합니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;
&lt;pre id=&quot;code_1643555265866&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;triggeringPolicy class=&quot;ch.qos.logback.core.rolling.SizeBasedTriggeringPolicy&quot;&amp;gt; 
    &amp;lt;maxFileSize&amp;gt;5MB&amp;lt;/maxFileSize&amp;gt; 
&amp;lt;/triggeringPolicy&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;b&gt;▶&lt;/b&gt;Encoder&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인코더는 이벤트를 바이트 배열로 변환하고 해당 바이트 배열을&amp;nbsp;OutputStream으로 변환합니다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1643554898141&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;encoder&amp;gt;
  &amp;lt;pattern&amp;gt;%d %-5level [%thread] %logger{0}: %msg%n&amp;lt;/pattern&amp;gt;
  &amp;lt;outputPatternAsHeader&amp;gt;true&amp;lt;/outputPatternAsHeader&amp;gt;
&amp;lt;/encoder&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;▶&lt;/b&gt;&lt;/b&gt;Layout&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;0.9.19&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;이전의 logback은 대부분의 Appender는 Layout에 의존하여 이벤트를 문자열로 변환하였으나 0.9.19부터&lt;span&gt;&amp;nbsp;&lt;/span&gt;FileAppender하위 클래스는 &lt;span style=&quot;color: #ee2323;&quot;&gt;더 이상 레이아웃을 사용하지 않습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;▶&lt;/b&gt;&lt;/b&gt;Filter&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;Filter는 삼항 논리를 기반으로 하여 조합되거나 연결되어 임의로 복잡한 필터링 정책을 구성할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #000000;&quot;&gt;필터 정보는 &lt;a href=&quot;https://logback.qos.ch/manual/filters.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;공식 문서&lt;/a&gt;에서 확인 할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 59.0698%; height: 281px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignCenter&quot; data-ke-style=&quot;style13&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;Filter Name&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 20px; text-align: center;&quot;&gt;&lt;b&gt;TYPE&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 20px;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;event&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 20px;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;LoggingEvent&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 20px;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;message&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 20px;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;String&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 20px;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;formattedMessage&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 20px;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;String&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 20px;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;logger&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 20px;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;String&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 20px;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;loggerContext&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 20px;&quot;&gt;&lt;b&gt;LoggerContextVO&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 20px;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;level&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 20px;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;int&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 20px;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;timeStamp&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 20px;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;long&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 20px;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;marker&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 20px;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Marker&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 20px;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;mdc&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;br /&gt;&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 20px;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Map&lt;/span&gt;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1643537417186&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;filter class=&quot;ch.qos.logback.classic.filter.LevelFilter&quot;&amp;gt;
   &amp;lt;level&amp;gt;WARN&amp;lt;/level&amp;gt;
   &amp;lt;onMatch&amp;gt;ACCEPT&amp;lt;/onMatch&amp;gt;
   &amp;lt;onMismatch&amp;gt;DENY&amp;lt;/onMismatch&amp;gt;
&amp;lt;/filter&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Spring Boot 적용하기&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;로깅 프레임워크인 logback-classic 모듈은 logback-classic.jar&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;외에도&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;logback-core.jar 가 필요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;spring-boot-starter를 implementation 사용하고 있다면 특별한 설정 없이 사용이 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;448&quot; data-origin-height=&quot;376&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IFgpq/btrr5UZXRKE/ckcKWbcB3yXIsZFydhtrK0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IFgpq/btrr5UZXRKE/ckcKWbcB3yXIsZFydhtrK0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IFgpq/btrr5UZXRKE/ckcKWbcB3yXIsZFydhtrK0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIFgpq%2Fbtrr5UZXRKE%2FckcKWbcB3yXIsZFydhtrK0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;448&quot; height=&quot;376&quot; data-origin-width=&quot;448&quot; data-origin-height=&quot;376&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;src/main/recources 경로에 logback 설정 파일인 logback-spring.xml 파일을 생성합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;303&quot; data-origin-height=&quot;209&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bzAoUK/btrr4wFaY1I/5MQolFD0QZ4LYAUBYuhXlK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bzAoUK/btrr4wFaY1I/5MQolFD0QZ4LYAUBYuhXlK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bzAoUK/btrr4wFaY1I/5MQolFD0QZ4LYAUBYuhXlK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbzAoUK%2Fbtrr4wFaY1I%2F5MQolFD0QZ4LYAUBYuhXlK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;303&quot; height=&quot;209&quot; data-origin-width=&quot;303&quot; data-origin-height=&quot;209&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;logback-spring.xml의 예시 입니다. &lt;a href=&quot;https://www.youtube.com/watch?v=JqZzy7RyudI&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;검프의 Logging(로깅) #2&lt;/a&gt; 영상을 참고하여 작성하였습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1643549846945&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&amp;gt;

&amp;lt;configuration&amp;gt;
    &amp;lt;timestamp key=&quot;BY_DATE&quot; datePattern=&quot;yyyy-MM-dd&quot;/&amp;gt;
    &amp;lt;property name=&quot;LOG_PATTERN&quot;
              value=&quot;[%d{yyyy-MM-dd HH:mm:ss}:%-4relative] %green([%thread]) %highlight(%-5level) %boldWhite([%C.%M:%yellow(%L)]) - %msg%n&quot;/&amp;gt;

    &amp;lt;springProfile name=&quot;prod&quot;&amp;gt;
        &amp;lt;appender name=&quot;FILE-INFO&quot; class=&quot;ch.qos.logback.core.rolling.RollingFileAppender&quot;&amp;gt;
            &amp;lt;file&amp;gt;./log/info/info-${BY_DATE}.log&amp;lt;/file&amp;gt;
            &amp;lt;filter class=&quot;ch.qos.logback.classic.filter.LevelFilter&quot;&amp;gt;
                &amp;lt;level&amp;gt;INFO&amp;lt;/level&amp;gt;
                &amp;lt;onMatch&amp;gt;ACCEPT&amp;lt;/onMatch&amp;gt;
                &amp;lt;onMismatch&amp;gt;DENY&amp;lt;/onMismatch&amp;gt;
            &amp;lt;/filter&amp;gt;
            &amp;lt;encoder&amp;gt;
                &amp;lt;pattern&amp;gt;${LOG_PATTERN}&amp;lt;/pattern&amp;gt;
            &amp;lt;/encoder&amp;gt;
            &amp;lt;rollingPolicy class=&quot;ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy&quot;&amp;gt;
                &amp;lt;fileNamePattern&amp;gt;./backup/info/info-%d{yyyy-MM-dd}.%i.log&amp;lt;/fileNamePattern&amp;gt;
                &amp;lt;maxFileSize&amp;gt;100MB&amp;lt;/maxFileSize&amp;gt;
                &amp;lt;maxHistory&amp;gt;30&amp;lt;/maxHistory&amp;gt;
                &amp;lt;totalSizeCap&amp;gt;3GB&amp;lt;/totalSizeCap&amp;gt;
            &amp;lt;/rollingPolicy&amp;gt;
        &amp;lt;/appender&amp;gt;

        &amp;lt;appender name=&quot;FILE-WARN&quot; class=&quot;ch.qos.logback.core.rolling.RollingFileAppender&quot;&amp;gt;
            &amp;lt;file&amp;gt;./log/warn/warn-${BY_DATE}.log&amp;lt;/file&amp;gt;
            &amp;lt;filter class=&quot;ch.qos.logback.classic.filter.LevelFilter&quot;&amp;gt;
                &amp;lt;level&amp;gt;WARN&amp;lt;/level&amp;gt;
                &amp;lt;onMatch&amp;gt;ACCEPT&amp;lt;/onMatch&amp;gt;
                &amp;lt;onMismatch&amp;gt;DENY&amp;lt;/onMismatch&amp;gt;
            &amp;lt;/filter&amp;gt;
            &amp;lt;encoder&amp;gt;
                &amp;lt;pattern&amp;gt;${LOG_PATTERN}&amp;lt;/pattern&amp;gt;
            &amp;lt;/encoder&amp;gt;
            &amp;lt;rollingPolicy class=&quot;ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy&quot;&amp;gt;
                &amp;lt;fileNamePattern&amp;gt;./backup/warn/warn-%d{yyyy-MM-dd}.%i.log&amp;lt;/fileNamePattern&amp;gt;
                &amp;lt;maxFileSize&amp;gt;100MB&amp;lt;/maxFileSize&amp;gt;
                &amp;lt;maxHistory&amp;gt;30&amp;lt;/maxHistory&amp;gt;
                &amp;lt;totalSizeCap&amp;gt;3GB&amp;lt;/totalSizeCap&amp;gt;
            &amp;lt;/rollingPolicy&amp;gt;
        &amp;lt;/appender&amp;gt;

        &amp;lt;appender name=&quot;FILE-ERROR&quot; class=&quot;ch.qos.logback.core.rolling.RollingFileAppender&quot;&amp;gt;
            &amp;lt;file&amp;gt;./log/error/error-${BY_DATE}.log&amp;lt;/file&amp;gt;
            &amp;lt;filter class=&quot;ch.qos.logback.classic.filter.LevelFilter&quot;&amp;gt;
                &amp;lt;level&amp;gt;ERROR&amp;lt;/level&amp;gt;
                &amp;lt;onMatch&amp;gt;ACCEPT&amp;lt;/onMatch&amp;gt;
                &amp;lt;onMismatch&amp;gt;DENY&amp;lt;/onMismatch&amp;gt;
            &amp;lt;/filter&amp;gt;
            &amp;lt;encoder&amp;gt;
                &amp;lt;pattern&amp;gt;${LOG_PATTERN}&amp;lt;/pattern&amp;gt;
            &amp;lt;/encoder&amp;gt;
            &amp;lt;rollingPolicy class=&quot;ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy&quot;&amp;gt;
                &amp;lt;fileNamePattern&amp;gt;./backup/error/error-%d{yyyy-MM-dd}.%i.log&amp;lt;/fileNamePattern&amp;gt;
                &amp;lt;maxFileSize&amp;gt;100MB&amp;lt;/maxFileSize&amp;gt;
                &amp;lt;maxHistory&amp;gt;30&amp;lt;/maxHistory&amp;gt;
                &amp;lt;totalSizeCap&amp;gt;3GB&amp;lt;/totalSizeCap&amp;gt;
            &amp;lt;/rollingPolicy&amp;gt;
        &amp;lt;/appender&amp;gt;

        &amp;lt;root level=&quot;INFO&quot;&amp;gt;
            &amp;lt;appender-ref ref=&quot;FILE-INFO&quot;/&amp;gt;
            &amp;lt;appender-ref ref=&quot;FILE-WARN&quot;/&amp;gt;
            &amp;lt;appender-ref ref=&quot;FILE-ERROR&quot;/&amp;gt;
        &amp;lt;/root&amp;gt;
    &amp;lt;/springProfile&amp;gt;
&amp;lt;/configuration&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Post&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://zangzangs.tistory.com/165&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2022.01.29 - [Spring Boot] - 로그(log) 기록하기, SLF4J란?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://zangzangs.tistory.com/166&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2022.01.30 - [Spring Boot] - Logback이란? feat.SLF4J&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;References&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=JqZzy7RyudI&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;검프의&amp;nbsp;Logging(로깅)&amp;nbsp;#2&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://logback.qos.ch/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://logback.qos.ch/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignCenter&quot; data-emoticon-type=&quot;niniz&quot; data-emoticon-name=&quot;012&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘못된 코드나 내용이 있다면 댓글을 남겨주세요. 즉시 수정하도록 하겠습니다! :)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Spring Boot</category>
      <category>log</category>
      <category>logback</category>
      <category>slf4j</category>
      <category>springboot</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/166</guid>
      <comments>https://zangzangs.tistory.com/166#entry166comment</comments>
      <pubDate>Sun, 30 Jan 2022 18:51:08 +0900</pubDate>
    </item>
    <item>
      <title>로그(log) 기록하기, SLF4J란?</title>
      <link>https://zangzangs.tistory.com/165</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;751&quot; data-origin-height=&quot;329&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cD7Wkb/btrr2Xo5qAH/2FYVF4Lo2BWMFWjCx7wsCk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cD7Wkb/btrr2Xo5qAH/2FYVF4Lo2BWMFWjCx7wsCk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cD7Wkb/btrr2Xo5qAH/2FYVF4Lo2BWMFWjCx7wsCk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcD7Wkb%2Fbtrr2Xo5qAH%2F2FYVF4Lo2BWMFWjCx7wsCk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;751&quot; height=&quot;329&quot; data-origin-width=&quot;751&quot; data-origin-height=&quot;329&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;로그(log) 기록하기, SLF4J란?&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;SLF4J 란?&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;a href=&quot;https://www.slf4j.org/&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;&lt;u&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Simple Logging Facade for Java (SLF4J)&lt;/span&gt;&lt;/u&gt;&lt;/span&gt;&lt;/b&gt;&lt;/a&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;Facade(퍼사드 패턴 : 간략화된 인터페이스를 제공해주는 디자인 패턴)&lt;/b&gt;&lt;/span&gt;라는 단어의 뜻 처럼 JAVA에서 심플한 로깅 인터페이스를 제공하는 API&amp;nbsp;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #4d5156;&quot;&gt;※&amp;nbsp;API: (Application Programming Interface, 응용 프로그램 프로그래밍 인터페이스)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;다양한 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;로깅 프레임워크(&lt;span style=&quot;background-color: #ffffff;&quot;&gt;logging framework&lt;/span&gt;)&lt;/b&gt;&lt;/span&gt;들에 대한 추상화 역할을 제공하여 최종 사용자가 배포 시 원하는 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;로깅 프레임워크&lt;/b&gt;&lt;/span&gt;를 연결할 수 있도록 합니다&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1203&quot; data-origin-height=&quot;820&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bPbqI1/btrr15VsiUf/ifgTeEbAHjsCjeNBzAbXHk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bPbqI1/btrr15VsiUf/ifgTeEbAHjsCjeNBzAbXHk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bPbqI1/btrr15VsiUf/ifgTeEbAHjsCjeNBzAbXHk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbPbqI1%2Fbtrr15VsiUf%2FifgTeEbAHjsCjeNBzAbXHk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;505&quot; height=&quot;344&quot; data-origin-width=&quot;1203&quot; data-origin-height=&quot;820&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;위 그림처럼 사용자는 구체적인 구현체에 직접 접근하지 않습니다. SLF4J에 요청하면 바인딩 된 구현체가 로깅 작업을 하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;SLF4J API를 사용하는 로깅 프레임워크로는 &lt;b&gt;java.util.logging, &lt;b&gt;log4j,&lt;/b&gt; logback, log4j2&lt;/b&gt; 등이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;Spring Boot는 SLF4J와 logback을 기본으로 사용하고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;a data-copystatus=&quot;32&quot; data-copyfailedreason=&quot;0&quot; data-clipservice-ccpid=&quot;31bc41f2-f4c7-4a24-999f-21d4a1828f06&quot; data-clipservice-version=&quot;19&quot; data-clipservice-location=&quot;wADm8ysmPUm_myINlRvJUV9odHRwOi8vb3MxcGVwZjAwMDA0ZGZlL3BvZHMvcG9kQ2xpcC5zdmM_UG9kU0lEPV8uXy5fLmNiZTQ3MGMyLWZjNTYtODgyNC00MjUwLWRiYzBkZWMxZDJkNi0uLS4tLg2&quot; data-clipservice-dc=&quot;PJP1&quot; data-clipservice-type=&quot;shape&quot; data-clipservice-count=&quot;1&quot; data-clipservice-cut=&quot;false&quot; data-clipservice-isemptyplaceholder=&quot;false&quot; data-pkey=&quot;9f5e1ec1-5c7e-4b23-aec3-83995f7002b0&quot; data-timestamp=&quot;Sat, 29 Jan 2022 11:13:19 GMT&quot; data-clipservice-param=&quot;{&amp;quot;msb&amp;quot;:[true]}&quot; data-sessionid=&quot;30ac480b-3068-4ae4-bd8c-36946f6aa52e&quot; data-shapeids=&quot;39&quot; data-slideid=&quot;&quot;&gt;&amp;nbsp;&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;SLF4J 모듈 구성&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;SLF4J는 크게 3가지 모듈로 구성되어 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;1. SLF4J-API&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;a href=&quot;https://www.slf4j.org/api/org/slf4j/Logger.html&quot;&gt;Logger interface&lt;/a&gt; 를 제공하며 로그 레벨에 따른 출력(printing) 메서드들을 제공합니다.&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 220px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 25%; text-align: center; height: 20px;&quot;&gt;로그 레벨&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 20px; text-align: center;&quot;&gt;출력 메서드&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px; text-align: center;&quot;&gt;설명&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 25%; text-align: center; height: 20px;&quot;&gt;TRACE&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 20px; text-align: center;&quot;&gt;trace()&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #474747;&quot;&gt;세분화된 정보 이벤트를 지정&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 40px;&quot;&gt;
&lt;td style=&quot;width: 25%; text-align: center; height: 40px;&quot;&gt;DEBUG&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 40px; text-align: center;&quot;&gt;debug()&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 40px;&quot;&gt;애플리케이션을 디버그하는 데 가장 유용한 세분화된 정보를 지정&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 40px;&quot;&gt;
&lt;td style=&quot;width: 25%; text-align: center; height: 40px;&quot;&gt;INFO&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 40px; text-align: center;&quot;&gt;info()&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 40px;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #474747;&quot;&gt;대략적인 수준에서 응용 프로그램의 진행 상황을 강조하는 정보 메시지를 지정&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 25%; text-align: center; height: 20px;&quot;&gt;WARN&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 20px; text-align: center;&quot;&gt;warn()&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #474747;&quot;&gt;잠재적으로 위험이 될 상황을 지정&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 40px;&quot;&gt;
&lt;td style=&quot;width: 25%; text-align: center; height: 40px;&quot;&gt;ERROR&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 40px; text-align: center;&quot;&gt;error()&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 40px;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #474747;&quot;&gt;애플리케이션이 계속 실행되도록 허용할 수 있는 오류 이벤트를 지정&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 40px;&quot;&gt;
&lt;td style=&quot;width: 25%; text-align: center; height: 40px;&quot;&gt;FATAL&lt;/td&gt;
&lt;td style=&quot;width: 25%; text-align: center; height: 40px;&quot;&gt;X&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 40px;&quot;&gt;응용 프로그램이 중단될 수 있는 매우 심각한 오류&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;2. SLF4J Binding (jar)&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;SLF4J-API 모듈은 class-path에 있는 로깅 프레임워크(logging framework) 구현체를 Class-loader 방식으로 바인딩 합니다. 이 때 구현체는 오직 &lt;b&gt;하나&lt;/b&gt;만 있어야 합니다. class path에 jar파일이 없을 시 no-operation 으로 설정됩니다. 즉, 아무것도 출력하지 않습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1271&quot; data-origin-height=&quot;809&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bYTd2p/btrr5VEa1TS/vt5Uyoi8RCje82B1szp0ek/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bYTd2p/btrr5VEa1TS/vt5Uyoi8RCje82B1szp0ek/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bYTd2p/btrr5VEa1TS/vt5Uyoi8RCje82B1szp0ek/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbYTd2p%2Fbtrr5VEa1TS%2Fvt5Uyoi8RCje82B1szp0ek%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1271&quot; height=&quot;809&quot; data-origin-width=&quot;1271&quot; data-origin-height=&quot;809&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;위 사진은 로깅 프레임 워크를 바인딩하는 방법을 그래프로 표현한 사진입니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;(아무것도 바인딩 하지 않은 경우)&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;logback-classic.jar, logback-core.jar &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;(logback-classic)&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;slf4j-reload4j.jar &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;(reload4j)&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;slf4j-jdkXX.jar &lt;b&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;(java.util.logging)&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;slf4j-simple.jar &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;(simple)&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;slf4j-nop.jar &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;(no-operation)&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;3. SLF4J Bridge&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;프로젝트에서 일부 구성 요소는 SLF4J가 아닌 다른 로깅(logging) API에 의존하는 경우가 있습니다. 예를 들면 spring-context는 JCL(Jarkarta Commons Logging) API를 사용합니다. 또한 이러한 구성 요소가 SLF4J로 전환되지 않을 수도 있습니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;이러한 상황을 처리하기 위해 SLF4J는 log4j, JCL 및 java.util.logging API에 대한 호출을 리디렉션하여 &lt;b&gt;SLF4J API에 대해 만들어진 것처럼 동작하도록 하는 여러 브리징 모듈&lt;/b&gt;과 을 제공합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;그림은 SLF4J Bridge 모듈의 동작 아이디어 입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;905&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bDtwcM/btrr5UkZGTl/bnXY2qTgaYEc7NK3q7Hyr0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bDtwcM/btrr5UkZGTl/bnXY2qTgaYEc7NK3q7Hyr0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bDtwcM/btrr5UkZGTl/bnXY2qTgaYEc7NK3q7Hyr0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbDtwcM%2Fbtrr5UkZGTl%2FbnXY2qTgaYEc7NK3q7Hyr0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;905&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;905&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;SLF4J 동작 방식&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;780&quot; data-origin-height=&quot;264&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ttLhC/btrr3omA4AQ/jtZohwdRwc0QQtWAPnnKP1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ttLhC/btrr3omA4AQ/jtZohwdRwc0QQtWAPnnKP1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ttLhC/btrr3omA4AQ/jtZohwdRwc0QQtWAPnnKP1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FttLhC%2Fbtrr3omA4AQ%2FjtZohwdRwc0QQtWAPnnKP1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;780&quot; height=&quot;264&quot; data-origin-width=&quot;780&quot; data-origin-height=&quot;264&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Post&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://zangzangs.tistory.com/165&quot;&gt;2022.01.29 - [Spring Boot] - 로그(log) 기록하기, SLF4J란?&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://zangzangs.tistory.com/166&quot;&gt;2022.01.30 - [Spring Boot] - Logback이란? feat.SLF4J&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;References&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.slf4j.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.slf4j.org/&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://gmlwjd9405.github.io/2019/01/04/logging-with-slf4j.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://gmlwjd9405.github.io/2019/01/04/logging-with-slf4j.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://livenow14.tistory.com/63?category=1009785&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://livenow14.tistory.com/63?category=1009785&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignCenter&quot; data-emoticon-type=&quot;niniz&quot; data-emoticon-name=&quot;012&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘못된 코드나 내용이 있다면 댓글을 남겨주세요. 즉시 수정하도록 하겠습니다! :)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Spring Boot</category>
      <category>logging</category>
      <category>slf4j</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/165</guid>
      <comments>https://zangzangs.tistory.com/165#entry165comment</comments>
      <pubDate>Sat, 29 Jan 2022 20:25:54 +0900</pubDate>
    </item>
    <item>
      <title>[스프링 부트] InvalidDataAccessApiUsageException: Unknown entity #그래들 멀티 모듈</title>
      <link>https://zangzangs.tistory.com/164</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;737&quot; data-origin-height=&quot;390&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvRfD5/btrrXriICdr/TIp1sNORgBLuI5vBSzevsk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvRfD5/btrrXriICdr/TIp1sNORgBLuI5vBSzevsk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvRfD5/btrrXriICdr/TIp1sNORgBLuI5vBSzevsk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbvRfD5%2FbtrrXriICdr%2FTIp1sNORgBLuI5vBSzevsk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;737&quot; height=&quot;390&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;737&quot; data-origin-height=&quot;390&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;[스프링 부트] InvalidDataAccessApiUsageException: Unknown entity 에러&lt;/h2&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;#그래들&amp;nbsp;멀티&amp;nbsp;모듈&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;인텔리제이로 프로젝트를 하던 중 에러가 났다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;JPA를 사용하고 있었는데 web, admin 에서 사용되는 domain이 공통으로 겹쳐게 되자 이를 효율적으로 사용하기 위해 web, admin, domain 3개의 멀티 그래들 모듈로 프로젝트를 구성한 상태였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1643292998018&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;├── web
│   ...
│   └── build.gradle
├── admin
│   ...
│   └── build.gradle
├── domain
│   ...
│   └── build.gradle
└── settings.gradle&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;그리고 admin에서 서버를 실행하자 다음과 같은 에러가 발생했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;InvalidDataAccessApiUsageException: Unknown entity&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;domain 모듈&lt;/b&gt;을 &lt;b&gt;admin 모듈&lt;/b&gt;의 서브 모듈로 설정 했지만 스프링 컨테이너가 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;domain 모듈에 있는 Entity를 인식하지 못해서 발생한 문제&lt;/b&gt;&lt;/span&gt;였다.&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;admin 모듈&lt;/b&gt;에서 scanBasePackages을 이용해서 &lt;b&gt;domain 모듈&lt;/b&gt;을 scan 하면 스프링 컨테이너가 Entity를 인식할 것이라 생각했는데 되지 않았다.&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@SpringBootApplication(scanBasePackages = {&quot;com.admin.*&quot;,&quot;com.domain.*&quot;})&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;해결방법&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;@EntityScan 어노테이션을 사용하면 다른 모듈의 Entity를 스캔할 수 있었다.&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@EntityScan(&quot;com.domain.*&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;또한 repository도 @EnableJpaRepositories 어노테이션을 사용해 스캔 할 수 있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@EnableJpaRepositories(&quot;com.domain.*&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;최종적인 admin 모듈의 AdminApplication 코드이다.&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@SpringBootApplication(scanBasePackages = {&quot;com.admin.*&quot;,&quot;com.domain.*&quot;})
@EntityScan(&quot;com.domain.*&quot;)
@EnableJpaRepositories(&quot;com.domain.*&quot;)
public class AdminApplication {

   public static void main(String[] args) {
      SpringApplication.run(AdminApplication.class, args);
   }

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;References&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://docs.gradle.org/current/userguide/multi_project_builds.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://docs.gradle.org/current/userguide/multi_project_builds.html&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://gwonsungjun.github.io/articles/2019-04/gradle_multi_module&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://gwonsungjun.github.io/articles/2019-04/gradle_multi_module&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignCenter&quot; data-emoticon-type=&quot;niniz&quot; data-emoticon-name=&quot;012&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘못된 코드나 내용이 있다면 댓글을 남겨주세요. 즉시 수정하도록 하겠습니다! :)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Spring Boot</category>
      <category>gradle</category>
      <category>gradle multi module</category>
      <category>spring boot</category>
      <category>그래들 멀티 모듈</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/164</guid>
      <comments>https://zangzangs.tistory.com/164#entry164comment</comments>
      <pubDate>Fri, 28 Jan 2022 01:31:14 +0900</pubDate>
    </item>
    <item>
      <title>[Spring boot] MySql 연결 에러,  com.mysql.cj.jdbc.driver</title>
      <link>https://zangzangs.tistory.com/162</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;737&quot; data-origin-height=&quot;390&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cgCJyv/btrq6PrW11c/IU4N2xjSxmL1bKkAAj68Jk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cgCJyv/btrq6PrW11c/IU4N2xjSxmL1bKkAAj68Jk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cgCJyv/btrq6PrW11c/IU4N2xjSxmL1bKkAAj68Jk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcgCJyv%2Fbtrq6PrW11c%2FIU4N2xjSxmL1bKkAAj68Jk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;737&quot; height=&quot;390&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;737&quot; data-origin-height=&quot;390&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;[스프링 부트] MySql 연결 에러, &lt;/b&gt;&lt;/h2&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;com.mysql.cj.jdbc.driver&lt;/b&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;this&amp;nbsp;is&amp;nbsp;deprecated.&amp;nbsp;the&amp;nbsp;new&amp;nbsp;driver&amp;nbsp;class&amp;nbsp;is&amp;nbsp;`com.mysql.cj.jdbc.driver'.&amp;nbsp;the&amp;nbsp;driver&amp;nbsp;is&amp;nbsp;automatically&amp;nbsp;registered&amp;nbsp;via&amp;nbsp;the&amp;nbsp;spi&amp;nbsp;and&amp;nbsp;manual&amp;nbsp;loading&amp;nbsp;of&amp;nbsp;the&amp;nbsp;driver&amp;nbsp;class&amp;nbsp;is&amp;nbsp;generally&amp;nbsp;unnecessary.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;뭔데&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 60px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 100%; height: 20px;&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-api-changes.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;4.4.1.3 Changes in the Connector/J API&lt;/span&gt;&lt;/span&gt;&lt;/a&gt;&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 40px;&quot;&gt;
&lt;td style=&quot;width: 100%; height: 40px;&quot;&gt;&lt;span&gt;&lt;span&gt;The name of the class that implements&lt;span&gt;&amp;nbsp;&lt;/span&gt;java.sql.Driver&lt;span&gt;&amp;nbsp;&lt;/span&gt;in MySQL Connector/J has changed from&lt;span&gt;&amp;nbsp;&lt;/span&gt;com.mysql.jdbc.Driver&lt;span&gt;&amp;nbsp;&lt;/span&gt;to&lt;span&gt;&amp;nbsp;&lt;/span&gt;com.mysql.cj.jdbc.Driver. The old class name has been deprecated.&lt;/span&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;버전 업데이트에 따라 Class 이름이 변경 되었다고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;b&gt;application&lt;/b&gt;.properties 사용&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;application.properties 을 사용할 경우 아래와 같이 변경한다.&lt;/p&gt;
&lt;pre id=&quot;code_1642516420919&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;spring.datasource.driver-class-name=com.mysql.jdbc.Driver&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1642516565380&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;application.yml 사용&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;application.yml 을 사용할 경우 아래와 같이 변경한다.&lt;/p&gt;
&lt;pre id=&quot;code_1642516462710&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;spring:
  datasource:
    driver-class-name: com.mysql.jdbc.Driver&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1642516479376&quot; class=&quot;css&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;spring:
  datasource:
    driver-class-name: com.mysql.cj.jdbc.Driver&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Post&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;References&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://dev.mysql.com/doc/connector-j/8.0/en/connector-j-api-changes.html&quot;&gt;&lt;span&gt;4.4.1.3 Changes in the Connector/J API&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/52032739/loading-class-com-mysql-jdbc-driver-this-is-deprecated-the-new-driver-class&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;스택오버플로우&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignCenter&quot; data-emoticon-type=&quot;niniz&quot; data-emoticon-name=&quot;012&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘못된 코드나 내용이 있다면 댓글을 남겨주세요. 즉시 수정하도록 하겠습니다! :)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Spring Boot</category>
      <category>error</category>
      <category>mysql</category>
      <category>springboot</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/162</guid>
      <comments>https://zangzangs.tistory.com/162#entry162comment</comments>
      <pubDate>Wed, 19 Jan 2022 00:01:10 +0900</pubDate>
    </item>
    <item>
      <title>[백준] 3197 백조의 호수 #JAVA #BFS #시간초과</title>
      <link>https://zangzangs.tistory.com/161</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-filename=&quot;알고리즘.png&quot; data-origin-width=&quot;945&quot; data-origin-height=&quot;502&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BdlZn/btrqCS9Rq6W/q5XCohlGqZlaZgwKK1OwEK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BdlZn/btrqCS9Rq6W/q5XCohlGqZlaZgwKK1OwEK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BdlZn/btrqCS9Rq6W/q5XCohlGqZlaZgwKK1OwEK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBdlZn%2FbtrqCS9Rq6W%2Fq5XCohlGqZlaZgwKK1OwEK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;945&quot; height=&quot;502&quot; data-filename=&quot;알고리즘.png&quot; data-origin-width=&quot;945&quot; data-origin-height=&quot;502&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;[백준] 3197 백조의 호수 #JAVA #BFS #시간초과&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;코드&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;pre id=&quot;code_1613404164341&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.io.*;
import java.util.*;

public class Main {
	
	static int[] dx = {0,1,0,-1};
	static int[] dy = {1,0,-1,0};
	static int R, C;
	static char[][] map;
	static boolean[][] visSwan, visWater;
	static Queue&amp;lt;int[]&amp;gt; waterQ, waterNextQ, swanQ, swanNextQ;
	
	static int startX, startY, endX, endY;
	
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		StringTokenizer st = new StringTokenizer(br.readLine());
		R = Integer.parseInt(st.nextToken()); //y
		C = Integer.parseInt(st.nextToken()); //x
		
		map = new char[R][C];
		
		visSwan = new boolean[R][C];
		swanQ = new LinkedList&amp;lt;&amp;gt;();
		swanNextQ = new LinkedList&amp;lt;int[]&amp;gt;();
		
		visWater = new boolean[R][C];
		waterQ = new LinkedList&amp;lt;int[]&amp;gt;();
		waterNextQ = new LinkedList&amp;lt;int[]&amp;gt;();
		
		int resultDays = -1;
		
		List&amp;lt;int[]&amp;gt; startEnd = new ArrayList&amp;lt;int[]&amp;gt;();
		
		for (int i = 0; i &amp;lt; R; i++) {
			String temp = br.readLine();
			for (int j = 0; j &amp;lt; C; j++) {
				
				if(temp.charAt(j) == 'X') {
					map[i][j] = 'X';
					
				}else {
					if(temp.charAt(j) == 'L') {
						startEnd.add(new int[] {j,i}); //x,y
					}
					waterQ.add(new int[] {j,i}); //x,y
					visWater[i][j] = true;
					map[i][j]='.';
				}
				
			}
		}
		
		startX =  startEnd.get(0)[0];
		startY =  startEnd.get(0)[1];
		endX =  startEnd.get(1)[0];
		endY =  startEnd.get(1)[1];
		
		visSwan[startY][startX] = true;
		swanQ.add(new int[] {startX, startY});

		while (!visSwan[endY][endX]) {
			waterBFS();
			swanBFS();
			resultDays++;
		}
		
		System.out.println(resultDays);
		
	}
	
	private static void swanBFS() {
		
		while (!swanNextQ.isEmpty()) {
			swanQ.add(swanNextQ.poll());
		}
		
		
		while (!swanQ.isEmpty()) {

			int[] cur = swanQ.poll();

			int x = cur[0];
			int y = cur[1];

			for (int k = 0; k &amp;lt; 4; k++) {
				int nx = x + dx[k];
				int ny = y + dy[k];

				if (nx &amp;lt; 0 || ny &amp;lt; 0 || nx &amp;gt;= C || ny &amp;gt;= R)	continue;
				if (visSwan[ny][nx]) continue;

				if (map[ny][nx] == 'X') {
					swanNextQ.add(new int[] {nx, ny});
				} else {
					swanQ.add(new int[] {nx, ny});
				}
				
				visSwan[ny][nx] = true;
			}
		}
	}
	
	private static void waterBFS() {
		while (!waterNextQ.isEmpty()) {
			int[] cur = waterNextQ.poll();
			map[cur[1]][cur[0]] = '.';
			waterQ.add(cur);
		}
		
		while (!waterQ.isEmpty()) {

			int[] cur = waterQ.poll();

			int x = cur[0];
			int y = cur[1];
			
			for (int k = 0; k &amp;lt; 4; k++) {
				int nx = x + dx[k];
				int ny = y + dy[k];

				if (nx &amp;lt; 0 || ny &amp;lt; 0 || nx &amp;gt;= C || ny &amp;gt;= R)	continue;
				if (visWater[ny][nx]) continue;
				
				if (map[ny][nx] == 'X') {
					waterNextQ.add(new int[] {nx, ny});
					visWater[ny][nx] = true;
				}
				
			}
		}
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;풀이&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;BFS를 통해 빙하를 녹여 물로 만든다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시간 단축을 위해 2개의 큐를 사용한다. &lt;b&gt;waterQ, waterNextQ(다음 턴에 물이 될 좌표)&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;waterQ&lt;/b&gt;를 BFS하며 다음 턴에 빙하에서 물이 될 좌표를 탐색하여 waterNextQ에 담는다.&lt;/li&gt;
&lt;li&gt;턴이 지날 때 마다 &lt;b&gt;waterNextQ&lt;/b&gt;의 좌표를 &lt;b&gt;waterQ&lt;/b&gt;로 옮긴다. 이 때, map을 &lt;b&gt;'X(빙하)'에서 '.(물)'로 변환&lt;/b&gt;한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;BFS를 통해 백조가 만날 수 있는지 확인한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시간 단축을 위해 2개의 큐를 사용한다. &lt;b&gt;swanQ, swanNextQ(다음 턴에 백조가 갈 수 있는 좌표)&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;swanQ&lt;/b&gt;를 BFS하며 다음 턴에 백조가 갈 수 있는 좌표를 탐색하여 &lt;b&gt;swanNextQ&lt;/b&gt;에 담는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;다른 백조가 있는 좌표에 방문 가능 할 때까지 1번과 2번을 반복한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;주의 사항&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;백조의 좌표는 물이다. 물에 대한 BFS를 돌릴 때 해당 좌표를 큐에 넣어야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘못된 코드나 내용이 있다면 댓글을 남겨주세요. 즉시 수정하도록 하겠습니다! :)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorithm Solving/BAEKJOON</category>
      <category>3197</category>
      <category>BFS</category>
      <category>java</category>
      <category>백조의호수</category>
      <category>백준</category>
      <category>시간초과</category>
      <category>자바</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/161</guid>
      <comments>https://zangzangs.tistory.com/161#entry161comment</comments>
      <pubDate>Thu, 13 Jan 2022 12:10:07 +0900</pubDate>
    </item>
    <item>
      <title>[백준] 18809 Gaaaaaaaaaarden #JAVA #백트래킹 #bfs</title>
      <link>https://zangzangs.tistory.com/160</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-filename=&quot;알고리즘.png&quot; data-origin-width=&quot;945&quot; data-origin-height=&quot;502&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/pXQVH/btrqun4jIXF/aCl4ZE6nTGlgao89U6hjD1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/pXQVH/btrqun4jIXF/aCl4ZE6nTGlgao89U6hjD1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/pXQVH/btrqun4jIXF/aCl4ZE6nTGlgao89U6hjD1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpXQVH%2Fbtrqun4jIXF%2FaCl4ZE6nTGlgao89U6hjD1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;945&quot; height=&quot;502&quot; data-filename=&quot;알고리즘.png&quot; data-origin-width=&quot;945&quot; data-origin-height=&quot;502&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;[백준] 18809 &lt;span&gt;Gaaaaaaaaaarden&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;#JAVA #백트래킹 #bfs&lt;/h2&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오랜 시간이 걸려서 풀었던 문제.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;코드&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;pre id=&quot;code_1613404164341&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.io.*;
import java.util.*;

public class Main {

	static List&amp;lt;int[]&amp;gt; baeyang;
	static int N,M,G,R;
	
	static int[][] garden;
	static int[] selectBaeyang;
	static int[] selectGR;
	static boolean[] isUsedBaeyang;
	static int[] spotG, spotR;
	
	static int[] dx = {0,1,0,-1};
	static int[] dy = {1,0,-1,0};
	
	static int max = 0;
	
	public static void main(String[] args) throws IOException{

		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		StringTokenizer st = new StringTokenizer(br.readLine());
		
		N = Integer.parseInt(st.nextToken()); //y
		M = Integer.parseInt(st.nextToken()); //x
		G = Integer.parseInt(st.nextToken());
		R = Integer.parseInt(st.nextToken());
		
		
		garden = new int[N][M];

		
		// 0 - 호수, 못들어가는 땅
		// 1 - 배양액, 배양액을 뿌릴 수 없는 땅
		// 2 - 배양액을 뿌릴 수 있는 땅

		
		baeyang = new ArrayList&amp;lt;int[]&amp;gt;();
		
		for (int i = 0; i &amp;lt; N; i++) {
			st = new StringTokenizer(br.readLine());
			for (int j = 0; j &amp;lt; M; j++) {
				garden[i][j] = Integer.parseInt(st.nextToken());
				
				if(garden[i][j] == 2) {
					baeyang.add(new int[] {j,i}); //x,y
				}
			}
			
		}
		
		isUsedBaeyang = new boolean[baeyang.size()];
		spotG = new int[G];
		spotR = new int[R];
		
		Arrays.fill(spotG, -1);
		Arrays.fill(spotR, -1);
		
		findSpotG(0);
		
		System.out.println(max);
	}
	
	/**
	 * G 배양액 좌표를 백트래킹으로 구한다.
	 */
	static void findSpotG(int k) {
		if(k == G) {
			findSpotR(0); // G 배양액 좌표를 다 구하면, R 배양액 좌표를 구한다.
			return;
		}
		
		for (int i = 0; i &amp;lt; baeyang.size(); i++) {
			if(isUsedBaeyang[i]) continue;
			if(k &amp;gt; 0 &amp;amp;&amp;amp; spotG[k-1] &amp;gt; i) continue;
			isUsedBaeyang[i] = true;
			spotG[k] = i;
			findSpotG(k+1);
			spotG[k] = -1;
			isUsedBaeyang[i] = false;
			
		}
	}
	
	/**
	 * R 배양액 좌표를 구한다.
	 */
	static void findSpotR(int k) {
		if(k == R) {
			bfs(); //G,R 배양액의 좌표를 가지고 BFS를 통해 꽃의 개수를 구한다.
			return;
		}
		
		for (int i = 0; i &amp;lt; baeyang.size(); i++) {
			if(isUsedBaeyang[i]) continue;
			if(k &amp;gt; 0 &amp;amp;&amp;amp; spotR[k-1] &amp;gt; i) continue;
			isUsedBaeyang[i] = true;
			spotR[k] = i;
			findSpotR(k+1);
			spotR[k] = -1;
			isUsedBaeyang[i] = false;
			
		}
	}
	
	static void bfs() {
		int flower = 0;
		int[][] dist = new int[N][M];
		char[][] flw = new char[N][M];
		
		Queue&amp;lt;int[]&amp;gt; Q = new LinkedList&amp;lt;int[]&amp;gt;();
		
		for (int g : spotG) {
			int tmp[] = baeyang.get(g);
			int x = tmp[0];
			int y = tmp[1];
			
			flw[y][x] = 'G';
			dist[y][x] = 1;
			Q.add(new int[] {x,y, 0, 1}); // , G/R ,time;
		}
		
		for (int r : spotR) {
			int tmp[] = baeyang.get(r);
			int x = tmp[0];
			int y = tmp[1];
			
			flw[y][x] = 'R';
			dist[y][x] = 1;
			Q.add(new int[] {x,y, 1, 1});
		}
		
		// 0 - 호수, 못들어가는 땅
		// 1 - 배양액, 배양액을 뿌릴 수 없는 땅
		// 2 - 배양액을 뿌릴 수 있는 땅

			
		//초록 배양액 bfs
		while (!Q.isEmpty()) {
			int[] cur = Q.poll(); //x,y
			int x = cur[0];
			int y = cur[1];
			char color = cur[2] == 0 ? 'G' : 'R'; //G:0 , R:1
			int time = cur[3];
			
			if(flw[y][x] == 'F') continue; //중요! : 이미 큐에 들어온 좌표가 꽃이 되는 경우가 있다.
			
			for (int k = 0; k &amp;lt; 4; k++) {
				int nx = dx[k] + x;
				int ny = dy[k] + y;
				
				if(nx&amp;lt;0 || ny&amp;lt;0 || nx&amp;gt;= M || ny &amp;gt;= N) continue;
				if(garden[ny][nx] == 0) {
					flw[ny][nx] = 'h';
					continue; //호수
				}
				if(flw[ny][nx] == 'F') continue; //이미 꽃이 피었다.
				if(flw[ny][nx] == color) continue; //같은 색상의 배양액
					
				//다른 색상의 배양색을 만날경우
				if(((color == 'G' &amp;amp;&amp;amp; flw[ny][nx] == 'R')) || (color == 'R' &amp;amp;&amp;amp; flw[ny][nx] == 'G')) {
					if(dist[ny][nx] == time+1) {
						flw[ny][nx] = 'F';
						flower++;
					}
					continue;
				}
				
				flw[ny][nx] = color;
				dist[ny][nx] = time+1;
				
				Q.add(new int[] {nx,ny, cur[2], time+1}); //x,y
			}
		}
		
		max = Math.max(flower, max);
		
		
	}

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;풀이&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;먼저 배양액이 뿌려질 수 있는 좌표의 조합을 구한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;백트래킹을 사용하여 G의 좌표를 구하고, 다음으로 R의 좌표를 구했다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;좌표를 구한 뒤 BFS를 이용하여 꽃이 피는 개수를 구한다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;큐에 {x좌표, y좌표, 배양액컬러, 시간} 을 넣는다. (문제와 다르게 시간은 1부터 시작하는 것으로 했다.)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;큐에서 꺼낸 현재 좌표가 꽃인지 체크한다.&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;조건에 맞는 좌표를 다시 큐에 삽입한다.
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;방문 좌표가 &lt;b&gt;호수인지&lt;/b&gt; 체크&lt;/li&gt;
&lt;li&gt;방문 좌표가 &lt;b&gt;꽃이 피었는지&lt;/b&gt; 체크&lt;/li&gt;
&lt;li&gt;방문 좌표가 &lt;b&gt;같은 색상의 배양액이 방문했는지&lt;/b&gt; 체크&lt;/li&gt;
&lt;li&gt;방문 좌표가 &lt;b&gt;다른 생상의 배양액이 방문했는지&lt;/b&gt; 체크 -&amp;gt; 방문 시간이 같으면 꽃을 피움&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;주의 사항&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;큐에서 꺼낸 현재 좌표가 꽃인지 체크한다.&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;위 조건 때문에 계속 틀렸었다. G가 방문하고 새로운 좌표를 큐에 넣게 된다. 그런데 R이 해당 좌표를 같은 시간에 방문하면 해당 좌표는 꽃이 된다. 즉, 큐에 들어있는 G의 좌표가 이미 꽃인 경우가 발생하게 되는데 이부분을 체크하지 못해서 계속해서 갯수가 정답보다 많이 나오는 오류에 걸렸었다.&lt;/li&gt;
&lt;li&gt;설계에서 해당 부분을 놓치게 되니, 오류를 찾기 위해 무한 디버그에 빠져버렸다.&lt;/li&gt;
&lt;li&gt;풀이 계획을 잘 세우자..&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘못된 코드나 내용이 있다면 댓글을 남겨주세요. 즉시 수정하도록 하겠습니다! :)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorithm Solving/BAEKJOON</category>
      <category>18809</category>
      <category>backtracking</category>
      <category>BFS</category>
      <category>Gaaaaaaaaaarden</category>
      <category>java</category>
      <category>백준</category>
      <category>백트래킹</category>
      <category>자바</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/160</guid>
      <comments>https://zangzangs.tistory.com/160#entry160comment</comments>
      <pubDate>Wed, 12 Jan 2022 14:34:14 +0900</pubDate>
    </item>
    <item>
      <title>[백준] 1202 보석 도둑 #JAVA #우선순위 큐</title>
      <link>https://zangzangs.tistory.com/158</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-filename=&quot;알고리즘.png&quot; data-origin-width=&quot;945&quot; data-origin-height=&quot;502&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ul9es/btroSs6ZLWg/Ug8Q1Lsny8oywGYucgiRhK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ul9es/btroSs6ZLWg/Ug8Q1Lsny8oywGYucgiRhK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ul9es/btroSs6ZLWg/Ug8Q1Lsny8oywGYucgiRhK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUl9es%2FbtroSs6ZLWg%2FUg8Q1Lsny8oywGYucgiRhK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;945&quot; height=&quot;502&quot; data-filename=&quot;알고리즘.png&quot; data-origin-width=&quot;945&quot; data-origin-height=&quot;502&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;[백준] 1202 보석 도둑 #JAVA #우선순위 큐&lt;/h2&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;코드&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;pre id=&quot;code_1613404164341&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.PriorityQueue;
import java.util.StringTokenizer;

public class Main {

	public static void main(String[] args) throws IOException{
		
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st;
		
		st = new StringTokenizer(br.readLine());
		
		int N = Integer.parseInt(st.nextToken()); //보석 정보 개수
		int K = Integer.parseInt(st.nextToken());
		
		//1. 보석의 무게, 가치를 담는 우선순위 큐 정의
		PriorityQueue&amp;lt;int[]&amp;gt; pQ = new PriorityQueue&amp;lt;int[]&amp;gt;((a,b)-&amp;gt;{
			if(a[0]-b[0] == 0) {
				return b[1]-a[1]; //가치 내림차순 정렬
			}
			return a[0]-b[0];//무게 오름 차순 정렬
		});
		
		//1-1. 우선순위 큐에 보석 정보 저장	
		for (int i = 0; i &amp;lt; N; i++) {
			st = new StringTokenizer(br.readLine());
			
			int M = Integer.parseInt(st.nextToken()); //보석 무게
			int V = Integer.parseInt(st.nextToken()); //보석 가격
			
			pQ.add(new int[] {M,V});
			
		}
		
		//2. 가방 정보 저장하는 List
		List&amp;lt;Integer&amp;gt; bag = new ArrayList&amp;lt;Integer&amp;gt;();
		for (int i = 0; i &amp;lt; K; i++) {
			int C = Integer.parseInt(br.readLine()); //가방 최대 무게 
			bag.add(C);
		}
		//2-1. 가방 오름차순 정렬
		Collections.sort(bag);
		
		
		//3. 가방에 들어갈 수 있는 무게를 valueQ로 옮긴후 가장 가치가 큰 값을 total에 더한다.
		PriorityQueue&amp;lt;Integer&amp;gt; valueQ = new PriorityQueue&amp;lt;Integer&amp;gt;(Collections.reverseOrder());
		long total = 0;
		for (int i = 0; i &amp;lt; bag.size(); i++) {
			int weight = bag.get(i);
			
			while (!pQ.isEmpty()) {
				 
				if(pQ.peek()[0] &amp;lt;= weight) {
					valueQ.add(pQ.poll()[1]); //가치만 넣는다.
				}else {
					break;
				}
			}
			
			if(valueQ.isEmpty()) continue;
			total += valueQ.poll();
			
			
		}

		
		System.out.println(total);
		
		
	}

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;풀이&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;그리디 알고리즘기반으로 &lt;b&gt;무게&lt;/b&gt;와 &lt;b&gt;가치&lt;/b&gt;를 고려해야 하다보니 꽤 복잡하여 고생한 고전한 문제입니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;제한 시간이 1초로 시간초과와의 싸움이였습니다.(넘나 싫은 것,,)&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;실패한 방법은,&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1.&lt;/b&gt; TreeMap을 사용하여 &amp;lt;Integer(가치), 우선 순위 큐&amp;gt; 를 사용하여 보석의 정보를 저장합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2.&lt;/b&gt; 가장 가치가 큰 값을 담을 가장 작은 가방 탐색을 실시합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;&amp;nbsp; &amp;nbsp; &lt;b&gt;2-1.&lt;/b&gt; 가방을 정렬 후 이분탐색을 실시하여 under bound 값을 찾기&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;결과는 시간 초과 였습니다.(&lt;s&gt;logN x logN + logN 맞나?&lt;/s&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;다른 방법을 찾아 시도 하여 성공하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1.&lt;/b&gt; 우선순위 큐에 보석 정보를 담습니다. &amp;lt;int[]&amp;gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; 1-1.&lt;/b&gt; [0]번 인덱스는 M(무게) [1]번 인덱스는 V(가치)가 담기도록 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; 1-2.&lt;/b&gt; 무게는 오름 차순으로 정렬되고, 가치는 내림차순으로 정렬되게 합니다. (가볍고, 비싼거 먼저!)&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2.&lt;/b&gt; 가방 정보를 List에 담습니다. (정리하며 생각해보니 배열도 됩니다 헤헤)&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; 2-1.&lt;/b&gt; 가방을 오름차순으로 정렬합니다. (2, 5, 10, &amp;middot;&amp;middot;&amp;middot; )&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;3.&lt;/b&gt; 가장 작은 가방부터 순회하며 가장 높은 가치의 물건을 담도록 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; 3-1.&lt;/b&gt; 새로운 우선순위 큐 &amp;lt;Integer&amp;gt;를 생성한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; 3-2.&lt;/b&gt; 인자는 V(가치)가 내림차순으로 정렬되게 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;&amp;nbsp; &amp;nbsp; 3-3.&lt;/b&gt; 가장 작은 가방에 들어갈 수 있는 가장 큰 가치의 보석을 하나씩 담는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;※참고: 우선순위 큐의 시간복잡도 IN 자바&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 65.3089%; height: 80px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;&lt;b&gt;시간 복잡도&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;&lt;b&gt;메서드&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;O(log(n))&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;offer, poll, remove, add&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;O(n)&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;remove&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;O(1)&lt;/td&gt;
&lt;td style=&quot;width: 50%; height: 20px;&quot;&gt;peek, element, size&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;882&quot; data-origin-height=&quot;43&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xqJiA/btroSVuitg0/gO1mcZN4O30z4z4MxaS6kk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xqJiA/btroSVuitg0/gO1mcZN4O30z4z4MxaS6kk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xqJiA/btroSVuitg0/gO1mcZN4O30z4z4MxaS6kk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxqJiA%2FbtroSVuitg0%2FgO1mcZN4O30z4z4MxaS6kk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;882&quot; height=&quot;43&quot; data-origin-width=&quot;882&quot; data-origin-height=&quot;43&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;주의 사항&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;total 변수는 &lt;span style=&quot;color: #ee2323; background-color: #f6e199;&quot;&gt;&lt;b&gt;long&lt;/b&gt;&lt;/span&gt;이여야 합니다. 가방 300,000개가 보석 가치 1,000,000을 담게 되면 int의 범위를 초과하게 됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;반례&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 80px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style9&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 20px;&quot;&gt;
&lt;td style=&quot;width: 100%; height: 20px;&quot;&gt;&lt;b&gt;INPUT 1&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 60px;&quot;&gt;
&lt;td style=&quot;width: 100%; height: 60px;&quot;&gt;3&amp;nbsp;2 &lt;br /&gt;5&amp;nbsp;20 &lt;br /&gt;7&amp;nbsp;25 &lt;br /&gt;8&amp;nbsp;50 &lt;br /&gt;5 &lt;br /&gt;5&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style9&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;&lt;b&gt;OUTPUT 1&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;20&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘못된 코드나 내용이 있다면 댓글을 남겨주세요. 즉시 수정하도록 하겠습니다! :)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorithm Solving/BAEKJOON</category>
      <category>1202</category>
      <category>java</category>
      <category>백준</category>
      <category>보석 도둑</category>
      <category>시간초과</category>
      <category>우선 순위 큐</category>
      <category>자바</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/158</guid>
      <comments>https://zangzangs.tistory.com/158#entry158comment</comments>
      <pubDate>Sun, 26 Dec 2021 14:34:03 +0900</pubDate>
    </item>
    <item>
      <title>[백준] 7662 이중 우선순위 큐 #JAVA #이진 탐색 트리</title>
      <link>https://zangzangs.tistory.com/157</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-filename=&quot;알고리즘.png&quot; data-origin-width=&quot;945&quot; data-origin-height=&quot;502&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bNn6wJ/btroRZCMAxv/ZMGc27ZlmLHFnAfGjXWes0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bNn6wJ/btroRZCMAxv/ZMGc27ZlmLHFnAfGjXWes0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bNn6wJ/btroRZCMAxv/ZMGc27ZlmLHFnAfGjXWes0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbNn6wJ%2FbtroRZCMAxv%2FZMGc27ZlmLHFnAfGjXWes0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;945&quot; height=&quot;502&quot; data-filename=&quot;알고리즘.png&quot; data-origin-width=&quot;945&quot; data-origin-height=&quot;502&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;[백준] 7662 이중 우선순위 큐 #JAVA #이진 탐색 트리&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;코드&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;pre id=&quot;code_1613404164341&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Map.Entry;
import java.util.StringTokenizer;
import java.util.TreeMap;

public class Main {

	public static void main(String[] args) throws IOException {

		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringBuilder sb = new StringBuilder();
		StringTokenizer st;

		int T = Integer.parseInt(br.readLine());
		
		for (int t = 0; t &amp;lt; T; t++) {
			int k = Integer.parseInt(br.readLine());

			TreeMap&amp;lt;Integer, Integer&amp;gt; tree = new TreeMap&amp;lt;&amp;gt;();

			for (int i = 0; i &amp;lt; k; i++) {
				st = new StringTokenizer(br.readLine());

				String cmd = st.nextToken();
				int number = Integer.parseInt(st.nextToken());

				if (cmd.equals(&quot;I&quot;)) {
					if(tree.get(number) != null) {
						tree.put(number, tree.get(number)+1);
					}else {
						tree.put(number, 1);
					}
					
				} else if (cmd.equals(&quot;D&quot;)) {
					if (tree.isEmpty())	continue;

					if (number == 1) { // 최댓값 삭제
						Entry&amp;lt;Integer, Integer&amp;gt; entry = tree.pollLastEntry();
						if(entry.getValue() &amp;gt; 1) {
							tree.put(entry.getKey(), entry.getValue()-1);
						}
						
					} else if (number == -1) { // 최솟값 삭제
						Entry&amp;lt;Integer, Integer&amp;gt; entry = tree.pollFirstEntry();
						if(entry.getValue() &amp;gt; 1) {
							tree.put(entry.getKey(), entry.getValue()-1);
						}
					}
				}

			}
			if (tree.isEmpty()) {
				sb.append(&quot;EMPTY&quot;);
			} else {
				int max = tree.lastKey();
				int min = tree.firstKey();
				sb.append(max + &quot; &quot; + min);
			}
			sb.append(&quot;\n&quot;);
		}
		System.out.println(sb.toString());

	}

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;풀이&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제 제목처럼&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;이중 우선순위 큐&lt;/b&gt;라는 자료구조가 있는 줄 알았다. 그런 자료구조는 자바에 존재하지 않았다.(&lt;s&gt;다른 언어는 있을지도?&lt;/s&gt;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 일단&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;우선순위 큐&lt;/b&gt;를 이용해서 풀었다. 하나의 우선순위 큐를 두고 삭제 시 최소인 경우 poll() 메서드를 사용해서 삭제했고, 최대인 경우는 loop문을 통해 마지막 원소를 찾아 삭제 하려고 했다(loop문을 짜는 순간 시간 초과임을 알았다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시간 초과를 해결하기 위해 삭제의 시간복잡도가 O(lonN)인 트리 자료구조를 사용하여 해결하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바에서는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;TreeSet&lt;/b&gt;&lt;/span&gt;&amp;nbsp;과&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #99cefa;&quot;&gt;&lt;b&gt;TreeMap&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;두 가지가 있다. 모두 이진 탐색 트리다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 문제에서는 중복된 수가 입력이 될 수 있으므로&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;TreeSet&lt;/b&gt;&lt;/span&gt;을 사용하지 않고&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #99cefa;&quot;&gt;&lt;b&gt;TreeMap&lt;/b&gt;&lt;/span&gt;을 사용하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;주의 사항&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;같은 수가 입력이 될 수 있다. TreeMap을 사용하여 구현하며 중복된 입력시 &amp;lt;key, value&amp;gt;에서 value의 값이 증가하도록 구현한다.&lt;/li&gt;
&lt;li&gt;삭제 시 value의 값이 1보다 큰 경우 삭제가 아니라, value 값을 -1 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;반례&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style9&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;&lt;b&gt;INPUT&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot; rowspan=&quot;6&quot;&gt;1 &lt;br /&gt;3 &lt;br /&gt;I&amp;nbsp;100 &lt;br /&gt;I&amp;nbsp;100 &lt;br /&gt;D&amp;nbsp;1&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style9&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;&lt;b&gt;OUTPUT&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 100%;&quot;&gt;100 100&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘못된 코드나 내용이 있다면 댓글을 남겨주세요. 즉시 수정하도록 하겠습니다! :)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorithm Solving/BAEKJOON</category>
      <category>7662</category>
      <category>BOJ</category>
      <category>BST</category>
      <category>java</category>
      <category>백준</category>
      <category>이중 우선순위 큐</category>
      <category>자바</category>
      <category>트리</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/157</guid>
      <comments>https://zangzangs.tistory.com/157#entry157comment</comments>
      <pubDate>Fri, 24 Dec 2021 18:15:57 +0900</pubDate>
    </item>
    <item>
      <title>[GoF]스테이트 패턴(State Pattern)</title>
      <link>https://zangzangs.tistory.com/155</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1538&quot; data-origin-height=&quot;336&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/byZ8t9/btrodRMRBn7/ezLIxU6GWSJ6MsCr4b3FR1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/byZ8t9/btrodRMRBn7/ezLIxU6GWSJ6MsCr4b3FR1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/byZ8t9/btrodRMRBn7/ezLIxU6GWSJ6MsCr4b3FR1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbyZ8t9%2FbtrodRMRBn7%2FezLIxU6GWSJ6MsCr4b3FR1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1538&quot; height=&quot;336&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1538&quot; data-origin-height=&quot;336&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;스테이트 패턴(State Pattern)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt;&amp;nbsp;스테이트 패턴이란?&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;클래스가 하나의 상태(state)에 따라 내부의 메서드의 기능이 바뀌는 경우&lt;i&gt;&lt;b&gt;&lt;span style=&quot;color: #666666;&quot;&gt;(같은 기능에서 분기(if-else)발생)&lt;/span&gt;&lt;/b&gt;&lt;/i&gt;한다고 하면 이를 각각의 클래스로 분리하는 패턴이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt; 스테이트 패턴 왜 사용할까?&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;객체의 기능이 어떤 상태에 있느냐에 따라 달라질 수 있는데(ex 자동차의 에코모드, 스포츠모드) 이러한 상태가 여러가지이면 if-else와 같은 분기로 표현이 되어 수정,삭제, 추가시 단점이 발생 할 수 있다. 이 때, 기능이 상태(특정 변수같은)에 의존적이라면 스테이트 패턴을 사용하여 클래스로 표현하는 것이 적절하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;스테이트 패턴을 사용하게 되면&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;상태에 따라 기능을 분리하여 구현&lt;/li&gt;
&lt;li&gt;새로운 상태 추가나 삭제가 용이함&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&amp;nbsp;클래스 다이어그램&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;147&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/WKfOV/btrocTdpSwF/KFfP1g3ukpHiJnhe0qMhwk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/WKfOV/btrocTdpSwF/KFfP1g3ukpHiJnhe0qMhwk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/WKfOV/btrocTdpSwF/KFfP1g3ukpHiJnhe0qMhwk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWKfOV%2FbtrocTdpSwF%2FKFfP1g3ukpHiJnhe0qMhwk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;512&quot; height=&quot;188&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;147&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&amp;nbsp;객체 협력&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;22:1-23:0&quot;&gt;&lt;b&gt;Context&lt;/b&gt; : ConcreteState의 인스턴스를 관리하고 서로 상태가 바뀌는 구간을 구현다&lt;/li&gt;
&lt;li data-sourcepos=&quot;24:1-25:0&quot;&gt;&lt;b&gt;State&lt;/b&gt; : Context 가 사용할 메서드를 선언한다. (&lt;s&gt;추상 클래스or인터페이스 둘다 되겠지&lt;/s&gt;)&lt;/li&gt;
&lt;li data-sourcepos=&quot;26:1-28:0&quot;&gt;&lt;b&gt;ConcreateState&lt;/b&gt; : 각 상태 클래스가 수행할 State에 선언된 메서드를 구현한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&amp;nbsp;코드보기 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;a style=&quot;color: #ee2323;&quot; href=&quot;https://github.com/ZANGZANGS/gof_design_pattern/tree/master#readme&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Click!&lt;/a&gt;&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;a style=&quot;color: #ee2323;&quot; href=&quot;https://github.com/ZANGZANGS/gof_design_pattern/commit/965ad9e1603a76455052986ce0a1bfdd36fe9885&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;GIT COMMIT 링크 열기!&lt;/span&gt;&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignLeft&quot; data-emoticon-type=&quot;friends1&quot; data-emoticon-name=&quot;047&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/friends1/large/047.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/friends1/large/047.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;</description>
      <category>Gof Design Pattern</category>
      <category>Gof</category>
      <category>state</category>
      <category>디자인패턴</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/155</guid>
      <comments>https://zangzangs.tistory.com/155#entry155comment</comments>
      <pubDate>Mon, 20 Dec 2021 21:12:41 +0900</pubDate>
    </item>
    <item>
      <title>[GoF] 어댑터패턴(Adapter Pattern)</title>
      <link>https://zangzangs.tistory.com/154</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1538&quot; data-origin-height=&quot;336&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/n8fj7/btrodSRTxh0/vXgzdSNOJXn9vnCHvt8u9K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/n8fj7/btrodSRTxh0/vXgzdSNOJXn9vnCHvt8u9K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/n8fj7/btrodSRTxh0/vXgzdSNOJXn9vnCHvt8u9K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fn8fj7%2FbtrodSRTxh0%2FvXgzdSNOJXn9vnCHvt8u9K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1538&quot; height=&quot;336&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1538&quot; data-origin-height=&quot;336&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;어댑터 패턴(Adapter Pattern)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt;&amp;nbsp;어댑터 패턴이란?&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;서로 다른 인터페이스를 중간에서 연결해주기 위해 사용하는 패턴입니다. 이미 사용중이거나 정의된 인터페이스들을 중간에서 맞춰서 적용해 줄 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt; 어댑터 패턴 왜 사용할까?&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;클라이언트에서 사용하던 방식대로 호출하여 사용할 수 있도록 조정이 가능합니다. 서로 일치하지 않는 인터페이스를 변경하지 않고 중간에서 호출하여 사용할 수 있도록 제공합니다. 일종의 wrapper와 유사합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;어댑터 패턴을 사용하게 되면&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;52:1-53:0&quot;&gt;Adpter 패턴을 사용하여 클라이언트가 사용하는 방식은 동일하면서 여러 기능이 제공될 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&amp;nbsp;클래스 다이어그램&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1) 객체 어댑터 (상속)&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;425&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b2FHST/btrobTRZRib/sYq03arWnW8vGZvtJdObck/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b2FHST/btrobTRZRib/sYq03arWnW8vGZvtJdObck/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b2FHST/btrobTRZRib/sYq03arWnW8vGZvtJdObck/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb2FHST%2FbtrobTRZRib%2FsYq03arWnW8vGZvtJdObck%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1024&quot; height=&quot;425&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;425&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2) 클래스 어댑터 (합성)&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;387&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cMzsPg/btrocSY8EzC/q8FIw02oInW1AMDae0VyCk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cMzsPg/btrocSY8EzC/q8FIw02oInW1AMDae0VyCk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cMzsPg/btrocSY8EzC/q8FIw02oInW1AMDae0VyCk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcMzsPg%2FbtrocSY8EzC%2Fq8FIw02oInW1AMDae0VyCk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1024&quot; height=&quot;387&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;387&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&amp;nbsp;객체 협력&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;41:1-42:0&quot;&gt;&lt;b&gt;Target&lt;/b&gt; : 클라이언트가 사용할 인터페이스를 정의&lt;/li&gt;
&lt;li data-sourcepos=&quot;43:1-44:0&quot;&gt;&lt;b&gt;Client&lt;/b&gt; : Target 인터페이스를 사용하는 객체&lt;/li&gt;
&lt;li data-sourcepos=&quot;45:1-46:0&quot;&gt;&lt;b&gt;Adaptee&lt;/b&gt; : 실제 적용될 기능이 제공되는 클래스&lt;/li&gt;
&lt;li data-sourcepos=&quot;47:1-49:0&quot;&gt;&lt;b&gt;Adapter&lt;/b&gt; : Target 인터페이스에 Adaptee의 인터페이스를 맞추는 클래스&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&amp;nbsp;코드보기 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;a style=&quot;color: #ee2323;&quot; href=&quot;https://github.com/ZANGZANGS/gof_design_pattern/tree/master#readme&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Click!&lt;/a&gt;&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;a style=&quot;color: #ee2323;&quot; href=&quot;https://github.com/ZANGZANGS/gof_design_pattern/commit/4b4967bd4407e39105e08b91325c0b11f7e63812&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;GIT COMMIT 링크 열기!&lt;/span&gt;&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignLeft&quot; data-emoticon-type=&quot;friends1&quot; data-emoticon-name=&quot;047&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/friends1/large/047.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/friends1/large/047.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;</description>
      <category>Gof Design Pattern</category>
      <category>Adapter</category>
      <category>Gof</category>
      <category>디자인패턴</category>
      <category>어댑터</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/154</guid>
      <comments>https://zangzangs.tistory.com/154#entry154comment</comments>
      <pubDate>Sun, 19 Dec 2021 21:21:06 +0900</pubDate>
    </item>
    <item>
      <title>[GoF]컴포지트 패턴(Composite Pattern)</title>
      <link>https://zangzangs.tistory.com/153</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1538&quot; data-origin-height=&quot;336&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cf8Qea/btrob1ISZMK/M2g7OBiEPG5MkOockragZ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cf8Qea/btrob1ISZMK/M2g7OBiEPG5MkOockragZ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cf8Qea/btrob1ISZMK/M2g7OBiEPG5MkOockragZ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcf8Qea%2Fbtrob1ISZMK%2FM2g7OBiEPG5MkOockragZ1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1538&quot; height=&quot;336&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1538&quot; data-origin-height=&quot;336&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;컴포지트 패턴(Composite Pattern)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt;&amp;nbsp;컴포지트 패턴이란?&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;그릇과 내용물을 동일시 하는 패턴으로 하나 이상의 유사한 객체를 구성으로 설계된 객체로 모두 유사한 기능을 나타낸다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt; 컴포지트 패턴 왜 사용할까?&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;부분과 전체에 대한 복합 객체의 트리구조를 나타낼 수가 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;클라이언트가 개별 객체와 복합 객체를 동일하게 다룰 수 있는 인터페이스를 제공합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;재귀적인 구조입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;컴포지트 패턴을 사용하게 되면&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;50:1-51:0&quot;&gt;기본 객체는 복합 객체에 포함이 되고, 복합 객체 역시 또 다른 복합 객체에 포함될 수 있다.&lt;/li&gt;
&lt;li data-sourcepos=&quot;52:1-53:0&quot;&gt;클라이언트 코드는 기본객체와 복합객체에 대한 일관된 프로그래밍을 할 수 있다.&lt;/li&gt;
&lt;li data-sourcepos=&quot;54:1-55:0&quot;&gt;기본 객체가 증가하여도 전체 객체의 코드에 영향을 주지 않는다.&lt;/li&gt;
&lt;li data-sourcepos=&quot;56:1-57:0&quot;&gt;새로운 요소의 추가가 편리하고 범용성 있는 설계가 가능하다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&amp;nbsp;클래스 다이어그램&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;900&quot; data-origin-height=&quot;546&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HDMdC/btrocq2AAES/cDlBJEsnHK0yKnjNQ1fHMk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HDMdC/btrocq2AAES/cDlBJEsnHK0yKnjNQ1fHMk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HDMdC/btrocq2AAES/cDlBJEsnHK0yKnjNQ1fHMk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHDMdC%2Fbtrocq2AAES%2FcDlBJEsnHK0yKnjNQ1fHMk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;900&quot; height=&quot;546&quot; data-origin-width=&quot;900&quot; data-origin-height=&quot;546&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&amp;nbsp;객체 협력&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;26:1-33:0&quot;&gt;&lt;b&gt;Component&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;26:1-33:0&quot;&gt;전체와 부분 객체에서 공통으로 사용할 기능 구현&lt;/li&gt;
&lt;li data-sourcepos=&quot;26:1-33:0&quot;&gt;전체 클래스가 부분요소들을 관리하기 위해 필요한 인터페이스 선언&lt;/li&gt;
&lt;li data-sourcepos=&quot;26:1-33:0&quot;&gt;전체와 부분 객체에서 공통적으로 사용할 인터페이스 선언&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-sourcepos=&quot;34:1-37:0&quot;&gt;&lt;b&gt;Leaf&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;34:1-37:0&quot;&gt;집합 관계에서 다른 객체를 포함할 수는 없고 포함되기만 하는 객체로 가장 기본이 되는 기능을 구현&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-sourcepos=&quot;34:1-37:0&quot;&gt;&lt;b&gt;Composite&lt;/b&gt;&amp;nbsp;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;34:1-37:0&quot;&gt;포함한 여러 객체를 저장하고 관리하는 기능을 구현&lt;/li&gt;
&lt;li data-sourcepos=&quot;34:1-37:0&quot;&gt;여러 객체를 포함하는 복합 객체에 대한 기능 구현&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li data-sourcepos=&quot;44:1-47:0&quot;&gt;&lt;b&gt;Client&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;44:1-47:0&quot;&gt;Component에 선언된 인터페이스를 통하여 부분과 전체를 동일하게 처리&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&amp;nbsp;코드보기 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;a style=&quot;color: #ee2323;&quot; href=&quot;https://github.com/ZANGZANGS/gof_design_pattern/tree/master#readme&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Click!&lt;/a&gt;&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;a style=&quot;color: #ee2323;&quot; href=&quot;https://github.com/ZANGZANGS/gof_design_pattern/commit/c0f1966298d641b8441c780f911089d7096d0332&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;GIT COMMIT 링크 열기!&lt;/span&gt;&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignLeft&quot; data-emoticon-type=&quot;friends1&quot; data-emoticon-name=&quot;047&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/friends1/large/047.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/friends1/large/047.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;</description>
      <category>Gof Design Pattern</category>
      <category>Composite</category>
      <category>Gof</category>
      <category>디자인패턴</category>
      <category>컴포지트</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/153</guid>
      <comments>https://zangzangs.tistory.com/153#entry153comment</comments>
      <pubDate>Sat, 18 Dec 2021 19:09:41 +0900</pubDate>
    </item>
    <item>
      <title>[백준] 3190 뱀 #JAVA #시뮬레이션</title>
      <link>https://zangzangs.tistory.com/152</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-filename=&quot;알고리즘.png&quot; data-origin-width=&quot;945&quot; data-origin-height=&quot;502&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/t2CgV/btrn6xV8CQL/J2J2SnjKwtQsdkEwvQIr50/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/t2CgV/btrn6xV8CQL/J2J2SnjKwtQsdkEwvQIr50/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/t2CgV/btrn6xV8CQL/J2J2SnjKwtQsdkEwvQIr50/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Ft2CgV%2Fbtrn6xV8CQL%2FJ2J2SnjKwtQsdkEwvQIr50%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;945&quot; height=&quot;502&quot; data-filename=&quot;알고리즘.png&quot; data-origin-width=&quot;945&quot; data-origin-height=&quot;502&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;[백준] 3190 뱀 #JAVA #시뮬레이션&lt;/h2&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;코드&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;pre id=&quot;code_1613404164341&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.io.*;
import java.util.*;
public class Main {

	public static void main(String[] args) throws IOException{

		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		int N = Integer.parseInt(br.readLine());//보드 크기
		int K = Integer.parseInt(br.readLine());//사과 개수
		
		int[][] board = new int[N][N];
		
		StringTokenizer st;
		
		for (int i = 0; i &amp;lt; K; i++) { //사과 자리
			st = new StringTokenizer(br.readLine());
			int y = Integer.parseInt(st.nextToken());
			int x = Integer.parseInt(st.nextToken());
			
			board[y-1][x-1] = 1;
			
		}
		
		Deque&amp;lt;int[]&amp;gt; snake = new LinkedList&amp;lt;&amp;gt;();
		snake.addFirst(new int[] {0,0});
		int snakeHead = 0; //0동 1남 2서 3북
		
		int L = Integer.parseInt(br.readLine());//방향 전환
		int[] dir = new int[10001];
		
		for (int i = 0; i &amp;lt; L; i++) {
			st = new StringTokenizer(br.readLine());
			int sec = Integer.parseInt(st.nextToken());
			String d = st.nextToken();
			
			if(d.equals(&quot;L&quot;)) dir[sec] = -1;
			else if(d.equals(&quot;D&quot;)) dir[sec] = 1;
			
		}
		
		int second = 0;
		while (true) {
			second++;
			
			int[] head =snake.peekFirst();
			
			int ny = head[0];
			int nx = head[1];
			if(snakeHead == 0) {//동
				nx += 1;
			} else if(snakeHead == 1) {//남
				ny += 1;
			} else if(snakeHead == 2) {//서
				nx -= 1; 
			} else if(snakeHead == 3) {//북
				ny -= 1;
			}
			
			//벽 부딪힘 check
			if(nx&amp;lt;0 || ny&amp;lt;0 || nx &amp;gt;=N || ny&amp;gt;=N) break;
			
			//몸통 부딪힘 check
			Iterator&amp;lt;int[]&amp;gt; iter= snake.iterator();
			boolean isBody = false;
			while (iter.hasNext()) {
				int[] tmp = iter.next();
				if(ny == tmp[0] &amp;amp;&amp;amp; nx == tmp[1]) {
					isBody = true;
					break;
				}
			}
			if(isBody)break;
			

			snake.addFirst(new int[] {ny,nx});//머리 이동
			if(board[ny][nx] == 1) {
				board[ny][nx] = 0; //사과 삭제
			}else {
				snake.removeLast();//사과 안먹었으면 꼬리 이동
			}			
			
			if(dir[second] != 0) {
				snakeHead += dir[second];
				if(snakeHead&amp;lt;0) snakeHead += 4;
				snakeHead %= 4;
			}
			
		}
		
		System.out.println(second);
	}

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;풀이&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Dequeue에 뱀의 좌표를 머리 ~ 꼬리 순으로 넣는다.&lt;/li&gt;
&lt;li&gt;뱀의 머리가 4방향중 어디인지 정의한다.&lt;/li&gt;
&lt;li&gt;이동할 떄마다 배열 범위를 벗어나는지 체크하고, 뱀 몸통에 부딪히는지 체크한다.&lt;/li&gt;
&lt;li&gt;뱀이 사과를 먹으면 몸이 길어지고, 사과는 삭제한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;주의 사항&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;뱀의 머리가 범위를 벗어나는 것을 체크해야 한다. (0~3 범위)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;뱀이 사과를 먹고나서 사과를 삭제해야한다.&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;반례&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 반례가 되지 않는다면 사과처리에 대해 다시 확인해 본다.&lt;/p&gt;
&lt;pre id=&quot;code_1637234841909&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#INPUT
35
28
21 2
22 23
3 5
34 30
29 31
3 28
20 12
27 26
31 7
5 10
21 10
19 2
15 23
4 23
3 19
3 35
13 30
30 30
23 27
32 17
22 24
8 27
4 8
30 18
15 28
22 29
28 5
16 33
20
27 D
61 L
68 L
100 L
133 L
160 L
165 D
168 D
170 D
182 D
206 D
207 D
214 D
215 D
216 L
237 D
240 D
241 L
251 D
252 D

#OUTPUT
237&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘못된 코드나 내용이 있다면 댓글을 남겨주세요. 즉시 수정하도록 하겠습니다! :)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorithm Solving/BAEKJOON</category>
      <category>3190</category>
      <category>java</category>
      <category>백준</category>
      <category>뱀</category>
      <category>자바</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/152</guid>
      <comments>https://zangzangs.tistory.com/152#entry152comment</comments>
      <pubDate>Fri, 17 Dec 2021 13:33:42 +0900</pubDate>
    </item>
    <item>
      <title>[GoF]데코레이터 패턴(Decorator Pattern)</title>
      <link>https://zangzangs.tistory.com/151</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1538&quot; data-origin-height=&quot;336&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cEfBZc/btrn836T7je/LzRI8aNGsW8Oc6EVH0Mq31/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cEfBZc/btrn836T7je/LzRI8aNGsW8Oc6EVH0Mq31/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cEfBZc/btrn836T7je/LzRI8aNGsW8Oc6EVH0Mq31/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcEfBZc%2Fbtrn836T7je%2FLzRI8aNGsW8Oc6EVH0Mq31%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1538&quot; height=&quot;336&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1538&quot; data-origin-height=&quot;336&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;데코레이터 패턴(Decorator&amp;nbsp;Pattern)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt; 데코레이터 패턴이란?&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;데코레이터 패턴은 장식과&amp;nbsp;실제&amp;nbsp;내용물을&amp;nbsp;동일시&amp;nbsp;하는&amp;nbsp;패턴으로&amp;nbsp;생성된&amp;nbsp;객체에&amp;nbsp;동적으로&amp;nbsp;행위를&amp;nbsp;추가하는&amp;nbsp;패턴입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;※자바의 I/O 스트림 클래스는 Decorator 패턴을 사용한 것입니다.&lt;/p&gt;
&lt;pre id=&quot;code_1639661673722&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Socket socket = new Socket();
BufferedReader br = new BufferedReader(new InputStreamReader(socket.getInputStream()));&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt; 데코레이터 패턴 왜 사용할까?&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;기능을 확장할 때 IS-A 관계라면 상속을 사용하게 됩니다. 그러나 HAS-A 관계라면 상속을 사용하기 모호한 상황이게 됩니다. 무언가 기능을 유연하게 추가하고자 할때 데코레이터 패턴을 사용하여 기능을 확장할 수 있습니다. 즉, 전체 객체를 바꾸는 게 아니라 객체에 새로운 기능을 하나씩 추가할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;데코레이터 패턴을 사용하게 되면&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;상속보다 설계의 유연성을 증가시킴&lt;/li&gt;
&lt;li&gt;Decorator 조합을 통해 새로운 서비스를 지속적으로 추가 할 수 있음&lt;/li&gt;
&lt;li&gt;불필요한 경우 Decorator 삭제가 가능함&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;Decorator와 실제 컴포넌트는 동일한 것이 아님&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;작은 규모의 객체들이 많이 생성될 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&amp;nbsp;클래스 다이어그램&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1661&quot; data-origin-height=&quot;987&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oamSF/btrn6yfHTiM/BrxMLiL4lg9dZNqOMUI13k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oamSF/btrn6yfHTiM/BrxMLiL4lg9dZNqOMUI13k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oamSF/btrn6yfHTiM/BrxMLiL4lg9dZNqOMUI13k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoamSF%2Fbtrn6yfHTiM%2FBrxMLiL4lg9dZNqOMUI13k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1661&quot; height=&quot;987&quot; data-origin-width=&quot;1661&quot; data-origin-height=&quot;987&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&amp;nbsp;객체 협력&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;26:1-27:0&quot;&gt;&lt;b&gt;Component&lt;/b&gt; : 동적으로 추가할 서비스를 가질 수 있는 객체 정의&lt;/li&gt;
&lt;li data-sourcepos=&quot;28:1-29:0&quot;&gt;&lt;b&gt;ConcreteComponent&lt;/b&gt; : 추가적인 서비스가 필요한 실제 객체&lt;/li&gt;
&lt;li data-sourcepos=&quot;30:1-31:0&quot;&gt;&lt;b&gt;Decorator&lt;/b&gt; : Component의 참조자를 관리하면서 Component에 정의된 인터페이스를 만족하도록 정의&lt;/li&gt;
&lt;li data-sourcepos=&quot;32:1-34:0&quot;&gt;&lt;b&gt;ConcreteDecorator&lt;/b&gt; : 새롭게 추가되는 서비스를 실제 구현한 클래스로 &lt;i&gt;addBehavior()&lt;/i&gt;를 구현&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&amp;nbsp;코드보기 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;a style=&quot;color: #ee2323;&quot; href=&quot;https://github.com/ZANGZANGS/gof_design_pattern/tree/master#readme&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Click!&lt;/a&gt;&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;a style=&quot;color: #ee2323;&quot; href=&quot;https://github.com/ZANGZANGS/gof_design_pattern/commit/a3a97ba979c6fe790f3b61e79009c47822344bda&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;GIT COMMIT 링크 열기!&lt;/span&gt;&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignLeft&quot; data-emoticon-type=&quot;friends1&quot; data-emoticon-name=&quot;047&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/friends1/large/047.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/friends1/large/047.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;</description>
      <category>Gof Design Pattern</category>
      <category>decorator</category>
      <category>Gof</category>
      <category>데코레이터</category>
      <category>디자인패턴</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/151</guid>
      <comments>https://zangzangs.tistory.com/151#entry151comment</comments>
      <pubDate>Thu, 16 Dec 2021 22:38:08 +0900</pubDate>
    </item>
    <item>
      <title>[GoF]브릿지 패턴(Bridge Pattern)</title>
      <link>https://zangzangs.tistory.com/150</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1538&quot; data-origin-height=&quot;336&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cx2T6A/btrndHMeUM1/A5HYU7aQuimzMYHaK7DxE1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cx2T6A/btrndHMeUM1/A5HYU7aQuimzMYHaK7DxE1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cx2T6A/btrndHMeUM1/A5HYU7aQuimzMYHaK7DxE1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcx2T6A%2FbtrndHMeUM1%2FA5HYU7aQuimzMYHaK7DxE1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1538&quot; height=&quot;336&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1538&quot; data-origin-height=&quot;336&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;브릿지 패턴(Bridge Pattern)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt;&amp;nbsp;브릿지 패턴이란?&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;기능의 계층과 구현의 계층을 분리하는 패턴입니다. 추상화와 구현을 분리하여 각각을 독립적으로 변경할 수 있게 합니다. 두 계층을 연결하는 다리(Bridge)를 통해 연결됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt; 브릿지 패턴 왜 사용할까?&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;기능의 확장과 구현의 확장을 따로 계층화 하는 것이 목적입니다. 따라서 기능에 대한 여러가지 구현을 다양하게 적용할 수 있습니다. 기능과 구현이 혼재하면 상속의 관계가 복잡하게 섞이게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;브릿지 패턴을 사용하게 되면&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&amp;nbsp;기능과 구현의 결합도가 약하기 떄문에 기능이 구현 방식에 얽매이지 않는다.&lt;/li&gt;
&lt;li&gt;기능의 구현 클래스를 런타임 때 지정이 가능합니다.&lt;/li&gt;
&lt;li&gt;구현이 변경되더라도 기능 클래스 부분에 대한 컴파일은 필요 없습니다.&lt;/li&gt;
&lt;li&gt;기능과 구현은 독립적으로 확장되며, 클라이언트는 기능의 인터페이스를 사용하므로 구체적인 구현 내용은 숨길 수가 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&amp;nbsp;클래스 다이어그램&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;750&quot; data-origin-height=&quot;375&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bHFuGh/btrndnUJxQp/J1cWaKvFDbzJYZCVhYIKqK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bHFuGh/btrndnUJxQp/J1cWaKvFDbzJYZCVhYIKqK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bHFuGh/btrndnUJxQp/J1cWaKvFDbzJYZCVhYIKqK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbHFuGh%2FbtrndnUJxQp%2FJ1cWaKvFDbzJYZCVhYIKqK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;750&quot; height=&quot;375&quot; data-origin-width=&quot;750&quot; data-origin-height=&quot;375&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&amp;nbsp;객체 협력&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;28:1-31:0&quot;&gt;&lt;b&gt;Abstraction&lt;/b&gt; : 추상화 개념의 상위 클래스이고 객체 구현자(Implemntor)에 대한 참조자를 관리&lt;/li&gt;
&lt;li data-sourcepos=&quot;32:1-35:0&quot;&gt;&lt;b&gt;RefinedAbstraction &lt;/b&gt;: 추상화 개념의 확장된 기능을 정의&lt;/li&gt;
&lt;li data-sourcepos=&quot;36:1-43:0&quot;&gt;&lt;b&gt;Implementor &lt;/b&gt;: Abstraction에 대한 선언을 제공하며, 하위 클래스가 구현해야 하는 기능들을 선언한다&lt;/li&gt;
&lt;li data-sourcepos=&quot;44:1-47:0&quot;&gt;&lt;b&gt;ConcreteImplementor&lt;/b&gt; : Implementor에 선언된 기능을 구현합니다. 여러가지 방식이 나올 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&amp;nbsp;코드보기 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;a style=&quot;color: #ee2323;&quot; href=&quot;https://github.com/ZANGZANGS/gof_design_pattern/tree/master#readme&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Click!&lt;/a&gt;&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;a style=&quot;color: #ee2323;&quot; href=&quot;https://github.com/ZANGZANGS/gof_design_pattern/commit/d9796a8b43c34c24448998e138c5f48c75f6d2a8&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;GIT COMMIT 링크 열기!&lt;/span&gt;&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignLeft&quot; data-emoticon-type=&quot;friends1&quot; data-emoticon-name=&quot;047&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/friends1/large/047.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/friends1/large/047.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;</description>
      <category>Gof Design Pattern</category>
      <category>Bridge</category>
      <category>Gof</category>
      <category>디자인패턴</category>
      <category>브릿지패턴</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/150</guid>
      <comments>https://zangzangs.tistory.com/150#entry150comment</comments>
      <pubDate>Mon, 13 Dec 2021 19:28:10 +0900</pubDate>
    </item>
    <item>
      <title>인텔리제이에 spring-boot-devtools 추가하기</title>
      <link>https://zangzangs.tistory.com/149</link>
      <description>&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;인텔리제이에 spring-boot-devtools 추가하기&lt;/b&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;안녕하세요? 장장스입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;intellij에서 spring-boot-devtools를&amp;nbsp; 추가하는 방법입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;spring-boot-devtools &lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;STEP_1&lt;/b&gt;&lt;/span&gt; build.gradle 파일에 spring-boot-devtools 의존성을 추가합니다.&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;runtimeOnly('org.springframework.boot:spring-boot-devtools')&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1638805122669&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;dependencies {
	implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
	implementation 'org.springframework.boot:spring-boot-starter-web'
	testImplementation 'org.springframework.boot:spring-boot-starter-test'
	runtimeOnly('org.springframework.boot:spring-boot-devtools')
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;STEP_2&lt;/b&gt;&lt;/span&gt; &lt;b&gt;File -&amp;gt; settings&lt;/b&gt; 에서 &lt;b&gt;Compiler&lt;/b&gt;를 검색합니다. &lt;b&gt;Build project automatically&lt;/b&gt; 옵션을 활성화 합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;902&quot; data-origin-height=&quot;703&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Y0GIi/btrnfBcqFu2/tdyGxUxjftPNn1kGFt8MW0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Y0GIi/btrnfBcqFu2/tdyGxUxjftPNn1kGFt8MW0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Y0GIi/btrnfBcqFu2/tdyGxUxjftPNn1kGFt8MW0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FY0GIi%2FbtrnfBcqFu2%2FtdyGxUxjftPNn1kGFt8MW0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;902&quot; height=&quot;703&quot; data-origin-width=&quot;902&quot; data-origin-height=&quot;703&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;STEP_3&lt;/b&gt;&lt;/span&gt; &lt;b&gt;File -&amp;gt; settings&lt;/b&gt; 에서 &lt;b&gt;Advanced Settings&lt;/b&gt;를 검색합니다. &lt;b&gt;Allow auto-make to start even if developed application is currently running&lt;/b&gt;&amp;nbsp;옵션을 활성화 합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;903&quot; data-origin-height=&quot;700&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BQIxc/btrnc3OuX9S/MnEMMfQMWyDcz87Ncjo0J1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BQIxc/btrnc3OuX9S/MnEMMfQMWyDcz87Ncjo0J1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BQIxc/btrnc3OuX9S/MnEMMfQMWyDcz87Ncjo0J1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBQIxc%2Fbtrnc3OuX9S%2FMnEMMfQMWyDcz87Ncjo0J1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;903&quot; height=&quot;700&quot; data-origin-width=&quot;903&quot; data-origin-height=&quot;700&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;※ 최신 인텔리제이는 Regisrty에서 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;compiler.automake.allow.when.app.running&lt;/span&gt;&lt;/b&gt;&amp;nbsp;설정이 검색되지 않습니다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;다른 방법도 있어요! 수동으로&amp;nbsp;리컴파일(Recompile)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;STEP2, 3 을 하지 않아도 수동으로 빌드 할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;html 파일을 수정한 후 &lt;b&gt;Build&lt;/b&gt;탭을 확인해 보면 아래 사진과 같이 해당 파일의 Recompile이 활성화 됩니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;285&quot; data-origin-height=&quot;161&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BFDpw/btrqmOmHKnh/dF9myTFOK9p1BJvxve6kD1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BFDpw/btrqmOmHKnh/dF9myTFOK9p1BJvxve6kD1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BFDpw/btrqmOmHKnh/dF9myTFOK9p1BJvxve6kD1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBFDpw%2FbtrqmOmHKnh%2FdF9myTFOK9p1BJvxve6kD1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;285&quot; height=&quot;161&quot; data-origin-width=&quot;285&quot; data-origin-height=&quot;161&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;position: absolute;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클릭하고 확인하면 정상적으로 반영이 됨을 확인 할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignCenter&quot; data-emoticon-type=&quot;niniz&quot; data-emoticon-name=&quot;012&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘못된 코드나 내용이 있다면 댓글을 남겨주세요. 즉시 수정하도록 하겠습니다! :)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Spring Boot</category>
      <category>Allow auto-make to start even if developed application is currently running</category>
      <category>compiler.automake.allow.when.app.running</category>
      <category>intellij</category>
      <category>spring-boot-devtools</category>
      <category>인텔리제이</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/149</guid>
      <comments>https://zangzangs.tistory.com/149#entry149comment</comments>
      <pubDate>Sat, 11 Dec 2021 01:58:30 +0900</pubDate>
    </item>
    <item>
      <title>[GoF]전략 패턴(Strategy)</title>
      <link>https://zangzangs.tistory.com/148</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1538&quot; data-origin-height=&quot;336&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bA9pND/btrnbIi1sBR/OmsP30GcCUUa6K8nIhydLK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bA9pND/btrnbIi1sBR/OmsP30GcCUUa6K8nIhydLK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bA9pND/btrnbIi1sBR/OmsP30GcCUUa6K8nIhydLK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbA9pND%2FbtrnbIi1sBR%2FOmsP30GcCUUa6K8nIhydLK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1538&quot; height=&quot;336&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1538&quot; data-origin-height=&quot;336&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;전략 패턴(Strategy)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt;&amp;nbsp;전략 패턴이란?&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;상황에 따라 전략이나 알고리즘을 교체하여 사용하는 패턴이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&amp;nbsp;전략 왜 사용할까?&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;다양한 알고리즘(혹은 기능)이 존재할 때, 하나의 클래스로 캡슐화 하여 대체가 가능하도록 할 수 있습니다. 새로운 전략을 반영하거나 기존 전략을 삭제할 때 독립적으로 수행되기에 서로 영향을 끼치지 않습니다. 예를 들어 if-else로 같은 내용이 반복적으로 사용되는 경우 전략 패턴 사용을 고려할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;전략 패턴을 사용하게 되면&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;인터페이스에 선언된 기능을 구현한 다양한 정책을 다른 클래스에 영향을 주지 않고 추가, 삭제 할 수 있다.&lt;/li&gt;
&lt;li&gt;if-else 조건문을 구현하는 것이 아닌 전략 패턴을 사용하여 클래스를 선택하도록 구현하여 유지보수가 용이해진다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&amp;nbsp;클래스 다이어그램&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;736&quot; data-origin-height=&quot;294&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OnAvG/btrndrVguaj/gM8NSrMXdwbKzVB8gKh69k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OnAvG/btrndrVguaj/gM8NSrMXdwbKzVB8gKh69k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OnAvG/btrndrVguaj/gM8NSrMXdwbKzVB8gKh69k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOnAvG%2FbtrndrVguaj%2FgM8NSrMXdwbKzVB8gKh69k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;736&quot; height=&quot;294&quot; data-origin-width=&quot;736&quot; data-origin-height=&quot;294&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&amp;nbsp;객체 협력&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;25:1-28:0&quot;&gt;&lt;b&gt;Strategy&lt;/b&gt; :정책이 수행해야 하는 기능들을 인터페이스로 선언&lt;/li&gt;
&lt;li data-sourcepos=&quot;29:1-34:0&quot;&gt;&lt;b&gt;ConcreteStrategy&lt;/b&gt; : Strategy에 선언된 여러 기능들을 구현한다. 각 클래스 별로 다른 전략이 구현될 수 있다.&lt;/li&gt;
&lt;li data-sourcepos=&quot;35:1-42:0&quot;&gt;&lt;b&gt;Context&lt;/b&gt; : 어떤 ConcreteStrategy 가 수행 될 것인지에 따라 정책을 선택후 Strategy에 선언된 메서드를 사용해 접근한다&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&amp;nbsp;코드보기 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;a style=&quot;color: #ee2323;&quot; href=&quot;https://github.com/ZANGZANGS/gof_design_pattern/tree/master#readme&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Click!&lt;/a&gt;&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;a style=&quot;color: #ee2323;&quot; href=&quot;https://github.com/ZANGZANGS/gof_design_pattern/commit/147eebdb5cf1f30a3e3dd890438ab59fcf9b095c&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;GIT COMMIT 링크 열기!&lt;/span&gt;&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignLeft&quot; data-emoticon-type=&quot;friends1&quot; data-emoticon-name=&quot;047&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/friends1/large/047.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/friends1/large/047.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;</description>
      <category>Gof Design Pattern</category>
      <category>Gof</category>
      <category>Strategy</category>
      <category>디자인패턴</category>
      <category>전략</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/148</guid>
      <comments>https://zangzangs.tistory.com/148#entry148comment</comments>
      <pubDate>Fri, 10 Dec 2021 16:38:18 +0900</pubDate>
    </item>
    <item>
      <title>[OS] 스레싱(thrashing)</title>
      <link>https://zangzangs.tistory.com/144</link>
      <description>&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;스레싱(thrashing)&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;안녕하세요? 장장스입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;프로세스가 원활하게 수행되기 위해서는 일정 수준 이상의 페이지 프레임을 물리적 메모리에 할당 받아야 합니다. 프로세스가 동작하는데 필요한 최소한의 페이지 프레임을 받지 못한다면 성능에 문제가 발생할 수 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;스레싱(thrashing)&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;프로세스가 집중적으로 사용하는 페이지들의 집합이 메모리에 한꺼번에 적재되지 못하여 페이지 부재율(page fault)가 많이 발생하게 되고 CPU 이용율이 급격히 떨어지는 현상&lt;/b&gt;&lt;/span&gt;을 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;스레싱&lt;/b&gt;&lt;/span&gt;이라고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;CPU 이용율이 낮다는 것은 메모리에 올라와 있는 프로세스의 수가 너무 적어 프로세스가 모두 I/O작업을 함으로써 준비 큐가 비는 경우가 발생했다는 것입니다. 따라서 CPU 이용율이 낮으면 운영체제는 메모리에 올라가는 프로세스의 수를 늘리게 됩니다. 우리는 &lt;b&gt;메모리에 동시에 올라가 있는 프로세스의 수&lt;/b&gt;를 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;다중 프로그래밍의 정도(MPD: Multi-Programming Degree)&lt;/b&gt;&lt;/span&gt; 라고 부릅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;스레싱은 어떻게 발생하는 걸까?&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;862&quot; data-origin-height=&quot;532&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VsWVK/btrmKZk8Pwo/8zHt8LEjKaQZebHTFGD3f1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VsWVK/btrmKZk8Pwo/8zHt8LEjKaQZebHTFGD3f1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VsWVK/btrmKZk8Pwo/8zHt8LEjKaQZebHTFGD3f1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVsWVK%2FbtrmKZk8Pwo%2F8zHt8LEjKaQZebHTFGD3f1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;702&quot; height=&quot;433&quot; data-origin-width=&quot;862&quot; data-origin-height=&quot;532&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;운영체제는 CPU 이용률이 낮으면 MPD를 높입니다. 그러나 과도하게 MPD가 높아지면 프로세스에게 할당되는 메모리의 양이 감소하게 될 것입니다. 프로세스가 원활하게 수행하려면 필요한 최소한의 페이지 프레임들이 있습니다.&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;그러면 각 프로세스는 수행에 필요한 최소한의 페이지 프레임도 할당 받지 못하게 되어 페이지 부재가 빈번히 발생하게 될 것입니다. 페이지 부재가 발생하면 스왑 영역에서 해당 페이지를 메모리로 가져오기 위해 디스크 I/O 작업이 발생하고 문맥 교환을 통해 다른 프로세스에게 CPU가 이양 됩니다. &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;font-family: AppleSDGothicNeo-Regular, 'Malgun Gothic', '맑은 고딕', dotum, 돋움, sans-serif;&quot;&gt;이 때 다른 프로세스 역시 할당 받은 메모리 양이 지나치게 적으면 페이지 부재가 발생할 수밖에 없게 됩니다. 그러면 또 다른 프로세스에게 CPU가 할당된다. 결국에는 준비 큐에 있는 모든 프로세스에게 CPU가 한 차례씩 할당되었는데도 모든 프로세스가 다 페이지 부재를 발생시켜 시스템은 페이지 부재를 처리하느라 매우 분주해지고 CPU 이용률은 급격히 떨어지게 된다. 이 상황에서 운영체제는 메모리에 올라와 있는 프로세스의 수가 적어 이러한 현상이 발생했다고 판단하고, MPD를 높이기 위해 또 다른&amp;nbsp; 프로세스를 메모리에 추가하게 된다. 이로 인해 프로세스당 할당된 프레임의 수가 더욱 감소하고 페이지 부재는 더욱 빈번히 발생하게 된다. 이 경우 프로세스들은 서로의 페이지를 교체하며 스왑 인(swap in)과 스왑 아웃(swap out)을 지속적으로 발생시키고, CPU는 대부분의 시간에 일을 하지 않게 됩니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;스레싱 발생 방지 알고리즘&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;MPD를 적절히 조절하여 CPU 이용률을 높이면서 스레싱이 발생하는 것을 막는 방법으로 &lt;b&gt;워킹셋 알고리즘&lt;/b&gt;과 &lt;b&gt;페이지 부재 빈도 알고리즘&lt;/b&gt;이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;워킹셋 알고리즘&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;프로세스가 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;일정 시간 동안 집중적으로 특정 주소 영역을 참조하는 경향이 있는데 이를&lt;/b&gt; &lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;b&gt;지역성 집합&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;이라고 합니. 워킹셋 알고리즘은 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;지역성 집합이 메모리에 동시에 올라갈 수 있도록 보장하는 메모리 관리 알고리즘&lt;/b&gt;&lt;/span&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;워킹셋은 한꺼번에 메모리에 올라가야 하는 페이지들의 집합입니다. 워킹셋 알고리즘은 프로세스의 워킹셋을 구성하는 페이지들이 한꺼번에 올라갈 수 있을 메모리 공간이 있을 때만 동작합니다. 그렇지 않으면 기존 메모리에 존재하는 페이지를 디스크로 스왑 아웃 시켜 공간을 확보합니다. 이러한 방법으로 MPD를 조절하고 스레싱을 방지하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1087&quot; data-origin-height=&quot;208&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/TyqDC/btrmLAZGGWA/NGOnW0BHYBHKm9st4TzwJ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/TyqDC/btrmLAZGGWA/NGOnW0BHYBHKm9st4TzwJ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/TyqDC/btrmLAZGGWA/NGOnW0BHYBHKm9st4TzwJ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FTyqDC%2FbtrmLAZGGWA%2FNGOnW0BHYBHKm9st4TzwJ1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1087&quot; height=&quot;208&quot; data-origin-width=&quot;1087&quot; data-origin-height=&quot;208&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;워킹셋 알고리즘에서 한꺼번에 메모리에 올라가야 할 페이지들의 집합을 결정하기 위해 워킹셋 윈도우를 사용합니다. 윈도우의 크기를&amp;nbsp;&lt;span style=&quot;background-color: #ffffff; color: #202124;&quot;&gt;&amp;Delta;라고 합니다, 워킹셋 알고리즘은 시각 t에서 &lt;span style=&quot;background-color: #ffffff; color: #202124;&quot;&gt;&amp;Delta;이전에 참조된&lt;/span&gt;&amp;nbsp;&lt;b&gt;[&lt;span style=&quot;background-color: #ffffff; color: #202124;&quot;&gt;&amp;Delta;-t, t&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;b&gt;]&lt;/b&gt; 사이에 참조된 페이지들의 집합으로 결정한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;워킹셋 윈도우의 크기를 조절하여 워킹셋의 크기를 조절하는 방법으로 프로세스가 메모리를 필요로 할때는 많이 할당하고 적게 필요로 할 때에는 적게 할당하는 동적인 프레임 할당 기능을 수행하게 됩니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;페이지 부재 빈도 알고리즘&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;프로세스의 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;페이지 부재율을 주기적으로 조사하고 이 값에 근거해서 각 프로세스에 할당할 메모리 양을 동적으로 조절하는 알고리즘&lt;/b&gt;&lt;/span&gt;입니다. 시스템이 미리 정해 놓은 &lt;b&gt;상한값(upper bound)을 넘어가거나 하한값(lower bound)이하로 떨어지게 되면 운영체제가 메모리에 올라가 있는 프로세스의 수를 조절&lt;/b&gt;하게 됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1180&quot; data-origin-height=&quot;532&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ba6BDF/btrmNoR1kMb/vTdkrLK8BQlUO1x0zDD3Vk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ba6BDF/btrmNoR1kMb/vTdkrLK8BQlUO1x0zDD3Vk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ba6BDF/btrmNoR1kMb/vTdkrLK8BQlUO1x0zDD3Vk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fba6BDF%2FbtrmNoR1kMb%2FvTdkrLK8BQlUO1x0zDD3Vk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;705&quot; height=&quot;318&quot; data-origin-width=&quot;1180&quot; data-origin-height=&quot;532&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Post&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-ke-size=&quot;size23&quot;&gt;&lt;a href=&quot;https://zangzangs.tistory.com/143&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[OS] 페이지 교체 알고리즘&lt;/a&gt;&lt;/li&gt;
&lt;li data-ke-size=&quot;size23&quot;&gt;&lt;a href=&quot;https://zangzangs.tistory.com/142&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[OS] 요구 페이징(가상메모리)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;References&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;KOCW 운영체제 강의 - 반효경 교수&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignCenter&quot; data-emoticon-type=&quot;niniz&quot; data-emoticon-name=&quot;012&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘못된 코드나 내용이 있다면 댓글을 남겨주세요. 즉시 수정하도록 하겠습니다! :)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>OS</category>
      <category>OS</category>
      <category>thrashing</category>
      <category>스레싱</category>
      <category>운영체제</category>
      <category>워킹셋 알고리즘</category>
      <category>페이지 부재 빈도 알고리즘</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/144</guid>
      <comments>https://zangzangs.tistory.com/144#entry144comment</comments>
      <pubDate>Wed, 8 Dec 2021 10:02:11 +0900</pubDate>
    </item>
    <item>
      <title>[OS] 페이지 교체 알고리즘 (FIFO, LRU, LFU, NRU, NUR)</title>
      <link>https://zangzangs.tistory.com/143</link>
      <description>&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;페이지 교체 알고리즘 (FIFO,&amp;nbsp;LRU,&amp;nbsp;LFU,&amp;nbsp;NRU,&amp;nbsp;NUR)&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;안녕하세요? 장장스입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;가상 메모리 기법을 구현하는 방식 중 하나인 요구 페이징 방식은 페이지 부재가 발생하게 됩니다. 페이지를 교체하는 작업은 오버헤드를 동반하므로 가능하면 페이지 교체가 적게 일어나도록 하는 것이 좋습니다. 페이지 교체가 무엇인지,&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;페이지 교체&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;페이지 부재(page fault)&lt;/b&gt;&lt;/span&gt;가 발생하면 요청된 페이지를 디스크에서 메모리로 읽어와야 합니다. 이때 물리적 메모리에 빈 프레임이 존재하지 않을 수 있습니다. 이 경우 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;물리적 메모리에 올라와 있는 페이지 중 하나를 선택해서 디스크의 스왑 영역으로 보내야 합니다.&lt;/b&gt;&lt;/span&gt; 이와 같은 과정을 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;페이지 교체&lt;/b&gt;&lt;/span&gt;라고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;페이지 교체 알고리즘&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;어떠한 프레임에 있는 페이지를 디스크의 스왑 영역으로 보낼 것인지를 결정하는 알고리즘을 교체 알고리즘&lt;/b&gt;&lt;/span&gt;이라고 합니다. 이 알고리즘의 목표는 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;페이지 부재율을 최소화 하는 것&lt;/b&gt;&lt;/span&gt;입니다. 그러므로 가까운 미래에 참조될 가능성이 가장 적은 페이지를 선택해서 내보내는 것이 성능을 향상 시킬 수 있는 방안이 될 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;선입선출 알고리즘(FIrst In First Out: FIFO)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;페이지 교체 시 물리적 메모리에 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;가장 먼저 올라온 페이지를 우선적으로 내보내는 알고리즘&lt;/b&gt;&lt;/span&gt;입니다. 페이지의 향후 참조 가능성을 고려하지 않기 때문에 비효율적인 상황이 발생할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;아래 그림은 3개의 페이지 프레임을 가질 경우 9번의 페이지 부재와 3번의 페이지 히트가 발생했습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1194&quot; data-origin-height=&quot;244&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bKb4ko/btrmFoLKxmY/XScdfI8xJeUInNZb3STuvk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bKb4ko/btrmFoLKxmY/XScdfI8xJeUInNZb3STuvk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bKb4ko/btrmFoLKxmY/XScdfI8xJeUInNZb3STuvk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbKb4ko%2FbtrmFoLKxmY%2FXScdfI8xJeUInNZb3STuvk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1194&quot; height=&quot;244&quot; data-origin-width=&quot;1194&quot; data-origin-height=&quot;244&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이번엔 페이지 프레임을 4개로 증가 시켰을 때의 과정입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;10번의 페이지 부재와 2번의 페이지 히트가 발생했습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1194&quot; data-origin-height=&quot;302&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dZRfuL/btrmzisIeZ9/Rkzzn37HlISFcQsmWF8a2K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dZRfuL/btrmzisIeZ9/Rkzzn37HlISFcQsmWF8a2K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dZRfuL/btrmzisIeZ9/Rkzzn37HlISFcQsmWF8a2K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdZRfuL%2FbtrmzisIeZ9%2FRkzzn37HlISFcQsmWF8a2K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1194&quot; height=&quot;302&quot; data-origin-width=&quot;1194&quot; data-origin-height=&quot;302&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;분명 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;페이지 프레임을 더 많이 사용하는데 오히려 페이지 부재 횟수가 증가하는 이상현상&lt;/span&gt;&lt;/b&gt;이 나타났습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;선입선출 알고리즘에서 메모리를 증가해도 페이지 부재가 더 증가하는 &lt;span style=&quot;color: #ee2323; background-color: #f6e199;&quot;&gt;&lt;b&gt;FIFO의 이상 현상(FIFO abnomaly)이 발생&lt;/b&gt;&lt;/span&gt;할 수 있습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;LRU 알고리즘 (Least&amp;nbsp;Recently&amp;nbsp;Used&amp;nbsp;Algorithm)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;페이지 교체 알고리즘의 성능 향상을 위해선 앞으로 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;사용 가능성이 낮은 페이지를 우선적으로 내보내는 것이 좋다.&lt;/b&gt;&lt;/span&gt; 이와 관련해서 시간 지역성이라는 성질이 있다. 시간 지역성은 최근에 참조된 페이지가 미래에 다시 참조될 가능성이 높은 성질을 말한다. LRU 알고리즘은 이와 같은 성질을 활용해서 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;페이지 교체 시 가장 오래전에 참조가 이루어진 페이지를 내보낸다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1194&quot; data-origin-height=&quot;302&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cE6jYl/btrmAKo09dn/YXCQoi2SwsmqJBptKegmw1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cE6jYl/btrmAKo09dn/YXCQoi2SwsmqJBptKegmw1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cE6jYl/btrmAKo09dn/YXCQoi2SwsmqJBptKegmw1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcE6jYl%2FbtrmAKo09dn%2FYXCQoi2SwsmqJBptKegmw1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1194&quot; height=&quot;302&quot; data-origin-width=&quot;1194&quot; data-origin-height=&quot;302&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LRU 알고리즘을 사용하니 8번의 페이지 부재와 4번의 페이지 히트가 발생했습니다. FIFO 알고리즘에 비해 페이지 부재 횟수가 감소 했음을 알 수 있습니다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;LFU 알고리즘 (Least Frequently Used Algorithm)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;물리적 메모리 내에 존재하는 페이지 중에서 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;과거에 참조 횟수가 가장 적은 페이지를 교체 시킬 페이지로 결정하는 알고리즘&lt;/b&gt;&lt;/span&gt;입니다. LFU 알고리즘은 크게 2가지로 나뉘어집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Incache-LFU: 메모리에 적재될 때부터 페이지의 횟수를 카운트 하는 방식&lt;/li&gt;
&lt;li&gt;Perfect-LFU: 메모리 적재 여부와 상관 없이 페이지의 과거 총 참조 횟수를 카운트 하는 방식&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;(Perfect-LFU의 경우 정확하게 참조 횟수를 참조할 수 있지만 시간에 따른 참조의 변화를 반영하지 못하고, 구현이 복잡하다는 단점이 있습니다.)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1123&quot; data-origin-height=&quot;302&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5aEU0/btrmEiE8HEu/dKdLaCdCjNc2D9xtc6IPlk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5aEU0/btrmEiE8HEu/dKdLaCdCjNc2D9xtc6IPlk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5aEU0/btrmEiE8HEu/dKdLaCdCjNc2D9xtc6IPlk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5aEU0%2FbtrmEiE8HEu%2FdKdLaCdCjNc2D9xtc6IPlk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1123&quot; height=&quot;302&quot; data-origin-width=&quot;1123&quot; data-origin-height=&quot;302&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;11번째로 5번을 참조 하려고 하면 페이지 폴트가 발생합니다. 이 때 LRU 알고리즘은 1번 페이지 프레임을 교체하게 됩니다. 이에 반해 LFU 알고리즘은 참조 횟수가 가장 적은 4번 페이지 프레임을 교체하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;1번 페이지가 오랫동안 쓰이지 않았지만 LFU 알고리즘은 참조 횟수가 가장 적은 4번 페이지를 교체 했습니다. 그러나 앞으로 4번 페이지가 계속 사용되는 페이지 일 수도 있습니다. 이처럼, LFU는 최신 흐름을 잘 반영하지 못할 수도 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;클럭 알고리즘 (NRU or NUR)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;클럭 알고리즘은 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;하드웨어적인 자원을 통해&lt;/b&gt;&lt;/span&gt; 기존(LRU, LFU)알고리즘의 소프트웨어적인 운영 오버헤드를 줄인 방식입니다. NRU(Not Used Recently) 또는 NUR(Not Recently Used) 알고리즘이라고도 부르기도 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;클럭 알고리즘은 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;LRU처럼 가장 최근에 참조되지 않은 페이지를 대상으로 선정한다는 점에서 LRU와 근사하지만 교체되는 페이지의 참조 시점이 가장 오래되었다는 것을 보장하지는 않는다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;클럭 알고리즘은 그림처럼 참조 비트(reference bit)를 순차적으로 조사하며 동작합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;1. 프레임 내의 페이지가 참조될 때 하드웨어에 의해 1로 자동 세팅됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;2. 클럭 알고리즘은 한 바퀴 돌며 참조되지 않은 페이지의 참조 비트 값을 0으로 바꾼 후 지나갑니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;3. 참조 비트가 0인 페이지를 방문하면 해당 페이지를 교체합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1221&quot; data-origin-height=&quot;568&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFLfwl/btrmGg7P1GN/RhZ8a263lfv7OxMiWytbw1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFLfwl/btrmGg7P1GN/RhZ8a263lfv7OxMiWytbw1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFLfwl/btrmGg7P1GN/RhZ8a263lfv7OxMiWytbw1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFLfwl%2FbtrmGg7P1GN%2FRhZ8a263lfv7OxMiWytbw1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;774&quot; height=&quot;360&quot; data-origin-width=&quot;1221&quot; data-origin-height=&quot;568&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;즉, 페이지가 참조되어 1이 되고, 한 바퀴 도는 동안 사용되지 않으면 0이 되고 다시 한 바퀴를 도는 동안 사용되지 않는 페이지는 참조되지 않았으므로 교체 대상 페이지로 선정하는 알고리즘입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;클럭 알고리즘은 시계 바늘이 한 바퀴 도는 동안 걸리는 시간만큼 페이지를 메모리에 유지시켜 페이지 부재율을 줄이도록 설계 되었다. 때문에 클럭 알고리즘을 &lt;b&gt;2차 기회 알고리즘&lt;/b&gt;이라 부르기도 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Post&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-ke-size=&quot;size23&quot;&gt;&lt;a href=&quot;https://zangzangs.tistory.com/142&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2021.12.06 - [OS] - [OS] 요구 페이징(가상메모리)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;References&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;KOCW 운영체제 강의 - 반효경 교수&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignCenter&quot; data-emoticon-type=&quot;niniz&quot; data-emoticon-name=&quot;012&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘못된 코드나 내용이 있다면 댓글을 남겨주세요. 즉시 수정하도록 하겠습니다! :)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>OS</category>
      <category>FIFO</category>
      <category>LFU</category>
      <category>lru</category>
      <category>OS</category>
      <category>운영체제</category>
      <category>클럭 알고리즘</category>
      <category>페이지 교체</category>
      <category>페이지 부재</category>
      <category>페이지 폴트</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/143</guid>
      <comments>https://zangzangs.tistory.com/143#entry143comment</comments>
      <pubDate>Tue, 7 Dec 2021 10:15:36 +0900</pubDate>
    </item>
    <item>
      <title>[OS] 요구 페이징(가상메모리)</title>
      <link>https://zangzangs.tistory.com/142</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;요구 페이징(가상메모리)&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;안녕하세요? 장장스입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;우리가 일반적으로 사용하는 컴퓨터의 메모리는 8GB, 16GB로 그 크기가 한정되어 있습니다. 그럼에도 우리는 많은 프로그램을 동시에 띄워 사용하고 있습니다. 운영체제는 한정된 메모리 공간을 효율적으로 사용하기 위해 &lt;b&gt;가상메모리&lt;/b&gt; 기법을 사용합니다.&lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;가상메모리 기법은 크게 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;요구 페이징 방식(demand paging)&lt;/b&gt;&lt;/span&gt;과 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;요구 세그먼테이션 방식(demand segmentation)&lt;/span&gt;&lt;/b&gt;으로 구현이 됩니다. 요구 세그먼테이션 방식의 경우에는 &lt;b&gt;&lt;a href=&quot;https://zangzangs.tistory.com/141&quot;&gt;페이지드 세그먼테이션&lt;/a&gt; &lt;/b&gt;기법을 사용하는 경우입니다. &lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;대부분의 경우에는 요구 페이징 방식을 사용합니다.&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;요구 페이징(demand paging)&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;요구 페이징은 프로그램 실행 시 프로세스를 구성하는 모든 페이지를 한꺼번에 메모리에 올리는 것이 아니라 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;당장 사용될 페이지만을 올리는 방식&lt;/b&gt;&lt;/span&gt;입니다. 따라서 요구 페이징 기법에서는 특정 페이지에 대해 CPU의 요청이 들어온 뒤 해당 페이지를 메모리에 적재합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;요구 페이징을 사용함으로써 얻을 수 있는 장점은 다음과 같습니다.&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;1. 필요한 페이지만 메모리에 적재하기 때문에 메모리 사용량이 감소한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;2. 프로세스 전체를 메모리에 올리는 데 소요되는 입출력 오버헤드가 감소한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;3. 사용되지 않는 주소 영역에 대한 입출력이 줄어 응답시간이 줄어든다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;4. 시스템이 더 많은 프로세스를 수용할 수 있게 해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;5. 물리적 메모리의 제약을 벗어날 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;페이지 부재(page fault)&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;가상메모리 기법은 일부 페이지만 메모리에 적재되어 있고 나머지는 디스크의 스왑 영역에 존재합니다. 이러한 이유로 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;메모리에 페이지가 존재하는지 구별하기 위해 &lt;b&gt;유효-무표 비트(valid-invalid bit)&lt;/b&gt;를 두어 각 페이지가 존재하는지 표시합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이때, &lt;span style=&quot;background-color: #f6e199;&quot;&gt;페이지가 메모리에 적재되지 않아 유효-무효 비트에 무효로 세팅되어 있는 경우를 &lt;b&gt;페이지 부재(page fault)&lt;/b&gt;가 일어났다&lt;/span&gt;고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;요구 페이징의 페이지 부재 처리는 어떻게?&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;CPU가 무효 페이지에 접근하면 주소 변환을 담담하는 하드웨어인 MMU(Memory &lt;span style=&quot;background-color: #ffffff; color: #4d5156;&quot;&gt;Management&lt;span&gt; Unit)가 페이지 부재 트랩을 발생시킵니다. 다음으로 CPU의 제어권이 커널모드로 변경되고 운영체제의 페이지 부재 처리 루틴이 호출됩니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #4d5156;&quot;&gt;&lt;span&gt;1. 운영체제가 해당 페이지에 대한 접근하기 위해 주소가 유효한지 확인합니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #4d5156;&quot;&gt;&lt;span&gt;2. 범위를 벗어나는 영역에 속한 페이지 접근이나 접근 권한 위반을 할 경우 프로세스를 종료시킵니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #4d5156;&quot;&gt;&lt;span&gt;3. 접근이 가능한 경우 물리적 메모리에 비어 있는 프레임을 할당받습니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #4d5156;&quot;&gt;&lt;span&gt;4. 비어 있는 프레임이 없다면 기존에 메모리에 올라와 있는 페이지 중 하나를 디스크로 내보냅니다. (스왑 아웃)&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #4d5156;&quot;&gt;&lt;span&gt;5. 디스크로부터 메모리 적재는 오랜 시간이 걸립니다. 따라서 페이지 부재가 발생한 프로세스는 CPU를 반납하고 PCB에 현재상태를 저장 후 봉쇄 상태가 됩니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #4d5156;&quot;&gt;&lt;span&gt;6. 디스크 입출력이 완료되어 인터럽트가 발생하면, 해당 페이지의 유효-무효 비트를 유효로 수정합니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #4d5156;&quot;&gt;&lt;span&gt;7. 봉쇄되었던 프로세스를 준비 큐로 이동시킵니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #4d5156;&quot;&gt;&lt;span&gt;8. CPU를 할당 받고 PCB로부터 저장한 값을 복원시켜 중단되었던 명령부터 실행을 이어갑니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Post&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-ke-size=&quot;size23&quot;&gt;&lt;a href=&quot;https://zangzangs.tistory.com/143&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2021.12.07 - [OS] - [OS] 페이지 교체 알고리즘&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;References&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;KOCW 운영체제 강의 - 반효경 교수&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignCenter&quot; data-emoticon-type=&quot;niniz&quot; data-emoticon-name=&quot;012&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘못된 코드나 내용이 있다면 댓글을 남겨주세요. 즉시 수정하도록 하겠습니다! :)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>OS</category>
      <category>OS</category>
      <category>가상메모리</category>
      <category>요구 페이징</category>
      <category>운영체제</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/142</guid>
      <comments>https://zangzangs.tistory.com/142#entry142comment</comments>
      <pubDate>Mon, 6 Dec 2021 09:53:20 +0900</pubDate>
    </item>
    <item>
      <title>[GoF] 팩토리 메서드 패턴(Factory Method Pattern)</title>
      <link>https://zangzangs.tistory.com/147</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1538&quot; data-origin-height=&quot;336&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/BfEoZ/btrm2n6JaYd/jyOS0t7Jvbm0kfUATKYgw0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/BfEoZ/btrm2n6JaYd/jyOS0t7Jvbm0kfUATKYgw0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/BfEoZ/btrm2n6JaYd/jyOS0t7Jvbm0kfUATKYgw0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FBfEoZ%2Fbtrm2n6JaYd%2FjyOS0t7Jvbm0kfUATKYgw0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1538&quot; height=&quot;336&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1538&quot; data-origin-height=&quot;336&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;팩토리 메서드 패턴(Factory Method Pattern)&lt;/b&gt;&lt;/h2&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt; 팩토리 메서드 패턴이란?&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;인스턴스 생성을 하위 클래스로 분리하도록 위임하는 패턴이다. 인스턴스를 생성하기 위한 인터페이스를 정의하고자 하지만, 어떤 클래스의 인스턴스를 생성할지에 대한 결정을 하위 클래스에서 결정하도록 할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size14&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;&lt;i&gt;(비유하자면 고객이 자량 구매를 요청 했을 때, 공장에서 요청에 맞게 차량을 생산하는 것과 같다.)&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt; 팩토리 메서드 패턴 왜 사용할까?&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;인스턴스를 생성할 때 관련된 &lt;b&gt;동일한 메서드는 상위 클래스에서 처리&lt;/b&gt;하여 공통처리되도록 구현이 가능하고, 나머지 상황에 따른 &lt;b&gt;각각 일어날 수 있는 인스턴스에 대한 생성을 하위 클래스에게 처리&lt;/b&gt;할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;팩토리 메서드 패턴을 사용하게 되면&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;하위 클래스에서 상황에 따라 다양한 인스턴스를 생성할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&amp;nbsp;클래스 다이어그램&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;769&quot; data-origin-height=&quot;342&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cLL7zf/btrm2nyTYkB/3TITETeqVUecFKF2IiBke0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cLL7zf/btrm2nyTYkB/3TITETeqVUecFKF2IiBke0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cLL7zf/btrm2nyTYkB/3TITETeqVUecFKF2IiBke0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcLL7zf%2Fbtrm2nyTYkB%2F3TITETeqVUecFKF2IiBke0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;769&quot; height=&quot;342&quot; data-origin-width=&quot;769&quot; data-origin-height=&quot;342&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&amp;nbsp;객체 협력&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Product&lt;/b&gt; 팩토리 메소드가 생성하는 객체의 인터페이스를 정의하는 abstract 클래스&lt;/li&gt;
&lt;li&gt;&lt;b&gt;ConcreteProduct&lt;/b&gt; Product 클래스에 정의된 인터페이스를 실제로 구현한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Creator&lt;/b&gt; Product 타입의 객체를 반환하는 팩토리 메소드를 선언한다. Creator 클래스는 팩토리 메소드를 기본적으로 구현하는데, 이 구현에서는 ConcreateProduct 객체를 반환한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;ConcreteCreator&lt;/b&gt; ConcreteProduct 의 인스턴스를 반환하기 위해 팩토리 메소드를 재정의 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&amp;nbsp;코드보기 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;a style=&quot;color: #ee2323;&quot; href=&quot;https://github.com/ZANGZANGS/gof_design_pattern/tree/master#readme&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Click!&lt;/a&gt;&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;a style=&quot;color: #ee2323;&quot; href=&quot;https://github.com/ZANGZANGS/gof_design_pattern/commit/9e8f8d297c4096fe20a3aef02237e2998d5343db&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #0593d3;&quot;&gt;GIT COMMIT 링크 열기!&lt;/span&gt;&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignLeft&quot; data-emoticon-type=&quot;friends1&quot; data-emoticon-name=&quot;047&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/friends1/large/047.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/friends1/large/047.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;</description>
      <category>Gof Design Pattern</category>
      <category>Gof</category>
      <category>디자인패턴</category>
      <category>팩토리메서드</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/147</guid>
      <comments>https://zangzangs.tistory.com/147#entry147comment</comments>
      <pubDate>Sun, 5 Dec 2021 20:03:13 +0900</pubDate>
    </item>
    <item>
      <title>[ GoF] 템플릿 메서드 패턴(Template Method Pattern)</title>
      <link>https://zangzangs.tistory.com/146</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1538&quot; data-origin-height=&quot;336&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/buu2Lj/btrmZJBWz2d/eMSSMIhskFXueSRQD3qKik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/buu2Lj/btrmZJBWz2d/eMSSMIhskFXueSRQD3qKik/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/buu2Lj/btrmZJBWz2d/eMSSMIhskFXueSRQD3qKik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbuu2Lj%2FbtrmZJBWz2d%2FeMSSMIhskFXueSRQD3qKik%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1538&quot; height=&quot;336&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1538&quot; data-origin-height=&quot;336&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;템플릿 메서드 패턴(Template Method Pattern)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt;&amp;nbsp;템플릿 메서드 패턴이란?&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;상위 클래스(abstract class)에서 전반적인 흐름을 구현하고 하위 클래스에서 이를 상속받아 구체적인 처리를 하도록 위임하는 패턴이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt; &lt;b&gt;템플릿 메서드 패턴 &lt;/b&gt;왜 사용할까?&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;오퍼레이션에 알고리즘(단계)의 기본 골격 구조를 정의하고 구체적인 단계는 하위 클래스에 정의한다. abstract 메서드를 통해서 알고리즘(단계)의 일부 단계를 정의함으로써 템플릿 메소드의 처리순서를 정할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;템플릿 메서드를 사용하게 되면&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;템플릿 메서드를 통해 코드 재사용을 할 수 있다.&lt;/li&gt;
&lt;li&gt;프레임워크에서 가장 많이 사용되는 패턴 중 하나 이다.&lt;/li&gt;
&lt;li&gt;클래스의 공통부분을 분리할 수 있다.&lt;/li&gt;
&lt;li&gt;템플릿 메서드에서 사용하는 오퍼레이션들
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;ConcreteClass 오퍼레이션이나 클라이언트 클래스에 정의된 오퍼레이션&lt;/li&gt;
&lt;li&gt;AbstractClass 에 정의된 오퍼레이션 중 구체적인 알고리즘을 가지고 있는 오퍼레이션 : final을 선언하여 재정의 할 수 없게 한다.&lt;/li&gt;
&lt;li&gt;기본 오퍼레이션으로 추상화된 오퍼레이션 : abstract 메서드를 말함.&lt;/li&gt;
&lt;li&gt;훅 오퍼레이션 : 상위 클래스에서 빈 메서드를 정의함. 필요한 경우 하위 클래스에서 재정의 하여 사용할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&amp;nbsp;클래스 다이어그램&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;300&quot; data-origin-height=&quot;311&quot;&gt;&lt;a href=&quot;https://ko.wikipedia.org/wiki/%ED%85%9C%ED%94%8C%EB%A6%BF_%EB%A9%94%EC%86%8C%EB%93%9C_%ED%8C%A8%ED%84%B4&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cnjQ8b/btrmWriu7Zp/lDUZk6efo4dOrA4L5Xotb0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcnjQ8b%2FbtrmWriu7Zp%2FlDUZk6efo4dOrA4L5Xotb0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;368&quot; height=&quot;382&quot; data-origin-width=&quot;300&quot; data-origin-height=&quot;311&quot;/&gt;&lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&amp;nbsp;객체 협력&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;AbstractClass&lt;/b&gt; 하위 클래스에서 반드시 구현해야 하는 알고리즘 처리 단계 내의 기본 오퍼레이션이 무엇인지를 정의한다. 하위 클래스에서 이들 오퍼레이션들을 구현한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;ConcreteClass&lt;/b&gt; 상위 클래스의 abstract 메서드를 구현하거나 구현된 메서드를 재정의(@Override)한다&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&amp;nbsp;코드보기 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;a style=&quot;color: #ee2323;&quot; href=&quot;https://github.com/ZANGZANGS/gof_design_pattern/tree/master#readme&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Click!&lt;/a&gt;&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/ZANGZANGS/gof_design_pattern/commit/1c54fe614c5ea26f5e3575f2c1374d7332e83cc7&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;GIT COMMIT 링크!&lt;/a&gt;&lt;/p&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignLeft&quot; data-emoticon-type=&quot;friends1&quot; data-emoticon-name=&quot;047&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/friends1/large/047.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/friends1/large/047.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Gof Design Pattern</category>
      <category>Gof</category>
      <category>Template Method Pattern</category>
      <category>디자인패턴</category>
      <category>템플릿메서드</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/146</guid>
      <comments>https://zangzangs.tistory.com/146#entry146comment</comments>
      <pubDate>Sat, 4 Dec 2021 13:40:08 +0900</pubDate>
    </item>
    <item>
      <title>[GoF] 빌더 패턴(Builder Pattern)</title>
      <link>https://zangzangs.tistory.com/145</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1538&quot; data-origin-height=&quot;336&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ce6Au6/btrmSxIssqu/CPBJDw3sBIcbEdbMk72Gu1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ce6Au6/btrmSxIssqu/CPBJDw3sBIcbEdbMk72Gu1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ce6Au6/btrmSxIssqu/CPBJDw3sBIcbEdbMk72Gu1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fce6Au6%2FbtrmSxIssqu%2FCPBJDw3sBIcbEdbMk72Gu1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1538&quot; height=&quot;336&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1538&quot; data-origin-height=&quot;336&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;빌더 패턴(Builder Pattern)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt;&amp;nbsp;빌더 패턴이란?&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;복잡한 객체를 생성하는 클래스와 구현하는 클래스를 분리하여, 동일한 생성 과정에서도 서로 다른 결과물이 나올 수 있도록 방법을 제공합니다. 사용자는 Builder에서 제공하는 메서드를 사용하여 (구현)결과물을 얻을 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt; 빌더 패턴 왜 사용할까?&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;객체를 생성할 때 생성 과정과 구현 방법을 분리함으로써 동일한 객체를 생성에서 과정에서 여러 다른 표현이 나올 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;빌더 패턴을 사용하게 되면&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;생성과 구현을 분리할 수 있다.&lt;/li&gt;
&lt;li&gt;구현을 다양하게 할 수 있다.&lt;/li&gt;
&lt;li&gt;복잡한 객체를 생성하는 절차를 세밀하게 나눌 수 있다.&lt;/li&gt;
&lt;li&gt;사용자는 구체적인 사항을 알 필요가 없다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&amp;nbsp;클래스 다이어그램&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;240&quot;&gt;&lt;a href=&quot;https://ko.wikipedia.org/wiki/%EB%B9%8C%EB%8D%94_%ED%8C%A8%ED%84%B4&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NauoJ/btrmK0lr7VB/XBnphzcUkLyhSh3y6oN0X0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNauoJ%2FbtrmK0lr7VB%2FXBnphzcUkLyhSh3y6oN0X0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;240&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;240&quot;/&gt;&lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&amp;nbsp;객체 협력&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-sourcepos=&quot;25:1-27:0&quot;&gt;&lt;b&gt;Builder&lt;/b&gt; Product의 각 요소들을 생성하는데 필요한 추상 메서드가 선언된 클래스나 인터페이스&lt;/li&gt;
&lt;li data-sourcepos=&quot;28:1-30:0&quot;&gt;&lt;b&gt;ConcreteBuilder&lt;/b&gt; Builder에 선언된 메서드를 구현한 클래스&lt;/li&gt;
&lt;li data-sourcepos=&quot;31:1-33:0&quot;&gt;&lt;b&gt;Director&lt;/b&gt; Builder 인터페이스를 사용하여 Product를 생성한다.&lt;/li&gt;
&lt;li data-sourcepos=&quot;34:1-36:2&quot;&gt;&lt;b&gt;Product&lt;/b&gt; 결과물&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt; 이펙티브 자바에서 사용하는 빌더 패턴&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이팩티브 자바 책에서도 빌더 패턴이 등장한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;책에서의 빌더 패턴은 객체를 생성할 때 여러개의 매개 변수가 점진적으로 늘어나는 경우 여러개의 생성자를 만들어 사용하기 보다 인스턴스 생성을 위한 Builder를 사용함으로써, 매개 변수의 개수에 상관없이 유연하게 수정하며 혹시 모를 오류를 방지하는 구조를 제공하는 것을 말한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;GoF의 Builder 패턴은 생성자 뿐만아니라 일련의 과정을 추상화하여 인스턴스를 생성한다는 차이가 있다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;background-color: #006dd7;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&amp;nbsp;코드보기 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;a style=&quot;color: #ee2323;&quot; href=&quot;https://github.com/ZANGZANGS/gof_design_pattern/tree/master#readme&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Click!&lt;/a&gt;&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/ZANGZANGS/gof_design_pattern/commit/7b4d50b33ae1461a1b1085d1344748018e96eaca&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Github 커밋 링크!&lt;/a&gt;&lt;/p&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignLeft&quot; data-emoticon-type=&quot;friends1&quot; data-emoticon-name=&quot;047&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/friends1/large/047.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/friends1/large/047.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Gof Design Pattern</category>
      <category>Gof</category>
      <category>디자인 패턴</category>
      <category>빌더</category>
      <category>생성자</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/145</guid>
      <comments>https://zangzangs.tistory.com/145#entry145comment</comments>
      <pubDate>Fri, 3 Dec 2021 13:30:41 +0900</pubDate>
    </item>
    <item>
      <title>[OS] 메모리 불연속할당 - (3) 페이지드 세그먼테이션</title>
      <link>https://zangzangs.tistory.com/141</link>
      <description>&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;[OS]&amp;nbsp;메모리&amp;nbsp;불연속할당&amp;nbsp;-&amp;nbsp;(3)&amp;nbsp;페이지드&amp;nbsp;세그먼테이션&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;안녕하세요? 장장스입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;실제 물리적 메모리는 크게&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;연속할당 방식&lt;/b&gt;과&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;불연속할당 방식&lt;/b&gt;으로 나뉩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;오늘은 메모리 불연속할당 방식중 하나인&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;b&gt;페이지드 세그먼테이션&lt;/b&gt;&lt;/span&gt;에 대해 정리해보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;페이지드 세그먼테이션&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;앞선 두 가지 포스팅을 보면&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://zangzangs.tistory.com/134&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(1) 페이징 기법&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://zangzangs.tistory.com/140&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;(2) 세그먼테이션&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;각각의 장단점을 갖고 있음을 알 수 있다. 페이지드 세그먼테이션은 페이징 기법과 세그먼테이션 기법의 장점을 취하는 주소 변환 기법이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;세그먼테이션과 마찬가지로 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;프로세스를 의미 단위의 세그먼트로 분할한다.&lt;/b&gt;&lt;/span&gt; 단, 세그먼테이션 처럼 불규칙한 길이가 아니라 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;동일한 크기의 페이지들의 집합&lt;/b&gt;&lt;/span&gt;으로 구성하는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;페이지드 세그먼테이션 테이블&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;하나의 세그먼트를 여러개의 페이지로 구성되므로 페이지드 세그먼테이션은 2개의 테이블을 사용한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;외부의 세그먼트 테이블&lt;/li&gt;
&lt;li&gt;내부의 페이지 테이블&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;페이징 기법의 2단계 페이지 테이블과 유사한 구조를 사용한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;페이지드 세그먼테이션 테이블을 활용하여 주소변환 하는 과정은 다음과 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;1. 논리적 주소의 상위 비트인 세그먼트 번호를 통해 세그먼트 테이블의 해당 항목을 확인한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;2. 해당 항목에는 세그먼트의 길이와 세그먼트의 페이지 테이블 시작 주소가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;3. 세그먼트 길이를 넘어선 메모리 접근인지 체크한다. 유효하지 않다면 트랩을 발생시킨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;4. 오프셋 값을 상위/하위 비트로 나누어 상위비트는 세그먼트 내의 페이지 번호로 사용하고, 하위 비트는 페이지 내에서의 변위로 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Post&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-ke-size=&quot;size23&quot;&gt;&lt;a href=&quot;https://zangzangs.tistory.com/134&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[OS] 메모리 불연속할당 - (1) 페이징 기법&lt;/a&gt;&lt;/li&gt;
&lt;li data-ke-size=&quot;size23&quot;&gt;&lt;a href=&quot;https://zangzangs.tistory.com/140&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[OS] 메모리 불연속할당 - (2) 세그먼테이션&lt;/a&gt;&lt;/li&gt;
&lt;li data-ke-size=&quot;size23&quot;&gt;&lt;a href=&quot;https://zangzangs.tistory.com/141&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[OS] 메모리 불연속할당 - (3) 페이지드 세그먼테이션&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;References&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;KOCW 운영체제 강의 - 반효경 교수&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignCenter&quot; data-emoticon-type=&quot;niniz&quot; data-emoticon-name=&quot;012&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘못된 코드나 내용이 있다면 댓글을 남겨주세요. 즉시 수정하도록 하겠습니다! :)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>OS</category>
      <category>OS</category>
      <category>메모리</category>
      <category>운영체제</category>
      <category>페이지드 세그먼테이션</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/141</guid>
      <comments>https://zangzangs.tistory.com/141#entry141comment</comments>
      <pubDate>Thu, 2 Dec 2021 19:16:20 +0900</pubDate>
    </item>
    <item>
      <title>[OS] 메모리 불연속할당 - (2) 세그먼테이션</title>
      <link>https://zangzangs.tistory.com/140</link>
      <description>&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;[OS] 메모리 불연속할당 - (2) 세그먼테이션&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;안녕하세요? 장장스입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;실제 물리적 메모리는 크게&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;연속할당 방식&lt;/b&gt;과&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;불연속할당 방식&lt;/b&gt;으로 나뉩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;오늘은 메모리 불연속할당 방식중 하나인 &lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;b&gt;세그먼테이션&lt;/b&gt;&lt;/span&gt;에 대해 정리해보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;세그먼테이션&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;세그먼테이션은 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;프로세스의 주소공간을 의미 단위의 세그먼트(segment)로 나누어 물리적 메모리에 올리는 방법&lt;/b&gt;&lt;/span&gt;이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;프로세스의 주소 공간은 일반적으로 코드, 데이터, 스택 등의 의미 있는 단위들로 구성이 된다. 세그먼트는 이와 같은 주소 공간 전체를 크게는 하나의 세그먼트로 보기도 한다. 일반적으로 코드, 데이터, 스택 등의 기능 단위로 세그먼트를 정의하며, 프로그램을 구성하는 함수 하나하나를 각각 세그먼트라고 정의할 수도 있다. 주의할 점은 논리적 단위로 나눈 것이기 때문에 세그먼트의 크기가 균일하지 않다는 점이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;세그먼트 테이블&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;세그먼테이션 기법에서는 주소 변환을 위해 세그먼트 테이블을 사용한다. 세그먼트 테이블의 각 항목은 기준점(base)과 한계점(limit)을 가지고 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;기준점(base) : 물리적 메모리에서 세그먼트의 시작 위치&lt;/li&gt;
&lt;li&gt;한계점(limit) : 세그먼트의 길이&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;세그먼테이션 기법에서는 세그먼트 길이가 균일하지 않으므로 세그먼트의 시작 위치 정보뿐 아니라 길이 정보도 함께 보관하고 있는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;페이징 기법에서는 주소 변환을 위해 기준 레지스터(PTBR)와 테이블 길이 레지스터(PTLR)를 사용했듯이 세그먼테이션 기법에서도 &lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;세그먼트 테이블 기준 레지스터(STBR)&lt;/span&gt;&lt;/b&gt;과 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;세그먼트 테이블 길이 레지스터(STLR)&lt;/b&gt;&lt;/span&gt;를 사용하게 된다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;세그먼트 테이블 기준 레지스터(STBR) : 프로세스의 세그먼트 테이블 메모리 위치(시작 주소)&lt;/li&gt;
&lt;li&gt;세그먼트 테이블 길이 레지스터(STLR) : 프로세스 세그먼트의 총 개수&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;세그먼트 테이블 주소 변환&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;세그먼테이션 기법에서는 논리적 주소를 물리적 주소로 변환하기 전에 두 가지 항목을 체크합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;1. 요청된 세그먼트의 번호가 STLR 미만의 값인지 확인합니다. 만약 그렇지 않다면 존재하지 않는 세그먼트에 대한 접근으로 예외상황을 발생시켜 메모리에 접근 봉쇄합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;2. 논리적 주소의 오프셋 값이 그 세그먼트의 길이보다 작은 값인지 확인합니다. 만약 그렇지 않다면 세그먼트 테이블의 길이를 넘어서는 오프셋 위치에 대한 접근으로 예외상황을 발생시켜 메모리에 접근 봉쇄합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1332&quot; data-origin-height=&quot;795&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LicHE/btrmxjYk54S/5DU9oWvfMdko3wAMvN8JE0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LicHE/btrmxjYk54S/5DU9oWvfMdko3wAMvN8JE0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LicHE/btrmxjYk54S/5DU9oWvfMdko3wAMvN8JE0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLicHE%2FbtrmxjYk54S%2F5DU9oWvfMdko3wAMvN8JE0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;674&quot; height=&quot;402&quot; data-origin-width=&quot;1332&quot; data-origin-height=&quot;795&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;장단점&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;세그먼트는 의미 단위로 나누어져 있기 때문에 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;공유와 보안의 측면에서 페이징 기법에 비해 효과적&lt;/b&gt;&lt;/span&gt;이다. 주소 공간의 일부를 공유하거나 특정 주소 공간에 접근 제어를 할경우 크기가 아니라 의미 단위로 공유되기 떄문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;세그먼테이션은 프로세스를 의미 단위로 나누어 메모리에 적재하기 때문에 세그먼트의 길이가 균일하지 않다. 따라서 물리적 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;메모리 관리에서 외부조각이 발생&lt;/span&gt;&lt;/b&gt;하게 되며, 세그먼트를 어느 가용 공간에 할당할 것이지 결정하는 문제가 발생한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Post&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-ke-size=&quot;size23&quot;&gt;&lt;a href=&quot;https://zangzangs.tistory.com/134&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[OS] 메모리 불연속할당 - (1) 페이징 기법&lt;/a&gt;&lt;/li&gt;
&lt;li data-ke-size=&quot;size23&quot;&gt;&lt;a href=&quot;https://zangzangs.tistory.com/140&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[OS] 메모리 불연속할당 - (2) 세그먼테이션&lt;/a&gt;&lt;/li&gt;
&lt;li data-ke-size=&quot;size23&quot;&gt;&lt;a href=&quot;https://zangzangs.tistory.com/141&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[OS] 메모리 불연속할당 - (3) 페이지드 세그먼테이션&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;References&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;KOCW 운영체제 강의 - 반효경 교수&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignCenter&quot; data-emoticon-type=&quot;niniz&quot; data-emoticon-name=&quot;012&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘못된 코드나 내용이 있다면 댓글을 남겨주세요. 즉시 수정하도록 하겠습니다! :)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>OS</category>
      <category>OS</category>
      <category>메모리</category>
      <category>세그먼테이션</category>
      <category>운영체제</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/140</guid>
      <comments>https://zangzangs.tistory.com/140#entry140comment</comments>
      <pubDate>Wed, 1 Dec 2021 18:37:32 +0900</pubDate>
    </item>
    <item>
      <title>[OS] 메모리 불연속할당 - (1) 페이징 기법</title>
      <link>https://zangzangs.tistory.com/134</link>
      <description>&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;[OS]&amp;nbsp;메모리&amp;nbsp;불연속할당&amp;nbsp;-&amp;nbsp;(1)&amp;nbsp;페이징&amp;nbsp;기법&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;안녕하세요? 장장스입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;실제 물리적 메모리는 크게&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;연속할당 방식&lt;/b&gt;과&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;불연속할당 방식&lt;/b&gt;으로 나뉩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;오늘은 메모리 불연속할당 방식중 하나인 &lt;span style=&quot;background-color: #dddddd;&quot;&gt;&lt;b&gt;페이징 기법&lt;/b&gt;&lt;/span&gt;에 대해 정리해보겠습니다.&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;메모리 불연속할당 기법&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;불연속할당 기법은 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;하나의 프로세스가 물리적 메모리의 여러 위치에 분산되어 올라갈 수 있는 메모리 할당 기법&lt;/b&gt;&lt;/span&gt;을 말합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;페이징 기법&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;페이징 기법은 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;프로세스의 주소 공간을 동일한 크기의 페이지 단위로 나누어 물리적 메모리의 서로 다른 위치에 페이지들을 저장하는 방식을 말한다&lt;/b&gt;&lt;/span&gt;. 페이징 기법에서는 각 프로세스의 주소 공간 일부는 백킹스토어에, 일부는 물리적 메모리에 혼재시키는 것이 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;페이징 기법에서는 물리적 메모리를 페이지와 동일한 크기의 프레임으로 미리 나누어 둔다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;메모리에 올리는 단위가 동일한 크기의 페이지 단위이므로, 메모리를 같은 크기로 미리 분할해 두더라도 빈 프레임이 있으면 어떤 위치이든 사용될 수 있기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;333&quot; data-origin-height=&quot;297&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CcuL5/btrlEJjdIIF/FiaKoLHy9bKlRlH1eeT6z0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CcuL5/btrlEJjdIIF/FiaKoLHy9bKlRlH1eeT6z0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CcuL5/btrlEJjdIIF/FiaKoLHy9bKlRlH1eeT6z0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCcuL5%2FbtrlEJjdIIF%2FFiaKoLHy9bKlRlH1eeT6z0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;333&quot; height=&quot;297&quot; data-origin-width=&quot;333&quot; data-origin-height=&quot;297&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;따라서 페이징 기법은 동적 메모리 할당 문제(&lt;i&gt;메모리 주소 공간 결정 문제&lt;/i&gt;)가 발생하지 않는다는 강점을 가진다. 빈 페이지가 보이면 메모리를 올리기만 하면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;페이징 기법에서는 프로세스의 주소 공간과 물리적 메모리가 모두 같은 크기의 페이지 단위로 나누어지기 때문에 빈 공간은 어느 곳이든 활용 할 수 있다. 따라서 메모리상의 가용 공간의 크기가 작아서 빈 공간임에도 활용되지 못하는 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;외부조각 문제가 발생하지 않는다.&lt;/b&gt;&lt;/span&gt;&amp;nbsp;그러나 프로그램의 크기가 항상 페이지 크기의 배수가 된다는 보장이 없기 때문에 프로세스의 주소 공간 중 제일 마지막에 위치한 페이지에서는 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;내부조각이 발생할 가능성이 있다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;주소 변환 기법&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;페이징 기법에서는 주소 변환 절차가 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;a style=&quot;color: #000000;&quot; href=&quot;https://zangzangs.tistory.com/133&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;연속할당 방식&lt;/a&gt;&lt;/span&gt;에 비해 다소 복잡하다. 이는 하나의 프로세스라 하더라도 페이지 단위로 물리적 메모리에 올리는 위치가 상이 하므로, 논리적 주소를 물리적 주소로 변환하는 작업이 페이지 단위로 이루어져야 하기 때문이다. 즉, &lt;span style=&quot;background-color: #f6e199;&quot;&gt;특정 프로세스의 몇 번째 페이지가 물리적 메모리의 몇 번째 프레임에 들어 있다는 페이지별 주소 변환 정보를 유지하고 있어야 한다.&lt;/span&gt; 따라서 페이징 기법에서는 모든 프로세스가 각각의 주소 변환을 위한 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;페이지 테이블(page table)&lt;/b&gt;&lt;/span&gt;을 가지며, 이 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;테이블은 프로세스가 가질 수 있는 페이지의 개수만큼 주소 변환 엔트리를 가지고 있게 된다.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;735&quot; data-origin-height=&quot;404&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bTOoz6/btrlDw51acx/gkL0RloEU3kWKeO59giYLk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bTOoz6/btrlDw51acx/gkL0RloEU3kWKeO59giYLk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bTOoz6/btrlDw51acx/gkL0RloEU3kWKeO59giYLk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbTOoz6%2FbtrlDw51acx%2FgkL0RloEU3kWKeO59giYLk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;699&quot; height=&quot;384&quot; data-origin-width=&quot;735&quot; data-origin-height=&quot;404&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;페이징 기법에서는 CPU가 사용하는 논리적 주소를 페이지 번호(p)와 페이지 오프셋(d)로 나누어 주소변환을 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;1. 페이지 테이블에서 페이지 번호(p)를 확인하여 물리적 메모리 상의 기준 주소(base address)를 확인한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;2. 물리적 주소에서 오프셋(d)만큼 떨어진 곳이 실제 물리적 메모리 주소이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;페이지 테이블&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;페이지 테이블에 접근하기 위해 운영체제는 2개의 레지스터를 사용한다.&amp;nbsp;이들은 각각&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;페이지 테이블 기준 레지스터(page table base register) : 페이지 테이블의 시작 위치&lt;/li&gt;
&lt;li&gt;페이지 테이블 길이 레지스터(page table length register) : 페이지 테이블의 크기&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;기능을 갖고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;그렇다면 페이지 테이블은 어디에 있을까&lt;/b&gt;❓&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;페이지 테이블은 메모리에 존재한다. 즉, 실제 물리적 메모리의 주소를 알기 위해서&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;1. 페이지 테이블 정보를 확인하기 위해 메모리 접근&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;2. 물리적 메모리를 얻기 위해 메모리 접근&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;총 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;2번의 메모리 접근을 하게되는 오버헤드가 발생&lt;/b&gt;&lt;/span&gt;한다. 이와 같은 문제를 해결하기 위해 &lt;span style=&quot;background-color: #99cefa;&quot;&gt;&lt;b&gt;TLB(Translation Look-aside Buffer)&lt;/b&gt;&lt;/span&gt;라고 불리는 고속의 주소 변환용 하드웨어 캐시를 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;TLB 하드웨어는 가격이 비싸서 용량이 적다. 따라서 &lt;b&gt;TLB에서 모든 페이지 테이블 정보를 확인 할 수는 없다&lt;/b&gt;. 또 원하는 페이지를 찾기 위해 모든 페이지를 뒤져야하게 되는데 페이지 테이블 개수가 n개 라면 O(n)의 시간 복잡도가 걸리게 된다. 이를 극복하기 위해 &lt;b&gt;병렬탐색이 가능한 연관 레지스터를 사용&lt;/b&gt;하여 모든 페이지 테이블 정보를 한꺼번에 찾는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;TLB를 확인해도 원하는 페이지 정보를 확인 할 수 없다면 페이지 테이블을 방문하여 물리적 메모리 주소를 확인한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;865&quot; data-origin-height=&quot;593&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GKdya/btrlEntXGOk/Gp1WYbb657uAmQwmTGVMQ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GKdya/btrlEntXGOk/Gp1WYbb657uAmQwmTGVMQ1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GKdya/btrlEntXGOk/Gp1WYbb657uAmQwmTGVMQ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGKdya%2FbtrlEntXGOk%2FGp1WYbb657uAmQwmTGVMQ1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;770&quot; height=&quot;528&quot; data-origin-width=&quot;865&quot; data-origin-height=&quot;593&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;계층적 페이징&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;현대의 컴퓨터는 32bit 혹은 64bit 주소 체계를 사용한다. 32bit 컴퓨터에서는 2^32byte(4GB)의 주소 공간을 갖는 프로그램을 지원할 수 있다. 이러한 컴퓨팅 환경에서 페이지 크기가 4KB라면 4GB/4KB = 1M(2^20)개의 페이지 테이블이 필요하게 된다. 각 페이지 테이블 항목이 4byte씩 필요로 한다면 한 프로세스당 필요한 페이지 수는 4MB의 공간을 필요로 하게 된다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;32bit 운영체제는 2^32byte의 주소공간 즉, 4GB의 주소공간을 갖는 프로그램을 지원한다.&lt;br /&gt;&lt;br /&gt;프로세스 주소공간 &lt;b&gt;4GB&lt;/b&gt;&lt;br /&gt;페이지 크기 &lt;b&gt;4KB&lt;br /&gt;&lt;/b&gt;페이지 테이블 항목당 필요한 용량 &lt;b&gt;4byte&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;4GB/4KBx4byte = 4MB&lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;사용하는 프로세스가 증가할수록 페이지 테이블을 위한 많은 메모리 공간이 사용된다. 이러한 메모리 낭비를 줄이기 위해 2단계 페이징 기법을 사용한다. 2단계 페이징 기법은 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;외부 페이지 테이블&lt;/b&gt;과 &lt;b&gt;내부 페이지 테이블&lt;/b&gt;을 사용&lt;/span&gt;한다. &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;사용되지 않는 주소 공간에 대해서는 외부 페이지 테이블의 항목을 NULL로 설정하여 대응되는 내부 페이지 테이블을 생성하지 않는 방법&lt;/b&gt;&lt;/span&gt;이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;727&quot; data-origin-height=&quot;423&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dBiaWO/btrlEIY1Id6/7MAcMFS7MxiqjlNZcCI5mk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dBiaWO/btrlEIY1Id6/7MAcMFS7MxiqjlNZcCI5mk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dBiaWO/btrlEIY1Id6/7MAcMFS7MxiqjlNZcCI5mk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdBiaWO%2FbtrlEIY1Id6%2F7MAcMFS7MxiqjlNZcCI5mk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;727&quot; height=&quot;423&quot; data-origin-width=&quot;727&quot; data-origin-height=&quot;423&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;계층적 페이징 기법은 메모리 공간을 줄여 공간적인 이득을 볼 수 있지만 주소 변환을 위해 페이지 단계수가 3단계, 4단계로 증가할 수록 메모리에 접근하는 횟수도 증가하여 오버헤드가 증가하는 손해가 뒤따르게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;그러므로 TLB와 계층적 페이징 기법을 적절히 사용하여 메모리 공간 효율과 시간 효율을 높여야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;역페이지 테이블&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;역페이지 테이블 기법은 물리적 메모리의 페이지 프레임 하나당 페이지 테이블에 하나씩 항목을 두는 방식이다. 다시 말하면 논리적 주소에 대해 페이지 테이블을 만드는 것이 아니라, 물리적 주소에 대해 페이지 테이블을 만드는 것이다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;역페이지 테이블❓&lt;/span&gt;&lt;/b&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;논리적 주소에 대한 페이지 테이블 ❌&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;물리적 주소에 대한 페이지 테이블 ✔️&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;즉, 프로세스마다 페이지 테이블을 두지 않고, 시스템 전체에 페이지 테이블을 하나만 두는 방법이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;페이지 테이블의 각 항목은 프로세스 번호(pid)와 프로세스 내의 논리적 페이지 번호(P)를 담고 있게 된다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;807&quot; data-origin-height=&quot;525&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EX2ct/btrlCzJka9z/NbVQGD2WWFPTQ8wnL2LsRk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EX2ct/btrlCzJka9z/NbVQGD2WWFPTQ8wnL2LsRk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EX2ct/btrlCzJka9z/NbVQGD2WWFPTQ8wnL2LsRk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEX2ct%2FbtrlCzJka9z%2FNbVQGD2WWFPTQ8wnL2LsRk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;742&quot; height=&quot;483&quot; data-origin-width=&quot;807&quot; data-origin-height=&quot;525&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;역페이지 테이블을 사용하기 위해 모든 페이지를 탐색해야 하므로 시간적으로 손해를 보게 된다. 이를 해결하기위해 역페이지 테이블은 병렬 탐색을 가능하게 하는 연관 레지스터를 사용하여 시간적 효율성을 높이게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;공유 페이지&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;공유 페이지란 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;공유 코드를 담고 있는 페이지&lt;/b&gt;&lt;/span&gt;를 말한다. 공유 페이지는 여러 프로세스에 의해 공유되는 페이지이므로 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;물리적 메모리에 하나만 적재되어 메모리를 좀 더 효율적으로 사용&lt;/b&gt;&lt;/span&gt;할 수 있게 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;메모리 보호&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;페이지 테이블에는 주소 변환을 위한 정보 뿐만 아니라 메모리 보호를 위한 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;보호비트(protection bit)&lt;/b&gt;&lt;/span&gt;와 &lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;&lt;b&gt;유효 무효 비트(valid-invalid bit)&lt;/b&gt;&lt;/span&gt;를 두고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;보호비트(protection bit)&lt;/b&gt;&lt;/span&gt;는 각 페이지에 대한 접근 권한의 내용을 담고 있다. 각 페이지에 대한 접근을 허용하는지의 정보가 보호비트에 저장된다. 다시 말해 각 페이지에 대한 읽기/쓰기 등의 접근 권한을 설정하는 데에 사용된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #ffc1c8;&quot;&gt;&lt;b&gt; 유효 무효 비트(valid-invalid bit)&lt;/b&gt;&lt;/span&gt;는 해당 페이지의 내용이 유효한지에 대한 내용을 담고 있다. '유효'로 설정되어 있으면 메모리에 해당 페이지가 존재함을 뜻하며, '무효'일 경우 프로세스가 주소 부분을 사용하지 않거나, 해당 페이지가 백킹스토어에 존재하여 접근 권한이 없다는 의미로 사용된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Post&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-ke-size=&quot;size23&quot;&gt;&lt;a href=&quot;https://zangzangs.tistory.com/134&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[OS] 메모리 불연속할당 - (1) 페이징 기법&lt;/a&gt;&lt;/li&gt;
&lt;li data-ke-size=&quot;size23&quot;&gt;&lt;a href=&quot;https://zangzangs.tistory.com/140&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[OS] 메모리 불연속할당 - (2) 세그먼테이션&lt;/a&gt;&lt;/li&gt;
&lt;li data-ke-size=&quot;size23&quot;&gt;&lt;a href=&quot;https://zangzangs.tistory.com/141&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[OS] 메모리 불연속할당 - (3) 페이지드 세그먼테이션&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;References&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;KOCW 운영체제 강의 - 반효경 교수&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignCenter&quot; data-emoticon-type=&quot;niniz&quot; data-emoticon-name=&quot;012&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘못된 코드나 내용이 있다면 댓글을 남겨주세요. 즉시 수정하도록 하겠습니다! :)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>OS</category>
      <category>OS</category>
      <category>TLB</category>
      <category>메모리</category>
      <category>역페이지</category>
      <category>운영체제</category>
      <category>테이블</category>
      <category>페이지</category>
      <category>페이징</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/134</guid>
      <comments>https://zangzangs.tistory.com/134#entry134comment</comments>
      <pubDate>Tue, 30 Nov 2021 15:38:42 +0900</pubDate>
    </item>
    <item>
      <title>[OS] 메모리 연속할당 - 고정분할 방식과 가변분할 방식</title>
      <link>https://zangzangs.tistory.com/133</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;795&quot; data-origin-height=&quot;389&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfkwUR/btrlpKEgldC/SgRSluDYG0i1ka4pTvySw1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfkwUR/btrlpKEgldC/SgRSluDYG0i1ka4pTvySw1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfkwUR/btrlpKEgldC/SgRSluDYG0i1ka4pTvySw1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfkwUR%2FbtrlpKEgldC%2FSgRSluDYG0i1ka4pTvySw1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;507&quot; height=&quot;248&quot; data-origin-width=&quot;795&quot; data-origin-height=&quot;389&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;[OS]&amp;nbsp;메모리&amp;nbsp;연속할당&amp;nbsp;-&amp;nbsp;고정분할&amp;nbsp;방식과&amp;nbsp;가변분할&amp;nbsp;방식&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;안녕하세요? 장장스입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;실제 물리적 메모리는 크게 &lt;b&gt;연속할당 방식&lt;/b&gt;과 &lt;b&gt;불연속할당 방식&lt;/b&gt;으로 나뉩니다.&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;오늘은 메모리 연속할당 방식인 &lt;b&gt;고정분할 방식&lt;/b&gt;과 &lt;b&gt;가변분할 방식&lt;/b&gt;에 대해 정리해보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;메모리 연속할당 기법&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;연속할당 기법은 프로세스를 메모리에 올릴 때 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;주소 공간을 메모리의 한 곳에 연속적으로 적재하는 방식입니다. 연속 할당 방식에서는 물리적 메모리를 다수의 분할로 나누어 하나의 분할에 하나의 프로세스가 적재되도록 합니다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;연속할당 기법은 크게 &lt;b&gt;고정분할 방식&lt;/b&gt;과 &lt;b&gt;가변분할 방식&lt;/b&gt;으로 나뉩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;고정분할 방식&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;고정분할 방식은 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;물리적 메모리를 정해진 개수만큼의 영구적인 분할로 나누어두고 각 분할에 하나의 프로세스를 적재하는 방식입니다. 분할의 크기는 모두 동일할 수도 있고 서로 다를 수도 있습니다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;고정분할 방식은 동시에 메모리에 올릴 수 있는 프로그램의 수가 고정되어 있으며 수행 가능한 프로그램의 최대 크기 또한 제한된다는 점에서 가변분할 방식에 비해 융통성이 떨어집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;또한 고정분할 방식에는 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;외부조각과 내부조각 문제&lt;/b&gt;&lt;/span&gt;가 발생할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;422&quot; data-origin-height=&quot;390&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qlyrs/btrlAta1CQ1/6lk7YTP3GUKdwkDlmWXQPk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qlyrs/btrlAta1CQ1/6lk7YTP3GUKdwkDlmWXQPk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qlyrs/btrlAta1CQ1/6lk7YTP3GUKdwkDlmWXQPk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fqlyrs%2FbtrlAta1CQ1%2F6lk7YTP3GUKdwkDlmWXQPk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;422&quot; height=&quot;390&quot; data-origin-width=&quot;422&quot; data-origin-height=&quot;390&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;가변분할 방식&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;가변분할 방식은 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;메모리에 적재되는 프로그램의 크기에 따라 분할의 크기, 개수가 동적으로 변하는 방식이다.&lt;/b&gt;&lt;/span&gt; 따라서 가변분할 방식은 프로그램의 크기를 고려해서 메모리를 할당하고 이를 기술적으로 관리할 수 있는 기법이 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;가변분할 방식은 프로세스에 딱 맞게 메모리 공간을 사용하기에 내부조각 문제는 발생하지 않는다. 그러나 사용중인 프로세스가 종료되어 메모리에 새로운 프로세스를 올릴 메모리 공간이 충분하지 않을 경우 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;외부 조각 문제&lt;/b&gt;&lt;/span&gt;가 발생한다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;364&quot; data-origin-height=&quot;358&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/sxYdS/btrlCN1ezvk/0TExthUbRxG3Qnuj7x74I1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/sxYdS/btrlCN1ezvk/0TExthUbRxG3Qnuj7x74I1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/sxYdS/btrlCN1ezvk/0TExthUbRxG3Qnuj7x74I1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FsxYdS%2FbtrlCN1ezvk%2F0TExthUbRxG3Qnuj7x74I1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;364&quot; height=&quot;358&quot; data-origin-width=&quot;364&quot; data-origin-height=&quot;358&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;가변분할 방식은 &lt;b&gt;어디 메모리 공간에 프로세스를 올려야 할지 결정해야하는 문제&lt;/b&gt;가 있다. 이를 해결하기 위한 기술적 방법으로 다음과 같이 3가지가 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;최초적합: 가장 먼저 나오는 가용 가능한 메모리 공간에 프로세스를 올리는 방법이다.&lt;/li&gt;
&lt;li&gt;최초적합: 가장 딱 맞는 메모리 공간을 찾아 프로세스를 올리는 방법이다.&lt;/li&gt;
&lt;li&gt;최초적합: 가장 큰 메모리 공간에 프로세스를 올리는 방법이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;가변분할 방식에서 발생하는 외부조각 문제를 해결하기 위한 방법으로 &lt;b&gt;컴팩션(compaction: 압축)&lt;/b&gt;방법이 있다. 물리적 메모리 중에서 사용중인 메모리 공간을 한쪽으로 몰고 가용 공간을 확보하는 방법이다. 메모리를 효율적으로 사용할 수 있는 측면에서는 좋은 선택이지만 수행중인 프로세스의 메모리 주소 공간을 이동시켜야 하므로 비용이 매우 많이 든다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Post&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;References&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;KOCW 운영체제 강의 - 반효경 교수&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignCenter&quot; data-emoticon-type=&quot;niniz&quot; data-emoticon-name=&quot;012&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘못된 코드나 내용이 있다면 댓글을 남겨주세요. 즉시 수정하도록 하겠습니다! :)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>OS</category>
      <category>OS</category>
      <category>가변분할</category>
      <category>고정분할</category>
      <category>메모리</category>
      <category>연속할당</category>
      <category>운영체제</category>
      <category>컴팩션</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/133</guid>
      <comments>https://zangzangs.tistory.com/133#entry133comment</comments>
      <pubDate>Sun, 28 Nov 2021 16:24:03 +0900</pubDate>
    </item>
    <item>
      <title>[백준] 2461 대표선수 #JAVA #투포인터</title>
      <link>https://zangzangs.tistory.com/139</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-filename=&quot;알고리즘.png&quot; data-origin-width=&quot;945&quot; data-origin-height=&quot;502&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ctDGIp/btrl3Kwlmd5/K03tkL7uhfPY6eCAgRcIu0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ctDGIp/btrl3Kwlmd5/K03tkL7uhfPY6eCAgRcIu0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ctDGIp/btrl3Kwlmd5/K03tkL7uhfPY6eCAgRcIu0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FctDGIp%2Fbtrl3Kwlmd5%2FK03tkL7uhfPY6eCAgRcIu0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;945&quot; height=&quot;502&quot; data-filename=&quot;알고리즘.png&quot; data-origin-width=&quot;945&quot; data-origin-height=&quot;502&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;[백준] 2461 대표선수 #JAVA #투포인터&lt;/h2&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;코드&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;pre id=&quot;code_1613404164341&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

public class Main {

	static int N,M;
	static int count[];
	
	public static void main(String[] args) throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		
		StringTokenizer st;
		
		st= new StringTokenizer(br.readLine());
		
		N = Integer.parseInt(st.nextToken());//학급
		M = Integer.parseInt(st.nextToken());//학급별 학생 수
		count = new int[N];
		
		List&amp;lt;int[]&amp;gt; student = new ArrayList&amp;lt;&amp;gt;();  
		
		for (int i = 0; i &amp;lt; N; i++) {
			st = new StringTokenizer(br.readLine());
			
			for (int j = 0; j &amp;lt; M; j++) {
				student.add(new int[] {i,Integer.parseInt(st.nextToken())}); //학급,능력치
			}
		}

		student.sort((a,b)-&amp;gt; a[1]-b[1]); // 능력치 순서로 정렬
		
		int lp = 0;
		int rp = 0;

		int diff= Integer.MAX_VALUE;
		
		while (lp &amp;lt; N*M-1 &amp;amp;&amp;amp; rp &amp;lt; N*M-1) {

			//모든 학급이 포함되도록 rp값 이동
			while (rp &amp;lt; N*M-1) {
				
				count[student.get(rp++)[0]]++;
				
				if(haveAllClass()) break;
			}
			
			//모든 학급이 포함되도록 lp값 이동
			while (count[student.get(lp)[0]]&amp;gt;1) {
				count[student.get(lp++)[0]]--;
			}

			//모든 학급 포함시 값 갱신
			if(haveAllClass()) {
				int min = Integer.MAX_VALUE;
				int max = Integer.MIN_VALUE;
				
				for (int i = lp; i &amp;lt; rp; i++) {
					min = Math.min(min, student.get(i)[1]);
					max = Math.max(max, student.get(i)[1]);
				}
				diff = Math.min(diff, max-min);
			}
			
			//lp 오른쪽으로 한칸 이동
			count[student.get(lp++)[0]]--;
			
		}
		System.out.println(diff);
		
	}

	private static boolean haveAllClass() { //모든 학급이 포함되었는지 확인하는 함수
		for (int cnt : count) {
			if(cnt == 0) return false;
		}
		
		return true;
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;풀이&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;능력치 순서대로 학생을 정렬한다. 이 때 학급의 정보를 확인 할 수 있어야 한다.&lt;/li&gt;
&lt;li&gt;투 포인터를 활용하여 모든 학급의 학생이 포함되는 연속된 범위를 찾아낸다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;해당 범위에서 최댓값-최솟값 이 최소가 되는 값을 갱신한다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;주의 사항&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;lp, rp 범위 주의&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘못된 코드나 내용이 있다면 댓글을 남겨주세요. 즉시 수정하도록 하겠습니다! :)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorithm Solving/BAEKJOON</category>
      <category>2461</category>
      <category>java</category>
      <category>대표 선수</category>
      <category>백준</category>
      <category>자바</category>
      <category>투포인터</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/139</guid>
      <comments>https://zangzangs.tistory.com/139#entry139comment</comments>
      <pubDate>Sat, 27 Nov 2021 08:01:46 +0900</pubDate>
    </item>
    <item>
      <title>[OS] 메모리 스왑(스와핑) #swap</title>
      <link>https://zangzangs.tistory.com/132</link>
      <description>&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;[OS] 메모리 스왑(스와핑) #swap&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;안녕하세요? 장장스입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;오늘은 메모리 스와핑에 대해 정리해보겠습니다!&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;스와핑 (swapping)&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;메모리에 올라온 프로세스의 주소 공간 전체를 디스크의 스왑 영역(swap area)에 일시적으로 내려놓는 것을 말한다.&lt;/b&gt;&lt;/span&gt; 이때 스왑 영역은 &lt;b&gt;백킹스토어(backing store)&lt;/b&gt;라고 부르며, 디스크 내에 파일 시스템과는 별도로 존재하는 일정 영역을 말한다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;잠깐&lt;/b&gt;❗&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;스와핑이라는 개념은 프로세스가 종료되어 그 주소 공간을 디스크로 내쫓는 것이 아니라, 특정한 이유로 수행 중인 프로세스의 주소 공간을 일시적으로 메모리에서 디스크로 내려놓는 것을 의미한다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;역할&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;그렇다면 스와핑의 역할은 무엇일까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;스와핑은 다중 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;프로그래밍의 정도(degree of multiprogramming)을 조절&lt;/b&gt;&lt;/span&gt;한다. 다시 말하면 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;메모리에 존재하는 프로세스의 수를 조절하는 것&lt;/b&gt;&lt;/span&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;너무 많은 프로그램에 메모리에 동시에 올라오게 되면 한정된 메모리의 양을 적게 사용하게 될 것이다. 이는 시스템의 성능을 크게 떨어뜨린다. 스와핑은 이러한 문제를 해결하기 위해 몇몇 프로그램을 통째로 디스크의 스왑 영역으로 보냄으로써 메모리에 있는 프로그램들에게 실행에 필요한 적절한 메모리 공간을 보장한다. 현재 메모리에 있는 프로그램이 충분히 실행되고 나면 디스크 영역에 보낸 프로그램을 스왑 인 시켜 다시 메모리에 올린다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;스와핑 과정&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;1. &lt;b&gt;스와퍼(swapper)&lt;/b&gt;라고 불리는 &lt;b&gt;중기 스케줄러&lt;/b&gt;에 의해 스왑 아웃시킬 프로세스를 선택한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;(중기 스케줄러는 메모리에 적재된 프로세스의 수를 동적으로 조절하기 위한 스케줄러이다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;2. 스와퍼가 선택한 프로세스에게 할당된 메모리 주소 공간을 통째로 빼앗아 디스크의 스왑 영역으로 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;스왑 아웃(swap out)&lt;/b&gt;&lt;/span&gt;시킨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;3. 여유가 생긴 메모리 공간에 필요한 프로세스의 메모리 주소 공간을 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;스왑 인(swap in)&lt;/b&gt;&lt;/span&gt; 시킨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;882&quot; data-origin-height=&quot;762&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PGyDP/btrlDe4Al2f/6p1JHJx2LPzGURRLYvcrJk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PGyDP/btrlDe4Al2f/6p1JHJx2LPzGURRLYvcrJk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PGyDP/btrlDe4Al2f/6p1JHJx2LPzGURRLYvcrJk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPGyDP%2FbtrlDe4Al2f%2F6p1JHJx2LPzGURRLYvcrJk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;450&quot; height=&quot;389&quot; data-origin-width=&quot;882&quot; data-origin-height=&quot;762&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Post&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;References&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;[KOCW] 운영체제 강의 - 반효경 교수&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignCenter&quot; data-emoticon-type=&quot;niniz&quot; data-emoticon-name=&quot;012&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘못된 코드나 내용이 있다면 댓글을 남겨주세요. 즉시 수정하도록 하겠습니다! :)&lt;/b&gt;&lt;/p&gt;</description>
      <category>OS</category>
      <category>OS</category>
      <category>swap</category>
      <category>Swapping</category>
      <category>메모리</category>
      <category>스와핑</category>
      <category>스왑</category>
      <category>운영체제</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/132</guid>
      <comments>https://zangzangs.tistory.com/132#entry132comment</comments>
      <pubDate>Fri, 26 Nov 2021 09:59:39 +0900</pubDate>
    </item>
    <item>
      <title>[DB] 트랜잭션의 장애와 복구</title>
      <link>https://zangzangs.tistory.com/136</link>
      <description>&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;트랜잭션의&amp;nbsp;장애와&amp;nbsp;복구&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;트랜잭션 장애와 복구&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;트랜잭션 동작 시 장애가 발생하면 어떻게 해야 할까. 보통 로그를 통한 복구를 진행하게 된다. 복구 방법으로 REDO 복구와 UNDO 복구가 있다. DBMS는 어떻게 복구를 해야할지 판단한 후 REDO와 UNDO를 통해 복구를 진행하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;DBMS의 페이지 버퍼&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;데이터베이스 시스템은 보통 비휘발성 저장 장치인 디스크에 데이터를 저장하며 전체 데이터베이스의 일부분을 메인 메모리에 유지한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;DBMS는 데이터를 고정 길이의 페이지(page)로 저장하며, 디스크에서 읽거나 쓸 때에 페이지 단위로 입출력이 이루어진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;메인 메모리에 유지하는 페이지들을 관리하는 모듈을 보통&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;페이지 버퍼(page buffer)&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;관리자 또는 버퍼 관리자라고 부르는데, DBMS의 많은 주요 모듈 중에서 매우 중요한 모듈 중의 하나이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;438&quot; data-origin-height=&quot;268&quot;&gt;&lt;a href=&quot;https://d2.naver.com/helloworld/407507&quot; target=&quot;_blank&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cOfZnO/btrlYOrqfGI/5RynttcvqOxDcXr1XwyPg1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcOfZnO%2FbtrlYOrqfGI%2F5RynttcvqOxDcXr1XwyPg1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;438&quot; height=&quot;268&quot; data-origin-width=&quot;438&quot; data-origin-height=&quot;268&quot;/&gt;&lt;/a&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;DBMS는 각 제품마다 구조가 다르기는 하지만, 크게&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;질의 처리기(Query Processor)&lt;/b&gt;와&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;저장 시스템(Storage System)&lt;/b&gt;으로 나눠볼 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;UNDO의 필요성&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;오퍼레이션 수행 중에 수정된 페이지들이 버퍼 관리자의 버퍼 교체 알고리즘에 따라서 디스크에 출력될 수 있다. 다음과 같은 2가지 정책이 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;STEAL: 수정된 페이지를 언제든지 디스크에 쓸 수 있는 정책&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;✔️&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;-STEAL: 수정된 페이지들을 최소한 트랜잭션 종료 시점(EOT, End of Transaction)까지는 버퍼에 유지하는 정책&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;-STEAL 정책의 경우 트랜잭션 종료 전에 수정된 페이지들을 디스크에 쓰지 않는다면, 장애 발생 시 디스크 페이지에 반영되지 않아 로그 파일을 토대로 재실행 하여 해결 할 수 있다. 이 부분은 매력적이지만 이 정책은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;매우 큰 크기의 메모리 버퍼가 필요하다는 문제점&lt;/span&gt;&lt;/b&gt;을 가지고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;그렇다보니 대부분의 DBMS는 STEAL 버퍼 관리 정책을 선택한다. 트랜잭션 시 변경 사항을 로그에 기록하며, 디스크 페이지에 변경사항을 적용하게 된다. 즉 장애 발생으로 트랜잭션이 중단 되면&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;아직 완료되지 않은 트랜잭션이 수정한 페이지들도 디스크에 출력될 수 있는 문제가 생긴다.&lt;/span&gt;&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;이를 해결 하기 위해&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;해당 트랜잭션이 어떤 이유든 정상적으로 종료될 수 없게 되면 트랜잭션의 원자성(Atomicity)에 근거하여 변경한 페이지들은 원상 복구되어야 한다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;STEAL 정책은 수정된 페이지가 어떠한 시점에도 디스크에 써질 수 있기 때문에 장애 발생시 트랜잭션의 원자성을 해치게 된다.&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;위에서 말한 복구가&amp;nbsp;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;UNDO(뜻:원상태로 되돌리다)&lt;/b&gt;&lt;/span&gt;라고 한다.&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;UNDO복구는 UNDO로그를 역순으로 실행하여 원상태로 복구하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;REDO의 필요성&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;REDO 복구는 UNDO 복구의 반대 개념이다. 커밋한 트랜잭션의 수정은 어떤 경우에도 지속(durability)되어야 한다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;이미 커밋한 트랜잭션의 수정을 재반영하는 복구 작업을 REDO 복구&lt;/b&gt;&lt;/span&gt;라고 하는데, REDO 복구 역시 UNDO 복구와 마찬가지로 버퍼 관리 정책에 영향을 받는다. 트랜잭션이 종료되는 시점에 해당 트랜잭션이 수정한 페이지들을 디스크에도 쓸 것인가 여부로 두 가지 정책이 구분된다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;FORCE: 수정했던 모든 페이지를 트랜잭션 커밋 시점에 디스크에 반영하는 정책&lt;/li&gt;
&lt;li&gt;-FORCE: 수정했던 페이지를 트랜잭션 커밋 시점에 디스크에 반영하지 않는 정책&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;✔️&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;여기서 주의 깊게 봐야 할 부분은 -FORCE 정책이 수정했던 페이지(데이터)를 디스크에 반영하지 않는다는 점이다. (어떤 일들을 했었다고 하는 로그는 기록하게 되다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;FORCE 정책을 따르면 트랜잭션이 커밋되면 수정되었던 페이지들이 이미 디스크 상의 데이터베이스에 반영되었으므로 REDO 복구가 필요 없게 된다. 반면에 -FORCE 정책을 따른다면&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;커밋한 트랜잭션의 내용이 디스크 상의 데이터베이스 상에 반영되어 있지 않을 수 있기 때문에 반드시 REDO 복구가 필요&lt;/b&gt;&lt;/span&gt;하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;트랜잭션에 대한 로그가 모두 기록되었으나 트랜잭션이 완료 되는 순간 장애가 발생하는 경우 REDO복구를 통해 복구를 진행 할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignCenter&quot; data-emoticon-type=&quot;friends1&quot; data-emoticon-name=&quot;016&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/friends1/large/016.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/friends1/large/016.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size14&quot;&gt;(그러면 디스크 반영은 언제 하는 거쥬? 아시는 분 댓글 좀 ㅎㅎ.. )&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size14&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;로그&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #555555;&quot;&gt;UNDO 복구와 REDO 복구를 위해서 가장 널리 쓰이는 구조는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #555555;&quot;&gt;보편적으로 사용되는 기법은&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;로그(log)이다. DBMS에서 사용되는 3가지 로깅 방법이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;physicalstatelogging&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;물리적인 상태 로깅(physical state logging)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이 방법은 DBMS에서 가장 널리 쓰이는 기본적인 로깅 방법이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;갱신 이전 이미지와 이후 이미지를 모두 다 가지고 있으며, UNDO 복구 때에는 이전 이미지로 현재 이미지를 대체하며, REDO 복구 때에는 이후 이미지를 반영하는 방식으로 복구가 이루어진다. 물리적인 상태 로깅은 이전 이미지 혹은 이후 이미지로 단순히 대체하는 작업으로 이해하면 된다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;physicaltransitionlogging&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;물리적인 전이 로깅(physical transition logging)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이 방법은 페이지 혹은 레코드에 대해서 XOR 차이점을 기록하는 방식으로 이루어진다. 복구 시점에서 로그 레코드에 기록된 XOR 이미지와 레코드 이미지를 이용하여 UNDO 복구와 REDO 복구를 수행하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p id=&quot;logicaltransitionlogging&quot; data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;논리적인 전이 로깅(logical transition logging)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이 방법은 오퍼레이션 로깅(operation logging)으로도 불리는데, 어떤 일을 했었는가를 기록하는 방식이다. 예를 들어, a = a + 1과 같은 연산을 로깅할 때 이전 값 0, 이후 값 1을 물리적으로 기록할 수도 있고, a = a + 1 이라는 연산 그 자체를 기록할 수 있다. 이러한 논리적인 로그에 대한 복구 작업은 REDO를 위하여 로그 레코드에 기록된 오퍼레이션을 재수행하거나, UNDO를 위하여 역 오퍼레이션을 수행하는 방식으로 이루어진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Post&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-ke-size=&quot;size23&quot;&gt;&lt;a href=&quot;https://zangzangs.tistory.com/135&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2021.11.23 - [database/DB Concept] - [DB] 트랜잭션&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;References&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=ImvYNlF_saE&quot;&gt;https://www.youtube.com/watch?v=ImvYNlF_saE&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://d2.naver.com/helloworld/407507&quot;&gt;https://d2.naver.com/helloworld/407507&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>database/DB Concept</category>
      <category>db</category>
      <category>dbms</category>
      <category>redo</category>
      <category>undo</category>
      <category>데이터베이스</category>
      <category>로그</category>
      <category>복구</category>
      <category>장애</category>
      <category>트랜잭션</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/136</guid>
      <comments>https://zangzangs.tistory.com/136#entry136comment</comments>
      <pubDate>Thu, 25 Nov 2021 12:36:18 +0900</pubDate>
    </item>
    <item>
      <title>[OS] 주소 바인딩</title>
      <link>https://zangzangs.tistory.com/131</link>
      <description>&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;[OS] 주소 바인딩&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;안녕하세요? 장장스입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;오늘은 주소 바인딩에 대해 정리해보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;주소 바인딩&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #222426;&quot;&gt;프로그램이 메모리에 적재되면 해당 프로세스의 독자적인 주소 공간이 생성됩니다. 이 주소를 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;논리적 주소(logical address)&lt;/b&gt;&lt;/span&gt; 혹은 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;가상 주소(virtual address&lt;/span&gt;)&lt;/b&gt;라고 합니다. 논리적 주소는 프로세스마다 독립적으로 할당되며 0부터 시작합니다. &lt;/span&gt;&lt;span style=&quot;color: #222426;&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;물리적 주소(physical address)&lt;/b&gt;&lt;/span&gt;는 실제 &lt;span style=&quot;color: #222426;&quot;&gt;물리적 메모리에&lt;span&gt; &lt;/span&gt;&lt;/span&gt;올라가는 위치를 말합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #222426;&quot;&gt;CPU가 기계어 명령을 수행하기 위해 논리적 주소를 통해 메모리 참조를 하게 되면 해당 논리적 주소가 물리적 메모리의 어느 위치에 매핑되는지 확인해야 합니다. 이렇게 &lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;프로세스의 논리적 주소를 물리적 메모리 주소로 연결시켜주는 작업&lt;/span&gt;&lt;/b&gt;을 '&lt;b&gt;주소 바인딩&lt;/b&gt;'이라고 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #222426;&quot;&gt;주소 바인딩의 방식은 물리적 메모리 주소가 결정되는 시기에 따라 3가지로 나뉜다.&lt;/span&gt;&lt;span style=&quot;color: #222426;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;주소 바인딩 방법 3가지&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;컴파일 타임 바인딩 (compile time binding)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;컴파일을 하는 시점에 해당 프로그램이 물리적 메모리의 몇 번지에 위치할 것인지를 결정한다.&lt;/span&gt;&amp;nbsp;절대코드를 생성하는 바인딩이라고도 부른다. 물리적인 메모리 위치를 변경하려면 컴파일을 다시해야한다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;로드 타임 바인딩 (load time binding)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;프로그램의 실행이 시작될 때에 물리적 메모리 주소를 결정한다.&lt;/span&gt; 로드 타임 바인딩 방식에서는 로더(loader)의 책임하에 물리적 메모리 주소가 부여되며 프로그램이 종료될 때까지 물리적 메모리상의 위치가 고정된다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;실행시간 바인딩 (run time binding)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;프로그램이 실행을 시작한 후에도 그 프로그램이 위치한 물리적 메모리상의 주소가 변경될 수 있는 바인딩 방식&lt;/span&gt;이다. CPU가 메모리 주소를 참조하기 위해 주소 매핑 테이블을 이용해 바인딩을 점검한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;실행시간 바인딩을 사용하기 위해 &lt;b&gt;기준 레지스터(base register), 한계 레지스터(limit register), MMU(Memory Management Unit)&lt;/b&gt;와 같은 하드웨어를 이용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;858&quot; data-origin-height=&quot;419&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1Z1qc/btrlzOqXesE/TUoOHJ7KerpWoEsWNJjPaK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1Z1qc/btrlzOqXesE/TUoOHJ7KerpWoEsWNJjPaK/img.png&quot; data-alt=&quot;MMU의 물리적 주소 계산&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1Z1qc/btrlzOqXesE/TUoOHJ7KerpWoEsWNJjPaK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1Z1qc%2FbtrlzOqXesE%2FTUoOHJ7KerpWoEsWNJjPaK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;729&quot; height=&quot;356&quot; data-origin-width=&quot;858&quot; data-origin-height=&quot;419&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;MMU의 물리적 주소 계산&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;사진처럼 &lt;b&gt;MMU&lt;/b&gt;는 기준 레지스터에 논리적 주소를 더해 실제 물리적 주소값을 얻어내는 하드웨어다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;예를 들어 기준 레지스터의 값이 17000일 때 논리적 주소가 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;186&lt;/b&gt;&lt;/span&gt;이라면 물리적 주소는 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;17186&lt;/b&gt;&lt;/span&gt;이 된다. 이때 물리적 메모리의 시작 위치인 기준 레지스터를 &lt;b&gt;재배치 레지스터(relocation register)&lt;/b&gt; 라고도 부른다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;한계 레지스터&lt;/b&gt;는 현재 수행중인 프로세스의 논리적 주소의 최댓값으로 프로세스의 크기를 담고 있다. 또 한계 레지스터는 프로세스가 자신의 주소 공간을 넘어서는 메모리를 참조하려고 하는지 체크하여 메모리 보안을 이루는 용도로 사용된다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;프로세스 주소를 넘어서는 메모리를 참조하려고 하면 어떻게 될까❓&lt;/b&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt;다른 프로세스를 메모리를 침범하게 된다. 뿐만 아니라 운영체제가 존재하는 메모리 영역을 변경하여 시스템에 심각한 영향을 끼칠 수 있다.&lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;References&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;KOCW 운영체제 강의 - 반효경 교수&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignCenter&quot; data-emoticon-type=&quot;niniz&quot; data-emoticon-name=&quot;012&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘못된 코드나 내용이 있다면 댓글을 남겨주세요. 즉시 수정하도록 하겠습니다! :)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>OS</category>
      <category>MMU</category>
      <category>OS</category>
      <category>바인딩</category>
      <category>운영체제</category>
      <category>주소</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/131</guid>
      <comments>https://zangzangs.tistory.com/131#entry131comment</comments>
      <pubDate>Wed, 24 Nov 2021 09:58:05 +0900</pubDate>
    </item>
    <item>
      <title>[DB] 트랜잭션</title>
      <link>https://zangzangs.tistory.com/135</link>
      <description>&lt;pre id=&quot;code_1703327987945&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# A친구의 통장 잔액은 300,000원 일때,
UPDATE account
SET balance = balance - 500000
WHERE name = 'A';&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;790&quot; data-origin-height=&quot;323&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/N1BuN/btrlZvEUQ15/3ZiB8MgkboNHxyn0W6L5W1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/N1BuN/btrlZvEUQ15/3ZiB8MgkboNHxyn0W6L5W1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/N1BuN/btrlZvEUQ15/3ZiB8MgkboNHxyn0W6L5W1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FN1BuN%2FbtrlZvEUQ15%2F3ZiB8MgkboNHxyn0W6L5W1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;433&quot; height=&quot;177&quot; data-origin-width=&quot;790&quot; data-origin-height=&quot;323&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;[DB]트랜잭션&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;트랜잭션이란&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;데이터베이스 트랜잭션&lt;/b&gt;은 일반적으로 데이터베이스의 모든 변경 사항을 나타냅니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;트랜잭션은 논리 또는 작업의 단일 단위이며 때로는 여러 작업으로 구성됩니다.&lt;span&gt;&amp;nbsp;&lt;/span&gt;데이터베이스의 일관된 모드에서 수행되는 모든 논리적 계산을 트랜잭션이라고 합니다.&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;트랜잭션은 왜 필요할까?&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;친구에게 빌린 돈 10,000원을 이체했습니다. 그런데 예기치 못한 오류가 발생해 버렸습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;제 계좌에서는 10,000원이 출금되어 나갔는데 친구 계좌에는 입금이 되지 않았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이러한 상황이 발생하지 않도록 중간에 거래가 실패하면 &lt;b&gt;처음의 상태로 되돌려야(rollback) &lt;/b&gt;합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;ACID&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;트랜잭션은&amp;nbsp; ACID라 불리는 특성이 있습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Atomicity(원자성)&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;트랜잭션 내의 &lt;b&gt;모든 명령은 반드시 모두 수행되어야 하며, 오류가 발생하면 트랜잭션 전부가 취소&lt;/b&gt;되어야 한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1703326733270&quot; class=&quot;sql&quot; data-ke-language=&quot;sql&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;------------------------------
START TRANSACTION;
------------------------------


------------------------------
#1.A의 통장에서 10,000원을 차감한다.
UPDATE account
SET balance = balance - 10000
WHERE name = 'A';
------------------------------


------------------------------
#2. B의 통장에서 10,000원을 받는다.
UPDATE account
SET balance = balance + 10000
WHERE name = 'B';
------------------------------


------------------------------
COMMIT;
------------------------------&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;친구A가 친구B에게 10,000원을 송금한다고 생각해 보면, &lt;/span&gt;#1.A의 통장에서 10,000원을 차감한다.&amp;nbsp; #2.B의 통장에서 10,000원을 받는다 모두 성공해야만 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;트랜잭션이 내에서  SQL이 단하나라도 실패했으면 트랜잭션 내의 SQL은 모두 취소(rollback)되어야 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;즉, 트랜잭션 내에서의 모든 작업이 성공하거나, 실패해야만 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Consistency(일관성)&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;트랜잭션이 그 실행을 성공적으로 &lt;b&gt;완료하면 언제나 일관성 있는 데이터베이스 상태로 유지하는 것&lt;/b&gt;을 말한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;계좌 잔액 칼럼에는 잔액이 0원 이상이여야 한다는 룰이 걸려 있습니다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;A친구가 500,000원을 이체하려고 하는데, 실제 통장에는 300,000원 뿐입니다.&lt;span&gt;&amp;nbsp; 500,000원을 뺴니 잔액이 마이너스가 되며&amp;nbsp; 잔액에 0원 이상이여야 한다는 룰을 위반하게 됩니다. &lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000; text-align: start;&quot;&gt;&lt;span&gt;DBMS는 룰을 위반했으므로 트랙잭션을 취소합니다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Isolation(독립성,격리성)&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;트랜잭션 여러개가 병행 실행되는 경우 어느 하나의 &lt;b&gt;트랜잭션 실행중에 다른 트랜잭션의 연산이 끼어들지 못하도록 보장&lt;/b&gt;한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;10,000원을 이체하는 동시에 친구가 점심 밥 값으로 8,000원을 이체하고 있습니다. 두 개의 트랜잭션은 서로 다른 트랙잭션이므로 각각 동작해야 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Durablility(영속성,지속성)&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;성공적으로 수행된 트랜잭션은 영구적으로 반영되어야 한다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Post&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://zangzangs.tistory.com/167&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2022.01.31 - &lt;/a&gt;&lt;a href=&quot;https://zangzangs.tistory.com/136&quot;&gt;[database/DB Concept]&lt;/a&gt;&lt;a href=&quot;https://zangzangs.tistory.com/167&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt; - [DB] 트랜잭션 격리수준 (Isolation Level)&lt;/a&gt;&lt;/li&gt;
&lt;li data-ke-size=&quot;size23&quot;&gt;&lt;a href=&quot;https://zangzangs.tistory.com/136&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2021.11.25 - [database/DB Concept] - [DB] 트랜잭션의 장애와 복구&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;References&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=ImvYNlF_saE&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://www.youtube.com/watch?v=ImvYNlF_saE&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://d2.naver.com/helloworld/407507&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://d2.naver.com/helloworld/407507&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignCenter&quot; data-emoticon-type=&quot;niniz&quot; data-emoticon-name=&quot;012&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘못된 코드나 내용이 있다면 댓글을 남겨주세요. 즉시 수정하도록 하겠습니다! :)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>database/DB Concept</category>
      <category>ACID</category>
      <category>db</category>
      <category>dbms</category>
      <category>데이터베이스</category>
      <category>트랜잭션</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/135</guid>
      <comments>https://zangzangs.tistory.com/135#entry135comment</comments>
      <pubDate>Tue, 23 Nov 2021 19:25:31 +0900</pubDate>
    </item>
    <item>
      <title>[OS] CPU 스케줄링</title>
      <link>https://zangzangs.tistory.com/129</link>
      <description>&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;615&quot; data-origin-height=&quot;512&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RdRLg/btrlbEp0zKO/6nkK5jdr7ahdaPekodkfEk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RdRLg/btrlbEp0zKO/6nkK5jdr7ahdaPekodkfEk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RdRLg/btrlbEp0zKO/6nkK5jdr7ahdaPekodkfEk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRdRLg%2FbtrlbEp0zKO%2F6nkK5jdr7ahdaPekodkfEk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;615&quot; height=&quot;512&quot; data-origin-width=&quot;615&quot; data-origin-height=&quot;512&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;CPU 스케줄링&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;안녕하세요? 장장스입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;오늘은 CPU 스케줄링을 정리해 볼게요!&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;CPU 스케줄러&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;CPU 스케줄러는 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;준비(ready) 상태에 있는 프로세스들 중 어떠한 프로세스에게 CPU를 할당할지 결정하는 운영체제의 코드&lt;/b&gt;&lt;/span&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;&lt;u&gt;&lt;i&gt;그렇다면 CPU 스케줄러는 어떻게 작동할까요&lt;/i&gt;&lt;/u&gt;&lt;/b&gt;&lt;/span&gt;❓&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;프로세스가 CPU를 할당 받고 기계어 명령을 수행하다가 타이머 인터럽트가 발생하면 CPU 스케줄러가 호출됩니다. 그러면 CPU 스케줄러는&lt;b&gt; 준비 큐(ready queue)에서 CPU를 기다리는 프로세스 중 하나를 선택해 CPU를 할당&lt;/b&gt;하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;위와 같은 경우 말고도 CPU 스케줄링이 필요한 다양한 경우들이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1.&lt;/b&gt; 실행(run)상태에 있던 프로세스가 I/O 요청 등에 의에 봉쇄(blocked)상태로 바뀌는 경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2.&lt;/b&gt; 실행(run)상태에 있던 프로세스가 타이머 인터럽트 발생에 의해 준비(ready)상태로 바뀌는 경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;3.&lt;/b&gt; I/O 요청으로 봉쇄(blocked)상태에 있던 프로세스가 I/O 작업이 완료되어 인터럽트가 발생하고 준비(ready)상태로 바뀌는 경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;4.&lt;/b&gt; CPU에서 실행(run)상태에 있는 프로세스가 종료되는 경우&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;비선점형(non&lt;b&gt;preemptive) VS &lt;b&gt;선점형(preemptive)&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;CPU 스케줄링 방식에는 2가지 방식이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;비선점형 방식(nonpreemptive)&lt;/b&gt;&lt;/span&gt;은 CPU를 획득한 프로세스가 스스로 CPU를 반납하기 전까지 CPU를 빼앗기지 않는 방법입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;선점형 방식(preemptive)&lt;/b&gt;&lt;/span&gt;은 프로세스가 CPU를 계속 사용하기를 원하더라도 강제로 빼앗을 수 있는 스케줄링 방법입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;디스패처 (dispathcer)&amp;nbsp;&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;CPU 스케줄러가 다음 프로세스에게 CPU를 할당해야 할지 결정되면 실제로 CPU를 이양하는 작업이 필요합니다. 이러한 작업을 도와주는 운영체제의 코드를 &lt;b&gt;디스패처(dispathcer)&lt;/b&gt;라고 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;디스패처는 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;현재 수행중이던 프로세스의 문맥(context)을 PCB에 저장하고, 새로운 프로세스의 문맥(context)를 새로운 프로세스의 PCB로부터 복원 후 해당 프로세스에게 CPU를 넘기는 과정&lt;/b&gt;&lt;/span&gt;을 수행합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;스케줄링 알고리즘&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(1) 선입선출 스케줄링 (FCFS)&lt;/span&gt; &lt;span style=&quot;color: #006dd7;&quot;&gt;[비선점]&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;선입선출(First-Come First-Served)&lt;/b&gt; 스케줄링은 프로세스가 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;준비 큐에 도착한 순서대로 CPU를 할당하는 방식&lt;/b&gt;&lt;/span&gt;을 말한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;먼저 온 요청을 먼저 처리하기 때문에 매우 합리적인 스케줄링 방식인 것 같지만 경우에 따라 비효율적인 결과를 초래하기도 한다. CPU 버스트가 긴CPU 사용 시간이 긴 작업) 프로세스 하나가 CPU 버스트가 짧은 프로세스 여러개보다 먼저 도착했다고 하자. 앞서 도착한 프로세스의 오랜 작업시간 동안 뒤에 있는 짧은 작업시간의 프로세스가 &lt;u&gt;&lt;b&gt;오랜 대기시간을 기다려야 하는 문제&lt;/b&gt;&lt;/u&gt;가 발생할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이처럼 FCFS 스케줄링 알고리즘은 먼저 도착한 프로세스의 성격에 따라 평균 대기시간이 크게 달라 질 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;(2) 최단작업 우선 스케줄링 (SJF)&lt;/span&gt; &lt;span style=&quot;color: #006dd7;&quot;&gt;[비선점]&lt;/span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;[선점]&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;최단작업 우선(Shortest-Job First)&lt;/b&gt; 스케줄링 알고리즘은 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;CPU 버스트가 가장 짧은 프로세스에게 제일 먼저 CPU를 할당하는 방식&lt;/b&gt;&lt;/span&gt;이다. 최단작업 우선 스케줄링(SJF)는 평균 대기시간을 가장 짧게 하는 최적 알고리즘으로 알려져 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;비선점형 방식&lt;/b&gt;&lt;/span&gt; 구현은 현재 작업중인 프로세스가 CPU를 할당받아 작업중일 때 CPU 버스트가 짧은 &lt;span style=&quot;color: #000000;&quot;&gt;요청이 새로 들어와도 해당 프로세스의 작업이 끝날 때까지 CPU를 반납하지 않는 방식이다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;선점형 방식&lt;/b&gt;&lt;/span&gt; 구현은 &lt;/span&gt;&lt;span style=&quot;color: #000000; font-size: 1.12em; letter-spacing: 0px;&quot;&gt;현재 작업중인 프로세스에게 CPU를 할당했다 하더라도 새로 들어온 요청의 CPU 버스트가 더 짧을 경우 CPU를 빼앗아 더 짧은 프로세스에게 부여하는 방식이다. 이러한 SJF의 선점형 구현방식을 SRTF(Shortest Remaining Time First)라고도 부른다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;SJF 스케줄링은 다음과 같은 문제점이 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;1. 프로세스의 CPU 버스트 시간을 미리 알 수 없다는 점&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;2.&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;&lt;span style=&quot;color: #ee2323;&quot;&gt;기아 현상(starvation)&lt;/span&gt; 문제&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;b&gt;CPU 버스트가 짧은 프로세스에게만 CPU를 할당하게 되면 CPU 버스트가 긴 프로세스는 준비 큐에 서서 무한정 기다리는 문제가 발생&lt;/b&gt;한다. 최악의 경우 영원히 CPU를 할당 받지 못할 수도 있다. &lt;span style=&quot;color: #000000;&quot;&gt;이는 SJF의 심각한 문제점이다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;(3) 우선순위 스케줄링 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;[비선점]&lt;/span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;[선점]&lt;/span&gt;&lt;/b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;우선순위(priority)&lt;/b&gt; 스케줄링이란 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;준비 큐에서 기다리는 프로세스들 중에서 우선순위가 가장 높은 프로세스에게 제일 먼저 CPU를 할당하는 방식&lt;/b&gt;&lt;/span&gt;을 말한다. 우선순위는 우선순위값을 통해 결정되며 우선순위값이 작을수록 높은 우선순위를 가지는 것으로 가정한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;현재 CPU에서 수행 중인 프로세스보다 우선순위가 높은 프로세스가 도착하여 CPU를 선점하게 되면 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;선점형 방식&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 되고, 이와 달리 CPU를 자진 반납하기 까지 기다리게 되면 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;비선점형 방식&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이 된다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;우선순위 스케줄링에도 &lt;span style=&quot;color: #ee2323;&quot;&gt;기아 현상(starvation)&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;문제가 발생한다. 이를 해결하기 위해 노화(aging) 기법을 사용할 수 있다. 대기 시간이 길어지는 프로세스의 우선순위를 조금씩 높여 CPU를 할당 받을 수 있게 해주는 것이다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;(4) 라운드 로빈 스케줄링 &lt;b&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;[선점]&lt;/span&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;라운드 로빈(Round Robin)&lt;/b&gt; 스케줄링은 시분할 시스템의 성질을 가장 잘 활용한 스케줄링 방식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;각 프로세스가 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;CPU를 연속적으로 사용할 수 있는 &lt;b&gt;특정 &lt;/b&gt;시간인 '할당시간(time quantum)'으로 제한하고,&amp;nbsp; 할당시간이 경과되면 해당 프로세스로부터 CPU를 회수해 준비 큐에 줄 서 있는 다른 프로세스에게 CPU를 할당하는 방식&lt;/b&gt;&lt;/span&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;할당시간이 너무 짧으면&lt;/b&gt; 문맥교환(context switching)이 빈번하여 오버헤드가 커지고, &lt;b&gt;할당시간이 너무 길면&lt;/b&gt; FCFS와 같은 결과가 나오게 된다. 즉, 적정 할당시간을 설정하는 것이 중요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;라운드 로빈 스케줄링은 대기 중인 모든 프로세스에게 CPU를 번갈아가며 할당할 수 있기에 대화형 프로세스의 빠른 응답시간을 보장할 수 있다는 장점이 있다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;(5) 멀티레벨 큐 &lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;[선점]&lt;/span&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;멀티레벨 큐(multi-level queue)&lt;/b&gt; 스케줄링은 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;준비 큐를 여러개로 분할해 관리하는 스케줄링 기법&lt;/b&gt;&lt;/span&gt;을 말한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;쉽게 말하면 CPU를 사용하기 위해 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;한 줄서기가 아니라 여러 줄로 서는 것&lt;/b&gt;&lt;/span&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;589&quot; data-origin-height=&quot;471&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Il9md/btrliNTkK31/BKn9kBCLRm3ReERW2nq0F0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Il9md/btrliNTkK31/BKn9kBCLRm3ReERW2nq0F0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Il9md/btrliNTkK31/BKn9kBCLRm3ReERW2nq0F0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIl9md%2FbtrliNTkK31%2FBKn9kBCLRm3ReERW2nq0F0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;589&quot; height=&quot;471&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;589&quot; data-origin-height=&quot;471&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;일반적으로 멀티레벨 큐에서는 대화형 작업을 담기 위한 &lt;b&gt;전위 큐(foreground queue)&lt;/b&gt;와 계산 위주의 작업을 담기 위한 &lt;b&gt;후위 큐(background queue)&lt;/b&gt;로 분할하여 운영된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;전위 큐에서는 응답시간을 짧게 하기 위해 라운드 로빈 스케줄링을 사용하는 반면, 응답시간이 중요하지 않은 후위 큐에서는 FCFS 스케줄링 기법을 사용해 문맥교환(context switching) 오버헤드를 줄인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;멀티레벨 큐에는 또 다른 스케줄링이 필요하다. 바로 큐 자체에 대한 스케줄링이다. 우선순위가 높은 큐를 순서대로 처리하는 &lt;b&gt;고정 우선순위(fixed priority) &lt;/b&gt;방식이 있으며, &lt;span style=&quot;color: #ee2323;&quot;&gt;기아 현상(starvation)&lt;/span&gt;을 해결하기 위한 &lt;b&gt;타임 슬라이스(time slice)&lt;/b&gt; 방식도 있다. 타임 슬라이스 방식은 각 큐에 CPU 시간을 적절한 비율로 할당하는 방법이다. 예를 들어 전위큐에 80% 후위 큐에 20%를 할당해 스케줄링하는 방식이다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;(6) 멀티레벨 피드백 큐&lt;/b&gt; &lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;[선점]&lt;/span&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;멀티레벨 피드백 큐(Multilevel Feedback Queue)&lt;/b&gt;는 여러 큐에 줄을 세운다는 측면에서 멀티레벨 큐와 유사하나, &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;프로세스가 하나의 큐에서 다른 큐로 이동이 가능하다는 점&lt;/b&gt;&lt;/span&gt;이 다르다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;486&quot; data-origin-height=&quot;241&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cHNoHH/btrlgTfskDv/p4XVJlBrIdfdRTnWVV2dx1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cHNoHH/btrlgTfskDv/p4XVJlBrIdfdRTnWVV2dx1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cHNoHH/btrlgTfskDv/p4XVJlBrIdfdRTnWVV2dx1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcHNoHH%2FbtrlgTfskDv%2Fp4XVJlBrIdfdRTnWVV2dx1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;486&quot; height=&quot;241&quot; data-origin-width=&quot;486&quot; data-origin-height=&quot;241&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;그림에서 상위 2개의 큐는 각각 할당시간(Quantum)이 8과 16인 라운드 로빈 스케줄링을 사용한다. 세번 째 큐는 FCFS 스케줄링 기법을 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;1. 프로세스가 준비 큐에 도착하면 우선순위가 가장 높은 큐에 줄을 선다. (할당시간 8)&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;2. CPU 사용시간이 짧은 프로세스는 작업이 완료되고, 작업이 완료되지 않은 프로세스들은 할당시간이 16인 두번째 큐로 내려가서 줄을 선다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;3. 두번째 큐에서도 작업이 완료 되지 않으면 계산 위주의 프로세스로 간주되어 최하위 큐로 이동하고 FCFS 스케줄링을 적용 받는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;멀티레벨 피드백 큐는 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;상위 큐가 비었을 때 다음 하위 큐가 CPU를 할당 받는 구조&lt;/b&gt;&lt;/span&gt;이다. 이러한 방식은 라운드 로빈 스케줄링을 발전시켜 CPU 작업시간을 다단계로 분류함으로써 작업시간이 짧은 프로세스일수록 더욱 빠른 서비스가 가능하게 되고, 작업시간이 긴 프로세스에 대해서는 문맥교환 없이 CPU 작업에만 열중할 수 있는 FCFS 방식을 사용할 수 있게 한다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;(7) 다중처리기 스케줄링&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;현대의 CPU는 프로세스가 여러개인 다중처리기 시스템(multi-processor system)이다. 다중처리기 환경에서의 CPU 스케줄링은 CPU가 하나인 시스템보다 복잡한 문제가 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;1. 준비큐에 한줄로 세워 CPU가 알아서 프로세스를 꺼내어가도록 할 수 있다. 그러나 반드시 특정 CPU에서 수행되어야 하는 프로세스가 있는 경우라면 문제가 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;2. 각 CPU 별로 줄 세우기를 한다. 이러한 경우 특정 CPU에만 작업이 집중되는 현상이 발생할 수 있다. 따라서 다중 처리기 스케줄링에서는 이와 같은 현상을 방지하기 위한 &lt;b&gt;부하균형(load balancing)&lt;/b&gt; 매커니즘을 필요로 한다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;(8) 실시간 스케줄링&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;실시간 시스템에서는 각 작업마다 주어진 데드라인이 있어 정해진 데&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;드라인 안에 반드시 작업을 처리&lt;/b&gt;&lt;/span&gt;해야 한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;실시간 시스템은 데드라인(deadline)을 반드시 지켜야하는 &lt;b&gt;경성 실시간 시스템&lt;/b&gt;과 데드라인이 존재하기는 하지만 데드라인을 지키지 못했다고 해서 위험한 상황이 발생하지는 않는 &lt;b&gt;연성 실시간 시스템&lt;/b&gt;이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;실시간 환경에서의 스케줄링은 빠른 서비스도 중요하지만 데드라인을 지키는 것이 더욱 중요하다. 따라서 데드라인이 얼마 남지 않은 요청을 먼저 처리하는 EDF(Earlist Deadline First) 스케줄링을 널리 사용하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Post&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;References&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;http://www.kocw.or.kr/home/cview.do?cid=4b9cd4c7178db077&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;KOCW [운영체제] - 반효경 교수&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignCenter&quot; data-emoticon-type=&quot;niniz&quot; data-emoticon-name=&quot;012&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘못된 코드나 내용이 있다면 댓글을 남겨주세요. 즉시 수정하도록 하겠습니다! :)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>OS</category>
      <category>CPU</category>
      <category>CPU 스케줄링</category>
      <category>fcfs</category>
      <category>SJF</category>
      <category>라운드 로빈</category>
      <category>멀티레벨 큐</category>
      <category>멀티레벨 피드백 큐</category>
      <category>선입선출</category>
      <category>우선순위</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/129</guid>
      <comments>https://zangzangs.tistory.com/129#entry129comment</comments>
      <pubDate>Mon, 22 Nov 2021 09:56:57 +0900</pubDate>
    </item>
    <item>
      <title>[OS] 뮤텍스(Mutex) vs 세마포어(Semaphore)</title>
      <link>https://zangzangs.tistory.com/128</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;620&quot; data-origin-height=&quot;526&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bDvjzU/btrlfXhFGeC/lOSVCv2P0qUHY1BcMZMYtK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bDvjzU/btrlfXhFGeC/lOSVCv2P0qUHY1BcMZMYtK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bDvjzU/btrlfXhFGeC/lOSVCv2P0qUHY1BcMZMYtK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbDvjzU%2FbtrlfXhFGeC%2FlOSVCv2P0qUHY1BcMZMYtK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;620&quot; height=&quot;526&quot; data-origin-width=&quot;620&quot; data-origin-height=&quot;526&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;뮤텍스(Mutex)와 세마포어(Semaphore)&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;안녕하세요? 장장스입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;오늘은 기술면접에서 물어본다고 하는(?) 뮤텍스와 세마포어에 대해 정리하겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;언제 등장해?&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;span style=&quot;color: #ee2323; background-color: #f6e199;&quot;&gt;&lt;b&gt;&lt;a style=&quot;color: #ee2323; background-color: #f6e199;&quot; href=&quot;https://zangzangs.tistory.com/116&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;교착상태(deadlock)&lt;/a&gt;&lt;/b&gt;&lt;/span&gt;에 대해 들어보셨다면 이 글을 읽을 준비가 되신겁니다. 교착상태는 제한된 자원을 두고 프로세스나 스레드가 작업을 하지 않고 무한 대기에 빠지게 되는 것을 말합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;교착상태가 발생하기 위해서 다음과 같은 4가지 조건이 필요합니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;상호 배제&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;점유 대기&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;비선점&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;순환 대기&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;이 중 &lt;b&gt;상호 배제&lt;/b&gt; 조건을 해결하기 위한 방법이 &lt;b&gt;뮤텍스(Mutex)와 세마포어(Semaphore)&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;뮤텍스(Mutex)&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;뮤텍스는 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;mut&lt;/span&gt;ual&lt;/b&gt;과 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;ex&lt;/span&gt;clusion&lt;/b&gt;의 합성어로, 여러 스레드를 실행하는 환경에서 자원에 대한 접근에 제한을 강제하기 위한 동기화 매커니즘을 말합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;1. Boolean 타입의 Lock 변수를 사용하여 자원에 대한 접근을 제한합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;2. 임계영역(critical section)의 자원에 접근하면 해당 스레드는 Lock을 걸어버립니다. 이 때, 다른 스레드가 공유자원에 접근하면 Blocking 후 대기 큐로 보냅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;3. 공유자원 사용을 마친 스레드는 Lock을 해제합니다. Lock 해제는 Lock을 건 스레드만 해제할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;스핀락(SpinLock)&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;뮤텍스와 유사한 스핀락이라는 방법도 있습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;1. 뮤텍스와 달리 대기 큐를 갖지 않으며 Busy-waiting 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;2. Mutex-nonblocking 모델로 볼 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;세마포어(Semaphore)&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;세마포어는 변수를 통해 접근 가능한 스레드를 제한합니다. 뮤택스는 1개의 스레드만 자원을 사용할 수 있었으나 세마포어변수 만큼 공유 자원에 접근 할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;1. 세마포어 변수를 통해 wait, signal을 관리합니다 세마포어 변수는 0이상의 정수 값을 갖습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;2. 세마포어 변수가 1개인 경우 뮤텍스 처럼 사용이 가능합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;3. 뮤텍스와 달리 Lock을 걸지 않은 스레드도 signal을 보내 Lock을 해제 할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Post&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-ke-size=&quot;size23&quot;&gt;&lt;a href=&quot;https://zangzangs.tistory.com/116&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2021.08.16 - [OS] - [OS] 데드락 (Deadlock) - 교착상태&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;References&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=oazGbhBCOfU&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[10분 테코톡] 와일더의 Mutex vs Semaphore&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignCenter&quot; data-emoticon-type=&quot;niniz&quot; data-emoticon-name=&quot;012&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘못된 코드나 내용이 있다면 댓글을 남겨주세요. 즉시 수정하도록 하겠습니다! :)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>OS</category>
      <category>deadlock</category>
      <category>mutex</category>
      <category>semaphore</category>
      <category>교착상태</category>
      <category>데드락</category>
      <category>뮤텍스</category>
      <category>세마포어</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/128</guid>
      <comments>https://zangzangs.tistory.com/128#entry128comment</comments>
      <pubDate>Fri, 19 Nov 2021 18:36:04 +0900</pubDate>
    </item>
    <item>
      <title>[백준] 2143 두 배열의 합 #JAVA #이분탐색</title>
      <link>https://zangzangs.tistory.com/130</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthContent&quot; data-filename=&quot;알고리즘.png&quot; data-origin-width=&quot;945&quot; data-origin-height=&quot;502&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cAGHF4/btrlykjonpa/K5iEJFO4hbAS4Z4HgKKbpk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cAGHF4/btrlykjonpa/K5iEJFO4hbAS4Z4HgKKbpk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cAGHF4/btrlykjonpa/K5iEJFO4hbAS4Z4HgKKbpk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcAGHF4%2Fbtrlykjonpa%2FK5iEJFO4hbAS4Z4HgKKbpk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;945&quot; height=&quot;502&quot; data-filename=&quot;알고리즘.png&quot; data-origin-width=&quot;945&quot; data-origin-height=&quot;502&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;[백준] 2143 두 배열의 합 #JAVA&lt;/h2&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;코드&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;pre id=&quot;code_1613404164341&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.io.*;
import java.util.*;

public class Main {

	public static void main(String[] args) throws IOException{
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));

		int[] arrA, arrB;
		int[] subArrA, subArrB;
		StringTokenizer stA,stB;
		long total = 0; // 21억개를 초과하는 경우가 존재
		
		int T = Integer.parseInt(br.readLine());
		int N = Integer.parseInt(br.readLine());
		stA = new StringTokenizer(br.readLine());
		int M = Integer.parseInt(br.readLine());
		stB = new StringTokenizer(br.readLine());
		
		arrA = new int[N];
		arrB = new int[M];
				
		for (int i = 0; i &amp;lt; N; i++) {
			arrA[i] = Integer.parseInt(stA.nextToken());
		}
		for (int i = 0; i &amp;lt; M; i++) {
			arrB[i] = Integer.parseInt(stB.nextToken());
		}
		
		// 배열 A,B로 만들 수 있는 누적합 배열을 구한다.
		//배열 A로 만들 수 있는 누적합 배열 구하기
		int size = 0;
		int idx = 0;
		
		for (int i = 1; i &amp;lt;= N; i++) {
			size += i;
		}
		subArrA = new int[size];
		for (int i = 0; i &amp;lt; N; i++) {
			int sum=0;
			int at = i;
			while (at &amp;lt; N) {
				sum += arrA[at++];
				subArrA[idx++] = sum;
			}
		}
		
		//배열 B로 만들 수 있는 누적합 배열 구하기
		size = 0;
		idx = 0;
		for (int i = 1; i &amp;lt;= M; i++) {
			size += i;
		}
		subArrB = new int[size];
		for (int i = 0; i &amp;lt; M; i++) {
			int sum=0;
			int at = i;
			while (at &amp;lt; M) {
				sum += arrB[at++];
				subArrB[idx++] = sum;
			}
		}
		
		//Arrays.sort(subArrA);
		Arrays.sort(subArrB);
		

		//이분탐색
		for (int num : subArrA) {
			int tar = T - num; // 타겟 숫자
			
			//타겟 숫자의 왼쪽을 찾는다.			
			int left= lower_idx(tar ,subArrB);
            
			//타겟 숫자의 오른쪽을 찾는다.
			int right = upper_idx(tar ,subArrB);
			
			//total에 더한다.
			total +=(right - left);
			
		}
		
		System.out.println(total);
		
	}
	
	private static int lower_idx(int target, int[] arr) {
		
		int st = 0;
		int en = arr.length;
		
		while (st &amp;lt; en) {
			int mid = (st+en)/2;
			
			if(arr[mid] &amp;gt;= target) {
				en=mid;
			}else {
				st = mid+1;
			}
		}
		
		return st;
		
	}
	
	private static int upper_idx(int target, int[] arr) {
		
		int st = 0;
		int en = arr.length;
		
		while (st &amp;lt; en) {
			int mid = (st+en)/2;
			
			if(arr[mid] &amp;gt; target) {
				en=mid;
			}else {
				st = mid+1;
			}
		}
		
		return st;
	
	}
	
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;풀이&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;배열 A,B의 누적합 배열을 구한다. (-&amp;gt; &lt;b&gt;subArrA, subArrB&lt;/b&gt;)&lt;/li&gt;
&lt;li&gt;배열 &lt;b&gt;subArrA&lt;/b&gt;를 for문을 돌리며 배열&lt;b&gt;subArrB&lt;/b&gt; B = T-A 의 값이 있는지 이분탐색을 통해 확인한다.&lt;/li&gt;
&lt;li&gt;lower_idx와, upper_idx 를 통해 타겟에 맞는 값을 찾는다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;주의 사항&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;정답인 total 변수는 int가 아닌 long 변수이다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;배열 A,B는 최대 1000개의 값으로 각각 1000!개만큼의 부 배열이 나온다. (&lt;b&gt;subArrA, subArrB&lt;/b&gt;의 크기 500500)&lt;/li&gt;
&lt;li&gt;모든 배열이 쌍 개수가 맞는다고 하면 500500 X 500500으로 int 자료형의 개수인 21억개를 넘어간다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;반례&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;pre id=&quot;code_1637234841909&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#INPUT
5
3
1 5 3
2 
1 2

#OUTPUT
15&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘못된 코드나 내용이 있다면 댓글을 남겨주세요. 즉시 수정하도록 하겠습니다! :)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>Algorithm Solving/BAEKJOON</category>
      <category>2143</category>
      <category>java</category>
      <category>두 배열의 합</category>
      <category>백준</category>
      <category>이분탐색</category>
      <category>자바</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/130</guid>
      <comments>https://zangzangs.tistory.com/130#entry130comment</comments>
      <pubDate>Thu, 18 Nov 2021 20:39:09 +0900</pubDate>
    </item>
    <item>
      <title>[자료구조] 힙(heap) #java</title>
      <link>https://zangzangs.tistory.com/125</link>
      <description>&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;힙(heap) 자료구조&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;안녕하세요? 장장스입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;오늘은 힙자료구조에 대해 알아보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;힙 (heap)&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;힙은 최댓값 및 최솟값을 찾아내는 연산을 빠르게 하기 위해 고안된&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #99cefa;&quot;&gt;&lt;b&gt;완전이진트리를 기반으로 한 자료구조&lt;/b&gt;&lt;/span&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;힙에는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;최대 힙(max heap)&lt;/b&gt;과&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;최소 힙(min heap)&lt;/b&gt;이 있습니다. 부모 노드가 자식 노드보다 크면 최대 힙, 반대이면 최소 힙입니다. 가장 큰 숫자가 뿌리에 있게 하려면 최대 힙, 가장 작은 숫자로부터 시작하려면 최소 힙을 사용하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;최대 힙 (max heap)&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;max heap은 root에 가장 큰 값이 오는 heap 입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;605&quot; data-origin-height=&quot;384&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/m0sNz/btrk6PyD5gb/kksbjHTABBwpVSTzXlhjY0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/m0sNz/btrk6PyD5gb/kksbjHTABBwpVSTzXlhjY0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/m0sNz/btrk6PyD5gb/kksbjHTABBwpVSTzXlhjY0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fm0sNz%2Fbtrk6PyD5gb%2FkksbjHTABBwpVSTzXlhjY0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;605&quot; height=&quot;384&quot; data-origin-width=&quot;605&quot; data-origin-height=&quot;384&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;최소 힙 (min heap)&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;min heap은 root에 가장 작은 값이 오는 heap 입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;605&quot; data-origin-height=&quot;384&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bcTWza/btrlbD5pFr0/FKMS8uhMVXM91L7zwkQkBk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bcTWza/btrlbD5pFr0/FKMS8uhMVXM91L7zwkQkBk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bcTWza/btrlbD5pFr0/FKMS8uhMVXM91L7zwkQkBk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbcTWza%2FbtrlbD5pFr0%2FFKMS8uhMVXM91L7zwkQkBk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;605&quot; height=&quot;384&quot; data-origin-width=&quot;605&quot; data-origin-height=&quot;384&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;힙 추가&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;그렇다면 새로운 데이터를 추가하거나 제거는 어떻게 될까요? max heap, min heap의 규칙을 지키야 합니다. &lt;span style=&quot;background-color: #ffffff; color: #666666;&quot;&gt;최대 힙이면 부모 노드가 자식 노드보다 커야 하고 최소 힙은 자식 노드가 부모 노드보다 커야 합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;443&quot; data-origin-height=&quot;299&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bmPGCE/btrlfeRDubt/VZuKFO4UxoqEkFDMHLaOv0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bmPGCE/btrlfeRDubt/VZuKFO4UxoqEkFDMHLaOv0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bmPGCE/btrlfeRDubt/VZuKFO4UxoqEkFDMHLaOv0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbmPGCE%2FbtrlfeRDubt%2FVZuKFO4UxoqEkFDMHLaOv0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;443&quot; height=&quot;299&quot; data-origin-width=&quot;443&quot; data-origin-height=&quot;299&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 비어있는 공간에 노드를 추가합니다.&lt;br /&gt;2. 부모 노드보다 큰 숫자인지 확인하고 만약 그렇다면 두 노드를 바꿉니다. (trickle up)&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;힙 제거&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;505&quot; data-origin-height=&quot;304&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/yyqQw/btroPwhBzhY/WXZt03EkGCgabwidtjJtVk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/yyqQw/btroPwhBzhY/WXZt03EkGCgabwidtjJtVk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/yyqQw/btroPwhBzhY/WXZt03EkGCgabwidtjJtVk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FyyqQw%2FbtroPwhBzhY%2FWXZt03EkGCgabwidtjJtVk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;505&quot; height=&quot;304&quot; data-origin-width=&quot;505&quot; data-origin-height=&quot;304&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;432&quot; data-origin-height=&quot;349&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c7cjPV/btrlgSfYi0h/yLKXXVoTWYFLiRhbqNaaq0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c7cjPV/btrlgSfYi0h/yLKXXVoTWYFLiRhbqNaaq0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c7cjPV/btrlgSfYi0h/yLKXXVoTWYFLiRhbqNaaq0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc7cjPV%2FbtrlgSfYi0h%2FyLKXXVoTWYFLiRhbqNaaq0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;432&quot; height=&quot;349&quot; data-origin-width=&quot;432&quot; data-origin-height=&quot;349&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;443&quot; data-origin-height=&quot;323&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mxHXF/btrlfrwsRs3/SyQpSfXf1GGMvt53MTYzC1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mxHXF/btrlfrwsRs3/SyQpSfXf1GGMvt53MTYzC1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mxHXF/btrlfrwsRs3/SyQpSfXf1GGMvt53MTYzC1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmxHXF%2FbtrlfrwsRs3%2FSyQpSfXf1GGMvt53MTYzC1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;443&quot; height=&quot;323&quot; data-origin-width=&quot;443&quot; data-origin-height=&quot;323&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 루트를 제거합니다.&lt;br /&gt;2. 트리의 마지막 요소를 루트에 넣어줍니다.&lt;br /&gt;3. 루트에서 시작하여 두 자식 중 큰 노드와 바꿔주어 힙의 규칙을 만족하게 합니다.&amp;nbsp;(trickle down)&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;무언가를 제거할 때 힙에서는 항상 루트를 제거해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Post&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-ke-size=&quot;size23&quot;&gt;&lt;a href=&quot;https://zangzangs.tistory.com/127&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2021.11.16 - [DataStructures] - [자료구조] 트리(Tree)&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;References&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.boostcourse.org/cs204/lecture/626042&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[부스트코스] 자바로 구현하고 배우는 자료구조&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignCenter&quot; data-emoticon-type=&quot;niniz&quot; data-emoticon-name=&quot;012&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘못된 코드나 내용이 있다면 댓글을 남겨주세요. 즉시 수정하도록 하겠습니다! :)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>DataStructures</category>
      <category>Heap</category>
      <category>힙</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/125</guid>
      <comments>https://zangzangs.tistory.com/125#entry125comment</comments>
      <pubDate>Wed, 17 Nov 2021 17:51:23 +0900</pubDate>
    </item>
    <item>
      <title>[자료구조] 트리(Tree)</title>
      <link>https://zangzangs.tistory.com/127</link>
      <description>&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;트리(Tree)&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;안녕하세요? 장장스입니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;오늘은 Tree 자료구조에 대해 알아보겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;트리 (Tree)&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;962&quot; data-origin-height=&quot;623&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/peSfp/btrk8lc6BNh/kvDn7OBNYrMoMA8SKddk20/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/peSfp/btrk8lc6BNh/kvDn7OBNYrMoMA8SKddk20/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/peSfp/btrk8lc6BNh/kvDn7OBNYrMoMA8SKddk20/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpeSfp%2Fbtrk8lc6BNh%2FkvDn7OBNYrMoMA8SKddk20%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;660&quot; height=&quot;427&quot; data-origin-width=&quot;962&quot; data-origin-height=&quot;623&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;가계도처럼&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #99cefa;&quot;&gt;&lt;b&gt;노드를 나무 형태로 연결한 구조&lt;/b&gt;&lt;/span&gt;를 트리라고 합니다. 트리에 있는 각각의 요소는 노드입니다. 위 사진에서처럼 노드는&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;부모, 자식&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;형태로 이어집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;뿌리 (root)&lt;/b&gt;: 트리의 시작 부분입니다. 뿌리를 통해 들어가서 트리를 탐색합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;잎 (leaf)&lt;/b&gt;: 자식이 딸려있지 않은 부분입니다. 노드라고 부르기도 합니다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;간선 (edge)&lt;/b&gt;: 두 노드를 연결하는 선입니다.&amp;nbsp;뿌리로부터의 간선의 수에 따라&amp;nbsp;level을 나눕니다.&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;트리의 높이, 깊이, 레벨&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;트리 자료구조에 대해 이야기하다 보면 높이, 깊이, 레벨에 대해 언급이 됩니다. 차이점에 대해 알아봅시다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;높이(height)&lt;/b&gt;: 루트에서 가장 먼 잎(노드) 까지 거치게되는 간선 개수를 말한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;깊이(depth)&lt;/b&gt;: 루트에서 현재 노드 사이의 간선 개수를 말한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;레벨(level)&lt;/b&gt;: 트리의 깊이와 정의가 비슷하지만 그 기준이 간선이 아닌 노드의 개수이다. 따라서&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span data-mathml=&quot;&amp;lt;math xmlns=&amp;quot;http://www.w3.org/1998/Math/MathML&amp;quot;&amp;gt;&amp;lt;mi&amp;gt;d&amp;lt;/mi&amp;gt;&amp;lt;mi&amp;gt;e&amp;lt;/mi&amp;gt;&amp;lt;mi&amp;gt;p&amp;lt;/mi&amp;gt;&amp;lt;mi&amp;gt;t&amp;lt;/mi&amp;gt;&amp;lt;mi&amp;gt;h&amp;lt;/mi&amp;gt;&amp;lt;mo&amp;gt;+&amp;lt;/mo&amp;gt;&amp;lt;mn&amp;gt;1&amp;lt;/mn&amp;gt;&amp;lt;mo&amp;gt;=&amp;lt;/mo&amp;gt;&amp;lt;mi&amp;gt;l&amp;lt;/mi&amp;gt;&amp;lt;mi&amp;gt;e&amp;lt;/mi&amp;gt;&amp;lt;mi&amp;gt;v&amp;lt;/mi&amp;gt;&amp;lt;mi&amp;gt;e&amp;lt;/mi&amp;gt;&amp;lt;mi&amp;gt;l&amp;lt;/mi&amp;gt;&amp;lt;/math&amp;gt;&quot;&gt;&lt;span aria-hidden=&quot;true&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span&gt;d&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;e&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;p&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;t&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;h&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;+&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;=&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;l&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;e&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;v&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;e&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span&gt;l&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span&gt;depth+1=level&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;이 성립한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;837&quot; data-origin-height=&quot;341&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dkVkRU/btrlfZl57GL/YyWEkSUlFGkNVR6yH0co0k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dkVkRU/btrlfZl57GL/YyWEkSUlFGkNVR6yH0co0k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dkVkRU/btrlfZl57GL/YyWEkSUlFGkNVR6yH0co0k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdkVkRU%2FbtrlfZl57GL%2FYyWEkSUlFGkNVR6yH0co0k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;837&quot; height=&quot;341&quot; data-origin-width=&quot;837&quot; data-origin-height=&quot;341&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Post&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;References&lt;/b&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.boostcourse.org/cs204/lecture/626041&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;[부스트코스] 자바로 구현하고 배우는 자료구조&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignCenter&quot; data-emoticon-type=&quot;niniz&quot; data-emoticon-name=&quot;012&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;잘못된 코드나 내용이 있다면 댓글을 남겨주세요. 즉시 수정하도록 하겠습니다! :)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>DataStructures</category>
      <category>tree</category>
      <category>간선</category>
      <category>노드</category>
      <category>자료구조</category>
      <category>트리</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/127</guid>
      <comments>https://zangzangs.tistory.com/127#entry127comment</comments>
      <pubDate>Tue, 16 Nov 2021 16:12:30 +0900</pubDate>
    </item>
    <item>
      <title>[자료구조] 해시 구현하기 #java</title>
      <link>https://zangzangs.tistory.com/124</link>
      <description>&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;해시 자료구조 자바로 구현하기&lt;/span&gt;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style2&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://zangzangs.tistory.com/123&quot;&gt;해시 자료구조 설명&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;&lt;a href=&quot;https://zangzangs.tistory.com/124&quot;&gt;해시 자료구조 JAVA 구현&lt;/a&gt;&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;font-size: 1.12em;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;Hash.java&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;pre id=&quot;code_1633419898362&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class Hash&amp;lt;K, V&amp;gt; implements HashInterface{

    class HashElement&amp;lt;K, V&amp;gt; implements Comparable&amp;lt;HashElement&amp;lt;K,V&amp;gt;&amp;gt;{

        K key;
        V value;

        public HashElement(K key, V value){
            this.key = key;
            this.value = value;
        }

        @Override
        public int compareTo(HashElement&amp;lt;K, V&amp;gt; o) {
            return (((Comparable&amp;lt;K&amp;gt;)this.key).compareTo(o.key));
        }
    }

    int numElements;
    int tableSize;  //array size
    double maxLoadFactor;
    LinkedList&amp;lt;HashElement&amp;lt;K,V&amp;gt;&amp;gt;[] hashArray;

    public Hash(int tableSize){
        this.tableSize = tableSize;
        hashArray = (LinkedList&amp;lt;HashElement&amp;lt;K,V&amp;gt;&amp;gt;[]) new LinkedList[tableSize];

        for (int i = 0; i &amp;lt; tableSize; i++) {
            hashArray[i] = new LinkedList&amp;lt;HashElement&amp;lt;K,V&amp;gt;&amp;gt;();
        }
        maxLoadFactor = 0.75;
        numElements = 0;
    }

    public double loadFactor(){
        return (double)numElements/tableSize;
    }

    public void resize(int newSize){

        LinkedList&amp;lt;HashElement&amp;lt;K,V&amp;gt;&amp;gt;[] new_array =(LinkedList&amp;lt;HashElement&amp;lt;K,V&amp;gt;&amp;gt;[]) new LinkedList[newSize];

        for (int i = 0; i &amp;lt; newSize; i++) {
            new_array[i] = new LinkedList&amp;lt;HashElement&amp;lt;K,V&amp;gt;&amp;gt;();

        }

        for (LinkedList&amp;lt;HashElement&amp;lt;K,V&amp;gt;&amp;gt; linkedList: hashArray) {

            for (HashElement&amp;lt;K,V&amp;gt; he :linkedList) {
                K key = he.key;
                V value = he.value;
                HashElement&amp;lt;K,V&amp;gt; new_he = new HashElement&amp;lt;&amp;gt;(key, value);
                int hashVal = (key.hashCode() &amp;amp; 0x7fffffff %newSize);

                new_array[hashVal].add(new_he);

            }
        }

        hashArray = new_array;
        tableSize = newSize;


    }

    public boolean add(K key, V value){

        if( loadFactor() &amp;gt;maxLoadFactor){
          resize(tableSize*2);
        }

        HashElement&amp;lt;K,V&amp;gt; he = new HashElement&amp;lt;&amp;gt;(key, value);

        int hashval = key.hashCode();
        hashval = hashval &amp;amp; 0x7fffffff;
        hashval = hashval % tableSize;

        hashArray[hashval].add(he);
        numElements++;
        return true;
    }

    public boolean remove(HashElement he){
        int hashval = he.key.hashCode();
        hashval = hashval &amp;amp; 0x7fffffff;
        hashval = hashval % tableSize;

        hashArray[hashval].remove(he);
        numElements--;
        return true;
    }

    public V getValue(K key){
        int hashval = key.hashCode()&amp;amp;0x7fffffff % tableSize;
        for (LinkedList&amp;lt;HashElement&amp;lt;K, V&amp;gt;&amp;gt; linkedList: hashArray) {

            for (HashElement&amp;lt;K,V&amp;gt; he: linkedList) {
                if( ((Comparable&amp;lt;K&amp;gt;)key).compareTo(he.key) == 0 ){
                    return he.value;
                }
            }
        }

        return null;
    }

    class IteratorHelper &amp;lt;T&amp;gt; implements Iterator&amp;lt;T&amp;gt;{

        T[] keys;
        int position;

        //constructor
        public IteratorHelper(){
            keys = (T[]) new Object[numElements];
            int p = 0;
            for (int i = 0; i &amp;lt; tableSize; i++) {
                LinkedList&amp;lt;HashElement&amp;lt;K,V&amp;gt;&amp;gt; list = hashArray[i];

                for (HashElement&amp;lt;K,V&amp;gt; he: list) {
                    keys[p++] = (T)he.key;
                }
            }
            position = 0;

        }

        @Override
        public boolean hasNext() {
            return position &amp;lt; keys.length;
        }

        @Override
        public T next() {
            if(!hasNext()){
                return null;
            }else{
                return keys[position];
            }
        }
    }

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/ZANGZANGS/data-structures-in-java/blob/master/README.md&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;  Git 소스 보기&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;Post&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-ke-size=&quot;size23&quot;&gt;&lt;a href=&quot;https://zangzangs.tistory.com/123&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;2021.10.01 - [DataStructures] - [자료구조] 해시(hash) #java&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;References&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a href=&quot;https://www.boostcourse.org/cs204/joinLectures/212446?isDesc=false&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;부스트코스 - 자바로 구현하고 배우는 자료구조&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style3&quot; /&gt;
&lt;figure contenteditable=&quot;false&quot; data-ke-type=&quot;emoticon&quot; data-ke-align=&quot;alignCenter&quot; data-emoticon-type=&quot;niniz&quot; data-emoticon-name=&quot;012&quot; data-emoticon-isanimation=&quot;false&quot; data-emoticon-src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot;&gt;&lt;img src=&quot;https://t1.daumcdn.net/keditor/emoticon/niniz/large/012.gif&quot; width=&quot;150&quot; /&gt;&lt;/figure&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Sans Light';&quot;&gt;&lt;b&gt;잘못된 코드나 내용이 있다면 댓글을 남겨주세요. 즉시 수정하도록 하겠습니다! :)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>DataStructures</category>
      <category>hash</category>
      <category>java</category>
      <category>자료구조</category>
      <category>자바</category>
      <category>해시</category>
      <author>장장스</author>
      <guid isPermaLink="true">https://zangzangs.tistory.com/124</guid>
      <comments>https://zangzangs.tistory.com/124#entry124comment</comments>
      <pubDate>Tue, 5 Oct 2021 16:46:18 +0900</pubDate>
    </item>
  </channel>
</rss>