Overview

HTML 페이지를 만들 때 고려해야 하는 것 중 하나가 웹 접근성입니다.

웹 접근성이란 시각장애인들이 웹 페이지를 원활하게 이용할 수 있도록 알려주는 가이드라인이라고 생각하면 됩니다.

대표적으로 input 과 label 이 있는데요.

일반 사람들은 별다른 설명 없이 input, button, a 등등의 태그만 있어도 어느정도 이용할 수 있지만 시각장애인들은 직접 클릭할 수도 없이 탭 같은 걸로 각 요소를 이동하는 수밖에 없습니다.

따라서 탭을 눌렀을 때 초점이 어느 순서로 이동하는지, 초점이 잡혔을 때의 안내 메시지가 제대로 나오는지 여부는 굉장히 중요합니다.

이런 설정들을 HTML native 요소만으로는 처리하기 어렵기 때문에 W3C 는 WAI-ARIA 라는 걸 정의했습니다.


1. WAI-ARIA

WAI-ARIA (Web Accessibility Initiative – Accessible Rich Internet Applications) 는 W3C 에서 정의한 기술로 웹 접근성을 위해 지원되는 여러 가지 특성들을 의미합니다.

일반 사용자가 보기에 정상인 화면들도 HTML 요소에 따라서 스크린 리더 등의 보조기기에서 제대로 읽히지 않을 수 있습니다.

WAI-ARIA 는 이를 개선하기 위해 웹 애플리케이션에 역할(Role), 속성(Property), 상태(State) 정보를 추가할 수 있습니다.


1.1. Role

Role 은 HTML 요소의 역할을 정의합니다.

일반적으로는 HTML native 요소만으로 이를 처리하는게 가장 이상적입니다.

버튼은 button, 링크는 a, 체크박스는 input checkbox 등등 이미 존재하는 요소들로도 충분히 표현할 수 있습니다.

하지만 이미지에 버튼 클릭 이벤트를 준다던가 좀더 세세하고 다양한 설정이 하고 싶을 때는 native 요소만으로 부족할 수 있습니다.

이럴 때 role 을 사용해서 해당 요소들의 역할을 명시합니다.

Role 의 종류는 W3C WAI ARIA 의 5.3 Categorization of Roles 에서 확인할 수 있습니다.

<!-- role example -->
<li role="menuitem">Open file…</li>

1.2. State and Property

속성 (Property) 는 해당 요소의 특징이나 상황을 정의하며 aria- 라는 접두사를 사용합니다.

상태 (State) 는 요소의 현재 상태를 나타냅니다.

<!-- property state example 1 -->
<li role="checkbox" aria-checked="true">체크박스 아이템</li>

<!-- property state example 2 -->
<div role="alert" aria-live="assertive">올바르지 않은 입력입니다.</div>

2. ARIA 속성들

공부한 속성들에 대해서 정리합니다.

앞으로도 생길때마다 조금씩 추가할 예정입니다.


2.1. role="checkbox" aria-checked="true"

<span role="checkbox" aria-checked="false" tabindex="0" aria-labelledby="chk1-label"></span> 
<label id="chk1-label">Remember my preferences</label>

<!-- native 요소로 사용할 수 있는 경우 -->
<input type="checkbox" id="chk1-label">
<label for="chk1-label">Remember my preferences</label>

특정 요소에 체크박스 역할을 부여합니다.

aria-checked 를 사용해서 체크됨, 체크안됨 여부를 판단할 수 있습니다.

focus 되지 않는 요소일 경우 tabindex 를 사용하기도 합니다.

가능하면 HTML native checkbox 를 사용하는게 권장되지만 사용할 수 없는 경우에 ARIA 속성을 사용합니다.


2.2. aria-label, aria-labelledby, aria-describedby

특정 요소를 설명하는 데 사용되는 ARIA 속성들입니다.

비슷해보이지만 조금씩 차이가 있습니다.


<button aria-label="menu" class="button"></button>

aria-label 은 우리가 흔히 알고 있는 Label 목적을 위한 속성입니다.

특정 요소에 대한 설명을 그대로 적습니다.

텍스트 대신 그래픽을 사용하는 경우처럼 추가 설명이 필요한 경우 사용할 수 있습니다.


<span id="rg-label">음료수 옵션</span>
<div role="radiogroup" aria-labelledby="rg-label"></div>

aria-labelledbyaria-label 과 비슷하지만 조금 다릅니다.

aria-label 은 어떤 요소에 대한 설명을 직접 적는 반면, aria-labelledby 은 다른 요소의 ID 값을 매칭시킵니다.

aria-labelledby 은 Label 자체를 재정의하기 때문에 다른 모든 Label 속성들, aria-label 또는 HTML native label 과 함께 쓰여도 항상 aria-labelledby 을 우선합니다.


<label for="pw">Password:</label>
<input type="password" id="pw" aria-describedby="pw-help">
<div id="pw-help">비밀번호는 12 자 이상으로 이루어져야 합니다</div>

aria-describedbyaria-labelledby 와 같은 방식으로 다른 요소의 ID 를 매칭하여 현재 요소에 대한 설명을 나타냅니다.

둘의 사용법과 쓰임새가 굉장히 비슷하여 헷갈릴 수도 있지만 다른 목적으로 사용됩니다.

MDN Web Docs - Using the aria-describedby attribute 에는 다음과 같이 나와있습니다.

This is very similar to aria-labelledby: a label describes the essence of an object, while a description provides more information that the user might need.

label 관련 속성들과의 가장 큰 차이점은 Label 이 요소의 필수 설명이라면 aria-describedby 은 어디까지나 부연 설명이라는 점입니다.

그래서 위 예시 코드에서처럼 label 태그와 함께 사용할 수 있습니다.


2.3. aria-live

JavaScript 를 사용하면 페이지를 새로 로드하지 않고 일부만 동적으로 변경하는게 가능합니다.

동적인 변경은 페이지를 볼 수 있는 사용자들은 알 수 있지만, 시각 장애인들은 알아채기 어렵습니다.

그래서 이런 동적인 (실시간) 변경들을 알려줄 수 있는 aria-live 라는 속성이 제공됩니다.


<input type="text" name="email">
<div role="alert" aria-live="assertive">이메일 형식이 올바르지 않습니다.</div>

회원가입 또는 로그인 페이지에서 사용하는 Email Input 은 실시간으로 Email 형식 검사를 하여 올바른 형식이 아니면 빨간색 에러 메시지를 사용자에게 노출합니다.

페이지를 볼 수 있는 사용자는 그 정보를 실시간으로 확인할 수 있지만 시각장애인은 에러 메시지가 노출되었다는 사실을 모를 수 있습니다.

이럴 때 role="alert" 로 경고 역할을 갖고 있는 요소를 만들고 실시간 변화를 감지해서 알려주는 aria-live 속성을 추가할 수 있습니다.

aria-live 의 값으로는 다음 값들이 올 수 있습니다.

  • off (default)
  • polite : 현재 진행중인 음성 또는 타이핑 이후에 알림
  • assertive : 현재 진행중인 알림을 중단하고 즉시 알림

assertive 값은 사용자의 현재 작업을 방해할 수 있기 때문에 신중하게 적용해야 합니다.


2.4. role="alert"

alert 역할은 사용자에게 동적인 변화를 알려줄 때 사용합니다.

스크린 리더는 alert 역할이 붙은 요소가 업데이트 되면 바로 읽기 시작합니다.

role="alert" 로 설정한다는 건 aria-live="assertive" aria-atomic="true" 와 동일합니다.


2.5. role="timer"

현재 요소가 timer 로 사용되고 있다는 걸 의미합니다.

초를 계속 세주려면 aria-live 속성을 켜주면 되지만.. 1초마다 계속 컨텐츠가 갱신되기 때문에 알림이 부자연스럽게 계속 끊기는 이슈가 존재합니다.

만약 timer 에 초점이 잡혔을 때의 남은 시간만 읽어주길 바란다면 role="timer" 설정만 추가해주면 됩니다.


Reference

'공부 > Web' 카테고리의 다른 글

JWT (Json Web Token)  (3) 2021.05.22
URI 란?  (0) 2020.08.26

에러 로그

$ yarn start  
yarn run v1.22.17
$ react-scripts start
node:internal/modules/cjs/loader:488
      throw e;
      ^

Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: Package subpath './lib/tokenize' is not defined by "exports" in /Users/Documents/my/projects/practice-codes/react-js-hello/node_modules/postcss-safe-parser/node_modules/postcss/package.json
    at new NodeError (node:internal/errors:371:5)
    at throwExportsNotFound (node:internal/modules/esm/resolve:416:9)
    at packageExportsResolve (node:internal/modules/esm/resolve:669:3)
    at resolveExports (node:internal/modules/cjs/loader:482:36)
    at Function.Module._findPath (node:internal/modules/cjs/loader:522:31)
    at Function.Module._resolveFilename (node:internal/modules/cjs/loader:919:27)
    at Function.Module._load (node:internal/modules/cjs/loader:778:27)
    at Module.require (node:internal/modules/cjs/loader:999:19)
    at require (node:internal/modules/cjs/helpers:102:18)
    at Object.<anonymous> (/Users/Documents/my/projects/practice-codes/react-js-hello/node_modules/postcss-safe-parser/lib/safe-parser.js:1:17) {
  code: 'ERR_PACKAGE_PATH_NOT_EXPORTED'
}

Node.js v17.0.1
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

원인

Mac OS 를 BigSur 로 업그레이드 후 연습중이던 React 프로젝트를 클론받아 실행했더니 에러가 발생했습니다.

복잡한 프로젝트도 아니어서 당황하던 중 검색해보니 node 17 버전을 사용해서 그렇다는 글을 봤습니다.

현재 제 노드 버전을 확인해보니 v17.0.1 을 사용하고 있었습니다.


해결

nvm (Node Version Manager) 을 설치한 후에 노드 버전을 다운그레이드 해서 해결했습니다.

처음에 brew install nvm 으로 설치했는데 잘 안되어서 nvm Github 을 보고 다시 설치했습니다.

# nvm 설치
$ curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | bash

설치 후에 ~/.zshrc 을 열어 맨 아래에 다음 내용을 붙여넣습니다.

기본 터미널을 bash 로 사용하고 있다면 ~/.bash_profile 에 추가하면 됩니다.

export NVM_DIR="$([ -z "${XDG_CONFIG_HOME-}" ] && printf %s "${HOME}/.nvm" || printf %s "${XDG_CONFIG_HOME}/nvm")"
[ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh" # This loads nvm

마지막으로 ~/.zshrc 를 갱신한 뒤 LTS 버전을 설치하고 다시 실행해보면 정상적으로 동작합니다.

# nvm command 가 안뜨면 갱신
$ source ~/.zshrc

# nvm 설치 확인
$ nvm -v
0.39.0

# node lts 버전 설치
$ nvm install --lts

# 16 버전이 설치됨
$ node -v
v16.13.0

Reference

1. Overview

Rails Session 은 우리가 알고있는 세션과 크게 다르지 않습니다.

사용자에 대한 일부 데이터를 저장하기 위해 사용합니다.

쿠키를 사용할 수도 있지만 외부에 노출되는 쿠키와 달리 서버에만 저장해야 하는 중요한 데이터들은 세션에 저장하면 편리합니다.


2. 사용법

Rails Session 은 Hash 처럼 사용하면 됩니다.

다른 Controller 에서 저장한 데이터를 꺼내 쓸 수 있습니다.


# app/controllers/index_controllers.rb
def create
    # ...
    session[:current_user_id] = @user.id
    # ...
end

예를 들어 IndexController 에서 저장한 세션값을..


# app/controllers/users_controllers.rb
def index
    # ...
    current_user = User.find_by_id(session[:current_user_id])
    # ...
end

UserController 에서 꺼내서 사용할 수 있습니다.


3. Session Stores

세션 저장소의 종류는 쿠키, 데이터베이스, Memcached, Redis 등등 다양합니다.

쿠키 세션 저장소를 제외한 모든 세션 저장소는 동일한 프로세스로 동작합니다.



3.1. Session 값 저장

  1. session[:current_user_id] = 1 을 호출했는데 기존에 사용하던 세션(Session ID) 이 없는 경우
  2. Rails 는 09497d46978bf6f32265fefb5cc52264 와 같은 임의의 Session ID 를 사용하여 sessions 테이블에 새로운 record 를 저장
  3. 해당 record 의 data 속성에 {current_user_id: 1} (Base64-encoded) 값도 함께 저장
  4. 생성한 Session ID (09497d46978bf6f32265fefb5cc52264) 는 Set-Cookie 를 사용하여 브라우저에게 전달

3.2. Session 값 가져오기

  1. 브라우저가 서버에 요청할 때 Cookie: 헤더를 사용해서 동일한 쿠키값을 전달
    • (1번 예시) Cookie: _my_app_session=09497d46978bf6f32265fefb5cc52264; path=/; HttpOnly
  2. 코드에서 session[:current_user_id] 을 호출
  3. 쿠키에 있는 Session ID 값으로 sessions 테이블에 있는 record 를 가져옴
  4. record 에 있는 data 속성에서 current_user_id 값을 가져옴

Reference

Shell Script 전체 코드

#! /usr/bin/env bash

hosts = (a.example.com b.example.com)
LOG = "access.log"
pattern = "ERROR|WARN"

for host in $hosts
do
    if [ -z $pattern ]; then
        ssh deploy@$host "tail -F $LOG" | awk -v server=$host '{print "["server"]", $0}' &
    else
        ssh deploy@$host "tail -F $LOG" | awk -v server=$host -v pattern=$pattern '$0~pattern {print "["server"]", $0}' &
    fi
done

trap "ps | grep ssh | grep $LOG | awk '{print \$1}' | xargs kill -9" INT
wait

명령어

각 명령어에 대한 자세한 설명은 생략하고 간단하게 나열합니다.


tail

ssh deploy@$host "tail -F $LOG" &

원격 서버에 명령어를 전달하려면 ssh deploy@$host "{command}" 형태로 사용합니다.

명령어의 끝에 & 을 붙여서 모든 tail 명령어를 백그라운드에서 실행시키고 출력값만 현재 쉘에서 모아서 봅니다.


awk

awk -v server=$host '{print "["server"]", $0}'

여기서 awk 명령어는 tail 로 출력되는 로그들을 특정 포맷으로 감싸서 재출력하는 기능을 합니다.

-v 옵션은 awk action 에 특정 변수를 넘겨주고 싶을 때 사용하고 $0 은 레코드 전체를 의미합니다.

awk -v server=$host '{print "["server"]", $0}' 은 로그들을 [a.example.com] 로그내용~ 으로 변환해서 출력해줍니다.

로그들이 여러개 쌓이면 어디 서버에서 발생한 건지 알수 없기 때문이죠


awk (filter)

awk -v server=$host -v pattern=$pattern '$0~pattern {print "["server"]", $0}'

ERROR 또는 WARN 로그만 보고 싶을 수도 있습니다.

정규표현식 ~ 오퍼레이터를 사용하여 레코드 전체 ($0) 에서 정규표현식 $pattern 이 포함되어 있는 경우에만 출력하도록 필터를 걸었습니다.

처음에는 grep 명령어를 사용했으나 속도가 너무 느려서 실시간 전달이 안되고 로그가 뚝뚝 끊겨서 전달되어 보기 굉장히 불편했습니다.


trap & wait

trap "ps | grep ssh | grep $LOG | awk '{print \$1}' | xargs kill -9" INT
wait

& 기호를 붙여 백그라운드에서 실행했기 때문에 로그를 그만 볼때 모든 프로세스를 한번에 종료시켜야 합니다.

trap <handler> <signal> 은 특정 시그널을 받았을 때 handler 를 실행시키는 명령어입니다.

wait 은 자식 프로세스가 종료될 때까지 대기합니다.

즉, 위 코드는 실행한 쉘 스크립트를 대기 시켰다가 Ctrl + C 시그널을 받았을 때 백그라운드 프로세스를 모두 kill 합니다.

wait 명령어를 넣지 않으면 스크립트를 실행한 후에 전달할 시그널이 애매합니다.

그리고 로그 보고 있을 거니까 부모 프로세스를 굳이 조작할 필요도 없습니다.


Reference

에러 로그

TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing

원인

JPA 연관 관계 테스트 중에 발생했습니다.

FK 로 사용되는 컬럼값이 없는 상태에서 데이터를 넣으려다 발생한 에러입니다.

예를 들어 Person (id, name) 이라는 테이블과 House (id, address, person_id) 라는 테이블 관계가 있을 때, Person 데이터를 넣지 않고 House 데이터를 넣으려고 하면 person_id 값이 없어서 에러가 발생합니다.

Person person = new Person("Alice");
House house = new House("Seoul", person);

houseRepository.save(house);    // 에러 발생 (person 의 id 값을 모르는데 테이블에 넣으려고 해서)

해결 방법

연관 관계 매핑해줄 때 사용하는 @ManyToOne, @OneToOne, @OneToMany 어노테이션에 cascade 옵션을 설정해줍니다.

cascade 는 "영속성 전이" 라고 하는 개념인데 특정 엔티티를 영속화 할 때 연관된 엔티티도 함께 영속화 합니다.

저장할 때만 사용하려면 cascade = CascadeType.PERSIST 로 설정해주면 되며, 전체 적용인 CascadeType.ALL 로 설정해도 됩니다.

그럼 House 데이터를 저장하기 전에 Person 값부터 저장합니다.


Reference

Overview

쉘 스크립트 파일을 보면 파일 최상단에 #!/usr/bin/env bash 가 있는 걸 많이 봤을겁니다.

잘 모를때는 그냥 주석으로 실행 환경을 의미하는 건 줄 알았는데 사실은 굉장히 중요한 문장이었습니다.


1. SheBang (#!)

우선 #! 은 주석이 아니라 이 자체가 하나의 기호입니다.

어원은 위키피디아에 의하면 어원은 Hash(#) 또는 Sharp(#) 과 Bang(!) 의 합성어에서 유래한 것 같다고 합니다.

#! 은 2 Byte 의 매직 넘버 (Magic Number) 로 스크립트의 맨 앞에서 이 파일이 어떤 명령어 해석기의 명령어 집합인지를 시스템에 알려주는 역할을 합니다.

#! 바로 뒤에 나오는 것은 경로명으로, 명령어들을 해석할 프로그램의 위치를 나타냅니다.

가장 일반적으로 사용되는건 #!/bin/bash 이며 앞으로 나올 명령어들을 주석을 제외하고 순서대로 실행시킵니다.

만약 경로가 정확하지 않다면 bad interpreter 가 발생하고 다른 인터프리터를 지정하면 문법 오류로 실패합니다.


1.1. 문법

#!<interpreter> [optional-arg]

문법은 위와 같으며 #! 뒤에 공백 (Space) 이 하나 있어도 동작합니다.

<Interpreter> 에는 프로그램의 절대경로가 입력되어야 합니다.


1.2. 예시

#!/bin/sh
#!/bin/bash
#!/usr/bin/pwsh
#!/usr/bin/env python3

2. #!/usr/bin/env 란?

위 설명에서 <interpreter> 에는 프로그램의 절대 경로가 와야 한다고 했습니다.

하지만 절대경로는 시스템에 따라 달라질 수도 있습니다.

파이썬을 예로 들면 시스템에 따라 /bin/local/python 또는 /usr/bin/python 에 위치할 수도 있고 버전 또한 python2 와 python3 둘다 설치되어 있을 수 있습니다.

이럴 때 #!/usr/bin/env 로 설정하면 절대경로에 상관 없이 인터프리터의 위치를 찾아서 실행해줍니다.

그러니 여러 환경에서 실행되야할 스크립트라면 #!/usr/bin/env 를 사용하는 게 좋습니다.


3. Test

간단하게 테스트를 해봅시다.

터미널을 켜서 vi test 로 파일 하나를 작성합니다.

#! /usr/bin/env bash

echo "Hello This is Bash"

위 파일에 실행 권한을 추가하고 실행하면 정상적으로 동작합니다.

# 권한 추가
$ chmod +x test

# 실행
$ ./test
Hello This is Bash

이번엔 다시 파일을 열어 인터프리터를 파이썬으로 지정합니다.

#! /usr/bin/env python

echo "Hello This is Bash"

권한은 아까 주었으니 다시 파일만 실행시키면 에러가 발생합니다.

파이썬 문법에 맞지 않아 오류가 발생한 겁니다.

$ ./test
  File "./test", line 3
    echo "Hello This is Bash"
                            ^
SyntaxError: invalid syntax

다시 파일을 열어 파이썬 문법으로 고쳐줍시다.

#! /usr/bin/env python

print "Hello This is Python"

파일을 실행시키면 정상적으로 실행됩니다.

$ ./test
Hello This is Python

Conclusion

SheBang(#!) 문법은 스크립트 파일에서 어떤 프로그램으로 해당 파일을 실행시킬 지 결정합니다.

#!/usr/bin/env 를 사용하면 인터프리터의 절대 경로를 지정하지 않아도 알아서 경로를 찾아주기 때문에 여러 시스템 환경에서 사용할 때 유용합니다.

테스트를 보면서 알 수 있었던 한가지 특징은 확장자를 입력하지 않아도 #! 으로 인터프리터를 지정하면 정상적으로 실행된다는 사실입니다.


Reference

Overview

최근에 Mac OS 를 BigSur 로 업그레이드 하면서 데이터를 초기화 했습니다.

거의 2년 넘게 사용하던 설정들이 다 초기화 돼서 하나씩 설정했는데 다음에 또 세팅할 일이 생기면 볼 수 있게 기록해둡니다.


1. 환경설정

    1. 트랙패드 탭해서 클릭
    1. 트랙패드 세손가락으로 드래그](#12-트랙패드-세손가락으로-드래그)
    1. 마우스 가속도 끄기
    1. ₩ 를 ` 로 입력하게 바꾸기
    1. Mac 에서 한글 입력이 잘 안되는 현상
    1. 화면 Zoom in 기능

1.1. 트랙패드 탭해서 클릭

맥북은 기본적으로 꾹 눌러서 클릭하는데 위 설정을 키면 손가락 한번 탭한 것으로 클릭 가능합니다.

더블 클릭도 마찬가지로 두번 탭하면 됩니다.


1.2. 트랙패드 세손가락으로 드래그

환경설정 > 손쉬운 사용 > 포인터 제어기 > 트랙패드 옵션 에 들어가서 활성화 가능합니다.

아이콘, 이미지 등을 드래그 할 때 꾹 누르는 대신 세 손가락으로 쉽게 드래그 가능합니다.


1.3. 마우스 가속도 끄기

# 현재 감도 확인
defaults read .GlobalPreferences com.apple.mouse.scaling

# 새로운 감도 지정 (-1 로 설정하면 끄기)
defaults write .GlobalPreferences com.apple.mouse.scaling -1

기본적으로 마우스 가속도가 켜져 있는데 저는 불편해서 끄는 편입니다.

인텔 맥북에서만 가능하고 M1 맥북에서는 별도의 툴을 다운받아야 한다고 하네요.


1.4. ₩ 를 ` 로 입력하게 바꾸기

BigSur OS 로 업그레이드 하고 나니 한글 상태에서 1 왼쪽에 있는 키가 ` (백틱) 대신 로 입력되어 마크다운이나 코드블럭을 작성할 때 불편했습니다.

https://ani2life.com/wp/?p=1753 포스트를 참고하여 키 설정 변경 후 각 애플리케이션들을 새로 시작하면 각각 적용됩니다.

# KeyBindings 디렉토리 생성
$ mkdir ~/Library/KeyBindings

# DefaultkeyBinding.dict 생성 및 편집
$ vi ~/Library/KeyBindings/DefaultkeyBinding.dict

# 아래 내용 추가
{
    "₩" = ("insertText:", "`");
}

1.5. Mac 에서 한글 입력이 잘 안되는 현상

개인적인 이슈였을 수도 있는데, 맥북 에디터에서 한글을 입력하면 자음이나 모음 한두개가 입력되지 않고 씹히는 현상을 겪었습니다.

환경설정 > 키보드 > 입력 소스 로 이동해서 "삭제 방식" 을 "글자" 로 변경하면 해결됩니다.

변경 후에는 백스페이스로 글자를 지울 때 자음, 모음 단위로 안 지워지고 무조건 문자 단위로 지워지는데 크게 불편한 점은 못느끼고 있습니다.


1.6. 화면 Zoom in 기능

Control + 마우스 스크롤 로 화면을 확대할 수 있습니다.


2. 유용한 앱들

다음은 제가 맥북에서 사용하는 앱들입니다.

    1. iShot
    1. itsycal
    1. Rectangle
    1. AppCleaner
    1. Notion
    1. Spark
    1. Amphetamine
    1. Visual Studio Code

2.1. iShot

App Store 에서 다운 받을 수 있는 화면 캡쳐 프로그램입니다.

실행만 하면 option + A 조합으로 별다른 설정 없이 바로 사용할 수 있습니다.

전체화면, 특정 창, 드래그, 스크롤 캡쳐 등 다양한 기능을 제공하고 캡쳐한 사진을 바로 편집해서 복사, 저장할 수 있습니다.


2.2. itsycal

https://www.mowglii.com/itsycal/ 에서 다운로드 하거나 brew install --cask itsycal 명령어로 설치할 수 있습니다.

맥북은 달력 보기가 굉장히 불편해서 하나 설치해서 보면 좋습니다.

맥 캘린더랑 연동도 되는 것 같은데 달력 보는 용도 외에는 사용해본 적 없는거 같네요.


2.3. Rectangle

https://rectangleapp.com/ 에서 직접 다운받아 사용 가능합니다.

윈도우에서는 기본으로 제공되는 화면 분할이 맥에서는 없기 때문에 별도의 앱이 필요합니다.

control + option + @ 의 조합으로 사용할 수 있으며 생각한것보다 굉장히 유용합니다.

더블 모니터를 사용하는 경우에는 서로 이동도 돼서 마우스 사용 빈도가 낮아졌습니다.


2.5. AppCleaner

앱 지울 때 사용하기 위해 다운 받습니다.


2.6. Notion

https://www.notion.so/desktop 에서 다운가능합니다.

업무용, 개인용으로도 사용하기 굉장히 좋은 메모 앱입니다.

Mac OS, Window, Mobile 전부 호환 돼서 편리합니다.


2.7. Spark

맥북 기본 메일앱이 마음에 안들어서 App Store 에서 다운 받았습니다.

기본 앱은 메일을 받아도 노티가 오래 걸렸는데 스파크는 속도가 빨라서 유용하게 사용하고 있습니다.


2.8. Amphetamine

App Store 에서 다운 가능한 잠자기 방지 앱입니다.

원래는 환경 설정에서 화면 보호기 없는걸로 세팅했었는데 이 앱을 사용하면 좀더 여러 가지 설정이 가능합니다.

저는 그냥 항상 깨움 상태로 사용합니다.


2.9. Visual Studio Code

유용한 에디터이며 공식 홈페이지에서 다운 가능합니다.

개발용으로도 많이 쓰지만 저는 JetBrain 제품을 사용하기 때문에 마크다운 에디터로만 사용하고 있습니다.

설치한 확장팩

  • Markdown All in One : Markdown 작성 도와주는 확장팩
  • Markdown Preview Enhanced : Markdown Github 스타일로 미리보기 가능
  • Material Icon Theme : 그냥 아이콘이 이뻐보여서..
  • One Dark Pro : 그냥 테마
  • Paste Image (by mushan) : 클립보드 이미지를 붙여넣을 때 자동으로 이미지 파일이 생성되게 도와줌
    • Paste Image: Path 설정을 ${currentFileDir}/images 으로 변경
    • Paste Image: Default Name 설정을 Y_MM_DD_HH_mm_ss 으로 변경
    • Paste Image: Name Prefix 설정을 screen_ 으로 추가

1. Hack Font 설치

개인적으로 가장 선호하는 폰트입니다.

https://sourcefoundry.org/hack/#download 에서 Mac OS Zip 을 다운받고 풀어서 ttl 파일들을 실행시면 서체를 다운받을 수 있습니다.


2. Iterm2 설치

Iterm2 은 기본 터미널 애플리케이션보다 다양한 기능과 테마가 탑재된 보조 터미널 애플리케이션입니다.

공식 홈페이지 에서 설치하거나 Homebrew 로 설치 가능합니다.

$ brew install --cask iterm2

설치 후에는 Preference > Profiles > Text 로 이동해서 폰트를 변경할 수 있습니다.



2.1. Iterm2 테마 변경 (Dracula)

$ git clone https://github.com/dracula/iterm.git

위 명령어로 Dracula 테마를 아무 위치에나 다운 받습니다.

다운 받은 폴더에 들어가 Dracula.itermcolors 파일 더블클릭 하면 자동으로 테마가 추가됩니다.

Iterm2 > Perferences > Profiles > Colors > Color Presets... 로 가서 Dracula 를 선택합니다.



2.2. 한글 깨짐 수정



3. Oh My ZSH 설치

Oh My Zsh 는 기본 쉘보다 더 다양한 기능을 제공하는 Z Shell 의 플러그인입니다.

Catalina OS 부터 zsh 가 기본 터미널이 되었기 때문에 따로 설치할 필요는 없고 플러그인만 설치하면 됩니다.

https://github.com/ohmyzsh/ohmyzsh 를 참고해서 설치 가능합니다.

# ohmyzsh curl 설치
$ sh -c "$(curl -fsSL https://raw.githubusercontent.com/ohmyzsh/ohmyzsh/master/tools/install.sh)"



3.1. zsh 테마 적용

agnoster 가 국룰인것 같은데 저는 powerlevel10k 테마를 적용했습니다.

# zsh 테마에 powerlevel10k 추가
$ git clone https://github.com/romkatv/powerlevel10k.git ~/.oh-my-zsh/themes/powerlevel10k

# .zshrc 파일 수정
$ vi ~/.zshrc

ZSH_THEME="powerlevel10k/powerlevel10k"

# 변경한 .zshrc 적용하면 여러 가지 설정 Step 이 나오고 다 선택하면 최종 적용됨
$ source ~/.zshrc

3.2. Syntax Highlighting 플러그인 적용

존재하지 않은 명령어를 입력하면 빨간색으로 알려주는 편리한 플러그인입니다.

존재하는 명령어는 녹색으로 표시됩니다.

# 설치
$ brew install zsh-syntax-highlighting

# 적용 (.zshrc 맨 밑에 추가해야 터미널을 껐다 켜도 적용됨)
# 환경에 따라 zsh 파일 위치가 다를 수 있으므로 설치 후 터미널 가이드 참고
$ source /opt/homebrew/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh

3.3. 자동완성제안 (Auto Suggestions) 플러그인 적용

과거에 입력한 명령어를 자동으로 만들어주는 기능입니다.

이미 입력해본 적이 있는 명령어라면 조금만 입력해도 위 사진처럼 가장 최근에 입력한 명령어를 보여줍니다.

이 상태에서 방향키 오른쪽 버튼을 누르면 전체 명령어를 완성해줍니다.

# 설치
$ brew install zsh-autosuggestions

# 적용 (.zshrc 맨 밑에 추가해야 터미널을 껐다 켜도 적용됨)
# 환경에 따라 zsh 파일 위치가 다를 수 있으므로 설치 후 터미널 가이드 참고
source /opt/homebrew/share/zsh-autosuggestions/zsh-autosuggestions.zsh

3.4. autojump 플러그인 추가

# 설치
brew install autojump

# .zshrc 수정
plugins=(git autojump)

과거에 방문했던 위치를 적당히 힌트만 주면 알아서 찾아줍니다.

예를 들어 위 사진 처럼 /Downloads 에서 j study 를 입력하면 study 라는 이름을 가진 디렉토리 중 가장 많이 방문한 곳으로 이동합니다.

j -s 명령어로 방문한 디렉토리 기록도 확인 가능합니다.

+ Recent posts