[JavaScript μ˜€λ””μ˜€ μ΄νŽ™ν„° λ§Œλ“€κΈ°] μ†Œλ¦¬μ˜ 흐름을 νŒŒμ•…ν•˜μž

    [JavaScript μ˜€λ””μ˜€ μ΄νŽ™ν„° λ§Œλ“€κΈ°] μ†Œλ¦¬μ˜ 흐름을 νŒŒμ•…ν•˜μž


    이번 ν¬μŠ€νŒ…μ—μ„œλŠ” μ»΄ν“¨ν„°λŠ” μ–΄λ–»κ²Œ μ†Œλ¦¬λ₯Ό λ“€μ„κΉŒ? ν¬μŠ€νŒ…μ—μ„œ μ§„ν–‰ν–ˆλ˜ μ˜€λ””μ˜€ νŒŒν˜• 그리기에 μ΄μ–΄μ„œ μ˜€λ””μ˜€μ— μ—¬λŸ¬κ°€μ§€ 효과λ₯Ό 쀄 수 μžˆλŠ” μ΄νŽ™ν„°λ₯Ό λ§Œλ“œλŠ” 과정을 μ„€λͺ…ν•˜λ €κ³  ν•œλ‹€. HTML5의 Audio APIλŠ” μ˜€λ””μ˜€μ— 효과λ₯Ό 쀄 수 μžˆλŠ” μ—¬λŸ¬κ°€μ§€ λ…Έλ“œλ₯Ό μ œκ³΅ν•˜λŠ”λ°, λŒ€λΆ€λΆ„μ˜ μ΄νŽ™ν„°λŠ” 이 λ…Έλ“œλ“€λ§Œ μ‚¬μš©ν•΄λ„ κ΅¬ν˜„ν•  수 μžˆμ„ μ •λ„λ‘œ μ™„μ„±λ„μžˆλŠ” APIλ₯Ό μ œκ³΅ν•œλ‹€.

    λ˜ν•œ 이 ν¬μŠ€νŒ…μ€ 총 λ‘νŽΈμ— λ‚˜λˆ μ„œ μž‘μ„±λ  μ˜ˆμ •μ΄λ©°, 이번 ν¬μŠ€νŒ…μ—μ„œλŠ” HTML5 Audio API의 κ°œμš”μ™€ μ˜€λ””μ˜€μ˜ μŒλŸ‰μ„ μ‘°μ ˆν•  수 μžˆλŠ” GainNodeλ₯Ό μ‚¬μš©ν•˜λŠ” 방법에 λŒ€ν•΄μ„œ, λ‹€μŒ ν¬μŠ€νŒ…μ—μ„œλŠ” μ’€ 더 λ³΅μž‘ν•œ μ˜€λ””μ˜€ μ΄νŽ™ν„°λ“€μ— λŒ€ν•œ μ„€λͺ…κ³Ό μ œμž‘ 과정을 μ„€λͺ…ν•  μ˜ˆμ •μ΄λ‹€.

    μ§€λ‚œ ν¬μŠ€νŒ…μ—μ„œ 이미 μ˜€λ””μ˜€μ— κ΄€ν•œ 기본적인 이둠을 μ„€λͺ…ν–ˆμœΌλ‹ˆ μ΄λ²ˆμ—λŠ” 기본적인 이둠이 μ•„λ‹ˆλΌ μ‹€μ œλ‘œ λ…ΉμŒμ‹€μ—μ„œ μ˜€λ””μ˜€λ₯Ό μ–΄λ–€ λ°©μ‹μœΌλ‘œ μ»¨νŠΈλ‘€ν•˜κ³  효과λ₯Ό μ£ΌλŠ” 지에 λŒ€ν•œ 방법에 λŒ€ν•΄ μ΄ˆμ μ„ λ§žμΆ”κ³  μ„€λͺ…을 μ§„ν–‰ν•˜λ„λ‘ ν•˜κ² λ‹€.

    μ˜€λ””μ˜€ μ‹ ν˜ΈλŠ” 흐λ₯΄λŠ” 것이닀

    일반적인 λ…ΉμŒμ‹€μ—μ„œ μš°λ¦¬λŠ” 마이크λ₯Ό ν†΅ν•΄μ„œ μ˜€λ””μ˜€λ₯Ό λ…ΉμŒν•˜κ±°λ‚˜ ν˜Ήμ€ 이미 λ…ΉμŒλœ μ˜€λ””μ˜€λ₯Ό Logic Proλ‚˜ Cubase와 같은 DAW(Digital Audio Workstation)으둜 λΆˆλŸ¬μ™€μ„œ μ‚¬μš©ν•˜κ²Œ λœλ‹€. μ΄λ•Œ 처음으둜 λ°›κ²Œλ˜λŠ” 이 μ˜€λ””μ˜€λ₯Ό μ†ŒμŠ€(Source)라고 ν•œλ‹€.

    이 μ†ŒμŠ€λŠ” μ•°ν”„, μ»΄ν”„λ ˆμ„œ, 이퀄라이저 λ“± μ˜€λ””μ˜€μ— νŠΉλ³„ν•œ λŠλ‚Œμ„ 쀄 수 μžˆλŠ” μ—¬λŸ¬κ°€μ§€ μ΄νŽ™ν„°λ“€μ„ μ§€λ‚˜μ„œ μ΅œμ’…μ μœΌλ‘œ μŠ€ν”Όμ»€λ‚˜ ν—€λ“œν°μ„ ν†΅ν•΄μ„œ 좜λ ₯되게 λœλ‹€. 이 흐름을 μ•Œκ³ λ‚˜λ©΄ HTML5의 Audio APIκ°€ μ œκ³΅ν•˜λŠ” λ…Έλ“œ(Node)의 κ°œλ…μ„ μ‰½κ²Œ 이해할 수 μžˆλ‹€. 일단 이해λ₯Ό 돕기 μœ„ν•΄ ν•„μžκ°€ μ˜ˆμ „μ— μ‚¬μš΄λ“œ μ—”μ§€λ‹ˆμ–΄λ‘œ 일할 λ•Œ μ‚¬μš©ν–ˆλ˜ μ‹œμŠ€ν…œμ„ 예둜 λ“€κ² λ‹€.

    mixer 필자가 예전에 사용했던 장비들

    μ‚¬μ§„μ˜ 쀑앙에 μžˆλŠ” μ»€λ‹€λž€ μž₯λΉ„λŠ” μ•„λ§ˆ μ—¬λŸ¬λΆ„λ„ TVμ—μ„œ λͺ‡λ²ˆ λ³΄μ•˜λ˜ μž₯비일 것이닀. 이 μž₯λΉ„λŠ” μ—¬λŸ¬ 개의 μ±„λ„λ‘œ λ‚˜λˆ μ§„ μ˜€λ””μ˜€ μ†ŒμŠ€μ˜ λ³Όλ₯¨μ΄λ‚˜ νŒ¨λ‹, μ΄ν€„λΌμ΄μ§•κΉŒμ§€ ν•  수 μžˆλŠ” μΌμ’…μ˜ 컨트둀 νƒ€μ›Œ 역할을 ν•˜λŠ” λ―Ήμ‹± μ½˜μ†”μ΄λ‹€.

    그리고 λ―Ήμ‹± μ½˜μ†”μ˜ 였λ₯Έμͺ½μ— μžˆλŠ” 것듀이 λ°”λ‘œ μ˜€λ””μ˜€μ— 효과λ₯Ό 쀄 수 μžˆλŠ” μ΄νŽ™ν„°λ“€μ΄λ‹€. 보톡은 λ―Ήμ‹± μ½˜μ†” μ–‘μͺ½μ— 가득 μ±„μ›Œλ†“κ³  μ“°λŠ”λ° μ € 사진은 아직 λ…ΉμŒμ‹€ 셋업이 덜 끝났을 λ•ŒλΌμ„œ λͺ‡κ°€μ§€ μž₯λΉ„λ§Œ λ“€μ–΄κ°€ μžˆλ‹€. 그리고 μ‚¬μ§„μ—λŠ” λ‚˜μ˜€μ§€ μ•Šμ•˜μ§€λ§Œ λ”°λ‘œ μ½˜μ†” λž™(Console Rack)μ΄λΌλŠ” μ„ λ°˜μ„ 두고 거기에도 μ΄νŽ™ν„°λ“€μ΄ 가득 μ±„μ›Œμ Έ μžˆλ‹€.

    그리고 μ΄νŽ™ν„°λ“€μ˜ μœ„μͺ½μ„ 보면 뢉은색 선이 κ½‚ν˜€μžˆλŠ” 것을 λ³Ό 수 μžˆλŠ”λ°, μ € μž₯λΉ„κ°€ μ˜€λ””μ˜€μ˜ 흐름을 μ»¨νŠΈλ‘€ν•  수 μžˆλŠ” 패치 ν…Œμ΄λΈ”(Patch Table)이라고 ν•˜λŠ” μž₯비이닀.

    보톡 μ‚¬μš΄λ“œ μ—”μ§€λ‹ˆμ–΄λ“€μ€ 같은 역할을 ν•˜λŠ” μ΄νŽ™ν„°λΌκ³  ν•˜λ”λΌλ„ μ—¬λŸ¬ μ’…λ₯˜μ˜ μž₯λΉ„λ₯Ό μ‚¬μš©ν•˜κ²Œ λ˜λŠ”λ°, μ΄λŠ” 같은 역할을 ν•˜λŠ” μ΄νŽ™ν„°λΌκ³  ν•˜λ”λΌλ„ μž₯λΉ„λ§ˆλ‹€ μ‘°κΈˆμ”© μ†Œλ¦¬κ°€ λ‹€λ₯Ό 수 있기 λ•Œλ¬Έμ΄λ‹€. 즉, 같은 λ¦¬λ²„λΈŒλ₯Ό μ‚¬μš©ν•œλ‹€κ³  해도 μ΅œμ’…μ μœΌλ‘œ λ§Œλ“€κ³ μžν•˜λŠ” μ†Œλ¦¬κ°€ μ–΄λ–€ λŠλ‚ŒμΈμ§€μ— 따라 A λ¦¬λ²„λΈŒλ₯Ό μ‚¬μš©ν•  μˆ˜λ„ 있고 B λ¦¬λ²„λΈŒλ₯Ό μ‚¬μš©ν•  μˆ˜λ„ μžˆλ‹€λŠ” 것이닀. κ·Έλž˜μ„œ 이런 μ†Œλ¦¬μ˜ μ§ˆμ„ λ§Œλ“œλŠ” κ³ μœ ν•œ μ•Œκ³ λ¦¬μ¦˜μ€ μ΄νŽ™ν„° 제쑰 νšŒμ‚¬λ“€μ˜ κΈ°μ—… 비밀이닀.

    ν•˜μ§€λ§Œ λ‹€λ₯Έ μ΄νŽ™ν„°λ₯Ό μ‚¬μš©ν•˜κ³  싢을 λ•Œλ§ˆλ‹€ μž₯비에 κ½‚ν˜€μžˆλŠ” 케이블을 일일히 ν•˜λ‚˜ν•˜λ‚˜ λΉΌμ„œ λ‹€μ‹œ λ‹€λ₯Έ μž₯비에 μ—°κ²°ν•˜λŠ” 것은 λΉ„νš¨μœ¨μ μ΄κΈ°λ„ ν•˜κ³  케이블을 계속 뺐닀가 κΌˆλ‹€κ°€ ν•˜λ©΄ μž₯비에 손상이 κ°ˆμˆ˜λ„ 있기 λ•Œλ¬Έμ— λͺ¨λ“  μž₯λΉ„μ˜ 라인을 μ € 패치 ν…Œμ΄λΈ”μ— 연결해놓고 μ‚¬μš©ν•˜λŠ” 것이닀. κ²Œλ‹€κ°€ 케이블은 λŒ€λΆ€λΆ„ μž₯λΉ„ λ’€μͺ½μ— μœ„μΉ˜ν•˜κΈ° λ•Œλ¬Έμ— μ € λ―Ήμ‹± μ½˜μ†”μ„ μ•žμœΌλ‘œ 살짝 λ°€κ³  λ΄μ•Όν•˜λŠ”λ°, λ”± 봐도 μ € 큰 μž₯λΉ„λ₯Ό 계속 λ°€μ—ˆλ‹€ λ‹Ήκ²Όλ‹€ ν•˜κΈ°μ—λŠ” λ¬΄κ±°μ›Œ 보이지 μ•ŠλŠ”κ°€? ν—ˆλ¦¬ λ‚˜κ°„λ‹€.

    patch table chart 패치 테이블은 대략 이런 느낌으로 정리된다

    μ‚¬μš΄λ“œ μ—”μ§€λ‹ˆμ–΄λŠ” μ΄λ ‡κ²Œ λ³΅μž‘ν•œ μ—¬λŸ¬ 개의 μž₯λΉ„ 사이λ₯Ό ν˜λŸ¬λ‹€λ‹ˆλŠ” μ˜€λ””μ˜€ μ‹ ν˜Έμ˜ 흐름을 패치 ν…Œμ΄λΈ”μ„ ν†΅ν•΄μ„œ ν•œλ²ˆμ— νŒŒμ•…ν•˜κ³  컨트둀 ν•  수 μžˆλ‹€. μ†Œλ¦¬λ₯Ό μ»¨νŠΈλ‘€ν•˜λŠ” μ‚¬λžŒμ—κ²Œ μ˜€λ””μ˜€ μ‹ ν˜Έμ˜ νλ¦„μ΄λΌλŠ” κ°œλ…μ€ ꡉμž₯히 μ€‘μš”ν•˜λ‹€. ν•„μžκ°€ 방금 예둜 λ“  ν•˜λ“œμ›¨μ–΄ μž₯λΉ„ 뿐만 μ•„λ‹ˆλΌ μ†Œν”„νŠΈμ›¨μ–΄λ‘œ κ΅¬ν˜„λœ μ΄νŽ™ν„°λ₯Ό μ‚¬μš©ν•˜λ €ν• λ•Œλ„ 결ꡭ은 이 흐름을 ν”„λ‘œκ·Έλž¨ λ‚΄λΆ€μ—μ„œ κ·ΈλŒ€λ‘œ κ΅¬ν˜„ν•΄μ€˜μ•Όν•˜κΈ° λ•Œλ¬Έμ΄λ‹€.

    protools

    μœ„ 사진은 μ „ 세계 λ…ΉμŒμ‹€ 쀑 90%κ°€ μ‚¬μš©ν•˜κ³  μžˆλŠ” ProtoolsλΌλŠ” DAW의 λ―Ήμ„œ 창이닀. 사진에 κ°•μ‘°λœ 뢀뢄에 Vocal Bus라고 μ ν˜€μžˆλŠ” 곳을 보면 맨 였λ₯Έμͺ½ 채널은 μœ„μͺ½μ— μœ„μΉ˜ν•˜κ³  있고 λ‚˜λ¨Έμ§€ 채널은 μ•„λž˜μͺ½μ— μœ„μΉ˜ν•˜κ³  μžˆλ‹€. I/O λ©”λ‰΄μ—μ„œ μœ„μͺ½μ€ In을 μ˜λ―Έν•˜κ³  μ•„λž˜μͺ½μ€ Out을 μ˜λ―Έν•˜κΈ° λ•Œλ¬Έμ— 이 κ·Έλ¦Όμ—μ„œ μ˜€λ””μ˜€μ˜ 흐름은 λŒ€λž΅ λ‹€μŒκ³Ό 같이 λ‚˜νƒ€λ‚  수 μžˆλ‹€.

    auxes

    μ΄λ•Œ μ € λ„€λͺ¨ ν•˜λ‚˜ν•˜λ‚˜κ°€ HTML5의 Audio APIμ—μ„œ μ œκ³΅ν•΄μ£ΌλŠ” λ…Έλ“œμ™€ μ •ν™•νžˆ 같은 κ°œλ…μ΄λ‹€. 즉, μžλ°”μŠ€ν¬λ¦½νŠΈλ‘œ μ € 흐름을 μ™„λ²½νžˆ λ™μΌν•˜κ²Œ κ΅¬ν˜„ν•  수 μžˆλ‹€λŠ” λœ»μ΄λ‹€.

    이해λ₯Ό 돕기 μœ„ν•΄ μ € λ…Έλ“œλ“€μ˜ 역할에 λŒ€ν•΄μ„œ 쑰금 더 λΆ€κ°€μ„€λͺ…을 ν•˜μžλ©΄, 일단 Lead VoxλŠ” 말 κ·ΈλŒ€λ‘œ 보컬의 λ…Έλž˜ μ†ŒμŠ€λ₯Ό 가진 λ…Έλ“œμ΄κ³  LeadVxDbl은 λ…Έλž˜λ₯Ό ν’λΆ€ν•˜κ²Œ λ“€λ¦¬κ²Œ ν•˜κΈ° μœ„ν•΄ 같은 λ©œλ‘œλ””λ₯Ό ν•œλ²ˆ 더 λ…ΉμŒν•œ 것, 즉 더블링 μž‘μ—…μ„ ν•œ λ…Έλ“œμ΄λ‹€. 그리고 Vox Fill은 ν™”μŒμ„ μŒ“μ€ μ½”λŸ¬μŠ€λ₯Ό 담은 λ…Έλ“œμ΄λ‹€.

    그리고 보컬이 λ…Έλž˜ν•œ 이 μ˜€λ””μ˜€ μ†ŒμŠ€λ₯Ό λͺ¨λ‘ Vocal BusλΌλŠ” λ…Έλ“œλ‘œ λͺ¨μœΌκ³  μžˆλ‹€. μ΄λ ‡κ²Œ ν•˜λŠ” μ΄μœ λŠ” μ—¬λŸ¬ 개의 μ˜€λ””μ˜€ μ†ŒμŠ€μ— μ΄νŽ™ν„°λ₯Ό 각각 μ‚¬μš©ν•˜λ©΄ λ…Έλ“œλ§ˆλ‹€ μ‘°κΈˆμ”© μ†Œλ¦¬μ˜ λŠλ‚Œμ΄ λ‹¬λΌμ§ˆ 수 있기 λ•Œλ¬Έμ— Vocal BusλΌλŠ” ν•˜λ‚˜μ˜ λ…Έλ“œλ‘œ μ˜€λ””μ˜€ μ‹ ν˜Έλ₯Ό λͺ¨μ€ λ‹€μŒ ν•΄λ‹Ή λ…Έλ“œμ—λ§Œ μ΄νŽ™ν„°λ₯Ό κ±Έμ–΄μ£ΌλŠ” 것이닀. μ΄λ ‡κ²Œ ν•˜λ©΄ λͺ¨λ“  λ…Έλ“œμ— μ΄νŽ™ν„°λ₯Ό μ‚¬μš©ν•˜μ§€μ•Šκ³  ν•˜λ‚˜μ˜ λ…Έλ“œμ—λ§Œ μ΄νŽ™ν„°λ₯Ό μ‚¬μš©ν•΄λ„ 되기 λ•Œλ¬Έμ— λ©”λͺ¨λ¦¬ λΉ„μš©λ„ μ•„λ‚„ 수 있고, λ³΄μ»¬μ΄λΌλŠ” ν•˜λ‚˜μ˜ μ†ŒμŠ€μ— λ™μΌν•œ λŠλ‚Œμ„ λΆ€μ—¬ν•  수 μžˆλ‹€.

    그리고 μ΅œμ’…μ μœΌλ‘œ μ‹ ν˜Έκ°€ λ“€μ–΄κ°€λŠ” Sub Master λ…Έλ“œλŠ” μ•„λ§ˆ μ΅œμ’… μ•„μ›ƒν’‹μœΌλ‘œ μ†Œλ¦¬κ°€ λ‚˜κ°€κΈ° 전에 ν•œλ²ˆ 더 μ΄νŽ™ν„° 처리λ₯Ό ν•˜κ³  μ‹Άμ–΄μ„œ μƒμ„±ν•œ 것일 ν…Œκ³ , Sub MasterκΉŒμ§€ λ„λ‹¬ν•œ μ˜€λ””μ˜€λŠ” 아웃풋, 즉 μŠ€ν”Όμ»€λ₯Ό 톡해 좜λ ₯λ˜μ–΄ 우리의 κ·€λ‘œ λ“€μ–΄μ˜€κ²Œ λ˜λŠ” 것이닀. κ²°κ΅­ in -> out -> in -> out의 κ³„μ†λœ 반볡이라고 보면 λœλ‹€. κ·Έλž˜μ„œ ν•„μžκ°€ μ˜€λ””μ˜€μ˜ 흐름이라고 ν‘œν˜„ν•˜λŠ” 것이닀.

    이제 μ˜€λ””μ˜€ μ†ŒμŠ€μ˜ νλ¦„μ΄λΌλŠ” 것이 λŒ€λž΅ 이해가 λ˜μ—ˆμœΌλ©΄ ν•œλ²ˆ 직접 HTML5의 Audio APIλ₯Ό μ‚¬μš©ν•΄μ„œ 이 흐름을 κ΅¬ν˜„ν•΄λ³΄λ„λ‘ ν•˜μž.

    μ˜€λ””μ˜€μ˜ μŒλŸ‰μ„ μ‘°μ ˆν•˜κΈ°

    μœ„μ—μ„œ μ΄μ•ΌκΈ°ν–ˆλ“―μ΄ 이번 ν¬μŠ€νŒ…μ—μ„œλŠ” 본격적으둜 μ΄νŽ™ν„°λ₯Ό κ΅¬ν˜„ν•΄λ³΄κΈ°μ— μ•žμ„œ μ˜€λ””μ˜€μ˜ 흐름을 직접 κ΅¬ν˜„ν•΄λ³΄κ³  μ²΄ν—˜ν•΄λ³΄λŠ” 것에 μ΄ˆμ μ„ 맞좜 것이닀. κ·Έλž˜μ„œ μ΄νŽ™ν„°λΌκΈ°μ—λŠ” 쑰금 μ• λ§€ν•œ λ‹¨μˆœν•œ ꡬ쑰의 흐름을 λ§Œλ“€μ–΄λ³΄λ €κ³  ν•œλ‹€. λ°”λ‘œ μ˜€λ””μ˜€μ˜ μŒλŸ‰μ„ μ‘°μ ˆν•˜λŠ” 흐름이닀. HTML5 Audio API의 GainNodeλ₯Ό μ‚¬μš©ν•˜λ©΄ μ˜€λ””μ˜€ μ†ŒμŠ€μ˜ μŒλŸ‰μ„ μ†μ‰½κ²Œ μ‘°μ ˆν•  수 μžˆλ‹€.

    Gainμ΄λž€ λ¬΄μ—‡μΈκ°€μš”?

    게인(Gain)μ΄λž€ μ‰½κ²Œ λ§ν•˜λ©΄ μž…λ ₯ λ³Όλ₯¨μ„ μ˜λ―Έν•œλ‹€. κ²ŒμΈμ„ μ‚¬μš©ν•˜μ—¬ λ§ˆμ΄ν¬μ—μ„œ μ˜€λ””μ˜€ λ―Ήμ„œλ‚˜ λ…ΉμŒκΈ°λ‘œ μ˜€λ””μ˜€ μ‹ ν˜Έλ₯Ό 보낼 λ•Œ κ·Έ μ‹ ν˜ΈλŸ‰μ„ μ»¨νŠΈλ‘€ν•˜λŠ” 것이닀. 처음 μ˜€λ””μ˜€μ— μž…λ¬Έν•˜μ‹œλŠ” 뢄듀이 게인(Gain)κ³Ό λ³Όλ₯¨(Volume)의 차이에 λŒ€ν•΄ ν—·κ°ˆλ €ν•˜μ‹œλŠ”λ°, μ‰½κ²Œ λ§ν•˜λ©΄ κ²ŒμΈμ€ β€œμž…λ ₯ μ‹ ν˜Έλ₯Ό μ‘°μ ˆν•˜λŠ” 것”이고 λ³Όλ₯¨μ€ β€œμΆœλ ₯ μ‹ ν˜Έλ₯Ό μ‘°μ ˆν•˜λŠ” 것”이닀.

    λ§Œμ•½ 100정도 μ„ΈκΈ°μ˜ μ‹ ν˜Έλ₯Ό μ²˜λ¦¬ν•  수 μžˆλŠ” λ…ΉμŒκΈ°κ°€ μžˆλ‹€κ³  μƒκ°ν•΄λ³΄μž. μ΄λ•Œ μš°λ¦¬κ°€ λ§ˆμ΄ν¬μ— λŒ€κ³  80 μ •λ„μ˜ μ„ΈκΈ°λ‘œ μ†Œλ¦¬λ₯Ό 왁! 지λ₯΄λ©΄ 이 λ…ΉμŒκΈ°λŠ” 무리없이 이 μ‹ ν˜Έλ₯Ό 받아듀일 수 μžˆμ§€λ§Œ, 150의 μ„ΈκΈ°λ‘œ μ†Œλ¦¬λ₯Ό 지λ₯΄κ²Œ 되면 이 λ…ΉμŒκΈ°λŠ” 50만큼의 μ†Œλ¦¬λ₯Ό 받아듀이지 λͺ»ν•˜κ³  κ·ΈλŒ€λ‘œ μœ μ‹€μ‹œν‚¨λ‹€.

    clipping 회색으로 표시된 부분이 잘려나간 신호이다.

    이 ν˜„μƒμ€ μ—¬λŸ¬λΆ„λ„ μ‚΄λ©΄μ„œ λͺ‡λ²ˆ κ²½ν—˜ν•œ ν˜„μƒμΌν…λ°, μŠ€ν”Όμ»€λ‘œ μ†Œλ¦¬λ₯Ό μ—„μ²­ 크게 ν‹€λ©΄ μ§€μ§€μ§κ±°λ¦¬λŠ” 작음이 λ°œμƒν•˜λŠ” 것을 λ“€μ–΄λ³Έ 적이 μžˆμ„ 것이닀. μ΄λ ‡κ²Œ μž₯λΉ„κ°€ μ²˜λ¦¬ν•  수 μžˆλŠ” μ‹ ν˜Έμ˜ μ„ΈκΈ°λ₯Ό λ„˜μ–΄κ°€λŠ” ν˜„μƒμ„ 클리핑(Clipping)이라고 ν•œλ‹€. 말 κ·Έλž˜λ„ μ‹ ν˜Έκ°€ μž˜λ €λ‚˜κ°€λŠ” 것이닀.

    μ΄λ ‡κ²Œ μž˜λ €λ‚˜κ°„ μ‹ ν˜ΈλŠ” μœ„ κ·Έλ¦Όμ—μ„œ λ³Ό 수 μžˆλ“―μ΄ 머리가 λ„€λͺ¨ λ°˜λ“―ν•œ μ‚¬κ°νŒŒμ˜ ν˜•νƒœλ₯Ό κ°€μ§€κ²Œ λ˜λŠ”λ°, 이 μ‚¬κ°νŒŒλŠ” μš°λ¦¬κ°€ EDM λ“±μ—μ„œ λ©œλ‘œλ””λ₯Ό ν‘œν˜„ν•  λ•Œ 많이 듀을 수 μžˆλŠ” 신디사이저 λ¦¬λ“œ(Lead) κ³„μ—΄μ˜ μ­ˆμ™€μ•™~ν•˜λŠ” κΈˆμ†μ„± μ†Œλ¦¬λ₯Ό λ‚Έλ‹€. λ§λ‘œλŠ” 잘 이해가 μ•ˆλ ν…Œλ‹ˆ ν•œλ²ˆ μŒμ•…μœΌλ‘œ λ“€μ–΄λ³΄λ©΄μ„œ μž μ‹œ 쉬어가도둝 ν•˜μž. μ•„λ§ˆ 클럽 μ’€ 닀녀보신 뢄듀은 μ•„! 이 μ†Œλ¦¬ν•  것이닀.

    ν•΄λ‹Ή 곑의 μΈνŠΈλ‘œκ°€ λλ‚˜λŠ” 35μ΄ˆλΆ€ν„° 메인 λ©œλ‘œλ””λ₯Ό λ§‘λŠ” μ•…κΈ°κ°€ μ‚¬κ°νŒŒλ₯Ό μ‚¬μš©ν•œ λ¦¬λ“œμ΄λ‹€.

    μ•„λ¬΄λž˜λ„ λ¦¬λ“œλŠ” μ•…κΈ°λ‘œμ¨ νŒŒν˜•μ΄ μ–΄λŠ 정도 μ •μ œλœ μƒνƒœμ΄κΈ° λ•Œλ¬Έμ— 클리핑이 λ°œμƒν–ˆμ„ λ•Œ λ‚˜λŠ” μ†Œλ¦¬λŠ” 이것보닀 더 κ±°μΉ κ³  λ‚ μΉ΄λ‘­λ‹€. 참고둜 μ΄λ ‡κ²Œ νŒŒν˜•μ— 따라 μ†Œλ¦¬κ°€ λ‹¬λΌμ§„λ‹€λŠ” κ°œλ…μ€ μ™œκ³‘κ³„(Distortion) μ΄νŽ™ν„°λ₯Ό λ§Œλ“€λ•Œλ„ μ‚¬μš©ν•˜λŠ” κ°œλ…μ΄κΈ° λ•Œλ¬Έμ— 기얡해두면 μ’‹λ‹€.

    μ–΄μ¨Œλ“  이런 클리핑 문제 λ•Œλ¬Έμ— μ‚¬μš΄λ“œ μ—”μ§€λ‹ˆμ–΄λ“€μ€ μ˜€λ””μ˜€ μ†ŒμŠ€μ™€ λ‹€μŒ μž₯λΉ„ 사이에 κ²ŒμΈμ„ μ‘°μ ˆν•  수 μžˆλŠ” μž₯치λ₯Ό 두고, μž₯λΉ„κ°€ 받아듀일 수 μžˆλŠ” μ‹ ν˜Έμ˜ 세기에 λ§žμΆ°μ„œ μ•Œλ§žκ²Œ κ²ŒμΈμ„ μ‘°μ ˆν•˜μ—¬ μ†ŒμŠ€ μ˜€λ””μ˜€μ˜ μ‹ ν˜Έκ°€ 컀지더라도 λͺ¨λ“  μ‹ ν˜Έλ₯Ό λ‹€ 담을 수 μžˆλ„λ‘ ν•œλ‹€.

    λ°˜λŒ€λ‘œ λ³Όλ₯¨μ€ μ†Œλ¦¬λ₯Ό 내보낼 λ•Œ μ–Όλ§ˆλ‚˜ μ¦ν­μ‹œν‚¬ 것이냐λ₯Ό μ˜λ―Έν•œλ‹€. λ§Žμ€ 뢄듀이 게인과 λ³Όλ₯¨μ„ ν—·κ°ˆλ €ν•˜λŠ” μ΄μœ κ°€ λ‘˜ λ‹€ μ†Œλ¦¬λ₯Ό μ¦ν­μ‹œν‚€κ±°λ‚˜ κ°μ†Œμ‹œν‚€λŠ” 역할을 ν•˜κΈ° λ•Œλ¬ΈμΈλ°, λ³Όλ₯¨μ€ 이미 μž…λ ₯된 μ‹ ν˜Έλ₯Ό 좜λ ₯ν•  λ•Œ κ±΄λ“œλ¦¬λŠ” 것이기 λ•Œλ¬Έμ— 클리핑이 λ°œμƒν•˜λ”λΌλ„ λ³Όλ₯¨μ„ 쀄이면 μ‹ ν˜Έκ°€ λŒμ•„μ˜€μ§€λ§Œ λ…ΉμŒν•  λ•Œ κ²ŒμΈμ„ 잘λͺ» μ„€μ •ν•˜μ—¬ μœ μ‹€λœ μ†Œλ¦¬λŠ” λ‹€μ‹œ λŒμ•„μ˜€μ§€ μ•ŠλŠ”λ‹€.

    μ‹ ν˜Έ μž…λ ₯ λ‹¨κ³„μ—μ„œ 이미 μœ μ‹€λœ 것이기 λ•Œλ¬Έμ— μ˜μ›ν•œ 이별인 것이닀. κ²Œλ‹€κ°€ λ…ΉμŒμ΄λΌλŠ” νŠΉμ„± 상 κ·Έ 원본 μ†ŒμŠ€λŠ” μ‚¬λžŒμΈ κ²½μš°κ°€ λ§Žλ‹€. κ²°κ΅­ 이 μœ μ‹€λœ μ‹ ν˜Έλ₯Ό λ‹€μ‹œ μ‚΄λ €λ‚Ό 수 μ—†κΈ° λ•Œλ¬Έμ— κ²ŒμΈμ„ 잘λͺ» μ„€μ •ν•˜λ©΄ λ‹€μ‹œ λ…ΉμŒμ„ ν•΄μ•Όν•˜λŠ” μŠ¬ν”ˆ 상황이 λ²Œμ–΄μ§ˆ 수 μžˆλŠ” 것이닀.

    κ·Έλž˜μ„œ μ‚¬μš΄λ“œ μ—”μ§€λ‹ˆμ–΄λ“€μ€ μ†Œλ¦¬λ₯Ό λ…ΉμŒν•  λ•Œ κ²ŒμΈμ„ 잘 λ‹€λ£¨λŠ” 것을 μ—„μ²­ μ€‘μš”ν•˜κ²Œ μƒκ°ν•œλ‹€. 사싀 게인만 해도 μ’€ 더 깊이 λ“€μ–΄κ°€λ©΄ ν•˜κ³  싢은 이야기가 λ§Žμ§€λ§Œ, 이 ν¬μŠ€νŒ…μ€ μ˜€λ””μ˜€ μ „λ¬Έ ν¬μŠ€νŒ…μ΄ μ•„λ‹ˆλ―€λ‘œ κ·Έλƒ₯ λΉ„μŠ·ν•œ 거라고 μƒκ°ν•˜κ³  λ„˜μ–΄κ°€λ„ 상관없닀.

    이제 게인이 무엇인지 μ΄ν•΄ν–ˆλ‹€λ©΄ GainNode와 ν•¨κ»˜ μ˜€λ””μ˜€ μ†ŒμŠ€μ˜ μ‹ ν˜Έ μ„ΈκΈ°λ₯Ό μ‘°μ ˆν•΄μ„œ μ†Œλ¦¬μ˜ 크기λ₯Ό λ³€ν˜•μ‹œμΌœλ³΄μž!

    Gain Nodeλ₯Ό μ‚¬μš©ν•˜μ—¬ μŒλŸ‰μ„ μ‘°μ ˆν•΄λ³΄μž

    일단 κ²ŒμΈμ„ μ‚¬μš©ν•΄λ³΄λ €λ©΄ μ˜€λ””μ˜€ μ†ŒμŠ€κ°€ ν•„μš”ν•˜λ‹€. μ˜€λ””μ˜€ μ†ŒμŠ€λŠ” HTML5의 <audio> νƒœκ·Έλ₯Ό μ‚¬μš©ν•˜κ±°λ‚˜ μ‚¬μš©μžκ°€ 직접 μ—…λ‘œλ“œν•œ νŒŒμΌμ—μ„œ μΆ”μΆœν•˜λŠ” 두가지 방법이 μžˆλŠ”λ°, ν•„μžλŠ” 이 쀑 ν›„μžμ˜ 방법을 μ‚¬μš©ν•˜μ˜€λ‹€.

    이것도 μ—„λ°€νžˆ λ§ν•˜μžλ©΄ <audio>νƒœκ·Έλ₯Ό μ‚¬μš©ν•˜μ—¬ μ†ŒμŠ€λ₯Ό μΆ”μΆœν–ˆμ„ λ•Œμ™€ 파일 λ²„νΌμ—μ„œ 직접 μΆ”μΆœν–ˆμ„ λ•ŒλŠ” λ‹€λ₯Έ μ†ŒμŠ€ λ…Έλ“œ 객체가 μƒμ„±λ˜κΈ΄ ν•˜μ§€λ§Œ κΈ°λŠ₯상 큰 차이 μ—†μœΌλ―€λ‘œ κ·Έλƒ₯ 개인의 μ·¨ν–₯λŒ€λ‘œ ν•˜λ©΄ λœλ‹€.

    const audioContext = new (Audiocontext || webkitAudioContext)();
    
    document.getElementById('audio-uploader').onchange = evt => {
      const file = evt.currentTarget.files[0];
      if (!file) {
        return;
      }
    
      const reader = new FileReader();
      reader.onload = async evt => {
        const buffer = await audioContext.decodeAudioData(file);
        const sourceNode = audioContext.createBufferSource();
        sourceNode.buffer = buffer;
        console.log(sourceNode);
      }
    };
    AudioBufferSourceNode {buffer: AudioBuffer, playbackRate: AudioParam, detune: AudioParam, loop: false, loopStart: 0, …}

    μš°μ„  κ°„λ‹¨ν•œ μ„€λͺ…을 ν•˜μžλ©΄ buffer λ³€μˆ˜μ— λ‹΄κΈ΄ μ˜€λ””μ˜€ λ°μ΄ν„°λŠ” rawν•œ μ˜€λ””μ˜€ 데이터일 뿐 아직 ν•˜λ‚˜μ˜ λ…Έλ“œκ°€ μ•„λ‹ˆκΈ° λ•Œλ¬Έμ— μ‚¬μš©ν•  수 μ—†λŠ” μƒνƒœμ΄λ‹€. κ·Έλ ‡κΈ° λ•Œλ¬Έμ— createBufferSource λ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ μ†ŒμŠ€ λ…Έλ“œλ₯Ό μƒμ„±ν•œ ν›„ ν•΄λ‹Ή μ†ŒμŠ€ λ…Έλ“œμ— μ˜€λ””μ˜€ 데이터λ₯Ό μž…λ ₯ν•΄μ€˜μ•Όλ§Œ λΉ„λ‘œμ†Œ μ˜€λ””μ˜€ 데이터λ₯Ό μ‚¬μš©ν•  수 μžˆλŠ” μƒνƒœκ°€ λ˜λŠ” 것이닀.

    μ΄λ•Œ ν•„μžλŠ” μ‚¬μš©μžκ°€ μ—…λ‘œλ“œν•œ νŒŒμΌμ—μ„œ 직접 μ˜€λ””μ˜€ 버퍼 데이터λ₯Ό λ½‘μ•„μ™€μ„œ λ…Έλ“œλ₯Ό λ§Œλ“  것이기 λ•Œλ¬Έμ— createBufferSource λ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν•˜μ—¬ μ†ŒμŠ€ λ…Έλ“œλ₯Ό μƒμ„±ν–ˆμ§€λ§Œ, λ§Œμ•½ <audio> νƒœκ·Έμ—μ„œ μΆ”μΆœν•œ μ˜€λ””μ˜€ 데이터λ₯Ό μ‚¬μš©ν•˜μ—¬ μ†ŒμŠ€ λ…Έλ“œλ₯Ό μƒμ„±ν•˜κ³  μ‹Άλ‹€λ©΄ createMediaElementSource λ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν•΄μ•Ό ν•œλ‹€.

    그럼 이제 GainNodeλ₯Ό μƒμ„±ν•˜κ³  μ†ŒμŠ€ λ…Έλ“œμ— μ—°κ²°λ§Œ μ‹œμΌœμ£Όλ©΄ λ°”λ‘œ 이 μ˜€λ””μ˜€ μ†ŒμŠ€μ˜ μŒλŸ‰μ„ μ‘°μ ˆν•  수 있게 λœλ‹€.

    const gainNode = audioContext.createGain();
    sourceNode.connect(gainNode);
    gainNode.connect(audioContext.destination);

    이 μ½”λ“œμ—μ„œ μ†ŒμŠ€ -> 게인 -> λ°μŠ€ν‹°λ„€μ΄μ…˜μœΌλ‘œ μ„€μ •λœ μ˜€λ””μ˜€μ˜ 흐름이 보인닀면 사싀상 Audio API에 λŒ€ν•œ μ΄ν•΄λŠ” 거의 끝났닀고 봐도 λ¬΄λ°©ν•˜λ‹€. μœ„μ—μ„œλ„ λ§ν–ˆλ“―μ΄ μ˜€λ””μ˜€λ₯Ό μ»¨νŠΈλ‘€ν•  λ•ŒλŠ” 이 κ°œλ…μ„ μ΄ν•΄ν•˜λŠ” 게 제일 μ€‘μš”ν•˜κΈ° λ•Œλ¬Έμ΄λ‹€.

    λ˜ν•œ gainNodeκ°€ μ—°κ²°λœ audioContext.destination은 μ΅œμ’… 아웃풋, 즉 μŠ€ν”Όμ»€λ‘œ ν–₯ν•˜λŠ” 정보λ₯Ό 가지고 μžˆλ‹€. 그럼 이제 μ—¬κΈ°μ„œ μ˜€λ””μ˜€μ˜ μ†Œλ¦¬λ₯Ό μ¦ν­μ‹œν‚€κ±°λ‚˜ κ°μ†Œμ‹œν‚€λ €λ©΄ μ–΄λ–»κ²Œ ν•΄μ•Όν• κΉŒ?

    gainNode.gain.value = 1.2;
    // λ˜λŠ”
    gainNode.gain.setValueAtTime(1.2, audioContext.currentTime);
    
    // κ·Έ ν›„ μ†ŒμŠ€λ₯Ό μž¬μƒν•΄λ³΄μž
    sourceNode.start();

    [Warinig] λ„ˆλ¬΄ 값을 크게 올리면 μž¬μƒν–ˆμ„ λ•Œ 고막 ν„°μ§‘λ‹ˆλ‹€.

    κ°„λ‹¨ν•˜λ‹€. κ·Έλƒ₯ GainNode.gain.value에 μ ‘κ·Όν•΄μ„œ 값을 λ³€κ²½ν•΄μ£Όλ©΄ λœλ‹€. 게인 같은 κ²½μš°λŠ” 값에 직접 μ ‘κ·Όν•˜μ—¬ λ³€κ²½ν•˜λŠ” 것이 κ°€λŠ₯ν•˜μ§€λ§Œ λ‹€λ₯Έ λ…Έλ“œμ˜ 경우 μžμ‹ μ˜ 값을 직접 λ³€κ²½ν•˜λŠ” 것이 ν—ˆμš©λ˜μ§€ μ•ŠλŠ” κ²½μš°κ°€ μžˆλŠ”λ°, 이럴 λ•ŒλŠ” setValueAtTime λ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν•˜λ©΄ λœλ‹€.

    setValueAtTime λ©”μ†Œλ“œλŠ” μΌμ’…μ˜ μŠ€μΌ€μ€„λŸ¬κ°™μ€ κ°œλ…μΈλ°, λ‘λ²ˆμ§Έ 인자둜 λ„˜κΈ΄ μ‹œκ°„μ΄ μ§€λ‚œ 후에 값을 μ μš©ν•˜λŠ” κΈ°λŠ₯을 가지고 μžˆλ‹€. μ΄λ•Œ 인자둜 λ„˜κΈ°λŠ” μ‹œκ°„μ˜ λ‹¨μœ„λŠ” μ΄ˆμ΄λ‹€. audioContext.currentTime을 인자둜 μ‚¬μš©ν•˜λ©΄ κ³§λ°”λ‘œ κ°’μ˜ 변경이 μ μš©λœλ‹€.

    ν•„μžλŠ” μ²˜μŒμ— 이런 λ…Έλ“œλ“€μ˜ 값을 λ³€κ²½ν•  λ•Œ ν—·κ°ˆλ Έλ˜ 것이 ν•˜λ‚˜ μžˆλŠ”λ°, λ°”λ‘œ minκ³Ό max이닀. 즉, 이 λ…Έλ“œκ°€ κ°€μ§€λŠ” κ°’μ˜ λ²”μœ„λ₯Ό μ•Œ μˆ˜κ°€ μ—†μ—ˆλ‹€. λ¬Όλ‘  곡식 λ¬Έμ„œμ— λ‹€ λ‚˜μ™€μžˆκΈ΄ ν•˜μ§€λ§Œ κ·Έκ±Έ μ–΄λŠ 세월에 ν•˜λ‚˜ν•˜λ‚˜ κ²€μƒ‰ν•΄μ„œ λ³΄κ² λŠ”κ°€?

    κ·Έλž˜μ„œ λ¬Έμ„œλ₯Ό 쑰금 더 λ’€μ Έλ³΄λ‹ˆ 이 λ…Έλ“œλ“€μ΄ κ°€μ§€λŠ” 값은 κ³΅ν†΅μ μœΌλ‘œ AudioParam νƒ€μž…μ΄λΌλŠ” 것을 μ•Œ 수 μžˆμ—ˆλ‹€. 이 νƒ€μž…μ€ min, max, defaultValue, value 속성을 가지고 μžˆμ—ˆκ³ , 이 값듀은 input[type="range"]λ₯Ό μ‚¬μš©ν•˜μ—¬ μ˜€λ””μ˜€λ₯Ό μ»¨νŠΈλ‘€ν• λ•Œ μœ μš©ν•˜κ²Œ μ‚¬μš©ν•  수 μžˆλ‹€.

    console.log(gainNode.gain);
    AudioParam {value: 1, automationRate: "a-rate", defaultValue: 1, minValue: -3.4028234663852886e+38, maxValue: 3.4028234663852886e+38}

    이 값을 잘 ν™•μΈν•˜κ³  게인의 값을 μ„€μ •ν•˜λ©΄ 적어도 고막과 이어폰이 ν„°μ Έλ‚˜κ°€λŠ” λΆˆμƒμ‚¬λŠ” 방지할 수 μžˆμ„ 것이닀. μœ„μ—μ„œ λ§ν–ˆλ“―μ΄ 컴퓨터가 μ²˜λ¦¬ν•  수 μžˆλŠ” μ‹ ν˜Έμ˜ μ„ΈκΈ°λ₯Ό λ„˜μ–΄κ°€κ²Œ 되면 클리핑 ν˜„μƒμ΄ λ°œμƒν•˜λ©΄μ„œ μ°’μ–΄μ§€λŠ” λ“―ν•œ μ†Œλ¦¬κ°€ λ‚˜κΈ° λ•Œλ¬Έμ— λ§Œμ•½ 이어폰을 끼고 μžˆμ—ˆλ‹€λ©΄ 농담이 μ•„λ‹ˆκ³  μ§„μ§œ 귀에 무리가 갈 μˆ˜λ„ μžˆλ‹€.

    자, μ΄λ ‡κ²Œ κ°„λ‹¨ν•˜κ²Œ μ˜€λ””μ˜€ μ†ŒμŠ€μ˜ κ²ŒμΈμ„ μ‘°μ ˆν•΄λ³΄μ•˜λ‹€. λ‚˜λ¨Έμ§€ μ΄νŽ™ν„°λ“€λ„ λŒ€λΆ€λΆ„ 이런 λŠλ‚ŒμœΌλ‘œ κ΅¬ν˜„λœλ‹€. κ°„ν˜Ή 쑰금 더 λ³΅μž‘ν•œ 연결이 ν•„μš”ν•œ μ΄νŽ™ν„°λ“€μ΄ 있긴 ν•˜μ§€λ§Œ λŒ€λΆ€λΆ„μ˜ 경우 κ°„λ‹¨ν•œ λͺ‡κ°œμ˜ λ…Έλ“œλ₯Ό μ—°κ²°ν•˜λŠ” κ²ƒλ§ŒμœΌλ‘œ κ΅¬ν˜„ν•  수 있기 λ•Œλ¬Έμ— κ·Έλ ‡κ²Œ 어렡지 μ•Šλ‹€.

    λ‹€μŒ ν¬μŠ€νŒ…μ—μ„œλŠ” μ΄λ²ˆμ— μ•Œμ•„λ³Έ κ°œλ…μ„ λ°”νƒ•μœΌλ‘œ μ†Œλ¦¬λ₯Ό μ••μΆ•ν•˜κ±°λ‚˜ 곡간감을 λΆ€μ—¬ν•˜κ³ , νŠΉμ • 주파수λ₯Ό μž˜λΌλ‚΄μ–΄ μ†Œλ¦¬μ— νŠΉλ³„ν•œ λŠλ‚Œμ„ 쀄 수 μžˆλŠ” λ‹€λ₯Έ μ΄νŽ™ν„°λ“€μ„ λ§Œλ“€μ–΄λ³΄λ„λ‘ ν•˜κ² λ‹€. λ˜ν•œ κΈ°νšŒκ°€ λœλ‹€λ©΄ 이미 μ‘΄μž¬ν•˜λŠ” μ˜€λ””μ˜€ μ†ŒμŠ€λ₯Ό λ³€ν˜•ν•˜λŠ” μ΄νŽ™ν„°κ°€ μ•„λ‹ˆλΌ μ§„μ§œλ‘œ μ˜€λ””μ˜€ μ‹ ν˜Έ 자체λ₯Ό λ§Œλ“€μ–΄ λ‚Ό 수 μžˆλŠ” μ˜€μ‹€λ ˆμ΄ν„°(Oscillator)λ₯Ό μ‚¬μš©ν•˜μ—¬ λ‚˜λ§Œμ˜ μ•…κΈ°λ₯Ό λ§Œλ“€μ–΄λ³Ό 수 μžˆλŠ” ν¬μŠ€νŒ…λ„ 진행할 μ˜ˆμ •μ΄λ‹€.

    μ΄μƒμœΌλ‘œ JavaScript둜 μ˜€λ””μ˜€ μ΄νŽ™ν„°λ₯Ό λ§Œλ“€μ–΄λ³΄μž - μ†Œλ¦¬μ˜ 흐름을 νŒŒμ•…ν•˜μž ν¬μŠ€νŒ…μ„ λ§ˆμΉœλ‹€.

    Evan Moon

    🐒 거뢁이처럼 μ‚΄μž

    κ°œλ°œμ„ μž˜ν•˜κΈ° μœ„ν•΄μ„œκ°€ μ•„λ‹Œ κ°œλ°œμ„ 즐기기 μœ„ν•΄ λ…Έλ ₯ν•˜λŠ” κ°œλ°œμžμž…λ‹ˆλ‹€. μ‚¬μ†Œν•œ 생각 정리뢀터 νŠœν† λ¦¬μ–Ό, μ‚½μ§ˆκΈ° 정도λ₯Ό 주둜 끄적이고 μžˆμŠ΅λ‹ˆλ‹€.