안전 설정 이해 및 구성하기

Gemini 모델은 안전을 우선시하도록 설계되었습니다. 하지만 특히 선정적인 프롬프트가 작성되는 경우 유해한 대답이 생성될 수 있습니다. 안전을 강화하고 오용을 최소화하기 위해 잠재적으로 유해한 대답을 차단하도록 안전 필터를 구성할 수 있습니다.

다음과 같은 두 가지 안전 보호 기능이 제공됩니다.

  • 기본 제공되는 핵심 보호 기능:

    • 모든 Gemini 모델에는 심각한 피해 (예: 아동 착취, 사이버 공격, 위험한 무기)에 대한 기본 제공 보호 기능이 포함되어 있습니다.
    • 이러한 보호 조치는 항상 활성 상태이며 모든 프롬프트와 대답에 자동으로 적용되며 수정하거나 사용 중지할 수 없습니다.
  • 구성 가능한 안전 필터:

    • Gemini API는 앱의 안전 설정을 사용하여 정의하는 추가 구성 가능한 안전 필터를 제공합니다.
    • 이 설정을 사용하면 괴롭힘, 증오심 표현, 음란물, 위험한 콘텐츠라는 네 가지 주요 피해 카테고리에서 콘텐츠가 차단되는 기준점을 제어할 수 있습니다.

코드 샘플로 이동

중요 안전 개념

Gemini 모델의 안전을 다룰 때 이해해야 할 몇 가지 중요한 개념은 다음과 같습니다.

  • 안전 설정: 앱 코드에서 정의하는 구성으로, 모니터링할 유해 카테고리와 콘텐츠를 차단할 기준을 지정합니다.

  • 안전 필터: Google의 안전 측정기준에 따라 프롬프트와 모델 대답을 평가하는 서버 측 분류기입니다. 필터는 구성된 안전 설정에 따라 콘텐츠를 차단합니다.

  • 안전 등급: 모델이 응답 객체에서 반환하는 평가 메타데이터입니다. 평점은 각 피해 카테고리에서 감지된 잠재적 피해의 확률과 심각도를 나타냅니다.

지원되는 모델

  • gemini-4-argon
  • gemini-3.8-flash (및 이전 gemini-3.7-flash, gemini-3.6-flash, gemini-3.5-flash)
  • gemini-3.5-flash-lite (및 이전 gemini-3.1-flash-lite)
  • gemini-nano-banana-2.1(Nano Banana 2.1)
  • gemini-3.1-flash-image(Nano Banana 2)
  • gemini-3.1-flash-lite-image(Nano Banana 2 Lite)
  • gemini-3-pro-image(Nano Banana Pro)

gemini-3.1-pro-preview 모델과 범용 및 이미지 생성 Gemini 2.5 모델 (지원 중단됨)도 이 기능을 지원합니다.



앱에서 안전 설정 구성

Gemini API 제공업체를 클릭하여 이 페이지에서 제공업체별 콘텐츠와 코드를 확인합니다.

GenerativeModel 인스턴스를 초기화하는 과정에서 안전 설정을 구성합니다. 구성은 해당 모델 인스턴스의 전체 기간 동안 유지됩니다.

이 페이지 뒷부분에서 사용 가능한 유해 카테고리와 각 카테고리에 설정할 수 있는 기준점에 대해 알아보세요.

Swift

GenerativeModel 인스턴스를 만들 때 SafetySetting를 구성합니다.


import FirebaseAILogic

let safetySettings = [
  SafetySetting(harmCategory: .harassment, threshold: .blockOnlyHigh),
  SafetySetting(harmCategory: .hateSpeech, threshold: .blockMediumAndAbove)
]

// Specify the safety settings as part of creating the `GenerativeModel` instance.
let model = FirebaseAI.firebaseAI(backend: .googleAI()).generativeModel(
  modelName: "GEMINI_MODEL_NAME",
  safetySettings: safetySettings
)

// ...

Kotlin

GenerativeModel 인스턴스를 만들 때 SafetySetting를 구성합니다.


// ...

val safetySettings = listOf(
    SafetySetting(HarmCategory.HARASSMENT, HarmBlockThreshold.ONLY_HIGH),
    SafetySetting(HarmCategory.HATE_SPEECH, HarmBlockThreshold.MEDIUM_AND_ABOVE)
)

// Specify the safety settings as part of creating the `GenerativeModel` instance.
val model = Firebase.ai(backend = GenerativeBackend.googleAI()).generativeModel(
    modelName = "GEMINI_MODEL_NAME",
    safetySettings = safetySettings
)

// ...

Java

GenerativeModel 인스턴스를 만들 때 SafetySetting를 구성합니다.


// ...

List safetySettings = List.of(
    new SafetySetting(HarmCategory.HARASSMENT, HarmBlockThreshold.ONLY_HIGH),
    new SafetySetting(HarmCategory.HATE_SPEECH, HarmBlockThreshold.MEDIUM_AND_ABOVE)
);

// Specify the safety settings as part of creating the `GenerativeModel` instance.
GenerativeModelFutures model = GenerativeModelFutures.from(
    FirebaseAI.getInstance(GenerativeBackend.googleAI())
        .generativeModel(
            /* modelName */ "GEMINI_MODEL_NAME",
            /* generationConfig is optional */ null,
            safetySettings
        )
);

// ...

Web

GenerativeModel 인스턴스를 만들 때 SafetySetting를 구성합니다.


import { HarmBlockThreshold, HarmCategory, getAI, getGenerativeModel, GoogleAIBackend } from "firebase/ai";

// ...

const ai = getAI(firebaseApp, { backend: new GoogleAIBackend() });

const safetySettings = [
  {
    category: HarmCategory.HARM_CATEGORY_HARASSMENT,
    threshold: HarmBlockThreshold.BLOCK_ONLY_HIGH,
  },
  {
    category: HarmCategory.HARM_CATEGORY_HATE_SPEECH,
    threshold: HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE,
  },
];

// Specify the safety settings as part of creating the `GenerativeModel` instance.
const model = getGenerativeModel(ai, {
  model: "GEMINI_MODEL_NAME",
  safetySettings,
});

// ...

Dart

GenerativeModel 인스턴스를 만들 때 SafetySetting를 구성합니다.


import 'package:firebase_ai/firebase_ai.dart';

final safetySettings = [
  SafetySetting(HarmCategory.harassment, HarmBlockThreshold.high),
  SafetySetting(HarmCategory.hateSpeech, HarmBlockThreshold.medium),
];

// Specify the safety settings as part of creating the `GenerativeModel` instance.
final model = FirebaseAI.googleAI().generativeModel(
  model: 'GEMINI_MODEL_NAME',
  safetySettings: safetySettings,
);

// ...

Unity

GenerativeModel 인스턴스를 만들 때 SafetySetting를 구성합니다.


// ...

var safetySettings = new SafetySetting[] {
  new SafetySetting(HarmCategory.Harassment, SafetySetting.HarmBlockThreshold.OnlyHigh),
  new SafetySetting(HarmCategory.HateSpeech, SafetySetting.HarmBlockThreshold.MediumAndAbove)
};

// Specify the safety settings as part of creating the `GenerativeModel` instance.
var ai = FirebaseAI.GetInstance(FirebaseAI.Backend.GoogleAI());
var model = ai.GetGenerativeModel(
  modelName: "GEMINI_MODEL_NAME",
  safetySettings: safetySettings
);

// ...



사용 가능한 유해 카테고리

안전 필터는 다음 구성 가능한 유해 카테고리를 기준으로 프롬프트와 모델 응답을 평가합니다.

유해 카테고리 설명
HARM_CATEGORY_HARASSMENT 개인 또는 정체성을 대상으로 위협하거나 협박하거나 괴롭히거나 모욕하는 부정적인 댓글
HARM_CATEGORY_HATE_SPEECH 보호 대상 속성 (예: 인종, 민족, 종교, 장애, 연령, 국적, 군필 여부, 성적 지향, 성 정체성)을 근거로 개인이나 집단을 공격하거나, 비하하거나, 증오심을 조장하거나, 폭력을 선동하는 콘텐츠
HARM_CATEGORY_SEXUALLY_EXPLICIT 성행위, 포르노 또는 기타 외설적이고 선정적인 콘텐츠에 대한 언급이 포함되어 있습니다.
HARM_CATEGORY_DANGEROUS_CONTENT 유해한 행위, 불법 상품 및 서비스, 무기, 자해 또는 위험한 활동을 조장, 촉진, 장려하거나 이에 대한 지침을 제공합니다.
HARM_CATEGORY_CIVIC_INTEGRITY 유권자를 오도하거나 시민 및 선거 절차를 저해하는 데 사용될 수 있는 콘텐츠 (일부 모델 및 지역에서 지원됨)

구성 불가능한 안전 필터

구성 가능한 카테고리 외에도 모든 요청은 조정할 수 없는 시스템 수준 필터를 통과합니다.

  • 아동 성적 학대 콘텐츠 (CSAM) / 금지된 콘텐츠: 금지된 콘텐츠로 신고된 프롬프트 또는 대답은 즉시 차단됩니다(PROHIBITED_CONTENT).

  • 민감한 개인 식별 정보 (SPII): 민감한 개인 정보 (예: 금융 계좌 번호 또는 주민등록번호)를 노출할 위험이 있는 대답은 차단됩니다 (SPII).



기준점 설정

앱에서 제어하려는 각 유해 카테고리에 대해 기준을 설정해야 합니다. 평가된 콘텐츠가 이 기준점을 충족하거나 초과하면 콘텐츠가 차단됩니다.

안전 평가 작동 방식: 확률과 심각도

안전 필터는 다음 두 가지 측정기준으로 콘텐츠를 평가합니다.

  • 확률: 콘텐츠가 특정 유해성 카테고리에 속할 가능성에 대한 모델의 신뢰도입니다.

  • 심각도: 콘텐츠가 유해한 경우 잠재적인 피해의 규모 또는 정도입니다.

각 측정기준에는 NEGLIGIBLE, LOW, MEDIUM, HIGH 중 하나의 수준이 할당됩니다.

콘텐츠는 심각도 수준이 낮고 확률이 높을 수 있고(예: 가벼운 코미디 농담 또는 친근한 모욕) 심각도 수준이 높고 확률이 낮을 수 있습니다(예: 폭력을 언급하는 의학적 또는 역사적 토론).

사용 가능한 피해 차단 기준점

앱에서 제어하려는 유해 카테고리에 대해 다음 기준을 설정할 수 있습니다.

임곗값 설명 허용되는 수준
BLOCK_LOW_AND_ABOVE 가장 강력한 제한입니다.
확률 (또는 심각도)이 LOW, MEDIUM 또는 HIGH인 경우 콘텐츠를 차단합니다.
NEGLIGIBLE만 허용
BLOCK_MEDIUM_AND_ABOVE 보통 수준의 제한입니다.
가능성 (또는 심각도)이 MEDIUM 또는 HIGH인 경우 콘텐츠를 차단합니다.
NEGLIGIBLE 및 LOW 허용
BLOCK_ONLY_HIGH 가장 경미한 제한이 적용되는 활성 필터입니다.
가능성 (또는 심각도)이 HIGH인 경우에만 콘텐츠를 차단합니다.
NEGLIGIBLE, LOW, MEDIUM 허용
BLOCK_NONE 이 카테고리에서는 자동 응답 차단이 사용 중지되어 있습니다. 앱에서 맞춤 검토를 수행할 수 있도록 안전 등급 메타데이터는 계속 계산되어 응답과 함께 반환됩니다. 모든 콘텐츠 허용됨
OFF 이 카테고리의 안전 필터를 완전히 사용 중지합니다. 자동 차단이 발생하지 않으며 안전 등급 메타데이터가 반환되지 않습니다. 모든 콘텐츠 허용됨



안전 등급 검사 및 차단된 콘텐츠 처리

콘텐츠는 요청 중에 다음 두 단계에서 차단될 수 있습니다.

  1. 프롬프트 차단됨 (PromptFeedback): 모델이 출력을 생성하기 전에 입력 프롬프트가 안전 필터를 위반했습니다. 응답 후보가 반환되지 않습니다.

  2. 대답 후보 차단됨 (finishReason == SAFETY): 모델이 구성된 기준점을 초과하는 대답 후보를 평가하거나 생성했습니다. 생성된 후보 텍스트가 삭제되거나 수정됩니다.

SafetyRating 객체

평가된 모든 프롬프트 또는 대답 후보에는 SafetyRating 객체의 배열이 포함됩니다. 각 등급은 다음을 제공합니다.

  • Gemini Developer API 및 Agent Platform Gemini API (formerly Vertex AI) 모두에서 사용할 수 있는 속성:

    • category: 평가된 HarmCategory입니다.

    • probability: 불연속 평가(NEGLIGIBLE, LOW, MEDIUM 또는 HIGH)입니다.

    • blocked: 이 특정 등급으로 인해 콘텐츠가 차단된 경우 true입니다.

  • Agent Platform Gemini API (formerly Vertex AI)에서 사용할 수 있는 추가 속성:

    • probabilityScore: 0.0~1.0 사이의 부동 소수점 신뢰도 점수입니다.

    • severity: 개별 심각도 수준(NEGLIGIBLE, LOW, MEDIUM 또는 HIGH)입니다.

    • severityScore: 0.0~1.0 사이의 부동 소수점 심각도 점수입니다.

SafetyRating 객체 예시

다음 예시는 안전 필터에 의해 대답 후보가 차단된 경우의 원시 JSON 응답 페이로드를 보여줍니다.

{
  "candidates": [
    {
      "finishReason": "SAFETY",
      "safetyRatings": [
        {
          "category": "HARM_CATEGORY_HARASSMENT",
          "probability": "NEGLIGIBLE",
          "blocked": false
        },
        {
          "category": "HARM_CATEGORY_HATE_SPEECH",
          "probability": "NEGLIGIBLE",
          "blocked": false
        },
        {
          "category": "HARM_CATEGORY_SEXUALLY_EXPLICIT",
          "probability": "NEGLIGIBLE",
          "blocked": false
        },
        {
          "category": "HARM_CATEGORY_DANGEROUS_CONTENT",
          "probability": "HIGH",
          "blocked": true
        }
      ]
    }
  ],
  "usageMetadata": {
    "promptTokenCount": 24,
    "totalTokenCount": 24
  }
}

코드의 안전 오류 포착

콘텐츠가 차단되면 클라이언트 SDK는 차단을 예외 또는 오류 코드로 표시하므로 앱에서 이를 원활하게 처리할 수 있습니다.

Swift

GenerateContentError.promptBlocked 또는 GenerateContentError.responseStoppedEarly를 포착할 수 있습니다.

do {
  let response = try await model.generateContent("Your prompt here")
  print(response.text ?? "No text generated.")
} catch GenerateContentError.promptBlocked(let response) {
  // The input prompt was blocked
  if let feedback = response.promptFeedback {
    let reason = feedback.blockReason?.rawValue ?? "unknown"
    print("Prompt blocked for reason: \(reason)")
    for rating in feedback.safetyRatings {
      let cat = rating.category.rawValue
      let prob = rating.probability.rawValue
      print("Category: \(cat), probability: \(prob)")
    }
  }
} catch GenerateContentError.responseStoppedEarly(let reason, let response) {
  // Candidate response was blocked or stopped early
  if reason == .safety {
    print("Response blocked due to safety.")
    if let candidate = response.candidates.first {
      for rating in candidate.safetyRatings where rating.blocked {
        print("Blocked by category: \(rating.category.rawValue)")
      }
    }
  }
} catch {
  print("Unexpected error: \(error)")
}

Kotlin

PromptBlockedException를 포착하거나 candidate.finishReason를 검사할 수 있습니다.

try {
  val response = model.generateContent("Your prompt here")
  val candidate = response.candidates.firstOrNull()

  if (candidate?.finishReason == FinishReason.SAFETY) {
    val blockedRating =
      candidate.safetyRatings.firstOrNull { it.blocked }
    println("Response blocked by category: ${blockedRating?.category}")
  } else {
    println(response.text)
  }
} catch (e: PromptBlockedException) {
  val reason = e.response?.promptFeedback?.blockReason
  println("Prompt was blocked: $reason")
} catch (e: Exception) {
  println("Error generating content: ${e.message}")
}

Java

PromptBlockedException를 포착하거나 candidate.getFinishReason()를 검사할 수 있습니다.

try {
  GenerateContentResponse response = model.generateContent("Your prompt here").get();
  Candidate candidate = response.getCandidates().isEmpty() ? null : response.getCandidates().get(0);

  if (candidate != null && candidate.getFinishReason() == FinishReason.SAFETY) {
    SafetyRating blockedRating = null;
    for (SafetyRating rating : candidate.getSafetyRatings()) {
      if (Boolean.TRUE.equals(rating.getBlocked())) {
        blockedRating = rating;
        break;
      }
    }
    System.out.println("Response blocked by category: " +
        (blockedRating != null ? blockedRating.getCategory() : "unknown"));
  } else {
    System.out.println(response.getText());
  }
} catch (ExecutionException e) {
  if (e.getCause() instanceof PromptBlockedException) {
    PromptBlockedException pbe = (PromptBlockedException) e.getCause();
    GenerateContentResponse blockedResponse = pbe.getResponse();
    String reason = (blockedResponse != null && blockedResponse.getPromptFeedback() != null)
        ? String.valueOf(blockedResponse.getPromptFeedback().getBlockReason())
        : "unknown";
    System.out.println("Prompt was blocked: " + reason);
  } else {
    System.out.println("Error generating content: " + e.getMessage());
  }
} catch (InterruptedException e) {
  System.out.println("Generation was interrupted: " + e.getMessage());
}

Web

promptFeedback 및 candidate.finishReason를 검사할 수 있습니다.

try {
  const response = await model.generateContent("Your prompt here");

  // Check if the prompt was blocked
  if (response.promptFeedback?.blockReason) {
    console.warn(`Prompt blocked: ${response.promptFeedback.blockReason}`);
    return;
  }

  const candidate = response.candidates?.[0];
  if (candidate?.finishReason === "SAFETY") {
    const blockedRating = candidate.safetyRatings?.find((r) => r.blocked);
    console.warn(`Response blocked by category: ${blockedRating?.category}`);
  } else {
    console.log(response.text);
  }
} catch (error) {
  console.error("Error generating content:", error);
}

Dart

promptFeedback 및 candidate.finishReason를 검사할 수 있습니다.

try {
  final response = await model.generateContent([Content.text('Your prompt here')]);

  // Check if the prompt was blocked
  if (response.promptFeedback?.blockReason != null) {
    print('Prompt blocked: ${response.promptFeedback?.blockReason}');
    return;
  }

  final candidate = response.candidates.firstOrNull;
  if (candidate?.finishReason == FinishReason.safety) {
    final blockedRating =
        candidate?.safetyRatings?.where((r) => r.isBlocked == true).firstOrNull;
    print('Response blocked by category: ${blockedRating?.category.name}');
  } else {
    print(response.text);
  }
} catch (e) {
  print('Error generating content: $e');
}

Unity

PromptFeedback 및 candidate.FinishReason를 검사할 수 있습니다.

try {
  var response = await model.GenerateContentAsync("Your prompt here");

  // Check if the prompt was blocked
  if (response.PromptFeedback?.BlockReason != null) {
    Debug.LogWarning($"Prompt blocked: {response.PromptFeedback.BlockReason}");
    return;
  }

  var candidate = response.Candidates.FirstOrDefault();
  if (candidate?.FinishReason == FinishReason.Safety) {
    var blockedRating = candidate.SafetyRatings?.FirstOrDefault(r => r.Blocked);
    Debug.LogWarning($"Response blocked by category: {blockedRating?.Category}");
  } else {
    Debug.Log(response.Text);
  }
} catch (Exception ex) {
  Debug.LogError($"Error generating content: {ex.Message}");
}



책임감 있는 앱 디자인을 위한 권장사항

  • 심층 방어: 안전 필터는 가드레일이지 지침이 아닙니다. 안전 설정을 명시적인 시스템 요청 사항 및 타겟팅된 프롬프트 설계와 결합하여 어조와 범위를 안내합니다.

  • 원활한 사용자 피드백: 콘텐츠가 차단될 때 비정상 종료되거나 빈 화면이 표시되지 않습니다. finishReason == SAFETY 또는 PromptBlockedException를 감지하고 콘텐츠 가이드라인에 따라 요청을 처리할 수 없음을 사용자에게 알리는 친절한 메시지를 표시합니다.

  • 커스텀 검토에 BLOCK_NONE 사용: 이미 자체 클라이언트 측 또는 서버 측 검토 파이프라인이 있는 경우 임곗값을 BLOCK_NONE로 설정하여 자동 차단 없이 모델의 safetyRatings를 수신하고 앱에서 커스텀 검토 정책을 시행할 수 있습니다.

  • 서비스 약관 검토: 제한이 적은 설정(BLOCK_ONLY_HIGH 또는 BLOCK_NONE)을 사용하는 경우 앱이 Google의 금지된 사용 정책을 계속 준수하는지 확인합니다.

콘텐츠 생성을 제어하는 다른 옵션

  • 프롬프트 설계에 대해 자세히 알아보고 모델이 필요에 맞는 출력을 생성하도록 영향을 줄 수 있습니다.
  • 모델 파라미터를 구성하여 모델이 대답을 생성하는 방식(예: 최대 출력 토큰, 반복되는 출력 토큰의 확률 등)을 제어합니다.
  • 시스템 요청 사항을 설정하여 모델의 동작을 조정합니다. 이 기능은 모델이 최종 사용자의 추가 안내에 노출되기 전에 추가하는 서문과 같습니다.
  • 프롬프트와 함께 응답 스키마를 전달하여 특정 출력 스키마를 지정합니다. 이 기능은 JSON 출력을 생성할 때 흔히 사용되지만, 모델이 특정 라벨이나 태그를 사용하도록 하려는 경우와 같은 분류 작업에도 사용할 수 있습니다.