OmniAICreator/Qiita-1.07M huggingface dataset:
【最速】Azureでtsuzumiをデプロイし利用できるようにするまで



日本語に特化したNTTの生成AI「tsuzumi」のデプロイ方法について書いています。
「難しいことはわからないけど、とにかく最速でtsuzumiを使いたいよー」という方に向けて書いています。

## はじめに
自己紹介やAzure AIについての概要を書いています。併せてお読みください。

https://qiita.com/5ugimotoh/items/3222f9411cd1a12fb9ca

ここでは、Azureのモデルカタログに新しく加わった「tsuzumi」をデプロイする方法について簡単にまとめています。

## tsuzumiのデプロイ
手順のみ簡潔に説明していきます。

:::note info
この説明ではAzure利用経験が1度でもある方を対象としています。
アカウントやサブスクリプションの登録方法等については別途お調べ下さい。
:::
---
1. Azure Portalを開きます
2. **「リソースの作成」** から検索で「tsuzumi」と入力します

3. 検索結果の **「NTTDATA tsuzumi-7B Instruct」** を選択し、**「購読する」** を押下します
![スクリーンショット (8).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3827807/5b2dac0c-a102-9985-c93e-8ec38d899e13.png)

4. **「Azure AI モデルカタログに進む」** を押下します
![スクリーンショット (10).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3827807/cb87551f-f92c-733d-214b-f73e2482ab97.png)

5. Azure AI Studio改め **Azure AI Foundry** のモデルカタログページへ遷移したら、表示されているtsuzumiのモデルをデプロイします
![スクリーンショット (11).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3827807/3863e979-c642-6d85-1cdd-167416c8a339.png)

6. ここで、モデルカタログにあるモデル利用のためには **「プロジェクト」** を作成しなくてはならないため、新しいプロジェクトを作成します
![スクリーンショット (12).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3827807/061ba165-932d-5ca3-b4b6-ca0d5eb38d10.png)

7. ここでは以下のように項目を入力し、プロジェクトを作成します
![スクリーンショット (13).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3827807/4ec35459-7aea-cb54-0dc2-3d4969620da5.png)

    **プロジェクト名** ：tsuzumi-deploy（名称任意）
    **ハブ名** ：tsuzumi-01（名称任意）
    **サブスクリプション** ：（既存のものを選択）
    **リソースグループ** ：（既存のものを選択、または新規作成）
    **場所** ：East US 2（日本だと利用できません）
    **Azure AIサービスまたはAzure OpenAIを接続する** ：（新規作成）
    **Azure AI検索に接続する** ：（スキップ）
    <br>
8. 少し経って画面が **「tsuzumi用のサーバーレスAPIデプロイ」** に切り替わったら、 **「サブスクライブとデプロイ」** を押下します
![スクリーンショット (14).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3827807/b47fafec-30ac-d69d-671a-28af4713f7e8.png)

9. 少しして **「tsuzumiをデプロイ」** 画面になったら **「デプロイ」** を押下します
![スクリーンショット (15).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3827807/c622cc64-ba0a-70ca-ec67-a7059b28d4f9.png)

![スクリーンショット (16).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3827807/2dffef51-440a-331f-4a9e-2b5df94e4876.png)

10. これでデプロイが完了し、Azure AI Foundryのプロジェクト内でモデルを動かせるようになりました。チャットボット機能を利用するには **「プレイグラウンドで開く」** を押下します
![スクリーンショット (17).png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3827807/586ca435-d03d-cc5b-87c3-cd3c38cc16fc.png)

11. チャットボットとしてtsuzumiを利用できます
---

## おわりに
Azureでtsuzumiを利用する方法が分かりました。
少し前から、仕様がいろいろと変わっているため、いきなり利用しようとすると混乱するかと思います。
Azure上で手軽にtsuzumiを使いたいという人は参考にしてみてください。

tsuzumiはAzure上でリリースされてからまだ日の浅いモデルです。
説明の足りない部分もあるかと思いますので、補足や修正、追記事項等いつでもお待ちしています。


参考文献
[Microsoft Azure上でNTT版LLM「tsuzumi」を2024年11月20日に提供開始](https://www.nttdata.com/global/ja/news/topics/2024/112000/ "Microsoft Azure上でNTT版LLM「tsuzumi」を2024年11月20日に提供開始")
[忘備録] batファイルをタスクバーに固定したい

## 前提
Windows11でbatファイルをタスクバーにピン止めしたいが、
デフォルトだと不可なので何とかする方法


## 1.ショートカットの作成
デスクトップでショートカットを作成する

## 2.リンク先を変更

バッチファイルのリンク先に、cmd /cを追加して、バッチファイルを"で囲う
cmd /c

例えば、ファイルが以下にあるなら
```
C:\project\app.bat
```

以下のようにすると良い。
```
cmd /c "C:\project\app.bat"
```

## 3.ピン止め
タスクバーにピン止め可能となる。
PDE（Professional Data Engineer）不合格の反省

## PDE不合格の要因分析：躓きポイント
 ### 過去の問題集を使用していた
 
 - 下記2つのudemyで主に学習していたが、2024年1月に試験範囲が変更されていた
 
     - [【最短攻略】Google Cloud 認定 Professional Data Engineer 模擬問題集](https://www.udemy.com/share/106gbA3@F7lv0RGOCbMwHQBDCx3T6YO9yGVjA-FKFOLA2lrRvUwyiO0UNveQY56H31Pf9-AyYw==/)
    
     - [Google Cloud認定 Professional Data Engineer（PDE） トレーニング](https://www.udemy.com/share/109eaS3@cm0q380XEyrrfUZ5D2ejxFk6g4LygUT19ie6J1AqSP5GIJkN-3lJtq7P_NMLay1NLw==/)  
     
  -  追加された下記のデータ分析サービスに対しての知識がなかった
        -  データメッシュ関連（Dataplex、Data Catalog）
        -  Datastream
        -  Dataform
        -  Workflows
        -  Analytics Hub
        -  BigQuery Omni
        -  BigLake

        本番の試験問題で初めてみるサービスが多く、感覚的に90%初見の問題だった。おそらく50%も本番でとれていないと思う。上記の問題集がでていたらギリ70%とれていたかなという感じだった。
        公式問題も解いたが、そこでも上記サービスに対する問題はなかったので、過去の問題集と公式問題集の勉強方法では不十分だった。
        
### その他の要因 (メンタル面、時間管理)
オンライン試験での受験で（年末で受験する人が多いのか？）試験開始までに、約１時間半かかった（６０人待ち）。
    ２時間の試験で、２時間あれば足りるだろうと予定を組んでいたため、結果的に２時間半以上かかり、かなり焦って試験を受けることになった。

## 再挑戦に向けて：学習プランと戦略

1. 下記のサービスについてSkills Boostを使用して、公式のハンズオンや動画学習をする

    - データメッシュ関連（Dataplex、Data Catalog）
    - Datastream
    - Dataform
    - Workflows
    - Analytics Hub
    - BigQuery Omni、BigLake
    
2. 下記のUdemyの問題集（2024年度対応）を解く
[GCP Professional Data Engineer Exam Practice Tests - 2024](https://www.udemy.com/share/10bEu33@oTM_dAqkETACwkYZ-NqzaywT2EJNog77fSmOHGlTJBu9ZIrr8g6DiW9iSYRXLFS4jw==/)

3. 不正解の部分はGoogle Cloudの公式ドキュメントで確認する

4. オンラインではなく、試験会場で受ける


## PDEを受ける人へ
公式の模擬問題や過去のUdemyの問題集では、試験対策として不足していました。
それらよりもGoogle Cloud公式のSkills BoostやCourseraを使用した方がよさそうです。
Udemyを購入する際は、最新のサービスが反映されているかやレビューを確認した方がよかったです。
また、オンライン試験は現在（2024年11月）とても混んでいるので時間に余裕をもって受験した方がいいです。


## 今後の予定
 再受験ポリシーがあり２週間は受験できないため、最短で12月2週目くらいに再トライする予定。遅くとも今年中には再トライする。次不合格だと、再受験に2ヶ月かかり、さらに4回目は1年後なので非常に厳しくなる模様。
IBM API Connectの製品とAPIに x-embedded-doc を使って、ドキュメントを追加する

# IBM API Connectの製品とAPIにx-embedded-doc を使って、ドキュメントを追加する
IBM API Connectでは、APIの仕様を公開するために、開発者ポータルという機能があります。
開発者ポータルでは、APIの概要（APIのタイプ、プロトコル、エンドポイント、セキュリティー）や、アクセスするURLやメソッド（GET,POST,PUT,DELETE)及び、プロパティ定義などが参照できるようになっています。

以下は、開発者ポータルのAPI仕様の画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3928184/4ecab832-4308-55af-e761-fb686af4a7a3.png)

この開発者ポータルのAPIのドキュメントに、x-embedded-docを利用してドキュメントを追加することが可能になっています。
API ConnectでAPIを定義すると、API Swaggerドキュメントができます。このAPI Swaggerドキュメントに追加のドキュメンテーション・ページを組み込むことが可能です。
ページの html コンテンツの Base64 エンコードされたストリング、またはマークダウン・ストリングです。 
これらのページは、左側のナビゲーションで、その製品または API の概要の下かつパスの上に表示されます。

## 製品および API の組み込みドキュメンテーション
製品または API の仕様に追加の x-embedded-doc オブジェクトを指定することで、個々の製品や API にドキュメントを組み込むことができます。


| フィールド名 | タイプ | 説明 |
| :-----------: | :------: | ----|
| 名前        | string | (必須) 組み込みドキュメントの名前|
| タイトル | string | (必須) 組み込みドキュメントの表示タイトル|
| 形式 | string | (オプション) 組み込みドキュメントのコンテンツ値の形式。<br> 値はb64htmlまたはmdです。 デフォルト値は md です。|
| コンテンツ | string | ページの Base64 エンコードされた html、またはマークダウン・ストリング。|
| 資料 | x-embedded-doc | 追加の組み込みドキュメンテーション。 親にコンテンツが指定されていない場合は、最初の子がコンテンツとして表示されます。|

## x-embedded-docの使用例
例として、下記のようなx-embedded-docをGlobalWeatherというAPIに組み込んでみます。

```
x-embedded-doc:
  - name: 紹介
    title: 紹介
    format: md
    content: '# マークダウンで記述'
  - name: concepts
    title: Concepts
    format: md
    content: |-
      ## Overview
      #### Philosophy 
      API仕様に関する補足情報をMarkdown形式で記載できます。

      ***
      - 
      1. 番号   
        2. 番号   
      `backslash`  
      > 引用です<br> *引用です*
      >> **2つの引用です**
  - name: authentication
    title: Authentication
    docs:
      - name: auth_clientid_secret
        title: Obtaining a Client ID and Secret
        format: md
        content: '### Client IDとSecretを取得する方法を記載'
      - name: auth_bearertoken
        title: Getting and Using a Bearer Token
        format: md
        content: '#### Bearer Tokenの取得と使い方を記載'
```

## API ManagerのAPI定義画面のソースに定義します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3928184/ef12126c-4c72-1a67-0071-1b238324e0c3.png)

## APIを公開します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3928184/425298c5-26be-ee60-bc17-6e24d58a66fc.png)

## 開発者ポータルから確認します
開発者ポータルから、GlobalWeatherのAPIを開いてみると、左側に新しく情報が追加されていることがわかります。以下の三つの項目が追加されています。
* 紹介
* Concept
* Authentication
  *  Obtaining a Client ID and Secret
  *  Getting and Using a Bearer Token

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3928184/4b974088-23f2-ed2e-7f50-ef7ef77922b7.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3928184/2d2f2a76-ee43-0661-4f0c-e2a57cbe81f3.png)


<strong>以上のように、API Connectの開発者ポータルに追加のドキュメントを記載するには、x-embedded-docを使うことで簡単に公開することが可能です。</strong>
インタードメイン・トラフィック・エンジニアリング

# BGPではネットワーク・プロトコルのパラメータと構成を調整する
>ネットワーク運営会社は、`使用率と輻輳を管理するため、ネットワーク・プロトコルのパラメータと構成を調整する`必要があることがよくある。このような`トラフィック・エンジニアリング`はBGPでよく行われている。
### ネットワークに入ってくる制御と出ていく制御を行う
>そこでは、ネットワークの運営会社がBGPのルートを選択する方法を制御して、`ネットワークに入ってくるトラフィックを制御（インバウンド・トラフィック・エンジニアリング）`したり、`ネットワークから出ていくトラフィックを制御（アウトバウンド・トラフィック・エンジニアリング）`したりしたいと思うかもしれない。

# 具体的な調整
>最も一般的な方法は、ルーターが`個々のルートに対してローカルな優先順位属性を設定`する方法を調整することである。例えば、特定の顧客ASから学習したすべてのルートに対して高いローカルな優先順位を設定することにより、ネットワークの運営会社は、`顧客ルートが存在するときはいつでもトランジットのルートよりもその顧客のルートが選択`されるようにすることができる。

### 他ASに対してルーターに間接的な信号を送り、制御する
>BGPは、`あるASが他のASにルートの選択方法を支持できない`ため、インバウンド・トラフィック・エンジニアリングはよりトリッキーなところがある。それゆえに`自律的という名前`がついている）。それでも、`ネットワークの運営会社は隣接するネットワークのルーターに間接的な信号`を送り、これらのルーターがどのようにルートを選択するかを制御することができる。

# 自律の意味
>他からの支配・制約などを受けずに、自分自身で立てた規範に従って行動すること。「—の精神を養う」⇔他律。

https://dictionary.goo.ne.jp/word/%E8%87%AA%E5%BE%8B/#:~:text=%E4%BB%96%E3%81%8B%E3%82%89%E3%81%AE%E6%94%AF%E9%85%8D%E3%83%BB%E5%88%B6%E7%B4%84%E3%81%AA%E3%81%A9%E3%82%92%E5%8F%97%E3%81%91%E3%81%9A%E3%81%AB%E3%80%81%E8%87%AA%E5%88%86%E8%87%AA%E8%BA%AB%E3%81%A7%E7%AB%8B%E3%81%A6%E3%81%9F%E8%A6%8F%E7%AF%84%E3%81%AB%E5%BE%93%E3%81%A3%E3%81%A6%E8%A1%8C%E5%8B%95%E3%81%99%E3%82%8B%E3%81%93%E3%81%A8%E3%80%82%E3%80%8C%E2%80%94%E3%81%AE%E7%B2%BE%E7%A5%9E%E3%82%92%E9%A4%8A%E3%81%86%E3%80%8D%E2%87%94%E4%BB%96%E5%BE%8B%E3%80%82

# 感想
BGPは初めて学んだ。
理解できていないことが多いので理解したい
【学習】インプットとアウトプットについて

## はじめに
プログラミングスクールにてプログラミングを学び始めたとき、情報の多さに圧倒される一方で、学んだことを活かしきれていないと感じることが多々ありました。そこで、『インプット』と『アウトプット』のバランスを意識して取り組むようにしました。本記事では、私が実践している（していた？）具体的な方法や気づきを共有したいと思います。

## ますはインプットとアウトプットについて
インプットとアウトプットの説明については記事参照になります。
### インプットとは
> インプットとは、日本語で「入力」という意味があり、新しい情報やスキルを身に付けることです。
たとえば、資格試験の勉強で、テキストに記載されている知識をインプットしたり、実技試験の動作を学習したりする際に用いられます。
また、社会人になっても、営業の仕方やプレゼンテーションのトークなどをインプットする場面が多くあります。
インプットを正確におこなわないと、間違った情報や知識を吸収してしまうだけでなく、仕事でのミスにもつながります。

https://go.chatwork.com/ja/column/business_chat/business-chat-191.html

### アウトプットとは
> アウトプットは、「出力」という意味で、インプットで身に付けた情報や動作を活かすことを指します。
インプットの例に加えると、テキストで学んだことを模擬試験や本試験で発揮することが、アウトプットに該当します。
同様に、ビジネスシーンでも、顧客先との商談でトーク力を発揮したり、マニュアルで学習した知識を仕事に活かせるように、さまざまな場面でアウトプットが求められます。
このように、インプットで知識や情報を吸収したあとに、アウトプットをおこないます。
アウトプットは記憶に定着させることが目的であり、反復的に実施する必要があります。


## 私自身が行っていたインプットとアウトプット
### インプット
　学びの出発点である「インプット」。私自身、プログラミングスクールで提供されるモノだけでなく、公式ドキュメントやオープンソースのコードを読み解くことで、自分の知識を広げてきました。特に、わからない単語にであったときは放置せず、すぐ検索する癖をつけることで、効率的に知識を吸収できるようになりました。
　また、しばらくしてから、調べた単語にもう一度遭遇した際は「前確か調べたような気がするからいいか」ではなく、時間はかかりますが再度調べることも徹底して行うようにしていました。
 一度見ただけでは覚えられない用語。

### アウトプット
自分が本当に理解しているかを確かめる良い機会である「アウトプット」。私は学んだことをNotionにまとめていました。例えば、実装の流れやポイント、わからない用語等を記録していました。また特定のエラーに関する解決方法をQiitaに記事として投稿することで、一度情報が整理され、どんな風に解決したか後から見返すことができ、同じような問題に直面した際の迅速な対応が可能になりました。

## おわりに
学習当初はインプットばかりをしていました。ですがアウトプットを意識することで、学習の効率が格段に上がることを実感しました。notionなどにまとめることで後から見返すことができるというのは意味のあるものだと思っています。（notionを始めるタイミングが私自身遅かったので少し後悔）
今後はさらにアウトプットの頻度を増やし、他の人に役立つ情報を発信していきたいと思います。この記事が、同じように学習中の方々の参考になれば幸いです。
free_null()

```c: free_null.c
#include <stdlib.h> // free()
#include <stdbool.h> // bool, true, false

bool free_null(void **ptr)
{
    if (ptr && *ptr) {
        free(*ptr);
        *ptr = NULL;
        return true;
    }
    return false;
}
```
コメントで書いていただいたマクロ
```c: free_null_macro.c
#include <stdlib.h> // free()

#define FreeNull(ptr) do {free(ptr); ptr = NULL;} while (0)
```
ダブルポインタ版
```c: free_null_dptr.c
#include <stdlib.h> // free()
#include <stdbool.h> // bool, true, false

bool free_null_dptr(void ***ptr)
{
    if (ptr && *ptr) {
        void **current = *ptr;

        while (*current) {
            free(*current);
            *current = NULL;
            current++;
        }
        free(*ptr);
        *ptr = NULL;
        return true;
    }
    return false;
}
```
別パターン
```c: free_null_dptr.c
#include <stdlib.h> // free()
#include <stdbool.h> // bool, true, false

bool free_null_dptr(void ***ptr)
{
    if (ptr && *ptr) {
        size_t i = 0;

        while ((*ptr)[i]) {
            free((*ptr)[i]);
            (*ptr)[i] = NULL;
            i++;
        }
        free(*ptr);
        *ptr = NULL;
        return true;
    }
    return false;
}
```
シングルポインタ用 `free_null()` とダブルポインタ用 `free_null_dptr()` を合わせたもの
```c: free_null.c
#include <stdlib.h> // free()
#include <stdbool.h> // bool, true, false

bool free_null(void **ptr)
{
    if (ptr && *ptr) {
        free(*ptr);
        *ptr = NULL;
        return true;
    }
    return false;
}

bool free_null_dptr(void ***ptr)
{
    if (ptr && *ptr) {
        void **current = *ptr;

        while (*current) {
            free_null(current); // = free_null(&*current);
            current++;
        }
        free(*ptr);
        *ptr = NULL;
        return true;
    }
    return false;
}
```
別パターン
```c: free_null.c
bool free_null_dptr(void ***ptr)
{
    if (ptr && *ptr) {
        size_t i = 0;

        while ((*ptr)[i]) {
            free_null(&((*ptr)[i]));
            i++;
        }
        free(*ptr);
        *ptr = NULL;
        return true;
    }
    return false;
}
```
SnowPro Core 受けてみた❄❄❄

# はじめに
Snowflake歴 約1年のエンジニアによるSnowPro Core Certification(※) の受験記です。個人の感想や気づきがメインです！
試験対策についてはより詳しい記事が世の中にたくさんあると思うので、そちらもご覧ください！

※SnowPro Core Certification：Snowflakeの認定資格の中で入門編といわれる認定資格 



# 試験形式
最新の情報は[こちら](https://learn.snowflake.com/en/certifications/snowpro-core-jpn%20/
)から

問題数: 100
問題の種類： 複数選択（私が受けたときは2つ選択でした）、多肢選択
制限時間： 115分
言語： 日本語
登録料： 175米ドル
合格点： 750点以上 



# 勉強法

試験前の私の状態：Snowflakeを約1年業務（開発）で使用
なんとなく機能は理解したつもりで、機能についての講座というよりも模試をどんどん解きたいタイプでした。その上で実践した勉強法を紹介します。

※初めて触るのであれば公式が提供しているハンズオンやUdemyの講義形式のコンテンツがよさそう

### 実践したこと

① Udemyの問題集を解く
色んな体験記を見ておすすめされていた[こちらの問題集](https://www.udemy.com/course/snowflake-snowpro-core-certification-exam-practice-sets)をひたすら繰り返しました。
問題文は英語なので適宜翻訳しながら解くのが良いと思います。内容的には、実際の試験で"これやったな～"みたいなものが結構あったので良い練習になったなと思います！


② ガイドラインにあてはまる公式サイトのページを読む
模試だけだと不安 + 飽きるので読み物もしました。
ガイドラインと該当するページをリンクさせてまとめてくれている[神サイト](https://blog.truestar.co.jp/snowflake/20231006/56553/)（感謝！）を見つけたので、気分転換に読んでいました。




# 所感
## 難しい、、、
1年触っていたのでイメージできることが多い反面、過信していました。正直難しかったです。全部回答した後、"落ちた、、、"と感じており復習の準備を始めていました。
業務で触ったことのない部分が練習問題でも出ていたのですが、公式サイトの説明の読み込みが足りなかったなと感じました。

業務で関わっていないところ、関わっていても過信してあまり理解できていなかった部分です↓ 何かの参考になれば
### 復習用

* 履歴系
何を見るか、どんな場面で役立つか、データの保持期間や用途
* クラスタリング
* マイクロパーティション
パーティショニング
パーティションキー
* クエリプロファイル
何を見るか、どんな場面で役立つか
* ロード/アンロード
JSON形式
VARIANT列
* セキュアビューの利用用途
* ストリーム
 

## 新しい発見！
前述した理解できていなかった部分に関して、テスト後に復習をしていたところめちゃくちゃ勉強になりました。

特に、**マイクロパーティション**です。
これはファイルの単位のことで、読んで字のごとくデータがとても細かく分割されてる状態なのですが、その分割する作業（=パーティショニング※後述）を自動且つ最適化する機能がSnowflakeにはあります。
自動なので、Snowflakeを触っていてそれを実感することは**全く**ないです。

　

**でも、テストに出るんです、、、！**（そりゃあそうですよね）



ユーザーが意識しない裏側もテストに出るのは製品の認定試験と考えれば当たり前ですよね。反省。。。
　

### そもそも

パーティショニングとは
* データを複数ファイルに分割して持つこと
* 分割して持つことで並列して取れるので大量のデータを高速で処理できる

パーティションキーとは
* パーティショニングに使われるカラム
* 何単位（カラム）でファイルを分けるかを決めるもの
* 何を設定するかがデータベースの処理性能やコストを左右する
* ★何を設定するのがベストか自分で検証して設定する
* ★データが増えたり使い方が変化（抽出条件や結合条件の変更）する度にパーティションキーも場合によっては変える必要がある
（→★の作業はデータエンジニアの仕事で最も手間と時間がかかる業務の一つだそうです）



「データウェアハウスといえばパーティショニング」というほど当たり前の技術要素だそうで、私は最初に触ったデータウェアハウス製品がこれを自動化するSnowflakeだったため、この存在を意識することなく生きて来られました。
Snowflakeはそれを細かく分割するのを、自動で + 最適に行ってくれるところ（★の作業を代行してくれる）が、ユーザーにとっては嬉しいポイントなんですね！
マイクロパーティション参考: https://docs.snowflake.com/ja/user-guide/tables-clustering-micropartitions

　
これらを知らずにデータウェアハウスを触っていたことに、まだまだ知らないことだらけだと思ったと同時に、製品のすごさを知りました。

# おわりに
最近色々なものが自動で処理されたり、クラウドにおいて「マネージドです」というものが多く便利になってきましたが、その仕組みやその機能ができた経緯を知らないことって結構あるのではないかなと思います。
この試験を通してそれを痛感しました！

結果として、テストに合格できたことも嬉しいのですが、こういう気づきを得たことにとても意味があったなと思います。

正直知らなくても困らないですが、知っている今では世界がものすごく広がったなと感じたので、この気持ちを忘れないためにも記事にしました。




最後までお付き合いいただきありがとうございました！
Style-Bert-VITS2をローカルで動かす

## 概要
Style-Bert-VITS2をWindows11でインストールしたときのメモ
音声の学習とTTS（Text-to-Speech）が可能で日本語のTTSが自然と言われているモデル。
https://github.com/litagin02/Style-Bert-VITS2

## この記事の対象者
Style-Bert-VITS2の推奨ハードウェア要件を満たしており、
かつ、以下の用語を理解できる人
```
git, pip, venv, winget
```
## Style-Bert-VITS2の推奨ハードウェア要件

Pythonのバージョン: Python 3.8 ~ 3.11
3.12の場合はエラーが出る。
使用ディスク量: 約11.16GBの空き容量が必要です。
RAMの使用量: 最低1.8GBのRAMが必要ですが、より快適に動作させるためにはそれ以上の容量を推奨します。
GPU: NVIDIA GPUが推奨されており、特にCUDA対応のものであれば性能が向上します。具体的には、RTX 3000シリーズ以上が望ましいとされています。
学習データ: 学習に必要な音声データやモデルファイルを保存するための十分なストレージが必要です。特に音声合成モデルを使用する場合、大量のデータを扱うため、ストレージ容量は重要です。

これらの要件は、Style-Bert-VITS2を効果的に運用するために必要な基本的なハードウェアスペックです。特にGPUの性能は音声合成処理に大きく影響するため、可能であれば高性能なGPUを使用することが推奨されます

## 下準備
任意の階層にffmpegをインストール
```
winget install ffmpeg
```
パスを通す
```
・「スタート」メニューから「設定」を開きます。
・「システム」>「詳細情報」>「システムの詳細設定」をクリックします。
・「環境変数」をクリックします。
・「システム環境変数」の「Path」を選択し、「編集」をクリックします。
・「新規」をクリックし、FFmpeg の実行ファイル (ffmpeg.exe) が含まれているディレクトリのパスを入力します。
・「OK」をクリックしてすべてのウィンドウを閉じます。
```

## 1.gitをクローン
***パスに日本語や空白が含まれない場所***にダウンロードして展開します。
```
 git clone https://github.com/litagin02/Style-Bert-VITS2.git
```

## 2.仮想環境を作成し、アクティベーション

```
cd Style-Bert-VITS2
```
```
python -m venv venv
```
```
.\venv\Scripts\Activate.ps1
```

## 3.依存関係をインストール
```
pip install -r requirements.txt
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3908981/39593ca8-487d-1f5f-12e0-77072398d86a.png)



## 4.初期化
```
python initialize.py
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3908981/992b65e5-55d7-8c71-aa56-5fd271b36c98.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3908981/fec91588-8710-cd68-11f2-34ec118067ab.png)


## 5.起動
Style-Bert-VITS2ディレクトリ配下にある
Editor.batというファイルをダブルクリック
または以下コマンドでTTS用のWebUIを起動できます。
```
python server_editor.py --inbrowser
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3908981/d089d9c2-d494-9704-4d2b-700a1529c0e4.png)

Style-Bert-VITS2ディレクトリ配下にある
App.batというファイルをダブルクリック、
または以下コマンドで学習用のWebUIを起動できます。
```
python app.py
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3908981/6dde68bc-97bc-7430-48f4-efb2b28c55b5.png)

ロード => テキスト入力欄に読ませたいテキストを入力 => 音声合成 で音声を読ませることができます。
モデル一覧から好きなモデルを選ぶこともできます。いろんな声を試してみてね！
初めてRubyバージョンアップをやったので、せっかくだからまとめる

ジョブカン事業部のアドベントカレンダー6日目です！

https://qiita.com/advent-calendar/2024/jobcan

昨日に引き続き、DONUTS札幌オフィスでジョブカン採用管理の開発インターンをしている@knotです。

新・RPG ジョブ診断が流行っている:thinking:のでやってみました。リスクマネジメントが強みらしいです。

https://rpg-shindan.wantedly.com/result/ac4af/

ということで、今回は~~リスクマネジメントの一環として~~Rubyバージョンアップを任せて頂けたので、この機会にやったこと・感想ナドナドを雑にまとめてみようと思います。

# バージョンアップの概要

ジョブカン採用管理では、`Ruby`を採用しています。

今回は`Ruby 3.1系`から`Ruby 3.2系`へのバージョンアップに挑戦しました。

# なんでバージョンアップしなきゃいけないの？

せっかくなのでバージョンアップをする理由から、考えをまとめてみます。

以下の3観点が主かと思います。
- バグ修正
- セキュリティ向上
- 新機能の追加

言語側が原因のバグを踏んで万が一サービスが止まったりしてしまったら大変ですし、脆弱性を放置し続けたせいで何らかのセキュリティ事故が起こってしまうのは怖いです。したがって、言語アップデートによるバグ修正とセキュリティ向上は、長く使われるソフトウェアにとって大切なことだと思います。
また、言語の新機能追加は、新機能の開発やリファクタリングなどの役に立つかもしれません。

# やったこと

## 現在の安定版を調べる

[Rubyのダウンロードページ](https://www.ruby-lang.org/ja/downloads/)に現在の安定版が載っているので、まずこちらを確認しました。

現在は`3.2.6`と`3.3.6`が安定版のようです。

## Ruby 3.2.0からの変更点を知り、調査する

### Ruby 3.2.0のリリースノートを読む

[Ruby 3.2.0のリリースノート](https://www.ruby-lang.org/ja/news/2022/12/25/ruby-3-2-0-released/)を読みに行きました。
(日本語でリリースノートを解説している記事もあったので、併せて参考にしました)

3.2.0のリリースノートには、マイナーバージョンが上がるにあたっての変更点がいろいろ書いてあります。メソッドや定数の削除や、今回だと3rdパーティライブラリの同梱廃止などもあるので、影響がありそうなものには注意します。

### ソースコードに影響があるものがないか調査する

リリースノートに書いてあったもので、動作に影響があるものはないか調査しました。
今回は`3.1 -> 3.2`なので、例えば`File.exists?`や`Kernel#=~`を使用していないかを調べることになります。(`Kernel#=~`は`{変数} =~ /hoge/`のパターンがあるのでわかりにくい)

## Gemをバージョンアップする

使用しているGemがRubyのバージョンアップの影響を受けて動かなくなってしまっては困るので、対象になりそうなGemを調査してバージョンアップをかけます。

### Gemの調査

[RubyGems](https://rubygems.org/)で使用しているGemのリポジトリを探して、リリースノートなどを読みました。Ruby 3.2への対応をしているGemがあれば、そのGemのバージョンを上げます。
また、CIなどの設定にRuby 3.2が追加されている場合もRuby 3.2での動作が保証されているということになるので、Gemを該当のバージョンへ上げるようにします。

## Rubyのバージョンを上げる

Gemのバージョンアップを済ませたら、Rubyのバージョンを上げます。
バージョンの上げ方は環境によっていろいろあると思うので、`rbenv`なりimageのバージョンを変えるなりして上げましょう。

### 動作確認する

バージョンアップができたら、動作確認をします。
RSpecを回してバージョンアップが原因でテストが落ちたりしないか確認します。また、RSpecや手動で動作確認しているときに、ログに警告などが出てこないかにも注意します。

# おわり

ここまでできれば作業は終了です。

# まとめ・感想

こうして書いてみるとそこまで量がありませんでしたが、初めてだったこともあり中々カロリー高めではありました。Rubyバージョンアップを通して感想や勉強になったこと書いてみます。

### OSSへのコントリビュート勘所がなんとなくわかる

あらゆるGemのリポジトリを見て回るので、リリースノートやプルリクからどんな感じでコントリビュートされているかがわかりました。ドキュメントのリンクが壊れていたから直したというような簡単なものから、がっつり機能追加している難易度の高そうなものまでありました。また、OSS開発にもいろいろ事情があるということも知ることができました。

### ユニットテストのありがたみ

ユニットテスト(RSpec)が用意されていれば、Rubyバージョンアップの影響確認がかなり楽にできるということがわかりました。これからもサボらずユニットテストは書いていこうと思います。

### 普段見る機会のない箇所への理解

影響確認のために、普段見ないところの内部処理を見に行くことがあります。Gemのちょっと深いところを見たりもしたので、自分のプロジェクトやGemのあまり見ないところを見ることができて勉強になりました。

### 使用しているGemについての知識

前の項目と被るところがありますが、プロジェクトで使用しているGemについていろいろ知ることができました。名前だけは見たことあるけど具体的な使い方を知らなかったものや、めったに登場しなくてほとんど何も知らないGemについてもいくらか触れる機会があるので、こちらも勉強になりました。

# さいごに

DONUTSでは新卒中途問わず積極的に採用活動を行っています。
インフラエンジニアの募集などもあるので、ご興味あればぜひご覧ください！

https://recruit.jobcan.jp/donuts/job_offers/1396392?hide_breadcrumb=false&hide_search=false

https://recruit.jobcan.jp/donuts/job_offers/1396393?hide_breadcrumb=false&hide_search=false
pythonにおける並列処理と並行処理

並列処理についての個人的なまとめ。
## CPUバウンドとI/Oバウンド
- 科学計算を行う様なプログラムでディスクとの入出力は行わない、計算に時間がかなりかかり、cpuに負担をかけるようなプログラム→`CPUバウンド`
例：数学演算、画像処理、ビデオ処理
- データが大量に保存されたディスクから任意のドキュメントを返すようなプログラム、CPUでの処理は少ない→`IOバウンド`
APサーバーは一般的にCPUバウンドになりがち、反対にDBサーバーはIOバウンドになりがち
例：ファイルの読み書きやネットワークからの応答待ち

## 識別方法
- CPUバウンド
    - cpu使用率が常に高いのに、アプリケーションの処理速度が低下している場合
    - マルチスレッドの処理の効果が低い場合
- IOバウンド
    - cpuの使用率が低い場合
    - ディスクの使用率やネットワークのトラフィックが高い場合
    - I/O待機時間が長い、システムがデータの読み書きを待っている時間が長い場合
## それぞれの対処法
- CPUバウンド
　プロセスの進行速度がcpuの速度によって制限されているので、コアの周波数をより高くするか、並列化して1コアでなく複数コアで処理する
 コア数以上の並列化を行ってしまうとコンテキストスイッチの時間がかかってしまうので、基本的に並列化はコア数程度にしとくといいらしい
 
- IOバウンド
## コンテキストスイッチとは
Linuxなどでは多数のプロセスを同時に動作させることができる（マルチタスク）。一般的に一つのプロセッサは同時に複数のプログラムを実行することができないが、複数のプロセスを短い時間で切り替えながら実行することで、体感上は複数のプロセスが同時に実行されているように見えている。
プロセスを切り替える際に処理中のデータが失われないように現在のプロセスが使用しているレジスタやフラグなどの状態を保存し、復帰できる様にする必要がある。
この状態のcpuのことをコンテキスト、保存と復帰をおこない、コンテキストを切り替えることをコンテキストスイッチと呼ぶ。
## 並列処理と並行処理の違い
### 並列処理
複数の処理を複数CPUで行う
### 並行処理
複数の処理を1CPUで行う
### CPUバウンドでは並行処理は効果なし
多くの処理はデータを読み込んでcpuで処理をすることが多いのでIO→cpuの流れにある。
この処理がIOで重たいのか、cpuで重たいのかによって並列化するのか、並行化するのかが分かれるらしい。
IOバウンドならIO待ちの間にcpuバウンドな処理を実行しておくことで処理が早くなるので、並行化で問題ないが、cpuバウンドな状態だと、cpuは同時に一つしか使えないため詰まってしまう。
`並行処理が有効な例:`複数のs3ファイルをローカルに落とす
`並列処理が有効な例:`数値計算など
## Pythonは並列処理が苦手
### Global Interpreter Lock(GIL)
goなどの言語と違い、pythonは一つのプロセス内で1つのスレッドでしかバイトコードを実行できないらしい
並列処理における難しさを取り除いているとも言える
並列処理の難しさの例:
- デッドロック(プロセスやスレッドがお互いのリソースの解放を待ち続けて、それぞれの処理が進行しなくなる状態)
- cpuが変数を書いている時にもう一つの変数がその変数を呼び出してしまい、データが壊れる
![スクリーンショット 2024-12-01 12.24.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3662112/65b12ea4-e1b3-67db-6d98-b769167c5b94.png)
※これを外そうという動きもあるらしい

## どう並列化するの？
- プロセスを分ける
普通の言語では一つのプロセスでいくつかのスレッドを建てて並列化
pythonはそれができないので、そもそもプロセスを分けてしまう
`pythonにおける並列処理の書き方の例`
```python
from concurrent.futures import ProcessPoolExecutor
from random import random
from time import sleep
def func(key):
 sleep(random())
 print(key)
def do_parallel():
 with ProcessPoolExecutor() as executor:
 for key in [1, 2, 3]:
 executor.submit(func, key)

if __name__ == '__main__':
 do_parallel()
```
かなり簡単にかける
### 裏の処理はちょっと複雑...
- unix系
 forkシステムコールで単純にプロセスをコピーする
- mac,windows
 新規にプロセス作り、そこでsubmitを読んだオブジェクトからpickle/unpikleで転送
 →pickle化できないオブジェクトが欠落してしまう...
     - ファイルオブジェクト
     - DBコネクション
     - s3クライアント
     - lambda関数
## まとめ
Pythonでの並列化の問題点について改めて学ぶことができた。
参考にした動画ではRustやほかの言語についての並列処理についても説明してあったので、また次の機会にまとめたい。

参考：
- GO TechTalk #21 並列処理をGo/Rust/Kotlin/Python/JSで解説！思想の違いを体感しよう

https://www.youtube.com/watch?v=m-1Drlk2G8w&t=1877s

- Linux のしくみを学ぶ - プロセス管理とスケジューリング

https://syuu1228.github.io/process_management_and_process_schedule/process_management_and_process_schedule.pdf
Qiita初投稿です！

<h1>現在の自分について</h1>
今年で、社会人２年目のWebエンジニアです。<br>
現状については下記の通りです。<br>
・titleの変更やh1の修正など、軽微な修正や初歩的な開発しかできない <br>
・0→1開発において、何から動けばいいいのかわからない<br>
・インプット学習をメインに行っているため、わかった気になっていることが多い<br>
・何がわからないのかわからない状態があり、解決するのに時間が膨大にかかる<br>
・開発において自信がない→目標とするエンジニアへは道が遠すぎる<br>
・初歩的なことしかできず、開発経験があるか言えない
まとめると、基礎が固まっておらず自信が絶望的にない、２年目エンジニアです。<br>

<h2>エンジニアとして成長したいと思った理由</h2>
下記３つのエピソードから、エンジニアとして成長したいきっかけとなりました。<br>
・自分にとって結構難しい案件のリリース<br>
・同期や一年目のエンジニアに負けたくない<br>
・目標のエンジニアになるために、現状とのギャップ

<h2>自分にとって結構難しい案件のリリース</h2>
案件内容としては、下記の課題を解決するための案件です。

```
手動でメールを送っていたのを、自動化したい
```
この案件から成長したいと思ったきっかけは、悔しい経験とリリース後の経験です。

```
【悔しい経験】
・内容しては、理解したが、技術でどうやって実現すればいいのかわからず、
　初めから、積んでいる状態で何を聞けばいいのかわからない状態
 →結果、チームメンバーへは迷惑をかける毎日
・１つのバッチを実装することはわかったが、実装イメージがわいておらず何をすればいいのかわからない
→リリースするまでに、約２〜３週間の案件を約半年間かかった
・開発進捗会で、毎日工数を遅れますの共有
→あと１日あれば終わると思いますと伝えても結局終わらず、工数状態も立てることができていない
 ```
 ```
【リリース後の経験】
・無事自動化することができ、助かった！！などお声を聞いたり、笑顔になってくれてる姿を見たこと
→諦めず開発してよかった、と心の底から喜びました
・案件について振り返りをし、将来エンジニアとしてどうなりたいのか考える機会になったこと
→このままではいけないと実感した瞬間でした！！
```

<h2>同期や一年目のエンジニアに負けたくない</h2>
他の同期や一年目のエンジニアでは、インターンの参加や開発のアルバイトなど学生時代に開発経験がある人ばかりでした。<br>
私自信、大学時代で初歩的なプログラミングや、内定者の時に研修もあったからついていけるだろうと思っていました。<br>
しかし、下記が発生し、同期や一年目のエンジニアに負けたくないと思い今のままではいけないと思いました。<br>

 ```
1年目：
・研修の際にも、わかった気になり同期と差が開いてしまう
・技術的な話について行けない
・教材でインプットを多くしていれば大丈夫だろう

２年目：
・後輩ができ、わからないことを質問してくれるのですが、回答するのにとても時間がかかってしまう
→一緒に他の同期や先輩に質問しに行く瞬間が多くありました
 本当に先輩かと自分でも恥ずかしくなる毎日
・他の同期は活躍し、任せてもらう案件が簡単な案件になってしまっている（titleやh1の変更など）
→常に焦っている状態
・勉強方法も１年目と変わらない（教材漁りまくり）
 ```

<h2>目標のエンジニアになるために、現状とのギャップ</h2>
私は、「新規事業で0→1の開発をし、使ってもらった人が笑顔に幸せにできるエンジニア」になることを目標としております。<br>
しかし、現状の状態と目標のエンジニアには大きな差があり、埋めるために今の進め方では差を縮めることができないため、このままではいけないと思いました。<br>


<h2>JISOUとの出会い</h2>
目標のエンジニアになるために、成長するための方法について記事を見ていました。その時、@Kei-dev-1213さんの記事と出会い、JISOUを知り、成長したいと思いました。<br>
エンジニアとして成長したいと思った理由があり本気で学ぶことに決めたため、成長するために、JISOUというサービスに参加させていただいて頑張っていきます。<br>

<h2>目標</h2>
短期(3ヶ月)：土台を固め、何をすればいいのかわからない状態を克服する<br>
中期(半年)：Reactで自分が作成したいものを実現でき、自信が持てる状態になる<br>
長期(1年)：サービスを0→1で開発できるようになる<br>

目標を達成するために、アウトプットを習慣化し成長に繋げていきます！！！


<h2>JISOUのメンバー募集中！</h2>
プログラミングコーチングJISOUでは、新たなメンバーを募集しています。<br>
日本一のアウトプットコミュニティでキャリアアップしませんか？<br>
興味のある方は、ぜひホームページをのぞいてみてくださ！<br>
▼▼▼<br>

https://projisou.jp/
OpenCVで人の顔をドナルドにする

# はじめに
MYJLab Advent Calender 2024の17日目を担当させていただく4年生です。
さて、今日は「OpenCVで人の顔をドナルドにする」ということで初心者にはハードルが高い機械学習の部分を"あるもの"で代用して誰でも簡単にできる手順を解説していきます。これを読み終わった後今回使った"あるもの"を自分で作ってみようと思ってもらえるよう頑張ります！

# 目標
- OpenCVの予め用意された"あるもの" = "カスケード型分類器"を使って、顔検出して顔部分にドナルドの画像を貼り付ける

# 環境
今回はPythonを使います。

- Windows 11 Home
- Python 3.11.0
- opencv-python 4.7.0

# 準備
カスケード分類器の準備

以下のリンクから学習済みのカスケード分類器をダウンロードします。
https://github.com/opencv/opencv/tree/master/data/haarcascades
今回はhaarcascade_frontalface_default.xml(正面からの顔を検出する分類器)をダウンロードして使いましょう！

[ここ重要]
分類器haarcascade_frontalface_default.xmlと検出したい画像(sample.jpg)は、pythonファイルは同じディレクトリに保存します。



# コード

## opencvをインストールする

```python
pip install opencv-python
```

## script
```python
import cv2

# 顔検出器のパス
cascade_path = cv2.data.haarcascades + 'haarcascade_frontalface_default.xml'

# 顔検出器の読み込み
face_cascade = cv2.CascadeClassifier(cascade_path)

# 上書きする画像の読み込み
overlay_image = cv2.imread('./sample![スクリーンショット 2024-12-02 102144.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3617886/8acf9699-c90f-f2b6-f666-e350e32b802e.png)
.png')

# カメラキャプチャの開始
cap = cv2.VideoCapture(0)

while True:
    # フレームの読み込み
    ret, frame = cap.read()

    if not ret:
        break

    # グレースケールに変換
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # 顔の検出を行う
    faces = face_cascade.detectMultiScale(gray, scaleFactor=1.1, minNeighbors=5, minSize=(20, 20))

    # 検出された顔の領域に上書きする画像を配置
    for (x, y, w, h) in faces:
        # 上書きする画像のサイズを調整
        resized_overlay = cv2.resize(overlay_image, (w, h))

        # 顔の領域に上書きする画像を配置
        frame[y:y+h, x:x+w] = resized_overlay

    # 結果を表示
    cv2.imshow('Result', frame)

    # 'q'キーを押して終了
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

# キャプチャの解放とウィンドウの破棄
cap.release()
cv2.destroyAllWindows()

#顔検出した画像を保存する 
cv2.imwrite('./sample_cascade.avi', frame)

```
### 出力結果の画面キャプチャ
![スクリーンショット 2024-12-02 102144.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3617886/b6df1ad3-1222-454d-9f57-cf4106eaab31.png)

# おわりに
- カスケード分類器を使った顔検出はいかがでしたか？
- カスケード分類器は容易に使うことはできますが、精度が低いことが現状です。精度を高めたい方は自分で機械学習することをおすすめします。
自己疑念を乗り越え、自信を育てる：テック業界でのインポスター症候群対策

### エンジニアリングは難しいです。
AIやさまざまなプログラミングツールの登場にも関わらず、依然として難しいです。新しい機能を実装したり、バグの原因を理解したり、どこから手をつけていいのかわからないとき、私は時々圧倒的な気持ちに襲われます。

### 私は完全にダメなエンジニアだ！！私はインポスターだ！！みんな私より優れている！！

恥ずかしさ、 嫌悪、疲れ… そんな暖かくて心地よい感情が湧いてきます。ある時、深く思い悩んでいる最中にGoogleで「どうして私はこんなにエンジニアリングが下手なんだ？」と検索してみたら… みんな同じことを検索していることに気がついた😂 そして、私が経験していたことを説明するための言葉がありました： **「インポスター症候群」**

そうです！自分の感じていたことを完全に表現した言葉があったんです（そしてありがたいことに、誰も私についてそう思っていなかった）。これに名前を付けることで、感情を整理し、なぜそのように感じていたのかを理解する手助けとなりました。

### インポスター症候群とは？
:::note info
インポスター症候群とは、自分の能力や成果に疑問を感じることです。自分が他の人が思っているほど才能がない、または価値がないと感じ、そのことをいつか誰かに見抜かれてしまうことを恐れます。自分の成功が本当に自分の努力やスキルの結果だとは信じられない状態です。「自分は他の人より優れていない」と言ってくる、邪魔で役に立たない声が頭の中に響きます。
:::
### 誰がインポスター症候群になるのか？
驚くかもしれませんが、最大で70%の人々が人生の中で少なくとも一度はこの現象を経験します¹。 何か新しいことに挑戦している時や、移行期にインポスター症候群を経験する傾向があります²。成功するプレッシャーと経験の不足が、自己不信を引き起こすことがあります。

ソフトウェア開発者は特にインポスター症候群に悩まされやすいです。なぜなら、職場での厳しい競争や、複雑で常に変化する技術に適応し学ぶプレッシャーがあるからです。多くの開発者は自分の知識が他の人と比べて限られていると感じ、そう思い込んでしまいがちです。実際には、すべての開発者が異なり、それぞれに異なるスキルセットがあることも忘れがちです。プログラマーは、問題に直面したとき、それを解決する方法がわからないときにも自己不信や不十分さを感じることがあります。

### インポスター症候群を克服する方法
私にとって、インポスター症候群を克服する最初の一歩は、**自分だけではない**ことに気づくことでした。ほとんどの人が似たような感情を経験しており、それらは嫌な侵入的な思考ですが、現実ではないということです。

ここで、頭の中のいじめっ子をどう対処するかについてのいくつかの方法を紹介します：

**自分の成功を思い出す**。これまでにうまくいったことや誇りに思う成果を思い返してみましょう。たとえば、プロジェクトが成功した時や、難しい問題を解決した瞬間など、自分の実力に自信を持てる瞬間を振り返ることが大切です。自己疑念が湧いたとき、その経験を思い出して、自分の成長と実力を信じる助けにしましょう。

**感情を事実から切り離す**。自分に対する疑念が湧いてきたとき、それはあくまで**感情であり**、**現実の自分の実力を反映していない**ことを意識しましょう。エンジニアとしての成長は一度で完了するものではなく、試行錯誤や失敗を繰り返しながら進んでいくものです。疑念にとらわれず、自分が成長し続けていることを信じることが重要です。

**自分に優しくする**。エンジニアとして最初から完璧にできる人は誰もいません。試行錯誤やエラーがつきものです。もし友達や同僚が同じように感じていたら、「大丈夫、成長の過程だよ」と励ますように、自分にも優しく接しましょう。失敗してもそれは成長の一部であることを認めることで、心に余裕が生まれます。

**賞賛を受け入れる練習をする**。誰かから褒められたとき、つい謙遜してしまうことがあるかもしれません。しかし、「ありがとう」と素直に受け入れることで、自己肯定感が高まります。自分の成し遂げたことに自信を持ち、他人からの評価を受け入れることが、自分をもっと受け入れる一歩となります。

:::note alert 
**他人と自分を比較しない。**
:::
特に同僚や他のエンジニアと自分を比較してしまうことがあるかもしれません。しかし、他のエンジニアにはそれぞれ異なる強みや専門分野があります。そして、あなたもその中で大切なスキルを持っていることを忘れないようにしましょう。他人との比較に時間を費やすよりも、自分自身の成長に集中することが大切です。

**自分に挑戦する**。自分の能力に対して厳しくなりすぎているときは、ポジティブな視点に切り替えてみましょう。例えば、「この問題が解決できないのは、他の人たちの方がもっと経験があるからだ」と思うのではなく、「この問題を解決できたら、私はさらに成長できるチャンスだ」と考えるようにしてみましょう。困難を乗り越えることが、さらに強いエンジニアへと成長させてくれます。

**この症候群を理解する**。インポスター症候群を持っている人は、実際には非常に高い基準を持ち、努力を続けている証拠です。逆に、本当にインポスターであれば、そのような感覚を持つことはありません。この感覚を受け入れ、それを自己成長の一部として活用することで、前に進む力になります。

この記事が、あなたの中の疑念の声を静め、自信を持つ手助けとなれば嬉しいです ✨。

Camille

<hr>

¹ Sakulku J, Alexander J. The imposter phenomenon. Int J Behav Sci. 2011;6(1):73-92. doi:10.14456/IJBS.2011.6
² Weir K. Feel like a fraud? American Psychological Association.
Google Cloudのコストレポートで急に利用料が0円になった話

# はじめに
こちらは[TVer Advent Calender 2024](https://qiita.com/advent-calendar/2024/tver)の13日目の記事です。

12日目の昨日は@okamiiiさんによる「[テレビ配信サービスだけではないTVer](https://techblog.tver.co.jp/entry/okamiii/tver-ownedmedia)」でした。

今年の9月にTVerへ入社しました、SREチームの藤岡です！猫とハイキュー!!が好きです。よろしくお願いします。

SREチームの業務の1つにAWSやGoogle Cloud等のサービス管理があります。
私は前職でGoogle Cloudを触っていたこともあり、TVerでもGoogle Cloudの管理を担当しています。入社後はプロジェクト整理や組織移行をして環境を整えている途中です。

今回はGoogle Cloudのコストレポートを見ていたら利用料が発生していない日があったので、その原因について書きます。

# コストレポートが歯抜けになっている
コストレポートを見たら急に利用料が0円になっている日がありました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3932181/e3cc0bdd-afdb-55c0-8d72-50bbe03cc1a1.png)

月初であれば各サービスの無料枠が考えられます（これまでの利用状況から0円にはならないはずですが）。
しかし前後の利用状況や10月13日からという月中ばであることから、無料枠は考えにくいです。

# 原因はクレジット
結論、クレジット適用が原因でした。
10月17日からまた利用料が発生しているのは、対象のクレジットを使い切ったからでした。

# クレジットの利用状況を確認する方法
お支払い画面から確認ができます。
今回は開始日が10月13日のものが適用されていました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3932181/f4f9fa02-75d3-b66d-394a-bc00098eb4d5.png)

# クレジットを除外したレポートを見たい場合
クレジット適用を除外した料金を見たい場合、レポートのフィルタでクレジットのチェックボックスを外します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3932181/35feb5b0-2fd0-3afe-c570-b4a710759fc4.png)

# 入社3か月の振り返りとこれから
今回の事象や他のタスクの相談など、チームメンバーと毎日話す時間があるのでスムーズに業務が進められます。

今後はTVerのセキュリティ強化に向けて、ツールの導入や運用の整備などに取り組んでいきます！


TVer Advent Calender 2024の明日は、@gapao_ken10さんの「[テレビ局の技術職がPMに挑戦](https://techblog.tver.co.jp/entry/2024/12/14/023623)」です！お楽しみに！
2024年版 「最もよく使われるパスワード」の nyanmage は Entra ID に使用できるのか？

## 想定読者と本記事の位置づけ
・想定読者 ： セキュリティ初心者
・セキュリティ技術に興味を持ってもらえるように簡単な検証と技術の必要性を紹介する記事です。
・私自身もセキュリティ初学者であるため、備忘録として執筆しています。
・内容に誤った記載を見つけましたら、コメントでご指摘いただけますと幸いです。勉強させていただきます。 

## 検証背景
先日、NordVPN によって開発されたパスワードマネージャー「NordPass」が、「世界で最もよく使われるパスワード」の 2024 年版を発表しました。このランキングを解説している [Gigazine の記事](https://gigazine.net/news/20241114-most-common-passwords-list-2024/) によると、日本企業に関連した使用数ランキングで「nyanmage」が 6 位、「takahiro」が 20 位にランクインしているとのことです。
Microsoft Entra ID でパスワードを新規に作成する際、**使用頻度が高い最新のパスワードにもパスワード保護機能が有効になっているのか**気になり、簡単に検証してみました。

## Entra ID のパスワード保護機能とは？

Entra ID（旧 Azure AD）のパスワード保護機能は、以下の仕組みで、**リストに登録されたパスワードの利用を禁止することで、パスワードスプレー攻撃などの侵害からアカウントを保護します**：

- **グローバル禁止パスワードリスト**：一般的なパスワードや脆弱とされるパスワードを含むリスト。
- **カスタム禁止パスワードリスト**：組織が独自に設定可能な追加リスト。

これにより、組織内で脆弱なパスワード使用を未然に防ぐことができます。詳細については Microsoft の公式ドキュメントを参照してください。

[参考：グローバルおよびカスタム禁止パスワードリスト - Microsoft Entra](https://learn.microsoft.com/ja-jp/azure/active-directory/authentication/concept-password-ban-bad)

## Entra ID のパスワード設定で起きた現象

実際の検証結果です。
Microsoft Entra ID の新規ユーザー作成時に、パスワードを「nyanmage」＋簡単な数字と記号で設定しようとしましたが、Entra のパスワード保護機能により弾かれました。

一方で、「nyanmage」と同じ文字数（8文字）のランダムなアルファベット＋同じ数字と記号を組み合わせたパスワードでは問題なく設定が可能でした。この現象から、**「nyanmage」が Entra ID のグローバル禁止パスワードリストに登録されている** と推測しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3762983/c7c971d5-09a3-9766-4b13-6617a3ce5a92.png)


## 検証結果まとめ

以下は本検証の結果です：

| パスワード候補         | 設定可能か | 理由/推測                        |
|------------------------|------------|----------------------------------|
| nyanmage123!         | ✖          | グローバル禁止パスワードリストに含まれる |
| hdnvdkmg123!        | ✔          | ランダムな文字列のため問題なし    |

## なぜ「nyanmage」は弾かれるのか？

「nyanmage」は、日本の企業ランキングで 6 位にランクインしており、一定の利用頻度があると考えられます。Entra ID のグローバル禁止パスワードリストは、こうしたよく使われるパスワードを特定してリスト化しているため、弾かれた可能性が高いです。

## まとめ

パスワード管理の重要性を考えると、脆弱なパスワードを防ぐ Entra ID のパスワード保護機能は非常に有用です。
ユーザーアカウントの侵害から、組織の機密情報を盗まれてしまう事例が発生することは少なくありあません。「nyanmage」のような一般的に知られるパスワードは避け、ランダムで複雑なパスワードを設定することで、身近なセキュリティから強化していきましょう！

### 関連リンク

- [Top 200 Most Common Passwords - NordPass](https://nordpass.com/most-common-passwords-list/)
- [2024年版「最もよく使われるパスワード」が公開される、日本企業からは「ニャンまげ」が謎のランクイン - Gigazine](https://gigazine.net/news/20241114-most-common-passwords-list-2024/)
laravel sailを使ってlaravelのアプリケーションの初期構築をしてみる

## 概要

laravel sail（以降 sailと呼ぶ）を使ってlaravelのアプリケーションの初期構築をしてみたので方法を簡単にまとめる。

## 注意

この記事は下記の公式ドキュメントの体験記です。

https://laravel.com/docs/11.x/installation#sail-on-macos

## 前提

使用PCのOS はMac OS

## 方法

1. 任意のディレクトリで下記コマンドを実行してディレクトリの作成とlaravelアプリケーションを作成（「任意のlaravelアプリケーション名」は筆者の場合「laravel-sail」とした）
    ※実行完了まで割と時間がかかった。

    ```terminal
    curl -s "https://laravel.build/任意のlaravelアプリケーション名" | bash
    ```

1. `Thank you! We hope you build something incredible. Dive in with: cd laravel-sail && ./vendor/bin/sail up`と出力されたら前述のコマンドの実行は完了
1. 「任意のlaravelアプリケーション名」のディレクトリが作成されているはずなので移動
1. 下記を実行してローカル開発環境を起動（バックグラウンドで起動したいなら`-d`オプションをつけて`$ ./vendor/bin/sail up -d`を実行）

    ```terminal
    ./vendor/bin/sail up
    ```

1. ターミナルの出力が安定し、`laravel-sail-meilisearch-1   | 2024-11-28T02:03:21.311249Z  INFO HTTP request{method=GET host="127.0.0.1:7700" route=/health query_parameters= user_agent=Wget status_code=200}: meilisearch: close time.busy=86.2µs time.idle=13.2µs`だけになったら起動はできている
1. [http://localhost/](http://localhost/)にアクセスするとエラー画面が出ることを確認（このタイミングではエラーが出て差し支えない）

    ![CleanShot 2024-11-28 at 11.04.27@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/3787f738-4c58-a936-f847-3f93dba2e66e.png)

1. 別のターミナルで「任意のlaravelアプリケーション名」のディレクトリを開き、下記コマンドを実行

    ```terminal
    ./vendor/bin/sail artisan migrate
    ```

1. 再度[http://localhost/](http://localhost/)にアクセスすると下記のように画面が出ることを確認

    ![CleanShot 2024-11-28 at 11.06.58@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/1d76569b-2ee2-71c4-0bb5-555e9fbc98a0.png)

ここまでできたら環境構築は完了
筆者はGit管理するための作業を実施する

1. Githubで「任意のlaravelアプリケーション名」の名前でリモートリポジトリを作成
1. 後は「任意のlaravelアプリケーション名」のディレクトリで下記のコマンドを実行してコミットとリモートリポジトリへのアップを実施

    ```terminal
    git init
    git config --local user.name 'ユーザー名'
    git config --local user.name 'メールアドレス'
    git config -l
    git remote add origin リモートリポジトリのアドレス
    git commit --allow-empty -m 'first commit'
    git add .
    git commit -m 'コード初回コミット'
    git push origin master
    ```

## 参考文献

https://laravel.com/docs/11.x/installation#sail-on-macos
Javaで学ぶアルゴリズム -線形探索（番兵法ver.）

# 番兵法

- 配列やリストの末尾に探索対象の値（いわゆる「番兵」となる値）を追加する
- これにより、ターゲットが見つからなかった場合にループを終了するための追加の条件チェックが不要になる
- 結果としてアルゴリズムが ﾁｮｯﾄ シンプルになり、場合によってはパフォーマンスが向上するカモ

# 実行環境

- JUnit 5
- Java 8


# テストコード

```java:SequentialSearchWithSentinelTest.java
public class SequentialSearchWithSentinelTest {

	@DisplayName("正常系テスト")
	@ParameterizedTest(name = "No.{index}: {0}を探すとインデックス{1}を返す")
	@CsvSource(value = {
			"-1, -1",
			"1, 0",
			"5, 4",
			"10, 9",
			"11, -1"
	})
	void testNormalSequentialSearch(int target, int expected) {
		int[] array = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
		assertThat(SequentialSearchWithSentinel.sequentialSearchWithSentinel(array, target), is(expected));
	}

	@DisplayName("配列が空である場合、-1を返す")
	@Test
	void testEmptyArray() {
		int[] array = {};
		assertThat(SequentialSearchWithSentinel.sequentialSearchWithSentinel(array, 1), is(-1));
	}

	@DisplayName("重複する要素がある場合、最初に見つかったインデックスを返す")
	@Test
	void testDuplicateElements() {
		int[] array = { 1, 2, 3, 4, 4, 5, 6, 7, 8, 9, 10 };
		assertThat(SequentialSearchWithSentinel.sequentialSearchWithSentinel(array, 4), is(3));
	}
}
```

# 番兵法を使った線形探索アルゴリズム

ループの終了条件（探索したい値が見つからずにすべて通り過ぎたか？）が1つ減るので、大量のデータセットを扱う場合には処理の効率が上がるかもしれません。

```java:SequentialSearchWithSentinel.java
public class SequentialSearchWithSentinel {

	/**
	 * 線形探索を番兵法を用いて実行するメソッド。
	 * 配列array内でtargetを探し、そのインデックスを返す。見つからない場合は-1を返す。
	 *
	 * @param array 探索対象の配列、nullが渡される可能性はないと仮定
	 * @param target 探索する値
	 * @return targetのインデックス、見つからない場合は -1 を返す
	 */
	public static int sequentialSearchWithSentinel(int[] array, int target) {

		// 配列のサイズを1増やす
		int[] arrayWithBanpei = Arrays.copyOf(array, array.length + 1);
		// 配列の最後に番兵を追加
		arrayWithBanpei[array.length] = target;

		int i;
		for (i = 0; arrayWithBanpei[i] != target; i++) {
			// ループ内の動作はすべてfor文に含まれているので記述不要
		}
		// 配列の本来の範囲外（番兵の位置）で見つかった場合は -1 を返す
		return i == array.length ? -1 : i;
	}

    // =======以下、番兵法を使わない場合（比較用）=======
	public static int sequentialSearch(int[] array, int target) {
		for (int i = 0; i < array.length; i++) {
			if (array[i] == target) {
				return i;
			}
		}
		return -1;
	} 
}
```

```java:SequentialSearchWithSentinel.java その2
public class SequentialSearchWithSentinel {

	/**
	 * 線形探索を番兵法を用いて実行するメソッド。
	 * 配列array内でtargetを探し、そのインデックスを返す。見つからない場合は-1を返す。
	 *
	 * @param array 探索対象の配列、nullが渡される可能性はないと仮定
	 * @param target 探索する値
	 * @return targetのインデックス、見つからない場合は -1 を返す
	 */
	public static int sequentialSearchWithSentinel(int[] array, int target) {

		// 配列のサイズを1増やす
		int[] arrayWithBanpei = Arrays.copyOf(array, array.length + 1);
		// 配列の最後に番兵を追加
		arrayWithBanpei[array.length] = target;

		int i = 0;
		while (arrayWithBanpei[i] != target) {
			i++;
		}
		// 配列の本来の範囲外（番兵の位置）で見つかった場合は -1 を返す
		return i == array.length ? -1 : i;
	}
 
    // =======以下、番兵法を使わない場合（比較用）=======
	public static int sequentialSearch(int[] array, int target) {
 
		int i = 0;
  
		while (true) {
			if (i == array.length) {
				return -1;
			}
			if (array[i] == target) {
				return i;
			}
			i++;
		}
	}
}
```

補足

番兵法使わないやつ

https://qiita.com/_mi/items/212b91da5ae3cbbdb696
laravel sailってなんだろう？

## 概要

「laravelのsailを使えばサクッとローカル開発環境の構築ができるっぽい」という話を聞いた。
laravelで開発環境の構築をするとなると「Dockerから作らないと〜、、、PHPのコンテナと、、、DBのコンテナと、、、あ、Makefileも用意してコマンドも用意しないと、、、」みたいな漠然としためんどくささがある。（個人的には）
この辺をサクッと解決してくれるのがlaravel sailらしい。
お恥ずかしながら今回始めてlaravel sailの存在を知ったので、まずはどういったものなのかを簡単にまとめてみようと思う。

## 内容

sailはおそらくlaravel8から入った機能のようだ。（公式ドキュメントのsailのページでバージョン7だとコンテンツがなく、バージョン8だとコンテンツが表示されるので）

https://laravel.com/docs/8.x/sail

公式の説明を要約すると下記のような感じになる。

>Dockerを使った開発経験がなくともDockerを使ったローカル開発環境の構築が可能。従来エンジニアが用意していたMakeコマンドに置き換わるような`sail`コマンドが準備されている。Mac Linux Windows(WSL2経由)でサポートされている。

ざっくりいうと今までエンジニアが手作業で環境構築していたものをsailが肩代わりしてくれる感じらしい。

Macでsailを使って環境構築するには下記の手順になるらしい。

https://laravel.com/docs/11.x/installation#sail-on-macos

非常に便利そうなのでどのくらいの自由度なのか早速使ってみようと思う。

## 参考文献

https://laravel.com/docs/11.x/sail
PHP set_time_limit()を始めて使ってみた

## 概要

`set_time_limit()`が思ったより使いやすかったので簡単にまとめる。

## 注意

多様は禁物！
「ちょっとデバッグするときに一時的に使う」くらいの感覚で使ったほうが良さそう。
でないと「php.iniのmax_execution_timeをいくらいじっても特定の処理だけタイムアウトが長くなる」みたいな事になりバグを生みそう。

## どんな関数？

実行処理時間をphp.iniをいじらずとも変更できる。
PHPは実行可能な秒数がphp.iniというファイル内部のmax_execution_timeで設定できる。
`set_time_limit()`を指定処理内部に記載することでphp.iniでの実行可能な秒数をいじることができる。

## 詳細

下記のように指定する。

```
set_time_limit(秒数の指定)
```

レスポンスはboolらしい。
引数に0を指定すると制限がなくなって永遠と実行される。
逆に引数を一切指定しないと30秒がデフォルトで設定される。ただしphp.iniでmax_execution_timeを使っている場合はその値がデフォルト値として設定される。

一連の処理の中で`set_time_limit()`が実行されたタイミングで制限時間のカウンターが`set_time_limit()`で指定した値でリセットされる。
なので一連の処理の中で`set_time_limit(15)`があるステップまで30秒かかって実行されたとする。`set_time_limit(15)`が実行されたタイミングでカウンターがリセットされ更にそこから15秒リミットが伸びる。
タイムリミットは45秒となる。

↑のような仕様を気にしたくないなら、一連の処理の序盤に`set_time_limit()`を定義することで実質その一連の処理のタイムリミットを`set_time_limit()`の引数で指定した秒数にすることができる。

## 参考文献

https://www.php.net/manual/ja/function.set-time-limit.php
Mac ローカルにPHPをインストールしてcomposerをインストールする方法

## 概要

MacのローカルにPHPをインストールしてcomposerをインストールする方法を簡単にまとめる。

## 前提

Homebrewがインストールされていること。

## 方法

1. 下記を実行してPHPをインストール（`command not found`になった場合[こちら](https://qiita.com/miriwo/items/e6545c892095af307d27)を参考にHomebrewを入れる）

    ```bash
    brew install php
    ```

1. 下記を実行してインストールしたPHPのバージョンを確認（`command not found`にならないこと）

    ```bash
    php -v
    ```

1. [こちら](https://getcomposer.org/download/)の赤枠内のコマンドを実行し、composerをインストール（composerのバージョンを指定したい場合は`php composer-setup.php`を実行する際に`php composer-setup.php --version=バージョン名`のように指定する。バージョン名は[こちら](https://github.com/composer/composer/releases)を参照）

    ![CleanShot 2024-11-27 at 00.24.09@2x.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/b50d486c-e21b-2236-35d7-a5367a1d662e.jpeg)

1. 筆者は今回composerの2.7.1を入れたいので下記のようにコマンドを実行

    ```bash
    php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
    php -r "if (hash_file('sha384', 'composer-setup.php') === 'dac665fdc30fdd8ec78b38b9800061b4150413ff2e3b6f88543c636f7cd84f6db9189d43a81e5503cda447da73c7e5b6') { echo 'Installer verified'; } else { echo 'Installer corrupt'; unlink('composer-setup.php'); } echo PHP_EOL;"
    php composer-setup.php --version=2.7.1
    php -r "unlink('composer-setup.php');"
    ```

1. 下記を実行してcomposerの実態ファイル？を移動

    ```bash
    sudo mv composer.phar /usr/local/bin/composer
    ```

1. 下記を実行して実行権限を付与

    ```bash
    chmod +x /usr/local/bin/composer
    ```

1. 下記を実行してインストールしたcomposerのバージョンを確認（`command not found`にならないこと）※筆者の場合、非推奨系の警告が出たがcomposerのバージョンは正常に出力された。非推奨系の警告はphp.iniに`error_reporting = E_ALL & ~E_DEPRECATED & ~E_STRICT`を記載することで出力しないようにできるらしい。

    ```bash
    composer -v
    ```

ここまで来たら目標達成となる。

## 参考文献

https://qiita.com/miriwo/items/e6545c892095af307d27

https://github.com/composer/composer/releases

https://getcomposer.org/download/

https://getcomposer.org/doc/00-intro.md#globally
Next.jsに追加されたforbiddenとunauthorized機能

## はじめに
Next.jsのApp Routerはプロジェクトの構造を`app`ディレクトリ内でファイル名とフォルダ名とその組み合わせを元にして決定します。

この記事ではNext.jsの`v15.1.0`から新たに追加された2つの予約されたファイル名と2つの機能を紹介します。

執筆現在`v15.0.4-canary.33`で`canary`として存在しています。そのためこれから紹介する機能を利用するには`experimental.authInterrupts`を`true`に設定する必要があります。
```ts:next.config.ts
const nextConfig: NextConfig = {
  experimental: {
    authInterrupts: true,
  },
};
```

追加された機能を利用して作成したデモページを作成しました。実際に触りたい場合はこちらをどうぞ。

https://forbidden-unauthorized.vercel.app/

https://github.com/k35o/forbidden-unauthorized

## forbidden
`forbidden.js`は`not-found.js`と同じような機能を持つファイルです。同時に追加された`forbidden`関数と合わせて権限の不足等のエラー時に利用されます。

ページのUIの作成中に`fobidden`が呼び出された時、そのセグメントの`page.js`ではなく、403エラーと合わせて`forbidden.js`に記述されたUIが表示されます(`forbidden.js`がなければNext.jsが用意したデフォルトのUIが表示されます)。

```tsx:forbidden.jsに遷移する例
import { forbidden } from 'next/navigation'
import { getUser } from '@/model/user'
 
export default async function CreateBlog() {
  const user = await getUser()

  // ブログを作成・編集する権限がなければforbiddenへ移動
  if (!hasWriteBlogPermission(user.permissions)) {
    // returnは不要
    forbidden()
  }

  // 通常表示されるUI
  return (
    <main>
      <CreateBlogForm />
    </main>
  )
}
```

`forbidden`関数がサーバーアクション、ルートハンドラ内で実行された場合は、処理を中断してステータスコード`403`を返します。

```ts:forbidden関数を利用した一例
'use server'
 
import { forbidden, notFound } from 'next/navigation'
import { getUser } from '@/model/user'
import { getBlog, updateBlog } from '@/model/blog'
 
export async function update(formData: FormData) {
  const user = await getUser()
  const blog = await getBlog(formData)

  // ブログがない場合は404を返す
  if (!blog) {
    notFound()
  }

  // ブログを記述したユーザーでない場合は403を返す
  if (blog.userId !== user.id) {
    forbidden()
  }
 
  // ブログの更新処理
  // ...
}
```

## unauthorized
`unauthorized.js`もまた`unauthorized`関数と合わせて未ログイン等のエラー時に利用されます。

ページのUIの作成中に`unauthorized`が呼び出された時、そのセグメントの`page.js`ではなく、401エラーと合わせて`unauthorized.js`に記述されたUIが表示されます(`unauthorized.js`がなければNext.jsが用意したデフォルトのUIが表示されます)。

```tsx:unauthorized.jsに遷移する例
import { unauthorized } from 'next/navigation'
import { getUser } from '@/model/user'
 
export default async function CreateBlog() {
  const user = await getUser()

  // ログインしていない場合はunauthorizedへ移動
  if (!user) {
    // returnは不要
    unauthorized()
  }

  // 通常表示されるUI
  return (
    <main>
      <CreateBlogForm />
    </main>
  )
}
```

`unauthorized`関数はサーバーアクション、ルートハンドラ内で実行された場合は、処理を中断してステータスコード`401`を返します。

```ts:unauthorized関数を利用した一例
'use server'
 
import { unauthorized, forbidden, notFound } from 'next/navigation'
import { getUser } from '@/model/user'
import { getBlog, updateBlog } from '@/model/blog'
 
export async function update(formData: FormData) {
  const user = await getUser()

  // ログインしていない場合は401を返す
  if (!user) {
    unauthorized()
  }
 
  // ブログの更新処理
  // ...
}
```

## さいごに
Next.jsの`canary`で2つの`File Conventions`が追加され、それに関連する2つの`navigation`APIを紹介しました。
今後も新たな意味を持つファイル名が追加されると考えられるので、現存しないファイル名であっても`_`を先頭につけるように心がけて行きたいです。
自前のSlackアプリにスラッシュコマンドを追加する

## 概要

自前のSlackアプリにスラッシュコマンドを追加する方法をまとめる。
追加したスラッシュコマンドで下記のGASを動かしてみる。

https://qiita.com/miriwo/items/b43654cba1235f331a75

## 前提

下記の内容が完了していること。

https://qiita.com/miriwo/items/2da4f736aca64ea88406

今回はテスト用として「commands」というSlakアプリを事前に作成した。

更に下記の内容が完了し、GASの関数がPOSTのAPIエンドポイントのURLが分かっていること

https://qiita.com/miriwo/items/b43654cba1235f331a75

## 方法

1. 下記にアクセス
    1. https://api.slack.com/apps
1. 対象のアプリ名をクリック
1. サイドバーの「Slash Commands」をクリック

    ![CleanShot 2024-11-21 at 00.30.28@2x.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/932dc549-f4c0-ea0a-33ad-b2dbd19b3448.png)

1. 「Create New Command」をクリック

    ![CleanShot 2024-11-21 at 12.20.13.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/f986c8e0-abd0-668d-f34e-cba22b5749d6.jpeg)

1. 下記のように指定して「Save」をクリック
    - Command: `/gas_trigger`
    - Request URL: `GASのウェブアプリのURL` 

    ![CleanShot 2024-11-21 at 15.08.35.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/59306503-a7b6-2db1-8ff9-c490b8d8624c.jpeg)

1. サイドバーで「Install App」をクリックし「Reinstall to ワークスペース名」をクリック

    ![CleanShot 2024-11-21 at 15.14.02.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/90b15f23-51a1-098b-91c6-5c5e59089e7a.jpeg)

1. 「許可する」をクリック
1. 当該のSlackワークスペースを開き`/gas_trigger`を入力し、メッセージを送信

    ![CleanShot 2024-11-21 at 15.17.03@2x.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/fefdc3bf-db38-e6f1-a1d2-7fb092847ce5.jpeg)

1. 下記の様に「The script completed but did not return anything.」が返ってきて、GASの実行数部分にSlackのスラッシュコマンドで実行し、トリガーされた実行があることを確認、ここまでできたら完了

    ![CleanShot 2024-11-21 at 16.15.57@2x.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/306417/42e235af-15d6-858e-e77f-c1aac9b94bca.jpeg)