<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>동재</title>
    <link>https://dongjae.tistory.com/</link>
    <description>안녕하세요! 동재입니다!</description>
    <language>ko</language>
    <pubDate>Thu, 20 Aug 2026 05:35:17 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>동재씨</managingEditor>
    <image>
      <title>동재</title>
      <url>https://tistory1.daumcdn.net/tistory/5209506/attach/c40c5a513bcd4fffb026544c03ed7ab9</url>
      <link>https://dongjae.tistory.com</link>
    </image>
    <item>
      <title>좌충우돌 면접기</title>
      <link>https://dongjae.tistory.com/6</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;3000&quot; data-origin-height=&quot;1687&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/lKpQ6/btsQK62q7VC/qyygDUhI49nNaVTNluYh9k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/lKpQ6/btsQK62q7VC/qyygDUhI49nNaVTNluYh9k/img.png&quot; data-alt=&quot;베트남어와 영어와 한글이 섞인 고통의 현장... 신기한건 그럼에도 대화가 통한다!&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/lKpQ6/btsQK62q7VC/qyygDUhI49nNaVTNluYh9k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FlKpQ6%2FbtsQK62q7VC%2FqyygDUhI49nNaVTNluYh9k%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;3000&quot; height=&quot;1687&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;3000&quot; data-origin-height=&quot;1687&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;베트남어와 영어와 한글이 섞인 고통의 현장... 신기한건 그럼에도 대화가 통한다!&lt;/figcaption&gt;
&lt;/figure&gt;
&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;/h2&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;&lt;span style=&quot;color: #333333; text-align: start;&quot;&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;p data-ke-size=&quot;size16&quot;&gt;브라이언과 함께 백엔드 개발자 4명을 면접하는 자리였는데, 생각보다 많은 걸 배우게 된 경험이었습니다.&lt;/p&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;/h2&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;1244&quot; data-origin-height=&quot;1526&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/m7HzE/btsQHX658Ud/KXBwwSlHPCTwJvZD6HlXu0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/m7HzE/btsQHX658Ud/KXBwwSlHPCTwJvZD6HlXu0/img.png&quot; data-alt=&quot;일단은 가장 중요한 복장! TPO..&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/m7HzE/btsQHX658Ud/KXBwwSlHPCTwJvZD6HlXu0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fm7HzE%2FbtsQHX658Ud%2FKXBwwSlHPCTwJvZD6HlXu0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;515&quot; height=&quot;632&quot; data-origin-width=&quot;1244&quot; data-origin-height=&quot;1526&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;일단은 가장 중요한 복장! TPO..&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;lt;면접 문제 준비&amp;gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실무에서 자주 마주치는 상황들로 문제를 준비했어요:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;코드 리팩토링 문제&lt;/b&gt;: 하나의 메서드에 모든 로직이 들어있는 OrderService 개선하기&lt;/li&gt;
&lt;li&gt;&lt;b&gt;로깅 최적화&lt;/b&gt;: PaymentService에 적절한 로그 레벨과 위치 설정하기&lt;/li&gt;
&lt;li&gt;&lt;b&gt;Stream API 활용&lt;/b&gt;: 사용자 데이터 필터링, 정렬, 집계 처리&lt;/li&gt;
&lt;li&gt;&lt;b&gt;JavaScript 함수형 메서드&lt;/b&gt;: 배열 메서드를 활용한 데이터 처리&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;lt;지원자 프로필 분석&amp;gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;4명의 지원자가 있었는데, 모두 &lt;b&gt;1-2년차 개발자&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;b&gt;부이 민 치엔&lt;/b&gt;: JHipster, Docker 경험이 풍부한 풀스택 개발자&lt;/li&gt;
&lt;li&gt;&lt;b&gt;탄 코아&lt;/b&gt;: Spring Boot + React 조합으로 전자상거래 프로젝트 경험&lt;/li&gt;
&lt;li&gt;&lt;b&gt;부이 후 투안&lt;/b&gt;: Spring Security, OAuth2에 특화된 백엔드 개발자&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  예상과 달랐던 면접 현장&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;lt;언어 장벽의 현실&amp;gt;&lt;/h3&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;pre class=&quot;arduino&quot;&gt;&lt;code&gt;// 이 코드에서 문제점이 뭐라고 생각하세요?
public String processOrder(OrderRequest request) {
    // 100줄이 넘는 하나의 메서드...
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 질문을 할 때, 단순히 &quot;Split method&quot;라고 답하는 게 아니라 &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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;lt;예상치 못한 상황들&amp;gt;&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;당일 불참&lt;/b&gt;: 쿠옥뒤는 연락도 없이 오지 않았어요  (과자먹으며 40분 기다림..)&lt;/li&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;/ol&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1950&quot; data-origin-height=&quot;316&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/xDoz9/btsQLCtdogq/jfOSPQoCiDRrjMHKdoDx01/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/xDoz9/btsQLCtdogq/jfOSPQoCiDRrjMHKdoDx01/img.png&quot; data-alt=&quot;면접을 도와주는 보미가 알려줌.. 어쩐지 내 질문에 대답이 없더라..&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/xDoz9/btsQLCtdogq/jfOSPQoCiDRrjMHKdoDx01/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FxDoz9%2FbtsQLCtdogq%2FjfOSPQoCiDRrjMHKdoDx01%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1950&quot; height=&quot;316&quot; data-filename=&quot;blob&quot; data-origin-width=&quot;1950&quot; data-origin-height=&quot;316&quot;/&gt;&lt;/span&gt;&lt;figcaption&gt;면접을 도와주는 보미가 알려줌.. 어쩐지 내 질문에 대답이 없더라..&lt;/figcaption&gt;
&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  가장 인상 깊었던 순간들&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;lt;영어 실력보다 소통 의지&amp;gt;&lt;/h3&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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;로그를 찍는문제때:&lt;/p&gt;
&lt;pre class=&quot;java&quot; data-ke-language=&quot;java&quot;&gt;&lt;code&gt;@Service
public class PaymentService {
    public PaymentResult processPayment(String orderId, PaymentRequest request) {
    
	//복잡한 결제로직들..
        // 어디에 로그를 찍을것이며, 무슨 레벨, 무슨 파라미터를 넣어서 기록할건가요? 
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;로그를 해당 로직의 어느 부분에 찍어야하며, 로그래벨은 무엇으로 하고, 어떤 파라미터를 넣을건지 물어봣어요&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;답변:&lt;/b&gt;&lt;b&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;A 지원자&lt;/b&gt;: &quot;INFO level at start, ERROR when exception&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;b&gt;B 지원자&lt;/b&gt;: &quot;I think... we need DEBUG for input parameters, INFO for success, WARN for business logic problems, ERROR for system problems. Also, we should not log sensitive data like card numbers.&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;b&gt;B 지원자&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;&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;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;lt;기술 vs 소통 능력&amp;gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이번 면접을 통해 깨달은 핵심은 &lt;b&gt;&quot;기술 스택이 화려해도 소통이 안 되면 의미가 없다&quot;&lt;/b&gt;는 거였어요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제로 &lt;b&gt;Docker, Microservice, JWT&lt;/b&gt; 등 키워드를 많이 아는 지원자보다, &lt;b&gt;코드 한 줄을 보고도 왜 이렇게 짰는지 같이 고민해볼 수 있는&lt;/b&gt; 지원자가 더 매력적으로 느껴졌어요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;lt;팀워크의 관점&amp;gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;개발팀에서 중요한 건:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;코드 리뷰 때 &lt;b&gt;건설적인 피드백&lt;/b&gt;을 주고받을 수 있는지&lt;/li&gt;
&lt;li&gt;문제 상황에서 &lt;b&gt;함께 해결책을 찾아갈 수 있는지&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;기술적 의사결정을 할 때 &lt;b&gt;자신의 의견을 논리적으로 설명&lt;/b&gt;할 수 있는지&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 부분들이 단순한 기술 지식보다 더 중요하다는 걸 실감했어요.&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;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  면접관으로서 배운 것들&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;lt;좋은 질문하기&amp;gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;단순히 &quot;이 기술 써봤어요?&quot;가 아니라:&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;&quot;로그를 어디에 찍으면 좋을까요? 왜요?&quot;&lt;/li&gt;
&lt;li&gt;&quot;이 방법 말고 다른 접근법은 없을까요?&quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런 식으로 &lt;b&gt;사고 과정을 볼 수 있는 질문&lt;/b&gt;이 더 의미 있더라구요.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;lt;지원자 평가 기준&amp;gt;&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;기술 지식&lt;/b&gt;: 기본기가 탄탄한가?&lt;/li&gt;
&lt;li&gt;&lt;b&gt;문제 해결&lt;/b&gt;: 논리적으로 접근하는가?&lt;/li&gt;
&lt;li&gt;&lt;b&gt;소통 능력&lt;/b&gt;: 자신의 생각을 명확히 전달할 수 있는가?&lt;/li&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;/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;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  다음번 면접을 위한 개선점&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;lt;면접 프로세스 개선&amp;gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&lt;b&gt;사전 과제&lt;/b&gt;: 간단한 코딩 테스트로 기본기 확인&lt;/li&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;h3 data-ke-size=&quot;size23&quot;&gt;&amp;lt;질문 다양화&amp;gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기술적인 질문뿐만 아니라:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;&quot;프로젝트에서 가장 어려웠던 점은?&quot;&lt;/li&gt;
&lt;li&gt;&quot;동료와 의견이 다를 때 어떻게 해결하나요?&quot;&lt;/li&gt;
&lt;li&gt;&quot;새로운 기술을 배울 때 어떤 방식으로 접근하나요?&quot;&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;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;첫 면접관 경험이었는데, &lt;b&gt;&quot;사람을 뽑는다는 것&quot;&lt;/b&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;b&gt;소통 능력&lt;/b&gt;이 중요하다는 걸 다시 한번 확인했어요. 아무리 뛰어난 코드를 짜도, 그걸 팀원들과 공유하고 함께 발전시켜나가지 못하면 의미가 없으니까요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음번에 면접관 기회가 생기면, 이번 경험을 바탕으로 더 나은 면접을 진행할 수 있을 것 같아요!&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;다음에 시도해보고 싶은 것들:&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;화이트보드 코딩으로 사고 과정 관찰하기( 화면공유로 가능할지도?)&lt;/li&gt;
&lt;li&gt;실제 업무 상황을 시뮬레이션하는 문제 만들어보기 (어느정도는 가능할거같아요)&lt;/li&gt;
&lt;li&gt;지원자의 질문을 통해 회사에 대한 관심도 파악하기 (정보가 없긴합니다.. S1000D표준스펙도 항공우주 분야에서나 쓰이는거니..)&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;&lt;b&gt;생각보다.. 내 이력서는 괜찮은가 .. 돌아보는 계기도 되더라고요.. 내가 뭐라고 이들을 평가할까..라는 생각도 들지만!&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;면접관으로 참관했으니!&amp;nbsp; 그자리에서는 회사의 얼굴을 대표하는 역할이라. 막상 진지하게 임했습니다!&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;</description>
      <category>개발일기</category>
      <author>동재씨</author>
      <guid isPermaLink="true">https://dongjae.tistory.com/6</guid>
      <comments>https://dongjae.tistory.com/6#entry6comment</comments>
      <pubDate>Mon, 22 Sep 2025 23:16:07 +0900</pubDate>
    </item>
    <item>
      <title>커피 한 잔에서 시작된 우주 과학 이야기</title>
      <link>https://dongjae.tistory.com/5</link>
      <description>&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;평소보다 긴 빨대가 들어있었는데, 30센티미터쯤 되어 보였다. 기존에 쓰던 25센티미터 빨대보다 5센티미터나 길었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;빨대로 커피를 빨아올리는데 뭔가 평소보다 힘이 더 드는 것 같았다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;b&gt;&quot;빨대가 길어지면 빨아올리는 힘이 얼마나 달라지는 걸까?&quot;&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;궁금해서 AI에게 물어봤다.&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;/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;AI는 흥미로운 답변을 해주었다.&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;평상시 내 입 안은 대기압인 1기압과 같다. 하지만 빨대로 음료를 마실 때는 입 안 압력을 0.9기압 정도로 낮춘다. 이 0.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;25센티미터에서 30센티미터로 5센티미터(20%) 늘어나면, 빨대 내벽과 액체 사이의 마찰 저항도 약 20% 증가한다. 게다가 5센티미터 더 높이 들어올려야 하니 추가적인 압력이 필요하다. 하지만 내가 쓰는 빨대는 직경이 7밀리미터로 꽤 굵은 편이라서, 실제로는 10-15% 정도 더 세게 빨면 되는 수준이었다.&lt;/p&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;u&gt;&quot;그럼 내 입속의 압력은 음압이라고 봐도 되나? 마이너스 압력?&quot;&lt;/u&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;압력의 진실&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI가 정정해주었다. 절대적인 음압은 아니라고 했다. 빨대로 빨 때 입 안이 대기압보다 낮아지긴 하지만, 여전히 양의 절대압력을 가지고 있다는 것이다. '음압'이라는 표현을 쓰기도 하지만, 이는 &lt;u&gt;&lt;b&gt;상대적 음압&lt;/b&gt;&lt;/u&gt;을 의미한다. 절대 압력이 0보다 낮다는 게 아니라, 기준점인 대기압보다 낮다는 뜻이었다.&lt;/p&gt;
&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;&quot;아, 그럼 진공에 가까워지는 것과 음압은 별개의 얘기구나?&quot;&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;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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;환경이 바뀌면 어떻게 될까?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이때 나는 흥미로운 질문을 떠올렸다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;b&gt; &quot;0.9기압이 중요한 게 아니구나? &lt;/b&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;b&gt;현재 그 공간의 총기압이 어느 정도냐에 따라, 0.9기압이라도 힘들게 느껴지는 거 맞지?&quot;&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;AI는 내가 핵심을 짚었다고 했다. 정말 중요한 건 절대값이 아니라 압력차라는 것이었다.&lt;/p&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기압이고 입 안을 0.9기압으로 만들면 0.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;하지만 고도 3000미터에서는 대기압이 0.7기압 정도다. 이때 입 안을 0.6기압으로 만들면 여전히 0.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;그런데 만약 고도 3000미터에서 입 안을 0.9기압으로 유지한다면? 이건 대기압 0.7기압보다 높은 거니까 역방향 압력차가 생긴다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;음료가 입으로 들어오는 게 아니라 밀려나가게 된다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;u&gt;&quot;잠깐, 그런데 대기압이 0.7기압인데 입 안이 0.9기압일 수가 있어?&quot;&lt;/u&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;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;AI가 웃으며 정정해주었다. &lt;u&gt;&lt;b&gt;물리적으로 불가능하다는 것이다.&lt;/b&gt; &lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;입 안에서 빨아들이는 행위는 압력을 낮추는 것이지, 높이는 게 아니기 때문이다.&lt;/p&gt;
&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;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;극한 환경으로의 여행&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;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;b&gt;&quot;그럼 기압이 낮아져서 0.2기압인 곳에 가면 우리 몸은 터지나?&quot;&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;p data-ke-size=&quot;size16&quot;&gt;AI는 터지지는 않지만 매우 위험한 상황이라고 했다. 0.2기압 환경은 약 16킬로미터 고도에 해당한다. 이 높이에서는 즉시 혈액 속 산소 부족으로 15초 내에 의식을 잃는다. 체액이 끓기 시작하기도 한다. 하지만 우리 몸은 유연한 조직으로 되어 있어서 영화처럼 폭발하지는 않는다.&lt;/p&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;1965년 NASA 직원이 진공 챔버에서 사고로 노출된 적이 있는데, 의식은 잃었지만 몸이 터지지는 않았고 구조 후 완전히 회복했다고 한다.&lt;/p&gt;
&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;u&gt;&quot;어, 그런데 갑자기 정상기압으로 돌리면 뭔가 피가 끓는 거 아니야?&quot;&lt;/u&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;h2 data-ke-size=&quot;size26&quot;&gt;특수한 실험실들&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;b&gt;&quot;저압실도 있어?&quot;&lt;/b&gt;&lt;/u&gt;라고 물었더니, 당연히 있다고 했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고압실만큼 흔하지는 않지만 특수 목적으로 많이 사용된다고 했다. 조종사나 승무원 고고도 적응 훈련, 의료 연구, 스포츠 과학 연구 등에 쓰인다.&lt;/p&gt;
&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;u&gt;&quot;저압실은 대체 왜 필요한 거야?&quot;&lt;/u&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;AI는 '안전하게 위험을 미리 경험'하기 위해서라고 설명했다. 조종사가 고도 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;h2 data-ke-size=&quot;size26&quot;&gt;우주복의 진화&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;u&gt;&quot;그럼 이론상 저압 상태에서도 산소마스크가 있다면, 잠수할 때처럼 상관없이 살 수 있어?&quot;&lt;/u&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이론적으로는 가능하지만 실제로는 여러 문제가 있다고 했다. 산소만 해결된다면 0.2기압 환경에서도 100% 순산소를 공급하면 생존 가능하다. 실제로 우주복이 이런 원리로 작동한다. 저압에 순산소를 공급하는 방식이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 체액 비등, 감압병, 온도 조절 문제 등이 추가로 발생한다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그래서 산소만으로는 부족하고 압력복과 산소, 온도조절이 모두 필요하다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;u&gt;&quot;36.5도에서 피가 끓는다고? 그럼 어떻게 그걸 방지해?&quot;&lt;/u&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;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;압력복의 놀라운 메커니즘&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;u&gt;&quot;압력복의 메커니즘은 뭐야?&quot;&lt;/u&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;AI는 압력복이 '인공적인 대기압을 만드는 옷'이라고 설명했다. 옷 안에 공기를 넣어서 부풀리는 팽창 방식이 일반적이다. 내가 상상한 게 정확했다.&lt;/p&gt;
&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;&quot;아니 옷 안에 그러니까, 내가 옷 안에 풍선처럼 만들어서 거기 안에 들어간다는 거지? 빵빵해지는 느낌으로?&quot;&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;p data-ke-size=&quot;size16&quot;&gt;바로 그거라고 했다! 사람이 풍선 안에 들어간 것 같은 상태다. 팔다리가 빵빵하게 부풀어 오르고, 미슐랭 타이어 캐릭터 같은 느낌이 된다. 옷 안쪽에 공기주머니가 있고, 그 안에 0.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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;관절이 뻣뻣해져서 손가락 하나 구부리기도 힘들고, 걷기나 작업하기가 거의 불가능하다.&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;/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;&lt;u&gt;&lt;b&gt;&quot;그럼 현재 2025년 기준으로는 어떤 선진화된 방식이 있어? SpaceX 우주복은 예쁘고 슬림하던데?&quot;&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;AI가 검색해서 알려준 내용이 흥미로웠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;SpaceX의 현재 우주복은 여전히 가스 압력 방식이지만 훨씬 더 선진화되었다. 할리우드 의상 디자이너 Jose Fernandez가 디자인에 참여해서 세련된 모습을 가지게 되었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기술적 혁신으로는 허벅지 한 곳에서 생명유지장치, 공기, 전력을 모두 공급하는 단일 연결점 시스템, 3D 프린팅된 맞춤형 헬멧과 HUD 시스템, 터치스크린 호환 장갑 등이 있다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 진짜 혁신은 MIT에서 연구하는 기계적 역압력 우주복(MCP Suit)에서 일어나고 있다. BioSuit이라고 불리는 이 기술은 가스 압력 대신 탄성 소재로 피부를 직접 압박하는 '제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;u&gt;&lt;b&gt;&quot;어, 풍선 방식이 아닌데 어떻게 압력을 유지하는지 좀 더 설명해줘&quot;&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;AI가 정정해주었다. SpaceX 우주복은 여전히 풍선 방식이라고 했다. 다만 더 효율적이고 슬림하게 만든 것뿐이다. 더 얇은 소재 사용, 더 타이트한 핏, 시스템 통합, 디자인 최적화로 슬림해 보이는 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;진짜 압력 유지 방식의 변화는 MIT의 BioSuit에서 일어나고 있다. 기존 방식은 공기 주입으로 풍선처럼 부풀어 올려 압력을 유지하지만, 차세대 기술은 탄성 소재로 피부를 압박해서 직접적인 물리적 압력을 가하는 방식이다. 공기가 불필요한 것이다.&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;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;우주정거장의 위기&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;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;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;b&gt;&quot;우주선이나 우주정거장에 양압시스템이 고장 나서 급격하게 우주선 내부가 0.1기압으로 변했다고 쳐봐.&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;b&gt;다행히 우연히 우주비행사들은 살아남았어. &lt;/b&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;b&gt;우주복을 입은 상태고.&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;b&gt;이 상태에서 양압시스템이 다시 복구됐어.&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;b&gt;그래서 기압을 돌려야 하는데, 그게 이론상 가능해?&lt;/b&gt;&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;&lt;b&gt;이미 기체는 빠져나갔잖아.&quot;&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;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;우주정거장에는 이런 상황을 대비한 비상 대비책들이 있다. 여분의 기체 저장고, CO2 스크러버, 재순환 시스템, 구획별 격리 시스템 등이다.&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;/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;&lt;u&gt;&lt;b&gt;&quot;실제 사례 세부설명과 나도 이해할 수 있도록 해결책들을 좀 쉽게 설명해줘&quot;&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;p data-ke-size=&quot;size16&quot;&gt;AI가 2018년 소유즈 구멍 사건을 자세히 설명해주었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;2018년 8월 29일 밤, 지상 관제소에서 국제우주정거장의 기압이 조금씩 떨어지는 것을 발견했다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음 날 조사 결과, 소유즈 MS-09 우주선의 궤도 모듈에 연필심 굵기인 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;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;&lt;u&gt;&quot;아니 구멍 찾는 게 말이 쉽지 어떻게 찾은 거야? &lt;/u&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;u&gt;아마 우주선 내부에서 촛불?&amp;nbsp; 아니면 담배를 피워 연기의 흐름을 추적하며 찾나?&quot;&lt;/u&gt;&lt;/b&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;웃기게도 우주에서 구멍 찾는 방법은 의외로 원시적이었다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;1단계는 소리로 찾기다. 공기가 빠져나가는 &quot;쉬잇-&quot; 소리를 찾는 것이다. 조용한 우주정거장에서는 이런 소리가 잘 들린다.&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;2단계는 촉감으로 찾기다. 손을 대보면 바람이 느껴진다. 마치 자전거 타이어에서 공기 새는 곳 찾는 것과 같다.&lt;/u&gt;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;u&gt;3단계는 종이나 천으로 확인하는 것이다. 실제로 우주비행사들이 러시아 구역을 중심으로 수색해서 빠르게 소유즈 MS-09에서 누출을 발견했다.&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;&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;수리 과정은 놀라울 정도로 간단했다. 30분 만에 우주비행사 세르게이 프로코피예프가&lt;b&gt; 캡톤 테이프로 임시 봉쇄한 후, 에폭시 접착제와 거즈로 완전 수리했다.&lt;/b&gt; 24시간 모니터링 결과 기압이 완전히 안정화되어 더 이상 문제가 없었다.&lt;/p&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;누출이 매우 작아서, 최대 누출 속도로도 산소 탱크가 18일은 버틸 수 있는 수준이었다고 한다.&lt;/p&gt;
&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;우주에서도 '테이프 + 접착제'가 완벽하게 작동한 것이다.&lt;/b&gt;&lt;/u&gt;&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;&amp;nbsp;&lt;/h2&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;/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;환경 대기압 빨대 사용 가능 여부&lt;/p&gt;
&lt;table style=&quot;border-collapse: collapse; width: 100%;&quot; border=&quot;1&quot; data-ke-align=&quot;alignLeft&quot;&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;평지&lt;/td&gt;
&lt;td&gt;1.0기압&lt;/td&gt;
&lt;td&gt;쉬움&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;고산지대 (3000m)&lt;/td&gt;
&lt;td&gt;0.7기압&lt;/td&gt;
&lt;td&gt;가능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;극고도 (16km)&lt;/td&gt;
&lt;td&gt;0.2기압&lt;/td&gt;
&lt;td&gt;불가능(그리고 사망)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 모든 이야기가 커피 한 잔에서 시작되었다니 신기하다. 빨대로 음료를 빨아올리는 간단한 행위 속에 압력의 원리가 숨어있고, 그 원리가 고도가 높은 곳에서의 생존, 우주복 기술, 우주정거장의 비상사태 해결까지 연결되어 있다는 것을 알게 되었다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&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;/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;그리고 우주비행사들이 2밀리미터 구멍을 테이프와 접착제로 수리했다는 사실에서, 때로는 가장 단순한 해결책이 가장 효과적일 수 있다는 것도 배웠다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;다음번에 빨대로 음료를 마실 때면, 나는 우주비행사가 된 기분을 느낄 것 같다. 그리고 그 작은 행위 속에 숨겨진 과학의 경이로움을 다시 한번 생각해볼 것이다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p 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;</description>
      <author>동재씨</author>
      <guid isPermaLink="true">https://dongjae.tistory.com/5</guid>
      <comments>https://dongjae.tistory.com/5#entry5comment</comments>
      <pubDate>Thu, 31 Jul 2025 14:54:40 +0900</pubDate>
    </item>
    <item>
      <title>정규식이 유한상태기계라고?, 근데.. 그게 뭐야? (2)</title>
      <link>https://dongjae.tistory.com/4</link>
      <description>&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;그리고 ,전 글의 예시에서 보여준 [IF문]을 연속으로 쓴거랑 뭐가 다를까요?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실제 Java 정규식 엔진의 내부를 파헤쳐보겠습니다.&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;Java 정규식 엔진의 진짜 정체&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;노드 기반 그래프 구조&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Java의 정규식 엔진은 실제로 &lt;b&gt;노드들을 연결한 그래프&lt;/b&gt;로 구현되어 있어요.&lt;/p&gt;
&lt;pre class=&quot;java&quot;&gt;&lt;code&gt;// OpenJDK 내부 구조 (실제)
abstract class Node {
    Node next;  // 다음 노드로의 포인터
    abstract boolean match(Matcher matcher, int i, CharSequence seq);
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이게 바로 &lt;b&gt;상태기계의 그래프 표현&lt;/b&gt;입니다:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;각 Node = 상태&lt;/li&gt;
&lt;li&gt;next 포인터 = 상태 전이&lt;/li&gt;
&lt;li&gt;match() 메서드 = 전이 조건&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;패턴에서 노드 그래프로 변환&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정규식 &quot;a(b|c)*d&quot;가 어떻게 변환되는지 보면&lt;/p&gt;
&lt;pre class=&quot;isbl&quot; style=&quot;background-color: #f8f8f8; color: #383a42;&quot;&gt;&lt;code&gt;입력: &quot;a(b|c)*d&quot;
     &amp;darr;
[파서] 토큰 분해
     &amp;darr;
StartNode &amp;rarr; SliceNode(&quot;a&quot;) &amp;rarr; LoopNode &amp;rarr; SliceNode(&quot;d&quot;) &amp;rarr; AcceptNode
                                &amp;darr;
                           GroupNode
                           ├─ SliceNode(&quot;b&quot;)
                           └─ SliceNode(&quot;c&quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이런식으로 변환됩니다.&lt;/p&gt;
&lt;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;/h3&gt;
&lt;pre class=&quot;scala&quot;&gt;&lt;code&gt;// 개념적인 구조
class SliceNode extends Node {  // &quot;abc&quot; 같은 리터럴 문자열
    char[] buffer;
    
    boolean match(Matcher matcher, int i, CharSequence seq) {
        // 문자열을 직접 비교
        for (int j = 0; j &amp;lt; buffer.length; j++) {
            if (seq.charAt(i + j) != buffer[j]) return false;
        }
        return next.match(matcher, i + buffer.length, seq);
    }
}

class GroupNode extends Node {  // (a|b) 같은 그룹
    Node[] alternatives;
    
    boolean match(Matcher matcher, int i, CharSequence seq) {
        // 각 대안을 시도
        for (Node alt : alternatives) {
            if (alt.match(matcher, i, seq)) return true;
        }
        return false;
    }
}

class LoopNode extends Node {  // a* 같은 반복
    Node body;
    int min, max;
    
    boolean match(Matcher matcher, int i, CharSequence seq) {
        // 백트래킹으로 최적의 매칭 찾기
        for (int count = min; count &amp;lt;= max; count++) {
            if (tryMatch(count, matcher, i, seq)) return true;
        }
        return false;
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;순수 정규식 부분 (상태기계)&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;기본 패턴 매칭은 정말 단순한 상태기계로 동작해요:&lt;/p&gt;
&lt;pre class=&quot;pgsql&quot;&gt;&lt;code&gt;// 기본 매칭 로직
Node current = startNode;
int position = 0;

while (current != null &amp;amp;&amp;amp; position &amp;lt; input.length()) {
    if (current.matches(input.charAt(position))) {
        current = current.next;  // 다음 상태로 전이
        position++;
    } else {
        return false;  // 매칭 실패
    }
}

return current == acceptNode;  // 최종 상태 도달했나?
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 부분은 정말 우리가 배운 유한상태기계와 동일해요!&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;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;/p&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;JIT 컴파일러 시점&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JIT 컴파일러가 노드 그래프를 어셈블리로 번역해줘요:&lt;/p&gt;
&lt;pre class=&quot;nsis&quot;&gt;&lt;code&gt;// Java 노드 실행 코드
if (current.matches(currentChar)) {
    current = current.next;
    position++;
}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;avrasm&quot;&gt;&lt;code&gt;# JIT이 생성하는 어셈블리
LOAD R1, [current_ptr]      # current 노드 로드
LOAD R2, [input_ptr]        # 현재 문자 로드
CALL [R1 + matches_offset]  # matches() 메서드 호출
TEST RAX, RAX               # 결과 체크
JZ   BACKTRACK              # 0이면 백트래킹으로 점프

# 매칭 성공시
LOAD R3, [R1 + next_offset] # current.next 로드  
MOV  current_ptr, R3        # current 업데이트
INC  input_ptr              # position++
JMP  MAIN_LOOP              # 다음 매칭으로
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&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;&lt;b&gt;&lt;u&gt;근데 요즘 Graal 많이 쓰시잖아요?.. JIT과는 어떠한 차이가 있는지 좀더 조사해봤어요.&lt;/u&gt;&lt;/b&gt;&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;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;GraalVM의 혁신적 접근&lt;/h2&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;JIT vs GraalVM&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;JIT(보수적)&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;Java 바이트코드 &amp;rarr; [C2 컴파일러] &amp;rarr; 네이티브 코드
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;GraalVM (혁신적?.. 방식)&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;css&quot;&gt;&lt;code&gt;Java 바이트코드 &amp;rarr; [Graal 컴파일러] &amp;rarr; 그래프 기반 IR &amp;rarr; 고도로 최적화된 기계어
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;그래프 기반 최적화의 위력&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;GraalVM은 &lt;b&gt;Sea of Nodes&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;pre class=&quot;asciidoc&quot;&gt;&lt;code&gt;정규식 패턴 &quot;ab*c&quot; 처리
    &amp;darr;
[Graal] 데이터 플로우 그래프 생성
    &amp;darr;
LoadChar₁ &amp;rarr; CompareA &amp;rarr; Branch &amp;rarr; LoadChar₂ &amp;rarr; CompareB &amp;rarr; Loop &amp;rarr; LoadChar₃ &amp;rarr; CompareC
    &amp;darr;
그래프 최적화
- 불필요한 노드 제거
- 공통 부분식 제거  
- 루프 언롤링
- 분기 예측 최적화
    &amp;darr;
초고도로 최적화된 기계어
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;실제 최적화 차이&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;JIT&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;subunit&quot;&gt;&lt;code&gt;# 보통 이런 식으로 번역
CALL matches_method
TEST RAX, RAX  
JZ   fail_label
CALL next_method
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;Graal&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;x86asm&quot;&gt;&lt;code&gt;# 훨씬 더 공격적 최적화
# 메서드 인라이닝 + 루프 언롤링 + 분기 예측 최적화

# 원래 여러 메서드 호출이었던 것이 하나의 최적화된 블록으로
CMP BYTE PTR [R5], 'a'      # 첫 번째 문자 비교
JNE fail_fast
INC R5                      # position++

# 'b*' 루프를 언롤링
loop_b:
    CMP BYTE PTR [R5], 'b'
    JNE check_c
    INC R5
    # 4번까지 언롤링해서 루프 오버헤드 제거
    CMP BYTE PTR [R5], 'b'
    JNE check_c
    INC R5
    # ... (반복)
    JMP loop_b

check_c:
    CMP BYTE PTR [R5], 'c'
    JNE fail_fast
    # 성공!
&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;h3 data-ke-size=&quot;size23&quot;&gt;벤치마크 결과&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;실제 성능 차이 (정규식 처리)&lt;/b&gt;&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;간단한 패턴: GraalVM이 15-25% 빠름&lt;/li&gt;
&lt;li&gt;복잡한 백트래킹: GraalVM이 30-50% 빠름&lt;/li&gt;
&lt;li&gt;Native Image: 시작 시간 10-100배 빠름&lt;/li&gt;
&lt;li&gt;메모리 사용량: Native Image가 2-5배 적음&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;결론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;Java 정규식 엔진의 실제 구현:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;노드 그래프&lt;/b&gt;: 상태기계를 객체 지향적으로 표현&lt;/li&gt;
&lt;li&gt;&lt;b&gt;백트래킹&lt;/b&gt;: 강력한 기능을 위한 복잡성 추가&lt;/li&gt;
&lt;li&gt;&lt;b&gt;JIT 최적화&lt;/b&gt;: 런타임에 효율적인 기계어로 변환&lt;/li&gt;
&lt;li&gt;&lt;b&gt;GraalVM&lt;/b&gt;: 그래프 기반 분석으로 한 단계 더 진화&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;순수 정규식 부분은 정말 단순한 상태기계 그래프가 맞아요. 백트래킹과 고급 기능들이 복잡함을 만든 주범이고, GraalVM 같은 차세대 컴파일러는 이 모든 걸 더 똑똑하게 최적화하고 있는 거죠!&lt;/p&gt;
&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>
      <author>동재씨</author>
      <guid isPermaLink="true">https://dongjae.tistory.com/4</guid>
      <comments>https://dongjae.tistory.com/4#entry4comment</comments>
      <pubDate>Tue, 29 Jul 2025 22:29:09 +0900</pubDate>
    </item>
    <item>
      <title>정규식이 유한상태기계라고?, 근데.. 그게 뭐야? (1)</title>
      <link>https://dongjae.tistory.com/3</link>
      <description>&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;그런데 어느 날 &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;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;유한상태기계가 뭔데?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;일단 이름부터가 어려워 보이죠. 근데 개념은 생각보다 간단해요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;TV 리모컨 생각해보세요.&lt;/p&gt;
&lt;pre class=&quot;brainfuck&quot;&gt;&lt;code&gt;TV 꺼짐 --전원버튼--&amp;gt; TV 켜짐
TV 켜짐 --전원버튼--&amp;gt; TV 꺼짐
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이게 유한상태기계예요. TV는 항상 &quot;꺼짐&quot; 아니면 &quot;켜짐&quot; 둘 중 하나 상태에 있고, 전원버튼 누르면 상태가 바뀌는 거죠.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;신호등도 마찬가지:&lt;/p&gt;
&lt;pre class=&quot;gcode&quot;&gt;&lt;code&gt;빨간불 &amp;rarr; 초록불 &amp;rarr; 노란불 &amp;rarr; 빨간불 (반복)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;핵심은 이거예요:&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;지금 어떤 상태인지 기억하고 있음&lt;/li&gt;
&lt;li&gt;뭔가 입력이 들어오면 (시간 지남, 버튼 누름 등)&lt;/li&gt;
&lt;li&gt;정해진 규칙대로 다른 상태로 바뀜&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;그게 정규식이랑 무슨 상관?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음엔 저도 이해 안 됐어요. 근데 생각해보니까...&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정규식 abc를 예로 들어볼게요. 이게 &quot;abc라는 문자가 순서대로 나오는지 확인하는 기계&quot;라고 생각해보면:&lt;/p&gt;
&lt;pre class=&quot;clean&quot;&gt;&lt;code&gt;시작 --'a'보면--&amp;gt; &quot;a 찾음&quot; --'b'보면--&amp;gt; &quot;ab 찾음&quot; --'c'보면--&amp;gt; &quot;성공!&quot;
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&quot;xabcy&quot;라는 문자열이 들어온다면:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;'x' 봄 &amp;rarr; 아직 시작 상태&lt;/li&gt;
&lt;li&gt;'a' 봄 &amp;rarr; &quot;a 찾음&quot; 상태로 바뀜&lt;/li&gt;
&lt;li&gt;'b' 봄 &amp;rarr; &quot;ab 찾음&quot; 상태로 바뀜&lt;/li&gt;
&lt;li&gt;'c' 봄 &amp;rarr; &quot;성공!&quot; 상태&lt;/li&gt;
&lt;li&gt;'y' 봄 &amp;rarr; 이미 성공했으니 상관없음&lt;/li&gt;
&lt;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이게 바로 유한상태기계죠!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;CPU는 이걸 어떻게 처리할까?&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;고수준 언어에서는 간단해 보이지만, CPU 레벨에서 보면 정말 흥미로워요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;입력 &quot;xabcy&quot;를 처리하는 과정:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;avrasm&quot;&gt;&lt;code&gt;# 1단계: 'x' 처리
LOAD R1, 'x'        # 메모리에서 'x' 로드
LOAD R2, 'a'        # 현재 기대하는 문자는 'a'
CMP R1, R2          # 'x'와 'a' 비교
JNE STAY_START      # 다르므로 START 상태 유지
MOV R3, 0           # state = START (0)

# 2단계: 'a' 처리  
LOAD R1, 'a'        # 다음 문자 'a' 로드
CMP R1, R2          # 'a'와 'a' 비교
JEQ FOUND_A         # 같으므로 FOUND_A로 점프
MOV R3, 1           # state = FOUND_A (1)
MOV R2, 'b'         # 이제 'b'를 기대

# 3단계: 'b' 처리
LOAD R1, 'b'        # 다음 문자 'b' 로드  
CMP R1, R2          # 'b'와 'b' 비교
JEQ FOUND_AB        # 같으므로 FOUND_AB로 점프
MOV R3, 2           # state = FOUND_AB (2)
MOV R2, 'c'         # 이제 'c'를 기대

# 4단계: 'c' 처리
LOAD R1, 'c'        # 다음 문자 'c' 로드
CMP R1, R2          # 'c'와 'c' 비교  
JEQ SUCCESS         # 같으므로 SUCCESS로 점프
MOV R3, 3           # state = SUCCESS (3)
MOV R4, 1           # result = true
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;쉬프트 연산의 실체&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 &quot;쉬프트&quot;라고 말한 건 사실 &lt;b&gt;문자 스트림을 순차적으로 읽는 과정&lt;/b&gt;이에요:&lt;/p&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;// Java 코드로 보면
String input = &quot;xabcy&quot;;
int position = 0;

while (position &amp;lt; input.length()) {
    char currentChar = input.charAt(position);  // 현재 위치 문자 읽기
    
    // 상태 전이 로직
    switch (currentState) {
        case START:
            if (currentChar == 'a') currentState = FOUND_A;
            break;
        // ...
    }
    
    position++;  // 다음 문자로 이동 (이게 &quot;쉬프트&quot;)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;참/거짓 저장하는 방식&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과를 저장하는 방식도 흥미로워요:&lt;/p&gt;
&lt;pre class=&quot;avrasm&quot;&gt;&lt;code&gt;# 불린 값은 보통 1비트지만, CPU는 보통 8비트 단위로 처리
MOV R4, 0    # false = 0
MOV R4, 1    # true = 1

# 조건 플래그 레지스터 활용
CMP R1, R2   # 비교 후 플래그 설정
JZ SUCCESS   # Zero Flag가 설정되면 (같으면) 성공

# 실제로는 이런 식으로 최적화
TEST R4, R4  # R4가 0인지 체크
JNZ FOUND    # 0이 아니면 (true면) 찾음
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;메모리 접근 패턴의 차이&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;생각해보면 스택과 무엇이 다를까요? .. 본질은 무언가 상태를 저장하고 비교하는건 똑같잖아요..?&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만, 공부해보니.. 생각보다 다르더라구요..&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;스택 방식(이해를 위한 예시.. 쓰이지는 않음):&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;avrasm&quot;&gt;&lt;code&gt;# 매번 다른 스택 위치에 접근
PUSH 'a'     # 스택[0] = 'a'
PUSH 'b'     # 스택[1] = 'b'  
PUSH 'c'     # 스택[2] = 'c'
# 나중에 POP으로 꺼내서 비교
POP R1       # 'c' 꺼냄
POP R2       # 'b' 꺼냄
POP R3       # 'a' 꺼냄
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;b&gt;상태기계 방식:&lt;/b&gt;&lt;/p&gt;
&lt;pre class=&quot;avrasm&quot;&gt;&lt;code&gt;# 항상 같은 레지스터만 사용
MOV R3, 0    # state = START
MOV R3, 1    # state = FOUND_A  
MOV R3, 2    # state = FOUND_AB
MOV R3, 3    # state = SUCCESS
&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&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;&amp;nbsp;&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&lt;b&gt;실제 필요한 최소 저장공간&lt;/b&gt;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하드웨어 레벨에서 정말 필요한 공간을 계산해보면:&lt;/p&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;// &quot;abc&quot; 패턴 매칭에 필요한 최소 비트
byte currentChar;    // 8비트 (현재 문자)
byte expectedChar;   // 8비트 (기대하는 문자)
byte state;         // 2비트 (4가지 상태: START, FOUND_A, FOUND_AB, SUCCESS)
boolean found;      // 1비트 (찾았는지 여부)

// 총 19비트 (약 3바이트)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이론적으로는 더 줄일 수도 있어요&lt;/p&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;// 극한 최적화
byte currentChar;    // 8비트
byte state;         // 2비트 (상태 정보에 기대 문자도 포함)
boolean found;      // 1비트

// 총 11비트
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;스택 방식이 입력 길이 &amp;times; 8비트 (예: &quot;xabcy&quot; = 40비트) 쓰는 거랑 비교하면 엄청난 차이죠.. 근데 느릴듯?..&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;왜 상태기계가 캐시에 유리한가?&lt;/h3&gt;
&lt;pre class=&quot;avrasm&quot;&gt;&lt;code&gt;# 상태기계: 같은 레지스터 반복 사용
MOV R3, 0    # 캐시에 R3 로드
MOV R3, 1    # R3는 이미 캐시에 있음
MOV R3, 2    # R3는 이미 캐시에 있음

# 스택: 매번 다른 메모리 위치 접근  
MOV [SP+0], 'a'    # 스택 위치 0에 저장
MOV [SP+1], 'b'    # 스택 위치 1에 저장 (캐시 미스 가능)
MOV [SP+2], 'c'    # 스택 위치 2에 저장 (캐시 미스 가능)
&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;CPU 입장에서는 이런 미세한 차이들이 모여서 큰 성능 차이를 만들어내는 거예요.&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;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;결론&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;정규식이 유한상태기계라는 건&lt;/p&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;메모리 효율적이고&lt;/li&gt;
&lt;li&gt;빠르고&lt;/li&gt;
&lt;li&gt;캐시 친화적이라는 뜻&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 표현력에는 한계가 있어서, 실제 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;이제 정규식 쓸 때마다 &quot;아, 지금 내부에서 상태기계가 돌고 있구나&quot; 생각하게 되네요.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;그냥 쓰기만 했는데 이런 원리가 있었다니... 컴퓨터과학이 참 재밌어요.&lt;/p&gt;</description>
      <author>동재씨</author>
      <guid isPermaLink="true">https://dongjae.tistory.com/3</guid>
      <comments>https://dongjae.tistory.com/3#entry3comment</comments>
      <pubDate>Tue, 29 Jul 2025 22:07:41 +0900</pubDate>
    </item>
    <item>
      <title>팀 프로젝트에서 List가 Set을 이기는 이유  </title>
      <link>https://dongjae.tistory.com/2</link>
      <description>&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;code&gt;Set&lt;/code&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; 팀원들은 순서(index)가 필요하거나 기존 코드와의 호환성 때문에 &lt;code&gt;List&lt;/code&gt;를 선호합니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결국, &lt;code&gt;Set&lt;/code&gt;을 &lt;code&gt;List&lt;/code&gt;로 변환하는 추가 작업이 빈번해지고, 이 과정이 코드 복잡도를 유발합니다. &lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;왜 이런 일이 발생하고, &lt;code&gt;List&lt;/code&gt;를 표준으로 사용하는 것이 팀 프로젝트에서 더 나은 선택인지 알아봅시다.  &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;문제: Set에서 List로의 변환  &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;한 개발자가 &lt;code&gt;HashSet&lt;/code&gt;을 사용해 중복 제거와 빠른 조회를 구현했습니다. 인터페이스는 이렇게 정의되었죠:&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;interface UserService {
    Set&amp;lt;User&amp;gt; getUsers();
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;문제는 팀원들이 &lt;code&gt;Set&lt;/code&gt; 대신 &lt;code&gt;List&lt;/code&gt;를 필요로 하는 경우가 많다는 점입니다. 예를 들어, 순서가 중요한 UI 렌더링이나 기존 &lt;code&gt;List&lt;/code&gt; 기반 로직과 통합해야 할 때, 이런 변환 코드가 자주 등장합니다:&lt;/p&gt;
&lt;pre class=&quot;routeros&quot;&gt;&lt;code&gt;List&amp;lt;User&amp;gt; users = new ArrayList&amp;lt;&amp;gt;(userService.getUsers());&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 변환은 CPU 자원을 소모하며, 특히 대량 데이터 처리 시 성능 병목의 원인이 될 수 있습니다. 더 큰 문제는 팀 내에서 데이터 구조 사용 방식이 일치하지 않아 코드가 점점 복잡해진다는 점입니다.  &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;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;두 가지 컬렉션 타입의 함정  &lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 문제를 해결하려고 &lt;code&gt;Set&lt;/code&gt;과 &lt;code&gt;List&lt;/code&gt; 두 가지 버전의 메서드를 제공하는 방법을 생각할 수 있습니다:&lt;/p&gt;
&lt;pre class=&quot;capnproto&quot;&gt;&lt;code&gt;interface UserService {
    Set&amp;lt;User&amp;gt; getUsersAsSet();
    List&amp;lt;User&amp;gt; getUsersAsList();
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 이 접근법은 여러 문제를 낳습니다:&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;&lt;b&gt;코드 중복&lt;/b&gt;: 거의 동일한 로직을 두 개의 메서드로 관리해야 합니다.  &lt;/li&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;/ol&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;시간이 지나면서 두 메서드의 동작이 미묘하게 달라질 수 있고, 이는 혼란과 오류로 이어집니다. &amp;ldquo;같은데 타입만 다르다&amp;rdquo;는 착각은 위험합니다!  &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;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;현실적인 해결책: List로 통일 ✅&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;두 가지 타입을 제공하는 대신, &lt;code&gt;List&lt;/code&gt;를 표준으로 사용하는 것이 더 현명합니다. 방법은 다음과 같습니다:&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. List 기반의 단일 인터페이스 정의&lt;/h3&gt;
&lt;pre class=&quot;capnproto&quot;&gt;&lt;code&gt;interface UserService {
    List&amp;lt;User&amp;gt; getUsers();
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;모든 팀원이 반환 타입을 명확히 알 수 있어 혼란이 줄어듭니다.  &lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 내부에서 Set으로 최적화&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;필요하다면 내부 로직에서 &lt;code&gt;HashSet&lt;/code&gt;을 사용해 성능을 최적화하고, 반환 시 &lt;code&gt;List&lt;/code&gt;로 변환합니다:&lt;/p&gt;
&lt;pre class=&quot;dart&quot;&gt;&lt;code&gt;@Override
public List&amp;lt;User&amp;gt; getUsers() {
    Set&amp;lt;User&amp;gt; uniqueUsers = new HashSet&amp;lt;&amp;gt;();
    // Set을 활용한 효율적인 로직
    // ...
    return new ArrayList&amp;lt;&amp;gt;(uniqueUsers);
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 방식은 API의 일관성을 유지하면서 내부 최적화를 가능하게 합니다.  ️&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;3. 이 접근법의 장점&lt;/h3&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;code&gt;List&lt;/code&gt;를 사용하니 어떤 타입을 써야 할지 고민할 필요가 없습니다.  &lt;/li&gt;
&lt;li&gt;&lt;b&gt;간단한 유지보수&lt;/b&gt;: 단일 메서드만 관리하면 되므로 버그가 줄어듭니다.  &lt;/li&gt;
&lt;li&gt;&lt;b&gt;팀 협업&lt;/b&gt;: 팀의 기존 코드 패턴과 조화를 이룹니다.  &lt;/li&gt;
&lt;li&gt;&lt;b&gt;오류 방지&lt;/b&gt;: 메서드 간 불일치로 인한 실수를 막습니다.  ️&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;개발자를 위한 조언  &lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;성능도 중요하지만, 일관성과 협업이 더 큰 가치를 만듭니다.&amp;rdquo;&lt;br /&gt;&amp;ldquo;완벽한 최적화보다 팀이 함께 유지할 수 있는 코드가 낫습니다.&amp;rdquo;&lt;br /&gt;&amp;ldquo;미래의 팀원을 생각하며 코드를 작성하세요.&amp;rdquo;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;실제 프로젝트에서는 &lt;code&gt;List&lt;/code&gt;와 &lt;code&gt;Set&lt;/code&gt;의 성능 차이가 미미한 경우가 많습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;List&lt;/code&gt;를 표준으로 사용하면 협업과 유지보수가 훨씬 수월해집니다.  &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;&amp;nbsp;&lt;/h2&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;&amp;nbsp;&lt;/h2&gt;
&lt;h2 style=&quot;text-align: center;&quot; data-ke-size=&quot;size26&quot;&gt;결론: 표준의 힘을 받아들이자  &lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;프로그래밍은 기술적 선택만큼 팀과의 조화도 중요합니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&lt;code&gt;List&lt;/code&gt;를 API의 표준으로 선택하면 명확성, 유지보수성, 협업 효율성을 높일 수 있습니다.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;성능 최적화를 위해 무조건 적인&amp;nbsp;&lt;code&gt;Set&lt;/code&gt;을 고집하기보다는, 팀 전체의 생산성을 우선시하세요.&lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;당신의 코드는 팀의 미래를 위한 자산이니까요!  &lt;/p&gt;
&lt;p style=&quot;text-align: center;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;ldquo;그냥 List 쓰자!..&amp;rdquo; &amp;mdash;&amp;nbsp; 다니던 팀의 시니어 개발자 &lt;/p&gt;
&lt;/blockquote&gt;</description>
      <category>Java</category>
      <category>list</category>
      <category>Set</category>
      <author>동재씨</author>
      <guid isPermaLink="true">https://dongjae.tistory.com/2</guid>
      <comments>https://dongjae.tistory.com/2#entry2comment</comments>
      <pubDate>Fri, 16 May 2025 22:49:22 +0900</pubDate>
    </item>
  </channel>
</rss>