6장: 고급 기능

Rust의 고급 기능들을 마스터하면 더 유연하고 재사용 가능한 코드를 작성할 수 있습니다. 이 장에서는 제네릭, 트레이트, 스마트 포인터, 클로저, 이터레이터 등을 심도 있게 다룹니다.

6.1 제네릭 (Generics) - 타입의 추상화

제네릭을 사용하면 여러 타입에서 작동하는 코드를 한 번만 작성할 수 있습니다. 코드 중복을 줄이고 타입 안전성을 유지합니다.

제네릭 함수

// 제네릭 없이 - 코드 중복
fn largest_i32(list: &[i32]) -> &i32 {
    let mut largest = &list[0];
    for item in list {
        if item > largest {
            largest = item;
        }
    }
    largest
}

fn largest_char(list: &[char]) -> &char {
    let mut largest = &list[0];
    for item in list {
        if item > largest {
            largest = item;
        }
    }
    largest
}

// 제네릭 사용 - 한 번만 작성
fn largest<T: PartialOrd>(list: &[T]) -> &T {
    let mut largest = &list[0];
    for item in list {
        if item > largest {
            largest = item;
        }
    }
    largest
}

fn main() {
    let numbers = vec![34, 50, 25, 100, 65];
    let result = largest(&numbers);
    println!("가장 큰 수: {}", result);

    let chars = vec!['y', 'm', 'a', 'q'];
    let result = largest(&chars);
    println!("가장 큰 문자: {}", result);
}

제네릭 구조체

// 하나의 타입 매개변수
struct Point<T> {
    x: T,
    y: T,
}

impl<T> Point<T> {
    fn x(&self) -> &T {
        &self.x
    }
}

fn main() {
    let integer = Point { x: 5, y: 10 };
    let float = Point { x: 1.0, y: 4.0 };

    // let wont_work = Point { x: 5, y: 4.0 }; // 에러! 타입이 달라야 함
}

// 여러 타입 매개변수
struct Point2D<T, U> {
    x: T,
    y: U,
}

fn main() {
    let both_integer = Point2D { x: 5, y: 10 };
    let both_float = Point2D { x: 1.0, y: 4.0 };
    let integer_and_float = Point2D { x: 5, y: 4.0 }; // OK!
}

제네릭 열거형

// Option과 Result는 제네릭 열거형
enum Option<T> {
    Some(T),
    None,
}

enum Result<T, E> {
    Ok(T),
    Err(E),
}

// 커스텀 제네릭 열거형
enum Data<T> {
    Single(T),
    Multiple(Vec<T>),
    None,
}

fn main() {
    let single = Data::Single(42);
    let multiple = Data::Multiple(vec![1, 2, 3]);
    let none: Data<i32> = Data::None;
}

메서드에서 제네릭

struct Point<T> {
    x: T,
    y: T,
}

impl<T> Point<T> {
    fn new(x: T, y: T) -> Self {
        Point { x, y }
    }
}

// 특정 타입에만 메서드 구현
impl Point<f32> {
    fn distance_from_origin(&self) -> f32 {
        (self.x.powi(2) + self.y.powi(2)).sqrt()
    }
}

fn main() {
    let p1 = Point::new(5, 10);
    let p2 = Point::new(1.0, 4.0);

    // p1.distance_from_origin(); // 에러! i32 타입에는 이 메서드 없음
    println!("거리: {}", p2.distance_from_origin()); // OK!
}
제네릭 성능

Rust는 컴파일 시 단형화(monomorphization)를 수행합니다. 제네릭 코드를 사용하는 각 구체 타입에 대해 별도의 코드를 생성하므로, 제네릭 사용에 런타임 비용이 없습니다!

6.2 트레이트 (Traits) - 공유 동작 정의

트레이트는 특정 타입이 가지고 있는 기능을 다른 타입과 공유할 수 있게 해줍니다. 다른 언어의 인터페이스와 비슷하지만 더 강력합니다.

트레이트 정의와 구현

pub trait Summary {
    fn summarize(&self) -> String;
}

pub struct NewsArticle {
    pub headline: String,
    pub location: String,
    pub author: String,
    pub content: String,
}

impl Summary for NewsArticle {
    fn summarize(&self) -> String {
        format!("{}, by {} ({})", self.headline, self.author, self.location)
    }
}

pub struct Tweet {
    pub username: String,
    pub content: String,
    pub reply: bool,
    pub retweet: bool,
}

impl Summary for Tweet {
    fn summarize(&self) -> String {
        format!("{}: {}", self.username, self.content)
    }
}

fn main() {
    let article = NewsArticle {
        headline: String::from("Rust 1.0 출시!"),
        location: String::from("서울"),
        author: String::from("김러스트"),
        content: String::from("안전하고 빠른 시스템 프로그래밍 언어..."),
    };

    let tweet = Tweet {
        username: String::from("@rustacean"),
        content: String::from("Rust 배우는 중! #rust"),
        reply: false,
        retweet: false,
    };

    println!("기사: {}", article.summarize());
    println!("트윗: {}", tweet.summarize());
}

기본 구현

pub trait Summary {
    fn summarize_author(&self) -> String;

    // 기본 구현
    fn summarize(&self) -> String {
        format!("({}님의 글 더 읽기...)", self.summarize_author())
    }
}

impl Summary for Tweet {
    fn summarize_author(&self) -> String {
        format!("@{}", self.username)
    }
    // summarize는 기본 구현 사용
}

fn main() {
    let tweet = Tweet {
        username: String::from("rustacean"),
        content: String::from("물론 Rust는 최고!"),
        reply: false,
        retweet: false,
    };

    println!("1개의 새 트윗: {}", tweet.summarize());
}

트레이트 바운드

제네릭 타입이 특정 트레이트를 구현하도록 제한합니다.

// 트레이트 바운드 - 긴 형식
pub fn notify<T: Summary>(item: &T) {
    println!("속보! {}", item.summarize());
}

// impl Trait 문법 - 짧은 형식
pub fn notify(item: &impl Summary) {
    println!("속보! {}", item.summarize());
}

// 여러 트레이트 바운드
pub fn notify<T: Summary + Display>(item: &T) {
    // T는 Summary와 Display 모두 구현해야 함
}

// where 절 - 복잡한 경우 더 읽기 쉬움
fn some_function<T, U>(t: &T, u: &U) -> i32
where
    T: Display + Clone,
    U: Clone + Debug,
{
    // ...
}

트레이트를 반환하기

// impl Trait을 반환 타입으로 사용
fn returns_summarizable() -> impl Summary {
    Tweet {
        username: String::from("rustacean"),
        content: String::from("Rust는 훌륭해!"),
        reply: false,
        retweet: false,
    }
}

// 주의: 여러 타입을 반환할 수 없음
// fn returns_summarizable(switch: bool) -> impl Summary {
//     if switch {
//         NewsArticle { ... }  // 에러!
//     } else {
//         Tweet { ... }
//     }
// }

조건부 메서드 구현

use std::fmt::Display;

struct Pair<T> {
    x: T,
    y: T,
}

impl<T> Pair<T> {
    fn new(x: T, y: T) -> Self {
        Self { x, y }
    }
}

// Display를 구현한 타입에만 cmp_display 메서드 제공
impl<T: Display + PartialOrd> Pair<T> {
    fn cmp_display(&self) {
        if self.x >= self.y {
            println!("가장 큰 멤버는 x = {}", self.x);
        } else {
            println!("가장 큰 멤버는 y = {}", self.y);
        }
    }
}
표준 라이브러리 트레이트

6.3 스마트 포인터

스마트 포인터는 포인터처럼 동작하지만 추가 메타데이터와 기능을 가진 데이터 구조입니다.

Box<T> - 힙 할당

fn main() {
    // 값을 힙에 저장
    let b = Box::new(5);
    println!("b = {}", b);

    // 재귀 타입 정의에 필수
    enum List {
        Cons(i32, Box<List>),
        Nil,
    }

    use List::{Cons, Nil};

    let list = Cons(1,
        Box::new(Cons(2,
            Box::new(Cons(3,
                Box::new(Nil))))));
}

Rc<T> - 참조 카운팅

여러 소유자가 하나의 데이터를 공유할 때 사용합니다.

use std::rc::Rc;

enum List {
    Cons(i32, Rc<List>),
    Nil,
}

use List::{Cons, Nil};

fn main() {
    let a = Rc::new(Cons(5, Rc::new(Cons(10, Rc::new(Nil)))));
    println!("a 생성 후 카운트 = {}", Rc::strong_count(&a));

    let b = Cons(3, Rc::clone(&a));
    println!("b 생성 후 카운트 = {}", Rc::strong_count(&a));

    {
        let c = Cons(4, Rc::clone(&a));
        println!("c 생성 후 카운트 = {}", Rc::strong_count(&a));
    }

    println!("c가 스코프를 벗어난 후 카운트 = {}", Rc::strong_count(&a));
}

RefCell<T> - 내부 가변성

불변 참조로도 내부 값을 변경할 수 있게 해줍니다. 런타임에 빌림 규칙을 확인합니다.

use std::cell::RefCell;

fn main() {
    let data = RefCell::new(5);

    // 불변 참조
    let value = data.borrow();
    println!("값: {}", value);
    drop(value); // 명시적으로 해제

    // 가변 참조
    *data.borrow_mut() += 1;

    println!("변경된 값: {}", data.borrow());
}

// 실제 사용 예: 목(mock) 객체
pub trait Messenger {
    fn send(&self, msg: &str);
}

pub struct MockMessenger {
    sent_messages: RefCell<Vec<String>>,
}

impl MockMessenger {
    pub fn new() -> MockMessenger {
        MockMessenger {
            sent_messages: RefCell::new(vec![]),
        }
    }
}

impl Messenger for MockMessenger {
    fn send(&self, message: &str) {
        // self가 불변이지만 내부 값 변경 가능!
        self.sent_messages.borrow_mut().push(String::from(message));
    }
}

Rc<RefCell<T>> - 여러 소유자 + 가변성

use std::rc::Rc;
use std::cell::RefCell;

#[derive(Debug)]
enum List {
    Cons(Rc<RefCell<i32>>, Rc<List>),
    Nil,
}

use List::{Cons, Nil};

fn main() {
    let value = Rc::new(RefCell::new(5));

    let a = Rc::new(Cons(Rc::clone(&value), Rc::new(Nil)));
    let b = Cons(Rc::new(RefCell::new(3)), Rc::clone(&a));
    let c = Cons(Rc::new(RefCell::new(4)), Rc::clone(&a));

    *value.borrow_mut() += 10;

    println!("a = {:?}", a);
    println!("b = {:?}", b);
    println!("c = {:?}", c);
}
Box vs Rc vs RefCell

6.4 클로저 - 환경을 캡처하는 익명 함수

클로저는 변수를 캡처할 수 있는 익명 함수입니다.

기본 클로저

fn main() {
    let expensive_closure = |num: u32| -> u32 {
        println!("계산 중...");
        std::thread::sleep(std::time::Duration::from_secs(2));
        num
    };

    println!("결과: {}", expensive_closure(10));

    // 타입 추론
    let add_one = |x| x + 1;
    println!("5 + 1 = {}", add_one(5));
}

환경 캡처

fn main() {
    let x = 4;

    // 불변 빌림으로 캡처
    let equal_to_x = |z| z == x;

    // let y = x; // 에러! x가 빌려진 상태

    println!("equal_to_x(4) = {}", equal_to_x(4));

    // 가변 빌림으로 캡처
    let mut list = vec![1, 2, 3];
    println!("변경 전: {:?}", list);

    let mut borrows_mutably = || list.push(7);
    borrows_mutably();

    println!("변경 후: {:?}", list);

    // 소유권 이동
    let list2 = vec![1, 2, 3];
    let takes_ownership = move || {
        println!("클로저에서: {:?}", list2);
    };

    // println!("{:?}", list2); // 에러! list2가 이동됨
    takes_ownership();
}

Fn 트레이트

// FnOnce: 한 번만 호출 가능 (소유권 이동)
// FnMut: 여러 번 호출 가능, 환경 변경 가능
// Fn: 여러 번 호출 가능, 환경 변경 불가

fn call_with_different_values<F>(f: F)
where
    F: Fn(i32) -> i32,
{
    println!("f(1) = {}", f(1));
    println!("f(2) = {}", f(2));
}

fn main() {
    let double = |x| x * 2;
    call_with_different_values(double);
}

6.5 이터레이터 - 컬렉션 순회

이터레이터는 값들의 시퀀스를 처리하는 방법을 제공합니다.

기본 이터레이터

fn main() {
    let v1 = vec![1, 2, 3];

    // iter() - 불변 참조
    let v1_iter = v1.iter();
    for val in v1_iter {
        println!("값: {}", val);
    }

    // into_iter() - 소유권 이동
    for val in v1.into_iter() {
        println!("소유한 값: {}", val);
    }
    // println!("{:?}", v1); // 에러! v1이 이동됨

    let mut v2 = vec![1, 2, 3];

    // iter_mut() - 가변 참조
    for val in v2.iter_mut() {
        *val += 10;
    }
    println!("{:?}", v2); // [11, 12, 13]
}

이터레이터 어댑터

fn main() {
    let v = vec![1, 2, 3, 4, 5];

    // map - 각 요소 변환
    let doubled: Vec<_> = v.iter().map(|x| x * 2).collect();
    println!("2배: {:?}", doubled);

    // filter - 조건에 맞는 요소만
    let evens: Vec<_> = v.iter().filter(|x| *x % 2 == 0).collect();
    println!("짝수: {:?}", evens);

    // 체이닝
    let result: Vec<_> = v.iter()
        .filter(|x| **x > 2)
        .map(|x| x * 2)
        .collect();
    println!("2보다 크고 2배: {:?}", result);
}

유용한 이터레이터 메서드

fn main() {
    let v = vec![1, 2, 3, 4, 5];

    // sum - 합계
    let sum: i32 = v.iter().sum();
    println!("합계: {}", sum);

    // any - 하나라도 조건 만족?
    let has_even = v.iter().any(|x| x % 2 == 0);
    println!("짝수 있음? {}", has_even);

    // all - 모두 조건 만족?
    let all_positive = v.iter().all(|x| *x > 0);
    println!("모두 양수? {}", all_positive);

    // find - 첫 번째 매칭 요소
    let first_even = v.iter().find(|x| *x % 2 == 0);
    println!("첫 짝수: {:?}", first_even);

    // enumerate - 인덱스와 함께
    for (i, val) in v.iter().enumerate() {
        println!("v[{}] = {}", i, val);
    }

    // zip - 두 이터레이터 결합
    let names = vec!["Alice", "Bob", "Carol"];
    let scores = vec![90, 85, 95];

    for (name, score) in names.iter().zip(scores.iter()) {
        println!("{}: {}", name, score);
    }
}

커스텀 이터레이터 만들기

struct Counter {
    count: u32,
}

impl Counter {
    fn new() -> Counter {
        Counter { count: 0 }
    }
}

impl Iterator for Counter {
    type Item = u32;

    fn next(&mut self) -> Option<Self::Item> {
        if self.count < 5 {
            self.count += 1;
            Some(self.count)
        } else {
            None
        }
    }
}

fn main() {
    let counter = Counter::new();

    for num in counter {
        println!("{}", num); // 1, 2, 3, 4, 5
    }

    // Iterator 트레이트의 다른 메서드 사용 가능
    let sum: u32 = Counter::new()
        .zip(Counter::new().skip(1))
        .map(|(a, b)| a * b)
        .filter(|x| x % 3 == 0)
        .sum();

    println!("합계: {}", sum);
}
이터레이터 vs 루프

이터레이터는 종종 루프보다 빠릅니다! Rust 컴파일러가 이터레이터를 최적화하여 zero-cost abstraction을 실현합니다.

6.6 WIA 고급 패턴 예제

use std::rc::Rc;
use std::cell::RefCell;

// WIA-AI-CITY 메모리 관리 시스템
trait MemoryAllocator {
    fn allocate(&mut self, size: usize) -> Result<usize, String>;
    fn deallocate(&mut self, ptr: usize);
}

struct HBMAllocator {
    total: usize,
    used: usize,
    blocks: RefCell<Vec<(usize, usize)>>, // (ptr, size)
}

impl HBMAllocator {
    fn new(total_gb: usize) -> Self {
        HBMAllocator {
            total: total_gb * 1024 * 1024 * 1024,
            used: 0,
            blocks: RefCell::new(Vec::new()),
        }
    }

    fn usage_percent(&self) -> f64 {
        (self.used as f64 / self.total as f64) * 100.0
    }
}

impl MemoryAllocator for HBMAllocator {
    fn allocate(&mut self, size: usize) -> Result<usize, String> {
        if self.used + size > self.total {
            return Err("HBM 용량 초과".to_string());
        }

        let ptr = self.used;
        self.used += size;
        self.blocks.borrow_mut().push((ptr, size));

        Ok(ptr)
    }

    fn deallocate(&mut self, ptr: usize) {
        let mut blocks = self.blocks.borrow_mut();
        if let Some(pos) = blocks.iter().position(|(p, _)| *p == ptr) {
            let (_, size) = blocks.remove(pos);
            self.used -= size;
        }
    }
}

fn main() {
    let mut hbm = HBMAllocator::new(80); // 80GB HBM

    match hbm.allocate(1024 * 1024 * 1024) {
        Ok(ptr) => println!("할당됨: 포인터 {}, 사용률: {:.2}%",
                           ptr, hbm.usage_percent()),
        Err(e) => println!("할당 실패: {}", e),
    }
}

6.7 성능 최적화 팁

제로 비용 추상화 활용

한국 일반 인프라 매핑 (제6장)

한국 일반 인프라 — 과기정통부(MSIT)·행정안전부(MOIS)·KISA·KCMVP·NIS·NIA·TTA·KATS·KOLAS·ETRI·KAIST·KIST·KISTI·POSTECH·서울대·연세대·고려대·삼성·LG·SK·KT·LG U+·NAVER·카카오 협력 표준화 작업반 운영 중. 「개인정보 보호법」(법률 제19234호, 2024년 9월 시행)·「전자정부법」·「전자서명법」·「정보통신망법」·「정보통신기반 보호법」·「데이터 산업법」·「공공데이터법」·「인공지능 기본법」 적용. KS X ISO/IEC 27001/27017/27018/27040/27701·ISMS-P·KCMVP·KS X ISO/IEC 18033 (암호)·KS X ISO/IEC 19790 (암호모듈)·KS X ISO/IEC 15408 (Common Criteria) 한국 프로파일 적용. NIA「ICT 표준화 추진체계 운영」·KISA「개인정보보호 종합 포털」·MSIT「K-디지털 2030」 로드맵 운영 중.

한국 표준화 인프라 종합 매핑

한국의 산업·기술 표준화는 다음 협력 체계를 통해 운영된다. 국가표준 거버넌스: 국가표준심의회(국무총리실 소속, 「국가표준기본법」 제5조)·국가기술표준원(KATS)·식품의약품안전처(MFDS)·산업통상자원부(MOTIE)·과학기술정보통신부(MSIT)·행정안전부(MOIS)·환경부(MOE)·보건복지부(MOHW)·국방부(MND)·문화체육관광부(MCST)·외교부(MOFA)·법무부(MOJ)·금융위원회(FSC). 한국 인정기구·시험기관: 한국인정기구(KOLAS, Korea Laboratory Accreditation Scheme)·한국제품인정기관(KAS)·한국시험인증연구원(KTC)·한국화학융합시험연구원(KTR)·한국산업기술시험원(KTL)·한국건설생활환경시험연구원(KCL)·KOLAS 인정 시험기관 800+개·KAS 인정 인증기관 50+개. 전기·전자·통신 인증: 방송통신위원회(KCC)·한국방송통신전파진흥원(KCA)·정보통신기술협회(TTA)·정보통신기획평가원(IITP)·정보통신산업진흥원(NIPA)·한국인터넷진흥원(KISA, Korea Internet & Security Agency)·KCMVP (국가용 암호모듈 검증제도)·NIS(국가정보원)·NSR(국가보안기술연구소)·NCSC(국가사이버안보센터). 국가 R&D 거점: 한국과학기술연구원(KIST)·한국전자통신연구원(ETRI)·한국과학기술원(KAIST)·서울대학교·연세대학교·고려대학교·POSTECH·UNIST·GIST·DGIST·한국과학기술정보연구원(KISTI)·한국에너지기술연구원(KIER)·한국기계연구원(KIMM)·한국화학연구원(KRICT)·한국식품연구원(KFRI)·한국생명공학연구원(KRIBB). 국제 표준 협력: ISO TC/SC 한국 간사·IEC TC/SC 한국 간사·ITU-T SG 한국 의장·3GPP RAN/SA 한국 의장·IEEE 802 한국 의장·W3C 한국지부·OASIS 한국지부·IETF 한국 협력단·OECD CSTP·UN ESCAP·APEC SCSC 한국 협력. 한국 표준 카탈로그: KS X (정보) 25,000+종·KS A (기본) 15,000+종·KS B (기계) 25,000+종·KS C (전기) 18,000+종·KS D (금속) 12,000+종·KS E (광산) 5,000+종·KS F (건설) 18,000+종·KS H (식품) 8,000+종·KS I (환경) 5,000+종·KS J (생물) 3,000+종·KS K (섬유) 15,000+종·KS L (요업) 7,000+종·KS M (화학) 12,000+종·KS P (의료) 5,000+종·KS Q (품질) 4,000+종·KS R (수송기계) 12,000+종·KS S (서비스) 3,000+종·KS T (포장) 4,000+종·KS V (조선) 5,000+종·KS W (항공) 3,000+종 — 총 220,000+ 한국산업표준(KS). 「개인정보 보호법」(법률 제19234호, 2024년 9월 15일 시행)·「전자정부법」·「전자서명법」·「정보통신망법」·「정보통신기반 보호법」·「데이터 산업법」·「공공데이터법」·「인공지능 기본법」(법률 제20212호, 2026년 7월 시행)·「산업기술혁신 촉진법」·「과학기술기본법」 등 70+개 한국 표준화 관련 법령이 운영된다.

한국 디지털 전환·표준화 상세 매핑

한국의 디지털 전환과 표준화는 다음 협력 체계로 운영된다. 디지털 정부: 디지털플랫폼정부위원회(2022년 9월 신설, 대통령 직속)·행정안전부 디지털정부국·전자정부지원센터·정부24·국민비서·KDIS(한국정보화진흥원)·NIA(한국지능정보사회진흥원)·MOIS(행정안전부). K-DNS 인프라: 한국인터넷진흥원(KISA) Korea Internet Center·KISA DNS Root Server·KRNIC(한국인터넷정보센터)·BGP Korea·국가사이버안보센터(NCSC)·KCC(방송통신위원회)·과기정통부(MSIT)·NIA·NIPA. 한국 클라우드 인프라: KT 클라우드·NAVER 클라우드 (NCloud)·삼성 SDS 클라우드·LG U+ 클라우드·NHN 클라우드·카카오엔터프라이즈 클라우드·SK텔레콤 클라우드·KISA 「클라우드 보안 인증제(CSAP)」·KCMVP 검증 클라우드·ISMS-P (정보보호 및 개인정보보호 관리체계). 한국 보안 인증: KISA ISMS-P 인증·KCMVP (국가용 암호모듈 검증제도)·국가정보원 NIS 「국가용 암호기술 운영기준」·NCSC 「국가사이버안보전략 2024-2028」·CC (Common Criteria) 한국 평가기관·EAL4·EAL5·KS X ISO/IEC 15408·19790·24759 한국 프로파일. 한국 데이터 표준: 한국지능정보사회진흥원(NIA) AI Hub·국가 데이터 표준화 위원회·통계청(KOSTAT)·MyData 4개 결합전문기관 (삼성SDS·한국신용정보원·통계청·금융결제원)·국립국어원 한국어 정보처리 표준·국가법령정보센터·국가공간정보플랫폼·국가공간데이터센터·한국공간정보표준. 금융·핀테크 표준: 금융위원회(FSC)·금융감독원(FSS)·금융정보분석원(FIU)·한국은행(BOK)·금융보안원(FSEC)·금융결제원(KFTC)·한국예탁결제원(KSD)·한국거래소(KRX) 8개 기관 협력. 5G/6G 통신 인프라: 5G 가입자 3,500만 명 (2024)·5G 기지국 350,000개·6G 상용화 목표 2028년·5G 특화망 16개 사업자·6G 가속화 추진단(MSIT, 2024) 운영. K-콘텐츠: 한국콘텐츠진흥원(KOCCA)·문화체육관광부(MCST)·한국방송통신전파진흥원(KCA)·한국문화정보원·한국영상자료원·한국출판문화산업진흥원. 「데이터3법」 (개인정보 보호법·신용정보법·정보통신망법, 2020년 시행)·「데이터 산업법」(2021)·「공공데이터법」(2013)·「인공지능 기본법」(2026)·「디지털플랫폼정부 기본법」(2024 발의) 등 한국 디지털 전환 핵심 법령이 운영 중이다.