

AWS Mainframe Modernization Service(관리형 런타임 환경 환경 환경)는 더 이상 신규 고객에게 공개되지 않습니다. AWS Mainframe Modernization Service(관리형 런타임 환경 환경)와 유사한 기능은 AWS Mainframe Modernization Service(자체 관리형 환경)를 참조하세요. 기존 고객은 정상적으로 서비스를 계속 이용할 수 있습니다. 자세한 내용은 [AWS Mainframe Modernization 가용성 변경을](https://docs.aws.amazon.com/m2/latest/userguide/mainframe-modernization-availability-change.html) 참조하세요.

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

# Gapwalk 애플리케이션에 대한 보안 구성
<a name="ba-runtime-security"></a>

다음 주제에서는 Gapwalk 애플리케이션을 보호하는 방법을 설명합니다.

메인프레임 프레임워크용 AWS 변환을 안전하게 사용할 수 있도록 올바른 구성을 제공하는 것은 사용자의 책임입니다.

모든 보안 관련 기능은 기본적으로 비활성화되어 있습니다. 인증(및 CSRF, XSS, CSP 등)을 활성화하려면 `gapwalk-application.security`를 `enabled`로 설정하고 `gapwalk-application.security.identity`를 `oauth`로 설정합니다.

**Topics**
+ [Gapwalk 애플리케이션에 대한 URI 접근성 구성](ba-runtime-filteringURIs.md)
+ [Gapwalk 애플리케이션에 대한 인증 구성](ba-runtime-auth.md)
+ [메인프레임 런타임의 AWS 변환에 대한 속도 제한 구성](ba-runtime-rate-limiting.md)

# Gapwalk 애플리케이션에 대한 URI 접근성 구성
<a name="ba-runtime-filteringURIs"></a>

이 주제에서는 Gapwalk 애플리케이션에 대한 URI 필터링을 구성하는 방법을 설명합니다. 이 기능에는 ID 제공업체(IdP)가 필요하지 않습니다.

URI 목록을 차단하려면 현대화된 애플리케이션의 `application-main.yml`에 다음 두 줄을 추가하여 *URI-1*, *URI-2* 등을 차단하려는 URIs로 바꿉니다.

```
gapwalk-application.security.filterURIs: enabled
gapwalk-application.security.blockedURIs: URI-1, URI-2, URI-3
```

# Gapwalk 애플리케이션에 대한 인증 구성
<a name="ba-runtime-auth"></a>

Gapwalk 애플리케이션에 대한 OAuth2 인증을 구성하려면 ID 제공업체(IdP)를 설정하고 애플리케이션과 통합해야 합니다. 이 안내서에서는 Amazon Cognito 또는 Keycloak을 IdP로 사용하는 단계를 다룹니다. Amazon Cognito 를 사용하면 Cognito 사용자 풀 세부 정보로 애플리케이션의 구성 파일을 업데이트할 수 있습니다. Keycloak을 사용하면 사용자의 할당된 역할에 따라 애플리케이션의 API 및 리소스에 대한 액세스를 제어할 수 있습니다.

**Topics**
+ [Amazon Cognito를 사용한 Gapwalk OAuth2 인증 구성](ba-runtime-auth-cognito.md)
+ [Keycloak을 사용하여 Gapwalk OAuth2 인증 구성](ba-runtime-auth-keycloak.md)

# Amazon Cognito를 사용한 Gapwalk OAuth2 인증 구성
<a name="ba-runtime-auth-cognito"></a>

이 섹션에서는 Amazon Cognito를 ID 제공업체(idP)로 사용하여 Gapwalk 애플리케이션에 대한 OAuth2 인증을 구성하는 방법에 대해 설명합니다.

## 사전 조건
<a name="ba-runtime-auth-cognito-prereq"></a>

이 자습서에서는 Amazon Cognito를 IdP로 사용하고 PlanetDemo를 현대화된 프로젝트로 사용합니다.

다른 모든 외부 ID 공급자를 사용할 수 있습니다. ClientRegistration 정보는 IdP에서 가져와야 하며 Gapwalk 인증에 필요합니다. 자세한 정보는 [Amazon Cognito 개발자 안내서](https://docs.aws.amazon.com/cognito/latest/developerguide/)를 참조하세요.

**ClientRegistration 정보:**

client-id  
ClientRegistration의 ID. 이 예제에서는 PlanetsDemo가 됩니다.

client-secret  
클라이언트 암호.

인증 엔드포인트  
인증 서버의 인증 엔드포인트 URI입니다.

토큰 엔드포인트  
권한 부여 서버의 토큰 엔드포인트 URI.

jwks 엔드포인트  
권한 부여 서버에서 발급한 JSON 웹 서명의 유효성을 검사하기 위한 키가 포함된 JSON 웹 키(JWK)를 가져오는 데 사용되는 URI입니다.

리디렉션 URI  
액세스 권한이 부여된 경우 권한 부여 서버가 최종 사용자를 리디렉션하는 URI입니다.

## Amazon Cognito 설정
<a name="cog-setup"></a>

먼저 배포된 Gapwalk 애플리케이션과 함께 테스트 목적으로 사용할 Amazon Cognito 사용자 풀과 사용자를 생성하고 구성합니다.

**참고**  
다른 IdP를 사용할 경우 이 단계를 건너뛸 수 있습니다.

**사용자 풀 생성**

1. 에서 Amazon Cognito로 이동하여 자격 AWS 증명을 사용하여 AWS Management Console 인증합니다.

1. **사용자 풀(User Pools)**을 선택합니다.

1. **사용자 풀 생성**을 선택합니다.

1. **로그인 환경 구성에서** **Cognito 사용자** 풀 기본 공급자 유형을 유지합니다. **Cognito 사용자 풀 로그인 옵션**을 하나 또는 여러 개 선택할 수 있습니다. 지금은 **사용자 이름을** 선택한 후 **다음**을 선택합니다.  
![\[alt_text\]](http://docs.aws.amazon.com/ko_kr/m2/latest/userguide/images/cog-auth-provider.png)

1. **보안 요구 사항 구성**에서 기본값을 유지하고 **MFA 없음**을 선택하여 **다단계 인증**을 비활성화하고 **다음**을 선택합니다.  
![\[alt_text\]](http://docs.aws.amazon.com/ko_kr/m2/latest/userguide/images/cog-sec-requirements.png)

1. 보안 조치로 **셀프 등록 사용**을 비활성화하고 **다음**을 선택합니다.  
![\[alt_text\]](http://docs.aws.amazon.com/ko_kr/m2/latest/userguide/images/cog-config-sign-up.png)

1. **Cognito를 사용하여 이메일 전송**을 선택한 다음 **다음**을 선택합니다.  
![\[alt_text\]](http://docs.aws.amazon.com/ko_kr/m2/latest/userguide/images/cog-email.png)

1. **앱 통합**에서 사용자 풀의 이름을 선택합니다. **호스팅된 인증 페이지**에서 **Cognito 호스팅 UI 사용**을 선택합니다.  
![\[alt_text\]](http://docs.aws.amazon.com/ko_kr/m2/latest/userguide/images/cog-domain.png)

1. 단순화를 위해 **도메인**에서 **Cognito 도메인 사용**을 선택하고 도메인 접두사를 입력합니다(예: `https://planetsdemo`). 데모 앱을 클라이언트로 추가해야 합니다.

   1. **초기 앱 클라이언트**에서 **기밀 클라이언트**를 선택합니다. 앱 클라이언트 이름(예: **planetsdemo**)을 입력하고 **클라이언트 보안 암호 생성**을 선택합니다.

   1. **허용된 콜백 URL**에 인증 후 사용자를 리디렉션할 URL을 입력합니다. URL은 `/login/oauth2/code/cognito`로 끝나야 합니다. 예를 들어 애플리케이션 및 백엔드 Gapwalk 및 BAC 애플리케이션의 경우:

      ```
      http://localhost:8080/bac
            http://localhost:8080/bac/login/oauth2/code/cognito
            http://localhost:8080/gapwalk-application
            http://localhost:8080/gapwalk-application/login/oauth2/code/cognito
            http://localhost:8080/planetsdemo
            http://localhost:8080/planetsdemo/login/oauth2/code/cognito
      ```

      나중에 URL을 편집할 수 있습니다.  
![\[alt_text\]](http://docs.aws.amazon.com/ko_kr/m2/latest/userguide/images/cog-urls.png)

   1. **허용된 로그아웃 URL**에 애플리케이션이 사용자를 로그아웃할 때 Amazon Cognito가 리디렉션할 로그아웃 페이지의 URL을 입력합니다. 예를 들어 백엔드 Gapwalk 및 BAC 애플리케이션의 경우:

      ```
      http://localhost:8080/bac/logout
      http://localhost:8080/gapwalk-application/logout
      http://localhost:8080/planetsdemo/logout
      ```

      나중에 URL을 편집할 수 있습니다.

   1. **고급 앱 클라이언트 설정** 및 **속성 읽기 및 쓰기 권한** 섹션의 기본값을 유지하세요.

   1. **다음**을 선택합니다.

1. **검토 및 생성**에서 선택 사항을 확인한 다음 **사용자 풀 생성**을 선택합니다.

자세한 내용은 [사용자 풀 생성](https://docs.aws.amazon.com/cognito/latest/developerguide/tutorial-create-user-pool.html)을 참조하세요.

**사용자 생성**

자체 등록이 비활성화되었으므로 Amazon Cognito 사용자를 만듭니다. AWS Management Console에서 Amazon Cognito 콘솔로 이동합니다. 만든 사용자 풀을 선택한 다음 **사용자**에서 **사용자 생성**을 선택합니다.

**사용자 정보**에서 **이메일 초대 보내기**를 선택하고 사용자 이름과 이메일 주소를 입력한 다음 **비밀번호 생성**을 선택합니다. **사용자 생성**을 선택합니다.

**역할 생성**

**그룹** 탭에서 3개의 그룹(SUPER\$1ADMIN, ADMIN 및 USER)을 생성하고 사용자를 이러한 그룹 중 하나 이상에 연결합니다. 이러한 역할은 나중에 Gapwalk 애플리케이션에서 ROLE\$1SUPER\$1ADMIN, ROLE\$1ADMIN 및 ROLE\$1USER에 매핑되어 일부 제한된 API REST 직접 호출에 액세스할 수 있도록 합니다.

애플리케이션은 여러 OAuth2 자격 증명 공급자와 함께 작동하는 계층적 scope-to-role 매핑을 구현합니다. Cognito에서 발급한 JWT 토큰을 리소스 서버 권한 부여에 사용하는 경우 토큰에 정의된 범위가 해당 역할에 자동으로 매핑됩니다.

## Gapwalk 애플리케이션에 Amazon Cognito 통합
<a name="integrate-cognito"></a>

이제 Amazon Cognito 사용자 풀과 사용자가 준비되었으므로 현대화된 애플리케이션의 `application-main.yml` 파일로 이동하여 다음 코드를 추가합니다.

```
gapwalk-application.security: enabled
gapwalk-application.security.identity: oauth
gapwalk-application.security.issuerUri: https://cognito-idp.<region-id>.amazonaws.com/<pool-id>
gapwalk-application.security.domainName: <your-cognito-domain>

spring:
  security:
    oauth2:
      client:
        registration:
          cognito:
            client-id: <client-id>
            client-name: <client-name>
            client-secret: <client-secret>
            provider: cognito
            authorization-grant-type: authorization_code
            scope: openid
            redirect-uri: "<redirect-uri>"
        provider:
          cognito:
            issuer-uri: ${gapwalk-application.security.issuerUri}
            authorization-uri: ${gapwalk-application.security.domainName}/oauth2/authorize
            jwk-set-uri: ${gapwalk-application.security.issuerUri}/.well-known/jwks.json
            token-uri: ${gapwalk-application.security.domainName}/oauth2/token
            user-name-attribute: username
      resourceserver:
        jwt:
          jwk-set-uri: ${gapwalk-application.security.issuerUri}/.well-known/jwks.json
```

다음과 같이 자리 표시자를 바꿉니다.

1. 에서 Amazon Cognito로 이동하여 자격 AWS 증명을 사용하여 AWS Management Console 인증합니다.

1. **사용자 풀**을 선택하고 생성한 사용자 풀을 선택합니다. **사용자 풀 ID**에서 *pool-id*를 찾을 수 있습니다.

1. *your-cognito-domain*을 찾을 수 있는 **앱 통합**을 선택하고 **앱 클라이언트 및 분석**으로 이동하여 앱을 선택하세요.

1. **앱 클라이언트: yourApp**에서 *client-name*, *client-id* 및 *client-secret*(**클라이언트 보안 암호 표시**)을 찾을 수 있습니다.

1. *region-id*는 Amazon Cognito 사용자 및 사용자 풀을 생성한 AWS 리전 ID에 해당합니다. 예시: `eu-west-3`.

1. *redirect-uri*에 **허용된 콜백 URL**에 대해 지정한 URI를 입력합니다. 이 예제에서는 `http://localhost:8080/planetsdemo/login/oauth2/code/cognito`입니다.

지금 Gapwalk 애플리케이션을 배포하고 이전에 생성한 사용자를 사용하여 앱에 로그인할 수 있습니다.

# Keycloak을 사용하여 Gapwalk OAuth2 인증 구성
<a name="ba-runtime-auth-keycloak"></a>

이 주제에서는 Keycloak을 ID 제공업체(IdP)로 사용하여 Gapwalk 애플리케이션에 대한 OAuth2 인증을 구성하는 방법에 대해 설명합니다. 이 자습서에서는 Keycloak 24.0.0을 사용합니다.

## 사전 조건
<a name="ba-runtime-auth-keycloak-prereq"></a>
+ [Keycloak](https://www.keycloak.org/)
+ Gapwalk 애플리케이션

## Keycloak 설정
<a name="keycloak-setup"></a>

1. 웹 브라우저에서 Keycloak 대시보드로 이동합니다. 기본 자격 증명은 admin/admin입니다. 왼쪽 상단 탐색 모음으로 이동하여 다음 이미지와 같이 **demo** 이름으로 영역을 생성합니다.  
![\[alt_text\]](http://docs.aws.amazon.com/ko_kr/m2/latest/userguide/images/ba-runtime-auth-keycloak_2.png)

1. **app-demo**라는 폴더를 생성합니다.  
![\[User interface for creating a new client in an authentication management system.\]](http://docs.aws.amazon.com/ko_kr/m2/latest/userguide/images/ba-runtime-auth-keycloak_3.jpg)

   `localhost:8080`을 Gapwalk 애플리케이션의 주소로 바꿉니다.  
![\[alt_text\]](http://docs.aws.amazon.com/ko_kr/m2/latest/userguide/images/ba-runtime-auth-keycloak_4.png)  
![\[alt_text\]](http://docs.aws.amazon.com/ko_kr/m2/latest/userguide/images/ba-runtime-auth-keycloak_5.png)

1. 클라이언트 보안 암호를 가져오려면 **클라이언트**, **app-demo**, **자격 증명**을 차례로 선택합니다.  
![\[alt_text\]](http://docs.aws.amazon.com/ko_kr/m2/latest/userguide/images/ba-runtime-auth-keycloak_6.jpg)

1. **클라이언트**, **클라이언트 범위**, **사전 정의된 매퍼 추가**를 차례로 선택합니다. **영역 역할**을 선택합니다.  
![\[alt_text\]](http://docs.aws.amazon.com/ko_kr/m2/latest/userguide/images/ba-runtime-auth-keycloak_7.jpg)

1. 다음 이미지에 표시된 구성으로 영역 역할을 편집합니다.  
![\[alt_text\]](http://docs.aws.amazon.com/ko_kr/m2/latest/userguide/images/ba-runtime-auth-keycloak_8.jpg)

1. 정의된 **토큰 클레임 이름**을 기억하세요. `gapwalk-application.security.claimGroupName` 속성에 대한 Gapwalk 설정 정의에 이 값이 필요합니다.  
![\[alt_text\]](http://docs.aws.amazon.com/ko_kr/m2/latest/userguide/images/ba-runtime-auth-keycloak_9.jpg)

1. **영역 역할**을 선택하고, **SUPER\$1ADMIN**, **ADMIN** 및 **USER**의 세 가지 역할을 생성합니다. 이러한 역할은 나중에 Gapwalk 애플리케이션에 의해 `ROLE_SUPER_ADMIN`, `ROLE_ADMIN` 및 `ROLE_USER`에 매핑되어 일부 제한된 API REST 직접 호출에 액세스할 수 있습니다.  
![\[alt_text\]](http://docs.aws.amazon.com/ko_kr/m2/latest/userguide/images/ba-runtime-auth-keycloak_10.jpg)

## Keycloak을 Gapwalk 애플리케이션에 통합
<a name="gapwalk-setup"></a>

다음과 같이 `application-main.yml`을 편집합니다.

```
gapwalk-application.security: enabled
gapwalk-application.security.identity: oauth
gapwalk-application.security.issuerUri: http://<KEYCLOAK_SERVER_HOSTNAME>/realms/<YOUR_REALM_NAME>
gapwalk-application.security.claimGroupName: "keycloak:groups"

gapwalk-application.security.userAttributeName: "preferred_username"
# Use "username" for cognito, 
#     "preferred_username" for keycloak
#      or any other string

spring:
  security:
    oauth2:
      client:
        registration:
          demo:
            client-id: <YOUR_CLIENT_ID>
            client-name: Demo App
            client-secret: <YOUR_CLIENT_SECRET>
            provider: keycloak
            authorization-grant-type: authorization_code
            scope: openid
            redirect-uri: "{baseUrl}/login/oauth2/code/{registrationId}"
        provider:
          keycloak:
            issuer-uri: ${gapwalk-application.security.issuerUri}
            authorization-uri: ${gapwalk-application.security.issuerUri}/protocol/openid-connect/auth
            jwk-set-uri: ${gapwalk-application.security.issuerUri}/protocol/openid-connect/certs
            token-uri: ${gapwalk-application.security.issuerUri}/protocol/openid-connect/token
            user-name-attribute: ${gapwalk-application.security.userAttributeName}
      resourceserver:
        jwt:
          jwk-set-uri: ${gapwalk-application.security.issuerUri}/protocol/openid-connect/certs
```

*<KEYCLOAK\$1SERVER\$1HOSTNAME>*, *<YOUR\$1REALM\$1NAME>*, *<YOUR\$1CLIENT\$1ID>* 및 *<YOUR\$1CLIENT\$1SECRET>*을 Keycloak 서버 호스트 이름, 영역 이름, 클라이언트 ID 및 클라이언트 보안 암호로 바꿉니다.

# 메인프레임 런타임의 AWS 변환에 대한 속도 제한 구성
<a name="ba-runtime-rate-limiting"></a>

AWS 메인프레임 런타임을 위한 변환에는 과도한 요청 및 잠재적 남용으로부터 gapwalk 애플리케이션을 보호하는 기본 제공 속도 제한 기능이 포함되어 있습니다. 속도 제한 시스템은 토큰 버킷 알고리즘을 사용하여 버스트 용량과 지속적인 속도 제한을 모두 제공합니다.

**Topics**
+ [속도 제한 개요](#ba-runtime-rate-limiting-overview)
+ [구성 속성](#ba-runtime-rate-limiting-config)
+ [속도 제한 활성화](#ba-runtime-rate-limiting-enable)
+ [클라이언트 식별](#ba-runtime-rate-limiting-client-id)
+ [속도 제한 헤더](#ba-runtime-rate-limiting-headers)
+ [메모리 관리](#ba-runtime-rate-limiting-memory)

## 속도 제한 개요
<a name="ba-runtime-rate-limiting-overview"></a>

속도 제한 시스템은 다음과 같은 기능을 제공합니다.

**토큰 버킷 알고리즘**  
+ 구성된 버스트 용량까지의 버스트 트래픽 허용
+ 분당 요청에 따라 일정한 속도로 토큰을 다시 채웁니다.
+ 합법적인 트래픽 급증을 차단하지 않고 원활한 속도 제한 제공

**클라이언트 식별**  
+ 프록시 지원을 통해 IP 주소로 클라이언트 식별
+ X-Forwarded-For 및 X-Real-IP 헤더 지원
+ 로드 밸런서 및 역방향 프록시 시나리오 처리

**자동 메모리 관리**  
+ 만료된 속도 제한 버킷을 자동으로 정리합니다.
+ 구성 가능한 정리 간격 및 만료 시간
+ 장기 실행 애플리케이션에서 메모리 누수 방지

**HTTP 통합**  
+ 한도를 초과하면 HTTP 429(요청이 너무 많음)를 반환합니다.
+ 응답에 표준 속도 제한 헤더 포함
+ 클라이언트에 대한 재시도 후 정보 제공

## 구성 속성
<a name="ba-runtime-rate-limiting-config"></a>

`application-main.yaml` 파일에서 속도 제한을 구성합니다.

```
gapwalk:
  ratelimiting:
    enabled: true                                        # Enable/disable rate limiting
    requestsPerMinute: 1000                              # Sustained rate limit per minute
    burstCapacity: 1500                                  # Maximum burst requests allowed
    includeHeaders: true                                 # Include X-RateLimit-* headers
    cleanupIntervalMinutes: 5                            # Cleanup interval for expired buckets
    bucketExpiryHours: 1                                 # Hours after which unused buckets expire
    errorMessage: "Too many requests. Try again later."  # Custom error message
    whitelistIps: ""                                     # Comma-separated IPs to bypass limiting
    perEndpointLimiting: false                           # Apply limits per endpoint (not implemented)
```

### 속성 설명
<a name="ba-runtime-rate-limiting-config-properties"></a>

**enabled**  
속도 제한 기능을 활성화 또는 비활성화하는 마스터 스위치입니다. 기본값: `false`

**requestsPerMinute**  
지속적인 속도 제한을 위해 분당 허용되는 요청 수입니다. 토큰 리필 속도를 나타냅니다. 기본값: `1000`

**burstCapacity**  
속도 제한이 적용되기 전에 버스트에 허용되는 최대 요청 수입니다. 트래픽 급증을 허용`requestsPerMinute`하려면 보다 높아야 합니다. 기본값: `1500`

**includeHeaders**  
HTTP 응답에 표준 속도 제한 헤더(`X-RateLimit-Limit`, `X-RateLimit-Remaining`, `X-RateLimit-Reset`)를 포함할지 여부입니다. 기본값: `true`

**cleanupIntervalMinutes**  
만료된 속도 제한 버킷의 자동 정리 간격. 메모리 누수를 방지하는 데 도움이 됩니다. 기본값: `5`

**bucketExpiryHours**  
미사용 비율 제한 버킷이 만료되어 정리할 수 있는 것으로 간주되는 시간입니다. 기본값: `1`

**errorMessage**  
속도 제한을 초과할 때 JSON 응답에 반환되는 사용자 지정 오류 메시지입니다. 기본값: `"Too many requests. Try again later."`

**whitelistIps**  
속도 제한을 완전히 우회하는 IP 주소의 쉼표로 구분된 목록입니다. 상태 확인 또는 신뢰할 수 있는 시스템에 유용합니다. 기본값: `empty`

**perEndpointLimiting**  
클라이언트당 대신 엔드포인트당 별도의 속도 제한을 적용할지 여부입니다. 현재 구현되지 않았습니다. 기본값: `false`

## 속도 제한 활성화
<a name="ba-runtime-rate-limiting-enable"></a>

기본 설정으로 속도 제한을 활성화하려면:

```
gapwalk:
  ratelimiting:
    enabled: true
```

## 클라이언트 식별
<a name="ba-runtime-rate-limiting-client-id"></a>

속도 제한 시스템은 다음 우선 순위에 따라 클라이언트를 식별합니다.

1. **X-Forwarded-For 헤더**(쉼표로 구분된 경우 첫 번째 IP)

1. **X-Real-IP 헤더**

1. HTTP 요청의 **원격 주소** 

이렇게 하면 애플리케이션이 뒤처질 때 적절한 클라이언트 식별이 보장됩니다.
+ 로드 밸런서
+ 역방향 프록시
+ CDNs
+ API 게이트웨이

### 클라이언트 식별 예제
<a name="ba-runtime-rate-limiting-client-id-example"></a>

```
# Direct connection
Client IP: 192.168.1.100

# Behind load balancer with X-Forwarded-For
X-Forwarded-For: 203.0.113.45, 192.168.1.100
Client IP: 203.0.113.45 (first IP used)

# Behind reverse proxy with X-Real-IP
X-Real-IP: 203.0.113.45
Client IP: 203.0.113.45
```

## 속도 제한 헤더
<a name="ba-runtime-rate-limiting-headers"></a>

`includeHeaders`이 활성화되면 HTTP 응답에 다음 헤더가 추가됩니다.

**X-RateLimit-Limit**  
클라이언트의 속도 제한 상한(분당 요청 수)

**X-RateLimit-Remaining**  
현재 속도 제한 창에 남아 있는 요청 수

**X-RateLimit-Reset**  
속도 제한 기간이 재설정되는 시간(Unix 타임스탬프)

### 응답 헤더 예제
<a name="ba-runtime-rate-limiting-headers-example"></a>

```
X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 847
X-RateLimit-Reset: 1640995200
```

### 속도 제한 초과 응답
<a name="ba-runtime-rate-limiting-headers-exceeded"></a>

속도 제한을 초과하면 시스템이 다음을 반환합니다.

**HTTP 상태**  
429 요청이 너무 많음

**Content-Type**  
application/json

**이후 재시도**  
재시도하기 전에 대기할 초 수

```
{
  "error": "Rate limit exceeded",
  "message": "Too many requests. Try again later.",
  "retryAfter": 60,
  "timestamp": 1640995140000
}
```

## 메모리 관리
<a name="ba-runtime-rate-limiting-memory"></a>

속도 제한 시스템은 메모리를 자동으로 관리하여 장기 실행 애플리케이션의 누수를 방지합니다.

**자동 정리**  
+ `cleanupIntervalMinutes` 분마다 실행
+ `bucketExpiryHours` 시간 동안 사용되지 않은 버킷을 제거합니다.
+ 모니터링을 위한 정리 활동을 로깅합니다.

**메모리 효율성**  
+ 스레드 안전을 위해 동시 데이터 구조 사용
+ 지연 버킷 생성(필요한 경우에만)
+ 효율적인 토큰 버킷 구현

### 정리 활동 모니터링
<a name="ba-runtime-rate-limiting-memory-monitoring"></a>

로그에서 정리 메시지를 확인합니다.

```
INFO  RateLimitingService - Cleaned up 15 expired rate limiting buckets
```