<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>dailyoon</title>
    <link>https://turtle8760.tistory.com/</link>
    <description>This is not rocket science !
</description>
    <language>ko</language>
    <pubDate>Thu, 27 Aug 2026 11:00:06 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>윤도ri</managingEditor>
    <image>
      <title>dailyoon</title>
      <url>https://tistory1.daumcdn.net/tistory/4980173/attach/e72516e21a2c4168aecf5289aad7d1ac</url>
      <link>https://turtle8760.tistory.com</link>
    </image>
    <item>
      <title>자바 웹 프로그래밍 Next Step 2장 TDD 맛보기</title>
      <link>https://turtle8760.tistory.com/104</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;저번 시간까지 Junit을 이용하여 리팩토링하는 것에 대해 배웠다. 책에서는 더 성장하고 싶을 시 추가적으로 TDD의 개념에 대해 학습하고 실습해볼 것을 추천하여 이렇게 글을 정리하게 되었다. &lt;br&gt; &lt;br&gt; 이 자료는 테스트 주도 개발 : 고품질 쾌속 개발을 위한 TDD 실천법과 도구” 책의 1장에 대한 내용이다. &lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;680&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cGHDib/btrJ3uCnq9q/0qLWCOBpQZykTz29FH7Up0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cGHDib/btrJ3uCnq9q/0qLWCOBpQZykTz29FH7Up0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cGHDib/btrJ3uCnq9q/0qLWCOBpQZykTz29FH7Up0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcGHDib%2FbtrJ3uCnq9q%2F0qLWCOBpQZykTz29FH7Up0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;727&quot; height=&quot;483&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;680&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt; &lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. 테스트 주도 개발(TDD)&lt;/b&gt;&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;TDD란?&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
 &lt;li&gt;Test-Driven Development 의 약자이며 테스트 주도 개발이라는 뜻이다.&lt;/li&gt;
 &lt;li&gt;업무 코드를 &lt;u&gt;작성하기 전에 테스트 코드를 만드는 것&lt;/u&gt;을 의미한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어렵게 들릴 수 있지만, 메소드나 함수 같은 프로그램 모듈을 작성할 때 작성 종료 조건을 먼저 정해놓고 코딩을 시작한다는 의미로 받아들이면 편하다.&lt;br&gt; &lt;br&gt;이를테면, 두 숫자의 합을 구해서 반환하는 sum이라는 메소드를 작성한다고 가정해보자.&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;755&quot; data-origin-height=&quot;191&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/HcMzW/btrJ2mLqBvM/gLxrba1JpJLXNmn1Alq4MK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/HcMzW/btrJ2mLqBvM/gLxrba1JpJLXNmn1Alq4MK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/HcMzW/btrJ2mLqBvM/gLxrba1JpJLXNmn1Alq4MK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FHcMzW%2FbtrJ2mLqBvM%2FgLxrba1JpJLXNmn1Alq4MK%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;755&quot; height=&quot;191&quot; data-origin-width=&quot;755&quot; data-origin-height=&quot;191&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt; 위 표는 만들고자 하는 메소드를 일종의 설계문서처럼 간단히 적어본 모습이다. 사실 우리가 프로그램을 작성할 때 머릿속으로 생각하는 내용과 별반 다르지 않다. 다만 ‘문서로 만들어 머리로 생각하고 눈으로 확인할 것인가?’ 아니면, ‘예상 결과를 코드로 표현해놓고 해당 코드가 자동으로 판단하게 할 것인가?’의 차이가 있다.&lt;br&gt; &lt;br&gt; 위 설계문서에 따라 sum 메소드를 작성할 때,코드를 통해 정상적으로 구현됐는지를 판단하는 방법을 선택한다면 아래와 같은 코드로 작업할 수도 있다.&lt;br&gt; &lt;/p&gt;
&lt;pre data-ke-type=&quot;codeblock&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;package tdd;

public class Calculator {
	public int sum(int a , int b) {
		return 0 ;
	}
	public static void main(String[] args) {
		Calculator cal = new Calculator();
		System.out.println(cal.sum(10,20)==30);
		System.out.println(cal.sum(1,2)==3);
		System.out.println(cal.sum(-10,20)==10);
		System.out.println(cal.sum(0,0)==0);
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; &lt;br&gt; 위 예제에서는 main 메소드를 테스트 메소드처럼 사용했다. sum 메소드는 컴파일 에러만 나지 않도록 해놓고 내부는 비어 있는 상태다. sum 메소드를 먼저 구현한 다음 테스트 할 수 있었지만 그렇게 하지 않고 검증코드를 먼저 만들었다. 그 검증 코드에 해당하는 테스트 케이스가 모두 만족하면 정상적으로 작성됐다고 판단하기로 한 것이다. 다시 말해, &lt;span style=&quot;color: #ee2323;&quot;&gt;명시적인 코드로 개발의 종료조건을 정해놓은 것이다. 이런식의 개발 접근 방식이 바로 TDD이다.&lt;/span&gt;&lt;br&gt; &lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. 테스트 주도 개발의 목표&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;h3 style=&quot;text-align: center;&quot; data-ke-size=&quot;size23&quot;&gt;&quot; Clean code that works &quot;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; &lt;br&gt;우리가 TDD를 통해 얻고자 하는 최종 목적은 ‘잘 동작하는 깔끔한 코드’이다.&lt;br&gt; &lt;br&gt;일반적인 소프트웨어 개발의 목표는 제대로 동작함이지만 TDD방식은 추가적으로 깔끔해야 한다. 이 차이점은 소프트웨어의 품질,유지보수의 편의성, 가독성, 그에 따른 소프트웨어 비용 등 여러 가지 측면을 내포한다.&lt;br&gt; &lt;br&gt; &lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3. 테스트 주도 개발의 기원&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;: 애자일 개발 방식 중 하나인 XP의 실천 방식 중 하나&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1) 애자일 개발이란?&lt;/h4&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;349&quot; data-origin-height=&quot;144&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c3FIaH/btrJ1JnePMO/WDjZ9doxTDIBFJESg2qcs1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c3FIaH/btrJ1JnePMO/WDjZ9doxTDIBFJESg2qcs1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c3FIaH/btrJ1JnePMO/WDjZ9doxTDIBFJESg2qcs1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc3FIaH%2FbtrJ1JnePMO%2FWDjZ9doxTDIBFJESg2qcs1%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;458&quot; height=&quot;189&quot; data-origin-width=&quot;349&quot; data-origin-height=&quot;144&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
 &lt;li&gt;애자일(agile)이란 ‘민첩한, 기만한’의 뜻을 갖는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;애자일 개발은 말 그대로, 좀 더 민첩하고 유연하게 개발에 임하는 것을 말하며, 개발 그 자체에 집중할 수 있도록 개발환경을 조성한다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2) TDD 기원&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TDD는 XP에서 등장하는 여러가지 실천 방법 중 하나로 테스트 우선 개발과 동일한 의미를 갖는다.&lt;br&gt; &lt;br&gt; XP는 2000년대 초반에 급부상한 애자일 소프트웨어 개발론의 하나로 단순성, 상호소통,피드백 등 원칙에 기반해 ‘고객에게 최고의 가치를 최대한 빠르게 전달하는 것’을 목표로 삼는다.&lt;br&gt; &lt;br&gt;다만 XP는 일부분 극단적인 실천 방법을 요구했기도 하여 XP의 유용한 기법들을 다른 애자일 방법론과 혼용해서 적용하는 상태가 많다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;4. 테스트 주도 개발의 진행 방식&lt;/b&gt;&lt;/h2&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;Ask → Response → Refine&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; &lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1) 질문(Ask)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테스트 작성을 통해 시스템에 질문한다. (수행 결과는 실패)&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2) 응답(Response)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테스트를 통과하는 코드를 작성해서 질문에 대답한다. (테스트 성공)&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3) 정제(Refine)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아이디어를 통합하고, 불필요한 것을 제거하고, 모호한 것은 명확히 해서 대답을 정제한다.&lt;br&gt;(리팩토링)&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;4) 반복(Repeat)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; 다음 질문을 통해 대화를 계속 진행한다.&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;551&quot; data-origin-height=&quot;420&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zpRuw/btrJ3SJOZxc/Z9xi1OZykFkvbntbMkZn4k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zpRuw/btrJ3SJOZxc/Z9xi1OZykFkvbntbMkZn4k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zpRuw/btrJ3SJOZxc/Z9xi1OZykFkvbntbMkZn4k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzpRuw%2FbtrJ3SJOZxc%2FZ9xi1OZykFkvbntbMkZn4k%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;551&quot; height=&quot;420&quot; data-origin-width=&quot;551&quot; data-origin-height=&quot;420&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;동일한 내용을 다이어그램으로 도식화 해보면 위와 같다. 흔히 단위 테스트 JUnit을 사용한 테스트 코드 작성이 이루어진다고 생각하면 된다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;5. 실습 시작해보기&lt;/b&gt;&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;| 목표&lt;/b&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
 &lt;li&gt;TDD의 기본적인 진행 방식을 익힌다.&lt;/li&gt;
 &lt;li&gt;시간을 절약시켜줄 이클립스 IDE의 관련 기능을 익힌다.&lt;/li&gt;
 &lt;li&gt;TDD를 진행할 때 발생할 수 있는 몇 가지 기본적인 고려사항을 살펴본다.&lt;/li&gt;
&lt;/ol&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;| 실습 예제: 은행 계좌(Account)클래스 만들기&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
 &lt;li&gt;기능&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; - 클래스 이름은 Account이다&lt;br&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;계좌 생성 구현을 위한 최초의 테스트 케이스를 만들고 실패하는 모습을 확인한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; TDD에서는 최하위 모듈인 ‘메소드’에서부터 단위 테스트를 작성하게 된다. 작성하고자 하는 메소드나 기능이 무엇인지 선별하고, 작성 완료 조건을 정해서 실패하는 테스트 케이스 코드를 작성해야 한다.&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;클래스 이름은 Account 이다&lt;/li&gt;
 &lt;li&gt;기능 : 잔고 조회, 입금, 출금 (금액은 원 단위로)&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2) 최초의 테스트 케이스 만들고 실패해보기&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
 &lt;li&gt;테스트 클래스를 만들고 테스트 케이스를 만들어라&lt;/li&gt;
 &lt;li&gt;테스트 케이스는 테스트하고자 하는 대상에 대해 간단한 시나리오를 만들고 코드로 표현한 모습이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; ( 시나리오: 계좌를 생성한다 → 계좌가 정상적으로 생성됐는지 확인한다.)&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
 &lt;li&gt;AccountTest() 클래스를 만들고 메소드로 testAccount()를 만든다.&lt;/li&gt;
 &lt;li&gt;시나리오의 첫번째가 계좌를 생성하는 것이므로 계좌 만들기.&lt;/li&gt;
 &lt;li&gt;Account 클래스 안 만들어서 무슨 타입인지 못 알아듣겠다고 에러가 뜬다.&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;package test;

public class AccountTest {
	
  @Test
	public void testAccount() {
		Account account = new Account();
	}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3) 실패한 부분 원인 찾아서 해결하기 (Response)&lt;/h4&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;/ol&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;package test;

import java.Account;

public class AccountTest {

	public void testAccount() throws Exception {
		Account account = new Account();
		if (account == null) {
			throw new Exception(&quot;계좌생성 실패&quot;);
		}
	}

	public static void main(String[] args) {
		AccountTest test = new AccountTest();
		try {
			test.testAccount();
		} catch (Exception e) {
			System.out.println(&quot;실패&quot;);
			return;
		}
		System.out.println(&quot;성공&quot;);
	}
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; &lt;br&gt; 개발이 시작되기도 전에 실패가 발생하는 상황부터 보고 시작하라고 하니 당황스러운것 같다. 보통 실패를 최대한 하지 않기 위해 노력하는 경우가 더 많다. 하지만 TDD는 실패를 통해 배움을 늘려가는 기법이다. OK 조건을 사전에 정해두고 빠르게 실패를 경험하며 빠르게 극복하고자 한다. 성공한 항목과 실패한 항목이 명확하고, 작업해야 하는 부분이 확실해진다. 성공에 필요한 조건을 만들고, 실패하는 조건 항목을 성공시킨다. 그래서 &lt;u&gt;&lt;i&gt;빨리 실패하면 실패할수록 좀 더 성공에 가까워지는 개발 방식이다.&lt;/i&gt;&lt;/u&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;4) Refine&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;ToDo 목록에서 완료된 부분을 지운다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리팩토링을 하는 정제 단계에서는 일반적으로 몇가지 질문에 대해 고민해보는 시간을 갖는다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
 &lt;li&gt;소스의 가독성은 적절한가?&lt;/li&gt;
 &lt;li&gt;중복된 코드는 없는가?&lt;/li&gt;
 &lt;li&gt;이름이 잘못 부여된 메소드나 변수명은 없는가?&lt;/li&gt;
 &lt;li&gt;구조의 개선이 필요한 부분이 없는가?&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같은 질문을 해보면서, 안전그물 (=앞서 작성한 테스트 케이스)에 의존해 소스를 가다듬는 단계가 정제 단계이다. 지금은 워낙 소심하게 진행해서 정제할 것은 없다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
 &lt;li&gt;계좌를 만드는 기능 테스트 성공을 하였으므로 ToDo 리스트에서 지워준다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;s&gt;- 클래스 이름은 Account이다.&lt;/s&gt;&lt;br&gt; &lt;br&gt; 사실 if문에서 account가 null값인 경우는 발생하지 않는다. 단지 시나리오의 흐름상 ‘검증’이라는 부분을 표현하기 위해 사용했을 뿐이다. 만일 계좌 생성하는 부분에 문제가 생긴다면 throw new Exception()을 안해도 자동적으로 예외가 던져지고 JUnit이 이 상황을 처리한다. 따라서 JUnit을 쓰면서 &lt;u&gt;main()메소드를 없앨 수 있고 If문도 지운다.&lt;/u&gt;&lt;/p&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;package test;

import org.junit.Test;

import main.Account;

public class AccountTest {
	
	@Test
	public void testAccount() throws Exception {
		Account account = new Account();
		
	}
	
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; &lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2.질문: 잔고 조회 테스트&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
 &lt;li&gt;잔고 조회 기능 작성을 위한 테스트 케이스를 작성한다.&lt;/li&gt;
 &lt;li&gt;수행 결과가 오류로 표시된 항목은 실패 항목으로 만든다.&lt;/li&gt;
&lt;/ul&gt;
&lt;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;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
 &lt;li&gt;10000원으로 계좌 생성&lt;/li&gt;
 &lt;li&gt;잔고 조회 결과 일치&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반드시 초기 금액을 넣어야 계좌 생성할 수 있게 끔 만들었다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2) 최초의 테스트 케이스 만들고 실패해보기&lt;/h4&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;package test;

import static org.junit.Assert.fail;

import org.junit.Test;

import main.Account;

public class AccountTest {
	
	@Test
	public void testAccount() throws Exception {
		Account account = new Account();
		
	}
	@Test
	public void testGetBalance() throws Exception {
		Account account = new Account(10000); //여기서 오류뜸 
		if(account.getBalance() != 10000 ) { //메소드 생성 안되서 오류
				fail();
			}
		}
	
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3) 실패한 부분 원인 찾아서 해결하기 (Response)&lt;/h4&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;package test;

import static org.junit.Assert.fail;

import org.junit.Test;

import main.Account;

public class AccountTest {
	
	@Test
	public void testAccount() throws Exception {
		Account account = new Account(10000);
		
	}
	@Test
	public void testGetBalance() throws Exception {
		Account account = new Account(10000);
		if(account.getBalance() != 10000 ) {
				fail();
			}
		}
	
}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;package main;

public class Account {
	private int balance;

	public Account(int i) {
		this.balance = i;
	}

	public int getBalance() {
		
		return this.balance;
	}
	
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;4) 두번째 정제하기 (Refine)&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
 &lt;li&gt;구현된 잔고 로직에 대한 리팩토링 작업을 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;Account 클래스 생성자의 파라미터 변수명 i는 의미가 명확하지 않아 money로 바꿔주었다.&lt;/li&gt;
 &lt;li&gt;JUnit을 쓰면 예상값과 실제값을 비교할때 assertEquals 를 이용해서 비교할 수 있었다. 이 메소드를 쓰면 훨씬 코드가 간단해지고 편리하므로 if문 대신 바꾸어 주었다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;package main;

public class Account {
	private int balance;

	public Account(int money) {
		this.balance = money;
	}

	public int getBalance() {
		
		return this.balance;
	}
	
}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;package test;

import static org.junit.Assert.fail;
import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.Test;

import main.Account;

public class AccountTest {

	@Test
	public void testAccount() throws Exception {
		Account account = new Account(10000);

	}

	@Test
	public void testGetBalance() throws Exception {
		Account account = new Account(10000);
		assertEquals(10000, account.getBalance());

	}

}
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;6. TDD의 장점&lt;/b&gt;&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 개발의 방향을 잃지 않게 유지해준다.&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 자신이 어떤 기능을 개발하고 또 어디까지 와 있는지를 항상 살펴볼 수 있다. 그리고 남은 단계와 목표를 잊지 않게 도와준다. TDD를 진행할 때 만들어지는 테스트 케이스들은, 자신이 어디까지 왔고, 앞으로 나아가야 하는 곳이 어디인지를 알려주는 나침판이 된다.&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;TDD를 통해 만들어진 애플리케이션은 필요한 만큼 테스트를 거친 품질이 검증된 부품을 갖게 되는 것과 마찬가지다. 실제로 TDD를 사용하지 않은 개발팀에 비해 TDD를 적용한 팀의 결함률이 최대 1/10 정도까지 감소됐다고 한다.&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;TDD의 부산물로 나오는 자동화된 단위 테스트 케이스들은 개발자가 필요한 시점에 언제든지 수행해볼 수 있다. 그리고 그 즉시 현재까지 작성된 시스템에 대한 이상 유무를 바로 확인할 수 있다. 또한 기능을 추가한다든가, 수정하게 됐을 때 수행해야 하는 회귀 테스트에 대한 부담도 줄어든다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;4. 사용설명서 &amp;amp; 의사소통의 수단&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TDD로 작성된 각 모듈에는 테스트 케이스라고 하는 테스트 코드가 개발 종료와 함께 남게 된다. 이 테스트 코드들의 가치는 고객뿐만 아니라 현재의 자신, 주위의 개발자 그리고 미래의 개발자에게 제공되는 상세화되는 모듈 사용 설명서라는 부분도 포함되어 있다. TDD를 통해 작성된 테스트 케이스는 사용 설명서이자, 그와 동시아 다른 개발자와 소통하는 커뮤니케이션 통로가 된다.&lt;br&gt;TDD는 리팩토링과 단짝으로 진행되며, 리팩토링을 하면 최대 미덕은 사람이 이해할 수 있는 코드로 만들 수 있다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;5. 설계 개선&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;테스트 케이스 작성 시에는 클래스나 인터페이스, 이름 짓기, 인자 등에 이르는 개발에 포함된 다양한 설계 요소들에 대해 미리부터 고민하게 된다. 흔히 테스트하기 어렵다고 생각되는 코드들은 객체 설계 원리 중 기본에 해당하는 원칙들이 잘못 적용됐거나 충분히 고려되지 않았을 가능성이 높다. TDD를 진행하면서, 테스트가 가능하도록 설계 구조를 고민하다 보면 자연스럽게 디자인을 개선하게 된다.&lt;br&gt; &lt;br&gt;미리 고민해보고 작성하는 것과 작성하면서 그때그때 추가하는 것은 모듈의 응집도와 의존성 정도에 있어 적지 않은 차이를 만들어 낸다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;6. 보다 자주 성공한다.&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 TDD는 매 주기를 짧게 설정하도록 권장한다. 그렇게 하면 목표를 이뤘다는 성취감을 느낄 수 있다. 또한 이런 성공 습관이 개발의 기초를 바꿀 수 있게 도와준다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;&amp;lt;정리&amp;gt;&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; TDD는 개발자가 목표를 세워 개발을 진행해나가고, 설계에 대해 지속적으로 고민할 수 있게 도와준다. 또한 그 와중에 정형화된 형태의 테스트 케이스들을 작성함으로써 테스트 과정을 자동화하고, 테스트의 수행 결과와 개발의 목표 달성 여부를 즉각적으로 알 수 있게 된다.&lt;br&gt; &lt;br&gt; 개발 완료 시점 이후에도 TDD의 부산물인 자동화된 단위 테스트 케이스를 이용한 지속적인 테스트가 가능해진다. 결과적으로 TDD는 개발에 좀 더 집중할 수 있게 도와주고, 프로그램의 안정성에 크게 기여한다.&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;u&gt;엉클 밥의 원칙을 들어보았는가? &lt;/u&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;엉클 밥이라는 별명으로 불리며 객체 지향 개발의 선구자인 로버트 마틴이 만든 원칙이다.&lt;br&gt;엉클 밥은 TDD의 원칙을 다음과 같이 말하고 있다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
 &lt;li&gt;&lt;b&gt;실패하는 코드를 작성&lt;/b&gt;하기 전에는 절대로 제품 코드를 작성하지 않는다.&lt;/li&gt;
 &lt;li&gt;실패하는 테스트 코드를&lt;b&gt; 한 번에 하나 이상 작성하지 않는다.&lt;/b&gt;&lt;/li&gt;
 &lt;li&gt;현재 실패하고 있는 테스트를 통과하기에 충분한 정도를 넘어서는 제품 코드를 작성하지 않는다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로버트 마틴은 이 세가지 법칙이 TDD 개발의 주기를 30초-1분 사이로 유지시켜 준다고 말한다.&lt;br&gt; &lt;br&gt; TDD의 주기가 짧아진다는 건 그만큼 리듬을 타고 빠르게 진행할 수 있도록 만들어준다는 의미이기도 한다. 위 원칙은 TDD를 시작하는 사람들에게 TDD가 습관이며 개발의 한 부분으로 자리잡을 수 있도록 도와주는 방법이기도 하다. 적극적으로 따라보도록 하자!&lt;br&gt; &lt;br&gt; &lt;br&gt; &lt;br&gt; &lt;br&gt;전체 소스 코드 ↓↓↓&lt;br&gt;&lt;a href=&quot;https://github.com/yoondori2/java_book-web_pro_nextstep&quot; target=&quot;_blank&quot;&gt;&lt;span&gt;https://github.com/yoondori2/java_book-web_pro_nextstep&lt;/span&gt;&lt;/a&gt;&lt;br&gt; &lt;br&gt;출처: 테스트 주도 개발 : 고품질 쾌속 개발을 위한 TDD 실천법과 도구 책 1장 &lt;br&gt; &lt;a href=&quot;https://velog.io/@ganghee/%ED%85%8C%EC%8A%A4%ED%8A%B8-%EC%BD%94%EB%93%9C-TDD&quot; target=&quot;_blank&quot;&gt;&lt;span&gt;https://velog.io/@ganghee/%ED%85%8C%EC%8A%A4%ED%8A%B8-%EC%BD%94%EB%93%9C-TDD&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;</description>
      <category>독서/Java</category>
      <author>윤도ri</author>
      <guid isPermaLink="true">https://turtle8760.tistory.com/104</guid>
      <comments>https://turtle8760.tistory.com/104#entry104comment</comments>
      <pubDate>Thu, 18 Aug 2022 21:58:14 +0900</pubDate>
    </item>
    <item>
      <title>자바 웹 프로그래밍 Next Step 2장</title>
      <link>https://turtle8760.tistory.com/103</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;| 시작하기 전..&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;196&quot; data-origin-height=&quot;257&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mhO7r/btrJXSpJR6J/UOFuhm8DkLtvLEgFrVu3ak/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mhO7r/btrJXSpJR6J/UOFuhm8DkLtvLEgFrVu3ak/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mhO7r/btrJXSpJR6J/UOFuhm8DkLtvLEgFrVu3ak/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmhO7r%2FbtrJXSpJR6J%2FUOFuhm8DkLtvLEgFrVu3ak%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;196&quot; height=&quot;257&quot; data-origin-width=&quot;196&quot; data-origin-height=&quot;257&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;국비학원에서 자바로 개발을 시작한 사람으로써 어떤 로드맵을 가지고 학습해야 하는지, 학습해야할 지식이 무엇인지, 지금 공부하는것이 잘하고 있는지 감이 안왔다. 회사에서 교육의 한 과정으로 이 책을 학습하라고 하셔서 시작하게 되었지만 주먹구구식으로 개발하는 것이 아닌 생각하고 고민하는 개발자가 되는데 큰 도움이 될 것이라 생각한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2장. 문자열 게산기 구현을 통한 테스트와 리팩토링&lt;/b&gt;&lt;/h2&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;1. main()메소드를 활용한 테스트의 문제점&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;소스 코드를 구현한 후 정상적으로 동작하는지 확인하는 일반적인 방법은 main() 메소드이다.&lt;/li&gt;
&lt;li&gt;예를 들어 계산기를 구현할 때 계산기 코드는 서비스를 담당하는 프로덕션 코드와 그 코드가 정상적으로 작동하는지 확인하기 위한 main()으로 나뉜다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;첫번째 구현&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;해결:&lt;span style=&quot;color: #000000;&quot;&gt; 프로덕션 코드와 테스트코드를 분리&lt;/span&gt;하면 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&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;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;프로덕션코드(Calculator 클래스)와 테스트 코드 (CalculatorTest)를 분리한다.&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;문제점: 별도의 클래스를 추가했지만 Main() 메소드 하나에서 프로덕션 코드의 여러 메소드를 동시에 테스트하고 있다. 프로덕션 코드의 복잡도가 증가하면 할수록 테스트코드를 유지하는데 &lt;u&gt;부담이 된다.&lt;/u&gt;&lt;/li&gt;
&lt;li&gt;해결: 테스트코드를 각 메소드 별로 분리해본다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;세번째 구현&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;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;테스트코드를 각 메소드별로 분리할 수 있다.&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;문제점: 모든 메소드가 아니라 현재 내가 구현하고 있는 메소드에 집중하고 싶은데 그게 안된다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;또한 main()메소드는 테스트 결과를 매번 콘솔에 출력되는 값을 통해 수동으로 확인해야 한다.&lt;/li&gt;
&lt;li&gt;해결 : main()메소드를 활용한 테스트의 이 같은 문제점을 해결하기 위해 틍장한 라이브러리가&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt; JUnit&lt;/b&gt;&lt;/span&gt;이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;네번째 구현&lt;/b&gt;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Junit&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;또한 로직을 실행한 후의 결과 값 확인을 프로그래밍을 통해 자동화하는 것이 가능하다.&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;2.JUnit을 활용해 Main()메소드 문제점 극복&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Junit 라이브러리를 설치하면 Junit안에 있는 메소드를 사용할 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1.한 번에 결과 하나에만 집중&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;CalculatorTest에 테스트 메소드마다&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;@Test&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;를 붙여주면 JUnit이 테스트를 해준다.&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;/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;main() 메소드에서 또 다른 문제점은 결과 값을 눈으로 봐야한다는 것이다. Junit은 이같은 문제점을 극복하기 위해&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;asssertEquals()&lt;/b&gt;&lt;/span&gt;메소드를 제공한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;assertEquals()&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;assertEquals(expected, actual)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(expected: 기대하는 값, actual :프로덕션 코드의 메소드를 실행한 결과의 결과 값)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;asssertEquals는 static 메소드라 import static 으로 메소드를 import한 후 구현할 수 있다.&lt;/li&gt;
&lt;li&gt;테스트가 성공한 경우 초록색 바가 뜨면서 테스트가 성공했음을 알려주고 실패해도 실패한 이유와 함께 실패했음을 빨간 바로 알려준다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1660736099872&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package main;

public class Calculator {
	
	int add(int i, int j ) {
		return i+j;
	}
	int substract (int i, int j) {
		return i-j;
	}
	int multiply(int i, int j) {
		return i*j;
	}
	int divide(int i, int j) {
		return i/j;
	}
	

}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1660736225675&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package main;

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.Test;

public class CalculatorTest {
	
   	//@Test를 쓰면 현재 내가 구현하는 코드에만 집중할 수 있다.
	@Test
	public void substract() {
		Calculator cal = new Calculator();
		System.out.println(cal.substract(6, 3));
	}
    
    //assertEquals를 쓰면 기대하는값과 결과값의 비교가 가능하다.
    @Test
	public void add() {
		Calculator cal = new Calculator();
		assertEquals(9,cal.add(6, 3));
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;결론&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;이와같이 JUnit 의 assertEquals()를 사용하면 수동으로 확인했던 실행 결과를 자동화하는 것이 가능하다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3.테스트 코드 중복 제거&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Calculator 인스턴스를 생성하는 부분에 중복되는 코드가 발생한다. 이때 Junit의 @Before 어노테이션을 사용하는 것을 추천한다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;@Before&lt;/b&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;1) Calculator 인스턴스를 매 테스트마다 생성하는 이유&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;add()테스트 메소드를 실행할 때&lt;u&gt; Calculator 메소드를 실행할 때 영향을 미칠 수 있기 때문이다.&lt;/u&gt; 이런 경우 테스트 실행 순서나 Calculator 상태 값에 따라 테스트가 성공하거나 실패할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;2) 왜 @Before 어노테이션을 사용하는것을 추천하는가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;JUnit에서는 @Runwith, @Rule 같은 어노테이션을 사용해 기능을 확장할 수 있는데 @Before안이여야만 @Runwith, @Rule에서 초기화된 객체에 접근할 수 있다는 제약사항이 있기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;따라서 이 어노테이션을 이용해 테스트 메소드에 대한 초기화 작업을 하는 것이 추후 문제가 발생할 가능성을 없앨 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;@After&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;/ul&gt;
&lt;pre id=&quot;code_1660736324020&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package main;

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

public class CalculatorTest2 {
	//Calculator: Calculator 인스턴스를 생성하는 부분에 중복이 발생한다.
	//이 클래스에서는 그 중복되는 것을 제거해줄 것이다. 
	
	private Calculator cal;
	
	@Before
	public void setup() {
		cal = new Calculator();
		System.out.println(&quot;before&quot;);
	}
	
	@Test
	public void add() {
		assertEquals(9,cal.add(6, 3));
		System.out.println(&quot;add&quot;);
	}
	
	@Test
	public void substract() {
		assertEquals(3,cal.substract(6, 3));
		System.out.println(&quot;substract&quot;);
	}
	@After
	public void teardown() {
		System.out.println(&quot;teardown&quot;);
	}
}&lt;/code&gt;&lt;/pre&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;이와 같이 Junit를 사용하면 매번 초기화, 후처리 작업을 통해 각 테스트 간에 영향을 미치지 않으며 독립적인 실행이 가능하도록 할 수 있다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;3. 문자열 계산기 요구사항 및 실습&lt;/h2&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;1) 요구사항&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;1.빈 문자열 또는 null 값을 입력할 경우 0을 반환하라&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;2.숫자 하나를 문자열로 입력할 경우 해당 숫자를 반환한다.&lt;/p&gt;
&lt;pre id=&quot;code_1660736858663&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package practice;

//1,2 요구사항에 대해 구현해보았다. 
//이 부분은 따로 리팩토링이 필요해보이지 않는다. 
public class Test1 {
	int add (String text) {
		if(text == null || text.isEmpty()) {
			return 0;
		}
		return Integer.parseInt(text);
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;3.숫자 두개를 쉼표 구분자로 입력할 경우 두 숫자의 합을 반환한다.&lt;/p&gt;
&lt;pre id=&quot;code_1660736993032&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package practice;

//세번째 요구조건을 구현했다. 
public class Test1 {
	int add (String text) {
		if(text == null || text.isEmpty()) {
			return 0;
		}
		if(text.contains(&quot;,&quot;)) {
			String[] values = text.split(&quot;,&quot;);
			int sum = 0;
			for (String value : values) {
				sum += Integer.parseInt(value);
			}
			return sum;
		}
		return Integer.parseInt(text);
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;else문을 쓰지않기로 정했기 때문에 if문으로 코드를 짰다. 위의 코드를 보면 점점 복잡해지는 것을 볼 수 있다. 여기서 찜찜한 점은 숫자가 하나인 경우와 쉼표 구분자를 포함하는 경우를 따로 분기해서 처리해야 하는 점이다.&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;string의 split() 메소드에 숫자 하나를 가지는 문자열을 전달하면 숫자 하나가 담겨있는 String[] 을 반환하게 된다. 그래서 if문을 없애줄 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1660737146111&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package practice;

public class Test1 {
	int add(String text) {
		if (text == null || text.isEmpty()) {
			return 0;
		}
		String[] values = text.split(&quot;,&quot;);
		int sum = 0;
		for (String value : values) {
			sum += Integer.parseInt(value);
		}

		return sum;
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;if절을 하나 제거했더니 조금 개선된 코드를 볼 수 있다. 추가적으로 리팩토링할 부분이 있을까? 보면 add()의 복잡도가 증가하고 있다. 먼저 숫자의 합을 구하는 부분을 별도의 메소드로 구현해볼 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1660737335012&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package practice;

public class Test1 {
	int add(String text) {
		if (text == null || text.isEmpty()) {
			return 0;
		}
		String[] values = text.split(&quot;,&quot;);

		return sum(values);
	}
    //합을 구하는 메소드를 따로 뺐다.
	private int sum (String[] values) {
		int sum = 0;
		for (String value : values) {
			sum += Integer.parseInt(value);
		}
		return sum;
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;더 이상 리팩토링할 부분이 없을까? 새로운 sum()메소드를 다시 보면 이 메소드는 합을 구하는 메소드인데 String을 int타입으로 바꿔주는 코드까지 들어있다.한 메소드가 두가지의 일을 할 수 있음을 알 수 있다.&lt;b&gt; 메소드는 한 가지의 책임만 져야하므로 원칙에 따라 이 두가지 작업을 분리해야 한다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1660737654379&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package practice;

public class Test1 {
	int add(String text) {
		if (text == null || text.isEmpty()) {
			return 0;
		}
		String[] values = text.split(&quot;,&quot;);

		return sum(isInt(values));
	}
    //문자열을 숫자로 변환하는 메소드 
	private int [] isInt (String[] values) {
		int[] numbers = new int [values.length];
		for (int i = 0; i &amp;lt; values.length; i++) {
			numbers[i] = Integer.parseInt(values[i]);
		}
		return numbers;
	}
    //변환한 값을 더해주는 메소드
	private int sum (int[] numbers) {
		int sum = 0;
		for (int number : numbers) {
			sum += number;
		}
		return sum;
	}
}&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; 이렇게 극단적으로 리팩토링하는 이유는 소스코드를 읽을 때 이 메소드가 무슨 일을 하는 메소드인지 최대한 쉽게 파악할 수 있게 하기 위함이다. add()메소드를 보면 아직 한눈에 보이지 않아서 null값인지 확인해주는 메소드, 문자열을 구분자로 구분해주는 메소드를 따로 만들어 보았다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1660737941010&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package practice;

public class Test1 {
	int add(String text) {
		if (isBlank(text)) {
			return 0;
		}

		return sum(isInt(split(text)));
	}
	//null값인지 체크해주는 메소드 
	private boolean isBlank(String text) {
		return text == null || text.isEmpty();
	}
	//구분자로 문자열 나눠주는 메소드
	private String[] split(String text) {
		return text.split(&quot;,&quot;);
	}

	private int[] isInt(String[] values) {
		int[] numbers = new int[values.length];
		for (int i = 0; i &amp;lt; values.length; i++) {
			numbers[i] = Integer.parseInt(values[i]);
		}
		return numbers;
	}

	private int sum(int[] numbers) {
		int sum = 0;
		for (int number : numbers) {
			sum += number;
		}
		return sum;
	}
}&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;세부 구현은 모두 private 메소드로 분리해 일단 관심사에서 제외하고 add()메소드가 무슨 일을 하는지에 대한 전체 흐름을 쉽게 볼 수 있게 되었다. add() 메소드가 무슨 일을 하는지 글로 표현해보면 &quot;text값이 비어 있으면 0을 반환, 비어 있지 않으면 구분자로 분리, 숫자로 변환한 다음 이 숫자의 합을 구한다&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;이 책의 필자는 세부 구현에 집중하도록 하지 않고 논리적인 로직을 쉽게 파악할 수 있도록 구현하는 것이 읽기 좋은 코드라고 생각한다고 하셨다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;4.구분자를 쉼표(,)이외에 콜론(:)을 사용할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1660738092633&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;	private String[] split(String text) {
		return text.split(&quot;,|:&quot;);
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이와 같이 메소드를 잘 분리해 놓으면 새로운 요구사항이 발생할 경우 해당 메소드를 찾아 해당 메소드만 수정하는 것이 가능하다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;5.//,\n 문자 사이에 커스텀 구분자를 지정할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1660738199868&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;private String[] split(String text) {
		// Pattern: 정규 표현식이 컴파일 된 클래스이며 정규 표현식에 대상 문자열을 검증하거나, 활요하기 위해 사용하는 클래스이다.
		// Pattern.compile 주어진 정규식을 갖는 패턴을 생성
		// Pattern.compile.matcher() 패턴에 매칭할 문자열을 입력해 Matcher를 생성한다.
		// m = [pattern=//(.)(.*) region=0,9 lastmatch=//;1;2;3]
		// m.find 패턴과 일치하는게 있다면
		// m.group(1) ;
		// m.group(2) 1;2;3
        
		Matcher m = Pattern.compile(&quot;//(.)\n(.*)&quot;).matcher(text);
		if (m.find()) {
			String customDelimeter = m.group(1);
			return m.group(2).split(customDelimeter);
		}
		return text.split(&quot;,|:&quot;);
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;커스텀 구분자는 정규 표현식을 이용해 문자열을 분리하고 있다. 정규 표현식을 사용하면 복잡한 문자열에서 원하는 문자열을 찾거나 특정한 패턴을 찾는데 유용하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;6.문자열 계산기에 음수를 전달하는 경우 RuntimeException으로 예외처리를 해야한다.&lt;/p&gt;
&lt;pre id=&quot;code_1660738343481&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;private int[] isInt(String[] values) {
		int[] numbers = new int[values.length];
		for (int i = 0; i &amp;lt; values.length; i++) {
			numbers[i] = toPositive(values[i]);
		}
		return numbers;
	}
//음수인지 확인하는 메소드를 따로 구현했다. 음수이면 런타임오류가 나게 된다.
	private int toPositive(String value) {
		int number = Integer.parseInt(value);
		if (number &amp;lt; 0) {
			throw new RuntimeException();
		}
		return number;
	}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;실제로 테스트를 해보면 다 잘되는 것을 볼 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1660738389088&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package practice;

import static org.junit.jupiter.api.Assertions.assertEquals;

import org.junit.Before;
import org.junit.Test;

public class StringCalculatorTest {
	private StringCalculator cal;
	
	@Before
	public void setup() {
		cal = new StringCalculator();
	}
	@Test
	public void add_null_bin() {
		assertEquals(0, cal.add(null));
		assertEquals(0, cal.add(&quot;&quot;));
	}
	@Test
	public void add_char() {
		assertEquals(4, cal.add(&quot;4&quot;));
	}
	@Test
	public void add_rest() {
		assertEquals(7, cal.add(&quot;4,3&quot;));
		assertEquals(9, cal.add(&quot;4,2:3&quot;));
	}
	@Test
	public void add_custom() {
		assertEquals(6, cal.add(&quot;//;\n1;2;3&quot;));
	}
	@Test(expected = RuntimeException.class)
	public void add_error() {
		cal.add(&quot;-2,3,2&quot;);
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2)&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt; 추가 요구사항&lt;/b&gt; &lt;/span&gt;⭐&lt;/h4&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;1.메소드가 하나의 책임만 가지도록 구현한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;2.인덴트(들여쓰기) 깊이를 1단계로 유지한다. 인덴트는 while문과 for문을 사용할 경우 인덴트 깊이가 1씩 증가한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;3.else를 사용하지 마라.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;4. 테스트와 리팩토링을 통한 문자열 계산기 구현&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;문자열 계산기를 구현하면서 복잡도가 증가함을 느꼈을것이다. 왜냐하면 요구사항의 복잡도가 높기때문이다. 개발자들은 이 복잡도와 평생을 더불어 살아갈 수밖에 없다. 그러므로 이 복잡도를 낮출 수 있는 방법을 찾아야 한다. 이 복잡도를 낮출 수 있는 방법 중의 하나가 끊임없는 &lt;b&gt;리팩토링을 통해 소스코드를 깔끔하게 구현하는 연습을 하는 것이다.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;1) 요구사항을 작은 단위로 나누기&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;2) 모든 단계의 끝은 리팩토링&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;각 단계에서 다음 단계로 넘어가기 위한 작업의 끝은 내가 기대하는 결과를 확인했을 때가 아니라 결과를 확인한 후 리팩토링까지 완료했을 때이다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;구현 &amp;rarr; 테스트를 통한 결과 확인 &amp;rarr; 리팩토링 과정&lt;/b&gt;&lt;/span&gt;을 거치도록 하자.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;결론&lt;/b&gt;&lt;/h4&gt;
&lt;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;b&gt;3가지 원칙&lt;/b&gt;)을 생각하면서 한다면 소스코드를 개선하는 데 도움이 될 것이다. 또한 중요한 점은 모든 요구사항을 다 구현하고 리팩토링 하는 것이 아니라 &lt;b&gt;&lt;i&gt;한개의 요구사항을 다 구현할때마다 리팩토링을 해야 소스코드의 복잡도를 줄일 수 있다는 점을 명심해야 한다.&amp;nbsp;&lt;/i&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;전체 코드 링크 &amp;darr;&amp;darr;&amp;darr;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/yoondori2/java_book-web_pro_nextstep&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/yoondori2/java_book-web_pro_nextstep&lt;/a&gt;&lt;/p&gt;</description>
      <category>독서/Java</category>
      <author>윤도ri</author>
      <guid isPermaLink="true">https://turtle8760.tistory.com/103</guid>
      <comments>https://turtle8760.tistory.com/103#entry103comment</comments>
      <pubDate>Wed, 17 Aug 2022 21:13:33 +0900</pubDate>
    </item>
    <item>
      <title>운영체제(OS)의 종류</title>
      <link>https://turtle8760.tistory.com/102</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;| 운영체제 (Operation System) 의 종류&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. OS/390 &amp;rarr; TEMDAM OS (메인 프레임) &amp;rarr; OS/400&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;- Unix나오기 전의 운영체제들&amp;nbsp;&amp;nbsp;&lt;b&gt;&lt;/b&gt;&amp;nbsp;- 낮은 레벨이다보니(디스크,메모리 등등&amp;nbsp;&amp;nbsp;다 함께 관리해야 하다보니..) assembly 언어로 프로그램을 짰다. (Os/400까지) &lt;br /&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;*&amp;nbsp;Assembly&amp;nbsp;Language란? &lt;br /&gt;- 기계어와 일대일 대응이 되는 컴퓨터 프로그래밍의 저급 언어이다. &lt;br /&gt;- 컴퓨터 구조를 확립한 폰 노이만은 기계어로 코딩을 했지만 거의 사람들이 알아보기 어려워 보완하기 위해 나온 언어가 어셈블리 언어이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;Unix&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;277&quot; data-origin-height=&quot;182&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cX2HAY/btrJrez6FzC/OXlC71QmoXQIhVtNbpcynK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cX2HAY/btrJrez6FzC/OXlC71QmoXQIhVtNbpcynK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cX2HAY/btrJrez6FzC/OXlC71QmoXQIhVtNbpcynK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcX2HAY%2FbtrJrez6FzC%2FOXlC71QmoXQIhVtNbpcynK%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;342&quot; height=&quot;225&quot; data-origin-width=&quot;277&quot; data-origin-height=&quot;182&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;-&amp;nbsp;Unix는&amp;nbsp;벨&amp;nbsp;연구소에서&amp;nbsp;연구를&amp;nbsp;위해&amp;nbsp;만든&amp;nbsp;운영체제이다.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;* &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;&lt;u&gt;Unix가 중요한 점&lt;/u&gt;&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp; : Unix를 만들기 위해 새로운 언어를 만들었다. &amp;rarr; 이 언어가 바로 **C언어**&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&amp;nbsp; &amp;nbsp;(이때 80 퍼센트는 C언어 10퍼센트는 Assembly로 짰다고 한다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;C 언어로 짜면 이점은 무엇일까?&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;사람들이 이해하기 쉽다는 것이다. 기존에는 기계어로만 이루어져 있어 직접 코드를 짠 사람이 아니면 사용하기 어려웠다. 그래서 하드웨어 이식성이 좋은 언어로 알려져 있다. (코드를 내 마음대로 바꿀 수 있음)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;i&gt;Unix의 탄생이 중요한 이유는 사람들이 이해할 수 있는 레벨인 C언어가 탄생했고 이때부터 오픈소스가 만들어지며 크게 발전했기 때문이다.&lt;/i&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;System V, BSD Unix(OSX &amp;rarr; IOS), Sun Solaris, AIX( IBM ), HP-UX, FreeBSD&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;3.MS-DOS (disk os)&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;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4.Window&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;window 3.0 3.1 .. 이렇게 업그레이드하다가 ui툴을 씌운게 윈도우 95이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;5.Macintosh (Mac)&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;241&quot; data-origin-height=&quot;209&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dv9SiT/btrJqr7BKO9/4xkkyVRLG5yu8mcMYyIYbk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dv9SiT/btrJqr7BKO9/4xkkyVRLG5yu8mcMYyIYbk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dv9SiT/btrJqr7BKO9/4xkkyVRLG5yu8mcMYyIYbk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdv9SiT%2FbtrJqr7BKO9%2F4xkkyVRLG5yu8mcMYyIYbk%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;283&quot; height=&quot;245&quot; data-origin-width=&quot;241&quot; data-origin-height=&quot;209&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;그래픽 사용자 인터페이스(GUI)와&amp;nbsp;&lt;a href=&quot;https://ko.wikipedia.org/wiki/%EB%A7%88%EC%9A%B0%EC%8A%A4&quot;&gt;마우스&lt;/a&gt;를 채용해 상업적으로 성공한 최초의 개인용 컴퓨터이다.(스티븐잡스가 함..멋찌다...)&lt;/li&gt;
&lt;li&gt;OSX가 매킨토시의 10번째 버전이라고 생각하면 된다. 애플의 노트북을 맥북이라고 부르는 이유도 매킨토시부터 os가 발전했기 때문이다. 넘나 신기한것..&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; *GUI란?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; &amp;nbsp; :&amp;nbsp; UI를 그시각적으로 화면에 표시한 것이다. (ex: 웹 아이콘)&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;6.&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;GNU/Linux&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;346&quot; data-origin-height=&quot;146&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/enzuMn/btrJrez6yAN/RwN93k0Ah6cBXKP80XSxN1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/enzuMn/btrJrez6yAN/RwN93k0Ah6cBXKP80XSxN1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/enzuMn/btrJrez6yAN/RwN93k0Ah6cBXKP80XSxN1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FenzuMn%2FbtrJrez6yAN%2FRwN93k0Ah6cBXKP80XSxN1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;346&quot; height=&quot;146&quot; data-origin-width=&quot;346&quot; data-origin-height=&quot;146&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&amp;lsquo;리차드 스톨만&amp;rsquo;이라는 오픈소스 운동하는 사람이 GNU를 만듦.&lt;/li&gt;
&lt;li&gt;Gnu is Not Unix - 'GNU는 유닉스가 아니다'라는 뜻의 재귀적 약어이다.&lt;/li&gt;
&lt;li&gt;Unix를 clone해서 사용하는 회사들이 license를 걸면서 리차드 스톨만이 저작권에 걸리지 않는 소스를 가져다가 새로운 프로그램을 짜서 오픈소스로 공개하기 시작한다.&lt;/li&gt;
&lt;li&gt;GNU는 갖다 써도 되는데 수정하고 나서는 똑같이 오픈소스로 공개해야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;GNU로 바뀌던 중 라누스라는 사람이 core 부분을 바꿔서 공개를 했다. 그것이 바로 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;리눅스&lt;/b&gt;&lt;/span&gt;이다. 리눅스의 core와 GNU의 shell이 합쳐진 게 우리가 알고 있는 리눅스이다. 공식 명칭은 &lt;i&gt;GNU/Linux&lt;/i&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;또한 이 OS를 설치 할 수 있게 만들어주는 것이 배포판인데 배포판의 종류는 debian,ubuntu, Android, Red hat, WebOS,LiMo 등이 있다.&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;간단히 설명을 하자면 안드로이드는 shell이 자바로 짠 shell이다. 우분투는 우분투 재단에서 만들고 있으며 Red hat 은 최초로 리눅스를 상용 배포한 회사이다. 오픈소스에 기여는 한다. WebOS는 안드로이드 초창기에 palmOS가 나올 때 만들어졌다. pam을 HP가 인수하면서 LG가 LG TV에 설치했다고 한다. LiMo는 삼성에서 만들던 OS 라고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 밖에도 BlackBerryOs,Symbian 등등이 있다.&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;오늘은 OS의 종류와 탄생 배경에 대해 배웠다. OS의 구성과 Shell의 종류에 대해서 다음에 더 자세히 알아봐야겠다.&lt;/p&gt;</description>
      <category>신입 개발자로 공부한 내용 정리</category>
      <author>윤도ri</author>
      <guid isPermaLink="true">https://turtle8760.tistory.com/102</guid>
      <comments>https://turtle8760.tistory.com/102#entry102comment</comments>
      <pubDate>Wed, 10 Aug 2022 20:46:14 +0900</pubDate>
    </item>
    <item>
      <title>이 카테고리를 만든 이유</title>
      <link>https://turtle8760.tistory.com/101</link>
      <description>&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;신입 개발자로 입사한 지 불과 2일밖에 되지 않았다. 본격적으로 프로젝트에 들어가기 전에&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;1-2달정도 교육을 받는다고 하여 앞으로 교육받는 부분을 글로 남겨보고자 하여 카테고리를 만들었다. 아마도 이 교육이 끝나고도 추가적으로 학습하고 공유하고 싶은 내용도 남길 것이다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;짧은 시간에 큰 틀로만 배우다 보니 내용의 깊이가 매우 얕을 것이라 생각한다.&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;이 점은 차근차근 내가 더 보충해나가려고 한다. 여러번 반복해서 공부하다보면 언젠가는 빠삭하게&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;익히는 날이 오지 않을까?&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;505&quot; data-origin-height=&quot;581&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7iLpY/btrJq4xxZIU/AM7KqkGxJwktuktDYa08w1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7iLpY/btrJq4xxZIU/AM7KqkGxJwktuktDYa08w1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7iLpY/btrJq4xxZIU/AM7KqkGxJwktuktDYa08w1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7iLpY%2FbtrJq4xxZIU%2FAM7KqkGxJwktuktDYa08w1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;505&quot; height=&quot;581&quot; data-origin-width=&quot;505&quot; data-origin-height=&quot;581&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;아직은 그래도 출근이 재미있다. 나 자신 파이팅!!&amp;nbsp;&lt;/p&gt;</description>
      <category>신입 개발자로 공부한 내용 정리</category>
      <author>윤도ri</author>
      <guid isPermaLink="true">https://turtle8760.tistory.com/101</guid>
      <comments>https://turtle8760.tistory.com/101#entry101comment</comments>
      <pubDate>Wed, 10 Aug 2022 20:27:35 +0900</pubDate>
    </item>
    <item>
      <title>객체 지향 프로그래밍(OOP)</title>
      <link>https://turtle8760.tistory.com/100</link>
      <description>&lt;h3 data-ke-size=&quot;size23&quot;&gt;| 본문을 시작하기 전..&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체지향 프로그래밍이란.. 자바 개발자에게 꼭 알아야 할 중요한 개념이다. 그러나 막상 객체지향 프로그래밍이 뭘까요? 라고 물어본다면.. 추상화를 통해 객체를 만들어서 프로그래밍하는것..? 이라고 밖에 떠오르지 않는다. 객체지향 프로그래밍은 개발을 하면서 부족한 점을 개선하려보니 탄생한 프로그래밍 패러다임이다. 그래서 나는 이번 포스팅에서 이전의 프로그래밍 몇가지에 대해서 먼저 이야기 해보고자 한다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;| 순차적(비구조적) 프로그래밍&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 정의한 기능의 흐름에 따라 순서대로 동작을 추가하며 프로그램을 완성하는 방식이다.&lt;br /&gt;&lt;br /&gt;간단한 프로그램의 경우, 이렇게 코드를 짜게 되면 흐름이 눈으로 보이기 때문에 매우 직관적일것이다. 그러나 프로그램의 규모가 커진다면 곤란해진다. A &amp;gt; B &amp;gt; C 동작을 구현하다가, C &amp;gt; A로 돌아가려는 상황이면 goto 를 활용해야한다. &lt;br /&gt;&lt;br /&gt;goto문을 무분별하게 활용하게 되면, 쭉 나열된 코드 속에서 스파게티 마냥 위로 갔다 아래로 갔다 난리가 아닐것이다.&lt;br /&gt;이렇게 되면 동작이 &lt;b&gt;직관적이지 못하고, 유일한 장점이 사라지게 된다. &lt;/b&gt;&lt;br /&gt;&lt;br /&gt;그래서 등장한 것이 &lt;span style=&quot;color: #5733b1;&quot;&gt;&lt;b&gt;절차적, 구조적 프로그래밍&lt;/b&gt;&lt;/span&gt;이다. &lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;| 절차적 프로그래밍 &lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;: 절차적 프로그래밍에서 '절차'는 함수를 의미한다. 따라서 절차적 프로그래밍이란, 반복되는 동작을 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;함수 및 프로시저 형태로 모듈화하여 사용&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;하는 방식이다.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 이 패러다임은 반복동작을 모듈화하여 코드를 많이 줄일 수 있다. 하지만 프로시저라는 것 자체가 너무 추상적이라는 단점이 있다. &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 예를 들면, 도서관의 도서 관리 프로그램을 개발한다고 했을때&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;'책'이라는 자료형을 구현해야 함&lt;/li&gt;
&lt;li&gt;책에 대한 함수를 구현해야 함&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나, 구조적 프로그래밍에서는 이 둘을 따로 생각할 수 밖에 없다. 책은 책이고 책에 관한 함수는 따로 있기 때문에, 같은 소스 파일 내에 있더라도 이 둘의 연관 여부는 단 번에 알아차리기 어렵다. 즉, 논리적으로 묶여있을 수 없는 구조이기 때문에 동작이 &lt;b&gt;추상적인&lt;/b&gt; 것이다.&lt;br /&gt;&lt;br /&gt;따라서, 이를 묶기 위한 패러다임으로 &lt;span style=&quot;color: #5733b1;&quot;&gt;&lt;b&gt;'객체지향 프로그래밍'&lt;/b&gt;&lt;/span&gt;이 등장하게 된다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;|&lt;/b&gt; 객체 지향 프로그래밍&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;650&quot; data-origin-height=&quot;376&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/32GVz/btrHTXHpFcL/h3FX7bYEJjAHYLJcECCLAk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/32GVz/btrHTXHpFcL/h3FX7bYEJjAHYLJcECCLAk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/32GVz/btrHTXHpFcL/h3FX7bYEJjAHYLJcECCLAk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F32GVz%2FbtrHTXHpFcL%2Fh3FX7bYEJjAHYLJcECCLAk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;650&quot; height=&quot;376&quot; data-origin-width=&quot;650&quot; data-origin-height=&quot;376&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 개념에 대한 자료형과 함수를 '객체' 형태로 함께 묶어서 관리하기 위해 객체 지향 프로그래밍 패러다임이 등장하게 되었다. 핵심 포인트는 객체 내부에 자료형 필드와 함수가 함께 존재한다는 것이다. 가능한 모든 물리적, 논리적 요소를 객체로 만드는 것이 객체지향 프로그래밍이다. &lt;br /&gt;&lt;br /&gt;위에 들었던 예시인 '도서 관리 프로그램'도 객체지향으로 구현하게 되면 책의 제목,저자,페이지수와 같은 자료형 필드와 대출하기,반납하기 등의 메소드를 책이라는 객체에 함께 관리하는 것이 가능해진다. 이렇게 되면 추상적이었던 동작도 훨씬 직관적으로 보이게 되어 코드 가독성이 증가한다.&lt;br /&gt;&lt;br /&gt;결론적으로 객체 간의 독립성이 뚜렷하게 생기고, 중복되는 코드의 양이 줄어든다. 따라서 유지보수에 용이해질 것이다. &lt;/p&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;| 객체지향 프로그래밍의 4가지 특징&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 추상화 (Abstraction) &lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;473&quot; data-origin-height=&quot;261&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/2Gggp/btrHVfHigx1/2ZyXPrV90YM2wTQMMj4Bfk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/2Gggp/btrHVfHigx1/2ZyXPrV90YM2wTQMMj4Bfk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/2Gggp/btrHVfHigx1/2ZyXPrV90YM2wTQMMj4Bfk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F2Gggp%2FbtrHVfHigx1%2F2ZyXPrV90YM2wTQMMj4Bfk%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;473&quot; height=&quot;261&quot; data-origin-width=&quot;473&quot; data-origin-height=&quot;261&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 객체들의 공통적인 속성과 기능을 뽑아내는 것이다. &lt;br /&gt;&lt;br /&gt;추상적인 개념에 의존하여 설계해야 &lt;b&gt;유연함&lt;/b&gt;을 갖출 수 있다. 즉, 세부적인 사물들의 공통적인 특징을 파악한 후, 하나의 묶음으로 만들어내는 것이 추상화다. &lt;br /&gt;&lt;br /&gt;ex) '평생 살 수 없는 아파트'라는 추상화 집합을 만들어두고, 평생 살 수 없는 아파트들이 가진 공통적인 특징들 ( 서울에 위치, 30억 이상함, 벼락부자 또는 금수저만 살 수 있음^^..) 을 만들어서 활용하면 된다. &lt;br /&gt;&lt;br /&gt;&lt;b&gt;2. 캡슐화 (Encapsulation)&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;350&quot; data-origin-height=&quot;144&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvmPRr/btrHTW9xzRb/GmD5n549LwZ8qu9HGkMI4K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvmPRr/btrHTW9xzRb/GmD5n549LwZ8qu9HGkMI4K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvmPRr/btrHTW9xzRb/GmD5n549LwZ8qu9HGkMI4K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbvmPRr%2FbtrHTW9xzRb%2FGmD5n549LwZ8qu9HGkMI4K%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;411&quot; height=&quot;169&quot; data-origin-width=&quot;350&quot; data-origin-height=&quot;144&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 정보 은닉화를 통해 높은 응집도, 낮은 결합도를 유지할 수 있도록 설계하는 것&lt;br /&gt;&lt;br /&gt;쉽게 말하면, 한 곳에서 변화가 일어나도 다른곳에 미치는 side effects 를 최소화 시키는 것을 의미한다. 즉, 객체 내부의 어떤 동작에 대한 구현이 어떻게 되어있는지 감추는 것이다. 이를 통해 외부에 세부 데이터가 노출되는 것을 방지하고 객체가 손상되는 일 또한 방지 할 수 있다.&lt;br /&gt;&lt;br /&gt;결합도란 어떤 기능을 실행할 때 다른 클래스가 모듈에 얼마나 의존적인지를 나타내는 지표이다. 객체 간의 독립성을 강조하기 위해 객체 지향 프로그래밍이 등장했다. 그런데 결합도가 높아지면 객체지향으로 설계하는 의미가 있을까?&lt;br /&gt;&lt;br /&gt;따라서, 독립적으로 만들어진 객체들 간의 의존도를 최대한 낮게 만드는 것이 중요한다. 이 때문에 소프트웨어 공학적으로, 객체 내의 모듈 간의 요소가 밀접한 관련이 있는 것으로 구성하여 &lt;b&gt;응집도를 높이고, 결합도를 줄여야 요구사항 변경에&lt;/b&gt; &lt;b&gt;대처하는 좋은 설계&lt;/b&gt;라고 배운다.&lt;br /&gt;&lt;br /&gt;한 줄로 정리하자면, 객체 각각은 독립적으로 작용할 수 있도록 응집도가 강해야 하고 결합도는 낮아야 한다. &lt;br /&gt;높은 응집도와 낮은 결합도는, '은닉화'를 통해 이루어낼 수 있다. 외부에서 접근할 필요 없는 것들은 접근 지정자를 &lt;b&gt;private 으&lt;/b&gt;로 두어 접근에 제한을 두는 것이다. 외부 객체는 객체 내부의 구조를 모르게 하고, 해당 객체가 노출해서 제공하는 필드와 메소드만 이용할 수 있도록 하여 의도하지 않은 &lt;b&gt;동작 오류를 방지하고 유지보수 효율을 높일 수 있다.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;3. 상속 (Inheritance)&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;540&quot; data-origin-height=&quot;486&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/blD0FJ/btrHTqXFBU9/vJpCyicyf8VbX0oF8ZZO30/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/blD0FJ/btrHTqXFBU9/vJpCyicyf8VbX0oF8ZZO30/img.png&quot; data-alt=&quot;동물에 인간과 애완동물이 속하고 애완동물에는 강아지와 고양이가 속하는 관계임을 볼 수 있다.&amp;amp;amp;amp;nbsp; 동물의 특징을 이들이 물려받을때 상속받는다라고 할 수 있다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/blD0FJ/btrHTqXFBU9/vJpCyicyf8VbX0oF8ZZO30/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FblD0FJ%2FbtrHTqXFBU9%2FvJpCyicyf8VbX0oF8ZZO30%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;540&quot; height=&quot;486&quot; data-origin-width=&quot;540&quot; data-origin-height=&quot;486&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;동물에 인간과 애완동물이 속하고 애완동물에는 강아지와 고양이가 속하는 관계임을 볼 수 있다.&amp;amp;amp;nbsp; 동물의 특징을 이들이 물려받을때 상속받는다라고 할 수 있다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 상위 개념의 특징을 하위 개념이 물려받는 것을 의미한다. &lt;br /&gt;&lt;br /&gt;상속을 활용하면 상위 클래스의 구현을 활용함으로써, 코드 재사용이 용이해진다. 그러나 상속을 통한 재사용을 할때 나타나는 단점이 명백하다. 따라서 객체 지향 프로그래밍에서 '코드 재사용'을 목적으로 하는 상속 행위는 엄격히 금한다. 단점은 아래와 같다. &lt;br /&gt;&lt;br /&gt;1) 부모 클래스의 변경이 불편해짐 &lt;br /&gt;:부모 클래스에 의존하는 자식 클래스가 많을 때 부모 클래스의 변경이 필요하다면, 이를 의존하는 자식 클래스들이 영향을 받게 된다. &lt;br /&gt;2) 불필요한 클래스의 증가&lt;br /&gt;: 유사 기능 확장시, 필요 이상의 불필요한 클래스를 만들어야 할 수 있다. &lt;br /&gt;3) 잘못된 상속 사용&lt;br /&gt;: 같은 종류가 아닌 클래스의 구현을 재사용하기 위해 상속을 받게 된다면, 문제가 발생할 수 있다. &lt;br /&gt;상속받는 클래스가 부모 클래스와 IS-A 관계가 아닐 때 발생함. &lt;br /&gt;&lt;br /&gt;그렇다면 이러한 문제는 어떻게 해결할까? 바로 &lt;b&gt;구성(Composition)&lt;/b&gt; 을 통해 해결이 가능하다.&lt;br /&gt;&lt;br /&gt;객체 구성은 객체 내부 필드에서 다른 객체를 참조하는 방식으로 구현한다. 상속에 비해 런타임 구조가 복잡하고 구현이 어렵지만, 변경시 유연함을 확보할 수 있다는 장점이 있다. --&amp;gt; 같은 종류가 아닌 클래스를 상속 받고 싶을 땐, 객체 컴포지션을 먼저 적용해볼것. &lt;br /&gt;&lt;br /&gt;상속이 반드시 이 두가지 경우에만 일어나야 한다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;IS-A 관계가 성립할 때&lt;/li&gt;
&lt;li&gt;재사용 관점 X, &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;기능의 확장 관점 O &lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상속을 코드 재사용의 개념으로 이해하면 안된다. 이렇게 되면 클래스간 &lt;b&gt;결합도가 너무 높아져 유지보수 효율이 낮아진다.&lt;/b&gt; 일반적인 개념을 구체화하는 상황에서 상속을 사용하자!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;(* IS-A 란 말그대로 포함 관계를 의미한다. eg. 햄스터는 동물이다. (햄스터의 부모 클래스는 동물) )&lt;br /&gt;&lt;br /&gt;이와 반대되는 것이 HAS-A 이다. &lt;br /&gt;(* HAS-A 란 구성(Composition)관계를 의미한다. 한 객체가 다른 객체에 속한다는 의미이다. eg.컴퓨터안에는 램이 있다. (컴퓨터 객체가 램 객체를 구성함)) &lt;br /&gt;&lt;br /&gt;&lt;b&gt;4. 다형성 (Polymorphism) &lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;599&quot; data-origin-height=&quot;389&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b8DqGg/btrHRPDCdUe/o5OKYK2PUmjUMAdNFQ4Pgk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b8DqGg/btrHRPDCdUe/o5OKYK2PUmjUMAdNFQ4Pgk/img.png&quot; data-alt=&quot;같은 메소드를 사용했는데 각자 특성에 맞게 동작하는 것을 볼 수 있다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b8DqGg/btrHRPDCdUe/o5OKYK2PUmjUMAdNFQ4Pgk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb8DqGg%2FbtrHRPDCdUe%2Fo5OKYK2PUmjUMAdNFQ4Pgk%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;599&quot; height=&quot;389&quot; data-origin-width=&quot;599&quot; data-origin-height=&quot;389&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;: 서로 다른 클래스의 객체가 같은 동작 수행 명령을 받았을 때, 각자의 특성에 맞는 방식으로 동작하는 것이다. &lt;br /&gt;&lt;br /&gt;객체지향 패러다임의 핵심이다. 다형성은 상속과는 시너지가 엄청나다. 다형성 구현을 통해 코드를 간결하게 해주고, 유연함을 갖추게 된다. 또한, 구체적으로 현재 어떤 클래스 객체가 참조되는 지는 무관하게 헐렁하게 프로그래밍하는 것이 가능하다. &lt;br /&gt;&lt;br /&gt;상속 관계에 있다면, 새로운 자식 클래스가 추가되어도 부모 클래스의 함수를 참조해오면 되기 때문에 다른 클래스는 영향을 받지 않게 된다. &lt;br /&gt;&lt;br /&gt;쉽게 생각하려면 오버라이딩, 오버로딩을 생각하면 될 것 같다. &lt;br /&gt;&lt;br /&gt;1) 오버라이딩(Overiding) &lt;br /&gt;- 같은 메서드 이름, 같은 인자 목록, 상위 클래스의 메서드를 재정의한다. &lt;br /&gt;- 상위 클래스 타밉의 객체 참조 변수에서 자동으로 하위 클래스가 오버라이딩한 메소드를 호출해준다. &lt;br /&gt;&lt;br /&gt;2) 오버로딩(Overroading)&lt;br /&gt;- 같은 메서드 이름, 다른 인자 목록, 다수의 매서드 중복 정의가 가능하다.&lt;br /&gt;&lt;br /&gt;(오버라이딩과 오버로딩에 대해 더 자세히 알고 싶다면, 이 게시글을 참고 하면 이해가 쉬울것이다. &lt;br /&gt;&lt;a href=&quot;https://turtle8760.tistory.com/39?category=1059080&quot; target=&quot;_self&quot;&gt;&lt;span&gt;https://turtle8760.tistory.com/39?category=1059080&lt;/span&gt;&lt;/a&gt; )&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;| 객체 지향 설계 원칙 (&lt;b&gt;SOLID&lt;/b&gt;)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;: 객체 지향적으로 설계하기 위해 SOLID 라 불리는 다섯 가지 원칙이 있다. &lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;1. 단일 책임 원칙(&lt;b&gt;SRP,&lt;/b&gt; Single Responsibility Principle)&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;단일 책임 원칙을 지키지 않을 경우 한 책임의 변경에 의해 다른 책임과 관련된 코드에 영향이 갈 수 있다. -&amp;gt;이렇게 되면 &lt;b&gt;유지보수가 매우 비효율적&lt;/b&gt;이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;책임이라는 기준이 모호하기 때문에 &lt;b&gt;변경&lt;/b&gt;을 책임의 기준으로 삼으면 설계에 용이 할 수 있다.어떠한 역할에 대해 변경사항이 발생했을때, 애플리케이션의 파급 효과가 적으면 SRP 원칙을 잘 따른것으로 볼 수 있다.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;2. 개방-폐쇄 원칙(&lt;b&gt;OCP&lt;/b&gt;, Open/Closed Principle)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;소프트웨어 요소는 확장에는 열려 있으나 변경에는 닫혀 있어야 한다.&lt;/li&gt;
&lt;li&gt;기능을 변경하거나 확장할 수 있으면서 기능을 사용하는 코드는 수정하지 않는다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;확장에 열려있다라는 것은 모듈의 확장성을 보장하는 것을 의미한다. 새로운 변경사항이 발생했을 때 유연하게 코드 추가 또는 수정을 할 수 있기 때문이다. 그러나 객체를 직접적으로 수정하는것은 제한해야 한다. 기능이 추가되거나 수정할 때 객체를 직접적으로 수정해야 한다면 새로운 변경사항에 대해 유연하게 대응할 수 없는 애플리케이션이다. &lt;br /&gt;이는 유지보수의 비용증가가 될 수 있으며, 객체 지향적인 설계로 볼 수 없다. &lt;br /&gt;&lt;br /&gt;따라서 객체를 직접 수정하지 않고도 변경사항을 적용할 수 있도록 설계해야 한다. 결과적으로 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;OCP는 추상화를 의미하는것으로 해석된다. &lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;자주 변화하는 부분을 추상화함으로써 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;기존 코드를 수정하지 않고도 기능을 확장할 수 있도록 함으로써 유연함을 높이는것이 핵심이다. &lt;/u&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;3. 리스코프 치환 원칙(&lt;b&gt;LSP, &lt;/b&gt;Liskov Substitution Principle)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;프로그램 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야 한다.&lt;/li&gt;
&lt;li&gt;상위 타입의 객체를 하위 타입의 객체로 치환해도, 상위 타입을 사용하는 프로그램은 정상적으로 동작해야 한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 상속관계에서는 꼭 일반화 관계(IS-A)가 성립해야 하고 상속관계가 아닌 클래스들을 상속관계로 설정하면, 이 원칙에 위배될 것이다. 예를들어 정사각형과 직사각형을 생각해보자. 정사각형도 넓게 보면 직사각형의 한 종류이니, 직사각형을 상속하여 정사각형 객체를 빠르게 만들 수 있을 것이라 생각할 수 있다. 그러나 실제로 자식 클래스인 정사각형에서 함수를 실행하면 객체의 높이와 너비를 같게 만들기 때문에 원하는 값을 얻기 어렵다. &lt;br /&gt;&lt;br /&gt;곰곰히 생각해보면 사각형의 특징을 서로 갖고 있긴 하지만, 두 사각형 모두 사각형의 한 종류일 뿐이므로, 하나가 다른 하나를 완전히 포함하지 못하는 구조다. 즉, 이 경우 리스코프 치환 원칙에 위배된다. &lt;br /&gt;&lt;br /&gt;따라서, &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;상속 관계를 잘 정의하여 LSP 원칙이 위배되지 않도록&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt; &lt;/span&gt;설계해야 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;4. 인터페이스 분리 원칙(&lt;b&gt;ISP&lt;/b&gt;, Interface Segregation Principle)&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;/ul&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;/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;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bGxpyY/btrHTDvPQny/4IDyR668aQwQFDRTjK7KVK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bGxpyY/btrHTDvPQny/4IDyR668aQwQFDRTjK7KVK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bGxpyY/btrHTDvPQny/4IDyR668aQwQFDRTjK7KVK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbGxpyY%2FbtrHTDvPQny%2F4IDyR668aQwQFDRTjK7KVK%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;720&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 그림은 규모가 너무 큰 객체를 상속했을 때 발생하는 문제와 이를 인터페이스로 분리하여 해결하는 방법을 도식화 한 것이다. 두번째 객체는 아무런 문제가 없지만 세번째 객체를 보면 상속 했기 때문에 좋든 싫든 해당 메소드를 가지고 있어야 한다. &lt;br /&gt;&lt;br /&gt;하지만 상속 대상인 객체의 메소드를 각 동작별로 구분해 인터페이스로 만든다면 각 객체가 인터페이스만을 상속하여 구현하면 되므로 각자가 필요한 메소드만을 가지게 된다. 이것이 인터페이스 분리 원칙을 지향하는 바이다. &lt;br /&gt;&lt;br /&gt;각 클라이언트가 필요로 하는 인터페이스들을 분리함으로써, 클라이언트가 사용하지 않는 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;인터페이스에 변경이 발생하더라도 영향을 받지 않도록 만들어야 하는것이 핵심이다. &lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;5. 의존 관계 역전 원칙(&lt;b&gt;DIP, &lt;/b&gt;Dependency Inversion Principle)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;추상화에 의존해야지 구체화에 의존하면 안된다.&lt;/li&gt;
&lt;li&gt;고수준 모듈은 저수준 모듈의 구현에 의존해서는 안되고 저수준 모듈은 고수준 모듈에서 정의한 추상 타입에 의존해야 한다.( 저수준 모듈이 변경되어도 고수준 모듈은 변경이 필요없는 형태가 이상적이다)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고수준 모듈이란 인터페이스와 같은 객체의 형태나 추상적인 개념이고 저수준 모듈이란 구현된 객체를 의미한다. 즉, 객체는 객체보다 인터페이스에 의존해야한다로 치환할 수 있다.&lt;span style=&quot;color: #ee2323;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;가급적 객체의 상속은 인터페이스를 통해 이루어져야 한다라는 의미로 해석될 수 있다. &lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;| 면접 대비 질문 답변 정리 ⭐&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&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;b&gt;프로그래밍에서 필요한 데이터를 추상화시켜&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;상태와 행위를 가진 객체를 만들고&lt;/b&gt;&lt;b&gt; 그 객체들 간의 유기적인 상호작용을 통해 로직을 구성하는 프로그래밍 방법입니다.&lt;/b&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. 객체 지향 프로그래밍의 특징 4가지를 설명해보세요&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체 지향 프로그래밍은 추상화, 캡슐화, 상속, 다형성 이 네가지의 특징을 가집니다. 첫번째로 추상화란 객체의 공통적인 기능과 속성을 뽑아내는 것입니다. 이를 통해 유연하게 개발할 수 있습니다. 두번째로는 캡슐화란 정보를 은닉하여 응집도를 높이고 결합도를 낮추는 것입니다. 보통 접근 제어자를 활용하여 은닉할 수 있습니다. 세번째로 상속이란 말그대로 부모클래스의 속성을 자식 클래스가 물려받는 것을 의미합니다. IS-A 관계가 성립하고 기능을 확장할때 사용하게 되고 이를 사용하게 되면 코드 재사용성이 증가합니다. 마지막으로 다형성이란 서로 다른 클래스의 객체가 같은 동작 수행 명령을 받았을 때, 각자의 특성에 맞는 방식으로 동작하는 것입니다. 오버라이딩이나 오버로딩을 생각하면 쉽게 이해하실 수 있습니다. &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;br /&gt;단점으로는, 캡슐화와 격리구조 때문에 절차지향 프로그래밍과 비교하면 상대적으로 느립니다. 또한, 모든 것을 객체로 생각하기 때문에 추가적인 메모리와 연산에 대한 비용이 들어가게 됩니다. &lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;4. 객체 지향 5대원칙에 대해 설명해보세요&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SRP(단일책임원칙)은 한 클래스의 하나의 책임만 가져야 합니다.&lt;br /&gt;OCP(개방-폐쇄 원칙)은 확장에는 열려 있으나 변경에는 닫혀 있어야 합니다.&lt;br /&gt;LSP(리스코프 치환 원칙)은 프로그램의 객체는 프로그램의 정확성을 깨뜨리지 않으면서 하위 타입의 인스턴스로 바꿀 수 있어야하는 원칙으로 상위 타입을 상속해서 재정의 했을 때 프로그램이 깨지지 않아야 합니다.&lt;br /&gt;ISP(인터페이스 분리 원칙)은 클라이언트는 자신이 사용하지 않는 메서드에 의존 관계를 맺으면 안되는 원칙입니다. 특정 클라이언트를 위한 인터페이스 여러 개가 범용 인터페이스 하나보다 더 낫습니다. 즉, 비대한 인터페이스보단 더 작고 구체적인 인터페이스로 분리해야합니다.&lt;br /&gt;DIP(의존관계 역전 원칙)은 추상적인 것은 자신보다 구체적인 것에 의존하지 않고, 변화하기 쉬운 것에 의존해서는 안된다는 원칙입니다. 구체적으론 구현 클래스에 의존하지 말고, 인터페이스에 의존해야 하는 원칙입니다.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;출처:&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;br /&gt;&lt;a href=&quot;https://blog.itcode.dev/posts/2021/08/17/dependency-inversion-principle&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span&gt;&lt;b&gt;https://blog.itcode.dev/posts/2021/08/17/dependency-inversion-principle&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://github.com/ksundong/backend-interview-question&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span&gt;&lt;b&gt;https://github.com/ksundong/backend-interview-question&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://debugdaldal.tistory.com/152&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span&gt;&lt;b&gt;https://debugdaldal.tistory.com/152&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;b&gt;https://m.blog.naver.com/PostView.naver?isHttpsRedirect=true&amp;amp;blogId=wisebrain84&amp;amp;logNo=100103435083&lt;/b&gt;&lt;br /&gt;&lt;a href=&quot;https://velog.io/@raed123456/13%EC%9E%A5.-%EA%B0%9D%EC%B2%B4-%EC%A7%80%ED%96%A5-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-1&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span&gt;&lt;b&gt;https://velog.io/@raed123456/13%EC%9E%A5.-%EA%B0%9D%EC%B2%B4-%EC%A7%80%ED%96%A5-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-1&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://velog.io/@haero_kim/%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span&gt;&lt;b&gt;https://velog.io/@haero_kim/%EA%B0%9D%EC%B2%B4%EC%A7%80%ED%96%A5-%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%B0%8D-%EC%9D%B4%ED%95%B4%ED%95%98%EA%B8%B0&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;a href=&quot;https://m.blog.naver.com/atalanta16/220249264429&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span&gt;https://m.blog.naver.com/atalanta16/220249264429&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;</description>
      <category>프로그래밍/Java 정리</category>
      <author>윤도ri</author>
      <guid isPermaLink="true">https://turtle8760.tistory.com/100</guid>
      <comments>https://turtle8760.tistory.com/100#entry100comment</comments>
      <pubDate>Thu, 21 Jul 2022 21:25:24 +0900</pubDate>
    </item>
    <item>
      <title>Spring IoC , Bean</title>
      <link>https://turtle8760.tistory.com/99</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;| IoC / DI 란?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- IoC란 Inversion of Control의 줄임말이며, 제어의 역전이라고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;(이를 스프링 컨테이너가 코드 대신 오브젝트에 대한 제어권을 갖고 있다고 해서 IoC라고 부른다.)&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;span&gt;- Spring에서 사용되는&lt;b&gt; IoC&lt;/b&gt;란 객체가 내부적으로 조작할 객체를 직접 생성하지 않고 외부로부터 주입받는 기법을 의미한다. 이때 &lt;/span&gt;&lt;span&gt;객체를 외부로부터 주입해주는 작업을 &lt;b&gt;DI(의존성 주입)&lt;/b&gt;&lt;/span&gt;&lt;span&gt;이라고 부른다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;​&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;520&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/m8Nxt/btrG3LhyKJV/KhQjonqnaqtzDsDNTdPN21/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/m8Nxt/btrG3LhyKJV/KhQjonqnaqtzDsDNTdPN21/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/m8Nxt/btrG3LhyKJV/KhQjonqnaqtzDsDNTdPN21/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fm8Nxt%2FbtrG3LhyKJV%2FKhQjonqnaqtzDsDNTdPN21%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;520&quot; data-origin-width=&quot;700&quot; data-origin-height=&quot;520&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p id=&quot;SE-c176701e-f5f4-4d95-aa82-72cc958a6220&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;IoC Container는 오브젝트의 생성과 관계설정, 사용, 제거 등의 작업을 대신 해준다하여 붙여진 이름&lt;/span&gt;&lt;span&gt;이다. 이때, IoC Container에 의해 관리되는 오브젝트들은 &lt;/span&gt;&lt;span&gt;Bean&lt;/span&gt;&lt;span&gt; 이라고 부른다. IoC Container는 Bean을 저장한다고 하여, BeanFactory 라고도 불린다. BeanFactory는 하나의 인터페이스이며, Application Context는 BeanFactory의 구현체를 상속받고 있는 인터페이스이다. 실제로 &lt;/span&gt;&lt;span&gt;스프링에서 IoC Container 라고 불리는 것은 Application Context의 구현체이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;| Spring DI/IoC 는 어떻게 동작하나?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;IoC(제어의 역전)은 프로그램의 제어 흐름을 직접 제어하는 것이 아니라 외부에서 관리하는 것으로 코드의 최종호출은 개발자가 제어하는 것이 아닌 프레임워크의 내부에서 결정된 대로 이루어진다.&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;DI(의존관계 주입)은 Spring 프레임워크에서 지원하는 IoC의 형태로 클래스 사이의 의존관계를 빈 설정 정보를 바탕으로 컨테이너가 자동으로 연결해준다.&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;스프링에서는 스프링 컨테이너 ApplicationContext를 이용하여 설정 정보를 생성, 등록하고 필요한 객체를 생성자 혹은 setter를 통해 주입한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;| IoC 컨테이너의 역할&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체의 생성을 책임지고, 의존성을 관리해준다. 그래서 개발자들은 비즈니스 로직에 집중할 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;| Spring Bean이란&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;IoC 컨테이너에 의해 관리되는 오브젝트들은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;Bean&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;이라고 부른다. &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;IoC 컨테이너 안에 들어있는 객체로 필요할 때 IoC컨테이너에서 가져와서 사용하며 @Bean 을 사용하거나 xml설정을 통해 일반 객체를 Bean으로 등록할 수 있다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;| Spring Bean 의 생성과정&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;객체 생성 &amp;rarr; 의존 설정 &amp;rarr; 초기화 &amp;rarr; 사용 &amp;rarr; 소멸 과정&lt;/b&gt;의 생명주기를 가지고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스프링 컨테이너가 초기화 될 때 먼저 빈 객체를 설정 정보에 맞추어 생성하고, 의존 관계를 설정한 뒤에 해당 프로세스가 완료되면 빈 객체가 지정한 메소드를 호출해서 초기화한다.객체를 사용한 뒤 컨테이너가 종료 될 때 빈이 지정한 메소드를 호출해 소멸 과정을 진행한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp;1. 빈 초기화, 소멸 (Initialize &amp;amp; Destory)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&amp;nbsp; 빈 초기화방법은 @PostConstruct 를 빈 소멸에서는 @PreDestroy 를 사용한다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;@PostConstruct&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;초기화하고 싶은 메서드에 @PostConstruct 애노테이션을 붙여주면 Spring이 해당 메서드를 초기화시에 호출하게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1657612079899&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Slf4j
@Component
public class SimpleBean {

    @PostConstruct
    public void postConstruct() {
        log.info(&quot;postConstruct&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;@PreDestroy&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;@PreDestroy는 컨테이너가 종료될 때 실행하고 싶은 메서드에 애노테이션을 붙여주면 Spring이 컨테이너 종료 시 해당 메서드를 호출한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1657711561061&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Slf4j
@Component
public class SimpleBean {

    @PreDestroy
    public void preDestroy() {
        log.info(&quot;preDestroy&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;div id=&quot;main__content&quot;&gt;
&lt;div id=&quot;__permalink_article&quot;&gt;
&lt;div data-mode=&quot;tape&quot;&gt;
&lt;div&gt;&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style8&quot; /&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&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;2. Spring Bean 등록&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생성한 스프링 빈을 등록할 때는 ComponentScan을 이용하거나 @Configuration 의 @Bean 을 사용하여 빈 설정파일에 직접 빈을 등록할 수 있다.&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;컴포넌트 스캔의 원리는 기본적으로 @Component 어노테이션이 있으면 자동으로 스프링 빈으로 등록된다. 참고로, @Component 어노테이션은&amp;nbsp; @Controller , @Service, @Repository를 포함한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1657611463134&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Controller 
public class MemberController {

    private final MemberService memberService;
    @Autowired
    //멤버 컨트롤러가 생성이 될떄 스프링빈에 등록되어있는 멤버서비스를 주입
    public MemberController(MemberService memberService) {
        this.memberService = memberService;
    }
}&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;@Configuration 어노테이션을 추가하고, 스프링 빈으로 등록하고자 하는 Service와 Repository에 @Bean 어노테이션을 추가하면, 스프링 빈으로 등록된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1657611557316&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;@Configuration
public class SpringConfig {

    @Bean
    public MemberService memberService() {
        return new MemberService(memberRepository());
    }

    @Bean
    public MemberRepository memberRepository(){
        return new MemoryMemberRepository();
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;| Spring Bean의 Scope 이란&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 빈 스코프는 &lt;b&gt;빈이 존재할 수 있는 범위&lt;/b&gt;를 뜻이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 종류: 싱글톤, 프로토타입, request, session, application 등&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;b&gt;프로토타입&lt;/b&gt;은 빈의 생성과 의존관계 주입까지만 관여하고 더는 관리하지 않는 매우 짧은 범위의 스코프이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;request&lt;/b&gt;는 웹 요청이 들어오고 나갈때까지 유지하는 스코프, session은 웹 세션이 생성, 종료할때까지, &lt;b&gt;application&lt;/b&gt;은 웹 서블릿 컨텍스트와 같은 범위로 유지하는 스코프이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;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://1-7171771.tistory.com/105&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://1-7171771.tistory.com/105&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;a href=&quot;https://github.com/ksundong/backend-interview-question&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/ksundong/backend-interview-question&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://ooeunz.tistory.com/107&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://ooeunz.tistory.com/107&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>프로그래밍/Spring</category>
      <author>윤도ri</author>
      <guid isPermaLink="true">https://turtle8760.tistory.com/99</guid>
      <comments>https://turtle8760.tistory.com/99#entry99comment</comments>
      <pubDate>Tue, 12 Jul 2022 16:53:46 +0900</pubDate>
    </item>
    <item>
      <title>[백준] 3184번 - 양(JAVA)</title>
      <link>https://turtle8760.tistory.com/98</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;양.jpg&quot; data-origin-width=&quot;1201&quot; data-origin-height=&quot;865&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/E2UK7/btrFxiF6GZH/sQKPIYWNTaQUCz2jTO34rK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/E2UK7/btrFxiF6GZH/sQKPIYWNTaQUCz2jTO34rK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/E2UK7/btrFxiF6GZH/sQKPIYWNTaQUCz2jTO34rK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FE2UK7%2FbtrFxiF6GZH%2FsQKPIYWNTaQUCz2jTO34rK%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1201&quot; height=&quot;865&quot; data-filename=&quot;양.jpg&quot; data-origin-width=&quot;1201&quot; data-origin-height=&quot;865&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;양2.jpg&quot; data-origin-width=&quot;1222&quot; data-origin-height=&quot;682&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eeDPmk/btrFuxjXYks/7Cw321AIWo0jbnYFUuGti1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eeDPmk/btrFuxjXYks/7Cw321AIWo0jbnYFUuGti1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eeDPmk/btrFuxjXYks/7Cw321AIWo0jbnYFUuGti1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeeDPmk%2FbtrFuxjXYks%2F7Cw321AIWo0jbnYFUuGti1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1222&quot; height=&quot;682&quot; data-filename=&quot;양2.jpg&quot; data-origin-width=&quot;1222&quot; data-origin-height=&quot;682&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;| 풀이&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;BFS&lt;/b&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;gt; 이를 위해 dfs() 메소드를 호출할 때 '.','v','o' 이어야 하며 방문하지 않았어야 합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- dfs() 메소드가 끝날 때마다 늑대의 수가 양의 수 이상일 경우에는 늑대의 수만 누적시켜주고&amp;nbsp; 그 반대의 경우에는 양의 수만 누적시켜준다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;캡처1.jpg&quot; data-origin-width=&quot;1188&quot; data-origin-height=&quot;658&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bBCtJZ/btrFT4uAiZo/JlsK8ungwBWVFuPWo129kk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bBCtJZ/btrFT4uAiZo/JlsK8ungwBWVFuPWo129kk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bBCtJZ/btrFT4uAiZo/JlsK8ungwBWVFuPWo129kk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbBCtJZ%2FbtrFT4uAiZo%2FJlsK8ungwBWVFuPWo129kk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1188&quot; height=&quot;658&quot; data-filename=&quot;캡처1.jpg&quot; data-origin-width=&quot;1188&quot; data-origin-height=&quot;658&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;bfs.jpg&quot; data-origin-width=&quot;1162&quot; data-origin-height=&quot;628&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dnqR2D/btrF9DqiRWP/gKA8ZCbBhZiIzKRM7Bvxek/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dnqR2D/btrF9DqiRWP/gKA8ZCbBhZiIzKRM7Bvxek/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dnqR2D/btrF9DqiRWP/gKA8ZCbBhZiIzKRM7Bvxek/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdnqR2D%2FbtrF9DqiRWP%2FgKA8ZCbBhZiIzKRM7Bvxek%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1162&quot; height=&quot;628&quot; data-filename=&quot;bfs.jpg&quot; data-origin-width=&quot;1162&quot; data-origin-height=&quot;628&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;| 입출력&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;bufferedreader 와 system.out.print 를 사용하여 입출력 했다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;| 문제 풀이&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1656316269423&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.*;
import java.io.*;

public class Sheep_3184 {
	
	//마당 , 방문체크, 총 양, 총 늑대 
	
	static int R, C;
	static char[][] yard;
	static boolean[][] visited;
	static int[] dx = { 0, 0, 1, -1 }, dy = { 1, -1, 0, 0 };
	static int sheepTotal, wolfTotal;

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

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

		R = Integer.parseInt(st.nextToken());
		C = Integer.parseInt(st.nextToken());

		yard = new char[R][C];
		visited = new boolean[R][C];

		for (int i = 0; i &amp;lt; R; i++) {
			yard[i] = br.readLine().toCharArray();
		}
		
		//울타리가 쳐있지 않은 구역의 시작을 기준으로 BFS 탐색을 한다. 
		
		for (int i = 0; i &amp;lt; R; i++) {
			for (int j = 0; j &amp;lt; C; j++) {
				if (yard[i][j] != '#' &amp;amp;&amp;amp; !visited[i][j]) {
					bfs(i, j);
				}
			}
		}
		System.out.println(sheepTotal + &quot; &quot; + wolfTotal);

	}

	static void bfs(int x, int y) {
		Queue&amp;lt;int[]&amp;gt; q = new LinkedList&amp;lt;&amp;gt;();
		
		visited[x][y] = true;
		
		q.add(new int[] { x, y });
		
		int sheepCnt = 0, wolfCnt = 0;

		while (!q.isEmpty()) {
			int[] now = q.poll();
			
			//양의 수 세기 
			if (yard[now[0]][now[1]] == 'o')
				sheepCnt++;
			//늑대의 수 세기 
			else if (yard[now[0]][now[1]] == 'v')
				wolfCnt++;
			
			
			for (int i = 0; i &amp;lt; 4; i++) {
				int nx = now[0] + dx[i];
				int ny = now[1] + dy[i];
					//범위를 벗어났느냐 or 방문했느냐 or 울타리에 있느냐 
				if (!isRange(nx, ny) || visited[nx][ny] || yard[nx][ny] == '#')
					continue;

				visited[nx][ny] = true;
				q.add(new int[] { nx, ny });

			}
		}
		//양의 수가 크면 총 양에 더한다.
		if (sheepCnt &amp;gt; wolfCnt) {
			
			sheepTotal += sheepCnt;
		}
		//양의 수가 작거나 같으면 총 늑대에 더한다. 
		else {
			
			wolfTotal += wolfCnt;			
		}

	}

	//범위를 벗어나는지 여부를 보여준다. 
	static boolean isRange(int x, int y) {
		return x &amp;gt;= 0 &amp;amp;&amp;amp; x &amp;lt; R &amp;amp;&amp;amp; y &amp;gt;= 0 &amp;amp;&amp;amp; y &amp;lt; C;
	}
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;참고:&amp;nbsp;&lt;b&gt;&lt;a href=&quot;https://ddb8036631.github.io/boj/3184_%EC%96%91/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://ddb8036631.github.io/boj/3184_%EC%96%91/&lt;/a&gt;&lt;/b&gt;&lt;/p&gt;</description>
      <category>알고리즘 &amp;amp; 자료구조/그래프</category>
      <author>윤도ri</author>
      <guid isPermaLink="true">https://turtle8760.tistory.com/98</guid>
      <comments>https://turtle8760.tistory.com/98#entry98comment</comments>
      <pubDate>Mon, 27 Jun 2022 16:59:23 +0900</pubDate>
    </item>
    <item>
      <title>치과위생사 개발자로 전향하다.</title>
      <link>https://turtle8760.tistory.com/97</link>
      <description>&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: center;&quot;&gt;그동안 참 바쁘게 지내고 많은 일이 있었다. 국비 학원을 수료하고 벌써 2개월이 지났다. 취업 준비를 하던 중 &lt;br&gt;내가 진로를 바꾸게 된 스토리를 남기고 싶어 적게 되었다. &lt;br&gt;&lt;br&gt;&lt;/p&gt;
&lt;h4 style=&quot;text-align: center;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #6164c6;&quot;&gt;나는 &lt;/span&gt;&lt;span style=&quot;color: #6164c6;&quot;&gt;&lt;b&gt;백엔드 개발자&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #6164c6;&quot;&gt;로 전직 준비중인 &lt;/span&gt;&lt;span style=&quot;color: #6164c6;&quot;&gt;&lt;b&gt;치과위생사&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #6164c6;&quot;&gt;이다. &lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot; style=&quot;text-align: center;&quot;&gt;다들 궁금해하실 것 같다. 문과도 아니고 보건계열인데 왜 개발자가 되었지? &lt;br&gt;글로 설명하면 나에게 관심을 가져주시는 분들께 도움이 되지 않을까 하여 작성해보았다.&lt;/p&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot;&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;p data-ke-size=&quot;size16&quot;&gt;&lt;br&gt;사람들을 돕는 일을 하고 싶어 2014년 치위생학과에 입학하여 2018년에 치과위생사 면허를 취득하고 바로 일을 시작했다. 줄글만 가득 찬 재미없는 책들만 보다가 직접 보고 해 보니 (물론 실습도 했다) 책의 이론들이 와닿고 임상이 재미있구나 생각을 했고 어느 신입들처럼 나 또한 희망찬 미래를 그려 나갔던 것 같다.&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kWPwP/btrFqcsGwr5/RPKVgCMRYSHCq3u40WQqH1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kWPwP/btrFqcsGwr5/RPKVgCMRYSHCq3u40WQqH1/img.jpg&quot; data-alt=&quot; 치과 CT이다. 임플란트를 심기전 보통 길이를 재기 위해 찍는데 치과에서 보통 이런 업무를 한다고 보면 될 것 같다. &quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kWPwP/btrFqcsGwr5/RPKVgCMRYSHCq3u40WQqH1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkWPwP%2FbtrFqcsGwr5%2FRPKVgCMRYSHCq3u40WQqH1%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;599&quot; height=&quot;449&quot; data-origin-width=&quot;4032&quot; data-origin-height=&quot;3024&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt; 치과 CT이다. 임플란트를 심기전 보통 길이를 재기 위해 찍는데 치과에서 보통 이런 업무를 한다고 보면 될 것 같다. &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;졸업 후 2년을 선생님들 밑에서 배우느라 정신없이 보내고 적응을 점차 해나갔다. 그런데 어느 날 갑자기 이 일을 계속할 수 있을까? 그런 의문이 들었다. 치료가 끝나고 환자분들이 나에게 감사하다고 말해주실 땐 행복하고 뿌듯함이 컸지만 이 직업에 대한 확신이 없었다. 이 직업으로 일한다면 어느 순간 &lt;u&gt;&lt;i&gt;내 성장이 멈출것 같았고 불안했다. &lt;/i&gt;&lt;/u&gt;&lt;br&gt;&lt;br&gt;그때의 난 직업을 바꾸겠다는 마음은 감히 먹지 못했다. 무려 4년이나 공부하고 면허를 땄기 때문이다. 그래서 치과분야에서 가능한 경우의 수를 모두 생각했던 것 같다. 하지만 한계가 있었고 갈 수 있는 곳이 많지 않았다. 그래서 난 외국을 나가보기로 결정했다. 처음엔 워킹 홀리데이로 1년만 다녀올까 생각하다가 캐나다에서 치과위생사로서 큰 메리트가 있다는 것을 알게 되었고 캐나다의 dental hygiene 이 있는 컬리지에 도전해보기로 했고 본격적으로 치과를 다니며 영어공부를 병행하기 시작했다.&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1107&quot; data-origin-height=&quot;462&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/btANjA/btrFo07IlWa/BHvjFtaCF9cdmYCULCYw5K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/btANjA/btrFo07IlWa/BHvjFtaCF9cdmYCULCYw5K/img.png&quot; data-alt=&quot; 대학교성적을 토대로 조건부 합격을 했었다. &quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/btANjA/btrFo07IlWa/BHvjFtaCF9cdmYCULCYw5K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbtANjA%2FbtrFo07IlWa%2FBHvjFtaCF9cdmYCULCYw5K%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;623&quot; height=&quot;260&quot; data-origin-width=&quot;1107&quot; data-origin-height=&quot;462&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt; 대학교성적을 토대로 조건부 합격을 했었다. &lt;/figcaption&gt;
&lt;/figure&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;p data-ke-size=&quot;size16&quot;&gt;&lt;br&gt;컬리지를 도전하려하니 해야 할 것이 많았다. 아이엘츠 점수도 만들어야 하고 비자도 신청해야 했고 돈을 만들어 놓기 위해 계속 일도 해야 했다. 일단 아이엘츠 .. 머나먼 산이었다. 영어라곤 대학교 때 토익한 이후로 처음이었기 때문이다. 자기소개도 헬로우 나이스투미츄 앤유? 정도 할 수 있는 왕초보중의 왕초보 수준이었다. &lt;br&gt;&lt;br&gt;첫 번째로 난 영어에 대한 자신감이 필요하다고 생각하여 일이 끝나고 회화학원에 다녔다. 3개월을 첫 번째 회화학원을 다녔는데 Basic Grammer in Use 를 활용하여 매일매일 페어와 함께 연습했다. 일이 끝나고 과제를 해야 하는데 너무 피곤해서 자지 않기 위해 나의 직장에서 역까지 걸어 다니면서 (거의 30분 거리) 외웠던 기억이 난다. 결국 이 학원에서 좋은 성적으로 졸업하게 되었고 영어로 말하는 것이 더 이상 두렵지 않았고 재밌었다. 두 번째 회화학원도 5개월 정도 다녔는데 엄청 재미있었던 기억이 난다. 숙제도 어마 무시했지만 한번 입이 트이고 나니 재미있어서 새벽을 새더라도 꾸준히 다 해갔던 기억이 난다.&lt;br&gt;&lt;br&gt;회화가 어느정도 됐다고 생각하여(그땐 그랬지만..지금은 가장 어렵다..) 난 아이엘츠를 준비하기 시작했다. 아이엘츠는 Listening, Reading, Writing, Speaking 총 4과목으로 이루어져 있다. 학교를 입학하기 위해 필요한 점수가 있었고 고군분투했다. 하지만 Speaking 한 과목 때문에 끝까지 노력했지만 조건부 허가를 받아놓고 결국 가지 못했다. 정말 힘들었고 이 길이 내 길이 맞을까 혼란스러웠다. 이때가 지금까지 내 인생에서 가장 힘든 순간이 아니었을까 싶다.&lt;/p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xp4hY/btrFpvzAKKC/QCKqVMFJaobrD6ia0gGb30/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xp4hY/btrFpvzAKKC/QCKqVMFJaobrD6ia0gGb30/img.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot; style=&quot;width: 49.4186%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xp4hY/btrFpvzAKKC/QCKqVMFJaobrD6ia0gGb30/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fxp4hY%2FbtrFpvzAKKC%2FQCKqVMFJaobrD6ia0gGb30%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3024&quot; height=&quot;4032&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Y6S4r/btrFpGgt17t/OqucGD7yNuKIcQAUA2OQIk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Y6S4r/btrFpGgt17t/OqucGD7yNuKIcQAUA2OQIk/img.jpg&quot; data-origin-width=&quot;3024&quot; data-origin-height=&quot;4032&quot; style=&quot;width: 49.4186%;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Y6S4r/btrFpGgt17t/OqucGD7yNuKIcQAUA2OQIk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FY6S4r%2FbtrFpGgt17t%2FOqucGD7yNuKIcQAUA2OQIk%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3024&quot; height=&quot;4032&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;첫번째 사진은 첫번째 학원에서 받은 상장이고 두번째는 두번쨰 학원에서 공부해온 책들이다.&amp;amp;amp;nbsp;&lt;/figcaption&gt;
&lt;/figure&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;p data-ke-size=&quot;size16&quot;&gt;&lt;br&gt;컬리지가 1년이 유예되면서 나는 내 인생에 대해 돌아보기 시작했다. 1년동안 무엇을 해야 할지 감이 잡히지 않았다. 아이엘츠 점수를 빨리 따고 다시 취업을 하는 게 맞았지만 치과위생사 길이 맞나 고민이 들었다. 처음에 말한 것처럼 사실 난 이 직업에 대한 확신이 없었다. &lt;br&gt;&lt;br&gt;캐나다에서 충분히 치과위생사로 일하고 먹고 살 수 있었지만 내가 이 일을 평생 하면 행복할까?라는 의문이 들었다. 만약 캐나다에서 계속 산다면? 만약 내가 혼자 산다 면 감당할 수 있을까? 이런 여러 가지 생각이 뒤엉켰던 것 같다. 쉬면서 영어공부는 계속했지만 진로에 대한 고민을 계속하게 되었다. &lt;br&gt;&lt;br&gt;&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;b&gt; &lt;/b&gt;&lt;br&gt;계속 방황을 하던 중 고민을 하더라도 돈을 벌면서 해야 겠다고 생각했다. 그래서 여러 가지 알아보던 중 아는 치과위생사 친구가 이 사업을 참여하면 소정의 돈을 준다고 하여 참여하게 되었다. 보건계열 학과면 누구나 참여할 수 있는 정부지원 사업이라 쉽게 지원할 수 있었다.&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;793&quot; data-origin-height=&quot;304&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/V99TX/btrFrddV9Fn/Sh1ukZ33zJghfTZ9ZUEGS1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/V99TX/btrFrddV9Fn/Sh1ukZ33zJghfTZ9ZUEGS1/img.png&quot; data-alt=&quot; 이렇게 이메일이 왔고 이때부터 시작하게 되었다. &quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/V99TX/btrFrddV9Fn/Sh1ukZ33zJghfTZ9ZUEGS1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FV99TX%2FbtrFrddV9Fn%2FSh1ukZ33zJghfTZ9ZUEGS1%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;540&quot; height=&quot;207&quot; data-origin-width=&quot;793&quot; data-origin-height=&quot;304&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt; 이렇게 이메일이 왔고 이때부터 시작하게 되었다. &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;코딩이라곤 ㅋ자도 모르던 나는 과제로 주어진 강의를 듣기 시작했다. 리눅스의 기초, 파이썬 문법, 프로그래밍 R을 강의로 학습하였는데 흥미로웠다. 가장 흥미로운 것은 내가 코드를 작성하는 대로 화면에 나타는 것이었다. 이때부터 프로그래밍에 관심이 많아졌던 것 같다.&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1075&quot; data-origin-height=&quot;932&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/K53Xr/btrFoDriXlF/cNoaKkh18AOnsRk5VUTDz0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/K53Xr/btrFoDriXlF/cNoaKkh18AOnsRk5VUTDz0/img.jpg&quot; data-alt=&quot; 열심히 강의들으며 정리했던 기록이 있다. 물론 지금은 쓴지 오래되어 잘 기억이 안나지만.. 다시 공부하면 빨리 학습 할 수 있지 않을까..? &quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/K53Xr/btrFoDriXlF/cNoaKkh18AOnsRk5VUTDz0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FK53Xr%2FbtrFoDriXlF%2FcNoaKkh18AOnsRk5VUTDz0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;535&quot; height=&quot;464&quot; data-origin-width=&quot;1075&quot; data-origin-height=&quot;932&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt; 열심히 강의들으며 정리했던 기록이 있다. 물론 지금은 쓴지 오래되어 잘 기억이 안나지만.. 다시 공부하면 빨리 학습 할 수 있지 않을까..? &lt;/figcaption&gt;
&lt;/figure&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;p data-ke-size=&quot;size16&quot;&gt;&lt;br&gt;바이오 데이터 엔지니어 사업에 참여하며 나는 진로에 대해 깊게 고민해보는 시간을 가졌다. 예전부터 눈여겨보던 진로를 찾아주는 프로그램이 있었는데 무려 30만원이라 3개월 동안 수많은 고민을 거쳐 내 인생을 위해 투자하기로 했다. 결국 이 경험은 &lt;u&gt;&lt;i&gt;나에게 진로를 바꾸겠다는 큰 확신을 가지게 해주었다.&lt;/i&gt;&lt;/u&gt;&lt;br&gt;&lt;br&gt;처음 몇 주는 직업을 선택하는 방법에 대해 알려주신다. 직업을 선택할 때 돈을 보고 선택하는 것이 아니라고 하셨다. 딱 3가지를 보고 결정하는 것인데 &lt;u&gt;재능, 성향, 직업을&lt;/u&gt; 선택할 때 &lt;u&gt;동기&lt;/u&gt; 3가지를 보고 결정하라고 하셨다. &lt;br&gt;&lt;br&gt;전화 상담 전 적어야 하는 항목이 있어 열심히 작성 후 1시간 상담을 했던 것 같다. 이때 충격받은 점이 있었는데 선생님이 나한테 치과위생사는 맞지 않는 직업이라고 하셨다. &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;i&gt;직업을 선택할 때 발전/성장하는 일을 할때 가장 동기부여를 많이 얻고 반복적인 일을 하는 것이 안 맞는다고 하셨다. &lt;/i&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이때부터 아차 했던 것 같다. 내가 지금껏 피곤하게 느끼고 힘들었던 이유가 이게 아니었을까 생각했다. 두 번째로 신기했던 건 나에게 적성이 맞는 직업목록에 SW 개발자가 있었다. &lt;/span&gt;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1617&quot; data-origin-height=&quot;445&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b0sGhP/btrFqq5Ft6u/cziyB3bwSdr56vrXrkAQuk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b0sGhP/btrFqq5Ft6u/cziyB3bwSdr56vrXrkAQuk/img.png&quot; data-alt=&quot; 동기에 발전/성장이 가장 높은 것을 볼 수 있고 호기심이 높은 편인걸 볼 수 있다. 재능에 봉사/서비스가 높게 나온건 내가 무의식적으로 사람을 돕는 일이 봉사/의료서비스 제공으로 생각했어서 인것 같다. &quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b0sGhP/btrFqq5Ft6u/cziyB3bwSdr56vrXrkAQuk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb0sGhP%2FbtrFqq5Ft6u%2FcziyB3bwSdr56vrXrkAQuk%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;1617&quot; height=&quot;445&quot; data-origin-width=&quot;1617&quot; data-origin-height=&quot;445&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt; 동기에 발전/성장이 가장 높은 것을 볼 수 있고 호기심이 높은 편인걸 볼 수 있다. 재능에 봉사/서비스가 높게 나온건 내가 무의식적으로 사람을 돕는 일이 봉사/의료서비스 제공으로 생각했어서 인것 같다. &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이때까지 난 반신반의했던 것 같다. 해보지도 않고 맞는지 여부를 알 수 없기 때문이다. 선생님은 그 직업에 대해 직접 알아보라고 하셨다. &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;처음엔 이럴 거면 이 프로그램을 왜 하나 30만 원이나 줬는데 넌 이게 맞아! 이렇게 사주 맛집처럼 말해주셔야 되는 거 아닌가 생각했다. 그렇지만 백수에겐 30만 원이란 피 같은 돈이기 때문에 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;난 유튜브, 구글 등을 뒤져가며 현실적인 부분, 일적인 부분, 비전공자로서의 어려움 등을 모두 다 찾아보고 잡코리아에 들어가서 개발자가 되려면 어떠한 역량이 필요한지 모두 찾아보았다. 직접 해보니 선생님의 말씀이 이해가 갔다. 내가 직접 주도적으로 알아보니 이 일이 나에게&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;i&gt; 잘 맞겠다는 확신을 들게 해 주었다.&lt;/i&gt;&lt;/u&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;모든 주도적으로 하는 것은 정말 중요하구나 깨달았다.&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;460&quot; data-origin-height=&quot;343&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EMNhS/btrFoo2csgi/J7niFOR359dy1Sl3tVH2I1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EMNhS/btrFoo2csgi/J7niFOR359dy1Sl3tVH2I1/img.png&quot; data-alt=&quot; 결국 SW 개발자를 선택하였다. &quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EMNhS/btrFoo2csgi/J7niFOR359dy1Sl3tVH2I1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEMNhS%2FbtrFoo2csgi%2FJ7niFOR359dy1Sl3tVH2I1%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;319&quot; height=&quot;238&quot; data-origin-width=&quot;460&quot; data-origin-height=&quot;343&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt; 결국 SW 개발자를 선택하였다. &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt; &lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;[ 생활코딩으로 CSS, HTML을 맛보다 ]&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br&gt;&lt;span style=&quot;color: #000000;&quot;&gt;이때쯤 나는 바이오 데이터 엔지니어 양성산업에 반정도 참여한 상태였는데(오직 강의만 들었다..) 진로 탐색을 끝나고 나서 바로 개발자로 도전을 할까 고민을 하다가 이 때 한번 더 직접 개발을 해보고 결정해야겠다고 생각했다. (의심하고 또 의심하라...^^..) 처음 입문을 보통 생활코딩으로 하길래 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;HTML과 CSS 강의를 들으며 독학했다. &lt;/b&gt;&lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 처음 화면을 구현해보며 신세계를 맛보았다. 와 이걸 내가 왜 이제 알았지 싶었다. 그냥 당연하게 생각했던 UI 가 코드 몇 줄로 나타난다는 것이 멋지다고 생각했다. 이때&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 개발자로 도전해야겠다고 확신했다. &lt;/span&gt;&lt;br&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;/span&gt;&lt;br&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 치과에서 일하면서 아쉬웠던 점들이 많았다. 의료정보에 대한 격차로 환자마다 받는 서비스가 크게 차이 난다는 것을 알았고 나 또한 겪는 일이기도 했다. 그래서 나중에 &lt;/span&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;i&gt;&lt;b&gt;의료 서비스 플랫폼을 만들어 이 격차를 줄이고 사회에 기여할 수 있는 개발자가 되고 싶다고 생각했다. &lt;/b&gt;&lt;/i&gt;&lt;/span&gt;&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;256&quot; data-origin-height=&quot;197&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bcnBsM/btrFqqLlAhY/Xf0ZWMKAN3Vt0KIPQm2vmK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bcnBsM/btrFqqLlAhY/Xf0ZWMKAN3Vt0KIPQm2vmK/img.png&quot; data-alt=&quot; 이 분 강의는 입문자에게 듣기 아주 적절한 강의이다. (강추) 나처럼 ㅋ 도 모르던 코알못도 쉽게 이해할 수 있다. &quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bcnBsM/btrFqqLlAhY/Xf0ZWMKAN3Vt0KIPQm2vmK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbcnBsM%2FbtrFqqLlAhY%2FXf0ZWMKAN3Vt0KIPQm2vmK%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;256&quot; height=&quot;197&quot; data-origin-width=&quot;256&quot; data-origin-height=&quot;197&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt; 이 분 강의는 입문자에게 듣기 아주 적절한 강의이다. (강추) 나처럼 ㅋ 도 모르던 코알못도 쉽게 이해할 수 있다. &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;[국비 학원을 신청하다]&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br&gt;개발자로 도전하기로 마음먹은 후 바이오 데이터 엔지니어 양성 산업은 중간에 그만두었다. 개발을 집중적으로 배워보고 싶었기 때문이다. 그리고 나는 컬리지를 환불했다.(약 200만 원의 손해를 봤지만..) 더 이상 돌이킬 수 없었고 나에겐 이 길을 가야겠다는 그만큼 확신이 있었다. &lt;br&gt;&lt;br&gt;국비 학원을 선택하는 것 또한 쉽지 않았다. 처음 선택이 중요하다는 것을 알았기에 이곳저곳 상담을 받았다. 그러던 중 쌍* 국비학원에 합격하였다.(국비 학원 또한 등록하려면 시험을 봐야 한다..) 그런데 그곳에 입과 준비를 하던 중 우연히 어떤 분이 타 학원의 강사님을 추천해주셨다. 난 학원보다 강사가 중요하다고 생각했기에 충분히 알아본 뒤 결국 타 학원으로 등록하게 되었다. &lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;[ 6개월간 국비 학원에서의 고군분투 ]&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br&gt;학원을 다니면서 나 자신에게 약속했던 것은 오늘 들은 수업은 오늘 모두 이해하고 복습하자였다. 처음엔 오프라인 수업이어서 우리 집부터 학원까지 한 시간 반이상이 소요되어 5시쯤 일어나서 학원을 가고 저녁 10시 넘어서까지 복습하고 갈 때도 많았다. 나는 알았다. 비전공자로서 전공자들을&amp;nbsp;&amp;nbsp;뛰어넘으려면 이건 아무것도 아니라고 생각했다. 그래서 결국 난 수업을 끝나기까지&lt;u&gt; &lt;/u&gt;&lt;u&gt;&lt;i&gt;수업들은 모든 내용을 블로그에 올리게 되었다&lt;/i&gt;&lt;/u&gt;&lt;u&gt;.&lt;/u&gt; 또한 일주일에 3번 이상 강사님이 짜주신 팀원들끼리 오늘 배운 부분에 대해 복습하고 토론했다. 전공자분들이 꽤 계셔서 모르는 부분을 도움받을 수 있었고 나 또한 열심히 찾아보고 내가 아는 부분은 열심히 설명해드렸던 것 같다. &lt;br&gt;&lt;br&gt;교육을 들은 지 4개월쯤 되어 JSP를 활용한 팀 프로젝트를 참여했다. 기획부터 개발까지 하는 것은 처음이라 어려움이 많았다. 열심히 최선을 다했지만 결과적으로 프로젝트가 미완성으로 끝나게 되었고 이때 커뮤니케이션의 중요성에 대해 크게 깨달았다. 느낀 점은 아래 링크를 달아두었다. &lt;br&gt;&lt;a href=&quot;https://turtle8760.tistory.com/87?category=1072840&quot; target=&quot;_self&quot;&gt;&lt;span&gt;https://turtle8760.tistory.com/87?category=1072840&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;
&lt;figure data-ke-type=&quot;opengraph&quot; data-og-title=&quot;JSP  팀 프로젝트 끝, 느낀점&quot; data-ke-align=&quot;alignCenter&quot; data-og-description=&quot;드디어 두 달 만에 첫 프로젝트를 마무리하게 되었다!! 사실 끝나자마자 쓰려고 했으나 시간이 부족하여 국비과정이 완료되고 작성하게 되었다. 일단 한 문장으로 느낀 점을 표현하자면 &amp;quot;많이 &quot; data-og-host=&quot;turtle8760.tistory.com&quot; data-og-source-url=&quot;https://turtle8760.tistory.com/87?category=1072840&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dlomR7/hyOQqaqMaj/x3agUEpkUK4hScMYYfUEUK/img.jpg?width=297&amp;amp;height=170&amp;amp;face=0_0_297_170,https://scrap.kakaocdn.net/dn/bJJ6m3/hyOQyGikNv/C3WnkqLkqkvNkGkPVoqXSk/img.jpg?width=297&amp;amp;height=170&amp;amp;face=0_0_297_170,https://scrap.kakaocdn.net/dn/wcBJw/hyOQqIgZms/0rqaBIMJ0UfN7HYzfwMxh1/img.jpg?width=750&amp;amp;height=750&amp;amp;face=0_0_750_750&quot; data-og-url=&quot;https://turtle8760.tistory.com/87&quot;&gt;
 &lt;a href=&quot;https://turtle8760.tistory.com/87&quot; target=&quot;_blank&quot; data-source-url=&quot;https://turtle8760.tistory.com/87?category=1072840&quot;&gt;
  &lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dlomR7/hyOQqaqMaj/x3agUEpkUK4hScMYYfUEUK/img.jpg?width=297&amp;amp;height=170&amp;amp;face=0_0_297_170,https://scrap.kakaocdn.net/dn/bJJ6m3/hyOQyGikNv/C3WnkqLkqkvNkGkPVoqXSk/img.jpg?width=297&amp;amp;height=170&amp;amp;face=0_0_297_170,https://scrap.kakaocdn.net/dn/wcBJw/hyOQqIgZms/0rqaBIMJ0UfN7HYzfwMxh1/img.jpg?width=750&amp;amp;height=750&amp;amp;face=0_0_750_750')&quot;&gt; 
  &lt;/div&gt;
  &lt;div class=&quot;og-text&quot;&gt;
   &lt;p class=&quot;og-title&quot;&gt;JSP&amp;nbsp;&amp;nbsp;팀 프로젝트 끝, 느낀점&lt;/p&gt;
   &lt;p class=&quot;og-desc&quot;&gt;드디어 두 달 만에 첫 프로젝트를 마무리하게 되었다!! 사실 끝나자마자 쓰려고 했으나 시간이 부족하여 국비과정이 완료되고 작성하게 되었다. 일단 한 문장으로 느낀 점을 표현하자면 &quot;많이 &lt;/p&gt;
   &lt;p class=&quot;og-host&quot;&gt;turtle8760.tistory.com&lt;/p&gt;
  &lt;/div&gt;&lt;/a&gt;
&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br&gt;Spring 수업을 마지막으로 국비 수업을 수료하게 되었다. 코로나로 인해 10% 오프라인 90% 온라인으로 진행되어 학원 동기들과 많이 친해지지 못했고 아쉬운 마음이 정말 컸다. 열심히 했지만 더 열심히 할걸 추가적으로 더 만들어 볼걸 이란 아쉬운 마음도 들었다. &lt;br&gt;&lt;br&gt;수많은 국비 학원 비추 후기를 보며 못 따라가면 어떡하지 걱정했는데 다행히 강사님이 설명을 너무 잘해주셨다. 역시 내 선택이 옳았음을.. 이길로 안내해주신 멘토님과 가르쳐주신 강사님께 정말 정말 감사했다. 물론 국비 학원의 단점도 많다. 비전공자에서 네 카라 쿠 배 리드 개발자가 되신 분들의 스토리를 찾아보면 알 수 있을 것이다.. &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;br&gt;이제 막 취업 시장에 뛰어들었는데 이제 시작이구나.. 학원이 시작이 아니었구나 깨달았다. 취업하면 또 이제 시작이구나 하겠지..? ^^.. 돌봐주던 어미새가 아기새에게 난 할 도리를 했으니 떠나거라 하는 것처럼 내던져진 기분이 든다. &lt;br&gt;두렵고 할 수 있을까 벌써 한 숨이 절로 나오지만 그래도 도전해보려 한다. 열심히 해서 안 되는 것은 없다고 한다. 사람마다 꽃이 피는 날이 다른 것처럼 나 또한 1000번 넘어져도 다시 일어나서 또 달리면 되는 게 아닌가 싶다.&lt;/p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;275&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ItRRq/btrFomXYkCo/v27rMKw6JeY5yyBKJrNFa0/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ItRRq/btrFomXYkCo/v27rMKw6JeY5yyBKJrNFa0/img.jpg&quot; data-alt=&quot; 자 시작이야 내꿈을~~ 이노래가 생각나네요 ^.^ &quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ItRRq/btrFomXYkCo/v27rMKw6JeY5yyBKJrNFa0/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FItRRq%2FbtrFomXYkCo%2Fv27rMKw6JeY5yyBKJrNFa0%2Fimg.jpg&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;275&quot; data-origin-width=&quot;400&quot; data-origin-height=&quot;275&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt; 자 시작이야 내꿈을~~ 이노래가 생각나네요 ^.^ &lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;비전공자였는데 개발자로 성공한 사례를 많이 봤다. 그러나 모두 다 쉽지 않았다. 다들 간절했고 어려운 길을 밟아왔고 고난 끝에 정상에 있는 게 아닌가 생각이 든다. 마인드 또한 멋지다. 혼자만 가는 것이 아니라 뒤돌아 이쪽이 지름길이라고 손을 내밀어 주신다. 이런 선배님들을 보며 나도 이런 개발자 선배가 돼야지 다짐하고 나도 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;함께 성장하고 개발하여 세상에 올바른 가치를 전해주는 개발자가 되고 싶다고 생각했다. &lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;hr data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 아주 긴 이야기였는데 읽어주신 모든 분들께 감사하다고 전하고 싶다. 이제 취업 준비를 시작하지만 마음 단단히 먹고 임해보려 한다. 다음엔 꼭 취업에 성공한 스토리로 글을 쓸 것이다. &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;This is not rocket science!&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt; 비전공자에서 개발자로 전향하신 개발자님께서 해주신 말인데 &quot;어려운 일이 아니야!&quot;라는 뜻이라고 한다. 힘들 때마다 이 말을 외쳐본다. 로켓과학도 아닌데 한번 도전해보자! 아자! &lt;/span&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;br&gt;&lt;/p&gt;</description>
      <category>회고록</category>
      <author>윤도ri</author>
      <guid isPermaLink="true">https://turtle8760.tistory.com/97</guid>
      <comments>https://turtle8760.tistory.com/97#entry97comment</comments>
      <pubDate>Wed, 22 Jun 2022 01:09:29 +0900</pubDate>
    </item>
    <item>
      <title>[백준] 14502번 -연구소(JAVA)</title>
      <link>https://turtle8760.tistory.com/96</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;연구소1.png&quot; data-origin-width=&quot;1311&quot; data-origin-height=&quot;754&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ciKaiB/btrEX1rhUnT/ktTYb2jj4rw0a8RX4hMwbk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ciKaiB/btrEX1rhUnT/ktTYb2jj4rw0a8RX4hMwbk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ciKaiB/btrEX1rhUnT/ktTYb2jj4rw0a8RX4hMwbk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FciKaiB%2FbtrEX1rhUnT%2FktTYb2jj4rw0a8RX4hMwbk%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;1311&quot; height=&quot;754&quot; data-filename=&quot;연구소1.png&quot; data-origin-width=&quot;1311&quot; data-origin-height=&quot;754&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;연구소2.png&quot; data-origin-width=&quot;1249&quot; data-origin-height=&quot;801&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LIP96/btrESP7D18W/7vAJd5j5Wlx3OYWLBxR9kk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LIP96/btrESP7D18W/7vAJd5j5Wlx3OYWLBxR9kk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LIP96/btrESP7D18W/7vAJd5j5Wlx3OYWLBxR9kk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLIP96%2FbtrESP7D18W%2F7vAJd5j5Wlx3OYWLBxR9kk%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;1249&quot; height=&quot;801&quot; data-filename=&quot;연구소2.png&quot; data-origin-width=&quot;1249&quot; data-origin-height=&quot;801&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;연구소3.png&quot; data-origin-width=&quot;1227&quot; data-origin-height=&quot;585&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RYaG3/btrEXPEEkzz/FEGs6QKRQS5WsVKFFmgm50/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RYaG3/btrEXPEEkzz/FEGs6QKRQS5WsVKFFmgm50/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RYaG3/btrEXPEEkzz/FEGs6QKRQS5WsVKFFmgm50/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRYaG3%2FbtrEXPEEkzz%2FFEGs6QKRQS5WsVKFFmgm50%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;1227&quot; height=&quot;585&quot; data-filename=&quot;연구소3.png&quot; data-origin-width=&quot;1227&quot; data-origin-height=&quot;585&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;정리1.png&quot; data-origin-width=&quot;1300&quot; data-origin-height=&quot;726&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b8Ebaa/btrEYHtj34K/gKEKdI3VzLj1aT5cJFNm60/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b8Ebaa/btrEYHtj34K/gKEKdI3VzLj1aT5cJFNm60/img.png&quot; data-alt=&quot;문제를 간단히 정리했다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b8Ebaa/btrEYHtj34K/gKEKdI3VzLj1aT5cJFNm60/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb8Ebaa%2FbtrEYHtj34K%2FgKEKdI3VzLj1aT5cJFNm60%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;1300&quot; height=&quot;726&quot; data-filename=&quot;정리1.png&quot; data-origin-width=&quot;1300&quot; data-origin-height=&quot;726&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;문제를 간단히 정리했다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;정리2.png&quot; data-origin-width=&quot;1296&quot; data-origin-height=&quot;717&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wtGlI/btrEX85JnXy/7NuBx8In4QSeAPIMAXuFOK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wtGlI/btrEX85JnXy/7NuBx8In4QSeAPIMAXuFOK/img.png&quot; data-alt=&quot;벽 3개 세우고 바이러스 퍼뜨려서 0의 최대 갯수를 구하라!&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wtGlI/btrEX85JnXy/7NuBx8In4QSeAPIMAXuFOK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwtGlI%2FbtrEX85JnXy%2F7NuBx8In4QSeAPIMAXuFOK%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;1296&quot; height=&quot;717&quot; data-filename=&quot;정리2.png&quot; data-origin-width=&quot;1296&quot; data-origin-height=&quot;717&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;벽 3개 세우고 바이러스 퍼뜨려서 0의 최대 갯수를 구하라!&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;정리3.png&quot; data-origin-width=&quot;1278&quot; data-origin-height=&quot;712&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/usbEh/btrEXWqXN2l/f0hMd55tf8OjlOs6KKfE40/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/usbEh/btrEXWqXN2l/f0hMd55tf8OjlOs6KKfE40/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/usbEh/btrEXWqXN2l/f0hMd55tf8OjlOs6KKfE40/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FusbEh%2FbtrEXWqXN2l%2Ff0hMd55tf8OjlOs6KKfE40%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;1278&quot; height=&quot;712&quot; data-filename=&quot;정리3.png&quot; data-origin-width=&quot;1278&quot; data-origin-height=&quot;712&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;정리4.png&quot; data-origin-width=&quot;1297&quot; data-origin-height=&quot;709&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/DRrq4/btrEX7TiwhY/7DSA7VPs5rLM8orMgkvTk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/DRrq4/btrEX7TiwhY/7DSA7VPs5rLM8orMgkvTk0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/DRrq4/btrEX7TiwhY/7DSA7VPs5rLM8orMgkvTk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDRrq4%2FbtrEX7TiwhY%2F7DSA7VPs5rLM8orMgkvTk0%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;1297&quot; height=&quot;709&quot; data-filename=&quot;정리4.png&quot; data-origin-width=&quot;1297&quot; data-origin-height=&quot;709&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;정리5.png&quot; data-origin-width=&quot;1267&quot; data-origin-height=&quot;682&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cRzHyQ/btrEXGIIPmc/clL2Ug6Ohb1LxoqHpzCcN1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cRzHyQ/btrEXGIIPmc/clL2Ug6Ohb1LxoqHpzCcN1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cRzHyQ/btrEXGIIPmc/clL2Ug6Ohb1LxoqHpzCcN1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcRzHyQ%2FbtrEXGIIPmc%2FclL2Ug6Ohb1LxoqHpzCcN1%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;1267&quot; height=&quot;682&quot; data-filename=&quot;정리5.png&quot; data-origin-width=&quot;1267&quot; data-origin-height=&quot;682&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;정리6.png&quot; data-origin-width=&quot;1318&quot; data-origin-height=&quot;715&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/beJrx5/btrEWoBP7F5/j8v4LXP2lyreaArTZaUxjK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/beJrx5/btrEWoBP7F5/j8v4LXP2lyreaArTZaUxjK/img.png&quot; data-alt=&quot;1. 오,왼,상,하로 움직일 수 있으므로 방향값을 저장해놓고 사용하면 된다.&amp;amp;amp;nbsp; 2. q에 2라는 값을 담아두고 그 주변 4방향으로 퍼뜨려나간다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/beJrx5/btrEWoBP7F5/j8v4LXP2lyreaArTZaUxjK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbeJrx5%2FbtrEWoBP7F5%2Fj8v4LXP2lyreaArTZaUxjK%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;1318&quot; height=&quot;715&quot; data-filename=&quot;정리6.png&quot; data-origin-width=&quot;1318&quot; data-origin-height=&quot;715&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;1. 오,왼,상,하로 움직일 수 있으므로 방향값을 저장해놓고 사용하면 된다.&amp;amp;nbsp; 2. q에 2라는 값을 담아두고 그 주변 4방향으로 퍼뜨려나간다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;정리7.png&quot; data-origin-width=&quot;1315&quot; data-origin-height=&quot;711&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cpHPzt/btrEWqsVV01/m3x84TLTemHzwZlARGZSn0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cpHPzt/btrEWqsVV01/m3x84TLTemHzwZlARGZSn0/img.png&quot; data-alt=&quot;조건에 맞으면 q에 넣기! 퍼지고 있구나~&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cpHPzt/btrEWqsVV01/m3x84TLTemHzwZlARGZSn0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcpHPzt%2FbtrEWqsVV01%2Fm3x84TLTemHzwZlARGZSn0%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;1315&quot; height=&quot;711&quot; data-filename=&quot;정리7.png&quot; data-origin-width=&quot;1315&quot; data-origin-height=&quot;711&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;조건에 맞으면 q에 넣기! 퍼지고 있구나~&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;정리8.png&quot; data-origin-width=&quot;1309&quot; data-origin-height=&quot;739&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/YB8jO/btrET8y9mz3/oxNhjHeuTQtOWTlKJ7PqS0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/YB8jO/btrET8y9mz3/oxNhjHeuTQtOWTlKJ7PqS0/img.png&quot; data-alt=&quot;안전영역(0)의 갯수를 구해야하므로&amp;amp;amp;nbsp; 0이면서 바이러스가 퍼뜨려지지 않은 영역(visited=false) 인 부분인 경우 count 를 올려준다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/YB8jO/btrET8y9mz3/oxNhjHeuTQtOWTlKJ7PqS0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FYB8jO%2FbtrET8y9mz3%2FoxNhjHeuTQtOWTlKJ7PqS0%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;1309&quot; height=&quot;739&quot; data-filename=&quot;정리8.png&quot; data-origin-width=&quot;1309&quot; data-origin-height=&quot;739&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;안전영역(0)의 갯수를 구해야하므로&amp;amp;nbsp; 0이면서 바이러스가 퍼뜨려지지 않은 영역(visited=false) 인 부분인 경우 count 를 올려준다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;| 입출력&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BufferedReader 로 입력을 받고 System.out.println 으로 출력했다.&lt;/p&gt;
&lt;pre id=&quot;code_1655371048714&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.io.*;
import java.util.LinkedList;
import java.util.Queue;
import java.util.StringTokenizer;

public class Lab_14502 {
    //1.벽을 3개 세운다. 
	//2.바이러스를 퍼뜨린다. 
	//3.최대 안전영역(0의갯수)를 구한다
	// --&amp;gt; 이 값을 max 값과 계속 비교하면서 최대값을 구한다. 
	
	public static int X; // X= M 
	public static int Y; // Y= N 
	public static int map[][];
	public static int max = 0;
	
	
	public static void main(String[] args) throws IOException{
    BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    StringTokenizer st = new StringTokenizer(br.readLine());
	
    Y = Integer.parseInt(st.nextToken());
    X = Integer.parseInt(st.nextToken());
    map = new int[X][Y];
    //0. map 을 (x,y)상태로 보기 위해서 X,Y 로 받아준다.
    
    //0.1 맨 윗줄이 y값이 Y-1 좌표부터 시작하므로 (높은것부터 점점 낮아져야 한다)
    for (int y = Y-1; y &amp;gt;=0; y--) {
    //0.2 왼쪽부터 x값을 받으니까 0부터 시작한다. 
    	st = new StringTokenizer(br.readLine());
		for (int x = 0; x &amp;lt; X; x++) {
			map[x][y]= Integer.parseInt(st.nextToken());
		} 
	}
    recursive(0);
    System.out.println(max);
	
	}
	//1. 벽을 3개 세운다 = 완전탐색 재귀 사용 
	
	public static void recursive(int index) {	
		if(index ==3) {
			//1.2 바이러스를 퍼뜨려 본다. == bfs 를 사용하라.  
			//1.3 남아있는 0의 갯수를 샌다. 
			int countOf0 = bfs();
			//1.4 남아있는 0의 갯수의 최댓값을 계속 갱신한다. 
			max = Math.max(max, countOf0);
			return;
		}
	//1.1 벽 3개를 만들어주고  위 if문에서 max값을 구한 다음 벽 부수고  새로운 경우의 수를 계속 탐색한다. 
		for (int i = 0; i &amp;lt; X; i++) {
			for (int j = 0; j &amp;lt; Y; j++) {
				if(map[i][j]==0) {
					map[i][j] = 1; //벽 만들기
					recursive(index+1);
					map[i][j] = 0; //벽 부수기 
					
				}
			}
		}
	}
	//2차원 에서 BFS 활용하기 위해 현재 좌표 기록하기. 
	public static int dx[] = new int[] {0,0,1,-1}; //상 하 오 왼
	public static int dy[] = new int[] {1,-1,0,0}; //상 하 오 왼 
	
	//2. 바이러스 퍼뜨리기
	public static int bfs() {
		
		Queue&amp;lt;int[]&amp;gt; q = new LinkedList&amp;lt;int[]&amp;gt;();
		
		boolean[][] visited = new boolean[X][Y];
		
		//2.1 바이러스가 2부터 뻗어나가므로 2를 q 에 넣어준다.
		for (int i = 0; i &amp;lt; X; i++) {
			for (int j = 0; j &amp;lt; Y; j++) {
				if(map[i][j]==2) {
					q.add(new int[] {i,j});
		//2.2  2를 들렸음을 check 해준다. 
					visited[i][j]= true;
				}
			}
		}
		//2.3  바이러스를 다 꺼내올때까지 반복한다. 
		while(!q.isEmpty()) {
			//q.poll -&amp;gt; 가장 먼저 보관한 값을 꺼내고 반환한다. 
			int list[] = q.poll(); 
			//2.4 현재 위치 등록 (curx = current x) 
			int curx = list[0];
			int cury = list[1];
			
			//2.5 다음위치로 퍼지는데 4방향이 가능하므로 4공간까지 반복문 돌린다.
			for (int i = 0; i &amp;lt; 4; i++) {
			//2.6 위치를 이동해준다. 
				int nx = curx + dx[i];
				int ny = cury + dy[i];
				//2.7
				//(1)현재 위치는 map 의 크기안에 들어가야 함 0 &amp;lt;= nx &amp;lt; X 
				                             //0 &amp;lt;= ny &amp;lt; Y
				//(2)방문했던 q는 제외해주어야 한다. --&amp;gt; visited = false
				//(3)벽(1)이 있는 공간도 제외해야 한다. --&amp;gt; map == 0
				// ** 이 조건에 충족하는 경우 바이러스가 퍼질 수 있다!
				
				if(0&amp;lt;=nx &amp;amp;&amp;amp; nx&amp;lt; X &amp;amp;&amp;amp; ny&amp;gt;=0 &amp;amp;&amp;amp; ny &amp;lt; Y &amp;amp;&amp;amp;
						visited[nx][ny]==false &amp;amp;&amp;amp; map[nx][ny]==0) {
					visited[nx][ny] = true; 
				//2.8 q에 넣었으므로 퍼진다. 
					q.add(new int[] {nx,ny}); 
					
				}
			}
		}
		//3.안전 영역의 갯수 구하기 
		int count = 0;
		for (int i = 0; i &amp;lt; X; i++) {
			for (int j = 0; j &amp;lt; Y; j++) {
				//3.1 0 이면서 바이러스가 들리지 않은 곳 = 안전영역
				if(map[i][j]==0 &amp;amp;&amp;amp; visited[i][j]==false) {
					count++;
				}
			}
		}
		return count;
	}
    
}&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; N과 M 을 받았는데 X와 Y는 무엇일까? 그리고 왜 Y부터 받는거지? 라고 충분히 생각할 수 있을 것 같다.&amp;nbsp; 이건 문제를 헷갈리지 않게 풀기위해 X와 Y로 잡은 것이다. Map 의 경우 보통 위치를 (x,y) 로 나타내므로 X와 Y로 나타내고, 두번째로&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Y부터 받는 이유는 문제에서 N 은 곧 Y값이기 때문이다.&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; 또한 map 에 값을 담을때도 순서대로 탐색하면 X는 순서대로 증가하므로 x++,&amp;nbsp; Y는 가장 큰 수에서 -1 만큼 줄어들므로 y--&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;풀어본 사람들이 BFS 만 잘 이해하고 있으면 어렵지 않은 문제라고 한다. 나는 아직 부족한가보다 ^^,,, 언제나 질문은 환영하니 궁금한게 있으면 댓글 달아주세요 ^^!&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>알고리즘 &amp;amp; 자료구조/그래프</category>
      <author>윤도ri</author>
      <guid isPermaLink="true">https://turtle8760.tistory.com/96</guid>
      <comments>https://turtle8760.tistory.com/96#entry96comment</comments>
      <pubDate>Thu, 16 Jun 2022 18:28:12 +0900</pubDate>
    </item>
    <item>
      <title>[백준] 11728번 -배열 합치기(JAVA)</title>
      <link>https://turtle8760.tistory.com/95</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;배열.jpg.png&quot; data-origin-width=&quot;964&quot; data-origin-height=&quot;790&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cxRjdW/btrEnMh4eyA/ZBO6bzoMhGLOzjMw0JbIl0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cxRjdW/btrEnMh4eyA/ZBO6bzoMhGLOzjMw0JbIl0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cxRjdW/btrEnMh4eyA/ZBO6bzoMhGLOzjMw0JbIl0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcxRjdW%2FbtrEnMh4eyA%2FZBO6bzoMhGLOzjMw0JbIl0%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;964&quot; height=&quot;790&quot; data-filename=&quot;배열.jpg.png&quot; data-origin-width=&quot;964&quot; data-origin-height=&quot;790&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;| 접근 방법&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;말 그대로 두개의 배열을 입력받아 정렬하여 결과를 출력하면 된다. 이 때 정렬하는 방법은 두가지가 있다.&amp;nbsp;첫번째는 Arrays.sort 메소드를 사용하고 두번째는 두포인터를 사용하는 것이다. 두가지 다 다뤄보겠다.&amp;nbsp;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;| 입출력&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;BufferedReader 를 사용하여 입력값을 받고 System.out.print 를 사용하여 출력했다.&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;| 1.Arrays.sort 사용하기&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1654766694688&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.*;
import java.io.*;


public class CombineArray_11728 {
	
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer st = new StringTokenizer(br.readLine());
		
		int n = Integer.parseInt(st.nextToken());  //첫번째 배열 길이
		int m = Integer.parseInt(st.nextToken());  //두번째 배열 길이 		
		int [] arr = new int[n+m];  //정렬할 배열 초기화 
		
		st = new StringTokenizer(br.readLine());  //첫번째 배열 
		
		for (int i = 0; i &amp;lt; n; i++) { 
			arr[i]= Integer.parseInt(st.nextToken());
		}
		st = new StringTokenizer(br.readLine()); //두번째 배열 
		
		for (int i = 0; i &amp;lt; m; i++) {
			arr[i+n] = Integer.parseInt(st.nextToken()); 
		}
		Arrays.sort(arr); //정렬 
		
		StringBuilder sb = new StringBuilder();
		
		for(int r : arr) {
			sb.append(r+&quot; &quot;); 
					
		}
		System.out.println(sb);

	}

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;| 2.두 포인터 사용하기&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 두개의 배열에 있는 값들을 비교하면서 작은 값들을 먼저 가져오고 포인터를 이동하는 식으로 구현하면 된다.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;array1.png&quot; data-origin-width=&quot;894&quot; data-origin-height=&quot;579&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ry2uP/btrEoXwrIGP/a6YErDKJgzFnwVf9vVKHv1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ry2uP/btrEoXwrIGP/a6YErDKJgzFnwVf9vVKHv1/img.png&quot; data-alt=&quot;포인터는 0부터 시작하여 두개의 배열을 비교한다.&amp;amp;amp;nbsp;이 경우 1이 작으므로 1 을 넣고 포인터를 옮겨준다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ry2uP/btrEoXwrIGP/a6YErDKJgzFnwVf9vVKHv1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRy2uP%2FbtrEoXwrIGP%2Fa6YErDKJgzFnwVf9vVKHv1%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;533&quot; height=&quot;345&quot; data-filename=&quot;array1.png&quot; data-origin-width=&quot;894&quot; data-origin-height=&quot;579&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;포인터는 0부터 시작하여 두개의 배열을 비교한다.&amp;amp;nbsp;이 경우 1이 작으므로 1 을 넣고 포인터를 옮겨준다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;array2.png&quot; data-origin-width=&quot;898&quot; data-origin-height=&quot;568&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zVVaY/btrEoW5oc6I/k4Umk9fZxIaYQ7mT9AjUjk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zVVaY/btrEoW5oc6I/k4Umk9fZxIaYQ7mT9AjUjk/img.png&quot; data-alt=&quot;2 &amp;amp;lt; 4 이므로 2를 넣고 a 의 포인터를 옮겨준다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zVVaY/btrEoW5oc6I/k4Umk9fZxIaYQ7mT9AjUjk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzVVaY%2FbtrEoW5oc6I%2Fk4Umk9fZxIaYQ7mT9AjUjk%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;591&quot; height=&quot;374&quot; data-filename=&quot;array2.png&quot; data-origin-width=&quot;898&quot; data-origin-height=&quot;568&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;2 &amp;lt; 4 이므로 2를 넣고 a 의 포인터를 옮겨준다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;array3.png&quot; data-origin-width=&quot;955&quot; data-origin-height=&quot;607&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cgTUwS/btrEnuoI2OK/38rdTSrg9jj91JBkL2mu9k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cgTUwS/btrEnuoI2OK/38rdTSrg9jj91JBkL2mu9k/img.png&quot; data-alt=&quot;이번에도 3 &amp;amp;lt; 4 이므로 3을 넣고 a의 포인터를 옮겨준다&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cgTUwS/btrEnuoI2OK/38rdTSrg9jj91JBkL2mu9k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcgTUwS%2FbtrEnuoI2OK%2F38rdTSrg9jj91JBkL2mu9k%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;593&quot; height=&quot;377&quot; data-filename=&quot;array3.png&quot; data-origin-width=&quot;955&quot; data-origin-height=&quot;607&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이번에도 3 &amp;lt; 4 이므로 3을 넣고 a의 포인터를 옮겨준다&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;array4.png&quot; data-origin-width=&quot;981&quot; data-origin-height=&quot;613&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cUGkoD/btrEpAHL1qT/irsdkh3x7EWmEzcUlZTDE0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cUGkoD/btrEpAHL1qT/irsdkh3x7EWmEzcUlZTDE0/img.png&quot; data-alt=&quot;이때 5 &amp;amp;gt; 4 이므로 4를 넣고 b의 포인터를 늘려준다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cUGkoD/btrEpAHL1qT/irsdkh3x7EWmEzcUlZTDE0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcUGkoD%2FbtrEpAHL1qT%2Firsdkh3x7EWmEzcUlZTDE0%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;602&quot; height=&quot;376&quot; data-filename=&quot;array4.png&quot; data-origin-width=&quot;981&quot; data-origin-height=&quot;613&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이때 5 &amp;gt; 4 이므로 4를 넣고 b의 포인터를 늘려준다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;array5.png&quot; data-origin-width=&quot;1003&quot; data-origin-height=&quot;580&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/420Ei/btrEjUBteKW/dtcTobumV92v58GK0gPFE0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/420Ei/btrEjUBteKW/dtcTobumV92v58GK0gPFE0/img.png&quot; data-alt=&quot;5 &amp;amp;lt; 7 이므로 5를 넣고 a의 포인터를 옮겨준다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/420Ei/btrEjUBteKW/dtcTobumV92v58GK0gPFE0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F420Ei%2FbtrEjUBteKW%2FdtcTobumV92v58GK0gPFE0%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;618&quot; height=&quot;357&quot; data-filename=&quot;array5.png&quot; data-origin-width=&quot;1003&quot; data-origin-height=&quot;580&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;5 &amp;lt; 7 이므로 5를 넣고 a의 포인터를 옮겨준다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;array6.png&quot; data-origin-width=&quot;1059&quot; data-origin-height=&quot;577&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b0Kn1v/btrEnCz2zOV/SoXZPD4hiziw0znzavqSek/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b0Kn1v/btrEnCz2zOV/SoXZPD4hiziw0znzavqSek/img.png&quot; data-alt=&quot;9 &amp;amp;gt; 7 이므로 7을 넣고 b의 포인터를 옮겨주려고 봤더니..?! 더이상 갈곳이 없다..!!&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b0Kn1v/btrEnCz2zOV/SoXZPD4hiziw0znzavqSek/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb0Kn1v%2FbtrEnCz2zOV%2FSoXZPD4hiziw0znzavqSek%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;581&quot; height=&quot;317&quot; data-filename=&quot;array6.png&quot; data-origin-width=&quot;1059&quot; data-origin-height=&quot;577&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;9 &amp;gt; 7 이므로 7을 넣고 b의 포인터를 옮겨주려고 봤더니..?! 더이상 갈곳이 없다..!!&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;array7.png&quot; data-origin-width=&quot;1218&quot; data-origin-height=&quot;630&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/crMzQl/btrEjkNZwQ3/J3PSoTayLWpu4Uksjk5tTk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/crMzQl/btrEjkNZwQ3/J3PSoTayLWpu4Uksjk5tTk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/crMzQl/btrEjkNZwQ3/J3PSoTayLWpu4Uksjk5tTk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcrMzQl%2FbtrEjkNZwQ3%2FJ3PSoTayLWpu4Uksjk5tTk%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;622&quot; height=&quot;322&quot; data-filename=&quot;array7.png&quot; data-origin-width=&quot;1218&quot; data-origin-height=&quot;630&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1654768424128&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;import java.util.*;
import java.io.*;


public class CombineArray_11728 {
	
	public static void main(String[] args) throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		StringBuilder sb = new StringBuilder();
			
		StringTokenizer st = new StringTokenizer(br.readLine());
		int n = Integer.parseInt(st.nextToken());
		int m = Integer.parseInt(st.nextToken());
		
		int [] a = new int[n];
		int [] b = new int[m];
		
		st = new StringTokenizer(br.readLine());
		
		for (int i = 0; i &amp;lt; n; i++) {
			a[i] = Integer.parseInt(st.nextToken());
		}
		
		st = new StringTokenizer(br.readLine());
		
		for (int i = 0; i &amp;lt; m; i++) {
			b[i] = Integer.parseInt(st.nextToken());
		}
		
		int p1 = 0, p2=0;
		
		while(p1&amp;lt;n &amp;amp;&amp;amp; p2&amp;lt;m) {  //두개의 배열 길이만큼만 탐색해야 하므로 
			if(a[p1]&amp;lt;= b[p2]) {
				sb.append(a[p1++]+&quot; &quot;);
			}
			else {
				sb.append(b[p2++]+&quot; &quot;);
			}
		}
		 //두개의 배열 길이가 같지 않은 경우 값을 다 담지 못하는 경우가 발생한다. 
        //그래서 한 배열의 탐색이 완료한 후에는 다른 배열의 남아있는 값도 넣어주어야 한다. 
		if(p1==n) {
			for (int i = p2; i &amp;lt; m; i++) {
				sb.append(b[i]+&quot; &quot;);
			}
		}
		if(p2==m) {
			for (int i = p1; i &amp;lt; n; i++) {
				sb.append(a[i]+&quot; &quot;);
			}
		}
		System.out.println(sb);

	}

}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;| 성능 비교&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;array9.png&quot; data-origin-width=&quot;1171&quot; data-origin-height=&quot;127&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/T7Qlc/btrEn8SZGMj/BMt3KvkqKyKTsKrIGKUGE0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/T7Qlc/btrEn8SZGMj/BMt3KvkqKyKTsKrIGKUGE0/img.png&quot; data-alt=&quot;첫번째가 두포인터를 사용했을때고 두번째 제출이 Arrays.sort 를 사용했을 때이다. 성능 차이가 크게 다르지 않다.&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/T7Qlc/btrEn8SZGMj/BMt3KvkqKyKTsKrIGKUGE0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FT7Qlc%2FbtrEn8SZGMj%2FBMt3KvkqKyKTsKrIGKUGE0%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;1171&quot; height=&quot;127&quot; data-filename=&quot;array9.png&quot; data-origin-width=&quot;1171&quot; data-origin-height=&quot;127&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;첫번째가 두포인터를 사용했을때고 두번째 제출이 Arrays.sort 를 사용했을 때이다. 성능 차이가 크게 다르지 않다.&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>알고리즘 &amp;amp; 자료구조/두포인터</category>
      <author>윤도ri</author>
      <guid isPermaLink="true">https://turtle8760.tistory.com/95</guid>
      <comments>https://turtle8760.tistory.com/95#entry95comment</comments>
      <pubDate>Thu, 9 Jun 2022 19:03:03 +0900</pubDate>
    </item>
  </channel>
</rss>