<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Administration on kenji.blog</title><link>http://kenji.blog/ko/categories/administration/</link><description>Recent content in Administration on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>ko</language><copyright>kenjinote</copyright><lastBuildDate>Sat, 12 Sep 2026 12:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/ko/categories/administration/index.xml" rel="self" type="application/rss+xml"/><item><title>Windows 레지스트리의 기초 지식과 프로그래밍 가능한 안전한 편집 방법</title><link>http://kenji.blog/ko/p/windows-registry-safe-programmable-editing/</link><pubDate>Sat, 12 Sep 2026 12:00:00 +0900</pubDate><guid>http://kenji.blog/ko/p/windows-registry-safe-programmable-editing/</guid><description>&lt;img src="http://kenji.blog/p/windows-registry-safe-programmable-editing/img/eyecatch.jpg" alt="Featured image of post Windows 레지스트리의 기초 지식과 프로그래밍 가능한 안전한 편집 방법" />&lt;h1 id="windows-레지스트리의-기초-지식과-프로그래밍-가능한-안전한-편집-방법">Windows 레지스트리의 기초 지식과 프로그래밍 가능한 안전한 편집 방법
&lt;/h1>&lt;p>Windows 운영 체제에서 &amp;ldquo;레지스트리(Registry)&amp;ldquo;는 시스템 및 애플리케이션의 다양한 설정을 저장하는 거대한 계층형 데이터베이스입니다. 본 기사에서는 Windows 레지스트리의 기초적인 아키텍처부터 PowerShell이나 C#을 사용한 프로그래밍 가능하고 안전한 레지스트리 편집 방법에 대해 매우 자세히 해설합니다.&lt;/p>
&lt;h2 id="1-시작하며-windows-레지스트리의-역사와-진화">1. 시작하며: Windows 레지스트리의 역사와 진화
&lt;/h2>&lt;p>Windows의 초기 버전(Windows 3.x 시대)에서는 시스템이나 애플리케이션의 설정은 주로 &lt;code>.ini&lt;/code>(초기화 파일)에 저장되었습니다. 그러나 애플리케이션마다 무수히 많은 INI 파일이 시스템 전체에 흩어지게 되어 관리가 현저히 번거로워졌습니다. 또한 INI 파일은 일반 텍스트 기반이기 때문에 바이너리 데이터의 저장이 어렵고, 액세스 제어(보안) 구조도 존재하지 않았습니다. 파일 파싱 속도도 느려 대규모 설정을 저장하는 데는 적합하지 않았습니다.&lt;/p>
&lt;p>이러한 문제들을 근본적으로 해결하기 위해 Windows NT 및 Windows 95 이후 중앙 집중식 설정 데이터베이스로서 &amp;ldquo;레지스트리&amp;quot;가 본격적으로 채택되었습니다. 레지스트리는 계층화된 데이터베이스로, 강력한 타입 지정, 바이너리 데이터 지원 및 접근 제어 목록(ACL)에 의한 견고한 보안 기능을 제공합니다. 이를 통해 OS 커널에서 사용자 공간의 애플리케이션까지 모든 구성 요소가 통일된 인터페이스(Win32 API의 &lt;code>Reg*&lt;/code> 함수군)로 설정을 읽고 쓸 수 있게 되었습니다.&lt;/p>
&lt;p>현대의 Windows 11에 이르기까지 레지스트리는 OS의 심장부로 계속 기능하고 있습니다. 하드웨어 구성, 디바이스 드라이버 로드 순서, 사용자의 데스크톱 환경, 설치된 소프트웨어 목록 등 시스템 동작에 필요한 모든 메타데이터가 레지스트리에 집약되어 있습니다.&lt;/p>
&lt;h2 id="2-아키텍처의-심층-레지스트리-하이브의-실체와-메모리-매핑">2. 아키텍처의 심층: 레지스트리 하이브의 실체와 메모리 매핑
&lt;/h2>&lt;p>레지스트리는 논리적으로 하나의 거대한 트리 구조로 보이지만, 물리적으로는 &amp;ldquo;하이브(Hive)&amp;ldquo;라고 불리는 여러 파일로 분할되어 디스크에 저장됩니다. 이를 통해 시스템 전체의 설정과 사용자 고유의 설정이 분리되어 효율적인 읽기가 가능해집니다.&lt;/p>
&lt;p>주요 하이브 파일은 보통 &lt;code>%SystemRoot%\System32\config&lt;/code> 디렉토리에 존재합니다.&lt;/p>
&lt;ul>
&lt;li>&lt;code>SYSTEM&lt;/code>: 운영 체제 부팅에 필요한 중요한 설정 (드라이버, 서비스, 부팅 구성 등).&lt;/li>
&lt;li>&lt;code>SOFTWARE&lt;/code>: 설치된 소프트웨어의 시스템 전체 설정. 서드파티 앱 설정의 대부분이 여기에 들어갑니다.&lt;/li>
&lt;li>&lt;code>SAM&lt;/code>: Security Accounts Manager (로컬 사용자 계정과 암호 해시).&lt;/li>
&lt;li>&lt;code>SECURITY&lt;/code>: 로컬 보안 정책 및 권한 할당.&lt;/li>
&lt;li>&lt;code>DEFAULT&lt;/code>: 기본 사용자 프로필 (새 사용자 생성 시 템플릿).&lt;/li>
&lt;/ul>
&lt;p>사용자 개별 하이브 파일은 사용자의 프로필 디렉토리(예: &lt;code>C:\Users\Username&lt;/code>)에 숨김 파일로 존재합니다.&lt;/p>
&lt;ul>
&lt;li>&lt;code>NTUSER.DAT&lt;/code>: 해당 사용자의 기본 설정 (HKCU의 대부분).&lt;/li>
&lt;li>&lt;code>UsrClass.dat&lt;/code>: 해당 사용자의 파일 확장자 연결 설정 (&lt;code>AppData\Local\Microsoft\Windows&lt;/code> 내에 존재).&lt;/li>
&lt;/ul>
&lt;p>이 파일들은 OS 부팅 시 커널의 &amp;ldquo;Configuration Manager (CM)&amp;ldquo;에 의해 커널 페이지 풀 메모리에 매핑됩니다. Configuration Manager는 레지스트리의 읽기/쓰기 요청을 처리하는 커널 모드 구성 요소입니다.&lt;/p>
&lt;p>특기할 점은 모든 레지스트리 데이터가 디스크 상에 존재하는 것은 아니라는 것입니다. 예를 들어 &lt;code>HARDWARE&lt;/code> 하이브는 휘발성(Volatile)이며 디스크의 파일에는 전혀 저장되지 않습니다. OS가 부팅되고 플러그 앤 플레이(PnP) 관리자가 하드웨어를 감지할 때마다 메모리 상에서 동적으로 재구성됩니다.&lt;/p>
&lt;p>또한 최신 Windows에서는 레지스트리의 신뢰성을 높이기 위해 트랜잭션 로깅이 구현되어 있습니다. 하이브 파일에 대한 변경 사항은 데이터 파일에 직접 기록되는 것이 아니라 먼저 트랜잭션 로그(&lt;code>.log1&lt;/code>, &lt;code>.log2&lt;/code>)에 기록됩니다. 이를 통해 쓰기 중 예상치 못한 전원 손실이나 시스템 크래시 시의 데이터 손상(Corruption)을 방지하고, 데이터베이스의 무결성을 ACID 특성에 가까운 형태로 보장합니다.&lt;/p>
&lt;h2 id="3-레지스트리-키와-값의-계층-구조">3. 레지스트리 키와 값의 계층 구조
&lt;/h2>&lt;p>레지스트리는 파일 시스템과 매우 유사한 계층 구조를 가지고 있습니다. 루트가 되는 노드는 &amp;ldquo;루트 키&amp;rdquo; 또는 &amp;ldquo;하이브&amp;quot;라고 불리며, 그 아래에 &amp;ldquo;키&amp;rdquo;, &amp;ldquo;서브 키&amp;rdquo;, 그리고 데이터의 실체인 &amp;ldquo;값(Value)&amp;ldquo;이 저장됩니다. 키는 디렉토리에, 값은 파일에 해당한다고 생각하면 이해하기 쉽습니다.&lt;/p>
&lt;p>주요 루트 키는 다음 5가지로 분류됩니다.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>HKEY_LOCAL_MACHINE (HKLM)&lt;/strong>: 컴퓨터 전체(모든 사용자)에 적용되는 시스템 설정이나 소프트웨어 설정이 저장됩니다. 변경하려면 관리자 권한이 필요합니다.&lt;/li>
&lt;li>&lt;strong>HKEY_CURRENT_USER (HKCU)&lt;/strong>: 현재 로그온한 사용자 고유의 설정이 저장됩니다. 사실 이는 독립된 데이터베이스가 아니라 &lt;code>HKEY_USERS&lt;/code> 아래에 있는 해당 사용자의 SID(보안 식별자) 키에 대한 심볼릭 링크(별칭)에 불과합니다.&lt;/li>
&lt;li>&lt;strong>HKEY_CLASSES_ROOT (HKCR)&lt;/strong>: 파일 확장자 연결, COM(Component Object Model) 클래스의 등록 정보, 셸 확장이 저장됩니다. 이 키는 특수하여 &lt;code>HKLM\SOFTWARE\Classes&lt;/code> (시스템 전체)와 &lt;code>HKCU\Software\Classes&lt;/code> (현재 사용자)를 Configuration Manager가 병합(통합)하여 표시하는 가상 뷰입니다. 충돌이 있는 경우 사용자 고유의 설정(HKCU)이 우선됩니다.&lt;/li>
&lt;li>&lt;strong>HKEY_USERS (HKU)&lt;/strong>: 시스템의 모든 사용자 프로필(현재 메모리에 로드된 것) 설정이 저장됩니다. SID 기반으로 계층화되어 있습니다.&lt;/li>
&lt;li>&lt;strong>HKEY_CURRENT_CONFIG (HKCC)&lt;/strong>: 현재 하드웨어 프로필에 관한 설정. 실체는 &lt;code>HKLM\SYSTEM\CurrentControlSet\Hardware Profiles\Current&lt;/code>에 대한 링크입니다.&lt;/li>
&lt;/ol>
&lt;p>이 복잡한 계층 구조와 링크 관계를 시각화하면 다음과 같습니다.&lt;/p>
&lt;pre class="mermaid">
mindmap
root((&amp;#34;Windows 레지스트리&amp;#34;))
HKLM((&amp;#34;HKEY_LOCAL_MACHINE&amp;#34;))
SAM((&amp;#34;SAM (보안 계정)&amp;#34;))
SECURITY((&amp;#34;SECURITY&amp;#34;))
SOFTWARE((&amp;#34;SOFTWARE&amp;#34;))
SYSTEM((&amp;#34;SYSTEM&amp;#34;))
HARDWARE((&amp;#34;HARDWARE (휘발성)&amp;#34;))
HKCU((&amp;#34;HKEY_CURRENT_USER (링크)&amp;#34;))
AppEvents((&amp;#34;AppEvents&amp;#34;))
Console((&amp;#34;Console&amp;#34;))
Software((&amp;#34;Software&amp;#34;))
System((&amp;#34;System&amp;#34;))
HKCR((&amp;#34;HKEY_CLASSES_ROOT (병합된 뷰)&amp;#34;))
HKU((&amp;#34;HKEY_USERS&amp;#34;))
SID((&amp;#34;사용자 SID...&amp;#34;))
HKCC((&amp;#34;HKEY_CURRENT_CONFIG (링크)&amp;#34;))
&lt;/pre>
&lt;h2 id="4-레지스트리의-데이터-형식-상세-해설">4. 레지스트리의 데이터 형식 (상세 해설)
&lt;/h2>&lt;p>레지스트리의 &amp;ldquo;값&amp;quot;에는 각각 엄격한 데이터 형식이 정의되어 있습니다. 프로그래밍을 통해 레지스트리를 조작할 경우, 이러한 형식을 올바르게 이해하고 적절한 형식으로 데이터를 쓰는 것이 필수적입니다. 잘못된 형식으로 쓰면 애플리케이션에서 예외가 발생하거나 OS 기능이 정지하는 원인이 됩니다.&lt;/p>
&lt;ul>
&lt;li>&lt;strong>REG_SZ (문자열 값)&lt;/strong>: 가장 일반적인 데이터 형식입니다. NULL로 끝나는 유니코드 문자열(UTF-16LE)을 저장합니다. 파일 경로, URL, UI의 표시 이름 등에 사용됩니다.&lt;/li>
&lt;li>&lt;strong>REG_DWORD (32비트 정수 값)&lt;/strong>: 32비트(4바이트)의 부호 없는 정수 값입니다. 부울 값(0=비활성화, 1=활성화)이나 밀리초 단위의 타임아웃 값, 오류 코드 설정 등에 자주 사용됩니다. Windows는 리틀 엔디안 아키텍처이기 때문에 디스크 상에서는 하위 바이트부터 순서대로(예: 0x12345678은 &lt;code>78 56 34 12&lt;/code>) 저장됩니다.&lt;/li>
&lt;li>&lt;strong>REG_QWORD (64비트 정수 값)&lt;/strong>: 64비트(8바이트)의 정수 값입니다. 64비트 아키텍처가 보급됨에 따라 거대한 수치(디스크 할당량이나 대용량 메모리 크기 지정 등)나 포인터 크기의 설정을 저장하기 위해 사용됩니다.&lt;/li>
&lt;li>&lt;strong>REG_MULTI_SZ (다중 문자열 값)&lt;/strong>: 여러 개의 NULL로 끝나는 문자열을 연속해서 저장하고, 마지막에 빈 NULL 종료 문자(Double NULL)를 두어 끝을 나타내는 형식입니다. IP 주소 목록, 종속성이 있는 서비스 목록, 바인딩 순서 등 배열적인 데이터를 저장하는 데 적합합니다.&lt;/li>
&lt;li>&lt;strong>REG_EXPAND_SZ (확장 가능한 문자열 값)&lt;/strong>: &lt;code>%USERPROFILE%&lt;/code>이나 &lt;code>%SystemRoot%&lt;/code>와 같은 확장되지 않은 환경 변수 문자열을 포함하는 특수한 문자열 형식입니다. 애플리케이션이 &lt;code>RegQueryValueEx&lt;/code> API를 통해 읽을 때, 또는 &lt;code>ExpandEnvironmentStrings&lt;/code> API를 호출함으로써 OS에 의해 동적으로 실제 절대 경로로 확장됩니다.&lt;/li>
&lt;li>&lt;strong>REG_BINARY (이진 값)&lt;/strong>: 임의의 원시 바이너리 데이터 스트림입니다. 암호화된 비밀번호(LSA Secrets 등), 디지털 인증서, 애플리케이션 고유의 복잡한 구조체나 직렬화된 데이터가 저장됩니다.&lt;/li>
&lt;li>&lt;strong>REG_NONE&lt;/strong>: 형식이 정의되지 않은 데이터입니다. 매우 드물지만 암호화 키의 예약 영역 등에 사용됩니다.&lt;/li>
&lt;li>&lt;strong>REG_RESOURCE_LIST&lt;/strong> / &lt;strong>REG_FULL_RESOURCE_DESCRIPTOR&lt;/strong>: 디바이스 드라이버가 하드웨어 리소스(IRQ, I/O 포트, DMA 채널)의 할당 정보를 기록하기 위해 사용하는 커널 전용의 고급 형식입니다.&lt;/li>
&lt;/ul>
&lt;h2 id="5-운영-체제에서의-레지스트리-수리-모델과-성능">5. 운영 체제에서의 레지스트리 수리 모델과 성능
&lt;/h2>&lt;p>레지스트리는 OS의 성능(특히 부팅 시간과 프로세스 초기화 속도)에 직결되기 때문에, 내부적으로는 &amp;ldquo;Cell Index&amp;quot;라고 불리는 B-Tree(B-트리)와 유사한 고도의 데이터 구조를 사용하여 최적화되어 있습니다.&lt;/p>
&lt;h3 id="검색-시간-복잡도-time-complexity">검색 시간 복잡도 (Time Complexity)
&lt;/h3>&lt;p>레지스트리 내의 특정 키(경로)를 검색할 때의 시간 복잡도 $T_{\text{search}}$는 트리의 깊이와 각 계층의 노드 수에 따라 달라집니다. 깊이가 $d$인 서브 키(예: &lt;code>A\B\C\D&lt;/code>라면 $d=4$)를 탐색할 경우의 계산 복잡도는 이론상 다음과 같이 모델링할 수 있습니다.&lt;/p>
$$
T_{\text{search}}(d, L) = \sum_{i=1}^{d} O(\log(C_i) \cdot L_i)
$$&lt;p>여기서 $C_i$는 깊이 $i$에서의 자식 노드(서브 키 또는 값)의 수, $L_i$는 비교 대상이 되는 문자열의 길이(문자 수)입니다. 레지스트리의 실체인 하이브 파일 내에서 서브 키 목록은 이름의 해시 값 또는 알파벳 순으로 정렬된 인덱스로 유지됩니다. 따라서 단순한 선형 탐색 $O(C_i)$가 아닌 이진 탐색 $O(\log(C_i))$가 가능하며, 하나의 키 아래에 수만 개의 서브 키가 존재하더라도 매우 빠른 액세스를 실현합니다.&lt;/p>
&lt;h3 id="스토리지-풋프린트-space-complexity">스토리지 풋프린트 (Space Complexity)
&lt;/h3>&lt;p>레지스트리의 전체 크기(물리 디스크 상의 점유량)는 각 하이브의 합계로 계산됩니다.&lt;/p>
$$
\text{Size}_{\text{Total}} = \sum_{h \in \text{Hives}} \left( N_{h} \times S_{\text{key\_metadata}} + \sum_{v \in h} S_{\text{value}}(v) \right) + S_{\text{overhead}}
$$&lt;p>$N_h$는 하이브 $h$ 내의 키 수, $S_{\text{key\_metadata}}$는 키 1개당 메타데이터(마지막 쓰기 타임스탬프, 보안 설명자에 대한 포인터, 부모 키에 대한 포인터 등)의 크기, $S_{\text{value}}(v)$는 값 $v$의 페이로드 크기입니다. 트랜잭션 로그나 불필요해진 빈 셀(단편화)로 인한 오버헤드 $S_{\text{overhead}}$도 포함됩니다. 레지스트리에 불필요한 데이터(제거가 완전히 되지 않은 소프트웨어의 잔해 등)를 장기간 방치하면 이 풋프린트가 증가하여 OS의 페이지 풀 메모리를 압박하고 성능 저하를 초래할 수 있습니다.&lt;/p>
&lt;h2 id="6-시스템의-견고성을-위협하는-수동-편집의-위험과-손상-확률">6. 시스템의 견고성을 위협하는 수동 편집의 위험과 손상 확률
&lt;/h2>&lt;p>레지스트리 편집기(&lt;code>regedit.exe&lt;/code>)를 이용한 수작업 편집은 시스템 관리의 최후의 수단으로 간주되어야 합니다. 레지스트리에는 일반적인 문서 편집기와 같은 &amp;ldquo;실행 취소(Undo)&amp;rdquo; 기능이 내장되어 있지 않으며, 값의 변경이나 키의 삭제는 Configuration Manager를 통해 즉시 시스템에 반영됩니다.&lt;/p>
&lt;p>특히 시스템 부팅에 필수적인 중요 키(예: &lt;code>HKLM\SYSTEM\CurrentControlSet\Services&lt;/code> 아래의 디스크 컨트롤러 드라이버 설정이나 &lt;code>HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon&lt;/code>의 &lt;code>Userinit&lt;/code> 값 등)를 한 글자라도 잘못 편집하거나 삭제할 경우, OS가 블루스크린(BSoD)을 일으켜 부팅할 수 없게 되거나 로그인 화면에서 더 이상 진행되지 않는(블랙스크린) 치명적인 위험이 있습니다.&lt;/p>
&lt;h3 id="손상-확률의-수학적-모델">손상 확률의 수학적 모델
&lt;/h3>&lt;p>레지스트리 내의 키를 무작위로 변경하거나 삭제했을 경우의 시스템 장애 발생 확률을 생각해 봅시다. 시스템이 정상적으로 동작하기 위해 필수적인 중요 키의 집합을 $C$, 그 총수를 $N_c = |C|$라고 합시다. 레지스트리 전체의 키 총수를 $N_{\text{total}}$이라고 합니다.
무작위로 $k$개의 키를 삭제하거나 파괴했을 때, 적어도 하나의 중요 키가 손상될 확률 $P_{\text{failure}}$는 비복원 추출(Sampling without replacement)의 확률 계산에 의해 다음과 같이 표현됩니다.&lt;/p>
$$
P_{\text{failure}} = 1 - \frac{\binom{N_{\text{total}} - N_c}{k}}{\binom{N_{\text{total}}}{k}} = 1 - \prod_{i=0}^{k-1} \left( 1 - \frac{N_c}{N_{\text{total}} - i} \right)
$$&lt;p>레지스트리 전체의 키 수 $N_{\text{total}}$은 수십만에서 수백만의 규모지만, $N_c$ 역시 수만의 규모로 존재합니다. 수학적으로 무작위 조작이라도 $k$가 증가하면 장애 확률은 급격히 상승합니다. 게다가 실제 수동 조작에서 사용자는 &amp;ldquo;무작위&amp;quot;로 편집하는 것이 아니라 시스템의 설정이나 소프트웨어의 동작과 직접 관련된 부분을 의도적으로(튜토리얼 사이트 등을 보면서) 조작하기 때문에, 중요 키를 건드릴 확률은 위의 이론값보다 훨씬 높아집니다.&lt;/p>
&lt;h2 id="7-레지스트리-가상화와-wow64-아키텍처">7. 레지스트리 가상화와 WOW64 아키텍처
&lt;/h2>&lt;p>Windows는 레거시 애플리케이션의 호환성을 유지하기 위해 레지스트리 액세스에 대해 몇 가지 고도의 &amp;ldquo;가상화(리디렉션)&amp;rdquo; 메커니즘을 구현하고 있습니다. 이를 이해하지 않고 프로그래밍을 수행하면 심각한 버그를 유발하는 원인이 됩니다.&lt;/p>
&lt;h3 id="uac-레지스트리-가상화-registry-virtualization">UAC 레지스트리 가상화 (Registry Virtualization)
&lt;/h3>&lt;p>Windows Vista 이후 사용자 계정 컨트롤(UAC)이 도입되었습니다. Windows XP 시대에 만들어진 오래된 애플리케이션(표준 사용자 권한으로 동작)이 본래 관리자 권한이 필요한 &lt;code>HKLM\SOFTWARE&lt;/code> 등의 보호된 키에 쓰기를 시도할 경우, 액세스 거부(Access Denied) 오류로 크래시되는 것을 방지하기 위해 Windows는 그 쓰기 작업을 몰래 사용자 프로필 내의 가상 스토어 &lt;code>HKCU\Software\Classes\VirtualStore\MACHINE\SOFTWARE&lt;/code>로 리디렉션합니다. 읽기 시에도 원래 위치와 가상 스토어 양쪽을 병합하여 반환합니다. 이를 통해 애플리케이션은 오류를 감지하지 않고 정상적으로 동작을 계속할 수 있습니다.
단, 프로그래밍 방식으로 시스템 전체의 설정을 변경하는 도구를 개발할 경우에는 매니페스트 파일에 &lt;code>&amp;lt;requestedExecutionLevel level=&amp;quot;requireAdministrator&amp;quot; /&amp;gt;&lt;/code>를 지정하여 이 가상화를 비활성화해야 합니다.&lt;/p>
&lt;h3 id="wow64-windows-32-bit-on-windows-64-bit-의-리디렉션">WOW64 (Windows 32-bit on Windows 64-bit) 의 리디렉션
&lt;/h3>&lt;p>64비트 버전의 Windows(현재 주류)에서 기존 32비트 애플리케이션을 실행할 때, 32비트 앱이 64비트의 네이티브 시스템 설정을 잘못 덮어쓰거나 호환되지 않는 64비트 DLL을 로드하지 않도록 특정 레지스트리 키는 자동으로 분리 및 리디렉션됩니다.
예를 들어 32비트 앱이 &lt;code>HKLM\SOFTWARE\Vendor\App&lt;/code>에 액세스하려고 하면 OS는 투명하게 &lt;code>HKLM\SOFTWARE\WOW6432Node\Vendor\App&lt;/code>으로 리디렉션합니다.&lt;/p>
&lt;pre class="mermaid">
flowchart TD
App32[&amp;#34;32비트 애플리케이션&amp;#34;]
App64[&amp;#34;64비트 애플리케이션&amp;#34;]
RegAPI[&amp;#34;레지스트리 API (Advapi32.dll)&amp;#34;]
CM[&amp;#34;Configuration Manager (커널)&amp;#34;]
HKLM_Soft[&amp;#34;HKLM\SOFTWARE&amp;#34;]
HKLM_WOW64[&amp;#34;HKLM\SOFTWARE\WOW6432Node&amp;#34;]
App32 --&amp;gt;| RegOpenKeyEx() | RegAPI
App64 --&amp;gt;| RegOpenKeyEx() | RegAPI
RegAPI --&amp;gt; CM
CM --&amp;gt;| 64비트 프로세스인 경우 | HKLM_Soft
CM --&amp;gt;| 32비트 프로세스인 경우 (리디렉션) | HKLM_WOW64
&lt;/pre>
&lt;p>PowerShell 스크립트나 C# 애플리케이션에서 레지스트리를 편집할 때는 실행 중인 프로세스 자체가 32비트인지 64비트인지를 강하게 의식해야 합니다. 그렇지 않으면 &amp;ldquo;분명히 쓴 설정이 탐색기에서 보이지 않는다(다른 곳에 쓰여 있다)&amp;ldquo;는 성가신 문제를 일으키게 됩니다.&lt;/p>
&lt;h2 id="8-powershell을-통한-프로그래밍-가능한-안전한-편집">8. PowerShell을 통한 프로그래밍 가능한 안전한 편집
&lt;/h2>&lt;p>레지스트리를 수동으로 편집하는 위험을 최소화하려면 PowerShell 스크립트를 사용하여 조작을 코드화(Infrastructure as Code)하고 자동화, 재현성, 테스트 가능성을 확보하는 것이 현대의 모범 사례입니다. PowerShell은 &amp;ldquo;Registry Provider&amp;quot;를 갖추고 있어 파일 시스템(C: 드라이브 등)을 조작하는 것과 완전히 동일한 cmdlet(&lt;code>Get-ChildItem&lt;/code>, &lt;code>Get-ItemProperty&lt;/code>, &lt;code>New-Item&lt;/code> 등)으로 레지스트리를 투명하게 조작할 수 있습니다.&lt;/p>
&lt;p>PowerShell에서는 기본적으로 &lt;code>HKLM:&lt;/code>이나 &lt;code>HKCU:&lt;/code>라는 전용 PSDrive(드라이브 문자 같은 것)가 마운트되어 있습니다.&lt;/p>
&lt;h3 id="기본적인-crud-조작">기본적인 CRUD 조작
&lt;/h3>&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-powershell" data-lang="powershell">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># 1. 존재 확인 (Read)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">$keyPath&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="s2">&amp;#34;HKCU:\Software\MyCustomApp&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="o">-Not&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nb">Test-Path&lt;/span> &lt;span class="n">-Path&lt;/span> &lt;span class="nv">$keyPath&lt;/span>&lt;span class="p">))&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># 2. 새로운 키 생성 (Create)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">New-Item&lt;/span> &lt;span class="n">-Path&lt;/span> &lt;span class="s2">&amp;#34;HKCU:\Software&amp;#34;&lt;/span> &lt;span class="n">-Name&lt;/span> &lt;span class="s2">&amp;#34;MyCustomApp&amp;#34;&lt;/span> &lt;span class="n">-Force&lt;/span> &lt;span class="p">|&lt;/span> &lt;span class="nb">Out-Null&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">Write-Host&lt;/span> &lt;span class="s2">&amp;#34;키를 생성했습니다.&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># 3. 값 쓰기/업데이트 (Update) - REG_DWORD로 1을 쓰기&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">Set-ItemProperty&lt;/span> &lt;span class="n">-Path&lt;/span> &lt;span class="nv">$keyPath&lt;/span> &lt;span class="n">-Name&lt;/span> &lt;span class="s2">&amp;#34;EnableDebug&amp;#34;&lt;/span> &lt;span class="n">-Value&lt;/span> &lt;span class="mf">1&lt;/span> &lt;span class="n">-Type&lt;/span> &lt;span class="n">DWord&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># 4. 값 읽기 (Read)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">$debugFlag&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nb">Get-ItemProperty&lt;/span> &lt;span class="n">-Path&lt;/span> &lt;span class="nv">$keyPath&lt;/span>&lt;span class="p">).&lt;/span>&lt;span class="py">EnableDebug&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">Write-Host&lt;/span> &lt;span class="s2">&amp;#34;현재 디버그 플래그: &lt;/span>&lt;span class="nv">$debugFlag&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># 5. 값 삭제 (Delete)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">Remove-ItemProperty&lt;/span> &lt;span class="n">-Path&lt;/span> &lt;span class="nv">$keyPath&lt;/span> &lt;span class="n">-Name&lt;/span> &lt;span class="s2">&amp;#34;EnableDebug&amp;#34;&lt;/span> &lt;span class="n">-Force&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="실전-예제-1-개발-환경-자동-설정-환경-변수-path-추가">실전 예제 1: 개발 환경 자동 설정 (환경 변수 PATH 추가)
&lt;/h3>&lt;p>다음 스크립트는 개발자가 새로운 Windows 머신을 설정할 때 사용자 환경 변수 &lt;code>PATH&lt;/code>에 사용자 지정 도구 디렉토리를 안전하게 추가하는 자동화 예제입니다.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-powershell" data-lang="powershell">&lt;span class="line">&lt;span class="cl">&lt;span class="nv">$envKey&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="s2">&amp;#34;HKCU:\Environment&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">$newPath&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="s2">&amp;#34;C:\tools\bin&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># 현재 PATH 읽기 (오류를 억제하여 안전하게 가져옴)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">$currentPathInfo&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="nb">Get-ItemProperty&lt;/span> &lt;span class="n">-Path&lt;/span> &lt;span class="nv">$envKey&lt;/span> &lt;span class="n">-Name&lt;/span> &lt;span class="s2">&amp;#34;Path&amp;#34;&lt;/span> &lt;span class="n">-ErrorAction&lt;/span> &lt;span class="n">SilentlyContinue&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">$currentPath&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nv">$currentPathInfo&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="nv">$currentPathInfo&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="py">Path&lt;/span> &lt;span class="p">}&lt;/span> &lt;span class="k">else&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="s2">&amp;#34;&amp;#34;&lt;/span> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># 이미 포함되어 있는지 정규 표현식으로 확인&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nv">$currentPath&lt;/span> &lt;span class="o">-notmatch&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="no">regex&lt;/span>&lt;span class="p">]::&lt;/span>&lt;span class="n">Escape&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nv">$newPath&lt;/span>&lt;span class="p">))&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># 끝에 세미콜론이 없으면 추가하여 결합&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="nv">$currentPath&lt;/span> &lt;span class="o">-and&lt;/span> &lt;span class="nv">$currentPath&lt;/span> &lt;span class="o">-notmatch&lt;/span> &lt;span class="s2">&amp;#34;;$&amp;#34;&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">$currentPath&lt;/span> &lt;span class="p">+=&lt;/span> &lt;span class="s2">&amp;#34;;&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nv">$updatedPath&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="nv">$currentPath&lt;/span> &lt;span class="p">+&lt;/span> &lt;span class="nv">$newPath&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># REG_EXPAND_SZ 형식으로 쓰기 (중요)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">Set-ItemProperty&lt;/span> &lt;span class="n">-Path&lt;/span> &lt;span class="nv">$envKey&lt;/span> &lt;span class="n">-Name&lt;/span> &lt;span class="s2">&amp;#34;Path&amp;#34;&lt;/span> &lt;span class="n">-Value&lt;/span> &lt;span class="nv">$updatedPath&lt;/span> &lt;span class="n">-Type&lt;/span> &lt;span class="n">ExpandString&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">Write-Host&lt;/span> &lt;span class="s2">&amp;#34;PATH 환경 변수를 업데이트했습니다: &lt;/span>&lt;span class="nv">$newPath&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># 실행 중인 프로세스에 환경 변수 변경을 알림 (WM_SETTINGCHANGE)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># 이를 통해 재부팅 없이 새로운 탐색기 등에 반영됨&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">[&lt;/span>&lt;span class="no">Environment&lt;/span>&lt;span class="p">]::&lt;/span>&lt;span class="n">SetEnvironmentVariable&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s2">&amp;#34;Path&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="nv">$updatedPath&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="p">[&lt;/span>&lt;span class="no">EnvironmentVariableTarget&lt;/span>&lt;span class="p">]::&lt;/span>&lt;span class="n">User&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span> &lt;span class="k">else&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">Write-Host&lt;/span> &lt;span class="s2">&amp;#34;PATH가 이미 추가되어 있습니다.&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="실전-예제-2-상황에-맞는-메뉴context-menu에-사용자-지정-작업-추가">실전 예제 2: 상황에 맞는 메뉴(Context Menu)에 사용자 지정 작업 추가
&lt;/h3>&lt;p>특정 파일이나 디렉토리를 마우스 오른쪽 버튼으로 클릭했을 때의 상황에 맞는 메뉴에 &amp;ldquo;My IDE로 열기&amp;quot;라는 고유 항목을 추가하는 스크립트입니다.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-powershell" data-lang="powershell">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># 디렉토리의 배경(여백 부분)을 마우스 오른쪽 버튼으로 클릭했을 때의 메뉴&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">$menuPath&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="s2">&amp;#34;HKCR:\Directory\Background\shell\OpenWithMyIDE&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">$commandPath&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="nv">$menuPath&lt;/span>&lt;span class="s2">\command&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">try&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># 메뉴 항목의 부모 키 생성&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">New-Item&lt;/span> &lt;span class="n">-Path&lt;/span> &lt;span class="nv">$menuPath&lt;/span> &lt;span class="n">-Force&lt;/span> &lt;span class="n">-ErrorAction&lt;/span> &lt;span class="n">Stop&lt;/span> &lt;span class="p">|&lt;/span> &lt;span class="nb">Out-Null&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># (default) 값에 표시 이름 설정&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">Set-ItemProperty&lt;/span> &lt;span class="n">-Path&lt;/span> &lt;span class="nv">$menuPath&lt;/span> &lt;span class="n">-Name&lt;/span> &lt;span class="s2">&amp;#34;(default)&amp;#34;&lt;/span> &lt;span class="n">-Value&lt;/span> &lt;span class="s2">&amp;#34;My IDE로 열기&amp;#34;&lt;/span> &lt;span class="n">-Type&lt;/span> &lt;span class="n">String&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># 아이콘 설정 (선택 사항)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">Set-ItemProperty&lt;/span> &lt;span class="n">-Path&lt;/span> &lt;span class="nv">$menuPath&lt;/span> &lt;span class="n">-Name&lt;/span> &lt;span class="s2">&amp;#34;Icon&amp;#34;&lt;/span> &lt;span class="n">-Value&lt;/span> &lt;span class="s2">&amp;#34;C:\Program Files\MyIDE\ide.exe,0&amp;#34;&lt;/span> &lt;span class="n">-Type&lt;/span> &lt;span class="n">String&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># command 서브 키를 생성하고, 실행될 명령줄을 설정&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c"># %V 는 현재 디렉토리 경로로 확장되는 변수&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">New-Item&lt;/span> &lt;span class="n">-Path&lt;/span> &lt;span class="nv">$commandPath&lt;/span> &lt;span class="n">-Force&lt;/span> &lt;span class="n">-ErrorAction&lt;/span> &lt;span class="n">Stop&lt;/span> &lt;span class="p">|&lt;/span> &lt;span class="nb">Out-Null&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">Set-ItemProperty&lt;/span> &lt;span class="n">-Path&lt;/span> &lt;span class="nv">$commandPath&lt;/span> &lt;span class="n">-Name&lt;/span> &lt;span class="s2">&amp;#34;(default)&amp;#34;&lt;/span> &lt;span class="n">-Value&lt;/span> &lt;span class="s2">&amp;#34;&lt;/span>&lt;span class="se">`&amp;#34;&lt;/span>&lt;span class="s2">C:\Program Files\MyIDE\ide.exe&lt;/span>&lt;span class="se">`&amp;#34;&lt;/span>&lt;span class="s2"> &lt;/span>&lt;span class="se">`&amp;#34;&lt;/span>&lt;span class="s2">%V&lt;/span>&lt;span class="se">`&amp;#34;&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span> &lt;span class="n">-Type&lt;/span> &lt;span class="n">String&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">Write-Host&lt;/span> &lt;span class="s2">&amp;#34;상황에 맞는 메뉴를 추가했습니다.&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span> &lt;span class="k">catch&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="nb">Write-Error&lt;/span> &lt;span class="s2">&amp;#34;레지스트리 변경에 실패했습니다. 관리자 권한으로 실행 중인지 확인하세요. 오류: &lt;/span>&lt;span class="nv">$_&lt;/span>&lt;span class="s2">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="powershell에서의-레지스트리-액세스-내부-시퀀스">PowerShell에서의 레지스트리 액세스 내부 시퀀스
&lt;/h3>&lt;p>PowerShell 스크립트가 레지스트리를 변경할 때의 OS 내부 동작 시퀀스를 아래에 나타냅니다.&lt;/p>
&lt;pre class="mermaid">
sequenceDiagram
participant U as &amp;#34;관리자 / PowerShell&amp;#34;
participant PS as &amp;#34;Registry Provider (.NET)&amp;#34;
participant CM as &amp;#34;Configuration Manager (커널)&amp;#34;
participant Disk as &amp;#34;NTFS의 하이브 파일&amp;#34;
U-&amp;gt;&amp;gt;PS: &amp;#34;Set-ItemProperty -Path ... -Value ...&amp;#34;
PS-&amp;gt;&amp;gt;PS: &amp;#34;경로 파싱 및 데이터 형식 검증&amp;#34;
PS-&amp;gt;&amp;gt;CM: &amp;#34;NtSetValueKey (시스템 호출)&amp;#34;
CM-&amp;gt;&amp;gt;CM: &amp;#34;키 ACL에 대해 액세스 토큰 확인&amp;#34;
alt &amp;#34;액세스 허용 (관리자 토큰)&amp;#34;
CM-&amp;gt;&amp;gt;CM: &amp;#34;휘발성 캐시에 셀 할당&amp;#34;
CM-&amp;gt;&amp;gt;Disk: &amp;#34;트랜잭션 로그(.log1)에 플러시&amp;#34;
Disk--&amp;gt;&amp;gt;CM: &amp;#34;로그 쓰기 성공&amp;#34;
CM-&amp;gt;&amp;gt;Disk: &amp;#34;하이브 데이터 파일에 지연 쓰기 (백그라운드)&amp;#34;
CM--&amp;gt;&amp;gt;PS: &amp;#34;STATUS_SUCCESS (0x00000000)&amp;#34;
PS--&amp;gt;&amp;gt;U: &amp;#34;명령 완료&amp;#34;
else &amp;#34;액세스 거부 (표준 사용자)&amp;#34;
CM--&amp;gt;&amp;gt;PS: &amp;#34;STATUS_ACCESS_DENIED (0xC0000022)&amp;#34;
PS--&amp;gt;&amp;gt;U: &amp;#34;UnauthorizedAccessException 발생&amp;#34;
end
&lt;/pre>
&lt;h2 id="9-c-net을-통한-견고한-레지스트리-액세스">9. C# (.NET)을 통한 견고한 레지스트리 액세스
&lt;/h2>&lt;p>.NET 애플리케이션(C# 등)에서 레지스트리에 액세스할 경우 &lt;code>Microsoft.Win32.Registry&lt;/code> 클래스 및 &lt;code>RegistryKey&lt;/code> 클래스를 사용합니다.
C#을 이용하는 가장 큰 장점은 강력한 예외 처리(&lt;code>try-catch&lt;/code>)에 의한 견고한 오류 처리, 엄격한 타입 검사, 그리고 &lt;code>RegistryView&lt;/code> 열거형을 사용한 명시적인 32비트/64비트 뷰 지정이 가능하다는 점입니다.&lt;/p>
&lt;p>아래는 64비트 OS 환경에서 확실하게 64비트 측의 레지스트리(WOW6432Node의 리디렉션을 회피)를 읽고 쓰는 C# 코드 예제입니다.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;span class="lnt">26
&lt;/span>&lt;span class="lnt">27
&lt;/span>&lt;span class="lnt">28
&lt;/span>&lt;span class="lnt">29
&lt;/span>&lt;span class="lnt">30
&lt;/span>&lt;span class="lnt">31
&lt;/span>&lt;span class="lnt">32
&lt;/span>&lt;span class="lnt">33
&lt;/span>&lt;span class="lnt">34
&lt;/span>&lt;span class="lnt">35
&lt;/span>&lt;span class="lnt">36
&lt;/span>&lt;span class="lnt">37
&lt;/span>&lt;span class="lnt">38
&lt;/span>&lt;span class="lnt">39
&lt;/span>&lt;span class="lnt">40
&lt;/span>&lt;span class="lnt">41
&lt;/span>&lt;span class="lnt">42
&lt;/span>&lt;span class="lnt">43
&lt;/span>&lt;span class="lnt">44
&lt;/span>&lt;span class="lnt">45
&lt;/span>&lt;span class="lnt">46
&lt;/span>&lt;span class="lnt">47
&lt;/span>&lt;span class="lnt">48
&lt;/span>&lt;span class="lnt">49
&lt;/span>&lt;span class="lnt">50
&lt;/span>&lt;span class="lnt">51
&lt;/span>&lt;span class="lnt">52
&lt;/span>&lt;span class="lnt">53
&lt;/span>&lt;span class="lnt">54
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-csharp" data-lang="csharp">&lt;span class="line">&lt;span class="cl">&lt;span class="k">using&lt;/span> &lt;span class="nn">System&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">using&lt;/span> &lt;span class="nn">System.Security&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">using&lt;/span> &lt;span class="nn">Microsoft.Win32&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="k">class&lt;/span> &lt;span class="nc">RegistryEditor&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kd">static&lt;/span> &lt;span class="k">void&lt;/span> &lt;span class="n">Main&lt;/span>&lt;span class="p">()&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// HKLM 아래의 경로 (관리자 권한 필요)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">string&lt;/span> &lt;span class="n">keyPath&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="s">@&amp;#34;SOFTWARE\MyEnterpriseApp\Settings&amp;#34;&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// RegistryView.Registry64 를 지정하여 64비트 네이티브 뷰 열기&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// using 문을 사용하여 레지스트리 키의 핸들(비관리 리소스)을 확실하게 Dispose함&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">try&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">using&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">RegistryKey&lt;/span> &lt;span class="n">baseKey&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="n">RegistryKey&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">OpenBaseKey&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">RegistryHive&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">LocalMachine&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">RegistryView&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Registry64&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 쓰기 권限 (writable: true) 으로 키를 엽니다. 존재하지 않으면 생성.&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">using&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">RegistryKey&lt;/span> &lt;span class="n">subKey&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="n">baseKey&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">CreateSubKey&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">keyPath&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">writable&lt;/span>&lt;span class="p">:&lt;/span> &lt;span class="kc">true&lt;/span>&lt;span class="p">))&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">subKey&lt;/span> &lt;span class="p">!=&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// REG_DWORD 로 값 쓰기&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">subKey&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">SetValue&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;MaxConnections&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="m">100&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">RegistryValueKind&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">DWord&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// REG_SZ 로 값 쓰기&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">subKey&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">SetValue&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;ApiEndpoint&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="s">&amp;#34;https://api.example.com&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">RegistryValueKind&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">String&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// REG_BINARY 로 바이트 배열 쓰기&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">byte&lt;/span>&lt;span class="p">[]&lt;/span> &lt;span class="n">secretData&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="p">{&lt;/span> &lt;span class="m">0x01&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="m">0x02&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="m">0x0A&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="m">0xFF&lt;/span> &lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">subKey&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">SetValue&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;BinarySecret&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">secretData&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="n">RegistryValueKind&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">Binary&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Console&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">WriteLine&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;레지스트리 쓰기에 성공했습니다.&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">catch&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">UnauthorizedAccessException&lt;/span> &lt;span class="n">ex&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 관리자 권한으로 실행하지 않았을 때 자주 발생&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Console&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">WriteLine&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">$&amp;#34;권한 오류: 프로그램을 &amp;#39;관리자 권한으로 실행&amp;#39;해 주세요. 상세: {ex.Message}&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">catch&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">SecurityException&lt;/span> &lt;span class="n">ex&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// .NET의 코드 액세스 보안(CAS)에 의해 차단된 경우&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Console&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">WriteLine&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">$&amp;#34;보안 예외: {ex.Message}&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">catch&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">Exception&lt;/span> &lt;span class="n">ex&lt;/span>&lt;span class="p">)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// 기타 예기치 않은 IO 오류 등&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">Console&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">WriteLine&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">$&amp;#34;예기치 않은 오류: {ex.Message}&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>레지스트리의 키를 열었을 때 OS로부터 반환되는 &amp;ldquo;핸들&amp;quot;은 메모리와 시스템 리소스를 소비하는 비관리 리소스입니다. 따라서 &lt;code>using&lt;/code> 블록을 사용하거나 &lt;code>finally&lt;/code> 블록 내에서 명시적으로 &lt;code>.Dispose()&lt;/code> (또는 &lt;code>.Close()&lt;/code>)를 호출하여 핸들 누수를 확실하게 방지하는 것이 C# 프로그래밍의 철칙입니다.&lt;/p>
&lt;h2 id="10-레지스트리-백업-및-복원-방법">10. 레지스트리 백업 및 복원 방법
&lt;/h2>&lt;p>스크립트나 프로그램에 의한 자동화라 하더라도 중요한 변경을 가하기 전에는 백업을 확보하는 것이 절대적으로 필수적입니다.&lt;/p>
&lt;h3 id="reg-파일을-통한-백업-및-가져오기">.reg 파일을 통한 백업 및 가져오기
&lt;/h3>&lt;p>가장 고전적이고 범용적인 방법은 &lt;code>.reg&lt;/code> 파일로 내보내는 것입니다. 이 파일은 고유한 형식을 가진 텍스트 기반 파일이며 구조는 다음과 같습니다.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-text" data-lang="text">&lt;span class="line">&lt;span class="cl">Windows Registry Editor Version 5.00
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">[HKEY_CURRENT_USER\Software\MyCustomApp]
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;EnableDebug&amp;#34;=dword:00000001
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;ApiEndpoint&amp;#34;=&amp;#34;https://api.example.com&amp;#34;
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&amp;#34;BinaryData&amp;#34;=hex:01,02,0a,ff
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>&lt;em>참고: 바이너리 데이터는 &lt;code>hex:&lt;/code>에 이어지는 쉼표로 구분된 16진수로 표현됩니다.&lt;/em>&lt;/p>
&lt;p>명령줄 도구 &lt;code>reg.exe&lt;/code>를 사용하여 배치 스크립트 내에서 자동 백업을 구현할 수 있습니다.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cmd" data-lang="cmd">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">REM 지정한 키를 백업 (서브 키도 재귀적으로 내보내짐)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">reg export HKLM\SOFTWARE\MyEnterpriseApp C:\backup\myapp_backup.reg /y
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">REM 백업 복원&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">reg import C:\backup\myapp_backup.reg
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="powershell을-이용한-더-고급-백업-방법">PowerShell을 이용한 더 고급 백업 방법
&lt;/h3>&lt;p>단순한 텍스트로서가 아니라 PowerShell의 객체 지향성을 살려 레지스트리의 객체를 내보내고 XML 형식(CliXML)으로 저장하는 것도 가능합니다. 이를 통해 복원 시 문자열 파싱에 의존하지 않고 형식 정보를 유지한 채 처리할 수 있습니다.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-powershell" data-lang="powershell">&lt;span class="line">&lt;span class="cl">&lt;span class="c"># 백업 확보 (속성을 XML로 저장)&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nb">Get-ItemProperty&lt;/span> &lt;span class="n">-Path&lt;/span> &lt;span class="s2">&amp;#34;HKCU:\Software\MyCustomApp&amp;#34;&lt;/span> &lt;span class="p">|&lt;/span> &lt;span class="nb">Export-Clixml&lt;/span> &lt;span class="n">-Path&lt;/span> &lt;span class="s2">&amp;#34;C:\backup\reg_backup.xml&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># 복원의 개념&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="nv">$backup&lt;/span> &lt;span class="p">=&lt;/span> &lt;span class="nb">Import-Clixml&lt;/span> &lt;span class="n">-Path&lt;/span> &lt;span class="s2">&amp;#34;C:\backup\reg_backup.xml&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># $backup 에는 복원된 사용자 지정 PSObject가 저장되어 있으므로,&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c"># 그 속성을 순회하여 Set-ItemProperty 로 다시 적용하는 로직을 구성할 수 있습니다.&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="11-sysinternals-process-monitor-procmon을-활용한-문제-해결">11. Sysinternals Process Monitor (Procmon)을 활용한 문제 해결
&lt;/h2>&lt;p>프로그램이 레지스트리의 어디에 쓰고 있는지 알 수 없는 경우나 &amp;ldquo;Access Denied&amp;quot;의 원인을 찾을 때, Microsoft가 무료로 제공하는 Sysinternals 도구인 &lt;strong>Process Monitor (Procmon)&lt;/strong> 가 매우 강력합니다.
Procmon을 사용하면 OS 상에서 발생하는 모든 레지스트리 API 호출(&lt;code>RegOpenKey&lt;/code>, &lt;code>RegQueryValue&lt;/code>, &lt;code>RegSetValue&lt;/code> 등)을 실시간으로 캡처하고 다음과 같은 고급 필터링으로 문제 해결이 가능합니다.&lt;/p>
&lt;ul>
&lt;li>&lt;code>Process Name&lt;/code> is &lt;code>powershell.exe&lt;/code>&lt;/li>
&lt;li>&lt;code>Operation&lt;/code> begins with &lt;code>Reg&lt;/code>&lt;/li>
&lt;li>&lt;code>Result&lt;/code> is &lt;code>ACCESS DENIED&lt;/code>&lt;/li>
&lt;/ul>
&lt;p>이를 통해 어느 키의 ACL 설정이 부족한지, 혹은 WOW6432Node로 잘못 리디렉션되고 있는지를 순식간에 특정할 수 있습니다.&lt;/p>
&lt;h2 id="12-보안과-모범-사례">12. 보안과 모범 사례
&lt;/h2>&lt;p>마지막으로 레지스트리를 다룰 때의 중요한 설계 원칙과 모범 사례를 정리합니다.&lt;/p>
&lt;ol>
&lt;li>&lt;strong>최소 권한의 원칙을 철저히 한다&lt;/strong>: 애플리케이션이나 스크립트의 설정은 가능한 한 &lt;code>HKCU&lt;/code>(현재 사용자) 내의 &lt;code>Software&lt;/code> 키 아래에 저장해야 합니다. &lt;code>HKLM&lt;/code>에 대한 쓰기는 UAC에 의한 관리자 권한 상승을 요구하므로 보안상의 공격 표면(Attack Surface)을 넓히고 사용자 경험을 손상시킵니다.&lt;/li>
&lt;li>&lt;strong>감사 (Auditing) 활성화&lt;/strong>: 보안상 매우 중요한 키(예: 자동 시작을 관장하는 &lt;code>Run&lt;/code> 키나 서비스 설정 키 등)에 대해서는 SACL(System Access Control List)을 구성하여, 누가 언제 값을 변경하거나 삭제했는지를 Windows 이벤트 뷰어의 &amp;ldquo;보안 로그&amp;quot;에 기록(감사)하도록 설정합니다.&lt;/li>
&lt;li>&lt;strong>트랜잭션 기능의 사용 중단에 대응&lt;/strong>: 과거 Windows Vista에서 도입된 &amp;ldquo;커널 트랜잭션 관리자(KTM)&amp;ldquo;를 이용한 레지스트리 트랜잭션 기능(TxR)은 Windows 10 이후 더 이상 사용되지 않습니다(Deprecated). 애플리케이션 측에서 독자적으로 백업 및 롤백 메커니즘(변경 전에 원래 값을 읽어 메모리에 보관해 두는 등)을 구현해야 합니다.&lt;/li>
&lt;li>&lt;strong>그룹 정책 (GPO)과의 충돌 주의&lt;/strong>: &lt;code>HKLM\SOFTWARE\Policies&lt;/code>나 &lt;code>HKCU\Software\Policies&lt;/code> 영역은 Active Directory의 그룹 정책에 의해 중앙 집중식으로 관리되어야 하는 영역입니다. 스크립트에서 직접 이러한 키를 수정하더라도, 다음번 그룹 정책 백그라운드 업데이트 주기(일반적으로 90분~120분 간격)에 도메인 컨트롤러의 설정에 의해 강제로 덮어씌워지므로 설정이 영구적으로 유지되지 않는 원인이 됩니다.&lt;/li>
&lt;/ol>
&lt;h2 id="요약">요약
&lt;/h2>&lt;p>Windows 레지스트리는 OS의 모든 동작과 애플리케이션 설정을 통합적으로 관리하는 강력하고 복잡한 기반 시스템입니다. 수동에 의한 무질서한 편집에는 수학적으로도 입증되는 높은 시스템 손상 위험이 따릅니다. 따라서 PowerShell이나 C# 등의 프로그래밍 가능한 수단을 사용하여 Infrastructure as Code의 원칙에 따라 안전하고 테스트 가능하며 재현성 있는 형태로 구성 관리를 수행하는 것이 현대의 시스템 관리와 개발에 있어 필수적입니다. 본 기사에서 해설한 깊은 아키텍처 이해와 구현 패턴을 활용하여 더욱 견고하고 안전한 Windows 환경 구축을 목표로 해 보세요.&lt;/p></description></item></channel></rss>