# Webレビューツール「PinRemark」に画像添付・ログイン状態・ビフォーアフター自動撮影を追加した話｜実案件で見えた3つの不足｜株式会社テクノスフィア

> 自社開発のWebレビューツールPinRemarkを実案件で約1か月半使い、見えてきた3つの不足を埋めました。指摘への画像複数添付（1コメント10枚・Ctrl+V貼り付け）、ログインで画面が変わるサイト向けのログイン状態の記録と警告、サーバー側Chromiumによる指摘時・返信時の画面自動撮影とビフォーアフター比較。実装の要点とハマりどころ、残る制約まで解説します。

URL: https://technosphere.co.jp/blog/pinremark-before-after-capture-update

** 目次
1. 実案件で使って見えた3つの不足
2. 不足①：指摘にスクリーンショットを付けたい
3. 不足②：ログインすると画面が変わる
4. 不足③：直す前と後を見比べたい
5. ハマりどころと残る制約
6. よくある質問（FAQ）
7. まとめ
   ** 本記事について

本記事は、当社が開発・運用しているWebレビューツール「PinRemark」の機能追加の記録です。PinRemarkの仕組み（リバースプロキシでウィジェットを注入する方式）は、前回の記事[「リバースプロキシ型Webレビューツールを自社開発した話」](https://technosphere.co.jp/blog/pinremark-reverse-proxy-review-tool)で解説しています。案件のサイト名は記載していません。

## 実案件で使って見えた3つの不足

 PinRemarkは、制作中のWebサイトを**お客様がブラウザで見ながら、直したい場所にピンを立ててコメントする**ためのツールです。2026年8月から当社のWeb制作案件で使い始め、これまでに複数の案件で500件を超える指摘がPinRemark上でやり取りされました。

 使い込むほど、「ピンとコメントだけでは伝えきれない場面」が見えてきます。運用の中で挙がった要望を整理すると、次の3つに集約されました。
- **参考画像やスクリーンショットを付けたい**——「この写真に差し替えて」「別のページのこの表示に合わせて」を文章だけで伝えるのは難しい
- **ログインすると画面が変わるサイトで、指摘の画面にたどり着けない**——会員向けマイページのあるサイトでは、同じURLでもログインの有無で表示が変わる
- **直す前と後を、あとから見比べたい**——「修正しました」と返しても、修正前の画面はもう残っていない

 以下、それぞれをどう機能にしたかを順に紹介します。

## 不足①：指摘にスクリーンショットを付けたい  （図: 複数の画像カードが矢印に沿ってコメントカードへ添付され、コメントの下にクリップのアイコンとサムネイルが並んでいるイメージイラスト）

 最初の指摘にも返信にも、**画像を1コメントあたり最大10枚**まで添付できるようにしました。添付の方法は3通りです。
| 方法 | 使いどころ |
| **「画像を添付」ボタン** | 手元の参考写真・デザインカンプを選ぶ（複数選択可） |
| **ドラッグ＆ドロップ** | デスクトップやフォルダから入力欄へそのまま落とす |
| **貼り付け（Ctrl+V／⌘+V）** | OSの機能で撮った画面キャプチャを、保存せずにそのまま貼る |

 特に便利なのが貼り付けです。画面キャプチャを撮ってコメント欄で貼るだけなので、ファイルを保存して探す手間がありません。クリップボードから来た画像は名前が付いていないため、「screenshot-日時」という名前を自動で付けています。

### 受け付ける画像は中身で判定する

 受け付けるのはPNG・JPEG・GIF・WebPで、1枚10MBまでです。形式はファイル名やブラウザが申告する種類ではなく、**ファイル先頭のバイト列**で判定しています。SVGは画像の中にスクリプトを埋め込めるため、見た目は画像でも受け付けません。

 アップロードは「画像を先に送って番号を受け取り、指摘や返信を送るときにその番号を添える」2段階にしています。途中で投稿をやめた画像は、24時間後に自動で片付けます。

## 不足②：ログインすると画面が変わる  （図: 同じWebページの2枚の画面が並び、会員バナーと開いた鍵のある左の画面にだけ赤いピンが立ち、閉じた鍵の右の画面には黄色い注意マークが浮かんでいるイメージイラスト）

 会員向けのマイページがあるサイトでは、同じトップページでも**ログイン中だけ会員向けのお知らせが出る**といった違いがあります。ログインした状態で立てたピンを、ログアウトした状態で開くと、画面の構成が違うので指摘の場所にたどり着けません。実際のレビューでも「ピンを選んでも、指摘したはずの画面が出てこない」ことが問題になりました。

 そこで、ピンを立てたときの**ログイン状態（ログイン中／ログアウト中）を一緒に記録**し、今の状態と違う指摘を開こうとしたときに知らせるようにしました。
- **バッジ表示**——一覧・詳細・管理画面の各指摘に「ログイン時」「ログアウト時」と表示
- **選んだときの警告**——状態の違う指摘を一覧から選ぶと「この指摘はログインした状態で登録されています。ログインしてからご確認ください。」と表示（ログアウトの場合も同様）
- **ページ上の案内**——状態の違う指摘は位置がずれるためピンを出さず、「ログインすると表示されます」と件数を添えて案内

### 「ログアウト」リンクだけでは判定できなかった

 ログイン状態はプロジェクトごとに「判定しない／自動／CSSセレクタ指定」から選びます。ログイン機能のないサイトには影響させたくないので、初期値は「判定しない」です。

 自動判定を作る際、当初は「画面に『ログアウト』リンクがあればログイン中」と考えていました。ところが実際の会員サイトを調べると、**ログイン中でもトップページには『ログアウト』リンクが無く、『〇〇さまマイページ』のリンクだけ**が出る作りでした。最終的に、次の順で判定しています。
| 順 | 画面にあるもの | 判定 |
| 1 | 「ログイン」だけのリンク・ボタン | ログアウト中 |
| 2 | 「ログアウト」のリンク・ボタン | ログイン中 |
| 3 | マイページへのリンク | ログイン中 |
| — | いずれも無い | 判定不能（区別しない） |

 自動判定が合わないサイト向けに、「ログイン中の画面にだけある要素」をCSSセレクタで指定する方法も用意しました。判定結果はピンを立てるフォームに初期値として入り、違っていれば指摘した方がその場で直せます。

## 不足③：直す前と後を見比べたい  （図: サーバーの箱からシャッターの光がブラウザ画面へ伸びて撮影し、要素がずれた修正前の画面と整った修正後の画面が矢印でつながって並ぶイメージイラスト）

 修正の確認では「どこがどう変わったか」を並べて見るのがいちばん早いのですが、指摘した時点の画面は、直した後にはもう残っていません。そこで、**ピンを立てたとき（指摘時）と、コメントを返したとき（返信時）に、そのページの画面を自動で撮影して保存**するようにしました。

 ピンの詳細で「ビフォーアフターを見る」を押すと、指摘時と返信時の画面が左右に並びます（スマートフォンでは上下）。返信が複数ある場合は、どの返信の時点と比べるかを選べます。管理画面のピン一覧にも、指摘時と最新の返信時の画面が並びます。

### 撮影はブラウザではなくサーバーで行う

 画面の撮影方法は2つ考えました。閲覧者のブラウザの中で画面を画像化する方法と、サーバー側で別のブラウザを動かして撮る方法です。前者はブラウザの機能だけで撮れる代わりに、描画の忠実さに限界があり、撮影のたびに許可を求められる方式もあります。

 決め手になったのは、**返信は人がブラウザから書くとは限らない**ことでした。当社では、修正を反映したあとの「修正しました」という返信を、AIエージェントがAPI経由で書き込むこともあります。サーバー側で撮れば、その返信の時点、つまり修正が反映された画面をアフターとして残せます。そのため、画面表示のないブラウザ（ヘッドレスChromium）をNode.jsから操作するpuppeteer-coreを採用しました。前回の記事で「依存パッケージは3つだけ」と書きましたが、これで4つになりました。

撮影の手順は次のとおりです。
- **同じ見え方で開く**——ピンを立てた方の画面幅・ブラウザ情報（PC／スマートフォン）でページを開く
- **ピンの位置に印を付ける**——ピンと同じ規則で要素を探して位置を求め、番号付きの印（範囲指定なら枠）を描く
- **ピンが見える位置で撮る**——ピンが画面の上から4割あたりに来るようスクロールして、表示範囲を撮影

 撮影は1件ずつ順番に処理し、サーバーの負荷を抑えています。本番環境での撮影時間は、指摘時が7秒（撮影用ブラウザの初回起動を含む）、返信時が4秒でした。撮影中のメモリ使用量は約230MBです。

## ハマりどころと残る制約

### 1. 前の撮影のログイン情報が、次の撮影に残っていた

 ログインが必要なページを撮るため、レビュー画面からの操作では閲覧者のCookie（ログイン情報）を撮影の間だけ使います。ところがテストで、**Cookieを持たないAPI経由の返信が、なぜかログイン状態で撮影される**現象が出ました。原因は、撮影用ブラウザを使い回していたために、前の撮影で渡したCookieがブラウザに残っていたことです。このままでは、別の人のログイン状態で撮影されかねません。

 撮影ごとに独立したブラウザ環境（シークレットウィンドウに相当）を作り、撮影が終わったら破棄するように直しました。

```
// 撮影ごとに独立したコンテキスト（Cookie・ストレージを他の撮影と共有しない）
const context = await browser.createBrowserContext();
const page = await context.newPage();
try {
  // ...閲覧者の Cookie をこのコンテキストにだけ設定して撮影...
} finally {
  await context.close();
}
```

### 2. サーバーが停止命令で止まらなくなった

 撮影用ブラウザを一度起動すると、サーバーが停止命令（SIGTERM）で終了しなくなりました。puppeteerはブラウザの後始末のために、既定で停止命令を自分で受け取ります。そのためNode.jsの標準の終了処理が働かず、このままではコンテナを止めるたびに、既定の10秒待たされたうえで強制終了されることになります。puppeteer側の処理を切り、サーバー側で「撮影用ブラウザを閉じてから終了する」処理を書いたところ、コンテナは**0.4秒で止まる**ようになりました。

### 3. 既存の配色が、文字の読みやすさの基準に届いていなかった

 当社では画面に手を入れたら、文字と背景のコントラスト（明暗差）を機械で検査してから完了にしています。今回の検査で、PinRemarkのボタンの白文字と赤背景が**3.91:1**で、Webアクセシビリティの基準WCAG AAが求める4.5:1に届いていないことが分かりました。赤をわずかに濃くして4.93:1にし、緑やグレーの文字も同様に調整しています。

### 残る制約
- **画面上の操作途中の状態は写らない**——撮影はページを開き直した状態なので、入力途中のフォームや開いたメニューは再現しない。必要な場合は手動でスクリーンショットを添付してもらう
- **API経由の返信はログアウト状態で撮影される**——閲覧者のCookieが無いため。ログインが必要な指摘では「ログアウト状態で撮影」と表示して区別している
- **機能追加より前のピンには指摘時の画面が無い**——今後の返信時の画面（アフター）からは残る
- **サーバーのイメージが大きくなった**——Chromiumと日本語フォントを入れたため、Dockerイメージが約220MBから約1GBに増えた

## よくある質問（FAQ）   Q. ビフォーアフターの画面は、指摘した人が自分で撮る必要がありますか？ A. 不要です。ピンを立てたときと、コメントを返したときに、PinRemarkのサーバーがそのページを自動で撮影して保存します。指摘した方と同じ画面幅・同じ端末（PC／スマートフォン）の表示で撮影し、ピンの位置に印を付けます。 Q. ログインが必要なページでも正しく撮影できますか？ A. レビュー画面から操作した場合は、その方のログイン状態のまま撮影します。ログイン情報（Cookie）は撮影の間だけ使い、保存はしません。ただしAPI経由の返信ではログインしていない状態で撮影されるため、画像に「ログアウト状態で撮影」と表示して区別しています。 Q. 指摘した時の画面をそのまま再現できますか？ A. 完全には再現しません。撮影はページを開き直した状態で行うため、入力途中のフォームや開いたメニューなど、画面上で操作した途中の状態は写りません。操作の途中を伝えたい場合は、ご自身で撮ったスクリーンショットを貼り付けて添付していただく運用と併用しています。

## まとめ

 実案件で500件を超える指摘をやり取りする中で見えた3つの不足を、**画像の複数添付（1コメント10枚・貼り付け対応）**、**ログイン状態の記録と警告**、**指摘時・返信時の自動撮影とビフォーアフター比較**として埋めました。撮影ではブラウザの使い回しによるCookieの持ち越しという、見落とすと別の人のログイン状態で撮影しかねない問題にも行き当たりました。

 社内ツールは、使い始めてから「本当に必要なもの」が見えてきます。最初から作り込みすぎず、実際の使われ方を見ながら小さく足していく進め方が、今回もうまく機能しました。

 当社では、PinRemarkを使ったレビューを含めて、Webサイトの制作から公開後の改善まで一貫して対応しています。「修正のやり取りに時間がかかっている」「社内の確認フローをWebで整えたい」という段階のご相談も歓迎です。    [技術コラム一覧に戻る](https://technosphere.co.jp/blog/)
