DAP에서 LDAP으로, 디렉터리 서비스 프로토콜이 가벼워진 이유
X.500 DAP과 LDAP의 프로토콜 스택·정보 모델 차이, 오퍼레이션, 복제 토폴로지, 보안 설계 절차를 실무 관점으로 정리한다.
2026-08-13 · 최초 발행 2025-12-03
X.500이 정의한 디렉터리 서비스는 조직 정보와 정책을 중앙집중식으로 관리하기 위한 야심 찬 표준이었지만, OSI 프로토콜 스택 전체를 요구했다. DAP(Directory Access Protocol)이 그 접근 방식이다. LDAP(Lightweight Directory Access Protocol)은 같은 정보 모델을 TCP/IP 위에 얹어 방화벽·클라이언트 호환성을 확보한 경량 대안으로 등장했고, 지금은 인증·조직 정보·접근 제어를 중앙에서 관리하는 사실상의 표준 인프라 구성요소가 됐다.
프로토콜 스택과 인코딩
DAP은 OSI 7계층에서 ACSE/ROSE 상단에 얹혀 동작해 네트워크·게이트웨이 요구사항이 늘어난다. LDAP은 TCP/IP를 직접 사용해 세션 수립과 스트리밍이 단순하고, ASN.1 BER로 효율적으로 직렬화한다. LDAP(RFC 4511 계열, 최신 정보는 확인이 필요하다)이 ASN.1/BER 인코딩 자체는 DAP과 공유하면서 전송 계층만 가볍게 만든 셈이다.
정보 모델: DIT와 스키마
두 프로토콜이 공유하는 정보 모델은 DIT(Directory Information Tree), 엔트리(객체), 속성(Attribute), 스키마(ObjectClass/AttributeType)다. DIT는 dc=example,dc=com 같은 계층 네임스페이스와 고유 DN(Distinguished Name)을 부여하고, 스키마가 데이터 타입·제약을 관리하며, 인덱스 설계가 조회 성능과 일관성을 좌우한다.
LDAP이 지원하는 오퍼레이션
Bind/Unbind로 세션을 열고 닫으며, Search·Compare로 조회하고, Add/Modify/Delete·ModifyDN으로 변경하며, Extended/Control로 확장 기능을 다룬다. 검색은 Base/One/Subtree 범위와 (&(objectClass=person)(uid=jkim)) 같은 필터, 정렬·페이징 옵션을 지원한다.
보안: TLS·SASL·ACL
TLS·StartTLS로 채널을 암호화하고 SASL이나 단순 바인드로 인증하며, 최소 권한 원칙에 따른 ACL/ACI를 적용한다. 비밀번호 정책, 계정 잠금, 감사 로그가 규정준수를 뒷받침한다.
복제 토폴로지와 확장
배포는 단일 마스터, 다중 마스터(MMR), 리드 리플리카 구조로 나뉘고, 동기·비동기 복제와 충돌 해결 정책이 필요하다. 파티셔닝·서브트리 분할, 리퍼럴·프록시로 수평 확장을 꾀한다. 단일 마스터는 충돌이 최소화되고 가용성은 리플리카로 보완하지만 쓰기가 집중되면 병목이 생기고, 다중 마스터는 가용성과 쓰기 확장에 유리한 대신 충돌 해결과 최종 일관성 관리 부담이 커진다.
DAP과 LDAP 비교
| 지표 | DAP | LDAP |
|---|---|---|
| 성능 | OSI 스택 오버헤드, 초기 지연 증가 경향 | TCP/IP 경량 프로토콜, 낮은 지연·높은 처리량 |
| 확장성 | 게이트웨이·전용 스택 요구, 확장 비용 상승 | 범용 네트워크·클라이언트 호환, 수평 확장 용이 |
| 일관성 | X.500 구현에 따라 강한 일관성 모델 가능 | 구현별, 복제 토폴로지에 따른 궁극적 일관성 흔함 |
| 안정성 | 복잡도↑, 운영 실패 모드 다양 | 단순성↑, 장애 도메인 축소·복구 용이 |
| 운영 편의 | 전문 장비·기술 요구, 방화벽 통과 어려움 | 표준 포트, 풍부한 도구 생태계, 자동화 친화적 |
어디에 쓰이는가
엔터프라이즈 IAM/SSO에서는 사용자 저장소로 인증·속성 조회와 그룹·역할 매핑, 패스워드 정책 적용에 쓰이며 SAML/OIDC 공급자와 연계해 로그인 지연을 줄이려 인덱스·캐시를 설계한다. 조직 주소록·권한 정책 중앙화에서는 메일 시스템·협업도구·VPN 정책의 단일 소스 오브 트루스(Single Source of Truth)를 구축하고 OU·그룹 기반 접근 제어와 변경 감사를 수행한다. 네트워크 장비·어플라이언스 AAA에서는 스위치·방화벽 관리자 인증과 명령 수준 권한 부여에 쓰이며 RADIUS/TACACS+와 연동해 LDAP 속성을 매핑한다. PKI·인증서·CRL 배포에서는 사용자·디바이스 인증서 속성을 검색하고 CRL/OCSP를 보완하며, 보안 영역별로 서브트리를 분리해 노출을 최소화한다.
설계·도입 절차
먼저 사용자·그룹 규모, QPS·지연 목표, 보안·규정 준수 범위를 명세하고 스키마 커스터마이즈 필요성과 외부 시스템 연동 경로를 정의한다. 네이밍·스키마 설계 단계에서는 DN 네임스페이스와 OU 구조를 고정해 변경을 최소화하고, 필수·선택 속성과 고유성·케이스 규칙, 인덱스(Equality, Substring, Presence)를 결정한다.
성능·용량 계획에서는 읽기·쓰기 비율과 페이징·정렬 사용 여부를 반영하고, 캐시 크기와 B-트리/MDB 백엔드, SSD IOPS·메모리를 산정한다. 보안·접근 제어 단계에서는 최소 TLS 1.2를 필수화하고 서버·클라이언트 인증서를 관리하며, ACL을 단계적으로 적용하고 관리 바인드 계정을 분리해 감사 로깅·SIEM과 연계한다. 배포·운영 단계에서는 복제 토폴로지와 충돌 해결 정책을 문서화하고, 헬스체크·백업·재해복구 시나리오, 스키마 변경 승인·롤백 프로세스를 정립한다.
운영에서 마주치는 트레이드오프
인덱스는 Equality·Substring을 최소화해 쓰기 비용을 줄이되 조회 SLA 기준으로 균형을 맞춰야 한다 — 과도한 인덱스는 재빌드 지연과 락 확대를 부른다. 보안·암호화는 StartTLS를 우선하고 단순 바인드에는 TLS를 강제하며 SASL/GSSAPI 도입을 검토해야 하고, 비밀번호는 ssha512 같은 해시로 표준화하고 회전·만료 정책을 적용한다. 스키마는 커스텀을 최소화하고 표준 객체클래스 재사용을 우선하며, 변경은 개발→스테이징→프로덕션 순의 변경 윈도우와 백아웃 계획을 포함해야 한다.
이런 원칙을 지키면 계정·권한 중앙화, 중복 데이터 제거, 프로비저닝 자동화로 표준 프로토콜 기반 통합 비용이 30~60% 절감될 수 있다(환경 의존). 캐시·인덱스를 최적화하면 조회 지연이 수 ms 수준까지 낮아질 수 있고(워크로드 의존), 리드 리플리카로 스케일아웃하면 가용성과 처리량을 동시에 확보할 수 있다. 전 구간 TLS와 최소 권한 ACL, 감사 추적은 침해 노출면을 줄이고 계정 수명주기 관리와 정책 일관성을 뒷받침한다.
신규 도입은 LDAP 중심 설계가 권장되며, X.500과의 상호운용이 필요하면 게이트웨이·스키마 매핑을 병행한다. 안정적인 스키마·네임스페이스, 인덱스·캐시 튜닝, 보안·복제 정책의 표준화와 자동화가 성공 요인이다.
인증·조회·수정·복제 흐름
조회·바인드 코드 예시
전제조건은 OpenLDAP 클라이언트 도구 2.6+와 TLS가 활성화된 서버, Python 3.10+와 ldap3 2.9다.
ldapsearch로 인증서 검증과 페이징을 적용해 안전하게 조회한다.
LDAPTLS_REQCERT=demand \
ldapsearch -H ldaps://ldap.example.com:636 \
-D "uid=svc_reader,ou=svc,dc=example,dc=com" -W \
-b "dc=example,dc=com" -s sub \
-E pr=200/noprompt \
"(&(objectClass=person)(uid=jkim))" \
cn mail memberOf
Python ldap3로 바인드·조회하는 코드도 동일한 조건을 따른다.
# Python 3.10+, pip install ldap3==2.9
from ldap3 import Server, Connection, Tls, ALL, SUBTREE
import ssl
tls = Tls(validate=ssl.CERT_REQUIRED)
server = Server('ldap.example.com', port=636, use_ssl=True, get_info=ALL, tls=tls)
with Connection(server,
user='uid=svc_reader,ou=svc,dc=example,dc=com',
password='secret',
auto_bind=True) as conn:
conn.search(search_base='dc=example,dc=com',
search_filter='(&(objectClass=person)(uid=jkim))',
search_scope=SUBTREE,
attributes=['cn', 'mail', 'memberOf'],
paged_size=200)
for entry in conn.entries:
print(entry.entry_dn, entry.cn, entry.mail)
에러 코드는 원인이 뚜렷하다. 49(invalidCredentials)는 자격 증명 오류이므로 계정 잠금을 확인하고, 32(noSuchObject)는 DN 경로를 확인하고 서브트리 권한을 검토하며, 50(insufficientAccessRights)는 ACL을 추가·수정하거나 바인드 주체를 바꿔야 한다.