<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>개발자 유니</title>
    <link>https://jae-yoon.tistory.com/</link>
    <description>단편적 지식을 통합된 지식으로</description>
    <language>ko</language>
    <pubDate>Tue, 9 Jun 2026 09:56:33 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>Dev Uni</managingEditor>
    <image>
      <title>개발자 유니</title>
      <url>https://tistory1.daumcdn.net/tistory/5252507/attach/1b18dc7f82d74e10be3bded9a76fe779</url>
      <link>https://jae-yoon.tistory.com</link>
    </image>
    <item>
      <title>[오늘의 일기] 자기 객관화</title>
      <link>https://jae-yoon.tistory.com/22</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;거의 1년여 만에 포스팅이다. 데브코스 이후 6개월이 지난 시점의 나는 어떠한 사람인가에 대해 자기 객관화가 필요하다고 생각되어 키보드에 손을 올리게 되었다. (오글거릴 수 있으니 미리 말씀드립니다.)&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: #666666;&quot;&gt;&lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;사실, 살면서 힘들다는 감정을 경험해 본 적이 거의 없었다. 긍정적인 사고를 가지도록 노력해 왔고, 실제로 어려움을 겪는 사람들에 비해 나의 어려움은 &lt;span style=&quot;background-color: #ffffff; text-align: start;&quot;&gt;상대적으로 &lt;/span&gt;크지 않다고 생각해 왔기 때문이다.&lt;/span&gt; 그러나, 최근에는 정말로 힘들다는 감정을 겪어왔다. 몇 번의 탈락을 경험했는지 세는 것을 까먹었으며, 개인적인 사정, 서울에 잔류하느냐 부산으로 돌아가느냐, 강아지의 아픔 등 단기간에 닥쳐왔다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;오랜만에 본가에 내려갔을 때, 주변에서 살이 너무 빠졌다고 하여 몸무게를 재보니 10kg 정도 빠져있었다. 여러 가지의 일들을 겪기도 했고 불규칙적인 습관과 취업 준비로 인하여 집에만 있다 보니 정신적으로도, 신체적으로도 피폐해질 대로 피폐해진 상태였다. 지금 당장은 무언가를 할 수 없는 상태라고 판단하여 푹 쉬면서 건강 회복에 전념한 것 같다. &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: #666666;&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;span style=&quot;color: #666666;&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;span style=&quot;color: #666666;&quot;&gt;&lt;b&gt;데브코스 이후에 어떻게 살아왔는가?&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1536&quot; data-origin-height=&quot;538&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b3htBy/btsHosHDoUU/5AlKb07IPyIPpiyoFdFVy0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b3htBy/btsHosHDoUU/5AlKb07IPyIPpiyoFdFVy0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b3htBy/btsHosHDoUU/5AlKb07IPyIPpiyoFdFVy0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb3htBy%2FbtsHosHDoUU%2F5AlKb07IPyIPpiyoFdFVy0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1536&quot; height=&quot;538&quot; data-origin-width=&quot;1536&quot; data-origin-height=&quot;538&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;부끄럽지만 데브코스&amp;nbsp;&lt;span style=&quot;text-align: start;&quot;&gt;수료 이후 깃허브의 빈 잔디에서 증명되듯이&lt;/span&gt;, 번아웃이 와버렸고 의미 없는 나날을 보내는 연속이었다. 게임을 할 때 나오는 한순간의 도파민에 이끌려 시간을 낭비해 왔었다.&amp;nbsp;&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: #666666;&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;span style=&quot;color: #666666;&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;&lt;b&gt;꽁꽁 얼어붙은 채용시장 위로 신재윤이 걸어갑니다&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;준비가 미흡하다고 생각하여, 이력서를 수정만 하는 나날이 지속되었다. 주변으로부터 많은 피드백을 받았고, 여러 회사에 지원하기 시작했다. 너무나도 많은 탈락을 경험했고 세는 것을 잊어버리게 되었다. 답답한 마음에 데브코스 멘토님들, 주변 지인, 심지어 유료 이력서 피드백에도 수십만 원을 썼다. 그럼에도 돌아오는 답변은 &quot;이 정도의 이력서면 그래도 신입 수준에서는 이미 충분한데..? 더 수정할 부분이 보이지 않는다&quot;였다. 그러나, 코딩테스트까지 가지도 못하고 서류탈락을 경험한 적이 대부분이었기에 답답한 마음이었다.&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: #666666;&quot;&gt;2024년 상반기의 채용시장이 정말 힘들다는 이야기가 많다. 하지만 그럼에도 불구하고, 취업하는 사람은 취업을 한다. 그래서 신입 수준에서 충분한 데의 이력서는 이제는 매력이 없는 것이 아닐까라고 생각하게 되었고 자기 객관화를 하기 시작했다. 채용 프로세스를 생각하며, 채워나가야 할 부족한 부분을 고민했다. 채용 프로세스는 크게 이력서, 코딩테스트, 면접으로 3가지이다.&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;&lt;b&gt;부족한 부분들 (1) - 이력서&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;객관적으로 나의 이력서를 보면, 백엔드적인 요소보다 인프라적인 요소가 많은 이력서라고 생각되고 고민한 흔적이 미흡하다고 판단했다. 내 이력서의 주된 키워드인 동시성, 검색 쿼리 최적화, DBCP 튜닝, nginx 튜닝, 모니터링을 통한 성능 최적화 정도는 신입 수준에서도 조금만 고민해 보면 충분히 나올 이야기이고 나와 비슷한 지원자 사이에서 매력을 어필하기에는 부족하다고 느껴졌다.&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: #666666;&quot;&gt;또, 주변에서 해준 피드백은 &quot;지금 내가 가지고 있는 역량&quot; 기준에서 충분하다는 의미였을 것 같다. 애초에 재료 자체가 뛰어난 재료가 아닌데 극강으로 요리해 봐야 나오는 결과물은 한정적이었을 것이다. 물론 이력서에서 프로젝트의 개수가 절대적인 것은 아니지만, 지금 내가 진행한 프로젝트로는 한정적이다.&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: #666666;&quot;&gt;흔히 MSA, 카프카, 웹플럭스, 엘라스틱 서치 등은 신입의 이력서에 맞지 않다고들 많이 이야기한다. 나 역시도 이에는 동의한다. 이 정도의 기술이 필요한 트래픽을 경험해 보기 어려운 것이 가장 큰 이유이고 워낙 어려운 기술이라 겉핥기식으로만 공부하고 이력서에 적는 경우가 많아서 이런 이야기가 나온 것 같다.&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: #666666;&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;span style=&quot;color: #666666;&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;span style=&quot;color: #666666;&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;&lt;b&gt;부족한 부분들 (2) - 코딩테스트&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&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;span style=&quot;color: #666666;&quot;&gt;그러나, 프로젝트를 하며 정신이 번쩍 든 경험이 있다. 내가 맡은 도메인 중 하나가 너무나 방대하여 다른 팀원과 페어 프로그래밍으로 진행하는 도메인이 있었는데 꽤나 복잡한 비즈니스 로직을 구현해야 했었다. 막막하여 어떻게 하나 고민만 하던 와중, 다른 팀원이 마치 코딩테스트 문제 풀 듯이 접근하여 코드를 작성한 것을 보고 흔히 말하는 &quot;코딩테스트 빡구현&quot; 문제에 대해 다시 생각하게 되었다.&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: #666666;&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;span style=&quot;color: #666666;&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;&lt;b&gt;부족한 부분들 (3) - 면접&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;부끄럽지만 면접 스터디를 진행해 오며 많이 들은 말이 있다. &quot;재윤 님은 면접까지 가기만 하면 무조건 합격할 것 같아요&quot;. 나는 면접에서 크게 긴장하지 않는 편이다. 특히나, 개발자의 관문인 기술 면접은 자신이 아는 지식에 대하여 편하게 커피챗하는 느낌이라 더욱 긴장하지 않는 것 같다.&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: #666666;&quot;&gt;면접에 있어서 소프트적인 스킬을 수정하기 보다는, 잊어버리지 않게 지속적으로 보는 것이 중요하다고 생각한다. 또, CS 지식은 내가 개발 공부를 하며 가장 흥미 있어하는 부분이라 꽤나 깊게 공부하기도 하고 재밌어서 지치지 않는다. 다만, 네트워크, 운영체제, 데이터베이스는 괜찮은데... 알고리즘과 자료구조는 사실 많이 미약하다.&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: #666666;&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;&lt;b&gt;새로운 도전&lt;/b&gt;&lt;/span&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #666666;&quot;&gt;취업 준비를 한다는 압박감에 마냥 집에만 있었던 것 같다. 체력적으로도 버텨줘야 장기전에서 버틸 수 있다고 생각하여, 다시 운동도 시작했다. 또, 사람을 아예 만나지 않고 준비하는 것보다 이번에 많은 사람을 만나며 얻은 에너지를 생각하면 사람을 만나는 것도 중요하다고 판단했다. MBTI를 그렇게 믿는 편은 아니지만, 집에만 있다 보니 I로 바뀐 건 아닐까 생각했는데, 사람을 만나는 게 좋은 것을 보니 역시나 나는 확신의 E인가 보다.&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: #666666;&quot;&gt;회복하기까지 많은 시간이 걸렸지만, 그래도 보낸 시간이 의미 없었다곤 생각하지 않는다. 오히려 이런 힘들다는 감정을 겪어봤기에, 앞으로 더 나아갈 수 있는 것 아닐까 싶다. 하반기는 더욱 의미 있는 시간을 보내며, 개발자로서 성장한 모습을 보이려고 한다.&lt;/span&gt;&lt;/p&gt;</description>
      <category>Retrospect/오늘의 일기</category>
      <author>Dev Uni</author>
      <guid isPermaLink="true">https://jae-yoon.tistory.com/22</guid>
      <comments>https://jae-yoon.tistory.com/22#entry22comment</comments>
      <pubDate>Tue, 14 May 2024 04:54:35 +0900</pubDate>
    </item>
    <item>
      <title>백엔드 데브코스 4기 월간 회고 6월 - VVS</title>
      <link>https://jae-yoon.tistory.com/21</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;아직도 정신이 없지만 6월의 나는 어땠는지 돌아보며, 머리도 식힐 겸 백엔드 데브코스 회고 글을 써내려 가보려고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이삿짐을 옮기다가 허리를 삐끗해서 며칠은 누워 지냈고, 이사 이후 계약에 문제가 생겨서 사실 6월은 데브코스에 집중하지 못했던 달이었다. 그래서 회고 글 부제가 VVS (Very Very Soso) 이다. 데일리 스크럼 때 팀원들과 컨디션 체크를 필수적으로 하는데 나는 VVS가 가장 많았던 것 같다 ㅋㅋㅋ 지금은 문제가 마무리 되었지만, 후폭풍으로 밀린 강의와 과제가 날 기다렸다.&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;나는 정말 열심히 공부해 왔는가?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;데브코스를 진행하면서, 많은 감정의 혼재를 겪고 있다. 예전에 봤던 1등 하는 학생의 인터뷰에서 &quot;&lt;u&gt;독서실에서 제가 제일 공부 잘하는데, 가장 늦게 집에 가요&lt;/u&gt;&quot;라는 구절을 본 적 있다. 이 속에서도 실력이 비슷한 사람만 있는 것이 아니라, 마치 벽이 보이는 것처럼 압도적인 사람이 몇몇 있는데, 그 사람들은 게더타운에 늦은 시각까지 접속하면서 엄청난 공부 시간을 보여준다.&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;첫 번째, 계산기 과제&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 감정을 가진 채, 계산기 과제를 시작했었다. 부담감이 있는 상태이다 보니 코드 한 줄을 짜내려 가기 어려웠고, 며칠간 설계에만 몰두했다. 조금이라도 마음에 들지 않으면 변경하고, 갈아엎고, 생각만 했다. 그러다 보니, 보이는 결과물이 없어서 짜증도 밀려왔었다. 팀원들이나 멘토님들이 생각하는 습관은 좋으나, 그래도 일단 코드를 짜는 것이 중요하다고 말해주셨었는데, 알면서도 참 작성하기가 어려웠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;코드를 작성할 때 이렇게 많이 고민해 본 경험이 전무했고, 낯설었지만, 동시에 재밌기도 했다. 추상화, 트레이드오프 등 많은 요인을 고려하며 객체지향적 설계란 무엇인가를 최대한 적용해보려고 했었다. 그 결과 아래와 같은 코드가 나왔다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/prgrms-be-devcourse/java-calculator/pull/192&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/prgrms-be-devcourse/java-calculator/pull/192&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1688650731178&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;[4기 - 신재윤] 1~2주차 과제: 계산기 구현 미션 제출합니다. by Shin-Jae-Yoon &amp;middot; Pull Request #192 &amp;middot; prgrms-be&quot; data-og-description=&quot;  과제 설명 콘솔로 구현 OOP 계산기 구현 더하기 빼기 곱하기 나누기 우선순위 (사칙연산) 테스트 코드 구현 계산 이력을 맵으로 데이터 저장 기능 애플리케이션이 동작하는 동안 DB 외에 데이&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/prgrms-be-devcourse/java-calculator/pull/192&quot; data-og-url=&quot;https://github.com/prgrms-be-devcourse/java-calculator/pull/192&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/T0kwG/hyTfBERUmr/EnAnZA3ba7KLm2bAb2KkPk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/prgrms-be-devcourse/java-calculator/pull/192&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/prgrms-be-devcourse/java-calculator/pull/192&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/T0kwG/hyTfBERUmr/EnAnZA3ba7KLm2bAb2KkPk/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&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;[4기 - 신재윤] 1~2주차 과제: 계산기 구현 미션 제출합니다. by Shin-Jae-Yoon &amp;middot; Pull Request #192 &amp;middot; prgrms-be&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;  과제 설명 콘솔로 구현 OOP 계산기 구현 더하기 빼기 곱하기 나누기 우선순위 (사칙연산) 테스트 코드 구현 계산 이력을 맵으로 데이터 저장 기능 애플리케이션이 동작하는 동안 DB 외에 데이&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; 걱정과 우려와는 달리, 멘토님들께 꽤나 좋은 평가를 받았다. (순한 맛으로 말씀해주신 건가!?) 사실 굉장히 얼떨떨했다. 최대한 고민하면서 작성했다고는 하지만 맞는 방식인지 틀린 방식인지를 몰랐는데, 이런 피드백을 받고 나니 그래도 고민한 나날이 헛되지는 않았구나라고 생각했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;두 번째,&amp;nbsp; 1차 바우처 과제&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만, 계산기 과제를 끝내고 나니 밀려오는 건 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;본격적으로 Spring을 사용하게 되어서, 레이어를 나눠서 설계하도록 노력했고, 계산기 과제보다는 설계를 조금 더 러프하게 가져가고 코드를 작성하도록 노력했다. 레이어를 나누고 DTO를 사용하는 것이 어색했는데, 작성하다가 한 번 감을 잡으니 막힘 없이 코드는 작성되었다. 글로벌로 aop를 활용한 로깅과 익셉션 처리 부분, DTO 변환에 대한 책임을 어느 계층에서 가져야 할까를 특히 많이 생각했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://github.com/prgrms-be-devcourse/springboot-basic/pull/734&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;https://github.com/prgrms-be-devcourse/springboot-basic/pull/734&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1688651176556&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;object&quot; data-og-title=&quot;[4기 - 신재윤] SpringBoot Part1 Weekly Mission PR 제출합니다. by Shin-Jae-Yoon &amp;middot; Pull Request #734 &amp;middot; prgrms-be-devcou&quot; data-og-description=&quot;  과제 설명 Spring Boot CLI 이용 Gradle 프로젝트 구성 바우처 관리 Command-line Application 제작 스프링부트 애플리케이션으로 생성 (Web 없이) 프로그램이 시작하면 아래와 같이 지원가능한 명령어 알&quot; data-og-host=&quot;github.com&quot; data-og-source-url=&quot;https://github.com/prgrms-be-devcourse/springboot-basic/pull/734&quot; data-og-url=&quot;https://github.com/prgrms-be-devcourse/springboot-basic/pull/734&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/b2ETfl/hyTfueGE5M/vBRm2BP4bZGUbqi45I1tuK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600&quot;&gt;&lt;a href=&quot;https://github.com/prgrms-be-devcourse/springboot-basic/pull/734&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://github.com/prgrms-be-devcourse/springboot-basic/pull/734&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/b2ETfl/hyTfueGE5M/vBRm2BP4bZGUbqi45I1tuK/img.png?width=1200&amp;amp;height=600&amp;amp;face=0_0_1200_600');&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;[4기 - 신재윤] SpringBoot Part1 Weekly Mission PR 제출합니다. by Shin-Jae-Yoon &amp;middot; Pull Request #734 &amp;middot; prgrms-be-devcou&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;  과제 설명 Spring Boot CLI 이용 Gradle 프로젝트 구성 바우처 관리 Command-line Application 제작 스프링부트 애플리케이션으로 생성 (Web 없이) 프로그램이 시작하면 아래와 같이 지원가능한 명령어 알&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;github.com&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번에도 올바른지에 대한 확신은 없지만, 멘토님이 전반적으로 깔끔하게 잘 작성해 주신 것 같다고 해주셔서 기분이 &quot;매우&quot; 좋았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;세 번째, 2차 바우처 과제 (진행 중)&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2차 바우처는 간단히 repository만 갈아 끼우면 된다고 생각했지만, 설계에서 난항인 상태이다. JPA가 아닌 JDBC를 이용하기에, 익숙하던 애노테이션을 사용하지 않고 어떻게 코드를 짜야할까도 걱정이고, Customer 도메인과 Voucher 도메인이 있는 상황에서 바우처에 고객을 할당해야 하는 상황인데, 두 도메인의 상위 애그리거트를 정의할 수 있을까? 둘 다 애그리거트 루트라서 고객 id에 대한 처리를 어느 쪽에서 가진다고 해도 어색한 감이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;s&gt;일단, 과제 제출이 얼마 안 남았기에 Customer - Wallet - Voucher 구조로 생각하여 분리할까 한다. 사실 고객과 바우처의 관계가 다대다가 아닌 일대다라고 생각하기 때문에, 일대다의 중간에 매핑 테이블을 또 두는 것이 좀 어색한 것 같기도 하고.. 일단 작성하고 코드리뷰받으며 리팩토링 하려고 한다.&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;아니 !!? 고객마다 사용하는 고유한 바우처라고 생각한다면 일대다의 관계가 맞기에 wallet을 두는 큰 의미가 없는 것 같다. 마치 게시판 - 댓글의 관계를 생각하고 바우처의 필드로 고객을 받는다면 해결될 것 같아서, 이렇게 결정 !&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;그래도 지구는 돈다&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;상황이 힘들건 기분이 안 좋건 어떻든 간에 공부는 지속되었다. 어떻게든 꾸역꾸역 밀어내니까 진행되었다. 진행하면서 느낀 것은, 데브코스 과정에 대한 고마움이 컸다. 이 과정을 통해, 내가 느끼지 못했을 감정들을 느끼게 해 줬고, 불과 한 달 전의 나와 지금의 나를 비교했을 때는 이미 사고하는 방식 자체가 바뀌었을 정도이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공부를 방해하던 상황적인 요소가 모두 해결되었고 과정 자체에만 집중이 가능한 상황이 만들어졌다. 치열하게 사는 데브코스의 사람들을 보며 느꼈던 무력감이 이제는 의욕으로 바뀌어가고 있다. 부족함을 깨달았으면 부족함을 채우기 위해 내가 더 치열하게 살면 된다.&lt;/p&gt;
&lt;p 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;2992&quot; data-origin-height=&quot;2992&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cNNCF9/btsmGWh02cc/d0mDtOeRwr54ehPv9aBUP0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cNNCF9/btsmGWh02cc/d0mDtOeRwr54ehPv9aBUP0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cNNCF9/btsmGWh02cc/d0mDtOeRwr54ehPv9aBUP0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcNNCF9%2FbtsmGWh02cc%2Fd0mDtOeRwr54ehPv9aBUP0%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;2992&quot; height=&quot;2992&quot; data-origin-width=&quot;2992&quot; data-origin-height=&quot;2992&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스펜서 님이 슬랙에 올려주신 OKR (Object Key Results) 게시글을 보며, 80%의 달성률을 기록하도록 본격적으로 목표 설정을 해보려고 한다. 한 달 이면, 과정에 적응도 끝났고 이제 변명할 거리도 남아있지 않다. 이 카드가 내가 원하는 기업의 사원증으로 바뀌도록 인생에서 후회 없는 6개월이 되도록 노력하려고 한다. 이상 생각이 많았던 6월이었다.&lt;/p&gt;</description>
      <category>Retrospect/데브코스</category>
      <category>코딩부트캠프</category>
      <category>프로그래머스 데브코스</category>
      <author>Dev Uni</author>
      <guid isPermaLink="true">https://jae-yoon.tistory.com/21</guid>
      <comments>https://jae-yoon.tistory.com/21#entry21comment</comments>
      <pubDate>Thu, 6 Jul 2023 23:04:56 +0900</pubDate>
    </item>
    <item>
      <title>객체지향 의식의 흐름 기법</title>
      <link>https://jae-yoon.tistory.com/20</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;데브코스 과정 중 본격적으로 과제가 나오며 바쁜 일상이 시작되겠다는 것이 느껴졌다. 아직 부산에 방이 빠지지 않고 서울에 방을 구하지 못한 상황이고, 개인사로 인하여 심리적으로 안정되지 못한 상태이기 때문에, 공부에 풀 집중이 안되는 것이 아쉽다. 하지만, 현재 상황에 맞춰서 최대한 집중해보려고 한다 :)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실, 벨로그에 TIL로 간단하게 작성하다가 내용이 길어져서 벨로그에만 올리기 아까워서 여기에도 올리게 되었다. &lt;b&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;객체지향 프로그래밍&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;평소, JAVA를 사용해왔기에 나는 객체지향 프로그래밍을 한다고 생각했지만, 오늘 강의를 통해 스스로 의문을 가지게 되었다. 나는 과연 객체지향적인 특성을 잘 활용하며 코드를 짜고 있을까? 결국 &lt;b&gt;객체지향 프로그래밍을 한다는 것은 좋은 객체를 잘 만들고 있는가&lt;/b&gt;를 의미한다고 생각했다. &lt;b&gt;프로그램이 거대화&lt;/b&gt;하면서 등장하게 된 객체지향 프로그래밍이라는 패러다임에 따른다면, 좋은 객체와 나쁜 객체는 아래와 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;b&gt;좋은 객체 : 역할과 책임에 충실하면서 다른 객체와 잘 협력하여 동작하는 객체&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;POJO와 PSA&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 객체를 생각하며, 자연스럽게 POJO(Plain Old Java Object)가 떠올랐다. POJO에 관한 자세한 내용은 &lt;b&gt;&lt;a title=&quot;https://shin-jae-yoon.github.io/brain/Interview/dog-study/dog-week06/#pojo&quot; href=&quot;https://shin-jae-yoon.github.io/brain/Interview/dog-study/dog-week06/#pojo&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Dev&amp;nbsp;Uni&amp;nbsp;기록용&amp;nbsp;블로그&amp;nbsp;-&amp;nbsp;POJO&amp;nbsp;설명&lt;/a&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;POJO(Plain Old Java Object)는 직역하자면 오래된 방식의 간단한 자바 객체라는 의미이다. 이는 특정 기술에 종속되지 않는 순수한 자바 객체를 의미한다. 객체 지향적인 원리에 충실하면서 환경과 기술에 종속되지 않고 필요에 따라 재활용될 수 있는 방식으로 설계된 오브젝트를 POJO라 말하고 POJO에 애플리케이션의 핵심로직과 기능을 담아 설계하고 개발하는 방법을 POJO 프로그래밍이라고 할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예를 들어, ORM(Object Relationship Mapping) 기술을 사용하려면 ORM을 지원하는 프레임워크를 사용해야한다. 만약에 Java 객체가 ORM 기술을 사용하기 위해 Hibernate 프레임워크를 직접 의존하는 순간 POJO라고 할 수 없다. &amp;ldquo;특정 기술에 종속되었기 때문&quot;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그런데 Java 객체가 ORM 기술을 사용하기 위해 Hibernate 프레임워크를 직접 의존하는 순간 POJO가 아니라고 했으면서, Spring은 어떻게 POJO를 유지하면서 Hibernate를 사용할까? 이는 Spring에서 정한 표준 인터페이스가 있기 때문이다. ORM을 사용하기 위해 JPA(Java Persistence API)라는 표준 인터페이스를 정의해뒀고, ORM 프레임워크들은 JPA의 구현체가 되어 실행된다. 이것이 &lt;b&gt;새로운 엔터프라이즈 기술을 도입하면서도 POJO를 유지하는 방법이고 이런 방법을 PSA&lt;/b&gt;라고 한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;PSA(Portable Service Abstraction)란 환경과 세부 기술의 변화에 관계없이 일관된 방식으로 기술에 접근할 수 있게 해주는 것&lt;/b&gt;을 의미한다. PSA가 적용된 대표적인 예시는 JDBC, JPA, Transaction Manager가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다시 POJO로 돌아와서, 그렇다면 특정 기술규약과 환경에 종속되지 않으면 모두 POJO라고 말할 수 있을까? 그렇지 않다. &lt;b&gt;진정한 POJO는 위에서 말한것처럼 객체 지향적인 원리에 충실하면서 환경과 기술에 종속되지 않고 필요에 따라 재활용될 수 있는 방식으로 설계된 오브젝트를 의미&lt;/b&gt;한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;정리하자면, 객체지향적인 원리에 충실하는 좋은 객체이면서 환경과 기술에 종속되지 않고 필요에 따라 재활용 될 수 있는 방식으로 설계된 오브젝트가 POJO이구나 !&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;아키텍처 이야기&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;거대한 프로그램에서 객체가 역할과 책임에 충실하도록 기능을 나눠서 좋은 객체로 만드는 것을 살펴보았다. 그렇다면 이것을 &lt;b&gt;아키텍처 자체의 관점에서 살펴보자. &lt;/b&gt;내가 지금까지 코드를 짜면서 해왔던 모든 방식은 &lt;b&gt;모놀리식 아키텍처&lt;/b&gt;이다. 모놀리식 아키텍처는 전통의 아키텍처를 지칭하며, 소프트웨어의 모든 구성요소가 한 프로젝트에 통합되어 있는 형태이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최선을 다하여 좋은 객체를 만들고 잘게 쪼갰음에도 애플리케이션에 대한 수요가 급증하면서 매우 거대한 프로그램이 되었고, 코드가 너무 복잡하여 유지보수 하기에 어려운 지경에 이르렀다고 하자. 어떻게 관리할 수 있을까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1. MSA (Micro Service Architecture)&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아마 먼저 떠올린 생각이 아닐까싶다. 모놀리식 아키텍처에서 MSA 아키텍처로 변경하는 것을 생각할 수 있다. 그러나, MSA 아키텍처에 관하여 자세히는 모르지만, 현직에 계신 분들의 의견을 들었을 때 생각보다 MSA에 부정적이신 분들이 많았고 MSA로 쪼개는 것은 그렇게 어울리는 방법이 아닐 수도 있다. 대표적인 단점은 아래와 같다.&lt;/p&gt;
&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;- 서비스마다 DB가 분리되어 데이터의 조회가 어려움 (당연히 DB 샤딩의 난이도도 급증할 것) + 데이터의 중복 발생&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 테스트가 불편&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 서비스 간 호출 시 REST API 사용으로 인한 통신비용, Latency(지연시간) 증가&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;이 중 가장 큰 단점은 개인적인 생각으로 비용적인 측면에 있지 않나라고 생각한다. DAU가 높지 않은 상황에 무리하게 모놀리식에서 MSA로 전환한다면 비용적인 폭탄을 맞지 않을까... 현업에 발을 디뎌본 적도 없는 취준생이라 개인적인 추측이고 자세한 상황은 모르겠지만 MSA로 전환은 쉽지 않다고 생각한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;2. 모놀리식을 유지하면서 멀티모듈&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최초에 애플리케이션을 개발할 때 멀티모듈로 개발한다면, 추후 서비스가 커졌을 때 확장성도 좋고 &lt;b&gt;응집도는 커지되, 결합도는 낮아진다&lt;/b&gt;라는 이야기를 들었다. 아직, 멀티 모듈에 관하여 지식이 부족한 상태라 장단점을 확실하게 언급할 수는 없지만, 내가 채택을 해야하는 상황이라면 MSA 보다는 이 방식을 채택할 것 같다. 멀티모듈에 관한 자세한 이야기는 &lt;b&gt;&lt;a title=&quot;https://techblog.woowahan.com/2637/&quot; href=&quot;https://techblog.woowahan.com/2637/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;우아한 형제들 - 멀티모듈 설계 이야기&lt;/a&gt;&lt;/b&gt;를 참고하도록 하자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;객체지향의 특성&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 객체, POJO가 되기 위하여 객체지향적인 원리에 충실해보자. 그러기 위하여 객체지향의 특성을 알아보려고 한다. 사실 개발 공부를 하면서 이런식의 암기는 좋아하지 않는데, 저번에 인터넷에서 보고 바로 외워버려서 말해보려고 한다. 객체지향의 특성은 캡상추다! (캡슐화, 상속, 추상화, 다형성)으로 쉽게 외워보자 ㅋㅋ&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;1. 캡슐화&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 완성도가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 정보가 은닉되어있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 객체가 되려면 객체가 기능을 수행해야 하는 책임을 가진다고 했는데, 이러한 관점에서 완성도가 있다는 의미이다. 캡슐화를 진행하면서 &lt;b&gt;의존성을 낮추고 결합도를 낮추는 것&lt;/b&gt;이 핵심이다. 캡슐화 과정에서 접근지정자, 접근제한자를 통해 정보은닉이 자연스레 따라온다. 객체의 정보에 밖에서 접근하는 행위를 막는 것이다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&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;size18&quot;&gt;&lt;b&gt;2. 상속&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 상위 = 부모 = super = &lt;b&gt;추상 객체&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 하위 = 자식 = (this) = &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;- 오해 : 공통된 기능을 여러 객체에게 전달하고 싶을 때 상속을 많이 사용&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 진실 : &lt;b&gt;추상과 구체 관계에서 상속을 표현해야 한다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;3. 추상화&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 상속에서의 진실은 자연스럽게 추상화의 개념으로 이어진다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 상속관계는 상위로 갈수록 추상화, 하위로 갈수록 구체화 된 모습이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 추상체 : 추상화된 객체 / 구상체 : 구체적인 객체&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;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;추상체와 구상체를 만드는 기준에는 크게 3가지 정도가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 둘다 구체적인 기능을 가지고 있으며, &lt;b&gt;의미적으로만 묶은 상태&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 구현체를 가지지 않고 정의만 하여 &lt;b&gt;추상클래스 형태로 제공하는 상태&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 객체 자체가 추상적인 &lt;b&gt;인터페이스 상태&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;4. 다형성&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- type(형)을 여러 형태로 표현할 수 있다.&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;pre id=&quot;code_1685977480299&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;List&amp;lt;Integer&amp;gt; list = new ArrayList&amp;lt;Integer&amp;gt;();&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;구체 클래스인 ArrayList를 추상 클래스인 List로 표현할 수 있는 상태이면서, List에 해당하는 기능만 필터링 된 형식으로 제공한다. 즉, ArrayList에만 있는 기능은 위와 같은 코드에서 사용할 수 없다.&lt;/p&gt;
&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;1562&quot; data-origin-height=&quot;948&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bh5Kqo/btsiQHul7WU/BxElBTKECAKmOxaho2saA0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bh5Kqo/btsiQHul7WU/BxElBTKECAKmOxaho2saA0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bh5Kqo/btsiQHul7WU/BxElBTKECAKmOxaho2saA0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbh5Kqo%2FbtsiQHul7WU%2FBxElBTKECAKmOxaho2saA0%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;1562&quot; height=&quot;948&quot; data-origin-width=&quot;1562&quot; data-origin-height=&quot;948&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구상체인 카카오 로그인이나 네이버 로그인으로 표현하지 않고 추상체인 로그인 인터페이스로 표현하면서, 접근하는 사람에 따라 필터링 된 기능만 제공하는 형식이 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;객체지향 설계, SOLID&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;캡슐, 상속, 추상화, 다형성 같은 객체지향의 특성을 잘 지키는 좋은 객체가 의미하는 바는 알았다. 그렇다면 &lt;b&gt;좋은 설계를 했는지는 어떻게 알아야할까?&lt;/b&gt;&amp;nbsp;이에 대한 답은 아래 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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 객체간의 연관관계가 어떠한지&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 설계를 하기 위해 객체를 기능에 따라 어떻게 잘 나누고, 어떻게 잘 연관짓느냐에 관한 원칙이 &lt;b&gt;SOLID 원칙&lt;/b&gt;이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;S : SRP (Single responsibility principle)&lt;/b&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;&lt;span&gt; &lt;/span&gt;- &lt;b&gt;수정이 필요할 경우, 수정되는 이유는 하나 때문이어야 한다.&lt;/b&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;&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;&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;b&gt;O : OCP (Open/Closed principle)&lt;/b&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;&lt;span&gt; &lt;/span&gt;- &lt;b&gt;수정에는 닫히고, 확장에는 열어라&lt;/b&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;&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;b&gt;L : LSP (Liskov substitution principle)&lt;/b&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;&lt;span&gt; &lt;/span&gt;- &lt;b&gt;추상객체로 사용되는 부분에 구상객체가 들어가도 아무 문제 없어야 한다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;- 추상체와 구상체의 관계가 명확하다면, LSP는 잘 지켜질 것 이지만, 추상화에서 언급한 상속관계에서 공통적인 기능은 부모에 두는 경우로써 상속을 사용했다면 LSP가 깨지기 쉽다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;I : ISP (Interface segregation principle)&lt;/b&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;&lt;span&gt; &lt;/span&gt;- 로그인이라는 인터페이스가 있고 검색이라는 인터페이스로 나눠서 구성한다고 하자. 로그인 기능만 제공해주고 싶으면 로그인 인터페이스로 보낼 수 있고, 검색 기능만 제공해주고 싶으면 검색 인터페이스로 보낼 수 있는 것이니까 인터페이스를 분리하면 유리하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;D : DIP (Dependency inversion principle)&lt;/b&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;&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;/span&gt;- &lt;/span&gt;결국&lt;span&gt;, &lt;/span&gt;클래스&lt;span&gt; &lt;/span&gt;간&lt;span&gt; &lt;/span&gt;결합을&lt;span&gt; &lt;/span&gt;느슨히&lt;span&gt; &lt;/span&gt;하기&lt;span&gt; &lt;/span&gt;위함이다&lt;span&gt;.&lt;span&gt;&amp;nbsp; &lt;/span&gt;&lt;/span&gt;클래스의&lt;span&gt; &lt;/span&gt;변경에&lt;span&gt; &lt;/span&gt;따른&lt;span&gt; &lt;/span&gt;클래스들의&lt;span&gt; &lt;/span&gt;영향을&lt;span&gt; &lt;/span&gt;최소화하는&lt;span&gt; &lt;/span&gt;것이&lt;span&gt; &lt;/span&gt;목적&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;마무으리&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좋은 객체를 만들기 위하여 객체지향의 특성을 알아보았고, 그 과정에서 POJO를 떠올려서 정리했고, POJO 이야기를 꺼내니 자연스레 PSA 이야기도 정리했고, 좋은 객체를 만들기 위하여 객체지향적인 특성을 이용하여 열심히 쪼개다가 거대한 프로그램 자체를 쪼개는 이야기가 생각나서 멀티모듈과 MSA 이야기도 꺼냈다. 최종적으로는 객체지향적인 설계를 위한 SOLID를 이야기하며 글을 마무리한다.&lt;/p&gt;
&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;</description>
      <category>Retrospect/데브코스</category>
      <category>백엔드 데브코스</category>
      <category>클라우드 기반 백엔드 데브코스</category>
      <category>프로그래머스</category>
      <category>프로그래머스 데브코스</category>
      <author>Dev Uni</author>
      <guid isPermaLink="true">https://jae-yoon.tistory.com/20</guid>
      <comments>https://jae-yoon.tistory.com/20#entry20comment</comments>
      <pubDate>Tue, 6 Jun 2023 00:11:39 +0900</pubDate>
    </item>
    <item>
      <title>프로그래머스 백엔드 데브코스 4기 최종합격 후기</title>
      <link>https://jae-yoon.tistory.com/19</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;2023년 2월 졸업 이후 그토록 기다리던 프로그래머스 주최 백엔드 데브코스 과정 4기에 지원하여 최종합격하게 되었고, 그에 대한 과정을 남겨보려고 한다. 개인마다 생각이 다를 수 있지만, 나의 글이 도움되었으면 한다. 데브코스를 진행하며 작성되는 TIL은 &lt;a title=&quot;벨로그&quot; href=&quot;https://velog.io/@jae_yoon&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;벨로그&lt;/b&gt;&lt;/a&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;1444&quot; data-origin-height=&quot;622&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b0gnRV/btsiheBcbTq/Rp40MXU9ujmCSTNADr0NYK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b0gnRV/btsiheBcbTq/Rp40MXU9ujmCSTNADr0NYK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b0gnRV/btsiheBcbTq/Rp40MXU9ujmCSTNADr0NYK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb0gnRV%2FbtsiheBcbTq%2FRp40MXU9ujmCSTNADr0NYK%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;1444&quot; height=&quot;622&quot; data-origin-width=&quot;1444&quot; data-origin-height=&quot;622&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;1. 여러 부트캠프 중 프로그래머스 데브코스 과정에 지원한 이유&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;취준생이라면 알고 있을 부트캠프에는 우아한 테크코스, 소마, 싸피, 네부캠, 데브코스 등등 다양한 부트캠프가 있다. 사실 필자의 생각으로는 어느 부트캠프를 &quot;간다고&quot; 취업을 잘 할 수 있는 것이 아니라, &quot;가서 열심히 해야&quot; 취업을 잘 할 수 있다고 생각한다. 즉, 부트캠프 출신 중 성공하는 사람들은 애초에 부트캠프를 가지 않아도 성공할 사람들이다. 이 점을 반드시 말하고 싶었다. 따라서, 부트캠프 자체에 목매는 것은 옳지 않고, 기준을 세워두고 기준에 해당하면서 상황에 맞는 부트캠프가 있다면 도전해보고 아니면 독학하는 것도 괜찮다고 생각한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;내가 세운 기준은 아래와 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;bull; 독학이 아닌 부트캠프에서만 얻을 수 있는 큰 이점이 있는가? (코드리뷰와 멘토링 같은 문화)&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;bull; 수강생끼리 발표식으로 지식을 공유하는 문화가 있는가?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;bull; 기간이 너무 늘어지지 않고 컴팩트 한 과정인가?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1.1 우아한 테크코스&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;아마 취준생이라면 많은 사람이 꿈꾸는 과정일 것이다. 물론 나도 꿈꾸지 않은 것은 아니다. 하지만 작년 모집하던 때에는 학회에 논문 출품을 했어야해서 정신 없었기에 지원조차 하지 못하였고, 올해 11월 부터 1년 과정을 하려고 하니 시기적으로 맞지 않고 너무 길다고 생각하였다. 학교 후배가 우테코 5기에 선정되어서 과정 진행 중에 있는데, 상당히 만족하고 있었다. 이 글을 읽는 분들도 상황이 맞다면, 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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1.2 소프트웨어 마에스트로, 네이버 부스트캠프&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;자세히 알아보지는 않았지만, 소프트웨어 마에스트로 과정은 취업이 당장 급한 사람보다는 프로젝트 경험을 해보며 창업을 원하는 사람이 맞다고 생각하였고, 네이버 부스트캠프 과정은 node로 진행되어서, 스프링으로 커리어를 쌓아가고 싶은 나로서는 관심이 가지 않았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1.3 싸피 SSAFY&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;마침 데브코스와 모집기간도 비슷하고 월 100만원이라는 큰 메리트가 있어서 고민을 했던 과정이다. 지인 중 서울 싸피, 부울경 싸피가 있어서 여러 이야기를 물어보게 되었는데, 1학기(수업)와 2학기(프로젝트)로 나눠 1년이라는 과정이 길기도 하고, 1학기에 구성된 커리큘럼이 내가 지향하는 바와 많이 다르다고 생각하여 지원조차 하지 않았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;1.4 &lt;span style=&quot;color: #ee2323;&quot;&gt;프로그래머스 데브코스&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 데브코스 기수가 싸피와 신청 기간이 겹쳐서 오픈 카카오톡 방에서도 싸피와 데브코스를 이야기 하는 경우가 많았다. 싸피나 데브코스 출신이신 분들의 말로는 싸피는 대기업si, 금융권 기업을 희망하면 좋다고 하고 데브코스는 서비스 기업을 희망하면 좋다고 하였다. 서비스 기업을 희망하는 나로서는 데브코스가 너무나도 끌렸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;2. 백엔드 데브코스 1차 합격을 위한 과정&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;백엔드 데브코스는 서류 제출 -&amp;gt; 코딩테스트 -&amp;gt; 면접의 순서로 진행된다. 과거 후기들을 봤을 때, 프로그래머스 기준 2~3레벨 문제가 3문제 정도 나온다고 했었는데, 나는 코딩테스트에 정말 약한 상태여서 코딩테스트 문제를 푸는 것에 집중했다. 4기 과정에서는 이전 기수들과 다르게 &lt;b&gt;JAVA 코딩테스트 2문제 + SQL 코딩테스트 2문제 + 객관식 36문제 (HTTP, 기본 웹, &amp;nbsp;JAVA 객관식, DB 기본개념 등)&lt;/b&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;JAVA 코테 1문제는 굉장히 쉬웠고 (거의 0렙 수준) 다른 1문제는 체감상 나에게는 너무 어려웠다. (2.5렙?) 나는 코딩테스트를 정말 못하는 사람이라서 난이도가 이정도인지는 확신할 수 없다. SQL 코딩테스트는 정말 쉬웠고 객관식도 전반적으로 정말정말 쉬웠다. 내가 예상하기로는 JAVA 코테 1문제와 객관식 3문제정도 틀린것으로 예상한다. JAVA 코테 1문제는 손도 못대었고, 객관식 1문제는 실수한게 시험 끝나자마자 생각났고, 나머지 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;면접에 가기 위해서는 서류 점수 + 코딩테스트 점수로 정해지기 때문에 코딩테스트가 만점이더라도 서류를 대충 쓴다거나 이상하게 쓴다면 면접까지 갈 수 없다. 반대로 코딩테스트 점수가 조금 낮더라도 서류가 좋다면 면접까지 갈 수 있다. 데브코스는 기업이 아닌 교육 기관이기 때문에&amp;nbsp;&lt;b&gt;내가 백엔드 개발자가 되기 위하여 걸어온 과정, 데브코스에서 학습하고자 하는 열정&lt;/b&gt;을 서류에 잘 녹여내야 한다. 즉, 데브코스를 겨냥하고 단기간 공부하여 붙을 수 없다는 의미이다. 노션을 통해 이번 기수 분들의 블로그를 보면 전반적으로 이미 백엔드 지식이 상당한 분들이 많았다. 그렇다고 부족한 상태라고 붙을 수 없는 것은 아니고 &lt;s&gt;(왜냐하면 내가 붙었기 때문이다.)&lt;/s&gt;&amp;nbsp;노력한 흔적이 보인다면 붙을 수 있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;꾸준하게 공부해오며 그를 자소서에 잘 녹여내고 코딩테스트를 다 맞추지 못하더라도 적정선만 넘긴다면 1차 합격은 무난할 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1674&quot; data-origin-height=&quot;642&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dQm9SR/btsimEEOmg6/9OX6GRp7Ib2WkOVZQ1H3yK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dQm9SR/btsimEEOmg6/9OX6GRp7Ib2WkOVZQ1H3yK/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dQm9SR/btsimEEOmg6/9OX6GRp7Ib2WkOVZQ1H3yK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdQm9SR%2FbtsimEEOmg6%2F9OX6GRp7Ib2WkOVZQ1H3yK%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;1674&quot; height=&quot;642&quot; data-origin-width=&quot;1674&quot; data-origin-height=&quot;642&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;hr contenteditable=&quot;false&quot; data-ke-type=&quot;horizontalRule&quot; data-ke-style=&quot;style6&quot; /&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; 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;면접은 면접관 2 + 지원자 4의 구조였다. 한 면접관님이 모든 면접을 주도하시고 다른 한 분은 카메라를 끄고 관리 감독하시는 역할 같았다. 면접 일정을 봤을 때 면접은 대략 2~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;하지만, &lt;b&gt;여러분은 이렇게 준비하지 말라고 이렇게 글을 작성한다.&lt;/b&gt; 데브코스는 교육을 위한 캠프이기 때문에 잘하는 사람을 뽑는 것이 아니다. 면접관님께서도 기술 질문은 최대한 &quot;지양&quot;한다고 하셨고 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;공통 질문도 인터넷 후기에서 찾아본 내용은 하나도 나오지 않았다. 예상 면접 질문 리스트를 50개 정도는 뽑은 것 같은데 2개? 정도 나온 것 같다. 심지어 대답도 준비한 내용으로 하지 못했고 프리스타일로 편하게 했다. &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;b&gt;개인적으로 생각하는 면접의 핵심은 아래와 같다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&amp;bull;&lt;span&gt; 면접을 준비한다는 생각으로 하지말고 개발자로써 어떤 미래를 그리고 있는지 생각해보자.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&amp;bull;&lt;span&gt; 본인이 가지고 있는 가치관에 대해서 생각해보자.&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&amp;bull; 내가 어떤 인생을 살아왔는지 돌이켜보자.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&amp;bull;&lt;span&gt; 자신이 작성한 자소서를 기반으로 면접을 대비하자.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;bull; 깃허브 레포지토리, 블로그 글 등등 제출한 링크를 엄청 꼼꼼하게 다 살펴보신다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;사실, 면접이 끝나고 나서 든 생각은 후련함 + 찝찝함이었다. 뭔가 나를 보여줄 수 있는 면접 질문이 있었나? 하는 생각과 기술 질문도 너무 쉬웠기에 이정도는 모두가 다 잘 대답했지 않았을까 하는 생각도 들어서 최종합격을 확신할 수 없다는 찝찝함이 있었다. &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;하지만 동시에 컴공으로 전과해서 1학기마다 최소 21학점 씩을 들으며 늦게 전과했음에도 4학년에 졸업했고 그 많은 수업을 들으며 졸업 프로젝트, 학회 논문 출품, 졸업 이후부터는 데브코스 준비 등 너무 바쁘게 살아왔어서 잠시 찾아온 꿀 같은 휴식이라 너무 후련했다. 데브코스 과정에서 떨어지더라도 후회가 남지 않을 정도로 준비했고 면접도 후회가 남지 않을 정도로 더듬지 않고 편하게 답변했기에 속이 시원했다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;1668&quot; data-origin-height=&quot;642&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cZGE6N/btsikUH90QV/R2YAq8K1zWObOmPBluG8M0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cZGE6N/btsikUH90QV/R2YAq8K1zWObOmPBluG8M0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cZGE6N/btsikUH90QV/R2YAq8K1zWObOmPBluG8M0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcZGE6N%2FbtsikUH90QV%2FR2YAq8K1zWObOmPBluG8M0%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;1668&quot; height=&quot;642&quot; data-origin-width=&quot;1668&quot; data-origin-height=&quot;642&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;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;결과적으로 최종 선발이 되었고, 6월 1일 어제 OT를 진행했고 6월 2일인 오늘부터 본격적인 수업이 시작된다. 정말 합격하고 싶었던 과정에 합격하여 너무 좋았고 OT를 진행하면서 커리큘럼과 여러 시스템을 본 지금은 더더욱 데브코스에 지원하기 잘했다는 생각이 든다. 무엇보다 면접을 봐주셨고 교육 매니저를 담당해주시는 스펜서 매니저님이 지원자들이 면접에서 보였던 특징을 하나하나 기억하고 슬랙에 답변 달아주시는 것을 보고 정말 대단하다고 생각했다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;많이 부족한 상태여서 앞으로 마주하게 될 개인 과제를 보면서 숨이 막히고 걱정되지만, 최선을 다하여 과정을 수료하고 나아가 좋은 기업에 취직하려고 한다. 이후 백엔드 데브코스 과정에 지원하는 사람들에게 이 글이 도움되었으면 좋겠고, 나아가 지원을 고려하는 사람들이 있다면 무조건 지원해보라고 권유하고 싶다.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;</description>
      <category>Retrospect/데브코스</category>
      <category>백엔드 데브코스</category>
      <category>클라우드 기반 백엔드 데브코스</category>
      <category>프로그래머스</category>
      <category>프로그래머스 데브코스</category>
      <author>Dev Uni</author>
      <guid isPermaLink="true">https://jae-yoon.tistory.com/19</guid>
      <comments>https://jae-yoon.tistory.com/19#entry19comment</comments>
      <pubDate>Fri, 2 Jun 2023 00:56:45 +0900</pubDate>
    </item>
    <item>
      <title>[Java의 실행원리 4편] Runtime 환경 - JVM Execute Engine</title>
      <link>https://jae-yoon.tistory.com/18</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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;a href=&quot;https://jae-yoon.tistory.com/14&quot;&gt;&lt;span&gt;&lt;b&gt;[Java의 실행원리 0편] 시리즈 개요&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;a href=&quot;https://jae-yoon.tistory.com/15&quot;&gt;&lt;span&gt;&lt;b&gt;[Java의 실행원리 1편] Compile-time 환경&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;a href=&quot;https://jae-yoon.tistory.com/16&quot;&gt;&lt;span&gt;&lt;b&gt;[Java의 실행원리 2편] Runtime 환경 - JVM Class Loader&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;a title=&quot;[Java의 실행원리 3편] Runtime 환경 - JVM Memory, Runtime Data Areas&quot; href=&quot;https://jae-yoon.tistory.com/17&quot;&gt;&lt;b&gt;[Java의 실행원리 3편] Runtime 환경 - JVM Memory, Runtime Data Areas&lt;/b&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;span&gt;&lt;b&gt;[Java의 실행원리 4편] Runtime 환경 - JVM Execute Engine&lt;/b&gt;&lt;/span&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;드디어 Java의 실행원리 마지막 이야기인 Execute Engine에 관련된 이야기이다. 개발자가 작성한 Java 코드가 자바 컴파일러에 의해 바이트 코드로 바뀌고 클래스로더에 의해 Runtime Data Areas에 올려지면서 사용할 준비가 완료되었다. Execute Engine은 이 바이트코드를 어떻게 실행하는지 살펴보고 Garbage Collector의 원리도 살펴보도록 하자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Execute Engine&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;2084&quot; data-origin-height=&quot;816&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/nSemk/btr45k6QZS8/ZAQgJXeAipkTEm4ke714Jk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/nSemk/btr45k6QZS8/ZAQgJXeAipkTEm4ke714Jk/img.png&quot; data-alt=&quot;그림1. Java의 실행원리 Execute Engine&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/nSemk/btr45k6QZS8/ZAQgJXeAipkTEm4ke714Jk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FnSemk%2Fbtr45k6QZS8%2FZAQgJXeAipkTEm4ke714Jk%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;2084&quot; height=&quot;816&quot; data-origin-width=&quot;2084&quot; data-origin-height=&quot;816&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림1. Java의 실행원리 Execute Engine&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;background-color: #f6e199;&quot;&gt;&lt;b&gt;Execute Engine은 클래스로더를 통해 JVM의 런타임 데이터 영역에 할당된 바이트 코드를 명령어 단위로 읽어와서 네이티브 코드(기계 코드, 바이너리 코드, 0과 1)로 바꿔서 실행한다.&lt;/b&gt;&lt;/span&gt; 실행 중인 애플리케이션의 각 스레드는 JVM Execute Engine의 개별 인스턴스이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그리고 실행 엔진은 이미 다른 언어로 작성된 라이브러리가 있어서 자바로 재작성 하고 싶지 않은 경우, 자바가 시스템 디바이스에 접근하거나 플랫폼 특정적인 작업을 원하는 경우, 자바로 구현하기에는 느리고 C/C++를 사용해서 성능 향상을 원하는 경우에 Host 운영체제에 있는 C/C++로 작성된 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;Native Method Libraries&lt;/b&gt;&lt;/span&gt;를 사용한다. 이때 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;네이티브 메서드 라이브러리를 호출할 수 있도록 도와주는 인터페이스가 바로 JNI(Java Native Interface)&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Interpreter&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;Interpreter는 바이트 코드를 명령어 단위로 한 줄씩 읽어서 네이티브 코드로&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;&amp;nbsp;해석(변환)하고 순차적으로 실행한다&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;.&lt;/b&gt;&lt;/span&gt;&amp;nbsp;컴파일러와는 다르게 한 줄 한 줄 해석하고 실행하는 과정을 거치기 때문에 번역 속도 자체는 컴파일러보다 빠르지만 프로그램 전체적인 실행 속도는 컴파일러보다 느리다. 컴파일러는 영어로 작성된 파일을 통으로 해석하고 번역본을 만드는 행위이고 인터프리터는 실시간 통역의 개념으로 이해하자. 컴파일러와 인터프리터에 관한 내용은 &lt;a title=&quot;[Computer Science]컴파일러와 인터프리터&quot; href=&quot;https://jae-yoon.tistory.com/3&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;[Computer&amp;nbsp;Science]컴파일러와&amp;nbsp;인터프리터&lt;/b&gt;&lt;/a&gt;를 참고하자.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;즉, 바이트 코드로 작성된 클래스 파일을 한 줄 한 줄 읽어서 네이티브 코드로 바꾼다는 건데 자주 실행되는 코드를 매번 Interpreter에 의해 변환한다는 것은 비효율적이다. &lt;u&gt;이러한 단점을 극복하기 나온 것이 JIT 컴파일러이다.&lt;/u&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span&gt;&lt;span&gt;JIT Compiler (Just-In-Time Compiler)&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;JIT Compiler는&lt;/b&gt;&lt;/span&gt; 바이트 코드가 인터프리터 방식으로 실행되다가 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;적절한 시점에 바이트코드 전체를 컴파일하여 네이티브 코드로 변환하고 이후에는 해당 메서드를 더이상 인터프리터 방식으로 실행하지 않고 네이티브 코드로 직접 실행하는 방식&lt;/b&gt;&lt;/span&gt;이다. 즉, 적절한 시기에 바이트 코드를 캐싱하고 최적화함으로써 자주 호출되는 메서드가 인터프리터에 의해 여러 번 변환되는 작업의 수를 줄일 수 있다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;실행 속도가 가장 빠른 것부터 C언어, Java, Python이라는 이유가 이 때문이다. C언어는 완전한 컴파일러 언어이고 Java는 인터프리터와 JIT 컴파일러를 섞어서 쓰는 방식, Python은 인터프리터 언어이기 때문이다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;JIT 컴파일러가 바이트코드 전체를 컴파일하는 과정은 당연하게도 인터프리터가 매번 실행하는 과정보다는 오래 걸릴 것이다. 그래서 한 번만 실행되는 코드라면 컴파일하지 않고 인터프리팅 하는 것이 훨씬 유리하다. 그렇다면 인터프리팅 하다가 어느 시점부터 JIT 컴파일러로 컴파일 하는 것이 유리할까?&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;span&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;컴파일 임계치(Compile Threshold) = JVM 내에 있는 메서드가 호출된 횟수 + 메서드가 루프를 빠져나오기 전까지 돌아간 횟수&lt;/b&gt;&lt;/span&gt;를 참고한다. JVM이 호출되는 메서드 각각에 호출 횟수를 누적시키는데, 컴파일 임계치 수치를 넘어서는 시점부터 인터프리팅 방식보다 JIT 컴파일러 방식이 유리하다는 의미이다. &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;컴파일 임계치를 넘어서서 컴파일되는 것이 유리하다면, 해당하는 메서드는 컴파일되기 위해 큐에서 대기하다가 이후 컴파일 스레드에 의해 컴파일된다.&lt;/b&gt;&lt;/span&gt;&amp;nbsp;&lt;/span&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_1679328485949&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 코드 출처 https://www.slideshare.net/dougqh/jvm-mechanics-understanding-the-jits-tricks-93206227

public class Main {
    public static void main(String[] args) {
        for (int i = 0; i &amp;lt; 500; ++i) {
            long startTime = System.nanoTime();
            for (int j = 0; j &amp;lt; 1000; ++j) {
                new Object();
            }

            long endTime = System.nanoTime();
            System.out.println(&quot;반복횟수 : &quot; + i + &quot;, 실행시간 측정 : &quot; + (endTime - startTime));
        }
    }
}&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;1674&quot; data-origin-height=&quot;816&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xKnOj/btr42SXmM1x/hHkC3UWMnoyKKMLQHjBKnK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xKnOj/btr42SXmM1x/hHkC3UWMnoyKKMLQHjBKnK/img.png&quot; data-alt=&quot;그림2. 루프 메서드에 대한 나노초 단위 시간 측정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xKnOj/btr42SXmM1x/hHkC3UWMnoyKKMLQHjBKnK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxKnOj%2Fbtr42SXmM1x%2FhHkC3UWMnoyKKMLQHjBKnK%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;1674&quot; height=&quot;816&quot; data-origin-width=&quot;1674&quot; data-origin-height=&quot;816&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림2. 루프 메서드에 대한 나노초 단위 시간 측정&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;1674&quot; data-origin-height=&quot;818&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FeW4T/btr4PqO1bJC/ocKoGWtBxcZRses5e0iePk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FeW4T/btr4PqO1bJC/ocKoGWtBxcZRses5e0iePk/img.png&quot; data-alt=&quot;그림3.&amp;amp;amp;nbsp;https://www.slideshare.net/dougqh/jvm-mechanics-understanding-the-jits-tricks-93206227&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FeW4T/btr4PqO1bJC/ocKoGWtBxcZRses5e0iePk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFeW4T%2Fbtr4PqO1bJC%2FocKoGWtBxcZRses5e0iePk%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;1674&quot; height=&quot;818&quot; data-origin-width=&quot;1674&quot; data-origin-height=&quot;818&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림3.&amp;amp;nbsp;https://www.slideshare.net/dougqh/jvm-mechanics-understanding-the-jits-tricks-93206227&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;측정된 실행 시간을 보면 루프 횟수가 어느 부분에서 급격히 줄어드는 것을 확인할 수 있다. 1차적으로 한 번 줄어들었고 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&gt;&lt;span&gt;이렇게 컴파일 임계치를 넘어 JIT 컴파일러에 의해 컴파일된 코드가 생긴 이후에, &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;JVM 스택 프레임에 올라가있던 인터프리팅 된 코드를 발견한다면 이를 컴파일된 코드로 교체하여 속도를 개선하는 작업&lt;/b&gt;&lt;/span&gt;도 진행한다. 이러한 작업을 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;On-Stack Replacement(OSR)&lt;/b&gt;&lt;/span&gt;이라고 한다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1624&quot; data-origin-height=&quot;758&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cCS1Gn/btr45jfPsGo/DANrGD9agpgrRKa5oz1jC1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cCS1Gn/btr45jfPsGo/DANrGD9agpgrRKa5oz1jC1/img.png&quot; data-alt=&quot;그림4. [Java의 실행원리 1편]에서 나온 컴파일러 그림&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cCS1Gn/btr45jfPsGo/DANrGD9agpgrRKa5oz1jC1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcCS1Gn%2Fbtr45jfPsGo%2FDANrGD9agpgrRKa5oz1jC1%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;1624&quot; height=&quot;758&quot; data-origin-width=&quot;1624&quot; data-origin-height=&quot;758&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림4. [Java의 실행원리 1편]에서 나온 컴파일러 그림&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;a title=&quot;[Java의 실행원리 1편] Compile-time 환경&quot; href=&quot;https://jae-yoon.tistory.com/15&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;[Java의 실행원리 1편] Compile-time 환경&lt;/b&gt;&lt;/a&gt;에서도 언급했지만, 바이트 코드를 네이티브 코드로 변환하는 과정에 있어서, JIT Compiler는 코드 최적화에 해당하는 부분이기에 최적화에 관하여 가장 중요하게 생각한다. 하지만, 실행 엔진이 어떻게 동작해야 하는지는 JVM 명세에 규정되지 않아서, 벤더마다 구현이 다를 수 있다. JVM 벤더들은 다양한 방법으로 실행 엔진을 구성하는데, &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;오라클 Hotspot JVM 기준으로 설명하자면 핫스팟 컴파일러라는 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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2084&quot; data-origin-height=&quot;1226&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wg4yA/btr43ZvadPD/nhvK9uB9XnHjPqlYktWEqk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wg4yA/btr43ZvadPD/nhvK9uB9XnHjPqlYktWEqk/img.png&quot; data-alt=&quot;그림5. JIT Compiler의 동작 과정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wg4yA/btr43ZvadPD/nhvK9uB9XnHjPqlYktWEqk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fwg4yA%2Fbtr43ZvadPD%2FnhvK9uB9XnHjPqlYktWEqk%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;2084&quot; height=&quot;1226&quot; data-origin-width=&quot;2084&quot; data-origin-height=&quot;1226&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림5. JIT Compiler의 동작 과정&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;그림과 같이 JIT 컴파일러는 바이트코드를 중간 단계의 표현으로 변환하여 최적화를 수행하고 그를 기반으로 Code Generator에서 네이티브 코드를 생성한다. 오라클 Hotspot JVM에서 사용하는&amp;nbsp;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;Hotspot Compiler는 내부적으로 Profiler를 통한 프로파일링으로 가장 컴파일이 필요한 부분인 Hotspot을 찾아내고 이 부분을 네이티브로 컴파일하기 때문에 Hotspot 컴파일러라고 한다.&lt;/b&gt;&lt;/span&gt; 또, &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;Hotspot Compiler는 한 번 컴파일된 바이트코드라도 해당 메서드가 더 이상 자주 불리지 않는다면 ( = 핫스팟이 아니게 된다면 ) 캐시에서 네이티브 코드를 덜어내고 다시 인터프리팅 방식으로 동작한다.&lt;/b&gt;&lt;/span&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;C언어에 비해 마냥 느리기만 할거라는 Java는 이렇게 JIT 컴파일러 뿐만이 아닌 다양한 최적화 기법을 적용하며 JVM의 Execute Engine을 개선하고 속도를 향상시키고 있다.&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;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Garbage Collector&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;Garbage Collector는 메모리를 자동으로 관리하여 Heap 영역의 인스턴스 중 더이상 사용되지 않는 객체에 할당된 메모리를 자동으로 해제하는 역할을 수행한다.&lt;/b&gt;&lt;/span&gt; 이 덕분에 개발자는 개발에 조금 더 집중하게 되었고 Garbage Collector가 사용되지 않는 인스턴스에 할당된 메모리를 해제하기에 메모리 누수(Memory Leak)을 막을 수도 있게 되었다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;GC에 관련된 자세한 이야기는 &lt;a title=&quot;네이버 d2 - Garbage Collection&quot; href=&quot;https://d2.naver.com/helloworld/1329&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;네이버 d2 - Garbage Collection&lt;/b&gt;&lt;/a&gt;, &lt;b&gt;&lt;a title=&quot;네이버 d2 - Reference와 GC&quot; href=&quot;https://d2.naver.com/helloworld/329631&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;네이버 d2 - Reference와 GC&lt;/a&gt;&lt;/b&gt;, &lt;b&gt;&lt;a title=&quot;impala님의 GC 정리&quot; href=&quot;https://velog.io/@impala/JAVA-JVM-Garbage-Collection&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;impala님의 GC 정리&lt;/a&gt;&lt;/b&gt;, &lt;b&gt;&lt;a title=&quot;우테코 10분 테코톡 - 엘리의 GC&quot; href=&quot;https://www.youtube.com/watch?v=Fe3TVCEJhzo&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;우테코 10분 테코톡 - 엘리의 GC&lt;/a&gt;&lt;/b&gt; 등 잘 정리된 내용이 너무 많아서 이를 참조하며 나중에 추가적으로 정리하기로 하고 본 게시글에서는 핵심만 간단히 살펴보도록 하자.&amp;nbsp;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt; GC(Garbage Collection) 개념이 도입이 가능했던 것은 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;weak generational hypothesis(약한 세대 가설)&lt;/b&gt;&lt;/span&gt; 덕분이라고 oracle docs에서는 소개한다. 해당 가설은 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;대부분의 객체는 금방 접근 불가능한 상태(unreachable)가 된다&lt;/b&gt;&lt;/span&gt;, &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;오래된 객체에서 젊은 객체로의 참조는 아주 적게 존재한다&lt;/b&gt;&lt;/span&gt;는 두 가지 이유를 든다. 예를 들어, 한 번 쓰이고 버려지는 객체들( = 금방 접근 불가능한 상태가 된 객체 )을 주기적으로 비움으로써 메모리를 효율적으로 사용한다는 것이 있다. 또, 어떤 값이나 상태를 저장하기 위해 생성된 POJO 객체는 다른 메서드나 클래스에 전달되고 난 이후에는 더이상 사용하지 않는 경우가 대부분인데 이러한 경우도 비우면 좋을 것이다.&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;2012&quot; data-origin-height=&quot;1276&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cjYUWp/btr41h4pGYK/ZKkZnIobEbskE2mtstt7Qk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cjYUWp/btr41h4pGYK/ZKkZnIobEbskE2mtstt7Qk/img.png&quot; data-alt=&quot;그림6. Reachable과 Unreachable&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cjYUWp/btr41h4pGYK/ZKkZnIobEbskE2mtstt7Qk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcjYUWp%2Fbtr41h4pGYK%2FZKkZnIobEbskE2mtstt7Qk%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;2012&quot; height=&quot;1276&quot; data-origin-width=&quot;2012&quot; data-origin-height=&quot;1276&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림6. Reachable과 Unreachable&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;Root에 해당하는 것은 JVM Stack에 있는 지역변수, 파라미터 혹은 static 변수, JNI에 의해 생성된 객체들이 해당된다. 어떤 객체에 Root로부터 유효한 참조가 존재한다고 하면 &lt;b&gt;Reachable하다&lt;/b&gt;고 하고 Root로부터&amp;nbsp;유효한 참조가 존재하지 않는다면 &lt;b&gt;Unreachable하다&lt;/b&gt;고 한다. 이 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;Unreachable한 객체들이 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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2012&quot; data-origin-height=&quot;1104&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rasNg/btr42TaWjSa/tZ7qCXUGOG79E6Ejw5glrk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rasNg/btr42TaWjSa/tZ7qCXUGOG79E6Ejw5glrk/img.png&quot; data-alt=&quot;그림7. Heap 메모리 구조&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rasNg/btr42TaWjSa/tZ7qCXUGOG79E6Ejw5glrk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrasNg%2Fbtr42TaWjSa%2FtZ7qCXUGOG79E6Ejw5glrk%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;2012&quot; height=&quot;1104&quot; data-origin-width=&quot;2012&quot; data-origin-height=&quot;1104&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림7. 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;Heap 메모리 구조는 그림과 같은데, 두 영역에서는 Minor GC와 Major GC가 일어난다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;New/Young Generation&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Heap 영역에 객체가 생성되면 Eden 영역에 객체가 지정된다.&lt;/li&gt;
&lt;li&gt;Eden 영역에 데이터가 가득차면 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;1차 GC인 Minor GC&lt;/b&gt;&lt;/span&gt;가 발생한다. 이 과정에서 살아남은 객체는 &lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;Survivor 0, Survivor 1 둘 중 하나의 영역으로 옮겨진다. Survivor 0과 1 둘 중에 우선순위는 없고 한 곳으로만 이동하면 된다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;하나의 Survivor 영역이 가득차면 1차 GC인 Minor GC가 발생하고 살아남은 객체를 다른 Survivor 영역으로 이동한다. 그리고 기존에 가득찼던 Survivor 영역은 아무 데이터가 없이 비워둔 상태로 유지한다. 따라서 Survivor 영역 둘 중 하나는 항상 비워져있는 공간인채로 유지된다.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;Minor GC는 기본적으로 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;Mark-Sweep-Compaction이라는 알고리즘을 사용하는데, 이는 먼저 살아있는 객체를 식별(Mark)하고 힙의 앞 부분부터 확인하여 살아있는 식별된 객체만 남기고 식별되지 않은 객체를 삭제하고(Sweep) 마지막에는 살아있는 객체들을 앞쪽으로 모아주는(Compact) 알고리즘&lt;/b&gt;&lt;/span&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;Old Generation (Tenured Generation)&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Survivor 0과 1을 왔다갔다 하는 과정에서 오랫동안 살아남은 객체들은 Old 영역으로 이동한다.&lt;/li&gt;
&lt;li&gt;New/Young 영역에서 Survivor 영역을 거치지 않고 바로 Eden에서 Old로 넘어가는 객체도 존재한다. 이 경우 객체의 크기가 아주 큰 경우이다. 예를 들어, Survivor 영역의 크기가 16MB인데 객체의 크기가 20MB라면 바로 Old로 넘어간다.&lt;/li&gt;
&lt;li&gt;오랫동안 살아남는다는 것의 기준은 Minor GC에서 얼마나 살아남았는 지를 의미한다. Minor GC가 발생할 때마다 age bit 값이 1씩 증가하는데, MaxTenuringThreshold라는 임계치를 초과하는 경우 Old Generation으로 이동하는 것이다. 임계치 초과 이전이라도 Survivor 영역의 메모리가 부족하다면 Old Generation으로 이동할 수 있다.&lt;/li&gt;
&lt;li&gt;Old 영역에서 데이터가 가득차면 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;2차 GC인 Major GC(Full GC)&lt;/b&gt;&lt;/span&gt;가 발생한다. 이때 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;Stop-The-World(STW) 상태&lt;/b&gt;&lt;/span&gt;가 발생한다. STW란, GC 하기 위하여 JVM이 애플리케이션 실행을 멈추는 것이다. STW가 발생하면 GC를 실행하는 스레드를 제외한 나머지 스레드는 모두 작업을 멈추고 GC 작업이 완료된 이후에야 중단했던 작업을 실행한다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;어떠한 GC 알고리즘을 사용하더라도 Stop-The-World는 무조건 발생한다. 그렇기 때문에 적절한 GC 알고리즘 선택과 GC 튜닝을 통한 stop-the-world 시간을 최소한으로 줄이는 것이 성능 향상의 핵심이다.&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;Old 영역의 GC 알고리즘 중 대표적으로 Serial GC, Parallel GC, Parallel old GC, CMS(Concurrent Mark &amp;amp; Sweep) GC, G1(Garbage First) GC 5가지를 소개하려고 한다. 먼저 말할 내용은 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;Java 8에서 default로 사용되는 GC 알고리즘은 Parrel GC이고 Java 9부터는, 그러니까 Java 11에서 default로 사용되는 GC 알고리즘은 G1GC이다. Java8과 11의 차이에서 중요한 차이이니 기억하도록 하자.&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;h4 data-ke-size=&quot;size20&quot;&gt;&lt;b&gt;Serial GC (-XX:+UseSerialGC)&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;예전 버전의 JDK에서 사용하던 방식으로 GC를 처리하는 스레드가 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;싱글스레드&lt;/b&gt;&lt;/span&gt;이다. 이러한 이유로 다른 GC 알고리즘에 비해 stop-the-world 시간이 길다는 단점이 있다. Serial GC에서 Young 영역과 Old 영역 모두 Mark-Sweep-Compaction 알고리즘을 사용하지만 싱글 스레드로 사용한다.&lt;/p&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는 적은 메모리와 CPU 코어 개수 1개일 때 적합하지만, 이 말은 현대 시대에 우리가 사용하는 컴퓨터에서 CPU 코어 개수가 1개인 경우는 찾기 힘드니까 Serial GC를 사용하면 애플리케이션의 성능이 많이 떨어지기 때문에 절대 사용하지 말라는 의미이다.&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;Parallel GC (-XX:+UseParrelGC) - &lt;span style=&quot;color: #ee2323;&quot;&gt;Java 8의 default GC&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Serial GC에서 mark-sweep-compaction 알고리즘을 사용하는 것처럼 기본적인 동작원리는 동일하지만, Parallel GC는 GC를 처리하는 스레드가 Young 영역에서 minor GC 하는 작업이 싱글스레드가 아닌 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;멀티스레드&lt;/b&gt;&lt;/span&gt;인 경우이다. 따라서 Serial GC보다 훨씬 빠르게 객체를 처리할 수 있었고 Java 8의 default GC였다. Parallel GC는 Throughput GC라고도 한다. 멀티 스레드로 처리하기 때문에 Stop-The-World 시간이 Serial 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;1698&quot; data-origin-height=&quot;378&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uIiFR/btr41J7rTAT/eQFxx9BgGrdQcoXBqhaKG1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uIiFR/btr41J7rTAT/eQFxx9BgGrdQcoXBqhaKG1/img.png&quot; data-alt=&quot;그림8. Serial GC와 Parallel GC의 차이 (이미지 출처: &amp;quot;Java Performance&amp;quot;, p.86)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uIiFR/btr41J7rTAT/eQFxx9BgGrdQcoXBqhaKG1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FuIiFR%2Fbtr41J7rTAT%2FeQFxx9BgGrdQcoXBqhaKG1%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;1698&quot; height=&quot;378&quot; data-origin-width=&quot;1698&quot; data-origin-height=&quot;378&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림8. Serial GC와 Parallel GC의 차이 (이미지 출처: &quot;Java Performance&quot;, p.86)&lt;/figcaption&gt;
&lt;/figure&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;Parallel Old GC(-XX:+UseParallelOldGC)&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Parallel Old GC는 Parallel GC와 비교하여 Young 영역의 방식은 동일하고 Old 영역 또한 멀티 스레드이면서, Old 영역의 GC 알고리즘을 개선한 방식이다. Parallel GC는 Mark-Sweep-Compaction 알고리즘을 사용했지만 Parallel Old GC는 Mark-Summary-Compaction 알고리즘을 수행한다. &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;Sweep은 단일 스레드가 Old 영역 전체를 훑어보고&lt;/b&gt;&lt;/span&gt; 살아있는 객체만 찾아내는 방식이지만 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;Summary는 멀티 스레드가 Old 영역을 분리하여 훑는 것&lt;/b&gt;&lt;/span&gt;이다. 또한 효율을 위해 앞선 GC에서 Compaction된 영역을 별도로 훑는다.&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;CMS GC (-XX:+UseConcMarkSweepGC)&lt;/b&gt;&lt;/h4&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1710&quot; data-origin-height=&quot;734&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ZCql1/btr42yq2cgp/TXJYYX6WqrKAYHMBmucQS0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ZCql1/btr42yq2cgp/TXJYYX6WqrKAYHMBmucQS0/img.png&quot; data-alt=&quot;그림9. Serial GC와 CMS GC (이미지 출처:https://www.oracle.com/java/technologies/)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ZCql1/btr42yq2cgp/TXJYYX6WqrKAYHMBmucQS0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FZCql1%2Fbtr42yq2cgp%2FTXJYYX6WqrKAYHMBmucQS0%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;1710&quot; height=&quot;734&quot; data-origin-width=&quot;1710&quot; data-origin-height=&quot;734&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림9. Serial GC와 CMS GC (이미지 출처:https://www.oracle.com/java/technologies/)&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CMS GC는 Stop-The-World 시간을 줄이기 위해 고안된 방식이다. Compaction 과정없이, 애플리케이션 중단 없이 Mark-and-Sweep이 가능한 방식이다. Initial Mark 단계와 Remark 단계에서는 짧게나마 Stop-The-World 현상이 발생한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;Initial Mark&lt;/b&gt; 단계에서는 현재 살아남은 객체를 탐색하는데 GC Root에서 참조하는 객체들만 우선적으로 탐색하고 끝내기 때문에 Stop-The-World 발생 시간이 매우 짧다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Concurrent Mark&lt;/b&gt; 단계에서는 방금 살아있다고 확인한 객체에서 참조하고 있는 모든 객체들을 추적하면서 GC의 대상인지 판별한다. Stop-The-World가 발생하지 않으며, 이 단계의 특징은 다른 스레드가 실행 중인 상태에서 동시에 진행된다는 것이다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Remark&lt;/b&gt; 단계에서는 Concurrent Mark 단계에서 식별한 객체를 다시 추적하여 새로 추가되거나 참조가 끊긴 객체를 확인한다. 이 과정에서 Stop-The-World가 발생하지만 멀티스레드로 동작하기 때문에 매우 짧다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Concurrent Sweep&lt;/b&gt; 단계에서는 Remark 단계까지 검증이 완료된 GC 대상 객체들을 삭제한다. 이 단계도 다른 스레드가 실행 중이 상태에서 동시에 진행한다.&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;이러한 이유로 CMS GC는 stop-the-world 시간이 매우 짧아서 모든 애플리케이션의 응답 속도가 중요한 경우 사용하면 좋은 GC 알고리즘이며 Low Latency GC라고도 부른다. 하지만, 시간이 짧다는 장점에 반해 &lt;b&gt;다른 GC 방식보다 메모리와 CPU를 더 많이 사용한다는 것&lt;/b&gt;과 &lt;b&gt;Compaction 단계가 기본적으로 제공되지 않아서 메모리 단편화 문제가 아쉽다는 단점이 존재&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;따라서, CMS GC를 사용할 때는 신중히 검토해서 사용해야 한다. 만약 조각난 메모리가 많아서 연속적인 메모리 할당이 어려울 정도로 메모리 단편화가 심한 경우에 Compaction 작업을 실행한다면 다른 GC 방식의 stop-the-world 시간보다 더 긴 stop-the-world가 발생하기 때문이다. Compaction 작업이 얼마나 자주, 오랫동안 수행되는지 반드시 확인하고 사용하도록 하자.&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;G1 GC (-XX:+UseG1GC) -&lt;span style=&quot;color: #ee2323;&quot;&gt; Java 9 이후의 default GC&lt;/span&gt;&lt;/b&gt;&lt;/h4&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;G1GC는 하드웨어가 발전되면서 Java 애플리케이션이 사용할 수 있는 메모리의 크기가 점점 커져왔는데 이 큰 메모리에서 좋은 성능을 내는 것에 초점을 둔 GC 알고리즘이다. 메모리 단편화 문제를 해결하면서 CMS GC를 대체하기 위해 만들어졌다. G1GC를 이해하기 위해서는 지금까지 heap 영역을 New/Young Generation과 Old Generation으로 나누던 것을 잊는 것이 좋다.&lt;/p&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 영역을 고정된 크기로 물리적으로 New/Young 영역, Old 영역으로 나누는 것이 아닌 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;전체 heap을 체스판처럼 Region이라는 일정한 크기의 논리적인 단위로 나누고 Region에 특정한 역할을 부여한다.&lt;/b&gt;&lt;/span&gt; Heap은 동일한 크기의 영역으로 나뉘어 집합으로 분할되어 연속된 가상 메모리로 존재하게 된다. G1GC의 목표 또한 STW의 최소화이다. 이 말은 G1GC도 STW를 완전히 없애지는 못했다는 의미이다.&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;2622&quot; data-origin-height=&quot;1332&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/miaqy/btr4LGYCQSR/KLxZDsKloSXTkOnAk39cm1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/miaqy/btr4LGYCQSR/KLxZDsKloSXTkOnAk39cm1/img.png&quot; data-alt=&quot;그림10. G1GC Heap Layout&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/miaqy/btr4LGYCQSR/KLxZDsKloSXTkOnAk39cm1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fmiaqy%2Fbtr4LGYCQSR%2FKLxZDsKloSXTkOnAk39cm1%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;2622&quot; height=&quot;1332&quot; data-origin-width=&quot;2622&quot; data-origin-height=&quot;1332&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림10. G1GC Heap Layout&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;G1GC 알고리즘은 이전 방식들과 동일하게 최초 객체가 생성이 되면 Eden에 할당하고 이후 Survivor 로 이동과 소멸 Old Region으로의 이동은 동일하다. 최초 객체 생성은 비어있는 영역에만 들어간다는 것이고 비어있는 영역이 Eden Region으로 될 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Humongous Region이라는 영역이 생겼는데 이는 한 영역보다 크기가 커서 여러 영역을 차지하는 커다란 객체이다. 한 영역의 절반 이상의 크기를 가진 객체를 의미하는데, 연속된 영역을 순차적으로 차지하도록 할당된다. 마지막 꼬리 영역에 남는 공간이 생길 수 있는데 그 잉여공간은 아깝지만 사용하지 않는다. 이 말은 Humongous Object가 회수되기 전까지 잉여공간을 사용할 수 없다는 의미이다.&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;2156&quot; data-origin-height=&quot;954&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wf5na/btr4LHJW18e/leQz2p64pAFHD2FkQbbgYk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wf5na/btr4LHJW18e/leQz2p64pAFHD2FkQbbgYk/img.png&quot; data-alt=&quot;그림11. G1GC의 Garbage Collection Cycle (그림출처 : Oracle docs)&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wf5na/btr4LHJW18e/leQz2p64pAFHD2FkQbbgYk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fwf5na%2Fbtr4LHJW18e%2FleQz2p64pAFHD2FkQbbgYk%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;2156&quot; height=&quot;954&quot; data-origin-width=&quot;2156&quot; data-origin-height=&quot;954&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림11. G1GC의 Garbage Collection Cycle (그림출처 : Oracle docs)&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;a title=&quot;Oracle docs&quot; href=&quot;https://docs.oracle.com/javase/9/gctuning/garbage-first-garbage-collector.htm#JSGCT-GUID-1CDEB6B6-9463-4998-815D-05E095BFBD0F&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;Oracle docs&lt;/b&gt;&lt;/a&gt;에서는 G1GC는 2개의 페이즈 Young-only phase, Space Reclamation phase를 번갈아가면서 GC 작업을 한다고 소개한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Young-only phase (Young-only 단계)&lt;/b&gt; : Old 영역의 점유율이 threshold 값을 넘어서면 Young-only phase로 전환된다. 이 단계에서는 Young Generation의 GC로 시작된다.&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Initial mark : Young GC를 수행하면서  Concurrent Marking 작업이 시작된다. Young GC 시점에 수행하니까 당연히 Stop-The-World가 발생한다.&lt;/li&gt;
&lt;li&gt;Concurrent Marking : Old Region을 GC하기 위해 현재 도달할 수 있는 live 객체(Object)를 결정한다. Concurrent Mark가 진행되는 도중에 Young GC가 동작할 수 있으며 이로 인해 방해받을 수 있다. Marking 작업은 Remark와 Cleanup 단계에서 Stop-The-World를 발생시킬 수 있다.&lt;/li&gt;
&lt;li&gt;Remark : Marking 작업 자체를 마무리하고 Reference 처리 및 클래스 언로딩을 수행하여 Empty Region을 회수하고 내부 데이터 구조를 정리한다. &lt;span style=&quot;color: #333333; text-align: left;&quot;&gt;즉, 마킹을 끝내고 쓰레기 영역을 해제한다는 의미이다.&lt;span&gt;&amp;nbsp;이때,&amp;nbsp;&lt;/span&gt;&lt;/span&gt;짧은 Stop-The-World 현상이 발생할 수 있다. Remark 단계와 Cleanup 단계 사이에서 G1은 Old Region에서 여유 공간을 회수 할 수 있도록 정보를 계산하고 이&lt;span&gt; &lt;/span&gt;계산은&lt;span&gt; Cleanup &lt;/span&gt;단계에서의&lt;span&gt; Stop-The-World&lt;/span&gt;에서&lt;span&gt; &lt;/span&gt;마무리 된다.&amp;nbsp;&lt;/li&gt;
&lt;li&gt;Cleanup : 이 단계는 Region 회수가 실제로 진행될 지 결정하는데, 만약 공간 재확보 단계가 온다면, Young-only 단계는 1회의 Mixed-GC만 진행하고 완료된다.&lt;/li&gt;
&lt;/ol&gt;
&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;Space Reclamation phase (공간 재확보 단계)&lt;/b&gt; : Young / Old 영역을 가리지 않고 live 객체를 적절한 곳으로 대피시킨다. 이 단계는 G1이 더이상 Old Region을 효율적으로 줄일 수 없다고 판단되는 시점에 이 페이즈는 끝나고, 다시 Young-only phase로 넘어가게 된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;G1GC는 위 두 개의 페이즈가 반복되는 방식으로 진행하다가 애플리케이션이 메모리가 부족하게 되어 OOM(Out Of Memory)로 가게 된다면 다른 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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;자바의 실행 원리 마무리, 소감&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;비로소 자바 실행원리에 대한 시리즈가 끝났다. 사실 이렇게까지 할 필요는 없었지만, 지적 호기심을 채우기위해 열심히 찾아보았다. 공부하면서 느낌 소감은 JVM 명세에 따라 구현된 JVM의 세부적인 작동원리나 내부가 어떻게 되어있는지는 벤더마다 차이가 있고 런타임 데이터 영역에서 정확히 어느 위치에 저장되는지와 같은 부분이 애매모호하긴 했다. 예를 들어, static 변수는 클래스 변수니까 메서드 영역이라고 알고있었는데 공부를 하면서 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;이를 정확하게 메서드 영역이냐 Heap 영역이냐!는 결국 큰 의미는 없었다. 중요한 핵심은 스레드마다 생성되는 것이 아닌 스레드 들이 공유자원으로 이용한다는 점이 중요했다. static 변수가 heap 영역에 있다고 하여 인스턴스 여러 개 생성되는 원리도 아니고, heap 영역에 넣어서 최대한 GC되게 했다지만 사실상 거의 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;마지막으로, 아직 취업 준비하는 입장이기도 하고 갈 길이 멀기 때문에 이런 DFS식 공부는 접어두고 취업까지는 BFS식 공부로 쭉쭉 달리기로 다시 한 번 다짐한다. 여러분도 아직 취업을 준비하는 단계라면 이렇게까지 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;&lt;b&gt;참고&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a title=&quot;beststar 으뜸별 님의 JIT 컴파일러 게시글&quot; href=&quot;https://beststar-1.tistory.com/3&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;beststar 으뜸별 님의 JIT 컴파일러 게시글&lt;/b&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a title=&quot;impala님의 JVM - Execution Engine 게시글&quot; href=&quot;https://velog.io/@impala/JAVA-JVM-Execution-Engine&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;impala님의 JVM - Execution Engine 게시글&lt;/b&gt;&lt;/a&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;a title=&quot;네이버 d2 - JVM Internal&quot; href=&quot;https://d2.naver.com/helloworld/1230&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;네이버 d2 - JVM Internal&lt;/b&gt;&lt;/a&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;a title=&quot;mirinae님의 JVM GC 게시글&quot; href=&quot;https://mirinae312.github.io/develop/2018/06/04/jvm_gc.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;mirinae님의 JVM GC 게시글&lt;/b&gt;&lt;/a&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;a title=&quot;1-7171771님의 티스토리 - Java 8 이후의 heap 메모리 구조와 GC 알고리즘&quot; href=&quot;https://1-7171771.tistory.com/140&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;1-7171771님의 티스토리 - Java 8 이후의 heap 메모리 구조와 GC 알고리즘&lt;/b&gt;&lt;/a&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;a title=&quot;ThinkGround Studio - 일반적인 GC 내용과 G1GC (Garbage-First Garbage Collector) 내용&quot; href=&quot;https://thinkground.studio/%EC%9D%BC%EB%B0%98%EC%A0%81%EC%9D%B8-gc-%EB%82%B4%EC%9A%A9%EA%B3%BC-g1gc-garbage-first-garbage-collector-%EB%82%B4%EC%9A%A9/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;ThinkGround Studio - 일반적인 GC 내용과 G1GC (Garbage-First Garbage Collector) 내용&lt;/b&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a title=&quot; 기계인간님의 oracle docs - g1gc 정리&quot; href=&quot;https://johngrib.github.io/wiki/java-g1gc/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;기계인간님의 oracle docs - g1gc 정리&lt;/b&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a title=&quot;Oracle docs - G1GC&quot; href=&quot;https://docs.oracle.com/javase/9/gctuning/garbage-first-garbage-collector.htm#JSGCT-GUID-1CDEB6B6-9463-4998-815D-05E095BFBD0F&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;Oracle docs - G1GC&lt;/b&gt;&lt;/a&gt;&amp;nbsp;&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;u&gt;&lt;b&gt;※&amp;nbsp;본&amp;nbsp;게시글은&amp;nbsp;공부하면서&amp;nbsp;작성했기에&amp;nbsp;틀린&amp;nbsp;부분이&amp;nbsp;있을&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;질문&amp;nbsp;사항이나&amp;nbsp;댓글로&amp;nbsp;알려주시면&amp;nbsp;감사하겠습니다.&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;</description>
      <category>Language/Java</category>
      <category>g1gc</category>
      <category>garbage collection</category>
      <category>Garbage Collector</category>
      <category>Hotspot Compiler</category>
      <category>JIT Compiler</category>
      <category>JVM Execute Engine</category>
      <author>Dev Uni</author>
      <guid isPermaLink="true">https://jae-yoon.tistory.com/18</guid>
      <comments>https://jae-yoon.tistory.com/18#entry18comment</comments>
      <pubDate>Tue, 21 Mar 2023 05:23:09 +0900</pubDate>
    </item>
    <item>
      <title>[Java의 실행원리 3편] Runtime 환경 - JVM Memory, Runtime Data Area</title>
      <link>https://jae-yoon.tistory.com/17</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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;a title=&quot;[Java의 실행원리 0편] 시리즈 개요&quot; href=&quot;https://jae-yoon.tistory.com/14&quot;&gt;&lt;span&gt;&lt;b&gt;[Java의 실행원리 0편] 시리즈 개요&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;a title=&quot;[Java의 실행원리 1편] Compile-time 환경&quot; href=&quot;https://jae-yoon.tistory.com/15&quot;&gt;&lt;span&gt;&lt;b&gt;[Java의 실행원리 1편] Compile-time 환경&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;a title=&quot;[Java의 실행원리 2편] Runtime 환경 - JVM Class Loader&quot; href=&quot;https://jae-yoon.tistory.com/16&quot;&gt;&lt;b&gt;[Java의 실행원리 2편] Runtime 환경 - JVM Class Loader&lt;/b&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;[Java의 실행원리 3편] Runtime 환경 - JVM Memory, Runtime Data Areas&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;a title=&quot;[Java의 실행원리 4편] Runtime 환경 - JVM Execute Engine&quot; href=&quot;https://jae-yoon.tistory.com/18&quot;&gt;&lt;b&gt;[Java의 실행원리 4편] Runtime 환경 - JVM Execute Engine&lt;/b&gt;&lt;/a&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;JVM의 클래스로더에 의해 메모리 영역에 Byte Code(.class) 파일이 올라가면 사용할 준비가 끝난 것이다. 이제, 메모리 영역의 어디에 올라간다는 것인지 구조를 살펴보고 의미를 파악할 것이다. 이와 더불어 Method Area 내부에 Runtime Constant Pool이라는 단어가 보이는데, Constant Pool과 Runtime Constant Pool이 무슨 차이인지, Heap 영역의 String Pool( = String Constant Pool)은 무엇인지, Java 7까지의 Perm 영역과 Java 8 이후부터의 Metaspace 영역 등 다루는 이야기가 많아서, &lt;u&gt;&lt;b&gt;이번&lt;/b&gt;&lt;b&gt;&amp;nbsp;편은 조금 길다. 이 부분 유의하자.&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Runtime Data Areas&lt;/b&gt;&lt;b&gt;&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;2082&quot; data-origin-height=&quot;926&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cUmIAE/btr4LGJiEGo/kP4Wyn02KxShGnKG5Ux7zK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cUmIAE/btr4LGJiEGo/kP4Wyn02KxShGnKG5Ux7zK/img.png&quot; data-alt=&quot;그림1. JVM Runtime Data Areas&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cUmIAE/btr4LGJiEGo/kP4Wyn02KxShGnKG5Ux7zK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcUmIAE%2Fbtr4LGJiEGo%2FkP4Wyn02KxShGnKG5Ux7zK%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;2082&quot; height=&quot;926&quot; data-origin-width=&quot;2082&quot; data-origin-height=&quot;926&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림1. JVM Runtime Data Areas&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;background-color: #f6e199;&quot;&gt;&lt;b&gt;Runtime Data Areas&lt;/b&gt;&lt;/span&gt;는 JVM이 Host Operating Systems 위에서 실행되면서 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;OS로부터 할당받는 메모리 영역&lt;/b&gt;&lt;/span&gt;이다. 그림을 보면 Thread로 묶이는 부분과 묶이지 않는 부분을 볼 수 있는데, 이는 공유하는 것과 아닌 것의 차이이다. PC Register, Stack Area, Native Method Stack은 스레드가 생성될 때마다 생성되는 영역이고 Method Area, Heap Area는 JVM이 시작될 때 단 1개씩만 생성된다. Method Area와 Heap Area는 모든 스레드가 공유한다는 의미이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Method Area&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;Method Area&lt;/b&gt;&lt;b&gt;는 모든 스레드가 공유하는 영역으로 JVM이 시작될 때 생성&lt;/b&gt;&lt;/span&gt;된다. Metaspace라고 불리는 영역 내부에 속하는데, Method Area에는 &lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;JVM이 읽어들인 각각의 클래스와 인터페이스에 대한 Runtime Constant Pool, 필드와 메서드 정보, 메서드의 바이트코드 등이 보관&lt;/span&gt;&lt;/b&gt;된다. 특이하게도 static object와 String에 관련된 정보는 Method Area가 아닌 Heap Area에서 보관하는데 이에 대한 내용은 아래에서 소개한다. 우선 Runtime Constant Pool에 관한 이야기를 해보겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a title=&quot;[Java의 실행원리 1편] Compile-time 환경&quot; href=&quot;https://jae-yoon.tistory.com/15&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;[Java의&amp;nbsp;실행원리&amp;nbsp;1편]&amp;nbsp;Compile-time&amp;nbsp;환경&lt;/b&gt;&lt;/a&gt;에서 Java Compiler(javac) 내부의 Lexcial Analyzer &amp;rarr; Syntax Analyzer &amp;rarr; Semantic Analyzer&lt;span&gt;를&lt;/span&gt; &lt;span&gt;거치면서&lt;/span&gt; &lt;span&gt;만들어져&lt;/span&gt; &lt;span&gt;온&lt;/span&gt; Symbol Table&lt;span&gt;을&lt;/span&gt; &lt;span&gt;이용하여&lt;/span&gt; &lt;span&gt;클래스나&lt;/span&gt; &lt;span&gt;인터페이스&lt;/span&gt; &lt;span&gt;별&lt;/span&gt; Constant Pool(&lt;span&gt;상수&lt;/span&gt; &lt;span&gt;풀&lt;/span&gt;)&lt;span&gt;을&lt;/span&gt; 만든다고 했었다. Symbol table은 컴파일러가 변수의 의미론적인 내용을 추적하기 위해 유지되는 데이터 구조인데, 변수의 스코프, 바인딩 정보, 변수의 인스턴스 등 다양한 엔티티의 정보를 저장하는 것이다.&lt;/p&gt;
&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;Constant Pool(상수 풀)은 Byte Code(.class) 파일에서 필요한 Literal Constant, Type Field(Local Variable, Class Variable), Class 및 Method로의 모든 Symbolic Reference 등을 모아놓은 데이터 구조&lt;/b&gt;&lt;/span&gt;이다. 이&lt;span&gt; &lt;/span&gt;상수&lt;span&gt; &lt;/span&gt;풀은&lt;span&gt; Byte Code(.class) 파일&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;내에&lt;span&gt; &lt;/span&gt;있으며&lt;span&gt;, &lt;/span&gt;클래스&lt;span&gt; &lt;/span&gt;또는&lt;span&gt; &lt;/span&gt;인터페이스가&lt;span&gt; JVM&lt;/span&gt;에&lt;span&gt; &lt;/span&gt;의해&lt;span&gt; &lt;/span&gt;로드될&lt;span&gt; &lt;/span&gt;때마다&lt;span&gt; &lt;/span&gt;해당&lt;span&gt; &lt;/span&gt;클래스&lt;span&gt; &lt;/span&gt;또는&lt;span&gt; &lt;/span&gt;인터페이스의&lt;span&gt; &lt;/span&gt;상수&lt;span&gt; &lt;/span&gt;풀이&lt;span&gt; &lt;/span&gt;내부적으로&lt;span&gt; &lt;/span&gt;만들어지는데, &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;내부적으로 만들어져서 런타임 데이터 구조를 가지는 상수 풀이 바로 Runtime Constant Pool(런타임 상수 풀)&lt;/b&gt;&lt;/span&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;1918&quot; data-origin-height=&quot;592&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bFTm5Z/btr4LFKv7Hd/grBhxv9vFYGAFxYPHo77P1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bFTm5Z/btr4LFKv7Hd/grBhxv9vFYGAFxYPHo77P1/img.png&quot; data-alt=&quot;그림2. oracle docs에 나와있는 .class 파일 구조&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bFTm5Z/btr4LFKv7Hd/grBhxv9vFYGAFxYPHo77P1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbFTm5Z%2Fbtr4LFKv7Hd%2FgrBhxv9vFYGAFxYPHo77P1%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;1918&quot; height=&quot;592&quot; data-origin-width=&quot;1918&quot; data-origin-height=&quot;592&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림2. oracle docs에 나와있는 .class 파일 구조&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&gt;자바 class 파일은 &lt;a title=&quot;oracle docs 4.7&quot; href=&quot;https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-4.html#jvms-4.7&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;oracle docs 4.7&lt;/b&gt;&lt;/a&gt;에서와 같은 구조를 가지는데, 이 구조의 &lt;b&gt;contant_pool_count, constant_pool[]&lt;/b&gt;이 흔히 말하는 &lt;b&gt;Constant Pool(상수 풀)을 의미&lt;/b&gt;한다. &lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;이때,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;특정&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;상수에&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;대한&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;모든&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;인덱스&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;또는&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;참조를&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;16&lt;/span&gt;비트&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;(type u2)&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;번호로&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;제공되며&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;,&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;여기서&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;인덱스&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;값&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;1&lt;/span&gt;은&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;표의&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;첫&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;번째&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;상수를&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;나타낸다. 그러면, 클래스 파일을 역어셈블러(javap)를 이용하여 살펴보겠다.&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_1679228595685&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// 역어셈블러(javap)를 사용하는 명령어
javap -v Main.class&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2178&quot; data-origin-height=&quot;1122&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Y9owI/btr4viw3sd8/mncFjHStkAe3bpDywjwjT1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Y9owI/btr4viw3sd8/mncFjHStkAe3bpDywjwjT1/img.png&quot; data-alt=&quot;그림3. 역어셈블러를 활용하여 Main.class 내용 보기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Y9owI/btr4viw3sd8/mncFjHStkAe3bpDywjwjT1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FY9owI%2Fbtr4viw3sd8%2FmncFjHStkAe3bpDywjwjT1%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;2178&quot; height=&quot;1122&quot; data-origin-width=&quot;2178&quot; data-origin-height=&quot;1122&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림3. 역어셈블러를 활용하여 Main.class 내용 보기&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;Constant Pool은 리터럴&lt;span&gt; &lt;/span&gt;상수&lt;span&gt; &lt;/span&gt;값을&lt;span&gt; &lt;/span&gt;저장하는&lt;span&gt; &lt;/span&gt;곳이라고 했다&lt;span&gt;. 그림에서 보는 것처럼&amp;nbsp;&lt;/span&gt;모든&lt;span&gt; &lt;/span&gt;종류의&lt;span&gt; &lt;/span&gt;숫자&lt;span&gt;, String, &lt;/span&gt;문자열&lt;span&gt;, &lt;/span&gt;식별자&lt;span&gt; &lt;/span&gt;이름&lt;span&gt;, Class &lt;/span&gt;및&lt;span&gt; Method &lt;/span&gt;에&lt;span&gt; &lt;/span&gt;대한&lt;span&gt; &lt;/span&gt; symbolic refernce가&lt;span&gt;&amp;nbsp;&lt;/span&gt;포함된다&lt;span&gt;. 상수와 리터럴을 헷갈릴 수 있는데, 상수는 final 키워드를 이용하여 초기화 이후 값이 변하지 않는 수를 의미하고 리터럴도 상수의 일종인데, 선언없이 바로 사용할 수 있는 문자 그대로의(=리터럴한) 상수를 의미한다.&amp;nbsp;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;다시 말하면,&lt;/b&gt; &lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;Constant Pool은 클래스 파일 내부에 있고, 클래스 파일을 동적 로딩하여 JVM에 의해 메모리에 올라가면서 메서드 영역에 존재하는 상수 풀의 런타임 표현이 Runtime Constant Pool이라는 의미&lt;/b&gt;&lt;/span&gt;이다.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;JVM의 특징에 관해서 설명할 때, 기본 자료형(primitive data type)을 제외한 모든 타입(클래스와 인터페이스)을 명시적인 메모리 주소 기반의 레퍼런스가 아니라 심볼릭 레퍼런스를 통해 참조한다고 했었는데, Runtime Constant Pool에 있는 심볼릭 레퍼런스를 통해서 참조하는 원리이다.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;JVM은 이 런타임 상수 풀을 통해 해당 메서드나 필드의 실제 메모리상 주소를 참조한다. &lt;a title=&quot;[Java의 실행원리 2편] Runtime 환경 - JVM Class Loader&quot; href=&quot;https://jae-yoon.tistory.com/16&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;[Java의 실행원리 2편] Runtime 환경 - JVM Class Loader&lt;/b&gt;&lt;/a&gt;에서 설명한 것처럼 JVM의 클래스로더가 클래스 파일을 Load하고 Link의 Resolving 단계를 진행하면서 상수 풀 내 모든 symbolic references를 실제 메모리 주소로 변환하는 과정을 통해 실제 메모리 상 주소를 참조한다. 런타임&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;상수&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;풀에&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;있는&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;심볼릭&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;참조를&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;통해&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;현재&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;클래스로더가&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;로드한&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;실제&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;클래스를&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;확인하고&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;클래스&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;인스턴스에&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;대한&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;참조를&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;반환하는 형태이다. 즉,&amp;nbsp;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;Runtime Constant Pool에 실제 메모리 주소 정보가 있다는 의미는 아니다. 심볼릭 레퍼런스는 java/lang/Object와 같이 class, field, method의 이름을 기반으로 참조하는 것이다.&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;Constant pool은 각 클래스와 인터페이스의 상수 뿐만 아니라 메서드와 필드에 대한 모든 레퍼런스까지 담고 있는 테이블이라서 JVM 명세에서도 중요하게 기술한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;정리하자면, Metaspace 영역에 속하는 Method Area에는 클래스 자체의 메타데이터, Runtime Constant Pool과 같이 어떤 메서드나 필드를 참조하기 위한 심볼릭 레퍼런스와 모든 클래스 수준에 대한 정보가 저장된다.&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Heap Area&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt; Heap Area&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;는 Method Area와 마찬가지로 모든 스레드가 공유하는 영역으로 JVM이 시작될 때 생성&lt;/b&gt;&lt;/span&gt;된다.&lt;span&gt; Method Area에 클래스 수준의 데이터를 저장했다면, Heap Area는 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;Runtime에 생성된 인스턴스, 객체(object)를 저장하는 메모리 영역&lt;/b&gt;&lt;/span&gt;이다. 힙 영역은 Garbage Collection의 대상이라서 Garbage Collector가 사용하지 않는 객체의 참조를 알아서 해제해준다. 그러나, Memory Leak 문제가 발생할 수 있어서 아무리 자동으로 GC된다지만 개발자도 신경써야한다.&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&gt;메모리 누수 (Memory Leak)&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;메모리 누수란, 프로그램에서 필요하지 않은 메모리들이 계속 점유되고 있는 현상을 의미한다. 더이상 사용하지 않는 객체가 GC에 의해서 회수되지 않고 계속 누적되는 현상 다. 메모리 누수가 계속 중첩되다보면 heap 영역의 공간이 부족해져서 OutOfMemeoryError가 발생할 수 있다.&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;&lt;span style=&quot;color: #333333; text-align: start;&quot;&gt;&lt;span&gt;아래 그림에서 보이는 Eden, Survivor 0, Survivor 1, Old 영역에 대한 자세한 설명과 GC 관련 내용은 &lt;a title=&quot;[Java의 실행원리 4편] Runtime 환경 - JVM Execute Engine&quot; href=&quot;https://jae-yoon.tistory.com/18&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;[Java의 실행원리 4편] Runtime 환경 - JVM Execute Engine&lt;/b&gt;&lt;/a&gt;에서 다루도록 한다. 여기에서는 힙 영역은 인스턴스와 객체를 저장하는 메모리 영역이고 GC의 대상이 되는구나 정도만 이해하고 넘어가자.&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;2218&quot; data-origin-height=&quot;1138&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lLNwU/btr4yll1XyI/PYS2tR7aGt6bLClCblSwpk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lLNwU/btr4yll1XyI/PYS2tR7aGt6bLClCblSwpk/img.png&quot; data-alt=&quot;그림4. Heap Area 자세히 보기&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lLNwU/btr4yll1XyI/PYS2tR7aGt6bLClCblSwpk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlLNwU%2Fbtr4yll1XyI%2FPYS2tR7aGt6bLClCblSwpk%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;2218&quot; height=&quot;1138&quot; data-origin-width=&quot;2218&quot; data-origin-height=&quot;1138&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림4. Heap Area 자세히 보기&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;시리즈 개요에서 설명했듯이, Hotspot JVM을 기준으로 설명한 Heap Area 구조는 그림과 같다. Java 7까지라고 적혀있는데, 이는 Java 7에 존재하는 Permanent 영역이 Java 8부터는 Metaspace 영역으로 변하면서 바뀌었기 때문이다. 먼저, Java 7까지의 Hotspot JVM 구조는 아래와 같다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1679240079836&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Java 7까지의 Hotspot JVM 구조

&amp;lt;----- Java Heap -----&amp;gt;             &amp;lt;--- Native Memory ---&amp;gt;
+------+----+----+-----+-----------+--------+--------------+
| Eden | S0 | S1 | Old | Permanent | C Heap | Thread Stack |
+------+----+----+-----+-----------+--------+--------------+
                        &amp;lt;---------&amp;gt;
                       Permanent Heap
S0: Survivor 0
S1: Survivor 1&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;그림에서 Application에서 사용이라고 적혀있는 것처럼 Eden - Survivor 0 - Survivor 1 - Old는 Java Application이 사용하는 JVM의 메인 메모리인 힙 영역이고 Permanent 영역이라는 곳이 따로 있는데, 이는 앞에서 말한 JVM의 메인 메모리 Heap과는 분리되는 특수한 힙 영역이다. 원래 Permenant 영역 내부에 Method Area가 존재했었어서 클래스 메타 데이터, Static Object, Runtime Constant Pool 등이 Permanent 영역에 저장되었었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div align=&quot;center&quot;&gt;
&lt;table style=&quot;border-collapse: collapse; width: 78.9535%; height: 199px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style4&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 17px;&quot;&gt;
&lt;td style=&quot;width: 49.5614%; height: 17px; text-align: center;&quot;&gt;&lt;b&gt;Java Heap&lt;/b&gt;&lt;/td&gt;
&lt;td style=&quot;width: 50.4386%; height: 17px; text-align: center;&quot;&gt;&lt;b&gt;Permanent Generation&lt;/b&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 149px;&quot;&gt;
&lt;td style=&quot;width: 49.5614%; height: 149px;&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Permanent 영역에 있는 &lt;br /&gt;클래스의 인스턴스 저장&lt;/li&gt;
&lt;li&gt;-Xms (min), -Xmx (max)로 사이즈 조절&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;td style=&quot;width: 50.4386%; height: 149px;&quot;&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;클래스, 메서드 등 메타 데이터 저장&lt;/li&gt;
&lt;li&gt;Constant Pool 정보&lt;/li&gt;
&lt;li&gt;JVM, JIT 관련 데이터&lt;/li&gt;
&lt;li&gt;-XX:PermSize (min)&lt;br /&gt;-XX:MaxPermSize(max)&lt;/li&gt;
&lt;/ul&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그러나, Permanent 영역은 JVM 메모리에 의해 관리되며 항상 고정된 최대 크기를 가진다는 문제가 있었다. 왜냐하면, OS에 의해 관리받는 Native Memory 보다 크기가 훨씬 작을 것이기 때문이다.  그래서, 예를 들어 Collection 객체를 static하게 구현하여 값을 계속해서 추가하다보면 perm 영역이 가득차서 java.lang.OutOfMemoryError: PermGen space 같은 오류가 났었다. 이런 이유로&amp;nbsp;&lt;a title=&quot;OpenJDK JEP 122&quot; href=&quot;https://openjdk.org/jeps/122&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;OpenJDK JEP 122&lt;/b&gt;&lt;/a&gt;에서는&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt; Perm 영역을 제거하면서 이를 Metaspace 영역으로 대체&lt;/span&gt;&lt;/b&gt;한다고 하였다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1679241205942&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;// Java 8부터 Hotspot JVM 구조

&amp;lt;----- Java Heap -----&amp;gt; &amp;lt;--------- Native Memory ---------&amp;gt;
+------+----+----+-----+-----------+--------+--------------+
| Eden | S0 | S1 | Old | Metaspace | C Heap | Thread Stack |
+------+----+----+-----+-----------+--------+--------------+&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;Java 8부터는 JVM 메모리 구조적인 개선 사항으로 Perm 영역이 Metaspace로 대체되면서 JVM에 의해 관리되던 Heap이 아닌 OS에 의해 관리되는 Native Memory 영역으로 취급하게 되었다. 즉, 메모리 영역 크기에 대한 고민을 개발자가 할 필요가 없어진 것이다. &lt;a title=&quot;기계인간&quot; href=&quot;https://johngrib.github.io/wiki/java8-why-permgen-removed/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;기계인간&lt;/b&gt;&lt;/a&gt;님이 확인해본 바로는 Perm 영역의 MaxPermSize는 약 82MB이지만 Metaspace 영역의 MaxMetaspaceSize는 17,592,186,044,415 MB 정도로 64비트 프로세서가 취급할 수 있는 메모리 상한에 가까울 정도로 크기가 컸다.&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;1758&quot; data-origin-height=&quot;852&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/rVK1L/btr40GiM23u/Jv4ceF5EQ085CN3WJeVZNK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/rVK1L/btr40GiM23u/Jv4ceF5EQ085CN3WJeVZNK/img.png&quot; data-alt=&quot;그림5. openJDK docs JEP122에 명시된 내용&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/rVK1L/btr40GiM23u/Jv4ceF5EQ085CN3WJeVZNK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FrVK1L%2Fbtr40GiM23u%2FJv4ceF5EQ085CN3WJeVZNK%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;1758&quot; height=&quot;852&quot; data-origin-width=&quot;1758&quot; data-origin-height=&quot;852&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림5. openJDK docs JEP122에 명시된 내용&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다만, Perm 영역을 Metaspace로 대체하는 과정에서&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt; 기존 Perm 영역에 존재하던 클래스,인터페이스,메서드의 메타 정보나 상수 정보들은 OS에 의해 관리받는 Native Memory에 속하는 Metaspace 영역으로 보내면서 Static Object, Intern String은 Heap 영역으로 이관하여 GC의 대상이 최대한 될 수 있도록 하였다.&lt;/b&gt;&lt;/span&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;1710&quot; data-origin-height=&quot;566&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dFnN6s/btr4G7aPt8Y/pt79ivRKkgd28wpyH5Kk1k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dFnN6s/btr4G7aPt8Y/pt79ivRKkgd28wpyH5Kk1k/img.png&quot; data-alt=&quot;그림6. stackoverflow에 나오는 String pool 그림&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dFnN6s/btr4G7aPt8Y/pt79ivRKkgd28wpyH5Kk1k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdFnN6s%2Fbtr4G7aPt8Y%2Fpt79ivRKkgd28wpyH5Kk1k%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;1710&quot; height=&quot;566&quot; data-origin-width=&quot;1710&quot; data-origin-height=&quot;566&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림6. stackoverflow에 나오는 String pool 그림&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;아마, String pool에 관련된 그림으로 위와 같은 그림을 본 적 있을 것이다. Intern String이 String Pool( = String Constant Pool)이라고 이해하면 된다. Perm 영역이 Metaspace 영역으로 대체되면서 Static Object, Intern String을 Heap 영역으로 이관했다는 것이 위 그림과 연관된 내용이다. &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;Java의 String은 &quot;불변 객체&quot;라는 특징이 있다. 그래서 클래스 파일 Constant Pool에 리터럴 String이 있다면, 문자열의 복사본을 String Pool에 하나만 저장하여 할당된 메모리 양을 최적화 하는 것이고 이 과정을 intern이라고 한다. String Pool에 문자열 리터럴을 캐싱하고 이후에 재사용하게 되면 힙 메모리 영역을 효율적으로 사용할 수 있다는 의미이다.&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;String pool은 String 객체만 관리하는 특수한 메모리 영역으로 문자열 리터럴을 선언하면 JVM이 String pool에 객체를 생성하고 해당 참조를 스택에 저장하는 원리이다. 이때, String Pool은 Hashmap으로 구현된다. 즉,&amp;nbsp;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;클래스로더에 의해 클래스가 로드되면 모든 클래스의 문자열 리터럴이 String Pool로 이동한다. Constant Pool의 문자열 리터럴은 직렬화되어있어서 전송 가능한 형태일 뿐, Java 객체가 아니기 때문에 String Pool에서 객체화하여 사용하기 위함이다.&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;이러한 특성 때문에, String 리터럴을 쌩으로 더하는 연산의 성능은 좋지 않다. 더한 경우 결과가 Heap 영역에 새로운 객체로 저장되기 때문이다.&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1679315032914&quot; class=&quot;java&quot; data-ke-language=&quot;java&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;String s1 = new String(&quot;Cat&quot;);
String s2 = s1 + &quot; Dog&quot;;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이와 같은 코드가 있을 때 &quot;Cat Dog&quot;가 Heap에 새로 생성된다. 피연산자인 s1의 경우 문자열 처리 이후 쓸모없어져서 GC 대상이 되기에 일거리가 늘어나기 때문에 문자열 연산이 많은 경우에는 StringBuilder나 StringBuffer를 사용하는 것이 좋다.&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;String을 단순 문자열로 활용하고 싶을 때는 불변객체가 적절하지 않을 수 있다는 말이다. 문자열 연산 +이 많은 경우 문자열 연산 등으로 기존 객체의 공간이 부족해지는 경우, 기존의 버퍼 크기를 늘려 유연하게 동작하는 가변객체를 이용할 수 있다.&lt;br /&gt;&lt;br /&gt;StringBuffer는 각 메서드별로 Synchronized Keyword가 존재하여, 멀티스레드 환경에서도 동기화를 지원하지만 StringBuilder는 동기화를 보장하지 않는다.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;String&lt;/b&gt; : 문자열 연산 자체가 적고 멀티스레드의 경우&lt;br /&gt;&lt;b&gt;StringBuffer&lt;/b&gt; : 문자열 연산이 많고 멀티스레드의 경우&lt;br /&gt;&lt;b&gt;StringBuilder&lt;/b&gt;&amp;nbsp;: 문자열 연산이 많고 단일스레드고 동기화를 고려하지 않아도 되는 경우&lt;br /&gt;&lt;br /&gt;&lt;b&gt;보통 Java-Spring에서는 멀티스레드 환경을 지원하고 있기 때문에 보통은 String, StringBuffer를 사용하는 편이다.&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;&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;b&gt;Constant Pool (상수 풀)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Byte Code(.class) 파일 내부에 존재하는 constant_pool[] 테이블이다.&lt;/li&gt;
&lt;li&gt;Literal Constant, Type Field(Local Variable, Class Variable), Class &lt;span&gt;및&lt;/span&gt; Method&lt;span&gt;로의&lt;/span&gt; &lt;span&gt;모든&lt;/span&gt; Symbolic Reference &lt;span&gt;등을&lt;/span&gt; &lt;span&gt;모아놓은&lt;/span&gt; &lt;span&gt;데이터&lt;/span&gt; &lt;span&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;b&gt;&lt;span&gt;Runtime Constant Pool (런타임 상수 풀)&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;클래스로더에 의해 클래스 파일이 동적 로딩되면서 메서드 영역에 생성되는 상수 풀의 런타임 데이터구조이다.&lt;/li&gt;
&lt;li&gt;Java 7의 Perm 영역이 없어지고 Java 8부터는 Metaspace 영역이 생기면서 Metaspace의 메서드 영역에 저장된다.&lt;/li&gt;
&lt;li&gt;String Pool, Static Object는 런타임 상수 풀이 아닌 Heap 영역에 저장되어 최대한 GC의 대상이 되게 한다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;String Pool ( = String Constant Pool, 문자열 풀 )&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Heap 영역에 있는 String 객체를 위한 특수한 메모리 영역이다.&lt;/li&gt;
&lt;li&gt;Heap에 있어서 문자열 객체가 더이상 참조되지 않으면 GC의 대상이다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Heap에 있는 String Pool의 Intern String 객체와 Static 객체는 GC 대상이다.&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Heap 영역에 있기도 하고 메모리 누수를 방지하기 위해 GC 대상이 된다.&lt;/li&gt;
&lt;li&gt;String이든 Static이든 더이상 객체가 참조되지 않으면 GC 된다.&lt;/li&gt;
&lt;li&gt;하지만, 일반적으로 참조를 해제할 일이 없어서 GC되지 않고 프로그램 수명동안 메모리에 있다고 생각하면 된다.&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;background-color: #f6e199;&quot;&gt;&lt;b&gt;Intern String 객체든 Static 객체든 메서드 영역에 있나 힙 영역에 있나는 그렇게 중요한 사실이 아니다. 어디에 있든 스레드가 공유하는 자원이고 여러 개 생성되지 않고 하나만 생성되고 여러 스레드가 이를 참조한다는 사실이 중요하다.&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;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;PC Register&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;PC(Program Counter) Register는 각 스레드마다 하나씩 존재하며, 스레드가 시작될 때 생성된다.&lt;/b&gt;&lt;/span&gt; 특정 스레드의 위치를 표시하므로 각각의 스레드별로 생성되는 것이다. PC 레지스터는 &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;현재 수행 중인 JVM의 명령의 주소를 가지고 스레드가 어떤 명령을 실행하게 될 지에 대하여 기록하는 곳이다.&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;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Stack Area&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;Stack Area는 각 스레드마다 하나씩 존재하며, 스레드가 시작될 때 생성된다.&lt;/b&gt;&lt;/span&gt; 스택은 흔히 아는 것처럼 LIFO(Last In First Out) 자료구조이고 이 스택 영역을 JVM 스택이라고도 한다. Stack Frame(스택 프레임)이라는 구조체를 저장하는 스택으로 &lt;b&gt;JVM은 오직 스택에 스택 프레임을 추가하고(push) 제거하는(pop) 동작만 수행&lt;/b&gt;한다. 이 영역에 너무 많은 데이터가 저장되는 경우 발생하는 문제가 stack overflow error이다.&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;1488&quot; data-origin-height=&quot;536&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NninF/btr4Yt5duap/0zMK1PpXonezUnCzTa3Crk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NninF/btr4Yt5duap/0zMK1PpXonezUnCzTa3Crk/img.png&quot; data-alt=&quot;그림7. 네이버 d2 -&amp;amp;amp;nbsp;https://d2.naver.com/helloworld/1230에 나와있는 그림&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NninF/btr4Yt5duap/0zMK1PpXonezUnCzTa3Crk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNninF%2Fbtr4Yt5duap%2F0zMK1PpXonezUnCzTa3Crk%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;1488&quot; height=&quot;536&quot; data-origin-width=&quot;1488&quot; data-origin-height=&quot;536&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림7. 네이버 d2 -&amp;amp;nbsp;https://d2.naver.com/helloworld/1230에 나와있는 그림&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;Stack Frame (스택 프레임)&lt;/b&gt; : &lt;span&gt;JVM &lt;/span&gt;내에서&lt;span&gt; &lt;/span&gt;메서드가&lt;span&gt; &lt;/span&gt;수행될&lt;span&gt; &lt;/span&gt;때마다&lt;span&gt; &lt;/span&gt;하나의&lt;span&gt; &lt;/span&gt;스택&lt;span&gt; &lt;/span&gt;프레임이&lt;span&gt; &lt;/span&gt;생성되어&lt;span&gt; &lt;/span&gt;해당&lt;span&gt; &lt;/span&gt;스레드의&lt;span&gt; JVM &lt;/span&gt;스택에&lt;span&gt; &lt;/span&gt;추가되고&lt;span&gt; &lt;/span&gt;메서드가&lt;span&gt; &lt;/span&gt;종료되면&lt;span&gt; &lt;/span&gt;스택&lt;span&gt; &lt;/span&gt;프레임이&lt;span&gt; &lt;/span&gt;제거된다&lt;span&gt;. &lt;/span&gt;각&lt;span&gt; &lt;/span&gt;스택&lt;span&gt; &lt;/span&gt;프레임은&lt;span&gt; &lt;/span&gt;지역&lt;span&gt; &lt;/span&gt;변수&lt;span&gt; &lt;/span&gt;배열&lt;span&gt;(Local Variable Array), &lt;/span&gt;피연산자&lt;span&gt; &lt;/span&gt;스택&lt;span&gt;(Operand Stack), &lt;/span&gt;현재&lt;span&gt; &lt;/span&gt;실행&lt;span&gt; &lt;/span&gt;중인&lt;span&gt; &lt;/span&gt;메서드가&lt;span&gt; &lt;/span&gt;속한&lt;span&gt; &lt;/span&gt;클래스의&lt;span&gt; &lt;/span&gt;런타임&lt;span&gt; &lt;/span&gt;상수&lt;span&gt; &lt;/span&gt;풀(Runtime Constant Pool)에&lt;span&gt; &lt;/span&gt;대한&lt;span&gt; &lt;/span&gt;&lt;b&gt;레퍼런스&lt;/b&gt;를&lt;span&gt; &lt;/span&gt;갖는다&lt;span&gt;. &lt;/span&gt;지역&lt;span&gt; &lt;/span&gt;변수&lt;span&gt; &lt;/span&gt;배열&lt;span&gt;, &lt;/span&gt;피연산자&lt;span&gt; &lt;/span&gt;스택의&lt;span&gt; &lt;/span&gt;크기는&lt;span&gt; &lt;/span&gt;컴파일&lt;span&gt; &lt;/span&gt;시에&lt;span&gt; &lt;/span&gt;결정되기&lt;span&gt; &lt;/span&gt;때문에&lt;span&gt; &lt;/span&gt;스택&lt;span&gt; &lt;/span&gt;프레임의&lt;span&gt; &lt;/span&gt;크기도&lt;span&gt; &lt;/span&gt;메서드에&lt;span&gt; &lt;/span&gt;따라&lt;span&gt; &lt;/span&gt;크기가&lt;span&gt; &lt;/span&gt;고정된다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;정리 하자면, &lt;/span&gt;&lt;u&gt;&lt;span&gt;Frame&lt;/span&gt;은&lt;span&gt; &lt;/span&gt;데이터와&lt;span&gt; &lt;/span&gt;부분적인&lt;span&gt; &lt;/span&gt;결과를&lt;span&gt; &lt;/span&gt;저장하고&lt;span&gt;, &lt;/span&gt;동적인&lt;span&gt; linking&lt;/span&gt;을&lt;span&gt; &lt;/span&gt;수행하고&lt;span&gt;, &lt;/span&gt;메서드를&lt;span&gt; &lt;/span&gt;위해&lt;span&gt; &lt;/span&gt;값을&lt;span&gt; &lt;/span&gt;리턴하고&lt;span&gt;, &lt;/span&gt;예외를&lt;span&gt; dispatch &lt;/span&gt;하기&lt;span&gt; &lt;/span&gt;위해&lt;span&gt; &lt;/span&gt;사용&lt;/u&gt;된다&lt;span&gt;.&amp;nbsp;&lt;/span&gt;프레임은&lt;span&gt; &lt;/span&gt;메서드를&lt;span&gt; &lt;/span&gt;호출하는&lt;span&gt; &lt;/span&gt;스레드의&lt;span&gt; JVM Stack&lt;/span&gt;으로&lt;span&gt; &lt;/span&gt;부터&lt;span&gt; &lt;/span&gt;할당되어지고&lt;span&gt; &lt;/span&gt;메서드가&lt;span&gt; &lt;/span&gt;호출되어질&lt;span&gt; &lt;/span&gt;때&lt;span&gt; &lt;/span&gt;생성되고&lt;span&gt; &lt;/span&gt;메서드가&lt;span&gt; &lt;/span&gt;완료되어질&lt;span&gt; &lt;/span&gt;때&lt;span&gt; &lt;/span&gt;소멸한다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;Local Variable Array (지역 변수 배열)&lt;/b&gt; : 0부터&amp;nbsp;시작하는&amp;nbsp;인덱스를&amp;nbsp;가진&amp;nbsp;배열이다.&amp;nbsp;0은&amp;nbsp;메서드가&amp;nbsp;속한&amp;nbsp;클래스&amp;nbsp;인스턴스의&amp;nbsp;this&amp;nbsp;레퍼런스이고,&amp;nbsp;1부터는&amp;nbsp;메서드에&amp;nbsp;전달된&amp;nbsp;&lt;u&gt;파라미터들이&amp;nbsp;저장&lt;/u&gt;되며,&amp;nbsp;메서드&amp;nbsp;파라미터&amp;nbsp;이후에는&amp;nbsp;&lt;u&gt;메서드의&amp;nbsp;지역&amp;nbsp;변수들이&amp;nbsp;저장&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&gt;&lt;b&gt;Operand Stack (피연산자 스택)&lt;/b&gt; : &lt;u&gt;메서드의 실제 작업 공간이다. 프로그램&amp;nbsp;연산을&amp;nbsp;수행하면서&amp;nbsp;필요한&amp;nbsp;데이터&amp;nbsp;및&amp;nbsp;결과를&amp;nbsp;저장하는&amp;nbsp;곳&lt;/u&gt;이다.각 메서드는 피연산자 스택과 지역 변수 배열 사이에서 데이터를 교환하고, 다른 메서드 호출 결과를 추가하거나(push) 꺼낸다(pop). 피연산자 스택 공간이 얼마나 필요한지는 컴파일할 때 결정할 수 있으므로, 피연산자 스택의 크기도 컴파일 시에 결정된다.&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;Reference to Constant Pool (상수 풀 참조)&lt;/b&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;1704&quot; data-origin-height=&quot;1116&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bo6aDD/btr4LGjQ7l3/MPQQfL7L37bwH7iIF9bDP0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bo6aDD/btr4LGjQ7l3/MPQQfL7L37bwH7iIF9bDP0/img.png&quot; data-alt=&quot;그림8. 역어셈블러(javap)를 이용하여 본 클래스 파일의 바이트 코드&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bo6aDD/btr4LGjQ7l3/MPQQfL7L37bwH7iIF9bDP0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbo6aDD%2Fbtr4LGjQ7l3%2FMPQQfL7L37bwH7iIF9bDP0%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;1704&quot; height=&quot;1116&quot; data-origin-width=&quot;1704&quot; data-origin-height=&quot;1116&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림8. 역어셈블러(javap)를 이용하여 본 클래스 파일의 바이트 코드&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;a title=&quot;[Java의 실행원리 1편] Compile-time 환경&quot; href=&quot;https://jae-yoon.tistory.com/15&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;[Java의&amp;nbsp;실행원리&amp;nbsp;1편]&amp;nbsp;Compile-time&amp;nbsp;환경&lt;/b&gt;&lt;/a&gt;에서 설명한 JVM의 특징 중에 스택기반 가상머신이라는 의미가 이것 때문이다. 피연산자 스택과 x86 아키텍처의 어셈블리에 나오는 OpCode(피연산자) 형식이 비슷해보이지만, Byte Code(.class) 파일에는 메모리 주소나 오프셋을 쓰지 않는다는 것을 확인할 수 있다.&lt;/p&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은 레지스터를 사용하지 않고 스택을 사용하며, 자체적으로 메모리를 관리하기 때문에 실제 메모리 주소 대신 #1와 같이 인덱스 번호를 사용하는 것이다. 상수 풀의 인덱스인데, JVM은 각 클래스마다 상수 풀을 생성하여 실제 대상의 레퍼런스를 보관하고 있다는 의미이다. &lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;정리하자면 실제 동작에서 각각의 클래스 인스턴스들, intern String, Static Object는 힙에 할당되고, 클래스 메타데이터는 Metaspace의 메서드 영역에 저장될 것이다.&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;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Native Method Stack&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;Native Method Stack은 자바가 이외의 언어인 네이티브 코드로 작성된 메서드를 위한 스택이다.&lt;/b&gt;&lt;/span&gt; Native Method Stack을 호출할 시 JVM 스택은 작동하지 않고 Frame을 push, pop한다. JNI(Java Native Interface)를 통해 호출하는 C/C++ 코드를 수행하기 위한 스택이며 언어에 맞게 C 스택이나 C++ 스택이 생성된다. 역시 이부분도 스레드별로 생성된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;JNI(Java Native Interface)는 JVM에서 실행 중인 Java 코드에서 다른 언어(C/C++)로 작성된 코드를 호출할 수 있도록 도와주는 프레임워크이다. 이를 통해 JVM은 C/C++ 라이브러리를 호출하고 하드웨어에 고유한 C/C++ 라이브러리에서 호출할 수 있게 된다.&lt;br /&gt;&lt;br /&gt;Native Method Libraries는 Execute Engine에 필요한 Native Libraries(C/C++)의 모음이다.&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;이렇게 Runtime Data Areas을 세부적으로 알아봤다. 이제 마지막 남은 시리즈에서는 어떻게 실행되는지 원리를 보며 JVM의 꽃이기도 한 Garbage Collection의 여러 알고리즘을 살펴보겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;span&gt;참고&lt;/span&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a title=&quot;baeldung - constant pool&quot; href=&quot;https://www.baeldung.com/jvm-constant-pool&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;baeldung - constant pool&lt;/b&gt;&lt;/a&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;a title=&quot;baeldung - String constant pool&quot; href=&quot;https://www.baeldung.com/java-string-constant-pool-heap-stack&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;baeldung - String constant pool&lt;/b&gt;&lt;/a&gt;&amp;nbsp;&lt;/li&gt;
&lt;li&gt;&lt;a title=&quot;jiwondev님의 String pool 정리&quot; href=&quot;https://jiwondev.tistory.com/114&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;jiwondev님의 String pool 정리&lt;/b&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a title=&quot; 기계인간님의 Java 8에서 permgen이 없어진 이유&quot; href=&quot;https://johngrib.github.io/wiki/java8-why-permgen-removed/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;기계인간님의 Java 8에서 permgen이 없어진 이유&lt;/b&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a title=&quot;네이버 d2 - JVM Internal&quot; href=&quot;https://d2.naver.com/helloworld/1230&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;네이버 d2 - JVM Internal&lt;/b&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a title=&quot;imbf님의 실무면접 준비 4편&quot; href=&quot;https://imbf.github.io/interview/2021/03/02/NAVER-Practical-Interview-Preparation-4.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;imbf님의 실무면접 준비 4편&lt;/b&gt;&lt;/a&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;u&gt;&lt;b&gt;※&amp;nbsp;본&amp;nbsp;게시글은&amp;nbsp;공부하면서&amp;nbsp;작성했기에&amp;nbsp;틀린&amp;nbsp;부분이&amp;nbsp;있을&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;질문&amp;nbsp;사항이나&amp;nbsp;댓글로&amp;nbsp;알려주시면&amp;nbsp;감사하겠습니다.&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;</description>
      <category>Language/Java</category>
      <category>Constant Pool</category>
      <category>JVM Memory Areas</category>
      <category>JVM Runtime Data Areas</category>
      <category>Runtime Constant Pool</category>
      <category>string pool</category>
      <author>Dev Uni</author>
      <guid isPermaLink="true">https://jae-yoon.tistory.com/17</guid>
      <comments>https://jae-yoon.tistory.com/17#entry17comment</comments>
      <pubDate>Mon, 20 Mar 2023 20:50:04 +0900</pubDate>
    </item>
    <item>
      <title>[Java의 실행원리 2편] Runtime 환경 - JVM Class Loader</title>
      <link>https://jae-yoon.tistory.com/16</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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;a title=&quot;[Java의 실행원리 0편] 시리즈 개요&quot; href=&quot;https://jae-yoon.tistory.com/14&quot;&gt;&lt;span&gt;&lt;b&gt;[Java의 실행원리 0편] 시리즈 개요&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;a title=&quot;[Java의 실행원리 1편] Compile-time 환경&quot; href=&quot;https://jae-yoon.tistory.com/15&quot;&gt;&lt;span&gt;&lt;b&gt;[Java의 실행원리 1편] Compile-time 환경&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;[Java의 실행원리 2편] Runtime 환경 - JVM Class Loader&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;a title=&quot;[Java의 실행원리 3편] Runtime 환경 - JVM Memory, Runtime Data Areas&quot; href=&quot;https://jae-yoon.tistory.com/17&quot;&gt;&lt;b&gt;[Java의 실행원리 3편] Runtime 환경 - JVM Memory, Runtime Data Areas&lt;/b&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a title=&quot;[Java의 실행원리 4편] Runtime 환경 - JVM Execute Engine&quot; href=&quot;https://jae-yoon.tistory.com/18&quot;&gt;&lt;b&gt;[Java의 실행원리 4편] Runtime 환경 - JVM Execute Engine&lt;/b&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;ClassLoader - Dynamic Loading&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저번 시간에 자바 컴파일러를 거쳐서 소스 코드(.java)에서 바이트 코드(.class) 파일까지는 만들었다. 이제 JVM 내부의&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&amp;nbsp;&lt;b&gt;클래스로더가 런타임 시점에 JVM의 Memory area인 Runtime Data Area에 바이트 코드인 클래스 파일을 올리면 이를 이용하여 JVM의 Execute Engine이 사용할 수 있게 된다.&lt;/b&gt;&lt;/span&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과 연결되는데, 이렇게 동적으로 클래스를 로딩해주는 역할을 하는 것이 바로 클래스 로더(class loader)이다. 클래스 로더는 클래스(.class) 파일을 묶어서 JVM이 Host Operating System으로부터 할당받은 메모리 영역인 Runtime Data Area로 적재한다.&lt;/p&gt;
&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;동적으로 클래스를 읽어온다&lt;/b&gt;&lt;/span&gt;는 것은, 간단하게 &quot;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;자바 클래스의 코드가 런타임 시에 필요할 때 메모리에 로드되는 것&lt;/b&gt;&lt;/span&gt;&quot;을 의미한다. 이를&amp;nbsp;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;동적 로딩(Dynamic Loading)&lt;/b&gt;&lt;/span&gt;이라고 하며, 이를 통해 자바 애플리케이션에서 코드를 실행하는 동안 클래스 파일을 동적으로 로드하고 초기화할 수 있다.&amp;nbsp;동적 로딩은 아래와 같이 두 가지 방식이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Load Time Dynamic Loading : 클래스를 로드하는 과정에서 그와 연관된 다른 클래스를 한 번에 동적으로 로드하는 것&lt;/li&gt;
&lt;li&gt;Run Time Dynamic Loading : Reflection &lt;span&gt;같이&lt;/span&gt; &lt;span&gt;실제로&lt;/span&gt; &lt;span&gt;메서드가&lt;/span&gt; &lt;span&gt;실행될&lt;/span&gt; &lt;span&gt;때&lt;/span&gt; &lt;span&gt;동적으로&lt;/span&gt; &lt;span&gt;로드하는&lt;/span&gt; &lt;span&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1306&quot; data-origin-height=&quot;486&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b2f1xU/btr4uKmvyQY/l4NSOKtB0AZ1PsD7TByHN1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b2f1xU/btr4uKmvyQY/l4NSOKtB0AZ1PsD7TByHN1/img.png&quot; data-alt=&quot;그림1. oracle docs - Class Loader 동작 과정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b2f1xU/btr4uKmvyQY/l4NSOKtB0AZ1PsD7TByHN1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb2f1xU%2Fbtr4uKmvyQY%2Fl4NSOKtB0AZ1PsD7TByHN1%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;1306&quot; height=&quot;486&quot; data-origin-width=&quot;1306&quot; data-origin-height=&quot;486&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림1. oracle docs - Class Loader 동작 과정&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;2956&quot; data-origin-height=&quot;1414&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SDS5X/btr4DtcabVj/eB3KLQahdD10PhT1Xk5pnk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SDS5X/btr4DtcabVj/eB3KLQahdD10PhT1Xk5pnk/img.png&quot; data-alt=&quot;그림2. ClassLoader 동작 과정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SDS5X/btr4DtcabVj/eB3KLQahdD10PhT1Xk5pnk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSDS5X%2Fbtr4DtcabVj%2FeB3KLQahdD10PhT1Xk5pnk%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;2956&quot; height=&quot;1414&quot; data-origin-width=&quot;2956&quot; data-origin-height=&quot;1414&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림2. ClassLoader 동작 과정&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;JVM&lt;span&gt;의&lt;/span&gt; &lt;span&gt;클래스로더는&lt;/span&gt; &lt;span&gt;클래스&lt;/span&gt; &lt;span&gt;파일을&lt;/span&gt; load, link, initialize&lt;span&gt;하는&lt;/span&gt; 3&lt;span&gt;가지&lt;/span&gt; &lt;span&gt;단계로&lt;/span&gt; &lt;span&gt;메모리에&lt;/span&gt; &lt;span&gt;올리는데&lt;/span&gt; &lt;span&gt;이를&lt;/span&gt; &lt;span&gt;상세히&lt;/span&gt; &lt;span&gt;보도록&lt;/span&gt; &lt;span&gt;하자&lt;/span&gt;.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;ClassLoader 작동 원리 - Load&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로드하는 단계에서는&amp;nbsp;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;JVM이 바이너리로 표현된 특정 이름을 가진 클래스 혹은 인터페이스를 찾고, 이를 생성하는 과정을 진행&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 data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;각 클래스로더는 로드된 클래스들을 네임스페이스(namespace)라는 장소에 보관하고, 클래스를 로드할 때 이미 로드된 클래스인지 확인하기 위하여 네임스페이스에 보관된 FQCN(Fully Qualified Class Name)을 기준으로 클래스를 찾는다.&lt;/b&gt;&lt;/span&gt;&amp;nbsp;비록 FQCN이 같더라도 네임스페이스가 다르면, 즉, 다른 클래스로더가 로드한 클래스면 다른 클래스로 간주한다는 의미이다.&amp;nbsp;클래스를 로드하는 ClassLoader를 알기 위하여 getClassLoader() 메서드를 사용할 수 있다. 모든 클래스는 바이너리 이름에 따라 로드되는데, 이러한 클래스 중 하나라도 발견되지 않는다면 NoClassDefFoundError나 ClassNotFoundException을 반환한다.&lt;/p&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;background-color: #f6e199;&quot;&gt;&lt;b&gt;Java 8과 Java 9 이후에서 약간의 차이가 있다.&lt;/b&gt;&amp;nbsp;&lt;/span&gt;이는&amp;nbsp;&lt;a title=&quot;[Java의 실행원리 1편] Compile-time 환경&quot; href=&quot;https://jae-yoon.tistory.com/15&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span&gt;&lt;b&gt;[Java의&amp;nbsp;실행원리&amp;nbsp;1편]&amp;nbsp;Compile-time&amp;nbsp;환경&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;에서 언급한 Java 9부터 모듈 시스템의 도입으로 인한 변화 때문이다.&lt;/p&gt;
&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;&amp;nbsp;&lt;/span&gt;이제&lt;span&gt; &lt;/span&gt;클래스로더를&lt;span&gt; &lt;/span&gt;상세하게&lt;span&gt; &lt;/span&gt;살펴보자&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2876&quot; data-origin-height=&quot;1772&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bz7lly/btr4wLdGQJC/lPbgtd93en3ib5xdK8pvhk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bz7lly/btr4wLdGQJC/lPbgtd93en3ib5xdK8pvhk/img.png&quot; data-alt=&quot;그림3. Java 8 Class Loader의 계층구조&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bz7lly/btr4wLdGQJC/lPbgtd93en3ib5xdK8pvhk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbz7lly%2Fbtr4wLdGQJC%2FlPbgtd93en3ib5xdK8pvhk%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;2876&quot; height=&quot;1772&quot; data-origin-width=&quot;2876&quot; data-origin-height=&quot;1772&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림3. Java 8 Class Loader의 계층구조&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;2876&quot; data-origin-height=&quot;1428&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b3VBtF/btr4uJunHQz/SVBNzfUCUeu6leI48LmuNk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b3VBtF/btr4uJunHQz/SVBNzfUCUeu6leI48LmuNk/img.png&quot; data-alt=&quot;그림4. Java 8 Class Loader 로드 대상&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b3VBtF/btr4uJunHQz/SVBNzfUCUeu6leI48LmuNk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb3VBtF%2Fbtr4uJunHQz%2FSVBNzfUCUeu6leI48LmuNk%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;2876&quot; height=&quot;1428&quot; data-origin-width=&quot;2876&quot; data-origin-height=&quot;1428&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림4. Java 8 Class Loader 로드 대상&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;Bootstrap Class Loader&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;클래스로더 중 최상위 계층의 클래스로더이며, JVM이 실행될 때 Java 애플리케이션에 필요한 기본적인 class 들을 로드한다.&lt;/li&gt;
&lt;li&gt;Java 8에서는 모든 Java 플랫폼 API, Java 애플리케이션을 함께 패키징한&amp;nbsp;&lt;b&gt;rt.jar&lt;/b&gt;&amp;nbsp;파일을 로드한다. (ex. java.lang )&lt;/li&gt;
&lt;li&gt;클래스로더 중 유일하게 Native C로 구현되어있다. 따라서, Java 코드에 의해 인스턴스화가 불가능하다는 뜻이라서 String.class.getClassLoader()는 null을 반환한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Extension Class Loader&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;주로,&amp;nbsp;&lt;b&gt;jre/lib/ext&lt;/b&gt;에 있는 .jar 파일들을 로드한다. JDK가 추가적으로 제공하는 라이브러리를 로드하는 것이다.&lt;/li&gt;
&lt;li&gt;Java로 구현되어있다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Application Class Loader&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;classpath에 설정된 클래스를 로드한다. 개발자가 -cp 명령어를 통해 직접 클래스 경로를 명시할 수도 있다.&lt;/li&gt;
&lt;li&gt;JAR 파일 내부의 Manifest의 Class-Path 속성값으로 지정된 폴더에 있는 클래스도 로드한다.&lt;/li&gt;
&lt;li&gt;Java로 구현되어있다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f6e199;&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;b&gt;User-defined Class Loader&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;개발자에 의해 정의된 사용자 정의 클래스로더로, JVM의 기본 클래스로더는 아니다.&lt;/li&gt;
&lt;li&gt;모든 사용자 정의 클래스로더는 추상 클래스인 ClassLoader의 하위 인스턴스이다. 이는&amp;nbsp;&lt;a title=&quot;오라클 공식문서의 5.3&quot; href=&quot;https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-5.html#jvms-5.3&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span&gt;&lt;b&gt;오라클 공식문서의 5.3&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;에 &quot;Every user-defined class loader is an instance of a subclass of the abstract class&amp;nbsp;ClassLoader&quot;라고 명시된 내용이다.&lt;/li&gt;
&lt;li&gt;클래스로더를&lt;span&gt; &lt;/span&gt;만들어서&lt;span&gt; &lt;/span&gt;사용하는&lt;span&gt; &lt;/span&gt;것은&lt;span&gt; &lt;/span&gt;클래스&lt;span&gt; &lt;/span&gt;로딩을&lt;span&gt; &lt;/span&gt;제어하고&lt;span&gt;, &lt;/span&gt;클래스를&lt;span&gt; &lt;/span&gt;동적으로&lt;span&gt; &lt;/span&gt;로드하고&lt;span&gt; &lt;/span&gt;언로드하며&lt;span&gt;, &lt;/span&gt;클래스를&lt;span&gt; &lt;/span&gt;다른&lt;span&gt; &lt;/span&gt;원격서버에서&lt;span&gt; &lt;/span&gt;로드할&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있도록&lt;span&gt; &lt;/span&gt;하기&lt;span&gt; &lt;/span&gt;위함이다&lt;span&gt;. &lt;/span&gt;예를&lt;span&gt; &lt;/span&gt;들어&lt;span&gt;, &lt;/span&gt;특정&lt;span&gt; &lt;/span&gt;조건을&lt;span&gt; &lt;/span&gt;충족하지&lt;span&gt; &lt;/span&gt;않으면&lt;span&gt; &lt;/span&gt;클래스를&lt;span&gt; &lt;/span&gt;로드하지&lt;span&gt; &lt;/span&gt;않도록&lt;span&gt; &lt;/span&gt;할&lt;span&gt; &lt;/span&gt;수도&lt;span&gt; &lt;/span&gt;있다&lt;span&gt;.&amp;nbsp;&lt;a title=&quot;스택오버플로우의 답변&quot; href=&quot;https://stackoverflow.com/questions/10828863/what-is-the-use-of-custom-class-loader&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span&gt;&lt;b&gt;스택오버플로우의&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;답변&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;을&lt;span&gt; &lt;/span&gt;추가적으로&lt;span&gt; &lt;/span&gt;참고하자&lt;span&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;b&gt;Java.lang.ClassLoader 메서드&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;loadClass(String name, boolean resolve)&lt;/b&gt;&amp;nbsp;: JVM이 참조하는 클래스를 로드할 때 사용한다. 이때, 클래스 이름을 매개변수로 사용한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;defineClass()&lt;/b&gt;&amp;nbsp;: final 메서드라서 재정의할 수 없다. 바이트 배열을 클래스의 인스턴스로 정의하는데 사용하는데, 클래스가 유효하지 않으면 ClassFormatError가 발생한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;findClass(String name)&lt;/b&gt;&amp;nbsp;: 지정된 클래스를 찾을 때 사용한다. 클래스를 찾기만하고 로드 하지는 않는다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;findLoadedClass(String name)&lt;/b&gt;&amp;nbsp;: JVM이 참조하는 클래스가 이전에 로드되었는지 여부를 확인한다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Class.forName(String name, boolean initialize, ClassLoader loader)&lt;/b&gt;&amp;nbsp;: 클래스를 로드할 뿐만 아니라 초기화하는 데에도 사용된다. 또한, ClassLoader 중 하나를 선택할 수 있는 옵션을 제공하는데 만약 ClassLoader 매개변수가 null이면 Bootstrap ClassLoader가 사용된다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;span&gt;이러한&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;클래스로더는&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;아래의&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;원칙에&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;의하여&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;작동한다&lt;/span&gt;&lt;span&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Delegation Model (&lt;/b&gt;&lt;span&gt;&lt;b&gt;위임&lt;/b&gt;&lt;/span&gt;&lt;b&gt; &lt;/b&gt;&lt;span&gt;&lt;b&gt;모델&lt;/b&gt;&lt;/span&gt;&lt;b&gt;)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1824&quot; data-origin-height=&quot;634&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/k7bid/btr4vI2LCa6/4xJ2TlW1ISIdgrvU1tnGIK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/k7bid/btr4vI2LCa6/4xJ2TlW1ISIdgrvU1tnGIK/img.png&quot; data-alt=&quot;그림5. geeksforgeeks.org에 명시된 그림&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/k7bid/btr4vI2LCa6/4xJ2TlW1ISIdgrvU1tnGIK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fk7bid%2Fbtr4vI2LCa6%2F4xJ2TlW1ISIdgrvU1tnGIK%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;1824&quot; height=&quot;634&quot; data-origin-width=&quot;1824&quot; data-origin-height=&quot;634&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림5. geeksforgeeks.org에 명시된 그림&lt;/figcaption&gt;
&lt;/figure&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;클래스로더는 위임-우선 모델이라는 방식을 따른다. 상위 계층의 클래스로더에게 클래스 로드 요청을 위임하고 상위 계층에서 클래스를 찾을 수 없거나 로드할 수 없는 경우에는 하위 계층 클래스로더에서 로드하는 방식이다. 만약, 하위 계층 클래스로더에서도 클래스를 찾을 수 없다면, ClassNotFoundException을 발생시킨다.&lt;/li&gt;
&lt;li&gt;과정을 살펴보면, 개발자가 작성한 Main 클래스를 로딩하는 과정에서 Application ClassLoader &amp;rarr; Extension ClassLoader &amp;rarr; Bootstrap ClassLoader로 loadClass() 메서드를 위임하고 상위&amp;nbsp;계층의&amp;nbsp;클래스로더에서&amp;nbsp;loadClass()&amp;nbsp;메서드로&amp;nbsp;클래스를&amp;nbsp;찾지&amp;nbsp;못하면&amp;nbsp;하위&amp;nbsp;계층으로&amp;nbsp;내려간다.&lt;/li&gt;
&lt;li&gt;Bootstrap ClassLoader &amp;rarr; Extension ClassLoader &amp;rarr; Application ClassLoader &lt;span&gt;순으로&lt;/span&gt; &lt;span&gt;클래스를&lt;/span&gt; &lt;span&gt;찾고&lt;/span&gt;, &lt;span&gt;찾지&lt;/span&gt; &lt;span&gt;못하면&lt;/span&gt; &lt;span&gt;최종적으로&lt;/span&gt; ClassNotFoundException&lt;span&gt;을&lt;/span&gt; &lt;span&gt;발생시킨다&lt;/span&gt;. &lt;span&gt;이렇게&lt;/span&gt; &lt;span&gt;런타임&lt;/span&gt; &lt;span&gt;과정에서&lt;/span&gt; JVM&lt;span&gt;이&lt;/span&gt; &lt;span&gt;예외를&lt;/span&gt; &lt;span&gt;발생시키기&lt;/span&gt; &lt;span&gt;때문에&lt;/span&gt; &lt;span&gt;명시적으로&lt;/span&gt; &lt;span&gt;처리하지&lt;/span&gt; &lt;span&gt;않으면&lt;/span&gt; &lt;span&gt;안돼서&lt;/span&gt; ClassNotFoundException&lt;span&gt;은&lt;/span&gt; Runtime Exception&lt;span&gt;을&lt;/span&gt; &lt;span&gt;상속하지&lt;/span&gt; &lt;span&gt;않는&lt;/span&gt; Checked Exception&lt;span&gt;인&lt;/span&gt; &lt;span&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;b&gt;Visibility Principle (가시성 원칙)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;가시성 원칙은 하위 계층의 클래스로더는 상위 계층의 클래스로더가 로드한 클래스를 볼 수 있지만, 상위 계층의 클래스로더는 하위 계층의 클래스로더가 로드한 클래스를 볼 수 없는 것을 의미한다.&lt;/li&gt;
&lt;li&gt;쉽게 말해서, 최상위 계층의 클래스로더인 Bootstrap ClassLoader에서 rt.jar을 로드하고 개발자가 작성한 클래스는 Application ClassLoader가 로드한다고 하였다. rt.jar 내부에는 java.lang 같이 우리가 흔히 사용하는 라이브러리가 있는데, 만약, 개발자가 작성한 Main 클래스에서 상위 계층 클래스로더가 로드한 java.lang.String을 볼 수 없다면 String을 사용할 수 없을 것이다.&lt;/li&gt;
&lt;li&gt;그런데 java.lang.String에서는 Main 클래스를 굳이 볼 필요가 없다. 이런 이유로 하위에서 상위를 볼 수 있지만, 상위에서는 하위를 볼 수 없는 것이 가시성 원칙이다.&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Uniqueness Property (유일성 속성)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;유일성 속성은 클래스를 정확히 &quot;한 번&quot;만 로드하여 클래스가 유일하고 반복되지 않도록 하는 것이다.&lt;/li&gt;
&lt;li&gt;하위 계층의 클래스로더가 상위 계층의 클래스로더가 이미 로드한 클래스를 다시 로드하지 않아야된다는 의미이다. 이는 클래스의 유일성을 보장하도록 하는 것이다.&lt;/li&gt;
&lt;li&gt;유일성을 식별하는 기준은 클래스의 바이너리 이름이다. 에를 들어, toString() 메서드를 찍어봤을 때 java.lang.String이라고 나오는 것을 말한다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Unload Impossibility (언로드 불가)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;클래스로더는 클래스를 로드할 수는 있지만, 언로드 할 수는 없다. 일반적으로 클래스로더가 로드한 클래스는 Garbage Collector의 수거 대상이 되지 않기 때문이다.&lt;/li&gt;
&lt;li&gt;대신, 현재 클래스로더를 삭제하고 아예 새로운 클래스로더를 생성하는 방법을 사용할 수 있다. 위에서 User-defined ClassLoader를 사용하는 이유에 대해서 클래스를 동적으로 로드하고 언로드하기 위하여 이야기했던게 바로 이것이다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게&lt;span&gt; &lt;/span&gt;클래스로더와&lt;span&gt; &lt;/span&gt;원칙에&lt;span&gt; &lt;/span&gt;관하여&lt;span&gt; &lt;/span&gt;이해하면&lt;span&gt; &lt;/span&gt;클래스로더가&lt;span&gt; Byte Code(.class)&lt;/span&gt;로부터&lt;span&gt; &lt;/span&gt;클래스를&lt;span&gt; &lt;/span&gt;로드하는&lt;span&gt; &lt;/span&gt;과정을&lt;span&gt; &lt;/span&gt;이해할&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있다&lt;span&gt;. &lt;/span&gt;위에서&lt;span&gt; &lt;/span&gt;잠깐&lt;span&gt; &lt;/span&gt;언급한&lt;span&gt; &lt;/span&gt;내용인데&lt;span&gt;&amp;nbsp;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;Java 8&lt;/b&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;의&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;클래스로더와&lt;/b&gt;&lt;b&gt; Java 9 &lt;/b&gt;&lt;b&gt;이후는&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;어떻게&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;클래스로더가&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;다를까&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;?&lt;/span&gt;&amp;nbsp;&lt;/b&gt;Java 9&lt;/span&gt;에서는&lt;span&gt; &lt;/span&gt;모듈&lt;span&gt; &lt;/span&gt;시스템이&lt;span&gt; &lt;/span&gt;도입되었다고&lt;span&gt; &lt;/span&gt;했었다&lt;span&gt;. &lt;/span&gt;이로&lt;span&gt; &lt;/span&gt;인하여&lt;span&gt; &lt;/span&gt;무겁던&lt;span&gt; rt.jar&lt;/span&gt;이&lt;span&gt; &lt;/span&gt;사라지고&lt;span&gt; &lt;/span&gt;로드할&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있는&lt;span&gt; &lt;/span&gt;클래스의&lt;span&gt; &lt;/span&gt;범위가&lt;span&gt; &lt;/span&gt;전반적으로&lt;span&gt; &lt;/span&gt;축소되면서&lt;span&gt; &lt;/span&gt;클래스로더&lt;span&gt; &lt;/span&gt;별로&lt;span&gt; &lt;/span&gt;담당하는&lt;span&gt; &lt;/span&gt;부분이나&lt;span&gt; &lt;/span&gt;클래스로더의&lt;span&gt; &lt;/span&gt;이름이&lt;span&gt; &lt;/span&gt;바뀌게&lt;span&gt; &lt;/span&gt;되었다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;567&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/eI0FLs/btr4voJ67uk/f7ldhJeG8Kytw0vuFgH9DK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/eI0FLs/btr4voJ67uk/f7ldhJeG8Kytw0vuFgH9DK/img.png&quot; data-alt=&quot;그림6. https://hackernoon.com/understanding-java-9-modules-7f573vfe에 명시된 그림&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/eI0FLs/btr4voJ67uk/f7ldhJeG8Kytw0vuFgH9DK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FeI0FLs%2Fbtr4voJ67uk%2Ff7ldhJeG8Kytw0vuFgH9DK%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;567&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;567&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림6. https://hackernoon.com/understanding-java-9-modules-7f573vfe에 명시된 그림&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;2876&quot; data-origin-height=&quot;1772&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/tUH3y/btr4xjuugAT/7eqAss1XiLf6zH9ZP7cHx0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/tUH3y/btr4xjuugAT/7eqAss1XiLf6zH9ZP7cHx0/img.png&quot; data-alt=&quot;그림7. Java 9부터 Class Loader의 계층구조&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/tUH3y/btr4xjuugAT/7eqAss1XiLf6zH9ZP7cHx0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FtUH3y%2Fbtr4xjuugAT%2F7eqAss1XiLf6zH9ZP7cHx0%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;2876&quot; height=&quot;1772&quot; data-origin-width=&quot;2876&quot; data-origin-height=&quot;1772&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림7. Java 9부터 Class Loader의 계층구조&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;Bootstrap Class Loader&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Java 9부터의 모듈 시스템으로 rt.jar과 tools.jar 등이 없어지면서 로드할 수 있는 클래스의 범위가 전반적으로 축소되었다.&lt;/li&gt;
&lt;li&gt;rt.jar과 tools.jar 안에 있던 내용들은 모듈 시스템에 맞게 더 효율적으로 재편되어 lib 디렉토리에 저장되었다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Platform Class Loader&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Extension ClassLoader &amp;rarr; Platform ClassLoader로 이름이 변경되었다.&lt;/li&gt;
&lt;li&gt;Java 9부터의 모듈 시스템으로 jre/lib/ext 등이 없어지면서 jre/lib/ext를 지원하지 않는다.&lt;/li&gt;
&lt;li&gt;Java SE 플랫폼의 모든 클래스를 Platform ClassLoader를 통해 볼 수 있다.&lt;/li&gt;
&lt;li&gt;Java SE 플랫폼이 아니지만, JCP(Java Community Process)에 의해 표준화 된 모듈 내의 클래스도 볼 수 있다.&lt;/li&gt;
&lt;li&gt;결과적으로 Java 8의 Extension ClassLoader에 비해 볼 수 있는 범위가 확장되었다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;System Class Loader&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Application ClassLoader&amp;nbsp;&amp;rarr;&amp;nbsp; System ClassLoader로 이름이 변경되었다.&lt;/li&gt;
&lt;li&gt;Class-Path&lt;span&gt;와&lt;/span&gt; &lt;span&gt;더불어&lt;/span&gt; Module-Path&lt;span&gt;에&lt;/span&gt; &lt;span&gt;있는&lt;/span&gt; &lt;span&gt;클래스를&lt;/span&gt; &lt;span&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;ClassLoader &lt;/b&gt;&lt;span&gt;&lt;b&gt;작동&lt;/b&gt;&lt;/span&gt;&lt;b&gt; &lt;/b&gt;&lt;span&gt;&lt;b&gt;원리&lt;/b&gt;&lt;/span&gt;&lt;b&gt; - Link, Initialize&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;2156&quot; data-origin-height=&quot;1200&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/wdUt3/btr4wNbxHsz/Uq0NHaiXX9hAN6FVkE0iJ0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/wdUt3/btr4wNbxHsz/Uq0NHaiXX9hAN6FVkE0iJ0/img.png&quot; data-alt=&quot;그림8. ClassLoader의 Link, Initialize 과정&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/wdUt3/btr4wNbxHsz/Uq0NHaiXX9hAN6FVkE0iJ0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FwdUt3%2Fbtr4wNbxHsz%2FUq0NHaiXX9hAN6FVkE0iJ0%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;2156&quot; height=&quot;1200&quot; data-origin-width=&quot;2156&quot; data-origin-height=&quot;1200&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림8. ClassLoader의 Link, Initialize 과정&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;Load 단계에서 Byte Code(.class) 파일을 가져와서 JVM의 메모리에 로드하고 난 이후, Link 단계에서는 Byte Code(.class) 파일 내의 symbolic references를 실제 메모리 주소로 변환하는 작업을 수행한다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Verifying (검증)&lt;/b&gt; : 읽은 Byte Code(.class) 파일이 Java 명세 및 JVM 명세에 명시된 대로 잘 구성되었는지 검사한다. 클래스 로드의 전 과정에서 가장 까다로운 검사를 수행하는 과정이라서 가장 복잡하고 시간이 많이 걸린다. Bytecode format, version number 등을 확인하는 단계이다. 만약 검증이 실패한다면 런타임 에러(java.lang.VerifyError)가 발생한다.&lt;/p&gt;
&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;Preparing (준비)&lt;/b&gt; : 클래스가 필요로 하는 메모리를 할당하는 단계이다. 클래스에서 정의된 필드, 메서드, 인터페이스들을 나타내는 데이터 구조를 준비한다. 이때 중요한 점은 static variable이 default로 초기화된다는 것이다. 예를 들어, boolean 타입의 static variable을 true로 설정하더라도 preparing 단계에서 해당 변수는 false로 초기화된다.&lt;/p&gt;
&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;Resolving (분석)&lt;/b&gt; : Resolving 단계에서는 class, field, method 그리고 constant pool 내 모든 symbolic references를 실제 메모리 주소로 변환한다. symbolic&amp;nbsp;reference란&amp;nbsp;우리가&amp;nbsp;코드를&amp;nbsp;작성하면서&amp;nbsp;사용한&amp;nbsp;class,&amp;nbsp;field,&amp;nbsp;method의&amp;nbsp;이름을&amp;nbsp;지칭한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Link 단계가 끝나면 &lt;b&gt;Initializing(초기화&lt;/b&gt;)을 실시하는데, static initializer들을 수행하고 statc variable들을 개발자가 설정한 값으로 초기화한다는 의미이다.&lt;/p&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;정리하자면, 최종적으로 Byte Code(.class) 파일이 클래스로더에 의해 JVM 메모리를 할당받고 올라가면서 JVM 메모리인 Runtime Data Areas에서 본격적으로 사용할 준비가 끝난 것이다. 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;&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;&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&gt;&lt;a title=&quot;Okky의 Java를 잘 이해하고 계신가요? &quot; href=&quot;https://okky.kr/articles/1390807&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span&gt;&lt;b&gt;Okky의 Java를 잘 이해하고 계신가요?&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;a title=&quot;네이버 D2 - JVM Internal&quot; href=&quot;https://d2.naver.com/helloworld/1230&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span&gt;&lt;b&gt;네이버 D2 - JVM Internal&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;a title=&quot;geeksforgeeks ClassLoader&quot; href=&quot;https://www.geeksforgeeks.org/classloader-in-java/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span&gt;&lt;b&gt;geeksforgeeks ClassLoader&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;a title=&quot;HomoEfficio님의 Java 클래스로더 훑어보기 포스팅&quot; href=&quot;https://homoefficio.github.io/2018/10/13/Java-%ED%81%B4%EB%9E%98%EC%8A%A4%EB%A1%9C%EB%8D%94-%ED%9B%91%EC%96%B4%EB%B3%B4%EA%B8%B0/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;HomoEfficio님의 Java 클래스로더 훑어보기 포스팅&lt;/b&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a title=&quot;kkang-joo님의 [JAVA] ClassLoader 포스팅&quot; href=&quot;https://kkang-joo.tistory.com/10?category=1031870&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;kkang-joo님의 [JAVA] ClassLoader 포스팅&lt;/b&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;a title=&quot;Oracle docs JVM chap5&quot; href=&quot;https://docs.oracle.com/javase/specs/jvms/se11/html/jvms-5.html#jvms-5.2&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span&gt;&lt;b&gt;Oracle docs JVM chap5&lt;/b&gt;&lt;/span&gt;&lt;/a&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;u&gt;&lt;b&gt;※&amp;nbsp;본&amp;nbsp;게시글은&amp;nbsp;공부하면서&amp;nbsp;작성했기에&amp;nbsp;틀린&amp;nbsp;부분이&amp;nbsp;있을&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;질문&amp;nbsp;사항이나&amp;nbsp;댓글로&amp;nbsp;알려주시면&amp;nbsp;감사하겠습니다.&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;</description>
      <category>Language/Java</category>
      <category>ClassLoader</category>
      <category>Dynamic Loading</category>
      <category>JVM</category>
      <category>JVM ClassLoader</category>
      <category>자바 동적로딩</category>
      <category>클래스로더</category>
      <author>Dev Uni</author>
      <guid isPermaLink="true">https://jae-yoon.tistory.com/16</guid>
      <comments>https://jae-yoon.tistory.com/16#entry16comment</comments>
      <pubDate>Sat, 18 Mar 2023 04:41:13 +0900</pubDate>
    </item>
    <item>
      <title>[Java의 실행원리 1편] Compile-time 환경</title>
      <link>https://jae-yoon.tistory.com/15</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;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;span&gt;&lt;a title=&quot;[Java의 실행원리 0편] 시리즈 개요&quot; href=&quot;https://jae-yoon.tistory.com/14&quot;&gt;&lt;span&gt;&lt;b&gt;[Java의 실행원리 0편] 시리즈 개요&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;b&gt;[Java의 실행원리 1편] Compile-time 환경&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;a title=&quot;[Java의 실행원리 2편] Runtime 환경 - JVM Class Loader&quot; href=&quot;https://jae-yoon.tistory.com/16&quot;&gt;&lt;span&gt;&lt;b&gt;[Java의 실행원리 2편] Runtime 환경 - JVM Class Loader&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;a title=&quot;[Java의 실행원리 3편] Runtime 환경 - JVM Memory, Runtime Data Areas&quot; href=&quot;https://jae-yoon.tistory.com/17&quot;&gt;&lt;b&gt;[Java의 실행원리 3편] Runtime 환경 - JVM Memory, Runtime Data Areas&lt;/b&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a title=&quot;[Java의 실행원리 4편] Runtime 환경 - JVM Execute Engine&quot; href=&quot;https://jae-yoon.tistory.com/18&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;[Java의 실행원리 4편] Runtime 환경 - JVM Execute Engine&lt;/b&gt;&lt;/a&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;1편에서는 JVM, JRE, JDK에 관한 설명을 하며 Java 8 이후부터는 런타임 이미지가 어떤 식으로 변경되었는지를 알아보며 간단하게 모듈화에 대한 이야기를 하고 Java Compiler를 통하여 Source Code(.java)가 Byte Code(.class)로 변경되어가는 과정을 상세하게 살펴볼 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;JVM, JRE, JDK&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실행원리를&lt;span&gt; &lt;/span&gt;설명하기&lt;span&gt; &lt;/span&gt;위해&lt;span&gt;, &lt;/span&gt;해당하는&lt;span&gt; &lt;/span&gt;용어들에&lt;span&gt; &lt;/span&gt;대하여&lt;span&gt; &lt;/span&gt;살펴보겠다&lt;span&gt;. Java&lt;/span&gt;를&lt;span&gt; &lt;/span&gt;설치하기&lt;span&gt; &lt;/span&gt;위해&lt;span&gt; &lt;/span&gt;사이트에&lt;span&gt; &lt;/span&gt;들어가보면&lt;span&gt;,&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1782&quot; data-origin-height=&quot;538&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/FjegF/btr4tLzjBR9/nIegF3imrbXUkYJX4lqZ11/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/FjegF/btr4tLzjBR9/nIegF3imrbXUkYJX4lqZ11/img.png&quot; data-alt=&quot;그림1. Oracle JDK download site&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/FjegF/btr4tLzjBR9/nIegF3imrbXUkYJX4lqZ11/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FFjegF%2Fbtr4tLzjBR9%2FnIegF3imrbXUkYJX4lqZ11%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;1782&quot; height=&quot;538&quot; data-origin-width=&quot;1782&quot; data-origin-height=&quot;538&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림1. Oracle JDK download site&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JDK (Java Development Kit), JRE (Java Runtime Environment)가 보인다. 여기서 알 수 있는 정보는 세 가지가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;JDK가 JRE보다 용량이 크다&lt;/li&gt;
&lt;li&gt;&lt;a title=&quot;[Java의 실행원리 개요] 시리즈 개요&quot; href=&quot;https://jae-yoon.tistory.com/14&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span&gt;&lt;b&gt;[Java의 실행원리 개요] 시리즈 개요&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&amp;nbsp;그림에서 봤던 Runtime Environment가 JRE이다.&lt;/li&gt;
&lt;li&gt;운영체제 별로 다운받아야 된다.&lt;/li&gt;
&lt;/ol&gt;
&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;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;JDK가 JRE를 포함하면서 추가적인 어떤 것들이 있을 수 있겠구나.&lt;/li&gt;
&lt;li&gt;Runtime Environment 내부에 JVM이 있었는데 JVM이 포함됐을 수 있겠구나.&lt;/li&gt;
&lt;li&gt;JVM이 운영체제마다 다르다는 의미일 수 있겠구나.&lt;/li&gt;
&lt;/ol&gt;
&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;JDK&lt;/span&gt;의&lt;span&gt; &lt;/span&gt;내부를&lt;span&gt; &lt;/span&gt;보니&lt;span&gt;,&amp;nbsp;&lt;/span&gt;역시&lt;span&gt; JDK&lt;/span&gt;안에는&lt;span&gt; JRE&lt;/span&gt;가&lt;span&gt; &lt;/span&gt;포함되어&lt;span&gt; &lt;/span&gt;있었다&lt;span&gt;. &lt;/span&gt;이외에도&lt;span&gt; lib&lt;/span&gt;와&lt;span&gt; &lt;/span&gt;같이&lt;span&gt; &lt;/span&gt;추가적인&lt;span&gt; &lt;/span&gt;것들을&lt;span&gt; &lt;/span&gt;확인할&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2092&quot; data-origin-height=&quot;464&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/br6Tqs/btr4DtJYXhm/kWMfhQREgpJkvRnqP0dbXk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/br6Tqs/btr4DtJYXhm/kWMfhQREgpJkvRnqP0dbXk/img.png&quot; data-alt=&quot;그림2. zulu OpenJDK download&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/br6Tqs/btr4DtJYXhm/kWMfhQREgpJkvRnqP0dbXk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbr6Tqs%2Fbtr4DtJYXhm%2FkWMfhQREgpJkvRnqP0dbXk%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;2092&quot; height=&quot;464&quot; data-origin-width=&quot;2092&quot; data-origin-height=&quot;464&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림2. zulu OpenJDK download&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;JDK&lt;span&gt;의&lt;/span&gt; Library&lt;span&gt;에는&lt;/span&gt; &lt;span&gt;추가적인&lt;/span&gt; &lt;span&gt;도구가&lt;/span&gt; &lt;span&gt;있었고&lt;/span&gt;, JRE&lt;span&gt;의&lt;/span&gt; Library &lt;span&gt;안에는&lt;/span&gt; &lt;span&gt;굉장히&lt;/span&gt; &lt;span&gt;많은&lt;/span&gt; &lt;span&gt;파일과&lt;/span&gt; JVM&lt;span&gt;이&lt;/span&gt; &lt;span&gt;있는&lt;/span&gt; &lt;span&gt;것을&lt;/span&gt; &lt;span&gt;확인했다&lt;/span&gt;.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2066&quot; data-origin-height=&quot;788&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cOe3bQ/btr4wF5MvZO/s1UxwvOwJoLM3TPyZreQH1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cOe3bQ/btr4wF5MvZO/s1UxwvOwJoLM3TPyZreQH1/img.png&quot; data-alt=&quot;그림3. JDK lib와 JRE lib 폴더 내부&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cOe3bQ/btr4wF5MvZO/s1UxwvOwJoLM3TPyZreQH1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcOe3bQ%2Fbtr4wF5MvZO%2Fs1UxwvOwJoLM3TPyZreQH1%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;2066&quot; height=&quot;788&quot; data-origin-width=&quot;2066&quot; data-origin-height=&quot;788&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림3. JDK lib와 JRE lib 폴더 내부&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;background-color: #f6e199;&quot;&gt;&lt;b&gt;J&lt;/b&gt;&lt;b&gt;VM(Java Virtual Machine) =&amp;nbsp;JIT Compiler + Java Interpreter + Garbage Collector&lt;/b&gt;&lt;/span&gt;&amp;nbsp;: 자바 가상머신이다. Source Code(.java)가 Java Compiler(javac)를 거쳐서 Byte Code(.class)가 되면, 이 byte code를 host 운영체제 위에서 실행할 수 있도록 하는 환경이다. 즉, 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;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;JRE(Java Runtime Environment) = JVM + Library Classes&lt;/b&gt;&lt;/span&gt; : Java 애플리케이션이 &quot;실행&quot;될 수 있는 최소한의 환경으로, JRE가 설치되어 있으면 애플리케이션을 실행하는 것에는 문제가 없다. 그러나, 개발을 위한 도구인 컴파일러나 디버거는 없다. JVM, 필수 라이브러리(rt.jar) 등이 있다. 이때, rt는 Runtime을 의미하는 것으로, String 클래스, System 클래스 등이 속한다.&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;JDK(Java Development Kit) = JRE&amp;nbsp;+&amp;nbsp;Development&amp;nbsp;Tool&lt;/b&gt;&lt;/span&gt;&amp;nbsp;: &lt;span&gt;개발&lt;/span&gt; &lt;span&gt;도구라는&lt;/span&gt; &lt;span&gt;이름에서&lt;/span&gt; &lt;span&gt;알&lt;/span&gt; &lt;span&gt;수&lt;/span&gt; &lt;span&gt;있듯이&lt;/span&gt;, Java &lt;span&gt;애플리케이션을&lt;/span&gt; &quot;&lt;span&gt;개발&lt;/span&gt;&quot;&lt;span&gt;할&lt;/span&gt; &lt;span&gt;수&lt;/span&gt; &lt;span&gt;있는&lt;/span&gt; &lt;span&gt;도구&lt;/span&gt; &lt;span&gt;모음이다&lt;/span&gt;. &lt;span&gt;실행될&lt;/span&gt; &lt;span&gt;수&lt;/span&gt; &lt;span&gt;있는&lt;/span&gt; &lt;span&gt;최소한의&lt;/span&gt; &lt;span&gt;환경인&lt;/span&gt; JRE&lt;span&gt;와&lt;/span&gt; &lt;span&gt;개발을&lt;/span&gt; &lt;span&gt;위한&lt;/span&gt; Java Compiler(javac), 역어셈블러(javap),&amp;nbsp; Debugger &lt;span&gt;등&lt;/span&gt; &lt;span&gt;도구가&lt;/span&gt; &lt;span&gt;있다&lt;/span&gt;.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JVM이 Java를 실행하는 것에 있어서 핵심적인 요소임은 파악하였다. 자바를 위한 가상머신이라는 건데, &lt;u&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;JVM의 특징&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;스택 기반 가상머신&lt;/span&gt;&lt;/b&gt; : 인텔 x86 아키텍처, ARM 아키텍처와 같은 하드웨어가 레지스터 기반으로 동작하는 것과는 다르게 JVM은 스택 기반으로 동작한다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;심볼릭 레퍼런스&lt;/b&gt;&lt;/span&gt; : 기본 자료형(primitive data type)을 제외한 모든 타입(클래스, 인터페이스)을 명시적인 메모리 주소 기반의 레퍼런스가 아니라 심볼릭 레퍼런스를 통해 참조. (기본 자료형은 명시적인 메모리 주소 기반의 레퍼런스)&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;가비지 컬렉션&lt;/b&gt;&lt;/span&gt; : 클래스 인스턴스는 사용자 코드에 의해 명시적으로 생성되지만, 그 이후에는 GC가 알아서 없애준다.&lt;/li&gt;
&lt;li&gt;&lt;span style=&quot;background-color: #f6e199;&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;&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;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Java 8 이후에는 어떻게 되었나?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;내&lt;/span&gt; &lt;span&gt;로컬에는&lt;/span&gt; &lt;span&gt;유명한&lt;/span&gt; LTS &lt;span&gt;버전인&lt;/span&gt; Java 8, 11, 17 &lt;span&gt;이렇게&lt;/span&gt; &lt;span&gt;세&lt;/span&gt; &lt;span&gt;버전이&lt;/span&gt; &lt;span&gt;있어서&lt;/span&gt; &lt;span&gt;내부를&lt;/span&gt; &lt;span&gt;봤는데&lt;/span&gt;, &lt;span&gt;어라&lt;/span&gt;? &lt;span&gt;자바&lt;/span&gt; 11&lt;span&gt;부터는&lt;/span&gt; jdk &lt;span&gt;내부에&lt;/span&gt; jre&lt;span&gt;가&lt;/span&gt; &lt;span&gt;없었다&lt;/span&gt;.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2062&quot; data-origin-height=&quot;416&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/GP4nz/btr4DsRP94d/2FdXCk1jhEHNPWPaK2pkj0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/GP4nz/btr4DsRP94d/2FdXCk1jhEHNPWPaK2pkj0/img.png&quot; data-alt=&quot;그림4. Java 11 JDK 폴더 구조&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/GP4nz/btr4DsRP94d/2FdXCk1jhEHNPWPaK2pkj0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FGP4nz%2Fbtr4DsRP94d%2F2FdXCk1jhEHNPWPaK2pkj0%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;2062&quot; height=&quot;416&quot; data-origin-width=&quot;2062&quot; data-origin-height=&quot;416&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림4. Java 11 JDK 폴더 구조&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;a title=&quot;Oracle Java11 downloads&quot; href=&quot;https://www.oracle.com/kr/java/technologies/downloads/#java11&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;Oracle Java11 downloads&lt;/b&gt;&lt;/a&gt; 오라클 홈페이지의 Java 11 다운로드 페이지에 가보면 JDK만 있고 따로 JRE를 찾을 수 없었다. 이는&amp;nbsp;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;JDK 9부터 JRE가 별도로 제공되지 않고 JDK에 포함되어 있기 때문이다.&lt;/b&gt;&lt;/span&gt;&amp;nbsp;엥!? JDK 8에도 JRE가 포함되어있다면서!!&lt;/p&gt;
&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;a title=&quot;Java 8에서 Java 9로 마이그레이션 하는 방법&quot; href=&quot;https://docs.oracle.com/javase/9/migrate/toc.htm#JSMIG-GUID-D867DCCC-CEB5-4AFA-9D11-9C62B7A3FAB1&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;Java 8에서 Java 9로 마이그레이션 하는 방법&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;공식문서를 참고해보면, 런타임 이미지를 생성하는 방식이 바뀌었다고 한다. 참고로, 런타임 이미지란 컴퓨터 프로그램이 실행될 때 메모리에 로드되는 실행 파일을 의미한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JDK 8까지의 런타임 이미지&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;JRE ( Java SE 플랫폼의 완전한 구현 )&lt;/li&gt;
&lt;li&gt;JDK ( jre/ 라는 디렉토리에 전체 JRE와 개발 도구 및 라이브러리 포함)&lt;/li&gt;
&lt;li&gt;두 런타임 이미지 모두 비모듈식&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JDK 9부터의 런타임 이미지&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;JRE, JDK 모두 아래의 디렉토리를 포함하는 런타임 이미지&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&gt; &lt;/span&gt;바탕으로&lt;span&gt; &lt;/span&gt;디렉토리&lt;span&gt; &lt;/span&gt;구조는&lt;span&gt; &lt;/span&gt;아래와&lt;span&gt; &lt;/span&gt;같은&lt;span&gt; &lt;/span&gt;형식이&lt;span&gt; &lt;/span&gt;된다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1498&quot; data-origin-height=&quot;664&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Nrpuv/btr4viQL7xZ/2EhPJinFZCUNnRYuLGKKl0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Nrpuv/btr4viQL7xZ/2EhPJinFZCUNnRYuLGKKl0/img.png&quot; data-alt=&quot;그림5. https://hackernoon.com/understanding-java-9-modules-7f573vfe의 그림&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Nrpuv/btr4viQL7xZ/2EhPJinFZCUNnRYuLGKKl0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNrpuv%2Fbtr4viQL7xZ%2F2EhPJinFZCUNnRYuLGKKl0%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;1498&quot; height=&quot;664&quot; data-origin-width=&quot;1498&quot; data-origin-height=&quot;664&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림5. https://hackernoon.com/understanding-java-9-modules-7f573vfe의 그림&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&gt; JDK 9&lt;/span&gt;부터는&lt;span&gt; &lt;/span&gt;기존의&lt;span&gt; &lt;/span&gt;모놀리틱한&lt;span&gt; JDK&lt;/span&gt;가&lt;span&gt; &lt;/span&gt;각각의&lt;span&gt; &lt;/span&gt;모듈로&lt;span&gt; &lt;/span&gt;분리되어&lt;span&gt; &lt;/span&gt;별도의&lt;span&gt; &lt;/span&gt;배포&lt;span&gt; &lt;/span&gt;없이&lt;span&gt; &lt;/span&gt;모듈화된&lt;span&gt; JRE&lt;/span&gt;가&lt;span&gt; JDK&lt;/span&gt;에&lt;span&gt; &lt;/span&gt;포함되어&lt;span&gt; &lt;/span&gt;제공된다고&lt;span&gt; &lt;/span&gt;한다&lt;span&gt;. &lt;/span&gt;하지만&lt;span&gt; JDK 9 &lt;/span&gt;이전&lt;span&gt; &lt;/span&gt;버전에서는&lt;span&gt; JDK&lt;/span&gt;와&lt;span&gt; JRE&lt;/span&gt;가&lt;span&gt; &lt;/span&gt;다른&lt;span&gt; &lt;/span&gt;유형의&lt;span&gt; &lt;/span&gt;런타임&lt;span&gt; &lt;/span&gt;이미지였어서&lt;span&gt; JDK&lt;/span&gt;와&lt;span&gt; JRE&lt;/span&gt;를&lt;span&gt; &lt;/span&gt;모두&lt;span&gt; &lt;/span&gt;설치했어야&lt;span&gt; &lt;/span&gt;하는데&lt;span&gt; &lt;/span&gt;공식&lt;span&gt; &lt;/span&gt;홈페이지에서&lt;span&gt; JDK&lt;/span&gt;를&lt;span&gt; &lt;/span&gt;설치하면&lt;span&gt; JRE&lt;/span&gt;도&lt;span&gt; &lt;/span&gt;같이&lt;span&gt; &lt;/span&gt;설치되는&lt;span&gt; &lt;/span&gt;원리였던&lt;span&gt; &lt;/span&gt;것이다&lt;span&gt;. &lt;/span&gt;그렇다면&lt;span&gt;, &lt;/span&gt;여기서&lt;span&gt; &lt;/span&gt;확장&lt;span&gt; &lt;/span&gt;가능한&lt;span&gt; &lt;/span&gt;생각이&lt;span&gt;&amp;nbsp;&lt;b&gt;J&lt;span style=&quot;background-color: #f6e199;&quot;&gt;ava 8&lt;/span&gt;&lt;/b&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;과&lt;/b&gt;&lt;b&gt; Java 11&lt;/b&gt;&lt;b&gt;의&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;차이점에는&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;모듈화라는&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;키워드가&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;추가되는&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;것&lt;/b&gt;&lt;/span&gt;이다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Java 9부터의 Modularization&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Modularization(모듈화)은 Java 9부터 도입된 기능으로, 코드를 모듈 단위로 나눌 수 있게 해준다. Java 모듈은 Java 애플리케이션 혹은 Java API를 별도의 Java 모듈로 패키징할 수 있는 패키징 매커니즘으로, Java 모듈은 모듈식 JAR 파일로 패키지된다. 쉽게 말하여, 모듈은 관련된 패키지, 타입, 코드, 데이터 및 정적 리소스 등을 모아놓은 단위로 패키지의 패키지, 패키지보다 상위, 패키지 관리 기능이 포함된 라이브러리를 모듈이라고 이해하면 된다.&lt;/p&gt;
&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;모듈은&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;왜&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;나오게&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;되었을까&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;?&lt;/b&gt;&lt;/span&gt;&amp;nbsp;&lt;/span&gt;자바가&lt;span&gt; &lt;/span&gt;더&lt;span&gt; &lt;/span&gt;많이&lt;span&gt; &lt;/span&gt;사용되고&lt;span&gt; &lt;/span&gt;규모가&lt;span&gt; &lt;/span&gt;커지면서&lt;span&gt;&amp;nbsp;&lt;/span&gt;기존의&lt;span&gt; &lt;/span&gt;방식만으로는&lt;span&gt; &lt;/span&gt;부족하여&lt;span&gt; &lt;/span&gt;여러&lt;span&gt; &lt;/span&gt;부분에서&lt;span&gt; &lt;/span&gt;문제가&lt;span&gt; &lt;/span&gt;생겼기&lt;span&gt; &lt;/span&gt;때문이다&lt;span&gt;. &lt;/span&gt;패키지의&lt;span&gt; &lt;/span&gt;부족함을&lt;span&gt; &lt;/span&gt;보완하기도&lt;span&gt; &lt;/span&gt;하며&lt;span&gt; &lt;/span&gt;모듈화의&lt;span&gt; &lt;/span&gt;부재로&lt;span&gt; &lt;/span&gt;인한&lt;span&gt; &lt;/span&gt;런타임의&lt;span&gt; &lt;/span&gt;거대화&lt;span&gt; &lt;/span&gt;등&lt;span&gt; &lt;/span&gt;문제점들을&lt;span&gt; &lt;/span&gt;어떻게&lt;span&gt; &lt;/span&gt;해결하였는지&lt;span&gt; &lt;/span&gt;살펴보자&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;1. 모듈식 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;Project Jigsaw의 일부로, 모든 Java 플랫폼 API가 별도의 모듈로 분할되었다.&amp;nbsp;Java 9 이전에는 모든 Java 플랫폼 API를 Java 애플리케이션과 함께 패키징해서 rt.jar라는 단 하나의 파일에 통합하여 배포하였는데, 이는 사용하지 않는 클래스 또한 배포에 포함된다는 의미로 비효율적이었고 이로 인해 스마트폰, 라즈베리 파이 같은 소형 장치에서 문제가 됐었다.&amp;nbsp;Java 9 이후에는 Java 애플리케이션에 필요한 Java 플랫폼의 모듈을 지정할 수 있게 돼서 애플리케이션이 실제로 사용하는 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;&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;2. 내부 패키지의 캡슐화&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;클래스, 패키지, JAR 세 가지 수준의 코드 그룹화를 제공하는데, 이 중 패키지와 JAR 수준에서 Java 9 이전까지는 캡슐화가 거의 지원되지 않았었다.&amp;nbsp;일반적인 라이브러리를 사용할 때는 내부에 포함된 모든 패키지에 외부 프로그램에서의 접근이 가능했었다. 하지만,&amp;nbsp;객체지향 프로그래밍에서 세부 구현을 숨기는 캡슐화는 필수적인 기법인데,&amp;nbsp;패키지의 캡슐화(Encapsulation)가 거의 지원되지 않았기에 문제가 생긴 것이다.&amp;nbsp;클래스에는 private을 붙이면서 정보 은닉이 쉬웠지만, 패키지는 그러한 작업이 힘들어서 여러 패키지에서 공용으로 사용되는 클래스를 은닉하기 힘들었고, 이는 라이브러리 내부 뿐만이 아니라 외부에서도 쉽게 사용할 수 있었다는 의미이다.&lt;/p&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 9 이전의 접근 제어자는 public, private, protected, default가 기본적이 었다면, Java 9부터는 기존의 private, protected, default와 더불어 public을 조금더 세세하게 나눴다. 외부에 모두 public, 특정 모듈에만 public, 모듈 내부만 public과 같이 exports 키워드와 requires 키워드를 이용하여 이를 사용한다. 내보내지(exports) 않은 패키지의 클래스는 다른 자바 모듈에서 사용할 수 없다. 이때 내보내지 않은 패키지는 숨겨진 패키지 또는 캡슐화 된 패키지라고 한다. 이렇게 클래스, 인터페이스, 메서드 등을 제외하고 패키지 단에서도 캡슐화가 가능해지며 한층 더 객체지향스러워 진 것이다.&lt;/p&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;3. 빌드 단계에서 누락된 모듈 감지&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;Java 9 이전에는 빌드 단계에서 프로그램 구동에 필요한 모든 클래스가 다 있는지 확인할 수 없었다.&amp;nbsp;자바는 동적 로딩(Dynamic Loading)을 통해 필요한 클래스를 실행 중에 로드하기 때문에 시작이 빠르고 생성할 클래스를 선택할 수 있지만 실행 직후에는 애플리케이션이 누락된 클래스를 사용하려고 시도하기 전까지 누락 사실을 알 수 없다. 클래스 누락을 방지하려면 실행 중에 로드되는 클래스가 다 있는지 수작업으로 일일이 확인하는 수 밖에 없었다는 의미이다.&lt;/p&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 9 이후에는 Java 애플리케이션도 Java 모듈로 패키징해야해서 애플리케이션 모듈은 사용하는 다른 모듈을 지정한다. 따라서, JVM이 시작될 때 애플리케이션 모듈에서 전체 모듈 종속성 그래프를 확인하고 필요한 모듈이 시작 시 발견되지 않으면 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 9&lt;span&gt;부터&lt;/span&gt; &lt;span&gt;추가된&lt;/span&gt; &lt;span&gt;모듈화로&lt;/span&gt; &lt;span&gt;인한&lt;/span&gt; &lt;span&gt;설명은&lt;/span&gt; &lt;span&gt;여기까지&lt;/span&gt; &lt;span&gt;하고&lt;/span&gt; &lt;span&gt;이제&lt;/span&gt; &lt;span&gt;본격적으로&lt;/span&gt; &lt;span&gt;자바&lt;/span&gt; &lt;span&gt;컴파일러를&lt;/span&gt; &lt;span&gt;통해&lt;/span&gt; &lt;span&gt;어떻게&lt;/span&gt; Source Code(.java)&lt;span&gt;가&lt;/span&gt; Byte Code(.class)&lt;span&gt;로&lt;/span&gt; &lt;span&gt;바뀌는지&lt;/span&gt; &lt;span&gt;알아보겠다&lt;/span&gt;.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Source Code&lt;/b&gt;&lt;span&gt;&lt;b&gt;가&lt;/b&gt;&lt;/span&gt;&lt;b&gt; Byte Code&lt;/b&gt;&lt;span&gt;&lt;b&gt;가&lt;/b&gt;&lt;/span&gt;&lt;b&gt; &lt;/b&gt;&lt;span&gt;&lt;b&gt;되기까지&lt;/b&gt;&lt;/span&gt;&lt;/h2&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1350&quot; data-origin-height=&quot;530&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1K9fR/btr4zbQolp4/Atv639PvkWdc3zLXQuOSwK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1K9fR/btr4zbQolp4/Atv639PvkWdc3zLXQuOSwK/img.png&quot; data-alt=&quot;그림6. Java 실행원리 - 컴파일시점 환경&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1K9fR/btr4zbQolp4/Atv639PvkWdc3zLXQuOSwK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1K9fR%2Fbtr4zbQolp4%2FAtv639PvkWdc3zLXQuOSwK%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;1350&quot; height=&quot;530&quot; data-origin-width=&quot;1350&quot; data-origin-height=&quot;530&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림6. Java 실행원리 - 컴파일시점 환경&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;a title=&quot;컴파일러와 인터프리터 &quot; href=&quot;https://jae-yoon.tistory.com/3&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span&gt;&lt;b&gt;컴파일러와 인터프리터&lt;/b&gt;&lt;/span&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/a&gt;게시글에서 설명했듯이, 사람이 작성한 High-Level Programming Language인 java 코드는 컴퓨터가 이해할 수 없어서 기계어까지 바꾸는 동작과정이 필요하다. Java는&amp;nbsp;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;한 번 작성하면, 어디서나 실행된다(Write once, run anywhere = WORA)&lt;/b&gt;&lt;/span&gt;는 가장 중요한 특징이 있는데 실행원리를 통하여 이를 이해할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;개발자가 작성한 Source Code (.java) 파일&lt;/li&gt;
&lt;li&gt;javac 명령어를 이용하여 Java Compiler에 Source Code 파일 넣기&lt;/li&gt;
&lt;li&gt;Intermidate Code인 Byte Code (.class) 파일 생성&lt;/li&gt;
&lt;/ol&gt;
&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;span&gt; Byte Code&lt;/span&gt;는&lt;span&gt; &lt;/span&gt;클래스&lt;span&gt; &lt;/span&gt;로더에&lt;span&gt; &lt;/span&gt;의하여&lt;span&gt; JVM&lt;/span&gt;의&lt;span&gt; &lt;/span&gt;메모리에&lt;span&gt; &lt;/span&gt;로드되고&lt;span&gt; &lt;/span&gt;연결하는&lt;span&gt; &lt;/span&gt;과정을&lt;span&gt; &lt;/span&gt;거친다&lt;span&gt;.&amp;nbsp; &lt;/span&gt;이&lt;span&gt; &lt;/span&gt;과정이&lt;span&gt; &lt;/span&gt;왜&lt;span&gt; Java&lt;/span&gt;는&lt;span&gt; &lt;/span&gt;한&lt;span&gt; &lt;/span&gt;번&lt;span&gt; &lt;/span&gt;작성&lt;span&gt;, &lt;/span&gt;어디서나&lt;span&gt; &lt;/span&gt;실행된다는&lt;span&gt; &lt;/span&gt;말일까&lt;span&gt;? &lt;/span&gt;분명히&lt;span&gt; Oracle JDK &lt;/span&gt;다운로드&lt;span&gt; &lt;/span&gt;홈페이지를&lt;span&gt; &lt;/span&gt;보면&lt;span&gt; &lt;/span&gt;아래와&lt;span&gt; &lt;/span&gt;같이&lt;span&gt; Linux, macOS, Windows&lt;/span&gt;로&lt;span&gt; &lt;/span&gt;운영체제마다&lt;span&gt; &lt;/span&gt;다르게&lt;span&gt; &lt;/span&gt;다운받는&lt;span&gt; &lt;/span&gt;것을&lt;span&gt; &lt;/span&gt;볼&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2448&quot; data-origin-height=&quot;1146&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bfsvom/btr4uI90Lke/Ghs1uD3SWB2fyA4S2TVop1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bfsvom/btr4uI90Lke/Ghs1uD3SWB2fyA4S2TVop1/img.png&quot; data-alt=&quot;그림7. Oracle JDK download&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bfsvom/btr4uI90Lke/Ghs1uD3SWB2fyA4S2TVop1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fbfsvom%2Fbtr4uI90Lke%2FGhs1uD3SWB2fyA4S2TVop1%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;2448&quot; height=&quot;1146&quot; data-origin-width=&quot;2448&quot; data-origin-height=&quot;1146&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림7. Oracle JDK download&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;&amp;nbsp;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;Java 언어 플랫폼 자체는 운영체제에 종속적이지 않고 독립적이지만, JVM은 운영체제에 종속적이다&lt;/span&gt;&lt;/b&gt;는 의미이다. 결국 Java 코드를 실행할 환경에 있어서는 각각의 OS에 맞는 JVM 설치가 필요하다. 그러면, 결국 OS에 맞는 JVM 설치가 필요한데 왜 Java가 OS에 독립적인 것이 장점일까?&lt;/p&gt;
&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;Java 코드가 OS에 독립적이라는 것은 Java 애플리케이션을 실행할 수 있는 모든 운영체제에서 동일한 코드가 작동할 수 있도록 보장한다는 의미다.&lt;/b&gt;&lt;/span&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;예를 들어, 내가 개발한 애플리케이션을 AWS EC2의 ubuntu에 배포하려는 상황을 상상해보자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;mac OS 환경에서 C/C++ 프로그램을 개발하여 컴파일하고 mac OS 환경에서 실행한다고 하면 아무 문제가 없다. 하지만, mac OS 환경에서 개발하고 컴파일한 C/C++ 파일을 ubuntu에 올려서 실행하면 작동하지 않는다. 일반적으로, C/C++는 하드웨어 아키텍처와 운영체제에 종속적이기 때문에 해당 운영체제에 맞게 컴파일하고 실행하는 과정이 필요하다. 만약, mac OS에서 개발한 프로그램을 다른 운영체제인 ubuntu에서 실행하려면, mac OS에서 타겟 플랫폼인 ubuntu에 맞춰 컴파일하는 &quot;크로스 컴파일&quot;이 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만, Java의 경우는 어떠한가? mac OS 환경에서 개발한 Java 애플리케이션을 ubuntu에 올리더라도 Java는 운영체제에 독립적이기 때문에 해당하는 서버의 OS에 맞는 JVM만 있다면 내가 빌드한 애플리케이션이 서버에서 작동한다는 것을 별다른 검증없이 보장할 수 있게 된다는 의미이다. 이렇게 비교해보니 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을 또 써야하냐는 질문이 있을 수 있다.&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&gt; mac OS&lt;/span&gt;에서&lt;span&gt; &lt;/span&gt;매번&lt;span&gt; &lt;/span&gt;프로그램을&lt;span&gt; &lt;/span&gt;만들때마다&lt;span&gt; window, linux &lt;/span&gt;뿐만이&lt;span&gt; &lt;/span&gt;아니라&lt;span&gt; &lt;/span&gt;모바일&lt;span&gt; &lt;/span&gt;환경&lt;span&gt; &lt;/span&gt;등&lt;span&gt; &lt;/span&gt;다양한&lt;span&gt; &lt;/span&gt;디바이스에&lt;span&gt; &lt;/span&gt;맞춰서&lt;span&gt; &lt;/span&gt;그때마다&lt;span&gt; &lt;/span&gt;크로스&lt;span&gt; &lt;/span&gt;컴파일하는&lt;span&gt; &lt;/span&gt;것과&lt;span&gt;, &lt;/span&gt;그냥&lt;span&gt; &lt;/span&gt;타겟에&lt;span&gt; JVM&lt;/span&gt;만&lt;span&gt; &lt;/span&gt;설치하면&lt;span&gt; &lt;/span&gt;되는&lt;span&gt; &lt;/span&gt;것&lt;span&gt;, &lt;/span&gt;둘&lt;span&gt; &lt;/span&gt;중&lt;span&gt; &lt;/span&gt;어느&lt;span&gt; &lt;/span&gt;것이&lt;span&gt; &lt;/span&gt;편하다고&lt;span&gt; &lt;/span&gt;생각하는가&lt;span&gt;? &lt;/span&gt;다양한&lt;span&gt; &lt;/span&gt;환경을&lt;span&gt; &lt;/span&gt;고려했을&lt;span&gt; &lt;/span&gt;때&lt;span&gt; &lt;/span&gt;나는&lt;span&gt; &lt;/span&gt;아무리&lt;span&gt; &lt;/span&gt;생각해도&lt;span&gt; &lt;/span&gt;후자인&lt;span&gt; &lt;/span&gt;것&lt;span&gt; &lt;/span&gt;같다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Java Compiler 동작과정&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;그렇다면&lt;/span&gt;, Java Compiler&lt;span&gt;는&lt;/span&gt; &lt;span&gt;어떻게&lt;/span&gt; &lt;span&gt;고수준&lt;/span&gt; &lt;span&gt;언어인&lt;/span&gt; Java&lt;span&gt;를&lt;/span&gt; Byte Code&lt;span&gt;로&lt;/span&gt; &lt;span&gt;변환할까&lt;/span&gt;? &lt;span&gt;기본적인&lt;/span&gt; &lt;span&gt;컴파일러의&lt;/span&gt; &lt;span&gt;원리를&lt;/span&gt; &lt;span&gt;살펴보자&lt;/span&gt;.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1502&quot; data-origin-height=&quot;924&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/Uhje5/btr4t5j33t3/eNoFpqVXHYQ8WUpC5YQJ9K/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/Uhje5/btr4t5j33t3/eNoFpqVXHYQ8WUpC5YQJ9K/img.png&quot; data-alt=&quot;그림8. 컴파일러의 Front-End와 Back-End&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/Uhje5/btr4t5j33t3/eNoFpqVXHYQ8WUpC5YQJ9K/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FUhje5%2Fbtr4t5j33t3%2FeNoFpqVXHYQ8WUpC5YQJ9K%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;1502&quot; height=&quot;924&quot; data-origin-width=&quot;1502&quot; data-origin-height=&quot;924&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림8. 컴파일러의 Front-End와 Back-End&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&gt; &lt;/span&gt;소스&lt;span&gt; &lt;/span&gt;코드를&lt;span&gt; &lt;/span&gt;받아서&lt;span&gt; &lt;/span&gt;목적이&lt;span&gt; &lt;/span&gt;되는&lt;span&gt; &lt;/span&gt;목적&lt;span&gt; &lt;/span&gt;코드를&lt;span&gt; &lt;/span&gt;만드는&lt;span&gt; &lt;/span&gt;것이&lt;span&gt; &lt;/span&gt;목적이다&lt;span&gt;. &lt;/span&gt;컴파일러에도&lt;span&gt; Front-end&lt;/span&gt;와&lt;span&gt; Back-end&lt;/span&gt;가&lt;span&gt; &lt;/span&gt;있는데&lt;span&gt; &lt;/span&gt;우리가&lt;span&gt; &lt;/span&gt;아는&lt;span&gt; &lt;/span&gt;웹&lt;span&gt; &lt;/span&gt;개발에서의&lt;span&gt; &lt;/span&gt;의미와는&lt;span&gt; &lt;/span&gt;다르다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Front-End&lt;/b&gt; : 프로그래밍 언어에 의존적, 기계에는 독립적&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Back-End&lt;/b&gt; : 프로그래밍 언어에 독립적, 기계에는 의존적&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴파일러의&lt;span&gt; Front-End&lt;/span&gt;는&lt;span&gt; &lt;/span&gt;개발자가&lt;span&gt; &lt;/span&gt;작성한&lt;span&gt; &lt;/span&gt;소스&lt;span&gt; &lt;/span&gt;코드를&lt;span&gt; &lt;/span&gt;분석하여&lt;span&gt; &lt;/span&gt;의미를&lt;span&gt; &lt;/span&gt;파악하는&lt;span&gt; &lt;/span&gt;역할이다&lt;span&gt;. Java&lt;/span&gt;로&lt;span&gt; &lt;/span&gt;작성되었는지&lt;span&gt; C&lt;/span&gt;로&lt;span&gt; &lt;/span&gt;작성되었는지에&lt;span&gt; &lt;/span&gt;따라&lt;span&gt; &lt;/span&gt;다르기&lt;span&gt; &lt;/span&gt;때문에&lt;span&gt; &lt;/span&gt;프로그래밍&lt;span&gt; &lt;/span&gt;언어에&lt;span&gt; &lt;/span&gt;굉장히&lt;span&gt; &lt;/span&gt;의존적이다&lt;span&gt;. Back-End&lt;/span&gt;는&lt;span&gt; Front-End&lt;/span&gt;에서&lt;span&gt; &lt;/span&gt;분석한&lt;span&gt; &lt;/span&gt;내용을&lt;span&gt; &lt;/span&gt;가지고&lt;span&gt; &lt;/span&gt;기계가&lt;span&gt; &lt;/span&gt;이해할&lt;span&gt; &lt;/span&gt;수&lt;span&gt; &lt;/span&gt;있도록&lt;span&gt; &lt;/span&gt;기계에&lt;span&gt; &lt;/span&gt;맞게&lt;span&gt; &lt;/span&gt;기계어&lt;span&gt;(&lt;/span&gt;바이너리&lt;span&gt; &lt;/span&gt;코드&lt;span&gt;)&lt;/span&gt;로&lt;span&gt; &lt;/span&gt;바꿔야&lt;span&gt; &lt;/span&gt;한다&lt;span&gt;. &lt;/span&gt;따라서&lt;span&gt; &lt;/span&gt;프로그래밍&lt;span&gt; &lt;/span&gt;언어에는&lt;span&gt; &lt;/span&gt;독립적이지만&lt;span&gt;, &lt;/span&gt;기계에는&lt;span&gt; &lt;/span&gt;의존적이라는&lt;span&gt; &lt;/span&gt;의미이다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1506&quot; data-origin-height=&quot;1620&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bqChog/btr4xiI6Cny/CtCO43X43R86pleRbA2kx1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bqChog/btr4xiI6Cny/CtCO43X43R86pleRbA2kx1/img.png&quot; data-alt=&quot;그림9. 일반적인 컴파일러의 구조&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bqChog/btr4xiI6Cny/CtCO43X43R86pleRbA2kx1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbqChog%2Fbtr4xiI6Cny%2FCtCO43X43R86pleRbA2kx1%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;1506&quot; height=&quot;1620&quot; data-origin-width=&quot;1506&quot; data-origin-height=&quot;1620&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림9. 일반적인 컴파일러의 구조&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&gt; &lt;/span&gt;컴파일러의&lt;span&gt; &lt;/span&gt;구조는&lt;span&gt; &lt;/span&gt;그림과&lt;span&gt; &lt;/span&gt;같다&lt;span&gt;. &lt;/span&gt;간단하게만&lt;span&gt; &lt;/span&gt;설명하고&lt;span&gt; &lt;/span&gt;넘어가겠다&lt;span&gt;. &lt;/span&gt;궁금하다면&lt;span&gt;&amp;nbsp;&lt;a title=&quot;나의 두 번째 뇌&quot; href=&quot;https://shin-jae-yoon.github.io/brain/CS/LT/Compiler/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span&gt;&lt;b&gt;나의&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;두&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;번째&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;뇌&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;를&lt;span&gt; &lt;/span&gt;참고하자&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;[Compiler Front-End]&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Lexical Analyzer (Scanner) : 어휘 분석기이다. 소스 코드 파일의 문자 시퀀스를 토큰 시퀀스로 변환하여 컴파일러 내부에서 효율적이며 다루기 쉬운 정수로 바꿔준다. Lexical Analyzer의 결과물은 tokens이다. 예를 들어,&amp;nbsp;&lt;span style=&quot;color: #ee2323;&quot;&gt;if ( a &amp;gt; 10 )&lt;/span&gt;이 있다고 하면,&amp;nbsp;&lt;span style=&quot;color: #ee2323;&quot;&gt;if&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #ee2323;&quot;&gt;(&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #ee2323;&quot;&gt;a&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #ee2323;&quot;&gt;&amp;gt;&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #ee2323;&quot;&gt;10&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #ee2323;&quot;&gt;)&lt;/span&gt;&amp;nbsp;6개의 토큰이 생성되고 if는 32, ( 는 7, a는 4와 같이 토큰에 정수가 매겨진다. 식별 가능한 문자 시퀀스는&amp;nbsp;&lt;b&gt;키워드&lt;/b&gt;(ex.&amp;nbsp;&lt;span style=&quot;color: #ee2323;&quot;&gt;public&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #ee2323;&quot;&gt;class&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #ee2323;&quot;&gt;main&lt;/span&gt;&amp;nbsp;등),&amp;nbsp;&lt;b&gt;리터럴&lt;/b&gt;(ex.&amp;nbsp;&lt;span style=&quot;color: #ee2323;&quot;&gt;1L&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #ee2323;&quot;&gt;2.3f&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #ee2323;&quot;&gt;&quot;Hello World!&quot;&lt;/span&gt;&amp;nbsp;등),&amp;nbsp;&lt;b&gt;식별자&lt;/b&gt;(ex.&amp;nbsp;&lt;span style=&quot;color: #ee2323;&quot;&gt;변수 이름&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #ee2323;&quot;&gt;상수 이름&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #ee2323;&quot;&gt;함수 이름&lt;/span&gt;&amp;nbsp;등 ),&amp;nbsp;&lt;b&gt;연산자&lt;/b&gt;(ex.&amp;nbsp;&lt;span style=&quot;color: #ee2323;&quot;&gt;+&lt;/span&gt;,&amp;nbsp;&lt;span style=&quot;color: #ee2323;&quot;&gt;-&lt;/span&gt;&amp;nbsp;등),&amp;nbsp;&lt;b&gt;구분 문자&lt;/b&gt;(ex.&amp;nbsp;&lt;span style=&quot;color: #ee2323;&quot;&gt;,&lt;/span&gt;&amp;nbsp;,&amp;nbsp;&lt;span style=&quot;color: #ee2323;&quot;&gt;[]&lt;/span&gt;&amp;nbsp;,&amp;nbsp;&lt;span style=&quot;color: #ee2323;&quot;&gt;{}&lt;/span&gt;&amp;nbsp;,&amp;nbsp;&lt;span style=&quot;color: #ee2323;&quot;&gt;()&lt;/span&gt; 등) 등이 있다. 이 &lt;b&gt;식별자 토큰은 Symbol Table (심볼 테이블)에 저장되고 나중에 Constant Pool 관련 지식에서 사용될 것이다.&amp;nbsp;&lt;/b&gt;대표적인 Lexical Analyzer에는 Lex가 있다.&lt;/li&gt;
&lt;li&gt;Syntax Analyzer (Parser) :&amp;nbsp; 구문 분석기이다. 문장의 문법적 구조를 파악하여 해당하는 프로그래밍 언어의 문법을 준수하는지 등을 확인한다.&amp;nbsp; 위에서 생성된 토큰 시퀀스들을 프로그램의 구문을 나타내는 파스 트리로 생성한다.&amp;nbsp;&lt;a title=&quot;파스 트리&quot; href=&quot;https://shin-jae-yoon.github.io/brain/CS/LT/ParseTree#:~:text=%ED%8C%8C%EC%8A%A4%20%ED%8A%B8%EB%A6%AC/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span&gt;&lt;b&gt;파스 트리&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;를 Abstract Syntax Tree, AST인 추상 구문 트리라고 하는 경우도 있다. 대표적인 Syntax Analyzer에는 Yacc이 있다. 보통 Lex + Yacc 조합을 많이 사용한다.&lt;/li&gt;
&lt;li&gt;Semantic Analyzer : 프로그램의 의미적인 측면을 분석한다. 이 단계에서는 변수의 유효성을 확인하거나 함수가 올바르게 호출되는지와 같은 작업을 수행한다. 타입 검사, 자동 타입 변환 등이 있는데, 예를 들어&amp;nbsp;int a = &quot;Hello&quot;;&amp;nbsp;라고 한다면 Syntax Analyzer에서는 에러를 잡지 못하지만, Semantic Analyzer 단계에서 에러가 나타난다. 위에서 생성된 파스 트리를 기반으로 타입 관련 정보가 추가되어 더 자세한 파스 트리가 완성된다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Intermediate Code Generator : 중간 코드인 Intermidate Code를 생성하는 곳이다. 컴퓨터가 직접 이해할 수 있는 형태가 아닌, 추상화된 형태로 보통 작성된다.&amp;nbsp;&lt;/b&gt;Lexcial Analyzer, Syntax Analyzer, Semantic Analyzer를 거치면서 만들어져 온 Symbol Table을 이용하여 클래스나 인터페이스 별 Constant Pool(상수 풀)을 만드는데 사용된다. 상수 풀에 저장된 정보는 해당 클래스나 인터페이스가 실제 생성될 때 Runtime Constant Pool을 구성하는데 사용되는데, 이는 &lt;a title=&quot;[Java의 실행원리 3편] Runtime 환경 - JVM Memory, Runtime Data Areas&quot; href=&quot;https://jae-yoon.tistory.com/17&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;[Java의&amp;nbsp;실행원리&amp;nbsp;3편]&amp;nbsp;Runtime&amp;nbsp;환경&amp;nbsp;-&amp;nbsp;JVM&amp;nbsp;Memory,&amp;nbsp;Runtime&amp;nbsp;Data&amp;nbsp;Areas&lt;/b&gt;&lt;/a&gt;에서 다루도록 한다.&lt;/li&gt;
&lt;/ol&gt;
&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;[Compiler Back-End]&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Code Optimizer : &lt;span&gt;비효율적인&lt;/span&gt; code&lt;span&gt;를&lt;/span&gt; &lt;span&gt;구분해내고&lt;/span&gt; &lt;span&gt;더&lt;/span&gt; &lt;span&gt;효율적인&lt;/span&gt; code&lt;span&gt;로&lt;/span&gt; &lt;span&gt;바꿔준다&lt;/span&gt;. &lt;span&gt;최적화를&lt;/span&gt; &lt;span&gt;담당하는&lt;/span&gt; &lt;span&gt;부분이다&lt;/span&gt;.&lt;/li&gt;
&lt;li&gt;Target Code Generator : &lt;span&gt;중간&lt;/span&gt; &lt;span&gt;코드로부터&lt;/span&gt; &lt;span&gt;최종&lt;/span&gt; &lt;span&gt;실행&lt;/span&gt; &lt;span&gt;코드&lt;/span&gt; Object Code&lt;span&gt;인&lt;/span&gt; &lt;span&gt;기계어를&lt;/span&gt; &lt;span&gt;생성한다&lt;/span&gt;. C/C++&lt;span&gt;의&lt;/span&gt; &lt;span&gt;경우&lt;/span&gt; &lt;span&gt;이&lt;/span&gt; Object Code&lt;span&gt;가&lt;/span&gt; &lt;span&gt;링커에&lt;/span&gt; &lt;span&gt;의해&lt;/span&gt; &lt;span&gt;링킹되고&lt;/span&gt; &lt;span&gt;실행&lt;/span&gt; &lt;span&gt;파일이&lt;/span&gt; &lt;span&gt;만들어지는&lt;/span&gt; &lt;span&gt;형태이다&lt;/span&gt;.&lt;/li&gt;
&lt;/ol&gt;
&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;span&gt; &lt;/span&gt;컴파일러에&lt;span&gt; &lt;/span&gt;의해&lt;span&gt; &lt;/span&gt;소스&lt;span&gt; &lt;/span&gt;코드&lt;span&gt;(.java)&lt;/span&gt;가&lt;span&gt; &lt;/span&gt;바이트&lt;span&gt; &lt;/span&gt;코드&lt;span&gt;(.class)&lt;/span&gt;로&lt;span&gt; &lt;/span&gt;변환된다고&lt;span&gt; &lt;/span&gt;했었다&lt;span&gt;. &lt;/span&gt;바로&lt;span&gt; Compiler Front-End &lt;/span&gt;부분을&lt;span&gt; &lt;/span&gt;자바&lt;span&gt; &lt;/span&gt;컴파일러가&lt;span&gt; &lt;/span&gt;담당하는&lt;span&gt; &lt;/span&gt;것이다&lt;span&gt;. &lt;/span&gt;컴퓨터가&lt;span&gt; &lt;/span&gt;직접적으로&lt;span&gt; &lt;/span&gt;이해할&lt;span&gt; &lt;/span&gt;수는&lt;span&gt; &lt;/span&gt;없지만&lt;span&gt;, &lt;/span&gt;추상화&lt;span&gt; &lt;/span&gt;된&lt;span&gt; &lt;/span&gt;형태인&lt;span&gt; Byte Code&lt;/span&gt;가&lt;span&gt; &lt;/span&gt;생성되기&lt;span&gt; &lt;/span&gt;때문이다&lt;span&gt;. Intermidate Code&lt;/span&gt;가&lt;span&gt; &lt;/span&gt;바로&lt;span&gt; Byte Code&lt;/span&gt;이다&lt;span&gt;. ( &lt;/span&gt;참고로&lt;span&gt;, &lt;/span&gt;기계어를&lt;span&gt; &lt;/span&gt;이루는&lt;span&gt; &lt;/span&gt;바이너리&lt;span&gt; &lt;/span&gt;코드와&lt;span&gt; &lt;/span&gt;바이트&lt;span&gt; &lt;/span&gt;코드는&lt;span&gt; &lt;/span&gt;다른&lt;span&gt; &lt;/span&gt;것이다&lt;span&gt;. ) &lt;/span&gt;이를&lt;span&gt; &lt;/span&gt;바탕으로&lt;span&gt; &lt;/span&gt;그림을&lt;span&gt; &lt;/span&gt;다시&lt;span&gt; &lt;/span&gt;그려보면&lt;span&gt; &lt;/span&gt;아래와&lt;span&gt; &lt;/span&gt;같다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1246&quot; data-origin-height=&quot;1342&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bsuYh8/btr4wFdB4Ms/PwdCHB3joxzN217x0meJXk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bsuYh8/btr4wFdB4Ms/PwdCHB3joxzN217x0meJXk/img.png&quot; data-alt=&quot;그림10. Java에서 컴파일러의 작동 원리&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bsuYh8/btr4wFdB4Ms/PwdCHB3joxzN217x0meJXk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbsuYh8%2Fbtr4wFdB4Ms%2FPwdCHB3joxzN217x0meJXk%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;1246&quot; height=&quot;1342&quot; data-origin-width=&quot;1246&quot; data-origin-height=&quot;1342&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림10. Java에서 컴파일러의 작동 원리&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은 플랫폼에 의존적이라는 말이 와닿을 것이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Front-End&lt;/b&gt; : 프로그래밍 언어에 의존적, 기계에는 독립적&amp;nbsp;&lt;b&gt;( = Java Compiler 부분 )&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Back-End&lt;/b&gt; : 프로그래밍 언어에 독립적, 기계에는 의존적&amp;nbsp;&lt;b&gt;( = JVM 부분 )&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;Source Code&lt;/span&gt;인&lt;span&gt; Java&lt;/span&gt;를&lt;span&gt; &lt;/span&gt;기반으로&lt;span&gt; &lt;/span&gt;어휘&lt;span&gt; &lt;/span&gt;분석&lt;span&gt;, &lt;/span&gt;구문&lt;span&gt; &lt;/span&gt;분석&lt;span&gt;, &lt;/span&gt;의미&lt;span&gt; &lt;/span&gt;분석의&lt;span&gt; &lt;/span&gt;과정을&lt;span&gt; &lt;/span&gt;거치고&lt;span&gt; &lt;/span&gt;중간&lt;span&gt; &lt;/span&gt;코드인&lt;span&gt; Byte Code &lt;/span&gt;클래스&lt;span&gt; &lt;/span&gt;파일을&lt;span&gt; &lt;/span&gt;만들기&lt;span&gt; &lt;/span&gt;때문에&lt;span&gt; &lt;/span&gt;언어에&lt;span&gt; &lt;/span&gt;의존적이다&lt;span&gt;. &lt;/span&gt;여기까지&lt;span&gt; &lt;/span&gt;작업을&lt;span&gt; &lt;/span&gt;하고&lt;span&gt; &lt;/span&gt;나면&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;&lt;b&gt;컴퓨터가&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;직접&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;이해할&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;수는&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;없지만&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;추상화&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;된&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;형태이기&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;때문에&lt;/b&gt;&lt;b&gt; JVM&lt;/b&gt;&lt;b&gt;이&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;운영체제에&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;맞게&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;기계어로&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;변환해주는&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;과정을&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;하는&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;것이다&lt;/b&gt;&lt;b&gt;. &lt;/b&gt;&lt;b&gt;그렇기에&lt;/b&gt;&lt;b&gt; JVM&lt;/b&gt;&lt;b&gt;은&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;플랫폼에&lt;/b&gt;&lt;b&gt; &lt;/b&gt;&lt;b&gt;의존적이다&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;&lt;span style=&quot;background-color: #f6e199;&quot;&gt;.&lt;/span&gt;&amp;nbsp;&lt;/b&gt;( JIT Compiler&lt;/span&gt;의&lt;span&gt; &lt;/span&gt;내용은 &lt;a title=&quot;[Java의 실행원리 4편] Runtime 환경 - JVM Execute Engine&quot; href=&quot;https://jae-yoon.tistory.com/18&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;&lt;span&gt;[Java&lt;/span&gt;의&lt;span&gt; &lt;/span&gt;실행원리&lt;span&gt; 4&lt;/span&gt;편&lt;span&gt;] Runtime &lt;/span&gt;환경&lt;span&gt; - JVM Execute Engine&lt;/span&gt;&lt;/b&gt;&lt;/a&gt;에서&lt;span&gt; &lt;/span&gt;다루기&lt;span&gt; &lt;/span&gt;때문에&lt;span&gt; &lt;/span&gt;여기서는&lt;span&gt; &lt;/span&gt;넘어가겠다&lt;span&gt;. )&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JVM, JRE, JDK&lt;span&gt;와&lt;/span&gt; &lt;span&gt;같은&lt;/span&gt; &lt;span&gt;기본적인&lt;/span&gt; &lt;span&gt;용어를&lt;/span&gt; &lt;span&gt;설명하고&lt;/span&gt; &lt;span&gt;간단한&lt;/span&gt; &lt;span&gt;컴파일러의&lt;/span&gt; &lt;span&gt;동작&lt;/span&gt; &lt;span&gt;과정을&lt;/span&gt; &lt;span&gt;보면서&lt;/span&gt; &lt;span&gt;소스&lt;/span&gt; &lt;span&gt;코드&lt;/span&gt;(.java)&lt;span&gt;가&lt;/span&gt; Java Compiler(javac)&lt;span&gt;에&lt;/span&gt; &lt;span&gt;의해&lt;/span&gt; &lt;span&gt;바이트&lt;/span&gt; &lt;span&gt;코드&lt;/span&gt;(.class)&lt;span&gt;로&lt;/span&gt; &lt;span&gt;변하는&lt;/span&gt; &lt;span&gt;컴파일&lt;/span&gt; &lt;span&gt;시점의&lt;/span&gt; &lt;span&gt;환경을&lt;/span&gt; &lt;span&gt;살펴보았다&lt;/span&gt;.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;참고&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;a title=&quot;네이버 D2- JVM Internal&quot; href=&quot;https://d2.naver.com/helloworld/1230&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;네이버 D2- JVM Internal&lt;/b&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a title=&quot;geeksforgeeks.org - 자바 컴파일 실행원리&quot; href=&quot;https://www.geeksforgeeks.org/compilation-execution-java-program/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;geeksforgeeks.org&amp;nbsp;-&amp;nbsp;자바&amp;nbsp;컴파일&amp;nbsp;실행원리&lt;/b&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a title=&quot;oracle Java 9 migration guide&quot; href=&quot;https://docs.oracle.com/javase/9/migrate/toc.htm#JSMIG-GUID-D867DCCC-CEB5-4AFA-9D11-9C62B7A3FAB1&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;oracle Java 9 migration guide&lt;/b&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;a title=&quot;Java 모듈에 관한 설명&quot; href=&quot;https://jenkov.com/tutorials/java/modules.html&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span&gt;&lt;b&gt;Java 모듈에 관한 설명&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;a title=&quot;Java에서 패키지와 모듈의 차이점&quot; href=&quot;https://raspberrylounge.medium.com/%EC%9E%90%EB%B0%94%EC%97%90%EC%84%9C-%ED%8C%A8%ED%82%A4%EC%A7%80-package-%EC%99%80-%EB%AA%A8%EB%93%88-module-%EC%9D%98-%EC%B0%A8%EC%9D%B4%EC%A0%90-16b2eda177b4&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span&gt;&lt;b&gt;Java에서 패키지와 모듈의 차이점&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;a title=&quot;우아한테크코스 10분 테코톡 - 무민의 JVM Stack &amp;amp; Heap&quot; href=&quot;https://www.youtube.com/watch?v=UzaGOXKVhwU&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span&gt;&lt;b&gt;우아한테크코스 10분 테코톡 - 무민의 JVM Stack &amp;amp; Heap&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span&gt;&lt;a title=&quot;개발자 유니의 두 번째 뇌 - 컴파일러&quot; href=&quot;https://shin-jae-yoon.github.io/brain/CS/LT/Compiler/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;span&gt;&lt;b&gt;개발자 유니의 두 번째 뇌 - 컴파일러&lt;/b&gt;&lt;/span&gt;&lt;/a&gt;&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;a title=&quot; stackoverflow - Does JVM generate bytecode or run bytecode?&quot; href=&quot;https://stackoverflow.com/questions/32011039/does-jvm-generate-bytecode-or-run-bytecode&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt; stackoverflow - Does&amp;nbsp;JVM&amp;nbsp;generate&amp;nbsp;bytecode&amp;nbsp;or&amp;nbsp;run&amp;nbsp;bytecode?&lt;/b&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a title=&quot;HomoEfficio님의 Back to the Essence - Java 컴파일에서 실행까지 - (1) 포스팅&quot; href=&quot;https://homoefficio.github.io/2019/01/31/Back-to-the-Essence-Java-%EC%BB%B4%ED%8C%8C%EC%9D%BC%EC%97%90%EC%84%9C-%EC%8B%A4%ED%96%89%EA%B9%8C%EC%A7%80-1/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;&lt;b&gt;HomoEfficio님의 Back to the Essence - Java 컴파일에서 실행까지 - (1) 포스팅&lt;/b&gt;&lt;/a&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;u&gt;&lt;span&gt;&lt;b&gt;※&amp;nbsp;본&amp;nbsp;게시글은&amp;nbsp;공부하면서&amp;nbsp;작성했기에&amp;nbsp;틀린&amp;nbsp;부분이&amp;nbsp;있을&amp;nbsp;수&amp;nbsp;있습니다.&amp;nbsp;질문&amp;nbsp;사항이나&amp;nbsp;댓글로&amp;nbsp;알려주시면&amp;nbsp;감사하겠습니다.&lt;/b&gt;&lt;/span&gt;&lt;/u&gt;&lt;/p&gt;</description>
      <category>Language/Java</category>
      <category>Java Compile time</category>
      <category>java 컴파일러</category>
      <category>Java 컴파일러 동작 원리</category>
      <category>jdk</category>
      <category>jre</category>
      <category>JVM</category>
      <category>모듈</category>
      <author>Dev Uni</author>
      <guid isPermaLink="true">https://jae-yoon.tistory.com/15</guid>
      <comments>https://jae-yoon.tistory.com/15#entry15comment</comments>
      <pubDate>Tue, 14 Mar 2023 01:43:34 +0900</pubDate>
    </item>
    <item>
      <title>[Java의 실행원리 0편] 시리즈 개요</title>
      <link>https://jae-yoon.tistory.com/14</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;자바를 복습하려고 자바의 정석 첫 장을 펼치자마자 난관에 봉착했다. 예전에는 아무 생각없이 읽었지만, JIT 컴파일러, HotSpot JVM, Runtime Constant Pool 등 외계어를 도저히 무시할 수 없어서 자바의 실행원리를 제대로 정리해야겠다고 다짐하여 글을 작성한다. 시리즈로 작성하려고 하는데,&amp;nbsp;&lt;u&gt;&lt;b&gt;&lt;span&gt;본 게시글은 지적 호기심으로 깊게 검색해본 내용으로 초심자에게 적합하지 않을 수 있다.&lt;/span&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;설명하기에 앞서,&amp;nbsp;Java는 썬 마이크로시스템즈(현 Oracle)에 의해 개발되었지만, JVM 명세(The Java Virtual Machine Specification)를 따르기만 하면 어떤 벤더든 JVM을 개발하여 제공할 수 있어서 JVM의 세부적인 구현은 다를 수 있다. 이 때문에 Hotspot JVM, IBM JVM, Azul zulu prime JVM 등 다양한 JVM이 있지만, &lt;b&gt;해당 시리즈에서 설명하는 JVM은 Oracle의&amp;nbsp;&lt;span&gt;Hotspot JVM을 기준으로 설명한다.&lt;/span&gt;&amp;nbsp;(근데 나는 zulu 사용 중이다 ㅋ)&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;아래의&lt;span&gt; &lt;/span&gt;그림을&lt;span&gt; &lt;/span&gt;보며&lt;span&gt;, &lt;/span&gt;목차에&lt;span&gt; &lt;/span&gt;대하여&lt;span&gt; &lt;/span&gt;설명하겠다&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;2082&quot; data-origin-height=&quot;2022&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bI4blO/btr4wMxuGMU/WVYSxeBrmnevOkKxKvOePK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bI4blO/btr4wMxuGMU/WVYSxeBrmnevOkKxKvOePK/img.png&quot; data-alt=&quot;그림 1. Java의 실행원리 Made by Dev Uni&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bI4blO/btr4wMxuGMU/WVYSxeBrmnevOkKxKvOePK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbI4blO%2Fbtr4wMxuGMU%2FWVYSxeBrmnevOkKxKvOePK%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;2082&quot; height=&quot;2022&quot; data-origin-width=&quot;2082&quot; data-origin-height=&quot;2022&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;그림 1. Java의 실행원리 Made by Dev Uni&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&gt;&lt;a title=&quot;[Java의 실행원리 1편] Compile-time 환경&quot; href=&quot;https://jae-yoon.tistory.com/15&quot;&gt;&lt;b&gt;[Java의 실행원리 1편] Compile-time 환경&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;JVM, JRE, JDK에 대한 이해&lt;/li&gt;
&lt;li&gt;모듈화로 인해 Java 9부터 JDK가 어떻게 변화했는지&lt;/li&gt;
&lt;li&gt;Java로 작성된 Source Code 파일(.java)이 자바 컴파일러(javac)에 의해 Byte Code 파일(.class)로 변하는 과정&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&gt;&lt;a title=&quot;[Java의 실행원리 2편] Runtime 환경 - JVM Class Loader&quot; href=&quot;https://jae-yoon.tistory.com/16&quot;&gt;&lt;b&gt;[Java의 실행원리 2편] Runtime 환경 - JVM Class Loader&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;&lt;/b&gt;&lt;/span&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Dynamic Loading (동적 로딩)&lt;/li&gt;
&lt;li&gt;Bootstrap Class Loader / Extension Class Loader / System Class Loader&lt;/li&gt;
&lt;li&gt;변환된 클래스 파일이 JVM의 클래스 로더에 의해 JVM 메모리에 올라가는 과정&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;a title=&quot;[Java의 실행원리 3편] Runtime 환경 - JVM Memory, Runtime Data Areas&quot; href=&quot;https://jae-yoon.tistory.com/17&quot;&gt;&lt;b&gt;[Java의 실행원리 3편] Runtime 환경 - JVM Memory, Runtime Data Areas&lt;/b&gt;&lt;/a&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Method area, Heap area, Stack area, PC Register, Native Method Stack&lt;/li&gt;
&lt;li&gt;Constant Pool, Runtime Constant Pool, String Constant Pool 셋은 다를까?&lt;/li&gt;
&lt;li&gt;Permenant 영역 &amp;rarr; Metaspace 영역으로 변하면서 생긴 변화&lt;/li&gt;
&lt;li&gt;static object 저장 위치는 method area가 아닌 heap area&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;a title=&quot;[Java의 실행원리 4편] Runtime 환경 - JVM Execute Engine&quot; href=&quot;https://jae-yoon.tistory.com/18&quot;&gt;&lt;b&gt;[Java의 실행원리 4편] Runtime 환경 - JVM Execute Engine&lt;/b&gt;&lt;/a&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Execute Engine의 Interpreter, JIT Compiler, Garbage Collector&lt;/li&gt;
&lt;li&gt;JNI를 통해 Host Operating System의 Native Method Libraries와 상호작용 하는 것&lt;/li&gt;
&lt;li&gt;Heap 영역을 자세히 보고 GC 알고리즘 살펴보기&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나와 비슷한 지적 호기심을 얻은 사람들을 위하여 해당 시리즈를 바친다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;span&gt;&lt;b&gt;&lt;b&gt;&lt;span&gt;※&amp;nbsp;&lt;/span&gt;&lt;/b&gt;본&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;게시글은&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;공부하면서&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;작성했기에&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;틀린&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;부분이&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;있을&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;수&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;있습니다&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;. 질문 사항이나&amp;nbsp;&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;댓글로&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;알려주시면&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt; &lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;감사하겠습니다&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;.&lt;/b&gt;&lt;/span&gt;&lt;/u&gt;&lt;/p&gt;</description>
      <category>Language/Java</category>
      <category>Java 실행원리</category>
      <category>JVM 실행원리</category>
      <author>Dev Uni</author>
      <guid isPermaLink="true">https://jae-yoon.tistory.com/14</guid>
      <comments>https://jae-yoon.tistory.com/14#entry14comment</comments>
      <pubDate>Mon, 13 Mar 2023 17:32:20 +0900</pubDate>
    </item>
    <item>
      <title>[오늘의 일기] vscode 오류 잡으려고 난리 부르쓰</title>
      <link>https://jae-yoon.tistory.com/8</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;평화롭게 강의 듣던 와중, vscode extension을 다운받으려고 하는데 오잉? 다운이 안된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;네트워크 속도가 1초에 2KB 수준으로 매우 느렸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나는 windows 환경에서 wsl2를 사용하고 있고 vscode 에서 wsl2를 터미널 기본 세팅으로 해놨다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;최근에 네트워크를 잘못 만지는 바람에 리눅스 서버가 다운되었던 경험이 있어서&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;당연히 리눅스 문제겠구나~ 싶었다. 그래서 vscode에서 remote-wsl을 이용하여 접속해보니 !?&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;525&quot; data-origin-height=&quot;127&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/zh1yr/btrJqLzG5Ke/9n5KDYjLLD133BP5lfpfS0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/zh1yr/btrJqLzG5Ke/9n5KDYjLLD133BP5lfpfS0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/zh1yr/btrJqLzG5Ke/9n5KDYjLLD133BP5lfpfS0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fzh1yr%2FbtrJqLzG5Ke%2F9n5KDYjLLD133BP5lfpfS0%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;525&quot; height=&quot;127&quot; data-origin-width=&quot;525&quot; data-origin-height=&quot;127&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&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;951&quot; data-origin-height=&quot;205&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1vgGY/btrJu1OylKM/yWO3QpIvDRKljcLQOQ03t0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1vgGY/btrJu1OylKM/yWO3QpIvDRKljcLQOQ03t0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1vgGY/btrJu1OylKM/yWO3QpIvDRKljcLQOQ03t0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1vgGY%2FbtrJu1OylKM%2FyWO3QpIvDRKljcLQOQ03t0%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;951&quot; height=&quot;205&quot; data-origin-width=&quot;951&quot; data-origin-height=&quot;205&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이러한 오류의 향연이었다. 일단, remote-wsl을 안쓴지 좀 되어서 vs code 서버 버전이 안맞구나~ 싶었는데 그를 다운받는 과정에서 다운로드가 제대로 되고 있지 않은 것으로 이해하였다.&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;첫번째 노력, Temp 폴더에 tar.gz 파일 넣기&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;관련 오류를 찾다보니&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;&quot;&lt;a href=&quot;https://update.code.visualstudio.com/commit~&quot;&gt;https://update.code.visualstudio.com/commit~&lt;/a&gt;&quot;&lt;/b&gt;&lt;span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;해당 부분을 윈도우 환경읜 웹브라우저에 붙혀넣기하고 다운로드 한 이후 해당하는 tar.gz 파일을 Temp 폴더에 넣으면 해결된다는 것을 봤다. 그런데 웬걸? 다운로드 속도가 역시나 1초에 2KB 정도 나오다가 네트워크 오류로 파일을 다운받지 못하였다.&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;s&gt;&lt;span&gt;이때 알아차렸어야 했다. 윈도우 환경에서 다운로드 하는데도 속도가 느린 것을 전혀 의심하지 않았다.&lt;/span&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;&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;두번째 노력, 네트워크 어댑터 설정&lt;/span&gt;&lt;/b&gt;&lt;/h3&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 data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;위의 경로로 들어가서 보니 vEthernet (WSL)은 충분히 잘.. 연결되어 있었다. 왜 이거부터 먼저 볼 생각을 안했을까?&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;하지만 그럼에도 나는 나를 믿지 못했다. 왜냐하면 파일 다운로드 시도했을 때 네트워크 오류라고 떴으니까.&amp;nbsp;&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span&gt;세번째 노력,&amp;nbsp; windows 기능 켜기/끄기, &lt;span&gt;Hyper-V 가상관리자&lt;/span&gt;&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;wsl을 이용하기 위해 windows 기능 켜기/끄기에서 Hyper-V, Linux용 Windows 하위 시스템, 가상 머신 플랫폼에 체크 했던&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기억이 있다. 이 과정에서 여러 세팅들이 이루어진다. wsl2는 윈도 기반 리눅스 인터페이스인 wsl1과는 다르게 순수 리눅스 커널을 vm에서 사용하기 때문에 가상화에 관련된 기능을 켰던 것이다. 그리고 네트워크를 호스트 os랑 포트 공유를 사용하도록 하여 처음에는 단순하게 내부 네트워크로 설정이 되어있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Hyper-V 관리자 - 가상 스위치 관리자 - WSL을 보면 내부 네트워크에 체크가 되어있다. 근데 wsl1과는 다르게 wsl2 부터는 브릿지 모드가 가능하기 때문에 VM에 실제 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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;네번째 노력, wsl2의 DNS 문제 ?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://digiconfactory.tistory.com/entry/WSL2-%EC%9A%B0%EB%B6%84%ED%88%AC-DNS%EC%84%9C%EB%B2%84&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;WSL2 DNS 문제&lt;/a&gt;를 보면 가정의 유동 IP 때문에 변경된 IP가 자동으로 할당되어 DNS 서버에 가지 않고 엉뚱한 경로로&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가서 vscode server 파일을 다운로드 하려고 하나? 싶어서 DNS도 만져봤다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #000000;&quot;&gt;DNS 설정은 &lt;a href=&quot;https://superroot.tistory.com/275&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;해당 블로그&lt;/a&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_1660220131701&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo rm /etc/resolv.conf
sudo bash -c 'echo &quot;nameserver 8.8.8.8&quot; &amp;gt; /etc/resolv.conf'
sudo bash -c 'echo &quot;[network]&quot; &amp;gt; /etc/wsl.conf'
sudo bash -c 'echo &quot;generateResolvConf = false&quot; &amp;gt;&amp;gt; /etc/wsl.conf'
sudo chattr +i /etc/resolv.conf&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기존의 DNS서버가 무작위로 부여되던 resolv.conf 파일을 지우고, 구글 무료 DNS 서버인 8.8.8.8을 이용했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파일 내용을 수정한 것이 아니라 지우고 새로 만든 이유는 기존의 파일이 심볼릭 링크되어 있어서이다. 다음으로&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;wsl.conf에 두 설정을 했다. 맨 밑은 resolv.conf에 immutable 속성을 줘서 자동으로 지우지 못하게 한 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결론은? 뭐... 여전히 안됐다. 그런데 이 설정 이후 다운 속도가 기존보다 훨씬 빠르길래 그냥 그대로 놔뒀다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;&lt;span style=&quot;color: #000000;&quot;&gt;다섯번째 노력, (드디어) VS code의 자체적인 문제?&lt;/span&gt;&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;3시간동안 만졌는데도 안되어서 멍하니 있다가.. 불현듯 wsl2 네트워크 문제가 아닌건가? 싶어서 apt-get으로 아무거나 다운받아봤다. 어라? 어????????????????? ㅋㅋ 잘된다. 그래서 vscode remote-wsl을 해보니까? 아. 안된다. 쓸데없는 짓을 계속 하고있었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 찾아봤더니, 최근 1.70 vscode 버전이 업데이트가 되었고 ( &lt;s&gt;나는 자동 업데이트 해놨다. 이제 자동 업데이트 무조건 푼다 진짜&lt;/s&gt; ) 관련 오류를 경험하는 사람들이 최근에 몇몇 있다는걸 알았다. 또 커뮤니티를 보니 vscode extensions이 다운 안된다는 말이 있었다. 그제서야 vs code 문제구나 싶었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;vscode 공식 홈페이지에서 보는데, 어? 위의 오류 사진을 다시 자세히 보면,&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;951&quot; data-origin-height=&quot;205&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/1vgGY/btrJu1OylKM/yWO3QpIvDRKljcLQOQ03t0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/1vgGY/btrJu1OylKM/yWO3QpIvDRKljcLQOQ03t0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/1vgGY/btrJu1OylKM/yWO3QpIvDRKljcLQOQ03t0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F1vgGY%2FbtrJu1OylKM%2FyWO3QpIvDRKljcLQOQ03t0%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;951&quot; height=&quot;205&quot; data-origin-width=&quot;951&quot; data-origin-height=&quot;205&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;commit: da76f93349a~ 어쩌구 부분이 있다. 나는 이게 내 컴퓨터의 뭐 특수한 번호 이런건줄 알았는데 그냥 vscode 버전의 커밋 id였다. 1.70 업데이트의 커밋이 바로 da76f9였다. 그래서 당장 &lt;a href=&quot;https://github.com/microsoft/vscode&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;vscode 깃허브&lt;/a&gt;에 뛰어가봤다. 역시나, 최근 오류들로 인하여 1.70.1 버전이 릴리즈 된 것을 확인할 수 있었다.&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;a id=&quot;issue_156690_link&quot; href=&quot;https://github.com/microsoft/vscode/issues/156690&quot; data-hovercard-type=&quot;issue&quot; data-hovercard-url=&quot;/microsoft/vscode/issues/156690/hovercard&quot;&gt;Remote development: Zombie file watcher processes not cleaned up on remote host&lt;/a&gt; 문제가 있는 것 같아서 remote-wsl 문제도 있는건가? 싶었다. 근데 이 오류는 1.70 버전으로 오면서 해결이 되었다고 하는데....&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;결론, 그냥 vscode 서버 터진거임&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;remote에 관련된 오류는 1.70 버전에 와서 이미 다 해결되었을 것이고 나와 관계 없는 오류를 해결하고 릴리즈한 1.70.1이&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;나오면서 서버가 느려지지 않았나싶다. 왜냐하면, &lt;u&gt;vscode를 지우고 다시 깔아보려고 홈페이지에서 설치 파일 다운로드 하려고 하니까 그것도 속도가 엄~청 느리더라.&lt;/u&gt; &lt;b&gt;그냥 단순하게 vscode 서버에 문제가 생겨서 일시적으로 느려진 것인데 혼자 멍청하게 리눅스 네트워크 !? vscode의 remote 오류!? 하면서 난리 부르쓰였다. 서버 복구할 때까지 기다리면 자연스레 해결 될 문제이다.&lt;/b&gt;&lt;b&gt;&amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;오늘의 교훈&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1. vscode 자동 업데이트 해놓지말자. 잘되던거 안되니까 정말 답답하더라&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2. 제발 오류가 생기면 좀 잘 읽어보자. 잘 모르는 분야라고 온갖 검색만 하지말고 원인을 파악하려하자.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;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;&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;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;추가내용&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;holix CTO인 살쾡이tv님께서 해결방법을 제시해주셨다.&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;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;해당하는 문제는, microsoft가 visual code를 업데이트 하는 과정에서 CDN을&lt;br /&gt;이용하는데, CDN의 한국 endpoint가 오늘따라 매우 느렸습니다. 그래서&lt;br /&gt;미국 endpoint ip 주소로 변경하니 잘 되었습니다 !&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;라고 하셔서 원인은 완전히 이해했으나, 막상 내가 해보니 잘 되지 않았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;먼저, wsl의 /etc/hosts에다가 해당하는 코드를 추가해봤다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1660220525892&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;sudo vim /etc/hosts

# 아래의 코드를 추가, 두 ip 모두 미국 endpoint
40.64.128.224 update.code.visualstudio.com
152.199.4.33 az764295.vo.msecnd.net&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;hosts 파일의 내용이 자동으로 날라가는 것을 방지하기 위하여 wsl.conf에 아래의 코드도 추가한다.&lt;/p&gt;
&lt;pre id=&quot;code_1660220727106&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;[network]
generateHosts = false&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;그리고 ping을 계속 날려봤더니, 아래 az764295 (visual code 업데이트 할 때 사용되는 CDN)은 잘 되는데 update.code는 패킷 손실률 100%로 ping이 튀었고, 역시나 속도가 느려서 해결되지 않았다. 사실, 잠깐 다른거 하느라 살쾡이님한테 문제 해결되었다고 너무 감사하다고 말하고 다른거 하고 와서 해봤는데 문제가 해결되지 않아서.. 다시 질문하기 죄송스러워서 그대로 방치해둔 상태이다. :( 하지만 원인은 알았으니 그것으로 만족한다.&amp;nbsp;&lt;/p&gt;</description>
      <category>Retrospect/오늘의 일기</category>
      <category>extension 다운 안됨</category>
      <category>vscode 오류</category>
      <category>wsl2 오류</category>
      <author>Dev Uni</author>
      <guid isPermaLink="true">https://jae-yoon.tistory.com/8</guid>
      <comments>https://jae-yoon.tistory.com/8#entry8comment</comments>
      <pubDate>Thu, 11 Aug 2022 17:46:00 +0900</pubDate>
    </item>
    <item>
      <title>[HTML/CSS] Vertical-align 수직정렬에 대한 오해</title>
      <link>https://jae-yoon.tistory.com/7</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Vertical-align은 당신이 아는 수직정렬이 아니다.&lt;/b&gt;&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;Flex 박스 이용 시 컨텐츠를 어떻게 수직정렬 해야할까?&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;항상 html/css는 가볍게 공부하고 넘어가고 그때 그때 구현하기에 바빴어서 평상시 어려움을 겪었던 수직 정렬에 관하여 말하고자 한다. 자극적인 제목을 사용했지만, &lt;b&gt;사실 대부분의 사람들이 잘 구현하고 있을 것이다. 이 글은 html/css에 처음으로 뛰어들어 어려움을 겪는 분들에게 나의 경험을 공유하고자 함&lt;/b&gt;이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;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;1280&quot; data-origin-height=&quot;688&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/cBnI9a/btrIT8NP9JO/gH5CQDkSKWilofDINaoUkK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/cBnI9a/btrIT8NP9JO/gH5CQDkSKWilofDINaoUkK/img.png&quot; data-alt=&quot;이미지. 초기 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/cBnI9a/btrIT8NP9JO/gH5CQDkSKWilofDINaoUkK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FcBnI9a%2FbtrIT8NP9JO%2FgH5CQDkSKWilofDINaoUkK%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;733&quot; height=&quot;394&quot; data-origin-width=&quot;1280&quot; data-origin-height=&quot;688&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이미지. 초기 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1659531973031&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; style=&quot;display: flex&quot;&amp;gt;
            &amp;lt;p&amp;gt;개발자 신재윤입니다 :)&amp;lt;/p&amp;gt;
            &amp;lt;img src=&quot;./광안리.png&quot; /&amp;gt;
        &amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위와 같은 레이아웃이 있다고 하자. 현재 텍스트는 태그 내부에 작성했고 사진은 img 태그이다. 두 레이아웃은 flex를 이용한 가로배치를 했다. 여기서 우리가 하고자 원하는 작업은 글자를 수직정렬하여 가운데 보내기를 원할 것이다.&lt;/p&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;1316&quot; data-origin-height=&quot;713&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bYY5YY/btrISOWDriI/YTmEfkfYsZMl25yMiKmeX1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bYY5YY/btrISOWDriI/YTmEfkfYsZMl25yMiKmeX1/img.png&quot; data-alt=&quot;이미지. 내가 원하는 화면&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bYY5YY/btrISOWDriI/YTmEfkfYsZMl25yMiKmeX1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbYY5YY%2FbtrISOWDriI%2FYTmEfkfYsZMl25yMiKmeX1%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;773&quot; height=&quot;419&quot; data-origin-width=&quot;1316&quot; data-origin-height=&quot;713&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이미지. 내가 원하는 화면&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;pre id=&quot;code_1659532308575&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; style=&quot;display: flex; vertical-align: middle;&quot;&amp;gt;
            &amp;lt;p&amp;gt;개발자 신재윤입니다 :)&amp;lt;/p&amp;gt;
            &amp;lt;img src=&quot;./광안리.png&quot; /&amp;gt;
        &amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 vertical-align: middle 속성을 주면? 저런. 별다른 변화가 없다. 분명히 수평정렬을 할 때 div 박스에 text-align: middle 속성을 주면 글자가 가운데 배치 되었던 경험이 있는데 수직정렬인 vertical-align은 왜 되지 않는 것일까?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;공식문서를 제발 &quot;잘&quot; 보도록 하자&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;구글 검색을 통하여 여러 게시글을 볼 시간에 공식문서를 먼저 보는 습관을 꼭! 기르자. &lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/CSS/text-align&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;MDN Docs - text align&lt;/a&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;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;span style=&quot;background-color: #ffffff; color: #1b1b1b;&quot;&gt;&lt;b&gt;&lt;span&gt;CSS &lt;/span&gt;text-align&lt;/b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;속성은 블록 요소나 표의 칸 상자의 가로 정렬을 설정합니다.&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #1b1b1b;&quot;&gt;&lt;span&gt;&amp;nbsp;&lt;br /&gt;&lt;/span&gt;즉&lt;span&gt; vertical-align&lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;background-color: #ffffff; color: #1b1b1b;&quot;&gt;과 동일하나 세로가 아닌 가로 방향으로 동작합니다.&lt;br /&gt;&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;처음 이 문구를 봤을 때는 vertical-align과 동일하게 동작한다고? 근데 vertical-align은 작동이 잘 안되던데? 라고 생각하고 넘겼지만, 잘 읽어보도록 한다. 분명 text-align은&amp;nbsp;&lt;b&gt;블록 요소나 표의 칸 상자&lt;/b&gt;의 가로 정렬을 한다고 한다. 다음으로 &lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/CSS/vertical-align&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;MDN Docs - vertical align&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;b&gt;vertical-align CSS &lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #1b1b1b;&quot;&gt;속성은 inline 또는 table-cell box에서의 수직 정렬을 지정합니다&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;vertical-align은&amp;nbsp;&lt;b&gt;inline 또는 table-cell box에서의&amp;nbsp;&lt;/b&gt;수직 정렬을 지정한다고 한다. 추가로, 중단까지 내려가면 친절하게 &quot;&lt;u&gt;vertical-align은 오로지 inline과 table-cell 엘리먼트에만 적용된다는 것에 주의하세요: 이 속성을&lt;span style=&quot;background-color: #ffffff; color: #1b1b1b;&quot;&gt;&amp;nbsp;&lt;/span&gt;&lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/HTML/Block-level_elements&quot;&gt;block level 엘리먼트&lt;/a&gt;&lt;/u&gt;&lt;span style=&quot;background-color: #ffffff; color: #1b1b1b;&quot;&gt;&lt;u&gt;에 사용할 수 없습니다.&lt;/u&gt;&quot;라고 설명되어있다.&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: #ffffff; color: #1b1b1b;&quot;&gt;아까, 내가 작성한 문구는 분명 &amp;lt;p&amp;gt; 태그로 작성했었다. &amp;lt;p&amp;gt; 태그는 display 기본 속성이 block인 녀석이다. mdn 문서에서 block에는 적용되지 않는다고 친절히 적어놨는데 나는 왜 안되냐고 울부짖었던 것이다. (&lt;s&gt;멍청이&lt;/s&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;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Vertical align의 역할&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;color: #1b1b1b;&quot;&gt;&lt;span style=&quot;background-color: #ffffff;&quot;&gt;block level 엘리먼트에 사용할 수 없기 때문에 해당하는 p 태그를 감싸는 div 박스를 만들고 display 속성을 inline-block과 같이 줘서 vertical-align을 주고 수직 정렬을 시킬 수 있다. 하지만 vertical-align을 주로 사용하는 곳은 한 줄 자체에서 수직정렬을 맞출 때 사용하는 것이 더 맞다고 판단했다. 수직 정렬 하는 방법은 vertical-align 이외에도 여러 방법으로 할 수 있어서이다. 따라서 vertical align은 inline 내부의 수직정렬에 더 집중하는 역할이 맞다고 생각한다. 예를 들어, &lt;a href=&quot;http://www.티스토리.com&quot;&gt;www.티스토리.com&lt;/a&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;a href=&quot;https://simsimjae.tistory.com/333?category=328771&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;vertical-align을 이용한 글자의 수직 정렬&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;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;해결방법 1. line-height / padding / margin (비추천)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;현재, 저는 display를 block이나 inline-block으로 하지 않고 flex를 사용하여 진행하고 있음을 다시 한 번 밝힙니다. block이나 inline-block의 경우 세로 정렬하는 방법은 인터넷에 많이 나와있으니 찾아보시면 나올 것 같습니다 :)&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- line-height&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;556&quot; data-origin-height=&quot;575&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/9xCe6/btrITmFttA6/yveUZCVFYTBAIKYVPZY0e0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/9xCe6/btrITmFttA6/yveUZCVFYTBAIKYVPZY0e0/img.png&quot; data-alt=&quot;01. line-height를 준 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/9xCe6/btrITmFttA6/yveUZCVFYTBAIKYVPZY0e0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F9xCe6%2FbtrITmFttA6%2FyveUZCVFYTBAIKYVPZY0e0%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;499&quot; height=&quot;516&quot; data-origin-width=&quot;556&quot; data-origin-height=&quot;575&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;01. line-height를 준 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순하게 p 태그에 line-height: 300px 정도 주고 맞춰본 모습이다. 글 한 줄이 굉장히 많은 영역을 차지하게 하여 가운데에 배치되도록 한 모습이다. line-height는 텍스트 한 줄을 세로 정렬할 때 사용하면 쓸만하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- padding&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;551&quot; data-origin-height=&quot;601&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/NTDnc/btrIOwJrf27/0ao36y1WsiIErEY3cXOqJ1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/NTDnc/btrIOwJrf27/0ao36y1WsiIErEY3cXOqJ1/img.png&quot; data-alt=&quot;02. padding-top을 준 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/NTDnc/btrIOwJrf27/0ao36y1WsiIErEY3cXOqJ1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FNTDnc%2FbtrIOwJrf27%2F0ao36y1WsiIErEY3cXOqJ1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;551&quot; height=&quot;601&quot; data-origin-width=&quot;551&quot; data-origin-height=&quot;601&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;02. padding-top을 준 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음으로, padding-top을 150px정도 줬다. 박스의 녹색 부분을 보면 패딩의 상단부분을 주면서 가운데로 내려왔음을 확인 가능하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;- margin&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;549&quot; data-origin-height=&quot;579&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/btkqSZ/btrITmFtA5W/PAMHrj2uWPuBUMmJwV75Yk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/btkqSZ/btrITmFtA5W/PAMHrj2uWPuBUMmJwV75Yk/img.png&quot; data-alt=&quot;03. margin-top을 준 모습&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/btkqSZ/btrITmFtA5W/PAMHrj2uWPuBUMmJwV75Yk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbtkqSZ%2FbtrITmFtA5W%2FPAMHrj2uWPuBUMmJwV75Yk%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;549&quot; height=&quot;579&quot; data-origin-width=&quot;549&quot; data-origin-height=&quot;579&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;03. margin-top을 준 모습&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;마지막으로, margin-top을 150px 정도 준 모습이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;세 방법 모두 px(픽셀) 단위로 줬기 때문에 반응형 웹에서는 치명적이다. rem이나 em 단위를 사용하는 것이 반응형에 잘 대처할 수 있다. 하지만 눈 대중으로 픽셀을 주고 가운데 정렬 시키는 방법 보다는 아래의 방법을 추천한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;해결방법 2. Flex의 Content를 정렬하는 방법 (추천)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://developer.mozilla.org/ko/docs/Web/CSS/align-content&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;MDN align-content&lt;/a&gt;를 보면 flex의 아이템에 관하여 정렬하는 방법이 자세히 나와있다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1659536807378&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; style=&quot;display: flex; align-items: center&quot;&amp;gt;
            &amp;lt;p&amp;gt;개발자 신재윤입니다 :)&amp;lt;/p&amp;gt;
            &amp;lt;img src=&quot;./광안리.png&quot; /&amp;gt;
        &amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이렇게 flex의 아이템들에 관하여 align-items: center로 가운데 정렬 시킬 수 있고&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1659536877236&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; style=&quot;display: flex&quot;&amp;gt;
            &amp;lt;p style=&quot;align-self: center&quot;&amp;gt;개발자 신재윤입니다 :)&amp;lt;/p&amp;gt;
            &amp;lt;img src=&quot;./광안리.png&quot; /&amp;gt;
        &amp;lt;/div&amp;gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;p 태그에 align-self: center를 이용하여 자기자신을 가운데 정렬 시킬 수도 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;눈대중으로 하는 방법보다는 이 방법이 훨씬 깔끔하지 않은가?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Bootstrap 사용 시&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;사실, 해당하는 문제는 부트스트랩을 사용하면서 겪었다. 부트스트랩 유틸리티에서 vertical-align: middle;과 동일한 역할을 하는 align-middle을 줬는데 아무리 해도 수직정렬이 되지 않았다. 애초에 &amp;lt;p&amp;gt; 태그에 계속 inline에서 사용 가능한 vertical을 적용하려고 하니 될리가 있나..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://getbootstrap.com/docs/5.1/utilities/vertical-align/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Bootstrap Docs vertical&lt;/a&gt;에서도 &quot;&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;To vertically center non-inline content (like&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&amp;lt;div&amp;gt;&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;s and more), use our&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;flex box utilities&lt;span style=&quot;background-color: #ffffff; color: #212529;&quot;&gt;.&quot;라고 떡하니 나와있다. &amp;lt;div&amp;gt;는 flex box utilities를 사용하세요!&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: #ffffff; color: #212529;&quot;&gt;&lt;a href=&quot;https://getbootstrap.com/docs/5.1/utilities/flex/#align-items&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Bootstrap Docs aligns&lt;/a&gt;를 살펴보면 flex item들을 정렬하는 것이 잘 나와있었다. 부트스트랩을 사용한 수직 정렬의 코드 최종본은 아래와 같다.&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_1659537277809&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;p class=&quot;align-self-center&quot;&amp;gt;개발자 신재윤입니다 :)&amp;lt;/p&amp;gt;
            &amp;lt;img src=&quot;./광안리.png&quot; /&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 data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;사실, 굉장히 단순한 것인데 한 번은 제대로 정리하고 넘어가야겠다 싶어서 이렇게 정리하게 되었다. inline-block을 이용한 수직정렬은 앞으로 잘 사용하지 않을 것 같고 flex나 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;b&gt;※ 본 게시글은 공부하면서 작성한 내용이라, 틀린 점이 있을 수 있습니다. 질문 사항이나 틀린 부분은 댓글을 남겨주시기 바랍니다.&lt;/b&gt;&lt;/p&gt;</description>
      <category>Language/HTML, CSS</category>
      <category>css</category>
      <category>flex</category>
      <category>flex align</category>
      <category>flex box</category>
      <category>flex vertical align</category>
      <category>flex 수직정렬</category>
      <author>Dev Uni</author>
      <guid isPermaLink="true">https://jae-yoon.tistory.com/7</guid>
      <comments>https://jae-yoon.tistory.com/7#entry7comment</comments>
      <pubDate>Wed, 3 Aug 2022 23:36:27 +0900</pubDate>
    </item>
    <item>
      <title>[Computer Architecture] 컴퓨터 성능 지표</title>
      <link>https://jae-yoon.tistory.com/6</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span&gt;Performance Metrics&lt;/span&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;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;There&amp;nbsp;are&amp;nbsp;many&amp;nbsp;ways&amp;nbsp;to&amp;nbsp;define&amp;nbsp;something&amp;nbsp;as&amp;nbsp;&quot;&lt;b&gt;the&amp;nbsp;best&lt;/b&gt;&quot;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 어떠한 기준을 잡느냐에 따라 최고의 성능을 낸다고 판단할 수 있다는 의미이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;750&quot; data-origin-height=&quot;322&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/SqEOE/btryyBHXBak/lwkZxRtTh7PLMqkmKMUIM0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/SqEOE/btryyBHXBak/lwkZxRtTh7PLMqkmKMUIM0/img.png&quot; data-alt=&quot;이미지. 항공기 성능에 관한 판단&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/SqEOE/btryyBHXBak/lwkZxRtTh7PLMqkmKMUIM0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FSqEOE%2FbtryyBHXBak%2FlwkZxRtTh7PLMqkmKMUIM0%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;750&quot; height=&quot;322&quot; data-origin-width=&quot;750&quot; data-origin-height=&quot;322&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;항공기의 예시로, 승객 수용량에 따라, 비행 시간에 따라, 속도에 따라, throughput에 따라, 여러 기준에 따라 성능이 최고인 것이 판가름 나는 것과 동일하게 컴퓨터의 성능 또한 마찬가지이다. 컴퓨터의 경우 &lt;span&gt;&lt;u&gt;프로세서 성능이 뛰어난 것을 기준으로 잡는지&lt;/u&gt; 혹은 &lt;u&gt;메모리 크기를 기준으로 잡는지&lt;/u&gt; &lt;b&gt;각기 다르게 성능을 평가&lt;/b&gt;할 수 있다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;무조건 최고로 하면 되지 않느냐고 물어볼 수 있지만&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&lt;b&gt;가격과 성능을 생각한 절충안을 고려&lt;/b&gt;해야 한다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div id=&quot;hwpEditorBoardContent&quot; data-hjsonver=&quot;1.0&quot; data-jsonlen=&quot;6530&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;성능을 평가하는 것은 매우 중요한 일이다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;컴퓨터를 구매하는 고객에게도 중요하고&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;새로운 기술을 개발하여 전작과 성능을 비교하는 개발자&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;소프트웨어를 개발하는 개발자 등 많은 사람이 필요로 한다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;이렇게 성능을 평가하는 것에 있어서 여러 가지 &lt;/span&gt;&lt;span&gt;지표&lt;/span&gt;&lt;span&gt;가 있다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;/div&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;361&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/5IEsf/btryDjM9VAR/kQkZpkbPNDDpSDYfco0Ee0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/5IEsf/btryDjM9VAR/kQkZpkbPNDDpSDYfco0Ee0/img.png&quot; data-alt=&quot;이미지. 컴퓨터 성능 측정에 관한 여러 지표&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/5IEsf/btryDjM9VAR/kQkZpkbPNDDpSDYfco0Ee0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F5IEsf%2FbtryDjM9VAR%2FkQkZpkbPNDDpSDYfco0Ee0%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;361&quot; data-origin-width=&quot;647&quot; data-origin-height=&quot;361&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이미지. 컴퓨터 성능 측정에 관한 여러 지표&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;아래의 하드웨어 영역에서 위의 소프트웨어 영역까지 여러 가지 지표가 있는데 ISA를 설명하기 이전이기 때문에&lt;/span&gt;&lt;span&gt;&amp;nbsp;하드웨어&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;부분의 지표에 관하여 먼저 설명한다. &lt;/span&gt;&lt;span&gt;여기 나온 지표들은 보통 &lt;b&gt;시간과 관련&lt;/b&gt;이 있다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;&lt;b&gt;시간이 짧게 소요되면 더 빠르게 실행할 수 있고 성능이 좋다는 것으로 이해&lt;/b&gt;한다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div id=&quot;hwpEditorBoardContent&quot; data-hjsonver=&quot;1.0&quot; data-jsonlen=&quot;8531&quot;&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span&gt;CPU execution tim&lt;/span&gt;&lt;/b&gt;&lt;b&gt;&lt;span&gt;e&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;div id=&quot;hwpEditorBoardContent&quot; data-hjsonver=&quot;1.0&quot; data-jsonlen=&quot;6250&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;Wall-clock time&lt;/b&gt;이란,&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;u&gt;특정한 작업을 수행하는데 소요된 실제 시간&lt;/u&gt;이다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;하지만 &lt;u&gt;이는 성능 평가에 적합하지 않는데&lt;/u&gt;&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;그 이유로는 &lt;/span&gt;&lt;span&gt;&lt;b&gt;CPU execution time &lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;이외에 다른 프로그램들도 포함하기 때문에 우리가 원하는 특정 작업에 대한 성능 평가가 어렵기 때문&lt;/b&gt;이다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;&lt;b&gt;&lt;span&gt;CPU execution time&lt;/span&gt;&lt;/b&gt;&lt;span&gt;은 &lt;u&gt;특정한 작업을 할 때 &lt;/u&gt;&lt;/span&gt;&lt;u&gt;&lt;span&gt;CPU&lt;/span&gt;&lt;/u&gt;&lt;span&gt;&lt;u&gt;가 소요한 시간&lt;/u&gt;을 의미하고 &lt;/span&gt;&lt;span&gt;Wall-clock time&lt;/span&gt;&lt;span&gt;과는 다르게 &lt;b&gt;불필요한 작업을 배제해서 우리가 원하는 특정 작업에 대한 성능 평가를 정확하게 수행&lt;/b&gt;할 수 있다&lt;/span&gt;&lt;span&gt;. CPU &lt;/span&gt;&lt;span&gt;성능은 실행시간과 밀접한 연관이 있다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;실행시간이 짧다는 것이 성능이 좋다는 것이므로 아래와 같은 식이 나온다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;blockquote data-hjsonver=&quot;1.0&quot; data-jsonlen=&quot;6646&quot; data-ke-style=&quot;style1&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;348&quot; data-origin-height=&quot;84&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/ljKLv/btryBsjMlx6/YftnV2JbJbhw5wt6h2qzYk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/ljKLv/btryBsjMlx6/YftnV2JbJbhw5wt6h2qzYk/img.png&quot; data-alt=&quot;이미지. Performance 공식&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/ljKLv/btryBsjMlx6/YftnV2JbJbhw5wt6h2qzYk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FljKLv%2FbtryBsjMlx6%2FYftnV2JbJbhw5wt6h2qzYk%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;348&quot; height=&quot;84&quot; data-origin-width=&quot;348&quot; data-origin-height=&quot;84&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이미지. Performance 공식&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;div id=&quot;hwpEditorBoardContent&quot; data-hjsonver=&quot;1.0&quot; data-jsonlen=&quot;6556&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;CPU execution time&lt;/span&gt;&lt;span&gt;을 알기 위해 &lt;/span&gt;&lt;b&gt;&lt;span&gt;CPU Clock&lt;/span&gt;&lt;/b&gt;&lt;span&gt;을 알아야 한다&lt;/span&gt;&lt;span&gt;. CPU Clock은 CPU에서&lt;/span&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;u&gt;&lt;span&gt;0&lt;/span&gt;&lt;span&gt;과 &lt;/span&gt;&lt;span&gt;1&lt;/span&gt;&lt;/u&gt;&lt;span&gt;&lt;u&gt;의 전기적인 신호&lt;/u&gt;를 보내는 신호인데&lt;/span&gt;&lt;span&gt;, 0 -&amp;gt; 1 -&amp;gt; 0&lt;/span&gt;&lt;span&gt;에서 &lt;/span&gt;&lt;span&gt;0 -&amp;gt; 1 &lt;/span&gt;&lt;span&gt;&lt;u&gt;한 번의 사이클&lt;/u&gt;이 바로 &lt;/span&gt;&lt;b&gt;&lt;span&gt;Clock cycle&lt;/span&gt;&lt;/b&gt;&lt;span&gt;이다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;하나의 상승 에지에서 다음의 상승 에지까지 걸리는 시간을 정확하게는 &lt;/span&gt;&lt;b&gt;&lt;span&gt;Clock cycle time&lt;/span&gt;&lt;/b&gt;&lt;span&gt;이라고 한다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;Clock frequency&lt;/span&gt;&lt;span&gt;는 &lt;/span&gt;&lt;span&gt;Clock cycle time &lt;/span&gt;&lt;span&gt;역수이다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;클록을 사용하는 이유는&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;&lt;b&gt;하드웨어에서 동기화할 수 있는 기준신호를 준다면 회로 내부의 다른 회로들이 클록에 맞추어 동기화를 하여 더 뛰어난 성능을 내기 때문&lt;/b&gt;이다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;즉&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;빠르게 작동하여 실행시간이 짧아지면 성능이 좋아진다는 뜻이다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;그러면 클록을 매우 빠르게 하면 성능이 좋아지기야 하겠지만 다른 회로들이 클록의 신호를 못 따라가게 된다&lt;/span&gt;&lt;span&gt;. &lt;u&gt;이러한 이유 때문에&lt;/u&gt;&lt;/span&gt;&lt;u&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;span&gt;최대 출력 주파수&lt;/span&gt;&lt;/u&gt;&lt;span&gt;&lt;u&gt;가 존재하는 것&lt;/u&gt;이다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;조합회로의 내부에 여러 개의 경로 중 가장 긴 경로를 &lt;/span&gt;&lt;span&gt;critical path&lt;/span&gt;&lt;span&gt;라고 하는데 이것이 &lt;/span&gt;&lt;span&gt;clock cycle time&lt;/span&gt;&lt;span&gt;을 결정한다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;따라서&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;아래와 같은 실행시간 식이 나오게 된다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;501&quot; data-origin-height=&quot;101&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/y59ao/btryDJR3FHH/VlXUz7LCRlTOVm4fdtC3DK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/y59ao/btryDJR3FHH/VlXUz7LCRlTOVm4fdtC3DK/img.png&quot; data-alt=&quot;이미지. CPU Execution time 공식&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/y59ao/btryDJR3FHH/VlXUz7LCRlTOVm4fdtC3DK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fy59ao%2FbtryDJR3FHH%2FVlXUz7LCRlTOVm4fdtC3DK%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;101&quot; data-origin-width=&quot;501&quot; data-origin-height=&quot;101&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이미지. CPU Execution time 공식&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;그러나&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;실행시간을 가지고 성능 평가를 하는 것은 최대 출력 주파수와 클럭 주파수의 관계 때문에 부족함이 있다&lt;/span&gt;&lt;span&gt;. 예를 들어, 노트북이 돌아가면서 우웅~ 소리를 내며 발열이 심해지면, 최대 출력 주파수보다 좀 낮게 동작 클럭 주파수를 설정해서 온도를 조절하는 경우가 있다. 그렇기 때문에 항상 일정한 값을 가지는 것이 아니라 실행시간이라고 딱 말하기에는 부족한 부분이 있다. &lt;/span&gt;&lt;span&gt;그래서 새로운 지표를 제시한 것이 바로 &lt;/span&gt;&lt;b&gt;&lt;span&gt;CPI&lt;/span&gt;&lt;/b&gt;&lt;span&gt;이다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;div id=&quot;hwpEditorBoardContent&quot; data-hjsonver=&quot;1.0&quot; data-jsonlen=&quot;6444&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div data-hjsonver=&quot;1.0&quot; data-jsonlen=&quot;6444&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span&gt;CPI &lt;/span&gt;&lt;span&gt;&amp;ndash; &lt;/span&gt;&lt;span&gt;Cycles Per Instruction &lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;div id=&quot;hwpEditorBoardContent&quot; data-hjsonver=&quot;1.0&quot; data-jsonlen=&quot;6263&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;&lt;b&gt;&lt;span&gt;CPI&lt;/span&gt;&lt;/b&gt;&lt;span&gt;는 &lt;u&gt;명령어 하나를 수행하는데 필요한 클록 사이클의 수&lt;/u&gt;를 뜻한다&lt;/span&gt;&lt;span&gt;. ( &lt;b&gt;IPC&lt;/b&gt;&lt;/span&gt;&lt;span&gt;는 &lt;u&gt;하나의 클록 사이클이 수행할 수 있는 명령어의 수&lt;/u&gt;를 뜻한다&lt;/span&gt;&lt;span&gt;. ) CPI&lt;/span&gt;&lt;span&gt;에서 클록 사이클의 수는 평균값을 사용한다&lt;/span&gt;&lt;span&gt;. CPI&lt;/span&gt;&lt;span&gt;에도 여러 가지 단점이 있는데&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;프로세서에 의해서만 결정되는 것이 아니라 메모리&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;버스 등을 신경 쓰는 것이고 평균값을 사용하는 것에 있어서 생기는 왜곡 등이 있다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;성능을 증가시키려면 클록 주파수를 늘려서 &lt;/span&gt;&lt;span&gt;( &lt;/span&gt;&lt;span&gt;클록 사이클 시간을 줄여서 &lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;하는 방법이 있고 &lt;/span&gt;&lt;span&gt;CPI &lt;/span&gt;&lt;span&gt;수를 줄이는 &lt;/span&gt;&lt;span&gt;( &lt;/span&gt;&lt;span&gt;명령어 수를 줄이는 &lt;/span&gt;&lt;span&gt;) &lt;/span&gt;&lt;span&gt;방법이 있다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;그래서 아래와 같은 식이 나온다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;div id=&quot;hwpEditorBoardContent&quot; data-hjsonver=&quot;1.0&quot; data-jsonlen=&quot;7416&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;644&quot; data-origin-height=&quot;109&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/0nGcq/btryExX7FYC/QyB2QKGrgFky9MFPGmLPck/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/0nGcq/btryExX7FYC/QyB2QKGrgFky9MFPGmLPck/img.png&quot; data-alt=&quot;이미지. CPI 이용 Execution time&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/0nGcq/btryExX7FYC/QyB2QKGrgFky9MFPGmLPck/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2F0nGcq%2FbtryExX7FYC%2FQyB2QKGrgFky9MFPGmLPck%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;644&quot; height=&quot;109&quot; data-origin-width=&quot;644&quot; data-origin-height=&quot;109&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이미지. CPI 이용 Execution time&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;위에서 언급한 &lt;/span&gt;&lt;span&gt;CPI&lt;/span&gt;&lt;span&gt;의 단점 중 &lt;u&gt;평균값을 사용한다는 것&lt;/u&gt;이 있었다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;이게 무슨 말이냐 하면 명령어 연산에서 산술연산과 논리연산 등 여러 가지 연산이 있는데 이 &lt;b&gt;연산마다 처리 속도가 달라서 평균을 사용하면 왜곡이 생기는 것&lt;/b&gt;이다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;이를 해결하는 방법이 각각의 명령어에 계산을 수행하는 &lt;/span&gt;&lt;b&gt;&lt;span&gt;instruction mix&lt;/span&gt;&lt;span&gt; &lt;/span&gt;&lt;/b&gt;&lt;span&gt;방법이다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote id=&quot;hwpEditorBoardContent&quot; data-hjsonver=&quot;1.0&quot; data-jsonlen=&quot;7600&quot; data-ke-style=&quot;style1&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;662&quot; data-origin-height=&quot;171&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/mXHFJ/btryCjGU1nj/A9cXVKkGW4lRg3RiM3nKuK/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/mXHFJ/btryCjGU1nj/A9cXVKkGW4lRg3RiM3nKuK/img.png&quot; data-alt=&quot;이미지. Instruction mix 방법 공식&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/mXHFJ/btryCjGU1nj/A9cXVKkGW4lRg3RiM3nKuK/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FmXHFJ%2FbtryCjGU1nj%2FA9cXVKkGW4lRg3RiM3nKuK%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;662&quot; height=&quot;171&quot; data-origin-width=&quot;662&quot; data-origin-height=&quot;171&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이미지. Instruction mix 방법 공식&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/blockquote&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span&gt;MIPS &lt;/span&gt;&lt;span&gt;&amp;ndash; &lt;/span&gt;&lt;span&gt;Million Instructions Per Second, MFLOPS&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;div id=&quot;hwpEditorBoardContent&quot; data-hjsonver=&quot;1.0&quot; data-jsonlen=&quot;6281&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;다음으로 컴퓨터 성능에 관련된 지표로는 &lt;/span&gt;&lt;b&gt;&lt;span&gt;MIPS&lt;/span&gt;&lt;/b&gt;&lt;span&gt;이다&lt;/span&gt;&lt;span&gt;. MIPS &lt;/span&gt;&lt;span&gt;이전에 &lt;/span&gt;&lt;span&gt;GIPS&lt;/span&gt;&lt;span&gt;가 있었는데&lt;/span&gt;&lt;span&gt;, GIPS&lt;/span&gt;&lt;span&gt;는 성능이 좋아질수록 값이 작아져서 직관적이지 못해 &lt;/span&gt;&lt;span&gt;MIPS&lt;/span&gt;&lt;span&gt;로 대체되었다&lt;/span&gt;&lt;span&gt;. (값이 크면 성능이 좋다는 것이 아무래도 직관적이니까) MIPS&lt;/span&gt;&lt;span&gt;는 성능이 좋을수록 값이 커져서 직관적이다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;하지만 이 역시 &lt;b&gt;명령어 수나 프로그램 간 다양성 때문에 문제점이 있다&lt;/b&gt;&lt;/span&gt;&lt;span&gt;&lt;b&gt;.&lt;/b&gt;&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;또다른 지표인 &lt;b&gt;MFLOPS&lt;/b&gt;&lt;/span&gt;&lt;span&gt;는 &lt;/span&gt;&lt;span&gt;Floating-point &lt;/span&gt;&lt;span&gt;관련 지표이다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span&gt;컴퓨터 성능 측정 방법&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;지표가 아닌 &lt;b&gt;성능을 측정하는 방법&lt;/b&gt;에 보통 쓰이는 것에 &lt;/span&gt;&lt;b&gt;&lt;span&gt;Response time&lt;/span&gt;&lt;/b&gt;&lt;span&gt;과 &lt;/span&gt;&lt;b&gt;&lt;span&gt;Throughput&lt;/span&gt;&lt;/b&gt;&lt;span&gt;이 있다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;&lt;u&gt;일의 시작부터 끝까지 걸리는 시간이 응답시간&lt;/u&gt;이고 &lt;u&gt;주어진 시간 안에 얼마나 많은 일을 수행하냐&lt;/u&gt;는 게 &lt;/span&gt;&lt;span&gt;Throughput&lt;/span&gt;&lt;span&gt;이다&lt;/span&gt;&lt;span&gt;. Throughput을 조금 더 간단하게 설명하면 &lt;u&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&gt;&lt;/span&gt;&lt;span&gt;Response time과 Throughput을 알아볼 때&amp;nbsp;&lt;b&gt;순차적인 처리 방법 &lt;/b&gt;&lt;/span&gt;&lt;b&gt;&lt;span&gt;Sequential&lt;/span&gt;&lt;/b&gt;&lt;span&gt;과 &lt;b&gt;공장에서 찍어내는 듯한 &lt;/b&gt;&lt;/span&gt;&lt;b&gt;&lt;span&gt;Pipelined &lt;/span&gt;&lt;/b&gt;&lt;span&gt;&lt;b&gt;방법&lt;/b&gt;이 있다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;순차적으로 일을 처리하면 놀고 있는 자원이 생겨서 &lt;/span&gt;&lt;span&gt;throughput&lt;/span&gt;&lt;span&gt;이 낮아진다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;놀고 있는 자원이 발생하지 않게 &lt;/span&gt;&lt;span&gt;Pipelined &lt;/span&gt;&lt;span&gt;방식으로 하면 총 시간이 단축되면서 &lt;/span&gt;&lt;span&gt;throughput&lt;/span&gt;&lt;span&gt;이 높아진다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;637&quot; data-origin-height=&quot;426&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/OUCbJ/btryDQRuq1x/Qu9q4EyaMNGbCCqgTA1iG1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/OUCbJ/btryDQRuq1x/Qu9q4EyaMNGbCCqgTA1iG1/img.png&quot; data-alt=&quot;이미지. Sequential 방법&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/OUCbJ/btryDQRuq1x/Qu9q4EyaMNGbCCqgTA1iG1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FOUCbJ%2FbtryDQRuq1x%2FQu9q4EyaMNGbCCqgTA1iG1%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;637&quot; height=&quot;426&quot; data-origin-width=&quot;637&quot; data-origin-height=&quot;426&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이미지. Sequential 방법&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;686&quot; data-origin-height=&quot;427&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xncZw/btryCjGVtjy/s2oDqRLRspJ2fwPkdBW9Q1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xncZw/btryCjGVtjy/s2oDqRLRspJ2fwPkdBW9Q1/img.png&quot; data-alt=&quot;이미지. Pipelined 방법&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xncZw/btryCjGVtjy/s2oDqRLRspJ2fwPkdBW9Q1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxncZw%2FbtryCjGVtjy%2Fs2oDqRLRspJ2fwPkdBW9Q1%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;686&quot; height=&quot;427&quot; data-origin-width=&quot;686&quot; data-origin-height=&quot;427&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이미지. Pipelined 방법&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;마지막으로, 위와 같은 것을 컴퓨터에서 측정할 때 &lt;/span&gt;&lt;b&gt;&lt;span&gt;Benchmark&lt;/span&gt;&lt;/b&gt;&lt;span&gt;를 이용한다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;측정하고자 원하는 성능을 타겟팅하여 벤치마크를 이용한다&lt;/span&gt;&lt;span&gt;. &lt;/span&gt;&lt;span&gt;어떤 것을 측정할지 확실하게 정하고 벤치마크 프로그램을 이해하며 다양하고 적절한 지표를 사용하여 올바르게 이용해야 한다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;&lt;span&gt;Amdahl&amp;rsquo;s law&lt;/span&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;&lt;b&gt;암달의 법칙&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #202122;&quot;&gt;(Amdahl's law)은&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;/span&gt;&lt;b&gt;암달의 저주&lt;/b&gt;&lt;span style=&quot;background-color: #ffffff; color: #202122;&quot;&gt;로도 불리며 컴퓨터 &lt;u&gt;시스템의 일부를 개선할 때&lt;/u&gt; &lt;b&gt;전체적으로&lt;/b&gt; &lt;u&gt;얼마만큼의 최대 성능 향상이 있는지 계산하는 데 사용&lt;/u&gt;된다.&lt;span&gt; 즉, &lt;span&gt;실행시간을 계산할 때 전체적인 시간에서&lt;b&gt;&lt;span&gt;&amp;nbsp;&lt;/span&gt;영향을 받은 시간&lt;/b&gt;과&lt;span&gt;&amp;nbsp;&lt;/span&gt;&lt;b&gt;영향을 받지 않은 시간&lt;/b&gt;을 나누어서 이해해야 한다는 것이다&lt;/span&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote id=&quot;hwpEditorBoardContent&quot; data-hjsonver=&quot;1.0&quot; data-jsonlen=&quot;6417&quot; data-ke-style=&quot;style1&quot;&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;602&quot; data-origin-height=&quot;91&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/b9M96s/btryBsqxU8R/Y2KAePtC2DUehGVFnl88Bk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/b9M96s/btryBsqxU8R/Y2KAePtC2DUehGVFnl88Bk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/b9M96s/btryBsqxU8R/Y2KAePtC2DUehGVFnl88Bk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fb9M96s%2FbtryBsqxU8R%2FY2KAePtC2DUehGVFnl88Bk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;602&quot; height=&quot;91&quot; data-origin-width=&quot;602&quot; data-origin-height=&quot;91&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;632&quot; data-origin-height=&quot;79&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bERzgh/btryDRpk7CJ/iGrP1Fo0Nxglk9RuKT3Td0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bERzgh/btryDRpk7CJ/iGrP1Fo0Nxglk9RuKT3Td0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bERzgh/btryDRpk7CJ/iGrP1Fo0Nxglk9RuKT3Td0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbERzgh%2FbtryDRpk7CJ%2FiGrP1Fo0Nxglk9RuKT3Td0%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;632&quot; height=&quot;79&quot; data-origin-width=&quot;632&quot; data-origin-height=&quot;79&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;br /&gt;&lt;br /&gt;&lt;/blockquote&gt;
&lt;div id=&quot;hwpEditorBoardContent&quot; data-hjsonver=&quot;1.0&quot; data-jsonlen=&quot;6246&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div id=&quot;hwpEditorBoardContent&quot; data-hjsonver=&quot;1.0&quot; data-jsonlen=&quot;9568&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div id=&quot;hwpEditorBoardContent&quot; data-hjsonver=&quot;1.0&quot; data-jsonlen=&quot;6611&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;/div&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;마지막 이야기&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;현실에서 기술의 발달은 공학적인 관점 말고 &lt;b&gt;상업적인 관점&lt;/b&gt;에서도 매우 중요하다&lt;/span&gt;&lt;span&gt;.&amp;nbsp; &lt;/span&gt;&lt;span&gt;처음에 나온 혁신적인 제품은 가격이 매우 비싸지만 생산 공정이 발달하면서 가격이 점점 싸지기도 하고 시장과의 이해관계도 맞아야 한다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt; &lt;/span&gt;&lt;span&gt;현재&lt;/span&gt;&lt;span&gt;, &lt;/span&gt;&lt;span&gt;나노 공정에서 &lt;/span&gt;&lt;span&gt;TSMC&lt;/span&gt;&lt;span&gt;사와 삼성전자가 힘 겨루기를 하고 있는데 만약 생산 공정에서 &lt;/span&gt;&lt;span&gt;1nm &lt;/span&gt;&lt;span&gt;이하의 영역으로 가게 되면 &lt;/span&gt;&lt;span&gt;Quantum &lt;/span&gt;&lt;span&gt;영역으로 가기 때문에 우리가 알던 기존의 상식이 모두 깨질 수도 있다&lt;/span&gt;&lt;span&gt;.&lt;/span&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span&gt;하지만, 아직 그러한 시대가 완벽하게 도래한 것은 아니기도 하고 과거의 역사를 잊지 않고 그를 알아야 더 나아갈 수 있기 때문에 성능에 관한 여러 지표들, 측정에 관한 방법들을 한 번 쯤은 알아야 할 필요가 있다.&lt;/span&gt;&lt;/p&gt;
&lt;div id=&quot;hwpEditorBoardContent&quot; data-hjsonver=&quot;1.0&quot; data-jsonlen=&quot;7491&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div data-hjsonver=&quot;1.0&quot; data-jsonlen=&quot;7491&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div data-hjsonver=&quot;1.0&quot; data-jsonlen=&quot;7491&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div data-hjsonver=&quot;1.0&quot; data-jsonlen=&quot;7491&quot;&gt;&lt;b&gt;※ 본 게시글은 공부하면서 작성한 내용이라, 틀린 점이 있을 수 있습니다. 질문 사항이나 틀린 부분은 댓글을 남겨주시기 바랍니다.&lt;/b&gt;&lt;/div&gt;</description>
      <category>Computer Science/컴퓨터구조</category>
      <category>Computer Architecture</category>
      <category>CPI</category>
      <category>CPU execution time</category>
      <category>컴퓨터 성능 지표</category>
      <category>컴퓨터 성능 측정</category>
      <category>컴퓨터 성능 향상</category>
      <category>컴퓨터구조</category>
      <author>Dev Uni</author>
      <guid isPermaLink="true">https://jae-yoon.tistory.com/6</guid>
      <comments>https://jae-yoon.tistory.com/6#entry6comment</comments>
      <pubDate>Thu, 7 Apr 2022 00:36:48 +0900</pubDate>
    </item>
    <item>
      <title>[Python] 리스트 자료형이 있지만, 튜플 자료형이 필요한 이유</title>
      <link>https://jae-yoon.tistory.com/4</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;리스트 자료형? 튜플 자료형?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;프로그래밍 언어에 연관성이 존재하는 데이터를 나열하는 방법을 흔히 &quot;배열&quot;이라고 불리는 형태로 많이 사용한다. 컴퓨터 공학에 입문할 때 배우는 대표적인 언어인 C언어에도 이 배열이라는 형태가 있다. C언어에서 배열을 배울 때 아래와 같은 형태를 먼저 배운다.&lt;/p&gt;
&lt;pre id=&quot;code_1645450000993&quot; class=&quot;c++ arduino&quot; data-ke-language=&quot;c++&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;

int main(void)
{
	int a[5] = {1, 2, 3, 4, 5}

	return 0;
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;C언어는 배열을 선언할 때 메모리에 해당하는 배열의 크기를 미리 할당한다. 위 코드에서 a 배열의 크기를 5로 지정했기 때문에 메모리의 5칸을 미리 할당 받는 것이다. 위에서는 정수형 자료를 5개 모두 넣었지만, 만약 &lt;code&gt;{1, 2}&lt;/code&gt;만 줬다고 하면 메모리의 나머지 3칸은 쓰레기 값이 들어가있는 상태이다.&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;즉, 메모리의 크기를 초기에 미리 정하여 선언하는 것이다. 그리고 처음에 정한 배열의 크기를 수정할 수 없다. 이를 변하지 않고 정적이다고 하여 &lt;b&gt;정적 배열&lt;/b&gt;이라고 한다. 물론 &lt;code&gt;malloc()&lt;/code&gt; 함수를 사용해서 동적 배열을 사용하는 방법도 있으나, 현재 python 관련 게시글이니까 깊게 들어가지는 않겠다. 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;하지만, 쉽고도 친숙한 언어인 Python 에서는 아주 쉽게 배열을 가지고 놀 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;리스트 자료형이 바로 C언어의 동적 배열이라고 받아들이면 되고 튜플 자료형이 정적 배열이라고 생각하면 된다. 더 자세하게 표현하자면, &lt;b&gt;리스트 자료형은 동적 배열이며 가변 객체를 사용&lt;/b&gt;한다. &lt;b&gt;튜플 자료형은 처음에 배열의 크기와 값을 선언하고 이 요소를 바꿀 수 없다. 즉, 불변 객체를 사용&lt;/b&gt;한다. 따라서, 파이썬에서 리스트를 선언하고 만들면 원하는대로 요소를 추가/수정/삭제 할 수 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파이썬의 내부를 살펴보면 대부분 C언어로 구현되어 있는데 이를 CPython이라고 한다. &lt;a href=&quot;https://github.com/zpoint/CPython-Internals/blob/master/BasicObject/list/list.md&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;Cpython - Github&lt;/a&gt;에서 리스트의 내부구조를 살펴보면,&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;asdf.png&quot; data-origin-width=&quot;503&quot; data-origin-height=&quot;347&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/p0bXu/btrtYc5osod/9in4wpEHcXaPaANjc4QJs1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/p0bXu/btrtYc5osod/9in4wpEHcXaPaANjc4QJs1/img.png&quot; data-alt=&quot;이미지. Github Cpython 리스트 내부 코드&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/p0bXu/btrtYc5osod/9in4wpEHcXaPaANjc4QJs1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fp0bXu%2FbtrtYc5osod%2F9in4wpEHcXaPaANjc4QJs1%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;347&quot; data-filename=&quot;asdf.png&quot; data-origin-width=&quot;503&quot; data-origin-height=&quot;347&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;이미지. Github Cpython 리스트 내부 코드&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;&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;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;실습을 통해 가변 객체, 불변 객체 메모리 위치 확인해보기&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파이썬에서는 모든 것을 객체로 취급한다. 리스트 자료형은 가변 객체, 튜플 자료형은 불변 객체라는 표현을 사용했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;가변 객체&lt;/b&gt;는 기존의 메모리 저장 위치에서 위치가 변경되지 않는다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;불변 객체&lt;/b&gt;는 메모리 위에 있는 값의 내용이 바뀌지 않는다. 따라서, 메모리 저장 위치가 바뀐다.&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;무슨 말인지 잘 와닿지 않을 것이다. 코드를 통해서 살펴보겠다.&lt;/p&gt;
&lt;pre id=&quot;code_1645956444528&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;str1 = &quot;hello&quot;
print(str1)
# 출력결과 : hello

str1 += &quot; world!&quot;
print(str1)
# 출력결과 : hello world!&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문자열 str은 대표적인 불변 객체이다. str1 변수는 hello라는 값을 가지고 있었는데 거기에 world!를 더해서 str1 변수의 값이 hello world!가 된 것 같이 보인다. 하지만, 메모리의 위치를 확인해보면 사실 hello 값 자체가 바뀐 것은 아니다.&lt;/p&gt;
&lt;pre id=&quot;code_1645956619749&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;str1 = &quot;hello&quot;
print(id(str1))
# 출력결과 : 140400021790896

str1 += &quot; world!&quot;
print(id(str1))
# 출력결과 : 140400021791152&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;메모리의 위치가 다른 것을 확인 가능하다. 즉, 값이 변경된 것이 아니라 새로운 문자열을 더하면서 새로운 객체를 형성하여 메모리의 위치가 바뀐 것이다. &lt;b&gt;불변 객체는 메모리 위에 있는 value를 변경하는 것이 아니다.&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;pre id=&quot;code_1645958105385&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;list1 = [1, 2, 3]
print(id(list1))
#출력결과 : 140032006714880

list1.append(4)
print(id(list1))
#출력결과 : 140032006714880&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;대표적인 &lt;b&gt;가변 객체&lt;/b&gt;인 리스트를 보면, 리스트에 내용을 추가해서 값을 수정해도 &lt;b&gt;메모리의 위치가 그대로&lt;/b&gt;인 것을 확인할 수 있다. 새로운 인덱스가 추가될 때 기존의 메모리 위치에서 메모리를 추가로 할당하여 인덱스가 추가되는 것을 확인할 수 있다.&lt;/p&gt;
&lt;pre id=&quot;code_1645958351598&quot; class=&quot;python&quot; data-ke-language=&quot;python&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;list1 = [1, 2, 3]
print(id(list1[0]))
print(id(list1[1]))
print(id(list1[2]))

list1.append(4)
print(id(list1[3]))

# 출력결과
# 9788608
# 9788640
# 9788672
# 9788704&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;리스트는 가변 객체, 튜플은 불변 객체 - 튜플 사용 이유는 ?&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;가변적으로 편리하게 변하는 배열인 리스트를 사용하면 되는데 굳이 값을 바꿀 수 없는 튜플을 사용하는 이유가 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&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;&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;솔직히, 웬만한 상황에서는 리스트를 사용하는 경우가 많겠지만, 프로그래머는 사용자가 더 좋은 성능으로 사용하도록 서비스를 제공해야 하기에 튜플이 성능 향상에 더 뛰어나다면 튜플을 사용해야 한다. 아직 내 수준에서는 리스트가 더 나은지 튜플이 더 나은지 상황을 판단할 능력이 부족해서 대부분 리스트를 사용할 것 같기는 하다. T_T&lt;/p&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;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;Reference&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;a href=&quot;https://ichi.pro/ko/python-ui-byeongyeong-ganeung-mich-byeongyeong-bulganeunghan-gaegche-18971482174035&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;가변객체와 불변객체&lt;/a&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;a href=&quot;https://fierycoding.tistory.com/59&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;튜플 사용 이유&lt;/a&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- &lt;a href=&quot;https://edykim.com/ko/post/python-list-vs.-tuple/&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot;&gt;리스트 vs 튜플의 문화적 관점&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;
&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;</description>
      <category>Language/Python</category>
      <category>가변객체</category>
      <category>리스트</category>
      <category>불변객체</category>
      <category>튜플</category>
      <category>파이썬</category>
      <author>Dev Uni</author>
      <guid isPermaLink="true">https://jae-yoon.tistory.com/4</guid>
      <comments>https://jae-yoon.tistory.com/4#entry4comment</comments>
      <pubDate>Mon, 21 Feb 2022 20:59:06 +0900</pubDate>
    </item>
    <item>
      <title>[Computer Science]컴파일러와 인터프리터</title>
      <link>https://jae-yoon.tistory.com/3</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;컴파일러(Compiler), 인터프리터(Interpreter)&lt;/b&gt;&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;파이썬 학습 도중, CS 공부하면서 대충 알고 넘겼던 컴파일러와 인터프리터에 대한 정리가 필요하겠다 싶어서 블로그 포스팅을 하기로 결정했다. 내 개발 블로그의 첫번째 주제는 컴파일러와 인터프리터에 대한 이해이다 ! 먼저, 기본적인 프로그래밍 언어에 관하여 설명을 하고 컴파일러와 인터프리터에 대한 비교를 진행하겠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;컴퓨터는 어떻게 프로그래밍 언어를 이해할까?&lt;/b&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;&lt;b&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;컴퓨터 본체라는 하드웨어가 있는 상태에서 뛰어난 개발자들이 프로그래밍 언어로 작성하여 개발한 운영체제, 어플리케이션을 활용하여 컴퓨터를 작동시킨다. 쉽게 말하여, &lt;b&gt;프로그래밍 언어는 컴퓨터와 의사 소통하기 위한 표현법&lt;/b&gt; 이다. 우리가 흔히 하는 SNS, 웹 사이트, 게임 모든 것은 프로그래밍 언어로 작성된다. 프로그래밍 언어는 흔히 &lt;b&gt;저급 언어(Low-Level language)&lt;/b&gt; 와 &lt;b&gt;고급 언어(High-Level language)&lt;/b&gt; 로 나뉜다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고급 언어(High-Level language)는 코딩 공부를 처음하면서 배웠던 C language, 혹은 Java, 지금 학습 중인 Python 등 &lt;b&gt;인간에게 그나마 친숙한 언어로 작성되어 있는 언어&lt;/b&gt; 를 뜻한다. 예를 들어, 표현 방법에 있어서 C언어의 출력은 &lt;code&gt;printf(&quot;Hello world!&quot;);&lt;/code&gt; Java의 경우 &lt;code&gt;System.out.print(&quot;Hello World!&quot;);&lt;/code&gt; Python의 경우 &lt;code&gt;print(&quot;Hello World!&quot;)&lt;/code&gt;이다. print나 system.out.print와 같은 문구를 보면 &quot;아, 현재 작성된 문법은 출력을 뜻하는 것이구나.&quot;라고 유추가 가능하다. 인간에게 친숙한 언어로 작성되어 있기 때문이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;저급 언어(Low-Level language)는 &lt;b&gt;컴퓨터가 이해하기 쉽게 작성된 프로그래밍 언어&lt;/b&gt;이다. 흔히, 어셈블리어(Assembly language)와 기계어(machine language)를 뜻한다. 어셈블리어는 add, lw와 같이 문법이 구성되어 있는 경우가 많은데 인간이 알아볼 수는 있지만 공부하지 않았다면 보고 뜻을 유추하기 힘든 경우가 많아진다. 기계어는 말 그대로 0과 1의 이진수로 이루어진 것이다. 컴퓨터는 결국 전자기기라서 전기적인 신호를 회로에 보내줘야 작동하니까 기계어까지의 변환 과정이 필요한 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;인간이 작성한 내용을 컴퓨터가 이해하여 작동하려면, 일련의 과정을 거친다. 이 과정을 &lt;b&gt;컴파일 과정&lt;/b&gt;이라고 한다. 소스 코드인 고급 언어를 컴파일러를 통하여 목적 코드인 어셈블리어로 변환한다. 그 다음에 소스 코드인 어셈블리어를 어셈블러를 통하여 목적 코드인 기계어로 변환한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/L6HS2/btrtHDwcvXs/X8BlXqT3V8gwfOi9XSJDc0/img.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;컴파일 과정은 왜 반드시 필요할까?&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;좁은 의미로 보면 인간이 작성한 언어를 컴퓨터가 이해하도록 변환해주는 것이지만, 조금 더 상세하게 보겠다. 컴퓨터 구조 전공 수업에서 들었던 내용이기도 한데, 컴퓨터를 이용하는 수많은 사용자들의 컴퓨터는 모두 동일한 것이 아니다. 쉽게 말하자면, 프로그래밍 언어의 고급 언어는 약속된 문법을 사용하기 때문에 윈도우인 내 컴퓨터로 python을 작성하든 맥북을 사용하는 옆집 철수의 컴퓨터로 python을 작성하든 똑같은 문법을 사용하여 똑같은 것을 작성할 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;그러나, 운영체제가 다르면 ISA(Instruction Set Architecture)도 다르고 컴퓨터가 작동하는 원리에 차이가 있을 수 밖에 없다.&lt;/b&gt; (ISA에 관련된 내용은 깊게 다뤄야해서 추후에 따로 포스팅 하겠다.) 같은 윈도우라도 window 7, 혹은 window 10과 같이 사용자의 컴퓨터들은 차이점이 반드시 존재한다. 컴퓨터 내부의 CPU, RAM 등 모든 부품에도 차이가 있기 때문에 사용자의 환경에 맞는 적절한 전기 신호를 보내야 하는데 인간이 작성한 고급 언어만 보고는 그런 작업을 할 수 없다. 컴파일 과정을 통해 각자의 환경에 맞는 어셈블리어로 변환하고 기계어로 변환해야 하는 것이다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&lt;b&gt;컴파일러가 뭔지 느낌은 오는데&amp;hellip; 그러면 인터프리터는?&lt;/b&gt;&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style3&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;두 친구는 비슷하면서도 확연히 다른 친구에요.&lt;/b&gt;&lt;br /&gt;&lt;b&gt;하지만, 시간이 지날수록 그 경계가 모호해지고 있어요. 구분하는 것에 중점을 두지는 마세요 !&lt;/b&gt;&lt;/p&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;컴파일러와 인터프리터가 하는 역할은 원래의 코드, 즉, 원시 코드, 소스 코드가 있는데 컴퓨터가 이해할 수 있게 목적 코드, object code로 변환해주는 역할을 수행한다. 각각의 특징을 살펴보면 &lt;b&gt;컴파일러는 소스 코드 전체를 목적 코드로 바꿔주고 컴퓨터에서 실행 가능하도록 한다. 쉽게 말해서 사람이 하는 말을 처음부터 끝까지 들은 후에 작업을 수행하는 것이다.&lt;/b&gt; 다음으로, &lt;b&gt;인터프리터는 소스 코드 한 줄 마다 번역함과 동시에 실행하는 작업을 수행한다. 쉽게 말해서 사람의 말을 동시통역 해준다고 이해하면 된다.&lt;/b&gt; 이때, 인터프리터는 줄 단위로 바로바로 프로그램이 실행되기 때문에 목적 프로그램이 따로 생성되지는 않는다. 인터프리터는 컴파일의 과정이 없는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;컴파일러&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;소스 코드 전체를 목적 코드로 번역하고 그 결과를 한 번에 실행&lt;/li&gt;
&lt;li&gt;번역과 실행 작업이 따로 진행된다. 번역의 과정은 오래 걸리지만, 실행의 과정은 빠르다.&lt;/li&gt;
&lt;li&gt;실행 프로그램이 따로 생성된다.&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size18&quot;&gt;&lt;b&gt;인터프리터&lt;/b&gt;&lt;/p&gt;
&lt;ol style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;소스 코드 한 줄 마다 번역과 실행이 동시에 이루어진다&lt;/li&gt;
&lt;li&gt;줄 단위로 진행되어 시분할 시스템에 유용하다.&lt;/li&gt;
&lt;li&gt;CPU 사용 시간의 낭비가 크다.&lt;/li&gt;
&lt;/ol&gt;
&lt;div style=&quot;text-align: center;&quot;&gt;
&lt;table style=&quot;border-collapse: collapse; width: 66.1628%; height: 217px;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot; data-ke-style=&quot;style13&quot;&gt;
&lt;tbody&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 19px;&quot;&gt;&amp;nbsp;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; text-align: center; height: 19px;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;컴파일러 (Compiler)&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.6121%; text-align: center; height: 19px;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;&lt;b&gt;인터프리터 (Interpreter)&lt;/b&gt;&lt;/span&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;번역 단위&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 19px;&quot;&gt;전체&lt;/td&gt;
&lt;td style=&quot;width: 33.6121%; height: 19px;&quot;&gt;한 줄 마다&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;실행 속도&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 19px;&quot;&gt;빠름&lt;/td&gt;
&lt;td style=&quot;width: 33.6121%; height: 19px;&quot;&gt;느림&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;번역 속도&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 19px;&quot;&gt;느림&lt;/td&gt;
&lt;td style=&quot;width: 33.6121%; height: 19px;&quot;&gt;빠름&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 19px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 19px;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;목적 코드&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 19px;&quot;&gt;생성 O&lt;/td&gt;
&lt;td style=&quot;width: 33.6121%; height: 19px;&quot;&gt;생성 X&lt;/td&gt;
&lt;/tr&gt;
&lt;tr style=&quot;height: 28px;&quot;&gt;
&lt;td style=&quot;width: 33.3333%; height: 28px;&quot;&gt;&lt;span style=&quot;color: #333333;&quot;&gt;예시&lt;/span&gt;&lt;/td&gt;
&lt;td style=&quot;width: 33.3333%; height: 28px;&quot;&gt;C, C++, Java Compiler&lt;/td&gt;
&lt;td style=&quot;width: 33.6121%; height: 28px;&quot;&gt;Python, JavaScript, Java Interpreter&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;/div&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;위의 표를 보면 실행 속도와 번역 속도에 차이가 있음을 볼 수 있다. 인터프리터는 한 줄, 행마다 번역을 하기 때문에 빠르지만, 프로그램 전체적으로 봤을 때는 줄마다 번역-&amp;gt;실행, 번역-&amp;gt;실행의 과정을 거쳐야하니까 컴파일러보다는 느리게 되는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;컴파일러와 인터프리터는 다르지만, 확실하게 다르다고 경계선을 그을 수는 없다. 최근에는 구분하지 않는 추세이다.&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바의 실행 원리를 통해 이를 설명하겠다.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/N2dEq/btrtLzlB7qa/Juyjyd1oLcHyA2Mujuvikk/img.png&quot; alt=&quot;&quot; /&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;자바는 컴파일러 방식과 인터프리터 방식을 모두 채택하고 있다. .java 파일을 javac 명령어를 통해 컴파일하면 바이트 코드로 작성된 .class 파일로 변환한다. 그러고 난 다음 인터프리터가 .class 파일의 코드를 한 줄 마다 읽어내려가면서 실행하는 원리이다. 파이썬 또한 마찬가지다. 인터프리터 언어라고 공식 홈페이지에 표기는 되어있지만, 프로그래머가 작성한 코드를 바이트 코드로 컴파일하고 VM(Virtual Machine)에서 라이브러리 모듈을 결합하여 변환된 바이트 코드를 실행하는 방식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;공부함에 있어서 프로그래밍 언어를 어떻게 컴퓨터가 이해하는지 간단하게 설명하며 컴파일러와 인터프리터를 알아보았다. 어떠한 언어가 컴파일러인지, 인터프리터인지 명확하게 구분하는 것은 중요하지 않고 컴파일러와 인터프리터 각각의 원리 자체가 중요하다고 생각된다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;※ 본 게시글은 공부하면서 작성한 내용이라, 틀린 점이 있을 수 있습니다. 질문 사항이나 틀린 부분은 댓글을 남겨주시기 바랍니다.&lt;/b&gt;&lt;/p&gt;</description>
      <category>Computer Science/프로그래밍 언어론</category>
      <category>compiler</category>
      <category>Interpreter</category>
      <category>Programming Language</category>
      <category>인터프리터</category>
      <category>컴파일러</category>
      <category>프로그래밍 언어</category>
      <author>Dev Uni</author>
      <guid isPermaLink="true">https://jae-yoon.tistory.com/3</guid>
      <comments>https://jae-yoon.tistory.com/3#entry3comment</comments>
      <pubDate>Fri, 18 Feb 2022 21:45:48 +0900</pubDate>
    </item>
  </channel>
</rss>