---
title: "프로그램 파생 주소(PDA)란?"
description: "프로그램 파생 주소가 무엇인지, PDA가 일반 주소와 어떻게 다른지, 그리고 PDA 사용 사례를 알아보세요"
---

# 프로그램 파생 주소(PDA)란?

프로그램 파생 주소\(Program Derived Addresses, PDAs\)는 Solana 블록체인에서 특별한 속성을 가진 계정입니다. PDA를 제대로 활용하면 프로그램 간 통신을 지원하기 때문에 [Solana dApp 개발을 빠르게](https://www.alchemy.com/overviews/learn-solana-development) 만들고 효율성을 높일 수 있습니다.

이 글에서는 PDA가 무엇인지, 어떤 문제를 해결하는지, 어떻게 작동하는지, 그리고 [Solana의 계정 모델](https://www.alchemy.com/overviews/solana-account-model)에서 다른 계정과 어떻게 다른지 설명합니다.

## **프로그램 파생 주소\(PDA\)란 무엇인가?**

**프로그램 파생 주소는 개인 키가 없는 Solana 블록체인상의 계정입니다**. PDA는 공개 키가 아니기 때문에, 계정 주소는 프로그램 ID, SHA-512 해싱 함수, 시드 배열, 그리고 특별한 범프 시드를 이용해 찾습니다.

### **Solana의 표준 계정이란 무엇인가?**

**Solana의 표준 계정은 개인 키와 공개 키\(각각 32바이트\)를 모두 가지고 있으며, 이 둘이 합쳐져 64바이트 길이의 키페어를 이루고 타원 곡선\(ED25519\) 위에 위치합니다**. 키페어가 유효하려면 이 곡선 위에 있어야 합니다.

다음은 ED25519 타원 곡선을 나타낸 것입니다:

<ImageBlock
  src="https://media.alchemy.com/1703701173-elliptic-curve-on-solana.png"
  alt="Solana 계정 키페어에 사용되는 ED25519 타원 곡선 그래프"
  width={1600}
  height={900}
  caption="Solana의 ED25519 타원 곡선"
/>

## **프로그램 주소는 어떻게 파생되는가?**

PDA에는 세 가지 주요 구성 요소가 필요합니다:

1. **부모 프로그램 ID** - PDA를 생성하는 부모 프로그램의 ID
1. **시드** - 문자열 배열
1. **범프 시드** - PDA가 개인 키를 갖지 않도록 보장

**유효한 프로그램 파생 주소를 생성하려면 부모 프로그램의 ID와 시드 배열을 SHA-512 해싱 함수에 통과시켜야 합니다**.

하지만 이 해시 결과값이 _ED25519 타원 곡선_ 위에 위치하는 키페어가 되는 경우가 약 50%에 달합니다. PDA는 개인 키를 가지지 않기 때문에, 프로그램 파생 주소는 **타원 곡선 위에 있어서는 안 됩니다**. PDA가 개인 키를 갖지 않도록 하기 위해, 특별한 _범프_ 시드를 사용해 해시 결과를 곡선 밖으로 "밀어냅니다".

범프 시드는 단순히 255부터 시작하는 숫자입니다. 범프 시드를 적용해도 해시 결과가 여전히 곡선 위에 있는 경우, 해싱 함수를 254, 253 등으로 범프 값을 줄여가며 다시 실행하여, 생성된 결과가 곡선 위에 있지 않을 때까지 반복합니다.

참고: 시드는 임의의 문자열이 될 수 있지만, 개발자들은 부모 프로그램의 상태 변수와 관련된 맥락에서 시드를 사용해 해시맵과 유사한 구조를 만듭니다.

## **PDA는 어떤 문제를 해결하는가?**

**프로그램 파생 주소는 트랜잭션 서명을 프로그래밍 방식으로 생성함으로써 트랜잭션 확인을 간소화하며, 이를 통해 DeFi 계정과 같은 신뢰가 필요 없는\(trustless\) 서비스가 원활하게 작동하도록 돕습니다.**

다음은 PDA의 가상 사용 사례입니다.

사용자가 NFT를 기본 프로필 사진\(PFP\)으로 설정할 수 있는 Solana 프로그램을 생각해봅시다. 이 프로그램은 두 개의 프로그램으로 구성됩니다:

1. **PFP 프로그램** - 사용자가 선택한 프로필 사진을 저장하는 계정을 생성
1. **Core 프로그램** - 사용자의 입력과 PFP 프로그램 사이의 프록시 역할

PFP 프로그램이 사용자가 선택한 프로필 사진을 업데이트하려면, 프로필 사진을 변경하는 트랜잭션에 서명하기 위해 자신의 개인 키를 사용해야 합니다. 하지만 이는 프로그램이 자신의 개인 키를 온체인에 저장해야 한다는 것을 의미합니다.

Solana 프로그램은 자신의 개인 키를 사용해 스스로를 대신하여 트랜잭션에 서명할 수 없습니다. 왜냐하면 그 키 자체가 온체인에 저장되어 모두에게 노출되기 때문입니다. 만약 이런 일이 발생한다면, 그 개인 키를 이용해 프로그램을 대신해 트랜잭션에 서명하고 임의의 사용자의 프로필 사진을 변경할 수 있게 됩니다.

PFP 프로그램이 수백만 개의 SOL 토큰을 다루는 상황을 상상해 보십시오. 이러한 취약점은 심각한 해킹으로 이어질 수 있습니다. 프로그램 파생 주소는 이 문제를 해결합니다.

## **PDA는 왜 중요한가?**

프로그램 파생 주소는 서로 다른 프로그램 간의 통신\(Cross Program Invocations\)을 돕고, 부모 프로그램이 쉽게 업데이트하고 변경할 수 있는 특정 데이터를 저장하는 해시맵 역할을 할 수 있기 때문에 Solana 프로그래밍에서 핵심적인 역할을 합니다.

### **1. 프로그램의 상태 변수 저장**

PDA를 이용하면 Solana 개발자는 특정 사용자와 관련된 변수 또는 변수 집합을 저장하고 추적할 수 있습니다. PDA의 가장 좋은 활용 사례는 부모 프로그램의 상태 변수나 데이터를 저장하는 것인데, 기본적으로 부모 프로그램이 PDA를 대신해 변경할 수 있는 권한을 부여받았기 때문입니다.

### **2. PDA를 해시맵으로 사용하기**

매핑\(Mapping\)은 키-값 쌍의 집합을 나타내며, 특정 키와 연관된 정보를 쉽게 찾는 데 사용됩니다. Solana 개발에서는 PDA의 시드와 올바른 문자열을 사용해 동일한 결과를 얻을 수 있습니다.

**앞서 다룬 지갑 프로필 사진 예시로 돌아가 보겠습니다.**

사용자가 지갑의 PFP를 선택하면, PFP 프로그램은 선택된 이미지와 사용자의 주소를 가져와 이를 '시드'로 사용하여 사용자의 선택을 저장할 PDA를 생성합니다.

해싱 알고리즘에 의해 프로그램 파생 주소가 성공적으로 찾아지면, 해당 공개 키는 사용자의 주소와 선택된 NFT 아바타에 '매핑'됩니다.

이 해시맵 기능은 또 다른 PDA를 세 번째 시드로 제공함으로써 더욱 잘 활용할 수 있습니다. 사용 가능한 모든 프로필 사진을 모아 별도의 PDA에 저장하고, 각 프로필 사진을 그 시드로 전달하면, 모든 프로필 사진을 저장하는 PDA를 얻게 됩니다.

이제 사용자가 프로필 사진을 선택하면, PDA는 마치 해시맵처럼 보일 것입니다. 왜냐하면 시드가 전달되는 방식을 보면, 프로필 사진 목록\(PFP 그룹 PDA\) 중에서, 첫 번째 시드로 전달한 사용자의 주소가, 두 번째 시드로 전달한 프로필 사진을 선택했다는 것을 알 수 있기 때문입니다.

이 예시를 확장하면 훨씬 더 깊은 해시맵 구조를 만들 수 있습니다.

<ImageBlock
  src="https://media.alchemy.com/1703701259-pda-as-hashmap-program-flow.jpeg"
  alt="해시맵으로서의 PDA 프로그램 흐름 - NFT 예제"
  width={1024}
  height={768}
  caption="해시맵으로서의 PDA 프로그램 흐름 - NFT 예제"
/>

### **3. 크로스 프로그램 호출**

[크로스 프로그램 호출\(Cross Program Invocations, CPI\)](https://www.alchemy.com/overviews/cross-program-invocation)은 한 프로그램이 다른 프로그램의 함수를 호출하는 과정입니다. CPI는 코드의 조합성\(composability\)을 높여주기 때문에 유용합니다.

다시 앞선 예시로 돌아가서, 사용자가 프로필 사진을 Degen Ape에서 Solana Monkey Business 아바타로 변경하려 한다고 가정해봅시다.

**내부적으로 일어나는 과정은 다음과 같습니다:**

사용자가 지갑에 로그인하면, Core 컨트랙트는 사용자의 주소\(공개 키\)를 가져와 해당 사용자의 공개 키를 시드로 포함하고 있는 이미 생성된 PDA를 찾습니다.

이를 찾은 후, Core 프로그램은 PFP 프로그램 내의 'changePFP\(\)'라는 함수를 호출합니다\(이것이 크로스 프로그램 호출입니다\). 이때 Core 프로그램이 이미 '선택'한 PDA를 인자로 전달합니다.

함수가 호출되면, 선택된 PDA는 변경을 '요청'하는 계정이 자신의 부모인지 확인합니다. PDA가 일치하지 않으면 트랜잭션은 거부됩니다. 오직 부모 프로그램만이 PDA의 데이터를 수정할 수 있기 때문입니다.

PFP 프로그램이 선택된 PDA의 부모이므로, 사용자의 프로필 사진을 Degen Ape에서 SMB 아바타로 변경할 수 있게 됩니다.

<ImageBlock
  src="https://media.alchemy.com/1703701345-cross-program-invocation-with-pda.jpeg"
  alt="PDA를 이용한 Cross Program Invocation - NFT 이미지 변경"
  width={1600}
  height={901}
  caption="PDA를 이용한 Cross Program Invocation - NFT 이미지 변경"
/>

프로그램 파생 주소는 부모 프로그램이 자신을 대신해 서명할 수 있도록 하며, 프로그램의 상태, 해시맵을 저장하고 크로스 프로그램 호출에 사용될 수 있습니다. PDA는 Solana 프로그래밍의 근본적인 주제로, 빠르고 효율적인 dApp 개발을 가능하게 합니다.

## **프로그램 파생 주소 FAQ**

프로그램 파생 주소를 다룰 때는 Solana가 트랜잭션과 데이터를 어떻게 처리하는지 이해하는 것이 도움이 됩니다. 계정의 두 가지 주요 유형은 실행 가능\(executable\) 계정과 실행 불가능\(non-executable\) 계정입니다.

### **실행 가능 계정이란 무엇인가?**

**_프로그램_**이라고도 불리는 실행 가능 계정은 Ethereum 스마트 컨트랙트와 유사합니다 — 계정이 상호작용할 때 상태를 변경하는 코드 조각입니다.

### **실행 불가능 계정이란 무엇인가?**

실행 불가능한 데이터 계정은 단순히 데이터를 저장하는 데 사용됩니다\(예: 계정이 소유한 SOL의 양, NFT, 토큰 잔액 등\). 본질적으로 프로그램의 상태 변수라 할 수 있습니다.

### **Solana 프로그램의 데이터 저장 방식은 Ethereum 스마트 컨트랙트와 어떻게 다른가?**

Ethereum과 Solana 사이의 근본적인 차이 중 하나는 실행 코드의 저장 방식이 어떻게 구성되는가입니다. Ethereum의 스마트 컨트랙트는 [스마트 컨트랙트가 모든 상태 변수를 저장하는](https://www.alchemy.com/docs/smart-contract-storage-layout) **저장소**가 '미리 내장'되어 있습니다. 반면 Solana의 프로그램은 미리 내장된 저장소를 가지고 있지 않고, 저장하고 참조하고자 하는 다양한 상태 변수를 담는 별도의 데이터 계정을 가지고 있습니다.
