<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0">
  <channel>
    <title>Json Media</title>
    <description>Json&apos;s Playground</description>
    <link>https://json.media</link>
    <pubDate>Fri, 26 Dec 25 00:00:00 +0000</pubDate>
    <lastBuildDate>Fri, 26 Dec 25 00:00:00 +0000</lastBuildDate>
    <image>
      <title>Json Media</title>
      <url>https://json.media/images/json-logo.png</url>
      <link>https://json.media</link>
    </image>
    <managingEditor>nallwhy@gmail.com (Jinkyou Son)</managingEditor>
    <webMaster>nallwhy@gmail.com (Jinkyou Son)</webMaster>
    <item>
      <title>PhoenixでLucideアイコンを使う</title>
      <description>Heroiconsだけでは足りないなら
Phoenixでは現在、以下のように Heroicons を CoreComponents.icon component にデフォルトで連携して提供しています。
defmodule MyApp.CoreComponents do
  @doc &quot;&quot;&quot;
  Renders a [Heroicon](https://heroicons.com).

  ...

  ## Examples

      &lt;.icon name=&quot;hero-x-mark-solid&quot; /&gt;
      &lt;.icon name=&quot;hero-arrow-path&quot; class=&quot;ml-1 w-3 h-3 animate-spin&quot; /&gt;
  &quot;&quot;&quot;
  attr :name, :string, required: true
  attr :class, :string, default: nil

  def icon(%&amp;lbrace;name: &quot;hero-&quot; &lt;&gt; _&amp;rbrace; = assigns) do
    ~H&quot;&quot;&quot;
    &lt;span class=&amp;lbrace;[@name, @class]&amp;rbrace; /&gt;
    &quot;&quot;&quot;
  end
end

HeroiconsはTailwind Labsが直接作ったアイコンライブラリなので期待していましたが、まだ足りないアイコンが多く、2024-11-18のv2.2.0以降は新しい更新がなく、実質的に放置されたプロジェクトに見えます。
これを補うために、Sidekickicons のようにHeroiconsスタイルのアイコンを追加したプロジェクトもありますが、なかなか活発にはなりにくいようです。
そこで、アイコン数が多く継続的に更新されている Lucide をPhoenixで使えるようにしてみました。

  
  v0.562.0時点でなんと1,666個のアイコンが登録されている。

PhoenixでLucideを使う設定
mix depsを追加
Heroiconsがtailwindlabs/heroiconsのGitHubリポジトリからoptimizedフォルダの内容だけを取得するように設定されているのと同様に、Lucideもiconsフォルダの内容だけを取得するよう、mix.exsのdeps/0に以下を追加します。
defmodule MyApp.MixProject do
  ...

  defp deps do
    [
      ...,
      &amp;lbrace;
        :lucide,
        github: &quot;lucide-icons/lucide&quot;,
        tag: &quot;0.562.0&quot;,
        sparse: &quot;icons&quot;,
        app: false,
        compile: false,
        depth: 1
      &amp;rbrace;
    ]
  end
end

lucide.js を作成
Phoenixがデフォルトで提供する heroicons.js を参考に、./assets/vendor/ に lucide.js も作成します。
Heroiconsはoutline/solid/mini/microの4種類に対してTailwind CSSの動的ユーティリティクラスを生成するため少し複雑ですが、Lucideはもっとシンプルです。さらにLucideに合わせてmask-sizeの設定を追加しました。
const plugin = require(&quot;tailwindcss/plugin&quot;)
const fs = require(&quot;fs&quot;)
const path = require(&quot;path&quot;)

module.exports = plugin(function (&amp;lbrace; matchComponents, theme &amp;rbrace;) &amp;lbrace;
  let iconsDir = path.join(__dirname, &quot;../../deps/lucide/icons&quot;)
  let values = &amp;lbrace;&amp;rbrace;

  fs.readdirSync(iconsDir).forEach(file =&gt; &amp;lbrace;
    if (file.endsWith(&quot;.svg&quot;)) &amp;lbrace;
      let name = path.basename(file, &quot;.svg&quot;)
      values[name] = &amp;lbrace; name, fullPath: path.join(iconsDir, file) &amp;rbrace;
    &amp;rbrace;
  &amp;rbrace;)

  matchComponents(&amp;lbrace;
    &quot;lucide&quot;: (&amp;lbrace; name, fullPath &amp;rbrace;) =&gt; &amp;lbrace;
      let content = fs.readFileSync(fullPath).toString().replace(/\r?\n|\r/g, &quot;&quot;)
      content = encodeURIComponent(content)
      let size = theme(&quot;spacing.6&quot;)

      return &amp;lbrace;
        [`--lucide-$&amp;lbrace;name&amp;rbrace;`]: `url(&amp;#39;data:image/svg+xml;utf8,$&amp;lbrace;content&amp;rbrace;&amp;#39;)`,
        &quot;-webkit-mask&quot;: `var(--lucide-$&amp;lbrace;name&amp;rbrace;)`,
        &quot;mask&quot;: `var(--lucide-$&amp;lbrace;name&amp;rbrace;)`,
        &quot;mask-size&quot;: &quot;contain&quot;,
        &quot;mask-repeat&quot;: &quot;no-repeat&quot;,
        &quot;background-color&quot;: &quot;currentColor&quot;,
        &quot;vertical-align&quot;: &quot;middle&quot;,
        &quot;display&quot;: &quot;inline-block&quot;,
        &quot;width&quot;: size,
        &quot;height&quot;: size
      &amp;rbrace;
    &amp;rbrace;
  &amp;rbrace;, &amp;lbrace; values &amp;rbrace;)
&amp;rbrace;)

app.css を変更
ここまで作成したLucideプラグインをTailwind CSSに登録するため、app.css に以下を追加します。
@plugin &quot;../vendor/lucide&quot;;

CoreComponents.icon component に &quot;lucide&quot; prefix を追加
既存の CoreComponents.icon component は&quot;hero&quot; prefixしか使えません。
以下のように&quot;lucide&quot; prefixも使えるように追加します。
defmodule MyApp.CoreComponents do
  ...

  attr :name, :string, required: true
  attr :class, :string, default: nil

  def icon(%&amp;lbrace;name: &quot;hero-&quot; &lt;&gt; _&amp;rbrace; = assigns) do
    ~H&quot;&quot;&quot;
    &lt;span class=&amp;lbrace;[@name, @class]&amp;rbrace; /&gt;
    &quot;&quot;&quot;
  end

  # lucide prefixを使えるように追加
  def icon(%&amp;lbrace;name: &quot;lucide-&quot; &lt;&gt; _&amp;rbrace; = assigns) do
    ~H&quot;&quot;&quot;
    &lt;span class=&amp;lbrace;[@name, @class]&amp;rbrace; /&gt;
    &quot;&quot;&quot;
  end
end

Lucideを使う
このように追加したLucideアイコンは、これまでHeroiconsを使っていたのと同じくらい簡単に使えます。
&lt;.icon name=&quot;lucide-newspaper&quot; /&gt;


  
  ヘッダーにそのまま適用。

実際にこのサイトにLucideを適用した全コードはこちらで確認できます。
これでアイコン不足から解放され、Lucideの大量のアイコンを使えるようになりました。Lucideのアイコンは今後も速いペースで増えていくので、必要に応じて定期的にLucideのバージョンを更新して使ってください。</description>
      <link>https://json.media/blog/ja/using-lucide-in-phoenix</link>
      <pubDate>Fri, 26 Dec 25 00:00:00 +0000</pubDate>
      <guid>https://json.media/blog/ja/using-lucide-in-phoenix</guid>
      <category>dev</category>
    </item>
    <item>
      <title>Ash Weekly: 第19号まとめ</title>
      <description>Ashホームページ/ドキュメント刷新、AshAdminファイルアップロード、AshAI非OpenAI LLM、UsageRules --sync-to-folderフラグ、Reactorドキュメント刷新、新しいAsh拡張。
Ash は現在Elixirで最も注目され、標準となりつつある宣言型フレームワークです。Ash Weekly はAshエコシステムで起きている出来事を毎週伝えており、その内容をまとめてお届けします。
原文: Ash Weekly: Issue #19
ホームページ &amp; What is Ashガイド刷新
Ashは他の言語では一般的でないコンセプトのフレームワークなので、その概念を理解するには追加の説明が必要です。
これまでホームページやドキュメントの説明がやや不足していましたが、今回AshホームページやドキュメントのWhat is Ash?セクションがアップデートされ、より分かりやすくなりました。
Ashがまだよく分からない方は、ぜひ一度ご覧ください！
AshAdminのファイルアップロード対応
AshAdminは、Ashの宣言から自動で管理画面を生成するライブラリです。
これまでファイルアップロードはできませんでしたが、今回:file型の引数に対して自動でファイルアップロードがサポートされるようになりました。（こうしたAshエコシステムの進化は多くがコミュニティメンバーによるものです👍）
デザインはまだあまり洗練されていませんが、今後の改善に期待です。
prompt-backed actionsでOpenAI以外のモデルも対応
AshAIはAshベースでAI関連の処理を簡単に作れるライブラリで、prompt-backed actionはLLMを使ってアクションを実行する機能です。
理解のため、AshAIのREADME.mdにある例を紹介します。
action :analyze_sentiment, :atom do
  constraints one_of: [:positive, :negative]

  description &quot;&quot;&quot;
  Analyzes the sentiment of a given piece of text to determine if it is overall positive or negative.
  &quot;&quot;&quot;

  argument :text, :string do
    allow_nil? false
    description &quot;The text for analysis&quot;
  end

  run prompt(
    LangChain.ChatModels.ChatOpenAI.new!(%&amp;lbrace; model: &quot;gpt-4o&quot;&amp;rbrace;)
  )
end

従来はOpenAIモデルのみ利用可能でしたが、さまざまなアダプターのサポートにより、他のプロバイダーのLLMも利用できるようになりました。
UsageRules --sync-to-folderフラグ
UsageRulesは各ライブラリのusage-rules.mdを集め、LLMのコンテキストとして使えるようにするプロジェクトです。
今回--sync-to-folderフラグが追加され、すべての内容を1つのファイルにまとめる代わりに、各ファイルへのリンク形式で利用できるようになりました。
例:
&lt;-- usage-rules-start --&gt;
&lt;-- ash-start --&gt;
## ash usage
[ash usage rules](deps/ash/usage-rules.md)
&lt;-- ash-end --&gt;
&lt;-- ash_ai-start --&gt;
## ash_ai usage
[ash_ai usage rules](deps/ash_ai/usage-rules.md)
&lt;-- ash_ai-end --&gt;
&lt;-- usage-rules-end --&gt;

この方法だとすべての内容をコンテキストに入れないため、トークン消費が減りますが、必要なファイルを探すのに時間がかかる場合もあります。用途に応じて使い分けてください。
Reactorドキュメント刷新
ReactorはSagaパターンを簡単に使えるようにするライブラリです。Sagaパターンは分散トランザクションの実装に適しています。
今回ドキュメントが刷新されたので、Sagaパターンに興味のある方はぜひご覧ください。
Changelogにコントリビューター名が記載
Ashプロジェクトに貢献すると、リリースノートに名前が記載されるようになりました。コミュニティ構築への取り組みが伺えます。
コミュニティ拡張
AshNeo4j
Ashで代表的なグラフデータベースNeo4jをサポートするライブラリです。
AshOutstanding
AshでOutstandingプロトコルをサポートするライブラリです。
Outstandingプロトコルは、期待する値が満たされているか、満たされていない場合はどこが未達かを簡単に把握できる仕組みのようです。
AshCommanded
AshでCQRS/ESパターンを簡単に適用できるCommandedをサポートするライブラリです。
CQRS/ESパターンは以前から試してみたいと思いつつまだ使ったことがありませんが、最近発表されたAshEventsもあるので、ぜひ挑戦してみたいです。
LLMs &amp; Elixir: Windfall or Deathblow
最近、Zach DanielによるLLMs &amp; Elixir: Windfall or DeathblowがHacker Newsで話題になりました。
最近のTidewave、Phoenix.new、UsageRulesなど、ElixirでAIを活用したコーディングをより簡単にする取り組みとも方向性が一致しています。</description>
      <link>https://json.media/blog/ja/ash-weekly-19-recap</link>
      <pubDate>Fri, 20 Jun 25 00:00:00 +0000</pubDate>
      <guid>https://json.media/blog/ja/ash-weekly-19-recap</guid>
      <category>dev</category>
    </item>
    <item>
      <title>Ash Weekly: 第18号まとめ</title>
      <description>AshPhoenix.Plug.CheckCodegenStatus、mix ash.codegen --dev、Shared Action Context、UsageRules、ash_ai.gen.chatの改善、Igniter.Scribe。
Ash は現在Elixirで最も注目されており、標準となりつつある宣言型フレームワークです。Ash Weekly はAshエコシステムで起きている出来事を毎週伝えており、その内容をまとめてお届けします。
原文: Ash Weekly: Issue #18
AshPhoenix.Plug.CheckCodegenStatus
AshPhoenix.Plug.CheckCodegenStatusプラグを利用すると、未実行のDBマイグレーションが存在する場合にPhoenixでマイグレーションを促す案内が表示されるのと同様に、Ashでコード変更によるコード生成が未実行の場合に親切な案内画面が表示されます。
提供されるボタンを押すことで、その操作をすぐに実行することもできます。

--devマイグレーション
上記で言及したmix ash.codegenを実行する際、--devオプションを使うと名前を付けることなくコード生成を進め、最後にmix ash.codegenで名前を付けて再実行すると、それまでに蓄積された作業をまとめてコード生成してくれます。
私たちDevAllCompanyではこのような機能を自作して使っていましたが、公式にサポートされて嬉しいです。
# 作業を蓄積した後
$ mix ash.codegen --dev

$ mix ash.codegen --dev

# ここで一度に再生成
$ mix ash.codegen create_user

Shared Action Context
Ashのアクションで使用していたcontextに、そのアクションから呼び出されるネストされたアクションにも伝播するsharedキーが追加されました。
伝播される値なので、大きすぎる値は入れないようにしましょう。並行性が使われる場合、プロセス間でコピーされるため注意が必要です。
MyApp.Domain.Resource.action(..., context: %&amp;lbrace;shared: %&amp;lbrace;key: &quot;value&quot;&amp;rbrace;&amp;rbrace;)

usage-rules.md
最近vibe codingをよくしていますか？Elixirは変化が速く、学習データが少ないため、LLMによるvibe codingの結果が満足できないことも多いですが、これをある程度解決できるUsageRulesプロジェクトが登場しました。
UsageRulesの仕組みはとてもシンプルです。
各ライブラリにあるusage-rules.mdファイルを集めて1つのファイルにまとめ、LLMがコンテキストとして使いやすくします。
例えばAshのusage-rules.mdには、Ashをどのように理解し使うべきかがまとめられています。
自分のプロジェクトでAshやAsh AIを使っている場合、以下のように実行すると、2つのライブラリのusage-rules.mdをまとめて1つのファイルにしてくれます。
$ mix usage_rules.sync CLAUDE.md ash, ash_ai

こうすることでClaudeを使う際に、その内容をコンテキストとしてvibe codingができます。
--allオプションで使用中のすべてのライブラリから取得することも可能です。
ash_ai.gen.chatの改善
mix ash_ai.gen.chatで生成されるコードでは、LLMのツールコールやツール結果が保存されるようになりました。
以前の会話を読み込んだ際にこれらの情報がないとコンテキストの多くが失われてしまいますが、今回の変更で過去の会話を引き継ぐ性能が大幅に向上したと思われます。
ただし、ツール結果が非常に大きくなることもあるため、保存やLLMへの再送信が常に最良かどうかは検討の余地があります。
Igniter.Scribe
Igniterは、ライブラリのインストールなどで必要なコード変更を自動で行うのを助けるライブラリです。
このとき、マニュアルガイド部分がコード変更に応じて自動で更新されず、手動で修正する必要があった点が改善されました。
自作ライブラリでIgniterを使っていた方には朗報です。</description>
      <link>https://json.media/blog/ja/ash-weekly-18-recap</link>
      <pubDate>Sun, 15 Jun 25 00:00:00 +0000</pubDate>
      <guid>https://json.media/blog/ja/ash-weekly-18-recap</guid>
      <category>dev</category>
    </item>
    <item>
      <title>Ash Weekly: 第17号まとめ</title>
      <description>Ash AI、ElixirConf EU 2025、Phoenix.new、Phoenix.Sync、AtomVM、Hologram、LangSchema。
Ashは、現在Elixirコミュニティで最も注目され、標準化が進んでいる宣言的フレームワークです。今回は、Ashエコシステムの最新情報を毎週お届けしているAsh Weeklyの内容をまとめてご紹介します。
原文: Ash Weekly: Issue #17
Ash AI リリース
最近、アプリケーション開発においてAI（LLM）の導入を検討しない開発者はほとんどいないと思います。このような状況で、強力な宣言的フレームワークであるAshにAI向けの拡張機能が追加されるのは当然の流れでした。
Ash AIリポジトリは2024年8月に作成され、そのコンセプトに期待が集まっていましたが、今回のElixirConf EU 2025で正式に発表されました。私も2025年3月から本格的にAsh AIを使い始め、貢献しています（現在#2コントリビューター）。
Ash AIは以下のような機能を提供します。

Prompt-backed Actions: AIを利用して結果を返す汎用的なアクションを簡単に宣言できます。
Tool Definition: 既に宣言したアクションをLLMのツールとして簡単に公開できます。
Vectorization: リソースに対してRAGを簡単に実装できます。
MCP Server: 開発用にアプリケーション情報を提供するMCPサーバーや、本番用に内部アクションをツールとして提供するMCPサーバーを簡単に作成できます。

参考: Ash AI: A comprehensive LLM toolbox for Ash Framework
ElixirConf EU 2025 まとめ
2025年5月14日〜16日にポーランド・クラクフでElixirConf EU 2025が開催されました。
ElixirConfはElixirユーザーにとって最大のイベントで、毎年上半期にEU、下半期にUSで開催されます。最大級のイベントの一つだけに、興味深い内容が多くありました。その中から主要なトピックが今回のニュースレターで共有されています。
Code generators are dead, long live code generators - Chris McCord
Chris McCordが所属するfly.ioからPhoniex.newというリモートコーディングエージェントサービスがリリースされました。
Zach DanielはPhoenix.newをIDE + Cloud + Elixir &amp; Phoenixに特化したコーディングアシスタントと表現しています。
AIの未来についてどう考えるかはさておき、ElixirでもAI関連の面白い試みが出てきていることを非常に前向きに評価しています。
現在はウェイトリスト経由でのみ利用可能なので、興味のある方は申し込んでみてください。
Introducing Phoenix.Sync - James Arthur
Phoenix.SyncはPhoenixにElectricを密接に統合し、リアルタイム同期を簡単に実現するための試みです。
Electricは優れたユーザー体験を提供するローカルファーストアプリケーションが増えている中で、それを実現する方法として注目していましたので、さらに期待が高まります。
LiveViewではなく、Reactやモバイル環境など、Electricが既に構築しているフロントエンド環境と連携できる点で、Phoenixの可能性がさらに広がる良い機会だと思います。
The AtomVM and New Horizons for Elixir
AtomVMはBEAMの軽量実装で、IoTデバイスやブラウザでErlang（およびElixir）をサポートすることを目指すプロジェクトです。
ElixirConf EU 2025ではブラウザでの動作によりフォーカスされていたようで、hexdocsのコードブロックをブラウザ上で直接実演することも可能だったようです。
今後、これを基盤にどのような試みが生まれるのか楽しみです。
Hologram: Building Rich UIs with Elixir Running in the Browser
HologramはElixirでフロントエンド／バックエンドの両方を記述することを目指すプロジェクトです。
LiveViewがバックエンドでほとんどを処理し、非常に薄いフロントエンドを志向するのに対し、Hologramは従来のアプリケーションのようにフロントエンドも独自の状態を持つ方向性ですが、それをElixirで簡単に記述できるようにしようとしているようです。
最初にリリースされた際に説明を読んでみましたが、まだコンセプトを完全には理解できていません。この方法でどこまで実装できるのか興味があります。
プロジェクト紹介 - LangSchema
Ash AIは現在、いくつかの機能がOpenAIのモデルのみ利用可能となっています。
これはAIプロバイダーごとにJSONスキーマ仕様が異なるためですが、この問題を解決するためにLangSchemaというライブラリを実装しました。
Abstract schemaという概念を設け、それを使ってコードを書くことで、AIプロバイダーのJSONスキーマ仕様に合わせて変換するというコンセプトです。
Ash AIでの利用も議論中なので、AI関連のコードを書く際にぜひ使ってみてください。</description>
      <link>https://json.media/blog/ja/ash-weekly-17-recap</link>
      <pubDate>Mon, 26 May 25 00:00:00 +0000</pubDate>
      <guid>https://json.media/blog/ja/ash-weekly-17-recap</guid>
      <category>dev</category>
    </item>
    <item>
      <title>오너십(주인의식)에 대하여</title>
      <description>주인이 아닌데 왜 주인의식을 가지라 그래??

그때는 전세나 월세로 살고 있다면 집을 꾸밀 수 있다는 생각은 전혀 하지 못했고 심지어 고장 나도 고치지 않고 살았던 모습이 떠오릅니다. 거주하는 집의 주인이 따로 있기 때문에 세입자들은 잠시 거쳐가는 집이라고 인식하는 경향이 강했기 때문인 것 같아요. 그런 분위기 속에 월세집을 자기 돈 써서 고치는 세입자가 있다는 사실에 첫째로 놀랐습니다.
-  뉴스레터 &apos;좋아하는 장소가 집이 아닌가요?&apos; 중

몇 달 전에 점핏 개취콘에서 &apos;중요한 건 인터페이스야, 바보야&apos; 라는 주제로 강연을 할 기회가 있었다.

  
  좋은 기회 감사합니다.

(강연 다시보기: 2023 두번째 개취콘, 백엔드 개발자 이야기 JUMPIT TO BACK - END)
강연이 끝나고 질문을 받는 시간이 있었는데, 아래와 같은 질문을 받았다.
&quot;함께 일하는 주니어 개발자 분들 중에 &apos;아 이 친구 정말 센스있게 일한다&apos; 라고 생각했던 분이 분명 있으실 것 같은데 어떤 부분에서 그렇게 느끼셨을지 궁금합니다.&quot;
그래서 &apos;오너십이 있는 사람과 일하는 경험이 좋았다&apos; 라는 내용으로 대답을 했는데, 어떤 분이 유튜브 채팅창에 이런 말을 올리셨다.
&quot;
신입한테 무슨오너까지..
직장인이 오너처럼 태도갖는사람 살면서본적이없음
오너만큼 돈받으면몰라도
&quot;
저 말대로 오너가 아닌 사람에게 오너십을 가져야한다고 얘기할 수는 없다.

내 집에 아닌 곳을 빌려서 살고 있는데, 집이 내 맘에 썩 들지 않으면 어떻게 할 것인가.
나는 내가 집의 주인이 아니라는 이유로 매일 집에 들어올 때 안 좋은 기분을 느끼고, 사람들을 초대할 때마다 집이 마음에 들지 않는 점들을 얘기하며 살아야 하는 사람은 누구인가?
내가 오너십을 가지고 집을 관리하면 집 주인이 덕을 보겠지. 하지만 그게 싫어서 오너십을 가지지 않으면 집이 좋아하는 공간이 될 수 없다.
내가 집의 주인이 아니라는 이유로 내 삶의 주인도 남에게 맡기는 것은 아닐까.

항상 오너십을 가져야한다는 것은 아니다. 그러기 좋지 않은 상황도, 그러기 어려운 상황도 있다.
다만 내가 오너십을 가지기로 선택했는지 가지지 않기로 선택했는지 명시적으로 생각해볼 필요는 있다.</description>
      <link>https://json.media/blog/ko/about-ownership</link>
      <pubDate>Sun, 05 Nov 23 00:00:00 +0000</pubDate>
      <guid>https://json.media/blog/ko/about-ownership</guid>
      <category>essay</category>
    </item>
    <item>
      <title>&apos;포기사회&apos;를 지나 &apos;파괴사회&apos;로 가고 있는 한국</title>
      <description>희망이 없으면 파괴하지 않을 이유가 있을까?
지난 글 포기하지 않기 위해서는 핑계가 필요해 에서 한국이 이미 &apos;피로사회&apos;에서 &apos;포기사회&apos;가 되었다고 얘기했다.

  

포기사회의 다음은 어디일까? 나는 &apos;파괴사회&apos; 라고 생각한다.
룰은 희망이 있을 때 지킬 이유가 있다. 룰을 어기면 사회의 처벌로 인해 미래에 대한 희망이 깨지기 때문이다.
반대로 희망이 없으면 룰을 어겨도 딱히 아쉬울 것이 별로 없다. 오히려 얻을 것이 더 많을 수도 있다. 분노 해소, 쾌감, 세상의 관심...
희망을 모두 포기하고 나면 파괴를 하지 않을 이유가 무엇이 남을까?
우리나라도 요즘 묻지마 살인 등이 파괴 범죄가 발생하고 있는데, 전체적인 범죄율 자체는 낮지만 포기한 혹은 포기당한 사람들이 이러한 파괴로 이어지고 있다고 생각한다.

  
  “남들도 불행하게 만들고 싶었다” https://biz.heraldcorp.com/view.php?ud=20230724000215

우리나라에서 포기를 하는 사람의 수는 계속 늘고 있다. 2022년 우리나라의 은둔형 외톨이 청년의 수는 24만명 규모로 추산되며, 이는 청년 인구의 2.4% 에 해당한다. 히키코모리로 유명한 일본보다도 한참 높은 수치라고 한다.

  
  https://www.seoul.co.kr/news/newsView.php?id=20230307500184

우리나라보다 일찍이 포기사회에 들어간 일본은 사회적 고립을 해소하기 위한 움직임이 일어나고 있다.

  
  https://www.khan.co.kr/world/world-general/article/202308061426001

사회 전반에 어떤 큰 움직임이 발생한다면 이는 사회의 압력이 발생시키는 문제다. 하지만 아직 우리나라에서는 이를 사회의 문제로 보기보다 개인의 문제로 보는 시각이 강하다.
예를 들어 학교에서 문제가 되는 학생은 퇴학은 시키면 되고, 범죄를 저지르는 사람은 감옥에 보내면 되며, 정신병이 생긴 사람은 정신병원에 보내면 된다는 것이다. 문제가 되는 사람을 사회에서 도태시키면 문제가 해결된다고 생각한다.
하지만 눈앞에서 보이지 않는다고 없어지는 것은 아니다. 이렇게 도태된 개인이 사라지면 해결되는 문제라는 피상적인 인식 때문에 본질적인 해결책은 논의되기 어려울 것이며, 앞으로도 사회 파괴적 범죄는 더 많아질 것으로 예상한다.
그리고 문제가 한참 더 심각해지고 나서야 이를 제대로 들여다보기 시작할 것이다.</description>
      <link>https://json.media/blog/ko/from-resignation-society-to-destruction-society</link>
      <pubDate>Wed, 25 Oct 23 00:00:00 +0000</pubDate>
      <guid>https://json.media/blog/ko/from-resignation-society-to-destruction-society</guid>
      <category>essay</category>
    </item>
    <item>
      <title>포기하지 않기 위해서는 핑계가 필요해</title>
      <description>핑곗거리가 부족한 포기사회의 사람들을 위하여

마모루: 네가 변명하길 바랐다.
일보: 그, 그치만 KO패 인데요? 완패인데? 변명 같은 걸 하면... 화내실 텐데요.
마모루: 화내는 게 당연하지. 등짝을 철썩철썩 때릴지도 몰라.
기뻐서 말이야.
보기 흉하고, 비루하고, 뻔뻔해도 돼. 아무리 꼴사나워도 괜찮아.
넌 아직 지지 않았다. 한 번 더 붙으면 이길 수 있다.
이런 말을 하란 말이야.
인정할 때가 끝나는 때다. 한 번 더 일어설 거면, 남자한테는 변명이 필요해.
-  109권 중

개인적으로 자기합리화를 잘해서 늘 핑계가 있는 편이다.
고등학교 때 성적이 나보다 잘 나오는 친구가 있을 때 &quot;그런데 쟤는 공부만 잘하잖아. 나는 여러 가지를 하니까.&quot;, 준비했던 결과가 잘 나오지 않았을 때 &quot;이번 거는 최선을 다 하지 않았어. 다른 거를 더 열심히 하려고 했어&quot;.
그런 성격 때문에 그동안 여러 사건들에서 좌절하지 않고 계속 해올 수 있었나 싶기도 하다.

한병철은  에서 저자는 과잉 긍정성의 성과사회에서 피로해지는 개인에 대한 이야기를 담았다.

&apos;아무것도 가능하지 않다&apos;는 우울한 개인의 한탄은 &apos;아무것도 불가능하지 않다&apos;고 믿는 사회에서만 가능한 것이다. 더 이상 할 수 있을 수 없다는 의식은 파괴적 자책과 자학으로 이어진다.
-  중

현대 사회는 개인에게서 불가능에대한 핑곗거리를 앗아갔다.
&quot;공부를 하고 싶어? 너는 하버드의 수업을 무료로 들을 수 있어. 옛날에는 책을 못사서 줏어다가 공부를 했어. 지금 시대에 공부를 못한다면 오로지 원인은 너야.&quot;
그래서 뭔가를 실패한 개인에게는 한 번 더 시도할 수 있는 원동력인 핑계가 없다. 그저 포기하게 될 뿐이다.
이 책으로 2016년 트레바리에서 독서모임을 했을 때, &apos;피로사회&apos;의 다음은 무엇일까에 대해 얘기 나눴었고 나는 &apos;포기사회&apos;일 것이라고 말했었다.
일본은 그때 당시 프리터, 히키코모리로 대표되는 사회 문제를 겪고 있었고, 우리나라도 이미 피로사회의 단계에 들어선 상태에서 일본을 따라가고 있다고 생각했기 때문이다.
그리고 2023년인 지금 이미 &apos;포기사회&apos;에 도달했다고 생각한다. 대표적으로 결혼과 출산을 포기해서 매우 낮은 혼인율과 출산율을 보이고 있고, 미래에 대한 희망을 포기해서 현재를 위한 과한 소비를 하고 있고, 보이지 않는 곳에서는 고독사가 일어나고 있다.
(간혹 &apos;피로사회&apos;의 해석 중에 탈진의 피로가 아닌 무위의 피로를 기반으로 &apos;현대사회 = 성과사회  피로사회&apos;의 개념으로 이야기 하려는 해석들이 있으나, 해당 내용은 책의 말미에 나오는 무위의 피로에 대한 이야기의 연장일 뿐 저자의 다른 원고 ,  등으로 미루어보았을 때 저자는 &apos;현대사회 = 성과사회 = 피로사회&apos; 라고 말하고자 하는 것이라고 생각한다.)

오히려 더 증가하고 있는 것은 재도전이 아닌 포기를 위한 핑계다. 포기를 위한 핑계는 현상이 아니라 자기 본질에 대해 핑계를 댄다.
예를 들면 성인 ADHD 가 그렇다. 나도 내가 성인 ADHD 이기를, 그래서 어쩔 수 없는 한계 짓기의 핑계를 얻을 수 있기를 기대했었으나, 검사 결과 그런 건 아니라고 한다.
MBTI 도 어찌보면 자신을 한계 짓고 포기하기 위한 핑계로 유행하고 있는지도 모른다.
매크로하게 사라져버린 원동력의 핑계를 개인이 찾아오기는 힘들다.

라고 쓰고보니, 내가 재도전을 위한 핑계를 말하는 것이 과잉 긍정성인가 싶다. 포기하면 편할 수도 있지 않은가?
무결론의 마무리</description>
      <link>https://json.media/blog/ko/excuse-to-avoid-giving-up</link>
      <pubDate>Sat, 23 Sep 23 00:00:00 +0000</pubDate>
      <guid>https://json.media/blog/ko/excuse-to-avoid-giving-up</guid>
      <category>essay</category>
    </item>
    <item>
      <title>당연한 것처럼 말하는 잘못된 가정 속에 역린이 있다</title>
      <description>건드리고 싶지만 건드리지 않는 편이 나은
어떤 사람과 논쟁을 할 때 그 사람이 충분히 논리적인 사람임에도 전혀 논리적이지 않은 논리의 근원이 있다면, 그것은 건드리지 않는 것이 좋다.
그곳에는 그 사람이 그렇게 하고 싶지 않았지만 그렇게 해버리고만 부끄러움이 있다.
인간이 그런 부끄러움에 대해 대응하는 방법은 크게 두 가지이다.

처음부터 솔직하게 말한다.
거기까지 상대방이 파고들지 않기를 바라면서 거짓말을 한다.

그런 것을 처음부터 솔직하게 말할 수 있는 사람이 얼마나 있을까?
대부분 제발 여기까지 파고들지 않기를 기대하는 마음으로 거짓말을 하며 버틴다.
그러다 그것이 파내어지고나면 그 사람에게 남은 선택지가 별로 없게 된다.

이제와서 자신도 그것이 아님을 알면서도 거짓말을 했음을 솔직히 인정한다.
상대방에게 화를 낸다.

여기서도 마찬가지로, 이제와서 앞의 모습은 다 알면서도 한 거짓이었음을 솔직하게 인정할 수 있는 사람이 얼마나 있을까?
대부분은 후자의 결과를 보게 될 것이다.
그것이 그렇게 궁금한가?

Cover Image: generated by DALL·E 2 with prompt &apos;There&apos;s a hidden danger in the incorrect assumptions spoken as if they&apos;re obvious it&apos;s better not to touch it even if one wants to&apos;</description>
      <link>https://json.media/blog/ko/hidden-danger-in-illogical-assumptions</link>
      <pubDate>Wed, 20 Sep 23 00:00:00 +0000</pubDate>
      <guid>https://json.media/blog/ko/hidden-danger-in-illogical-assumptions</guid>
      <category>essay</category>
    </item>
    <item>
      <title>하지 않아도 되는데 굳이 하는 행동에 욕망이 있다</title>
      <description>부러우니까 자랑을 하고 자랑을 하니까 부러워지고

부러우니까 자랑을 하고 자랑을 하니까 부러워지고
-  - 장기하

예를 들어 누군가 누가 묻지도 않았는데 굳이 &quot;나는 이러이러한 사람이야&quot; 라고 말한다면, 그것은 다른 사람들이 나를 그런 사람으로 알아줬으면 하는 욕망 때문일 것이다.
너무 뻔한 얘기인가?
그 사람이 정말 내가 &quot;그러그러한&quot; 사람인 것 자체가 중요했다면 굳이 저렇게 얘기하지 않았을 것이다.
내가 그런 사람인데 사람들이 그렇다고 생각해주지 않는 것은 실제로는 그런 사람이 아니기 때문일 가능성이 높다.
그렇다면 그 사람은 자신이 되고 싶은 자신과 실제 자신 사이에 괴리가 있는 것이다.
그것이 사람의 욕망이다.
그 괴리로 인한 욕망은 좀처럼 채워지지 않는다. 왜냐하면 실제로 자신이 원하는 사람이 될 수 있는 경우는 잘 없기 때문이다.
그 욕망을 잘 파악해서 건드린다면, 그 사람을 내가 원하는 대로 다루기 쉬워진다.

나는 이 글을 왜 썼을까?

Cover Image: generated by DALL·E 2 with prompt &apos;person who is jealous, photo, no text&apos;</description>
      <link>https://json.media/blog/ko/desire-in-not-necessary-actions</link>
      <pubDate>Mon, 11 Sep 23 00:00:00 +0000</pubDate>
      <guid>https://json.media/blog/ko/desire-in-not-necessary-actions</guid>
      <category>essay</category>
    </item>
    <item>
      <title>B2B SaaS 의 보안을 높여주는 데이터 암호화 in Elixir</title>
      <description>Elixir 로 B2B SaaS 를 만드는 여정 - (2)
Elixir 로 B2B SaaS reflow 를 만들면서 경험한 내용 시리즈입니다.

B2B SaaS 의 보안을 높여주는 Multi-Tenancy in Elixir
B2B SaaS 의 보안을 높여주는 데이터 암호화 in Elixir
B2B SaaS 의 보안을 높여주는 Redaction in Elixir
Job Scheduling 예정
Feature Flag 예정
Obfuscation 예정


B2B SaaS 는 대체로 고객의 민감한 정보를 다루기 때문에 암호화의 필요성을 더 말할 필요는 없을 것 같습니다.
이번 글에서는 암호화가 무엇이고, Elixir 에서 암호화를 어떻게 구현할 수 있는지 알아봅니다.
암호화란 무엇인가
암호화는 어떤 정보를 encoding 하여, 나중에 권한을 가지고 있는 주체만 이를 복호화해서 정보를 볼 수 있도록 하는 것을 말합니다.

In cryptography, encryption is the process of encoding information. This process converts the original representation of the information, known as plaintext, into an alternative form known as ciphertext. Ideally, only authorized parties can decipher a ciphertext back to plaintext and access the original information.
- Wikipedia - Encryption

저장되거나 전송되는 고객의 정보가 절대 탈취당하지 않으면 좋겠지만, 불의의 사고는 항상 일어나기 마련입니다. 암호화는 누군가 저장되거나 전송되는 정보를 탈취하더라도, 그 정보를 해석할 수 없게 하여 최종적으로 고객 정보의 유출을 막기위해 사용됩니다.
예를 들어 데이터베이스에 저장되어있던 데이터들이 탈취당한다고 하더라도, 데이터가 암호화 되어있다면 암호화 키도 같이 탈취당한 것이 아닌 이상 데이터 유출 걱정은 적습니다.
간단한 암호화 방법의 예
간단한 암호화 방법을 한 번 살펴볼까요?
Caesar cipher 는 고대 로마의 황제 시저가 사용했던 암호화 방법으로, 암호화 하고자 하는 글의 알파벳을 일정 차이만큼 다른 알파벳으로 바꾸는 암호화 방법입니다.
예를 들어, A -&gt; C, B -&gt; D, C -&gt; E 이렇게 2글자 차이만큼 다른 알파벳으로 바꿔서 적는 것이죠.
그러면 APPLE -&gt; CRRNG 와 같이 암호화되어 원래 내용을 쉽게 알아볼 수 없게 됩니다.

  
  Caesar cipher 는 이런 기계를 이용하여 쉽게 암호화/복호화 할 수 있습니다.

이러한 암호화를 공격하는 방법에는 대표적인 몇 가지 방법들이 있습니다.
암호화 키 탈취
암호화는 복호화를 할 수 있어야 하기에, 암호화된 정보를 복호화 할 수 있는 키가 존재합니다. 따라서 이 키를 탈취하면 쉽게 암호화된 정보를 복호화 할 수 있습니다. 위의 예시에서 CRRNG 가 2글자 차이로 암호화 되었다는 사실을 알면 APPLE 로의 복호화는 매우 쉽습니다.
통계적인 특성으로 유추
Caesar cipher 로 긴 영어 문장을 암호화했다고 가정합시다. 우리는 영어에서 e 가 가장 빈도가 높은 알파벳임을 알고 있습니다. 따라서 암호화된 정보에서 빈도가 높은 알파벳들이 e 라는 가정하에 복호화를 시도하면 이를 쉽게 성공할 수 있습니다.
반복적인 내용으로 유추
Caesar cipher 로 두 사람간의 편지를 암호화했다고 가정합시다. 오가는 편지를 여러 개 모아서 보면, 편지가 시작할 때 자주 보이는 패턴이 Hi 같이 자주 사용되는 인사가 아닐까 생각해볼 수 있습니다. 이런 방식으로 암호화된 정보를 많이 모아서 규칙을 찾아 암호화를 공격할 수 있습니다.
무차별 대입 (Brute Force)
Caesar cipher 는 암호화 할 수 있는 방법이 알파벳 개수인 26가지 밖에 되지 않습니다. 따라서 26가지 방법을 다 시도하면 복호화를 할 수 있습니다.
이 밖에도 많은 암호화 공격 방법이 있습니다.
현대 암호화 방법은 키의 값이 매우 크다든지, 같은 정보를 반복적으로 암호화 해도 다른 결과로 암호화 된다든지, 주기적으로 키를 rotation 할 수 있다든지 등의 방법으로 여러가지 공격에 최대한 대응할 수 있도록 설계되어있습니다.
Elixir 로 데이터 암호화 구현하기
Cloak 은 Elixir 에서 데이터를 암호화를 도와주는 라이브러리로, 아래와 같은 특징을 가지고 있습니다.

AES-GCM, AES-CTR 두 가지 암호화 방법을 자체적으로 지원하며, 원하면 직접 암호화 방법을 구현하여 사용할 수도 있습니다.
Random IV(Initialization Vector) 기능을 제공하기 때문에 같은 정보를 반복적으로 암호화 해도 매번 다른 결과로 암호화 되어 보안적으로 실수하지 않게 해줍니다.
암호화 결과에 태그 정보가 있어서, 나중에 암호화 키를 rotation 하기 용이합니다.
Cloak.Ecto 도 함께 제공하여, 데이터베이스 암호화에 쉽게 사용할 수 있습니다. (Ecto 는 Elixir 에서 데이터베이스 관련 작업을 도와주는 라이브러리입니다.)

Cloak 으로 데이터베이스에 저장하기/불러오기 시 자동으로 암호화/복호화 되도록 하는 작업해보겠습니다.
Cloak 설정하기
먼저 Cloak, Cloak.Ecto 를 dependency 에 추가해줍니다.
defmodule MyApp.MixProject do
  use Mix.Project

  ...

  defp deps do
    [
      ...
      &amp;lbrace;:cloak, &quot;~&gt; 1.1&quot;&amp;rbrace;,
      &amp;lbrace;:cloak_ecto, &quot;~&gt; 1.2&quot;&amp;rbrace;
    ]
  end
end

다음으로 암호화/복호화를 담당하는 Vault module 을 만들고, config 를 추가해줍니다. 여기서는 암호화 방법으로 AES-GCM 을 이용했습니다.
defmodule MyApp.Vault do
  use Cloak.Vault, otp_app: :my_app
end

import Config

...

config :my_app, MyApp.Valut,
  ciphers: [
    default: &amp;lbrace;Cloak.Ciphers.AES.GCM, tag: &quot;AES.GCM.V1&quot;, key: Base.decode64!(&quot;your-key-here&quot;)&amp;rbrace;
  ]

cipher key 는 IEx(Interactive Shell) 등에서 아래와 같은 방법으로 쉽게 만들 수 있습니다.
iex&gt; 32 |&gt; :crypto.strong_rand_bytes() |&gt; Base.encode64()
&quot;HXCdm5z61eNgUpnXObJRv94k3JnKSrnfwppyb60nz6w=&quot;

마지막으로 Application supervison tree 에 추가해주면 Cloak 을 사용할 준비는 끝납니다.
defmodule MyApp.Application do
  use Application

  ...

  def start(_type, _args) do
    children = [
      ...,
      MyApp.Vault
    ]
  end
end

Cloak 으로 암호화/복호화 하기
위에서 만든 MyApp.Vault module 로 아래와 같이 쉽게 암호화/복호화를 할 수 있습니다.
iex&gt; &amp;lbrace;:ok, ciphertext&amp;rbrace; = MyApp.Vault.encrypt(&quot;plaintext&quot;)
&amp;lbrace;:ok, &lt;&lt;1, 10, 65, 69, 83, 46, 71, 67, 77, 46, 86, 49, 93, 140, 255, 234,
1, 195, 125, 112, 121, 186, 169, 185, 129, 122, 237, 161, 160, 24, 166,
48, 224, 230, 53, 194, 251, 175, 215, 10, 186, 130, 61, 230, 176, 102,
213, 209, ...&gt;&gt;&amp;rbrace;

iex&gt; MyApp.Vault.decrypt(ciphertext)
&amp;lbrace;:ok, &quot;plaintext&quot;&amp;rbrace;

Cloak.Ecto 로 데이터베이스 저장하기/불러오기 시에 자동으로 암호화/복호화 하기
먼저 각 Vault, 각 type 별로 local Ecto type 을 선언해줘야 합니다. 여기서는 MyApp.Vault 로 Binary(String) 을 저장하기 위한 local Ecto type 을 선언해보겠습니다.
defmodule MyApp.Encrypted.Binary do
  use Cloak.Ecto.Binary, vault: MyApp.Vault
end

다음으로 새로 User 를 만들면서 email 을 암호화 하고자 하는 시나리오로 구현해보겠습니다.
users table 을 만들 때 encrypted_email column 을 binary type 으로 설정해줍니다. (email 로 만들어도 되지만 column 명이 명확한 것을 좋아합니다.)
defmodule MyApp.Repo.Migrations.CreateUsers do
  use Ecto.Migration

  def change do
    create table(:users) do
      field :encrypted_email, :binary, null: false
    end
  end
end

defmodule MyApp.Accounts.User do
  use Ecto.Schema

  schema &quot;users&quot; do
    field :email, MyApp.Encrypted.Binary, source: :encrypted_email
  end
end

이렇게 field type 만 설정해주면 데이터를 데이터베이스에 저장하고 불러올 때 자동으로 암호화/복호화가 되어 어플리케이션에서는 신경쓸 것이 없습니다.
MyApp.Repo.get(MyApp.Accounts.User, 1)
# =&gt; %Accounts.User&amp;lbrace;email: &quot;test@example.com&quot;&amp;rbrace;


이렇게 Elixir 에서는 적은 코드의 수정으로 전체 어플리케이션에 데이터 암호화를 적용할 수 있습니다.
이는 더 빠르고 안전한 B2B SaaS 개발로 이어집니다.
다음 글에서는 &apos;B2B SaaS 의 보안을 높여주는 Redaction in Elixir&apos; 에 대해 얘기해보도록 하겠습니다.
감사합니다!

References:

Why Your SaaS App Needs Better Encryption
</description>
      <link>https://json.media/blog/ko/data-encryption-in-elixir</link>
      <pubDate>Thu, 17 Aug 23 00:00:00 +0000</pubDate>
      <guid>https://json.media/blog/ko/data-encryption-in-elixir</guid>
      <category>dev</category>
    </item>
  </channel>
</rss>