Ecoer Logo
VOTING POWER100.00%
DOWNVOTE POWER100.00%
RESOURCE CREDITS100.00%
REPUTATION PROGRESS0.00%
Net Worth
0.025USD
STEEM
0.003STEEM
SBD
0.036SBD
Effective Power
5.007SP
├── Own SP
0.125SP
└── Incoming Deleg
+4.882SP

Detailed Balance

STEEM
balance
0.000STEEM
market_balance
0.000STEEM
savings_balance
0.000STEEM
reward_steem_balance
0.003STEEM
STEEM POWER
Own SP
0.125SP
Delegated Out
0.000SP
Delegation In
4.882SP
Effective Power
5.007SP
Reward SP (pending)
0.020SP
SBD
sbd_balance
0.000SBD
sbd_conversions
0.000SBD
sbd_market_balance
0.000SBD
savings_sbd_balance
0.000SBD
reward_sbd_balance
0.036SBD
{
  "balance": "0.000 STEEM",
  "savings_balance": "0.000 STEEM",
  "reward_steem_balance": "0.003 STEEM",
  "vesting_shares": "203.852317 VESTS",
  "delegated_vesting_shares": "0.000000 VESTS",
  "received_vesting_shares": "7939.807489 VESTS",
  "sbd_balance": "0.000 SBD",
  "savings_sbd_balance": "0.000 SBD",
  "reward_sbd_balance": "0.036 SBD",
  "conversions": []
}

Account Info

namemnkim
id937523
rank316,037
reputation454084791
created2018-04-12T00:47:48
recovery_accountsteem
proxyNone
post_count4
comment_count0
lifetime_vote_count0
witnesses_voted_for0
last_post2018-06-06T13:57:09
last_root_post2018-06-05T09:08:06
last_vote_time2018-06-06T13:57:15
proxied_vsf_votes0, 0, 0, 0
can_vote1
voting_power0
delayed_votes0
balance0.000 STEEM
savings_balance0.000 STEEM
sbd_balance0.000 SBD
savings_sbd_balance0.000 SBD
vesting_shares203.852317 VESTS
delegated_vesting_shares0.000000 VESTS
received_vesting_shares7939.807489 VESTS
reward_vesting_balance40.655714 VESTS
vesting_balance0.000 STEEM
vesting_withdraw_rate0.000000 VESTS
next_vesting_withdrawal1969-12-31T23:59:59
withdrawn0
to_withdraw0
withdraw_routes0
savings_withdraw_requests0
last_account_recovery1970-01-01T00:00:00
reset_accountnull
last_owner_update1970-01-01T00:00:00
last_account_update1970-01-01T00:00:00
minedNo
sbd_seconds0
sbd_last_interest_payment1970-01-01T00:00:00
savings_sbd_last_interest_payment1970-01-01T00:00:00
{
  "id": 937523,
  "name": "mnkim",
  "owner": {
    "weight_threshold": 1,
    "account_auths": [],
    "key_auths": [
      [
        "STM83T3qMZ6smHSVkVu9bzsfZYmkuB8HTr7UaPBhCd2jcAcX1xxAC",
        1
      ]
    ]
  },
  "active": {
    "weight_threshold": 1,
    "account_auths": [],
    "key_auths": [
      [
        "STM85PsTh3MXSxG8hspgT4LoQrpayLqHiMSRGFVufs9rnY5cAi1VZ",
        1
      ]
    ]
  },
  "posting": {
    "weight_threshold": 1,
    "account_auths": [],
    "key_auths": [
      [
        "STM6adjVawMAg7bnZaGoxxqs2CEQdq16HvpAcfrhZ7PWtAdQpRVRb",
        1
      ]
    ]
  },
  "memo_key": "STM7NCpqSwzRLX8fCWvoyCaLsVCBBbLEYoiJA9vtFk4KKemk1BitM",
  "json_metadata": "{}",
  "posting_json_metadata": "",
  "proxy": "",
  "last_owner_update": "1970-01-01T00:00:00",
  "last_account_update": "1970-01-01T00:00:00",
  "created": "2018-04-12T00:47:48",
  "mined": false,
  "recovery_account": "steem",
  "last_account_recovery": "1970-01-01T00:00:00",
  "reset_account": "null",
  "comment_count": 0,
  "lifetime_vote_count": 0,
  "post_count": 4,
  "can_vote": true,
  "voting_manabar": {
    "current_mana": "8143659806",
    "last_update_time": 1779076533
  },
  "downvote_manabar": {
    "current_mana": 2035914951,
    "last_update_time": 1779076533
  },
  "voting_power": 0,
  "balance": "0.000 STEEM",
  "savings_balance": "0.000 STEEM",
  "sbd_balance": "0.000 SBD",
  "sbd_seconds": "0",
  "sbd_seconds_last_update": "1970-01-01T00:00:00",
  "sbd_last_interest_payment": "1970-01-01T00:00:00",
  "savings_sbd_balance": "0.000 SBD",
  "savings_sbd_seconds": "0",
  "savings_sbd_seconds_last_update": "1970-01-01T00:00:00",
  "savings_sbd_last_interest_payment": "1970-01-01T00:00:00",
  "savings_withdraw_requests": 0,
  "reward_sbd_balance": "0.036 SBD",
  "reward_steem_balance": "0.003 STEEM",
  "reward_vesting_balance": "40.655714 VESTS",
  "reward_vesting_steem": "0.020 STEEM",
  "vesting_shares": "203.852317 VESTS",
  "delegated_vesting_shares": "0.000000 VESTS",
  "received_vesting_shares": "7939.807489 VESTS",
  "vesting_withdraw_rate": "0.000000 VESTS",
  "next_vesting_withdrawal": "1969-12-31T23:59:59",
  "withdrawn": 0,
  "to_withdraw": 0,
  "withdraw_routes": 0,
  "curation_rewards": 0,
  "posting_rewards": 39,
  "proxied_vsf_votes": [
    0,
    0,
    0,
    0
  ],
  "witnesses_voted_for": 0,
  "last_post": "2018-06-06T13:57:09",
  "last_root_post": "2018-06-05T09:08:06",
  "last_vote_time": "2018-06-06T13:57:15",
  "post_bandwidth": 0,
  "pending_claimed_accounts": 0,
  "vesting_balance": "0.000 STEEM",
  "reputation": 454084791,
  "transfer_history": [],
  "market_history": [],
  "post_history": [],
  "vote_history": [],
  "other_history": [],
  "witness_votes": [],
  "tags_usage": [],
  "guest_bloggers": [],
  "rank": 316037
}

Withdraw Routes

IncomingOutgoing
Empty
Empty
{
  "incoming": [],
  "outgoing": []
}
From Date
To Date
steemdelegated 4.882 SP to @mnkim
2026/05/18 03:55:33
delegateemnkim
delegatorsteem
vesting shares7939.807489 VESTS
Transaction InfoBlock #106147834/Trx b73a78f806b8b6e66a121e39020169e6d5e405ab
View Raw JSON Data
{
  "block": 106147834,
  "op": [
    "delegate_vesting_shares",
    {
      "delegatee": "mnkim",
      "delegator": "steem",
      "vesting_shares": "7939.807489 VESTS"
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2026-05-18T03:55:33",
  "trx_id": "b73a78f806b8b6e66a121e39020169e6d5e405ab",
  "trx_in_block": 3,
  "virtual_op": 0
}
steemdelegated 3.214 SP to @mnkim
2026/05/12 18:43:09
delegateemnkim
delegatorsteem
vesting shares5227.597084 VESTS
Transaction InfoBlock #105993526/Trx 0491263b8dfbdfc857f7eb26b46d87c1fa5f41a8
View Raw JSON Data
{
  "block": 105993526,
  "op": [
    "delegate_vesting_shares",
    {
      "delegatee": "mnkim",
      "delegator": "steem",
      "vesting_shares": "5227.597084 VESTS"
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2026-05-12T18:43:09",
  "trx_id": "0491263b8dfbdfc857f7eb26b46d87c1fa5f41a8",
  "trx_in_block": 0,
  "virtual_op": 0
}
steemdelegated 4.889 SP to @mnkim
2026/04/26 03:10:42
delegateemnkim
delegatorsteem
vesting shares7952.323245 VESTS
Transaction InfoBlock #105515382/Trx d3807cb171dc9272dfc88ba2ed47642fda01cba4
View Raw JSON Data
{
  "block": 105515382,
  "op": [
    "delegate_vesting_shares",
    {
      "delegatee": "mnkim",
      "delegator": "steem",
      "vesting_shares": "7952.323245 VESTS"
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2026-04-26T03:10:42",
  "trx_id": "d3807cb171dc9272dfc88ba2ed47642fda01cba4",
  "trx_in_block": 2,
  "virtual_op": 0
}
steemdelegated 3.240 SP to @mnkim
2026/01/23 17:39:03
delegateemnkim
delegatorsteem
vesting shares5269.143903 VESTS
Transaction InfoBlock #102863612/Trx b4ef1ff622f10a1e8fadbbd54f72a755ff390e3d
View Raw JSON Data
{
  "block": 102863612,
  "op": [
    "delegate_vesting_shares",
    {
      "delegatee": "mnkim",
      "delegator": "steem",
      "vesting_shares": "5269.143903 VESTS"
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2026-01-23T17:39:03",
  "trx_id": "b4ef1ff622f10a1e8fadbbd54f72a755ff390e3d",
  "trx_in_block": 26,
  "virtual_op": 0
}
steemdelegated 3.341 SP to @mnkim
2024/12/17 12:51:36
delegateemnkim
delegatorsteem
vesting shares5433.363100 VESTS
Transaction InfoBlock #91309876/Trx 272179fb15a972a011bd1c34c86d12009dbcb3fa
View Raw JSON Data
{
  "block": 91309876,
  "op": [
    "delegate_vesting_shares",
    {
      "delegatee": "mnkim",
      "delegator": "steem",
      "vesting_shares": "5433.363100 VESTS"
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2024-12-17T12:51:36",
  "trx_id": "272179fb15a972a011bd1c34c86d12009dbcb3fa",
  "trx_in_block": 2,
  "virtual_op": 0
}
steemdelegated 3.445 SP to @mnkim
2023/11/14 04:33:18
delegateemnkim
delegatorsteem
vesting shares5602.496632 VESTS
Transaction InfoBlock #79864047/Trx deb37ed2f19cec860f5d11ee8276269533198a95
View Raw JSON Data
{
  "block": 79864047,
  "op": [
    "delegate_vesting_shares",
    {
      "delegatee": "mnkim",
      "delegator": "steem",
      "vesting_shares": "5602.496632 VESTS"
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2023-11-14T04:33:18",
  "trx_id": "deb37ed2f19cec860f5d11ee8276269533198a95",
  "trx_in_block": 0,
  "virtual_op": 0
}
steemdelegated 5.250 SP to @mnkim
2023/09/22 07:35:15
delegateemnkim
delegatorsteem
vesting shares8539.405418 VESTS
Transaction InfoBlock #78359511/Trx 51a333aeded4488d3f4a01853b313224f0b756fa
View Raw JSON Data
{
  "block": 78359511,
  "op": [
    "delegate_vesting_shares",
    {
      "delegatee": "mnkim",
      "delegator": "steem",
      "vesting_shares": "8539.405418 VESTS"
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2023-09-22T07:35:15",
  "trx_id": "51a333aeded4488d3f4a01853b313224f0b756fa",
  "trx_in_block": 1,
  "virtual_op": 0
}
steemdelegated 5.387 SP to @mnkim
2022/11/03 15:24:51
delegateemnkim
delegatorsteem
vesting shares8761.456856 VESTS
Transaction InfoBlock #69117692/Trx 611b08d34efe1c47e683c153f5a4b1423bfd95e9
View Raw JSON Data
{
  "block": 69117692,
  "op": [
    "delegate_vesting_shares",
    {
      "delegatee": "mnkim",
      "delegator": "steem",
      "vesting_shares": "8761.456856 VESTS"
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2022-11-03T15:24:51",
  "trx_id": "611b08d34efe1c47e683c153f5a4b1423bfd95e9",
  "trx_in_block": 1,
  "virtual_op": 0
}
steemdelegated 5.522 SP to @mnkim
2022/01/17 20:50:39
delegateemnkim
delegatorsteem
vesting shares8981.564457 VESTS
Transaction InfoBlock #60821218/Trx 6194343692cd55b568a8d3d74373ee30fffa1966
View Raw JSON Data
{
  "block": 60821218,
  "op": [
    "delegate_vesting_shares",
    {
      "delegatee": "mnkim",
      "delegator": "steem",
      "vesting_shares": "8981.564457 VESTS"
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2022-01-17T20:50:39",
  "trx_id": "6194343692cd55b568a8d3d74373ee30fffa1966",
  "trx_in_block": 7,
  "virtual_op": 0
}
steemdelegated 5.636 SP to @mnkim
2021/06/14 04:07:51
delegateemnkim
delegatorsteem
vesting shares9165.758745 VESTS
Transaction InfoBlock #54611677/Trx 4c1c93674c6fde63dbaba500a57f31b02b3a5283
View Raw JSON Data
{
  "block": 54611677,
  "op": [
    "delegate_vesting_shares",
    {
      "delegatee": "mnkim",
      "delegator": "steem",
      "vesting_shares": "9165.758745 VESTS"
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2021-06-14T04:07:51",
  "trx_id": "4c1c93674c6fde63dbaba500a57f31b02b3a5283",
  "trx_in_block": 10,
  "virtual_op": 0
}
steemdelegated 5.751 SP to @mnkim
2020/12/11 14:22:27
delegateemnkim
delegatorsteem
vesting shares9353.180719 VESTS
Transaction InfoBlock #49359010/Trx 7a2217a72053e384b94756c7b9fdf19db8d1f12d
View Raw JSON Data
{
  "block": 49359010,
  "op": [
    "delegate_vesting_shares",
    {
      "delegatee": "mnkim",
      "delegator": "steem",
      "vesting_shares": "9353.180719 VESTS"
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2020-12-11T14:22:27",
  "trx_id": "7a2217a72053e384b94756c7b9fdf19db8d1f12d",
  "trx_in_block": 4,
  "virtual_op": 0
}
steemdelegated 1.176 SP to @mnkim
2020/12/06 07:58:21
delegateemnkim
delegatorsteem
vesting shares1912.543513 VESTS
Transaction InfoBlock #49210541/Trx 5e838046b56667e5ff513ea3dabc7c3bf5067e16
View Raw JSON Data
{
  "block": 49210541,
  "op": [
    "delegate_vesting_shares",
    {
      "delegatee": "mnkim",
      "delegator": "steem",
      "vesting_shares": "1912.543513 VESTS"
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2020-12-06T07:58:21",
  "trx_id": "5e838046b56667e5ff513ea3dabc7c3bf5067e16",
  "trx_in_block": 3,
  "virtual_op": 0
}
steemdelegated 5.755 SP to @mnkim
2020/12/05 18:00:06
delegateemnkim
delegatorsteem
vesting shares9359.388573 VESTS
Transaction InfoBlock #49194093/Trx 832654d4ff5c8faf5402011e7270b589f7b08252
View Raw JSON Data
{
  "block": 49194093,
  "op": [
    "delegate_vesting_shares",
    {
      "delegatee": "mnkim",
      "delegator": "steem",
      "vesting_shares": "9359.388573 VESTS"
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2020-12-05T18:00:06",
  "trx_id": "832654d4ff5c8faf5402011e7270b589f7b08252",
  "trx_in_block": 0,
  "virtual_op": 0
}
steemdelegated 1.181 SP to @mnkim
2020/11/02 22:22:03
delegateemnkim
delegatorsteem
vesting shares1920.017158 VESTS
Transaction InfoBlock #48265727/Trx 6d15cf57871fb00104c2c9871189ca521fc10ba3
View Raw JSON Data
{
  "block": 48265727,
  "op": [
    "delegate_vesting_shares",
    {
      "delegatee": "mnkim",
      "delegator": "steem",
      "vesting_shares": "1920.017158 VESTS"
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2020-11-02T22:22:03",
  "trx_id": "6d15cf57871fb00104c2c9871189ca521fc10ba3",
  "trx_in_block": 5,
  "virtual_op": 0
}
steemdelegated 5.879 SP to @mnkim
2020/05/09 08:59:30
delegateemnkim
delegatorsteem
vesting shares9562.193932 VESTS
Transaction InfoBlock #43220844/Trx 00421f559f9bcaa9d8a9e157b4238b00e6e8d606
View Raw JSON Data
{
  "block": 43220844,
  "op": [
    "delegate_vesting_shares",
    {
      "delegatee": "mnkim",
      "delegator": "steem",
      "vesting_shares": "9562.193932 VESTS"
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2020-05-09T08:59:30",
  "trx_id": "00421f559f9bcaa9d8a9e157b4238b00e6e8d606",
  "trx_in_block": 2,
  "virtual_op": 0
}
steemdelegated 1.201 SP to @mnkim
2020/05/08 13:05:15
delegateemnkim
delegatorsteem
vesting shares1953.311140 VESTS
Transaction InfoBlock #43197525/Trx 4db2b891015860dded7090ae0e4aca7e1bc7e1c4
View Raw JSON Data
{
  "block": 43197525,
  "op": [
    "delegate_vesting_shares",
    {
      "delegatee": "mnkim",
      "delegator": "steem",
      "vesting_shares": "1953.311140 VESTS"
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2020-05-08T13:05:15",
  "trx_id": "4db2b891015860dded7090ae0e4aca7e1bc7e1c4",
  "trx_in_block": 19,
  "virtual_op": 0
}
steemdelegated 5.971 SP to @mnkim
2019/08/19 22:06:30
delegateemnkim
delegatorsteem
vesting shares9712.126504 VESTS
Transaction InfoBlock #35700268/Trx 9fa260431fe1c01b4563372e58c2adba371b13a2
View Raw JSON Data
{
  "block": 35700268,
  "op": [
    "delegate_vesting_shares",
    {
      "delegatee": "mnkim",
      "delegator": "steem",
      "vesting_shares": "9712.126504 VESTS"
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2019-08-19T22:06:30",
  "trx_id": "9fa260431fe1c01b4563372e58c2adba371b13a2",
  "trx_in_block": 16,
  "virtual_op": 0
}
2019/04/12 02:06:36
authorsteemitboard
bodyCongratulations @mnkim! You received a personal award! <table><tr><td>https://steemitimages.com/70x70/http://steemitboard.com/@mnkim/birthday1.png</td><td>Happy Birthday! - You are on the Steem blockchain for 1 year!</td></tr></table> <sub>_You can view [your badges on your Steem Board](https://steemitboard.com/@mnkim) and compare to others on the [Steem Ranking](http://steemitboard.com/ranking/index.php?name=mnkim)_</sub> ###### [Vote for @Steemitboard as a witness](https://v2.steemconnect.com/sign/account-witness-vote?witness=steemitboard&approve=1) to get one more award and increased upvotes!
json metadata{"image":["https://steemitboard.com/img/notify.png"]}
parent authormnkim
parent permlinkangular-route
permlinksteemitboard-notify-mnkim-20190412t020636000z
title
Transaction InfoBlock #31967834/Trx 5b940332d18359a01cf74514c460afd0cb318739
View Raw JSON Data
{
  "block": 31967834,
  "op": [
    "comment",
    {
      "author": "steemitboard",
      "body": "Congratulations @mnkim! You received a personal award!\n\n<table><tr><td>https://steemitimages.com/70x70/http://steemitboard.com/@mnkim/birthday1.png</td><td>Happy Birthday! - You are on the Steem blockchain for 1 year!</td></tr></table>\n\n<sub>_You can view [your badges on your Steem Board](https://steemitboard.com/@mnkim) and compare to others on the [Steem Ranking](http://steemitboard.com/ranking/index.php?name=mnkim)_</sub>\n\n\n###### [Vote for @Steemitboard as a witness](https://v2.steemconnect.com/sign/account-witness-vote?witness=steemitboard&approve=1) to get one more award and increased upvotes!",
      "json_metadata": "{\"image\":[\"https://steemitboard.com/img/notify.png\"]}",
      "parent_author": "mnkim",
      "parent_permlink": "angular-route",
      "permlink": "steemitboard-notify-mnkim-20190412t020636000z",
      "title": ""
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2019-04-12T02:06:36",
  "trx_id": "5b940332d18359a01cf74514c460afd0cb318739",
  "trx_in_block": 15,
  "virtual_op": 0
}
steemdelegated 6.093 SP to @mnkim
2018/09/05 16:17:09
delegateemnkim
delegatorsteem
vesting shares9910.468788 VESTS
Transaction InfoBlock #25698142/Trx 51a359b6ef8de7a3bff95a91514232faa311b111
View Raw JSON Data
{
  "block": 25698142,
  "op": [
    "delegate_vesting_shares",
    {
      "delegatee": "mnkim",
      "delegator": "steem",
      "vesting_shares": "9910.468788 VESTS"
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2018-09-05T16:17:09",
  "trx_id": "51a359b6ef8de7a3bff95a91514232faa311b111",
  "trx_in_block": 11,
  "virtual_op": 0
}
steemdelegated 18.551 SP to @mnkim
2018/08/16 23:34:57
delegateemnkim
delegatorsteem
vesting shares30171.251422 VESTS
Transaction InfoBlock #25131195/Trx d6b4339f8b3dcaa332d0682cfb6649e3e47f8dca
View Raw JSON Data
{
  "block": 25131195,
  "op": [
    "delegate_vesting_shares",
    {
      "delegatee": "mnkim",
      "delegator": "steem",
      "vesting_shares": "30171.251422 VESTS"
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2018-08-16T23:34:57",
  "trx_id": "d6b4339f8b3dcaa332d0682cfb6649e3e47f8dca",
  "trx_in_block": 10,
  "virtual_op": 0
}
mnkimreceived 0.003 STEEM, 0.022 SBD, 0.019 SP author reward for @mnkim / angular-route
2018/06/12 09:08:06
authormnkim
permlinkangular-route
sbd payout0.022 SBD
steem payout0.003 STEEM
vesting payout30.480632 VESTS
Transaction InfoBlock #23252940/Virtual Operation #13
View Raw JSON Data
{
  "block": 23252940,
  "op": [
    "author_reward",
    {
      "author": "mnkim",
      "permlink": "angular-route",
      "sbd_payout": "0.022 SBD",
      "steem_payout": "0.003 STEEM",
      "vesting_payout": "30.480632 VESTS"
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2018-06-12T09:08:06",
  "trx_id": "0000000000000000000000000000000000000000",
  "trx_in_block": 4294967295,
  "virtual_op": 13
}
2018/06/06 15:21:30
authoreversloth
body스팀잇이 많이 불친절하죠 ㅠㅠ 즐거운 스팀잇 활동 되시길!
json metadata{"tags":["angular"],"app":"steemit/0.1"}
parent authormnkim
parent permlinkre-eversloth-re-mnkim-angular-route-20180606t135708515z
permlinkre-mnkim-re-eversloth-re-mnkim-angular-route-20180606t152129093z
title
Transaction InfoBlock #23088221/Trx 97cd34b6fcbb473f4a63f94587726cd13860aaad
View Raw JSON Data
{
  "block": 23088221,
  "op": [
    "comment",
    {
      "author": "eversloth",
      "body": "스팀잇이 많이 불친절하죠 ㅠㅠ 즐거운 스팀잇 활동 되시길!",
      "json_metadata": "{\"tags\":[\"angular\"],\"app\":\"steemit/0.1\"}",
      "parent_author": "mnkim",
      "parent_permlink": "re-eversloth-re-mnkim-angular-route-20180606t135708515z",
      "permlink": "re-mnkim-re-eversloth-re-mnkim-angular-route-20180606t152129093z",
      "title": ""
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2018-06-06T15:21:30",
  "trx_id": "97cd34b6fcbb473f4a63f94587726cd13860aaad",
  "trx_in_block": 20,
  "virtual_op": 0
}
mnkimpublished a new post: angular-route
2018/06/06 13:57:39
authormnkim
body![P5270018.jpg](https://cdn.steemitimages.com/DQmeKHhZfrBdBqKy97xpbpnXqNv8EDt4oRuw3ouU1n1uwWZ/P5270018.jpg) [블로터닷넷 기사](https://www.bloter.net/archives/281976)에 따르면 2017년 대한민국 1분기 평균 모바일 인터넷 속도는 28Mbps입니다. 이 속도로 계산된 [email protected]의 다운로드 시간은 8.5ms(아래 계산식 참고)입니다. 여기에 [LTE망 평균 응답속도 30ms](https://www.sktinsight.com/13617), 다운받은 스크립트를 [파싱하고 실행하는 데 까지 15ms(iPhone 5S 기준)](https://timkadlec.com/2014/09/js-parse-and-execution-time/)를 더하면 대략 53.5ms입니다. 시간이 지난 자료를 토대로 계산한 결과이지만. 이마저도 평균이거나 좋은 조건일때 기준이고. 보통 이런 파일을 하나만 다운로드하는것이 아니기 때문에 실제 서비스를 사용할 때는 더 느릴 것입니다. ``` 30KB after gzipped. 28Mbps = 3500KBps 1s : 3500KB = x : 30KB x = 0.008571429 ``` <br /> 서비스 초기 진입 시간의 중요성은 규모가 커질수록 중요해집니다. Google은 10개의 검색결과를 400ms에 노출하던 것에서. 30개의 검색결과를 900ms에 노출하도록 변경한 후 20%의 트래픽과 광고 수익 감소를 겪었다고 합니다. Google Maps는 리소스 용량을 30KB 줄인 것으로 첫주 10%의 트래픽 증가를. 이후 3주 내에 추가로 25%의 트래픽이 증가했다고 합니다. Amazon.com은 로드 타임이 100ms증가할때마다 매출액이 1%씩 감소했다고 합니다. [본문 링크](http://www.websiteoptimization.com/speed/tweak/psychology-web-performance/) 위의 내용을 볼 때 30ms도 결코 작다고 할 수 없습니다. 서비스 초기 진입 시간을 줄일 수 있는 방법은 많지만 이 글에서 소개할 동적 모듈 로딩은 가장 간편하면서도 큰 효과를 볼 수 있는 기법입니다. Angular는 출시될때부터 이 기능을 가지고 있었습니다. 동적으로 받을 리소스들을 모아 별도의 모듈로 만들고 아래 코드와 같이 라우터에 등록하면 됩니다. ``` const routes: Routes = [{ path: 'customers', loadChildren: 'app/customers/customers.module#CustomersModule' }]; ``` <br /> 사용자가 `/customers`에 접속하면 자동으로 `app-customers-customers.module.js`파일을 동적으로 다운로드받고 파일 내 `CustomerModule`을 사용할 수 있게 됩니다. jQuery등의 라이브러리를 해당 페이지에서만 사용하는 것이 확실하다면. 이 분리된 모듈에서 사용하는것으로 간단히 기법을 적용할 수 있습니다. 이렇게 분리된 모듈 파일의 용량 만큼 서비스 초기 진입에 걸리는 시간을 줄일 수 있습니다. 하지만 어떤 모듈은 해당 컴포넌트가 사용되는 시점에 받는 것이 더 자연스럽고 편리한 경우가 있습니다. 위지윅 에디터를 예로 들 수 있습니다. 동적 모듈 로딩 없이 개발된 A페이지에 위지윅 에디터를 추가한다고 가정해 봅시다. 라우터에 기존에 등록된 컴포넌트를 모듈로 변경하고 위와 같이 수정해야 합니다. 또 이렇게 모듈을 동적으로 받는다고 해도. 만약 위지윅 에디터 자체를 특정 버튼으로 노출하도록 기획한 경우 실제 위지윅 에디터를 사용하지 않아도 페이지 진입 만으로 리소스를 받게 됩니다. 위지윅 에디터 컴포넌트를 실제로 사용하는 시점에 관련 모듈을 다운로드받도록 하고 싶으면 `NgModuleFactoryLoader`를 사용하면 됩니다. 이 모듈을 사용하기 위해서는 먼저 루트 모듈에 해당 모듈들을 추가해야 합니다. ``` @NgModule({ ... providers: [{provide: NgModuleFactoryLoader, useClass: SystemJsNgModuleLoader}] }) export class AppModule {} ``` <br /> 그리고 필요한 리소스들을 동적으로 로드하는 별도의 모듈을 만듭니다. ``` @NgModule() export class EditorModule { constructor(@Inject(DOCUMENT) private document: Document) {} async load() { const style = document.createElement('style'); style.textContent = require('../../assets/css/editor.css').default; this.document.head.appendChild(style); return require('../../assets/js/editor.js'); } } ``` 동적으로 다운로드할 모듈을 직접 사용하지 않아도 될 경우 코드를 생성자에 구현하면 됩니다. 예제 코드에서는 `editor.js`파일이 내보내는 함수를 직접 사용해야 하기 때문에 해당 모듈을 반환하는 별도의 메서드 `load`에 구현합니다. 모듈을 구현했으면 `angular.json` 파일에 해당 모듈을 등록합니다. ``` { "projects": { "my-app": { "architect": { "build": { "lazyModules": [ "src/app/modules/editor.module#EditorModule" ] } } } } } ``` <br /> `lazyModules`의 배열에 해당 모듈 파일의 경로와 모듈의 이름을 #으로 구분해 기재합니다. 이후 이 프로젝트가 빌드될 때 `editor.module.ts`, `editor.css`, `editor.js`파일들은 `src-app-modules-editor.module.js`로 묶여 별도의 파일로 분리됩니다. 이제 아래의 코드로 위지윅 에디터의 생성자를 동적으로 얻어올 수 있습니다. ``` @Component({...}) export class AppComponent { title = 'app'; @ViewChild('textarea') el: ElementRef; constructor(private injector: Injector, private loader: NgModuleFactoryLoader) {} onClickLoadEditor() { this.loader.load('src/app/modules/editor.module#EditorModule') .then(factory => factory.create(this.injector).instance.load()) .then(({Editor}) => new Editor(this.el.nativeElement)); } } ``` <br /> 사실 Angular@v5 이하에서는 webpack이 기본적으로 사용했던 `System.import`파서 플러그인으로 `.ts`파일 뿐만 아닌 여러 파일을 동적으로 간단히 분리할 수 있었습니다. 하지만 [email protected] 부터 webpack이 `System.import`파서 플러그인을 사용하지 않게 되었고. Angular@v6 버전 이후부터는 해당 코드가 발견되면 컴파일 시점에 경고를 출력합니다. 그렇기 때문에 `System.import`를 직접적으로 사용할 수 없고 본문과 같이 `NgModuleFactoryLoader`를 사용해야 합니다. 재미있는 것은 `NgModuleFactoryLoader`의 구현체인 `SystemJsNgModuleLoader`내부에서는 `System.import`를 아직 사용하고 있다는 것입니다. 공식 github에서는 이 코드를 typescript의 `import`문을 사용하는 것으로 수정하려는 [PR](https://github.com/angular/angular/issues/21560)이 있습니다. 이 PR이 머지된다고 하더라도. 위 방법을 이용하는 데 문제는 없습니다.
json metadata{"tags":["angular","angular2","lazyloading","kr-newbie"],"image":["https://cdn.steemitimages.com/DQmeKHhZfrBdBqKy97xpbpnXqNv8EDt4oRuw3ouU1n1uwWZ/P5270018.jpg"],"links":["https://www.bloter.net/archives/281976","https://www.sktinsight.com/13617","https://timkadlec.com/2014/09/js-parse-and-execution-time/","http://www.websiteoptimization.com/speed/tweak/psychology-web-performance/","https://github.com/angular/angular/issues/21560"],"app":"steemit/0.1","format":"markdown"}
parent author
parent permlinkangular
permlinkangular-route
titleAngular에서 Route없이 모듈 동적 로딩하기
Transaction InfoBlock #23086545/Trx dc39c22ca37f5e36b634e2cfe4f4207af71f78a4
View Raw JSON Data
{
  "block": 23086545,
  "op": [
    "comment",
    {
      "author": "mnkim",
      "body": "![P5270018.jpg](https://cdn.steemitimages.com/DQmeKHhZfrBdBqKy97xpbpnXqNv8EDt4oRuw3ouU1n1uwWZ/P5270018.jpg)\n\n[블로터닷넷 기사](https://www.bloter.net/archives/281976)에 따르면 2017년 대한민국 1분기 평균 모바일 인터넷 속도는 28Mbps입니다. 이 속도로 계산된 [email protected]의 다운로드 시간은 8.5ms(아래 계산식 참고)입니다. 여기에 [LTE망 평균 응답속도 30ms](https://www.sktinsight.com/13617), 다운받은 스크립트를 [파싱하고 실행하는 데 까지 15ms(iPhone 5S 기준)](https://timkadlec.com/2014/09/js-parse-and-execution-time/)를 더하면 대략 53.5ms입니다. 시간이 지난 자료를 토대로 계산한 결과이지만. 이마저도 평균이거나 좋은 조건일때 기준이고. 보통 이런 파일을 하나만 다운로드하는것이 아니기 때문에 실제 서비스를 사용할 때는 더 느릴 것입니다.\n\n```\n30KB after gzipped.\n28Mbps = 3500KBps\n1s : 3500KB = x : 30KB\nx = 0.008571429\n```\n<br />\n서비스 초기 진입 시간의 중요성은 규모가 커질수록 중요해집니다. Google은 10개의 검색결과를 400ms에 노출하던 것에서. 30개의 검색결과를 900ms에 노출하도록 변경한 후 20%의 트래픽과 광고 수익 감소를 겪었다고 합니다. Google Maps는 리소스 용량을 30KB 줄인 것으로 첫주 10%의 트래픽 증가를. 이후 3주 내에 추가로 25%의 트래픽이 증가했다고 합니다. Amazon.com은 로드 타임이 100ms증가할때마다 매출액이 1%씩 감소했다고 합니다.  [본문 링크](http://www.websiteoptimization.com/speed/tweak/psychology-web-performance/)\n\n위의 내용을 볼 때 30ms도 결코 작다고 할 수 없습니다. 서비스 초기 진입 시간을 줄일 수 있는 방법은 많지만 이 글에서 소개할 동적 모듈 로딩은 가장 간편하면서도 큰 효과를 볼 수 있는 기법입니다. Angular는 출시될때부터 이 기능을 가지고 있었습니다. 동적으로 받을 리소스들을  모아 별도의 모듈로 만들고 아래 코드와 같이 라우터에 등록하면 됩니다.\n\n```\nconst routes: Routes = [{\n  path: 'customers',\n  loadChildren: 'app/customers/customers.module#CustomersModule'\n}];\n```\n<br />\n사용자가 `/customers`에 접속하면 자동으로 `app-customers-customers.module.js`파일을 동적으로 다운로드받고 파일 내 `CustomerModule`을 사용할 수 있게 됩니다. jQuery등의 라이브러리를 해당 페이지에서만 사용하는 것이 확실하다면. 이 분리된 모듈에서 사용하는것으로 간단히 기법을 적용할 수 있습니다. 이렇게 분리된 모듈 파일의 용량 만큼 서비스 초기 진입에 걸리는 시간을 줄일 수 있습니다.\n\n하지만 어떤 모듈은 해당 컴포넌트가 사용되는 시점에 받는 것이 더 자연스럽고 편리한 경우가 있습니다. 위지윅 에디터를 예로 들 수 있습니다. 동적 모듈 로딩 없이 개발된 A페이지에 위지윅 에디터를 추가한다고 가정해 봅시다. 라우터에 기존에 등록된 컴포넌트를 모듈로 변경하고 위와 같이 수정해야 합니다. 또 이렇게 모듈을 동적으로 받는다고 해도. 만약 위지윅 에디터 자체를 특정 버튼으로 노출하도록 기획한 경우 실제 위지윅 에디터를 사용하지 않아도 페이지 진입 만으로 리소스를 받게 됩니다.\n\n위지윅 에디터 컴포넌트를 실제로 사용하는 시점에 관련 모듈을 다운로드받도록 하고 싶으면 `NgModuleFactoryLoader`를 사용하면 됩니다. 이 모듈을 사용하기 위해서는 먼저 루트 모듈에 해당 모듈들을 추가해야 합니다.\n\n```\n@NgModule({\n  ...\n  providers: [{provide: NgModuleFactoryLoader, useClass: SystemJsNgModuleLoader}]\n})\nexport class AppModule {}\n```\n<br />\n그리고 필요한 리소스들을 동적으로 로드하는 별도의 모듈을 만듭니다.\n\n```\n@NgModule()\nexport class EditorModule {\n  constructor(@Inject(DOCUMENT) private document: Document) {}\n\n  async load() {\n    const style = document.createElement('style');\n    style.textContent = require('../../assets/css/editor.css').default;\n    this.document.head.appendChild(style);\n\n    return require('../../assets/js/editor.js');\n  }\n}\n```\n\n동적으로 다운로드할 모듈을 직접 사용하지 않아도 될 경우 코드를 생성자에 구현하면 됩니다. 예제 코드에서는 `editor.js`파일이 내보내는 함수를 직접 사용해야 하기 때문에 해당 모듈을 반환하는 별도의 메서드 `load`에 구현합니다. 모듈을 구현했으면 `angular.json` 파일에 해당 모듈을 등록합니다.\n\n```\n{\n  \"projects\": {\n    \"my-app\": {\n      \"architect\": {\n        \"build\": {\n          \"lazyModules\": [\n            \"src/app/modules/editor.module#EditorModule\"\n          ]\n        }\n      }\n    }\n  }\n}\n```\n<br />\n`lazyModules`의 배열에 해당 모듈 파일의 경로와 모듈의 이름을 #으로 구분해 기재합니다. 이후 이 프로젝트가 빌드될 때 `editor.module.ts`, `editor.css`, `editor.js`파일들은 `src-app-modules-editor.module.js`로 묶여 별도의 파일로 분리됩니다. 이제 아래의 코드로 위지윅 에디터의 생성자를 동적으로 얻어올 수 있습니다.\n\n```\n@Component({...})\nexport class AppComponent {\n  title = 'app';\n  @ViewChild('textarea') el: ElementRef;\n\n  constructor(private injector: Injector, private loader: NgModuleFactoryLoader) {}\n\n  onClickLoadEditor() {\n    this.loader.load('src/app/modules/editor.module#EditorModule')\n        .then(factory => factory.create(this.injector).instance.load())\n        .then(({Editor}) => new Editor(this.el.nativeElement));\n  }\n}\n```\n<br />\n사실 Angular@v5 이하에서는 webpack이 기본적으로 사용했던 `System.import`파서 플러그인으로 `.ts`파일 뿐만 아닌 여러 파일을 동적으로 간단히 분리할 수 있었습니다. 하지만 [email protected] 부터 webpack이 `System.import`파서 플러그인을 사용하지 않게 되었고. Angular@v6 버전 이후부터는 해당 코드가 발견되면 컴파일 시점에 경고를 출력합니다. 그렇기 때문에 `System.import`를 직접적으로 사용할 수 없고 본문과 같이 `NgModuleFactoryLoader`를 사용해야 합니다.\n\n재미있는 것은 `NgModuleFactoryLoader`의 구현체인 `SystemJsNgModuleLoader`내부에서는 `System.import`를 아직 사용하고 있다는 것입니다. 공식 github에서는 이 코드를 typescript의 `import`문을 사용하는 것으로 수정하려는 [PR](https://github.com/angular/angular/issues/21560)이 있습니다. 이 PR이 머지된다고 하더라도. 위 방법을 이용하는 데 문제는 없습니다.",
      "json_metadata": "{\"tags\":[\"angular\",\"angular2\",\"lazyloading\",\"kr-newbie\"],\"image\":[\"https://cdn.steemitimages.com/DQmeKHhZfrBdBqKy97xpbpnXqNv8EDt4oRuw3ouU1n1uwWZ/P5270018.jpg\"],\"links\":[\"https://www.bloter.net/archives/281976\",\"https://www.sktinsight.com/13617\",\"https://timkadlec.com/2014/09/js-parse-and-execution-time/\",\"http://www.websiteoptimization.com/speed/tweak/psychology-web-performance/\",\"https://github.com/angular/angular/issues/21560\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}",
      "parent_author": "",
      "parent_permlink": "angular",
      "permlink": "angular-route",
      "title": "Angular에서 Route없이 모듈 동적 로딩하기"
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2018-06-06T13:57:39",
  "trx_id": "dc39c22ca37f5e36b634e2cfe4f4207af71f78a4",
  "trx_in_block": 58,
  "virtual_op": 0
}
2018/06/06 13:57:15
authoreversloth
permlinkre-mnkim-angular-route-20180606t134426151z
votermnkim
weight10000 (100.00%)
Transaction InfoBlock #23086537/Trx 15555b2b62e6cf203186e7b2967fecb7fc8d5dd5
View Raw JSON Data
{
  "block": 23086537,
  "op": [
    "vote",
    {
      "author": "eversloth",
      "permlink": "re-mnkim-angular-route-20180606t134426151z",
      "voter": "mnkim",
      "weight": 10000
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2018-06-06T13:57:15",
  "trx_id": "15555b2b62e6cf203186e7b2967fecb7fc8d5dd5",
  "trx_in_block": 58,
  "virtual_op": 0
}
2018/06/06 13:57:09
authormnkim
body와 좋은 팁 고맙습니다. 사실 맨땅에 헤딩하는 기분으로 글을 쓰고 태그를 달고있긴한데 이런 방법이 있었군요! 알려주신 링크도 정독하겠습니다. 고마워요!
json metadata{"tags":["angular"],"app":"steemit/0.1"}
parent authoreversloth
parent permlinkre-mnkim-angular-route-20180606t134426151z
permlinkre-eversloth-re-mnkim-angular-route-20180606t135708515z
title
Transaction InfoBlock #23086535/Trx 809b3c9257b1515fb606731649831227de0352f7
View Raw JSON Data
{
  "block": 23086535,
  "op": [
    "comment",
    {
      "author": "mnkim",
      "body": "와 좋은 팁 고맙습니다. 사실 맨땅에 헤딩하는 기분으로 글을 쓰고 태그를 달고있긴한데 이런 방법이 있었군요! 알려주신 링크도 정독하겠습니다. 고마워요!",
      "json_metadata": "{\"tags\":[\"angular\"],\"app\":\"steemit/0.1\"}",
      "parent_author": "eversloth",
      "parent_permlink": "re-mnkim-angular-route-20180606t134426151z",
      "permlink": "re-eversloth-re-mnkim-angular-route-20180606t135708515z",
      "title": ""
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2018-06-06T13:57:09",
  "trx_id": "809b3c9257b1515fb606731649831227de0352f7",
  "trx_in_block": 42,
  "virtual_op": 0
}
everslothupvoted (20.00%) @mnkim / angular-route
2018/06/06 13:44:42
authormnkim
permlinkangular-route
votereversloth
weight2000 (20.00%)
Transaction InfoBlock #23086286/Trx c04f58eff3b60ce95b8b57e445bb67984eb36217
View Raw JSON Data
{
  "block": 23086286,
  "op": [
    "vote",
    {
      "author": "mnkim",
      "permlink": "angular-route",
      "voter": "eversloth",
      "weight": 2000
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2018-06-06T13:44:42",
  "trx_id": "c04f58eff3b60ce95b8b57e445bb67984eb36217",
  "trx_in_block": 51,
  "virtual_op": 0
}
2018/06/06 13:44:27
authoreversloth
bodyLTE가 꽤나 빠르다고는 해도 반응시간이 무시 못할 수준이군요.. 좋은 정보 감사합니다. #kr 태그를 달지 않으시면 한국어 사용자에게 글이 잘 노출되지 않습니다. 스팀잇에 익숙해지실 때까지 #kr-newbie 태그를 사용하시는 것을 추천드립니다. #kr 커뮤니티에서 사용하는 태그 목록은 [@myfan 님의 태그 정리글](https://steemit.com/kr/@myfan/5-7)에서 확인하실 수 있습니다. [이지스팀잇 가이드북](https://steemit.com/kr/@easysteemit/3s7jfa-pdf) 을 보시면 앞으로 스팀잇 활동하시는데 도움이 되실겁니다.
json metadata{"tags":["angular","kr","kr-newbie"],"links":["https://steemit.com/kr/@myfan/5-7","https://steemit.com/kr/@easysteemit/3s7jfa-pdf"],"app":"steemit/0.1"}
parent authormnkim
parent permlinkangular-route
permlinkre-mnkim-angular-route-20180606t134426151z
title
Transaction InfoBlock #23086281/Trx 3f2cf21dec9b2a0d1c50fc9d3835d2bf9b067392
View Raw JSON Data
{
  "block": 23086281,
  "op": [
    "comment",
    {
      "author": "eversloth",
      "body": "LTE가 꽤나 빠르다고는 해도 반응시간이 무시 못할 수준이군요.. 좋은 정보 감사합니다.\n\n#kr 태그를 달지 않으시면 한국어 사용자에게 글이 잘 노출되지 않습니다. 스팀잇에 익숙해지실 때까지 #kr-newbie 태그를 사용하시는 것을 추천드립니다. #kr 커뮤니티에서 사용하는 태그 목록은 [@myfan 님의 태그 정리글](https://steemit.com/kr/@myfan/5-7)에서 확인하실 수 있습니다.\n[이지스팀잇 가이드북](https://steemit.com/kr/@easysteemit/3s7jfa-pdf) 을 보시면 앞으로 스팀잇 활동하시는데 도움이 되실겁니다.",
      "json_metadata": "{\"tags\":[\"angular\",\"kr\",\"kr-newbie\"],\"links\":[\"https://steemit.com/kr/@myfan/5-7\",\"https://steemit.com/kr/@easysteemit/3s7jfa-pdf\"],\"app\":\"steemit/0.1\"}",
      "parent_author": "mnkim",
      "parent_permlink": "angular-route",
      "permlink": "re-mnkim-angular-route-20180606t134426151z",
      "title": ""
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2018-06-06T13:44:27",
  "trx_id": "3f2cf21dec9b2a0d1c50fc9d3835d2bf9b067392",
  "trx_in_block": 22,
  "virtual_op": 0
}
mnkimpublished a new post: angular-route
2018/06/05 14:33:03
authormnkim
body@@ -3025,17 +3025,20 @@ itor.js%60 -%EA%B0%80 +%ED%8C%8C%EC%9D%BC%EB%93%A4%EC%9D%80 %60src-ap @@ -3070,12 +3070,10 @@ s%60%EB%A1%9C -%EB%B6%84%EB%A6%AC%EB%90%98%EC%96%B4 +%EB%AC%B6%EC%97%AC %EB%B3%84%EB%8F%84%EC%9D%98 @@ -3077,18 +3077,18 @@ %EB%B3%84%EB%8F%84%EC%9D%98 %ED%8C%8C%EC%9D%BC%EB%A1%9C -%EC%83%9D%EC%84%B1 +%EB%B6%84%EB%A6%AC %EB%90%A9%EB%8B%88%EB%8B%A4. %EC%9D%B4%EC%A0%9C
json metadata{"tags":["angular","angular2","lazyloading"],"image":["https://cdn.steemitimages.com/DQmeKHhZfrBdBqKy97xpbpnXqNv8EDt4oRuw3ouU1n1uwWZ/P5270018.jpg"],"links":["https://www.bloter.net/archives/281976","https://www.sktinsight.com/13617","https://timkadlec.com/2014/09/js-parse-and-execution-time/","http://www.websiteoptimization.com/speed/tweak/psychology-web-performance/","https://github.com/angular/angular/issues/21560"],"app":"steemit/0.1","format":"markdown"}
parent author
parent permlinkangular
permlinkangular-route
titleAngular에서 Route없이 모듈 동적 로딩하기
Transaction InfoBlock #23058462/Trx d329f686cafa5ccff8eb9698e3c68f02638c9b21
View Raw JSON Data
{
  "block": 23058462,
  "op": [
    "comment",
    {
      "author": "mnkim",
      "body": "@@ -3025,17 +3025,20 @@\n itor.js%60\n-%EA%B0%80\n+%ED%8C%8C%EC%9D%BC%EB%93%A4%EC%9D%80\n  %60src-ap\n@@ -3070,12 +3070,10 @@\n s%60%EB%A1%9C \n-%EB%B6%84%EB%A6%AC%EB%90%98%EC%96%B4\n+%EB%AC%B6%EC%97%AC\n  %EB%B3%84%EB%8F%84%EC%9D%98\n@@ -3077,18 +3077,18 @@\n %EB%B3%84%EB%8F%84%EC%9D%98 %ED%8C%8C%EC%9D%BC%EB%A1%9C \n-%EC%83%9D%EC%84%B1\n+%EB%B6%84%EB%A6%AC\n %EB%90%A9%EB%8B%88%EB%8B%A4. %EC%9D%B4%EC%A0%9C \n",
      "json_metadata": "{\"tags\":[\"angular\",\"angular2\",\"lazyloading\"],\"image\":[\"https://cdn.steemitimages.com/DQmeKHhZfrBdBqKy97xpbpnXqNv8EDt4oRuw3ouU1n1uwWZ/P5270018.jpg\"],\"links\":[\"https://www.bloter.net/archives/281976\",\"https://www.sktinsight.com/13617\",\"https://timkadlec.com/2014/09/js-parse-and-execution-time/\",\"http://www.websiteoptimization.com/speed/tweak/psychology-web-performance/\",\"https://github.com/angular/angular/issues/21560\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}",
      "parent_author": "",
      "parent_permlink": "angular",
      "permlink": "angular-route",
      "title": "Angular에서 Route없이 모듈 동적 로딩하기"
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2018-06-05T14:33:03",
  "trx_id": "d329f686cafa5ccff8eb9698e3c68f02638c9b21",
  "trx_in_block": 4,
  "virtual_op": 0
}
swaggerupvoted (0.03%) @mnkim / angular-route
2018/06/05 14:32:42
authormnkim
permlinkangular-route
voterswagger
weight3 (0.03%)
Transaction InfoBlock #23058455/Trx 5cc480e0a42289798727453e3da82a3e3d225f9d
View Raw JSON Data
{
  "block": 23058455,
  "op": [
    "vote",
    {
      "author": "mnkim",
      "permlink": "angular-route",
      "voter": "swagger",
      "weight": 3
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2018-06-05T14:32:42",
  "trx_id": "5cc480e0a42289798727453e3da82a3e3d225f9d",
  "trx_in_block": 0,
  "virtual_op": 0
}
mnkimpublished a new post: angular-route
2018/06/05 14:31:12
authormnkim
body@@ -106,16 +106,58 @@ g)%0A%0A +%5B %EB%B8%94%EB%A1%9C%ED%84%B0%EB%8B%B7%EB%84%B7 %EA%B8%B0%EC%82%AC +%5D(https://www.bloter.net/archives/281976) %EC%97%90 %EB%94%B0%EB%A5%B4 @@ -257,16 +257,17 @@ %EB%8B%88%EB%8B%A4. %EC%97%AC%EA%B8%B0%EC%97%90 +%5B LTE%EB%A7%9D %ED%8F%89%EA%B7%A0 @@ -275,16 +275,51 @@ %EB%8B%B5%EC%86%8D%EB%8F%84 30ms +%5D(https://www.sktinsight.com/13617) , %EB%8B%A4%EC%9A%B4%EB%B0%9B%EC%9D%80 %EC%8A%A4 @@ -323,16 +323,17 @@ %EC%9D%80 %EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EB%A5%BC +%5B %ED%8C%8C%EC%8B%B1%ED%95%98%EA%B3%A0 %EC%8B%A4%ED%96%89%ED%95%98 @@ -357,16 +357,77 @@ e 5S %EA%B8%B0%EC%A4%80) +%5D(https://timkadlec.com/2014/09/js-parse-and-execution-time/) %EB%A5%BC %EB%8D%94%ED%95%98%EB%A9%B4 %EB%8C%80%EB%9E%B5 @@ -906,16 +906,25 @@ %EB%8B%A4%EA%B3%A0 %ED%95%A9%EB%8B%88%EB%8B%A4. + %5B%EB%B3%B8%EB%AC%B8 %EB%A7%81%ED%81%AC%5D( http://w @@ -989,16 +989,17 @@ ormance/ +) %0A%0A%EC%9C%84%EC%9D%98 %EB%82%B4%EC%9A%A9%EC%9D%84
json metadata{"tags":["angular","angular2","lazyloading"],"image":["https://cdn.steemitimages.com/DQmeKHhZfrBdBqKy97xpbpnXqNv8EDt4oRuw3ouU1n1uwWZ/P5270018.jpg"],"links":["https://www.bloter.net/archives/281976","https://www.sktinsight.com/13617","https://timkadlec.com/2014/09/js-parse-and-execution-time/","http://www.websiteoptimization.com/speed/tweak/psychology-web-performance/","https://github.com/angular/angular/issues/21560"],"app":"steemit/0.1","format":"markdown"}
parent author
parent permlinkangular
permlinkangular-route
titleAngular에서 Route없이 모듈 동적 로딩하기
Transaction InfoBlock #23058425/Trx ff7dab786866148b5933f89967433d0ba424f352
View Raw JSON Data
{
  "block": 23058425,
  "op": [
    "comment",
    {
      "author": "mnkim",
      "body": "@@ -106,16 +106,58 @@\n g)%0A%0A\n+%5B\n %EB%B8%94%EB%A1%9C%ED%84%B0%EB%8B%B7%EB%84%B7 %EA%B8%B0%EC%82%AC\n+%5D(https://www.bloter.net/archives/281976)\n %EC%97%90 %EB%94%B0%EB%A5%B4\n@@ -257,16 +257,17 @@\n %EB%8B%88%EB%8B%A4. %EC%97%AC%EA%B8%B0%EC%97%90 \n+%5B\n LTE%EB%A7%9D %ED%8F%89%EA%B7%A0 \n@@ -275,16 +275,51 @@\n %EB%8B%B5%EC%86%8D%EB%8F%84 30ms\n+%5D(https://www.sktinsight.com/13617)\n , %EB%8B%A4%EC%9A%B4%EB%B0%9B%EC%9D%80 %EC%8A%A4\n@@ -323,16 +323,17 @@\n %EC%9D%80 %EC%8A%A4%ED%81%AC%EB%A6%BD%ED%8A%B8%EB%A5%BC \n+%5B\n %ED%8C%8C%EC%8B%B1%ED%95%98%EA%B3%A0 %EC%8B%A4%ED%96%89%ED%95%98\n@@ -357,16 +357,77 @@\n e 5S %EA%B8%B0%EC%A4%80)\n+%5D(https://timkadlec.com/2014/09/js-parse-and-execution-time/)\n %EB%A5%BC %EB%8D%94%ED%95%98%EB%A9%B4 %EB%8C%80%EB%9E%B5\n@@ -906,16 +906,25 @@\n %EB%8B%A4%EA%B3%A0 %ED%95%A9%EB%8B%88%EB%8B%A4. \n+ %5B%EB%B3%B8%EB%AC%B8 %EB%A7%81%ED%81%AC%5D(\n http://w\n@@ -989,16 +989,17 @@\n ormance/\n+)\n %0A%0A%EC%9C%84%EC%9D%98 %EB%82%B4%EC%9A%A9%EC%9D%84\n",
      "json_metadata": "{\"tags\":[\"angular\",\"angular2\",\"lazyloading\"],\"image\":[\"https://cdn.steemitimages.com/DQmeKHhZfrBdBqKy97xpbpnXqNv8EDt4oRuw3ouU1n1uwWZ/P5270018.jpg\"],\"links\":[\"https://www.bloter.net/archives/281976\",\"https://www.sktinsight.com/13617\",\"https://timkadlec.com/2014/09/js-parse-and-execution-time/\",\"http://www.websiteoptimization.com/speed/tweak/psychology-web-performance/\",\"https://github.com/angular/angular/issues/21560\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}",
      "parent_author": "",
      "parent_permlink": "angular",
      "permlink": "angular-route",
      "title": "Angular에서 Route없이 모듈 동적 로딩하기"
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2018-06-05T14:31:12",
  "trx_id": "ff7dab786866148b5933f89967433d0ba424f352",
  "trx_in_block": 9,
  "virtual_op": 0
}
dongkunupvoted (100.00%) @mnkim / angular-route
2018/06/05 13:09:48
authormnkim
permlinkangular-route
voterdongkun
weight10000 (100.00%)
Transaction InfoBlock #23056797/Trx 45cda5d522627f1754fcb367ece2de45e59d2e0f
View Raw JSON Data
{
  "block": 23056797,
  "op": [
    "vote",
    {
      "author": "mnkim",
      "permlink": "angular-route",
      "voter": "dongkun",
      "weight": 10000
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2018-06-05T13:09:48",
  "trx_id": "45cda5d522627f1754fcb367ece2de45e59d2e0f",
  "trx_in_block": 32,
  "virtual_op": 0
}
mnkimpublished a new post: angular-route
2018/06/05 09:20:39
authormnkim
body@@ -3882,18 +3882,69 @@ %EB%A1%9C %EC%88%98%EC%A0%95%ED%95%98%EB%A0%A4%EB%8A%94 +%5B PR +%5D(https://github.com/angular/angular/issues/21560) %EC%9D%B4 %EC%9E%88%EC%8A%B5%EB%8B%88%EB%8B%A4.
json metadata{"tags":["angular","angular2","lazyloading"],"image":["https://cdn.steemitimages.com/DQmeKHhZfrBdBqKy97xpbpnXqNv8EDt4oRuw3ouU1n1uwWZ/P5270018.jpg"],"links":["http://www.websiteoptimization.com/speed/tweak/psychology-web-performance/","https://github.com/angular/angular/issues/21560"],"app":"steemit/0.1","format":"markdown"}
parent author
parent permlinkangular
permlinkangular-route
titleAngular에서 Route없이 모듈 동적 로딩하기
Transaction InfoBlock #23052215/Trx 7512e7c9be6a66a32a3c7830585c027dbc609fa1
View Raw JSON Data
{
  "block": 23052215,
  "op": [
    "comment",
    {
      "author": "mnkim",
      "body": "@@ -3882,18 +3882,69 @@\n %EB%A1%9C %EC%88%98%EC%A0%95%ED%95%98%EB%A0%A4%EB%8A%94 \n+%5B\n PR\n+%5D(https://github.com/angular/angular/issues/21560)\n %EC%9D%B4 %EC%9E%88%EC%8A%B5%EB%8B%88%EB%8B%A4. \n",
      "json_metadata": "{\"tags\":[\"angular\",\"angular2\",\"lazyloading\"],\"image\":[\"https://cdn.steemitimages.com/DQmeKHhZfrBdBqKy97xpbpnXqNv8EDt4oRuw3ouU1n1uwWZ/P5270018.jpg\"],\"links\":[\"http://www.websiteoptimization.com/speed/tweak/psychology-web-performance/\",\"https://github.com/angular/angular/issues/21560\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}",
      "parent_author": "",
      "parent_permlink": "angular",
      "permlink": "angular-route",
      "title": "Angular에서 Route없이 모듈 동적 로딩하기"
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2018-06-05T09:20:39",
  "trx_id": "7512e7c9be6a66a32a3c7830585c027dbc609fa1",
  "trx_in_block": 69,
  "virtual_op": 0
}
mnkimpublished a new post: angular-route
2018/06/05 09:19:30
authormnkim
body@@ -492,17 +492,23 @@ 429%0A%60%60%60%0A +%3Cbr /%3E %0A - %EC%84%9C%EB%B9%84%EC%8A%A4 %EC%B4%88%EA%B8%B0 %EC%A7%84 @@ -1169,17 +1169,23 @@ %7D%5D;%0A%60%60%60%0A +%3Cbr /%3E %0A - %EC%82%AC%EC%9A%A9%EC%9E%90%EA%B0%80 %60/c @@ -1966,17 +1966,23 @@ %7B%7D%0A%60%60%60%0A +%3Cbr /%3E %0A - %EA%B7%B8%EB%A6%AC%EA%B3%A0 %ED%95%84%EC%9A%94%ED%95%9C @@ -2750,17 +2750,23 @@ %7D%0A%7D%0A%60%60%60%0A +%3Cbr /%3E %0A - %60lazyMod @@ -3407,16 +3407,22 @@ %7D%0A%7D%0A%60%60%60%0A +%3Cbr /%3E %0A%EC%82%AC%EC%8B%A4 Angu
json metadata{"tags":["angular","angular2","lazyloading"],"image":["https://cdn.steemitimages.com/DQmeKHhZfrBdBqKy97xpbpnXqNv8EDt4oRuw3ouU1n1uwWZ/P5270018.jpg"],"links":["http://www.websiteoptimization.com/speed/tweak/psychology-web-performance/"],"app":"steemit/0.1","format":"markdown"}
parent author
parent permlinkangular
permlinkangular-route
titleAngular에서 Route없이 모듈 동적 로딩하기
Transaction InfoBlock #23052192/Trx 512ea1fe0901b2c088b1682502686a60c845b4a8
View Raw JSON Data
{
  "block": 23052192,
  "op": [
    "comment",
    {
      "author": "mnkim",
      "body": "@@ -492,17 +492,23 @@\n 429%0A%60%60%60%0A\n+%3Cbr /%3E\n %0A\n-\n %EC%84%9C%EB%B9%84%EC%8A%A4 %EC%B4%88%EA%B8%B0 %EC%A7%84\n@@ -1169,17 +1169,23 @@\n %7D%5D;%0A%60%60%60%0A\n+%3Cbr /%3E\n %0A\n-\n %EC%82%AC%EC%9A%A9%EC%9E%90%EA%B0%80 %60/c\n@@ -1966,17 +1966,23 @@\n  %7B%7D%0A%60%60%60%0A\n+%3Cbr /%3E\n %0A\n-\n %EA%B7%B8%EB%A6%AC%EA%B3%A0 %ED%95%84%EC%9A%94%ED%95%9C \n@@ -2750,17 +2750,23 @@\n %7D%0A%7D%0A%60%60%60%0A\n+%3Cbr /%3E\n %0A\n-\n %60lazyMod\n@@ -3407,16 +3407,22 @@\n %7D%0A%7D%0A%60%60%60%0A\n+%3Cbr /%3E\n %0A%EC%82%AC%EC%8B%A4 Angu\n",
      "json_metadata": "{\"tags\":[\"angular\",\"angular2\",\"lazyloading\"],\"image\":[\"https://cdn.steemitimages.com/DQmeKHhZfrBdBqKy97xpbpnXqNv8EDt4oRuw3ouU1n1uwWZ/P5270018.jpg\"],\"links\":[\"http://www.websiteoptimization.com/speed/tweak/psychology-web-performance/\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}",
      "parent_author": "",
      "parent_permlink": "angular",
      "permlink": "angular-route",
      "title": "Angular에서 Route없이 모듈 동적 로딩하기"
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2018-06-05T09:19:30",
  "trx_id": "512ea1fe0901b2c088b1682502686a60c845b4a8",
  "trx_in_block": 14,
  "virtual_op": 0
}
aripratamaupvoted (100.00%) @mnkim / angular-route
2018/06/05 09:08:42
authormnkim
permlinkangular-route
voteraripratama
weight10000 (100.00%)
Transaction InfoBlock #23051976/Trx 53b606abf5d7a4187fb85af0642554bd4377d9b8
View Raw JSON Data
{
  "block": 23051976,
  "op": [
    "vote",
    {
      "author": "mnkim",
      "permlink": "angular-route",
      "voter": "aripratama",
      "weight": 10000
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2018-06-05T09:08:42",
  "trx_id": "53b606abf5d7a4187fb85af0642554bd4377d9b8",
  "trx_in_block": 51,
  "virtual_op": 0
}
modemserupvoted (1.00%) @mnkim / angular-route
2018/06/05 09:08:09
authormnkim
permlinkangular-route
votermodemser
weight100 (1.00%)
Transaction InfoBlock #23051965/Trx 46d3d9350da3ced7122e3e9d2e5050c87ec7be7b
View Raw JSON Data
{
  "block": 23051965,
  "op": [
    "vote",
    {
      "author": "mnkim",
      "permlink": "angular-route",
      "voter": "modemser",
      "weight": 100
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2018-06-05T09:08:09",
  "trx_id": "46d3d9350da3ced7122e3e9d2e5050c87ec7be7b",
  "trx_in_block": 26,
  "virtual_op": 0
}
mnkimpublished a new post: angular-route
2018/06/05 09:08:06
authormnkim
body![P5270018.jpg](https://cdn.steemitimages.com/DQmeKHhZfrBdBqKy97xpbpnXqNv8EDt4oRuw3ouU1n1uwWZ/P5270018.jpg) 블로터닷넷 기사에 따르면 2017년 대한민국 1분기 평균 모바일 인터넷 속도는 28Mbps입니다. 이 속도로 계산된 [email protected]의 다운로드 시간은 8.5ms(아래 계산식 참고)입니다. 여기에 LTE망 평균 응답속도 30ms, 다운받은 스크립트를 파싱하고 실행하는 데 까지 15ms(iPhone 5S 기준)를 더하면 대략 53.5ms입니다. 시간이 지난 자료를 토대로 계산한 결과이지만. 이마저도 평균이거나 좋은 조건일때 기준이고. 보통 이런 파일을 하나만 다운로드하는것이 아니기 때문에 실제 서비스를 사용할 때는 더 느릴 것입니다. ``` 30KB after gzipped. 28Mbps = 3500KBps 1s : 3500KB = x : 30KB x = 0.008571429 ``` 서비스 초기 진입 시간의 중요성은 규모가 커질수록 중요해집니다. Google은 10개의 검색결과를 400ms에 노출하던 것에서. 30개의 검색결과를 900ms에 노출하도록 변경한 후 20%의 트래픽과 광고 수익 감소를 겪었다고 합니다. Google Maps는 리소스 용량을 30KB 줄인 것으로 첫주 10%의 트래픽 증가를. 이후 3주 내에 추가로 25%의 트래픽이 증가했다고 합니다. Amazon.com은 로드 타임이 100ms증가할때마다 매출액이 1%씩 감소했다고 합니다. http://www.websiteoptimization.com/speed/tweak/psychology-web-performance/ 위의 내용을 볼 때 30ms도 결코 작다고 할 수 없습니다. 서비스 초기 진입 시간을 줄일 수 있는 방법은 많지만 이 글에서 소개할 동적 모듈 로딩은 가장 간편하면서도 큰 효과를 볼 수 있는 기법입니다. Angular는 출시될때부터 이 기능을 가지고 있었습니다. 동적으로 받을 리소스들을 모아 별도의 모듈로 만들고 아래 코드와 같이 라우터에 등록하면 됩니다. ``` const routes: Routes = [{ path: 'customers', loadChildren: 'app/customers/customers.module#CustomersModule' }]; ``` 사용자가 `/customers`에 접속하면 자동으로 `app-customers-customers.module.js`파일을 동적으로 다운로드받고 파일 내 `CustomerModule`을 사용할 수 있게 됩니다. jQuery등의 라이브러리를 해당 페이지에서만 사용하는 것이 확실하다면. 이 분리된 모듈에서 사용하는것으로 간단히 기법을 적용할 수 있습니다. 이렇게 분리된 모듈 파일의 용량 만큼 서비스 초기 진입에 걸리는 시간을 줄일 수 있습니다. 하지만 어떤 모듈은 해당 컴포넌트가 사용되는 시점에 받는 것이 더 자연스럽고 편리한 경우가 있습니다. 위지윅 에디터를 예로 들 수 있습니다. 동적 모듈 로딩 없이 개발된 A페이지에 위지윅 에디터를 추가한다고 가정해 봅시다. 라우터에 기존에 등록된 컴포넌트를 모듈로 변경하고 위와 같이 수정해야 합니다. 또 이렇게 모듈을 동적으로 받는다고 해도. 만약 위지윅 에디터 자체를 특정 버튼으로 노출하도록 기획한 경우 실제 위지윅 에디터를 사용하지 않아도 페이지 진입 만으로 리소스를 받게 됩니다. 위지윅 에디터 컴포넌트를 실제로 사용하는 시점에 관련 모듈을 다운로드받도록 하고 싶으면 `NgModuleFactoryLoader`를 사용하면 됩니다. 이 모듈을 사용하기 위해서는 먼저 루트 모듈에 해당 모듈들을 추가해야 합니다. ``` @NgModule({ ... providers: [{provide: NgModuleFactoryLoader, useClass: SystemJsNgModuleLoader}] }) export class AppModule {} ``` 그리고 필요한 리소스들을 동적으로 로드하는 별도의 모듈을 만듭니다. ``` @NgModule() export class EditorModule { constructor(@Inject(DOCUMENT) private document: Document) {} async load() { const style = document.createElement('style'); style.textContent = require('../../assets/css/editor.css').default; this.document.head.appendChild(style); return require('../../assets/js/editor.js'); } } ``` 동적으로 다운로드할 모듈을 직접 사용하지 않아도 될 경우 코드를 생성자에 구현하면 됩니다. 예제 코드에서는 `editor.js`파일이 내보내는 함수를 직접 사용해야 하기 때문에 해당 모듈을 반환하는 별도의 메서드 `load`에 구현합니다. 모듈을 구현했으면 `angular.json` 파일에 해당 모듈을 등록합니다. ``` { "projects": { "my-app": { "architect": { "build": { "lazyModules": [ "src/app/modules/editor.module#EditorModule" ] } } } } } ``` `lazyModules`의 배열에 해당 모듈 파일의 경로와 모듈의 이름을 #으로 구분해 기재합니다. 이후 이 프로젝트가 빌드될 때 `editor.module.ts`, `editor.css`, `editor.js`가 `src-app-modules-editor.module.js`로 분리되어 별도의 파일로 생성됩니다. 이제 아래의 코드로 위지윅 에디터의 생성자를 동적으로 얻어올 수 있습니다. ``` @Component({...}) export class AppComponent { title = 'app'; @ViewChild('textarea') el: ElementRef; constructor(private injector: Injector, private loader: NgModuleFactoryLoader) {} onClickLoadEditor() { this.loader.load('src/app/modules/editor.module#EditorModule') .then(factory => factory.create(this.injector).instance.load()) .then(({Editor}) => new Editor(this.el.nativeElement)); } } ``` 사실 Angular@v5 이하에서는 webpack이 기본적으로 사용했던 `System.import`파서 플러그인으로 `.ts`파일 뿐만 아닌 여러 파일을 동적으로 간단히 분리할 수 있었습니다. 하지만 [email protected] 부터 webpack이 `System.import`파서 플러그인을 사용하지 않게 되었고. Angular@v6 버전 이후부터는 해당 코드가 발견되면 컴파일 시점에 경고를 출력합니다. 그렇기 때문에 `System.import`를 직접적으로 사용할 수 없고 본문과 같이 `NgModuleFactoryLoader`를 사용해야 합니다. 재미있는 것은 `NgModuleFactoryLoader`의 구현체인 `SystemJsNgModuleLoader`내부에서는 `System.import`를 아직 사용하고 있다는 것입니다. 공식 github에서는 이 코드를 typescript의 `import`문을 사용하는 것으로 수정하려는 PR이 있습니다. 이 PR이 머지된다고 하더라도. 위 방법을 이용하는 데 문제는 없습니다.
json metadata{"tags":["angular","angular2","lazyloading"],"image":["https://cdn.steemitimages.com/DQmeKHhZfrBdBqKy97xpbpnXqNv8EDt4oRuw3ouU1n1uwWZ/P5270018.jpg"],"links":["http://www.websiteoptimization.com/speed/tweak/psychology-web-performance/"],"app":"steemit/0.1","format":"markdown"}
parent author
parent permlinkangular
permlinkangular-route
titleAngular에서 Route없이 모듈 동적 로딩하기
Transaction InfoBlock #23051964/Trx 2d82e847cdb4d8e844fcd4ca3b13b7076072ec99
View Raw JSON Data
{
  "block": 23051964,
  "op": [
    "comment",
    {
      "author": "mnkim",
      "body": "![P5270018.jpg](https://cdn.steemitimages.com/DQmeKHhZfrBdBqKy97xpbpnXqNv8EDt4oRuw3ouU1n1uwWZ/P5270018.jpg)\n\n블로터닷넷 기사에 따르면 2017년 대한민국 1분기 평균 모바일 인터넷 속도는 28Mbps입니다. 이 속도로 계산된 [email protected]의 다운로드 시간은 8.5ms(아래 계산식 참고)입니다. 여기에 LTE망 평균 응답속도 30ms, 다운받은 스크립트를 파싱하고 실행하는 데 까지 15ms(iPhone 5S 기준)를 더하면 대략 53.5ms입니다. 시간이 지난 자료를 토대로 계산한 결과이지만. 이마저도 평균이거나 좋은 조건일때 기준이고. 보통 이런 파일을 하나만 다운로드하는것이 아니기 때문에 실제 서비스를 사용할 때는 더 느릴 것입니다.\n\n```\n30KB after gzipped.\n28Mbps = 3500KBps\n1s : 3500KB = x : 30KB\nx = 0.008571429\n```\n\n서비스 초기 진입 시간의 중요성은 규모가 커질수록 중요해집니다. Google은 10개의 검색결과를 400ms에 노출하던 것에서. 30개의 검색결과를 900ms에 노출하도록 변경한 후 20%의 트래픽과 광고 수익 감소를 겪었다고 합니다. Google Maps는 리소스 용량을 30KB 줄인 것으로 첫주 10%의 트래픽 증가를. 이후 3주 내에 추가로 25%의 트래픽이 증가했다고 합니다. Amazon.com은 로드 타임이 100ms증가할때마다 매출액이 1%씩 감소했다고 합니다. http://www.websiteoptimization.com/speed/tweak/psychology-web-performance/\n\n위의 내용을 볼 때 30ms도 결코 작다고 할 수 없습니다. 서비스 초기 진입 시간을 줄일 수 있는 방법은 많지만 이 글에서 소개할 동적 모듈 로딩은 가장 간편하면서도 큰 효과를 볼 수 있는 기법입니다. Angular는 출시될때부터 이 기능을 가지고 있었습니다. 동적으로 받을 리소스들을  모아 별도의 모듈로 만들고 아래 코드와 같이 라우터에 등록하면 됩니다.\n\n```\nconst routes: Routes = [{\n  path: 'customers',\n  loadChildren: 'app/customers/customers.module#CustomersModule'\n}];\n```\n\n사용자가 `/customers`에 접속하면 자동으로 `app-customers-customers.module.js`파일을 동적으로 다운로드받고 파일 내 `CustomerModule`을 사용할 수 있게 됩니다. jQuery등의 라이브러리를 해당 페이지에서만 사용하는 것이 확실하다면. 이 분리된 모듈에서 사용하는것으로 간단히 기법을 적용할 수 있습니다. 이렇게 분리된 모듈 파일의 용량 만큼 서비스 초기 진입에 걸리는 시간을 줄일 수 있습니다.\n\n하지만 어떤 모듈은 해당 컴포넌트가 사용되는 시점에 받는 것이 더 자연스럽고 편리한 경우가 있습니다. 위지윅 에디터를 예로 들 수 있습니다. 동적 모듈 로딩 없이 개발된 A페이지에 위지윅 에디터를 추가한다고 가정해 봅시다. 라우터에 기존에 등록된 컴포넌트를 모듈로 변경하고 위와 같이 수정해야 합니다. 또 이렇게 모듈을 동적으로 받는다고 해도. 만약 위지윅 에디터 자체를 특정 버튼으로 노출하도록 기획한 경우 실제 위지윅 에디터를 사용하지 않아도 페이지 진입 만으로 리소스를 받게 됩니다.\n\n위지윅 에디터 컴포넌트를 실제로 사용하는 시점에 관련 모듈을 다운로드받도록 하고 싶으면 `NgModuleFactoryLoader`를 사용하면 됩니다. 이 모듈을 사용하기 위해서는 먼저 루트 모듈에 해당 모듈들을 추가해야 합니다.\n\n```\n@NgModule({\n  ...\n  providers: [{provide: NgModuleFactoryLoader, useClass: SystemJsNgModuleLoader}]\n})\nexport class AppModule {}\n```\n\n그리고 필요한 리소스들을 동적으로 로드하는 별도의 모듈을 만듭니다.\n\n```\n@NgModule()\nexport class EditorModule {\n  constructor(@Inject(DOCUMENT) private document: Document) {}\n\n  async load() {\n    const style = document.createElement('style');\n    style.textContent = require('../../assets/css/editor.css').default;\n    this.document.head.appendChild(style);\n\n    return require('../../assets/js/editor.js');\n  }\n}\n```\n\n동적으로 다운로드할 모듈을 직접 사용하지 않아도 될 경우 코드를 생성자에 구현하면 됩니다. 예제 코드에서는 `editor.js`파일이 내보내는 함수를 직접 사용해야 하기 때문에 해당 모듈을 반환하는 별도의 메서드 `load`에 구현합니다. 모듈을 구현했으면 `angular.json` 파일에 해당 모듈을 등록합니다.\n\n```\n{\n  \"projects\": {\n    \"my-app\": {\n      \"architect\": {\n        \"build\": {\n          \"lazyModules\": [\n            \"src/app/modules/editor.module#EditorModule\"\n          ]\n        }\n      }\n    }\n  }\n}\n```\n\n`lazyModules`의 배열에 해당 모듈 파일의 경로와 모듈의 이름을 #으로 구분해 기재합니다. 이후 이 프로젝트가 빌드될 때 `editor.module.ts`, `editor.css`, `editor.js`가 `src-app-modules-editor.module.js`로 분리되어 별도의 파일로 생성됩니다. 이제 아래의 코드로 위지윅 에디터의 생성자를 동적으로 얻어올 수 있습니다.\n\n```\n@Component({...})\nexport class AppComponent {\n  title = 'app';\n  @ViewChild('textarea') el: ElementRef;\n\n  constructor(private injector: Injector, private loader: NgModuleFactoryLoader) {}\n\n  onClickLoadEditor() {\n    this.loader.load('src/app/modules/editor.module#EditorModule')\n        .then(factory => factory.create(this.injector).instance.load())\n        .then(({Editor}) => new Editor(this.el.nativeElement));\n  }\n}\n```\n\n사실 Angular@v5 이하에서는 webpack이 기본적으로 사용했던 `System.import`파서 플러그인으로 `.ts`파일 뿐만 아닌 여러 파일을 동적으로 간단히 분리할 수 있었습니다. 하지만 [email protected] 부터 webpack이 `System.import`파서 플러그인을 사용하지 않게 되었고. Angular@v6 버전 이후부터는 해당 코드가 발견되면 컴파일 시점에 경고를 출력합니다. 그렇기 때문에 `System.import`를 직접적으로 사용할 수 없고 본문과 같이 `NgModuleFactoryLoader`를 사용해야 합니다.\n\n재미있는 것은 `NgModuleFactoryLoader`의 구현체인 `SystemJsNgModuleLoader`내부에서는 `System.import`를 아직 사용하고 있다는 것입니다. 공식 github에서는 이 코드를 typescript의 `import`문을 사용하는 것으로 수정하려는 PR이 있습니다. 이 PR이 머지된다고 하더라도. 위 방법을 이용하는 데 문제는 없습니다.",
      "json_metadata": "{\"tags\":[\"angular\",\"angular2\",\"lazyloading\"],\"image\":[\"https://cdn.steemitimages.com/DQmeKHhZfrBdBqKy97xpbpnXqNv8EDt4oRuw3ouU1n1uwWZ/P5270018.jpg\"],\"links\":[\"http://www.websiteoptimization.com/speed/tweak/psychology-web-performance/\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}",
      "parent_author": "",
      "parent_permlink": "angular",
      "permlink": "angular-route",
      "title": "Angular에서 Route없이 모듈 동적 로딩하기"
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2018-06-05T09:08:06",
  "trx_id": "2d82e847cdb4d8e844fcd4ca3b13b7076072ec99",
  "trx_in_block": 11,
  "virtual_op": 0
}
mnkimreceived 0.014 SBD, 0.006 SP author reward for @mnkim / angular
2018/05/15 07:29:24
authormnkim
permlinkangular
sbd payout0.014 SBD
steem payout0.000 STEEM
vesting payout10.175082 VESTS
Transaction InfoBlock #22445695/Virtual Operation #14
View Raw JSON Data
{
  "block": 22445695,
  "op": [
    "author_reward",
    {
      "author": "mnkim",
      "permlink": "angular",
      "sbd_payout": "0.014 SBD",
      "steem_payout": "0.000 STEEM",
      "vesting_payout": "10.175082 VESTS"
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2018-05-15T07:29:24",
  "trx_id": "0000000000000000000000000000000000000000",
  "trx_in_block": 4294967295,
  "virtual_op": 14
}
2018/05/15 04:34:12
authormnkim
body@@ -149,21 +149,16 @@ %EA%B3%B5%ED%95%98%EB%8B%88 -%EC%9D%B4%EB%9F%B0%EB%A9%B4%EC%97%90%EC%84%9C %ED%9B%A8%EC%94%AC %EC%A2%8B%EC%8A%B5%EB%8B%88%EB%8B%A4 +%ED%9B%A8%EC%94%AC %EC%A2%8B%EB%8D%94%EB%9D%BC%EA%B3%A0%EC%9A%94 .%0A%0AR @@ -194,16 +194,27 @@ lar%EA%B0%80 + %EA%B2%B0%EA%B3%BC%EC%A0%81%EC%9C%BC%EB%A1%9C %EB%8D%94 %ED%95%99%EC%8A%B5%EA%B3%A1%EC%84%A0%EC%9D%B4 +%EB%82%98 %EB%B9%84%EC%9A%A9%EC%9D%B4 %EB%82%AE%EC%9D%80%EA%B1%B0
json metadata{"tags":["angular"],"app":"steemit/0.1"}
parent authorwoojin.joe
parent permlinkre-mnkim-angular-20180508t222709116z
permlinkre-woojinjoe-re-mnkim-angular-20180509t045821027z
title
Transaction InfoBlock #22442192/Trx 47ebab890e668e45a658a5ebb445b1fd0593f715
View Raw JSON Data
{
  "block": 22442192,
  "op": [
    "comment",
    {
      "author": "mnkim",
      "body": "@@ -149,21 +149,16 @@\n %EA%B3%B5%ED%95%98%EB%8B%88 \n-%EC%9D%B4%EB%9F%B0%EB%A9%B4%EC%97%90%EC%84%9C %ED%9B%A8%EC%94%AC %EC%A2%8B%EC%8A%B5%EB%8B%88%EB%8B%A4\n+%ED%9B%A8%EC%94%AC %EC%A2%8B%EB%8D%94%EB%9D%BC%EA%B3%A0%EC%9A%94\n .%0A%0AR\n@@ -194,16 +194,27 @@\n lar%EA%B0%80\n+ %EA%B2%B0%EA%B3%BC%EC%A0%81%EC%9C%BC%EB%A1%9C\n  %EB%8D%94 %ED%95%99%EC%8A%B5%EA%B3%A1%EC%84%A0%EC%9D%B4\n+%EB%82%98 %EB%B9%84%EC%9A%A9%EC%9D%B4\n  %EB%82%AE%EC%9D%80%EA%B1%B0\n",
      "json_metadata": "{\"tags\":[\"angular\"],\"app\":\"steemit/0.1\"}",
      "parent_author": "woojin.joe",
      "parent_permlink": "re-mnkim-angular-20180508t222709116z",
      "permlink": "re-woojinjoe-re-mnkim-angular-20180509t045821027z",
      "title": ""
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2018-05-15T04:34:12",
  "trx_id": "47ebab890e668e45a658a5ebb445b1fd0593f715",
  "trx_in_block": 8,
  "virtual_op": 0
}
2018/05/09 04:58:21
authormnkim
bodyReact, Vue.js는 렌더링에 관련된 라이브러리만 제공되고 규모가 커질수록 서드파티 라이브러리를 사용해야 개발이 수월해지는데요. 이게 나중에 버전이 안맞는다던가 하는 등. 유지보수에 발목을 잡더군요. Angular는 그 자체로 웹 앱에 필요한 거의 모든것을 제공하니 이런면에서 훨씬 좋습니다. React, Angular둘 다 해본 입장에선 Angular가 더 학습곡선이 낮은거 같아요.
json metadata{"tags":["angular"],"app":"steemit/0.1"}
parent authorwoojin.joe
parent permlinkre-mnkim-angular-20180508t222709116z
permlinkre-woojinjoe-re-mnkim-angular-20180509t045821027z
title
Transaction InfoBlock #22269895/Trx f64e47e421d28c940752e92a13228a0530ed4c56
View Raw JSON Data
{
  "block": 22269895,
  "op": [
    "comment",
    {
      "author": "mnkim",
      "body": "React, Vue.js는 렌더링에 관련된 라이브러리만 제공되고 규모가 커질수록 서드파티 라이브러리를 사용해야 개발이 수월해지는데요. 이게 나중에 버전이 안맞는다던가 하는 등. 유지보수에 발목을 잡더군요. Angular는 그 자체로 웹 앱에 필요한 거의 모든것을 제공하니 이런면에서 훨씬 좋습니다.\n\nReact, Angular둘 다 해본 입장에선 Angular가 더 학습곡선이 낮은거 같아요.",
      "json_metadata": "{\"tags\":[\"angular\"],\"app\":\"steemit/0.1\"}",
      "parent_author": "woojin.joe",
      "parent_permlink": "re-mnkim-angular-20180508t222709116z",
      "permlink": "re-woojinjoe-re-mnkim-angular-20180509t045821027z",
      "title": ""
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2018-05-09T04:58:21",
  "trx_id": "f64e47e421d28c940752e92a13228a0530ed4c56",
  "trx_in_block": 46,
  "virtual_op": 0
}
2018/05/09 04:51:54
authorwoojin.joe
permlinkre-mnkim-angular-20180508t222709116z
votermnkim
weight10000 (100.00%)
Transaction InfoBlock #22269766/Trx 61228337032ac84a26639322e0c1c19e96d641b1
View Raw JSON Data
{
  "block": 22269766,
  "op": [
    "vote",
    {
      "author": "woojin.joe",
      "permlink": "re-mnkim-angular-20180508t222709116z",
      "voter": "mnkim",
      "weight": 10000
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2018-05-09T04:51:54",
  "trx_id": "61228337032ac84a26639322e0c1c19e96d641b1",
  "trx_in_block": 0,
  "virtual_op": 0
}
2018/05/08 22:27:09
authorwoojin.joe
body잘 봤습니다. :) 그래서 앵귤러 전도사(?) 역할을 하는 Minko Gechev가 DI기능만 쏙 빼서 이런것도 만들었죠. https://github.com/mgechev/injection-js 앵귤러가 리액트,뷰에 비해 학습곡선이 높지만 (저 같은 백엔드 엔지니어에겐) DI 등과 같이 기능적으로나 아키텍처측면에서 친숙한 것 같아요.
json metadata{"tags":["angular"],"links":["https://github.com/mgechev/injection-js"],"app":"steemit/0.1"}
parent authormnkim
parent permlinkangular
permlinkre-mnkim-angular-20180508t222709116z
title
Transaction InfoBlock #22262071/Trx 39f1f41323eb84e7aace3c57593d766739a9a9d1
View Raw JSON Data
{
  "block": 22262071,
  "op": [
    "comment",
    {
      "author": "woojin.joe",
      "body": "잘 봤습니다. :)\n그래서 앵귤러 전도사(?) 역할을 하는 Minko Gechev가 DI기능만 쏙 빼서 이런것도 만들었죠. \n\nhttps://github.com/mgechev/injection-js\n\n앵귤러가 리액트,뷰에 비해 학습곡선이 높지만 (저 같은 백엔드 엔지니어에겐) DI 등과 같이 기능적으로나 아키텍처측면에서 친숙한 것 같아요.",
      "json_metadata": "{\"tags\":[\"angular\"],\"links\":[\"https://github.com/mgechev/injection-js\"],\"app\":\"steemit/0.1\"}",
      "parent_author": "mnkim",
      "parent_permlink": "angular",
      "permlink": "re-mnkim-angular-20180508t222709116z",
      "title": ""
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2018-05-08T22:27:09",
  "trx_id": "39f1f41323eb84e7aace3c57593d766739a9a9d1",
  "trx_in_block": 22,
  "virtual_op": 0
}
woojin.joeupvoted (100.00%) @mnkim / angular
2018/05/08 22:21:36
authormnkim
permlinkangular
voterwoojin.joe
weight10000 (100.00%)
Transaction InfoBlock #22261960/Trx 425bd65963f26cf213f62ab1c8b5e281537b8e27
View Raw JSON Data
{
  "block": 22261960,
  "op": [
    "vote",
    {
      "author": "mnkim",
      "permlink": "angular",
      "voter": "woojin.joe",
      "weight": 10000
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2018-05-08T22:21:36",
  "trx_id": "425bd65963f26cf213f62ab1c8b5e281537b8e27",
  "trx_in_block": 9,
  "virtual_op": 0
}
mnkimpublished a new post: angular
2018/05/08 09:01:54
authormnkim
body@@ -946,16 +946,22 @@ %0A%7D%0A%60%60%60%0A%0A +----%0A%0A %60%60%60javas @@ -1644,19 +1644,32 @@ %0A/** -%0A * %5B%EC%B0%B8%EA%B3%A01%5D%0A +******** %5B%EC%B0%B8%EA%B3%A01%5D ********* */%0Av @@ -2080,27 +2080,32 @@ /** -%0A * %5B%EC%B0%B8%EA%B3%A02%5D%0A +******** %5B%EC%B0%B8%EA%B3%A02%5D ********* */%0A
json metadata{"tags":["angular","javascript","typescript","di","dependencyinjection"],"links":["http://www.typescriptlang.org/docs/handbook/decorators.html#metadata","https://github.com/angular/angular/blob/b7544cccc699c2274bbc9a3e2eb4351632d0b410/packages/core/src/reflection/reflection_capabilities.ts#L62","https://github.com/rbuckton/reflect-metadata"],"app":"steemit/0.1","format":"markdown","image":["https://steemitimages.com/DQmNiYjKBVhCZdwFeYoHB2MhpnKNq8wjbijAFQj241kKfGq/P4280164%20(1).jpg"]}
parent author
parent permlinkangular
permlinkangular
titleAngular는 클래스 생성에 필요한 인자들을 어떻게 알까
Transaction InfoBlock #22245967/Trx 6eb08fea14e8bd1ffcaa269facb1004db5ed4d8c
View Raw JSON Data
{
  "block": 22245967,
  "op": [
    "comment",
    {
      "author": "mnkim",
      "body": "@@ -946,16 +946,22 @@\n %0A%7D%0A%60%60%60%0A%0A\n+----%0A%0A\n %60%60%60javas\n@@ -1644,19 +1644,32 @@\n %0A/**\n-%0A * %5B%EC%B0%B8%EA%B3%A01%5D%0A \n+******** %5B%EC%B0%B8%EA%B3%A01%5D *********\n */%0Av\n@@ -2080,27 +2080,32 @@\n  /**\n-%0A     * %5B%EC%B0%B8%EA%B3%A02%5D%0A     \n+******** %5B%EC%B0%B8%EA%B3%A02%5D *********\n */%0A \n",
      "json_metadata": "{\"tags\":[\"angular\",\"javascript\",\"typescript\",\"di\",\"dependencyinjection\"],\"links\":[\"http://www.typescriptlang.org/docs/handbook/decorators.html#metadata\",\"https://github.com/angular/angular/blob/b7544cccc699c2274bbc9a3e2eb4351632d0b410/packages/core/src/reflection/reflection_capabilities.ts#L62\",\"https://github.com/rbuckton/reflect-metadata\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\",\"image\":[\"https://steemitimages.com/DQmNiYjKBVhCZdwFeYoHB2MhpnKNq8wjbijAFQj241kKfGq/P4280164%20(1).jpg\"]}",
      "parent_author": "",
      "parent_permlink": "angular",
      "permlink": "angular",
      "title": "Angular는 클래스 생성에 필요한 인자들을 어떻게 알까"
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2018-05-08T09:01:54",
  "trx_id": "6eb08fea14e8bd1ffcaa269facb1004db5ed4d8c",
  "trx_in_block": 51,
  "virtual_op": 0
}
dongkunupvoted (100.00%) @mnkim / angular
2018/05/08 08:42:12
authormnkim
permlinkangular
voterdongkun
weight10000 (100.00%)
Transaction InfoBlock #22245573/Trx 313bbd16d2826049f4e4ee5d3df25fb3272c60d4
View Raw JSON Data
{
  "block": 22245573,
  "op": [
    "vote",
    {
      "author": "mnkim",
      "permlink": "angular",
      "voter": "dongkun",
      "weight": 10000
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2018-05-08T08:42:12",
  "trx_id": "313bbd16d2826049f4e4ee5d3df25fb3272c60d4",
  "trx_in_block": 55,
  "virtual_op": 0
}
mnkimpublished a new post: angular
2018/05/08 08:30:54
authormnkim
body@@ -2933,16 +2933,17 @@ API%EC%9E%85%EB%8B%88%EB%8B%A4. +%5B Typescri @@ -2949,16 +2949,87 @@ ipt%EA%B3%B5%EC%8B%9D %EB%AC%B8%EC%84%9C +%5D(http://www.typescriptlang.org/docs/handbook/decorators.html#metadata) %EC%97%90%EC%84%9C%EB%8A%94 Deco
json metadata{"tags":["angular","javascript","typescript","di","dependencyinjection"],"links":["http://www.typescriptlang.org/docs/handbook/decorators.html#metadata","https://github.com/angular/angular/blob/b7544cccc699c2274bbc9a3e2eb4351632d0b410/packages/core/src/reflection/reflection_capabilities.ts#L62","https://github.com/rbuckton/reflect-metadata"],"app":"steemit/0.1","format":"markdown","image":["https://steemitimages.com/DQmNiYjKBVhCZdwFeYoHB2MhpnKNq8wjbijAFQj241kKfGq/P4280164%20(1).jpg"]}
parent author
parent permlinkangular
permlinkangular
titleAngular는 클래스 생성에 필요한 인자들을 어떻게 알까
Transaction InfoBlock #22245347/Trx 9e644195195fb9b8be059fbbd421859d31a6424c
View Raw JSON Data
{
  "block": 22245347,
  "op": [
    "comment",
    {
      "author": "mnkim",
      "body": "@@ -2933,16 +2933,17 @@\n API%EC%9E%85%EB%8B%88%EB%8B%A4. \n+%5B\n Typescri\n@@ -2949,16 +2949,87 @@\n ipt%EA%B3%B5%EC%8B%9D %EB%AC%B8%EC%84%9C\n+%5D(http://www.typescriptlang.org/docs/handbook/decorators.html#metadata)\n %EC%97%90%EC%84%9C%EB%8A%94 Deco\n",
      "json_metadata": "{\"tags\":[\"angular\",\"javascript\",\"typescript\",\"di\",\"dependencyinjection\"],\"links\":[\"http://www.typescriptlang.org/docs/handbook/decorators.html#metadata\",\"https://github.com/angular/angular/blob/b7544cccc699c2274bbc9a3e2eb4351632d0b410/packages/core/src/reflection/reflection_capabilities.ts#L62\",\"https://github.com/rbuckton/reflect-metadata\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\",\"image\":[\"https://steemitimages.com/DQmNiYjKBVhCZdwFeYoHB2MhpnKNq8wjbijAFQj241kKfGq/P4280164%20(1).jpg\"]}",
      "parent_author": "",
      "parent_permlink": "angular",
      "permlink": "angular",
      "title": "Angular는 클래스 생성에 필요한 인자들을 어떻게 알까"
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2018-05-08T08:30:54",
  "trx_id": "9e644195195fb9b8be059fbbd421859d31a6424c",
  "trx_in_block": 15,
  "virtual_op": 0
}
mnkimpublished a new post: angular
2018/05/08 08:21:09
authormnkim
body@@ -1,22 +1,26 @@ !%5BP4280164 + (1) .jpg%5D(https: @@ -46,52 +46,52 @@ /DQm -YC1jHE29iZTJSuxUdxTQjB77gKUNSzj3gJyeNHzzXs8o +NiYjKBVhCZdwFeYoHB2MhpnKNq8wjbijAFQj241kKfGq /P42 @@ -95,16 +95,22 @@ P4280164 +%2520(1) .jpg)%0A%0A%EC%9D%98
json metadata{"tags":["angular","javascript","typescript","di","dependencyinjection"],"links":["https://github.com/angular/angular/blob/b7544cccc699c2274bbc9a3e2eb4351632d0b410/packages/core/src/reflection/reflection_capabilities.ts#L62","https://github.com/rbuckton/reflect-metadata"],"app":"steemit/0.1","format":"markdown","image":["https://steemitimages.com/DQmNiYjKBVhCZdwFeYoHB2MhpnKNq8wjbijAFQj241kKfGq/P4280164%20(1).jpg"]}
parent author
parent permlinkangular
permlinkangular
titleAngular는 클래스 생성에 필요한 인자들을 어떻게 알까
Transaction InfoBlock #22245152/Trx 998c0c4566cd9aae23a0a52e0d8138e4075748a4
View Raw JSON Data
{
  "block": 22245152,
  "op": [
    "comment",
    {
      "author": "mnkim",
      "body": "@@ -1,22 +1,26 @@\n !%5BP4280164\n+ (1)\n .jpg%5D(https:\n@@ -46,52 +46,52 @@\n /DQm\n-YC1jHE29iZTJSuxUdxTQjB77gKUNSzj3gJyeNHzzXs8o\n+NiYjKBVhCZdwFeYoHB2MhpnKNq8wjbijAFQj241kKfGq\n /P42\n@@ -95,16 +95,22 @@\n P4280164\n+%2520(1)\n .jpg)%0A%0A%EC%9D%98\n",
      "json_metadata": "{\"tags\":[\"angular\",\"javascript\",\"typescript\",\"di\",\"dependencyinjection\"],\"links\":[\"https://github.com/angular/angular/blob/b7544cccc699c2274bbc9a3e2eb4351632d0b410/packages/core/src/reflection/reflection_capabilities.ts#L62\",\"https://github.com/rbuckton/reflect-metadata\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\",\"image\":[\"https://steemitimages.com/DQmNiYjKBVhCZdwFeYoHB2MhpnKNq8wjbijAFQj241kKfGq/P4280164%20(1).jpg\"]}",
      "parent_author": "",
      "parent_permlink": "angular",
      "permlink": "angular",
      "title": "Angular는 클래스 생성에 필요한 인자들을 어떻게 알까"
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2018-05-08T08:21:09",
  "trx_id": "998c0c4566cd9aae23a0a52e0d8138e4075748a4",
  "trx_in_block": 22,
  "virtual_op": 0
}
mnkimpublished a new post: angular
2018/05/08 08:20:06
authormnkim
body![P4280164.jpg](https://steemitimages.com/DQmYC1jHE29iZTJSuxUdxTQjB77gKUNSzj3gJyeNHzzXs8o/P4280164.jpg) 의존성 주입 패턴은 Angular의 핵심 시스템입니다. 이 패턴으로 각 모듈은 더 이상 다른 모듈을 직접 참조하거나 생성하지 않습니다. 필요한 모듈은 일반적으로 '컨테이너'라 불리는 별도의 인스턴스 관리 객체로 부터 주입받습니다. 이 의존성 주입 시스템은 사실 순수하게 Angular의 기능은 아닙니다. Javascript를 래핑해 타입 시스템을 추가한 언어인 Typescript와 proposal 단계의 ECMASscript 스펙 `reflect-metadata`가 이 패턴이 동작하는 데 필요한 역할들을 하고 있습니다. 의존성 주입 시스템의 필요한 조건들 중 하나는 어떤 클래스가 생성될 때 어떤 인자를 필요로 하는지 알고 있어야 한다는 것입니다. 이 글이 쓰여질 때 ECMAScript의 최신 버전인 2018 에도 아직 해당 스펙이 존재하거나 논의되지 않고 있습니다. 따라서 순수한 Javascript만으로는 별도의 처리 없이 이 패턴을 구현하기가 까다롭습니다. 따라서 Typescript와 같은 트랜스파일러가 꼭 필요합니다. Typescript는 Decorator가 달린 클래스를 트랜스파일 할 때 이를 처리하기 위한 폴리필 함수를 소스에 추가합니다 1). 아래는 Typescript소스와 이를 트랜스파일한 소스입니다. 1) 공식 문서에 따르면 Decorator와 Metadata를 사용하려면 tsconfig.json에 experimentalDecorators, emitDecoratorMetadata옵션을 true로 설정해야 합니다. ```typescript // User.ts @log class User { constructor(name: string) {} } ``` ```javascript // bundle.js "use strict"; var __decorate = this && this.__decorate || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if ((typeof Reflect === "undefined" ? "undefined" : _typeof(Reflect)) === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);else for (var i = decorators.length - 1; i >= 0; i--) { if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; }return c > 3 && r && Object.defineProperty(target, key, r), r; }; /** * [참고1] */ var __metadata = this && this.__metadata || function (k, v) { if ((typeof Reflect === "undefined" ? "undefined" : _typeof(Reflect)) === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; Object.defineProperty(exports, "__esModule", { value: true }); var User = /** @class */function () { function User(name) {} User = __decorate([ decorators_1.forClass, /** * [참고2] */ __metadata("design:paramtypes", [String]) ], User); return User; }(); ``` 트랜스파일 된 소스엔 원본 파일에 있는 소스 말고도 `__decorate`와 `__metadata`라는 두 함수가 추가로 정의되어 있습니다. `__decorate`함수는 `@log`의 기능을 `User` 클래스에 적용하기 위한 폴리필 함수입니다. 아래에서 `User`클래스를 생성할 때 `log` `Decorator`를 배열에 담아 인자로 호출하고 있습니다. `Decorator`가 달린 클래스들은 전부 동일하게 트랜스파일됩니다. `__metadata`함수*[참고1]*는 이 글의 주제인 의존성 주입 패턴과 밀접한 관련이 있습니다. 강조된 코드에서 `__metadata`함수에 `"design:paramtypes"` 리터럴 문자열과 배열로 `String` 클래스를 넘기는 것을 볼 수 있습니다. *[참고2]* 이 정보가 바로 `User`클래스 생성자 함수의 인자에 대한 정보입니다. 이어서 `__metadata`함수는 전달받은 생성자 파라미터 정보를 그대로 `Reflect.metadata`함수의 인자로 호출하고 있습니다. 이렇게 메타데이터가 등록된 후 아래의 코드를 실행하면 앞서 언급했던 조건인 `User`클래스의 생성자가 어떤 인자를 필요로 하는지에 대한 정보를 얻을 수 있습니다. ```typescript Reflect.getMedata('design':paramtypes', User); // log: [String] ``` `reflect-metadata` API는 `TC39`에 아직 등록조자 되지 않은 Experimental 상태의 비표준 API입니다. Typescript공식 문서에서는 Decorator가 표준이 될 때 아마 같이 표준으로 등록될 것이라고 안내하고 있습니다. 실제로 [`ReflectionCapabilities`클래스 내부 구현](https://github.com/angular/angular/blob/b7544cccc699c2274bbc9a3e2eb4351632d0b410/packages/core/src/reflection/reflection_capabilities.ts#L62)을 보면 Angular가 해당 API를 사용하고 있는 것을 볼 수 있습니다. `reflect-metadata`말고도 direct API, tsickle등의 도구에서 분석된 파라미터도 참고하고 있는 것을 볼 수 있습니다만. 기본적인 방식은 같습니다. 참고 - `reflect-metadata` https://github.com/rbuckton/reflect-metadata
json metadata{"tags":["angular","javascript","typescript","di","dependencyinjection"],"links":["https://github.com/angular/angular/blob/b7544cccc699c2274bbc9a3e2eb4351632d0b410/packages/core/src/reflection/reflection_capabilities.ts#L62","https://github.com/rbuckton/reflect-metadata"],"app":"steemit/0.1","format":"markdown","image":["https://steemitimages.com/DQmYC1jHE29iZTJSuxUdxTQjB77gKUNSzj3gJyeNHzzXs8o/P4280164.jpg"]}
parent author
parent permlinkangular
permlinkangular
titleAngular는 클래스 생성에 필요한 인자들을 어떻게 알까
Transaction InfoBlock #22245131/Trx 0ab9587eb59ca3ff6234c177abdf1fa7ba4d4df5
View Raw JSON Data
{
  "block": 22245131,
  "op": [
    "comment",
    {
      "author": "mnkim",
      "body": "![P4280164.jpg](https://steemitimages.com/DQmYC1jHE29iZTJSuxUdxTQjB77gKUNSzj3gJyeNHzzXs8o/P4280164.jpg)\n\n의존성 주입 패턴은 Angular의 핵심 시스템입니다. 이 패턴으로 각 모듈은 더 이상 다른 모듈을 직접 참조하거나 생성하지 않습니다. 필요한 모듈은 일반적으로 '컨테이너'라 불리는 별도의 인스턴스 관리 객체로 부터 주입받습니다.\n\n이 의존성 주입 시스템은 사실 순수하게 Angular의 기능은 아닙니다. Javascript를 래핑해 타입 시스템을 추가한 언어인 Typescript와 proposal 단계의 ECMASscript 스펙 `reflect-metadata`가 이 패턴이 동작하는 데 필요한 역할들을 하고 있습니다.\n\n의존성 주입 시스템의 필요한 조건들 중 하나는 어떤 클래스가 생성될 때 어떤 인자를 필요로 하는지 알고 있어야 한다는 것입니다. 이 글이 쓰여질 때 ECMAScript의 최신 버전인 2018 에도 아직 해당 스펙이 존재하거나 논의되지 않고 있습니다. 따라서 순수한 Javascript만으로는 별도의 처리 없이 이 패턴을 구현하기가 까다롭습니다. 따라서 Typescript와 같은 트랜스파일러가 꼭 필요합니다.\n\nTypescript는 Decorator가 달린 클래스를 트랜스파일 할 때 이를 처리하기 위한 폴리필 함수를 소스에 추가합니다 1). 아래는 Typescript소스와 이를 트랜스파일한 소스입니다.\n\n1) 공식 문서에 따르면 Decorator와 Metadata를 사용하려면 tsconfig.json에 experimentalDecorators, emitDecoratorMetadata옵션을 true로 설정해야 합니다.\n\n```typescript\n// User.ts\n@log\nclass User {\n  constructor(name: string) {}\n}\n```\n\n```javascript\n// bundle.js\n\"use strict\";\nvar __decorate = this && this.__decorate || function (decorators, target, key, desc) {\n    var c = arguments.length,\n        r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc,\n        d;\n    if ((typeof Reflect === \"undefined\" ? \"undefined\" : _typeof(Reflect)) === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);else for (var i = decorators.length - 1; i >= 0; i--) {\n        if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n    }return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\n\n/**\n * [참고1]\n */\nvar __metadata = this && this.__metadata || function (k, v) {\n    if ((typeof Reflect === \"undefined\" ? \"undefined\" : _typeof(Reflect)) === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(k, v);\n};\n\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar User = /** @class */function () {\n  function User(name) {}\n  User = __decorate([\n    decorators_1.forClass,\n    /**\n     * [참고2]\n     */\n    __metadata(\"design:paramtypes\", [String])\n  ], User);\n  return User;\n}();\n```\n\n트랜스파일 된 소스엔 원본 파일에 있는 소스 말고도 `__decorate`와 `__metadata`라는 두 함수가 추가로 정의되어 있습니다.\n\n`__decorate`함수는 `@log`의 기능을 `User` 클래스에 적용하기 위한 폴리필 함수입니다. 아래에서 `User`클래스를 생성할 때 `log` `Decorator`를 배열에 담아 인자로 호출하고 있습니다. `Decorator`가 달린 클래스들은 전부 동일하게 트랜스파일됩니다.\n\n`__metadata`함수*[참고1]*는 이 글의 주제인 의존성 주입 패턴과 밀접한 관련이 있습니다. 강조된 코드에서 `__metadata`함수에 `\"design:paramtypes\"` 리터럴 문자열과 배열로 `String` 클래스를 넘기는 것을 볼 수 있습니다. *[참고2]* 이 정보가 바로 `User`클래스 생성자 함수의 인자에 대한 정보입니다.\n\n이어서 `__metadata`함수는 전달받은 생성자 파라미터 정보를 그대로 `Reflect.metadata`함수의 인자로 호출하고 있습니다. 이렇게 메타데이터가 등록된 후 아래의 코드를 실행하면 앞서 언급했던 조건인 `User`클래스의 생성자가 어떤 인자를 필요로 하는지에 대한 정보를 얻을 수 있습니다.\n\n```typescript\nReflect.getMedata('design':paramtypes', User);\n// log: [String]\n```\n\n`reflect-metadata` API는 `TC39`에 아직 등록조자 되지 않은 Experimental 상태의 비표준 API입니다. Typescript공식 문서에서는 Decorator가 표준이 될 때 아마 같이 표준으로 등록될 것이라고 안내하고 있습니다.\n\n실제로 [`ReflectionCapabilities`클래스 내부 구현](https://github.com/angular/angular/blob/b7544cccc699c2274bbc9a3e2eb4351632d0b410/packages/core/src/reflection/reflection_capabilities.ts#L62)을 보면 Angular가 해당 API를 사용하고 있는 것을 볼 수 있습니다. `reflect-metadata`말고도 direct API, tsickle등의 도구에서 분석된 파라미터도 참고하고 있는 것을 볼 수 있습니다만. 기본적인 방식은 같습니다.\n\n참고\n\n- `reflect-metadata` https://github.com/rbuckton/reflect-metadata",
      "json_metadata": "{\"tags\":[\"angular\",\"javascript\",\"typescript\",\"di\",\"dependencyinjection\"],\"links\":[\"https://github.com/angular/angular/blob/b7544cccc699c2274bbc9a3e2eb4351632d0b410/packages/core/src/reflection/reflection_capabilities.ts#L62\",\"https://github.com/rbuckton/reflect-metadata\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\",\"image\":[\"https://steemitimages.com/DQmYC1jHE29iZTJSuxUdxTQjB77gKUNSzj3gJyeNHzzXs8o/P4280164.jpg\"]}",
      "parent_author": "",
      "parent_permlink": "angular",
      "permlink": "angular",
      "title": "Angular는 클래스 생성에 필요한 인자들을 어떻게 알까"
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2018-05-08T08:20:06",
  "trx_id": "0ab9587eb59ca3ff6234c177abdf1fa7ba4d4df5",
  "trx_in_block": 46,
  "virtual_op": 0
}
mnkimpublished a new post: angular
2018/05/08 08:19:03
authormnkim
body@@ -1,16 +1,121 @@ +!%5BP4280164.jpg%5D(https://steemitimages.com/DQmYC1jHE29iZTJSuxUdxTQjB77gKUNSzj3gJyeNHzzXs8o/P4280164.jpg)%0A%0A %EC%9D%98%EC%A1%B4%EC%84%B1 %EC%A3%BC%EC%9E%85 %ED%8C%A8%ED%84%B4%EC%9D%80 Angul
json metadata{"tags":["angular","javascript","typescript","di","dependencyinjection"],"links":["https://github.com/angular/angular/blob/b7544cccc699c2274bbc9a3e2eb4351632d0b410/packages/core/src/reflection/reflection_capabilities.ts#L62","https://github.com/rbuckton/reflect-metadata"],"app":"steemit/0.1","format":"markdown","image":["https://steemitimages.com/DQmYC1jHE29iZTJSuxUdxTQjB77gKUNSzj3gJyeNHzzXs8o/P4280164.jpg"]}
parent author
parent permlinkangular
permlinkangular
titleAngular는 클래스 생성에 필요한 인자들을 어떻게 알까
Transaction InfoBlock #22245110/Trx 166b993cb450b330e2532d7c322032cf9cab808b
View Raw JSON Data
{
  "block": 22245110,
  "op": [
    "comment",
    {
      "author": "mnkim",
      "body": "@@ -1,16 +1,121 @@\n+!%5BP4280164.jpg%5D(https://steemitimages.com/DQmYC1jHE29iZTJSuxUdxTQjB77gKUNSzj3gJyeNHzzXs8o/P4280164.jpg)%0A%0A\n %EC%9D%98%EC%A1%B4%EC%84%B1 %EC%A3%BC%EC%9E%85 %ED%8C%A8%ED%84%B4%EC%9D%80 Angul\n",
      "json_metadata": "{\"tags\":[\"angular\",\"javascript\",\"typescript\",\"di\",\"dependencyinjection\"],\"links\":[\"https://github.com/angular/angular/blob/b7544cccc699c2274bbc9a3e2eb4351632d0b410/packages/core/src/reflection/reflection_capabilities.ts#L62\",\"https://github.com/rbuckton/reflect-metadata\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\",\"image\":[\"https://steemitimages.com/DQmYC1jHE29iZTJSuxUdxTQjB77gKUNSzj3gJyeNHzzXs8o/P4280164.jpg\"]}",
      "parent_author": "",
      "parent_permlink": "angular",
      "permlink": "angular",
      "title": "Angular는 클래스 생성에 필요한 인자들을 어떻게 알까"
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2018-05-08T08:19:03",
  "trx_id": "166b993cb450b330e2532d7c322032cf9cab808b",
  "trx_in_block": 46,
  "virtual_op": 0
}
ax3upvoted (1.00%) @mnkim / angular
2018/05/08 07:29:33
authormnkim
permlinkangular
voterax3
weight100 (1.00%)
Transaction InfoBlock #22244120/Trx 6a23f2f0766d120322101d976017a491a7f02513
View Raw JSON Data
{
  "block": 22244120,
  "op": [
    "vote",
    {
      "author": "mnkim",
      "permlink": "angular",
      "voter": "ax3",
      "weight": 100
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2018-05-08T07:29:33",
  "trx_id": "6a23f2f0766d120322101d976017a491a7f02513",
  "trx_in_block": 12,
  "virtual_op": 0
}
mnkimpublished a new post: angular
2018/05/08 07:29:24
authormnkim
body의존성 주입 패턴은 Angular의 핵심 시스템입니다. 이 패턴으로 각 모듈은 더 이상 다른 모듈을 직접 참조하거나 생성하지 않습니다. 필요한 모듈은 일반적으로 '컨테이너'라 불리는 별도의 인스턴스 관리 객체로 부터 주입받습니다. 이 의존성 주입 시스템은 사실 순수하게 Angular의 기능은 아닙니다. Javascript를 래핑해 타입 시스템을 추가한 언어인 Typescript와 proposal 단계의 ECMASscript 스펙 `reflect-metadata`가 이 패턴이 동작하는 데 필요한 역할들을 하고 있습니다. 의존성 주입 시스템의 필요한 조건들 중 하나는 어떤 클래스가 생성될 때 어떤 인자를 필요로 하는지 알고 있어야 한다는 것입니다. 이 글이 쓰여질 때 ECMAScript의 최신 버전인 2018 에도 아직 해당 스펙이 존재하거나 논의되지 않고 있습니다. 따라서 순수한 Javascript만으로는 별도의 처리 없이 이 패턴을 구현하기가 까다롭습니다. 따라서 Typescript와 같은 트랜스파일러가 꼭 필요합니다. Typescript는 Decorator가 달린 클래스를 트랜스파일 할 때 이를 처리하기 위한 폴리필 함수를 소스에 추가합니다 1). 아래는 Typescript소스와 이를 트랜스파일한 소스입니다. 1) 공식 문서에 따르면 Decorator와 Metadata를 사용하려면 tsconfig.json에 experimentalDecorators, emitDecoratorMetadata옵션을 true로 설정해야 합니다. ```typescript // User.ts @log class User { constructor(name: string) {} } ``` ```javascript // bundle.js "use strict"; var __decorate = this && this.__decorate || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if ((typeof Reflect === "undefined" ? "undefined" : _typeof(Reflect)) === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);else for (var i = decorators.length - 1; i >= 0; i--) { if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; }return c > 3 && r && Object.defineProperty(target, key, r), r; }; /** * [참고1] */ var __metadata = this && this.__metadata || function (k, v) { if ((typeof Reflect === "undefined" ? "undefined" : _typeof(Reflect)) === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; Object.defineProperty(exports, "__esModule", { value: true }); var User = /** @class */function () { function User(name) {} User = __decorate([ decorators_1.forClass, /** * [참고2] */ __metadata("design:paramtypes", [String]) ], User); return User; }(); ``` 트랜스파일 된 소스엔 원본 파일에 있는 소스 말고도 `__decorate`와 `__metadata`라는 두 함수가 추가로 정의되어 있습니다. `__decorate`함수는 `@log`의 기능을 `User` 클래스에 적용하기 위한 폴리필 함수입니다. 아래에서 `User`클래스를 생성할 때 `log` `Decorator`를 배열에 담아 인자로 호출하고 있습니다. `Decorator`가 달린 클래스들은 전부 동일하게 트랜스파일됩니다. `__metadata`함수*[참고1]*는 이 글의 주제인 의존성 주입 패턴과 밀접한 관련이 있습니다. 강조된 코드에서 `__metadata`함수에 `"design:paramtypes"` 리터럴 문자열과 배열로 `String` 클래스를 넘기는 것을 볼 수 있습니다. *[참고2]* 이 정보가 바로 `User`클래스 생성자 함수의 인자에 대한 정보입니다. 이어서 `__metadata`함수는 전달받은 생성자 파라미터 정보를 그대로 `Reflect.metadata`함수의 인자로 호출하고 있습니다. 이렇게 메타데이터가 등록된 후 아래의 코드를 실행하면 앞서 언급했던 조건인 `User`클래스의 생성자가 어떤 인자를 필요로 하는지에 대한 정보를 얻을 수 있습니다. ```typescript Reflect.getMedata('design':paramtypes', User); // log: [String] ``` `reflect-metadata` API는 `TC39`에 아직 등록조자 되지 않은 Experimental 상태의 비표준 API입니다. Typescript공식 문서에서는 Decorator가 표준이 될 때 아마 같이 표준으로 등록될 것이라고 안내하고 있습니다. 실제로 [`ReflectionCapabilities`클래스 내부 구현](https://github.com/angular/angular/blob/b7544cccc699c2274bbc9a3e2eb4351632d0b410/packages/core/src/reflection/reflection_capabilities.ts#L62)을 보면 Angular가 해당 API를 사용하고 있는 것을 볼 수 있습니다. `reflect-metadata`말고도 direct API, tsickle등의 도구에서 분석된 파라미터도 참고하고 있는 것을 볼 수 있습니다만. 기본적인 방식은 같습니다. 참고 - `reflect-metadata` https://github.com/rbuckton/reflect-metadata
json metadata{"tags":["angular","javascript","typescript","di","dependencyinjection"],"links":["https://github.com/angular/angular/blob/b7544cccc699c2274bbc9a3e2eb4351632d0b410/packages/core/src/reflection/reflection_capabilities.ts#L62","https://github.com/rbuckton/reflect-metadata"],"app":"steemit/0.1","format":"markdown"}
parent author
parent permlinkangular
permlinkangular
titleAngular는 클래스 생성에 필요한 인자들을 어떻게 알까
Transaction InfoBlock #22244117/Trx 8b0448273b4f7f6843c6abf1736e8d391707c724
View Raw JSON Data
{
  "block": 22244117,
  "op": [
    "comment",
    {
      "author": "mnkim",
      "body": "의존성 주입 패턴은 Angular의 핵심 시스템입니다. 이 패턴으로 각 모듈은 더 이상 다른 모듈을 직접 참조하거나 생성하지 않습니다. 필요한 모듈은 일반적으로 '컨테이너'라 불리는 별도의 인스턴스 관리 객체로 부터 주입받습니다.\n\n이 의존성 주입 시스템은 사실 순수하게 Angular의 기능은 아닙니다. Javascript를 래핑해 타입 시스템을 추가한 언어인 Typescript와 proposal 단계의 ECMASscript 스펙 `reflect-metadata`가 이 패턴이 동작하는 데 필요한 역할들을 하고 있습니다.\n\n의존성 주입 시스템의 필요한 조건들 중 하나는 어떤 클래스가 생성될 때 어떤 인자를 필요로 하는지 알고 있어야 한다는 것입니다. 이 글이 쓰여질 때 ECMAScript의 최신 버전인 2018 에도 아직 해당 스펙이 존재하거나 논의되지 않고 있습니다. 따라서 순수한 Javascript만으로는 별도의 처리 없이 이 패턴을 구현하기가 까다롭습니다. 따라서 Typescript와 같은 트랜스파일러가 꼭 필요합니다.\n\nTypescript는 Decorator가 달린 클래스를 트랜스파일 할 때 이를 처리하기 위한 폴리필 함수를 소스에 추가합니다 1). 아래는 Typescript소스와 이를 트랜스파일한 소스입니다.\n\n1) 공식 문서에 따르면 Decorator와 Metadata를 사용하려면 tsconfig.json에 experimentalDecorators, emitDecoratorMetadata옵션을 true로 설정해야 합니다.\n\n```typescript\n// User.ts\n@log\nclass User {\n  constructor(name: string) {}\n}\n```\n\n```javascript\n// bundle.js\n\"use strict\";\nvar __decorate = this && this.__decorate || function (decorators, target, key, desc) {\n    var c = arguments.length,\n        r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc,\n        d;\n    if ((typeof Reflect === \"undefined\" ? \"undefined\" : _typeof(Reflect)) === \"object\" && typeof Reflect.decorate === \"function\") r = Reflect.decorate(decorators, target, key, desc);else for (var i = decorators.length - 1; i >= 0; i--) {\n        if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;\n    }return c > 3 && r && Object.defineProperty(target, key, r), r;\n};\n\n/**\n * [참고1]\n */\nvar __metadata = this && this.__metadata || function (k, v) {\n    if ((typeof Reflect === \"undefined\" ? \"undefined\" : _typeof(Reflect)) === \"object\" && typeof Reflect.metadata === \"function\") return Reflect.metadata(k, v);\n};\n\nObject.defineProperty(exports, \"__esModule\", { value: true });\nvar User = /** @class */function () {\n  function User(name) {}\n  User = __decorate([\n    decorators_1.forClass,\n    /**\n     * [참고2]\n     */\n    __metadata(\"design:paramtypes\", [String])\n  ], User);\n  return User;\n}();\n```\n\n트랜스파일 된 소스엔 원본 파일에 있는 소스 말고도 `__decorate`와 `__metadata`라는 두 함수가 추가로 정의되어 있습니다.\n\n`__decorate`함수는 `@log`의 기능을 `User` 클래스에 적용하기 위한 폴리필 함수입니다. 아래에서 `User`클래스를 생성할 때 `log` `Decorator`를 배열에 담아 인자로 호출하고 있습니다. `Decorator`가 달린 클래스들은 전부 동일하게 트랜스파일됩니다.\n\n`__metadata`함수*[참고1]*는 이 글의 주제인 의존성 주입 패턴과 밀접한 관련이 있습니다. 강조된 코드에서 `__metadata`함수에 `\"design:paramtypes\"` 리터럴 문자열과 배열로 `String` 클래스를 넘기는 것을 볼 수 있습니다. *[참고2]* 이 정보가 바로 `User`클래스 생성자 함수의 인자에 대한 정보입니다.\n\n이어서 `__metadata`함수는 전달받은 생성자 파라미터 정보를 그대로 `Reflect.metadata`함수의 인자로 호출하고 있습니다. 이렇게 메타데이터가 등록된 후 아래의 코드를 실행하면 앞서 언급했던 조건인 `User`클래스의 생성자가 어떤 인자를 필요로 하는지에 대한 정보를 얻을 수 있습니다.\n\n```typescript\nReflect.getMedata('design':paramtypes', User);\n// log: [String]\n```\n\n`reflect-metadata` API는 `TC39`에 아직 등록조자 되지 않은 Experimental 상태의 비표준 API입니다. Typescript공식 문서에서는 Decorator가 표준이 될 때 아마 같이 표준으로 등록될 것이라고 안내하고 있습니다.\n\n실제로 [`ReflectionCapabilities`클래스 내부 구현](https://github.com/angular/angular/blob/b7544cccc699c2274bbc9a3e2eb4351632d0b410/packages/core/src/reflection/reflection_capabilities.ts#L62)을 보면 Angular가 해당 API를 사용하고 있는 것을 볼 수 있습니다. `reflect-metadata`말고도 direct API, tsickle등의 도구에서 분석된 파라미터도 참고하고 있는 것을 볼 수 있습니다만. 기본적인 방식은 같습니다.\n\n참고\n\n- `reflect-metadata` https://github.com/rbuckton/reflect-metadata",
      "json_metadata": "{\"tags\":[\"angular\",\"javascript\",\"typescript\",\"di\",\"dependencyinjection\"],\"links\":[\"https://github.com/angular/angular/blob/b7544cccc699c2274bbc9a3e2eb4351632d0b410/packages/core/src/reflection/reflection_capabilities.ts#L62\",\"https://github.com/rbuckton/reflect-metadata\"],\"app\":\"steemit/0.1\",\"format\":\"markdown\"}",
      "parent_author": "",
      "parent_permlink": "angular",
      "permlink": "angular",
      "title": "Angular는 클래스 생성에 필요한 인자들을 어떻게 알까"
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2018-05-08T07:29:24",
  "trx_id": "8b0448273b4f7f6843c6abf1736e8d391707c724",
  "trx_in_block": 41,
  "virtual_op": 0
}
steemdelegated 18.675 SP to @mnkim
2018/04/12 02:54:30
delegateemnkim
delegatorsteem
vesting shares30373.861677 VESTS
Transaction InfoBlock #21490628/Trx 3715c3e2bf295faa0d966c0545852b04db2450b9
View Raw JSON Data
{
  "block": 21490628,
  "op": [
    "delegate_vesting_shares",
    {
      "delegatee": "mnkim",
      "delegator": "steem",
      "vesting_shares": "30373.861677 VESTS"
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2018-04-12T02:54:30",
  "trx_id": "3715c3e2bf295faa0d966c0545852b04db2450b9",
  "trx_in_block": 34,
  "virtual_op": 0
}
steemcreated a new account: @mnkim
2018/04/12 00:47:48
active{"account_auths":[],"key_auths":[["STM85PsTh3MXSxG8hspgT4LoQrpayLqHiMSRGFVufs9rnY5cAi1VZ",1]],"weight_threshold":1}
creatorsteem
delegation30690.000000 VESTS
extensions[]
fee0.100 STEEM
json metadata{}
memo keySTM7NCpqSwzRLX8fCWvoyCaLsVCBBbLEYoiJA9vtFk4KKemk1BitM
new account namemnkim
owner{"account_auths":[],"key_auths":[["STM83T3qMZ6smHSVkVu9bzsfZYmkuB8HTr7UaPBhCd2jcAcX1xxAC",1]],"weight_threshold":1}
posting{"account_auths":[],"key_auths":[["STM6adjVawMAg7bnZaGoxxqs2CEQdq16HvpAcfrhZ7PWtAdQpRVRb",1]],"weight_threshold":1}
Transaction InfoBlock #21488095/Trx 079a7ed852555fe985ec1e0a7e23c7b70d115fdf
View Raw JSON Data
{
  "block": 21488095,
  "op": [
    "account_create_with_delegation",
    {
      "active": {
        "account_auths": [],
        "key_auths": [
          [
            "STM85PsTh3MXSxG8hspgT4LoQrpayLqHiMSRGFVufs9rnY5cAi1VZ",
            1
          ]
        ],
        "weight_threshold": 1
      },
      "creator": "steem",
      "delegation": "30690.000000 VESTS",
      "extensions": [],
      "fee": "0.100 STEEM",
      "json_metadata": "{}",
      "memo_key": "STM7NCpqSwzRLX8fCWvoyCaLsVCBBbLEYoiJA9vtFk4KKemk1BitM",
      "new_account_name": "mnkim",
      "owner": {
        "account_auths": [],
        "key_auths": [
          [
            "STM83T3qMZ6smHSVkVu9bzsfZYmkuB8HTr7UaPBhCd2jcAcX1xxAC",
            1
          ]
        ],
        "weight_threshold": 1
      },
      "posting": {
        "account_auths": [],
        "key_auths": [
          [
            "STM6adjVawMAg7bnZaGoxxqs2CEQdq16HvpAcfrhZ7PWtAdQpRVRb",
            1
          ]
        ],
        "weight_threshold": 1
      }
    }
  ],
  "op_in_trx": 0,
  "timestamp": "2018-04-12T00:47:48",
  "trx_id": "079a7ed852555fe985ec1e0a7e23c7b70d115fdf",
  "trx_in_block": 4,
  "virtual_op": 0
}

Account Metadata

POSTING JSON METADATA
None
JSON METADATA
None
{
  "posting_json_metadata": {},
  "json_metadata": {}
}

Auth Keys

Owner
Single Signature
Public Keys
STM83T3qMZ6smHSVkVu9bzsfZYmkuB8HTr7UaPBhCd2jcAcX1xxAC1/1
Active
Single Signature
Public Keys
STM85PsTh3MXSxG8hspgT4LoQrpayLqHiMSRGFVufs9rnY5cAi1VZ1/1
Posting
Single Signature
Public Keys
STM6adjVawMAg7bnZaGoxxqs2CEQdq16HvpAcfrhZ7PWtAdQpRVRb1/1
Memo
STM7NCpqSwzRLX8fCWvoyCaLsVCBBbLEYoiJA9vtFk4KKemk1BitM
{
  "owner": {
    "weight_threshold": 1,
    "account_auths": [],
    "key_auths": [
      [
        "STM83T3qMZ6smHSVkVu9bzsfZYmkuB8HTr7UaPBhCd2jcAcX1xxAC",
        1
      ]
    ]
  },
  "active": {
    "weight_threshold": 1,
    "account_auths": [],
    "key_auths": [
      [
        "STM85PsTh3MXSxG8hspgT4LoQrpayLqHiMSRGFVufs9rnY5cAi1VZ",
        1
      ]
    ]
  },
  "posting": {
    "weight_threshold": 1,
    "account_auths": [],
    "key_auths": [
      [
        "STM6adjVawMAg7bnZaGoxxqs2CEQdq16HvpAcfrhZ7PWtAdQpRVRb",
        1
      ]
    ]
  },
  "memo": "STM7NCpqSwzRLX8fCWvoyCaLsVCBBbLEYoiJA9vtFk4KKemk1BitM"
}

Witness Votes

0 / 30
No active witness votes.
[]