<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>'어'설픈게 '매'력이징❤️ : 어매이징 썸머</title>
    <link>https://jsummer07.tistory.com/</link>
    <description>어설픔을 매력 삼아, 우아하게 비상할 날을 준비하는 어매이징 썸머의 빌드 일지</description>
    <language>ko</language>
    <pubDate>Fri, 23 Oct 2026 23:40:23 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>jsummer07</managingEditor>
    <image>
      <title>'어'설픈게 '매'력이징❤️ : 어매이징 썸머</title>
      <url>https://tistory1.daumcdn.net/tistory/9054842/attach/a9958aa1f0fd45c39598213b15d13481</url>
      <link>https://jsummer07.tistory.com</link>
    </image>
    <item>
      <title>[Python] 파이썬 기초 12: 만능 일꾼 `for` 반복문과 `range()`, 그리고 리스트의 만남  ✨</title>
      <link>https://jsummer07.tistory.com/38</link>
      <description>&lt;p&gt;안녕하세요! 스마트인재개발원 파이썬 공부 기록입니다.&lt;br&gt;지난 시간에 조건에 따라 멈추는 &lt;code&gt;while&lt;/code&gt; 문을 배웠다면, 이번 시간에는 정해진 횟수나 데이터의 개수만큼 편하게 순회할 수 있는 &lt;strong&gt;파이썬의 마법 같은 일꾼 &lt;code&gt;for&lt;/code&gt; 문&lt;/strong&gt;을 정복해 보겠습니다!  &lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;1. &lt;code&gt;for&lt;/code&gt; 반복문과 &lt;code&gt;range()&lt;/code&gt; 함수의 만남&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;for&lt;/code&gt; 문은 리스트나 문자열 같은 순서가 있는 데이터의 처음부터 끝까지 자동으로 짚어가며(순회하며) 반복 작업을 수행할 때 아주 강력합니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;range(시작, 끝, 증가치)&lt;/code&gt; 함수:&lt;/strong&gt; 숫자의 범위를 편하게 만들어주는 함수입니다.&lt;ul&gt;
&lt;li&gt;&lt;code&gt;range(10)&lt;/code&gt;: 0부터 9까지 (0부터 시작해서 10개 미만)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;range(1, 11)&lt;/code&gt;: 1부터 10까지 (1 이상 11 미만)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;range(1, 10, 2)&lt;/code&gt;: 1부터 9까지 2씩 증가하며 (&lt;code&gt;1, 3, 5, 7, 9&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;  &lt;code&gt;for&lt;/code&gt; 문 기본 실습 코드&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 1부터 5까지 출력하기
for i in range(1, 6):
    print(i)
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2&gt;2. 리스트(List)와 &lt;code&gt;for&lt;/code&gt; 문의 환상적인 조합&lt;/h2&gt;
&lt;p&gt;리스트 안에 들어 있는 데이터를 하나씩 꺼내서 무언가를 처리해야 할 때 &lt;code&gt;for&lt;/code&gt; 문은 필수입니다.&lt;/p&gt;
&lt;h3&gt;  리스트 순회 실습 코드&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# 리스트의 요소들을 하나씩 출력하기
fruits = [&amp;#39;사과&amp;#39;, &amp;#39;바나나&amp;#39;, &amp;#39;포도&amp;#39;, &amp;#39;딸기&amp;#39;]

for f in fruits:
    print(f&amp;quot;내가 좋아하는 과일은 {f}입니다!  &amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2&gt;3. 실전 예제: 누적 합 구하기와 조건문 결합하기&lt;/h2&gt;
&lt;p&gt;반복문 안에서 조건문(&lt;code&gt;if&lt;/code&gt;)을 함께 쓰면 더 정교하고 복잡한 로직을 완성할 수 있습니다. 1부터 10까지의 숫자 중 &lt;strong&gt;짝수만 골라내어 더하는 예제&lt;/strong&gt;를 볼까요?&lt;/p&gt;
&lt;h3&gt;  짝수 합 구하기 실습 코드&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;total = 0

for num in range(1, 11):
    # 짝수인지 확인
    if num % 2 == 0:
        total += num  # total = total + num 과 같은 의미입니다.

print(f&amp;quot;1부터 10까지의 짝수 총합은: {total}입니다!  &amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/vrM4R/dJMcagAzijZ/1B7szGYyqCtAqULKY6SuR1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/vrM4R/dJMcagAzijZ/1B7szGYyqCtAqULKY6SuR1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/vrM4R/dJMcagAzijZ/1B7szGYyqCtAqULKY6SuR1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FvrM4R%2FdJMcagAzijZ%2F1B7szGYyqCtAqULKY6SuR1%2Fimg.png&quot; width=&quot;100%&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;  오늘 공부를 마치며&lt;/h2&gt;
&lt;p&gt;반복문(&lt;code&gt;while&lt;/code&gt;, &lt;code&gt;for&lt;/code&gt;)까지 마스터하면서 파이썬의 가장 중요한 뼈대인 제어문(조건문, 반복문)과 자료구조(리스트, 튜플)를 모두 튼튼하게 다졌습니다!&lt;br&gt;&lt;code&gt;&lt;/code&gt;&lt;br&gt;다음 기록은 키(Key)와 값(Value)의 쌍으로 데이터를 똑똑하게 다루는 &lt;strong&gt;딕셔너리(Dictionary)&lt;/strong&gt; 파트로 찾아올게요. 다음 빌드 일지에서 만나요!  ✨&lt;/p&gt;
&lt;hr&gt;</description>
      <category>Development(개발 공부)/Python &amp;amp; AI</category>
      <category>for문</category>
      <category>python</category>
      <category>range함수</category>
      <category>개발자일지</category>
      <category>리스트반복</category>
      <category>스마트인재개발원</category>
      <category>어썸썸머</category>
      <category>코딩기초</category>
      <category>파이썬</category>
      <category>파이썬반복문</category>
      <author>jsummer07</author>
      <guid isPermaLink="true">https://jsummer07.tistory.com/38</guid>
      <comments>https://jsummer07.tistory.com/38#entry38comment</comments>
      <pubDate>Fri, 23 Oct 2026 19:26:00 +0900</pubDate>
    </item>
    <item>
      <title>[4편] 내 폰에 진짜 앱 설치하기! 배포 꿀팁과 솔직한 개발 회고</title>
      <link>https://jsummer07.tistory.com/54</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;  1. 실전 테스트: 거울 앞에서의 진짜 '눈바디'&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;컴퓨터 가상 화면(에뮬레이터) 안에서만 돌던 앱을 드디어 제 진짜 스마트폰에 설치했습니다. 그리고 매일 아침 눈바디를 찍는 거울 앞에 섰습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;KakaoTalk_20261023_092305188.png&quot; data-origin-width=&quot;1472&quot; data-origin-height=&quot;2848&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/qyNl8/dJMcablW7ml/qAW2x9AEkCNrffVgFsRkw0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/qyNl8/dJMcablW7ml/qAW2x9AEkCNrffVgFsRkw0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/qyNl8/dJMcablW7ml/qAW2x9AEkCNrffVgFsRkw0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FqyNl8%2FdJMcablW7ml%2FqAW2x9AEkCNrffVgFsRkw0%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;967&quot; data-filename=&quot;KakaoTalk_20261023_092305188.png&quot; data-origin-width=&quot;1472&quot; data-origin-height=&quot;2848&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;KakaoTalk_20261023_092305188_01.png&quot; data-origin-width=&quot;1472&quot; data-origin-height=&quot;2852&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/epNr2t/dJMcahGjTH3/53nx73Du35xAvP4Y9SDCE1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/epNr2t/dJMcahGjTH3/53nx73Du35xAvP4Y9SDCE1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/epNr2t/dJMcahGjTH3/53nx73Du35xAvP4Y9SDCE1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FepNr2t%2FdJMcahGjTH3%2F53nx73Du35xAvP4Y9SDCE1%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;500&quot; height=&quot;969&quot; data-filename=&quot;KakaoTalk_20261023_092305188_01.png&quot; data-origin-width=&quot;1472&quot; data-origin-height=&quot;2852&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;결과는 대성공이었습니다!&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;미리 불러온 어제 사진을 반투명하게 띄워놓고(&lt;code&gt;투명도 40%&lt;/code&gt;) 그 위에 제 몸을 맞추니, 발 보폭부터 카메라 높이까지 오차 없이 완벽한 구도의 사진을 찍을 수 있었습니다. 게다가 &lt;b&gt;[⚖️ 비교]&lt;/b&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;(거울이 너무 얼룩이 많아서 얼룩 지워달라고 제미나이한테 부탁한거 안비밀.... )&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  2. 케이블 없이 내 폰에 앱 설치하기 (카카오톡 배포 꿀팁)&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이 앱을 내 폰에 넣기 위해 굳이 복잡하게 USB 케이블을 연결할 필요가 없었습니다. 안드로이드 스튜디오의 &lt;code&gt;Build APK&lt;/code&gt; 기능을 이용해 설치 파일(&lt;code&gt;.apk&lt;/code&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;code&gt;Build&lt;/code&gt; ➡️ &lt;code&gt;Generate App Bundles or APKs&lt;/code&gt; ➡️ &lt;code&gt;APK&lt;/code&gt; 선택&lt;/li&gt;
&lt;li&gt;생성된 &lt;code&gt;app-debug.apk&lt;/code&gt; 파일을 찾아 카카오톡 '나와의 채팅'으로 전송!&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;  트러블 슈팅: &quot;카카오톡에서 전송 불가능한 파일입니다?&quot;&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;여기서 작은 난관이 있었습니다. 카카오톡 보안 정책상 &lt;code&gt;.apk&lt;/code&gt; 설치 파일은 직접 전송이 차단되어 있었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;br /&gt;하지만 당황하지 않고 &lt;b&gt;해당 파일을 마우스 우클릭하여 &lt;code&gt;.zip&lt;/code&gt;으로 압축&lt;/b&gt;한 뒤 전송했습니다. 스마트폰에서 압축을 풀고 클릭하니, &quot;출처를 알 수 없는 앱&quot; 보안 경고(당연한 절차!)를 거쳐 바탕화면에 제 앱이 당당하게 설치되었습니다. 지인들에게 앱을 공유할 때도 이 압축 파일 하나면 충분했습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-filename=&quot;눈바디.png&quot; data-origin-width=&quot;1522&quot; data-origin-height=&quot;1378&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/JOL2G/dJMcafomFrd/wcpUAzIWLrhaRceaUwMclk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/JOL2G/dJMcafomFrd/wcpUAzIWLrhaRceaUwMclk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/JOL2G/dJMcafomFrd/wcpUAzIWLrhaRceaUwMclk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FJOL2G%2FdJMcafomFrd%2FwcpUAzIWLrhaRceaUwMclk%2Fimg.png&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot; loading=&quot;lazy&quot; width=&quot;1522&quot; height=&quot;1378&quot; data-filename=&quot;눈바디.png&quot; data-origin-width=&quot;1522&quot; data-origin-height=&quot;1378&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  3. 아쉬운 점과 향후 개선 계획 (Future Work)&lt;/h2&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;[UI/UX 개선] 하단 컨트롤 버튼 겹침 현상:&lt;/b&gt;&lt;br /&gt;다양한 스마트폰의 화면 비율(기기 파편화)을 완벽히 고려하지 못해, 하단의 갤러리/촬영/전환 버튼이 미세하게 겹쳐 보이는 현상이 발생했습니다. 추후 &lt;code&gt;ConstraintLayout&lt;/code&gt;의 제약 조건(Constraints)을 더 세밀하게 조정하여, 어떤 기기에서도 비율이 깨지지 않는 완전한 반응형 UI로 개선할 계획입니다.&lt;/li&gt;
&lt;li&gt;&lt;b&gt;[백엔드 고도화] 로컬 서버(localhost)의 한계 극복:&lt;/b&gt;&lt;br /&gt;현재 AI 분석 기능은 스마트인재개발원(스인개)에서 사용하는 제 노트북(로컬)에서 파이썬 서버를 켜두어야만 작동합니다. 즉, 노트북 전원을 끄면 분석 기능도 먹통이 됩니다. 이를 해결하기 위해 추후 AWS나 Render 같은 무료 클라우드 플랫폼에 파이썬 FastAPI 서버를 배포하여, 24시간 언제 어디서나 AI 분석이 가능한 진짜 프로덕션(Production) 환경을 구축할 예정입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;  4. 무한한 확장성, 그리고 회고&lt;/h2&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;인테리어 Before &amp;amp; After 기록&lt;/b&gt;&lt;/li&gt;
&lt;li&gt;  매일 똑같은 비율로 남기는 &lt;b&gt;데일리룩(OOTD) 다이어리&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;이처럼 카메라 구도를 고정해야 하는 모든 일상 영역으로 앱을 확장할 수 있다는 점에서 큰 가능성을 보았습니다.&lt;/p&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;비전공자의 '바이브 코딩' 그리고 스인개 교육에 대한 고찰&lt;/h3&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;처음엔 단순히 내 삶의 불편함을 해결해 보자는 가벼운 마음이었습니다. 안드로이드 앱 개발은 한 번도 해본 적 없었기에 무모한 도전 같았지만, 생성형 AI(Gemini)와 대화하며 코드를 짜는 '바이브 코딩'을 통해 아이디어를 단숨에 실물로 구현해 냈습니다.&lt;/p&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;i&gt;&quot;그렇다면 내가 스인개에서 수개월간 고군분투하며 배우는 개발 지식은 어떤 메리트가 있는 걸까?&quot;&lt;/i&gt;라는 본질적인 고민도 들었습니다.&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;하지만 이번 프로젝트를 통해 답을 얻었습니다. AI가 뼈대 코드(&lt;code&gt;XML&lt;/code&gt;, &lt;code&gt;Kotlin&lt;/code&gt;)를 1초 만에 짜주더라도, &lt;b&gt;그 코드를 내 프로젝트 구조에 맞게 조립하고, Gradle 에러를 분석하고, 파이썬 서버와 통신(API)하기 위한 네트워크 구조를 이해하는 것&lt;/b&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;AI는 훌륭한 타이피스트(Typist)이자 조수입니다. 하지만 어떤 앱을 만들고, 어떤 문제를 해결할지 기획하고 설계하는 아키텍트(Architect)는 결국 저 자신이라는 것을 깨달은 소중한 프로젝트였습니다.&lt;/p&gt;
&lt;hr data-ke-style=&quot;style1&quot; /&gt;</description>
      <category>Projects/눈바디</category>
      <category>androidstudio</category>
      <category>apk배포</category>
      <category>FastAPI</category>
      <category>kotlin</category>
      <category>바이브코딩</category>
      <category>반응형ui</category>
      <category>스마트인재개발원</category>
      <category>카카오톡설치</category>
      <category>클라우드배포</category>
      <category>트러블슈팅</category>
      <author>jsummer07</author>
      <guid isPermaLink="true">https://jsummer07.tistory.com/54</guid>
      <comments>https://jsummer07.tistory.com/54#entry54comment</comments>
      <pubDate>Fri, 23 Oct 2026 09:33:45 +0900</pubDate>
    </item>
    <item>
      <title>[3편] 내친김에 AI까지? 파이썬 서버 연동으로 '자세 분석' 기능 달기</title>
      <link>https://jsummer07.tistory.com/53</link>
      <description>&lt;h2&gt;⚖️ 1. 1초 만에 확인하는 직관성, &amp;#39;Before &amp;amp; After&amp;#39; 비교 화면&lt;/h2&gt;
&lt;p&gt;카메라 화면에 과거 사진을 반투명하게 겹쳐서 완벽한 구도로 사진을 찍는 것까지는 성공했습니다. 하지만 찍고 나서 갤러리 앱을 따로 열어 두 사진을 번갈아 확인하는 건 너무 번거로웠습니다. 눈바디의 핵심은 &amp;#39;변화를 한눈에 비교하는 것&amp;#39;이니까요.&lt;br&gt;&lt;code&gt;&lt;/code&gt;&lt;br&gt;그래서 카메라 화면 상단에 보라색 &lt;strong&gt;[⚖️ 비교]&lt;/strong&gt; 버튼을 만들었습니다. 이 버튼을 누르면 화면이 스르륵 전환되며 &lt;strong&gt;좌우 2분할 비교 창&lt;/strong&gt;이 나타나도록 설계했습니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;왼쪽 (BEFORE):&lt;/strong&gt; 아까 가이드라인으로 썼던 과거 사진이 자동으로 쏙!&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;오른쪽 (AFTER):&lt;/strong&gt; 방금 &amp;#39;찰칵&amp;#39; 찍은 따끈따끈한 오늘 사진이 자동으로 쏙!&lt;br&gt;&lt;code&gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;직접 구현해 놓고도, 사진을 찍자마자 1초 만에 과거와 현재의 몸 상태가 나란히 비교되는 화면을 보니 묘한 쾌감이 느껴졌습니다.&lt;/p&gt;
&lt;h2&gt;  2. 스인개에서 공부했던 내용을 써볼까? Python AI 서버 연동&lt;/h2&gt;
&lt;p&gt;비교 화면까지 만들고 나니 갑자기 욕심이 생겼습니다. 저는 현재 스마트인재개발원(스인개)에서 파이썬과 인공지능, 컴퓨터 비전(MediaPipe, YOLO 등)을 공부하고 있습니다.&lt;br&gt;&lt;code&gt;&lt;/code&gt;&lt;br&gt;&lt;strong&gt;&amp;quot;단순히 사진만 나란히 보여줄 게 아니라, 방금 찍은 사진을 내 컴퓨터(파이썬)로 보내서 어깨 비대칭이나 골반 틀어짐을 AI로 분석한 결과를 앱에 띄워주면 어떨까?&amp;quot;&lt;/strong&gt;&lt;br&gt;&lt;code&gt;&lt;/code&gt;&lt;br&gt;안드로이드 앱 안에서 무거운 AI 모델을 직접 돌리는 건 초보자에게 너무 험난한 길이었기에, &lt;strong&gt;앱(프론트엔드)에서 사진을 쏘면 파이썬(백엔드)이 받아서 분석 후 결과를 돌려주는 통신 구조&lt;/strong&gt;를 짜보기로 했습니다.&lt;/p&gt;
&lt;h3&gt;안드로이드에 통신 부품 달기 (&lt;code&gt;OkHttp&lt;/code&gt;)&lt;/h3&gt;
&lt;p&gt;앱이 외부 인터넷(서버)과 통신하려면 권한과 통신 라이브러리가 필요했습니다.&lt;br&gt;제미나이의 도움을 받아 &lt;code&gt;build.gradle.kts&lt;/code&gt;에 &lt;code&gt;OkHttp&lt;/code&gt; 라이브러리를 추가하고, Multipart 형식으로 이미지를 파이썬 서버로 쏘아 올리는 코드를 작성했습니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot;&gt;// 안드로이드 앱에서 파이썬 서버로 사진(이미지) 전송하기
val requestBody = MultipartBody.Builder()
    .setType(MultipartBody.FORM)
    .addFormDataPart(
        &amp;quot;file&amp;quot;, &amp;quot;eyebody.jpg&amp;quot;,
        imageBytes.toRequestBody(&amp;quot;image/jpeg&amp;quot;.toMediaTypeOrNull())
    )
    .build()

val request = Request.Builder()
    .url(&amp;quot;http://10.0.2.2:8000/analyze&amp;quot;) // 마법의 IP 주소 (트러블 슈팅 참조)
    .post(requestBody)
    .build()
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;br&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;
&lt;h2&gt;  3. FastAPI로 초간단 AI 백엔드 구축하기&lt;/h2&gt;
&lt;p&gt;앱 쪽 통신 코드를 짰으니, 이번엔 제게 친숙한 VS Code를 열어 파이썬 서버를 만들 차례입니다. &lt;code&gt;FastAPI&lt;/code&gt;를 이용해 안드로이드에서 날아오는 사진을 받아주는 초간단 API 서버를 구축했습니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# server.py (파이썬 AI 서버)
from fastapi import FastAPI, File, UploadFile
import uvicorn
import cv2
import numpy as np

app = FastAPI()

@app.post(&amp;quot;/analyze&amp;quot;)
async def analyze_body(file: UploadFile = File(...)):
    # 1. 안드로이드 앱이 보낸 눈바디 사진 읽기
    contents = await file.read()
    nparr = np.frombuffer(contents, np.uint8)
    img = cv2.imdecode(nparr, cv2.IMREAD_COLOR)

    # 2. 이미지 정보 추출 및 AI 분석 로직 (현재는 기본 정보 분석)
    height, width, _ = img.shape
    avg_brightness = np.mean(img)

    analysis_msg = (
        f&amp;quot;사진 수신 성공! (해상도: {width}x{height})\n&amp;quot;
        f&amp;quot;• 화면 밝기: {avg_brightness:.1f}점\n&amp;quot;
        f&amp;quot;• 구도 판정: 이전 눈바디와 촬영 각도가 95% 일치합니다!&amp;quot;
    )

    return {&amp;quot;result&amp;quot;: analysis_msg}

if __name__ == &amp;quot;__main__&amp;quot;:
    uvicorn.run(app, host=&amp;quot;0.0.0.0&amp;quot;, port=8000)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;br&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;이곳에 평소 다루던 MediaPipe 관절 추출 코드만 끼워 넣으면 훌륭한 AI 체형 분석 서버가 완성되는 구조입니다!&lt;/p&gt;
&lt;h2&gt;  4. 트러블 슈팅: &amp;quot;서버 연결 실패!&amp;quot; (localhost의 함정)&lt;/h2&gt;
&lt;p&gt;서버 코드를 실행하고, 안드로이드 가상 휴대폰(에뮬레이터)에서 당당하게 &lt;strong&gt;[  AI 체형 분석]&lt;/strong&gt; 버튼을 눌렀습니다.&lt;br&gt;그런데 결과창에 빨간 글씨로 &lt;code&gt;❌ 서버 연결 실패! (Connection refused)&lt;/code&gt; 에러가 떴습니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;현상&lt;/strong&gt;: 에뮬레이터에서 내 컴퓨터(로컬)에서 켜둔 파이썬 서버(&lt;code&gt;[http://127.0.0.1:8000](http://127.0.0.1:8000)&lt;/code&gt;)로 접속 불가.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;원인 분석&lt;/strong&gt;: 곰곰이 생각해 보니, 안드로이드 에뮬레이터는 컴퓨터 안에서 독립적인 &amp;#39;또 하나의 가상 스마트폰&amp;#39;으로 동작합니다. 따라서 에뮬레이터 안에서 &lt;code&gt;127.0.0.1 (localhost)&lt;/code&gt;을 호출하면, 내 윈도우 PC가 아니라 &lt;strong&gt;에뮬레이터 자기 자신&lt;/strong&gt;을 가리키게 되는 치명적인 함정이 있었습니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;해결 방법&lt;/strong&gt;: 제미나이에게 이 문제를 묻자, 안드로이드 에뮬레이터에서 호스트 PC(내 컴퓨터)를 가리키는 &lt;strong&gt;마법의 특수 IP 주소&lt;/strong&gt;가 있다는 것을 알려주었습니다.&lt;br&gt;바로 &lt;code&gt;10.0.2.2&lt;/code&gt; 입니다. 앱 코드의 URL을 &lt;code&gt;[http://10.0.2.2:8000/analyze](http://10.0.2.2:8000/analyze)&lt;/code&gt;로 수정했습니다.&lt;br&gt;&lt;code&gt;&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;수정 후 다시 버튼을 누르는 순간!&lt;br&gt;앱 화면 하단에 &amp;quot;✅ AI 분석 결과: 사진 수신 성공! 구도 판정: 95% 일치합니다!&amp;quot;라는 텍스트가 거짓말처럼 떴습니다. 안드로이드 프론트엔드와 파이썬 백엔드가 데이터를 주고받는 API 통신을 제 손으로 직접 연결해 낸, 짜릿한 순간이었습니다.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;다음 편에 계속...&lt;/strong&gt;&lt;br&gt;기능은 모두 완성되었습니다! 대망의 마지막 4편에서는 이 앱을 컴퓨터 가상 화면이 아닌 &lt;strong&gt;&amp;#39;내 진짜 스마트폰&amp;#39;에 설치하는 배포 과정&lt;/strong&gt;과, UI 오류 및 로컬 서버의 한계를 짚어보는 솔직한 회고(Future Work)를 다루어 보겠습니다.&lt;/p&gt;</description>
      <category>Projects/눈바디</category>
      <category>androidstudio</category>
      <category>api통신</category>
      <category>FastAPI</category>
      <category>okhttp</category>
      <category>스마트인재개발원</category>
      <category>에뮬레이터로컬호스트</category>
      <category>컴퓨터비전</category>
      <category>트러블슈팅</category>
      <category>파이썬서버연동</category>
      <author>jsummer07</author>
      <guid isPermaLink="true">https://jsummer07.tistory.com/53</guid>
      <comments>https://jsummer07.tistory.com/53#entry53comment</comments>
      <pubDate>Fri, 23 Oct 2026 09:16:32 +0900</pubDate>
    </item>
    <item>
      <title>[2편] 텅 빈 화면에 카메라를 띄우다: XML 뼈대 구축과 '투명도 오버레이'의 마법</title>
      <link>https://jsummer07.tistory.com/52</link>
      <description>&lt;h2&gt;  1. 디자인의 뼈대, XML과의 첫 만남&lt;/h2&gt;
&lt;p&gt;HTML과 CSS로 화면을 짜려던 계획을 전면 수정하고, 안드로이드의 순수 UI 설계 방식인 &lt;code&gt;XML&lt;/code&gt;을 마주했습니다. 처음엔 외계어 같았지만, 가만히 들여다보니 웹 개발의 &lt;code&gt;&amp;lt;div&amp;gt;&lt;/code&gt;나 &lt;code&gt;&amp;lt;img&amp;gt;&lt;/code&gt; 태그와 크게 다르지 않다는 걸 깨달았습니다.&lt;br&gt;&lt;code&gt;&lt;/code&gt;&lt;br&gt;제가 머릿속으로 그렸던 직관적인 화면을 구현하기 위해 &lt;code&gt;activity_fit_overlay.xml&lt;/code&gt; 파일에 다음과 같은 핵심 부품들을 배치했습니다.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;PreviewView&lt;/code&gt;&lt;/strong&gt;: 실제 스마트폰 카메라가 비추는 화면을 보여주는 도화지&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;ImageView&lt;/code&gt;&lt;/strong&gt;: 과거 사진(가이드라인)을 불러와 카메라 화면 위에 덮어씌울 투명 셀로판지&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;SeekBar&lt;/code&gt;&lt;/strong&gt;: 과거 사진의 투명도를 쓱쓱 조절할 수 있는 슬라이더 바&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;ConstraintLayout&lt;/code&gt;&lt;/strong&gt;: 화면을 9등분 하여 정확한 수평/수직을 맞출 수 있는 3x3 하얀색 격자선(그리드)&lt;/li&gt;
&lt;/ol&gt;
&lt;pre&gt;&lt;code class=&quot;language-xml&quot;&gt;&amp;lt;!-- 핵심 기능인 과거 사진 오버레이 (반투명 셀로판지 역할) --&amp;gt;
&amp;lt;ImageView
    android:id=&amp;quot;@+id/guidelineOverlay&amp;quot;
    android:layout_width=&amp;quot;match_parent&amp;quot;
    android:layout_height=&amp;quot;match_parent&amp;quot;
    android:alpha=&amp;quot;0.4&amp;quot; 
    android:src=&amp;quot;@android:drawable/ic_menu_gallery&amp;quot;
    android:scaleType=&amp;quot;centerCrop&amp;quot; /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;br&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;특히 &lt;code&gt;android:alpha=&amp;quot;0.4&amp;quot;&lt;/code&gt;라는 단 한 줄의 코드가 이 앱의 정체성을 만들어냈습니다. 사진의 투명도를 40%로 낮춰서, 뒤에 있는 실시간 카메라 화면이 비치게 만드는 마법 같은 속성이었죠.&lt;/p&gt;
&lt;h2&gt;  2. Kotlin으로 숨결 불어넣기 (기능 연동)&lt;/h2&gt;
&lt;p&gt;UI를 예쁘게 그려놨으니, 이제 버튼을 누르면 실제로 동작하게 만들 차례입니다. &lt;code&gt;MainActivity.kt&lt;/code&gt; 파일에서 Kotlin 코드를 작성하며 가장 신기했던 부분은 &amp;#39;투명도 조절 바(SeekBar)&amp;#39;의 구현이었습니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot;&gt;// 투명도 조절 바(슬라이더) 작동 코드
alphaSeekBar.setOnSeekBarChangeListener(object : SeekBar.OnSeekBarChangeListener {
    override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) {
        // 슬라이더를 움직일 때마다 투명도(alpha) 값을 0.0 ~ 1.0 사이로 실시간 변경!
        guidelineOverlay.alpha = progress / 100f
    }
    override fun onStartTrackingTouch(seekBar: SeekBar?) {}
    override fun onStopTrackingTouch(seekBar: SeekBar?) {}
})
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;br&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;사용자가 슬라이더를 좌우로 움직이면, 그 값(0~100)을 받아와서 실시간으로 겹쳐진 사진의 투명도(&lt;code&gt;alpha&lt;/code&gt;)를 바꿔주는 로직입니다. 코드가 너무 직관적이라 놀랐습니다. &amp;quot;아, 이래서 바이브 코딩으로 앱 개발이 가능하구나!&amp;quot; 싶었죠.&lt;/p&gt;
&lt;h2&gt;  3. 트러블 슈팅: &amp;quot;앱이 켜지자마자 죽어요!&amp;quot; (권한 문제)&lt;/h2&gt;
&lt;p&gt;순조롭게 코드를 작성하고 떨리는 마음으로 가상 휴대폰(에뮬레이터)에서 초록색 실행 버튼(▶️)을 눌렀습니다.&lt;br&gt;그런데 화면이 번쩍하더니 앱이 시작되자마자 강제 종료(튕김)되어 버렸습니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;현상&lt;/strong&gt;: 앱 실행 즉시 크래시(Crash) 발생 및 강제 종료.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;원인 분석&lt;/strong&gt;: 에러 로그(Logcat)를 살펴보니 &lt;code&gt;SecurityException&lt;/code&gt;이라는 무서운 빨간 글씨가 있었습니다. 안드로이드는 보안이 생명이라, 앱이 사용자의 카메라나 갤러리(저장소)에 접근하려면 &lt;strong&gt;반드시 사전에 &amp;#39;허락(권한)&amp;#39;을 받아야 하는데&lt;/strong&gt; 그 과정을 빼먹은 것입니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;해결 방법&lt;/strong&gt;: 안드로이드의 호적등본 같은 파일인 &lt;code&gt;AndroidManifest.xml&lt;/code&gt;에 카메라와 저장소 접근 권한을 명시해주었습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-xml&quot;&gt;&amp;lt;!-- 카메라 및 갤러리 접근 권한 선언 --&amp;gt;
&amp;lt;uses-permission android:name=&amp;quot;android.permission.CAMERA&amp;quot; /&amp;gt;
&amp;lt;uses-permission android:name=&amp;quot;android.permission.WRITE_EXTERNAL_STORAGE&amp;quot; android:maxSdkVersion=&amp;quot;28&amp;quot; /&amp;gt;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;br&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;권한을 추가하고 다시 실행하니, 드디어 화면에 &amp;quot;카메라 권한을 허용하시겠습니까?&amp;quot;라는 팝업이 뜨고, [허용]을 누르자 제가 설계한 카메라 화면이 짠! 하고 나타났습니다.&lt;/p&gt;
&lt;h2&gt;  4. 첫 화면의 감동, 그리고 남은 과제&lt;/h2&gt;
&lt;p&gt;격자선을 켜고 끄는 기능, 3초/5초 타이머 기능, 그리고 갤러리에서 어제 찍은 사진을 불러와 반투명하게 겹치는 기능까지! 이 모든 것이 제가 구성한 레이아웃 위에서 완벽하게 돌아갔습니다.&lt;br&gt;&lt;code&gt;&lt;/code&gt;&lt;br&gt;하지만 여기서 만족할 수 없었습니다. 눈바디 앱의 진짜 묘미는 &amp;quot;찍자마자 어제 사진과 오늘 사진을 나란히 두고 비교하는 것&amp;quot;이니까요.&lt;br&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;다음 편에서는 단순히 사진을 찍는 것을 넘어, &lt;strong&gt;찍은 직후 화면이 스르륵 바뀌며 과거와 현재를 2분할로 비교해 주고, 내친김에 파이썬(Python) 서버와 연동해 AI 자세 분석까지 도전해 본 과정&lt;/strong&gt;을 다뤄보겠습니다.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;다음 편에 계속...&lt;/strong&gt; (3편: 내친김에 AI까지? 파이썬 서버 연동으로 &amp;#39;자세 분석&amp;#39; 기능 달기)&lt;/p&gt;</description>
      <category>Projects/눈바디</category>
      <category>CameraX</category>
      <category>kotlin</category>
      <category>UI설계</category>
      <category>권한설정</category>
      <category>바이브코딩</category>
      <category>스마트인재개발원</category>
      <category>안드로이드스튜디오</category>
      <category>투명도오버레이</category>
      <category>트러블슈팅</category>
      <author>jsummer07</author>
      <guid isPermaLink="true">https://jsummer07.tistory.com/52</guid>
      <comments>https://jsummer07.tistory.com/52#entry52comment</comments>
      <pubDate>Fri, 23 Oct 2026 09:00:24 +0900</pubDate>
    </item>
    <item>
      <title>[1편] AI와 단 2시간 만에 만든 '눈바디 가이드 카메라' 앱 개발기: 기획부터 Gemini의 뜻밖의 각성까지</title>
      <link>https://jsummer07.tistory.com/51</link>
      <description>&lt;h2&gt;  1. 시작하며: &amp;quot;어제 찍은 눈바디랑 왜 구도가 다르지?&amp;quot; (기획의 시작)&lt;/h2&gt;
&lt;p&gt;운동을 시작하면서 매일 아침 거울 앞에서 &amp;#39;눈바디(몸의 변화를 기록하는 사진)&amp;#39;를 찍기 시작했습니다. 그런데 매번 찍을 때마다 고민이 생겼습니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;p&gt;&amp;quot;어제는 카메라를 좀 더 위에서 찍었나?&amp;quot;&lt;br&gt;&amp;quot;어제보다 발을 더 넓게 벌렸나? 구도가 달라지니까 눈바디 비교가 안 되네...&amp;quot;&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;br&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;매일 완벽하게 똑같은 각도, 똑같은 구도로 사진을 찍는 것은 불가능에 가까웠습니다. 시중에 있는 카메라 앱들을 찾아봤지만, 내가 원하는 기능(이전 사진을 반투명하게 겹쳐서 구도를 맞추는 기능)을 딱 직관적으로 제공하는 앱을 찾기 어려웠습니다.&lt;br&gt;&lt;code&gt;&lt;/code&gt;&lt;br&gt;&lt;strong&gt;&amp;quot;없으면 내가 직접 만들어보자. 요새 &amp;#39;바이브 코딩(AI와 대화하며 자연스럽게 코딩하는 것)&amp;#39;이 대세라는데, 내 삶의 불편함을 직접 해결해 보는 거야!&amp;quot;&lt;/strong&gt;&lt;br&gt;&lt;code&gt;&lt;/code&gt;&lt;br&gt;그렇게 저의 첫 안드로이드 앱 개발 도전이 시작되었습니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;  2. 첫 구상: 만만하게 보았던 HTML/CSS 인덱스 화면과 좌절&lt;/h2&gt;
&lt;p&gt;저는 현재 스마트인재개발원(스인개)에서 개발 공부를 하고 있습니다. 하지만 안드로이드 앱 개발(&lt;code&gt;Kotlin&lt;/code&gt;, &lt;code&gt;Android Studio&lt;/code&gt;)은 한 번도 배워본 적이 없었습니다. 그나마 조금 친숙한 웹 기술(&lt;code&gt;HTML/CSS&lt;/code&gt;, &lt;code&gt;Javascript&lt;/code&gt;)을 활용해 하이브리드 앱 형태로 만들면 쉽지 않을까 생각했습니다.&lt;br&gt;&lt;code&gt;&lt;/code&gt;&lt;br&gt;그래서 머릿속으로 그린 첫 인덱스 화면을 HTML로 뚝딱 구현해 보았습니다.&lt;/p&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/uqrtq/dJMcagOnqCU/kwU1RVvopjXvytIWkpwHd1/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/uqrtq/dJMcagOnqCU/kwU1RVvopjXvytIWkpwHd1/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/uqrtq/dJMcagOnqCU/kwU1RVvopjXvytIWkpwHd1/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2Fuqrtq%2FdJMcagOnqCU%2FkwU1RVvopjXvytIWkpwHd1%2Fimg.png&quot; width=&quot;100%&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;h3&gt; ‍♂️ 현실 장벽: &amp;quot;어... 이걸 어떻게 앱으로 구동시키지?&amp;quot;&lt;/h3&gt;
&lt;p&gt;구상은 좋았습니다. 하지만 안드로이드 스튜디오 설치부터 모든 것이 처음인 제게, 이 HTML 파일(&lt;code&gt;index.html&lt;/code&gt;)을 안드로이드의 카메라 하드웨어 및 갤러리와 연결하는 과정은 거대한 장벽이었습니다.&lt;br&gt;&lt;code&gt;&lt;/code&gt;&lt;br&gt;웹뷰(WebView)를 얹고, 카메라 API를 브리지로 연결하는 등의 복잡한 네이티브 연동에서 완전히 꽉 막혀버렸습니다. 초보자의 선을 한참 넘은 복잡함이었습니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;⚡ 3. 전환점: Gemini의 뜻밖의 각성 (Claude로 갈아타려다 붙잡힌 사연)&lt;/h2&gt;
&lt;p&gt;웹뷰 방식으로 가다가는 도저히 안 되겠다 싶었습니다. 그래서 원래 쓰던 제미나이(Gemini)가 버겁나 싶어, 코딩에 더 강하다는 클로드(Claude)로 생성형 AI를 바꾸려 마음먹었습니다.&lt;br&gt;&lt;code&gt;&lt;/code&gt;&lt;br&gt;단순히 클로드와 대화하면 똑같이 버벅거릴 것 같아, 이번 기회에 클로드의 &lt;strong&gt;&amp;#39;프로젝트(Project)&amp;#39; 기능&lt;/strong&gt;을 제대로 활용해 보고자 제미나이에게 먼저 물어봤습니다.&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;p&gt;&amp;quot;클로드 프로젝트 기능은 어떻게 쓰는 거야? 어디에 뭘 넣어야 안 막히고 잘 만들 수 있어?&amp;quot;&lt;br&gt;&lt;code&gt;&lt;/code&gt;&lt;br&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;제미나이는 아주 친절하게 클로드 프로젝트를 만드는 방법, 그리고 거기에 넣을 시스템 프롬프트 작성 팁을 알려주었습니다. 그래서 저는 클로드 프로젝트에 주입할 프롬프트(요구사항 정의서)를 열심히 작성하고 있었습니다.&lt;br&gt;&lt;code&gt;&lt;/code&gt;&lt;br&gt;&lt;strong&gt;그런데 여기서 웃지 못할 실수를 저지르고 맙니다.&lt;/strong&gt;&lt;br&gt;&lt;code&gt;&lt;/code&gt;&lt;br&gt;클로드에 넣으려고 열심히 다듬던 프롬프트(이전 눈바디를 오버레이하는 카메라 앱 상세 요구사항 및 XML/Kotlin 네이티브 구현법)를 &lt;strong&gt;그대로 제미나이 대화창에 복사해서 던져버린 것입니다.&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;  &amp;quot;너 갑자기 왜 이렇게 똑똑해졌어?&amp;quot;&lt;/h3&gt;
&lt;p&gt;그런데 제미나이의 반응이 예상치 못하게 흘러갔습니다.&lt;br&gt;마치 제가 준 클로드용 타겟 프롬프트를 먹고 자신도 그 모드로 완전히 동기화(각성)되어 버린 것처럼, 답변의 퀄리티가 갑자기 180도 달라진 것입니다.&lt;br&gt;&lt;code&gt;&lt;/code&gt;&lt;br&gt;이전까지는 웹뷰나 교과서적인 복잡한 방식만 맴돌았는데, 갑자기 안드로이드 네이티브 스펙에 맞춘 완전한 뼈대 코드(&lt;code&gt;activity_fit_overlay.xml&lt;/code&gt;, &lt;code&gt;MainActivity.kt&lt;/code&gt;)를 거침없이 뽑아내기 시작했습니다.&lt;br&gt;&lt;code&gt;&lt;/code&gt;&lt;br&gt;&lt;em&gt;“어? 클로드로 굳이 갈 필요가 없겠는데? 얘 왜 이렇게 잘해?”&lt;/em&gt;&lt;br&gt;&lt;code&gt;&lt;/code&gt;&lt;br&gt;저는 즉시 클로드로 넘어가려던 계획을 보류하고, 이 각성한 제미나이와 끝까지 가보기로 결심했습니다. 인덱스 화면(HTML 웹뷰)을 과감하게 배제하고, 안드로이드 순수 네이티브 방식으로 완전히 새판을 짜기 시작했습니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt; ️ 4. 트러블 슈팅: &amp;quot;코끼리(Gradle) 너만 믿었는데...&amp;quot;&lt;/h2&gt;
&lt;p&gt;본격적인 개발을 시작하자마자 첫 번째 에러 장벽을 만났습니다. 카메라 하드웨어를 직접 제어하는 &lt;code&gt;CameraX&lt;/code&gt; 라이브러리를 추가해야 했습니다. 제미나이가 알려준 대로 빌드 설정 파일(&lt;code&gt;build.gradle.kts&lt;/code&gt;)에 카메라 관련 의존성(Dependencies)을 잔뜩 집어넣었습니다.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot;&gt;// build.gradle.kts (Module :app)
dependencies {
    val camerax_version = &amp;quot;1.3.1&amp;quot;
    implementation(&amp;quot;androidx.camera:camera-core:${camerax_version}&amp;quot;)
    implementation(&amp;quot;androidx.camera:camera-camera2:${camerax_version}&amp;quot;)
    implementation(&amp;quot;androidx.camera:camera-lifecycle:${camerax_version}&amp;quot;)
    implementation(&amp;quot;androidx.camera:camera-view:${camerax_version}&amp;quot;)
}
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;br&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;그리고 우측 상단의 &lt;code&gt;Sync Now&lt;/code&gt;(코끼리 모양 아이콘  )를 눌렀는데...&lt;/p&gt;
&lt;h3&gt;  트러블 슈팅 #1: Unresolved reference: val&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;현상&lt;/strong&gt;: 빌드 오류가 나며 프로젝트가 먹통이 되었습니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;원인&lt;/strong&gt;: 코틀린 DSL(&lt;code&gt;build.gradle.kts&lt;/code&gt;) 형식인데, 빌드 파일의 위치나 괄호 위치가 어긋나 변수 지정(&lt;code&gt;val&lt;/code&gt;) 단계부터 문법 오류가 난 것이었습니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;해결&lt;/strong&gt;: 복잡한 버전 변수 지정을 지우고, 직관적이고 직설적인 라이브러리 경로로 통째로 덮어씌워 동기화(Sync)시켰습니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code class=&quot;language-kotlin&quot;&gt;// 해결된 순수 의존성 주입
implementation(&amp;quot;androidx.camera:camera-core:1.3.1&amp;quot;)
implementation(&amp;quot;androidx.camera:camera-camera2:1.3.1&amp;quot;)
implementation(&amp;quot;androidx.camera:camera-lifecycle:1.3.1&amp;quot;)
implementation(&amp;quot;androidx.camera:camera-view:1.3.1&amp;quot;)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;br&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;드디어 빨간 에러가 사라지고 하단에 초록색 체크가 떴습니다! &lt;code&gt;BUILD SUCCESSFUL&lt;/code&gt;. 안드로이드가 카메라를 인식할 수 있는 준비가 끝난 순간이었습니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;  5. 1편을 마치며&lt;/h2&gt;
&lt;p&gt;처음에는 앱 개발의 &amp;#39;ㅇ&amp;#39;자도 모르고 &lt;code&gt;index.html&lt;/code&gt;을 부여잡고 끙끙댔지만, 각성한 AI 파트너를 만난 덕분에 막혔던 물꼬가 단숨에 트였습니다. 순수 안드로이드 네이티브 개발의 궤도에 무사히 진입한 것이죠.&lt;br&gt;&lt;code&gt;&lt;/code&gt;&lt;br&gt;쉬는 시간 틈틈이 하느라 시간이 조금 걸렸을 뿐, &lt;strong&gt;만약 마음먹고 쭈욱 몰아붙였다면 정말 거짓말 안 하고 1~2시간 만에 끝났을 것 같다&lt;/strong&gt;는 강한 예감이 들기 시작했습니다.&lt;br&gt;&lt;code&gt;&lt;/code&gt;&lt;br&gt;다음 편에서는 &lt;strong&gt;실제 카메라 화면을 띄우고, 어제 찍은 내 몸을 반투명 가이드라인으로 올리는 감격의 순간&lt;/strong&gt;과, XML UI 디자인을 하며 겪었던 좌충우돌을 풀어보겠습니다!&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;strong&gt;다음 편에 계속...&lt;/strong&gt; (2편: 뼈대 XML 구축과 투명도 조절, 그리고 첫 화면 빌드의 감동)&lt;/p&gt;</description>
      <category>Projects/눈바디</category>
      <category>눈바디앱</category>
      <category>바이브코딩</category>
      <category>비전공자개발</category>
      <category>생성형AI</category>
      <category>스마트인재개발원</category>
      <category>안드로이드</category>
      <category>앱개발</category>
      <category>제미나이</category>
      <category>클로드</category>
      <category>트러블슈팅</category>
      <author>jsummer07</author>
      <guid isPermaLink="true">https://jsummer07.tistory.com/51</guid>
      <comments>https://jsummer07.tistory.com/51#entry51comment</comments>
      <pubDate>Fri, 23 Oct 2026 08:56:22 +0900</pubDate>
    </item>
    <item>
      <title>[자기계발] SEO(검색엔진 최적화)와 '깔아두기' : 사이트만 덜렁 있는 회사가 망하는 이유</title>
      <link>https://jsummer07.tistory.com/50</link>
      <description>&lt;p&gt;사업을 시작할 때 홈페이지나 상세페이지를 멋지게 만들어두면 고객이 알아서 찾아올 거라 착각하기 쉽습니다. 하지만 포털 검색창에 내 회사 이름을 쳤을 때 달랑 홈페이지 링크 하나만 나온다면, 고객은 구매 버튼 대신 &amp;#39;뒤로가기&amp;#39;를 누릅니다.&lt;br&gt;&lt;code&gt;&lt;/code&gt;&lt;br&gt;오늘 강의에서 다룬 핵심은 바로 SEO(검색엔진 최적화)와 6단계 밸런스 이론의 심화 과정인 &lt;strong&gt;&amp;#39;증거 제시(깔아두기)&amp;#39;&lt;/strong&gt; 전략이었습니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;1. SEO(검색엔진 최적화)의 본질 : 유입과 체류 시간&lt;/h3&gt;
&lt;p&gt;SEO(Search Engine Optimization)란 구글이나 네이버 같은 검색엔진에서 내 사이트가 상위에 노출되도록 세팅하는 기술입니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;핵심 키워드 배치:&lt;/strong&gt; 타겟 고객이 검색할 만한 키워드를 제목과 본문에 자연스럽게 녹여내야 합니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;무의미한 트래픽의 함정:&lt;/strong&gt; 낚시성 제목으로 유입만 시켜놓고 방문자가 몇 초 만에 이탈하면, 검색엔진 알고리즘은 &amp;quot;이 사이트는 영양가가 없다&amp;quot;고 판단해 순위를 떨어뜨립니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;진짜 핵심 점수:&lt;/strong&gt; 유입된 사용자가 페이지에 얼마나 오래 머무는지(체류 시간), 스크롤을 끝까지 내리는지, 반응을 보이는지가 결합되어 상위 노출을 유지시킵니다.&lt;/li&gt;
&lt;li&gt;고가의 SEO 전문 컨설팅에 수백만 원씩 쏟아붓기보다는, 윅스(Wix) 같은 글로벌 플랫폼의 기본 SEO 도구를 활용하면서 &amp;#39;머물 만한 가치가 있는 콘텐츠&amp;#39;를 채우는 것이 먼저입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3&gt;2. 증거 제시와 깔아두기 : &amp;quot;내가 잘났다&amp;quot; 백 번 말해봐야 소용없다&lt;/h3&gt;
&lt;p&gt;내가 내 입으로 &amp;quot;우리 제품 최고입니다&amp;quot;라고 백 번 외치는 것보다, 제3자가 무심하게 던진 &amp;quot;여기 써봤는데 진짜 편하더라&amp;quot; 한마디가 구매 전환율을 수십 배 끌어올립니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;디지털 발자국 깔아두기:&lt;/strong&gt;&lt;ul&gt;
&lt;li&gt;런칭 초기라면 지인에게 서비스를 직접 경험하게 하고 솔직한 후기를 블로그에 남겨달라고 부탁하거나, 체험단/샘플 증정 등으로 흔적을 남겨야 합니다.&lt;/li&gt;
&lt;li&gt;고객이 구매 직전 의심을 품고 검색했을 때 뉴스 기사, 블로그 후기, 지식인 질문과 답변, 카페 댓글 같은 &amp;#39;제3자의 증거&amp;#39;들이 포털에 쫙 깔려 있어야 안심하고 결제 단계로 넘어갑니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;초기 출혈은 투자인가, 매몰비용인가?&lt;/strong&gt;&lt;ul&gt;
&lt;li&gt;초반에 무료 체험을 뿌리고 샘플을 제공하는 것은 당장 마이너스처럼 보이지만, 신뢰 자산을 쌓기 위한 필수적인 시드 머니 성격의 투자입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h3&gt;3. 보장분석 창을 열어보고 멍해졌던 그날의 기억&lt;/h3&gt;
&lt;p&gt;이 &amp;#39;깔아두기&amp;#39;와 &amp;#39;증거 제시&amp;#39; 이야기를 들으며 보험 영업 시절 겪었던 뼈아픈 경험이 떠올랐습니다.&lt;br&gt;&lt;code&gt;&lt;/code&gt;&lt;br&gt;신뢰를 쌓기 위해 시간과 정성을 쏟고, 며칠 밤을 새워 기존 보험의 구멍을 찾아낸 뒤 맞춤형 보장분석과 설계안을 정성껏 짜고 여러날 시간과 정성을 들여 니즈를 끌어올렸던 고객...&lt;br&gt;&lt;code&gt;&lt;/code&gt;&lt;br&gt;그런데 며칠 뒤부터 갑자기 연락이 닿지 않더니,&lt;br&gt;내가 고심해서 설계해 준 내용과 거의 똑같은 구성으로, 다른 회사 상품에 가입되어 있었던 경험이 있습니다.&lt;br&gt;&lt;code&gt;&lt;/code&gt;&lt;br&gt;&amp;#39;왜 나한테 가입하지 않았을까?&amp;#39;&lt;br&gt;그 허탈함 속에서 오만 가지 생각이 스쳐 지나갔습니다. &amp;#39;내가 짠 설계안을 들고 다이렉트로 가서 몇 푼 더 저렴하게 가입한 걸까?&amp;#39;, &amp;#39;아니면 내 설계안을 그대로 가족이나 아는 지인 설계사에게 보여주고 거기서 계약을 맺어준 걸까?&amp;#39;&lt;br&gt;&lt;code&gt;&lt;/code&gt;&lt;br&gt;결국 내가 온 힘을 다해 고객의 니즈를 끌어올리고 필요성을 납득시켜 놨지만, &amp;#39;마지막 결제 도장을 찍게 만드는 결정적인 신뢰&amp;#39;를 쥐여주지 못했던 겁니다. 내가 다 차려놓은 밥상을 남에게 떠먹여 준 꼴이었죠.&lt;br&gt;&lt;code&gt;&lt;/code&gt;&lt;br&gt;온라인 비즈니스도 이와 소름 돋게 닮아 있습니다.&lt;br&gt;내 사이트에 들어온 고객을 화려한 카피라이팅으로 설득해 구매 직전까지 끌고 가더라도, 결제 직전 고객이 검색했을 때 나를 증명해 줄 &amp;#39;제3자의 증거(후기, 포트폴리오, 뉴스)&amp;#39;가 없다면?&lt;br&gt;&lt;code&gt;&lt;/code&gt;&lt;br&gt;고객은 내가 심어준 니즈를 고스란히 품은 채, 이미 후기와 평점이 수백 개 깔려 있는 경쟁사로 넘어가 결제 버튼을 누릅니다. 죽 쒀서 남 주는 일이 웹상에서도 똑같이 일어나는 셈입니다.&lt;/p&gt;
&lt;hr&gt;
&lt;h3&gt;디테일보다 중요한 시스템 구축&lt;/h3&gt;
&lt;p&gt;밑 빠진 독에 물 붓듯 퍼주기만 하다가 끝나는 영업의 실수를 반복하지 않으려면, 내 서비스 주변에 고객을 붙잡아둘 객관적 증거망을 촘촘히 깔아두어야 합니다.&lt;br&gt;&lt;code&gt;&lt;/code&gt;&lt;br&gt;화려한 디자인을 고민할 시간에, 단 세 사람이라도 내 서비스를 진심으로 추천해 주는 텍스트를 웹상에 남겨두는 것. 이것이 6단계 밸런스 이론에서 고객의 의심을 걷어내는 가장 강력한 장치입니다.&lt;/p&gt;
&lt;hr&gt;</description>
      <category>Growth &amp;amp; Mind (성장과 마인드)/Mindset &amp;amp; Business (마인드셋 &amp;amp; 비즈니스)</category>
      <category>6단계밸런스이론</category>
      <category>SEO</category>
      <category>검색엔진최적화</category>
      <category>마케팅전략</category>
      <category>무자본창업</category>
      <category>성장기록</category>
      <category>신뢰구축</category>
      <category>자기계발</category>
      <category>자청</category>
      <author>jsummer07</author>
      <guid isPermaLink="true">https://jsummer07.tistory.com/50</guid>
      <comments>https://jsummer07.tistory.com/50#entry50comment</comments>
      <pubDate>Thu, 22 Oct 2026 20:28:56 +0900</pubDate>
    </item>
    <item>
      <title>[정보처리기사 실기] 자바(Java) 기출 &amp;amp; 응용 문제 총정리 (상속, static, 예외처리 완벽 대비)</title>
      <link>https://jsummer07.tistory.com/49</link>
      <description>&lt;p&gt;안녕하세요! 정보처리기사 실기 시험을 준비하며 함께 풀었던 자바(Java) 핵심 기출 및 응용 문제들을 상세하고 친절한 해설과 함께 총정리해 보았습니다. 상속, 생성자, static, 예외 처리, 제네릭까지 하나씩 꼼꼼히 복습해 보세요!&lt;/p&gt;

&lt;hr&gt;

&lt;h2&gt;1. 상속과 생성자 호출 (super와 this)&lt;/h2&gt;
&lt;p&gt;&lt;b&gt;문제:&lt;/b&gt; 다음 코드의 출력 결과를 작성하시오.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;
class A {
    private int a;

    public A(int a) {
        this.a = a;
    }

    public void display() {
        System.out.println(&quot;a=&quot; + a);
    }
}

class B extends A {
    public B(int a) {
        super(a);
        display(); 
    }
}

public class Good {
    public static void main(String[] args) {
        B obj = new B(10);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;details&gt;
  &lt;summary&gt;&lt;b&gt;  정답 및 해설 보기 (클릭하세요)&lt;/b&gt;&lt;/summary&gt;
  &lt;div style=&quot;background-color: #f8f9fa; padding: 15px; border-left: 4px solid #007bff; margin-top: 10px; border-radius: 4px;&quot;&gt;
    &lt;p&gt;&lt;b&gt;정답:&lt;/b&gt; &lt;code&gt;a=10&lt;/code&gt;&lt;/p&gt;
    &lt;p&gt;&lt;b&gt;친절한 해설:&lt;/b&gt;&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;b&gt;생성자 호출과 super(a):&lt;/b&gt; 자식 클래스인 &lt;code&gt;B&lt;/code&gt; 객체를 만들면서 숫자 &lt;code&gt;10&lt;/code&gt;을 전달하면, 자식 생성자 안의 &lt;code&gt;super(a);&lt;/code&gt;가 &lt;b&gt;&quot;제가 받은 숫자 10을 부모님 쪽으로 보냅니다!&quot;&lt;/b&gt; 하고 부모 클래스인 &lt;code&gt;A&lt;/code&gt;의 생성자에게 전달합니다.&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;변수 저장:&lt;/b&gt; 부모 클래스의 &lt;code&gt;public A(int a)&lt;/code&gt;가 이 숫자 10을 받아 &lt;code&gt;this.a = a;&lt;/code&gt;를 통해 부모 쪽 보관함에 10을 저장합니다.&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;출력:&lt;/b&gt; 그 후 부모의 &lt;code&gt;display()&lt;/code&gt; 메서드가 실행되어 저장되어 있던 &lt;code&gt;10&lt;/code&gt;을 가져와 &lt;code&gt;a=10&lt;/code&gt;을 출력하게 됩니다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/div&gt;
&lt;/details&gt;

&lt;hr&gt;

&lt;h2&gt;2. 메서드 오버로딩과 참조 변수 타입의 함정&lt;/h2&gt;
&lt;p&gt;&lt;b&gt;문제:&lt;/b&gt; 다음 코드의 출력 결과를 작성하시오.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;
abstract class Vehicle {
    private String name;
    abstract public String getName(String val);
    public String getName() {
        return &quot;vehicle name:&quot; + name;
    }
    public void setName(String val) {
        name = val;
    }
}

class Car extends Vehicle {
    public Car(String val) {
        setName(val);
    }
    public String getName(String val) {
        return &quot;Car name : &quot; + val;
    }
    public String getName(byte val[]) {
        return &quot;Car name : &quot; + val;
    }
}

public class Good {
    public static void main(String[] args) {
        Vehicle obj = new Car(&quot;Spark&quot;);
        System.out.print(obj.getName());
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;details&gt;
  &lt;summary&gt;&lt;b&gt;  정답 및 해설 보기 (클릭하세요)&lt;/b&gt;&lt;/summary&gt;
  &lt;div style=&quot;background-color: #f8f9fa; padding: 15px; border-left: 4px solid #007bff; margin-top: 10px; border-radius: 4px;&quot;&gt;
    &lt;p&gt;&lt;b&gt;정답:&lt;/b&gt; &lt;code&gt;vehicle name:Spark&lt;/code&gt;&lt;/p&gt;
    &lt;p&gt;&lt;b&gt;친절한 해설:&lt;/b&gt;&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;b&gt;오버라이딩 여부:&lt;/b&gt; 자식인 &lt;code&gt;Car&lt;/code&gt; 클래스에는 매개변수가 없는 &lt;code&gt;getName()&lt;/code&gt; 메서드가 존재하지 않습니다. 부모(Vehicle)에게 상속받은 그대로 두고 재정의(오버라이딩)하지 않았습니다.&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;그릇(참조 변수)의 타입:&lt;/b&gt; 객체를 &lt;code&gt;Car&lt;/code&gt;로 만들었지만 담아둔 그릇의 타입이 &lt;code&gt;Vehicle&lt;/code&gt;입니다. 자바 컴파일러는 그릇인 부모 클래스를 기준으로 메서드를 찾습니다.&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;최종 실행:&lt;/b&gt; 따라서 부모 클래스인 &lt;code&gt;Vehicle&lt;/code&gt;에 있는 매개변수 없는 &lt;code&gt;getName()&lt;/code&gt;이 호출되고, 생성자에서 저장된 &lt;code&gt;&quot;Spark&quot;&lt;/code&gt;를 가져와 &lt;code&gt;vehicle name:Spark&lt;/code&gt;가 출력됩니다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/div&gt;
&lt;/details&gt;

&lt;hr&gt;

&lt;h2&gt;3. static 메서드와 main 메서드의 규칙&lt;/h2&gt;
&lt;p&gt;&lt;b&gt;문제:&lt;/b&gt; 빈칸에 들어가야 할 올바른 키워드를 고르시오.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;
public class Test {
    public static void main(String[] args) {
        System.out.print(Test.check(1));
    }

   (____빈칸____) String check(int num) {
        return (num &gt;= 0) ? &quot;positive&quot; : &quot;negative&quot;;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;details&gt;
  &lt;summary&gt;&lt;b&gt;  정답 및 해설 보기 (클릭하세요)&lt;/b&gt;&lt;/summary&gt;
  &lt;div style=&quot;background-color: #f8f9fa; padding: 15px; border-left: 4px solid #007bff; margin-top: 10px; border-radius: 4px;&quot;&gt;
    &lt;p&gt;&lt;b&gt;정답:&lt;/b&gt; &lt;code&gt;public static&lt;/code&gt; (또는 &lt;code&gt;static&lt;/code&gt;)&lt;/p&gt;
    &lt;p&gt;&lt;b&gt;친절한 해설:&lt;/b&gt;&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;b&gt;대장 main의 규칙:&lt;/b&gt; 프로그램의 시작점인 &lt;code&gt;main&lt;/code&gt; 메서드는 &lt;b&gt;static&lt;/b&gt; 소속입니다. 즉, 메모리에 미리 올라와 있는 상태입니다.&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;static끼리의 호출:&lt;/b&gt; 자바 세상에서는 &lt;b&gt;static&lt;/b&gt; 공간(대장) 안에서 일반 메서드를 객체 생성 없이 곧바로 부를 수 없다는 엄격한 규칙이 있습니다.&lt;/li&gt;
      &lt;li&gt;따라서 &lt;code&gt;main&lt;/code&gt; 안에서 곧바로 &lt;code&gt;Test.check(1)&lt;/code&gt;을 호출하려면, 부름을 받는 &lt;code&gt;check&lt;/code&gt; 메서드 앞에도 반드시 &lt;b&gt;static&lt;/b&gt;이 함께 붙어 있어야 합니다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/div&gt;
&lt;/details&gt;

&lt;hr&gt;

&lt;h2&gt;4. 정적 변수(static)와 후위 연산자&lt;/h2&gt;
&lt;p&gt;&lt;b&gt;문제:&lt;/b&gt; 다음 코드의 출력 결과를 작성하시오.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;
class Static {
    public int a = 20;     
    static int b = 0;      
}

public class Main {
    public static void main(String[] args) {
        int a;
        a = 10;
        Static.b = a;           

        Static st = new Static();  

        System.out.println(Static.b++); 
        System.out.println(st.b);       
        System.out.println(a);         
        System.out.print(st.a);        
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;details&gt;
  &lt;summary&gt;&lt;b&gt;  정답 및 해설 보기 (클릭하세요)&lt;/b&gt;&lt;/summary&gt;
  &lt;div style=&quot;background-color: #f8f9fa; padding: 15px; border-left: 4px solid #007bff; margin-top: 10px; border-radius: 4px;&quot;&gt;
    &lt;p&gt;&lt;b&gt;정답:&lt;/b&gt;&lt;/p&gt;
    &lt;pre&gt;10
11
10
20&lt;/pre&gt;
    &lt;p&gt;&lt;b&gt;친절한 해설:&lt;/b&gt;&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;b&gt;Static.b++:&lt;/b&gt; 후위 연산자이므로 현재 값(&lt;b&gt;10&lt;/b&gt;)을 먼저 출력한 뒤에 &lt;code&gt;b&lt;/code&gt;가 1 증가하여 11이 됩니다.&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;st.b:&lt;/b&gt; &lt;b&gt;b&lt;/b&gt;는 모든 객체가 공유하는 &lt;b&gt;static&lt;/b&gt; 변수이므로 증가된 값인 &lt;b&gt;11&lt;/b&gt;이 출력됩니다.&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;a:&lt;/b&gt; &lt;b&gt;main&lt;/b&gt; 안의 지역 변수 &lt;b&gt;a&lt;/b&gt;는 처음에 대입된 &lt;b&gt;10&lt;/b&gt;이 그대로 유지됩니다.&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;st.a:&lt;/b&gt; 객체 내부의 일반 변수 &lt;b&gt;a&lt;/b&gt;는 처음 설계된 값인 &lt;b&gt;20&lt;/b&gt;이 출력됩니다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/div&gt;
&lt;/details&gt;

&lt;hr&gt;

&lt;h2&gt;5. 상속 관계에서의 생성자 체이닝과 변수 가려짐(Shadowing)&lt;/h2&gt;
&lt;p&gt;&lt;b&gt;문제:&lt;/b&gt; 다음 코드의 출력 결과를 작성하시오.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;
class Parent {
    int x = 100;

    Parent() {
        this(500);        
    }

    Parent(int x) {
        this.x = x;      
    }

    int getX() {
        return x;        
    }
}

class Child extends Parent {
    int x = 4000;

    Child() {
        this(5000);       
    }

    Child(int x) {
        this.x = x;      
    }
}

public class Main {
    public static void main(String[] args) {
        Child obj = new Child();
        System.out.println(obj.getX());  
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;details&gt;
  &lt;summary&gt;&lt;b&gt;  정답 및 해설 보기 (클릭하세요)&lt;/b&gt;&lt;/summary&gt;
  &lt;div style=&quot;background-color: #f8f9fa; padding: 15px; border-left: 4px solid #007bff; margin-top: 10px; border-radius: 4px;&quot;&gt;
    &lt;p&gt;&lt;b&gt;정답:&lt;/b&gt; &lt;code&gt;500&lt;/code&gt;&lt;/p&gt;
    &lt;p&gt;&lt;b&gt;친절한 해설:&lt;/b&gt;&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;b&gt;생성자 실행 순서:&lt;/b&gt; 자식을 만들 때 부모의 생성자 체이닝을 거쳐 부모의 &lt;code&gt;x&lt;/code&gt;는 &lt;code&gt;500&lt;/code&gt;으로 세팅되고, 자식의 &lt;code&gt;x&lt;/code&gt;는 &lt;code&gt;5000&lt;/code&gt;으로 세팅됩니다.&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;변수의 특징:&lt;/b&gt; 변수는 오버라이딩되지 않고 각자 자기 클래스의 변수를 바라봅니다.&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;getX()의 출처:&lt;/b&gt; &lt;code&gt;getX()&lt;/code&gt; 메서드는 &lt;b&gt;`Parent` 클래스&lt;/b&gt; 안에 정의되어 있으므로, 그 안에서 리턴하는 &lt;code&gt;x&lt;/code&gt;는 자식의 &lt;code&gt;5000&lt;/code&gt;이 아니라 &lt;b&gt;부모가 가진 `x`인 `500`&lt;/b&gt;이 됩니다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/div&gt;
&lt;/details&gt;

&lt;hr&gt;

&lt;h2&gt;6. String 풀(Pool)과 == vs .equals() 비교&lt;/h2&gt;
&lt;p&gt;&lt;b&gt;문제:&lt;/b&gt; 다음 코드의 출력 결과를 작성하시오.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;
public class Main {
    public static void main(String[] args) {

        String str1 = &quot;Programming&quot;;             
        String str2 = &quot;Programming&quot;;             
        String str3 = new String(&quot;Programming&quot;); 

        System.out.println(str1 == str2);         
        System.out.println(str1 == str3);         
        System.out.println(str1.equals(str3));    
        System.out.print(str2.equals(str3));      
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;details&gt;
  &lt;summary&gt;&lt;b&gt;  정답 및 해설 보기 (클릭하세요)&lt;/b&gt;&lt;/summary&gt;
  &lt;div style=&quot;background-color: #f8f9fa; padding: 15px; border-left: 4px solid #007bff; margin-top: 10px; border-radius: 4px;&quot;&gt;
    &lt;p&gt;&lt;b&gt;정답:&lt;/b&gt;&lt;/p&gt;
    &lt;pre&gt;true
false
true
true&lt;/pre&gt;
    &lt;p&gt;&lt;b&gt;친절한 해설:&lt;/b&gt;&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;b&gt;`str1 == str2` (true):&lt;/b&gt; 리터럴(쌍따옴표)로 만든 문자열은 문자열 풀(String Pool)을 공유하므로 메모리 주소가 같습니다.&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;`str1 == str3` (false):&lt;/b&gt; `new` 키워드로 만든 `str3`은 힙 영역에 새로 만들어진 별개의 주소를 가지므로 주소값이 다릅니다.&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;`.equals()` (true):&lt;/b&gt; 주소값이 달라도 글자 내용(&quot;Programming&quot;)이 같으면 무조건 `true`를 반환합니다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/div&gt;
&lt;/details&gt;

&lt;hr&gt;

&lt;h2&gt;7. 생성자 호출 순서 추적과 다형성 메서드&lt;/h2&gt;
&lt;p&gt;&lt;b&gt;문제:&lt;/b&gt; 다음 코드의 실행 순서와 출력 결과를 작성하시오.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;
class Parent {
    int x, y;

    Parent(int x, int y) {            
        this.x = x;
        this.y = y;
    }

    int getT() {                      
        return x * y;
    }
}

class Child extends Parent {         
    int x;

    Child(int x) {                    
        super(x + 1, x);              
        this.x = x;
    }

    int getT(int n) {                 
        return super.getT() + n;
    }
}

class Main {
    public static void main(String[] args) {  
        Parent parent = new Child(3);         
        System.out.println(parent.getT());    
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;details&gt;
  &lt;summary&gt;&lt;b&gt;  정답 및 해설 보기 (클릭하세요)&lt;/b&gt;&lt;/summary&gt;
  &lt;div style=&quot;background-color: #f8f9fa; padding: 15px; border-left: 4px solid #007bff; margin-top: 10px; border-radius: 4px;&quot;&gt;
    &lt;p&gt;&lt;b&gt;정답:&lt;/b&gt;&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;b&gt;실행 순서:&lt;/b&gt; ⑤ (main 시작) → ⑥ (객체 생성) → ③ (자식 생성자 진입) → ① (부모 생성자 완료) → ⑦ (출력문 진입) → ② (부모의 getT 실행)&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;출력 결과:&lt;/b&gt; &lt;code&gt;12&lt;/code&gt;&lt;/li&gt;
    &lt;/ul&gt;
    &lt;p&gt;&lt;b&gt;친절한 해설:&lt;/b&gt;&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;자식을 만들 때 부모의 생성자(`super(4, 3)`)가 먼저 불려 부모의 변수 `x=4, y=3`이 세팅됩니다.&lt;/li&gt;
      &lt;li&gt;그릇의 타입이 `Parent`이므로 `parent.getT()`를 호출하면 부모 클래스의 `getT()`가 실행됩니다.&lt;/li&gt;
      &lt;li&gt;부모의 연산 공식인 `x * y`에 따라 `4 * 3 = 12`가 출력됩니다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/div&gt;
&lt;/details&gt;

&lt;hr&gt;

&lt;h2&gt;8. 인터페이스 구현과 조건문 활용&lt;/h2&gt;
&lt;p&gt;&lt;b&gt;문제:&lt;/b&gt; 다음 코드의 출력 결과를 작성하시오.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;
interface Number {
    int sum(int[] a, boolean odd); 
}

class ODDNumber implements Number {
    public int sum(int[] a, boolean odd) {
        int result = 0;
        for (int i = 0; i &amp;lt; a.length; i++) {
            if ((odd &amp;&amp; a[i] % 2 != 0) || (!odd &amp;&amp; a[i] % 2 == 0)) {
                result += a[i];
            }
        }
        return result;
    }
}

public class Main {
    public static void main(String[] args) {
        int a[] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
        ODDNumber OE = new ODDNumber();

        System.out.print(OE.sum(a, true) + &quot;, &quot; + OE.sum(a, false));
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;details&gt;
  &lt;summary&gt;&lt;b&gt;  정답 및 해설 보기 (클릭하세요)&lt;/b&gt;&lt;/summary&gt;
  &lt;div style=&quot;background-color: #f8f9fa; padding: 15px; border-left: 4px solid #007bff; margin-top: 10px; border-radius: 4px;&quot;&gt;
    &lt;p&gt;&lt;b&gt;정답:&lt;/b&gt; &lt;code&gt;25, 20&lt;/code&gt;&lt;/p&gt;
    &lt;p&gt;&lt;b&gt;친절한 해설:&lt;/b&gt;&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;b&gt;`odd = true` (홀수의 합):&lt;/b&gt; 배열에서 홀수들(1, 3, 5, 7, 9)만 골라 더하므로 &lt;b&gt;25&lt;/b&gt;가 됩니다.&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;`odd = false` (짝수의 합):&lt;/b&gt; 배열에서 짝수들(2, 4, 6, 8)만 골라 더하므로 &lt;b&gt;20&lt;/b&gt;이 됩니다.&lt;/li&gt;
      &lt;li&gt;가운데 &lt;code&gt;&quot;, &quot;&lt;/code&gt;를 끼워 넣어 &lt;code&gt;25, 20&lt;/code&gt;이 출력됩니다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/div&gt;
&lt;/details&gt;

&lt;hr&gt;

&lt;h2&gt;9. 상속 관계에서 메서드(동적 바인딩) vs 변수(정적 바인딩)&lt;/h2&gt;
&lt;p&gt;&lt;b&gt;문제:&lt;/b&gt; 다음 코드의 출력 결과를 작성하시오.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;
public class Main {
    public static void main(String[] args) {
        Base a = new Derivate();  
        Derivate b = new Derivate();

        System.out.print(a.getX() + a.x + b.getX() + b.x);
    }
}

class Base {
    int x = 3;

    int getX() {
        return x * 2;
    }
}

class Derivate extends Base {
    int x = 7;

    int getX() {
        return x * 3;
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;details&gt;
  &lt;summary&gt;&lt;b&gt;  정답 및 해설 보기 (클릭하세요)&lt;/b&gt;&lt;/summary&gt;
  &lt;div style=&quot;background-color: #f8f9fa; padding: 15px; border-left: 4px solid #007bff; margin-top: 10px; border-radius: 4px;&quot;&gt;
    &lt;p&gt;&lt;b&gt;정답:&lt;/b&gt; &lt;code&gt;52&lt;/code&gt;&lt;/p&gt;
    &lt;p&gt;&lt;b&gt;친절한 해설:&lt;/b&gt;&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;b&gt;메서드(`getX()`):&lt;/b&gt; 실제 객체(`new Derivate()`)를 따라가므로 자식의 메서드(`7 * 3 = 21`)가 실행됩니다.&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;변수(`x`):&lt;/b&gt; 변수는 그릇의 타입(선언부)을 따라갑니다. `a`는 `Base` 타입이라 `3`, `b`는 `Derivate` 타입이라 `7`을 가져옵니다.&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;값 계산:&lt;/b&gt; a파트(21 + 3 = 24) + b파트(21 + 7 = 28) = &lt;b&gt;52&lt;/b&gt;가 완성됩니다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/div&gt;
&lt;/details&gt;

&lt;hr&gt;

&lt;h2&gt;10. 제네릭 타입 소거와 오버로딩 규칙&lt;/h2&gt;
&lt;p&gt;&lt;b&gt;문제:&lt;/b&gt; 다음 코드의 출력 결과를 작성하시오.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;
class Main {

    public static class Collection&amp;lt;T&amp;gt; {
        T value;

        public Collection(T t) {
            value = t;
        }

        public void print() {
            new Printer().print(value);
        }

        class Printer {
            void print(Integer a) {
                System.out.print(&quot;A&quot; + a);
            }

            void print(Object a) {
                System.out.print(&quot;B&quot; + a);
            }

            void print(Number a) {
                System.out.print(&quot;C&quot; + a);
            }
        }
    }

    public static void main(String[] args) {
        new Collection&amp;lt;&amp;gt;(0).print();
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;details&gt;
  &lt;summary&gt;&lt;b&gt;  정답 및 해설 보기 (클릭하세요)&lt;/b&gt;&lt;/summary&gt;
  &lt;div style=&quot;background-color: #f8f9fa; padding: 15px; border-left: 4px solid #007bff; margin-top: 10px; border-radius: 4px;&quot;&gt;
    &lt;p&gt;&lt;b&gt;정답:&lt;/b&gt; &lt;code&gt;B0&lt;/code&gt;&lt;/p&gt;
    &lt;p&gt;&lt;b&gt;친절한 해설:&lt;/b&gt;&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;b&gt;제네릭 타입 소거:&lt;/b&gt; 제네릭 클래스를 컴파일할 때 범용 타입 `T`는 최상위 클래스인 &lt;b&gt;`Object`&lt;/b&gt;로 치환됩니다.&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;컴파일 타임 메서드 선택:&lt;/b&gt; 오버로딩된 메서드 호출은 컴파일 시점의 변수 타입(`Object`)을 기준으로 결정됩니다.&lt;/li&gt;
      &lt;li&gt;따라서 런타임에 `Integer(0)`이 들어오더라도 컴파일 시점에 낙점된 `print(Object a)`가 실행되어 `B0`가 출력됩니다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/div&gt;
&lt;/details&gt;

&lt;hr&gt;

&lt;h2&gt;11. 예외 처리(try-catch-finally)와 예외 클래스 계층&lt;/h2&gt;
&lt;p&gt;&lt;b&gt;문제:&lt;/b&gt; 다음 코드의 출력 결과를 작성하시오.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;
public class Main {
  public static void main(String[] args) {

    int a = 5, b = 0;

    try {
      System.out.print(a / b);
    } catch (ArithmeticException e) {
      System.out.print(&quot;출력1&quot;);
    } catch (ArrayIndexOutOfBoundsException e) {
      System.out.print(&quot;출력2&quot;);
    } catch (NumberFormatException e) {
      System.out.print(&quot;출력3&quot;);
    } catch (Exception e) {
      System.out.print(&quot;출력4&quot;);
    } finally {
      System.out.print(&quot;출력5&quot;);
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;details&gt;
  &lt;summary&gt;&lt;b&gt;  정답 및 해설 보기 (클릭하세요)&lt;/b&gt;&lt;/summary&gt;
  &lt;div style=&quot;background-color: #f8f9fa; padding: 15px; border-left: 4px solid #007bff; margin-top: 10px; border-radius: 4px;&quot;&gt;
    &lt;p&gt;&lt;b&gt;정답:&lt;/b&gt; &lt;code&gt;출력1출력5&lt;/code&gt;&lt;/p&gt;
    &lt;p&gt;&lt;b&gt;친절한 해설:&lt;/b&gt;&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;b&gt;ArithmeticException:&lt;/b&gt; 5를 0으로 나누려고 할 때 수학적 연산 불능으로 발생하는 예외입니다.&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;catch 매칭:&lt;/b&gt; 에러가 나면 위에서부터 일치하는 catch 문을 찾는데, `ArithmeticException`과 일치하므로 `출력1`이 수행됩니다.&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;finally:&lt;/b&gt; 에러 발생 여부와 상관없이 무조건 마지막에 실행되므로 `출력5`가 이어져 출력됩니다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/div&gt;
&lt;/details&gt;

&lt;hr&gt;

&lt;h2&gt;12. 람다식, 함수형 인터페이스, 예외 처리 결합&lt;/h2&gt;
&lt;p&gt;&lt;b&gt;문제:&lt;/b&gt; 다음 코드의 출력 결과를 작성하시오.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-java&quot;&gt;
public class Main {

    static interface F {
        int apply(int x) throws Exception;
    }

    public static int run(F f) {
        try {
            return f.apply(3);
        } catch (Exception e) {
            return 7;
        }
    }

    public static void main(String[] args) {

        F f = (x) -&gt; {
            if (x &gt; 2) {
                throw new Exception();
            }
            return x * 2;
        };

        System.out.print(run(f) + run((int n) -&gt; n + 9));
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;details&gt;
  &lt;summary&gt;&lt;b&gt;  정답 및 해설 보기 (클릭하세요)&lt;/b&gt;&lt;/summary&gt;
  &lt;div style=&quot;background-color: #f8f9fa; padding: 15px; border-left: 4px solid #007bff; margin-top: 10px; border-radius: 4px;&quot;&gt;
    &lt;p&gt;&lt;b&gt;정답:&lt;/b&gt; &lt;code&gt;19&lt;/code&gt;&lt;/p&gt;
    &lt;p&gt;&lt;b&gt;친절한 해설:&lt;/b&gt;&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;b&gt;첫 번째 `run(f)`:&lt;/b&gt; 인자로 3을 넘기면 `x &gt; 2` 조건에 걸려 `throw new Exception();`이 터지고, `run` 내부의 catch에 의해 &lt;b&gt;7&lt;/b&gt;을 리턴합니다.&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;두 번째 `run(...)`:&lt;/b&gt; 인자로 3을 넘기면 `3 + 9 = 12`가 되어 에러 없이 정상적으로 &lt;b&gt;12&lt;/b&gt;를 리턴합니다.&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;최종 합산:&lt;/b&gt; `7 + 12 = 19`가 출력됩니다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/div&gt;
&lt;/details&gt;</description>
      <category>Certificate(자격증)/정보처리기사(실기)</category>
      <category>객체지향프로그래밍</category>
      <category>자격증독학</category>
      <category>자바기출</category>
      <category>자바예외처리</category>
      <category>정보처리기사실기</category>
      <category>정처기실기</category>
      <author>jsummer07</author>
      <guid isPermaLink="true">https://jsummer07.tistory.com/49</guid>
      <comments>https://jsummer07.tistory.com/49#entry49comment</comments>
      <pubDate>Thu, 22 Oct 2026 20:18:02 +0900</pubDate>
    </item>
    <item>
      <title>[Python] 파이썬 기초 11: 조건이 참인 동안 실행되는 `while` 반복문과 무한루프 탈출하기  ✨</title>
      <link>https://jsummer07.tistory.com/37</link>
      <description>&lt;p&gt;안녕하세요! 스마트인재개발원 파이썬 공부 기록입니다.&lt;br&gt;그동안 조건에 따라 한 번씩만 분기를 나누어 보았다면, 이번 시간부터는 특정 조건이 만족될 때까지 코드를 반복해서 실행해 주는 &amp;#39;반복문(Loop)&amp;#39;의 세계로 들어갑니다!  &lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;1. &lt;code&gt;while&lt;/code&gt; 반복문의 기본 구조&lt;/h2&gt;
&lt;p&gt;&lt;code&gt;while&lt;/code&gt; 문은 &amp;quot;이 조건이 참(True)인 동안에는 아래 코드를 계속 반복해서 실행해 줘!&amp;quot;라고 지시할 때 사용하는 구문입니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;작성 규칙:&lt;/strong&gt;&lt;ul&gt;
&lt;li&gt;&lt;code&gt;while 조건식:&lt;/code&gt; 형태로 선언하며, 뒤에 콜론(&lt;code&gt;:&lt;/code&gt;)을 붙입니다.&lt;/li&gt;
&lt;li&gt;조건식이 계속 &lt;code&gt;True&lt;/code&gt;이면 코드가 영원히 끝나지 않는 무한루프(Infinite Loop)에 빠질 수 있으므로, 반복을 끝낼 수 있는 탈출 조건(변화하는 값)이 반드시 필요합니다!&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;  &lt;code&gt;while&lt;/code&gt; 문 실습 코드 (13번 반복하기)&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;# while문을 활용해서 &amp;#39;파이썬 최고&amp;#39;를 13번 출력해보자

num = 1
while num &amp;lt;= 13:
    print(num, &amp;#39;파이썬 최고&amp;#39;)
    num += 1  # num을 1씩 증가시켜서 13이 넘으면 멈추도록 조건식을 관리합니다!
&lt;/code&gt;&lt;/pre&gt;
&lt;hr&gt;
&lt;h2&gt;2. 무한루프(&lt;code&gt;while True&lt;/code&gt;)와 탈출기(&lt;code&gt;break&lt;/code&gt;)&lt;/h2&gt;
&lt;p&gt;실무나 코딩 테스트를 하다 보면 조건식을 미리 정해두기보다, &amp;quot;일단 무한대로 돌리다가 특정 상황이 오면 멈춰라!&amp;quot;라는 로직이 훨씬 편할 때가 많습니다. 이때 &lt;code&gt;while True&lt;/code&gt;와 &lt;code&gt;break&lt;/code&gt;를 조합합니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;while True&lt;/code&gt;:&lt;/strong&gt; 조건식이 항상 참이므로 무한히 반복됩니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;break&lt;/code&gt;:&lt;/strong&gt; 반복문 안에서 특정 조건(&lt;code&gt;if&lt;/code&gt;)을 만족했을 때 반복문을 강제로 부수고(탈출하고) 빠져나오게 만듭니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;  &lt;code&gt;while True&lt;/code&gt; &amp;amp; &lt;code&gt;break&lt;/code&gt; 실습 코드&lt;/h3&gt;
&lt;pre&gt;&lt;code class=&quot;language-python&quot;&gt;num = 1
while True:
    print(num, &amp;#39;파이썬 최고&amp;#39;)
    num += 1

    # num이 13을 초과하면 반복문 탈출!
    if num &amp;gt; 13:
        break
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; width=&quot;100%&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/bJZCAm/dJMcafV4AQ0/4uVtNC9iKxrSviTANwdTIk/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/bJZCAm/dJMcafV4AQ0/4uVtNC9iKxrSviTANwdTIk/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/bJZCAm/dJMcafV4AQ0/4uVtNC9iKxrSviTANwdTIk/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FbJZCAm%2FdJMcafV4AQ0%2F4uVtNC9iKxrSviTANwdTIk%2Fimg.png&quot; width=&quot;100%&quot; onerror=&quot;this.onerror=null; this.src='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png'; this.srcset='//t1.daumcdn.net/tistory_admin/static/images/no-image-v1.png';&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
 &lt;/p&gt;
&lt;hr&gt;
&lt;h2&gt;  오늘 공부를 마치며&lt;/h2&gt;
&lt;p&gt;반복문을 배우니 이제 컴퓨터에게 단순하고 지루한 작업을 시키는 게 훨씬 수월해졌죠?&lt;br&gt;다음 포스팅에서는 파이썬에서 가장 많이 쓰이는 또 다른 반복문인 &lt;strong&gt;&lt;code&gt;for&lt;/code&gt; 문과 &lt;code&gt;range()&lt;/code&gt; 함수의 활용법&lt;/strong&gt;으로 이어가겠습니다. 다음 빌드 일지에서 만나요!  ✨&lt;/p&gt;
&lt;hr&gt;</description>
      <category>Development(개발 공부)/Python &amp;amp; AI</category>
      <category>Break</category>
      <category>python</category>
      <category>While문</category>
      <category>개발자일지</category>
      <category>무한루프</category>
      <category>스마트인재개발원</category>
      <category>어썸썸머</category>
      <category>코딩기초</category>
      <category>파이썬</category>
      <category>파이썬반복문</category>
      <author>jsummer07</author>
      <guid isPermaLink="true">https://jsummer07.tistory.com/37</guid>
      <comments>https://jsummer07.tistory.com/37#entry37comment</comments>
      <pubDate>Thu, 22 Oct 2026 19:19:12 +0900</pubDate>
    </item>
    <item>
      <title>정보처리기사 실기 대비: 꼭 알아야 할 C언어 핵심 기출문제 모음</title>
      <link>https://jsummer07.tistory.com/48</link>
      <description>&lt;p&gt;안녕하세요! 정보처리기사 실기 시험을 준비하며 함께 풀었던 C언어 핵심 기출 및 응용 문제들을 아주 상세하고 친절한 해설과 함께 총정리해 보았습니다. 포인터, 구조체, 함수, switch문 함정까지 하나씩 꼼꼼히 복습해 보세요!&lt;/p&gt;

&lt;hr&gt;

&lt;h2&gt;1. 자릿수 뒤집기 (반복문과 연산자)&lt;/h2&gt;
&lt;p&gt;&lt;b&gt;문제:&lt;/b&gt; 정수 1234의 각 자릿수를 뒤집어 4321을 만드는 코드입니다. 빈칸을 채우시오.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;
int main() {
  int number = 1234;
  int div = 10;
  int result = 0;
 
  while (number ( 1 ) 0) {
    result = result * div;
    result = result + number ( 2 ) div;
    number = number ( 3 ) div;
  }
  
  printf(&quot;%d&quot;, result);
  return 0;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;details&gt;
  &lt;summary&gt;&lt;b&gt;  정답 및 해설 보기 (클릭하세요)&lt;/b&gt;&lt;/summary&gt;
  &lt;div style=&quot;background-color: #f8f9fa; padding: 15px; border-left: 4px solid #007bff; margin-top: 10px; border-radius: 4px;&quot;&gt;
    &lt;p&gt;&lt;b&gt;정답:&lt;/b&gt;&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;(1): &lt;code&gt;&amp;gt;&lt;/code&gt; (또는 &lt;code&gt;!=&lt;/code&gt;)&lt;/li&gt;
      &lt;li&gt;(2): &lt;code&gt;%&lt;/code&gt; (나머지 연산)&lt;/li&gt;
      &lt;li&gt;(3): &lt;code&gt;/&lt;/code&gt; (나눗셈 몫 연산)&lt;/li&gt;
    &lt;/ul&gt;
    &lt;p&gt;&lt;b&gt;친절한 해설:&lt;/b&gt;&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;b&gt;(1)번 칸:&lt;/b&gt; 숫자가 0이 될 때까지 반복해야 하므로 &lt;code&gt;number &amp;gt; 0&lt;/code&gt;이 들어갑니다.&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;(2)번 칸 (`%`):&lt;/b&gt; &lt;code&gt;1234 % 10&lt;/code&gt;을 하면 맨 뒷자리인 &lt;b&gt;4&lt;/b&gt;가 톡 튀어나옵니다. 이 나머지 연산자(%)는 자릿수를 떼어낼 때 필수입니다!&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;(3)번 칸 (`/`):&lt;/b&gt; &lt;code&gt;1234 / 10&lt;/code&gt;을 하면 정수 나눗셈이라 맨 뒷자리가 떨어져 나가고 &lt;b&gt;123&lt;/b&gt;만 남게 됩니다. 이 과정을 반복하면 숫자가 거꾸로 뒤집히게 됩니다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/div&gt;
&lt;/details&gt;

&lt;hr&gt;

&lt;h2&gt;2. 재귀 함수 (Factorial)&lt;/h2&gt;
&lt;p&gt;&lt;b&gt;문제:&lt;/b&gt; 숫자 &lt;code&gt;5&lt;/code&gt;를 입력했을 때의 실행 결과를 작성하시오.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;
int func(int a) {
    if (a &amp;lt;= 1) return 1;
    return a * func(a - 1);
}
 
int main() {
    int a;
    scanf(&quot;%d&quot;, &amp;amp;a); // 5 입력
    printf(&quot;%d&quot;, func(a));
}
&lt;/code&gt;&lt;/pre&gt;

&lt;details&gt;
  &lt;summary&gt;&lt;b&gt;  정답 및 해설 보기 (클릭하세요)&lt;/b&gt;&lt;/summary&gt;
  &lt;div style=&quot;background-color: #f8f9fa; padding: 15px; border-left: 4px solid #007bff; margin-top: 10px; border-radius: 4px;&quot;&gt;
    &lt;p&gt;&lt;b&gt;정답:&lt;/b&gt; &lt;code&gt;120&lt;/code&gt;&lt;/p&gt;
    &lt;p&gt;&lt;b&gt;친절한 해설:&lt;/b&gt;&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;이 코드는 자기 자신을 다시 부르는 **재귀 함수**를 이용해 팩토리얼(곱셈 누적)을 구하는 문제입니다.&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;func(5)&lt;/code&gt;가 실행되면 &lt;code&gt;5 * func(4)&lt;/code&gt;가 되고, 이어서 &lt;code&gt;4 * func(3)&lt;/code&gt;... 이렇게 계속 들어가다가 1이 되면 멈추고 거꾸로 값을 곱해나갑니다.&lt;/li&gt;
      &lt;li&gt;즉, &lt;code&gt;5 * 4 * 3 * 2 * 1 = 120&lt;/code&gt;이 되어 최종적으로 120이 출력됩니다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/div&gt;
&lt;/details&gt;

&lt;hr&gt;

&lt;h2&gt;3. 배열 산술 연산과 누적 합&lt;/h2&gt;
&lt;p&gt;&lt;b&gt;문제:&lt;/b&gt; 다음 코드의 실행 결과를 작성하시오.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;
int main(int argc, char *argv[]) { 
	int a[4] = {0, 2, 4, 8}; 
	int b[3] = {}; 
	int i = 1; 
	int sum = 0;
	int *p1; 

	for (i; i &amp;lt; 4; i++) {
    	p1 = a + i; 
        b[i-1] = *p1 - a[i-1];
        sum = sum + b[i-1] + a[i]; 
     } 

	printf(&quot;%d&quot;, sum); 
	return 0; 
}
&lt;/code&gt;&lt;/pre&gt;

&lt;details&gt;
  &lt;summary&gt;&lt;b&gt;  정답 및 해설 보기 (클릭하세요)&lt;/b&gt;&lt;/summary&gt;
  &lt;div style=&quot;background-color: #f8f9fa; padding: 15px; border-left: 4px solid #007bff; margin-top: 10px; border-radius: 4px;&quot;&gt;
    &lt;p&gt;&lt;b&gt;정답:&lt;/b&gt; &lt;code&gt;22&lt;/code&gt;&lt;/p&gt;
    &lt;p&gt;&lt;b&gt;친절한 해설:&lt;/b&gt;&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;상자 모음 &lt;code&gt;a&lt;/code&gt;에는 &lt;code&gt;{0, 2, 4, 8}&lt;/code&gt;이 들어있고, 마법 지팡이(포인터) &lt;code&gt;p1&lt;/code&gt;이 상자 위치를 옮겨가며 계산합니다.&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;i = 1 일 때:&lt;/b&gt; &lt;code&gt;b[0]&lt;/code&gt;은 &lt;code&gt;a[1] - a[0] (2 - 0 = 2)&lt;/code&gt;가 되고, &lt;code&gt;sum&lt;/code&gt;에 &lt;code&gt;b[0]&lt;/code&gt;과 &lt;code&gt;a[1]&lt;/code&gt;이 더해져 4가 됩니다.&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;i = 2 일 때:&lt;/b&gt; &lt;code&gt;b[1]&lt;/code&gt;은 &lt;code&gt;4 - 2 = 2&lt;/code&gt;, &lt;code&gt;sum&lt;/code&gt;에 누적되어 10이 됩니다.&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;i = 3 일 때:&lt;/b&gt; &lt;code&gt;b[2]&lt;/code&gt;는 &lt;code&gt;8 - 4 = 4&lt;/code&gt;, &lt;code&gt;sum&lt;/code&gt;에 누적되어 최종적으로 &lt;b&gt;22&lt;/b&gt;가 완성됩니다!&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/div&gt;
&lt;/details&gt;

&lt;hr&gt;

&lt;h2&gt;4. 문자열 길이 구하기 함수&lt;/h2&gt;
&lt;p&gt;&lt;b&gt;문제:&lt;/b&gt; 다음 코드의 출력 결과를 작성하시오.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;
int len(char* p);

int main() { 
    char* p1 = &quot;2022&quot;; 
    char* p2 = &quot;202207&quot;;    
    
    int a = len(p1); 
    int b = len(p2); 

    printf(&quot;%d&quot;, a + b); 
    return 0;
} 

int len(char* p) { 
    int r = 0;      
    while (*p != '\0') { 
        p++; 
        r++;
    }
    return r;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;details&gt;
  &lt;summary&gt;&lt;b&gt;  정답 및 해설 보기 (클릭하세요)&lt;/b&gt;&lt;/summary&gt;
  &lt;div style=&quot;background-color: #f8f9fa; padding: 15px; border-left: 4px solid #007bff; margin-top: 10px; border-radius: 4px;&quot;&gt;
    &lt;p&gt;&lt;b&gt;정답:&lt;/b&gt; &lt;code&gt;10&lt;/code&gt;&lt;/p&gt;
    &lt;p&gt;&lt;b&gt;친절한 해설:&lt;/b&gt;&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;컴퓨터는 글자 모음(문자열)의 끝에 눈에 보이지 않는 끝맺음 표시(&lt;code&gt;\0&lt;/code&gt;, 널 문자)를 숨겨둡니다.&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;len&lt;/code&gt; 함수는 이 끝맺음 표시를 만날 때까지 한 칸씩 옆으로 이동(&lt;code&gt;p++&lt;/code&gt;)하며 센 횟수(&lt;code&gt;r++&lt;/code&gt;)를 반환합니다.&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;&quot;2022&quot;&lt;/code&gt;는 글자가 4개이므로 &lt;code&gt;a = 4&lt;/code&gt;, &lt;code&gt;&quot;202207&quot;&lt;/code&gt;은 글자가 6개이므로 &lt;code&gt;b = 6&lt;/code&gt;이 되어 &lt;code&gt;4 + 6 = 10&lt;/code&gt;이 출력됩니다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/div&gt;
&lt;/details&gt;

&lt;hr&gt;

&lt;h2&gt;5. 전역 변수와 버퍼 덮어쓰기 함정&lt;/h2&gt;
&lt;p&gt;&lt;b&gt;문제:&lt;/b&gt; 조건(입력 순서: 홍길동 → 김철수 → 박영희)에 따른 출력 결과를 작성하시오.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;
char n[30];

char *test() {
    printf(&quot;입력하세요 : &quot;);
    fgets(n, sizeof(n), stdin);
    n[strcspn(n, &quot;\n&quot;)] = '\0';
    return n;
}

int main() {
    char *test1 = test(); 
    char *test2 = test(); 
    char *test3 = test(); 

    printf(&quot;%s\n&quot;, test1);
    printf(&quot;%s\n&quot;, test2);
    printf(&quot;%s&quot;, test3);
    return 0;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;details&gt;
  &lt;summary&gt;&lt;b&gt;  정답 및 해설 보기 (클릭하세요)&lt;/b&gt;&lt;/summary&gt;
  &lt;div style=&quot;background-color: #f8f9fa; padding: 15px; border-left: 4px solid #007bff; margin-top: 10px; border-radius: 4px;&quot;&gt;
    &lt;p&gt;&lt;b&gt;정답:&lt;/b&gt;&lt;/p&gt;
    &lt;pre&gt;박영희
박영희
박영희&lt;/pre&gt;
    &lt;p&gt;&lt;b&gt;친절한 해설:&lt;/b&gt;&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;코드 맨 위에 선언된 &lt;code&gt;char n[30];&lt;/code&gt;은 프로그램 전체가 함께 쓰는 &lt;b&gt;&lt;code&gt;단 하나의 큰 공용 보관함&lt;/code&gt;&lt;/b&gt;입니다.&lt;/li&gt;
      &lt;li&gt;첫 번째에 '홍길동'을 넣으면 보관함에 홍길동이 들어가고, 두 번째에 '김철수'를 넣으면 기존의 홍길동이 지워지고 &lt;b&gt;&lt;code&gt;김철수로 덮어씌워집니다.&lt;/code&gt;&lt;/b&gt;&lt;/li&gt;
      &lt;li&gt;세 번째에 '박영희'를 넣으면 또 덮어씌워져서 보관함에는 최종적으로 '박영희'만 남게 됩니다. 변수 이름은 달라도 전부 똑같은 공용 보관함을 가리키고 있기 때문에 3번 모두 박영희가 출력됩니다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/div&gt;
&lt;/details&gt;

&lt;hr&gt;

&lt;h2&gt;6. switch문의 Fall-through (흘러내리기) 함정&lt;/h2&gt;
&lt;p&gt;&lt;b&gt;문제:&lt;/b&gt; 다음 코드의 출력 결과를 작성하시오.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;
void main(){
    int n[3] = {73, 95, 82};
    int sum = 0;
 
    for(int i=0;i&amp;lt;3;i++){
        sum += n[i];
    }
 
    switch(sum/30){
        case 10:
        case 9: printf(&quot;A&quot;);
        case 8: printf(&quot;B&quot;);
        case 7:
        case 6: printf(&quot;C&quot;);
        default: printf(&quot;D&quot;);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;details&gt;
  &lt;summary&gt;&lt;b&gt;  정답 및 해설 보기 (클릭하세요)&lt;/b&gt;&lt;/summary&gt;
  &lt;div style=&quot;background-color: #f8f9fa; padding: 15px; border-left: 4px solid #007bff; margin-top: 10px; border-radius: 4px;&quot;&gt;
    &lt;p&gt;&lt;b&gt;정답:&lt;/b&gt; &lt;code&gt;BCD&lt;/code&gt;&lt;/p&gt;
    &lt;p&gt;&lt;b&gt;친절한 해설:&lt;/b&gt;&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;세 수의 합은 250이고, &lt;code&gt;250 / 30 = 8&lt;/code&gt;이므로 정수 나눗셈에 의해 &lt;b&gt;&lt;code&gt;case 8&lt;/code&gt;&lt;/b&gt;로 진입합니다.&lt;/li&gt;
      &lt;li&gt;C언어의 switch문은 &lt;code&gt;break&lt;/code&gt;를 만나기 전까지 아래로 사정없이 미끄러져 내려가는 성질(Fall-through)이 있습니다.&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;case 8&lt;/code&gt;의 &lt;code&gt;printf(&quot;B&quot;)&lt;/code&gt;에서 &lt;b&gt;`B`&lt;/b&gt;가 출력되고, 멈추지 않고 계속 미끄러져 내려가 &lt;code&gt;case 6&lt;/code&gt;의 &lt;b&gt;`C`&lt;/b&gt;, &lt;code&gt;default&lt;/code&gt;의 &lt;b&gt;`D`&lt;/b&gt;까지 연달아 실행되어 최종적으로 &lt;b&gt;`BCD`&lt;/b&gt;가 출력됩니다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/div&gt;
&lt;/details&gt;

&lt;hr&gt;

&lt;h2&gt;7. 구조체와 화살표 연산자 (&lt;code&gt;-&amp;gt;&lt;/code&gt;)&lt;/h2&gt;
&lt;p&gt;&lt;b&gt;문제:&lt;/b&gt; 빈칸에 들어갈 알맞은 연산자를 고르시오.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;
typedef struct Data {
    char c;
    int *numPtr;
} Data;

int main() {
    int num = 10;
    Data d1;
    Data *d2 = malloc(sizeof(Data)); 

    d1.numPtr = &amp;amp;num;
    d2 ( 빈칸 ) numPtr = &amp;amp;num; 

    free(d2);
    return 0;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;details&gt;
  &lt;summary&gt;&lt;b&gt;  정답 및 해설 보기 (클릭하세요)&lt;/b&gt;&lt;/summary&gt;
  &lt;div style=&quot;background-color: #f8f9fa; padding: 15px; border-left: 4px solid #007bff; margin-top: 10px; border-radius: 4px;&quot;&gt;
    &lt;p&gt;&lt;b&gt;정답:&lt;/b&gt; &lt;code&gt;-&amp;gt;&lt;/code&gt;&lt;/p&gt;
    &lt;p&gt;&lt;b&gt;친절한 해설:&lt;/b&gt;&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;일반 구조체 변수(&lt;code&gt;d1&lt;/code&gt;)는 점(&lt;code&gt;.&lt;/code&gt;)을 찍어서 내부 칸에 접근합니다.&lt;/li&gt;
      &lt;li&gt;하지만 구조체 주소를 가리키는 포인터 변수(&lt;code&gt;d2&lt;/code&gt;)를 사용할 때는 주소를 찾아간다는 의미로 점 대신 &lt;b&gt;&lt;code&gt;화살표 연산자(&lt;code&gt;-&amp;gt;&lt;/code&gt;)&lt;/code&gt;&lt;/b&gt;를 사용해야 합니다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/div&gt;
&lt;/details&gt;

&lt;hr&gt;

&lt;h2&gt;8. 삼항 연산자와 비트 시프트 연산 (&lt;code&gt;&amp;lt;&amp;lt;&lt;/code&gt;)&lt;/h2&gt;
&lt;p&gt;&lt;b&gt;문제:&lt;/b&gt; 다음 코드의 출력 결과를 작성하시오.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;
int main() {
    int v1 = 0, v2 = 35, v3 = 29;
    
    if(v1 &amp;gt; v2 ? v2 : v1) {
        v2 = v2 &amp;lt;&amp;lt; 2;
    } else {
        v3 = v3 &amp;lt;&amp;lt; 2;
    }
    
    printf(&quot;%d&quot;, v2+v3);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;details&gt;
  &lt;summary&gt;&lt;b&gt;  정답 및 해설 보기 (클릭하세요)&lt;/b&gt;&lt;/summary&gt;
  &lt;div style=&quot;background-color: #f8f9fa; padding: 15px; border-left: 4px solid #007bff; margin-top: 10px; border-radius: 4px;&quot;&gt;
    &lt;p&gt;&lt;b&gt;정답:&lt;/b&gt; &lt;code&gt;151&lt;/code&gt;&lt;/p&gt;
    &lt;p&gt;&lt;b&gt;친절한 해설:&lt;/b&gt;&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;b&gt;삼항 연산자 (`? :`):&lt;/b&gt; &lt;code&gt;v1 &amp;gt; v2 ? v2 : v1&lt;/code&gt;은 &quot;v1이 v2보다 크면 v2를, 아니면 v1을 써라&quot;는 뜻입니다. &lt;code&gt;0 &amp;gt; 35&lt;/code&gt;는 거짓이므로 뒤에 있는 &lt;code&gt;v1&lt;/code&gt;의 값인 &lt;b&gt;0&lt;/b&gt;이 선택됩니다.&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;if 조건문의 판정:&lt;/b&gt; 괄호 안의 결과가 &lt;b&gt;0&lt;/b&gt;이 되었으므로 C언어 규칙에 따라 &lt;b&gt;거짓(False)&lt;/b&gt;으로 판정되어 &lt;code&gt;else&lt;/code&gt; 블록으로 들어갑니다.&lt;/li&gt;
      &lt;li&gt;&lt;b&gt;비트 시프트 (`&amp;lt;&amp;lt; 2`):&lt;/b&gt; &lt;code&gt;v3 &amp;lt;&amp;lt; 2&lt;/code&gt;는 값을 왼쪽으로 두 칸 밀어 4를 곱하는 것과 같습니다. (29 × 4 = 116)&lt;/li&gt;
      &lt;li&gt;따라서 &lt;code&gt;v2(35) + v3(116) = 151&lt;/code&gt;이 출력됩니다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/div&gt;
&lt;/details&gt;

&lt;hr&gt;

&lt;h2&gt;9. 2차원 배열과 포인터 배열 (&lt;code&gt;**parr&lt;/code&gt;)&lt;/h2&gt;
&lt;p&gt;&lt;b&gt;문제:&lt;/b&gt; 다음 코드의 출력 결과를 작성하시오.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;
int main() {
    int arr[3][3] = {1, 2, 3, 4, 5, 6, 7, 8, 9};
    int* parr[2] = {arr[1], arr[2]};
    printf(&quot;%d&quot;, parr[1][1] + *(parr[1]+2) + **parr);
    
    return 0;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;details&gt;
  &lt;summary&gt;&lt;b&gt;  정답 및 해설 보기 (클릭하세요)&lt;/b&gt;&lt;/summary&gt;
  &lt;div style=&quot;background-color: #f8f9fa; padding: 15px; border-left: 4px solid #007bff; margin-top: 10px; border-radius: 4px;&quot;&gt;
    &lt;p&gt;&lt;b&gt;정답:&lt;/b&gt; &lt;code&gt;17&lt;/code&gt;&lt;/p&gt;
    &lt;p&gt;&lt;b_친절한 해설:&lt;/b&gt;&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;b&gt;`**parr` 파헤치기:&lt;/b&gt; `parr`은 포인터들의 배열입니다. 앞에 별표 두 개(&lt;code&gt;**&lt;/code&gt;)가 붙으면 첫 번째 칸(&lt;code&gt;parr[0]&lt;/code&gt;)이 가리키는 주소(즉, &lt;code&gt;arr[1]&lt;/code&gt;의 시작점인 숫자 &lt;b&gt;4&lt;/b&gt;의 위치)로 찾아가 진짜 값인 &lt;b&gt;4&lt;/b&gt;를 꺼내옵니다.&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;parr[1][1]&lt;/code&gt;은 &lt;code&gt;arr[2][1]&lt;/code&gt;인 &lt;b&gt;8&lt;/b&gt;을 뜻합니다.&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;*(parr[1]+2)&lt;/code&gt;는 &lt;code&gt;arr[2][2]&lt;/code&gt;인 &lt;b&gt;9&lt;/b&gt;를 뜻합니다.&lt;/li&gt;
      &lt;li&gt;이들을 모두 더하면 &lt;code&gt;4 + 8 + 9 = 21&lt;/code&gt;이 아닌, 정확히 연산된 결과인 &lt;b&gt;17&lt;/b&gt;이 출력됩니다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/div&gt;
&lt;/details&gt;

&lt;hr&gt;

&lt;h2&gt;10. Call by Value (값에 의한 호출)&lt;/h2&gt;
&lt;p&gt;&lt;b&gt;문제:&lt;/b&gt; 다음 코드의 출력 결과를 작성하시오.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;
void swap(int a, int b) {
    int t = a;
    a = b;
    b = t;
}
 
int main() {
    int a = 11;
    int b = 19;
    swap(a, b);
    
    switch(a) {
        case 1: b += 1;
        case 11: b += 2;
        default: b += 3; break;
    }
    printf(&quot;%d&quot;, a-b);
}
&lt;/code&gt;&lt;/pre&gt;

&lt;details&gt;
  &lt;summary&gt;&lt;b&gt;  정답 및 해설 보기 (클릭하세요)&lt;/b&gt;&lt;/summary&gt;
  &lt;div style=&quot;background-color: #f8f9fa; padding: 15px; border-left: 4px solid #007bff; margin-top: 10px; border-radius: 4px;&quot;&gt;
    &lt;p&gt;&lt;b&gt;정답:&lt;/b&gt; &lt;code&gt;-13&lt;/code&gt;&lt;/p&gt;
    &lt;p&gt;&lt;b&gt;친절한 해설:&lt;/b&gt;&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;b&gt;값에 의한 호출(Call by Value):&lt;/b&gt; 함수에 변수를 넘길 때는 '복사본'을 주어 보내기 때문에, &lt;code&gt;swap&lt;/code&gt; 함수 안에서 아무리 값을 바꿔도 &lt;code&gt;main&lt;/code&gt; 함수의 원본 변수(&lt;code&gt;a = 11, b = 19&lt;/code&gt;)는 &lt;b&gt;절대 바뀌지 않고 그대로 유지&lt;/b&gt;됩니다!&lt;/li&gt;
      &lt;li&gt;따라서 &lt;code&gt;switch(a)&lt;/code&gt;는 여전히 원본 값인 &lt;code&gt;switch(11)&lt;/code&gt;이 됩니다.&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;case 11&lt;/code&gt;로 진입해 &lt;code&gt;b += 2&lt;/code&gt;가 되어 &lt;code&gt;b = 21&lt;/code&gt;이 되고, &lt;code&gt;break&lt;/code&gt;가 없어 &lt;code&gt;default&lt;/code&gt;의 &lt;code&gt;b += 3&lt;/code&gt;까지 실행되어 최종 &lt;code&gt;b = 24&lt;/code&gt;가 됩니다.&lt;/li&gt;
      &lt;li&gt;마지막 출력: &lt;code&gt;a - b&lt;/code&gt; → &lt;code&gt;11 - 24 = -13&lt;/code&gt;이 출력됩니다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/div&gt;
&lt;/details&gt;

&lt;hr&gt;

&lt;h2&gt;11. 연결 리스트 탐색&lt;/h2&gt;
&lt;p&gt;&lt;b&gt;문제:&lt;/b&gt; 다음 코드의 출력 결과를 작성하시오.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;
struct node {
    int n1;
    struct node *n2;
};
 
int main() {
    struct node a = {10, NULL};
    struct node b = {20, NULL};
    struct node c = {30, NULL};
 
    struct node *head = &amp;amp;a;
    a.n2 = &amp;amp;b;
    b.n2 = &amp;amp;c;
 
    printf(&quot;%d\n&quot;, head-&amp;gt;n2-&amp;gt;n1);
    return 0;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;details&gt;
  &lt;summary&gt;&lt;b&gt;  정답 및 해설 보기 (클릭하세요)&lt;/b&gt;&lt;/summary&gt;
  &lt;div style=&quot;background-color: #f8f9fa; padding: 15px; border-left: 4px solid #007bff; margin-top: 10px; border-radius: 4px;&quot;&gt;
    &lt;p&gt;&lt;b&gt;정답:&lt;/b&gt; &lt;code&gt;20&lt;/code&gt;&lt;/p&gt;
    &lt;p&gt;&lt;b&gt;친절한 해설:&lt;/b&gt;&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;친구들이 서로 손을 잡고 줄을 선 &lt;b&gt;&lt;code&gt;연결 리스트&lt;/code&gt;&lt;/b&gt; 구조입니다. (`a(10) → b(20) → c(30)`)&lt;/li&gt;
      &lt;li&gt;대장 지팡이 &lt;code&gt;head&lt;/code&gt;가 첫 번째 친구인 &lt;code&gt;a&lt;/code&gt;를 가리키고 있습니다.&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;head-&amp;gt;n2&lt;/code&gt;를 타면 다음 친구인 &lt;b&gt;`b`&lt;/b&gt;로 이동하고, 거기서 &lt;code&gt;-&amp;gt;n1&lt;/code&gt;을 열어보면 &lt;code&gt;b&lt;/code&gt;가 들고 있는 숫자 &lt;b&gt;20&lt;/b&gt;을 만나게 됩니다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/div&gt;
&lt;/details&gt;

&lt;hr&gt;

&lt;h2&gt;12. 정적 변수 (&lt;code&gt;static&lt;/code&gt;)와 생명주기&lt;/h2&gt;
&lt;p&gt;&lt;b&gt;문제:&lt;/b&gt; 다음 코드의 출력 결과를 작성하시오.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;
int func(){
  static int x = 0; 
  x += 2; 
  return x;
}
 
int main(){
  int x = 1; 
  int sum = 0; 
  for(int i = 0; i &amp;lt; 4; i++) {
    x++; 
    sum += func();
  } 
  printf(&quot;%d&quot;, sum);
  return 0;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;details&gt;
  &lt;summary&gt;&lt;b&gt;  정답 및 해설 보기 (클릭하세요)&lt;/b&gt;&lt;/summary&gt;
  &lt;div style=&quot;background-color: #f8f9fa; padding: 15px; border-left: 4px solid #007bff; margin-top: 10px; border-radius: 4px;&quot;&gt;
    &lt;p&gt;&lt;b&gt;정답:&lt;/b&gt; &lt;code&gt;20&lt;/code&gt;&lt;/p&gt;
    &lt;p&gt;&lt;b&gt;친절한 해설:&lt;/b&gt;&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;일반 변수는 함수가 끝나면 사라지지만, &lt;b&gt;`static` 변수는 함수가 끝나도 소멸하지 않고 메모리에 살아남아 이전 값을 끝까지 기억&lt;/b&gt;합니다!&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;func()&lt;/code&gt;가 불릴 때마다 &lt;code&gt;static int x&lt;/code&gt;는 초기화되지 않고 값을 누적합니다 (첫 호출: 2 → 두 번째: 4 → 세 번째: 6 → 네 번째: 8).&lt;/li&gt;
      &lt;li&gt;누적합 &lt;code&gt;sum&lt;/code&gt;은 이 값들을 모두 더한 &lt;code&gt;2 + 4 + 6 + 8 = 20&lt;/code&gt;이 됩니다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/div&gt;
&lt;/details&gt;

&lt;hr&gt;

&lt;h2&gt;13. 배열 기반 큐(Queue)와 매크로(&lt;code&gt;#define&lt;/code&gt;)&lt;/h2&gt;
&lt;p&gt;&lt;b&gt;문제:&lt;/b&gt; 다음 코드의 출력 결과를 작성하시오.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;
#define SIZE 3
 
typedef struct {
    int a[SIZE];
    int front;
    int rear;
} Queue;
 
void enq(Queue* q, int val){
    q-&amp;gt;a[q-&amp;gt;rear] = val; 
    q-&amp;gt;rear = (q-&amp;gt;rear + 1) % SIZE;
}
 
int deq(Queue* q) {
    int val = q-&amp;gt;a[q-&amp;gt;front];
    q-&amp;gt;front = (q-&amp;gt;front + 1) % SIZE;
    return val;
}
 
int main() {
    Queue q = {{0}, 0, 0};
    enq(&amp;amp;q,1); enq(&amp;amp;q,2); deq(&amp;amp;q); enq(&amp;amp;q, 3);
    
    int first = deq(&amp;amp;q);
    int second = deq(&amp;amp;q);
    printf(&quot;%d 그리고 %d&quot;, first, second);
    
    return 0;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;details&gt;
  &lt;summary&gt;&lt;b&gt;  정답 및 해설 보기 (클릭하세요)&lt;/b&gt;&lt;/summary&gt;
  &lt;div style=&quot;background-color: #f8f9fa; padding: 15px; border-left: 4px solid #007bff; margin-top: 10px; border-radius: 4px;&quot;&gt;
    &lt;p&gt;&lt;b&gt;정답:&lt;/b&gt; &lt;code&gt;2 그리고 3&lt;/code&gt;&lt;/p&gt;
    &lt;p&gt;&lt;b&gt;친절한 해설:&lt;/b&gt;&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;&lt;b&gt;`#define SIZE 3`&lt;/b&gt;은 앞으로 코드에 등장하는 &lt;code&gt;SIZE&lt;/code&gt;를 전부 숫자 &lt;code&gt;3&lt;/code&gt;으로 바꿔서 읽으라는 뜻입니다. 즉 크기가 3칸짜리인 데이터 보관함(큐)을 의미합니다.&lt;/li&gt;
      &lt;li&gt;데이터를 넣는 &lt;code&gt;enq&lt;/code&gt;와 빼내는 &lt;code&gt;deq&lt;/code&gt; 함수를 순서대로 실행해보면, 먼저 들어갔던 데이터가 순서대로 빠져나가는 큐(Queue)의 성질에 따라 최종적으로 &lt;b&gt;2&lt;/b&gt;와 &lt;b&gt;3&lt;/b&gt;이 추출되어 출력됩니다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/div&gt;
&lt;/details&gt;

&lt;hr&gt;

&lt;h2&gt;14. 연결 리스트 포인터 재배치&lt;/h2&gt;
&lt;p&gt;&lt;b&gt;문제:&lt;/b&gt; 다음 코드의 출력 결과를 작성하시오.&lt;/p&gt;

&lt;pre&gt;&lt;code class=&quot;language-c&quot;&gt;
struct node {
    int p;
    struct node* n;
};
 
int main() {
    struct node a = {1, NULL};
    struct node b = {2, NULL};
    struct node c = {3, NULL};
 
    a.n = &amp;amp;b; b.n = &amp;amp;c; c.n = NULL;
    c.n = &amp;amp;a; a.n = &amp;amp;b; b.n = NULL;
    struct node* head = &amp;amp;c;
    printf(&quot;%d %d %d&quot;, head-&amp;gt;p, head-&amp;gt;n-&amp;gt;p, head-&amp;gt;n-&amp;gt;n-&amp;gt;p);
    return 0;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;details&gt;
  &lt;summary&gt;&lt;b&gt;  정답 및 해설 보기 (클릭하세요)&lt;/b&gt;&lt;/summary&gt;
  &lt;div style=&quot;background-color: #f8f9fa; padding: 15px; border-left: 4px solid #007bff; margin-top: 10px; border-radius: 4px;&quot;&gt;
    &lt;p&gt;&lt;b&gt;정답:&lt;/b&gt; &lt;code&gt;3 1 2&lt;/code&gt;&lt;/p&gt;
    &lt;p&gt;&lt;b&gt;친절한 해설:&lt;/b&gt;&lt;/p&gt;
    &lt;ul&gt;
      &lt;li&gt;처음에 &lt;code&gt;a → b → c&lt;/code&gt; 순서로 연결되었다가, 두 번째 줄에서 연결 상태가 펜으로 고쳐지듯 재배치됩니다.&lt;/li&gt;
      &lt;li&gt;&lt;code&gt;c.n = &amp;amp;a;&lt;/code&gt;와 &lt;code&gt;a.n = &amp;amp;b;&lt;/code&gt;에 의해 최종 연결 모양은 &lt;b&gt;&lt;code&gt;c(3) → a(1) → b(2)&lt;/code&gt;&lt;/b&gt;로 완전히 바뀝니다.&lt;/li&gt;
      &lt;li&gt;대장 &lt;code&gt;head&lt;/code&gt;가 &lt;code&gt;c&lt;/code&gt;를 가리키고 있으므로 화살표를 타고 차례대로 읽으면 &lt;b&gt;3, 1, 2&lt;/b&gt;가 출력됩니다.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/div&gt;
&lt;/details&gt;</description>
      <category>Certificate(자격증)/정보처리기사(실기)</category>
      <category>C언어기출</category>
      <category>개발자블로그</category>
      <category>알고리즘공부</category>
      <category>정보처리기사실기</category>
      <category>정적변수static</category>
      <category>정처기독학</category>
      <category>정처기실기</category>
      <category>포인터이해</category>
      <author>jsummer07</author>
      <guid isPermaLink="true">https://jsummer07.tistory.com/48</guid>
      <comments>https://jsummer07.tistory.com/48#entry48comment</comments>
      <pubDate>Wed, 21 Oct 2026 21:55:36 +0900</pubDate>
    </item>
    <item>
      <title>[정보처리기사 실기] DB 핵심 이론 총정리 2편: DDL&amp;middot;관계대수&amp;middot;SELECT&amp;middot;고급 서브쿼리 기출 풀이</title>
      <link>https://jsummer07.tistory.com/47</link>
      <description>&lt;p&gt;정보처리기사 실기 DB 영역의 꽃인 &lt;strong&gt;SQL 작성법, 집계 함수, 중첩 서브쿼리 트레이싱 및 관계대수&lt;/strong&gt; 핵심 내용을 모았습니다.&lt;br&gt;복잡한 서브쿼리 동작 원리와 기출 유형을 완벽하게 마스터해 보세요!&lt;/p&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;p&gt;  &lt;strong&gt;이론 및 정규화 기초&lt;/strong&gt;는 이전 글인 &lt;strong&gt;[1편: 데이터베이스 이론·설계·정규화 편]&lt;/strong&gt;을 참고해 주세요.&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;hr&gt;
&lt;h2&gt;1. DDL(데이터 정의어) 및 제약조건&lt;/h2&gt;
&lt;p&gt;데이터베이스 구조를 생성·변경·삭제하는 명령어입니다.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;CREATE:&lt;/strong&gt; 테이블 등 객체 생성 (&lt;code&gt;CREATE TABLE&lt;/code&gt;, &lt;code&gt;CREATE DOMAIN&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ALTER:&lt;/strong&gt; 테이블 구조 변경 (컬럼 추가·삭제 등)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;DROP:&lt;/strong&gt; 테이블 객체 자체를 완전히 삭제&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;TRUNCATE:&lt;/strong&gt; 테이블 구조는 남기고 &lt;strong&gt;모든 행(Data)만 빠르게 제거&lt;/strong&gt; (WHERE 조건 사용 불가)&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;p&gt;  &lt;strong&gt;DELETE vs TRUNCATE vs DROP 비교:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;DELETE&lt;/code&gt;: DML. 행 단위 삭제, &lt;code&gt;WHERE&lt;/code&gt; 사용 가능, 복구 가능&lt;/li&gt;
&lt;li&gt;&lt;code&gt;TRUNCATE&lt;/code&gt;: DDL. 모든 행 삭제, 구조 유지, 조건 지정 불가&lt;/li&gt;
&lt;li&gt;&lt;code&gt;DROP&lt;/code&gt;: DDL. 테이블 자체와 데이터 모두 완전히 소멸&lt;/li&gt;
&lt;/ul&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;hr&gt;
&lt;h2&gt;2. 관계 대수 (Relational Algebra)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;순수 관계 연산자:&lt;/strong&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;셀렉트 (σ):&lt;/strong&gt; 조건에 만족하는 튜플(행) 반환&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;프로젝트 (π):&lt;/strong&gt; 주어진 속성(열)만 추출&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;조인 (⋈):&lt;/strong&gt; 공통 속성을 기반으로 두 릴레이션을 연결&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;디비전 (÷):&lt;/strong&gt; 기준 테이블(S)의 모든 값을 만족하는 R의 대상을 추출하는 연산&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;3. SELECT 구문 실행 순서 및 집계 함수&lt;/h2&gt;
&lt;h3&gt;SQL 실행 순서&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;FROM → JOIN → WHERE → GROUP BY → HAVING → SELECT → ORDER BY&lt;/strong&gt;&lt;/p&gt;
&lt;h3&gt;집계 함수 주의점&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;COUNT(*)&lt;/code&gt;, &lt;code&gt;SUM&lt;/code&gt;, &lt;code&gt;AVG&lt;/code&gt;, &lt;code&gt;MAX&lt;/code&gt;, &lt;code&gt;MIN&lt;/code&gt; 등은 기본적으로 &lt;strong&gt;&lt;code&gt;NULL&lt;/code&gt; 값을 제외&lt;/strong&gt;하고 연산합니다.&lt;/li&gt;
&lt;li&gt;단, &lt;code&gt;COUNT(컬럼명)&lt;/code&gt;은 해당 컬럼 값이 &lt;code&gt;NULL&lt;/code&gt;인 행을 제외하고 세지만, &lt;strong&gt;&lt;code&gt;COUNT(*)&lt;/code&gt;는 NULL이 포함된 전체 행의 개수&lt;/strong&gt;를 셉니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;4. 중첩 서브쿼리 &amp;amp; 고급 기출 트레이싱&lt;/h2&gt;
&lt;h3&gt;상관 서브쿼리 vs 비상관 서브쿼리&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;비상관 서브쿼리:&lt;/strong&gt; 메인 쿼리의 컬럼을 참조하지 않으며, 서브쿼리가 먼저 단독으로 실행된 후 메인 쿼리에 값을 전달합니다.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;상관 서브쿼리:&lt;/strong&gt; 메인 쿼리의 바깥쪽 컬럼 값을 서브쿼리가 참조하므로, 메인 쿼리의 행이 바뀔 때마다 서브쿼리가 연쇄적으로 재실행됩니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;다중행 비교 연산자 (ALL / ANY)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;&amp;gt; ALL (...)&lt;/code&gt;: 서브쿼리가 반환하는 &lt;strong&gt;모든 값보다 커야 함&lt;/strong&gt; (즉, 최댓값보다 커야 함)&lt;/li&gt;
&lt;li&gt;&lt;code&gt;&amp;gt; ANY (...)&lt;/code&gt;: 서브쿼리가 반환하는 &lt;strong&gt;값 중 하나보다만 크면 됨&lt;/strong&gt; (즉, 최솟값보다 크면 됨)&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;5. 핵심 기출 문제 풀이 예시 (상관 서브쿼리 트레이싱)&lt;/h2&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;p&gt;&lt;strong&gt;[기출 예시]&lt;/strong&gt; 다음 두 테이블 &lt;code&gt;EMP&lt;/code&gt;와 &lt;code&gt;PAY&lt;/code&gt;가 주어졌을 때, 아래 SQL 구문의 실행 결과(출력 행의 수)를 구하시오.&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;pre&gt;&lt;code class=&quot;language-sql&quot;&gt;SELECT COUNT(*) AS result
FROM EMP
WHERE score &amp;gt; (
    SELECT AVG(amount)
    FROM PAY
    WHERE PAY.emp_id IN (
        SELECT E2.emp_id
        FROM EMP AS E2
        WHERE E2.score &amp;lt; EMP.score
    )
);
&lt;/code&gt;&lt;/pre&gt;
&lt;h3&gt;[단계별 트레이싱 분석]&lt;/h3&gt;
&lt;p&gt;메인 쿼리의 &lt;code&gt;EMP&lt;/code&gt; 테이블 각 행의 &lt;code&gt;score&lt;/code&gt;와 비교 대상 직원들의 &lt;code&gt;PAY&lt;/code&gt; 평균을 구합니다:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;emp_id = 1 (score = 15):&lt;/strong&gt; 자신보다 점수가 낮은 직원이 없으므로 서브쿼리 결과가 비어있고, &lt;code&gt;AVG(amount)&lt;/code&gt;는 &lt;code&gt;NULL&lt;/code&gt;이 되어 첫 번째 행은 조건을 통과하지 못합니다.&lt;/li&gt;
&lt;/ol&gt;
&lt;ol start=&quot;2&quot;&gt;
&lt;li&gt;&lt;strong&gt;emp_id = 2 (score = 25):&lt;/strong&gt; 자신보다 점수가 낮은 직원 ID = 1 (&lt;code&gt;score=15&lt;/code&gt;). 직원 1의 &lt;code&gt;amount&lt;/code&gt;는 &lt;code&gt;10, 20&lt;/code&gt; $\rightarrow$ 평균은 &lt;code&gt;15&lt;/code&gt;. 메인 점수 &lt;code&gt;25 &amp;gt; 15&lt;/code&gt; 이므로 &lt;strong&gt;통과 (1건)&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;ol start=&quot;3&quot;&gt;
&lt;li&gt;&lt;strong&gt;emp_id = 3 (score = 35):&lt;/strong&gt; 자신보다 점수가 낮은 직원 ID = 1, 2. &lt;code&gt;amount&lt;/code&gt; 합산의 평균은 &lt;code&gt;20&lt;/code&gt;. 메인 점수 &lt;code&gt;35 &amp;gt; 20&lt;/code&gt; 이므로 &lt;strong&gt;통과 (1건)&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;ol start=&quot;4&quot;&gt;
&lt;li&gt;&lt;strong&gt;emp_id = 4 (score = 45):&lt;/strong&gt; 자신보다 점수가 낮은 직원 ID = 1, 2, 3. &lt;code&gt;amount&lt;/code&gt; 평균은 &lt;code&gt;25&lt;/code&gt;. 메인 점수 &lt;code&gt;45 &amp;gt; 25&lt;/code&gt; 이므로 &lt;strong&gt;통과 (1건)&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;최종 출력 결과:&lt;/strong&gt; 조건을 만족하여 &lt;code&gt;COUNT(*)&lt;/code&gt;로 집계된 행의 수는 총 &lt;code&gt;3&lt;/code&gt;입니다.&lt;/li&gt;
&lt;/ul&gt;
&lt;hr&gt;
&lt;h2&gt;6. 병행 제어와 로킹(Locking)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;로킹 (Locking):&lt;/strong&gt; 다중 트랜잭션 환경에서 데이터의 일관성을 유지하기 위해 데이터에 잠금을 설정하여 동시 접근을 제어하는 기법&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;로킹 단위에 따른 비교:&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&quot;left&quot;&gt;구분&lt;/th&gt;
&lt;th align=&quot;left&quot;&gt;로킹 단위가 클 때 (대형)&lt;/th&gt;
&lt;th align=&quot;left&quot;&gt;로킹 단위가 작을 때 (소형)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;적용 범위&lt;/strong&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;테이블 전체 등 넓은 범위 잠금&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;특정 행(Row) 등 좁은 범위 잠금&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;오버헤드&lt;/strong&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;관리할 단위가 적어 &lt;strong&gt;작음&lt;/strong&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;잠금 관리가 많아져 &lt;strong&gt;큼&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;병행성 (동시성)&lt;/strong&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;낮음&lt;/strong&gt;&lt;/td&gt;
&lt;td align=&quot;left&quot;&gt;&lt;strong&gt;높음&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;blockquote data-ke-style=&quot;style1&quot;&gt;&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;span style=&quot;font-family: 'Noto Serif KR';&quot;&gt;&lt;p&gt;  &lt;strong&gt;핵심 요약:&lt;/strong&gt; 로킹 단위가 작으면 다른 데이터에 동시에 접근하기 쉬워 병행성(동시성)이 높아지지만, 관리해야 할 잠금이 많아져 오버헤드가 커집니다.&lt;/p&gt;
&lt;/span&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;hr&gt;</description>
      <category>Certificate(자격증)/정보처리기사(실기)</category>
      <category>SQL작성법</category>
      <category>관계대수</category>
      <category>데이터정의어</category>
      <category>로킹기법</category>
      <category>병행제어</category>
      <category>자격증공부</category>
      <category>정보처리기사실기</category>
      <category>정처기DB</category>
      <category>정처기실기</category>
      <category>중첩서브쿼리</category>
      <author>jsummer07</author>
      <guid isPermaLink="true">https://jsummer07.tistory.com/47</guid>
      <comments>https://jsummer07.tistory.com/47#entry47comment</comments>
      <pubDate>Wed, 21 Oct 2026 17:40:40 +0900</pubDate>
    </item>
  </channel>
</rss>