Firebase-tools: ์—๋ฎฌ๋ ˆ์ดํ„ฐ ์ œํ’ˆ๊ตฐ์— Firebase ์ธ์ฆ ์—๋ฎฌ๋ ˆ์ดํ„ฐ ์ถ”๊ฐ€

์— ๋งŒ๋“  2019๋…„ 09์›” 26์ผ  ยท  66์ฝ”๋ฉ˜ํŠธ  ยท  ์ถœ์ฒ˜: firebase/firebase-tools

๋” ๋น ๋ฅธ ๋กœ์ปฌ ๊ฐœ๋ฐœ ๋ฐ ์ข…๋‹จ ๊ฐ„ ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•ด ์ธ์ฆ API๋ฅผ ์—๋ฎฌ๋ ˆ์ดํŠธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? Firestore ์—๋ฎฌ๋ ˆ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋‹ค์–‘ํ•œ ํ™˜๊ฒฝ(dev, testing, staging, prod)์— ๋Œ€ํ•ด ์„œ๋กœ ๋‹ค๋ฅธ ํ”„๋กœ์ ํŠธ๋ฅผ ์ƒ์„ฑํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ์—๋ฎฌ๋ ˆ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๊ฑฐ๋‚˜ ๊ฐœ๋ฐœ์„ ์œ„ํ•ด ๊ฐ์‹œ ๋ชจ๋“œ์˜ JSON ํŒŒ์ผ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์‹œ๋“œํ•˜๊ฑฐ๋‚˜ ๋ชจ๋“  ํ”„๋กœ์ ํŠธ์— ๋Œ€ํ•ด ์‹œ๋“œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค ๋“ฑ. ์‚ฌ์šฉ์ž ๋กœ๊ทธ์ธ, ์—ญํ•  ๊ธฐ๋ฐ˜ ํƒ์ƒ‰ ๋ฐ ์ผ๋ถ€ ์ž‘์—…์ด ์žˆ๋Š” ์ข…๋‹จ ๊ฐ„ ํ…Œ์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์œผ๋ ค๋ฉด ํ…Œ์ŠคํŠธ ์‚ฌ์šฉ์ž๋ฅผ ๊ฒฉ๋ฆฌํ•˜๊ณ  ๊ฑฐ๊ธฐ์—์„œ ์‚ฌ์šฉ์ž๋ฅผ ์‹œ๋“œ ๋ฐ ์ง€์šฐ๊ธฐ ์œ„ํ•œ ๋ณ„๋„์˜ ํ”„๋กœ์ ํŠธ๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ๋ชจ๋“  ํ…Œ์ŠคํŠธ ์ผ€์ด์Šค์— ๋Œ€ํ•ด.

emulator-suite feature request

๊ฐ€์žฅ ์œ ์šฉํ•œ ๋Œ“๊ธ€

์šฐ๋ฆฌ๋Š” ์™„์ „ํ•œ ์ธ์ฆ ์—๋ฎฌ๋ ˆ์ดํ„ฐ๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ์—ด์‹ฌํžˆ ๋…ธ๋ ฅํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
๋ชจ๋‘๊ฐ€ ์›ํ•˜๋Š”. ์ง€๊ธˆ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๋Š” ์ผ์ •์€ ์—†์ง€๋งŒ ์šฐ์„  ์ˆœ์œ„๊ฐ€ ๋†’์Šต๋‹ˆ๋‹ค.
์šฐ๋ฆฌ๋ฅผ ์œ„ํ•ด.

2020๋…„ 5์›” 22์ผ ๊ธˆ์š”์ผ ์˜ค์ „ 8์‹œ 12๋ถ„์— ChuckB [email protected]์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.

@samtstern https://github.com/samtstern ์ง„ํ–‰ ์ƒํ™ฉ ๋˜๋Š” ๊ธฐํƒ€
์ด ๋ฌธ์ œ/๊ธฐ๋Šฅ์— ๋Œ€ํ•œ ์†”๋ฃจ์…˜์€ ๋ฌด์—‡์ž…๋‹ˆ๊นŒ? ์ž‘์—…ํ•˜๋ ค๋ฉด (1) setEmulatedUser๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
ํด๋ผ์šฐ๋“œ Firestore ์—๋ฎฌ๋ ˆ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋กœ์ปฌ์—์„œ ์ˆ˜๋™ ํ…Œ์ŠคํŠธ๋ฅผ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ท€ํ•˜์˜ ์˜๊ฒฌ์— ๋”ฐ๋ผ: 2019๋…„ 10์›” 17์ผ
_ ๋‚˜๋Š” ๋ถ„๋ช…ํžˆ (2)๊ฐ€ ๋งž๋Š” ์ด์•ผ๊ธฐ๋ผ๊ณ  ์ƒ๊ฐํ•˜์ง€๋งŒ ๋‚˜๋Š”
ํ›จ์”ฌ ๋” ๊ฐ„๋‹จํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์–ผ๋งˆ๋‚˜ ๋งŽ์€ ์‚ฌ๋žŒ๋“ค์ด (1)์— ๋งŒ์กฑํ•  ๊ฒƒ์ธ๊ฐ€?
๊ตฌํ˜„ํ•˜๊ณ  ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค.

(1) ๋กœ๊ทธ์ธ ์—†์ด Firestore ๋˜๋Š” Realtime Database์™€ ๊ฐ™์€ ์„œ๋น„์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด
์‹ค์ œ๋กœ ์‹ค์ œ ์‚ฌ์šฉ์ž๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ง€๊ธˆ์€ ๊ทธ๋Ÿฐ ๊ฒƒ ๊ฐ™๋‹ค.
setEmulatedUser๊ฐ€ ํ•ด๊ฒฐํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ฐ€์งœ ์ธ์ฆ์„ ํ—ˆ์šฉํ•  ๋ฟ์ž…๋‹ˆ๋‹ค.
์—๋ฎฌ๋ ˆ์ดํ„ฐ๊ฐ€ ์ˆ˜๋ฝํ•˜์ง€๋งŒ ๊ฑฐ๋ถ€ํ•  ๋กœ์ปฌ ํ† ํฐ
์ฐŒ๋ฅด๋‹ค. ๋” ๋งŽ์€ ์•ˆ์ „, ๋” ๋งŽ์€ ๊ฒฉ๋ฆฌ ๋“ฑ_

โ€”
๋‹น์‹ ์ด ์–ธ๊ธ‰๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ์„ ๋ฐ›๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
์ด ์ด๋ฉ”์ผ์— ์ง์ ‘ ๋‹ต์žฅํ•˜๊ณ  GitHub์—์„œ ํ™•์ธํ•˜์„ธ์š”.
https://github.com/firebase/firebase-tools/issues/1677#issuecomment-632660684 ,
๋˜๋Š” ๊ตฌ๋… ์ทจ์†Œ
https://github.com/notifications/unsubscribe-auth/ACATB2Q4LV7NXMQFEALNPXLRSZT25ANCNFSM4I27PTFA
.

๋ชจ๋“  66 ๋Œ“๊ธ€

@vladimirdjurdjevic ์˜ฌ๋ ค ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค! ์ด๊ฒƒ์€ ์šฐ๋ฆฌ๊ฐ€ ํ•  ์ผ ๋ชฉ๋ก์— ์žˆ์ง€๋งŒ ์—๋ฎฌ๋ ˆ์ด์…˜ํ•  ์ธ์ฆ ์„œ๋น„์Šค์˜ ์–‘๊ณผ ์ด๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•œ ์ตœ์„ ์˜ ์ „๋žต์€ ์•„์ง ๊ฒฐ์ •ํ•˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค. ํŠน์ • ํ•ญ๋ชฉ(์˜ˆ: ์ต๋ช… ์ธ์ฆ)์€ ์—๋ฎฌ๋ ˆ์ดํŠธํ•˜๊ธฐ๊ฐ€ ๋งค์šฐ ์‰ฌ์šด ๋ฐ˜๋ฉด ๋‹ค๋ฅธ ํ•ญ๋ชฉ(์˜ˆ: SMS ์ธ์ฆ)์€ ๋งค์šฐ ์–ด๋ ต์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์šฐ๋ฆฌ๋Š” ๋‹น์‹ ์ด ์–ธ๊ธ‰ํ•œ ์—”๋“œ ํˆฌ ์—”๋“œ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ํ™œ์„ฑํ™”ํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค!

์งˆ๋ฌธ: ์—๋ฎฌ๋ ˆ์ดํ„ฐ์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  Firebase ์‚ฌ์šฉ์ž๋ฅผ ๋กœ์ปฌ๋กœ ์กฐ๋กฑํ•  ์ˆ˜ ์žˆ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์žˆ๋‹ค๋ฉด ์œ ์šฉํ• ๊นŒ์š”? ๋‹ค์Œ๊ณผ ๊ฐ™์€ ๊ฒƒ:

firebase.auth().setEmulatedUser({
   uid: 'abc123',
   // ...
});

@samtstern setEmulatedUser() ๋ฅผ ํ˜ธ์ถœํ•˜๋ฉด functions.auth.user().onCreate() ์—๋ฎฌ๋ ˆ์ดํŠธ๋œ ํด๋ผ์šฐ๋“œ ๊ธฐ๋Šฅ๋„ ํŠธ๋ฆฌ๊ฑฐ๋ฉ๋‹ˆ๊นŒ? ๊ทธ๋ ‡๋‹ค๋ฉด ๋งค์šฐ ์œ ์šฉํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

@samtstern ์ผ๋ถ€ ํ…Œ์ŠคํŠธ ์‹œ๋‚˜๋ฆฌ์˜ค์—๋Š” ํ™•์‹คํžˆ ๋„์›€์ด ๋˜์ง€๋งŒ ์—ฌ์ „ํžˆ ๊ฐœ๋ฐœ์„ ์œ„ํ•œ ์‹ค์ œ ์ธ์Šคํ„ด์Šค๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๋‚ด ์ƒ๊ฐ์€ ์„œ๋กœ ๋‹ค๋ฅธ ํ™˜๊ฒฝ์— ๋Œ€ํ•ด ์—ฌ๋Ÿฌ Firebase ํ”„๋กœ์ ํŠธ๋ฅผ ๋งŒ๋“œ๋Š” ๊ฒƒ์„ ํ”ผํ•˜๊ณ  ๋กœ์ปฌ์—์„œ(์˜คํ”„๋ผ์ธ์œผ๋กœ) ๊ฐœ๋ฐœํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋˜ ๋‹ค๋ฅธ ์ ‘๊ทผ ๋ฐฉ์‹์€ ์„œ๋น„์Šค์— ๋Œ€ํ•œ ๋‹ค์–‘ํ•œ ํ™˜๊ฒฝ์„ ์ง€์›ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋™์ผํ•œ ํ”„๋กœ์ ํŠธ์—์„œ firestore ๋ฐ auth๋ฅผ ์œ„ํ•ด ๋‹ค๋ฅธ ํ™˜๊ฒฝ์„ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค๋ฉด ๋งŽ์€ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ™˜๊ฒฝ๋ณ„๋กœ ํ”„๋กœ์ ํŠธ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ์ง€๋งŒ ๊ทธ๊ฒƒ์€ ์ •๋ง ๊ณจ์น˜ ์•„ํ”ˆ ์ผ์ž…๋‹ˆ๋‹ค. ๋ชจ๋“  ํ™˜๊ฒฝ ๊ตฌ์„ฑ, ๋ฐ์ดํ„ฐ ๋ณต์ œ ๋“ฑ. ์ด์ƒ์ ์œผ๋กœ๋Š” ํ•˜๋‚˜์˜ Firebase ํ”„๋กœ์ ํŠธ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๊ณ  ์ˆ˜๋™ ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•œ ๋”๋ฏธ ๋ฐ์ดํ„ฐ๊ฐ€ ํ•„์š”ํ•œ ๊ฒฝ์šฐ Firestore์šฉ ์Šคํ…Œ์ด์ง• ํ™˜๊ฒฝ์„ ๋งŒ๋“ค๊ณ  ๊ฑฐ๊ธฐ์— ๋ฐ์ดํ„ฐ๋ฅผ ์—…๋กœ๋“œํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

@noelmansour ์ข‹์€ ์งˆ๋ฌธ์ž…๋‹ˆ๋‹ค! ๊ทธ๋ ‡๊ฒŒ ํ•˜๋Š” ๊ฒƒ์€ ์–ด๋ ต์ง€ ์•Š์Šต๋‹ˆ๋‹ค. signInAsEmulatedUser ๋ฐ signUpAsEmulatedUser ์™€ ๊ฐ™์€ ๋‘ ๊ฐ€์ง€ ๋‹ค๋ฅธ ํ˜ธ์ถœ์ด ํ•„์š”ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ๋‘ ๋ฒˆ์งธ ํ˜ธ์ถœ๋งŒ ํ•จ์ˆ˜๋ฅผ ํŠธ๋ฆฌ๊ฑฐํ•ฉ๋‹ˆ๋‹ค.

@vladimirdjurdjevic ์€ ๋ชจ๋“  ๊ธฐ๋Šฅ์„ ๊ฐ–์ถ˜ ์—๋ฎฌ๋ ˆ์ดํ„ฐ๊ฐ€ ์ตœ๊ณ ๋ผ๋Š” ๋ฐ ์ „์ ์œผ๋กœ ๋™์˜ํ•ฉ๋‹ˆ๋‹ค. ์‚ฌ์šฉ์ž๋ฅผ ๋กœ์ปฌ๋กœ ์„ค์ •ํ•  ์ˆ˜ ์—†์–ด ํ•ด๊ฒฐ๋˜์ง€ ์•Š๋Š” "๊ฐœ๋ฐœ์„ ์œ„ํ•œ ์‹ค์ œ ์ธ์Šคํ„ด์Šค"์—์„œ ํ•„์š”ํ•œ ๊ฒƒ์ด ๋ฌด์—‡์ธ์ง€ ์„ค๋ช…ํ•ด ์ฃผ์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?

์งˆ๋ฌธ: ์—๋ฎฌ๋ ˆ์ดํ„ฐ์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•  Firebase ์‚ฌ์šฉ์ž๋ฅผ ๋กœ์ปฌ๋กœ ์กฐ๋กฑํ•  ์ˆ˜ ์žˆ๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๊ฐ€ ์žˆ๋‹ค๋ฉด ์œ ์šฉํ• ๊นŒ์š”?

์ •๋ง ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋งŽ์€ ๋„์›€์ด ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค.
์ง€๊ธˆ์€ ๋กœ์ปฌ์—์„œ ๋ฌด์–ธ๊ฐ€๋ฅผ ํ…Œ์ŠคํŠธํ•ด์•ผ ํ•  ๋•Œ๋งˆ๋‹ค ๊ธฐ๋ก๋œ ์‚ฌ์šฉ์ž๋ฅผ ๊ฒ€์ฆํ•˜๋Š” ๊ทœ์น™ ํ•จ์ˆ˜๋ฅผ true ์„ค์ •ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ๊ฝค ์•ˆ์ „ํ•˜์ง€ ์•Š์ง€๋งŒ ์—๋ฎฌ๋ ˆ์ดํŠธ๋œ ํ˜„์žฌ ์‚ฌ์šฉ์ž ์—†์ด ํ•  ์ˆ˜ ์žˆ๋Š” ๋” ๊ฐ„๋‹จํ•œ ์ผ์ž…๋‹ˆ๋‹ค.

์˜ˆ, ์ด๊ฒƒ์€ ๋งค์šฐ ์œ ์šฉํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋˜ํ•œ functions.auth.user().onCreate() ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋ฅผ ํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ์ง€๊ธˆ ๊ฐ€์žฅ ์ข‹์€ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์€ ๊ธฐ๋ณธ์ ์œผ๋กœ onCreate ์ „๋‹ฌ๋œ ์ฝœ๋ฐฑ ํ•จ์ˆ˜๋ฅผ ๋‚ด๋ณด๋‚ด๊ณ  ๊ฐ€์งœ user ๊ฐœ์ฒด๋ฅผ ์ œ๊ณตํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ทธ๋Ÿฐ ์ข…๋ฅ˜์˜ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•ด firebase-functions-test๋ฅผ ํ™•์ธํ•˜์‹ญ์‹œ์˜ค.
๋ชจ์˜ ๋ฐ์ดํ„ฐ๋กœ ํ•จ์ˆ˜ ํ•ธ๋“ค๋Ÿฌ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๋ฐ ๋„์›€์ด ๋˜๋Š” ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค.

2019๋…„ 10์›” 13์ผ ์ผ์š”์ผ ์˜ค์ „ 5์‹œ 44๋ถ„ Daniel K. [email protected]์ด ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ผ์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ functions.auth.user().onCreate() ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋ฅผ ํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. NS
์ง€๊ธˆ ๊ฐ€์žฅ ์ข‹์€ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์€ ๊ธฐ๋ณธ์ ์œผ๋กœ ์ฝœ๋ฐฑ ๋‚ด๋ณด๋‚ด๊ธฐ๋ผ๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค.
onCreate์— ์ „๋‹ฌ๋œ ํ•จ์ˆ˜์— ๊ฐ€์งœ ์‚ฌ์šฉ์ž ๊ฐ์ฒด๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

โ€”
๋‹น์‹ ์ด ์–ธ๊ธ‰๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ์„ ๋ฐ›๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
์ด ์ด๋ฉ”์ผ์— ์ง์ ‘ ๋‹ต์žฅํ•˜๊ณ  GitHub์—์„œ ํ™•์ธํ•˜์„ธ์š”.
https://github.com/firebase/firebase-tools/issues/1677?email_source=notifications&email_token=ACATB2QYJLX2LNVDTWJV25TQOMJ4VA5CNFSM4I27PTFKYY3PNVWWK3TUL52HS4DFWEXG43
๋˜๋Š” ๊ตฌ๋… ์ทจ์†Œ
https://github.com/notifications/unsubscribe-auth/ACTB2SO3IR6UB73F4EMZPTQOMJ4VANCNFSM4I27PTFA
.

@samtstern ์‹ค์ œ๋กœ Firestore ์—๋ฎฌ๋ ˆ์ดํ„ฐ์™€ ํ•จ๊ป˜ ์ž‘๋™ํ•ฉ๋‹ˆ๊นŒ? ์ด๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ๋‹ค๋ฅธ ๋ชฉ์ ์„ ์œ„ํ•œ ๊ฒƒ์ด๋ผ๋Š” ์ธ์ƒ์„ ๋ฐ›์•˜์Šต๋‹ˆ๋‹ค.

image
https://firebase.google.com/docs/functions/unit-testing#initializing

๋‚˜๋Š” ํ™•์‹คํžˆ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•œ ์˜จ๋ผ์ธ ๋ชจ๋“œ๋ฅผ ์›ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  "stubbing"์„ ํ†ตํ•ด Firestore ์—๋ฎฌ๋ ˆ์ดํ„ฐ์— ์•ก์„ธ์Šคํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ํ™•์‹คํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

@FredyC ํ•ด๋‹น ๋ฌธ์„œ๋ฅผ ์ง€์ ํ•ด ์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. "๋ชจ๋“œ"๊ฐ€ ํ™œ์„ฑํ™”ํ•  ์ˆ˜ ์žˆ๋Š” ์Šค์œ„์น˜๊ฐ€ ์•„๋‹ˆ๋ผ ์ทจํ•  ์ˆ˜ ์žˆ๋Š” ์ „๋žต์„ ์„ค๋ช…ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์‚ฌ์šฉ๋œ ๋‹จ์–ด๊ฐ€ ํ˜ผ๋ž€์Šค๋Ÿฝ์Šต๋‹ˆ๋‹ค.

๋‹จ์œ„ ํ…Œ์ŠคํŠธ์™€ ํ•จ๊ป˜ Firestore ์—๋ฎฌ๋ ˆ์ดํ„ฐ๋ฅผ ์‹œ์ž‘ํ•˜๋Š” ๊ฒฝ์šฐ ์ฝ”๋“œ๊ฐ€ ํ™•์‹คํžˆ ์—ฐ๊ฒฐ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. FIRESTORE_EMULATOR_HOST ํ™˜๊ฒฝ ๋ณ€์ˆ˜๋ฅผ ์„ค์ •ํ•˜๋ฉด Firebase Admin SDK๊ฐ€ ์ž๋™์œผ๋กœ Firestore ์—๋ฎฌ๋ ˆ์ดํ„ฐ์— ์—ฐ๊ฒฐ๋ฉ๋‹ˆ๋‹ค( firebase emulators:exec ๊ฐ€ ์ž๋™์œผ๋กœ ์ˆ˜ํ–‰).

@samtstern ์—ฌ์ „ํžˆ ์ ์„ ์—ฐ๊ฒฐํ•˜๋Š” ๋ฐ ๋ฌธ์ œ๊ฐ€ ์žˆ์œผ๋ฉฐ ์ด ๋ชจ๋“  ๊ฒƒ์ด functions.auth.user().onCreate() ํ…Œ์ŠคํŠธ์— ์–ด๋–ป๊ฒŒ ๋„์›€์ด ๋ ๊นŒ์š”? ๊ธฐ๋Šฅ์ด ํ”„๋กœ๋•์…˜ ๋ฒ„์ „์ด ์•„๋‹Œ ์—๋ฎฌ๋ ˆ์ดํ„ฐ์— ์—ฐ๊ฒฐ๋˜๋Š” ๊ฒƒ์€ ์ข‹์€๋ฐ Firestore๋งŒ ํ•ด๋‹น๋˜๋Š” ๊ฒƒ์ด๊ฒ ์ฃ ? ํ…Œ์ŠคํŠธ์—์„œ ์‚ฌ์šฉ์ž ์ƒ์„ฑ์„ ํ˜ธ์ถœํ•˜์—ฌ ์‹ค์ œ๋กœ ๊ธฐ๋Šฅ ์ฝ”๋“œ๋ฅผ ์‹œ์ž‘ํ•˜๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ•ฉ๋‹ˆ๊นŒ?

์–ธ๊ธ‰๋œ firebase-functions-test์— makeUserRecord ๋น„๋ฐ€์Šค๋Ÿฌ์šด ๋ฐฉ๋ฒ• ์ด ์žˆ๋Š” ๊ฒƒ ๊ฐ™์ง€๋งŒ ๊ทธ๊ฒƒ์ด ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ๋˜๋Š” ์‹ค์ œ๋กœ ์‚ฌ์šฉํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ๊ทธ๋‹ค์ง€ ์˜๋ฏธ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.

@firebase/testing ํŒจํ‚ค์ง€์—์„œ auth.createUserWithEmailAndPassword() ๋ฅผ ํ˜ธ์ถœํ•˜๋ ค๊ณ  ์‹œ๋„ํ–ˆ์ง€๋งŒ ์œ ํšจํ•˜์ง€ ์•Š์€ API ํ‚ค์— ๋Œ€ํ•ด ๋ถˆํ‰ํ•˜๋ฏ€๋กœ ์˜จ๋ผ์ธ ๋ฒ„์ „์—์„œ๋งŒ ์ž‘๋™ํ•œ๋‹ค๊ณ  ๊ฐ€์ •ํ•ฉ๋‹ˆ๋‹ค.

์–ธ๊ธ‰ํ•œ env ๋ณ€์ˆ˜์— ๋Œ€ํ•ด org ๋ฅผ

๋‚˜๋Š” ๋˜ํ•œ https://github.com/firebase/functions-samples๋ฅผ ํƒ์ƒ‰ํ–ˆ์ง€๋งŒ ๊ฑฐ๊ธฐ์—์„œ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ์˜ ์˜ˆ๋ฅผ ์ฐพ์ง€ ๋ชปํ–ˆ์Šต๋‹ˆ๋‹ค.

์ข€ ์ดํ•ดํ•ด ์ฃผ์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ? :)

ํด๋ผ์šฐ๋“œ ํ•จ์ˆ˜ ์ฝ”๋“œ๊ฐ€ admin.auth().getUserByEmail() ํ˜ธ์ถœ์„ ์‚ฌ์šฉํ•˜๋Š” ๋˜ ๋‹ค๋ฅธ ๊ฒฝ์šฐ๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ๋†€๋ž๊ฒŒ๋„ ์˜ค๋ฅ˜๋กœ ๋๋‚˜์ง€ ์•Š์ง€๋งŒ ๋ฐ˜ํ™˜๋  ์ˆ˜ ์žˆ๋„๋ก ํ•ด๋‹น ์‚ฌ์šฉ์ž๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ๋ชจ๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค. ๋ฌผ๋ก  ์ „์ฒด ๊ด€๋ฆฌ ๋ชจ๋“ˆ์„ ์กฐ๋กฑํ•˜๋Š” ๊ฒƒ์„ ์ œ์™ธํ•˜๊ณ ๋Š” ๋ฏธ์นœ ์ง“์ž…๋‹ˆ๋‹ค. :)

@samtstern ๋Šฆ์–ด์„œ ์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค. ๋‚ด๊ฐ€ ์‹ค์ œ ์ธ์Šคํ„ด์Šค๋ผ๊ณ  ๋งํ•  ๋•Œ ์‹ค์ œ ์ธ์Šคํ„ด์Šค๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. D ์ด์ƒ์ ์œผ๋กœ๋Š” ๊ฐœ๋ฐœ์„ ์œ„ํ•ด ๊ฐ๋„ ํ™˜๊ฒฝ ํŒŒ์ผ์˜ ๊ตฌ์„ฑ์„ ๋ฐ”๊พธ๊ณ  ์•ฑ์ด ์‹ค์ œ API์™€ ํ†ต์‹ ํ•˜๋Š” ๊ฒƒ๊ณผ ๊ฐ™์€ ์ธ์ฆ ๊ธฐ๋Šฅ์„ ๊ณ„์† ๊ตฌํ˜„ํ•˜๊ณ  ์‹ถ์ง€๋งŒ ์‹ค์ œ๋กœ๋Š” ๋‚ด ์ปดํ“จํ„ฐ์—์„œ ์‹คํ–‰๋˜๋Š” ์—๋ฎฌ๋ ˆ์ดํ„ฐ์ž…๋‹ˆ๋‹ค. ์˜คํ”„๋ผ์ธ์œผ๋กœ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด์ œ ์˜ˆ๋ฅผ ๋“ค์–ด SMS๋ฅผ ๋ณด๋‚ผ ๋•Œ์˜ ์–ด๋ ค์›€์„ ์ดํ•ดํ•ฉ๋‹ˆ๋‹ค. ์—๋ฎฌ๋ ˆ์ดํ„ฐ๊ฐ€ ์‹ค์ œ SMS๋ฅผ ๋‚ด ์ „ํ™”๋กœ ๋ณด๋‚ผ ๊ฒƒ์ด๋ผ๊ณ  ๊ธฐ๋Œ€ํ•˜๋Š” ๊ฒƒ์€ ์–ด๋ฆฌ์„์€ ์ผ์ด์ง€๋งŒ, ์ฝ˜์†”์— ์ธ์‡„ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค(์ „์†ก๋  SMS์˜ ๋‚ด์šฉ). ์•„๋งˆ๋„ ์ด๊ฒƒ์— ๋Œ€ํ•œ ๊ฐ€์น˜๋ณด๋‹ค ๋” ๋ฒˆ๊ฑฐ๋กญ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ํ”„๋กœ์ ํŠธ๋‹น ์—ฌ๋Ÿฌ ํ™˜๊ฒฝ์„ ์ง€์›ํ•˜๋Š” ๊ฒƒ๋งŒ์œผ๋กœ๋„ ํ›จ์”ฌ ๋” ๋‚˜์€ ๊ฒฐ๊ณผ๋ฅผ ์–ป์„ ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์„œ๋กœ ๋‹ค๋ฅธ ํ™˜๊ฒฝ์˜ ์—ฌ๋Ÿฌ ํ”„๋กœ์ ํŠธ ๊ฐ„์— ๊ตฌ์„ฑ์„ ๋ณต์ œํ•˜๋Š” ๋ฐ ๋„ˆ๋ฌด ๋งŽ์€ ์‹œ๊ฐ„์ด ๊ฑธ๋ฆฝ๋‹ˆ๋‹ค. ๋˜ํ•œ ์—ฌ๋Ÿฌ Firestore ํ”„๋กœ์ ํŠธ์— ๋ฐ์ดํ„ฐ๋ฅผ ์‹œ๋“œํ•  ์ˆ˜ ์žˆ๋„๋ก ์Šคํฌ๋ฆฝํŠธ์— ๋Œ€ํ•œ ์—ฌ๋Ÿฌ ์„œ๋น„์Šค ๊ณ„์ •์„ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ๋„ ํž˜๋“  ์ผ์ž…๋‹ˆ๋‹ค. ์ด๊ฒƒ์ด ๋‚ด๊ฐ€ ์ „์ฒด Firebase ํ”Œ๋žซํผ์„ ์—๋ฎฌ๋ ˆ์ดํŠธํ•˜๋ฉด ๋ชจ๋“  ๋น„ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๊ณ  ์‹ค์ œ Firebase ํ”„๋กœ์ ํŠธ ํ•˜๋‚˜๋งŒ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ๊ฐ€๋ฅด์นœ ์ด์œ ์ž…๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ํ”„๋กœ์ ํŠธ๋‹น ์—ฌ๋Ÿฌ ํ™˜๊ฒฝ์„ ์ง€์›ํ•˜๋Š” ๊ฒƒ์ด ์ˆ˜์šฉ ๊ฐ€๋Šฅํ•œ ๊ฒฐ๊ณผ๋ฅผ ์ œ๊ณตํ•˜๋Š” ๋” ๋‚˜์€ ์†”๋ฃจ์…˜์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@FredyC ๋ชจ๋“  ํ”ผ๋“œ๋ฐฑ์— ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค! ์ด๊ฒƒ์ด ์–ผ๋งˆ๋‚˜ ํ˜ผ๋ž€์Šค๋Ÿฌ์šธ ์ˆ˜ ์žˆ๋Š”์ง€ ๋ณด๋Š” ๊ฒƒ์€ ์šฐ๋ฆฌ์—๊ฒŒ ์ •๋ง ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค. ์‚ฌ๋žŒ๋“ค์ด ์ธ์ฆ๊ณผ ๊ด€๋ จ๋œ ํ…Œ์ŠคํŠธ์—์„œ ํ•˜๊ณ  ์‹ถ์€ ๊ฒƒ์€ ๋‘ ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค.

  1. ์‹ค์ œ ์‚ฌ์šฉ์ž๋ฅผ ์ƒ์„ฑํ•˜์ง€ ์•Š๊ณ  ๋กœ๊ทธ์ธํ•˜์—ฌ Firestore ๋˜๋Š” Realtime Database์™€ ๊ฐ™์€ ์„œ๋น„์Šค๋ฅผ ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค. ์ง€๊ธˆ ๋‹น์žฅ์€ setEmulatedUser ๊ฒƒ์ด ํ•ด๊ฒฐ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์—๋ฎฌ๋ ˆ์ดํ„ฐ๊ฐ€ ์ˆ˜๋ฝํ•˜์ง€๋งŒ ์ œํ’ˆ์— ์˜ํ•ด ๊ฑฐ๋ถ€๋˜๋Š” ๊ฐ€์งœ ์ธ์ฆ ํ† ํฐ์„ ๋กœ์ปฌ๋กœ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋” ๋งŽ์€ ์•ˆ์ „, ๋” ๋งŽ์€ ๊ฒฉ๋ฆฌ ๋“ฑ
  2. ์‹ค์ œ๋กœ ์ง์ ‘ ์ธ์ฆ์„ ํ…Œ์ŠคํŠธํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—๋Š” ๋ช‡ ๊ฐ€์ง€ ์กฐ๊ฐ์ด ์žˆ์Šต๋‹ˆ๋‹ค.
    NS. ์ธ์ฆ SDK๋ฅผ ๊ฐ€๋ฆฌํ‚ฌ ์ˆ˜ ์žˆ๋„๋ก ํ•„์š”ํ•œ ๋ชจ๋“  API ํ˜ธ์ถœ์— ์‘๋‹ตํ•˜๋Š” ์ธ์ฆ ์—๋ฎฌ๋ ˆ์ดํ„ฐ์ž…๋‹ˆ๋‹ค.
    NS. .onCreate ํ•จ์ˆ˜๊ฐ€ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ํŠธ๋ฆฌ๊ฑฐ๋˜๋„๋ก ํ•ด๋‹น ์—๋ฎฌ๋ ˆ์ดํ„ฐ์™€ ํ•จ์ˆ˜ ์—๋ฎฌ๋ ˆ์ดํ„ฐ ๊ฐ„์˜ ํ†ตํ•ฉ.
    ์”จ. ์˜ค๋Š˜๋‚  Firestore ๋ฐ RTDB์—์„œ์™€ ๊ฐ™์ด admin.auth() ๊ฐ€ ์ธ์ฆ ์—๋ฎฌ๋ ˆ์ดํ„ฐ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋„๋ก ํ•จ์ˆ˜ ์—๋ฎฌ๋ ˆ์ดํ„ฐ ๋‚ด๋ถ€์—์„œ ์ž๋™ ์กฐ๋กฑํ•ฉ๋‹ˆ๋‹ค.

๋ถ„๋ช…ํžˆ (2)๊ฐ€ ์˜ฌ๋ฐ”๋ฅธ ์ด์•ผ๊ธฐ๋ผ๊ณ  ์ƒ๊ฐํ•˜์ง€๋งŒ ๊ตฌํ˜„ ๋ฐ ์œ ์ง€ ๊ด€๋ฆฌ๊ฐ€ ํ›จ์”ฌ ๋” ๊ฐ„๋‹จํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์–ผ๋งˆ๋‚˜ ๋งŽ์€ ์‚ฌ๋žŒ๋“ค์ด (1)์— ๋งŒ์กฑํ• ์ง€ ์ดํ•ดํ•˜๋ ค๊ณ  ๋…ธ๋ ฅํ–ˆ์Šต๋‹ˆ๋‹ค.

@samttern ์•Œ๊ฒ ์Šต๋‹ˆ๋‹ค . ๋‚ด๊ฐ€ ํ‹€๋ ธ๋‹ค๋ฉด ์ •์ •ํ•˜์ง€๋งŒ (1)์€ ์ด๋ฏธ ํ•ด๊ฒฐ๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๊นŒ? ํ…Œ์ŠคํŠธ์—์„œ ๋‹ค์Œ์„ ํ˜ธ์ถœํ•˜๋ฉด Firestore ์—๋ฎฌ๋ ˆ์ดํ„ฐ๊ฐ€ ๋‚˜๋ฅผ ํ•ด๋‹น ์‚ฌ์šฉ์ž๋กœ ์ธ์‹ํ•˜์—ฌ ๋ณด์•ˆ ๊ทœ์น™์— ๋Œ€ํ•ด ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ์Œ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ๋‚˜๋Š” ์‹ค์ œ๋กœ ๊ทธ๊ฒƒ์„ ์•„์ง ์‹œ๋„ํ•˜์ง€ ์•Š์•˜์ง€๋งŒ ์ง€๊ธˆ๊นŒ์ง€๋Š” ์œ ๋งํ•ด ๋ณด์ž…๋‹ˆ๋‹ค :)

  const app = firebase.initializeTestApp({
    projectId,
    auth: {
      uid: 'owner'
    }
  })

(2)๋Š” ํ™•์‹คํžˆ ๋งค์šฐ ์œ ์šฉํ•˜๊ฒŒ ๋“ค๋ฆฌ์ง€๋งŒ ํ™•์‹คํžˆ ๋‹ค๋ฃจ๊ธฐ์—๋Š” ํ›จ์”ฌ ๋” ๋ณต์žกํ•ฉ๋‹ˆ๋‹ค. ์Šฌํ”„๊ฒŒ๋„ ์ „์ฒด ์ œํ’ˆ์— ๋Œ€ํ•œ ๋‚˜์˜ ํ†ต์ฐฐ๋ ฅ์€ ๋„ˆ๋ฌด ์ œํ•œ์ ์ด์–ด์„œ ์—ฌ๊ธฐ์„œ ์œ ์šฉํ•œ ์•„์ด๋””์–ด๋ฅผ ์‹ค์ œ๋กœ ์ œ๊ณตํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

์ฐจ๊ณก์ฐจ๊ณก ์Œ“์•„์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ํ•œ ๋ฒˆ์— ๋ชจ๋“  ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ๋‹ค๋ฃจ๋ ค๊ณ  ํ•˜๋Š” ๋Œ€์‹  ์•Œ๋ ค์ง„ ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ๊ตฌ์ถ•ํ•˜๊ณ  ์ด๋™ ์ค‘์— ์ถ”๊ฐ€ํ•˜์„ธ์š”. ๋‚ด ์ œํ•œ๋œ ์˜๊ฒฌ์œผ๋กœ๋Š” ๊ธฐ๋Šฅ ํŠธ๋ฆฌ๊ฑฐ์™€ ํ•จ๊ป˜ "์‚ฌ์šฉ์ž ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค"๋ฅผ ์—๋ฎฌ๋ ˆ์ดํŠธํ•˜๋Š” ๊ฒƒ์ด ๊ทธ๋ ‡๊ฒŒ ์–ด๋ ต์ง€ ์•Š์€ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

@FredyC ๋‹น์‹ ์€ (1)์ด ํ…Œ์ŠคํŠธ ์Šค์œ„ํŠธ ๋‚ด์—์„œ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ํ•ด๊ฒฐ๋˜์—ˆ๋‹ค๋Š” ๊ฒƒ์ด ๋งž์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ๋‹ค๋ฅธ ์‚ฌ์šฉ ์‚ฌ๋ก€๋Š” ์‹ค์ œ๋กœ ๋กœ์ปฌ ๊ฐœ๋ฐœ์„ ์œ„ํ•ด Android/iOS/์›น ์•ฑ์„ ์—๋ฎฌ๋ ˆ์ดํ„ฐ์— ์ง์ ‘ ์—ฐ๊ฒฐํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด ๊ฒฝ์šฐ @firebase/testing ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

์•Œ ๊ฒ ์–ด์š”. ์†”์งํžˆ @firebase/testing ๋ฅผ ๋ณ„๋„์˜ ์†”๋ฃจ์…˜ ๋Œ€์‹  ํฌ๋กœ์Šค ํ”Œ๋žซํผ์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๋ฉด ์ •๋ง ์ข‹์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํ†ต์‹ ์„ ์—๋ฎฌ๋ ˆ์ดํ„ฐ๋กœ ๋ฆฌ๋””๋ ‰์…˜ํ•˜๋Š” ๊ฒƒ์ด ์–ผ๋งˆ๋‚˜ ์–ด๋ ค์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ? ๋ฐ”๋กœ FIRESTORE_EMULATOR_HOST ์•„๋‹Œ๊ฐ€์š”? ์—๋ฎฌ๋ ˆ์ดํ„ฐ์— ๋‹ค๋ฅธ ์„œ๋น„์Šค๋„ ํฌํ•จ๋œ๋‹ค๋ฉด FIREBASE_EMULATOR_HOST ์™€ ๊ฐ™์€ ๊ฒƒ์ด ๋” ์ ์ ˆํ•  ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

@vladimirdjurdjevic ๋‚ด ์ƒ๊ฐ์—๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ signInWithPhone ๋ฉ”์„œ๋“œ๋ฅผ ์กฐ๋กฑํ•˜์—ฌ ๋™์ž‘์„ ์ œ์–ดํ•  ์ˆ˜ ์žˆ๋„๋ก ์‹ค์ œ๋กœ ์ž‘๋™ํ•˜์ง€ ์•Š์„๊นŒ์š”? ๊ทธ๋Ÿฌ๋ฉด ์ฝ˜์†”์—์„œ ์—๋ฎฌ๋ ˆ์ดํ„ฐ์™€ ์‹œ๋ฎฌ๋ ˆ์ด์…˜๋œ SMS ์ฝ”๋“œ๋ฅผ ๋ฐ›๋Š” ๊ฒƒ์— ๋Œ€ํ•ด ๊ฑฑ์ •ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. :)

๋ฌผ๋ก  Firestore์šฉ ์—๋ฎฌ๋ ˆ์ดํ„ฐ์— ๋Œ€ํ•ด ์ธ์ฆํ•˜๊ณ  ์—ฐ๊ฒฐํ•˜๋Š” ๋ฐฉ๋ฒ•์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ์ด์ „ https://github.com/firebase/firebase-tools/issues/1677#issuecomment -542897671์—์„œ ์„ค๋ช…ํ•œ ๊ฒƒ๊ณผ ๊ฐ™์€ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ณด์•ˆ๋˜์ง€ ์•Š์€ ํ† ํฐ์„ ์ƒ์„ฑํ•˜๋Š” ๊ธฐ๋ณธ ๋ฐฉ๋ฒ•์ด ์žˆ์Šต๋‹ˆ๋‹ค. https://github.com/firebase/firebase-js-sdk/blob/master/packages/testing/src/api/index.ts#L64. ๊ทธ๊ฒƒ์ด ํšจ๊ณผ๊ฐ€ ์žˆ๋Š”์ง€ ํ™•์‹คํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋ฌผ๋ก  ์ œ3์ž ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์กฐ๋กฑํ•˜๋Š” ๊ฒƒ์ด ํ•ญ์ƒ ์‰ฌ์šด ๊ฒƒ์€ ์•„๋‹ˆ์ง€๋งŒ ์ผ๋‹จ ์•Œ์•„๋‚ด๋ฉด ํ›Œ๋ฅญํ•œ ๊ฒฐ๊ณผ๋ฅผ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฒฐ๊ตญ, ์ผ๋ฐ˜์ ์œผ๋กœ ๋” ์‰ฝ๊ฒŒ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ์ผ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋กœ ์ถ”์ถœ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋˜ํ•œ ์ด๋Ÿฌํ•œ signIn ๋ฉ”์„œ๋“œ๋Š” ์ ์ ˆํ•œ ํ…Œ์ŠคํŠธ์—์„œ๋„ ์ฒ˜๋ฆฌํ•ด์•ผ ํ•˜๋Š” ๋งŽ์€ ์˜ค๋ฅ˜ ์ฝ”๋“œ๋ฅผ ๋˜์งˆ ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์กฐ๋กฑ์œผ๋กœ๋„ ์‰ฝ๊ฒŒ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@samtstern setEmulatedUser ์™€ ๊ฐ™์€ ์ฃผ์ œ๋กœ firebase.auth() ๋„ค์ž„์ŠคํŽ˜์ด์Šค ์ปจํ…์ŠคํŠธ๋ฅผ ํ™•์žฅํ•˜๋Š” ๊ฒƒ์€ ๊ธฐ์กด ์—๋ฎฌ๋ ˆ์ด์…˜ ์ „๋žต์— ๋ฐ˜ํŒจํ„ด์ฒ˜๋Ÿผ ๋ณด์ž…๋‹ˆ๋‹ค. ์ด ๊ถŒ์žฅ ์‚ฌํ•ญ์€ ํŒจํ‚ค์ง€ ์ธก๋ฉด์˜ ํ™•์žฅ ์šฉ์ด์„ฑ์˜ ์˜ํ–ฅ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

๋‹ค๋ฅธ ์—๋ฎฌ๋ ˆ์ดํ„ฐ์™€ ํ•จ๊ป˜ ๋ณ„๋„์˜ ์ธ์ฆ ์„œ๋น„์Šค ๊ณ„์ธต์ด HTTP๋ฅผ ํ†ตํ•ด ์‹œ์ž‘๋  ๊ฒƒ์œผ๋กœ ์˜ˆ์ƒํ•˜๊ณ  ํด๋ผ์ด์–ธํŠธ ์ธก ๊ตฌ์„ฑ์ด ๊ธฐ์กด API ํ‘œ๋ฉด์„ ๋ฆฌ๋””๋ ‰์…˜ํ•˜์—ฌ ํ™œ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š” ์˜คํžˆ๋ ค ํŽธ์‹ฌ AuthN ์ผ€์ด์Šค๊ฐ€ ์‚ฌ์šฉ์ž ์ด๋ฆ„/๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ํ†ตํ•ด ๊ธฐ๋ณธ ์‚ฌ์šฉ์ž์— ๋Œ€ํ•ด CRUD๋ฅผ ์ตœ์†Œํ•œ์œผ๋กœ ์ง€์›ํ•˜๋Š” Admin ๋ฐ Client API๋กœ ์˜ค๋ฅ˜๋ฅผ ๋ฐ˜ํ™˜ํ•˜๊ธฐ๋ฅผ ์›ํ•ฉ๋‹ˆ๋‹ค. ์  ์žฅ, Admin๊ณผ signInWithCustomToken ์—์„œ Custom Token ์ง€์›์œผ๋กœ ์‹œ์ž‘ํ•˜๋Š” ๊ฒƒ์กฐ์ฐจ ์ •๋ง ๋ฉ€๋ฆฌ ๊ฐˆ ๊ฒƒ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ๋ฌธ์„œ์— ๊ฒŒ์‹œ๋œ API ์ง€์› ๋งคํŠธ๋ฆญ์Šค๋กœ ๋‚ฎ์€ ๋งค๋‹ฌ๋ฆฐ ๊ณผ์ผ์„ ๊ตฌํ˜„ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

@FredyC ๋Š” ํ†ตํ•ฉ ์ธ์ฆ ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•œ ํ˜„์žฌ ์ „๋žต์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ฝ”๋“œ์—์„œ ์กฐ๊ฑด๋ถ€๋กœ @firebase/testing ๋ฅผ ๊ฐ€์ ธ์™€ ์‚ฌ์šฉ์ž ์ •์˜ initializeTestApp ํ˜ธ์ถœ๋กœ ๋ผ์šฐํŒ…ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด ์ž‘์—…์€ ํ”„๋กœ์ ํŠธ ํŒ€์˜ ๋นŒ๋“œ ์‹œ ํŒจํ‚ค์ง€ ์ œ์™ธ๋ฅผ ๊ฐ•์กฐํ•˜๊ณ  ๋‘ ํŒจํ‚ค์ง€ API( initializeTestApp ๋ฐ firestore.settings / functions.useFunctionsEmulator )์— ์—๋ฎฌ๋ ˆ์ดํ„ฐ ๋ฆฌ๋””๋ ‰์…˜ ๊ตฌ์„ฑ์„ ํ™•์‚ฐํ•ฉ๋‹ˆ๋‹ค.

ํ–‰์„ฑ์„ ํ•ดํ‚น!

ํ†ตํ•ฉ ์ธ์ฆ ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•œ ํ˜„์žฌ ์ „๋žต์€ ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ์ฝ”๋“œ์—์„œ ์กฐ๊ฑด๋ถ€๋กœ @firebase/testing ๋ฅผ ๊ฐ€์ ธ์™€ ์‚ฌ์šฉ์ž ์ •์˜ initializeTestApp ํ˜ธ์ถœ๋กœ ๋ผ์šฐํŒ…ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์Œ, ํ…Œ์ŠคํŠธ ๋‚ด์—์„œ ๊ทธ ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ํŠธ๋ฆญ์€ ์ผ๋ฐ˜ initializeApp ํ•จ์ˆ˜๋ฅผ ๊ฐ€์ ธ์˜ค๋Š” index.ts ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์—๋ฎฌ๋ ˆ์ดํ„ฐ๊ฐ€ ์‹œ์ž‘๋  ๋•Œ ํ˜ธ์ถœ๋˜์ง€๋งŒ ํ…Œ์ŠคํŠธ๊ฐ€ ์‹คํ–‰๋  ๋•Œ๋Š” ๋‹ค๋ฅธ ํ”„๋กœ์„ธ์Šค์ด๋ฉฐ ์„œ๋กœ ์ถฉ๋Œํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์‹ค์ œ๋กœ ์กฐ๊ฑด๋ถ€ ์ˆ˜์ž…์˜ ๋ถ€๋‹ด์ด ์—†์Šต๋‹ˆ๋‹ค.

๋ฌผ๋ก  ์ด๊ฒƒ์€ ์ธ์ฆ ํ…Œ์ŠคํŠธ์™€ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ…Œ์ŠคํŠธ ๋Ÿฌ๋„ˆ๊ฐ€ ์•ฑ ์ฝ”๋“œ์™€ ํ”„๋กœ์„ธ์Šค๋ฅผ ๊ณต์œ ํ•˜๋Š” ์›น ์•ฑ. ๊ทธ๋Ÿฌ๋‚˜ ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ผ๋ฐ˜์ ์œผ๋กœ ์ „์ฒด ์•ฑ์„ ํ…Œ์ŠคํŠธ๋กœ ๊ฐ€์ ธ์˜ค์ง€ ์•Š์Šต๋‹ˆ๋‹ค. initializeApp ๋Š” ํ…Œ์ŠคํŠธ์™€ ๊ด€๋ จ์ด ์—†๊ณ  ์ „ํ˜€ ๊ฐ€์ ธ์˜ค์ง€ ์•Š๋Š” ์ผ๋ถ€ ์ฝ”๋“œ์—์„œ ์ˆ˜ํ–‰๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

@FredyC ๋‹จ์œ„ ํ…Œ์ŠคํŠธ์— ๋Œ€ํ•ด ๋ฌธ์„œํ™”๋œ ์‚ฌ์šฉ๋ฒ•์— ๋™์˜ํ–ˆ์Šต๋‹ˆ๋‹ค. API๊ฐ€ ๋ถ„๊ธฐ๋˜๊ณ  ๋™์  ๊ฐ€์ ธ์˜ค๊ธฐ๊ฐ€ ๋ฌธ์„œํ™”๋œ ๋งต์—์„œ ๋ฒ—์–ด๋‚˜๋Š” ์ „์ฒด ์•ฑ ์‹œ๋‚˜๋ฆฌ์˜ค์— ๋Œ€ํ•ด ์ด์•ผ๊ธฐํ•˜๊ณ  ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

Honestly, it would be kinda superb if @firebase/testing could be used cross-platform instead of having separate solutions ๋Œ€ํ•œ ์ €์ž‘์ž ํ‘œ์‹œ๋ฅผ ํ•˜๊ณ  ์‹ถ์—ˆ์Šต๋‹ˆ๋‹ค. ๋””์ง€ํ„ธ ํ•˜์ดํŒŒ์ด๋ธŒ

@FredyC ๋ชจ๋“  ํ”ผ๋“œ๋ฐฑ์— ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค! ์ด๊ฒƒ์ด ์–ผ๋งˆ๋‚˜ ํ˜ผ๋ž€์Šค๋Ÿฌ์šธ ์ˆ˜ ์žˆ๋Š”์ง€ ๋ณด๋Š” ๊ฒƒ์€ ์šฐ๋ฆฌ์—๊ฒŒ ์ •๋ง ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค. ์‚ฌ๋žŒ๋“ค์ด ์ธ์ฆ๊ณผ ๊ด€๋ จ๋œ ํ…Œ์ŠคํŠธ์—์„œ ํ•˜๊ณ  ์‹ถ์€ ๊ฒƒ์€ ๋‘ ๊ฐ€์ง€์ž…๋‹ˆ๋‹ค.

  1. ์‹ค์ œ ์‚ฌ์šฉ์ž๋ฅผ ์ƒ์„ฑํ•˜์ง€ ์•Š๊ณ  ๋กœ๊ทธ์ธํ•˜์—ฌ Firestore ๋˜๋Š” Realtime Database์™€ ๊ฐ™์€ ์„œ๋น„์Šค๋ฅผ ์‚ฌ์šฉํ•˜์‹ญ์‹œ์˜ค. ์ง€๊ธˆ ๋‹น์žฅ์€ setEmulatedUser ๊ฒƒ์ด ํ•ด๊ฒฐ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์—๋ฎฌ๋ ˆ์ดํ„ฐ๊ฐ€ ์ˆ˜๋ฝํ•˜์ง€๋งŒ ์ œํ’ˆ์— ์˜ํ•ด ๊ฑฐ๋ถ€๋˜๋Š” ๊ฐ€์งœ ์ธ์ฆ ํ† ํฐ์„ ๋กœ์ปฌ๋กœ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋” ๋งŽ์€ ์•ˆ์ „, ๋” ๋งŽ์€ ๊ฒฉ๋ฆฌ ๋“ฑ
  2. ์‹ค์ œ๋กœ ์ง์ ‘ ์ธ์ฆ์„ ํ…Œ์ŠคํŠธํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—๋Š” ๋ช‡ ๊ฐ€์ง€ ์กฐ๊ฐ์ด ์žˆ์Šต๋‹ˆ๋‹ค.
    NS. ์ธ์ฆ SDK๋ฅผ ๊ฐ€๋ฆฌํ‚ฌ ์ˆ˜ ์žˆ๋„๋ก ํ•„์š”ํ•œ ๋ชจ๋“  API ํ˜ธ์ถœ์— ์‘๋‹ตํ•˜๋Š” ์ธ์ฆ ์—๋ฎฌ๋ ˆ์ดํ„ฐ์ž…๋‹ˆ๋‹ค.
    NS. .onCreate ํ•จ์ˆ˜๊ฐ€ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ํŠธ๋ฆฌ๊ฑฐ๋˜๋„๋ก ํ•ด๋‹น ์—๋ฎฌ๋ ˆ์ดํ„ฐ์™€ ํ•จ์ˆ˜ ์—๋ฎฌ๋ ˆ์ดํ„ฐ ๊ฐ„์˜ ํ†ตํ•ฉ.
    ์”จ. ์˜ค๋Š˜๋‚  Firestore ๋ฐ RTDB์—์„œ์™€ ๊ฐ™์ด admin.auth() ๊ฐ€ ์ธ์ฆ ์—๋ฎฌ๋ ˆ์ดํ„ฐ๋ฅผ ๊ฐ€๋ฆฌํ‚ค๋„๋ก ํ•จ์ˆ˜ ์—๋ฎฌ๋ ˆ์ดํ„ฐ ๋‚ด๋ถ€์—์„œ ์ž๋™ ์กฐ๋กฑํ•ฉ๋‹ˆ๋‹ค.

๋ถ„๋ช…ํžˆ (2)๊ฐ€ ์˜ฌ๋ฐ”๋ฅธ ์ด์•ผ๊ธฐ๋ผ๊ณ  ์ƒ๊ฐํ•˜์ง€๋งŒ ๊ตฌํ˜„ ๋ฐ ์œ ์ง€ ๊ด€๋ฆฌ๊ฐ€ ํ›จ์”ฌ ๋” ๊ฐ„๋‹จํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์–ผ๋งˆ๋‚˜ ๋งŽ์€ ์‚ฌ๋žŒ๋“ค์ด (1)์— ๋งŒ์กฑํ• ์ง€ ์ดํ•ดํ•˜๋ ค๊ณ  ๋…ธ๋ ฅํ–ˆ์Šต๋‹ˆ๋‹ค.

@samtstern ์šฐ์„  ์ด๋Ÿฐ ์ข…๋ฅ˜์˜ ์—๋ฎฌ๋ ˆ์ด์…˜์„ โค๏ธํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š” ์•„๋‹ˆ์˜ค๋ฅผ ๋ณผ ๊ฒƒ์ž…๋‹ˆ๋‹ค. 1 e2 ํ…Œ์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๋ฐ ๋งค์šฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค. ํ˜„์žฌ ํ˜ธ์ŠคํŒ…, ๊ทœ์น™, Firestore ๋ฐ ๊ธฐ๋Šฅ์— ์—๋ฎฌ๋ ˆ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๋™์•ˆ ์ธ์ฆ์„ ์œ„ํ•ด ์‹ค์ œ ์ธ์Šคํ„ด์Šค๋ฅผ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

firebase.initializeTestApp์—์„œ์™€ ๋™์ผํ•œ ๋ฐฉ์‹์œผ๋กœ setEmulatedUser๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์‚ฌ์šฉ์ž๋ฅผ ์กฐ๋กฑํ•˜๋Š” ๊ฒƒ์ด ๊ฐ€๋Šฅํ•ด์•ผ ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด ์‚ฌ์šฉ์ž ์ •์˜ ํ† ํฐ ๋ฐ ๊ธฐํƒ€ ์‚ฌ์šฉ์ž ๊ด€๋ จ ๋ฐ์ดํ„ฐ๋ฅผ ์ œ์ถœํ•  ์ˆ˜ ์žˆ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

firebase.auth().signInWithCredential(credential) ๋กœ ํด๋ผ์ด์–ธํŠธ ์•ฑ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ƒ˜ํ”Œ ์ž๊ฒฉ ์ฆ๋ช…์„ ์–ป์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ๋ฌธ์ œ๋ฅผ ์ œ๊ธฐํ•ด ์ฃผ์‹  @vladimirdjurdjevic ์—๊ฒŒ ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค! ์šฐ๋ฆฌ๋Š” ์ด๋ฏธ ๊ฑฐ์˜ 1๋…„ ๋™์•ˆ ์†”๋ฃจ์…˜์„ ์ฐพ๊ณ  ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๋Š” ์„ธ ๊ฐ€์ง€์— ๋Œ€ํ•œ ์‹ค์ œ ์—๋ฎฌ๋ ˆ์ดํ„ฐ๋ฅผ ๋ณด๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

  1. e2e๋Š” ์ „์ฒด ์•ฑ์— ๋Œ€ํ•ด ํ…Œ์ŠคํŠธํ•˜๋ฏ€๋กœ @vladimirdjurdjevic์ด ๋งํ•œ ๊ฒƒ์ฒ˜๋Ÿผ ๋‹ค๋ฅธ ํ™˜๊ฒฝ์„ ๋งŒ๋“ค ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.
  2. API๊ฐ€ ํ˜ธ์ถœ๋˜๊ณ  Firebase์—์„œ ์‚ฌ์šฉ์ž์˜ ์œ ํšจ์„ฑ์„ ๊ฒ€์‚ฌํ•ด์•ผ ํ•˜๋Š” ๋ฐฑ์—”๋“œ์— ๋Œ€ํ•œ ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ์ž…๋‹ˆ๋‹ค.
  3. ๋ชจ๋“  ๊ฐœ๋ฐœ์ž๋Š” ๊ฐœ๋ฐœ ์ค‘์— ์ค‘์•™ Firebase ํ™˜๊ฒฝ์„ ์‚ฌ์šฉํ•˜๋ฏ€๋กœ ๋งŽ์€ ์ถฉ๋Œ์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ๋ฌผ๋ก  ๋ชจ๋“  ๊ฐœ๋ฐœ์ž๋Š” ์ž์‹ ์˜ Firebase ํ”„๋กœ์ ํŠธ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์ง€๋งŒ ์—ฌ์ „ํžˆ Firebase ๋Œ€์‹œ๋ณด๋“œ์—์„œ ํ…Œ์ŠคํŠธ ์‚ฌ์šฉ์ž๋ฅผ ๊ด€๋ฆฌํ•ด์•ผ ํ•˜๋ฏ€๋กœ ์ด์ƒ์ ์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ์‹ค์ œ ์—๋ฎฌ๋ ˆ์ดํ„ฐ๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์˜ค๋Š˜๋‚ ์—๋Š” ๋ถˆ๊ฐ€๋Šฅํ–ˆ๋˜ ์•ฑ์„ ์˜คํ”„๋ผ์ธ์—์„œ ๊ฐœ๋ฐœํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

๋‹น์‹ ์ด ๊ณง ์šฐ๋ฆฌ๋ฅผ ์œ„ํ•ด ๋ฌด์–ธ๊ฐ€๋ฅผ ์ถœ์‹œํ•˜๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค. ๊ทธ๊ฒƒ์€ ๋‹น์‹ ์˜ ์ œํ’ˆ์„ ๋” ๊ฐ€์น˜ ์žˆ๊ฒŒ ๋งŒ๋“ค ๊ฒƒ์ž…๋‹ˆ๋‹ค! ์ด๋Ÿฌํ•œ ์„œ๋น„์Šค์—์„œ๋Š” ๊ฐœ๋ฐœ์ž ์ƒ์‚ฐ์„ฑ์ด ๋งค์šฐ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค!

์ด๊ฒƒ์€ ๋งŽ์€ ์‚ฌ๋žŒ๋“ค์˜ ์œ„์‹œ๋ฆฌ์ŠคํŠธ์— ์žˆ๋Š” ๊ธฐ๋Šฅ์ธ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. Firebase ์ธ์ฆ์€ ํ˜„์žฌ ๊ฐ€๊ฒฉ ์ธก๋ฉด์—์„œ 1์œ„ IDaaS์ธ ๊ฒƒ ๊ฐ™์œผ๋ฏ€๋กœ Cloud Functions๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋กœ์ปฌ์—์„œ ๊ฐœ๋ฐœํ•  ์ˆ˜ ์—†๋‹ค๋Š” ๊ฒƒ์€ ์ •๋ง ๊ณ ํ†ต์Šค๋Ÿฌ์šด ์ผ์ž…๋‹ˆ๋‹ค. FB ํŒ€์— ๊ณง ์—…๋ฐ์ดํŠธ๊ฐ€ ์žˆ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค! ๐Ÿ™

ํŽธ์ง‘: ์ด ์Šค๋ ˆ๋“œ๊ฐ€ ๋ฌธ์ œ์— ๋ฌปํ˜€ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— @ firebase -ops์—์„œ

๋‚˜๋Š” ๋˜ํ•œ์ด ์˜ค๋ฅ˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค ... ์ธ์ฆ ์—๋ฎฌ๋ ˆ์ดํ„ฐ๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š๊ฑฐ๋‚˜ ์‹คํ–‰๋˜๊ณ  ์žˆ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๊ธฐ๋Šฅ์ด ๋ฌด์‹œ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ๋‹ค์Œ ์ฝ”๋“œ์— ์˜ํ•ด ํŠธ๋ฆฌ๊ฑฐ๋ฉ๋‹ˆ๋‹ค.

function.auth.user().onDelete()

์ด๊ฒƒ์— ๋Œ€ํ•œ ๋ชจ๋“  ์ •๋ณด ...

@๋„๋ฏธ๋‹ˆํฌํด๋””

๋‚˜๋Š” ๋‹น์‹ ์˜ ์š”์ ์— ๋™์˜ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ ๋™์•ˆ ๋„์›€์ด ๋  ์ˆ˜ ์žˆ๋Š” ํ•œ ๊ฐ€์ง€ ํŒ:

๋ฌผ๋ก  ๋ชจ๋“  ๊ฐœ๋ฐœ์ž๋Š” ์ž์‹ ์˜ Firebase ํ”„๋กœ์ ํŠธ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์ง€๋งŒ ์—ฌ์ „ํžˆ Firebase ๋Œ€์‹œ๋ณด๋“œ์—์„œ ํ…Œ์ŠคํŠธ ์‚ฌ์šฉ์ž๋ฅผ ๊ด€๋ฆฌํ•ด์•ผ ํ•˜๋ฏ€๋กœ ์ด์ƒ์ ์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

Firebase ๊ด€๋ฆฌ SDK(์˜ˆ: auth().createUser )๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๋ฐฉ์‹์œผ๋กœ ์‚ฌ์šฉ์ž๋ฅผ ์‹œ๋“œํ•˜๊ณ  ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. https://firebase.google.com/docs/auth/admin/manage-users ๋„

์ด ์Šค๋ ˆ๋“œ๋ฅผ ์ฝ์€ ํ›„ ์—ฌ๊ธฐ ์‚ฌ๋žŒ๋“ค์ด Foundry๋ฅผ ์œ ์šฉํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.

์ €๋Š” Foundry์˜ ๊ณต๋™ ์„ค๋ฆฝ์ž ์ค‘ ํ•œ ๋ช…์ž…๋‹ˆ๋‹ค. Foundry๋Š” Firebase Cloud Functions๋ฅผ ๊ฐ€์ ธ์™€์„œ ์ฝ”๋“œ๋ฅผ ์ง์ ‘ ์‹คํ–‰ํ•˜๋Š” ๊ฐœ๋ฐœ ํ™˜๊ฒฝ ์—ญํ• ์„ ํ•˜๋Š” ๋‹น์‚ฌ ์„œ๋ฒ„์— ํ”„๋กœ๋•์…˜ Firebase ์•ฑ์˜ ์‚ฌ๋ณธ์„ ์ƒ์„ฑํ•˜๋Š” CLI ๋„๊ตฌ์ž…๋‹ˆ๋‹ค. ๊ตฌ์„ฑ์ด ํ•„์š”ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

Foundry๋Š” ์†Œ์Šค ์ฝ”๋“œ ํŒŒ์ผ์„ ๊ฐ์‹œํ•˜๊ณ  ์ฝ”๋“œ๋ฅผ ๋กœ์ปฌ์— ์ €์žฅํ•  ๋•Œ๋งˆ๋‹ค ์„œ๋ฒ„์—์„œ ์‹คํ–‰ํ•˜๊ณ  ๋‹จ ๋ช‡ ์ดˆ ์•ˆ์— ๊ฒฐ๊ณผ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ๋ชจ๋“  ๊ฒƒ์ด ๋งค์šฐ ๋น ๋ฆ…๋‹ˆ๋‹ค.
๊ฐœ๋ฐœ ์ค‘์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก YAML ํŒŒ์ผ์„ ํ†ตํ•ด ํ”„๋กœ๋•์…˜ ์•ฑ์—์„œ ๋ณต์‚ฌํ•ด์•ผ ํ•˜๋Š” Firestore, RealtimeDB ๋ฐ ์ธ์ฆ ์‚ฌ์šฉ์ž ๋ฐ์ดํ„ฐ๋ฅผ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค.

 users:
      - getFromProd: 5 # Copy first 5 users from your Firebase project
      - getFromProd: ['id-1', 'id-2'] # Copy users with the specified IDs from your Firebase project

 # Copy first 3 documents from production from the collection 'userWorkspaces'
 # also add a custom document with id 'new-user-workspace' with a new data
 # format that you want to use
 firestore:
     - collection: userWorkspaces
       docs:
         - getFromProd: 3
         - id: new-user-workspace
           data: {"newDataFormat": 42}

๋˜ํ•œ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•  ๋•Œ ํด๋ผ์šฐ๋“œ ๊ธฐ๋Šฅ์„ ํŠธ๋ฆฌ๊ฑฐํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ง€์ •ํ•ฉ๋‹ˆ๋‹ค. ํด๋ผ์šฐ๋“œ ๊ธฐ๋Šฅ์— ๋Œ€ํ•œ REPL๊ณผ ์œ ์‚ฌํ•˜๊ฒŒ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋ ‡๊ฒŒ ํ•˜๋ฉด ํด๋ผ์šฐ๋“œ ๊ธฐ๋Šฅ์ด ์ผ๋‹จ ๋ฐฐํฌ๋˜๋ฉด ํ”„๋กœ๋•์…˜ ๋ฐ์ดํ„ฐ์™€ ํ”„๋กœ๋•์…˜ ํ™˜๊ฒฝ์—์„œ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ์ž‘๋™ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ํ•ญ์ƒ ํ™•์‹ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๋˜ํ•œ ํด๋ผ์šฐ๋“œ ๊ธฐ๋Šฅ์€ ๋ฐฐํฌ๋œ ๊ฒƒ์ฒ˜๋Ÿผ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค.

์ด๋Ÿฌํ•œ ๊ฐœ๋ฐœ ํ™˜๊ฒฝ์€ ์„ธ์…˜์„ ์‹œ์ž‘ํ•˜๋ฉด ์ž„์‹œ๋กœ ์ƒ์„ฑ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ํŒ€์˜ ๋ชจ๋“  ์‚ฌ๋žŒ์€ ์ž์‹ ์˜ ํ™˜๊ฒฝ์—์„œ ์ž‘์—…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋‚˜๋Š” ์—ฌ๊ธฐ์—์„œ ํ† ๋ก ์„ ์ŠคํŒธํ•˜๊ณ  ์‹ถ์ง€ ์•Š์œผ๋ฏ€๋กœ ์งˆ๋ฌธ์ด ์žˆ์œผ์‹œ๋ฉด ์–ธ์ œ๋“ ์ง€
์ด๋ฉ”์ผ์„ ๋ณด๋‚ด์ฃผ์‹œ๋ฉด ํ”„๋กœ์ ํŠธ์— Foundry๋ฅผ ์„ค์ •ํ•˜๋Š” ๋ฐ ๋„์›€์„ ๋“œ๋ฆฌ๊ฒ ์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ๊ท€ํ•˜๊ฐ€ ์„ค๋ช…ํ•œ ๋ฐฉ๋ฒ•๊ณผ ํ™ˆํŽ˜์ด์ง€์—์„œ ์ฝ์€ ๋‚ด์šฉ์— ๋”ฐ๋ฅด๋ฉด ํ•ด๋‹น ์„œ๋น„์Šค๋Š” ํด๋ผ์šฐ๋“œ ๊ธฐ๋ฐ˜์ž…๋‹ˆ๋‹ค.
Firebase ์—๋ฎฌ๋ ˆ์ดํ„ฐ๋Š” ๋Œ€์‹  ์˜คํ”„๋ผ์ธ์—์„œ๋„ ์ž‘๋™ํ•˜๋ฏ€๋กœ ์ž๋™ ํ…Œ์ŠคํŠธ์— ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

@samtstern ์ด ๋ฌธ์ œ/๊ธฐ๋Šฅ์— ๋Œ€ํ•œ ์ง„ํ–‰ ์ƒํ™ฉ์ด๋‚˜ ๋‹ค๋ฅธ ์†”๋ฃจ์…˜์ด ์žˆ์Šต๋‹ˆ๊นŒ? ๋กœ์ปฌ์—์„œ ์ˆ˜๋™ ํ…Œ์ŠคํŠธ๋ฅผ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ๋„๋ก ํด๋ผ์šฐ๋“œ Firestore ์—๋ฎฌ๋ ˆ์ดํ„ฐ์™€ ํ•จ๊ป˜ ์ž‘์—…ํ•˜๋ ค๋ฉด (1) setEmulatedUser๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค. ๋˜ ๋‹ค๋ฅธ ์˜ต์…˜์€ ์—๋ฎฌ๋ ˆ์ดํ„ฐ๊ฐ€ ์‹œ์ž‘๋  ๋•Œ ์‚ฌ์šฉ์ž ID๋ฅผ ์„ค์ •ํ•˜๋Š” ๋ช…๋ น์ค„ ์ธ์ˆ˜๋ฅผ ๊ฐ–๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๋Ÿฐ ์‹์œผ๋กœ ์—๋ฎฌ๋ ˆ์ดํ„ฐ๋Š” ์‹œ์ž‘ ์ค‘์— ์ „๋‹ฌ๋œ ์‚ฌ์šฉ์ž ID๋กœ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ์ด๋Ÿฌํ•œ ๋ฐฉ์‹์œผ๋กœ ๊ทœ์น™์„ ๋กœ์ปฌ์—์„œ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ท€ํ•˜์˜ ์˜๊ฒฌ์— ๋”ฐ๋ผ: 2019๋…„ 10์›” 17์ผ
_๋‚˜๋Š” ๋ถ„๋ช…ํžˆ (2)๊ฐ€ ๋งž๋Š” ์ด์•ผ๊ธฐ๋ผ๊ณ  ์ƒ๊ฐํ•˜์ง€๋งŒ ๊ตฌํ˜„ ๋ฐ ์œ ์ง€ ๊ด€๋ฆฌ๊ฐ€ ํ›จ์”ฌ ๋” ๊ฐ„๋‹จํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์–ผ๋งˆ๋‚˜ ๋งŽ์€ ์‚ฌ๋žŒ๋“ค์ด (1)์— ๋งŒ์กฑํ• ์ง€ ์ดํ•ดํ•˜๋ ค๊ณ  ๋…ธ๋ ฅํ–ˆ์Šต๋‹ˆ๋‹ค.

(1) ์‹ค์ œ ์‚ฌ์šฉ์ž๋ฅผ ์ƒ์„ฑํ•˜์ง€ ์•Š๊ณ  Firestore ๋˜๋Š” Realtime Database์™€ ๊ฐ™์€ ์„œ๋น„์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ๋กœ๊ทธ์ธํ•ฉ๋‹ˆ๋‹ค. ๋ฐ”๋กœ ์ง€๊ธˆ ๊ทธ๊ฒƒ์ด setEmulatedUser์™€ ๊ฐ™์€ ๊ฒƒ์ด ํ•ด๊ฒฐ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์—๋ฎฌ๋ ˆ์ดํ„ฐ๊ฐ€ ์ˆ˜๋ฝํ•˜์ง€๋งŒ ์ œํ’ˆ์— ์˜ํ•ด ๊ฑฐ๋ถ€๋˜๋Š” ๊ฐ€์งœ ์ธ์ฆ ํ† ํฐ์„ ๋กœ์ปฌ๋กœ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋” ๋งŽ์€ ์•ˆ์ „, ๋” ๋งŽ์€ ๊ฒฉ๋ฆฌ ๋“ฑ_

์šฐ๋ฆฌ๋Š” ์™„์ „ํ•œ ์ธ์ฆ ์—๋ฎฌ๋ ˆ์ดํ„ฐ๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ์—ด์‹ฌํžˆ ๋…ธ๋ ฅํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
๋ชจ๋‘๊ฐ€ ์›ํ•˜๋Š”. ์ง€๊ธˆ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ๋Š” ์ผ์ •์€ ์—†์ง€๋งŒ ์šฐ์„  ์ˆœ์œ„๊ฐ€ ๋†’์Šต๋‹ˆ๋‹ค.
์šฐ๋ฆฌ๋ฅผ ์œ„ํ•ด.

2020๋…„ 5์›” 22์ผ ๊ธˆ์š”์ผ ์˜ค์ „ 8์‹œ 12๋ถ„์— ChuckB [email protected]์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ž‘์„ฑํ–ˆ์Šต๋‹ˆ๋‹ค.

@samtstern https://github.com/samtstern ์ง„ํ–‰ ์ƒํ™ฉ ๋˜๋Š” ๊ธฐํƒ€
์ด ๋ฌธ์ œ/๊ธฐ๋Šฅ์— ๋Œ€ํ•œ ์†”๋ฃจ์…˜์€ ๋ฌด์—‡์ž…๋‹ˆ๊นŒ? ์ž‘์—…ํ•˜๋ ค๋ฉด (1) setEmulatedUser๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.
ํด๋ผ์šฐ๋“œ Firestore ์—๋ฎฌ๋ ˆ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋กœ์ปฌ์—์„œ ์ˆ˜๋™ ํ…Œ์ŠคํŠธ๋ฅผ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ท€ํ•˜์˜ ์˜๊ฒฌ์— ๋”ฐ๋ผ: 2019๋…„ 10์›” 17์ผ
_ ๋‚˜๋Š” ๋ถ„๋ช…ํžˆ (2)๊ฐ€ ๋งž๋Š” ์ด์•ผ๊ธฐ๋ผ๊ณ  ์ƒ๊ฐํ•˜์ง€๋งŒ ๋‚˜๋Š”
ํ›จ์”ฌ ๋” ๊ฐ„๋‹จํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์–ผ๋งˆ๋‚˜ ๋งŽ์€ ์‚ฌ๋žŒ๋“ค์ด (1)์— ๋งŒ์กฑํ•  ๊ฒƒ์ธ๊ฐ€?
๊ตฌํ˜„ํ•˜๊ณ  ์œ ์ง€ํ•ฉ๋‹ˆ๋‹ค.

(1) ๋กœ๊ทธ์ธ ์—†์ด Firestore ๋˜๋Š” Realtime Database์™€ ๊ฐ™์€ ์„œ๋น„์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๋ฉด
์‹ค์ œ๋กœ ์‹ค์ œ ์‚ฌ์šฉ์ž๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. ์ง€๊ธˆ์€ ๊ทธ๋Ÿฐ ๊ฒƒ ๊ฐ™๋‹ค.
setEmulatedUser๊ฐ€ ํ•ด๊ฒฐํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๊ฐ€์งœ ์ธ์ฆ์„ ํ—ˆ์šฉํ•  ๋ฟ์ž…๋‹ˆ๋‹ค.
์—๋ฎฌ๋ ˆ์ดํ„ฐ๊ฐ€ ์ˆ˜๋ฝํ•˜์ง€๋งŒ ๊ฑฐ๋ถ€ํ•  ๋กœ์ปฌ ํ† ํฐ
์ฐŒ๋ฅด๋‹ค. ๋” ๋งŽ์€ ์•ˆ์ „, ๋” ๋งŽ์€ ๊ฒฉ๋ฆฌ ๋“ฑ_

โ€”
๋‹น์‹ ์ด ์–ธ๊ธ‰๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด๊ฒƒ์„ ๋ฐ›๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
์ด ์ด๋ฉ”์ผ์— ์ง์ ‘ ๋‹ต์žฅํ•˜๊ณ  GitHub์—์„œ ํ™•์ธํ•˜์„ธ์š”.
https://github.com/firebase/firebase-tools/issues/1677#issuecomment-632660684 ,
๋˜๋Š” ๊ตฌ๋… ์ทจ์†Œ
https://github.com/notifications/unsubscribe-auth/ACATB2Q4LV7NXMQFEALNPXLRSZT25ANCNFSM4I27PTFA
.

1. ์‹ค์ œ ์‚ฌ์šฉ์ž๋ฅผ ์ƒ์„ฑํ•˜์ง€ ์•Š๊ณ  ๋กœ๊ทธ์ธํ•˜์—ฌ Firestore ๋˜๋Š” Realtime Database์™€ ๊ฐ™์€ ์„œ๋น„์Šค๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋ฐ”๋กœ ์ง€๊ธˆ ๊ทธ๊ฒƒ์ด setEmulatedUser์™€ ๊ฐ™์€ ๊ฒƒ์ด ํ•ด๊ฒฐ๋  ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์—๋ฎฌ๋ ˆ์ดํ„ฐ๊ฐ€ ์ˆ˜๋ฝํ•˜์ง€๋งŒ ์ œํ’ˆ์— ์˜ํ•ด ๊ฑฐ๋ถ€๋˜๋Š” ๊ฐ€์งœ ์ธ์ฆ ํ† ํฐ์„ ๋กœ์ปฌ๋กœ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋” ๋งŽ์€ ์•ˆ์ „, ๋” ๋งŽ์€ ๊ฒฉ๋ฆฌ ๋“ฑ

๋‚˜๋Š” ์—ฌ๊ธฐ์„œ 1๋“ฑ์œผ๋กœ ๋งŒ์กฑํ•  ๊ฒƒ์ด๋‹ค. ๊ทธ ์‚ฌ์ด์—

https://stackoverflow.com/questions/62736060/firebase-test-auth-cloud-functions-locally

์•„์ง๋„ ๋ถˆ๊ฐ€๋Šฅํ•œ๊ฐ€์š”?

@rishishingh-dev ํ˜„์žฌ Firebase ์—๋ฎฌ๋ ˆ์ดํ„ฐ๊ฐ€ ์ œ๊ณตํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์ธ์ฆ ์—๋ฎฌ๋ ˆ์ดํ„ฐ๋ฅผ ์‹คํ–‰ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

๊ทธ๋Ÿฌ๋‚˜ ์ธ์ฆ๊ณผ ๊ด€๋ จ๋œ ํด๋ผ์šฐ๋“œ ๊ธฐ๋Šฅ์„ ํ…Œ์ŠคํŠธํ•˜๋Š” ๊ฒƒ์€ ์™„๋ฒฝํ•˜๊ฒŒ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ์ผ๋ถ€ ์ธ์ฆ API๊ฐ€ ํ•„์š”ํ•œ ํ•จ์ˆ˜๋ฅผ ๋ฆฌํŒฉํ„ฐ๋งํ•˜๊ณ  ํ…Œ์ŠคํŠธ์—์„œ ๋ชจ์˜ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ Firebase ํ•จ์ˆ˜ ํŒŒ์ผ์— ์‹ค์ œ API๋ฅผ ์ œ๊ณตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ…Œ์ŠคํŠธ ์„ค์ •์˜ ์ถฉ์‹ค๋„๋Š” ๋” ๋‚ฎ์ง€๋งŒ ์ข…๋ฅ˜์˜ ๋ฌธ์ œ๊ฐ€ ์•„๋‹ˆ๋ผ ์ •๋„์˜ ๋ฌธ์ œ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค. ์ธ์ฆ ํ˜ธ์ถœ์„ ์ง์ ‘ ํ…Œ์ŠคํŠธํ•˜๋Š” ๊ฒƒ์ด์ง€๋งŒ ์˜ˆ์ƒํ•œ ๋Œ€๋กœ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๊ทธ SO ์งˆ๋ฌธ์—์„œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

function sendWelcomeEmail(user) {
  console.log(user.uid);
  console.log(user.email);
  console.log(user.displayName);
}

exports.sendWelcomeEmail = functions.auth.user().onCreate((user) => sendWelcomeEmail(user));

๊ทธ๋ฆฌ๊ณ  ํ…Œ์ŠคํŠธ์—์„œ sendWelcomeEmail ์ง์ ‘ ํ˜ธ์ถœํ•˜์—ฌ ํ•„์š”ํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.

addFriend ๋ผ๋Š” ๋” ๋ณต์žกํ•œ ํด๋ผ์šฐ๋“œ ํ•จ์ˆ˜๊ฐ€ ์žˆ๋‹ค๊ณ  ์ƒ์ƒํ•ด๋ณด์‹ญ์‹œ์˜ค. ์—ฌ๊ธฐ์„œ ์‚ฌ์šฉ์ž๋Š” ์นœ๊ตฌ ์ด๋ฉ”์ผ์„ ์ž…๋ ฅํ•˜๊ณ  uid๋ฅผ ์›ํ•ฉ๋‹ˆ๋‹ค. getUserByEmail ์„ ํ†ตํ•ด ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

function addFriend(email, getUserByEmail ) {
  const friendUid = getUserByEmail(email);
  // do things with friendUid;
}

exports.addFriend = functions.https.onCall(async (data, context) => {
  const email = data.email;
  const getUserByEmail = (email) => admin.auth().getUserByEmail(email);
  return { res: await addFriend(email, getUserByEmail ) };
}

ํด๋ผ์šฐ๋“œ fn ์„ ์–ธ์—์„œ ์‹ค์ œ getUserByEmail ๋ฅผ ๋ณด๋‚ด์ง€๋งŒ ํ…Œ์ŠคํŠธ์—์„œ๋Š” ๋Œ€์‹  ๊ฐ€์งœ๋ฅผ ๋ณด๋ƒ…๋‹ˆ๋‹ค.

async function testAddFriend() {
  const emails = {"[email protected]": "test-uid")
  const fakeGetUserByEmail = (email) => emails[email];
  addFriend("[email protected]);
  // verify the things were done with friendUid
}

์ด๊ฒƒ์ด ๋‹จ์œ„ ํ…Œ์ŠคํŠธ์—์„œ ํƒ€์‚ฌ API๋ฅผ ํ…Œ์ŠคํŠธํ•˜๋Š” ๊ฒƒ๊ณผ ํฌ๊ฒŒ ๋‹ค๋ฅด์ง€ ์•Š๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. Firebase ์—๋ฎฌ๋ ˆ์ดํ„ฐ์—์„œ ์ธ์ฆ์„ ์ œ๊ณตํ•˜๋ฉด ์ข…๋‹จ ๊ฐ„ ํ…Œ์ŠคํŠธ ์‹œ๋‚˜๋ฆฌ์˜ค์— ๋Œ€ํ•œ ์ƒ์šฉ๊ตฌ๊ฐ€ ์ œ๊ฑฐ๋˜์ง€๋งŒ ํ…Œ์ŠคํŠธ ๊ฐ„์— ์˜๊ตฌ ์ƒํƒœ๊ฐ€ ์œ ์ง€๋˜๋Š” ๊ฒƒ์„ ์›ํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ๋‹จ์œ„ ํ…Œ์ŠคํŠธ๋ฅผ ํฌ๊ฒŒ ๋ณ€๊ฒฝํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด ํด๋ผ์šฐ๋“œ์— ์—…๋กœ๋“œํ•  ํ•„์š” ์—†์ด ๋กœ์ปฌ์—์„œ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹ค.

export const onCreate = functions.auth.user().onCreate((user) => {
    addGravatarURLtoUserData(user.uid, user.email)
})

export const addGravatarURLtoUserData = async (uid, email) => {
    const hash = crypto.createHash("md5").update(email).digest("hex")
    await admin.database().ref(`users/${uid}`).update({ gravatarURL: uid })
}

๊ทธ๊ฑด ๊ทธ๋ ‡๊ณ , onCreate ํ•จ์ˆ˜ ๋‚ด์—์„œ user.displayName์„ ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

๋„ค ์„ค์ •๋˜์–ด ์žˆ๋‹ค๋ฉด ์‹œ๋„ํ•ด ๋ณด์…จ๋‚˜์š”?

์˜ˆ, null์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
ํด๋ผ์šฐ๋“œ์—์„œ ์‹œ๋„ํ–ˆ์Šต๋‹ˆ๋‹ค(๋กœ์ปฌ์ด ์•„๋‹˜).

Screen Shot 2020-07-10 at 2 43 12 AM

๋‚ด ์ฝ”๋“œ๊ฐ€ ์—ฌ๊ธฐ์— ์žˆ์Šต๋‹ˆ๋‹ค.

exports.sendWelcomeEmail = functions.auth.user().onCreate((user) => {
  console.log(user.uid);
  console.log(user.email);
  console.log(user.displayName);
});

ํฅ๋ฏธ๋กญ๊ฒŒ๋„ ํ‘œ์‹œ ์ด๋ฆ„์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  ์‚ฌ์šฉ์ž ์ง€์ • ์‚ฌ์šฉ์ž displayName์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
์‹ค์‹œ๊ฐ„ DB

/**
 * updates Custom data in the realtime datastore users object, except for the username
 * <strong i="7">@param</strong> data
 * <strong i="8">@returns</strong> {Promise<void>}
 */
export async function updatePersonalData(data) {
    const { displayName } = data
    try {
        await firebase
            .database()
            .ref("users/" + firebase.auth().currentUser.uid)
            .update({
                displayName: displayName,
            })

        userDataStore.update((user) => {
            return { ...user, displayName: displayName }
        })
    } catch (e) {
        alert(e.message)
    }
}

2020๋…„ 7์›” 10์ผ ๊ธˆ์š”์ผ 10:44 rishingh-dev [email protected]
์ผ๋‹ค:

์˜ˆ, null์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
ํด๋ผ์šฐ๋“œ์—์„œ ์‹œ๋„ํ–ˆ์Šต๋‹ˆ๋‹ค(๋กœ์ปฌ์ด ์•„๋‹˜).

[์ด๋ฏธ์ง€: ์Šคํฌ๋ฆฐ์ƒท 2020-07-10 at 2 43 AM 12 AM]
https://user-images.githubusercontent.com/56976320/87140958-29f3ac80-c257-11ea-98d3-084fad619de7.png

๋‚ด ์ฝ”๋“œ๊ฐ€ ์—ฌ๊ธฐ์— ์žˆ์Šต๋‹ˆ๋‹ค.

console.log(user.uid);
console.log(์‚ฌ์šฉ์ž.์ด๋ฉ”์ผ);
console.log(user.displayName);
});```

โ€”
์ด ์Šค๋ ˆ๋“œ์— ๊ฐ€์ž…ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ›๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
์ด ์ด๋ฉ”์ผ์— ์ง์ ‘ ๋‹ต์žฅํ•˜๊ณ  GitHub์—์„œ ํ™•์ธํ•˜์„ธ์š”.
https://github.com/firebase/firebase-tools/issues/1677#issuecomment-656587759 ,
๋˜๋Š” ๊ตฌ๋… ์ทจ์†Œ
https://github.com/notifications/unsubscribe-auth/AABU35Q27EMMHYAYU5CNZR3R23PIDANCNFSM4I27PTFA
.

>

์•ˆ๋ถ€

๋‹ˆ์ฝ”์Šค ์นด์น˜์นด๋‹ˆ์Šค

๋„ค, ์ œ ์ฃผ์š” ๋ชฉํ‘œ๋Š” onCreate ํ•จ์ˆ˜ ๋‚ด๋ถ€์˜ ์‚ฌ์šฉ์ž ์ •๋ณด๋กœ ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค๋ฅผ ์—…๋ฐ์ดํŠธํ•˜๋Š” ๊ฒƒ์ด์—ˆ์Šต๋‹ˆ๋‹ค.
ํ•˜์ง€๋งŒ displayName ์–ป์„ ์ˆ˜ ์—†๊ธฐ ๋•Œ๋ฌธ์— onCallable ํ•จ์ˆ˜๋ฅผ ๋งŒ๋“ค์–ด ์‹คํ–‰ํ–ˆ์Šต๋‹ˆ๋‹ค.

๊ฐ์‚ฌ ํ•ด์š”.

@samtstern ์ด ์ž‘์—…์„ ํ•˜๋Š” ๊ฒƒ์„ ๋ณด๊ฒŒ ๋˜์–ด ๋งค์šฐ ๊ธฐ์ฉ๋‹ˆ๋‹ค :) ๋ฐฉ๊ธˆ

๋˜ ๋‹ค๋ฅธ ๊ฐ€์žฅ ์ข‹์€ ์ ์€ ๋ณด์•ˆ ์—†์ด ํฌ๋กฌ์„ ์—ด ํ•„์š”๊ฐ€ ์—†๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

@samtstern

๋‘ ๋‹ฌ์ด ์ง€๋‚œ ์ง€๊ธˆ, ๋Œ€๋žต์ ์ธ ๊ฒฌ์ ์„ ๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

๋‚ด๋…„ ์ดˆ์— ์ถœํ•˜ํ•˜๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค. ์ด์ œ ์šฐ๋ฆฌ๋Š” ์‹ค์ œ ํ”„๋กœ์ ํŠธ์— ๋Œ€ํ•œ ํ†ตํ•ฉ ํ…Œ์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ•  ๊ฒƒ์ธ์ง€ ์•„๋‹ˆ๋ฉด ์ธ์ฆ ์—๋ฎฌ๋ ˆ์ดํ„ฐ๋ฅผ ์œ„ํ•ด ๋ช‡ ๋‹ฌ์„ ๊ธฐ๋‹ค๋ ค์•ผ ํ•  ๊ฒƒ์ธ์ง€ ๊ฒฐ์ •ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์„œ ์šฐ๋ฆฌ๋ฅผ ์กฐ๊ธˆ ๋„์™€์ฃผ์‹œ๊ฒ ์Šต๋‹ˆ๊นŒ?

์ตœ์ƒ์˜,

๋‹ˆํด๋ผ์Šค

Firebase์˜ ์ •์ฑ…์€ 100% ํ™•์‹ ํ•  ์ˆ˜ ์—†๋Š” ๊ฒฝ์šฐ ์ถœ์‹œ ์‹œ์ ์— ๋Œ€ํ•œ ์ถ”์ •์น˜๋ฅผ ์ œ๊ณตํ•˜์ง€ ์•Š๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ง€๊ธˆ ์šฐ๋ฆฌ๋Š” ์ธ์ฆ ์—๋ฎฌ๋ ˆ์ดํ„ฐ์— ๋Œ€ํ•ด ์—ด์‹ฌํžˆ ๋…ธ๋ ฅํ•˜๊ณ  ์žˆ์ง€๋งŒ ์ถœ์‹œ ๋‚ ์งœ๋ฅผ ์„ ํƒํ•˜๊ธฐ์—๋Š” ์ถฉ๋ถ„ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๊ทธ๊ฒƒ์€ ์šฐ๋ฆฌ์˜ ์ตœ์šฐ์„  ์ˆœ์œ„ ์ค‘ ํ•˜๋‚˜์ด์ง€๋งŒ, ์šฐ๋ฆฌ๊ฐ€ ๋‹น์‹ ์˜ ์•ฑ ํ…Œ์ŠคํŠธ๋ฅผ ์‹œ์ž‘ํ•  ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฌ๋ฉด ์•ˆ ๋œ๋‹ค๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค. ์˜ค๋Š˜ prod์— ๋Œ€ํ•œ ํ…Œ์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ•˜๊ณ  ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ ์—๋ฎฌ๋ ˆ์ดํ„ฐ๋ฅผ ๋Œ€์ƒ์œผ๋กœ ํ•˜๋„๋ก ์ „ํ™˜ํ•˜์‹ญ์‹œ์˜ค.

์•Œ๊ฒ ์Šต๋‹ˆ๋‹ค. @samttern ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ๋„์›€์ด ๋ฉ๋‹ˆ๋‹ค!

์ธ์ฆ ์—๋ฎฌ๋ ˆ์ดํ„ฐ๋ฅผ ์‹ค์ œ๋กœ ์‚ฌ์šฉํ•˜๊ณ  ์‹ถ์€ ๊ฒƒ์€ ์‚ฌ์šฉ์ž ํ† ํฐ์— ๋Œ€ํ•œ ์ปค์Šคํ…€ ํด๋ ˆ์ž„ ์„ ํฌํ•จํ•˜๋Š” Cloud Functions ๋ฐ Firestore ์š”์ฒญ์„ ํ…Œ์ŠคํŠธํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. Firebase ์ฝ˜์†”์˜ ๊ทœ์น™ ํ”Œ๋ ˆ์ด๊ทธ๋ผ์šด๋“œ์—์„œ Firestore๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ผ์ข…์˜ ๋งž์ถค ํด๋ ˆ์ž„์„ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ์ง€๋งŒ ๋ณธ๊ฒฉ์ ์ธ ์ธ์ฆ ์—๋ฎฌ๋ ˆ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ด๋ก ์ ์œผ๋กœ ์‚ฌ์šฉ์ž ํ† ํฐ๊ณผ ๊ด€๋ จํ•˜์—ฌ ํ…Œ์ŠคํŠธํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ํ›จ์”ฌ ๋” ๋งŽ์€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๋ถ„๋ช…ํžˆ ํ•˜์ž๋ฉด, ์šฐ๋ฆฌ๋Š” ์‹ค์ œ ์„œ๋น„์Šค ์—”๋“œํฌ์ธํŠธ๋ฅผ ์—๋ฎฌ๋ ˆ์ดํŠธํ•˜๋Š” ๋ณธ๊ฒฉ์ ์ธ ์ธ์ฆ ์—๋ฎฌ๋ ˆ์ดํ„ฐ์— ์ „๋…ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค(๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ). ์šฐ๋ฆฌ๋Š” ๋” ์ด์ƒ ์ด์ „ ์˜๊ฒฌ์ด ์ œ์•ˆํ•œ

@samtstern ์€ ๋“ฃ๊ธฐ ์ข‹์Šต๋‹ˆ๋‹ค(์‚ฌ์šฉ์ž ์ง€์ • ํด๋ ˆ์ž„๊ณผ ํ•จ๊ป˜, ํƒ€์‚ฌ ํ†ตํ•ฉ๊ณผ ํ•จ๊ป˜ ์ž์ฃผ ์‚ฌ์šฉ๋˜๊ธฐ ๋•Œ๋ฌธ์—). ์ง„ํ–‰ ์ƒํ™ฉ/ETA๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋Š” ๊ณณ์ด ์žˆ์Šต๋‹ˆ๊นŒ?

@fandy no ์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค ์•„์ง ๊ณต์œ ํ•  ๋‚ด์šฉ์ด ์—†์Šต๋‹ˆ๋‹ค...

Sam์—๊ฒŒ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค. ํ˜„์žฌ ์ˆ˜๋™์œผ๋กœ ๋ชจ๋“  ํ…Œ์ŠคํŠธ๋ฅผ ์ˆ˜ํ–‰ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
Auth ๋ชจ์˜ ์—†์ด e2e ํ…Œ์ŠคํŠธ๋ฅผ ์ž‘์„ฑํ•  ๊ฐ€์น˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

2020๋…„ 8์›” 26์ผ ์ˆ˜์š”์ผ 14:32 Sam Stern [email protected]์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์ผ์Šต๋‹ˆ๋‹ค.

>
>

@fandy https://github.com/fandy ์ฃ„์†กํ•ฉ๋‹ˆ๋‹ค.
์•„์ง ๊ณต์œ ...

โ€”
์ด ์Šค๋ ˆ๋“œ์— ๊ฐ€์ž…ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์ด ๋ฉ”์‹œ์ง€๋ฅผ ๋ฐ›๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
์ด ์ด๋ฉ”์ผ์— ์ง์ ‘ ๋‹ต์žฅํ•˜๊ณ  GitHub์—์„œ ํ™•์ธํ•˜์„ธ์š”.
https://github.com/firebase/firebase-tools/issues/1677#issuecomment-680850282 ,
๋˜๋Š” ๊ตฌ๋… ์ทจ์†Œ
https://github.com/notifications/unsubscribe-auth/AABU35UAQDBYEXKKINJSM43SCT6E7ANCNFSM4I27PTFA
.

--

์•ˆ๋ถ€

๋‹ˆ์ฝ”์Šค ์นด์น˜์นด๋‹ˆ์Šค

์ด ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๋ธŒ๋ผ์šฐ์ €์—์„œ @firebase/testing ๊ฐ€์ ธ์˜ค๊ธฐ๋ฅผ ์‹คํ—˜ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ •๋ง ํšจ๊ณผ๊ฐ€ ์—†์—ˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋Ÿฌ๋‚˜ ์ด๊ฒƒ์€ ๋‹ค์Œ๊ณผ ๊ฐ™์ด ์•ฝ๊ฐ„ ํŽธ์ง‘๋œ ์ฒญํฌ๋ฅผ ๋ณต์‚ฌํ•˜๊ธฐ ์œ„ํ•ด @firebase/testing source๋ฅผ mangleํ•ฉ๋‹ˆ๋‹ค.

import firebase from "firebase/app"
import * as component from "@firebase/component"
import * as util from "@firebase/util"
import { __awaiter, __generator } from "tslib"

function createUnsecuredJwt(auth) {
    // Unsecured JWTs use "none" as the algorithm.
    var header = {
        alg: 'none',
        kid: 'fakekid'
    };
    // Ensure that the auth payload has a value for 'iat'.
    auth.iat = auth.iat || 0;
    // Use `uid` field as a backup when `sub` is missing.
    auth.sub = auth.sub || auth.uid;
    if (!auth.sub) {
        throw new Error("auth must be an object with a 'sub' or 'uid' field");
    }
    // Unsecured JWTs use the empty string as a signature.
    var signature = '';
    return [
        util.base64.encodeString(JSON.stringify(header), /*webSafe=*/ false),
        util.base64.encodeString(JSON.stringify(auth), /*webSafe=*/ false),
        signature
    ].join('.');
}

function initializeApp(accessToken, options) {
    var _this = this;
    var app = firebase.initializeApp(options);
    if (accessToken) {
        var mockAuthComponent = new component.Component('auth-internal', function () {
            return ({
                getToken: function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
                    return [2 /*return*/, ({ accessToken: accessToken })];
                }); }); },
                getUid: function () { return null; },
                addAuthTokenListener: function (listener) {
                    // Call listener once immediately with predefined accessToken.
                    listener(accessToken);
                },
                removeAuthTokenListener: function () { }
            });
        }, "PRIVATE" /* PRIVATE */);
        app._addOrOverwriteComponent(mockAuthComponent);
    }
    return app;
}

export function initializeTestApp(options) {
  let accessToken = undefined
  if (options.auth !== undefined) {
    accessToken = createUnsecuredJwt(options.auth)
  }
  return initializeApp(accessToken, options)
}

์ด์ œ ์•ฑ ๋ธŒ๋ผ์šฐ์ € ์ธก ์ฝ”๋“œ์—์„œ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  let app
  if (dev) {
    app = initializeTestApp({projectId: "test", auth: {uid: "testuser"}})
    app.firestore().settings({
      host: "localhost:8080",
      ssl: false,
    })
  } else {
    app = firebaseProduction.initializeApp({ firebase config here })
    app.firestore().settings({ firestore config here })
  }
  window.firebase = app

์ž˜ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค! ์ด์ œ ๊ฐœ๋ฐœ ์ค‘์ผ ๋•Œ ์—๋ฎฌ๋ ˆ์ดํ„ฐ๊ฐ€ "testuser"๋ผ๊ณ  ์ƒ๊ฐํ•˜๋Š” ๋กœ์ปฌ ๊ฐ€์งœ ์‚ฌ์šฉ์ž๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค(firestore ๋ณด์•ˆ ๊ทœ์น™ ํ…Œ์ŠคํŠธ ๊ฐ€์ด๋“œ์—์„œ ๋ณด์—ฌ ์ฃผ๋Š” ๊ฒƒ์ฒ˜๋Ÿผ).

๋‚ด๊ฐ€ ์‚ฌ์šฉํ•˜๋Š” ๋˜ ๋‹ค๋ฅธ ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•์€ ์ธ์ฆ์„ ์Šคํ…ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค(ํ…Œ์ŠคํŠธ๋ฅผ ์œ„ํ•ด ์ƒ์„ฑ๋œ ๊ฐ€์งœ ์‚ฌ์šฉ์ž๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค).

TypeScript ์˜ˆ:

import type { User as AuthUser } from '@firebase/auth-types'
// not importing a type, but a module of types
import { auth as authTypes} from 'firebase/app'
type Auth = authTypes.Auth

export const authStub = {
    getUser(uid: string) {
        // for uids like `testuser1234uid`
        let n = uid ? uid.replace("testuser", '').replace("uid", '') : ''
        return Promise.resolve({
            uid,
            email: `test.user${n}@foo.com`,
            emailVerified: true,
            providerData: [{
                providerId: 'google.com',
                email: `test.user${n}@foo.com`,
                uid: `testuser${n}provideruid`,
                phoneNumber: null,
                displayName: `Test User ${n}`.trim(),
                photoURL: 'https://thispersondoesnotexist.com/image',
            }],
            metadata: {
                // https://firebase.google.com/docs/reference/admin/node/admin.auth.UserMetadata
                createTime: new Date().toUTCString(),
                lastSignInTime: new Date().toUTCString()
            },
            customClaims: {
                username: `testuser${n}`
            }
        })
    },
    deleteUser(uid: string) {
        return Promise.resolve()
    },
    async updateUser(uid: string, data: AuthUser) {
        let user = await this.getUser(uid)
        return { ...user, data }
    },
    setCustomUserClaims(uid: string, customUserClaims: Object): Promise<void> {
        return Promise.resolve()
    }
}

export const auth = <Auth><unknown>authStub

๋˜ํ•œ auth.token ๊ฐ€ ์—๋ฎฌ๋ ˆ์ดํŠธ๋˜์ง€ ์•Š์œผ๋ฏ€๋กœ ๊ทœ์น™์„ ์ˆ˜์ •ํ•˜์‹ญ์‹œ์˜ค. ์˜ˆ๋ฅผ ๋“ค์–ด:

const rules = fs.readFileSync(__dirname + '/src/firebase/firestore/firestore.rules', 'utf8')
const modifiedRules =
    rules
        .replace(/request\.auth\.token\.email_verified/g, "true")
        .replace(/request\.auth\.token\.firebase\.sign_in_provider/g, "'password'")

await firebase.loadFirestoreRules({ projectId, rules: modifiedRules })

๊ทธ๊ฒƒ์€ ๋‚˜๋ฅผ ์œ„ํ•ด ์ž˜ ์ž‘๋™ํ•ฉ๋‹ˆ๋‹ค. ๋„์›€์ด ๋˜๊ธฐ๋ฅผ ๋ฐ”๋ž๋‹ˆ๋‹คโ€ฆ

์ด ์Šค๋ ˆ๋“œ๋ฅผ ํŒ”๋กœ์šฐํ•˜๊ณ  Firebase ์ธ์ฆ ์—๋ฎฌ๋ ˆ์ดํ„ฐ์˜ ์•ŒํŒŒ ํ…Œ์Šคํ„ฐ๊ฐ€ ๋˜๊ณ  ์‹ถ๋‹ค๋ฉด ๋‹ค์Œ ๋‹จ๊ณ„๋ฅผ ๋”ฐ๋ฅด์„ธ์š”.

  1. Firebase ์•ŒํŒŒ ํ”„๋กœ๊ทธ๋žจ ๊ฐ€์ž…: https://services.google.com/fb/forms/firebasealphaprogram/
  2. [email protected] ์œผ๋กœ ์ด๋ฉ”์ผ์„ ๋ณด๋‚ด์ฃผ์„ธ์š”. ํ…Œ์ŠคํŠธ์— ์‚ฌ์šฉํ•  ์ด๋ฉ”์ผ ์ฃผ์†Œ๋กœ ๋ณด๋‚ด์ฃผ์„ธ์š”.

์ดˆ๊ธฐ ๋‹จ๊ณ„์˜ ์—๋ฎฌ๋ ˆ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•ด ๋ณด๊ณ  ํ”ผ๋“œ๋ฐฑ์„ ์ œ๊ณตํ•˜๋Š” ๋ฐ ์ง„์ง€ํ•˜๊ฒŒ ๊ด€์‹ฌ์ด ์žˆ๋Š” ๊ฒฝ์šฐ์—๋งŒ ์ด ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜์„ธ์š”! ๋ฒ„๊ทธ๊ฐ€ ์žˆ๊ณ  ์„ค์ •์˜ ์ผ๋ถ€๊ฐ€ ์–ด๋ ค์šธ ์ˆ˜ ์žˆ์ง€๋งŒ ๊ท€ํ•˜์˜ ์ƒ๊ฐ์„ ์•Œ๊ณ  ์‹ถ์Šต๋‹ˆ๋‹ค.

@samttern ๋ฐ˜๊ฐ€์šด ์†Œ์‹์ž…๋‹ˆ๋‹ค! ํ•ด๋ณด๊ณ  ์‹ถ์ง€๋งŒ ์ฃผ๋ง๊นŒ์ง€ ํ˜„์žฌ ํ”„๋กœ์ ํŠธ๋กœ ํ”„๋กœ๋•์…˜์— ๋“ค์–ด๊ฐˆ ์˜ˆ์ •์ด๋ฏ€๋กœ ํ˜„์žฌ๋กœ์„œ๋Š” ๊ทธ๊ฒƒ์„ ๊ฐ€์ง€๊ณ  ๋†€ ์—ฌ์œ ๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๊ฐ€๋Šฅํ•œ ํ•œ ๋นจ๋ฆฌ ์•ŒํŒŒ์— ๋“ฑ๋กํ•  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค. :) ํ›Œ๋ฅญํ•œ ์ž‘์—…์— ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค.

100% ์ด๊ฒƒ์„ ์‹œ๋„ํ•˜๊ณ  ์‹ถ์–ดํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค! ๋‹น์‹ ์˜ ๋‚จ์ž ์ƒ˜!

@samttern ์€ ๊ทธ๊ฒƒ์„ ์‹œ๋„ํ•˜๊ณ  ๋‚ด๊ฐ€ ํ•  ์ˆ˜ ์žˆ๋Š” ๋ชจ๋“  ๊ฒƒ์„ ๋„์šธ ์ˆ˜ ์žˆ๊ธฐ๋ฅผ ๊ณ ๋Œ€ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค!

Android์—์„œ ๋กœ์ปฌ๋กœ ๊ธฐ๋Šฅ์„ ํ…Œ์ŠคํŠธํ•˜๋ ค๋ฉด ์ธ์ฆ ๊ธฐ๋Šฅ์„ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์ธ์ฆ ์ปจํ…์ŠคํŠธ๋Š” ํ•ญ์ƒ null์ž…๋‹ˆ๋‹ค.

์ข‹์€ ์†Œ์‹์ž…๋‹ˆ๋‹ค. ์ธ์ฆ ์—๋ฎฌ๋ ˆ์ดํ„ฐ๋Š” ์ƒˆ๋กœ์šด 8.14.0 ๋ฆด๋ฆฌ์Šค์˜ ์ผ๋ถ€์ž…๋‹ˆ๋‹ค! ๐Ÿ™Œ๐ŸŽŠ

๊ณ ์ƒํ•œ ์นœ๊ตฌ๋“ค๊ณผ @samtstern ์—๊ฒŒ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค ๐Ÿ’ช

๋ฉ‹์ง„ ๋…€์„๋“ค!

๋‚œ ๊ทธ๋ƒฅ ๋ฉ”์‹ ์ €! Auth ์—๋ฎฌ๋ ˆ์ดํ„ฐ๋Š” @yuchenshi ์—์„œ 99% ๊ตฌ์ถ•ํ–ˆ์Šต๋‹ˆ๋‹ค... ๊ทธ๋ž˜์„œ ๊ทธ๊ฐ€ ๊นจ์–ด๋‚ฌ์„ ๋•Œ ์ด ๋ฌธ์ œ๋ฅผ ๋‹ซ๋Š” ์˜๊ด‘์„

์ด ์ƒˆ๋กœ์šด ์—๋ฎฌ๋ ˆ์ดํ„ฐ์— ๋Œ€ํ•œ ๋ฌธ์„œ๊ฐ€ ์žˆ์Šต๋‹ˆ๊นŒ? (ํด๋ผ์ด์–ธํŠธ ์„ค์น˜, ๊ตฌ์„ฑ ๋ฐฉ๋ฒ• ๋“ฑ)

PS ์ด๊ฒƒ์— ๋Œ€ํ•œ ๋ชจ๋“  ๋…ธ๊ณ ์— ๊ฐ์‚ฌ๋“œ๋ฆฝ๋‹ˆ๋‹ค. ์ด๊ฒƒ์€ ์šฐ๋ฆฌ๋ฅผ ์œ„ํ•ด ๋ชจ๋“  ์ข…๋ฅ˜์˜ ๋ฉ‹์ง„ ๊ฒƒ๋“ค์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

@nicoburns ๊ณง! ๊ณต์‹ ๋ฐœํ‘œ, ๋ฌธ์„œ ๋ฐ ๋ชจ๋“  ์ข‹์€ ๊ฒƒ๋“ค์ด ๊ณง ์ œ๊ณต๋  ์˜ˆ์ •์ž…๋‹ˆ๋‹ค.

์ข‹์€ ์†Œ์‹! :) ๋นจ๋ฆฌ ์‹œ๋„ํ•ด๋ณด์„ธ์š” :)

๋‹น์‹ ์ด ์ด๊ฒƒ์„ ๊ธฐ๋‹ค๋ฆฌ๊ณ  ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ณ  ์žˆ์œผ๋ฏ€๋กœ ์š”์ ์œผ๋กœ ์ž˜๋ผ ๋ด…์‹œ๋‹ค.

  • ์ด์ œ Firebase ์ธ์ฆ ์—๋ฎฌ๋ ˆ์ดํ„ฐ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. Firebase CLI >= v8.14.0์„ ์„ค์น˜ํ•˜๋ฉด ์–ป์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ์—๋ฎฌ๋ ˆ์ดํ„ฐ ์ œํ’ˆ๊ตฐ ๊ฐ€์ด๋“œ์— ๋”ฐ๋ผ ์‹œ์ž‘ ํ•˜๊ณ  ์•ฑ์„ ์—ฐ๊ฒฐํ•ฉ๋‹ˆ๋‹ค .
  • ์ด์™€ ๊ฐ™์€ ํฅ๋ฏธ๋กœ์šด ๋ฐœํ‘œ์™€ ํ›จ์”ฌ ๋” ๋งŽ์€ ๊ฒƒ์„ ๋ณด๋ ค๋ฉด ์ง€๊ธˆ Firebase Summit ์‹ค์‹œ๊ฐ„ ์ŠคํŠธ๋ฆฌ๋ฐ์„

**๋ป”๋ป”ํ•œ ํ”Œ๋Ÿฌ๊ทธ: ์˜ค๋Š˜ ๋‚˜์ค‘์— "Firebase Emulator ์ œํ’ˆ๊ตฐ์„ ์‚ฌ์šฉํ•˜์—ฌ CI๋ฅผ ์„ค์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•"์— ๋Œ€ํ•œ ์„ธ์…˜๋„ ์ง„ํ–‰ ์ค‘์ž…๋‹ˆ๋‹ค. ์„ธ์…˜ ์ผ์ • ์—์„œ ๊ทธ๊ฒƒ์„ ์ฐพ๋Š” ๊ฒƒ์€ ๋…์ž๋ฅผ ์œ„ํ•œ ์—ฐ์Šต์œผ๋กœ ๋‚จ๊ฒจ๋‘ก๋‹ˆ๋‹ค.


_์ถ”์‹ . Auth Emulator๋Š” ๋ฌผ๋ก  ํŒ€์›Œํฌ์ด๊ธฐ ๋•Œ๋ฌธ์— 99%์˜ ํฌ๋ ˆ๋”ง์„ ๋ฐ›์„ ์ˆ˜๋Š” ์—†์Šต๋‹ˆ๋‹ค. Firebase์˜ ๋‹ค์–‘ํ•œ ์‚ฌ๋žŒ๋“ค๊ณผ Firebase ๊ฐœ๋ฐœ์ž(๊ท€ํ•˜)๋„ ์—ฌ๊ธฐ์— ํฐ ์—ญํ• ์„ ํ–ˆ์Šต๋‹ˆ๋‹ค. ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค!_

@yuchenshi Firestore ์—๋ฎฌ๋ ˆ์ดํ„ฐ์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ์ข…๋ฃŒ ์‹œ ์ƒ์„ฑ๋œ ์‚ฌ์šฉ์ž๋ฅผ ๋‚ด๋ณด๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๊นŒ?

@vdjurdjevic ์•„์ง, ์šฐ๋ฆฌ๋Š” ๊ทธ๊ฒƒ์— ๋Œ€ํ•ด ๋…ธ๋ ฅํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๊ฒƒ์€ ์ •๋ง ์ธ๊ธฐ ์žˆ๋Š” ๋ฌธ์ œ์ด๋ฉฐ ๋ชจ๋“  ์—…๋ฐ์ดํŠธ๋Š” 50-100๋ช…์—๊ฒŒ ์•Œ๋ฆฝ๋‹ˆ๋‹ค. ์ด์ œ Auth ์—๋ฎฌ๋ ˆ์ดํ„ฐ๋ฅผ ์ถœ์‹œํ–ˆ์œผ๋ฏ€๋กœ ํ–ฅํ›„ ์—…๋ฐ์ดํŠธ์—์„œ ์ด ๋ฌธ์ œ๋ฅผ ์ž ๊ธ€ ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์งˆ๋ฌธ, ๋ฒ„๊ทธ ๋˜๋Š” ๊ธฐ๋Šฅ ์š”์ฒญ์ด ์žˆ๋Š” ๊ฒฝ์šฐ ์ƒˆ ๋ฌธ์ œ๋ฅผ ์‹œ์ž‘ํ•˜์„ธ์š”!

์ด ํŽ˜์ด์ง€๊ฐ€ ๋„์›€์ด ๋˜์—ˆ๋‚˜์š”?
0 / 5 - 0 ๋“ฑ๊ธ‰