
Oracle AI Database의 Deep Data Security와 Java를 사용하여 데이터베이스가 강제하는 엔드 유저 인증 개발하기
요약
Spring Boot 애플리케이션에서 Microsoft Entra ID를 통해 Oracle AI Database의 행, 열, 셀 수준 보안을 구현하는 실무 가이드입니다. JDBC 연결을 통해 엔드 유저의 신원을 전파하고 데이터베이스 수준에서 권한 부여를 강제하는 방법을 다룹니다.
핵심 포인트
- JDBC 엔드 유저 보안 컨텍스트를 통한 신원 전달
- OAuth on-behalf-of 흐름을 이용한 토큰 전파
- Microsoft Entra 앱 역할을 Oracle 데이터 역할로 매핑
- 애플리케이션의 역할 독립성 유지 및 DB 중심 권한 제어
행(row), 열(column) 및 셀(cell) 수준의 액세스 규칙을 강제하는 Oracle AI Database로의 JDBC 연결을 통해, Spring Boot 애플리케이션을 거쳐 Microsoft Entra ID를 전파하는 실무 가이드입니다.
소스 코드 및 비디오
애플리케이션의 모든 소스 코드는 GitHub repo에서 확인할 수 있습니다.
비디오 가이드 (8분): 임베디드 플레이어를 사용할 수 없는 경우
하세요.핵심 요약 (Key Takeaways)
- 애플리케이션 코드나
ojdbc-provider-spring이 SQL 실행 전에 Oracle JDBC 엔드 유저 보안 컨텍스트(end-user security context)를 부착하면, 풀링된(Pooled) JDBC 연결을 통해 엔드 유저의 신원을 전달할 수 있습니다. - OAuth의 on-behalf-of 흐름은 별도의 데이터베이스 액세스 토큰(database-access token)을 생성하므로, 사용자 토큰은 브라우저 사용자를 증명하고 데이터베이스 토큰은 Oracle AI Database에 대한 액세스를 증명합니다.
- EMPLOYEES 및 MANAGERS와 같은 Microsoft Entra 앱 역할(app roles)은 Oracle Deep Data Security 데이터 역할(data roles)로 매핑되어, 동일한 SQL이라도 로그인한 사용자에 따라 서로 다른 행을 반환할 수 있게 합니다.
- Java 애플리케이션은 역할에 구애받지 않는 상태(role-agnostic)를 유지합니다. Oracle AI Database가 행, 열 및 셀 수준의 권한 부여(authorization)를 위한 강제 지점(enforcement point)이 됩니다.
네, 엔터프라이즈 Spring Boot 애플리케이션은 풀링된 JDBC 연결을 유지하면서도, Oracle AI Database가 로그인한 각 Microsoft Entra 사용자에 대해 권한 부여를 강제할 수 있습니다. 애플리케이션은 사용자 및 데이터베이스 토큰을 전파하며, Deep Data Security는 SQL이 실행될 때 선언적인 행, 열 및 셀 수준의 규칙을 적용합니다.

이것이 중요한 이유
대부분의 엔터프라이즈 Java 서비스는 커넥션 풀 (Connection Pool)을 사용합니다. 이는 빠르고, 안정적이며, 관찰 가능하고, 운영하기 쉬운 훌륭한 엔지니어링 방식입니다. 하지만 이는 모든 요청이 동일한 애플리케이션 데이터베이스 계정을 통해 데이터베이스에 도달할 수 있음을 의미하기도 합니다.
바로 이 지점에서 권한 부여 (Authorization)가 까다로워집니다. 만약 Emma와 Marvin이 모두 동일한 풀링된 데이터베이스 사용자를 사용한다면, 데이터베이스는 자연스럽게 어떤 행 (Row)이 Emma의 것인지, Marvin이 어떤 열 (Column)을 볼 수 있는지, 또는 관리자가 어떤 값을 업데이트할 수 있는지 구분할 수 없습니다.
한 가지 방법은 모든 애플리케이션 쿼리에 해당 로직을 밀어 넣는 것입니다. 다른 방법은 사용자당 별도의 데이터 소스 (Data Source) 또는 커넥션 풀을 생성하는 것입니다. 하지만 두 방법 모두 실제 엔터프라이즈 시스템에는 적합하지 않습니다.
Oracle Deep Data Security는 이 문제의 형태를 바꿉니다. 애플리케이션은 여전히 풀링된 커넥션을 사용하지만, SQL이 실행되기 전에 JDBC 커넥션에 엔드 유저 보안 컨텍스트 (End-user security context)를 부착합니다. Oracle AI Database는 실행 시점에 선언적 데이터 권한 (Declarative data grants)을 평가합니다.
이는 에이전트형 애플리케이션 (Agentic applications)에서 더욱 중요합니다. 에이전트 (Agents), 코파일럿 (Copilots), 그리고 자연어 SQL 도구들은 수많은 가능한 데이터 경로로 확산될 수 있습니다. Deep Data Security를 사용하면, 데이터베이스가 세밀한 행 (Row), 열 (Column), 그리고 셀 (Cell) 수준의 액세스에 대한 최종 정책 강제 지점 (Policy enforcement point)으로 남게 됩니다.
핵심 아이디어: Spring Boot 앱은 SQL을 재작성하거나 권한 부여 로직을 구현하지 않습니다. 대신 신원 (Identity)과 토큰을 Oracle AI Database로 전달하며, 데이터베이스가 권한 부여 정책을 강제합니다.
이 가이드에는 Microsoft 문서를 링크하는 대신 Microsoft Entra 설정 과정을 명시적으로 포함했습니다. 이 부분은 미묘하게 틀리기 쉬운 부분이며, 이를 직접 작성하면서 저 또한 더 깊이 이해할 수 있었습니다.
좋은 시작점이자 제가 이 Java 애플리케이션을 만들기 위해 확장한 기반은 Richard C. Evans의 훌륭한 LiveLabs FastLab: Microsoft Entra ID 및 Oracle Deep Data Security를 사용한 ID 인식 데이터베이스 액세스입니다. 공로를 인정하며 덧붙이자면, Michael McMahon은 이 Deep Data Security 기능을 위한 Java 지원을 작성한 환상적이고 친절한 개발자입니다.
우리가 구축하는 것
이 데모는 네 가지 주요 작업을 수행하는 Spring Boot 애플리케이션입니다:
- Microsoft Entra ID를 사용하여 브라우저 사용자를 인증합니다.
- OAuth 2.0 on-behalf-of 플로우를 사용하여 데이터베이스 액세스 토큰을 요청합니다.
- EndUserSecurityContext를 사용하여 Oracle JDBC 연결에 두 토큰을 모두 부착합니다.
- Oracle AI Database가 데이터 권한 (data grants)을 강제하는 동안 HR 테이블에 대해 일반 SQL 쿼리를 실행합니다.
리포지토리에는 풀링된 JDBC 연결을 위해 Oracle UCP를 사용하는 두 가지 정렬된 데모가 포함되어 있습니다:
- 명시적 JDBC API 버전: 애플리케이션 코드가 두 토큰을 모두 가져와
OracleConnection.setEndUserSecurityContext(...)및clearEndUserSecurityContext()를 호출합니다. - ojdbc-provider-spring provider/SPI 버전: Oracle JDBC가 현재 Spring Security 컨텍스트를 읽고 provider SPI를 통해 엔드 유저 보안 컨텍스트 (end-user security context)를 제공합니다.
런타임 흐름 (Runtime Flow)
- 브라우저가
GET /deepsec/query를 호출합니다. - Spring Security가 브라우저를 Microsoft Entra ID로 리다이렉트합니다.
- 사용자가 로그인합니다.
- Spring Security가 권한 부여 코드 (authorization code)를 수신하고, 이를 사용자의 Entra 액세스 토큰 (access token)으로 교환합니다.
- 백엔드는 OAuth 2.0의 on-behalf-of (OBO) 흐름을 사용하여 해당 사용자 토큰을 별도의 데이터베이스 액세스 토큰 (database-access token)으로 교환합니다.
- Oracle JDBC는 명시적인 애플리케이션 코드 또는 Spring 프로바이더 SPI (Spring provider SPI)를 통해 두 토큰을 모두 포함하는
EndUserSecurityContext를 수신합니다. - Oracle AI Database는 컨텍스트를 검증하고, Entra 역할 클레임 (roles claim)으로부터 매핑된 데이터 역할 (data roles)을 활성화하며, SQL이 실행되는 동안 데이터 권한 (data grants)을 강제합니다.
- 명시적 API 앱은 커넥션을 풀 (pool)에 반환하기 전에 컨텍스트를 삭제하며, 프로바이더는 SPI를 통해 해당 컨텍스트의 생명주기 (lifecycle)를 관리합니다.
결과: 애플리케이션은 역할에 구애받지 않는 (role-agnostic) 상태를 유지합니다. 권한 부여 로직이 Java 코드에서 제거됩니다. Oracle AI Database가 강제 지점 (enforcement point)이 됩니다.
ID 및 토큰 모델 (Identity and Token Model)
OBO 이전에 토큰 모델 이해하기
두 토큰을 초기에 분리하면 on-behalf-of 흐름을 더 쉽게 이해할 수 있습니다:
| 토큰 | 증명 내용 | 대상 (Audience) / 주요 클레임 (claims) |
|---|---|---|
| 사용자 토큰 (User token) | Spring Boot 애플리케이션에 로그인한 브라우저 사용자를 증명합니다. 백엔드는 이를 OBO를 위한 어서션 (assertion)으로 사용합니다. | 대상은 Spring Boot 앱입니다. 브라우저 로그인 중에 요청됩니다. |
| 데이터베이스 액세스 토큰 (Database-access token) | 요청이 보호된 리소스인 Oracle AI Database를 향하고 있음을 증명합니다. | 대상은 데이터베이스/API 앱입니다. 이 데모의 경우, v2여야 하며 DDS 역할 매핑에 사용되는 roles 클레임을 포함해야 합니다. |
두 토큰 모두 중요합니다. 명시적 API 데모는 EndUserSecurityContext.createWithToken(databaseAccessToken, endUserToken)을 사용하여 컨텍스트를 생성하며, 프로바이더 데모는 JDBC 프로바이더 SPI를 통해 동일한 컨텍스트를 제공합니다.
실제 사용자 및 샘플 HR 레코드
실제 Entra 사용자
브라우저 로그인은 실제 Microsoft Entra 사용자를 사용합니다. 해당 사용자는 데이터베이스/API 엔터프라이즈 애플리케이션(Enterprise Application)에서 EMPLOYEES 또는 MANAGERS와 같은 앱 역할(app-role) 할당을 받습니다.
샘플 HR 레코드
Emma, Marvin, Charlie, Dana는 데이터베이스 내의 샘플 HR 행(row)이며, Entra 사용자가 아닙니다. 직원 데모를 위해, 하나의 HR 행이 ORA_END_USER_CONTEXT.username에서 Oracle이 확인하는 값으로 매핑됩니다.
설정 순서: 남은 섹션에서는 데모를 실행하기 전에 데이터베이스, Microsoft Entra를 구성한 다음 Spring Boot 구현체를 구성합니다.
데이터베이스 설정
1. Oracle AI Database가 없는 경우 생성하기
Deep Data Security 지원이 가능한 Oracle AI Database가 필요합니다. Autonomous Database, 컨테이너 내의 Oracle AI Database Free, 또는 Spring Boot 앱에서 접속 가능한 다른 로컬 또는 클라우드 데이터베이스를 포함하여, 23.26.2 이상의 모든 데이터베이스를 이 실습에 사용할 수 있습니다.
2. Microsoft Entra 신뢰 구성
Oracle AI Database가 데이터베이스 액세스 토큰(database-access token)을 검증하기 전에, Entra 테넌트(tenant)와 데이터베이스/API 앱 등록(app registration)을 신뢰해야 합니다. 사용 중인 환경에 맞는 데이터베이스 관리자(database-admin) 설정 스크립트를 선택하세요:
sql-entraid/01_enable_adb_entra_external_authentication.sql은 Autonomous Database를 위해DBMS_CLOUD_ADMIN.ENABLE_EXTERNAL_AUTHENTICATION을 사용합니다.DEFINE값을 편집한 후ADMIN권한으로 한 번 실행하십시오.sql-entraid/01_enable_database_free_entra_external_authentication.sql은 Oracle AI Database Free 또는 다른 비-ADB(non-ADB) 설치 환경을 위해IDENTITY_PROVIDER_TYPE및IDENTITY_PROVIDER_CONFIG를 사용합니다.SYSDBA또는 그에 상응하는 권한으로 한 번 실행하십시오.
비-ADB 데이터베이스의 경우, 도메인 자격 증명이 포함된 애플리케이션 ID URI(Application ID URI)를 데이터베이스/API 앱 등록, DEEPSEC_ENTRA_DATABASE_SCOPE, 그리고 선택 사항인 tnsnames.ora의 azure_db_app_id_uri 값 간에 일치하도록 유지하십시오.
-- Autonomous Database, DEFINE 값을 편집한 후 ADMIN 권한으로 한 번 실행:
@security/deepdatasecurity-api-version/sql-entraid/01_enable_adb_entra_external_authentication.sql
...
데이터베이스가 ID 제공자(identity provider)를 인식했는지 확인합니다:
SELECT name, value
FROM v$parameter
WHERE name IN ('identity_provider_type', 'identity_provider_config');
애플리케이션 커넥션 풀(connection-pool) 사용자에게 연결 및 엔드 유저 보안 컨텍스트(end-user security context)를 부착하는 데 필요한 권한만 부여합니다:
GRANT CREATE SESSION TO hr_app_user;
GRANT CREATE END USER SECURITY CONTEXT TO hr_app_user;
3. Entra 앱 역할(App Roles)을 Deep Data Security 역할로 매핑하기
데이터베이스 내에서 Microsoft Entra 앱 역할은 Oracle Deep Data Security 데이터 역할(data roles)로 매핑됩니다:
CREATE OR REPLACE DATA ROLE hrapp_employees
MAPPED TO 'AZURE_ROLE=EMPLOYEES';
...
로그인한 사용자가 Entra 앱 역할인 EMPLOYEES를 가지고 있으면, Oracle은 HRAPP_EMPLOYEES를 활성화합니다. 만약 동일한 사용자가 나중에 Entra 앱 역할인 MANAGERS를 갖게 되거나, 다른 로그인 사용자가 MANAGERS를 가지고 있다면, Oracle은 매니저 데이터 역할을 활성화합니다. 사용자는 여러 개의 앱 역할을 가질 수도 있습니다.
4. 데이터 권한(Data Grants) 생성하기
정책 자체는 SQL에 존재합니다. 직원의 경우, 행 술어(row predicate)는 사용자가 테이블의 username이 ORA_END_USER_CONTEXT.username과 일치하는 행을 볼 수 있다고 명시합니다:
CREATE OR REPLACE DATA GRANT hr.HRAPP_EMPLOYEES_ACCESS
AS SELECT, UPDATE(phone_number, first_name)
ON hr.employees
...
매니저의 경우, 정책은 ssn과 같은 민감한 컬럼을 제외하면서 직속 부하 직원에게는 접근을 허용합니다:
CREATE OR REPLACE DATA GRANT hr.HRAPP_MANAGER_ACCESS
AS SELECT (ALL COLUMNS EXCEPT ssn),
UPDATE (salary, department_id, first_name)
...
여기서 일어나지 않고 있는 점에 주목하십시오. Java 서비스나 AI 에이전트가 직원과 매니저를 위해 별도의 커스텀 SQL을 구축하고 있지 않습니다. 애플리케이션은 동일한 비즈니스 쿼리를 발행할 수 있으며, Oracle이 활성화된 엔드 유저 보안 컨텍스트(end-user security context)에 따라 결과를 필터링하거나 제한합니다.
tnsnames.ora의 선택적 연결 메타데이터
이 단계는 선택 사항입니다. 프로바이더 데모와 해당 Deep Data Security 흐름은 tnsnames.ora에 Entra 메타데이터를 요구하지 않습니다. 직접적인 JDBC Thin 대화형 Entra 로그인 또는 중앙에서 관리되는 TNS 연결 메타데이터를 원하는 경우에만 사용하십시오.
Wallet의 tnsnames.ora 항목은 해당 Entra 전용 연결 메타데이터를 포함할 수 있습니다. 주요 추가 사항은 보안 블록(security block) 내의 token_auth=azure_interactive 및 azure_db_app_id_uri=api://<DB_APP_CLIENT_ID>입니다. mydb_high 별칭(alias)은 다음과 같은 형태가 됩니다:
mydb_high =
(description=
(retry_count=20)(retry_delay=3)
...
사용자 고유의 서비스 이름과 데이터베이스/API 앱 ID URI를 사용하십시오. token_auth=azure_interactive는 드라이버가 브라우저 기반의 Entra 로그인 흐름을 열 수 있기 때문에 직접적인 JDBC Thin 테스트에 유용합니다. azure_db_app_id_uri는 드라이버에게 어떤 Entra 리소스가 데이터베이스를 나타내는지 알려줍니다.
Spring Boot 데모 자체는 일반적인 풀링된 애플리케이션 데이터베이스 사용자를 사용하며 프로그래밍 방식으로 Deep Data Security 컨텍스트를 부착하므로, UCP 풀을 위해 token_auth=azure_interactive가 없는 별도의 애플리케이션 별칭을 유지합니다.
Entra 설정
아래의 모든 ID 설정은 Azure Portal의 Microsoft Entra ID에서 수행됩니다. 앱 등록(App registrations)과 엔터프라이즈 애플리케이션(Enterprise applications) 사이를 이동하며 작업하게 됩니다.
앱 등록(App registration)의 역할
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기