<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>molamola.log</title>
        <link>https://velog.io/</link>
        <description></description>
        <lastBuildDate>Wed, 14 May 2025 00:51:57 GMT</lastBuildDate>
        <docs>https://validator.w3.org/feed/docs/rss2.html</docs>
        <generator>https://github.com/jpmonette/feed</generator>
        <image>
            <title>molamola.log</title>
            <url>https://velog.velcdn.com/images/hwan2-dev/profile/c6930498-3847-4a32-bbb0-4658635a882e/image.png</url>
            <link>https://velog.io/</link>
        </image>
        <copyright>Copyright (C) 2019. molamola.log. All rights reserved.</copyright>
        <atom:link href="https://v2.velog.io/rss/hwan2-dev" rel="self" type="application/rss+xml"/>
        <item>
            <title><![CDATA[Salesforce OAuth 2.0 Access Token 획득 방식 총정리]]></title>
            <link>https://velog.io/@hwan2-dev/Salesforce-OAuth-2.0-Access-Token-%ED%9A%8D%EB%93%9D-%EB%B0%A9%EC%8B%9D-%EC%B4%9D%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@hwan2-dev/Salesforce-OAuth-2.0-Access-Token-%ED%9A%8D%EB%93%9D-%EB%B0%A9%EC%8B%9D-%EC%B4%9D%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Wed, 14 May 2025 00:51:57 GMT</pubDate>
            <description><![CDATA[<p>Salesforce API와 통합하기 위해서는 가장 먼저 <strong>Access Token</strong>을 발급받아야 합니다. Salesforce는 OAuth 2.0 표준을 따르며, 다양한 인증 방식(Grant Type)을 제공합니다.</p>
<hr>
<h2 id="✅-oauth-20-access-token이란">✅ OAuth 2.0 Access Token이란?</h2>
<p>Access Token은 Salesforce에 API 요청을 보낼 수 있게 해주는 <strong>인증된 키</strong>입니다.
하지만 이 토큰은 사용자 인증 방식에 따라 얻는 방법이 다르며, <strong>단기 또는 장기 세션 유지 여부</strong>에도 영향을 줍니다.</p>
<hr>
<h2 id="📦-salesforce-oauth-20-인증-방식-정리">📦 Salesforce OAuth 2.0 인증 방식 정리</h2>
<table>
<thead>
<tr>
<th>인증 방식 (Grant Type)</th>
<th>설명</th>
<th>Refresh Token</th>
<th>사용자 로그인 필요</th>
<th>사용 예시</th>
</tr>
</thead>
<tbody><tr>
<td><code>authorization_code</code></td>
<td>사용자가 로그인하여 승인 코드를 받아 토큰 발급</td>
<td>✅ 지원</td>
<td>✅</td>
<td>Web App</td>
</tr>
<tr>
<td><code>password</code></td>
<td>사용자 ID, PW 직접 입력</td>
<td>✅ (조건부)</td>
<td>❌</td>
<td>백오피스, 테스트</td>
</tr>
<tr>
<td><code>client_credentials</code></td>
<td>앱 자체 인증 (M2M)</td>
<td>❌</td>
<td>❌</td>
<td>백엔드 to Salesforce</td>
</tr>
<tr>
<td><code>jwt_bearer</code></td>
<td>JWT로 서명된 토큰으로 인증</td>
<td>❌</td>
<td>❌</td>
<td>서버 자동화, CI/CD</td>
</tr>
<tr>
<td><code>device_code</code></td>
<td>디바이스에서 브라우저 없는 인증</td>
<td>✅</td>
<td>✅</td>
<td>IoT, TV 앱 등</td>
</tr>
<tr>
<td><code>refresh_token</code></td>
<td>기존 토큰으로 새 토큰 재발급</td>
<td>🔁</td>
<td>❌</td>
<td>세션 연장</td>
</tr>
<tr>
<td><code>saml2-bearer</code></td>
<td>SAML 기반의 인증 연동</td>
<td>❌</td>
<td>❌</td>
<td>SSO 시스템</td>
</tr>
</tbody></table>
<hr>
<h2 id="🔍-주요-인증-방식-자세히-보기">🔍 주요 인증 방식 자세히 보기</h2>
<h3 id="1️⃣-authorization-code-flow-authorization_code">1️⃣ Authorization Code Flow (<code>authorization_code</code>)</h3>
<blockquote>
<p>사용자 로그인을 통해 Salesforce가 승인 코드를 발급 → 이를 통해 Access Token 획득</p>
</blockquote>
<p><strong>특징:</strong></p>
<ul>
<li>가장 안전하고 표준적인 방식</li>
<li>사용자 인증이 필요</li>
<li><code>refresh_token</code>도 함께 받을 수 있어 장기 세션 유지 가능</li>
</ul>
<p><strong>사용 예시:</strong></p>
<ul>
<li>Salesforce를 연동하는 웹앱</li>
<li>마케팅/고객 관리 SaaS</li>
</ul>
<hr>
<h3 id="2️⃣-username-password-flow-password">2️⃣ Username-Password Flow (<code>password</code>)</h3>
<blockquote>
<p>사용자 ID, 비밀번호, 보안 토큰을 직접 입력하여 Access Token 발급</p>
</blockquote>
<p><strong>특징:</strong></p>
<ul>
<li>로그인 UI 없이 토큰 발급 가능</li>
<li>보안상 위험도가 높아 <strong>실제 서비스에서는 권장되지 않음</strong></li>
<li><code>refresh_token</code> 발급은 Connected App 설정에 따라 가능</li>
</ul>
<p><strong>사용 예시:</strong></p>
<ul>
<li>테스트 자동화</li>
<li>내부 관리툴</li>
</ul>
<hr>
<h3 id="3️⃣-client-credentials-flow-client_credentials">3️⃣ Client Credentials Flow (<code>client_credentials</code>)</h3>
<blockquote>
<p>앱 자체가 Salesforce 리소스에 접근할 수 있도록 인증 (사용자 없음)</p>
</blockquote>
<p><strong>특징:</strong></p>
<ul>
<li>Machine-to-Machine 인증</li>
<li>사용자 개입 없이 서버 간 통신</li>
<li><code>refresh_token</code> 없음</li>
</ul>
<p><strong>사용 예시:</strong></p>
<ul>
<li>서버 백엔드에서 Salesforce 데이터를 주기적으로 조회</li>
</ul>
<p><strong>주의:</strong></p>
<ul>
<li>Salesforce에서는 이 Flow를 사용하려면 <strong>Connected App에서 Client Credentials Flow 허용 + 사용자 연결</strong> 필요</li>
</ul>
<hr>
<h3 id="4️⃣-jwt-bearer-flow-jwt_bearer">4️⃣ JWT Bearer Flow (<code>jwt_bearer</code>)</h3>
<blockquote>
<p>사전에 등록된 사용자와 비밀 키를 사용하여 서명된 JWT를 제출 → Access Token 발급</p>
</blockquote>
<p><strong>특징:</strong></p>
<ul>
<li>사용자 로그인 없이 무인 인증 가능</li>
<li><code>refresh_token</code> 없음</li>
<li>고도화된 자동화/보안에 적합</li>
</ul>
<p><strong>사용 예시:</strong></p>
<ul>
<li>CI/CD 파이프라인</li>
<li>서버-to-Salesforce 인증 연동</li>
</ul>
<hr>
<h3 id="5️⃣-device-flow-device_code">5️⃣ Device Flow (<code>device_code</code>)</h3>
<blockquote>
<p>디바이스(예: TV, 콘솔)에서 브라우저 없이 인증 수행</p>
</blockquote>
<p><strong>특징:</strong></p>
<ul>
<li>사용자 브라우저에서 인증 진행</li>
<li>디바이스는 승인 여부만 폴링</li>
<li><code>refresh_token</code> 발급 가능</li>
</ul>
<p><strong>사용 예시:</strong></p>
<ul>
<li>POS, IoT, 터치스크린 등에서 Salesforce 인증</li>
</ul>
<hr>
<h3 id="6️⃣-refresh-token-flow-refresh_token">6️⃣ Refresh Token Flow (<code>refresh_token</code>)</h3>
<blockquote>
<p>기존에 받은 Refresh Token을 사용하여 새 Access Token을 재발급</p>
</blockquote>
<p><strong>특징:</strong></p>
<ul>
<li>사용자가 다시 로그인하지 않아도 됨</li>
<li>자동 로그인/세션 유지에 필수</li>
</ul>
<p><strong>사용 예시:</strong></p>
<ul>
<li>모바일 앱의 자동 로그인</li>
<li>토큰 만료 후 자동 재인증</li>
</ul>
<hr>
<h2 id="🧭-어떤-flow를-써야-할까">🧭 어떤 Flow를 써야 할까?</h2>
<table>
<thead>
<tr>
<th>사용 환경</th>
<th>추천 Flow</th>
</tr>
</thead>
<tbody><tr>
<td>웹/프론트엔드 앱</td>
<td><code>authorization_code</code></td>
</tr>
<tr>
<td>내부 관리자용 툴</td>
<td><code>password</code> (단, 주의)</td>
</tr>
<tr>
<td>CI/CD 서버, 배치 작업</td>
<td><code>jwt_bearer</code></td>
</tr>
<tr>
<td>백엔드 서비스 (M2M)</td>
<td><code>client_credentials</code></td>
</tr>
<tr>
<td>IoT/디바이스 앱</td>
<td><code>device_code</code></td>
</tr>
</tbody></table>
<hr>
<h2 id="✅-refresh-token-지원-여부-정리">✅ Refresh Token 지원 여부 정리</h2>
<table>
<thead>
<tr>
<th>Grant Type</th>
<th>Refresh Token 지원</th>
</tr>
</thead>
<tbody><tr>
<td><code>authorization_code</code></td>
<td>✔️ 지원</td>
</tr>
<tr>
<td><code>password</code></td>
<td>✔️ 조건부</td>
</tr>
<tr>
<td><code>device_code</code></td>
<td>✔️ 지원</td>
</tr>
<tr>
<td><code>jwt_bearer</code></td>
<td>❌</td>
</tr>
<tr>
<td><code>client_credentials</code></td>
<td>❌</td>
</tr>
</tbody></table>
<hr>
<h2 id="🚨-참고-connected-app-설정에-따라-영향-받는-항목">🚨 참고: Connected App 설정에 따라 영향 받는 항목</h2>
<ul>
<li><code>refresh_token</code> 발급 여부 → OAuth Scopes에 <code>offline_access</code> 필수</li>
<li><code>password</code> flow 허용 여부 → &quot;Permitted Users&quot; 설정 필요</li>
<li><code>client_credentials</code> flow 사용 시 → 사용자 연결 필요</li>
</ul>
<hr>
<h2 id="🔚-마무리">🔚 마무리</h2>
<p>Salesforce OAuth 2.0은 강력하지만 복잡합니다.
<strong>각 Flow는 사용 환경과 보안 요구사항에 따라 신중하게 선택</strong>해야 합니다.
가장 일반적이고 권장되는 방식은 <code>authorization_code</code>이며,
자동화나 서버 작업에는 <code>jwt_bearer</code>가 탁월한 선택이 될 수 있습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Salesforce REST API – HTTP 메서드 정리]]></title>
            <link>https://velog.io/@hwan2-dev/Salesforce-REST-API-HTTP-%EB%A9%94%EC%84%9C%EB%93%9C-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@hwan2-dev/Salesforce-REST-API-HTTP-%EB%A9%94%EC%84%9C%EB%93%9C-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Mon, 12 May 2025 05:26:26 GMT</pubDate>
            <description><![CDATA[<p>Salesforce에서는 REST API를 통해 오브젝트를 생성, 조회, 수정, 삭제하는 다양한 HTTP 메서드를 제공합니다.<br>또한 <code>Upsert</code>라는 매우 강력한 기능도 함께 지원되며, 외부 시스템과의 연동에 유용하게 사용됩니다.</p>
<hr>
<h2 id="✅-1-get--데이터-조회">✅ 1. GET – 데이터 조회</h2>
<table>
<thead>
<tr>
<th>항목</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>목적</td>
<td>오브젝트 또는 레코드의 <strong>데이터를 조회</strong>할 때 사용</td>
</tr>
<tr>
<td>예시 1</td>
<td><code>/sobjects/Account/001Hu00000ABC123</code> → 특정 Account 조회</td>
</tr>
<tr>
<td>예시 2</td>
<td><code>/query?q=SELECT+Name+FROM+Account</code> → SOQL 쿼리 실행</td>
</tr>
<tr>
<td>응답</td>
<td>JSON 형식의 레코드 정보 반환</td>
</tr>
</tbody></table>
<hr>
<h2 id="✅-2-post--레코드-생성">✅ 2. POST – 레코드 생성</h2>
<table>
<thead>
<tr>
<th>항목</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>목적</td>
<td>새 레코드 생성</td>
</tr>
<tr>
<td>예시</td>
<td><code>/sobjects/Account</code></td>
</tr>
<tr>
<td>Body:</td>
<td></td>
</tr>
<tr>
<td>```json</td>
<td></td>
</tr>
<tr>
<td>{</td>
<td></td>
</tr>
<tr>
<td>&quot;Name&quot;: &quot;New Company&quot;</td>
<td></td>
</tr>
<tr>
<td>}</td>
<td></td>
</tr>
<tr>
<td>````</td>
<td></td>
</tr>
</tbody></table>
<p>| 응답 | 생성된 레코드 ID 반환 |</p>
<h2 id="✅-3-patch--레코드-수정--upsert">✅ 3. PATCH – 레코드 수정 &amp; Upsert</h2>
<h3 id="🔹-기본-사용-수정">🔹 기본 사용 (수정)</h3>
<table>
<thead>
<tr>
<th>항목</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>목적</td>
<td>기존 레코드의 <strong>일부 필드만 수정</strong></td>
</tr>
<tr>
<td>예시</td>
<td><code>/sobjects/Account/001Hu00000ABC123</code></td>
</tr>
<tr>
<td>특징</td>
<td>전체가 아닌 일부 필드만 전송 가능 (<code>PATCH</code>는 <code>PUT</code>보다 유연함)</td>
</tr>
</tbody></table>
<h3 id="🔹-upsert-존재하면-수정-없으면-생성">🔹 Upsert (존재하면 수정, 없으면 생성)</h3>
<blockquote>
<p><code>PATCH</code> 요청에 <strong>External ID 필드 기반 경로</strong>를 사용하면 Upsert가 동작합니다.</p>
</blockquote>
<table>
<thead>
<tr>
<th>예시</th>
</tr>
</thead>
</table>
<pre><code class="language-http">PATCH /services/data/v58.0/sobjects/Order__c/External_Order_Id__c/ORD-001</code></pre>
<pre><code class="language-json">{
  &quot;Status__c&quot;: &quot;Confirmed&quot;,
  &quot;AccountId&quot;: &quot;001Hu00000XXXXXX&quot;
}</code></pre>
<ul>
<li><code>External_Order_Id__c = &#39;ORD-001&#39;</code>인 레코드가 있으면 수정</li>
<li>없으면 새로 생성</li>
</ul>
<hr>
<h2 id="❗-upsert-시-주의사항-external-id-필드-필수">❗ Upsert 시 주의사항: External ID 필드 필수</h2>
<blockquote>
<p>Upsert 시 경로에 사용되는 필드는 반드시 <code>External ID</code>로 지정된 필드여야 합니다.</p>
</blockquote>
<h3 id="✅-external-id란">✅ External ID란?</h3>
<ul>
<li>Salesforce가 <strong>레코드를 식별하기 위해 사용하는 필드</strong></li>
<li>오브젝트 설정에서 필드 생성 또는 수정 시 체크 가능</li>
<li><strong>Text, Number, Email 타입만 가능</strong></li>
</ul>
<h3 id="✅-사용-가능한-필드-타입">✅ 사용 가능한 필드 타입</h3>
<table>
<thead>
<tr>
<th>타입</th>
<th>External ID 지정 가능</th>
</tr>
</thead>
<tbody><tr>
<td>Text</td>
<td>✅</td>
</tr>
<tr>
<td>Number</td>
<td>✅</td>
</tr>
<tr>
<td>Email</td>
<td>✅</td>
</tr>
<tr>
<td>Lookup, Picklist, Date 등</td>
<td>❌</td>
</tr>
</tbody></table>
<h3 id="❌-일반-필드로는-upsert-불가">❌ 일반 필드로는 Upsert 불가</h3>
<p>예:</p>
<pre><code class="language-http">PATCH /sobjects/Order__c/OrderNumber__c/ORD001</code></pre>
<p>→ ❌ 실패 (OrderNumber__c가 External ID가 아니면 사용 불가)</p>
<hr>
<h2 id="✅-4-delete--레코드-삭제">✅ 4. DELETE – 레코드 삭제</h2>
<table>
<thead>
<tr>
<th>항목</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>목적</td>
<td>레코드 삭제</td>
</tr>
<tr>
<td>예시</td>
<td><code>/sobjects/Account/001Hu00000ABC123</code></td>
</tr>
<tr>
<td>응답</td>
<td>상태 코드 204 (No Content) 반환</td>
</tr>
</tbody></table>
<hr>
<h2 id="✅-5-put--전체-덮어쓰기-잘-안-씀">✅ 5. PUT – 전체 덮어쓰기 (잘 안 씀)</h2>
<table>
<thead>
<tr>
<th>항목</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>목적</td>
<td>전체 레코드 교체</td>
</tr>
<tr>
<td>Salesforce에서는</td>
<td>거의 사용되지 않음. 대부분 <code>PATCH</code>로 처리</td>
</tr>
</tbody></table>
<hr>
<h2 id="✅-기타-기능">✅ 기타 기능</h2>
<table>
<thead>
<tr>
<th>기능</th>
<th>경로</th>
</tr>
</thead>
<tbody><tr>
<td>SOQL 쿼리 실행</td>
<td><code>/query?q=SELECT+Name+FROM+Account</code></td>
</tr>
<tr>
<td>SOSL 검색</td>
<td><code>/search?q=FIND+{John}</code></td>
</tr>
<tr>
<td>오브젝트 정보 조회</td>
<td><code>/sobjects/Account/describe</code></td>
</tr>
<tr>
<td>오브젝트 목록</td>
<td><code>/sobjects</code></td>
</tr>
</tbody></table>
<hr>
<h2 id="🔐-인증-방식-요약">🔐 인증 방식 요약</h2>
<table>
<thead>
<tr>
<th>방식</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>OAuth 2.0 Authorization Code</td>
<td>사용자 로그인 기반</td>
</tr>
<tr>
<td>OAuth 2.0 Client Credentials</td>
<td>백엔드 시스템 간 통신용</td>
</tr>
<tr>
<td>Username-Password Flow</td>
<td>테스트/비추천 (보안상 취약)</td>
</tr>
</tbody></table>
<hr>
<h2 id="📌-전체-요약표">📌 전체 요약표</h2>
<table>
<thead>
<tr>
<th>메서드</th>
<th>기능</th>
<th>특징</th>
</tr>
</thead>
<tbody><tr>
<td><code>GET</code></td>
<td>조회</td>
<td>쿼리 또는 ID 기반 조회</td>
</tr>
<tr>
<td><code>POST</code></td>
<td>생성</td>
<td>새 레코드 삽입</td>
</tr>
<tr>
<td><code>PATCH</code></td>
<td>수정 / Upsert</td>
<td>일부 필드 수정 / External ID 기반 Upsert</td>
</tr>
<tr>
<td><code>DELETE</code></td>
<td>삭제</td>
<td>레코드 제거</td>
</tr>
<tr>
<td><code>PUT</code></td>
<td>전체 수정</td>
<td>거의 안 씀</td>
</tr>
</tbody></table>
<hr>
<h2 id="🧠-정리">🧠 정리</h2>
<ul>
<li><code>PATCH + External ID</code> 경로를 사용하면 Upsert 가능</li>
<li>일반 필드는 Upsert에 사용할 수 없음</li>
<li>External ID는 반드시 <strong>Text / Number / Email 필드</strong>에 직접 지정해야 함</li>
<li>API 통합 시 외부 시스템의 고유 ID를 External ID로 맞추는 것이 매우 중요</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[Java Exception & Error 정리 총정리]]></title>
            <link>https://velog.io/@hwan2-dev/Java-Exception-Error-%EC%A0%95%EB%A6%AC-%EC%B4%9D%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@hwan2-dev/Java-Exception-Error-%EC%A0%95%EB%A6%AC-%EC%B4%9D%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Fri, 02 May 2025 02:09:52 GMT</pubDate>
            <description><![CDATA[<p>Java의 예외(Exception)와 오류(Error)는 모두 <code>Throwable</code> 클래스를 상속받으며, 프로그램 실행 중 발생할 수 있는 <strong>비정상적인 상황</strong>을 처리하기 위해 사용됩니다.</p>
<hr>
<h2 id="📚-전체-계층-구조">📚 전체 계층 구조</h2>
<pre><code>Throwable
├── Exception (예외)
│   ├── CheckedException (체크 예외)
│   └── UncheckedException (언체크 예외, RuntimeException)
└── Error (오류 - 시스템/VM 레벨)</code></pre><hr>
<h2 id="✅-exception-예외">✅ Exception (예외)</h2>
<h3 id="1-checked-exception-컴파일러가-반드시-처리-요구">1. Checked Exception (컴파일러가 반드시 처리 요구)</h3>
<table>
<thead>
<tr>
<th>예외 클래스</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td><strong>IOException</strong></td>
<td>입출력 실패 또는 인터럽트 (파일, 네트워크 등)</td>
</tr>
<tr>
<td><strong>FileNotFoundException</strong></td>
<td>지정한 파일을 찾을 수 없음</td>
</tr>
<tr>
<td><strong>SQLException</strong></td>
<td>DB 작업 도중 발생하는 예외</td>
</tr>
<tr>
<td><strong>ParseException</strong></td>
<td>날짜/시간 파싱 오류</td>
</tr>
<tr>
<td><strong>ClassNotFoundException</strong></td>
<td>클래스 로딩 실패</td>
</tr>
<tr>
<td><strong>InterruptedException</strong></td>
<td>스레드가 인터럽트됨</td>
</tr>
<tr>
<td><strong>NoSuchMethodException</strong></td>
<td>지정한 메서드가 존재하지 않음</td>
</tr>
<tr>
<td><strong>InstantiationException</strong></td>
<td>클래스 인스턴스화 실패</td>
</tr>
</tbody></table>
<blockquote>
<p>✔ <code>try-catch</code> 또는 <code>throws</code> 선언 필요</p>
</blockquote>
<hr>
<h3 id="2-unchecked-exception--runtimeexception-하위-클래스">2. Unchecked Exception (= RuntimeException 하위 클래스)</h3>
<table>
<thead>
<tr>
<th>예외 클래스</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td><strong>NullPointerException</strong></td>
<td>null 객체 접근 시 발생</td>
</tr>
<tr>
<td><strong>IllegalArgumentException</strong></td>
<td>잘못된 매개변수 전달 시</td>
</tr>
<tr>
<td><strong>IndexOutOfBoundsException</strong></td>
<td>인덱스 초과 접근 시</td>
</tr>
<tr>
<td><strong>NumberFormatException</strong></td>
<td>숫자 형식이 잘못됐을 때</td>
</tr>
<tr>
<td><strong>ArithmeticException</strong></td>
<td>산술 오류 (예: 0으로 나누기)</td>
</tr>
<tr>
<td><strong>IllegalStateException</strong></td>
<td>잘못된 상태에서 메서드 호출 시</td>
</tr>
<tr>
<td><strong>ClassCastException</strong></td>
<td>잘못된 타입 변환 시</td>
</tr>
<tr>
<td><strong>UnsupportedOperationException</strong></td>
<td>구현되지 않은 기능 호출 시</td>
</tr>
</tbody></table>
<blockquote>
<p>❗ 예외 처리 선택 가능 (<code>throws</code> 없이 사용 가능)</p>
</blockquote>
<hr>
<h2 id="❌-error-오류---거의-처리하지-않음">❌ Error (오류 - 거의 처리하지 않음)</h2>
<table>
<thead>
<tr>
<th>오류 클래스</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td><strong>OutOfMemoryError</strong></td>
<td>JVM의 메모리 부족</td>
</tr>
<tr>
<td><strong>StackOverflowError</strong></td>
<td>스택 오버플로우 (무한 재귀 등)</td>
</tr>
<tr>
<td><strong>VirtualMachineError</strong></td>
<td>JVM 내부 문제 발생</td>
</tr>
<tr>
<td><strong>NoClassDefFoundError</strong></td>
<td>클래스 정의를 찾을 수 없음</td>
</tr>
<tr>
<td><strong>InternalError</strong></td>
<td>JVM 내부 오류</td>
</tr>
<tr>
<td><strong>ThreadDeath</strong></td>
<td>스레드 강제 종료</td>
</tr>
</tbody></table>
<blockquote>
<p>❌ 대부분 <strong>try-catch로 처리하지 않고</strong>, JVM이 종료되거나 복구 불가 상황</p>
</blockquote>
<hr>
<h2 id="🧠-exception-vs-error-vs-throwable-차이">🧠 Exception vs Error vs Throwable 차이</h2>
<table>
<thead>
<tr>
<th>항목</th>
<th>Throwable</th>
<th>Exception</th>
<th>Error</th>
</tr>
</thead>
<tbody><tr>
<td>정의</td>
<td>예외/오류의 최상위 클래스</td>
<td>개발자가 처리 가능한 예외</td>
<td>시스템 수준의 치명적 오류</td>
</tr>
<tr>
<td>사용 목적</td>
<td>예외나 오류 포괄적 처리</td>
<td>로직 오류/외부 문제 처리</td>
<td>시스템/메모리 문제 대응</td>
</tr>
<tr>
<td>예외 처리 강제 여부</td>
<td>-</td>
<td>Checked는 강제, Unchecked는 선택</td>
<td>거의 처리하지 않음</td>
</tr>
<tr>
<td>예시</td>
<td>-</td>
<td><code>IOException</code>, <code>NullPointerException</code></td>
<td><code>OutOfMemoryError</code></td>
</tr>
</tbody></table>
<hr>
<h2 id="📌-실무에서의-사용-팁">📌 실무에서의 사용 팁</h2>
<ul>
<li>외부 환경(DB, 파일, API 등): <strong>Checked Exception</strong> → 반드시 처리</li>
<li>내부 로직/개발 실수: <strong>Unchecked Exception</strong> → 가독성 위해 선택적 처리</li>
<li>시스템 오류: <strong>Error</strong> → 복구 불가, 보통 로그만 남기고 종료</li>
</ul>
<hr>
<h2 id="📎-자주-사용하는-처리-방식">📎 자주 사용하는 처리 방식</h2>
<pre><code class="language-java">try {
    FileReader reader = new FileReader(&quot;data.txt&quot;);
} catch (FileNotFoundException e) {
    System.err.println(&quot;파일을 찾을 수 없습니다: &quot; + e.getMessage());
}</code></pre>
<hr>
<h2 id="📘-마무리">📘 마무리</h2>
<blockquote>
<p>자바에서 예외는 단순히 &quot;오류&quot;가 아니라 <strong>정상적인 흐름을 벗어난 상태를 통제하기 위한 메커니즘</strong>입니다. 예외를 잘 이해하고 적절히 처리하면, <strong>프로그램의 안정성과 유지보수성이 훨씬 향상</strong>됩니다.</p>
</blockquote>
]]></description>
        </item>
        <item>
            <title><![CDATA[Spring Boot 테스트 시 로그인 페이지가 나올 때 (Postman 인증 문제 해결법)]]></title>
            <link>https://velog.io/@hwan2-dev/Spring-Boot-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EC%8B%9C-%EB%A1%9C%EA%B7%B8%EC%9D%B8-%ED%8E%98%EC%9D%B4%EC%A7%80%EA%B0%80-%EB%82%98%EC%98%AC-%EB%95%8C-Postman-%EC%9D%B8%EC%A6%9D-%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0%EB%B2%95</link>
            <guid>https://velog.io/@hwan2-dev/Spring-Boot-%ED%85%8C%EC%8A%A4%ED%8A%B8-%EC%8B%9C-%EB%A1%9C%EA%B7%B8%EC%9D%B8-%ED%8E%98%EC%9D%B4%EC%A7%80%EA%B0%80-%EB%82%98%EC%98%AC-%EB%95%8C-Postman-%EC%9D%B8%EC%A6%9D-%EB%AC%B8%EC%A0%9C-%ED%95%B4%EA%B2%B0%EB%B2%95</guid>
            <pubDate>Wed, 30 Apr 2025 02:16:52 GMT</pubDate>
            <description><![CDATA[<p>최근에 Spring Boot로 Webhook API를 만들고, Postman을 이용해 아래와 같이 테스트를 진행했습니다.</p>
<pre><code>POST http://localhost:8001/webhook/save?param=hello</code></pre><p>그런데 응답 결과가 의외였습니다:</p>
<pre><code class="language-html">&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
  &lt;head&gt;
    &lt;meta charset=&quot;utf-8&quot;&gt;
    &lt;title&gt;Please sign in&lt;/title&gt;
    ...
  &lt;/head&gt;
  &lt;body&gt;
    &lt;h2&gt;Login with OAuth 2.0&lt;/h2&gt;
  &lt;/body&gt;
&lt;/html&gt;</code></pre>
<p>Spring Boot 프로젝트에서 REST API를 만들었는데, <strong>갑자기 로그인 페이지?</strong></p>
<h2 id="📌-원인">📌 원인</h2>
<p>이건 Spring Boot에서 <code>spring-boot-starter-security</code> 또는 <code>spring-boot-starter-oauth2-client</code>를 사용 중일 때 발생하는 <strong>기본 동작</strong>입니다.</p>
<ul>
<li>Spring Security는 기본적으로 <strong>모든 요청에 인증을 요구</strong>합니다.</li>
<li>Postman이나 외부 요청이 인증되지 않은 상태로 들어오면 → <strong>자동으로 로그인 페이지를 반환</strong>합니다.</li>
</ul>
<h2 id="🛠-해결-방법-security-설정-커스터마이징">🛠 해결 방법: Security 설정 커스터마이징</h2>
<p>이 문제를 해결하려면 특정 엔드포인트(<code>/webhook/**</code>)는 인증 없이 접근할 수 있도록 <strong>SecurityFilterChain</strong>을 설정해야 합니다.</p>
<h3 id="✅-예제-코드-모든-요청-허용">✅ 예제 코드: 모든 요청 허용</h3>
<pre><code class="language-java">@Configuration
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .csrf().disable() // 테스트용으로만 사용! 운영 시 주의
            .authorizeHttpRequests()
                .anyRequest().permitAll(); // 모든 요청을 인증 없이 허용
        return http.build();
    }
}</code></pre>
<h3 id="✅-일부-경로만-허용-예-webhook">✅ 일부 경로만 허용 (예: <code>/webhook/**</code>)</h3>
<pre><code class="language-java">@Configuration
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
            .csrf().disable()
            .authorizeHttpRequests()
                .requestMatchers(&quot;/webhook/**&quot;).permitAll()
                .anyRequest().authenticated();
        return http.build();
    }
}</code></pre>
<h2 id="⚠-주의사항">⚠ 주의사항</h2>
<ul>
<li><code>csrf().disable()</code>은 <strong>POST 요청을 테스트용으로만 허용할 때</strong> 사용하는 설정입니다.</li>
<li>운영환경에서는 보안을 강화하기 위해 CSRF 보호나 세션 관리 정책도 함께 설정해줘야 합니다.</li>
</ul>
<hr>
<h2 id="✅-결론">✅ 결론</h2>
<p>Spring Boot에 보안 의존성이 포함되면, Postman이나 외부 시스템에서 API를 호출할 때 <strong>기본 로그인 페이지 응답</strong>이 나올 수 있습니다.<br>이 문제는 <code>SecurityFilterChain</code> 설정으로 간단하게 해결할 수 있으니, 개발 초기에는 필수로 설정해두는 걸 추천합니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[Flask란 무엇인가? 설치부터 실행까지 쉽게 정리!]]></title>
            <link>https://velog.io/@hwan2-dev/Flask%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80-%EC%84%A4%EC%B9%98%EB%B6%80%ED%84%B0-%EC%8B%A4%ED%96%89%EA%B9%8C%EC%A7%80-%EC%89%BD%EA%B2%8C-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@hwan2-dev/Flask%EB%9E%80-%EB%AC%B4%EC%97%87%EC%9D%B8%EA%B0%80-%EC%84%A4%EC%B9%98%EB%B6%80%ED%84%B0-%EC%8B%A4%ED%96%89%EA%B9%8C%EC%A7%80-%EC%89%BD%EA%B2%8C-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Tue, 29 Apr 2025 00:39:12 GMT</pubDate>
            <description><![CDATA[<h2 id="✅-flask란">✅ Flask란?</h2>
<blockquote>
<p><strong>Flask는 파이썬으로 만든 아주 가벼운 웹 서버 프레임워크입니다.</strong><br>몇 줄 코드만으로 빠르게 웹 서버나 API를 만들 수 있게 도와줍니다.</p>
</blockquote>
<ul>
<li>가볍고 빠른 웹 프레임워크</li>
<li>복잡한 설정 없이 바로 실행 가능</li>
<li>학습용, 실습용, 소규모 프로젝트에 최적</li>
</ul>
<hr>
<h2 id="✅-flask-설치-방법">✅ Flask 설치 방법</h2>
<h3 id="1-python-설치">1. Python 설치</h3>
<ul>
<li>Python 3.x 버전을 설치합니다.</li>
<li>설치할 때 <strong>&quot;Add Python to PATH&quot;</strong> 옵션을 꼭 체크하세요.</li>
</ul>
<h3 id="2-pip로-flask-설치">2. pip로 Flask 설치</h3>
<p>터미널(명령어창)에서 아래 명령어를 입력합니다.</p>
<pre><code class="language-bash">pip install flask</code></pre>
<p>✅ 이 명령어 한 줄로 Flask 설치 완료!</p>
<hr>
<h2 id="✅-flask-기본-서버-만들기">✅ Flask 기본 서버 만들기</h2>
<h3 id="1-apppy-파일-생성">1. <code>app.py</code> 파일 생성</h3>
<p>아래처럼 코드를 작성합니다.</p>
<pre><code class="language-python">from flask import Flask

app = Flask(__name__)

@app.route(&#39;/&#39;)
def hello():
    return &quot;Hello, Flask!&quot;

if __name__ == &#39;__main__&#39;:
    app.run(port=5000)</code></pre>
<ul>
<li><code>/</code> 주소로 접속하면 &quot;Hello, Flask!&quot;를 보여줍니다.</li>
</ul>
<hr>
<h2 id="✅-flask-서버-실행-방법">✅ Flask 서버 실행 방법</h2>
<p>터미널에서 <code>app.py</code>가 있는 폴더로 이동한 뒤, 실행합니다.</p>
<pre><code class="language-bash">python app.py</code></pre>
<p>성공적으로 실행되면 다음과 같은 메시지가 뜹니다.</p>
<pre><code class="language-text">* Running on http://127.0.0.1:5000/</code></pre>
<p>브라우저에서 <code>http://localhost:5000</code>에 접속하면<br><strong>&quot;Hello, Flask!&quot;</strong> 라는 문구를 볼 수 있습니다!</p>
<hr>
<h2 id="✅-flask-서버-종료-방법">✅ Flask 서버 종료 방법</h2>
<ul>
<li>터미널 창에서 <code>CTRL + C</code>를 눌러 서버를 종료합니다.</li>
</ul>
<hr>
<h2 id="✅-flask-특징-정리">✅ Flask 특징 정리</h2>
<table>
<thead>
<tr>
<th align="left">항목</th>
<th align="left">설명</th>
</tr>
</thead>
<tbody><tr>
<td align="left">초간단 서버</td>
<td align="left">파일 하나로 웹 서버 만들기 가능</td>
</tr>
<tr>
<td align="left">빠른 개발</td>
<td align="left">코드 수정 → 바로 실행</td>
</tr>
<tr>
<td align="left">경량 프레임워크</td>
<td align="left">필요한 기능만 최소한으로 제공</td>
</tr>
<tr>
<td align="left">확장성</td>
<td align="left">필요시 데이터베이스, 인증 등 추가 가능</td>
</tr>
</tbody></table>
<hr>
<h2 id="✅-flask로-할-수-있는-것">✅ Flask로 할 수 있는 것</h2>
<ul>
<li>Webhook 요청 받는 서버 만들기</li>
<li>REST API 서버 만들기</li>
<li>간단한 개인 웹사이트 개발</li>
<li>프로젝트용 백엔드 서버 구축</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Salesforce] LWC에서 사용하는 어노테이션 완전 정복]]></title>
            <link>https://velog.io/@hwan2-dev/Salesforce-LWC%EC%97%90%EC%84%9C-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-%EC%96%B4%EB%85%B8%ED%85%8C%EC%9D%B4%EC%85%98-%EC%99%84%EC%A0%84-%EC%A0%95</link>
            <guid>https://velog.io/@hwan2-dev/Salesforce-LWC%EC%97%90%EC%84%9C-%EC%82%AC%EC%9A%A9%ED%95%98%EB%8A%94-%EC%96%B4%EB%85%B8%ED%85%8C%EC%9D%B4%EC%85%98-%EC%99%84%EC%A0%84-%EC%A0%95</guid>
            <pubDate>Thu, 24 Apr 2025 09:02:27 GMT</pubDate>
            <description><![CDATA[<p>Lightning Web Components(LWC)에서는 JavaScript 상단에서 사용하는 특수한 어노테이션들을 <strong>데코레이터(Decorator)</strong>라고 부릅니다.<br>이 데코레이터들은 Salesforce 플랫폼과의 연동, 데이터 바인딩, 컴포넌트 통신 등에 중요한 역할을 합니다.</p>
<p>이 글에서는 <strong>LWC에서 사용 가능한 모든 데코레이터를 깔끔하게 정리</strong>했습니다.</p>
<hr>
<h2 id="✅-1-api">✅ 1. @api</h2>
<table>
<thead>
<tr>
<th>항목</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>역할</td>
<td><strong>공개 속성(Public Property)</strong> 또는 메서드로 외부 컴포넌트(LWC, Aura)에서 접근 가능하게 만듦</td>
</tr>
<tr>
<td>주 사용 위치</td>
<td>부모 → 자식 컴포넌트 간 데이터 전달</td>
</tr>
<tr>
<td>사용 대상</td>
<td>변수, 메서드</td>
</tr>
<tr>
<td>예시 용도</td>
<td>부모가 자식 컴포넌트에 데이터를 전달하거나 메서드를 직접 호출할 때 사용</td>
</tr>
</tbody></table>
<hr>
<h2 id="✅-2-track-⚠️-deprecated">✅ 2. @track (⚠️ Deprecated)</h2>
<table>
<thead>
<tr>
<th>항목</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>역할</td>
<td>컴포넌트 내에서 <strong>반응형 상태 추적(리액티브)</strong> 을 위해 사용되던 속성</td>
</tr>
<tr>
<td>현재 상태</td>
<td>⚠️ 최신 버전에서는 대부분 자동 추적됨. <strong>객체/배열의 일부 요소만 업데이트할 경우에만 필요</strong></td>
</tr>
<tr>
<td>사용 대상</td>
<td>변수</td>
</tr>
</tbody></table>
<hr>
<h2 id="✅-3-wire">✅ 3. @wire</h2>
<table>
<thead>
<tr>
<th>항목</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>역할</td>
<td>Apex, Lightning Data Service, Platform Resource 등에서 <strong>데이터를 자동으로 가져오는 바인딩 방식</strong></td>
</tr>
<tr>
<td>특징</td>
<td>자동 호출 + 자동 반응형 처리</td>
</tr>
<tr>
<td>사용 대상</td>
<td>Apex 메서드, LDS 객체, Schema 등</td>
</tr>
<tr>
<td>예시 용도</td>
<td>Apex에서 <code>@AuraEnabled(cacheable=true)</code> 메서드를 가져와 LWC에 자동 연결</td>
</tr>
</tbody></table>
<hr>
<h2 id="✅-4-readonly-내부용-공식-지원-x">✅ 4. @readonly (내부용, 공식 지원 X)</h2>
<table>
<thead>
<tr>
<th>항목</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>상태</td>
<td>과거 일부 컴포넌트 라이브러리 내부에서만 사용되던 비공식 데코레이터</td>
</tr>
<tr>
<td>일반 개발자 사용 여부</td>
<td>❌ 지원되지 않으며 일반적으로 사용할 필요 없음</td>
</tr>
</tbody></table>
<hr>
<h2 id="✅-5-track-vs-일반-변수-비교">✅ 5. @track vs 일반 변수 (비교)</h2>
<table>
<thead>
<tr>
<th>속성</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>일반 변수</td>
<td>LWC는 대부분의 변수 변경을 자동 감지함</td>
</tr>
<tr>
<td>@track</td>
<td>배열/객체의 <strong>일부 속성 변경</strong>을 감지시키고 싶을 때 수동으로 지정</td>
</tr>
<tr>
<td>예외 케이스</td>
<td><code>this.data.name = &#39;abc&#39;</code> 처럼 객체의 내부만 변경하는 경우 <code>@track</code> 필요할 수 있음 (구버전 기준)</td>
</tr>
</tbody></table>
<hr>
<h2 id="⚠️-사용-시-주의사항">⚠️ 사용 시 주의사항</h2>
<table>
<thead>
<tr>
<th>데코레이터</th>
<th>주의사항</th>
</tr>
</thead>
<tbody><tr>
<td><code>@api</code></td>
<td>부모가 접근하는 속성/메서드는 꼭 <code>@api</code>로 선언되어야 함</td>
</tr>
<tr>
<td><code>@wire</code></td>
<td>사용하려는 Apex 메서드는 반드시 <code>@AuraEnabled(cacheable=true)</code> 설정 필요</td>
</tr>
<tr>
<td><code>@track</code></td>
<td>LWC의 최신 버전에서는 대부분의 상태 추적이 자동화됨 → 특별한 경우에만 사용</td>
</tr>
</tbody></table>
<hr>
<h2 id="✅-요약-표">✅ 요약 표</h2>
<table>
<thead>
<tr>
<th>데코레이터</th>
<th>역할</th>
<th>대상</th>
<th>비고</th>
</tr>
</thead>
<tbody><tr>
<td><code>@api</code></td>
<td>외부 접근 가능 속성/메서드</td>
<td>변수, 메서드</td>
<td>부모 → 자식 통신</td>
</tr>
<tr>
<td><code>@wire</code></td>
<td>데이터 바인딩 (Apex, LDS)</td>
<td>변수, 메서드</td>
<td>자동 호출 + 자동 반응형</td>
</tr>
<tr>
<td><code>@track</code></td>
<td>객체/배열 내부 속성 추적</td>
<td>변수</td>
<td>최신 버전에서는 거의 불필요</td>
</tr>
<tr>
<td>(비공식) <code>@readonly</code></td>
<td>내부용</td>
<td>변수</td>
<td>사용 비권장, 공식 미지원</td>
</tr>
</tbody></table>
<hr>
<h2 id="✨-마무리">✨ 마무리</h2>
<p>LWC는 React나 Vue처럼 <strong>반응형 프론트엔드 개발을 가능하게 해주는 컴포넌트 기반 프레임워크</strong>입니다.<br>여기서 사용하는 데코레이터들은 Salesforce의 서버(Apex), UI, 컴포넌트 간 통신을 부드럽게 연결해주는 핵심 역할을 합니다.</p>
<p>정확한 의미와 사용 목적을 이해하면, 더 유연하고 강력한 LWC 컴포넌트를 만들 수 있습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Salesforce] Apex 어노테이션 완전 정리]]></title>
            <link>https://velog.io/@hwan2-dev/Salesforce-Apex-%EC%96%B4%EB%85%B8%ED%85%8C%EC%9D%B4%EC%85%98-%EC%99%84%EC%A0%84-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@hwan2-dev/Salesforce-Apex-%EC%96%B4%EB%85%B8%ED%85%8C%EC%9D%B4%EC%85%98-%EC%99%84%EC%A0%84-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Thu, 24 Apr 2025 08:59:34 GMT</pubDate>
            <description><![CDATA[<h1 id="🔖-salesforce-apex-어노테이션-완전-정리">🔖 Salesforce Apex 어노테이션 완전 정리</h1>
<p>Apex에서 어노테이션은 클래스, 메서드, 변수 등에 <strong>특정한 역할이나 실행 조건</strong>을 지정해주는 메타정보입니다.<br>이 글에서는 Salesforce Apex에서 사용할 수 있는 <strong>모든 어노테이션</strong>을 <strong>분류별로 깔끔하게 정리</strong>했습니다.</p>
<hr>
<h2 id="✅-1-lwc--aura-통신용">✅ 1. LWC / Aura 통신용</h2>
<table>
<thead>
<tr>
<th>어노테이션</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td><code>@AuraEnabled</code></td>
<td>Apex 메서드나 변수에 Aura 또는 LWC에서 접근 가능하게 함</td>
</tr>
<tr>
<td><code>@AuraEnabled(cacheable=true)</code></td>
<td>클라이언트 측 캐싱을 허용함 (<code>@wire</code> 방식에서만 사용 가능)</td>
</tr>
</tbody></table>
<hr>
<h2 id="✅-2-flow-통합용">✅ 2. Flow 통합용</h2>
<table>
<thead>
<tr>
<th>어노테이션</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td><code>@InvocableMethod</code></td>
<td>Flow에서 호출 가능한 Apex 메서드로 선언</td>
</tr>
<tr>
<td><code>@InvocableVariable</code></td>
<td>Flow에서 접근 가능한 변수로 선언</td>
</tr>
</tbody></table>
<hr>
<h2 id="✅-3-비동기배치-관련">✅ 3. 비동기/배치 관련</h2>
<table>
<thead>
<tr>
<th>어노테이션</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td><code>@future</code></td>
<td>메서드를 비동기 처리 (즉시 반환, 서버에서 나중에 실행됨)</td>
</tr>
<tr>
<td><code>@Reentrancy</code></td>
<td>Flow 또는 프로세스에서 재진입 허용을 명시 (동시성 충돌 방지)</td>
</tr>
</tbody></table>
<hr>
<h2 id="✅-4-테스트-전용">✅ 4. 테스트 전용</h2>
<table>
<thead>
<tr>
<th>어노테이션</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td><code>@isTest</code></td>
<td>테스트 전용 클래스 또는 메서드로 지정</td>
</tr>
<tr>
<td><code>@testSetup</code></td>
<td>테스트 실행 전 공통 셋업 데이터를 구성하는 메서드</td>
</tr>
<tr>
<td><code>@TestVisible</code></td>
<td><code>private</code> 변수나 메서드를 테스트 클래스에서 접근 가능하게 함</td>
</tr>
</tbody></table>
<hr>
<h2 id="✅-5-rest-api--visualforce-연동">✅ 5. REST API / Visualforce 연동</h2>
<table>
<thead>
<tr>
<th>어노테이션</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td><code>@RemoteAction</code></td>
<td>Visualforce에서 Apex 메서드를 Ajax로 호출 가능하게 함</td>
</tr>
<tr>
<td><code>@RestResource</code></td>
<td>Apex 클래스를 REST API 엔드포인트로 공개함</td>
</tr>
<tr>
<td><code>@HttpGet</code> / <code>@HttpPost</code> / <code>@HttpPatch</code> / <code>@HttpDelete</code></td>
<td>REST API 메서드에서 HTTP 동작을 매핑함 (<code>@RestResource</code> 내부에서 사용됨)</td>
</tr>
</tbody></table>
<hr>
<h2 id="✅-6-보안--성능-제어">✅ 6. 보안 / 성능 제어</h2>
<table>
<thead>
<tr>
<th>어노테이션</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td><code>@ReadOnly</code></td>
<td>트랜잭션을 읽기 전용으로 제한 (조회 성능 향상, 대용량 조회용)</td>
</tr>
<tr>
<td><code>@NamespaceAccessible</code></td>
<td>Managed Package 외부에서도 클래스/메서드 접근 가능하게 설정</td>
</tr>
<tr>
<td><code>@Deprecated</code></td>
<td>더 이상 사용하지 말아야 할 항목으로 표시 (경고만, 실행은 가능)</td>
</tr>
</tbody></table>
<hr>
<h2 id="✅-7-json-직렬화">✅ 7. JSON 직렬화</h2>
<table>
<thead>
<tr>
<th>어노테이션</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td><code>@JsonAccess</code></td>
<td>JSON 직렬화/역직렬화 시 특정 변수 포함 여부 지정 (실사용 빈도 낮음)</td>
</tr>
</tbody></table>
<hr>
<h2 id="✅-부가적인-메모">✅ 부가적인 메모</h2>
<table>
<thead>
<tr>
<th>어노테이션</th>
<th>상태</th>
</tr>
</thead>
<tbody><tr>
<td><code>@WithSharing</code> / <code>@WithoutSharing</code></td>
<td>공유 설정 제어용 키워드 (<code>@</code> 없이 사용되지만 어노테이션처럼 보일 수 있음)</td>
</tr>
<tr>
<td><code>@codeCoverageIgnore</code></td>
<td>비공식 테스트 커버리지 제외 표시 (공식 Apex에는 없음)</td>
</tr>
</tbody></table>
<hr>
<h2 id="✅-정리-요약">✅ 정리 요약</h2>
<table>
<thead>
<tr>
<th>분류</th>
<th>대표 어노테이션</th>
</tr>
</thead>
<tbody><tr>
<td>LWC 연동</td>
<td><code>@AuraEnabled</code></td>
</tr>
<tr>
<td>Flow 연동</td>
<td><code>@InvocableMethod</code>, <code>@InvocableVariable</code></td>
</tr>
<tr>
<td>비동기 처리</td>
<td><code>@future</code>, <code>@Reentrancy</code></td>
</tr>
<tr>
<td>테스트용</td>
<td><code>@isTest</code>, <code>@testSetup</code>, <code>@TestVisible</code></td>
</tr>
<tr>
<td>API 연동</td>
<td><code>@RestResource</code>, <code>@RemoteAction</code>, <code>@Http*</code></td>
</tr>
<tr>
<td>성능/보안</td>
<td><code>@ReadOnly</code>, <code>@NamespaceAccessible</code>, <code>@Deprecated</code></td>
</tr>
</tbody></table>
<hr>
<h2 id="✨-마무리">✨ 마무리</h2>
<p>Salesforce Apex에서 어노테이션은 단순히 코드의 부가기능이 아닌, <strong>플랫폼과 완벽하게 통합되도록 돕는 핵심 요소</strong>입니다.<br>LWC, Flow, Visualforce, REST API 등 Salesforce의 다양한 계층과 연결되는 만큼, 각각의 어노테이션 목적을 명확히 이해해두면 훨씬 강력한 Apex 개발자가 될 수 있습니다.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[개발] DOM이란? 웹 개발자를 위한 완벽 정리]]></title>
            <link>https://velog.io/@hwan2-dev/%EA%B0%9C%EB%B0%9C-DOM%EC%9D%B4%EB%9E%80-%EC%9B%B9-%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%A5%BC-%EC%9C%84%ED%95%9C-%EC%99%84%EB%B2%BD-%EC%A0%95%EB%A6%AC</link>
            <guid>https://velog.io/@hwan2-dev/%EA%B0%9C%EB%B0%9C-DOM%EC%9D%B4%EB%9E%80-%EC%9B%B9-%EA%B0%9C%EB%B0%9C%EC%9E%90%EB%A5%BC-%EC%9C%84%ED%95%9C-%EC%99%84%EB%B2%BD-%EC%A0%95%EB%A6%AC</guid>
            <pubDate>Thu, 24 Apr 2025 07:51:49 GMT</pubDate>
            <description><![CDATA[<p>웹 개발을 하다 보면 <code>DOM</code>이라는 단어를 자주 듣게 됩니다.<br>HTML을 작성할 때도, JavaScript로 버튼을 눌렀을 때 무언가를 바꿀 때도 사실 우리는 DOM을 다루고 있습니다.</p>
<p>이 글에서는 <strong>DOM이 무엇인지</strong>, <strong>왜 필요한지</strong>, 그리고 <strong>어떻게 동작하는지</strong> 쉽고 명확하게 정리합니다.</p>
<hr>
<h2 id="✅-dom이란">✅ DOM이란?</h2>
<blockquote>
<p><strong>DOM (Document Object Model)</strong>은 웹 페이지를 <strong>트리 형태로 구조화한 객체 모델</strong>입니다.</p>
</blockquote>
<p>간단히 말해서:</p>
<ul>
<li>HTML 문서를 <strong>브라우저가 이해할 수 있는 객체(오브젝트) 구조로 만든 것</strong>입니다.</li>
<li>JavaScript로 쉽게 조작할 수 있게 해줍니다.</li>
</ul>
<hr>
<h2 id="📄-html-→-dom-변환-예시">📄 HTML → DOM 변환 예시</h2>
<p>HTML 문서가 있으면:</p>
<pre><code class="language-html">&lt;html&gt;
  &lt;body&gt;
    &lt;h1&gt;Hello&lt;/h1&gt;
    &lt;p&gt;Welcome to my website.&lt;/p&gt;
  &lt;/body&gt;
&lt;/html&gt;</code></pre>
<p>브라우저는 이걸 내부적으로 다음처럼 구조화합니다:</p>
<pre><code>Document
 └── html
      └── body
          ├── h1
          │    └── &quot;Hello&quot;
          └── p
               └── &quot;Welcome to my website.&quot;</code></pre><h3 id="✨-이-구조가-바로-dom-트리입니다">✨ 이 구조가 바로 <strong>DOM 트리</strong>입니다.</h3>
<hr>
<h2 id="🔧-dom-조작-예시">🔧 DOM 조작 예시</h2>
<p>JavaScript를 통해 DOM을 조작할 수 있습니다.</p>
<pre><code class="language-js">document.querySelector(&#39;h1&#39;).textContent = &#39;Hi there!&#39;;</code></pre>
<ul>
<li><code>h1</code> 요소를 선택하고</li>
<li>그 안의 텍스트를 <code>&quot;Hi there!&quot;</code>로 변경하는 코드입니다.</li>
</ul>
<p>➡️ 사용자가 보는 화면이 <strong>즉시 업데이트</strong> 됩니다.</p>
<hr>
<h2 id="🧠-dom을-왜-써야-할까">🧠 DOM을 왜 써야 할까?</h2>
<table>
<thead>
<tr>
<th>이유</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td><strong>브라우저와 소통</strong></td>
<td>브라우저가 화면에 표시하는 모든 것은 DOM을 통해 제어됨</td>
</tr>
<tr>
<td><strong>인터랙티브 웹 구현</strong></td>
<td>버튼 클릭, 데이터 입력 등 사용자 액션에 반응하려면 DOM을 조작해야 함</td>
</tr>
<tr>
<td><strong>UI 변경</strong></td>
<td>DOM 조작으로 화면 내용을 동적으로 수정 가능</td>
</tr>
</tbody></table>
<hr>
<h2 id="⚙️-dom-관련-주요-용어">⚙️ DOM 관련 주요 용어</h2>
<table>
<thead>
<tr>
<th>용어</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Document</strong></td>
<td>현재 웹 페이지 전체를 대표하는 객체</td>
</tr>
<tr>
<td><strong>Element</strong></td>
<td>HTML 요소 (<code>div</code>, <code>p</code>, <code>h1</code> 등) 하나하나</td>
</tr>
<tr>
<td><strong>Node</strong></td>
<td>DOM 트리의 모든 점 (텍스트, 태그, 속성 등 포함)</td>
</tr>
<tr>
<td><strong>Parent/Child</strong></td>
<td>DOM은 부모-자식 관계로 연결된 트리 구조</td>
</tr>
</tbody></table>
<hr>
<h2 id="📦-dom과-현대-프레임워크">📦 DOM과 현대 프레임워크</h2>
<p>React, Vue, LWC 같은 현대적인 프론트엔드 프레임워크들은 DOM을 더 효율적으로 다루기 위해 등장했습니다.</p>
<ul>
<li><strong>Virtual DOM</strong>: 실제 DOM에 바로 적용하지 않고 메모리상 가상 DOM에서 먼저 비교하고 최적화하여 적용</li>
<li><strong>Shadow DOM</strong>: 컴포넌트 단위로 독립된 DOM 영역을 생성해서 외부로부터 격리</li>
</ul>
<p>➡️ 결국, <strong>모두 DOM 조작을 효율적으로 하려는 것</strong>입니다.</p>
<hr>
<h2 id="✨-요약">✨ 요약</h2>
<table>
<thead>
<tr>
<th>항목</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>DOM이란?</td>
<td>HTML을 브라우저가 이해하고 조작할 수 있게 만든 트리 구조</td>
</tr>
<tr>
<td>왜 필요?</td>
<td>웹 페이지를 동적으로 수정하거나 사용자 입력에 반응하기 위해</td>
</tr>
<tr>
<td>어떻게 쓰나?</td>
<td>JavaScript로 요소를 선택하고 수정</td>
</tr>
<tr>
<td>현대 프레임워크와의 관계</td>
<td>DOM을 더 빠르고 효율적으로 다루기 위한 기술 (Virtual DOM, Shadow DOM 등)</td>
</tr>
</tbody></table>
<hr>
<p>#태그<br><code>#DOM</code> <code>#웹개발</code> <code>#프론트엔드</code> <code>#JavaScript</code> <code>#HTML</code> <code>#LWC</code></p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[VS Code] Salesforce Playground + VS Code 연결 방법]]></title>
            <link>https://velog.io/@hwan2-dev/VS-Code-Salesforce-Playground-VS-Code-%EC%97%B0%EA%B2%B0-%EB%B0%A9%EB%B2%95</link>
            <guid>https://velog.io/@hwan2-dev/VS-Code-Salesforce-Playground-VS-Code-%EC%97%B0%EA%B2%B0-%EB%B0%A9%EB%B2%95</guid>
            <pubDate>Thu, 24 Apr 2025 07:15:46 GMT</pubDate>
            <description><![CDATA[<ol>
<li><p>플레이 그라운드를 생성한다.</p>
</li>
<li><p>Setup -&gt; Users -&gt; Users 들어간다.</p>
</li>
<li><p>본인 계정을 클릭한다.</p>
</li>
<li><p>User Detail 에서 Reset Password 를 누른다.
<img src="https://velog.velcdn.com/images/hwan2-dev/post/a97adf09-120f-47a7-832e-756e3ee96f58/image.png" alt="">
그러면 등록된 이메일로 메일이 보내진다. 거기서 비밀번호 설정하면 됨.</p>
</li>
<li><p>만약 메일이 오지 않는다면
해당 유저를 다시 들어가면
Reset Password 버튼이 Change Password 로 바뀌어있을거임.
그거 누르고 새 비밀번호 설정하면 됨.</p>
</li>
<li><p>VS Code 에서 
Authorize an Org 해서 해당 계정으로 로그인하면 됨.</p>
</li>
</ol>
<p>끝.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[VS Code] Salesforce LWC 에서 Jest 사용 방법]]></title>
            <link>https://velog.io/@hwan2-dev/VS-Code-Salesforce-LWC-%EC%97%90%EC%84%9C-Jest-%EC%82%AC%EC%9A%A9-%EB%B0%A9%EB%B2%95</link>
            <guid>https://velog.io/@hwan2-dev/VS-Code-Salesforce-LWC-%EC%97%90%EC%84%9C-Jest-%EC%82%AC%EC%9A%A9-%EB%B0%A9%EB%B2%95</guid>
            <pubDate>Thu, 24 Apr 2025 05:33:55 GMT</pubDate>
            <description><![CDATA[<p>VS Code 에서 JS 파일을 테스트 하는 방법</p>
<p>우선 Node.js가 있어야 함.
Node.js 가 없다면 설치하고 오시오.</p>
<p>그 다음 npm으로 해당 프로젝트에 Jest 를 위한 라이브러리를 설치한다.</p>
<hr>
<h2 id="✅-전체-명령어">✅ 전체 명령어:</h2>
<pre><code class="language-bash">npm install --save-dev sfdx-lwc-jest</code></pre>
<h3 id="💡-해석">💡 해석:</h3>
<blockquote>
<p><code>npm install</code>  </p>
<blockquote>
<p>→ <code>sfdx-lwc-jest</code>라는 npm 패키지를 설치하겠다</p>
</blockquote>
</blockquote>
<blockquote>
<p><code>--save-dev</code>  </p>
<blockquote>
<p>→ 이 패키지를 <strong>개발할 때만 필요한 도구(devDependency)</strong>로 설치하겠다</p>
</blockquote>
</blockquote>
<hr>
<h2 id="✅-그럼---save-dev는-왜-쓰는-건가">✅ 그럼 <code>--save-dev</code>는 왜 쓰는 건가?</h2>
<h3 id="📦---save-dev로-설치한-패키지는">📦 <code>--save-dev</code>로 설치한 패키지는:</h3>
<ul>
<li><code>package.json</code>의 <code>&quot;devDependencies&quot;</code>에 등록됨</li>
<li><strong>배포할 때 포함되지 않음</strong></li>
<li>예: <strong>테스트 도구, 빌드 도구, 린터, 번들러 등</strong></li>
</ul>
<hr>
<h2 id="✅-반대로---save는">✅ 반대로 <code>--save</code>는?</h2>
<ul>
<li>(요즘은 생략 가능)  </li>
<li><code>&quot;dependencies&quot;</code>에 등록됨</li>
<li>실제 서비스 구동에도 필요한 라이브러리용</li>
</ul>
<table>
<thead>
<tr>
<th>구분</th>
<th>쓰임</th>
<th>예시</th>
</tr>
</thead>
<tbody><tr>
<td><code>--save-dev</code></td>
<td>개발 전용 도구</td>
<td>Jest, ESLint, Webpack 등</td>
</tr>
<tr>
<td><code>--save</code> or 생략</td>
<td>앱에서 직접 쓰는 라이브러리</td>
<td>React, Axios 등</td>
</tr>
</tbody></table>
<hr>
<h2 id="🔍-예시-packagejson에-반영되는-모습">🔍 예시: package.json에 반영되는 모습</h2>
<pre><code class="language-json">&quot;devDependencies&quot;: {
  &quot;sfdx-lwc-jest&quot;: &quot;^12.0.0&quot;
}</code></pre>
<p>이렇게 되면 <strong>다른 개발자들도 <code>npm install</code> 한 번이면 자동 설치</strong>되니까 협업에도 좋아요.</p>
<hr>
<h3 id="🔧-요약-정리">🔧 요약 정리</h3>
<table>
<thead>
<tr>
<th>명령어</th>
<th>의미</th>
</tr>
</thead>
<tbody><tr>
<td><code>npm install</code></td>
<td>모듈 설치</td>
</tr>
<tr>
<td><code>--save-dev</code></td>
<td>개발용으로만 쓰겠다는 뜻</td>
</tr>
<tr>
<td><code>sfdx-lwc-jest</code></td>
<td>Salesforce LWC 유닛 테스트 도구</td>
</tr>
</tbody></table>
<hr>
<p>이렇게 설치를 하면 테스트 할 수 있는 라이브러리 준비는 끝이다.</p>
<hr>
<p>테스트 방법은 다음과 같다.</p>
<p>방법 1.
LWC 폴더에 <strong>__</strong>tests__ 폴더가 있다. 그 안에 있는 파일명.test.js 파일을 들어가서
<img src="https://velog.velcdn.com/images/hwan2-dev/post/425570e1-d461-4907-9895-ede69e5ff8ad/image.png" alt="">
sum.js 를 불러와서 해당 js 안에 sum() 이라는 함수를 테스트하는 과정이다.
회색 글씨로 Run Test 있는데 저걸 클릭하면 알아서 테스트를 진행한다.</p>
<hr>
<p>방법 2.
터미널 명령어로 npm run test:unit 을 치면 프로젝트에 있는 모든 .test.js 파일이 테스트 실행한다. <img src="https://velog.velcdn.com/images/hwan2-dev/post/a0e2b3e3-b52b-4174-a789-470d8e8105db/image.png" alt="">
그래서 해당 방법으로 특정 .test.js 만 실행하고 싶다면
<img src="https://velog.velcdn.com/images/hwan2-dev/post/2e914a5f-b51e-49ba-af6c-e5a99805b396/image.png" alt="">
저렇게 &quot;test:one&quot; 을 추가해서 파일 경로를 지정한 뒤
npm run test:one 명령어를 치면된다.
저기서 one 은 그냥 임의로 만든 스크립트 이름이다. 맘대로 정하면 됨.</p>
<hr>
<p>방법 3.
명령어로 바로 테스트하는 방법인데 이 방법이 젤 간편한 거 같다.
명령어로</p>
<pre><code>npx jest 파일명.test.js</code></pre><p>또는</p>
<pre><code>npx sfdx-lwc-jest -- 파일명.test.js</code></pre><p>치면 된다.</p>
<p>만약 같은 이름의 파일명.test.js 파일이 두 개 이상 있다면?
-&gt; 둘 다 실행됨.</p>
<hr>
<p>끝.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Node.js] npm vs npx 차이]]></title>
            <link>https://velog.io/@hwan2-dev/npm-vs-npx-%EC%B0%A8%EC%9D%B4</link>
            <guid>https://velog.io/@hwan2-dev/npm-vs-npx-%EC%B0%A8%EC%9D%B4</guid>
            <pubDate>Thu, 24 Apr 2025 05:27:57 GMT</pubDate>
            <description><![CDATA[<h1 id="🔍-npm-vs-npx-차이-한-번에-이해하기">🔍 npm vs npx 차이, 한 번에 이해하기</h1>
<p>개발을 하다 보면 자주 등장하는 두 명령어 <code>npm</code>과 <code>npx</code>.  
비슷하게 생겼지만 용도는 완전히 다릅니다.<br>이 글에서는 둘의 <strong>정확한 차이</strong>, <strong>언제 어떤 걸 써야 하는지</strong>, 그리고 <strong>실무에서의 활용법</strong>까지 정리해드립니다.</p>
<hr>
<h2 id="✅-간단-요약">✅ 간단 요약</h2>
<table>
<thead>
<tr>
<th>구분</th>
<th><code>npm</code></th>
<th><code>npx</code></th>
</tr>
</thead>
<tbody><tr>
<td>주 목적</td>
<td>패키지 <strong>설치 &amp; 관리</strong></td>
<td>패키지 <strong>즉시 실행</strong></td>
</tr>
<tr>
<td>설치 여부 필요</td>
<td>✅ 설치 필요</td>
<td>❌ 설치 없이도 실행 가능</td>
</tr>
<tr>
<td>사용 위치</td>
<td>주로 프로젝트 내부에서</td>
<td>로컬 또는 글로벌 어디서나</td>
</tr>
<tr>
<td>대표 용도</td>
<td><code>npm install</code>, <code>npm run</code></td>
<td>CLI 실행, 일회성 명령어 실행</td>
</tr>
</tbody></table>
<hr>
<h2 id="📦-npm이란">📦 <code>npm</code>이란?</h2>
<blockquote>
<p><code>npm (Node Package Manager)</code>는 패키지를 <strong>설치하고 관리하는 도구</strong>입니다.</p>
</blockquote>
<h3 id="🔧-예시">🔧 예시</h3>
<pre><code class="language-bash">npm install jest --save-dev</code></pre>
<ul>
<li><code>jest</code>를 프로젝트에 설치</li>
<li><code>node_modules</code>에 저장</li>
<li>나중에 <code>npm run test</code>로 사용</li>
</ul>
<hr>
<h2 id="🚀-npx란">🚀 <code>npx</code>란?</h2>
<blockquote>
<p><code>npx</code>는 설치하지 않아도 <strong>즉시 실행할 수 있는 실행 도구</strong>입니다.</p>
</blockquote>
<h3 id="🔧-예시-1">🔧 예시</h3>
<pre><code class="language-bash">npx jest</code></pre>
<ul>
<li>프로젝트에 jest가 설치되어 있다면 그것을 실행</li>
<li>없다면 <strong>임시로 다운로드</strong>해서 실행</li>
<li>실행 후 자동 삭제</li>
</ul>
<hr>
<h2 id="💬-쉽게-비교해보면">💬 쉽게 비교해보면</h2>
<table>
<thead>
<tr>
<th>상황</th>
<th>npm 사용</th>
<th>npx 사용</th>
</tr>
</thead>
<tbody><tr>
<td>CLI 도구를 설치하고 계속 쓸 때</td>
<td>✅ <code>npm install eslint</code></td>
<td>❌</td>
</tr>
<tr>
<td>CLI 도구를 한 번만 실행하고 말 때</td>
<td>❌</td>
<td>✅ <code>npx create-react-app my-app</code></td>
</tr>
<tr>
<td>특정 테스트 파일을 바로 실행할 때</td>
<td>❌</td>
<td>✅ <code>npx sfdx-lwc-jest -- sum.test.js</code></td>
</tr>
</tbody></table>
<hr>
<h2 id="🧪-실전-예시-salesforce-lwc-테스트">🧪 실전 예시: Salesforce LWC 테스트</h2>
<h3 id="npm-run-testunit"><code>npm run test:unit</code></h3>
<pre><code class="language-json">&quot;scripts&quot;: {
  &quot;test:unit&quot;: &quot;sfdx-lwc-jest&quot;
}</code></pre>
<ul>
<li>전체 테스트 실행</li>
<li>사전에 스크립트 등록 필요</li>
</ul>
<h3 id="npx-sfdx-lwc-jest----파일경로"><code>npx sfdx-lwc-jest -- [파일경로]</code></h3>
<pre><code class="language-bash">npx sfdx-lwc-jest -- force-app/main/default/lwc/myComp/__tests__/myComp.test.js</code></pre>
<ul>
<li>특정 테스트 파일만 실행</li>
<li>경로만 알면 스크립트 없이 바로 실행 가능</li>
</ul>
<hr>
<h2 id="✨-결론">✨ 결론</h2>
<table>
<thead>
<tr>
<th>요약</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td><code>npm</code>은 설치 &amp; 관리용</td>
<td>패키지를 가져와서 나중에 쓸 수 있도록 저장</td>
</tr>
<tr>
<td><code>npx</code>는 실행 전용</td>
<td>설치하지 않아도 즉시 실행 가능 (특히 CLI에 유용)</td>
</tr>
</tbody></table>
]]></description>
        </item>
        <item>
            <title><![CDATA[Loyalty와 Royalty의 차이]]></title>
            <link>https://velog.io/@hwan2-dev/Loyalty%EC%99%80-Royalty%EC%9D%98-%EC%B0%A8%EC%9D%B4</link>
            <guid>https://velog.io/@hwan2-dev/Loyalty%EC%99%80-Royalty%EC%9D%98-%EC%B0%A8%EC%9D%B4</guid>
            <pubDate>Thu, 24 Apr 2025 02:27:35 GMT</pubDate>
            <description><![CDATA[<p><strong>Loyalty</strong>와 <strong>Royalty</strong>는 비즈니스, 마케팅, 콘텐츠 산업에서 자주 등장하는 단어입니다.<br>발음은 비슷하지만 <strong>의미는 완전히 다르며</strong>, 헷갈릴 경우 실제 업무에서 혼선을 줄 수 있습니다.</p>
<p>이번 글에서는 두 개념을 명확히 구분하고, 헷갈리지 않도록 정리해드립니다.</p>
<hr>
<h2 id="✅-loyalty로열티-고객의-충성도">✅ Loyalty(로열티): 고객의 충성도</h2>
<blockquote>
<p>Loyalty는 고객이 브랜드나 서비스에 대해 <strong>애착을 갖고 지속적으로 이용하는 정도</strong>를 말합니다.</p>
</blockquote>
<h3 id="🎁-대표-개념-loyalty-program-멤버십-포인트-마일리지-등">🎁 대표 개념: Loyalty Program (멤버십, 포인트, 마일리지 등)</h3>
<p>고객의 반복 구매를 유도하기 위해 포인트, 쿠폰, 등급 등의 혜택을 제공하는 마케팅 전략입니다.</p>
<h4 id="📌-예시">📌 예시</h4>
<ul>
<li>커피숍에서 10잔 사면 1잔 무료</li>
<li>항공사 마일리지 적립</li>
<li>네이버페이 포인트, 롯데멤버스 리워드</li>
</ul>
<hr>
<h2 id="✅-royalty로열티-자산-사용에-대한-대가">✅ Royalty(로열티): 자산 사용에 대한 대가</h2>
<blockquote>
<p>Royalty는 <strong>콘텐츠, 기술, 상표 등 지식재산을 사용할 때 발생하는 사용료 또는 수익 분배</strong>를 말합니다.</p>
</blockquote>
<h3 id="💡-대표-개념-저작권료-특허-사용료-라이선스-비용">💡 대표 개념: 저작권료, 특허 사용료, 라이선스 비용</h3>
<p>창작물이나 브랜드, 기술을 사용하는 사람은 소유자에게 로열티를 지급하게 됩니다.</p>
<h4 id="📌-예시-1">📌 예시</h4>
<ul>
<li>작가의 책 판매 수익 중 인세</li>
<li>유튜브·멜론 등의 음원 스트리밍 수익 정산</li>
<li>캐릭터나 로고 사용 시 브랜드 라이선스 비용</li>
<li>특허 기술을 사용한 제품의 수익 분배</li>
</ul>
<hr>
<h2 id="📊-loyalty-vs-royalty-비교표">📊 Loyalty vs Royalty 비교표</h2>
<table>
<thead>
<tr>
<th>항목</th>
<th><strong>Loyalty</strong></th>
<th><strong>Royalty</strong></th>
</tr>
</thead>
<tbody><tr>
<td>📘 의미</td>
<td>고객의 애착, 반복 이용</td>
<td>자산(저작권, 기술 등)의 사용료</td>
</tr>
<tr>
<td>🙋‍♀️ 대상</td>
<td>고객, 사용자</td>
<td>창작자, 권리자, 소유자</td>
</tr>
<tr>
<td>🎁 예시</td>
<td>포인트, 쿠폰, 마일리지</td>
<td>인세, 특허료, 스트리밍 수익</td>
</tr>
<tr>
<td>💬 맥락</td>
<td>마케팅, 고객 보상, CRM</td>
<td>라이선스 계약, 콘텐츠 수익 정산</td>
</tr>
<tr>
<td>🔤 발음</td>
<td>/ˈlɔɪ.əl.ti/</td>
<td>/ˈrɔɪ.əl.ti/</td>
</tr>
</tbody></table>
<hr>
<h2 id="❗-자주-헷갈리는-표현-예시">❗ 자주 헷갈리는 표현 예시</h2>
<table>
<thead>
<tr>
<th>❌ 잘못된 표현</th>
<th>✅ 올바른 표현</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td>로열티 포인트</td>
<td>Loyalty 포인트</td>
<td>고객 보상은 Royalty가 아니라 Loyalty</td>
</tr>
<tr>
<td>로열티 프로그램</td>
<td>Loyalty 프로그램</td>
<td>멤버십은 충성도 관리 전략</td>
</tr>
<tr>
<td>로열티 적립</td>
<td>포인트 적립</td>
<td>사용료 개념이 아님</td>
</tr>
</tbody></table>
<hr>
<h2 id="🧠-기억하세요">🧠 기억하세요!</h2>
<blockquote>
<p><strong>Loyalty</strong>는 &quot;고객 충성도&quot;,<br><strong>Royalty</strong>는 &quot;사용 대가(저작권료)&quot;입니다.</p>
</blockquote>
<p>두 단어는 비슷해 보여도 <strong>의미, 대상, 목적이 완전히 다릅니다.</strong><br>기획서나 미팅에서 &quot;로열티&quot;라는 말을 쓸 때, 이게 충성도인지 사용료인지 정확히 구분해보세요!</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[VS Code] 자주 쓰는 Salesforce Org 명령어 모음표]]></title>
            <link>https://velog.io/@hwan2-dev/VS-Code-%EC%9E%90%EC%A3%BC-%EC%93%B0%EB%8A%94-Salesforce-Org-%EB%AA%85%EB%A0%B9%EC%96%B4-%EB%AA%A8%EC%9D%8C%ED%91%9C</link>
            <guid>https://velog.io/@hwan2-dev/VS-Code-%EC%9E%90%EC%A3%BC-%EC%93%B0%EB%8A%94-Salesforce-Org-%EB%AA%85%EB%A0%B9%EC%96%B4-%EB%AA%A8%EC%9D%8C%ED%91%9C</guid>
            <pubDate>Tue, 22 Apr 2025 07:43:37 GMT</pubDate>
            <description><![CDATA[<h1 id="🧩-salesforce-org-명령어-모음표">🧩 Salesforce Org 명령어 모음표</h1>
<table>
<thead>
<tr>
<th>구분</th>
<th>설명</th>
<th><code>sf</code> 명령어 (최신)</th>
<th><code>sfdx</code> 명령어 (기존)</th>
</tr>
</thead>
<tbody><tr>
<td>✅ Org 로그인</td>
<td>브라우저로 Org 인증</td>
<td><code>sf org login web --alias [별칭]</code></td>
<td><code>sfdx auth:web:login -a [별칭]</code></td>
</tr>
<tr>
<td>✅ Org 샌드박스 로그인</td>
<td>브라우저로 Org 인증</td>
<td><code>sf org login web --alias [별칭] --instance-url https://test.salesforce.com</code></td>
<td></td>
</tr>
<tr>
<td>🧾 Org 목록 보기</td>
<td>연결된 모든 Org 확인</td>
<td><code>sf org list</code></td>
<td><code>sfdx force:org:list</code></td>
</tr>
<tr>
<td>⭐ 디폴트 Org 설정</td>
<td>기본으로 사용할 Org 지정</td>
<td><code>sf config set target-org=[별칭]</code></td>
<td><code>sfdx force:config:set defaultusername=[별칭]</code></td>
</tr>
<tr>
<td>❓ 디폴트 Org 확인</td>
<td>현재 연결된 기본 Org 보기</td>
<td><code>sf config get target-org</code></td>
<td><code>sfdx force:config:get defaultusername</code></td>
</tr>
<tr>
<td>🌐 Org 열기</td>
<td>브라우저에서 Org 열기</td>
<td><code>sf org open</code></td>
<td><code>sfdx force:org:open</code></td>
</tr>
<tr>
<td>🔍 Org 정보 보기</td>
<td>Org ID, 사용자, 도메인 확인</td>
<td><code>sf org display</code></td>
<td><code>sfdx force:org:display</code></td>
</tr>
<tr>
<td>🚪 로그아웃</td>
<td>연결 해제</td>
<td><code>sf org logout --target-org [별칭]</code></td>
<td><code>sfdx auth:logout -u [별칭]</code></td>
</tr>
<tr>
<td>🧪 Scratch Org 생성</td>
<td>임시 개발 Org 생성</td>
<td><code>sf org create scratch --alias dev1</code></td>
<td><code>sfdx force:org:create -f config/project-scratch-def.json -a dev1 -d 7 -s</code></td>
</tr>
<tr>
<td>❌ Scratch Org 삭제</td>
<td>Scratch Org 제거</td>
<td><code>sf org delete scratch --target-org dev1</code></td>
<td><code>sfdx force:org:delete -u dev1</code></td>
</tr>
<tr>
<td>🔃 Org와 연결된 사용자 보기</td>
<td>해당 Org 사용자 목록 출력</td>
<td>–</td>
<td><code>sfdx force:user:list -u [별칭]</code></td>
</tr>
</tbody></table>
<hr>
<h2 id="✨-실무-팁">✨ 실무 팁</h2>
<table>
<thead>
<tr>
<th>목적</th>
<th>자주 쓰는 명령어</th>
</tr>
</thead>
<tbody><tr>
<td><strong>Org 연결 상태 점검</strong></td>
<td><code>sf org list</code> 또는 <code>sfdx force:org:list</code></td>
</tr>
<tr>
<td><strong>브라우저로 빠르게 열기</strong></td>
<td><code>sf org open</code></td>
</tr>
<tr>
<td><strong>Org 정보 출력 후 기록</strong></td>
<td><code>sf org display &gt; org-info.txt</code></td>
</tr>
<tr>
<td><strong>복수 프로젝트 관리</strong></td>
<td>Org마다 별칭(alias)을 지정해서 구분</td>
</tr>
</tbody></table>
<hr>
<h2 id="💬-예시-명령어-모음-복붙용">💬 예시 명령어 모음 (복붙용)</h2>
<pre><code class="language-bash"># Org 인증
sf org login web --alias vscodeOrg

# 디폴트 org 설정
sf config set target-org=vscodeOrg

# Org 열기
sf org open

# Org 정보 확인
sf org display

# Org 목록 보기
sf org list

# 연결 해제
sf org logout --target-org vscodeOrg</code></pre>
<hr>
]]></description>
        </item>
        <item>
            <title><![CDATA[[VS Code] Create Project with Manifest에 관하여]]></title>
            <link>https://velog.io/@hwan2-dev/VS-Code-Create-Project-with-Manifest</link>
            <guid>https://velog.io/@hwan2-dev/VS-Code-Create-Project-with-Manifest</guid>
            <pubDate>Tue, 22 Apr 2025 07:14:00 GMT</pubDate>
            <description><![CDATA[<h1 id="🧩-sfdx-프로젝트-생성-방식-비교">🧩 SFDX 프로젝트 생성 방식 비교</h1>
<table>
<thead>
<tr>
<th>항목</th>
<th>일반 프로젝트 생성<br><code>SFDX: Create Project</code></th>
<th>매니페스트 포함 생성<br><code>SFDX: Create Project with Manifest</code></th>
</tr>
</thead>
<tbody><tr>
<td>📂 폴더 구조</td>
<td><code>force-app/</code>만 생성</td>
<td><code>force-app/</code> + <code>manifest/</code> 폴더 생성</td>
</tr>
<tr>
<td>🧾 <code>package.xml</code> 포함 여부</td>
<td>❌ 없음</td>
<td>✅ <strong>포함됨</strong> (모든 메타데이터 타입 포함한 템플릿 제공)</td>
</tr>
<tr>
<td>🔄 retrieve 방식</td>
<td>수동 선택 (<code>-m</code> 옵션 or Org Browser)</td>
<td><code>package.xml</code> 기준으로 자동 가져오기 가능</td>
</tr>
<tr>
<td>Git 관리 편의성</td>
<td>❌ 가져온 항목 추적 어려움</td>
<td>✅ 가져올 대상 명확하게 추적 가능</td>
</tr>
<tr>
<td>협업 시 일관성</td>
<td>❌ 가져온 항목이 사람마다 다를 수 있음</td>
<td>✅ 동일한 package.xml 사용으로 <strong>공통 기반 확보 가능</strong></td>
</tr>
<tr>
<td>반복 배포/백업</td>
<td>❌ 명령 재사용 어려움</td>
<td>✅ <code>package.xml</code> 한 번 작성해두면 반복 활용 가능</td>
</tr>
<tr>
<td>추천 대상</td>
<td>빠르게 새 기능을 개발하거나 실습할 때</td>
<td>실무 개발, 팀 협업, Org 메타데이터 관리 목적일 때</td>
</tr>
<tr>
<td>기타 장점</td>
<td>간단하고 빠름</td>
<td><strong>대규모 Org에 최적</strong>, 메타데이터 관리 유리</td>
</tr>
</tbody></table>
<hr>
<h2 id="🔍-두-방식의-retrieve-예시-차이">🔍 두 방식의 retrieve 예시 차이</h2>
<h3 id="⛔-일반-프로젝트">⛔ 일반 프로젝트</h3>
<pre><code class="language-bash">sfdx force:source:retrieve -m ApexClass</code></pre>
<ul>
<li>→ ApexClass 전체 또는 일부를 직접 명령어에 입력해야 함</li>
<li>→ 어떤 항목이 들어오는지 추적 어려움</li>
</ul>
<hr>
<h3 id="✅-매니페스트-프로젝트">✅ 매니페스트 프로젝트</h3>
<pre><code class="language-bash">sfdx force:source:retrieve -x manifest/package.xml</code></pre>
<ul>
<li>→ XML에 적힌 메타데이터만 가져옴</li>
<li>→ 추적 가능, Git에 함께 보관 가능</li>
</ul>
<hr>
<h2 id="🛠-실무-팁-매니페스트-관리-전략">🛠 실무 팁: 매니페스트 관리 전략</h2>
<table>
<thead>
<tr>
<th>전략</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td><code>package.xml</code>을 목적별로 분리</td>
<td>예: <code>package_apex.xml</code>, <code>package_flows.xml</code>, <code>package_ui.xml</code></td>
</tr>
<tr>
<td>커밋 시 함께 보관</td>
<td>Git에 <code>manifest/</code> 폴더 그대로 커밋</td>
</tr>
<tr>
<td>팀원 간 공유</td>
<td>→ 팀 전체가 동일한 retrieve/배포 대상 사용 가능</td>
</tr>
<tr>
<td>코드 리뷰에도 용이</td>
<td>가져올 대상 명시되어 있어 변경사항 추적 쉬움</td>
</tr>
</tbody></table>
<hr>
<h2 id="📌-추가로-알면-좋은-내용">📌 추가로 알면 좋은 내용</h2>
<table>
<thead>
<tr>
<th>개념</th>
<th>설명</th>
</tr>
</thead>
<tbody><tr>
<td><code>*</code> 와일드카드</td>
<td><code>members&gt;*&lt;/members&gt;</code>는 해당 타입의 <strong>모든 항목</strong>을 의미</td>
</tr>
<tr>
<td>retrieve vs deploy</td>
<td><code>retrieve</code>: Org → 로컬<br><code>deploy</code>: 로컬 → Org</td>
</tr>
<tr>
<td>Org Browser</td>
<td>매니페스트 없이도 특정 항목만 클릭으로 가져올 수 있는 도구 (GUI 방식)</td>
</tr>
<tr>
<td><code>.gitignore</code>와의 관계</td>
<td><code>package.xml</code>은 <strong>가져올 대상 정의</strong>, <code>.gitignore</code>은 <strong>버전 관리 제외 대상 정의</strong></td>
</tr>
<tr>
<td>package.xml 없이 retrieve</td>
<td>가능하지만 반복 불가하고 추적 어려움 (임시적 활용에 적합)</td>
</tr>
</tbody></table>
<hr>
<h2 id="✅-결론-요약">✅ 결론 요약</h2>
<table>
<thead>
<tr>
<th>목적</th>
<th>추천 생성 방식</th>
</tr>
</thead>
<tbody><tr>
<td>빠르게 코드 실습만 해보려는 경우</td>
<td><code>SFDX: Create Project</code> (간단하고 가볍게)</td>
</tr>
<tr>
<td>기존 Org에서 코드/구성요소를 체계적으로 가져와서 개발하려는 경우</td>
<td><code>SFDX: Create Project with Manifest</code> <strong>(강력 추천)</strong></td>
</tr>
<tr>
<td>팀 협업, Git 연동, 배포 자동화까지 고려하는 실무 환경</td>
<td><strong>무조건 매니페스트 방식 추천</strong></td>
</tr>
</tbody></table>
<hr>
<p><strong>실제 실무에서 자주 사용하는 <code>package.xml</code> 예시</strong>를 보여드릴게요.</p>
<hr>
<h1 id="📦-packagexml-샘플-예시-대표-메타데이터-포함">📦 <code>package.xml</code> 샘플 예시 (대표 메타데이터 포함)</h1>
<pre><code class="language-xml">&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;
&lt;Package xmlns=&quot;http://soap.sforce.com/2006/04/metadata&quot;&gt;

  &lt;!-- Apex 클래스 전체 --&gt;
  &lt;types&gt;
    &lt;members&gt;*&lt;/members&gt;
    &lt;name&gt;ApexClass&lt;/name&gt;
  &lt;/types&gt;

  &lt;!-- Apex 트리거 전체 --&gt;
  &lt;types&gt;
    &lt;members&gt;*&lt;/members&gt;
    &lt;name&gt;ApexTrigger&lt;/name&gt;
  &lt;/types&gt;

  &lt;!-- LWC (LightningComponentBundle) 전체 --&gt;
  &lt;types&gt;
    &lt;members&gt;*&lt;/members&gt;
    &lt;name&gt;LightningComponentBundle&lt;/name&gt;
  &lt;/types&gt;

  &lt;!-- 사용자 정의 객체 일부만 가져오기 --&gt;
  &lt;types&gt;
    &lt;members&gt;Account&lt;/members&gt;
    &lt;members&gt;CustomObject__c&lt;/members&gt;
    &lt;name&gt;CustomObject&lt;/name&gt;
  &lt;/types&gt;

  &lt;!-- 사용자 정의 필드 일부만 가져오기 --&gt;
  &lt;types&gt;
    &lt;members&gt;Account.My_Custom_Field__c&lt;/members&gt;
    &lt;name&gt;CustomField&lt;/name&gt;
  &lt;/types&gt;

  &lt;!-- 페이지 레이아웃 전체 --&gt;
  &lt;types&gt;
    &lt;members&gt;*&lt;/members&gt;
    &lt;name&gt;Layout&lt;/name&gt;
  &lt;/types&gt;

  &lt;!-- 권한 세트 전체 --&gt;
  &lt;types&gt;
    &lt;members&gt;*&lt;/members&gt;
    &lt;name&gt;PermissionSet&lt;/name&gt;
  &lt;/types&gt;

  &lt;!-- 정적 리소스 전체 --&gt;
  &lt;types&gt;
    &lt;members&gt;*&lt;/members&gt;
    &lt;name&gt;StaticResource&lt;/name&gt;
  &lt;/types&gt;

  &lt;!-- API 버전 --&gt;
  &lt;version&gt;59.0&lt;/version&gt;

&lt;/Package&gt;</code></pre>
<hr>
<h2 id="✅-이-예시의-특징">✅ 이 예시의 특징</h2>
<table>
<thead>
<tr>
<th>포함된 항목</th>
<th>용도</th>
</tr>
</thead>
<tbody><tr>
<td><code>ApexClass</code>, <code>ApexTrigger</code></td>
<td>백엔드 코드 자동 가져오기</td>
</tr>
<tr>
<td><code>LightningComponentBundle</code></td>
<td>LWC 전체</td>
</tr>
<tr>
<td><code>CustomObject</code>, <code>CustomField</code></td>
<td>객체 및 필드 설정 관리</td>
</tr>
<tr>
<td><code>Layout</code>, <code>PermissionSet</code></td>
<td>사용자 UI 및 권한 구성</td>
</tr>
<tr>
<td><code>StaticResource</code></td>
<td>이미지, CSS, JS 등 정적 리소스 포함</td>
</tr>
</tbody></table>
<hr>
<h2 id="🛠-사용하는-방법">🛠 사용하는 방법</h2>
<p>프로젝트 루트에 <code>manifest/package.xml</code> 파일을 만든 뒤, 아래 명령어로 retrieve:</p>
<pre><code class="language-bash">sfdx force:source:retrieve -x manifest/package.xml</code></pre>
<p>또는 <code>sf</code> CLI에서는:</p>
<pre><code class="language-bash">sf project retrieve start --manifest manifest/package.xml</code></pre>
<hr>
<h2 id="✳️-필요에-따라-커스터마이징-가능">✳️ 필요에 따라 커스터마이징 가능</h2>
<ul>
<li><p>특정 클래스만 가져오려면:</p>
<pre><code class="language-xml">&lt;members&gt;MyClass&lt;/members&gt;</code></pre>
</li>
<li><p>특정 객체만 가져오고 싶다면:</p>
<pre><code class="language-xml">&lt;members&gt;Contact&lt;/members&gt;</code></pre>
</li>
</ul>
]]></description>
        </item>
        <item>
            <title><![CDATA[[VS Code] Agentforce for Developers Extension에 관하여]]></title>
            <link>https://velog.io/@hwan2-dev/VS-Code-Agentforce-for-Developers-Extension%EC%97%90-%EA%B4%80%ED%95%98%EC%97%AC</link>
            <guid>https://velog.io/@hwan2-dev/VS-Code-Agentforce-for-Developers-Extension%EC%97%90-%EA%B4%80%ED%95%98%EC%97%AC</guid>
            <pubDate>Tue, 22 Apr 2025 06:24:35 GMT</pubDate>
            <description><![CDATA[<p>Agentforce for Developers는 Salesforce가 제공하는 AI 기반 개발 도구로, Visual Studio Code 확장 프로그램으로 제공됩니다. 이 도구는 Salesforce 개발자들이 Apex 및 Lightning Web Components(LWC) 개발을 보다 효율적으로 수행할 수 있도록 지원합니다.​</p>
<p>🧠 주요 기능</p>
<ol>
<li>Dev Assistant와의 대화형 지원
코드 작성 중 자연어로 질문하거나 요청하면, Dev Assistant가 실시간으로 도움을 제공합니다.</li>
</ol>
<p>예: /explain 명령어를 통해 코드 설명을 요청하거나, /test로 테스트 코드 생성을 요청할 수 있습니다.​</p>
<ol start="2">
<li>인라인 코드 자동 완성
Apex 및 LWC(JavaScript, HTML, CSS) 파일에서 코드를 입력할 때, AI가 실시간으로 코드 완성 제안을 제공합니다.</li>
</ol>
<p>이 기능은 Salesforce의 커스텀 LLM인 CodeGen2.5를 기반으로 작동합니다.​</p>
<ol start="3">
<li><p>테스트 코드 자동 생성
작성한 Apex 메서드나 LWC 컴포넌트에 대한 단위 테스트 코드를 자동으로 생성하여 코드 커버리지를 향상시킬 수 있습니다.​</p>
</li>
<li><p>명령 팔레트 기반 코드 생성
VS Code의 명령 팔레트에서 &quot;Agentforce: Generate Code&quot; 명령어를 사용하여, 원하는 기능을 자연어로 설명하면 해당하는 Apex 코드를 생성해줍니다.​</p>
</li>
<li><p>코드 설명 및 문서화
/explain 명령어로 복잡한 코드를 설명받거나, /document 명령어로 코드에 대한 문서를 자동으로 생성할 수 있습니다.​</p>
</li>
</ol>
<p>⚙️ 설치 및 사용 방법</p>
<ol>
<li>필수 조건
Visual Studio Code 버전 1.90.0 이상</li>
</ol>
<p>Salesforce Extension Pack 설치</p>
<p>Salesforce CLI 설치 및 설정​</p>
<ol start="2">
<li><p>설치 방법
VS Code의 확장 프로그램 마켓플레이스에서 &quot;Agentforce for Developers&quot;를 검색하여 설치하거나, Salesforce Extension Pack을 설치하면 함께 설치됩니다.​</p>
</li>
<li><p>사용 방법
VS Code 하단의 상태 표시줄에 있는 Agentforce 아이콘을 클릭하여 활성화하거나 비활성화할 수 있습니다.</p>
</li>
</ol>
<p>명령 팔레트(Ctrl+Shift+P)에서 &quot;Agentforce&quot;로 시작하는 명령어들을 실행하여 다양한 기능을 사용할 수 있습니다.​</p>
<p>🔒 주의사항
Agentforce for Developers는 AI 기반 도구이므로, 생성된 코드나 응답이 항상 정확하거나 안전하지 않을 수 있습니다.</p>
<p>따라서, 생성된 코드를 실제 프로젝트에 적용하기 전에 반드시 검토하고 테스트하는 것이 중요합니다.​</p>
<h3 id="한글은-못-알아먹음-영어로-질문해야함">한글은 못 알아먹음. 영어로 질문해야함.</h3>
<h3 id="답변도-무조건-영어인거같음">답변도 무조건 영어인거같음.</h3>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Java] Salesforce 개발을 위한 JDK 설치 및 환경변수 설정]]></title>
            <link>https://velog.io/@hwan2-dev/Java-Salesforce-%EA%B0%9C%EB%B0%9C%EC%9D%84-%EC%9C%84%ED%95%9C-JDK-%EC%84%A4%EC%B9%98-%EB%B0%8F-%ED%99%98%EA%B2%BD%EB%B3%80%EC%88%98-%EC%84%A4</link>
            <guid>https://velog.io/@hwan2-dev/Java-Salesforce-%EA%B0%9C%EB%B0%9C%EC%9D%84-%EC%9C%84%ED%95%9C-JDK-%EC%84%A4%EC%B9%98-%EB%B0%8F-%ED%99%98%EA%B2%BD%EB%B3%80%EC%88%98-%EC%84%A4</guid>
            <pubDate>Tue, 22 Apr 2025 04:58:28 GMT</pubDate>
            <description><![CDATA[<p>참고 링크 : <a href="https://developer.salesforce.com/docs/platform/sfvscode-extensions/guide/java-setup.html">https://developer.salesforce.com/docs/platform/sfvscode-extensions/guide/java-setup.html</a></p>
<ol>
<li><p>JDK 21버전을 설치한다.
<img src="https://velog.velcdn.com/images/hwan2-dev/post/ee15057d-a5fd-4191-aa1d-64c5f26dd329/image.png" alt="">
21버전이 젤 좋다고 함.</p>
</li>
<li><p><a href="https://www.oracle.com/java/technologies/downloads/#jdk21-windows">https://www.oracle.com/java/technologies/downloads/#jdk21-windows</a> 들어가서
<img src="https://velog.velcdn.com/images/hwan2-dev/post/61d7afef-5d5e-4a88-80bc-5719cf11db5c/image.png" alt="">
다운 ㄱ</p>
</li>
<li><p>실행해서 다음 다음 다음 설치.</p>
</li>
<li><p>환경변수 설정하기
윈도우 하단 바 검색칸에 &quot;시스템 환경 변수 편집&quot; 입력 -&gt; 시스템 속성 창이 뜨면 고급 탭의 하단의 환경 변수를 클릭한다.환경 변수 창이 뜨게되면 하단의 시스템 변수(S)에 환경변수 설정을 진행할 것이다.
<img src="https://velog.velcdn.com/images/hwan2-dev/post/8ed85720-32b4-4387-97f8-5e59672895d4/image.png" alt="">
 </p>
</li>
<li><p>새로 만들기(W)... 버튼을 클릭한다.새 시스템 변수 창이 뜨면 변수 이름에 JAVA_HOME 을 입력하고,변수 값에 본인이 설치한 자바 경로를 입력한다.입력 후 확인 버튼을 눌러준다.
<img src="https://velog.velcdn.com/images/hwan2-dev/post/1c0c748b-266a-467a-a768-8bfafa578bca/image.png" alt=""></p>
</li>
</ol>
<ol start="6">
<li><p>환경 변수 창 &gt; 시스템 변수에서 변수 명이 Path인 항목을 찾는다.Path 선택 후 편집 버튼을 클릭한다.
<img src="https://velog.velcdn.com/images/hwan2-dev/post/88407674-7502-4026-be0e-f61ed1f67ac6/image.png" alt=""></p>
</li>
<li><p>환경 변수 편집 창에서 새로 만들기(N) 버튼을 클릭하면 입력 줄이 추가된다.%JAVA_HOME%\bin 을 추가 후 확인 버튼을 누른다.확인 버튼을 눌러 시스템 속성창까지 닫아준다.
<img src="https://velog.velcdn.com/images/hwan2-dev/post/f708c878-a5de-4547-b0d2-82c9091bab5e/image.png" alt="">
 </p>
</li>
<li><p>window + R 키를 누른 후 cmd를 입력하여 명령 프롬프트 창을 호출한다.java -version 명령어 입력 후 엔터를 치면 자바 버전이 출력된다.
<img src="https://velog.velcdn.com/images/hwan2-dev/post/bab1b242-b085-4795-8acb-21802e6bd169/image.png" alt=""></p>
</li>
</ol>
<p>출처: <a href="https://mi2mic.tistory.com/231">https://mi2mic.tistory.com/231</a></p>
<ol start="9">
<li>VS Code에서 설정하기
<img src="https://velog.velcdn.com/images/hwan2-dev/post/ec3cfa58-33d0-42d6-b66c-dab365255472/image.png" alt="">
설정(setting) -&gt; apex 검색 -&gt; 저 부분에 jdk 설치 경로 입력</li>
</ol>
<p>이렇게 하면 VS Code에서 Apex를 쓸 수 있다.(Salesforce Extension 설치했다는 가정하에)</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Salesforce] Salesforce CLI 설치]]></title>
            <link>https://velog.io/@hwan2-dev/Salesforce-Salesforce-CLI-%EC%84%A4%EC%B9%98</link>
            <guid>https://velog.io/@hwan2-dev/Salesforce-Salesforce-CLI-%EC%84%A4%EC%B9%98</guid>
            <pubDate>Tue, 22 Apr 2025 04:24:40 GMT</pubDate>
            <description><![CDATA[<ol>
<li><p><a href="https://developer.salesforce.com/tools/salesforcecli">https://developer.salesforce.com/tools/salesforcecli</a> 들어가서 운영체제에 맞는 거 설치ㄱ<img src="https://velog.velcdn.com/images/hwan2-dev/post/95c9a979-ba09-43da-ad7c-672937c46c37/image.png" alt=""></p>
</li>
<li><p><img src="https://velog.velcdn.com/images/hwan2-dev/post/6273fd96-2172-4647-a690-0d928dbe9a78/image.png" alt=""></p>
</li>
</ol>
<p>✅ 각 옵션 설명</p>
<ol>
<li><p>@salesforce/cli CLI 2.84.x
Salesforce CLI 본체입니다.
필수로 체크되어 있어야 합니다. (기본 체크)</p>
</li>
<li><p>Set PATH to @salesforce/cli
sfdx, sf 명령어를 터미널(cmd, PowerShell, VS Code 등) 어디서든 쓸 수 있게 해주는 옵션입니다.
✅ 반드시 체크하는 걸 추천합니다.
체크해야 sfdx force:org:list 같은 명령어를 어디서나 쓸 수 있음</p>
</li>
<li><p>Add %LOCALAPPDATA%
일부 시스템에서 CLI 관련 데이터 저장 위치를 %LOCALAPPDATA% 경로로 설정
특별한 목적이 없다면 선택은 자유입니다.
→ 일반적으로는 체크하지 않아도 무방</p>
</li>
</ol>
<p>✅ 추천 체크 상태</p>
<p>항목    추천 여부
@salesforce/cli CLI    ✅ 필수
Set PATH to CLI    ✅ 필수
Add %LOCALAPPDATA%    ⭕ 선택 (대부분 비워둬도 무방)</p>
<p>나는 사진 그대로 진행함.</p>
<ol start="3">
<li><p>다음</p>
</li>
<li><p>Install</p>
</li>
<li><p>Completed 뜨면 Close</p>
</li>
</ol>
<p>끝.</p>
]]></description>
        </item>
        <item>
            <title><![CDATA[[VS Code] VS Code 설치하기]]></title>
            <link>https://velog.io/@hwan2-dev/VS-Code-VS-Code-%EC%84%A4%EC%B9%98%ED%95%98%EA%B8%B0</link>
            <guid>https://velog.io/@hwan2-dev/VS-Code-VS-Code-%EC%84%A4%EC%B9%98%ED%95%98%EA%B8%B0</guid>
            <pubDate>Tue, 22 Apr 2025 04:14:16 GMT</pubDate>
            <description><![CDATA[<ol>
<li><p><a href="https://code.visualstudio.com/">https://code.visualstudio.com/</a> 들어가서 
<img src="https://velog.velcdn.com/images/hwan2-dev/post/f8306f4d-653f-4ca7-9352-e0f306162ac8/image.png" alt="">
다운 ㄱㄱ</p>
</li>
<li><p>다음 다음 쭉 하다가 설정부분에서
<img src="https://velog.velcdn.com/images/hwan2-dev/post/a0267a41-c357-4c34-9b41-b0f0b335e301/image.png" alt=""></p>
</li>
</ol>
<p>[각 옵션 설명]
🔲 바탕 화면에 바로가기 만들기
바탕화면에 VS Code 아이콘을 생성합니다.</p>
<p>🔲 “Code”로 열기 - 파일 탐색기 메뉴
파일을 마우스 오른쪽 클릭했을 때 “Code로 열기” 메뉴가 나옵니다.
→ 개별 파일에 적용</p>
<p>🔲 “Code”로 열기 - 디렉터리 탐색기 메뉴
폴더를 마우스 오른쪽 클릭했을 때 “Code로 열기” 메뉴가 나옵니다.
→ 프로젝트 폴더 단위로 열 때 편리</p>
<p>✅ Code로 등록 (기본 선택됨)
VS Code를 기본 코드 편집기로 등록 (예: .js, .html, .cls 등 더블 클릭 시 VS Code로 열림)</p>
<p>✅ PATH에 추가
매우 중요 ⚠️
이 옵션을 선택하면 cmd 또는 PowerShell에서 code . 명령으로 VS Code 실행이 가능해집니다.
Salesforce 개발 시 CLI와 함께 사용할 일이 많기 때문에 반드시 체크하는 걸 추천합니다.</p>
<p>✳️ 추천 설정</p>
<p>항목    추천 여부    이유
바탕화면 바로가기    선택 여부는 자유    습관에 따라
“Code로 열기” 파일 메뉴    ✅    소스 파일 열기 편리
“Code로 열기” 폴더 메뉴    ✅    프로젝트 폴더 열기 필수
Code 등록    ✅ (기본값)    대부분의 코드 확장자와 연결
PATH에 추가    ✅ 필수!    code . 명령어 실행용 (CLI 필수)</p>
<p>나는 그냥 저 사진에서 다음 누름.</p>
<ol start="3">
<li><p>설치</p>
</li>
<li><p>종료</p>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Trailhead] 목록 보기 만들기]]></title>
            <link>https://velog.io/@hwan2-dev/Trailhead-%EB%AA%A9%EB%A1%9D-%EB%B3%B4%EA%B8%B0-%EB%A7%8C%EB%93%A4%EA%B8%B0</link>
            <guid>https://velog.io/@hwan2-dev/Trailhead-%EB%AA%A9%EB%A1%9D-%EB%B3%B4%EA%B8%B0-%EB%A7%8C%EB%93%A4%EA%B8%B0</guid>
            <pubDate>Tue, 22 Apr 2025 02:20:00 GMT</pubDate>
            <description><![CDATA[<p>트레일헤드 링크 : <a href="https://trailhead.salesforce.com/ko/content/learn/projects/prepare-your-salesforce-org-for-users/create-a-unique-account-list-view">https://trailhead.salesforce.com/ko/content/learn/projects/prepare-your-salesforce-org-for-users/create-a-unique-account-list-view</a></p>
<ol>
<li><p><img src="https://velog.velcdn.com/images/hwan2-dev/post/5c1f437a-c27c-42c1-bc1e-c44ae2b3005e/image.png" alt=""></p>
</li>
<li><p><img src="https://velog.velcdn.com/images/hwan2-dev/post/b7df18a1-fd50-4354-bcc9-1a9cf98a8a8b/image.png" alt=""></p>
</li>
<li><p><img src="https://velog.velcdn.com/images/hwan2-dev/post/9a1442ac-fbb7-425c-8f59-9c656ceec52d/image.png" alt=""></p>
</li>
<li><p><img src="https://velog.velcdn.com/images/hwan2-dev/post/a1a1df52-26fc-4363-9d75-0076276ad5de/image.png" alt=""></p>
</li>
<li><p><img src="https://velog.velcdn.com/images/hwan2-dev/post/028bf55b-a04f-428d-a5df-21677e633688/image.png" alt=""></p>
</li>
<li><p><img src="https://velog.velcdn.com/images/hwan2-dev/post/d1ac70cb-edaa-4d45-a7f4-aad2118d41da/image.png" alt=""></p>
</li>
<li><p><img src="https://velog.velcdn.com/images/hwan2-dev/post/680ea2af-48ad-4881-966f-7bb7179e64b4/image.png" alt=""></p>
</li>
</ol>
]]></description>
        </item>
        <item>
            <title><![CDATA[[Trailhead] Lightning App Builder로 홈페이지 만들기]]></title>
            <link>https://velog.io/@hwan2-dev/Trailhead-Lightning-App-Builder%EB%A1%9C-%ED%99%88%ED%8E%98%EC%9D%B4%EC%A7%80-%EB%A7%8C%EB%93%A4%EA%B8%B0</link>
            <guid>https://velog.io/@hwan2-dev/Trailhead-Lightning-App-Builder%EB%A1%9C-%ED%99%88%ED%8E%98%EC%9D%B4%EC%A7%80-%EB%A7%8C%EB%93%A4%EA%B8%B0</guid>
            <pubDate>Tue, 22 Apr 2025 02:04:33 GMT</pubDate>
            <description><![CDATA[<p>트레일 링크 : <a href="https://trailhead.salesforce.com/ko/content/learn/projects/prepare-your-salesforce-org-for-users/customize-the-home-page">https://trailhead.salesforce.com/ko/content/learn/projects/prepare-your-salesforce-org-for-users/customize-the-home-page</a></p>
<ol>
<li><p><img src="https://velog.velcdn.com/images/hwan2-dev/post/4fb2bb83-4585-4f81-9f2d-e23ec77ef8cc/image.png" alt=""></p>
</li>
<li><p><img src="https://velog.velcdn.com/images/hwan2-dev/post/a72e5dfa-7a75-4469-8213-32b7b44c4169/image.png" alt=""></p>
</li>
<li><p><img src="https://velog.velcdn.com/images/hwan2-dev/post/7af27a3a-61c3-4152-ba66-97d4ec9d32fd/image.png" alt=""></p>
</li>
<li><p><img src="https://velog.velcdn.com/images/hwan2-dev/post/a5fc77f6-7094-47b4-9b1b-655b05f7bde7/image.png" alt=""></p>
</li>
<li><p><img src="https://velog.velcdn.com/images/hwan2-dev/post/943ed068-9c0b-4b58-bf9d-be87eca40457/image.png" alt=""></p>
</li>
<li><p><img src="https://velog.velcdn.com/images/hwan2-dev/post/c2e77330-1552-4886-ad45-fe4d5de5406f/image.png" alt=""></p>
</li>
<li><p><img src="https://velog.velcdn.com/images/hwan2-dev/post/d33a7eb5-abdb-415e-91eb-107fe2f5e37d/image.png" alt=""></p>
</li>
<li><p><img src="https://velog.velcdn.com/images/hwan2-dev/post/be499510-5ee5-4ff7-b0e2-160685604c1b/image.png" alt=""></p>
</li>
<li><p><img src="https://velog.velcdn.com/images/hwan2-dev/post/c762b335-0d6c-4e44-9a54-4afe7a0ed6f2/image.png" alt=""></p>
</li>
<li><p><img src="https://velog.velcdn.com/images/hwan2-dev/post/20e9b73e-d396-4b6a-bd80-b9d51ae61147/image.png" alt=""></p>
</li>
<li><p><img src="https://velog.velcdn.com/images/hwan2-dev/post/5e06f889-533f-4fd5-abce-c83522ee7e8d/image.png" alt=""></p>
</li>
<li><p><img src="https://velog.velcdn.com/images/hwan2-dev/post/aedfb2e4-5237-43fb-967b-dcb2288210fb/image.png" alt=""></p>
</li>
<li><p><img src="https://velog.velcdn.com/images/hwan2-dev/post/61b2747f-f402-4e37-ae83-a3a73a774ac1/image.png" alt=""></p>
</li>
<li><p><img src="https://velog.velcdn.com/images/hwan2-dev/post/66ad051d-4052-4e72-a1f5-809a84e57876/image.png" alt=""></p>
</li>
<li><p><img src="https://velog.velcdn.com/images/hwan2-dev/post/7d7c4eb2-cf46-4af0-bf65-f792b61aa8d0/image.png" alt=""></p>
</li>
<li><p><img src="https://velog.velcdn.com/images/hwan2-dev/post/cf62d005-d5e1-4bd5-8f90-4ae4c2f57295/image.png" alt=""></p>
</li>
<li><p><img src="https://velog.velcdn.com/images/hwan2-dev/post/5383ac6c-7044-48a4-a9de-2d8bd92aadb9/image.png" alt=""></p>
</li>
</ol>
]]></description>
        </item>
    </channel>
</rss>