<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>KoreanPaper</title>
    <link>https://koreanpaper.tistory.com/</link>
    <description></description>
    <language>ko</language>
    <pubDate>Mon, 1 Jun 2026 22:21:48 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>KoreanPaper</managingEditor>
    <image>
      <title>KoreanPaper</title>
      <url>https://tistory1.daumcdn.net/tistory/7023203/attach/40bc5f71bea14549addb171b0a7ce224</url>
      <link>https://koreanpaper.tistory.com</link>
    </image>
    <item>
      <title>객체지향 프로그래밍 기초</title>
      <link>https://koreanpaper.tistory.com/18</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;1. 객체와 클래스 : 사용자 정의 자료형의 이해&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체지향 프로그래밍의 가장 큰 특징 중 하나는&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자가 &lt;b&gt;새로운 자료형&lt;/b&gt;을 직접 정의해서 사용할 수 있다는 점이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리는 int, string 같은 자료형을 사용해 데이터를 저장한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바는 이처럼 내가 원하는 구조를 가진 새로운 자료형도 만들 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 '책'이라는 자료형이 필요하다면 '제목/저자/가격' 과 같은 정보로 묶을 수 있다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;객체(Object)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체는 서로 다른 타입의 데이터를 하나로 묶은 구조이다.(이질적)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, &lt;b&gt;관련된 데이터를 하나의 단위로 관리&lt;/b&gt;하기 위한 개념이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;클래스(Class)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;클래스는 객체를 생성하기 위한 설계도이다.&lt;/p&gt;
&lt;pre id=&quot;code_1778652247085&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class Book{
    public String title;
    public String author;
    public int price;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;'책' 이라는 새로운 자료형을 정의&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;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;1. Book 타입의 변수 b 선언&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Book b;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1110&quot; data-origin-height=&quot;1000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bg6ewN/dJMcad23box/CkYdvwrE3ntkz6tHw5RZC1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bg6ewN/dJMcad23box/CkYdvwrE3ntkz6tHw5RZC1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bg6ewN/dJMcad23box/CkYdvwrE3ntkz6tHw5RZC1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbg6ewN%2FdJMcad23box%2FCkYdvwrE3ntkz6tHw5RZC1%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;65&quot; height=&quot;59&quot; data-origin-width=&quot;1110&quot; data-origin-height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 메모리에 실제 Book 객체 생성&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;new Book();&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1619&quot; data-origin-height=&quot;1000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mYPD4/dJMcagS4LCS/zt991DGlwbaPsmAPePZ7NK/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mYPD4/dJMcagS4LCS/zt991DGlwbaPsmAPePZ7NK/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mYPD4/dJMcagS4LCS/zt991DGlwbaPsmAPePZ7NK/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmYPD4%2FdJMcagS4LCS%2Fzt991DGlwbaPsmAPePZ7NK%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;116&quot; height=&quot;72&quot; data-origin-width=&quot;1619&quot; data-origin-height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 생성된 객체의 주소를 변수 b에 저장&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;b = new Book();&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2846&quot; data-origin-height=&quot;1000&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eljggC/dJMb99TVHmT/nTeFLSE3TwdERvKryKSOdk/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eljggC/dJMb99TVHmT/nTeFLSE3TwdERvKryKSOdk/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eljggC/dJMb99TVHmT/nTeFLSE3TwdERvKryKSOdk/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeljggC%2FdJMb99TVHmT%2FnTeFLSE3TwdERvKryKSOdk%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;251&quot; height=&quot;88&quot; data-origin-width=&quot;2846&quot; data-origin-height=&quot;1000&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 합치면 다음과 같이 표현된다.&lt;/p&gt;
&lt;pre id=&quot;code_1778652447222&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Book b = new Book();&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. 클래스와 배열의 차이 + 객체 배열&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;클래스&lt;/b&gt; : &lt;b&gt;서로 다른 타입의 데이터&lt;/b&gt;를 묶어 관리한다.&lt;/p&gt;
&lt;pre id=&quot;code_1778657648552&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Person {
    String name;
    int age;
}&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;배열&lt;/b&gt; : &lt;b&gt;동일한 타입의 데이터&lt;/b&gt;를 묶어 관리한다.&lt;/p&gt;
&lt;pre id=&quot;code_1778652702123&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int[] a = new int[5]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 자바는 배열도 객체로 취급된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;객체 배열&amp;nbsp;&lt;/b&gt;: 사용자가 만든 자료형을 배열로 생성&lt;/p&gt;
&lt;pre id=&quot;code_1778652740673&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Book[] books = new Book[3];

books[0]=new Book();
books[1]=new Book();
books[2]=new Book();&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2114&quot; data-origin-height=&quot;999&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bGEAlP/dJMcagMktwB/84LBVNpxPlSB9fw94HusB1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bGEAlP/dJMcagMktwB/84LBVNpxPlSB9fw94HusB1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bGEAlP/dJMcagMktwB/84LBVNpxPlSB9fw94HusB1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbGEAlP%2FdJMcagMktwB%2F84LBVNpxPlSB9fw94HusB1%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;496&quot; height=&quot;234&quot; data-origin-width=&quot;2114&quot; data-origin-height=&quot;999&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;3. Method (메서드)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;메서드는 객체의 동작(행위)을 정의하는 기능이다.&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1778652992174&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public int add(int x, int y){
	int z = x+y;
    return z;
}&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;메서드 구성요소&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 접근 제한자 : Public / Private / Protected / default(생략)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* &lt;b&gt;Public으로 선언된 클래스는 반드시 파일이름과 같아야함.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 같은 파일에 여러 클래스를 작성할 경우, public 제거하고 작성 ( 다른 패키지에 접근 제한됨)&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. 반환 타입 (리턴 타입) : int, String, void 등&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;* 반환 값이 없는 경우에는 void 사용 (ex. System.out.println)&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 style=&quot;color: #333333; text-align: start;&quot;&gt;3. 메서드 이름 (매개 변수=파라미터) : &lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;메서드 실행에 필요한 값을 전달 받는다.&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;메서드 Overloading&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;하나의 클래스 안에서 같은 이름의 메서드를 여러 개 정의하는 기법&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1778658144235&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public int add(int a, int b) {
    return a + b;
}

public double add(double a, double b) {
    return a + b;
}&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;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;오버로딩 조건&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;- 메서드 이름이 같아야 함&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;- 매개변수의 타입 또는 개수가 달라야함.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;오버로딩과 바인딩&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;오버로딩은 컴파일 시점에 호출할 메서드가 결정된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이를 '&lt;b&gt;정적 바인딩'&lt;/b&gt;이라고 한다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;4. 클래스 구성 요소&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;클래스는 크게 두 가지 정보로 구성된다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;- 상태 정보 &amp;gt; &lt;b&gt;멤버 변수&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;- 행위 정보 &amp;gt; &lt;b&gt;멤버 메서드&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1778653922350&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class Person{

    public String name;
    public int age;

    public void play(){
        System.out.println(&quot;밥을 먹는다&quot;);
    }
    
    // 생성자 메서드
    public Person(){
    	// 객체를 생성하는 코드
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;5. 생성자 (Constructor)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생성자는 객체를 생성하고 초기화 하는 특별한 메서드이다.&lt;/p&gt;
&lt;pre id=&quot;code_1778658367489&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class Person {

    public Person() {
		// 객체 초기화 코드
    }
}&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;특징&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 클래스 이름과 동일&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 반환 타입 없음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 객체 생성 시 자동 호출&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 객체 초기화 용도로 사용&lt;/p&gt;
&lt;pre id=&quot;code_1778658493922&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Person p = new Person();&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 코드에서 new Person()이 생성자를 호출한다.&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;*실제 메모리 할당은 new가 수행, 생성자는 초기화 담당&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;5. 클래스 종류 (Model)&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;1. Main Class&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;프로그램 실행 시작 지점이 되는 클래스&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1778658560369&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public static void main(String[] args)&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;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;2. DTO / VO&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;데이터를 저장하고 전달하기 위한 객체 = &lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;계층 간 데이터를 전달하기 위한 객체&lt;/span&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1778658597138&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class BookDTO {
    private String title;
    private int price;
}&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;span style=&quot;color: #333333; text-align: start;&quot;&gt;데이터를 하나로 묶어야할 경우 사용 (데이터를 하나로 수집)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;DB에 있는 데이터를 가져와 사용해야하는 경우 사용 &amp;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 style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;b&gt;3. DAO&lt;/b&gt; &lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;데이터베이스 접근 로직을 담당하는 객체&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데이터 저장, 조회, 수정, 삭제 기능 수행 (CRUD)&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: #333333; text-align: start;&quot;&gt;&lt;b&gt;4. Utility Class&lt;/b&gt;&lt;/span&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;ex. 날짜 처리, 문자열 처리, 계산 기능 등 &amp;gt; 객체 생성 없이 사용하는 경우가 많다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;6. This 와 Static&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;This&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;현재 메서드를 호출한 객체 자기 자신을 의미한다.&lt;/p&gt;
&lt;pre id=&quot;code_1778658774174&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public void setName(String name) {
    this.name = name;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ex. 같은 클래스로 생성된 객체 p1,p2,p3 중, 어떤 객체가 호출했는지 알아야 데이터 수정 가능&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;Static&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특징&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 기능만 제공하기 때문에 데이터 사용 안함. &amp;gt; DTO,DAO 사용 안함&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- This 사용 불가 (현재 객체 자체가 없기 때문)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Static 메서드의 경우, 호출되는 다른 메서드들도 static 이어야함 !&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Utility, 공통 상수, 상태 없는 기능에서 사용&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;7. 접근 제한자&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체 간 접근 범위를 제어하기 위한 문법이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;접근 제한자접근 범위&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 57.2093%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 30.814%;&quot;&gt;public&lt;/td&gt;
&lt;td style=&quot;width: 26.2791%;&quot;&gt;모든 클래스 접근 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 30.814%;&quot;&gt;private&lt;/td&gt;
&lt;td style=&quot;width: 26.2791%;&quot;&gt;자기 클래스 내부만 접근 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 30.814%;&quot;&gt;protected&lt;/td&gt;
&lt;td style=&quot;width: 26.2791%;&quot;&gt;상속 관계에서 접근 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style=&quot;width: 30.814%;&quot;&gt;default&lt;/td&gt;
&lt;td style=&quot;width: 26.2791%;&quot;&gt;같은 패키지 내부만 접근 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;8. 정보 은닉&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체 내부 데이터를 외부에서 직접 수정하지 못하도록 숨기는 개념이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;보통 멤버 변수는 private로 선언한다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;9. Private 변수에 접근하기 위한 방법&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. Getter, Setter 메서드 + toString() 메서드 사용&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;Setter : private 상태 변수에 정보 삽입&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Getter : private 상태 변수의 정보를 읽어옴.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;toString() : 객체가 가진 값 전체를 문자열 형태로 읽어옴.(리턴)&lt;/p&gt;
&lt;pre id=&quot;code_1778656121135&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class Person{
    private String name;
    private int age;

    public void setName(String name){
        this.name=name;
    }

    public void setAge(int age){
        this.age=age;
    }

    public String getName(){
        return this.name;
    }

    public int getAge(){
        return this.age;
    }
    
    public String toString(){
    	return name+age;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* Setter 메서드 사용 보다는, Change변수명의 메서드를 직접 생성하여 사용하는 걸 권장 &amp;gt; 상태 변경에 있어 추적이 중요하기 때문&lt;/p&gt;
&lt;pre id=&quot;code_1778656453517&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Person p = new Person();
p.setName(&quot;홍길동&quot;);
p.setAge(50);

String name = p.getName();
int age = p.getAge();

System.out.println(p.toString());&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 생성자 메서드를 이용해 객체 초기화&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1778655949152&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class Person{
    private String name;
    private int age;

    Public Person(){
        this.name=&quot;홍길동&quot;;
        this.age=50;
    }
    
    public String toString(){
    	return name+age;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1778656428801&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Person p = new Person();

System.out.println(p.toString());&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체 생성시 &lt;b&gt;원하는 값&lt;/b&gt;으로 초기화를 원할 경우, 생성자 메서드를 오버로딩해서 초기화&lt;/p&gt;
&lt;pre id=&quot;code_1778656330885&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class Person{
    private String name;
    private int age;

    Public Person(String name, int age){
        this.name=name;
        this.age=age;
    }
    
    public String toString(){
    	return name+age;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1778656515918&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Person p = new Person(&quot;홍길동&quot;,50);

System.out.println(p.toString());&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>공부/Java</category>
      <category>Java</category>
      <category>객체</category>
      <category>객체지향프로그램</category>
      <category>메서드</category>
      <category>접근 제한자</category>
      <category>클래스</category>
      <author>KoreanPaper</author>
      <guid isPermaLink="true">https://koreanpaper.tistory.com/18</guid>
      <comments>https://koreanpaper.tistory.com/18#entry18comment</comments>
      <pubDate>Fri, 15 May 2026 16:24:39 +0900</pubDate>
    </item>
    <item>
      <title>Kafka를 배워보자(2) _ Docker를 활용한 실습 환경 구성 + 기본 개념 실습</title>
      <link>https://koreanpaper.tistory.com/17</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;Kafka는 로컬 환경에 직접 설치하려고 하면 설정이 꽤 복잡하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서, Docker를 사용해 간단한 환경 구성을 통해 실습을 진행하였다. ( Docker 기본 지식 필요 )&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;먼저 docker -v와 docker compose version을 통해 Docker가 설치되어 있는지 확인이 필요하다.(설치 필요)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 지속적인 실습을 위해, OrdStack을 이용해 컨테이너를 종료하지 않고 시작-정지 하는 방식을 사용했다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;실습 환경 구성&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 실습 디렉토리 생성&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;터미널 실행 (디렉토리 생성 위치로 이동 cd)&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;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;mkdir kafka-practice&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;566&quot; data-start=&quot;558&quot; data-ke-size=&quot;size16&quot;&gt;디렉토리 이동&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;bash&quot;&gt;&lt;code&gt;cd kafka-practice&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;620&quot; data-start=&quot;611&quot; data-ke-size=&quot;size16&quot;&gt;현재 위치 확인&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;bash&quot;&gt;&lt;code&gt;pwd&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&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. 실습 디렉토리 내에 docker-compose.yml 생성&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. docker-compose.yml 작성&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1778131726956&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;version: '3'
services:
    zookeeper:
        image: confluentinc/cp-zookeeper:7.5.0
        environment:
            ZOOKEEPER_CLIENT_PORT: 2181
            
    # zookeeper는 kafka 의 관리자 역할을 수행
    # kafka가 zookeeper에게 접속하는 포트 : 2181 (관리자 서버는 2181에서 대기 중)

    kafka:
        image: confluentinc/cp-kafka:7.5.0
        ports:
            - &quot;9092:9092&quot; # 9092 포트에 kafka 서버 연결
        environment:
            KAFKA_BROKER_ID: 1 # 브로커 아이디(kafka 서버 고유 아이디, 여러개 존재시 구분용)
            KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181 # zookeeper 주소(카프카가 주키퍼한테 말함)
            KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://localhost:9092 # 외부에서 접속하는 주소(카프카는 내부 포트로 접속하지만 외부에서는 9092 포트로 접속함)
            KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1 # 토픽 복제 수(단일서버, 브로커 1개)
        depends_on:
            - zookeeper
            # Kafka는 Zookeeper가 먼저 실행된 다음 시작&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;4. Kafka 실행&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;터미널에서 실습 디렉토리로 이동 후 실행&lt;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;ebnf&quot;&gt;&lt;code&gt;docker compose up -d&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;* 실행 상태 확인 : docker ps&lt;/div&gt;
&lt;div&gt;* 종료하기 : docker compose down&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;div&gt;&lt;b&gt;5. Kafka 컨테이너 접속&lt;/b&gt;&lt;/div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;applescript&quot;&gt;&lt;code&gt;docker exec -it kafka bash&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&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;* 나가기 : exit / Ctrl+d&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;기본 개념 실습&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. Topic&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;/p&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;kafka-topics --create \
  --topic test-topic \
  --bootstrap-server localhost:9092 \
  --partitions 1 \
  --replication-factor 1
  
  
  
####
--create --topic 생성할 topic 이름 입력

--bootstrap-server localhost:9092 
어느 카프카 서버에 접속할 것인지 명시 (항상 작성 필요)

--partition 파티션 개수
--replication-factor 복제 개수
####&lt;/code&gt;&lt;/pre&gt;
&lt;/div&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;/p&gt;
&lt;pre id=&quot;code_1778132378025&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Kafka-topics &amp;mdash;bootstrap-server localhost:9092 &amp;mdash;list&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[ 상세 조회 ]&lt;/p&gt;
&lt;pre id=&quot;code_1778132388258&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Kafka-topics &amp;mdash;bootstrap-server localhost:9092 &amp;mdash;describe &amp;mdash;topic test-topic&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;[ 삭제 ]&lt;/p&gt;
&lt;pre id=&quot;code_1778132398174&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Kafka-topics &amp;mdash;bootstrap-server localhost:9092 &amp;mdash;delete &amp;mdash;topic test-topic&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. Producer 실행 (메시지 보내기)&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1778132476041&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kafka-console-producer \
  --topic test-topic \
  --bootstrap-server localhost:9092&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 종료 : ctrl+c&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. Consumer 실행(메시지 읽기)&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;pre id=&quot;code_1778132515425&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;kafka-console-consumer \
  --topic test-topic \
  --from-beginning \
  --bootstrap-server localhost:9092&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;* Earliest : 처음 오프셋 부터 읽음 / Latest : 마지막 오프셋 부터 읽음&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* 디폴트는 Latest = 마지막 다음부터 읽음 &amp;gt; &amp;mdash;from-beginning : earliest 로 지정 필요&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* ctrl+c 로 종료&lt;/p&gt;</description>
      <category>공부/Kafka</category>
      <category>docker</category>
      <category>Kafka</category>
      <category>기본실습</category>
      <category>실습환경세팅</category>
      <author>KoreanPaper</author>
      <guid isPermaLink="true">https://koreanpaper.tistory.com/17</guid>
      <comments>https://koreanpaper.tistory.com/17#entry17comment</comments>
      <pubDate>Thu, 7 May 2026 14:47:58 +0900</pubDate>
    </item>
    <item>
      <title>Kafka를 배워보자(1) _ 기본 개념</title>
      <link>https://koreanpaper.tistory.com/16</link>
      <description>&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span&gt;&lt;span&gt;Apache Kafka란?&lt;/span&gt;&lt;/span&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;'분산 시스템 기반의 이벤트 스트리밍 플랫폼'&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;496&quot; data-start=&quot;412&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;428&quot; data-start=&quot;412&quot;&gt;대용량 이벤트 데이터 처리&lt;/li&gt;
&lt;li data-end=&quot;443&quot; data-start=&quot;429&quot;&gt;실시간 데이터 스트리밍&lt;/li&gt;
&lt;li data-end=&quot;458&quot; data-start=&quot;444&quot;&gt;데이터 파이프라인 구축&lt;/li&gt;
&lt;li data-end=&quot;473&quot; data-start=&quot;459&quot;&gt;시스템 간 데이터 전달&lt;/li&gt;
&lt;li data-end=&quot;496&quot; data-start=&quot;474&quot;&gt;분산 환경에서의 안정적인 메시지 저장&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-end=&quot;609&quot; data-start=&quot;592&quot; data-ke-size=&quot;size20&quot;&gt;메시징 시스템이 필요한 이유&lt;/h4&gt;
&lt;p data-end=&quot;657&quot; data-start=&quot;611&quot; data-ke-size=&quot;size16&quot;&gt;서비스 간 직접 통신을 하게 되면 시스템 간 결합도가 높아진다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-end=&quot;702&quot; data-start=&quot;667&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li data-end=&quot;675&quot; data-start=&quot;667&quot;&gt;주문 서비스&lt;/li&gt;
&lt;li data-end=&quot;684&quot; data-start=&quot;676&quot;&gt;결제 서비스&lt;/li&gt;
&lt;li data-end=&quot;693&quot; data-start=&quot;685&quot;&gt;알림 서비스&lt;/li&gt;
&lt;li data-end=&quot;702&quot; data-start=&quot;694&quot;&gt;배송 서비스&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end=&quot;742&quot; data-start=&quot;704&quot; data-ke-size=&quot;size16&quot;&gt;의 경우들은 서로 직접 연결되면 구조가 복잡해지고 장애 전파 가능성도 커진다.&lt;/p&gt;
&lt;p data-end=&quot;786&quot; data-start=&quot;744&quot; data-ke-size=&quot;size16&quot;&gt;Kafka 같은 메시징 시스템은 &lt;b&gt;중간에서 데이터를 전달하는 역할을 수행&lt;/b&gt;한다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;기본 구조&lt;/h4&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div&gt;
&lt;div id=&quot;code-block-viewer&quot;&gt;
&lt;div&gt;
&lt;pre class=&quot;nginx&quot;&gt;&lt;code&gt;Producer &amp;rarr; Kafka &amp;rarr; Consumer&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-end=&quot;861&quot; data-start=&quot;833&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-end=&quot;861&quot; data-start=&quot;833&quot; data-ke-size=&quot;size16&quot;&gt;Producer : 메시지를 생성하고 보내는 객체&lt;/p&gt;
&lt;p data-end=&quot;861&quot; data-start=&quot;833&quot; data-ke-size=&quot;size16&quot;&gt;Kafka : 메시지를 저장하고 전달하는 중간 플랫폼&lt;/p&gt;
&lt;p data-end=&quot;861&quot; data-start=&quot;833&quot; data-ke-size=&quot;size16&quot;&gt;Consumer : 저장된 메시지를 읽어 처리하는 객체&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-end=&quot;861&quot; data-start=&quot;833&quot; data-ke-size=&quot;size20&quot;&gt;Kafka 구조&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;ChatGPT Image 2026년 5월 7일 오후 01_37_03.png&quot; data-origin-width=&quot;1536&quot; data-origin-height=&quot;1024&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RaaFj/dJMcah5pNQf/BTrY811dRPNGPQtAd4ziO0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RaaFj/dJMcah5pNQf/BTrY811dRPNGPQtAd4ziO0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RaaFj/dJMcah5pNQf/BTrY811dRPNGPQtAd4ziO0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRaaFj%2FdJMcah5pNQf%2FBTrY811dRPNGPQtAd4ziO0%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;1536&quot; height=&quot;1024&quot; data-filename=&quot;ChatGPT Image 2026년 5월 7일 오후 01_37_03.png&quot; data-origin-width=&quot;1536&quot; data-origin-height=&quot;1024&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Broker &lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Kafaka 서버 1대&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 여러개로 구성 가능, 메시지 분산 저장&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 확장성, 장애대응, 고가용성 확도&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;특정 서버가 다운되더라도 복제된 데이터를 통해 서비스를 지속&lt;/b&gt;할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;U&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;Topic&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;- 하니의 DB 테이블이라고 생각할 수 있음.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;Key와 Value 기반 구조&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;U&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;Partition&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 독립적인 로그 파일&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 병렬 처리, 확장성, 고성능 처리 가능&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Offset이 지정 되어 순차 저장&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 같은 Partition 내에서는 순서가 보장됨 ( 다른 Partition에서는 순서 보장 안됨 )&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;* Kafka는 네트워크를 통해 데이터를 전송하기 때문에 직렬화(Serializer)과정이 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;* '객체 &amp;gt; 바이트 배열'로 변환 후 전송됨.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;메시지 순서 보장 방식&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Kafka는 같은 Partition 내에서만 순서를 보장하고, &lt;b&gt;Topic 전체 순서를 보장하지 않는다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, Partition이 여러개라면 Consumer에서 메시지를 읽는 순서가 달라질 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 동일한 Key값을 가진 메시지는 동일한 Partition으로 전송&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. Key값이 없는 경우, 자동으로 Partion 선택&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; - Round Robin 방식 : 메시지를 순차적으로 Partition에 분배 (Kafka 2.4 이전)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp; - Sticky Partitioning 방식 : 하나의 Partition에 배치를 빠르게 채워 전송한 뒤, 다른 Partition으로 이동 (Kafka 2.4 이후)&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Leader 과 Follower&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여러개의 Broker 중, 하나의 서버가 다운될 경우를 대응 &amp;gt; 각 Broker에 복제 데이터를 저장&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;- Leader Partition : 실제 서비스를 담당, Producer와 Consumer는 Leader와 통신&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- Follower Partiton : Leader 데이터를 복제하는 역할 (읽기,쓰기 불가)&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;Leader가 있는 Broker가 다운되면, Follower 중 하나를 새로운 Leader로 승격시킴 &amp;gt; 고가용성&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;( Partiton에는 Leader가 반드시 1개만 존재 )&lt;/p&gt;</description>
      <category>공부/Kafka</category>
      <category>backend</category>
      <category>Kafka</category>
      <category>분산 시스템</category>
      <author>KoreanPaper</author>
      <guid isPermaLink="true">https://koreanpaper.tistory.com/16</guid>
      <comments>https://koreanpaper.tistory.com/16#entry16comment</comments>
      <pubDate>Thu, 7 May 2026 14:06:45 +0900</pubDate>
    </item>
    <item>
      <title>MSA 구조만 나누면 끝일까? DDD와 TDD가 필요한 이유 : 프로젝트 구조 파악하기</title>
      <link>https://koreanpaper.tistory.com/15</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;최근 백엔드 아키텍처를 논할 때 MSA는 빠지지 않는 주제이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 MSA는 단순히 서비스를 쪼개는 것이 아닌 &quot;어떻게 쪼갤 것인가(DDD)&quot;와 &quot;쪼개진 서비스를 어떻게 신뢰할 것인가(TDD)&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;한 번 간단히 알아보자..!&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-path-to-node=&quot;7&quot; data-ke-size=&quot;size20&quot;&gt;1. 설계의 기준 : DDD&lt;/h4&gt;
&lt;p data-path-to-node=&quot;8&quot; data-ke-size=&quot;size16&quot;&gt;MSA를 시작할 때 가장 먼저 &quot;&lt;b&gt;어디를 기준으로 서비스를 나눌 것인가?&lt;/b&gt;&quot;에 대해 고민한다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;8&quot; data-ke-size=&quot;size16&quot;&gt;이때 &lt;b&gt;DDD는 훌륭한 설계 도면&lt;/b&gt;이 된다고 한다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;8&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;8&quot; data-ke-size=&quot;size16&quot;&gt;DDD는 &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;b&gt;Bounded Context : 비즈니스 로직을 분석해 하위 도메인을 나누고, 그 사이에 명확한 경계를 만든다. 이 경계가 MSA 서비스를 나누는 핵심 기준이 된다.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b data-path-to-node=&quot;8,1,1,0,0&quot; data-index-in-node=&quot;0&quot;&gt;장점:&lt;/b&gt;&lt;span&gt; 복잡한 비즈니스 로직을 명확하게 관리할 수 있고, 기획-개발 간 소통 오류가 줄어듦.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b data-path-to-node=&quot;8,1,1,1,0&quot; data-index-in-node=&quot;0&quot;&gt;단점:&lt;/b&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;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;설계한 도메인을 물리적으로 구현하기 = 멀티모듈&lt;br /&gt;&lt;/b&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;앞서 DDD로 나눈 '논리적인 경계'를 실제 코드상에서 '물리적으로 격리'하기 위해&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;멀티 모듈&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;구조를 활용한다.&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot; data-path-to-node=&quot;8&quot;&gt;
&lt;li&gt;&lt;b data-path-to-node=&quot;8,0,0&quot; data-index-in-node=&quot;0&quot;&gt;모듈:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;독립적으로 배포될 수 있는 코드의 최소 단위.&lt;/li&gt;
&lt;li&gt;&lt;b data-path-to-node=&quot;8,1,0&quot; data-index-in-node=&quot;0&quot;&gt;멀티 모듈 구조:&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;하나의 프로젝트를 여러 개의 모듈로 나누어 관리하며, 각 하위 도메인을 별도의 모듈로 작성.&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;장점:&lt;span&gt;&amp;nbsp;&lt;/span&gt;코드 재사용성이 높아지고 독립적인 빌드가 가능해 유연성 향상.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;단점:&lt;span&gt;&amp;nbsp;&lt;/span&gt;설정이 복잡해질 수 있고, 도메인 설계가 잘못될 경우 도메인 간 의존성 때문에 개선이 어려울 수 있음.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2. MSA 란?&lt;/h4&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;DDD라는 도면을 바탕으로 세워진 실제 건물이 바로 MSA !&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;쪼개진 서비스들이 각자 독립적인 DB를 가지고 배포되는 구조를 가진다.&lt;/b&gt;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;장점: 특정 서비스에 트래픽이 몰릴 때 해당 부분만 확장하면 되는 엄청난 유연성을 가진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단점: 서비스가 늘어날수록 서비스 간 호출 관계가 복잡해져, 코드 수정이 다른 서비스에 어떤 영향을 주는지 파악하기 힘들다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. TDD 란?&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;MSA 환경에서 서비스 간의 복잡한 호출 관계를 일일이 손으로 테스트하는 것은 불가능에 가까우므로,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;TDD를 사용해 자동 테스트가 가능하게 한다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;테스트 주도 개발로 &lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;Red - Green - Refactor 사이클을 따른다.&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;740&quot; data-origin-height=&quot;230&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/clJlNt/dJMcajnrIaA/c3Q6B4SakBlXb7QLFfZRy1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/clJlNt/dJMcajnrIaA/c3Q6B4SakBlXb7QLFfZRy1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/clJlNt/dJMcajnrIaA/c3Q6B4SakBlXb7QLFfZRy1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FclJlNt%2FdJMcajnrIaA%2Fc3Q6B4SakBlXb7QLFfZRy1%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;740&quot; height=&quot;230&quot; data-origin-width=&quot;740&quot; data-origin-height=&quot;230&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;안전한 리팩토링 : 기능을 수정해도 기존 테스트 코드가 성공한다면, 안심하고 배포할 수 있다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문서화 역할 : 테스트 코드는 그 자체로 &quot;이 기능은 이렇게 동작해야 한다&quot;는 가장 정확한 명세서가 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;Spring Boot에서는 &lt;b&gt;Junit + Mockito + AssertJ 조합&lt;/b&gt;으로 테스트 환경을 잘 구축할 수 있다.(공부 예정)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;MSA 환경이라면 서비스 간의 통신을 테스트하는 &lt;b&gt;계약 테스트(contract test)&lt;/b&gt;를 알아보려고 한다. (이것 또한 공부 예정)&lt;/span&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;결론&lt;/span&gt;&lt;/h4&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-path-to-node=&quot;20&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;20,0,0&quot;&gt;DDD&lt;/b&gt;로 비즈니스 로직을 분석해서 &lt;b data-index-in-node=&quot;19&quot; data-path-to-node=&quot;20,0,0&quot;&gt;MSA&lt;/b&gt;의 경계를 나눈다.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;20,1,0&quot;&gt;MSA&lt;/b&gt; 구조 위에서 서비스 간의 복잡함을 &lt;b data-index-in-node=&quot;23&quot; data-path-to-node=&quot;20,1,0&quot;&gt;TDD&lt;/b&gt;로 검증하며 개발한다.&lt;/li&gt;
&lt;li&gt;결과적으로 비즈니스 변화에 빠르고 안정적으로 대응하는 &lt;b data-index-in-node=&quot;30&quot; data-path-to-node=&quot;20,2,0&quot;&gt;유연한 시스템&lt;/b&gt;이 완성된다&lt;/li&gt;
&lt;/ol&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;+실제 프로젝트에 어떻게 적용되는지 살펴보자!&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;계층 기준으로 나눈 모듈 구조&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;744&quot; data-origin-height=&quot;358&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dZbLX2/dJMcad1PCM0/ym0qufKAdeq4mLYScU4jx1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dZbLX2/dJMcad1PCM0/ym0qufKAdeq4mLYScU4jx1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dZbLX2/dJMcad1PCM0/ym0qufKAdeq4mLYScU4jx1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdZbLX2%2FdJMcad1PCM0%2Fym0qufKAdeq4mLYScU4jx1%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;800&quot; height=&quot;385&quot; data-origin-width=&quot;744&quot; data-origin-height=&quot;358&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;DDD + TDD 기반의 프로젝트 구조 (스프링 부트 기준)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignLeft&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;712&quot; data-origin-height=&quot;1130&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bVwcEX/dJMcab33K2V/WRvThAgyCpqOBTcKqvCobK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bVwcEX/dJMcab33K2V/WRvThAgyCpqOBTcKqvCobK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bVwcEX/dJMcab33K2V/WRvThAgyCpqOBTcKqvCobK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbVwcEX%2FdJMcab33K2V%2FWRvThAgyCpqOBTcKqvCobK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;400&quot; height=&quot;635&quot; data-origin-width=&quot;712&quot; data-origin-height=&quot;1130&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;+ 위의 내용들을 바탕으로 여러 아카텍처들의 특징을 알아보자!&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock widthContent&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;757&quot; data-origin-height=&quot;273&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/piecY/dJMcaaYopgg/L3EZ7cLUIiN6fynVI7Wqk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/piecY/dJMcaaYopgg/L3EZ7cLUIiN6fynVI7Wqk0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/piecY/dJMcaaYopgg/L3EZ7cLUIiN6fynVI7Wqk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FpiecY%2FdJMcaaYopgg%2FL3EZ7cLUIiN6fynVI7Wqk0%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;757&quot; height=&quot;273&quot; data-origin-width=&quot;757&quot; data-origin-height=&quot;273&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;DDD 단계: Layered이 아닌 Domain-based&amp;nbsp;기준으로 서비스를 바라보기 시작.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;MSA 단계: 쪼개진 도메인을 Multi-module이나 Hexagonal 구조를 활용해 독립적인 서비스로 구축.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;TDD 단계: 헥사고날 아키텍처는 입출력이 분리되어 있어, 외부 환경(DB 등)에 상관없이 핵심 로직만 테스트하기에 최적의 환경을 제공.&lt;/b&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개인 프로젝트나 간단한 프로젝트들 (보통 내가 진행했던) 은 Layered 구조를 많이 사용했다.&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;+ 그렇다면 왜 Domain-based로 넘어가는게 좋을까? (코드 중심 &amp;gt; 비지니스 중심)&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존의 &lt;b&gt;Layered Architecture는 기술적 계층(Controller, Service, Repository)을 기준&lt;/b&gt;으로 코드를 나눈다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 프로젝트 규모가 커지고 MSA를 고려하게 되면 다음과 같은 한계에 부딪히게 된다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;5&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;5&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 무엇을 하는 코드인지 찾기 힘들다 (가독성)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;6&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Layered: 새로운 '주문' 기능을 추가하려면 OrderController, OrderService, OrderRepository를 각각의 패키지에서 찾아야 한다. &amp;gt; &lt;b&gt;기능이 많아질수록 Service 패키지 안에 수십 개의 파일이 쌓여 어떤 코드가 서로 연관되어 있는지 파악하기 어려워진다.&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;Domain-based: Order라는 &lt;b&gt;도메인 폴더 하나에 관련 컨트롤러, 서비스, 엔티티를 모두 모아둔다.&lt;/b&gt; 특정 기능을 수정할 때 해당 폴더 안에서 모든 것을 해결할 수 있어 &lt;b&gt;가독성이 압도적이다.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;7&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 서비스 간 결합도가 너무 높다 (의존성)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;8&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Layered: &lt;b&gt;모든 서비스가 하나의 거대한 Service 계층에 섞여 있다 보니, '회원' 로직이 '주문' 로직을 직접 참조하거나 복잡하게 얽히는 경우가 빈번하다.&lt;/b&gt; 하나를 수정했을 때 어디가 문제될지 무서움이 시작된다..&lt;/li&gt;
&lt;li&gt;Domain-based: 각 도메인이 명확한 경계(Bounded Context)를 가진다. &lt;b&gt;도메인 간의 참조를 엄격히 제한하거나 필요한 경우 인터페이스를 통해 소통하게 함으로써 결합도를 낮출 수 있다.&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;9&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. MSA 전환이 불가능에 가깝다 (확장성)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;10&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Layered: 특정 기능을 별도의 서비스로 분리하고 싶어도, 기술 계층별로 코드가 흩어져 있고 강하게 결합되어 있어 떼어내기가 매우 어렵다.&lt;/li&gt;
&lt;li&gt;Domain-based: 도메인 단위로 이미 응집되어 있기 때문에, 특정 도메인을 그대로 복사해서 새로운 마이크로서비스로 독립시키기가 훨씬 수월하다.&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;마무리하며.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국 우리가 MSA 구조로 넘어가기 위해선 정확한 경계와 테스트가 필요하다.&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;추가로 내가 많이 헷갈렸던 부분은 'Domain-based와 Multi-module은 같은 구조 아니였나?' 이었는데,&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;pre id=&quot;code_1769261138723&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;root-project/
├── build.gradle (전체 설정)
├── settings.gradle (모듈 포함 설정: include 'api', 'domain', 'common' ...)
│
├── app-api/                # [실행 모듈] 외부 요청(Controller) 처리
│   ├── build.gradle        # domain, common 모듈을 의존함
│   └── src/main/java/.../controller/
│
├── core-domain/            # [도메인 모듈] 핵심 비즈니스 로직 및 엔티티
│   ├── build.gradle        # 특정 기술에 종속되지 않도록 설정
│   └── src/main/java/.../domain/ (Order, Member 등)
│
├── core-common/            # [공통 모듈] 유틸리티, 공통 예외 처리 등
│   ├── build.gradle
│   └── src/main/java/.../utils/
│
└── infrastructure/         # [인프라 모듈] DB 설정, 외부 API 통신 등
    ├── build.gradle
    └── src/main/java/.../config/&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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Root Project: 전체 프로젝트의 설정을 관리합니다. 어떤 모듈들이 모여 하나의 시스템을 이루는지 settings.gradle에 정의합니다.&lt;/li&gt;
&lt;li&gt;App 모듈 (API): 사용자의 요청을 받는 접점입니다. 여러 도메인 모듈을 조합하여 실제 서비스를 제공합니다. MSA로 전환할 때 이 모듈 단위로 떼어내게 됩니다.&lt;/li&gt;
&lt;li&gt;Domain 모듈: DDD에서 설계한 바운디드 컨텍스트가 실제로 구현되는 곳입니다. 비즈니스 규칙과 엔티티(Entity)가 위치하며, 외부 환경(DB 등)이 변해도 이 모듈의 로직은 변하지 않는 것이 이상적입니다.&lt;/li&gt;
&lt;li&gt;Common 모듈: 프로젝트 어디서든 공통으로 쓰이는 코드를 모아둡니다. 하지만 이 모듈이 너무 커지면 모듈 간 결합도가 다시 높아질 수 있어 주의가 필요합니다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #1f1f1f; text-align: start;&quot;&gt;의존성 방향(API -&amp;gt; Domain -&amp;gt; DB)&lt;/span&gt;&lt;/li&gt;
&lt;/ul&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;의존성 제어: 예를 들어, domain 모듈은 api 모듈의 존재를 몰라야 합니다. 이렇게 의존성 방향을 한쪽으로만 흐르게 강제할 수 있어 코드가 꼬이는 것을 방지합니다.&lt;/li&gt;
&lt;li&gt;TDD 용이성: 핵심 로직이 담긴 domain 모듈만 따로 떼어내어 가벼운 테스트 환경을 구축할 수 있습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;.. 나중에 좀 더 알아보도록 하자&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;투비컨티뉴~&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;끄읏.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>공부/CS</category>
      <category>CS</category>
      <category>DDD</category>
      <category>MSA</category>
      <category>TDD</category>
      <category>구조</category>
      <category>도메인주도설계</category>
      <category>멀티모듈</category>
      <category>아키텍처</category>
      <author>KoreanPaper</author>
      <guid isPermaLink="true">https://koreanpaper.tistory.com/15</guid>
      <comments>https://koreanpaper.tistory.com/15#entry15comment</comments>
      <pubDate>Sat, 24 Jan 2026 22:43:54 +0900</pubDate>
    </item>
    <item>
      <title>Mac에서 MariaDB 설치 후, DBeaver 연동 중 발생한 오류들</title>
      <link>https://koreanpaper.tistory.com/14</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;과거에 DB를 연결하면서 발생한 오류들의 해결 방법을 기록해 보자..!..&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;1.&amp;nbsp; MariaDB 설치 중 발생한 오류&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;Error: Cannot install mariadb because conflicting formulae are installed. mysql: because mariadb, mysql, and percona install the same binaries&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;gt; Mac에 이미 Mysql이 설치되어 있어, MariaDB와 충돌이 발생한 상황&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;1. mysql을 일시적으로 비활성화 시키기&lt;/p&gt;
&lt;pre id=&quot;code_1769253507418&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;brew unlink mysql
# MairaDB만 완전히 사용할 계획이라면 brew uninstall mysql을 권장&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;2. MariaDB 재설치&lt;/p&gt;
&lt;pre id=&quot;code_1769253526265&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;brew install mariadb&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;3. mysql을 다시 사용할 수 있도록 변경&lt;/p&gt;
&lt;pre id=&quot;code_1769253547843&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;brew link mysql&lt;/code&gt;&lt;/pre&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;2.&amp;nbsp; MariaDB 실행 시, 발생한 오류&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;ERROR 2002 (HY000): Can't connect to local server through socket '/tmp/mysql.sock'&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;gt; MariaDB 서버가 실행 중이지 않거나, 잘못된 소켓을 참조하고 있어 발생&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;1. 재실행&lt;/p&gt;
&lt;pre id=&quot;code_1769253660938&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;brew services restart mariadb&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;gt; 하지만 나는 또 다른 오류 발생 ㅠ..&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;Bootstrap failed: 5: Input/output error Try re-running the command as root for richer errors. Error: Failure while executing; `/bin/launchctl bootstrap gui/501 /Users/Library/LaunchAgents/homebrew.mxcl.mariadb.plist` exited with 5.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;gt; 마리아를 정상적으로 실행 시키지 못했다고 함..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. MariaDB를&amp;nbsp;삭제하고&amp;nbsp;재설치&amp;nbsp;-&amp;gt;&amp;nbsp;위의&amp;nbsp;2가지&amp;nbsp;오류&amp;nbsp;상황을&amp;nbsp;계속&amp;nbsp;반복&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. brew services restart mariadb를 실행시키면 정상적으로 실행되었다고 뜨는데, brew services list을 확인해보니 상태가 stopped로 되는것을 알 수 있었음..!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. Homebrew를 삭제 후, 재설치 &amp;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;재설치를 통해 homebrew가 사용하는 관련 환경 변수들을 새로 설정하고, 문제가 있었던 패키지나 설정 파일을 복구 시킴.&lt;/li&gt;
&lt;li&gt;homebrew, Mariadb, mysql을 모두 삭제 후 재실행 시키니 드디어 Mariadb started 상태로 바뀌었다...ㅎ&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;gt; 하지만 Homebrew 재설치는 최후의 수단 느낌이라..재민이 한테 다시 물어보았다..!&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;Homebrew 재설치라는 강력한 처방을 쓰셨는데, 사실 sudo chown -R $(whoami) /usr/local/var/mysql처럼 권한을 수정하거나 /tmp/mysql.sock.lock 파일을 지우는 가벼운 방법도 있습니다. '최후의 수단으로 Homebrew 재설치를 선택했다'는 뉘앙스를 주면 더 완벽할 것 같습니다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;라고 한다.&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;3. DBeaver과&amp;nbsp;연동&amp;nbsp;시&amp;nbsp;오류&amp;nbsp;발생&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;RSA&amp;nbsp;public&amp;nbsp;key&amp;nbsp;is&amp;nbsp;not&amp;nbsp;available&amp;nbsp;client&amp;nbsp;side&amp;nbsp;(option&amp;nbsp;serverRsaPublicKeyFile&amp;nbsp;not&amp;nbsp;set)&amp;nbsp;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;gt; MariaDB 서버와 인증시, RSA 공개키가 설정되지 않아서 발생&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;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1.&amp;nbsp;Connection&amp;nbsp;settings에서&amp;nbsp;Driver&amp;nbsp;Properties으로&amp;nbsp;들어가기&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. allowPublicKeyRetrieval=true&amp;nbsp;로&amp;nbsp;변경&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. useSSL&amp;nbsp;라는&amp;nbsp;속성&amp;nbsp;추가하고&amp;nbsp;false로&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;+ allowPublicKeyRetrieval=true&amp;nbsp;란?&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;JDBC 설정 옵션으로, 서버에서 클라이언트로 RSA로 암호화 된 공개키를 동적으로 가져오는 것을 허용한다는 뜻이다.&lt;/li&gt;
&lt;li&gt;이를 통해 클라이언트(DBeaver)가 서버에 연결될 수 있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;+ useSSL=false&amp;nbsp;란?&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;DB와의 연결시 SSL을 사용하지 않도록 설정하는 옵션이다.&lt;/li&gt;
&lt;li&gt;SSL은 클라이언트와 서버간의 통신을 암호화하여 데이터 유출을 방지하는 보안 프로토콜이다.&lt;/li&gt;
&lt;li&gt;기본적으로 SSL이 설정된 경우 클라이언트는 SSL을 통해 서버와 통신을 시도하지만, 로컬 환경 또는 개발 환경에서는 SSL이 필요하지 않을 수 있다.&lt;/li&gt;
&lt;li&gt;보안 인증서가 구성되지 않은 MariaDB와 MySQL의 서버와 연결할 때 SSL 인증서를 요청하는 오류가 발생할 수 있는데, 이 설정을 통해 이를 방지할 수 있다.&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;h4 data-ke-size=&quot;size20&quot;&gt;4. 3번째 오류를 해결하니 다른 오류 발생&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;Access denied for user 'root'@'localhost' (using password: YES)&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;gt; 비밀번호가 잘못 입력되었거나, root 계정에 대한 인증 방법이 올바르게 설정되지 않았을 때 발생&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;1. MariaDB 비밀번호 재설정 &amp;gt; 해결 불가&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 검색해 보니, &lt;b&gt;포트의 문제..!&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 해당 포트 번호를 확인해 보니 mysqld가 실행되고 있었음.&lt;/p&gt;
&lt;pre id=&quot;code_1769254434324&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo lsof -i:3306&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;4. stop을 하니, mysql이 실행이 되지 않고 있다함 &amp;gt; ..?&lt;/p&gt;
&lt;pre id=&quot;code_1769254500101&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;brew services stop mysql&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;5. 그래서 걍 완전 종료 시켜벌임..!&lt;/p&gt;
&lt;pre id=&quot;code_1769254541352&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo killall mysqld&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;6. MariaDB를 재실행 시키고, DBeaver에 연동하니 정상적으로 연결이 되었다..휴우~&lt;/p&gt;
&lt;pre id=&quot;code_1769254570265&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;brew services restart mariadb&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;하지만, 뭔가 찝찝해서 원인을 좀 더 찾아보았다..!&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;재민이는&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;MariaDB가 설치될 때 내부 엔진 이름이 mysqld인 경우가 많습니다. 즉, 아까 죽인 프로세스는 '삭제된 MySQL'이 아니라 '정상 설치된 MariaDB'였을 가능성이 큽니다.&lt;br /&gt;&lt;br /&gt;포트 충돌은 보통 3306을 이미 다른 프로세스(이전 설치본 등)가 점유하고 있어서 새로 띄운 MariaDB가 뜨지 못했던 것입니다. killall로 싹 정리한 것이 신의 한 수였습니다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;라고 하는데..그래서 다시 정리하자면..?&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;MariaDB와 MySQL의 데이터베이스 서버가 동시에 실행되어,&lt;br /&gt;동일한 기본 포트(3306)을 사용하려고 했기 때문에 충돌이 일어났나..? &amp;gt;1차 의심&lt;br /&gt;&lt;br /&gt;근데 분명 mysql을 삭제하였는데 왜 이런 오류가 나지..?? &amp;gt; 2차의심&lt;br /&gt;&lt;br /&gt;그래서 터미널로&amp;nbsp;mysql&amp;nbsp;--version을&amp;nbsp;입력해&amp;nbsp;보았더니,&amp;nbsp;&lt;br /&gt;mysql&amp;nbsp;from&amp;nbsp;11.5.2-MariaDB,&amp;nbsp;client&amp;nbsp;15.2&amp;nbsp;for&amp;nbsp;osx10.19&amp;nbsp;(arm64)&amp;nbsp;using&amp;nbsp;&amp;nbsp;EditLine&amp;nbsp;wrapper&amp;nbsp;을&amp;nbsp;볼&amp;nbsp;수&amp;nbsp;있었다.&lt;br /&gt;&lt;br /&gt;알고보니 MariaDB는&amp;nbsp;MySQL과&amp;nbsp;호환되는&amp;nbsp;데이터베이스&amp;nbsp;서버이기&amp;nbsp;때문에,&amp;nbsp;MySQL&amp;nbsp;명령어를&amp;nbsp;입력해도&amp;nbsp;MariaDB가&amp;nbsp;대신&amp;nbsp;실행될&amp;nbsp;수&amp;nbsp;있다고&amp;nbsp;한다.&amp;nbsp;(MariaDB를&amp;nbsp;설치할&amp;nbsp;때&amp;nbsp;mysql&amp;nbsp;명령어도&amp;nbsp;함께&amp;nbsp;설치)&lt;br /&gt;&lt;br /&gt;&lt;b&gt;MariaDB 클라이언트는 MySQL 명령어와 동일한 인터페이스를 제공하기 때문에 mysql --version 명령어가 동작하는 것이였고, &lt;/b&gt;&lt;b&gt;MySQL이 삭제된 상태에서도 MariaDB가 설치되어 있기 때문에 mysql 명령어를 입력하면 MariaDB 클라이언트가 대신 실행되고 있는 것이였다.&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;따라서..&lt;br /&gt;MariaDB 설치 시 MySQL 클라이언트를 별도로 설치할 필요 없이, &lt;b&gt;MariaDB가 이미 MySQL 명령어와 호환되도록 모든 도구를 제공한다는 것을 알게되었다.&lt;br /&gt;&lt;br /&gt;&lt;/b&gt;그래서 결국엔 sudo killall mysqld 해당 방법이 맞았던거 같다...!&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발/문제 해결</category>
      <category>#MariaDB오류</category>
      <category>3306포트</category>
      <category>accessdenied</category>
      <category>dbeaver</category>
      <category>DB연동</category>
      <category>ERROR2002</category>
      <category>Mac</category>
      <category>MySQL충돌</category>
      <category>RSA_public_key</category>
      <category>오류해결</category>
      <author>KoreanPaper</author>
      <guid isPermaLink="true">https://koreanpaper.tistory.com/14</guid>
      <comments>https://koreanpaper.tistory.com/14#entry14comment</comments>
      <pubDate>Sat, 24 Jan 2026 20:56:31 +0900</pubDate>
    </item>
    <item>
      <title>Mac에서 발생한 Git의 13K+ 알림 지옥 : 터미널 명령어 정리+ git init</title>
      <link>https://koreanpaper.tistory.com/13</link>
      <description>&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;맥북으로 VSC에서 개발을 하는 도중, 난 별로 한게 없는데 왜 갈수록 변경 사항이 늘어나는거지? 오류인가? 하며,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대수롭게 여기지 않았던 회피형 인간은 나는 나중에 업보 청산을 하게 되는데..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;어느 순간 Git 알림이 13K+를 넘어가고 있었다.&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;이걸 어떻게 지우지? 하며 모든 변경 사항을 Discard Changes를 해버렸고, &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;왜 이런 일이 생겨버린걸까.. 하며 원인을 찾아보았는데..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자의 홈 디렉토리?( ~, /Users/이름 )에서 git init 명령어가 실행되어 그랬다고 한다.&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;git init 을 실행하면 그 폴더와 그 안의 모든 하위 폴더를 Git의 감시가 시작한다고 하니.. 나의 모든 것이 Git에 올라갔던거다..!....&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;원래는 특정 프로젝트 폴더 안에서 git init를 실행했어야 했는데, 터미널을 켜자마자 바로 입력해서 이런 일이 발생한것 같다.&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;만약 이런 일이 생긴다면 어떻게 해결해야 할까? &amp;gt; 홈 디렉토리에 잘못 생성된 .git 숨김 폴더를 삭제해야 한다.&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;해결 방법&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;1. git이 저장된 상위 디렉터리 찾기&lt;br /&gt;터미널 실행 후,&amp;nbsp;&lt;b&gt;git rev-parse --show-toplevel &lt;/b&gt;&amp;nbsp;입력 &amp;gt; git 경로가 나온다.&lt;br /&gt;&lt;br /&gt;2. cd 를 이용해 git의 상위 디렉터리로 이동&lt;br /&gt;&lt;b&gt;cd 상위_디렉터리_경로&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;3. 이동한 해당 디렉토리에 들어간 파일 목록 확인 해보기 &amp;gt;&amp;nbsp;&lt;b&gt;ls -a&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;4. git 삭제하기 &amp;gt;&amp;nbsp;&lt;b&gt;rm -rf .git&lt;br /&gt;&lt;/b&gt;+ 여기서, &lt;b&gt;rm -rf는 무조건 삭제 명령&lt;/b&gt;이니 현재 위치를 꼭꼭 확인하도록 하자.&lt;br /&gt;&lt;br /&gt;5. git 파일이 삭제 되었는지 확인 &amp;gt;&amp;nbsp;&lt;b&gt;ls -a&lt;/b&gt;&lt;/blockquote&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;추가로 터미널 명령어에 대해 정리해 보자 !&lt;/h4&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;cd 명령어 모음&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;1. 기본 이동&lt;br /&gt;&lt;b&gt;cd [폴더명]&lt;/b&gt; : 현재 위치에 있는 특정 폴더로 들어간다.&lt;br /&gt;&lt;b&gt;cd ..&lt;/b&gt; : 한 단계 위 폴더로 나간다.&lt;br /&gt;&lt;b&gt;cd ../..&lt;/b&gt; : 두 단계 위 폴더로 한꺼번에 나간다.&lt;br /&gt;&lt;br /&gt;2. 경로 바로가기&lt;br /&gt;&lt;b&gt;cd ~&lt;/b&gt; : 어느 위치에 있든 내 컴퓨터의 홈 디렉토리(/Users/사용자이름)로 즉시 이동&lt;br /&gt;&lt;b&gt;cd -&lt;/b&gt; : 바로 직전에 있었던 폴더로 돌아갑니다. (실수로 폴더를 잘못 나왔을 때 유용)&lt;br /&gt;&lt;b&gt;cd /&lt;/b&gt; : 시스템의 최상위 루트(Root) 폴더로 이동합니다.&lt;br /&gt;&lt;br /&gt;3. 한 번에 깊이 들어가기 &lt;b&gt;( Tab 키를 누르면 자동 완성 됨 )&lt;/b&gt;&lt;br /&gt;&lt;b&gt;cd src/components/header&lt;/b&gt; : 하위 폴더 이름을 슬래시(/)로 연결하면 여러 단계를 한 번에 들어갈 수 있다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;+ 가고 싶은 폴더가 너무 깊은 곳에 있어서 경로를 다 치기 귀찮다면?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;gt;&lt;b&gt; 터미널에 cd 를 입력하고(공백 한 칸 포함), Finder에서 해당 폴더를 마우스로 잡아서 터미널 창에 드래그 앤 드롭 해보기.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;15&quot; data-ke-size=&quot;size16&quot;&gt;+ 공백이 있는 폴더명&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;18,0,0&quot;&gt;:&amp;nbsp;&lt;/b&gt; 만약 폴더 이름에 공백이 있다면 cd My\ Project라고 치거나 cd &quot;My Project&quot;처럼 따옴표로 감싸줘야 한다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;15&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;(폴더명에 공백 대신 하이픈-이나 언더바_를 쓰기)&lt;/b&gt;&lt;/p&gt;
&lt;p data-path-to-node=&quot;15&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-path-to-node=&quot;15&quot; data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;ls 명령어 모음&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;1. 기본 보기&lt;br /&gt;&lt;b&gt;ls&lt;/b&gt;: 현재 폴더의 파일과 폴더 이름을 간단히 보여준다.&lt;br /&gt;&lt;b&gt;ls -l:&lt;/b&gt; 상세 정보(권한, 소유자, 파일 크기, 수정 날짜 등)를 포함하여 리스트 형태로 보여준다.&amp;nbsp;&lt;br /&gt;&lt;b&gt;ls -a&lt;/b&gt;: 숨겨진 파일까지 전부 보여준다.&lt;br /&gt;&lt;br /&gt;+ .git 폴더나 .gitignore 파일은 이름 앞에 .이 붙은 숨김 파일이라 -a를 붙여야 확인 가능!&lt;br /&gt;&lt;br /&gt;2. 조합해서 쓰기&lt;br /&gt;&lt;b&gt;ls -la&lt;/b&gt; : 숨김 파일을 포함하여 상세 정보까지 한 번에 보기.&lt;br /&gt;&lt;br /&gt;3. 유용한 추가 옵션&lt;br /&gt;&lt;b&gt;ls -lh&lt;/b&gt;: 파일 크기를 K, M, G 단위로 읽기 편하게(Human-readable) 보여줍니다. (ls -l은 바이트 단위라 읽기 힘들거든요.)&lt;br /&gt;&lt;b&gt;ls -t&lt;/b&gt;: 수정 시간(Time) 순서대로 정렬해서 보여줍니다. (방금 수정한 파일을 찾을 때 좋아요.)&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;+ &lt;b&gt;pwd&lt;/b&gt; : 현재 내 위치 확인&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;+ &lt;b&gt;clear&lt;/b&gt; : 터미널 청소&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;그렇다면, 새로운 프로젝트를 시작할때 git 설정은 어떻게 해야될까?&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;1. &lt;b&gt;새로운 프로젝트를 생성 할 경우&lt;/b&gt;&lt;/p&gt;
&lt;div data-ved=&quot;0CAAQhtANahgKEwi0o5eq1qOSAxUAAAAAHQAAAAAQpQQ&quot; data-hveid=&quot;0&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;# 0. 원하는 위치로 이동 
cd ~/Desktop

# 1. 새 프로젝트 폴더 만들기
mkdir my-new-project

# 2. 만든 폴더 안으로 들어가기
cd my-new-project

# 3. Git 초기화!
git init&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h4 data-path-to-node=&quot;7&quot; data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;h4 data-path-to-node=&quot;7&quot; data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;p data-path-to-node=&quot;8&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;8&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. .gitignore 설정&lt;/b&gt;&lt;/p&gt;
&lt;p data-path-to-node=&quot;8&quot; data-ke-size=&quot;size16&quot;&gt;모든 파일을 전부 기록할 필요가 없으므로, 필요없는 파일을 지정해 주는 기능을 한다.&lt;/p&gt;
&lt;p data-path-to-node=&quot;8&quot; data-ke-size=&quot;size16&quot;&gt;프로젝트 최상위 폴더에 .gitignore 파일을 만들고, Git이 무시해야 할 목록을 적는다.( node_modules, .env, .DS_Store 등)&lt;/p&gt;
&lt;p data-path-to-node=&quot;8&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;직접 쓰기 어렵다면? &amp;gt;&amp;nbsp;&lt;a href=&quot;https://www.toptal.com/developers/gitignore&quot; data-ved=&quot;0CAAQ_4QMahgKEwi0o5eq1qOSAxUAAAAAHQAAAAAQpgQ&quot; data-hveid=&quot;0&quot;&gt;gitignore.io&lt;/a&gt; 참고하기 !&lt;/b&gt;&lt;/p&gt;
&lt;p data-path-to-node=&quot;8&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;8&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. 첫번째 기록 남기기&lt;/b&gt;&lt;/p&gt;
&lt;p data-path-to-node=&quot;11&quot; data-ke-size=&quot;size16&quot;&gt;첫 번째 커밋을 해야 브랜치가 실체화 된다.&lt;/p&gt;
&lt;div data-ved=&quot;0CAAQhtANahgKEwi0o5eq1qOSAxUAAAAAHQAAAAAQpwQ&quot; data-hveid=&quot;0&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;touch README.md                    # 설명 파일 생성
git add README.md                  # 장바구니에 담기
git commit -m &quot;Chore: Initial commit&quot; # 첫 기록 완료!&lt;/code&gt;&lt;/pre&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;4. GitHub에 연결하기&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;미리 만들어둔 GitHub 레포지토리의 링크를 가져와 연결&lt;/p&gt;
&lt;div data-ved=&quot;0CAAQhtANahgKEwi0o5eq1qOSAxUAAAAAHQAAAAAQwgM&quot; data-hveid=&quot;0&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;git remote add origin https://github.com/내아이디/내프로젝트.git&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-path-to-node=&quot;22&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;22&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;5. 첫 Push&lt;/b&gt;&lt;/p&gt;
&lt;p data-path-to-node=&quot;22&quot; data-ke-size=&quot;size16&quot;&gt;로컬에서 만든 내용을 서버로 처음 보내기.&lt;/p&gt;
&lt;div data-ved=&quot;0CAAQhtANahgKEwi0o5eq1qOSAxUAAAAAHQAAAAAQwwM&quot; data-hveid=&quot;0&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt;git push -u origin main	
# 앞으로 git push = git push origin main 이라는 뜻 (다른 브렌치랑 헷갈리지 않게 주의!)&lt;/code&gt;&lt;/pre&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-path-to-node=&quot;9&quot; data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;p data-path-to-node=&quot;10&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;+ GitHub에 있는 코드를 가져올 때 = Clone 하기&lt;/b&gt;&lt;/p&gt;
&lt;p data-path-to-node=&quot;10&quot; data-ke-size=&quot;size16&quot;&gt;이미 GitHub에 올려둔 저장소가 있다면 init을 할 필요가 없다.&lt;/p&gt;
&lt;div data-ved=&quot;0CAAQhtANahgKEwi0o5eq1qOSAxUAAAAAHQAAAAAQjgM&quot; data-hveid=&quot;0&quot;&gt;
&lt;div&gt;
&lt;div&gt;
&lt;pre class=&quot;jboss-cli&quot;&gt;&lt;code&gt;# 1. 코드를 저장할 부모 폴더로 이동
cd ~/Documents/projects

# 2. 주소를 복사해서 클론 (이때 폴더가 자동으로 생성됨)
git clone https://github.com/사용자이름/저장소이름.git

# 3. 생성된 폴더로 이동
cd 저장소이름&lt;/code&gt;&lt;/pre&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;+ 내가 제대로 한게 맞을까? 의문이 들때 필요한 git 명령어&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;git status : 현재 작업 상태를 보여줌. (nothing to commit, working tree clean이 나오면 성공)&lt;/li&gt;
&lt;li&gt;git log : 커밋한 기록들을 보여줌. ( 나갈 때는 q 누르기)&lt;/li&gt;
&lt;li&gt;git remote -v : 현재 내 폴더가 어느 깃허브와 연결되어 있는지 알려줌.&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>개발/문제 해결</category>
      <category>CD</category>
      <category>Git</category>
      <category>git init</category>
      <category>GitHub</category>
      <category>ls</category>
      <category>명령어</category>
      <category>터미널</category>
      <author>KoreanPaper</author>
      <guid isPermaLink="true">https://koreanpaper.tistory.com/13</guid>
      <comments>https://koreanpaper.tistory.com/13#entry13comment</comments>
      <pubDate>Sat, 24 Jan 2026 20:09:59 +0900</pubDate>
    </item>
    <item>
      <title>인턴이 TF팀에서 협업하는 법(1) : Git Branch 전략</title>
      <link>https://koreanpaper.tistory.com/12</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;인턴 활동을 하면서, 여러 TF 팀에 들어가 프로젝트를 진행한 경험이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(TF란 Task Force로, 빠른 과제 해결을 위해 사람을 모아 임시로 만든 팀이라고 한다.)&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;누구나 한눈에 알 수 있는 구조의 Git 브렌치 전략&lt;/b&gt;이 필요했다..!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용했던 Git 전략들을 기록 해 보고자 한닷.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리 팀은 빠른 개발이 필요했기 때문에, 재민이가 말해준 두가지 방법 중 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;GitHub Flow&lt;span&gt; &lt;/span&gt;&lt;/span&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;1. Git Flow (표준 방식)&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;5&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Main (Master): 실제 사용자에게 서비스 중인 '최종' 코드.&lt;/li&gt;
&lt;li&gt;Develop: 다음 버전을 위해 개발 중인 코드들이 모이는 곳.&lt;/li&gt;
&lt;li&gt;Feature: 기능을 개발하는 브랜치. 개발이 끝나면 Develop에 합친다.&lt;/li&gt;
&lt;li&gt;Release: 배포를 준비하는 단계. 버그 수정만 진행한다.&lt;/li&gt;
&lt;li&gt;Hotfix: 서비스 중인 코드(Main)에 급한 버그가 터졌을 때 즉시 수정하는 용도.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. GitHub Flow (단순하고 빠름)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;9&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Main 브랜치 하나만 중심으로 잡는다.&lt;/li&gt;
&lt;li&gt;새로운 기능이 필요하면 브랜치를 만들고, 완료되면 바로 Pull Request (PR)를 보낸다.&lt;/li&gt;
&lt;li&gt;동료의 리뷰를 거쳐 Main에 합쳐지자마자 바로 배포하는 구조.&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;h4 data-ke-size=&quot;size20&quot;&gt;Branch 전략&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;main : 배포 및 기준 브렌치&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;1. 기능 개발 브렌치 생성하기 ( 서버와 클라이언트 구분 )&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;feature/client/기능명&lt;/b&gt; : 프론트엔드 부분에서의 기능 개발 (ex. feature/client/home)&lt;/li&gt;
&lt;li&gt;&lt;b&gt;feature/server/기능명&lt;/b&gt; : 백엔드 부분에서의 기능 개발(ex. feature/server/login)&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 기능 개발이 완료되면 main으로 PR 보내고 병합하기.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;Git 명령어 정리&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1. 새로운 브렌치 생성&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;main 브렌치에서 최신 코드를 가져온 후, 기능 브렌치 만들기&lt;/p&gt;
&lt;pre id=&quot;code_1769240432980&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# main으로 이동
git checkout main

# main의 최신 상태 가져오기
git pull origin main

# 새로운 작업 브렌치 생성 및 이동 (-b : 생성 및 이동을 동시에 진행 )
git checkout -b feature/client/home&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2. 새로운 기능 개발 완료 후, 현재 작업 브랜치에서 실행하기&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1769241254798&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 팀원들의 코드와의 충돌을 방지하기 위해 진행
git pull origin main

# 수정된 파일 목록 확인 (초록색이 저장될 파일들)
git status

# 모든 변경 사항을 저장 대기열에 추가
git add .

# 저장 메시지 작성
git commit -m &quot;유형: 작업 내용 요약(무엇을,왜)&quot;

# 서버로 코드 보내기
git push origin [내 브랜치명]&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;+ 항상 push 하기 전, git pull origin main을 하는 습관 필요!&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;+ 현재 브렌치 상태 확인 명령어 (push 하기 전, 확인해보면 좋음!)&lt;/p&gt;
&lt;pre id=&quot;code_1769241407031&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;# 현재 내가 위치한 브렌치 확인
git branch

# 현재 브렌치, 수정 사항, 커밋할 내용 등 전반적인 상태 알려줌
git status&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;+ 커밋 메시지 유형&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;feat&lt;/b&gt; : 새로운 기능 추가&lt;/li&gt;
&lt;li&gt;&lt;b&gt;fix&lt;/b&gt; : 버그 수정&lt;/li&gt;
&lt;li&gt;&lt;b&gt;design&lt;/b&gt; : 디자인 수정&lt;/li&gt;
&lt;li&gt;&lt;b&gt;refactor&lt;/b&gt; : 기능은 그대로지만, 코드 구조를 개선했을 경우&lt;/li&gt;
&lt;li&gt;&lt;b&gt;docs&lt;/b&gt; : readme.md와 같은 문서 파일 수정&lt;/li&gt;
&lt;li&gt;&lt;b&gt;chore&lt;/b&gt; : 빌드 설정 변경, 패키지 설치 등 코드와 상관 없는 작업&lt;/li&gt;
&lt;li&gt;&lt;b&gt;comment&lt;/b&gt; : 주석을 추가하거나 변경했을 경우&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;3. PR 진행하기 : GitHub에 접속&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;상단에 나타난 &lt;b data-index-in-node=&quot;8&quot; data-path-to-node=&quot;17,0,0&quot;&gt;[Compare &amp;amp; pull request]&lt;/b&gt; 노란색 버튼을 클릭.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;0&quot; data-path-to-node=&quot;17,1,0&quot;&gt;Base:&lt;/b&gt; main &amp;larr; &lt;b data-index-in-node=&quot;13&quot; data-path-to-node=&quot;17,1,0&quot;&gt;Compare:&lt;/b&gt; feature/client/home 상태인지 확인.&lt;/li&gt;
&lt;li&gt;작업 내용을 간단히 적고 Create pull request를 클릭.&lt;/li&gt;
&lt;li&gt;&lt;b data-index-in-node=&quot;9&quot; data-path-to-node=&quot;17,3,0&quot;&gt;Merge pull request &lt;/b&gt;버튼을 눌러 main에 최종 합치기.&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;마무리하며.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;팀원들과 개발을 하다보니, 시작하기 전 main을 업데이트 해주는 습관이 매우 중요하다는 것을 알게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Github Desktop 만 편리하게? 사용하다가 직접 명령어를 입력하며 관리하니 이해도가 한층 깊어졌고, 협업에 대한 자신감이 올라갔던 경험이 되었던거 같다..!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발/문제 해결</category>
      <category>Branch</category>
      <category>Git</category>
      <category>GitHub</category>
      <category>TF</category>
      <category>인턴</category>
      <category>협업</category>
      <author>KoreanPaper</author>
      <guid isPermaLink="true">https://koreanpaper.tistory.com/12</guid>
      <comments>https://koreanpaper.tistory.com/12#entry12comment</comments>
      <pubDate>Sat, 24 Jan 2026 17:33:44 +0900</pubDate>
    </item>
    <item>
      <title>비밀번호 어떤 방식으로 지켜내야 할까? : 개발에 필요한 암호화 전략</title>
      <link>https://koreanpaper.tistory.com/11</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;최근 개인 정보 유출 사고가 빈번해지면서, 많은 보안 이슈들이 문제되고 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 문득 개발 하면서 사용자가 작성한 비밀번호는 어떤 방식으로 암호화가 될까? 라는 생각이 들어, 간단히 알아보게 되었다.&lt;/p&gt;
&lt;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;3단계를 거쳐 암호화&lt;/b&gt;가 된다고 한다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. 해시 함수&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;사용자에게 입력 받은 비밀번호를 완전 다른 문자열(=다이제스트)로 변환 시킨다.&lt;/li&gt;
&lt;li&gt;해시는 데이터를 &lt;b&gt;되돌릴 수 없게 변경하는 단방향 함수&lt;/b&gt; 이므로 원래 비밀번호를 알아내는 것은 어렵다.&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;여기서 &lt;b&gt;단방향 함수의 단점&lt;/b&gt;은?&lt;br /&gt;&lt;br /&gt;&lt;b&gt;1) 레인보우 공격에 당할 수 있음&lt;/b&gt;&lt;br /&gt;- 같은 비밀번호를 사용하는 사람은 동일한 다이제스트를 가짐&lt;br /&gt;- 공격자가 다이제스트를 최대한 확보&lt;br /&gt;- 확보한 다이제스트와 탈취한 다이제스트를 비요해 원본 메시지를 찾아냄&lt;br /&gt;&lt;br /&gt;&lt;b&gt;2) 해시 함수가 너무 빨라, 해커가 초당 수억 번의 대입 공격 (Brute-force)이 가능 &lt;/b&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;+ 그렇다면, 단방향 함수를 어떻게 보완하는가? &amp;gt; 아래 2단계를 추가 진행한다.&lt;/b&gt;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;2. 솔팅(Salting)&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;원본 메시지에 문자열을 추가&lt;/b&gt;하여 다이제스트를 생성한다.&lt;/li&gt;
&lt;li&gt;salt : 다이제시트를 생성할 때 추가되는 바이트 단위의 임의 문자열.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3. 키 스트레칭&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;해싱 과정을 수만 번 반복하여 연산 속도를 의도적으로 늦추는 기법&lt;/li&gt;
&lt;li&gt;&lt;b&gt;생성된 다이제스트를 다시 입력하여 새로운 다이제스트를 다시 생성 &amp;gt; 반복&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;입력한 패스워드를 동일한 횟수만큼 해시해야만, 입력한 패스워드의 일치 여부를 확인할 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;해싱 알고리즘 종류&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc; background-color: #ffffff; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;SHA-1, SHA-256, MD-5, Argon2, scrypt, bcrypt, PBKDF2 등&lt;/li&gt;
&lt;li&gt;암호 보안을 위해 Argon2, bcrypt, scrypt가 권장&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;Adaptive Key Derivation Functions&lt;/span&gt;&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;솔팅과 키 스트레칭을 반복하는 함수&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;연산 난이도를 조절하고, 더 복잡한 암호 키를 만들어 낸다&lt;/li&gt;
&lt;li&gt;&lt;b&gt;일반 적인 해시 함수(MD5, SHA-256 등)는 데이터를 최대한 빨리 처리 &amp;gt; 이 과정을 복잡하고 무겁게 만든 함수&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;PBKDF2 : 솔트를 적용한 후 해시 함수의 반복 횟수를 임의로 선택&lt;/li&gt;
&lt;li&gt;Bcrypt, Argon2 등의 알고리즘이 존재&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;Argon2&lt;/b&gt;&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;CPU 및 메모리의 사용량 조정 가능&lt;/li&gt;
&lt;li&gt;시간 및 메모리 요구 사항을 조정하여, 알고리즘 복잡성 설정 가능&lt;/li&gt;
&lt;li&gt;솔트 사용&lt;/li&gt;
&lt;li&gt;최신 암호화 함수로 가장 강력한 보안성과 유연성 지원&lt;/li&gt;
&lt;li&gt;실행 속도가 느리고 구현이 복잡&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;bcrypt&lt;/b&gt;&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;느린 해시 함수를 사용하여, brute-force 공격에 강함&lt;/li&gt;
&lt;li&gt;보안적으로 검증된 함수이므로, 가장 널리 사용&lt;/li&gt;
&lt;li&gt;솔트 사용, 상대적으로 빠른 실행 속도, 단순한 구현&lt;/li&gt;
&lt;li&gt;강력한 패스워드 다이제스트를 생성하는 시스템을 쉽게 구현하고 싶다면 사용&lt;/li&gt;
&lt;li&gt;GPU를 사용한 공격이 취약&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;scrypt&lt;/b&gt;&lt;br /&gt;
&lt;ul style=&quot;list-style-type: disc; color: #212529; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;대량의 메모리를 요구하여 공격을 어렵게함&lt;/li&gt;
&lt;li&gt;솔트 사용, 느린 해시 함수&lt;br /&gt;(다이제스트를 생성할 때 메모리 오버헤드를 갖도록 설계되어, brute-force 공격을 시도할 때 병렬화 처리가 매우 어려움)&lt;/li&gt;
&lt;li&gt;긴 비밀번호도 저장 가능&lt;/li&gt;
&lt;li&gt;메모리 및 시간 사용량 조정 가능&lt;/li&gt;
&lt;li&gt;실행속도가 느리고 구현이 복잡&lt;/li&gt;
&lt;li&gt;무차별 대입 공격에 대해 최대로 강하지만, Argon2만큼 메모리나 시간을 많이 소모하지는 않음&lt;/li&gt;
&lt;li&gt;구현하려는 시스템이 매우 민감한 정보를 다루고, 보안 시스템을 구현하는 데 많은 비용을 투자할 수 있다면 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #ffffff; color: #212529; text-align: start;&quot;&gt;백엔드 개발 부분에서의 회원가입 / 로그인 로직 흐름&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;회원가입 : 사용자 비밀번호 &amp;gt; Salt 생성 &amp;gt; Bcrypt 해싱 &amp;gt; DB 저장 (Hash+Salt)&lt;/li&gt;
&lt;li&gt;로그인 : 입력 비밀번호 &amp;gt; DB의 Salt와 결합 후 해싱 &amp;gt; DB의 해시값과 비교&lt;/li&gt;
&lt;/ul&gt;
&lt;p style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;+ 검증된 라이브러리 사용 : Spring Security &amp;gt; BCryptPasswordEncoder 사용, Node.js &amp;gt; bcrypt 사용&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;클라이언트와 서버 사이에서의 암호화&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. 사용자가 클라이언트에서 비번 입력&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. &lt;b&gt;비번을 서버로 전송하기 전, HTTPS 암호화 필수 진행 (전송 중 패킷을 가로채는 'MITM' 차단)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3. 전달받은 비번을 해싱 알고리즘을 이용해 솔팅 및 DB에 저장/비교&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;DB가 해킹 당하더라도, 솔팅을 시켰기 때문에 원본 비번 유추가 어렵다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만, &lt;b&gt;솔트와 저장된 암호화 키를 둘다 알게 된다면 해킹이 가능&lt;/b&gt;해 진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보안을 한 층 더 강화할 순 없을까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;재민이한테 또 한번 물어보자.&lt;/p&gt;
&lt;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;b&gt;페퍼(Pepper) 사용 : DB 밖의 비밀 키&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-path-to-node=&quot;5&quot; data-ke-size=&quot;size16&quot;&gt;Salt가 사용자마다 다른 '공개된 양념'이라면, &lt;b&gt;Pepper는 모든 비밀번호에 공통적으로 적용되는 '비밀 양념'이다.&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;6&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;방법: 암호화할 때 Password + Salt + Pepper 조합으로 해싱&lt;/li&gt;
&lt;li&gt;핵심: Salt는 DB에 저장하지만, Pepper는 애플리케이션의 환경 변수나 별도의 보안 서버에 보관&lt;/li&gt;
&lt;li&gt;효과: 해커가 DB를 탈취해도 Pepper를 모르면 암호를 풀 수 없음 &amp;gt; &lt;b&gt;물리적으로 저장소를 분리하는 전략&lt;/b&gt;입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;7&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;하드웨어 보안 모듈 (HSM) 및 KMS 활용&lt;/b&gt;&lt;/p&gt;
&lt;p data-path-to-node=&quot;8&quot; 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-path-to-node=&quot;9&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;AWS KMS / Google Cloud KMS&lt;/b&gt; : 암호화 키를 클라우드 제공업체의 인프라 내부에 저장하고, 키 자체는 절대 밖으로 노출되지 않게 관리한다.&lt;/li&gt;
&lt;li&gt;장점: 키&lt;b&gt;에 접근하는 로그가 모두 남고&lt;/b&gt;, 특정 IP나 권한이 있는 서버에서만 암호화/복호화 요청을 보낼 수 있어 관리 효율성과 보안성이 극대화 된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-path-to-node=&quot;10&quot; data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;2단계 인증 (2FA / MFA) 도입&lt;/b&gt;&lt;/p&gt;
&lt;p data-path-to-node=&quot;11&quot; data-ke-size=&quot;size16&quot;&gt;암호화 알고리즘이 아무리 강력해도, 사용자의 비밀번호 자체가 너무 단순하거나 피싱에 당하면 무용지물이다.&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-path-to-node=&quot;12&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;방법: &lt;b&gt;비밀번호 인증 성공 후, 이메일/SMS 인증번호나 Google Authenticator(OTP) 등을 추가로 요구&lt;/b&gt;한다.&lt;/li&gt;
&lt;li&gt;효과: 암호화 키가 유출되어 비밀번호가 뚫리더라도, &lt;b&gt;물리적인 인증 수단이 없는 해커는 로그인을 할 수 없다.&lt;/b&gt; 최근 테크 기업들이 가장 강조하는 '제로 트러스트(Zero Trust)' 모델의 핵심이다.&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;마무리하며&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 암호화 과정을 알아보니 보안 강도는 '해커를 얼마나 귀찮고 힘들게 만드는가'에 달려 있다는 생각을 하게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무 생각없이 보안 라이브러리에 의존하기보단 직접 과정과 방식을 알아보니 전체적인 보안 로직을 이해하는데 도움이 되었고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;직접 페퍼나 2단계 인증 단계를 도입한 프로젝트를 후기로 가져와야겠다는 목표를 세웠다.&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;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;크리덴셜 스터핑 (Credential Stuffing) :&amp;nbsp;&lt;b&gt;다른 곳에서 유출된 아이디/비번을 대입해 로그인을 시도&lt;/b&gt;하는 방식.&lt;/li&gt;
&lt;li&gt;접근 제어 미흡 :&amp;nbsp;권한이 없는 사용자가 &lt;b&gt;타인의 API 주소를 유추&lt;/b&gt;해 정보를 빼가는 것.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;로그 관리 및 모니터링 부족&lt;/b&gt; :&amp;nbsp;해커가 들어와서 며칠 동안 데이터를 긁어가는데도 시스템이 이를 감지하지 못한 상태.&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;클라우드 설정 오류 : 저장소 권한 설정을 'public'으로 두어 외부 누구나 접근 가능하게 방치&lt;/li&gt;
&lt;li&gt;Access Key 유출 : 깃허브 등에 DB 접속 키나 인증키를 포함해 올려둠&lt;/li&gt;
&lt;li&gt;API 취약점 공격 : 허점이 있는 API를 찾아내, 타인의 정보를 조회하여 무한으로 확보&lt;/li&gt;
&lt;li&gt;공급망 공격 : 협력업체나 외부 솔루션의 취약점을 통해 내부망으로 침투&lt;/li&gt;
&lt;li&gt;내부 직원이 고의로 데이터를 공유&lt;/li&gt;
&lt;li&gt;피싱 : 관리자의 PC를 해킹하여 내부망 접속&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞으로 더욱 주의하며 개발해야겠슨&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;진짜로 끄읏.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>공부/CS</category>
      <category>개인정보</category>
      <category>로그인</category>
      <category>백엔드</category>
      <category>보안</category>
      <category>비밀번호</category>
      <category>암호화</category>
      <category>유출</category>
      <category>해싱</category>
      <category>해킹</category>
      <category>회원가입</category>
      <author>KoreanPaper</author>
      <guid isPermaLink="true">https://koreanpaper.tistory.com/11</guid>
      <comments>https://koreanpaper.tistory.com/11#entry11comment</comments>
      <pubDate>Thu, 22 Jan 2026 17:24:41 +0900</pubDate>
    </item>
    <item>
      <title>기본 문법(4)</title>
      <link>https://koreanpaper.tistory.com/10</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;1000&quot; data-origin-height=&quot;530&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KrczE/dJMcafk4VbC/XA0aEmo9ExKv9i2vUt5L9K/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KrczE/dJMcafk4VbC/XA0aEmo9ExKv9i2vUt5L9K/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KrczE/dJMcafk4VbC/XA0aEmo9ExKv9i2vUt5L9K/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKrczE%2FdJMcafk4VbC%2FXA0aEmo9ExKv9i2vUt5L9K%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;300&quot; height=&quot;159&quot; data-filename=&quot;자바.jpg&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;530&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. 객체 (Object)&lt;/b&gt;&lt;br /&gt;-&amp;nbsp;객체란,&amp;nbsp;서로&amp;nbsp;다른&amp;nbsp;구성&amp;nbsp;요소들로&amp;nbsp;이루어진&amp;nbsp;하나의&amp;nbsp;구조이다.&lt;br /&gt;-&amp;nbsp;하나의&amp;nbsp;바구니라&amp;nbsp;생각을&amp;nbsp;하면&amp;nbsp;이해하기&amp;nbsp;쉽다.&lt;br /&gt;-&amp;nbsp;데이터의&amp;nbsp;이동이&amp;nbsp;쉽고,&amp;nbsp;이질적인&amp;nbsp;구조를&amp;nbsp;가진다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;2. 새로운 자료형 만들기&lt;/b&gt;&lt;br /&gt;- 기본 자료형 외 새로운 자료형이 필요할 경우, 개발자가 직접 자료형을 만들어서 사용한다.&lt;br /&gt;&amp;nbsp;=&amp;nbsp;객체&amp;nbsp;지향&amp;nbsp;프로그래밍의&amp;nbsp;특징&amp;nbsp;=&amp;nbsp;새로운&amp;nbsp;자료형&amp;nbsp;=&amp;nbsp;사용자&amp;nbsp;정의&amp;nbsp;자료형&lt;br /&gt;&amp;nbsp;&lt;br /&gt;&amp;nbsp;- &lt;b&gt;Class란&lt;/b&gt;, '새로운 자료형을 만들어주는 도구' 라고 생각하면 된다.&lt;br /&gt;&lt;br /&gt;- Person 이라는 새로운 자료형 생성&amp;nbsp;&lt;/h4&gt;
&lt;pre id=&quot;code_1768975249635&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class Person{
String name;
    int age;
    int phone;
    }&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;- 새로 선언 된 name, age, phone는 &lt;b&gt;'속성 = 멤버변수 = 프로퍼티 = 상태 변수'&lt;/b&gt; 라고 한다.&lt;br /&gt;&lt;b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;3. 새로운 자료형 사용하기&lt;/b&gt;&lt;br /&gt;1.&amp;nbsp;새로운&amp;nbsp;자료형을&amp;nbsp;가지고&amp;nbsp;변수&amp;nbsp;선언&amp;nbsp;-&amp;gt;&amp;nbsp;Person&amp;nbsp;p;&lt;br /&gt;2.&amp;nbsp;객체&amp;nbsp;생성하기&amp;nbsp;=&amp;nbsp;인스턴스&amp;nbsp;생성&amp;nbsp;-&amp;gt;&amp;nbsp;new&amp;nbsp;Person();&amp;nbsp;&amp;nbsp;&lt;br /&gt;3.&amp;nbsp;변수&amp;nbsp;p와&amp;nbsp;생성된&amp;nbsp;객체&amp;nbsp;연결&amp;nbsp;-&amp;gt;&amp;nbsp;p&amp;nbsp;=&amp;nbsp;new&amp;nbsp;Person();&lt;/h4&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&amp;nbsp;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1404&quot; data-origin-height=&quot;496&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dm0B6Y/dJMcacBTjm0/fbBR3K8kD6CSlXybigneTK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dm0B6Y/dJMcacBTjm0/fbBR3K8kD6CSlXybigneTK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dm0B6Y/dJMcacBTjm0/fbBR3K8kD6CSlXybigneTK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdm0B6Y%2FdJMcacBTjm0%2FfbBR3K8kD6CSlXybigneTK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;700&quot; height=&quot;247&quot; data-origin-width=&quot;1404&quot; data-origin-height=&quot;496&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;=&amp;gt;&amp;nbsp;&amp;nbsp;**Person p = new Person();**&lt;/h4&gt;
&lt;pre id=&quot;code_1768975390586&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public static void main(String[] args) {
&amp;gt; 
Person p1 = new Person();
p1.name=&quot;홍길동&quot;;
p1.age=24;
p1.phone=12345;
&amp;gt; 
Person p2 = new Person();
p2.name=&quot;최길동&quot;;
p2.age=25;
p2.phone=13335;
}&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;4. 메서드 (Method)&lt;/b&gt;&lt;br /&gt;- 객체가 가지고 있는 동작 = 메서드 = 함수&lt;br /&gt;-&amp;nbsp;'접근제한자&amp;nbsp;리턴타입&amp;nbsp;메소드명&amp;nbsp;(인수1,&amp;nbsp;인수2){수행코드,&amp;nbsp;return&amp;nbsp;반환값&amp;nbsp;;}'&amp;nbsp;으로&amp;nbsp;구성&lt;/h4&gt;
&lt;pre id=&quot;code_1768975420149&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public void test (int a, int b) {
System.out.println(a);
}&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;br /&gt;-&amp;nbsp;리턴&amp;nbsp;타입이&amp;nbsp;void일&amp;nbsp;경우,&amp;nbsp;아무&amp;nbsp;결과도&amp;nbsp;반환하지&amp;nbsp;않는&amp;nbsp;것이다.&amp;nbsp;(return이&amp;nbsp;없음)&lt;br /&gt;-&amp;nbsp;인수&amp;nbsp;=&amp;nbsp;매개변수&lt;br /&gt;&lt;br /&gt;&lt;b&gt;5. 오버로딩 (Overloading)&lt;/b&gt;&lt;br /&gt;-&amp;nbsp;서로&amp;nbsp;비슷한&amp;nbsp;동작(메서드)들을&amp;nbsp;같은&amp;nbsp;이름으로&amp;nbsp;사용하는&amp;nbsp;것.&amp;nbsp;=&amp;nbsp;중복&amp;nbsp;정의&lt;br /&gt;-&amp;nbsp;객체&amp;nbsp;지향&amp;nbsp;프로그래밍의&amp;nbsp;한&amp;nbsp;특징이다.&lt;br /&gt;-&amp;nbsp;오버로딩을&amp;nbsp;하기&amp;nbsp;위해서는&amp;nbsp;매개&amp;nbsp;변수의&amp;nbsp;개수와&amp;nbsp;타입이&amp;nbsp;서로&amp;nbsp;달라야&amp;nbsp;한다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;정적 바인딩 이란?&lt;/b&gt;&lt;br /&gt;-&amp;nbsp;컴파일&amp;nbsp;시점에서&amp;nbsp;사용될&amp;nbsp;메서드가&amp;nbsp;결정&amp;nbsp;되는&amp;nbsp;것.&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1382&quot; data-origin-height=&quot;562&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d7Y1Q4/dJMcab32t13/kDeLOwcIYzEktdrB1KR4oK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d7Y1Q4/dJMcab32t13/kDeLOwcIYzEktdrB1KR4oK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d7Y1Q4/dJMcab32t13/kDeLOwcIYzEktdrB1KR4oK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd7Y1Q4%2FdJMcab32t13%2FkDeLOwcIYzEktdrB1KR4oK%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;1382&quot; height=&quot;562&quot; data-origin-width=&quot;1382&quot; data-origin-height=&quot;562&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;- println의 메소드 오버로딩 사용 예시&lt;/h4&gt;
&lt;pre id=&quot;code_1768975487333&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;System.out.println(12);
System.out.println(12.23);
System.out.println(&quot;afd&quot;);&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;-&amp;nbsp;int,&amp;nbsp;float,&amp;nbsp;srting&amp;nbsp;등&amp;nbsp;자료형&amp;nbsp;구분&amp;nbsp;없이&amp;nbsp;오버로딩을&amp;nbsp;사용하여&amp;nbsp;편리하게&amp;nbsp;사용&lt;/h4&gt;</description>
      <category>공부/Java</category>
      <category>Java</category>
      <category>객체</category>
      <category>기본문법</category>
      <category>메서드</category>
      <category>오버로딩</category>
      <category>자료형</category>
      <author>KoreanPaper</author>
      <guid isPermaLink="true">https://koreanpaper.tistory.com/10</guid>
      <comments>https://koreanpaper.tistory.com/10#entry10comment</comments>
      <pubDate>Wed, 21 Jan 2026 15:05:52 +0900</pubDate>
    </item>
    <item>
      <title>기본 문법(3)</title>
      <link>https://koreanpaper.tistory.com/9</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;1000&quot; data-origin-height=&quot;530&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nqWcu/dJMcacolDqo/Q3bAenFzYWwIVJJKl4aRH1/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nqWcu/dJMcacolDqo/Q3bAenFzYWwIVJJKl4aRH1/img.jpg&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nqWcu/dJMcacolDqo/Q3bAenFzYWwIVJJKl4aRH1/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnqWcu%2FdJMcacolDqo%2FQ3bAenFzYWwIVJJKl4aRH1%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;300&quot; height=&quot;159&quot; data-filename=&quot;자바.jpg&quot; data-origin-width=&quot;1000&quot; data-origin-height=&quot;530&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;1. 비교 연산자&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1768974710712&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public static void main(String[] args) {
boolean Kor=false;
boolean Adult=true;

System.out.println(Kor &amp;amp;&amp;amp; Adult);  // ANd -&amp;gt; &amp;amp;&amp;amp;는 둘다 T일 때만, T
System.out.println(Kor || Adult);  // OR -&amp;gt; ||는 하나라도 T이면, T


System.out.println(1==0 &amp;amp;&amp;amp; 1/0==0);  // &amp;amp;&amp;amp;는 앞에 있는 피연산자가 F이면 뒤를 평가하지 않음(단축평가)
System.out.println(1!=0 || 1/0==0);  // ||은 앞에 있는 피연산자가 T이면 뒤를 평가하지 않음

String str1 = new String(&quot;java&quot;); 
String str2 = new String(&quot;java&quot;);
System.out.println(str1==str2);  // String 안에 텍스트가 저장 되어 있는게 아니라 텍스트 데이터가 있는 주소가 저장되어있음

Scanner sc = new Scanner(System.in);
String t1 =sc.nextLine();
String t2 =sc.nextLine();
System.out.println(t1==t2);  // 다르다고 인식, scanner가 각기 다른 별개의 텍스트로 메모리에 저장, 즉 주소비교
System.out.println(t1.equals(t2));  // 텍스트가 같은지 비교 (내용이 같은지)

char c ='A'; // 원시타입 -&amp;gt; 메모리에 직접저장
System.out.println('A'=='A'); //한글자씩 직접적으로 메모리 저장되는 char는 비교가 보장된다.



}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;br /&gt;&lt;b&gt;2. 증감 연산자(전위, 후위)&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1768974744644&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;int b =10;
System.out.println(b); //10
System.out.println(b++); //10
System.out.println(b); //11

int c = b++;
System.out.println(b +&quot;&quot;+c); // 12 11

int d = ++b;
System.out.println(b+&quot;&quot;+d); // 13 13&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;br /&gt;&lt;br /&gt;&lt;b&gt;3. if문(조건)&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1768974774295&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class Solution03 {
public static void main(String[] args) {

int c = 100;
if (c &amp;lt; 40) {
System.out.println(&quot;c가 40보다 작다&quot;);
} else if (c&amp;lt;90) {
System.out.println(&quot;c가 90보다 작다&quot;);
} else {
System.out.println(&quot;아무 조건도 해당하지 않는다.&quot;);
}

}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;br /&gt;&lt;b&gt;4. switch문(조건)&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1768974799996&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public static void main(String[] args) {

Scanner sc = new Scanner(System.in);
int day = sc.nextInt();

switch (day%7) {

case 0:
System.out.println(&quot;sun&quot;);
break;

case 1:
System.out.println(&quot;mon&quot;);
break;

case 2:
System.out.println(&quot;tue&quot;);
break;

case 3:
System.out.println(&quot;wen&quot;);
break;

default:
System.out.println(&quot;해당 없음&quot;);
break;
}

}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;br /&gt;&lt;b&gt;5. for문(반복)&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1768974838979&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public static void main(String[] args) {

for(int i =0; i&amp;lt;5; i+=2) {
System.out.println(i);
}
        
-------------------------------------------------------
        
for (int a=5; a&amp;gt;=0; a--) {
System.out.println(a); // '5-a' 으로도 표현 가능
}

}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;br /&gt;&lt;b&gt;6. while문(반복)&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1768974876263&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public static void main(String[] args) {

Scanner sc = new Scanner(System.in);
String name =&quot;&quot;;

while(name.equals(&quot;&quot;)) {
Systehttp://m.out.print(&quot;name: &quot;);
name=sc.nextLine();

if(name.equals(&quot;&quot;)) {
System.out.println(&quot;nothing&quot;);
} else {
System.out.println(&quot;hi &quot;+name);
}
}

----------------------------------------------------------------
        
int i=0;
while(i&amp;lt;5) {
System.out.println(i);
i++;
}

----------------------------------------------------------------
        
int j =0;
do {
System.out.println(j);
j++;
} while (j&amp;lt;5);

}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;br /&gt;&lt;b&gt;7. 여러가지 조건에 의해 끝나는 경우 Or 조건문으로 표현하기 매애한 경우&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1768974940662&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public static void main(String[] args) {

Scanner sc= new Scanner(System.in);
while(true) {
System.out.println(&quot;name: &quot;);
String input = sc.nextLine();

if(input.equals(&quot;&quot;)) {
System.out.println(&quot;nothing&quot;);
continue;
}
System.out.println(&quot;hi &quot;+input);
break;
}
}&lt;/code&gt;&lt;/pre&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;br /&gt;&lt;b&gt;8. 배열&lt;/b&gt;&lt;/h4&gt;
&lt;pre id=&quot;code_1768974967513&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public static void main(String[] args) {

int[] numbers; //배열 선언
numbers = new int[5]; // 초기화
numbers[0]=10; // 0번째 자리에 10을 삽입
System.out.println(numbers[0]);

String[] names = new String[10]; // 빈 배열을 선언하고 초기화

int[] ages = {10,20,30};
String[] titles = {&quot;dd&quot;,&quot;ff&quot;,&quot;gg&quot;};
System.out.println(titles); // 주소 출력
System.out.println(Arrays.toString(titles)); //데이터 출력

int[][] matrix = new int[5][3]; // 2차원 배열, 4주치의 3일치
int [][] matrix2 = {
{1,2,3},
{0,6,4},
}; //행렬
System.out.println(matrix2[1][2]);
System.out.println(Arrays.toString(matrix2)); //주소 출력
System.out.println(Arrays.deepToString(matrix2)); //데이터 출력

}
    ---------------------------------------------------------------------------
          int[] numbers= {1,2,3,4,5};

              for(int i=0; i&amp;lt;numbers.length; i++) {
                  System.out.println(numbers[i]);
              }

              //향상된 for문
              for(int number : numbers) {
                  System.out.println(number); // 1 2 3 4 5 형태로 출력
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>공부/Java</category>
      <category>Java</category>
      <category>기본문법</category>
      <category>반복문</category>
      <category>배열</category>
      <category>연산자</category>
      <category>조건문</category>
      <author>KoreanPaper</author>
      <guid isPermaLink="true">https://koreanpaper.tistory.com/9</guid>
      <comments>https://koreanpaper.tistory.com/9#entry9comment</comments>
      <pubDate>Wed, 21 Jan 2026 14:57:06 +0900</pubDate>
    </item>
  </channel>
</rss>