VOTING POWER100.00%
DOWNVOTE POWER100.00%
RESOURCE CREDITS100.00%
REPUTATION PROGRESS40.31%
Net Worth
9.338USD
STEEM
0.340STEEM
SBD
0.000SBD
Own SP
174.009SP
Detailed Balance
| STEEM | ||
| balance | 0.340STEEM | STEEM |
| market_balance | 0.000STEEM | STEEM |
| savings_balance | 0.000STEEM | STEEM |
| reward_steem_balance | 0.000STEEM | STEEM |
| STEEM POWER | ||
| Own SP | 174.009SP | SP |
| Delegated Out | 0.000SP | SP |
| Delegation In | 0.000SP | SP |
| Effective Power | 174.009SP | SP |
| Reward SP (pending) | 0.000SP | SP |
| SBD | ||
| sbd_balance | 0.000SBD | SBD |
| sbd_conversions | 0.000SBD | SBD |
| sbd_market_balance | 0.000SBD | SBD |
| savings_sbd_balance | 0.000SBD | SBD |
| reward_sbd_balance | 0.000SBD | SBD |
{
"balance": "0.340 STEEM",
"savings_balance": "0.000 STEEM",
"reward_steem_balance": "0.000 STEEM",
"vesting_shares": "283360.173712 VESTS",
"delegated_vesting_shares": "0.000000 VESTS",
"received_vesting_shares": "0.000000 VESTS",
"sbd_balance": "0.000 SBD",
"savings_sbd_balance": "0.000 SBD",
"reward_sbd_balance": "0.000 SBD",
"conversions": []
}Account Info
| name | kormanocorp |
| id | 1013706 |
| rank | 12,129 |
| reputation | 14318683607877 |
| created | 2018-05-24T12:42:33 |
| recovery_account | steem |
| proxy | None |
| post_count | 259 |
| comment_count | 0 |
| lifetime_vote_count | 0 |
| witnesses_voted_for | 0 |
| last_post | 2023-04-25T01:29:42 |
| last_root_post | 2023-04-25T01:29:42 |
| last_vote_time | 2025-09-17T03:56:36 |
| proxied_vsf_votes | 0, 0, 0, 0 |
| can_vote | 1 |
| voting_power | 0 |
| delayed_votes | 0 |
| balance | 0.340 STEEM |
| savings_balance | 0.000 STEEM |
| sbd_balance | 0.000 SBD |
| savings_sbd_balance | 0.000 SBD |
| vesting_shares | 283360.173712 VESTS |
| delegated_vesting_shares | 0.000000 VESTS |
| received_vesting_shares | 0.000000 VESTS |
| reward_vesting_balance | 0.000000 VESTS |
| vesting_balance | 0.000 STEEM |
| vesting_withdraw_rate | 0.000000 VESTS |
| next_vesting_withdrawal | 1969-12-31T23:59:59 |
| withdrawn | 0 |
| to_withdraw | 0 |
| withdraw_routes | 0 |
| savings_withdraw_requests | 0 |
| last_account_recovery | 1970-01-01T00:00:00 |
| reset_account | null |
| last_owner_update | 1970-01-01T00:00:00 |
| last_account_update | 2022-03-24T11:14:06 |
| mined | No |
| sbd_seconds | 0 |
| sbd_last_interest_payment | 2023-04-12T03:03:30 |
| savings_sbd_last_interest_payment | 1970-01-01T00:00:00 |
{
"id": 1013706,
"name": "kormanocorp",
"owner": {
"weight_threshold": 1,
"account_auths": [],
"key_auths": [
[
"STM7FEPPzEHdiiJ29tLraF7sFa4DSmVQykZ7gKtU6z7guEo1drpUh",
1
]
]
},
"active": {
"weight_threshold": 1,
"account_auths": [],
"key_auths": [
[
"STM5yzbcYCe5sEoMWhyEjAE9BtE5rn9pCU7LEsQJMU6dcivQVUsGN",
1
]
]
},
"posting": {
"weight_threshold": 1,
"account_auths": [
[
"auto.steemkorea",
1
]
],
"key_auths": [
[
"STM7nTCj3e3s54pgejJUFaKFTAAb7EJKxzGba9M1JxGyyxyrKFcCt",
1
]
]
},
"memo_key": "STM8hnKpxC7hJdo9esQkSvPvB4bqtvkkEoQXrfASKir4WqRWBTD6W",
"json_metadata": "{\"profile\":{\"profile_image\":\"https://cdn.steemitimages.com/DQmZvXgPLYdfANFEY9G9ohtLABGcBo6RjhExcvocRcL8LN2/KakaoTalk_20180425_190709001.jpg\",\"name\":\"코마노\",\"website\":\"https://kormano.co.kr\",\"about\":\"마스터노드, 장기투자의 끝판대장\"}}",
"posting_json_metadata": "{\"profile\":{\"profile_image\":\"https://cdn.steemitimages.com/DQmeBbaEtLd4iP9DBR9fmKzTQTr72SXFhxCVEd3W9Njufui/20211001_124323.jpg\",\"name\":\"아울렛\",\"version\":2}}",
"proxy": "",
"last_owner_update": "1970-01-01T00:00:00",
"last_account_update": "2022-03-24T11:14:06",
"created": "2018-05-24T12:42:33",
"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": 259,
"can_vote": true,
"voting_manabar": {
"current_mana": "283360173712",
"last_update_time": 1758635379
},
"downvote_manabar": {
"current_mana": "70840043427",
"last_update_time": 1758635379
},
"voting_power": 0,
"balance": "0.340 STEEM",
"savings_balance": "0.000 STEEM",
"sbd_balance": "0.000 SBD",
"sbd_seconds": "0",
"sbd_seconds_last_update": "2025-09-23T13:49:39",
"sbd_last_interest_payment": "2023-04-12T03:03:30",
"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.000 SBD",
"reward_steem_balance": "0.000 STEEM",
"reward_vesting_balance": "0.000000 VESTS",
"reward_vesting_steem": "0.000 STEEM",
"vesting_shares": "283360.173712 VESTS",
"delegated_vesting_shares": "0.000000 VESTS",
"received_vesting_shares": "0.000000 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": 423,
"posting_rewards": 461097,
"proxied_vsf_votes": [
0,
0,
0,
0
],
"witnesses_voted_for": 0,
"last_post": "2023-04-25T01:29:42",
"last_root_post": "2023-04-25T01:29:42",
"last_vote_time": "2025-09-17T03:56:36",
"post_bandwidth": 0,
"pending_claimed_accounts": 0,
"vesting_balance": "0.000 STEEM",
"reputation": "14318683607877",
"transfer_history": [],
"market_history": [],
"post_history": [],
"vote_history": [],
"other_history": [],
"witness_votes": [],
"tags_usage": [],
"guest_bloggers": [],
"rank": 12129
}Withdraw Routes
| Incoming | Outgoing |
|---|---|
Empty | Empty |
{
"incoming": [],
"outgoing": []
}From Date
To Date
kormanocorpclaimed reward balance: 0.001 SP2025/09/23 13:49:39
kormanocorpclaimed reward balance: 0.001 SP
2025/09/23 13:49:39
| account | kormanocorp |
| reward steem | 0.000 STEEM |
| reward sbd | 0.000 SBD |
| reward vests | 1.656741 VESTS |
| Transaction Info | Block #99354289/Trx ebf0fbddb40f2a8d448eb25a88f1f37686b8265c |
View Raw JSON Data
{
"trx_id": "ebf0fbddb40f2a8d448eb25a88f1f37686b8265c",
"block": 99354289,
"trx_in_block": 0,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2025-09-23T13:49:39",
"op": [
"claim_reward_balance",
{
"account": "kormanocorp",
"reward_steem": "0.000 STEEM",
"reward_sbd": "0.000 SBD",
"reward_vests": "1.656741 VESTS"
}
]
}kormanocorpreceived 0.001 SP curation reward for @dorian-dev / 2025-1582025/09/23 13:47:39
kormanocorpreceived 0.001 SP curation reward for @dorian-dev / 2025-158
2025/09/23 13:47:39
| curator | kormanocorp |
| reward | 1.656741 VESTS |
| comment author | dorian-dev |
| comment permlink | 2025-158 |
| Transaction Info | Block #99354248/Virtual Operation #17 |
View Raw JSON Data
{
"trx_id": "0000000000000000000000000000000000000000",
"block": 99354248,
"trx_in_block": 4294967295,
"op_in_trx": 0,
"virtual_op": 17,
"timestamp": "2025-09-23T13:47:39",
"op": [
"curation_reward",
{
"curator": "kormanocorp",
"reward": "1.656741 VESTS",
"comment_author": "dorian-dev",
"comment_permlink": "2025-158"
}
]
}kormanocorpupvoted (100.00%) @dorian-dev / 2025-1582025/09/17 03:56:36
kormanocorpupvoted (100.00%) @dorian-dev / 2025-158
2025/09/17 03:56:36
| voter | kormanocorp |
| author | dorian-dev |
| permlink | 2025-158 |
| weight | 10000 (100.00%) |
| Transaction Info | Block #99170052/Trx 6d08153517462fe2ebb0eebb5d614039eb32f719 |
View Raw JSON Data
{
"trx_id": "6d08153517462fe2ebb0eebb5d614039eb32f719",
"block": 99170052,
"trx_in_block": 0,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2025-09-17T03:56:36",
"op": [
"vote",
{
"voter": "kormanocorp",
"author": "dorian-dev",
"permlink": "2025-158",
"weight": 10000
}
]
}kormanocorpcustom json: notify2025/01/13 08:55:51
kormanocorpcustom json: notify
2025/01/13 08:55:51
| required auths | [] |
| required posting auths | ["kormanocorp"] |
| id | notify |
| json | ["setLastRead",{"date":"2025-01-13T08:55:51"}] |
| Transaction Info | Block #92080895/Trx 6d78873f978a675784746ca85bd2f1e7fe24e6af |
View Raw JSON Data
{
"trx_id": "6d78873f978a675784746ca85bd2f1e7fe24e6af",
"block": 92080895,
"trx_in_block": 2,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2025-01-13T08:55:51",
"op": [
"custom_json",
{
"required_auths": [],
"required_posting_auths": [
"kormanocorp"
],
"id": "notify",
"json": "[\"setLastRead\",{\"date\":\"2025-01-13T08:55:51\"}]"
}
]
}earn.steemsent 0.001 STEEM to @kormanocorp- "Did you know that you can get rewarded for your witness vote? Cast your witness vote on @earn.steem and start to receive STEEM tokens everyday."2023/12/02 17:25:36
earn.steemsent 0.001 STEEM to @kormanocorp- "Did you know that you can get rewarded for your witness vote? Cast your witness vote on @earn.steem and start to receive STEEM tokens everyday."
2023/12/02 17:25:36
| from | earn.steem |
| to | kormanocorp |
| amount | 0.001 STEEM |
| memo | Did you know that you can get rewarded for your witness vote? Cast your witness vote on @earn.steem and start to receive STEEM tokens everyday. |
| Transaction Info | Block #80389799/Trx 1fea7c5147a488d74fa332a15c20d4a60b2e8a27 |
View Raw JSON Data
{
"trx_id": "1fea7c5147a488d74fa332a15c20d4a60b2e8a27",
"block": 80389799,
"trx_in_block": 2,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-12-02T17:25:36",
"op": [
"transfer",
{
"from": "earn.steem",
"to": "kormanocorp",
"amount": "0.001 STEEM",
"memo": "Did you know that you can get rewarded for your witness vote? Cast your witness vote on @earn.steem and start to receive STEEM tokens everyday."
}
]
}kormanocorpclaimed reward balance: 0.051 STEEM, 0.056 SP2023/05/02 01:33:30
kormanocorpclaimed reward balance: 0.051 STEEM, 0.056 SP
2023/05/02 01:33:30
| account | kormanocorp |
| reward steem | 0.051 STEEM |
| reward sbd | 0.000 SBD |
| reward vests | 91.945187 VESTS |
| Transaction Info | Block #74255188/Trx f76445637f6bc1a82b48039b02954379d3c7bc06 |
View Raw JSON Data
{
"trx_id": "f76445637f6bc1a82b48039b02954379d3c7bc06",
"block": 74255188,
"trx_in_block": 10,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-05-02T01:33:30",
"op": [
"claim_reward_balance",
{
"account": "kormanocorp",
"reward_steem": "0.051 STEEM",
"reward_sbd": "0.000 SBD",
"reward_vests": "91.945187 VESTS"
}
]
}kormanocorpreceived 0.051 STEEM, 0.056 SP author reward for @kormanocorp / 3s8drs-rest-api2023/05/02 01:29:42
kormanocorpreceived 0.051 STEEM, 0.056 SP author reward for @kormanocorp / 3s8drs-rest-api
2023/05/02 01:29:42
| author | kormanocorp |
| permlink | 3s8drs-rest-api |
| sbd payout | 0.000 SBD |
| steem payout | 0.051 STEEM |
| vesting payout | 91.945187 VESTS |
| Transaction Info | Block #74255111/Virtual Operation #4 |
View Raw JSON Data
{
"trx_id": "0000000000000000000000000000000000000000",
"block": 74255111,
"trx_in_block": 4294967295,
"op_in_trx": 0,
"virtual_op": 4,
"timestamp": "2023-05-02T01:29:42",
"op": [
"author_reward",
{
"author": "kormanocorp",
"permlink": "3s8drs-rest-api",
"sbd_payout": "0.000 SBD",
"steem_payout": "0.051 STEEM",
"vesting_payout": "91.945187 VESTS"
}
]
}kormanocorpclaimed reward balance: 0.085 STEEM, 0.092 SP2023/05/01 04:18:30
kormanocorpclaimed reward balance: 0.085 STEEM, 0.092 SP
2023/05/01 04:18:30
| account | kormanocorp |
| reward steem | 0.085 STEEM |
| reward sbd | 0.000 SBD |
| reward vests | 150.305308 VESTS |
| Transaction Info | Block #74229803/Trx 1e3e8e096b2debca05abff9f41309a96886dfb9a |
View Raw JSON Data
{
"trx_id": "1e3e8e096b2debca05abff9f41309a96886dfb9a",
"block": 74229803,
"trx_in_block": 5,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-05-01T04:18:30",
"op": [
"claim_reward_balance",
{
"account": "kormanocorp",
"reward_steem": "0.085 STEEM",
"reward_sbd": "0.000 SBD",
"reward_vests": "150.305308 VESTS"
}
]
}kormanocorpreceived 0.085 STEEM, 0.092 SP author reward for @kormanocorp / 3qj1d92023/05/01 04:10:57
kormanocorpreceived 0.085 STEEM, 0.092 SP author reward for @kormanocorp / 3qj1d9
2023/05/01 04:10:57
| author | kormanocorp |
| permlink | 3qj1d9 |
| sbd payout | 0.000 SBD |
| steem payout | 0.085 STEEM |
| vesting payout | 150.305308 VESTS |
| Transaction Info | Block #74229651/Virtual Operation #6 |
View Raw JSON Data
{
"trx_id": "0000000000000000000000000000000000000000",
"block": 74229651,
"trx_in_block": 4294967295,
"op_in_trx": 0,
"virtual_op": 6,
"timestamp": "2023-05-01T04:10:57",
"op": [
"author_reward",
{
"author": "kormanocorp",
"permlink": "3qj1d9",
"sbd_payout": "0.000 SBD",
"steem_payout": "0.085 STEEM",
"vesting_payout": "150.305308 VESTS"
}
]
}kormanocorpclaimed reward balance: 0.049 STEEM, 0.053 SP2023/04/28 06:48:30
kormanocorpclaimed reward balance: 0.049 STEEM, 0.053 SP
2023/04/28 06:48:30
| account | kormanocorp |
| reward steem | 0.049 STEEM |
| reward sbd | 0.000 SBD |
| reward vests | 86.665315 VESTS |
| Transaction Info | Block #74149375/Trx 1bba9181f2496254938bac751f637e83623af1cd |
View Raw JSON Data
{
"trx_id": "1bba9181f2496254938bac751f637e83623af1cd",
"block": 74149375,
"trx_in_block": 2,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-04-28T06:48:30",
"op": [
"claim_reward_balance",
{
"account": "kormanocorp",
"reward_steem": "0.049 STEEM",
"reward_sbd": "0.000 SBD",
"reward_vests": "86.665315 VESTS"
}
]
}kormanocorpreceived 0.049 STEEM, 0.053 SP author reward for @kormanocorp / 4eals62023/04/28 06:41:24
kormanocorpreceived 0.049 STEEM, 0.053 SP author reward for @kormanocorp / 4eals6
2023/04/28 06:41:24
| author | kormanocorp |
| permlink | 4eals6 |
| sbd payout | 0.000 SBD |
| steem payout | 0.049 STEEM |
| vesting payout | 86.665315 VESTS |
| Transaction Info | Block #74149239/Virtual Operation #3 |
View Raw JSON Data
{
"trx_id": "0000000000000000000000000000000000000000",
"block": 74149239,
"trx_in_block": 4294967295,
"op_in_trx": 0,
"virtual_op": 3,
"timestamp": "2023-04-28T06:41:24",
"op": [
"author_reward",
{
"author": "kormanocorp",
"permlink": "4eals6",
"sbd_payout": "0.000 SBD",
"steem_payout": "0.049 STEEM",
"vesting_payout": "86.665315 VESTS"
}
]
}kormanocorpclaimed reward balance: 0.051 STEEM, 0.055 SP2023/04/27 00:03:30
kormanocorpclaimed reward balance: 0.051 STEEM, 0.055 SP
2023/04/27 00:03:30
| account | kormanocorp |
| reward steem | 0.051 STEEM |
| reward sbd | 0.000 SBD |
| reward vests | 90.211540 VESTS |
| Transaction Info | Block #74112672/Trx 74125d5140acc729f5f79da8619b29d63c94116e |
View Raw JSON Data
{
"trx_id": "74125d5140acc729f5f79da8619b29d63c94116e",
"block": 74112672,
"trx_in_block": 3,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-04-27T00:03:30",
"op": [
"claim_reward_balance",
{
"account": "kormanocorp",
"reward_steem": "0.051 STEEM",
"reward_sbd": "0.000 SBD",
"reward_vests": "90.211540 VESTS"
}
]
}kormanocorpreceived 0.051 STEEM, 0.055 SP author reward for @kormanocorp / 4og2em2023/04/27 00:01:00
kormanocorpreceived 0.051 STEEM, 0.055 SP author reward for @kormanocorp / 4og2em
2023/04/27 00:01:00
| author | kormanocorp |
| permlink | 4og2em |
| sbd payout | 0.000 SBD |
| steem payout | 0.051 STEEM |
| vesting payout | 90.211540 VESTS |
| Transaction Info | Block #74112621/Virtual Operation #4 |
View Raw JSON Data
{
"trx_id": "0000000000000000000000000000000000000000",
"block": 74112621,
"trx_in_block": 4294967295,
"op_in_trx": 0,
"virtual_op": 4,
"timestamp": "2023-04-27T00:01:00",
"op": [
"author_reward",
{
"author": "kormanocorp",
"permlink": "4og2em",
"sbd_payout": "0.000 SBD",
"steem_payout": "0.051 STEEM",
"vesting_payout": "90.211540 VESTS"
}
]
}kormanocorpclaimed reward balance: 0.051 STEEM, 0.055 SP2023/04/26 07:33:33
kormanocorpclaimed reward balance: 0.051 STEEM, 0.055 SP
2023/04/26 07:33:33
| account | kormanocorp |
| reward steem | 0.051 STEEM |
| reward sbd | 0.000 SBD |
| reward vests | 90.216308 VESTS |
| Transaction Info | Block #74092964/Trx ce6fa1326e634c8c8740f64e42258bc98ae1af42 |
View Raw JSON Data
{
"trx_id": "ce6fa1326e634c8c8740f64e42258bc98ae1af42",
"block": 74092964,
"trx_in_block": 3,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-04-26T07:33:33",
"op": [
"claim_reward_balance",
{
"account": "kormanocorp",
"reward_steem": "0.051 STEEM",
"reward_sbd": "0.000 SBD",
"reward_vests": "90.216308 VESTS"
}
]
}kormanocorpreceived 0.051 STEEM, 0.055 SP author reward for @kormanocorp / api-gateway-bff-backend-for-frontend2023/04/26 07:32:06
kormanocorpreceived 0.051 STEEM, 0.055 SP author reward for @kormanocorp / api-gateway-bff-backend-for-frontend
2023/04/26 07:32:06
| author | kormanocorp |
| permlink | api-gateway-bff-backend-for-frontend |
| sbd payout | 0.000 SBD |
| steem payout | 0.051 STEEM |
| vesting payout | 90.216308 VESTS |
| Transaction Info | Block #74092934/Virtual Operation #4 |
View Raw JSON Data
{
"trx_id": "0000000000000000000000000000000000000000",
"block": 74092934,
"trx_in_block": 4294967295,
"op_in_trx": 0,
"virtual_op": 4,
"timestamp": "2023-04-26T07:32:06",
"op": [
"author_reward",
{
"author": "kormanocorp",
"permlink": "api-gateway-bff-backend-for-frontend",
"sbd_payout": "0.000 SBD",
"steem_payout": "0.051 STEEM",
"vesting_payout": "90.216308 VESTS"
}
]
}kr-devupvoted (100.00%) @kormanocorp / 3s8drs-rest-api2023/04/25 01:34:48
kr-devupvoted (100.00%) @kormanocorp / 3s8drs-rest-api
2023/04/25 01:34:48
| voter | kr-dev |
| author | kormanocorp |
| permlink | 3s8drs-rest-api |
| weight | 10000 (100.00%) |
| Transaction Info | Block #74057152/Trx e3399a621140d762c0f11a26a76c804be582b39a |
View Raw JSON Data
{
"trx_id": "e3399a621140d762c0f11a26a76c804be582b39a",
"block": 74057152,
"trx_in_block": 0,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-04-25T01:34:48",
"op": [
"vote",
{
"voter": "kr-dev",
"author": "kormanocorp",
"permlink": "3s8drs-rest-api",
"weight": 10000
}
]
}anpigonupvoted (100.00%) @kormanocorp / 3s8drs-rest-api2023/04/25 01:34:21
anpigonupvoted (100.00%) @kormanocorp / 3s8drs-rest-api
2023/04/25 01:34:21
| voter | anpigon |
| author | kormanocorp |
| permlink | 3s8drs-rest-api |
| weight | 10000 (100.00%) |
| Transaction Info | Block #74057143/Trx b64ecff05c66f3411ecb56f4ac94dd266eeaeffa |
View Raw JSON Data
{
"trx_id": "b64ecff05c66f3411ecb56f4ac94dd266eeaeffa",
"block": 74057143,
"trx_in_block": 0,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-04-25T01:34:21",
"op": [
"vote",
{
"voter": "anpigon",
"author": "kormanocorp",
"permlink": "3s8drs-rest-api",
"weight": 10000
}
]
}kr-dev.cu1replied to @kormanocorp / adreply-16823861970872023/04/25 01:29:57
kr-dev.cu1replied to @kormanocorp / adreply-1682386197087
2023/04/25 01:29:57
| parent author | kormanocorp |
| parent permlink | 3s8drs-rest-api |
| author | kr-dev.cu1 |
| permlink | adreply-1682386197087 |
| title | |
| body | [광고] [STEEM 개발자 커뮤니티에 참여](/hive-137029/@kr-dev/x3v6n) 하시면, 다양한 혜택을 받을 수 있습니다. |
| json metadata | {"tags":["kr-dev"],"image":["https://lh4.googleusercontent.com/kGsBpLXavskkjVN-zHSeMhctiYqHHIWIrPHMk98diNJBi0w-b07XMnb0W8_umEaQlz07bs-TfuM3RLxQwfg4hy6JsJlrJPk3bUMWgYstthHYBz2bddOaMJJZZgJ1etW32MZ-2wNy","https://lh4.googleusercontent.com/lDAvcIA_MCAHvo6JEjD7Lj1De7agI3EnG7P3GQMCtm7UvknY7SPY0tZeCrURICMQQwmymd3a1lxtNwwY0tNqIi6PbrgUGtAVv-HZR_yjm3UmOZaEl8Owes8cefRKnSyC538mG2ba","https://lh6.googleusercontent.com/ArmW2xiK3tg-Ft02u98Ts7vBAlHdK6v_MVSsy7UO4ZEOoTDjK927DoFicvSvf27tlcO1Ql2MugxXRwRH__8nW-FWwG0rW9FGG1FUV5papwVwRHKhsMOd746RMeEUzk_DD3rdLHiK","https://lh3.googleusercontent.com/YPx6E9ZiwCkCxlYq-6y71jao086YzXMictI03KIK-x84jmYu9qUfq9-9nVYqtt-CUOuK8Sb00vnmZ-IFS8i3tZDnaXiYqd1aVFQIO9Kna7lJ8s4u4D6W7h2-9rP_llUxYtBtZ0-n"],"links":["https://stoplight.io/api-design-guide/basics/","https://blog.stoplight.io/api-design-patterns-for-rest-web-services?utm_source=pocket_saves#http-methods-and-status-codes","https://blog.stoplight.io/crud-api-design","https://stripe.com/blog/idempotency","https://tools.ietf.org/html/rfc7234#page-24","https://stoplight.io/mock-api-guide/basics/","https://blog.stoplight.io/rest-api-standards-do-they-even-exist","https://blog.stoplight.io/designing-apis-for-microservices","https://blog.stoplight.io/open-banking-guide","https://stoplight.io/openapi/","https://stoplight.io/api-documentation/","https://stoplight.io/api-mocking/","https://stoplight.io/studio/","https://stoplight.io/api-style-guides-guidelines-and-best-practices/","https://blog.stoplight.io/introducing-spectral","https://stoplight.io/","https://blog.stoplight.io/rest-api-security","https://blog.stoplight.io/api-design-patterns-for-rest-web-services?utm_source=pocket_saves"],"app":"steemit/0.2","format":"markdown"} |
| Transaction Info | Block #74057055/Trx fb1aab776c7a46f9be49d7c667f585b6850f8950 |
View Raw JSON Data
{
"trx_id": "fb1aab776c7a46f9be49d7c667f585b6850f8950",
"block": 74057055,
"trx_in_block": 1,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-04-25T01:29:57",
"op": [
"comment",
{
"parent_author": "kormanocorp",
"parent_permlink": "3s8drs-rest-api",
"author": "kr-dev.cu1",
"permlink": "adreply-1682386197087",
"title": "",
"body": "[광고] [STEEM 개발자 커뮤니티에 참여](/hive-137029/@kr-dev/x3v6n) 하시면, 다양한 혜택을 받을 수 있습니다.",
"json_metadata": "{\"tags\":[\"kr-dev\"],\"image\":[\"https://lh4.googleusercontent.com/kGsBpLXavskkjVN-zHSeMhctiYqHHIWIrPHMk98diNJBi0w-b07XMnb0W8_umEaQlz07bs-TfuM3RLxQwfg4hy6JsJlrJPk3bUMWgYstthHYBz2bddOaMJJZZgJ1etW32MZ-2wNy\",\"https://lh4.googleusercontent.com/lDAvcIA_MCAHvo6JEjD7Lj1De7agI3EnG7P3GQMCtm7UvknY7SPY0tZeCrURICMQQwmymd3a1lxtNwwY0tNqIi6PbrgUGtAVv-HZR_yjm3UmOZaEl8Owes8cefRKnSyC538mG2ba\",\"https://lh6.googleusercontent.com/ArmW2xiK3tg-Ft02u98Ts7vBAlHdK6v_MVSsy7UO4ZEOoTDjK927DoFicvSvf27tlcO1Ql2MugxXRwRH__8nW-FWwG0rW9FGG1FUV5papwVwRHKhsMOd746RMeEUzk_DD3rdLHiK\",\"https://lh3.googleusercontent.com/YPx6E9ZiwCkCxlYq-6y71jao086YzXMictI03KIK-x84jmYu9qUfq9-9nVYqtt-CUOuK8Sb00vnmZ-IFS8i3tZDnaXiYqd1aVFQIO9Kna7lJ8s4u4D6W7h2-9rP_llUxYtBtZ0-n\"],\"links\":[\"https://stoplight.io/api-design-guide/basics/\",\"https://blog.stoplight.io/api-design-patterns-for-rest-web-services?utm_source=pocket_saves#http-methods-and-status-codes\",\"https://blog.stoplight.io/crud-api-design\",\"https://stripe.com/blog/idempotency\",\"https://tools.ietf.org/html/rfc7234#page-24\",\"https://stoplight.io/mock-api-guide/basics/\",\"https://blog.stoplight.io/rest-api-standards-do-they-even-exist\",\"https://blog.stoplight.io/designing-apis-for-microservices\",\"https://blog.stoplight.io/open-banking-guide\",\"https://stoplight.io/openapi/\",\"https://stoplight.io/api-documentation/\",\"https://stoplight.io/api-mocking/\",\"https://stoplight.io/studio/\",\"https://stoplight.io/api-style-guides-guidelines-and-best-practices/\",\"https://blog.stoplight.io/introducing-spectral\",\"https://stoplight.io/\",\"https://blog.stoplight.io/rest-api-security\",\"https://blog.stoplight.io/api-design-patterns-for-rest-web-services?utm_source=pocket_saves\"],\"app\":\"steemit/0.2\",\"format\":\"markdown\"}"
}
]
}kormanocorppublished a new post: 3s8drs-rest-api2023/04/25 01:29:42
kormanocorppublished a new post: 3s8drs-rest-api
2023/04/25 01:29:42
| parent author | |
| parent permlink | kr-dev |
| author | kormanocorp |
| permlink | 3s8drs-rest-api |
| title | REST용 API 디자인 패턴 |
| body | REST는 몇 달 후면 22세가 됩니다. Roy Fielding의 논문에 요약된 API 아키텍처 및 권장 사항 외에도 이제 20년 동안 실용적으로 적용할 수 있습니다. [API 프로젝트를 설계할 때](https://stoplight.io/api-design-guide/basics/) 수많은 다른 사람들이 이미 구현한 웹 서비스에 대한 REST 모범 사례 및 지침을 기반으로 구축하는 것이 좋습니다. 이 게시물은 사용자가 RESTful API가 무엇인지, 그리고 여러 범주에서 가장 일반적인 REST API 디자인 패턴, 개발 및 원칙을 배우는 데 도움이 됩니다. 새로 시작하는 대신 수천 개의 성공적인 API 회사의 API 지침 기반을 기반으로 구축하십시오. RESTful API를 구축해 보겠습니다. ## [🔗](https://blog.stoplight.io/api-design-patterns-for-rest-web-services?utm_source=pocket_saves#http-methods-and-status-codes)HTTP 메서드 및 상태 코드 REST API를 정의해 봅시다. RESTful API의 정의는 HTTP 프로토콜을 사용할 필요가 없음을 의미합니다. 그러나 이 둘은 함께 개발되었으며 거의 모든 RESTful API 코드는 HTTP에 의존합니다. 이러한 이유로 HTTP에서 이미 잘 정의된 기본 제공 메서드 및 상태 코드를 중심으로 API를 구성하는 것이 좋습니다. 다음은 HTTP REST API를 설계, 개발 및 생성하는 방법입니다. REST API 설계를 위해 각 HTTP 요청에는 각 호출에 대한 많은 컨텍스트를 제공하는 "HTTP 동사"라고도 하는 메서드가 포함됩니다. 가장 일반적인 HTTP 메서드는 다음과 같습니다. - **GET** : API에서 데이터 읽기 - **POST** : API에 _새 데이터_ 추가 - **PUT** : API로 _기존 데이터 업데이트_ - **PATCH** : API로 _기존 데이터의 하위 집합을 업데이트합니다._ - **DELETE** : API에서 데이터(일반적으로 단일 리소스)를 제거합니다. 이 모든 것을 자세히 논의하지는 않겠지만 CRUD와 REST에 대한 자세한 내용은 [CRUD API 디자인](https://blog.stoplight.io/crud-api-design) 에 대한 게시물을 확인하십시오 . API를 설계할 때 RESTful API URL에 목적을 추가하는 대신 호출의 기본 목적을 표현하기 위해 이러한 메서드에 의존하고 싶을 것입니다. 우리는 그것에 대해 조금 더 알게 될 것입니다. 이러한 메서드가 클라이언트에서 서버로 요청 컨텍스트를 제공하는 것처럼 HTTP 상태 코드는 응답을 반대 방향으로 설명하는 데 도움이 됩니다. 몇 가지 일반적인 HTTP 상태 코드는 다음과 같습니다. - **200** : 성공적인 요청, 종종 GET - **201** : 생성 후 성공적인 요청, 일반적으로 POST - **204** : 반환된 콘텐츠 없이 성공적인 요청, 일반적으로 PUT 또는 PATCH - **301** : 다른 끝점으로 영구적으로 리디렉션 - **400** : 잘못된 요청(클라이언트가 요청을 수정해야 함) - **401** : 승인되지 않음, 자격 증명이 인식되지 않음 - **403** : 금지됨, 자격 증명이 허용되지만 권한이 없음 - **404** : 찾을 수 없음, 리소스가 존재하지 않음 - **410** : 사라짐, 리소스가 이전에 존재했지만 지금은 없음 - **429** : 속도 제한에 사용되는 요청이 너무 많으며 재시도 헤더를 포함해야 합니다. - **500** : 서버 오류, 일반적이며 대신 다른 500 수준 오류를 살펴볼 가치가 있습니다. - **503** : 서비스를 사용할 수 없음, 재시도 헤더가 유용한 다른 서비스 고려해야 할 더 많은 HTTP 상태 코드와 메서드가 있지만 위의 목록은 대부분의 API에 대해 잘 이해할 수 있도록 합니다. ## 친근하고 일반적인 API 엔드포인트 이름 사용 웹 사이트의 API 끝점을 어떻게 찾고 결정합니까? REST API를 사용하는 일반적인 디자인 패턴은 리소스를 기반으로 엔드포인트를 구축하는 것입니다. 이들은 HTTP 메서드 동사에 대한 "명사"입니다. 이러한 이름이 설명적이면 API 디자인을 훨씬 더 쉽게 이해할 수 있습니다. API 디자인 예제의 경우 요리책 API에서 작업하는 경우 다음 API 엔드포인트 예제의 코드 예제는 /recipes/일 수 있습니다. 새 레시피를 추가하면 이를 엔드포인트에 POST합니다. 목록을 가져오려면 동일한 끝점에서 GET 메서드를 사용합니다. 특정 레시피를 검색하려면 URL의 식별자로 호출할 수 있습니다. /recipes/42 친숙한 REST 끝점 이름으로 특별히 피해야 할 한 가지는 요청에 대한 새로운 정보를 전달하지 않기 때문에 작업을 설명하는 것입니다. 예를 들어 엔드포인트 내의 동사(예: /getRecipes/)는 해당 컨텍스트를 제공하기 위해 HTTP 메서드에 의존하는 것과 반대로 실행됩니다. [CRUD API 설계 권장 사항](https://blog.stoplight.io/crud-api-design) 게시물 은 복수형 및 버전 관리와 같은 인기 있는 주제를 포함하여 더 자세히 설명합니다. ## GET 대 POST API 대량 작업 RESTful API를 설계할 때 호출의 기본 목적을 표현하기 위해 HTTP 메서드 및 모범 사례에 의존하고 싶을 것입니다. 이러한 이유로 단순히 데이터를 검색하기 위해 POST를 사용하고 싶지는 않습니다. GET이 데이터를 생성하거나 제거하는 것도 원하지 않습니다. 사용 사례를 검토하여 각 사용 시기를 결정해야 합니다. 다음은 귀하의 결정에 영향을 미치는 몇 가지 요소입니다. - **GET** 요청을 캐시할 수 있습니다. - **GET 요청은** [멱등적](https://stripe.com/blog/idempotency) 입니다 (동일한 결과를 보장하면서 여러 번 호출할 수 있음). - **GET** 요청은 민감한 데이터를 처리할 때 사용해서는 안 됩니다. - **GET** 요청에는 길이 제한이 있습니다. - **GET** 요청은 데이터 검색에만 사용해야 합니다. - **POST** 요청은 캐시되지 않습니다(헤더에 지정되지 않은 경우). - **POST** 요청은 멱등성이 아닙니다. - **POST** 요청에는 데이터 길이에 대한 제한이 없습니다. 방법을 현명하게 선택하면 경로를 간결하게 유지하고 기본 RESTful API 관행을 따릅니다. 간단한 예를 살펴보겠습니다. 기본 CRUD 기능(만들기, 읽기, 업데이트, 삭제)을 구현하는 경로가 있다고 가정하면 다음 경로로 끝납니다. - \[POST\] /api/recipe - 레시피 생성 - \[GET\] /api/recipe - 레시피 나열 - \[GET\] /api/recipe/:id - ID로 레시피 가져오기 - \[PUT\] /api/recipe/:id - ID로 레시피 업데이트 - \[DELETE\] /api/recipe/:id - ID별로 레시피 삭제 - \[DELETE\] /api/recipe - 대량 삭제 레시피 이 예에서는 실제로 "/api/recipes" 및 "/api/recipe/:id" 2개의 경로만 있습니다. POST만 사용한다면 6개의 다른 경로가 생깁니다. ## 성능 향상을 위한 캐시 데이터 캐싱은 불필요한 서버 이동을 부분적으로 제거합니다. 각각의 새 요청에 대한 쿼리를 보내는 대신 로컬 메모리에서 데이터를 반환하면 앱의 성능을 향상시킬 수 있습니다. **GET** 요청은 기본적으로 캐시 가능하지만 **POST** 요청의 경우 헤더에 캐시 요구 사항을 지정해야 합니다. 그러나 캐싱은 클라이언트의 브라우저에서 오래된 데이터로 이어질 수 있습니다. **POST** 헤더 에서 이를 처리하는 방법은 다음과 같습니다 . ### 만료 이 경우 캐시된 버전에 대한 절대 만료 시간을 지정합니다. 지정된 시간을 초과하는 모든 항목은 오래된 것으로 간주되며 원본 서버로 업데이트해야 합니다. 최대 1년 후의 시간을 지정할 수 있습니다.  ### 캐시 제어 이 옵션을 사용할 때 max-age, must-revalidate 또는 no-transform과 같은 특정 [지시문을](https://tools.ietf.org/html/rfc7234#page-24) 설정할 수 있습니다 .  ### 마지막 수정 이 옵션을 사용하면 응답 헤더를 사용하여 캐싱 요구 사항을 결정합니다. 응답의 날짜 값은 초기 응답이 생성된 시기를 지정합니다. Last-Modified 날짜는 리소스와 연결된 응답이 마지막으로 변경된 날짜를 지정합니다. 최종 수정 날짜는 날짜 값보다 작을 수 없습니다. ## API 매개변수를 사용한 향후 사용 사례 계획 순진하거나 단순한 API 설계는 위의 모든 지침을 따를 수 있지만 여전히 개발자에게 필요한 사용 사례를 지원하지 않습니다. API가 사용되는 방식을 철저히 이해하고 [모의 API 서버](https://stoplight.io/mock-api-guide/basics/) 와 같은 공동작업자로부터 피드백을 받는 것이 중요합니다 . 종종 API가 구축된 후 사용 사례가 발견되면 엔지니어는 이러한 발굴된 요구 사항을 지원하기 위해 새로운 엔드포인트를 생성합니다. 예를 들어 요리책 API는 특정 카테고리의 레시피만 반환해야 하거나 준비 시간이 가장 짧은 레시피를 표시해야 할 수 있습니다. 중복 엔드포인트를 생성하는 대신 처음부터 스마트 매개변수를 계획하십시오. API에 대해 고려해야 할 세 가지 일반적인 유형의 매개변수가 있습니다. - **필터링** : 필드 나이를 매개변수로 사용하여 필터와 일치하는 결과만 반환합니다. 예를 들어: GET /사용자?나이=30 - **페이지 매김** : 모든 것을 제공하여 클라이언트와 서버에 과부하를 주지 마십시오. 대신 제한을 설정하고 응답에 이전 및 다음 링크를 제공하십시오. 예: GET /users?page=3&results\_per\_page=20 - **정렬** : 정렬 방법을 제공하거나 일부 사용 사례에서는 여전히 필요한 것을 찾기 위해 모든 결과를 페이징해야 합니다. 예: GET /users?sort\_by=first\_name&order=asc 이 세 가지 접근 방식을 함께 사용하여 매우 구체적인 쿼리를 지원할 수 있습니다. 사용 사례를 이해하면 매개변수의 복잡성을 결정하는 데 도움이 됩니다. ## 기존 대회에서 차용 이 게시물은 전반적인 API 디자인 패턴을 다루기 위해 최선을 다하고 있지만 업계 또는 특정 기능에 특정한 표준 및 규칙을 살펴보고 싶을 것입니다. 완전히 고유한 API를 구축하는 사람은 거의 없기 때문에 다른 사람에게서 배울 점이 많습니다. [많은 API 표준이](https://blog.stoplight.io/rest-api-standards-do-they-even-exist) REST API를 중심으로 구축되었습니다. 예를 들어 API에 대한 인증을 구현할 때 새로운 길을 개척하지 마십시오. 사용자 관련 데이터를 제공할 때 잘 알려진 OAuth 경로를 포함하여 API 인증 패턴에 대한 많은 옵션이 있습니다. API 헤더에 대한 표준과 JSON 및 XML과 같은 데이터 형식 및 모델에 대한 몇 가지를 찾을 수 있습니다. 고유한 고려 사항이 있는 [마이크로서비스 API를 설계](https://blog.stoplight.io/designing-apis-for-microservices) 할 수 있습니다 . 이 게시물에서 다루는 모든 내용이 여전히 적용될 가능성이 높지만 마이크로서비스를 설계할 때 더욱 주의를 기울여야 합니다. 각각은 그 자체로 의미가 있어야 하지만 조합(느슨한 결합)의 이점을 누릴 수 있습니다. 반면 [오픈 뱅킹 API는](https://blog.stoplight.io/open-banking-guide) 자체 처리가 필요합니다. 유럽 표준은 가장 성숙했으며 이러한 규정을 기반으로 하는 일련의 디자인 패턴을 가지고 있습니다. 귀하의 산업에는 고유한 표준 또는 규칙이 있을 수 있습니다. 은행 규정만큼 엄격하지 않더라도 개발자에게 이미 친숙한 패턴에 대해 적절한 고려를 할 가치가 있습니다. ## OpenAPI 정의가 있는 문서 [API를 설계할 때 OpenAPI](https://stoplight.io/openapi/) 정의를 정보 소스로 유지하는 것이 매우 유용합니다 . 이전 Swagger 파일의 차세대 형식인 이 형식은 엔드포인트, 요청 데이터, 응답, 오류 코드 등을 설명합니다. 또한 API 수명 주기 전반에 걸쳐 도구를 사용하여 자동화하는 데 사용할 수 있습니다.  아마도 OpenAPI 문서의 가장 일반적인 용도는 [API 문서](https://stoplight.io/api-documentation/) , 특히 API 참조를 생성하는 것입니다. 형식은 API를 호출할 수 있는 방법을 설명하므로 개발자가 API와 통합하는 데 필요한 모든 정보가 포함됩니다. 또한 일부 API 참조에는 오류 코드와 같은 필수 세부 정보가 포함되어 있지 않으므로 OpenAPI는 정확한 문서화를 권장합니다. 또한 API가 변경될 때마다 새 문서를 생성할 수 있으므로 항상 최신 상태를 유지할 수 있습니다. 또한 OpenAPI 정의를 사용하여 [모의 HTTP 서버를 생성](https://stoplight.io/api-mocking/) 할 수 있습니다 . 이를 통해 코드를 작성하기 전에 API를 시험해 볼 수 있습니다. 초기 피드백 또는 온라인 REST API 클라이언트의 요청 유효성 검사를 위해 팀 간에 인터페이스를 순환합니다. 이는 YAML 또는 JSON을 사용하여 OpenAPI 정의 파일을 생성할 수 있는 기계 판독 가능 API 정의의 두 가지 잠재적 용도입니다. 또는 시각적 OpenAPI 편집기를 사용하여 훨씬 빠르게 만들 수 있습니다. [Stoplight Studio는](https://stoplight.io/studio/) 모든 git 저장소에서 기존 OpenAPI 파일을 읽을 수 있으며 아름다운 편집 환경 내에서 편집하거나 처음부터 시작할 수 있습니다. ## 일관성을 위해 스타일 가이드 사용 일부 디자인 패턴은 기본 설정의 문제입니다. 이상적으로는 API를 생성할 때마다 다시 방문하지 않고 조직의 접근 방식을 한 번에 체계화할 수 있습니다. 스타일 [가이드는](https://stoplight.io/api-style-guides-guidelines-and-best-practices/) API 디자인과 동일한 페이지에 회사를 유지할 수 있습니다. API 간에 일관성을 유지하는 것 외에도 단일 API 내에서 일관성을 유지하는 것이 훨씬 더 중요합니다. 일부 조직에서는 서면 API 스타일 가이드를 작성합니다. 인트라넷 내에서 쉽게 액세스할 수 있는 문서는 모든 사람이 이미 채택한 디자인 패턴을 이해하는 데 도움이 됩니다. 그러나 프로그래밍 방식으로 스타일 가이드를 적용하여 더 멀리 갈 수 있습니다. [오픈 소스 린터](https://blog.stoplight.io/introducing-spectral) 와 같은 도구를 사용하여 OpenAPI 문서에 대한 규칙 세트를 정의할 수 있습니다. API 스타일 가이드를 자동화하면 리소스 및 필드 이름, 대문자 형식, 구두점 사용 방법, 버전 관리 등 API 특성을 얼마든지 찾아볼 수 있습니다. 서면이든 프로그래밍 방식이든 스타일 가이드는 여기에서 다루는 디자인 패턴에 대한 자신만의 가이드라인이 됩니다. 조직에서 HTTP 메서드를 올바르게 사용하고, 적절한 상태 코드를 반환하고, 친숙한 엔드포인트 이름을 구현하고, 스마트 매개변수를 사용하고, 이미 식별한 기존 규칙에서 차용하도록 돕습니다. [환상적인 API를 만들고 API 디자인 아키텍처를 더 잘 이해할 준비가 되었으니 Stoplight의 API 디자인 관리 플랫폼](https://stoplight.io/) 에서 세계 최고의 API 우선 회사에 합류하세요 . API RESTful 웹 서비스 예제 및 API REST 빌드의 모범 사례에 대한 자세한 내용은 [REST에 대한 이 블로그를](https://blog.stoplight.io/rest-api-security) 확인하여 REST API를 빌드하는 방법에 대해 자세히 알아보세요. 출처 : https://blog.stoplight.io/api-design-patterns-for-rest-web-services?utm_source=pocket_saves |
| json metadata | {"tags":["kr-dev"],"image":["https://lh4.googleusercontent.com/kGsBpLXavskkjVN-zHSeMhctiYqHHIWIrPHMk98diNJBi0w-b07XMnb0W8_umEaQlz07bs-TfuM3RLxQwfg4hy6JsJlrJPk3bUMWgYstthHYBz2bddOaMJJZZgJ1etW32MZ-2wNy","https://lh4.googleusercontent.com/lDAvcIA_MCAHvo6JEjD7Lj1De7agI3EnG7P3GQMCtm7UvknY7SPY0tZeCrURICMQQwmymd3a1lxtNwwY0tNqIi6PbrgUGtAVv-HZR_yjm3UmOZaEl8Owes8cefRKnSyC538mG2ba","https://lh6.googleusercontent.com/ArmW2xiK3tg-Ft02u98Ts7vBAlHdK6v_MVSsy7UO4ZEOoTDjK927DoFicvSvf27tlcO1Ql2MugxXRwRH__8nW-FWwG0rW9FGG1FUV5papwVwRHKhsMOd746RMeEUzk_DD3rdLHiK","https://lh3.googleusercontent.com/YPx6E9ZiwCkCxlYq-6y71jao086YzXMictI03KIK-x84jmYu9qUfq9-9nVYqtt-CUOuK8Sb00vnmZ-IFS8i3tZDnaXiYqd1aVFQIO9Kna7lJ8s4u4D6W7h2-9rP_llUxYtBtZ0-n"],"links":["https://stoplight.io/api-design-guide/basics/","https://blog.stoplight.io/api-design-patterns-for-rest-web-services?utm_source=pocket_saves#http-methods-and-status-codes","https://blog.stoplight.io/crud-api-design","https://stripe.com/blog/idempotency","https://tools.ietf.org/html/rfc7234#page-24","https://stoplight.io/mock-api-guide/basics/","https://blog.stoplight.io/rest-api-standards-do-they-even-exist","https://blog.stoplight.io/designing-apis-for-microservices","https://blog.stoplight.io/open-banking-guide","https://stoplight.io/openapi/","https://stoplight.io/api-documentation/","https://stoplight.io/api-mocking/","https://stoplight.io/studio/","https://stoplight.io/api-style-guides-guidelines-and-best-practices/","https://blog.stoplight.io/introducing-spectral","https://stoplight.io/","https://blog.stoplight.io/rest-api-security","https://blog.stoplight.io/api-design-patterns-for-rest-web-services?utm_source=pocket_saves"],"app":"steemit/0.2","format":"markdown"} |
| Transaction Info | Block #74057050/Trx f0bdbd10cea84bbed15d57aeba4a45aeba6abb56 |
View Raw JSON Data
{
"trx_id": "f0bdbd10cea84bbed15d57aeba4a45aeba6abb56",
"block": 74057050,
"trx_in_block": 2,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-04-25T01:29:42",
"op": [
"comment",
{
"parent_author": "",
"parent_permlink": "kr-dev",
"author": "kormanocorp",
"permlink": "3s8drs-rest-api",
"title": "REST용 API 디자인 패턴",
"body": "REST는 몇 달 후면 22세가 됩니다. Roy Fielding의 논문에 요약된 API 아키텍처 및 권장 사항 외에도 이제 20년 동안 실용적으로 적용할 수 있습니다. [API 프로젝트를 설계할 때](https://stoplight.io/api-design-guide/basics/) 수많은 다른 사람들이 이미 구현한 웹 서비스에 대한 REST 모범 사례 및 지침을 기반으로 구축하는 것이 좋습니다.\n\n이 게시물은 사용자가 RESTful API가 무엇인지, 그리고 여러 범주에서 가장 일반적인 REST API 디자인 패턴, 개발 및 원칙을 배우는 데 도움이 됩니다. 새로 시작하는 대신 수천 개의 성공적인 API 회사의 API 지침 기반을 기반으로 구축하십시오. RESTful API를 구축해 보겠습니다.\n\n## [🔗](https://blog.stoplight.io/api-design-patterns-for-rest-web-services?utm_source=pocket_saves#http-methods-and-status-codes)HTTP 메서드 및 상태 코드\n\nREST API를 정의해 봅시다. RESTful API의 정의는 HTTP 프로토콜을 사용할 필요가 없음을 의미합니다. 그러나 이 둘은 함께 개발되었으며 거의 모든 RESTful API 코드는 HTTP에 의존합니다. 이러한 이유로 HTTP에서 이미 잘 정의된 기본 제공 메서드 및 상태 코드를 중심으로 API를 구성하는 것이 좋습니다. 다음은 HTTP REST API를 설계, 개발 및 생성하는 방법입니다.\n\nREST API 설계를 위해 각 HTTP 요청에는 각 호출에 대한 많은 컨텍스트를 제공하는 \"HTTP 동사\"라고도 하는 메서드가 포함됩니다. 가장 일반적인 HTTP 메서드는 다음과 같습니다.\n\n- **GET** : API에서 데이터 읽기\n- **POST** : API에 _새 데이터_ 추가\n- **PUT** : API로 _기존 데이터 업데이트_\n- **PATCH** : API로 _기존 데이터의 하위 집합을 업데이트합니다._\n- **DELETE** : API에서 데이터(일반적으로 단일 리소스)를 제거합니다.\n\n이 모든 것을 자세히 논의하지는 않겠지만 CRUD와 REST에 대한 자세한 내용은 [CRUD API 디자인](https://blog.stoplight.io/crud-api-design) 에 대한 게시물을 확인하십시오 .\n\nAPI를 설계할 때 RESTful API URL에 목적을 추가하는 대신 호출의 기본 목적을 표현하기 위해 이러한 메서드에 의존하고 싶을 것입니다. 우리는 그것에 대해 조금 더 알게 될 것입니다.\n\n이러한 메서드가 클라이언트에서 서버로 요청 컨텍스트를 제공하는 것처럼 HTTP 상태 코드는 응답을 반대 방향으로 설명하는 데 도움이 됩니다.\n\n몇 가지 일반적인 HTTP 상태 코드는 다음과 같습니다.\n\n- **200** : 성공적인 요청, 종종 GET\n- **201** : 생성 후 성공적인 요청, 일반적으로 POST\n- **204** : 반환된 콘텐츠 없이 성공적인 요청, 일반적으로 PUT 또는 PATCH\n- **301** : 다른 끝점으로 영구적으로 리디렉션\n- **400** : 잘못된 요청(클라이언트가 요청을 수정해야 함)\n- **401** : 승인되지 않음, 자격 증명이 인식되지 않음\n- **403** : 금지됨, 자격 증명이 허용되지만 권한이 없음\n- **404** : 찾을 수 없음, 리소스가 존재하지 않음\n- **410** : 사라짐, 리소스가 이전에 존재했지만 지금은 없음\n- **429** : 속도 제한에 사용되는 요청이 너무 많으며 재시도 헤더를 포함해야 합니다.\n- **500** : 서버 오류, 일반적이며 대신 다른 500 수준 오류를 살펴볼 가치가 있습니다.\n- **503** : 서비스를 사용할 수 없음, 재시도 헤더가 유용한 다른 서비스\n\n고려해야 할 더 많은 HTTP 상태 코드와 메서드가 있지만 위의 목록은 대부분의 API에 대해 잘 이해할 수 있도록 합니다.\n\n## 친근하고 일반적인 API 엔드포인트 이름 사용\n\n웹 사이트의 API 끝점을 어떻게 찾고 결정합니까? REST API를 사용하는 일반적인 디자인 패턴은 리소스를 기반으로 엔드포인트를 구축하는 것입니다. 이들은 HTTP 메서드 동사에 대한 \"명사\"입니다. 이러한 이름이 설명적이면 API 디자인을 훨씬 더 쉽게 이해할 수 있습니다. API 디자인 예제의 경우 요리책 API에서 작업하는 경우 다음 API 엔드포인트 예제의 코드 예제는 /recipes/일 수 있습니다.\n\n새 레시피를 추가하면 이를 엔드포인트에 POST합니다. 목록을 가져오려면 동일한 끝점에서 GET 메서드를 사용합니다. 특정 레시피를 검색하려면 URL의 식별자로 호출할 수 있습니다. /recipes/42\n\n친숙한 REST 끝점 이름으로 특별히 피해야 할 한 가지는 요청에 대한 새로운 정보를 전달하지 않기 때문에 작업을 설명하는 것입니다.\n\n예를 들어 엔드포인트 내의 동사(예: /getRecipes/)는 해당 컨텍스트를 제공하기 위해 HTTP 메서드에 의존하는 것과 반대로 실행됩니다. [CRUD API 설계 권장 사항](https://blog.stoplight.io/crud-api-design) 게시물 은 복수형 및 버전 관리와 같은 인기 있는 주제를 포함하여 더 자세히 설명합니다.\n\n## GET 대 POST API 대량 작업\n\nRESTful API를 설계할 때 호출의 기본 목적을 표현하기 위해 HTTP 메서드 및 모범 사례에 의존하고 싶을 것입니다. 이러한 이유로 단순히 데이터를 검색하기 위해 POST를 사용하고 싶지는 않습니다. GET이 데이터를 생성하거나 제거하는 것도 원하지 않습니다. 사용 사례를 검토하여 각 사용 시기를 결정해야 합니다. 다음은 귀하의 결정에 영향을 미치는 몇 가지 요소입니다.\n\n- **GET** 요청을 캐시할 수 있습니다.\n- **GET 요청은** [멱등적](https://stripe.com/blog/idempotency) 입니다 (동일한 결과를 보장하면서 여러 번 호출할 수 있음).\n- **GET** 요청은 민감한 데이터를 처리할 때 사용해서는 안 됩니다.\n- **GET** 요청에는 길이 제한이 있습니다.\n- **GET** 요청은 데이터 검색에만 사용해야 합니다.\n- **POST** 요청은 캐시되지 않습니다(헤더에 지정되지 않은 경우).\n- **POST** 요청은 멱등성이 아닙니다.\n- **POST** 요청에는 데이터 길이에 대한 제한이 없습니다.\n\n방법을 현명하게 선택하면 경로를 간결하게 유지하고 기본 RESTful API 관행을 따릅니다. 간단한 예를 살펴보겠습니다.\n\n기본 CRUD 기능(만들기, 읽기, 업데이트, 삭제)을 구현하는 경로가 있다고 가정하면 다음 경로로 끝납니다.\n\n- \\[POST\\] /api/recipe - 레시피 생성\n- \\[GET\\] /api/recipe - 레시피 나열\n- \\[GET\\] /api/recipe/:id - ID로 레시피 가져오기\n- \\[PUT\\] /api/recipe/:id - ID로 레시피 업데이트\n- \\[DELETE\\] /api/recipe/:id - ID별로 레시피 삭제\n- \\[DELETE\\] /api/recipe - 대량 삭제 레시피\n\n이 예에서는 실제로 \"/api/recipes\" 및 \"/api/recipe/:id\" 2개의 경로만 있습니다. POST만 사용한다면 6개의 다른 경로가 생깁니다.\n\n## 성능 향상을 위한 캐시 데이터\n\n캐싱은 불필요한 서버 이동을 부분적으로 제거합니다. 각각의 새 요청에 대한 쿼리를 보내는 대신 로컬 메모리에서 데이터를 반환하면 앱의 성능을 향상시킬 수 있습니다. **GET** 요청은 기본적으로 캐시 가능하지만 **POST** 요청의 경우 헤더에 캐시 요구 사항을 지정해야 합니다. 그러나 캐싱은 클라이언트의 브라우저에서 오래된 데이터로 이어질 수 있습니다. **POST** 헤더 에서 이를 처리하는 방법은 다음과 같습니다 .\n\n### 만료\n\n이 경우 캐시된 버전에 대한 절대 만료 시간을 지정합니다. 지정된 시간을 초과하는 모든 항목은 오래된 것으로 간주되며 원본 서버로 업데이트해야 합니다. 최대 1년 후의 시간을 지정할 수 있습니다.\n\n\n\n### 캐시 제어\n\n이 옵션을 사용할 때 max-age, must-revalidate 또는 no-transform과 같은 특정 [지시문을](https://tools.ietf.org/html/rfc7234#page-24) 설정할 수 있습니다 .\n\n\n\n### 마지막 수정\n\n이 옵션을 사용하면 응답 헤더를 사용하여 캐싱 요구 사항을 결정합니다. 응답의 날짜 값은 초기 응답이 생성된 시기를 지정합니다. Last-Modified 날짜는 리소스와 연결된 응답이 마지막으로 변경된 날짜를 지정합니다. 최종 수정 날짜는 날짜 값보다 작을 수 없습니다.\n\n## API 매개변수를 사용한 향후 사용 사례 계획\n\n순진하거나 단순한 API 설계는 위의 모든 지침을 따를 수 있지만 여전히 개발자에게 필요한 사용 사례를 지원하지 않습니다. API가 사용되는 방식을 철저히 이해하고 [모의 API 서버](https://stoplight.io/mock-api-guide/basics/) 와 같은 공동작업자로부터 피드백을 받는 것이 중요합니다 .\n\n종종 API가 구축된 후 사용 사례가 발견되면 엔지니어는 이러한 발굴된 요구 사항을 지원하기 위해 새로운 엔드포인트를 생성합니다. 예를 들어 요리책 API는 특정 카테고리의 레시피만 반환해야 하거나 준비 시간이 가장 짧은 레시피를 표시해야 할 수 있습니다. 중복 엔드포인트를 생성하는 대신 처음부터 스마트 매개변수를 계획하십시오.\n\nAPI에 대해 고려해야 할 세 가지 일반적인 유형의 매개변수가 있습니다.\n\n- **필터링** : 필드 나이를 매개변수로 사용하여 필터와 일치하는 결과만 반환합니다. 예를 들어:\n\nGET /사용자?나이=30\n\n- **페이지 매김** : 모든 것을 제공하여 클라이언트와 서버에 과부하를 주지 마십시오. 대신 제한을 설정하고 응답에 이전 및 다음 링크를 제공하십시오. 예:\n\nGET /users?page=3&results\\_per\\_page=20\n\n- **정렬** : 정렬 방법을 제공하거나 일부 사용 사례에서는 여전히 필요한 것을 찾기 위해 모든 결과를 페이징해야 합니다. 예:\n\nGET /users?sort\\_by=first\\_name&order=asc\n\n이 세 가지 접근 방식을 함께 사용하여 매우 구체적인 쿼리를 지원할 수 있습니다. 사용 사례를 이해하면 매개변수의 복잡성을 결정하는 데 도움이 됩니다.\n\n## 기존 대회에서 차용\n\n이 게시물은 전반적인 API 디자인 패턴을 다루기 위해 최선을 다하고 있지만 업계 또는 특정 기능에 특정한 표준 및 규칙을 살펴보고 싶을 것입니다. 완전히 고유한 API를 구축하는 사람은 거의 없기 때문에 다른 사람에게서 배울 점이 많습니다.\n\n[많은 API 표준이](https://blog.stoplight.io/rest-api-standards-do-they-even-exist) REST API를 중심으로 구축되었습니다. 예를 들어 API에 대한 인증을 구현할 때 새로운 길을 개척하지 마십시오. 사용자 관련 데이터를 제공할 때 잘 알려진 OAuth 경로를 포함하여 API 인증 패턴에 대한 많은 옵션이 있습니다. API 헤더에 대한 표준과 JSON 및 XML과 같은 데이터 형식 및 모델에 대한 몇 가지를 찾을 수 있습니다.\n\n고유한 고려 사항이 있는 [마이크로서비스 API를 설계](https://blog.stoplight.io/designing-apis-for-microservices) 할 수 있습니다 . 이 게시물에서 다루는 모든 내용이 여전히 적용될 가능성이 높지만 마이크로서비스를 설계할 때 더욱 주의를 기울여야 합니다. 각각은 그 자체로 의미가 있어야 하지만 조합(느슨한 결합)의 이점을 누릴 수 있습니다.\n\n반면 [오픈 뱅킹 API는](https://blog.stoplight.io/open-banking-guide) 자체 처리가 필요합니다. 유럽 표준은 가장 성숙했으며 이러한 규정을 기반으로 하는 일련의 디자인 패턴을 가지고 있습니다.\n\n귀하의 산업에는 고유한 표준 또는 규칙이 있을 수 있습니다. 은행 규정만큼 엄격하지 않더라도 개발자에게 이미 친숙한 패턴에 대해 적절한 고려를 할 가치가 있습니다.\n\n## OpenAPI 정의가 있는 문서\n\n[API를 설계할 때 OpenAPI](https://stoplight.io/openapi/) 정의를 정보 소스로 유지하는 것이 매우 유용합니다 . 이전 Swagger 파일의 차세대 형식인 이 형식은 엔드포인트, 요청 데이터, 응답, 오류 코드 등을 설명합니다. 또한 API 수명 주기 전반에 걸쳐 도구를 사용하여 자동화하는 데 사용할 수 있습니다.\n\n\n\n아마도 OpenAPI 문서의 가장 일반적인 용도는 [API 문서](https://stoplight.io/api-documentation/) , 특히 API 참조를 생성하는 것입니다. 형식은 API를 호출할 수 있는 방법을 설명하므로 개발자가 API와 통합하는 데 필요한 모든 정보가 포함됩니다. 또한 일부 API 참조에는 오류 코드와 같은 필수 세부 정보가 포함되어 있지 않으므로 OpenAPI는 정확한 문서화를 권장합니다. 또한 API가 변경될 때마다 새 문서를 생성할 수 있으므로 항상 최신 상태를 유지할 수 있습니다.\n\n또한 OpenAPI 정의를 사용하여 [모의 HTTP 서버를 생성](https://stoplight.io/api-mocking/) 할 수 있습니다 . 이를 통해 코드를 작성하기 전에 API를 시험해 볼 수 있습니다. 초기 피드백 또는 온라인 REST API 클라이언트의 요청 유효성 검사를 위해 팀 간에 인터페이스를 순환합니다.\n\n이는 YAML 또는 JSON을 사용하여 OpenAPI 정의 파일을 생성할 수 있는 기계 판독 가능 API 정의의 두 가지 잠재적 용도입니다. 또는 시각적 OpenAPI 편집기를 사용하여 훨씬 빠르게 만들 수 있습니다. [Stoplight Studio는](https://stoplight.io/studio/) 모든 git 저장소에서 기존 OpenAPI 파일을 읽을 수 있으며 아름다운 편집 환경 내에서 편집하거나 처음부터 시작할 수 있습니다.\n\n## 일관성을 위해 스타일 가이드 사용\n\n일부 디자인 패턴은 기본 설정의 문제입니다. 이상적으로는 API를 생성할 때마다 다시 방문하지 않고 조직의 접근 방식을 한 번에 체계화할 수 있습니다. 스타일 [가이드는](https://stoplight.io/api-style-guides-guidelines-and-best-practices/) API 디자인과 동일한 페이지에 회사를 유지할 수 있습니다. API 간에 일관성을 유지하는 것 외에도 단일 API 내에서 일관성을 유지하는 것이 훨씬 더 중요합니다.\n\n일부 조직에서는 서면 API 스타일 가이드를 작성합니다. 인트라넷 내에서 쉽게 액세스할 수 있는 문서는 모든 사람이 이미 채택한 디자인 패턴을 이해하는 데 도움이 됩니다. 그러나 프로그래밍 방식으로 스타일 가이드를 적용하여 더 멀리 갈 수 있습니다. [오픈 소스 린터](https://blog.stoplight.io/introducing-spectral) 와 같은 도구를 사용하여 OpenAPI 문서에 대한 규칙 세트를 정의할 수 있습니다.\n\nAPI 스타일 가이드를 자동화하면 리소스 및 필드 이름, 대문자 형식, 구두점 사용 방법, 버전 관리 등 API 특성을 얼마든지 찾아볼 수 있습니다.\n\n서면이든 프로그래밍 방식이든 스타일 가이드는 여기에서 다루는 디자인 패턴에 대한 자신만의 가이드라인이 됩니다. 조직에서 HTTP 메서드를 올바르게 사용하고, 적절한 상태 코드를 반환하고, 친숙한 엔드포인트 이름을 구현하고, 스마트 매개변수를 사용하고, 이미 식별한 기존 규칙에서 차용하도록 돕습니다.\n\n[환상적인 API를 만들고 API 디자인 아키텍처를 더 잘 이해할 준비가 되었으니 Stoplight의 API 디자인 관리 플랫폼](https://stoplight.io/) 에서 세계 최고의 API 우선 회사에 합류하세요 . API RESTful 웹 서비스 예제 및 API REST 빌드의 모범 사례에 대한 자세한 내용은 [REST에 대한 이 블로그를](https://blog.stoplight.io/rest-api-security) 확인하여 REST API를 빌드하는 방법에 대해 자세히 알아보세요.\n\n\n출처 : https://blog.stoplight.io/api-design-patterns-for-rest-web-services?utm_source=pocket_saves",
"json_metadata": "{\"tags\":[\"kr-dev\"],\"image\":[\"https://lh4.googleusercontent.com/kGsBpLXavskkjVN-zHSeMhctiYqHHIWIrPHMk98diNJBi0w-b07XMnb0W8_umEaQlz07bs-TfuM3RLxQwfg4hy6JsJlrJPk3bUMWgYstthHYBz2bddOaMJJZZgJ1etW32MZ-2wNy\",\"https://lh4.googleusercontent.com/lDAvcIA_MCAHvo6JEjD7Lj1De7agI3EnG7P3GQMCtm7UvknY7SPY0tZeCrURICMQQwmymd3a1lxtNwwY0tNqIi6PbrgUGtAVv-HZR_yjm3UmOZaEl8Owes8cefRKnSyC538mG2ba\",\"https://lh6.googleusercontent.com/ArmW2xiK3tg-Ft02u98Ts7vBAlHdK6v_MVSsy7UO4ZEOoTDjK927DoFicvSvf27tlcO1Ql2MugxXRwRH__8nW-FWwG0rW9FGG1FUV5papwVwRHKhsMOd746RMeEUzk_DD3rdLHiK\",\"https://lh3.googleusercontent.com/YPx6E9ZiwCkCxlYq-6y71jao086YzXMictI03KIK-x84jmYu9qUfq9-9nVYqtt-CUOuK8Sb00vnmZ-IFS8i3tZDnaXiYqd1aVFQIO9Kna7lJ8s4u4D6W7h2-9rP_llUxYtBtZ0-n\"],\"links\":[\"https://stoplight.io/api-design-guide/basics/\",\"https://blog.stoplight.io/api-design-patterns-for-rest-web-services?utm_source=pocket_saves#http-methods-and-status-codes\",\"https://blog.stoplight.io/crud-api-design\",\"https://stripe.com/blog/idempotency\",\"https://tools.ietf.org/html/rfc7234#page-24\",\"https://stoplight.io/mock-api-guide/basics/\",\"https://blog.stoplight.io/rest-api-standards-do-they-even-exist\",\"https://blog.stoplight.io/designing-apis-for-microservices\",\"https://blog.stoplight.io/open-banking-guide\",\"https://stoplight.io/openapi/\",\"https://stoplight.io/api-documentation/\",\"https://stoplight.io/api-mocking/\",\"https://stoplight.io/studio/\",\"https://stoplight.io/api-style-guides-guidelines-and-best-practices/\",\"https://blog.stoplight.io/introducing-spectral\",\"https://stoplight.io/\",\"https://blog.stoplight.io/rest-api-security\",\"https://blog.stoplight.io/api-design-patterns-for-rest-web-services?utm_source=pocket_saves\"],\"app\":\"steemit/0.2\",\"format\":\"markdown\"}"
}
]
}fulireplied to @kormanocorp / 20230424t042020777z2023/04/24 04:20:36
fulireplied to @kormanocorp / 20230424t042020777z
2023/04/24 04:20:36
| parent author | kormanocorp |
| parent permlink | 3qj1d9 |
| author | fuli |
| permlink | 20230424t042020777z |
| title | upvoted |
| body | You've got a free upvote from <a href='https://steemitwallet.com/~witnesses'>witness fuli</a>. <br /> Peace & Love! <br /> |
| json metadata | {} |
| Transaction Info | Block #74031780/Trx 8357ad9afe4029bc39fbe314c079ef902ccb0dfd |
View Raw JSON Data
{
"trx_id": "8357ad9afe4029bc39fbe314c079ef902ccb0dfd",
"block": 74031780,
"trx_in_block": 4,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-04-24T04:20:36",
"op": [
"comment",
{
"parent_author": "kormanocorp",
"parent_permlink": "3qj1d9",
"author": "fuli",
"permlink": "20230424t042020777z",
"title": "upvoted",
"body": "You've got a free upvote from <a href='https://steemitwallet.com/~witnesses'>witness fuli</a>. <br /> Peace & Love! <br />",
"json_metadata": "{}"
}
]
}fuliupvoted (40.00%) @kormanocorp / 3qj1d92023/04/24 04:20:18
fuliupvoted (40.00%) @kormanocorp / 3qj1d9
2023/04/24 04:20:18
| voter | fuli |
| author | kormanocorp |
| permlink | 3qj1d9 |
| weight | 4000 (40.00%) |
| Transaction Info | Block #74031774/Trx cbc005270620d71fd0108d3eed0ee171d6449e7b |
View Raw JSON Data
{
"trx_id": "cbc005270620d71fd0108d3eed0ee171d6449e7b",
"block": 74031774,
"trx_in_block": 1,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-04-24T04:20:18",
"op": [
"vote",
{
"voter": "fuli",
"author": "kormanocorp",
"permlink": "3qj1d9",
"weight": 4000
}
]
}kr-devupvoted (100.00%) @kormanocorp / 3qj1d92023/04/24 04:16:00
kr-devupvoted (100.00%) @kormanocorp / 3qj1d9
2023/04/24 04:16:00
| voter | kr-dev |
| author | kormanocorp |
| permlink | 3qj1d9 |
| weight | 10000 (100.00%) |
| Transaction Info | Block #74031688/Trx cc5722f614d1174db06e88986ae6a3a0ca58aa60 |
View Raw JSON Data
{
"trx_id": "cc5722f614d1174db06e88986ae6a3a0ca58aa60",
"block": 74031688,
"trx_in_block": 0,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-04-24T04:16:00",
"op": [
"vote",
{
"voter": "kr-dev",
"author": "kormanocorp",
"permlink": "3qj1d9",
"weight": 10000
}
]
}anpigonupvoted (100.00%) @kormanocorp / 3qj1d92023/04/24 04:15:36
anpigonupvoted (100.00%) @kormanocorp / 3qj1d9
2023/04/24 04:15:36
| voter | anpigon |
| author | kormanocorp |
| permlink | 3qj1d9 |
| weight | 10000 (100.00%) |
| Transaction Info | Block #74031680/Trx c4e6d7247ce8ea5692321732f98c53a948fcf0a4 |
View Raw JSON Data
{
"trx_id": "c4e6d7247ce8ea5692321732f98c53a948fcf0a4",
"block": 74031680,
"trx_in_block": 4,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-04-24T04:15:36",
"op": [
"vote",
{
"voter": "anpigon",
"author": "kormanocorp",
"permlink": "3qj1d9",
"weight": 10000
}
]
}kr-dev.cu2replied to @kormanocorp / adreply-16823094720192023/04/24 04:11:12
kr-dev.cu2replied to @kormanocorp / adreply-1682309472019
2023/04/24 04:11:12
| parent author | kormanocorp |
| parent permlink | 3qj1d9 |
| author | kr-dev.cu2 |
| permlink | adreply-1682309472019 |
| title | |
| body | [광고] [STEEM 개발자 커뮤니티에 참여](/hive-137029/@kr-dev/x3v6n) 하시면, 다양한 혜택을 받을 수 있습니다. |
| json metadata | {"tags":["kr-dev"],"image":["https://trunkbaseddevelopment.com/trunk1a.png","https://trunkbaseddevelopment.com/trunk1b.png","https://trunkbaseddevelopment.com/trunk1c.png","https://trunkbaseddevelopment.com/ix_key.png"],"links":["https://trunkbaseddevelopment.com/#one-line-summary","https://trunkbaseddevelopment.com/#shared-branches-off-mainlinemaintrunk-are-bad-at-any-release-cadence","https://trunkbaseddevelopment.com/#trunk-based-development-for-smaller-teams","https://trunkbaseddevelopment.com/#scaled-trunk-based-development","https://trunkbaseddevelopment.com/#elaboration-claims-and-caveats","https://trunkbaseddevelopment.com/continuous-integration/","https://trunkbaseddevelopment.com/continuous-delivery/","https://trunkbaseddevelopment.com/#claims","https://trunkbaseddevelopment.com/#caveats","https://trunkbaseddevelopment.com/short-lived-feature-branches/","https://trunkbaseddevelopment.com/continuous-review/","https://trunkbaseddevelopment.com/committing-straight-to-the-trunk/","https://trunkbaseddevelopment.com/branch-for-release/","https://trunkbaseddevelopment.com/release-from-trunk/","https://trunkbaseddevelopment.com/branch-by-abstraction/","https://trunkbaseddevelopment.com/feature-flags/","https://trunkbaseddevelopment.com/concurrent-development-of-consecutive-releases/","https://trunkbaseddevelopment.com/game-changers/index.html#google-revealing-their-monorepo-trunk-2016","https://trunkbaseddevelopment.com/monorepos/","https://trunkbaseddevelopment.com/expanding-contracting-monorepos/","https://trunkbaseddevelopment.com/alternative-branching-models/index.html#modern-claimed-high-throughput-branching-models","https://trunkbaseddevelopment.com/alternative-branching-models/index.html#legacy-branching-models","https://trunkbaseddevelopment.com/publications/","https://trunkbaseddevelopment.com/#history","https://trunkbaseddevelopment.com/game-changers/","https://trunkbaseddevelopment.com/#this-site","https://trunkbaseddevelopment.com/"],"app":"steemit/0.2","format":"markdown"} |
| Transaction Info | Block #74031592/Trx e8607f224e777ad7cfdc34b0baa8b4da678081a2 |
View Raw JSON Data
{
"trx_id": "e8607f224e777ad7cfdc34b0baa8b4da678081a2",
"block": 74031592,
"trx_in_block": 1,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-04-24T04:11:12",
"op": [
"comment",
{
"parent_author": "kormanocorp",
"parent_permlink": "3qj1d9",
"author": "kr-dev.cu2",
"permlink": "adreply-1682309472019",
"title": "",
"body": "[광고] [STEEM 개발자 커뮤니티에 참여](/hive-137029/@kr-dev/x3v6n) 하시면, 다양한 혜택을 받을 수 있습니다.",
"json_metadata": "{\"tags\":[\"kr-dev\"],\"image\":[\"https://trunkbaseddevelopment.com/trunk1a.png\",\"https://trunkbaseddevelopment.com/trunk1b.png\",\"https://trunkbaseddevelopment.com/trunk1c.png\",\"https://trunkbaseddevelopment.com/ix_key.png\"],\"links\":[\"https://trunkbaseddevelopment.com/#one-line-summary\",\"https://trunkbaseddevelopment.com/#shared-branches-off-mainlinemaintrunk-are-bad-at-any-release-cadence\",\"https://trunkbaseddevelopment.com/#trunk-based-development-for-smaller-teams\",\"https://trunkbaseddevelopment.com/#scaled-trunk-based-development\",\"https://trunkbaseddevelopment.com/#elaboration-claims-and-caveats\",\"https://trunkbaseddevelopment.com/continuous-integration/\",\"https://trunkbaseddevelopment.com/continuous-delivery/\",\"https://trunkbaseddevelopment.com/#claims\",\"https://trunkbaseddevelopment.com/#caveats\",\"https://trunkbaseddevelopment.com/short-lived-feature-branches/\",\"https://trunkbaseddevelopment.com/continuous-review/\",\"https://trunkbaseddevelopment.com/committing-straight-to-the-trunk/\",\"https://trunkbaseddevelopment.com/branch-for-release/\",\"https://trunkbaseddevelopment.com/release-from-trunk/\",\"https://trunkbaseddevelopment.com/branch-by-abstraction/\",\"https://trunkbaseddevelopment.com/feature-flags/\",\"https://trunkbaseddevelopment.com/concurrent-development-of-consecutive-releases/\",\"https://trunkbaseddevelopment.com/game-changers/index.html#google-revealing-their-monorepo-trunk-2016\",\"https://trunkbaseddevelopment.com/monorepos/\",\"https://trunkbaseddevelopment.com/expanding-contracting-monorepos/\",\"https://trunkbaseddevelopment.com/alternative-branching-models/index.html#modern-claimed-high-throughput-branching-models\",\"https://trunkbaseddevelopment.com/alternative-branching-models/index.html#legacy-branching-models\",\"https://trunkbaseddevelopment.com/publications/\",\"https://trunkbaseddevelopment.com/#history\",\"https://trunkbaseddevelopment.com/game-changers/\",\"https://trunkbaseddevelopment.com/#this-site\",\"https://trunkbaseddevelopment.com/\"],\"app\":\"steemit/0.2\",\"format\":\"markdown\"}"
}
]
}kormanocorppublished a new post: 3qj1d92023/04/24 04:10:57
kormanocorppublished a new post: 3qj1d9
2023/04/24 04:10:57
| parent author | |
| parent permlink | kr-dev |
| author | kormanocorp |
| permlink | 3qj1d9 |
| title | 트렁크 기반 개발 |
| body | ## 한 줄 요약[#](https://trunkbaseddevelopment.com/#one-line-summary "영구 링크") 개발자가 '트렁크'\*라는 단일 분기에서 코드에 대해 공동 작업하는 소스 제어 분기 모델은 문서화된 기술을 사용하여 다른 장기 개발 분기를 생성해야 한다는 압력에 저항합니다. 따라서 그들은 병합 지옥을 피하고 빌드를 깨지 않고 행복하게 산다. \* 2020년부터 Git 커뮤니티의 _메인_`master` ( 이전에는 불미스러운 의미 포함) ## 메인라인/메인/트렁크의 공유 분기는 모든 릴리스 주기에서 좋지 않습니다.[#](https://trunkbaseddevelopment.com/#shared-branches-off-mainlinemaintrunk-are-bad-at-any-release-cadence "영구 링크")  ## 소규모 팀을 위한 트렁크 기반 개발:[#](https://trunkbaseddevelopment.com/#trunk-based-development-for-smaller-teams "영구 링크")  ## 확장 트렁크 기반 개발:[#](https://trunkbaseddevelopment.com/#scaled-trunk-based-development "영구 링크")  ## 정교화, 주장 및 주의 사항[#](https://trunkbaseddevelopment.com/#elaboration-claims-and-caveats "영구 링크")  트렁크 기반 개발은 [지속적인 통합](https://trunkbaseddevelopment.com/continuous-integration/) 및 확장 [된 지속적인 전달](https://trunkbaseddevelopment.com/continuous-delivery/) 의 핵심 인에이블러입니다 . 팀의 개인이 변경 사항을 하루에 여러 번 트렁크에 커밋하면 모든 팀 구성원이 적어도 24시간마다 트렁크에 커밋해야 하는 지속적인 통합의 핵심 요구 사항을 쉽게 충족할 수 있습니다. 이를 통해 코드베이스는 항상 온디맨드로 릴리스할 수 있으며 지속적인 전달을 실현하는 데 도움이 됩니다. 소규모 팀 트렁크 기반 개발과 확장된 트렁크 기반 개발 사이의 구분선은 팀 규모와 커밋 속도 고려 대상입니다. 개발 팀이 더 이상 "소규모"가 아니라 "확장"으로 전환한 정확한 순간은 실무자 토론의 대상입니다. 그럼에도 불구하고 팀은 다른 사람(또는 봇)이 볼 수 있도록 커밋/푸시하기 전에 개발 워크스테이션에서 전체 "사전 통합" 빌드(컴파일, 단위 테스트, 통합 테스트)를 수행합니다. ### 클레임[#](https://trunkbaseddevelopment.com/#claims "영구 링크") - GitFlow 및 여러 장기 실행 분기를 특징으로 하는 기타 분기 모델 대신 트렁크 기반 개발을 수행해야 합니다. - 이러한 기능 분기가 수명이 짧고 한 사람의 제품인 경우 트렁크 커밋/푸시(v 소규모 팀) 또는 풀 요청 워크플로에 직접 수행할 수 있습니다. ### 주의 사항[#](https://trunkbaseddevelopment.com/#caveats "영구 링크") - 팀 규모와 커밋 속도에 따라 코드 검토 및 빌드 확인(CI)에는 [수명이 짧은 기능 분기가](https://trunkbaseddevelopment.com/short-lived-feature-branches/) 사용되지만 커밋이 다른 개발자가 의존할 수 있도록 트렁크에 저장되기 전에 발생하는 아티팩트 생성 또는 게시에는 사용되지 않습니다. 에. 이러한 분기를 통해 개발자는 코드가 트렁크에 통합되기 전에 [열심히 지속적으로 기여 코드 검토](https://trunkbaseddevelopment.com/continuous-review/) 에 참여할 수 있습니다 . 매우 작은 팀은 [트렁크에 직접 커밋](https://trunkbaseddevelopment.com/committing-straight-to-the-trunk/) 할 수 있습니다 . - 의도한 릴리스 주기에 따라 적시에 트렁크에서 잘라내어 릴리스 전에 '강화'되고(팀 활동 없이) 해당 분기가 언젠가 **삭제되는 릴리스** [분기가](https://trunkbaseddevelopment.com/branch-for-release/) 있을 수 있습니다. 릴리스 후. [또는 팀이 Trunk 에서 릴리스](https://trunkbaseddevelopment.com/release-from-trunk/) 하고 버그 수정을 위해 "앞으로 수정" 전략을 선택하는 경우 릴리스 분기가 없을 수도 있습니다 . 트렁크에서 해제하는 것도 처리량이 많은 팀을 위한 것입니다.[](https://trunkbaseddevelopment.com/release-from-trunk/) - 팀은 변경 사항을 더 오래 달성하기 위해 [추상화 기술을 통해](https://trunkbaseddevelopment.com/branch-by-abstraction/) 관련 분기에 익숙해져야 하며 일상적인 개발에서 [기능 플래그를 사용하여 릴리스 순서를 헤지할 수 있도록 해야 합니다(및 기타 좋은 점 -](https://trunkbaseddevelopment.com/feature-flags/) [연속 릴리스의 동시 개발](https://trunkbaseddevelopment.com/concurrent-development-of-consecutive-releases/) 참조 ) . - [프로젝트에 2명 이상의 개발자가 있는 경우 빌드 서버를](https://trunkbaseddevelopment.com/continuous-integration/) 연결하여 그들의 커밋이 트렁크에 도착한 후 그리고 병합할 준비가 되었을 때 **빌드를 손상시키지 않았는지** 확인 해야 합니다. 수명이 짧은 기능 분기에서 트렁크로 다시 돌아갑니다. - 개발 팀은 처리량이나 품질에 영향을 주지 않고 자연스럽게 크기를 늘리거나 줄일 수 있습니다(트렁크에서). 증거? [Google은 트렁크 기반 개발을 수행](https://trunkbaseddevelopment.com/game-changers/index.html#google-revealing-their-monorepo-trunk-2016) 하고 해당 단일 단일 [리포지토리 트렁크에](https://trunkbaseddevelopment.com/monorepos/) **35000명의 개발자와 QA 자동화를** 보유하고 있으며 , 이들의 경우 문제의 개발자에 맞게 [확장하거나 축소 할 수 있습니다.](https://trunkbaseddevelopment.com/expanding-contracting-monorepos/)[](https://trunkbaseddevelopment.com/monorepos/)[](https://trunkbaseddevelopment.com/expanding-contracting-monorepos/) - [GitHub 흐름 분기 모델을](https://trunkbaseddevelopment.com/alternative-branching-models/index.html#modern-claimed-high-throughput-branching-models) 실행하는 사람들은 이것이 매우 유사하다고 느낄 것입니다. 그러나 릴리스 위치에는 작은 차이가 있습니다. - Gitflow 분기 모델을 연습하는 사람들은 [과거의](https://trunkbaseddevelopment.com/alternative-branching-models/index.html#legacy-branching-models) 인기 있는 ClearCase, Subversion, Perforce, StarTeam, VCS 분기 모델에 익숙한 많은 개발자들이 그러하듯이 이것이 **매우 다르다는 것을** 알게 될 것입니다 .[](https://trunkbaseddevelopment.com/alternative-branching-models/index.html#legacy-branching-models) - [여기에서 설명하는 것처럼 많은 간행물에서](https://trunkbaseddevelopment.com/publications/) 트렁크 기반 개발을 홍보합니다. 여기에는 베스트 셀러인 'Continuous Delivery' 및 'DevOps 핸드북'이 포함됩니다. 이것은 더 이상 논쟁의 여지가 없어야 합니다! ## 역사[#](https://trunkbaseddevelopment.com/#history "영구 링크") 트렁크 기반 개발은 새로운 분기 모델이 아닙니다. '트렁크'라는 단어는 성장하는 나무의 개념과 관련이 있으며, 여기서 가장 뚱뚱하고 가장 긴 범위는 트렁크에서 방사되고 더 제한된 길이의 가지가 아니라 트렁크입니다. 90년대 중반 이후로 덜 알려진 분기 모델이었으며 80년대 이후 전술적으로 고려되었습니다. Google(언급한 대로) 및 Facebook과 같은 가장 큰 개발 조직은 이를 대규모로 실행합니다. [소스 제어 기술 및 관련 도구/기술에 대한](https://trunkbaseddevelopment.com/game-changers/) 30년 이상의 다양한 발전 으로 인해 Trunk-Based Development가 더 많이(때로는 덜) 보급되었지만 많은 사람들이 수년 동안 고수해 온 분기 모델이었습니다. ## 이 장소[#](https://trunkbaseddevelopment.com/#this-site "영구 링크") 이 사이트는 트렁크 기반 개발에 대한 모든 관련 사실, 이론적 근거 및 기술을 한 곳에서 함께 수집하려고 시도하며, 이를 설명하는 데 도움이 되는 25개의 다이어그램을 완성합니다. TBD를 약어로 사용하지 않고 모두~한 번~두 배. https://trunkbaseddevelopment.com/ |
| json metadata | {"tags":["kr-dev"],"image":["https://trunkbaseddevelopment.com/trunk1a.png","https://trunkbaseddevelopment.com/trunk1b.png","https://trunkbaseddevelopment.com/trunk1c.png","https://trunkbaseddevelopment.com/ix_key.png"],"links":["https://trunkbaseddevelopment.com/#one-line-summary","https://trunkbaseddevelopment.com/#shared-branches-off-mainlinemaintrunk-are-bad-at-any-release-cadence","https://trunkbaseddevelopment.com/#trunk-based-development-for-smaller-teams","https://trunkbaseddevelopment.com/#scaled-trunk-based-development","https://trunkbaseddevelopment.com/#elaboration-claims-and-caveats","https://trunkbaseddevelopment.com/continuous-integration/","https://trunkbaseddevelopment.com/continuous-delivery/","https://trunkbaseddevelopment.com/#claims","https://trunkbaseddevelopment.com/#caveats","https://trunkbaseddevelopment.com/short-lived-feature-branches/","https://trunkbaseddevelopment.com/continuous-review/","https://trunkbaseddevelopment.com/committing-straight-to-the-trunk/","https://trunkbaseddevelopment.com/branch-for-release/","https://trunkbaseddevelopment.com/release-from-trunk/","https://trunkbaseddevelopment.com/branch-by-abstraction/","https://trunkbaseddevelopment.com/feature-flags/","https://trunkbaseddevelopment.com/concurrent-development-of-consecutive-releases/","https://trunkbaseddevelopment.com/game-changers/index.html#google-revealing-their-monorepo-trunk-2016","https://trunkbaseddevelopment.com/monorepos/","https://trunkbaseddevelopment.com/expanding-contracting-monorepos/","https://trunkbaseddevelopment.com/alternative-branching-models/index.html#modern-claimed-high-throughput-branching-models","https://trunkbaseddevelopment.com/alternative-branching-models/index.html#legacy-branching-models","https://trunkbaseddevelopment.com/publications/","https://trunkbaseddevelopment.com/#history","https://trunkbaseddevelopment.com/game-changers/","https://trunkbaseddevelopment.com/#this-site","https://trunkbaseddevelopment.com/"],"app":"steemit/0.2","format":"markdown"} |
| Transaction Info | Block #74031587/Trx 3df08c2be83c37919a75ac9ff9290e09ca9fce90 |
View Raw JSON Data
{
"trx_id": "3df08c2be83c37919a75ac9ff9290e09ca9fce90",
"block": 74031587,
"trx_in_block": 3,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-04-24T04:10:57",
"op": [
"comment",
{
"parent_author": "",
"parent_permlink": "kr-dev",
"author": "kormanocorp",
"permlink": "3qj1d9",
"title": "트렁크 기반 개발",
"body": "## 한 줄 요약[#](https://trunkbaseddevelopment.com/#one-line-summary \"영구 링크\")\n\n개발자가 '트렁크'\\*라는 단일 분기에서 코드에 대해 공동 작업하는 소스 제어 분기 모델은 문서화된 기술을 사용하여 다른 장기 개발 분기를 생성해야 한다는 압력에 저항합니다. 따라서 그들은 병합 지옥을 피하고 빌드를 깨지 않고 행복하게 산다.\n\n\\* 2020년부터 Git 커뮤니티의 _메인_`master` ( 이전에는 불미스러운 의미 포함)\n\n## 메인라인/메인/트렁크의 공유 분기는 모든 릴리스 주기에서 좋지 않습니다.[#](https://trunkbaseddevelopment.com/#shared-branches-off-mainlinemaintrunk-are-bad-at-any-release-cadence \"영구 링크\")\n\n\n\n## 소규모 팀을 위한 트렁크 기반 개발:[#](https://trunkbaseddevelopment.com/#trunk-based-development-for-smaller-teams \"영구 링크\")\n\n\n\n## 확장 트렁크 기반 개발:[#](https://trunkbaseddevelopment.com/#scaled-trunk-based-development \"영구 링크\")\n\n\n\n## 정교화, 주장 및 주의 사항[#](https://trunkbaseddevelopment.com/#elaboration-claims-and-caveats \"영구 링크\")\n\n\n\n트렁크 기반 개발은 [지속적인 통합](https://trunkbaseddevelopment.com/continuous-integration/) 및 확장 [된 지속적인 전달](https://trunkbaseddevelopment.com/continuous-delivery/) 의 핵심 인에이블러입니다 . 팀의 개인이 변경 사항을 하루에 여러 번 트렁크에 커밋하면 모든 팀 구성원이 적어도 24시간마다 트렁크에 커밋해야 하는 지속적인 통합의 핵심 요구 사항을 쉽게 충족할 수 있습니다. 이를 통해 코드베이스는 항상 온디맨드로 릴리스할 수 있으며 지속적인 전달을 실현하는 데 도움이 됩니다.\n\n소규모 팀 트렁크 기반 개발과 확장된 트렁크 기반 개발 사이의 구분선은 팀 규모와 커밋 속도 고려 대상입니다. 개발 팀이 더 이상 \"소규모\"가 아니라 \"확장\"으로 전환한 정확한 순간은 실무자 토론의 대상입니다. 그럼에도 불구하고 팀은 다른 사람(또는 봇)이 볼 수 있도록 커밋/푸시하기 전에 개발 워크스테이션에서 전체 \"사전 통합\" 빌드(컴파일, 단위 테스트, 통합 테스트)를 수행합니다.\n\n### 클레임[#](https://trunkbaseddevelopment.com/#claims \"영구 링크\")\n\n- GitFlow 및 여러 장기 실행 분기를 특징으로 하는 기타 분기 모델 대신 트렁크 기반 개발을 수행해야 합니다.\n- 이러한 기능 분기가 수명이 짧고 한 사람의 제품인 경우 트렁크 커밋/푸시(v 소규모 팀) 또는 풀 요청 워크플로에 직접 수행할 수 있습니다.\n\n### 주의 사항[#](https://trunkbaseddevelopment.com/#caveats \"영구 링크\")\n\n- 팀 규모와 커밋 속도에 따라 코드 검토 및 빌드 확인(CI)에는 [수명이 짧은 기능 분기가](https://trunkbaseddevelopment.com/short-lived-feature-branches/) 사용되지만 커밋이 다른 개발자가 의존할 수 있도록 트렁크에 저장되기 전에 발생하는 아티팩트 생성 또는 게시에는 사용되지 않습니다. 에. 이러한 분기를 통해 개발자는 코드가 트렁크에 통합되기 전에 [열심히 지속적으로 기여 코드 검토](https://trunkbaseddevelopment.com/continuous-review/) 에 참여할 수 있습니다 . 매우 작은 팀은 [트렁크에 직접 커밋](https://trunkbaseddevelopment.com/committing-straight-to-the-trunk/) 할 수 있습니다 .\n \n- 의도한 릴리스 주기에 따라 적시에 트렁크에서 잘라내어 릴리스 전에 '강화'되고(팀 활동 없이) 해당 분기가 언젠가 **삭제되는 릴리스** [분기가](https://trunkbaseddevelopment.com/branch-for-release/) 있을 수 있습니다. 릴리스 후. [또는 팀이 Trunk 에서 릴리스](https://trunkbaseddevelopment.com/release-from-trunk/) 하고 버그 수정을 위해 \"앞으로 수정\" 전략을 선택하는 경우 릴리스 분기가 없을 수도 있습니다 . 트렁크에서 해제하는 것도 처리량이 많은 팀을 위한 것입니다.[](https://trunkbaseddevelopment.com/release-from-trunk/)\n \n- 팀은 변경 사항을 더 오래 달성하기 위해 [추상화 기술을 통해](https://trunkbaseddevelopment.com/branch-by-abstraction/) 관련 분기에 익숙해져야 하며 일상적인 개발에서 [기능 플래그를 사용하여 릴리스 순서를 헤지할 수 있도록 해야 합니다(및 기타 좋은 점 -](https://trunkbaseddevelopment.com/feature-flags/) [연속 릴리스의 동시 개발](https://trunkbaseddevelopment.com/concurrent-development-of-consecutive-releases/) 참조 ) .\n \n- [프로젝트에 2명 이상의 개발자가 있는 경우 빌드 서버를](https://trunkbaseddevelopment.com/continuous-integration/) 연결하여 그들의 커밋이 트렁크에 도착한 후 그리고 병합할 준비가 되었을 때 **빌드를 손상시키지 않았는지** 확인 해야 합니다. 수명이 짧은 기능 분기에서 트렁크로 다시 돌아갑니다.\n \n- 개발 팀은 처리량이나 품질에 영향을 주지 않고 자연스럽게 크기를 늘리거나 줄일 수 있습니다(트렁크에서). 증거? [Google은 트렁크 기반 개발을 수행](https://trunkbaseddevelopment.com/game-changers/index.html#google-revealing-their-monorepo-trunk-2016) 하고 해당 단일 단일 [리포지토리 트렁크에](https://trunkbaseddevelopment.com/monorepos/) **35000명의 개발자와 QA 자동화를** 보유하고 있으며 , 이들의 경우 문제의 개발자에 맞게 [확장하거나 축소 할 수 있습니다.](https://trunkbaseddevelopment.com/expanding-contracting-monorepos/)[](https://trunkbaseddevelopment.com/monorepos/)[](https://trunkbaseddevelopment.com/expanding-contracting-monorepos/)\n \n- [GitHub 흐름 분기 모델을](https://trunkbaseddevelopment.com/alternative-branching-models/index.html#modern-claimed-high-throughput-branching-models) 실행하는 사람들은 이것이 매우 유사하다고 느낄 것입니다. 그러나 릴리스 위치에는 작은 차이가 있습니다.\n \n- Gitflow 분기 모델을 연습하는 사람들은 [과거의](https://trunkbaseddevelopment.com/alternative-branching-models/index.html#legacy-branching-models) 인기 있는 ClearCase, Subversion, Perforce, StarTeam, VCS 분기 모델에 익숙한 많은 개발자들이 그러하듯이 이것이 **매우 다르다는 것을** 알게 될 것입니다 .[](https://trunkbaseddevelopment.com/alternative-branching-models/index.html#legacy-branching-models)\n \n- [여기에서 설명하는 것처럼 많은 간행물에서](https://trunkbaseddevelopment.com/publications/) 트렁크 기반 개발을 홍보합니다. 여기에는 베스트 셀러인 'Continuous Delivery' 및 'DevOps 핸드북'이 포함됩니다. 이것은 더 이상 논쟁의 여지가 없어야 합니다!\n \n\n## 역사[#](https://trunkbaseddevelopment.com/#history \"영구 링크\")\n\n트렁크 기반 개발은 새로운 분기 모델이 아닙니다. '트렁크'라는 단어는 성장하는 나무의 개념과 관련이 있으며, 여기서 가장 뚱뚱하고 가장 긴 범위는 트렁크에서 방사되고 더 제한된 길이의 가지가 아니라 트렁크입니다.\n\n90년대 중반 이후로 덜 알려진 분기 모델이었으며 80년대 이후 전술적으로 고려되었습니다. Google(언급한 대로) 및 Facebook과 같은 가장 큰 개발 조직은 이를 대규모로 실행합니다.\n\n[소스 제어 기술 및 관련 도구/기술에 대한](https://trunkbaseddevelopment.com/game-changers/) 30년 이상의 다양한 발전 으로 인해 Trunk-Based Development가 더 많이(때로는 덜) 보급되었지만 많은 사람들이 수년 동안 고수해 온 분기 모델이었습니다.\n\n## 이 장소[#](https://trunkbaseddevelopment.com/#this-site \"영구 링크\")\n\n이 사이트는 트렁크 기반 개발에 대한 모든 관련 사실, 이론적 근거 및 기술을 한 곳에서 함께 수집하려고 시도하며, 이를 설명하는 데 도움이 되는 25개의 다이어그램을 완성합니다. TBD를 약어로 사용하지 않고 모두~한 번~두 배.\n\nhttps://trunkbaseddevelopment.com/",
"json_metadata": "{\"tags\":[\"kr-dev\"],\"image\":[\"https://trunkbaseddevelopment.com/trunk1a.png\",\"https://trunkbaseddevelopment.com/trunk1b.png\",\"https://trunkbaseddevelopment.com/trunk1c.png\",\"https://trunkbaseddevelopment.com/ix_key.png\"],\"links\":[\"https://trunkbaseddevelopment.com/#one-line-summary\",\"https://trunkbaseddevelopment.com/#shared-branches-off-mainlinemaintrunk-are-bad-at-any-release-cadence\",\"https://trunkbaseddevelopment.com/#trunk-based-development-for-smaller-teams\",\"https://trunkbaseddevelopment.com/#scaled-trunk-based-development\",\"https://trunkbaseddevelopment.com/#elaboration-claims-and-caveats\",\"https://trunkbaseddevelopment.com/continuous-integration/\",\"https://trunkbaseddevelopment.com/continuous-delivery/\",\"https://trunkbaseddevelopment.com/#claims\",\"https://trunkbaseddevelopment.com/#caveats\",\"https://trunkbaseddevelopment.com/short-lived-feature-branches/\",\"https://trunkbaseddevelopment.com/continuous-review/\",\"https://trunkbaseddevelopment.com/committing-straight-to-the-trunk/\",\"https://trunkbaseddevelopment.com/branch-for-release/\",\"https://trunkbaseddevelopment.com/release-from-trunk/\",\"https://trunkbaseddevelopment.com/branch-by-abstraction/\",\"https://trunkbaseddevelopment.com/feature-flags/\",\"https://trunkbaseddevelopment.com/concurrent-development-of-consecutive-releases/\",\"https://trunkbaseddevelopment.com/game-changers/index.html#google-revealing-their-monorepo-trunk-2016\",\"https://trunkbaseddevelopment.com/monorepos/\",\"https://trunkbaseddevelopment.com/expanding-contracting-monorepos/\",\"https://trunkbaseddevelopment.com/alternative-branching-models/index.html#modern-claimed-high-throughput-branching-models\",\"https://trunkbaseddevelopment.com/alternative-branching-models/index.html#legacy-branching-models\",\"https://trunkbaseddevelopment.com/publications/\",\"https://trunkbaseddevelopment.com/#history\",\"https://trunkbaseddevelopment.com/game-changers/\",\"https://trunkbaseddevelopment.com/#this-site\",\"https://trunkbaseddevelopment.com/\"],\"app\":\"steemit/0.2\",\"format\":\"markdown\"}"
}
]
}kr-devupvoted (100.00%) @kormanocorp / 4eals62023/04/21 06:46:30
kr-devupvoted (100.00%) @kormanocorp / 4eals6
2023/04/21 06:46:30
| voter | kr-dev |
| author | kormanocorp |
| permlink | 4eals6 |
| weight | 10000 (100.00%) |
| Transaction Info | Block #73948685/Trx fc4316720370ea6274616c74857477500fbe4666 |
View Raw JSON Data
{
"trx_id": "fc4316720370ea6274616c74857477500fbe4666",
"block": 73948685,
"trx_in_block": 4,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-04-21T06:46:30",
"op": [
"vote",
{
"voter": "kr-dev",
"author": "kormanocorp",
"permlink": "4eals6",
"weight": 10000
}
]
}kr-dev.cu4replied to @kormanocorp / adreply-16820592989252023/04/21 06:41:39
kr-dev.cu4replied to @kormanocorp / adreply-1682059298925
2023/04/21 06:41:39
| parent author | kormanocorp |
| parent permlink | 4eals6 |
| author | kr-dev.cu4 |
| permlink | adreply-1682059298925 |
| title | |
| body | [광고] [STEEM 개발자 커뮤니티에 참여](/hive-137029/@kr-dev/x3v6n) 하시면, 다양한 혜택을 받을 수 있습니다. |
| json metadata | {"tags":["kr-dev"],"image":["https://i0.wp.com/skolaparthi.com/wp-content/uploads/2022/10/image-3.png?resize=638%2C275&ssl=1"],"links":["https://cloud.google.com/dataflow","https://www.ibm.com/cloud/event-streams","https://aws.amazon.com/kinesis/","https://keen.io/","https://solace.com/solutions/initiative/ipaas/","https://skolaparthi.com/apache-kafka-installation/","https://skolaparthi.com/event-driven-architecture/"],"app":"steemit/0.2","format":"markdown"} |
| Transaction Info | Block #73948588/Trx 1ea34467e2d7aee5f3bae4942e2b85d89098fc39 |
View Raw JSON Data
{
"trx_id": "1ea34467e2d7aee5f3bae4942e2b85d89098fc39",
"block": 73948588,
"trx_in_block": 2,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-04-21T06:41:39",
"op": [
"comment",
{
"parent_author": "kormanocorp",
"parent_permlink": "4eals6",
"author": "kr-dev.cu4",
"permlink": "adreply-1682059298925",
"title": "",
"body": "[광고] [STEEM 개발자 커뮤니티에 참여](/hive-137029/@kr-dev/x3v6n) 하시면, 다양한 혜택을 받을 수 있습니다.",
"json_metadata": "{\"tags\":[\"kr-dev\"],\"image\":[\"https://i0.wp.com/skolaparthi.com/wp-content/uploads/2022/10/image-3.png?resize=638%2C275&ssl=1\"],\"links\":[\"https://cloud.google.com/dataflow\",\"https://www.ibm.com/cloud/event-streams\",\"https://aws.amazon.com/kinesis/\",\"https://keen.io/\",\"https://solace.com/solutions/initiative/ipaas/\",\"https://skolaparthi.com/apache-kafka-installation/\",\"https://skolaparthi.com/event-driven-architecture/\"],\"app\":\"steemit/0.2\",\"format\":\"markdown\"}"
}
]
}kormanocorppublished a new post: 4eals62023/04/21 06:41:24
kormanocorppublished a new post: 4eals6
2023/04/21 06:41:24
| parent author | |
| parent permlink | kr-dev |
| author | kormanocorp |
| permlink | 4eals6 |
| title | 이벤트 기반 마이크로서비스 아키텍처 |
| body | **EDA** ( **Event-Driven Architecture** )는 조직이 "이벤트" 또는 중요한 비즈니스 순간(예: 트랜잭션, 사이트 방문, 장바구니 포기 등)을 감지하고 실시간으로 또는 그에 가까운 조치를 취할 수 있도록 하는 소프트웨어 디자인 패턴입니다. 실시간. 이벤트 기반 아키텍처는 종종 "비동기" 통신이라고 합니다. 이는 발신자와 수신자가 다음 작업으로 넘어가기 위해 서로를 기다릴 필요가 없음을 의미합니다. 시스템은 그 하나의 메시지에 의존하지 않습니다. 이벤트 기반 데이터 관리 시스템은 주로 마이크로 서비스를 구동하기 위해 실행됩니다. 이 시스템의 일부로 하나의 마이크로 서비스는 주목할만한 일이 발생하면 이벤트를 브로드캐스트하고 다른 마이크로 서비스는 이를 구독합니다. 이는 현대 기업의 높아지는 기대치를 충족하고 마이크로서비스를 보다 안전하게 만들기 위해 중개 이벤트 브로커를 통해 수행됩니다. 마이크로서비스는 이벤트를 수신한 후 비즈니스 엔터티를 수정할 수 있으며 이로 인해 새로운 이벤트가 게시됩니다. 이 디자인 패턴은 모든 언어와 플랫폼에 대해 작성된 프로그램에 적용됩니다.  이벤트 기반 아키텍처 ## 이벤트 기반 아키텍처의 이점: - **반응성** . 모든 것이 가능한 한 빨리 발생하고 아무도 다른 사람을 기다리지 않기 때문에 이벤트 기반 아키텍처는 가능한 가장 빠른 응답 시간을 제공합니다. - **확장성** . 다운스트림에서 발생하는 상황을 고려할 필요가 없으므로 확장할 서비스 인스턴스를 추가할 수 있습니다. 주제 라우팅 및 필터링은 명령 쿼리 책임 분리에서와 같이 빠르고 쉽게 서비스를 나눌 수 있습니다. - **민첩성** . 다른 서비스를 추가하려는 경우 이벤트를 구독하고 자체적으로 새 이벤트를 생성하도록 할 수 있습니다. 기존 서비스는 이러한 일이 발생했음을 모르거나 신경 쓰지 않으므로 영향을 미치지 않습니다. - 확장성 및 분산성이 뛰어납니다 **.** ## 이 아키텍처를 사용하는 경우: - 여러 하위 시스템이 동일한 이벤트를 처리해야 합니다. - 최소 시간 지연으로 실시간 처리. - 시간 창에 따른 패턴 일치 또는 집계와 같은 복잡한 이벤트 처리. - IoT와 같은 대용량 및 고속 데이터. ## 과제: - 배달 보장. 일부 시스템, 특히 IoT 시나리오에서는 이벤트가 전달되도록 보장하는 것이 중요합니다. - 이벤트를 순서대로 또는 정확히 한 번 처리합니다. 각 소비자 유형은 일반적으로 복원력과 확장성을 위해 여러 인스턴스에서 실행됩니다. ## 게시/구독 및 이벤트 기반 아키텍처를 활성화하는 주요 도구: - [구글 클라우드 플랫폼 데이터 흐름](https://cloud.google.com/dataflow) - [IBM 이벤트 스트림](https://www.ibm.com/cloud/event-streams) - [AWS 키네시스](https://aws.amazon.com/kinesis/) - [날카로운](https://keen.io/) - [위안](https://solace.com/solutions/initiative/ipaas/) - [아파치 카프카](https://skolaparthi.com/apache-kafka-installation/) - 활성 MQ - 펄서 ## 이벤트 기반 마이크로서비스 아키텍처의 패턴: 다음 패턴은 마이크로 서비스 개발의 이벤트 중심 방식으로 활용됩니다. - 이벤트 스트림 - 이벤트 소싱 - 다국어 지속성 - 명령 쿼리 책임 분리(CQRS) 결론: 이 기사에서는 이벤트 기반 마이크로 서비스와 이벤트 기반 접근 방식을 사용하여 마이크로 서비스를 구축하는 방법에 대해 설명했습니다. 이벤트 기반 아키텍처에서 게시자는 이벤트를 게시하고 소비자는 이벤트를 구독합니다. 이러한 이벤트는 서비스가 분리된 방식으로 통신하는 데 도움이 됩니다. https://skolaparthi.com/event-driven-architecture/ |
| json metadata | {"tags":["kr-dev"],"image":["https://i0.wp.com/skolaparthi.com/wp-content/uploads/2022/10/image-3.png?resize=638%2C275&ssl=1"],"links":["https://cloud.google.com/dataflow","https://www.ibm.com/cloud/event-streams","https://aws.amazon.com/kinesis/","https://keen.io/","https://solace.com/solutions/initiative/ipaas/","https://skolaparthi.com/apache-kafka-installation/","https://skolaparthi.com/event-driven-architecture/"],"app":"steemit/0.2","format":"markdown"} |
| Transaction Info | Block #73948583/Trx 4eb4b46ba4ba1f5abc364f7dfe75be5e79b5fbef |
View Raw JSON Data
{
"trx_id": "4eb4b46ba4ba1f5abc364f7dfe75be5e79b5fbef",
"block": 73948583,
"trx_in_block": 1,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-04-21T06:41:24",
"op": [
"comment",
{
"parent_author": "",
"parent_permlink": "kr-dev",
"author": "kormanocorp",
"permlink": "4eals6",
"title": "이벤트 기반 마이크로서비스 아키텍처",
"body": "**EDA** ( **Event-Driven Architecture** )는 조직이 \"이벤트\" 또는 중요한 비즈니스 순간(예: 트랜잭션, 사이트 방문, 장바구니 포기 등)을 감지하고 실시간으로 또는 그에 가까운 조치를 취할 수 있도록 하는 소프트웨어 디자인 패턴입니다. 실시간.\n\n이벤트 기반 아키텍처는 종종 \"비동기\" 통신이라고 합니다. 이는 발신자와 수신자가 다음 작업으로 넘어가기 위해 서로를 기다릴 필요가 없음을 의미합니다. 시스템은 그 하나의 메시지에 의존하지 않습니다.\n\n이벤트 기반 데이터 관리 시스템은 주로 마이크로 서비스를 구동하기 위해 실행됩니다. 이 시스템의 일부로 하나의 마이크로 서비스는 주목할만한 일이 발생하면 이벤트를 브로드캐스트하고 다른 마이크로 서비스는 이를 구독합니다. 이는 현대 기업의 높아지는 기대치를 충족하고 마이크로서비스를 보다 안전하게 만들기 위해 중개 이벤트 브로커를 통해 수행됩니다.\n\n마이크로서비스는 이벤트를 수신한 후 비즈니스 엔터티를 수정할 수 있으며 이로 인해 새로운 이벤트가 게시됩니다. 이 디자인 패턴은 모든 언어와 플랫폼에 대해 작성된 프로그램에 적용됩니다.\n\n\n\n이벤트 기반 아키텍처\n\n## 이벤트 기반 아키텍처의 이점:\n\n- **반응성** . 모든 것이 가능한 한 빨리 발생하고 아무도 다른 사람을 기다리지 않기 때문에 이벤트 기반 아키텍처는 가능한 가장 빠른 응답 시간을 제공합니다.\n- **확장성** . 다운스트림에서 발생하는 상황을 고려할 필요가 없으므로 확장할 서비스 인스턴스를 추가할 수 있습니다. 주제 라우팅 및 필터링은 명령 쿼리 책임 분리에서와 같이 빠르고 쉽게 서비스를 나눌 수 있습니다.\n- **민첩성** . 다른 서비스를 추가하려는 경우 이벤트를 구독하고 자체적으로 새 이벤트를 생성하도록 할 수 있습니다. 기존 서비스는 이러한 일이 발생했음을 모르거나 신경 쓰지 않으므로 영향을 미치지 않습니다.\n- 확장성 및 분산성이 뛰어납니다 **.**\n\n## 이 아키텍처를 사용하는 경우:\n\n- 여러 하위 시스템이 동일한 이벤트를 처리해야 합니다.\n- 최소 시간 지연으로 실시간 처리.\n- 시간 창에 따른 패턴 일치 또는 집계와 같은 복잡한 이벤트 처리.\n- IoT와 같은 대용량 및 고속 데이터.\n\n## 과제:\n\n- 배달 보장. 일부 시스템, 특히 IoT 시나리오에서는 이벤트가 전달되도록 보장하는 것이 중요합니다.\n- 이벤트를 순서대로 또는 정확히 한 번 처리합니다. 각 소비자 유형은 일반적으로 복원력과 확장성을 위해 여러 인스턴스에서 실행됩니다.\n\n## 게시/구독 및 이벤트 기반 아키텍처를 활성화하는 주요 도구:\n\n- [구글 클라우드 플랫폼 데이터 흐름](https://cloud.google.com/dataflow)\n- [IBM 이벤트 스트림](https://www.ibm.com/cloud/event-streams)\n- [AWS 키네시스](https://aws.amazon.com/kinesis/)\n- [날카로운](https://keen.io/)\n- [위안](https://solace.com/solutions/initiative/ipaas/)\n- [아파치 카프카](https://skolaparthi.com/apache-kafka-installation/)\n- 활성 MQ\n- 펄서\n\n## 이벤트 기반 마이크로서비스 아키텍처의 패턴:\n\n다음 패턴은 마이크로 서비스 개발의 이벤트 중심 방식으로 활용됩니다.\n\n- 이벤트 스트림\n- 이벤트 소싱\n- 다국어 지속성\n- 명령 쿼리 책임 분리(CQRS)\n\n결론:\n\n이 기사에서는 이벤트 기반 마이크로 서비스와 이벤트 기반 접근 방식을 사용하여 마이크로 서비스를 구축하는 방법에 대해 설명했습니다. 이벤트 기반 아키텍처에서 게시자는 이벤트를 게시하고 소비자는 이벤트를 구독합니다. 이러한 이벤트는 서비스가 분리된 방식으로 통신하는 데 도움이 됩니다.\n\n\nhttps://skolaparthi.com/event-driven-architecture/",
"json_metadata": "{\"tags\":[\"kr-dev\"],\"image\":[\"https://i0.wp.com/skolaparthi.com/wp-content/uploads/2022/10/image-3.png?resize=638%2C275&ssl=1\"],\"links\":[\"https://cloud.google.com/dataflow\",\"https://www.ibm.com/cloud/event-streams\",\"https://aws.amazon.com/kinesis/\",\"https://keen.io/\",\"https://solace.com/solutions/initiative/ipaas/\",\"https://skolaparthi.com/apache-kafka-installation/\",\"https://skolaparthi.com/event-driven-architecture/\"],\"app\":\"steemit/0.2\",\"format\":\"markdown\"}"
}
]
}anpigonupvoted (100.00%) @kormanocorp / 4og2em2023/04/20 02:00:51
anpigonupvoted (100.00%) @kormanocorp / 4og2em
2023/04/20 02:00:51
| voter | anpigon |
| author | kormanocorp |
| permlink | 4og2em |
| weight | 10000 (100.00%) |
| Transaction Info | Block #73914331/Trx 7f52578624908f8a33cfac6a50bf574cd1c4a0f0 |
View Raw JSON Data
{
"trx_id": "7f52578624908f8a33cfac6a50bf574cd1c4a0f0",
"block": 73914331,
"trx_in_block": 1,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-04-20T02:00:51",
"op": [
"vote",
{
"voter": "anpigon",
"author": "kormanocorp",
"permlink": "4og2em",
"weight": 10000
}
]
}kr-devupvoted (100.00%) @kormanocorp / 4og2em2023/04/20 00:06:06
kr-devupvoted (100.00%) @kormanocorp / 4og2em
2023/04/20 00:06:06
| voter | kr-dev |
| author | kormanocorp |
| permlink | 4og2em |
| weight | 10000 (100.00%) |
| Transaction Info | Block #73912047/Trx 29b7867f62dac253f4f1247d4c02d1a42ee93f92 |
View Raw JSON Data
{
"trx_id": "29b7867f62dac253f4f1247d4c02d1a42ee93f92",
"block": 73912047,
"trx_in_block": 0,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-04-20T00:06:06",
"op": [
"vote",
{
"voter": "kr-dev",
"author": "kormanocorp",
"permlink": "4og2em",
"weight": 10000
}
]
}kr-dev.cu4replied to @kormanocorp / adreply-16819488750812023/04/20 00:01:15
kr-dev.cu4replied to @kormanocorp / adreply-1681948875081
2023/04/20 00:01:15
| parent author | kormanocorp |
| parent permlink | 4og2em |
| author | kr-dev.cu4 |
| permlink | adreply-1681948875081 |
| title | |
| body | [광고] [STEEM 개발자 커뮤니티에 참여](/hive-137029/@kr-dev/x3v6n) 하시면, 다양한 혜택을 받을 수 있습니다. |
| json metadata | {"tags":["kr-dev"],"image":["https://miro.medium.com/v2/resize:fit:1050/1*RH0EOOfjRw3nr7vrhka4Yw.png","https://miro.medium.com/v2/resize:fit:756/1*m0EDDXHW65GHkwqa1hGLdw.jpeg","https://miro.medium.com/v2/resize:fit:1050/1*698jnL-oqs79vlNY_7ABTg.png","https://miro.medium.com/v2/resize:fit:1050/1*Ts0vUM2Pw8_EbhMUwjkh1A.png","https://miro.medium.com/v2/resize:fit:1050/1*VvRPbDcC4ibH_BIu66PP5Q.png","https://miro.medium.com/v2/resize:fit:750/1*4AJgIRw4cD_7IgnPenLx0g.jpeg","https://miro.medium.com/v2/resize:fit:969/1*gGXSdMAOwBUrX6ZkHQkF4g.png","https://miro.medium.com/v2/resize:fit:1050/1*trMNToEMMrpenbMD7GINRA.png"],"links":["https://javarevisited.blogspot.com/2012/06/jdbc-database-connection-pool-in-spring.html","https://www.java67.com/2019/04/top-10-spring-mvc-and-rest-annotations-examples-java.html","https://javarevisited.blogspot.com/2016/09/javasqlsqlexception-no-suitable-driver-mysql-jdbc-localhost.html","http://www.java67.com/2018/01/jdbc-how-to-get-row-and-column-count-from-resultset-java.html","http://javarevisited.blogspot.sg/2016/10/how-to-check-if-resultset-is-empty-in-Java-JDBC.html","https://softcover.s3.amazonaws.com/14738/python_book/images/connect_database3.jpg","https://medium.com/javarevisited/top-5-courses-to-learn-mysql-in-2020-4ffada70656f","https://medium.com/javarevisited/5-best-books-and-courses-to-learn-computer-networking-tcp-ip-and-udp-protocols-5a0e4dce75fa","https://medium.com/javarevisited/8-free-oracle-database-and-sql-courses-for-beginners-f4e9b25b33c4","https://vladmihalcea.com/wp-content/uploads/2014/04/connectionlifecycle.gif","https://raw.githubusercontent.com/practicalli/graphic-design/live/practicalli-clojure-webapps-database-postgres-no-connection-pool.png","https://raw.githubusercontent.com/practicalli/graphic-design/live/practicalli-clojure-webapps-database-postgres-connection-pool.png","http://javarevisited.blogspot.sg/2016/07/difference-in-string-pool-between-java6-java7.html","https://ejbvn.files.wordpress.com/2008/11/95.jpg?w=529","https://medium.com/javarevisited/10-best-java-microservices-courses-with-spring-boot-and-spring-cloud-6d04556bdfed","https://www.java67.com/2021/02/microservices-interview-questions-answers-java-spring.html","https://javarevisited.blogspot.com/2015/07/how-to-solve-javalangclassnotfoundexception-sun.jdbc.odbc.jdbcodbcdriver.html","https://medium.com/javarevisited/why-do-we-need-a-database-connection-pool-every-programmer-must-know-9f90e7c8e5af"],"app":"steemit/0.2","format":"markdown"} |
| Transaction Info | Block #73911950/Trx 5db9064ecf7cd8122b9e66400fab39d22a805cdb |
View Raw JSON Data
{
"trx_id": "5db9064ecf7cd8122b9e66400fab39d22a805cdb",
"block": 73911950,
"trx_in_block": 4,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-04-20T00:01:15",
"op": [
"comment",
{
"parent_author": "kormanocorp",
"parent_permlink": "4og2em",
"author": "kr-dev.cu4",
"permlink": "adreply-1681948875081",
"title": "",
"body": "[광고] [STEEM 개발자 커뮤니티에 참여](/hive-137029/@kr-dev/x3v6n) 하시면, 다양한 혜택을 받을 수 있습니다.",
"json_metadata": "{\"tags\":[\"kr-dev\"],\"image\":[\"https://miro.medium.com/v2/resize:fit:1050/1*RH0EOOfjRw3nr7vrhka4Yw.png\",\"https://miro.medium.com/v2/resize:fit:756/1*m0EDDXHW65GHkwqa1hGLdw.jpeg\",\"https://miro.medium.com/v2/resize:fit:1050/1*698jnL-oqs79vlNY_7ABTg.png\",\"https://miro.medium.com/v2/resize:fit:1050/1*Ts0vUM2Pw8_EbhMUwjkh1A.png\",\"https://miro.medium.com/v2/resize:fit:1050/1*VvRPbDcC4ibH_BIu66PP5Q.png\",\"https://miro.medium.com/v2/resize:fit:750/1*4AJgIRw4cD_7IgnPenLx0g.jpeg\",\"https://miro.medium.com/v2/resize:fit:969/1*gGXSdMAOwBUrX6ZkHQkF4g.png\",\"https://miro.medium.com/v2/resize:fit:1050/1*trMNToEMMrpenbMD7GINRA.png\"],\"links\":[\"https://javarevisited.blogspot.com/2012/06/jdbc-database-connection-pool-in-spring.html\",\"https://www.java67.com/2019/04/top-10-spring-mvc-and-rest-annotations-examples-java.html\",\"https://javarevisited.blogspot.com/2016/09/javasqlsqlexception-no-suitable-driver-mysql-jdbc-localhost.html\",\"http://www.java67.com/2018/01/jdbc-how-to-get-row-and-column-count-from-resultset-java.html\",\"http://javarevisited.blogspot.sg/2016/10/how-to-check-if-resultset-is-empty-in-Java-JDBC.html\",\"https://softcover.s3.amazonaws.com/14738/python_book/images/connect_database3.jpg\",\"https://medium.com/javarevisited/top-5-courses-to-learn-mysql-in-2020-4ffada70656f\",\"https://medium.com/javarevisited/5-best-books-and-courses-to-learn-computer-networking-tcp-ip-and-udp-protocols-5a0e4dce75fa\",\"https://medium.com/javarevisited/8-free-oracle-database-and-sql-courses-for-beginners-f4e9b25b33c4\",\"https://vladmihalcea.com/wp-content/uploads/2014/04/connectionlifecycle.gif\",\"https://raw.githubusercontent.com/practicalli/graphic-design/live/practicalli-clojure-webapps-database-postgres-no-connection-pool.png\",\"https://raw.githubusercontent.com/practicalli/graphic-design/live/practicalli-clojure-webapps-database-postgres-connection-pool.png\",\"http://javarevisited.blogspot.sg/2016/07/difference-in-string-pool-between-java6-java7.html\",\"https://ejbvn.files.wordpress.com/2008/11/95.jpg?w=529\",\"https://medium.com/javarevisited/10-best-java-microservices-courses-with-spring-boot-and-spring-cloud-6d04556bdfed\",\"https://www.java67.com/2021/02/microservices-interview-questions-answers-java-spring.html\",\"https://javarevisited.blogspot.com/2015/07/how-to-solve-javalangclassnotfoundexception-sun.jdbc.odbc.jdbcodbcdriver.html\",\"https://medium.com/javarevisited/why-do-we-need-a-database-connection-pool-every-programmer-must-know-9f90e7c8e5af\"],\"app\":\"steemit/0.2\",\"format\":\"markdown\"}"
}
]
}kormanocorppublished a new post: 4og2em2023/04/20 00:01:00
kormanocorppublished a new post: 4og2em
2023/04/20 00:01:00
| parent author | |
| parent permlink | kr-dev |
| author | kormanocorp |
| permlink | 4og2em |
| title | 데이터베이스 연결 풀이 필요한 이유는 무엇입니까? |
| body | 여러분, 안녕하세요. **이 기사에서는 데이터베이스 연결** 및 **수명 주기를** 살펴보겠습니다 . [**그런 다음 연결 풀**](https://javarevisited.blogspot.com/2012/06/jdbc-database-connection-pool-in-spring.html) 과 그 내부를 살펴보고 이를 사용해야 하는 이유를 살펴보겠습니다. 그런 다음 연결 풀을 배치할 위치에 대한 **디자인 패턴을** 살펴보겠습니다 . 그런 다음 데이터베이스 연결 풀에서 발생할 수 있는 **성능 문제** 를 살펴보고 **Java에서 사용되는 일반적인 연결 풀 프레임워크를** 살펴보는 것으로 기사를 마무리하겠습니다 . 시작하자. [  ](https://www.java67.com/2019/04/top-10-spring-mvc-and-rest-annotations-examples-java.html) ## 데이터베이스 연결이란 무엇입니까? 모든 소프트웨어 응용 프로그램은 데이터베이스에 데이터를 저장해야 하며 응용 프로그램이 **데이터베이스 서버 와 상호 작용하려면** **데이터베이스 연결이** 필요합니다 . 데이터베이스 [연결은](https://javarevisited.blogspot.com/2016/09/javasqlsqlexception-no-suitable-driver-mysql-jdbc-localhost.html) 애플리케이션 소프트웨어가 데이터베이스 서버 소프트웨어와 상호 작용하는 방법일 뿐이며 연결을 사용하여 **데이터베이스에 명령(SQL)을 보내고** [결과 집합](http://www.java67.com/2018/01/jdbc-how-to-get-row-and-column-count-from-resultset-java.html) 의 형태로 데이터베이스에서 응답을 얻습니다 .[](http://www.java67.com/2018/01/jdbc-how-to-get-row-and-column-count-from-resultset-java.html) [  ](http://javarevisited.blogspot.sg/2016/10/how-to-check-if-resultset-is-empty-in-Java-JDBC.html) 이미지 출처: [https://softcover.s3.amazonaws.com/14738/python\_book/images/connect\_database3.jpg](https://softcover.s3.amazonaws.com/14738/python_book/images/connect_database3.jpg) 데이터베이스 응용 프로그램은 일반적으로 응용 프로그램 서버와 다른 **데이터베이스 서버** 라는 **전용 서버 에서 실행됩니다.** 데이터베이스 응용 프로그램은 응용 프로그램 서버가 명령을 보내고 데이터를 받을 수 있는 데이터베이스 서버의 특정 포트에서 실행됩니다. 예: [MySQL 데이터베이스](https://medium.com/javarevisited/top-5-courses-to-learn-mysql-in-2020-4ffada70656f) 응용 프로그램은 데이터베이스 서버 시스템의 기본 포트 3306에서 실행됩니다. 이는 포트 8080에서 실행되는 백엔드 애플리케이션과 정확히 동일한 방식입니다.[](https://medium.com/javarevisited/top-5-courses-to-learn-mysql-in-2020-4ffada70656f) 브라우저나 모바일과 같은 클라이언트가 백엔드 애플리케이션에서 데이터를 요청할 때마다 백엔드 애플리케이션은 데이터를 검색하고 클라이언트에 응답하기 위해 데이터베이스와 통신해야 합니다. **백엔드 응용 프로그램이 데이터베이스 서버 응용 프로그램에 연결하려면 데이터베이스 서버 IP 및 포트** 정보와 연결 자격 증명과 함께 [**TCP-IP 프로토콜을**](https://medium.com/javarevisited/5-best-books-and-courses-to-learn-computer-networking-tcp-ip-and-udp-protocols-5a0e4dce75fa) 통해 호출해야 합니다 . 응용 프로그램 서버가 데이터를 얻기 위해 데이터베이스 서버에 연결하는 프로세스는 **데이터베이스 연결** 이라는 메커니즘을 통해 이루어집니다 . 데이터베이스 연결을 구축하려면 아래와 같이 **호스트, 포트 및 데이터베이스 이름, 드라이버, 사용자 이름 및 암호를** 포함하는 **서버 URL** 과 같은 정보를 제공해야 합니다. ``` db_url = jdbc:mysql://HOST/DATABASE db_driver = com.mysql.jdbc.Driver db_username = 사용자 이름 db_password = PASSWORD ``` 데이터베이스에 대한 연결이 생성되면 언제든지 열고 닫을 수 있으며 시간 초과를 설정할 수도 있습니다. 열린 연결이 없으면 [데이터베이스](https://medium.com/javarevisited/8-free-oracle-database-and-sql-courses-for-beginners-f4e9b25b33c4) 와 통신 할 수 없습니다. 데이터베이스 연결 생성은 많은 단계가 필요하므로 비용이 많이 드는 작업입니다. 데이터베이스 연결을 처리하는 방법은 전체 응용 프로그램을 만들거나 끊을 수 있으며 전체 응용 프로그램을 정지시킬 수도 있습니다. ## 데이터베이스 연결의 수명 주기 **위의 데이터베이스 연결에 대해 자세히 살펴보았으므로 연결의 수명 주기** , 즉 응용 프로그램 서버에서 데이터베이스에 대한 연결을 생성하는 단계를 살펴보겠습니다.  이미지 출처: [https://vladmihalcea.com/wp-content/uploads/2014/04/connectionlifecycle.gif](https://vladmihalcea.com/wp-content/uploads/2014/04/connectionlifecycle.gif) 1. _연결 문자열을 사용하여 데이터베이스에 대한_ **_연결 열기_** 2. _연결을 설정하기 전에 연결 문자열에 제공된_ **_사용자 자격 증명 인증_** 3. _데이터 읽기/쓰기를 위한_ **_TCP 소켓 생성 및 열기_** 4. _소켓을 통한_ **_데이터 송수신_** 5. **_데이터베이스 연결_** _닫기_ 6. **_TCP 소켓_** _닫기_ **여러 단계가 포함된 데이터베이스 시스템과의 연결을 생성하는 것은 비용과 시간이 많이 소요되는 작업이며 , 즉시 연결을** 생성하면 응용 **프로그램이 중단되고** 사용자는 페이지 로딩 속도가 느려집니다. 또한 애플리케이션에 대규모 사용자가 있고 모든 요청에 대해 연결을 열면 동시 연결 수가 증가하여 CPU **및 메모리 리소스가** 증가하여 매우 위험합니다. 이것이 매번 새 연결을 만들지 않고 기존 연결을 재사용하는 **연결 풀이** 있는 이유입니다 . 연결 풀이 없으면 각 클라이언트에 대해 **새 데이터베이스 연결이** 생성됩니다. 데이터베이스 연결이 생성될 때마다 어떤 일이 발생하는지 살펴보겠습니다.  이미지 출처: [https://raw.githubusercontent.com/practicalli/graphic-design/live/practicalli-clojure-webapps-database-postgres-no-connection-pool.png](https://raw.githubusercontent.com/practicalli/graphic-design/live/practicalli-clojure-webapps-database-postgres-no-connection-pool.png) 위의 다이어그램에서 RDMS 데이터베이스에 대한 새 연결이 생성되는 것을 볼 수 있습니다. 포스트그레스 백엔드 애플리케이션이 PostgreSQL 데이터베이스에 연결되면 데이터베이스 서버의 **상위 프로세스가** 새로 생성된 연결을 수신 대기하는 **작업자 프로세스를 생성합니다.** 매번 작업 프로세스를 생성하면 데이터베이스 서버에 추가 오버헤드가 발생합니다. 동시 연결 수가 증가함에 따라 데이터베이스 서버의 CPU 및 메모리 리소스도 증가하여 데이터베이스 서버가 충돌할 수 있습니다. ## 데이터베이스 연결 풀이란 무엇입니까? 위에서 응용 프로그램이 데이터베이스와 상호 작용해야 할 때마다 데이터베이스 연결을 생성, 사용 및 닫는 것은 비효율적임을 보았습니다. **연결 풀은** 즉시 연결 생성과 관련된 문제를 해결하고 시스템 성능을 개선하는 데 도움이 되는 기술입니다.  이미지 출처: [https://raw.githubusercontent.com/practicalli/graphic-design/live/practicalli-clojure-webapps-database-postgres-connection-pool.png](https://raw.githubusercontent.com/practicalli/graphic-design/live/practicalli-clojure-webapps-database-postgres-connection-pool.png) 연결 풀은 응용 프로그램 시작 시 미리 만든 다음 데이터베이스에 액세스해야 하는 응용 프로그램 간에 연결을 공유( _새 연결을 만드는 대신 )할 수_ **있는 데이터베이스 연결 풀 입니다.** 응용 프로그램이 초기화되면 제공자는 제공된 기본 연결을 생성합니다 **(예: 서버 인스턴스당 10개)** . 이를 풀에 유지합니다. 이 DB 연결 풀은 **Application Server의 메모리에 상주합니다.** 응용 프로그램에 연결이 필요한 경우 모든 요청에 대해 새 연결을 만드는 것은 비용이 많이 드는 작업이므로 풀의 이러한 연결은 재활용됩니다. 연결 풀에서 얻은 연결 개체는 **실제 데이터베이스 연결을 둘러싼 래퍼** 이며 풀의 연결을 사용하는 응용 프로그램은 기본 복잡성에서 숨겨집니다. 이러한 연결은 연결 풀 내부의 연결 수명 주기 관리를 담당하는 **풀 연결 관리자** 에 의해 관리됩니다 . 연결 풀의 접근 방식은 필요할 때만 응용 프로그램에서 연결을 열고 응용 프로그램의 전체 수명 동안 연결을 열린 상태로 유지하지 않고 작업이 완료되는 즉시 닫도록 권장합니다. 이 접근 방식을 사용하면 상대적으로 적은 수의 연결로 많은 수의 요청을 처리할 수 있으며 이를 **다중화** 라고도 합니다 . **연결 풀** 의 개념은 **서버 스레드 풀** 또는 이미 생성된 객체의 재사용성을 촉진하여 객체를 다시 생성하는 오버헤드를 줄여 애플리케이션 성능을 향상시키는 [**문자열 풀**](http://javarevisited.blogspot.sg/2016/07/difference-in-string-pool-between-java6-java7.html) 과 유사합니다 . ## 연결 풀에서 데이터베이스 연결을 어떻게 재사용합니까? 아래 다이어그램은 클라이언트가 풀의 연결을 사용하는 방법을 명확하게 나타냅니다.  이미지 출처: [https://ejbvn.files.wordpress.com/2008/11/95.jpg?w=529](https://ejbvn.files.wordpress.com/2008/11/95.jpg?w=529) ## 연결 풀이 필요한 이유는 무엇입니까? 데이터베이스 연결은 여러 가지 이유로 풀링됩니다. - 데이터베이스 연결은 생성하는 데 상대적으로 비용이 많이 들기 때문에 즉석에서 생성하는 대신 미리 생성하여 데이터베이스에 액세스해야 할 때마다 사용하도록 선택합니다. - 데이터베이스는 공유 리소스이므로 연결 풀을 만들고 모든 비즈니스 트랜잭션에서 공유하는 것이 좋습니다. - 데이터베이스 연결 풀은 데이터베이스에 보낼 수 있는 로드의 양을 제한합니다. ## 데이터베이스 연결 풀을 어디에 배치합니까? 아래와 같이 데이터베이스 연결 풀을 배치하는 두 가지 일반적인 방법이 있습니다. 1. **클라이언트 수준의 데이터베이스 연결 풀** 이것은 데이터베이스 연결 풀이 **서버/마이크로 서비스 애플리케이션의 메모리에 상주하는 기본 접근 방식입니다.** 특정 서버가 가동될 때마다 지정된 연결을 생성하고 메모리 내의 풀에 배치합니다. 이러한 연결은 이 서버 인스턴스에 도달하는 요청에만 사용할 수 있으며 다른 마이크로 서비스에서는 사용할 수 없습니다. 마찬가지로 모든 [마이크로 서비스](https://medium.com/javarevisited/10-best-java-microservices-courses-with-spring-boot-and-spring-cloud-6d04556bdfed) 인스턴스에는 자체 연결 풀이 있습니다. [  ](https://www.java67.com/2021/02/microservices-interview-questions-answers-java-spring.html) **장점** - 풀이 요청자와 동일한 상자에 있기 때문에 대기 시간이 짧습니다. - 연결이 하나의 클라이언트로 제한되므로 보안이 향상됩니다. **단점** - 마이크로서비스를 너무 많이 사용하면 연결을 모니터링하고 제어하기 어려울 수 있습니다. **2\. 별도의 미들웨어로서의 공유 데이터베이스 연결 풀** 이 접근법에서 우리는**별도의 미들웨어에 있는 연결 풀**또는 데이터베이스 서버 인스턴스에서 데이터베이스 연결 풀을 중앙 집중식으로 관리합니다. 연결은 **PgBouncer** 와 같은 소프트웨어에 의해 연결 풀에서 생성되며 모든 마이크로 서비스 인스턴스가 이를 공유합니다. [  ](https://javarevisited.blogspot.com/2015/07/how-to-solve-javalangclassnotfoundexception-sun.jdbc.odbc.jdbcodbcdriver.html) **장점:** - 유연성 — 데이터베이스 교체 가능 - 연결을 보다 쉽게 모니터링하고 제어할 수 있는 중앙 집중식 연결 제어 **단점:** - 새로운 레이어를 소개합니다. 대기 시간을 추가할 수 있음 - 모든 클라이언트에서 데이터베이스 호출에 대한 단일 실패 지점 - 레이어 간에 연결을 공유하므로 잠재적인 보안 문제 연결 풀을 배치할 위치 선택은 특정 요구 사항에 따라 다릅니다. 애플리케이션이 작은 경우 첫 번째 접근 방식을 사용하여 마이크로 서비스 인스턴스 내부에 배치하고 애플리케이션이 커지면 연결 풀을 중앙 집중식 위치로 이동하여 쉽게 관리할 수 있습니다. ## **연결 풀의 성능 문제** 데이터베이스에 대한 부하를 줄이기 위해 연결을 풀링합니다. 그렇지 않으면 너무 많은 부하로 데이터베이스가 포화되어 중단될 수 있기 때문입니다. 요점은 연결 풀을 원할 뿐만 아니라 풀 **크기도 올바르게 구성 해야 한다는 것입니다.** **연결이** **충분하지 않은** 경우 비즈니스 **트랜잭션은** 처리를 계속하기 전에 연결이 사용 가능해질 때까지 기다려야 합니다. **그러나 연결이 너무 많으면** 데이터베이스 에 너무 많은 부하를 보내고 있을 수 있으며 모든 애플리케이션 서버의 모든 비즈니스 트랜잭션이 데이터베이스 성능 저하로 인해 어려움을 겪을 수 있습니다. 트릭은 중간 지점을 찾는 것입니다 크기가 너무 작은 데이터베이스 연결 풀의 주요 증상은 대부분의 비즈니스 트랜잭션이 대기 중인 여러 비즈니스 트랜잭션에서 응답 시간이 증가하고 크기가 너무 큰 데이터베이스 연결 풀의 증상은 여러 비즈니스에서 응답 시간이 증가하는 것입니다. 대부분의 비즈니스 트랜잭션이 쿼리의 응답을 기다리고 있고 데이터베이스 시스템의 높은 리소스 사용률이 있습니다. 연결 풀이 오버플로되면 응용 프로그램 오류가 발생합니다. 이것은 응용 프로그램이 연결을 요청할 때 풀의 모든 연결이 사용 중인 경우에 발생할 수 있습니다. 예를 들어 너무 많은 클라이언트가 웹 사이트에 액세스하려고 시도하거나 하나 이상의 작업이 차단되거나 단순히 비효율적인 경우 응용 프로그램이 연결을 너무 오래 사용할 수 있습니다. 연결 풀은 CPU 및 메모리 사용량을 줄이는 데 도움이 되지만 효율적으로 사용해야 합니다. 고정된 연결 집합을 **풀 크기 라고 하며** **통합 테스트** 중에 사용되는 풀 크기를 테스트하여 **응용 프로그램별** 또는 서버 인스턴스별 최적 값을 찾는 것이 좋습니다. ## Java용 연결 풀 구현 다음은 Java용 데이터베이스 연결 풀 구현 중 일부입니다. 애플리케이션 내에서 라이브러리로 사용될 때 이러한 프레임워크는 애플리케이션의 연결 풀을 관리합니다. - **Apache Commons DBCP2** — Commons Pool 2 기반 JDBC 프레임워크로 JDBC 드라이버를 통해 더 나은 데이터베이스 연결 성능을 제공하고 JMX 지원 등의 기능을 제공합니다. - **Tomcat JDBC** — 고도의 동시 환경과 멀티 코어/CPU 시스템을 지원합니다. - **pgBouncer** — PostgreSQL용 경량 오픈 소스 미들웨어 연결 풀입니다. - **HikariCP** — 빠르고 간단하며 가볍고 안정적입니다. 이는 Java를 사용하는 Spring Boot 애플리케이션의 기본 설정입니다. 라이브러리의 크기는 130Kb에 불과합니다. - **c3p0** — 기존 JDBC 드라이버를 만들기 위한 사용하기 쉬운 라이브러리 다른 언어에 대한 다양한 연결 풀 라이브러리도 있습니다. 또한 필요한 경우 고유한 연결 풀을 구축할 수도 있습니다. ## 요약 **이 기사에서는 데이터베이스 연결과 수명주기가** 무엇인지 살펴 보았습니다 . 그런 다음 즉시 연결 생성의 단점을 확인한 다음 **데이터베이스** **연결 풀을** 사용해야 할 필요성을 확인했습니다 . 또한 연결 풀을 배치할 위치에 대한 디자인 패턴도 살펴보았습니다. 그런 다음 데이터베이스 연결 풀에서 발생할 수 있는 **성능 문제를** 살펴보고 Java에서 사용되는 일반적인 연결 풀 프레임워크를 살펴보는 것으로 기사를 마무리했습니다. https://medium.com/javarevisited/why-do-we-need-a-database-connection-pool-every-programmer-must-know-9f90e7c8e5af |
| json metadata | {"tags":["kr-dev"],"image":["https://miro.medium.com/v2/resize:fit:1050/1*RH0EOOfjRw3nr7vrhka4Yw.png","https://miro.medium.com/v2/resize:fit:756/1*m0EDDXHW65GHkwqa1hGLdw.jpeg","https://miro.medium.com/v2/resize:fit:1050/1*698jnL-oqs79vlNY_7ABTg.png","https://miro.medium.com/v2/resize:fit:1050/1*Ts0vUM2Pw8_EbhMUwjkh1A.png","https://miro.medium.com/v2/resize:fit:1050/1*VvRPbDcC4ibH_BIu66PP5Q.png","https://miro.medium.com/v2/resize:fit:750/1*4AJgIRw4cD_7IgnPenLx0g.jpeg","https://miro.medium.com/v2/resize:fit:969/1*gGXSdMAOwBUrX6ZkHQkF4g.png","https://miro.medium.com/v2/resize:fit:1050/1*trMNToEMMrpenbMD7GINRA.png"],"links":["https://javarevisited.blogspot.com/2012/06/jdbc-database-connection-pool-in-spring.html","https://www.java67.com/2019/04/top-10-spring-mvc-and-rest-annotations-examples-java.html","https://javarevisited.blogspot.com/2016/09/javasqlsqlexception-no-suitable-driver-mysql-jdbc-localhost.html","http://www.java67.com/2018/01/jdbc-how-to-get-row-and-column-count-from-resultset-java.html","http://javarevisited.blogspot.sg/2016/10/how-to-check-if-resultset-is-empty-in-Java-JDBC.html","https://softcover.s3.amazonaws.com/14738/python_book/images/connect_database3.jpg","https://medium.com/javarevisited/top-5-courses-to-learn-mysql-in-2020-4ffada70656f","https://medium.com/javarevisited/5-best-books-and-courses-to-learn-computer-networking-tcp-ip-and-udp-protocols-5a0e4dce75fa","https://medium.com/javarevisited/8-free-oracle-database-and-sql-courses-for-beginners-f4e9b25b33c4","https://vladmihalcea.com/wp-content/uploads/2014/04/connectionlifecycle.gif","https://raw.githubusercontent.com/practicalli/graphic-design/live/practicalli-clojure-webapps-database-postgres-no-connection-pool.png","https://raw.githubusercontent.com/practicalli/graphic-design/live/practicalli-clojure-webapps-database-postgres-connection-pool.png","http://javarevisited.blogspot.sg/2016/07/difference-in-string-pool-between-java6-java7.html","https://ejbvn.files.wordpress.com/2008/11/95.jpg?w=529","https://medium.com/javarevisited/10-best-java-microservices-courses-with-spring-boot-and-spring-cloud-6d04556bdfed","https://www.java67.com/2021/02/microservices-interview-questions-answers-java-spring.html","https://javarevisited.blogspot.com/2015/07/how-to-solve-javalangclassnotfoundexception-sun.jdbc.odbc.jdbcodbcdriver.html","https://medium.com/javarevisited/why-do-we-need-a-database-connection-pool-every-programmer-must-know-9f90e7c8e5af"],"app":"steemit/0.2","format":"markdown"} |
| Transaction Info | Block #73911945/Trx 8af7fc54286a63590f9091b04567f918244cd742 |
View Raw JSON Data
{
"trx_id": "8af7fc54286a63590f9091b04567f918244cd742",
"block": 73911945,
"trx_in_block": 4,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-04-20T00:01:00",
"op": [
"comment",
{
"parent_author": "",
"parent_permlink": "kr-dev",
"author": "kormanocorp",
"permlink": "4og2em",
"title": "데이터베이스 연결 풀이 필요한 이유는 무엇입니까?",
"body": "여러분, 안녕하세요. **이 기사에서는 데이터베이스 연결** 및 **수명 주기를** 살펴보겠습니다 . [**그런 다음 연결 풀**](https://javarevisited.blogspot.com/2012/06/jdbc-database-connection-pool-in-spring.html) 과 그 내부를 살펴보고 이를 사용해야 하는 이유를 살펴보겠습니다. 그런 다음 연결 풀을 배치할 위치에 대한 **디자인 패턴을** 살펴보겠습니다 . 그런 다음 데이터베이스 연결 풀에서 발생할 수 있는 **성능 문제** 를 살펴보고 **Java에서 사용되는 일반적인 연결 풀 프레임워크를** 살펴보는 것으로 기사를 마무리하겠습니다 . 시작하자.\n\n[\n\n\n\n](https://www.java67.com/2019/04/top-10-spring-mvc-and-rest-annotations-examples-java.html)\n\n## 데이터베이스 연결이란 무엇입니까?\n\n모든 소프트웨어 응용 프로그램은 데이터베이스에 데이터를 저장해야 하며 응용 프로그램이 **데이터베이스 서버 와 상호 작용하려면** **데이터베이스 연결이** 필요합니다 . 데이터베이스 [연결은](https://javarevisited.blogspot.com/2016/09/javasqlsqlexception-no-suitable-driver-mysql-jdbc-localhost.html) 애플리케이션 소프트웨어가 데이터베이스 서버 소프트웨어와 상호 작용하는 방법일 뿐이며 연결을 사용하여 **데이터베이스에 명령(SQL)을 보내고** [결과 집합](http://www.java67.com/2018/01/jdbc-how-to-get-row-and-column-count-from-resultset-java.html) 의 형태로 데이터베이스에서 응답을 얻습니다 .[](http://www.java67.com/2018/01/jdbc-how-to-get-row-and-column-count-from-resultset-java.html)\n\n[\n\n\n\n](http://javarevisited.blogspot.sg/2016/10/how-to-check-if-resultset-is-empty-in-Java-JDBC.html)\n\n이미지 출처: [https://softcover.s3.amazonaws.com/14738/python\\_book/images/connect\\_database3.jpg](https://softcover.s3.amazonaws.com/14738/python_book/images/connect_database3.jpg)\n\n데이터베이스 응용 프로그램은 일반적으로 응용 프로그램 서버와 다른 **데이터베이스 서버** 라는 **전용 서버 에서 실행됩니다.** 데이터베이스 응용 프로그램은 응용 프로그램 서버가 명령을 보내고 데이터를 받을 수 있는 데이터베이스 서버의 특정 포트에서 실행됩니다. 예: [MySQL 데이터베이스](https://medium.com/javarevisited/top-5-courses-to-learn-mysql-in-2020-4ffada70656f) 응용 프로그램은 데이터베이스 서버 시스템의 기본 포트 3306에서 실행됩니다. 이는 포트 8080에서 실행되는 백엔드 애플리케이션과 정확히 동일한 방식입니다.[](https://medium.com/javarevisited/top-5-courses-to-learn-mysql-in-2020-4ffada70656f)\n\n브라우저나 모바일과 같은 클라이언트가 백엔드 애플리케이션에서 데이터를 요청할 때마다 백엔드 애플리케이션은 데이터를 검색하고 클라이언트에 응답하기 위해 데이터베이스와 통신해야 합니다.\n\n**백엔드 응용 프로그램이 데이터베이스 서버 응용 프로그램에 연결하려면 데이터베이스 서버 IP 및 포트** 정보와 연결 자격 증명과 함께 [**TCP-IP 프로토콜을**](https://medium.com/javarevisited/5-best-books-and-courses-to-learn-computer-networking-tcp-ip-and-udp-protocols-5a0e4dce75fa) 통해 호출해야 합니다 . 응용 프로그램 서버가 데이터를 얻기 위해 데이터베이스 서버에 연결하는 프로세스는 **데이터베이스 연결** 이라는 메커니즘을 통해 이루어집니다 .\n\n데이터베이스 연결을 구축하려면 아래와 같이 **호스트, 포트 및 데이터베이스 이름, 드라이버, 사용자 이름 및 암호를** 포함하는 **서버 URL** 과 같은 정보를 제공해야 합니다.\n\n```\ndb_url = jdbc:mysql://HOST/DATABASE db_driver = com.mysql.jdbc.Driver db_username = 사용자 이름 db_password = PASSWORD\n```\n\n데이터베이스에 대한 연결이 생성되면 언제든지 열고 닫을 수 있으며 시간 초과를 설정할 수도 있습니다.\n\n열린 연결이 없으면 [데이터베이스](https://medium.com/javarevisited/8-free-oracle-database-and-sql-courses-for-beginners-f4e9b25b33c4) 와 통신 할 수 없습니다. 데이터베이스 연결 생성은 많은 단계가 필요하므로 비용이 많이 드는 작업입니다. 데이터베이스 연결을 처리하는 방법은 전체 응용 프로그램을 만들거나 끊을 수 있으며 전체 응용 프로그램을 정지시킬 수도 있습니다.\n\n## 데이터베이스 연결의 수명 주기\n\n**위의 데이터베이스 연결에 대해 자세히 살펴보았으므로 연결의 수명 주기** , 즉 응용 프로그램 서버에서 데이터베이스에 대한 연결을 생성하는 단계를 살펴보겠습니다.\n\n\n\n이미지 출처: [https://vladmihalcea.com/wp-content/uploads/2014/04/connectionlifecycle.gif](https://vladmihalcea.com/wp-content/uploads/2014/04/connectionlifecycle.gif)\n\n1. _연결 문자열을 사용하여 데이터베이스에 대한_ **_연결 열기_**\n2. _연결을 설정하기 전에 연결 문자열에 제공된_ **_사용자 자격 증명 인증_**\n3. _데이터 읽기/쓰기를 위한_ **_TCP 소켓 생성 및 열기_**\n4. _소켓을 통한_ **_데이터 송수신_**\n5. **_데이터베이스 연결_** _닫기_\n6. **_TCP 소켓_** _닫기_\n\n**여러 단계가 포함된 데이터베이스 시스템과의 연결을 생성하는 것은 비용과 시간이 많이 소요되는 작업이며 , 즉시 연결을** 생성하면 응용 **프로그램이 중단되고** 사용자는 페이지 로딩 속도가 느려집니다. 또한 애플리케이션에 대규모 사용자가 있고 모든 요청에 대해 연결을 열면 동시 연결 수가 증가하여 CPU **및 메모리 리소스가** 증가하여 매우 위험합니다.\n\n이것이 매번 새 연결을 만들지 않고 기존 연결을 재사용하는 **연결 풀이** 있는 이유입니다 . 연결 풀이 없으면 각 클라이언트에 대해 **새 데이터베이스 연결이** 생성됩니다.\n\n데이터베이스 연결이 생성될 때마다 어떤 일이 발생하는지 살펴보겠습니다.\n\n\n\n이미지 출처: [https://raw.githubusercontent.com/practicalli/graphic-design/live/practicalli-clojure-webapps-database-postgres-no-connection-pool.png](https://raw.githubusercontent.com/practicalli/graphic-design/live/practicalli-clojure-webapps-database-postgres-no-connection-pool.png)\n\n위의 다이어그램에서 RDMS 데이터베이스에 대한 새 연결이 생성되는 것을 볼 수 있습니다. 포스트그레스\n\n백엔드 애플리케이션이 PostgreSQL 데이터베이스에 연결되면 데이터베이스 서버의 **상위 프로세스가** 새로 생성된 연결을 수신 대기하는 **작업자 프로세스를 생성합니다.** 매번 작업 프로세스를 생성하면 데이터베이스 서버에 추가 오버헤드가 발생합니다. 동시 연결 수가 증가함에 따라 데이터베이스 서버의 CPU 및 메모리 리소스도 증가하여 데이터베이스 서버가 충돌할 수 있습니다.\n\n## 데이터베이스 연결 풀이란 무엇입니까?\n\n위에서 응용 프로그램이 데이터베이스와 상호 작용해야 할 때마다 데이터베이스 연결을 생성, 사용 및 닫는 것은 비효율적임을 보았습니다. **연결 풀은** 즉시 연결 생성과 관련된 문제를 해결하고 시스템 성능을 개선하는 데 도움이 되는 기술입니다.\n\n\n\n이미지 출처: [https://raw.githubusercontent.com/practicalli/graphic-design/live/practicalli-clojure-webapps-database-postgres-connection-pool.png](https://raw.githubusercontent.com/practicalli/graphic-design/live/practicalli-clojure-webapps-database-postgres-connection-pool.png)\n\n연결 풀은 응용 프로그램 시작 시 미리 만든 다음 데이터베이스에 액세스해야 하는 응용 프로그램 간에 연결을 공유( _새 연결을 만드는 대신 )할 수_ **있는 데이터베이스 연결 풀 입니다.**\n\n응용 프로그램이 초기화되면 제공자는 제공된 기본 연결을 생성합니다 **(예: 서버 인스턴스당 10개)** . 이를 풀에 유지합니다. 이 DB 연결 풀은 **Application Server의 메모리에 상주합니다.** 응용 프로그램에 연결이 필요한 경우 모든 요청에 대해 새 연결을 만드는 것은 비용이 많이 드는 작업이므로 풀의 이러한 연결은 재활용됩니다.\n\n연결 풀에서 얻은 연결 개체는 **실제 데이터베이스 연결을 둘러싼 래퍼** 이며 풀의 연결을 사용하는 응용 프로그램은 기본 복잡성에서 숨겨집니다. 이러한 연결은 연결 풀 내부의 연결 수명 주기 관리를 담당하는 **풀 연결 관리자** 에 의해 관리됩니다 .\n\n연결 풀의 접근 방식은 필요할 때만 응용 프로그램에서 연결을 열고 응용 프로그램의 전체 수명 동안 연결을 열린 상태로 유지하지 않고 작업이 완료되는 즉시 닫도록 권장합니다. 이 접근 방식을 사용하면 상대적으로 적은 수의 연결로 많은 수의 요청을 처리할 수 있으며 이를 **다중화** 라고도 합니다 .\n\n**연결 풀** 의 개념은 **서버 스레드 풀** 또는 이미 생성된 객체의 재사용성을 촉진하여 객체를 다시 생성하는 오버헤드를 줄여 애플리케이션 성능을 향상시키는 [**문자열 풀**](http://javarevisited.blogspot.sg/2016/07/difference-in-string-pool-between-java6-java7.html) 과 유사합니다 .\n\n## 연결 풀에서 데이터베이스 연결을 어떻게 재사용합니까?\n\n아래 다이어그램은 클라이언트가 풀의 연결을 사용하는 방법을 명확하게 나타냅니다.\n\n\n\n이미지 출처: [https://ejbvn.files.wordpress.com/2008/11/95.jpg?w=529](https://ejbvn.files.wordpress.com/2008/11/95.jpg?w=529)\n\n## 연결 풀이 필요한 이유는 무엇입니까?\n\n데이터베이스 연결은 여러 가지 이유로 풀링됩니다.\n\n- 데이터베이스 연결은 생성하는 데 상대적으로 비용이 많이 들기 때문에 즉석에서 생성하는 대신 미리 생성하여 데이터베이스에 액세스해야 할 때마다 사용하도록 선택합니다.\n- 데이터베이스는 공유 리소스이므로 연결 풀을 만들고 모든 비즈니스 트랜잭션에서 공유하는 것이 좋습니다.\n- 데이터베이스 연결 풀은 데이터베이스에 보낼 수 있는 로드의 양을 제한합니다.\n\n## 데이터베이스 연결 풀을 어디에 배치합니까?\n\n아래와 같이 데이터베이스 연결 풀을 배치하는 두 가지 일반적인 방법이 있습니다.\n\n1. **클라이언트 수준의 데이터베이스 연결 풀**\n\n이것은 데이터베이스 연결 풀이 **서버/마이크로 서비스 애플리케이션의 메모리에 상주하는 기본 접근 방식입니다.** 특정 서버가 가동될 때마다 지정된 연결을 생성하고 메모리 내의 풀에 배치합니다. 이러한 연결은 이 서버 인스턴스에 도달하는 요청에만 사용할 수 있으며 다른 마이크로 서비스에서는 사용할 수 없습니다. 마찬가지로 모든 [마이크로 서비스](https://medium.com/javarevisited/10-best-java-microservices-courses-with-spring-boot-and-spring-cloud-6d04556bdfed) 인스턴스에는 자체 연결 풀이 있습니다.\n\n[\n\n\n\n](https://www.java67.com/2021/02/microservices-interview-questions-answers-java-spring.html)\n\n**장점**\n\n- 풀이 요청자와 동일한 상자에 있기 때문에 대기 시간이 짧습니다.\n- 연결이 하나의 클라이언트로 제한되므로 보안이 향상됩니다.\n\n**단점**\n\n- 마이크로서비스를 너무 많이 사용하면 연결을 모니터링하고 제어하기 어려울 수 있습니다.\n\n**2\\. 별도의 미들웨어로서의 공유 데이터베이스 연결 풀**\n\n이 접근법에서 우리는**별도의 미들웨어에 있는 연결 풀**또는 데이터베이스 서버 인스턴스에서 데이터베이스 연결 풀을 중앙 집중식으로 관리합니다.\n\n연결은 **PgBouncer** 와 같은 소프트웨어에 의해 연결 풀에서 생성되며 모든 마이크로 서비스 인스턴스가 이를 공유합니다.\n\n[\n\n\n\n](https://javarevisited.blogspot.com/2015/07/how-to-solve-javalangclassnotfoundexception-sun.jdbc.odbc.jdbcodbcdriver.html)\n\n**장점:**\n\n- 유연성 — 데이터베이스 교체 가능\n- 연결을 보다 쉽게 모니터링하고 제어할 수 있는 중앙 집중식 연결 제어\n\n**단점:**\n\n- 새로운 레이어를 소개합니다. 대기 시간을 추가할 수 있음\n- 모든 클라이언트에서 데이터베이스 호출에 대한 단일 실패 지점\n- 레이어 간에 연결을 공유하므로 잠재적인 보안 문제\n\n연결 풀을 배치할 위치 선택은 특정 요구 사항에 따라 다릅니다. 애플리케이션이 작은 경우 첫 번째 접근 방식을 사용하여 마이크로 서비스 인스턴스 내부에 배치하고 애플리케이션이 커지면 연결 풀을 중앙 집중식 위치로 이동하여 쉽게 관리할 수 있습니다.\n\n## **연결 풀의 성능 문제**\n\n데이터베이스에 대한 부하를 줄이기 위해 연결을 풀링합니다. 그렇지 않으면 너무 많은 부하로 데이터베이스가 포화되어 중단될 수 있기 때문입니다. 요점은 연결 풀을 원할 뿐만 아니라 풀 **크기도 올바르게 구성 해야 한다는 것입니다.**\n\n**연결이** **충분하지 않은** 경우 비즈니스 **트랜잭션은** 처리를 계속하기 전에 연결이 사용 가능해질 때까지 기다려야 합니다.\n\n**그러나 연결이 너무 많으면** 데이터베이스 에 너무 많은 부하를 보내고 있을 수 있으며 모든 애플리케이션 서버의 모든 비즈니스 트랜잭션이 데이터베이스 성능 저하로 인해 어려움을 겪을 수 있습니다. 트릭은 중간 지점을 찾는 것입니다\n\n크기가 너무 작은 데이터베이스 연결 풀의 주요 증상은 대부분의 비즈니스 트랜잭션이 대기 중인 여러 비즈니스 트랜잭션에서 응답 시간이 증가하고 크기가 너무 큰 데이터베이스 연결 풀의 증상은 여러 비즈니스에서 응답 시간이 증가하는 것입니다. 대부분의 비즈니스 트랜잭션이 쿼리의 응답을 기다리고 있고 데이터베이스 시스템의 높은 리소스 사용률이 있습니다.\n\n연결 풀이 오버플로되면 응용 프로그램 오류가 발생합니다. 이것은 응용 프로그램이 연결을 요청할 때 풀의 모든 연결이 사용 중인 경우에 발생할 수 있습니다. 예를 들어 너무 많은 클라이언트가 웹 사이트에 액세스하려고 시도하거나 하나 이상의 작업이 차단되거나 단순히 비효율적인 경우 응용 프로그램이 연결을 너무 오래 사용할 수 있습니다.\n\n연결 풀은 CPU 및 메모리 사용량을 줄이는 데 도움이 되지만 효율적으로 사용해야 합니다. 고정된 연결 집합을 **풀 크기 라고 하며** **통합 테스트** 중에 사용되는 풀 크기를 테스트하여 **응용 프로그램별** 또는 서버 인스턴스별 최적 값을 찾는 것이 좋습니다.\n\n## Java용 연결 풀 구현\n\n다음은 Java용 데이터베이스 연결 풀 구현 중 일부입니다. 애플리케이션 내에서 라이브러리로 사용될 때 이러한 프레임워크는 애플리케이션의 연결 풀을 관리합니다.\n\n- **Apache Commons DBCP2** — Commons Pool 2 기반 JDBC 프레임워크로 JDBC 드라이버를 통해 더 나은 데이터베이스 연결 성능을 제공하고 JMX 지원 등의 기능을 제공합니다.\n- **Tomcat JDBC** — 고도의 동시 환경과 멀티 코어/CPU 시스템을 지원합니다.\n- **pgBouncer** — PostgreSQL용 경량 오픈 소스 미들웨어 연결 풀입니다.\n- **HikariCP** — 빠르고 간단하며 가볍고 안정적입니다. 이는 Java를 사용하는 Spring Boot 애플리케이션의 기본 설정입니다. 라이브러리의 크기는 130Kb에 불과합니다.\n- **c3p0** — 기존 JDBC 드라이버를 만들기 위한 사용하기 쉬운 라이브러리\n\n다른 언어에 대한 다양한 연결 풀 라이브러리도 있습니다. 또한 필요한 경우 고유한 연결 풀을 구축할 수도 있습니다.\n\n## 요약\n\n**이 기사에서는 데이터베이스 연결과 수명주기가** 무엇인지 살펴 보았습니다 . 그런 다음 즉시 연결 생성의 단점을 확인한 다음 **데이터베이스** **연결 풀을** 사용해야 할 필요성을 확인했습니다 . 또한 연결 풀을 배치할 위치에 대한 디자인 패턴도 살펴보았습니다. 그런 다음 데이터베이스 연결 풀에서 발생할 수 있는 **성능 문제를** 살펴보고 Java에서 사용되는 일반적인 연결 풀 프레임워크를 살펴보는 것으로 기사를 마무리했습니다.\n\nhttps://medium.com/javarevisited/why-do-we-need-a-database-connection-pool-every-programmer-must-know-9f90e7c8e5af",
"json_metadata": "{\"tags\":[\"kr-dev\"],\"image\":[\"https://miro.medium.com/v2/resize:fit:1050/1*RH0EOOfjRw3nr7vrhka4Yw.png\",\"https://miro.medium.com/v2/resize:fit:756/1*m0EDDXHW65GHkwqa1hGLdw.jpeg\",\"https://miro.medium.com/v2/resize:fit:1050/1*698jnL-oqs79vlNY_7ABTg.png\",\"https://miro.medium.com/v2/resize:fit:1050/1*Ts0vUM2Pw8_EbhMUwjkh1A.png\",\"https://miro.medium.com/v2/resize:fit:1050/1*VvRPbDcC4ibH_BIu66PP5Q.png\",\"https://miro.medium.com/v2/resize:fit:750/1*4AJgIRw4cD_7IgnPenLx0g.jpeg\",\"https://miro.medium.com/v2/resize:fit:969/1*gGXSdMAOwBUrX6ZkHQkF4g.png\",\"https://miro.medium.com/v2/resize:fit:1050/1*trMNToEMMrpenbMD7GINRA.png\"],\"links\":[\"https://javarevisited.blogspot.com/2012/06/jdbc-database-connection-pool-in-spring.html\",\"https://www.java67.com/2019/04/top-10-spring-mvc-and-rest-annotations-examples-java.html\",\"https://javarevisited.blogspot.com/2016/09/javasqlsqlexception-no-suitable-driver-mysql-jdbc-localhost.html\",\"http://www.java67.com/2018/01/jdbc-how-to-get-row-and-column-count-from-resultset-java.html\",\"http://javarevisited.blogspot.sg/2016/10/how-to-check-if-resultset-is-empty-in-Java-JDBC.html\",\"https://softcover.s3.amazonaws.com/14738/python_book/images/connect_database3.jpg\",\"https://medium.com/javarevisited/top-5-courses-to-learn-mysql-in-2020-4ffada70656f\",\"https://medium.com/javarevisited/5-best-books-and-courses-to-learn-computer-networking-tcp-ip-and-udp-protocols-5a0e4dce75fa\",\"https://medium.com/javarevisited/8-free-oracle-database-and-sql-courses-for-beginners-f4e9b25b33c4\",\"https://vladmihalcea.com/wp-content/uploads/2014/04/connectionlifecycle.gif\",\"https://raw.githubusercontent.com/practicalli/graphic-design/live/practicalli-clojure-webapps-database-postgres-no-connection-pool.png\",\"https://raw.githubusercontent.com/practicalli/graphic-design/live/practicalli-clojure-webapps-database-postgres-connection-pool.png\",\"http://javarevisited.blogspot.sg/2016/07/difference-in-string-pool-between-java6-java7.html\",\"https://ejbvn.files.wordpress.com/2008/11/95.jpg?w=529\",\"https://medium.com/javarevisited/10-best-java-microservices-courses-with-spring-boot-and-spring-cloud-6d04556bdfed\",\"https://www.java67.com/2021/02/microservices-interview-questions-answers-java-spring.html\",\"https://javarevisited.blogspot.com/2015/07/how-to-solve-javalangclassnotfoundexception-sun.jdbc.odbc.jdbcodbcdriver.html\",\"https://medium.com/javarevisited/why-do-we-need-a-database-connection-pool-every-programmer-must-know-9f90e7c8e5af\"],\"app\":\"steemit/0.2\",\"format\":\"markdown\"}"
}
]
}anpigonupvoted (100.00%) @kormanocorp / api-gateway-bff-backend-for-frontend2023/04/19 07:47:54
anpigonupvoted (100.00%) @kormanocorp / api-gateway-bff-backend-for-frontend
2023/04/19 07:47:54
| voter | anpigon |
| author | kormanocorp |
| permlink | api-gateway-bff-backend-for-frontend |
| weight | 10000 (100.00%) |
| Transaction Info | Block #73892566/Trx 3a60bf8dbc120822ffdff3515477390d8a32f29d |
View Raw JSON Data
{
"trx_id": "3a60bf8dbc120822ffdff3515477390d8a32f29d",
"block": 73892566,
"trx_in_block": 1,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-04-19T07:47:54",
"op": [
"vote",
{
"voter": "anpigon",
"author": "kormanocorp",
"permlink": "api-gateway-bff-backend-for-frontend",
"weight": 10000
}
]
}kr-devupvoted (100.00%) @kormanocorp / api-gateway-bff-backend-for-frontend2023/04/19 07:37:12
kr-devupvoted (100.00%) @kormanocorp / api-gateway-bff-backend-for-frontend
2023/04/19 07:37:12
| voter | kr-dev |
| author | kormanocorp |
| permlink | api-gateway-bff-backend-for-frontend |
| weight | 10000 (100.00%) |
| Transaction Info | Block #73892353/Trx 83ef51c3daa086cc95c4390f74ff5436a1da3c6e |
View Raw JSON Data
{
"trx_id": "83ef51c3daa086cc95c4390f74ff5436a1da3c6e",
"block": 73892353,
"trx_in_block": 0,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-04-19T07:37:12",
"op": [
"vote",
{
"voter": "kr-dev",
"author": "kormanocorp",
"permlink": "api-gateway-bff-backend-for-frontend",
"weight": 10000
}
]
}kr-dev.cu2replied to @kormanocorp / adreply-16818895408272023/04/19 07:32:21
kr-dev.cu2replied to @kormanocorp / adreply-1681889540827
2023/04/19 07:32:21
| parent author | kormanocorp |
| parent permlink | api-gateway-bff-backend-for-frontend |
| author | kr-dev.cu2 |
| permlink | adreply-1681889540827 |
| title | |
| body | [광고] [STEEM 개발자 커뮤니티에 참여](/hive-137029/@kr-dev/x3v6n) 하시면, 다양한 혜택을 받을 수 있습니다. |
| json metadata | {"tags":["kr-dev"],"image":["https://miro.medium.com/v2/resize:fit:1050/1*ljR5uswvXDpoCAcPLDUmyw.png","https://miro.medium.com/v2/resize:fit:1050/1*ShUrqBepv_1bcYrUSz6ygg.png","https://miro.medium.com/v2/resize:fit:900/1*botmiI62309_1bf3cORRug.png","https://miro.medium.com/v2/resize:fit:923/1*eaEBUnX24pBz9uvUQtWV2A.jpeg","https://miro.medium.com/v2/resize:fit:1050/0*sKKvCHKBQbNac-uY.png"],"links":["https://medium.com/javarevisited/10-best-java-microservices-courses-with-spring-boot-and-spring-cloud-6d04556bdfed","https://javarevisited.blogspot.com/2021/09/microservices-design-patterns-principles.html","https://raw.githubusercontent.com/abpio/abp-commercial-docs/rel-4.3/en/images/gateway-bff.png","https://javarevisited.blogspot.com/2011/05/top-10-tips-on-logging-in-java.html","https://medium.com/javarevisited/8-best-online-courses-to-learn-service-oriented-soa-and-microservices-architecture-94c01d6b94e6","https://www.java67.com/2021/02/microservices-interview-questions-answers-java-spring.html","https://learn.microsoft.com/en-us/dotnet/architecture/microservices/architect-microservice-container-applications/media/direct-client-to-microservice-communication.png","https://hub.packtpub.com/wp-content/uploads/2018/02/B04926_02_05-600x427.png","https://educosta.dev/wp-content/uploads/API-Gatey-Architecture.jpg","https://medium.com/javarevisited/everything-you-need-to-know-about-iot-internet-of-things-1b481e917edc","https://tsh.io/wp-content/uploads/2019/09/backend-for-frontend-design-pattern.png","https://medium.com/javarevisited/api-gateway-vs-backend-for-frontend-bff-everything-you-need-to-know-90154a1e693f"],"app":"steemit/0.2","format":"markdown"} |
| Transaction Info | Block #73892257/Trx 779cc2bc4f047f2308026efc07f353af40a1f510 |
View Raw JSON Data
{
"trx_id": "779cc2bc4f047f2308026efc07f353af40a1f510",
"block": 73892257,
"trx_in_block": 2,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-04-19T07:32:21",
"op": [
"comment",
{
"parent_author": "kormanocorp",
"parent_permlink": "api-gateway-bff-backend-for-frontend",
"author": "kr-dev.cu2",
"permlink": "adreply-1681889540827",
"title": "",
"body": "[광고] [STEEM 개발자 커뮤니티에 참여](/hive-137029/@kr-dev/x3v6n) 하시면, 다양한 혜택을 받을 수 있습니다.",
"json_metadata": "{\"tags\":[\"kr-dev\"],\"image\":[\"https://miro.medium.com/v2/resize:fit:1050/1*ljR5uswvXDpoCAcPLDUmyw.png\",\"https://miro.medium.com/v2/resize:fit:1050/1*ShUrqBepv_1bcYrUSz6ygg.png\",\"https://miro.medium.com/v2/resize:fit:900/1*botmiI62309_1bf3cORRug.png\",\"https://miro.medium.com/v2/resize:fit:923/1*eaEBUnX24pBz9uvUQtWV2A.jpeg\",\"https://miro.medium.com/v2/resize:fit:1050/0*sKKvCHKBQbNac-uY.png\"],\"links\":[\"https://medium.com/javarevisited/10-best-java-microservices-courses-with-spring-boot-and-spring-cloud-6d04556bdfed\",\"https://javarevisited.blogspot.com/2021/09/microservices-design-patterns-principles.html\",\"https://raw.githubusercontent.com/abpio/abp-commercial-docs/rel-4.3/en/images/gateway-bff.png\",\"https://javarevisited.blogspot.com/2011/05/top-10-tips-on-logging-in-java.html\",\"https://medium.com/javarevisited/8-best-online-courses-to-learn-service-oriented-soa-and-microservices-architecture-94c01d6b94e6\",\"https://www.java67.com/2021/02/microservices-interview-questions-answers-java-spring.html\",\"https://learn.microsoft.com/en-us/dotnet/architecture/microservices/architect-microservice-container-applications/media/direct-client-to-microservice-communication.png\",\"https://hub.packtpub.com/wp-content/uploads/2018/02/B04926_02_05-600x427.png\",\"https://educosta.dev/wp-content/uploads/API-Gatey-Architecture.jpg\",\"https://medium.com/javarevisited/everything-you-need-to-know-about-iot-internet-of-things-1b481e917edc\",\"https://tsh.io/wp-content/uploads/2019/09/backend-for-frontend-design-pattern.png\",\"https://medium.com/javarevisited/api-gateway-vs-backend-for-frontend-bff-everything-you-need-to-know-90154a1e693f\"],\"app\":\"steemit/0.2\",\"format\":\"markdown\"}"
}
]
}kormanocorppublished a new post: api-gateway-bff-backend-for-frontend2023/04/19 07:32:06
kormanocorppublished a new post: api-gateway-bff-backend-for-frontend
2023/04/19 07:32:06
| parent author | |
| parent permlink | kr-dev |
| author | kormanocorp |
| permlink | api-gateway-bff-backend-for-frontend |
| title | API Gateway와 BFF(Backend For Frontend) |
| body | 여러분, 안녕하세요. **이 기사에서는 API 게이트웨이 가 무엇이며** [**마이크로 서비스**](https://medium.com/javarevisited/10-best-java-microservices-courses-with-spring-boot-and-spring-cloud-6d04556bdfed) [**아키텍처**](https://medium.com/javarevisited/10-best-java-microservices-courses-with-spring-boot-and-spring-cloud-6d04556bdfed) 에서 **클라이언트-서버** 통신 에 API 게이트웨이가 어떻게 사용되는지 살펴보겠습니다 . 또한 API 게이트웨이 패턴의 장점과 단점도 살펴보겠습니다. 그런 다음 API Gateway 패턴의 변형인 **Front End용 Backend** 라는 패턴을 살펴보고 API GW와 BFF가 필요한 시점을 살펴보며 글을 마무리하겠습니다. 시작하자.[](https://medium.com/javarevisited/10-best-java-microservices-courses-with-spring-boot-and-spring-cloud-6d04556bdfed) [  ](https://javarevisited.blogspot.com/2021/09/microservices-design-patterns-principles.html) 이미지 출처: [https://raw.githubusercontent.com/abpio/abp-commercial-docs/rel-4.3/en/images/gateway-bff.png](https://raw.githubusercontent.com/abpio/abp-commercial-docs/rel-4.3/en/images/gateway-bff.png) ## API 게이트웨이란 무엇입니까? API 게이트웨이는 클라이언트가 상호 작용할 수 있도록 단일 위치에서 많은 기능을 처리하는 서버입니다. 또한 클라이언트 애플리케이션과 백엔드 마이크로서비스 아키텍처 간의 **리버스 프록시** 로도 작동합니다. ``` 리버스 프록시 는 웹 서버 앞에 있는 서버 구성 요소 이며 클라이언트 요청 을 해당 웹 서버 로 전달 하고 응답 을 다시 클라이언트 로 보내는 역할 을 합니다 . 리버스 프록시 는 추가 수준 의 추상화 및 제어 를 제공 하여 _ _ _ _ _ _ 클라이언트 와 서버 간의 원활한 네트워크 트래픽 흐름 . _ ``` 서버 API를 호출하는 여러 클라이언트가 있을 수 있으며 API 게이트웨이는 요청을 관련 마이크로 서비스로 라우팅한 다음 응답을 받아 클라이언트로 보내는 구성 요소입니다. 모든 단일 마이크로 서비스에서 이러한 기능을 구현하는 대신 **보안,** [**로깅**](https://javarevisited.blogspot.com/2011/05/top-10-tips-on-logging-in-java.html) **, 캐싱** 등과 같은 모든 교차 기능을 단일 위치에서 처리합니다 . _또한 클라이언트가 통신할 수 있는 단일 엔드포인트를 사용하여 여러 마이크로 서비스 집계에서_ 데이터를 통합하고 집계할 수 있습니다 . [_마이크로서비스 아키텍처가_](https://medium.com/javarevisited/8-best-online-courses-to-learn-service-oriented-soa-and-microservices-architecture-94c01d6b94e6) 발전하기 전에는 대부분의 시스템이 모노리스 패턴을 사용했으며 단일 또는 두 개의 서버에서 교차 절단 문제를 처리할 수도 있었습니다. 그러나 마이크로서비스를 사용하면 더 큰 메모리 공간으로 인해 시스템 성능이 저하되어 작업 속도가 느려지는 각 마이크로서비스의 교차 절단 문제를 처리할 여유가 없습니다. ## API 게이트웨이를 사용하지 않고 클라이언트에서 마이크로서비스로의 통신 API 게이트웨이가 없는 마이크로서비스 아키텍처의 시나리오를 살펴보겠습니다. 아래 다이어그램에서 클라이언트는 API 게이트웨이 없이 마이크로서비스와 직접 통신합니다. [  ](https://www.java67.com/2021/02/microservices-interview-questions-answers-java-spring.html) 이미지 출처: [https://learn.microsoft.com/en-us/dotnet/architecture/microservices/architect-microservice-container-applications/media/direct-client-to-microservice-communication.png](https://learn.microsoft.com/en-us/dotnet/architecture/microservices/architect-microservice-container-applications/media/direct-client-to-microservice-communication.png) 거기에는 많은 단점이 있습니다. 1. 마이크로서비스가 커지고 시스템이 복잡해지면 클라이언트는 모든 엔드포인트를 기억해야 합니다. 2. 클라이언트는 대기 시간을 증가시킬 수 있고 사용자에게 좋은 경험을 제공하지 않을 수 있는 데이터를 로드하기 위해 다양한 마이크로 서비스에 대한 많은 API 호출을 수행해야 합니다. 3. 위에서 논의한 바와 같이 권한 부여, 로깅, 캐싱 등과 같은 교차 편집 문제는 모든 마이크로 서비스에서 구현되어야 합니다. 4. 일반적으로 마이크로서비스는 인터넷에 연결되어 있지 않으며 사설 IP가 있는 사설 서브넷 내부에 배치됩니다. 대중에게 마이크로서비스를 공개하는 것은 공격자에게 문제를 요구하는 것입니다. 5. 클라이언트는 AMQP 또는 이진 프로토콜과 같은 특정 프로토콜만 지원하는 마이크로 서비스와 통신하지 못할 수 있습니다. ## 마이크로서비스 아키텍처에서 API 게이트웨이를 사용한 클라이언트 서버 통신  이미지 출처: [https://hub.packtpub.com/wp-content/uploads/2018/02/B04926\_02\_05-600x427.png](https://hub.packtpub.com/wp-content/uploads/2018/02/B04926_02_05-600x427.png) 우리는 마이크로서비스 아키텍처에서 API 게이트웨이를 사용하지 않으면 많은 단점을 보았습니다. 이러한 단점을 없애고 우리의 삶을 편리하게 만들기 위해서는 Client와 Services 사이의 Layer로서 API Gateway가 반드시 필요합니다. ## API 게이트웨이의 이점  이미지 출처: [https://educosta.dev/wp-content/uploads/API-Gatey-Architecture.jpg](https://educosta.dev/wp-content/uploads/API-Gatey-Architecture.jpg) API 게이트웨이는 많은 일을 할 수 있으며 아래에서 이점을 살펴보겠습니다. 1\. 백엔드 시스템의 복잡성으로부터 **클라이언트 추상화** 2\. 전체 시스템에 대한 사용자 **인증 및 권한 부여를** 한 곳에서 처리 3\. 필요한 형식에 따라 **요청 및 응답 변환** 4\. 백엔드 서비스에 대한 부하를 방지하기 위해 각 API에 대한 **속도 제한** 5\. DDOS 공격을 방지하기 위해 단일 사용자의 **API 요청 제한** 6\. 반복되는 요청에 대한 **응답을 Caching하여** 서비스의 부하를 줄입니다. **7\. 다양한 프로토콜** 지원 8\. **개별 API를 측정하여** 사용량에 따라 클라이언트에 청구 9\. 단일 위치에서 시스템에 대한 API 호출 **로깅 및 추적** 10\. **오류 처리** 11\. 마이크로서비스 전반에 걸쳐 **데이터를 집계** 하고 단일 API 호출로 클라이언트에 데이터를 응답합니다. 이렇게 하면 클라이언트가 만들어야 하는 여러 API 호출을 피할 수 있습니다. ## API 게이트웨이의 단점 모든 장점에는 단점이 있으며 API 게이트웨이도 마찬가지입니다. 1. API 게이트웨이는 전체 시스템의 **단일 실패 지점이 될 수 있습니다.** 2\. API 게이트웨이에서 너무 많은 작업을 수행하면 **성능 문제가 발생하고 API 호출 대기 시간이 늘어날** 수 있습니다 . 3\. 마이크로서비스가 너무 많으면 **너무 많은 경로를 관리하는** 것이 복잡해질 수 있습니다. 4\. 클라이언트에서 서버로의 **API 호출에는** 항상 추가 홉이 있습니다 . 5\. 관련된 추가 서버 구성 요소로 인한 **추가 비용** ## **FrontEnd(BFF) 패턴용 백엔드란 무엇입니까?** 우리는 API Gateway에 대해 자세히 보았고 웹이나 모바일과 같은 단일 클라이언트가 있는 경우 이 접근 방식이 좋습니다. [우리 애플리케이션이 웹, 모바일, IoT](https://medium.com/javarevisited/everything-you-need-to-know-about-iot-internet-of-things-1b481e917edc) 등과 같은 여러 클라이언트에서 사용되는 경우 모든 유형의 클라이언트에 대해 단일 API 게이트웨이를 사용하는 것은 좋지 않습니다. 이는 더 커질 수 있으며 API 게이트웨이 서비스를 하나의 큰 Monolith 서비스로 만들어 부풀릴 수 있습니다. 이러한 유형의 시나리오에 대한 더 나은 접근 방식은 각 클라이언트 유형에 대해 별도의 API 게이트웨이를 사용하는 것입니다. 이 아키텍처 패턴은 BFF(Backend for FrontEnd) 패턴이라고 하며 유행어가 되었습니다. > _BFF 패턴은 API 게이트웨이 패턴의 변형인 아키텍처 패러다임_ 이며구성하다[데스크톱, 브라우저, 기본 모바일 애플리케이션, IOT](https://medium.com/javarevisited/everything-you-need-to-know-about-iot-internet-of-things-1b481e917edc) 장치 등과 같은 특정 프런트 엔드 애플리케이션의 요구 사항을 충족하도록 설계된 여러 백엔드  이미지 출처: [https://tsh.io/wp-content/uploads/2019/09/backend-for-frontend-design-pattern.png](https://tsh.io/wp-content/uploads/2019/09/backend-for-frontend-design-pattern.png) ## 언제 API GW와 BFF를 사용해야 합니까? 음, 이것은 열린 질문이며 전적으로 조직에 달려 있습니다. 1\. 응용 프로그램이 새로운 경우 사전에 사용법을 알 수 없습니다. 따라서 처음에는 API 게이트웨이가 단일 구성 요소가 될 수 있으며 클라이언트 전체에서 사용량이 증가하면 클라이언트용 API를 BFF와 같은 개별 구성 요소로 이동할 수 있습니다. 2\. 클라이언트마다 다른 유형의 인증이 필요한 경우 단일 API GW를 사용하는 것보다 BFF를 사용하는 것이 확실히 좋습니다. 3\. 클라이언트 응용 프로그램이 다른 팀에서 소유하는 경우 BFF를 사용하는 것이 합리적입니다. 그렇지 않으면 단일 API GW가 있을 때 많은 상호 작용과 오버헤드가 발생합니다. **이 기사에서는 API 게이트웨이가** 무엇인지 살펴보고 API 게이트웨이를 사용하거나 사용하지 않고 클라이언트와 마이크로 서비스 간의 통신 시나리오를 살펴보았습니다. API Gateway 패턴의 장단점도 살펴보았습니다. 그런 다음 API Gateway 패턴의 변형인 **Backend for Front End** 라는 패턴을 살펴보고 API GW와 BFF를 사용해야 하는 경우를 살펴보며 글을 마무리했습니다. https://medium.com/javarevisited/api-gateway-vs-backend-for-frontend-bff-everything-you-need-to-know-90154a1e693f |
| json metadata | {"tags":["kr-dev"],"image":["https://miro.medium.com/v2/resize:fit:1050/1*ljR5uswvXDpoCAcPLDUmyw.png","https://miro.medium.com/v2/resize:fit:1050/1*ShUrqBepv_1bcYrUSz6ygg.png","https://miro.medium.com/v2/resize:fit:900/1*botmiI62309_1bf3cORRug.png","https://miro.medium.com/v2/resize:fit:923/1*eaEBUnX24pBz9uvUQtWV2A.jpeg","https://miro.medium.com/v2/resize:fit:1050/0*sKKvCHKBQbNac-uY.png"],"links":["https://medium.com/javarevisited/10-best-java-microservices-courses-with-spring-boot-and-spring-cloud-6d04556bdfed","https://javarevisited.blogspot.com/2021/09/microservices-design-patterns-principles.html","https://raw.githubusercontent.com/abpio/abp-commercial-docs/rel-4.3/en/images/gateway-bff.png","https://javarevisited.blogspot.com/2011/05/top-10-tips-on-logging-in-java.html","https://medium.com/javarevisited/8-best-online-courses-to-learn-service-oriented-soa-and-microservices-architecture-94c01d6b94e6","https://www.java67.com/2021/02/microservices-interview-questions-answers-java-spring.html","https://learn.microsoft.com/en-us/dotnet/architecture/microservices/architect-microservice-container-applications/media/direct-client-to-microservice-communication.png","https://hub.packtpub.com/wp-content/uploads/2018/02/B04926_02_05-600x427.png","https://educosta.dev/wp-content/uploads/API-Gatey-Architecture.jpg","https://medium.com/javarevisited/everything-you-need-to-know-about-iot-internet-of-things-1b481e917edc","https://tsh.io/wp-content/uploads/2019/09/backend-for-frontend-design-pattern.png","https://medium.com/javarevisited/api-gateway-vs-backend-for-frontend-bff-everything-you-need-to-know-90154a1e693f"],"app":"steemit/0.2","format":"markdown"} |
| Transaction Info | Block #73892252/Trx 66a1b0618865309ac267dfd1ef7a5bdc2fae23aa |
View Raw JSON Data
{
"trx_id": "66a1b0618865309ac267dfd1ef7a5bdc2fae23aa",
"block": 73892252,
"trx_in_block": 3,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-04-19T07:32:06",
"op": [
"comment",
{
"parent_author": "",
"parent_permlink": "kr-dev",
"author": "kormanocorp",
"permlink": "api-gateway-bff-backend-for-frontend",
"title": "API Gateway와 BFF(Backend For Frontend)",
"body": "여러분, 안녕하세요. **이 기사에서는 API 게이트웨이 가 무엇이며** [**마이크로 서비스**](https://medium.com/javarevisited/10-best-java-microservices-courses-with-spring-boot-and-spring-cloud-6d04556bdfed) [**아키텍처**](https://medium.com/javarevisited/10-best-java-microservices-courses-with-spring-boot-and-spring-cloud-6d04556bdfed) 에서 **클라이언트-서버** 통신 에 API 게이트웨이가 어떻게 사용되는지 살펴보겠습니다 . 또한 API 게이트웨이 패턴의 장점과 단점도 살펴보겠습니다. 그런 다음 API Gateway 패턴의 변형인 **Front End용 Backend** 라는 패턴을 살펴보고 API GW와 BFF가 필요한 시점을 살펴보며 글을 마무리하겠습니다. 시작하자.[](https://medium.com/javarevisited/10-best-java-microservices-courses-with-spring-boot-and-spring-cloud-6d04556bdfed)\n\n[\n\n\n\n](https://javarevisited.blogspot.com/2021/09/microservices-design-patterns-principles.html)\n\n이미지 출처: [https://raw.githubusercontent.com/abpio/abp-commercial-docs/rel-4.3/en/images/gateway-bff.png](https://raw.githubusercontent.com/abpio/abp-commercial-docs/rel-4.3/en/images/gateway-bff.png)\n\n## API 게이트웨이란 무엇입니까?\n\nAPI 게이트웨이는 클라이언트가 상호 작용할 수 있도록 단일 위치에서 많은 기능을 처리하는 서버입니다. 또한 클라이언트 애플리케이션과 백엔드 마이크로서비스 아키텍처 간의 **리버스 프록시** 로도 작동합니다.\n\n```\n리버스 프록시 는 웹 서버 앞에 있는 서버 구성 요소 이며 클라이언트 요청 을 해당 웹 서버 로 전달 하고 응답 을 다시 클라이언트 로 보내는 역할 을 합니다 . 리버스 프록시 는 추가 수준 의 추상화 및 제어 를 제공 하여 _ _ _ _ _ _ 클라이언트 와 서버 간의 원활한 네트워크 트래픽 흐름 . _ \n```\n\n서버 API를 호출하는 여러 클라이언트가 있을 수 있으며 API 게이트웨이는 요청을 관련 마이크로 서비스로 라우팅한 다음 응답을 받아 클라이언트로 보내는 구성 요소입니다.\n\n모든 단일 마이크로 서비스에서 이러한 기능을 구현하는 대신 **보안,** [**로깅**](https://javarevisited.blogspot.com/2011/05/top-10-tips-on-logging-in-java.html) **, 캐싱** 등과 같은 모든 교차 기능을 단일 위치에서 처리합니다 . _또한 클라이언트가 통신할 수 있는 단일 엔드포인트를 사용하여 여러 마이크로 서비스 집계에서_ 데이터를 통합하고 집계할 수 있습니다 .\n\n[_마이크로서비스 아키텍처가_](https://medium.com/javarevisited/8-best-online-courses-to-learn-service-oriented-soa-and-microservices-architecture-94c01d6b94e6) 발전하기 전에는 대부분의 시스템이 모노리스 패턴을 사용했으며 단일 또는 두 개의 서버에서 교차 절단 문제를 처리할 수도 있었습니다. 그러나 마이크로서비스를 사용하면 더 큰 메모리 공간으로 인해 시스템 성능이 저하되어 작업 속도가 느려지는 각 마이크로서비스의 교차 절단 문제를 처리할 여유가 없습니다.\n\n## API 게이트웨이를 사용하지 않고 클라이언트에서 마이크로서비스로의 통신\n\nAPI 게이트웨이가 없는 마이크로서비스 아키텍처의 시나리오를 살펴보겠습니다. 아래 다이어그램에서 클라이언트는 API 게이트웨이 없이 마이크로서비스와 직접 통신합니다.\n\n[\n\n\n\n](https://www.java67.com/2021/02/microservices-interview-questions-answers-java-spring.html)\n\n이미지 출처: [https://learn.microsoft.com/en-us/dotnet/architecture/microservices/architect-microservice-container-applications/media/direct-client-to-microservice-communication.png](https://learn.microsoft.com/en-us/dotnet/architecture/microservices/architect-microservice-container-applications/media/direct-client-to-microservice-communication.png)\n\n거기에는 많은 단점이 있습니다.\n\n1. 마이크로서비스가 커지고 시스템이 복잡해지면 클라이언트는 모든 엔드포인트를 기억해야 합니다.\n2. 클라이언트는 대기 시간을 증가시킬 수 있고 사용자에게 좋은 경험을 제공하지 않을 수 있는 데이터를 로드하기 위해 다양한 마이크로 서비스에 대한 많은 API 호출을 수행해야 합니다.\n3. 위에서 논의한 바와 같이 권한 부여, 로깅, 캐싱 등과 같은 교차 편집 문제는 모든 마이크로 서비스에서 구현되어야 합니다.\n4. 일반적으로 마이크로서비스는 인터넷에 연결되어 있지 않으며 사설 IP가 있는 사설 서브넷 내부에 배치됩니다. 대중에게 마이크로서비스를 공개하는 것은 공격자에게 문제를 요구하는 것입니다.\n5. 클라이언트는 AMQP 또는 이진 프로토콜과 같은 특정 프로토콜만 지원하는 마이크로 서비스와 통신하지 못할 수 있습니다.\n\n## 마이크로서비스 아키텍처에서 API 게이트웨이를 사용한 클라이언트 서버 통신\n\n\n\n이미지 출처: [https://hub.packtpub.com/wp-content/uploads/2018/02/B04926\\_02\\_05-600x427.png](https://hub.packtpub.com/wp-content/uploads/2018/02/B04926_02_05-600x427.png)\n\n우리는 마이크로서비스 아키텍처에서 API 게이트웨이를 사용하지 않으면 많은 단점을 보았습니다. 이러한 단점을 없애고 우리의 삶을 편리하게 만들기 위해서는 Client와 Services 사이의 Layer로서 API Gateway가 반드시 필요합니다.\n\n## API 게이트웨이의 이점\n\n\n\n이미지 출처: [https://educosta.dev/wp-content/uploads/API-Gatey-Architecture.jpg](https://educosta.dev/wp-content/uploads/API-Gatey-Architecture.jpg)\n\nAPI 게이트웨이는 많은 일을 할 수 있으며 아래에서 이점을 살펴보겠습니다.\n\n1\\. 백엔드 시스템의 복잡성으로부터 **클라이언트 추상화**\n\n2\\. 전체 시스템에 대한 사용자 **인증 및 권한 부여를** 한 곳에서 처리\n\n3\\. 필요한 형식에 따라 **요청 및 응답 변환**\n\n4\\. 백엔드 서비스에 대한 부하를 방지하기 위해 각 API에 대한 **속도 제한**\n\n5\\. DDOS 공격을 방지하기 위해 단일 사용자의 **API 요청 제한**\n\n6\\. 반복되는 요청에 대한 **응답을 Caching하여** 서비스의 부하를 줄입니다.\n\n**7\\. 다양한 프로토콜** 지원\n\n8\\. **개별 API를 측정하여** 사용량에 따라 클라이언트에 청구\n\n9\\. 단일 위치에서 시스템에 대한 API 호출 **로깅 및 추적**\n\n10\\. **오류 처리**\n\n11\\. 마이크로서비스 전반에 걸쳐 **데이터를 집계** 하고 단일 API 호출로 클라이언트에 데이터를 응답합니다. 이렇게 하면 클라이언트가 만들어야 하는 여러 API 호출을 피할 수 있습니다.\n\n## API 게이트웨이의 단점\n\n모든 장점에는 단점이 있으며 API 게이트웨이도 마찬가지입니다.\n\n1. API 게이트웨이는 전체 시스템의 **단일 실패 지점이 될 수 있습니다.**\n\n2\\. API 게이트웨이에서 너무 많은 작업을 수행하면 **성능 문제가 발생하고 API 호출 대기 시간이 늘어날** 수 있습니다 .\n\n3\\. 마이크로서비스가 너무 많으면 **너무 많은 경로를 관리하는** 것이 복잡해질 수 있습니다.\n\n4\\. 클라이언트에서 서버로의 **API 호출에는** 항상 추가 홉이 있습니다 .\n\n5\\. 관련된 추가 서버 구성 요소로 인한 **추가 비용**\n\n## **FrontEnd(BFF) 패턴용 백엔드란 무엇입니까?**\n\n우리는 API Gateway에 대해 자세히 보았고 웹이나 모바일과 같은 단일 클라이언트가 있는 경우 이 접근 방식이 좋습니다. [우리 애플리케이션이 웹, 모바일, IoT](https://medium.com/javarevisited/everything-you-need-to-know-about-iot-internet-of-things-1b481e917edc) 등과 같은 여러 클라이언트에서 사용되는 경우 모든 유형의 클라이언트에 대해 단일 API 게이트웨이를 사용하는 것은 좋지 않습니다. 이는 더 커질 수 있으며 API 게이트웨이 서비스를 하나의 큰 Monolith 서비스로 만들어 부풀릴 수 있습니다.\n\n이러한 유형의 시나리오에 대한 더 나은 접근 방식은 각 클라이언트 유형에 대해 별도의 API 게이트웨이를 사용하는 것입니다. 이 아키텍처 패턴은 BFF(Backend for FrontEnd) 패턴이라고 하며 유행어가 되었습니다.\n\n> _BFF 패턴은 API 게이트웨이 패턴의 변형인 아키텍처 패러다임_ 이며구성하다[데스크톱, 브라우저, 기본 모바일 애플리케이션, IOT](https://medium.com/javarevisited/everything-you-need-to-know-about-iot-internet-of-things-1b481e917edc) 장치 등과 같은 특정 프런트 엔드 애플리케이션의 요구 사항을 충족하도록 설계된 여러 백엔드\n\n\n\n이미지 출처: [https://tsh.io/wp-content/uploads/2019/09/backend-for-frontend-design-pattern.png](https://tsh.io/wp-content/uploads/2019/09/backend-for-frontend-design-pattern.png)\n\n## 언제 API GW와 BFF를 사용해야 합니까?\n\n음, 이것은 열린 질문이며 전적으로 조직에 달려 있습니다.\n\n1\\. 응용 프로그램이 새로운 경우 사전에 사용법을 알 수 없습니다. 따라서 처음에는 API 게이트웨이가 단일 구성 요소가 될 수 있으며 클라이언트 전체에서 사용량이 증가하면 클라이언트용 API를 BFF와 같은 개별 구성 요소로 이동할 수 있습니다.\n\n2\\. 클라이언트마다 다른 유형의 인증이 필요한 경우 단일 API GW를 사용하는 것보다 BFF를 사용하는 것이 확실히 좋습니다.\n\n3\\. 클라이언트 응용 프로그램이 다른 팀에서 소유하는 경우 BFF를 사용하는 것이 합리적입니다. 그렇지 않으면 단일 API GW가 있을 때 많은 상호 작용과 오버헤드가 발생합니다.\n\n**이 기사에서는 API 게이트웨이가** 무엇인지 살펴보고 API 게이트웨이를 사용하거나 사용하지 않고 클라이언트와 마이크로 서비스 간의 통신 시나리오를 살펴보았습니다. API Gateway 패턴의 장단점도 살펴보았습니다. 그런 다음 API Gateway 패턴의 변형인 **Backend for Front End** 라는 패턴을 살펴보고 API GW와 BFF를 사용해야 하는 경우를 살펴보며 글을 마무리했습니다.\n\nhttps://medium.com/javarevisited/api-gateway-vs-backend-for-frontend-bff-everything-you-need-to-know-90154a1e693f",
"json_metadata": "{\"tags\":[\"kr-dev\"],\"image\":[\"https://miro.medium.com/v2/resize:fit:1050/1*ljR5uswvXDpoCAcPLDUmyw.png\",\"https://miro.medium.com/v2/resize:fit:1050/1*ShUrqBepv_1bcYrUSz6ygg.png\",\"https://miro.medium.com/v2/resize:fit:900/1*botmiI62309_1bf3cORRug.png\",\"https://miro.medium.com/v2/resize:fit:923/1*eaEBUnX24pBz9uvUQtWV2A.jpeg\",\"https://miro.medium.com/v2/resize:fit:1050/0*sKKvCHKBQbNac-uY.png\"],\"links\":[\"https://medium.com/javarevisited/10-best-java-microservices-courses-with-spring-boot-and-spring-cloud-6d04556bdfed\",\"https://javarevisited.blogspot.com/2021/09/microservices-design-patterns-principles.html\",\"https://raw.githubusercontent.com/abpio/abp-commercial-docs/rel-4.3/en/images/gateway-bff.png\",\"https://javarevisited.blogspot.com/2011/05/top-10-tips-on-logging-in-java.html\",\"https://medium.com/javarevisited/8-best-online-courses-to-learn-service-oriented-soa-and-microservices-architecture-94c01d6b94e6\",\"https://www.java67.com/2021/02/microservices-interview-questions-answers-java-spring.html\",\"https://learn.microsoft.com/en-us/dotnet/architecture/microservices/architect-microservice-container-applications/media/direct-client-to-microservice-communication.png\",\"https://hub.packtpub.com/wp-content/uploads/2018/02/B04926_02_05-600x427.png\",\"https://educosta.dev/wp-content/uploads/API-Gatey-Architecture.jpg\",\"https://medium.com/javarevisited/everything-you-need-to-know-about-iot-internet-of-things-1b481e917edc\",\"https://tsh.io/wp-content/uploads/2019/09/backend-for-frontend-design-pattern.png\",\"https://medium.com/javarevisited/api-gateway-vs-backend-for-frontend-bff-everything-you-need-to-know-90154a1e693f\"],\"app\":\"steemit/0.2\",\"format\":\"markdown\"}"
}
]
}kormanocorpclaimed reward balance: 0.052 STEEM, 0.057 SP2023/04/12 03:03:30
kormanocorpclaimed reward balance: 0.052 STEEM, 0.057 SP
2023/04/12 03:03:30
| account | kormanocorp |
| reward steem | 0.052 STEEM |
| reward sbd | 0.000 SBD |
| reward vests | 92.085921 VESTS |
| Transaction Info | Block #73686248/Trx 405abaf1cbcbea476dabb9b1fde7cf44d2d0c146 |
View Raw JSON Data
{
"trx_id": "405abaf1cbcbea476dabb9b1fde7cf44d2d0c146",
"block": 73686248,
"trx_in_block": 13,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-04-12T03:03:30",
"op": [
"claim_reward_balance",
{
"account": "kormanocorp",
"reward_steem": "0.052 STEEM",
"reward_sbd": "0.000 SBD",
"reward_vests": "92.085921 VESTS"
}
]
}kormanocorpreceived 0.052 STEEM, 0.057 SP author reward for @kormanocorp / windows-10-minikube-virtualbox2023/04/12 02:53:36
kormanocorpreceived 0.052 STEEM, 0.057 SP author reward for @kormanocorp / windows-10-minikube-virtualbox
2023/04/12 02:53:36
| author | kormanocorp |
| permlink | windows-10-minikube-virtualbox |
| sbd payout | 0.000 SBD |
| steem payout | 0.052 STEEM |
| vesting payout | 92.085921 VESTS |
| Transaction Info | Block #73686050/Virtual Operation #4 |
View Raw JSON Data
{
"trx_id": "0000000000000000000000000000000000000000",
"block": 73686050,
"trx_in_block": 4294967295,
"op_in_trx": 0,
"virtual_op": 4,
"timestamp": "2023-04-12T02:53:36",
"op": [
"author_reward",
{
"author": "kormanocorp",
"permlink": "windows-10-minikube-virtualbox",
"sbd_payout": "0.000 SBD",
"steem_payout": "0.052 STEEM",
"vesting_payout": "92.085921 VESTS"
}
]
}kr-devupvoted (100.00%) @kormanocorp / windows-10-minikube-virtualbox2023/04/05 02:58:39
kr-devupvoted (100.00%) @kormanocorp / windows-10-minikube-virtualbox
2023/04/05 02:58:39
| voter | kr-dev |
| author | kormanocorp |
| permlink | windows-10-minikube-virtualbox |
| weight | 10000 (100.00%) |
| Transaction Info | Block #73485479/Trx ee389a462c4734c1a4d02a332c0a9d9216237d66 |
View Raw JSON Data
{
"trx_id": "ee389a462c4734c1a4d02a332c0a9d9216237d66",
"block": 73485479,
"trx_in_block": 2,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-04-05T02:58:39",
"op": [
"vote",
{
"voter": "kr-dev",
"author": "kormanocorp",
"permlink": "windows-10-minikube-virtualbox",
"weight": 10000
}
]
}anpigonupvoted (100.00%) @kormanocorp / windows-10-minikube-virtualbox2023/04/05 02:57:51
anpigonupvoted (100.00%) @kormanocorp / windows-10-minikube-virtualbox
2023/04/05 02:57:51
| voter | anpigon |
| author | kormanocorp |
| permlink | windows-10-minikube-virtualbox |
| weight | 10000 (100.00%) |
| Transaction Info | Block #73485463/Trx 274d281f6423136e860e62a53fe8375764128cee |
View Raw JSON Data
{
"trx_id": "274d281f6423136e860e62a53fe8375764128cee",
"block": 73485463,
"trx_in_block": 0,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-04-05T02:57:51",
"op": [
"vote",
{
"voter": "anpigon",
"author": "kormanocorp",
"permlink": "windows-10-minikube-virtualbox",
"weight": 10000
}
]
}kr-dev.cu2replied to @kormanocorp / adreply-16806632309942023/04/05 02:53:51
kr-dev.cu2replied to @kormanocorp / adreply-1680663230994
2023/04/05 02:53:51
| parent author | kormanocorp |
| parent permlink | windows-10-minikube-virtualbox |
| author | kr-dev.cu2 |
| permlink | adreply-1680663230994 |
| title | |
| body | [광고] [STEEM 개발자 커뮤니티에 참여](/hive-137029/@kr-dev/x3v6n) 하시면, 다양한 혜택을 받을 수 있습니다. |
| json metadata | {"tags":["kr-dev"],"image":["https://devopshandbook.com/wp-content/uploads/2022/01/Powershell-Run.png","https://devopshandbook.com/wp-content/uploads/2022/01/Powershell-Version.png","https://devopshandbook.com/wp-content/uploads/2022/01/dotNet-Version.png","https://devopshandbook.com/wp-content/uploads/2022/01/Control-Panel.png","https://devopshandbook.com/wp-content/uploads/2022/01/Programs-and-Features.png","https://devopshandbook.com/wp-content/uploads/2022/01/Features-on-or-off.png","https://devopshandbook.com/wp-content/uploads/2022/01/hyper-v-hypervisor.png"],"links":["https://chocolatey.org/","https://devopshandbook.com/setting-up-minikube-virtualbox-on-windows-10/#:~:text=Steps%20to%20set%20up%20minikube%20%26%20VirtualBox%20on,is%20turned%20off%206%20Install%20VirtualBox%20%EA%B8%B0%ED%83%80%20%ED%95%AD%EB%AA%A9"],"app":"steemit/0.2","format":"markdown"} |
| Transaction Info | Block #73485383/Trx d1124bb581e051f6c02bb3d039fbdfbf70fa96a5 |
View Raw JSON Data
{
"trx_id": "d1124bb581e051f6c02bb3d039fbdfbf70fa96a5",
"block": 73485383,
"trx_in_block": 3,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-04-05T02:53:51",
"op": [
"comment",
{
"parent_author": "kormanocorp",
"parent_permlink": "windows-10-minikube-virtualbox",
"author": "kr-dev.cu2",
"permlink": "adreply-1680663230994",
"title": "",
"body": "[광고] [STEEM 개발자 커뮤니티에 참여](/hive-137029/@kr-dev/x3v6n) 하시면, 다양한 혜택을 받을 수 있습니다.",
"json_metadata": "{\"tags\":[\"kr-dev\"],\"image\":[\"https://devopshandbook.com/wp-content/uploads/2022/01/Powershell-Run.png\",\"https://devopshandbook.com/wp-content/uploads/2022/01/Powershell-Version.png\",\"https://devopshandbook.com/wp-content/uploads/2022/01/dotNet-Version.png\",\"https://devopshandbook.com/wp-content/uploads/2022/01/Control-Panel.png\",\"https://devopshandbook.com/wp-content/uploads/2022/01/Programs-and-Features.png\",\"https://devopshandbook.com/wp-content/uploads/2022/01/Features-on-or-off.png\",\"https://devopshandbook.com/wp-content/uploads/2022/01/hyper-v-hypervisor.png\"],\"links\":[\"https://chocolatey.org/\",\"https://devopshandbook.com/setting-up-minikube-virtualbox-on-windows-10/#:~:text=Steps%20to%20set%20up%20minikube%20%26%20VirtualBox%20on,is%20turned%20off%206%20Install%20VirtualBox%20%EA%B8%B0%ED%83%80%20%ED%95%AD%EB%AA%A9\"],\"app\":\"steemit/0.2\",\"format\":\"markdown\"}"
}
]
}kormanocorppublished a new post: windows-10-minikube-virtualbox2023/04/05 02:53:36
kormanocorppublished a new post: windows-10-minikube-virtualbox
2023/04/05 02:53:36
| parent author | |
| parent permlink | kr-dev |
| author | kormanocorp |
| permlink | windows-10-minikube-virtualbox |
| title | Windows 10에서 minikube 및 VirtualBox 설정 |
| body | **minikube** 는 학습 또는 개발 목적으로 로컬 Kubernetes 클러스터를 설정하고 실행할 수 있는 도구입니다. minikube를 사용하여 가상 머신(VM)에 포함된 Kubernetes 클러스터를 생성할 수 있습니다. **VirtualBox** 는 전용 하드웨어를 사용하지 않고도 다양한 운영 체제에서 VM(가상 머신)을 빠르게 가동하는 데 사용할 수 있는 무료 오픈 소스 도구입니다. 이 튜토리얼에서는 로컬 Kubernetes 클러스터를 호스팅할 일부 Linux VM을 생성하기 위해 minikube를 사용하여 VirtualBox와 인터페이스할 것입니다. minikube와 VirtualBox를 설치하기 위해 우리는 설치 프로세스를 크게 단순화하는 Windows용 패키지 관리자인 **Chocolatey를** 사용할 것입니다 . ## Windows 10에서 minikube 및 VirtualBox를 설정하는 단계 1. 설치된 Windows Powershell 버전을 확인하고 필요한 경우 업그레이드하십시오. 2. Windows .Net 버전 확인 및 필요한 경우 업그레이드 3. 초콜릿 설치 4. 미니큐브 설치 5. Hyper-V가 꺼져 있는지 확인 6. 버추얼박스 설치 7. Minikube 시작(VirtualBox로 정의된 드라이버 사용) ### 1단계. Windows Powershell 버전 확인 초콜릿을 사용하려면 Powershell V3 이상이 설치되어 있어야 합니다. Powershell 자체 내에서 명령을 사용하여 Powershell 버전을 확인할 수 있습니다. 시작하자! 시작하려면 "시작" 메뉴를 열고 "PowerShell"을 검색한 다음 검색 결과에서 클릭하십시오.  Powershell 창에서 다음 명령을 입력합니다. ``` $PSVersionTable ``` The value of PSVersion will indicate the current version of Powershell, which in this case is version 5.1.19041.1320  ### Step 2. Check .NET version To use chocolatey we need .NET Framework 4.5 or greater to be installed. We can check the .Net version using another Powershell command. Open Powershell as before, and then enter the following command: ``` Get-ChildItem 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP' -Recurse | Get-ItemProperty -Name version -EA 0 | Where { $_.PSChildName -Match '^(?!S)\p{L}'} | Select PSChildName, version ``` The current version of .Net will be shown  ### Step 3. Install Chocolatey Open Powershell as an administrator and run the following commands. First, check that the execution policy is not restricted: ``` Get-ExecutionPolicy ``` If it is restricted, then set the policy to All-Signed ``` Set-ExecutionPolicy AllSigned ``` Run the following command to install chocolatey: ``` Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1')) ``` Wait a few seconds for the command to complete. Wait a few seconds for the command to complete, and if you don’t see any errors, then you should be ready to use Chocolatey! Try the following to command to check the installation: ``` choco -? ``` For more information see [chocolatey.org](https://chocolatey.org/) ### Step 4. Install minikube With chocolately installed, we can now install minikube with the following command: ``` choco install minikube -y ``` Running the above command will install **minikube** and **kubernetes-cli** tools in your system. ### Step 5. Disable Hyper-V We’re going to use VirtualBox to provide our VMs, but Windows already has a built in virtualization technology called Hyper-V. VirtualBox and Hyper-V cannot run at the same time, so we are going to disable Hyper-V. Press **Windows Start** and search for “control panel” and run the app  Select **Programs and Features**  In the left pane, click the **Turn Windows features on or off** link  Find the **Hyper-V** option and deselect it using the tick box.  Click **OK** to save the changes and reboot your PC. ### Step 6. Install VirtualBox Install Virtualbox using chocolatey: ``` choco install virtualbox -y ``` ### Step 7. Start minikube Start minikube with the following command: ``` minikube start --driver=virtualbox ``` If minikube started successfully, you should now be able to interact with the local kubernetes cluster. In a Powershell window, try some of the following commands: ``` kubectl version kubectl get nodes kubectl get namespaces kubectl config view ``` 출처 : https://devopshandbook.com/setting-up-minikube-virtualbox-on-windows-10/#:~:text=Steps%20to%20set%20up%20minikube%20%26%20VirtualBox%20on,is%20turned%20off%206%20Install%20VirtualBox%20%EA%B8%B0%ED%83%80%20%ED%95%AD%EB%AA%A9 |
| json metadata | {"tags":["kr-dev"],"image":["https://devopshandbook.com/wp-content/uploads/2022/01/Powershell-Run.png","https://devopshandbook.com/wp-content/uploads/2022/01/Powershell-Version.png","https://devopshandbook.com/wp-content/uploads/2022/01/dotNet-Version.png","https://devopshandbook.com/wp-content/uploads/2022/01/Control-Panel.png","https://devopshandbook.com/wp-content/uploads/2022/01/Programs-and-Features.png","https://devopshandbook.com/wp-content/uploads/2022/01/Features-on-or-off.png","https://devopshandbook.com/wp-content/uploads/2022/01/hyper-v-hypervisor.png"],"links":["https://chocolatey.org/","https://devopshandbook.com/setting-up-minikube-virtualbox-on-windows-10/#:~:text=Steps%20to%20set%20up%20minikube%20%26%20VirtualBox%20on,is%20turned%20off%206%20Install%20VirtualBox%20%EA%B8%B0%ED%83%80%20%ED%95%AD%EB%AA%A9"],"app":"steemit/0.2","format":"markdown"} |
| Transaction Info | Block #73485378/Trx 12de1043fac8032e76d065673fd6c6c8228c6ebe |
View Raw JSON Data
{
"trx_id": "12de1043fac8032e76d065673fd6c6c8228c6ebe",
"block": 73485378,
"trx_in_block": 2,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-04-05T02:53:36",
"op": [
"comment",
{
"parent_author": "",
"parent_permlink": "kr-dev",
"author": "kormanocorp",
"permlink": "windows-10-minikube-virtualbox",
"title": "Windows 10에서 minikube 및 VirtualBox 설정",
"body": "**minikube** 는 학습 또는 개발 목적으로 로컬 Kubernetes 클러스터를 설정하고 실행할 수 있는 도구입니다. minikube를 사용하여 가상 머신(VM)에 포함된 Kubernetes 클러스터를 생성할 수 있습니다.\n\n**VirtualBox** 는 전용 하드웨어를 사용하지 않고도 다양한 운영 체제에서 VM(가상 머신)을 빠르게 가동하는 데 사용할 수 있는 무료 오픈 소스 도구입니다.\n\n이 튜토리얼에서는 로컬 Kubernetes 클러스터를 호스팅할 일부 Linux VM을 생성하기 위해 minikube를 사용하여 VirtualBox와 인터페이스할 것입니다.\n\nminikube와 VirtualBox를 설치하기 위해 우리는 설치 프로세스를 크게 단순화하는 Windows용 패키지 관리자인 **Chocolatey를** 사용할 것입니다 .\n\n## Windows 10에서 minikube 및 VirtualBox를 설정하는 단계\n\n1. 설치된 Windows Powershell 버전을 확인하고 필요한 경우 업그레이드하십시오.\n2. Windows .Net 버전 확인 및 필요한 경우 업그레이드\n3. 초콜릿 설치\n4. 미니큐브 설치\n5. Hyper-V가 꺼져 있는지 확인\n6. 버추얼박스 설치\n7. Minikube 시작(VirtualBox로 정의된 드라이버 사용)\n\n### 1단계. Windows Powershell 버전 확인\n\n초콜릿을 사용하려면 Powershell V3 이상이 설치되어 있어야 합니다.\n\nPowershell 자체 내에서 명령을 사용하여 Powershell 버전을 확인할 수 있습니다. 시작하자!\n\n시작하려면 \"시작\" 메뉴를 열고 \"PowerShell\"을 검색한 다음 검색 결과에서 클릭하십시오.\n\n\n\nPowershell 창에서 다음 명령을 입력합니다.\n\n```\n$PSVersionTable\n```\n\nThe value of PSVersion will indicate the current version of Powershell, which in this case is version 5.1.19041.1320\n\n\n\n### Step 2. Check .NET version\n\nTo use chocolatey we need .NET Framework 4.5 or greater to be installed.\n\nWe can check the .Net version using another Powershell command.\n\nOpen Powershell as before, and then enter the following command:\n\n```\nGet-ChildItem 'HKLM:\\SOFTWARE\\Microsoft\\NET Framework Setup\\NDP' -Recurse | Get-ItemProperty -Name version -EA 0 | Where { $_.PSChildName -Match '^(?!S)\\p{L}'} | Select PSChildName, version\n```\n\nThe current version of .Net will be shown\n\n\n\n### Step 3. Install Chocolatey\n\nOpen Powershell as an administrator and run the following commands.\n\nFirst, check that the execution policy is not restricted:\n\n```\nGet-ExecutionPolicy\n```\n\nIf it is restricted, then set the policy to All-Signed\n\n```\nSet-ExecutionPolicy AllSigned\n```\n\nRun the following command to install chocolatey:\n\n```\nSet-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iex ((New-Object System.Net.WebClient).DownloadString('https://community.chocolatey.org/install.ps1'))\n```\n\nWait a few seconds for the command to complete.\n\nWait a few seconds for the command to complete, and if you don’t see any errors, then you should be ready to use Chocolatey! Try the following to command to check the installation:\n\n```\nchoco -?\n```\n\nFor more information see [chocolatey.org](https://chocolatey.org/)\n\n### Step 4. Install minikube\n\nWith chocolately installed, we can now install minikube with the following command:\n\n```\nchoco install minikube -y\n```\n\nRunning the above command will install **minikube** and **kubernetes-cli** tools in your system.\n\n### Step 5. Disable Hyper-V\n\nWe’re going to use VirtualBox to provide our VMs, but Windows already has a built in virtualization technology called Hyper-V. VirtualBox and Hyper-V cannot run at the same time, so we are going to disable Hyper-V.\n\nPress **Windows Start** and search for “control panel” and run the app\n\n\n\nSelect **Programs and Features**\n\n\n\nIn the left pane, click the **Turn Windows features on or off** link\n\n\n\nFind the **Hyper-V** option and deselect it using the tick box.\n\n\n\nClick **OK** to save the changes and reboot your PC.\n\n### Step 6. Install VirtualBox\n\nInstall Virtualbox using chocolatey:\n\n```\nchoco install virtualbox -y\n```\n\n### Step 7. Start minikube\n\nStart minikube with the following command:\n\n```\nminikube start --driver=virtualbox\n```\n\nIf minikube started successfully, you should now be able to interact with the local kubernetes cluster. In a Powershell window, try some of the following commands:\n\n```\nkubectl version\nkubectl get nodes\nkubectl get namespaces\nkubectl config view\n```\n\n출처 : https://devopshandbook.com/setting-up-minikube-virtualbox-on-windows-10/#:~:text=Steps%20to%20set%20up%20minikube%20%26%20VirtualBox%20on,is%20turned%20off%206%20Install%20VirtualBox%20%EA%B8%B0%ED%83%80%20%ED%95%AD%EB%AA%A9",
"json_metadata": "{\"tags\":[\"kr-dev\"],\"image\":[\"https://devopshandbook.com/wp-content/uploads/2022/01/Powershell-Run.png\",\"https://devopshandbook.com/wp-content/uploads/2022/01/Powershell-Version.png\",\"https://devopshandbook.com/wp-content/uploads/2022/01/dotNet-Version.png\",\"https://devopshandbook.com/wp-content/uploads/2022/01/Control-Panel.png\",\"https://devopshandbook.com/wp-content/uploads/2022/01/Programs-and-Features.png\",\"https://devopshandbook.com/wp-content/uploads/2022/01/Features-on-or-off.png\",\"https://devopshandbook.com/wp-content/uploads/2022/01/hyper-v-hypervisor.png\"],\"links\":[\"https://chocolatey.org/\",\"https://devopshandbook.com/setting-up-minikube-virtualbox-on-windows-10/#:~:text=Steps%20to%20set%20up%20minikube%20%26%20VirtualBox%20on,is%20turned%20off%206%20Install%20VirtualBox%20%EA%B8%B0%ED%83%80%20%ED%95%AD%EB%AA%A9\"],\"app\":\"steemit/0.2\",\"format\":\"markdown\"}"
}
]
}kormanocorpcancelled power down2023/03/30 22:10:09
kormanocorpcancelled power down
2023/03/30 22:10:09
| account | kormanocorp |
| vesting shares | 0.000000 VESTS |
| Transaction Info | Block #73336447/Trx e00f2c5b6633d8647da15a157344897d3e047cc4 |
View Raw JSON Data
{
"trx_id": "e00f2c5b6633d8647da15a157344897d3e047cc4",
"block": 73336447,
"trx_in_block": 1,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-03-30T22:10:09",
"op": [
"withdraw_vesting",
{
"account": "kormanocorp",
"vesting_shares": "0.000000 VESTS"
}
]
}kormanocorpsent 65.857 STEEM to @user.dunamu- "4c0018f4-31c4-40f5-b27f-f7dae3fc83c1"2023/03/30 22:09:27
kormanocorpsent 65.857 STEEM to @user.dunamu- "4c0018f4-31c4-40f5-b27f-f7dae3fc83c1"
2023/03/30 22:09:27
| from | kormanocorp |
| to | user.dunamu |
| amount | 65.857 STEEM |
| memo | 4c0018f4-31c4-40f5-b27f-f7dae3fc83c1 |
| Transaction Info | Block #73336433/Trx 2fcd9b7caf5f2af94935a9384bedd16e97ca7478 |
View Raw JSON Data
{
"trx_id": "2fcd9b7caf5f2af94935a9384bedd16e97ca7478",
"block": 73336433,
"trx_in_block": 5,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-03-30T22:09:27",
"op": [
"transfer",
{
"from": "kormanocorp",
"to": "user.dunamu",
"amount": "65.857 STEEM",
"memo": "4c0018f4-31c4-40f5-b27f-f7dae3fc83c1"
}
]
}kormanocorpreceived 65.857 STEEM from power down installment (71.682 SP)2023/03/29 01:10:15
kormanocorpreceived 65.857 STEEM from power down installment (71.682 SP)
2023/03/29 01:10:15
| from account | kormanocorp |
| to account | kormanocorp |
| withdrawn | 116728.968278 VESTS |
| deposited | 65.857 STEEM |
| Transaction Info | Block #73282685/Virtual Operation #3 |
View Raw JSON Data
{
"trx_id": "0000000000000000000000000000000000000000",
"block": 73282685,
"trx_in_block": 4294967295,
"op_in_trx": 0,
"virtual_op": 3,
"timestamp": "2023-03-29T01:10:15",
"op": [
"fill_vesting_withdraw",
{
"from_account": "kormanocorp",
"to_account": "kormanocorp",
"withdrawn": "116728.968278 VESTS",
"deposited": "65.857 STEEM"
}
]
}kormanocorpsent 131.714 STEEM to @user.dunamu- "4c0018f4-31c4-40f5-b27f-f7dae3fc83c1"2023/03/22 07:51:48
kormanocorpsent 131.714 STEEM to @user.dunamu- "4c0018f4-31c4-40f5-b27f-f7dae3fc83c1"
2023/03/22 07:51:48
| from | kormanocorp |
| to | user.dunamu |
| amount | 131.714 STEEM |
| memo | 4c0018f4-31c4-40f5-b27f-f7dae3fc83c1 |
| Transaction Info | Block #73090027/Trx 0f3e3a5fd3efd34b3492c61fa2c6c8b8829ead70 |
View Raw JSON Data
{
"trx_id": "0f3e3a5fd3efd34b3492c61fa2c6c8b8829ead70",
"block": 73090027,
"trx_in_block": 1,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-03-22T07:51:48",
"op": [
"transfer",
{
"from": "kormanocorp",
"to": "user.dunamu",
"amount": "131.714 STEEM",
"memo": "4c0018f4-31c4-40f5-b27f-f7dae3fc83c1"
}
]
}kormanocorpreceived 65.821 STEEM from power down installment (71.682 SP)2023/03/22 01:10:15
kormanocorpreceived 65.821 STEEM from power down installment (71.682 SP)
2023/03/22 01:10:15
| from account | kormanocorp |
| to account | kormanocorp |
| withdrawn | 116728.968278 VESTS |
| deposited | 65.821 STEEM |
| Transaction Info | Block #73082032/Virtual Operation #4 |
View Raw JSON Data
{
"trx_id": "0000000000000000000000000000000000000000",
"block": 73082032,
"trx_in_block": 4294967295,
"op_in_trx": 0,
"virtual_op": 4,
"timestamp": "2023-03-22T01:10:15",
"op": [
"fill_vesting_withdraw",
{
"from_account": "kormanocorp",
"to_account": "kormanocorp",
"withdrawn": "116728.968278 VESTS",
"deposited": "65.821 STEEM"
}
]
}kormanocorpreceived 65.786 STEEM from power down installment (71.682 SP)2023/03/15 01:10:15
kormanocorpreceived 65.786 STEEM from power down installment (71.682 SP)
2023/03/15 01:10:15
| from account | kormanocorp |
| to account | kormanocorp |
| withdrawn | 116728.968278 VESTS |
| deposited | 65.786 STEEM |
| Transaction Info | Block #72881361/Virtual Operation #2 |
View Raw JSON Data
{
"trx_id": "0000000000000000000000000000000000000000",
"block": 72881361,
"trx_in_block": 4294967295,
"op_in_trx": 0,
"virtual_op": 2,
"timestamp": "2023-03-15T01:10:15",
"op": [
"fill_vesting_withdraw",
{
"from_account": "kormanocorp",
"to_account": "kormanocorp",
"withdrawn": "116728.968278 VESTS",
"deposited": "65.786 STEEM"
}
]
}kormanocorpcustom json: notify2023/03/14 01:55:33
kormanocorpcustom json: notify
2023/03/14 01:55:33
| required auths | [] |
| required posting auths | ["kormanocorp"] |
| id | notify |
| json | ["setLastRead",{"date":"2023-03-14T01:55:32"}] |
| Transaction Info | Block #72853621/Trx 5eebb0d0fce5ae0b8d90b38db69696c453da0a0c |
View Raw JSON Data
{
"trx_id": "5eebb0d0fce5ae0b8d90b38db69696c453da0a0c",
"block": 72853621,
"trx_in_block": 2,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-03-14T01:55:33",
"op": [
"custom_json",
{
"required_auths": [],
"required_posting_auths": [
"kormanocorp"
],
"id": "notify",
"json": "[\"setLastRead\",{\"date\":\"2023-03-14T01:55:32\"}]"
}
]
}kormanocorpstarted power down of 286.729 SP2023/03/08 01:10:15
kormanocorpstarted power down of 286.729 SP
2023/03/08 01:10:15
| account | kormanocorp |
| vesting shares | 466915.873110 VESTS |
| Transaction Info | Block #72680724/Trx 229a6364cce157851414b05d3c31905720db7a8f |
View Raw JSON Data
{
"trx_id": "229a6364cce157851414b05d3c31905720db7a8f",
"block": 72680724,
"trx_in_block": 1,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-03-08T01:10:15",
"op": [
"withdraw_vesting",
{
"account": "kormanocorp",
"vesting_shares": "466915.873110 VESTS"
}
]
}kormanocorpclaimed reward balance: 0.054 STEEM, 0.059 SP2023/02/21 05:03:30
kormanocorpclaimed reward balance: 0.054 STEEM, 0.059 SP
2023/02/21 05:03:30
| account | kormanocorp |
| reward steem | 0.054 STEEM |
| reward sbd | 0.000 SBD |
| reward vests | 96.000405 VESTS |
| Transaction Info | Block #72255373/Trx 7ce81c59ab21b32f48df257172145fa9c72a630e |
View Raw JSON Data
{
"trx_id": "7ce81c59ab21b32f48df257172145fa9c72a630e",
"block": 72255373,
"trx_in_block": 2,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-02-21T05:03:30",
"op": [
"claim_reward_balance",
{
"account": "kormanocorp",
"reward_steem": "0.054 STEEM",
"reward_sbd": "0.000 SBD",
"reward_vests": "96.000405 VESTS"
}
]
}kormanocorpreceived 0.054 STEEM, 0.059 SP author reward for @kormanocorp / ab-ml2023/02/21 04:51:00
kormanocorpreceived 0.054 STEEM, 0.059 SP author reward for @kormanocorp / ab-ml
2023/02/21 04:51:00
| author | kormanocorp |
| permlink | ab-ml |
| sbd payout | 0.000 SBD |
| steem payout | 0.054 STEEM |
| vesting payout | 96.000405 VESTS |
| Transaction Info | Block #72255122/Virtual Operation #4 |
View Raw JSON Data
{
"trx_id": "0000000000000000000000000000000000000000",
"block": 72255122,
"trx_in_block": 4294967295,
"op_in_trx": 0,
"virtual_op": 4,
"timestamp": "2023-02-21T04:51:00",
"op": [
"author_reward",
{
"author": "kormanocorp",
"permlink": "ab-ml",
"sbd_payout": "0.000 SBD",
"steem_payout": "0.054 STEEM",
"vesting_payout": "96.000405 VESTS"
}
]
}kormanocorpclaimed reward balance: 0.053 STEEM, 0.059 SP2023/02/19 23:18:30
kormanocorpclaimed reward balance: 0.053 STEEM, 0.059 SP
2023/02/19 23:18:30
| account | kormanocorp |
| reward steem | 0.053 STEEM |
| reward sbd | 0.000 SBD |
| reward vests | 96.009786 VESTS |
| Transaction Info | Block #72219827/Trx c9b8d9d867d2b4d04bc6346f2b890def1d214d31 |
View Raw JSON Data
{
"trx_id": "c9b8d9d867d2b4d04bc6346f2b890def1d214d31",
"block": 72219827,
"trx_in_block": 6,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-02-19T23:18:30",
"op": [
"claim_reward_balance",
{
"account": "kormanocorp",
"reward_steem": "0.053 STEEM",
"reward_sbd": "0.000 SBD",
"reward_vests": "96.009786 VESTS"
}
]
}kormanocorpreceived 0.053 STEEM, 0.059 SP author reward for @kormanocorp / 34yhqe2023/02/19 23:12:21
kormanocorpreceived 0.053 STEEM, 0.059 SP author reward for @kormanocorp / 34yhqe
2023/02/19 23:12:21
| author | kormanocorp |
| permlink | 34yhqe |
| sbd payout | 0.000 SBD |
| steem payout | 0.053 STEEM |
| vesting payout | 96.009786 VESTS |
| Transaction Info | Block #72219703/Virtual Operation #4 |
View Raw JSON Data
{
"trx_id": "0000000000000000000000000000000000000000",
"block": 72219703,
"trx_in_block": 4294967295,
"op_in_trx": 0,
"virtual_op": 4,
"timestamp": "2023-02-19T23:12:21",
"op": [
"author_reward",
{
"author": "kormanocorp",
"permlink": "34yhqe",
"sbd_payout": "0.000 SBD",
"steem_payout": "0.053 STEEM",
"vesting_payout": "96.009786 VESTS"
}
]
}kormanocorpsent 4.706 STEEM to @user.dunamu- "4c0018f4-31c4-40f5-b27f-f7dae3fc83c1"2023/02/17 00:53:30
kormanocorpsent 4.706 STEEM to @user.dunamu- "4c0018f4-31c4-40f5-b27f-f7dae3fc83c1"
2023/02/17 00:53:30
| from | kormanocorp |
| to | user.dunamu |
| amount | 4.706 STEEM |
| memo | 4c0018f4-31c4-40f5-b27f-f7dae3fc83c1 |
| Transaction Info | Block #72135721/Trx d4f58a59afbe4013902156a8f90d73fb8b9fe6c7 |
View Raw JSON Data
{
"trx_id": "d4f58a59afbe4013902156a8f90d73fb8b9fe6c7",
"block": 72135721,
"trx_in_block": 0,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-02-17T00:53:30",
"op": [
"transfer",
{
"from": "kormanocorp",
"to": "user.dunamu",
"amount": "4.706 STEEM",
"memo": "4c0018f4-31c4-40f5-b27f-f7dae3fc83c1"
}
]
}kormanocorpsent 1.895 SBD to @user.dunamu- "4c0018f4-31c4-40f5-b27f-f7dae3fc83c1"2023/02/17 00:51:00
kormanocorpsent 1.895 SBD to @user.dunamu- "4c0018f4-31c4-40f5-b27f-f7dae3fc83c1"
2023/02/17 00:51:00
| from | kormanocorp |
| to | user.dunamu |
| amount | 1.895 SBD |
| memo | 4c0018f4-31c4-40f5-b27f-f7dae3fc83c1 |
| Transaction Info | Block #72135671/Trx cc7a9b56c37b878bd625a09c2320f91c425a683f |
View Raw JSON Data
{
"trx_id": "cc7a9b56c37b878bd625a09c2320f91c425a683f",
"block": 72135671,
"trx_in_block": 2,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-02-17T00:51:00",
"op": [
"transfer",
{
"from": "kormanocorp",
"to": "user.dunamu",
"amount": "1.895 SBD",
"memo": "4c0018f4-31c4-40f5-b27f-f7dae3fc83c1"
}
]
}steemeggsent 0.001 STEEM to @kormanocorp- "Accumulate free UPVOTES every 6 hours. Just vote for our witness. It costs you nothing, and the sooner you make se-witness one of your witness choices, the sooner your free votes will start showing ..."2023/02/16 23:49:48
steemeggsent 0.001 STEEM to @kormanocorp- "Accumulate free UPVOTES every 6 hours. Just vote for our witness. It costs you nothing, and the sooner you make se-witness one of your witness choices, the sooner your free votes will start showing ..."
2023/02/16 23:49:48
| from | steemegg |
| to | kormanocorp |
| amount | 0.001 STEEM |
| memo | Accumulate free UPVOTES every 6 hours. Just vote for our witness. It costs you nothing, and the sooner you make se-witness one of your witness choices, the sooner your free votes will start showing up. We have already given out hundreds of steem worth of upvotes and were just getting started... https://steemlogin.com/sign/account-witness-vote?witness=se-witness&approve=1 |
| Transaction Info | Block #72134455/Trx e2de448a47efbb83605947f38b613ed713e55865 |
View Raw JSON Data
{
"trx_id": "e2de448a47efbb83605947f38b613ed713e55865",
"block": 72134455,
"trx_in_block": 9,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-02-16T23:49:48",
"op": [
"transfer",
{
"from": "steemegg",
"to": "kormanocorp",
"amount": "0.001 STEEM",
"memo": "Accumulate free UPVOTES every 6 hours. Just vote for our witness. It costs you nothing, and the sooner you make se-witness one of your witness choices, the sooner your free votes will start showing up. We have already given out hundreds of steem worth of upvotes and were just getting started... https://steemlogin.com/sign/account-witness-vote?witness=se-witness&approve=1"
}
]
}kormanocorpclaimed reward balance: 0.954 STEEM, 1.042 SP2023/02/15 23:18:30
kormanocorpclaimed reward balance: 0.954 STEEM, 1.042 SP
2023/02/15 23:18:30
| account | kormanocorp |
| reward steem | 0.954 STEEM |
| reward sbd | 0.000 SBD |
| reward vests | 1696.710474 VESTS |
| Transaction Info | Block #72105166/Trx e42f222cac334ad95e25eba3767408a8570268f0 |
View Raw JSON Data
{
"trx_id": "e42f222cac334ad95e25eba3767408a8570268f0",
"block": 72105166,
"trx_in_block": 1,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-02-15T23:18:30",
"op": [
"claim_reward_balance",
{
"account": "kormanocorp",
"reward_steem": "0.954 STEEM",
"reward_sbd": "0.000 SBD",
"reward_vests": "1696.710474 VESTS"
}
]
}kormanocorpreceived 0.954 STEEM, 1.042 SP author reward for @kormanocorp / 41ults2023/02/15 23:11:57
kormanocorpreceived 0.954 STEEM, 1.042 SP author reward for @kormanocorp / 41ults
2023/02/15 23:11:57
| author | kormanocorp |
| permlink | 41ults |
| sbd payout | 0.000 SBD |
| steem payout | 0.954 STEEM |
| vesting payout | 1696.710474 VESTS |
| Transaction Info | Block #72105035/Virtual Operation #5 |
View Raw JSON Data
{
"trx_id": "0000000000000000000000000000000000000000",
"block": 72105035,
"trx_in_block": 4294967295,
"op_in_trx": 0,
"virtual_op": 5,
"timestamp": "2023-02-15T23:11:57",
"op": [
"author_reward",
{
"author": "kormanocorp",
"permlink": "41ults",
"sbd_payout": "0.000 SBD",
"steem_payout": "0.954 STEEM",
"vesting_payout": "1696.710474 VESTS"
}
]
}kormanocorpclaimed reward balance: 0.911 STEEM, 0.995 SP2023/02/14 23:18:30
kormanocorpclaimed reward balance: 0.911 STEEM, 0.995 SP
2023/02/14 23:18:30
| account | kormanocorp |
| reward steem | 0.911 STEEM |
| reward sbd | 0.000 SBD |
| reward vests | 1620.362742 VESTS |
| Transaction Info | Block #72076498/Trx 5c67ce0fc14a427a605ab31719617660b29212fc |
View Raw JSON Data
{
"trx_id": "5c67ce0fc14a427a605ab31719617660b29212fc",
"block": 72076498,
"trx_in_block": 3,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-02-14T23:18:30",
"op": [
"claim_reward_balance",
{
"account": "kormanocorp",
"reward_steem": "0.911 STEEM",
"reward_sbd": "0.000 SBD",
"reward_vests": "1620.362742 VESTS"
}
]
}kormanocorpreceived 0.911 STEEM, 0.995 SP author reward for @kormanocorp / dineshchandgr2023/02/14 23:07:36
kormanocorpreceived 0.911 STEEM, 0.995 SP author reward for @kormanocorp / dineshchandgr
2023/02/14 23:07:36
| author | kormanocorp |
| permlink | dineshchandgr |
| sbd payout | 0.000 SBD |
| steem payout | 0.911 STEEM |
| vesting payout | 1620.362742 VESTS |
| Transaction Info | Block #72076280/Virtual Operation #4 |
View Raw JSON Data
{
"trx_id": "0000000000000000000000000000000000000000",
"block": 72076280,
"trx_in_block": 4294967295,
"op_in_trx": 0,
"virtual_op": 4,
"timestamp": "2023-02-14T23:07:36",
"op": [
"author_reward",
{
"author": "kormanocorp",
"permlink": "dineshchandgr",
"sbd_payout": "0.000 SBD",
"steem_payout": "0.911 STEEM",
"vesting_payout": "1620.362742 VESTS"
}
]
}kr-devupvoted (100.00%) @kormanocorp / ab-ml2023/02/14 04:56:03
kr-devupvoted (100.00%) @kormanocorp / ab-ml
2023/02/14 04:56:03
| voter | kr-dev |
| author | kormanocorp |
| permlink | ab-ml |
| weight | 10000 (100.00%) |
| Transaction Info | Block #72054557/Trx fbb17cb9fb18eae412a481573417e51d3ff5167a |
View Raw JSON Data
{
"trx_id": "fbb17cb9fb18eae412a481573417e51d3ff5167a",
"block": 72054557,
"trx_in_block": 7,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-02-14T04:56:03",
"op": [
"vote",
{
"voter": "kr-dev",
"author": "kormanocorp",
"permlink": "ab-ml",
"weight": 10000
}
]
}anpigonupvoted (100.00%) @kormanocorp / ab-ml2023/02/14 04:55:12
anpigonupvoted (100.00%) @kormanocorp / ab-ml
2023/02/14 04:55:12
| voter | anpigon |
| author | kormanocorp |
| permlink | ab-ml |
| weight | 10000 (100.00%) |
| Transaction Info | Block #72054540/Trx d5af2e97ebdf8a9ad8fc3672e26eb709ba57b6f1 |
View Raw JSON Data
{
"trx_id": "d5af2e97ebdf8a9ad8fc3672e26eb709ba57b6f1",
"block": 72054540,
"trx_in_block": 2,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-02-14T04:55:12",
"op": [
"vote",
{
"voter": "anpigon",
"author": "kormanocorp",
"permlink": "ab-ml",
"weight": 10000
}
]
}kr-dev.cu2replied to @kormanocorp / adreply-16763502748662023/02/14 04:51:15
kr-dev.cu2replied to @kormanocorp / adreply-1676350274866
2023/02/14 04:51:15
| parent author | kormanocorp |
| parent permlink | ab-ml |
| author | kr-dev.cu2 |
| permlink | adreply-1676350274866 |
| title | |
| body | [광고] [STEEM 개발자 커뮤니티에 참여](/hive-137029/@kr-dev/x3v6n) 하시면, 다양한 혜택을 받을 수 있습니다. |
| json metadata | {"tags":["kr-dev"],"image":["https://miro.medium.com/max/770/1*DwS66Pwz-Ov36SefUCse3g.png","https://miro.medium.com/max/770/1*8taAtEznYLPj6V5KUj9Cww.png","https://miro.medium.com/max/770/1*WlrhIvUnheoG40XJ9AsCwQ.png","https://miro.medium.com/max/770/1*Onq_gohPMQQDXPh2zTT-hg.png","https://miro.medium.com/max/770/1*aC1etsb7MIHFLPBZy_g27g.png","https://miro.medium.com/max/770/1*V_QjC_8BUCIMjjvn6ZAZMw.png","https://miro.medium.com/max/770/1*hqvlyc5JDb9x8HkywX0u6Q.png","https://miro.medium.com/max/770/1*XM6su-G2iD8IPU8P70EJHQ.png","https://miro.medium.com/max/770/1*IuYKudZiizvOEjFteTwfYg.png","https://miro.medium.com/max/770/1*yeZjBAVB4ndHPWNkOu1BQQ.png","https://miro.medium.com/max/770/1*9G4UeN7KkTxarI9gyy0qMA.png","https://miro.medium.com/max/770/0*Jn-1BEALgQS0a7cL.png"],"links":["https://towardsdatascience.com/using-causal-ml-instead-of-a-b-testing-eeb1067d7fc0"],"app":"steemit/0.2","format":"markdown"} |
| Transaction Info | Block #72054461/Trx 975c222fc44d2e0ecfd31c48ce211d121d523717 |
View Raw JSON Data
{
"trx_id": "975c222fc44d2e0ecfd31c48ce211d121d523717",
"block": 72054461,
"trx_in_block": 1,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-02-14T04:51:15",
"op": [
"comment",
{
"parent_author": "kormanocorp",
"parent_permlink": "ab-ml",
"author": "kr-dev.cu2",
"permlink": "adreply-1676350274866",
"title": "",
"body": "[광고] [STEEM 개발자 커뮤니티에 참여](/hive-137029/@kr-dev/x3v6n) 하시면, 다양한 혜택을 받을 수 있습니다.",
"json_metadata": "{\"tags\":[\"kr-dev\"],\"image\":[\"https://miro.medium.com/max/770/1*DwS66Pwz-Ov36SefUCse3g.png\",\"https://miro.medium.com/max/770/1*8taAtEznYLPj6V5KUj9Cww.png\",\"https://miro.medium.com/max/770/1*WlrhIvUnheoG40XJ9AsCwQ.png\",\"https://miro.medium.com/max/770/1*Onq_gohPMQQDXPh2zTT-hg.png\",\"https://miro.medium.com/max/770/1*aC1etsb7MIHFLPBZy_g27g.png\",\"https://miro.medium.com/max/770/1*V_QjC_8BUCIMjjvn6ZAZMw.png\",\"https://miro.medium.com/max/770/1*hqvlyc5JDb9x8HkywX0u6Q.png\",\"https://miro.medium.com/max/770/1*XM6su-G2iD8IPU8P70EJHQ.png\",\"https://miro.medium.com/max/770/1*IuYKudZiizvOEjFteTwfYg.png\",\"https://miro.medium.com/max/770/1*yeZjBAVB4ndHPWNkOu1BQQ.png\",\"https://miro.medium.com/max/770/1*9G4UeN7KkTxarI9gyy0qMA.png\",\"https://miro.medium.com/max/770/0*Jn-1BEALgQS0a7cL.png\"],\"links\":[\"https://towardsdatascience.com/using-causal-ml-instead-of-a-b-testing-eeb1067d7fc0\"],\"app\":\"steemit/0.2\",\"format\":\"markdown\"}"
}
]
}kormanocorppublished a new post: ab-ml2023/02/14 04:51:00
kormanocorppublished a new post: ab-ml
2023/02/14 04:51:00
| parent author | |
| parent permlink | kr-dev |
| author | kormanocorp |
| permlink | ab-ml |
| title | AB 테스트 대신 인과적 ML 사용 |
| body | ## 복잡한 환경에서 Causal ML은 A/B 테스트보다 유연하고 강력한 가정이 필요하지 않기 때문에 강력한 도구입니다.  \[저자 이미지\] 반사실적 질문은 비즈니스에서 가장 중요한 주제 중 하나입니다. 나는 회사에서 항상 이런 종류의 질문을 하는 것을 듣습니다. > “우리는 이 조치를 취했습니다. 이후 평균 사용자 지출은 100$였습니다. 하지만 우리가 조치를 취하지 않았다면 그들이 얼마를 썼을지 어떻게 알 수 있습니까?” 이러한 문제는 일반적으로 A/B 테스트를 통해 해결됩니다. 그러나 A/B 테스트에는 여러 가지 요구 사항이 있으며 그 중 동시에 너무 많은 테스트를 실행하면 안 됩니다. 그러나 실제 조직은 서로 다른 프로세스가 지속적으로 진행되는 매우 지저분합니다. 따라서 테스트를 실행하는 동안 다른 모든 것이 일정하게 유지되고 있다고 가정하는 것은 종종 불가능합니다. 이것이 바로 이 기사에서 반사실적 질문, 즉 인과적 기계 학습을 해결할 수 있는 다른 도구를 살펴보는 이유입니다. Causal ML의 이점은 훨씬 더 유연하며 가장 중요한 것은 모든 비즈니스 프로세스를 거의 또는 전혀 제어할 수 없을 때 사용할 수 있다는 것입니다(데이터 과학자의 경우가 종종 있음). ## 문제 프레이밍 간단한 예를 들어보겠습니다. 사용자가 4명이라고 가정해 보겠습니다. 그들에게 할인을 제공하면 우리 플랫폼에서 더 많은 돈을 쓰게 될지 알고 싶습니다. **이것은 두 개의 평행 우주를 관찰** 하라고 요구하는 것과 같습니다 . 하나의 유니버스에서 모든 사용자가 할인을 받습니다. 다른 우주에서는 어떤 사용자도 할인을 받지 못합니다. 두 유니버스는 사용자에게 할인을 제공하는(또는 제공하지 않는) 순간까지 정확히 동일합니다. 실제로 두 우주를 관찰할 수 있다고 상상해 보십시오. 다음 이미지에서 실험 결과를 볼 수 있습니다.  다중 우주에서 마케팅 활동 테스트: 하나의 우주에서 모든 사용자에게 할인이 제공됩니다. 다른 우주에서는 그들 중 누구도 할인을 받지 못합니다. \[저자 이미지\] 첫 번째 유니버스에서 사용자는 총 120$를 지출한 반면, 두 번째 유니버스에서는 총 100$를 지출했습니다. 따라서 우리는 할인이 사용자가 평균 5$ 더 지출하게 만드는 효과가 있다고 결론을 내릴 수 있습니다(120$ - 100$를 4명의 사용자로 나눈 값). 좋습니다. 할인이 적용됩니다! ## 평행 우주에서 A/B 테스트까지 불행하게도 실제로는 서로 다른 우주를 동시에 관찰할 수 있는 특권이 없습니다. 그래서 우리는 다른 방법을 찾아야 합니다. 이 방법은 A/B 테스트를 통해 제공됩니다. A/B 테스트는 단일 유니버스에서 다른 유니버스를 생성하는 현명한 트릭입니다. A/B 테스트에서 우리는 사용자를 치료 그룹과 통제 그룹이라는 두 그룹으로 나눕니다. 그런 다음 치료 그룹에만 할인을 제공합니다. 두 그룹이 충분히 "유사"하고 두 그룹이 서로 영향을 미치지 않는다고 가정하면 이는 서로 다른 두 우주를 관찰하는 것과 매우 유사합니다.  A/B 테스트, 즉 단일 유니버스에서 마케팅 활동을 테스트합니다. \[저자 이미지\] 따라서 우리가 해야 할 일은 처리 그룹의 평균 사용자 지출(30$)과 통제 그룹의 평균 사용자 지출(25$)을 비교하여 할인이 사용자가 평균적으로 지출하게 만드는 효과가 있다는 결론을 내리는 것입니다. 5 $ 더 (30 $ - 25 $). ## 그렇다면 A/B 테스트의 문제점은 무엇입니까? 아무 것도 아닙니다. A/B 테스트는 잘 작동합니다. 하지만**A/B 테스트의 요구 사항 중 하나는 서로의 결과를 "오염"시킬 수 있기 때문에 동시에 너무 많은 테스트를 실행하지 않는 것입니다.**. > 실제 조직은 엄청나게 지저분하고 실제 프로세스는 A/B 테스트에서 요구하는 가정을 준수하지 않는 경우가 많습니다. 실제 회사에서 일어나는 일은 서로 다른 팀이 동일한 사용자에 대해 서로 다른 마케팅 조치를 취하는 것입니다. 그런 다음 귀하(데이터 과학자)에게 자신이 수행한 마케팅 조치의 효과를 평가하도록 요청합니다. 따라서 데이터를 분석하면 다음과 같은 사실을 알 수 있습니다. 1. 일부 팀은 대조군을 별도로 두는 것을 잊었습니다. 2. 일부 팀은 처리된 그룹과 충분히 유사하지 않은 대조군을 따로 보관했습니다. 3. 일부 팀은 너무 작은 통제 그룹을 따로 보관했습니다. 4. 서로 다른 팀이 충돌하는 마케팅 캠페인(예: 유지 캠페인 및 상향 판매 캠페인)을 동일한 사용자에게 보냈습니다. 5. 일부 팀은 다른 팀의 컨트롤 그룹에 속한 사용자에게 마케팅 캠페인을 보냈습니다. 이렇게 지저분한 프로세스를 처리하면서 어떻게 견고한 통계 기반을 유지할 수 있습니까? ## 인과 ML 구조 인과 추론은 우리의 상황에 매우 잘 적응하는 프레임워크를 제공합니다. 사용자에 대한 정보 집합을 의미하는 공변량 집합이 있습니다. 마케팅 팀은 이러한 정보를 기반으로 결정을 내립니다. 이러한 결정은 마케팅 조치(치료라고도 함)의 형태를 취합니다. 예를 들어 지난 3개월 동안 구매하지 않은 사용자에게 할인을 보내기로 결정할 수 있습니다. 공변량과 처리의 조합은 우리가 관심 있는 KPI인 결과를 생성합니다. 이 경우 이것은 사용자의 지출일 수 있습니다. 다이어그램에서 이 프로세스를 요약해 보겠습니다.  인과 관계 다이어그램. \[저자 이미지\] 좀 더 구체적으로 설명하기 위해 작은 데이터 세트를 상상해 봅시다. 데이터 세트는 각 원인 요소에 대해 하나씩 3개의 테이블로 구성됩니다. 공변량은 사용자 테이블에서 찾을 수 있습니다. 처리 또는 조치는 캠페인 표에서 찾을 수 있습니다. 결과는 구매 표에서 확인할 수 있습니다.  장난감 데이터 세트. \[저자 이미지\] 타임라인에서 각 사용자의 여정을 그래픽으로 시각화할 수 있습니다.  각 사용자의 고객 여정. \[저자 이미지\] 앨리스를 데려가자 그녀는 9월 15일 캠페인 A의 표적이 되었고 10월 4일 캠페인 B의 표적이 되었습니다. 그런 다음 그녀는 10월 18일에 구매했습니다(75달러 지출). 이제 해당 구매가 캠페인 A, 캠페인 B 또는 둘의 조합으로 인한 것인지 어떻게 알 수 있습니까? 하지만 무엇보다도 캠페인을 보내지 않았다면 그녀가 구매했을지 여부를 어떻게 알 수 있습니까? 이 문제를 해결하려면 기계 학습에서 자주 사용되는 단순화를 만들어야 합니다. 우리는 특정 시점(이를 컷오프 포인트라고 부름)을 선택하고 그 순간 이전에 일어난 모든 일(행동)이 그 순간 이후에 일어난 모든 일(결과)의 원인이 되었다고 가정해야 합니다.  예측 모델의 시간 차원. \[저자 이미지\] 이제 우리는 이것에 동의했으므로 두 기간이 얼마나 길어야 하는지 결정하기만 하면 됩니다. 이는 비즈니스에 따라 크게 달라지며 조정할 수 있습니다(예: 이벤트가 마감 지점에서 얼마나 멀리 떨어져 있는지에 따라 이벤트에 가중치를 다르게 적용). 간단하게 하기 위해 작업 기간(이미지의 노란색 밴드)과 결과 기간(파란색 밴드)이 모두 한 달이어야 한다고 가정합니다. 이 접근 방식을 사용하면 데이터로 돌아갈 수 있습니다. 캠페인 A가 9월 15일에 전송되었음을 알고 있습니다. 따라서 이 날을 모든 사용자의 컷오프 포인트로 삼을 수 있습니다.  노란색 배경: 행동 관찰. 파란색 배경: 결과 관찰. \[저자 이미지\] 결과(파란색 배경)를 관찰할 때 작업을 무시합니다. 이 경우 중요한 것은 결과입니다. 캠페인 B의 전송 날짜를 기준점으로 삼아 이 프로세스를 반복할 수 있습니다. 이 경우 다음을 갖게 됩니다.  노란색 배경: 행동 관찰. 파란색 배경: 결과 관찰. \[저자 이미지\] 공변량, 처리 및 결과를 종합하면 초기 데이터를 다음 형식으로 재정렬할 수 있습니다.  데이터 준비 후 데이터 세트. \[저자 이미지\] 이제 공변량과 처리로 구성된 독립 변수 세트(행렬 _X_ )와 결과를 포함하는 하나의 목표 변수(벡터 _y )가 있습니다._ 이 두 가지 요소를 사용하여 이제 모든 기계 학습 모델을 교육할 수 있습니다. 모델 **은 치료와 대상 변수 간의 관계(A/B 테스트에서 발생하는 것처럼)뿐만 아니라 치료와 공변량 간의 관계도 학습할 수 있습니다** . 예를 들어 프랑스 사용자는 캠페인 A에 더 반응하고 독일 사용자는 캠페인 B에 더 반응한다는 사실을 학습할 수 있습니다. 지금까지 우리는 이 문제를 전형적인 기계 학습 문제로 다루었지만, 이 경우 예측할 것이 없다고 반대할 수 있습니다. 그렇다면 애초에 ML을 사용한 이유는 무엇일까요? ## 직장에서의 인과적 ML 우리의 초기 목적은 다음과 같은 질문에 답하는 것이었습니다. > 어떤 사용자에게도 캠페인을 보내지 않았다면 어떻게 되었을까요? 캠페인을 모든 사용자에게 보냈다면 어떻게 되었을까요? Causal ML을 사용하면 반사실적 질문에 답할 수 있습니다. 또는 — 좀 더 거창한 용어로 표현하고 싶다면 Causal ML을 통해 다양한 우주를 시뮬레이션할 수 있습니다. 예를 들어 두 가지 시나리오를 시뮬레이션하고 싶다고 가정해 보겠습니다. - 유니버스 A: 어떤 사용자에게도 캠페인을 보내지 않았다면 어떻게 되었을까요? - 유니버스 B: 캠페인을 모든 사용자에게 보냈다면 어떻게 되었을까요? 이러한 시나리오를 시뮬레이션하는 것은 예측자 행렬에서 처리 변수의 값을 변경하는 것을 의미합니다. 매우 중요하기 때문에 이 점을 강조하고 싶습니다. **치료 변수만 변경할 수 있고 공변량은 변경할 수 없습니다** . 그래픽으로,  Causal ML을 사용한 다양한 시나리오의 시뮬레이션. \[저자 이미지\] 이 접근 방식이 얼마나 유연한지 아십니까? 우리가 관심을 가질 수 있는 모든 사용자 하위 집합에서 거의 모든 시나리오를 시뮬레이션할 수 있습니다. 이 시점에서 질문이 있을 수 있습니다. 모델을 교육한 동일한 데이터에 대해 어떻게 예측을 수행합니까? 기계 학습의 첫 번째 " _하지 마십시오_ " 아닌가요 ? 교차 유효성 검사에서와 마찬가지로 데이터 세트를 여러 개로 분할하고 각 데이터 세트에 대해 다른 모델을 훈련하는 것으로 충분합니다. ``` import pandas as pd from sklearn.model_selection import KFold from lightgbm import LGBMRegressor = 5 folds = {fold: dict () for fold in range (n_folds)} for fold, (ix_train, ix_test) in enumerate (KFold(n_splits=n_folds).split(X=X)): folds[fold][ "ix_test" ] = ix_test 폴드[폴드]["모델" ] = LGBMRegressor().fit( X=X.loc[ix_train, :], y=y.loc[ix_train] ) ``` 이제 각 폴드에 대해 샘플 외부에서 훈련된 모델이 있습니다. 이 시점에서 이러한 모델을 사용하여 두 유니버스 각각에서 어떤 일이 발생할지 예측할 수 있습니다. ``` X_zeros = X.replace({ "campaign_A" : { 1 : 0 }}) X_ones = X.replace({ "campaign_A" : { 0 : 1 }} ) # 유니버스 B: 사람 이 . folds.keys() 에서 접기 : ix_test = folds[fold][ "ix_test" ] model = folds[fold][ "model" ] pred_zeros.loc[ix_test] = model.predict(X_zeros.loc[ix_test, :]) pred_ones.loc[ix_test] = model.predict(X_ones.loc[ix_test, :]) ``` `pred_ones`"캠페인 A를 모든 사용자에게 보내고 다른 모든 것은 일정하게 유지했다면 어떻게 되었을까요?"라는 질문에 답합니다. `pred_zeros`"캠페인 A를 어떤 사용자에게도 보내지 않고 다른 모든 것은 일정하게 유지했다면 어떻게 되었을까요?"라는 질문에 답합니다. 이제 우리는 캠페인 A `pred_zeros`와 `pred_ones` **관련하여 우리가 원하는 거의 모든 것을 계산할 수 있습니다** . 특정 하위 그룹의 평균 처리 효과, 중간 처리 효과 또는 우리가 관심을 가질 수 있는 다른 측정값입니다. 예를 들어 평균 처리 효과는 다음과 같이 계산할 수 있습니다. ``` 먹었다 = (pred_ones - pred_zeros).mean() ``` 위에서 본 동일한 논리가 이진 응답 변수에 적용될 수 있습니다(예: 사용자가 구매했습니까, 예 또는 아니오?). 이 경우 실제 확률을 예측할 수 있도록 모델을 보정해야 합니다. ## 합산 실제 조직은 복잡하고 다양한 프로세스가 지속적으로 사용자와 관련되어 있습니다. 이 상황에서 A/B 테스트가 의존하는 요구 사항이 반드시 충족되는 것은 아닙니다. 이 경우 Causal ML을 사용하여 반사실적 질문에 답할 수 있습니다. Causal ML에는 많은 장점이 있습니다. 유연하고 불가지론적이며 거의 모든 시나리오를 시뮬레이션할 수 있습니다.  출처 : https://towardsdatascience.com/using-causal-ml-instead-of-a-b-testing-eeb1067d7fc0 |
| json metadata | {"tags":["kr-dev"],"image":["https://miro.medium.com/max/770/1*DwS66Pwz-Ov36SefUCse3g.png","https://miro.medium.com/max/770/1*8taAtEznYLPj6V5KUj9Cww.png","https://miro.medium.com/max/770/1*WlrhIvUnheoG40XJ9AsCwQ.png","https://miro.medium.com/max/770/1*Onq_gohPMQQDXPh2zTT-hg.png","https://miro.medium.com/max/770/1*aC1etsb7MIHFLPBZy_g27g.png","https://miro.medium.com/max/770/1*V_QjC_8BUCIMjjvn6ZAZMw.png","https://miro.medium.com/max/770/1*hqvlyc5JDb9x8HkywX0u6Q.png","https://miro.medium.com/max/770/1*XM6su-G2iD8IPU8P70EJHQ.png","https://miro.medium.com/max/770/1*IuYKudZiizvOEjFteTwfYg.png","https://miro.medium.com/max/770/1*yeZjBAVB4ndHPWNkOu1BQQ.png","https://miro.medium.com/max/770/1*9G4UeN7KkTxarI9gyy0qMA.png","https://miro.medium.com/max/770/0*Jn-1BEALgQS0a7cL.png"],"links":["https://towardsdatascience.com/using-causal-ml-instead-of-a-b-testing-eeb1067d7fc0"],"app":"steemit/0.2","format":"markdown"} |
| Transaction Info | Block #72054456/Trx 361e7be59ed46dd6d4faeed2b98e13855a6ec883 |
View Raw JSON Data
{
"trx_id": "361e7be59ed46dd6d4faeed2b98e13855a6ec883",
"block": 72054456,
"trx_in_block": 1,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-02-14T04:51:00",
"op": [
"comment",
{
"parent_author": "",
"parent_permlink": "kr-dev",
"author": "kormanocorp",
"permlink": "ab-ml",
"title": "AB 테스트 대신 인과적 ML 사용",
"body": "## 복잡한 환경에서 Causal ML은 A/B 테스트보다 유연하고 강력한 가정이 필요하지 않기 때문에 강력한 도구입니다.\n\n\n\n\\[저자 이미지\\]\n\n반사실적 질문은 비즈니스에서 가장 중요한 주제 중 하나입니다. 나는 회사에서 항상 이런 종류의 질문을 하는 것을 듣습니다.\n\n> “우리는 이 조치를 취했습니다. 이후 평균 사용자 지출은 100$였습니다. 하지만 우리가 조치를 취하지 않았다면 그들이 얼마를 썼을지 어떻게 알 수 있습니까?”\n\n이러한 문제는 일반적으로 A/B 테스트를 통해 해결됩니다. 그러나 A/B 테스트에는 여러 가지 요구 사항이 있으며 그 중 동시에 너무 많은 테스트를 실행하면 안 됩니다.\n\n그러나 실제 조직은 서로 다른 프로세스가 지속적으로 진행되는 매우 지저분합니다. 따라서 테스트를 실행하는 동안 다른 모든 것이 일정하게 유지되고 있다고 가정하는 것은 종종 불가능합니다.\n\n이것이 바로 이 기사에서 반사실적 질문, 즉 인과적 기계 학습을 해결할 수 있는 다른 도구를 살펴보는 이유입니다. Causal ML의 이점은 훨씬 더 유연하며 가장 중요한 것은 모든 비즈니스 프로세스를 거의 또는 전혀 제어할 수 없을 때 사용할 수 있다는 것입니다(데이터 과학자의 경우가 종종 있음).\n\n## 문제 프레이밍\n\n간단한 예를 들어보겠습니다. 사용자가 4명이라고 가정해 보겠습니다. 그들에게 할인을 제공하면 우리 플랫폼에서 더 많은 돈을 쓰게 될지 알고 싶습니다.\n\n**이것은 두 개의 평행 우주를 관찰** 하라고 요구하는 것과 같습니다 .\n\n하나의 유니버스에서 모든 사용자가 할인을 받습니다. 다른 우주에서는 어떤 사용자도 할인을 받지 못합니다. 두 유니버스는 사용자에게 할인을 제공하는(또는 제공하지 않는) 순간까지 정확히 동일합니다.\n\n실제로 두 우주를 관찰할 수 있다고 상상해 보십시오. 다음 이미지에서 실험 결과를 볼 수 있습니다.\n\n\n\n다중 우주에서 마케팅 활동 테스트: 하나의 우주에서 모든 사용자에게 할인이 제공됩니다. 다른 우주에서는 그들 중 누구도 할인을 받지 못합니다. \\[저자 이미지\\]\n\n첫 번째 유니버스에서 사용자는 총 120$를 지출한 반면, 두 번째 유니버스에서는 총 100$를 지출했습니다. 따라서 우리는 할인이 사용자가 평균 5$ 더 지출하게 만드는 효과가 있다고 결론을 내릴 수 있습니다(120$ - 100$를 4명의 사용자로 나눈 값).\n\n좋습니다. 할인이 적용됩니다!\n\n## 평행 우주에서 A/B 테스트까지\n\n불행하게도 실제로는 서로 다른 우주를 동시에 관찰할 수 있는 특권이 없습니다. 그래서 우리는 다른 방법을 찾아야 합니다. 이 방법은 A/B 테스트를 통해 제공됩니다.\n\nA/B 테스트는 단일 유니버스에서 다른 유니버스를 생성하는 현명한 트릭입니다. A/B 테스트에서 우리는 사용자를 치료 그룹과 통제 그룹이라는 두 그룹으로 나눕니다. 그런 다음 치료 그룹에만 할인을 제공합니다.\n\n두 그룹이 충분히 \"유사\"하고 두 그룹이 서로 영향을 미치지 않는다고 가정하면 이는 서로 다른 두 우주를 관찰하는 것과 매우 유사합니다.\n\n\n\nA/B 테스트, 즉 단일 유니버스에서 마케팅 활동을 테스트합니다. \\[저자 이미지\\]\n\n따라서 우리가 해야 할 일은 처리 그룹의 평균 사용자 지출(30$)과 통제 그룹의 평균 사용자 지출(25$)을 비교하여 할인이 사용자가 평균적으로 지출하게 만드는 효과가 있다는 결론을 내리는 것입니다. 5 $ 더 (30 $ - 25 $).\n\n## 그렇다면 A/B 테스트의 문제점은 무엇입니까?\n\n아무 것도 아닙니다. A/B 테스트는 잘 작동합니다.\n\n하지만**A/B 테스트의 요구 사항 중 하나는 서로의 결과를 \"오염\"시킬 수 있기 때문에 동시에 너무 많은 테스트를 실행하지 않는 것입니다.**.\n\n> 실제 조직은 엄청나게 지저분하고 실제 프로세스는 A/B 테스트에서 요구하는 가정을 준수하지 않는 경우가 많습니다.\n\n실제 회사에서 일어나는 일은 서로 다른 팀이 동일한 사용자에 대해 서로 다른 마케팅 조치를 취하는 것입니다. 그런 다음 귀하(데이터 과학자)에게 자신이 수행한 마케팅 조치의 효과를 평가하도록 요청합니다.\n\n따라서 데이터를 분석하면 다음과 같은 사실을 알 수 있습니다.\n\n1. 일부 팀은 대조군을 별도로 두는 것을 잊었습니다.\n2. 일부 팀은 처리된 그룹과 충분히 유사하지 않은 대조군을 따로 보관했습니다.\n3. 일부 팀은 너무 작은 통제 그룹을 따로 보관했습니다.\n4. 서로 다른 팀이 충돌하는 마케팅 캠페인(예: 유지 캠페인 및 상향 판매 캠페인)을 동일한 사용자에게 보냈습니다.\n5. 일부 팀은 다른 팀의 컨트롤 그룹에 속한 사용자에게 마케팅 캠페인을 보냈습니다.\n\n이렇게 지저분한 프로세스를 처리하면서 어떻게 견고한 통계 기반을 유지할 수 있습니까?\n\n## 인과 ML 구조\n\n인과 추론은 우리의 상황에 매우 잘 적응하는 프레임워크를 제공합니다.\n\n사용자에 대한 정보 집합을 의미하는 공변량 집합이 있습니다. 마케팅 팀은 이러한 정보를 기반으로 결정을 내립니다. 이러한 결정은 마케팅 조치(치료라고도 함)의 형태를 취합니다. 예를 들어 지난 3개월 동안 구매하지 않은 사용자에게 할인을 보내기로 결정할 수 있습니다.\n\n공변량과 처리의 조합은 우리가 관심 있는 KPI인 결과를 생성합니다. 이 경우 이것은 사용자의 지출일 수 있습니다.\n\n다이어그램에서 이 프로세스를 요약해 보겠습니다.\n\n\n\n인과 관계 다이어그램. \\[저자 이미지\\]\n\n좀 더 구체적으로 설명하기 위해 작은 데이터 세트를 상상해 봅시다. 데이터 세트는 각 원인 요소에 대해 하나씩 3개의 테이블로 구성됩니다. 공변량은 사용자 테이블에서 찾을 수 있습니다. 처리 또는 조치는 캠페인 표에서 찾을 수 있습니다. 결과는 구매 표에서 확인할 수 있습니다.\n\n\n\n장난감 데이터 세트. \\[저자 이미지\\]\n\n타임라인에서 각 사용자의 여정을 그래픽으로 시각화할 수 있습니다.\n\n\n\n각 사용자의 고객 여정. \\[저자 이미지\\]\n\n앨리스를 데려가자 그녀는 9월 15일 캠페인 A의 표적이 되었고 10월 4일 캠페인 B의 표적이 되었습니다. 그런 다음 그녀는 10월 18일에 구매했습니다(75달러 지출).\n\n이제 해당 구매가 캠페인 A, 캠페인 B 또는 둘의 조합으로 인한 것인지 어떻게 알 수 있습니까? 하지만 무엇보다도 캠페인을 보내지 않았다면 그녀가 구매했을지 여부를 어떻게 알 수 있습니까?\n\n이 문제를 해결하려면 기계 학습에서 자주 사용되는 단순화를 만들어야 합니다. 우리는 특정 시점(이를 컷오프 포인트라고 부름)을 선택하고 그 순간 이전에 일어난 모든 일(행동)이 그 순간 이후에 일어난 모든 일(결과)의 원인이 되었다고 가정해야 합니다.\n\n\n\n예측 모델의 시간 차원. \\[저자 이미지\\]\n\n이제 우리는 이것에 동의했으므로 두 기간이 얼마나 길어야 하는지 결정하기만 하면 됩니다. 이는 비즈니스에 따라 크게 달라지며 조정할 수 있습니다(예: 이벤트가 마감 지점에서 얼마나 멀리 떨어져 있는지에 따라 이벤트에 가중치를 다르게 적용).\n\n간단하게 하기 위해 작업 기간(이미지의 노란색 밴드)과 결과 기간(파란색 밴드)이 모두 한 달이어야 한다고 가정합니다.\n\n이 접근 방식을 사용하면 데이터로 돌아갈 수 있습니다. 캠페인 A가 9월 15일에 전송되었음을 알고 있습니다. 따라서 이 날을 모든 사용자의 컷오프 포인트로 삼을 수 있습니다.\n\n\n\n노란색 배경: 행동 관찰. 파란색 배경: 결과 관찰. \\[저자 이미지\\]\n\n결과(파란색 배경)를 관찰할 때 작업을 무시합니다. 이 경우 중요한 것은 결과입니다.\n\n캠페인 B의 전송 날짜를 기준점으로 삼아 이 프로세스를 반복할 수 있습니다. 이 경우 다음을 갖게 됩니다.\n\n\n\n노란색 배경: 행동 관찰. 파란색 배경: 결과 관찰. \\[저자 이미지\\]\n\n공변량, 처리 및 결과를 종합하면 초기 데이터를 다음 형식으로 재정렬할 수 있습니다.\n\n\n\n데이터 준비 후 데이터 세트. \\[저자 이미지\\]\n\n이제 공변량과 처리로 구성된 독립 변수 세트(행렬 _X_ )와 결과를 포함하는 하나의 목표 변수(벡터 _y )가 있습니다._\n\n이 두 가지 요소를 사용하여 이제 모든 기계 학습 모델을 교육할 수 있습니다.\n\n모델 **은 치료와 대상 변수 간의 관계(A/B 테스트에서 발생하는 것처럼)뿐만 아니라 치료와 공변량 간의 관계도 학습할 수 있습니다** . 예를 들어 프랑스 사용자는 캠페인 A에 더 반응하고 독일 사용자는 캠페인 B에 더 반응한다는 사실을 학습할 수 있습니다.\n\n지금까지 우리는 이 문제를 전형적인 기계 학습 문제로 다루었지만, 이 경우 예측할 것이 없다고 반대할 수 있습니다. 그렇다면 애초에 ML을 사용한 이유는 무엇일까요?\n\n## 직장에서의 인과적 ML\n\n우리의 초기 목적은 다음과 같은 질문에 답하는 것이었습니다.\n\n> 어떤 사용자에게도 캠페인을 보내지 않았다면 어떻게 되었을까요? 캠페인을 모든 사용자에게 보냈다면 어떻게 되었을까요?\n\nCausal ML을 사용하면 반사실적 질문에 답할 수 있습니다. 또는 — 좀 더 거창한 용어로 표현하고 싶다면 Causal ML을 통해 다양한 우주를 시뮬레이션할 수 있습니다.\n\n예를 들어 두 가지 시나리오를 시뮬레이션하고 싶다고 가정해 보겠습니다.\n\n- 유니버스 A: 어떤 사용자에게도 캠페인을 보내지 않았다면 어떻게 되었을까요?\n- 유니버스 B: 캠페인을 모든 사용자에게 보냈다면 어떻게 되었을까요?\n\n이러한 시나리오를 시뮬레이션하는 것은 예측자 행렬에서 처리 변수의 값을 변경하는 것을 의미합니다. 매우 중요하기 때문에 이 점을 강조하고 싶습니다. **치료 변수만 변경할 수 있고 공변량은 변경할 수 없습니다** .\n\n그래픽으로,\n\n\n\nCausal ML을 사용한 다양한 시나리오의 시뮬레이션. \\[저자 이미지\\]\n\n이 접근 방식이 얼마나 유연한지 아십니까? 우리가 관심을 가질 수 있는 모든 사용자 하위 집합에서 거의 모든 시나리오를 시뮬레이션할 수 있습니다.\n\n이 시점에서 질문이 있을 수 있습니다. 모델을 교육한 동일한 데이터에 대해 어떻게 예측을 수행합니까? 기계 학습의 첫 번째 \" _하지 마십시오_ \" 아닌가요 ?\n\n교차 유효성 검사에서와 마찬가지로 데이터 세트를 여러 개로 분할하고 각 데이터 세트에 대해 다른 모델을 훈련하는 것으로 충분합니다.\n\n```\nimport pandas as pd from sklearn.model_selection import KFold from lightgbm import LGBMRegressor = 5 folds = {fold: dict () for fold in range (n_folds)} for fold, (ix_train, ix_test) in enumerate (KFold(n_splits=n_folds).split(X=X)): folds[fold][ \"ix_test\" ] = ix_test 폴드[폴드][\"모델\" ] = LGBMRegressor().fit( X=X.loc[ix_train, :], y=y.loc[ix_train] )\n```\n\n이제 각 폴드에 대해 샘플 외부에서 훈련된 모델이 있습니다. 이 시점에서 이러한 모델을 사용하여 두 유니버스 각각에서 어떤 일이 발생할지 예측할 수 있습니다.\n\n```\n X_zeros = X.replace({ \"campaign_A\" : { 1 : 0 }}) X_ones = X.replace({ \"campaign_A\" : { 0 : 1 }} ) # 유니버스 B: 사람 이 . folds.keys() 에서 접기 : ix_test = folds[fold][ \"ix_test\" ] model = folds[fold][ \"model\" ] pred_zeros.loc[ix_test] = model.predict(X_zeros.loc[ix_test, :]) pred_ones.loc[ix_test] = model.predict(X_ones.loc[ix_test, :])\n```\n\n`pred_ones`\"캠페인 A를 모든 사용자에게 보내고 다른 모든 것은 일정하게 유지했다면 어떻게 되었을까요?\"라는 질문에 답합니다.\n\n`pred_zeros`\"캠페인 A를 어떤 사용자에게도 보내지 않고 다른 모든 것은 일정하게 유지했다면 어떻게 되었을까요?\"라는 질문에 답합니다.\n\n이제 우리는 캠페인 A `pred_zeros`와 `pred_ones` **관련하여 우리가 원하는 거의 모든 것을 계산할 수 있습니다** . 특정 하위 그룹의 평균 처리 효과, 중간 처리 효과 또는 우리가 관심을 가질 수 있는 다른 측정값입니다.\n\n예를 들어 평균 처리 효과는 다음과 같이 계산할 수 있습니다.\n\n```\n먹었다 = (pred_ones - pred_zeros).mean()\n```\n\n위에서 본 동일한 논리가 이진 응답 변수에 적용될 수 있습니다(예: 사용자가 구매했습니까, 예 또는 아니오?). 이 경우 실제 확률을 예측할 수 있도록 모델을 보정해야 합니다.\n\n## 합산\n\n실제 조직은 복잡하고 다양한 프로세스가 지속적으로 사용자와 관련되어 있습니다. 이 상황에서 A/B 테스트가 의존하는 요구 사항이 반드시 충족되는 것은 아닙니다.\n\n이 경우 Causal ML을 사용하여 반사실적 질문에 답할 수 있습니다. Causal ML에는 많은 장점이 있습니다. 유연하고 불가지론적이며 거의 모든 시나리오를 시뮬레이션할 수 있습니다.\n\n\n\n출처 : https://towardsdatascience.com/using-causal-ml-instead-of-a-b-testing-eeb1067d7fc0",
"json_metadata": "{\"tags\":[\"kr-dev\"],\"image\":[\"https://miro.medium.com/max/770/1*DwS66Pwz-Ov36SefUCse3g.png\",\"https://miro.medium.com/max/770/1*8taAtEznYLPj6V5KUj9Cww.png\",\"https://miro.medium.com/max/770/1*WlrhIvUnheoG40XJ9AsCwQ.png\",\"https://miro.medium.com/max/770/1*Onq_gohPMQQDXPh2zTT-hg.png\",\"https://miro.medium.com/max/770/1*aC1etsb7MIHFLPBZy_g27g.png\",\"https://miro.medium.com/max/770/1*V_QjC_8BUCIMjjvn6ZAZMw.png\",\"https://miro.medium.com/max/770/1*hqvlyc5JDb9x8HkywX0u6Q.png\",\"https://miro.medium.com/max/770/1*XM6su-G2iD8IPU8P70EJHQ.png\",\"https://miro.medium.com/max/770/1*IuYKudZiizvOEjFteTwfYg.png\",\"https://miro.medium.com/max/770/1*yeZjBAVB4ndHPWNkOu1BQQ.png\",\"https://miro.medium.com/max/770/1*9G4UeN7KkTxarI9gyy0qMA.png\",\"https://miro.medium.com/max/770/0*Jn-1BEALgQS0a7cL.png\"],\"links\":[\"https://towardsdatascience.com/using-causal-ml-instead-of-a-b-testing-eeb1067d7fc0\"],\"app\":\"steemit/0.2\",\"format\":\"markdown\"}"
}
]
}kormanocorpclaimed reward balance: 0.957 STEEM, 1.046 SP2023/02/14 00:33:30
kormanocorpclaimed reward balance: 0.957 STEEM, 1.046 SP
2023/02/14 00:33:30
| account | kormanocorp |
| reward steem | 0.957 STEEM |
| reward sbd | 0.000 SBD |
| reward vests | 1704.087337 VESTS |
| Transaction Info | Block #72049327/Trx d878e659f75a4822c1b97efce099f1694940a6d8 |
View Raw JSON Data
{
"trx_id": "d878e659f75a4822c1b97efce099f1694940a6d8",
"block": 72049327,
"trx_in_block": 1,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-02-14T00:33:30",
"op": [
"claim_reward_balance",
{
"account": "kormanocorp",
"reward_steem": "0.957 STEEM",
"reward_sbd": "0.000 SBD",
"reward_vests": "1704.087337 VESTS"
}
]
}kormanocorpreceived 0.957 STEEM, 1.046 SP author reward for @kormanocorp / 6glsat2023/02/14 00:26:42
kormanocorpreceived 0.957 STEEM, 1.046 SP author reward for @kormanocorp / 6glsat
2023/02/14 00:26:42
| author | kormanocorp |
| permlink | 6glsat |
| sbd payout | 0.000 SBD |
| steem payout | 0.957 STEEM |
| vesting payout | 1704.087337 VESTS |
| Transaction Info | Block #72049191/Virtual Operation #4 |
View Raw JSON Data
{
"trx_id": "0000000000000000000000000000000000000000",
"block": 72049191,
"trx_in_block": 4294967295,
"op_in_trx": 0,
"virtual_op": 4,
"timestamp": "2023-02-14T00:26:42",
"op": [
"author_reward",
{
"author": "kormanocorp",
"permlink": "6glsat",
"sbd_payout": "0.000 SBD",
"steem_payout": "0.957 STEEM",
"vesting_payout": "1704.087337 VESTS"
}
]
}kormanocorpclaimed reward balance: 0.959 STEEM, 1.048 SP2023/02/13 04:48:30
kormanocorpclaimed reward balance: 0.959 STEEM, 1.048 SP
2023/02/13 04:48:30
| account | kormanocorp |
| reward steem | 0.959 STEEM |
| reward sbd | 0.000 SBD |
| reward vests | 1705.977453 VESTS |
| Transaction Info | Block #72025740/Trx 7ebaa3fe83e78b8e173d9fbaa63d34544e03e549 |
View Raw JSON Data
{
"trx_id": "7ebaa3fe83e78b8e173d9fbaa63d34544e03e549",
"block": 72025740,
"trx_in_block": 1,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-02-13T04:48:30",
"op": [
"claim_reward_balance",
{
"account": "kormanocorp",
"reward_steem": "0.959 STEEM",
"reward_sbd": "0.000 SBD",
"reward_vests": "1705.977453 VESTS"
}
]
}kormanocorpreceived 0.959 STEEM, 1.048 SP author reward for @kormanocorp / marten-cqrs2023/02/13 04:38:33
kormanocorpreceived 0.959 STEEM, 1.048 SP author reward for @kormanocorp / marten-cqrs
2023/02/13 04:38:33
| author | kormanocorp |
| permlink | marten-cqrs |
| sbd payout | 0.000 SBD |
| steem payout | 0.959 STEEM |
| vesting payout | 1705.977453 VESTS |
| Transaction Info | Block #72025540/Virtual Operation #4 |
View Raw JSON Data
{
"trx_id": "0000000000000000000000000000000000000000",
"block": 72025540,
"trx_in_block": 4294967295,
"op_in_trx": 0,
"virtual_op": 4,
"timestamp": "2023-02-13T04:38:33",
"op": [
"author_reward",
{
"author": "kormanocorp",
"permlink": "marten-cqrs",
"sbd_payout": "0.000 SBD",
"steem_payout": "0.959 STEEM",
"vesting_payout": "1705.977453 VESTS"
}
]
}kr-devupvoted (100.00%) @kormanocorp / 34yhqe2023/02/12 23:17:24
kr-devupvoted (100.00%) @kormanocorp / 34yhqe
2023/02/12 23:17:24
| voter | kr-dev |
| author | kormanocorp |
| permlink | 34yhqe |
| weight | 10000 (100.00%) |
| Transaction Info | Block #72019154/Trx 97342cca966188f9061f891e50d8057e2f7f50c6 |
View Raw JSON Data
{
"trx_id": "97342cca966188f9061f891e50d8057e2f7f50c6",
"block": 72019154,
"trx_in_block": 4,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-02-12T23:17:24",
"op": [
"vote",
{
"voter": "kr-dev",
"author": "kormanocorp",
"permlink": "34yhqe",
"weight": 10000
}
]
}anpigonupvoted (100.00%) @kormanocorp / 34yhqe2023/02/12 23:16:33
anpigonupvoted (100.00%) @kormanocorp / 34yhqe
2023/02/12 23:16:33
| voter | anpigon |
| author | kormanocorp |
| permlink | 34yhqe |
| weight | 10000 (100.00%) |
| Transaction Info | Block #72019137/Trx f4f63e87df74993b920d53d7a385d304f7e4a8c6 |
View Raw JSON Data
{
"trx_id": "f4f63e87df74993b920d53d7a385d304f7e4a8c6",
"block": 72019137,
"trx_in_block": 2,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-02-12T23:16:33",
"op": [
"vote",
{
"voter": "anpigon",
"author": "kormanocorp",
"permlink": "34yhqe",
"weight": 10000
}
]
}kr-dev.cu2replied to @kormanocorp / adreply-16762435557952023/02/12 23:12:36
kr-dev.cu2replied to @kormanocorp / adreply-1676243555795
2023/02/12 23:12:36
| parent author | kormanocorp |
| parent permlink | 34yhqe |
| author | kr-dev.cu2 |
| permlink | adreply-1676243555795 |
| title | |
| body | [광고] [STEEM 개발자 커뮤니티에 참여](/hive-137029/@kr-dev/x3v6n) 하시면, 다양한 혜택을 받을 수 있습니다. |
| json metadata | {"tags":["kr-dev"],"image":["https://miro.medium.com/max/770/1*wKEwI_zU33dt0sNk_HMHog.png"],"links":["https://levelup.gitconnected.com/javascript-design-patterns-aa4adb7b85e6"],"app":"steemit/0.2","format":"markdown"} |
| Transaction Info | Block #72019058/Trx b7a06c113aa7f662a9a3a3d6e908032bec01d3f0 |
View Raw JSON Data
{
"trx_id": "b7a06c113aa7f662a9a3a3d6e908032bec01d3f0",
"block": 72019058,
"trx_in_block": 4,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-02-12T23:12:36",
"op": [
"comment",
{
"parent_author": "kormanocorp",
"parent_permlink": "34yhqe",
"author": "kr-dev.cu2",
"permlink": "adreply-1676243555795",
"title": "",
"body": "[광고] [STEEM 개발자 커뮤니티에 참여](/hive-137029/@kr-dev/x3v6n) 하시면, 다양한 혜택을 받을 수 있습니다.",
"json_metadata": "{\"tags\":[\"kr-dev\"],\"image\":[\"https://miro.medium.com/max/770/1*wKEwI_zU33dt0sNk_HMHog.png\"],\"links\":[\"https://levelup.gitconnected.com/javascript-design-patterns-aa4adb7b85e6\"],\"app\":\"steemit/0.2\",\"format\":\"markdown\"}"
}
]
}kormanocorppublished a new post: 34yhqe2023/02/12 23:12:21
kormanocorppublished a new post: 34yhqe
2023/02/12 23:12:21
| parent author | |
| parent permlink | kr-dev |
| author | kormanocorp |
| permlink | 34yhqe |
| title | 자바스크립트 디자인 패턴 |
| body | ## 싱글톤 패턴(Redux 또는 React 컨텍스트 사용)  - Singleton 디자인 패턴은 여러 구성 요소에서 사용할 수 있는 단일 인스턴스를 노출합니다. - **Singleton Pattern은** **Redux나 React Context** 와 같은 전역 상태 관리 라이브러리의 기본이라고 할 수 있습니다 . - 인스턴스를 하나만 생성하도록 클래스를 제한하는 패턴입니다. - 전역적으로 액세스할 수 있으며 전역 상태에 액세스하기 위한 단일 액세스 지점 역할을 합니다. ``` 인스턴스를 보자 ; let globalState = { 색상 : "" }; class StateUtility { constructor ( ) { if (instance) { throw new Error ( "새 인스턴스를 생성할 수 없습니다!!" ); } 인스턴스 = 이 ; } getPropertyByName ( propertyName ) { return globalState[propertyName]; } setPropertyValue ( propertyName, propertyValue ) { globalState[propertyName] = propertyValue; }} let stateUtilityInstance = 개체 . 동결 ( new StateUtility ()); 기본 stateUtilityInstance 내보내기 ; ``` - 우리는 `globalState`. 의 클래스 메서드를 사용하여 노출합니다 `StateUtility`. 이러한 방식으로 글로벌 상태가 직접 변경되지 않도록 보호합니다. - 마지막으로 다음과 같이 클래스의 인스턴스를 만듭니다. `let stateUtilityInstance = Object.freeze(new StateUtility());`. - `Object.freeze`우리는 다른 클래스/구성 요소/모듈이 노출된 를 수정할 수 없도록 사용했습니다 `stateUtilityInstance`. ## 팩토리 패턴(팩토리 패턴 대 생성자) — - 팩토리는 객체를 생성하기 위한 함수형 프로그래밍 패러다임의 객체 또는 클래스 또는 함수입니다. - **_Factory Method는_** 클라이언트의 지시에 따라 **새 객체를 생성합니다 .** JavaScript에서 객체를 생성하는 한 가지 방법은 new 연산자로 생성자 함수를 호출하는 것입니다. - **팩토리 디자인 패턴 은 여러 하위 클래스가 있는 상위 클래스가 있고 입력에 따라 하위 클래스 중 하나를 반환해야 할 때** 사용됩니다 . 이 패턴은 클라이언트 프로그램에서 팩터리 클래스로 클래스를 인스턴스화하는 책임을 집니다. - 클래스는 여러 도우미 하위 클래스 중 하나에 책임을 위임하고 어떤 도우미 하위 클래스가 위임인지에 대한 지식을 지역화하려고 합니다. - **팩토리 메소드 는 다르지만 동시에 많은 특성(예: 메소드 및 속성)을** 공통으로 갖는 객체 모음을 관리, 유지 또는 조작하는 애플리케이션에서 자주 사용됩니다 . - 팩토리 패턴은 내부에서 생성자나 클래스를 사용할 수 있습니다. 그러나 동적으로 서브클래스를 생성하려는 경우와 같이 객체 생성 프로세스가 동적 요소에 의존하는 경우에는 팩토리 패턴이 선호됩니다. - Factory는 유연하고 재사용 가능한 객체 생성 메커니즘을 제공합니다 **.** ``` 함수 생성 vehicleFactory (manufacturer, plateNO) { return { manufacturer, plateNO, startEngine () { console. log ( "reving engine" ) }, drive () { 콘솔. log ( "자동차 운전..." ) } } } const Vehicle1 = vehicleFactory ( "Toyota" , 12345 ); 콘솔. log (Vehicle1) const Vehicle2 = vehicleFactory ( "Ford" , 13345 ); 콘솔. log (Vehicle2) ``` 예, - `StartEngine`팩터리 패턴은 , `driveVehicle`및 메서드를 재사용하여 코드 재사용성을 촉진합니다 `stopEngine`. ``` class Car { 생성자 ( 옵션 ) { this . 휠 =옵션 바퀴 || 4 ; 이 . 문 = 옵션. 문 || 4 ; 이 . 색상 = 옵션. 색상 || "실버" ; } } class Truck { 생성자 ( 옵션 ) { this . 휠 =옵션 바퀴 || 6 ; 이것. 문 = 옵션. 문 || 2 ; 이 . 색상 = 옵션. 색상 || "빨간색" ; } } class Factory { create = ( options, vehicleType ) => { if (!vehicleType) { return "차량을 만들 수 없습니다. 차량 유형을 지정하고 다시 시도하십시오!" } 차량을 보자 ; if (vehicleType === "car" ) { vehicle = 새 자동차 (옵션); }else if (vehicleType === "트럭" ) { 차량 = 새 트럭 (옵션); } 차량. 차량 유형 = 차량 유형; 차량. startEngine = ()=> 콘솔 . log ( `Reving ${vehicleType} 엔진 ` ); 차량. driveVehicle = ()=> 콘솔 . log ( `Driving ${vehicleType} ...` ); 차량. stopEngine = ()=> 콘솔 . log ( ` ${vehicleType} 엔진 중지 ` ); 반환 차량; } }; const vehicleFactory = 새 공장 (); const car = 차량 공장. 생성 ({ 바퀴 : 4 , 문 : 2 , 색상 : "검은색" , }, "자동차" ); 콘솔 . 로그 (자동차) 콘솔 . 로그 ( car.startEngine ()) 콘솔 .log (car.driveVehicle ()) [ const truck = vehicleFactory. create ({ 바퀴 : 4 , 문 : 2 , 색상 : "노란색" , }, "트럭" ) 콘솔 . 로그 (트럭) 콘솔 . 로그 ( truck.startEngine ()) 콘솔 . log (truck.stopEngine ()) ' ``` - **팩토리 패턴을 사용하면 코드를 쉽게 유지 관리할 수 있으므로** 비즈니스가 확장되고 공장에서 새로운 종류의 차량을 생산하기 시작하면 구현을 쉽게 내화하여 아래와 같이 처리할 수 있습니다. ``` class Car { 생성자 ( 옵션 ) { this . 휠 =옵션 바퀴 || 4 ; 이 . 문 = 옵션. 문 || 4 ; 이 . 색상 = 옵션. 색상 || "실버" ; } } class Truck { 생성자 ( 옵션 ) { this . 휠 =옵션 바퀴 || 6 ; 이것. 문 = 옵션. 문 || 2 ; 이 . 색상 = 옵션. 색상 || "빨간색" ; } } class Bus { 생성자 ( 옵션 ) { this . 휠 =옵션 바퀴 || 4 ; 이 . 문 = 옵션. 문 || 4 ; 이 . 색상 = 옵션. 색상 || "흰색" ; }} 클래스 오토바이 { 생성자 ( 옵션 ) { 이 . 휠 =옵션 바퀴 || 2 ; 이 . 문 = 옵션. 문 || 0 ; 이 . 색상 = 옵션. 색상 || "블랙" ; } } class Factory { create = ( options, vehicleType ) => { if (!vehicleType) { 반환 "차량을 만들 수 없습니다. 차량 유형을 지정하고 다시 시도하십시오!" } 차량을 보자 ; if (vehicleType === "car" ) { vehicle = 새 자동차 (옵션); } else if (vehicleType === "트럭" ) { 차량 = 새 트럭 (옵션); } else if (vehicleType === "버스" ) { 차량 = 새 버스 (옵션); } else if (vehicleType === "오토바이") { 차량 = 새 오토바이 (옵션); } 차량. 차량 유형 = 차량 유형; 차량. startEngine = ()=> 콘솔 . log ( `Reving ${vehicleType} 엔진 ` ); 차량. driveVehicle = ()=> 콘솔 . log ( `Driving ${vehicleType} ...` ); 차량. stopEngine = ()=> 콘솔 . 로그 ( `중지${vehicleType} 엔진 ` ); 반환 차량; }}; const vehicleFactory = 새 공장 (); const 버스 = 차량 공장. 생성 ({ 바퀴 : 4 , 문 : 4 , 색상 : "노란색" ,}, "버스" ); 콘솔 . 로그 (버스) 콘솔 . 로그 ( bus.startEngine()) 콘솔 . 로그 (bus.driveVehicle ( ))const bike = vehicleFactory. create ({ 바퀴 : 2 , 문 : 0 , 색상 : "빨간색" , }, "오토바이" ) 콘솔 . 로그 (자전거) 콘솔 . 로그 ( bike.startEngine()) 콘솔 . log (bike.stopEngine ()) // ``` 더 많은 예, ``` var 팩토리 = 함수 ( ) { 이 . createEmployee = 기능 ( 유형 ) { var 직원; if (type === "fulltime" ) { 직원 = new FullTime (); } else if (type === "parttime" ) { 직원 = new PartTime (); } else if (type === "임시" ) { 직원 = 새 임시(); } else if (유형 === "계약자" ) { 직원 = 새 계약자 (); } 직원. 유형 = 유형; 직원. = function ( ) { 콘솔 . log ( this . type + ": rate " + this . hourly + "/hour" ); } 복귀 직원; } } var 풀타임 = 함수 ( ) { 이 . 매시간 = "$12" ; }; var PartTime = 함수 ( ) { 이 . 매시간 = "$11" ; }; var 임시 = 함수 ( ) { 이 . 시간당 = "$10" ; }; var 계약자 = 함수 ( ) { 이 . 매시간 = "$15" ; }; 기능 실행( ) { var 직원 = []; var factory = 새 공장 (); 직원. push ( factory.createEmployee ( "풀타임" )); 직원. push ( factory.createEmployee ( "파트타임" )); 직원. push ( factory.createEmployee ( "임시" )); 직원. push ( factory.createEmployee ( "계약자" )); 에 대한 ( 변수 i = 0, 렌 = 직원. 길이 ; i < 렌; i++) { 직원[i]. 말하다 (); } } ``` ## 팩토리 패턴과 생성자 - 생성자 패턴과 팩토리 패턴은 **새로운 객체를 반환하는 객체 생성 패턴이므로 유사하다.** - Factory 메서드는 항상 새 인스턴스를 생성하는 생성자와 달리 **이미 생성된 객체를 반환할 수 있습니다 .** - 팩토리 메서드는 인터페이스를 사용한 코딩 아이디어를 촉진한 다음 구현을 통해 더 유연한 코드를 생성하지만 생성자는 코드를 특정 구현에 연결합니다. - **생성자를 사용하는 이유:** 생성자를 사용하여 **객체를 기본 또는 초기 상태로 초기화합니다** . 프리미티브의 기본값은 원하는 값이 아닐 수 있습니다. 생성자를 사용하는 또 다른 이유는 종속성에 대해 알려주기 때문입니다. - **팩토리를 사용하는 이유:** 팩토리 메소드 패턴을 **사용하면 하위 클래스에서 생성할 객체 유형을 선택할 수 있습니다** . 응용 프로그램별 클래스를 코드에 바인딩할 필요가 없으므로 느슨한 결합이 촉진됩니다. ``` const vehicleOptions = { type : "cars" , color : "white" , doors : 4 , wheels : 4 } 함수 Factory ( options ) { let factory = {}; 공장. 유형 = 옵션. 유형 ; 공장. 색상 = 옵션. 색상 ; 공장. 휠 =옵션 바퀴 ; 공장. 문 = 옵션. 문; 반품 공장; } const 차량 = 공장 (vehicleOptions); function ConstructorPattern ( options ) { this . 유형 = 옵션. 유형 ; 이 . 색상 = 옵션. 이것을 색칠하십시오 . 문 = 옵션. 문 ; 이 . 휠 =옵션 바퀴 ; } const vehicle2 = new ConstructorPattern (vehicleOptions); 콘솔 . log ( "factory car" , vehicle) console . log ( "constructor car" , vehicle2) ``` ## 팩토리 패턴을 사용하는 경우 Factory 패턴은 다음과 같은 상황에 적용할 때 특히 유용할 수 있습니다. - 개체 또는 구성 요소 설정에 높은 수준의 복잡성이 포함된 경우. - 우리가 처한 환경에 따라 다양한 객체 인스턴스를 쉽게 생성해야 할 때. - 동일한 속성을 공유하는 많은 작은 개체 또는 구성 요소로 작업할 때. - 작동하려면 API 계약(일명 덕 타이핑)만 충족하면 되는 다른 객체의 인스턴스로 객체를 구성할 때. 이는 디커플링에 유용합니다. 출처 : https://levelup.gitconnected.com/javascript-design-patterns-aa4adb7b85e6 |
| json metadata | {"tags":["kr-dev"],"image":["https://miro.medium.com/max/770/1*wKEwI_zU33dt0sNk_HMHog.png"],"links":["https://levelup.gitconnected.com/javascript-design-patterns-aa4adb7b85e6"],"app":"steemit/0.2","format":"markdown"} |
| Transaction Info | Block #72019053/Trx f69878051ad234b1aebc102581020ae6ea0421d6 |
View Raw JSON Data
{
"trx_id": "f69878051ad234b1aebc102581020ae6ea0421d6",
"block": 72019053,
"trx_in_block": 2,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-02-12T23:12:21",
"op": [
"comment",
{
"parent_author": "",
"parent_permlink": "kr-dev",
"author": "kormanocorp",
"permlink": "34yhqe",
"title": "자바스크립트 디자인 패턴",
"body": "## 싱글톤 패턴(Redux 또는 React 컨텍스트 사용)\n\n\n\n- Singleton 디자인 패턴은 여러 구성 요소에서 사용할 수 있는 단일 인스턴스를 노출합니다.\n- **Singleton Pattern은** **Redux나 React Context** 와 같은 전역 상태 관리 라이브러리의 기본이라고 할 수 있습니다 .\n- 인스턴스를 하나만 생성하도록 클래스를 제한하는 패턴입니다.\n- 전역적으로 액세스할 수 있으며 전역 상태에 액세스하기 위한 단일 액세스 지점 역할을 합니다.\n\n```\n인스턴스를 보자 ; let globalState = { 색상 : \"\" }; class StateUtility { constructor ( ) { if (instance) { throw new Error ( \"새 인스턴스를 생성할 수 없습니다!!\" ); } 인스턴스 = 이 ; } getPropertyByName ( propertyName ) { return globalState[propertyName]; } setPropertyValue ( propertyName, propertyValue ) { globalState[propertyName] = propertyValue; }} let stateUtilityInstance = 개체 . 동결 ( new StateUtility ()); 기본 stateUtilityInstance 내보내기 ;\n```\n\n- 우리는 `globalState`. 의 클래스 메서드를 사용하여 노출합니다 `StateUtility`. 이러한 방식으로 글로벌 상태가 직접 변경되지 않도록 보호합니다.\n- 마지막으로 다음과 같이 클래스의 인스턴스를 만듭니다. `let stateUtilityInstance = Object.freeze(new StateUtility());`.\n- `Object.freeze`우리는 다른 클래스/구성 요소/모듈이 노출된 를 수정할 수 없도록 사용했습니다 `stateUtilityInstance`.\n\n## 팩토리 패턴(팩토리 패턴 대 생성자) —\n\n- 팩토리는 객체를 생성하기 위한 함수형 프로그래밍 패러다임의 객체 또는 클래스 또는 함수입니다.\n- **_Factory Method는_** 클라이언트의 지시에 따라 **새 객체를 생성합니다 .** JavaScript에서 객체를 생성하는 한 가지 방법은 new 연산자로 생성자 함수를 호출하는 것입니다.\n- **팩토리 디자인 패턴 은 여러 하위 클래스가 있는 상위 클래스가 있고 입력에 따라 하위 클래스 중 하나를 반환해야 할 때** 사용됩니다 . 이 패턴은 클라이언트 프로그램에서 팩터리 클래스로 클래스를 인스턴스화하는 책임을 집니다.\n- 클래스는 여러 도우미 하위 클래스 중 하나에 책임을 위임하고 어떤 도우미 하위 클래스가 위임인지에 대한 지식을 지역화하려고 합니다.\n- **팩토리 메소드 는 다르지만 동시에 많은 특성(예: 메소드 및 속성)을** 공통으로 갖는 객체 모음을 관리, 유지 또는 조작하는 애플리케이션에서 자주 사용됩니다 .\n- 팩토리 패턴은 내부에서 생성자나 클래스를 사용할 수 있습니다. 그러나 동적으로 서브클래스를 생성하려는 경우와 같이 객체 생성 프로세스가 동적 요소에 의존하는 경우에는 팩토리 패턴이 선호됩니다.\n- Factory는 유연하고 재사용 가능한 객체 생성 메커니즘을 제공합니다 **.**\n\n```\n함수 생성 vehicleFactory (manufacturer, plateNO) { return { manufacturer, plateNO, startEngine () { console. log ( \"reving engine\" ) }, drive () { 콘솔. log ( \"자동차 운전...\" ) } } } const Vehicle1 = vehicleFactory ( \"Toyota\" , 12345 ); 콘솔. log (Vehicle1) const Vehicle2 = vehicleFactory ( \"Ford\" , 13345 ); 콘솔. log (Vehicle2) \n```\n\n예,\n\n- `StartEngine`팩터리 패턴은 , `driveVehicle`및 메서드를 재사용하여 코드 재사용성을 촉진합니다 `stopEngine`.\n\n```\nclass Car { 생성자 ( 옵션 ) { this . 휠 =옵션 바퀴 || 4 ; 이 . 문 = 옵션. 문 || 4 ; 이 . 색상 = 옵션. 색상 || \"실버\" ; } } class Truck { 생성자 ( 옵션 ) { this . 휠 =옵션 바퀴 || 6 ; 이것. 문 = 옵션. 문 || 2 ; 이 . 색상 = 옵션. 색상 || \"빨간색\" ; } } class Factory { create = ( options, vehicleType ) => { if (!vehicleType) { return \"차량을 만들 수 없습니다. 차량 유형을 지정하고 다시 시도하십시오!\" } 차량을 보자 ; if (vehicleType === \"car\" ) { vehicle = 새 자동차 (옵션); }else if (vehicleType === \"트럭\" ) { 차량 = 새 트럭 (옵션); } 차량. 차량 유형 = 차량 유형; 차량. startEngine = ()=> 콘솔 . log ( `Reving ${vehicleType} 엔진 ` ); 차량. driveVehicle = ()=> 콘솔 . log ( `Driving ${vehicleType} ...` ); 차량. stopEngine = ()=> 콘솔 . log ( ` ${vehicleType} 엔진 중지 ` ); 반환 차량; } }; const vehicleFactory = 새 공장 (); const car = 차량 공장. 생성 ({ 바퀴 : 4 , 문 : 2 , 색상 : \"검은색\" , }, \"자동차\" ); 콘솔 . 로그 (자동차) 콘솔 . 로그 ( car.startEngine ()) 콘솔 .log (car.driveVehicle ()) [ const truck = vehicleFactory. create ({ 바퀴 : 4 , 문 : 2 , 색상 : \"노란색\" , }, \"트럭\" ) 콘솔 . 로그 (트럭) 콘솔 . 로그 ( truck.startEngine ()) 콘솔 . log (truck.stopEngine ()) ' \n```\n\n- **팩토리 패턴을 사용하면 코드를 쉽게 유지 관리할 수 있으므로** 비즈니스가 확장되고 공장에서 새로운 종류의 차량을 생산하기 시작하면 구현을 쉽게 내화하여 아래와 같이 처리할 수 있습니다.\n\n```\nclass Car { 생성자 ( 옵션 ) { this . 휠 =옵션 바퀴 || 4 ; 이 . 문 = 옵션. 문 || 4 ; 이 . 색상 = 옵션. 색상 || \"실버\" ; } } class Truck { 생성자 ( 옵션 ) { this . 휠 =옵션 바퀴 || 6 ; 이것. 문 = 옵션. 문 || 2 ; 이 . 색상 = 옵션. 색상 || \"빨간색\" ; } } class Bus { 생성자 ( 옵션 ) { this . 휠 =옵션 바퀴 || 4 ; 이 . 문 = 옵션. 문 || 4 ; 이 . 색상 = 옵션. 색상 || \"흰색\" ; }} 클래스 오토바이 { 생성자 ( 옵션 ) { 이 . 휠 =옵션 바퀴 || 2 ; 이 . 문 = 옵션. 문 || 0 ; 이 . 색상 = 옵션. 색상 || \"블랙\" ; } } class Factory { create = ( options, vehicleType ) => { if (!vehicleType) { 반환 \"차량을 만들 수 없습니다. 차량 유형을 지정하고 다시 시도하십시오!\" } 차량을 보자 ; if (vehicleType === \"car\" ) { vehicle = 새 자동차 (옵션); } else if (vehicleType === \"트럭\" ) { 차량 = 새 트럭 (옵션); } else if (vehicleType === \"버스\" ) { 차량 = 새 버스 (옵션); } else if (vehicleType === \"오토바이\") { 차량 = 새 오토바이 (옵션); } 차량. 차량 유형 = 차량 유형; 차량. startEngine = ()=> 콘솔 . log ( `Reving ${vehicleType} 엔진 ` ); 차량. driveVehicle = ()=> 콘솔 . log ( `Driving ${vehicleType} ...` ); 차량. stopEngine = ()=> 콘솔 . 로그 ( `중지${vehicleType} 엔진 ` ); 반환 차량; }}; const vehicleFactory = 새 공장 (); const 버스 = 차량 공장. 생성 ({ 바퀴 : 4 , 문 : 4 , 색상 : \"노란색\" ,}, \"버스\" ); 콘솔 . 로그 (버스) 콘솔 . 로그 ( bus.startEngine()) 콘솔 . 로그 (bus.driveVehicle ( ))const bike = vehicleFactory. create ({ 바퀴 : 2 , 문 : 0 , 색상 : \"빨간색\" , }, \"오토바이\" ) 콘솔 . 로그 (자전거) 콘솔 . 로그 ( bike.startEngine()) 콘솔 . log (bike.stopEngine ()) // \n```\n\n더 많은 예,\n\n```\nvar 팩토리 = 함수 ( ) { 이 . createEmployee = 기능 ( 유형 ) { var 직원; if (type === \"fulltime\" ) { 직원 = new FullTime (); } else if (type === \"parttime\" ) { 직원 = new PartTime (); } else if (type === \"임시\" ) { 직원 = 새 임시(); } else if (유형 === \"계약자\" ) { 직원 = 새 계약자 (); } 직원. 유형 = 유형; 직원. = function ( ) { 콘솔 . log ( this . type + \": rate \" + this . hourly + \"/hour\" ); } 복귀 직원; } } var 풀타임 = 함수 ( ) { 이 . 매시간 = \"$12\" ; }; var PartTime = 함수 ( ) { 이 . 매시간 = \"$11\" ; }; var 임시 = 함수 ( ) { 이 . 시간당 = \"$10\" ; }; var 계약자 = 함수 ( ) { 이 . 매시간 = \"$15\" ; }; 기능 실행( ) { var 직원 = []; var factory = 새 공장 (); 직원. push ( factory.createEmployee ( \"풀타임\" )); 직원. push ( factory.createEmployee ( \"파트타임\" )); 직원. push ( factory.createEmployee ( \"임시\" )); 직원. push ( factory.createEmployee ( \"계약자\" )); 에 대한 ( 변수 i = 0, 렌 = 직원. 길이 ; i < 렌; i++) { 직원[i]. 말하다 (); } }\n```\n\n## 팩토리 패턴과 생성자\n\n- 생성자 패턴과 팩토리 패턴은 **새로운 객체를 반환하는 객체 생성 패턴이므로 유사하다.**\n- Factory 메서드는 항상 새 인스턴스를 생성하는 생성자와 달리 **이미 생성된 객체를 반환할 수 있습니다 .**\n- 팩토리 메서드는 인터페이스를 사용한 코딩 아이디어를 촉진한 다음 구현을 통해 더 유연한 코드를 생성하지만 생성자는 코드를 특정 구현에 연결합니다.\n- **생성자를 사용하는 이유:** 생성자를 사용하여 **객체를 기본 또는 초기 상태로 초기화합니다** . 프리미티브의 기본값은 원하는 값이 아닐 수 있습니다. 생성자를 사용하는 또 다른 이유는 종속성에 대해 알려주기 때문입니다.\n- **팩토리를 사용하는 이유:** 팩토리 메소드 패턴을 **사용하면 하위 클래스에서 생성할 객체 유형을 선택할 수 있습니다** . 응용 프로그램별 클래스를 코드에 바인딩할 필요가 없으므로 느슨한 결합이 촉진됩니다.\n\n```\nconst vehicleOptions = { type : \"cars\" , color : \"white\" , doors : 4 , wheels : 4 } 함수 Factory ( options ) { let factory = {}; 공장. 유형 = 옵션. 유형 ; 공장. 색상 = 옵션. 색상 ; 공장. 휠 =옵션 바퀴 ; 공장. 문 = 옵션. 문; 반품 공장; } const 차량 = 공장 (vehicleOptions); function ConstructorPattern ( options ) { this . 유형 = 옵션. 유형 ; 이 . 색상 = 옵션. 이것을 색칠하십시오 . 문 = 옵션. 문 ; 이 . 휠 =옵션 바퀴 ; } const vehicle2 = new ConstructorPattern (vehicleOptions); 콘솔 . log ( \"factory car\" , vehicle) console . log ( \"constructor car\" , vehicle2) \n```\n\n## 팩토리 패턴을 사용하는 경우\n\nFactory 패턴은 다음과 같은 상황에 적용할 때 특히 유용할 수 있습니다.\n\n- 개체 또는 구성 요소 설정에 높은 수준의 복잡성이 포함된 경우.\n- 우리가 처한 환경에 따라 다양한 객체 인스턴스를 쉽게 생성해야 할 때.\n- 동일한 속성을 공유하는 많은 작은 개체 또는 구성 요소로 작업할 때.\n- 작동하려면 API 계약(일명 덕 타이핑)만 충족하면 되는 다른 객체의 인스턴스로 객체를 구성할 때. 이는 디커플링에 유용합니다.\n\n\n출처 : https://levelup.gitconnected.com/javascript-design-patterns-aa4adb7b85e6",
"json_metadata": "{\"tags\":[\"kr-dev\"],\"image\":[\"https://miro.medium.com/max/770/1*wKEwI_zU33dt0sNk_HMHog.png\"],\"links\":[\"https://levelup.gitconnected.com/javascript-design-patterns-aa4adb7b85e6\"],\"app\":\"steemit/0.2\",\"format\":\"markdown\"}"
}
]
}kr-devupvoted (100.00%) @kormanocorp / 41ults2023/02/08 23:17:03
kr-devupvoted (100.00%) @kormanocorp / 41ults
2023/02/08 23:17:03
| voter | kr-dev |
| author | kormanocorp |
| permlink | 41ults |
| weight | 10000 (100.00%) |
| Transaction Info | Block #71904564/Trx 3155676f7a9b5c747c2de861d855f8d174c16c54 |
View Raw JSON Data
{
"trx_id": "3155676f7a9b5c747c2de861d855f8d174c16c54",
"block": 71904564,
"trx_in_block": 7,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-02-08T23:17:03",
"op": [
"vote",
{
"voter": "kr-dev",
"author": "kormanocorp",
"permlink": "41ults",
"weight": 10000
}
]
}anpigonupvoted (100.00%) @kormanocorp / 41ults2023/02/08 23:16:15
anpigonupvoted (100.00%) @kormanocorp / 41ults
2023/02/08 23:16:15
| voter | anpigon |
| author | kormanocorp |
| permlink | 41ults |
| weight | 10000 (100.00%) |
| Transaction Info | Block #71904548/Trx 00ce97b0349df615d88ebb182cc9ffbfe6c5b224 |
View Raw JSON Data
{
"trx_id": "00ce97b0349df615d88ebb182cc9ffbfe6c5b224",
"block": 71904548,
"trx_in_block": 2,
"op_in_trx": 0,
"virtual_op": 0,
"timestamp": "2023-02-08T23:16:15",
"op": [
"vote",
{
"voter": "anpigon",
"author": "kormanocorp",
"permlink": "41ults",
"weight": 10000
}
]
}Manabar
Voting Power100.00%
Downvote Power100.00%
Resource Credits100.00%
Reputation Progress40.31%
{
"voting_manabar": {
"current_mana": "283360173712",
"last_update_time": 1758635379
},
"downvote_manabar": {
"current_mana": "70840043427",
"last_update_time": 1758635379
},
"rc_account": {
"account": "kormanocorp",
"rc_manabar": {
"current_mana": "285280931917",
"last_update_time": 1758635379
},
"max_rc_creation_adjustment": {
"amount": "2020748973",
"precision": 6,
"nai": "@@000000037"
},
"max_rc": "285380922685"
}
}Account Metadata
| POSTING JSON METADATA | |
| profile | {"profile_image":"https://cdn.steemitimages.com/DQmeBbaEtLd4iP9DBR9fmKzTQTr72SXFhxCVEd3W9Njufui/20211001_124323.jpg","name":"아울렛","version":2} |
| JSON METADATA | |
| profile | {"profile_image":"https://cdn.steemitimages.com/DQmZvXgPLYdfANFEY9G9ohtLABGcBo6RjhExcvocRcL8LN2/KakaoTalk_20180425_190709001.jpg","name":"코마노","website":"https://kormano.co.kr","about":"마스터노드, 장기투자의 끝판대장"} |
{
"posting_json_metadata": {
"profile": {
"profile_image": "https://cdn.steemitimages.com/DQmeBbaEtLd4iP9DBR9fmKzTQTr72SXFhxCVEd3W9Njufui/20211001_124323.jpg",
"name": "아울렛",
"version": 2
}
},
"json_metadata": {
"profile": {
"profile_image": "https://cdn.steemitimages.com/DQmZvXgPLYdfANFEY9G9ohtLABGcBo6RjhExcvocRcL8LN2/KakaoTalk_20180425_190709001.jpg",
"name": "코마노",
"website": "https://kormano.co.kr",
"about": "마스터노드, 장기투자의 끝판대장"
}
}
}Auth Keys
Owner
Single Signature
Public Keys
STM7FEPPzEHdiiJ29tLraF7sFa4DSmVQykZ7gKtU6z7guEo1drpUh1/1
Active
Single Signature
Public Keys
STM5yzbcYCe5sEoMWhyEjAE9BtE5rn9pCU7LEsQJMU6dcivQVUsGN1/1
Posting
Single Signature
Public Keys
STM7nTCj3e3s54pgejJUFaKFTAAb7EJKxzGba9M1JxGyyxyrKFcCt1/1
App Permissions
Memo
STM8hnKpxC7hJdo9esQkSvPvB4bqtvkkEoQXrfASKir4WqRWBTD6W
{
"owner": {
"weight_threshold": 1,
"account_auths": [],
"key_auths": [
[
"STM7FEPPzEHdiiJ29tLraF7sFa4DSmVQykZ7gKtU6z7guEo1drpUh",
1
]
]
},
"active": {
"weight_threshold": 1,
"account_auths": [],
"key_auths": [
[
"STM5yzbcYCe5sEoMWhyEjAE9BtE5rn9pCU7LEsQJMU6dcivQVUsGN",
1
]
]
},
"posting": {
"weight_threshold": 1,
"account_auths": [
[
"auto.steemkorea",
1
]
],
"key_auths": [
[
"STM7nTCj3e3s54pgejJUFaKFTAAb7EJKxzGba9M1JxGyyxyrKFcCt",
1
]
]
},
"memo": "STM8hnKpxC7hJdo9esQkSvPvB4bqtvkkEoQXrfASKir4WqRWBTD6W"
}Witness Votes
0 / 30
No active witness votes.
[]