카테고리 없음
immutable (불변성)을 지키며 작성하는 코드 (feat.javascript)
shiningjean
2022. 6. 29. 16:53
Immutable
왜 immutable을 사용하는가??
=> 로직 외의 부분에서 내용이 수정될 수 있다.
function sleep(ms) {
return new Promise((r) => setTimeout(r, ms));
}
async function logicA1(mymap) {
await sleep(100);
mymap['a'] = 1;
await sleep(100);
console.log("logicA1", mymap['a']);
};
async function logicA2(mymap) {
await sleep(100);
mymap['a'] = 2;
await sleep(100);
console.log("logicA2", mymap['a']);
};
async function main() {
const mymap = {};
await Promise.all([logicA1(mymap), logicA2(mymap)])
};
main();
Aggregation
데이터들을 조합해서 원하는 데이터 형태로 만들어주는 과정.
const { Map } = require('immutable');
const users = Map([
["user1", {name: "A", phone: "010-xxxx-xxx1"}],
["user2", {name: "B", phone: "010-xxxx-xxx2"}],
["user3", {name: "B", phone: undefined}],
]);
console.log(users.map(e => e.phone).filter(e => e !== undefined).reduce((r, n) => r + n, '')) // 010-xxxx-xxx1010-xxxx-xxx2
mongodb에서도 aggregation이란게 있는데 nosql에는 join이 없어서 map.reduce방식으로 join해서 결과를 만들어낸다!
천만 건이 넘을 경우는 RDBMS의 조인보다 훨씬 성능이 좋다! map.reduce는 다양하게 쓰임. (피보나치 수열같은 동작원리)
List -> Map (List를 Map으로)
const { Map, List } = require('immutable');
const users = List([
{id: "user1", name: "A", phone: "010-xxxx-xxx1"},
{id: "user2", name: "B", phone: "010-xxxx-xxx2"},
{id: "user3", name: "B", phone: undefined},
]);
console.log(
Map(users.map(e => [e.id, { name: e.name, phone: e.phone }])).toJS()
)
// {
// user1: { name: 'A', phone: '010-xxxx-xxx1' },
// user2: { name: 'B', phone: '010-xxxx-xxx2' },
// user3: { name: 'B', phone: undefined }
// }
실제 사용 사례
RESTful하게 바꾸면 모든 join된 데이터를 한번에 주는게 아니라 front단에서 여러 API를 가져와 aggregation처럼 join해서 전처리 해서 사용
ex) getUser에서 userId를 주면 (immutable한 param) Map으로 value로 유저 정보를 내려주겠다.
const { Map } = require('immutable');
async function getFeeds(...): Map<string, {...}>;
async function getLikes(currentUserId: string, feedIds: Set<string>): Map<string, boolean>;
async function getUsers(userIds: Set<string>): Map<string, {...}>;
async function getBrokers(userIds: Set<string>): Map<string, {...}>;
async function main() {
const feeds = await getFeeds();
// Map([
// ["feed1", {writer: "user1", contents: "아아아아아..."}],
// ["feed2", {writer: "user1", contents: "가가가가가..."}],
// ["feed3", {writer: "user2", contents: "나나나나나..."}],
// ["feed4", {writer: "user2", contents: "다다다다다..."}],
//]);
const [users, likes] = await Promise.all([
getUsers(feeds.map(e => e.writer)).toSet(),
//Map([
// ["user1", {name: "A", type: "BROKER", phone: "010-xxxx-xxxx"}],
// ["user2", {name: "B", type: "CUSTOMER", phone: "010-xxxx-xxxx"}],
//]);
getLikes("currentUserId", feeds.keySeq().toSet())),
//Map([
// ["feed1", true],
// ["feed2", false],
// ["feed3", false],
// ["feed4", false],
//]);
]);
const brokers = await getBrokers(users.filter(e => e.type === "BROKER").keySeq().toSet());
//Map([
// ["user1", {score: 4.5}]
//]);
const combinedFeeds = feeds.map((e, k) => {
const user = users.get(e.writer);
const like = likes.get(k);
const broker = brokers.get(e.writer);
return {
writer: {
id: e.writer,
type: user.type,
score: broker?.score,
name: user.name,
phone: user.phone
},
like: like === true,
contents: e.contents
}
})
console.log(combinedFeeds.get("feed1"));
}
* get보다 upert같은 업데이트 치는 로직이 어떻게 보면 더 중요하다(사견)
동남아 같은 네트워크 상황이 낙후된 지역에서는 데이터를 묶어서 보내주기도 하는게 나을 수 있음.