Pythonのグローバル変数とは、関数の外(モジュールの直下)で定義した変数のことで、関数の中から「読む」だけなら宣言なしで使えますが、「再代入する」ときは global 宣言が必要です。 この「読むのは自由、再代入には宣言」というルールと、名前を探す順番(LEGB)を押さえると、UnboundLocalError の原因がすっきり理解できます。

この記事では、スコープを図(Mermaid)と表で整理し、UnboundLocalError を Python 3.10・3.11・3.14 の実際のトレースバックで再現して、原因と修正コードを対で示します。global と nonlocal の違い、「宣言が要る・要らない」の判定表、クラススコープや内包表記の落とし穴、モジュール間でグローバル変数を共有するときの注意、グローバル変数を減らす書き方まで、実行結果つきで解説します。

グローバル変数とスコープの早見表

まず、4種類のスコープ(変数が見える範囲)の一覧です。

スコープ 頭文字 どこで定義した名前か 書き換えるための宣言
ローカル L(Local) いま実行している関数の中 不要
エンクロージング E(Enclosing) 外側の関数の中(関数の入れ子のとき) nonlocal
グローバル G(Global) モジュールの直下(関数の外) global
ビルトイン B(Built-in) len・print など、最初から使える名前 (上書きしないのがおすすめ)

次に、関数の中からグローバル変数を使うとき、宣言が要るかどうかの判定表です。すべて下の実行結果で確かめています。

関数の中でやること 例 宣言 理由
値を読むだけ print(total) / total * 2 不要 外側のスコープを順に探してくれる
再代入する count = 10 global が必要 宣言がないと新しいローカル変数になる
+= などで更新する count += 1 global が必要 += も代入の一種。宣言がないと UnboundLocalError
リストに追加する items.append("a") 不要 変数はそのまま。指している中身を変えるだけ
辞書の値を変える config["debug"] = True 不要 同上
リストに += する items += ["c"] global が必要 見た目は追加でも、代入として扱われる
外側の関数の変数を更新する n += 1(入れ子の関数) nonlocal が必要 外側の関数の変数は global では届かない

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「Pythonグローバル変数とスコープ|global・nonlocalとエラー解決」

この記事の検証環境

  • Python 3.14.7(Linux)を基本に、エラーメッセージの比較では Python 3.10.18 と 3.11.15 でも同じファイルを実行しました
  • トレースバック中のファイルパスは、読みやすいように /home/user/demo/ へ短く書き換えています。それ以外の行は出力のままです

スコープとは:名前を探す順番 LEGB

スコープとは、ある名前(変数名・関数名)が見える範囲のことです。 Python は名前を見つけるとき、内側から外側へ L → E → G → B の順に探し、最初に見つかったものを使います。

flowchart TB
    subgraph B["B: ビルトイン(len, print など)"]
        subgraph G["G: グローバル(モジュールの直下)"]
            subgraph E["E: エンクロージング(外側の関数)"]
                L["L: ローカル(いまの関数)"]
            end
        end
    end
    L -- "見つからなければ外へ" --> E
    E -- "見つからなければ外へ" --> G
    G -- "見つからなければ外へ" --> B
    B -- "どこにもない" --> N["NameError"]

同じ名前 x を3か所で定義して、どれが使われるかを確かめます。

import builtins

x = "global"

def outer():
    x = "enclosing"
    def inner():
        x = "local"
        print("inner:", x)
    inner()
    print("outer:", x)

outer()
print("module:", x)
print("builtin:", len, "len" in dir(builtins))

実行結果(Python 3.14.7):

inner: local
outer: enclosing
module: global
builtin: <built-in function len> True

3つの x は名前が同じでも別の変数で、それぞれの場所でいちばん内側のものが使われています。inner の中で x = "local" と代入しても、外側の x は変わっていません。

押さえるポイント 内容
探す方向は内→外の一方通行 外側から内側の変数は見えない
スコープを作るのは関数・クラス・モジュール・内包表記 if・for・while・with・try のブロックはスコープを作らない
どこにもなければ NameError NameError: name 'undefined_name' is not defined

ローカルかどうかは「代入があるか」で決まる

ここが最も大切なルールです。関数の中のどこかに、その名前への代入が1つでもあると、その名前は関数全体でローカル変数として扱われます。 代入より前の行でも同じです。この判定は関数を実行する前(定義を読み込んだ時点)に決まります。

関数の中の書き方 その名前の扱い
代入がない(読むだけ) 外側のスコープ(E → G → B)を探す
代入がある(=・+=・for の変数・import・with ... as・except ... as・def) 関数全体でローカル
global 名前 と宣言した グローバル変数として扱う
nonlocal 名前 と宣言した 外側の関数の変数として扱う

どの名前がローカルになったかは、関数オブジェクトから確認できます。

count = 0

def read():
    return count * 2          # 読むだけ

def rebind():
    count = 10                # 代入がある

print(read.__code__.co_varnames, rebind.__code__.co_varnames)
() ('count',)

rebind では count がローカル変数の一覧に入り、read では入っていません。この仕組みが、次の UnboundLocalError の原因です。

UnboundLocalError の原因と直し方

UnboundLocalError は、「ローカル変数として扱うと決まった名前を、値が入る前に使った」ときに出るエラーです。よくある4つのパターンを、原因→修正コードの対で見ていきます。

バージョンによるメッセージの違い

同じコードでも、Python のバージョンでメッセージが変わります。検索するときの手がかりになるので、先に整理します。

バージョン メッセージ(実行して確認)
3.10 まで UnboundLocalError: local variable 'count' referenced before assignment
3.11 以降 UnboundLocalError: cannot access local variable 'count' where it is not associated with a value

どちらも意味は同じで、「ローカル変数 count に、まだ値が結び付いていない」ということです。3.11 以降は、問題の箇所に ^^^^^ の印も付くようになりました。

パターン1:グローバル変数を += で更新した

count = 0

def increment():
    count += 1
    return count

increment()

Python 3.10.18 での実行結果:

Traceback (most recent call last):
  File "/home/user/demo/err1.py", line 7, in <module>
    increment()
  File "/home/user/demo/err1.py", line 4, in increment
    count += 1
UnboundLocalError: local variable 'count' referenced before assignment

Python 3.11.15 での実行結果:

Traceback (most recent call last):
  File "/home/user/demo/err1.py", line 7, in <module>
    increment()
  File "/home/user/demo/err1.py", line 4, in increment
    count += 1
    ^^^^^
UnboundLocalError: cannot access local variable 'count' where it is not associated with a value

Python 3.14.7 での実行結果:

Traceback (most recent call last):
  File "/home/user/demo/err1.py", line 7, in <module>
    increment()
    ~~~~~~~~~^^
  File "/home/user/demo/err1.py", line 4, in increment
    count += 1
    ^^^^^
UnboundLocalError: cannot access local variable 'count' where it is not associated with a value

原因: count += 1 は count = count + 1 と同じ意味で、代入を含みます。そのため count は increment のローカル変数と判定されます。ところが右辺で読もうとした時点では、ローカルの count にはまだ値がありません。

修正A:global で「グローバル変数を更新する」と宣言する

count = 0

def increment():
    global count
    count += 1

increment()
increment()
print(count)
2

修正B:引数で受け取り、戻り値で返す(おすすめ)

def increment(count):
    return count + 1

count = 0
count = increment(count)
count = increment(count)
print(count)
2

修正Bは、関数が外の変数に頼らないので、どこで値が変わるかが呼び出し側を見るだけでわかります。

パターン2:読んだあとで同じ名前に代入している

message = "こんにちは"

def show():
    print(message)
    message = "こんばんは"

show()

Python 3.14.7 での実行結果:

Traceback (most recent call last):
  File "/home/user/demo/err2.py", line 7, in <module>
    show()
    ~~~~^^
  File "/home/user/demo/err2.py", line 4, in show
    print(message)
          ^^^^^^^
UnboundLocalError: cannot access local variable 'message' where it is not associated with a value

原因: エラーの行は print(message) で、一見グローバルの message を読めそうに見えます。しかし次の行に代入があるため、message は関数全体でローカルと判定されています。3.10.18 では local variable 'message' referenced before assignment と表示されました。

修正: 関数内の変数を別の名前にします。

message = "こんにちは"

def show():
    print(message)
    evening = "こんばんは"
    print(evening)

show()
こんにちは
こんばんは

パターン3:入れ子の関数で外側の変数を更新した

def outer():
    total = 0
    def add(n):
        total += n
        return total
    return add(5)

outer()

Python 3.14.7 での実行結果:

Traceback (most recent call last):
  File "/home/user/demo/err3.py", line 8, in <module>
    outer()
    ~~~~~^^
  File "/home/user/demo/err3.py", line 6, in outer
    return add(5)
  File "/home/user/demo/err3.py", line 4, in add
    total += n
    ^^^^^
UnboundLocalError: cannot access local variable 'total' where it is not associated with a value

原因: total は outer のローカル変数(add から見るとエンクロージング)です。add の中で += したため、add のローカル変数と判定されました。total はグローバル変数ではないので、global total では届きません。

修正:nonlocal を使う

def outer():
    total = 0
    def add(n):
        nonlocal total
        total += n
        return total
    return add(5)

print(outer())
5

パターン4:条件によって代入されないまま使った

def find(items, key):
    for item in items:
        if item == key:
            result = item
    return result

find(["a", "b"], "z")

Python 3.14.7 での実行結果:

Traceback (most recent call last):
  File "/home/user/demo/err4.py", line 7, in <module>
    find(["a", "b"], "z")
    ~~~~^^^^^^^^^^^^^^^^^
  File "/home/user/demo/err4.py", line 5, in find
    return result
           ^^^^^^
UnboundLocalError: cannot access local variable 'result' where it is not associated with a value

原因: グローバル変数とは関係のないパターンです。"z" が見つからないと result = item が一度も実行されず、値のないまま return result に進みます。

修正:最初に初期値を入れておく

def find(items, key):
    result = None
    for item in items:
        if item == key:
            result = item
    return result

print(find(["a", "b"], "z"), find(["a", "b"], "b"))
None b

そのほかの UnboundLocalError

次の2つも同じエラーになることを、3.14.7 で確認しました。

書き方 起きること
del x のあとで x を使う cannot access local variable 'x' where it is not associated with a value
except ZeroDivisionError as e: のブロックを抜けたあとで e を使う except を抜けると e は自動で削除されるため、同じエラーになる

except の外でも例外の情報を使いたいときは、ブロックの中で saved = e のように別の変数へ入れておきます。

UnboundLocalError を見たときのチェック表

確認すること 当てはまったら
その名前に、関数の中で代入(=・+=)しているか グローバルを更新したいなら global、外側の関数の変数なら nonlocal
グローバル変数と同じ名前を、関数内の別の用途で使っていないか 名前を変える
if や for の中だけで代入していないか 先に初期値を入れる
そもそも外の変数を書き換える必要があるか 引数と戻り値に置き換える

global と nonlocal の違い

項目 global nonlocal
対象 モジュール直下の変数 外側の関数のローカル変数
使える場所 関数の中(モジュール直下に書いても意味はない) 入れ子になった関数の中だけ
対象の変数がまだないとき 代入した時点で新しく作られる SyntaxError(先に外側で定義が必要)
主な用途 設定値やカウンターの更新 クロージャ(状態を持つ関数)

同じ名前 v に対して、global と nonlocal がそれぞれどの変数を書き換えるかを確かめます。

v = "module"

def f():
    v = "f"
    def g():
        global v
        v = "changed by g(global)"
    def h():
        nonlocal v
        v = "changed by h(nonlocal)"
    g()
    print("after g:", v)
    h()
    print("after h:", v)

f()
print("module v:", v)
after g: f
after h: changed by h(nonlocal)
module v: changed by g(global)

global は途中の関数 f の v を飛び越えてモジュールの v を、nonlocal はすぐ外側の関数 f の v を書き換えています。

nonlocal の使いどころ:状態を持つ関数(クロージャ)

def make_counter():
    n = 0
    def counter():
        nonlocal n
        n += 1
        return n
    return counter

c = make_counter()
print(c(), c(), c())
c2 = make_counter()
print(c2())
1 2 3
1

c と c2 は別々の n を持っているので、互いに影響しません。グローバル変数でカウンターを作る場合と比べて、数を増やしても混ざらないのが利点です。

宣言の書き方で出る SyntaxError

宣言の位置や対象が合わないと、実行前に SyntaxError になります。3.14.7 で確認したメッセージです。

書き方 メッセージ
変数を使ったあとで global x と書く SyntaxError: name 'x' is used prior to global declaration
外側の関数に x がないのに nonlocal x SyntaxError: no binding for nonlocal 'x' found
引数と同じ名前を global x SyntaxError: name 'x' is parameter and global
モジュール直下に nonlocal x SyntaxError: nonlocal declaration not allowed at module level

global・nonlocal は関数の先頭に書くと覚えておくと、1つ目のエラーを避けられます。

宣言が要る・要らないを実行で確かめる

冒頭の判定表を、実際に動かして確かめます。

items = []
config = {"debug": False}
total = 10

def read():
    return total * 2            # 読むだけ → 宣言不要

def append():
    items.append("a")           # メソッドで中身を変更 → 宣言不要

def setitem():
    config["debug"] = True      # 要素への代入 → 宣言不要

def rebind():
    items = ["new"]             # 再代入 → 新しいローカル変数になる

def iadd_list():
    items += ["c"]              # += → 代入の扱い

print(read())
append(); setitem(); rebind()
print(items, config)
try:
    iadd_list()
except UnboundLocalError as e:
    print("UnboundLocalError:", e)
20
['a'] {'debug': True}
UnboundLocalError: cannot access local variable 'items' where it is not associated with a value

読み取れることは3つです。

  • append や config["debug"] = True は宣言なしでグローバルの中身が変わる。 変数 items が指す先は変えず、リストや辞書の中身を変えているためです
  • rebind の items = ["new"] はエラーにならないが、グローバルの items は ['a'] のまま。 関数の中だけの別の変数が作られ、関数が終わると消えます。エラーが出ないぶん気づきにくいので注意が必要です
  • items += ["c"] は UnboundLocalError。 リストの += は中身を変える操作ですが、文法上は代入なのでローカル扱いになります。items.extend(["c"]) と書けば宣言は不要です

クラススコープの落とし穴

クラスの直下で定義した変数(クラス変数)は、LEGB の探索に含まれません。 メソッドや内包表記の中からは、名前だけでは見つからないのです。

class Shop:
    rate = 1.1
    prices = [100, 200]

    def total(self):
        return sum(self.prices) * rate     # rate を名前だけで参照

try:
    Shop().total()
except NameError as e:
    print("NameError:", e)
NameError: name 'rate' is not defined

メソッドの中では self.rate(または Shop.rate)と書きます。

class Shop:
    rate = 1.1
    prices = [100, 200]
    first = [p for p in prices]            # 最初の for の対象だけはクラス変数を使える

    def total(self):
        return round(sum(self.prices) * self.rate)

print(Shop.first, Shop().total())
[100, 200] 330

クラス直下の内包表記にも同じ注意があります。taxed = [p * rate for p in prices] とクラス直下に書くと、prices(最初の for の対象)は読めますが、rate は NameError: name 'rate' is not defined になることを確認しました。内包表記の中身は、関数と同じように独立したスコープで動くためです。

場所 クラス変数 rate の参照方法
クラス直下の通常の文 rate でそのまま使える
メソッドの中 self.rate または Shop.rate
クラス直下の内包表記の中 最初の for の対象以外は使えない。メソッドやクラスの外で計算する

内包表記・ループ変数・if ブロックのスコープ

内包表記の変数は外に漏れない、for 文の変数は外に残る

i = "before"
squares = [i * i for i in range(3)]
print(squares, i)

for j in range(3):
    pass
print("j =", j)

for k in []:
    pass
try:
    print(k)
except NameError as e:
    print("NameError:", e)

if True:
    inside_if = 1
print(inside_if)
[0, 1, 4] before
j = 2
NameError: name 'k' is not defined
1
書き方 変数は外に残るか 実行結果
内包表記 [i * i for i in ...] 残らない 外の i は before のまま
for j in range(3): 残る ループのあと j = 2
for k in []:(0回) 作られない NameError
if ブロックの中の代入 残る inside_if は外で使える

for 文のループ変数は、ループが終わったあとも最後の値を持ったまま残ります。 同じ名前を後ろで別の用途に使うと思わぬ値が入っていることがあるので、ループ変数には用途のわかる名前を付けるのがおすすめです。空のリストを回した場合は変数が作られない点も、あわせて覚えておくと役立ちます。

ループの中で作った関数は「最後の値」を見る

funcs = [lambda: n for n in range(3)]
print([f() for f in funcs])

funcs = [lambda n=n: n for n in range(3)]
print([f() for f in funcs])
[2, 2, 2]
[0, 1, 2]

1つ目は、3つの関数がすべて 2 を返します。関数は変数 n の「値」ではなく「名前」を覚えていて、呼ばれた時点の値を見に行くためです。lambda n=n: n のように既定値として渡すと、作った時点の値を固定できます。

モジュール間でグローバル変数を共有する

「グローバル」といっても、Python のグローバル変数はモジュール(ファイル)単位です。複数のファイルで同じ値を使いたいときは、設定用のモジュールを1つ作って import します。ここに from ... import の落とし穴があります。

# settings.py
counter = 0
items = []

def increment():
    global counter
    counter += 1
# main_from.py
from settings import counter, items, increment

increment()
items.append("a")
print("from import:", counter, items)

import settings
print("settings.counter:", settings.counter, settings.items)

python main_from.py の実行結果:

from import: 0 ['a']
settings.counter: 1 ['a']

increment() で settings.counter は 1 になったのに、from settings import counter で取り込んだ counter は 0 のままです。

取り込み方 起きること
from settings import counter その時点の値を指す新しい名前が main_from 側に作られる。あとで settings.counter が再代入されても追従しない
from settings import items(リスト) 同じリストを指しているので、append の結果は両方から見える
import settings → settings.counter 毎回 settings モジュールの変数を見に行くので、常に最新の値

モジュール間で共有する値は、import settings して settings.counter と書くのが確実です。更新もこの形でできます。

# main_mod.py
import settings

settings.increment()
settings.counter += 10
print(settings.counter)
11

グローバル変数を減らす書き方

グローバル変数は手軽ですが、数が増えると「どの関数がいつ書き換えたか」を追うのに時間がかかるようになります。次の3つの書き方に置き換えると、値の流れが見えやすくなります。

方法 向いている場面 ポイント
引数と戻り値 計算・変換の関数 関数だけを見れば入力と出力がわかる
クラス(dataclass)にまとめる 関連する複数の値と、それを操作する処理 状態の置き場所が1か所に決まる
定数は大文字で書く 設定値・上限値など、変えない値 「書き換えない約束」が名前で伝わる
from dataclasses import dataclass, field

MAX_RETRY = 3                      # 定数は大文字。書き換えない約束

def add_tax(price, rate=0.1):      # 引数で受け取り、戻り値で返す
    return round(price * (1 + rate))

@dataclass
class Cart:                        # 状態はクラスにまとめる
    items: list = field(default_factory=list)

    def add(self, name, price):
        self.items.append((name, price))

    def total(self):
        return sum(price for _, price in self.items)

cart = Cart()
cart.add("ノート", 300)
cart.add("ペン", 120)
print(add_tax(cart.total()), MAX_RETRY)
print(Cart().items)
462 3
[]

最後の行のとおり、新しく作った Cart() は空のリストから始まるので、テストや複数の利用者を同時に扱う処理でも値が混ざりません。

グローバル変数が向いているもの 関数の引数やクラスに移すとよいもの
変えない定数(MAX_RETRY、BASE_DIR) 処理の途中で変わるカウンター・合計
ロガー(logger = logging.getLogger(__name__)) 利用者ごと・処理ごとに異なる値
正規表現のコンパイル結果など、作り直す必要のないもの 関数の計算結果(戻り値で返す)

Python には定数を書き換えられなくする専用の構文はありません。大文字の名前は「変えないでください」という合図として、多くのコードで共通の約束になっています。

globals() と locals() でスコープの中身を見る

globals() はグローバル変数の辞書、locals() はいまのスコープの変数の辞書を返します。調べものやデバッグに便利です。

count = 2

def demo(a):
    b = a * 2
    return locals()

print(demo(3))
print(globals()["count"], "count" in globals())

globals()["made_by_dict"] = 42
print(made_by_dict)

def demo2():
    z = 1
    locals()["z"] = 99
    return z

print(demo2())
print(locals() is globals())
{'a': 3, 'b': 6}
2 True
42
1
True
関数 返すもの 辞書を書き換えると
globals() モジュールのグローバル変数の辞書 実際の変数に反映される(made_by_dict が作られた)
locals()(関数の中) その時点のローカル変数の辞書 反映されない(z は 1 のまま)
locals()(モジュール直下) globals() と同じ辞書 反映される

globals()["名前"] = 値 で変数を作ることもできますが、どこで作られた変数かが追いにくくなります。名前を動的に決めたいときは、辞書を1つ用意して data["名前"] = 値 とするほうが、読みやすく安全です。

入れ子の関数が外側のどの変数を覚えているかは、次のように確認できます。

def outer2():
    a = 1
    def inner2():
        return a
    return inner2

fn = outer2()
print(fn.__code__.co_freevars, fn.__closure__[0].cell_contents)
('a',) 1

よくある質問

Q. グローバル変数を関数の中で読むだけなら、global は必要ですか? A. 不要です。関数の中にその名前への代入がなければ、Python は外側のスコープを順に探して値を見つけます。global が必要なのは、再代入や += で変数そのものを書き換えるときだけです。

Q. global と nonlocal はどう使い分けますか? A. 書き換えたい変数がモジュール直下にあるなら global、外側の関数の中にあるなら nonlocal です。nonlocal は入れ子の関数でだけ使え、対象の変数が外側の関数に定義されている必要があります。

Q. リストに append するだけなのに、宣言が要らないのはなぜですか? A. items.append("a") は、変数 items が指しているリストの中身を変える操作で、items という名前への代入ではないためです。一方 items = [...] や items += [...] は代入なので、宣言がないとローカル変数として扱われます。

Q. UnboundLocalError と NameError の違いは何ですか? A. NameError は、その名前がどのスコープにも見つからないときのエラーです。UnboundLocalError は NameError の一種で、ローカル変数と判定された名前に、まだ値が入っていないときに出ます。関数の中に代入があるかどうかが見分けるポイントです。

まとめ

  • 名前は L(ローカル)→ E(外側の関数)→ G(グローバル)→ B(ビルトイン)の順に探される
  • 関数の中に代入が1つでもあると、その名前は関数全体でローカルになる。これが UnboundLocalError の原因
  • メッセージは 3.10 まで referenced before assignment、3.11 以降は cannot access local variable ...
  • 読むだけ・append・要素への代入は宣言不要、再代入と += は global/nonlocal が必要
  • global はモジュールの変数、nonlocal は外側の関数の変数を書き換える
  • クラス変数はメソッドから self.名前 で参照、for 文のループ変数は外に残る
  • モジュール間の共有は import settings → settings.counter。状態は引数・戻り値やクラスにまとめ、定数は大文字で書く

本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。

(記載例)出典:株式会社RJC「Pythonグローバル変数とスコープ|global・nonlocalとエラー解決」

株式会社RJCでは、Pythonのスコープとグローバル変数の扱い方を仲間と学び合っています。こうした知識を共有しながら、日々技術を磨いています。

株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。

WE ARE HIRING

RJCで一緒に開発しながら、
成長を楽しみませんか?

RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!

  • 127日年間休日
  • 12時間平均残業時間
  • 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!

ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。

ABOUT RJC RJCがどんな会社か知る 考え方、研修、働き方、福利厚生、社員の前職まで。RJCのことが丸わかり! RJC丸わかりページへ JOB DESCRIPTION 仕事内容・待遇を見てみる 仕事内容、給与・待遇、選考の流れ。経験者も未経験も!応募前に知りたいこと、まとめました! 募集要項を見る ENTRY エントリーする エントリーは1〜2分・履歴書不要です。まずは話を聞いてみたい、という方でも歓迎です! エントリーフォームへ

RJCで一緒に開発しながら、 成長を楽しみませんか?