J124 | J153 | J190 | S002 | S015 |
---|---|---|---|---|
์ ์ ๊ท(sunkest) | ์ด์ ํ(lcpnine) | ์กฐ๋ณ๊ฑด(marulloc) | ๊ฐ๋ณ๋ฏผ(mike123789-dev) | ๋ฅ์ฐ์(yeonduing) |
Link to Web Dev Logs
Link to iOS Dev Logs
[Web ์คํํ๋ฉด]
๋ค์ํ ํ๋ก์ ํธ์์ ๋ ๋ฆฝ์ ์ผ๋ก ์ ์ฉ ๊ฐ๋ฅํ User Event Collector ์ ์
User Event ? UI/UX ๊ฐ์ ๋ฑ์ ์ํด ์์งํ๋ Event
ํ๋ก์ ํธ ๋ง๋ค **์๋ฏธ ์๋ ์ด๋ฒคํธ**๋ ๋ค๋ฅผ ๊ฒ ์ ๋๋ค. **DIVE**๋ ์์ ๋ ๋๊ฒ ์ค๊ณ๋์ด, **์๋ฏธ ์๋ ์ด๋ฒคํธ**์ ๋ฒ์ฃผ๋ฅผ ๊ฐ๋ฐ์๊ฐ ์ ํ ์ ์์ต๋๋ค.
์ฆ, ๊ฐ๋ฐ์๊ฐ ์ํ๋ค๋ฉด, ๊ธฐ๋ณธ์ ์ผ๋ก ์ ๊ณต๋๋ ์ด๋ฒคํธ ๋ฟ๋ง ์๋๋ผ ์น์ ๊ฒฝ์ฐ, ๋จ์ผ ์ด๋ฒคํธ ์ฌ๋ฌ๊ฐ๋ก ์ด๋ฃจ์ด์ง ๋ณตํฉ ์ด๋ฒคํธ๋ฅผ ์์งํ๊ฑฐ๋, ์ฑ์ ๊ฒฝ์ฐ, ์ฑ์ ์ข ๋ฃํ๊ฑฐ๋ ๋ ธ๋๋ฅผ ์ฌ์ํ๋ ์ด๋ฒคํธ๋ค์ ์์งํ ์ ์์ต๋๋ค.
**DIVE**๋ฅผ ์ด์ฉํ์ฌ, ์ํ๋ ์ด๋ฒคํธ๋ฅผ ์์งํ ์ ์์ผ๋ฉฐ, ์์งํ ๋ฐ์ดํฐ๋ UI/UX ๊ฐ์ ์ ์ค์ํ ๋ฐ์ดํฐ๊ฐ ๋ ๊ฒ์ ๋๋ค.
DIVE์ ๋์์ ๋ณด์ด๊ธฐ ์ํ์ฌ, Naver ์คํธ๋ฆฌ๋ฐ ์๋น์ค VIBE๋ฅผ Cloneํ์ฌ ์ด๋ฒคํธ๋ฅผ ์์งํ์ต๋๋ค. Clone scope์์ VIBE์ ์ถ์ฒ ๊ธฐ๋ฅ๊ณผ ์์ ์ฌ์ ๊ธฐ๋ฅ์ ์ ์ธ
React ํ๋ก์ ํธ๋ผ๋ฉด, ์ด๋์๋ ์ฌ์ฉ์ด ๊ฐ๋ฅํ Event ์์ง๊ธฐ์ ๋๋ค.
Config Object ๋ฅผ ์์ฑํ๊ณ , ์ด๋ฒคํธ ๋ก๊น ์ ์ํ๋ ์ปดํฌ๋ํธ๋ฅผ Emitter ๋ก ๊ฐ์ธ๊ณ , ๋ถ๋ชจ ์ปดํฌ๋ํธ ์ด๋๊ฐ์์ Collector ๋ก ๊ฐ์ธ์ค๋ค๋ฉด ๋์ ๋๋ค.
๊ฐ๋จํ Native Event์ ์ฌ์ฉ์๊ฐ ์ํ๋ ์๋ฏธ๋ฅผ ๋ถ์ฌํ ์ ์์ผ๋ฉฐ, ์ฌ๋ฌ event๋ก ๊ตฌ์ฑ๋ ๋ณตํฉ ์ด๋ฒคํธ์๋ ์๋ฏธ๋ฅผ ๋ถ์ฌํ์ฌ ๋ก๊น ํ ์ ์์ต๋๋ค.
1. Event Config Object
โ ์ฌ์ฉ์๊ฐ ์ํ๋ Event๋ค์ด ๋์ด๋์ด ์๋ค.
โ ์กฐ๊ฑด์ด ์ถฉ์กฑ๋๋ฉด, ์ฌ์ฉ์์๊ฒ ์ฃผ์ด์ง Event๋ค์ ์ ์
โ Event์ ์ต์ ๋ค์ ์ ์
โ ์ฌ๋ฌ๊ฐ์ Config Object๊ฐ ์กด์ฌ ํ ์ ์๋ค.
โ ์ํ๋ Collector์๊ฒ ์ํ๋ Config Object๋ฅผ ๋๊ธธ ์ ์๋ค.
2. Collector
โ config object์์ ์ ์๋ ์ด๋ฒคํธ๋ค์ ํด์
โ Emiiter๋ก๋ถํฐ ์ ํ๋๋ ์ด๋ฒคํธ๋ค์ ๊ฐ์ง ๋ฐ ํํฐ๋ง
โ ๊ฐ์ง๋ ์ด๋ฒคํธ์ ๋ํด dispatch๋ก ์ ๋ฌ
โ dispatch: ์ฌ์ฉ์๊ฐ ์ง์ ์ ์ํ ์ ์๋ ์ด๋ฒคํธ ํธ๋ค๋ฌ.
3. Emitter
โ ์ฌ์ฉ์๊ฐ ์ ์ํ Event๊ฐ ๋ฐ์ํ๋ Wrapping Component
โ Event๊ฐ Bubbling๋๊ธฐ ์ , Event ๊ฐ์ฒด์ props์ Event ID๋ฅผ ์ฝ์ ํ๋ค.
โ Native Event๊ฐ ์๋๋ผ, ์ปดํฌ๋ํธ์ ์ํ ๊ฐ์ ์กฐ๊ฑด์ผ๋ก Event๋ฅผ ๋ฐ์์ํฌ ์ ์๋ค.
4. Dispatch
โ Collector์ ์ธ์๋ก ๋๊ฒจ์ผ ํ๋ ํจ์๋ก ์ฌ์ฉ์๊ฐ ์ง์ ์ ์ํด์ผ ํฉ๋๋ค.
โ ๋ก๊น ๋๋ ์ด๋ฒคํธ์ getterํจ์๋ก ์๊ฐํ๋ฉด ๋ฉ๋๋ค.
โ Collector๋ ์ฌ์ฉ์๊ฐ ์ ์ํ ์ด๋ฒคํธ ๋ฐ์ ์กฐ๊ฑด์ ๋ง์กฑํ๋ฉด dispatch๋ฅผ ํธ์ถํฉ๋๋ค.
โ ๋ฐ๋ผ์, dispatch ํจ์๋, ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ์ ๋ ์ฒ๋ฆฌํ๋ ๋ก์ง์ ๋ด๊ณ ์์ด์ผ ํฉ๋๋ค.
const example1: EventObject = {
simple: {
identifier_1: {
event_id: 1,
event_type: "click",
description: "ํด๋ฆญ ์ด๋ฒคํธ ๋ฐ์",
},
identifier_2: {
event_id: 2,
event_type: "mouseover",
description: "๋ง์ฐ์ค ์ค๋ฒ ์ด๋ฒคํธ ๋ฐ์",
},
}
}
- Simple ์๋ ๋จ์ผ Event๋ฅผ ์ ์ํฉ๋๋ค.
line [2]
- DIVE (our event collector)๋ "identifier_1"๊ณผ ๊ฐ์ด string์ผ๋ก event๋ฅผ ์๋ณํฉ๋๋ค. ๋ฐ๋ผ์ identifier_1๊ณผ ๊ฐ์ด ๊ฐ์ฒด์ key๊ฐ์ Uniqueํด์ผ ๋ฉ๋๋ค.
line [3][9]
- DIVE ๋ ์ฌ์ฉ์๊ฐ event_type์ ์
๋ ฅํ event์ ๋ฐ๋ผ, event log๋ฅผ ๋ด๋ณด๋
๋๋ค.
DIVE ๋ Native Event๋ฅผ ๋๋ถ๋ถ ์ง์ํฉ๋๋ค.
line [5][11]
- ๋ํ
["click","mouseover"]
์ ๊ฐ์ด ์ ๋ ฅ์ ํ๋ค๋ฉด, Emitter ๊ฐ ๊ฐ์ธ๋ ์ปดํฌ๋ํธ์์ click, mouseover์ ๋ํด DIVE๊ฐ Event log๋ฅผ ๋จ๊น๋๋ค. - description ๋ optional์ ๋๋ค. description์ ์ ๋ ฅํ๋ค๋ฉด, event log์ description์ด ๋ด๊ธธ ๊ฒ์ ๋๋ค.
import { EventObject } from "./collector";
const example1: EventObject = {
simple: {
identifier_1: {
event_id: 1,
event_type: ["click"],
once: true,
description: "ํด๋ฆญ ์ด๋ฒคํธ ๋ฐ์",
},
identifier_2: {
event_id: 2,
event_type: ["mouseover"],
once: true,
description: "๋ง์ฐ์ค ์ค๋ฒ ์ด๋ฒคํธ ๋ฐ์",
},
identifier_3: {
event_id: 4,
event_type: ["click"],
once: false,
description: "๋ค์ ํด๋ฆญ ์ด๋ฒคํธ ๋ฐ์",
},
},
complex: {
{
timer: 3000,
sequence: ["identifier_1", "identifier_2", "identifier_1"],
event_id: 3,
once: false,
description: "์๋จ์ 3๊ฐ์ง ์ด๋ฒคํธ๊ฐ ๋ชจ๋ ๋ฐ์ํ๋ฉด ํด๋น ์ด๋ฒคํธ๊ฐ ์์ง๋ฉ๋๋ค",
},
},
};
export default example1;
- complex ์๋ ๋ณตํฉ ์ด๋ฒคํธ๋ฅผ ์ ์ํฉ๋๋ค.
- sequence ์๋, simple์์ ์ ์ํ ๋จ์ผ ์ด๋ฒคํธ์ ์๋ณ์๊ฐ ๋ฐฐ์ด ํํ๋ก ๋ค์ด๊ฐ๋๋ค.
- sequence์ ๋์ดํ ์ด๋ฒคํธ๋ค์ด, timer ์ ์์ฑํ ms๊ฐ ๋๋ ๋ ๊น์ง ๋ชจ๋ ๋ฐ์ํ๋ค๋ฉด, ์ด๋ฒคํธ๋ฅผ ๋ก๊น ํฉ๋๋ค. ์ฌ๊ธฐ์ , 3์ด ์์, identifier1, identifier2, identifier1์ด ๋ฐ์ํ ๋, ์ด๋ฒคํธ๋ฅผ ๋ก๊น ํฉ๋๋ค.
Note: ์ด๋ฒคํธ์ ๋ก๊น ์ Collector์์ ์ด๋ค์ง๋๋ค. ์ด๋ฒคํธ ๋ก๊น ์ด ๋ฐ์ํ๋ฉด, Collector๋ ์ฌ์ฉ์๊ฐ ๋๊ธด dispatchํจ์๋ฅผ ํธ์ถํฉ๋๋ค. ์ด๋ฒคํธ ๊ฐ์ฒด๋ฅผ dispatch ํจ์์ ์ธ์๋ก ๋๊ธฐ๋ฉด์, ์ฌ์ฉ์๊ฐ dispatch๋ฅผ ์ ์ํ๋๋ก event๋ฅผ ์ฌ์ฉํ ์ ์์ต๋๋ค.
const IndexPage = () => {
return (
<Collector eventConfig={example1} dispatch={(e) => {console.log(e)}}>
<div>
<Emitter identifier="testH1Event" eventType={["click"]}>
<h1>Click Event Tester</h1>
</Emitter>
<div>Nothing Div</div>
<Emitter identifier="testComponentEvent" eventType={["mouseover"]}>
<TestComponent />
</Emitter>
</div>
</Collector>
);
};
- Collector ๋ ํ๋์ React Component๋ก, ์ ์ฝ๋์์์ ๊ฐ์ด ์ํ๋ ์ปดํฌ๋ํธ ๋ฐ๊นฅ์ชฝ์ ๋ํํฉ๋๋ค.
- ํ๋์ Collector ์์ชฝ์ ์๋ ์ฌ๋ฌ ๊ฐ์ Emitter ๋ค๋ก ๋ถํฐ ๋ฐ์๋ ๋ชจ๋ ์ด๋ฒคํธ๋ ๋ชจ๋ ๊ฐ์ Collector์์ ์์ง๋ฉ๋๋ค.
- ํ๋์ Complex Event์ ํฌํจ๋๋ Simple Event ๋ค์ ํ๋์ Collector์์ ์์ฑ๋์ด์ผ ํฉ๋๋ค.
- ์ฃผ์ด์ง๋ props๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
- eventConfig: ์์ ์ค๋ช ๋ ์ด๋ฒคํธ ์ ์ object
- dispatch: ํด๋น Collector์์ ์ด๋ฒคํธ ๊ฐ์ง์ ํธ์ถ๋ ์ฝ๋ฐฑ ๋ฉ์๋. dispatch์ ์์ฑ์ ๋ํด์๋ ํ์ ๋ฉ๋๋ค.
Note: Collector๋ฅผ ์ด๋ค ์ปดํฌ๋ํธ์ ๋ํํ ๊ฒ์ธ์ง ์ ํ๋ ๊ฒ์ ๊ฐ๋ฐ์์ ๋ชซ์ ๋๋ค. ๋ค๋ง, ์ ์ญ์ผ๋ก ์ฌ์ฉํ๊ฑฐ๋, ๋๋ฌด ํฐ ํ์ด์ง์ ๊ฐ์ ์ปดํฌ๋ํธ์ ์ฌ์ฉ๋๋ค๋ฉด ํ๋์ Collector์ ๋ฒ๋ธ๋ง๋๋ ์ด๋ฒคํธ๊ฐ ๊ณผ๋ํ๊ฒ ๋ง์์ง ์ ์์ต๋๋ค. ๊ฐ๋ฅํ๋ค๋ฉด, ์ ์ ํ Collector๋ฅผ ๋ถ๋ฆฌํ๋ ๊ฒ์ ๊ถ์ฅํฉ๋๋ค.
- Emitter ๋ํ ํ๋์ React Component๋ก, ๊ธฐ๋ณธ ์ด๋ฒคํธ ์์ง ๋์ ์ปดํฌ๋ํธ ๋ฐ๋ก ๋ฐ๊นฅ์ชฝ์ ๋ํํฉ๋๋ค.
- ์ฃผ์ด์ง๋ props๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
- identifier: ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ ์ปดํฌ๋ํธ๋ฅผ ๊ตฌ๋ถํ ์๋ณ์๋ก, ๋ฌธ์์ด ํํ์ ๋๋ค. config object์ ์ ์ํ ์๋ณ์๊ฐ ๋ค์ด๊ฐ๋๋ค.
- eventType: ๋ฐ์๋ ์ด๋ฒคํธ์ ๋ํ ์ ์๊ฐ ๋ค์ด๊ฐ๋ฉฐ, ๋ฌธ์์ด ๋๋ object ์ ๋ฐฐ์ด ํํ๋ก ์
๋ ฅ๋ฐ์ผ๋ฉฐ ์ฌ๋ฌ ๊ฐ๋ฅผ ์
๋ ฅํ ์๋ ์์ต๋๋ค.
- eventType์ ๋ค์ด๊ฐ Object ์์ :
-
{ eventType: "click", restrictFire: { method: "throttle", time: 3, }
- ๋ณ๋ option๋ค์ด ํ์ํ์ง ์์ ๊ฒฝ์ฐ string ํํ๋ก eventType๋ง ์ ๋ ฅํ ์๋ ์์ต๋๋ค.
- Emitter๋ก ๊ฐ์ผ ์ปดํฌ๋ํธ์์ eventType์ผ๋ก ์ง์ ํ ์ด๋ฒคํธ๊ฐ ๋ฐ์๋ ๊ฒฝ์ฐ, identifier, ๋ธ๋ผ์ฐ์ ์ nativeEvent์ ๋ณด, children์ props ๋ฑ ๋ช๊ฐ์ง ์ ๋ณด๋ฅผ ๋ด์ ๊ฐ์ฒด๋ฅผ ๋ถ๋ชจ ์์๋ก ๋ฒ๋ธ๋งํฉ๋๋ค.
- children์ด ๋ฐ๋์ single React element์ผ ํ์๋ ์์ง๋ง single React element๊ฐ ์๋๋ผ๋ฉด children props๋ undefined๋ก ๋ฒ๋ธ๋ง ๋ ๊ฒ์ ๋๋ค.
- ์ด๋ ์ ๋ฒ๋ธ๋ง ๋๋ ์ด๋ฒคํธ๋ Collector๋ฅผ ๋ง๋ ๋ ๊น์ง ๋ฒ๋ธ๋ง๋๋ฉฐ, Collector๋ฅผ ๋ง๋๋ฉด config object ์ ๋ณด์, identifier, eventType์ ๋น๊ตํ์ฌ ํํฐ๋ง๋๊ณ , ์์ง ๋์์ธ ์ด๋ฒคํธ์ ๊ฒฝ์ฐ dispatch์ ์ ๋ฌ๋ฉ๋๋ค.
- Collector ์ ์ธ์๋ก ๋๊ฒจ์ง๋ ํจ์๋ก, ์ฌ์ฉ์๊ฐ ์ง์ ์ ์ํด์ผ ํฉ๋๋ค.
dispatch={console.log}
์ ๊ฐ์ด ๋๊ฒจ์ง๋๋ค. ์ ์๋ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๋ฉด, Collector ๋ ๋ฐ๋ก dispatch ๋ฅผ ํธ์ถํฉ๋๋ค.- dispatch์ ๋๊ฒจ์ง๋ ์ธ์๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
dispatch({ userEvent : {user๊ฐ config object์ ์ ์ํ ๊ฐ์ฒด}, data : {Emitter๊ฐ ๋ํํ๊ณ ์๋ ์ปดํฌ๋ํธ์ props}, nativeEvent : {๋ธ๋ผ์ฐ์ ์ native ์ด๋ฒคํธ ๊ฐ์ฒด} })
- data ๋ฅผ ํตํด, map์ ํตํด ์์ฑ๋ ์ปดํฌ๋ํธ๋ผ๋, ์ด๋ ์์๋ฅผ ํด๋ฆญํ๋์ง ์ฌ์ฉ์๊ฐ dispatch ํจ์๋ฅผ ํตํด ํ๋จํ ์ ์์ต๋๋ค.
- nativeEvent ์ userEvent ๊ฐ์ฒด๋ฅผ ๋ฐ์ ์ฌ์ฉ์๊ฐ ์์ ๋กญ๊ฒ ์ด์ฉํ ์ ์๊ฒ ํ์ต๋๋ค.
- Event
- Event Collector์์ ์ ๊ณตํ๋ ๋ชจ๋ ์ด๋ฒคํธ.
Event
ํ๋กํ ์ฝ ์ฑํ
- EventManager
- ์ด๋ฒคํธ๋ฅผ ๋ก๊น ํ๊ธฐ ์ํ ์ต์๋จ API, ์ค์ ๋ก ๋ก๊น ์ํ์ง๋ ์๊ณ ,
EventEngine
์ ์ด์ฉํ์ฌ ๋ณด๋.
- EventEngine
- ์ง์ ์ ์ผ๋ก ๋ก๊น ์ ์ก/์ ์ฅ์ ๋ด๋น.
EventSendable
,EventFetchable
ํ๋กํ ์ฝ ์ฑํ
public protocol Event: Codable {
var name: String { get }
var createdAt: String? { get }
var metadata: [String: String]? { get }
}
๊ธฐ๋ณธ์ ์ผ๋ก ์ ๊ณต๋๋ ์ด๋ฒคํธ
class BaseEvent: Event {
var name: String
var createdAt: String?
var metadata: [String: String]?
public init(name: String, createdAt: String?, metadata: [String: String]?) {
self.name = name
self.createdAt = createdAt
self.metadata = metadata
}
}
Event ํ๋กํ ์ฝ์ ์ฑํํ๋ Custom Event์ ์์
struct ScreenEvent: Event {
var name: String
var metadata: [String: String]?
private init(name: String, metadata: [String: String]? = nil) {
self.name = name
self.metadata = metadata
}
static let playerPushed = ScreenEvent(name: "playerPushed")
static let playerPopped = ScreenEvent(name: "playerPopped")
}
public protocol EventSendable: class {
func send<T: Event>(_ event: T)
}
public protocol EventFetchable: class {
func fetch() -> [BaseEvent]
}
public protocol EventSendableAndFetchable: EventSendable, EventFetchable {
}
๊ธฐ๋ณธ์ ์ผ๋ก ์ ๊ณต๋๋ Engine
public final class MockServerEngine: EventSendable {
public init() {
}
public func send<T: Event>(_ event: T) {
print("MockServer - \(event.name)")
event.metadata?.forEach { key, value in
print("ใด \(key) : \(value)")
}
}
}
Event
protocol๋ก ๊ตฌํํจ์ผ๋ก์จ, ์๋ก์ด ์ด๋ฒคํธ๋ฅผ ์ถ๊ฐํ๋๊ฒ์ ๋งค์ฐ ๊ฐํธํด์ง๋๋ค.
Event
protocol์ ์ฑํํ๋ custom type์ ์ด๋ฒคํธ๋ฅผ ๊ตฌํํจ์ผ๋ก์จ, ์ํ๋ ์ด๋ฒคํธ์ ๋ํ ์๋์์ฑ ๊ฒฐ๊ณผ๋ฅผ ๋ณผ์ ์์ต๋๋ค.
EventSendable
, EventFetchable
protocol์ ์ฑํํ๋ ์์ง์ ๋ค์ํ๊ฒ ๊ตฌํํ ์ ์์ต๋๋ค.
๊ทธ๋ฆฌ๊ณ ์ํฉ์ ๋ง๊ฒ ํ์ํ ์์ง์ ๊ฐ์ ๋ผ์ฐ๋๊ฒ๋ ๋งค์ฐ ์ฝ์ต๋๋ค.
๋ํ, EventManager๋ ๋ค์์ ์์ง์ ๊ฐ์ง ์๋ ์์ต๋๋ค.
์ค์ ๋ก ์ ํฌ ์ฑ์์๋ back end server๋ฅผ ์ํ engine
๊ณผ core data๋ฅผ ์ํ engine
๋๊ฐ๋ฅผ ๊ตฌํํ๊ณ ์ฃผ์
ํ์ต๋๋ค.
์ด๋ ํ๋ก์ ํธ์์๋ ์ฌ์ฉ ๊ฐ๋ฅํ๋๋ก Swift package manager๋ฅผ ์ด์ฉํ ์ค์น๊ฐ ๊ฐ๋ฅํฉ๋๋ค.
- Xcode ๋ฉ๋ด์์ File > Swift Packages > Add Package Dependency๋ฅผ ์ ํํ
https://github.com/mike123789-dev/DiveEventCollector
๋ฅผ ์ ๋ ฅํฉ๋๋ค
Web Dev Logs | Author |
---|---|
Next.js | ์กฐ๋ณ๊ฑด |
Sequelize ๋ ๋๋ณด๋ด๊ธฐ | ์ด์ ํ |
Prisma ๋์ ๊ณผ ์ฌ์ฉ๋ฒ | ์ด์ ํ |
Vercel๋ก Next app ๋ฐฐํฌํ๊ธฐ | ์ด์ ํ |
Jenkins๋ก CI ๊ตฌํํ๊ธฐ | ์กฐ๋ณ๊ฑด |
Naver OAuth2.0 ์ฐ๋ํ๊ธฐ | ์ ์ ๊ท |
์ฐ๋ฆฌ๋ง์ Storybook ํ์ฉ๋ฒ... Spread Operator(...)๋ก props๋ฅผ ์ ๋ฌํ๋ ๊ฒ์ ์ ๋ง anti-pattern์ธ๊ฐ? |
์กฐ๋ณ๊ฑด,์ด์ ํ,์ ์ ๊ท |