πŸ’»μš©λ‡½ 개발 λ…ΈνŠΈπŸ’»
article thumbnail
λ°˜μ‘ν˜•

 

[JavaScript] μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ(Execution Context)κ°€ λ¬΄μ—‡μΌκΉŒμš”?

λ“€μ–΄κ°€λ©° πŸ“–

μžλ°”μŠ€ν¬λ¦½νŠΈλ₯Ό μ΄ν•΄ν•˜λŠ” 데 μžˆμ–΄μ„œ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ(Execution Context)의 κ°œλ…μ— λŒ€ν•΄μ„œ μˆ™μ§€ν•˜λŠ” 것은 μ€‘μš”ν•©λ‹ˆλ‹€.

 

μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ 핡심 κ°œλ… 쀑 ν•˜λ‚˜λ‘œ, μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ μ½”λ“œμ˜ μ‹€ν–‰ μˆœμ„œμ™€ 방식을 κ²°μ •ν•˜κ²Œ 되죠.

μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ(Excution Context)λž€β“

μ‹€ν–‰ν•  μ½”λ“œμ— μ œκ³΅ν•  ν™˜κ²½ 정보듀을 λͺ¨μ•„놓은 κ°μ²΄μž…λ‹ˆλ‹€.

μžλ°”μŠ€ν¬λ¦½νŠΈμ˜ 동적 μ–Έμ–΄λ‘œμ„œμ˜ 성격을 κ°€μž₯ 잘 νŒŒμ•…ν•  수 μžˆλŠ” κ°œλ…μž…λ‹ˆλ‹€.

 

κ·Έλž˜μ„œ μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” μ‹€ν–‰ μ»¨ν…μŠ€νŠΈκ°€ ν™œμ„±ν™”λ˜λŠ” μ‹œμ μ— μ•„λž˜μ™€ 같은 λ™μž‘μ„ μˆ˜ν–‰ν•©λ‹ˆλ‹€.

  • ν˜Έμ΄μŠ€νŒ…(hoisting)
  • μ™ΈλΆ€ ν™˜κ²½ 정보 ꡬ성
  • this κ°’ μ„€μ •

λ“±λ“± 이둜 인해 λ‹€λ₯Έ μ–Έμ–΄μ—μ„œλŠ” λ°œκ²¬ν•  수 μ—†λŠ” νŠΉμ΄ν•œ ν˜•μƒλ“€μ΄ λ°œμƒν•©λ‹ˆλ‹€.

λ™μž‘ κ³Όμ •

λ™μΌν•œ ν™˜κ²½μ— μžˆλŠ” μ½”λ“œλ“€μ„ μ‹€ν–‰ν•  λ•Œ ν•„μš”ν•œ ν™˜κ²½ 정보듀을 λͺ¨μ•„ μ»¨ν…μŠ€νŠΈλ₯Ό κ΅¬μ„±ν•©λ‹ˆλ‹€.

이λ₯Ό 콜 μŠ€νƒ(Call Stack)에 μŒ“μ•„ μ˜¬λ¦½λ‹ˆλ‹€.

κ°€μž₯ μœ„μ— μŒ“μ—¬μžˆλŠ” μ»¨ν…μŠ€νŠΈμ™€ κ΄€λ ¨ μžˆλŠ” μ½”λ“œλ“€μ„ μ‹€ν–‰ν•˜λŠ” μ‹μœΌλ‘œ 전체 μ½”λ“œμ˜ ν™˜κ²½κ³Ό μˆœμ„œλ₯Ό 보μž₯ν•©λ‹ˆλ‹€.

 

μ‹€ν–‰ μ»¨ν…μŠ€νŠΈλ₯Ό ꡬ성할 수 μžˆλŠ” λ°©λ²•μœΌλ‘œλŠ”

  • μ „μ—­ 곡간
  • eval() ν•¨μˆ˜
  • ν•¨μˆ˜

등이 μžˆμŠ΅λ‹ˆλ‹€.

μ—¬κΈ°μ„œ μš°λ¦¬κ°€ ν”νžˆ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈλ₯Ό κ΅¬μ„±ν•˜λŠ” 방법은 ν•¨μˆ˜λ₯Ό μ‹€ν–‰ν•˜λŠ” κ²ƒμž…λ‹ˆλ‹€.

var a = 1;
function outer() {
  function inner() {
    console.log(a); // undefined
    var a = 3;
  }
  inner();
  console.log(a); // 1
}
outer();
console.log(a); // 1

μœ„ μ½”λ“œμ˜ μˆœμ„œλ₯Ό μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ κ΄€μ μ—μ„œ 보면 μ•„λž˜μ™€ κ°™μŠ΅λ‹ˆλ‹€.

μ‹€ν–‰ μ»¨ν…μŠ€νŠΈμ™€ 콜 μŠ€νƒ

  1. μžλ°”μŠ€ν¬λ¦½νŠΈ μ½”λ“œ μ‹€ν–‰
  2. μ „μ—­ μ»¨ν…μŠ€νŠΈλ₯Ό 콜 μŠ€νƒμ— μΆ”κ°€
  3. μ „μ—­ μ»¨ν…μŠ€νŠΈμ™€ κ΄€λ ¨λœ μ½”λ“œλ“€μ„ 순차둜 진행
  4. outer에 λŒ€ν•œ ν™˜κ²½ 정보 μˆ˜μ§‘
  5. outer μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ 생성 ν›„ 콜 μŠ€νƒμ— μΆ”κ°€
  6. μ „μ—­ μ»¨ν…μŠ€νŠΈμ™€ κ΄€λ ¨λœ μ½”λ“œμ˜ μ‹€ν–‰ μΌμ‹œμ€‘λ‹¨ (콜 μŠ€νƒ 맨 μœ„μ— outer μ‹€ν–‰ μ»¨ν…μŠ€νŠΈκ°€ 놓인 μƒνƒœ)
  7. outer ν•¨μˆ˜ λ‚΄λΆ€μ˜ μ½”λ“œ 순차둜 μ‹€ν–‰
  8. inner μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ 생성 ν›„ 콜 μŠ€νƒμ— μΆ”κ°€
  9. outer와 κ΄€λ ¨λœ μ½”λ“œμ˜ μ‹€ν–‰ μΌμ‹œμ€‘λ‹¨ (콜 μŠ€νƒ 맨 μœ„μ— inner μ‹€ν–‰ μ»¨ν…μŠ€νŠΈκ°€ 놓인 μƒνƒœ)
  10. inner ν•¨μˆ˜ λ‚΄λΆ€μ˜ μ½”λ“œ 순차둜 μ‹€ν–‰
  11. 이후에 ν•¨μˆ˜ 싀행이 μ’…λ£Œλ˜λ©΄ 콜 μŠ€νƒμ—μ„œ 제거 되고 μ•„λž˜μ— 있던 μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ μ΄μ–΄μ„œ μ‹€ν–‰

ꡬ성

μ‹€ν–‰ μ»¨ν…μŠ€νŠΈμ— λ‹΄κΈ°λŠ” 정보듀은 μ•„λž˜μ™€ κ°™μŠ΅λ‹ˆλ‹€.

VariableEnvironment

  • ν˜„μž¬ μ»¨ν…μŠ€νŠΈ λ‚΄μ˜ μ‹λ³„μžλ“€μ— λŒ€ν•œ 정보
  • μ™ΈλΆ€ ν™˜κ²½ 정보
  • μ„ μ–Έ μ‹œμ μ˜ LexicalEnvironment의 μŠ€λƒ…μƒ· ➑️ λ³€κ²½ 사항은 λ°˜μ˜λ˜μ§€ μ•ŠμŒ

VariableEnvironment에 λ‹΄κΈ°λŠ” λ‚΄μš©μ€ LexicalEnvironment와 κ°™μŠ΅λ‹ˆλ‹€.

ν•˜μ§€λ§Œ, 졜초 μ‹€ν–‰ μ‹œμ˜ μŠ€λƒ…μƒ·μ„ μœ μ§€ν•œλ‹€λŠ” 차이가 μžˆμŠ΅λ‹ˆλ‹€.

즉, μ‹€ν–‰ μ»¨ν…μŠ€νŠΈλ₯Ό 생성할 λ•Œ VariableEnvironment에 정보λ₯Ό λ¨Όμ € λ‹΄μŠ΅λ‹ˆλ‹€.

λ‹€μŒμœΌλ‘œ 이λ₯Ό κ·ΈλŒ€λ‘œ λ³΅μ‚¬ν•΄μ„œ LexicalEnvironmentλ₯Ό λ§Œλ“­λ‹ˆλ‹€.

 

μ΄ν›„μ—λŠ” LexicalEnvironmentλ₯Ό 주둜 ν™œμš©ν•©λ‹ˆλ‹€.

LexicalEnvironment

  • μ΄ˆκΈ°μ—λŠ” VaribaleEnvironment와 κ°™μŒ
  • 이후 λ³€κ²½ 사항이 μ‹€μ‹œκ°„μœΌλ‘œ 반영됨

environmentRecord와 ν˜Έμ΄μŠ€νŒ…

environmentRecordμ—λŠ” λ§€κ°œλ³€μˆ˜μ˜ 이름, ν•¨μˆ˜ μ„ μ–Έ, λ³€μˆ˜λͺ… 등이 λ‹΄κΉλ‹ˆλ‹€.

ν˜„μž¬ μ»¨ν…μŠ€νŠΈμ™€ κ΄€λ ¨λœ μ½”λ“œμ˜ μ‹λ³„μž 정보듀이 μ €μž₯λ©λ‹ˆλ‹€.

μ‹λ³„μž μ •λ³΄λž€?
ν•¨μˆ˜μ— μ§€μ •λœ λ§€κ°œλ³€μˆ˜ μ‹λ³„μž, ν•¨μˆ˜ 자체, var둜 μ„ μ–Έλœ λ³€μˆ˜μ˜ μ‹λ³„μž λ“±λ“± μ˜λ―Έν•©λ‹ˆλ‹€.
즉, μ»¨ν…μŠ€νŠΈ λ‚΄λΆ€ 전체λ₯Ό μ²˜μŒλΆ€ν„° λκΉŒμ§€ μˆœμ„œλŒ€λ‘œ μˆ˜μ§‘ν•©λ‹ˆλ‹€.

μ΄λŸ¬ν•œ κ³Όμ •μœΌλ‘œ λ³€μˆ˜ 정보λ₯Ό μˆ˜μ§‘ν•˜μ—¬ μ½”λ“œκ°€ μ‹€ν–‰λ˜κΈ° μ „μž„μ—λ„ λΆˆκ΅¬ν•˜κ³ ,

μžλ°”μŠ€ν¬λ¦½νŠΈ 엔진은 이미 ν•΄λ‹Ή ν™˜κ²½μ— μ†ν•œ μ½”λ“œμ˜ λ³€μˆ˜λͺ…듀을 λͺ¨λ‘ μ•Œκ²Œ 된 μƒν™©μž…λ‹ˆλ‹€.

λ•Œλ¬Έμ— μ—¬κΈ°μ„œ ν˜Έμ΄μŠ€νŒ…(hoisting)μ΄λΌλŠ” κ°œλ…μ΄ λ“±μž₯ν•©λ‹ˆλ‹€.

 

ν˜Έμ΄μŠ€νŒ…μ— κ΄€λ ¨ν•΄μ„œλŠ” ν•΄λ‹Ή κΈ€μ—μ„œ μžμ„Ένžˆ λ‹€λ£Ήλ‹ˆλ‹€.

μŠ€μ½”ν”„(Scope)와 outerEnvironmentReference

  • μŠ€μ½”ν”„(Scope)λž€ μ‹λ³„μžμ— λŒ€ν•œ 유효 λ²”μœ„μž…λ‹ˆλ‹€.
  • μ–΄λ–€ 경계 A의 μ™ΈλΆ€μ—μ„œ μ„ μ–Έν•œ λ³€μˆ˜λŠ” A의 외뢀뿐 μ•„λ‹ˆλΌ A의 λ‚΄λΆ€μ—μ„œλ„ 접근이 κ°€λŠ₯ν•©λ‹ˆλ‹€.
  • ν•˜μ§€λ§Œ, A의 λ‚΄λΆ€μ—μ„œ μ„ μ–Έν•œ λ³€μˆ˜λŠ” 였직 A의 λ‚΄λΆ€μ—μ„œλ§Œ 접근이 κ°€λŠ₯ν•©λ‹ˆλ‹€.

ES5
κΉŒμ§€μ˜ μžλ°”μŠ€ν¬λ¦½νŠΈλŠ” 전역곡간을 μ œμ™Έν•˜λ©΄ 였직 ν•¨μˆ˜μ— μ˜ν•΄μ„œλ§Œ μŠ€μ½”ν”„κ°€ μƒμ„±λ©λ‹ˆλ‹€.
ES6μ—μ„œλŠ” 블둝에 μ˜ν•΄μ„œλ„ μŠ€μ½”ν”„ 경계가 λ°œμƒν•©λ‹ˆλ‹€.
이 블둝은 ES6에 λ“±μž₯ν•œ let, const, class, strict modeμ—μ„œμ˜ ν•¨μˆ˜ μ„ μ–Έ 등에 λŒ€ν•΄μ„œλ§Œ λ²”μœ„λ‘œμ„œ 역할을 μˆ˜ν–‰ν•©λ‹ˆλ‹€.
κ·Έλž˜μ„œ λ‘˜μ„ κ΅¬λΆ„ν•˜κΈ° μœ„ν•΄ ν•¨μˆ˜ μŠ€μ½”ν”„, 블둝 μŠ€μ½”ν”„λΌλŠ” μš©μ–΄λ₯Ό μ‚¬μš©ν•©λ‹ˆλ‹€.

μŠ€μ½”ν”„ 체인(Scope Chain)

μ‹λ³„μžμ˜ μœ νš¨λ²”μœ„λ₯Ό μ•ˆμ—μ„œλΆ€ν„° λ°”κΉ₯으둜 μ°¨λ‘€λ‘œ 검색해 λ‚˜κ°€λŠ” κ²ƒμž…λ‹ˆλ‹€.

그리고 이λ₯Ό κ°€λŠ₯ν•˜κ²Œ ν•˜λŠ” 것이 LexicalEnvironment의 두 번째 μˆ˜μ§‘ 자료인 outerEnvironmentReferenceμž…λ‹ˆλ‹€.

 

outerEnvironmentReferenceλŠ” ν˜„μž¬ 호좜된 ν•¨μˆ˜κ°€ 선언될 λ‹Ήμ‹œμ˜ LexicalEnvironmentλ₯Ό μ°Έμ‘°ν•©λ‹ˆλ‹€.

'μ„ μ–Έν•˜λ‹€'λΌλŠ” ν–‰μœ„κ°€ μ‹€μ œλ‘œ 일어날 수 μžˆλŠ” μ‹œμ μ΄λž€?
콜 μŠ€νƒ μƒμ—μ„œ μ–΄λ–€ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈκ°€ ν™œμ„±ν™”λœ μƒνƒœμΌ λ•ŒλΏμž…λ‹ˆλ‹€.
즉, λͺ¨λ“  μ½”λ“œλŠ” μ‹€ν–‰ μ»¨ν…μŠ€νŠΈκ°€ ν™œμ„±ν™” μƒνƒœμΌ λ•Œ μ‹€ν–‰λ˜κΈ° λ•Œλ¬Έμž…λ‹ˆλ‹€.

예λ₯Ό λ“€μ–΄ A ν•¨μˆ˜ 내뢀에 B ν•¨μˆ˜λ₯Ό μ„ μ–Έν•˜κ³  λ‹€μ‹œ B ν•¨μˆ˜ 내뢀에 C ν•¨μˆ˜λ₯Ό μ„ μ–Έν•œ 경우

  • ν•¨μˆ˜ C의 outerEnvironmentReference ➑️ ν•¨μˆ˜ B의 LexicalEnvironment
  • ν•¨μˆ˜ B의 outerEnvironmentReference ➑️ ν•¨μˆ˜ A의 LexicalEnvironment
  • 이처럼 outerEnvironmentReferenceλŠ” μ—°κ²°λ¦¬μŠ€νŠΈ(linked list) ν˜•νƒœλ₯Ό λ±λ‹ˆλ‹€.

μ„ μ–Έ μ‹œμ μ˜ LexicalEnvironmentλ₯Ό 계속 μ°Ύμ•„ μ˜¬λΌκ°€λ©΄ λ§ˆμ§€λ§‰μ—λŠ” μ „μ—­ μ»¨ν…μŠ€νŠΈμ˜ LexicalEnvironmentκ°€ λ‚˜μ˜΅λ‹ˆλ‹€.

 

κ·Έλž˜μ„œ 각 outerEnvironmentReferenceλŠ” 였직 μžμ‹ μ΄ μ„ μ–Έλœ μ‹œμ μ˜ LexicalEnvironment만 μ°Έμ‘°ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.

λ”°λΌμ„œ, κ°€μž₯ κ°€κΉŒμš΄ μš”μ†ŒλΆ€ν„° μ°¨λ‘€λŒ€λ‘œ μ ‘κ·Όν•  수 있고 λ‹€λ₯Έ μˆœμ„œλ‘œ 접근은 λΆˆκ°€λŠ₯ν•©λ‹ˆλ‹€.

 

μ΄λŸ¬ν•œ ꡬ쑰적 νŠΉμ„± 덕뢄에 μ—¬λŸ¬ μŠ€μ½”ν”„μ—μ„œ λ™μΌν•œ μ‹λ³„μžλ₯Ό μ„ μ–Έν•œ κ²½μš°μ—λŠ” 무쑰건 μŠ€μ½”ν”„ 체인 μƒμ—μ„œ κ°€μž₯ λ¨Όμ € 발견된 μ‹λ³„μžμ—λ§Œ 접근이 κ°€λŠ₯ν•©λ‹ˆλ‹€.

// μ‹œμž‘: μ „μ—­ μ»¨ν…μŠ€νŠΈ ν™œμ„±ν™” (μ„ μ–Έ μ‹œμ μ΄ μ—†μœΌλ―€λ‘œ outerEnvironmentReferenceλŠ” 빈 κ°’)
// enviromnetRecord에{a, outer} μ‹λ³„μž μ €μž₯
var a = 1; // μ „μ—­ μŠ€μ½”ν”„μ˜ a에 1 ν• λ‹Ή
var outer = function () {
	// enviromnetRecord에 { inner } μ‹λ³„μž μ €μž₯
  var inner = function () {
  	// environmentRecord에 { a } μ‹λ³„μž μ €μž₯
    console.log(a); // environmentRecordμ—μ„œ aλ₯Ό 검색 => 아직 값이 ν• λ‹Ή λ˜μ§€ μ•ŠμŒ undefined 좜λ ₯
    var a = 3;
  }
  inner(); // inner μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ ν™œμ„±ν™” => μ„ μ–Έ λ‹Ήμ‹œμΈ outer의 LexicalEnvironment 참쑰볡사 
  console.log(a); // enviromnetRecordμ—μ„œ aλ₯Ό μ°Ύμ•„λ³΄λ‹ˆ μ—†μŒ => outerEnvironmentReference에 μžˆλŠ” enviromnetRecordλ₯Ό 탐색 => 1 좜λ ₯
}
outer(); // outer μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ ν™œμ„±ν™” => μ„ μ–Έ λ‹Ήμ‹œμΈ μ „μ—­ μ»¨ν…μŠ€νŠΈμ˜ LexicalEnvironment 참쑰볡사 첫번째둜 μ‹€ν–‰ μ»¨ν…μŠ€νŠΈμ˜ 이름, λ‘λ²ˆμ§Έλ‘œ environmentRecord 객체(this: μ „μ—­ 객체)
console.log(a);

ThisBinding

μ‹λ³„μžκ°€ 바라봐야 ν•  λŒ€μƒ κ°μ²΄μž…λ‹ˆλ‹€.

즉, this둜 μ§€μ •λœ 객체가 μ €μž₯λ©λ‹ˆλ‹€.

μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ ν™œμ„±ν™” λ‹Ήμ‹œμ— thisκ°€ μ§€μ •λ˜μ§€ μ•Šμ€ 경우 thisμ—λŠ” μ „μ—­ 객체가 μ €μž₯λ©λ‹ˆλ‹€.

 

this에 λŒ€ν•΄μ„œλŠ” ν•΄λ‹Ή κΈ€μ—μ„œ  μžμ„Ένžˆ λ‹€λ£Ήλ‹ˆλ‹€.

정리 πŸ“•

  • μ‹€ν–‰ μ»¨ν…μŠ€νŠΈλŠ” μ‹€ν–‰ν•  μ½”λ“œμ— μ œκ³΅ν•  ν™˜κ²½ 정보듀을 λͺ¨μ•„놓은 객체
    • μ „μ—­ κ³΅κ°„μ—μ„œ μžλ™μœΌλ‘œ μƒμ„±λ˜λŠ” μ „μ—­ μ»¨ν…μŠ€νŠΈ
    • eval()
    • ν•¨μˆ˜ 싀행에 μ˜ν•œ μ»¨ν…μŠ€νŠΈ
  • μ‹€ν–‰ μ»¨ν…μŠ€νŠΈλŠ” ν™œμ„±ν™”λ˜λŠ” μ‹œμ μ— μ„Έ 가지 정보λ₯Ό μˆ˜μ§‘
    • VariableEnvironment: : environmentRecord, outerEnvironmnetReference둜 ꡬ성, 초기 μƒνƒœλ₯Ό μœ μ§€ν•¨.
    • LexicalEnvironment: VariableEnvironment와 λ™μΌν•œ ꡬ성, ν•¨μˆ˜ μ‹€ν–‰ 도쀑에 λ³€κ²½λ˜λŠ” 사항이 μ¦‰μ‹œ 반영
    • ThisBinding
  • environmentRecordλŠ” λ§€κ°œλ³€μˆ˜λͺ…, λ³€μˆ˜μ˜ μ‹λ³„μž, μ„ μ–Έν•œ ν•¨μˆ˜μ˜ ν•¨μˆ˜ λͺ… 등을 μˆ˜μ§‘
  • outerEnvironmnetλŠ” 직전 μ»¨ν…μŠ€νŠΈμ˜ LexicalEnvironment 정보λ₯Ό μ°Έμ‘°
  • environmentRecord의 μˆ˜μ§‘ 과정을 μΆ”μƒν™”ν•œ κ°œλ… ➑️ ν˜Έμ΄μŠ€νŒ…(hoisting)
  • μŠ€μ½”ν”„λŠ” λ³€μˆ˜μ˜ μœ νš¨λ²”μœ„λ₯Ό λœ»ν•¨
    • μ½”λ“œ μƒμ—μ„œ μ–΄λ–€ λ³€μˆ˜μ— μ ‘κ·Όν•˜λ €κ³  ν•˜λ©΄ ν˜„μž¬ μ»¨ν…μŠ€νŠΈμ˜ LexicalEnvironmentλ₯Ό 탐색
    • μ „μ—­ μ»¨ν…μŠ€νŠΈμ˜ LexicalEnvironmentκΉŒμ§€ 도달해도 찾지 λͺ»ν–ˆλ‹€λ©΄ undefined λ°˜ν™˜
  • μ „μ—­ λ³€μˆ˜ = μ „μ—­ μ»¨ν…μŠ€νŠΈμ˜ LexicalEnvironment에 λ‹΄κΈ΄ λ³€μˆ˜
  • 지역 λ³€μˆ˜ = ν•¨μˆ˜μ— μ˜ν•΄ μƒμ„±λœ μ‹€ν–‰ μ»¨ν…μŠ€νŠΈμ˜ λ³€μˆ˜
  • thisμ—λŠ” μ‹€ν–‰ μ»¨ν…μŠ€νŠΈλ₯Ό ν™œμ„±ν™”ν•˜λŠ” λ‹Ήμ‹œμ— μ§€μ •λœ thisκ°€ μ €μž₯됨

μ°Έκ³  λ¬Έν—Œ: μ½”μ–΄μžλ°”μŠ€ν¬λ¦½νŠΈ - μ‹€ν–‰ μ»¨ν…μŠ€νŠΈ

λ°˜μ‘ν˜•
profile

πŸ’»μš©λ‡½ 개발 λ…ΈνŠΈπŸ’»

@μš©λ‡½

ν¬μŠ€νŒ…μ΄ μ’‹μ•˜λ‹€λ©΄ "μ’‹μ•„μš”β€οΈ" λ˜λŠ” "κ΅¬λ…πŸ‘πŸ»" ν•΄μ£Όμ„Έμš”!