タタッと!ドラゴンさん🐉

タタッ!と書いてく記事まとめ

DXF TEXT エンティティの読み方まとめ

はじめに

DXF ファイルは「グループコード(番号)」と「」の組み合わせで構成されます。\ グループコードは「次の値が何を意味するか」を決める役割を持ちます。

この資料では、TEXT エンティティを例に\ DXF の読み方をわかりやすく整理したメモをまとめています。


基本:DXF の行はこう読む

10
130.39
  • 10 → グループコード(意味:X 座標)\
  • 130.39 → 値(X = 130.39)

DXF はすべてこの形式です。


代表的なグループコード(TEXT 用)

グループコード 意味


0 エンティティ種別 1 テキスト内容 5 ハンドル(ID) 7 テキストスタイル 8 レイヤ名 10 / 20 / 30 挿入位置(X / Y / Z) 11 / 21 / 31 第2基準点 40 文字高さ 50 回転角度 72 水平揃え(左・中央など) 73 生成フラグ


■サンプル TEXT エンティティ(DXF 生データ)

0
TEXT
5
A9
330
C
100
AcDbEntity
8
info
100
AcDbText
10
130.39496288806708
20
40.2434320017132
30
0
40
2.6458333333333335
1
4F : 11840mm
50
0
7
STANDARD
72
0
11
130.39496288806708
21
40.2434320017132
31
0
100
AcDbText
73
2

■サンプルの内容を読み解いた結果(整形表示)

ENTITY TYPE : TEXT
──────────────────────────────────
ハンドル           : A9
レイヤ             : info

表示文字列         : "4F : 11840mm"
文字高さ           : 2.6458333333333335
回転角             : 0°
整列方法           : 左揃え (72 = 0)
文字生成フラグ     : 2

挿入位置(基準点)
  X : 130.39496288806708
  Y : 40.2434320017132
  Z : 0

第2基準点
  X : 130.39496288806708
  Y : 40.2434320017132
  Z : 0

フォントスタイル   : STANDARD

DXF の理解を深めるポイント

  • DXF は すべてが「番号 → 意味 → 値」で構成される\
  • TEXT の本文は グループコード 1\
  • 座標系の基本は 10・20・30\
  • 文字の見た目は 40(高さ)、50(角度)、7(フォント)\
  • エンティティは 0 で始まり、次の 0 の直前までがひとつの塊

zshでIssueごとにBranch作る運用を助ける

Git Helper Functions

Issue単位でブランチを切り替える際の手間を軽減するためのZsh関数集。

gnew - 新しいIssue用ブランチへの切り替え

現在のブランチを削除し、main を最新化してから新しいブランチを作成する。

使い方

gnew <new-branch-name>

# feature/issue-123 ブランチで作業完了後、次のIssueへ
gnew feature/issue-456

# 実行される処理:
# 1. git checkout main
# 2. git branch -D feature/issue-123  (現在のブランチを削除)
# 3. git pull
# 4. git checkout -b feature/issue-456

注意事項

  • 未コミットの変更がある場合: git checkout main が失敗するため、先にコミットまたはstashしてください
  • main/master上で実行した場合: ブランチ削除をスキップし、pull → 新ブランチ作成のみ実行
  • PRがマージされていない場合: リモートブランチは残るため、GitHub上で別途削除が必要

セットアップ

~/.zshrc に以下が追加済み:

gnew() {
  local current_branch=$(git branch --show-current)
  local new_branch=$1
  
  if [[ -z "$new_branch" ]]; then
    echo "Usage: gnew <new-branch-name>"
    return 1
  fi
  
  if [[ "$current_branch" == "main" || "$current_branch" == "master" ]]; then
    echo "Already on main/master. Pulling and creating new branch..."
    git pull && git checkout -b "$new_branch"
    return
  fi
  
  echo "Switching from '$current_branch' to new branch '$new_branch'..."
  git checkout main && \
  git branch -D "$current_branch" && \
  git pull && \
  git checkout -b "$new_branch"
}

反映方法

新しいターミナルを開くか、以下を実行:

source ~/.zshrc

【TypeScript】残余プロパティを使った分割代入

残余プロパティを使った分割代入

オブジェクトから特定のプロパティを除外して、残りのプロパティを新しいオブジェクトとして取得するパターン。 書いていて思いついたので、メモしておく!

パターン例

例えば特大オブジェクトがあるとする

// オリジナルのユーザーデータから特定フィールドを除外してコピーを作成
const {
  id: _id,
  password: _password,
  createdAt: _createdAt,
  updatedAt: _updatedAt,
  ...userDataWithoutMetadata
} = originalUserData

このパターンの優れた点

ポイント 説明
Immutable 元のoriginalUserDataを変更せず、新しいオブジェクトを生成
型安全 TypeScriptがuserDataWithoutMetadataの型を自動推論(除外プロパティを除いたOmit<T, 'id' | 'password' | ...>相当)
宣言的 「何を除外するか」が明確に見える
_プレフィックス 「意図的に未使用」を示す慣例(ESLintのno-unused-vars対策にもなる)

代替案の問題点

// NG例1: 手動コピー(DRY違反、メンテナンス困難)
const userDataWithoutMetadata = {
  name: originalUserData.name,
  email: originalUserData.email,
  // ... 大量のプロパティを列挙
}

// NG例2: delete使用(型が崩れる、意図が不明瞭)
const userDataWithoutMetadata = { ...originalUserData }
delete userDataWithoutMetadata.id
delete userDataWithoutMetadata.password

汎用テンプレート

// 特定プロパティを除外してオブジェクトをコピー
const { 
  propToRemove1: _propToRemove1,  // _ = 「意図的に捨てる」
  propToRemove2: _propToRemove2,
  ...rest                          // 残りのプロパティを取得
} = sourceObject

// TypeScriptの型推論
// rest → Omit<typeof sourceObject, 'propToRemove1' | 'propToRemove2'>

ユースケース

  • 新規作成用データ: 既存データからidを除外してPOSTリクエスト用に変換
  • セキュリティ: passwordtokenを除外してログ出力やレスポンスに使用
  • 状態リセット: 特定のフィールドをクリアしたコピーを作成
  • APIレスポンス整形: 不要なメタデータを除外してフロントに返却

【拡張記事】structuredCloneで関数がクローンできない理由

structuredCloneで関数がクローンできない理由は、もともとStructured Clone Algorithmは他の実行コンテキストにデータを移送したり、データを永続化したりする目的で定義されていたからだと思われます。例えば、他のWindowにpostMessageでオブジェクトを送信するとき、あるいはオブジェクトをIndexedDBに保存する場合にStructured Clone Algorithmが使用されます。

とくに永続化のことを考えると、structuredCloneでクローンできるためにはデータがシリアライズできる必要があります。実際の実装はともかく、structuredCloneの挙動は仕様書上では「シリアライズしてからデシリアライズする」というアルゴリズムで定義されています。

zenn.dev

  1. structuredCloneの元々の目的 javascript// 他のウィンドウにデータ送信 window.postMessage({ name: "太郎", age: 25 }, "*")

// データベースに保存 indexedDB.put({ name: "太郎", age: 25 }) → データを別の場所に移すための仕組み 2. シリアライズの問題 シリアライズ = データを文字列や bytes に変換すること javascript// これはOK(文字列に変換可能) const data = { name: "太郎", age: 25 } JSON.stringify(data) // '{"name":"太郎","age":25}'

// これはNG(関数は文字列にできない) const func = () => console.log("hello") JSON.stringify(func) // undefined 3. 関数が特殊な理由 javascriptlet x = 100 const myFunc = () => x + 1 // 外の変数xを参照

// この関数をコピーしても... // 新しい場所にxは存在しない! 環境依存 = 関数は周りの変数やスコープに依存している → 関数だけコピーしても動かない 簡単に言うと 「関数は周りの環境とセットじゃないと意味がないから、単体ではコピーできない」

【拡張記事】コンポーネントの中にコンポーネントを作るということ

zenn.dev

Reactにおける再レンダリングの詳細な仕組み(Reconciliation)

1. 再描画の流れ(Reconciliation)

Reactの再描画処理は、2段階の比較を行って差分を検出します。

(1) Elementの種類(type)の比較

  • 同じ位置のElement同士のtypeを比較。
  • 異なればDOMを破棄し、再生成。
  • 同じならDOMを維持し、次の段階へ進む。

(2) propsや子要素の差分比較

  • propsや子要素を比較し、差分を検出。
  • 差分があればその部分のみをDOMに反映。
  • 差分がなければ再描画は行われない。

2. {renderInner()}が常にtype安定でも再描画される理由

疑問点

常にtypeが安定(例:'div')なら、再描画されずpropsやstateの変更を認識しないのではないか?

回答

  • 「typeが安定」は「DOMの破棄を防ぐ」ことを意味し、「再描画しない」ことではない。
  • propsや子要素に変更があれば、差分のみが再描画される。

初回レンダリング時:

<div>0</div>

再レンダリング時(stateが更新):

<div>1</div>
  • Reactはtype('div')が同じであるため、DOMを維持。
  • 子要素の差分(0 → 1)のみ更新される。

3. コンポーネントの再生成でtypeが毎回異なる場合の挙動

function OuterComponent() {
  const [count, setCount] = useState(0);

  const InnerComponent = () => <div>{count}</div>;

  return <InnerComponent />;
}

起こる現象

  • typeが毎回異なるため、DOMが毎回破棄・再生成される。
  • 差分比較が意味をなさず、全て再描画される。
  • 非効率でパフォーマンスが悪化する。

4. 再描画処理のまとめ(比較)

状態 typeが毎回変わる typeが安定
DOMの操作 全て破棄・再生成 DOMを再利用
再描画範囲 全て 差分のみ
パフォーマンス 悪化 良好
副作用(useEffect等) 毎回発生 初回のみ発生
Reactの挙動 非効率 効率的

5. React公式ドキュメントでの表現(参考)

Reactは最初にElementの種類(type)が変わったかを調べます。種類が変わった場合、新しいElementのツリーが構築されます。同じ種類であれば、Reactはpropsを調べ、変更されたpropsだけを更新します。


6. 結論

  • 「typeが安定していると再描画がされない」わけではなく、「typeが安定しているからDOMが維持され、propsや子要素の差分更新のみが効率的に行われる」。

🚩 実務上の注意点

  • コンポーネントは外部で定義する(毎回新たに生成しない)。
  • JSX要素のtypeを安定させることで、Reactの再レンダリング効率を向上させる。

【React Hooks】Hooksどれ使うの問題① [拡張記事]

Powered By qiita.com

問題1

以下は、非同期処理の状態管理を行うコードです。非同期処理をしたあとの結果でステート更新ができるフックを使用しています。

const initialPosts: Post[] = [];

const [posts, getPosts, isPending] = ■■■■■■■■■■■■(
  async (currentPosts: Post[], payload: void) => {
    const response = await fetch('https://api.example.com/posts');
    const newPosts: Post[] = await response.json();
    
    return newPosts;
  },
  initialPosts
);

const handleClick = () => {
  getPosts();
};

return (
  <div>
    <button onClick={handleClick} disabled={isPending}>
      {isPending ? '読み込み中...' : '投稿を取得'}
    </button>
    <ul>
      {posts.map(post => (
        <li key={post.id}>{post.title}</li>
      ))}
    </ul>
  </div>
);

問1の答えと解説を見る

正解: useActionState

解説: useActionStateは、非同期処理とステート管理を組み合わせたフックで、useTransition + useReducerのような機能を提供します。非同期処理の実行中はisPendingフラグでローディング状態を管理でき、処理完了後に自動的にステートが更新されます。第一引数には非同期処理を行う関数、第二引数には初期値を指定します。このフックにより、複雑な非同期ステート管理を簡潔に記述できます。

問題2

useEffectでデータ取得を行う際に発生する、親コンポーネントのデータフェッチが完了するまで子コンポーネントのデータフェッチが開始されず、全体の表示速度が遅くなる問題を■■■■■■■■■■■問題と呼びます。

問2の答えと解説を見る

正解: ウォーターフォール

解説: ウォーターフォール問題は、コンポーネントが階層的にデータを取得する際、親から子へと順次データフェッチが行われる現象です。本来並列で実行できるAPI呼び出しが順次実行されるため、全体的なパフォーマンスが低下します。この問題を回避するには、React QueryやSWR、TanStack Queryなどのデータフェッチライブラリを使用するか、データ取得を上位コンポーネントでまとめて行うアプローチが有効です。

問題3

以下は、DOM要素への直接アクセスを行うコードです。適切なフック名を埋めてください。

const MyComponent = () => {
  const inputRef = ■■■■■■■■(null);
  
  const focusInput = () => {
    inputRef.current?.focus();
  };

  return (
    <div>
      <input ref={inputRef} type="text" />
      <button onClick={focusInput}>フォーカスを当てる</button>
    </div>
  );
};

問3の答えと解説を見る

正解: useRef

解説: useRefは、DOM要素への参照や再レンダリングを引き起こさない値の保持に使用されるフックです。DOM要素にアクセスする場合、refオブジェクトのcurrentプロパティを通じて実際のDOM要素を取得できます。TypeScriptでは、null許容型で初期化し、アクセス時には?演算子やnull チェックを行うことで型安全性を保ちます。useStateと異なり、値の変更時に再レンダリングが発生しないため、パフォーマンス上のメリットもあります。

問題4

以下は、楽観的更新を実装するコードです。適切なフック名を埋めてください。

function LikeButton() {
  const [likes, setLikes] = useState(0);

  const [optimisticLikes, addOptimisticLike] = ■■■■■■■■■■■■(
    likes,
    (state: number) => state + 1
  );

  const handleClick = async () => {
    addOptimisticLike();

    try {
      await fetch('/api/like', { method: 'POST' });
      setLikes(likes + 1);
    } catch (error) {
      // エラー時は楽観的な更新が自動的にロールバックされる
    }
  };

  return (
    <button onClick={handleClick}>
      いいね!({optimisticLikes})
    </button>
  );
}

問4の答えと解説を見る

正解: useOptimistic

解説: useOptimisticは、楽観的更新(Optimistic UI)を実装するためのフックです。ユーザーのアクション結果を即座に画面に反映し、バックグラウンドで実際の処理を行うことでUXを向上させます。第一引数には実際のステート、第二引数には楽観的更新時の変換関数を指定します。API呼び出しが失敗した場合、楽観的な更新は自動的にロールバックされ、元の状態に戻ります。いいね機能やフォーム送信などでよく使用されるパターンです。

問題5

以下のコードで、検索クエリの更新を遅延させるために使用すべきフック名を埋めてください。

import React, { useState } from 'react';
import ExpensiveList from './ExpensiveList';

function SearchableList() {
  const [searchQuery, setSearchQuery] = useState('');
  const ■■■■■■■■■■■■ = ■■■■■■■■■■■■(searchQuery);

  const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => {
    setSearchQuery(e.target.value);
  };

  return (
    <div>
      <input 
        type="text" 
        value={searchQuery}
        onChange={handleSearch} 
        placeholder="検索..."
      />
      <ExpensiveList searchText={■■■■■■■■■■■■} />
    </div>
  );
}

問5の答えと解説を見る

正解: deferredQuery, useDeferredValue, deferredQuery

解説: useDeferredValueは、値の更新を遅延させることができるフックです。useTransitionが関数自体を遅延するのに対し、useDeferredValueは値を遅延させます。主な用途は、サードパーティコンポーネントなど、コードを直接制御できない場合です。入力値は即座に更新されますが、コストの高いコンポーネントには遅延された値が渡されるため、入力のレスポンシブ性を維持しながらパフォーマンスを向上させることができます。

問題6

以下は、複数の関連する状態を管理するコードです。適切なフック名を埋めてください。

interface FormState {
  name: string;
  email: string;
  isValid: boolean;
}

type FormAction = 
  | { type: 'SET_NAME'; payload: string }
  | { type: 'SET_EMAIL'; payload: string }
  | { type: 'VALIDATE' };

function formReducer(state: FormState, action: FormAction): FormState {
  switch (action.type) {
    case 'SET_NAME':
      return { ...state, name: action.payload };
    case 'SET_EMAIL':
      return { ...state, email: action.payload };
    case 'VALIDATE':
      return { ...state, isValid: state.name !== '' && state.email !== '' };
    default:
      return state;
  }
}

function Form() {
  const [formState, dispatch] = ■■■■■■■■■■■■(formReducer, {
    name: '',
    email: '',
    isValid: false
  });
  
  return (
    <form>
      <input 
        value={formState.name}
        onChange={(e) => dispatch({ type: 'SET_NAME', payload: e.target.value })}
      />
      <input 
        value={formState.email}
        onChange={(e) => dispatch({ type: 'SET_EMAIL', payload: e.target.value })}
      />
    </form>
  );
}

問6の答えと解説を見る

正解: useReducer

解説: useReducerは、複数の関連する状態や複雑な状態更新ロジックを扱う際に有効なフックです。useStateと比較して、アクション(action)という概念を使って状態の変更を一元管理できます。TypeScriptでは、StateとActionの型を適切に定義することで、型安全な状態管理が可能になります。複数の状態が密接に関連している場合や、条件分岐が多い更新ロジックがある場合にuseReducerを選択することで、コードの保守性と可読性が向上します。

問題7

以下は、優先度の低い状態更新を後回しにするコードです。適切なフック名を埋めてください。

function Search() {
  const [searchTerm, setSearchTerm] = useState('');
  const [results, setResults] = useState<SearchResult[]>([]);
  const [isPending, ■■■■■■■■■■■■] = ■■■■■■■■■■■■();

  const handleSearch = (e: React.ChangeEvent<HTMLInputElement>) => {
    setSearchTerm(e.target.value);

    ■■■■■■■■■■■■(() => {
      // 大量のデータを検索する処理(時間がかかる)
      const filtered = performExpensiveSearch(e.target.value);
      setResults(filtered);
    });
  };

  return (
    <>
      <input value={searchTerm} onChange={handleSearch} />
      {isPending && <div>更新中...</div>}
      <SearchResults results={results} />
    </>
  );
}

問7の答えと解説を見る

正解: startTransition, useTransition, startTransition

解説: useTransitionは、優先度の低い状態更新を後回しにできるフックです。ユーザーの入力などの高優先度の更新を妨げることなく、重い処理を実行できます。isPendingフラグを使用して処理中の状態を表示し、startTransition関数で優先度の低い更新をラップします。検索機能、ページネーション、タブ切り替えなど、即座の反応が不要な処理に適用することで、ユーザー体験を大幅に向上させることができます。React 18の concurrent features の一部として導入されました。

問題8

useEffectでデータ取得を行う際に発生する、複数のリクエストが同時に発生した場合に古いリクエストの結果が新しいリクエストの結果を上書きしてしまう問題を■■■■■■■■■■■■■問題と呼びます。

問8の答えと解説を見る

正解: レースコンディション

解説: レースコンディション問題は、非同期処理において複数のリクエストが競合状態になる問題です。例えば検索機能で「りんご」を検索後すぐに「りんごジュース」を検索した場合、「りんご」のAPI応答が遅くて後から到着すると、新しい検索結果を古い結果で上書きしてしまいます。この問題を避けるには、useEffectのクリーンアップ関数でAbortControllerを使用するか、React QueryやSWRなどのライブラリを使用することが推奨されます。これらのライブラリは自動的にリクエストの競合を管理してくれます。

問題9

以下は、一意のIDを生成するコードです。アクセシビリティSSRの安全性のために使用されるフック名を埋めてください。

function Form() {
  const id = ■■■■■■■();

  return (
    <form>
      <div>
        <label htmlFor={`${id}-name`}>名前:</label>
        <input id={`${id}-name`} type="text" />
      </div>
      <div>
        <label htmlFor={`${id}-email`}>メール:</label>
        <input id={`${id}-email`} type="email" />
      </div>
    </form>
  );
}

問9の答えと解説を見る

正解: useId

解説: useIdは、一意のIDを生成するためのフックです。主にアクセシビリティの向上(ラベルとフォーム要素の紐付け)とSSR(サーバーサイドレンダリング)の安全性のために使用されます。ランダムなIDを使用するとサーバーとクライアントで異なるIDが生成され、ハイドレーション時に不整合が発生する可能性がありますが、useIdは一貫したIDを生成するため、この問題を回避できます。複数のID が必要な場合は、基本IDに接尾辞を付けて使用します。

問題10

以下は、DOMの変更を同期的に処理するコードです。useEffectではちらつきが発生してしまうため、適切なフック名を埋めてください。

function NoFlickerComponent() {
  const [position, setPosition] = useState({ x: 0, y: 0 });

  ■■■■■■■■■■■■(() => {
    setPosition({ 
      x: window.innerWidth - 100, 
      y: window.innerHeight - 100 
    });
  }, []);

  return (
    <div
      style={{
        position: 'absolute',
        left: `${position.x}px`,
        top: `${position.y}px`
      }}
    >
      Hello World
    </div>
  );
}

問10の答えと解説を見る

正解: useLayoutEffect

解説: useLayoutEffectは、DOMの変更を同期的に処理するためのフックです。useEffectと異なり、ブラウザが画面を描画する前に実行されるため、視覚的なちらつき(flicker)を防ぐことができます。DOM要素のサイズや位置を測定・変更する処理、スクロール位置の調整、初期レンダリング時のレイアウト計算などに使用されます。ただし、同期実行のためパフォーマンスに影響を与える可能性があるので、必要な場合のみ使用し、通常はuseEffectを優先すべきです。

まとめ

これらのReact Hooksは、モダンなReactアプリケーション開発において重要な役割を果たします。特に以下の点に注意して実装することが重要です:

  • パフォーマンス: useMemo、useCallback、useTransition を適切に使用してレンダリング最適化を図る
  • データ取得: useEffectでの直接的なデータ取得は避け、専用ライブラリの使用を検討する
  • 型安全性: TypeScriptの型システムを活用し、各フックに適切な型定義を行う
  • ユーザー体験: useOptimistic、useTransitionを使用して応答性の高いUIを実現する

各種プロトコルにおける暗号化方式と鍵の利用法について:公開鍵で暗号化するんだっけ?秘密鍵で暗号化するんだっけ?

本記事では、代表的なネットワークプロトコルにおける暗号化処理と、公開鍵・秘密鍵の使い分けに関する要点を技術的に整理する。 クッソ間違うので目安とか無いかと思って調べてみた。


1. 鍵の基本的な役割

暗号化方式において、公開鍵暗号共通鍵暗号が存在する。

目的に応じて以下のように使い分ける。

目的 使用する鍵 代表例
内容の秘匿 受信者の公開鍵 PGP, TLS(鍵交換時)
送信者の証明 送信者の秘密鍵 電子署名, PGP署名, S/MIME

2. 各種プロトコルにおける鍵の利用法一覧

プロトコル 鍵の使い方 用途 鍵の種類 説明
TLS/SSLHTTPS サーバの公開鍵で共通鍵を暗号化 暗号化 公開鍵 → 共通鍵 公開鍵で共通鍵を安全に送信後、共通鍵暗号で通信
SSH クライアントまたはサーバの秘密鍵で署名・認証 署名+暗号化 公開鍵・秘密鍵 サーバまたはクライアント認証で鍵を利用
PGP/GPG 相手の公開鍵で暗号化、自分の秘密鍵で署名 暗号化+署名 公開鍵・秘密鍵 公開鍵で秘匿、秘密鍵で署名を実施
S/MIME 受信者の公開鍵で暗号化、送信者の秘密鍵で署名 暗号化+署名 公開鍵・秘密鍵 電子メールの暗号化と署名に使用
IPSec 事前共有鍵またはDH鍵交換で共通鍵を確立 暗号化 共通鍵 共通鍵を用いた対称暗号方式
Wi-Fi(WPA2等) PSK等から共通鍵を生成 暗号化 共通鍵 公開鍵暗号は基本使用せず共通鍵暗号を採用
X.509証明書 認証局秘密鍵で証明書に署名 署名 秘密鍵 発行元の信頼性を担保するための署名処理

3. まとめ

  • 暗号化を通じた秘匿性の確保には、受信者の公開鍵を使用する。
  • メッセージの真正性・送信者証明には、送信者の秘密鍵で署名する。
  • 通信の高速性と効率を重視するプロトコルTLSIPSecなど)は、共通鍵暗号とのハイブリッド方式を採用している。

プロトコルごとに目的と使用される鍵の種類を把握すると試験対策に役立ちそうですなぁ