본문 바로가기
Artificial Intelligence/60. Python

[PYTHON] 강화학습 RL 환경 구축을 위한 Gymnasium 활용 방법과 2가지 핵심 기술적 차이 해결책

by Papa Martino V 2026. 4. 13.
728x90

Gymnasium 활용
Gymnasium 활용

1. 강화학습의 새로운 표준: OpenAI Gym에서 Gymnasium으로의 전환

강화학습(Reinforcement Learning, RL) 연구와 개발에서 환경(Environment)의 표준화는 매우 중요합니다. 수년간 업계 표준이었던 OpenAI Gym이 유지보수 종료 단계에 접어들면서, 커뮤니티 주도의 Gymnasium이 그 자리를 완벽하게 대체했습니다. Gymnasium은 기존의 API 호환성을 유지하면서도, 병렬 처리 성능 향상과 더 엄격한 타입 체크를 통해 실무 개발 환경에서의 안정성을 극대화했습니다. 본 포스팅에서는 단순한 라이브러리 소개를 넘어, Python을 활용해 복잡한 비즈니스 로직을 강화학습 환경으로 설계하는 도메인 특화 환경 구축 전략을 심도 있게 다룹니다. 특히 에이전트가 마주하는 상태 공간(Observation Space)과 행동 공간(Action Space)의 정밀한 설계 방법을 7가지 실전 Example을 통해 분석합니다.


2. 기존 Gym과 신규 Gymnasium의 API 설계 및 기능 차이 비교

기존의 레거시 코드를 Gymnasium으로 마이그레이션하거나 새로운 프로젝트를 시작할 때 반드시 알아야 할 구조적 차이점입니다.

비교 항목 OpenAI Gym (Legacy) Gymnasium (Standard)
Step 반환값 4개 (obs, reward, done, info) 5개 (obs, reward, terminated, truncated, info)
종료 조건 정의 done 하나로 통합 처리 목표 달성(Terminated)과 시간 초과(Truncated) 분리
렌더링 모드 불안정한 수동 설정 'render_mode' 인수를 통한 표준화된 관리
벡터화 환경 별도 패키지 의존성 높음 Native Async/Sync VectorEnv 지원 강화
타입 힌트 제한적임 강력한 Python Type Hinting 지원

3. Gymnasium 실전 응용 및 커스텀 환경 설계 Example 7선

개발자가 로컬 머신이나 클라우드 학습 서버에서 즉시 구동할 수 있는 Gymnasium 기반의 Python 실무 코드입니다.

Example 1: 표준 환경 로드 및 기본 루프 최적화 (v0.26+ 기준)

가장 기초적인 루프 구현이지만, Gymnasium의 'truncated' 파라미터를 정확히 처리하는 해결 방법입니다.

import gymnasium as gym

# 시각화를 위한 렌더링 모드 설정
env = gym.make("CartPole-v1", render_mode="human")
observation, info = env.reset(seed=42)

for _ in range(1000):
    action = env.action_space.sample()  # 무작위 행동 선택
    # Gymnasium의 새로운 5개 반환값 처리
    observation, reward, terminated, truncated, info = env.step(action)

    if terminated or truncated:
        observation, info = env.reset()

env.close()
        

Example 2: 커스텀 상태 공간(Box) 및 행동 공간(Discrete) 정의

실제 물류나 제조 공정의 수치를 강화학습 데이터 구조로 변환할 때 필수적인 클래스 설계입니다.

import numpy as np
from gymnasium import spaces

class MyCustomEnv(gym.Env):
    def __init__(self):
        super().__init__()
        # 행동 공간: 0(정지), 1(전진), 2(후진)
        self.action_space = spaces.Discrete(3)
        # 상태 공간: [온도, 압력] 형태의 연속값 (최소 0, 최대 100)
        self.observation_space = spaces.Box(low=0, high=100, shape=(2,), dtype=np.float32)

    def reset(self, seed=None, options=None):
        super().reset(seed=seed)
        return np.array([25.0, 1.0], dtype=np.float32), {}
        

Example 3: Wrapper를 활용한 보상 스케일링(Reward Scaling)

모델의 수렴 속도를 높이기 위해 환경 코드를 건드리지 않고 보상값만 가공하는 가속화 방법입니다.

class RewardRescale(gym.RewardWrapper):
    def __init__(self, env, factor):
        super().__init__(env)
        self.factor = factor

    def reward(self, reward):
        # 모든 보상에 특정 가중치를 곱해 경사 하강 최적화 지원
        return reward * self.factor

env = gym.make("MountainCar-v0")
env = RewardRescale(env, factor=0.1)
        

Example 4: 복합 데이터 구조를 위한 Dict 관찰 공간 설계

이미지 센서 데이터와 텍스트 로그 데이터가 공존하는 복잡한 시스템을 위한 해결책입니다.

self.observation_space = spaces.Dict({
    "visual": spaces.Box(low=0, high=255, shape=(64, 64, 3), dtype=np.uint8),
    "sensor": spaces.Box(low=-1, high=1, shape=(5,), dtype=np.float32),
    "status": spaces.Discrete(2)
})
        

Example 5: 병렬 학습을 위한 AsyncVectorEnv 구현

여러 개의 CPU 코어를 활용하여 동시에 수십 개의 환경을 실행, 학습 시간을 10배 이상 단축하는 방법입니다.

num_envs = 4
envs = gym.vector.AsyncVectorEnv([
    lambda: gym.make("LunarLander-v2") for _ in range(num_envs)
])

observations, infos = envs.reset()
# 4개의 환경에서 동시에 행동을 수행
actions = envs.action_space.sample()
observations, rewards, terminations, truncations, infos = envs.step(actions)
        

Example 6: ObservationWrapper를 이용한 그레이스케일 이미지 변환

비전 기반 RL에서 학습 연산량을 줄이기 위해 컬러 이미지를 흑백으로 전처리하는 파이썬 스크립트입니다.

import cv2

class GrayscaleObservation(gym.ObservationWrapper):
    def observation(self, obs):
        # RGB 이미지를 흑백으로 변환하여 차원 축소
        obs = cv2.cvtColor(obs, cv2.COLOR_RGB2GRAY)
        return np.expand_dims(obs, axis=-1)
        

Example 7: 정교한 시간 제한(TimeLimit) 수동 제어

무한 루프에 빠질 수 있는 환경에서 'truncated' 신호를 강제로 발생시켜 에이전트가 고착되지 않게 하는 해결 방법입니다.

def step(self, action):
    self.current_step += 1
    # ... 기존 로직 ...
    terminated = self.check_goal()
    # 500 스텝 초과 시 학습 중단이 아닌 에피소드 중단 신호 발생
    truncated = True if self.current_step >= 500 else False
    
    return obs, reward, terminated, truncated, {}
        

4. 성공적인 RL 환경 구축을 위한 3가지 도메인 설계 가이드

단순히 코드를 짜는 것보다 중요한 것은 보상(Reward)상태(State)의 공학적 설계입니다. 실무자가 자주 범하는 실수를 방지하는 가이드입니다.

  • Sparse Reward 문제 해결: 목표 도달 시에만 큰 보상을 주면 학습이 매우 어렵습니다. 목표에 근접할수록 점진적인 보상(Shaping Reward)을 주되, 에이전트가 보상만 챙기고 목표는 무시하는 'Reward Hacking'이 발생하지 않는지 감시하십시오.
  • Markov Property 준수: 현재의 '상태' 정보만으로 다음 행동을 결정할 수 있어야 합니다. 과거 데이터가 필요하다면 `Frame Stacking` 기법을 통해 이전 n개의 상태를 하나의 관찰값으로 묶어서 제공하십시오.
  • 시뮬레이션 속도 최적화: 환경의 `step` 함수 내에 무거운 연산이나 I/O 작업을 넣지 마십시오. RL은 수백만 번의 반복 학습이 필요하므로, 환경 코드는 극도로 최적화된 NumPy 연산 위주로 구성해야 합니다.

5. 결론: Gymnasium과 함께하는 지능형 시스템의 시작

강화학습은 정답이 없는 환경에서 최적의 전략을 찾아가는 여정입니다. Gymnasium은 그 여정을 시작하기 위한 가장 견고한 기반 시설(Infrastructure)입니다. 본 가이드에서 다룬 7가지 실무 예제와 설계 원칙을 적용한다면, 단순히 예제를 따라 하는 수준을 넘어 실제 비즈니스 문제를 해결하는 강력한 RL 에이전트를 개발할 수 있을 것입니다.

내용 출처

  • Gymnasium Documentation (Farama Foundation): "Basic Usage and API reference".
  • Sutton, R. S., & Barto, A. G. (2018). "Reinforcement Learning: An Introduction." MIT Press.
  • Farama Foundation Blog: "The transition from OpenAI Gym to Gymnasium".
  • DeepMind Research: "Standardizing Reinforcement Learning Environments".
728x90