<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>코딩하는 경제학도</title>
    <link>https://ssocoit.tistory.com/</link>
    <description>방문해주셔서 감사합니다! 컴퓨터 공학과 관련해서 공부한 내용들을 정리하기 위해서 이렇게 블로그를 만들게 되었습니다 :) 잘 부탁 드립니다!!</description>
    <language>ko</language>
    <pubDate>Tue, 12 May 2026 11:32:28 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>Ssoco</managingEditor>
    <image>
      <title>코딩하는 경제학도</title>
      <url>https://tistory1.daumcdn.net/tistory/4455942/attach/40a2e7e6fd044dc1a905dfa31a700afe</url>
      <link>https://ssocoit.tistory.com</link>
    </image>
    <item>
      <title>[Kotlin] 범위지정함수 let, run, with, apply, also를 공식 문서를 통해 알아보자!</title>
      <link>https://ssocoit.tistory.com/276</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;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;범위지정함수&lt;/b&gt;&lt;/span&gt;에 대해서 공식 문서를 번역해 보면서 알아보려고 합니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(의역 혹은 원문에는 없는 추가 코멘트들이 다수 포함될 수 있으니 참고 바랍니다!!)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;더 원활한 이해를 위해 원문을 읽고 싶으신 분들을 위해 하단에 공식문서 링크도 함께 첨부드립니다~~  &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1731958356800&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Scope functions | Kotlin&quot; data-og-description=&quot; &quot; data-og-host=&quot;kotlinlang.org&quot; data-og-source-url=&quot;https://kotlinlang.org/docs/scope-functions.html&quot; data-og-url=&quot;https://kotlinlang.org/docs/scope-functions.html&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bKAjwT/hyXzSb50m6/kUU4CWmUKyqvXaLkRbrQS0/img.png?width=800&amp;amp;height=400&amp;amp;face=0_0_800_400&quot;&gt;&lt;a href=&quot;https://kotlinlang.org/docs/scope-functions.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://kotlinlang.org/docs/scope-functions.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bKAjwT/hyXzSb50m6/kUU4CWmUKyqvXaLkRbrQS0/img.png?width=800&amp;amp;height=400&amp;amp;face=0_0_800_400');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Scope functions | Kotlin&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;kotlinlang.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class=&quot;book-toc&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;목차&lt;/p&gt;
&lt;ul id=&quot;toc&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;/ul&gt;
&lt;/div&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;0. 범위지정함수가 뭔데?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코틀린에서의 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;범위지정함수&lt;/b&gt;&lt;/span&gt;는 &lt;u&gt;&lt;b&gt;람다 표현식을 통해 임시 스코프를 만들고 그 안에서 이름 없이 객체에 접근할 수 있도록 도와주는 함수&lt;/b&gt;&lt;/u&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;let, run, with, apply, also 총 5종류가 존재하고, 모두 동일하게 내부 블록(람다 표현식)을 실행하도록 동작&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 부분은 가장 중요한 설명 부분이므로 단순히 의역하기보다는 보다 명확하게 설명하는게 좋을 것 같아서, 특별히 코틀린 공식 홈페이지의 원문을 가져왔습니다. (이 문단 뒤부터 원문은 생략합니다 ㅋㅋㅋ)&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt; The Kotlin standard library contains several functions whose sole purpose is to execute a block of code within the context of an object. When you call such a function on an object with a&amp;nbsp;lambda expression&amp;nbsp;provided, it forms a temporary scope. In this scope, you can access the object without its name. Such functions are called&amp;nbsp;scope functions. There are five of them:&amp;nbsp;let,&amp;nbsp;run,&amp;nbsp;with,&amp;nbsp;apply, and&amp;nbsp;also.&lt;br /&gt;&lt;br /&gt;&lt;span style=&quot;background-color: #ffffff; color: #19191c; text-align: start;&quot;&gt;&lt;b&gt;Basically, these functions all perform the same action: execute a block of code on an object.&lt;/b&gt; What's different is how this object becomes available inside the block and what the result of the whole expression is.&lt;/span&gt; &lt;/span&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 예시는 let이라는 범위지정함수를 사용한 예입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 범위지정함수를 쓰지 않더라도 동일하게 동작하는 코드를 만들 수도 있기 때문에, 해당 케이스도 예시에 같이 포함시켰습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1731925798874&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 범위지정함수 let 사용
Person(&quot;Alice&quot;, 20, &quot;Amsterdam&quot;).let {
    println(it)
    it.moveTo(&quot;London&quot;)
    it.incrementAge()
    println(it)
}

// 범위지정함수 미사용
val alice = Person(&quot;Alice&quot;, 20, &quot;Amsterdam&quot;)
println(alice)
alice.moveTo(&quot;London&quot;)
alice.incrementAge()
println(alice)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 예시를 봤을 때 큰 차이가 느껴지지 않을 수도 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 let이 없는 아래 코드의 경우 alice라는 변수를 선언하고 이것을 반복해서 사용해야 한다는 것을 볼 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉 let을 사용함으로써 코드가 비교적 짧아지거나 가독성이 높아질 수 있다는 것을 확인할 수 있습니다.&lt;/p&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;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이걸 위해서 범위지정함수가 어떤 차이가 있는지, 각각 어떤 방식으로 동작하는지에 대해서 보다 자세히 알아볼 필요가 있습니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. 먼저 간단히 요약좀..&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각각의 범위지정함수에 대해서 자세하게 알아보기 전에, 먼저 표를 통해 간단하게 차이점부터 알아보고 갑시다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래에서 더 자세히 다룰 예정이니, 여기서 짧게 다룬다고 너무 걱정하지 않으셔도 됩니다~&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%; height: 123px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style12&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 21px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 21px; text-align: center;&quot;&gt;함수&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 21px; text-align: center;&quot;&gt;객체 참조&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 21px; text-align: center;&quot;&gt;반환값&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 21px; text-align: center;&quot;&gt;확장함수 여부&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 17px; text-align: center;&quot;&gt;let&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 17px; text-align: center;&quot;&gt;it&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 17px; text-align: center;&quot;&gt;람다 결과값&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 17px; text-align: center;&quot;&gt;O&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 17px; text-align: center;&quot;&gt;run&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 17px; text-align: center;&quot;&gt;this&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 17px; text-align: center;&quot;&gt;람다 결과값&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 17px; text-align: center;&quot;&gt;O&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 17px; text-align: center;&quot;&gt;run&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 17px; text-align: center;&quot;&gt;-&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 17px; text-align: center;&quot;&gt;람다 결과값&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 17px; text-align: center;&quot;&gt;X (단독으로 사용 가능)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 17px; text-align: center;&quot;&gt;with&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 17px; text-align: center;&quot;&gt;this&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 17px; text-align: center;&quot;&gt;람다 결과값&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 17px; text-align: center;&quot;&gt;X (매개변수로 객체를 받음)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 17px; text-align: center;&quot;&gt;apply&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 17px; text-align: center;&quot;&gt;this&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 17px; text-align: center;&quot;&gt;컨텍스트 객체&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 17px; text-align: center;&quot;&gt;O&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 25%; height: 17px; text-align: center;&quot;&gt;also&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 17px; text-align: center;&quot;&gt;it&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 17px; text-align: center;&quot;&gt;컨텍스트 객체&lt;/td&gt;
&lt;td style=&quot;width: 25%; height: 17px; text-align: center;&quot;&gt;O&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p 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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;let&lt;/b&gt; &lt;/span&gt;: non-nullable한 객체에 대해서 람다 표현식을 실행하고 싶을 때 / 지역 스코프에서 표현식을 변수 형태로 사용하고 싶을 때&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;apply&lt;/b&gt; &lt;/span&gt;: 객체를 정의할 때&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;run&lt;/b&gt; &lt;/span&gt;: 객체를 정의하고 결과값을 연산해야할 때 / 표현식이 필요한 명령문을 실행할 때 (단독 사용 시)&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;also&lt;/b&gt; &lt;/span&gt;: 추가적인 effect가 존재할 때 (side-effect의 그 effect입니다)&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;with&lt;/b&gt; &lt;/span&gt;: 객체에서 함수 호출을 묶고싶을 때&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반드시 위 상황에서만 써야하는 것은 아니고, 팀 내에 특정 컨벤션이 존재하거나 한다면 거기에 따라가도 좋습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 &lt;b&gt;범위지정함수를 남발&lt;/b&gt;하게 되면 오히려 코드의 가독성을 해치거나 잘못 사용하게 되어 에러가 발생할 수도 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 &lt;b&gt;중첩해서 범위지정함수를 사용하는 것&lt;/b&gt;도 코드의 이해도를 낮추거나, 범위지정함수가 대상으로 하는 객체, 혹은 스코프 내부에서 사용하는 this, it과 같은 객체 참조 요소에 대한 혼동을 줄 수 있으니 주의해야 합니다.&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. 대충 알았으니까 무슨 차이가 있는건데?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;범위지정함수는 일반적으로 비슷하게 보이지만, 크게 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;객체 참조 방식&lt;/b&gt;&lt;/span&gt;과 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;반환값&lt;/span&gt;&lt;/b&gt;&amp;nbsp;두 가지 형태로 나눌 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사진으로 미리 정리해보면 아래와 같습니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1075&quot; data-origin-height=&quot;706&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uewoV/btsKOeSRpDT/wxs6rQdv6ANYI1llwCgsvk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uewoV/btsKOeSRpDT/wxs6rQdv6ANYI1llwCgsvk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uewoV/btsKOeSRpDT/wxs6rQdv6ANYI1llwCgsvk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuewoV%2FbtsKOeSRpDT%2Fwxs6rQdv6ANYI1llwCgsvk%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;677&quot; height=&quot;445&quot; data-origin-width=&quot;1075&quot; data-origin-height=&quot;706&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2.0. 객체 참조 방식: this / it&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;객체 참조 방식&lt;/b&gt;&lt;/span&gt;에 있어서 &lt;b&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;this&lt;/span&gt;&lt;/b&gt;를 쓰는 범위지정함수와 &lt;b&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;it&lt;/span&gt;&lt;/b&gt;을 쓰는 범위지정함수로 나뉩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;this의 경우 람다 수신자(객체 참조자), it은 람다 인수(람다 매개변수)라고 부릅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래에서 두 케이스에 대한 사용법과 장단점 등을 알아봅시다.&lt;/p&gt;
&lt;pre id=&quot;code_1731949103116&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;fun main() {
    val str = &quot;Hello&quot;
    // this를 사용하는 run
    str.run {
        println(&quot;The string's length: $length&quot;)
        //println(&quot;The string's length: ${this.length}&quot;) // 이렇게도 가능!!
    }

    // it을 사용하는 let
    str.let {
        println(&quot;The string's length is ${it.length}&quot;)
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt; &lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;b&gt;2.0.0. this&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;this&lt;/span&gt;&lt;/b&gt;를 사용하는 케이스는 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;run&lt;/b&gt;&lt;/span&gt;, &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;with&lt;/b&gt;&lt;/span&gt;, &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;apply&lt;/b&gt;&lt;/span&gt;가 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세 가지 케이스에서는 람다 표현식 내부에서 일반적인 클래스 함수들처럼 객체를 사용할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1731949209515&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;val adam = Person(&quot;Adam&quot;).apply { 
    age = 20  // this.age = 20와 동일!!
    city = &quot;London&quot;
}
println(adam)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt; &lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;b&gt;2.0.1. it&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;it&lt;/b&gt;&lt;/span&gt;을 사용하는 케이스는 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt;과 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;also&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;만약 명시적으로 이름을 설정하지 않으면 &lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;it&lt;/b&gt;&lt;/span&gt; 이라는 기본 이름으로 참조할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1731949730350&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 암시적(it)으로 인수를 설정했을 경우
fun getRandomInt(): Int {
    return Random.nextInt(100).also {
        writeToLog(&quot;getRandomInt() generated value $it&quot;)
    }
}

val i = getRandomInt()
println(i)&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1731949743981&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 명시적(value)으로 인수를 설정했을 경우
fun getRandomInt(): Int {
    return Random.nextInt(100).also { value -&amp;gt;
        writeToLog(&quot;getRandomInt() generated value $value&quot;)
    }
}

val i = getRandomInt()
println(i)&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: #8a3db6;&quot;&gt;&lt;b&gt; it&lt;/b&gt;&lt;/span&gt;은 &lt;span style=&quot;color: #009a87;&quot;&gt;&lt;b&gt;this&lt;/b&gt;&lt;/span&gt;보다 짧고, 가독성이 좋습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 &lt;span style=&quot;color: #009a87;&quot;&gt;&lt;b&gt;this&lt;/b&gt;&lt;/span&gt;의 경우 객체의 함수나 속성값(property)를 사용할 때는 아예 생략해버릴 수 있다는 장점이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러므로 함수의 인자로 들어가야 한다거나, 코드블럭 내에서 여러 변수를 사용해야 한다거나하는 케이스에서 it이 더 좋습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2.1. 반환값: 객체 / 람다 표현식&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;반환값&lt;/b&gt;&lt;/span&gt;의 유무로도 범위지정함수를 구분할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;apply&lt;/b&gt;&lt;/span&gt;와 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;also&lt;/b&gt;&lt;/span&gt;는 &lt;u&gt;&lt;b&gt;객체&lt;/b&gt;&lt;b&gt;를 그대로 반환&lt;/b&gt;&lt;/u&gt;하고 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt;, &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;run&lt;/b&gt;&lt;/span&gt;, &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;with&lt;/b&gt;&lt;/span&gt;은 &lt;u&gt;&lt;b&gt;람다 표현식의 결과값을 반환&lt;/b&gt;&lt;/u&gt;합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt;, &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;run&lt;/b&gt;&lt;/span&gt;, &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;with&lt;/b&gt;&lt;/span&gt;은 반환값이 없을 수도 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇기 때문에 다음에 이 결과값으로 무엇을 할 지에 따라 사용하는 범위지정함수를 잘 결정해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;  2.1.0. 객체 반환&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;apply&lt;/b&gt;&lt;/span&gt;와 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;also&lt;/b&gt;&lt;/span&gt;는 &lt;u&gt;&lt;b&gt;객체를 반환&lt;/b&gt;&lt;/u&gt;하기 때문에 chain 함수를 사용할 수도 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 예시처럼 람다 표현식을 마치고 정렬을 한다거나.. 할 수 있는 거죠.&lt;/p&gt;
&lt;pre id=&quot;code_1731950539315&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;val numberList = mutableListOf&amp;lt;Double&amp;gt;()
numberList.also { println(&quot;Populating the list&quot;) }
    .apply {
        add(2.71)
        add(3.14)
        add(1.0)
    }
    .also { println(&quot;Sorting the list&quot;) }
    .sort()&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;아니면 object의 함수 반환문 형태로도 사용할 수 있습니다. (반환할 때 어떠한 동작을 추가한 다음 반환할 수 있습니다!!)&lt;/p&gt;
&lt;pre id=&quot;code_1731950608820&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;fun getRandomInt(): Int {
    return Random.nextInt(100).also {
        writeToLog(&quot;getRandomInt() generated value $it&quot;)
    }
}

val i = getRandomInt()&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size20&quot;&gt;&lt;b&gt; &lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/b&gt;&lt;b&gt;2.1.1. 람다 표현식 반환&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;let&lt;/b&gt;, &lt;b&gt;run&lt;/b&gt;, &lt;b&gt;with&lt;/b&gt;은 &lt;u&gt;&lt;b&gt;람다 표현식을 반환&lt;/b&gt;&lt;/u&gt;하기 때문에 따로 변수에 결과값을 할당해 주어야만 결과값을 이어서 사용할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1731951058359&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;val numbers = mutableListOf(&quot;one&quot;, &quot;two&quot;, &quot;three&quot;)
val countEndsWithE = numbers.run { 
    add(&quot;four&quot;)
    add(&quot;five&quot;)
    count { it.endsWith(&quot;e&quot;) }
}
println(&quot;There are $countEndsWithE elements that end with e.&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아예 반환을 하지 않고 임시 스코프 형태로 사용할 수도 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1731951118125&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;val numbers = mutableListOf(&quot;one&quot;, &quot;two&quot;, &quot;three&quot;)
with(numbers) {
    val firstItem = first()
    val lastItem = last()        
    println(&quot;First item: $firstItem, last item: $lastItem&quot;)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3. 각각의 함수들에 대해서 자세히 알려줘!&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 5가지의 범위지정함수에 대해서 좀 더 디테일하게 뜯어봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3.0. let&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt;은 객체 참조는 &lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;it&lt;/b&gt;&lt;/span&gt;으로 가능하고, &lt;u&gt;&lt;b&gt;람다 표현식을 반환&lt;/b&gt;&lt;/u&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;예를 들면 두 collections가 존재하고, 결과값을 출력해야 한다고 가정해보겠습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1731953687701&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;val numbers = mutableListOf(&quot;one&quot;, &quot;two&quot;, &quot;three&quot;, &quot;four&quot;, &quot;five&quot;)
val resultList = numbers.map { it.length }.filter { it &amp;gt; 3 }
println(resultList)&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: #ee2323;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt;을 사용하면 resultList를 변수에 할당하지 않고도 똑같이 동작하는 코드를 만들 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1731953780486&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;val numbers = mutableListOf(&quot;one&quot;, &quot;two&quot;, &quot;three&quot;, &quot;four&quot;, &quot;five&quot;)
numbers.map { it.length }.filter { it &amp;gt; 3 }.let { 
    println(it)
    // 필요하면 여기에서 함수를 더 호출할 수도 있다!
}&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: #ee2323;&quot;&gt;&lt;b&gt;let&lt;/b&gt; &lt;/span&gt;안에 하나의 함수만 들어가는 경우, 메서드 참조(::)를 사용해서 더 간단히 표현할 수도 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1731953816309&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;val numbers = mutableListOf(&quot;one&quot;, &quot;two&quot;, &quot;three&quot;, &quot;four&quot;, &quot;five&quot;)
numbers.map { it.length }.filter { it &amp;gt; 3 }.let(::println)&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: #ee2323;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt;은 non-null값들을 담은 코드블럭을 실행할 때도 자주 사용됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;non-null object에서만 실행되게 하기 위해 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;safe call operator(?.)&lt;/b&gt;&lt;/span&gt;를 사용할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1731954063421&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;val str: String? = &quot;Hello&quot;

// str은 String? 타입으로 null이 올 수 있어서 compilation error가 발생!!
// processNonNullString(str) 

// 'it' 은 '?.let { }' 블럭 내에서 not-null을 보장받을 수 있다!!
val length = str?.let { 
    println(&quot;let() called on $it&quot;)        
    processNonNullString(it) 
    it.length
}&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: #ee2323;&quot;&gt;&lt;b&gt;let&lt;/b&gt;&lt;/span&gt;을 사용할 수도 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체에 새로운 변수를 정의하기 위해서 람다 표현식의 인수(매개변수)에 이름을 부여하여 it 대신 그 이름으로 대신 사용할 수도 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1731954762795&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;val numbers = listOf(&quot;one&quot;, &quot;two&quot;, &quot;three&quot;, &quot;four&quot;)
val modifiedFirstItem = numbers.first().let { firstItem -&amp;gt;
    println(&quot;The first item of the list is '$firstItem'&quot;)
    if (firstItem.length &amp;gt;= 5) firstItem else &quot;!&quot; + firstItem + &quot;!&quot;
}.uppercase()
println(&quot;First item after modifications: '$modifiedFirstItem'&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3.1. with&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;with&lt;/b&gt;&lt;/span&gt;은&lt;span&gt; &lt;/span&gt;&lt;/span&gt;객체 참조는 &lt;span style=&quot;color: #009a87;&quot;&gt;&lt;b&gt;this&lt;/b&gt;&lt;/span&gt;로 가능하고, &lt;u&gt;&lt;b&gt;람다 표현식을 반환&lt;/b&gt;&lt;/u&gt;합니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&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 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;with&lt;/b&gt;&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 style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;with&lt;/b&gt;&lt;/span&gt;은 코드상에서 &quot;매개변수로 받은 객체와 함께, 람다 표현식을 실행합니다!&quot; 로도 읽힐 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1731955111945&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;val numbers = mutableListOf(&quot;one&quot;, &quot;two&quot;, &quot;three&quot;)
with(numbers) {
    println(&quot;'with' is called with argument $this&quot;)
    println(&quot;It contains $size elements&quot;)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;with&lt;/b&gt;&lt;/span&gt;은 값을 연산하는데 사용되는 속성이나 함수를 가진 &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;helper 객체를 &lt;/span&gt;선언하기 위해서도 사용됩니다.&lt;/p&gt;
&lt;pre id=&quot;code_1731955809665&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;val numbers = mutableListOf(&quot;one&quot;, &quot;two&quot;, &quot;three&quot;)
val firstAndLast = with(numbers) {
    &quot;The first element is ${first()},&quot; +
    &quot; the last element is ${last()}&quot;
}
println(firstAndLast)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3.2. run&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;run&lt;/b&gt;&lt;/span&gt;은&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;객체 참조는 &lt;span style=&quot;color: #009a87;&quot;&gt;&lt;b&gt;this&lt;/b&gt;&lt;/span&gt;로 가능하고, &lt;u&gt;&lt;b&gt;람다 표현식을 반환&lt;/b&gt;&lt;/u&gt;합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 with이랑 똑같은 게 아니냐?? 라고 생각할 수도 있겠지만, &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;run&lt;/b&gt;&lt;/span&gt;은 확장함수 형태로 사용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 let처럼 객체 뒤에 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;.run { }&lt;/b&gt;&lt;/span&gt; 과 같은 형태로 사용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;run은 람다 표현식 내에서 객체를 초기화하고 반환값을 연산해야 하는 경우 유용하게 사용될 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1731956028775&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;val service = MultiportService(&quot;https://example.kotlinlang.org&quot;, 80)

val result = service.run {
    port = 8080
    query(prepareRequest() + &quot; to port $port&quot;)
}

// let으로 똑같이 동작하도록 만들 수도 있습니다
val letResult = service.let {
    it.port = 8080
    it.query(it.prepareRequest() + &quot; to port ${it.port}&quot;)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 특이한 점이라면, &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;run&lt;/b&gt;&lt;/span&gt;은 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;확장함수가 아닌 형태&lt;/b&gt;&lt;/span&gt;로도 사용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;확장함수가 아닌 형태의 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;run&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;확장함수가 아닌 형태의 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;run&lt;/b&gt;&lt;/span&gt;은 코드 상에서 &quot;코드 블럭을 run 하고 결과를 도출합니다!&quot;로 읽힐 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1731956277546&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;val hexNumberRegex = run {
    val digits = &quot;0-9&quot;
    val hexDigits = &quot;A-Fa-f&quot;
    val sign = &quot;+-&quot;

    Regex(&quot;[$sign]?[$digits$hexDigits]+&quot;)
}

for (match in hexNumberRegex.findAll(&quot;+123 -FFFF !%*&amp;amp; 88 XYZ&quot;)) {
    println(match.value)
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3.3. apply&lt;/b&gt;&lt;/h3&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;apply&lt;/b&gt;&lt;/span&gt;는&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;객체 참조는 &lt;span style=&quot;color: #009a87;&quot;&gt;&lt;b&gt;this&lt;/b&gt;&lt;/span&gt;로 가능하고, &lt;u&gt;&lt;b&gt;객체를 반환&lt;/b&gt;&lt;/u&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 style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;객체를 그대로 반환하기 때문에, 객체의 멤버 변수를 주로 실행하면서 값을 반환하지 않는 케이스에 사용하는 것을 권장합니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;가장 대표적으로 많이 쓰이는 케이스가 객체 구성(설정)입니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;이러한 동작은 &quot;객체에 다음과 같은 할당을 적용합니다!&quot;로 읽힐 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1731956892862&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;val adam = Person(&quot;Adam&quot;).apply {
    age = 32
    city = &quot;London&quot;        
}
println(adam)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또 다른 사용 예시의 경우 복잡한 처리 과정을 위해 여러번 체이닝을 하는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(이건 원문에 따로 예시가 없어서 직접 만들었습니다!)&lt;/p&gt;
&lt;pre id=&quot;code_1731957123458&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;val adam = Person(&quot;Adam&quot;).plusAge().celebrate().apply {
    status = &quot;adult&quot;        
}
println(adam)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3.4. also&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;also&lt;/b&gt;&lt;/span&gt;는 객체 참조는 &lt;b&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;it&lt;/span&gt;&lt;/b&gt;으로 가능하고, &lt;u&gt;&lt;b&gt;객체를 반환&lt;/b&gt;&lt;/u&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: #ee2323;&quot;&gt;&lt;b&gt; also&lt;/b&gt;&lt;/span&gt;는 객체를 인수로 사용하는 일부 작업을 수행하는 데 유용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;객체의 속성이나 함수가 아닌 객체 자체에 대한 참조가 필요하거나, 외부 스코프의 this 참조를 가리지 않으려는 경우 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;also&lt;/b&gt;&lt;/span&gt;를 사용하는 것을 권장합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 동작은 &quot;그 객체로 다음의 작업을 수행합니다!&quot;로 읽힐 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1731957426165&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;val numbers = mutableListOf(&quot;one&quot;, &quot;two&quot;, &quot;three&quot;)
numbers
    .also { println(&quot;The list elements before adding new one: $it&quot;) }
    .add(&quot;four&quot;)&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;4. 번외로 알아보는 takeIf와 takeUnless&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 공부한 범위지정함수 외에도 표준 라이브러리에는 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;takeIf&lt;/b&gt;&lt;/span&gt;와 &lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;takeUnless&lt;/span&gt;&lt;/b&gt;라는 함수가 포함되어 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 두 함수를 통해 객체 상태를 검사할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt; &lt;b&gt;takeIf&lt;/b&gt;&lt;/span&gt;는 객체의 확장함수 형태로 &lt;u&gt;&lt;b&gt;조건식과 함께 호출되었을 때 해당 조건을 만족하면 해당 객체를 반환&lt;/b&gt;&lt;b&gt;하고, 만족하지 못하면 null을 반환&lt;/b&gt;&lt;/u&gt;합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 takeIf는 단일 객체를 위한 필터링 함수입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;takeUnless&lt;/b&gt;&lt;/span&gt;는 takeIf와 반대의 로직으로 동작합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;b&gt;조건을 만족하면 null, 만족하지 않으면 객체를 반환&lt;/b&gt;&lt;/u&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;두 케이스 모두에서 객체는 람다 표현식 내에서 it으로 접근할 수 있습니다.&lt;/p&gt;
&lt;pre id=&quot;code_1731957777649&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;val number = Random.nextInt(100)

val evenOrNull = number.takeIf { it % 2 == 0 }
val oddOrNull = number.takeUnless { it % 2 == 0 }
println(&quot;even: $evenOrNull, odd: $oddOrNull&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;❗ 여기서 한 가지 주의해야 하는 점이라면, takeIf나 takeUnless 뒤에 다른 함수를 체이닝할 때는 &lt;br /&gt;&lt;u&gt;&lt;b&gt;safe call operator(?.)을 사용&lt;/b&gt;&lt;/u&gt;하거나 &lt;u&gt;&lt;b&gt;null 체크를 하는 것&lt;/b&gt;&lt;/u&gt;을 잊지 마세요!!&lt;br /&gt;(takeIf랑 takeUnless는 nullable한 반환값을 주니까!!!)&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1731957958595&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;val str = &quot;Hello&quot;
val caps = str.takeIf { it.isNotEmpty() }?.uppercase()

// str이 empty면 null에 대해 .uppercase()를 할 수 없어서 compilation 에러가 발생한다!!
// val caps = str.takeIf { it.isNotEmpty() }.uppercase() 

println(caps)&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: #000000;&quot;&gt;&lt;b&gt;takeIf&lt;/b&gt;&lt;/span&gt;와 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;takeUnless&lt;/b&gt;&lt;/span&gt;는 &lt;u&gt;&lt;b&gt;범위지정함수와 결합할 때 굉장히 유용&lt;/b&gt;&lt;/u&gt;합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어 takeIf, takeUnless와 let을 체이닝하면 특정 조건에 만족하는 객체에 대해서만 코드 블럭을 실행할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이걸 위해 takeIf를 호출한 이후 safe call operator(?.)와 함께 let을 호출하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;조건에 만족하지 않는 객체에 대해서는 takeIf가 null을 반환하게 되고 let이라는 범위지정함수의 람다 표현식은 실행되지 않겠죠?&lt;/p&gt;
&lt;pre id=&quot;code_1731958266104&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;fun displaySubstringPosition(input: String, sub: String) {
    input.indexOf(sub).takeIf { it &amp;gt;= 0 }?.let {
        println(&quot;The substring $sub is found in $input.&quot;)
        println(&quot;Its start position is $it.&quot;)
    }
}

displaySubstringPosition(&quot;010000011&quot;, &quot;11&quot;)
displaySubstringPosition(&quot;010000011&quot;, &quot;12&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비교를 위해서 아래 예시는 takeIf와 범위지정함수를 사용하지 않으면 어떻게 되는지를 보여줍니다.&lt;/p&gt;
&lt;pre id=&quot;code_1731958342809&quot; class=&quot;kotlin&quot; data-ke-language=&quot;kotlin&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;fun displaySubstringPosition(input: String, sub: String) {
    val index = input.indexOf(sub)
    if (index &amp;gt;= 0) {
        println(&quot;The substring $sub is found in $input.&quot;)
        println(&quot;Its start position is $index.&quot;)
    }
}

displaySubstringPosition(&quot;010000011&quot;, &quot;11&quot;)
displaySubstringPosition(&quot;010000011&quot;, &quot;12&quot;)&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category># 공부 자료들/Kotlin</category>
      <category>Kotlin</category>
      <category>scope function</category>
      <category>범위지정함수</category>
      <category>코틀린</category>
      <author>Ssoco</author>
      <guid isPermaLink="true">https://ssocoit.tistory.com/276</guid>
      <comments>https://ssocoit.tistory.com/276#entry276comment</comments>
      <pubDate>Tue, 19 Nov 2024 04:45:24 +0900</pubDate>
    </item>
    <item>
      <title>[Android] 안드로이드 개발의 기초, Activity의 생명주기 톺아보기!</title>
      <link>https://ssocoit.tistory.com/275</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;인턴 생활을 자발적으로 그만두고(!) 새로운 회사에 들어가고 단 한번도 생각해보지 않았던 앱 개발을 맡게 되어서 어떻게든 살아남기 위해서 발버둥치다보니 어느새 입사하고 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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞으로는 이전처럼 FE 관련 글도 올라오겠지만, 현업에서 사용하고 있는 &lt;span style=&quot;color: #409d00;&quot;&gt;&lt;b&gt;Kotlin&lt;/b&gt;&lt;/span&gt;과 &lt;span style=&quot;color: #a6bc00;&quot;&gt;&lt;b&gt;Android&lt;/b&gt;&lt;/span&gt;에 대한 글들도 많이 올라가게 될 것 같습니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무래도 Android 앱 개발팀에서 일을 하다보니, 기존과는 다르게 Kotlin과 Android에 대한 지식들이 필요해졌습니다. (심지어 현재 회사에 들어올 때도 FE로 면접을 보고 들어왔다보니 앱 개발 취준생이 가진 기본적인 면접 지식들도 부족합니다 ㅠㅠ)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;게다가 이와 관련된 다양한 업무들을 처리하기 위해서는 그때그때마다 산발적으로 공부해야 했는데, 이 때 부분적으로 익혔던 내용들을 보다 깔끔하게 정리하며 복습하는 용도로 블로그를 운영해 보려고 합니다 ㅎㅎㅎ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 오늘은, 안드로이드 개발에서 가장 핵심이 되는 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;Activity의 생명주기&lt;/b&gt;&lt;/span&gt;에 대해서 알아보도록 하겠습니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class=&quot;book-toc&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;목차&lt;/p&gt;
&lt;ul id=&quot;toc&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;/ul&gt;
&lt;/div&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;0. Activity가 뭘까&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;우리가 사용하는 애플리케이션은 각각의 화면들로 이루어져있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떤 앱에서는 로그인 화면이 있을거고, 메인 화면이 있을거고, 결제 화면이 있을 수 있겠죠?!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;이런 &lt;/b&gt;&lt;/u&gt;&lt;u&gt;&lt;b&gt;화면들 하나하나&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;가 &lt;b&gt;&lt;/b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;Activity&lt;/b&gt;&lt;/span&gt;라고 볼 수 있게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;Activity&lt;/b&gt;&lt;/span&gt;는 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;UI를 작성하는 하나의 도화지&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;라고 볼 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Activity라는 도화지에 우리가 볼 수 있는 다양한 요소들이 들어가게 되고, 사용자와 상호작용할 수 있게 되는 것이죠.&lt;/p&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;Activity 역시 분리되어 있기 때문에 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;서로 다른 진입점&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;을 가지고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메인 화면 Activity에서 어떤 버튼을 클릭해서 결제 화면 Activity로 넘어갈 수도 있고, 아예 다른 웹 환경에서 버튼을 클릭했을 때 바로 결제 화면 Activity로 넘어갈 수도 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이처럼 각각의 Activity는 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;기본적으로 언제든지 분리해서 사용할 수 있는 독립적인 존재&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;503&quot; data-origin-height=&quot;323&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/4EWs2/btsGdqSI4sE/ClXHaaqIRgXxZnqYPzqddk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/4EWs2/btsGdqSI4sE/ClXHaaqIRgXxZnqYPzqddk/img.png&quot; data-alt=&quot;출처:https://dinfree.com/lecture/android/android_3.1.html&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/4EWs2/btsGdqSI4sE/ClXHaaqIRgXxZnqYPzqddk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F4EWs2%2FbtsGdqSI4sE%2FClXHaaqIRgXxZnqYPzqddk%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;503&quot; height=&quot;323&quot; data-origin-width=&quot;503&quot; data-origin-height=&quot;323&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처:https://dinfree.com/lecture/android/android_3.1.html&lt;/figcaption&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;아래 링크는 액티비티에 대해 잘 설명이 되어있는 Android Developers에 작성된 글입니다. (영어 주의!)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1711918952290&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Activity &amp;nbsp;|&amp;nbsp; Android Developers&quot; data-og-description=&quot;&quot; data-og-host=&quot;developer.android.com&quot; data-og-source-url=&quot;https://developer.android.com/reference/android/app/Activity&quot; data-og-url=&quot;https://developer.android.com/reference/android/app/Activity&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bypF54/hyVGHKKpCk/Vhv72MKgjLvbSFGHKSuKsk/img.png?width=1201&amp;amp;height=676&amp;amp;face=0_0_1201_676&quot;&gt;&lt;a href=&quot;https://developer.android.com/reference/android/app/Activity&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developer.android.com/reference/android/app/Activity&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bypF54/hyVGHKKpCk/Vhv72MKgjLvbSFGHKSuKsk/img.png?width=1201&amp;amp;height=676&amp;amp;face=0_0_1201_676');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Activity &amp;nbsp;|&amp;nbsp; Android Developers&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;developer.android.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Activity에 대해서 계속 공부하다보면 볼 수 있는 다른 개념들이 꽤 많이 존재합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 대표적으로 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;u&gt;Activity 사이에서 데이터를 전달하기 위한 용도&lt;/u&gt;&lt;/b&gt;&lt;/span&gt;로 사용되는 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Intent&lt;/b&gt;&lt;/span&gt;,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;복잡해지는 Activity를 보다 단순화하고 재사용이 용이하도록 모듈화 하는 용도&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;로 사용되는 &lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;Fragment &lt;/b&gt;&lt;/span&gt;정도가 있겠네요!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 요소들은 오늘의 주제에서 약간 벗어나기 때문에 해당 포스팅에서는 이정도로만 알아보고 넘어가겠습니다  &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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. Activity의 생명주기가 뭘까&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 오늘 포스팅의 핵심 주제인 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;생명주기&lt;/b&gt;&lt;/span&gt;에 대해서 보다 자세히 알아보도록 하겠습니다.&lt;/p&gt;
&lt;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;안드로이드 개발을 하신다면 아래 Activity의 생명주기 그림,&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;513&quot; data-origin-height=&quot;663&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bi6TwD/btsGetgIxYV/XYdfG4Zpxohzp969ogKMA0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bi6TwD/btsGetgIxYV/XYdfG4Zpxohzp969ogKMA0/img.png&quot; data-alt=&quot;출처 : https://developer.android.com/reference/android/app/Activity&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bi6TwD/btsGetgIxYV/XYdfG4Zpxohzp969ogKMA0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbi6TwD%2FbtsGetgIxYV%2FXYdfG4Zpxohzp969ogKMA0%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;513&quot; height=&quot;663&quot; data-origin-width=&quot;513&quot; data-origin-height=&quot;663&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처 : https://developer.android.com/reference/android/app/Activity&lt;/figcaption&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;위 그림을 확실하게 파악했다면, 아래와 같이 Activity의 상태 중심으로 그려진 그림도 쉽게 이해할 수 있게 되겠죠?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 포스팅을 모두 읽었을 때 쯤이라면 두 그림이 의미하는 바를 단번에 파악하실 수 있게 될 겁니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;410&quot; data-origin-height=&quot;469&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vFObN/btsGgzVA22i/7FHhpX56in2WiLWmM5B7c0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vFObN/btsGgzVA22i/7FHhpX56in2WiLWmM5B7c0/img.png&quot; data-alt=&quot;출처:https://developer.android.com/codelabs/basic-android-kotlin-compose-activity-lifecycle#2&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vFObN/btsGgzVA22i/7FHhpX56in2WiLWmM5B7c0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvFObN%2FbtsGgzVA22i%2F7FHhpX56in2WiLWmM5B7c0%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;410&quot; height=&quot;469&quot; data-origin-width=&quot;410&quot; data-origin-height=&quot;469&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처:https://developer.android.com/codelabs/basic-android-kotlin-compose-activity-lifecycle#2&lt;/figcaption&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;안드로이드 환경에서는 각각의 Activity들이 위와 같은 생명주기를 예외 없이 따라가게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각 단계들에서 &lt;span style=&quot;color: #000000;&quot;&gt;동작이 필요한 부분이 있다면 &lt;b&gt;&lt;/b&gt;&lt;u&gt;&lt;b&gt;콜백 형태의 메서드(생명주기함수) 내부에 구현&lt;/b&gt;&lt;/u&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;/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;br /&gt;이걸 막기 위해서는 전화가 왔을 때 잠시 영상을 멈추는 동작을 어느 순간에 해야겠다는 생각이 들죠?!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바로 위와 같은 상황을 처리하기 위해서 특정 생명주기함수(onStop) 안에 원하는 동작(영상 멈추기)을 넣음으로써 우리가 원하는 대로 애플리케이션을 동작하게 만들 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 Activity의 생명주기를 모르는 상태에서 위와 같은 상황을 마주한다면 생각대로 애플리케이션이 동작하게 만들기 위해서 한참을 삽질해야 할 지도 모릅니다.&lt;/p&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;그렇다면 Activity의 탄생과 소멸까지의 과정중에 발생할 수 있는 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;5가지의 상태&lt;/b&gt;&lt;/span&gt;와 &lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;7가지의 생명주기함수&lt;/b&gt;&lt;/span&gt;에 대해서 더 자세하게 알아봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. Activity의 5가지 상태&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Activity에 생명주기가 있다는 말은, 특정한 상태에 따라 생성과 소멸을 하게 된다는 말과 동일합니다.&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 style=&quot;color: #000000;&quot;&gt;기본적으로 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;생성(Initialized)&lt;/b&gt;&lt;/span&gt;과 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;소멸(Destroyed)&lt;/b&gt;&lt;/span&gt;이라는 상태를 가지고 있고, 그 사이에 보여지는지 여부와 포커스 가능 여부에 따라 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;3가지의 상태(Created, Started, Resumed)&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 style=&quot;color: #000000;&quot;&gt;상태 자체는 크게 어렵지 않죠?&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;각각의 개념은 아래에서 추가로 설명하겠습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;아, 개념을 설명하기 전에 Android 내에서 Activity의 상태가 어떻게 사용되는지에 대해서 간단하게 설명하고 넘어가겠습니다. 어떤 방식으로 쓰이는 지는 알아야 하니까요!&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: #000000;&quot;&gt;기본적으로 &lt;b&gt;&lt;/b&gt;&lt;u&gt;&lt;b&gt;Android의 운영체제는 Activity들을 Stack형태로 관리&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 이 Stack을 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;Back Stack&lt;/b&gt;&lt;/span&gt;이라고 부릅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Stack의 개념에 대해서 잘 모르신다면.. 자료구조 카테고리의 stack 글을.. ㅋㅋㅋㅋ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1711993122834&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[자료구조] 스택(stack), 큐(queue)&quot; data-og-description=&quot;오늘은 자료구조의 가장 기본이 되는 스택과 큐에 대해서 알아보도록 하겠습니다! 목차 0. 스택 스택(Stack)이란 이름 그대로 순서대로 쌓인 무언가를 의미합니다. 우리가 뭘 쌓을 때 아래 요소를 &quot; data-og-host=&quot;ssocoit.tistory.com&quot; data-og-source-url=&quot;https://ssocoit.tistory.com/230&quot; data-og-url=&quot;https://ssocoit.tistory.com/230&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/e4RGI/hyVGKOqRu5/MYKX5AdK7DwFkxaM9MqdFk/img.png?width=350&amp;amp;height=245&amp;amp;face=0_0_350_245,https://scrap.kakaocdn.net/dn/tSiCB/hyVJUWbM2o/HLy11Q627953qXWxVS3Zmk/img.png?width=350&amp;amp;height=245&amp;amp;face=0_0_350_245,https://scrap.kakaocdn.net/dn/C7Ys9/hyVGFl5xRf/o1uTZ98TWqyJqsqnzZkzPK/img.png?width=1219&amp;amp;height=397&amp;amp;face=0_0_1219_397&quot;&gt;&lt;a href=&quot;https://ssocoit.tistory.com/230&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://ssocoit.tistory.com/230&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/e4RGI/hyVGKOqRu5/MYKX5AdK7DwFkxaM9MqdFk/img.png?width=350&amp;amp;height=245&amp;amp;face=0_0_350_245,https://scrap.kakaocdn.net/dn/tSiCB/hyVJUWbM2o/HLy11Q627953qXWxVS3Zmk/img.png?width=350&amp;amp;height=245&amp;amp;face=0_0_350_245,https://scrap.kakaocdn.net/dn/C7Ys9/hyVGFl5xRf/o1uTZ98TWqyJqsqnzZkzPK/img.png?width=1219&amp;amp;height=397&amp;amp;face=0_0_1219_397');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[자료구조] 스택(stack), 큐(queue)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;오늘은 자료구조의 가장 기본이 되는 스택과 큐에 대해서 알아보도록 하겠습니다! 목차 0. 스택 스택(Stack)이란 이름 그대로 순서대로 쌓인 무언가를 의미합니다. 우리가 뭘 쌓을 때 아래 요소를&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;ssocoit.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아무튼!! &lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;Stack방식을 사용해서 Activity를 관리한다&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;는 말은,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Activity가 새롭게 띄워질 때마다 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;Stack의 top 위치에 새로운 Activity가 올라가는 방식&lt;/b&gt;&lt;/u&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;반대로 뒤로가기 버튼을 누르게 되면 Stack에서 pop되어서 이전 Activity가 Stack의 top에 위치하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;top 위치에 있는 Activity를 Foreground Activity라고 부르고, 포커스를 가질 수 있는 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Resumed 상태&lt;/b&gt;&lt;/span&gt;가 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나머지 Activity들은 화면에 보여지는지 여부에 따라 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Created 상태&lt;/b&gt;&lt;/span&gt;이거나 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Started 상태&lt;/b&gt;&lt;/span&gt;인 것이죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 사진을 보면 이해하기 쉽습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;687&quot; data-origin-height=&quot;213&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dkdQh1/btsGizfSVM7/GTnHYJocXM0NH2jKuHVSik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dkdQh1/btsGizfSVM7/GTnHYJocXM0NH2jKuHVSik/img.png&quot; data-alt=&quot;출처:https://developer.android.com/guide/components/activities/tasks-and-back-stack?hl=ko&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dkdQh1/btsGizfSVM7/GTnHYJocXM0NH2jKuHVSik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdkdQh1%2FbtsGizfSVM7%2FGTnHYJocXM0NH2jKuHVSik%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;687&quot; height=&quot;213&quot; data-origin-width=&quot;687&quot; data-origin-height=&quot;213&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처:https://developer.android.com/guide/components/activities/tasks-and-back-stack?hl=ko&lt;/figcaption&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;만약 동일한 Activity가 두번 뜨게 되면 어떻게 될까요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로는 Stack이 새롭게 정렬되는 것이 아니라, Activity의 새로운 인스턴스가 생성되어서 Back Stack에 추가됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;같은 Activity의 다른 인스턴스가 Back Stack에 들어가게 되는 것이고, 서로 다른 인스턴스인 만큼 UI도 각각 관리됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(엄밀히 말하면 Back Stack에는 Activity 자체가 들어가는게 아닌 &lt;u&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Activity로부터 생성된 인스턴스&lt;/b&gt;&lt;/span&gt;&lt;/u&gt;가 들어가는 것이죠. 하지만 편의상 Activity로 말하는 경우가 많습니다 ^^;;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 아래 사진처럼 중복된 Activity가 2개 들어갈 수도 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;357&quot; data-origin-height=&quot;266&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cEBPo6/btsGeO6Z56W/Wyk9EOBeglZvFbbzFvhk6K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cEBPo6/btsGeO6Z56W/Wyk9EOBeglZvFbbzFvhk6K/img.png&quot; data-alt=&quot;출처 :&amp;amp;amp;nbsp;https://developer.android.com/guide/components/activities/tasks-and-back-stack?hl=ko&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cEBPo6/btsGeO6Z56W/Wyk9EOBeglZvFbbzFvhk6K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcEBPo6%2FbtsGeO6Z56W%2FWyk9EOBeglZvFbbzFvhk6K%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;357&quot; height=&quot;266&quot; data-origin-width=&quot;357&quot; data-origin-height=&quot;266&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처 :&amp;amp;nbsp;https://developer.android.com/guide/components/activities/tasks-and-back-stack?hl=ko&lt;/figcaption&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;물론 Activity의 속성값이나 Intent 플래그를 통해서 하나의 Activity로부터 생성된 인스턴스는 반드시 하나만 존재하는 상태로 Back Stack에 들어가도록 조절하거나 할 수 있는데, 이 부분도 오늘 포스팅의 범위를 넘어가므로 관련 링크로 간단하게 넘어가도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1711985783060&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;작업 및 백 스택 &amp;nbsp;|&amp;nbsp; Android 개발자 &amp;nbsp;|&amp;nbsp; Android Developers&quot; data-og-description=&quot;작업은 사용자가 앱에서 어떤 작업을 하려고 할 때 상호작용하는 활동의 모음입니다. 이러한 활동은 스택(백 스택)에 각 활동이 열린 순서대로 정렬됩니다.&quot; data-og-host=&quot;developer.android.com&quot; data-og-source-url=&quot;https://developer.android.com/guide/components/activities/tasks-and-back-stack?hl=ko#ManagingTasks&quot; data-og-url=&quot;https://developer.android.com/guide/components/activities/tasks-and-back-stack?hl=ko&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/kBKaN/hyVGFM7GYj/tdKWw1DgzvQaf1JffVhBa0/img.png?width=550&amp;amp;height=309&amp;amp;face=0_0_550_309&quot;&gt;&lt;a href=&quot;https://developer.android.com/guide/components/activities/tasks-and-back-stack?hl=ko#ManagingTasks&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developer.android.com/guide/components/activities/tasks-and-back-stack?hl=ko#ManagingTasks&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/kBKaN/hyVGFM7GYj/tdKWw1DgzvQaf1JffVhBa0/img.png?width=550&amp;amp;height=309&amp;amp;face=0_0_550_309');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;작업 및 백 스택 &amp;nbsp;|&amp;nbsp; Android 개발자 &amp;nbsp;|&amp;nbsp; Android Developers&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;작업은 사용자가 앱에서 어떤 작업을 하려고 할 때 상호작용하는 활동의 모음입니다. 이러한 활동은 스택(백 스택)에 각 활동이 열린 순서대로 정렬됩니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;developer.android.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Activity의 상태를 설명하려다가 경로이탈을 엄청나게 해버렸네요 ^^;;;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이왕 이렇게 된거 상태에 대해서 하나하나 알아보기 전에&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제로 잘 구현이 되어있는지 여부도 코드로 직접 보고 넘어갑시다!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Androidx.lifecycle 패키지를 뜯어보면 아래와 같은 State 클래스를 볼 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;DESTROYED, INITIALIZED, CREATED, STARTED, RESUMED 이렇게 총 5개의 상태가 존재함을 알 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;s&gt;사실 아래 사진만 봐도 쉽게 이해 가능할 수도 있습니다 ^^;;&lt;/s&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;802&quot; data-origin-height=&quot;894&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nV5uM/btsGhRnTUwM/QR86qB6dFlfsy12fZpTeMK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nV5uM/btsGhRnTUwM/QR86qB6dFlfsy12fZpTeMK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nV5uM/btsGhRnTUwM/QR86qB6dFlfsy12fZpTeMK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnV5uM%2FbtsGhRnTUwM%2FQR86qB6dFlfsy12fZpTeMK%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;802&quot; height=&quot;894&quot; data-origin-width=&quot;802&quot; data-origin-height=&quot;894&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2.0. Initialized&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;LifecycleOwner에 의해서 처음으로 Activity가 만들어졌을 때의 상태입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메모리에 Actvitiy의 인스턴스가 올라가있는 최초의 상태이자, onCreate() 라는 생명주기함수가 동작하기 전의 상태입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 상태는 처음 Activity가 생성되었을 때만 존재하는, 즉 굉장히 짧은 시간만 존재하는 상태라고 볼 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2.1. Created&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;onCreate()&lt;/b&gt;&lt;/span&gt; 혹은 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;onStop()&lt;/b&gt;&lt;/span&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;Activity에 UI가 그려져서 화면에 보여질 준비가 된 상태를 의미합니다.&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 style=&quot;color: #006dd7;&quot;&gt;&lt;b&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;따라서 메모리가 꽉 찬 경우 Created된 Activity는 다른 상태들보다 메모리에서 우선 제거 대상이 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;게임 등 메모리를 많이 사용하는 작업을 하다가 다른 작업으로 넘어갔다가 다시 돌아가는 경우 게임과 같은 메모리를 많이 사용하는 작업이 강제로 재시작되는 경우가 있는데, 이 케이스가 바로 운영체제가 onStop() 생명주기함수에 의해 Created 상태가 된 Activity를 메모리에서 제거한 케이스입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2.2. Started&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;onStart()&lt;/b&gt;&lt;/span&gt; 혹은 &lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;onRestart()&lt;/span&gt;&lt;/b&gt; 가 동작한 직후의 상태입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또는 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;onPause()&lt;/b&gt;&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 style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;사용자가&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;Activity를 볼 수는 있으나&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;포커스를 가지지 않아서 입력할 수 없는 상태&lt;/span&gt;&lt;/b&gt;를 의미합니다.&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;사용자가 Activity를 더이상 볼 수 없게 된 경우에도&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;반드시 Started 상태를 거쳐서 Created 상태로 가게 됩니다.&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(onPause()와 onStop()이 모두 실행된다는 말과 동일합니다)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2.3. Resumed&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;onResume()&lt;/b&gt;&lt;/span&gt; 이 동작한 직후의 상태입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용자가 Activity와 상호작용할 수 있는 상태를 의미합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;사용자가 볼 수 있으며&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;,&amp;nbsp;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;포커스되어 있어서 입력을 받을 수 있는 상태&lt;/span&gt;&lt;/b&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;를 말합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2.4. Destroyed&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;onDestroy()&lt;/b&gt;&lt;/span&gt;&amp;nbsp;이 동작한 직후의 상태로, Activity가 종료된 경우를 의미합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Created 상태의 Activity가 운영체제에 의해 메모리에서 제거된 경우 역시 Destroyed 상태가 된다고 볼 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 사용하기 위해서는 재시작해야하는 것이죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 상태 역시 매우 짧은 시간만 존재하는 상태입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3. Activity의 생명주기함수&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에는 생명주기함수(생명주기메서드)입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;b&gt;Activity의 상태 변화에 따라 자동으로 실행되는 함수&lt;/b&gt;&lt;/u&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;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 사진은 androidx.lifecycle의 Event 클래스를 가져온 사진입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아까 분명히 onRestart()라는 생명주기함수가 있었는데..?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서는 onRestart가 없어서 의아할 수 있지만!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;682&quot; data-origin-height=&quot;940&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dHlzoZ/btsGgAto46j/1YMdWhdpiguMwSRYvUH6A1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dHlzoZ/btsGgAto46j/1YMdWhdpiguMwSRYvUH6A1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dHlzoZ/btsGgAto46j/1YMdWhdpiguMwSRYvUH6A1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdHlzoZ%2FbtsGgAto46j%2F1YMdWhdpiguMwSRYvUH6A1%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;682&quot; height=&quot;940&quot; data-origin-width=&quot;682&quot; data-origin-height=&quot;940&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;Activity 클래스 내부 구현 코드에는 아래와 같은 함수들이 정의되어있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기에는 onRestart가 존재하죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 나눠진 이유는 아래에서 더 자세하게 알아보겠습니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;894&quot; data-origin-height=&quot;412&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cH1EFC/btsGeQcEm8S/7ke4kCpoW52xk4WAEZsz4k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cH1EFC/btsGeQcEm8S/7ke4kCpoW52xk4WAEZsz4k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cH1EFC/btsGeQcEm8S/7ke4kCpoW52xk4WAEZsz4k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcH1EFC%2FbtsGeQcEm8S%2F7ke4kCpoW52xk4WAEZsz4k%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;894&quot; height=&quot;412&quot; data-origin-width=&quot;894&quot; data-origin-height=&quot;412&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3.0. onCreate()&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;Activity가 생성되었을 때 가장 먼저 호출&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;되는 함수입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;onDestroy()&lt;/b&gt;&lt;/span&gt;와 함께 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;전체 생명주기에서 단 한번만 수행되는 함수&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보통은 Layout을 정의하거나, View를 생성하고 DataBinding하는 부분들이 여기에 들어가게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매개변수에 savedInstanceState가 들어가는데, 만약 상태가 보관되어 있는 경우 이 번들 객체를 가져와서 사용할 수도 있습니다.&lt;/p&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: #f6e199;&quot;&gt;&lt;b&gt;onStart()&lt;/b&gt;&lt;/span&gt;가 따라나옵니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3.1. onStart()&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;Activity가 사용자에게 보여지기 직전, Started 상태로 가기 직전에 호출&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 바로 Foreground로 표시되어서 포커스를 가져가는 경우에는 &lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;onResume()&lt;/span&gt;&lt;/b&gt; 생명주기함수가 뒤따라 동작하게 됩니다.혹은 모종의 이유로 사용자에게 더이상 보여지지 않는 경우 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;onStop()&lt;/b&gt;&lt;/span&gt; 생명주기함수가 뒤따라 동작하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3.2. onRestart()&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;Activity가 사용자에게 보여지기 직전, Started 상태로 가기 직전에 호출&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;되는 것은 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;onStart()&lt;/b&gt;&lt;/span&gt;와 동일합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 &lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;onRestart()&lt;/b&gt;&lt;/span&gt;는 최초에 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;onCreate()&lt;/b&gt;&lt;/span&gt;에 뒤따라서 Started 상태로 가는 경우에는 호출되지 않고,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;u&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;onStop()&lt;/span&gt;이 된 이후에 새롭게 Started 상태로 가는 경우에만 동작&lt;/b&gt;&lt;/u&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;u&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;onStart()&lt;/span&gt;보다 항상 먼저 동작&lt;/b&gt;&lt;/span&gt;&lt;/u&gt;하고, &lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;함께 동작&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(onRestart만 동작되는 경우는 없습니다!)&lt;/p&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: #9feec3;&quot;&gt;&lt;b&gt;onRestart()&lt;/b&gt;&lt;/span&gt;의 주석을 보면 확인할 수 있죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(It will be followed by onStart~)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;712&quot; data-origin-height=&quot;351&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JnFGN/btsGi0YDlkB/3gsGErm7KZ7A75p9mY5pak/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JnFGN/btsGi0YDlkB/3gsGErm7KZ7A75p9mY5pak/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JnFGN/btsGi0YDlkB/3gsGErm7KZ7A75p9mY5pak/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJnFGN%2FbtsGi0YDlkB%2F3gsGErm7KZ7A75p9mY5pak%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;712&quot; height=&quot;351&quot; data-origin-width=&quot;712&quot; data-origin-height=&quot;351&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;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;onStop()&lt;/b&gt;&lt;/span&gt;의 구현을 봐도 다시 Activity가 Started 상태로 돌아가는 경우 onStart()가 아닌 onRestart()를 부른다는 것을 확인할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;399&quot; data-origin-height=&quot;361&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/csCDlY/btsGifPw064/TUKugitVhOU41zZX8wcpP0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/csCDlY/btsGifPw064/TUKugitVhOU41zZX8wcpP0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/csCDlY/btsGifPw064/TUKugitVhOU41zZX8wcpP0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcsCDlY%2FbtsGifPw064%2FTUKugitVhOU41zZX8wcpP0%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;399&quot; height=&quot;361&quot; data-origin-width=&quot;399&quot; data-origin-height=&quot;361&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: #9feec3;&quot;&gt;onRestart()&lt;/span&gt;&lt;/b&gt;가 동작하는 것은 항상 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;onStart()&lt;/b&gt;&lt;/span&gt;와 함께하기 때문에,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #9feec3;&quot;&gt;&lt;b&gt;onRestart()&lt;/b&gt;&lt;/span&gt;의 동작은 ON_START라는 이벤트로 함께 처리해도 무방하다고 볼수 있어서 위에서 확인한 Event 클래스에서는 ON_RESTART라는 이벤트를 만들지 않았다고 추측할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3.3. onResume()&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;Activity가 사용자의 포커스를 받을 수 있는 Resumed 상태가 되기 직전에 호출&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Resumed 상태에서 이어서 동작할 수 있는 생명주기함수는 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;onPause()&lt;/b&gt;&lt;/span&gt; 뿐입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3.4. onPause()&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;다른 Activity가 포커스를 받을 수 있는 Resumed 상태가 되었을 때 호출&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 다른 Activity에 의해서 화면에 보이지 않는 상태가 되었을 경우 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;onStop()&lt;/b&gt;&lt;/span&gt;이 이어서 호출됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 이 상태에서 다시 Activity가 활성화되어 포커스를 받을 수 있게 되는 경우 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;onResume()&lt;/b&gt;&lt;/span&gt;이 호출됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3.5. onStop()&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;Activity가&lt;/b&gt; &lt;/u&gt;&lt;u&gt;&lt;b&gt;사용자에게 더이상 보이지 않게 되는 경우 호출&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 Created 상태로 되돌아간 Activity가 사용자에게 화면을 보여주기 위해 Started 상태, 혹은 Resumed 상태로 가는 경우 &lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;onRestart()&lt;/span&gt; -&amp;gt; &lt;span style=&quot;background-color: #f6e199;&quot;&gt;onStart()&lt;/span&gt; -&amp;gt; &lt;span style=&quot;color: #ee2323;&quot;&gt;*&lt;/span&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;onResumed()&lt;/span&gt;&lt;/b&gt; 순서대로 생명주기함수가 실행됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;onResumed()&lt;/b&gt;&lt;/span&gt;는 Resumed 상태가 되는 경우에만 실행됩니다!)&lt;/p&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: #f6e199;&quot;&gt;&lt;b&gt;onDestroy()&lt;/b&gt;&lt;/span&gt;로 Activity가 삭제될 수도 있겠죠?!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3.6. onDestroy()&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;Activity가 메모리에서 사라지기 직전에 호출&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모종의 이유로 Activity가 finish() 처리 되었거나, 운영체제에 의해 강제로 메모리에서 할당해제되었을 경우 동작합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(이 두 케이스의 경우 isFinishing() 메서드를 통해서 구분할 수 있다고 합니다)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1711992311053&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Activity &amp;nbsp;|&amp;nbsp; Android Developers&quot; data-og-description=&quot;&quot; data-og-host=&quot;developer.android.com&quot; data-og-source-url=&quot;https://developer.android.com/reference/android/app/Activity#isFinishing()&quot; data-og-url=&quot;https://developer.android.com/reference/android/app/Activity&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bVGMzL/hyVJUhAdK5/qI0Wo1ysWbvvJzSe4d0bMk/img.png?width=1201&amp;amp;height=676&amp;amp;face=0_0_1201_676&quot;&gt;&lt;a href=&quot;https://developer.android.com/reference/android/app/Activity#isFinishing()&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developer.android.com/reference/android/app/Activity#isFinishing()&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bVGMzL/hyVJUhAdK5/qI0Wo1ysWbvvJzSe4d0bMk/img.png?width=1201&amp;amp;height=676&amp;amp;face=0_0_1201_676');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Activity &amp;nbsp;|&amp;nbsp; Android Developers&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;developer.android.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;onCreate()&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&quot;&gt;와 함께 &lt;/span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;전체 생명주기에서 단 한번만 수행되는 함수&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;&lt;span style=&quot;letter-spacing: 0px;&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;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;4. 정리&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금까지 Activity의 생명주기에 대해서 알아보았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 이야기했듯이, 생명주기를 모르는 상태에서 개발을 한다면 애플리케이션의 정상 동작을 보증하기 어렵고, 추후에 문제가 발생한다고 했을 때 문제 파악에 있어서 어려운 부분들이 발생할 여지가 굉장히 많습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러므로 조금이라도 헷갈리는 부분이 있다면 확실하게 알고 넘어가는 것이 훌륭한 애플리케이션을 만드는 데에 있어서 튼튼한 기반이 될 것이라고 생각합니다.&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;추가로 코드를 작성하면서 직접 Lifecycle에 대해서 이해해보고 싶은 분들이 있다면 아래 코드랩을 진행하시면 도움이 되실겁니다 ㅎㅎ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1711987538655&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Android 기초 02.2: Activity 수명 주기 및 상태 &amp;nbsp;|&amp;nbsp; Android Developers&quot; data-og-description=&quot;이 Codelab에서는 TwoActivities 앱에 로깅 문을 추가하고 활동 수명 주기 변경사항을 확인합니다. 이러한 변경사항을 사용하여 이러한 조건에서 사용자 입력을 처리하는 방법을 살펴봅니다.&quot; data-og-host=&quot;developer.android.com&quot; data-og-source-url=&quot;https://developer.android.com/codelabs/android-fundamentals-02-2-activity-lifecycle-and-state?hl=ko#0&quot; data-og-url=&quot;https://developer.android.com/codelabs/android-fundamentals-02-2-activity-lifecycle-and-state?hl=ko&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cfHcmF/hyVGP3kxfJ/IYEEsk5OK2K2q9DXddDD2k/img.png?width=900&amp;amp;height=1600&amp;amp;face=0_0_900_1600,https://scrap.kakaocdn.net/dn/B9oSe/hyVJZiTpxO/xUxEgGVPI7kpoINcGfd0J1/img.png?width=926&amp;amp;height=339&amp;amp;face=0_0_926_339,https://scrap.kakaocdn.net/dn/niFAE/hyVJ18P63T/oZTfmm7nqDcJpRFt9p2al0/img.png?width=662&amp;amp;height=295&amp;amp;face=0_0_662_295&quot;&gt;&lt;a href=&quot;https://developer.android.com/codelabs/android-fundamentals-02-2-activity-lifecycle-and-state?hl=ko#0&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developer.android.com/codelabs/android-fundamentals-02-2-activity-lifecycle-and-state?hl=ko#0&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cfHcmF/hyVGP3kxfJ/IYEEsk5OK2K2q9DXddDD2k/img.png?width=900&amp;amp;height=1600&amp;amp;face=0_0_900_1600,https://scrap.kakaocdn.net/dn/B9oSe/hyVJZiTpxO/xUxEgGVPI7kpoINcGfd0J1/img.png?width=926&amp;amp;height=339&amp;amp;face=0_0_926_339,https://scrap.kakaocdn.net/dn/niFAE/hyVJ18P63T/oZTfmm7nqDcJpRFt9p2al0/img.png?width=662&amp;amp;height=295&amp;amp;face=0_0_662_295');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Android 기초 02.2: Activity 수명 주기 및 상태 &amp;nbsp;|&amp;nbsp; Android Developers&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이 Codelab에서는 TwoActivities 앱에 로깅 문을 추가하고 활동 수명 주기 변경사항을 확인합니다. 이러한 변경사항을 사용하여 이러한 조건에서 사용자 입력을 처리하는 방법을 살펴봅니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;developer.android.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;5. 참고자료&lt;/b&gt;&lt;/h2&gt;
&lt;figure id=&quot;og_1711921252904&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Activity &amp;nbsp;|&amp;nbsp; Android Developers&quot; data-og-description=&quot;&quot; data-og-host=&quot;developer.android.com&quot; data-og-source-url=&quot;https://developer.android.com/reference/android/app/Activity&quot; data-og-url=&quot;https://developer.android.com/reference/android/app/Activity&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bypF54/hyVGHKKpCk/Vhv72MKgjLvbSFGHKSuKsk/img.png?width=1201&amp;amp;height=676&amp;amp;face=0_0_1201_676&quot;&gt;&lt;a href=&quot;https://developer.android.com/reference/android/app/Activity&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developer.android.com/reference/android/app/Activity&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bypF54/hyVGHKKpCk/Vhv72MKgjLvbSFGHKSuKsk/img.png?width=1201&amp;amp;height=676&amp;amp;face=0_0_1201_676');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Activity &amp;nbsp;|&amp;nbsp; Android Developers&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;developer.android.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1711921275777&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;blog&quot; data-og-title=&quot;안드로이드 기초&quot; data-og-description=&quot;안드로이드 액티비티의 라이프사이클을 알아보고 시스템에서 액티비티가 관리되는 방식과 라이프사이클 변화에 따라 개발자가 처리해 주어야 할 작업들을 배웁니다.&quot; data-og-host=&quot;dinfree.com&quot; data-og-source-url=&quot;https://dinfree.com/lecture/android/android_3.2.html&quot; data-og-url=&quot;https://dinfree.com/lecture/android/android_3.2.html&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bwcrsg/hyVGOXpGKS/B5clzmNjtRoS42QZcWusP0/img.png?width=1884&amp;amp;height=852&amp;amp;face=0_0_1884_852,https://scrap.kakaocdn.net/dn/cDdfqg/hyVJ5b8h04/bxXU399zv5Q7udadtvoIZK/img.png?width=666&amp;amp;height=334&amp;amp;face=0_0_666_334,https://scrap.kakaocdn.net/dn/cgrXiw/hyVJ3yCzMW/kyERKhTUK0wEUfMDypYbe1/img.png?width=662&amp;amp;height=295&amp;amp;face=0_0_662_295&quot;&gt;&lt;a href=&quot;https://dinfree.com/lecture/android/android_3.2.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://dinfree.com/lecture/android/android_3.2.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bwcrsg/hyVGOXpGKS/B5clzmNjtRoS42QZcWusP0/img.png?width=1884&amp;amp;height=852&amp;amp;face=0_0_1884_852,https://scrap.kakaocdn.net/dn/cDdfqg/hyVJ5b8h04/bxXU399zv5Q7udadtvoIZK/img.png?width=666&amp;amp;height=334&amp;amp;face=0_0_666_334,https://scrap.kakaocdn.net/dn/cgrXiw/hyVJ3yCzMW/kyERKhTUK0wEUfMDypYbe1/img.png?width=662&amp;amp;height=295&amp;amp;face=0_0_662_295');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;안드로이드 기초&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;안드로이드 액티비티의 라이프사이클을 알아보고 시스템에서 액티비티가 관리되는 방식과 라이프사이클 변화에 따라 개발자가 처리해 주어야 할 작업들을 배웁니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;dinfree.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1711986122672&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;작업 및 백 스택 &amp;nbsp;|&amp;nbsp; Android 개발자 &amp;nbsp;|&amp;nbsp; Android Developers&quot; data-og-description=&quot;작업은 사용자가 앱에서 어떤 작업을 하려고 할 때 상호작용하는 활동의 모음입니다. 이러한 활동은 스택(백 스택)에 각 활동이 열린 순서대로 정렬됩니다.&quot; data-og-host=&quot;developer.android.com&quot; data-og-source-url=&quot;https://developer.android.com/guide/components/activities/tasks-and-back-stack?hl=ko#ManagingTasks&quot; data-og-url=&quot;https://developer.android.com/guide/components/activities/tasks-and-back-stack?hl=ko&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/kBKaN/hyVGFM7GYj/tdKWw1DgzvQaf1JffVhBa0/img.png?width=550&amp;amp;height=309&amp;amp;face=0_0_550_309&quot;&gt;&lt;a href=&quot;https://developer.android.com/guide/components/activities/tasks-and-back-stack?hl=ko#ManagingTasks&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developer.android.com/guide/components/activities/tasks-and-back-stack?hl=ko#ManagingTasks&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/kBKaN/hyVGFM7GYj/tdKWw1DgzvQaf1JffVhBa0/img.png?width=550&amp;amp;height=309&amp;amp;face=0_0_550_309');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;작업 및 백 스택 &amp;nbsp;|&amp;nbsp; Android 개발자 &amp;nbsp;|&amp;nbsp; Android Developers&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;작업은 사용자가 앱에서 어떤 작업을 하려고 할 때 상호작용하는 활동의 모음입니다. 이러한 활동은 스택(백 스택)에 각 활동이 열린 순서대로 정렬됩니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;developer.android.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1711992395267&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;활동 수명 주기 단계 &amp;nbsp;|&amp;nbsp; Android Developers&quot; data-og-description=&quot;이 Codelab에서는 활동 수명 주기와 로깅을 알아봅니다.&quot; data-og-host=&quot;developer.android.com&quot; data-og-source-url=&quot;https://developer.android.com/codelabs/basic-android-kotlin-compose-activity-lifecycle?hl=ko&amp;amp;continue=https%3A%2F%2Fdeveloper.android.com%2Fcourses%2Fpathways%2Fandroid-basics-compose-unit-4-pathway-1%3Fhl%3Dko%23codelab-https%3A%2F%2Fdeveloper.android.com%2Fcodelabs%2Fbasic-android-kotlin-compose-activity-lifecycle&quot; data-og-url=&quot;https://developer.android.com/codelabs/basic-android-kotlin-compose-activity-lifecycle?hl=ko&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/iSRSv/hyVJVAM4zD/ZKNZKX2XK9D2IFfsyTxBjK/img.png?width=1200&amp;amp;height=1022&amp;amp;face=0_0_1200_1022,https://scrap.kakaocdn.net/dn/jtIfa/hyVGMleOuj/L4FoSOduk7HfwbHofQUFY0/img.png?width=758&amp;amp;height=1600&amp;amp;face=0_0_758_1600,https://scrap.kakaocdn.net/dn/ezEdXd/hyVGPCdC19/rlDnJd6CxryW2yJxDRmfo1/img.png?width=852&amp;amp;height=1126&amp;amp;face=0_0_852_1126&quot;&gt;&lt;a href=&quot;https://developer.android.com/codelabs/basic-android-kotlin-compose-activity-lifecycle?hl=ko&amp;amp;continue=https%3A%2F%2Fdeveloper.android.com%2Fcourses%2Fpathways%2Fandroid-basics-compose-unit-4-pathway-1%3Fhl%3Dko%23codelab-https%3A%2F%2Fdeveloper.android.com%2Fcodelabs%2Fbasic-android-kotlin-compose-activity-lifecycle&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developer.android.com/codelabs/basic-android-kotlin-compose-activity-lifecycle?hl=ko&amp;amp;continue=https%3A%2F%2Fdeveloper.android.com%2Fcourses%2Fpathways%2Fandroid-basics-compose-unit-4-pathway-1%3Fhl%3Dko%23codelab-https%3A%2F%2Fdeveloper.android.com%2Fcodelabs%2Fbasic-android-kotlin-compose-activity-lifecycle&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/iSRSv/hyVJVAM4zD/ZKNZKX2XK9D2IFfsyTxBjK/img.png?width=1200&amp;amp;height=1022&amp;amp;face=0_0_1200_1022,https://scrap.kakaocdn.net/dn/jtIfa/hyVGMleOuj/L4FoSOduk7HfwbHofQUFY0/img.png?width=758&amp;amp;height=1600&amp;amp;face=0_0_758_1600,https://scrap.kakaocdn.net/dn/ezEdXd/hyVGPCdC19/rlDnJd6CxryW2yJxDRmfo1/img.png?width=852&amp;amp;height=1126&amp;amp;face=0_0_852_1126');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;활동 수명 주기 단계 &amp;nbsp;|&amp;nbsp; Android Developers&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이 Codelab에서는 활동 수명 주기와 로깅을 알아봅니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;developer.android.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category># 공부 자료들/Android</category>
      <category>Activity</category>
      <category>Activity 상태</category>
      <category>activity 생명주기</category>
      <category>Android</category>
      <category>생명주기</category>
      <category>생명주기메서드</category>
      <category>생명주기함수</category>
      <author>Ssoco</author>
      <guid isPermaLink="true">https://ssocoit.tistory.com/275</guid>
      <comments>https://ssocoit.tistory.com/275#entry275comment</comments>
      <pubDate>Tue, 2 Apr 2024 03:06:45 +0900</pubDate>
    </item>
    <item>
      <title>[CSS] 모르면 평생 안쓸 미치도록 유용한 CSS 형제 결합자</title>
      <link>https://ssocoit.tistory.com/274</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;HTML과 CSS를 이용해서 연속된 요소들을 순서대로 나열할 때 정해진 수치만큼 padding이나 margin을 주는 경우가 아주아주 빈번하게 발생합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 과정에서 보통 첫 요소에는 padding이나 margin이 필요하지 않을 수 있는데, 이런 경우 전체에 padding 혹은 margin을 먹이고 덮어 씌우는 방법을 많이 사용하곤 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 &lt;span&gt;우리가 별로 신경써서 공부하지 않았던 요소를 사용한다면 이걸 훨씬 &lt;/span&gt;더 편하게, 그리고 효율적으로 구현할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바로 오늘 설명할 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;형제 결합자&lt;/b&gt;&lt;/span&gt;를 사용하는 방법입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class=&quot;book-toc&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;목차&lt;/p&gt;
&lt;ul id=&quot;toc&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;/ul&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;0. 결합자가 뭐지?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결합자가 뭔지 이해하기 전에, 선택자에 대해서 알 필요가 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;선택자&lt;/span&gt;&lt;/b&gt;는 &lt;b&gt;&lt;u&gt;CSS 규칙을 적용할 요소를 정의하는 데에 쓰이는 요소&lt;/u&gt;&lt;/b&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;조금 더 자세하게 말하면, CSS 속성값을 적용하기 위해 어떤 HTML 요소를 선택해야 할 지 브라우저에게 알려주는 패턴을 의미합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;본 글은 선택자의 기초부터 설명하기 위한 글은 아니기 때문에 어느 정도는 이미 알고 있고 사용했다는 가정하에 설명합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;보통 &lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;*&lt;/b&gt;&lt;/span&gt;를 사용해서 모든 요소를 선택하거나, &lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;class(&quot;.&quot;)&lt;/b&gt;&lt;/span&gt;나 &lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;id(&quot;#&quot;)&lt;/b&gt;&lt;/span&gt;를 통해 선택하곤 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1676385398438&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* 전체 선택자 */
* {
  color: brown;
}

/* 클래스 선택자 */
.ssoco_class {
  color: red;
}

/* 아이디 선택자 */
#ssoco_id {
  color: blue;
}&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;몇몇 CSS에 조예가 깊으신 분들은 &lt;b&gt;&lt;span style=&quot;color: #781b33;&quot;&gt;가상 클래스(&quot;:&quot;)&lt;/span&gt;&lt;/b&gt;, 혹은 &lt;span style=&quot;color: #1b711d;&quot;&gt;&lt;b&gt;가상 요소(&quot;::&quot;)&lt;/b&gt;&lt;/span&gt;를 사용하기도 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;특정 조건에 스타일을 입힐 때 사용&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;하는 &lt;span style=&quot;color: #781b33;&quot;&gt;&lt;b&gt;가상 클래스&lt;/b&gt;&lt;/span&gt;의 대표적인 예시로는 :hover,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;실제로 존재하지 않는 가상의 요소를 만들 때 사용&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;하는&lt;b&gt; &lt;span style=&quot;color: #1b711d;&quot;&gt;가상 요소&lt;/span&gt;&lt;/b&gt;의 대표적인 예시로는 ::after가 있습니다.&lt;/p&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;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;결합자&lt;/b&gt;&lt;/span&gt;라는 것을 쓸 수 있는데, &lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;여러 선택자들을 결합하여 사용할 수 있는 방법&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;을 말합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대표적으로 &lt;span style=&quot;color: #781b33;&quot;&gt;&lt;b&gt;자손 결합자 (&quot; &quot;)&lt;/b&gt;&lt;/span&gt;, &lt;span style=&quot;color: #1b711d;&quot;&gt;&lt;b&gt;자식 결합자 (&quot;&amp;lt;&quot;)&lt;/b&gt;&lt;/span&gt;를 많이 사용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #781b33;&quot;&gt;&lt;b&gt;자손 결합자&lt;/b&gt;&lt;/span&gt;는 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;첫 번째 요소의 자손인 요소를 모두 선택&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #1b711d;&quot;&gt;&lt;b&gt;자식 결합자&lt;/b&gt;&lt;/span&gt;는 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;첫 번째 요소의 바로 아래인 요소를 선택&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1676385521489&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;/* 자손 결합자 */
.ssoco_class .ssoco_inside_class {
  color: green;
}

/* 자식 결합자 */
.ssoco_class &amp;gt; span {
  color: yellow;
}&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;더 자세한 내용은 MDN 문서를 참조하시길 바랍니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1676386500568&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;CSS 선택자 - Web 개발 학습하기 | MDN&quot; data-og-description=&quot;CSS 에서, 선택자는 스타일을 지정할 웹 페이지의 HTML 요소를 대상으로 하는 데 사용됩니다. 사용 가능한 다양한 CSS 선택자가 있으며, 스타일을 지정할 요소를 선택할 때 세밀한 정밀도를 허용합&quot; data-og-host=&quot;developer.mozilla.org&quot; data-og-source-url=&quot;https://developer.mozilla.org/ko/docs/Learn/CSS/Building_blocks/Selectors&quot; data-og-url=&quot;https://developer.mozilla.org/ko/docs/Learn/CSS/Building_blocks/Selectors&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/c6d8Ll/hyRCZVBM7L/tMJ0LkAa0jiOXzFsYVhHE1/img.png?width=1920&amp;amp;height=1080&amp;amp;face=0_0_1920_1080,https://scrap.kakaocdn.net/dn/bhKegh/hyRC0fULsL/LJ1DUUrzqDQQkKzrNSDml0/img.png?width=471&amp;amp;height=218&amp;amp;face=0_0_471_218&quot;&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Learn/CSS/Building_blocks/Selectors&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developer.mozilla.org/ko/docs/Learn/CSS/Building_blocks/Selectors&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/c6d8Ll/hyRCZVBM7L/tMJ0LkAa0jiOXzFsYVhHE1/img.png?width=1920&amp;amp;height=1080&amp;amp;face=0_0_1920_1080,https://scrap.kakaocdn.net/dn/bhKegh/hyRC0fULsL/LJ1DUUrzqDQQkKzrNSDml0/img.png?width=471&amp;amp;height=218&amp;amp;face=0_0_471_218');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;CSS 선택자 - Web 개발 학습하기 | MDN&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;CSS 에서, 선택자는 스타일을 지정할 웹 페이지의 HTML 요소를 대상으로 하는 데 사용됩니다. 사용 가능한 다양한 CSS 선택자가 있으며, 스타일을 지정할 요소를 선택할 때 세밀한 정밀도를 허용합&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;developer.mozilla.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 문서를 참고하면, 우리가 안쓴다고 생각하고 간단하게 존재 여부만 파악하고 넘어가기 쉬운 형제 결합자들이 맨 마지막 쯤에 등장합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것들이 뭔지에 대해서 간단하게 알아보고 본론으로 넘어가겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;715&quot; data-origin-height=&quot;104&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dcahka/btrZei3oBuy/w6HjWQchOb0Lwq6KCbTJo1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dcahka/btrZei3oBuy/w6HjWQchOb0Lwq6KCbTJo1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dcahka/btrZei3oBuy/w6HjWQchOb0Lwq6KCbTJo1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdcahka%2FbtrZei3oBuy%2Fw6HjWQchOb0Lwq6KCbTJo1%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;715&quot; height=&quot;104&quot; data-origin-width=&quot;715&quot; data-origin-height=&quot;104&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;0.0. 인접 형제 결합자&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;인접 형제 결합자(&quot;+&quot;)&lt;/b&gt;&lt;/span&gt;는 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;앞에서 지정한 요소의 바로 다음에 위치하는 형제 요소만 선택하는 결합자&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1676387951792&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;div&amp;gt;
  &amp;lt;h1 class=&quot;ssoco_class&quot;&amp;gt;ㅎㅇㅎㅇ&amp;lt;/h1&amp;gt;
  &amp;lt;h2 class=&quot;next&quot;&amp;gt;hihi&amp;lt;/h2&amp;gt;
  &amp;lt;h2 class=&quot;next&quot;&amp;gt;하이하이&amp;lt;/h2&amp;gt;
&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1676387085054&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;.ssoco_class + .next {
  color: red;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1291&quot; data-origin-height=&quot;705&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bbmwUS/btrZjzbM1W4/sP0lkg7HqJt4vOerKssbmk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bbmwUS/btrZjzbM1W4/sP0lkg7HqJt4vOerKssbmk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bbmwUS/btrZjzbM1W4/sP0lkg7HqJt4vOerKssbmk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbbmwUS%2FbtrZjzbM1W4%2FsP0lkg7HqJt4vOerKssbmk%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;1291&quot; height=&quot;705&quot; data-origin-width=&quot;1291&quot; data-origin-height=&quot;705&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;0.1. 일반 형제 결합자&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;일반 형제 결합자(&quot;~&quot;)&lt;/b&gt;&lt;/span&gt;는 &lt;u&gt;&lt;b&gt;서로 형제인 요소 중에서 앞 요소 뒤에 뒤 요소가 존재하는 경우 전부 선택하는 결합자&lt;/b&gt;&lt;/u&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1676388048206&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;.ssoco_class ~ .next {
  color: red;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1294&quot; data-origin-height=&quot;687&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7lpfz/btrZj0AfEHJ/kdkgPUx836uc2QO3EtCAvk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7lpfz/btrZj0AfEHJ/kdkgPUx836uc2QO3EtCAvk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7lpfz/btrZj0AfEHJ/kdkgPUx836uc2QO3EtCAvk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7lpfz%2FbtrZj0AfEHJ%2FkdkgPUx836uc2QO3EtCAvk%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;1294&quot; height=&quot;687&quot; data-origin-width=&quot;1294&quot; data-origin-height=&quot;687&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. 인생은 실전&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;형제 결합자&lt;/b&gt;&lt;/span&gt;에 대해서 알아봤으니, &lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;실제로 어떻게 유용하게 써먹는 지&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;에 대해서 알아보도록 하겠습니다.&lt;/p&gt;
&lt;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;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;첫 번째 요소에는 마진과 같은 효과를 넣지 않고 싶은 경우&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;가 발생할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 포스팅의 도입부에서 이야기한 바로 그런 상황인 것이죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1676388494711&quot; class=&quot;html xml&quot; data-ke-language=&quot;html&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;div class=&quot;container&quot;&amp;gt;
  &amp;lt;span class=&quot;box&quot;&amp;gt;&amp;lt;/span&amp;gt;
  &amp;lt;span class=&quot;box&quot;&amp;gt;&amp;lt;/span&amp;gt;
  &amp;lt;span class=&quot;box&quot;&amp;gt;&amp;lt;/span&amp;gt;
  &amp;lt;span class=&quot;box&quot;&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;941&quot; data-origin-height=&quot;260&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/79Vgt/btrZlqyluVc/41xHUpTE2J1U6kYudLfKkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/79Vgt/btrZlqyluVc/41xHUpTE2J1U6kYudLfKkK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/79Vgt/btrZlqyluVc/41xHUpTE2J1U6kYudLfKkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F79Vgt%2FbtrZlqyluVc%2F41xHUpTE2J1U6kYudLfKkK%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;941&quot; height=&quot;260&quot; data-origin-width=&quot;941&quot; data-origin-height=&quot;260&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;위 HTML 코드를 CSS로 사진처럼 만드려면 어떻게 할 수 있을까요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;물론 HTML코드를 수정할 수도 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(inline-block으로 인해 발생하는 공백은 해당 포스팅의 내용과 관련이 없으니 무시하고 넘어가겠습니다!)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1676388886797&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;&amp;lt;div class=&quot;container&quot;&amp;gt;
  &amp;lt;span class=&quot;box first&quot;&amp;gt;&amp;lt;/span&amp;gt;
  &amp;lt;span class=&quot;box&quot;&amp;gt;&amp;lt;/span&amp;gt;
  &amp;lt;span class=&quot;box&quot;&amp;gt;&amp;lt;/span&amp;gt;
  &amp;lt;span class=&quot;box&quot;&amp;gt;&amp;lt;/span&amp;gt;
&amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1676388922503&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;.container {
  background-color: salmon;
  height: 150px;
  margin-top: 50px;
}

.box {
  display: inline-block;
  width: 150px;
  height: 150px;
  background-color: brown;
  margin-left: 30px;
}

.box.first {
  margin-left: 0;
}&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;하지만 코드의 크기가 커지고 이와 비슷한 로직이 반복되면 매번 HTML 코드를 새롭게 수정해야 할 것이기에 굉장히 비효율적일 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또는 HTML을 변경시키면 안되는 상황이라면 사용할 수 없을 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 단계 더 나아가서 가상 클래스를 사용한다면 아래와 같은 코드를 만들 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1676389139424&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;.container {
  background-color: salmon;
  height: 150px;
  margin-top: 50px;
}

.box {
  display: inline-block;
  width: 150px;
  height: 150px;
  background-color: brown;
  margin-left: 30px;
}

.box:first-child {
  margin-left: 0;
}&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;이렇게 전체에 마진을 먹이고 first-child에만 마진을 0으로 덮어씌우는 방법도 나쁘지 않지만, &lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;아예 처음부터 첫 요소를 제외한 나머지 요소에 편하게 CSS 규칙을 적용할 수 있는 방법&lt;/b&gt;&lt;/u&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: #000000;&quot;&gt;&lt;b&gt;형제 결합자&lt;/b&gt;&lt;/span&gt;, 그 중에서도 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;인접 형제 결합자&lt;/b&gt;&lt;/span&gt;를 사용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래와 같이 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;.box + .box&lt;/span&gt;&lt;/b&gt;&lt;/span&gt; 형태를 사용하면 box 클래스 뒤에 box 클래스가 있는 경우에 CSS 규칙이 적용되기에 보다 명확하고 깔끔하게 CSS를 적용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1676388576269&quot; class=&quot;css&quot; data-ke-language=&quot;css&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;.container {
  background-color: salmon;
  height: 150px;
  margin-top: 50px;
}

.box {
  display: inline-block;
  width: 150px;
  height: 150px;
  background-color: brown;
}

/* 인접 형제 결합자 사용 */
.box + .box {
  margin-left: 30px;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;922&quot; data-origin-height=&quot;815&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/N9LKb/btrZg8zrBfZ/K6ijikIF1dIstKov02aIi0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/N9LKb/btrZg8zrBfZ/K6ijikIF1dIstKov02aIi0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/N9LKb/btrZg8zrBfZ/K6ijikIF1dIstKov02aIi0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FN9LKb%2FbtrZg8zrBfZ%2FK6ijikIF1dIstKov02aIi0%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;922&quot; height=&quot;815&quot; data-origin-width=&quot;922&quot; data-origin-height=&quot;815&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;해당 케이스에서 일반 형제 결합자를 사용할 수도 있지만, 매번 뒤에 있는 모든 box 클래스 요소들을 중복해서 체크하는 불필요한 과정이 발생하기 때문에 일반적으로 인접 형제 결합자를 사용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제는 냅다 덮어씌우지 말고 보다 스마트하게 반복되는 CSS 규칙들을 처리해봅시다!!&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. 참고자료&lt;/b&gt;&lt;/h2&gt;
&lt;figure id=&quot;og_1676390067469&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Adjacent sibling combinator - CSS: Cascading Style Sheets | MDN&quot; data-og-description=&quot;The adjacent sibling combinator (+) separates two selectors and matches the second element only if it immediately follows the first element, and both are children of the same parent element.&quot; data-og-host=&quot;developer.mozilla.org&quot; data-og-source-url=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Adjacent_sibling_combinator&quot; data-og-url=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Adjacent_sibling_combinator&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Adjacent_sibling_combinator&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developer.mozilla.org/en-US/docs/Web/CSS/Adjacent_sibling_combinator&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Adjacent sibling combinator - CSS: Cascading Style Sheets | MDN&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;The adjacent sibling combinator (+) separates two selectors and matches the second element only if it immediately follows the first element, and both are children of the same parent element.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;developer.mozilla.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1676390106010&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;The Adjacent-Sibling Selector&quot; data-og-description=&quot;The Adjacent-Sibling Selector Web Review July 2000 As previous articles in this series have shown, CSS has some interesting new selectors. Between the universal selector and the child selector, it's possible to construct selectors which would be next to im&quot; data-og-host=&quot;meyerweb.com&quot; data-og-source-url=&quot;https://meyerweb.com/eric/articles/webrev/200007a.html&quot; data-og-url=&quot;https://meyerweb.com/eric/articles/webrev/200007a.html&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/r5HkC/hyRC1610rw/jZjn0MTS66zKG1F4GkJqTK/img.png?width=1040&amp;amp;height=330&amp;amp;face=0_0_1040_330,https://scrap.kakaocdn.net/dn/cC6Y6Q/hyRC4o9U0G/a07KKlWCTVpUsFo24U4PPK/img.png?width=1024&amp;amp;height=1024&amp;amp;face=0_0_1024_1024&quot;&gt;&lt;a href=&quot;https://meyerweb.com/eric/articles/webrev/200007a.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://meyerweb.com/eric/articles/webrev/200007a.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/r5HkC/hyRC1610rw/jZjn0MTS66zKG1F4GkJqTK/img.png?width=1040&amp;amp;height=330&amp;amp;face=0_0_1040_330,https://scrap.kakaocdn.net/dn/cC6Y6Q/hyRC4o9U0G/a07KKlWCTVpUsFo24U4PPK/img.png?width=1024&amp;amp;height=1024&amp;amp;face=0_0_1024_1024');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;The Adjacent-Sibling Selector&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;The Adjacent-Sibling Selector Web Review July 2000 As previous articles in this series have shown, CSS has some interesting new selectors. Between the universal selector and the child selector, it's possible to construct selectors which would be next to im&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;meyerweb.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category># 공부 자료들/HTML CSS</category>
      <category>css</category>
      <category>인접 형제 결합자</category>
      <category>일반 형제 결합자</category>
      <category>형제 결합자</category>
      <author>Ssoco</author>
      <guid isPermaLink="true">https://ssocoit.tistory.com/274</guid>
      <comments>https://ssocoit.tistory.com/274#entry274comment</comments>
      <pubDate>Wed, 15 Feb 2023 00:57:40 +0900</pubDate>
    </item>
    <item>
      <title>[Git] 이게 머지? Merge를 하는 세 가지 방식!</title>
      <link>https://ssocoit.tistory.com/273</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이번 소재거리는 친구들과 함께 Git에 대한 면접 질문으로 뭐가 나올 수 있을까에 대해서 고민을 하다가 우연히 등장했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;s&gt;딱 봐도 드립치기 좋아보이네요&lt;/s&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;협업할 때 대부분의 케이스에서 기본 Merge만 사용해왔던 저는&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style2&quot;&gt;기본 Merge로도 충분한데, 다른 건 나중에 공부하자~&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;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 이번 기회에 자세하게 알아보았습니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class=&quot;book-toc&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;목차&lt;/p&gt;
&lt;ul id=&quot;toc&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;/ul&gt;
&lt;/div&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;0. 머지에도 전략이 있다?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GitHub에서 Pull Request를 날릴 때 유심히 살펴봤다면, 아래와 같은 Merge 전략을 확인하실 수 있었을 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;s&gt;저는 알았음에도 바꾸지 않았지만&lt;/s&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;아래 사진으로 확인할 수 있듯이, 머지 전략에는 대표적으로 일반적인 Merge commit을 남기는 방법, Squash and merge, Rebase and merge 세 가지 방법이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;516&quot; data-origin-height=&quot;465&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uyJbn/btrVpfOPd3S/XnqqOrGG9L29yKbZ7SYRgK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uyJbn/btrVpfOPd3S/XnqqOrGG9L29yKbZ7SYRgK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uyJbn/btrVpfOPd3S/XnqqOrGG9L29yKbZ7SYRgK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuyJbn%2FbtrVpfOPd3S%2FXnqqOrGG9L29yKbZ7SYRgK%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;516&quot; height=&quot;465&quot; data-origin-width=&quot;516&quot; data-origin-height=&quot;465&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;/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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. 전략이 왜 필요한건데?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 잠깐, 대표적인 세 가지 전략을 살펴보기 전에 왜 저런 다양한 전략들을 사용해야 하는지부터 알아봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Merge가 뭔지 제대로 이해하기 위해서는 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;Commit&lt;/b&gt;&lt;/span&gt;에 대한 이해가 필요합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;Commit&lt;/span&gt;&lt;/b&gt;이란 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;&lt;u&gt;파일이나 폴더의 추가, 변경 사항을 저장소에 기록하는 행위&lt;/u&gt;&lt;/b&gt;&lt;/span&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 이러한 Commit들이 쌓여서 &lt;b&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;커밋 히스토리&lt;/span&gt;&lt;/b&gt;를 만들게 되는데, 이 &lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;커밋 히스토리&lt;/b&gt;&lt;/span&gt;를 통해 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;저장소 내에서 도대체 무슨 일이 벌어졌는지&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;에 대해서 알 수 있게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;663&quot; data-origin-height=&quot;282&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/W0yiz/btrVkWvWbq1/qE3iCTL0xrUG38UfSBDBk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/W0yiz/btrVkWvWbq1/qE3iCTL0xrUG38UfSBDBk0/img.png&quot; data-alt=&quot;최근 진행한 사이드프로젝트인 십이장기의 깃 그래프&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/W0yiz/btrVkWvWbq1/qE3iCTL0xrUG38UfSBDBk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FW0yiz%2FbtrVkWvWbq1%2FqE3iCTL0xrUG38UfSBDBk0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;663&quot; height=&quot;282&quot; data-origin-width=&quot;663&quot; data-origin-height=&quot;282&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;최근 진행한 사이드프로젝트인 십이장기의 깃 그래프&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;또한 협업할 때 다른 사람들이 남겨놓은 코드의 변경사항을 쉽게 파악하는 데에도 쓰입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시간 순서대로 나와있고, 해당 커밋에서 변경된 내용만 쉽게 파악할 수 있기 때문에 잘 이해가 안가거나 문제가 발생하더라도 해당 부분만 찾아서 확인할 수 있다는 어마어마한 효율성을 보여줄 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 이렇게 유용하게 쓸 수 있는 커밋 히스토리의 커밋 메시지를 대충 쓴다면 어떻게 될까요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;커밋 히스토리를 열심히 쌓아봐야 유지보수에도 아무 도움이 안되고 내가 무슨 내용을 했는지도 모르게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러면 커밋 히스토리를 쌓을 필요가 전혀 없어지게 되는 것이죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇기 때문에 우리는 &lt;u&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;의미있는 단위의 커밋&lt;/b&gt;&lt;/span&gt;&lt;/u&gt;을 하고 &lt;u&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;의미 있는 커밋 메시지&lt;/b&gt;&lt;/span&gt;&lt;/u&gt;를 작성해야 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;553&quot; data-origin-height=&quot;161&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JDVSr/btrVkfbem5B/iNYWqpVk6Gm7yYKKT22SWK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JDVSr/btrVkfbem5B/iNYWqpVk6Gm7yYKKT22SWK/img.png&quot; data-alt=&quot;이렇게 하시면 안돼요!&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JDVSr/btrVkfbem5B/iNYWqpVk6Gm7yYKKT22SWK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJDVSr%2FbtrVkfbem5B%2FiNYWqpVk6Gm7yYKKT22SWK%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;553&quot; height=&quot;161&quot; data-origin-width=&quot;553&quot; data-origin-height=&quot;161&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이렇게 하시면 안돼요!&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;아래 예시는 제가 Sooltreaming 개발을 하면서 만들어냈던 지하철 노선도(?) 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 시점에 개발을 할 때는 기본 Merge 전략만 사용했기 때문에 저런 그래프가 등장하게 되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 화려한 깃 그래프가 알아보기 엄청나게 어려운건 아니지만 조금 더 깔끔하게 정리할 수도 있었을 텐데 하는 아쉬움도 약간 드네요!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;468&quot; data-origin-height=&quot;405&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cXTZTg/btrVjPcOCI1/jjUdvjuRJX4qKKfEQOtM8K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cXTZTg/btrVjPcOCI1/jjUdvjuRJX4qKKfEQOtM8K/img.png&quot; data-alt=&quot;으악&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cXTZTg/btrVjPcOCI1/jjUdvjuRJX4qKKfEQOtM8K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcXTZTg%2FbtrVjPcOCI1%2FjjUdvjuRJX4qKKfEQOtM8K%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;468&quot; height=&quot;405&quot; data-origin-width=&quot;468&quot; data-origin-height=&quot;405&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;으악&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 이것들을 가독성 있게 만들기 위한 용도로 만들어진 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;머지 전략&lt;/b&gt;&lt;/span&gt;에 대해서 배워봅시다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. 세 가지 머지 전략&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2.0. Create a merge commit&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본 Merge라고도 불리는 &lt;span style=&quot;color: #1b711d;&quot;&gt;&lt;b&gt;Create a merge commit&lt;/b&gt;&lt;/span&gt;의 경우 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;각각의 브랜치에 남은 커밋을 히스토리에 그대로 남깁니다&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 어떤 브랜치에서 어떻게 만들어져서 이렇게 머지가 되었구나를 &lt;u&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;아주아주아주 상세하게 파악&lt;/b&gt;&lt;/span&gt;&lt;/u&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;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;git merge {머지할 브랜치}&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;577&quot; data-origin-height=&quot;227&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3hNpB/btrVqJhmGVT/k2KrzMnNSTXDQo3DoaHPMk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3hNpB/btrVqJhmGVT/k2KrzMnNSTXDQo3DoaHPMk/img.png&quot; data-alt=&quot;출처:https://meetup.nhncloud.com/posts/122&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3hNpB/btrVqJhmGVT/k2KrzMnNSTXDQo3DoaHPMk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3hNpB%2FbtrVqJhmGVT%2Fk2KrzMnNSTXDQo3DoaHPMk%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;577&quot; height=&quot;227&quot; data-origin-width=&quot;577&quot; data-origin-height=&quot;227&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처:https://meetup.nhncloud.com/posts/122&lt;/figcaption&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;별다른 HEAD 조작을 하지 않았다면 develop 혹은 main 브랜치가 맨 왼쪽에 위치해서 어찌어찌 따라갈 수 있을 지도 모르지만, 만약 HEAD가 밀려버리는 상황이 발생하게 되면 그래프의 순서가 꼬여버릴 수도 있게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러면 이제 develop 혹은 main 브랜치가 어디서부터 어디까지인지 눈알 빠지게 찾아버려야 하는 상황이 발생할 수도 있습니다...!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;380&quot; data-origin-height=&quot;301&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bvCvko/btrVsoKNsDP/b2CA5LAOaDmaMK30pb0FAk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bvCvko/btrVsoKNsDP/b2CA5LAOaDmaMK30pb0FAk/img.png&quot; data-alt=&quot;사실 얘도 출발은 하나였지만..&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bvCvko/btrVsoKNsDP/b2CA5LAOaDmaMK30pb0FAk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbvCvko%2FbtrVsoKNsDP%2Fb2CA5LAOaDmaMK30pb0FAk%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;380&quot; height=&quot;301&quot; data-origin-width=&quot;380&quot; data-origin-height=&quot;301&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;사실 얘도 출발은 하나였지만..&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2.1. Squash and merge&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Squash and merge&lt;/b&gt;&lt;/span&gt;는 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;개발용 브랜치에 있던 내용들을 하나로 합쳐서 중앙 브랜치에 하나의 커밋으로 저장하는 전략&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새롭게 발생하는 머지 커밋은 개발용 브랜치에서의 변경사항들을 하나도 뭉쳐놓은 커밋이 되는 것이죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;기존 변경사항들이 어떻게 변했는가보다 &lt;/span&gt;&lt;u&gt;&lt;b&gt;머지가 되었다&lt;/b&gt;&lt;/u&gt;&lt;span style=&quot;color: #333333;&quot;&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;Create a merge commit에 비해서 남아있는 정보량이 비교적 적기 때문에, &lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;개발용 브랜치에서 언제 어떤 코드를 바꿨는지에 대한 정보를 잃을 수 있다는 단점&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;도 가지고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(필요 없는 간단한 console.log 수정이나 버그 수정같은 것들을 뭉뚱그려서 합치는 데에 쓰일 수 있겠죠?)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;493&quot; data-origin-height=&quot;214&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bBNK1m/btrVo5r9pF5/9qrwyTxP3XGHwk7jpBQd8K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bBNK1m/btrVo5r9pF5/9qrwyTxP3XGHwk7jpBQd8K/img.png&quot; data-alt=&quot;출처:https://meetup.nhncloud.com/posts/122&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bBNK1m/btrVo5r9pF5/9qrwyTxP3XGHwk7jpBQd8K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbBNK1m%2FbtrVo5r9pF5%2F9qrwyTxP3XGHwk7jpBQd8K%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;493&quot; height=&quot;214&quot; data-origin-width=&quot;493&quot; data-origin-height=&quot;214&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처:https://meetup.nhncloud.com/posts/122&lt;/figcaption&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;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Squash and merge&lt;/b&gt;&lt;/span&gt;를 아까 만든 커밋메시지 테스트용 브랜치에 적용해보도록 하겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;s&gt;커밋 메시지는 따라하면 안됩니다&lt;/s&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;503&quot; data-origin-height=&quot;178&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cPGBe9/btrVjQQiWUx/0heW0e7hukbNflRZqwcGHK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cPGBe9/btrVjQQiWUx/0heW0e7hukbNflRZqwcGHK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cPGBe9/btrVjQQiWUx/0heW0e7hukbNflRZqwcGHK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcPGBe9%2FbtrVjQQiWUx%2F0heW0e7hukbNflRZqwcGHK%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;503&quot; height=&quot;178&quot; data-origin-width=&quot;503&quot; data-origin-height=&quot;178&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;이 상태에서 testBranch에서의 변경사항 3개를 하나로 뭉뚱그려서 처리할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;646&quot; data-origin-height=&quot;131&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ckgIf6/btrVqJuTmhU/6f5qFomBkMYzNedYo7blf0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ckgIf6/btrVqJuTmhU/6f5qFomBkMYzNedYo7blf0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ckgIf6/btrVqJuTmhU/6f5qFomBkMYzNedYo7blf0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FckgIf6%2FbtrVqJuTmhU%2F6f5qFomBkMYzNedYo7blf0%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;646&quot; height=&quot;131&quot; data-origin-width=&quot;646&quot; data-origin-height=&quot;131&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;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;git merge --squash {머지할 브랜치}&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;명령어를 쳤더니 staging area에 변경사항이 올라갔습니다. (아직 commit이 안된 상태)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 저장소에 새롭게 뭉뚱그린 커밋을 등록하기 위해 git commit -m &quot;커밋메시지&quot;만 하면 되겠네요!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;647&quot; data-origin-height=&quot;111&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b7Ms4e/btrVqfU43y8/56MWRPudEJK5nOJEqUtVX0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b7Ms4e/btrVqfU43y8/56MWRPudEJK5nOJEqUtVX0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b7Ms4e/btrVqfU43y8/56MWRPudEJK5nOJEqUtVX0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb7Ms4e%2FbtrVqfU43y8%2F56MWRPudEJK5nOJEqUtVX0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;647&quot; height=&quot;111&quot; data-origin-width=&quot;647&quot; data-origin-height=&quot;111&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Squash and merge는 이게 끝입니다. 간단하죠?!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;530&quot; data-origin-height=&quot;192&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JFChA/btrVk6SECIp/i76XrURHVClU3JCYn1CtQK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JFChA/btrVk6SECIp/i76XrURHVClU3JCYn1CtQK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JFChA/btrVk6SECIp/i76XrURHVClU3JCYn1CtQK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJFChA%2FbtrVk6SECIp%2Fi76XrURHVClU3JCYn1CtQK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;530&quot; height=&quot;192&quot; data-origin-width=&quot;530&quot; data-origin-height=&quot;192&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2.2. Rebase and merge&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;Rebase and merge&lt;/b&gt;&lt;/span&gt;는 말 그대로 이미 존재하는&amp;nbsp;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;Rebase&lt;/b&gt;&lt;/span&gt;라는 기능을 이용해서 브랜치를 머지하는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;히스토리의 Base를 직접 옮겨서 처리하는 방식&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;이기 때문에 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;개발용 브랜치에서 변경한 내용을 중앙 브랜치에서 변경한 것처럼 바꿔버릴 수 있습니다&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 본 Create a merge commit에서 만들어진 지하철을 한 줄로 예쁘게 만들 수 있다는 것이죠!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방식도 단점이 있는데, 바로 기본적으로 Merge commit이 없기 때문에 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;어느 시점에 Merge가 되었는지 나중에 판단하기 어렵다는 것&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이걸 보완하기 위해서 어디서 Merge가 되었는지 태그를 남겨놓기도 합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;696&quot; data-origin-height=&quot;220&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Dh6xR/btrVsnkO0IQ/7IIyoLuVp7QwKQfs2ZzHik/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Dh6xR/btrVsnkO0IQ/7IIyoLuVp7QwKQfs2ZzHik/img.png&quot; data-alt=&quot;출처:https://meetup.nhncloud.com/posts/122&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Dh6xR/btrVsnkO0IQ/7IIyoLuVp7QwKQfs2ZzHik/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FDh6xR%2FbtrVsnkO0IQ%2F7IIyoLuVp7QwKQfs2ZzHik%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;696&quot; height=&quot;220&quot; data-origin-width=&quot;696&quot; data-origin-height=&quot;220&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처:https://meetup.nhncloud.com/posts/122&lt;/figcaption&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;color: #ee2323;&quot;&gt;Rebase and merge&lt;/span&gt;&lt;/b&gt;도 실제로 테스트 해 보죠!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 초기 상태로 돌아왔고, testBranch2에 커밋을 더 쌓아보았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;381&quot; data-origin-height=&quot;180&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bUU9TE/btrVpeCoFTW/CEy3fESo5HGljZtgupZOJk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bUU9TE/btrVpeCoFTW/CEy3fESo5HGljZtgupZOJk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bUU9TE/btrVpeCoFTW/CEy3fESo5HGljZtgupZOJk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbUU9TE%2FbtrVpeCoFTW%2FCEy3fESo5HGljZtgupZOJk%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;381&quot; height=&quot;180&quot; data-origin-width=&quot;381&quot; data-origin-height=&quot;180&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;testBranch의 base를 testBranch2로 바꿔버렸습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;647&quot; data-origin-height=&quot;190&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vJxc2/btrVo5lmmP6/DrYDbNbGg3Zh7aGKOVEZtK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vJxc2/btrVo5lmmP6/DrYDbNbGg3Zh7aGKOVEZtK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vJxc2/btrVo5lmmP6/DrYDbNbGg3Zh7aGKOVEZtK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvJxc2%2FbtrVo5lmmP6%2FDrYDbNbGg3Zh7aGKOVEZtK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;647&quot; height=&quot;190&quot; data-origin-width=&quot;647&quot; data-origin-height=&quot;190&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(base가 testBranch2와 같기 때문에 2줄일 필요가 없어진 것이죠!)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;294&quot; data-origin-height=&quot;172&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/t3mif/btrVsmTLdmf/kDdJ4borwHugRgie2iGF30/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/t3mif/btrVsmTLdmf/kDdJ4borwHugRgie2iGF30/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/t3mif/btrVsmTLdmf/kDdJ4borwHugRgie2iGF30/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Ft3mif%2FbtrVsmTLdmf%2FkDdJ4borwHugRgie2iGF30%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;294&quot; height=&quot;172&quot; data-origin-width=&quot;294&quot; data-origin-height=&quot;172&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;이제 testBranch2로 넘어가서 testBranch와 merge를 하게 되면?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순히 해당 Branch의 HEAD의 위치만 바꾸는 Fast-forward가 수행되어 머지가 마무리됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;253&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eBYgQw/btrVpZEKeM0/lUTiRQslaZIAIwOfYHH461/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eBYgQw/btrVpZEKeM0/lUTiRQslaZIAIwOfYHH461/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eBYgQw/btrVpZEKeM0/lUTiRQslaZIAIwOfYHH461/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeBYgQw%2FbtrVpZEKeM0%2FlUTiRQslaZIAIwOfYHH461%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;640&quot; height=&quot;253&quot; data-origin-width=&quot;640&quot; data-origin-height=&quot;253&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아주아주아주 깔끔해졌습니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;408&quot; data-origin-height=&quot;207&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/chHZis/btrVpgAeTm7/77gRXFXdn0GdgnBHp8icfK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/chHZis/btrVpgAeTm7/77gRXFXdn0GdgnBHp8icfK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/chHZis/btrVpgAeTm7/77gRXFXdn0GdgnBHp8icfK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FchHZis%2FbtrVpgAeTm7%2F77gRXFXdn0GdgnBHp8icfK%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;408&quot; height=&quot;207&quot; data-origin-width=&quot;408&quot; data-origin-height=&quot;207&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;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;git rebase -i HEAD~&amp;lt;n&amp;gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;명령어를 통해 rebase의 기능을 활용해서 커밋 메시지를 변경시키는 방법을 사용하셔도 좋습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(위 코드는 HEAD로부터 n번째 커밋까지 불러와서 대화형 명령(-i)을 통해 커밋을 이리저리 바꾸겠다는 말입니다)&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3. 3-way merge와 Fast-forward merge&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 세 가지 머지 전략에 대해서 살펴봤는데, 조금 더 깊게 생각했다면 병합을 도대체 어떻게 처리할까? 라는 고민까지 충분히 하셨을 것이라고 생각합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;위에서 살짝 언급한&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;Fast-forward merge&lt;/span&gt;&lt;/b&gt;와 함께 브랜치를 합치는 로직인 &lt;span style=&quot;color: #781b33;&quot;&gt;&lt;b&gt;3-way merge&lt;/b&gt;&lt;/span&gt;를 간단하게 알아보고 넘어가려고 합니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3.0. Fast-forward merge&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 간단하게 언급했지만, 서로 다른 상태를 병합하는 것이 아니라 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;단순히 HEAD만 이동시키면 Merge가 처리될 수 있는 환경&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;에서는 &lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;Fast-forward merge&lt;/b&gt;&lt;/span&gt;가 수행됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 상황에서는 단순히 testBranch2의 HEAD를 testBranch로 옮기기만 하면 되는 것이죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위에서 사용한 사진 2개를 모아 보면 간단히 파악할 수 있습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/t3mif/btrVsmTLdmf/kDdJ4borwHugRgie2iGF30/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/t3mif/btrVsmTLdmf/kDdJ4borwHugRgie2iGF30/img.png&quot; data-origin-width=&quot;294&quot; data-origin-height=&quot;172&quot; data-is-animation=&quot;false&quot; style=&quot;width: 45.9044%; margin-right: 10px;&quot; data-widthpercent=&quot;46.44&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/t3mif/btrVsmTLdmf/kDdJ4borwHugRgie2iGF30/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Ft3mif%2FbtrVsmTLdmf%2FkDdJ4borwHugRgie2iGF30%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;294&quot; height=&quot;172&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/chHZis/btrVpgAeTm7/77gRXFXdn0GdgnBHp8icfK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/chHZis/btrVpgAeTm7/77gRXFXdn0GdgnBHp8icfK/img.png&quot; data-origin-width=&quot;408&quot; data-origin-height=&quot;207&quot; data-is-animation=&quot;false&quot; style=&quot;width: 52.9328%;&quot; data-widthpercent=&quot;53.56&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/chHZis/btrVpgAeTm7/77gRXFXdn0GdgnBHp8icfK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FchHZis%2FbtrVpgAeTm7%2F77gRXFXdn0GdgnBHp8icfK%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;408&quot; height=&quot;207&quot;/&gt;&lt;/span&gt;&lt;/div&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;Fast-forward와 관련해서 특별하게 처리할 수 있는 명령어가 두 가지 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;병합 대상 브랜치와 현재 브랜치와의 관계가 Fast-forward라고 하더라도 머지 커밋을 남기고 싶다면 아래 명령어를 사용합니다. (&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;Rebase and merge&lt;/b&gt;&lt;/span&gt;를 할 때 머지했다는 커밋 메시지를 남기고 싶다면 이걸 쓰면 됩니다!)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;git merge --no-ff {머지할 브랜치}&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반대로 Fast-forward가 아니면 머지를 하지 않고 싶다면 아래 명령어를 사용하면 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;git merge --ff-only {머지할 브랜치}&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;3.1. 3-way merge&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 세상은 이렇게 단순하지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;매우 높은 확률로 두 명의 개발자는 서로 다른 내용을 바꿨을 것이고, 지금처럼 HEAD만 옮겨서는 제대로 머지가 되지 않는 상황이 발생하게 됩니다.&lt;/p&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: #781b33;&quot;&gt;&lt;b&gt;3-way merge&lt;/b&gt;&lt;/span&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 1번 브랜치와 2번 브랜치가 병합을 한다고 하면, &lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;총 세 가지 커밋을 서로 비교&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;하게 됩니다.&lt;/p&gt;
&lt;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;1번 브랜치 커밋&lt;/li&gt;
&lt;li&gt;2번 브랜치 커밋&lt;/li&gt;
&lt;li&gt;1번 브랜치와 2번 브랜치의 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;공통 조상 커밋&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;만약 &lt;span style=&quot;color: #333333;&quot;&gt;단순하게 1번 브랜치와 2번 브랜치의 현재 상태만 비교(&lt;span style=&quot;color: #1a5490;&quot;&gt;&lt;b&gt;2-way merge&lt;/b&gt;&lt;/span&gt;)&lt;/span&gt;한다면, 어떤 요소가 어떻게 변했는 지, 혹은 두 브랜치가 충돌해서 병합할 수 없는 상태인 지 알 방법이 없습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;b와 b'를 비교했을 때 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;b가 원본임을 증명할 수 있는 방법이 없는 것&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;이죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;616&quot; data-origin-height=&quot;319&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1kboX/btrVpEAOMRf/IWK18jFu4FG7KYNK5sxvU1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1kboX/btrVpEAOMRf/IWK18jFu4FG7KYNK5sxvU1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1kboX/btrVpEAOMRf/IWK18jFu4FG7KYNK5sxvU1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1kboX%2FbtrVpEAOMRf%2FIWK18jFu4FG7KYNK5sxvU1%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;616&quot; height=&quot;319&quot; data-origin-width=&quot;616&quot; data-origin-height=&quot;319&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;공통 조상&lt;/b&gt;&lt;/span&gt;을 가져와보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 공통 조상을 기준으로 변동사항을 파악한다면 충돌 여부를 명확하게 알 수 있게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;a의 경우 변동사항이 없었으니 그대로 a가 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 b의 경우 원본에서 변경된 내용이 2번 브랜치한테만 있으니 2번 브랜치의 b'가 결과값이 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 c의 경우 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;두 브랜치에서 모두 변경&lt;/b&gt;&lt;/span&gt;되었기 때문에 결과를 c'로 해야할 지, c''로 해야할 지 알 수 없기 때문에 충돌이 난다는 것을 확실하게 알 수 있는 것이죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;859&quot; data-origin-height=&quot;405&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/XomAz/btrVpDBWaAw/xmd5fDxlCfAjnfN4SvC1J1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/XomAz/btrVpDBWaAw/xmd5fDxlCfAjnfN4SvC1J1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/XomAz/btrVpDBWaAw/xmd5fDxlCfAjnfN4SvC1J1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FXomAz%2FbtrVpDBWaAw%2Fxmd5fDxlCfAjnfN4SvC1J1%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;859&quot; height=&quot;405&quot; data-origin-width=&quot;859&quot; data-origin-height=&quot;405&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;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;세 개의 커밋을 비교해서 머지를 진행한다는 뜻&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;을 가진 용어가 바로 &lt;span style=&quot;color: #781b33;&quot;&gt;&lt;b&gt;3-way merge&lt;/b&gt;&lt;/span&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;4. 참고자료&lt;/b&gt;&lt;/h2&gt;
&lt;figure id=&quot;og_1672855623977&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;[Git] Merge(3-way merge) 이해하기  - SW Developer&quot; data-og-description=&quot;다른 형상 관리툴들과는 달리 git은 branch를 생성할 때 파일을 복사하는 것이 아니라 파일의 스냅샷만 가지고 생성하기 때문에 자원의 부담없이 branch를 만들어 사용할 수 있다. 이러한 장점 때문&quot; data-og-host=&quot;wonyong-jang.github.io&quot; data-og-source-url=&quot;https://wonyong-jang.github.io/git/2021/02/05/Github-Merge.html&quot; data-og-url=&quot;https://wonyong-jang.github.io/git/2021/02/05/Github-Merge.html&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cyXpkp/hyQ8VmOiqP/TFJOK3Yzs6ftaOgckuAjDk/img.png?width=1542&amp;amp;height=692&amp;amp;face=0_0_1542_692,https://scrap.kakaocdn.net/dn/bkULTT/hyQ8ZCNHT7/WoMb24K4KGvBzGASyv4HnK/img.png?width=1496&amp;amp;height=694&amp;amp;face=0_0_1496_694,https://scrap.kakaocdn.net/dn/vLA4T/hyRatvtR9t/39gfnSDprjk636sKBkANq0/img.png?width=1186&amp;amp;height=658&amp;amp;face=0_0_1186_658&quot;&gt;&lt;a href=&quot;https://wonyong-jang.github.io/git/2021/02/05/Github-Merge.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://wonyong-jang.github.io/git/2021/02/05/Github-Merge.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cyXpkp/hyQ8VmOiqP/TFJOK3Yzs6ftaOgckuAjDk/img.png?width=1542&amp;amp;height=692&amp;amp;face=0_0_1542_692,https://scrap.kakaocdn.net/dn/bkULTT/hyQ8ZCNHT7/WoMb24K4KGvBzGASyv4HnK/img.png?width=1496&amp;amp;height=694&amp;amp;face=0_0_1496_694,https://scrap.kakaocdn.net/dn/vLA4T/hyRatvtR9t/39gfnSDprjk636sKBkANq0/img.png?width=1186&amp;amp;height=658&amp;amp;face=0_0_1186_658');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[Git] Merge(3-way merge) 이해하기 - SW Developer&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;다른 형상 관리툴들과는 달리 git은 branch를 생성할 때 파일을 복사하는 것이 아니라 파일의 스냅샷만 가지고 생성하기 때문에 자원의 부담없이 branch를 만들어 사용할 수 있다. 이러한 장점 때문&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;wonyong-jang.github.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1672855708396&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;커밋 히스토리를 이쁘게 단장하자&quot; data-og-description=&quot;이번 포스팅에서는 Git의 머지 전략 중 대표적인 3가지인 , , 의 차이에 대해서 한번 이야기해보려고 한다. 이 3가지 머지 전략 모두 브랜치를 머지한다는 목적은 같지만, 어떤 방식을 선택하냐에 &quot; data-og-host=&quot;evan-moon.github.io&quot; data-og-source-url=&quot;https://evan-moon.github.io/2019/08/30/commit-history-merge-strategy/&quot; data-og-url=&quot;https://evan-moon.github.io/2019/08/30/commit-history-merge-strategy/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/VmXsq/hyRaFbBov4/kRP7KCEA4ltvAtpbTGLTak/img.jpg?width=800&amp;amp;height=450&amp;amp;face=0_0_800_450,https://scrap.kakaocdn.net/dn/d8UAfj/hyQ8VNTzXx/n6lvK9VKHaldbHUY0uGUr1/img.jpg?width=800&amp;amp;height=450&amp;amp;face=0_0_800_450,https://scrap.kakaocdn.net/dn/buWHv4/hyQ86vbjzC/xz1kKjUZNPaQjf8sR2lrP1/img.png?width=640&amp;amp;height=365&amp;amp;face=0_0_640_365&quot;&gt;&lt;a href=&quot;https://evan-moon.github.io/2019/08/30/commit-history-merge-strategy/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://evan-moon.github.io/2019/08/30/commit-history-merge-strategy/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/VmXsq/hyRaFbBov4/kRP7KCEA4ltvAtpbTGLTak/img.jpg?width=800&amp;amp;height=450&amp;amp;face=0_0_800_450,https://scrap.kakaocdn.net/dn/d8UAfj/hyQ8VNTzXx/n6lvK9VKHaldbHUY0uGUr1/img.jpg?width=800&amp;amp;height=450&amp;amp;face=0_0_800_450,https://scrap.kakaocdn.net/dn/buWHv4/hyQ86vbjzC/xz1kKjUZNPaQjf8sR2lrP1/img.png?width=640&amp;amp;height=365&amp;amp;face=0_0_640_365');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;커밋 히스토리를 이쁘게 단장하자&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이번 포스팅에서는 Git의 머지 전략 중 대표적인 3가지인 , , 의 차이에 대해서 한번 이야기해보려고 한다. 이 3가지 머지 전략 모두 브랜치를 머지한다는 목적은 같지만, 어떤 방식을 선택하냐에&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;evan-moon.github.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1672855631208&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;GitHub의 Merge, Squash and Merge, Rebase and Merge 정확히 이해하기 : NHN Cloud Meetup&quot; data-og-description=&quot;GitHub의 Merge, Squash and Merge, Rebase and Merge 정확히 이해하기&quot; data-og-host=&quot;meetup.nhncloud.com&quot; data-og-source-url=&quot;https://meetup.nhncloud.com/posts/122&quot; data-og-url=&quot;https://meetup.toast.com/posts/122&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/OUD6s/hyQ8XEX9js/QjwEDjVZMphMJYDdweCed1/img.png?width=489&amp;amp;height=204&amp;amp;face=0_0_489_204,https://scrap.kakaocdn.net/dn/HUUnx/hyQ82M2dSx/hbsW9AD2pTanDeSxMFwAbk/img.png?width=489&amp;amp;height=204&amp;amp;face=0_0_489_204&quot;&gt;&lt;a href=&quot;https://meetup.nhncloud.com/posts/122&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://meetup.nhncloud.com/posts/122&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/OUD6s/hyQ8XEX9js/QjwEDjVZMphMJYDdweCed1/img.png?width=489&amp;amp;height=204&amp;amp;face=0_0_489_204,https://scrap.kakaocdn.net/dn/HUUnx/hyQ82M2dSx/hbsW9AD2pTanDeSxMFwAbk/img.png?width=489&amp;amp;height=204&amp;amp;face=0_0_489_204');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub의 Merge, Squash and Merge, Rebase and Merge 정확히 이해하기 : NHN Cloud Meetup&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;GitHub의 Merge, Squash and Merge, Rebase and Merge 정확히 이해하기&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;meetup.nhncloud.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1672855671338&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[Git] Merge 이해하기 (Merge / Squash and Merge / Rebase and Merge)&quot; data-og-description=&quot;회사에서 Git을 사용해서 형상 관리를 하고 있다. 그 동안 내가 개인 repository branch에 commit, push등을 해본 적은 많지만 다른 사람과 협업을 하면서 branch를 생성하고 master에 merge를 해본 적은 없어서&quot; data-og-host=&quot;im-developer.tistory.com&quot; data-og-source-url=&quot;https://im-developer.tistory.com/182&quot; data-og-url=&quot;https://im-developer.tistory.com/182&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/vCMaw/hyQ8V8dPFs/Xa9Z96AWhR96qwrTNOe9JK/img.jpg?width=308&amp;amp;height=210&amp;amp;face=0_0_308_210,https://scrap.kakaocdn.net/dn/fXWKr/hyRaGBArA2/Aw6rspFP6By5sS6M7w6ANK/img.jpg?width=308&amp;amp;height=210&amp;amp;face=0_0_308_210,https://scrap.kakaocdn.net/dn/cLbXn7/hyQ8VmOiVj/zAmvVxQ0GthDDp2BYcaJRk/img.jpg?width=1449&amp;amp;height=912&amp;amp;face=0_0_1449_912&quot;&gt;&lt;a href=&quot;https://im-developer.tistory.com/182&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://im-developer.tistory.com/182&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/vCMaw/hyQ8V8dPFs/Xa9Z96AWhR96qwrTNOe9JK/img.jpg?width=308&amp;amp;height=210&amp;amp;face=0_0_308_210,https://scrap.kakaocdn.net/dn/fXWKr/hyRaGBArA2/Aw6rspFP6By5sS6M7w6ANK/img.jpg?width=308&amp;amp;height=210&amp;amp;face=0_0_308_210,https://scrap.kakaocdn.net/dn/cLbXn7/hyQ8VmOiVj/zAmvVxQ0GthDDp2BYcaJRk/img.jpg?width=1449&amp;amp;height=912&amp;amp;face=0_0_1449_912');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[Git] Merge 이해하기 (Merge / Squash and Merge / Rebase and Merge)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;회사에서 Git을 사용해서 형상 관리를 하고 있다. 그 동안 내가 개인 repository branch에 commit, push등을 해본 적은 많지만 다른 사람과 협업을 하면서 branch를 생성하고 master에 merge를 해본 적은 없어서&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;im-developer.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1672855690530&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Git Merge에서 Fast Forward 관계 이해하기 - Jay's Blog&quot; data-og-description=&quot;Git Merge에서 항상 헷갈리는 Fast Forward 관계에 대해 정리해보았습니다.   들어가며 Git을 사용하다보면 브랜치를 분기하여 다시 병합하는 일이 빈번하게 일어납니다. 최근 Git 커밋 히스토리 관리&quot; data-og-host=&quot;otzslayer.github.io&quot; data-og-source-url=&quot;https://otzslayer.github.io/git/2021/12/05/git-merge-fast-forward.html&quot; data-og-url=&quot;https://otzslayer.github.io/git/2021/12/05/git-merge-fast-forward.html&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dmVaGy/hyRayp12BW/O5QJmxRkopuOM8uRST4suK/img.png?width=2254&amp;amp;height=708&amp;amp;face=0_0_2254_708,https://scrap.kakaocdn.net/dn/Sq8zu/hyQ8WMPRYI/cAIagkUSz7B1sBAK7iCkhk/img.png?width=2138&amp;amp;height=574&amp;amp;face=0_0_2138_574,https://scrap.kakaocdn.net/dn/cnSibB/hyRaAnRk7r/tONEzNKRQKWQkZZrzJOVxk/img.png?width=2138&amp;amp;height=574&amp;amp;face=0_0_2138_574&quot;&gt;&lt;a href=&quot;https://otzslayer.github.io/git/2021/12/05/git-merge-fast-forward.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://otzslayer.github.io/git/2021/12/05/git-merge-fast-forward.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dmVaGy/hyRayp12BW/O5QJmxRkopuOM8uRST4suK/img.png?width=2254&amp;amp;height=708&amp;amp;face=0_0_2254_708,https://scrap.kakaocdn.net/dn/Sq8zu/hyQ8WMPRYI/cAIagkUSz7B1sBAK7iCkhk/img.png?width=2138&amp;amp;height=574&amp;amp;face=0_0_2138_574,https://scrap.kakaocdn.net/dn/cnSibB/hyRaAnRk7r/tONEzNKRQKWQkZZrzJOVxk/img.png?width=2138&amp;amp;height=574&amp;amp;face=0_0_2138_574');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Git Merge에서 Fast Forward 관계 이해하기 - Jay's Blog&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Git Merge에서 항상 헷갈리는 Fast Forward 관계에 대해 정리해보았습니다.   들어가며 Git을 사용하다보면 브랜치를 분기하여 다시 병합하는 일이 빈번하게 일어납니다. 최근 Git 커밋 히스토리 관리&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;otzslayer.github.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;</description>
      <category># 공부 자료들/Git</category>
      <category>Git</category>
      <category>git merge</category>
      <category>merge</category>
      <category>rebase</category>
      <category>Rebase merge</category>
      <category>squash</category>
      <category>Squash merge</category>
      <category>깃 머지</category>
      <category>머지</category>
      <category>머지전략</category>
      <author>Ssoco</author>
      <guid isPermaLink="true">https://ssocoit.tistory.com/273</guid>
      <comments>https://ssocoit.tistory.com/273#entry273comment</comments>
      <pubDate>Thu, 5 Jan 2023 03:13:29 +0900</pubDate>
    </item>
    <item>
      <title>[뻘] CI/CD 입문! 자율 프로젝트 꽃바다 회고</title>
      <link>https://ssocoit.tistory.com/272</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;433&quot; data-origin-height=&quot;937&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bNy9Mi/btrTt1kkUL2/EdrO37SimhmKOEFY9V7cr1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bNy9Mi/btrTt1kkUL2/EdrO37SimhmKOEFY9V7cr1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bNy9Mi/btrTt1kkUL2/EdrO37SimhmKOEFY9V7cr1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbNy9Mi%2FbtrTt1kkUL2%2FEdrO37SimhmKOEFY9V7cr1%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;229&quot; height=&quot;496&quot; data-origin-width=&quot;433&quot; data-origin-height=&quot;937&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2022년, 1년 간의 추억을 되돌아보며 실물 롤링페이퍼 및 꽃배달 서비스를 기획하고 개발하게 되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(현재는 프로젝트 기간이 종료되어 공식적으로 제공되는 AWS 서버가 회수되었지만, 비공식적으로 팀원들끼리 AWS 서버를 한대 구매해서 이것저것 시도해보고 있습니다 ㅎㅎ)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;이번 프로젝트에서는 어떤 걸 했고 무엇을 배웠으며 어떤 부분에 대해 보충해야 할 지&lt;/b&gt;&lt;/span&gt;에 대해서 간단하게 정리해보았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class=&quot;book-toc&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;목차&lt;/p&gt;
&lt;ul id=&quot;toc&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;/ul&gt;
&lt;/div&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;0. 팀 컬쳐&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에도 역시 Notion을 주로 사용했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기록해야 하는 것들이 있으면 Notion에 전부 기록했고, 기타 알림이나 실시간으로 전달해야 하는 부분들은 Mattermost를 연결해서 사용하거나 카톡방, 혹은 Jira를 사용했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1532&quot; data-origin-height=&quot;481&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9fErf/btrTtGAKQX1/HGTKpkbuxgQOWyVy6Hae31/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9fErf/btrTtGAKQX1/HGTKpkbuxgQOWyVy6Hae31/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9fErf/btrTtGAKQX1/HGTKpkbuxgQOWyVy6Hae31/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9fErf%2FbtrTtGAKQX1%2FHGTKpkbuxgQOWyVy6Hae31%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;1532&quot; height=&quot;481&quot; data-origin-width=&quot;1532&quot; data-origin-height=&quot;481&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;0.0. 팀 규칙&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전 프로젝트에서 사용했던 팀 규칙을 현재 프로젝트에 맞게 살짝 수정한 형태로 사용했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특별히 다른 부분이 있다면 이번에는 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;MR(Merge Request)를 날리고 나서 2명 이상의 동의가 있을 때만 &lt;/b&gt;&lt;/u&gt;&lt;/span&gt;&lt;span&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;적용&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;하도록 자체적인 규칙을 설정해서 끝까지 지켰습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;(GitLab 무료버전은 몇 명 이상이 Approved를 해야 MR 적용이 되는 기능이 유료.. 입니다 ㅠ)&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;822&quot; data-origin-height=&quot;818&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cTh7AN/btrTsmivuBD/Gnxe8o8F2YNWUdRL5OHdeK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cTh7AN/btrTsmivuBD/Gnxe8o8F2YNWUdRL5OHdeK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cTh7AN/btrTsmivuBD/Gnxe8o8F2YNWUdRL5OHdeK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcTh7AN%2FbtrTsmivuBD%2FGnxe8o8F2YNWUdRL5OHdeK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;822&quot; height=&quot;818&quot; data-origin-width=&quot;822&quot; data-origin-height=&quot;818&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;0.1. 갤러리&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전 2번의 프로젝트에서도 그랬듯이 이번에도 갤러리를 운영했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 이번 프로젝트는 대부분이 오프라인으로 진행되었기에 사진 관리가 다소 어려운 부분이 있었으나, 제가 하겠다고 선언한 이상 시간을 투자해서 철저하게 관리했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1267&quot; data-origin-height=&quot;620&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/C00Yw/btrTse5YL7u/nlfVa1EyMCmQiKY16y9vH0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/C00Yw/btrTse5YL7u/nlfVa1EyMCmQiKY16y9vH0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/C00Yw/btrTse5YL7u/nlfVa1EyMCmQiKY16y9vH0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FC00Yw%2FbtrTse5YL7u%2FnlfVa1EyMCmQiKY16y9vH0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1267&quot; height=&quot;620&quot; data-origin-width=&quot;1267&quot; data-origin-height=&quot;620&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;0.2. 회의록&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스크럼때 이야기를 나누기에는 시간이 부족하다고 느낀 경우 아예 시간을 길게 잡고 회의를 진행했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;회의를 진행한 내용은 서기 혹은 대체자가 직접 &lt;span style=&quot;color: #333333;&quot;&gt;Notion&lt;/span&gt;에 정리해두었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;526&quot; data-origin-height=&quot;608&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dIMrNE/btrTu3vkppE/HA2Yfki1Nq4GwUUsU1axrk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dIMrNE/btrTu3vkppE/HA2Yfki1Nq4GwUUsU1axrk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dIMrNE/btrTu3vkppE/HA2Yfki1Nq4GwUUsU1axrk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdIMrNE%2FbtrTu3vkppE%2FHA2Yfki1Nq4GwUUsU1axrk%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;526&quot; height=&quot;608&quot; data-origin-width=&quot;526&quot; data-origin-height=&quot;608&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;0.3. 고민한 내용들 게시판&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전 프로젝트에서의 삽질 게시판이 고민한 내용들 게시판으로 이름이 변경되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전보다 조금더 자유로운 형식으로 자신이 고민한 내용들을 정리해두었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;887&quot; data-origin-height=&quot;776&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/RQTyA/btrTtWpWLnu/7LIX5KirvtN9n3Uk5HizK1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/RQTyA/btrTtWpWLnu/7LIX5KirvtN9n3Uk5HizK1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/RQTyA/btrTtWpWLnu/7LIX5KirvtN9n3Uk5HizK1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FRQTyA%2FbtrTtWpWLnu%2F7LIX5KirvtN9n3Uk5HizK1%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;887&quot; height=&quot;776&quot; data-origin-width=&quot;887&quot; data-origin-height=&quot;776&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;0.4. 개선사항&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발 초반부에 MR의 단위를 상세하게 나누지 않아서 누구는 양이 엄청 많아지고 누구는 양이 적은 등 차이가 나는 문제가 발생했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Git 담당자로서 Commit 컨벤션이나 폴더구조와 같은 것들 뿐만 아니라 MR도 많이 신경을 썼어야 했는데 그런 부분에 있어서 조금 아쉬웠기에 다음번에는 MR컨벤션도 자세하게 나눠서 처리해볼 생각입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 이전 ImTeller 프로젝트에서 진행했던 다른 팀과의 코드리뷰 혹은 개인 공부 내용 발표와 같은 것들을 진행하지 못한 부분이 다소 아쉬웠습니다.&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. 기획단계&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구현 내용이 양 보다는 새로운 기술의 시도쪽에 가까웠기 때문에 &lt;span&gt;생각보다 빠르게 기획 내용이 정리되었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span&gt;1.0. 디자인&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;이번에도 디자인 협업에 &lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;Figma&lt;/b&gt;&lt;/span&gt;가 사용되었습니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;820&quot; data-origin-height=&quot;792&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ovFKd/btrTtFhDbWV/qQoHrcxYq2K50MJhCPBWuk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ovFKd/btrTtFhDbWV/qQoHrcxYq2K50MJhCPBWuk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ovFKd/btrTtFhDbWV/qQoHrcxYq2K50MJhCPBWuk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FovFKd%2FbtrTtFhDbWV%2FqQoHrcxYq2K50MJhCPBWuk%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;820&quot; height=&quot;792&quot; data-origin-width=&quot;820&quot; data-origin-height=&quot;792&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1.1. ERD&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;ERDCloud&lt;/b&gt;&lt;/span&gt;를 사용했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음에는 롤링페이퍼가 주 서비스 내용이었기 때문에 기본적인 CRUD를 기반으로 몇 가지 테이블만 추가하면 될 거라고 생각했는데, 꽃과 꽃다발, 배송, 신고 등등 다양한 기능들이 추가되면서 연관관계가 점차 증가하여 다소 복잡한 ERD가 완성되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;카카오페이를 이용한 가상결제시스템을 도입할 때 최대한 컬럼의 수를 줄이고자 노력해서 배송 테이블에 들어가는 내용이 비교적 적은 편이었지만, 실제로 결제 시스템과 배송 시스템을 구현한다고 하면 이것보다 훨씬 더 많은 컬럼이 필요했을 것 같습니다. (예를 들자면 할인률과 같은 컬럼들이 존재할 수 있겠죠?!)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1426&quot; data-origin-height=&quot;810&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dIjEp3/btrTthamHxt/9Ozmn5Rg0zcRqCDmKn6Ook/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dIjEp3/btrTthamHxt/9Ozmn5Rg0zcRqCDmKn6Ook/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dIjEp3/btrTthamHxt/9Ozmn5Rg0zcRqCDmKn6Ook/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdIjEp3%2FbtrTthamHxt%2F9Ozmn5Rg0zcRqCDmKn6Ook%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;1426&quot; height=&quot;810&quot; data-origin-width=&quot;1426&quot; data-origin-height=&quot;810&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1.2. API 문서&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;API와 관련된 내용 역시 &lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;Notion&lt;/b&gt;&lt;/span&gt;에 자세히 기록하려고 노력했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기능별로 &lt;span&gt;API&lt;/span&gt;의 첫 주소를 나누고, 각 주소에 맞는 &lt;span&gt;API&lt;/span&gt;의 URI와 설명, 그리고 현재 작업 진행 정도를 나타내는 페이지를 만들어서 관리했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 페이지로 개발을 진행하던 중 롤링페이퍼와 메시지간의 역할이 비슷한 부분 때문에 어디에 특정 API를 넣어야 할까에 대해 많은 고민을 했던 기억이 나네요 ㅎㅎ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(처음에는 롤링페이퍼 조회 안에 모든 메시지를 가져오는 방식을 사용하려고 했으나, 최종적으로는 롤링페이퍼 조회와 메시지 조회를 각각 나누어서 관리했습니다!)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oedA9/btrTuA1ahQv/UKPf0GSugEBZYrW82rGzUk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oedA9/btrTuA1ahQv/UKPf0GSugEBZYrW82rGzUk/img.png&quot; data-origin-width=&quot;1417&quot; data-origin-height=&quot;668&quot; data-is-animation=&quot;false&quot; style=&quot;width: 77.183%; margin-right: 10px;&quot; data-widthpercent=&quot;78.09&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oedA9/btrTuA1ahQv/UKPf0GSugEBZYrW82rGzUk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoedA9%2FbtrTuA1ahQv%2FUKPf0GSugEBZYrW82rGzUk%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;1417&quot; height=&quot;668&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nZlYN/btrTsedTXoN/zVPW1MwzUWdkVUkCKr2ykK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nZlYN/btrTsedTXoN/zVPW1MwzUWdkVUkCKr2ykK/img.png&quot; data-origin-width=&quot;269&quot; data-origin-height=&quot;452&quot; data-is-animation=&quot;false&quot; style=&quot;width: 21.6542%;&quot; data-widthpercent=&quot;21.91&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nZlYN/btrTsedTXoN/zVPW1MwzUWdkVUkCKr2ykK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnZlYN%2FbtrTsedTXoN%2FzVPW1MwzUWdkVUkCKr2ykK%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;269&quot; height=&quot;452&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1.3. Git&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전 프로젝트의 GitHub-Flow 전략을 버리고 다시 &lt;span style=&quot;color: #1b711d;&quot;&gt;&lt;b&gt;Git-Flow&lt;/b&gt;&lt;/span&gt;로 돌아왔습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제 큰 프로젝트에서 진행하는 것과 비슷하게 Git 전략을 사용해보고 싶다는 팀원들의 의견을 받아들였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 외에도 Commit 컨벤션의 경우 Gitmoji를 사용했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 편의상 커밋 메시지는 한글로 작성하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;410&quot; data-origin-height=&quot;726&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/VRiTW/btrTvjLEHaA/IKftYbzIuQUKEH7xp3mbf0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/VRiTW/btrTvjLEHaA/IKftYbzIuQUKEH7xp3mbf0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/VRiTW/btrTvjLEHaA/IKftYbzIuQUKEH7xp3mbf0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FVRiTW%2FbtrTvjLEHaA%2FIKftYbzIuQUKEH7xp3mbf0%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;410&quot; height=&quot;726&quot; data-origin-width=&quot;410&quot; data-origin-height=&quot;726&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;figure id=&quot;og_1670852489110&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;gitmoji&quot; data-og-description=&quot;:truck: Move or rename resources (e.g.: files, paths, routes).&quot; data-og-host=&quot;gitmoji.dev&quot; data-og-source-url=&quot;https://gitmoji.dev/&quot; data-og-url=&quot;https://gitmoji.dev/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/mcSfp/hyQRTPAx4N/BT6SppByml9nvu7eKmfKYk/img.gif?width=2048&amp;amp;height=2048&amp;amp;face=0_0_2048_2048,https://scrap.kakaocdn.net/dn/b9j3HX/hyQRNoiA99/FFUYs6ucsvbksleWSSJNtK/img.gif?width=2048&amp;amp;height=2048&amp;amp;face=0_0_2048_2048&quot;&gt;&lt;a href=&quot;https://gitmoji.dev/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://gitmoji.dev/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/mcSfp/hyQRTPAx4N/BT6SppByml9nvu7eKmfKYk/img.gif?width=2048&amp;amp;height=2048&amp;amp;face=0_0_2048_2048,https://scrap.kakaocdn.net/dn/b9j3HX/hyQRNoiA99/FFUYs6ucsvbksleWSSJNtK/img.gif?width=2048&amp;amp;height=2048&amp;amp;face=0_0_2048_2048');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;gitmoji&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;:truck: Move or rename resources (e.g.: files, paths, routes).&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;gitmoji.dev&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. 개발단계&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2.0. 기술 스택&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세 번의 프로젝트를 진행하면서, &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;매번 같은 기술 스택만 사용하는 것&lt;/b&gt;&lt;/span&gt;이 굉장히 마음에 걸렸습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다고 해서 프론트엔드에 익숙하지 않은 팀원들이 있는데 새로운 기술 스택을 마구 도입하는 것 역시 이기적인 선택일 수 있겠다는 생각을 했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 팀원들과 많은 이야기를 나누었고, 문제가 발생한다고 해도 제가 커버해낼 수 있다고 생각한 한도 내에서 새로운 기술 스택을 선정하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대표적으로 새롭게 도입하게 된 기술 스택은 바로 &lt;b&gt;&lt;span style=&quot;color: #006dd7;&quot;&gt;Recoil&lt;/span&gt;&lt;/b&gt;이었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전 프로젝트에서 여러 차례 사용해봤고, 익숙한 Redux와 Redux-Toolkit을 버리고 Recoil을 선택한 이유는 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;Redux 계열 상태관리 라이브러리에 비해서 간단하게 쓸 수 있고&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;, &lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;React와 동일하게 Meta에서 만든 상태관리 라이브러리였기 때문&lt;/b&gt;&lt;/u&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;그리고 드디어 CRA를 버리고 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;Vite&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;이걸 해결하기 위해서는 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;모듈 번들러 차원의 개선&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;이 필요했는데, &lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;Webpack이 아닌 ESBuild를 사용하는 Vite를 사용하면 속도면에서 엄청난 개선을 얻을 수 있다&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;는 것을 이미 이전에 Vite를 사용해봤기 때문에 알고 있었습니다. 그래서 Vite를 사용함으로써 겪어야 하는 다양한 불편함 (정보의 부족, 특정 라이브러리의 미지원)을 감수하고 도입하게 되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;634&quot; data-origin-height=&quot;123&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zytJN/btrTt1rbU4Q/kfbrRMFkXLHH8Wb2wPpir1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zytJN/btrTt1rbU4Q/kfbrRMFkXLHH8Wb2wPpir1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zytJN/btrTt1rbU4Q/kfbrRMFkXLHH8Wb2wPpir1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzytJN%2FbtrTt1rbU4Q%2FkfbrRMFkXLHH8Wb2wPpir1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;634&quot; height=&quot;123&quot; data-origin-width=&quot;634&quot; data-origin-height=&quot;123&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;실제로 Vite를 도입하고 배포하는 과정에서 도커 컨테이너로 요청이 제대로 전달이 안되는 과정이 발생했는데, 해당 오류를 고치기 위해서 꽤 오랜 시간을 고민했던 경험이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;698&quot; data-origin-height=&quot;325&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/efeSHl/btrTu24hVjV/is2NQx0cCmzTA8j8r5Rzu0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/efeSHl/btrTu24hVjV/is2NQx0cCmzTA8j8r5Rzu0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/efeSHl/btrTu24hVjV/is2NQx0cCmzTA8j8r5Rzu0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FefeSHl%2FbtrTu24hVjV%2Fis2NQx0cCmzTA8j8r5Rzu0%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;698&quot; height=&quot;325&quot; data-origin-width=&quot;698&quot; data-origin-height=&quot;325&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;702&quot; data-origin-height=&quot;300&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vQUNQ/btrTsnV818a/SBEft2EJatuClk0RJ53sDK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vQUNQ/btrTsnV818a/SBEft2EJatuClk0RJ53sDK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vQUNQ/btrTsnV818a/SBEft2EJatuClk0RJ53sDK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvQUNQ%2FbtrTsnV818a%2FSBEft2EJatuClk0RJ53sDK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;702&quot; height=&quot;300&quot; data-origin-width=&quot;702&quot; data-origin-height=&quot;300&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;제가 겪었던 문제에 대한 Vite 공식문서의 내용을 추가로 첨부합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1670853896725&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Vite&quot; data-og-description=&quot;Vite, 차세대 프런트엔드 개발 툴&quot; data-og-host=&quot;vitejs-kr.github.io&quot; data-og-source-url=&quot;https://vitejs-kr.github.io/config/server-options.html&quot; data-og-url=&quot;https://vitejs-kr.github.io&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bwbBfQ/hyQRS4f11Y/7zuq75jChiSPTlTFV8Qk8K/img.png?width=2600&amp;amp;height=1302&amp;amp;face=0_0_2600_1302,https://scrap.kakaocdn.net/dn/bn6pVJ/hyQRUHMvi3/EFaZchXk3h5ykiOB7az8f1/img.png?width=640&amp;amp;height=640&amp;amp;face=0_0_640_640&quot;&gt;&lt;a href=&quot;https://vitejs-kr.github.io/config/server-options.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://vitejs-kr.github.io/config/server-options.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bwbBfQ/hyQRS4f11Y/7zuq75jChiSPTlTFV8Qk8K/img.png?width=2600&amp;amp;height=1302&amp;amp;face=0_0_2600_1302,https://scrap.kakaocdn.net/dn/bn6pVJ/hyQRUHMvi3/EFaZchXk3h5ykiOB7az8f1/img.png?width=640&amp;amp;height=640&amp;amp;face=0_0_640_640');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Vite&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Vite, 차세대 프런트엔드 개발 툴&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;vitejs-kr.github.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 이런 어려움에도 불구하고 프로그램 동작과 관련해서 Vite가 문제를 일으키는 부분들을 모두 제거할 수 있었고, 속도의 장점만을 얻어낼 수 있었습니다!&lt;/p&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;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;TypeScript&lt;/b&gt;&lt;/span&gt;와 &lt;b&gt;&lt;span style=&quot;color: #8a3db6;&quot;&gt;React&lt;/span&gt;&lt;/b&gt;를 사용하였으며, CSS 처리를 위해 &lt;b&gt;&lt;span style=&quot;color: #6164c6;&quot;&gt;Emotion&lt;/span&gt;&lt;/b&gt;을 사용했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;백엔드는 &lt;span style=&quot;color: #ef5369;&quot;&gt;&lt;b&gt;Spring Boot&lt;/b&gt;&lt;/span&gt;와 &lt;span style=&quot;color: #1b711d;&quot;&gt;&lt;b&gt;MySQL&lt;/b&gt;&lt;/span&gt;를 사용했습니다. ORM으로 &lt;span style=&quot;color: #0593d3;&quot;&gt;&lt;b&gt;JPA&lt;/b&gt;&lt;/span&gt;를 사용했으며, QueryDSL을 사용하려고 했으나 실제로 적용하지는 못했습니다. (코드가 간단해서 Native로 모두 처리했습니다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가로 로그인 과정에서 액세스 토큰을 사용하기에 이걸 따로 저장해두어 로그아웃 시 해당 액세스 토큰을 사용하지 못하도록 하기 위해서, 그리고 리프레시 토큰을 이용한 유효성 검사를 하기 위해서 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;Redis&lt;/b&gt;&lt;/span&gt;를 사용했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CI/CD로는 &lt;span style=&quot;color: #99cefa;&quot;&gt;&lt;b&gt;Docker&lt;/b&gt;&lt;/span&gt;와 &lt;span style=&quot;color: #781b33;&quot;&gt;&lt;b&gt;Jenkins&lt;/b&gt;&lt;/span&gt;를 사용했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;921&quot; data-origin-height=&quot;536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wZUfu/btrTmYW9L8w/ODl9LarD6OlYNLvKHJFr0K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wZUfu/btrTmYW9L8w/ODl9LarD6OlYNLvKHJFr0K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wZUfu/btrTmYW9L8w/ODl9LarD6OlYNLvKHJFr0K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwZUfu%2FbtrTmYW9L8w%2FODl9LarD6OlYNLvKHJFr0K%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;921&quot; height=&quot;536&quot; data-origin-width=&quot;921&quot; data-origin-height=&quot;536&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2.1. 실제 개발 과정&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아이디어 회의부터 기획이 약 1주 반만에 끝났기 때문에 개발 기간을 2주 반, 최대 3주 반까지 잡았고 나머지 1주일은 이벤트 진행 및 QA를 진행하려고 계획했고, 실제로 개발 기간은 약 3주 정도가 걸렸습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 프로젝트는 9-6를 거의 완벽하게 지켜냈다는 점에서 매우 만족했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;620&quot; data-origin-height=&quot;450&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/csVqjz/btrTtCk2TjX/VeZAaVbxnfXB3Owhtb0MTk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/csVqjz/btrTtCk2TjX/VeZAaVbxnfXB3Owhtb0MTk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/csVqjz/btrTtCk2TjX/VeZAaVbxnfXB3Owhtb0MTk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcsVqjz%2FbtrTtCk2TjX%2FVeZAaVbxnfXB3Owhtb0MTk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;620&quot; height=&quot;450&quot; data-origin-width=&quot;620&quot; data-origin-height=&quot;450&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트 막판에 출력부분과 iOS 지원 관련 문제때문에 조금 고생했습니다...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1463&quot; data-origin-height=&quot;637&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cyDwpp/btrToDkUHxk/Sv81cr0NGrdt2IKQoR5Ke0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cyDwpp/btrToDkUHxk/Sv81cr0NGrdt2IKQoR5Ke0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cyDwpp/btrToDkUHxk/Sv81cr0NGrdt2IKQoR5Ke0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcyDwpp%2FbtrToDkUHxk%2FSv81cr0NGrdt2IKQoR5Ke0%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;1463&quot; height=&quot;637&quot; data-origin-width=&quot;1463&quot; data-origin-height=&quot;637&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;개발과는 무관할 수도 있지만,, 개발이 종료되고 QA를 진행하면서 동시에 이벤트를 2차례 진행했고, 모두 성황리에 종료되어서 당첨자들에게 꽃다발과 실물 롤링페이퍼까지 전달할 수 있었습니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1349&quot; data-origin-height=&quot;610&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bJkkOy/btrToborrzU/QKJh2XbfLKbgbTJN8bxYXK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bJkkOy/btrToborrzU/QKJh2XbfLKbgbTJN8bxYXK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bJkkOy/btrToborrzU/QKJh2XbfLKbgbTJN8bxYXK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbJkkOy%2FbtrToborrzU%2FQKJh2XbfLKbgbTJN8bxYXK%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;1349&quot; height=&quot;610&quot; data-origin-width=&quot;1349&quot; data-origin-height=&quot;610&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2.2. 폴더 구조&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;프론트엔드&lt;/b&gt;&lt;/span&gt; 폴더 구조는 크게 특별한 요소가 존재하지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;pages 폴더에는 각각의 페이지가 들어있고, 페이지를 구성하는 요소들은 components에서 관리합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;api 폴더에는 api 요청을 편리하게 사용하기 위해 객체 형태로 함수들을 정리해놓은 파일들을 모아놓았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;assets 폴더에는 애플리케이션에 필요한 다양한 사진 자료들이 들어있고, kakao 폴더에는 카카오 로그인과 관련된 파일들이 들어있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;recoil 폴더에는 전역에서 관리해야 하는 다양한 상태값들이 들어있고, utils에는 dateFormatters 함수와 액세스 토큰과 리프레쉬 토큰을 업데이트하기 위한 updateTokens가 들어있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;371&quot; data-origin-height=&quot;559&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/oHnWV/btrTwANahVe/KBkK4jcUAIUBOFmOxWcbn1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/oHnWV/btrTwANahVe/KBkK4jcUAIUBOFmOxWcbn1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/oHnWV/btrTwANahVe/KBkK4jcUAIUBOFmOxWcbn1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FoHnWV%2FbtrTwANahVe%2FKBkK4jcUAIUBOFmOxWcbn1%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;371&quot; height=&quot;559&quot; data-origin-width=&quot;371&quot; data-origin-height=&quot;559&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;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;백엔드&lt;/b&gt;&lt;/span&gt; 폴더 구조 역시 단순합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Controller에서 사용자의 요청을 받고, Service에서 비즈니스 로직을 처리합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Converter 폴더에는 DB에서 데이터를 가져온 후에 그대로 사용하지 않고 DTO형태로 변경해서 사용하기 위한 용도의 파일들이 들어있고, DTO 폴더에는 입력값과 반환값에 대한 정보가 들어있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Entity 폴더에는 DB의 테이블에 해당하는 정보가 들어있고, Repository 폴더에는 JPA를 사용하기 위한 파일들이 들어있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로 util 폴더에는 S3와 관련된 내용들이 들어있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가로 resources의 env.yml에는 Kakao Developer에서 생성한 꽃바다 애플리케이션의 adminKey가 들어있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 내용은 중요한 정보이므로 Git에 올라가지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;229&quot; data-origin-height=&quot;385&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ci8u8a/btrTvXPfqD7/6F9xehnTZWQvRBPAcjKRAk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ci8u8a/btrTvXPfqD7/6F9xehnTZWQvRBPAcjKRAk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ci8u8a/btrTvXPfqD7/6F9xehnTZWQvRBPAcjKRAk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fci8u8a%2FbtrTvXPfqD7%2F6F9xehnTZWQvRBPAcjKRAk%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;229&quot; height=&quot;385&quot; data-origin-width=&quot;229&quot; data-origin-height=&quot;385&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2.3. 담당 개발 기능&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 프로젝트에서 저에게 주어진 가장 큰 임무는 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;서버 배포를 처음부터 끝까지 하는 것&lt;/b&gt;&lt;/span&gt;이었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전 프로젝트들에서 Docker와 Jenkins를 사용하는 모습들을 여러 차례 봐오기도 했고, 그러한 배포 작업들에 관심도 있었고 실제로 작은 부분에서는 관여하기도 했었기 때문에 크게 무리 없이 자동 배포까지 완료했습니다.&lt;/p&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;(대표적으로 위에서 언급한 Vite 관련 문제가 있겠네요...)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;몇 가지 예시를 들자면 백엔드 도커파일을 잘못 이해해서 이상하게 작성한다거나 (jar파일의 이름을 잘못 적었습니다 ㅠㅠ)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;442&quot; data-origin-height=&quot;155&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rf0iO/btrTvjx9myC/OJYpuoKSyMNel0ch3JlPp1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rf0iO/btrTvjx9myC/OJYpuoKSyMNel0ch3JlPp1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rf0iO/btrTvjx9myC/OJYpuoKSyMNel0ch3JlPp1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Frf0iO%2FbtrTvjx9myC%2FOJYpuoKSyMNel0ch3JlPp1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;442&quot; height=&quot;155&quot; data-origin-width=&quot;442&quot; data-origin-height=&quot;155&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;Vite의 기본 포트를 EC2 서버가 허락하지 않아서 3000으로 접속한 이후 포트포워딩 해야했다거나&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;582&quot; data-origin-height=&quot;150&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bdeAm3/btrTuzusKVj/kJazGXktlXv0VlF7r8vfLK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bdeAm3/btrTuzusKVj/kJazGXktlXv0VlF7r8vfLK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bdeAm3/btrTuzusKVj/kJazGXktlXv0VlF7r8vfLK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbdeAm3%2FbtrTuzusKVj%2FkJazGXktlXv0VlF7r8vfLK%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;582&quot; height=&quot;150&quot; data-origin-width=&quot;582&quot; data-origin-height=&quot;150&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;/p&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;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;22번 포트를 열지 않고 서버를 종료한 것&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;이었습니다...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;분명히 젠킨스에서 자동 빌드도 성공적으로 이루어졌고, 서버도 잘 돌아가는데 ssh가 접속이 안됐습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하필 전날 방화벽을 설정하고 집으로 갔던 탓에 문제가 무엇인지 정확히 파악하는데 시간이 오래 걸렸습니다..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(아니 어제 집가기 전까지는 잘되던게 오늘 아침에 왜 안되는거지? 라고 생각했습니다 ㅠ)&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;677&quot; data-origin-height=&quot;296&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/trlWg/btrTmYQnUlG/eIbRuuKZ8MiK69E4qZeRkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/trlWg/btrTmYQnUlG/eIbRuuKZ8MiK69E4qZeRkk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/trlWg/btrTmYQnUlG/eIbRuuKZ8MiK69E4qZeRkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtrlWg%2FbtrTmYQnUlG%2FeIbRuuKZ8MiK69E4qZeRkk%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;677&quot; height=&quot;296&quot; data-origin-width=&quot;677&quot; data-origin-height=&quot;296&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;포팅매뉴얼에 적기 위해 찍어둔 포트상태를 확인해보니...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;449&quot; data-origin-height=&quot;196&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/6a7Co/btrToaJQkfe/gV3UNsAFvxkuv13jnIsWB1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/6a7Co/btrToaJQkfe/gV3UNsAFvxkuv13jnIsWB1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/6a7Co/btrToaJQkfe/gV3UNsAFvxkuv13jnIsWB1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F6a7Co%2FbtrToaJQkfe%2FgV3UNsAFvxkuv13jnIsWB1%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;449&quot; height=&quot;196&quot; data-origin-width=&quot;449&quot; data-origin-height=&quot;196&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;22번 포트가 닫혀버려서 접근할 수 없는 상황....&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어쩔 수 없이 서버를 초기화 하고 세팅을 다시 했습니다 ㅋㅋㅋㅋㅋ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;절대 잊지 않을 것 같습니다 22번 포트 ㅠ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;612&quot; data-origin-height=&quot;421&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rIgrw/btrTvX2MAU3/KfuPAcVlVH7DNBlmGyvml1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rIgrw/btrTvX2MAU3/KfuPAcVlVH7DNBlmGyvml1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rIgrw/btrTvX2MAU3/KfuPAcVlVH7DNBlmGyvml1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrIgrw%2FbtrTvX2MAU3%2FKfuPAcVlVH7DNBlmGyvml1%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;612&quot; height=&quot;421&quot; data-origin-width=&quot;612&quot; data-origin-height=&quot;421&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;두 번째 시도에는 무사히 세팅을 마칠 수 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;438&quot; data-origin-height=&quot;263&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ds5HXR/btrTtAU3uS9/Jemrhww28IImSz8ITTLTwK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ds5HXR/btrTtAU3uS9/Jemrhww28IImSz8ITTLTwK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ds5HXR/btrTtAU3uS9/Jemrhww28IImSz8ITTLTwK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fds5HXR%2FbtrTtAU3uS9%2FJemrhww28IImSz8ITTLTwK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;438&quot; height=&quot;263&quot; data-origin-width=&quot;438&quot; data-origin-height=&quot;263&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;CI/CD 작업을 마치고 진행한 개발은 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;카카오페이를 연동하여 결제 시스템을 적용하는 부분&lt;/b&gt;&lt;/span&gt;이었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저희가 만드는 애플리케이션으로는 사업자 등록을 할 수 없는 상황이었기 때문에 어쩔 수 없이 테스트 결제로 구현해야했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cjoiK3/btrTulJSIHz/7rKNkXMs6B7NeXN8nKXyOk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cjoiK3/btrTulJSIHz/7rKNkXMs6B7NeXN8nKXyOk/img.png&quot; data-origin-width=&quot;276&quot; data-origin-height=&quot;541&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;39.35&quot; style=&quot;width: 38.8947%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cjoiK3/btrTulJSIHz/7rKNkXMs6B7NeXN8nKXyOk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcjoiK3%2FbtrTulJSIHz%2F7rKNkXMs6B7NeXN8nKXyOk%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;276&quot; height=&quot;541&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KBgF9/btrTvj5YXVH/qCkVrCeD14ogYapiDaJcR1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KBgF9/btrTvj5YXVH/qCkVrCeD14ogYapiDaJcR1/img.png&quot; data-origin-width=&quot;320&quot; data-origin-height=&quot;407&quot; data-is-animation=&quot;false&quot; style=&quot;width: 59.9425%;&quot; data-widthpercent=&quot;60.65&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KBgF9/btrTvj5YXVH/qCkVrCeD14ogYapiDaJcR1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKBgF9%2FbtrTvj5YXVH%2FqCkVrCeD14ogYapiDaJcR1%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;320&quot; height=&quot;407&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;결제 시스템 초기 구현&lt;/figcaption&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필요한 데이터를 서버에 넘겨주고, 서버에서 카카오페이 테스트 API를 요청하는 동시에 결제 및 배송 관련 데이터를 MySQL에 저장합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 카카오페이 테스트 API의 결과로 돌아오는 정보들을 다시 화면에 띄워주기만 하면 쉽게 완료되는 구조였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 테스트 과정에서 예상치 못한 문제가 하나 발생했는데, 분명 코드가 작동을 잘 하는데 아주 가끔씩 결제가 정상적으로 되지 않는 현상이 발생했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드적으로 무언가 문제가 있나 싶어서 하루종일 찾아봤는데, 아무리 생각해도 코드에는 문제가 없었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 카카오페이 API에서 F1002에러에 대해서 정말 많이 찾아봤고, 공식 답변들도 찾아보았지만 답변을 얻지 못했는데..&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;카카오 DevTalk 게시판에 아래 질문들을 남겨주신 분이 있어서 원인을 파악할 수 있었습니다.&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;834&quot; data-origin-height=&quot;693&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bwMOjF/btrTu2cdxrm/EseVXNEoxJo7ZoexKy4Gl0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bwMOjF/btrTu2cdxrm/EseVXNEoxJo7ZoexKy4Gl0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bwMOjF/btrTu2cdxrm/EseVXNEoxJo7ZoexKy4Gl0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbwMOjF%2FbtrTu2cdxrm%2FEseVXNEoxJo7ZoexKy4Gl0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;834&quot; height=&quot;693&quot; data-origin-width=&quot;834&quot; data-origin-height=&quot;693&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;791&quot; data-origin-height=&quot;383&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7P2cD/btrTsfjy0Td/cgjzoIx5a6ZR3sb5KgMhJ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7P2cD/btrTsfjy0Td/cgjzoIx5a6ZR3sb5KgMhJ0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7P2cD/btrTsfjy0Td/cgjzoIx5a6ZR3sb5KgMhJ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7P2cD%2FbtrTsfjy0Td%2FcgjzoIx5a6ZR3sb5KgMhJ0%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;791&quot; height=&quot;383&quot; data-origin-width=&quot;791&quot; data-origin-height=&quot;383&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;결제 관련 UI를 모두 만들고 난 이후에는 다른 팀원들의 일 중에서 도움이 필요하거나 미흡한 부분을 고쳐주었습니다.&lt;/p&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: #ee2323;&quot;&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: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;코드 스플리팅&lt;/b&gt;&lt;/u&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;814&quot; data-origin-height=&quot;135&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cN9CHV/btrTtjlDL85/DsISkx3dvQlvbA4GgriXn0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cN9CHV/btrTtjlDL85/DsISkx3dvQlvbA4GgriXn0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cN9CHV/btrTtjlDL85/DsISkx3dvQlvbA4GgriXn0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcN9CHV%2FbtrTtjlDL85%2FDsISkx3dvQlvbA4GgriXn0%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;814&quot; height=&quot;135&quot; data-origin-width=&quot;814&quot; data-origin-height=&quot;135&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;어떻게 보면 결국 모든 서비스를 이용하기 위해서는 같은 시간이 들겠지만, 과도한 초기 로딩을 잡음으로써 유저들이 처음부터 답답해서 빠져나가지 않도록 막는 하나의 장치를 마련했다고 생각합니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2016&quot; data-origin-height=&quot;1113&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cfXJKx/btrTsnIACG1/uFVJqKi937H2VLcQLIJuO0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cfXJKx/btrTsnIACG1/uFVJqKi937H2VLcQLIJuO0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cfXJKx/btrTsnIACG1/uFVJqKi937H2VLcQLIJuO0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcfXJKx%2FbtrTsnIACG1%2FuFVJqKi937H2VLcQLIJuO0%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;2016&quot; height=&quot;1113&quot; data-origin-width=&quot;2016&quot; data-origin-height=&quot;1113&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;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;LightHouse&lt;/b&gt;&lt;/span&gt;를 돌려보면서 문제점들을 조금 더 자세하게 파악할 수 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 중에서도 가장 예상 로딩 절감치가 높았던 텍스트 압축 사용에 대해서 찾아보게 되었고, &lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;GZip 최적화&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;에 대해서 알게 되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;483&quot; data-origin-height=&quot;406&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b2JHEB/btrTvjLHMKW/CYFft48Vkr2kWkgDrjKQl1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b2JHEB/btrTvjLHMKW/CYFft48Vkr2kWkgDrjKQl1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b2JHEB/btrTvjLHMKW/CYFft48Vkr2kWkgDrjKQl1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb2JHEB%2FbtrTvjLHMKW%2FCYFft48Vkr2kWkgDrjKQl1%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;483&quot; height=&quot;406&quot; data-origin-width=&quot;483&quot; data-origin-height=&quot;406&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;데이터를 그대로 넘겨주는 것이 아니라 서버에서 압축해서 처리하는 방식을 사용하는 것인데, 압축률을 높이면 클라이언트에서의 로딩속도는 줄겠지만 압축에 따른 서버의 부하가 늘어난다는 Trade-off가 있는 방식이었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금 당장은 서버에 여유가 있고, 유저가 직접 경험하는 로딩속도를 줄이는 것이 우선이었기 때문에 nginx.conf의 gzip 관련 옵션들의 주석을 풀었고, 이를 통해 로딩시간을 상당히 많이 줄일 수 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1705&quot; data-origin-height=&quot;427&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dWNCAo/btrTABAgiKw/55ho5fiFQDKlkXmei8j0h1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dWNCAo/btrTABAgiKw/55ho5fiFQDKlkXmei8j0h1/img.png&quot; data-alt=&quot;기본적으로 만들어져있는 nginx.conf에는 gzip 옵션이 주석처리 되어있는데, 이걸 풀어줬습니다!&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dWNCAo/btrTABAgiKw/55ho5fiFQDKlkXmei8j0h1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdWNCAo%2FbtrTABAgiKw%2F55ho5fiFQDKlkXmei8j0h1%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;1705&quot; height=&quot;427&quot; data-origin-width=&quot;1705&quot; data-origin-height=&quot;427&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;기본적으로 만들어져있는 nginx.conf에는 gzip 옵션이 주석처리 되어있는데, 이걸 풀어줬습니다!&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;664&quot; data-origin-height=&quot;362&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Wx6sJ/btrTsn2VyYN/bBTwSGO0jv3F1FFN7KwP51/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Wx6sJ/btrTsn2VyYN/bBTwSGO0jv3F1FFN7KwP51/img.png&quot; data-alt=&quot;절감치가 드라마틱하게 줄어듦을 확인할 수 있었습니다!&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Wx6sJ/btrTsn2VyYN/bBTwSGO0jv3F1FFN7KwP51/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FWx6sJ%2FbtrTsn2VyYN%2FbBTwSGO0jv3F1FFN7KwP51%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;664&quot; height=&quot;362&quot; data-origin-width=&quot;664&quot; data-origin-height=&quot;362&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;절감치가 드라마틱하게 줄어듦을 확인할 수 있었습니다!&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3. 종합&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;서버를 다루고 Docker와 Jenkins로 자동배포를 구현해본다는 것은 정말로 색다른 경험이었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제 손짓 하나로 서버가 닫혀버려서 초기화가 강제되는 위험천만한 상황도 겪어보았고, 로컬에선 잘 되는 코드가 서버에 올라갔을 때 문제가 발생해서 nano에디터를 이용해서 shell 환경에서 하나하나 고치는 경험도 해볼 수 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프론트엔드, 그리고 백엔드를 담당했을 때는 분명 실수를 만회할 수 있는 기회가 어느정도 주어지는 느낌이었는데 Shell을 직접 다루고 CI/CD를 구축하고 배포환경을 구성하는 일은 정말 꼼꼼하게 공부해서 처리하지 않으면 다른 팀원들의 시간까지 상당수 뺏어버릴 수 있다는 것을 깨달았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 기회를 통해 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;개발에 있어 더욱 꼼꼼해야 할 필요가 있다는 것&lt;/b&gt;&lt;/span&gt;을 몸소 체감할 수 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;메모에 대한 중요성&lt;/b&gt;&lt;/span&gt;을 더더욱 많이 느꼈던 프로젝트였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CI/CD를 전담했지만, 다른 팀원들 역시 CI/CD에 대해 관심이 굉장히 많았고, 한번 쯤은 경험해보고 싶다는 의견이 많았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 다른 팀원들도 제가 배포를 성공적으로 마친 후에 쉽게 따라할 수 있도록 최대한 자세하게 포팅매뉴얼을 작성하였고, 현재 새로운 배포 서버에서 다른 팀원이 배포과정을 겪으면서 제가 작성한 포팅매뉴얼을 수정하기도 하고 다양하게 의견을 나누기도 하면서 학습하고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 문서화 과정을 통해서 제가 실제로 공부하고 적용했던 부분들에 대해 쉽게 되돌아볼 수 있고 다른 팀원들의 피드백을 받을 수 있다는 점에서 문서화의 소중함을 깨달았고, 앞으로도 제가 새롭게 공부해서 적용한 부분에 대한 내용, 적용에 대한 근거와 같은 것들을 적어놓으면 미래의 제가 훨씬 편하게 개발을 할 수 있을 거라는 확신을 얻을 수 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;새로운 도전이 꽤 있었음에도 이전의 프로젝트들에 비해 확실히 여유있는 개발이었고, 팀원들간의 캐미도 좋은 편이었고 서로에 대해 알아가는 시간도 그다지 필요하지 않았기 때문에 정말 편하게 개발할 수 있었던 것 같습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정말 감사하게도 운영진 측에서 노력을 인정해주셨는지 최우수상을 수여해주셨고, 별개로 UCC상까지 2관왕을 거머쥘 수 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1년 간의 여정을 행복하게 마칠 수 있어서 정말로 기분 좋은 프로젝트였습니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;4. 애플리케이션 화면 사진&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/8gaWq/btrTuAGU6Kj/03efKYJmfcI0hXQrIKZ8h0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/8gaWq/btrTuAGU6Kj/03efKYJmfcI0hXQrIKZ8h0/img.png&quot; style=&quot;width: 32.0717%; margin-right: 10px;&quot; data-origin-width=&quot;279&quot; data-origin-height=&quot;634&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;32.84&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/8gaWq/btrTuAGU6Kj/03efKYJmfcI0hXQrIKZ8h0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F8gaWq%2FbtrTuAGU6Kj%2F03efKYJmfcI0hXQrIKZ8h0%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;279&quot; height=&quot;634&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/LtN0U/btrTsfjzHGM/N4nn2pc3v755JretzVTLn1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/LtN0U/btrTsfjzHGM/N4nn2pc3v755JretzVTLn1/img.png&quot; style=&quot;width: 33.1272%; margin-right: 10px;&quot; data-origin-width=&quot;295&quot; data-origin-height=&quot;649&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;33.92&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/LtN0U/btrTsfjzHGM/N4nn2pc3v755JretzVTLn1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FLtN0U%2FbtrTsfjzHGM%2FN4nn2pc3v755JretzVTLn1%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;295&quot; height=&quot;649&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nrPCh/btrTsnhw4zr/Y35rKQttFtInbr5hf9p9ek/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nrPCh/btrTsnhw4zr/Y35rKQttFtInbr5hf9p9ek/img.png&quot; data-origin-width=&quot;299&quot; data-origin-height=&quot;671&quot; data-is-animation=&quot;false&quot; style=&quot;width: 32.4755%;&quot; data-widthpercent=&quot;33.24&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nrPCh/btrTsnhw4zr/Y35rKQttFtInbr5hf9p9ek/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnrPCh%2FbtrTsnhw4zr%2FY35rKQttFtInbr5hf9p9ek%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;299&quot; height=&quot;671&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;꽃다발 생성 1&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/KIlOj/btrTmZuZI03/0yK74mc78RCLDagrKPZBck/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/KIlOj/btrTmZuZI03/0yK74mc78RCLDagrKPZBck/img.png&quot; data-origin-width=&quot;299&quot; data-origin-height=&quot;667&quot; data-is-animation=&quot;false&quot; style=&quot;width: 32.6511%; margin-right: 10px;&quot; data-widthpercent=&quot;33.43&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/KIlOj/btrTmZuZI03/0yK74mc78RCLDagrKPZBck/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FKIlOj%2FbtrTmZuZI03%2F0yK74mc78RCLDagrKPZBck%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;299&quot; height=&quot;667&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ce5Pej/btrToDFd31d/22OX9KZxKtgXDyWbpLIkE0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ce5Pej/btrToDFd31d/22OX9KZxKtgXDyWbpLIkE0/img.png&quot; data-origin-width=&quot;285&quot; data-origin-height=&quot;636&quot; data-is-animation=&quot;false&quot; style=&quot;width: 32.6392%; margin-right: 10px;&quot; data-widthpercent=&quot;33.42&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ce5Pej/btrToDFd31d/22OX9KZxKtgXDyWbpLIkE0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fce5Pej%2FbtrToDFd31d%2F22OX9KZxKtgXDyWbpLIkE0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;285&quot; height=&quot;636&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bsRwPL/btrTseLKwZv/Xr6lbMtsyTKv5x4W8SsUjK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bsRwPL/btrTseLKwZv/Xr6lbMtsyTKv5x4W8SsUjK/img.png&quot; data-origin-width=&quot;297&quot; data-origin-height=&quot;668&quot; data-is-animation=&quot;false&quot; style=&quot;width: 32.3841%;&quot; data-widthpercent=&quot;33.15&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bsRwPL/btrTseLKwZv/Xr6lbMtsyTKv5x4W8SsUjK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbsRwPL%2FbtrTseLKwZv%2FXr6lbMtsyTKv5x4W8SsUjK%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;297&quot; height=&quot;668&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;꽃다발 생성 2 (개봉일 전에는 봉오리 상태)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgYl7S/btrTtBNc9lS/TQYXz4fI3lLCjU6U6NaqSk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgYl7S/btrTtBNc9lS/TQYXz4fI3lLCjU6U6NaqSk/img.png&quot; style=&quot;width: 48.901%; margin-right: 10px;&quot; data-origin-width=&quot;295&quot; data-origin-height=&quot;671&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;49.48&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgYl7S/btrTtBNc9lS/TQYXz4fI3lLCjU6U6NaqSk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgYl7S%2FbtrTtBNc9lS%2FTQYXz4fI3lLCjU6U6NaqSk%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;295&quot; height=&quot;671&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NdZs9/btrTt1ktE8P/5q0YX8Y0ktIyebzi6D6PIk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NdZs9/btrTt1ktE8P/5q0YX8Y0ktIyebzi6D6PIk/img.png&quot; style=&quot;width: 49.9362%;&quot; data-origin-width=&quot;299&quot; data-origin-height=&quot;666&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;50.52&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NdZs9/btrTt1ktE8P/5q0YX8Y0ktIyebzi6D6PIk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNdZs9%2FbtrTt1ktE8P%2F5q0YX8Y0ktIyebzi6D6PIk%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;299&quot; height=&quot;666&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;새 메시지 작성&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bWo1Mj/btrTuliOiGN/KvjfjO7HKTKRJn9lNozerK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bWo1Mj/btrTuliOiGN/KvjfjO7HKTKRJn9lNozerK/img.png&quot; data-origin-width=&quot;296&quot; data-origin-height=&quot;670&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;33.26&quot; style=&quot;width: 32.482%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bWo1Mj/btrTuliOiGN/KvjfjO7HKTKRJn9lNozerK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbWo1Mj%2FbtrTuliOiGN%2FKvjfjO7HKTKRJn9lNozerK%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;296&quot; height=&quot;670&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ij7wn/btrTvYHpOgi/8xdravtBcMLDFrCk78V6M1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ij7wn/btrTvYHpOgi/8xdravtBcMLDFrCk78V6M1/img.png&quot; data-origin-width=&quot;296&quot; data-origin-height=&quot;668&quot; data-is-animation=&quot;false&quot; style=&quot;width: 32.5793%; margin-right: 10px;&quot; data-widthpercent=&quot;33.35&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ij7wn/btrTvYHpOgi/8xdravtBcMLDFrCk78V6M1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIj7wn%2FbtrTvYHpOgi%2F8xdravtBcMLDFrCk78V6M1%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;296&quot; height=&quot;668&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bVKrhq/btrTthuFeFG/gMOG6HYN7yX2E34MC99PV0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bVKrhq/btrTthuFeFG/gMOG6HYN7yX2E34MC99PV0/img.png&quot; data-origin-width=&quot;283&quot; data-origin-height=&quot;638&quot; data-is-animation=&quot;false&quot; style=&quot;width: 32.6131%;&quot; data-widthpercent=&quot;33.39&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bVKrhq/btrTthuFeFG/gMOG6HYN7yX2E34MC99PV0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbVKrhq%2FbtrTthuFeFG%2FgMOG6HYN7yX2E34MC99PV0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;283&quot; height=&quot;638&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;개봉일 이후 메시지 확인 및 신고 기능&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/q9Pfv/btrTqEX9SpP/8bYBqz5y7qTGBbkrSHSqA1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/q9Pfv/btrTqEX9SpP/8bYBqz5y7qTGBbkrSHSqA1/img.png&quot; data-origin-width=&quot;296&quot; data-origin-height=&quot;664&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.6136%; margin-right: 10px;&quot; data-widthpercent=&quot;50.2&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/q9Pfv/btrTqEX9SpP/8bYBqz5y7qTGBbkrSHSqA1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fq9Pfv%2FbtrTqEX9SpP%2F8bYBqz5y7qTGBbkrSHSqA1%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;296&quot; height=&quot;664&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cTk7Z4/btrTseSwHhW/pqh2ub4UdnnSCFgzyjkvyk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cTk7Z4/btrTseSwHhW/pqh2ub4UdnnSCFgzyjkvyk/img.png&quot; data-origin-width=&quot;295&quot; data-origin-height=&quot;667&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.2236%;&quot; data-widthpercent=&quot;49.8&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cTk7Z4/btrTseSwHhW/pqh2ub4UdnnSCFgzyjkvyk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcTk7Z4%2FbtrTseSwHhW%2Fpqh2ub4UdnnSCFgzyjkvyk%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;295&quot; height=&quot;667&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;꽃다발 결제 1&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nm0nF/btrTmZ2LQhI/vBl5BaX3ERiG78upXGtnt0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nm0nF/btrTmZ2LQhI/vBl5BaX3ERiG78upXGtnt0/img.png&quot; data-origin-width=&quot;298&quot; data-origin-height=&quot;665&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.7153%; margin-right: 10px;&quot; data-widthpercent=&quot;50.3&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nm0nF/btrTmZ2LQhI/vBl5BaX3ERiG78upXGtnt0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fnm0nF%2FbtrTmZ2LQhI%2FvBl5BaX3ERiG78upXGtnt0%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;298&quot; height=&quot;665&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cuqkn8/btrTvk4TP4K/sadrdcNvQhWMjeoJd2k20k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cuqkn8/btrTvk4TP4K/sadrdcNvQhWMjeoJd2k20k/img.png&quot; data-origin-width=&quot;294&quot; data-origin-height=&quot;664&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.1219%;&quot; data-widthpercent=&quot;49.7&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cuqkn8/btrTvk4TP4K/sadrdcNvQhWMjeoJd2k20k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fcuqkn8%2FbtrTvk4TP4K%2FsadrdcNvQhWMjeoJd2k20k%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;294&quot; height=&quot;664&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;꽃다발 결제 2&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bWqfEf/btrTmuPlcHR/9zUbatYuS0QNUsFBoHBfg0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bWqfEf/btrTmuPlcHR/9zUbatYuS0QNUsFBoHBfg0/img.png&quot; data-origin-width=&quot;297&quot; data-origin-height=&quot;580&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;20.23&quot; style=&quot;width: 19.758%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bWqfEf/btrTmuPlcHR/9zUbatYuS0QNUsFBoHBfg0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbWqfEf%2FbtrTmuPlcHR%2F9zUbatYuS0QNUsFBoHBfg0%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;297&quot; height=&quot;580&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IyA6m/btrTu3vqrjh/ouy8tyWb0BbBhn10lTwAKk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IyA6m/btrTu3vqrjh/ouy8tyWb0BbBhn10lTwAKk/img.png&quot; data-origin-width=&quot;298&quot; data-origin-height=&quot;580&quot; data-is-animation=&quot;false&quot; style=&quot;width: 19.8245%; margin-right: 10px;&quot; data-widthpercent=&quot;20.3&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IyA6m/btrTu3vqrjh/ouy8tyWb0BbBhn10lTwAKk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIyA6m%2FbtrTu3vqrjh%2Fouy8tyWb0BbBhn10lTwAKk%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;298&quot; height=&quot;580&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cAfbpj/btrTtAOiFQX/JWyf1hGL6J91ruMGhixKrk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cAfbpj/btrTtAOiFQX/JWyf1hGL6J91ruMGhixKrk/img.png&quot; data-origin-width=&quot;676&quot; data-origin-height=&quot;449&quot; data-is-animation=&quot;false&quot; style=&quot;width: 58.0919%;&quot; data-widthpercent=&quot;59.47&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cAfbpj/btrTtAOiFQX/JWyf1hGL6J91ruMGhixKrk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcAfbpj%2FbtrTtAOiFQX%2FJWyf1hGL6J91ruMGhixKrk%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;676&quot; height=&quot;449&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;꽃다발 프린트&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bIPjW7/btrTseLKMkD/DfE3ZXXcIHRG0KYptUF8LK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bIPjW7/btrTseLKMkD/DfE3ZXXcIHRG0KYptUF8LK/img.png&quot; data-origin-width=&quot;296&quot; data-origin-height=&quot;666&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.7444%; margin-right: 10px;&quot; data-widthpercent=&quot;50.33&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bIPjW7/btrTseLKMkD/DfE3ZXXcIHRG0KYptUF8LK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbIPjW7%2FbtrTseLKMkD%2FDfE3ZXXcIHRG0KYptUF8LK%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;296&quot; height=&quot;666&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cqXFXH/btrTmZ2LQCJ/Ou55AhNxzNJmKhnWoRGHE1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cqXFXH/btrTmZ2LQCJ/Ou55AhNxzNJmKhnWoRGHE1/img.png&quot; data-origin-width=&quot;293&quot; data-origin-height=&quot;668&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.0928%;&quot; data-widthpercent=&quot;49.67&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cqXFXH/btrTmZ2LQCJ/Ou55AhNxzNJmKhnWoRGHE1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcqXFXH%2FbtrTmZ2LQCJ%2FOu55AhNxzNJmKhnWoRGHE1%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;293&quot; height=&quot;668&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;그린하우스 (롤링페이퍼 목록)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bBZciq/btrTqDStCDU/oOKqPb9oDkYFVAsM77vTYK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bBZciq/btrTqDStCDU/oOKqPb9oDkYFVAsM77vTYK/img.png&quot; data-origin-width=&quot;298&quot; data-origin-height=&quot;666&quot; data-is-animation=&quot;false&quot; data-widthpercent=&quot;50.01&quot; style=&quot;width: 49.4329%; margin-right: 10px;&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bBZciq/btrTqDStCDU/oOKqPb9oDkYFVAsM77vTYK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbBZciq%2FbtrTqDStCDU%2FoOKqPb9oDkYFVAsM77vTYK%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;298&quot; height=&quot;666&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/caIPGE/btrTvj5ZDbG/8urGuqncBLZvybcx3u9dhk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/caIPGE/btrTvj5ZDbG/8urGuqncBLZvybcx3u9dhk/img.png&quot; data-origin-width=&quot;326&quot; data-origin-height=&quot;729&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.4043%;&quot; data-widthpercent=&quot;49.99&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/caIPGE/btrTvj5ZDbG/8urGuqncBLZvybcx3u9dhk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcaIPGE%2FbtrTvj5ZDbG%2F8urGuqncBLZvybcx3u9dhk%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;326&quot; height=&quot;729&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;꽃가게 (꽃다발 및 꽃 구매)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zcjqw/btrTsnWbW6A/gQ1EQnh63080CZ993h4JbK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zcjqw/btrTsnWbW6A/gQ1EQnh63080CZ993h4JbK/img.png&quot; data-origin-width=&quot;302&quot; data-origin-height=&quot;692&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.1217%; margin-right: 10px;&quot; data-widthpercent=&quot;49.7&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zcjqw/btrTsnWbW6A/gQ1EQnh63080CZ993h4JbK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fzcjqw%2FbtrTsnWbW6A%2FgQ1EQnh63080CZ993h4JbK%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;302&quot; height=&quot;692&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dQaCH0/btrTul39S2H/Sg5yqhr2MwolIKX7kYdYRK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dQaCH0/btrTul39S2H/Sg5yqhr2MwolIKX7kYdYRK/img.png&quot; data-origin-width=&quot;303&quot; data-origin-height=&quot;686&quot; data-is-animation=&quot;false&quot; style=&quot;width: 49.7155%;&quot; data-widthpercent=&quot;50.3&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dQaCH0/btrTul39S2H/Sg5yqhr2MwolIKX7kYdYRK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdQaCH0%2FbtrTul39S2H%2FSg5yqhr2MwolIKX7kYdYRK%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;303&quot; height=&quot;686&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
  &lt;figcaption&gt;마이페이지&lt;/figcaption&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;5. 참고자료 및 기술 스택 관련 자료&lt;/b&gt;&lt;/h2&gt;
&lt;figure id=&quot;og_1670861174603&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Vite&quot; data-og-description=&quot;Vite, 차세대 프런트엔드 개발 툴&quot; data-og-host=&quot;vitejs-kr.github.io&quot; data-og-source-url=&quot;https://vitejs-kr.github.io/guide/&quot; data-og-url=&quot;https://vitejs-kr.github.io&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/ekVfz3/hyQRO1VsAO/OCGeOcKsY2oJTRdkkr16kk/img.png?width=2600&amp;amp;height=1302&amp;amp;face=0_0_2600_1302,https://scrap.kakaocdn.net/dn/FECKD/hyQRU8Uk00/rX3lsrLEnappYOHAEHkuWK/img.png?width=640&amp;amp;height=640&amp;amp;face=0_0_640_640&quot;&gt;&lt;a href=&quot;https://vitejs-kr.github.io/guide/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://vitejs-kr.github.io/guide/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/ekVfz3/hyQRO1VsAO/OCGeOcKsY2oJTRdkkr16kk/img.png?width=2600&amp;amp;height=1302&amp;amp;face=0_0_2600_1302,https://scrap.kakaocdn.net/dn/FECKD/hyQRU8Uk00/rX3lsrLEnappYOHAEHkuWK/img.png?width=640&amp;amp;height=640&amp;amp;face=0_0_640_640');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Vite&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Vite, 차세대 프런트엔드 개발 툴&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;vitejs-kr.github.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1670861188491&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Recoil&quot; data-og-description=&quot;A state management library for React.&quot; data-og-host=&quot;recoiljs.org&quot; data-og-source-url=&quot;https://recoiljs.org/ko/&quot; data-og-url=&quot;https://recoiljs.org/ko/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cKS6yE/hyQRPT3rCu/2ygkM5kCRwu3DrNfqlNjKk/img.png?width=1420&amp;amp;height=646&amp;amp;face=0_0_1420_646,https://scrap.kakaocdn.net/dn/b01Ehq/hyQRS4kJlY/xa1iiJ2epSoqUKdmpzJ791/img.png?width=1420&amp;amp;height=646&amp;amp;face=0_0_1420_646&quot;&gt;&lt;a href=&quot;https://recoiljs.org/ko/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://recoiljs.org/ko/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cKS6yE/hyQRPT3rCu/2ygkM5kCRwu3DrNfqlNjKk/img.png?width=1420&amp;amp;height=646&amp;amp;face=0_0_1420_646,https://scrap.kakaocdn.net/dn/b01Ehq/hyQRS4kJlY/xa1iiJ2epSoqUKdmpzJ791/img.png?width=1420&amp;amp;height=646&amp;amp;face=0_0_1420_646');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Recoil&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;A state management library for React.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;recoiljs.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1670861203652&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Redis&quot; data-og-description=&quot;Redis is an open source (BSD licensed), in-memory data structure store, used as a database, cache, and message broker&quot; data-og-host=&quot;redis.io&quot; data-og-source-url=&quot;https://redis.io/&quot; data-og-url=&quot;https://redis.io/&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://redis.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://redis.io/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Redis&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Redis is an open source (BSD licensed), in-memory data structure store, used as a database, cache, and message broker&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;redis.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1670861376580&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Kakao Developers&quot; data-og-description=&quot;카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.&quot; data-og-host=&quot;developers.kakao.com&quot; data-og-source-url=&quot;https://developers.kakao.com/docs/latest/ko/kakaopay/common&quot; data-og-url=&quot;https://developers.kakao.com/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/izaOf/hyQRMXly9Z/WoE2FUk4bMn0K7EzkZUoz0/img.png?width=800&amp;amp;height=400&amp;amp;face=0_0_800_400,https://scrap.kakaocdn.net/dn/dTVEaK/hyQRV05bVa/hRdONATDbKdE9mUbkKPigK/img.png?width=3840&amp;amp;height=1000&amp;amp;face=0_0_3840_1000,https://scrap.kakaocdn.net/dn/8zGeT/hyQRH9CphX/uErfnKXfDvEbzcUvrllYLK/img.png?width=3840&amp;amp;height=1000&amp;amp;face=0_0_3840_1000&quot;&gt;&lt;a href=&quot;https://developers.kakao.com/docs/latest/ko/kakaopay/common&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://developers.kakao.com/docs/latest/ko/kakaopay/common&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/izaOf/hyQRMXly9Z/WoE2FUk4bMn0K7EzkZUoz0/img.png?width=800&amp;amp;height=400&amp;amp;face=0_0_800_400,https://scrap.kakaocdn.net/dn/dTVEaK/hyQRV05bVa/hRdONATDbKdE9mUbkKPigK/img.png?width=3840&amp;amp;height=1000&amp;amp;face=0_0_3840_1000,https://scrap.kakaocdn.net/dn/8zGeT/hyQRH9CphX/uErfnKXfDvEbzcUvrllYLK/img.png?width=3840&amp;amp;height=1000&amp;amp;face=0_0_3840_1000');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Kakao Developers&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;developers.kakao.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1670861448125&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Code-Splitting &amp;ndash; React&quot; data-og-description=&quot;A JavaScript library for building user interfaces&quot; data-og-host=&quot;reactjs.org&quot; data-og-source-url=&quot;https://reactjs.org/docs/code-splitting.html&quot; data-og-url=&quot;https://reactjs.org/docs/code-splitting.html&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/mI6BM/hyQRKrINUM/KTMQvoRYUp1VmNAeZzKeK1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://reactjs.org/docs/code-splitting.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://reactjs.org/docs/code-splitting.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/mI6BM/hyQRKrINUM/KTMQvoRYUp1VmNAeZzKeK1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Code-Splitting &amp;ndash; React&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;A JavaScript library for building user interfaces&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;reactjs.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1670861499389&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;nginx 에 gzip 으로 컨텐츠 압축 설정하기&quot; data-og-description=&quot;&quot; data-og-host=&quot;www.lesstif.com&quot; data-og-source-url=&quot;https://www.lesstif.com/system-admin/nginx-gzip-59343019.html&quot; data-og-url=&quot;https://www.lesstif.com/system-admin/nginx-gzip-59343019.html&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/yKinT/hyQROARk33/cOg1PQibZ1oh9zHJp4oBw1/img.png?width=1039&amp;amp;height=602&amp;amp;face=0_0_1039_602&quot;&gt;&lt;a href=&quot;https://www.lesstif.com/system-admin/nginx-gzip-59343019.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.lesstif.com/system-admin/nginx-gzip-59343019.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/yKinT/hyQROARk33/cOg1PQibZ1oh9zHJp4oBw1/img.png?width=1039&amp;amp;height=602&amp;amp;face=0_0_1039_602');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;nginx 에 gzip 으로 컨텐츠 압축 설정하기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.lesstif.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category># 주저리주저리/가끔 하고 싶은 뻘소리</category>
      <category>7주 프로젝트</category>
      <category>flowerbada</category>
      <category>꽃바다</category>
      <category>자율프로젝트</category>
      <category>프로젝트회고</category>
      <category>프로젝트후기</category>
      <category>회고</category>
      <category>후기</category>
      <author>Ssoco</author>
      <guid isPermaLink="true">https://ssocoit.tistory.com/272</guid>
      <comments>https://ssocoit.tistory.com/272#entry272comment</comments>
      <pubDate>Tue, 13 Dec 2022 01:12:35 +0900</pubDate>
    </item>
    <item>
      <title>[Java] Java의 메모리 관리와 가비지컬렉션에 대하여</title>
      <link>https://ssocoit.tistory.com/271</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;이전 포스팅에서 Java의 컴파일 과정 및 JVM에 대해서 알아보았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1669598768431&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[Java] Java의 컴파일 과정을 최대한 쉽게 이해해보자&quot; data-og-description=&quot;도대체 .java 확장자 파일은 어떻게 우리가 원하는 대로 실행될 수 있을까요? 이것에 대한 궁금증을 갖고 Java의 컴파일 과정에 대해서 공부하게 되었습니다. 틀린 부분이 있다면 지체없이 댓글을 &quot; data-og-host=&quot;ssocoit.tistory.com&quot; data-og-source-url=&quot;https://ssocoit.tistory.com/270&quot; data-og-url=&quot;https://ssocoit.tistory.com/270&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/ciVXef/hyQJJedQ7R/EjAlneapAOrbiaYh3vI4vk/img.png?width=800&amp;amp;height=606&amp;amp;face=0_0_800_606,https://scrap.kakaocdn.net/dn/lUWJ5/hyQJBAt6gs/B6hIHaX3Ik5BFBLNonIQ00/img.png?width=800&amp;amp;height=606&amp;amp;face=0_0_800_606,https://scrap.kakaocdn.net/dn/UfsV2/hyQJxri7Vw/BpgAX1jTg9WK1MS3U9nI11/img.png?width=933&amp;amp;height=1106&amp;amp;face=0_0_933_1106&quot;&gt;&lt;a href=&quot;https://ssocoit.tistory.com/270&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://ssocoit.tistory.com/270&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/ciVXef/hyQJJedQ7R/EjAlneapAOrbiaYh3vI4vk/img.png?width=800&amp;amp;height=606&amp;amp;face=0_0_800_606,https://scrap.kakaocdn.net/dn/lUWJ5/hyQJBAt6gs/B6hIHaX3Ik5BFBLNonIQ00/img.png?width=800&amp;amp;height=606&amp;amp;face=0_0_800_606,https://scrap.kakaocdn.net/dn/UfsV2/hyQJxri7Vw/BpgAX1jTg9WK1MS3U9nI11/img.png?width=933&amp;amp;height=1106&amp;amp;face=0_0_933_1106');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[Java] Java의 컴파일 과정을 최대한 쉽게 이해해보자&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;도대체 .java 확장자 파일은 어떻게 우리가 원하는 대로 실행될 수 있을까요? 이것에 대한 궁금증을 갖고 Java의 컴파일 과정에 대해서 공부하게 되었습니다. 틀린 부분이 있다면 지체없이 댓글을&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;ssocoit.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것저것 다룬다고 직접 그림까지 그려가며 작성했는데, &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;각각의 메모리의 역할(특히 Heap과 Stack 영역)&lt;/b&gt;&lt;/span&gt;과 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;실행 엔진의 가비지컬렉션&lt;/b&gt;&lt;/span&gt;에 대한 부분은 간단하게 언급만 하고 넘어갔었죠?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 부분에 대해 보다 자세히 알아보기 위해서 다시 한번 포스팅을 작성합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class=&quot;book-toc&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;목차&lt;/p&gt;
&lt;ul id=&quot;toc&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;/ul&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;0. 가비지컬렉션이란?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특정한 인스턴스가 생성되어 메모리 공간을 차지한 상태에서 해당 인스턴스가 더이상 사용되지 않는 상황이 되었다면 그 인스턴스는 Garbage가 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C와 C++의 경우 이렇게 불필요하게 메모리를 잡아먹고 있는 인스턴스를 직접 제거해줘야 하지만, Java의 경우 JVM이 알아서 불필요한 메모리를 정리해줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것을 바로 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;가비지컬렉션(이하 GC)&lt;/b&gt;&lt;/span&gt;이라고 부릅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본적으로 JVM이 알아서 정리해주지만,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;System.gc();&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;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;Runtime.getRuntime().gc();&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;를 호출하여 명시적으로 GC를 발생시킬 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1669619410675&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;System (Java Platform SE 8 )&quot; data-og-description=&quot;Sets the system property indicated by the specified key. First, if a security manager exists, its SecurityManager.checkPermission method is called with a PropertyPermission(key, &amp;quot;write&amp;quot;) permission. This may result in a SecurityException being thrown. If n&quot; data-og-host=&quot;docs.oracle.com&quot; data-og-source-url=&quot;https://docs.oracle.com/javase/8/docs/api/java/lang/System.html#gc--&quot; data-og-url=&quot;https://docs.oracle.com/javase/8/docs/api/java/lang/System.html#gc--&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://docs.oracle.com/javase/8/docs/api/java/lang/System.html#gc--&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.oracle.com/javase/8/docs/api/java/lang/System.html#gc--&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;System (Java Platform SE 8 )&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Sets the system property indicated by the specified key. First, if a security manager exists, its SecurityManager.checkPermission method is called with a PropertyPermission(key, &quot;write&quot;) permission. This may result in a SecurityException being thrown. If n&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.oracle.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1814&quot; data-origin-height=&quot;415&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b9ZKTr/btrSlYWar8R/xdunQnkdgnCkJZ9zzxaic1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b9ZKTr/btrSlYWar8R/xdunQnkdgnCkJZ9zzxaic1/img.png&quot; data-alt=&quot;출처:https://docs.oracle.com/javase/8/docs/api/java/lang/System.html#gc--&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b9ZKTr/btrSlYWar8R/xdunQnkdgnCkJZ9zzxaic1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb9ZKTr%2FbtrSlYWar8R%2FxdunQnkdgnCkJZ9zzxaic1%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;1814&quot; height=&quot;415&quot; data-origin-width=&quot;1814&quot; data-origin-height=&quot;415&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처:https://docs.oracle.com/javase/8/docs/api/java/lang/System.html#gc--&lt;/figcaption&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;하지만 이 방식의 경우 개발자가 GC를 컨트롤하는 것이기 때문에 휴먼 에러가 발생할 확률이 높기 때문에 권장하지 않는 방식입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GC 한번에.. 약 20000배의 속도차이를 보여주는 모습...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JVM을 믿읍시다 (?)&lt;/p&gt;
&lt;pre id=&quot;code_1669619701167&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class GCTimeCheck {
    public static void main(String[] args) {
        long startTime = System.nanoTime();
        long endTime = System.nanoTime();
        System.out.println(endTime - startTime + &quot;ns&quot;); // 약 300ns
    }
}

public class GCTimeCheck2 {
    public static void main(String[] args) {
        long startTime = System.nanoTime();
        System.gc();
        long endTime = System.nanoTime();
        System.out.println(endTime - startTime + &quot;ns&quot;); // 약 7000000ns
    }
}&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. Java의 메모리 관리&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전 포스팅에서 Heap 영역에 대해서 간단하게 인스턴스나 객체가 생성되는 경우에 Heap영역에 저장된다고 했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 Heap 영역에 할당되었던 메모리는 사용이 되지 않는다고 하더라도 자동으로 사라지지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반면 Stack 영역의 경우 메서드가 생성될 때 스택 프레임이 생성됐다가 메서드가 종료되면 해당 스택 프레임이 자동으로 pop되기 때문에 GC가 필요하지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(TMI : &lt;span style=&quot;color: #009a87;&quot;&gt;&lt;b&gt;Java 메모리의 Heap 영역&lt;/b&gt;&lt;/span&gt;과 &lt;b&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;자료구조에서의 Heap&lt;/span&gt;&lt;/b&gt;은 다른 Heap이니 조심!!)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1.0. Heap 영역과 Stack 영역을 활용한 관리 예시&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이해를 돕기 위해 아래 예시를 하나 들고왔습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1669613876397&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class HeapTest {
    public static void main(String[] args) {
        String t = null; // Integer 타입의 객체 t 선언 및 Stack 영역에 공간 할당
        System.out.println(t); // null
        t = &quot;ㅎㅇ&quot;; // Heap 영역에 &quot;ㅎㅇ&quot;를 할당하고, 객체 t에 &quot;ㅎㅇ&quot;가 저장된 주소를 할당
        System.out.println(t); // @32ab41b2
        t = &quot;ㅂㅇ&quot;; // Heap 영역에 &quot;ㅂㅇ&quot;를 할당하고, 객체 t에 &quot;ㅎㅇ&quot;의 주소가 아닌 &quot;ㅂㅇ&quot;가 저장된 주소를 할당
        System.out.println(t); // @32abd256
    }
}&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;t라는 지역변수의 경우 Stack 영역에 할당되고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;null, &quot;ㅎㅇ&quot;, &quot;ㅂㅇ&quot; 와 같은 데이터들은 Heap 영역에 할당됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단히 말해서, 모든 Object 타입(Integer, String, ArrayList) 등은 Heap 영역에 생성되고, Heap 영역에 있는 오브젝트를 가리키는 레퍼런스 변수들이 Stack 영역에 할당되는 것이죠,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(String의 상위 객체는 Object라는 것을 생각하면 쉽게 이해할 수 있습니다!)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 예시와 같은 상황에서 &quot;ㅎㅇ&quot;는 더이상 참조되지 않기 때문에 GC의 대상이 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;757&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vM4t8/btrSkDdeM8Q/PkBawjIOTynAkUzkI8r961/img.jpg&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vM4t8/btrSkDdeM8Q/PkBawjIOTynAkUzkI8r961/img.jpg&quot; data-alt=&quot;출처:https://dzone.com/articles/java-memory-management&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vM4t8/btrSkDdeM8Q/PkBawjIOTynAkUzkI8r961/img.jpg&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvM4t8%2FbtrSkDdeM8Q%2FPkBawjIOTynAkUzkI8r961%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;1280&quot; height=&quot;757&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;757&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처:https://dzone.com/articles/java-memory-management&lt;/figcaption&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. Heap 영역의 구조&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;791&quot; data-origin-height=&quot;442&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kRM1Z/btrSkFJmnhZ/1yRmhHzHT4HD3j39Gy7JqK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kRM1Z/btrSkFJmnhZ/1yRmhHzHT4HD3j39Gy7JqK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kRM1Z/btrSkFJmnhZ/1yRmhHzHT4HD3j39Gy7JqK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkRM1Z%2FbtrSkFJmnhZ%2F1yRmhHzHT4HD3j39Gy7JqK%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;791&quot; height=&quot;442&quot; data-origin-width=&quot;791&quot; data-origin-height=&quot;442&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;GC의 등장 배경과 예시를 살펴보았으니, Heap 영역의 구조에 대해 조금 더 심도있게 살펴봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JVM은 이런 Heap 영역에 저장되는 데이터 및 메모리를 효율적으로 최적화하기 위해서 여러 공간을 나눠서 사용하고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Heap 영역의 경우 크게 &lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;Young Generation(이하 Young 영역)&lt;/b&gt;&lt;/span&gt;과 &lt;b&gt;&lt;span style=&quot;color: #7e98b1;&quot;&gt;Old Generation(이하 Old 영역)&lt;/span&gt;&lt;/b&gt;으로 나뉘어집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2.0. Young Generation&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인스턴스를 처음 생성하면 &lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;Young 영역&lt;/b&gt;&lt;/span&gt;의 메모리가 배정됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 그 중에서도 맨 처음에는 &lt;span style=&quot;color: #009a87;&quot;&gt;&lt;b&gt;Eden&lt;/b&gt;&lt;b&gt;&amp;nbsp;영역&lt;/b&gt;&lt;/span&gt;에 할당이 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러다가 &lt;b&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;Eden 영역&lt;/span&gt;&lt;/b&gt;이 꽉 차서 더이상 메모리를 할당할 수 없는 상황이 되면,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;Minor GC(Minor Garbage Collection)&lt;/b&gt;&lt;/span&gt;에 의해서 Eden 영역에 있는 요소의 참조 여부를 살피고 GC를 진행합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;Young 영역에서 발생하는 GC&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;를 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;Minor GC&lt;/b&gt;&lt;/span&gt;라고 부릅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 한번 GC가 되어서 정리된 데이터들은 &lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;Survivor Space&lt;/b&gt;&lt;/span&gt;로 이동됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼 여기서 궁금증이 하나 생깁니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;Survivor Space&lt;/b&gt;&lt;/span&gt;가 2개가 있는데, 어떤걸 쓰냐는 의문점이 생길 수 있죠.&lt;/p&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: #ee2323;&quot;&gt;&lt;b&gt;Minor GC&lt;/b&gt;&lt;/span&gt;가 끝난 데이터들은 먼저 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;S0 영역&lt;/b&gt;&lt;/span&gt;으로 이동합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 &lt;span style=&quot;color: #009a87;&quot;&gt;&lt;b&gt;Eden 영역&lt;/b&gt;&lt;/span&gt;과 &lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;S1 영역&lt;/span&gt;&lt;/b&gt;이 Clear됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(S1영역에 뭐가 없는데 왜 Clear하는 지 궁금하시다면, S1영역도 Minor GC가 일어나긴 했는데 아직 안에 내용물이 없기 때문에 생략한 것입니다!)&lt;/p&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: #009a87;&quot;&gt;&lt;b&gt;Eden 영역&lt;/b&gt;&lt;/span&gt;을 채웁니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 &lt;span style=&quot;color: #009a87;&quot;&gt;&lt;b&gt;Eden 영역&lt;/b&gt;&lt;/span&gt;이 다시 꽉 찹니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번엔 &lt;span style=&quot;color: #009a87;&quot;&gt;&lt;b&gt;Eden 영역&lt;/b&gt;&lt;/span&gt;과 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;S0 영역&lt;/b&gt;&lt;/span&gt;에 대해서 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;Minor GC&lt;/b&gt;&lt;/span&gt;가 발생합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서도 살아남은 친구들은 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;S1 영역&lt;/b&gt;&lt;/span&gt;으로 복사되고, &lt;span style=&quot;color: #009a87;&quot;&gt;&lt;b&gt;Eden 영역&lt;/b&gt;&lt;/span&gt;과 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;S0 영역&lt;/b&gt;&lt;/span&gt;이 Clear됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정리하면 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;S0, S1 영역&lt;/b&gt;&lt;/span&gt;중에서 하나의 영역에만 데이터가 존재하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;&lt;b&gt;Eden 영역&lt;/b&gt;&lt;/span&gt;과 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;S0, S1 영역&lt;/b&gt;&lt;/span&gt;중 하나에 대한 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;Minor GC&lt;/b&gt;&lt;/span&gt;의 결과물을 &lt;b&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;Minor GC&lt;/span&gt;&lt;/b&gt;가 진행되지 않은 &lt;b&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;Survivor Space&lt;/span&gt;&lt;/b&gt;에 옮겨놓고 기존 영역들을 정리하는 방식인 것이죠!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2.1. Old Generation&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;반복되는 과정 속에서 S0 영역과 S1 영역을 반복적으로 이동하는 데이터가 있을 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 친구들은 age값이 증가하게 되는데, 특정 값 이상이 되면 Old Generation으로 데이터가 옮겨지게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 &lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;Young 영역&lt;/b&gt;&lt;/span&gt;에서 &lt;span style=&quot;color: #7e98b1;&quot;&gt;&lt;b&gt;Old 영역&lt;/b&gt;&lt;/span&gt;으로 데이터가 옮겨지는 것을 &lt;b&gt;&lt;span style=&quot;color: #f3c000;&quot;&gt;Promotion&lt;/span&gt;&lt;/b&gt;이라고 부릅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #f3c000;&quot;&gt;&lt;b&gt;Promotion&lt;/b&gt;&lt;/span&gt;이 반복되면 &lt;span style=&quot;color: #7e98b1;&quot;&gt;&lt;b&gt;Old 영역&lt;/b&gt;&lt;/span&gt;에 데이터가 쌓이게 되고, &lt;span style=&quot;color: #009a87;&quot;&gt;&lt;b&gt;Eden 영역&lt;/b&gt;&lt;/span&gt;과 같은 방식으로 &lt;span style=&quot;color: #7e98b1;&quot;&gt;&lt;b&gt;Old 영역&lt;/b&gt;&lt;/span&gt; 역시 GC를 통해 메모리에서 필요없어진 요소들을 제거하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;Old 영역에서 발생하는 GC&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;를 &lt;span style=&quot;color: #781b33;&quot;&gt;&lt;b&gt;Major GC&lt;/b&gt;&lt;/span&gt;라고 부릅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 Heap 전체에 대해서 GC가 동작하는 것, &lt;b&gt;&lt;span style=&quot;color: #781b33;&quot;&gt;Major GC&lt;/span&gt;&lt;/b&gt;와 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;Minor GC&lt;/b&gt;&lt;/span&gt;가 동시에 일어나는 것을 &lt;span style=&quot;color: #1a5490;&quot;&gt;&lt;b&gt;Full GC&lt;/b&gt;&lt;/span&gt;라고 부릅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아주 드문 경우지만, &lt;span style=&quot;color: #7e98b1;&quot;&gt;&lt;b&gt;Old 영역&lt;/b&gt;&lt;/span&gt;에서 &lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;Young 영역&lt;/b&gt;&lt;/span&gt;을 참조하는 경우가 있을 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 경우를 대비해서 Old 영역에는 참조 확인 용도의 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;카드 테이블&lt;/b&gt;&lt;/span&gt;이 존재해서, &lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;Young 영역&lt;/b&gt;&lt;/span&gt;의 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;Minor GC&lt;/b&gt;&lt;/span&gt;가 동작할 때 모든 &lt;span style=&quot;color: #7e98b1;&quot;&gt;&lt;b&gt;Old 영역&lt;/b&gt;&lt;/span&gt;의 요소를 확인하는 것이 아닌 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;해당 카드 테이블&lt;/b&gt;&lt;/span&gt;만 확인하는 방식을 사용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;517&quot; data-origin-height=&quot;312&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JQuNR/btrSjohdttk/22Ro0RPKSpCmeUnk2XL7q1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JQuNR/btrSjohdttk/22Ro0RPKSpCmeUnk2XL7q1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JQuNR/btrSjohdttk/22Ro0RPKSpCmeUnk2XL7q1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJQuNR%2FbtrSjohdttk%2F22Ro0RPKSpCmeUnk2XL7q1%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;517&quot; height=&quot;312&quot; data-origin-width=&quot;517&quot; data-origin-height=&quot;312&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3. Garbage Collection의 동작방식&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그렇다면 JVM은 어떤 방식으로 GC 대상을 파악하는 걸까요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;적용 알고리즘의 경우 Serial GC, Parallel GC, CMS GC, G1 GC 등등 다양하지만, 기본적으로 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;Stop The World&lt;/b&gt;&lt;/span&gt;와 &lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;Mark &amp;amp; Sweep&lt;/b&gt;&lt;/span&gt;에 기초를 두고 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 GC를 하기 위해 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;Stop The World&lt;/b&gt;&lt;/span&gt;를 진행합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;Marking 작업을 위해서 모든 스레드를 중단&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;시키는데, 이것을 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;Stop The World&lt;/b&gt;&lt;/span&gt;라고 부릅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(GC를 튜닝하는 과정은 이 Stop The World 시간을 줄이는 것이라고 보시면 됩니다!)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 스레드를 멈추고, 스택 내의 모든 지역 변수를 스캔하면서 각각 어떤 오브젝트를 참조하고 있는지를 찾는 과정이 바로 Marking 작업이고, 참조가 되어있지 않은 오브젝트들을 Heap에서 제거(Sweep)하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방식을 &lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;Mark &amp;amp; Sweep&lt;/b&gt;&lt;/span&gt;이라고 부릅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;각각의 GC 알고리즘에 대해 더 자세하게 알고 싶다면 아래 사이트들을 확인하시면 됩니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1669619064460&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Java Garbage Collection Basics&quot; data-og-description=&quot;Java Overview Java is a programming language and computing platform first released by Sun Microsystems in 1995. It is the underlying technology that powers Java programs including utilities, games, and business applications. Java runs on more than 850 mill&quot; data-og-host=&quot;www.oracle.com&quot; data-og-source-url=&quot;https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html&quot; data-og-url=&quot;https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bxzAO5/hyQJGBYpkD/Pxb9G1lNO78cpXyMJCZlU1/img.png?width=960&amp;amp;height=720&amp;amp;face=0_0_960_720,https://scrap.kakaocdn.net/dn/Qk8qH/hyQJzCPL0u/p6EcBeo1iksPSqkfW8viVK/img.png?width=960&amp;amp;height=720&amp;amp;face=0_0_960_720,https://scrap.kakaocdn.net/dn/c0IGm6/hyQHZb4VNV/oCB4KfO5nw8du6upTqIsC0/img.png?width=960&amp;amp;height=720&amp;amp;face=0_0_960_720&quot;&gt;&lt;a href=&quot;https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bxzAO5/hyQJGBYpkD/Pxb9G1lNO78cpXyMJCZlU1/img.png?width=960&amp;amp;height=720&amp;amp;face=0_0_960_720,https://scrap.kakaocdn.net/dn/Qk8qH/hyQJzCPL0u/p6EcBeo1iksPSqkfW8viVK/img.png?width=960&amp;amp;height=720&amp;amp;face=0_0_960_720,https://scrap.kakaocdn.net/dn/c0IGm6/hyQHZb4VNV/oCB4KfO5nw8du6upTqIsC0/img.png?width=960&amp;amp;height=720&amp;amp;face=0_0_960_720');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Java Garbage Collection Basics&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Java Overview Java is a programming language and computing platform first released by Sun Microsystems in 1995. It is the underlying technology that powers Java programs including utilities, games, and business applications. Java runs on more than 850 mill&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.oracle.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1669619045606&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Garbage Collection (GC) : 가비지 컬렉션&quot; data-og-description=&quot;Garbage Collection java에서는 개발자가 코드로 메모리를 명시적으로 해제하지 않기 때문에 Garbage Collector가 더이상 필요없는 객체를 찾아 지우는 작업을 한다. stop-the-world GC를 실행하기 위해 JVM이 애&quot; data-og-host=&quot;seungahyoo.tistory.com&quot; data-og-source-url=&quot;https://seungahyoo.tistory.com/84&quot; data-og-url=&quot;https://seungahyoo.tistory.com/84&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bHzFns/hyQJxyfXSJ/3MSkwieCrbXolaI0Te5WT1/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/bJikyA/hyQH3MjVAm/rYuBaJfklxRa11BNnjiSM1/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/by6OQo/hyQJIGyZIC/FAWZ5duWoPBpCcEqFTKC1K/img.png?width=355&amp;amp;height=665&amp;amp;face=0_0_355_665&quot;&gt;&lt;a href=&quot;https://seungahyoo.tistory.com/84&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://seungahyoo.tistory.com/84&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bHzFns/hyQJxyfXSJ/3MSkwieCrbXolaI0Te5WT1/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/bJikyA/hyQH3MjVAm/rYuBaJfklxRa11BNnjiSM1/img.png?width=800&amp;amp;height=800&amp;amp;face=0_0_800_800,https://scrap.kakaocdn.net/dn/by6OQo/hyQJIGyZIC/FAWZ5duWoPBpCcEqFTKC1K/img.png?width=355&amp;amp;height=665&amp;amp;face=0_0_355_665');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Garbage Collection (GC) : 가비지 컬렉션&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Garbage Collection java에서는 개발자가 코드로 메모리를 명시적으로 해제하지 않기 때문에 Garbage Collector가 더이상 필요없는 객체를 찾아 지우는 작업을 한다. stop-the-world GC를 실행하기 위해 JVM이 애&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;seungahyoo.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;NAVER D2 - Java Garbage Collection&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://d2.naver.com/helloworld/1329&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://d2.naver.com/helloworld/1329&lt;/a&gt;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;4. 정리&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;가비지컬렉션(GC)&lt;/b&gt;&lt;/span&gt;는 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;Heap 영역에 있는 데이터들 중에서 불필요해진 데이터들을 자동으로 정리해주는 작업&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반적으로 JVM이 알아서 해주지만, 개발자가 임의로 진행할 수도 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 개발자가 직접 GC에 관여하는 방식은 권장하지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;동작 방식의 경우 Stop The World를 통해 스레드를 멈추고 Mark &amp;amp; Sweep 방식으로 더이상 참조되지 않는 요소들을 걸러내서 메모리에서 할당 해제를 진행하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 효율적인 Heap 메모리 사용을 위해 Young 영역과 Old 영역으로 나눠서 데이터를 관리하고, 각 영역의 GC를 Minor GC, Major GC라고 부르고 두 GC를 합쳐서 Full GC라고 부릅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한, JavaScript의 가비지컬렉션 동작 방식과도 굉장히 유사합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Java가 Stack 영역의 지역변수를 기준으로 marking 과정을 진행하고 참조 여부를 판단한다면, JavaScript는 root부터 root가 참조하는 모든 객체를 방문하고 mark 하는 방식으로 참조를 판단한다는 차이를 가지고 있습니다.&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;5. 참고자료&lt;/b&gt;&lt;/h2&gt;
&lt;figure id=&quot;og_1669620576450&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Java Garbage Collection Basics&quot; data-og-description=&quot;Java Overview Java is a programming language and computing platform first released by Sun Microsystems in 1995. It is the underlying technology that powers Java programs including utilities, games, and business applications. Java runs on more than 850 mill&quot; data-og-host=&quot;www.oracle.com&quot; data-og-source-url=&quot;https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html&quot; data-og-url=&quot;https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bxzAO5/hyQJGBYpkD/Pxb9G1lNO78cpXyMJCZlU1/img.png?width=960&amp;amp;height=720&amp;amp;face=0_0_960_720,https://scrap.kakaocdn.net/dn/Qk8qH/hyQJzCPL0u/p6EcBeo1iksPSqkfW8viVK/img.png?width=960&amp;amp;height=720&amp;amp;face=0_0_960_720,https://scrap.kakaocdn.net/dn/c0IGm6/hyQHZb4VNV/oCB4KfO5nw8du6upTqIsC0/img.png?width=960&amp;amp;height=720&amp;amp;face=0_0_960_720&quot;&gt;&lt;a href=&quot;https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.oracle.com/webfolder/technetwork/tutorials/obe/java/gc01/index.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bxzAO5/hyQJGBYpkD/Pxb9G1lNO78cpXyMJCZlU1/img.png?width=960&amp;amp;height=720&amp;amp;face=0_0_960_720,https://scrap.kakaocdn.net/dn/Qk8qH/hyQJzCPL0u/p6EcBeo1iksPSqkfW8viVK/img.png?width=960&amp;amp;height=720&amp;amp;face=0_0_960_720,https://scrap.kakaocdn.net/dn/c0IGm6/hyQHZb4VNV/oCB4KfO5nw8du6upTqIsC0/img.png?width=960&amp;amp;height=720&amp;amp;face=0_0_960_720');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Java Garbage Collection Basics&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Java Overview Java is a programming language and computing platform first released by Sun Microsystems in 1995. It is the underlying technology that powers Java programs including utilities, games, and business applications. Java runs on more than 850 mill&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.oracle.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1669620561396&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;자바 메모리 관리 - 가비지 컬렉션&quot; data-og-description=&quot;개요 Java 가비지 컬렉션에 대해서 공부한 내용을 정리해본다. Java 에서 메모리 관리는 어떻게 이루어지는지 이해하고 있으면 좋다. 자바 메모리 관리 - 스택 &amp;amp; 힙 를 먼저 읽는 것을 추천한다. 모&quot; data-og-host=&quot;yaboong.github.io&quot; data-og-source-url=&quot;https://yaboong.github.io/java/2018/06/09/java-garbage-collection/&quot; data-og-url=&quot;https://yaboong.github.io/java/2018/06/09/java-garbage-collection/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cD04ji/hyQH54sVBs/Chuvc6i9RkFZHaB5rpNrFK/img.png?width=1312&amp;amp;height=594&amp;amp;face=0_0_1312_594,https://scrap.kakaocdn.net/dn/bGdZOC/hyQH8GTAkx/jnp7iE2lRKxQcJLmyKan8k/img.png?width=1318&amp;amp;height=590&amp;amp;face=0_0_1318_590,https://scrap.kakaocdn.net/dn/bnrGH7/hyQHWsVE7X/PfWQQsD53ZtpZXdKQ4cgpk/img.png?width=1292&amp;amp;height=586&amp;amp;face=0_0_1292_586&quot;&gt;&lt;a href=&quot;https://yaboong.github.io/java/2018/06/09/java-garbage-collection/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://yaboong.github.io/java/2018/06/09/java-garbage-collection/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cD04ji/hyQH54sVBs/Chuvc6i9RkFZHaB5rpNrFK/img.png?width=1312&amp;amp;height=594&amp;amp;face=0_0_1312_594,https://scrap.kakaocdn.net/dn/bGdZOC/hyQH8GTAkx/jnp7iE2lRKxQcJLmyKan8k/img.png?width=1318&amp;amp;height=590&amp;amp;face=0_0_1318_590,https://scrap.kakaocdn.net/dn/bnrGH7/hyQHWsVE7X/PfWQQsD53ZtpZXdKQ4cgpk/img.png?width=1292&amp;amp;height=586&amp;amp;face=0_0_1292_586');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;자바 메모리 관리 - 가비지 컬렉션&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;개요 Java 가비지 컬렉션에 대해서 공부한 내용을 정리해본다. Java 에서 메모리 관리는 어떻게 이루어지는지 이해하고 있으면 좋다. 자바 메모리 관리 - 스택 &amp;amp; 힙 를 먼저 읽는 것을 추천한다. 모&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;yaboong.github.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1669620568682&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[자바 기초] 3. 자바의 동작원리 : Garbage Collection&quot; data-og-description=&quot;1. Garbage Collection(GC) 개념 기본 개념은 쉽다. 어떤 인스턴스가 생성되어 메모리 공간을 차지한 상태에서 해당 인스턴스가 프로그램에서 사용되지 않게 되었다면(null 처리 되었거나 해당 인스턴스&quot; data-og-host=&quot;whitepro.tistory.com&quot; data-og-source-url=&quot;https://whitepro.tistory.com/462&quot; data-og-url=&quot;https://whitepro.tistory.com/462&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/biD0ML/hyQJImfrUR/zBIYf6cJiNdFkzrOtEIig0/img.png?width=389&amp;amp;height=243&amp;amp;face=0_0_389_243,https://scrap.kakaocdn.net/dn/ceEFke/hyQH4YMq6M/drB8u6bj3kXw9ognfpoKzk/img.png?width=389&amp;amp;height=243&amp;amp;face=0_0_389_243,https://scrap.kakaocdn.net/dn/gK6U3/hyQH7gTswA/HGptAhPV6UaXC74VsOhqSK/img.png?width=828&amp;amp;height=293&amp;amp;face=0_0_828_293&quot;&gt;&lt;a href=&quot;https://whitepro.tistory.com/462&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://whitepro.tistory.com/462&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/biD0ML/hyQJImfrUR/zBIYf6cJiNdFkzrOtEIig0/img.png?width=389&amp;amp;height=243&amp;amp;face=0_0_389_243,https://scrap.kakaocdn.net/dn/ceEFke/hyQH4YMq6M/drB8u6bj3kXw9ognfpoKzk/img.png?width=389&amp;amp;height=243&amp;amp;face=0_0_389_243,https://scrap.kakaocdn.net/dn/gK6U3/hyQH7gTswA/HGptAhPV6UaXC74VsOhqSK/img.png?width=828&amp;amp;height=293&amp;amp;face=0_0_828_293');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[자바 기초] 3. 자바의 동작원리 : Garbage Collection&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;1. Garbage Collection(GC) 개념 기본 개념은 쉽다. 어떤 인스턴스가 생성되어 메모리 공간을 차지한 상태에서 해당 인스턴스가 프로그램에서 사용되지 않게 되었다면(null 처리 되었거나 해당 인스턴스&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;whitepro.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1669620588259&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Java Platform SE 8&quot; data-og-description=&quot;&quot; data-og-host=&quot;docs.oracle.com&quot; data-og-source-url=&quot;https://docs.oracle.com/javase/8/docs/api/&quot; data-og-url=&quot;https://docs.oracle.com/javase/8/docs/api/&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://docs.oracle.com/javase/8/docs/api/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.oracle.com/javase/8/docs/api/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Java Platform SE 8&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.oracle.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1669620601856&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;JAVA의 GC의 종류 및 특징&quot; data-og-description=&quot;GC(Garbage Collector) 란? JAVA 개발을 하면서 Out Of Memory Error는 접할 수 밖에 없으며, 해당 에러가 운영환경에서 발생하게 되었을 때 서비스 장애로 까지 이어 질 수 있다. 때문에 메모리를 괸리해주는 &quot; data-og-host=&quot;blog.ycpark.net&quot; data-og-source-url=&quot;https://blog.ycpark.net/entry/JAVA%EC%9D%98-GC%EC%9D%98-%EC%A2%85%EB%A5%98-%EB%B0%8F-%ED%8A%B9%EC%A7%95&quot; data-og-url=&quot;https://blog.ycpark.net/entry/JAVA%EC%9D%98-GC%EC%9D%98-%EC%A2%85%EB%A5%98-%EB%B0%8F-%ED%8A%B9%EC%A7%95&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bbwTNs/hyQJuBxWjS/hTCTIpdvQfTzxe3LB1YuY1/img.png?width=800&amp;amp;height=268&amp;amp;face=0_0_800_268,https://scrap.kakaocdn.net/dn/ba1FQc/hyQH0WouVQ/motCMLLB5xoFttFSB369ik/img.png?width=800&amp;amp;height=268&amp;amp;face=0_0_800_268,https://scrap.kakaocdn.net/dn/bZKtpO/hyQJxkJofK/VxqefQIjqs4Ktu5j5Pw7Kk/img.png?width=983&amp;amp;height=330&amp;amp;face=0_0_983_330&quot;&gt;&lt;a href=&quot;https://blog.ycpark.net/entry/JAVA%EC%9D%98-GC%EC%9D%98-%EC%A2%85%EB%A5%98-%EB%B0%8F-%ED%8A%B9%EC%A7%95&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://blog.ycpark.net/entry/JAVA%EC%9D%98-GC%EC%9D%98-%EC%A2%85%EB%A5%98-%EB%B0%8F-%ED%8A%B9%EC%A7%95&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bbwTNs/hyQJuBxWjS/hTCTIpdvQfTzxe3LB1YuY1/img.png?width=800&amp;amp;height=268&amp;amp;face=0_0_800_268,https://scrap.kakaocdn.net/dn/ba1FQc/hyQH0WouVQ/motCMLLB5xoFttFSB369ik/img.png?width=800&amp;amp;height=268&amp;amp;face=0_0_800_268,https://scrap.kakaocdn.net/dn/bZKtpO/hyQJxkJofK/VxqefQIjqs4Ktu5j5Pw7Kk/img.png?width=983&amp;amp;height=330&amp;amp;face=0_0_983_330');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;JAVA의 GC의 종류 및 특징&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;GC(Garbage Collector) 란? JAVA 개발을 하면서 Out Of Memory Error는 접할 수 밖에 없으며, 해당 에러가 운영환경에서 발생하게 되었을 때 서비스 장애로 까지 이어 질 수 있다. 때문에 메모리를 괸리해주는&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;blog.ycpark.net&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1669620615046&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[JAVA/자바] 메모리 구조(static, stack, heap)&quot; data-og-description=&quot;&amp;nbsp;이번 글은 자바(JAVA)를 사용하는 입장에서 알아야 할&amp;nbsp;메모리 구조 및 특징에 대해서 알아...&quot; data-og-host=&quot;blog.naver.com&quot; data-og-source-url=&quot;https://m.blog.naver.com/heartflow89/220954420688&quot; data-og-url=&quot;https://blog.naver.com/heartflow89/220954420688&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/6hRTo/hyQJB8wguv/ewA7TitkIa30jykR6zgibk/img.png?width=569&amp;amp;height=115&amp;amp;face=0_0_569_115&quot;&gt;&lt;a href=&quot;https://m.blog.naver.com/heartflow89/220954420688&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://m.blog.naver.com/heartflow89/220954420688&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/6hRTo/hyQJB8wguv/ewA7TitkIa30jykR6zgibk/img.png?width=569&amp;amp;height=115&amp;amp;face=0_0_569_115');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[JAVA/자바] 메모리 구조(static, stack, heap)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;이번 글은 자바(JAVA)를 사용하는 입장에서 알아야 할&amp;nbsp;메모리 구조 및 특징에 대해서 알아...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;blog.naver.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category># 공부 자료들/Java</category>
      <category>garbage collection</category>
      <category>GC</category>
      <category>Java</category>
      <category>가비지컬렉션</category>
      <category>메모리관리</category>
      <author>Ssoco</author>
      <guid isPermaLink="true">https://ssocoit.tistory.com/271</guid>
      <comments>https://ssocoit.tistory.com/271#entry271comment</comments>
      <pubDate>Mon, 28 Nov 2022 16:31:12 +0900</pubDate>
    </item>
    <item>
      <title>[Java] Java의 컴파일 과정을 최대한 쉽게 이해해보자</title>
      <link>https://ssocoit.tistory.com/270</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;도대체 .java 확장자 파일은 어떻게 우리가 원하는 대로 실행될 수 있을까요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것에 대한 궁금증을 갖고 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Java의 컴파일 과정&lt;/b&gt;&lt;/span&gt;에 대해서 공부하게 되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;틀린 부분이 있다면 지체없이 댓글을 남겨주시면 최대한 빠르게 수정하도록 하겠습니다!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class=&quot;book-toc&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;목차&lt;/p&gt;
&lt;ul id=&quot;toc&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;/ul&gt;
&lt;/div&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;0. 전체 실행 과정&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 사진은 전반적인 실행 과정을 간략하게 표시해놓은 그림입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;굉장히 복잡한 단어들이 나열되어있는 것 같지만, 하나하나 뜯어보면 처음 자바를 익히는 사람들도 충분히 이해할 수 있는 구조로 되어있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 하나하나 뜯어가며 살펴보도록 하죠!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1051&quot; data-origin-height=&quot;797&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/AJaIs/btrR835NMvS/YtkXSN5ynqqf9KvIScyB0k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/AJaIs/btrR835NMvS/YtkXSN5ynqqf9KvIScyB0k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/AJaIs/btrR835NMvS/YtkXSN5ynqqf9KvIScyB0k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FAJaIs%2FbtrR835NMvS%2FYtkXSN5ynqqf9KvIScyB0k%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;1051&quot; height=&quot;797&quot; data-origin-width=&quot;1051&quot; data-origin-height=&quot;797&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. JVM이란?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Java 이전 C와 C++의 경우 컴파일 플랫폼과 타겟 플랫폼이 다른 경우 프로그램이 동작하지 않는 경우가 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(이유는 운영체제, CPU 하드웨어 등 다양...)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;470&quot; data-origin-height=&quot;216&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/okrAG/btrSda3yZaC/mbERI0gxRgkAk5KgF4WhbK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/okrAG/btrSda3yZaC/mbERI0gxRgkAk5KgF4WhbK/img.png&quot; data-alt=&quot;출처 : 무민의 JVM Stack &amp;amp;amp; Heap 영상&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/okrAG/btrSda3yZaC/mbERI0gxRgkAk5KgF4WhbK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FokrAG%2FbtrSda3yZaC%2FmbERI0gxRgkAk5KgF4WhbK%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;470&quot; height=&quot;216&quot; data-origin-width=&quot;470&quot; data-origin-height=&quot;216&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처 : 무민의 JVM Stack &amp;amp; Heap 영상&lt;/figcaption&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;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;타겟 플랫폼에 맞춰서 컴파일하는 것&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;을 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;크로스컴파일&lt;/b&gt;&lt;/span&gt;이라고 부릅니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;460&quot; data-origin-height=&quot;207&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/CghRf/btrR9Xc3zAF/V6raVtGONXNJ9CMl7Dzpj1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/CghRf/btrR9Xc3zAF/V6raVtGONXNJ9CMl7Dzpj1/img.png&quot; data-alt=&quot;출처 : 무민의 JVM Stack &amp;amp;amp; Heap 영상&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/CghRf/btrR9Xc3zAF/V6raVtGONXNJ9CMl7Dzpj1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCghRf%2FbtrR9Xc3zAF%2FV6raVtGONXNJ9CMl7Dzpj1%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;460&quot; height=&quot;207&quot; data-origin-width=&quot;460&quot; data-origin-height=&quot;207&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처 : 무민의 JVM Stack &amp;amp; Heap 영상&lt;/figcaption&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;이렇게 복잡하게 타겟 플랫폼에 맞춰서 컴파일해야한다는 단점을 보완하기 위해서, Java의 바이트코드는 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;JVM(Java Virtual Machine)이라는 &lt;span style=&quot;background-color: #ffffff; text-align: justify;&quot;&gt;자바를 실행하기 위한 가상 기계&lt;/span&gt; 위에서 돌아감&lt;/b&gt;&lt;/span&gt;으로써 문제를 어느정도 해결할 수 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JVM이 설치된 플랫폼이라면 OS가 무엇이든 플랫폼이 뭐든 똑같이 바이트코드가 동작할 수 있는 것이죠!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(물론 JVM은 각 타겟 플랫폼에서 동작할 수 있는 버전이 설치되어있어야 합니다)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;604&quot; data-origin-height=&quot;223&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bhO0Kc/btrSas4W6h9/Rp6VotKohlfZzlnCK6G7pk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bhO0Kc/btrSas4W6h9/Rp6VotKohlfZzlnCK6G7pk/img.png&quot; data-alt=&quot;출처 : 무민의 JVM Stack &amp;amp;amp; Heap 영상&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bhO0Kc/btrSas4W6h9/Rp6VotKohlfZzlnCK6G7pk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbhO0Kc%2FbtrSas4W6h9%2FRp6VotKohlfZzlnCK6G7pk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;604&quot; height=&quot;223&quot; data-origin-width=&quot;604&quot; data-origin-height=&quot;223&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처 : 무민의 JVM Stack &amp;amp; Heap 영상&lt;/figcaption&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;그렇다면 Java가 크로스컴파일이 아닌 JVM방식을 선택한 이유는 무엇일까요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Java가 등장하던 시기는 새로운 운영체제 및 디바이스가 마구마구 출시되기 시작하던 시절이었고, 모든 운영체제 및 기종들에 대해서 컴파일을 고려하는 것은 굉장히 어려운 일이었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순히 JVM위에서 돌아갈 수 있게 해놓고, 각 운영체제 및 디바이스별로 JVM만 설치할 수 있다면 조금 더 편하게 모든 곳에서 동일하게 동작할 수 있는 시스템을 구축할 수 있을 것이라고 생각했기에 이런 방식을 선택했다고 보시면 되겠습니다!&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. 바이트코드 변환&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 JVM에 대해서도 어느 정도 이해했으니, 맨 윗 부분에 있던 자바 컴파일러에 의한 바이트코드 변환부터 차근차근 살펴봅시다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;435&quot; data-origin-height=&quot;195&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bLbfQ5/btrR9GvuE4X/77I1b0WPSKK42dXnq9009k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bLbfQ5/btrR9GvuE4X/77I1b0WPSKK42dXnq9009k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bLbfQ5/btrR9GvuE4X/77I1b0WPSKK42dXnq9009k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbLbfQ5%2FbtrR9GvuE4X%2F77I1b0WPSKK42dXnq9009k%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;435&quot; height=&quot;195&quot; data-origin-width=&quot;435&quot; data-origin-height=&quot;195&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;span style=&quot;background-color: #ffc1c8;&quot;&gt;&lt;b&gt;.java 파일&lt;/b&gt;&lt;/span&gt;을 생성하고 Build를 하게 되면,&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바 컴파일러의 javac라는 명령어를 사용하여 자바 바이트코드로 구성된&amp;nbsp;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;.class파일&lt;/span&gt;&lt;/b&gt;을 생성하게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;해당 클래스 파일을 통해서 어떤 환경에서든 같은 코드 결과를 얻을 수 있게 된겁니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(이 부분은 JVM의 클래스 로더를 설명하는 과정에서 다시 한 번 이해할 수 있습니다!!)&lt;/p&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;아래 첨부한 사진을 보시면, 실제로 .java파일을 javac를 이용하여 빌드한 후에 추출된 .class파일을 확인해보았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(왼쪽이 .java 파일, 오른쪽이 .class 바이트코드입니다)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;ICONST는 이미 저장되어있는 정수변수값을 가져올 때 사용하고, ISTORE는 사용하는 메모리단을 보여줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 IMUL과 ISUB는 각각 곱셈과 뺄셈을 담당한다는 것도 어렴풋이 알 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 우리가 어느 정도 알아들을 수 있게 컴파일됐다는 것은, .class파일이 완벽한 기계어가 아니라는 것의 한 가지 증거가 됩니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;933&quot; data-origin-height=&quot;1106&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dnd0I3/btrR8ySTw4i/HSjK9RHz0i5U617uTNVjY0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dnd0I3/btrR8ySTw4i/HSjK9RHz0i5U617uTNVjY0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dnd0I3/btrR8ySTw4i/HSjK9RHz0i5U617uTNVjY0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdnd0I3%2FbtrR8ySTw4i%2FHSjK9RHz0i5U617uTNVjY0%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;933&quot; height=&quot;1106&quot; data-origin-width=&quot;933&quot; data-origin-height=&quot;1106&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;추가로, 바이트코드는 JVM과 같은 가상머신이 이해할 수 있는 언어이고, 바이너리 코드는 CPU가 이해할 수 있는 언어입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바의 경우 자바 컴파일러가 JVM이 이해할 수 있도록 소스 파일을 .class 파일로 변환하는 것이고, C의 경우 한번에 바이너리코드로 변환하는 것이죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기까지 이해했다면, JVM이 바이트코드를 읽어와야 한다는 필요성을 느낄 수 있을 것입니다!&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3. 클래스 로더와 실행 엔진&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 추출해낸 .class파일은 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;클래스 로더&lt;/b&gt;&lt;/span&gt;에 의해서 JVM의 영역으로 들어가게 됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;878&quot; data-origin-height=&quot;455&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SHQHC/btrSeimMWRW/VFFyyrtiIR9GmkQeb23ar0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SHQHC/btrSeimMWRW/VFFyyrtiIR9GmkQeb23ar0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SHQHC/btrSeimMWRW/VFFyyrtiIR9GmkQeb23ar0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSHQHC%2FbtrSeimMWRW%2FVFFyyrtiIR9GmkQeb23ar0%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;878&quot; height=&quot;455&quot; data-origin-width=&quot;878&quot; data-origin-height=&quot;455&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;로딩 과정&lt;/b&gt;&lt;/span&gt;에서 메서드 영역에 클래스를 저장하고, &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;링크 과정&lt;/b&gt;&lt;/span&gt;에서 구성 요소를 검증하고 메모리를 할당한 후에, &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;초기화 과정&lt;/b&gt;&lt;/span&gt;에서 클래스 변수들을 적절한 값으로 초기화합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 클래스 로더는 하나만 존재하는 것이 아니라 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;계층적으로 존재&lt;/b&gt;&lt;/u&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: #000000;&quot;&gt;&lt;b&gt;Bootstrap Class Loader&lt;/b&gt;&lt;/span&gt;이 JVM을 기동할 때 생성되는 가장 기본적인 자바 API를 로드하는 클래스로더입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Extension Class Loader&lt;/b&gt;&lt;/span&gt;는 기본 자바 API를 제외한 나머지 확장 클래스를 로드하고, &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;System Class Loader&lt;/b&gt;&lt;/span&gt;는 애플리케이션의 클래스들을 로드합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 하위의 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;User-Defined Class Loader&lt;/b&gt;&lt;/span&gt;는 사용자가 직접 생성해서 사용하는 클래스 로더입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;311&quot; data-origin-height=&quot;268&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/chfYex/btrScabHtBw/xShekiwSKFzHxKVac0UsSk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/chfYex/btrScabHtBw/xShekiwSKFzHxKVac0UsSk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/chfYex/btrScabHtBw/xShekiwSKFzHxKVac0UsSk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FchfYex%2FbtrScabHtBw%2FxShekiwSKFzHxKVac0UsSk%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;311&quot; height=&quot;268&quot; data-origin-width=&quot;311&quot; data-origin-height=&quot;268&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;이렇게 어찌어찌 JVM에 들어온 바이트코드는 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;실행 엔진&lt;/b&gt;&lt;/span&gt;에 의해 기계어로 해석되어 메모리에 배치되고 실행됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;인터프리터 방식&lt;/b&gt;&lt;/span&gt;과 &lt;b&gt;&lt;span style=&quot;color: #f89009;&quot;&gt;JIT 컴파일러 방식&lt;/span&gt;&lt;/b&gt;으로 나눠집니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;인터프리터 방식&lt;/b&gt;&lt;/span&gt;의 경우 바이트 코드를 한 줄씩 읽고, &lt;span style=&quot;color: #f89009;&quot;&gt;&lt;b&gt;JIT 컴파일러 방식&lt;/b&gt;&lt;/span&gt;은 바이트 코드를 한번에 컴파일하고 캐싱하는 방식입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JVM은 기본적으로 인터프리터 방식을 사용하고, 내부적으로 특정 메서드가 얼마나 자주 수행되는지 체크하고 일정 정도를 넘을 때만 JIT 컴파일러 방식을 사용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 실행 엔진이 어떻게 동작하는 지는 JVM 명세에 규정되어있지 않기 때문에 JVM을 만들어내는 곳에서는 다양한 방식으로 실행 엔진을 최적화하고 있다고 합니다.&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;4. 런타임 데이터 영역&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 자바 컴파일 과정을 나타낸 그림의 최하단에 위치해있던 런타임 데이터 영역에 대해서 조금 더 자세하게 알아보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;495&quot; data-origin-height=&quot;200&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/csL4AP/btrR8VG5VTh/vxiQkq9Lk6fuCUfRTjDyf0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/csL4AP/btrR8VG5VTh/vxiQkq9Lk6fuCUfRTjDyf0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/csL4AP/btrR8VG5VTh/vxiQkq9Lk6fuCUfRTjDyf0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcsL4AP%2FbtrR8VG5VTh%2FvxiQkq9Lk6fuCUfRTjDyf0%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;495&quot; height=&quot;200&quot; data-origin-width=&quot;495&quot; data-origin-height=&quot;200&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;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;메서드 영역&lt;/b&gt;&lt;/span&gt;에 저장됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메서드 영역에는 클래스와 인터페이스에 대한 필드 및 메서드 정보, Static 변수, 메서드의 바이트코드 등등이 저장됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메서드 영역은 JVM을 어떻게 만드냐에 따라 다양한 형태로 구현할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특히 이 메서드 영역 안에는 &lt;b&gt;&lt;span style=&quot;color: #009a87;&quot;&gt;런타임 상수 풀(Runtime Constant Pool)&lt;/span&gt;&lt;/b&gt;이라는 영역도 존재하는데, 각 클래스와 인터페이스의 상수, 그리고 메서드의 모든 정보를 담고 있는 테이블을 의미합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JVM은 런타임 상수 풀에서 특정 메서드나 필드의 실제 메모리상의 주소를 찾아서 참조하게 됩니다.&lt;/p&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: #8a3db6;&quot;&gt;&lt;b&gt;힙 영역&lt;/b&gt;&lt;/span&gt;에 저장됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TMI 하나 방출하자면, 실행엔진의 가비지컬렉터는 보통 힙 영역의 메모리가 부족할 때 작동합니다.&lt;/p&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;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;모든 스레드가 공유한다는 특징&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;을 가지고 있습니다.&lt;/p&gt;
&lt;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: #7e98b1;&quot;&gt;&lt;b&gt;스택 영역&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;PC 레지스터 영역&lt;/b&gt;&lt;/span&gt;의 경우 현재 스레드가 수행중인 JVM 명령의 주소값이 담깁니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;멀티스레드 프로그래밍 환경에서 한 스레드가 작업하다가 다른 스레드로 잠시 CPU 점유를 넘겨주고 돌아왔을 때 어떤 일을 하고 있었는지 기억해야 거기서부터 다시 할 수 있겠죠?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이럴 때 사용되는 영역입니다.&lt;/p&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: #f89009;&quot;&gt;&lt;b&gt;네이티브 메서드 스택&lt;/b&gt;&lt;/span&gt;의 경우에는 Java의 바이트코드가 아닌 다른 언어(C, C++ 등..)로 작성된 메서드를 담아두는 공간입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스택 영역, PC 레지스터 영역, 네이티브 메서드 스택은 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;하나의 스레드가 생성될 때마다 같이 생성&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;이 되고, &lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;서로 다른 스레드가 침범할 수 없습니다&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;5. 정리&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;지금까지 Java의 컴파일 과정이 어떻게 진행되는지에 대해서 알아본 내용을 간단하게 정리해봅시다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 JVM을 사용하는 이유에 대해서 알아봤습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Java는 어디에서나 같은 결과물을 내기 위해서 JVM을 사용합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 다음에는 Java 컴파일 과정에 대해 하나하나 살펴보았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 개발자가 만든 .java 파일을 자바 컴파일러의 javac에 의해 JVM이 읽을 수 있는 바이트코드로 바꿉니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 바이트코드는 계층적으로 존재하는 JVM의 클래스 로더에 의해 JVM의 메모리에 할당되고 실행 엔진에 의해 기계어로 변환되고, 최종적으로 실행됩니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실행 엔진은 크게 두 가지로 나눌 수 있는데, 한줄씩 읽는 인터프리터 방식과 한번에 읽는 JIT 컴파일러 방식이 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;또한 런타임 데이터 영역에서 읽어들인 데이터를 저장하게 되는데, 메서드 영역과 힙 영역의 경우 모든 스레드가 공유하고, 스택 영역과 PC 레지스터 영역, 네이티브 메서드 영역은 하나의 스레드가 각각의 영역을 보유합니다.&lt;/p&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;엄청나게 어려워보였던 Java의 컴파일 과정이 어느 정도 요약이 되었을까요?!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가비지컬렉터가 동작하는 방식, 생성된 바이트 코드가 의미하는 것 등등 핵심 내용에서 살짝 벗어나기 때문에 다루지 않은 내용들도 존재하지만, Java의 컴파일 과정에 대해 궁금증을 품었던 것처럼 하나하나 찾아보면서 익히면 Java에 대한 이해도가 훨씬 높아질 수 있을 것이라고 확신합니다!!&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(저도 해당 포스팅을 작성하면서 Java의 동작 방식에 대해 더 깊은 정보까지 공부해보고 싶어졌습니다 ㅎㅎ)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음에는 더 자세하고 깊이있고 유익한 포스팅으로 돌아오겠습니다 :)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;6. 참고자료&lt;/b&gt;&lt;/h2&gt;
&lt;figure id=&quot;og_1669488941559&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[JAVA] JVM 동작원리 및 기본개념&quot; data-og-description=&quot;JAVA라는 언어를 통해 코딩을 하고 있는 사람으로서 JAVA의 간단한 탄생배경 그리고 JAVA의 시작과 끝이라고 할 수 있는 JVM을 한 번 짚고넘어가려고 해요 우선 JAVA의 탄생배경을 좀 알고가면 이해하&quot; data-og-host=&quot;steady-snail.tistory.com&quot; data-og-source-url=&quot;https://steady-snail.tistory.com/67&quot; data-og-url=&quot;https://steady-snail.tistory.com/67&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/Kxl1W/hyQHYXv61w/nQCVj1GqpB4PV0NBtEcbEk/img.png?width=800&amp;amp;height=533&amp;amp;face=0_0_800_533,https://scrap.kakaocdn.net/dn/cvUzXi/hyQH3xKPIE/izCXhVACcUojpe89luKFwK/img.png?width=800&amp;amp;height=533&amp;amp;face=0_0_800_533,https://scrap.kakaocdn.net/dn/ntZs0/hyQHU1UEN4/rcVxa3OPLSR2OsbzMjmIZ1/img.png?width=823&amp;amp;height=696&amp;amp;face=0_0_823_696&quot;&gt;&lt;a href=&quot;https://steady-snail.tistory.com/67&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://steady-snail.tistory.com/67&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/Kxl1W/hyQHYXv61w/nQCVj1GqpB4PV0NBtEcbEk/img.png?width=800&amp;amp;height=533&amp;amp;face=0_0_800_533,https://scrap.kakaocdn.net/dn/cvUzXi/hyQH3xKPIE/izCXhVACcUojpe89luKFwK/img.png?width=800&amp;amp;height=533&amp;amp;face=0_0_800_533,https://scrap.kakaocdn.net/dn/ntZs0/hyQHU1UEN4/rcVxa3OPLSR2OsbzMjmIZ1/img.png?width=823&amp;amp;height=696&amp;amp;face=0_0_823_696');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[JAVA] JVM 동작원리 및 기본개념&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;JAVA라는 언어를 통해 코딩을 하고 있는 사람으로서 JAVA의 간단한 탄생배경 그리고 JAVA의 시작과 끝이라고 할 수 있는 JVM을 한 번 짚고넘어가려고 해요 우선 JAVA의 탄생배경을 좀 알고가면 이해하&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;steady-snail.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1669488977894&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;알기쉽게 정리한 JAVA의 컴파일과정 및 JVM 메모리 구조, JVM GC&quot; data-og-description=&quot;알기쉽게 정리한 JAVA의 컴파일과정 및 JVM 메모리 구조, JVM GC 자바 개발자들이 간과 하기 쉬운 JAVA의 메모리 구조에 대해 포스팅 해보려고 합니다. 이와 관련하여 JAVA의 컴파일 과정과 Garbage Collect&quot; data-og-host=&quot;aljjabaegi.tistory.com&quot; data-og-source-url=&quot;https://aljjabaegi.tistory.com/387&quot; data-og-url=&quot;https://aljjabaegi.tistory.com/387&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/ZKged/hyQH5PS0OH/nZrKX93lQZkmRM2GFlzct1/img.jpg?width=683&amp;amp;height=474&amp;amp;face=0_0_683_474,https://scrap.kakaocdn.net/dn/bOvneb/hyQH4KeV5g/d44nagW9EfUbr7v6YeAPQK/img.jpg?width=683&amp;amp;height=474&amp;amp;face=0_0_683_474,https://scrap.kakaocdn.net/dn/gIxws/hyQHYwrTXQ/jgrZpMQHPPMcybWnBlwcy0/img.jpg?width=683&amp;amp;height=458&amp;amp;face=0_0_683_458&quot;&gt;&lt;a href=&quot;https://aljjabaegi.tistory.com/387&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://aljjabaegi.tistory.com/387&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/ZKged/hyQH5PS0OH/nZrKX93lQZkmRM2GFlzct1/img.jpg?width=683&amp;amp;height=474&amp;amp;face=0_0_683_474,https://scrap.kakaocdn.net/dn/bOvneb/hyQH4KeV5g/d44nagW9EfUbr7v6YeAPQK/img.jpg?width=683&amp;amp;height=474&amp;amp;face=0_0_683_474,https://scrap.kakaocdn.net/dn/gIxws/hyQHYwrTXQ/jgrZpMQHPPMcybWnBlwcy0/img.jpg?width=683&amp;amp;height=458&amp;amp;face=0_0_683_458');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;알기쉽게 정리한 JAVA의 컴파일과정 및 JVM 메모리 구조, JVM GC&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;알기쉽게 정리한 JAVA의 컴파일과정 및 JVM 메모리 구조, JVM GC 자바 개발자들이 간과 하기 쉬운 JAVA의 메모리 구조에 대해 포스팅 해보려고 합니다. 이와 관련하여 JAVA의 컴파일 과정과 Garbage Collect&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;aljjabaegi.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1669488994053&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[Java] 자바의 동작과정 Java Compiler와 JVM&quot; data-og-description=&quot;이클립스에서 *.java를 단축키 눌러서 실행시킬 줄만 알았지 *.java 파일이 어떠한 과정을 거쳐 실행이 되는지는 알지 못했습니다. 따라서 자바 컴파일러는 어떤 역할을 수행하며, 어디서 많이 들&quot; data-og-host=&quot;kingofbackend.tistory.com&quot; data-og-source-url=&quot;https://kingofbackend.tistory.com/123&quot; data-og-url=&quot;https://kingofbackend.tistory.com/123&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/csxM2A/hyQH3q0XEB/RrZjTLui2RnZ8ylnDEN8a1/img.jpg?width=626&amp;amp;height=626&amp;amp;face=0_0_626_626,https://scrap.kakaocdn.net/dn/cMfnS4/hyQH35Av2K/aUx4s2jOYKkBSSXG5TOkF1/img.jpg?width=626&amp;amp;height=626&amp;amp;face=0_0_626_626,https://scrap.kakaocdn.net/dn/ptBiu/hyQHUgxtnH/jz5scMP0NZdKlNhODBkbZk/img.jpg?width=626&amp;amp;height=626&amp;amp;face=0_0_626_626&quot;&gt;&lt;a href=&quot;https://kingofbackend.tistory.com/123&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://kingofbackend.tistory.com/123&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/csxM2A/hyQH3q0XEB/RrZjTLui2RnZ8ylnDEN8a1/img.jpg?width=626&amp;amp;height=626&amp;amp;face=0_0_626_626,https://scrap.kakaocdn.net/dn/cMfnS4/hyQH35Av2K/aUx4s2jOYKkBSSXG5TOkF1/img.jpg?width=626&amp;amp;height=626&amp;amp;face=0_0_626_626,https://scrap.kakaocdn.net/dn/ptBiu/hyQHUgxtnH/jz5scMP0NZdKlNhODBkbZk/img.jpg?width=626&amp;amp;height=626&amp;amp;face=0_0_626_626');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[Java] 자바의 동작과정 Java Compiler와 JVM&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이클립스에서 *.java를 단축키 눌러서 실행시킬 줄만 알았지 *.java 파일이 어떠한 과정을 거쳐 실행이 되는지는 알지 못했습니다. 따라서 자바 컴파일러는 어떤 역할을 수행하며, 어디서 많이 들&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;kingofbackend.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1669489225519&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[Java] JVM의 클래스 로더란?&quot; data-og-description=&quot;java-study에서 스터디를 진행하고 있습니다. 클래스 로더란? 자바는 동적 로드, 즉 컴파일 타임이 아니라 런타임(바이트 코드를 실행할 때)에 클래스 로드하고 링크하는 특징이 있다. 이 동적 로드&quot; data-og-host=&quot;steady-coding.tistory.com&quot; data-og-source-url=&quot;https://steady-coding.tistory.com/593&quot; data-og-url=&quot;https://steady-coding.tistory.com/593&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/b6eWVO/hyQHZ3bUXb/4HQWKHBHuWPquK2uTz96Qk/img.png?width=377&amp;amp;height=320&amp;amp;face=0_0_377_320,https://scrap.kakaocdn.net/dn/b5G37i/hyQH5oOuC1/sM1n6VyIFozO4ruLCFxChk/img.png?width=377&amp;amp;height=320&amp;amp;face=0_0_377_320,https://scrap.kakaocdn.net/dn/toIUk/hyQH0OzxHG/VGn1Y8Wd3TA4OfP7cYSKkk/img.jpg?width=421&amp;amp;height=421&amp;amp;face=92_157_236_314&quot;&gt;&lt;a href=&quot;https://steady-coding.tistory.com/593&quot; data-source-url=&quot;https://steady-coding.tistory.com/593&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/b6eWVO/hyQHZ3bUXb/4HQWKHBHuWPquK2uTz96Qk/img.png?width=377&amp;amp;height=320&amp;amp;face=0_0_377_320,https://scrap.kakaocdn.net/dn/b5G37i/hyQH5oOuC1/sM1n6VyIFozO4ruLCFxChk/img.png?width=377&amp;amp;height=320&amp;amp;face=0_0_377_320,https://scrap.kakaocdn.net/dn/toIUk/hyQH0OzxHG/VGn1Y8Wd3TA4OfP7cYSKkk/img.jpg?width=421&amp;amp;height=421&amp;amp;face=92_157_236_314');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[Java] JVM의 클래스 로더란?&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;java-study에서 스터디를 진행하고 있습니다. 클래스 로더란? 자바는 동적 로드, 즉 컴파일 타임이 아니라 런타임(바이트 코드를 실행할 때)에 클래스 로드하고 링크하는 특징이 있다. 이 동적 로드&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;steady-coding.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1669489222306&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;The Java&amp;reg; Virtual Machine Specification&quot; data-og-description=&quot;Tim Lindholm Frank Yellin Gilad Bracha Alex Buckley&quot; data-og-host=&quot;docs.oracle.com&quot; data-og-source-url=&quot;https://docs.oracle.com/javase/specs/jvms/se7/html/&quot; data-og-url=&quot;https://docs.oracle.com/javase/specs/jvms/se7/html/&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://docs.oracle.com/javase/specs/jvms/se7/html/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.oracle.com/javase/specs/jvms/se7/html/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;The Java&amp;reg; Virtual Machine Specification&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Tim Lindholm Frank Yellin Gilad Bracha Alex Buckley&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.oracle.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;NAVER D2 JVM Internal&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://d2.naver.com/helloworld/1230&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://d2.naver.com/helloworld/1230&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category># 공부 자료들/Java</category>
      <category>Java</category>
      <category>jvm</category>
      <category>기초지식</category>
      <category>백엔드</category>
      <category>빌드과정</category>
      <category>컴파일과정</category>
      <author>Ssoco</author>
      <guid isPermaLink="true">https://ssocoit.tistory.com/270</guid>
      <comments>https://ssocoit.tistory.com/270#entry270comment</comments>
      <pubDate>Sun, 27 Nov 2022 04:05:09 +0900</pubDate>
    </item>
    <item>
      <title>[JS] 자바스크립트는 왜 멀티스레드가 아니라 싱글스레드로 동작하는걸까?</title>
      <link>https://ssocoit.tistory.com/269</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;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;b&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;자바스크립트는 &lt;span style=&quot;color: #ee2323;&quot;&gt;싱글스레드&lt;/span&gt;로 동작한다&lt;/span&gt;&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;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 드는 의문점 하나는, 왜 굳이 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;멀티스레드를 놔두고 싱글스레드로 동작할까&lt;/b&gt;&lt;/span&gt; 입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;누구나 멀티스레드가 싱글스레드보다 좋지 않냐고 쉽게 생각할 수 있는데, 왜 자바스크립트 개발자들은 여전히 싱글스레드를 고집하는 것일까에 대한 고민이 해당 포스팅으로 이어지게 되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;0. 싱글스레드인데 어떻게 여러 작업을 동시에 처리하지?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;멀티스레드를 놔두고 싱글스레드로 동작하는 이유를 알아보기 전에, 진짜 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;자바스크립트가 싱글스레드&lt;/b&gt;&lt;/span&gt;인지, 또 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;어떻게 자바스크립트가 우리의 눈을 속이고 있을까&lt;/b&gt;&lt;/span&gt;에 대해서 먼저 알아보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;0.0. 자바스크립트, 싱글스레드 맞아?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저 자바스크립트가 싱글스레드임을 확인하기 위해서 간단한 코드 하나를 가져왔습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;435&quot; data-origin-height=&quot;99&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qVCC6/btrQkuEgy6M/UYZHRbfjkC9t69nodqgRg0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qVCC6/btrQkuEgy6M/UYZHRbfjkC9t69nodqgRg0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qVCC6/btrQkuEgy6M/UYZHRbfjkC9t69nodqgRg0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqVCC6%2FbtrQkuEgy6M%2FUYZHRbfjkC9t69nodqgRg0%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;435&quot; height=&quot;99&quot; data-origin-width=&quot;435&quot; data-origin-height=&quot;99&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;pre id=&quot;code_1667523463387&quot; class=&quot;javascript&quot; data-ke-language=&quot;javascript&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;setTimeout(() =&amp;gt; {console.log(&quot;코딩하는&quot;}, 0); // 1
while(1) console.log(&quot;경제학도&quot;); // 2
console.log(&quot;쏘코입니다.&quot;); // 3&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: #ee2323;&quot;&gt;&lt;b&gt;Run-To-Completion&lt;/b&gt;&lt;/span&gt; 특성에 의해서 &quot;경제학도&quot; 만 출력되고 나머지는 영원히 출력되지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Run-To-Completion을 간단히 설명하면 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;하나의 함수의 실행이 끝날 때 까지 다른 작업은 수행되지 않는다는 것&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;이죠.&lt;/p&gt;
&lt;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;조금 더 자세하게 설명하면 해당 코드의 실행 순서는 2 3 &lt;span&gt;1&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;입니다. (동작 순서에 대한 자세한 설명은 후술할 이벤트루프와 연관되어있습니다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 2번 동작이 영원히 끝나지 않기 때문에 3과 1은 동작하지 않습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;0.1. 자바스크립트의 동시성 치트키 이벤트루프&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이제 자바스크립트가 싱글스레드임을 확인했으니, 눈을 속이는 방법에 대해서 알아보겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웹 브라우저가 어떻게 &lt;span&gt;자바스크립트 코드를 실행시키는지에 대한 자세한 내용을 알지 못한다고 하더라도 일반적으로 사람들은 웹 페이지에서 자연스럽게 여러 동작이 동시에 일어난다고 인식합니다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;768&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cZ4j17/btrQrtSgbcR/RpdI7fp85ByeVDQxo82dk1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cZ4j17/btrQrtSgbcR/RpdI7fp85ByeVDQxo82dk1/img.png&quot; data-alt=&quot;출처:https://blog.sessionstack.com/how-does-javascript-actually-work-part-1-b0bacc073cf&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cZ4j17/btrQrtSgbcR/RpdI7fp85ByeVDQxo82dk1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcZ4j17%2FbtrQrtSgbcR%2FRpdI7fp85ByeVDQxo82dk1%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;1024&quot; height=&quot;768&quot; data-origin-width=&quot;1024&quot; data-origin-height=&quot;768&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처:https://blog.sessionstack.com/how-does-javascript-actually-work-part-1-b0bacc073cf&lt;/figcaption&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;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;이벤트루프&lt;/b&gt;&lt;/span&gt;가 어떻게 동작하는지에 대해서 간략하게 도식화한 사진입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JavaScript 코드 내에서 비동기로 처리해야 하는 요소가 생긴다면 (callback이라든지, Promise라든지, async await이라든지, setTimeout이라든지...) JS는 자신이 그 요소를 처리하지 않고 Web API라는 친구에게 위임합니다.&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;Web API에서 처리된 내용은 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Callback Queue(Task Queue)&lt;/b&gt;&lt;/span&gt;로 들어갑니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Callback Queue는 또 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;일반 Callback Queue&lt;/b&gt;&lt;/span&gt;와 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Animation Frames&lt;/b&gt;&lt;/span&gt;, &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Microtask Queue&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;&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;이벤트루프는 JS엔진의 Call Stack을 지속적으로 바라보고 있다가, Call Stack이 비면 우선순위에 따라 각각의 Queue들에서 대기중인 요소들을 Call Stack으로 넣어줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;880&quot; data-origin-height=&quot;495&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3J7Dr/btrQp7pdoTd/OCWCnkC2lwOIsioMEifp5k/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3J7Dr/btrQp7pdoTd/OCWCnkC2lwOIsioMEifp5k/img.gif&quot; data-alt=&quot;출처:https://dev.to/lydiahallie/javascript-visualized-promises-async-await-5gke&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3J7Dr/btrQp7pdoTd/OCWCnkC2lwOIsioMEifp5k/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/3J7Dr/btrQp7pdoTd/OCWCnkC2lwOIsioMEifp5k/img.gif&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;880&quot; height=&quot;495&quot; data-origin-width=&quot;880&quot; data-origin-height=&quot;495&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;출처:https://dev.to/lydiahallie/javascript-visualized-promises-async-await-5gke&lt;/figcaption&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;u&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;JavaScript가 싱글 스레드&lt;/b&gt;&lt;/span&gt;&lt;/u&gt;라는 것은 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;하나의 Call Stack을 가졌다&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;는 의미와도 일맥상통합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;따라서 단 하나 존재하는 그 Call Stack이 비지 않았다면 Callback Queue에서 동작이 무한히 대기하게 되는 것이고, 그래서 위에서 두 번째 요소를 제외한 나머지 요소들이 동작하지 않은 것입니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 오래 걸릴 수 있는 동작들을 이벤트루프를 통해서 동시에 처리되는 것처럼 보이게 한다는 사실을 이제 잘 알 수 있겠죠?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. 이벤트루프가 짱이네. 근데 멀티스레드 쓰면 되는거 아니야?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;맞습니다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;멀티스레드를 쓰면 자바스크립트의 동작을 WebAPI에게 굳이 위임하지 않아도 되고, 이벤트루프나 Callback Queue들도 필요가 없어지게 되겠죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만, 자바스크립트가 싱글스레드를 사용함으로써 얻는 이점은 바로 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;동시성 문제를 신경쓰지 않아도 된다는 것&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 예시로 iOS나 Android같이 멀티스레드 환경을 제공함에도 항상 주의사항이 따라붙는데, UI 스레드(메인 스레드) 이외의 다른 Worker 스레드에서는 &lt;span&gt;UI 작업을 하지 말아야 한다는 것입니다.&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: #000000;&quot;&gt;&lt;b&gt;사용자에게 있어서 화면이라는 자원에 여러 스레드가 동시에 접근하게 된다면 문제가 발생할 여지가 생기게 됩니다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 위험성을 차단하기 위한 목적과 함께, 멀티스레드로 얻을 수 있는 이득이 싱글스레드를 유지하는 것보다 크지 않기 때문에 JavaScript는 싱글스레드를 사용한다고 추측할 수 있겠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1.0. 주의!&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼에도 자바스크립트에서 멀티스레드를 사용하기 위한 다양한 노력은 계속되고 있고, ES2017(ES8)에서 SharedArrayBuffer, 그리고 atomics 객체를 사용해서 메모리를 동시에 접근할 수 있게 하는 새로운 방법을 제시했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 해당 내용의 경우 2018년 초에 발생한 Intel CPU의 이슈문제 때문에 사용이 중단되기도 했고, 지금 시점에서 자유자재로 사용하기엔 어려운 부분이 있으니 꼭 필요한 경우에만 확인하고 사용하시는 것을 추천드립니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1667633323637&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;메모리 특강 ★
      Mozilla 웹 기술 블로그&quot; data-og-description=&quot;이 글은 3부작 시리즈의 첫번째 글입니다. 메모리 특강 만화로 소개하는 ArrayBuffer 와 SharedArrayBuffer Atomics 를 이용해서 SharedArrayBuffer 레이스 컨디션 피하기 ArrayBuffer 와 SharedArrayBuffer 가 JavaScript 에 &quot; data-og-host=&quot;hacks.mozilla.or.kr&quot; data-og-source-url=&quot;http://hacks.mozilla.or.kr/2017/11/a-crash-course-in-memory-management/&quot; data-og-url=&quot;http://hacks.mozilla.or.kr/2017/11/a-crash-course-in-memory-management/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cpiZEO/hyQseHbvwk/gFkmWHzku3SdhgKW8Yg5b1/img.png?width=500&amp;amp;height=373&amp;amp;face=0_0_500_373,https://scrap.kakaocdn.net/dn/bIQOlV/hyQr4ExBie/NvwVy08Mg7WeY4dK65PAf0/img.png?width=500&amp;amp;height=371&amp;amp;face=0_0_500_371,https://scrap.kakaocdn.net/dn/TE4z7/hyQr9FRV9L/4MUW2Xh3YsRIeVqs3ztNu0/img.png?width=500&amp;amp;height=370&amp;amp;face=0_0_500_370&quot;&gt;&lt;a href=&quot;http://hacks.mozilla.or.kr/2017/11/a-crash-course-in-memory-management/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;http://hacks.mozilla.or.kr/2017/11/a-crash-course-in-memory-management/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cpiZEO/hyQseHbvwk/gFkmWHzku3SdhgKW8Yg5b1/img.png?width=500&amp;amp;height=373&amp;amp;face=0_0_500_373,https://scrap.kakaocdn.net/dn/bIQOlV/hyQr4ExBie/NvwVy08Mg7WeY4dK65PAf0/img.png?width=500&amp;amp;height=371&amp;amp;face=0_0_500_371,https://scrap.kakaocdn.net/dn/TE4z7/hyQr9FRV9L/4MUW2Xh3YsRIeVqs3ztNu0/img.png?width=500&amp;amp;height=370&amp;amp;face=0_0_500_370');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;메모리 특강 ★ Mozilla 웹 기술 블로그&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이 글은 3부작 시리즈의 첫번째 글입니다. 메모리 특강 만화로 소개하는 ArrayBuffer 와 SharedArrayBuffer Atomics 를 이용해서 SharedArrayBuffer 레이스 컨디션 피하기 ArrayBuffer 와 SharedArrayBuffer 가 JavaScript 에&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;hacks.mozilla.or.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1667633381313&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;A crash course in memory management &amp;ndash; Mozilla Hacks - the Web developer blog&quot; data-og-description=&quot;This is the first article in a 3-part series of code cartoons that explore SharedArrayBuffers in JavaScript and how they are used. To understand why ArrayBuffer and SharedArrayBuffer were added ...&quot; data-og-host=&quot;hacks.mozilla.org&quot; data-og-source-url=&quot;https://hacks.mozilla.org/2017/06/a-crash-course-in-memory-management/&quot; data-og-url=&quot;https://hacks.mozilla.org/2017/06/a-crash-course-in-memory-management&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/9sOQG/hyQttQfgeW/jrQvBalRGKFMGHOwjKaSZk/img.jpg?width=1200&amp;amp;height=660&amp;amp;face=0_0_1200_660,https://scrap.kakaocdn.net/dn/oImUO/hyQtpmL4ZG/XiPBr43rK60snK0QYj3gi0/img.jpg?width=1200&amp;amp;height=660&amp;amp;face=0_0_1200_660,https://scrap.kakaocdn.net/dn/kmf9p/hyQttQfgjl/gAwUX02YRPPv4TGtyXnKn0/img.png?width=500&amp;amp;height=373&amp;amp;face=0_0_500_373&quot;&gt;&lt;a href=&quot;https://hacks.mozilla.org/2017/06/a-crash-course-in-memory-management/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://hacks.mozilla.org/2017/06/a-crash-course-in-memory-management/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/9sOQG/hyQttQfgeW/jrQvBalRGKFMGHOwjKaSZk/img.jpg?width=1200&amp;amp;height=660&amp;amp;face=0_0_1200_660,https://scrap.kakaocdn.net/dn/oImUO/hyQtpmL4ZG/XiPBr43rK60snK0QYj3gi0/img.jpg?width=1200&amp;amp;height=660&amp;amp;face=0_0_1200_660,https://scrap.kakaocdn.net/dn/kmf9p/hyQttQfgjl/gAwUX02YRPPv4TGtyXnKn0/img.png?width=500&amp;amp;height=373&amp;amp;face=0_0_500_373');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;A crash course in memory management &amp;ndash; Mozilla Hacks - the Web developer blog&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;This is the first article in a 3-part series of code cartoons that explore SharedArrayBuffers in JavaScript and how they are used. To understand why ArrayBuffer and SharedArrayBuffer were added ...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;hacks.mozilla.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1667633359740&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;ES proposal: Shared memory and atomics&quot; data-og-description=&quot;ES proposal: Shared memory and atomics (Ad, please don&amp;rsquo;t block) The ECMAScript proposal &amp;ldquo;Shared memory and atomics&amp;rdquo; by Lars T. Hansen has reached stage 4 this week and will be part of ECMAScript 2017. It introduces a new constructor SharedArrayBuffer&quot; data-og-host=&quot;2ality.com&quot; data-og-source-url=&quot;https://2ality.com/2017/01/shared-array-buffer.html&quot; data-og-url=&quot;https://2ality.com/2017/01/shared-array-buffer.html&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://2ality.com/2017/01/shared-array-buffer.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://2ality.com/2017/01/shared-array-buffer.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;ES proposal: Shared memory and atomics&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;ES proposal: Shared memory and atomics (Ad, please don&amp;rsquo;t block) The ECMAScript proposal &amp;ldquo;Shared memory and atomics&amp;rdquo; by Lars T. Hansen has reached stage 4 this week and will be part of ECMAScript 2017. It introduces a new constructor SharedArrayBuffer&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;2ality.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. 참고자료&lt;/b&gt;&lt;/h2&gt;
&lt;figure id=&quot;og_1667633694841&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;How JavaScript works: an overview of the engine, the runtime, and the call stack&quot; data-og-description=&quot;As JavaScript is getting more and more popular, teams are leveraging its support on many levels in their stack - front-end, back-end&amp;hellip;&quot; data-og-host=&quot;blog.sessionstack.com&quot; data-og-source-url=&quot;https://blog.sessionstack.com/how-does-javascript-actually-work-part-1-b0bacc073cf&quot; data-og-url=&quot;https://blog.sessionstack.com/how-does-javascript-actually-work-part-1-b0bacc073cf&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bmks2f/hyQtAhxeLv/yY6S6sVIAW1pDIDAynmQr0/img.png?width=1024&amp;amp;height=768&amp;amp;face=0_0_1024_768&quot;&gt;&lt;a href=&quot;https://blog.sessionstack.com/how-does-javascript-actually-work-part-1-b0bacc073cf&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://blog.sessionstack.com/how-does-javascript-actually-work-part-1-b0bacc073cf&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bmks2f/hyQtAhxeLv/yY6S6sVIAW1pDIDAynmQr0/img.png?width=1024&amp;amp;height=768&amp;amp;face=0_0_1024_768');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;How JavaScript works: an overview of the engine, the runtime, and the call stack&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;As JavaScript is getting more and more popular, teams are leveraging its support on many levels in their stack - front-end, back-end&amp;hellip;&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;blog.sessionstack.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1667633640594&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;⭐️  JavaScript Visualized: Promises &amp;amp; Async/Await&quot; data-og-description=&quot;Ever had to deal with JS code that just... didn't run the way you expected it to? Maybe it seemed lik...&quot; data-og-host=&quot;dev.to&quot; data-og-source-url=&quot;https://dev.to/lydiahallie/javascript-visualized-promises-async-await-5gke&quot; data-og-url=&quot;https://dev.to/lydiahallie/javascript-visualized-promises-async-await-5gke&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dgNuyx/hyQr786r81/3PrJFrQ0Nne5Ekp99V2Lk0/img.png?width=1000&amp;amp;height=500&amp;amp;face=0_0_1000_500,https://scrap.kakaocdn.net/dn/bwkk2J/hyQtzbRsXU/wUfripQb5JwTKZhynYPDY0/img.png?width=880&amp;amp;height=495&amp;amp;face=0_0_880_495,https://scrap.kakaocdn.net/dn/yvQeO/hyQseAnB0A/mcAhOhkMlfKwDveZEzs2L0/img.png?width=880&amp;amp;height=491&amp;amp;face=0_0_880_491&quot;&gt;&lt;a href=&quot;https://dev.to/lydiahallie/javascript-visualized-promises-async-await-5gke&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://dev.to/lydiahallie/javascript-visualized-promises-async-await-5gke&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dgNuyx/hyQr786r81/3PrJFrQ0Nne5Ekp99V2Lk0/img.png?width=1000&amp;amp;height=500&amp;amp;face=0_0_1000_500,https://scrap.kakaocdn.net/dn/bwkk2J/hyQtzbRsXU/wUfripQb5JwTKZhynYPDY0/img.png?width=880&amp;amp;height=495&amp;amp;face=0_0_880_495,https://scrap.kakaocdn.net/dn/yvQeO/hyQseAnB0A/mcAhOhkMlfKwDveZEzs2L0/img.png?width=880&amp;amp;height=491&amp;amp;face=0_0_880_491');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;⭐️  JavaScript Visualized: Promises &amp;amp; Async/Await&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Ever had to deal with JS code that just... didn't run the way you expected it to? Maybe it seemed lik...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;dev.to&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1667633627612&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[ 번역 ] 자바스크립트 시각화 : 비동기 처리&quot; data-og-description=&quot;원문 : ⭐️  JavaScript Visualized: Promises &amp;amp; Async/Await&quot; data-og-host=&quot;velog.io&quot; data-og-source-url=&quot;https://velog.io/@jjunyjjuny/%EB%B2%88%EC%97%AD-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%8B%9C%EA%B0%81%ED%99%94-%EB%B9%84%EB%8F%99%EA%B8%B0-%EC%B2%98%EB%A6%AC&quot; data-og-url=&quot;https://velog.io/@jjunyjjuny/번역-자바스크립트-시각화-비동기-처리&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bvM54I/hyQsbKtjV0/v6MlPzyW5CyEy9ogt9YhQK/img.png?width=1000&amp;amp;height=420&amp;amp;face=0_0_1000_420,https://scrap.kakaocdn.net/dn/BX2kl/hyQtrdP5vU/4P8LBGZ7RadwLrhJlosUpk/img.png?width=1000&amp;amp;height=420&amp;amp;face=0_0_1000_420,https://scrap.kakaocdn.net/dn/gui0j/hyQr6vCRTF/t7g1gVlMIOHyMkCfWtk3Wk/img.png?width=880&amp;amp;height=495&amp;amp;face=0_0_880_495&quot;&gt;&lt;a href=&quot;https://velog.io/@jjunyjjuny/%EB%B2%88%EC%97%AD-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%8B%9C%EA%B0%81%ED%99%94-%EB%B9%84%EB%8F%99%EA%B8%B0-%EC%B2%98%EB%A6%AC&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://velog.io/@jjunyjjuny/%EB%B2%88%EC%97%AD-%EC%9E%90%EB%B0%94%EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8-%EC%8B%9C%EA%B0%81%ED%99%94-%EB%B9%84%EB%8F%99%EA%B8%B0-%EC%B2%98%EB%A6%AC&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bvM54I/hyQsbKtjV0/v6MlPzyW5CyEy9ogt9YhQK/img.png?width=1000&amp;amp;height=420&amp;amp;face=0_0_1000_420,https://scrap.kakaocdn.net/dn/BX2kl/hyQtrdP5vU/4P8LBGZ7RadwLrhJlosUpk/img.png?width=1000&amp;amp;height=420&amp;amp;face=0_0_1000_420,https://scrap.kakaocdn.net/dn/gui0j/hyQr6vCRTF/t7g1gVlMIOHyMkCfWtk3Wk/img.png?width=880&amp;amp;height=495&amp;amp;face=0_0_880_495');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[ 번역 ] 자바스크립트 시각화 : 비동기 처리&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;원문 : ⭐️  JavaScript Visualized: Promises &amp;amp; Async/Await&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;velog.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1667633548087&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;Event Loop (이벤트 루프)&quot; data-og-description=&quot;이번 글은 Event Loop (이벤트 루프) 에 대해 정리해보려고 한다. Event Loop? Event Loop 출처 How JavaScript works: an overview of the engine, the runtime, and the call stack Event Loop는 MDN 문서로 검색하면 &amp;quot;큐의 다음 메시&quot; data-og-host=&quot;velog.io&quot; data-og-source-url=&quot;https://velog.io/@thms200/Event-Loop-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%A3%A8%ED%94%84&quot; data-og-url=&quot;https://velog.io/@thms200/Event-Loop-이벤트-루프&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/ccd8Dh/hyQr7advGp/3Qb9YOstAYRXIopdPpGNX1/img.png?width=950&amp;amp;height=500&amp;amp;face=0_0_950_500,https://scrap.kakaocdn.net/dn/cwJLnT/hyQtB1Pa7x/M2KsQJldqmU8zjowYAfODk/img.png?width=1024&amp;amp;height=768&amp;amp;face=0_0_1024_768&quot;&gt;&lt;a href=&quot;https://velog.io/@thms200/Event-Loop-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%A3%A8%ED%94%84&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://velog.io/@thms200/Event-Loop-%EC%9D%B4%EB%B2%A4%ED%8A%B8-%EB%A3%A8%ED%94%84&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/ccd8Dh/hyQr7advGp/3Qb9YOstAYRXIopdPpGNX1/img.png?width=950&amp;amp;height=500&amp;amp;face=0_0_950_500,https://scrap.kakaocdn.net/dn/cwJLnT/hyQtB1Pa7x/M2KsQJldqmU8zjowYAfODk/img.png?width=1024&amp;amp;height=768&amp;amp;face=0_0_1024_768');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Event Loop (이벤트 루프)&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이번 글은 Event Loop (이벤트 루프) 에 대해 정리해보려고 한다. Event Loop? Event Loop 출처 How JavaScript works: an overview of the engine, the runtime, and the call stack Event Loop는 MDN 문서로 검색하면 &quot;큐의 다음 메시&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;velog.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1667633531557&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[JavaScript] setTimeout과 setInterval은 정확한 시간을 보장하지 않는다!&quot; data-og-description=&quot;이번에도 스톱워치를 만들다가.. 말로만 듣던 setTimeout과 setInterval의 시간보장문제를 직접 맞닥뜨리게 되었습니다. 말로만 듣던걸 간단한 프로그램을 만들면서 직접 겪으니까 참 오묘하네요 ㅎ&quot; data-og-host=&quot;ssocoit.tistory.com&quot; data-og-source-url=&quot;https://ssocoit.tistory.com/249&quot; data-og-url=&quot;https://ssocoit.tistory.com/249&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/qICv5/hyQty45O5R/77mR2A70bWn4a7AB3deDy0/img.png?width=800&amp;amp;height=539&amp;amp;face=0_0_800_539,https://scrap.kakaocdn.net/dn/4D0Hl/hyQsfF5nLf/mbgvIcwitefoKDZac5R6zk/img.png?width=800&amp;amp;height=539&amp;amp;face=0_0_800_539,https://scrap.kakaocdn.net/dn/bCMvHS/hyQtyjIGDi/O2JX15wAdZGGPeXusXxYa0/img.png?width=1364&amp;amp;height=509&amp;amp;face=0_0_1364_509&quot;&gt;&lt;a href=&quot;https://ssocoit.tistory.com/249&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://ssocoit.tistory.com/249&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/qICv5/hyQty45O5R/77mR2A70bWn4a7AB3deDy0/img.png?width=800&amp;amp;height=539&amp;amp;face=0_0_800_539,https://scrap.kakaocdn.net/dn/4D0Hl/hyQsfF5nLf/mbgvIcwitefoKDZac5R6zk/img.png?width=800&amp;amp;height=539&amp;amp;face=0_0_800_539,https://scrap.kakaocdn.net/dn/bCMvHS/hyQtyjIGDi/O2JX15wAdZGGPeXusXxYa0/img.png?width=1364&amp;amp;height=509&amp;amp;face=0_0_1364_509');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[JavaScript] setTimeout과 setInterval은 정확한 시간을 보장하지 않는다!&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;이번에도 스톱워치를 만들다가.. 말로만 듣던 setTimeout과 setInterval의 시간보장문제를 직접 맞닥뜨리게 되었습니다. 말로만 듣던걸 간단한 프로그램을 만들면서 직접 겪으니까 참 오묘하네요 ㅎ&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;ssocoit.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1667633518531&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;자바스크립트 호출 스택(Call Stack) 이해하기&quot; data-og-description=&quot;시작하기에 앞서자바스크립트를 심도 있게 이해하기 위해 &amp;quot;모든 자바스크립트 개발자가 알아야할 33가지 개념(https://github.com/yjs03057/33-js-concepts)&amp;quot;의 항목들과 링크되어있는 블로그 글들을 정리하&quot; data-og-host=&quot;new93helloworld.tistory.com&quot; data-og-source-url=&quot;https://new93helloworld.tistory.com/358&quot; data-og-url=&quot;https://new93helloworld.tistory.com/358&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/CPl4s/hyQr27NGWE/oUZR7lWttOYELGJsvhNqkK/img.jpg?width=800&amp;amp;height=533&amp;amp;face=0_0_800_533,https://scrap.kakaocdn.net/dn/ctSRi4/hyQtyD1Re0/Wh9SRNxfs7EyhSUN4mxn0k/img.jpg?width=800&amp;amp;height=533&amp;amp;face=0_0_800_533,https://scrap.kakaocdn.net/dn/YCnRM/hyQr6h3SNh/AuCpF0wojHPTOOsizOY1a1/img.jpg?width=860&amp;amp;height=573&amp;amp;face=0_0_860_573&quot;&gt;&lt;a href=&quot;https://new93helloworld.tistory.com/358&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://new93helloworld.tistory.com/358&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/CPl4s/hyQr27NGWE/oUZR7lWttOYELGJsvhNqkK/img.jpg?width=800&amp;amp;height=533&amp;amp;face=0_0_800_533,https://scrap.kakaocdn.net/dn/ctSRi4/hyQtyD1Re0/Wh9SRNxfs7EyhSUN4mxn0k/img.jpg?width=800&amp;amp;height=533&amp;amp;face=0_0_800_533,https://scrap.kakaocdn.net/dn/YCnRM/hyQr6h3SNh/AuCpF0wojHPTOOsizOY1a1/img.jpg?width=860&amp;amp;height=573&amp;amp;face=0_0_860_573');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;자바스크립트 호출 스택(Call Stack) 이해하기&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;시작하기에 앞서자바스크립트를 심도 있게 이해하기 위해 &quot;모든 자바스크립트 개발자가 알아야할 33가지 개념(https://github.com/yjs03057/33-js-concepts)&quot;의 항목들과 링크되어있는 블로그 글들을 정리하&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;new93helloworld.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1667633401490&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;코드스피츠85 2회-(1) 자바스크립트의 동시성&quot; data-og-description=&quot;코드스피츠 85에서는 none blocking에 대한 이야기와자바스크립트를 짜는 근본적인 방법에 대한 고찰을 이야기해본다.   TL;DR 자바스크립트의 동시성 모델에 대해서 알아본다. 동시성이라는&quot; data-og-host=&quot;feel5ny.github.io&quot; data-og-source-url=&quot;https://feel5ny.github.io/2019/11/10/JS_26_1/&quot; data-og-url=&quot;http://feel5ny.github.io/2019/11/10/JS_26_1/index.html&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/cfG6K9/hyQttipBgR/yteFLQtiC5HzH7a4vomKik/img.jpg?width=1040&amp;amp;height=490&amp;amp;face=0_0_1040_490,https://scrap.kakaocdn.net/dn/bqNQf8/hyQtpmL5wC/tgvQjLC01Km3G39vrPENWK/img.jpg?width=1040&amp;amp;height=490&amp;amp;face=0_0_1040_490,https://scrap.kakaocdn.net/dn/seS9K/hyQtqMLJPo/KWif80sFxnPKLhMKyKW2o1/img.png?width=1480&amp;amp;height=864&amp;amp;face=0_0_1480_864&quot;&gt;&lt;a href=&quot;https://feel5ny.github.io/2019/11/10/JS_26_1/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://feel5ny.github.io/2019/11/10/JS_26_1/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/cfG6K9/hyQttipBgR/yteFLQtiC5HzH7a4vomKik/img.jpg?width=1040&amp;amp;height=490&amp;amp;face=0_0_1040_490,https://scrap.kakaocdn.net/dn/bqNQf8/hyQtpmL5wC/tgvQjLC01Km3G39vrPENWK/img.jpg?width=1040&amp;amp;height=490&amp;amp;face=0_0_1040_490,https://scrap.kakaocdn.net/dn/seS9K/hyQtqMLJPo/KWif80sFxnPKLhMKyKW2o1/img.png?width=1480&amp;amp;height=864&amp;amp;face=0_0_1480_864');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;코드스피츠85 2회-(1) 자바스크립트의 동시성&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;코드스피츠 85에서는 none blocking에 대한 이야기와자바스크립트를 짜는 근본적인 방법에 대한 고찰을 이야기해본다.   TL;DR 자바스크립트의 동시성 모델에 대해서 알아본다. 동시성이라는&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;feel5ny.github.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1667633456635&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;자바스크립트는 왜 싱글 쓰레드일까? :: chanyeong&quot; data-og-description=&quot;자바스크립트라는 언어는 싱글 쓰레드 언어라고 알려져있다. 보통 싱글 쓰레드라고 하면 한 번에 하나의 작업만 수행할 수 있다고 생각한다. 그렇다면 자바스크립트를 주로 사용하는 웹 사이트&quot; data-og-host=&quot;chanyeong.com&quot; data-og-source-url=&quot;https://chanyeong.com/blog/post/44&quot; data-og-url=&quot;https://chanyeong.com/blog/post/44&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/ka88t/hyQsiQli7B/l7r805Hv7EUXZCiIS2Tba1/img.png?width=515&amp;amp;height=526&amp;amp;face=0_0_515_526,https://scrap.kakaocdn.net/dn/oFuiG/hyQr6vCNW6/KStAVp5Z1VGl5HkjqrLWOk/img.png?width=515&amp;amp;height=526&amp;amp;face=0_0_515_526,https://scrap.kakaocdn.net/dn/qdmeK/hyQr3ZVZDq/JOTOKXoXatQry7Ro4mPTKk/img.png?width=515&amp;amp;height=526&amp;amp;face=0_0_515_526&quot;&gt;&lt;a href=&quot;https://chanyeong.com/blog/post/44&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://chanyeong.com/blog/post/44&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/ka88t/hyQsiQli7B/l7r805Hv7EUXZCiIS2Tba1/img.png?width=515&amp;amp;height=526&amp;amp;face=0_0_515_526,https://scrap.kakaocdn.net/dn/oFuiG/hyQr6vCNW6/KStAVp5Z1VGl5HkjqrLWOk/img.png?width=515&amp;amp;height=526&amp;amp;face=0_0_515_526,https://scrap.kakaocdn.net/dn/qdmeK/hyQr3ZVZDq/JOTOKXoXatQry7Ro4mPTKk/img.png?width=515&amp;amp;height=526&amp;amp;face=0_0_515_526');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;자바스크립트는 왜 싱글 쓰레드일까? :: chanyeong&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;자바스크립트라는 언어는 싱글 쓰레드 언어라고 알려져있다. 보통 싱글 쓰레드라고 하면 한 번에 하나의 작업만 수행할 수 있다고 생각한다. 그렇다면 자바스크립트를 주로 사용하는 웹 사이트&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;chanyeong.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;네이버 D2 - 2018과 이후 JavaScript의 동향 - JavaScript(ECMAScript)&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://d2.naver.com/helloworld/7495331&quot;&gt;https://d2.naver.com/helloworld/7495331&lt;/a&gt;&lt;/p&gt;</description>
      <category># 공부 자료들/JavaScript</category>
      <category>concurrency</category>
      <category>JavaScript</category>
      <category>동시성</category>
      <category>멀티스레드</category>
      <category>싱글스레드</category>
      <category>자바스크립트</category>
      <author>Ssoco</author>
      <guid isPermaLink="true">https://ssocoit.tistory.com/269</guid>
      <comments>https://ssocoit.tistory.com/269#entry269comment</comments>
      <pubDate>Sat, 5 Nov 2022 16:36:08 +0900</pubDate>
    </item>
    <item>
      <title>[뻘] 첫 백엔드 도전, 아임텔러 회고</title>
      <link>https://ssocoit.tistory.com/268</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;605&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b14Fsc/btrPfX8bEHq/eHIXzbDa8fcbAoxb7fL3ak/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b14Fsc/btrPfX8bEHq/eHIXzbDa8fcbAoxb7fL3ak/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b14Fsc/btrPfX8bEHq/eHIXzbDa8fcbAoxb7fL3ak/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb14Fsc%2FbtrPfX8bEHq%2FeHIXzbDa8fcbAoxb7fL3ak%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;605&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;605&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;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;NFT&lt;/b&gt;&lt;/span&gt;를 끼얹어 버렸습니다 ㅋㅋ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;특화 프로젝트에서는 하나의 특화 아이템을 선택해야 했는데, 그게 바로 NFT였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나름 최근에 핫한 주제이기도 하고, 이전부터 한번 공부해봐야지~ 라고 생각했던 소재였기에 주저없이 NFT를 선택했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;심지어.. 거기에 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;게임&lt;/b&gt;&lt;/span&gt;까지 더해버렸습니다!!&lt;/p&gt;
&lt;p data-ke-size=&quot;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;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;백엔드&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;Team Classic 팀원들에게 무한한 감사 ㅎㅎ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class=&quot;book-toc&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;목차&lt;/p&gt;
&lt;ul id=&quot;toc&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;/ul&gt;
&lt;/div&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;0. 팀 컬쳐&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;0.0. 그라운드 룰&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전의 팀 규칙을 이번에는 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Ground Rule&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;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;732&quot; data-origin-height=&quot;414&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kF0fQ/btrPfbF91vb/MYz8Io6Ig0uAxIe4C9dr21/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kF0fQ/btrPfbF91vb/MYz8Io6Ig0uAxIe4C9dr21/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kF0fQ/btrPfbF91vb/MYz8Io6Ig0uAxIe4C9dr21/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkF0fQ%2FbtrPfbF91vb%2FMYz8Io6Ig0uAxIe4C9dr21%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;732&quot; height=&quot;414&quot; data-origin-width=&quot;732&quot; data-origin-height=&quot;414&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;0.1. 갤러리&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 프로젝트에서도 저번 프로젝트에서 긍정적인 반응을 이끌어냈던 갤러리 작업을 진행했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실 사진 찍고 관리하는 것이 쉬운 일은 아니지만, 하다보니까 재밌어서 벌써 세 번째 갤러리 운영을 하게 됐네요 ㅎㅎ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;edited_blob&quot; data-origin-width=&quot;1643&quot; data-origin-height=&quot;742&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfjyTn/btrPfbzssde/R1EFvMoOAYQAXgD7lsV6hk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfjyTn/btrPfbzssde/R1EFvMoOAYQAXgD7lsV6hk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfjyTn/btrPfbzssde/R1EFvMoOAYQAXgD7lsV6hk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbfjyTn%2FbtrPfbzssde%2FR1EFvMoOAYQAXgD7lsV6hk%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;1643&quot; height=&quot;742&quot; data-filename=&quot;edited_blob&quot; data-origin-width=&quot;1643&quot; data-origin-height=&quot;742&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;0.2. 바로가기&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에는 다른 팀원이 사용하던 양식을 사용해보았습니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메인에 달력을 띄워놓는게 가장 큰 차이였는데, 접근성 측면에 있어서 좋았습니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;앞에 꺼내둘 요소들이 많이 없다면 앞으로도 달력을 계속 꺼내놓지 않을까.. 생각해봅니다!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1493&quot; data-origin-height=&quot;551&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GoJ2M/btrPhnkuVr0/xSIFp2tqFyvppPuqBgtOz1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GoJ2M/btrPhnkuVr0/xSIFp2tqFyvppPuqBgtOz1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GoJ2M/btrPhnkuVr0/xSIFp2tqFyvppPuqBgtOz1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGoJ2M%2FbtrPhnkuVr0%2FxSIFp2tqFyvppPuqBgtOz1%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;1493&quot; height=&quot;551&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1493&quot; data-origin-height=&quot;551&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;0.3. 삽질게시판&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에도 삽질게시판을 운영했습니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 대부분 저만 사용해서 아주 쪼금 아쉬웠습니다 ㅎㅎ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다들 무난하게 프로젝트를 진행했기 때문에 그런게 아닐까~&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;957&quot; data-origin-height=&quot;639&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/UuYjW/btrPh79Cb1I/sLgR2HbSEkq8AJErAZhxR0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/UuYjW/btrPh79Cb1I/sLgR2HbSEkq8AJErAZhxR0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/UuYjW/btrPh79Cb1I/sLgR2HbSEkq8AJErAZhxR0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUuYjW%2FbtrPh79Cb1I%2FsLgR2HbSEkq8AJErAZhxR0%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;957&quot; height=&quot;639&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;957&quot; data-origin-height=&quot;639&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;0.4. 주간 Tech Talk&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전 프로젝트에서 못해서 아쉬웠다고 했던 바로 그 주간테크톡을 이번 프로젝트에서는 진행했습니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;u&gt;&lt;b&gt;매주 한번씩 자신이 공부한 내용이나 삽질한 내용에 대해서 딥하게 팀원들에게 설명하는 시간&lt;/b&gt;&lt;/u&gt;&lt;/span&gt;을 가졌습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;팀원들과 함께 서로가 알게되거나 새로 습득하게 된 지식을 나눌 수 있어서 정말 좋은 경험이었다고 생각합니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;532&quot; data-origin-height=&quot;341&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Ctg5A/btrPg0JTSlt/VoT8B1tGcQHkwQB4aCMtwK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Ctg5A/btrPg0JTSlt/VoT8B1tGcQHkwQB4aCMtwK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Ctg5A/btrPg0JTSlt/VoT8B1tGcQHkwQB4aCMtwK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FCtg5A%2FbtrPg0JTSlt%2FVoT8B1tGcQHkwQB4aCMtwK%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;532&quot; height=&quot;341&quot; data-origin-width=&quot;532&quot; data-origin-height=&quot;341&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫 주는 온라인, 두 번째 주부터는 오프라인으로 진행했는데, 오프라인으로 진행했을 때의 호응도가 더 높았기 때문에 앞으로도 이렇게 스터디를 진행하게 된다면 오프라인으로 추진하게 될 것 같습니다 ㅎㅎ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;edited_blob&quot; data-origin-width=&quot;764&quot; data-origin-height=&quot;341&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uqQkX/btrPfpEvXnt/j67q3MX08tGPmxTOgtHK2K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uqQkX/btrPfpEvXnt/j67q3MX08tGPmxTOgtHK2K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uqQkX/btrPfpEvXnt/j67q3MX08tGPmxTOgtHK2K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuqQkX%2FbtrPfpEvXnt%2Fj67q3MX08tGPmxTOgtHK2K%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;764&quot; height=&quot;341&quot; data-filename=&quot;edited_blob&quot; data-origin-width=&quot;764&quot; data-origin-height=&quot;341&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;0.5. 리뷰투게더&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리뷰투게더 역시 저번 프로젝트에서 제대로 진행하지 못했던 코드리뷰를 보다 적극적으로 진행하기 위해서 도입했습니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순히 팀 내에서 리뷰를 진행하는 것 이외에도 &lt;u&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;다른 프로젝트 팀원들과 코드를 공유하고 리뷰&lt;/b&gt;&lt;/span&gt;&lt;/u&gt;를 주고받을 수 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리뷰를 작성하면서 내가 알고 있는 지식이 맞는 지식인가를 다시 한 번 확인하게 되고, 더 열심히 공부해야겠다는 생각을 했습니다...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 다들 프로젝트에 몰두하느라 이전 부스트캠프에서 진행했던 것 만큼의 참여도는 나오지 않아서 다소 아쉬웠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;같은 주제로 프로젝트를 진행하는 다른 반 팀을 섭외하는 데에 굉장한 어려움을 겪었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;총 4팀에게 컨택했지만, 딱 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;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;728&quot; data-origin-height=&quot;582&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NELqI/btrPgoR28SG/LmkAKea14KpbBTpcALG6KK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NELqI/btrPgoR28SG/LmkAKea14KpbBTpcALG6KK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NELqI/btrPgoR28SG/LmkAKea14KpbBTpcALG6KK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNELqI%2FbtrPgoR28SG%2FLmkAKea14KpbBTpcALG6KK%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;728&quot; height=&quot;582&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;728&quot; data-origin-height=&quot;582&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;0.6. 개선사항&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;팀 내 문화는 정말로 좋았고, 개발 자체도 잘 진행되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 백엔드 학습시간때문에 개발에 많은 시간을 할애하지 못한 점은 다소 아쉽습니다. (백엔드 실력이슈 ㅠ)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 빠르게 백엔드를 마치고 프론트엔드를 돕고 싶었으나, 게임 개발 특성상 백엔드에서 다뤄야 하는 데이터와 로직이 굉장히 많았고, 이것들을 프로젝트 마지막까지 계속해서 붙잡아야 했다보니 처음에 예상했던 것보다 프론트엔드와 스마트 컨트랙트에 힘을 별로 못 쏟은 것 같아서 그 부분 역시 조금 아쉬웠습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래도 이런 부분들은 프로젝트가 거듭되고 백엔드에 대한 지식을 늘려나가면서 충분히 해결할 수 있을 것이라고 생각합니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. 기획단계&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 NFT 특화 프로젝트에서는 기획을 많이 뒤엎기도 했고, 디자인 작업 및 팀원 변동 이슈때문에 다소 시간이 오래 걸렸습니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;NFT 프로젝트라는게 참 어렵더라구요..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1.0. 디자인&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에도 디자인 협업에는 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;Figma&lt;/b&gt;&lt;/span&gt;가 사용되었습니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한창 디자인작업을 하던 중 Adobe에 Figma가 인수되었다는 무시무시한 소식도 들려왔지만.. ㅋㅋㅋ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;피그마에 메모를 남기는 기능을 알게 되어서 알차게 사용할 수 있었습니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1354&quot; data-origin-height=&quot;790&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bpHhCH/btrPfn7rFTx/h7CXZEo8ZKlIZuZfR9MCO1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bpHhCH/btrPfn7rFTx/h7CXZEo8ZKlIZuZfR9MCO1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bpHhCH/btrPfn7rFTx/h7CXZEo8ZKlIZuZfR9MCO1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbpHhCH%2FbtrPfn7rFTx%2Fh7CXZEo8ZKlIZuZfR9MCO1%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;1354&quot; height=&quot;790&quot; data-origin-width=&quot;1354&quot; data-origin-height=&quot;790&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1.1. ERD&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;ERDCloud&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그럼에도 불구하고 예상보다 훨씬 많은 양의 테이블과 컬럼들이 생성되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 부분 이외에도 게임 처리에 대한 데이터스키마가 존재했기 때문에 어떻게 보면 핑퐁클래스보다 훨씬 더 대규모의 데이터셋을 다룬게 아닐까라고 생각할 수 있을 것 같습니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1175&quot; data-origin-height=&quot;736&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/liNvs/btrPe9axhxO/7ytiJrKAZ1QQuiaihqt5x1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/liNvs/btrPe9axhxO/7ytiJrKAZ1QQuiaihqt5x1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/liNvs/btrPe9axhxO/7ytiJrKAZ1QQuiaihqt5x1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FliNvs%2FbtrPe9axhxO%2F7ytiJrKAZ1QQuiaihqt5x1%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;1175&quot; height=&quot;736&quot; data-origin-width=&quot;1175&quot; data-origin-height=&quot;736&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1.2. API문서&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일반 API, Socket, SmartContract 세 가지로 나누어서 문서를 작성하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;익숙하지 않은 부분이 있어서 계속해서 변경되는 부분들이 있었지만, 이런 식으로 스프레드시트에 잘 정리해두다보니 나중에 개발할 때에는 서로간에 의사소통에 있어서 훌륭한 매개체가 될 수 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1528&quot; data-origin-height=&quot;320&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bgmtXy/btrPitY6hLu/eJVOlmR0Gk1m96rnwrY0Zk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bgmtXy/btrPitY6hLu/eJVOlmR0Gk1m96rnwrY0Zk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bgmtXy/btrPitY6hLu/eJVOlmR0Gk1m96rnwrY0Zk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbgmtXy%2FbtrPitY6hLu%2FeJVOlmR0Gk1m96rnwrY0Zk%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;1528&quot; height=&quot;320&quot; data-origin-width=&quot;1528&quot; data-origin-height=&quot;320&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1117&quot; data-origin-height=&quot;366&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cYlzCC/btrPh9sQuN0/L1F4oK5Z9k30gFK0qNuqhK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cYlzCC/btrPh9sQuN0/L1F4oK5Z9k30gFK0qNuqhK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cYlzCC/btrPh9sQuN0/L1F4oK5Z9k30gFK0qNuqhK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcYlzCC%2FbtrPh9sQuN0%2FL1F4oK5Z9k30gFK0qNuqhK%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;1117&quot; height=&quot;366&quot; data-origin-width=&quot;1117&quot; data-origin-height=&quot;366&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;1.3. Git&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에는 Git 전략으로 &lt;span style=&quot;color: #8a3db6;&quot;&gt;&lt;b&gt;GitHub-Flow&lt;/b&gt;&lt;/span&gt;를 사용했습니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존에 사용했던 Git-Flow의 경우 프로젝트 규모에 비해서 다소 많은 절차가 있다고 판단되어, Develop Branch를 없애고 FE와 BE, SC(Smart Contract)에서 각각 Feature Branch를 파고 바로 master에 합치는 방식을 사용하였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 방식을 사용하다보니 잘못된 내용이 Master Branch에 올라가는 위험성이 증가한다는 단점이 있었지만, 기존보다 훨씬 빠르고 간결하게 Branch Merge를 진행할 수 있다는 장점이 그러한 단점을 충분히 덮을 수 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;741&quot; data-origin-height=&quot;343&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ddMFVO/btrPgFspgqJ/2Akkvuo4shUgsUEDLjNkIK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ddMFVO/btrPgFspgqJ/2Akkvuo4shUgsUEDLjNkIK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ddMFVO/btrPgFspgqJ/2Akkvuo4shUgsUEDLjNkIK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FddMFVO%2FbtrPgFspgqJ%2F2Akkvuo4shUgsUEDLjNkIK%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;741&quot; height=&quot;343&quot; data-origin-width=&quot;741&quot; data-origin-height=&quot;343&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. 개발단계&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2.0. 기술 스택&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발 진행 중에도 사소하게 많은 변화를 겪었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Spring Boot&lt;/b&gt;&lt;/span&gt;와 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;MySQL&lt;/b&gt;&lt;/span&gt; 및 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;JPA&lt;/b&gt;&lt;/span&gt;를 사용한다는 기본 골자는 변하지 않았지만, &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;Redis&lt;/b&gt;&lt;/span&gt;를 사용하려다가 사용하지 않게 되었습니다. (이 내용에 대해서는 후술합니다!)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그 외에 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;NginX&lt;/b&gt;&lt;/span&gt;, &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Docker&lt;/b&gt;&lt;/span&gt;, &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Jenkins&lt;/b&gt;&lt;/span&gt;의 사용은 이전과 동일했고, 백엔드 서버는 &lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;Amazon EC2&lt;/span&gt;&lt;/b&gt;, 그림 및 사진 데이터 저장은 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Amazon S3&lt;/b&gt;&lt;/span&gt;에서 이루어졌습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;블록체인 코드의 경우 &lt;span style=&quot;color: #009a87;&quot;&gt;&lt;b&gt;Solidity&lt;/b&gt;&lt;/span&gt;를 기반으로 진행하였고, 테스트는 편의상 &lt;span style=&quot;color: #009a87;&quot;&gt;&lt;b&gt;Remix&lt;/b&gt;&lt;/span&gt;환경에서 진행하고 실제 프로젝트 안에서는 &lt;span style=&quot;color: #009a87;&quot;&gt;&lt;b&gt;Truffle&lt;/b&gt;&lt;/span&gt;을 사용했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이것도 기술 스택이라고 봐야하는 지는 잘 모르겠지만, 블록체인 토큰 및 NFT 저장용 지갑으로는 &lt;span style=&quot;color: #009a87;&quot;&gt;&lt;b&gt;MetaMask&lt;/b&gt;&lt;/span&gt;를 사용했습니다. (실제 서비스 내에서의 재화 사용 및 그림의 NFT화도 MetaMask 로그인을 해야 가능합니다)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트 진행 막판에 블록체인 네트워크 관련 문제들이 많이 발생해서, 프로젝트 후반부에는 제공된 네트워크 서버 대신 Goerli 테스트 네트워크를 사용했습니다.&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;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;TypeScript &lt;/b&gt;&lt;/span&gt;기반의 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;React&lt;/b&gt;&lt;/span&gt;와 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Redux-Toolkit&lt;/b&gt;&lt;/span&gt;, 그리고 &lt;span style=&quot;color: #006dd7;&quot;&gt;&lt;b&gt;Emotion&lt;/b&gt;&lt;/span&gt;을 사용했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1056&quot; data-origin-height=&quot;592&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/baer6d/btrPfpjXfmw/rRaiMhX33Qc7gbis7hgapk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/baer6d/btrPfpjXfmw/rRaiMhX33Qc7gbis7hgapk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/baer6d/btrPfpjXfmw/rRaiMhX33Qc7gbis7hgapk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbaer6d%2FbtrPfpjXfmw%2FrRaiMhX33Qc7gbis7hgapk%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;1056&quot; height=&quot;592&quot; data-origin-width=&quot;1056&quot; data-origin-height=&quot;592&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2.1. 실제 개발 과정&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제 개발은 약 3주간 진행되었고, 마지막 1주 정도는 수면 시간을 거의 5시간 이내로 줄여가면서 개발했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;게임 개발 특성상 실시간성이 강한 요소들이 많다보니 다양한 오류들이 발생하였고, 기존보다 훨씬 적은 인원이 백엔드를 담당하기도 했고 무엇보다 제가 Java를 이용한 백엔드 개발이 사실상 처음이었기 때문에 시행착오가 굉장히 많았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래도 개발 초기에 Java와 Spring Boot를 이용한 백엔드 경험이 있는 다른 팀원들에게 많은 도움을 받았고, 개발 막판에 잠을 줄여가면서까지 개발을 진행했기 때문에 정해둔 일정에 크게 벗어나지 않게 개발을 진행할 수 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;868&quot; data-origin-height=&quot;203&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/7ZzyP/btrPfPbAZhZ/erTkqFfkBKYt9PXDcXVZe0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/7ZzyP/btrPfPbAZhZ/erTkqFfkBKYt9PXDcXVZe0/img.png&quot; data-alt=&quot;돌아버린 개발시간?&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/7ZzyP/btrPfPbAZhZ/erTkqFfkBKYt9PXDcXVZe0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F7ZzyP%2FbtrPfPbAZhZ%2FerTkqFfkBKYt9PXDcXVZe0%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;868&quot; height=&quot;203&quot; data-origin-width=&quot;868&quot; data-origin-height=&quot;203&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;돌아버린 개발시간?&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 프로젝트에서는 Discord를 이용하여 화면공유 및 작업 내용을 공유하였고, 모르는 부분이 있으면 실시간 Live, 혹은 VSCode의 LiveShare를 사용하여 질문하거나 오류를 해결했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2.2. 폴더 구조&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;백엔드는 크게 api, config, exception, util로 폴더를 구성했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;api 폴더 내에는 controller, dto, repository, service가 존재합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;controller에는 프론트엔드로부터 받아온 요청들을 처리하는 컨트롤러들을 담아두었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;dto에는 사용자로부터 받는 요청의 양식, 사용자에게 전달하는 반환값의 양식들을 담아두었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;repository에는 백엔드단에서 사용하는 Entity와 JPA를 사용하기 위한 repository가 담겨있습니다. (두 요소를 따로 분리할 수도 있었지만, 팀원들과의 협의 하에 하나의 폴더로 뭉쳐두었습니다.)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;service에는 백엔드단에서 사용하는 각종 서비스 로직을 담아두었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가장 큰 특징이라고 한다면, 백엔드에서 게임 데이터와 관련된 요소를 관리하는데, 관리를 위한 각종 로직들을 RoomRepository에서 처리했습니다. DB를 대신한다는 측면에서 이 곳에 두는 것으로 결정하였는데, 맞는 결정인지는 잘 모르겠으나 개발 과정 중 의사소통에 있어서 크게 문제는 없었기에 변경 없이 그대로 진행하였습니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;252&quot; data-origin-height=&quot;406&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/msZ3O/btrPfCXyJrm/v2ui68cXgt5kG8yZaD7rnK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/msZ3O/btrPfCXyJrm/v2ui68cXgt5kG8yZaD7rnK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/msZ3O/btrPfCXyJrm/v2ui68cXgt5kG8yZaD7rnK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmsZ3O%2FbtrPfCXyJrm%2Fv2ui68cXgt5kG8yZaD7rnK%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;252&quot; height=&quot;406&quot; data-origin-width=&quot;252&quot; data-origin-height=&quot;406&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;프론트엔드는 pages 폴더에 우리 눈에 보이는 화면들을 정리해두고, components 폴더에 실제 내부에서 사용하는 커다란 기능들을 만들었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 layout에는 Modal, Header, Footer와 같은 화면 구성 요소들에 대한 내용들을 담았고, Store에는 상태관리를 위한 내용들, Style에는 공통 스타일 요소들을 담았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;추가로 actions에는 API 관련 내용들, assets에는 사진, 음성 및 영상 관련 소스들, contract에는 블록체인 관련 API와 소스들을 담아두었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imagegridblock&quot;&gt;
  &lt;div class=&quot;image-container&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/3WDX3/btrPh9zDMnl/4TMcn6izcdk9z2obIqoQn0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/3WDX3/btrPh9zDMnl/4TMcn6izcdk9z2obIqoQn0/img.png&quot; data-origin-width=&quot;194&quot; data-origin-height=&quot;244&quot; data-is-animation=&quot;false&quot; style=&quot;width: 40.4566%; margin-right: 10px;&quot; data-widthpercent=&quot;40.93&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/3WDX3/btrPh9zDMnl/4TMcn6izcdk9z2obIqoQn0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F3WDX3%2FbtrPh9zDMnl%2F4TMcn6izcdk9z2obIqoQn0%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;194&quot; height=&quot;244&quot;/&gt;&lt;/span&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/PPxee/btrPfDPGT7m/KezuD0uG0OnVZMhkNZKdG0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/PPxee/btrPfDPGT7m/KezuD0uG0OnVZMhkNZKdG0/img.png&quot; data-origin-width=&quot;366&quot; data-origin-height=&quot;319&quot; data-is-animation=&quot;false&quot; style=&quot;width: 58.3806%;&quot; data-widthpercent=&quot;59.07&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/PPxee/btrPfDPGT7m/KezuD0uG0OnVZMhkNZKdG0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FPPxee%2FbtrPfDPGT7m%2FKezuD0uG0OnVZMhkNZKdG0%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;366&quot; height=&quot;319&quot;/&gt;&lt;/span&gt;&lt;/div&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;2.3. 담당 개발 기능&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제가 맡아서 진행했던 부분은 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;유저와 관련된 백엔드 로직&lt;/b&gt;&lt;/span&gt;과 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;게임과 관련된 백엔드 로직&lt;/b&gt;&lt;/span&gt;이었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;유저 처리의 경우 일반적인 회원가입 로직과 크게 차이가 없었기 때문에 Spring Boot와 JPA를 공부하고 경험한다는 측면에서 편하게 진행할 수 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한 가지 특별한 점이라고 한다면 MetaMask 정보를 연결하는 부분일텐데, 이 부분도 API 처리가 잘 되어있어서 받아오는 대로 DB에 연결만 해주면 됐기 때문에 크게 무리 없이 진행할 수 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;344&quot; data-origin-height=&quot;145&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b7uttA/btrPhp3NF0e/bVwOZx538feVtG0O8A3WkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b7uttA/btrPhp3NF0e/bVwOZx538feVtG0O8A3WkK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b7uttA/btrPhp3NF0e/bVwOZx538feVtG0O8A3WkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb7uttA%2FbtrPhp3NF0e%2FbVwOZx538feVtG0O8A3WkK%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;344&quot; height=&quot;145&quot; data-origin-width=&quot;344&quot; data-origin-height=&quot;145&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 부분에서는 우여곡절이 정말로 많았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;게임 내 모든 데이터를 관리해야 하는 것은 아주 당연한 것이었는데, 어떻게 관리할까에 대한 고민을 계속해서 하게 되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;MongoDB&lt;/b&gt;&lt;/span&gt;를 도입해서 게임 데이터를 별도로 관리하는 방법, &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Redis&lt;/b&gt;&lt;/span&gt;에다가 게임 데이터를 저장하는 방법, &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;백엔드 서버 자체&lt;/b&gt;&lt;/span&gt;에 게임 데이터를 저장하는 방법이 존재했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 중에서 MongoDB를 도입하는 것은 다소 과하다고 생각되어 Redis를 도입하고자 마음먹고 레퍼런스를 찾아보고 실제로 도입까지 성공했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1206&quot; data-origin-height=&quot;946&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/df88tq/btrPfODU7XG/ZSTRtFFoqpTjldyQJJxy8K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/df88tq/btrPfODU7XG/ZSTRtFFoqpTjldyQJJxy8K/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/df88tq/btrPfODU7XG/ZSTRtFFoqpTjldyQJJxy8K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fdf88tq%2FbtrPfODU7XG%2FZSTRtFFoqpTjldyQJJxy8K%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;1206&quot; height=&quot;946&quot; data-origin-width=&quot;1206&quot; data-origin-height=&quot;946&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;하지만 또 하나 발생한 문제는, Redis에 모든 데이터를 다 넣기에는 너무나도 복잡한 자료구조였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Redis에 자료를 넣게 된다면 매번 꺼내서 파싱을 해야하는 문제가 있는데, 파싱을 하기에는 너무나도 거대한 양의 데이터여서 부담이 됐습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(Redis를 어떻게든 써보려고 공부하면서 채팅 서비스에서 Redis를 사용하면 지금 개발하고 있는 게임 서비스보다 훨씬 효율적으로 Text 데이터를 저장할 수 있겠다는 생각도 할 수 있었습니다 ㅋㅋㅋㅋ;;)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1383&quot; data-origin-height=&quot;869&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bh33m5/btrPfnzPcli/YZXqo9l0UzFdUEHJA6QWP1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bh33m5/btrPfnzPcli/YZXqo9l0UzFdUEHJA6QWP1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bh33m5/btrPfnzPcli/YZXqo9l0UzFdUEHJA6QWP1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbh33m5%2FbtrPfnzPcli%2FYZXqo9l0UzFdUEHJA6QWP1%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;1383&quot; height=&quot;869&quot; data-origin-width=&quot;1383&quot; data-origin-height=&quot;869&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;u&gt;&lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;백엔드 서버에 직접 저장&lt;/b&gt;&lt;/span&gt;&lt;/u&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;span&gt;static 형태로&lt;span&gt; 선언해서 처리한 이유는 해당 RoomRepository가 아닌 다른 곳에서도 new를 통해 객체를 생성하는 행위를 하지 않고도 바로 접근할 수 있게 만들기 위해서였습니다.&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;849&quot; data-origin-height=&quot;266&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bBRWOU/btrPfYlYqFD/BOgnkaYkYh6FJ0KTqr1A1k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bBRWOU/btrPfYlYqFD/BOgnkaYkYh6FJ0KTqr1A1k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bBRWOU/btrPfYlYqFD/BOgnkaYkYh6FJ0KTqr1A1k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbBRWOU%2FbtrPfYlYqFD%2FBOgnkaYkYh6FJ0KTqr1A1k%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;849&quot; height=&quot;266&quot; data-origin-width=&quot;849&quot; data-origin-height=&quot;266&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;이제 RoomRepository 안에 각각의 게임 데이터를 변경할 수 있는 다양한 로직을 메서드 형태로 넣어두었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마치 Service단에서 요청을 처리하듯이 비슷한 방식으로 Room이 담긴 HashMap의 자료를 조회하고 변경하는 형태입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래는 대표적인 예시로 가져온 방에 접속하는 joinRoom 메서드입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1414&quot; data-origin-height=&quot;984&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/d8bTV6/btrPfmAPncm/uLMkJVR4iBKHEA42NYZKu0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/d8bTV6/btrPfmAPncm/uLMkJVR4iBKHEA42NYZKu0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/d8bTV6/btrPfmAPncm/uLMkJVR4iBKHEA42NYZKu0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fd8bTV6%2FbtrPfmAPncm%2FuLMkJVR4iBKHEA42NYZKu0%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;1414&quot; height=&quot;984&quot; data-origin-width=&quot;1414&quot; data-origin-height=&quot;984&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 또 다른 어려움이 생겼는데, 그것은 바로 &lt;span style=&quot;color: #ee2323;&quot;&gt;&lt;b&gt;소켓 연결&lt;/b&gt;&lt;/span&gt;이었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이전 Sooltreaming 프로젝트에서 node.js와 client간의 socket통신을 socket.io를 이용해서 구현한 적이 있었는데, 이번에는 백엔드 서버가 Java로 구성되었기 때문에 socket.io를 사용할 수 없었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 어쩔 수 없이 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Stomp&lt;/b&gt;&lt;/span&gt;와 &lt;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Sock.js&lt;/b&gt;&lt;/span&gt;를 사용해야했죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;850&quot; data-origin-height=&quot;674&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/c6ZPYZ/btrPfX8oMQ5/0UrPutoBC8FYpOLuEkFYI0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/c6ZPYZ/btrPfX8oMQ5/0UrPutoBC8FYpOLuEkFYI0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/c6ZPYZ/btrPfX8oMQ5/0UrPutoBC8FYpOLuEkFYI0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fc6ZPYZ%2FbtrPfX8oMQ5%2F0UrPutoBC8FYpOLuEkFYI0%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;850&quot; height=&quot;674&quot; data-origin-width=&quot;850&quot; data-origin-height=&quot;674&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;/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;백엔드서버에서 socket요청을 받으면, 그 요청에 맞는 roomRepository 내의 메서드가 작동하여 잘 동작하게 만드는 것이 프로그램의 핵심이었기 때문에 사용자로부터 요청을 받기 위한 SocketController를 만들었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래 사진은 MessageMapping 과정을 통해 &lt;span&gt;게임방에 입장할 때 작동하는&lt;/span&gt;&amp;nbsp;코드입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;소켓 기초 url + /room/{sessionId}/join&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로 socket 요청이 들어오면 joinRoom 메서드가 작동하고, sendingOperation.convertAndSend 메서드에 의해서 적절한 데이터가 다시 연결된 socket(방에 있는 모든 사람들)으로 전달되는 방식입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 Stomp를 이용한 소켓 연결 방식과 구조에 대해서 모두 설명하기에는 &quot;프로젝트 리뷰&quot; 라는 포스팅의 핵심에서 많이 벗어날 것 같아서, 보다 자세한 내용은 나중에 Stomp의 작동방식에 대해서 설명할 기회가 있다면 그 때 작성해보도록 하겠습니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1034&quot; data-origin-height=&quot;366&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lcMD1/btrPfPQodVl/k9tPnizm71IA04FfjSUJG0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lcMD1/btrPfPQodVl/k9tPnizm71IA04FfjSUJG0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lcMD1/btrPfPQodVl/k9tPnizm71IA04FfjSUJG0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlcMD1%2FbtrPfPQodVl%2Fk9tPnizm71IA04FfjSUJG0%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;1034&quot; height=&quot;366&quot; data-origin-width=&quot;1034&quot; data-origin-height=&quot;366&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;span style=&quot;color: #000000;&quot;&gt;&lt;b&gt;Apic&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;혹시나 Stomp로 연결한 socket을 브라우저 상에서 프론트엔드 도움 없이 테스트해보고 싶다면 크롬 웹스토어에서 Apic을 사용해보는 것도 좋은 경험이 될 것이라고 생각합니다!!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1666416193702&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Apic - Complete API solution&quot; data-og-description=&quot;The only tool you will ever need for all you API Design, Documentation and Testing needs.&quot; data-og-host=&quot;chrome.google.com&quot; data-og-source-url=&quot;https://chrome.google.com/webstore/detail/apic-complete-api-solutio/ggnhohnkfcpcanfekomdkjffnfcjnjam?hl=ko&quot; data-og-url=&quot;https://chrome.google.com/webstore/detail/apic-complete-api-solutio/ggnhohnkfcpcanfekomdkjffnfcjnjam&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bYwkLi/hyQbAci27g/hcHYiyK6mvt89f9EkOzASk/img.jpg?width=128&amp;amp;height=128&amp;amp;face=0_0_128_128&quot;&gt;&lt;a href=&quot;https://chrome.google.com/webstore/detail/apic-complete-api-solutio/ggnhohnkfcpcanfekomdkjffnfcjnjam?hl=ko&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://chrome.google.com/webstore/detail/apic-complete-api-solutio/ggnhohnkfcpcanfekomdkjffnfcjnjam?hl=ko&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bYwkLi/hyQbAci27g/hcHYiyK6mvt89f9EkOzASk/img.jpg?width=128&amp;amp;height=128&amp;amp;face=0_0_128_128');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Apic - Complete API solution&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;The only tool you will ever need for all you API Design, Documentation and Testing needs.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;chrome.google.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;664&quot; data-origin-height=&quot;392&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/K4ed5/btrPg1PPDJN/079EzBrOVnK9OVb9zLauSK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/K4ed5/btrPg1PPDJN/079EzBrOVnK9OVb9zLauSK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/K4ed5/btrPg1PPDJN/079EzBrOVnK9OVb9zLauSK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FK4ed5%2FbtrPg1PPDJN%2F079EzBrOVnK9OVb9zLauSK%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;664&quot; height=&quot;392&quot; data-origin-width=&quot;664&quot; data-origin-height=&quot;392&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;/p&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: #ee2323;&quot;&gt;&lt;b&gt;타이머&lt;/b&gt;&lt;/span&gt;였습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;30초, 혹은 10초가 지나면 턴이 종료되는 부분은 게임 정보이고, 게임 정보는 모두 백엔드에서 관리하고 있어야 한다는 의견에 모두가 동의했기 때문에 현재 남은 시간을 처리하기 위해서 Timer를 사용해야 했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 하나의 방에는 타이머 변수를 담은 무언가가 필요했고, Room Entity 안에 Timer객체를 넣어서 사용하는 방식을 채택하게 되었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 요소는 프론트엔드에서의 setTimeout과 비슷하게 동작했기 때문에 이해 자체는 크게 어렵지 않았습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(Redis를 사용했다면 Timer 객체를 별도로 관리해야 할 것 같아서 더욱 어려웠을 것이라고 생각합니다!!)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;482&quot; data-origin-height=&quot;49&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bux5kL/btrPfEH1rbY/vBhF7GcckjgYJ2y5ln9skK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bux5kL/btrPfEH1rbY/vBhF7GcckjgYJ2y5ln9skK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bux5kL/btrPfEH1rbY/vBhF7GcckjgYJ2y5ln9skK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbux5kL%2FbtrPfEH1rbY%2FvBhF7GcckjgYJ2y5ln9skK%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;482&quot; height=&quot;49&quot; data-origin-width=&quot;482&quot; data-origin-height=&quot;49&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;이제 이 타이머변수에다가 게임 내 Phase가 지날 때마다 변경시키고, 현재 Phase 자체를 변경시키는 부분을 담아두었습니다.&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1114&quot; data-origin-height=&quot;478&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/QFX0n/btrPjkgPwgE/PWNAk745HHC7dAdbYul051/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/QFX0n/btrPjkgPwgE/PWNAk745HHC7dAdbYul051/img.png&quot; data-alt=&quot;SocketController&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/QFX0n/btrPjkgPwgE/PWNAk745HHC7dAdbYul051/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FQFX0n%2FbtrPjkgPwgE%2FPWNAk745HHC7dAdbYul051%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;1114&quot; height=&quot;478&quot; data-origin-width=&quot;1114&quot; data-origin-height=&quot;478&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;SocketController&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1002&quot; data-origin-height=&quot;683&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0gJYp/btrPgKU5DtF/OwZVEFZodmV3ZjKb3VwGu0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0gJYp/btrPgKU5DtF/OwZVEFZodmV3ZjKb3VwGu0/img.png&quot; data-alt=&quot;RoomRepository 내 startTimer 메서드&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0gJYp/btrPgKU5DtF/OwZVEFZodmV3ZjKb3VwGu0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0gJYp%2FbtrPgKU5DtF%2FOwZVEFZodmV3ZjKb3VwGu0%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;1002&quot; height=&quot;683&quot; data-origin-width=&quot;1002&quot; data-origin-height=&quot;683&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;RoomRepository 내 startTimer 메서드&lt;/figcaption&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(물론 QA과정에서 발생하는 백엔드 에러 수정은 프로젝트 종료시까지 계속되었습니다!)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프론트엔드에서는 메인 페이지, 랭킹 페이지, 게임 내 일부 기능(채팅 등), FAQ 페이지를 맡아서 진행했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사용해보고 싶었던 grid도 직접 적용해보았고, 스크롤 처리 문제도 직접 해결할 수 있었습니다.&lt;/p&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;&quot;&lt;b&gt;너비가 넓으면 가운데 정렬하되 맨 앞부터 보이게 하는 문제&lt;/b&gt;&quot;&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;랭킹의 오늘의 NFT 거래 파트에서는 flex를 사용했는데, 어떤 속성을 만져야할 지에 대해서 고민을 많이 했었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;한참을 고민하고 검색하던 중 StackOverflow에서 같은 고민을 하다가 해결한 분의 메시지를 보고 원하는 대로 구현을 할 수 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Safe center라는 조건을 처음 알았습니다.. 정말로...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1666416867078&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Can't scroll to top of flex item that is overflowing container&quot; data-og-description=&quot;In attempting to make a useful modal using flexbox, I found what seems to be a browser issue and am wondering if there is a known fix or workaround -- or ideas on how to resolve it. The thing I'm t...&quot; data-og-host=&quot;stackoverflow.com&quot; data-og-source-url=&quot;https://stackoverflow.com/questions/33454533/cant-scroll-to-top-of-flex-item-that-is-overflowing-container&quot; data-og-url=&quot;https://stackoverflow.com/questions/33454533/cant-scroll-to-top-of-flex-item-that-is-overflowing-container&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/bYQTXp/hyQandm2yV/BMd9e833UygM1mfow2D3DK/img.png?width=316&amp;amp;height=316&amp;amp;face=0_0_316_316,https://scrap.kakaocdn.net/dn/WrKEW/hyQbsSScwt/02Pfq6mZswY0G7I27ZLlwk/img.png?width=758&amp;amp;height=345&amp;amp;face=0_0_758_345,https://scrap.kakaocdn.net/dn/Kkr9P/hyQbrTY4Jv/s2cCmhYRzsM1B96aOSISr0/img.png?width=708&amp;amp;height=327&amp;amp;face=0_0_708_327&quot;&gt;&lt;a href=&quot;https://stackoverflow.com/questions/33454533/cant-scroll-to-top-of-flex-item-that-is-overflowing-container&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://stackoverflow.com/questions/33454533/cant-scroll-to-top-of-flex-item-that-is-overflowing-container&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/bYQTXp/hyQandm2yV/BMd9e833UygM1mfow2D3DK/img.png?width=316&amp;amp;height=316&amp;amp;face=0_0_316_316,https://scrap.kakaocdn.net/dn/WrKEW/hyQbsSScwt/02Pfq6mZswY0G7I27ZLlwk/img.png?width=758&amp;amp;height=345&amp;amp;face=0_0_758_345,https://scrap.kakaocdn.net/dn/Kkr9P/hyQbrTY4Jv/s2cCmhYRzsM1B96aOSISr0/img.png?width=708&amp;amp;height=327&amp;amp;face=0_0_708_327');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Can't scroll to top of flex item that is overflowing container&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;In attempting to make a useful modal using flexbox, I found what seems to be a browser issue and am wondering if there is a known fix or workaround -- or ideas on how to resolve it. The thing I'm t...&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;stackoverflow.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Honeycam_2022-10-07_00-52-03.gif&quot; data-origin-width=&quot;1340&quot; data-origin-height=&quot;709&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/puxuN/btrPgoSjhhb/K8KKppiCkJ7aKgA43OKHP0/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/puxuN/btrPgoSjhhb/K8KKppiCkJ7aKgA43OKHP0/img.gif&quot; data-alt=&quot;Normal Center일 때 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/puxuN/btrPgoSjhhb/K8KKppiCkJ7aKgA43OKHP0/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/puxuN/btrPgoSjhhb/K8KKppiCkJ7aKgA43OKHP0/img.gif&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1340&quot; height=&quot;709&quot; data-filename=&quot;Honeycam_2022-10-07_00-52-03.gif&quot; data-origin-width=&quot;1340&quot; data-origin-height=&quot;709&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Normal Center일 때 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;Honeycam_2022-10-07_00-52-43.gif&quot; data-origin-width=&quot;1340&quot; data-origin-height=&quot;709&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bmLH35/btrPf223Tvb/Ew8m0TOKrTAlhl4gagGrH0/img.gif&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bmLH35/btrPf223Tvb/Ew8m0TOKrTAlhl4gagGrH0/img.gif&quot; data-alt=&quot;Safe Center일 때 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bmLH35/btrPf223Tvb/Ew8m0TOKrTAlhl4gagGrH0/img.gif&quot; srcset=&quot;https://blog.kakaocdn.net/dn/bmLH35/btrPf223Tvb/Ew8m0TOKrTAlhl4gagGrH0/img.gif&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1340&quot; height=&quot;709&quot; data-filename=&quot;Honeycam_2022-10-07_00-52-43.gif&quot; data-origin-width=&quot;1340&quot; data-origin-height=&quot;709&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;Safe Center일 때 모습&lt;/figcaption&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;3. 종합&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음으로 맡는 백엔드 작업이었기 때문에 설레기도 했고, 어렵기도 했습니다만 정말로 재미있게 프로젝트를 진행할 수 있었습니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로젝트 초반부에 팀원의 수가 줄어들었고, 사정상 프로젝트에 많은 시간을 할애할 수 없는 팀원이 있었기에 팀 내 유일한 풀타임 백엔드 개발자로서 부담감이 다소 늘어났지만, 오히려 '내가 할 부분이 많아졌다는 점에서 재미있겠다' 라고 느낄정도로 열정적으로 프로젝트에 임할 수 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만 쪼오금 아쉬웠던 점은 위에서 언급한 대로 같이 Backend를 맡게 된 팀원들 중 1명은 온전히 시간을 쏟을 수 없었던 상황이었고, 1명은 프로젝트 사정상 Smart Contract로 할당되어야 했기 때문에 대부분의 문제에 있어서 혼자서 난관을 헤쳐나가야 했던 부분입니다.&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;그래도 Java, Spring Boot, MySQL, JPA 등 프론트엔드 개발자가 쉽게 접하기 힘든 백엔드적인 요소들에 대해서 정말로 많이 부딪히면서 배우게 되었다는 것입니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 도전이 아니었다면 또 언제 Spring Boot를 이용해서 이정도 규모의 프로젝트에서 백엔드 부분을 맡아서 진행할 수 있을까요 ㅎㅎ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아쉽게도 본상 수상에는 실패했지만 NFT에 대해서 많이 알게 되었고, 백엔드 개발자가 고민할 수 있는 부분에 대해서도 많이 고민할 수 있었고, 코드리뷰와 주간테크톡을 통해서 학습적인 부분도 충분히 챙겨갈 수 있었기에 정말로 만족스러운 프로젝트였습니다!!&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;4. 애플리케이션 화면 사진&lt;/b&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/kLhNJ/btrPg0KbGiz/iJ9pRRJbKH4GRB4q1LVp10/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/kLhNJ/btrPg0KbGiz/iJ9pRRJbKH4GRB4q1LVp10/img.png&quot; data-alt=&quot;게임 내 카드 제출&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/kLhNJ/btrPg0KbGiz/iJ9pRRJbKH4GRB4q1LVp10/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FkLhNJ%2FbtrPg0KbGiz%2FiJ9pRRJbKH4GRB4q1LVp10%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;720&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;게임 내 카드 제출&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cgNtTT/btrPgWnoV3b/UKSFNwPkVTBLScm6G42Ask/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cgNtTT/btrPgWnoV3b/UKSFNwPkVTBLScm6G42Ask/img.png&quot; data-alt=&quot;게임 내 카드 선택&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cgNtTT/btrPgWnoV3b/UKSFNwPkVTBLScm6G42Ask/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcgNtTT%2FbtrPgWnoV3b%2FUKSFNwPkVTBLScm6G42Ask%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;720&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;게임 내 카드 선택&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/IrDIv/btrPfpxH16D/TkfD0grRPKS7PkIfSZBi2K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/IrDIv/btrPfpxH16D/TkfD0grRPKS7PkIfSZBi2K/img.png&quot; data-alt=&quot;게임 결과&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/IrDIv/btrPfpxH16D/TkfD0grRPKS7PkIfSZBi2K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FIrDIv%2FbtrPfpxH16D%2FTkfD0grRPKS7PkIfSZBi2K%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;720&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;게임 결과&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vixZs/btrPjGD6yxq/OKm9FeWa2Fmuu3KwaLA2A0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vixZs/btrPjGD6yxq/OKm9FeWa2Fmuu3KwaLA2A0/img.png&quot; data-alt=&quot;내 카드 확인&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vixZs/btrPjGD6yxq/OKm9FeWa2Fmuu3KwaLA2A0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvixZs%2FbtrPjGD6yxq%2FOKm9FeWa2Fmuu3KwaLA2A0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;720&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;내 카드 확인&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Msrdd/btrPg1I54cX/CQhJ9TIUMGHhyKINsE96x1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Msrdd/btrPg1I54cX/CQhJ9TIUMGHhyKINsE96x1/img.png&quot; data-alt=&quot;그림 생성&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Msrdd/btrPg1I54cX/CQhJ9TIUMGHhyKINsE96x1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FMsrdd%2FbtrPg1I54cX%2FCQhJ9TIUMGHhyKINsE96x1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;720&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림 생성&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cYze3k/btrPjGYogm8/7BaCpekIQsGe4Uus6rDqkk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cYze3k/btrPjGYogm8/7BaCpekIQsGe4Uus6rDqkk/img.png&quot; data-alt=&quot;NFT 카드 거래소&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cYze3k/btrPjGYogm8/7BaCpekIQsGe4Uus6rDqkk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcYze3k%2FbtrPjGYogm8%2F7BaCpekIQsGe4Uus6rDqkk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;720&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;NFT 카드 거래소&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bNreea/btrPgf11tEW/UPYJLOry8BkAwx84LcCa01/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bNreea/btrPgf11tEW/UPYJLOry8BkAwx84LcCa01/img.png&quot; data-alt=&quot;이달의 그림 투표&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bNreea/btrPgf11tEW/UPYJLOry8BkAwx84LcCa01/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbNreea%2FbtrPgf11tEW%2FUPYJLOry8BkAwx84LcCa01%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;720&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이달의 그림 투표&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qg6XF/btrPgEm0acz/10tjIIqgkkb60PDKvJVqgk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qg6XF/btrPgEm0acz/10tjIIqgkkb60PDKvJVqgk/img.png&quot; data-alt=&quot;랭킹페이지&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qg6XF/btrPgEm0acz/10tjIIqgkkb60PDKvJVqgk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fqg6XF%2FbtrPgEm0acz%2F10tjIIqgkkb60PDKvJVqgk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;720&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;랭킹페이지&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bH8Dyf/btrPjHQxPMX/lXs6QgOB6KSzikmTjkO8B0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bH8Dyf/btrPjHQxPMX/lXs6QgOB6KSzikmTjkO8B0/img.png&quot; data-alt=&quot;FAQ 페이지&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bH8Dyf/btrPjHQxPMX/lXs6QgOB6KSzikmTjkO8B0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbH8Dyf%2FbtrPjHQxPMX%2FlXs6QgOB6KSzikmTjkO8B0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1280&quot; height=&quot;720&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;720&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;FAQ 페이지&lt;/figcaption&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;5. 참고 자료 및 기술 스택 관련 자료&lt;/b&gt;&lt;/h2&gt;
&lt;figure id=&quot;og_1666417775501&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;GitHub Flow&quot; data-og-description=&quot;Git/GitHub 안내서 - GitHub Flow&quot; data-og-host=&quot;subicura.com&quot; data-og-source-url=&quot;https://subicura.com/git/guide/github-flow.html#github-flow-%E1%84%87%E1%85%A1%E1%86%BC%E1%84%89%E1%85%B5%E1%86%A8&quot; data-og-url=&quot;https://subicura.com/git/guide/github-flow.html&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/jPycq/hyQarGOFfq/NhYgY5aAarbMWNKzTy5CO0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/ebxGPq/hyQhCl81Ow/ZejxxZWF0Y0lu1gHwbkI51/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://subicura.com/git/guide/github-flow.html#github-flow-%E1%84%87%E1%85%A1%E1%86%BC%E1%84%89%E1%85%B5%E1%86%A8&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://subicura.com/git/guide/github-flow.html#github-flow-%E1%84%87%E1%85%A1%E1%86%BC%E1%84%89%E1%85%B5%E1%86%A8&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/jPycq/hyQarGOFfq/NhYgY5aAarbMWNKzTy5CO0/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630,https://scrap.kakaocdn.net/dn/ebxGPq/hyQhCl81Ow/ZejxxZWF0Y0lu1gHwbkI51/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;GitHub Flow&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Git/GitHub 안내서 - GitHub Flow&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;subicura.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1666417797914&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Spring Data JPA&quot; data-og-description=&quot;Spring Data JPA, part of the larger Spring Data family, makes it easy to easily implement JPA based repositories. This module deals with enhanced support for JPA based data access layers. It makes it easier to build Spring-powered applications that use dat&quot; data-og-host=&quot;spring.io&quot; data-og-source-url=&quot;https://spring.io/projects/spring-data-jpa&quot; data-og-url=&quot;https://spring.io/projects/spring-data-jpa&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://spring.io/projects/spring-data-jpa&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://spring.io/projects/spring-data-jpa&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Spring Data JPA&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Spring Data JPA, part of the larger Spring Data family, makes it easy to easily implement JPA based repositories. This module deals with enhanced support for JPA based data access layers. It makes it easier to build Spring-powered applications that use dat&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;spring.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1666417822563&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Redis&quot; data-og-description=&quot;Redis is an open source (BSD licensed), in-memory data structure store, used as a database, cache, and message broker&quot; data-og-host=&quot;redis.io&quot; data-og-source-url=&quot;https://redis.io/&quot; data-og-url=&quot;https://redis.io/&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://redis.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://redis.io/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Redis&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Redis is an open source (BSD licensed), in-memory data structure store, used as a database, cache, and message broker&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;redis.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1666417982617&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Timer (Java Platform SE 7 )&quot; data-og-description=&quot;Schedules the specified task for repeated fixed-rate execution, beginning at the specified time. Subsequent executions take place at approximately regular intervals, separated by the specified period. In fixed-rate execution, each execution is scheduled re&quot; data-og-host=&quot;docs.oracle.com&quot; data-og-source-url=&quot;https://docs.oracle.com/javase/7/docs/api/java/util/Timer.html&quot; data-og-url=&quot;https://docs.oracle.com/javase/7/docs/api/java/util/Timer.html&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://docs.oracle.com/javase/7/docs/api/java/util/Timer.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://docs.oracle.com/javase/7/docs/api/java/util/Timer.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Timer (Java Platform SE 7 )&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Schedules the specified task for repeated fixed-rate execution, beginning at the specified time. Subsequent executions take place at approximately regular intervals, separated by the specified period. In fixed-rate execution, each execution is scheduled re&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;docs.oracle.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1666418461810&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;STOMP&quot; data-og-description=&quot;STOMP is a very simple and easy to implement protocol, coming from the HTTP school of design; the server side may be hard to implement well, but it is very easy to write a client to get yourself connected. For example you can use Telnet to login to any STO&quot; data-og-host=&quot;stomp.github.io&quot; data-og-source-url=&quot;https://stomp.github.io/&quot; data-og-url=&quot;https://stomp.github.io/&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://stomp.github.io/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://stomp.github.io/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;STOMP&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;STOMP is a very simple and easy to implement protocol, coming from the HTTP school of design; the server side may be hard to implement well, but it is very easy to write a client to get yourself connected. For example you can use Telnet to login to any STO&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;stomp.github.io&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1666418495091&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;sockjs&quot; data-og-description=&quot;SockJS-node is a server counterpart of SockJS-client a JavaScript library that provides a WebSocket-like object in the browser. SockJS gives you a coherent, cross-browser, Javascript API which creates a low latency, full duplex, cross-domain communication.&quot; data-og-host=&quot;www.npmjs.com&quot; data-og-source-url=&quot;https://www.npmjs.com/package/sockjs&quot; data-og-url=&quot;https://www.npmjs.com/package/sockjs&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/yBZyz/hyQan5voLK/RfH8kk5wV2NVCxuxs8m2p1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630&quot;&gt;&lt;a href=&quot;https://www.npmjs.com/package/sockjs&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.npmjs.com/package/sockjs&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/yBZyz/hyQan5voLK/RfH8kk5wV2NVCxuxs8m2p1/img.png?width=1200&amp;amp;height=630&amp;amp;face=0_0_1200_630');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;sockjs&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;SockJS-node is a server counterpart of SockJS-client a JavaScript library that provides a WebSocket-like object in the browser. SockJS gives you a coherent, cross-browser, Javascript API which creates a low latency, full duplex, cross-domain communication.&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.npmjs.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category># 주저리주저리/가끔 하고 싶은 뻘소리</category>
      <category>7주</category>
      <category>ImTeller</category>
      <category>아임텔러</category>
      <category>특화프로젝트</category>
      <category>프로젝트회고</category>
      <category>프로젝트후기</category>
      <category>회고</category>
      <author>Ssoco</author>
      <guid isPermaLink="true">https://ssocoit.tistory.com/268</guid>
      <comments>https://ssocoit.tistory.com/268#entry268comment</comments>
      <pubDate>Sat, 22 Oct 2022 15:03:47 +0900</pubDate>
    </item>
    <item>
      <title>[SSH] MobaXterm으로 편하게 SSH 원격 접속하기</title>
      <link>https://ssocoit.tistory.com/267</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;저번 프로젝트동안 알차게 썼던 MobaXterm이었는데, 이번에는 아예 백엔드 및 서버 파트를 담당하게 되었기 때문에 서버에 접속하게 될 일이 훨씬 많아질 것 같아서, 사용법에 대해서 간단하게 정리해보려고 합니다.&lt;/p&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: #ee2323;&quot;&gt;&lt;b&gt;Windows 환경&lt;/b&gt;&lt;/span&gt;에서 설명하는 점 참고 부탁드리겠습니다 :)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div class=&quot;book-toc&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;목차&lt;/p&gt;
&lt;ul id=&quot;toc&quot; style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;&lt;/ul&gt;
&lt;/div&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;0. MobaXtrem 다운로드 받기&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존에는 서버에 접속하기 위해서 PuTTY만 사용했었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;몇 년 전에도, 지금도 PuTTY가 업계 1위인건 맞는 것 같습니다만.. ㅋㅋㅋㅋㅋ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure id=&quot;og_1663134925920&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;Download PuTTY - a free SSH and telnet client for Windows&quot; data-og-description=&quot;Is Bitvise affiliated with PuTTY? Bitvise is not affiliated with PuTTY. We develop our SSH Server for Windows, which is compatible with PuTTY. Many PuTTY users are therefore our users as well. From time to time, they need to find the PuTTY download link. W&quot; data-og-host=&quot;www.putty.org&quot; data-og-source-url=&quot;https://www.putty.org/&quot; data-og-url=&quot;https://www.putty.org/&quot; data-og-image=&quot;&quot;&gt;&lt;a href=&quot;https://www.putty.org/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://www.putty.org/&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url();&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;Download PuTTY - a free SSH and telnet client for Windows&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;Is Bitvise affiliated with PuTTY? Bitvise is not affiliated with PuTTY. We develop our SSH Server for Windows, which is compatible with PuTTY. Many PuTTY users are therefore our users as well. From time to time, they need to find the PuTTY download link. W&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;www.putty.org&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 저번 프로젝트를 통해서 MobaXterm이라는 새로운 친구를 만나게 되었고, 보다 편리하게 서버에 접속할 수 있게 되었습니다.&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;figure id=&quot;og_1663134988228&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;MobaXterm free Xserver and tabbed SSH client for Windows&quot; data-og-description=&quot;The ultimate toolbox for remote computing - includes X server, enhanced SSH client and much more!&quot; data-og-host=&quot;mobaxterm.mobatek.net&quot; data-og-source-url=&quot;https://mobaxterm.mobatek.net/download.html&quot; data-og-url=&quot;https://mobaxterm.mobatek.net/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/NygHB/hyPM2s61MR/HgyNOrAgq5azseh96mgAD0/img.png?width=764&amp;amp;height=489&amp;amp;face=0_0_764_489,https://scrap.kakaocdn.net/dn/ebso0t/hyPMRybOH3/kNWFzajpJ1CkC9WLJT2HR0/img.png?width=768&amp;amp;height=443&amp;amp;face=0_0_768_443,https://scrap.kakaocdn.net/dn/bQ5ToI/hyPMV1ErMi/tyNRgmsA9vLUdnwG5d3pw1/img.png?width=768&amp;amp;height=443&amp;amp;face=0_0_768_443&quot;&gt;&lt;a href=&quot;https://mobaxterm.mobatek.net/download.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://mobaxterm.mobatek.net/download.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/NygHB/hyPM2s61MR/HgyNOrAgq5azseh96mgAD0/img.png?width=764&amp;amp;height=489&amp;amp;face=0_0_764_489,https://scrap.kakaocdn.net/dn/ebso0t/hyPMRybOH3/kNWFzajpJ1CkC9WLJT2HR0/img.png?width=768&amp;amp;height=443&amp;amp;face=0_0_768_443,https://scrap.kakaocdn.net/dn/bQ5ToI/hyPMV1ErMi/tyNRgmsA9vLUdnwG5d3pw1/img.png?width=768&amp;amp;height=443&amp;amp;face=0_0_768_443');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;MobaXterm free Xserver and tabbed SSH client for Windows&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;The ultimate toolbox for remote computing - includes X server, enhanced SSH client and much more!&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;mobaxterm.mobatek.net&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위 페이지에 접속해서 Home Edition을 받으면 무료로 사용할 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(필요하시다면 Professional Edition도 69달러..)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;간단하게 다운로드 받은 후에 압축을 풀고 msi 확장자를 가진 프로그램을 실행해서 깔아줍니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;501&quot; data-origin-height=&quot;125&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cGeYK6/btrL8Tm3gY8/9Revy80nPuyYqZxKyOAEa0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cGeYK6/btrL8Tm3gY8/9Revy80nPuyYqZxKyOAEa0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cGeYK6/btrL8Tm3gY8/9Revy80nPuyYqZxKyOAEa0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcGeYK6%2FbtrL8Tm3gY8%2F9Revy80nPuyYqZxKyOAEa0%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;501&quot; height=&quot;125&quot; data-origin-width=&quot;501&quot; data-origin-height=&quot;125&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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;짜잔~ MobaXterm 화면이 등장했습니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;제가 기존에 사용하던 PuTTY 세션들도 자동으로 등록된 모습도 확인이 가능하네요!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;909&quot; data-origin-height=&quot;522&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bv5ul3/btrL7uHPuir/jyUUKLwYkByXA18bxxuVP1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bv5ul3/btrL7uHPuir/jyUUKLwYkByXA18bxxuVP1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bv5ul3/btrL7uHPuir/jyUUKLwYkByXA18bxxuVP1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbv5ul3%2FbtrL7uHPuir%2FjyUUKLwYkByXA18bxxuVP1%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;909&quot; height=&quot;522&quot; data-origin-width=&quot;909&quot; data-origin-height=&quot;522&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. SSH로 접속하기&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왼쪽 위의 Session 버튼을 클릭해줍시다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;259&quot; data-origin-height=&quot;220&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/btNZAX/btrL35ba32b/f1sYxse8FMAb4GLx4qEk11/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/btNZAX/btrL35ba32b/f1sYxse8FMAb4GLx4qEk11/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/btNZAX/btrL35ba32b/f1sYxse8FMAb4GLx4qEk11/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbtNZAX%2FbtrL35ba32b%2Ff1sYxse8FMAb4GLx4qEk11%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;259&quot; height=&quot;220&quot; data-origin-width=&quot;259&quot; data-origin-height=&quot;220&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;그러면 다양한 세션 세팅 화면이 나오는데, 우리는 SSH를 통해 연결할 것이므로 SSH를 눌러줍시다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;896&quot; data-origin-height=&quot;601&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cGBs6W/btrL9j6A9tg/JJjuonATObC8oWdwXwrXk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cGBs6W/btrL9j6A9tg/JJjuonATObC8oWdwXwrXk0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cGBs6W/btrL9j6A9tg/JJjuonATObC8oWdwXwrXk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcGBs6W%2FbtrL9j6A9tg%2FJJjuonATObC8oWdwXwrXk0%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;896&quot; height=&quot;601&quot; data-origin-width=&quot;896&quot; data-origin-height=&quot;601&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;그렇다면 아래 SSH 화면이 뜨게 됩니다.&lt;/p&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: #ee2323;&quot;&gt;&lt;b&gt;Remote host&lt;/b&gt;&lt;/span&gt;부분인데, 이 부분에는 접속하려는 서버의 Public IP 혹은 도메인 이름을 입력하면 됩니다.&lt;/p&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: #ee2323;&quot;&gt;Remote host&lt;/span&gt;&lt;/b&gt;에 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;아이디@ip(혹은 도메인)&lt;/b&gt;&lt;/span&gt; 형식을 입력해주시면 되겠습니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;(자주 사용하는 유저네임이라면 오른쪽에 있는 Specify username을 체크하고 따로 입력해줄 수 있습니다. 비밀번호가 있는 경우 오른쪽 사람+열쇠버튼을 눌러서 등록해둘 수 있습니다!!)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;877&quot; data-origin-height=&quot;106&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9SKkr/btrL8TUUyDm/1rZt6IWaxktikmGYOughmk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9SKkr/btrL8TUUyDm/1rZt6IWaxktikmGYOughmk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9SKkr/btrL8TUUyDm/1rZt6IWaxktikmGYOughmk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9SKkr%2FbtrL8TUUyDm%2F1rZt6IWaxktikmGYOughmk%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;877&quot; height=&quot;106&quot; data-origin-width=&quot;877&quot; data-origin-height=&quot;106&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;만약 키 파일이 따로 있는 경우에는 아래에 Use private key 박스가 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이걸 체크하고 해당하는 .pem파일을 등록해주시면 되겠습니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;881&quot; data-origin-height=&quot;310&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dexaWS/btrL4k0jFdA/qB2DQGU6UpVSDcQBnJqIk0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dexaWS/btrL4k0jFdA/qB2DQGU6UpVSDcQBnJqIk0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dexaWS/btrL4k0jFdA/qB2DQGU6UpVSDcQBnJqIk0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdexaWS%2FbtrL4k0jFdA%2FqB2DQGU6UpVSDcQBnJqIk0%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;881&quot; height=&quot;310&quot; data-origin-width=&quot;881&quot; data-origin-height=&quot;310&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;여기까지 마치고 OK버튼을 누르면?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;바로 접속이 되는 모습을 보실 수 있습니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저는 Ubuntu 20.04 서버를 사용하고 있기 때문에 해당 서버에 잘 접속이 된 모습을 볼 수 있습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;PuTTY를 사용하던 시절보다 뭔가 설정하기도 편하고 접속하기도 쉬워진 것 같아요 ㅎㅎ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;898&quot; data-origin-height=&quot;418&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zLmfP/btrL5cOuxvT/LeYkYCAExpFOxifUKUIJ9k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zLmfP/btrL5cOuxvT/LeYkYCAExpFOxifUKUIJ9k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zLmfP/btrL5cOuxvT/LeYkYCAExpFOxifUKUIJ9k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FzLmfP%2FbtrL5cOuxvT%2FLeYkYCAExpFOxifUKUIJ9k%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;898&quot; height=&quot;418&quot; data-origin-width=&quot;898&quot; data-origin-height=&quot;418&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;style5&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. 참고자료&lt;/b&gt;&lt;/h2&gt;
&lt;figure id=&quot;og_1663136179133&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;MobaXterm free Xserver and tabbed SSH client for Windows&quot; data-og-description=&quot;The ultimate toolbox for remote computing - includes X server, enhanced SSH client and much more!&quot; data-og-host=&quot;mobaxterm.mobatek.net&quot; data-og-source-url=&quot;https://mobaxterm.mobatek.net/documentation.html&quot; data-og-url=&quot;https://mobaxterm.mobatek.net/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/dqQme0/hyPMZiKPCY/J9FQmAGTjVZmhQBvY8kqQ0/img.png?width=764&amp;amp;height=489&amp;amp;face=0_0_764_489,https://scrap.kakaocdn.net/dn/braJQU/hyPMNo8Ovh/rFGauCb6CtegfpUnhfFqZ1/img.png?width=768&amp;amp;height=443&amp;amp;face=0_0_768_443,https://scrap.kakaocdn.net/dn/bdA5wj/hyPM2moslX/chcv8xaAd5WoMuBm0sV2k0/img.png?width=768&amp;amp;height=443&amp;amp;face=0_0_768_443&quot;&gt;&lt;a href=&quot;https://mobaxterm.mobatek.net/documentation.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://mobaxterm.mobatek.net/documentation.html&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/dqQme0/hyPMZiKPCY/J9FQmAGTjVZmhQBvY8kqQ0/img.png?width=764&amp;amp;height=489&amp;amp;face=0_0_764_489,https://scrap.kakaocdn.net/dn/braJQU/hyPMNo8Ovh/rFGauCb6CtegfpUnhfFqZ1/img.png?width=768&amp;amp;height=443&amp;amp;face=0_0_768_443,https://scrap.kakaocdn.net/dn/bdA5wj/hyPM2moslX/chcv8xaAd5WoMuBm0sV2k0/img.png?width=768&amp;amp;height=443&amp;amp;face=0_0_768_443');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;MobaXterm free Xserver and tabbed SSH client for Windows&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;The ultimate toolbox for remote computing - includes X server, enhanced SSH client and much more!&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;mobaxterm.mobatek.net&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1663136148965&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[Linux] SSH 원격 접속 툴 - MobaXterm 설치 방법&amp;amp;사용법&quot; data-og-description=&quot;안녕하세요. 오늘은 SSH 원격 접속 툴 - MobaXterm 설치 방법&amp;amp;사용법에 대해 알아보도록 하겠습니다. 해당 툴은 PuTTY와 FileZilla를 한꺼번에 사용할 수 있는 툴이고 PuTTY보다 가독성이 좋습니다. 사용법&quot; data-og-host=&quot;jeeu147.tistory.com&quot; data-og-source-url=&quot;https://jeeu147.tistory.com/108&quot; data-og-url=&quot;https://jeeu147.tistory.com/108&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/b0Qfis/hyPMS4XTQ4/AWxSRYPG7VqLT8PveMdOSk/img.png?width=800&amp;amp;height=538&amp;amp;face=0_0_800_538,https://scrap.kakaocdn.net/dn/pvwj9/hyPMNioUUj/nEjyrBwhxEestevkxbQJFk/img.png?width=800&amp;amp;height=538&amp;amp;face=0_0_800_538,https://scrap.kakaocdn.net/dn/bdrPxT/hyPM0orDlD/FB9AUwrOUsTcGR1nT2pXW0/img.png?width=1920&amp;amp;height=1080&amp;amp;face=0_0_1920_1080&quot;&gt;&lt;a href=&quot;https://jeeu147.tistory.com/108&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://jeeu147.tistory.com/108&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/b0Qfis/hyPMS4XTQ4/AWxSRYPG7VqLT8PveMdOSk/img.png?width=800&amp;amp;height=538&amp;amp;face=0_0_800_538,https://scrap.kakaocdn.net/dn/pvwj9/hyPMNioUUj/nEjyrBwhxEestevkxbQJFk/img.png?width=800&amp;amp;height=538&amp;amp;face=0_0_800_538,https://scrap.kakaocdn.net/dn/bdrPxT/hyPM0orDlD/FB9AUwrOUsTcGR1nT2pXW0/img.png?width=1920&amp;amp;height=1080&amp;amp;face=0_0_1920_1080');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[Linux] SSH 원격 접속 툴 - MobaXterm 설치 방법&amp;amp;사용법&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;안녕하세요. 오늘은 SSH 원격 접속 툴 - MobaXterm 설치 방법&amp;amp;사용법에 대해 알아보도록 하겠습니다. 해당 툴은 PuTTY와 FileZilla를 한꺼번에 사용할 수 있는 툴이고 PuTTY보다 가독성이 좋습니다. 사용법&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;jeeu147.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;figure id=&quot;og_1663136160781&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;article&quot; data-og-title=&quot;[터미널] MobaXterm 설치법, 사용법&quot; data-og-description=&quot;서버에 접속할 때 많이 쓰는 프로그램에는 'Putty'가 있다. 여러 파일들을 vi에디터로 수정/관리해야하는 경우 'Putty'만으로는 한계가 있기 때문에 'MobaXterm'을 추천한다. 'MobaXterm'은 'Putty', Xwindows환&quot; data-og-host=&quot;whiteramen.tistory.com&quot; data-og-source-url=&quot;https://whiteramen.tistory.com/17&quot; data-og-url=&quot;https://whiteramen.tistory.com/17&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/gw6nx/hyPMWlZ8G9/59UgTkuXTztqf6BvV3OK80/img.png?width=691&amp;amp;height=78&amp;amp;face=299_22_322_45,https://scrap.kakaocdn.net/dn/wkApj/hyPMQ0ov9L/kqOLorGvJvY41sixOvRc5k/img.png?width=691&amp;amp;height=78&amp;amp;face=299_22_322_45,https://scrap.kakaocdn.net/dn/bKqrMF/hyPMWsK3c5/psckGqRnpeKpdP8ZG3VnOk/img.png?width=898&amp;amp;height=604&amp;amp;face=0_0_898_604&quot;&gt;&lt;a href=&quot;https://whiteramen.tistory.com/17&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://whiteramen.tistory.com/17&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/gw6nx/hyPMWlZ8G9/59UgTkuXTztqf6BvV3OK80/img.png?width=691&amp;amp;height=78&amp;amp;face=299_22_322_45,https://scrap.kakaocdn.net/dn/wkApj/hyPMQ0ov9L/kqOLorGvJvY41sixOvRc5k/img.png?width=691&amp;amp;height=78&amp;amp;face=299_22_322_45,https://scrap.kakaocdn.net/dn/bKqrMF/hyPMWsK3c5/psckGqRnpeKpdP8ZG3VnOk/img.png?width=898&amp;amp;height=604&amp;amp;face=0_0_898_604');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;[터미널] MobaXterm 설치법, 사용법&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;서버에 접속할 때 많이 쓰는 프로그램에는 'Putty'가 있다. 여러 파일들을 vi에디터로 수정/관리해야하는 경우 'Putty'만으로는 한계가 있기 때문에 'MobaXterm'을 추천한다. 'MobaXterm'은 'Putty', Xwindows환&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;whiteramen.tistory.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category># 공부 자료들/기타</category>
      <category>mobaXterm</category>
      <category>putty</category>
      <category>ssh</category>
      <category>대체</category>
      <category>원격접속</category>
      <author>Ssoco</author>
      <guid isPermaLink="true">https://ssocoit.tistory.com/267</guid>
      <comments>https://ssocoit.tistory.com/267#entry267comment</comments>
      <pubDate>Wed, 14 Sep 2022 15:17:29 +0900</pubDate>
    </item>
  </channel>
</rss>