<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>'조예빈'의 개발 흔적</title>
    <link>https://yebin0322.tistory.com/</link>
    <description>안녕하세요!
개발자 조예빈 입니다 :)</description>
    <language>ko</language>
    <pubDate>Sat, 11 Apr 2026 04:12:42 +0900</pubDate>
    <generator>TISTORY</generator>
    <ttl>100</ttl>
    <managingEditor>yebin0322</managingEditor>
    <image>
      <title>'조예빈'의 개발 흔적</title>
      <url>https://tistory1.daumcdn.net/tistory/7558550/attach/2c15ff19135749b38be48d1717b5fe6a</url>
      <link>https://yebin0322.tistory.com</link>
    </image>
    <item>
      <title>간편인증, 전자서명, 증명서, 본인확인</title>
      <link>https://yebin0322.tistory.com/entry/%EA%B0%84%ED%8E%B8%EC%9D%B8%EC%A6%9D-%EC%A0%84%EC%9E%90%EC%84%9C%EB%AA%85-%EC%A6%9D%EB%AA%85%EC%84%9C-%EB%B3%B8%EC%9D%B8%ED%99%95%EC%9D%B8</link>
      <description>&lt;h1&gt;간편인증(Simple Authentication)&lt;/h1&gt;
&lt;h2&gt;개념&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;기존의 공인인증서나 복잡한 로그인 방식보다 더 간단하고 빠르게 본인을 인증하는 방식&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;예시&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;카카오페이 인증&lt;/li&gt;
&lt;li&gt;PASS 앱 인증&lt;/li&gt;
&lt;li&gt;네이버 인증서&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;원리&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;사용자가 인증 요청을 받으면 등록된 앱에서 생체인증 / 간단한 비밀번호로 확인(서버는 인증 요청 토큰(Authorization Code)과 함께 사용자의 식별자(휴대폰번호 등) 전송&lt;/li&gt;
&lt;li&gt;서버는 해당 사용자에게 기기 고유 정보, 시간정보, 암호화된 데이터 등을 이용해 서명 검증(&lt;/li&gt;
&lt;li&gt;인증 성공 시, 서버는 &amp;#39;이 사용자가 맞다&amp;#39;고 판단&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;=&amp;gt; 비대면 + 모바일 + 암호화 기반으로 빠른 신원 확인&lt;/p&gt;
&lt;h1&gt;전자서명(Digital Signature)&lt;/h1&gt;
&lt;h2&gt;개념&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;전자문서에 대해 누가 작성했는지, 위/변조되지 않았는지를 증명하는 기술&lt;/li&gt;
&lt;li&gt;종이 서명과 비슷한 역할&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;예시&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;전자계약서 서명&lt;/li&gt;
&lt;li&gt;공공기관 민원 서명&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;원리&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;문서를 암호화 알고리즘(SHA, RSA 등)으로 요약(해시)&lt;/li&gt;
&lt;li&gt;개인키로 이 요약 값을 암호화 -&amp;gt; 전자서명&lt;/li&gt;
&lt;li&gt;상대방은 공개키로 이 전자서명을 복호화하여 원래 해시와 비교함으로써 위/변조 여부를 확인&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;=&amp;gt; 개인키로 암호화, 공개키로 검증 -&amp;gt; 서명자 확인 + 문서 무결성 보장&lt;/p&gt;
&lt;h1&gt;증명서(Certificate)&lt;/h1&gt;
&lt;h2&gt;개념&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;어떤 정보(신분, 자격, 인증 등)가 공식적으로 맞다고 증명하는 문서&lt;/li&gt;
&lt;li&gt;종이 혹은 전자 형태가 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;예시&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;주민등록등본&lt;/li&gt;
&lt;li&gt;졸업증명서&lt;/li&gt;
&lt;li&gt;건강보험 자격득실 확인서&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;원리&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;발급기관이 특정 정보를 담은 전자문서에 전자서명을 함&lt;/li&gt;
&lt;li&gt;수신사는 서명이 유효한지, 위/변조가 없는지를 공개키로 검증 가능&lt;/li&gt;
&lt;li&gt;일부는 QR 코드나 블록체인을 이용해 진위 여부 확인도 가능&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;=&amp;gt; 신뢰기관이 서명한 전자문서 -&amp;gt; 공식적으로 진짜라는 것을 증명&lt;/p&gt;
&lt;h1&gt;본인확인(Identity Verification)&lt;/h1&gt;
&lt;h2&gt;개념&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;어떤 사람이 실제로 본인(당사자)이 맞는지를 확인하는 절차&lt;/li&gt;
&lt;li&gt;보안의 가장 기본 단계&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;예시&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;휴대폰 본인확인(문자인증)&lt;/li&gt;
&lt;li&gt;아이핀(i-PIN)&lt;/li&gt;
&lt;li&gt;신분증 OCR + 얼굴 인식&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;원리&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;사용자가 입력한 정보(이름, 주민번호 등)와&lt;/li&gt;
&lt;li&gt;통신사 / 신용정보사 등에 등록된 정보를 대조하여 일치하는지 확인&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;=&amp;gt; 정보 비교 또는 기기 인증 + 생체정보 조합으로 본인 여부 검증&lt;/p&gt;</description>
      <category>보안</category>
      <author>yebin0322</author>
      <guid isPermaLink="true">https://yebin0322.tistory.com/80</guid>
      <comments>https://yebin0322.tistory.com/entry/%EA%B0%84%ED%8E%B8%EC%9D%B8%EC%A6%9D-%EC%A0%84%EC%9E%90%EC%84%9C%EB%AA%85-%EC%A6%9D%EB%AA%85%EC%84%9C-%EB%B3%B8%EC%9D%B8%ED%99%95%EC%9D%B8#entry80comment</comments>
      <pubDate>Mon, 14 Jul 2025 10:11:33 +0900</pubDate>
    </item>
    <item>
      <title>인증 중계 플랫폼 기반의 통합 인증 서비스</title>
      <link>https://yebin0322.tistory.com/entry/%EC%9D%B8%EC%A6%9D-%EC%A4%91%EA%B3%84-%ED%94%8C%EB%9E%AB%ED%8F%BC-%EA%B8%B0%EB%B0%98%EC%9D%98-%ED%86%B5%ED%95%A9-%EC%9D%B8%EC%A6%9D-%EC%84%9C%EB%B9%84%EC%8A%A4</link>
      <description>&lt;h1&gt;인증 중계 플랫폼&lt;/h1&gt;
&lt;ul&gt;
&lt;li&gt;여러 인증 수단(패스워드, OTP, 생체인식, 공동 인증서 등)을 통합 관리하고, 다양한 서비스 제공자에게 일관된 방식으로 인증 정보를 전달해주는 중개 시스템&lt;/li&gt;
&lt;li&gt;사용자의 신원 확인(인증) 과정을 다양한 서비스 제공자(Service Provider, SP)와 인증 제공자(Identity Provider, IdP) 사이에서 중계해주는 역할을 하는 시스템&lt;/li&gt;
&lt;li&gt;디지털 서비스 이용 시 간편하고 안전한 로그인 및 인증 경험을 제공하는 데 중점을 둠&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;작동 구조&lt;/h2&gt;
&lt;ol&gt;
&lt;li&gt;사용자(User) : 서비스에 접속하려는 사람&lt;/li&gt;
&lt;li&gt;서비스 제공자(SP) : 웹사이트, 앱 등 사용자가 이용하려는 서비스&lt;/li&gt;
&lt;li&gt;인증 제공자(IdP) : 사용자의 신원을 실제로 인증하는 기관 또는 시스템&lt;/li&gt;
&lt;li&gt;인증 중계 플랫폼 : SP와 IdP 사이의 브릿지 역할. SP는 다양한 IdP를 직접 연동할 필요 없이, 인증 중계 플랫폼 하나만 연동하면 됨&lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;예시 시나리오&lt;/h4&gt;
&lt;p&gt;사용자 -&amp;gt; SP 접속 -&amp;gt; 인증 중계 플랫폼으로 인증 요청 -&amp;gt; 사용자 선택에 따라 인증 수단(공동인증서, PASS, 카카오 등) 선택 -&amp;gt; 인증 완료 후 -&amp;gt; SP에 인증 결과 전달&lt;/p&gt;
&lt;h2&gt;주요 기능&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;기능&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;인증 수단 통합&lt;/td&gt;
&lt;td&gt;다양한 인증 수단을 하나의 플랫폼에서 연동 및 제공&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;다중 IdP 연동&lt;/td&gt;
&lt;td&gt;여러 인증 제공자를 한 번에 연동 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;보안성 확보&lt;/td&gt;
&lt;td&gt;암호화, 위변조 방지, 세션 관리 등 보안 기능 포함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;편의성 제공&lt;/td&gt;
&lt;td&gt;사용자에게 선택 가능한 다양한 인증 수단 제공&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;로그 추적 및 감사&lt;/td&gt;
&lt;td&gt;인증 이력 및 로그 저장으로 감사 및 모니터링 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h2&gt;활용 사례&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;정부24, 민원24 등 공공기관 서비스&lt;/li&gt;
&lt;li&gt;핀테크 앱에서 본인 인증&lt;/li&gt;
&lt;li&gt;대학 포털 로그인 통합&lt;/li&gt;
&lt;li&gt;기업 내부 시스템의 SSO(Single Sign-On)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;장점&lt;/h2&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;/ul&gt;
&lt;h2&gt;단점&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;인증 중계 플랫폼에 문제가 생기면 &lt;strong&gt;연동된 모든 서비스의 로그인 및 인증이 불가능(단일 장애점(SPoF, Single Point of Failure)해짐&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;/ul&gt;
&lt;h2&gt;관련 기술&lt;/h2&gt;
&lt;h3&gt;SAML(Security Assertion Markup Language)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;XML 기반의 SSO 프로토콜&lt;/li&gt;
&lt;li&gt;사용자가 로그인하면 인증 정보를 토큰(Assertion) 형태로 전달&lt;/li&gt;
&lt;li&gt;고정된 기업 환경에 강하고 보안 수준이 높지만, 모바일이나 현대적 UX와는 잘 안맞음(인증 흐름이 브라우저 리다이렉트 기반이라 모바일 앱을 쓰다가 인증하려 하면 외부 웹 브라우저가 열렸다가 다시 돌아오는 구조)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;OAuth / OpenID Connect(OIDC)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;OAuth 2.0 : 권한 위임 프로토콜&lt;/li&gt;
&lt;li&gt;OpenID Connect : OAuth 위에 얹은 인증(Identification) 계층&lt;/li&gt;
&lt;li&gt;로그인 인증, 사용자 정보 조회에 사용됨&lt;/li&gt;
&lt;li&gt;토큰 기반(JWT)&lt;/li&gt;
&lt;li&gt;카카오 네이버, 토스, PASS가 OIDC 기반 로그인 API 제공&lt;/li&gt;
&lt;li&gt;웹/모바일 친화적, 소셜 로그인에 최적화 되어 있으며 범용성 높고 확장 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;FIDO(Fast Identity Online)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;비밀번호 없는 인증&lt;/strong&gt; 방식&lt;/li&gt;
&lt;li&gt;생체인식(지문, 얼굴), 보안키 등을 사용한 로컬 인증 + 공개키 암호화&lt;/li&gt;
&lt;li&gt;서버에 비밀번호를 저장하지 않기 때문에 해킹에 강함&lt;/li&gt;
&lt;li&gt;패스워드 없는 미래형 인증&lt;/li&gt;
&lt;li&gt;보안성이 매우 높으며, 단말기에 따라 적용 제약 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;DID(Decentralized Identity)&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;중앙 기관 없이 사용자가 자신의 신원 정보를 직접 관리&lt;/li&gt;
&lt;li&gt;블록체인 기반으로 위조, 변조가 불가능&lt;/li&gt;
&lt;li&gt;SSI(Self-Sovereign Identity) : 자기주권 신원&lt;/li&gt;
&lt;li&gt;통신 3사와 라온시큐어에서 서비스 제공&lt;/li&gt;
&lt;li&gt;개인정보를 분산해서 보관하기 때문에 프라이버시가 강화됨&lt;/li&gt;
&lt;li&gt;공공, 금융, 대학 등에서 디지털 신분증으로 활용 확산 중&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Web</category>
      <author>yebin0322</author>
      <guid isPermaLink="true">https://yebin0322.tistory.com/78</guid>
      <comments>https://yebin0322.tistory.com/entry/%EC%9D%B8%EC%A6%9D-%EC%A4%91%EA%B3%84-%ED%94%8C%EB%9E%AB%ED%8F%BC-%EA%B8%B0%EB%B0%98%EC%9D%98-%ED%86%B5%ED%95%A9-%EC%9D%B8%EC%A6%9D-%EC%84%9C%EB%B9%84%EC%8A%A4#entry78comment</comments>
      <pubDate>Wed, 9 Jul 2025 11:09:31 +0900</pubDate>
    </item>
    <item>
      <title>Docker, VMware의 차이</title>
      <link>https://yebin0322.tistory.com/entry/Docker-VMware%EC%9D%98-%EC%B0%A8%EC%9D%B4</link>
      <description>&lt;p&gt;VMware = OS 단위 가상화(하드웨어 가상화)&lt;br&gt;Docker = 애플리케이션 단위 가상화(프로세스 가상화, 컨테이너)&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;구분&lt;/th&gt;
&lt;th&gt;VMware(VM)&lt;/th&gt;
&lt;th&gt;Docker(Container)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;가상화 대상&lt;/td&gt;
&lt;td&gt;전체 OS(하드웨어 가상화)&lt;/td&gt;
&lt;td&gt;애플리케이션(프로세스 가상화)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;커널&lt;/td&gt;
&lt;td&gt;각 VM이 자기 OS + 커널 포함&lt;/td&gt;
&lt;td&gt;모든 컨테이너가 호스트 OS 커널 공유&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;속도&lt;/td&gt;
&lt;td&gt;느림(부팅 시간 필요)&lt;/td&gt;
&lt;td&gt;빠름(수 초 내 실행)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;무게&lt;/td&gt;
&lt;td&gt;무거움(GB 단위)&lt;/td&gt;
&lt;td&gt;가벼움(MB~GB)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;사용 목적&lt;/td&gt;
&lt;td&gt;OS 격리, 보안 환경 분리&lt;/td&gt;
&lt;td&gt;앱 배포, DevOps, 마이크로서비스&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;컴퓨터 구조&lt;/h3&gt;
&lt;p&gt;[5] 사용자&lt;br&gt;[4] 애플리케이션(앱, 프로그램)&lt;br&gt;[3] 운영체제(OS) -&amp;gt; 사용자 친화적 인터페이스&lt;br&gt;[2] 커널(Kernel) -&amp;gt; 하드웨어와 소통하는 뇌&lt;br&gt;[1] 펌웨어(BIOS, UEFI) -&amp;gt; 하드웨어 초기 설정&lt;br&gt;[0] 하드웨어(CPU, 메모리, 디스크, GPU 등)&lt;/p&gt;
&lt;h3&gt;하드웨어 가상화 =&amp;gt; 운영체제 전체를 가상화&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;VMware는 하드웨어 1개 위에 여러 개의 OS를 독립적으로 올려주는 가상화 플랫폼&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;[Hardware]
      ↓
[BIOS/UEFI]
      ↓
[Hypervisor (VMware)]
   ↓↓             ↓↓             ↓↓
[VM1: 커널 + OS] [VM2: 커널 + OS] [VM3: 커널 + OS]
   ↓              ↓               ↓
[앱1]            [앱2]           [앱3]&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;실제 물리 하드웨어처러 가짜 컴퓨터 전체를 만들어 주는 기술 -&amp;gt; VM&lt;/li&gt;
&lt;li&gt;완전한 가상 컴퓨터를 만들어서 그 안에 OS 설치&lt;/li&gt;
&lt;li&gt;VM끼리는 서로 다른 OS도 가능(윈도우/리눅스 혼합)&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;프로세스 가상화 =&amp;gt; 운영체제는 공유하고 애플리케이션만 격리해서 실행&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;하나의 운영체제 위에서 앱 실행 환경만 가짜로 분리하는 기술 -&amp;gt; 컨테이너&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;[Hardware]
      ↓
[BIOS/UEFI]
      ↓
[Host OS]
      ↓
[Docker Engine(도커 데몬)]
      ↓                        ↓
[Container 1] ← 앱 A만 있음 [Container 2] ← 앱 B만 있음 (커널은 공유)
&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;운영체제는 하나고 그 위에서 앱만 분리&lt;/li&gt;
&lt;li&gt;OS 공유, 커널도 공유&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;VMware 구조&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;bare-metal, hosted 구조 모두에서 사용 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;[하드웨어]
    ↓
[Hypervisor (VMware ESXi)]
    ↓
[Guest OS 1]     [Guest OS 2]
  App A             App B&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;하드웨어 위에 Hypervisor가 있고, 그 위에 서로 다른 OS(Windows, Linux 등)가 통째로 올라감&lt;/li&gt;
&lt;li&gt;각 VM은 완전히 격리됨 -&amp;gt; 보안에 강함&lt;/li&gt;
&lt;li&gt;하지만 무겁고, 리소스를 많이 씀&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Docker 구조&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;hosted 방식에서만 사용 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;pre&gt;&lt;code&gt;[하드웨어]
    ↓
[Host OS]
    ↓
[Docker Engine]
    ↓
[Container A]   [Container B]
   App A           App B&lt;/code&gt;&lt;/pre&gt;&lt;ul&gt;
&lt;li&gt;Host OS 커널을 공유하고, 그 위에 앱만 실행됨&lt;/li&gt;
&lt;li&gt;컨테이너는 가벼운 프로세스 수준의 격리&lt;/li&gt;
&lt;li&gt;실행 속도도 빠르고 자원 효율도 좋음&lt;/li&gt;
&lt;li&gt;단, 보안 격리는 VM만큼 강력하진 않음&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;OS위에 설치(프로세스 수준 vs 앱처럼 설치)&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;구분&lt;/th&gt;
&lt;th&gt;의미&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;프로세스 수준에서 실행된다&lt;/td&gt;
&lt;td&gt;시스템 내에서 마치 OS의 서비스나 백그라운드 데몬처럼 작동&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;앱처럼 설치된다&lt;/td&gt;
&lt;td&gt;사용자가 클릭해서 설치하고, 실행 아이콘 눌러서 켜는 일반 데스크탑 프로그램&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;=&amp;gt; Docker는 OS의 일부처럼 자동으로 떠 있고, VMware Workstation은 사용자가 앱을 실행해서 작동하는 GUI 기반 도구&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;구분&lt;/th&gt;
&lt;th&gt;Docker&lt;/th&gt;
&lt;th&gt;VMware Workstation&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;기능&lt;/td&gt;
&lt;td&gt;앱(컨테이너) 격리/실행&lt;/td&gt;
&lt;td&gt;운영체제 전체(OS)를 가상화&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;구조적 목적&lt;/td&gt;
&lt;td&gt;OS 위에서 앱을 프로세스처럼 실행&lt;/td&gt;
&lt;td&gt;OS 위에서 또 다른 OS를 VM 형태로 설치&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;실행 대상&lt;/td&gt;
&lt;td&gt;컨테이너(앱) = 호스트 OS의 커널을 공유&lt;/td&gt;
&lt;td&gt;게스트 OS = 호스트와 완전히 다른 커널 가짐&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;작동 방식&lt;/td&gt;
&lt;td&gt;커널 기능을 이용해 리눅스의 한 부분처럼 작동&lt;/td&gt;
&lt;td&gt;VM 하이퍼바이저가 CPU, RAM, 디스크까지 가상으로 분리해 제공&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;그럼 hosted방식에서의 docker와 VMware의 차이는?&lt;/h3&gt;
&lt;p&gt;Docker는 애초에 ‘하드웨어 시뮬레이션’도 없고, 커널도 공유&lt;br&gt;→ OS 위에서 그냥 “리눅스 프로세스를 격리해서 실행하는 도구”&lt;br&gt;→ 즉, 커널이 곧 호스트 커널 = 실행 대상이 프로세스(앱)&lt;br&gt;→ 그래서 우리가 &amp;quot;프로세스 수준의 가상화&amp;quot;라고 부르는 거&lt;/p&gt;
&lt;p&gt;VMware는 그 위에서 ‘하드웨어처럼 보이는 가짜 컴퓨터’를 만듦&lt;br&gt;→ 그 위에 OS를 다시 설치해야 돌아가요. 부팅도 해야 하고 커널도 별도&lt;br&gt;→ 즉, 실행 대상이 OS = 운영체제 수준 가상화&lt;/p&gt;</description>
      <category>인프라</category>
      <author>yebin0322</author>
      <guid isPermaLink="true">https://yebin0322.tistory.com/77</guid>
      <comments>https://yebin0322.tistory.com/entry/Docker-VMware%EC%9D%98-%EC%B0%A8%EC%9D%B4#entry77comment</comments>
      <pubDate>Sat, 21 Jun 2025 17:30:57 +0900</pubDate>
    </item>
    <item>
      <title>OS 로컬 설치 vs VM 방식</title>
      <link>https://yebin0322.tistory.com/entry/OS-%EB%A1%9C%EC%BB%AC-%EC%84%A4%EC%B9%98-vs-VM-%EB%B0%A9%EC%8B%9D</link>
      <description>&lt;h3&gt;1. 기본 개념&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;구분&lt;/th&gt;
&lt;th&gt;로컬 설치(베어메탈)&lt;/th&gt;
&lt;th&gt;가상화(VM)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;방식&lt;/td&gt;
&lt;td&gt;하드웨어에 직접 OS 설치&lt;/td&gt;
&lt;td&gt;Hypervisor 위에 여러 OS 실행&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;예시&lt;/td&gt;
&lt;td&gt;노트북에 윈도우 10 설치&lt;/td&gt;
&lt;td&gt;VMware ESXi위에 여러 리눅스 VM 실행&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;2. 실무 운영 측면 차이&lt;/h3&gt;
&lt;h4&gt;하드웨어 자원의 효율성&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;로컬 설치 : 하나의 OS가 CPU/RAM/디스크를 전부 점유 -&amp;gt; 비효율적, 서버마다 OS 한개만 가능&lt;/li&gt;
&lt;li&gt;가상화 : 여러 VM이 자원을 나눠씀(CPU가 16코어면, VM 4개에 4코어씩 할당 가능) -&amp;gt; 자원 활용률 극대화, 서버 통합 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;장애 복구 및 유연성&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;로컬 설치 : 장애 발생 시 OS 재설치 / 이미지(운영체제, 프로그램, 설정 등이 저장된 전체 복제본) 복원 필요 -&amp;gt; 시간 오래 걸림&lt;/li&gt;
&lt;li&gt;가상화 : VM 스냅샷 / 복제 기능으로 수분 내 복구 가능 -&amp;gt; RTO ↓&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;배포 및 확장성&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;로컬 설치 : 신규 서버 구축 = 하드웨어 세팅 + OS 설치 + 설정(1~2일 소요)&lt;/li&gt;
&lt;li&gt;가상화 : VM 탬플릿 기반으로 몇 분 만에 서버 수십 대 생성 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;테스트 및 개발 환경&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;로컬 설치 : 운영체제를 바꾸려면 디스크 초기화 or 듀얼부팅 설정 필요&lt;/li&gt;
&lt;li&gt;가상화 : 리눅스, 윈도우, CentOS 등 다양한 OS를 동시에 올려 테스트 가능 -&amp;gt; 실무 테스트 / QA 환경 구축에 필수&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;3. 실무 예시&lt;/h3&gt;
&lt;p&gt;[상황] 테스트 서버 3대가 필요함 (CentOS, Rocky Linux, Windows Server)&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;로컬 설치&lt;ul&gt;
&lt;li&gt;물리 서버 3대 필요&lt;/li&gt;
&lt;li&gt;각각의 서버에 OS 설치&lt;/li&gt;
&lt;li&gt;테스트가 끝나면 방치될 가능성 존재&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;가상화&lt;ul&gt;
&lt;li&gt;1대의 고성능 서버에 VMware 설치 후 3개의 VM 생성&lt;/li&gt;
&lt;li&gt;필요 시 삭제/복제/스냅샷 가능&lt;/li&gt;
&lt;li&gt;자원도 유동적으로 할당 가능&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;로컬 설치의 장점(가상화보다 나은 점)&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;항목&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;성능(오버헤드 없음)&lt;/td&gt;
&lt;td&gt;커널, 드라이버, 자원을 100% 그대로 쓰기 때문에 성능이 가장 좋음&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;예측 가능한 동작&lt;/td&gt;
&lt;td&gt;직접 설치한 OS는 가상화 계층이 없어서 단순하고 안정적이며, 하드웨어에 최적화된 드라이버 구성이 가능함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;하드웨어 직접 제어&lt;/td&gt;
&lt;td&gt;GPU, 센서, USB 등 특정 장치를 완전히 제어해야 할 때는 로컬이 유리(CPU는 나눠쓰거나 일부만 쓰는 것이 가능하지만 GPU는 그게 안됨)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;디버깅/하드웨어 테스트에 적합&lt;/td&gt;
&lt;td&gt;BIOS, 부팅, 커널 초기화 등 하드웨어에 가까운 문제를 직접 볼 수 있음&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;로컬 설치가 더 나은 상황&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;사용 사례&lt;/th&gt;
&lt;th&gt;이유&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;고성능 게임/그래픽 워크스테이션&lt;/td&gt;
&lt;td&gt;GPU 성능 극대화, 직접 제어&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;산업용 장비 제어용 PC&lt;/td&gt;
&lt;td&gt;센서, USB, 시리얼포트 직접 연결&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;카페 POS, 공장 제어 시스템&lt;/td&gt;
&lt;td&gt;로컬 환경에서 단일 기능 수행, 가상화 불필요&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;</description>
      <category>인프라</category>
      <author>yebin0322</author>
      <guid isPermaLink="true">https://yebin0322.tistory.com/76</guid>
      <comments>https://yebin0322.tistory.com/entry/OS-%EB%A1%9C%EC%BB%AC-%EC%84%A4%EC%B9%98-vs-VM-%EB%B0%A9%EC%8B%9D#entry76comment</comments>
      <pubDate>Sat, 21 Jun 2025 16:31:14 +0900</pubDate>
    </item>
    <item>
      <title>VMware</title>
      <link>https://yebin0322.tistory.com/entry/VMware</link>
      <description>&lt;h2&gt;VMware&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;가상화 기술을 제공하는 대표적인 회사이며, 이 제품군을 통칭&lt;/li&gt;
&lt;li&gt;서버, 네트워크, 스토리지를 논리적으로 추상화해서 하드웨어 리소스를 효율적으로 운영할 수 있도록 해줌&lt;/li&gt;
&lt;li&gt;기업용 인프라의 중심 플랫폼&lt;/li&gt;
&lt;li&gt;고가용성, 유연성, 보안성을 확보한 채 물리 자원을 효율적으로 활용할 수 있는 가상화 솔루션&lt;/li&gt;
&lt;li&gt;원래는 온프레미스 방식이 기본이었으나, 지금은 클라우드 확장을 위해 다양한 솔루션을 출시함&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;기본 구성 요소&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;구성요소&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;기본 OS(Host OS)&lt;/td&gt;
&lt;td&gt;Windows/Linux 등 실제 컴퓨터에 설치된 OS&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VMware Workstation/ESXi&lt;/td&gt;
&lt;td&gt;가상화 프로그램&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Guest OS&lt;/td&gt;
&lt;td&gt;VMware 위에 설치되는 Windows Server 같은 가상 OS&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;핵심 구성요소&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;구성요소&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;vSphere&lt;/td&gt;
&lt;td&gt;VMware의 핵심 가상화 플랫폼. vCenter + ESXi 포함&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ESXi&lt;/td&gt;
&lt;td&gt;VMware의 하이퍼바이저. Bare-metal 위에 직접 설치됨&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;vCenter Server&lt;/td&gt;
&lt;td&gt;여러 ESXi 호스트를 중앙에서 관리하는 관리 서버&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;vSAN&lt;/td&gt;
&lt;td&gt;스토리지를 가상화해 풀로 묶어 사용하는 소프트웨어 정의 스토리지&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;NSX&lt;/td&gt;
&lt;td&gt;네트워크 가상화 플랫폼. 보안, 라우팅, 로드밸런싱까지 지원&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;VMware Tools&lt;/td&gt;
&lt;td&gt;게스트 OS 성능 향상을 위한 도구(시간 동기화, 드라이버 등)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Hypervisor(하이퍼바이저) : 하드웨어 위에 여러 개의 가상 머신을 올릴 수 있게 해주는 소프트웨어 또는 플랫폼. 하나의 물리 서버(호스트)에서 여러 개의 운영체제(게스트 OS)를 동시에 실행할 수 있게 해주는 가상화의 핵심&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;구분&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;Type 1(Bare-metal)&lt;/td&gt;
&lt;td&gt;하드웨어 위에 직접 설치. 고성능, 고안정성.기업용 인프라에 사용&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Type 2(Hosted)&lt;/td&gt;
&lt;td&gt;일반 OS 위에 설치. 개인 개발/테스트용. 일반 PC나 노트북에 설치&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;ul&gt;
&lt;li&gt;Bare-metal(베어메탈) : 운영체제 없이 하드웨어 그 자체, 혹은 OS 없이 바로 하이퍼바이저를 설치하는 방식. 서버에 아무것도 설치되어 있지 않은 순수한 상태 = 베어메탈 상태&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;사용 이유&lt;/h3&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;항목&lt;/th&gt;
&lt;th&gt;이유&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;리소스 통합&lt;/td&gt;
&lt;td&gt;여러 대의 물리 서버를 가상화로 묶어 자원 활용률 극대화&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;고가용성(HA)&lt;/td&gt;
&lt;td&gt;호스트 장애 시 자동으로 VM을 다룬 호스트로 이동시켜 서비스 무중단 유지&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;vMotion&lt;/td&gt;
&lt;td&gt;실행 중인 VM을 다운타임 없이 다른 호스트로 실시간 이전 가능&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;DR/백업 연동&lt;/td&gt;
&lt;td&gt;Veeam, NetBackup 등과 연동해 백업/복구 체계 구성 용이&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;온프레미스 + 클라우드 연동&lt;/td&gt;
&lt;td&gt;VMware Cloud on AWS 등과 연계 가능. 클라우드 전환에 유연함&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h3&gt;AWS EC2 vs VMware&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;EC2는 AWS가 대신 만들어준 가상 서버이고, VMware는 우리가 직접 만드는 가상 서버 플랫폼임&lt;/li&gt;
&lt;li&gt;둘 다 가상 머신(VM)을 돌리는 기술이지만, 누가 어떻게 어디서 얼마나 제어하는지가 다름&lt;/li&gt;
&lt;/ul&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;항목&lt;/th&gt;
&lt;th&gt;AWS EC2&lt;/th&gt;
&lt;th&gt;VMware&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;위치&lt;/td&gt;
&lt;td&gt;퍼블릭 클라우드(AWS 서버)&lt;/td&gt;
&lt;td&gt;온프레미스, 프라이빗 클라우드&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;소유권&lt;/td&gt;
&lt;td&gt;AWS가 서버/하이퍼바이저 소유&lt;/td&gt;
&lt;td&gt;우리가 직접 서버/하이퍼바이저 운영&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;하이퍼바이저&lt;/td&gt;
&lt;td&gt;AWS가 내부에서 관리&lt;/td&gt;
&lt;td&gt;직접 설치한 ESXi&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;서버 생성 방식&lt;/td&gt;
&lt;td&gt;EC2 인스턴스 생성 클릭 -&amp;gt; 바로 생성&lt;/td&gt;
&lt;td&gt;VM 생성 전 서버/스토리지/네트워크 구성 필요&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;제어 범위&lt;/td&gt;
&lt;td&gt;제한적(인스턴스 수준 제어만 가능)&lt;/td&gt;
&lt;td&gt;전체 인프라 제어 가능(CPU/메모리/NIC/스토리지 등)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;관리 도구&lt;/td&gt;
&lt;td&gt;AWS 콘솔, CLI, SDK&lt;/td&gt;
&lt;td&gt;vCenter, PowerCLI, vSphere Client 등&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;장애 대응&lt;/td&gt;
&lt;td&gt;AWS가 자동 복구 또는 알림 제공&lt;/td&gt;
&lt;td&gt;우리가 직접 HA, 백업, vMotion 구성&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;확장/축소&lt;/td&gt;
&lt;td&gt;쉽고 빠름(Auto Scaling 등)&lt;/td&gt;
&lt;td&gt;수동 또는 자동화 구성 필요&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;비용&lt;/td&gt;
&lt;td&gt;사용한 만큼 과금(OPEX)&lt;/td&gt;
&lt;td&gt;장비 도입 및 라이선스 필요(CAPEX)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;보안 통제권&lt;/td&gt;
&lt;td&gt;AWS에 일부 위임&lt;/td&gt;
&lt;td&gt;완전한 통제권(OS, 네트워크, 저장소 등)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;ul&gt;
&lt;li&gt;AWS EC2 : AWS가 만들어놓은 큰 아파트에 월세로 방 하나를 빌려서 바로 컴퓨터를 켜는 느낌. 전기, 수도, 수도꼭지 등이 다 세팅되어 있어서 전기 배선이나 벽을 못 뜯음 -&amp;gt; 제어 범위 제한&lt;/li&gt;
&lt;li&gt;VMware : 우리가 건물을 직접 설계하고, 뼈대 올리고, 방도 직접 만들고, 배선도 깔기. 어떤 서버, 네트워크, 스토리지를 쓸지도 직접 정하고 관리, 유지보수도 100% 담당.&lt;/li&gt;
&lt;/ul&gt;
&lt;h4&gt;OPEX(운영비용) vs CAPEX(자본지출)&lt;/h4&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;구분&lt;/th&gt;
&lt;th&gt;CAPEX(Capital Expenditure)&lt;/th&gt;
&lt;th&gt;OPEX(Operating Expenditure)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;의미&lt;/td&gt;
&lt;td&gt;자산 구매에 드는 돈(한 번에 크게 지출)&lt;/td&gt;
&lt;td&gt;운영 유지에 드는 돈(지속적으로 나가는 비용)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;예시&lt;/td&gt;
&lt;td&gt;서버, 스토리지, 스위치 장비 구매&lt;/td&gt;
&lt;td&gt;전기세, 유지보수비, 클라우드 사용료&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;비용 처리&lt;/td&gt;
&lt;td&gt;감가상각(몇 년에 걸쳐 나눠서 처리)&lt;/td&gt;
&lt;td&gt;사용한 만큼 비용 처리&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;인프라 예&lt;/td&gt;
&lt;td&gt;사내에 직접 구매 + IDC 구축&lt;/td&gt;
&lt;td&gt;AWS EC2, S3 등 클라우드 자원 사용료&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;
&lt;h4&gt;Auto Scaling(자동 확장)&lt;/h4&gt;
&lt;ul&gt;
&lt;li&gt;서버 수를 트래픽 변화에 따라 자동으로 늘리거나 줄이는 기능. 주로 클라우드 환경에서 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;효과&lt;/th&gt;
&lt;th&gt;설명&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;&lt;tr&gt;
&lt;td&gt;비용 절감&lt;/td&gt;
&lt;td&gt;피크 시간 외엔 서버 수 줄이기&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;무중단 처리&lt;/td&gt;
&lt;td&gt;서버 자동 추가로 트래픽 감당&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;자동화&lt;/td&gt;
&lt;td&gt;운영자가 수동 개입 안 해도 됨&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;&lt;/table&gt;</description>
      <category>인프라</category>
      <author>yebin0322</author>
      <guid isPermaLink="true">https://yebin0322.tistory.com/75</guid>
      <comments>https://yebin0322.tistory.com/entry/VMware#entry75comment</comments>
      <pubDate>Sat, 21 Jun 2025 14:38:59 +0900</pubDate>
    </item>
    <item>
      <title>OpenAI API를 50% 싼 값에 호출하는 방법 : Batch API</title>
      <link>https://yebin0322.tistory.com/entry/OpenAI-API%EB%A5%BC-50-%EC%8B%BC-%EA%B0%92%EC%97%90-%ED%98%B8%EC%B6%9C%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95-Batch-API</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;Batch API&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;여러 개의 요청(Request)을 한 번에 묶어서 처리할 수 있도록 해주는 API&lt;/li&gt;
&lt;li&gt;여러 개의 요청을 한 번에 처리하도록 서버에 제출(submit)하고, 백그라운드에서 비동기 처리&lt;/li&gt;
&lt;li&gt;완료되면 결과를 나중에 조회&lt;br /&gt;=&amp;gt; 일괄 처리 예약 시스템&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;armasm&quot;&gt;&lt;code&gt;[POST /v1/batches]  &amp;larr; 요청 제출 (배치 등록)
        &amp;darr;
[배치 상태: processing]  &amp;larr; 서버가 비동기 처리 중
        &amp;darr;
[GET /v1/batches/{batch_id}]  &amp;larr; 상태 확인
        &amp;darr;
[GET /v1/files/{output_file_id}]  &amp;larr; 결과 다운로드&lt;/code&gt;&lt;/pre&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;1. 하나의 HTTP 요청으로 여러 작업 처리(Http Batching)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;장점 : 클라이언트-서버 간 왕복 횟수(RTT)를 줄이고, 대기 시간(latency) 개선&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;2. 대용량 데이터를 한꺼번에 처리(데이터 배치 작업)&lt;/h3&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;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;저렴한 이유&lt;/h2&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;/ul&gt;
&lt;table data-ke-align=&quot;alignLeft&quot;&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;기준&lt;/th&gt;
&lt;th&gt;실시간 API&lt;/th&gt;
&lt;th&gt;Batch API&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;처리 시간&lt;/td&gt;
&lt;td&gt;즉시&lt;/td&gt;
&lt;td&gt;예약 시간에 처리(24시간 이내에 처리)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;서버 부하&lt;/td&gt;
&lt;td&gt;높음&lt;/td&gt;
&lt;td&gt;서버가 한가한 시간에 처리&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;비용&lt;/td&gt;
&lt;td&gt;높음(온디맨드)&lt;/td&gt;
&lt;td&gt;낮음(예약 기반, 대량 처리 최적화)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;실시간 API : 사용자가 지금 요청하니까 즉시 처리 -&amp;gt; 고성능 인프라 필요 -&amp;gt; 비용 비쌈&lt;/li&gt;
&lt;li&gt;Batch API : 사용자가 미리 요청해둠 -&amp;gt; 서버 유휴 시간대에 천천히 처리 -&amp;gt; 비용 낮음&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;주의할 점&lt;/h2&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;요청 순서와 응답 순서 일치 여부 확인 : 식별자를 요청마다 넣고, 응답에서 그걸 기준으로 매칭해야 함&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;json&quot;&gt;&lt;code&gt;{
  &quot;requests&quot;: [
    { &quot;id&quot;: &quot;u1&quot;, &quot;method&quot;: &quot;GET&quot;, &quot;path&quot;: &quot;/users/1&quot; },
    { &quot;id&quot;: &quot;u2&quot;, &quot;method&quot;: &quot;GET&quot;, &quot;path&quot;: &quot;/users/2&quot; }
  ]
}&lt;/code&gt;&lt;/pre&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; start=&quot;2&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;개별 응답의 성공 / 실패 분기 처리 : 응답이 한 번에 오더라도 개별 요청마다 성공 여부가 다를 수 있으므로 하나씩 순회하며 상태코드 확인 후 분기 처리해야 함&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;clojure&quot;&gt;&lt;code&gt;{
  &quot;responses&quot;: [
    { &quot;status&quot;: 200, &quot;body&quot;: { ... } },
    { &quot;status&quot;: 404, &quot;body&quot;: { &quot;error&quot;: &quot;Not Found&quot; } }
  ]
}&lt;/code&gt;&lt;/pre&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; start=&quot;3&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Batch 크기 제한 확인 : 서버 성능 보호를 위해 최대 요청 개수 제한이 있기 때문에, 요청을 미리 나눠서 보내야 함&lt;/li&gt;
&lt;/ol&gt;
&lt;pre class=&quot;lisp&quot;&gt;&lt;code&gt;for (int i = 0; i &amp;lt; total; i += batchSize)
{
    var chunk = requests.Skip(i).Take(batchSize).ToList();
    SendBatch(chunk);
}&lt;/code&gt;&lt;/pre&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; start=&quot;4&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;타입 일관성 확인 : 하나의 Batch에서 서로 다른 리소스나 요청 형식이 섞일 경우, API에서 처리 실패할 수 있으므로 요청마다 같은 인증/헤더 조건을 따르는지 확인 필요&lt;/li&gt;
&lt;li&gt;에러 발생 시 롤백 여부 : OpenAI의 Batch API는 &quot;Partial Success&quot; 방식&lt;/li&gt;
&lt;/ol&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;요청 중 일부가 실패해도, 나머지는 정상 처리됨 -&amp;gt; 전체 롤백은 안됨&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;json&quot;&gt;&lt;code&gt;{
  &quot;requests&quot;: [
    { &quot;prompt&quot;: &quot;A cute dog&quot;, &quot;id&quot;: &quot;1&quot; },
    { &quot;prompt&quot;: &quot;&quot;, &quot;id&quot;: &quot;2&quot; },  // 빈 프롬프트 &amp;rarr; 오류 발생
    { &quot;prompt&quot;: &quot;A spaceship&quot;, &quot;id&quot;: &quot;3&quot; }
  ]
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;json&quot;&gt;&lt;code&gt;{
  &quot;results&quot;: [
    { &quot;id&quot;: &quot;1&quot;, &quot;status&quot;: &quot;completed&quot;, &quot;output&quot;: &quot;...&quot; },
    { &quot;id&quot;: &quot;2&quot;, &quot;status&quot;: &quot;failed&quot;, &quot;error&quot;: &quot;Invalid prompt&quot; },
    { &quot;id&quot;: &quot;3&quot;, &quot;status&quot;: &quot;completed&quot;, &quot;output&quot;: &quot;...&quot; }
  ]
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;1번, 3번은 성공이고 2번만 실패 -&amp;gt; status == &quot;failed&quot;인 항목을 찾아 재시도하거나 로깅해야 함&lt;/p&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; start=&quot;6&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;Rate Limit 처리 방식 : 1개의 Batch에 20개가 요청되면, 20번 호출한 것으로 계산됨&lt;/li&gt;
&lt;/ol&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;개별 요청 기준인 경우 : chunk로 분할해서 일정 시간 간격ㅇ로 보내기&lt;/li&gt;
&lt;li&gt;현재 사용량 모니터링 가능 시 : X-RateLimit-Remaining 같은 응답 헤더 확인 후 조절&lt;/li&gt;
&lt;li&gt;실패 시 재시도 : 429 Too Many Requests 발생 시 exponential backoff 재시도 적용&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Web/.Net</category>
      <author>yebin0322</author>
      <guid isPermaLink="true">https://yebin0322.tistory.com/73</guid>
      <comments>https://yebin0322.tistory.com/entry/OpenAI-API%EB%A5%BC-50-%EC%8B%BC-%EA%B0%92%EC%97%90-%ED%98%B8%EC%B6%9C%ED%95%98%EB%8A%94-%EB%B0%A9%EB%B2%95-Batch-API#entry73comment</comments>
      <pubDate>Mon, 14 Apr 2025 13:30:48 +0900</pubDate>
    </item>
    <item>
      <title>ASP.NET 프로젝트 구조와 Spring 프레임워크와의 비교</title>
      <link>https://yebin0322.tistory.com/entry/NET-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EA%B5%AC%EC%A1%B0%EC%99%80-Spring-%ED%94%84%EB%A0%88%EC%9E%84%EC%9B%8C%ED%81%AC%EC%99%80%EC%9D%98-%EB%B9%84%EA%B5%90</link>
      <description>&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;211&quot; data-origin-height=&quot;312&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/EFhs5/btsMVbuDUPt/MYuzLTljkKOAek4kJmpO5k/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/EFhs5/btsMVbuDUPt/MYuzLTljkKOAek4kJmpO5k/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/EFhs5/btsMVbuDUPt/MYuzLTljkKOAek4kJmpO5k/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FEFhs5%2FbtsMVbuDUPt%2FMYuzLTljkKOAek4kJmpO5k%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;211&quot; height=&quot;312&quot; data-origin-width=&quot;211&quot; data-origin-height=&quot;312&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;.NET 프로젝트는 기본적으로 Spring MVC와 비슷한 구조를 가짐&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;ASP.NET&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;C#과 같은 .NET 언어를 사용하여 웹 애플리케이션 개발&lt;/li&gt;
&lt;li&gt;MS에서 제공하는 웹 애플리케이션과 웹 서비스를 개발할 수 있는 프레임워크&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Properties(프로퍼티)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;.NET 프로젝트에서 자동 생성됨&lt;/li&gt;
&lt;li&gt;AssemblyInfo.cs 같은 메타데이터를 담고 있는 파일들이 위치&lt;/li&gt;
&lt;li&gt;역할 : 애플리케이션의 비전, 이름, 저자 등의 정보를 담고 있음&lt;/li&gt;
&lt;li&gt;Spring에서의 src/main/resources&lt;/li&gt;
&lt;li&gt;Spring 프로젝트에서 메타데이터는 주로 application.properties나 application.yml 파일에서 관리&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;2. References(참조)&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;프로젝트에서 사용하는 외부 라이브러리 및 참조된 어셈블리들을 관리&lt;/li&gt;
&lt;li&gt;역할 : 외부 라이브러리나 다른 프로젝트 간의 의존성 관리&lt;/li&gt;
&lt;li&gt;Spring에서의 pom.xml이나 build.gradle&lt;/li&gt;
&lt;li&gt;Spring에서는 Maven이나 Gradle을 사용해 의존성 관리를 하며, pom.xml이나 build.gradle 파일에 라이브러리 의존성 선언&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;3. App_Data&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;데이터 파일이나 애플리케이션에서 사용하는 DB 파일들이 위치하는 폴더&lt;/li&gt;
&lt;li&gt;역할 : DB 파일, XML 파일 등 애플리케이션의 데이터 관련 파일들이 저장됨&lt;/li&gt;
&lt;li&gt;Spring에서의 resources 디렉토리&lt;/li&gt;
&lt;li&gt;Spring에서는 DB 연결 설정을 application.properties에서 하거나, JPA를 사용하여 엔티티 클래스를 생성하고 application.yml에서 연결 설정을 함&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;4. App_Start&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;애플리케이션 시작 시 설정 및 초기화를 담당하는 클래스들이 위치하는 폴더&lt;/li&gt;
&lt;li&gt;역할 : 애플리케이션 초기화 설정, 라우팅 설정, 필터 설정 등 관리&lt;/li&gt;
&lt;li&gt;Spring에서 @Configuration을 사용하여 설정 클래스를 정의하고, JavaConfig나 XML을 사용하여 설정을 관리하는 부분&lt;/li&gt;
&lt;li&gt;Spring에서 @Configuration, Spring Boot에서의 @SpringBootApplication을 통한 초기화 작업&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;5. Content&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;CSS, 이미지, 폰트, JS 파일 등 애플리케이션의 정적 파일들이 위치하는 폴더&lt;/li&gt;
&lt;li&gt;역할 : 스타일시트(CSS), 이미지, 폰트, 정적 자원 파일들 저장&lt;/li&gt;
&lt;li&gt;Spring에서의 src/main/resources/static 또는 src/main/resources/public 디렉토리&lt;/li&gt;
&lt;li&gt;Spring에서는 static 폴더에서 정적 파일을 제공하며, application.properties에서 이를 설정할 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;6. Controllers&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;ASP.NET MVC에서 사용되는 컨트롤러 클래스들이 위치하는 곳&lt;/li&gt;
&lt;li&gt;HTTP 요청을 받아 처리하고, 적절한 뷰나 데이터 반환&lt;/li&gt;
&lt;li&gt;역할 : 사용자 요청을 처리하는 비즈니스 로직을 담고 있는 컨트롤러 클래스가 위치&lt;/li&gt;
&lt;li&gt;Spring에서는 @Controller 어노테이션을 사용하여 요청을 처리하는 컨트롤러 정의&lt;/li&gt;
&lt;li&gt;@Controller 어노테이션을 사용하여 HTTP 요청을 처리하는 클래스들, 그리고 @RequestMapping 등을 사용하여 URL 매핑 설정&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;7. Models&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;애플리케이션에서 사용하는 데이터 모델 클래스들이 위치하는 곳&lt;/li&gt;
&lt;li&gt;DB table과 매핑되는 엔티티 클래스가 들어감&lt;/li&gt;
&lt;li&gt;역할 : DB와 매핑되는 모델 클래스가 위치&lt;/li&gt;
&lt;li&gt;Spring에서는 주로 @Entity 어노테이션을 사용하여 모델 클래스를 정의하고, DB와 매핑&lt;/li&gt;
&lt;li&gt;Spring에서는 주로 JPA를 사용하여 entity class를 정의하고, @Entity, @Id 등을 사용하여 DB와의 매핑 설정&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;8. Scripts&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;JavaScript 파일들이 위치하는 폴더&lt;/li&gt;
&lt;li&gt;jQuery, Angular, Vue.js 등의 JS 라이브러리가 관리됨&lt;/li&gt;
&lt;li&gt;역할 : 클라이언트 사이드에서 사용할 JS 파일들 위치&lt;/li&gt;
&lt;li&gt;Spring에서의 src/main/resources/static/js 폴더&lt;/li&gt;
&lt;li&gt;Spring에서는 JS파일을 static 폴더에 배치하고, 필요한 경우 JS 프레임워크와 라이브러리 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;9. Views&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;사용자에게 보여줄 HTML 콘텐츠를 담고 있는 Razor 뷰 파일들이 위치하는 폴더&lt;/li&gt;
&lt;li&gt;역할 : 웹 페이지에서 사용자에게 출력할 뷰 템플릿이 위치&lt;/li&gt;
&lt;li&gt;Spring에서는 src/main/resources/templates 폴더에 Thymeleaf 또는 JSP 파일들이 위치&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;10. favicon.ico&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;브라우저 탭에 표시되는 아이콘 파일&lt;/li&gt;
&lt;li&gt;Spring에서는 static 폴더에 favicon.ico 파일을 두어 브라우저에서 표시될 아이콘을 관리&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;11. Global.asax&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;애플리케이션의 전역 이벤트(애플리케이션 시작, 종료, 오류 처리 등)를 처리하는 파일&lt;/li&gt;
&lt;li&gt;역할 : 애플리케이션의 전역 이벤트를 처리&lt;ul&gt;
&lt;li&gt;애플리케이션 시작 시 필요한 초기화 작업&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Spring에서는 web.xml 또는 ServletInitializer 클래스를 통해 애플리케이션의 초기화 및 전역적인 설정을 함&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;12. packages.config&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;NuGet 패키지 관리 파일로, 프로젝트에서 사용하는 외부 패키지들에 대한 정보를 관리&lt;/li&gt;
&lt;li&gt;역할 : NuGet 패키지 의존성 정보를 관리&lt;/li&gt;
&lt;li&gt;Spring에서는 의존성 관리 도구로 Maven이나 Gradle을 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;13. Web.config&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;ASP.NET 애플리케이션의 설정 파일&lt;/li&gt;
&lt;li&gt;보안 설정, 데이터베이스 연결 문자열, 애플리케이션 설정 등을 담고 있음&lt;/li&gt;
&lt;li&gt;역할 : 애플리케이션의 설정과 환경 설정을 관리&lt;/li&gt;
&lt;li&gt;Spring에서는 application.properties 또는 application.yml파일을 사용하여 환경을 설정&lt;/li&gt;
&lt;/ul&gt;</description>
      <category>Web/.Net</category>
      <author>yebin0322</author>
      <guid isPermaLink="true">https://yebin0322.tistory.com/71</guid>
      <comments>https://yebin0322.tistory.com/entry/NET-%ED%94%84%EB%A1%9C%EC%A0%9D%ED%8A%B8-%EA%B5%AC%EC%A1%B0%EC%99%80-Spring-%ED%94%84%EB%A0%88%EC%9E%84%EC%9B%8C%ED%81%AC%EC%99%80%EC%9D%98-%EB%B9%84%EA%B5%90#entry71comment</comments>
      <pubDate>Wed, 26 Mar 2025 12:02:59 +0900</pubDate>
    </item>
    <item>
      <title>C#의 소개와 특징, 문법, JAVA와의 비교</title>
      <link>https://yebin0322.tistory.com/entry/C%EC%9D%98-%EC%86%8C%EA%B0%9C%EC%99%80-%ED%8A%B9%EC%A7%95-%EB%AC%B8%EB%B2%95-JAVA%EC%99%80%EC%9D%98-%EB%B9%84%EA%B5%90</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;C#(C-Sharp)&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;MS가 개발한 객체지향 프로그래밍 언어&lt;/li&gt;
&lt;li&gt;.NET 프레임워크와 함께 사용되며, 윈도우, 웹, 모바일, 클라우드 기반 등 다양한 플랫폼에서 실행되는 소프트웨어를 개발할 수 있도록 설계됨&lt;/li&gt;
&lt;li&gt;JAVA와 유사한 문법을 갖고 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 data-ke-size=&quot;size23&quot;&gt;주요 특징&lt;/h3&gt;
&lt;ol style=&quot;list-style-type: decimal;&quot; data-ke-list-type=&quot;decimal&quot;&gt;
&lt;li&gt;객체지향(OOP) 언어 : 클래스와 객체를 중심으로 프로그램 작성&lt;/li&gt;
&lt;li&gt;타입 안전성(Type Safety) : 컴파일 시간에 타입 오류를 잡을 수 있음&lt;/li&gt;
&lt;li&gt;메모리 관리 : Garbage Collection을 통해 자동으로 메모리를 관리&lt;/li&gt;
&lt;li&gt;다양한 플랫폼 지원 : .Net Core와 Xamarin 등을 통해 Windows, Linux, macOS, iOS, Android 등 다양한 플랫폼에서 실행되는 애플리케이션을 만들 수 있음&lt;/li&gt;
&lt;li&gt;언어 통합 쿼리(LINQ) : 데이터 쿼리를 객체지향 방식으로 처리할 수 있도록 LINQ 제공&lt;/li&gt;
&lt;li&gt;비동기 프로그래밍 : async와 await 키워드를 통해 비동기 작업을 쉽게 처리할 수 있음&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;문법&lt;/h2&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&lt;span&gt;&amp;nbsp;1. 데이터 타입(Data Types)&lt;/span&gt;&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc; color: #333333; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;JAVA와 나머지 기본 타입 비슷&lt;/li&gt;
&lt;li&gt;JAVA에서는 boolean, C#에서는 bool 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JAVA :&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1742947617999&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;boolean isActive = true;&lt;/code&gt;&lt;/pre&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p style=&quot;color: #333333; text-align: start;&quot; data-ke-size=&quot;size16&quot;&gt;C# :&lt;/p&gt;
&lt;pre id=&quot;code_1742947662977&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;bool isActive = 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;2. 클래스(Class)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;JAVA에서와 동일하게 class 키워드를 사용&lt;/li&gt;
&lt;li&gt;클래스 내의 변수와 메소드에 접근 제어자를 지정해 주어야 함 -&amp;gt; 자바에서처럼 default 접근 제어자가 자동으로 적용되지 않음&lt;/li&gt;
&lt;li&gt;접근 제어자를 지정하지 않으면 컴파일 오류 발생&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JAVA :&lt;/p&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;class Car {
    String color;

    void start() {
        System.out.println(&quot;Car is starting&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;C# :&lt;/p&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;class Car {
    public string color;

    public void Start() {
        Console.WriteLine(&quot;Car is starting&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실습 :&lt;/p&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;using System;

class Car {
    public string color;

    public void Start() {
        Console.WriteLine(&quot;Car is starting&quot;);
    }
}

class Program {
    static void Main(String[] args) {
        Car myCar = new Car();
        myCar.color = &quot;Red&quot;;
        myCar.Start();
        Console.WriteLine(&quot;Car color : &quot; + myCar.color);
    }
}&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;3. 인터페이스(Interface)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;JAVA와 비슷하게, 인터페이스는 구현을 강제하는 메소드의 집합&lt;/li&gt;
&lt;li&gt;C#에서는 인터페이스 이름에 I를 붙이는 것이 관습임&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JAVA :&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;interface Vehicle {
    void Start();
}

class Car implements Vehicle {
    public void Start() {
        System.out.println(&quot;Car is starting&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;C# :&lt;/p&gt;
&lt;pre class=&quot;angelscript&quot;&gt;&lt;code&gt;interface IVehicle {
    void Start();
}

class Car : IVehicle {
    public void Start() {
        Console.WriteLine(&quot;Car is starting&quot;);
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실습 :&amp;nbsp;&lt;/p&gt;
&lt;pre class=&quot;cs&quot;&gt;&lt;code&gt;using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp1 {
    interface IVehicle {
        void Start();
    }
    class Car : IVehicle {
        public void Start() {
            Console.WriteLine(&quot;Car is starting&quot;);
        }
    }
    class Program {
        static void Main(string[] args) {
            IVehicle myCar = new Car();
            myCar.Start();
        }
    }
}&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;4. 상속(Inheritance)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;: base 키워드를 사용하여 부모 클래스 지정&lt;/li&gt;
&lt;li&gt;부모 클래스는 base 클래스, 자식 클래스는 derived 클래스라고 함&lt;/li&gt;
&lt;li&gt;virtual : 메소드 오버라이딩을 허용한다는 의미&lt;/li&gt;
&lt;li&gt;C#에서는 virtual 키워드를 사용해 부모 클래스에서 오버라이딩을 허용하는 메소드를 선언하고, 자식 클래스에서는 override 키워드로 메소드를 오버라이딩 함&lt;/li&gt;
&lt;li&gt;JAVA에서는 @Override 어노테이션을 사용하여 메소드 오버라이딩을 명시함&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JAVA :&lt;/p&gt;
&lt;pre class=&quot;scala&quot;&gt;&lt;code&gt;class Animal {
    void sound() {
        System.out.println(&quot;Some sound&quot;);
    }
}

class Dog extends Animal {
    void sound() {
        System.out.println(&quot;Bark&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;C# :&lt;/p&gt;
&lt;pre class=&quot;bash&quot; data-ke-language=&quot;bash&quot;&gt;&lt;code&gt; class Animal {
     public virtual void Sound() {
         Console.WriteLine(&quot;Some sound&quot;);
     }
 }
 class Dog : Animal {
     public override void Sound() {
         Console.WriteLine(&quot;Bark&quot;);
     }&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;실습 :&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1742947906401&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp1 {
    class Animal {
        public virtual void Sound() {
            Console.WriteLine(&quot;Some sound&quot;);
        }
    }
    class Dog : Animal {
        public override void Sound() {
            Console.WriteLine(&quot;Bark&quot;);
        }

        static void Main(string[] args) {
            Animal animal = new Dog();
            animal.Sound();
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;5. 조건문(If-Else Statement)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc; color: #333333; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;문법이 같음&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;6. 반복문(Looping)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc; color: #333333; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;문법이 같음&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;7. 생성자(Constructor)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc; color: #333333; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;문법이 같음&lt;/li&gt;
&lt;li&gt;C#에서는 생성자에 접근 제어자를 명시적으로 작성해 주어야 함&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JAVA :&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1742948424531&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Car {
	String model;
    
    //생성자
    Car(String model) {
    	this.model = model;
    }
}&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;C# :&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1742948454078&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Car {
	public string model;
    
    //생성자
    public Car(string model) {
    	this.model = model;
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;8. 프로퍼티(Property)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc; color: #333333; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;C#에서는 멤버 변수에 대한 접근을 직접 제공하는 대신, 프로퍼티를 사용하는 것이 일반적&lt;/li&gt;
&lt;li&gt;C#에서는 get과 set을 통해 멤버 변수에 접근할 수 있는 프로퍼티를 정의할 수 있음&lt;/li&gt;
&lt;li&gt;JAVA에서는 직접 메소드를 사용해 접근&amp;nbsp;&lt;/li&gt;
&lt;li&gt;객체의 필드를 읽고 수정할 수 있는 것 -&amp;gt; get과 set 블록을 사용하여 값을 가져오거나 설정할 수 있음&lt;/li&gt;
&lt;li&gt;JAVA에서의 getter, setter와 같은 개념이지만, C#에서는 프로퍼티를 사용하면 &lt;b&gt;자동으로 get이나 set이 호출됨&lt;/b&gt; -&amp;gt; 아래 예시에서 &lt;b&gt;myCar.Model이 읽기인 경우 get이 호출되고, 쓰기일 경우 set이 호출됨&lt;/b&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JAVA :&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1742949735231&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;class Car {
	private String model; //private 필드
    
    //getter 메소드
    public String getModel() {
    	return model;
    }
    
    //setter 메소드
    public void setModel(String model) {
    	this.model = model;
    }&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1742949790465&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;public class Main {
	public static void main(String[] args) {
    	Car myCar = new Car();
        myCar.setModel(&quot;Tesla&quot;); //setter를 사용하여 값을 설정
        System.out.println(myCar.getModel()); //getter를 사용하여 값 출력
    }
}&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;C# :&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1742949655960&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;namespace ConsoleApp1 {
    class Car {
        private string model; //private 필드

        //프로퍼티 정의
        public string Model {
            get { return model; } //값을 가져오는 get
            set { model = value; } //값을 설정하는 set
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1742949665272&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;using ConsoleApp1;

class Program {
    static void Main() {
        Car myCar = new Car();
        myCar.Model = &quot;Tesla&quot;; //set을 사용하여 값을 설정
        Console.WriteLine(myCar.Model); //get을 사용하여 값을 출력

    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;&amp;nbsp;&lt;/h3&gt;
&lt;h3 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size23&quot;&gt;9. 예외 처리 구문(Exceptin Handling Syntax)&lt;/h3&gt;
&lt;ul style=&quot;list-style-type: disc; color: #333333; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;JAVA와 C# 모두 예외 처리의 기본적인 구조는 거의 같음(두 언어 모두 try, catch, finally 구문을 사용하여 예외 처리)&lt;/li&gt;
&lt;li&gt;예외 클래스는 언어마다 다름
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;JAVA에서는 산술 오류를 처리할 때 ArithmeticException 사용&lt;/li&gt;
&lt;li&gt;C#에서는 DivideByZeroException(System namespace에 포함되어 있음)을 사용하여 0으로 나누는 오류를 처리&amp;nbsp;&amp;nbsp;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;JAVA :&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1742948755135&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;try {
	int result = 10 / 0; //ArithmeticException 발생
} catch (ArithmeticException e) {
	System.out.println(&quot;Cannot divide by zero&quot;); //예외 처리
} finally {
	System.out.println(&quot;Finally block executed&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;C# :&amp;nbsp;&lt;/p&gt;
&lt;pre id=&quot;code_1742948855843&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;try {
	int result = 10 / 0; //DivideByZeroException 발생
} catch (DivideByZeroException e) {
	Console.WriteLine(&quot;Cannot divide by zero&quot;); //예외 처리
} finally {
	Console.WriteLine(&quot;Finally block executed&quot;);
}&lt;/code&gt;&lt;/pre&gt;</description>
      <category>C#</category>
      <author>yebin0322</author>
      <guid isPermaLink="true">https://yebin0322.tistory.com/70</guid>
      <comments>https://yebin0322.tistory.com/entry/C%EC%9D%98-%EC%86%8C%EA%B0%9C%EC%99%80-%ED%8A%B9%EC%A7%95-%EB%AC%B8%EB%B2%95-JAVA%EC%99%80%EC%9D%98-%EB%B9%84%EA%B5%90#entry70comment</comments>
      <pubDate>Wed, 26 Mar 2025 09:51:55 +0900</pubDate>
    </item>
    <item>
      <title>[프로그래머스, SQL] 가격이 제일 비싼 식품의 정보 출력하기</title>
      <link>https://yebin0322.tistory.com/entry/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-SQL-%EA%B0%80%EA%B2%A9%EC%9D%B4-%EC%A0%9C%EC%9D%BC-%EB%B9%84%EC%8B%BC-%EC%8B%9D%ED%92%88%EC%9D%98-%EC%A0%95%EB%B3%B4-%EC%B6%9C%EB%A0%A5%ED%95%98%EA%B8%B0</link>
      <description>&lt;p data-ke-size=&quot;size16&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/131115&quot; target=&quot;_blank&quot; rel=&quot;noopener&amp;nbsp;noreferrer&quot;&gt;https://school.programmers.co.kr/learn/courses/30/lessons/131115&lt;/a&gt;&lt;/p&gt;
&lt;figure id=&quot;og_1742901884762&quot; contenteditable=&quot;false&quot; data-ke-type=&quot;opengraph&quot; data-ke-align=&quot;alignCenter&quot; data-og-type=&quot;website&quot; data-og-title=&quot;프로그래머스&quot; data-og-description=&quot;SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프&quot; data-og-host=&quot;programmers.co.kr&quot; data-og-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/131115&quot; data-og-url=&quot;https://programmers.co.kr/&quot; data-og-image=&quot;https://scrap.kakaocdn.net/dn/zEZVt/hyYvqlz0hG/UlhK0ouqfjrxFMSuCTQbB1/img.png?width=1920&amp;amp;height=960&amp;amp;face=0_0_1920_960,https://scrap.kakaocdn.net/dn/BHyBi/hyYvrdIwSK/4AYkg1vKfZpIgXi4hnjNMK/img.png?width=1920&amp;amp;height=960&amp;amp;face=0_0_1920_960&quot;&gt;&lt;a href=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/131115&quot; target=&quot;_blank&quot; rel=&quot;noopener&quot; data-source-url=&quot;https://school.programmers.co.kr/learn/courses/30/lessons/131115&quot;&gt;
&lt;div class=&quot;og-image&quot; style=&quot;background-image: url('https://scrap.kakaocdn.net/dn/zEZVt/hyYvqlz0hG/UlhK0ouqfjrxFMSuCTQbB1/img.png?width=1920&amp;amp;height=960&amp;amp;face=0_0_1920_960,https://scrap.kakaocdn.net/dn/BHyBi/hyYvrdIwSK/4AYkg1vKfZpIgXi4hnjNMK/img.png?width=1920&amp;amp;height=960&amp;amp;face=0_0_1920_960');&quot;&gt;&amp;nbsp;&lt;/div&gt;
&lt;div class=&quot;og-text&quot;&gt;
&lt;p class=&quot;og-title&quot; data-ke-size=&quot;size16&quot;&gt;프로그래머스&lt;/p&gt;
&lt;p class=&quot;og-desc&quot; data-ke-size=&quot;size16&quot;&gt;SW개발자를 위한 평가, 교육, 채용까지 Total Solution을 제공하는 개발자 성장을 위한 베이스캠프&lt;/p&gt;
&lt;p class=&quot;og-host&quot; data-ke-size=&quot;size16&quot;&gt;programmers.co.kr&lt;/p&gt;
&lt;/div&gt;
&lt;/a&gt;&lt;/figure&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 data-ke-size=&quot;size26&quot;&gt;방법 1 : 집계 함수(Aggregate Function) 이용&lt;/h2&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;- 집계 함수 : 여러 행의 데이터를 하나의 값으로 요약 -&amp;gt; select문과 함께 사용해야 함&lt;/p&gt;
&lt;pre id=&quot;code_1742901939026&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;SELECT *
FROM FOOD_PRODUCT
WHERE PRICE = (
    SELECT MAX(PRICE)
    FROM FOOD_PRODUCT
);&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;방법 2 : 정렬해서 맨 위에꺼만 뽑기&lt;/h2&gt;
&lt;pre id=&quot;code_1742902143331&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;SELECT 
    PRODUCT_ID, PRODUCT_NAME, PRODUCT_CD, CATEGORY, PRICE
FROM
    FOOD_PRODUCT
ORDER BY PRICE DESC
LIMIT 1;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;figure class=&quot;imageblock alignCenter&quot; data-ke-mobileStyle=&quot;widthOrigin&quot; data-origin-width=&quot;1190&quot; data-origin-height=&quot;558&quot;&gt;&lt;span data-url=&quot;https://blog.kakaocdn.net/dn/dmnMPD/btsMVhg5E1I/ThVDpJMeJlOhAaymU2zsx0/img.png&quot; data-phocus=&quot;https://blog.kakaocdn.net/dn/dmnMPD/btsMVhg5E1I/ThVDpJMeJlOhAaymU2zsx0/img.png&quot;&gt;&lt;img src=&quot;https://blog.kakaocdn.net/dn/dmnMPD/btsMVhg5E1I/ThVDpJMeJlOhAaymU2zsx0/img.png&quot; srcset=&quot;https://img1.daumcdn.net/thumb/R1280x0/?scode=mtistory2&amp;fname=https%3A%2F%2Fblog.kakaocdn.net%2Fdn%2FdmnMPD%2FbtsMVhg5E1I%2FThVDpJMeJlOhAaymU2zsx0%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;1190&quot; height=&quot;558&quot; data-origin-width=&quot;1190&quot; data-origin-height=&quot;558&quot;/&gt;&lt;/span&gt;&lt;/figure&gt;
&lt;/p&gt;</description>
      <category>JAVA/Coding Test 준비</category>
      <author>yebin0322</author>
      <guid isPermaLink="true">https://yebin0322.tistory.com/69</guid>
      <comments>https://yebin0322.tistory.com/entry/%ED%94%84%EB%A1%9C%EA%B7%B8%EB%9E%98%EB%A8%B8%EC%8A%A4-SQL-%EA%B0%80%EA%B2%A9%EC%9D%B4-%EC%A0%9C%EC%9D%BC-%EB%B9%84%EC%8B%BC-%EC%8B%9D%ED%92%88%EC%9D%98-%EC%A0%95%EB%B3%B4-%EC%B6%9C%EB%A0%A5%ED%95%98%EA%B8%B0#entry69comment</comments>
      <pubDate>Tue, 25 Mar 2025 20:24:13 +0900</pubDate>
    </item>
    <item>
      <title>Map</title>
      <link>https://yebin0322.tistory.com/entry/Map</link>
      <description>&lt;h2 data-ke-size=&quot;size26&quot;&gt;Map.entrySet()&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;보통 Map은 keySet()으로 키만 가져오거나 values()로 값만 가져올 수 있음&lt;/li&gt;
&lt;li&gt;&lt;b&gt;키와 값이 함께 필요할 때&lt;/b&gt; entrySet() 사용&lt;/li&gt;
&lt;li&gt;entrySet()을 사용하면 Map에 있는 &amp;lt;Key, Value&amp;gt; 쌍을 Set&amp;lt;Map.Entry&amp;lt;K, V&amp;gt;&amp;gt; 형태로 반환&lt;/li&gt;
&lt;li&gt;getKey(), getValue()메소드를 사용해 각각 키와 값을 얻을 수 있음&lt;/li&gt;
&lt;/ul&gt;
&lt;pre class=&quot;arduino&quot;&gt;&lt;code&gt;package Map;

import java.util.HashMap;
import java.util.Map;

public class EntrySet {
    public static void main(String[] args){
        Map&amp;lt;String, Integer&amp;gt; map = new HashMap&amp;lt;&amp;gt;();
        map.put(&quot;Apple&quot;, 3);
        map.put(&quot;Banana&quot;, 5);
        map.put(&quot;Cherry&quot;, 7);

        //entrySet()을 사용해 전체 출력
        for(Map.Entry&amp;lt;String, Integer&amp;gt; entry : map.entrySet()){
            System.out.println(&quot;Key: &quot; + entry.getKey() + &quot; Value: &quot; + entry.getValue());
        }
    }
}
&lt;/code&gt;&lt;/pre&gt;
&lt;pre class=&quot;groovy&quot;&gt;&lt;code&gt;Key: Apple Value: 3
Key: Cherry Value: 7
Key: Banana Value: 5&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Map.keySet()&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc; color: #333333; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Map에 저장된 모든 키(key)만 모아서 Set&amp;lt;K&amp;gt; 형태로 반환하는 메소드&lt;/li&gt;
&lt;li&gt;Map에서 모든 키를 가져와서 반복문을 돌리거나 특정 키를 찾을 때 유용&lt;/li&gt;
&lt;li&gt;반복문에서 map.get(key)를 계속 호출하면 성능이 저하됨 -&amp;gt; entrySet()을 사용해 한 번에 키-값을 가져와야 함&lt;/li&gt;
&lt;li&gt;반환된 Set을 수정하면 Map도 변경됨 -&amp;gt; map.keySet().remove(&quot;Apple&quot;)을 하면 map에서도 &quot;Apple&quot;이 삭제됨&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1742815773667&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package Map;

import java.util.HashMap;
import java.util.Map;

public class KeySet {
    public static void main(String[] args){
        Map&amp;lt;String, Integer&amp;gt; map = new HashMap&amp;lt;&amp;gt;();
        map.put(&quot;Apple&quot;, 3);
        map.put(&quot;Banana&quot;, 5);
        map.put(&quot;Cherry&quot;, 7);

        //keySet()을 사용하여 전체 키 출력
        for(String key : map.keySet()){
            System.out.println(key);
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1742815806125&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Apple
Cherry
Banana&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Map.get()&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc; color: #333333; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;주어진 키(key)에 해당하는 값을 반환하는 메소드&lt;/li&gt;
&lt;li&gt;Map에서 특정 키에 저장된 값을 가져올 때 사용&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1742815651133&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package Map;

import java.util.HashMap;
import java.util.Map;

public class Get {
    public static void main(String[] args){
        Map&amp;lt;String, Integer&amp;gt; map = new HashMap&amp;lt;&amp;gt;();
        map.put(&quot;Apple&quot;, 3);
        map.put(&quot;Banana&quot;, 5);
        map.put(&quot;Cherry&quot;, 7);

        System.out.println(&quot;Apple 개수 : &quot; + map.get(&quot;Apple&quot;));
        System.out.println(&quot;Banana 개수 : &quot; + map.get(&quot;Banana&quot;));
        System.out.println(&quot;Grape 개수 : &quot; + map.get(&quot;Grape&quot;));
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1742815661790&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Apple 개수 : 3
Banana 개수 : 5
Grape 개수 : null&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Map.values()&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc; color: #333333; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;해당 map의 value 목록을 Collection&amp;lt;V&amp;gt; 형태로 return&lt;/li&gt;
&lt;li&gt;key는 필요 없고 값만 갖고 오고 싶을 때 유용&lt;/li&gt;
&lt;li&gt;중복이 있어도 모두 포함됨&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1742816495415&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package Map;

import java.util.HashMap;
import java.util.Map;

public class Values {
    public static void main(String[] args){
        Map&amp;lt;String, Integer&amp;gt; map = new HashMap&amp;lt;&amp;gt;();
        map.put(&quot;Apple&quot;, 3);
        map.put(&quot;Banana&quot;, 5);
        map.put(&quot;Cherry&quot;, 7);
        
        //values()를 사용하여 전체 값 출력
        for(Integer value : map.values()){
            System.out.println(value);
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1742816504964&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;3
7
5&lt;/code&gt;&lt;/pre&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;Map.entrySet().Iterator()&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc; color: #333333; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Map의 key-value 쌍(Entry)을 순차적으로 탐색할 수 있도록 Iterator를 반환하는 코드&lt;/li&gt;
&lt;li&gt;Map을 Iterator를 사용해 반복하면서 요소를 하나씩 가져오거나 삭제할 때 유용&lt;/li&gt;
&lt;li&gt;요소 삭제가 필요할 때 사용하면 좋음 -&amp;gt; 요소 삭제 시 안전함&amp;nbsp;
&lt;ul style=&quot;list-style-type: disc;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;map.entrySet() -&amp;gt; Set&amp;lt;Map.Entry&amp;lt;K, V&amp;gt;&amp;gt; 반환&lt;/li&gt;
&lt;li&gt;.Iterator() -&amp;gt; set에 대한 Iterator&amp;lt;Map.Entry&amp;lt;K, V&amp;gt;&amp;gt; 생성&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1742816974278&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package Map;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

public class EntrySetIterator {
    public static void main(String[] args){
        Map&amp;lt;String, Integer&amp;gt; map = new HashMap&amp;lt;&amp;gt;();
        map.put(&quot;Apple&quot;, 3);
        map.put(&quot;Banana&quot;, 5);
        map.put(&quot;Cherry&quot;, 7);

        Iterator&amp;lt;Entry&amp;lt;String, Integer&amp;gt;&amp;gt; iterator = map.entrySet().iterator();

        while (iterator.hasNext()){
            Map.Entry&amp;lt;String, Integer&amp;gt; entry = iterator.next();
            System.out.println(entry.getKey() + &quot; &quot; + entry.getValue());
        }
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1742816982577&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Apple 3
Cherry 7
Banana 5&lt;/code&gt;&lt;/pre&gt;
&lt;p data-ke-size=&quot;size16&quot;&gt;&amp;nbsp;&lt;/p&gt;
&lt;h2 style=&quot;color: #000000; text-align: start;&quot; data-ke-size=&quot;size26&quot;&gt;forEach()&lt;/h2&gt;
&lt;ul style=&quot;list-style-type: disc; color: #333333; text-align: start;&quot; data-ke-list-type=&quot;disc&quot;&gt;
&lt;li&gt;Map의 각 요소(key-value)를 순회하는 메소드&lt;/li&gt;
&lt;li&gt;Java 8부터 람다식(Lambda Expression)을 활용한 forEach() 메소드 도입&lt;/li&gt;
&lt;li&gt;단순 조회 시 사용하면 좋음&lt;/li&gt;
&lt;li&gt;내부적으로 entrySet()을 사용함&lt;/li&gt;
&lt;/ul&gt;
&lt;pre id=&quot;code_1742817196736&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;package Map;

import java.util.HashMap;
import java.util.Map;

public class ForEach {
    public static void main(String[] args) {
        Map&amp;lt;String, Integer&amp;gt; map = new HashMap&amp;lt;&amp;gt;();
        map.put(&quot;Apple&quot;, 3);
        map.put(&quot;Banana&quot;, 5);
        map.put(&quot;Cherry&quot;, 7);

        map.forEach((key, value) -&amp;gt; {
            System.out.print(key + &quot; &quot; + value);
        });
    }
}&lt;/code&gt;&lt;/pre&gt;
&lt;pre id=&quot;code_1742817203559&quot; class=&quot;bash&quot; data-ke-language=&quot;bash&quot; data-ke-type=&quot;codeblock&quot;&gt;&lt;code&gt;Apple 3
Cherry 7
Banana 5&lt;/code&gt;&lt;/pre&gt;</description>
      <category>JAVA/Coding Test 준비</category>
      <author>yebin0322</author>
      <guid isPermaLink="true">https://yebin0322.tistory.com/67</guid>
      <comments>https://yebin0322.tistory.com/entry/Map#entry67comment</comments>
      <pubDate>Mon, 24 Mar 2025 20:55:15 +0900</pubDate>
    </item>
  </channel>
</rss>