- Next.js
Next.js proxy.ts入門|middleware移行とmatcher実例
Next.js の proxy.ts とは、リクエストがページやAPIに届く前に実行される処理(旧 middleware.ts)を書くファイルで、Next.js 16 から middleware.ts はこの名前に変わりました。 移行は「ファイル名を proxy.ts に変え、関数名を proxy にする」だけで、公式の codemod が自動でやってくれます。ただし、Proxy の実行環境は Node.js に固定になり、Edge Runtime を指定するとビルドが止まる点が大きな違いです。
この記事では、Next.js 16.3.6(2026年9月時点の最新安定版)で実際に next build / next start を動かし、非推奨警告の実際の文面、codemod の差分、よく出るビルドエラー3種、matcher の判定結果一覧、6つの定番処理の curl -i 実出力をそのまま載せています。移行手順だけでなく「どう書けば意図どおりに動くか」をコピペで確認できる構成です。
Next.js proxy.ts の早見表
| やりたいこと | 書き方・結論 |
|---|---|
| middleware.ts から移行 | npx @next/codemod@canary middleware-to-proxy .(ファイル名と関数名を変更) |
| ファイルの置き場所 | プロジェクト直下、または src/ 直下(app と同じ階層)。1プロジェクト1ファイル |
| エクスポート | export function proxy(request) または export default function proxy(request) |
| 実行環境(ランタイム) | Node.js 固定。runtime を書くとビルドエラー |
| Edge Runtime が必要 | 当面は middleware.ts のまま使う(公式の案内。非推奨警告は出る) |
| 対象パスを絞る | export const config = { matcher: [...] }(定数で書く) |
| 静的ファイルを除外 | '/((?!api|_next/static|_next/image|favicon.ico).*)' |
| ヘッダーや Cookie で条件 | matcher のオブジェクト形式で has / missing |
| ログイン前はリダイレクト | Cookie の存在チェックだけして NextResponse.redirect() |
| URL を変えずに別ページを表示 | NextResponse.rewrite() |
| サーバー側に値を渡す | NextResponse.next({ request: { headers } }) |
| 直接レスポンスを返す | new NextResponse(body, { status }) / Response.json() |
| 単純な固定リダイレクト | Proxy ではなく next.config.ts の redirects を優先 |
| DB 問い合わせ・重い処理 | Proxy では避け、ページ・Server Action・Route Handler 側で行う |
| テスト | next/experimental/testing/server(16.3.6 の関数名は後述) |
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Next.js proxy.ts入門|middleware移行とmatcher実例」
検証環境
この記事の出力は、すべて次の環境で実際に実行したものです。
| 項目 | バージョン |
|---|---|
| Next.js | 16.3.6(Turbopack) |
| React | 19.2.8 |
| Node.js | 22.22.2 |
| @next/codemod | 16.4.0-canary.52(@canary で取得された版) |
| 作成コマンド | npx create-next-app@16.3.6(TypeScript・App Router) |
middleware.ts から proxy.ts への移行手順
1. middleware.ts のままビルドすると出る警告
次の、よくある形の middleware.ts を用意しました。
// middleware.ts(移行前)
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export function middleware(request: NextRequest) {
if (!request.cookies.has('session')) {
return NextResponse.redirect(new URL('/login', request.url))
}
return NextResponse.next()
}
export const config = {
matcher: ['/dashboard/:path*'],
}
next build の実際の出力です(抜粋)。
▲ Next.js 16.3.6 (Turbopack)
⚠ The "middleware" file convention is deprecated. Please use "proxy" instead.
To migrate automatically, run:
npx @next/codemod@canary middleware-to-proxy .
Learn more: https://nextjs.org/docs/messages/middleware-to-proxy
Creating an optimized production build ...
✓ Compiled successfully in 5.1s
...
ƒ Proxy (Middleware)
middleware.ts は 16.3.6 でもそのまま動きます(警告のみ)。 curl で確かめると、Cookie なしでは 307 でリダイレクトされました。
$ curl -si localhost:7220/dashboard
HTTP/1.1 307 Temporary Redirect
location: /login
生成物を見ると、middleware.ts は Edge Runtime 用(server/edge/chunks/)にビルドされていました。
2. codemod で proxy.ts に変換する
npx @next/codemod@canary middleware-to-proxy .
実行結果の末尾は 0 errors / 8 unmodified / 1 skipped / 0 ok でした。
「0 ok」と表示されましたが、実際にはファイル名と関数名が変わっていました。 git diff -M で確認した差分です。
diff --git a/middleware.ts b/proxy.ts
similarity index 85%
rename from middleware.ts
rename to proxy.ts
--- a/middleware.ts
+++ b/proxy.ts
@@ -1,7 +1,7 @@
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
-export function middleware(request: NextRequest) {
+export function proxy(request: NextRequest) {
if (!request.cookies.has('session')) {
return NextResponse.redirect(new URL('/login', request.url))
}
変わるのはファイル名と関数名だけで、config.matcher や中身の処理はそのままです。 手で移行する場合も、mv middleware.ts proxy.ts と関数名の変更の2点で完了します。
next.config.ts の設定名も変わっています。skipMiddlewareUrlNormalize は skipProxyUrlNormalize になりました(バージョン16への upgrade codemod で一緒に更新されます)。
3. 移行後のビルドと、ランタイムの違い
移行後の next build では警告が消え、ルート一覧の下に ƒ Proxy (Middleware) と表示されます。生成物を比べると、ランタイムの違いがはっきり出ました。
| 項目 | middleware.ts(16.3.6) | proxy.ts(16.3.6) |
|---|---|---|
| ビルド時の警告 | 非推奨警告あり | なし |
| 出力先 | middleware-manifest.json に登録、server/edge/chunks/ |
functions-config-manifest.json に登録、server/middleware.js |
| ランタイム | Edge(既定) | "runtime": "nodejs" |
runtime の指定 |
可能 | 不可(ビルドエラー) |
Proxy が Node.js で動くことで、Node.js の API(node:fs など)や Node.js 前提のライブラリをそのまま使えるのが利点です。
Edge Runtime が必要な場合はどうするか
公式のアップグレードガイドは、「proxy では edge ランタイムはサポートされず、ランタイムは nodejs で変更できない。edge を使い続けたい場合は middleware を使い続ける」と明記しています(edge についての追加の案内は今後のマイナーリリースで示す予定)。つまり 16.3.6 時点では、Edge が必要なら middleware.ts のまま(警告は出る)、Node.js でよいなら proxy.ts の二択です。
移行でよく出るビルドエラー3種と直し方
実際に next build で出したエラーです。
① proxy.ts に runtime: 'edge' を書いた
export const config = {
matcher: ['/dashboard/:path*'],
runtime: 'edge', // ← これがあるとビルドが止まる
}
> Build error occurred
Error: Turbopack build failed with 1 error:
./proxy.ts:11:14
Error: Next.js can't recognize the exported `config` field in route. Proxy does not support Edge runtime.
直し方:runtime の行を削除します。 Edge が必須なら middleware.ts に戻します。
② middleware.ts と proxy.ts が両方ある
手で proxy.ts を作り、元の middleware.ts を消し忘れたときに出ます。
> Build error occurred
Error: Both middleware file "./middleware.ts" and proxy file "./proxy.ts" are detected. Please use "./proxy.ts" only. Learn more: https://nextjs.org/docs/messages/middleware-to-proxy
直し方:middleware.ts を削除します。
③ ファイル名だけ変えて、関数名が middleware のまま
> Build error occurred
Error: Turbopack build failed with 1 error:
./proxy.ts
Error: Proxy is missing expected function export name
This function is what Next.js runs for every request handled by this proxy (previously called middleware).
...
- Ensure this file has either a default or "proxy" function export.
直し方:export function proxy にするか、export default function にします。 公式はデフォルトエクスポートの場合も関数名を proxy にすることを推奨しています。
matcher のパターン一覧(判定結果つき)
matcher は「Proxy をどのパスで動かすか」の指定です。matcher を書かないと、_next/static の JS・CSS や public/ の画像を含むすべてのリクエストで Proxy が動きます。 認証リダイレクトを書くと CSS まで止まることがあるため、除外パターンとセットで書くのが基本です。
次の表は、Next.js 付属のテスト用関数で実際に判定させた結果です(true = Proxy が動く)。
| matcher | パス → 判定 |
|---|---|
'/about/:path*'(0個以上) |
/about → true、/about/team → true、/about/a/b → true、/blog/about → false |
'/about/:path'(ちょうど1つ) |
/about → false、/about/team → true、/about/a/b → false |
'/about/:path+'(1個以上) |
/about → false、/about/team → true |
'/about/:path?'(0か1) |
/about → true、/about/team → true、/about/a/b → false |
'/posts/:id(\\d+)'(正規表現) |
/posts/123 → true、/posts/abc → false |
'/((?!api|_next/static|_next/image|favicon.ico).*)' |
/ → true、/dashboard → true、/api/hello → false、/_next/static/x.js → false、/favicon.ico → false、/apikey → false |
'/((?!api(?:/|$)|_next/static|_next/image|favicon.ico).*)' |
/api → false、/api/hello → false、/apikey → true、/dashboard → true |
'/((?!_next|.*\\..*).*)'(拡張子付きを除外) |
/ → true、/docs → true、/logo.png → false、/robots.txt → false |
公式例の (?!api|...) は「api で始まるパス」をすべて除外するため、/apikey や /apiary のようなページも Proxy の対象外になります。 api 配下だけを除外したいときは api(?:/|$) のように区切りまで書くと意図どおりになります。
has / missing でヘッダーや Cookie を条件にする
export const config = {
matcher: [
{
source: '/api/:path*',
has: [{ type: 'header', key: 'authorization' }], // このヘッダーがあるときだけ
missing: [{ type: 'cookie', key: 'bypass' }], // この Cookie がないときだけ
},
],
}
判定結果です。
has/missing:
auth header only -> true
no auth header -> false
auth header + bypass -> false
type には header / query / cookie を指定でき、value を省くと「キーが存在するか」だけで判定します。プリフェッチ(リンク先の先読み)を除外したい場合は、公式例のとおり missing: [{ type: 'header', key: 'next-router-prefetch' }, { type: 'header', key: 'purpose', value: 'prefetch' }] を使います。
matcher の書き方ルール
| ルール | 内容 |
|---|---|
| 先頭一致 | /about は /about/team にも一致、/blog/about には一致しない |
| 定数で書く | ビルド時に静的解析されるため、変数や関数呼び出しは無視される |
_next/data |
除外パターンに書いても Proxy は実行される(保護漏れを防ぐための仕様) |
| Server Function | 独立したルートではなく、使われているページへの POST として扱われる |
Server Action は「呼び出し元ページのパス」への POST なので、matcher でそのページを除外すると Server Action も Proxy を通りません。
matcher を単体テストする(16.3.6 の関数名に注意)
公式ドキュメントでは unstable_doesProxyMatch と紹介されていますが、16.3.6 のパッケージに入っている関数名は unstable_doesMiddlewareMatch でした(型定義にも doesProxyMatch は含まれていません)。また Jest などを使わずに Node.js で直接読み込む場合は、AsyncLocalStorage をグローバルに用意する必要がありました。上の表を出したスクリプトです。
// matcher-test.mjs(node matcher-test.mjs で実行)
import { AsyncLocalStorage } from 'node:async_hooks'
globalThis.AsyncLocalStorage = AsyncLocalStorage
const { default: pkg } = await import('next/experimental/testing/server.js')
const match = pkg.unstable_doesMiddlewareMatch
const matcher = '/((?!api(?:/|$)|_next/static|_next/image|favicon.ico).*)'
for (const url of ['/api', '/api/hello', '/apikey', '/dashboard']) {
console.log(`${url.padEnd(12)} -> ${match({ config: { matcher }, url })}`)
}
/api -> false
/api/hello -> false
/apikey -> true
/dashboard -> true
matcher を変えたときにこのテストを流しておくと、「保護したいページが対象から外れていた」を事前に見つけられます。
コピペで使える proxy.ts 実例集(curl -i の実出力つき)
Proxy は1プロジェクトに1ファイルなので、処理ごとに小さな関数に分け、proxy() で順番に呼ぶ形にすると読みやすくなります。次のファイル1つで、6つの定番処理をまとめて動かしました。
// proxy.ts(Next.js 16.3.6 で動作確認)
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
const LOCALES = ['ja', 'en'] as const
const DEFAULT_LOCALE = 'ja'
// ① メンテナンスモード:環境変数が "1" のとき、全ページをメンテナンス画面に差し替える
function maintenance(request: NextRequest) {
if (process.env.MAINTENANCE_MODE !== '1') return null
if (request.nextUrl.pathname === '/maintenance') return null
return NextResponse.rewrite(new URL('/maintenance', request.url), { status: 503 })
}
// ② Basic認証:/admin 配下だけ
function basicAuth(request: NextRequest) {
if (!request.nextUrl.pathname.startsWith('/admin')) return null
const header = request.headers.get('authorization') ?? ''
const [scheme, encoded] = header.split(' ')
if (scheme === 'Basic' && encoded) {
const [user, pass] = atob(encoded).split(':')
if (user === process.env.BASIC_USER && pass === process.env.BASIC_PASS) return null
}
return new NextResponse('Authentication required', {
status: 401,
headers: { 'WWW-Authenticate': 'Basic realm="admin"' },
})
}
// ③ 認証リダイレクト:Cookie が無ければ /login へ(元のURLを from に残す)
function authRedirect(request: NextRequest) {
if (!request.nextUrl.pathname.startsWith('/dashboard')) return null
if (request.cookies.has('session')) return null
const url = new URL('/login', request.url)
url.searchParams.set('from', request.nextUrl.pathname)
return NextResponse.redirect(url)
}
// ④ i18n リダイレクト:/docs → /ja/docs または /en/docs(Accept-Language で判定)
function i18nRedirect(request: NextRequest) {
const { pathname } = request.nextUrl
if (!pathname.startsWith('/docs')) return null
const accept = request.headers.get('accept-language') ?? ''
const locale = LOCALES.find((l) => accept.toLowerCase().startsWith(l)) ?? DEFAULT_LOCALE
return NextResponse.redirect(new URL(`/${locale}${pathname}`, request.url))
}
// ⑤ rewrite:/blog/xxx を /posts/xxx で表示(URLは /blog/xxx のまま)
function blogRewrite(request: NextRequest) {
const { pathname } = request.nextUrl
if (!pathname.startsWith('/blog/')) return null
return NextResponse.rewrite(new URL(pathname.replace('/blog/', '/posts/'), request.url))
}
export function proxy(request: NextRequest) {
const early =
maintenance(request) ??
basicAuth(request) ??
authRedirect(request) ??
i18nRedirect(request) ??
blogRewrite(request)
if (early) return early
// ⑥ ヘッダー付与:リクエストID(サーバー側へ)とセキュリティヘッダー(ブラウザへ)
const requestId = crypto.randomUUID()
const requestHeaders = new Headers(request.headers)
requestHeaders.set('x-request-id', requestId)
const response = NextResponse.next({ request: { headers: requestHeaders } })
response.headers.set('x-request-id', requestId)
response.headers.set('X-Content-Type-Options', 'nosniff')
response.headers.set('Referrer-Policy', 'strict-origin-when-cross-origin')
return response
}
export const config = {
matcher: [
// api・静的ファイル・画像最適化・メタデータファイルを除くすべて
'/((?!api|_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)',
],
}
確認用のページは app/login、app/dashboard、app/ja/docs、app/en/docs、app/posts/[slug]、app/admin、app/maintenance、app/api/hello/route.ts を用意し、BASIC_USER=admin BASIC_PASS=secret npx next start -p 7220 で起動しました。
認証リダイレクト(ログイン前は /login へ)
$ curl -si localhost:7220/dashboard
HTTP/1.1 307 Temporary Redirect
location: /login?from=%2Fdashboard
from に元のパスを残しておくと、ログイン後に元のページへ戻せます。 戻すときは、外部URLへ飛ばされないよう「/ で始まり // で始まらない」ことを確認してから使います。
ここでの Cookie チェックは「あるかどうか」だけです。公式は Proxy では Cookie からの楽観的チェック(optimistic check)にとどめ、DB でのセッション確認はページ側で行うよう案内しています。
ヘッダー付与(サーバー側とブラウザ側)
$ curl -si -b 'session=dummy' localhost:7220/dashboard
HTTP/1.1 200 OK
referrer-policy: strict-origin-when-cross-origin
x-content-type-options: nosniff
x-request-id: d391956c-86ed-4ece-a33e-a78ac42bdfe9
...
<p>request-id: <!-- -->d391956c-86ed-4ece-a33e-a78ac42bdfe9</p>
ページ側は headers() で読むだけです。
// app/dashboard/page.tsx
import { headers } from 'next/headers'
export default async function Page() {
const h = await headers()
return (
<main>
<h1>ダッシュボード</h1>
<p>request-id: {h.get('x-request-id')}</p>
</main>
)
}
同じ1回のリクエストで、レスポンスヘッダーとページ本文に同じ ID が入りました。 使い分けは次のとおりです。
| 書き方 | 届く先 |
|---|---|
NextResponse.next({ request: { headers } }) |
サーバー側(ページ・Route Handler の headers()) |
response.headers.set(...) |
ブラウザ(レスポンスヘッダー) |
NextResponse.next({ headers }) |
ブラウザに届く(サーバーへ渡すつもりなら誤り) |
大きな値をヘッダーに入れると、サーバー構成によっては 431 Request Header Fields Too Large になるため、ID 程度の小さな値にとどめます。
i18n リダイレクト(Accept-Language で振り分け)
$ curl -si -H 'Accept-Language: en-US,en;q=0.9' localhost:7220/docs
HTTP/1.1 307 Temporary Redirect
location: /en/docs
$ curl -si -H 'Accept-Language: ja,en;q=0.8' localhost:7220/docs
HTTP/1.1 307 Temporary Redirect
location: /ja/docs
ここでは先頭の言語だけを見る簡易版です。q= の優先度まで扱うなら、公式の国際化ガイドにあるライブラリを使う方法があります。
rewrite(URL を変えずに別ページを表示)
$ curl -si localhost:7220/blog/hello-proxy
HTTP/1.1 200 OK
...
<h1>記事: <!-- -->hello-proxy</h1>
リダイレクトはブラウザの URL が変わり、rewrite は URL が変わらずに中身だけ差し替わります。 旧URLの互換維持や A/B テストの振り分けに向いています。NextResponse.rewrite() を使えば RSC(Server Components)用の内部ヘッダーも自動で引き継がれます。
Basic 認証(/admin だけ)
$ curl -si localhost:7220/admin
HTTP/1.1 401 Unauthorized
www-authenticate: Basic realm="admin"
$ curl -si -u admin:secret localhost:7220/admin
HTTP/1.1 200 OK
$ curl -si -u admin:wrong localhost:7220/admin
HTTP/1.1 401 Unauthorized
WWW-Authenticate を返すとブラウザが入力欄を出し、ステージング環境の簡易な保護に使えます。 ID とパスワードは環境変数に置き、HTTPS で配信します。
メンテナンスモード(503 を返す)
MAINTENANCE_MODE=1 npx next start -p 7220 で起動し直した結果です。
$ curl -si localhost:7220/
HTTP/1.1 503 Service Unavailable
...
<h1>ただいまメンテナンス中です</h1>
$ curl -si localhost:7220/api/hello
HTTP/1.1 200 OK
NextResponse.rewrite(url, { status: 503 }) で、メンテナンス画面を 503 付きで返せました。 503 は「一時的に利用できない」を検索エンジンに伝えるステータスです。環境変数は next start 時に読まれたため、再ビルドなしで切り替えられました。一方で /api/hello は matcher で除外しているので 200 のままです。API も止めたい場合は matcher の除外から api を外します。
Proxy に書くこと・書かないことの判断表
公式ドキュメントは、Proxy を「他に手段がないときの最後の選択肢」と位置づけ、より使いやすい API で目的を達成できる方向へ進めていると説明しています。名称変更の理由も、Express のミドルウェアと混同されて何でも書かれがちだったためです。
| やりたいこと | おすすめの場所 | 理由 |
|---|---|---|
固定の URL 移転(/old → /new) |
next.config.ts の redirects |
Proxy より前に処理され、コードが不要 |
| 全ページ共通の固定ヘッダー | next.config.ts の headers |
条件分岐がなければ設定で足りる |
| Cookie・ヘッダーで分岐するリダイレクト | proxy.ts | リクエストの中身を見て判断できる |
| A/B テストの振り分け | proxy.ts(rewrite) | URL を変えずに出し分けられる |
| ログイン済みかの入口チェック | proxy.ts(Cookie の存在・署名の確認まで) | 楽観的チェックとして公式が紹介 |
| セッションの本確認・権限チェック | ページ・Server Action・Route Handler(DAL) | データに近い場所で必ず確認する |
| DB からのデータ取得 | Server Component・Route Handler | Proxy は遅いデータ取得向けではない |
公式の実行順は next.config の headers → redirects → Proxy → beforeFiles rewrites → ファイルシステムのルート(public/・app/ など)→ afterFiles → 動的ルート → fallback です。固定の転送を next.config に書くと、Proxy より先に処理されます。
Proxy で避けたいことと、代わりの方法
- DB への問い合わせ → Proxy はプリフェッチを含む多くのリクエストで動くため、Cookie だけで判定し、DB 確認はページ側に集約します。
fetchのキャッシュ指定 →cache・next.revalidate・next.tagsは Proxy では効かないため、ページ側で取得します。- グローバル変数での状態共有 → Proxy は描画コードと別に実行されるため、値はヘッダー・Cookie・URL で渡します。
- Proxy だけで守る設計 → matcher の変更で保護が外れることがあるため、Server Action・Route Handler の中でも認証・認可を確認します。
アクセスログの送信のようにレスポンスを待たせたくない処理は、proxy(request, event) の第2引数の event.waitUntil(promise) に渡すと、レスポンスを返した後も完了まで実行されます。
よくある質問
Q. middleware.ts のままでも動きますか? A. はい、Next.js 16.3.6 では非推奨警告が出るだけで動作しました。ただし名称は非推奨扱いなので、Edge Runtime が必須でなければ codemod で proxy.ts に移行しておくと、今後のアップデートがスムーズです。
Q. Proxy で Edge Runtime を使えますか?
A. 使えません。runtime: 'edge' を書くと「Proxy does not support Edge runtime」でビルドが止まります。公式は、Edge を使い続けたい場合は middleware.ts を使い続けるよう案内しており、Edge についての追加の案内は今後のマイナーリリースで示すとしています。
Q. Proxy の中で DB に問い合わせてもよいですか? A. 公式の認証ガイドは、Proxy ではセッションを Cookie から読むだけにして DB チェックを避けるよう案内しています。Node.js ランタイムなので技術的には書けますが、すべての対象リクエストで動く点を考えると、DB 確認はページや Server Action 側で行うのがおすすめです。
まとめ
- Next.js 16 で middleware.ts は proxy.ts に改名。変更点はファイル名と関数名の2つで、
npx @next/codemod@canary middleware-to-proxy .で自動変換できる - Proxy のランタイムは Node.js 固定。Edge が必要なら当面は middleware.ts を使い続ける(16.3.6 では警告のみで動作)
- ビルドエラーは 「runtime 指定」「2ファイル共存」「関数名のまま」 の3種を押さえれば直せる
- matcher は除外パターンとセットで。
(?!api|...)は/apikeyも除外するので、区切りまで書くと正確 - ヘッダーは
next({ request: { headers } })がサーバー向け、response.headersがブラウザ向け - Proxy は入口の振り分け役。固定リダイレクトは
next.config、セッションの本確認や DB 処理はページ・Server Action 側で行う
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「Next.js proxy.ts入門|middleware移行とmatcher実例」
株式会社RJCでは、フレームワークの仕様変更を実際に手を動かして確かめ、その結果をチームで共有しながら開発に活かしています。こうした知識を共有しながら、日々技術を磨いています。
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。