<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>softwareNote</title>
    <link>https://soyangkim98.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Thu, 4 Jun 2026 23:28:12 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>haileykim1</managingEditor>
    <item>
      <title>[오류 기록] Custom WebSecurityConfigurerAdapter가 적용되지 않음</title>
      <link>https://soyangkim98.tistory.com/35</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;문제&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;WebSecurityConfigurerAdapter을 상속받은 SecurityConfig 클래스에서 configure 메서드를 오버라이딩하여 인증을 선택적으로 적용하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;/&quot; 은 permitAll을 적용한 url중 하나인데 /페이지에 접속하면 인증을 요구하였다.&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;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SecurityConfig 클래스가 포함된 oauth2 패키지가 @SpringBootApplication을 포함하고 있는 DeveloperCommunityApplication.kt 파일을 포함하는 프로젝트 패키지에 포함되어 있지 않았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 ComponentScan의 적용 대상이 되지 않았다.&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;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;oauth2 패키지를 developercommunity 패키지(프로젝트 패키지) 하위로 옮겼다.&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;h2 data-ke-size=&quot;size26&quot;&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Reference&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;a href=&quot;https://stackoverflow.com/questions/43868329/custom-security-is-not-working-when-extending-the-websecurityconfigureradapter-c&quot;&gt;https://stackoverflow.com/questions/43868329/custom-security-is-not-working-when-extending-the-websecurityconfigureradapter-c&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1656196276703&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;Custom security is not working when extending the WebSecurityConfigurerAdapter class in different package&quot; data-og-description=&quot;I have extendend WebSecurityConfigurerAdapter in a different package other than the package containing class for @SpringBootApplication. Then it's not working its generating default username and pa...&quot; data-og-host=&quot;stackoverflow.com&quot; data-og-source-url=&quot;https://stackoverflow.com/questions/43868329/custom-security-is-not-working-when-extending-the-websecurityconfigureradapter-c&quot; data-og-url=&quot;https://stackoverflow.com/questions/43868329/custom-security-is-not-working-when-extending-the-websecurityconfigureradapter-c&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cemkfk/hyOSHJ0PaU/O83bMoELSoS0AwiCB9TjVk/img.png?width=316&amp;amp;height=316&amp;amp;face=0_0_316_316&quot;&gt;&lt;a href=&quot;https://stackoverflow.com/questions/43868329/custom-security-is-not-working-when-extending-the-websecurityconfigureradapter-c&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://stackoverflow.com/questions/43868329/custom-security-is-not-working-when-extending-the-websecurityconfigureradapter-c&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cemkfk/hyOSHJ0PaU/O83bMoELSoS0AwiCB9TjVk/img.png?width=316&amp;amp;height=316&amp;amp;face=0_0_316_316');&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;Custom security is not working when extending the WebSecurityConfigurerAdapter class in different package&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;I have extendend WebSecurityConfigurerAdapter in a different package other than the package containing class for @SpringBootApplication. Then it's not working its generating default username and pa...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;stackoverflow.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;</description>
      <category>Spring</category>
      <category>antMatchers</category>
      <category>Issues</category>
      <category>not working</category>
      <category>permitAll</category>
      <category>SpringSecurity</category>
      <category>WebSecurityConfigurerAdapter</category>
      <author>haileykim1</author>
      <guid isPermaLink="true">https://soyangkim98.tistory.com/35</guid>
      <comments>https://soyangkim98.tistory.com/35#entry35comment</comments>
      <pubDate>Sun, 26 Jun 2022 07:32:01 +0900</pubDate>
    </item>
    <item>
      <title>CPU와 메모리</title>
      <link>https://soyangkim98.tistory.com/34</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;CPU&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;CPU의 기본 구성&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;산술논리 연산장치 ALU(Arithmetic and Logic Unit)&lt;br /&gt;&amp;nbsp;: 데이터의 산술 연산(덧셈, 뺄셈, 곱셈, 나눗셈 등)과 논리연산(AND, OR 등) 수행한다.&lt;/li&gt;
&lt;li&gt;제어장치 control unit&lt;br /&gt;&amp;nbsp;: CPU에서 작업을 지시하는 부분&lt;/li&gt;
&lt;li&gt;레지스터 register&lt;br /&gt;&amp;nbsp;: CPU내의 데이터를 임시로 보관하는 곳&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;h4 data-ke-size=&quot;size20&quot;&gt;가시 레지스터 user-visible register&lt;/h4&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;데이터 레지스터 data register (일반 레지스터, 범용 레지스터)&lt;br /&gt;&amp;nbsp;: 메모리에서 가져온 데이터를 임시로 보관할 때 사용한다.&lt;/li&gt;
&lt;li&gt;주소 레지스터 address register&lt;br /&gt;&amp;nbsp;: 데이터 또는 명령어가 저장된 메모리의 주소가 저장된느 곳이다.&lt;/li&gt;
&lt;/ul&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;프로그램 카운터(PC)&lt;br /&gt;&amp;nbsp;: 다음에 실행할 명령어의 주소를 저장하는 레지스터이다.&lt;/li&gt;
&lt;li&gt;명령어 레지스터(IR; instruction register)&lt;br /&gt;&amp;nbsp;: 현재 실행 중인 명령어를 저장한다.&lt;/li&gt;
&lt;li&gt;메모리 주소 레지스터(MAR; memory address register)&lt;br /&gt;&amp;nbsp;: 메모리에서 데이터를 가져오거나 메모리로 데이터를 보낼 때 주소를 지정하기 위해 사용한다.&lt;/li&gt;
&lt;li&gt;메모리 버퍼 레지스터(MBR; memory buffer register)&lt;br /&gt;&amp;nbsp;: 메모리에서 가져온 데이터나 메모리로 옮겨 갈 데이터를 임시로 저장한다.&lt;/li&gt;
&lt;li&gt;프로그램 상태 레지스터(PSR; program status register)&lt;br /&gt;&amp;nbsp;: 연산 결과(양수 음수 여부, 0인지 여부, 자리 올림 여부)를 저장한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;MBR은 항상 MAR과 함께 동작한다.&lt;/blockquote&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;버스는 CPU와 메모리, 주변장치 간에 데이터를 주고 받을 때 사용한다.&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;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;1. 제어버스&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음에 어떤 작업을 할 지 지시하는 제어 신호가 오고간다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) 읽기 신호, 쓰기 신호, 등&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메모리에서 오류가 발생한 경우나 주변장치에 데이터가 도착했다는 신호 등도 CPU로 전달된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제어버스의 신호는 CPU, 메모리, 주변장치와 &lt;b&gt;양방향&lt;/b&gt;으로 오고 간다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. 주소버스&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메모리의 데이터를 읽거나 쓸 때 어느 위치에서 작업할 것인지를 알려주는 주소가 오고 간다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;주소버스는 MAR과 연결되어 있고 &lt;b&gt;단방향&lt;/b&gt;이다.(CPU &amp;rarr; 주변장치)&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. 데이터버스&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터가 실려 목적지까지 이동하는 버스이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터 버스는 MBR와 연결되어 있으며 &lt;b&gt;양방향&lt;/b&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;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 번에 전달할 수 있는 데이터의 최대 크기이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CPU가 한 번에 처리할 수 있는 데이터의 크기와 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex) 32bit, 64bit&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;/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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;메모리의 종류&lt;/b&gt;&lt;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;램 Random Access Memory&lt;/h4&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;휘발성 메모리 volatility memory&lt;/li&gt;
&lt;/ul&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;DRAM (Dynamic Ram, 동적 램)&lt;br /&gt;&amp;nbsp;: 일정 시간이 지나면 사라지므로 일정 시간마다 다시 재생시켜야 한다.&lt;/li&gt;
&lt;li&gt;SRAM (Static RAM, 정적램)&lt;br /&gt;&amp;nbsp;: 전력이 공급되는 동안에는 데이터를 보관할 수 있어 재생할 필요가 없다.&lt;/li&gt;
&lt;li&gt;SDRAM (Synchronous Dynamic Random Access Memory)&lt;br /&gt;&amp;nbsp;: DRAM이 발전된 형태. 클록틱이 발생할 때 마다 데이터를 저장하는 동기 DRAM&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;비휘발성 메모리&amp;nbsp; non-volatility memory&lt;/li&gt;
&lt;/ul&gt;
&lt;ul style=&quot;list-style-type: circle;&quot; data-ke-list-type=&quot;circle&quot;&gt;
&lt;li&gt;플래시 메모리&lt;br /&gt;플래시메모리의 각 소자는 최대 사용 횟수가 제한되어 몇 천번~만번 사용하면 기능을 잃는다.&lt;/li&gt;
&lt;li&gt;FRAM Ferroelectric RAM&lt;/li&gt;
&lt;li&gt;PRAM Phase change RAM&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;비휘발성 메모리는 내부가 복잡하고 속도가 느리고 가격이 비싸서 메인메모리는 휘발성 메모리를 사용한다.&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;롬 Read Only Memory&lt;/h4&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;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;바이오스를 롬에 저장한다.&lt;/blockquote&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;CPU는 현재 진행 중인 작업의 메모리 시작 주소를 경계 레지스터(bound register)에 저장한 후 작업한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 현재 진행중인 작업이 차지하고 있는 메모리의 크기를 한계 레지스터(limit register)에 저장한다.&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;만약 두 레지스터 값을 벗어나면 메모리 오류와 관련된 인터럽트가 발생한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(인터럽트가 발생하면 모든 작업이 중단되고 CPU는 운영체제를 깨워서 인터럽트를 처리하도록 시킨다.)&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;운영체제도 CPU에 의해 실행되는 프로그램이기 때문에 메모리에 올라와야 한다&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;부팅 booting : 컴퓨터를 켰을 때 운영체제를 메모리에 올리는 과정&lt;/blockquote&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;바이오스는 CPU, 메모리, HDD, 키보드, 마우스와 같은 주요 HW가 제대로 작동하는지 확인한다.&lt;/li&gt;
&lt;li&gt;이상이 없으면 HDD의 마스터 부트 레코드(MBR)에 저장된 작은 프로그램을 메모리로 가져와 실행한다.&lt;/li&gt;
&lt;li&gt;HDD에 저장된 운영체제를 메모리로 불러온다.&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;마스터 부트 레코드 : 하드 디스크의 첫번째 섹터. OS를 실행하기 위한 코드인 부트스트랩이 저장되어 있다.&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;부트스트랩 코드 : OS를 메모리로 가져와 실행하는 역할을 하는 작은 프로그램&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;[출처]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쉽게 배우는 운영체제&lt;/p&gt;</description>
      <category>CS - Operating System</category>
      <category>CPU</category>
      <category>레지스터</category>
      <category>메모리</category>
      <category>버스</category>
      <category>운영체제</category>
      <author>haileykim1</author>
      <guid isPermaLink="true">https://soyangkim98.tistory.com/34</guid>
      <comments>https://soyangkim98.tistory.com/34#entry34comment</comments>
      <pubDate>Tue, 24 May 2022 16:48:09 +0900</pubDate>
    </item>
    <item>
      <title>컴퓨터의 기본 구성 - 하드웨어 구성</title>
      <link>https://soyangkim98.tistory.com/33</link>
      <description>&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;&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;중앙처리장치(CPU)&lt;/li&gt;
&lt;li&gt;메인메모리(제1저장장치, first storage)&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;입력장치&lt;/li&gt;
&lt;li&gt;출력장치&lt;/li&gt;
&lt;li&gt;저장장치(제2저장장치, second storage)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;CPU와 메모리&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;CPU : 명령어를 해석하여 실행하는 장치.&lt;/li&gt;
&lt;li&gt;메모리 : 작업에 필요한 프로그램과 데이터를 저장하는 장소.&lt;/li&gt;
&lt;/ul&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;br /&gt;ex) 키보드, 마우스, 스캐너&lt;/li&gt;
&lt;li&gt;출력장치 :&amp;nbsp; 컴퓨터에서 처리한 결과를 사용자가 원하는 형태로 출력하는 장치&lt;br /&gt;ex) 프린터, 모니터, 스피커 등&lt;/li&gt;
&lt;/ul&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;/li&gt;
&lt;li&gt;레이저를 이용하는 장치 : CD, DVD, 블루레이디스크 등&lt;/li&gt;
&lt;li&gt;메모리를 이용하는 장치 : USB, SD 카드, CF 카드, SSD 등&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;메인보드&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CPU와 메모리 등 다양한 부품을 연결하는 커다란 판이다.&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;폰 노이만 구조 von Neumann architecture&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;CPU, 메모리, 입출력장치, 저장장치가 버스로 연결되어있는 구조이다.&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;h4 data-ke-size=&quot;size20&quot;&gt;클록 clock&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CPU 속도와 관련된 단위&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클록이 일정 간격으로 틱을 만들어 내면 거기에 맞추어 CPU안의 모든 구성 부품이 작업을 한다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;헤르츠&amp;nbsp; Hz&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클록틱이 발생하는 속도를 말한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1초에 클록틱 한 번 = 1Hz&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;시스템 버스와 내부 버스&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시스템 버스 = FSB(Front-Side Bus) : 메모리와 주변 장치를 연결하는 버스&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CPU 내부 버스 = BSB(Back-Side Bus) :&amp;nbsp; CPU 내부에 있는 장치를 연결하는 버스.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CPU의 클록과 같아서 시스템 버스보다 훨씬 빠르다.&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;쉽게 배우는 운영체제&lt;/p&gt;</description>
      <category>CS - Operating System</category>
      <category>운영체제</category>
      <category>입력장치</category>
      <category>저장장치</category>
      <category>출력장치</category>
      <category>클록</category>
      <category>폰 노이만 구조</category>
      <category>하드웨어 구성</category>
      <author>haileykim1</author>
      <guid isPermaLink="true">https://soyangkim98.tistory.com/33</guid>
      <comments>https://soyangkim98.tistory.com/33#entry33comment</comments>
      <pubDate>Tue, 24 May 2022 15:12:30 +0900</pubDate>
    </item>
    <item>
      <title>[Spring][Kotlin] 빈 스코프</title>
      <link>https://soyangkim98.tistory.com/31</link>
      <description>&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;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;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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;request : 웹 요청이 들어오고 나갈때 까지 유지되는 스코프&lt;/li&gt;
&lt;li&gt;session : 웹 세션이 생성되고 종료될 때 까지 유지되는 스코프&lt;/li&gt;
&lt;li&gt;application : 웹의 서블릿 컨텍스트와 같은 범위로 유지되는 스코프&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;빈 스코프는 다음과 같이 지정 가능하다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[컴포넌트 스캔 자동 등록]&lt;/p&gt;
&lt;pre id=&quot;code_1653111194024&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Scope(&quot;prototype&quot;)
@Component
class HelloBean{...}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[수동 등록]&lt;/p&gt;
&lt;pre id=&quot;code_1653111795425&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class LifeCycleConfig{
	@Scope(&quot;prototype&quot;)
	@Bean
	fun helloBean = HelloBean()
}&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;프로토타입 스코프&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&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;619&quot; data-origin-height=&quot;353&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/D2HAd/btrCKj9H62M/iNWubRkFzo2bIPATRJiLtk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/D2HAd/btrCKj9H62M/iNWubRkFzo2bIPATRJiLtk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/D2HAd/btrCKj9H62M/iNWubRkFzo2bIPATRJiLtk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FD2HAd%2FbtrCKj9H62M%2FiNWubRkFzo2bIPATRJiLtk%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;619&quot; height=&quot;353&quot; data-origin-width=&quot;619&quot; data-origin-height=&quot;353&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;445&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cVML4X/btrCKXefAoZ/F8ULXq0lK3wTWvPe73bcWk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cVML4X/btrCKXefAoZ/F8ULXq0lK3wTWvPe73bcWk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cVML4X/btrCKXefAoZ/F8ULXq0lK3wTWvPe73bcWk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcVML4X%2FbtrCKXefAoZ%2FF8ULXq0lK3wTWvPe73bcWk%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;717&quot; height=&quot;406&quot; data-origin-width=&quot;786&quot; data-origin-height=&quot;445&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;750&quot; data-origin-height=&quot;424&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/x1uVv/btrCIHKsUji/do9UMLDZHroRbK4STHyIdk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/x1uVv/btrCIHKsUji/do9UMLDZHroRbK4STHyIdk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/x1uVv/btrCIHKsUji/do9UMLDZHroRbK4STHyIdk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fx1uVv%2FbtrCIHKsUji%2Fdo9UMLDZHroRbK4STHyIdk%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;711&quot; height=&quot;402&quot; data-origin-width=&quot;750&quot; data-origin-height=&quot;424&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;&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;gt; @PreDestroy가 자동으로 호출되자 않는다.&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;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;아래에서 싱글톤 빈이 의존관계 주입을 통해 프로토타입 빈을 주입받아서 사용하는 예를 보자&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;634&quot; data-origin-height=&quot;346&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OMOpz/btrCLzqINTK/EW7Aa2N4nYznUOR6WCAZYK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OMOpz/btrCLzqINTK/EW7Aa2N4nYznUOR6WCAZYK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OMOpz/btrCLzqINTK/EW7Aa2N4nYznUOR6WCAZYK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOMOpz%2FbtrCLzqINTK%2FEW7Aa2N4nYznUOR6WCAZYK%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;634&quot; height=&quot;346&quot; data-origin-width=&quot;634&quot; data-origin-height=&quot;346&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;clientBean은 싱글톤이므로 스프링 컨테이너 생성 시점에 함께 생성되고 의존관계 주입도 발생한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;clientBean이 의존관계 자동 주입을 사용한다면 주입 시점에 스프링 컨테이너에 프로토타입 빈을 요청한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스프링 컨테이너는 프로토타입 빈을 생성해서 clientBean에 반환한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;clientBean은 프로토타입 빈의 참조값을 내부 필드에 보관한다.&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;클라이언트가 싱글톤 빈인 clientBean을 스프링 컨테이너에게 요청해서 받고 그 내부의 프로토타입 빈을 이용해서 로직을 수행하는 상황이 있다.&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;프로토타입 스코프 : 싱글톤 빈과 함께 사용 시 Provider로 문제 해결&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금 필요한 기능은 지정한 프로토타입 빈을 컨테이너에서 찾아주는 DL기능이다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;DL : Dependency Lookup = 의존관계 탐색&lt;/blockquote&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;ObjectFactory, ObjectProvider&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[ObjectProvider]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: getObject하면 그때서야 스프링 컨테이너에게 오브젝트 받아서 반환해주는 기능 제공(DL)&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;[ObjectFactory]&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;: getObject 기능 하나만 제공&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;ObjectProvider는 ObjectFactory 인터페이스를 상속받고 있다.&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;정리&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;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;스프링이 제공하는 기능와 자바 표준이 둘다 비슷한 기능을 제공한다면 다양하고 편리한 기능을 제공해주는 스프링을 쓰자.&lt;br /&gt;다른 컨테이너를 쓸 일이 있다면 자바 표준을 쓰면 된다.&lt;/blockquote&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;p data-ke-size=&quot;size16&quot;&gt;프로토타입 스코프와 다르게 스프링이 스코프의 종료시점까지 관리한다. -&amp;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;request&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTTP 요청 하나가 들어오고 나갈 때 까지 유지되는 스코프.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각각의 HTTP 요청마다 별도의 빈 인스턴스가 생성되고 관리된다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;session&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;HTTP Session과 동일한 생명주기를 가지는 스코프&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;application&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서블릿 컨텍스트(Servlet Context)와 동일한 생명주기를 가지는 스코프&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;websocket&lt;/h4&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;blockquote data-ke-style=&quot;style2&quot;&gt;P] 스프링 앱 실행 시점에 싱글톤 빈 생성해서 주입 가능하지만 request 빈은 실제 고객의 요청이 와야 생성이 가능하기 때문에 오류가 발생할 수 있다.&lt;/blockquote&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;스코프와 Provider&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Provider을 적용한다면 ObjectProvider.getObject()를 호출하는 시점까지 request scope 빈의 생성을 지연할 수 있다.&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;pre id=&quot;code_1653114641936&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Component
@Scope(value = &quot;request&quot;, proxyMode = ScopedProxyMode.TARGET_CLASS)
class xxx{...}&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;적용 대상이 클래스면 TARGET_CLASS,&amp;nbsp;&lt;br /&gt;적용 대상이 인터페이스이면 INTERFACES를 선택&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;이렇게 프록시 방식을 사용하기만 하면 오류가 발생하지 않는다.&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;주입된 스코프 빈의 클래스 정보를 찍어보면 CGLIB 라이브러리로 만든 객체라는 것을 알 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1653115057384&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//클래스 정보 출력 결과
xxx = class soyang.hellocore.common.xxx$$EnhancerBySpringCGLIB&amp;amp;&amp;amp;~~~&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;@Scope의 proxyMode = ScopedProxyMode.TARGET_CLASS 를 설정하면 스프링 컨테이너는 CGLIB라는 바이트코드를 조작하는 라이브러리를 사용해서 xxx를 상속받은 가짜 프록시 객체를 생성한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 스프링 컨테이너에 빈 이름으로 진짜 대신 가짜 프록시 객체를 등록한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(xxx 타입의 자식 타입이기 때문에 빈 조회시 조회 가능하다)&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;&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;클라이언트가 객체의 메서드를 호출하면 (이 객체는 프록시 객체이므로) 가짜 프록시 객체의 메서드가 호출되지만 이 가짜 프록시 객체가 request 스코프의 진짜 객체의 메서드를 호출한다.&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;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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard&quot;&gt;https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1653110398235&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;스프링 핵심 원리 - 기본편 - 인프런 | 강의&quot; data-og-description=&quot;스프링 입문자가 예제를 만들어가면서 스프링의 핵심 원리를 이해하고, 스프링 기본기를 확실히 다질 수 있습니다., - 강의 소개 | 인프런...&quot; data-og-host=&quot;www.inflearn.com&quot; data-og-source-url=&quot;https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard&quot; data-og-url=&quot;https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/GcyPG/hyOue8xOf6/dEzFJvEvlwC4dF1uistjTk/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/ba8nIk/hyOuhYvqea/WHkbPC0prPKgdnmrqkNIik/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/n2Xjn/hyOs74eqzB/EI8z1vmiKN7iQijzAFf9l0/img.png?width=1000&amp;amp;height=479&amp;amp;face=0_0_1000_479&quot;&gt;&lt;a href=&quot;https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/GcyPG/hyOue8xOf6/dEzFJvEvlwC4dF1uistjTk/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/ba8nIk/hyOuhYvqea/WHkbPC0prPKgdnmrqkNIik/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/n2Xjn/hyOs74eqzB/EI8z1vmiKN7iQijzAFf9l0/img.png?width=1000&amp;amp;height=479&amp;amp;face=0_0_1000_479');&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;스프링 핵심 원리 - 기본편 - 인프런 | 강의&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;스프링 입문자가 예제를 만들어가면서 스프링의 핵심 원리를 이해하고, 스프링 기본기를 확실히 다질 수 있습니다., - 강의 소개 | 인프런...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.inflearn.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;</description>
      <category>Spring</category>
      <category>kotlin</category>
      <category>Spring</category>
      <category>빈 스코프</category>
      <category>싱글톤</category>
      <category>웹 스코프</category>
      <category>프로토타입</category>
      <author>haileykim1</author>
      <guid isPermaLink="true">https://soyangkim98.tistory.com/31</guid>
      <comments>https://soyangkim98.tistory.com/31#entry31comment</comments>
      <pubDate>Sat, 21 May 2022 15:44:08 +0900</pubDate>
    </item>
    <item>
      <title>[Spring][Kotlin] 빈 생명주기 콜백</title>
      <link>https://soyangkim98.tistory.com/30</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DB 커넥션 풀이나 네트워크 소켓처럼 애플리케이션 시작 시점에 필요한 연결을 미리 해두고, 애플리케이션 종료 시점에 연결을 모두 종료하는 작업을 진행하려면 &lt;b&gt;객체의 초기화 + 종료 작업&lt;/b&gt;이 필요하다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;서버 뜰 때 애플리케이션이랑 DB를 미리 10~100개정도 연결해놓는다.&lt;br /&gt;고객 요청이 올 때 연결해놓을 걸 재활용할 수 있다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;스프링 빈은 간단하게 다음과 같은 lifeCycle을 가진다&lt;br /&gt;객체 생성 -&amp;gt; 의존관계 주입&lt;br /&gt;(예외 : 생성자 주입)&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스프링 빈은 객체 생성 후 의존관계 주입이 다 끝난 다음에야 필요한 데이터를 사용할 수 있는 준비가 완료된다&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;=&amp;gt; 안전하게 초기화 + 종료 작업 진행이 가능하다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;스프링 빈의 이벤트 라이프사이클(싱글톤 빈)&lt;br /&gt;스프링 컨테이너 생성 -&amp;gt; 스프링 빈 생성 -&amp;gt; 의존관계 주입 -&amp;gt; 초기화 콜백 -&amp;gt; 사용 -&amp;gt; 소멸 전 콜백 -&amp;gt; 스프링 종료&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(생명주기가 짧은 빈들은 컨테이너와 무관하게 해당 빈이 종료되기 직전 소멸 전 콜백이 일어난다. 자세한건 스코프에서)&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;객체의 생성과 초기화는 분리하는 것이 좋다.&lt;br /&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;스프링 빈 생명주기 콜백 지원방식은 3가지가 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;인터페이스(InitializingBean, DisposableBean)&lt;/li&gt;
&lt;li&gt;설정 정보에 초기화 메서드, 종료 메서드 지원&lt;/li&gt;
&lt;li&gt;@PostConstruct, @PreDestroy 애노테이션 지원&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;인터페이스 InitializingBean, Disposable Bean&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인터페이스 InitializingBean, DisposableBean을 구현해서 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;초기화 메서드인 afterPropertiesSet과 소멸 메서드인 destroy를 override 하여 사용한다.&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;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;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;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;pre id=&quot;code_1653109256793&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Configuration
class LifeCycleConfig{

	@Bean(initMethod = &quot;init&quot;, destroyMethod = &quot;close&quot;)
    fun networkClient(): NetworkClient{...}

}&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;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;코드가 아니라 설정 정보를 사용하기 때문에 코드를 고칠 수 없는 외부 라이브러리에도 초기화, 종료 메서드 적용이 가능하다.(NetworkClient 코드 내부가 아니라 설정정보에서 메서드를 지정했다.)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;종료 메서드 추론&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@Bean의 destroyMethod는 default 값이 (inferred)이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;라이브러리는 대부분 close, shutdown이라는 종료 메서드를 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 종료 메서드를 inferred(추론) 하여 close, shutdown이라는 이름의 메서드를 자동으로 호출해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 직접 스프링 빈으로 등록하면 종료 메서드는 따로 적어주지 않아도 잘 동작한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추론 기능을 사용하기 싫으면 destroyMethod = &quot;&quot; 로 지정해주면 된다.&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;애노테이션 @PostConstruct, @PreDestroy&lt;/b&gt;&lt;/h3&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;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;javax는 자바 진영에서 공식적으로 지원하는것이다.&lt;br /&gt;꼭 스프링이 아니라 다른 컨테이너를 사용하더라도 적용 가능하다&lt;/blockquote&gt;
&lt;pre id=&quot;code_1653110269782&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class NetworkClient{


	...
	
    @PostConstruct
    fun init(){...}
    
    @PreDestroy
    fun close(){...}
    
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1653110320295&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Configuration
class LifeCycleConfig{

	@Bean
    fun networkClient: NetworkClient{...}

}&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;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;/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://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard&quot;&gt;https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1653107272124&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;스프링 핵심 원리 - 기본편 - 인프런 | 강의&quot; data-og-description=&quot;스프링 입문자가 예제를 만들어가면서 스프링의 핵심 원리를 이해하고, 스프링 기본기를 확실히 다질 수 있습니다., - 강의 소개 | 인프런...&quot; data-og-host=&quot;www.inflearn.com&quot; data-og-source-url=&quot;https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard&quot; data-og-url=&quot;https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/GcyPG/hyOue8xOf6/dEzFJvEvlwC4dF1uistjTk/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/ba8nIk/hyOuhYvqea/WHkbPC0prPKgdnmrqkNIik/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/n2Xjn/hyOs74eqzB/EI8z1vmiKN7iQijzAFf9l0/img.png?width=1000&amp;amp;height=479&amp;amp;face=0_0_1000_479&quot;&gt;&lt;a href=&quot;https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/GcyPG/hyOue8xOf6/dEzFJvEvlwC4dF1uistjTk/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/ba8nIk/hyOuhYvqea/WHkbPC0prPKgdnmrqkNIik/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/n2Xjn/hyOs74eqzB/EI8z1vmiKN7iQijzAFf9l0/img.png?width=1000&amp;amp;height=479&amp;amp;face=0_0_1000_479');&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;스프링 핵심 원리 - 기본편 - 인프런 | 강의&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;스프링 입문자가 예제를 만들어가면서 스프링의 핵심 원리를 이해하고, 스프링 기본기를 확실히 다질 수 있습니다., - 강의 소개 | 인프런...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.inflearn.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;</description>
      <category>Spring</category>
      <category>@PostConstruct</category>
      <category>@PreDestroy</category>
      <category>kotlin</category>
      <category>Spring</category>
      <category>빈 생명주기 콜백</category>
      <author>haileykim1</author>
      <guid isPermaLink="true">https://soyangkim98.tistory.com/30</guid>
      <comments>https://soyangkim98.tistory.com/30#entry30comment</comments>
      <pubDate>Sat, 21 May 2022 14:18:46 +0900</pubDate>
    </item>
    <item>
      <title>[Spring][Kotlin]의존관계 자동 주입</title>
      <link>https://soyangkim98.tistory.com/29</link>
      <description>&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;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;수정자 주입(setter 주입)&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;h4 data-ke-size=&quot;size20&quot;&gt;생성자 주입&lt;/h4&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;생성자 호출 시점에 딱 한번만 호출되는 것이 보장 -&amp;gt; 그때 값 세팅하고 그 후 세팅 못하게 막기 가능하다&lt;/li&gt;
&lt;li&gt;&lt;b&gt;불변, 필수&lt;/b&gt; 의존관계에 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;생성자가 딱 하나 있다면 @Autowired 생략 가능하다.&lt;br /&gt;(스프링 빈인 경우)&lt;/blockquote&gt;
&lt;pre id=&quot;code_1652890186139&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Component
class OrderServiceImpl: OrderService{

	val memberRepository: MemberRepository
    val discountPolicy: DiscountPolicy
    
    @Autowired
    constructor(memberRepository: MemberRepository, discountPolicy: DiscountPolicy){
    
    	this.memberRepository = memberRepository
        this.discountPolicy = discountPolicy
    }


}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;수정자 주입&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;: 수정자 메서드 setter를 통해 의존관계 주입하는 방법이다.&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;/li&gt;
&lt;li&gt;빈 등록과 의존관계 주입이 나뉘어져 있는 경우임&lt;/li&gt;
&lt;li&gt;값 주입해주면 생성자 주입은 필요없음&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1652890150372&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Component
class OrderServiceImpl: OrderService{

	lateinit var memberRepository: MemberRepository
    lateinit var discountPolicy: DiscountPolicy
    
    @Autowired
    fun setMemberRepository(memberRepository: MemberRepository){
    	this.memberRepisotry = memberRepository
    }
	
    @Autowired
    fun setDiscountPolicy(discountPolicy: DiscountPolicy){
    	this.discountPolicy = discountPolicy
    }

}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;필드 주입&lt;/h4&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;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;DI 프레임워크가 없으면 아무것도 할 수 없다&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;쓰지 말자.&lt;/blockquote&gt;
&lt;pre id=&quot;code_1652890502411&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Component
class OrderServiceImpl: OrderService{
	
    @Autowired
	lateinit var memberRepository: MemberRepository
    @Autowired
    lateinit var discountPolicy: DiscountPolicy
    
    }

}&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;/h4&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;/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;blockquote data-ke-style=&quot;style2&quot;&gt;의존관계 자동 주입은 스프링 컨테이너가 관리하는 스프링 빈이어야 동작한다. 스프링 빈이 아닌 클래스에서 Autowired 코드를 적용해도 아무 기능도 동작하지 않는다.&lt;/blockquote&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;주입할 스프링 빈이 없어도 동작해야 할 때가 있다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 @Autowired만 사용하면 required 옵션 default 값이 true이기 때문에 자동 주입 대상이 없으면 오류가 발생할 수 있다.&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;Autowired(required = false) : 자동 주입할 대상이 없으면 수정자 메서드 자체가 호출 안됨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;org.springframework.lang.@Nullable : 자동 주입할 대상이 없으면 null이 입력된다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Optional&amp;lt;&amp;gt; : 자동 주입할 대상이 없으면 Optional.empty가 입력된다&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Optional은 값이 null일수도 있고 아닐수도 있다는 상태를 감싼 것이다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;@Nullable, Optional은 스프링 전반에 걸쳐서 지원된다.&lt;/blockquote&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;최근에는 스프링을 포함한 DI 프레임워크 대부분이 생성자 주입을 권장한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[이유]&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 불변&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;수정자 주입을 사용하면 setter 메서드들을 public으로 열어두어야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. 누락&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;: 프레임워크 없이 순수 자바 코드 단위 테스트하는 경우 생성자 주입을 사용하면 필수 값들이 안들어가면 컴파일 오류가 뜨가 때문에 미리 버그를 잡을 수 있다.(@Autowired가 동작하지 않기 때문에)&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;3. final 키워드를 넣을 수 있음&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생성자 주입을 사용하면 필드에 final 키워드를 넣을 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;kotlin에서도 val을 사용할 수 있다.&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;/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;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;p data-ke-size=&quot;size16&quot;&gt;@Autowired는 타입으로 빈을 조회한다.&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;이때의 해결방법을 알아보자&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;@Autowired 필드 명 매칭&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@Autowired는 타입 매칭을 시도하고 이때 여러 빈이 있으면 필드 이름, 파라미터 이름으로 빈 이름을 추가 매칭한다.&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;@Qualifier -&amp;gt; @Qualifier 끼리 매칭 -&amp;gt; 빈 이름 매칭&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@Qualifier는 추가 구분자를 붙여주는 방법이다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;이것은 빈 이름을 변경하는 것은 아니다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;등록 시 Qualifier 애노테이션 붙이고 생성자 주입에서나 수정자 주입에서 필드 앞에 Qualifier 애노테이션으로 지정하면 된다.&lt;/p&gt;
&lt;pre id=&quot;code_1653104435725&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Component
@Qualifier(&quot;mainDiscountPolicy&quot;)
class RateDiscountPolicy: DiscountPolicy{...}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1653104535962&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Autowired
constructor(memberRepository: MemberRepository, 
			@Qualifier(&quot;mainDiscountPolicy&quot;) discountPolicy: DiscountPolicy){
            
	this.memberRepository = memberRepository
    this.discountPolicy = discountPolicy
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@Qualifier로 주입할 때 해당 Qualifier를 못찾으면 위의 mainDiscountPolicy 처럼 Qualifier안의 문자열과 같은이름의 스프링 빈을 추가로 찾는다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 Qualifier용도로만 사용하는 게 명확하고 좋다.&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;h4 data-ke-size=&quot;size20&quot;&gt;@Primary 사용&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것도 편하고 자주 사용하는 방법이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@Autowired시에 여러 빈이 매칭이 되면 @Primary 가진 빈이 우선권을 가진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;메인 DB 커넥션을 획득하는 스프링 빈은 Primary를 적용해서 조회하는 것에 Qualifier지정 없이 편하게 조회하고,&lt;br /&gt;서브 DB 커넥션 빈을 획득할 때는 Qualifier 지정해서 명시적으로 획득하면 코드를 깔끔하게 유지할 수 있다.&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Primary와 Qualifier가 만나면 Qualifier 가 우선권을 갖는다&lt;br /&gt;Qualifier이 더 세세한 설정이기 때문&lt;/blockquote&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;@Qualifier(&quot;xxx&quot;) 이렇게 적으면 컴파일 시 문자열로 타입 체크가 안되기 때문에 실수를 모르고 넘어갈 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 @xxx 과 같은 애노테이션을 만들어서 문제를 해결할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot;&gt;&lt;code&gt;package soyang.hellocore.annotation

import org.springframework.beans.factory.annotation.Qualifier
import java.lang.annotation.*
import java.lang.annotation.Retention
import java.lang.annotation.Target

@Target(ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER, ElementType.TYPE, ElementType.ANNOTATION_TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@Qualifier(&quot;mainDiscountPolicy&quot;)
annotation class MainDiscountPolicy()&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot;&gt;&lt;code&gt;package soyang.hellocore.discount

import org.springframework.stereotype.Component
import soyang.hellocore.annotation.MainDiscountPolicy
import soyang.hellocore.member.Grade
import soyang.hellocore.member.Member

@Component
@MainDiscountPolicy
class RateDiscountPolicy: DiscountPolicy {...}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot;&gt;&lt;code&gt;@Component
class OrderServiceImpl: OrderService {

    val memberRepository: MemberRepository
    val discountPolicy: DiscountPolicy

    @Autowired
    constructor(memberRepository: MemberRepository,
                @MainDiscountPolicy discountPolicy: DiscountPolicy){
        this.memberRepository = memberRepository
        this.discountPolicy = discountPolicy
    }

	...
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;애노테이션에는 상속이라는 개념이 없다.&lt;br /&gt;이렇게 여러 애노테이션을 모아서 사용하는 기능은 스프링이 지원해주는 기능이다.&lt;br /&gt;Autowired도 재정의 가능하지만 뚜렷한 기능을 무분별하게 재정의하는 것은 유지보수에 혼란을 줄 뿐이다.&lt;/blockquote&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;조회한 빈이 모두 필요할 때, List, Map&lt;/b&gt;&lt;/h3&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;p data-ke-size=&quot;size16&quot;&gt;서비스가 모든 Policy를 다 주입받고 어떤 메서드로 string이 내려오면 map에서 string으로 Policy 찾아서 해당 로직을 호출하면 된다.&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;HashMap&amp;lt;String, 빈 타입&amp;gt;으로 빈을 모두 저장한 다음 입력된 spring으로 검색해서 해당 빈을 사용해서 로직 수행하면 된다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;실무에서는 HashMap 대신 ConcurrentHashMap을 써야 Thread-safe 하게 동작할 수 있다.&lt;/blockquote&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;h4 data-ke-size=&quot;size20&quot;&gt;편리한 자동 기능을 기본으로 하자&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;: 스프링이 나오고 시간이 많이 지나서 Component 뿐만 아니라 Controller, Service, Repository 처럼 계층에 맞추어 일반적인 애플리케이션 로직을 자동으로 스캔할 수 있도록 지원한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자동 빈 등록을 해도 OCP, DIP 지킬 수 있다.&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;/h4&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;기술 지원 빈 : 기술적인 문제나 공통 관심사(AOP)를 처리할 때 주로 사용된다. DB 연결이나 공통 로그 처리처럼 업무 로직을 지원하기 위한 하부 기술이나 공통 기술들이다.&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;기술지원 로직은 수는 적지만 애플리케이션 전반에 걸쳐서 광범위하게 영향을 미치고 적용이 잘 되고 있는지 여부를 파악하기 어려운 경우가 많으므로 수동 빈 등록을 해서 명확하게 드러내는 것이 좋다.&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;[출처]&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://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard&quot;&gt;https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1652888656861&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;스프링 핵심 원리 - 기본편 - 인프런 | 강의&quot; data-og-description=&quot;스프링 입문자가 예제를 만들어가면서 스프링의 핵심 원리를 이해하고, 스프링 기본기를 확실히 다질 수 있습니다., - 강의 소개 | 인프런...&quot; data-og-host=&quot;www.inflearn.com&quot; data-og-source-url=&quot;https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard&quot; data-og-url=&quot;https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/f32cU/hyOra1kj6k/KSM7xrGglwg9yLDEI69xDK/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/bfMCPa/hyOrfVRzwK/QAaIU1vH3YfCEv1CN1cRMK/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/E3GU5/hyOsqVNAF7/dEBfuiIKiwXDQkfxr0YPqK/img.png?width=1805&amp;amp;height=1044&amp;amp;face=0_0_1805_1044&quot;&gt;&lt;a href=&quot;https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/f32cU/hyOra1kj6k/KSM7xrGglwg9yLDEI69xDK/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/bfMCPa/hyOrfVRzwK/QAaIU1vH3YfCEv1CN1cRMK/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/E3GU5/hyOsqVNAF7/dEBfuiIKiwXDQkfxr0YPqK/img.png?width=1805&amp;amp;height=1044&amp;amp;face=0_0_1805_1044');&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;스프링 핵심 원리 - 기본편 - 인프런 | 강의&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;스프링 입문자가 예제를 만들어가면서 스프링의 핵심 원리를 이해하고, 스프링 기본기를 확실히 다질 수 있습니다., - 강의 소개 | 인프런...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.inflearn.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;</description>
      <category>Spring</category>
      <category>kotlin</category>
      <category>Spring</category>
      <category>생성자 주입</category>
      <category>스프링</category>
      <category>의존관계 자동 주입</category>
      <category>코틀린</category>
      <author>haileykim1</author>
      <guid isPermaLink="true">https://soyangkim98.tistory.com/29</guid>
      <comments>https://soyangkim98.tistory.com/29#entry29comment</comments>
      <pubDate>Sat, 21 May 2022 13:26:45 +0900</pubDate>
    </item>
    <item>
      <title>[Spring][Kotlin]컴포넌트 스캔</title>
      <link>https://soyangkim98.tistory.com/28</link>
      <description>&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;+ 의존관계 자동으로 주입하는 @Autowired 기능도 제공한다.&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;h4 data-ke-size=&quot;size20&quot;&gt;컴포넌트 스캔&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@ComponentScan을 설정정보에 붙여주면 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴포넌트 스캔은 @Component 애노테이션이 붙은 클래스를 스캔해서 스프링 빈으로 등록한다.&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;Autowired 의존관계 자동 주입&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전에는 설정정보 클래스에서 @Bean으로 직접 설정 정보를 작성했고 의존관계도 명시했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 컴포넌트 스캔을 사용하면 이런 설정 정보 자체가 없기 때문에 의존관계 주입도 @Autowired를 통해서 해주어야한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@Autowired를 사용하면 생성자에서 여러 의존관계도 한번에 주입받을 수 있다.&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;@Autowired 테스트 시 싱글톤 빈의 인스턴스 인식한 로그와 Autowired한 내용도 나오는데, 빈 이름 규칙은 다음과 같다.&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;빈 이름 직접 지정 : @Component(&quot;이름&quot;)&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;1280&quot; data-origin-height=&quot;435&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bbCjJg/btrCw9TvNDY/yjmj3zvGP4Y1hkmRKNQKM0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bbCjJg/btrCw9TvNDY/yjmj3zvGP4Y1hkmRKNQKM0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bbCjJg/btrCw9TvNDY/yjmj3zvGP4Y1hkmRKNQKM0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbbCjJg%2FbtrCw9TvNDY%2Fyjmj3zvGP4Y1hkmRKNQKM0%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;435&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;435&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생성자에 파라미터가 많아도 @Component 붙은 클랫 다 찾아서 자동으로 주입한다.&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;h4 data-ke-size=&quot;size20&quot;&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;basePackages : 탐색할 패키지의 시작 위치를 지정한다. 이 패키지를 포함해서 하위 패키지를 모두 탐색한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;basePackageClasses : 지정한 클래스의 패키지를 탐색 시작 위치로 지정한다.&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;h4 data-ke-size=&quot;size20&quot;&gt;컴포넌트 스캔 기본 대상&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴포넌트 스캔은 @Component뿐만 아니라 다음 내용도 추가로 대상에 포함된다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;@Component : 컴포넌트 스캔에 사용&lt;/li&gt;
&lt;li&gt;@Controller : 스프링 MVC 컨트롤러에서 사용&lt;/li&gt;
&lt;li&gt;@Service : 스프링 비즈니스 로직에서 사용&lt;/li&gt;
&lt;li&gt;@Repository : 스프링 데이터 접근 계층에서 사용&lt;/li&gt;
&lt;li&gt;@Configuration : 스프링 설정 정보에서 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;해당 애노테이션으로 가보면 안에 @Component 붙어있다.&lt;br /&gt;하지만 사실 Annotation에는 상속관계라는게 없다.&lt;br /&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;컴포넌트 스캔의 용도 뿐만 아니라 다음 애노테이션이 있으면 스프링은 부가 기능을 수행한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;@Controller : 스프링 MVC 컨트롤러로 인식&lt;/li&gt;
&lt;li&gt;@Repository : 스프링 데이터 접근 계층으로 인식, 데이터 계층의 예외를 스프링 예외로 변환해줌&lt;/li&gt;
&lt;li&gt;@Configuration : 스프링 설정 정보로 안식하고 스프링 빈이 싱글톤을 유지하도록 추가 처리함&lt;/li&gt;
&lt;li&gt;@Service : 특변한 처리하지 않지만 개발자들이 핵심 비즈니스 로직 계측 인식하는 데 도움을 줌&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;includeFilters : 컴포넌트 스캔 대상 추가 지정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;excludeFilters : 컴포넌트 스캔에서 제외할 대상 지정&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;자체 애노테이션 만들어서 적용 대상 지정할 수 있다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;FilterType 옵션&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ANNOTATION : 디폴트. 애노테이션을 인식해서 동작&lt;br /&gt;ex) org.example.xxAnnotation&lt;/li&gt;
&lt;li&gt;ASSIGNABLE_TYPE : 지정한 타입과 자식 타입을 인색해서 동작한다.&lt;br /&gt;ex) org.example.xxClass&lt;/li&gt;
&lt;li&gt;REGEX : 정규 표현식&lt;br /&gt;ex)org\.example\.Default.*&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;(잘 사용하는 일이 없다)&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;p data-ke-size=&quot;size16&quot;&gt;Q. 컴포넌트 스캔에서 같은 빈 이름으로 등록하면 어떻게 될까?&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;자동 빈 등록 vs 자동 빈 등록&lt;/li&gt;
&lt;li&gt;자동 빈 등록 vs 수동 빈 등록&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;자동 빈 등록 vs 자동 빈 등록&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스프링에 의해 ConflictBeanDefinitionException 예외가 발생한다.&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;자동 빈 등록 vs 수동 빈 등록&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;blockquote data-ke-style=&quot;style2&quot;&gt;이것으로 인해 여러 설정들이 꼬려 버그가 많이 만들어졌다.&lt;br /&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;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;[출처]&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://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard&quot;&gt;https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1652869181526&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;스프링 핵심 원리 - 기본편 - 인프런 | 강의&quot; data-og-description=&quot;스프링 입문자가 예제를 만들어가면서 스프링의 핵심 원리를 이해하고, 스프링 기본기를 확실히 다질 수 있습니다., - 강의 소개 | 인프런...&quot; data-og-host=&quot;www.inflearn.com&quot; data-og-source-url=&quot;https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard&quot; data-og-url=&quot;https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/f32cU/hyOra1kj6k/KSM7xrGglwg9yLDEI69xDK/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/bfMCPa/hyOrfVRzwK/QAaIU1vH3YfCEv1CN1cRMK/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/E3GU5/hyOsqVNAF7/dEBfuiIKiwXDQkfxr0YPqK/img.png?width=1805&amp;amp;height=1044&amp;amp;face=0_0_1805_1044&quot;&gt;&lt;a href=&quot;https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/f32cU/hyOra1kj6k/KSM7xrGglwg9yLDEI69xDK/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/bfMCPa/hyOrfVRzwK/QAaIU1vH3YfCEv1CN1cRMK/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/E3GU5/hyOsqVNAF7/dEBfuiIKiwXDQkfxr0YPqK/img.png?width=1805&amp;amp;height=1044&amp;amp;face=0_0_1805_1044');&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;스프링 핵심 원리 - 기본편 - 인프런 | 강의&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;스프링 입문자가 예제를 만들어가면서 스프링의 핵심 원리를 이해하고, 스프링 기본기를 확실히 다질 수 있습니다., - 강의 소개 | 인프런...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.inflearn.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;</description>
      <category>Spring</category>
      <category>autowired</category>
      <category>kotlin</category>
      <category>Spring</category>
      <category>컴포넌트 스캔</category>
      <author>haileykim1</author>
      <guid isPermaLink="true">https://soyangkim98.tistory.com/28</guid>
      <comments>https://soyangkim98.tistory.com/28#entry28comment</comments>
      <pubDate>Thu, 19 May 2022 00:44:03 +0900</pubDate>
    </item>
    <item>
      <title>[Spring][Kotlin] 싱글톤 컨테이너</title>
      <link>https://soyangkim98.tistory.com/27</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;스프링은 기업용 온라인 서비스 기술을 지원하기 위해 탄생했다.&lt;br /&gt;그리고 대부분 스프링 애플리케이션은 웹 애플리케이션이다.&lt;br /&gt;웹앱은 보통 여러 고객이 동시에 요청한다.&lt;br /&gt;&lt;br /&gt;Problem] Request 마다 객체 생성하면 메모리 낭비가 매우 심하다.&lt;br /&gt;Sol) 해당 객체를 1개만 생성하고&amp;nbsp; 공유하도록 하면 된다.&lt;br /&gt;(사실 요즘 GC가 좋아서 초당 100최 정도는 괜찮지만 효율적이면 좋으니까)&lt;/blockquote&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;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;: 클래스의 인스턴스가 딱 1개만 생성되는 것을 보장하는 디자인 패턴이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;-&amp;gt; 객체 인스턴스가 2개 이상 생성 못하도록 막야야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;싱글톤 구현 방법은 많다.&lt;br /&gt;그 중 하나의 방법은 private 생성자를 사용해서 생성자를 사용하지 못하도록 막는 것이다.&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Kotlin에서는 object 키워드를 붙이면 싱글톤 클래스 생성이 가능하다.&lt;br /&gt;※단, 생성자에 파라미터 넣지 않는 클래스에서만 사용이 가능하다.&lt;br /&gt;생성자 통해 파라미터 전달받는 싱글톤 클래스는 companion object를 사용하면 된다.&lt;/blockquote&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;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;클라이언트가 구체 클래스에 의존한다.(내부적으로 객체 반환 함수를 만든다면) -&amp;gt; DIP위반, OCP위반 가능성&amp;uarr;&lt;/li&gt;
&lt;li&gt;유연성이 떨어져서 테스트 하기가 어렵다.&lt;/li&gt;
&lt;li&gt;내부 속성을 변경하고 초기화 하기 어렵다.&lt;/li&gt;
&lt;li&gt;private생성자로 자식 클래스를 만들기 어렵다.&lt;/li&gt;
&lt;li&gt;안티패턴으로 불리기도 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;-&amp;gt; 스프링 컨테이너는 default로 객체를 싱글톤으로 만들어서 관리해준다(성능 굿굿)&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;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;: 싱글톤 패턴의 문제점을 해결하면서 객체 인스턴스를 싱글톤으로 관리해준다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(객체를 미리 생성해서 관리해주기 때문에 지저분한 코드가 없고 DIP, OCP, 테스트 모두 유연하게 가능하다.)&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;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;: 객체 인스턴스를 공유하기 때문에 싱글톤 객체는 stateful 하게 설계하면 안된다.&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;무상태 stateless&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;필드 대신에 자바에서 공유되지 않는 지역변수, 파라미터, ThreadLocal 등을 이용해야한다.&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;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;@Configuration과 싱글톤&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@Configuration은 싱글톤을 위해 존재한다.&lt;/p&gt;
&lt;pre id=&quot;code_1652866307983&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Bean
fun memberService() = MemberServiceImpl(memberRepository())

@Bean
fun orderService() = OrderServiceImpl(memberRepository(), discountPolicy())

@Bean
fun memberRepository() = MemoryMemberRepository()&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 예제코드의 경우 memberService와 orderService 빈을 만드는 코드를 보면 memberRepository()를 호출한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 memberRepository 빈을 만드는 코드도 실행된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 memberRepository는 MemoryMemberRepository 생성자를 호출하며 3개의 객체가 생성되면서 싱글톤이 깨지는 것 처럼 보인다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 memberRepository는 빈 등록 시 1번만 호출된다. -&amp;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;@Configuration과 바이트 코드 조작&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 Kotlin코드 자체만 보면 3번 호출되어야하는게 맞지만,&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스프링은 이것이 되게 하기 위해 바이트코드를 조작하는 라이브러리를 사용한다.&lt;/p&gt;
&lt;pre id=&quot;code_1652867169912&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Test
@DisplayName(&quot;CGLIB 확인하기&quot;)
fun confiruationDeep(){
    val bean = ac.getBean(AppConfig::class.java)
    println(&quot;bean = ${bean::class.java}&quot;)
}&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;600&quot; data-origin-height=&quot;25&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/brbgvc/btrCunrTI47/gENHm4jLKtjuK9yhIMsks0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/brbgvc/btrCunrTI47/gENHm4jLKtjuK9yhIMsks0/img.png&quot; data-alt=&quot;예제 코드 실행 시 나온 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/brbgvc/btrCunrTI47/gENHm4jLKtjuK9yhIMsks0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbrbgvc%2FbtrCunrTI47%2FgENHm4jLKtjuK9yhIMsks0%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;25&quot; data-origin-width=&quot;600&quot; data-origin-height=&quot;25&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;클래스 정보를 출력하면 클래스 이름인 AppConfig가 아닌 AppConfig&amp;amp;&amp;amp;EnhancerBySpringCGLIB$$~~~가 출력된다.&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;CGLIB&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것은 사용자가 만든 클래스가 아니라 스프링이 CGLIB라는 바이트 조작 라이브러리를 사용해서 해당 클래스를 상속받은 임의의 다른 클래스를 만들고 그 클리스를 스프링 빈으로 등록한 것이다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 @Configuration를 안붙이면 CGLIB 안쓰기 때문에 순수한 인스턴스가 조회되고 싱글톤이 깨진다.&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;[출처]&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://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard&quot;&gt;https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1652869147413&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;스프링 핵심 원리 - 기본편 - 인프런 | 강의&quot; data-og-description=&quot;스프링 입문자가 예제를 만들어가면서 스프링의 핵심 원리를 이해하고, 스프링 기본기를 확실히 다질 수 있습니다., - 강의 소개 | 인프런...&quot; data-og-host=&quot;www.inflearn.com&quot; data-og-source-url=&quot;https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard&quot; data-og-url=&quot;https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/f32cU/hyOra1kj6k/KSM7xrGglwg9yLDEI69xDK/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/bfMCPa/hyOrfVRzwK/QAaIU1vH3YfCEv1CN1cRMK/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/E3GU5/hyOsqVNAF7/dEBfuiIKiwXDQkfxr0YPqK/img.png?width=1805&amp;amp;height=1044&amp;amp;face=0_0_1805_1044&quot;&gt;&lt;a href=&quot;https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/f32cU/hyOra1kj6k/KSM7xrGglwg9yLDEI69xDK/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/bfMCPa/hyOrfVRzwK/QAaIU1vH3YfCEv1CN1cRMK/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/E3GU5/hyOsqVNAF7/dEBfuiIKiwXDQkfxr0YPqK/img.png?width=1805&amp;amp;height=1044&amp;amp;face=0_0_1805_1044');&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;스프링 핵심 원리 - 기본편 - 인프런 | 강의&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;스프링 입문자가 예제를 만들어가면서 스프링의 핵심 원리를 이해하고, 스프링 기본기를 확실히 다질 수 있습니다., - 강의 소개 | 인프런...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.inflearn.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;</description>
      <category>Spring</category>
      <category>kotlin</category>
      <category>singleton</category>
      <category>Spring</category>
      <category>스프링</category>
      <category>싱글톤컨테이너</category>
      <author>haileykim1</author>
      <guid isPermaLink="true">https://soyangkim98.tistory.com/27</guid>
      <comments>https://soyangkim98.tistory.com/27#entry27comment</comments>
      <pubDate>Wed, 18 May 2022 19:19:10 +0900</pubDate>
    </item>
    <item>
      <title>[Spring][Kotlin] 스프링 컨테이너</title>
      <link>https://soyangkim98.tistory.com/26</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;ApplicationContext를 스프링 컨테이너라고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ApplicationContext 는 인터페이스인데 XML기반, 애노테이션 기반의 자바 설정 클래스로 하는 구현체를 선택할 수 있다.&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;pre id=&quot;code_1649783339814&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//스프링 컨테이너 생성
val applicationContext = AnnotationConfigApplicationContext(AppConfig::class.java)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AnnotationConfigApplicationContext -&amp;gt; 이 클래스는 ApplicationContext 인터페이스의 구현체이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;스프링컨테이너를 부를 때 Bean Factory, ApplicationContext로 구분하지만 일반적으로는 ApplicationContext를 스프링 컨테이너라고 한다.&lt;/blockquote&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;/h2&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;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 스프링 컨테이너 생성&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;212&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFDkS3/btrzgjdvgBN/ZHKdwG6rJdPDiatJmCWLq1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFDkS3/btrzgjdvgBN/ZHKdwG6rJdPDiatJmCWLq1/img.png&quot; data-alt=&quot;여기서는 AppConfig.class를 구성 정보를 지정하였다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFDkS3/btrzgjdvgBN/ZHKdwG6rJdPDiatJmCWLq1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFDkS3%2FbtrzgjdvgBN%2FZHKdwG6rJdPDiatJmCWLq1%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;212&quot; data-origin-width=&quot;448&quot; data-origin-height=&quot;212&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;여기서는 AppConfig.class를 구성 정보를 지정하였다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&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;447&quot; data-origin-height=&quot;199&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bC4J3c/btrzd8Q7CB2/rhekT5n2FMY9Nhwe0ctLuK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bC4J3c/btrzd8Q7CB2/rhekT5n2FMY9Nhwe0ctLuK/img.png&quot; data-alt=&quot;스프링 컨테이너는 설정 클래스 정보를 사용해서 스프링 빈을 등록한다. @Bean Annotation을 붙여주면 된다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bC4J3c/btrzd8Q7CB2/rhekT5n2FMY9Nhwe0ctLuK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbC4J3c%2Fbtrzd8Q7CB2%2FrhekT5n2FMY9Nhwe0ctLuK%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;447&quot; height=&quot;199&quot; data-origin-width=&quot;447&quot; data-origin-height=&quot;199&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;스프링 컨테이너는 설정 클래스 정보를 사용해서 스프링 빈을 등록한다. @Bean Annotation을 붙여주면 된다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 스프링 빈 의존관계 주입&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;202&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/U2tFe/btrzdu1bGgs/EqYxieQdLLHn4lgyEnR2VK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/U2tFe/btrzdu1bGgs/EqYxieQdLLHn4lgyEnR2VK/img.png&quot; data-alt=&quot;스프링 컨테이너는 설정 정보를 참고해서 DI 한다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/U2tFe/btrzdu1bGgs/EqYxieQdLLHn4lgyEnR2VK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FU2tFe%2Fbtrzdu1bGgs%2FEqYxieQdLLHn4lgyEnR2VK%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;202&quot; data-origin-width=&quot;448&quot; data-origin-height=&quot;202&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;스프링 컨테이너는 설정 정보를 참고해서 DI 한다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;빈 이름은 겹치지 않게 설정해야 한다.&lt;br /&gt;겹치면 다른 빈을 무시하거나 기존 빈을 덮어버리거나 설정에 따른 오류가 발생한다.&lt;/blockquote&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;/h3&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;컨테이너에 등록된 모든 빈 조회&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 구성 정보를 담고 있는 AppConfig class이다.&lt;/p&gt;
&lt;pre class=&quot;crystal&quot;&gt;&lt;code&gt;package soyang.hellocore

import org.springframework.context.annotation.Bean
import org.springframework.context.annotation.Configuration
import soyang.hellocore.discount.DiscountPolicy
import soyang.hellocore.discount.RateDiscountPolicy
import soyang.hellocore.member.MemberRepository
import soyang.hellocore.member.MemberService
import soyang.hellocore.member.MemberServiceImpl
import soyang.hellocore.member.MemoryMemberRepository
import soyang.hellocore.order.OrderService
import soyang.hellocore.order.OrderServiceImpl

@Configuration
class AppConfig {


    @Bean
    fun memberService(): MemberService = MemberServiceImpl(memberRepository())

    @Bean
    fun orderService(): OrderService = OrderServiceImpl(memberRepository(), discountPolicy())

    @Bean
    fun memberRepository(): MemberRepository = MemoryMemberRepository()

    @Bean
    fun discountPolicy(): DiscountPolicy = RateDiscountPolicy()

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 Bean을 출력하는 테스트 코드를 작성했다.&lt;/p&gt;
&lt;pre class=&quot;kotlin&quot;&gt;&lt;code&gt;package soyang.hellocore.beanfind

import org.junit.jupiter.api.DisplayName
import org.junit.jupiter.api.Test
import org.springframework.context.annotation.AnnotationConfigApplicationContext
import soyang.hellocore.AppConfig

class ApplicationContextInfoTest {

    val ac = AnnotationConfigApplicationContext(AppConfig::class.java)

    @Test
    @DisplayName(&quot;모든 빈 출력하기&quot;)
    fun findAllBean(){
        val beanDefinitionNames = ac.beanDefinitionNames
        beanDefinitionNames.forEach{
            val bean = ac.getBean(it)
            println(&quot;name=$it obejct=$bean&quot;)
        }
    }

}&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;2507&quot; data-origin-height=&quot;990&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bXL5kg/btrBLGdRWeU/kxEojeysYj61auy0wRxZj1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bXL5kg/btrBLGdRWeU/kxEojeysYj61auy0wRxZj1/img.png&quot; data-alt=&quot;Test 실행 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bXL5kg/btrBLGdRWeU/kxEojeysYj61auy0wRxZj1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbXL5kg%2FbtrBLGdRWeU%2FkxEojeysYj61auy0wRxZj1%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;2507&quot; height=&quot;990&quot; data-origin-width=&quot;2507&quot; data-origin-height=&quot;990&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Test 실행 결과&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 중 이 부분이 모든 Bean 조회 결과이다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2168&quot; data-origin-height=&quot;327&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ckpbTX/btrBLFMOlDZ/ZUAfmqXZrP2uFZw1SNNod1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ckpbTX/btrBLFMOlDZ/ZUAfmqXZrP2uFZw1SNNod1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ckpbTX/btrBLFMOlDZ/ZUAfmqXZrP2uFZw1SNNod1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FckpbTX%2FbtrBLFMOlDZ%2FZUAfmqXZrP2uFZw1SNNod1%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;2168&quot; height=&quot;327&quot; data-origin-width=&quot;2168&quot; data-origin-height=&quot;327&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;AppConfig도 스프링 빈도 등록된다!!&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;직접 등록한 memberService, orderService, memberReository, discountPolicy 외에도 Bean들이 있다.&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;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 Role을 사용하여 사용자 정의 빈을 따로 조회할 수 있다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;ROLE_APPLICATION : 직접 등록한 애플리케이션 빈&lt;/li&gt;
&lt;li&gt;ROLE_INFRASTRUCTURE : 스프링이 내부에서 사용하는 빈&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;kotlin&quot;&gt;&lt;code&gt;@Test
@DisplayName(&quot;애플리케이션 빈 출력하기&quot;)
fun findApplicationBean(){
    val beanDefinitionNames = ac.beanDefinitionNames
    beanDefinitionNames.forEach{
        val beanDefinition = ac.getBeanDefinition(it)
        if(beanDefinition.role == BeanDefinition.ROLE_APPLICATION){
            val bean = ac.getBean(it)
            println(&quot;name=$it obejct=$bean&quot;)
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Test를 돌려보면 내가 등록한 빈들만 출력된다.&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;pre id=&quot;code_1652170305582&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;val bean1 = ac.getBean(빈 이름, 타입)
//또는
val bean2 = ac.getBean(타입)&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;메서드에서 반환하는 대상이 없으면 suchNoBeanDefinitionException이 발생한다.&lt;/blockquote&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;동일한 타입이 둘 이상인 경우&lt;/p&gt;
&lt;pre id=&quot;code_1652337518682&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;//해당 타입 모든 빈 조회. Map 반환
val map = ac.getBeansOfType(타입)&lt;/code&gt;&lt;/pre&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;Configuration 클래스를 inner class로 만들면 UnsatifiedDependencyException이 발생하였다.&lt;br /&gt;&lt;br /&gt;이유를 찾아봤는데,&lt;br /&gt;innerclass는 outerclass에 종속되어 있다.&lt;br /&gt;따라서 outerclass가 생성되어야 사용이 가능하다.&lt;br /&gt;근데 외부 클래스 객체가 생성되기도 전에 스프링 컨테이너에서 innerclass를 찾아오려고 한다.&lt;br /&gt;그럼 그런 클래스가 없다고 오류가 발생하는 것이다.&lt;br /&gt;=&amp;gt; Sol) static(companion object)로 생성해주면 외부 클래스 객체 생성 유무와 별개로 생성되어서 독립적으로 사용이 가능하다.&lt;/blockquote&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;&amp;nbsp;: 부모타입 조회 시 자식타입이 함께 조회된다. (줄줄이 다 끌려나온다.)&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&amp;nbsp;그래서 Object 타입으로 조회 시 모든 스프링 빈이 조회된다.&lt;/blockquote&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;BeanFactory와 ApplicationContext&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;186&quot; data-origin-height=&quot;272&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JuqLh/btrBT6j8PNp/2cFwoZDrSsD0pLi8L9LSDk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JuqLh/btrBT6j8PNp/2cFwoZDrSsD0pLi8L9LSDk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JuqLh/btrBT6j8PNp/2cFwoZDrSsD0pLi8L9LSDk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJuqLh%2FbtrBT6j8PNp%2F2cFwoZDrSsD0pLi8L9LSDk%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;215&quot; height=&quot;314&quot; data-origin-width=&quot;186&quot; data-origin-height=&quot;272&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;BeanFactory&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;br /&gt;ex) getBean()&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;ApplicationContext&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;: BeanFactory의 모든 개능을 상속받아 제공한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 외 제공하는 부가기능( + Bean 관리 기능)&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;환경변수 : 각 환경별로 어떤 DB연결해야할지 등 환경변수와 관련된 정보 처리&lt;/li&gt;
&lt;li&gt;애플리케이션 이벤트 : 이벤트 발행, 구독 모델 편리하게 지원&lt;/li&gt;
&lt;li&gt;편이한 리소스 조회 : 파일, 클래스 패스, 외부 리소스 추상화 등 편리하게 조회&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;스프링 컨테이너는 다양한 설정 정보 받아들일 수 있게 유연하게 설계되어 있다.&lt;/blockquote&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;XML로 설정&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;GenericXmlApplicationContext() 사용한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&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;h3 data-ke-size=&quot;size23&quot;&gt;스프링 빈 설정 메타정보 - BeanDefinition&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Spring이 다양한 설정 형식을 지원할 수 있는 건 BeanDefinition이라는 추상화가 있기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(역할과 구현을 분리하였다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 BeanDefinition이 빈 설정 메타정보이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@Bean 하나 당 메타정보가 하나씩 생성된다.&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;p data-ke-size=&quot;size16&quot;&gt;ApplicationContext의 Reader가 설정정보(AppConfig.class)를 쭉 읽은 다음 빈 메타정보를 생성한다(BeanDefinition)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;666&quot; data-origin-height=&quot;364&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nnuyB/btrBZxUdgjF/H8llbIZVlkGzX5I0GJDG9K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nnuyB/btrBZxUdgjF/H8llbIZVlkGzX5I0GJDG9K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nnuyB/btrBZxUdgjF/H8llbIZVlkGzX5I0GJDG9K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnnuyB%2FbtrBZxUdgjF%2FH8llbIZVlkGzX5I0GJDG9K%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;364&quot; data-origin-width=&quot;666&quot; data-origin-height=&quot;364&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필요하다면 ApplicationContext를 상속받은 임의의 형식을 만들어도 된다.&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;h4 data-ke-size=&quot;size20&quot;&gt;스프링 빈 등록 방법에는&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 직접 등록 방법&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. Factory Bean 통해서 쓰는 법&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;BeanDefinition에서 팩토리빈, 팩토리 메서드 확인이 가능하다.&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;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;a href=&quot;https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard&quot;&gt;https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1649782171094&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;스프링 핵심 원리 - 기본편 - 인프런 | 강의&quot; data-og-description=&quot;스프링 입문자가 예제를 만들어가면서 스프링의 핵심 원리를 이해하고, 스프링 기본기를 확실히 다질 수 있습니다., - 강의 소개 | 인프런...&quot; data-og-host=&quot;www.inflearn.com&quot; data-og-source-url=&quot;https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard&quot; data-og-url=&quot;https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cIUlrc/hyN0q4xKur/f8ZE2eEJY5paYvuplk1Ekk/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/OKOZ9/hyN0pEzRal/U9zkP1dHF8mdtaoK6PUMP0/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/zShwa/hyN0h7BjP8/mZimfXXB98A7dS1xdRNJe1/img.png?width=1805&amp;amp;height=1044&amp;amp;face=0_0_1805_1044&quot;&gt;&lt;a href=&quot;https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cIUlrc/hyN0q4xKur/f8ZE2eEJY5paYvuplk1Ekk/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/OKOZ9/hyN0pEzRal/U9zkP1dHF8mdtaoK6PUMP0/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/zShwa/hyN0h7BjP8/mZimfXXB98A7dS1xdRNJe1/img.png?width=1805&amp;amp;height=1044&amp;amp;face=0_0_1805_1044');&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;스프링 핵심 원리 - 기본편 - 인프런 | 강의&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;스프링 입문자가 예제를 만들어가면서 스프링의 핵심 원리를 이해하고, 스프링 기본기를 확실히 다질 수 있습니다., - 강의 소개 | 인프런...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.inflearn.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;</description>
      <category>Spring</category>
      <author>haileykim1</author>
      <guid isPermaLink="true">https://soyangkim98.tistory.com/26</guid>
      <comments>https://soyangkim98.tistory.com/26#entry26comment</comments>
      <pubDate>Thu, 12 May 2022 16:37:37 +0900</pubDate>
    </item>
    <item>
      <title>[Spring][Kotlin] 제어의 역전(Ioc)과 의존관계 주입(DI)</title>
      <link>https://soyangkim98.tistory.com/25</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;제어의 역전 IoC (Inversion of Control)&lt;/h2&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;/p&gt;
&lt;pre id=&quot;code_1649775699116&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class MemberServiceImpl: MemberService(){

	val memberRepository = MemoryMemberRepository()
    
	//생략
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 코드는 MemberServiceImpl 객체가 스스로 필요한 서버 구현 객체를 생성하고 연결하고 실행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉 구현 객체가 프로그램의 제어 흐름을 조종한다.&lt;/p&gt;
&lt;pre id=&quot;code_1649775976344&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class AppConfig{
	
    fun memberRepository() = MemoryMemberRepository()
    
	fun memberService() = MemberServiceImpl(memberRepository())
    
    //생략
    
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 AppConfig가 등장하고는 제어 흐름의 권한은 AppConfig에게 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체들은 자신의 로직을 실행할 뿐이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 제어의 흐름이 외부에서 관리되는 것을 IoC 라고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;c.f] 프레임워크 vs 라이브러리&lt;br /&gt;내가 작성한 코드를 제어하고 대신 실행한다면 프레임워크. ex) JUnit&lt;br /&gt;내가 작성한 코드가 직접 제어흐름을 담당한다면 그것은 라이브러리.&lt;br /&gt;&lt;br /&gt;여기서 JUnit을 예로 들면 프레임워크는 본인만의 라이프 사이클이 있다.&lt;br /&gt;BeforeEach 먼저 실행하고 Test 실행, AfterEach 실행 이런 흐름.&lt;br /&gt;그 lifecycle 속에서 내 코드는 콜백 형태로 호출되는것이다.&lt;br /&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;h2 data-ke-size=&quot;size26&quot;&gt;의존관계 주입 DI (Dependency Injection)&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;[정적인 클래스 의존관계]&lt;br /&gt;&amp;nbsp;: import 코드만 보고도 파악 가능한 의존관계&lt;br /&gt;앱을 실행하지 않고도 분석 가능하다.&lt;br /&gt;하지만 이것만으론 실제 어떤 객체가 주입될 지 알 수 없다.&lt;br /&gt;&lt;br /&gt;[동적인 객체 의존관계]&lt;br /&gt;&amp;nbsp;: 애플리케이션 실행 시점에 실제 생성된 객체 인스턴스의 참조가 연결관 의존관계&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DI(의존관계 주입)을 사용하면 정적인 클래스 의존관계를 변경하지 않고 동적인 객체 인스턴스 의존관계를 쉽게 변경할 수 있다.&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;이렇게 IoC, DI 해주는 컨테이너를&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;IoC 컨테이너 = DI 컨테이너 = 어셈블러 = 오브젝트 팩토리&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;라고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;의존관계 주입에 초점 맞추어 최근에는 주로 DI 컨테이너라고 한다고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DI 컨테이너 ex) AppConfig, Spring..etc&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;[출처]&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://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard&quot;&gt;https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1649774721941&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;스프링 핵심 원리 - 기본편 - 인프런 | 강의&quot; data-og-description=&quot;스프링 입문자가 예제를 만들어가면서 스프링의 핵심 원리를 이해하고, 스프링 기본기를 확실히 다질 수 있습니다., - 강의 소개 | 인프런...&quot; data-og-host=&quot;www.inflearn.com&quot; data-og-source-url=&quot;https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard&quot; data-og-url=&quot;https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cIUlrc/hyN0q4xKur/f8ZE2eEJY5paYvuplk1Ekk/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/OKOZ9/hyN0pEzRal/U9zkP1dHF8mdtaoK6PUMP0/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/zShwa/hyN0h7BjP8/mZimfXXB98A7dS1xdRNJe1/img.png?width=1805&amp;amp;height=1044&amp;amp;face=0_0_1805_1044&quot;&gt;&lt;a href=&quot;https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.inflearn.com/course/%EC%8A%A4%ED%94%84%EB%A7%81-%ED%95%B5%EC%8B%AC-%EC%9B%90%EB%A6%AC-%EA%B8%B0%EB%B3%B8%ED%8E%B8/dashboard&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cIUlrc/hyN0q4xKur/f8ZE2eEJY5paYvuplk1Ekk/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/OKOZ9/hyN0pEzRal/U9zkP1dHF8mdtaoK6PUMP0/img.png?width=768&amp;amp;height=500&amp;amp;face=0_0_768_500,https://scrap.kakaocdn.net/dn/zShwa/hyN0h7BjP8/mZimfXXB98A7dS1xdRNJe1/img.png?width=1805&amp;amp;height=1044&amp;amp;face=0_0_1805_1044');&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;스프링 핵심 원리 - 기본편 - 인프런 | 강의&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;스프링 입문자가 예제를 만들어가면서 스프링의 핵심 원리를 이해하고, 스프링 기본기를 확실히 다질 수 있습니다., - 강의 소개 | 인프런...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.inflearn.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;</description>
      <category>Spring</category>
      <category>Di</category>
      <category>IOC</category>
      <category>kotlin</category>
      <category>Spring</category>
      <author>haileykim1</author>
      <guid isPermaLink="true">https://soyangkim98.tistory.com/25</guid>
      <comments>https://soyangkim98.tistory.com/25#entry25comment</comments>
      <pubDate>Wed, 13 Apr 2022 01:08:20 +0900</pubDate>
    </item>
  </channel>
</rss>