Hi, I'm who's behind Fedify, Hollo, BotKit, and this website, Hackers' Pub!

Fedify, Hollo, BotKit, 그리고 보고 계신 이 사이트 Hackers' Pub을 만들고 있습니다.

FedifyHolloBotKit、そしてこのサイト、Hackers' Pubを作っています。

嗨,我是 FedifyHolloBotKit 以及這個網站 Hackers' Pub 的開發者!

Website
hongminhee.org
GitHub
@dahlia
Hollo
@hongminhee@hollo.social
DEV
@hongminhee
velog
@hongminhee
Qiita
@hongminhee
Zenn
@hongminhee
Matrix
@hongminhee:matrix.org
X
@hongminhee

이 글에선 없는, bash보다 Ruby가 좋은 이유가 하니 더 떠오른다.

셸 스크립트를 작성하다보면 필연적으로 awk나 sed 같은 걸 쓰게 되는데, 이게 macOS/BSD와 Linux에서 서로 다른 버전(BSD awk / GNU awk)이 들어있고 지원하는 기능도 미묘하게 다르다보니 작성한 스크립트가 다른 OS에서 작동하지 않을 수 있는데, Ruby나 Perl로 짜면 이런 걱정을 하지 않아도 된다.
hackers.pub/@kodingwarrior/202

CLI 도구를 조합하여 나만의 요술봉 만들기 (feat. Ruby)

<본론으로 들어가기에 앞서, 이 글에서는 Bash 스크립트에다가 Ruby를 섞어서 사용하는 트릭을 서술할 예정인데, 다른 스크립팅 언어로도 해낼 수 있음을 강조해둔다.쉘스크립트로 어떻게 워크플로우를 개선할 수 있을까?어떻게 하면 CLI 도구를 잘 사용할 수 있을까?<이런 고민들, 누군가는 했을 것이다. 이 글을 읽는 여러분은 한번씩은 거치고도 남았을 것이다. 이 글에서는 간단한 커맨드의 조합만으로도 여러분의 삶을 바꿀지도 모르는 비법을 소개하고자 한다. Bash 스크립트를 잘 짜는 방법을 안다면 분명 도움이 되는 구석이 많다. OpenBSD, 리눅스 등을 기반한 어지간한 OS에서는 Bash 스크립트를 지원하기도 하니까 말이다. 하지만, Bash 스크립트 단독으로는 가독성이 떨어지기도 하고, 일회성으로 짠다면 더더욱 직관적으로 와닿는 코드를 짜기도 어렵다. 하지만, Ruby나 Perl 등의 스크립트와 함께라면 그나마 좀 더 가독성이 있는 스크립트를 짤 수 있게 된다.그렇다면 왜 Bash 대신 Ruby인가? Bash를 사용해서 스크립트 짜는 것이 원론적인 접근이고, 많은 곳에서 스크립트를 짤 때 권장하고 있다. 가능하면 외부 소프트웨어와의 의존성을 줄여야 하고, 어디서든 돌아가는 스크립트를 짜야하기 때문이다. 하지만, 내 개발환경에서만 돌리는 일회성의 스크립트라면? Ruby 정도는 섞어서 써도 괜찮다. 사실상 답정너이긴 하지만, 왜 Ruby로 스크립트를 짜는 것이 도움이 되는가? 왜, 꼭 Ruby를 써야하는가? 이유를 나열하자면 아래와 같다.자료형을 다루는 데 있어서 타입 구분이 확실하다내가 다루는 데이터가 어떤 자료형인지 긴가민가한 Bash 스크립트에 비해, Integer/Float/String/Hash/Array 등 명시적으로 구분되는 자료형으로 확실하게 구분되는 점에 감사할 수 있다.여러분이 macOS를 사용하고 있다면, homebrew가 깔려있다면, 사실상 Ruby는 기본으로 딸려오는 옵션이라고 보면 된다.(macOS 유저 한정으로) 빌드 스크립트를 짜는데 요긴하게 도움이 될 수 있다.XCode에서 빌드할때 CocoaPod를 사용하는데, 내부적으로 Ruby 스크립트로 구성이 되어 있다. 또한 Fastlane에서 빌드 스크립트를 작성할때 Ruby를 사용한다. 유사한 작업을 할 때 지식이 전이될 수 있다.JSON/CSV/YAML을 다루는 라이브러리가 표준라이브러리로서 내장이 되어 있다. 이를 어떻게 다룰 수 있는지는 후술하겠다.<Ruby로 One-liner 스크립트 작성하기 보통은 Ruby 코드를 작성할때 irb 같은 대화형 인터페이스를 사용하는 것이 일반적이지만, Bash 스크립트와 섞어서 사용할때는 one-liner 스크립트를 작성하는 것으로 시작한다. 여기서 one-liner 스크립트란 한줄짜리로 실행하는 스크립트라고 이해하면 된다. ruby one-liner 스크립트로 작성할때는 다음과 같이 시작한다.$ ruby -e "<expression>"<여기서 -e 옵션은 one-liner 스크립트의 필수요소인데, 파라미터로 넘겨준 한줄짜리 Ruby 코드를 evaluation해주는 역할을 한다. 여러분이 파이프 혹은 리다이렉션에 대한 개념을 이해하고 있다면, 이런 트릭도 사용할 수 있다.$ echo "5" | ruby -e "gets.to_i.times |t| \{ puts 'hello world' \}"# =># hello world# hello world# hello world# hello world# hello world<여러분이 표준라이브러리를 사용하고 싶을때는 -r 옵션을 사용할 수도 있다. 이 옵션은 ruby에서 require를 의미하는데, 식을 평가하기전에 require문을 미리 선언하고 들어가는 것이라 이해하면 된다. 예를 들면, 이런 것도 가능하다.$ echo "9" | ruby -rmath -e "puts Math.sqrt(gets.to_i)"# => 3.0<위의 스크립트는 아래와 동일하다.$ echo "9" | ruby -e "require 'math'; puts Math.sqrt(gets.to_i)"# => 3.0<이런 원리를 이용하면, JSON/XML/CSV/YAML 등의 포맷으로 출력되는 데이터를 어렵지 않게 처리할 수 있다.다른 CLI 도구와 조합해서 사용해보기 <이 글에서는 여러분이 표준 입출력, 리다이렉션, 그리고 유닉스 기본 명령어(e.g. echo/tail/tead/more/grep 등)는 이미 숙지를 하고 있으리라 생각한다. 이에 대해서 다루자면, 전하고자 하는 의도에 비해 글이 엄청 길어질 수 있어서 의도적으로 생략했다. 혹시나 당장은 모르더라도 상관없다. 그렇게 어렵지 않으니 실습을 한번쯤은 해보는 것을 권장한다.<위에서 예시를 든 것 가지고는 어떻게 하면 나한테 유용한 도구를 만들 수 있는지 파악하기 어려울 수 있다. 그렇다면, 실제로 우리가 사용하고 있는 CLI 도구를 같이 결합해보는건 어떨까? 친숙한 사례를 예시로 들자면 aws-cli, git, gh, jq, curl 등의 커맨드라인 도구가 있을 수 있겠다. 각각은 단일 작업에 특화되어 있어 그 자체로도 훌륭하지만, Ruby 스크립트와 결합했을 때 더욱 강력한 도구로 탈바꿈할 수 있다. 아래에서는 몇 가지 활용 사례와 그로 인해서 어떻게 시너지 효과를 일으킬 수 있는지 살펴보자. 먼저, 간단한 예시를 살펴보자.JSON 데이터 처리하기 JSON 포맷은 어떻게 보면 굉장히 범용적으로 사용되는 포맷이다. API 요청 날릴 때 쓰이는 것은 물론이고, 설정 파일에 쓰이기도 하고, 다른 인터페이스 간 데이터를 교환할 때도 많이 쓰이기도 한다. Ruby에서는 JSON 라이브러리를 표준 라이브러리로 포함하고 있기 때문에, 이것을 굉장히 유용하게 활용할 수 있다.$ curl -s https://jsonplaceholder.typicode.com/posts/1 | ruby -rjson -e 'data = JSON.parse(STDIN.read); puts "Title: #{data["title"]}"'<동작하는 방식은 간단하다.curl로 요청을 날려서 JSON 응답을 반환받는다.JSON 데이터를 파싱하고, 그 중에서 title 필드를 추출한다출력한다.<외부 API에 요청을 날리고 거기서 받은 JSON 응답을 처리하고자 할 때 굉장히 편리하게 처리할 수 있다. 단순히 뽑아내기만 할 때는 jq를 사용하는 것도 방법이긴 하지만, Ruby 스크립트 안에서는 더욱 다양하게 활용할 수 있다. 또한, GitHub CLI/Flutter/AWS CLI 등등이 --format json 같은 옵션을 지원하는데, 한번 섞어서 사용해보는 것을 권장한다.YAML 데이터 처리하기 YAML 포맷은 일반적으로는 설정 파일에 널리 사용된다. Ruby는 기본적으로 yaml 라이브러리를 포함하고 있으므로 YAML 파일을 읽고, 필요한 정보만 출력하는 작업을 쉽게 수행할 수 있다. 예를 들어, config.yaml 파일에서 특정 설정 값을 추출하는 스크립트는 다음과 같다.$ cat config.yaml | ruby -ryaml -e 'config = YAML.load(STDIN.read); puts "Server port: #{config["server"]["port"]}"'<이것도 역시 동작방식은 간단하다.cat 명령어로 config.yaml 파일의 내용을 읽어오고,Ruby의 YAML.load를 사용해 파싱한 후,서버 설정에서 포트 번호를 출력한다.<이와 같이 YAML 파일을 손쉽게 읽어서 원하는 부분만 추출하거나, 구조화된 데이터를 다른 CLI 도구와 연계하여 활용할 수 있다.이도 역시 --format yaml 같은 옵션을 지원하는 kubectl 같은 CLI 도구와 함께 유용하게 사용될 수 있다.정형화되어 있지 않은 복잡한 텍스트 데이터를 처리하기 모든 데이터가 JSON/CSV/YAML 포맷처럼 정형화되어 있으리라는 보장이 없다. 많은 경우 로그 파일, 시스템 메시지, 사용자 입력 등은 형식이 일정하지 않은 경우가 많다. 이런 경우에도 Ruby의 강력한 정규표현식 기능이나 텍스트 처리 능력을 활용하면 데이터를 원하는 형태로 추출하거나 가공할 수 있다. 대부분의 경우에는 높은 확률로 한줄한줄 읽어서 처리하면 되는 경우가 많다. 이번엔, 간단하면서 친숙한 git log를 예시로 살펴보자. 이번에는 글의 주제(one-liner)에서 다소 벗어났지만, 이런 식의 활용도 가능하다는걸 밝히고 싶다. 다음에서 설명하는 스크립트는 내가 굉장히 애용하는 스크립트 중 하나이다. Git 로그 중에서 원하는 커밋을 선택하고, 해당 커밋의 변경사항을 보여준 후, 조회한 내역을 체크리스트 형태로 출력한다.git_logs = `git log --oneline #{file} | gum choose --limit 100`git_logs.each_line do |line| commit_hash, *_ = line.split system("git show #{commit_hash}") puts("=====") puts("Press ENTER key to CONTINUE") puts("=====") getsendchecklist = []git_logs.each_line do |line| checklist << "- [ ] #{line}"endputs checklist.join<이번엔 조금 복잡할 수 있다. 그래도 인내심을 가지고 보면 그렇게 어렵진 않다.<Git 로그 추출:git log --oneline #{file} 명령을 실행하여 한 줄에 하나의 커밋 정보를 출력한다.gum choose --limit 100을 사용해, 출력된 로그 중 조회하고 싶은 라인을 인터랙티브하게 선택할 수 있다.선택된 결과는 git_logs 변수에 저장된다.<각 커밋별 상세 조회:git_logs.each_line을 통해 선택된 로그를 한 줄씩 순회한다.각 줄은 <commit hash> <commit message> 형식을 갖고 있으므로, split 메서드를 사용해 첫 번째 토큰(커밋 해시)만 추출한다.추출한 커밋 해시를 이용해 git show #{commit_hash} 명령을 실행, 해당 커밋의 변경 내용을 출력한다.각 커밋 조회 후, 사용자에게 "계속 진행하려면 ENTER 키를 누르라"는 메시지를 띄워 한 단계씩 진행할 수 있도록 한다.<체크리스트 생성:다시 한 번 git_logs의 각 라인을 순회하며, 각 커밋 로그 앞에 체크리스트 형식(- [ ])을 붙여 리스트 항목을 만든다.모든 항목을 조합해 최종 체크리스트를 출력한다.<마치며 우리는 CLI 도구들과 Ruby 스크립트를 비롯한 다양한 스크립팅 언어를 활용해, 간단한 커맨드 조합만으로도 나만의 비밀무기를 만들 수 있는 방법들을 살펴보았다. 이러한 접근법을 통해 각 도구가 가진 단일 기능의 강점을 그대로 유지하면서, 이를 결합해 더욱 강력하고 유연한 자동화 워크플로우를 구성할 수 있음을 확인했다. 작은 한 줄의 스크립트가 복잡한 데이터 처리, 로그 분석, 버전 관리 작업을 손쉽게 해결해줄 뿐만 아니라, 실제 업무 현장에서 생산성을 극대화할 수 있는 발판이 된다. 여러분도 이번 기회를 계기로 다양한 CLI 도구와 스크립트를 조합하여, 나만의 맞춤형 자동화 도구를 만들어 보는 것은 어떨까? 이 글을 작성하기까지 적지 않은 영향을 주셨던 @ssiumha님께 감사를 표한다.<그 외에도, Perl도 익혀두면 도움이 될 수 있다. Perl은 Git(libgit)이 설치되어 있다면 원플러스원으로 같이 설치되기 때문이다. 요즘은 Perl One-Liners Guide 같은 훌륭한 교재도 있고, LLM도 perl로 one liner 스크립트를 짜달라고 물어보면 뚝딱뚝딱하고 잘 짜주는 편이다.

hackers.pub · Hackers' Pub

Link author: Jaeyeol Lee@kodingwarrior@hackers.pub

0

드디어 해커스펍에서 스팸을 받았습니다. 자리를 잡아가는 마일 스톤에 있는 이벤트 아닌가 싶습니다. ㅎ (얼마전 올라온 외래어 규칙을 보니, 한글 이름이 해커스펍이 아닌 해커즈 퍼브가 규칙에 맞을텐데, 과연 해커즈 퍼브가 사람들 입에 붙을 수 있을까 싶은데요.)

0

일전에 Hackers' Pub 에서 일본에서는 개발자를 어떻게 부르는가에 대한 이야기가 오간 적이 있는데, 이런 의견의 글도 있어서 공유합니다.

PG(프로그래머)와 SE(시스템 엔지니어)의 차이?
PG(プログラマー)とSE(システムエンジニア)の違いって?

PG(プログラマー) → 設計書をもとにコードを書く人
SE(システムエンジニア) → 要件定義・設計・プログラミング・テストまで全部できる人
「エンジニア=プログラミングする人」ってイメージがあるかもしれませんが、実際には 開発ってプログラミングだけじゃない んです。

PG: 설계서 보고 코딩하는 사람
SE: 요구사항 정의, 설계, 프로그래밍, 테스트까지 전부할 수 있는 사람

(원문: 일본어) https://qiita.com/ryoheiiwamoto/items/73f74b76a23236ff9d5e

0
0

洪 民憙 (Hong Minhee) shared the below article:

CLI 도구를 조합하여 나만의 요술봉 만들기 (feat. Ruby)

Jaeyeol Lee @kodingwarrior@hackers.pub

본론으로 들어가기에 앞서, 이 글에서는 Bash 스크립트에다가 Ruby를 섞어서 사용하는 트릭을 서술할 예정인데, 다른 스크립팅 언어로도 해낼 수 있음을 강조해둔다.

  • 쉘스크립트로 어떻게 워크플로우를 개선할 수 있을까?
  • 어떻게 하면 CLI 도구를 잘 사용할 수 있을까?

이런 고민들, 누군가는 했을 것이다. 이 글을 읽는 여러분은 한번씩은 거치고도 남았을 것이다. 이 글에서는 간단한 커맨드의 조합만으로도 여러분의 삶을 바꿀지도 모르는 비법을 소개하고자 한다.

Bash 스크립트를 잘 짜는 방법을 안다면 분명 도움이 되는 구석이 많다. OpenBSD, 리눅스 등을 기반한 어지간한 OS에서는 Bash 스크립트를 지원하기도 하니까 말이다. 하지만, Bash 스크립트 단독으로는 가독성이 떨어지기도 하고, 일회성으로 짠다면 더더욱 직관적으로 와닿는 코드를 짜기도 어렵다.

하지만, Ruby나 Perl 등의 스크립트와 함께라면 그나마 좀 더 가독성이 있는 스크립트를 짤 수 있게 된다.

그렇다면 왜 Bash 대신 Ruby인가?

Bash를 사용해서 스크립트 짜는 것이 원론적인 접근이고, 많은 곳에서 스크립트를 짤 때 권장하고 있다. 가능하면 외부 소프트웨어와의 의존성을 줄여야 하고, 어디서든 돌아가는 스크립트를 짜야하기 때문이다.

하지만, 내 개발환경에서만 돌리는 일회성의 스크립트라면? Ruby 정도는 섞어서 써도 괜찮다. 사실상 답정너이긴 하지만, 왜 Ruby로 스크립트를 짜는 것이 도움이 되는가? 왜, 꼭 Ruby를 써야하는가?

이유를 나열하자면 아래와 같다.

  • 자료형을 다루는 데 있어서 타입 구분이 확실하다
    • 내가 다루는 데이터가 어떤 자료형인지 긴가민가한 Bash 스크립트에 비해, Integer/Float/String/Hash/Array 등 명시적으로 구분되는 자료형으로 확실하게 구분되는 점에 감사할 수 있다.
  • 여러분이 macOS를 사용하고 있다면, homebrew가 깔려있다면, 사실상 Ruby는 기본으로 딸려오는 옵션이라고 보면 된다.
  • (macOS 유저 한정으로) 빌드 스크립트를 짜는데 요긴하게 도움이 될 수 있다.
    • XCode에서 빌드할때 CocoaPod를 사용하는데, 내부적으로 Ruby 스크립트로 구성이 되어 있다. 또한 Fastlane에서 빌드 스크립트를 작성할때 Ruby를 사용한다. 유사한 작업을 할 때 지식이 전이될 수 있다.
  • JSON/CSV/YAML을 다루는 라이브러리가 표준라이브러리로서 내장이 되어 있다. 이를 어떻게 다룰 수 있는지는 후술하겠다.

Ruby로 One-liner 스크립트 작성하기

보통은 Ruby 코드를 작성할때 irb 같은 대화형 인터페이스를 사용하는 것이 일반적이지만, Bash 스크립트와 섞어서 사용할때는 one-liner 스크립트를 작성하는 것으로 시작한다. 여기서 one-liner 스크립트란 한줄짜리로 실행하는 스크립트라고 이해하면 된다. ruby one-liner 스크립트로 작성할때는 다음과 같이 시작한다.

$ ruby -e "<expression>"

여기서 -e 옵션은 one-liner 스크립트의 필수요소인데, 파라미터로 넘겨준 한줄짜리 Ruby 코드를 evaluation해주는 역할을 한다. 여러분이 파이프 혹은 리다이렉션에 대한 개념을 이해하고 있다면, 이런 트릭도 사용할 수 있다.

$ echo "5" | ruby -e "gets.to_i.times |t| \{ puts 'hello world' \}"
# =>
# hello world
# hello world
# hello world
# hello world
# hello world

여러분이 표준라이브러리를 사용하고 싶을때는 -r 옵션을 사용할 수도 있다. 이 옵션은 ruby에서 require를 의미하는데, 식을 평가하기전에 require문을 미리 선언하고 들어가는 것이라 이해하면 된다.

예를 들면, 이런 것도 가능하다.

$ echo "9" | ruby -rmath -e "puts Math.sqrt(gets.to_i)"
# => 3.0

위의 스크립트는 아래와 동일하다.

$ echo "9" | ruby -e "require 'math'; puts Math.sqrt(gets.to_i)"
# => 3.0

이런 원리를 이용하면, JSON/XML/CSV/YAML 등의 포맷으로 출력되는 데이터를 어렵지 않게 처리할 수 있다.

다른 CLI 도구와 조합해서 사용해보기

이 글에서는 여러분이 표준 입출력, 리다이렉션, 그리고 유닉스 기본 명령어(e.g. echo/tail/tead/more/grep 등)는 이미 숙지를 하고 있으리라 생각한다. 이에 대해서 다루자면, 전하고자 하는 의도에 비해 글이 엄청 길어질 수 있어서 의도적으로 생략했다. 혹시나 당장은 모르더라도 상관없다. 그렇게 어렵지 않으니 실습을 한번쯤은 해보는 것을 권장한다.

위에서 예시를 든 것 가지고는 어떻게 하면 나한테 유용한 도구를 만들 수 있는지 파악하기 어려울 수 있다. 그렇다면, 실제로 우리가 사용하고 있는 CLI 도구를 같이 결합해보는건 어떨까? 친숙한 사례를 예시로 들자면 aws-cli, git, gh, jq, curl 등의 커맨드라인 도구가 있을 수 있겠다. 각각은 단일 작업에 특화되어 있어 그 자체로도 훌륭하지만, Ruby 스크립트와 결합했을 때 더욱 강력한 도구로 탈바꿈할 수 있다. 아래에서는 몇 가지 활용 사례와 그로 인해서 어떻게 시너지 효과를 일으킬 수 있는지 살펴보자.

먼저, 간단한 예시를 살펴보자.

JSON 데이터 처리하기

JSON 포맷은 어떻게 보면 굉장히 범용적으로 사용되는 포맷이다. API 요청 날릴 때 쓰이는 것은 물론이고, 설정 파일에 쓰이기도 하고, 다른 인터페이스 간 데이터를 교환할 때도 많이 쓰이기도 한다. Ruby에서는 JSON 라이브러리를 표준 라이브러리로 포함하고 있기 때문에, 이것을 굉장히 유용하게 활용할 수 있다.

$ curl -s https://jsonplaceholder.typicode.com/posts/1 | ruby -rjson -e 'data = JSON.parse(STDIN.read); puts "Title: #{data["title"]}"'

동작하는 방식은 간단하다.

  1. curl로 요청을 날려서 JSON 응답을 반환받는다.
  2. JSON 데이터를 파싱하고, 그 중에서 title 필드를 추출한다
  3. 출력한다.

외부 API에 요청을 날리고 거기서 받은 JSON 응답을 처리하고자 할 때 굉장히 편리하게 처리할 수 있다. 단순히 뽑아내기만 할 때는 jq를 사용하는 것도 방법이긴 하지만, Ruby 스크립트 안에서는 더욱 다양하게 활용할 수 있다. 또한, GitHub CLI/Flutter/AWS CLI 등등이 --format json 같은 옵션을 지원하는데, 한번 섞어서 사용해보는 것을 권장한다.

YAML 데이터 처리하기

YAML 포맷은 일반적으로는 설정 파일에 널리 사용된다. Ruby는 기본적으로 yaml 라이브러리를 포함하고 있으므로 YAML 파일을 읽고, 필요한 정보만 출력하는 작업을 쉽게 수행할 수 있다.

예를 들어, config.yaml 파일에서 특정 설정 값을 추출하는 스크립트는 다음과 같다.

$ cat config.yaml | ruby -ryaml -e 'config = YAML.load(STDIN.read); puts "Server port: #{config["server"]["port"]}"'

이것도 역시 동작방식은 간단하다.

  1. cat 명령어로 config.yaml 파일의 내용을 읽어오고,
  2. Ruby의 YAML.load를 사용해 파싱한 후,
  3. 서버 설정에서 포트 번호를 출력한다.

이와 같이 YAML 파일을 손쉽게 읽어서 원하는 부분만 추출하거나, 구조화된 데이터를 다른 CLI 도구와 연계하여 활용할 수 있다. 이도 역시 --format yaml 같은 옵션을 지원하는 kubectl 같은 CLI 도구와 함께 유용하게 사용될 수 있다.

정형화되어 있지 않은 복잡한 텍스트 데이터를 처리하기

모든 데이터가 JSON/CSV/YAML 포맷처럼 정형화되어 있으리라는 보장이 없다. 많은 경우 로그 파일, 시스템 메시지, 사용자 입력 등은 형식이 일정하지 않은 경우가 많다. 이런 경우에도 Ruby의 강력한 정규표현식 기능이나 텍스트 처리 능력을 활용하면 데이터를 원하는 형태로 추출하거나 가공할 수 있다. 대부분의 경우에는 높은 확률로 한줄한줄 읽어서 처리하면 되는 경우가 많다.

이번엔, 간단하면서 친숙한 git log를 예시로 살펴보자. 이번에는 글의 주제(one-liner)에서 다소 벗어났지만, 이런 식의 활용도 가능하다는걸 밝히고 싶다. 다음에서 설명하는 스크립트는 내가 굉장히 애용하는 스크립트 중 하나이다. Git 로그 중에서 원하는 커밋을 선택하고, 해당 커밋의 변경사항을 보여준 후, 조회한 내역을 체크리스트 형태로 출력한다.

git_logs = `git log --oneline #{file} | gum choose --limit 100`

git_logs.each_line do |line|
  commit_hash, *_ = line.split
  system("git show #{commit_hash}")
  puts("=====")
  puts("Press ENTER key to CONTINUE")
  puts("=====")
  gets
end

checklist = []
git_logs.each_line do |line|
  checklist << "- [ ] #{line}"
end

puts checklist.join

이번엔 조금 복잡할 수 있다. 그래도 인내심을 가지고 보면 그렇게 어렵진 않다.

  1. Git 로그 추출:

    • git log --oneline #{file} 명령을 실행하여 한 줄에 하나의 커밋 정보를 출력한다.
    • gum choose --limit 100을 사용해, 출력된 로그 중 조회하고 싶은 라인을 인터랙티브하게 선택할 수 있다.
    • 선택된 결과는 git_logs 변수에 저장된다.
  2. 각 커밋별 상세 조회:

    • git_logs.each_line을 통해 선택된 로그를 한 줄씩 순회한다.
    • 각 줄은 <commit hash> <commit message> 형식을 갖고 있으므로, split 메서드를 사용해 첫 번째 토큰(커밋 해시)만 추출한다.
    • 추출한 커밋 해시를 이용해 git show #{commit_hash} 명령을 실행, 해당 커밋의 변경 내용을 출력한다.
    • 각 커밋 조회 후, 사용자에게 "계속 진행하려면 ENTER 키를 누르라"는 메시지를 띄워 한 단계씩 진행할 수 있도록 한다.
  3. 체크리스트 생성:

    • 다시 한 번 git_logs의 각 라인을 순회하며, 각 커밋 로그 앞에 체크리스트 형식(- [ ])을 붙여 리스트 항목을 만든다.
    • 모든 항목을 조합해 최종 체크리스트를 출력한다.

마치며

우리는 CLI 도구들과 Ruby 스크립트를 비롯한 다양한 스크립팅 언어를 활용해, 간단한 커맨드 조합만으로도 나만의 비밀무기를 만들 수 있는 방법들을 살펴보았다. 이러한 접근법을 통해 각 도구가 가진 단일 기능의 강점을 그대로 유지하면서, 이를 결합해 더욱 강력하고 유연한 자동화 워크플로우를 구성할 수 있음을 확인했다.

작은 한 줄의 스크립트가 복잡한 데이터 처리, 로그 분석, 버전 관리 작업을 손쉽게 해결해줄 뿐만 아니라, 실제 업무 현장에서 생산성을 극대화할 수 있는 발판이 된다. 여러분도 이번 기회를 계기로 다양한 CLI 도구와 스크립트를 조합하여, 나만의 맞춤형 자동화 도구를 만들어 보는 것은 어떨까?

이 글을 작성하기까지 적지 않은 영향을 주셨던 @ssiumha님께 감사를 표한다.


그 외에도, Perl도 익혀두면 도움이 될 수 있다. Perl은 Git(libgit)이 설치되어 있다면 원플러스원으로 같이 설치되기 때문이다. 요즘은 Perl One-Liners Guide 같은 훌륭한 교재도 있고, LLM도 perl로 one liner 스크립트를 짜달라고 물어보면 뚝딱뚝딱하고 잘 짜주는 편이다.

Read more →
0

회사에서 쓴 코드를 공개 저장소에 올릴 수는 없어서 hackage-server를 직접 돌려보기로 했다. 빌드할 때 의존성 맞추기가 어려울 것 같아서 속는 셈 치고 Nix를 써봤는데⋯ 한 번에 서버가 에러 없이 실행됐다. 이제 사내에서 하스켈 패키지 관리를 할 수 있다!(그런데 아무도 안 씀⋯)

0

간혹 "이모지"가 아니라 "에모지"라고 쓰는 이유에 대한 질문을 받습니다. 여기다 써 두면 앞으로 링크만 던지면 되겠지?

요약: 에모지라서 에모지라고 씁니다.

"이모지"라는 표기는 아마도 "emoji"가 "emotion"이나 "emoticon"과 관련이 있다고 생각해서 나오는 것으로 보이는데요. "emoji"와 "emoticon"은 가짜동족어(false cognate)입니다. "emoji"는 일본어 絵文字(에모지)를 영어에서 그대로 받아들여 쓰고 있는 것입니다. 심지어 구성원리도 에모+지가 아니고 에+모지(絵+文字)입니다. "emotion"과 유사해 보이는 것은 순전히 우연일 뿐, 계통적으로 전혀 아무 상관이 없습니다. "이모티콘"과 "이미지"의 합성어가 아닙니다. (그랬으면 "-ji"가 아니라 "-ge"였겠죠.)

그리고 그렇기 때문에 에모지를 에모지로 표기할 실익이 생깁니다. :), ¯\_(ツ)_/¯, ^_^ 등은 이모티콘입니다. 반면 😂는 명확히 에모지입니다.

프로그래머에게 이건 정말 중요한 구분입니다. "이모티콘을 잘 표현하는 시스템"과 "에모지를 잘 표현하는 시스템"은 전혀 다른 과제이기 때문입니다. 에모지는 "그림 문자"라는 원래 뜻 그대로, 어떤 문자 집합(예를 들어 유니코드)에서 그림 문자가 "따로 있는" 것입니다. 내부 표현이야 어떻든, 적어도 최종 렌더링에서는 별도의 글리프가 할당되는 것이 에모지입니다. "무엇이 에모지이고 무엇이 에모지가 아닌가"는 상대적으로 명확합니다(문자 집합에 규정되어 있으니까).

반면 이모티콘은 "무엇이 이모티콘인가?"부터 불명확합니다. 우선 대부분의 이모티콘은 이모티콘이 아닌 문자를 조합하여 이모티콘이 만들어지는 형식입니다. 예를 들어 쌍점(:)이나 닫는 괄호())는 그 자체로는 이모티콘이 아니지만 합쳐 놓으면 :) 이모티콘이 됩니다. 하지만 조합에 새로운 의미를 부여했다고 해서 다 이모티콘이라고 부르지도 않습니다. -_- 같은 것은 대다수가 이모티콘으로 인정하지만, -> 같은 것은 이모티콘이라고 부르지 않는 경향이 있습니다.

- 문자와 > 문자에는 화살표라는 의미가 없기 때문에, -> 조합과 화살표의 시각적 유사성에 기대어 화살표라는 새로운 의미로 "오용"한 것은 이모티콘의 구성 원리에 해당합니다. 하지만 화살표는 인간의 특정한 정서(emotion)에 대응하지 않으므로 이모티콘이라고는 잘 부르지 않습니다. 그렇다고 얼굴 표정을 나타내야만 이모티콘인가 하면 그렇지도 않습니다. orz 같은 것은 이모티콘으로 간주하는 경향이 있어 보입니다. 오징어를 나타내는 <:=는 이모티콘인가? 이모티콘이 맞다면, 왜 ->는 이모티콘이 아니고 <:=는 이모티콘인가? 알 수 없습니다. ㅋㅋㅠㅠ는 둘 다 정서를 나타내는데, ㅠㅠ만이 아이콘적 성질을 가지므로 이모티콘이고 는 이모티콘이 아닌가? 알 수 없습니다. 만약 만 이모티콘이 아니라고 한다면, ㅋ큐ㅠ 에서 는 이모티콘인가 아닌가?? 알 수 없습니다. 이 알 수 없음은 이모티콘의 생래적 성질입니다. 어쩔 수 없죠.

0
0
0

하스켈의 Lazy Evaluation을 설명하려고 기상천외한 예시를(처음 보면 저게 왜 돌아가지 싶은 fibonacci 등) 드는게 좋은지 잘 모르겠다. 뭐, 자랑하고 싶은 마음은 이해가 가나, 평소에 개발하면서 Lazy Evaluation의 쓸모를 느끼게 되는 경우랑 좀 거리가 있어보인다. 그냥 최대한 선언적인 코드를 짜고싶으면 Eager Evaluation이 방해가 되게 되고 이때 Lazy Evaluation이 필요하다는 설명으로 족하다.

0

오 안녕하세요, 웹 몇 개월 전에 직접 운영하고 계신 접근성 사이트맵을 접한 프런트엔드 프로그래머입니다.

개인 블로그에 올릴 웹 접근성이 UI 설계에 중요한 이유 - 웹 접근성의 의의와 의미론적인 CSS 규칙을 설계하는 방법 초안 작성을 마치고 퇴고 작업을 거치는 중입니다. 레퍼런스 검증 등 객관성이 중요한 분야이다 보니, 작업 중간에 몇몇 전문가 분의 의견을 받고 싶어 커뮤니티 가입을 신청했습니다.

그리고 글 맨 하단 섹션에 글을 기획하며 찾은 외부 자료에 대해 목록을 추렸어서 참고 문서 추가에 도움이 되지 않을까 싶습니다.

서문

W3C 홈페이지의 내비게이션 항목 중 사명(Mission) 페이지를 가보면 설계 철학 중 첫 번째가 접근성으로 “모든 사람이 웹을 사용할 수 있게 해야 한다"라고 정의되어 있습니다. 웹 표준 명세는 그런 설계 철학을 지키고자 항상 접근성을 같이 고려하여 만들어지고 있습니다.

    웹의 힘은 보편성에 있습니다. 장애에 관계없이 모든 사람의 접근은 필수적인 측면입니다.
    – Tim Berners-Lee, Accessibility | Our mission | W3C

HTML은 마크업의 구조적 의미를 충분히 고려해서 웹 콘텐츠를 만든다면, 특별한 대응을 하지 않고 접근성을 담보되는 특징이 있습니다. Switch UI 같이 프런트엔드 프로그래머가 직접 구현이 필요해서 생기는 접근성의 한계에 대해서는1 WAI-ARIA를 통해 직접 접근성을 보조할 수 있습니다.

그리고 aria-busy, aria-current, aria-expanded, aria-pressed와 같은 WAI-ARIA 상태를 제대로 활용하면 명시적으로 UI 상태를 관리하기 용이한 개발자 경험(DX)을 갖고 있습니다. 해당 경험을 실무에서 적용한 사례 두가지를 소개하고자 합니다.
의미론적인 CSS 작성법
그간 CSS에서 픽셀을 움직이는건 꽤 빡셌지! 하지만 이제 논시멘틱(non-semantic) 한 클래스 이름과 HTML안에 쓰는 인라인 CSS, 거기다 자바스크립트 안에 작성하는 CSS 스타일을 쓰는게 진짜로 오지고 지리고 렛잇고인 방법인 것이다! 패밀리 가이 CSS GIF를 여기다 넣어라! 이렇게 ㅋ

(번역) 구닥다리 공룡을 위한 오늘날의 CSS — Steemit
원본 이미지 출처 - Dinosaur Comics

의미론적인 CSS 작성법이란 HTML의 의미성과 WAI-ARIA 접근성 요소를 기반으로 하는 CSS Rules 설계 방법입니다. 이 글에서 무엇을 다룰지 영상으로 이해하고 싶으신 분은 “How to write Semantic CSS - YouTube“를 먼저 보시길 바랍니다.

클래스 선택자는 CSS 특이도(Specificity)2 중에 중간 정도의 우선순위를 갖고 있어 범용도가 높은 특징을 갖고 있습니다. 이러한 특징으로 인해 모든 CSS 규칙(Rules)을 클래스 이름으로 정의하는 것이 흔한 사용 패턴이 되었습니다.

그러나 아래 문단에 인용한 W3C CSS 명세에 따르면 클래스 이름 위주의 CSS 규칙 정의는 웹 표준 측면에서 HTML이 가진 논리적 구조와 CSS 가상 클래스(Pseudo-classes)로 참조할 수 있는 빌트인 상태인 :checked, :default, :disabled, :invalid, :required 등이 충분히 있음에도 무시하는 것은 HTML의 구조적 의미를 약화하는 좋지 않은 관행이라고 합니다.

    CSS는 클래스 어트리뷰트에 강력한 기능을 부여하여, 고유한 역할이 거의 없는 엘리먼트(예: HTML의 <div> 및 <span>)를 기반으로 나만의 “문서 언어"를 설계하고 “class” 어트리뷰트를 통해 스타일을 지정할 수 있습니다. 하지만 문서 언어의 구조적 요소는 일반적으로 정해진 의미가 있지만, 사용자가 임의로 정의한 클래스는 그렇지 않을 수 있습니다. 따라서 이러한 관행을 피하는 것이 좋습니다. — “Class Selectors” Selectors Level 3 | W3C

    *원문에서 “Authors (작성자)” 키워드를 직역해 보니 어색해서 생략하거나 “사용자"로 대치했습니다.

또한 이 문제는 WAI-ARIA 상태를 활용해서 더욱 깊어질 수 있습니다. 서문의 마지막 문단에서 언급한 aria-busy(로딩 중), aria-current(현재 위치한 탭), aria-expanded(열림 닫힘 상태), aria-pressed(버튼 눌림 상태) 어트리뷰트 등으로 UI 상태를 의미상으로 관리할 수 있기 때문입니다.참고하면 좋은 자료
접근성 기반 UI 컴포넌트 설계 자료

직접 실습으로 익히는 것을 권하고자 바로 행동으로 옮겨 실천할 수 있는 자료를 중심으로 골랐습니다.

    논리적 설계와 HTML5 아웃라인 알고리즘: 웹의 근본인 HTML의 논리적 설계를 바탕으로 React 컴포넌트 디자인에 대해서 고민해 보고 아웃라인 알고리즘에 대해서 간단하게 알아보는 글입니다.
    접근성이 이끄는 웹 프런트엔드 테스트 자동화 : Wonderwall Tech: 여러 웹 표준 접근성 요소를 바탕으로 컴포넌트 마크업과 제어 상태를 설계하여, 이를 종단 테스트 수트의 시멘틱 플래그(Semantic Flag)로 활용할 수 있다고 소개한 글입니다.
    PandaCSS와 함께 CSS-in-JS의 미래로 : Wonderwall Tech: 바로 위 항목의 동 저자이신 김태희님의 의미론적 CSS 작성법에 대해 최근의 CSS-in-JS 도구 사용 측면으로 다룬 글입니다.
    Open UI: W3C 커뮤니티 그룹 중 하나로, 기본 HTML 사양에는 없어 별도 구현이 필요한 UI 컴포넌트에 대한 모범 사례를 정리하여 연구하는 커뮤니티입니다.
    Inclusive Components: 포괄적인(Inclusive) 여러 웹 인터페이스 설계 패턴이 수록된 블로그입니다.
        블로그 배너에 전자책 발간이 소개되어 있는데, 이미 국내에서 『인클루시브 디자인 패턴』이라는 제목으로 웹액츄얼리코리아를 통해 번역 출간되었습니다.

웹 접근성 학습 자료

    AOA11Y 접근성 오픈 아카데미 - YouTube: 정보접근성 인식 개선 및 확산을 목표로 NIA이 운영하는 YouTube 채널입니다. 해당 기관에서 만든 항공사 접근성 사례집 또한 유용합니다.
    웹 애플리케이션 엔지니어를 위한 웹 접근성의 기초 - azukiazusa.dev (일본어)
    웹 프런트엔드 구현에서 원본 기능을 손상시키지 마십시오 - azukiazusa.dev (일본어)
    WAI-ARIA를 배울 때 정리해 두고 싶은 것 - Hirao Yusuke (일본어)
    [명세 읽는 법] HTML의 요소를 어떻게 배울 것인가 (일본어)
        표준 명세를 통해 어떤 HTML 엘리먼트에 대한 콘텐츠 모델과 어트리뷰트, 접근성 고려 사항 등의 규칙을 파악하는 법을 소개합니다. 웹 표준 명세를 읽는 걸 낮설어 하시는 분에게 추천드립니다.
        제 경우 MDN 문서만으로 어떤 엘리먼트의 기술 사양을 파악하기에 애매하거나 누락된 부분에 대해 WHATWG 명세를 직접 참고하고 있습니다.6

웹 접근성 참고 자료

    레진 WAI-ARIA 가이드라인
    How to Meet WCAG (Quick Reference) | W3C, GitBook 형태의 WCAG 2.1 한국어 가이드
    https://a11ykr.github.io: KWCAG 및 W3C 한국어 초벌 번역 모음 사이트맵입니다.
0
0
1

Powershell은. Net기반이라. Net 라이브러리도 가져다 쓸 수 있고 좀 더 이상하게까지 가면 C#코드를 임베딩해서 쓸 수도 있다. 어쨌든 셸 이지만 모든 것이 문자열이 아닌 납득할만한 타입이 있는 셸이다. 그리고 크로스 플랫폼도 지원한다. 하지만 몇몇 명령어는 어째 특정 경우의 동작이 괴상하고, 나중에 나온 크로스 플랫폼 버전에서만 납득 할만한 동작을 하게 하는 플래그가 제공 되기도 한다. 예를 들어 ConvertTo-Json은 json 문자열로 직렬화 해주는 명령인데, https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/convertto-json?view=powershell-7.5#-asarray 옵션이 없으면 요소가 한개인 배열의 경우 그 요소만 꺼내서 직렬화 해버린다.

0

패키지 저장소에 내가 만든 패키지를 업로드해보니까 다음과 같이 코딩말고도 할 게 꽤 많다.

  • 저장소 계정 만들고 권한 승인 받기[1]
  • 라이브러리 코드에 주석 적기
  • 라이선스 정하기
  • 소스 코드 저장소 정하기
  • 커밋 메시지 적기
  • 체인지로그 적기
  • 테스트 코드 적기
  • 버전 관리하기[^4]

LLM 덕분에 영어로 적어야 하는 문서 대부분은 어렵지 않게 할 수 있었다. LLM 때문에 바보 된다는 말도 많지만 영어 때문에 주저 했던 작업을 쉽게 시작할 수 있었다는 점에서 확실히 진입 장벽은 낮아졌다.

앞으로 더 해볼 일은 특정 배포판에 패키지를 배포하는 일이다. 해키지에서 지원하는 배포판은 다음과 같다.

  • Arch
  • Debian
  • Fedora
  • FreeBSD
  • LTS
  • LTSHaskell
  • NixOS
  • Stackage
  • openSUSE

도전 과제로 위에 적은 모든 배포판에 내가 만든 패키지 배포해보는 것도 재밌겠다. LTS, LTSHaskell은 뭔가 했는데, 스태키지(Stackage)에 패키지 업로드하는 방법을 안내한 문서를 보니까 스태키지의 저장소 종류인 것 같다.

한편 해커즈 퍼브의 홍민희 님도 헤비(?) 하스켈 패키지 업로더이신데 예를 들어 seonbi도 사실 하스켈 패키지이다.

해키지 업로더 계정이 필요하신 분은 나와 홍민희 님을 멘션하면 이미 두 명의 승인은 따 놓은 당상이다.


  1. 해키지에서는 가입 후 기존 해키지 업로더 2명의 승인이 필요하다. ↩︎

0

FTP로 배포하는 php 서버에서(20년 전 대부분의 웹사이트), GitOps, 서버리스 아키텍쳐, 이벤트 드라이븐 프로그래밍의 편린을 엿볼수 있다. 지나고나서 이런 얘기는 누구나 다 할수있다. 근데 그 당시에 다같이 php 욕하는거에 휩쓸리지 않고 이걸 알아챈 사람이 있었을까.

0

ESM 알못인데 왠지 tsx를 쓰니까 잘 돌아서(뭔가 알아서 해주는듯하다), 그냥 배포도 .ts 파일로해서 tsx로 실행하도록 바꿨다. ...는 Deno잖아;;

0
0

디지털 접근성에 관심 있는 분들이 계시려나...

구린 영어 실력에 LLM을 빌어서 일단은 혼자 하고 있지만...

예전처럼 평가 중심이 아닌 구현 방법 중심의 글을 좀 생산하고 싶다고...

일단 계획은 이런데... 같이 할 사람 있으면 좋겠다고 생각합니다아아...

https://a11ykr.github.io/docs/

0

보통은 Ruby 코드를 작성할때 irb 같은 대화형 인터페이스를 사용하는 것이 일반적이지만, Bash 스크립트와 섞어서 사용할때 one-liner 스크립트를 작성하면 더욱 빛을 발휘합니다. 여기서 one-liner 스크립트란 한줄짜리로 실행하는 스크립트라고 이해하면 됩니다. ruby one-liner 스크립트로 작성할때는 다음과 같이 시작합니다.

$ ruby -e "<expression>"

여기서 -e 옵션은 one-liner 스크립트의 필수요소인데, 파라미터로 넘겨준 한줄짜리 Ruby 코드를 evaluation해주는 역할을 합니다. 여러분이 **파이프 연산자**에 대한 개념을 이해하고 있다면, 이런 트릭도 사용할 수 있습니다.

$ echo "5" | ruby -e "gets.to_i.times |t| \{ puts 'hello world' \}"
# =>
# hello world
# hello world
# hello world
# hello world
# hello world

표준라이브러리를 사용하고 싶을때는 -r 옵션을 사용할 수도 있습니다. 이 옵션은 ruby에서 require를 의미하는데, 식을 평가하기전에 require문을 미리 선언하고 들어가는 것이라 이해하면 됩니다.

예를 들면, 이런 것도 가능합니다 .

$ echo "9" | ruby -rmath -e "puts Math.sqrt(gets.to_i)"
# => 3.0

위의 스크립트는 아래와 동일합니다.

$ echo "9" | ruby -e "require 'math'; puts Math.sqrt(gets.to_i)"
# => 3.0

이런 원리를 이용하면, JSON/XML/CSV/YAML 등의 포맷으로 출력되는 데이터를 어렵지 않게 처리할 수 있습니다. one-liner 스크립트를 작성하는 방법에 대해 자세히 알아가고 싶다면, https://learnbyexample.github.io/learn_ruby_oneliners/one-liner-introduction.html 여기를 참고해주시면 좋을 것 같습니다.

이에 관해서, 25분-30분 정도 분량의 글을 정리해서 올릴 것 같은데 커밍쑨.....

0

CLI 도구를 조합해서 커맨드 작성할때, (일회성이라면 모르겠지만) 자주 사용하는 스크립트라면 짧은 옵션보다 긴 옵션을 사용하는 것이 좋습니다. 풀 네임으로 커맨드라인 명령어를 작성하는 것이 어떻게 보면 문서화의 역할도 하기 때문입니다. 다른 프로그램에서 시스템 콜을 호출해서 사용하는 유즈케이스라면 더더욱 가독성을 높이는 효과가 있습니다.

어떤 CLI 도구는 man 커맨드로 문서를 봤을때 양이 어마어마하고 어렵게 느껴질 수 있습니다. 하지만, 위에서 언급한 것처럼 full name으로 작성한 스니펫들을 모아놓으면 그렇게 어렵지도 않고 각 도구의 역할을 명확하게 이해할 수 있고, 결과적으로는 장기적인 기억으로 남을 수 있습니다. git, curl, aws-cli, jq, gh 어떤 CLI 도구이던간에 모든 옵션을 하나하나 기억하려고 할 필요도 없습니다. 필요하면 그때그때 full name으로 명시된 옵션으로 스크립트를 짜놓고 모아두면 됩니다.

https://matklad.github.io/2025/03/21/use-long-options-in-scripts.html

0

https://newsletter.posthog.com/p/50-things-weve-learned-about-building

PostHog가 성공적인 제품을 만들면서 깨달은 50가지 교훈 (뉴스레터에서 지금까지 발행해놓은 것들 오마카세처럼 모아놓음)

그 중에서 마음에 드는 것들을 몇개 뽑아보자면...

  1. 신뢰는 투명성에서 온다. Build in Public 같은 것이 도움이 될 수 있음
  2. 시장에 내놓지 않으면 검증 조차 할 수 없음. 일단 시장에 내놓고 반응을 살펴볼 것
  3. 개밥먹기를 통해서 고객에게 전달되기 전에 문제점을 빠르게 인식하고 개선할 수 있는 흐름을 만들 것
0

洪 民憙 (Hong Minhee) shared the below article:

mkDerivation 인자로 함수를 넘기는 이유

lionhairdino @lionhairdino@hackers.pub

NixOS.kr 디스코드에 올렸는데, 다른 분들의 의견을 들어보려고 해커스펍에도 올립니다. 닉스 경험이 많지 않은 사람의 글이니, 정확하지 않을 수 있습니다. 틀린 곳이 있으면 바로 알려주세요.

※ 닉스를 처음 접하는 분들이나, 닉스로 실용적인 업무를 하시는데 문제가 없는 분들한테는 적당한 글은 아닙니다. 서두에 읽으면 도움이 될만한 분들을 추려서 알려 드리려고 하니, 의외로 필요한 분들이 없겠습니다. 실무자들은 이렇게까지 파고들며 알 필요 없고, 닉스 개발자들이야 당연히 아는 내용일테고, 입문자 분들도 역시 이런 내용으로 어렵다는 인식을 갖고 시작할 필요는 없으니까요. 그럼 남은 건 하나네요. mkDerivation 동작을 이미 아는 분들의 킬링 타임용이 되겠습니다.


외국어를 익힐 때, 문법없이 실전과 부딪히며 배우는 방법이 더 좋기는 한데, 가끔은 문법을 따로 보기 전엔 넘기 힘든 것들이 있습니다. 닉스란 외국어를 익히는데도 실제 설정 파일을 많이 보는 것이 우선이지만, 가끔 "문법"을 짚고 넘어가면 도움이 되는 것들이 있습니다.

닉스 알약 (제목이 재밌네요. 알약) 글을 보면 mkDerivation속성 집합을 받아, 거기에 stdenv 등 기본적인 것을 추가한 속성 집합을 만들어 derivaition 함수에 넘기는 간단한 래핑 함수임을 직관적으로 잘 설명하고 있습니다.

그런데, 실제 사용 예시들을 만나면, mkDerivation에 속성 집합을 넘기지 않고, attr: {...} 형태의 함수를 넘기는 경우를 더 자주 만납니다. 그래서, 왜 그러는지 실제 구현 코드를 보고 이유를 찾아 봤습니다.

  mkDerivation =
    fnOrAttrs:
    if builtins.isFunction fnOrAttrs then
      makeDerivationExtensible fnOrAttrs
    else
      makeDerivationExtensibleConst fnOrAttrs;

mkDerivation의 정의를 보면 인자로 함수를 받았느냐 아니냐에 따른 동작을 분기합니다. 단순히, stdenv에서 가져온 속성들을 추가한다면, 함수를 인자로 받지 않아도 속성 집합을 병합해주는 //의 동작만 있어도 충분합니다.

{ a = 1; } // { b = stdenv.XXX; }

하지만, 함수로 받는 이유를 찾으면, 코드가 단순하지 않습니다. 아래는 함수를 받을 때 동작하는 실제 구현 일부를 가져 왔습니다.

makeDerivationExtensible =
    rattrs:
    let
      args = rattrs (args // { inherit finalPackage overrideAttrs; });
      ...

전체를 보기 전에 일단 args에서부터 머리가 좀 복잡해집니다. argsargs를 재귀 참조하고 있습니다. 보통 rattrs 매개 변수로는 아래와 같은 함수들이 들어 옵니다.

stdenv.mkDerivation (finalAttrs: {
  pname = "timed";
  version = "3.6.23";
  ...
    tag = finalAttrs.version;
}

(와, 해커스펍은 코드 블록에 ANSI가 먹습니다! 지원하는 곳들이 드문데요.)
코드를 바로 분석하기 전에, 닉스의 재귀 동작을 먼저 보면 좋습니다.

재귀 생각 스트레칭

nix-repl> let r = {a = 1; b = a;}; in r
error: undefined variable 'a'

위 동작은 오류지만, 아래처럼 rec를 넣어주면 가능합니다.

nix-repl> let r = rec {a = 1; b = a;}; in r 
{ a = 1; b = 1; }

rec동작은 Lazy 언어의 fix로 재귀를 구현하는 동작입니다. ※ 참고 Fix 함수

rec를 써서 속성 안에 정의 중인 속성에 접근할 수 있습니다. 그런데, 아래 같이 속성을 r.a 로 접근하면, rec 없이도 가능해집니다.

nix-repl> let r = {a = 1; b = r.a;}; in r
{ a = 1; b = 1; }

닉스 언어의 Lazy한 특성 때문에 가능합니다.

이제, 원래 문제와 비슷한 모양으로 넘어가 보겠습니다. 아래같은 형태로 바로 자기 자신에 재귀적으로 접근하면 무한 재귀 에러가 나지만,

nix-repl> let x = x + 1; in x
       error: infinite recursion encountered

아래처럼 람다 함수에 인자로 넘기면 얘기가 달라집니다.

nix-repl> let args = (attr: {c = 1; b = attr.a + attr.c + 1;}) (args // { a = 1; }); in args
{ b = 3; c = 1; }

여기서 속성b의 정의 동작이 중요합니다. 위 내용을 nix-instantiate로 평가하면,

 nix-instantiate --eval -E 'let args = (attr: {c = 1; b = attr.a + attr.c + 1;}) (args // { a = 1; }); in args'
{ b = <CODE>; c = 1; }

--eval 옵션은 WHNF까지만 평가합니다. <CODE>는 하스켈 문서에서 나오는 <thunk>와 같은, 평가가 아직 이루어지지 않은 상태를 뜻합니다. ※ Nix Evaluation Performance
b는 아직 평가가 되지 않았으니, 에러가 나지 않고, b가 필요한 순간에는 attr.a가 뭔지 알 수 있는 때가 됩니다.

attr: 
  { c = 1; 
    b = attr.a + attr.c + 1;
  }

속성 b아직 알 수 없는, 미래의 attr에 있는 a를 받아 써먹고, 원래는 rec없이 접근하지 못했던, c에도 attr.c로 접근이 가능합니다. (attr.c은 현재 정의하고 있는 속성셋의 c가 아니라, 매개 변수 attr로 들어온 속성셋의 c입니다.)

원래 문제로 다시 설명하면, mkDerivation에 넘기고 있는, 사용자 함수 finalAttrs: { ... }에서, 닉스 시스템이 넣어주는 stdenv 값 같은 것들과 사용자 함수내의 속성들을 섞어서 속성 정의를 할 수 있다는 얘기입니다. 아래처럼 말입니다.

    tag = finalAttrs.version;

뭐하러, 이런 복잡한 개념을 쓰는가 하면, 단순히 속성 추가가 아니라, 기존 속성이 앞으로 추가 될 속성을 기반으로 정의되어야 할 때는 이렇게 해야만 합니다. 함수형 언어에선 자주 보이는, 미래값을 가져다 쓰는 재귀 패턴인데, 저는 아직 그리 익숙하진 않습니다.

Read more →
0

프론트엔드 개발자분들 위주로 페디버스로 영입을 많이 해보고 싶다. 포트폴리오로 개발할만한 것이 지천에 널려있는데...!!

  • 인스타그램 클론코딩 : PixelFed 클라이언트 개발에 적용하기
  • 트위터 클론코딩 : 마스토돈 클라이언트 개발할때 적용하기
  • 나만의 블로그 만들기 : 이건.... 해커스펍이 그 역할을 하겠지...?
0
0
0
0
0

昨晩、俺が寝てる間にアメリカにいる誰かが俺の blockchain.com アカウントにログインしようとして、実際に成功しやがった。しかも、2段階認証(2FA)まで解除されてたんだ。カスタマーサポートにはすぐに状況を連絡して、とりあえずパスワードだけは変更しておいた。どうしてこんなことになったのか一つずつ確認したかったけど、週末だし家族との時間を優先したかったから、深追いは後回しにした。

残高はゼロだったから金銭的な被害はなかったけど、自分の2FA(OTP)が突破されたのは初めてのことだし、原因はきっちり突き止めるつもりだ。

原因は全然分からないまま、結局退会することにした。メールのデバイス認証をしないと進めない仕様で、俺のGmailには侵入の証跡なんて全く無いのに、2段階認証まで無効にした。まおかげさまで、Googleにログインしてる端末の履歴と、1Passwordのアクセス履歴も全部チェック済み。(写真のあの時間、当たり前だけど俺はぐっすり寝てたよ。)

なんとも後味の悪い話だな。

blockchain.comからの認証要請のメール。あの時間俺は眠っていた。
0
0
0

닉스(Nix)를 써보려고 Nix Pills라는 글을 읽기 시작했다. 화면에 Hello, world!를 출력하는 패키지 hello를 닉스로 설치하는 방법이 나오더라.

nix-env -i hello

저런 하찮은 프로그램이 패키지로 존재하는지 처음 알았다.

혹시 해키지에도 저런 게 있는지 검색을 해봤는데 있더라.[1] 2010년에 Simon Marlow가 업로드했다. 그런데 특이한 점이 이 패키지의 소스 코드 저장소 주소가 darcs.haskell.org라는 것이다. darcs를 호스팅하는 곳은 hub.darcs.net만 있는 줄 알았는데 haskell.org에도 있었구나⋯ 그런데 이 사이트 UI도 아예 없고 그냥 디렉터리 리스팅이 나오는데 hub.darcs.net으로 이전하시면 안 되려나.


  1. https://hackage.haskell.org/package/hello-1.0.0.2 ↩︎

0
0

BotKit을 이용해 국내외 기술 블로그의 아티클을 업로드하는 'Tech Blog Bot'을 만들었다. 1시간에 한 번씩 구독중인 블로그들의 새 아티클을 확인해 큐에 넣고, 1분에 하나씩 큐의 아티클을 업로드한다. BotKit의 유려함에 첫 번째로 놀랐고, 테스트로 돌려본 봇이 스팸짓을 하는 걸 보면서 두 번째로 놀랐다. techblogbot.parksb.xyz/

트위터 봇 만들 때는 스팸짓 좀 해도 어차피 팔로워가 없으면 다른 사람 피드를 가득 채울 일이 없으니 부담도 없었다. 그런데 여기에서는 봇을 조금 잘못 돌리면 연합 타임라인이 순식간에 봇의 스팸글로 가득 차 버린다. 트위터 서버에 비해 영세한 이 서버에 부담을 주지 않아야 한다는 생각도 들고... 아무쪼록 조심해야 할 것 같다.

0

BotKit을 이용해 국내외 기술 블로그의 아티클을 업로드하는 'Tech Blog Bot'을 만들었다. 1시간에 한 번씩 구독중인 블로그들의 새 아티클을 확인해 큐에 넣고, 1분에 하나씩 큐의 아티클을 업로드한다. BotKit의 유려함에 첫 번째로 놀랐고, 테스트로 돌려본 봇이 스팸짓을 하는 걸 보면서 두 번째로 놀랐다. techblogbot.parksb.xyz/

0

그러고보니 문득 생각이 난 건데 해커스.펍 (@hollo@hollo.socialHollo :hollo:)와 마찬가지로 @hongminhee@hollo.social洪 民憙 (Hong Minhee) 님이 Fedify(@fedify@hollo.socialFedify: an ActivityPub server framework) 기반으로 만든 자체 ActivityPub 소프트웨어라는 걸 알게 된 건 꽤 됐지만 그렇게 규모가 제법 되는 서비스가 저 분 소유의 홈서버에서 돌아가고 있다는 사실을 알게 된 건 얼마 전의 일이다.

1
0
0
0

昨晩、俺が寝てる間にアメリカにいる誰かが俺の blockchain.com アカウントにログインしようとして、実際に成功しやがった。しかも、2段階認証(2FA)まで解除されてたんだ。カスタマーサポートにはすぐに状況を連絡して、とりあえずパスワードだけは変更しておいた。どうしてこんなことになったのか一つずつ確認したかったけど、週末だし家族との時間を優先したかったから、深追いは後回しにした。

残高はゼロだったから金銭的な被害はなかったけど、自分の2FA(OTP)が突破されたのは初めてのことだし、原因はきっちり突き止めるつもりだ。

0
0

国漢文混用体からHolloまで

本日、第8回FediLUG勉強会で「国漢文混用体からHolloまで」というタイトルで発表をしてきました。

私がなぜActivityPubサーバーフレームワークのFedifyと、シングルユーザー向けActivityPubサーバーのHolloを開発する事に成ったのか、その旅路を共有しました。

実は全ての始まりは、韓国語の「国漢文混用体」(漢字ハングル混じり文)に「振りハングル」を付けたいという単純な願いからでした。この小さな目標が、最終的にFedifyHolloという二つのプロジェクトへと発展したのです。

興味のある方は、発表スライドをご覧ください: 「国漢文混用体からHolloまで」(Speaker Deck)

0
0
0
0
0
0