<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>후르트링의 CS 블로그</title>
    <link>https://frootjy.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Mon, 6 Jul 2026 12:29:17 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>후르트링</managingEditor>
    <item>
      <title>PlantUML 문법 정리(시퀀스 다이어그램)</title>
      <link>https://frootjy.tistory.com/73</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트 설계할 때 그동안은 Draw.io를 이용하여서 시퀀스 다이어그램을 그렸었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러던 중, 텍스트로 UML을 만들 수 있는 &lt;b&gt;PlantUML&lt;/b&gt;을 알게되었고, 무척 편리했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시퀀스 다이어그램 그릴 때 필요한 PlantUML 문법을 간단하게 정리해보려고 합니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h1&gt;PlantUML&lt;/h1&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;PlantUML&lt;/b&gt; 은 다이어그램을 빠르게 작성하기 위한 오픈 소스 프로젝트입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공식 사이트 : &lt;a href=&quot;https://plantuml.com/ko/&quot;&gt;https://plantuml.com/ko/&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&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;a href=&quot;https://plantuml.com/ko/sequence-diagram&quot;&gt;시퀀스 다이어그램&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://plantuml.com/ko/use-case-diagram&quot;&gt;유스케이스 다이어그램&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://plantuml.com/ko/class-diagram&quot;&gt;클래스 다이어그램&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://plantuml.com/ko/object-diagram&quot;&gt;객체 다이어그램&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://plantuml.com/ko/activity-diagram-beta&quot;&gt;액티비티 다이어그램&lt;/a&gt; (예전 문법은 &lt;a href=&quot;https://plantuml.com/ko/activity-diagram-legacy&quot;&gt;여기에)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://plantuml.com/ko/component-diagram&quot;&gt;컴포넌트 다이어그램&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://plantuml.com/ko/deployment-diagram&quot;&gt;배치 다이어그램&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://plantuml.com/ko/state-diagram&quot;&gt;상태 다이어그램&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://plantuml.com/ko/timing-diagram&quot;&gt;타이밍 다이어그램&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;기본 예제&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;1.png&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;336&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Pj437/btsgDO4JW94/Kkrf1Y7Y1vgCFihx4oE9q1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Pj437/btsgDO4JW94/Kkrf1Y7Y1vgCFihx4oE9q1/img.png&quot; data-alt=&quot;기본 예제&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Pj437/btsgDO4JW94/Kkrf1Y7Y1vgCFihx4oE9q1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPj437%2FbtsgDO4JW94%2FKkrf1Y7Y1vgCFihx4oE9q1%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;400&quot; height=&quot;336&quot; data-filename=&quot;1.png&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;336&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;기본 예제&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;@StartUML
' 작성본문입력
A -&amp;gt; B : This is a request
B --&amp;gt; A : This is a response

' 한줄 주석
/' 
 여러줄 주석 사용방법
'/
@EndUML&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;@StartUML / @EndUML : 작성할 UML의 시작과 끝을 의미합니다.&lt;/li&gt;
&lt;li&gt;-&amp;gt; : 실선 화살표&lt;/li&gt;
&lt;li&gt;--&amp;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;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;참여자 선언&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PlantUML에서는 다음과 같은 참여자를 선언하여 사용할 수 있습니다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;actor&lt;/li&gt;
&lt;li&gt;boundary&lt;/li&gt;
&lt;li&gt;control&lt;/li&gt;
&lt;li&gt;entity&lt;/li&gt;
&lt;li&gt;database&lt;/li&gt;
&lt;li&gt;collections&lt;/li&gt;
&lt;/ul&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-filename=&quot;2.png&quot; data-origin-width=&quot;836&quot; data-origin-height=&quot;674&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bPH9Hs/btsgDhsyrNA/pyoOJxtZQlwSwcvJmkHEXk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bPH9Hs/btsgDhsyrNA/pyoOJxtZQlwSwcvJmkHEXk/img.png&quot; data-alt=&quot;참여자&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bPH9Hs/btsgDhsyrNA/pyoOJxtZQlwSwcvJmkHEXk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbPH9Hs%2FbtsgDhsyrNA%2FpyoOJxtZQlwSwcvJmkHEXk%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;836&quot; height=&quot;674&quot; data-filename=&quot;2.png&quot; data-origin-width=&quot;836&quot; data-origin-height=&quot;674&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;참여자&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;@startuml
actor Foo1
boundary Foo2
control Foo3
entity Foo4
database Foo5
collections Foo6
Foo1 -&amp;gt; Foo2 : To boundary
Foo1 -&amp;gt; Foo3 : To control
Foo1 -&amp;gt; Foo4 : To entity
Foo1 -&amp;gt; Foo5 : To database
Foo1 -&amp;gt; Foo6 : To collections

@enduml&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;@startuml
participant Last order 30
participant Middle order 20
participant First order 10
@enduml&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;메시지에 순서 번호 출력하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;autonumber&lt;/code&gt; 키워드를 사용하여 메시지에 자동으로 번호를 출력하게 할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;6.png&quot; data-origin-width=&quot;530&quot; data-origin-height=&quot;304&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NsqE9/btsgFvwiAXq/2V1BVpHLPw3XeH23ohZ971/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NsqE9/btsgFvwiAXq/2V1BVpHLPw3XeH23ohZ971/img.png&quot; data-alt=&quot;autonumber&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NsqE9/btsgFvwiAXq/2V1BVpHLPw3XeH23ohZ971/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNsqE9%2FbtsgFvwiAXq%2F2V1BVpHLPw3XeH23ohZ971%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;530&quot; height=&quot;304&quot; data-filename=&quot;6.png&quot; data-origin-width=&quot;530&quot; data-origin-height=&quot;304&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;autonumber&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;@startuml
autonumber
Bob -&amp;gt; Alice : Authentication Request
Bob &amp;lt;- Alice : Authentication Response
@enduml&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;다이어그램 그룹화&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&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;alt/else : if/else와 같은 분기 처리 표현(조건이 여러 개일 때 표현)&lt;/li&gt;
&lt;li&gt;opt : option의 약자, 조건에 선택사항이 단 1개인 경우를 표현&lt;/li&gt;
&lt;li&gt;loop : for, while 같은 반복 표현&lt;/li&gt;
&lt;li&gt;par : parallel의 약자로 병렬 처리 표현&lt;/li&gt;
&lt;li&gt;break&lt;/li&gt;
&lt;li&gt;critical&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;3.png&quot; data-origin-width=&quot;556&quot; data-origin-height=&quot;886&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/V1rRP/btsgG4Feqqj/NKoPULbzZIerKjNRW2uaI1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/V1rRP/btsgG4Feqqj/NKoPULbzZIerKjNRW2uaI1/img.png&quot; data-alt=&quot;무한루프&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/V1rRP/btsgG4Feqqj/NKoPULbzZIerKjNRW2uaI1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FV1rRP%2FbtsgG4Feqqj%2FNKoPULbzZIerKjNRW2uaI1%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;886&quot; data-filename=&quot;3.png&quot; data-origin-width=&quot;556&quot; data-origin-height=&quot;886&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;무한루프&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;@startuml
A -&amp;gt; B : 나 화났어
B --&amp;gt; A : 미안해
loop
    A -&amp;gt; B : 뭐가 미안한데?
    loop xxx times
        alt case1
            B --&amp;gt; A : 몰라
            A -&amp;gt; B : 모르면서 미안해?
        else case2
            B --&amp;gt; A : 알아
            A -&amp;gt; B : 알면서 그래?
        end
    end
    B --&amp;gt; A :잘못했어
end
@enduml&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;메시지에 노트 추가하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;note left&lt;/code&gt; , &lt;code&gt;note right&lt;/code&gt; 키워드를 사용하여 메시지에 노트를 추가할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;end note&lt;/code&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-filename=&quot;4.png&quot; data-origin-width=&quot;762&quot; data-origin-height=&quot;500&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xMNmW/btsgDJ9R1xg/lyA4qxy0scBN3NSUSvkWU1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xMNmW/btsgDJ9R1xg/lyA4qxy0scBN3NSUSvkWU1/img.png&quot; data-alt=&quot;노트&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xMNmW/btsgDJ9R1xg/lyA4qxy0scBN3NSUSvkWU1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxMNmW%2FbtsgDJ9R1xg%2FlyA4qxy0scBN3NSUSvkWU1%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;762&quot; height=&quot;500&quot; data-filename=&quot;4.png&quot; data-origin-width=&quot;762&quot; data-origin-height=&quot;500&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;노트&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;@startuml
Alice-&amp;gt;Bob : hello
note left: this is a first note
Bob-&amp;gt;Alice : ok
note right: this is another note
Bob-&amp;gt;Bob : I am thinking
note left
a note
can also be defined
on several lines
end note
@enduml&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;구분자 추가하기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;==&lt;/code&gt; 를 사용하여 다이어그램을 논리적인 단계로 구분하여 나눌 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;5.png&quot; data-origin-width=&quot;644&quot; data-origin-height=&quot;608&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvbqzx/btsgECvTr5l/gOPNiazbjUxI49AMEMBMCk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvbqzx/btsgECvTr5l/gOPNiazbjUxI49AMEMBMCk/img.png&quot; data-alt=&quot;구분자&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvbqzx/btsgECvTr5l/gOPNiazbjUxI49AMEMBMCk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbvbqzx%2FbtsgECvTr5l%2FgOPNiazbjUxI49AMEMBMCk%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;644&quot; height=&quot;608&quot; data-filename=&quot;5.png&quot; data-origin-width=&quot;644&quot; data-origin-height=&quot;608&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;구분자&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;pre class=&quot;asciidoc&quot;&gt;&lt;code&gt;@startuml
== Initialization ==
Alice -&amp;gt; Bob: Authentication Request
Bob --&amp;gt; Alice: Authentication Response
== Repetition ==
Alice -&amp;gt; Bob: Another authentication Request
Alice &amp;lt;-- Bob: another authentication Response
@enduml&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://plantuml.com/ko/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://plantuml.com/ko/&lt;/a&gt;&lt;/p&gt;</description>
      <category>프로그래밍/일반</category>
      <category>plantuml</category>
      <category>시퀀스다이어그램</category>
      <author>후르트링</author>
      <guid isPermaLink="true">https://frootjy.tistory.com/73</guid>
      <comments>https://frootjy.tistory.com/73#entry73comment</comments>
      <pubDate>Sat, 20 May 2023 15:05:07 +0900</pubDate>
    </item>
    <item>
      <title>[ JPA ] 다양한 연관 관계 매핑</title>
      <link>https://frootjy.tistory.com/33</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;객체에서 연관 관계를 설정하고 주인을 정하여 외래키를 다루는 법을&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a title=&quot;이전 글&quot; href=&quot;https://frootjy.tistory.com/32&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;이전 글&lt;/a&gt;에서 다루었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에는 연관관계 매핑을 하는 다양한 방법에 대해 알아보겠습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;엔티티 연관 관계 매핑 시 고려해야 할 것&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;다중성&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&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;다대일 : @ManyToOne&lt;/li&gt;
&lt;li&gt;일대다 : @OneToMany&lt;/li&gt;
&lt;li&gt;일대일 : @OneToOne&lt;/li&gt;
&lt;li&gt;다대다 : @ManyToMany&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;단방향, 양방향&lt;/b&gt;&lt;/h3&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;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;객체가 한쪽만 참조한다면 단방향, 객체가 양쪽이 서로 참조한다면 양방향이라고 할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;연관관계의 주인&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;i&gt;&lt;b&gt;연관 관계의 주인 : 외래 키를 관리하는 참조&lt;/b&gt;&lt;/i&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터베이스는 외래 키 한개로 두 테이블이 연관관계를 가집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나 객체의 양방향 관계는 양쪽에서 서로를 참조하므로 객체의 연관관계를 관리하는 포인트가 2개가 생깁니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JPA는 두 객체 연관관계 중에 하나를 정해서 데이터 베이스의 외래키를 관리해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 &lt;b&gt;외래 키를 가지고 있는 테이블과 매핑된 엔티티를 연관관계의 주인&lt;/b&gt;으로 정하고 &lt;b&gt;이곳을 통해서만 수정, 삭제&lt;/b&gt; 등이 이루어집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주인의 반대편은 외래키에 영향을 주지 않으며 단순 조회만 가능합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;다 대 일 [N:1]&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;다대일 단방향&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;image-20220414154348430.png&quot; data-origin-width=&quot;609&quot; data-origin-height=&quot;355&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c2MhWH/btrzmkLqkzQ/hQPt3Izv9pVBcyWQPzE0qK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c2MhWH/btrzmkLqkzQ/hQPt3Izv9pVBcyWQPzE0qK/img.png&quot; data-alt=&quot;다대일 단방향&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c2MhWH/btrzmkLqkzQ/hQPt3Izv9pVBcyWQPzE0qK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc2MhWH%2FbtrzmkLqkzQ%2FhQPt3Izv9pVBcyWQPzE0qK%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;609&quot; height=&quot;355&quot; data-filename=&quot;image-20220414154348430.png&quot; data-origin-width=&quot;609&quot; data-origin-height=&quot;355&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;다대일 단방향&lt;/figcaption&gt;
&lt;/figure&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;/li&gt;
&lt;li&gt;다대일의 반대는 일대다&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;다대일 양방향&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;image-20220414154430582.png&quot; data-origin-width=&quot;663&quot; data-origin-height=&quot;387&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bxUWou/btrzmi7SRdA/3y8IsAfPzIlIq6Z0iKy5m0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bxUWou/btrzmi7SRdA/3y8IsAfPzIlIq6Z0iKy5m0/img.png&quot; data-alt=&quot;다대일 양방향&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bxUWou/btrzmi7SRdA/3y8IsAfPzIlIq6Z0iKy5m0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbxUWou%2Fbtrzmi7SRdA%2F3y8IsAfPzIlIq6Z0iKy5m0%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;663&quot; height=&quot;387&quot; data-filename=&quot;image-20220414154430582.png&quot; data-origin-width=&quot;663&quot; data-origin-height=&quot;387&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;다대일 양방향&lt;/figcaption&gt;
&lt;/figure&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;외래 키가 있는 쪽이 연관관계의 주인&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;/li&gt;
&lt;li&gt;연관관계 편의 메소드를 작성하여 양쪽을 한번에 작성하는 것이 좋습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;외래키는 &quot;다&quot; 쪽에 두는 것이 올바른 설계입니다.&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;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;일 대 다 [1:N]&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일대다 관계는 엔티티를 하나 이상 참조 가능하므로 자바 컬렉션인 &lt;code&gt;Collection&lt;/code&gt;, &lt;code&gt;List&lt;/code&gt;, &lt;code&gt;Set&lt;/code&gt;, &lt;code&gt;Map&lt;/code&gt; 중에 하나를 사용해야합니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;일대다 단방향 [1:N]&lt;/b&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;image-20220414154823661.png&quot; data-origin-width=&quot;666&quot; data-origin-height=&quot;375&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UsQWb/btrzpsanG3H/QhxcuvpKQVBIJdP6SnTwck/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UsQWb/btrzpsanG3H/QhxcuvpKQVBIJdP6SnTwck/img.png&quot; data-alt=&quot;일대다 단방향&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UsQWb/btrzpsanG3H/QhxcuvpKQVBIJdP6SnTwck/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUsQWb%2FbtrzpsanG3H%2FQhxcuvpKQVBIJdP6SnTwck%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;666&quot; height=&quot;375&quot; data-filename=&quot;image-20220414154823661.png&quot; data-origin-width=&quot;666&quot; data-origin-height=&quot;375&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;일대다 단방향&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;일대다 단방향은 일(1)이 연관관계의 주인입니다.&lt;/li&gt;
&lt;li&gt;외래키가 다(N)쪽에 있기 때문에 반대편 테이블의 외래키를 관리하는 구조가 됩니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@JoinColumn&lt;/code&gt;을 사용해야합니다.&lt;/li&gt;
&lt;/ul&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;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;연관 관계 처리를 위한 UPDATE SQL을 추가로 실행해야됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;일대다 단방향보다는 &lt;b&gt;다대일 양방향 매핑&lt;/b&gt;을 사용해야 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;일대다 양방향&lt;/b&gt;&lt;/h3&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;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;일 대 일 [1:1]&lt;/b&gt;&lt;/h2&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;b&gt;일대일&lt;/b&gt; 입니다.&lt;/li&gt;
&lt;li&gt;그러므로 테이블 두 곳 중에 외래 키가 들어갈 곳을 자유롭게 선택할 수 있습니다.&lt;/li&gt;
&lt;li&gt;외래 키에는 데이터베이스 유니크(UNI) 제약조건을 추가해야합니다.&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;/li&gt;
&lt;li&gt;일대일 양방향은 다대일 양방향과 같이 설정합니다
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;연관관계의 주인을 지정하고 반대편에는 &lt;code&gt;mappedby&lt;/code&gt; 속성으로 주인을 나타냅니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&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;b&gt;주 테이블에 외래키&lt;/b&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;주 객체가 대상 객체의 참조를 가지는 것처럼 주 테이블에 외래 키를 가지고 대상 테이블을 찾습니다.&lt;/li&gt;
&lt;li&gt;객체지향 개발자가 선호하며 JPA 매핑이 편리합니다&lt;/li&gt;
&lt;li&gt;장점: 주 테이블만 조회해도 대상 테이블에 데이터가 있는지 확인 가능&lt;/li&gt;
&lt;li&gt;단점: 값이 없으면 외래 키에 null 허용&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;대상 테이블에 외래키&lt;/b&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&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;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;다 대 다 [N:M]&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;관계형 데이터베이스는 정규화된 테이블 2개로 다대다 관계를 표현할 수 없습니다.
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;그러므로 다대다는 연결 테이블을 추가하여 일대다, 다대일 관계로 풀어내야 합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;반면에 객체는 컬렉션을 사용해서 객체 2개로 다대다 관계가 가능합니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@ManyToMany&lt;/code&gt;를 사용하고, &lt;code&gt;@JoinTable&lt;/code&gt;로 연결 테이블을 지정합니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@JoinTable&lt;/code&gt;로 연결을 하게되면 연결 테이블이 생성되는데 이는 실무에서 사용하는데 한계가 있습니다.
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;회원과 상품을 주문하면 연결테이블에 회원_상품 테이블이 생성됩니다.&lt;/li&gt;
&lt;li&gt;이곳에는 회원과 상품뿐만 아니라 주문 수량이나 날짜와 같은 추가적인 컬럼이 필요합니다.&lt;/li&gt;
&lt;li&gt;컬럼을 추가하게 되면 더이상 &lt;code&gt;@ManyToMany&lt;/code&gt;를 사용할 수 없습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p 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;&lt;code&gt;@ManyToMany&lt;/code&gt;는 &lt;code&gt;@OneToMany&lt;/code&gt;와 &lt;code&gt;@ManyToOne&lt;/code&gt;으로 나누어서 사용합니다.&lt;/p&gt;</description>
      <category>프로그래밍/JPA</category>
      <category>jpa</category>
      <author>후르트링</author>
      <guid isPermaLink="true">https://frootjy.tistory.com/33</guid>
      <comments>https://frootjy.tistory.com/33#entry33comment</comments>
      <pubDate>Thu, 14 Apr 2022 16:17:43 +0900</pubDate>
    </item>
    <item>
      <title>[ JPA ] 연관관계 매핑 기초</title>
      <link>https://frootjy.tistory.com/32</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;엔티티들은 대부분 다른 엔티티와 연관 관계가 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&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;/li&gt;
&lt;li&gt;테이블은 외래 키를 사용해서 조인(join)을 통해 연관관계를 맺습니다.&lt;/li&gt;
&lt;/ul&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;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;단방향 연관관계&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단방향 연관관계는 회원 -&amp;gt; 팀 또는 팀 -&amp;gt; 회원 과 같이 둘 중 한 쪽만 참조하는 것을 단방향 관계라고 말합니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;image-20220413131849505.png&quot; data-origin-width=&quot;689&quot; data-origin-height=&quot;382&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cdPJD3/btrzjo0mBDx/UB6VWXnY0x93IO3K9YlJj1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cdPJD3/btrzjo0mBDx/UB6VWXnY0x93IO3K9YlJj1/img.png&quot; data-alt=&quot;객체 및 테이블 연관관계&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cdPJD3/btrzjo0mBDx/UB6VWXnY0x93IO3K9YlJj1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcdPJD3%2Fbtrzjo0mBDx%2FUB6VWXnY0x93IO3K9YlJj1%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;689&quot; height=&quot;382&quot; data-filename=&quot;image-20220413131849505.png&quot; data-origin-width=&quot;689&quot; data-origin-height=&quot;382&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;객체 및 테이블 연관관계&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;member와 team이 다음과 같이 연관 관계를 맺고 있습니다.&lt;/p&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;@Entity
public class Member {
    @Id @GeneratedValue
    @Column(name= &quot;MEMBER_ID&quot;)
    private String id;
    private String username;

    @ManyToOne
    @JoinColumn(name = &quot;TEAM_ID&quot;)
    private Team team;
}

@Entity
public class Team {
    @Id @GeneratedValue
    @Column(name = &quot;TEAM_ID&quot;)
    private Long id;
    private String name;
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;객체의 연관 관계 설정을 위해 Member 객체의 Member.team 필드를 사용하였습니다.&lt;/li&gt;
&lt;li&gt;이것은 테이블에서는 MEMBER 테이블에 TEAM_ID를 외래키로 사용한 것입니다.&lt;/li&gt;
&lt;li&gt;Team과 Member는 &lt;code&gt;1 대 다&lt;/code&gt; 관계이기 때분에 &lt;code&gt;@ManyToOne&lt;/code&gt; 애노테이션을 사용해서 표현하였습니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;@JoinColumn&lt;/code&gt;을 사용하여 외래 키를 매핑 하였습니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;@JoinColumn&lt;/code&gt;의 &lt;code&gt;name&lt;/code&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;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;양방향 연관관계&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;양방향 연관관계는 단방향 연관관계와 다르게 서로 참조하는 구조를 가지고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&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;b&gt;테이블의 연관관계&lt;/b&gt;는 &lt;code&gt;외래 키&lt;/code&gt; 한개로 양방향 연관관계가 구현이 됩니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;DB에서는 방향이라고 이야기 할 것이 없습니다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;외래키 한 개&lt;/code&gt;로&lt;code&gt;JOIN&lt;/code&gt;을 통해 양방향으로 조회를 할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;객체의 연관관계&lt;/b&gt;에서 양방향 연관관계는 사실 2개의 단방향 연관관계 입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;kotlin&quot;&gt;&lt;code&gt;@Entity
public class Team{

    @Id @GeneratedValue
    private Long id;
       private String name;

    @OneToMany(mappedBy = &quot;team&quot;)
    List&amp;lt;Member&amp;gt; members = new ArrayList&amp;lt;Member&amp;gt;();
}&lt;/code&gt;&lt;/pre&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;객체의 연관관계 : 2개
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Member -&amp;gt; Team&lt;/li&gt;
&lt;li&gt;Team -&amp;gt; Member&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;테이블 연관관계 : 1개
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Member &amp;lt;-&amp;gt; Team / 외래 키 설정된 양방향&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Team 엔티티에서 Member로 매핑을 작성하여 양방향 관계를 완성한 것을 확인 할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;연관 관계의 주인&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 코드에서 @OneToMany 애노테이션 안에 &lt;code&gt;mappedBy= &quot;team&quot;&lt;/code&gt;이라는 속성이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;mappedBy 속성&lt;/b&gt;은 양방향 연관관계에서 주인을 설정하는 속성입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&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;/li&gt;
&lt;li&gt;두 객체 연관관계 중에 하나를 &lt;b&gt;연관관계의 주인으로 정해서 외래키를 관리&lt;/b&gt;합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 코드에서 &lt;code&gt;@OneToMany(mappedBy = &quot;team&quot;)&lt;/code&gt;의 의미는&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Member 엔티티에 있는 &lt;code&gt;private Team team&lt;/code&gt;을 연관관계의 주인으로 설정한다는 뜻입니다.&lt;/p&gt;
&lt;p 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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;연관 관계 주인 규칙&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&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;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;데이터의 등록 및 수정 등은 연관 관계의 주인을 통해서만 이루어져야합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;연관 관계의 주인이 아닌 쪽은 읽기만 가능합니다.&lt;/li&gt;
&lt;li&gt;연관 관계의 주인은 mappedBy 속성을 사용하지 않습니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;연관 관계의 주인이 아닌 쪽은 mappedBy 속성을 사용하여 주인을 지정해줍니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;실전 주인 설정 방법&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;DB 설계시에 외래 키가 있는 곳을 주인으로 설정하는 것이 좋습니다.&lt;/li&gt;
&lt;li&gt;1 대 다 관계에서는 &quot;다&quot; 쪽이 연관관계의 주인이 됩니다.&lt;/li&gt;
&lt;/ul&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;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;/li&gt;
&lt;li&gt;그러나 영속성 컨텍스트에 입력한 후에 바로 조회를 하게 된다면 1차 캐시에 데이터가 나오므로 연관 관계가 형성되지 않았을 가능성이 있습니다.
&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;/li&gt;
&lt;li&gt;addMember() 와 같은 &lt;b&gt;연관 관계 편의 메서드를 작성하여 양쪽에 값을 설정&lt;/b&gt;합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;양방향 매핑시에 무한 루프가 생길 수 있습니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;to_string()을 사용시에 서로 계속해서 참조하는 무한루프가 발생할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;정리&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&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;양방향 매핑은 반대 방향으로 조회 기능이 추가 된 것일 뿐입니다.&lt;/li&gt;
&lt;li&gt;단방향 매핑이 잘 되어 있는 상태에서 양방향을 추가한다고 해도 테이블은 단방향 상태 그대로 유지 됩니다.(테이블에 영향이 가지 않습니다.)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;b&gt;연관 관계의 주인&lt;/b&gt;은 비즈니스 로직이 아니라 &lt;b&gt;외래 키의 위치를 기준&lt;/b&gt;으로 정해야합니다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>프로그래밍/JPA</category>
      <category>jpa</category>
      <author>후르트링</author>
      <guid isPermaLink="true">https://frootjy.tistory.com/32</guid>
      <comments>https://frootjy.tistory.com/32#entry32comment</comments>
      <pubDate>Wed, 13 Apr 2022 17:55:55 +0900</pubDate>
    </item>
    <item>
      <title>[ JPA ] 영속성 컨텍스트란?</title>
      <link>https://frootjy.tistory.com/31</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;영속성 컨텍스트란?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;code&gt;영속성 컨텍스트(Persistence Context)&lt;/code&gt;&lt;/b&gt;는 JPA에서 &lt;b&gt;Server와 데이터 베이스 사이에 엔티티를 영구 저장하는 환경이자 논리적인 영역&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음은 &lt;code&gt;&lt;b&gt;EntityManager&lt;/b&gt;&lt;/code&gt;에 관한 자바 공식 문서의 설명입니다.&lt;/p&gt;
&lt;pre class=&quot;html xml&quot; data-ke-language=&quot;html&quot;&gt;&lt;code&gt;An EntityManager instance is associated with a persistence context. 
A persistence context is a set of entity instances in which for any 
persistent entity identity there is a unique entity instance.
Within the persistence context, the entity instances and their lifecycle are managed. 
The EntityManager API is used to create and remove persistent entity instances, 
to find entities by their primary key, and to query over entities.&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;출처 : &lt;a href=&quot;https://docs.oracle.com/javaee/7/api/javax/persistence/EntityManager.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://docs.oracle.com/javaee/7/api/javax/persistence/EntityManager.html&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1648478566349&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;EntityManager (Java(TM) EE 7 Specification APIs)&quot; data-og-description=&quot;Interface used to interact with the persistence context. An EntityManager instance is associated with a persistence context. A persistence context is a set of entity instances in which for any persistent entity identity there is a unique entity instance. W&quot; data-og-host=&quot;docs.oracle.com&quot; data-og-source-url=&quot;https://docs.oracle.com/javaee/7/api/javax/persistence/EntityManager.html&quot; data-og-url=&quot;https://docs.oracle.com/javaee/7/api/javax/persistence/EntityManager.html&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://docs.oracle.com/javaee/7/api/javax/persistence/EntityManager.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.oracle.com/javaee/7/api/javax/persistence/EntityManager.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;EntityManager (Java(TM) EE 7 Specification APIs)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Interface used to interact with the persistence context. An EntityManager instance is associated with a persistence context. A persistence context is a set of entity instances in which for any persistent entity identity there is a unique entity instance. W&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.oracle.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&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;영속성 컨텍스트&lt;/b&gt;는 &lt;b&gt;&lt;code&gt;Entity Manager&lt;/code&gt;&lt;/b&gt;를 통해 영속성 컨텍스트에 접근 할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 영속성 컨텍스트 내에서 &lt;b&gt;엔티티의 인스턴스&lt;/b&gt;와 &lt;b&gt;수명 주기&lt;/b&gt;가 관리된다고 하고 있습니다.&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;image-20220328224237798.png&quot; data-origin-width=&quot;822&quot; data-origin-height=&quot;302&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0ddja/btrxAaq0lJ9/pfFZQ7kaXmlbcHKaq0aHM1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0ddja/btrxAaq0lJ9/pfFZQ7kaXmlbcHKaq0aHM1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0ddja/btrxAaq0lJ9/pfFZQ7kaXmlbcHKaq0aHM1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0ddja%2FbtrxAaq0lJ9%2FpfFZQ7kaXmlbcHKaq0aHM1%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;822&quot; height=&quot;302&quot; data-filename=&quot;image-20220328224237798.png&quot; data-origin-width=&quot;822&quot; data-origin-height=&quot;302&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;EntityManager와 EntityManagerFactory&lt;/b&gt;&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;EntityManagerFactory&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;엔티티 매니저 팩토리는 엔티티 매니저를 관리하기 위한 객체입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애플리케이션이 실행될 때 생성되며 하나의 엔티티 매니저 팩토리는 애플리케이션 전체에서 공유됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서로 다른 스레드가 동시 접근해도 안전합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하나의 엔티티 매니저 팩토리가 여러개의 EntityManager를 생성하는 등 관리를 합니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;EntityManager&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;엔티티 매니저는 엔티티 매니저 팩토리에서 생성되며, 엔티티를 저장, 수정, 삭제, 조회 등의 엔티티와 관련된 모든 일을 처리합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이름 그대로 엔티티 관리자의 역할을 수행하므로 가상의 데이터베이스라고 생각하셔도 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;엔티티 매니저는 여러 스레드가 동시에 접근하면 동시성 문제가 발생하므로 스레드 간에 공유는 절대 불가합니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;엔티티의 생명주기&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&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;b&gt;비영속(new/transient)&lt;/b&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;/li&gt;
&lt;/ul&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;영속(managed)&lt;/b&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;/li&gt;
&lt;/ul&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;준영속(detached)&lt;/b&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;code&gt;em.datach()&lt;/code&gt;를 호출하면 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;삭제(removed)&lt;/b&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;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;영속성 컨텍스트&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 영속성 컨텍스트의 의미는 &lt;code&gt;엔티티를 영구 저장하는 환경&lt;/code&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;EntityManager로 엔티티를 조회하거나, 저장하면 엔티티 매니저는 영속성 컨텍스트에 엔티티를 보관하고 관리합니다.&lt;/p&gt;
&lt;pre class=&quot;abnf&quot;&gt;&lt;code&gt;entityManager.persist(member);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같은 코드는 JPA를 사용할 때 DB에 저장하는 기능을 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 정확하게 말하자면 DB에 저장을 하는 것이 아니라,&lt;/p&gt;
&lt;p 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;이러한 영속성 컨텍스트를 사용함으로써 얻는 장점이 다양하게 있습니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1차 캐시 및 동일성 보장&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;영속성 컨텍스트는 내부에 캐시를 가지고 있습니다. (id, instance) 형식의 맵을 가지고 엔티티들이 저장됩니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;image-20220328231459905.png&quot; data-origin-width=&quot;506&quot; data-origin-height=&quot;393&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/y1SM7/btrxEDznRdp/5fIQkJDA1dD2sVdXhkzjrk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/y1SM7/btrxEDznRdp/5fIQkJDA1dD2sVdXhkzjrk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/y1SM7/btrxEDznRdp/5fIQkJDA1dD2sVdXhkzjrk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fy1SM7%2FbtrxEDznRdp%2F5fIQkJDA1dD2sVdXhkzjrk%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;506&quot; height=&quot;393&quot; data-filename=&quot;image-20220328231459905.png&quot; data-origin-width=&quot;506&quot; data-origin-height=&quot;393&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;&lt;code&gt;em.persist(member)&lt;/code&gt;로 member가 영속성 컨텍스트에 저장되면, 영속성 컨텍스트의 1차 캐시에 이를 담게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이후에 조회를 하게 된다면, DB에 접근하기 전에 1차 캐시에서 먼저 조회를 하게됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;캐시가 있다면, DB에 접근하지 않고 1차 캐시에 있는 정보를 반환하고, 없다면 DB에서 찾은 후에 1차 캐시에 저장한 후에 반환합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 1차 캐시의 특징 때문에 같은 엔티티 조회를 반복해서 호출하더라도, 1차 캐시에 있는 같은 인스턴스를 반환합니다. 그러므로 성능상 이점과 엔티티의 동일성을 보장하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;※ entityManager는 트랜잭션 후에 삭제하기 때문에 하나의 트랜잭션에서만 1차 캐시가 유지되므로 생각보다 큰 성능 향상을 기대하기는 어렵습니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;쓰기 지연&lt;/b&gt;&lt;/h4&gt;
&lt;pre class=&quot;less&quot;&gt;&lt;code&gt;tx.begin();

em.persist(member1);
em.persist(member2);

// ---- 1 ----
em.flush();
// ---- 2 ----

tx.commit();&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같이 영속성 컨텍스트에 member1과 member2를 저장하는 코드가 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;순차적으로 보면 &lt;code&gt;em.persist(member1)&lt;/code&gt;이 실행되면 바로 DB에 저장 될 것 같지만 실제로는 &lt;code&gt;em.flush()&lt;/code&gt;가 실행 된 후에 2번 영역에서 DB에 저장이 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1번 영역까지는 DB로 쿼리를 보내지 않고, 1차 캐시에만 Entity가 저장됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;후에 트랜잭션을 commit하거나, 컨텍스트 버퍼를 비우는 flush()를 명령할 때 DB로 쿼리가 넘어가게 됩니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;변경감지(Dirty Checking)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JPA로 엔티티를 수정할 때는 단순히 엔티티를 조회해서 데이터를 변경하면 됩니다.&lt;/p&gt;
&lt;pre class=&quot;reasonml&quot;&gt;&lt;code&gt;EntityManager em = emf.createEntityManager();
EntityTransaction transaction = em.getTransaction();
transaction.begin();

Member member = em.find(Member.class, &quot;member1&quot;);
member.setName(&quot;froot&quot;);

transaction.commit();&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같이 member1을 조회 해온 뒤에 자바 컬렉션을 다루듯이 setName() 메서드를 통해서 데이터만 바꾸게 되면 DB에 반영이 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 엔티티의 변경사항을 DB에 자동으로 반영하는 기능을 변경 감지(Dirty Checking)이라고 합니다.&lt;/p&gt;
&lt;p 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;변경감지의 흐름은 다음과 같습니다.&lt;/p&gt;
&lt;ol 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;변경된 엔티티가 있으면 수정 쿼리를 생성해서 쓰기 지연 SQL 저장소에 저장한다.&lt;/li&gt;
&lt;li&gt;쓰기 지연 저장소의 SQL을 플러시한다.&lt;/li&gt;
&lt;li&gt;데이터베이스 트랜잭션을 커밋한다.&lt;/li&gt;
&lt;/ol&gt;</description>
      <category>프로그래밍/JPA</category>
      <category>jpa</category>
      <author>후르트링</author>
      <guid isPermaLink="true">https://frootjy.tistory.com/31</guid>
      <comments>https://frootjy.tistory.com/31#entry31comment</comments>
      <pubDate>Mon, 28 Mar 2022 23:39:19 +0900</pubDate>
    </item>
    <item>
      <title>[ JPA ] JPA란?</title>
      <link>https://frootjy.tistory.com/30</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;442&quot; data-origin-height=&quot;298&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bmzwbq/btrxu8ejZZ6/MQeP1H21Li6LCnif0gr8Lk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bmzwbq/btrxu8ejZZ6/MQeP1H21Li6LCnif0gr8Lk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bmzwbq/btrxu8ejZZ6/MQeP1H21Li6LCnif0gr8Lk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbmzwbq%2Fbtrxu8ejZZ6%2FMQeP1H21Li6LCnif0gr8Lk%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;442&quot; height=&quot;298&quot; data-origin-width=&quot;442&quot; data-origin-height=&quot;298&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;JPA&lt;/b&gt;&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;Java 진영에서 ORM(Object-Relational Mapping) 기술 표준으로 사용하는 인터페이스 모음&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;자바 어플리케이션에서 관계형 데이터베이스를 사용하는 방식을 정의한 인터페이스&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;인터페이스 이기 때문에 Hibernate, OpenJPA 등이 JPA를 구현합니다&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;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;ORM(Object Relational Mapping)&lt;/b&gt;&lt;/h2&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;개발자 대신 SQL문을 작성해주기 때문에 개발자는 단순한 SQL문 작성보다 비즈니스 로직 구성하는데 집중할 수 있어 &lt;b&gt;생산성이 높아집니다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;Java의 대표적인 ORM은 JPA가 있으며 다른 언어, 프레임워크에도 ORM이 존재합니다(Python -django)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;JPA 사용 이유&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바를 통한 데이터 접근 방식에는 JDBC API, MyBatis 등이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&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;b&gt;등록, 수정, 삭제, 조회(CRUD)의 SQL 반복&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;객체에 있는 멤버변수가 추가 혹은 삭제 될때마다 SQL문을 수정해야합니다&lt;/li&gt;
&lt;li&gt;쿼리 사용시 선언문 혹은 연결 등의 부가적인 코드가 생기므로, 코드의 가독성이 떨어집니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&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;객체를 단순히 데이터 전달 목적으로 사용할 뿐, 객체 지향적이지 못함 ( 페러다임 불일치 )&lt;/li&gt;
&lt;li&gt;SQL 중심적인 개발&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 문제들을 해결하기 위해 JPA가 등장하였습니다.&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;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;JPA 장점&lt;/b&gt;&lt;/h2&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;JPA를 자바 컬렉션에 &lt;b&gt;객체를 저장하듯&lt;/b&gt; JPA에게 저장할 객체를 전달.&lt;/li&gt;
&lt;li&gt;SQL을 작성하고 JDBC API 사용하는 &lt;b&gt;지루하고 반복적인 일을 JPA가 대신&lt;/b&gt; 처리해준다.&lt;/li&gt;
&lt;li&gt;CREATE TABLE같은 &lt;b&gt;DDL문 자동 생성&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;데이터베이스 설계 중심의 &lt;b&gt;패러다임을 객체 설계 중심&lt;/b&gt;으로 역전&lt;/li&gt;
&lt;/ul&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;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;/li&gt;
&lt;/ul&gt;</description>
      <category>프로그래밍/JPA</category>
      <category>jpa</category>
      <author>후르트링</author>
      <guid isPermaLink="true">https://frootjy.tistory.com/30</guid>
      <comments>https://frootjy.tistory.com/30#entry30comment</comments>
      <pubDate>Sun, 27 Mar 2022 16:55:55 +0900</pubDate>
    </item>
    <item>
      <title>[ 자바 / JAVA ] 출력 format(printf)</title>
      <link>https://frootjy.tistory.com/24</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Java에서 출력할 때 System.out.printf() 메소드를 사용하여 특정 형식의 문자열을 출력할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C언어에서의 printf() 함수를 사용하는 것과 사용 법은 비슷합니다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;[ printf() ]&lt;/h4&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;public PrintWriter printf(String format, Object... args)
System.out.printf(&quot;출력 format&quot;, 출력할 내용);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 58.0218%; height: 243px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;th style=&quot;height: 21px; width: 10.0122%;&quot;&gt;format&lt;/th&gt;
&lt;th style=&quot;height: 21px; width: 42.2503%;&quot;&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px; width: 10.0122%; text-align: center;&quot;&gt;&lt;b&gt;%s&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px; width: 42.2503%; text-align: left;&quot;&gt;String 형식으로 출력&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 25px;&quot;&gt;
&lt;td style=&quot;height: 25px; width: 10.0122%; text-align: center;&quot;&gt;&lt;b&gt;%d&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 25px; width: 42.2503%; text-align: left;&quot;&gt;정수 형식으로 출력&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px; width: 10.0122%; text-align: center;&quot;&gt;&lt;b&gt;%n&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px; width: 42.2503%; text-align: left;&quot;&gt;줄바꿈&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px; width: 10.0122%; text-align: center;&quot;&gt;&lt;b&gt;%f&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px; width: 42.2503%; text-align: left;&quot;&gt;float 형식으로 출력&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px; width: 10.0122%; text-align: center;&quot;&gt;&lt;b&gt;%t&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px; width: 42.2503%; text-align: left;&quot;&gt;date, time 형식으로 출력&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px; width: 10.0122%; text-align: center;&quot;&gt;&lt;b&gt;%o&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px; width: 42.2503%; text-align: left;&quot;&gt;8진수 정수의 형식으로 출력&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 52px;&quot;&gt;
&lt;td style=&quot;height: 52px; width: 10.0122%; text-align: center;&quot;&gt;&lt;b&gt;%x&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 52px; width: 42.2503%; text-align: left;&quot;&gt;16진수 정수의 형식으로 출력&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 31px;&quot;&gt;
&lt;td style=&quot;height: 31px; width: 10.0122%; text-align: center;&quot;&gt;&lt;b&gt;%b&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 31px; width: 42.2503%; text-align: left;&quot;&gt;boolean 형식으로 출력&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;height: 19px; width: 10.0122%; text-align: center;&quot;&gt;&lt;b&gt;%e&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;height: 19px; width: 42.2503%; text-align: left;&quot;&gt;지수 표현식의 형식으로 출력&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h4 style=&quot;text-align: left;&quot; data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&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;code&gt;%20s&lt;/code&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;size16&quot;&gt;&lt;b&gt;Code:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;perl&quot;&gt;&lt;code&gt;String hello = &quot;Hello&quot;;
String world = &quot;World!&quot;;
System.out.printf(&quot;%s %s %n&quot;,hello,world);

System.out.printf(&quot;(%20s) %n&quot;,hello);
System.out.printf(&quot;(%-20s) %n&quot;,world);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Output:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;lisp&quot;&gt;&lt;code&gt;hello world 
(              hello)
(world              )&lt;/code&gt;&lt;/pre&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;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;%3.2f&lt;/code&gt;는 소수점 이하 2자리만 출력하게 할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;%03d&lt;/code&gt;의 의미는 3자리를 차지하고, 만약에 수가 3자리가 되지 않는 다면 빈공간에 0을 채우는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Code:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;System.out.printf(&quot;%f%n&quot;, 123.456);
System.out.printf(&quot;%5.2f%n&quot;, 123.456);
System.out.printf(&quot;%5.2e%n&quot;, 123.456);

System.out.printf(&quot;%03d %n&quot;,100);
System.out.printf(&quot;%03d %n&quot;,65);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Output:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;123.456000
123.46
1.23e+02

100
065&lt;/code&gt;&lt;/pre&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;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;code&gt;%c&lt;/code&gt;는 소문자로 출력&lt;/li&gt;
&lt;li&gt;&lt;code&gt;%C&lt;/code&gt;는 대문자로 출력&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Code:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;perl&quot;&gt;&lt;code&gt;System.out.printf(&quot;%c%n&quot;, 's');
System.out.printf(&quot;%C%n&quot;, 's');&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Output:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;ebnf&quot;&gt;&lt;code&gt;s
S&lt;/code&gt;&lt;/pre&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;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;Date&lt;/code&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;code&gt;%tH&lt;/code&gt; : Date의 Hour값을 출력&lt;/li&gt;
&lt;li&gt;&lt;code&gt;%tM&lt;/code&gt; : Date의 minute 값을 출력&lt;/li&gt;
&lt;li&gt;&lt;code&gt;%tS&lt;/code&gt; : Date의 second 값을 출력&lt;/li&gt;
&lt;li&gt;&lt;code&gt;%tA&lt;/code&gt; : Date의 요일&lt;/li&gt;
&lt;li&gt;&lt;code&gt;%tB&lt;/code&gt; : Date의 달(month)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;%tY&lt;/code&gt; : Date의 연도(year)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Code:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;Date date = new Date();
System.out.printf(&quot;hours: %tH, minutes: %tM, seconds: %tS %n&quot;,
        date, date, date);

System.out.printf(&quot;%tA, %tB %tY %n&quot;, date, date, date);&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Output:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;yaml&quot;&gt;&lt;code&gt;hours: 19, minutes: 55, seconds: 26
Monday, December 2021&lt;/code&gt;&lt;/pre&gt;</description>
      <category>프로그래밍/자바(Java)</category>
      <category>Format</category>
      <category>java</category>
      <category>printf</category>
      <category>자바</category>
      <author>후르트링</author>
      <guid isPermaLink="true">https://frootjy.tistory.com/24</guid>
      <comments>https://frootjy.tistory.com/24#entry24comment</comments>
      <pubDate>Mon, 13 Dec 2021 20:34:53 +0900</pubDate>
    </item>
    <item>
      <title>[자료구조] 힙(Heap) / 우선순위 큐</title>
      <link>https://frootjy.tistory.com/22</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;heap.png&quot; data-origin-width=&quot;883&quot; data-origin-height=&quot;292&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KU92E/btrlqMurOF5/ZyZ46pnJLjg3I9RSaA2kHk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KU92E/btrlqMurOF5/ZyZ46pnJLjg3I9RSaA2kHk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KU92E/btrlqMurOF5/ZyZ46pnJLjg3I9RSaA2kHk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKU92E%2FbtrlqMurOF5%2FZyZ46pnJLjg3I9RSaA2kHk%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;883&quot; height=&quot;292&quot; data-filename=&quot;heap.png&quot; data-origin-width=&quot;883&quot; data-origin-height=&quot;292&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;[ Heap의 정의 ]&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;우선순위 큐를 구현한 &lt;code&gt;완전 이진트리&lt;/code&gt;로 최댓값 혹은 최솟값을 빠르게 찾아내기 위한 이진트리.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;높이가 작은 곳부터, 왼쪽부터 삽입하는 방식으로 작동하며 느슨한 정렬 상태를 유지합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&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;code&gt;최소 힙(Min Heap)&lt;/code&gt; : 부모 노드의 값이 자식 노드보다 작다.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;최대 힙(Max Heap)&lt;/code&gt; : 부모 노드의 값이 자식 노드보다 크다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;Heap&lt;/code&gt;은 &lt;code&gt;이진 탐색 트리(Binary Search Tree)&lt;/code&gt;와 비슷한 트리이지만, 자식과 부모 사이의 대소관계가 다릅니다. Heap은 중복값을 허용, 이진 탐색 트리는 중복값을 허용하지 않습니다.&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;b&gt;Heap에서 할 수 있는 것은 이진 탐색 트리에서도 가능한데 힙을 쓰는 이유가 무엇일까요?&lt;/b&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;code&gt;Heap&lt;/code&gt;으로 구현 가능한 것은 &lt;code&gt;균형 이진트리&lt;/code&gt;에서도 가능 한것이 맞고, 시간복잡도도 O(logN)으로 동일합니다.&lt;/li&gt;
&lt;li&gt;그러나 &lt;code&gt;Heap&lt;/code&gt;은 &lt;code&gt;균형 이진 트리&lt;/code&gt;보다 &lt;b&gt;수행 속도가 빠르고, 공간을 적게 차지&lt;/b&gt;합니다.&lt;/li&gt;
&lt;li&gt;그러므로 &lt;b&gt;최소/ 최대 값의 확인 및 삭제가 필요할 때&lt;/b&gt;는 &lt;code&gt;Heap&lt;/code&gt;을 사용하는 것이 더 좋습니다.&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;[ 힙의 특징 ]&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;완전 이진 트리(Complete binary tree)&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;[ 힙 연산 ]&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;연산은 모두 &lt;code&gt;최소힙&lt;/code&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;&lt;b&gt;삽입 연산&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시간 복잡도 : O(logN)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;E:%5C%EB%B8%94%EB%A1%9C%EA%B7%B8%5C%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98%5Cheap%5Cheap_insert1.gif&quot; alt=&quot;&quot; /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;heap_insert1.gif&quot; data-origin-width=&quot;1279&quot; data-origin-height=&quot;352&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/diGFYi/btrlox5Q2QW/c0yCGL1PzKBEh2MsoCWmOk/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/diGFYi/btrlox5Q2QW/c0yCGL1PzKBEh2MsoCWmOk/img.gif&quot; data-alt=&quot;삽입연산1&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/diGFYi/btrlox5Q2QW/c0yCGL1PzKBEh2MsoCWmOk/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/diGFYi/btrlox5Q2QW/c0yCGL1PzKBEh2MsoCWmOk/img.gif&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;1279&quot; height=&quot;352&quot; data-filename=&quot;heap_insert1.gif&quot; data-origin-width=&quot;1279&quot; data-origin-height=&quot;352&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;삽입연산1&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;힙에 새로운 요소가 들어오면 새로운 노드를 힙의 마지막 노드로 삽입합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약에 새로운 요소가 부모 노드 보다 작다면 위치를 교환하여 최소 힙의 성질을 만족시켜 줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3번째로 들어온 3이 부모 값인 5보다 작으므로 위치를 교환합니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;E:%5C%EB%B8%94%EB%A1%9C%EA%B7%B8%5C%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98%5Cheap%5Cheap_insert2.gif&quot; alt=&quot;&quot; /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;heap_insert2.gif&quot; data-origin-width=&quot;1279&quot; data-origin-height=&quot;352&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLbOaE/btrlpbuFMz1/n5AW5NTukGYFC4T0N8gUm0/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLbOaE/btrlpbuFMz1/n5AW5NTukGYFC4T0N8gUm0/img.gif&quot; data-alt=&quot;삽입연산2&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLbOaE/btrlpbuFMz1/n5AW5NTukGYFC4T0N8gUm0/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/bLbOaE/btrlpbuFMz1/n5AW5NTukGYFC4T0N8gUm0/img.gif&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;1279&quot; height=&quot;352&quot; data-filename=&quot;heap_insert2.gif&quot; data-origin-width=&quot;1279&quot; data-origin-height=&quot;352&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;삽입연산2&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새로운 요소가 들어와 부모노드와 교환을 하고 난뒤에도 부모노드보다 작다면, 또 교환을 해줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로 들어온 1은 부모노드인 5보다 작으므로 교환을 해주었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;교환한 상태에서 1은 부모노인 2 보다 작으므로 다시 교환을 하여 1은 루트 노드의 위치에 가게 됩니다.&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;&lt;b&gt;삭제 연산&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;시간 복잡도 : O(logN)&lt;/li&gt;
&lt;li&gt;힙에서의 삭제 연산은 &lt;b&gt;힙의 최대값, 최솟값&lt;/b&gt;을 삭제합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;E:%5C%EB%B8%94%EB%A1%9C%EA%B7%B8%5C%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98%5Cheap%5Cheap.png&quot; alt=&quot;&quot; /&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;heap_erase1.gif&quot; data-origin-width=&quot;1279&quot; data-origin-height=&quot;352&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cRJPNf/btrloSBHHDD/2FTW35LwGVlwKpR8lqLRF1/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cRJPNf/btrloSBHHDD/2FTW35LwGVlwKpR8lqLRF1/img.gif&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cRJPNf/btrloSBHHDD/2FTW35LwGVlwKpR8lqLRF1/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/cRJPNf/btrloSBHHDD/2FTW35LwGVlwKpR8lqLRF1/img.gif&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;1279&quot; height=&quot;352&quot; data-filename=&quot;heap_erase1.gif&quot; data-origin-width=&quot;1279&quot; data-origin-height=&quot;352&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같이 힙이 있을 때 최솟값인 1을 삭제 연산을 하게 된다면 힙의 구조가 깨지게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 힙의 삭제는 마지막 노드(5)와 부모노드(1)를 교환한 후에 삭제를 진행합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;교환하고 삭제한 후에 힙의 성질을 만족시키기 위해 부모-자식 노드간의 비교를 하여 교환하여 줍니다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;E:%5C%EB%B8%94%EB%A1%9C%EA%B7%B8%5C%EC%95%8C%EA%B3%A0%EB%A6%AC%EC%A6%98%5Cheap%5Cheap_erase1.gif&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1) 최소 값인 1을 삭제하고 마지막 노드(5)를 루트 노드에 올립니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2) 루트 노드(5)와 자식 노드를 비교하여 더 작은 노드(2) 와 교환합니다.&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;힙 구현(STL)&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;C++ STL에 힙이 있습니다. 이름은 priority_queue입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;cpp&quot;&gt;&lt;code&gt;#include &amp;lt;queue&amp;gt;
priority_queue&amp;lt;int, vector&amp;lt;int&amp;gt;, greater&amp;lt;int&amp;gt;&amp;gt; pq; //min_heap
//default는 less&amp;lt;int&amp;gt; -&amp;gt; max_heap
pq.push(1);    //1을 추가
pq.top();    //최소값을 반환
pq.pop();    //힙의 최소값을 삭제&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>코딩테스트(C++)/자료구조, 알고리즘</category>
      <category>c++</category>
      <category>heap</category>
      <category>자료구조</category>
      <author>후르트링</author>
      <guid isPermaLink="true">https://frootjy.tistory.com/22</guid>
      <comments>https://frootjy.tistory.com/22#entry22comment</comments>
      <pubDate>Thu, 18 Nov 2021 14:47:00 +0900</pubDate>
    </item>
    <item>
      <title>[ 알고리즘 ]최소 비용 신장 트리(MST, Minimum Spanning Tree)</title>
      <link>https://frootjy.tistory.com/19</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;768&quot; data-origin-height=&quot;292&quot; data-filename=&quot;신장트리.png&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bQIxs6/btriRYcdPsK/1rP1UeHEj1OmTDwADe3OwK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bQIxs6/btriRYcdPsK/1rP1UeHEj1OmTDwADe3OwK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bQIxs6/btriRYcdPsK/1rP1UeHEj1OmTDwADe3OwK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbQIxs6%2FbtriRYcdPsK%2F1rP1UeHEj1OmTDwADe3OwK%2Fimg.png&quot; data-origin-width=&quot;768&quot; data-origin-height=&quot;292&quot; data-filename=&quot;신장트리.png&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;[ 신장트리(Spanning Tree) ]&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;주어진 방향성이 없는 그래프의 서브 그래프(Subgraph)들 중에서 모든 정점을 포함하는 트리&lt;/li&gt;
&lt;li&gt;&lt;b&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;[ MST ]&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래프의 신장 트리 중에서 &lt;b&gt;간선들의 가중치 합이 최소인 신장트리를 MST(최소 비용 신장 트리,Minimum Spanning Tree)&lt;/b&gt;라고 합니다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;간선들의 가중치의 합이 최소&lt;/li&gt;
&lt;li&gt;V개의 정점 그래프는 V-1개의 간선&lt;/li&gt;
&lt;li&gt;사이클 존재 X&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;총 3가지의 특징을 가지고 있어야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최소 비용 신장트리를 찾는 방법은 &lt;b&gt;크루스칼(Kruskal) 알고리즘&lt;/b&gt;과 &lt;b&gt;프림(Prim) 알고리즘&lt;/b&gt;이 대표적입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 가지 모두 그리디 방식으로 구현합니다.&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;[ 크루스칼(Kruskal) ]&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;i&gt;O&lt;/i&gt;(&lt;i&gt;ElgE&lt;/i&gt;), 간선을 정렬하는 시간에 비례합니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;알고리즘 과정&lt;/b&gt;&lt;/li&gt;
&lt;/ul&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;현재 선택한 간선의 정점 u,v가 다른 그룹이면 같은 그룹으로 만들고, 현재 선택한 간선을 최소 신장 트리에 추가합니다. ※같은 그룹인지 판별하는 것과 그룹을 합치는 것은 &lt;b&gt;Union-find 알고리즘&lt;/b&gt;을 사용합니다.&lt;/li&gt;
&lt;li&gt;최소 신장 트리에 V-1개의 간선이 있다면 종료합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;pre id=&quot;code_1635149982296&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//cost, v1, v2
vector&amp;lt;pair&amp;lt;int, pair&amp;lt;int, int&amp;gt; &amp;gt;&amp;gt; edge;

for (int i = 0; i &amp;lt; e; i++) {
    cost = edge[i].first;
    v1 = edge[i].second.first;
    v2 = edge[i].second.second;
    if (!unionFind(v1, v2)) continue;
    ans += cost;
    cnt++;
    if (cnt == v - 1) break;
}&lt;/code&gt;&lt;/pre&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;[ Union - find ]&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;Union( x, y ) : 집합을 합치는 함수&lt;/li&gt;
&lt;li&gt;find(x) : 원소 x가 속한 집합을 반환&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 노드의 부모에 대한 포인터를 저장합니다.&lt;/p&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;//부모 index 값을 저장한다. 처음에 -1로 초기화.
int p[100001];

//최고 부모를 찾는 함수
int find(int x) {
    if (p[x] ==-1) return x;
    return p[x] = find(p[x]);
}

bool unionFind(int v1, int v2) {
    int root1 = find(v1); 
    int root2 = find(v2);
    if (root1 == root2) return false;        //같은 집합에 속한다.
    p[root1] = root2;                    //다른 집합에 속하면 집합을 합쳐준다.
    return true;
}&lt;/code&gt;&lt;/pre&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;[ 프림(Prim) ]&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;i&gt;O&lt;/i&gt;(&lt;i&gt;ElgE&lt;/i&gt;)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;알고리즘 과정&lt;/b&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;신장트리 집합에 인접한 최소 신장트리에 포함되지 않은 정점들 중에 최저 간선으로 연결된 정점을 선택하여 트리를 확장합니다.&lt;/li&gt;
&lt;li&gt;최소 신장 트리에 V-1 개 간선이 생기면 종료합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Heap을 이용한 Prim 알고리즘 구현
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;하나의 정점을 MST에 추가하고 해당 정점과 연결된 모든 간선을 Heap에 추가&lt;/li&gt;
&lt;li&gt;Heap에서 비용이 가장 작은 간선을 꺼낸다.&lt;/li&gt;
&lt;li&gt;-1 해당 간선이 MST에 포함된 두 정점을 연결하면 Continue;&lt;/li&gt;
&lt;li&gt;-2 해당 간선이 MST에 포함된 정점 u와 포함되지 않는 정점 v를 연결하면 해당 간선과 정점 v를 MST에 추가,&lt;/li&gt;
&lt;li&gt;정점 v에서 연결된 모든 간선 중 MST에 포함되지 않는 간선을 힙에 추가&lt;/li&gt;
&lt;li&gt;최소 신장트리의 간선이 V-1개 이면 종료합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;a style=&quot;color: #006dd7;&quot; href=&quot;https://www.acmicpc.net/problem/1197&quot;&gt;1197번: 최소 스패닝 트리 (acmicpc.net)&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;</description>
      <category>코딩테스트(C++)/자료구조, 알고리즘</category>
      <category>Kruskal</category>
      <category>MST</category>
      <category>prim</category>
      <category>신장트리</category>
      <category>알고리즘</category>
      <author>후르트링</author>
      <guid isPermaLink="true">https://frootjy.tistory.com/19</guid>
      <comments>https://frootjy.tistory.com/19#entry19comment</comments>
      <pubDate>Mon, 25 Oct 2021 17:18:17 +0900</pubDate>
    </item>
    <item>
      <title>[Web/용어정리]  JSP와 Servlet</title>
      <link>https://frootjy.tistory.com/18</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;JSP와 Servlet의 차이에 대해서 알아보겠습니다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Servlet에 대한 설명은 여기 를 참고해 주세요&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Sans Demilight', 'Noto Sans KR';&quot;&gt;[ JSP ]&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 JSP는 Java Server Page의 약자로 &lt;b&gt;정적인 HTML 파일에 동적인 정보를 넣어서 동적 웹페이지를 생성 가능하게 해주는 Server-side 웹 어플리케이션&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JSP는 서블릿의 확장판으로 관리와 배포가 쉬운 특징을 가지고 있습니다.&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;[ JSP vs Servlet ]&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&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;b&gt;Servlet(서블릿)&lt;/b&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;b&gt;Java 코드&lt;/b&gt;이며 안에 HTML 코드를 넣습니다.&lt;/li&gt;
&lt;li&gt;서블릿은 사용자(Client)의 요청(request) 데이터를 처리하는 것(Controller)에 강점이 있습니다.&lt;/li&gt;
&lt;li&gt;DB와의 통신, Bussiness Logic 호출에 강점을 가지고 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;JSP&lt;/b&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;JSP는 &lt;b&gt;기본적으로 HTML 코드&lt;/b&gt;이며 안에 Java 코드를 넣습니다.&lt;/li&gt;
&lt;li&gt;JSP는 presentation(View)에 좋습니다. 즉 요청 결과를 나타내는 HTML 작성하는데 유용합니다.&lt;/li&gt;
&lt;li&gt;JSP가 수정된 경우 재배포할 필요가 없이 WAS가 알아서 처리해 쉬운 배포의 특징을 가집니다.&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;아래는 3개의 인자를 Client로부터 입력받아서 같은 결과를 응답하는 서블릿과 JSP 코드입니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;955&quot; data-origin-height=&quot;576&quot; data-filename=&quot;jsp vs servlet.png&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XTbY6/btriSKdBPe2/Ceo3PIyIsuPyxlcRkDnCaK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XTbY6/btriSKdBPe2/Ceo3PIyIsuPyxlcRkDnCaK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XTbY6/btriSKdBPe2/Ceo3PIyIsuPyxlcRkDnCaK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXTbY6%2FbtriSKdBPe2%2FCeo3PIyIsuPyxlcRkDnCaK%2Fimg.png&quot; data-origin-width=&quot;955&quot; data-origin-height=&quot;576&quot; data-filename=&quot;jsp vs servlet.png&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&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;JSP와 Servlet은 둘 중에 어떤 것이 더 좋다라고 할 수 없습니다. 각각의 상황에 맞는 편리함, 유지보수의 관점에서 선택하여 사용하면 될 것 같습니다.&amp;nbsp;&lt;/p&gt;</description>
      <category>프로그래밍/WEB</category>
      <category>jsp</category>
      <category>Servlet</category>
      <category>web</category>
      <author>후르트링</author>
      <guid isPermaLink="true">https://frootjy.tistory.com/18</guid>
      <comments>https://frootjy.tistory.com/18#entry18comment</comments>
      <pubDate>Mon, 25 Oct 2021 16:27:45 +0900</pubDate>
    </item>
    <item>
      <title>[Web/용어정리] 서블릿(Servlet)이란</title>
      <link>https://frootjy.tistory.com/17</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;서블릿(Servlet)의 정의는 다음과 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&quot;웹 요청(request)의 동적인 처리가 가능한 서버(Server-side)의 자바 프로그램&quot;&lt;/b&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;[서블릿의 특징]&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;서블릿은 WAS안에 있는 서블릿 컨테이너를 통해 관리가 됩니다. &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;a style=&quot;color: #006dd7;&quot; href=&quot;https://frootjy.tistory.com/15&quot;&gt;(참고: was설명)&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;서블릿을 사용하게 되면 동적인 페이지를 생성할 수 있습니다.&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;a style=&quot;color: #006dd7;&quot; href=&quot;https://frootjy.tistory.com/16&quot;&gt;(참고 : 동적페이지 vs 정적 페이지)&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;서블릿은 JAVA 코드입니다. 서블릿 안에는 HTML 코드가 들어가 있습니다.&lt;br /&gt;(※JSP는 HTML코드 안에 JAVA 코드를 넣습니다.)&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;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음과 같은 HTML FORM이 있습니다.&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;&amp;lt;form name=&quot;loginForm&quot; method=&quot;post&quot; action=&quot;loginServlet&quot;&amp;gt;
    Username: &amp;lt;input type=&quot;text&quot; name=&quot;username&quot;/&amp;gt; &amp;lt;br/&amp;gt;
    Password: &amp;lt;input type=&quot;password&quot; name=&quot;password&quot;/&amp;gt; &amp;lt;br/&amp;gt;
    &amp;lt;input type=&quot;submit&quot; value=&quot;Login&quot; /&amp;gt;
&amp;lt;/form&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1) form 태그에서 action에 어떤 서블릿을 사용할지 정해주고(&quot;loginServlet&quot;), method에는 어떤 method를 사용할지 정해줍니다.(&quot;post&quot;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2) 그 다음 웹 서버로 전달합니다.&lt;/p&gt;
&lt;pre class=&quot;scala&quot;&gt;&lt;code&gt;public class LoginServlet extends HttpServlet {

    protected void doPost(HttpServletRequest request, HttpServletResponse response)
             throws ServletException, IOException {

        // html 폼에서 받은 정보
        String username = request.getParameter(&quot;username&quot;);
        String password = request.getParameter(&quot;password&quot;);

        // get response writer
        PrintWriter writer = response.getWriter();

        // HTML 코드 생성
        String htmlResponse = &quot;&amp;lt;html&amp;gt;&quot;;
        htmlResponse += &quot;&amp;lt;h2&amp;gt;Your username is: &quot; + username + &quot;&amp;lt;br/&amp;gt;&quot;;      
        htmlResponse += &quot;Your password is: &quot; + password + &quot;&amp;lt;/h2&amp;gt;&quot;;    
        htmlResponse += &quot;&amp;lt;/html&amp;gt;&quot;;

        // 생성된 HTML 코드를 return response
        writer.println(htmlResponse);    
    }
 }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3) 웹 서버에서 받은 정보는 Web Application Server에 있는 서블릿 컨테이너에게 전달 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4) 서블릿 컨테이너는 &quot;loginServlet&quot;에서 처리해야 한다는 것을 확인한 후에&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;​ -&amp;gt; LoginServlet 인스턴스가 없다면 생성하여 초기화 후 스레드를 생성합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;​ -&amp;gt; 있다면 기존 인스턴스에 스레드를 생성합니다.&lt;/p&gt;
&lt;p 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;5) doPost method를 실행하여 동적인 HTML 파일을 작성 한 후에 서블릿 컨테이너에 전달합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;6) 서블릿 컨테이너는 HTTP 형태로 바꾸어 웹 서버로 전송합니다. 그리고 스레드는 종료됩니다.&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;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-origin-width=&quot;620&quot; data-origin-height=&quot;507&quot; data-filename=&quot;서블릿 라이프사이클.png&quot; data-ke-mobilestyle=&quot;widthOrigin&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cM6KfR/btriCEzufCt/jA5c44FMCiWjQP9xaktOTk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cM6KfR/btriCEzufCt/jA5c44FMCiWjQP9xaktOTk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cM6KfR/btriCEzufCt/jA5c44FMCiWjQP9xaktOTk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcM6KfR%2FbtriCEzufCt%2FjA5c44FMCiWjQP9xaktOTk%2Fimg.png&quot; data-origin-width=&quot;620&quot; data-origin-height=&quot;507&quot; data-filename=&quot;서블릿 라이프사이클.png&quot; data-ke-mobilestyle=&quot;widthOrigin&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;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 본 것과 같이 서블릿 컨테이너는 서블릿 인스턴스를 찾거나, 생성하여 스레드를 사용해 실행합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 말하면, 서블릿 컨테이너는 요청을 받으면, 스레드를 생성하여 서블릿 인스턴스를 실행합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 요청이 N개가 들어온다면 스레드도 N개가 생성됩니다. (최대 스레드 개수를 넘지 않는 선에서)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&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;생성 될때 init() 메서드가 실행됩니다.&lt;/li&gt;
&lt;li&gt;서블릿이 요청을 받을 때마다 서블릿의 service() 메서드가 호출됩니다.
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;service() 메서드는 HTTP 요청 타입(GET, POST, PUT, DELETE 등등)을 확인하고 그에 맞는 메서드(doGet, doPost 등등)을 호출합니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;마지막으로 서블릿 인스턴스가 소멸할 때는 destroy() 메서드가 호출 됩니다.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>프로그래밍/WEB</category>
      <category>Servlet</category>
      <category>서블릿</category>
      <author>후르트링</author>
      <guid isPermaLink="true">https://frootjy.tistory.com/17</guid>
      <comments>https://frootjy.tistory.com/17#entry17comment</comments>
      <pubDate>Sun, 24 Oct 2021 18:32:00 +0900</pubDate>
    </item>
  </channel>
</rss>