Profile img

lionhairdino

@lionhairdino@hackers.pub · 73 following · 80 followers

여행 기분내며, 여기 저기 낙서하는 https://yearit.com 을 운영 중입니다.

지금까지 다루어 봤던 언어는 아래와 같습니다. MSX Basic Z80 Assembly Pascal GW-Basic C Macromedia Director Visual Basic PHP Flash Actionscript C++ Javascript

그리고 지금은, 하스켈을 비즈니스에 쓰려고 몇 년간 노력하고 있습니다. 지금 상태는, 하스켈 자체를 연구하는 게 아니라, 하스켈 (혹은 함수형 언어) 이해가 어려운 이유를 연구하는 아마추어 연구가쯤 되어버렸습니다. 하스켈 주제로 블로그를 운영 중이지만, 아직은 하스켈 프로그래머라고 자신 있게 말하진 못하고 있습니다. 가끔 이해에 도움이 될만한 측면이 보이면, 가볍게 아이디어를 여러 SNS에 올려보곤 하는데, 그다지 프로그래머에게 쓸모 있는 내용이 포함되진 않는 것 같습니다.

Blog
lionhairdino.github.io
YearIt
yearit.com
0
0

lionhairdino replied to the below article:

애플리케이션 개발 측면에서 본 Drizzle ORM 대 Kysely 비교

洪 民憙 (Hong Minhee) @hongminhee@hackers.pub

TypeScript로 백엔드 서버를 개발하면서 적절한 ORM 선택은 항상 중요한 결정 중 하나입니다. 최근 제 프로젝트에서 Drizzle ORM과 Kysely를 모두 사용해 볼 기회가 있었는데, 개인적으로는 Drizzle ORM이 더 편리하고 생산성이 높았던 경험을 공유하고자 합니다.

두 ORM에 대한 간략한 소개

Drizzle ORM은 TypeScript용 ORM으로, 타입 안전성과 직관적인 API를 강점으로 내세우고 있습니다. 스키마 정의부터 마이그레이션, 쿼리 빌더까지 풀스택 개발 경험을 제공합니다.

Kysely는 “타입 안전한 SQL 쿼리 빌더”로 자신을 소개하며, 타입스크립트의 타입 시스템을 활용해 쿼리 작성 시 타입 안전성을 보장합니다.

두 도구 모두 훌륭하지만, 제 개발 경험에 비추어 볼 때 Drizzle ORM이 몇 가지 측면에서 더 편리했습니다.

Drizzle ORM을 선호하게 된 이유

스키마 정의의 직관성

Drizzle ORM의 스키마 정의 방식은 매우 직관적이고 선언적입니다:

import { pgTable, serial, text, integer } from 'drizzle-orm/pg-core';

export const users = pgTable('users', {
  id: serial('id').primaryKey(),
  name: text('name').notNull(),
  email: text('email').unique().notNull(),
  age: integer('age')
});

Drizzle ORM은 이 스키마 정의로부터 자동으로 CREATE TABLE SQL을 생성할 수 있어, 스키마와 코드가 항상 동기화되어 있습니다.

반면 Kysely는 타입 정의에 더 중점을 두고 있어 스키마와 타입 정의가 분리되는 경향이 있습니다:

interface Database {
  users: {
    id: Generated<number>;
    name: string;
    email: string;
    age: number | null;
  };
}

이 타입 정의는 TypeScript 코드에서 타입 안전성을 제공하지만, 이 타입 정의만으로는 CREATE TABLE SQL을 생성할 수 없다는 것이 결정적인 단점입니다. 실제로 테이블을 생성하려면 별도의 SQL 스크립트나 마이그레이션 코드를 작성해야 합니다. 이는 타입과 실제 데이터베이스 스키마 간의 불일치 가능성을 높입니다.

Drizzle의 접근 방식이 데이터베이스 스키마와 TypeScript 타입을 더 긴밀하게 연결해주어 개발 과정에서 혼란을 줄여주었습니다.

마이그레이션 경험

Drizzle ORM의 마이그레이션 도구(drizzle-kit)는 정말 인상적이었습니다. 스키마 변경사항을 자동으로 감지하고 SQL 마이그레이션 파일을 생성해주는 기능이 개발 워크플로우를 크게 개선했습니다:

npx drizzle-kit generate:pg

이 명령어 하나로 스키마 변경사항에 대한 마이그레이션 파일이 생성되며, 이를 검토하고 적용하는 과정이 매우 간단했습니다.

반면 Kysely의 마이그레이션은 본질적으로 수동적입니다. 개발자가 직접 마이그레이션 파일을 작성해야 하며, 스키마 변경사항을 자동으로 감지하거나 SQL을 생성해주는 기능이 없습니다:

// Kysely의 마이그레이션 예시
async function up(db: Kysely<any>): Promise<void> {
  await db.schema
    .createTable('users')
    .addColumn('id', 'serial', (col) => col.primaryKey())
    .addColumn('name', 'text', (col) => col.notNull())
    .addColumn('email', 'text', (col) => col.unique().notNull())
    .addColumn('age', 'integer')
    .execute();
}

async function down(db: Kysely<any>): Promise<void> {
  await db.schema.dropTable('users').execute();
}

이러한 수동 방식은 복잡한 스키마 변경에서 실수할 가능성이 높아지고, 특히 큰 프로젝트에서는 작업량이 상당히 증가할 수 있었습니다.

하지만 Kysely의 마이그레이션에도 두 가지 중요한 장점이 있습니다:

  1. TypeScript 기반 마이그레이션: Kysely의 마이그레이션 스크립트는 TypeScript로 작성되기 때문에, 마이그레이션 로직에 애플리케이션 로직을 통합할 수 있습니다. 예를 들어, S3와 같은 오브젝트 스토리지의 데이터도 함께 마이그레이트하는 복잡한 시나리오를 구현할 수 있습니다. 반면 Drizzle ORM은 SQL 기반 마이그레이션이므로 이러한 통합이 불가능합니다.

  2. 양방향 마이그레이션: Kysely는 updown 함수를 모두 정의하여 업그레이드와 다운그레이드를 모두 지원합니다. 이는 특히 팀 협업 환경에서 중요한데, 다른 개발자의 변경사항과 충돌이 발생할 경우 롤백이 필요할 수 있기 때문입니다. Drizzle ORM은 현재 업그레이드만 지원하며, 다운그레이드 기능이 없어 협업 시 불편할 수 있습니다.

참고로, Python 생태계의 SQLAlchemy 마이그레이션 도구인 Alembic은 훨씬 더 발전된 형태의 마이그레이션을 제공합니다. Alembic은 비선형적인 마이그레이션 경로(브랜치포인트 생성 가능)를 지원하여 복잡한 팀 개발 환경에서도 유연하게 대응할 수 있습니다. 이상적으로는 JavaScript/TypeScript 생태계의 ORM도 이러한 수준의 마이그레이션 도구를 제공하는 것이 바람직합니다.

관계 설정의 용이성

Drizzle ORM에서 테이블 간 관계 설정이 매우 직관적이었습니다:

import { relations } from 'drizzle-orm';

export const usersRelations = relations(users, ({ one, many }) => ({
  profile: one(profiles, {
    fields: [users.id],
    references: [profiles.userId],
  }),
  posts: many(posts)
}));

이 방식은 데이터베이스 설계의 본질적인, 관계적인 측면을 명확하게 표현해주었습니다.

쿼리 작성의 편의성과 동일 이름 칼럼 문제 처리

두 ORM 모두 쿼리 작성을 위한 API를 제공하지만, Drizzle의 접근 방식이 더 직관적이고 관계형 모델을 활용하기 쉬웠습니다:

// Drizzle ORM - db.query 방식으로 관계 활용
const result = await db.query.posts.findMany({
  where: eq(posts.published, true),
  with: {
    user: true  // 게시물 작성자 정보를 함께 조회
  }
});

// 결과 접근이 직관적이고 타입 안전함
console.log(result[0].title);       // 게시물 제목
console.log(result[0].user.name);   // 작성자 이름 - 객체 구조로 명확하게 구분됨
console.log(result[0].user.id);     // 작성자 ID - 게시물 ID와 이름이 같아도 문제 없음

// Kysely
const result = await db
  .selectFrom('posts')
  .where('posts.published', '=', true)
  .leftJoin('users', 'posts.userId', 'users.id')
  .selectAll();

// 결과 접근 시 칼럼 이름 충돌 문제
console.log(result[0].id) // 오류: posts.id와 users.id 중 어떤 것인지 모호함
console.log(result[0].name) // 오류: 둘 다 name 칼럼이 있다면 모호함

Drizzle의 접근 방식이 테이블과 컬럼을 참조할 때 타입 안전성을 더 강력하게 보장하고, 관계를 활용한 쿼리 작성이 더 직관적이었습니다.

특히 여러 테이블 조인 시 동일한 이름의 칼럼 처리 부분에서 Drizzle ORM이 훨씬 더 편리했습니다. 이는 제 개발 경험에서 가장 중요한 차이점 중 하나였습니다.

// Drizzle ORM - 동일 이름 칼럼 처리
const result = await db.query.posts.findMany({
  with: {
    user: true  // posts.id와 users.id가 모두 있지만 자동으로 구분됨
  }
});

// 결과에 자연스럽게 접근 가능
console.log(result[0].id);        // 게시물 ID
console.log(result[0].user.id);   // 사용자 ID - 명확하게 구분됨
console.log(result[0].user.name); // 사용자 이름

// Kysely - 동일 이름 칼럼 처리를 위해 별칭 필요
const result = await db
  .selectFrom('posts')
  .leftJoin('users', 'posts.userId', 'users.id')
  .select([
    'posts.id as postId',       // 별칭 필수
    'posts.title',
    'posts.content',
    'users.id as userId',       // 별칭 필수
    'users.name as userName',   // 칼럼 이름이 같을 수 있으므로 별칭 필수
    'users.email as userEmail'  // 일관성을 위해 모든 사용자 관련 칼럼에 접두어 필요
  ]);

// 별칭을 통한 접근
console.log(result[0].postId);    // 게시물 ID
console.log(result[0].userId);    // 사용자 ID
console.log(result[0].userName);  // 사용자 이름

Drizzle ORM은 테이블과 칼럼을 객체로 참조하기 때문에, 동일한 이름의 칼럼이 있어도 자연스럽게 계층 구조로 처리되며 타입 추론도 정확하게 작동합니다. 반면 Kysely에서는 문자열 기반 접근 방식 때문에 별칭을 수동으로 지정해야 하는 경우가 많았고, 복잡한 조인에서 이런 작업이 번거로워졌습니다. 특히 여러 테이블에 같은 이름의 칼럼이 많을수록 모든 칼럼에 명시적인 별칭을 지정해야 하는 불편함이 있었습니다.

또한 Drizzle ORM은 결과 타입을 자동으로 정확하게 추론해주어 별도의 타입 지정 없이도 안전하게 결과를 사용할 수 있었습니다.

Kysely의 장점

물론 Kysely도 여러 강점이 있습니다:

  1. 더 가벼운 구조: 필요한 기능만 포함할 수 있는 모듈화된 구조
  2. SQL에 더 가까운 접근: SQL 구문에 매우 충실한 API 설계
  3. 유연성: 복잡한 쿼리에서 때로 더 유연한 작성이 가능

또한 앞서 언급했듯이, Kysely의 TypeScript 기반 마이그레이션과 양방향(up/down) 마이그레이션 지원은 특정 상황에서 Drizzle ORM보다 우위에 있는 기능입니다.

SQLAlchemy와의 비교 및 앞으로의 기대

JavaScript/TypeScript 생태계의 ORM을 이야기하기 전에, 여러 언어 중에서도 Python의 SQLAlchemy는 특별한 위치를 차지합니다. 개인적으로 여태 사용해본 다양한 언어의 ORM 중에서 SQLAlchemy가 가장 기능이 풍부하고 강력하다고 느꼈습니다. 복잡한 쿼리 구성, 고급 관계 매핑, 트랜잭션 관리, 이벤트 시스템 등 SQLAlchemy의 기능은 정말 방대합니다.

Drizzle ORM은 JavaScript 생태계에서 매우 인상적인 발전을 이루었지만, 아직 SQLAlchemy의 경지에는 이르지 못했다고 생각합니다. 특히 다음과 같은 부분에서 SQLAlchemy의 성숙도와 기능 풍부함이 돋보입니다:

  • 복잡한 서브쿼리와 윈도우 함수 지원
  • 다양한 이벤트 리스너와 훅
  • 다양한 상속 전략
  • 복잡한 트랜잭션 관리와 세션 관리
  • 대규모 프로젝트에서 검증된 안정성
  • Alembic을 통한 비선형적 마이그레이션 지원
  • 놀라울 정도로 방대하고 상세한 문서화

결론

두 ORM 모두 훌륭한 도구이지만, 제 개발 스타일과 프로젝트 요구사항에는 Drizzle ORM이 더 잘 맞았습니다. 특히 스키마 정의의 직관성, 강력한 마이그레이션 도구, 그리고 전반적인 개발자 경험 측면에서 Drizzle ORM이 더 생산적인 개발을 가능하게 해주었습니다.

동일 이름 칼럼 처리와 같은 실질적인 문제에서 Drizzle ORM의 객체 기반 접근 방식이 가져다주는 편리함은 실제 프로젝트에서 큰 차이를 만들었습니다.

ORM 선택은 결국 프로젝트 특성과 개인 선호도에 크게 좌우됩니다. 새로운 프로젝트를 시작한다면 두 도구 모두 간단히 테스트해보고 자신의 워크플로우에 더 적합한 것을 선택하는 것이 좋겠지만, 제 경우에는 Drizzle ORM이 명확한 승자였습니다.

앞으로 Drizzle ORM이 더욱 발전하여 SQLAlchemy 수준의 풍부한 기능과 유연성을 제공하게 되길 바랍니다. JavaScript/TypeScript 생태계에도 그런 수준의 강력한 ORM이 있으면 좋겠습니다. 다행히도 Drizzle ORM은 계속해서 발전하고 있으며, 그 발전 속도를 보면 기대가 큽니다.

여러분의 경험은 어떤가요? 다른 ORM 도구나 언어를 사용해보셨다면 의견을 공유해주세요!

Read more →
0

딱 ORM은 아니지만, 목적은 같은 하스켈의 opaleye 가 있습니다. 쿼리에 타입을 도입한 모양이라, 쿼리 검사에 타입 체커의 도움을 받을 수 있습니다. 처음 봤을 때, 함수형 방식으로 ORM 같은 걸 만든다면, 이렇게 되는 구나 감탄했는데, 익히는 비용이 만만치 않은 것 같습니다. @hongminhee洪 民憙 (Hong Minhee)

0
0

@lionhairdino 사실 전 어떤 좋은 설명을 제공해야한다는 생각 자체에 좀 회의적입니다. 그냥 하다보면 알게되도록 보조해주는게 최선이라고 생각합니다. 약간 별개의 얘긴데, 옛날에 파인만 빨간책 읽다가 참 좋은 책이란 생각이 들었지만 설명이 너무 똑똑해서 덮었습니다.

0

@lionhairdino 사실 전 어떤 좋은 설명을 제공해야한다는 생각 자체에 좀 회의적입니다. 그냥 하다보면 알게되도록 보조해주는게 최선이라고 생각합니다. 약간 별개의 얘긴데, 옛날에 파인만 빨간책 읽다가 참 좋은 책이란 생각이 들었지만 설명이 너무 똑똑해서 덮었습니다.

큰 틀에서는 동의합니다. 파인만 아저씨 책을 보셨다니..며칠전 전공자들의 고집을 짚었던 걸로 보아, 전공은 아니신가 했는데, 셀프 디스를 하셨던 건가!) (다른 비함수형 언어와 달리) 워낙 IO란 걸, 잘 구분해야 하는 게, 쉽지 않은 미션인데, 시작을 너무 전통 hello world 에 얽매이는 건 아닐까 싶어서요. 굳이 쉽지 않은 걸 보여주고, 모르고 넘어가자라고 하느니, 차라리 더하기 하며, 로그 남기는 걸, 직접 순수 함수로 만들어 보는 게, 낫지 않을까 혼자 상상해 봤습니다. @bglbgl gwyng

1
main = do
  n <- getLine
  putStrLn $ "hello " <> n

설명해야 될 게 한가득인데, 나중에, 나중에 하며 넘어가야 한다. 꼭 Lazy 평가처럼 말이다. 전통적인 "hello world"에서 출발하지 않아도 되는 것 아닐까? 첫 언어가 아닌 분들한테는, Writer 혹은 State 만들기부터 시작하면 어떨까? 단, "모나드"라고 말하지 않고.

2
0
1

익숙한 정main, 부sub를 써서 정작용(주작용), 부작용을 같이 보여주면 "부"의 뜻을 인지하는데 도움을 줄 것 같긴 한데, side effect 얘기를 할 때 primary effect를 거론하는 자료도 드물고, 뭔지 궁금해하는 분들도 못봤습니다.(왜 안 궁금해할까요? ㅎㅎ)

어떤 논문은 Side-effect를 Computational Effect 전반을 가리키는 용어로 쓰고, 어떤 논문들은 Effect 중 mutation을 가리키는 용어로만 씁니다. 오래된 논문일수록 전자처럼 쓰고, 요즘은 후자로 자리잡아 가고 있다고 합니다.

그동안 본 번역은 부작용, 부수 효과 정도고, 그 외 생각해 본 번역은 "부차 효과"정도가 있습니다. 맥락에서 특별히 튀지 않으면, 저는 문장에서, 원어에 바로 연결되지 않는 단점이 있긴 하지만, 의미 전달에는 유리하다 생각하는 "비순수 효과"를 쓰기도 합니다. @hongminhee洪 民憙 (Hong Minhee)

2

익숙한 정main, 부sub를 써서 정작용(주작용), 부작용을 같이 보여주면 "부"의 뜻을 인지하는데 도움을 줄 것 같긴 한데, side effect 얘기를 할 때 primary effect를 거론하는 자료도 드물고, 뭔지 궁금해하는 분들도 못봤습니다.(왜 안 궁금해할까요? ㅎㅎ)

어떤 논문은 Side-effect를 Computational Effect 전반을 가리키는 용어로 쓰고, 어떤 논문들은 Effect 중 mutation을 가리키는 용어로만 씁니다. 오래된 논문일수록 전자처럼 쓰고, 요즘은 후자로 자리잡아 가고 있다고 합니다.

그동안 본 번역은 부작용, 부수 효과 정도고, 그 외 생각해 본 번역은 "부차 효과"정도가 있습니다. 맥락에서 특별히 튀지 않으면, 저는 문장에서, 원어에 바로 연결되지 않는 단점이 있긴 하지만, 의미 전달에는 유리하다 생각하는 "비순수 효과"를 쓰기도 합니다. @hongminhee洪 民憙 (Hong Minhee)

1

개인적으로 영단어 “side effect”의 가장 적절한 번역은 “부작용”이라고 생각하고, 실제로 프로그래밍 이외의 분야에서는 여전히 이 번역어를 가장 많이 쓰는 것 같은데… 사람들이 “부작용”을 副作用이 아니라 否(?)作用이라고 착각하는 것을 염려해서인지 프로그래밍 분야에서는 “부수 효과” 같은 번역어를 더 많이 쓰는 듯하다. “부작용”의 “부”(副)는 “사장”–“부사장”할 때의 “부”인데 말이다.

0

부끄럽지만 typst로 깎은 이력서와 포트폴리오를 공개합니다: https://github.com/gidongkwon/resume

게임 클라이언트에서 웹 프론트엔드로 커리어 전환을 하는 단계에 있습니다.
혹 피드백주실 것이 있다면 언제든지 좋아요...!

직링크는 아래:
이력서 - https://gidongkwon.github.io/resume/resume-gidongkwon.pdf
포트폴리오 - https://gidongkwon.github.io/resume/portfolio-gidongkwon.pdf

4
1
0
0
0

많은 프로그래머가 아이디어를 시각화하기 위해 화이트보드나 종이에 손으로 필기를 한다. 기존에도 AI가 사용자의 필기를 기반으로 코드를 작성해주는 연구는 있었지만, 필기와 코드가 분리되어 있다는 한계를 벗어나지 못했다. Code Shaping은 단순히 스케치를 코드로 변환하는 툴이 아니라, 필기와 코드 편집이라는 두 워크플로우를 통합하는 툴. 사용자가 코드 위에 자유롭게 필기함으로써 코드를 편집할 수 있다. 코드를 한줄씩 작성하는 것이 아니라, 2차원 평면을 탐색하며 코드를 편집하기 때문에 피험자들이 선형적으로 인식했던 코드 작성을 공간적으로 감각하게 되었다고. programs.sigchi.org/chi/2025/p

Code Shaping: Iterative Code Editing with Free-form AI-Interpreted Sketching
0
1
1

업자를 위한 아주 인포멀한 모나드 설명

lionhairdino @lionhairdino@hackers.pub

1.

함수형에선, 스트림 [1,2,3]
(+1)map해서 [2,3,4]를 만들고,
(+2)map해서 [3,4,5]를 만드는 작업을,
(+2) ∘ (+1)[1,2,3]map하는 걸로 표현할 수 있어야 한다.

(+1), (+2), ((+2) ∘ (+1)) 함수들은 모두 Int -> Int 함수를 원하는 곳에 넣어 줄 수 있는 함수들이다.

위와 같이, 완벽하게 정보를 유지하진 않지만, 같은 "류"의 작업을 두 번 하는 것을, 한 번 작업하는 것으로 표현할 수 있는 경우도 있다. 예를 들어, 첫 번째 작업으로, "hello"를 로그로 남기고, 두 번째 작업으로, " world"를 로그로 남기는데, 이를 한 번의 작업으로, "hello world"를 로그로 남기는 작업으로 표현할 수 있다. 여기는 로그를 남기는 횟수 정보는 필요 없고, 최종 로그만 필요하다는 인위적 정보 선택이 들어가 있다. 이 인위적 선택(여기선 로그 문자열을 합치는 것)을 수긍해야만 가능하다.

로그를 남기는 작업을 m이라 부를 때, m a를 받는 곳에 m (m a)를 넘길 방법이 생긴다는 뜻이다. 달리 말하면, m (m a)로 표현되는 작업을 인위적인 절차를 거쳐 m a로 만들어도, 내가 필요한 정보는 사라지지 않는다는 뜻이다.

2.

무언가가 하나인데, 유심히 보면 하나가 아닌 경우, 이게 바로 모노이드다. mono는 하나를 뜻하고, ~oid는 "척"하는 걸 말한다. (예. 인간인 척 하는 휴머노이드) 하나인척 하는 게 모노이드다. 수학 책 앞 부분에서 이항 연산, 결합 법칙, 항등원이 있으면 모노이드라는 설명을 하는데, 그래서 모노이드가 뭐에 쓰는 물건인지는 한참 공부해야 알 게 된다.

(아래는 혼자만의 생각입니다.)
모노이드를 바라 보는 눈 중 하나로, "모든 대상을 이항 연산으로 표현"을 들 수 있다.

0을 포함한 자연수들 0,1,2,3,... 들은, + 이항 연산과, 이 연산의 항등원 0이 있으면, 모두 ○ + ○ 한 가지 모양으로 표현할 수 있게 된다.
0 -> 0+0
1 -> 0+1
2 -> 0+(1+1) = 1+1
...
모노이드 구조이기에, 어딘가에서 ○ + ○ 모양을 원한다면, 0,1,2,3,...을 모두 넣어 줄 수 있다.

3.

"어딘가에서 m a를 원한다면, m a, m (m a), m (m (m a)), ...를 모두 넣어 줄 수 있다."를 위와 비교하며 보자.

위에서 얘기한 인위적 선택 작업join으로 표현하면,
m (m a) --join--> m a
m (m (m a)) --join--> m (m a) --join--> m a
...
m 반복 작업을 모두 ○ --join--> ○ 모양으로 표현할 수 있을 것만 같다. 그런데, 딱 하나는 표현하지 못한다. joinm이 두 개 있는 걸, 하나로 만드는 작업이라, m하나를 ○ --join--> ○로 표현하지 못한다. mjoin이 들어간 모양으로 표현하려면, 자연수, + 에서 처럼 0에 대응하는 것이 필요하다. m하나를, m 두 개로 만들되, 최종 결과에 영향을 미치지 않는 pure라는 작업을 만든다. 위 로그 작업을 예로 들면, 로그로 빈문자 ""을 추가하는 작업을 pure로 만든다. 그러면 이제야 비로소, 모든 반복된 m 을 join으로 표현할 수 있게 된다

m a --pure--> m (m a) --join--> m a
m (m a) --join--> m a
m (m (m a)) --join--> m (m a) --join--> m a
...

이제, join절차가 항상 있는 m a를 원하는 곳에 m am (m (m a))도 넣어 줄 수 있게 되었다. "hello"와 " world"를 남기던 두 개의 작업 합쳐, "hello world"를 남기는 하나의 작업으로 표현할 수 있게 되었다.

※ 지금 눈에 명확히 보이진 않지만, m 둘을 합성하는 연산을 .이라 하면, .만으론 모노이드 이항 연산 역할을 못하지만, join의 도움을 받고, id 만으론 항등원 역할을 못하지만, pure의 도움을 받아 모노이드 구조를 이룬다.

결론.

당연히 모든 내용이 담겨 있진 않고, 모나드를 무엇의 모노이드로 보는 내용을 비수학적으로 풀어 봤다. 모노이드는 모두를 하나의 모양으로 표현 할 수 있다는 걸, 보증해주는 거대한 개념이지만, 업자인 나에겐 "그렇게 해도 된다"는 정도의 느낌만 있다. (결합 법칙이 빠졌는데, 나중에 코드를 모듈화 하는 것과 연관지어 보면, 명확한 대응을 알 수 있다.)

모나드는, 조금 다르게 생긴 것을, 당장 필요한 요소만 잘 관리한다면 "같은 걸로 치자"를 멋지게(,어렵게) 형식화한 이론이다.

사족.
저와 대화를 나눠본 분들은 아시겠지만, 제가 비전공자라 용어 선택이나 개념 정의가 매우 인포멀해서 인상을 찌푸리는 경우도 자주 만듭니다. PL 전공자분들처럼 깊숙히 이론을 파고 싶은 게 아니라, 현실에 적용할 수 있을 만큼의 눈만 가지고 싶습니다. 현실을 모델링할 때, "인위적 정보 선택"을 해서 필요한 정보를 남길 수 있는 경우를 알아채는 눈을 길러야 되는데, bind 또는 flatmap, return 또는 pure가 있는 구조가 모나드라고만 배우면, 이런 눈을 가지는데 매우 오래 걸리는 것 같습니다.

비전공 업자분이 보셨다면, 얻어 가시는 아이디어가 있었으면 좋겠고, 전공자분이 보셨다면, 인포멀한 부분에 너무 인상 찌푸리지 마시고, 틀린 개념이 있다면, 부드럽게 조언을 해주시면 좋겠습니다.

※ 모나드 용어는 monotriad에 온 게 아닐까 의심한다는 설이 있습니다.(검색해 보면 근거는 미약해 보입니다.) 모나드는 join, return 그리고 위에서 명시적 언급은 안했지만, 펑터의 fmap, 이렇게 세 개 triad의 도움을 받아 모노이드로 만들 수 있는 구조입니다.

※ "정교한" 내용이 아님을 강조하고 선입견이 생기지 않기 위해, 일부러 제목을 달지 않고, 반말(혼잣말)투로 썼습니다.

제목은

  1. 함수형
  2. 모노이드
  3. 모나드

순서 입니다.

Read more →
6
2
1

배포distribute 配布 (유사어 배치排置: 일정한 간격으로 벌여 놓다)
신문이나 책자 따위를 널리 나누어 주다

배치deploy 配置
군대를 전장에 배치하듯, 비즈니스 서비스에서 서버를 현장에 배치한다. 실전을 뛰게 배치한다.

"새로 만든 앱을 배치해서 사용자에게 배포했어"

1
3
1

'모나드는 모노이드 엔도펑터다'가 이제 무슨 뜻인지는 안다. '모노이드'라는게 >>= 보다는 join을 쓸때 더 와닿는데, >>=join보다 한 30배는 더 자주 쓴다. 그래서 저 사실을 평소에 잘 느끼고 살진 못하는거 같다. 하지만 가끔 join으로 타입을 눌러서 맞출때 개꿀따리란 생각이 들긴하다.

1
0
0
0

생각보다 훨씬 자세하게 명문화된 규칙이 있군요.! 공부하면서 이 예시 저 예시 보다 보면, 버전이 널뛰고, 그러다 보면 HLS 지원이 오락 가락하게 되어, 사실 각 잡고 프로젝트에 쓰는 것 아니면, 의존도가 높지 않게 되어버리더라고요. 그 이유가 버전 지원 때문이란 생각에, 미리 HLS 친화적인 버전을 골라낼 수 있나 했는데, 그러긴 어려울 것 같네요.

0
0
1
0
0
0
0

@lionhairdino 들여쓰기를 제외한 토큰을 구분하는 용도로 쓰이는 공백을 그냥 공백이라고 했네요.

들여쓰기가 물론 가독성은 좋지요. 근데 편집할때 불편을 주는 문제가 있고, 에디터가 좀 힘을써주면 양쪽의 장점을 다 취할수있다는 얘기였습니다.

1
1
0

@hongminhee洪 民憙 (Hong Minhee) 약간 딴 얘긴데, 저는 들여쓰기가 그냥 안좋은 문법요소 같습니다. 코드의 복붙을 unreliable하게 만들어버려서요. 반대로 space sensitive한 문법은 괜찮다고 생각합니다. 복붙시 문제가 생겨도 스페이스 한번 치면 해결되니까요. 들여쓰기 대신에 {} 쌍을 쓰게 만들되, 에디터에서 보여줄때 어떻게 알아서 예쁘게 보여주는게 낫다고 생각해요.

0
1
1
0

나의 퀀트 투자 3개월 수익률... 첫 1개월은 10~15% 정도의 양호한 수익률을 유지하다가 트럼프가 무역전쟁을 시작하면서 나락에 빠졌다. 이런 상황에도 용기를 갖고 다음 3개월을 준비해야 한다...

종목별 수익률 목록. 전체 수익률 -12.45%, 최고 43.07%, 최저 -51.14%.
0

Mastodon 호환 API를 구현할 계획에 대해 문의 주시는 분들이 종종 계십니다만, 아마도 Hackers' Pub은 앞으로도 Mastodon 호환 API를 구현하지는 않을 것 같습니다. 개인적으로 Mastodon 호환 API가 사용성이 많이 떨어진다고도 생각하고, 이미 Hackers' Pub 고유의 기능들 가운데 Mastodon 호환 API로 표현 불가능한 것들이 좀 있기 때문입니다.

장기적으로는 GraphQL을 이용해 웹 프런트엔드도 크게 개선하고, 모바일 앱까지 만드는 걸 염두에 두고 있습니다.

1

@lionhairdino 예를 들면 "다양한 시선에서 코드를 이해한다"가 지금 공개한 연작의 2 편에서 논건 대수를 통한 계산의 이해와도 밀접한 연관이 있다고 읽혔습니다. 원래 두번째 주제에 대해서 쓰다가 방향성을 틀었네요.

"여론에 따라" 함수형 추상 기계 관련 글을 쓰고 있었는데, 쓰다 보니 논리와 low-level data representation 이 보였다는 핑계 말씀이지요? 생각할 엄두조차 내지 못했던 주제들, 다 이해는 못하지만 감사히 보고 있습니다. SPJ, 와들러 교수님 등의 교양 수준 강의 활동들을 보다 보면, 왜 국내 교수님(고인물-댓가없이 입문자들에게 도움을 준다는 의미)들은 없나 아쉬운데, 엘룬님 글로 조금 달래지네요. @ailrunAilrun (UTC-5/-4)

1
1

말씀하신 것들을 보아 몇몇 분들은 실제 내용 측면에서는 논리와 저수준 자료표현에 더 관심을 가질 분들이 있는 것 같아 전자를 (먼저?) 다뤄보도록 하겠습니다. 2 편으로 나눠져 올라갈 예정입니다.

1